@astryxdesign/core 0.1.0 → 0.1.1-canary.080d887

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 (170) hide show
  1. package/CHANGELOG.md +66 -0
  2. package/README.md +119 -1
  3. package/dist/AvatarGroup/AvatarGroupOverflow.d.ts +1 -1
  4. package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
  5. package/dist/AvatarGroup/AvatarGroupOverflow.js +4 -1
  6. package/dist/Banner/Banner.d.ts +7 -0
  7. package/dist/Banner/Banner.d.ts.map +1 -1
  8. package/dist/Banner/Banner.js +9 -2
  9. package/dist/Button/Button.d.ts +12 -2
  10. package/dist/Button/Button.d.ts.map +1 -1
  11. package/dist/Button/Button.js +51 -13
  12. package/dist/Chat/ChatLayoutScrollButton.d.ts.map +1 -1
  13. package/dist/Chat/ChatLayoutScrollButton.js +5 -1
  14. package/dist/ContextMenu/ContextMenu.js +2 -2
  15. package/dist/DropdownMenu/DropdownMenu.js +2 -2
  16. package/dist/DropdownMenu/{renderXDSDropdownItems.d.ts → renderDropdownItems.d.ts} +3 -3
  17. package/dist/DropdownMenu/renderDropdownItems.d.ts.map +1 -0
  18. package/dist/DropdownMenu/{renderXDSDropdownItems.js → renderDropdownItems.js} +2 -2
  19. package/dist/EmptyState/EmptyState.d.ts.map +1 -1
  20. package/dist/EmptyState/EmptyState.js +7 -1
  21. package/dist/HoverCard/HoverCard.d.ts +2 -2
  22. package/dist/HoverCard/HoverCard.d.ts.map +1 -1
  23. package/dist/HoverCard/HoverCard.js +18 -6
  24. package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
  25. package/dist/HoverCard/useHoverCard.js +6 -3
  26. package/dist/Kbd/Kbd.d.ts.map +1 -1
  27. package/dist/Kbd/Kbd.js +1 -1
  28. package/dist/Layer/useLayer.d.ts +13 -0
  29. package/dist/Layer/useLayer.d.ts.map +1 -1
  30. package/dist/Layer/useLayer.js +7 -2
  31. package/dist/Layout/Layout.d.ts +10 -1
  32. package/dist/Layout/Layout.d.ts.map +1 -1
  33. package/dist/Layout/Layout.js +5 -1
  34. package/dist/Markdown/Markdown.d.ts.map +1 -1
  35. package/dist/Markdown/Markdown.js +13 -3
  36. package/dist/MobileNav/MobileNav.d.ts.map +1 -1
  37. package/dist/MobileNav/MobileNav.js +13 -0
  38. package/dist/Outline/Outline.d.ts +3 -2
  39. package/dist/Outline/Outline.d.ts.map +1 -1
  40. package/dist/Outline/Outline.js +23 -4
  41. package/dist/Outline/useScrollSpy.d.ts +14 -1
  42. package/dist/Outline/useScrollSpy.d.ts.map +1 -1
  43. package/dist/Outline/useScrollSpy.js +161 -50
  44. package/dist/Pagination/Pagination.d.ts.map +1 -1
  45. package/dist/Pagination/Pagination.js +31 -27
  46. package/dist/Resizable/useResizable.d.ts.map +1 -1
  47. package/dist/Resizable/useResizable.js +1 -5
  48. package/dist/Selector/Selector.d.ts.map +1 -1
  49. package/dist/Selector/Selector.js +1 -1
  50. package/dist/Slider/Slider.js +2 -2
  51. package/dist/Table/BaseTable.d.ts.map +1 -1
  52. package/dist/Table/BaseTable.js +26 -8
  53. package/dist/Table/Table.d.ts.map +1 -1
  54. package/dist/Table/Table.js +30 -7
  55. package/dist/Table/index.d.ts +3 -1
  56. package/dist/Table/index.d.ts.map +1 -1
  57. package/dist/Table/index.js +1 -0
  58. package/dist/Table/plugins/stickyColumns/index.d.ts +3 -0
  59. package/dist/Table/plugins/stickyColumns/index.d.ts.map +1 -0
  60. package/dist/Table/plugins/stickyColumns/index.js +3 -0
  61. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.d.ts +25 -0
  62. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.d.ts.map +1 -0
  63. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +376 -0
  64. package/dist/Table/types.d.ts +90 -5
  65. package/dist/Table/types.d.ts.map +1 -1
  66. package/dist/Table/useBaseTablePlugins.d.ts.map +1 -1
  67. package/dist/Table/useBaseTablePlugins.js +1 -1
  68. package/dist/Timestamp/Timestamp.d.ts +1 -1
  69. package/dist/Timestamp/Timestamp.d.ts.map +1 -1
  70. package/dist/Timestamp/Timestamp.js +28 -3
  71. package/dist/ToggleButton/ToggleButton.d.ts +10 -5
  72. package/dist/ToggleButton/ToggleButton.d.ts.map +1 -1
  73. package/dist/ToggleButton/ToggleButton.js +40 -17
  74. package/dist/astryx.css +20 -0
  75. package/dist/astryx.umd.js +147 -0
  76. package/dist/astryx.umd.js.map +7 -0
  77. package/dist/theme/Theme.js +1 -1
  78. package/dist/theme/defineTheme.d.ts +1 -1
  79. package/dist/theme/defineTheme.d.ts.map +1 -1
  80. package/dist/theme/defineTheme.js +1 -1
  81. package/dist/theme/index.d.ts +1 -1
  82. package/dist/theme/index.d.ts.map +1 -1
  83. package/dist/theme/index.js +1 -1
  84. package/dist/theme/syntax/defineSyntaxTheme.js +1 -1
  85. package/dist/theme/tokens.d.ts +1 -1
  86. package/dist/theme/tokens.js +4 -4
  87. package/dist/theme/useTheme.d.ts +2 -2
  88. package/dist/utils/dateParser.d.ts.map +1 -1
  89. package/dist/utils/dateParser.js +15 -2
  90. package/package.json +7 -3
  91. package/src/AvatarGroup/AvatarGroupOverflow.tsx +3 -0
  92. package/src/Banner/Banner.test.tsx +16 -7
  93. package/src/Banner/Banner.tsx +9 -2
  94. package/src/Button/Button.doc.mjs +6 -0
  95. package/src/Button/Button.test.tsx +105 -11
  96. package/src/Button/Button.tsx +73 -5
  97. package/src/Chat/ChatLayoutScrollButton.tsx +7 -1
  98. package/src/Collapsible/useCollapsible.doc.mjs +2 -2
  99. package/src/ContextMenu/ContextMenu.tsx +2 -2
  100. package/src/DateInput/DateInput.test.tsx +68 -20
  101. package/src/Divider/Divider.doc.mjs +1 -1
  102. package/src/DropdownMenu/DropdownMenu.tsx +2 -2
  103. package/src/DropdownMenu/{renderXDSDropdownItems.tsx → renderDropdownItems.tsx} +2 -2
  104. package/src/EmptyState/EmptyState.test.tsx +4 -2
  105. package/src/EmptyState/EmptyState.tsx +6 -2
  106. package/src/FormLayout/FormLayout.doc.mjs +3 -3
  107. package/src/HoverCard/HoverCard.doc.mjs +3 -0
  108. package/src/HoverCard/HoverCard.test.tsx +178 -2
  109. package/src/HoverCard/HoverCard.tsx +20 -16
  110. package/src/HoverCard/useHoverCard.tsx +12 -10
  111. package/src/Icon/Icon.doc.mjs +12 -4
  112. package/src/Item/Item.doc.mjs +2 -2
  113. package/src/Kbd/Kbd.tsx +2 -9
  114. package/src/Layer/useLayer.doc.mjs +7 -2
  115. package/src/Layer/useLayer.tsx +19 -2
  116. package/src/Layout/Layout.doc.mjs +2 -1
  117. package/src/Layout/Layout.tsx +15 -1
  118. package/src/Layout/__tests__/childrenAsContent.test.tsx +59 -0
  119. package/src/Lightbox/Lightbox.doc.mjs +0 -2
  120. package/src/Link/Link.doc.mjs +3 -3
  121. package/src/Link/LinkProvider.doc.mjs +3 -3
  122. package/src/Markdown/Markdown.doc.mjs +6 -4
  123. package/src/Markdown/Markdown.test.tsx +17 -26
  124. package/src/Markdown/Markdown.tsx +16 -6
  125. package/src/MobileNav/MobileNav.doc.mjs +8 -8
  126. package/src/MobileNav/MobileNav.tsx +13 -0
  127. package/src/MobileNav/MobileNavReopen.test.tsx +118 -0
  128. package/src/Outline/Outline.doc.mjs +1 -1
  129. package/src/Outline/Outline.test.tsx +76 -38
  130. package/src/Outline/Outline.tsx +23 -4
  131. package/src/Outline/useScrollSpy.ts +196 -63
  132. package/src/Pagination/Pagination.test.tsx +137 -13
  133. package/src/Pagination/Pagination.tsx +33 -28
  134. package/src/Resizable/Resizable.doc.mjs +3 -3
  135. package/src/Resizable/useResizable.ts +1 -7
  136. package/src/Selector/Selector.doc.mjs +4 -0
  137. package/src/Selector/Selector.tsx +5 -6
  138. package/src/Skeleton/Skeleton.doc.mjs +11 -1
  139. package/src/Slider/Slider.doc.mjs +4 -0
  140. package/src/Slider/Slider.test.tsx +3 -16
  141. package/src/Slider/Slider.tsx +1 -1
  142. package/src/Table/BaseTable.tsx +50 -24
  143. package/src/Table/Table.doc.mjs +15 -3
  144. package/src/Table/Table.tsx +22 -1
  145. package/src/Table/index.ts +3 -0
  146. package/src/Table/plugins/stickyColumns/index.ts +4 -0
  147. package/src/Table/plugins/stickyColumns/useTableStickyColumns.test.tsx +163 -0
  148. package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +414 -0
  149. package/src/Table/types.ts +96 -4
  150. package/src/Table/useBaseTablePlugins.ts +1 -0
  151. package/src/Text/Heading.doc.mjs +13 -0
  152. package/src/Timestamp/Timestamp.test.tsx +44 -18
  153. package/src/Timestamp/Timestamp.tsx +30 -10
  154. package/src/ToggleButton/ToggleButton.doc.mjs +4 -4
  155. package/src/ToggleButton/ToggleButton.test.tsx +172 -9
  156. package/src/ToggleButton/ToggleButton.tsx +57 -31
  157. package/src/Toolbar/Toolbar.doc.mjs +1 -1
  158. package/src/hooks/useEntryAnimation.doc.mjs +3 -3
  159. package/src/hooks/useMediaQuery.doc.mjs +2 -2
  160. package/src/hooks/useStreamingText.doc.mjs +3 -3
  161. package/src/theme/Theme.doc.mjs +2 -2
  162. package/src/theme/Theme.tsx +1 -1
  163. package/src/theme/defineTheme.ts +1 -1
  164. package/src/theme/index.ts +1 -1
  165. package/src/theme/syntax/defineSyntaxTheme.ts +1 -1
  166. package/src/theme/tokens.ts +4 -4
  167. package/src/theme/useTheme.ts +2 -2
  168. package/src/utils/dateParser.test.ts +26 -0
  169. package/src/utils/dateParser.ts +16 -2
  170. package/dist/DropdownMenu/renderXDSDropdownItems.d.ts.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,69 @@
