@ai-matrx/design-system 0.86.349 → 0.86.351

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 (96) hide show
  1. package/CHANGELOG.md +22 -2
  2. package/dist/carousel.cjs.map +1 -1
  3. package/dist/carousel.js +5 -5
  4. package/dist/chunk-4WSXAP24.js +51 -0
  5. package/dist/chunk-4WSXAP24.js.map +1 -0
  6. package/dist/{chunk-XTP6HOB6.js → chunk-6XNYYROM.js} +1 -1
  7. package/dist/chunk-6XNYYROM.js.map +1 -0
  8. package/dist/{chunk-CEA6X445.js → chunk-CFUXEGW2.js} +2 -2
  9. package/dist/{chunk-54UK6P7E.js → chunk-FLWSEDUW.js} +3 -3
  10. package/dist/{chunk-BC7LMEOD.js → chunk-GJ6UGQ4X.js} +7 -3
  11. package/dist/chunk-GJ6UGQ4X.js.map +1 -0
  12. package/dist/{chunk-6CDAHINE.js → chunk-GMNROZQJ.js} +4 -4
  13. package/dist/{chunk-6CDAHINE.js.map → chunk-GMNROZQJ.js.map} +1 -1
  14. package/dist/{chunk-6QKT52FR.js → chunk-MTE6N7XU.js} +2 -2
  15. package/dist/{chunk-S6F34AX5.js → chunk-QA7EHFRX.js} +2 -2
  16. package/dist/{chunk-CJBSBKG5.js → chunk-SOCNWQMX.js} +2 -2
  17. package/dist/{chunk-GLLPO66A.js → chunk-U46XUQI7.js} +2 -2
  18. package/dist/{chunk-KYH42WEX.js → chunk-UGQRAQTE.js} +433 -344
  19. package/dist/chunk-UGQRAQTE.js.map +1 -0
  20. package/dist/{chunk-TWRC7NP4.js → chunk-WUD23YTG.js} +4 -4
  21. package/dist/{chunk-MIJMP4WI.js → chunk-YRF22M5S.js} +6 -1
  22. package/dist/{chunk-MIJMP4WI.js.map → chunk-YRF22M5S.js.map} +1 -1
  23. package/dist/clipboard-fallback-dialog.cjs.map +1 -1
  24. package/dist/clipboard-fallback-dialog.js +1 -1
  25. package/dist/controls.cjs +547 -458
  26. package/dist/controls.cjs.map +1 -1
  27. package/dist/controls.css +52 -18
  28. package/dist/controls.d.cts +51 -3
  29. package/dist/controls.d.ts +51 -3
  30. package/dist/controls.js +13 -5
  31. package/dist/data-table/data-row-inspector.cjs.map +1 -1
  32. package/dist/data-table/data-row-inspector.js +4 -4
  33. package/dist/data-table/data-row-window.cjs.map +1 -1
  34. package/dist/data-table/data-row-window.js +5 -5
  35. package/dist/data-table/index.cjs +53 -43
  36. package/dist/data-table/index.cjs.map +1 -1
  37. package/dist/data-table/index.js +52 -45
  38. package/dist/data-table/index.js.map +1 -1
  39. package/dist/data-table/pagination.cjs.map +1 -1
  40. package/dist/data-table/pagination.js +2 -2
  41. package/dist/data-table/spreadsheet.cjs +6 -2
  42. package/dist/data-table/spreadsheet.cjs.map +1 -1
  43. package/dist/data-table/spreadsheet.d.cts +4 -1
  44. package/dist/data-table/spreadsheet.d.ts +4 -1
  45. package/dist/data-table/spreadsheet.js +3 -1
  46. package/dist/data-table/uuid-cell.cjs.map +1 -1
  47. package/dist/data-table/uuid-cell.js +2 -2
  48. package/dist/desktop.cjs +158 -16
  49. package/dist/desktop.cjs.map +1 -1
  50. package/dist/desktop.css +46 -0
  51. package/dist/desktop.d.cts +6 -5
  52. package/dist/desktop.d.ts +6 -5
  53. package/dist/desktop.js +127 -17
  54. package/dist/desktop.js.map +1 -1
  55. package/dist/index.cjs +19 -9
  56. package/dist/index.cjs.map +1 -1
  57. package/dist/index.d.cts +10 -1
  58. package/dist/index.d.ts +10 -1
  59. package/dist/index.js +21 -14
  60. package/dist/index.js.map +1 -1
  61. package/dist/item.cjs.map +1 -1
  62. package/dist/item.js +2 -2
  63. package/dist/lite-table.cjs.map +1 -1
  64. package/dist/lite-table.js +1 -1
  65. package/dist/notice-stack.cjs +70 -0
  66. package/dist/notice-stack.cjs.map +1 -0
  67. package/dist/notice-stack.d.cts +60 -0
  68. package/dist/notice-stack.d.ts +60 -0
  69. package/dist/notice-stack.js +16 -0
  70. package/dist/notice-stack.js.map +1 -0
  71. package/dist/record-list.cjs.map +1 -1
  72. package/dist/record-list.js +2 -2
  73. package/dist/settings.cjs +2 -2
  74. package/dist/settings.cjs.map +1 -1
  75. package/dist/settings.js +3 -3
  76. package/dist/swipe-deck.cjs +95 -25
  77. package/dist/swipe-deck.cjs.map +1 -1
  78. package/dist/swipe-deck.css +14 -0
  79. package/dist/swipe-deck.d.cts +20 -0
  80. package/dist/swipe-deck.d.ts +20 -0
  81. package/dist/swipe-deck.js +87 -25
  82. package/dist/swipe-deck.js.map +1 -1
  83. package/dist/writing-field.cjs +2 -2
  84. package/dist/writing-field.cjs.map +1 -1
  85. package/dist/writing-field.js +2 -2
  86. package/package.json +12 -18
  87. package/dist/chunk-BC7LMEOD.js.map +0 -1
  88. package/dist/chunk-KYH42WEX.js.map +0 -1
  89. package/dist/chunk-XTP6HOB6.js.map +0 -1
  90. /package/dist/{chunk-CEA6X445.js.map → chunk-CFUXEGW2.js.map} +0 -0
  91. /package/dist/{chunk-54UK6P7E.js.map → chunk-FLWSEDUW.js.map} +0 -0
  92. /package/dist/{chunk-6QKT52FR.js.map → chunk-MTE6N7XU.js.map} +0 -0
  93. /package/dist/{chunk-S6F34AX5.js.map → chunk-QA7EHFRX.js.map} +0 -0
  94. /package/dist/{chunk-CJBSBKG5.js.map → chunk-SOCNWQMX.js.map} +0 -0
  95. /package/dist/{chunk-GLLPO66A.js.map → chunk-U46XUQI7.js.map} +0 -0
  96. /package/dist/{chunk-TWRC7NP4.js.map → chunk-WUD23YTG.js.map} +0 -0
