@astryxdesign/lab 0.7.5-canary.577e8ca → 0.7.5-canary.5b691cd

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.
@@ -74,7 +74,7 @@ export function ChatUnreadDivider({
74
74
  }
75
75
  }), /*#__PURE__*/_jsx("span", {
76
76
  ...{
77
- className: "x2lah0s x9ynric x141an7d x1lvx875 xjt36v0 x1ltkj2j"
77
+ className: "x2lah0s x9ynric x141an7d x1lvx875 x1wj83wy x1ltkj2j"
78
78
  },
79
79
  children: label
80
80
  })]
@@ -106,15 +106,15 @@ const variantStyles = {
106
106
  $$css: true
107
107
  },
108
108
  success: {
109
- kjVXCG: "x8y33gb",
109
+ kjVXCG: "x88o7k4",
110
110
  $$css: true
111
111
  },
112
112
  warning: {
113
- kjVXCG: "x9ezeq1",
113
+ kjVXCG: "x16d96h5",
114
114
  $$css: true
115
115
  },
116
116
  error: {
117
- kjVXCG: "x1vco6zm",
117
+ kjVXCG: "xqb94c9",
118
118
  $$css: true
119
119
  },
120
120
  neutral: {
@@ -1,5 +1,6 @@
1
1
  import { type MouseEvent, type ReactNode, type Ref } from 'react';
2
2
  import type { BaseProps } from '@astryxdesign/core';
3
+ import { type CodeLanguage } from '@astryxdesign/core/CodeBlock';
3
4
  import { type SyntaxThemeDefinition } from '@astryxdesign/core/theme/syntax';
4
5
  import type { DiffViewerFile, DiffViewerLineRef } from './diffTypes.js';
5
6
  /** How hunks are laid out: one column, or old and new side by side. */
@@ -34,10 +35,20 @@ export interface DiffViewerProps extends BaseProps<HTMLDivElement> {
34
35
  */
35
36
  viewMode?: DiffViewerViewMode;
36
37
  /**
37
- * Syntax-highlighting language. Defaults to one inferred from the file's
38
- * extension; unknown extensions render as plain text.
38
+ * Syntax-highlighting language: a built-in identifier such as `'rust'`, or
39
+ * a language value — a module imported on its own, such as `graphql` from
40
+ * `@astryxdesign/core/CodeBlock/languages/graphql`, or one made with
41
+ * `createCodeLanguage`. Defaults to one inferred from the file's name or
42
+ * extension among the built-ins and `codeLanguages`; an unmatched file
43
+ * renders as plain text.
39
44
  */
40
- language?: string;
45
+ language?: string | CodeLanguage;
46
+ /**
47
+ * Language values the file's name or extension may infer, such as
48
+ * `[graphql, dockerfile]`; a later entry wins. Pass the same list to every
49
+ * DiffViewer on a review page.
50
+ */
51
+ codeLanguages?: ReadonlyArray<CodeLanguage>;
41
52
  /**
42
53
  * Show the old and new line-number gutters.
43
54
  * @default true
@@ -125,7 +136,7 @@ export interface DiffViewerProps extends BaseProps<HTMLDivElement> {
125
136
  * <DiffViewer file={file} viewMode="split" />
126
137
  * ```
127
138
  */
128
- export declare function DiffViewer({ ref, file, viewMode, language: languageProp, hasLineNumbers, isWrapped, changeIndicator, inlineHighlight, hasChangeBackground, isCollapsible, isCollapsed: isCollapsedProp, defaultIsCollapsed, onCollapsedChange, headerEnd, renderLineAnnotation, onLineNumberClick, maxHeight, syntaxTheme, xstyle, className, style, ...props }: DiffViewerProps): import("react").JSX.Element;
139
+ export declare function DiffViewer({ ref, file, viewMode, language: languageProp, codeLanguages, hasLineNumbers, isWrapped, changeIndicator, inlineHighlight, hasChangeBackground, isCollapsible, isCollapsed: isCollapsedProp, defaultIsCollapsed, onCollapsedChange, headerEnd, renderLineAnnotation, onLineNumberClick, maxHeight, syntaxTheme, xstyle, className, style, ...props }: DiffViewerProps): import("react").JSX.Element;
129
140
  export declare namespace DiffViewer {
130
141
  var displayName: string;
131
142
  }
@@ -1 +1 @@
1
- {"version":3,"file":"DiffViewer.d.ts","sourceRoot":"","sources":["../../src/DiffViewer/DiffViewer.tsx"],"names":[],"mappings":"AAqCA,OAAO,EAQL,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,GAAG,EAET,MAAM,OAAO,CAAC;AAGf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,oBAAoB,CAAC;AAalD,OAAO,EAEL,KAAK,qBAAqB,EAC3B,MAAM,iCAAiC,CAAC;AAqBzC,OAAO,KAAK,EACV,cAAc,EAGd,iBAAiB,EAElB,MAAM,aAAa,CAAC;AAGrB,uEAAuE;AACvE,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,OAAO,CAAC;AAErD;;;;GAIG;AACH,MAAM,MAAM,yBAAyB,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,CAAC;AAEpE;;;GAGG;AACH,MAAM,MAAM,yBAAyB,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAEjE,MAAM,WAAW,eAAgB,SAAQ,SAAS,CAAC,cAAc,CAAC;IAChE,yCAAyC;IACzC,GAAG,CAAC,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;IAC1B;;;OAGG;IACH,IAAI,EAAE,cAAc,CAAC;IACrB;;;;;;;;OAQG;IACH,QAAQ,CAAC,EAAE,kBAAkB,CAAC;IAC9B;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;;;;;;OAQG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;OAGG;IACH,eAAe,CAAC,EAAE,yBAAyB,CAAC;IAC5C;;;;;OAKG;IACH,eAAe,CAAC,EAAE,yBAAyB,CAAC;IAC5C;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,iEAAiE;IACjE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;OAGG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,uEAAuE;IACvE,iBAAiB,CAAC,EAAE,CAAC,WAAW,EAAE,OAAO,KAAK,IAAI,CAAC;IACnD;;;OAGG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB;;;;;OAKG;IACH,oBAAoB,CAAC,EAAE,CAAC,GAAG,EAAE,iBAAiB,KAAK,SAAS,CAAC;IAC7D;;;;;;OAMG;IACH,iBAAiB,CAAC,EAAE,CAClB,GAAG,EAAE,iBAAiB,EACtB,KAAK,EAAE,UAAU,CAAC,iBAAiB,CAAC,KACjC,IAAI,CAAC;IACV,yDAAyD;IACzD,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B;;;OAGG;IACH,WAAW,CAAC,EAAE,qBAAqB,CAAC;CACrC;AAk0BD;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CAAC,EACzB,GAAG,EACH,IAAI,EACJ,QAAoB,EACpB,QAAQ,EAAE,YAAY,EACtB,cAAqB,EACrB,SAAiB,EACjB,eAA2B,EAC3B,eAAwB,EACxB,mBAA0B,EAC1B,aAAoB,EACpB,WAAW,EAAE,eAAe,EAC5B,kBAA0B,EAC1B,iBAAiB,EACjB,SAAS,EACT,oBAAoB,EACpB,iBAAiB,EACjB,SAAS,EACT,WAAW,EACX,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,KAAK,EACT,EAAE,eAAe,+BAopBjB;yBA3qBe,UAAU"}
1
+ {"version":3,"file":"DiffViewer.d.ts","sourceRoot":"","sources":["../../src/DiffViewer/DiffViewer.tsx"],"names":[],"mappings":"AAqCA,OAAO,EAQL,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,GAAG,EAET,MAAM,OAAO,CAAC;AAGf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAGL,KAAK,YAAY,EAGlB,MAAM,8BAA8B,CAAC;AAOtC,OAAO,EAEL,KAAK,qBAAqB,EAC3B,MAAM,iCAAiC,CAAC;AAqBzC,OAAO,KAAK,EACV,cAAc,EAGd,iBAAiB,EAElB,MAAM,aAAa,CAAC;AAGrB,uEAAuE;AACvE,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,OAAO,CAAC;AAErD;;;;GAIG;AACH,MAAM,MAAM,yBAAyB,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,CAAC;AAEpE;;;GAGG;AACH,MAAM,MAAM,yBAAyB,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAEjE,MAAM,WAAW,eAAgB,SAAQ,SAAS,CAAC,cAAc,CAAC;IAChE,yCAAyC;IACzC,GAAG,CAAC,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;IAC1B;;;OAGG;IACH,IAAI,EAAE,cAAc,CAAC;IACrB;;;;;;;;OAQG;IACH,QAAQ,CAAC,EAAE,kBAAkB,CAAC;IAC9B;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,YAAY,CAAC;IACjC;;;;OAIG;IACH,aAAa,CAAC,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IAC5C;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;;;;;;OAQG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;OAGG;IACH,eAAe,CAAC,EAAE,yBAAyB,CAAC;IAC5C;;;;;OAKG;IACH,eAAe,CAAC,EAAE,yBAAyB,CAAC;IAC5C;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,iEAAiE;IACjE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;OAGG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,uEAAuE;IACvE,iBAAiB,CAAC,EAAE,CAAC,WAAW,EAAE,OAAO,KAAK,IAAI,CAAC;IACnD;;;OAGG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB;;;;;OAKG;IACH,oBAAoB,CAAC,EAAE,CAAC,GAAG,EAAE,iBAAiB,KAAK,SAAS,CAAC;IAC7D;;;;;;OAMG;IACH,iBAAiB,CAAC,EAAE,CAClB,GAAG,EAAE,iBAAiB,EACtB,KAAK,EAAE,UAAU,CAAC,iBAAiB,CAAC,KACjC,IAAI,CAAC;IACV,yDAAyD;IACzD,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B;;;OAGG;IACH,WAAW,CAAC,EAAE,qBAAqB,CAAC;CACrC;AAi2BD;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CAAC,EACzB,GAAG,EACH,IAAI,EACJ,QAAoB,EACpB,QAAQ,EAAE,YAAY,EACtB,aAAa,EACb,cAAqB,EACrB,SAAiB,EACjB,eAA2B,EAC3B,eAAwB,EACxB,mBAA0B,EAC1B,aAAoB,EACpB,WAAW,EAAE,eAAe,EAC5B,kBAA0B,EAC1B,iBAAiB,EACjB,SAAS,EACT,oBAAoB,EACpB,iBAAiB,EACjB,SAAS,EACT,WAAW,EACX,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,KAAK,EACT,EAAE,eAAe,+BAopBjB;yBA5qBe,UAAU"}
@@ -92,18 +92,42 @@ const EXTENSION_LANGUAGES = {
92
92
  yaml: 'yaml',
93
93
  yml: 'yaml',
94
94
  md: 'markdown',
95
- markdown: 'markdown'
95
+ markdown: 'markdown',
96
+ c: 'c',
97
+ h: 'c',
98
+ cpp: 'cpp',
99
+ cc: 'cpp',
100
+ cxx: 'cpp',
101
+ hpp: 'cpp',
102
+ hh: 'cpp',
103
+ sql: 'sql',
104
+ rs: 'rust',
105
+ kt: 'kotlin',
106
+ kts: 'kotlin',
107
+ swift: 'swift',
108
+ go: 'go'
96
109
  };
97
- function inferLanguage(path) {
110
+
111
+ /**
112
+ * The language a file's name or extension infers: a listed value first (a
113
+ * later entry wins), then a built-in, else plain text (CodeBlock FR13).
114
+ */
115
+ function inferLanguage(path, codeLanguages) {
98
116
  if (path == null) {
99
117
  return 'plaintext';
100
118
  }
101
119
  const base = path.slice(path.lastIndexOf('/') + 1);
102
120
  const dot = base.lastIndexOf('.');
103
- if (dot <= 0) {
104
- return 'plaintext';
121
+ const extension = dot > 0 ? base.slice(dot + 1).toLowerCase() : null;
122
+ if (codeLanguages != null) {
123
+ for (let i = codeLanguages.length - 1; i >= 0; i--) {
124
+ const language = codeLanguages[i];
125
+ if (language.fileNames.includes(base) || extension != null && language.fileExtensions.includes(extension)) {
126
+ return language;
127
+ }
128
+ }
105
129
  }
106
- return EXTENSION_LANGUAGES[base.slice(dot + 1).toLowerCase()] ?? 'plaintext';
130
+ return extension == null ? 'plaintext' : EXTENSION_LANGUAGES[extension] ?? 'plaintext';
107
131
  }
108
132
 
109
133
  // ---------------------------------------------------------------------------
@@ -698,6 +722,7 @@ export function DiffViewer({
698
722
  file,
699
723
  viewMode = 'unified',
700
724
  language: languageProp,
725
+ codeLanguages,
701
726
  hasLineNumbers = true,
702
727
  isWrapped = false,
703
728
  changeIndicator = 'classic',
@@ -723,7 +748,7 @@ export function DiffViewer({
723
748
  ensureHighlightStyles();
724
749
  }, []);
725
750
  const path = file.newPath ?? file.oldPath;
726
- const language = languageProp ?? inferLanguage(path);
751
+ const language = languageProp ?? inferLanguage(path, codeLanguages);
727
752
  const displayPath = file.status === 'renamed' && file.oldPath != null && file.newPath != null ? t('@astryx.diffViewer.renamedPath', {
728
753
  oldPath: file.oldPath,
729
754
  newPath: file.newPath
@@ -1 +1 @@
1
- {"version":3,"file":"LogStream.d.ts","sourceRoot":"","sources":["../../src/LogStream/LogStream.tsx"],"names":[],"mappings":"AAyBA,OAAO,EAML,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAGf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,oBAAoB,CAAC;AAkBlD,iCAAiC;AACjC,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;AAEjE,0EAA0E;AAC1E,MAAM,WAAW,QAAQ;IACvB,4CAA4C;IAC5C,EAAE,EAAE,MAAM,CAAC;IACX,qEAAqE;IACrE,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,cAAc,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oEAAoE;IACpE,MAAM,CAAC,EAAE,SAAS,CAAC;CACpB;AAED,MAAM,WAAW,cAAe,SAAQ,IAAI,CAC1C,SAAS,CAAC,cAAc,CAAC,EACzB,UAAU,CACX;IACC,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC,6DAA6D;IAC7D,OAAO,EAAE,QAAQ,EAAE,CAAC;IACpB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC;IACjC;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,+EAA+E;IAC/E,cAAc,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;IAC9C,uDAAuD;IACvD,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,+CAA+C;IAC/C,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gEAAgE;IAChE,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,SAAS,CAAC;CAC9C;AAwOD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,SAAS,CAAC,EACxB,OAAO,EACP,OAAmB,EACnB,WAAW,EACX,cAAc,EACd,SAAS,EACT,aAAoB,EACpB,KAAoB,EACpB,WAAW,EACX,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,EACH,GAAG,IAAI,EACR,EAAE,cAAc,+BAqNhB;yBAnOe,SAAS"}
1
+ {"version":3,"file":"LogStream.d.ts","sourceRoot":"","sources":["../../src/LogStream/LogStream.tsx"],"names":[],"mappings":"AAyBA,OAAO,EAML,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAGf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,oBAAoB,CAAC;AAkBlD,iCAAiC;AACjC,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;AAEjE,0EAA0E;AAC1E,MAAM,WAAW,QAAQ;IACvB,4CAA4C;IAC5C,EAAE,EAAE,MAAM,CAAC;IACX,qEAAqE;IACrE,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,cAAc,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oEAAoE;IACpE,MAAM,CAAC,EAAE,SAAS,CAAC;CACpB;AAED,MAAM,WAAW,cAAe,SAAQ,IAAI,CAC1C,SAAS,CAAC,cAAc,CAAC,EACzB,UAAU,CACX;IACC,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC,6DAA6D;IAC7D,OAAO,EAAE,QAAQ,EAAE,CAAC;IACpB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC;IACjC;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,+EAA+E;IAC/E,cAAc,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;IAC9C,uDAAuD;IACvD,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,+CAA+C;IAC/C,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gEAAgE;IAChE,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,SAAS,CAAC;CAC9C;AAsOD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,SAAS,CAAC,EACxB,OAAO,EACP,OAAmB,EACnB,WAAW,EACX,cAAc,EACd,SAAS,EACT,aAAoB,EACpB,KAAoB,EACpB,WAAW,EACX,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,EACH,GAAG,IAAI,EACR,EAAE,cAAc,+BAqNhB;yBAnOe,SAAS"}
@@ -164,11 +164,11 @@ const styles = {
164
164
  $$css: true
165
165
  },
166
166
  levelWarn: {
167
- kMwMTN: "xuj0v0c",
167
+ kMwMTN: "x10h9ou4",
168
168
  $$css: true
169
169
  },
170
170
  levelError: {
171
- kMwMTN: "x1lenag",
171
+ kMwMTN: "x1wj83wy",
172
172
  $$css: true
173
173
  },
174
174
  levelInfoTerminal: {
@@ -75,15 +75,15 @@ const colorStyles = {
75
75
  $$css: true
76
76
  },
77
77
  positive: {
78
- kMwMTN: "xtjic6",
78
+ kMwMTN: "x1vau044",
79
79
  $$css: true
80
80
  },
81
81
  negative: {
82
- kMwMTN: "xjt36v0",
82
+ kMwMTN: "xskb5cx",
83
83
  $$css: true
84
84
  },
85
85
  warning: {
86
- kMwMTN: "xs3pv69",
86
+ kMwMTN: "x4z9hng",
87
87
  $$css: true
88
88
  },
89
89
  inherit: {
package/dist/Stat/Stat.js CHANGED
@@ -78,11 +78,11 @@ const sizeStyles = {
78
78
  */
79
79
  const sentimentStyles = {
80
80
  positive: {
81
- kMwMTN: "xtjic6",
81
+ kMwMTN: "x1caiuuo",
82
82
  $$css: true
83
83
  },
84
84
  negative: {
85
- kMwMTN: "xjt36v0",
85
+ kMwMTN: "x1wj83wy",
86
86
  $$css: true
87
87
  },
88
88
  neutral: {
package/dist/lab.css CHANGED
@@ -337,16 +337,15 @@
337
337
  .x1s4jh2n:not(#\#):not(#\#):not(#\#){color:color-mix(in srgb,var(--color-text-teal) 52%,var(--color-text-secondary))}
338
338
  .x1wzna5w:not(#\#):not(#\#):not(#\#){color:color-mix(in srgb,var(--color-text-yellow) 52%,var(--color-text-secondary))}
339
339
  .x1heor9g:not(#\#):not(#\#):not(#\#){color:inherit}
340
- .xuj0v0c:not(#\#):not(#\#):not(#\#){color:light-dark(color-mix(in srgb,var(--color-warning) 58%,black),var(--color-warning))}
341
- .x1lenag:not(#\#):not(#\#):not(#\#){color:light-dark(var(--color-error),color-mix(in srgb,var(--color-error) 82%,white))}
342
340
  .x19co3pv:not(#\#):not(#\#):not(#\#){color:transparent}
343
341
  .xqwr325:not(#\#):not(#\#):not(#\#){color:var(--color-accent)}
344
- .xjt36v0:not(#\#):not(#\#):not(#\#){color:var(--color-error)}
345
342
  .xqa6c3m:not(#\#):not(#\#):not(#\#){color:var(--color-icon-disabled)}
343
+ .xskb5cx:not(#\#):not(#\#):not(#\#){color:var(--color-icon-error)}
346
344
  .xtbr613:not(#\#):not(#\#):not(#\#){color:var(--color-icon-primary)}
347
345
  .xv9yike:not(#\#):not(#\#):not(#\#){color:var(--color-icon-secondary)}
346
+ .x1vau044:not(#\#):not(#\#):not(#\#){color:var(--color-icon-success)}
347
+ .x4z9hng:not(#\#):not(#\#):not(#\#){color:var(--color-icon-warning)}
348
348
  .x17wrial:not(#\#):not(#\#):not(#\#){color:var(--color-on-accent)}
349
- .xtjic6:not(#\#):not(#\#):not(#\#){color:var(--color-success)}
350
349
  .x1wxerb0:not(#\#):not(#\#):not(#\#){color:var(--color-syntax-added-marker)}
351
350
  .xt5rlkq:not(#\#):not(#\#):not(#\#){color:var(--color-syntax-punctuation)}
352
351
  .x103bwea:not(#\#):not(#\#):not(#\#){color:var(--color-syntax-removed-marker)}
@@ -355,6 +354,7 @@
355
354
  .x1vvqiwl:not(#\#):not(#\#):not(#\#){color:var(--color-text-blue)}
356
355
  .x1txnczv:not(#\#):not(#\#):not(#\#){color:var(--color-text-cyan)}
357
356
  .xnbbluu:not(#\#):not(#\#):not(#\#){color:var(--color-text-disabled)}
357
+ .x1wj83wy:not(#\#):not(#\#):not(#\#){color:var(--color-text-error)}
358
358
  .xru1t7f:not(#\#):not(#\#):not(#\#){color:var(--color-text-gray)}
359
359
  .xltfdvo:not(#\#):not(#\#):not(#\#){color:var(--color-text-green)}
360
360
  .xm47u9q:not(#\#):not(#\#):not(#\#){color:var(--color-text-orange)}
@@ -363,9 +363,10 @@
363
363
  .x1m9wyeb:not(#\#):not(#\#):not(#\#){color:var(--color-text-purple)}
364
364
  .x1joocv1:not(#\#):not(#\#):not(#\#){color:var(--color-text-red)}
365
365
  .xv1l7n4:not(#\#):not(#\#):not(#\#){color:var(--color-text-secondary)}
366
+ .x1caiuuo:not(#\#):not(#\#):not(#\#){color:var(--color-text-success)}
366
367
  .x9x0lbs:not(#\#):not(#\#):not(#\#){color:var(--color-text-teal)}
368
+ .x10h9ou4:not(#\#):not(#\#):not(#\#){color:var(--color-text-warning)}
367
369
  .xdhq94a:not(#\#):not(#\#):not(#\#){color:var(--color-text-yellow)}
368
- .xs3pv69:not(#\#):not(#\#):not(#\#){color:var(--color-warning)}
369
370
  .x1kihgfc:not(#\#):not(#\#):not(#\#){column-gap:var(--spacing-0-5)}
370
371
  .x1lfs0n9:not(#\#):not(#\#):not(#\#){column-gap:var(--spacing-1)}
371
372
  .xak3so:not(#\#):not(#\#):not(#\#){column-gap:var(--spacing-2)}
@@ -528,13 +529,13 @@
528
529
  .ximx5ud:not(#\#):not(#\#):not(#\#){stroke:var(--color-accent-muted)}
529
530
  .xjsr54c:not(#\#):not(#\#):not(#\#){stroke:var(--color-accent)}
530
531
  .xjswp7v:not(#\#):not(#\#):not(#\#){stroke:var(--color-error-muted)}
531
- .x1vco6zm:not(#\#):not(#\#):not(#\#){stroke:var(--color-error)}
532
532
  .x1uro670:not(#\#):not(#\#):not(#\#){stroke:var(--color-success-muted)}
533
- .x8y33gb:not(#\#):not(#\#):not(#\#){stroke:var(--color-success)}
534
533
  .xuxf9kk:not(#\#):not(#\#):not(#\#){stroke:var(--color-text-disabled)}
534
+ .xqb94c9:not(#\#):not(#\#):not(#\#){stroke:var(--color-text-error)}
535
+ .x88o7k4:not(#\#):not(#\#):not(#\#){stroke:var(--color-text-success)}
536
+ .x16d96h5:not(#\#):not(#\#):not(#\#){stroke:var(--color-text-warning)}
535
537
  .xpi25hw:not(#\#):not(#\#):not(#\#){stroke:var(--color-track)}
536
538
  .x1wjzxuj:not(#\#):not(#\#):not(#\#){stroke:var(--color-warning-muted)}
537
- .x9ezeq1:not(#\#):not(#\#):not(#\#){stroke:var(--color-warning)}
538
539
  .xeq4nuv:not(#\#):not(#\#):not(#\#){tab-size:2}
539
540
  .x140o2bo:not(#\#):not(#\#):not(#\#){table-layout:fixed}
540
541
  .x2b8uid:not(#\#):not(#\#):not(#\#){text-align:center}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astryxdesign/lab",
3
- "version": "0.7.5-canary.577e8ca",
3
+ "version": "0.7.5-canary.5b691cd",
4
4
  "description": "Experimental Astryx components — published to npm only under the @canary dist-tag for early testing; never released as a stable (latest) version.",
5
5
  "author": "Meta Open Source",
6
6
  "license": "MIT",
@@ -49,7 +49,7 @@
49
49
  },
50
50
  "peerDependencies": {
51
51
  "@stylexjs/stylex": ">=0.10.0",
52
- "@astryxdesign/core": "0.7.5-canary.577e8ca",
52
+ "@astryxdesign/core": "0.7.5-canary.5b691cd",
53
53
  "react": ">=19.0.0",
54
54
  "react-dom": ">=19.0.0"
55
55
  },
@@ -59,8 +59,8 @@
59
59
  "d3-shape": "^3.2.0"
60
60
  },
61
61
  "devDependencies": {
62
- "@astryxdesign/a11y-spec": "0.7.5-canary.577e8ca",
63
- "@astryxdesign/cli": "0.7.5-canary.577e8ca",
62
+ "@astryxdesign/a11y-spec": "0.7.5-canary.5b691cd",
63
+ "@astryxdesign/cli": "0.7.5-canary.5b691cd",
64
64
  "@babel/cli": "^7.29.7",
65
65
  "@babel/core": "^7.29.7",
66
66
  "@babel/preset-react": "^7.29.7",
@@ -74,14 +74,14 @@
74
74
  },
75
75
  "scripts": {
76
76
  "build": "node ../../scripts/clean-dist.mjs && pnpm build:esm && tsc --project tsconfig.build.json && node ../../scripts/add-declaration-extensions.mjs && pnpm build:css && node ../../scripts/check-no-dev-jsx.mjs && node ../../scripts/check-fully-specified.mjs",
77
- "build:esm": "babel src --out-dir dist --extensions .ts,.tsx --out-file-extension .js --ignore \"**/*.test.ts,**/*.test.tsx,**/__tests__/**,**/*.perf.test.*,**/*.doc.mjs,**/*.d.ts,**/*.css,**/*.css.d.ts\" --config-file ./babel.config.json",
77
+ "build:esm": "babel src --out-dir dist --extensions .ts,.tsx --out-file-extension .js --ignore \"**/*.test.ts,**/*.test.tsx,**/__tests__/**,**/*.perf.test.*,**/*.doc.mjs,**/*.d.ts,**/*.css,**/*.css.d.ts\" --config-file ./babel.config.cjs",
78
78
  "build:css": "node ../../scripts/build-css.mjs --package lab",
79
- "dev": "babel src --watch --out-dir dist --extensions .ts,.tsx --out-file-extension .js --ignore \"**/*.test.*,**/*.doc.mjs,**/*.d.ts,**/*.css*\" --config-file ./babel.config.json",
79
+ "dev": "babel src --watch --out-dir dist --extensions .ts,.tsx --out-file-extension .js --ignore \"**/*.test.*,**/*.doc.mjs,**/*.d.ts,**/*.css*\" --config-file ./babel.config.cjs",
80
80
  "test": "vitest run --root ../..",
81
81
  "test:watch": "vitest --root ../..",
82
82
  "lint": "eslint src",
83
83
  "typecheck:docs": "tsc --project tsconfig.docs.json",
84
- "typecheck": "tsc --project tsconfig.json --noEmit",
84
+ "typecheck": "tsc --project tsconfig.json --noEmit && pnpm typecheck:docs",
85
85
  "generate:emoji-data": "node scripts/generate-emoji-data.mjs"
86
86
  }
87
87
  }
@@ -63,7 +63,7 @@ const styles = stylex.create({
63
63
  fontFamily: typographyVars['--font-family-body'],
64
64
  fontSize: typeScaleVars['--text-supporting-size'],
65
65
  fontWeight: fontWeightVars['--font-weight-bold'],
66
- color: colorVars['--color-error'],
66
+ color: colorVars['--color-text-error'],
67
67
  lineHeight: typeScaleVars['--text-supporting-leading'],
68
68
  },
69
69
  });
@@ -1,4 +1,5 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // @pr-a11y release-only
2
3
 
3
4
  /** Real-browser and accessibility-tree binding for ChatTypingIndicator. */
4
5
 
@@ -260,13 +260,13 @@ const variantStyles = stylex.create({
260
260
  stroke: colorVars['--color-accent'],
261
261
  },
262
262
  success: {
263
- stroke: colorVars['--color-success'],
263
+ stroke: colorVars['--color-text-success'],
264
264
  },
265
265
  warning: {
266
- stroke: colorVars['--color-warning'],
266
+ stroke: colorVars['--color-text-warning'],
267
267
  },
268
268
  error: {
269
- stroke: colorVars['--color-error'],
269
+ stroke: colorVars['--color-text-error'],
270
270
  },
271
271
  neutral: {
272
272
  stroke: colorVars['--color-text-disabled'],
@@ -1,4 +1,5 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // @pr-a11y scope ^(internal/a11y-spec/src/patterns/progressbar\.|packages/core/src/ProgressBar/|packages/lab/src/CircularProgress/|apps/storybook/stories/ProgressbarA11y)
2
3
 
3
4
  /**
4
5
  * @file CircularProgress.a11y.chromium.spec.ts
@@ -82,6 +82,12 @@ import type {
82
82
  CommentUser,
83
83
  } from './types';
84
84
 
85
+ // The page's shared live regions are not the component's error Banner.
86
+ const errorBanner = () =>
87
+ screen
88
+ .queryAllByRole('alert')
89
+ .find(element => !element.hasAttribute('data-astryx-live-region'));
90
+
85
91
  const VIEWER: CommentUser = {id: 'avery', name: 'Avery Kim'};
86
92
  const OTHER: CommentUser = {id: 'maya', name: 'Maya Chen'};
87
93
  const AGENT: CommentUser = {
@@ -900,12 +906,12 @@ describe('Comments threads', () => {
900
906
  }),
901
907
  );
902
908
  await flush();
903
- const banner = screen.getByRole('alert');
909
+ const banner = errorBanner()!;
904
910
  expect(banner.textContent).toContain("Your reaction couldn't be saved.");
905
911
  await click(within(banner).getByRole('button', {name: 'Retry'}));
906
912
  await flush();
907
913
  expect(onReact).toHaveBeenCalledTimes(2);
908
- expect(screen.queryByRole('alert')).toBeNull();
914
+ expect(errorBanner()).toBeUndefined();
909
915
  });
910
916
 
911
917
  it('copies a link to the comment', async () => {
@@ -999,7 +1005,7 @@ describe('Comments threads', () => {
999
1005
  />
1000
1006
  </Sized>,
1001
1007
  );
1002
- const banner = screen.getByRole('alert');
1008
+ const banner = errorBanner()!;
1003
1009
  expect(banner.textContent).toContain("Couldn't post this comment.");
1004
1010
  await click(within(banner).getByRole('button', {name: 'Retry'}));
1005
1011
  await flush();
@@ -1022,7 +1028,7 @@ describe('Comments threads', () => {
1022
1028
  );
1023
1029
  await click(screen.getByRole('button', {name: 'Load earlier comments'}));
1024
1030
  await flush();
1025
- const banner = screen.getByRole('alert');
1031
+ const banner = errorBanner()!;
1026
1032
  expect(banner.textContent).toContain("Earlier comments couldn't load");
1027
1033
  await click(within(banner).getByRole('button', {name: 'Retry'}));
1028
1034
  await flush();
@@ -112,9 +112,15 @@ export const docs = {
112
112
  },
113
113
  {
114
114
  name: 'language',
115
- type: 'string',
115
+ type: 'string | CodeLanguage',
116
116
  description:
117
- 'Syntax-highlighting language. Defaults to one inferred from the file extension; unknown extensions render as plain text.',
117
+ 'Syntax-highlighting language: a built-in identifier, or a CodeBlock language value imported on its own (e.g. graphql from @astryxdesign/core/CodeBlock/languages/graphql) or made with createCodeLanguage. Defaults to one inferred from the file name or extension among the built-ins and codeLanguages; an unmatched file renders as plain text.',
118
+ },
119
+ {
120
+ name: 'codeLanguages',
121
+ type: 'ReadonlyArray<CodeLanguage>',
122
+ description:
123
+ 'Language values the file name or extension may infer, such as [graphql, dockerfile]; a later entry wins. Pass the same list to every DiffViewer on a review page.',
118
124
  },
119
125
  {
120
126
  name: 'hasLineNumbers',
@@ -7,6 +7,10 @@ import {createRef} from 'react';
7
7
  import {DiffViewer} from './DiffViewer';
8
8
  import {parseUnifiedDiff} from './parseUnifiedDiff';
9
9
  import type {DiffViewerLineRef} from './diffTypes';
10
+ import {createDiffFile} from './createDiffFile';
11
+ import {dockerfile} from '@astryxdesign/core/CodeBlock/languages/dockerfile';
12
+ import {graphql} from '@astryxdesign/core/CodeBlock/languages/graphql';
13
+ import {createCodeLanguage} from '@astryxdesign/core/CodeBlock';
10
14
 
11
15
  const PATCH = `diff --git a/src/greet.ts b/src/greet.ts
12
16
  --- a/src/greet.ts
@@ -72,6 +76,73 @@ describe('DiffViewer', () => {
72
76
  expect(container.querySelector('.astryx-token-keyword')).not.toBeNull();
73
77
  });
74
78
 
79
+ describe('language values (CodeBlock FR13)', () => {
80
+ const keywords = (root: ParentNode) =>
81
+ Array.from(root.querySelectorAll('.astryx-token-keyword')).map(
82
+ node => node.textContent,
83
+ );
84
+ const schema = createDiffFile({
85
+ oldValue: 'type User {}\n',
86
+ newValue: 'type User { name: String }\n',
87
+ newPath: 'api/schema.graphql',
88
+ });
89
+
90
+ it('takes a language value as language', () => {
91
+ const plain = render(<DiffViewer file={schema} language="graphql" />);
92
+ expect(keywords(plain.container)).toEqual([]);
93
+ const {container} = render(
94
+ <DiffViewer file={schema} language={graphql} />,
95
+ );
96
+ expect(keywords(container)).toContain('type');
97
+ });
98
+
99
+ it('infers a listed value from the file extension or name', () => {
100
+ const unlisted = render(<DiffViewer file={schema} />);
101
+ expect(keywords(unlisted.container)).toEqual([]);
102
+ const listed = render(
103
+ <DiffViewer file={schema} codeLanguages={[dockerfile, graphql]} />,
104
+ );
105
+ expect(keywords(listed.container)).toContain('type');
106
+ const docker = createDiffFile({
107
+ oldValue: 'FROM node:20\n',
108
+ newValue: 'FROM node:22\n',
109
+ newPath: 'Dockerfile',
110
+ });
111
+ const byName = render(
112
+ <DiffViewer file={docker} codeLanguages={[graphql, dockerfile]} />,
113
+ );
114
+ expect(keywords(byName.container)).toContain('FROM');
115
+ });
116
+
117
+ it('infers a custom language from its extension', () => {
118
+ const zig = createCodeLanguage({
119
+ name: 'zig',
120
+ identifiers: ['zig'],
121
+ fileExtensions: ['zig'],
122
+ tokenize: () => [{type: 'keyword', start: 0, end: 3}],
123
+ });
124
+ const file = createDiffFile({
125
+ oldValue: 'pub a\n',
126
+ newValue: 'pub b\n',
127
+ newPath: 'src/main.zig',
128
+ });
129
+ const {container} = render(
130
+ <DiffViewer file={file} codeLanguages={[zig]} />,
131
+ );
132
+ expect(keywords(container)).toContain('pub');
133
+ });
134
+
135
+ it('infers the newer built-ins from their extensions', () => {
136
+ const rust = createDiffFile({
137
+ oldValue: 'fn a() {}\n',
138
+ newValue: 'fn b() {}\n',
139
+ newPath: 'src/lib.rs',
140
+ });
141
+ const {container} = render(<DiffViewer file={rust} />);
142
+ expect(keywords(container)).toContain('fn');
143
+ });
144
+ });
145
+
75
146
  it('marks changed lines for assistive technology', () => {
76
147
  const {container} = render(<DiffViewer file={FILE} />);
77
148
  const addedCells = container.querySelectorAll('td[data-diff="added"]');
@@ -54,6 +54,7 @@ import type {BaseProps} from '@astryxdesign/core';
54
54
  import {
55
55
  ensureHighlightStyles,
56
56
  tokenize,
57
+ type CodeLanguage,
57
58
  type SyntaxToken,
58
59
  type TokenLine,
59
60
  } from '@astryxdesign/core/CodeBlock';
@@ -131,10 +132,20 @@ export interface DiffViewerProps extends BaseProps<HTMLDivElement> {
131
132
  */
132
133
  viewMode?: DiffViewerViewMode;
133
134
  /**
134
- * Syntax-highlighting language. Defaults to one inferred from the file's
135
- * extension; unknown extensions render as plain text.
135
+ * Syntax-highlighting language: a built-in identifier such as `'rust'`, or
136
+ * a language value — a module imported on its own, such as `graphql` from
137
+ * `@astryxdesign/core/CodeBlock/languages/graphql`, or one made with
138
+ * `createCodeLanguage`. Defaults to one inferred from the file's name or
139
+ * extension among the built-ins and `codeLanguages`; an unmatched file
140
+ * renders as plain text.
136
141
  */
137
- language?: string;
142
+ language?: string | CodeLanguage;
143
+ /**
144
+ * Language values the file's name or extension may infer, such as
145
+ * `[graphql, dockerfile]`; a later entry wins. Pass the same list to every
146
+ * DiffViewer on a review page.
147
+ */
148
+ codeLanguages?: ReadonlyArray<CodeLanguage>;
138
149
  /**
139
150
  * Show the old and new line-number gutters.
140
151
  * @default true
@@ -246,18 +257,49 @@ const EXTENSION_LANGUAGES: Record<string, string> = {
246
257
  yml: 'yaml',
247
258
  md: 'markdown',
248
259
  markdown: 'markdown',
260
+ c: 'c',
261
+ h: 'c',
262
+ cpp: 'cpp',
263
+ cc: 'cpp',
264
+ cxx: 'cpp',
265
+ hpp: 'cpp',
266
+ hh: 'cpp',
267
+ sql: 'sql',
268
+ rs: 'rust',
269
+ kt: 'kotlin',
270
+ kts: 'kotlin',
271
+ swift: 'swift',
272
+ go: 'go',
249
273
  };
250
274
 
251
- function inferLanguage(path: string | null): string {
275
+ /**
276
+ * The language a file's name or extension infers: a listed value first (a
277
+ * later entry wins), then a built-in, else plain text (CodeBlock FR13).
278
+ */
279
+ function inferLanguage(
280
+ path: string | null,
281
+ codeLanguages: ReadonlyArray<CodeLanguage> | undefined,
282
+ ): string | CodeLanguage {
252
283
  if (path == null) {
253
284
  return 'plaintext';
254
285
  }
255
286
  const base = path.slice(path.lastIndexOf('/') + 1);
256
287
  const dot = base.lastIndexOf('.');
257
- if (dot <= 0) {
258
- return 'plaintext';
288
+ const extension = dot > 0 ? base.slice(dot + 1).toLowerCase() : null;
289
+ if (codeLanguages != null) {
290
+ for (let i = codeLanguages.length - 1; i >= 0; i--) {
291
+ const language = codeLanguages[i];
292
+ if (
293
+ language.fileNames.includes(base) ||
294
+ (extension != null && language.fileExtensions.includes(extension))
295
+ ) {
296
+ return language;
297
+ }
298
+ }
259
299
  }
260
- return EXTENSION_LANGUAGES[base.slice(dot + 1).toLowerCase()] ?? 'plaintext';
300
+ return extension == null
301
+ ? 'plaintext'
302
+ : (EXTENSION_LANGUAGES[extension] ?? 'plaintext');
261
303
  }
262
304
 
263
305
  // ---------------------------------------------------------------------------
@@ -337,7 +379,7 @@ function addInlineEmphasis(
337
379
  */
338
380
  function buildCells(
339
381
  file: DiffViewerFile,
340
- language: string,
382
+ language: string | CodeLanguage,
341
383
  inlineHighlight: DiffViewerInlineHighlight,
342
384
  ): LineCell[][] {
343
385
  return file.hunks.map((hunk, hunkIndex) => {
@@ -1063,6 +1105,7 @@ export function DiffViewer({
1063
1105
  file,
1064
1106
  viewMode = 'unified',
1065
1107
  language: languageProp,
1108
+ codeLanguages,
1066
1109
  hasLineNumbers = true,
1067
1110
  isWrapped = false,
1068
1111
  changeIndicator = 'classic',
@@ -1090,7 +1133,7 @@ export function DiffViewer({
1090
1133
  }, []);
1091
1134
 
1092
1135
  const path = file.newPath ?? file.oldPath;
1093
- const language = languageProp ?? inferLanguage(path);
1136
+ const language = languageProp ?? inferLanguage(path, codeLanguages);
1094
1137
  const displayPath =
1095
1138
  file.status === 'renamed' && file.oldPath != null && file.newPath != null
1096
1139
  ? t('@astryx.diffViewer.renamedPath', {
@@ -660,10 +660,13 @@ describe('ListInput', () => {
660
660
  expect(animate).not.toHaveBeenCalled();
661
661
  expect(screen.queryByDisplayValue('Ada')).not.toBeInTheDocument();
662
662
  expect(screen.getByRole('button', {name: 'Add guest'})).toHaveFocus();
663
+ // The removal and the empty state that appears join in one frame (FR9).
663
664
  await waitFor(() => {
664
665
  expect(
665
666
  Array.from(document.querySelectorAll('[aria-live="polite"]')).some(
666
- node => node.textContent === 'Removed guest 1.',
667
+ node =>
668
+ node.textContent ===
669
+ 'Removed guest 1. No guests yet Add a guest to get started.',
667
670
  ),
668
671
  ).toBe(true);
669
672
  });
@@ -11,7 +11,7 @@ export const docs = {
11
11
 
12
12
  usage: {
13
13
  description:
14
- 'Experimental streaming log viewer: mono grid rows (timestamp | level | source | message) with token-derived level accents, expandable per-row detail panels, follow-scroll live tailing with a "Jump to latest" affordance, and an always-dark terminal variant. Appended rows fade in via @starting-style. Live announcements follow the pinning state: the role="log" region is aria-live="polite" only while following the tail, and aria-live="off" while unfollowed, so a busy stream never floods assistive tech.',
14
+ 'Experimental streaming log viewer: mono grid rows (timestamp | level | source | message) with token-derived level accents, expandable per-row detail panels, follow-scroll live tailing with a "Jump to latest" affordance, and an always-dark terminal variant. In the default variant, warning and error labels use their plain-surface status foreground roles. Appended rows fade in via @starting-style. Live announcements follow the pinning state: the role="log" region is aria-live="polite" only while following the tail, and aria-live="off" while unfollowed, so a busy stream never floods assistive tech.',
15
15
  },
16
16
 
17
17
  props: [
@@ -233,14 +233,12 @@ const styles = stylex.create({
233
233
  },
234
234
  levelInfo: {color: colorVars['--color-text-secondary']},
235
235
  levelDebug: {color: colorVars['--color-text-disabled']},
236
- // Token amber/red are tuned for fills; as small text they miss 4.5:1.
237
- // light-dark() darkens the amber in light mode and lifts the red in dark
238
- // mode, both derived from the tokens.
236
+ // Plain-surface warning/error labels use the dedicated foreground roles.
239
237
  levelWarn: {
240
- color: `light-dark(color-mix(in srgb, ${colorVars['--color-warning']} 58%, black), ${colorVars['--color-warning']})`,
238
+ color: colorVars['--color-text-warning'],
241
239
  },
242
240
  levelError: {
243
- color: `light-dark(${colorVars['--color-error']}, color-mix(in srgb, ${colorVars['--color-error']} 82%, white))`,
241
+ color: colorVars['--color-text-error'],
244
242
  },
245
243
  levelInfoTerminal: {color: TERM.text},
246
244
  levelDebugTerminal: {color: TERM.textDim},
@@ -56,7 +56,14 @@ function Harness({
56
56
  );
57
57
  }
58
58
 
59
- function CreateHarness({spy}: {spy: ReturnType<typeof vi.fn>}) {
59
+ function CreateHarness({
60
+ spy,
61
+ }: {
62
+ spy: (
63
+ items: SearchableItem[],
64
+ change: MobileTokenizerChange<SearchableItem>,
65
+ ) => void;
66
+ }) {
60
67
  const [value, setValue] = useState<SearchableItem[]>([]);
61
68
  return (
62
69
  <MobileTokenizer
@@ -105,8 +112,10 @@ beforeEach(() => {
105
112
  window.scrollTo = vi.fn();
106
113
  vi.stubGlobal(
107
114
  'requestAnimationFrame',
115
+ // Next microtask, not synchronously: a real frame never runs before
116
+ // requestAnimationFrame returns, and callers may rely on its id.
108
117
  vi.fn((cb: FrameRequestCallback) => {
109
- cb(0);
118
+ queueMicrotask(() => cb(0));
110
119
  return 1;
111
120
  }),
112
121
  );
@@ -302,7 +311,7 @@ describe('MobileTokenizer (Lab, single-sheet flow)', () => {
302
311
  const title = await screen.findByRole('heading', {
303
312
  name: 'No results found',
304
313
  });
305
- const emptyState = title.closest('[role="status"]');
314
+ const emptyState = title.closest('.astryx-empty-state');
306
315
  expect(emptyState).toHaveTextContent('Try a different search.');
307
316
  expect(emptyState?.querySelector('.astryx-icon')).toHaveAttribute(
308
317
  'data-size',
@@ -118,9 +118,9 @@ const colorStyles = stylex.create({
118
118
  secondary: {color: colorVars['--color-icon-secondary']},
119
119
  disabled: {color: colorVars['--color-icon-disabled']},
120
120
  accent: {color: colorVars['--color-accent']},
121
- positive: {color: colorVars['--color-success']},
122
- negative: {color: colorVars['--color-error']},
123
- warning: {color: colorVars['--color-warning']},
121
+ positive: {color: colorVars['--color-icon-success']},
122
+ negative: {color: colorVars['--color-icon-error']},
123
+ warning: {color: colorVars['--color-icon-warning']},
124
124
  inherit: {color: 'inherit'},
125
125
  });
126
126
 
package/src/Stat/Stat.tsx CHANGED
@@ -116,10 +116,10 @@ const sizeStyles = stylex.create({
116
116
  */
117
117
  const sentimentStyles = stylex.create({
118
118
  positive: {
119
- color: colorVars['--color-success'],
119
+ color: colorVars['--color-text-success'],
120
120
  },
121
121
  negative: {
122
- color: colorVars['--color-error'],
122
+ color: colorVars['--color-text-error'],
123
123
  },
124
124
  neutral: {
125
125
  color: colorVars['--color-text-secondary'],
@@ -1,4 +1,5 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // @pr-a11y always
2
3
 
3
4
  /**
4
5
  * @file ReorderGripPinchZoom.a11y.chromium.spec.ts