1
1
  # @xds/core
2
2
 
3
+ # 0.1.1
4
+
5
+ #### Breaking Changes
6
+
7
+ - Rename `xdsTokenDefaults` export to `tokenDefaults`
8
+ The token-defaults constant is renamed from `xdsTokenDefaults` to
9
+ `tokenDefaults` (exported from `@astryxdesign/core/theme`). Update imports
10
+ accordingly. Part of removing xds naming from the public API.
11
+
12
+ #### Fixes
13
+
14
+ - Increase trailing padding on `ChatLayoutScrollButton` when a label is shown
15
+ With a label (e.g. "New messages"), the chevron icon sits on the leading edge
16
+ and the text on the trailing edge. The symmetric inline padding left the label
17
+ text cramped against the pill's rounded corner. The trailing inline padding is
18
+ now widened when a label is present, giving the text comfortable breathing room
19
+ from the rounded edge. The icon-only (collapsed) state is unchanged and stays
20
+ balanced.
21
+ - Prevent `DateInput` from crashing the page while typing an incomplete
22
+ date. Typing a leading `0` or `1` (e.g. starting to enter `01` for January)
23
+ could coerce the in-progress value into an invalid date with a year of `0`,
24
+ which then threw a `RangeError` and crashed the surrounding page. Partial,
25
+ not-yet-complete input is now treated as incomplete instead of being parsed
26
+ into a date, so the field stays usable as you type.
27
+ - Remove doubled focus ring on `Selector`. The inner combobox button drew
28
+ its own `:focus-visible` outline on top of the wrapper's `:focus-within` ring,
29
+ producing a stacked, rounded outline over the trigger after selecting an option
30
+ or navigating with the keyboard. The button now defers to the wrapper's focus
31
+ ring, matching `TextInput` and `NumberInput`.
32
+ - `<Layout>…</Layout>` no longer renders a blank page. `Layout` is
33
+ slot-driven (`content`/`header`/`start`/`end`/`footer`), and the natural nested
34
+ form `<Layout><LayoutContent /></Layout>` previously type-checked and built
35
+ green while dropping its children at runtime — an empty shell. Children now
36
+ render as a shorthand for the `content` slot (`<Layout>{main}</Layout>` is
37
+ equivalent to `<Layout content={main} />`), matching how `Card` and `Section`
38
+ accept content; an explicit `content` prop still wins when both are provided.
39
+ - ToggleButton runs pressedChangeAction in an interruptible transition with optimistic state
40
+ `pressedChangeAction` was fired as a non-awaited promise, so the documented
41
+ loading spinner never appeared and the toggle ignored the action's lifecycle.
42
+ It now runs inside a transition with an optimistic pressed state, matching
43
+ `Switch`:
44
+
45
+ #### Other Changes
46
+
47
+ - The optimistic pressed state flips immediately on click; the spinner is
48
+ debounced so a fast action shows the new state without a spinner flash.
49
+ - The action is interruptible — clicking again while it is pending starts a
50
+ new transition with the next optimistic state (e.g. true -> false -> true),
51
+ instead of being dropped or guarded out.
52
+ - Synchronous handlers are supported too: a `pressedChangeAction` (or
53
+ `onPressedChange`) that synchronously triggers a suspending update, such as
54
+ a router navigation that suspends on data, also drives the pending state.
55
+ `pressedChangeAction` now accepts `void | Promise<void>`.
56
+
57
+ #### Contributors
58
+
59
+ Thanks to everyone who contributed to this release:
60
+
61
+ - @cixzhang
62
+ - @ejhammond
63
+ - @josephfarina
64
+
65
+ ---
66
+
3
67
  # 0.1.0
