@kanso-labs/kanso-ui 0.40.8 → 0.41.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 (54) hide show
  1. package/dist/color-scheme.d.ts +6 -0
  2. package/dist/color-scheme.js +9 -2
  3. package/dist/color-scheme.js.map +1 -1
  4. package/dist/components/app-bar/index.d.ts +11 -2
  5. package/dist/components/app-bar/index.js +53 -46
  6. package/dist/components/app-bar/index.js.map +1 -1
  7. package/dist/components/avatar/index.d.ts +7 -0
  8. package/dist/components/avatar/index.js.map +1 -1
  9. package/dist/components/badge/index.js +7 -3
  10. package/dist/components/badge/index.js.map +1 -1
  11. package/dist/components/card/index.d.ts +12 -1
  12. package/dist/components/card/index.js +136 -66
  13. package/dist/components/card/index.js.map +1 -1
  14. package/dist/components/dialog/index.js +3 -2
  15. package/dist/components/dialog/index.js.map +1 -1
  16. package/dist/components/popover/index.d.ts +4 -1
  17. package/dist/components/popover/index.js +241 -138
  18. package/dist/components/popover/index.js.map +1 -1
  19. package/dist/components/product-icon/index.d.ts +3 -1
  20. package/dist/components/product-icon/index.js.map +1 -1
  21. package/dist/components/progress-indicator/index.js +1 -1
  22. package/dist/components/progress-indicator/index.js.map +1 -1
  23. package/dist/components/search-field/index.js +7 -3
  24. package/dist/components/search-field/index.js.map +1 -1
  25. package/dist/components/segmented-button/index.d.ts +20 -1
  26. package/dist/components/segmented-button/index.js +253 -114
  27. package/dist/components/segmented-button/index.js.map +1 -1
  28. package/dist/components/separator/index.js +2 -2
  29. package/dist/components/separator/index.js.map +1 -1
  30. package/dist/components/sheet/index.js +17 -16
  31. package/dist/components/sheet/index.js.map +1 -1
  32. package/dist/components/snackbar/index.d.ts +10 -3
  33. package/dist/components/snackbar/index.js +32 -12
  34. package/dist/components/snackbar/index.js.map +1 -1
  35. package/dist/components/switch/index.js +12 -3
  36. package/dist/components/switch/index.js.map +1 -1
  37. package/dist/components/toolbar/index.d.ts +3 -2
  38. package/dist/components/toolbar/index.js +3 -2
  39. package/dist/components/toolbar/index.js.map +1 -1
  40. package/dist/field/index.js +67 -61
  41. package/dist/field/index.js.map +1 -1
  42. package/dist/field/press.js +27 -0
  43. package/dist/field/press.js.map +1 -0
  44. package/dist/mark/initials.js +41 -26
  45. package/dist/mark/initials.js.map +1 -1
  46. package/dist/overlay/index.js +24 -0
  47. package/dist/overlay/index.js.map +1 -0
  48. package/dist/styles/scheme.js +19 -0
  49. package/dist/styles/scheme.js.map +1 -0
  50. package/dist/styles.css +106 -34
  51. package/dist/theme-scope.d.ts +5 -2
  52. package/dist/theme-scope.js +2 -1
  53. package/dist/theme-scope.js.map +1 -1
  54. package/package.json +1 -1
@@ -26,6 +26,12 @@ declare const themeScope: string;
26
26
  *
27
27
  * A `--kui-color-*` override still applies under either, declared on the
28
28
  * same element or above it.
29
+ *
30
+ * Either also paints the element's surface and text in its scheme and sets
31
+ * `color-scheme`, which native controls and scrollbars follow, as
32
+ * `ThemeScope` does with `scheme` set. On `<html>` that makes the page's
33
+ * own background and text colour the scheme's; an app's own stylesheet
34
+ * still wins over both, since the library's rules sit in a cascade layer.
29
35
  */