package/dist/desktop.css CHANGED
@@ -1281,3 +1281,49 @@
1281
1281
  [data-slot="scope-bar"]::-webkit-scrollbar {
1282
1282
  display: none;
1283
1283
  }
1284
+
1285
+ /* ---------- The notice stack (layout.tsx Notices, ../notice-stack.ts) ----------
1286
+ A macOS notification card: a 14 pt rounded panel of the popover's translucent, blurred material
1287
+ with its shadow, floating in the frame's top-right corner. The tone lives in the icon only, so an
1288
+ error is a small card with a red glyph, never a red bar across the window. */
1289
+ /* The stack: out of the flow, in the frame's top-right corner (the frame is `relative`), never wider
1290
+ than the frame; it lets clicks through between its cards. */
1291
+ [data-slot="notices"][data-float] {
1292
+ position: absolute;
1293
+ top: 12px;
1294
+ right: 12px;
1295
+ z-index: 40;
1296
+ max-width: calc(100% - 24px);
1297
+ pointer-events: none;
1298
+ }
1299
+ [data-slot="notices"][data-float] > * {
1300
+ pointer-events: auto;
1301
+ }
1302
+ [data-slot="banner"][data-float] {
1303
+ border-radius: 14px;
1304
+ background: var(--mx-popover);
1305
+ -webkit-backdrop-filter: blur(30px) saturate(1.8);
1306
+ backdrop-filter: blur(30px) saturate(1.8);
1307
+ box-shadow: var(--mx-shadow-popover);
1308
+ color: var(--mx-label);
1309
+ padding: 10px 10px 10px 12px;
1310
+ }
1311
+ /* Inside the card the title is one line cut with an ellipsis and the line at most two, so a long
1312
+ notice never runs past the card or under its ×. Plain CSS here (not utility classes) so every
1313
+ host's build draws it. */
1314
+ [data-slot="banner"][data-float] [data-slot="banner-title"] {
1315
+ display: block;
1316
+ overflow: hidden;
1317
+ text-overflow: ellipsis;
1318
+ white-space: nowrap;
1319
+ }
1320
+ [data-slot="banner"][data-float] [data-slot="banner-message"] {
1321
+ display: -webkit-box;
1322
+ -webkit-line-clamp: 2;
1323
+ -webkit-box-orient: vertical;
1324
+ overflow: hidden;
1325
+ overflow-wrap: anywhere;
1326
+ }
1327
+ [data-slot="banner"][data-float] [data-slot="banner-text"] {
1328
+ flex-basis: 0;
1329
+ }
@@ -238,9 +238,8 @@ interface PageProps extends React.HTMLAttributes<HTMLDivElement> {
238
238
  width?: PageWidth;
239
239
  /** The page header; drawn at the top of the scrolling column. */
240
240
  header?: React.ReactNode;
241
- /** Banners (errors, "Not live", a result, a selection bar). They sit in the page's foot bar, in
242
- * the layout flow, never over content; the scrolling column's top never moves when one appears
243
- * or goes. The lint refuses a Banner anywhere else on a page. */
241
+ /** Banners (errors, "Not live", a result). They float as small cards in the page's top-right
242
+ * corner (Notices), never a bar across it. The lint refuses a Banner anywhere else on a page. */
244
243
  notices?: React.ReactNode;
245
244
  /** A leading source list inside the page (Console's devices and reports, System Information's
246
245
  * categories): a fixed column with its own scroll, a hairline on its trailing edge. */
@@ -265,7 +264,7 @@ declare function Notices({ children, className, onHeight, ...props }: React.HTML
265
264
  declare function NoticeSlot({ children, className, ...props }: React.HTMLAttributes<HTMLDivElement>): React.JSX.Element;
266
265
  /**
267
266
  * One scrolling content page: 20 px window margins, the HIG spacing scale (20 px between groups),
268
- * and its notices in a foot bar below the scrolling column (see Notices).
267
+ * and its notices as small cards in its top-right corner (see Notices).
269
268
  */
270
269
  declare const Page: React.ForwardRefExoticComponent<PageProps & React.RefAttributes<HTMLDivElement>>;
271
270
  interface PageHeaderProps extends Omit<React.HTMLAttributes<HTMLElement>, "title"> {
@@ -2194,12 +2193,14 @@ interface BannerProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "title"
2194
2193
  detail?: string;
2195
2194
  /** Shows the close (×) button: for notices the person can put away. */
2196
2195
  onDismiss?: () => void;
2196
+ /** How many identical notices this card stands for (the stack collapses them, Notices). */
2197
+ count?: number;
2197
2198
  }
2198
2199
  /**
2199
2200
  * THE inline notice (one pattern, every screen): the tone's icon, a semantic tint, one fixed
2200
2201
  * minimum height, the title and one line, trailing actions, and × when it can be put away.
2201
2202
  */
2202
- declare function Banner({ tone, icon, title, message, actions, detail, onDismiss, className, ...props }: BannerProps): React.JSX.Element;
2203
+ declare function Banner({ tone, icon, title, message, actions, detail, onDismiss, count, className, ...props }: BannerProps): React.JSX.Element | null;
2203
2204
  interface ErrorBannerProps extends Omit<BannerProps, "tone" | "title" | "message" | "actions" | "detail" | "onDismiss"> {
2204
2205
  /** The failed action's error (e.g. `useDesktopAction().error`); nothing renders without one. */
2205
2206
  error: {
package/dist/desktop.d.ts CHANGED
@@ -238,9 +238,8 @@ interface PageProps extends React.HTMLAttributes<HTMLDivElement> {
238
238
  width?: PageWidth;
239
239
  /** The page header; drawn at the top of the scrolling column. */
240
240
  header?: React.ReactNode;
241
- /** Banners (errors, "Not live", a result, a selection bar). They sit in the page's foot bar, in
242
- * the layout flow, never over content; the scrolling column's top never moves when one appears
243
- * or goes. The lint refuses a Banner anywhere else on a page. */
241
+ /** Banners (errors, "Not live", a result). They float as small cards in the page's top-right
242
+ * corner (Notices), never a bar across it. The lint refuses a Banner anywhere else on a page. */
244
243
  notices?: React.ReactNode;
245
244
  /** A leading source list inside the page (Console's devices and reports, System Information's
246
245
  * categories): a fixed column with its own scroll, a hairline on its trailing edge. */
@@ -265,7 +264,7 @@ declare function Notices({ children, className, onHeight, ...props }: React.HTML
265
264
  declare function NoticeSlot({ children, className, ...props }: React.HTMLAttributes<HTMLDivElement>): React.JSX.Element;
266
265
  /**
267
266
  * One scrolling content page: 20 px window margins, the HIG spacing scale (20 px between groups),
268
- * and its notices in a foot bar below the scrolling column (see Notices).
267
+ * and its notices as small cards in its top-right corner (see Notices).
269
268
  */
270
269
  declare const Page: React.ForwardRefExoticComponent<PageProps & React.RefAttributes<HTMLDivElement>>;
271
270
  interface PageHeaderProps extends Omit<React.HTMLAttributes<HTMLElement>, "title"> {
@@ -2194,12 +2193,14 @@ interface BannerProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "title"
2194
2193
  detail?: string;
2195
2194
  /** Shows the close (×) button: for notices the person can put away. */
2196
2195
  onDismiss?: () => void;
2196
+ /** How many identical notices this card stands for (the stack collapses them, Notices). */
2197
+ count?: number;
2197
2198
  }
2198
2199
  /**
2199
2200
  * THE inline notice (one pattern, every screen): the tone's icon, a semantic tint, one fixed
2200
2201
  * minimum height, the title and one line, trailing actions, and × when it can be put away.
2201
2202
  */
2202
- declare function Banner({ tone, icon, title, message, actions, detail, onDismiss, className, ...props }: BannerProps): React.JSX.Element;
2203
+ declare function Banner({ tone, icon, title, message, actions, detail, onDismiss, count, className, ...props }: BannerProps): React.JSX.Element | null;
2203
2204
  interface ErrorBannerProps extends Omit<BannerProps, "tone" | "title" | "message" | "actions" | "detail" | "onDismiss"> {
2204
2205
  /** The failed action's error (e.g. `useDesktopAction().error`); nothing renders without one. */
2205
2206
  error: {
package/dist/desktop.js CHANGED
@@ -1,4 +1,10 @@
1
1
  "use client";
2
+ import {
3
+ NOTICE_STACK,
4
+ collapseNotices,
5
+ noticeKey,
6
+ visibleNotices
7
+ } from "./chunk-4WSXAP24.js";
2
8
  import {
3
9
  AppRail,
4
10
  AppRailAvatar,
@@ -13,7 +19,7 @@ import {
13
19
  matchesOrganizationQuery,
14
20
  orderOrganizationsForPicker,
15
21
  organizationColor
16
- } from "./chunk-54UK6P7E.js";
22
+ } from "./chunk-FLWSEDUW.js";
17
23
  import {
18
24
  Collapsible,
19
25
  CollapsibleContent,
@@ -35,7 +41,7 @@ import {
35
41
  import "./chunk-VQQ3O7J5.js";
36
42
  import {
37
43
  Tile
38
- } from "./chunk-6CDAHINE.js";
44
+ } from "./chunk-GMNROZQJ.js";
39
45
  import "./chunk-HKLIRHT2.js";
40
46
  import {
41
47
  Skeleton
@@ -65,7 +71,7 @@ import {
65
71
  } from "./chunk-OPF265PU.js";
66
72
  import {
67
73
  Button
68
- } from "./chunk-XTP6HOB6.js";
74
+ } from "./chunk-6XNYYROM.js";
69
75
  import "./chunk-BD77DHUO.js";
70
76
  import "./chunk-BKCJUFD3.js";
71
77
  import {
@@ -1114,16 +1120,78 @@ var WIDTH = {
1114
1120
  wide: "max-w-none",
1115
1121
  full: "max-w-none"
1116
1122
  };
1117
- function hasNotices(children) {
1118
- return React8.Children.toArray(children).some((c) => React8.isValidElement(c) && c.type === React8.Fragment ? hasNotices(c.props.children) : Boolean(c));
1123
+ var EMPTY_LAYOUT = { drawn: /* @__PURE__ */ new Map(), folded: 0, total: 0 };
1124
+ function createNoticeRegistry() {
1125
+ let entries = [];
1126
+ let expanded = false;
1127
+ let layout = EMPTY_LAYOUT;
1128
+ const listeners = /* @__PURE__ */ new Set();
1129
+ const recompute = () => {
1130
+ const groups = collapseNotices(entries, (e) => e.key);
1131
+ const { shown, folded } = expanded ? { shown: groups, folded: 0 } : visibleNotices(groups);
1132
+ const drawn = /* @__PURE__ */ new Map();
1133
+ for (const g of shown) {
1134
+ const dismissers = g.members.map((m) => m.dismiss).filter((d) => typeof d === "function");
1135
+ drawn.set(g.item.id, { count: g.count, dismissAll: g.item.dismiss ? () => dismissers.forEach((d) => d()) : void 0 });
1136
+ }
1137
+ layout = { drawn, folded, total: entries.length };
1138
+ listeners.forEach((l) => l());
1139
+ };
1140
+ return {
1141
+ set(id, key2, dismiss) {
1142
+ const at = entries.findIndex((e) => e.id === id);
1143
+ if (at >= 0) {
1144
+ const old = entries[at];
1145
+ if (old.key === key2 && old.dismiss === dismiss) return;
1146
+ entries = entries.map((e, i) => i === at ? { id, key: key2, dismiss } : e);
1147
+ } else {
1148
+ entries = [...entries, { id, key: key2, dismiss }];
1149
+ }
1150
+ recompute();
1151
+ },
1152
+ remove(id) {
1153
+ if (!entries.some((e) => e.id === id)) return;
1154
+ entries = entries.filter((e) => e.id !== id);
1155
+ if (entries.length === 0) expanded = false;
1156
+ recompute();
1157
+ },
1158
+ subscribe(listener) {
1159
+ listeners.add(listener);
1160
+ return () => listeners.delete(listener);
1161
+ },
1162
+ snapshot: () => layout,
1163
+ expand() {
1164
+ expanded = true;
1165
+ recompute();
1166
+ }
1167
+ };
1168
+ }
1169
+ var NoticeStackContext = React8.createContext(null);
1170
+ function useNoticeStackLayout(registry) {
1171
+ return React8.useSyncExternalStore(
1172
+ React8.useCallback((l) => registry ? registry.subscribe(l) : () => void 0, [registry]),
1173
+ () => registry ? registry.snapshot() : EMPTY_LAYOUT,
1174
+ () => registry ? registry.snapshot() : EMPTY_LAYOUT
1175
+ );
1176
+ }
1177
+ function bannerNoticeKey(tone, title, message) {
1178
+ if (typeof title !== "string" && typeof title !== "number") return null;
1179
+ return noticeKey(tone, title, message);
1180
+ }
1181
+ function holdsElements(children) {
1182
+ return React8.Children.toArray(children).some(
1183
+ (c) => React8.isValidElement(c) && c.type === React8.Fragment ? holdsElements(c.props.children) : React8.isValidElement(c)
1184
+ );
1119
1185
  }
1120
1186
  function Notices({ children, className, onHeight, ...props }) {
1121
1187
  const stack = React8.useRef(null);
1122
- const drawn = hasNotices(children);
1188
+ const [registry] = React8.useState(createNoticeRegistry);
1189
+ const layout = useNoticeStackLayout(registry);
1190
+ const drawn = layout.total > 0;
1123
1191
  React8.useLayoutEffect(() => {
1124
1192
  const el = stack.current;
1125
1193
  if (!onHeight) return;
1126
- if (!el) return onHeight(0);
1194
+ if (!el || !drawn) return onHeight(0);
1127
1195
  const report = () => onHeight(el.offsetHeight);
1128
1196
  report();
1129
1197
  if (typeof ResizeObserver === "undefined") return;
@@ -1134,8 +1202,27 @@ function Notices({ children, className, onHeight, ...props }) {
1134
1202
  onHeight(0);
1135
1203
  };
1136
1204
  }, [onHeight, drawn]);
1137
- if (!drawn) return null;
1138
- return /* @__PURE__ */ jsx11("div", { ref: stack, "data-slot": "notices", "aria-live": "polite", className: cn2("flex shrink-0 flex-col gap-2 empty:hidden", className), ...props, children });
1205
+ if (!holdsElements(children)) return null;
1206
+ return /* @__PURE__ */ jsx11(
1207
+ "div",
1208
+ {
1209
+ ref: stack,
1210
+ "data-slot": "notices",
1211
+ "data-float": "",
1212
+ "aria-live": "polite",
1213
+ hidden: !drawn || void 0,
1214
+ style: { width: `${NOTICE_STACK.widthRem}rem` },
1215
+ className: cn2("flex flex-col items-stretch gap-2 empty:hidden", className),
1216
+ ...props,
1217
+ children: /* @__PURE__ */ jsxs7(NoticeStackContext.Provider, { value: registry, children: [
1218
+ layout.folded > 0 ? /* @__PURE__ */ jsx11("button", { type: "button", "data-slot": "notices-more", className: "order-first self-end rounded-full px-2 py-0.5", onClick: () => registry.expand(), children: /* @__PURE__ */ jsxs7(Text, { variant: "caption", tone: "secondary", children: [
1219
+ layout.folded,
1220
+ " more"
1221
+ ] }) }) : null,
1222
+ children
1223
+ ] })
1224
+ }
1225
+ );
1139
1226
  }
1140
1227
  function NoticeSlot({ children, className, ...props }) {
1141
1228
  return /* @__PURE__ */ jsx11("div", { "data-slot": "notice-slot", "aria-live": "polite", className: cn2("h-16 shrink-0 overflow-hidden [&>*]:h-full [&>*]:overflow-hidden", className), ...props, children });
@@ -1143,14 +1230,14 @@ function NoticeSlot({ children, className, ...props }) {
1143
1230
  var Page = React8.forwardRef(function Page2({ width = "wide", header, notices, sidebar, scopeBar, footer, flush, className, children, ...props }, ref) {
1144
1231
  const frame = (
1145
1232
  // The frame is always there (with or without notices), so a notice never remounts the page.
1146
- /* @__PURE__ */ jsxs7("div", { "data-slot": "page-frame", className: "flex h-full min-w-0 flex-1 flex-col bg-content", children: [
1233
+ /* @__PURE__ */ jsxs7("div", { "data-slot": "page-frame", className: "relative flex h-full min-w-0 flex-1 flex-col bg-content", children: [
1147
1234
  scopeBar ? /* @__PURE__ */ jsx11("div", { "data-slot": "page-scope-bar", className: "flex h-control-lg shrink-0 items-center gap-2 border-b border-separator px-3", children: scopeBar }) : null,
1148
1235
  /* @__PURE__ */ jsx11("div", { ref, "data-slot": "page", "data-flush": flush || void 0, className: cn2("min-h-0 flex-1 overflow-y-auto bg-content", className), ...props, children: /* @__PURE__ */ jsxs7("div", { className: cn2("flex w-full flex-col", flush ? "min-h-full" : "gap-5 px-5 pb-5 pt-3", WIDTH[width]), children: [
1149
1236
  header,
1150
1237
  children
1151
1238
  ] }) }),
1152
1239
  footer ? /* @__PURE__ */ jsx11("div", { "data-slot": "page-footer", className: "flex shrink-0 flex-col border-t border-separator bg-content", children: footer }) : null,
1153
- /* @__PURE__ */ jsx11(Notices, { "data-page-notices": "", className: "border-t border-separator px-5 py-3", children: notices })
1240
+ /* @__PURE__ */ jsx11(Notices, { "data-page-notices": "", children: notices })
1154
1241
  ] })
1155
1242
  );
1156
1243
  if (!sidebar) return frame;
@@ -3085,22 +3172,45 @@ var BANNER_ICON = {
3085
3172
  danger: /* @__PURE__ */ jsx28(Glyph, { d: ALERT }),
3086
3173
  success: /* @__PURE__ */ jsx28(Glyph, { d: DONE })
3087
3174
  };
3088
- function Banner({ tone, icon, title, message, actions, detail, onDismiss, className, ...props }) {
3175
+ function Banner({ tone, icon, title, message, actions, detail, onDismiss, count, className, ...props }) {
3089
3176
  const [copied, setCopied] = React20.useState(false);
3177
+ const registry = React20.useContext(NoticeStackContext);
3178
+ const floating = registry !== null;
3179
+ const id = React20.useId();
3180
+ const key2 = bannerNoticeKey(tone, title, message);
3181
+ React20.useLayoutEffect(() => {
3182
+ registry?.set(id, key2, onDismiss);
3183
+ }, [registry, id, key2, onDismiss]);
3184
+ React20.useLayoutEffect(() => registry ? () => registry.remove(id) : void 0, [registry, id]);
3185
+ const layout = useNoticeStackLayout(registry);
3186
+ const slot = layout.drawn.get(id);
3187
+ if (floating && !slot) return null;
3188
+ if (slot) {
3189
+ count = Math.max(count ?? 1, slot.count);
3190
+ if (slot.dismissAll) onDismiss = slot.dismissAll;
3191
+ }
3090
3192
  return /* @__PURE__ */ jsxs22(
3091
3193
  "div",
3092
3194
  {
3093
3195
  role: tone === "danger" || tone === "warning" ? "alert" : "status",
3094
3196
  "data-slot": "banner",
3095
3197
  "data-tone": tone,
3096
- className: cn2("flex min-h-row items-center gap-2.5 rounded-group px-3 py-2", BANNER_TONE[tone].box, className),
3198
+ "data-float": floating ? "" : void 0,
3199
+ "data-count": count && count > 1 ? count : void 0,
3200
+ className: cn2("flex min-h-row items-center gap-2.5 rounded-group px-3 py-2", floating ? "items-start" : BANNER_TONE[tone].box, className),
3097
3201
  ...props,
3098
3202
  children: [
3099
3203
  /* @__PURE__ */ jsx28("span", { className: cn2("flex shrink-0 self-start pt-px [&_svg]:size-icon", BANNER_TONE[tone].icon), children: icon ?? BANNER_ICON[tone] }),
3100
3204
  /* @__PURE__ */ jsxs22("div", { "data-slot": "banner-body", className: "flex min-w-0 flex-1 flex-wrap items-center gap-x-3 gap-y-2", children: [
3101
3205
  /* @__PURE__ */ jsxs22("div", { "data-slot": "banner-text", className: "flex min-w-0 flex-1 basis-56 flex-col gap-0.5", title: detail || void 0, children: [
3102
- /* @__PURE__ */ jsx28(Text, { emphasized: true, children: title }),
3103
- message ? /* @__PURE__ */ jsx28(Text, { as: "p", tone: "secondary", selectable: true, children: message }) : null
3206
+ /* @__PURE__ */ jsxs22(Text, { "data-slot": "banner-title", emphasized: true, ...floating && typeof title === "string" ? { title } : {}, children: [
3207
+ title,
3208
+ count && count > 1 ? /* @__PURE__ */ jsxs22("span", { "data-slot": "banner-count", className: "ml-1.5 font-normal text-label-secondary", children: [
3209
+ "\xD7",
3210
+ count
3211
+ ] }) : null
3212
+ ] }),
3213
+ message ? /* @__PURE__ */ jsx28(Text, { "data-slot": "banner-message", as: "p", tone: "secondary", selectable: true, children: message }) : null
3104
3214
  ] }),
3105
3215
  actions || detail ? /* @__PURE__ */ jsxs22("div", { "data-slot": "banner-actions", className: "ml-auto flex shrink-0 items-center gap-2", children: [
3106
3216
  detail ? /* @__PURE__ */ jsx28(
@@ -4392,7 +4502,7 @@ function EndOfList({ onEndReached }) {
4392
4502
  import { jsx as jsx33, jsxs as jsxs27 } from "react/jsx-runtime";
4393
4503
  var LIST_WIDTH = { md: "w-70", lg: "w-85" };
4394
4504
  function SplitView({ header, notices, source, list, listHeader, listFooter, detail, listWidth = "lg", detailScrolls = true, narrow, className, ...props }) {
4395
- return /* @__PURE__ */ jsxs27("div", { "data-slot": "split-view", className: cn2("flex h-full min-h-0 flex-col bg-content", className), ...props, children: [
4505
+ return /* @__PURE__ */ jsxs27("div", { "data-slot": "split-view", className: cn2("relative flex h-full min-h-0 flex-col bg-content", className), ...props, children: [
4396
4506
  header ? /* @__PURE__ */ jsx33("div", { className: "shrink-0 px-5 empty:hidden", children: header }) : null,
4397
4507
  /* @__PURE__ */ jsxs27("div", { "data-slot": "split-columns", "data-narrow": detail !== void 0 ? narrow : void 0, "data-has-source": source ? "" : void 0, className: "flex min-h-0 flex-1", children: [
4398
4508
  source ? /* @__PURE__ */ jsx33("div", { "data-slot": "split-view-source", className: "flex w-52 min-w-40 shrink flex-col overflow-y-auto border-r border-separator py-2", children: source }) : null,
@@ -4403,7 +4513,7 @@ function SplitView({ header, notices, source, list, listHeader, listFooter, deta
4403
4513
  ] }),
4404
4514
  detail !== void 0 ? /* @__PURE__ */ jsx33("div", { "data-slot": "split-view-detail", className: cn2("flex min-w-80 flex-1 flex-col", detailScrolls ? "overflow-y-auto" : "min-h-0"), children: detail }) : null
4405
4515
  ] }),
4406
- /* @__PURE__ */ jsx33(Notices, { "data-page-notices": "", className: "border-t border-separator px-5 py-3", children: notices })
4516
+ /* @__PURE__ */ jsx33(Notices, { "data-page-notices": "", children: notices })
4407
4517
  ] });
4408
4518
  }
4409
4519