4
68
 
5
69
  #### Breaking Changes
@@ -52,9 +116,11 @@
52
116
  - import {neutralTheme} from '@astryxdesign/theme-neutral/built';
53
117
  - <Theme theme={defaultTheme}>...</Theme>
54
118
  - <Theme theme={neutralTheme}>...</Theme>
119
+
55
120
  ```
56
121
 
57
122
  ```
123
+
58
124
  - Rename the npm package scope from `@xds/*` to `@astryxdesign/*`
59
125
  All published packages move to the new `@astryxdesign` scope (e.g. `@xds/core` → `@astryxdesign/core`), along with the workspace lockfile, build/runtime scope-directory scans, and docsite slug derivation. Consumers must update their imports and dependency names. The internal ESLint plugin namespace (`@xds/*` rules) is intentionally untouched and tracked separately. Existing `@xds/*` codemods continue to target the old scope so projects still on `@xds/*` can migrate.
60
126
 
package/README.md CHANGED
@@ -70,7 +70,57 @@ npm install @astryxdesign/core @astryxdesign/theme-neutral
70
70
 
71
71
  Then pick your setup below based on your framework and styling approach.
72
72
 
73
- ### Next.js + Tailwind (simplest)
73
+ ### Next.js (simplest)
74
+
75
+ The fastest way to get started. No build plugins, no PostCSS, no Babel config — Astryx ships pre-built CSS and JS, so you import three stylesheets (order matters) and wrap your app in a theme provider.
76
+
77
+ **`src/app/globals.css`**
78
+
79
+ ```css
80
+ @import '@astryxdesign/core/reset.css';
81
+ @import '@astryxdesign/core/astryx.css';
82
+ @import '@astryxdesign/theme-neutral/theme.css';
83
+ ```
84
+
85
+ The import order maps to the layer cascade: `reset.css` (`@layer reset`) → `astryx.css` component styles (`@layer astryx-base`) → `theme.css` token overrides (`@layer astryx-theme`).
86
+
87
+ **`src/app/providers.tsx`**
88
+
89
+ ```tsx
90
+ 'use client';
91
+
92
+ import Link from 'next/link';
93
+ import {Theme} from '@astryxdesign/core/theme';
94
+ import {LinkProvider} from '@astryxdesign/core/Link';
95
+ import {neutralTheme} from '@astryxdesign/theme-neutral/built';
96
+
97
+ export function Providers({children}: {children: React.ReactNode}) {
98
+ return (
99
+ <Theme theme={neutralTheme}>
100
+ <LinkProvider component={Link}>{children}</LinkProvider>
101
+ </Theme>
102
+ );
103
+ }
104
+ ```
105
+
106
+ **`src/app/layout.tsx`**
107
+
108
+ ```tsx
109
+ import './globals.css';
110
+ import {Providers} from './providers';
111
+
112
+ export default function RootLayout({children}: {children: React.ReactNode}) {
113
+ return (
114
+ <html lang="en">
115
+ <body>
116
+ <Providers>{children}</Providers>
117
+ </body>
118
+ </html>
119
+ );
120
+ }
121
+ ```
122
+
123
+ ### Next.js + Tailwind
74
124
 
75
125
  No build plugins needed; XDS ships pre-built CSS that works alongside Tailwind.
76
126
 
@@ -183,3 +233,71 @@ npm install @astryxdesign/core @astryxdesign/theme-neutral
183
233
  ```
184
234
 
185
235
  Same CSS imports and providers as above. No build plugins needed; XDS ships pre-built.
236
+
237
+ ### No build step (CDN)
238
+
239
+ For prototypes, embeds, or pages without a bundler, load the components straight
240
+ from a public CDN. Two delivery options ship in the published package:
241
+
242
+ **1. UMD global (`<script>` tag).** A single pre-bundled file exposes every export
243
+ on `window.Astryx`. React and ReactDOM are peer dependencies — load them yourself.
244
+ Pair it with the precompiled stylesheet.
245
+
246
+ ```html
247
+ <!doctype html>
248
+ <html data-astryx-theme="neutral">
249
+ <head>
250
+ <link
251
+ rel="stylesheet"
252
+ href="https://cdn.jsdelivr.net/npm/@astryxdesign/core/src/reset.css" />
253
+ <link
254
+ rel="stylesheet"
255
+ href="https://cdn.jsdelivr.net/npm/@astryxdesign/core/dist/astryx.css" />
256
+ </head>
257
+ <body>
258
+ <div id="root"></div>
259
+ <script
260
+ crossorigin
261
+ src="https://unpkg.com/react@19/umd/react.production.min.js"></script>
262
+ <script
263
+ crossorigin
264
+ src="https://unpkg.com/react-dom@19/umd/react-dom.production.min.js"></script>
265
+ <script src="https://cdn.jsdelivr.net/npm/@astryxdesign/core/dist/astryx.umd.js"></script>
266
+ <script>
267
+ const {Button, Card} = window.Astryx;
268
+ const e = React.createElement;
269
+ ReactDOM.createRoot(document.getElementById('root')).render(
270
+ e(Card, null, e(Button, {variant: 'primary'}, 'Hello from a CDN')),
271
+ );
272
+ </script>
273
+ </body>
274
+ </html>
275
+ ```
276
+
277
+ **2. ES modules (no UMD, no globals).** Use [esm.sh](https://esm.sh), which rewrites
278
+ bare imports to browser-resolvable URLs. An import map keeps a single React instance.
279
+
280
+ ```html
281
+ <link
282
+ rel="stylesheet"
283
+ href="https://cdn.jsdelivr.net/npm/@astryxdesign/core/dist/astryx.css" />
284
+ <script type="importmap">
285
+ {
286
+ "imports": {
287
+ "react": "https://esm.sh/react@19",
288
+ "react-dom/client": "https://esm.sh/react-dom@19/client",
289
+ "@astryxdesign/core": "https://esm.sh/@astryxdesign/core?external=react,react-dom"
290
+ }
291
+ }
292
+ </script>
293
+ <script type="module">
294
+ import {createRoot} from 'react-dom/client';
295
+ import {Button} from '@astryxdesign/core';
296
+ // ...render as usual
297
+ </script>
298
+ ```
299
+
300
+ > Pin a version in production (e.g. `@astryxdesign/core@0.1.1`) — unversioned CDN URLs
301
+ > resolve to the latest release and are cached aggressively. The raw ESM entry
302
+ > (`dist/index.js`) uses bare `react` imports and will **not** run from a plain
303
+ > `<script src>`; use the UMD global or esm.sh as shown above.
@@ -41,7 +41,7 @@ export interface AvatarGroupOverflowProps extends Omit<BaseProps<HTMLElement>, '
41
41
  * </AvatarGroup>
42
42
  * ```