30
36
  declare const colorScheme: {
31
37
  dark: string;
@@ -1,5 +1,6 @@
1
1
  import { props } from "./node_modules/@stylexjs/stylex/lib/es/stylex.js";
2
2
  import { colorDefaultsDarkTheme, colorDefaultsLightTheme, tokenScope } from "./tokens/design.tokens.stylex.js";
3
+ import { pinnedScheme } from "./styles/scheme.js";
3
4
  //#region src/color-scheme.ts
4
5
  /**
5
6
  * The class that lets an element theme what is inside it. A `--kui-*`
@@ -28,10 +29,16 @@ const themeScope = props(tokenScope).className ?? "";
28
29
  *
29
30
  * A `--kui-color-*` override still applies under either, declared on the
30
31
  * same element or above it.
32
+ *
33
+ * Either also paints the element's surface and text in its scheme and sets
34
+ * `color-scheme`, which native controls and scrollbars follow, as
35
+ * `ThemeScope` does with `scheme` set. On `<html>` that makes the page's
36
+ * own background and text colour the scheme's; an app's own stylesheet
37
+ * still wins over both, since the library's rules sit in a cascade layer.
31
38
  */
32
39
  const colorScheme = {
33
- dark: props(tokenScope, colorDefaultsDarkTheme).className ?? "",
34
- light: props(tokenScope, colorDefaultsLightTheme).className ?? ""
40
+ dark: props(tokenScope, colorDefaultsDarkTheme, pinnedScheme.dark).className ?? "",
41
+ light: props(tokenScope, colorDefaultsLightTheme, pinnedScheme.light).className ?? ""
35
42
  };
36
43
  //#endregion
37
44
  export { colorScheme, themeScope };
@@ -1 +1 @@
1
- {"version":3,"file":"color-scheme.js","names":["stylex","colorDefaultsDarkTheme","colorDefaultsLightTheme","tokenScope","themeScope","props","className","colorScheme","dark","light","stylex.props"],"sources":["../src/color-scheme.ts"],"sourcesContent":["import * as stylex from '@stylexjs/stylex';\nimport { colorDefaultsDarkTheme, colorDefaultsLightTheme, tokenScope } from './tokens/design.tokens.stylex';\n\n// The library's tokens resolve once, on `:root`, and follow the reader's OS\n// through `prefers-color-scheme` unless something says otherwise. These are\n// the classes that say otherwise, for a page that cannot or would rather not\n// render `ThemeScope`: `themeScope` resolves every token again on the element\n// it lands on, and each `colorScheme` class does that and pins the scheme\n// too. All three were generated for Storybook first, where the Theme control\n// uses the scheme pair; nothing in the package named them, so an app with a\n// switch of its own had to restate every colour token under its own\n// selector, twice — dark for a light OS, light for a dark one.\n//\n// A server module like the entry, since it is three strings.\n\n/**\n * The class that lets an element theme what is inside it. A `--kui-*`\n * override declared on that element, or on one around it, reaches every\n * component rendered inside, where on any element but `<html>` it would\n * otherwise reach none — the tokens resolve on `:root` and are inherited from\n * there already resolved. The scheme is inherited from around it, so a scope\n * inside a dark page stays dark.\n *\n * Overlays are portalled to the body, outside the element, so they keep the\n * page's tokens; `ThemeScope` is the same class with a portal container of\n * its own, which takes them along.\n */\nconst themeScope = stylex.props(tokenScope).className ?? '';\n\n/**\n * The classes that pin the library's colours to its light or its dark\n * scheme, whatever the reader's OS asks for — for an app with a theme switch\n * of its own. Put one on the `<html>` element, where overlays portalled to\n * the body still sit inside it; with neither there, the colours follow the\n * OS as they always have. Each is also a {@link themeScope}, so either on a\n * smaller element pins and scopes the subtree under it.\n *\n * Shaped as an object of class names, one per scheme. Each name is several\n * classes separated by spaces, so add them with `className` rather than\n * `classList.add`, which takes one class per argument.\n *\n * A `--kui-color-*` override still applies under either, declared on the\n * same element or above it.\n */\nconst colorScheme = {\n dark: stylex.props(tokenScope, colorDefaultsDarkTheme).className ?? '',\n light: stylex.props(tokenScope, colorDefaultsLightTheme).className ?? ''\n};\nexport { colorScheme, themeScope };"],"mappings":";;;;;;;;;;;;;;;AA2BA,MAAMI,aAAaJ,MAAaG,UAAU,CAAC,CAACG,aAAa;;;;;;;;;;;;;;;;AAiBzD,MAAMC,cAAc;CAClBC,MAAMR,MAAaG,YAAYF,sBAAsB,CAAC,CAACK,aAAa;CACpEG,OAAOT,MAAaG,YAAYD,uBAAuB,CAAC,CAACI,aAAa;AACxE"}
1
+ {"version":3,"file":"color-scheme.js","names":["stylex","pinnedScheme","colorDefaultsDarkTheme","colorDefaultsLightTheme","tokenScope","themeScope","props","className","colorScheme","dark","light","stylex.props"],"sources":["../src/color-scheme.ts"],"sourcesContent":["import * as stylex from '@stylexjs/stylex';\nimport { pinnedScheme } from './styles/scheme';\nimport { colorDefaultsDarkTheme, colorDefaultsLightTheme, tokenScope } from './tokens/design.tokens.stylex';\n\n// The library's tokens resolve once, on `:root`, and follow the reader's OS\n// through `prefers-color-scheme` unless something says otherwise. These are\n// the classes that say otherwise, for a page that cannot or would rather not\n// render `ThemeScope`: `themeScope` resolves every token again on the element\n// it lands on, and each `colorScheme` class does that and pins the scheme\n// too. All three were generated for Storybook first, where the Theme control\n// uses the scheme pair; nothing in the package named them, so an app with a\n// switch of its own had to restate every colour token under its own\n// selector, twice — dark for a light OS, light for a dark one.\n//\n// A server module like the entry, since it is three strings.\n\n/**\n * The class that lets an element theme what is inside it. A `--kui-*`\n * override declared on that element, or on one around it, reaches every\n * component rendered inside, where on any element but `<html>` it would\n * otherwise reach none — the tokens resolve on `:root` and are inherited from\n * there already resolved. The scheme is inherited from around it, so a scope\n * inside a dark page stays dark.\n *\n * Overlays are portalled to the body, outside the element, so they keep the\n * page's tokens; `ThemeScope` is the same class with a portal container of\n * its own, which takes them along.\n */\nconst themeScope = stylex.props(tokenScope).className ?? '';\n\n/**\n * The classes that pin the library's colours to its light or its dark\n * scheme, whatever the reader's OS asks for — for an app with a theme switch\n * of its own. Put one on the `<html>` element, where overlays portalled to\n * the body still sit inside it; with neither there, the colours follow the\n * OS as they always have. Each is also a {@link themeScope}, so either on a\n * smaller element pins and scopes the subtree under it.\n *\n * Shaped as an object of class names, one per scheme. Each name is several\n * classes separated by spaces, so add them with `className` rather than\n * `classList.add`, which takes one class per argument.\n *\n * A `--kui-color-*` override still applies under either, declared on the\n * same element or above it.\n *\n * Either also paints the element's surface and text in its scheme and sets\n * `color-scheme`, which native controls and scrollbars follow, as\n * `ThemeScope` does with `scheme` set. On `<html>` that makes the page's\n * own background and text colour the scheme's; an app's own stylesheet\n * still wins over both, since the library's rules sit in a cascade layer.\n */\nconst colorScheme = {\n dark: stylex.props(tokenScope, colorDefaultsDarkTheme, pinnedScheme.dark).className ?? '',\n light: stylex.props(tokenScope, colorDefaultsLightTheme, pinnedScheme.light).className ?? ''\n};\nexport { colorScheme, themeScope };"],"mappings":";;;;;;;;;;;;;;;;AA4BA,MAAMK,aAAaL,MAAaI,UAAU,CAAC,CAACG,aAAa;;;;;;;;;;;;;;;;;;;;;;AAuBzD,MAAMC,cAAc;CAClBC,MAAMT,MAAaI,YAAYF,wBAAwBD,aAAaQ,IAAI,CAAC,CAACF,aAAa;CACvFG,OAAOV,MAAaI,YAAYD,yBAAyBF,aAAaS,KAAK,CAAC,CAACH,aAAa;AAC5F"}
@@ -10,7 +10,7 @@ type AppBarProps = Omit<RenderComponentProps<'header'>, 'children'> & {
10
10
  align?: 'center' | 'start';
11
11
  /**
12
12
  * Collapses a flexible bar to the height and headline of the small one, for
13
- * a pinned bar over content that has been scrolled. Material Design
13
+ * a bar `pinned` over content that has been scrolled. Material Design
14
14
  * specifies it for the flexible sizes, and without it a pinned `lg` costs
15
15
  * 152px of the viewport for as long as the page is open.
16
16
  *
@@ -76,6 +76,15 @@ type AppBarProps = Omit<RenderComponentProps<'header'>, 'children'> & {
76
76
  headline?: ReactNode;
77
77
  /** Usually a back or menu icon button. Sits before the text. */
78
78
  leading?: ReactNode;
79
+ /**
80
+ * Holds the bar at the top of its scroll container while the content
81
+ * scrolls beneath it, and keeps it painted over that content. The bar
82
+ * still needs a scrolling ancestor to stick inside: the window, or an
83
+ * element with its own overflow. A pinned bar is the one `collapsed` and
84
+ * `scrolled` are for.
85
+ * @default false
86
+ */
87
+ pinned?: boolean;
79
88
  /**
80
89
  * Whether the content beneath has been scrolled. Material Design separates
81
90
  * a bar from scrolled content with a fill colour rather than a shadow, and
@@ -112,7 +121,7 @@ type AppBarProps = Omit<RenderComponentProps<'header'>, 'children'> & {
112
121
  * and `collapsed` exist. Neither watches the page: only the app knows which
113
122
  * element scrolls, so both are set from its own scroll handler.
114
123
  */
115
- declare function AppBar({ align, collapsed, contentInset, contentMaxInlineSize, headingLevel, headline, leading, render, scrolled, size, subtitle, trailing, ...props }: AppBarProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
124
+ declare function AppBar({ align, collapsed, contentInset, contentMaxInlineSize, headingLevel, headline, leading, pinned, render, scrolled, size, subtitle, trailing, ...props }: AppBarProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
116
125
  //#endregion
117
126
  export { type AppBarProps, AppBar as default };
118
127
  //# sourceMappingURL=index.d.ts.map
@@ -26,6 +26,12 @@ const HEIGHTS = {
26
26
  };
27
27
  const COLLAPSED_HEIGHT = HEIGHTS.sm.plain;
28
28
  const styles = {
29
+ pinned: {
30
+ k87sOh: "x13vifvy",
31
+ kVAEAm: "x7wzq59",
32
+ kY2c9j: "xfj7q76",
33
+ $$css: true
34
+ },
29
35
  root: {
30
36
  k6CgDc: "x12w9bfk",
31
37
  kGNEyG: "x6s0dn4",
@@ -117,15 +123,16 @@ function AppBar(t0) {
117
123
  let t4;
118
124
  let t5;
119
125
  if ($[0] !== t0) {
120
- const { align: t6, collapsed: t7, contentInset: t8, contentMaxInlineSize: t9, headingLevel: t10, headline, leading, render: t11, scrolled: t12, size: t13, subtitle, trailing, ...props$1 } = t0;
121
- render = t11;
126
+ const { align: t6, collapsed: t7, contentInset: t8, contentMaxInlineSize: t9, headingLevel: t10, headline, leading, pinned: t11, render: t12, scrolled: t13, size: t14, subtitle, trailing, ...props$1 } = t0;
127
+ render = t12;
122
128
  const align = t6 === void 0 ? "start" : t6;
123
129
  const collapsed = t7 === void 0 ? false : t7;
124
130
  const contentInset = t8 === void 0 ? spacing.lg : t8;
125
131
  const contentMaxInlineSize = t9 === void 0 ? "none" : t9;
126
132
  const headingLevel = t10 === void 0 ? 1 : t10;
127
- const scrolled = t12 === void 0 ? false : t12;
128
- const size = t13 === void 0 ? "sm" : t13;
133
+ const pinned = t11 === void 0 ? false : t11;
134
+ const scrolled = t13 === void 0 ? false : t13;
135
+ const size = t14 === void 0 ? "sm" : t14;
129
136
  const collapse = collapsed && size !== "sm";
130
137
  const expandedHeight = hasContent(subtitle) ? HEIGHTS[size].withSubtitle : HEIGHTS[size].plain;
131
138
  const height = collapse ? COLLAPSED_HEIGHT : expandedHeight;
@@ -134,29 +141,29 @@ function AppBar(t0) {
134
141
  t5 = useRender;
135
142
  t4 = "header";
136
143
  t1 = props$1;
137
- const t14 = props(styles.row, rowStyles.root(edgePadding(contentInset, hasLeading), edgePadding(contentInset, hasTrailing), contentMaxInlineSize));
138
- let t15;
144
+ const t15 = props(styles.row, rowStyles.root(edgePadding(contentInset, hasLeading), edgePadding(contentInset, hasTrailing), contentMaxInlineSize));
145
+ let t16;
139
146
  if ($[7] !== hasLeading || $[8] !== leading) {
140
- t15 = !hasLeading ? null : /* @__PURE__ */ jsx("div", {
147
+ t16 = !hasLeading ? null : /* @__PURE__ */ jsx("div", {
141
148
  className: "x6s0dn4 x9f619 x78zum5 x2lah0s x1r8zjiw x1let9r4",
142
149
  children: leading
143
150
  });
144
151
  $[7] = hasLeading;
145
152
  $[8] = leading;
146
- $[9] = t15;
147
- } else t15 = $[9];
148
- let t16;
153
+ $[9] = t16;
154
+ } else t16 = $[9];
155
+ let t17;
149
156
  if ($[10] === Symbol.for("react.memo_cache_sentinel")) {
150
- t16 = {
157
+ t17 = {
151
158
  0: { className: "x9f619 x78zum5 xdt5ytf x1iyjqo2 xkjl1po xl56j7k xeuugli xj0a0fe x1cmllll" },
152
159
  1: { className: "x9f619 x78zum5 xdt5ytf x1iyjqo2 xkjl1po xl56j7k xeuugli xj0a0fe x1cmllll x2b8uid" }
153
160
  };
154
- $[10] = t16;
155
- } else t16 = $[10];
156
- const t17 = t16[!!(align === "center") << 0];
157
- let t18;
161
+ $[10] = t17;
162
+ } else t17 = $[10];
163
+ const t18 = t17[!!(align === "center") << 0];
164
+ let t19;
158
165
  if ($[11] !== collapse || $[12] !== headingLevel || $[13] !== headline || $[14] !== size) {
159
- t18 = !hasContent(headline) ? null : /* @__PURE__ */ jsx(Text, {
166
+ t19 = !hasContent(headline) ? null : /* @__PURE__ */ jsx(Text, {
160
167
  className: "x12w9bfk xioksi3 x1nxaspg x1seskgd",
161
168
  render: heading(headingLevel),
162
169
  variant: collapse ? HEADLINE_VARIANT.sm : HEADLINE_VARIANT[size],
@@ -166,11 +173,11 @@ function AppBar(t0) {
166
173
  $[12] = headingLevel;
167
174
  $[13] = headline;
168
175
  $[14] = size;
169
- $[15] = t18;
170
- } else t18 = $[15];
171
- let t19;
176
+ $[15] = t19;
177
+ } else t19 = $[15];
178
+ let t20;
172
179
  if ($[16] !== collapse || $[17] !== subtitle) {
173
- t19 = !hasContent(subtitle) || collapse ? null : /* @__PURE__ */ jsx(Text, {
180
+ t20 = !hasContent(subtitle) || collapse ? null : /* @__PURE__ */ jsx(Text, {
174
181
  render: PARAGRAPH,
175
182
  tone: "muted",
176
183
  variant: "bodyMedium",
@@ -178,45 +185,45 @@ function AppBar(t0) {
178
185
  });
179
186
  $[16] = collapse;
180
187
  $[17] = subtitle;
181
- $[18] = t19;
182
- } else t19 = $[18];
183
- let t20;
184
- if ($[19] !== t17 || $[20] !== t18 || $[21] !== t19) {
185
- t20 = /* @__PURE__ */ jsxs("div", {
186
- ...t17,
187
- children: [t18, t19]
188
- });
189
- $[19] = t17;
190
- $[20] = t18;
191
- $[21] = t19;
192
- $[22] = t20;
193
- } else t20 = $[22];
188
+ $[18] = t20;
189
+ } else t20 = $[18];
194
190
  let t21;
191
+ if ($[19] !== t18 || $[20] !== t19 || $[21] !== t20) {
192
+ t21 = /* @__PURE__ */ jsxs("div", {
193
+ ...t18,
194
+ children: [t19, t20]
195
+ });
196
+ $[19] = t18;
197
+ $[20] = t19;
198
+ $[21] = t20;
199
+ $[22] = t21;
200
+ } else t21 = $[22];
201
+ let t22;
195
202
  if ($[23] !== hasTrailing || $[24] !== trailing) {
196
- t21 = !hasTrailing ? null : /* @__PURE__ */ jsx("div", {
203
+ t22 = !hasTrailing ? null : /* @__PURE__ */ jsx("div", {
197
204
  className: "x6s0dn4 x9f619 x78zum5 x2lah0s x1r8zjiw x1let9r4",
198
205
  children: trailing
199
206
  });
200
207
  $[23] = hasTrailing;
201
208
  $[24] = trailing;
202
- $[25] = t21;
203
- } else t21 = $[25];
204
- if ($[26] !== t14 || $[27] !== t15 || $[28] !== t20 || $[29] !== t21) {
209
+ $[25] = t22;
210
+ } else t22 = $[25];
211
+ if ($[26] !== t15 || $[27] !== t16 || $[28] !== t21 || $[29] !== t22) {
205
212
  t2 = /* @__PURE__ */ jsxs("div", {
206
- ...t14,
213
+ ...t15,
207
214
  children: [
208
- t15,
209
- t20,
210
- t21
215
+ t16,
216
+ t21,
217
+ t22
211
218
  ]
212
219
  });
213
- $[26] = t14;
214
- $[27] = t15;
215
- $[28] = t20;
216
- $[29] = t21;
220
+ $[26] = t15;
221
+ $[27] = t16;
222
+ $[28] = t21;
223
+ $[29] = t22;
217
224
  $[30] = t2;
218
225
  } else t2 = $[30];
219
- t3 = mergeStyles(props(styles.root, heightStyles.root(height), scrolled && styles.scrolled), props$1);
226
+ t3 = mergeStyles(props(styles.root, heightStyles.root(height), scrolled && styles.scrolled, pinned && styles.pinned), props$1);
220
227
  $[0] = t0;
221
228
  $[1] = render;
222
229
  $[2] = t1;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["c","_c","ReactNode","stylex","createElement","RenderComponentProps","COLLAPSED_BLOCK_SIZE","hasContent","useRender","mergeStyles","colors","motion","sizing","spacing","Text","ICON_BUTTON_TARGET","ICON_SIZE","GLYPH_INSET","HEIGHTS","lg","plain","withSubtitle","md","sm","const","COLLAPSED_HEIGHT","FORCED_COLORS","styles","root","k6CgDc","kGNEyG","kWkggS","kB7OPa","k1xSpc","kjj79g","kIyJzY","k1ekBW","kAMwcw","$$css","row","kOIVth","kzqmXN","kUOVxO","scrolled","kL6WhQ","kfdmCh","kt9PQ7","HEADLINE_VARIANT","HEADINGS","heading","level","index","Math","min","max","round","length","PARAGRAPH","_temp","kAzted","heightStyles","minBlockSize","val","undefined","_temp2","ks0D6T","rowStyles","start","end","maxInlineSize","kwRFfy","kZCmMZ","AppBarProps","Omit","align","collapsed","contentInset","contentMaxInlineSize","headingLevel","headline","leading","size","subtitle","trailing","AppBar","t0","$","render","t1","t2","t3","t4","t5","t6","t7","t8","t9","t10","t11","t12","t13","props","collapse","expandedHeight","height","hasLeading","hasTrailing","t14","edgePadding","t15","t16","Symbol","for","0","className","1","t17","t18","t19","t20","t21","children","defaultTagName","hasSlot","inset","trim","_c","props","stylex.props"],"sources":["../../../src/components/app-bar/index.tsx"],"sourcesContent":["'use client';\n\nimport type { ReactNode } from 'react';\nimport * as stylex from '@stylexjs/stylex';\nimport { createElement } from 'react';\nimport type { RenderComponentProps } from '../../render/useRender';\nimport { COLLAPSED_BLOCK_SIZE } from '../../hooks/useAppBarScroll';\nimport { hasContent } from '../../render/content';\nimport { useRender } from '../../render/useRender';\nimport { mergeStyles } from '../../styles/merge';\nimport '../../tokens/design.tokens.stylex';\nimport { colors, motion, sizing, spacing } from '../../tokens/design.tokens.stylex';\nimport Text from '../text';\n\n// Material Design's app bar, in the three sizes the spec recommends.\n//\n// `md` and `lg` are Material Design's medium and large *flexible* bars, the\n// newer of the two sets the spec gives and the one it recommends, which is why\n// those two steps are theirs.\n//\n// Material Design also merged the old center-aligned variant into small as a\n// configuration rather than a variant, which is why alignment is a prop here\n// and applies to every size.\n//\n// Heights are Material Design's, and they are minimums rather than fixed. The\n// spec says the flexible bars \"hug the text contents\" and gives them multi-line\n// support and text wrapping, so a headline long enough to wrap has to be able\n// to make its bar taller. Fixing the height would truncate exactly the case\n// the variant was redesigned for.\n\n// The geometry Material Design lays a bar's icon buttons out on. Its tokens\n// give a 4dp leading and trailing space between the bar's edge and the first\n// button's 48dp target, no space between one target and the next, and a 24dp\n// icon centred in each — so a glyph lands 4 + 12 = 16dp in, on the page's own\n// margin.\n//\n// The library's icon button draws a 40dp box with its 48dp target out of\n// flow, so a slot pads half the difference either side and puts the whole\n// difference between two buttons, which lays the targets edge to edge as the\n// tokens do. The target is IconButton's TARGET_SIZE, a literal there for the\n// reason it gives: it is a floor the page states, not a step of the control\n// scale.\nconst ICON_BUTTON_TARGET = '48px';\nconst ICON_SIZE = '24px';\n\n// How far an icon sits inside its target, which is how much less than the\n// content inset the row is padded on an edge that holds a slot. That is what\n// puts a leading glyph, rather than the edge of its target, at the inset.\nconst GLYPH_INSET = `(${ICON_BUTTON_TARGET} - ${ICON_SIZE}) / 2`;\nconst HEIGHTS = {\n lg: {\n plain: '120px',\n withSubtitle: '152px'\n },\n md: {\n plain: '112px',\n withSubtitle: '136px'\n },\n sm: {\n plain: `${COLLAPSED_BLOCK_SIZE}px`,\n withSubtitle: `${COLLAPSED_BLOCK_SIZE}px`\n }\n} as const;\n\n// What a flexible bar collapses to, which is the small bar exactly. Material\n// Design does not describe the collapsed large bar as a state of its own — it\n// describes it as becoming the small bar, which is why this reads off the same\n// table rather than being a fourth height.\nconst COLLAPSED_HEIGHT = HEIGHTS.sm.plain;\n\n// Windows High Contrast and the rest of the forced-colours modes. Spelled\n// here rather than imported, for the reason src/field/styles.ts records: the\n// StyleX compiler resolves a constant across files only out of a `.stylex.ts`\n// module, and the generated one holds design tokens rather than queries.\nconst FORCED_COLORS = '@media (forced-colors: active)';\nconst styles = {\n root: {\n k6CgDc: \"x12w9bfk\",\n kGNEyG: \"x6s0dn4\",\n kWkggS: \"x14s9m32\",\n kB7OPa: \"x9f619\",\n k1xSpc: \"x78zum5\",\n kjj79g: \"xl56j7k\",\n kIyJzY: \"xioksi3\",\n k1ekBW: \"x8u3r54\",\n kAMwcw: \"x1seskgd\",\n $$css: true\n },\n row: {\n kGNEyG: \"x6s0dn4\",\n kB7OPa: \"x9f619\",\n k1xSpc: \"x78zum5\",\n kOIVth: \"xzoy561\",\n kzqmXN: \"xh8yej3\",\n kUOVxO: \"xvueqy4\",\n $$css: true\n },\n scrolled: {\n kWkggS: \"x1mjdul6\",\n kL6WhQ: \"xszdk7l\",\n kfdmCh: \"xe3zi7u\",\n kt9PQ7: \"x15anc7y\",\n $$css: true\n }\n};\n\n// One entry per size, and each names a type role rather than a figure.\n// Material Design's own tokens are `md.comp.app-bar.<size>.title.font`,\n// aliases onto the type scale rather than sizes of their own, so this maps to\n// the scale the same way and lets Text apply it.\nconst HEADLINE_VARIANT = {\n lg: 'headlineMedium',\n md: 'headlineSmall',\n sm: 'titleLarge'\n} as const;\n\n// The headline is the page's title in Material Design's model, so it is the\n// page's <h1> unless the call site says otherwise. `headingLevel` is what says\n// otherwise, and a bar drawn beside another bar — one per pane in a\n// `ListDetail` or a `SupportingPane` — or under a page heading of its own\n// should lower it.\n//\n// Built here rather than kept as a constant per level: `headline` becomes the\n// heading's children, so a call site cannot demote the heading by passing one\n// of its own. `headline={<h2>…</h2>}` renders an h2 inside the h1 — two\n// headings where one was wanted, which React does not warn about.\n//\n// The level is looked up rather than interpolated into a tag name. `h7` is a\n// custom element as far as React is concerned, so it renders without a word\n// said and leaves the outline worse than the default would have. Disclosure's\n// own `headingLevel` hands the number to React Aria, which is why that one\n// needs no equivalent.\nconst HEADINGS = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'] as const;\nfunction heading(level: number) {\n const index = Math.min(Math.max(Math.round(level), 1), HEADINGS.length) - 1;\n return createElement(HEADINGS[index]);\n}\nconst PARAGRAPH = <p />;\n\n// Height is the one value the call site does not choose, and it depends on two\n// props at once, so it is a function style rather than one key per\n// combination. StyleX writes it to a custom property inline, the same\n// mechanism Feed uses for its cell minimum.\nconst _temp = {\n kAzted: \"x1chvrdh\",\n \"$$css\": true\n};\nconst heightStyles = {\n root: (minBlockSize: string) => [_temp, {\n \"--x-minBlockSize\": (val => typeof val === \"number\" ? val + \"px\" : val != null ? val : undefined)(minBlockSize)\n }]\n};\n\n// The row's measure and inset both come from the call site, so both are\n// function styles too. Each edge is worked out on its own: where it holds a\n// slot the row stops short of the inset by GLYPH_INSET, so the glyph rather\n// than its target is what sits at the inset, and where it holds none the\n// headline itself starts there. Clamped at zero, since an inset smaller than\n// a glyph's own room would otherwise ask for a negative padding, which CSS\n// throws away whole.\nconst _temp2 = {\n ks0D6T: \"x13i5qev\",\n \"$$css\": true\n};\nconst rowStyles = {\n root: (start: string, end: string, maxInlineSize: string) => [_temp2, {\n kwRFfy: end != null ? \"x120eax6\" : end,\n kZCmMZ: start != null ? \"xnvo3vl\" : start,\n $$css: true\n }, {\n \"--x-maxInlineSize\": (val => typeof val === \"number\" ? val + \"px\" : val != null ? val : undefined)(maxInlineSize),\n \"--x-paddingInlineEnd\": (val => typeof val === \"number\" ? val + \"px\" : val != null ? val : undefined)(end),\n \"--x-paddingInlineStart\": (val => typeof val === \"number\" ? val + \"px\" : val != null ? val : undefined)(start)\n }]\n};\ntype AppBarProps = Omit<RenderComponentProps<'header'>, 'children'> & {\n /**\n * Which of Material Design's alignments the text takes. `center` is the\n * configuration that replaced the old center-aligned variant.\n * @default 'start'\n */\n align?: 'center' | 'start';\n /**\n * Collapses a flexible bar to the height and headline of the small one, for\n * a pinned bar over content that has been scrolled. Material Design\n * specifies it for the flexible sizes, and without it a pinned `lg` costs\n * 152px of the viewport for as long as the page is open.\n *\n * Controlled, and for the same reason `scrolled` is: only the app knows\n * which element scrolls, and how far into it the bar should have finished\n * collapsing. `useAppBarScroll` derives both from that element's scroll,\n * and is the way to set them unless the app needs a rule of its own.\n *\n * Ignored on `sm`, which is already the height this collapses to. The\n * subtitle goes with the height, since there is no room for a second line\n * in the small bar.\n *\n * Collapsing hands the page back the height the bar gives up, and a bar\n * whose state is read off the scroll offset can then undo itself in two\n * ways. Both move the offset back under the threshold, so the bar expands,\n * the page regains its height, and the two take turns for as long as the\n * reader stays there.\n *\n * - **Scroll anchoring.** Browsers answer a change in height above the\n * viewport by moving the offset by the same amount, to keep the content\n * in place. Give the scroll container `overflow-anchor: none`, which is\n * also the movement you want: the content follows the bar's bottom edge\n * up rather than standing still while the bar shrinks behind it.\n * - **The shorter page.** A page that overflows by less than the threshold\n * plus the height the bar gives back cannot scroll that far once the bar\n * has collapsed, so the browser pulls the offset back inside it. No\n * threshold avoids this, since the band moves with it; what does is not\n * collapsing on such a page, which is the rule `useAppBarScroll` applies.\n * @default false\n */\n collapsed?: boolean;\n /**\n * Where the bar's content starts on each edge: the headline where nothing\n * comes before it, and the leading icon's glyph where something does, with\n * the headline after the icon button's target. The trailing edge is the\n * same mirrored. Any length works, `0` included, for a bar drawn flush.\n *\n * The default is Material Design's own margin for a top app bar, the\n * spacing scale's `lg` step, which is also the margin it gives body\n * content, so a bar and the page beneath line up without either being told\n * about the other. Set it to the page's gutter where that differs.\n * @default spacing.lg\n */\n contentInset?: string;\n /**\n * How wide the bar's contents may run before they stop growing, with the\n * row centred in whatever is left. The bar's own surface still paints edge\n * to edge.\n *\n * This is what lines a full-bleed bar up with a page whose content sits in\n * a measure: give it the page's measure, and `contentInset` the page's\n * gutter. Unset, the row is as wide as the bar.\n */\n contentMaxInlineSize?: string;\n /**\n * Where the headline sits in the page's outline. A screen reader moves\n * between headings, so a bar drawn beside another bar, or under a page\n * heading of its own, should lower it.\n * @default 1\n */\n headingLevel?: number;\n /** The page's title. Wraps rather than truncating, and grows the bar with it. */\n headline?: ReactNode;\n /** Usually a back or menu icon button. Sits before the text. */\n leading?: ReactNode;\n /**\n * Whether the content beneath has been scrolled. Material Design separates\n * a bar from scrolled content with a fill colour rather than a shadow, and\n * this is what applies it.\n *\n * Controlled, with no listener of its own: only the app knows which element\n * scrolls, and a bar that watched the window would be wrong inside every\n * pane and dialog that scrolls independently.\n * @default false\n */\n scrolled?: boolean;\n /**\n * Height and headline size, as steps of the library's size scale. `sm` is\n * Material Design's small bar, a fixed 64px; `md` and `lg` are its medium\n * and large flexible bars, which hug their text.\n * @default 'sm'\n */\n size?: 'lg' | 'md' | 'sm';\n /** A second line under the headline. Makes `md` and `lg` taller. */\n subtitle?: ReactNode;\n /** Actions, at the far end. Usually icon buttons. */\n trailing?: ReactNode;\n};\n\n/**\n * Material Design's app bar: the container at the top of a page carrying its\n * title, one or two actions, and the way back out.\n *\n * Three sizes. `sm` is a fixed 64px bar for a page whose title is a label;\n * `md` and `lg` are the flexible bars, which give the headline a larger\n * type role and grow to fit a subtitle or a headline that wraps.\n *\n * It paints its own surface, unlike the layout components, because separating\n * itself from the content beneath is the job — which is also why `scrolled`\n * and `collapsed` exist. Neither watches the page: only the app knows which\n * element scrolls, so both are set from its own scroll handler.\n */\nfunction AppBar({\n align = 'start',\n collapsed = false,\n contentInset = spacing.lg,\n contentMaxInlineSize = 'none',\n headingLevel = 1,\n headline,\n leading,\n render,\n scrolled = false,\n size = 'sm',\n subtitle,\n trailing,\n ...props\n}: AppBarProps) {\n // `sm` is already what the flexible bars collapse to, so collapsing it is\n // a no-op rather than an error. A bar whose size is chosen at the call site\n // from a breakpoint would otherwise have to guard the prop as well.\n const collapse = collapsed && size !== 'sm';\n const expandedHeight = hasContent(subtitle) ? HEIGHTS[size].withSubtitle : HEIGHTS[size].plain;\n const height = collapse ? COLLAPSED_HEIGHT : expandedHeight;\n const hasLeading = hasContent(leading);\n const hasTrailing = hasContent(trailing);\n return useRender({\n defaultTagName: 'header',\n props: {\n ...props,\n children: <div {...stylex.props(styles.row, rowStyles.root(edgePadding(contentInset, hasLeading), edgePadding(contentInset, hasTrailing), contentMaxInlineSize))}>\n {!hasLeading ? null : <div className=\"x6s0dn4 x9f619 x78zum5 x2lah0s x1r8zjiw x1let9r4\">{leading}</div>}\n <div {...{\n 0: {\n className: \"x9f619 x78zum5 xdt5ytf x1iyjqo2 xkjl1po xl56j7k xeuugli xj0a0fe x1cmllll\"\n },\n 1: {\n className: \"x9f619 x78zum5 xdt5ytf x1iyjqo2 xkjl1po xl56j7k xeuugli xj0a0fe x1cmllll x2b8uid\"\n }\n }[!!(align === 'center') << 0]}>\n {!hasContent(headline) ? null : <Text className=\"x12w9bfk xioksi3 x1nxaspg x1seskgd\" render={heading(headingLevel)} variant={collapse ? HEADLINE_VARIANT.sm : HEADLINE_VARIANT[size]}>\n {headline}\n </Text>}\n {!hasContent(subtitle) || collapse ? null : <Text render={PARAGRAPH} tone=\"muted\" variant=\"bodyMedium\">\n {subtitle}\n </Text>}\n </div>\n {!hasTrailing ? null : <div className=\"x6s0dn4 x9f619 x78zum5 x2lah0s x1r8zjiw x1let9r4\">{trailing}</div>}\n </div>,\n ...mergeStyles(stylex.props(styles.root, heightStyles.root(height), scrolled && styles.scrolled), props)\n },\n render\n });\n}\n\n/**\n * The row's padding on one edge, for the inset the call site gave.\n *\n * A bare `0` is the one length CSS accepts without a unit, and the one it\n * rejects inside `max()`, where it reads as a number, so it is given its\n * unit before the arithmetic sees it.\n */\nfunction edgePadding(contentInset: string, hasSlot: boolean) {\n const inset = contentInset.trim() === '0' ? '0px' : contentInset;\n return hasSlot ? `max(0px, ${inset} - ${GLYPH_INSET})` : inset;\n}\nexport type { AppBarProps };\nexport default AppBar;"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["c","_c","ReactNode","stylex","createElement","RenderComponentProps","COLLAPSED_BLOCK_SIZE","hasContent","useRender","layers","mergeStyles","colors","motion","sizing","spacing","Text","ICON_BUTTON_TARGET","ICON_SIZE","GLYPH_INSET","HEIGHTS","lg","plain","withSubtitle","md","sm","const","COLLAPSED_HEIGHT","FORCED_COLORS","styles","pinned","k87sOh","kVAEAm","kY2c9j","$$css","root","k6CgDc","kGNEyG","kWkggS","kB7OPa","k1xSpc","kjj79g","kIyJzY","k1ekBW","kAMwcw","row","kOIVth","kzqmXN","kUOVxO","scrolled","kL6WhQ","kfdmCh","kt9PQ7","HEADLINE_VARIANT","HEADINGS","heading","level","index","Math","min","max","round","length","PARAGRAPH","_temp","kAzted","heightStyles","minBlockSize","val","undefined","_temp2","ks0D6T","rowStyles","start","end","maxInlineSize","kwRFfy","kZCmMZ","AppBarProps","Omit","align","collapsed","contentInset","contentMaxInlineSize","headingLevel","headline","leading","size","subtitle","trailing","AppBar","t0","$","render","t1","t2","t3","t4","t5","t6","t7","t8","t9","t10","t11","t12","t13","t14","props","collapse","expandedHeight","height","hasLeading","hasTrailing","t15","edgePadding","t16","t17","Symbol","for","0","className","1","t18","t19","t20","t21","t22","children","defaultTagName","hasSlot","inset","trim","_c","props","stylex.props"],"sources":["../../../src/components/app-bar/index.tsx"],"sourcesContent":["'use client';\n\nimport type { ReactNode } from 'react';\nimport * as stylex from '@stylexjs/stylex';\nimport { createElement } from 'react';\nimport type { RenderComponentProps } from '../../render/useRender';\nimport { COLLAPSED_BLOCK_SIZE } from '../../hooks/useAppBarScroll';\nimport { hasContent } from '../../render/content';\nimport { useRender } from '../../render/useRender';\nimport '../../styles/layers.stylex';\nimport { layers } from '../../styles/layers.stylex';\nimport { mergeStyles } from '../../styles/merge';\nimport '../../tokens/design.tokens.stylex';\nimport { colors, motion, sizing, spacing } from '../../tokens/design.tokens.stylex';\nimport Text from '../text';\n\n// Material Design's app bar, in the three sizes the spec recommends.\n//\n// `md` and `lg` are Material Design's medium and large *flexible* bars, the\n// newer of the two sets the spec gives and the one it recommends, which is why\n// those two steps are theirs.\n//\n// Material Design also merged the old center-aligned variant into small as a\n// configuration rather than a variant, which is why alignment is a prop here\n// and applies to every size.\n//\n// Heights are Material Design's, and they are minimums rather than fixed. The\n// spec says the flexible bars \"hug the text contents\" and gives them multi-line\n// support and text wrapping, so a headline long enough to wrap has to be able\n// to make its bar taller. Fixing the height would truncate exactly the case\n// the variant was redesigned for.\n\n// The geometry Material Design lays a bar's icon buttons out on. Its tokens\n// give a 4dp leading and trailing space between the bar's edge and the first\n// button's 48dp target, no space between one target and the next, and a 24dp\n// icon centred in each — so a glyph lands 4 + 12 = 16dp in, on the page's own\n// margin.\n//\n// The library's icon button draws a 40dp box with its 48dp target out of\n// flow, so a slot pads half the difference either side and puts the whole\n// difference between two buttons, which lays the targets edge to edge as the\n// tokens do. The target is IconButton's TARGET_SIZE, a literal there for the\n// reason it gives: it is a floor the page states, not a step of the control\n// scale.\nconst ICON_BUTTON_TARGET = '48px';\nconst ICON_SIZE = '24px';\n\n// How far an icon sits inside its target, which is how much less than the\n// content inset the row is padded on an edge that holds a slot. That is what\n// puts a leading glyph, rather than the edge of its target, at the inset.\nconst GLYPH_INSET = `(${ICON_BUTTON_TARGET} - ${ICON_SIZE}) / 2`;\nconst HEIGHTS = {\n lg: {\n plain: '120px',\n withSubtitle: '152px'\n },\n md: {\n plain: '112px',\n withSubtitle: '136px'\n },\n sm: {\n plain: `${COLLAPSED_BLOCK_SIZE}px`,\n withSubtitle: `${COLLAPSED_BLOCK_SIZE}px`\n }\n} as const;\n\n// What a flexible bar collapses to, which is the small bar exactly. Material\n// Design does not describe the collapsed large bar as a state of its own — it\n// describes it as becoming the small bar, which is why this reads off the same\n// table rather than being a fourth height.\nconst COLLAPSED_HEIGHT = HEIGHTS.sm.plain;\n\n// Windows High Contrast and the rest of the forced-colours modes. Spelled\n// here rather than imported, for the reason src/field/styles.ts records: the\n// StyleX compiler resolves a constant across files only out of a `.stylex.ts`\n// module, and the generated one holds design tokens rather than queries.\nconst FORCED_COLORS = '@media (forced-colors: active)';\nconst styles = {\n pinned: {\n k87sOh: \"x13vifvy\",\n kVAEAm: \"x7wzq59\",\n kY2c9j: \"xfj7q76\",\n $$css: true\n },\n root: {\n k6CgDc: \"x12w9bfk\",\n kGNEyG: \"x6s0dn4\",\n kWkggS: \"x14s9m32\",\n kB7OPa: \"x9f619\",\n k1xSpc: \"x78zum5\",\n kjj79g: \"xl56j7k\",\n kIyJzY: \"xioksi3\",\n k1ekBW: \"x8u3r54\",\n kAMwcw: \"x1seskgd\",\n $$css: true\n },\n row: {\n kGNEyG: \"x6s0dn4\",\n kB7OPa: \"x9f619\",\n k1xSpc: \"x78zum5\",\n kOIVth: \"xzoy561\",\n kzqmXN: \"xh8yej3\",\n kUOVxO: \"xvueqy4\",\n $$css: true\n },\n scrolled: {\n kWkggS: \"x1mjdul6\",\n kL6WhQ: \"xszdk7l\",\n kfdmCh: \"xe3zi7u\",\n kt9PQ7: \"x15anc7y\",\n $$css: true\n }\n};\n\n// One entry per size, and each names a type role rather than a figure.\n// Material Design's own tokens are `md.comp.app-bar.<size>.title.font`,\n// aliases onto the type scale rather than sizes of their own, so this maps to\n// the scale the same way and lets Text apply it.\nconst HEADLINE_VARIANT = {\n lg: 'headlineMedium',\n md: 'headlineSmall',\n sm: 'titleLarge'\n} as const;\n\n// The headline is the page's title in Material Design's model, so it is the\n// page's <h1> unless the call site says otherwise. `headingLevel` is what says\n// otherwise, and a bar drawn beside another bar — one per pane in a\n// `ListDetail` or a `SupportingPane` — or under a page heading of its own\n// should lower it.\n//\n// Built here rather than kept as a constant per level: `headline` becomes the\n// heading's children, so a call site cannot demote the heading by passing one\n// of its own. `headline={<h2>…</h2>}` renders an h2 inside the h1 — two\n// headings where one was wanted, which React does not warn about.\n//\n// The level is looked up rather than interpolated into a tag name. `h7` is a\n// custom element as far as React is concerned, so it renders without a word\n// said and leaves the outline worse than the default would have. Disclosure's\n// own `headingLevel` hands the number to React Aria, which is why that one\n// needs no equivalent.\nconst HEADINGS = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'] as const;\nfunction heading(level: number) {\n const index = Math.min(Math.max(Math.round(level), 1), HEADINGS.length) - 1;\n return createElement(HEADINGS[index]);\n}\nconst PARAGRAPH = <p />;\n\n// Height is the one value the call site does not choose, and it depends on two\n// props at once, so it is a function style rather than one key per\n// combination. StyleX writes it to a custom property inline, the same\n// mechanism Feed uses for its cell minimum.\nconst _temp = {\n kAzted: \"x1chvrdh\",\n \"$$css\": true\n};\nconst heightStyles = {\n root: (minBlockSize: string) => [_temp, {\n \"--x-minBlockSize\": (val => typeof val === \"number\" ? val + \"px\" : val != null ? val : undefined)(minBlockSize)\n }]\n};\n\n// The row's measure and inset both come from the call site, so both are\n// function styles too. Each edge is worked out on its own: where it holds a\n// slot the row stops short of the inset by GLYPH_INSET, so the glyph rather\n// than its target is what sits at the inset, and where it holds none the\n// headline itself starts there. Clamped at zero, since an inset smaller than\n// a glyph's own room would otherwise ask for a negative padding, which CSS\n// throws away whole.\nconst _temp2 = {\n ks0D6T: \"x13i5qev\",\n \"$$css\": true\n};\nconst rowStyles = {\n root: (start: string, end: string, maxInlineSize: string) => [_temp2, {\n kwRFfy: end != null ? \"x120eax6\" : end,\n kZCmMZ: start != null ? \"xnvo3vl\" : start,\n $$css: true\n }, {\n \"--x-maxInlineSize\": (val => typeof val === \"number\" ? val + \"px\" : val != null ? val : undefined)(maxInlineSize),\n \"--x-paddingInlineEnd\": (val => typeof val === \"number\" ? val + \"px\" : val != null ? val : undefined)(end),\n \"--x-paddingInlineStart\": (val => typeof val === \"number\" ? val + \"px\" : val != null ? val : undefined)(start)\n }]\n};\ntype AppBarProps = Omit<RenderComponentProps<'header'>, 'children'> & {\n /**\n * Which of Material Design's alignments the text takes. `center` is the\n * configuration that replaced the old center-aligned variant.\n * @default 'start'\n */\n align?: 'center' | 'start';\n /**\n * Collapses a flexible bar to the height and headline of the small one, for\n * a bar `pinned` over content that has been scrolled. Material Design\n * specifies it for the flexible sizes, and without it a pinned `lg` costs\n * 152px of the viewport for as long as the page is open.\n *\n * Controlled, and for the same reason `scrolled` is: only the app knows\n * which element scrolls, and how far into it the bar should have finished\n * collapsing. `useAppBarScroll` derives both from that element's scroll,\n * and is the way to set them unless the app needs a rule of its own.\n *\n * Ignored on `sm`, which is already the height this collapses to. The\n * subtitle goes with the height, since there is no room for a second line\n * in the small bar.\n *\n * Collapsing hands the page back the height the bar gives up, and a bar\n * whose state is read off the scroll offset can then undo itself in two\n * ways. Both move the offset back under the threshold, so the bar expands,\n * the page regains its height, and the two take turns for as long as the\n * reader stays there.\n *\n * - **Scroll anchoring.** Browsers answer a change in height above the\n * viewport by moving the offset by the same amount, to keep the content\n * in place. Give the scroll container `overflow-anchor: none`, which is\n * also the movement you want: the content follows the bar's bottom edge\n * up rather than standing still while the bar shrinks behind it.\n * - **The shorter page.** A page that overflows by less than the threshold\n * plus the height the bar gives back cannot scroll that far once the bar\n * has collapsed, so the browser pulls the offset back inside it. No\n * threshold avoids this, since the band moves with it; what does is not\n * collapsing on such a page, which is the rule `useAppBarScroll` applies.\n * @default false\n */\n collapsed?: boolean;\n /**\n * Where the bar's content starts on each edge: the headline where nothing\n * comes before it, and the leading icon's glyph where something does, with\n * the headline after the icon button's target. The trailing edge is the\n * same mirrored. Any length works, `0` included, for a bar drawn flush.\n *\n * The default is Material Design's own margin for a top app bar, the\n * spacing scale's `lg` step, which is also the margin it gives body\n * content, so a bar and the page beneath line up without either being told\n * about the other. Set it to the page's gutter where that differs.\n * @default spacing.lg\n */\n contentInset?: string;\n /**\n * How wide the bar's contents may run before they stop growing, with the\n * row centred in whatever is left. The bar's own surface still paints edge\n * to edge.\n *\n * This is what lines a full-bleed bar up with a page whose content sits in\n * a measure: give it the page's measure, and `contentInset` the page's\n * gutter. Unset, the row is as wide as the bar.\n */\n contentMaxInlineSize?: string;\n /**\n * Where the headline sits in the page's outline. A screen reader moves\n * between headings, so a bar drawn beside another bar, or under a page\n * heading of its own, should lower it.\n * @default 1\n */\n headingLevel?: number;\n /** The page's title. Wraps rather than truncating, and grows the bar with it. */\n headline?: ReactNode;\n /** Usually a back or menu icon button. Sits before the text. */\n leading?: ReactNode;\n /**\n * Holds the bar at the top of its scroll container while the content\n * scrolls beneath it, and keeps it painted over that content. The bar\n * still needs a scrolling ancestor to stick inside: the window, or an\n * element with its own overflow. A pinned bar is the one `collapsed` and\n * `scrolled` are for.\n * @default false\n */\n pinned?: boolean;\n /**\n * Whether the content beneath has been scrolled. Material Design separates\n * a bar from scrolled content with a fill colour rather than a shadow, and\n * this is what applies it.\n *\n * Controlled, with no listener of its own: only the app knows which element\n * scrolls, and a bar that watched the window would be wrong inside every\n * pane and dialog that scrolls independently.\n * @default false\n */\n scrolled?: boolean;\n /**\n * Height and headline size, as steps of the library's size scale. `sm` is\n * Material Design's small bar, a fixed 64px; `md` and `lg` are its medium\n * and large flexible bars, which hug their text.\n * @default 'sm'\n */\n size?: 'lg' | 'md' | 'sm';\n /** A second line under the headline. Makes `md` and `lg` taller. */\n subtitle?: ReactNode;\n /** Actions, at the far end. Usually icon buttons. */\n trailing?: ReactNode;\n};\n\n/**\n * Material Design's app bar: the container at the top of a page carrying its\n * title, one or two actions, and the way back out.\n *\n * Three sizes. `sm` is a fixed 64px bar for a page whose title is a label;\n * `md` and `lg` are the flexible bars, which give the headline a larger\n * type role and grow to fit a subtitle or a headline that wraps.\n *\n * It paints its own surface, unlike the layout components, because separating\n * itself from the content beneath is the job — which is also why `scrolled`\n * and `collapsed` exist. Neither watches the page: only the app knows which\n * element scrolls, so both are set from its own scroll handler.\n */\nfunction AppBar({\n align = 'start',\n collapsed = false,\n contentInset = spacing.lg,\n contentMaxInlineSize = 'none',\n headingLevel = 1,\n headline,\n leading,\n pinned = false,\n render,\n scrolled = false,\n size = 'sm',\n subtitle,\n trailing,\n ...props\n}: AppBarProps) {\n // `sm` is already what the flexible bars collapse to, so collapsing it is\n // a no-op rather than an error. A bar whose size is chosen at the call site\n // from a breakpoint would otherwise have to guard the prop as well.\n const collapse = collapsed && size !== 'sm';\n const expandedHeight = hasContent(subtitle) ? HEIGHTS[size].withSubtitle : HEIGHTS[size].plain;\n const height = collapse ? COLLAPSED_HEIGHT : expandedHeight;\n const hasLeading = hasContent(leading);\n const hasTrailing = hasContent(trailing);\n return useRender({\n defaultTagName: 'header',\n props: {\n ...props,\n children: <div {...stylex.props(styles.row, rowStyles.root(edgePadding(contentInset, hasLeading), edgePadding(contentInset, hasTrailing), contentMaxInlineSize))}>\n {!hasLeading ? null : <div className=\"x6s0dn4 x9f619 x78zum5 x2lah0s x1r8zjiw x1let9r4\">{leading}</div>}\n <div {...{\n 0: {\n className: \"x9f619 x78zum5 xdt5ytf x1iyjqo2 xkjl1po xl56j7k xeuugli xj0a0fe x1cmllll\"\n },\n 1: {\n className: \"x9f619 x78zum5 xdt5ytf x1iyjqo2 xkjl1po xl56j7k xeuugli xj0a0fe x1cmllll x2b8uid\"\n }\n }[!!(align === 'center') << 0]}>\n {!hasContent(headline) ? null : <Text className=\"x12w9bfk xioksi3 x1nxaspg x1seskgd\" render={heading(headingLevel)} variant={collapse ? HEADLINE_VARIANT.sm : HEADLINE_VARIANT[size]}>\n {headline}\n </Text>}\n {!hasContent(subtitle) || collapse ? null : <Text render={PARAGRAPH} tone=\"muted\" variant=\"bodyMedium\">\n {subtitle}\n </Text>}\n </div>\n {!hasTrailing ? null : <div className=\"x6s0dn4 x9f619 x78zum5 x2lah0s x1r8zjiw x1let9r4\">{trailing}</div>}\n </div>,\n ...mergeStyles(stylex.props(styles.root, heightStyles.root(height), scrolled && styles.scrolled, pinned && styles.pinned), props)\n },\n render\n });\n}\n\n/**\n * The row's padding on one edge, for the inset the call site gave.\n *\n * A bare `0` is the one length CSS accepts without a unit, and the one it\n * rejects inside `max()`, where it reads as a number, so it is given its\n * unit before the arithmetic sees it.\n */\nfunction edgePadding(contentInset: string, hasSlot: boolean) {\n const inset = contentInset.trim() === '0' ? '0px' : contentInset;\n return hasSlot ? `max(0px, ${inset} - ${GLYPH_INSET})` : inset;\n}\nexport type { AppBarProps };\nexport default AppBar;"],"mappings":"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"}
@@ -5,6 +5,13 @@ type AvatarProps = Omit<RenderComponentProps<'span'>, 'children'> & {
5
5
  * The person this represents. Supplies both the initials and the accessible
6
6
  * name, so a screen reader announces who it is rather than reading two
7
7
  * letters aloud.
8
+ *
9
+ * A display name, as a reader would see it written: the initials are its
10
+ * first and last words. A title before the name ("Dr."), a generational
11
+ * suffix after it ("Jr.", "III") and an aside in brackets at its end
12
+ * ("(she/her)") are passed over, as is punctuation a word opens with. A
13
+ * name written without spaces between its words, as Japanese and Chinese
14
+ * names are, is one word, and takes one initial.
8
15
  */
9
16
  name: string;
10
17
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["c","_c","RenderComponentProps","Mark","AvatarProps","Omit","name","size","src","tone","Avatar","t0","$","props","t1","t2","undefined","t3","_c"],"sources":["../../../src/components/avatar/index.tsx"],"sourcesContent":["'use client'\n\nimport type { RenderComponentProps } from '../../render/useRender'\n\nimport Mark from '../../mark'\n\n// A person, drawn as a circle with the photo cropped to fill it. The box, the\n// sizes, the tones, the photo's loading and the labelling are the mark's in\n// `src/mark`, which ProductIcon draws a thing through as well, so a person\n// and a thing fill the same slot.\n//\n// Which tone a given person gets is the consuming app's decision — the design\n// cycles colours per person, and that cycle belongs where the list of people\n// is, not in this component.\n\ntype AvatarProps = Omit<RenderComponentProps<'span'>, 'children'> & {\n /**\n * The person this represents. Supplies both the initials and the accessible\n * name, so a screen reader announces who it is rather than reading two\n * letters aloud.\n */\n name: string\n /**\n * Diameter: `sm` 36px, `md` 40px, `lg` 56px.\n * @default 'md'\n */\n size?: 'lg' | 'md' | 'sm'\n /**\n * A photo to show in place of the initials. The initials stay until it has\n * loaded, and come back if it fails.\n */\n src?: string\n /**\n * Which container/on-container colour pair to tint with.\n * @default 'primary'\n */\n tone?: 'negative' | 'positive' | 'primary' | 'secondary' | 'tertiary'\n}\n\n/**\n * A person, as a circle holding their photo or, until it loads or when there\n * is none, their initials. `name` is both where the initials come from and\n * what a screen reader announces, so it is required even with a photo.\n *\n * ```tsx\n * <Avatar name=\"Ada Lovelace\" src={photo} size=\"lg\" />\n * ```\n *\n * Reach for ProductIcon when what is drawn is not a person; the two share\n * their sizes, so either fills the same slot in a row or a card.\n *\n * The call site's `className` and `style` land on the circle.\n */\nfunction Avatar({ size = 'md', tone = 'primary', ...props }: AvatarProps) {\n return <Mark {...props} kind=\"person\" size={size} tone={tone} />\n}\n\nexport type { AvatarProps }\n\nexport default Avatar\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAqDA,SAAAU,OAAAC,IAAA;CAAA,MAAAC,IAAAX,EAAA,CAAA;CAAA,IAAAY;CAAA,IAAAC;CAAA,IAAAC;CAAA,IAAAH,EAAA,OAAAD,IAAA;EAAgB,CAAA,CAAAJ,MAAAO,IAAAL,MAAAM,IAAA,GAAAF,SAAAF;EAAwDC,EAAA,KAAAD;EAAAC,EAAA,KAAAC;EAAAD,EAAA,KAAAE;EAAAF,EAAA,KAAAG;CAAA,OAAA;EAAAF,QAAAD,EAAA;EAAAE,KAAAF,EAAA;EAAAG,KAAAH,EAAA;CAAA;CAAtD,MAAAL,OAAAO,OAAAE,KAAAA,IAAA,OAAAF;CAAa,MAAAL,OAAAM,OAAAC,KAAAA,IAAA,YAAAD;CAAgB,IAAAE;CAAA,IAAAL,EAAA,OAAAC,SAAAD,EAAA,OAAAL,QAAAK,EAAA,OAAAH,MAAA;EACtCQ,KAAA,oBAAC,MAAD;GAAK,GAAKJ;GAAY,MAAA;GAAeN;GAAYE;EAAI,CAAA;EAAIG,EAAA,KAAAC;EAAAD,EAAA,KAAAL;EAAAK,EAAA,KAAAH;EAAAG,EAAA,KAAAK;CAAA,OAAAA,KAAAL,EAAA;CAAA,OAAzDK;AAAyD"}
1
+ {"version":3,"file":"index.js","names":["c","_c","RenderComponentProps","Mark","AvatarProps","Omit","name","size","src","tone","Avatar","t0","$","props","t1","t2","undefined","t3","_c"],"sources":["../../../src/components/avatar/index.tsx"],"sourcesContent":["'use client'\n\nimport type { RenderComponentProps } from '../../render/useRender'\n\nimport Mark from '../../mark'\n\n// A person, drawn as a circle with the photo cropped to fill it. The box, the\n// sizes, the tones, the photo's loading and the labelling are the mark's in\n// `src/mark`, which ProductIcon draws a thing through as well, so a person\n// and a thing fill the same slot.\n//\n// Which tone a given person gets is the consuming app's decision — the design\n// cycles colours per person, and that cycle belongs where the list of people\n// is, not in this component.\n\ntype AvatarProps = Omit<RenderComponentProps<'span'>, 'children'> & {\n /**\n * The person this represents. Supplies both the initials and the accessible\n * name, so a screen reader announces who it is rather than reading two\n * letters aloud.\n *\n * A display name, as a reader would see it written: the initials are its\n * first and last words. A title before the name (\"Dr.\"), a generational\n * suffix after it (\"Jr.\", \"III\") and an aside in brackets at its end\n * (\"(she/her)\") are passed over, as is punctuation a word opens with. A\n * name written without spaces between its words, as Japanese and Chinese\n * names are, is one word, and takes one initial.\n */\n name: string\n /**\n * Diameter: `sm` 36px, `md` 40px, `lg` 56px.\n * @default 'md'\n */\n size?: 'lg' | 'md' | 'sm'\n /**\n * A photo to show in place of the initials. The initials stay until it has\n * loaded, and come back if it fails.\n */\n src?: string\n /**\n * Which container/on-container colour pair to tint with.\n * @default 'primary'\n */\n tone?: 'negative' | 'positive' | 'primary' | 'secondary' | 'tertiary'\n}\n\n/**\n * A person, as a circle holding their photo or, until it loads or when there\n * is none, their initials. `name` is both where the initials come from and\n * what a screen reader announces, so it is required even with a photo.\n *\n * ```tsx\n * <Avatar name=\"Ada Lovelace\" src={photo} size=\"lg\" />\n * ```\n *\n * Reach for ProductIcon when what is drawn is not a person; the two share\n * their sizes, so either fills the same slot in a row or a card.\n *\n * The call site's `className` and `style` land on the circle.\n */\nfunction Avatar({ size = 'md', tone = 'primary', ...props }: AvatarProps) {\n return <Mark {...props} kind=\"person\" size={size} tone={tone} />\n}\n\nexport type { AvatarProps }\n\nexport default Avatar\n"],"mappings":";;;;;;;;;;;;;;;;;;;AA4DA,SAAAU,OAAAC,IAAA;CAAA,MAAAC,IAAAX,EAAA,CAAA;CAAA,IAAAY;CAAA,IAAAC;CAAA,IAAAC;CAAA,IAAAH,EAAA,OAAAD,IAAA;EAAgB,CAAA,CAAAJ,MAAAO,IAAAL,MAAAM,IAAA,GAAAF,SAAAF;EAAwDC,EAAA,KAAAD;EAAAC,EAAA,KAAAC;EAAAD,EAAA,KAAAE;EAAAF,EAAA,KAAAG;CAAA,OAAA;EAAAF,QAAAD,EAAA;EAAAE,KAAAF,EAAA;EAAAG,KAAAH,EAAA;CAAA;CAAtD,MAAAL,OAAAO,OAAAE,KAAAA,IAAA,OAAAF;CAAa,MAAAL,OAAAM,OAAAC,KAAAA,IAAA,YAAAD;CAAgB,IAAAE;CAAA,IAAAL,EAAA,OAAAC,SAAAD,EAAA,OAAAL,QAAAK,EAAA,OAAAH,MAAA;EACtCQ,KAAA,oBAAC,MAAD;GAAK,GAAKJ;GAAY,MAAA;GAAeN;GAAYE;EAAI,CAAA;EAAIG,EAAA,KAAAC;EAAAD,EAAA,KAAAL;EAAAK,EAAA,KAAAH;EAAAG,EAAA,KAAAK;CAAA,OAAAA,KAAAL,EAAA;CAAA,OAAzDK;AAAyD"}
@@ -9,6 +9,10 @@ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
9
9
  import { useLocale } from "react-aria-components";
10
10
  //#region src/components/badge/index.tsx
11
11
  const styles = {
12
+ count: {
13
+ kgeoSG: "xvss7es",
14
+ $$css: true
15
+ },
12
16
  inFlow: {
13
17
  kVAEAm: "x1uhb9sk",
14
18
  $$css: true
@@ -91,7 +95,7 @@ function Badge(t0) {
91
95
  const t4 = mergeStyles({ className: "x9f619 x3nfvp2 x1n2onr6" }, props$1);
92
96
  let t5;
93
97
  if ($[4] !== children || $[5] !== label || $[6] !== placed) {
94
- t5 = props(styles.mark, label === void 0 ? styles.small : styles.large, (children === void 0 || children === null) && styles.inFlow, label !== void 0 && placed);
98
+ t5 = props(styles.mark, label === void 0 ? styles.small : [styles.large, styles.count], (children === void 0 || children === null) && styles.inFlow, label !== void 0 && placed);
95
99
  $[4] = children;
96
100
  $[5] = label;
97
101
  $[6] = placed;
@@ -101,8 +105,8 @@ function Badge(t0) {
101
105
  if ($[8] !== label || $[9] !== t5) {
102
106
  t6 = /* @__PURE__ */ jsx("span", {
103
107
  "aria-hidden": "true",
104
- ...t5,
105
- children: label
108
+ "data-count": label,
109
+ ...t5
106
110
  });
107
111
  $[8] = label;
108
112
  $[9] = t5;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["c","_c","stylex","useContext","useLocale","RenderComponentProps","BadgeMarkContext","useRender","mergeStyles","colors","radii","spacing","typography","FORCED_COLORS","styles","inFlow","kVAEAm","$$css","large","kGNEyG","kZKoxP","kMwMTN","k1xSpc","kMv6JI","kGuDYH","kcqcaj","k63SB2","k87sOh","kLqNvP","kjj79g","kb6lSQ","kLWn49","k7Eaqz","kg3NbH","khDVqt","mark","kWkggS","kVAM5u","kaIpWk","ksu8eU","kMzoRj","kB7OPa","kfzvcC","small","kzqmXN","kt4wiu","BadgeProps","count","max","Badge","t0","$","children","t1","render","props","undefined","locale","placed","t2","numbers","Intl","NumberFormat","format","label","t3","t4","className","t5","t6","t7","t8","t9","defaultTagName","_c","props","stylex.props"],"sources":["../../../src/components/badge/index.tsx"],"sourcesContent":["'use client';\n\nimport * as stylex from '@stylexjs/stylex';\nimport { useContext } from 'react';\nimport { useLocale } from 'react-aria-components';\nimport type { RenderComponentProps } from '../../render/useRender';\nimport { BadgeMarkContext } from '../../badge';\nimport { useRender } from '../../render/useRender';\nimport { mergeStyles } from '../../styles/merge';\nimport '../../tokens/design.tokens.stylex';\nimport { colors, radii, spacing, typography } from '../../tokens/design.tokens.stylex';\n\n// The badges page's badge: a mark on the corner of an icon that flags\n// something new there, either as the 6dp small badge or as the 16dp large\n// badge holding a count. Both are the error pair — the error role, with the\n// count in on error — on a full corner, and the count is label small, capped\n// at four characters with a plus, as \"999+\".\n//\n// The badge wraps what it is drawn on, usually an icon, and places the mark\n// against that element's box, which is what the page measures from. The\n// small badge fills the icon's top trailing 6dp square. The large badge's\n// bottom leading corner sits 14dp down and 12dp in from the icon's top\n// trailing corner, so it stands 2dp above the icon and grows toward the end\n// as its count lengthens, to the page's 34dp at \"999+\". Both are logical\n// insets, so the mark stays on the trailing corner under right-to-left.\n//\n// Given nothing to wrap, the badge is the mark alone, standing in the line\n// rather than over a corner. That is the form the tabs page draws after a\n// label with no icon above it.\n//\n// The mark is hidden from assistive technology. A count read on its own is a\n// number with no subject; it belongs in the name of the control it sits on,\n// where a reader meets it with what it counts — \"Notifications, 3 new\" — and\n// the stories show it there.\n//\n// Under forced colours the error fill is painted over in the mode's\n// background, which left the small badge as nothing at all. It takes a 1px\n// border there instead, which the mode keeps and paints in its text colour.\n\n// Windows High Contrast and the rest of the forced-colours modes. Spelled\n// here rather than imported, for the reason src/field/styles.ts records: the\n// StyleX compiler resolves a constant across files only out of a `.stylex.ts`\n// module, and the generated one holds design tokens rather than queries.\nconst FORCED_COLORS = '@media (forced-colors: active)';\nconst styles = {\n inFlow: {\n kVAEAm: \"x1uhb9sk\",\n $$css: true\n },\n large: {\n kGNEyG: \"x6s0dn4\",\n kZKoxP: \"xlup9mm\",\n kMwMTN: \"x1l7c2jh\",\n k1xSpc: \"x78zum5\",\n kMv6JI: \"xs1w0rn\",\n kGuDYH: \"x1n35her\",\n kcqcaj: \"xss6m8b\",\n k63SB2: \"x1su64ma\",\n k87sOh: \"x1qiirwl\",\n kLqNvP: \"xty0069\",\n kjj79g: \"xl56j7k\",\n kb6lSQ: \"xdlnduh\",\n kLWn49: \"xaomhve\",\n k7Eaqz: \"x15kz4h8\",\n kg3NbH: \"ximhkdq\",\n khDVqt: \"xuxw1ft\",\n $$css: true\n },\n mark: {\n kWkggS: \"xwi4nbo\",\n kVAM5u: \"x1w1tqly\",\n kaIpWk: \"x1dkaolv\",\n ksu8eU: \"xx61lck\",\n kMzoRj: \"x13rsnn2\",\n kB7OPa: \"x9f619\",\n kfzvcC: \"x47corl\",\n kVAEAm: \"x10l6tqk\",\n $$css: true\n },\n small: {\n kZKoxP: \"xols6we\",\n kzqmXN: \"x1v4s8kt\",\n k87sOh: \"x13vifvy\",\n kt4wiu: \"xtijo5x\",\n $$css: true\n }\n};\ntype BadgeProps = RenderComponentProps<'span'> & {\n /**\n * The number to show, which draws the page's large badge. Left out, the\n * badge is the small 6dp dot, which flags without counting. A count of 0\n * still draws, so leave the badge out when there is nothing to count.\n */\n count?: number;\n /**\n * The largest count drawn as itself. Above it the badge reads `max` and a\n * plus, which is the page's 999+ at the default.\n * @default 999\n */\n max?: number;\n};\n\n/**\n * A badge on the corner of what it wraps, usually an icon: the small dot,\n * or with `count` the large badge holding a number. The mark is hidden from\n * assistive technology, so put what it says in the name of the control it\n * sits on.\n *\n * ```tsx\n * <IconButton aria-label=\"Notifications, 3 new\">\n * <Badge count={3}>\n * <BellIcon />\n * </Badge>\n * </IconButton>\n * ```\n *\n * Given no children, the mark stands alone in the line, as a tab draws it\n * after its label.\n *\n * The call site's `className` and `style` land on the element wrapping what\n * the badge is drawn on.\n */\nfunction Badge({\n children,\n count,\n max = 999,\n render,\n ...props\n}: BadgeProps) {\n const {\n locale\n } = useLocale();\n const placed = useContext(BadgeMarkContext);\n const numbers = new Intl.NumberFormat(locale);\n const label = count === undefined ? undefined : count > max ? `${numbers.format(max)}+` : numbers.format(count);\n return useRender({\n defaultTagName: 'span',\n props: {\n ...props,\n ...mergeStyles({\n className: \"x9f619 x3nfvp2 x1n2onr6\"\n }, props),\n children: <>\n {children}\n <span aria-hidden=\"true\" {...stylex.props(styles.mark, label === undefined ? styles.small : styles.large, (children === undefined || children === null) && styles.inFlow,\n // What a destination drawing it asks of a count's mark — see\n // src/badge. The small mark stays inside its icon's box, so\n // nothing has to make room for it.\n label !== undefined && placed)}>\n {label}\n </span>\n </>\n },\n render\n });\n}\nexport type { BadgeProps };\nexport default Badge;"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["c","_c","stylex","useContext","useLocale","RenderComponentProps","BadgeMarkContext","useRender","mergeStyles","colors","radii","spacing","typography","FORCED_COLORS","styles","count","kgeoSG","$$css","inFlow","kVAEAm","large","kGNEyG","kZKoxP","kMwMTN","k1xSpc","kMv6JI","kGuDYH","kcqcaj","k63SB2","k87sOh","kLqNvP","kjj79g","kb6lSQ","kLWn49","k7Eaqz","kg3NbH","khDVqt","mark","kWkggS","kVAM5u","kaIpWk","ksu8eU","kMzoRj","kB7OPa","kfzvcC","small","kzqmXN","kt4wiu","BadgeProps","max","Badge","t0","$","children","t1","render","props","undefined","locale","placed","t2","numbers","Intl","NumberFormat","format","label","t3","t4","className","t5","t6","t7","t8","t9","defaultTagName","_c","props","stylex.props"],"sources":["../../../src/components/badge/index.tsx"],"sourcesContent":["'use client';\n\nimport * as stylex from '@stylexjs/stylex';\nimport { useContext } from 'react';\nimport { useLocale } from 'react-aria-components';\nimport type { RenderComponentProps } from '../../render/useRender';\nimport { BadgeMarkContext } from '../../badge';\nimport { useRender } from '../../render/useRender';\nimport { mergeStyles } from '../../styles/merge';\nimport '../../tokens/design.tokens.stylex';\nimport { colors, radii, spacing, typography } from '../../tokens/design.tokens.stylex';\n\n// The badges page's badge: a mark on the corner of an icon that flags\n// something new there, either as the 6dp small badge or as the 16dp large\n// badge holding a count. Both are the error pair — the error role, with the\n// count in on error — on a full corner, and the count is label small, capped\n// at four characters with a plus, as \"999+\".\n//\n// The badge wraps what it is drawn on, usually an icon, and places the mark\n// against that element's box, which is what the page measures from. The\n// small badge fills the icon's top trailing 6dp square. The large badge's\n// bottom leading corner sits 14dp down and 12dp in from the icon's top\n// trailing corner, so it stands 2dp above the icon and grows toward the end\n// as its count lengthens, to the page's 34dp at \"999+\". Both are logical\n// insets, so the mark stays on the trailing corner under right-to-left.\n//\n// Given nothing to wrap, the badge is the mark alone, standing in the line\n// rather than over a corner. That is the form the tabs page draws after a\n// label with no icon above it.\n//\n// The mark is hidden from assistive technology. A count read on its own is a\n// number with no subject; it belongs in the name of the control it sits on,\n// where a reader meets it with what it counts — \"Notifications, 3 new\" — and\n// the stories show it there.\n//\n// The count is drawn as the mark's generated content rather than written as\n// its text, so it is no part of the text of what it sits on. Written as text\n// it was, hidden or not: a destination labelled \"Second item\" with a count of\n// 3 read \"3Second item\", which is no name a speech-input user could say and\n// which axe's label-in-name check fails against the name \"Second item, 3 new\"\n// the library recommends. It also ran into anything that copied the\n// control's text.\n//\n// Under forced colours the error fill is painted over in the mode's\n// background, which left the small badge as nothing at all. It takes a 1px\n// border there instead, which the mode keeps and paints in its text colour.\n\n// Windows High Contrast and the rest of the forced-colours modes. Spelled\n// here rather than imported, for the reason src/field/styles.ts records: the\n// StyleX compiler resolves a constant across files only out of a `.stylex.ts`\n// module, and the generated one holds design tokens rather than queries.\nconst FORCED_COLORS = '@media (forced-colors: active)';\nconst styles = {\n count: {\n kgeoSG: \"xvss7es\",\n $$css: true\n },\n inFlow: {\n kVAEAm: \"x1uhb9sk\",\n $$css: true\n },\n large: {\n kGNEyG: \"x6s0dn4\",\n kZKoxP: \"xlup9mm\",\n kMwMTN: \"x1l7c2jh\",\n k1xSpc: \"x78zum5\",\n kMv6JI: \"xs1w0rn\",\n kGuDYH: \"x1n35her\",\n kcqcaj: \"xss6m8b\",\n k63SB2: \"x1su64ma\",\n k87sOh: \"x1qiirwl\",\n kLqNvP: \"xty0069\",\n kjj79g: \"xl56j7k\",\n kb6lSQ: \"xdlnduh\",\n kLWn49: \"xaomhve\",\n k7Eaqz: \"x15kz4h8\",\n kg3NbH: \"ximhkdq\",\n khDVqt: \"xuxw1ft\",\n $$css: true\n },\n mark: {\n kWkggS: \"xwi4nbo\",\n kVAM5u: \"x1w1tqly\",\n kaIpWk: \"x1dkaolv\",\n ksu8eU: \"xx61lck\",\n kMzoRj: \"x13rsnn2\",\n kB7OPa: \"x9f619\",\n kfzvcC: \"x47corl\",\n kVAEAm: \"x10l6tqk\",\n $$css: true\n },\n small: {\n kZKoxP: \"xols6we\",\n kzqmXN: \"x1v4s8kt\",\n k87sOh: \"x13vifvy\",\n kt4wiu: \"xtijo5x\",\n $$css: true\n }\n};\ntype BadgeProps = RenderComponentProps<'span'> & {\n /**\n * The number to show, which draws the page's large badge. Left out, the\n * badge is the small 6dp dot, which flags without counting. A count of 0\n * still draws, so leave the badge out when there is nothing to count.\n */\n count?: number;\n /**\n * The largest count drawn as itself. Above it the badge reads `max` and a\n * plus, which is the page's 999+ at the default.\n * @default 999\n */\n max?: number;\n};\n\n/**\n * A badge on the corner of what it wraps, usually an icon: the small dot,\n * or with `count` the large badge holding a number. The mark is hidden from\n * assistive technology, so put what it says in the name of the control it\n * sits on.\n *\n * ```tsx\n * <IconButton aria-label=\"Notifications, 3 new\">\n * <Badge count={3}>\n * <BellIcon />\n * </Badge>\n * </IconButton>\n * ```\n *\n * Given no children, the mark stands alone in the line, as a tab draws it\n * after its label.\n *\n * The call site's `className` and `style` land on the element wrapping what\n * the badge is drawn on.\n */\nfunction Badge({\n children,\n count,\n max = 999,\n render,\n ...props\n}: BadgeProps) {\n const {\n locale\n } = useLocale();\n const placed = useContext(BadgeMarkContext);\n const numbers = new Intl.NumberFormat(locale);\n const label = count === undefined ? undefined : count > max ? `${numbers.format(max)}+` : numbers.format(count);\n return useRender({\n defaultTagName: 'span',\n props: {\n ...props,\n ...mergeStyles({\n className: \"x9f619 x3nfvp2 x1n2onr6\"\n }, props),\n children: <>\n {children}\n <span aria-hidden=\"true\" data-count={label} {...stylex.props(styles.mark, label === undefined ? styles.small : [styles.large, styles.count], (children === undefined || children === null) && styles.inFlow,\n // What a destination drawing it asks of a count's mark — see\n // src/badge. The small mark stays inside its icon's box, so\n // nothing has to make room for it.\n label !== undefined && placed)} />\n </>\n },\n render\n });\n}\nexport type { BadgeProps };\nexport default Badge;"],"mappings":"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"}
@@ -9,6 +9,17 @@ type CardProps = {
9
9
  * @default false
10
10
  */
11
11
  interactive?: boolean;
12
+ /**
13
+ * Turns an interactive card off: it fades as the cards page draws a
14
+ * disabled card, stops rippling and lifting, and takes no press. The
15
+ * default `<button>` is disabled outright. An element of the call site's
16
+ * own through `render` is marked `aria-disabled`, and an element handed in
17
+ * directly loses its `href`, `tabIndex` and `onClick`, so a link card can
18
+ * neither be followed nor focused. Has no effect on a card that is not
19
+ * `interactive`, which cannot be pressed to begin with.
20
+ * @default false
21
+ */
22
+ isDisabled?: boolean;
12
23
  /**
13
24
  * `none` removes the card's own padding, for a card whose children run to
14
25
  * its edges — a list of rows separated by rules.
@@ -35,7 +46,7 @@ type CardVariant = 'elevated' | 'filled' | 'outlined';
35
46
  * `<button>`, which is the right default for one that acts rather than
36
47
  * navigates.
37
48
  */
38
- declare function Card({ children, interactive, onClick, onContextMenu, onPointerCancel, onPointerDown, onPointerLeave, onPointerUp, padding, render, variant, ...props }: CardProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
49
+ declare function Card({ children, interactive, isDisabled, onClick, onContextMenu, onPointerCancel, onPointerDown, onPointerLeave, onPointerUp, padding, render, variant, ...props }: CardProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
39
50
  //#endregion
40
51
  export { type CardProps, type CardVariant, Card as default };
41
52
  //# sourceMappingURL=index.d.ts.map