43
43
  */
44
- export declare function AvatarGroupOverflow({ ref, count, onClick, children, xstyle, className, style, }: AvatarGroupOverflowProps): ReactNode;
44
+ export declare function AvatarGroupOverflow({ ref, count, onClick, children, xstyle, className, style, ...rest }: AvatarGroupOverflowProps): ReactNode;
45
45
  export declare namespace AvatarGroupOverflow {
46
46
  var displayName: string;
47
47
  }
@@ -1 +1 @@
1
- {"version":3,"file":"AvatarGroupOverflow.d.ts","sourceRoot":"","sources":["../../src/AvatarGroup/AvatarGroupOverflow.tsx"],"names":[],"mappings":"AAGA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,EAAC,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAU5C,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAM5C,MAAM,WAAW,wBAAyB,SAAQ,IAAI,CACpD,SAAS,CAAC,WAAW,CAAC,EACtB,SAAS,CACV;IACC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAC7B;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IAErB;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AA6DD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,GAAG,EACH,KAAK,EACL,OAAO,EACP,QAAQ,EACR,MAAM,EACN,SAAS,EACT,KAAK,GACN,EAAE,wBAAwB,GAAG,SAAS,CAsDtC;yBA9De,mBAAmB"}
1
+ {"version":3,"file":"AvatarGroupOverflow.d.ts","sourceRoot":"","sources":["../../src/AvatarGroup/AvatarGroupOverflow.tsx"],"names":[],"mappings":"AAGA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,EAAC,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAU5C,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAM5C,MAAM,WAAW,wBAAyB,SAAQ,IAAI,CACpD,SAAS,CAAC,WAAW,CAAC,EACtB,SAAS,CACV;IACC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAC7B;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IAErB;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AA6DD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,GAAG,EACH,KAAK,EACL,OAAO,EACP,QAAQ,EACR,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,IAAI,EACR,EAAE,wBAAwB,GAAG,SAAS,CAwDtC;yBAjEe,mBAAmB"}
@@ -100,7 +100,8 @@ export function AvatarGroupOverflow({
100
100
  children,
101
101
  xstyle,
102
102
  className,
103
- style
103
+ style,
104
+ ...rest
104
105
  }) {
105
106
  const group = useAvatarGroup();
106
107
  const numericSize = group?.numericSize ?? 36;
@@ -113,6 +114,7 @@ export function AvatarGroupOverflow({
113
114
  type: "button",
114
115
  onClick: onClick,
115
116
  "aria-label": label,
117
+ ...rest,
116
118
  ...mergeProps(themeProps('avatar-group-overflow'), stylex.props(styles.base, styles.button, styles.overlap, dynamicStyles.size(numericSize), dynamicStyles.fontSize(numericSize), dynamicStyles.overlap(-overlap), xstyle), className, style),
117
119
  children: content
118
120
  });
@@ -120,6 +122,7 @@ export function AvatarGroupOverflow({
120
122
  return /*#__PURE__*/_jsx("span", {
121
123
  ref: ref,
122
124
  "aria-label": label,
125
+ ...rest,
123
126
  ...mergeProps(themeProps('avatar-group-overflow'), stylex.props(styles.base, styles.overlap, dynamicStyles.size(numericSize), dynamicStyles.fontSize(numericSize), dynamicStyles.overlap(-overlap), xstyle), className, style),
124
127
  children: content
125
128
  });
@@ -12,6 +12,13 @@
12
12
  * - Each visual area owns its own border-radius (no overflow:clip on the container)
13
13
  * - When children are provided, a collapse/expand toggle button appears in the end area
14
14
  *
15
+ * Title and description render as <div> (not <p>): they accept arbitrary
16
+ * ReactNode content, and <p> cannot legally contain block-level children
17
+ * (the HTML parser reparents them, desyncing SSR markup from the hydrated
18
+ * DOM). Using <div> keeps these slots composable with any content. Their
19
+ * StyleX styles set margin: 0 and explicit typography, so the rendered
20
+ * appearance is identical to the previous <p>.
21
+ *
15
22
  * SYNC: When modified, update these files to stay in sync:
16
23
  * - /packages/core/src/Banner/Banner.doc.mjs (props table, features, implementation notes)
17
24
  * - /packages/core/src/Banner/Banner.test.tsx (tests for new/changed behavior)
@@ -1 +1 @@
1
- {"version":3,"file":"Banner.d.ts","sourceRoot":"","sources":["../../src/Banner/Banner.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAW,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAE/C,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAsB5C;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,IAAI,CAAC;IACX,OAAO,EAAE,IAAI,CAAC;IACd,KAAK,EAAE,IAAI,CAAC;IACZ,OAAO,EAAE,IAAI,CAAC;CACf;AAED;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,eAAe,CAAC;AAEjD;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,IAAI,CAAC;IACX,OAAO,EAAE,IAAI,CAAC;CACf;AAED;;;;;;GAMG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,kBAAkB,CAAC;AAEvD,MAAM,WAAW,WAAY,SAAQ,SAAS,CAAC,cAAc,CAAC;IAC5D,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC;;OAEG;IACH,MAAM,EAAE,YAAY,CAAC;IACrB;;OAEG;IACH,KAAK,EAAE,SAAS,CAAC;IACjB;;OAEG;IACH,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB;;OAEG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB;;;;;;;;OAQG;IACH,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AA2JD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,wBAAgB,MAAM,CAAC,EACrB,MAAM,EACN,KAAK,EACL,WAAW,EACX,IAAI,EACJ,aAAqB,EACrB,SAAS,EACT,UAAU,EACV,SAAkB,EAClB,iBAAyB,EACzB,QAAQ,EACR,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,EACH,GAAG,IAAI,EACR,EAAE,WAAW,sCA0Hb;yBA1Ie,MAAM"}
1
+ {"version":3,"file":"Banner.d.ts","sourceRoot":"","sources":["../../src/Banner/Banner.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,EAAW,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAE/C,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAsB5C;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,IAAI,CAAC;IACX,OAAO,EAAE,IAAI,CAAC;IACd,KAAK,EAAE,IAAI,CAAC;IACZ,OAAO,EAAE,IAAI,CAAC;CACf;AAED;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,eAAe,CAAC;AAEjD;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,IAAI,CAAC;IACX,OAAO,EAAE,IAAI,CAAC;CACf;AAED;;;;;;GAMG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,kBAAkB,CAAC;AAEvD,MAAM,WAAW,WAAY,SAAQ,SAAS,CAAC,cAAc,CAAC;IAC5D,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC;;OAEG;IACH,MAAM,EAAE,YAAY,CAAC;IACrB;;OAEG;IACH,KAAK,EAAE,SAAS,CAAC;IACjB;;OAEG;IACH,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB;;OAEG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB;;;;;;;;OAQG;IACH,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AA2JD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,wBAAgB,MAAM,CAAC,EACrB,MAAM,EACN,KAAK,EACL,WAAW,EACX,IAAI,EACJ,aAAqB,EACrB,SAAS,EACT,UAAU,EACV,SAAkB,EAClB,iBAAyB,EACzB,QAAQ,EACR,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,EACH,GAAG,IAAI,EACR,EAAE,WAAW,sCA0Hb;yBA1Ie,MAAM"}
@@ -16,6 +16,13 @@
16
16
  * - Each visual area owns its own border-radius (no overflow:clip on the container)
17
17
  * - When children are provided, a collapse/expand toggle button appears in the end area
18
18
  *
19
+ * Title and description render as <div> (not <p>): they accept arbitrary
20
+ * ReactNode content, and <p> cannot legally contain block-level children
21
+ * (the HTML parser reparents them, desyncing SSR markup from the hydrated
22
+ * DOM). Using <div> keeps these slots composable with any content. Their
23
+ * StyleX styles set margin: 0 and explicit typography, so the rendered
24
+ * appearance is identical to the previous <p>.
25
+ *
19
26
  * SYNC: When modified, update these files to stay in sync:
20
27
  * - /packages/core/src/Banner/Banner.doc.mjs (props table, features, implementation notes)
21
28
  * - /packages/core/src/Banner/Banner.test.tsx (tests for new/changed behavior)
@@ -291,12 +298,12 @@ export function Banner({
291
298
  ...{
292
299
  className: "x78zum5 xdt5ytf xxhr3t x98rzlu xeuugli"
293
300
  },
294
- children: [/*#__PURE__*/_jsx("p", {
301
+ children: [/*#__PURE__*/_jsx("div", {
295
302
  ...{
296
303
  className: "x1ghz6dp xjb2p0i xcr08ib x2mo6ok x1kq96og x1tgivj0"
297
304
  },
298
305
  children: title
299
- }), description != null && /*#__PURE__*/_jsx("p", {
306
+ }), description != null && /*#__PURE__*/_jsx("div", {
300
307
  ...{
301
308
  className: "x1ghz6dp xjb2p0i x141an7d x1sodnla x1ltkj2j xv1l7n4"
302
309
  },
@@ -11,7 +11,7 @@
11
11
  * - /apps/storybook/stories/Button.stories.tsx (storybook stories)
12
12
  * - /packages/cli/templates/blocks/components/Button/ (showcase blocks)
13
13
  *
14
- * Last synced props: label, variant, size, isDisabled, isLoading, clickAction, icon, isIconOnly, children, tooltip, endContent, href, as, target, rel
14
+ * Last synced props: label, variant, size, isDisabled, isLoading, isInterruptible, clickAction, icon, isIconOnly, children, tooltip, endContent, href, as, target, rel
15
15
  */
16
16
  import { type ReactNode } from 'react';
17
17
  import type { BaseProps } from '../BaseProps';
@@ -93,6 +93,16 @@ export interface ButtonProps extends BaseProps<HTMLButtonElement> {
93
93
  * @default false
94
94
  */
95
95
  isLoading?: boolean;
96
+ /**
97
+ * Keep the button interactive while a `clickAction` is pending. The loading
98
+ * state still renders the spinner and `aria-busy`, but the button is not
99
+ * disabled and the in-flight action is not deduped — so a re-click lands and
100
+ * interrupts the previous action with a fresh one. Use for interruptible
101
+ * actions (e.g. a toggle whose action can be re-triggered before the previous
102
+ * one settles), not fire-once actions (submit/save/pay).
103
+ * @default false
104
+ */
105
+ isInterruptible?: boolean;
96
106
  /**
97
107
  * Click handler. For async actions that should show a loading state,
98
108
  * use `clickAction` instead.
@@ -175,7 +185,7 @@ export interface ButtonProps extends BaseProps<HTMLButtonElement> {
175
185
  * <Button label="Open in new tab" href="https://example.com" target="_blank" rel="noopener noreferrer" />
176
186
  * ```
177
187
  */
178
- export declare function Button({ label, variant, size: sizeProp, type, isDisabled, isLoading, clickAction, icon, isIconOnly, children, endContent, tooltip, href, as, target, rel, xstyle, className, style, ref, ...props }: ButtonProps): ReactNode;
188
+ export declare function Button({ label, variant, size: sizeProp, type, isDisabled, isLoading, isInterruptible, clickAction, icon, isIconOnly, children, endContent, tooltip, href, as, target, rel, xstyle, className, style, ref, ...props }: ButtonProps): ReactNode;
179
189
  export declare namespace Button {
180
190
  var displayName: string;
181
191
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../src/Button/Button.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAwB,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAC5D,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,MAAM,MAAM,kBAAkB,CAAC;AAoB3C,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,eAAe,CAAC;AAoGrD,QAAA,MAAM,UAAU;;;;;;;;;;EAUd,CAAC;AAsGH;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,IAAI,CAAC;IACd,SAAS,EAAE,IAAI,CAAC;IAChB,KAAK,EAAE,IAAI,CAAC;IACZ,WAAW,EAAE,IAAI,CAAC;CACnB;AAED;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,gBAAgB,CAAC;AAEnD;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,OAAO,UAAU,CAAC;AAEjD,MAAM,WAAW,WAAY,SAAQ,SAAS,CAAC,iBAAiB,CAAC;IAC/D,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACnC,oDAAoD;IACpD,IAAI,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;IACrC,+CAA+C;IAC/C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gDAAgD;IAChD,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IAChD,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB;;;OAGG;IACH,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;OAGG;IACH,OAAO,CAAC,EAAE,KAAK,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,CAAC;IACrD;;OAEG;IACH,WAAW,CAAC,EAAE,CACZ,CAAC,EAAE,KAAK,CAAC,UAAU,CAAC,iBAAiB,CAAC,KACnC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B;;OAEG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,EAAE,CAAC,EAAE,iBAAiB,CAAC;IACvB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAmFD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,MAAM,CAAC,EACrB,KAAK,EACL,OAAqB,EACrB,IAAI,EAAE,QAAQ,EACd,IAAe,EACf,UAAkB,EAClB,SAAiB,EACjB,WAAW,EACX,IAAI,EACJ,UAAkB,EAClB,QAAQ,EACR,UAAU,EACV,OAAO,EACP,IAAI,EACJ,EAAE,EACF,MAAM,EACN,GAAG,EACH,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,EACH,GAAG,KAAK,EACT,EAAE,WAAW,GAAG,SAAS,CAkLzB;yBAxMe,MAAM"}
1
+ {"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../src/Button/Button.tsx"],"names":[],"mappings":"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"}
@@ -15,7 +15,7 @@
15
15
  * - /apps/storybook/stories/Button.stories.tsx (storybook stories)
16
16
  * - /packages/cli/templates/blocks/components/Button/ (showcase blocks)
17
17
  *
18
- * Last synced props: label, variant, size, isDisabled, isLoading, clickAction, icon, isIconOnly, children, tooltip, endContent, href, as, target, rel
18
+ * Last synced props: label, variant, size, isDisabled, isLoading, isInterruptible, clickAction, icon, isIconOnly, children, tooltip, endContent, href, as, target, rel
19
19
  */
20
20
  import { useRef, useTransition } from 'react';
21
21
  import * as stylex from '@stylexjs/stylex';
@@ -88,6 +88,10 @@ const styles = {
88
88
  kmuXW: "x2lah0s",
89
89
  $$css: true
90
90
  },
91
+ contentWrapper: {
92
+ k1xSpc: "xjp7ctv",
93
+ $$css: true
94
+ },
91
95
  link: {
92
96
  kybGjl: "x1hl2dhg",
93
97
  $$css: true
@@ -202,6 +206,27 @@ const variants = {
202
206
  * Button size type derived from the sizeStyles StyleX object
203
207
  */
204
208
 
209
+ const spinnerReveal = "x18re5ia-B";
210
+ const contentHide = "x188b6p3-B";
211
+
212
+ // Hold the loading swap for a short delay so a fast action (e.g. clickAction)
213
+ // that settles within the delay never flashes a spinner. The spinner fade-in
214
+ // and the content hide share the same delay so the button never shows an empty
215
+ // frame in between. Reduced motion is instant.
216
+ const SPINNER_DELAY = durationVars['--duration-medium-min'];
217
+ const loadingStyles = {
218
+ hiddenContent: {
219
+ kMwMTN: "x19co3pv",
220
+ $$css: true
221
+ },
222
+ hiddenContentDelayed: {
223
+ kKVMdj: "x1ffowhz",
224
+ k44tkh: "xjlvqhv",
225
+ kWV6AL: "x10e4vud",
226
+ kKxzle: "x17yabm6 x14q22ui",
227
+ $$css: true
228
+ }
229
+ };
205
230
  const groupStyles = {
206
231
  horizontal: {
207
232
  krdFHd: "x15mokao x8eehn2",
@@ -265,6 +290,7 @@ export function Button({
265
290
  type = 'button',
266
291
  isDisabled = false,
267
292
  isLoading = false,
293
+ isInterruptible = false,
268
294
  clickAction,
269
295
  icon,
270
296
  isIconOnly = false,
@@ -284,10 +310,22 @@ export function Button({
284
310
  const size = useSize(sizeProp, 'md');
285
311
  const buttonGroup = useButtonGroup();
286
312
  const [isPending, startTransition] = useTransition();
313
+ // clickAction is normally fire-once (submit/save/pay), so a same-tick
314
+ // double-click must dedupe — which neither isPending nor useOptimistic do.
315
+ // Hence the ref guard. Interruptible callers (e.g. ToggleButton) opt out so a
316
+ // re-click can land and interrupt the in-flight action with a fresh one.
287
317
  const actionInFlightRef = useRef(false);
288
318
  const isLoadingState = isLoading || isPending;
319
+ // Delay the spinner reveal for action-driven loading (clickAction's own
320
+ // transition) so a fast action that settles within the delay does not flash
321
+ // a spinner. Interruptible loading is delayed too, so rapid re-clicks settle
322
+ // before any spinner shows. Explicit isLoading-only stays immediate, since
323
+ // the consumer is deliberately showing it.
324
+ const delaySpinner = isPending || isInterruptible;
289
325
  const groupDisabled = buttonGroup?.isDisabled ?? false;
290
- const buttonDisabled = isDisabled || groupDisabled || isLoadingState;
326
+ // When interruptible, the loading state drives the spinner and aria-busy but
327
+ // not disabled, so clicks keep landing and can interrupt the in-flight action.
328
+ const buttonDisabled = isDisabled || groupDisabled || isLoadingState && !isInterruptible;
291
329
  // isIconOnly prop is the source of truth for icon-only rendering.
292
330
  // When false (default), label is always rendered as visible text.
293
331
 
@@ -301,7 +339,9 @@ export function Button({
301
339
  // for keyboard users to reach the tooltip. Otherwise use native disabled.
302
340
  const useAriaDisabled = tooltip != null && buttonDisabled;
303
341
  const handleClick = e => {
304
- if (buttonDisabled || actionInFlightRef.current) {
342
+ // The ref guard dedupes fire-once actions. Interruptible callers skip it so
343
+ // a re-click while pending starts a fresh action that interrupts the prior.
344
+ if (buttonDisabled || actionInFlightRef.current && !isInterruptible) {
305
345
  e.preventDefault();
306
346
  return;
307
347
  }
@@ -344,22 +384,20 @@ export function Button({
344
384
  const buttonContent = /*#__PURE__*/_jsxs(_Fragment, {
345
385
  children: [isLoadingState && /*#__PURE__*/_jsx("span", {
346
386
  ...{
347
- className: "x10l6tqk x13vifvy xu96u03 x3m8u43 x1ey2m1c xrvj5dj x1ku5rj1"
348
- },
387
+ 0: {
388
+ className: "x10l6tqk x13vifvy xu96u03 x3m8u43 x1ey2m1c xrvj5dj x1ku5rj1"
389
+ },
390
+ 1: {
391
+ className: "x10l6tqk x13vifvy xu96u03 x3m8u43 x1ey2m1c xrvj5dj x1ku5rj1 xqcmdr3 xb2rp9n xskzprw x17yabm6 x14q22ui"
392
+ }
393
+ }[!!delaySpinner << 0],
349
394
  "aria-hidden": "true",
350
395
  children: /*#__PURE__*/_jsx(Spinner, {
351
396
  size: "sm",
352
397
  shade: "inherit"
353
398
  })
354
399
  }), /*#__PURE__*/_jsxs("span", {
355
- ...{
356
- 0: {
357
- className: "xjp7ctv"
358
- },
359
- 1: {
360
- className: "xjp7ctv x19co3pv"
361
- }
362
- }[!!isLoadingState << 0],
400
+ ...stylex.props(styles.contentWrapper, isLoadingState && (delaySpinner ? loadingStyles.hiddenContentDelayed : loadingStyles.hiddenContent)),
363
401
  "aria-hidden": isLoadingState || undefined,
364
402
  children: [icon && /*#__PURE__*/_jsx("span", {
365
403
  ...stylex.props(styles.iconWrapper, iconSizeStyles[size]),
@@ -1 +1 @@
1
- {"version":3,"file":"ChatLayoutScrollButton.d.ts","sourceRoot":"","sources":["../../src/Chat/ChatLayoutScrollButton.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAY1B,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAO5C,MAAM,WAAW,2BAA4B,SAAQ,IAAI,CACvD,SAAS,CAAC,cAAc,CAAC,EACzB,SAAS,CACV;IACC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC,qCAAqC;IACrC,SAAS,EAAE,OAAO,CAAC;IACnB,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qBAAqB;IACrB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAkDD;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,EACrC,GAAG,EACH,SAAS,EACT,KAAK,EACL,OAAO,EACP,MAAM,EACN,SAAS,EACT,KAAK,GACN,EAAE,2BAA2B,qBAwB7B;yBAhCe,sBAAsB"}
1
+ {"version":3,"file":"ChatLayoutScrollButton.d.ts","sourceRoot":"","sources":["../../src/Chat/ChatLayoutScrollButton.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAY1B,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAO5C,MAAM,WAAW,2BAA4B,SAAQ,IAAI,CACvD,SAAS,CAAC,cAAc,CAAC,EACzB,SAAS,CACV;IACC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC,qCAAqC;IACrC,SAAS,EAAE,OAAO,CAAC;IACnB,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qBAAqB;IACrB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAwDD;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,EACrC,GAAG,EACH,SAAS,EACT,KAAK,EACL,OAAO,EACP,MAAM,EACN,SAAS,EACT,KAAK,GACN,EAAE,2BAA2B,qBAwB7B;yBAhCe,sBAAsB"}
@@ -43,6 +43,10 @@ const styles = {
43
43
  khDVqt: "xuxw1ft",
44
44
  kg3NbH: "xf314gf",
45
45
  $$css: true
46
+ },
47
+ buttonWithLabel: {
48
+ kwRFfy: "x1t818jl",
49
+ $$css: true
46
50
  }
47
51
  };
48
52
 
@@ -95,7 +99,7 @@ export function ChatLayoutScrollButton({
95
99
  variant: "ghost",
96
100
  size: "md",
97
101
  onClick: onClick,
98
- xstyle: styles.button,
102
+ xstyle: [styles.button, label ? styles.buttonWithLabel : null],
99
103
  children: label ?? undefined
100
104
  })
101
105
  })
@@ -27,7 +27,7 @@
27
27
  import React, { useCallback, useEffect, useId, useMemo, useRef, useState } from 'react';
28
28
  import * as stylex from '@stylexjs/stylex';
29
29
  import { useLayer } from "../Layer/useLayer.js";
30
- import { renderXDSDropdownItems } from "../DropdownMenu/renderXDSDropdownItems.js";
30
+ import { renderDropdownItems } from "../DropdownMenu/renderDropdownItems.js";
31
31
  import { DropdownMenuContext } from "../DropdownMenu/DropdownMenuContext.js";
32
32
  import { useListFocus } from "../hooks/useListFocus.js";
33
33
  import { layerAnimations } from "../Layer/layerAnimations.stylex.js";
@@ -199,7 +199,7 @@ export function ContextMenu({
199
199
  closeMenu,
200
200
  menuSize: size
201
201
  }), [closeMenu, size]);
202
- const resolvedMenuContent = props.items !== undefined ? renderXDSDropdownItems(items) : menuContent;
202
+ const resolvedMenuContent = props.items !== undefined ? renderDropdownItems(items) : menuContent;
203
203
  return /*#__PURE__*/_jsxs(_Fragment, {
204
204
  children: [/*#__PURE__*/_jsx("div", {
205
205
  ref: ref,
@@ -26,7 +26,7 @@ import * as stylex from '@stylexjs/stylex';
26
26
  import { usePopover } from "../Popover/usePopover.js";
27
27
  import { Button } from "../Button/index.js";
28
28
  import { Icon } from "../Icon/index.js";
29
- import { renderXDSDropdownItems } from "./renderXDSDropdownItems.js";
29
+ import { renderDropdownItems } from "./renderDropdownItems.js";
30
30
  import { DropdownMenuContext } from "./DropdownMenuContext.js";
31
31
  import { useListFocus } from "../hooks/useListFocus.js";
32
32
  import { layerAnimations } from "../Layer/layerAnimations.stylex.js";
@@ -265,7 +265,7 @@ export function DropdownMenu({
265
265
  }), [closeMenu, menuSize]);
266
266
 
267
267
  // Resolve menu content: data-driven items become components
268
- const menuContent = props.items !== undefined ? renderXDSDropdownItems(items) : children;
268
+ const menuContent = props.items !== undefined ? renderDropdownItems(items) : children;
269
269
  return /*#__PURE__*/_jsxs(_Fragment, {
270
270
  children: [/*#__PURE__*/_jsx(Button, {
271
271
  ...button,
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @file renderXDSDropdownItems.tsx
2
+ * @file renderDropdownItems.tsx
3
3
  * @output Converts data-driven menu items into DropdownMenuItem components
4
4
  * @position Utility; used by DropdownMenu to unify data-driven and compound paths
5
5
  */
@@ -9,5 +9,5 @@ import type { DropdownMenuOption } from './DropdownMenu';
9
9
  * Converts data-driven items into DropdownMenuItem components,
10
10
  * so both modes share the same rendering and keyboard navigation path.
11
11
  */
12
- export declare function renderXDSDropdownItems(items: DropdownMenuOption[]): ReactNode;
13
- //# sourceMappingURL=renderXDSDropdownItems.d.ts.map
12
+ export declare function renderDropdownItems(items: DropdownMenuOption[]): ReactNode;
13
+ //# sourceMappingURL=renderDropdownItems.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renderDropdownItems.d.ts","sourceRoot":"","sources":["../../src/DropdownMenu/renderDropdownItems.tsx"],"names":[],"mappings":"AAEA;;;;GAIG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,OAAO,CAAC;AAUrC,OAAO,KAAK,EAEV,kBAAkB,EAEnB,MAAM,gBAAgB,CAAC;AAyBxB;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,kBAAkB,EAAE,GAC1B,SAAS,CA8CX"}
@@ -1,7 +1,7 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
2
 
3
3
  /**
4
- * @file renderXDSDropdownItems.tsx
4
+ * @file renderDropdownItems.tsx
5
5
  * @output Converts data-driven menu items into DropdownMenuItem components
6
6
  * @position Utility; used by DropdownMenu to unify data-driven and compound paths
7
7
  */
@@ -29,7 +29,7 @@ function getSectionKey(section, index) {
29
29
  * Converts data-driven items into DropdownMenuItem components,
30
30
  * so both modes share the same rendering and keyboard navigation path.
31
31
  */
32
- export function renderXDSDropdownItems(items) {
32
+ export function renderDropdownItems(items) {
33
33
  const elements = [];
34
34
  for (let i = 0; i < items.length; i++) {
35
35
  const option = items[i];
@@ -1 +1 @@
1
- {"version":3,"file":"EmptyState.d.ts","sourceRoot":"","sources":["../../src/EmptyState/EmptyState.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAC,KAAK,SAAS,EAAgB,MAAM,OAAO,CAAC;AAQpD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AA4D5C,MAAM,WAAW,eAAgB,SAAQ,SAAS,CAAC,cAAc,CAAC;IAChE,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB;;;OAGG;IACH,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB;;;;OAIG;IACH,YAAY,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACrC;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,WAAW,EACX,IAAI,EACJ,OAAO,EACP,YAAgB,EAChB,SAAiB,EACjB,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,EACH,GAAG,KAAK,EACT,EAAE,eAAe,+BA0CjB;yBAtDe,UAAU"}
1
+ {"version":3,"file":"EmptyState.d.ts","sourceRoot":"","sources":["../../src/EmptyState/EmptyState.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAC,KAAK,SAAS,EAAgB,MAAM,OAAO,CAAC;AAQpD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AA4D5C,MAAM,WAAW,eAAgB,SAAQ,SAAS,CAAC,cAAc,CAAC;IAChE,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB;;;OAGG;IACH,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB;;;;OAIG;IACH,YAAY,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACrC;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,WAAW,EACX,IAAI,EACJ,OAAO,EACP,YAAgB,EAChB,SAAiB,EACjB,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,EACH,GAAG,KAAK,EACT,EAAE,eAAe,+BA8CjB;yBA1De,UAAU"}
@@ -96,7 +96,13 @@ export function EmptyState({
96
96
  1: {
97
97
  className: "x1ghz6dp xjb2p0i x2mo6ok xf74fhv x1tgivj0 xcr08ib"
98
98
  }
99
- }[!!isCompact << 0], title), description != null && /*#__PURE__*/_jsx("p", {
99
+ }[!!isCompact << 0], title), description != null &&
100
+ /*#__PURE__*/
101
+ // Rendered as <div> (not <p>): description accepts ReactNode and a
102
+ // <p> cannot legally contain block children, which causes hydration
103
+ // mismatches. The StyleX style sets margin: 0, so appearance is
104
+ // unchanged.
105
+ _jsx("div", {
100
106
  ...{
101
107
  0: {
102
108
  className: "x1ghz6dp xjb2p0i xjm74w1 x1sodnla xw6l6zx xv1l7n4"
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * @file HoverCard.tsx
3
- * @input Uses React, ReactDOM createPortal, useHoverCard hook
3
+ * @input Uses React, useHoverCard hook
4
4
  * @output Exports HoverCard component for hover/focus triggered layers
5
- * @position Layer component; uses inline-safe trigger wrapper and portals floating layer
5
+ * @position Layer component; uses inline-safe trigger wrapper and renders the floating layer inline
6
6
  *
7
7
  * SYNC: When modified, update these files to stay in sync:
8
8
  * - /packages/core/src/HoverCard/HoverCard.test.tsx
@@ -1 +1 @@
1
- {"version":3,"file":"HoverCard.d.ts","sourceRoot":"","sources":["../../src/HoverCard/HoverCard.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;GAWG;AAEH,OAAc,EAGZ,KAAK,YAAY,EACjB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAIf,OAAO,EAAe,KAAK,qBAAqB,EAAC,MAAM,gBAAgB,CAAC;AACxE,OAAO,KAAK,EAAC,cAAc,EAAE,cAAc,EAAC,MAAM,mBAAmB,CAAC;AACtE,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAG5C,YAAY,EAAC,qBAAqB,EAAC,MAAM,gBAAgB,CAAC;AAiB1D,MAAM,WAAW,cAAe,SAAQ,IAAI,CAC1C,SAAS,EACT,QAAQ,GAAG,WAAW,GAAG,OAAO,CACjC;IACC;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;IAEpB;;OAEG;IACH,OAAO,EAAE,SAAS,CAAC;IAEnB;;;OAGG;IACH,SAAS,CAAC,EAAE,cAAc,CAAC;IAE3B;;;OAGG;IACH,SAAS,CAAC,EAAE,cAAc,CAAC;IAE3B;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,qBAAqB,CAAC;IAErC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;OAGG;IACH,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IAEzC;;;;;;;OAOG;IACH,kBAAkB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAEtC;;;;;OAKG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAiBD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,SAAS,CAAC,EACxB,QAAQ,EACR,OAAO,EACP,SAAmB,EACnB,SAAoB,EACpB,KAAW,EACX,SAAe,EACf,YAAqB,EACrB,SAAgB,EAChB,YAAY,EACZ,kBAA2B,EAC3B,MAAM,EACN,aAAa,EACb,MAAM,EACN,SAAS,EACT,KAAK,GACN,EAAE,cAAc,GAAG,YAAY,CAsG/B;yBAtHe,SAAS"}
1
+ {"version":3,"file":"HoverCard.d.ts","sourceRoot":"","sources":["../../src/HoverCard/HoverCard.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAsB,KAAK,YAAY,EAAE,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAG7E,OAAO,EAAe,KAAK,qBAAqB,EAAC,MAAM,gBAAgB,CAAC;AACxE,OAAO,KAAK,EAAC,cAAc,EAAE,cAAc,EAAC,MAAM,mBAAmB,CAAC;AACtE,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAG5C,YAAY,EAAC,qBAAqB,EAAC,MAAM,gBAAgB,CAAC;AAiB1D,MAAM,WAAW,cAAe,SAAQ,IAAI,CAC1C,SAAS,EACT,QAAQ,GAAG,WAAW,GAAG,OAAO,CACjC;IACC;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;IAEpB;;OAEG;IACH,OAAO,EAAE,SAAS,CAAC;IAEnB;;;OAGG;IACH,SAAS,CAAC,EAAE,cAAc,CAAC;IAE3B;;;OAGG;IACH,SAAS,CAAC,EAAE,cAAc,CAAC;IAE3B;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,qBAAqB,CAAC;IAErC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;OAGG;IACH,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IAEzC;;;;;;;OAOG;IACH,kBAAkB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAEtC;;;;;OAKG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAiBD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,SAAS,CAAC,EACxB,QAAQ,EACR,OAAO,EACP,SAAmB,EACnB,SAAoB,EACpB,KAAW,EACX,SAAe,EACf,YAAqB,EACrB,SAAgB,EAChB,YAAY,EACZ,kBAA2B,EAC3B,MAAM,EACN,aAAa,EACb,MAAM,EACN,SAAS,EACT,KAAK,GACN,EAAE,cAAc,GAAG,YAAY,CAgH/B;yBAhIe,SAAS"}