@molecule/app-ui-react 1.0.2 → 1.2.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 (32) hide show
  1. package/README.md +521 -1
  2. package/dist/components/ConfirmButton.d.ts +71 -0
  3. package/dist/components/ConfirmButton.d.ts.map +1 -0
  4. package/dist/components/ConfirmButton.js +88 -0
  5. package/dist/components/ConfirmButton.js.map +1 -0
  6. package/dist/components/ConfirmDialog.d.ts +71 -0
  7. package/dist/components/ConfirmDialog.d.ts.map +1 -0
  8. package/dist/components/ConfirmDialog.js +20 -0
  9. package/dist/components/ConfirmDialog.js.map +1 -0
  10. package/dist/components/Icon.d.ts.map +1 -1
  11. package/dist/components/Icon.js +12 -1
  12. package/dist/components/Icon.js.map +1 -1
  13. package/dist/components/LoadErrorBanner.d.ts +71 -0
  14. package/dist/components/LoadErrorBanner.d.ts.map +1 -0
  15. package/dist/components/LoadErrorBanner.js +31 -0
  16. package/dist/components/LoadErrorBanner.js.map +1 -0
  17. package/dist/components/PromptDialog.d.ts +91 -0
  18. package/dist/components/PromptDialog.d.ts.map +1 -0
  19. package/dist/components/PromptDialog.js +90 -0
  20. package/dist/components/PromptDialog.js.map +1 -0
  21. package/dist/components/ResponsiveAppShell.d.ts +327 -0
  22. package/dist/components/ResponsiveAppShell.d.ts.map +1 -0
  23. package/dist/components/ResponsiveAppShell.js +470 -0
  24. package/dist/components/ResponsiveAppShell.js.map +1 -0
  25. package/dist/components/UserMenu.d.ts.map +1 -1
  26. package/dist/components/UserMenu.js +5 -1
  27. package/dist/components/UserMenu.js.map +1 -1
  28. package/dist/components/index.d.ts +5 -0
  29. package/dist/components/index.d.ts.map +1 -1
  30. package/dist/components/index.js +5 -0
  31. package/dist/components/index.js.map +1 -1
  32. package/package.json +2 -2
package/README.md CHANGED
@@ -3,7 +3,7 @@ AUTO-GENERATED — DO NOT EDIT THIS FILE.
3
3
  Generated by `mlcl sync-docs` from the package's src/index.ts JSDoc + mlcl/registry.json.
4
4
  Edits here are overwritten on the next commit (molecule's pre-commit hook regenerates).
5
5
  To change this document, edit the module-level JSDoc in src/index.ts.
6
- Generated: 2026-08-04T01:53:05.300Z
6
+ Generated: 2026-09-24T21:35:36.593Z
7
7
  -->
8
8
 
9
9
  # @molecule/app-ui-react
@@ -423,6 +423,83 @@ interface CheckboxProps extends InputElementProps {
423
423
  }
424
424
  ```
425
425
 
426
+ #### `ConfirmButtonProps`
427
+
428
+ Props for {@link ConfirmButton}.
429
+
430
+ ```typescript
431
+ interface ConfirmButtonProps extends Omit<
432
+ ButtonProps,
433
+ 'onClick' | 'children' | 'onConfirm' | keyof React.DOMAttributes<HTMLButtonElement>
434
+ > {
435
+ /**
436
+ * Fired ONLY on the confirming (second) click — i.e. when the action
437
+ * actually commits. Errors should be handled by the caller (render an
438
+ * inline banner); while the returned promise is pending the button stays
439
+ * in its confirming state and ignores further clicks.
440
+ */
441
+ onConfirm: () => void | Promise<void>
442
+ /**
443
+ * Visible label in the idle (armed-to-be-clicked) state.
444
+ */
445
+ label: React.ReactNode
446
+ /**
447
+ * Visible label in the armed state — the "click again to confirm" step.
448
+ * Defaults to a localized "Confirm?" via the i18n bond.
449
+ */
450
+ confirmLabel?: React.ReactNode
451
+ /**
452
+ * Visible label while {@link onConfirm} is pending. Defaults to a
453
+ * localized "Working…".
454
+ */
455
+ pendingLabel?: React.ReactNode
456
+ /**
457
+ * Seconds before the armed state auto-disarms back to idle. Low-stakes
458
+ * actions tolerate a long window; destructive ones should keep it short.
459
+ * `0` disables auto-disarm (not recommended — a stray click then leaves
460
+ * the button armed forever).
461
+ */
462
+ disarmSeconds?: number
463
+ /**
464
+ * Disable the control entirely (idle and confirming states).
465
+ */
466
+ disabled?: boolean
467
+ /**
468
+ * data-mol-id for the button (all states share one element).
469
+ */
470
+ testId?: string
471
+ }
472
+ ```
473
+
474
+ #### `ConfirmDialogProps`
475
+
476
+ Props for {@link ConfirmDialog}.
477
+
478
+ ```typescript
479
+ interface ConfirmDialogProps {
480
+ /** Whether the dialog is open. */
481
+ open: boolean
482
+ /** Called when the dialog should close (escape, backdrop, cancel). */
483
+ onClose: () => void
484
+ /** Title. */
485
+ title: ReactNode
486
+ /** Body / warning text. */
487
+ description: ReactNode
488
+ /** Confirm-button label (e.g. "Delete"). */
489
+ confirmLabel?: ReactNode
490
+ /** Cancel-button label. */
491
+ cancelLabel?: ReactNode
492
+ /** Called when the user confirms. */
493
+ onConfirm: () => void | Promise<void>
494
+ /** Is the confirm action destructive? Defaults to true. */
495
+ destructive?: boolean
496
+ /** Extra body content between description and footer. */
497
+ children?: ReactNode
498
+ /** Disables both buttons. Set it yourself while your `onConfirm` promise is pending — the dialog does not track it and does not auto-close. */
499
+ loading?: boolean
500
+ }
501
+ ```
502
+
426
503
  #### `ContainerProps`
427
504
 
428
505
  Props for the Container layout component.
@@ -778,6 +855,31 @@ interface LanguagePickerProps extends Omit<
778
855
  }
779
856
  ```
780
857
 
858
+ #### `LoadErrorBannerProps`
859
+
860
+ Props for {@link LoadErrorBanner}.
861
+
862
+ ```typescript
863
+ interface LoadErrorBannerProps extends HTMLElementProps {
864
+ /** The primary error line (e.g. the localized "Could not load X."). */
865
+ message: React.ReactNode
866
+ /** Secondary line under the message (status code, hint). */
867
+ detail?: React.ReactNode
868
+ /**
869
+ * Called when Retry is clicked. Return the promise; while pending, the
870
+ * button is disabled and shows "Retrying…". Omit for a display-only
871
+ * banner.
872
+ */
873
+ onRetry?: () => void | Promise<void>
874
+ /** Retry-button label. Falls back to a localized "Retry". */
875
+ retryLabel?: React.ReactNode
876
+ /** `data-mol-id` for the retry button (default `load-error-retry`). */
877
+ retryMolId?: string
878
+ /** Extra content between message and retry row (e.g. an error code). */
879
+ children?: React.ReactNode
880
+ }
881
+ ```
882
+
781
883
  #### `ModalProps`
782
884
 
783
885
  Props for the Modal/Dialog component.
@@ -944,6 +1046,46 @@ interface ProgressProps extends BaseProps {
944
1046
  }
945
1047
  ```
946
1048
 
1049
+ #### `PromptDialogProps`
1050
+
1051
+ Props for {@link PromptDialog}.
1052
+
1053
+ ```typescript
1054
+ interface PromptDialogProps {
1055
+ /** Whether the dialog is open. */
1056
+ open: boolean
1057
+ /** Called when the dialog should close (escape, backdrop, cancel, or a fulfilled {@link PromptDialogProps.onSubmit}). */
1058
+ onClose: () => void
1059
+ /** Dialog heading. */
1060
+ title: React.ReactNode
1061
+ /** Explanatory line under the title. */
1062
+ description?: React.ReactNode
1063
+ /** Input placeholder. */
1064
+ placeholder?: string
1065
+ /** Value the input starts from every time the dialog opens. */
1066
+ initialValue?: string
1067
+ /**
1068
+ * Called with the entered value on confirm. Resolve to close the dialog;
1069
+ * reject or throw to keep it open (show the error via {@link PromptDialogProps.children}).
1070
+ */
1071
+ onSubmit: (value: string) => void | Promise<void>
1072
+ /** Confirm-button label. Falls back to a localized "Confirm". */
1073
+ confirmLabel?: React.ReactNode
1074
+ /** Cancel-button label. Falls back to a localized "Cancel". */
1075
+ cancelLabel?: React.ReactNode
1076
+ /** Render the confirm button in the error color (e.g. an irreversible reset). */
1077
+ destructive?: boolean
1078
+ /** `data-mol-id` for the text input. */
1079
+ inputMolId?: string
1080
+ /** `data-mol-id` for the confirm button. */
1081
+ confirmMolId?: string
1082
+ /** `data-mol-id` for the cancel button. */
1083
+ cancelMolId?: string
1084
+ /** Extra body content under the input (error banners, hints). */
1085
+ children?: React.ReactNode
1086
+ }
1087
+ ```
1088
+
947
1089
  #### `RadioGroupProps`
948
1090
 
949
1091
  Props for the RadioGroup component.
@@ -1011,6 +1153,151 @@ interface RadioOption<T = string> {
1011
1153
  }
1012
1154
  ```
1013
1155
 
1156
+ #### `ResponsiveAppShellContentProps`
1157
+
1158
+ Props for the {@link ResponsiveAppShellContent} sub-component.
1159
+
1160
+ ```typescript
1161
+ interface ResponsiveAppShellContentProps {
1162
+ /** The routed page content — typically an `<Outlet />`. */
1163
+ children: ReactNode
1164
+ /** Extra classes on the `<main>`. */
1165
+ className?: string
1166
+ /** Inline styles on the `<main>` (rarely needed — layout is owned). */
1167
+ style?: React.CSSProperties
1168
+ /** `data-mol-id` override. Default: `'shell-content'`. */
1169
+ dataMolId?: string
1170
+ /** `data-testid` override. */
1171
+ testId?: string
1172
+ }
1173
+ ```
1174
+
1175
+ #### `ResponsiveAppShellDrawerProps`
1176
+
1177
+ Props for the {@link ResponsiveAppShellDrawer} sub-component.
1178
+
1179
+ ```typescript
1180
+ interface ResponsiveAppShellDrawerProps {
1181
+ /**
1182
+ * Nav content — the links, same as (or adapted from) the Sidebar's. Only
1183
+ * mounted while the drawer is open on a below-breakpoint viewport.
1184
+ */
1185
+ children: ReactNode
1186
+ /**
1187
+ * Header row content (typically the brand), rendered next to the close
1188
+ * button.
1189
+ */
1190
+ header?: ReactNode
1191
+ /**
1192
+ * Accessible name for the dialog and its `<nav>` landmark. Defaults to the
1193
+ * `appShell.primaryNav` translation (English fallback `"Primary
1194
+ * navigation"`).
1195
+ */
1196
+ navLabel?: string
1197
+ /** Below-nav content (user card, sign-out), after the `<nav>`. */
1198
+ footer?: ReactNode
1199
+ /** Whether the panel shows a close (X) button. Default: `true`. */
1200
+ showCloseButton?: boolean
1201
+ /** Extra classes on the dialog panel. */
1202
+ className?: string
1203
+ /** `data-mol-id` override for the panel. Default: `'shell-drawer'`. */
1204
+ dataMolId?: string
1205
+ /** `data-mol-id` override for the close button. Default: `'shell-drawer-close'`. */
1206
+ closeDataMolId?: string
1207
+ /** `data-testid` override for the panel. */
1208
+ testId?: string
1209
+ }
1210
+ ```
1211
+
1212
+ #### `ResponsiveAppShellProps`
1213
+
1214
+ Props for the {@link ResponsiveAppShell} root.
1215
+
1216
+ ```typescript
1217
+ interface ResponsiveAppShellProps {
1218
+ /**
1219
+ * The shell sub-components — `<ResponsiveAppShell.TopBar />`,
1220
+ * `<ResponsiveAppShell.Sidebar />`, `<ResponsiveAppShell.Drawer />` and
1221
+ * `<ResponsiveAppShell.Content />`.
1222
+ */
1223
+ children: ReactNode
1224
+ /**
1225
+ * Sidebar (and drawer) width: `'sm'` (208px), `'md'` (240px, default),
1226
+ * `'lg'` (256px) or an exact pixel number.
1227
+ */
1228
+ sidebarWidth?: ShellSidebarWidth
1229
+ /** Extra classes on the root flex-row container. */
1230
+ className?: string
1231
+ /**
1232
+ * `data-mol-id` for the root container. Defaults to `'shell-root'`.
1233
+ */
1234
+ dataMolId?: string
1235
+ }
1236
+ ```
1237
+
1238
+ #### `ResponsiveAppShellSidebarProps`
1239
+
1240
+ Props for the {@link ResponsiveAppShellSidebar} sub-component.
1241
+
1242
+ ```typescript
1243
+ interface ResponsiveAppShellSidebarProps {
1244
+ /**
1245
+ * Nav content — the links (they land inside the sidebar's `<nav>` landmark;
1246
+ * pass `aria-current="page"` from the active one yourself). Typically the
1247
+ * SAME element variable the Drawer receives, so only the mounted
1248
+ * breakpoint's copy ever instantiates.
1249
+ */
1250
+ children: ReactNode
1251
+ /**
1252
+ * Accessible name for the sidebar's `<nav>` landmark. Defaults to the
1253
+ * `appShell.primaryNav` translation (English fallback `"Primary
1254
+ * navigation"`).
1255
+ */
1256
+ navLabel?: string
1257
+ /**
1258
+ * Below-nav content (user card, quick action) — rendered after the `<nav>`
1259
+ * in a bordered footer row, so it does not sit inside the nav landmark.
1260
+ */
1261
+ footer?: ReactNode
1262
+ /** Extra classes on the `<aside>`. */
1263
+ className?: string
1264
+ /** `data-mol-id` override. Default: `'shell-sidebar'`. */
1265
+ dataMolId?: string
1266
+ /** `data-testid` override. */
1267
+ testId?: string
1268
+ }
1269
+ ```
1270
+
1271
+ #### `ResponsiveAppShellTopBarProps`
1272
+
1273
+ Props for the {@link ResponsiveAppShellTopBar} sub-component.
1274
+
1275
+ ```typescript
1276
+ interface ResponsiveAppShellTopBarProps {
1277
+ /**
1278
+ * Brand/title node, rendered after the menu trigger — typically a
1279
+ * `<Link to="/…">` with the app name or logo. The shell wraps it in a
1280
+ * flex row; style the node itself.
1281
+ */
1282
+ brand?: ReactNode
1283
+ /** Trailing actions — user menu, theme toggle, search, etc. */
1284
+ actions?: ReactNode
1285
+ /**
1286
+ * Render the top bar only below the breakpoint (mount-conditioned, not
1287
+ * CSS-hidden — no dead DOM on desktop). For apps whose desktop shell has
1288
+ * no top bar (e.g. the sidebar carries everything). Default: `false`
1289
+ * (top bar on every breakpoint).
1290
+ */
1291
+ mobileOnly?: boolean
1292
+ /** Extra classes on the `<header>`. */
1293
+ className?: string
1294
+ /** `data-mol-id` override. Default: `'shell-topbar'`. */
1295
+ dataMolId?: string
1296
+ /** `data-testid` override. */
1297
+ testId?: string
1298
+ }
1299
+ ```
1300
+
1014
1301
  #### `SelectElementProps`
1015
1302
 
1016
1303
  Base props for select elements.
@@ -1805,6 +2092,19 @@ Framework-agnostic mouse event handler.
1805
2092
  type MouseEventHandler = EventHandler<MouseEvent>
1806
2093
  ```
1807
2094
 
2095
+ #### `ShellSidebarWidth`
2096
+
2097
+ Semantic sidebar width — the same stack-agnostic presets
2098
+ `@molecule/app-sidebar-layout-react` uses, so both shells render the same
2099
+ fleet geometry: `sm` → 208px, `md` → 240px (default), `lg` → 256px. A raw
2100
+ `number` is an exact pixel width. Applied via inline style (a specific
2101
+ pixel width is the documented "value a swappable ClassMap cannot express
2102
+ as a token" case).
2103
+
2104
+ ```typescript
2105
+ type ShellSidebarWidth = 'sm' | 'md' | 'lg' | number
2106
+ ```
2107
+
1808
2108
  #### `Size`
1809
2109
 
1810
2110
  Standard size scale used across all molecule UI components (buttons, inputs, badges, etc.).
@@ -1864,6 +2164,30 @@ function cn(inputs?: (string | false | null | undefined)[]): string
1864
2164
 
1865
2165
  **Returns:** A single space-separated class string.
1866
2166
 
2167
+ #### `ConfirmDialog(props)`
2168
+
2169
+ Are-you-sure-style confirmation modal for destructive actions.
2170
+
2171
+ Use standalone (around delete buttons, revoke tokens, irreversible
2172
+ migrations) or with a DangerZoneSection action.
2173
+
2174
+ ```typescript
2175
+ function ConfirmDialog({
2176
+ open,
2177
+ onClose,
2178
+ title,
2179
+ description,
2180
+ confirmLabel,
2181
+ cancelLabel,
2182
+ onConfirm,
2183
+ destructive = true,
2184
+ children,
2185
+ loading,
2186
+ }: ConfirmDialogProps): JSX.Element
2187
+ ```
2188
+
2189
+ - `props` — Component props (see {@link ConfirmDialogProps}).
2190
+
1867
2191
  #### `Icon(props)`
1868
2192
 
1869
2193
  Renders an SVG glyph looked up by `name` from the bonded
@@ -1930,6 +2254,24 @@ function LanguagePicker({
1930
2254
 
1931
2255
  - `props` — {@link LanguagePickerProps}
1932
2256
 
2257
+ #### `LoadErrorBanner(props)`
2258
+
2259
+ Error banner with an owned pending-state Retry button.
2260
+
2261
+ ```typescript
2262
+ function LoadErrorBanner({
2263
+ message,
2264
+ detail,
2265
+ onRetry,
2266
+ retryLabel,
2267
+ retryMolId = 'load-error-retry',
2268
+ children,
2269
+ ...rest
2270
+ }: LoadErrorBannerProps): JSX.Element
2271
+ ```
2272
+
2273
+ - `props` — Component props (see {@link LoadErrorBannerProps}).
2274
+
1933
2275
  #### `PanelCloseProvider(props)`
1934
2276
 
1935
2277
  Provides the panel-close callback to descendants. Rendered internally
@@ -1944,6 +2286,127 @@ function PanelCloseProvider({ close, children }: PanelCloseProviderProps): JSX.E
1944
2286
 
1945
2287
  **Returns:** The children wrapped in the close-context provider.
1946
2288
 
2289
+ #### `PromptDialog(props)`
2290
+
2291
+ Modal that asks the user for a short string, replacing `window.prompt`.
2292
+
2293
+ ```typescript
2294
+ function PromptDialog({
2295
+ open,
2296
+ onClose,
2297
+ title,
2298
+ description,
2299
+ placeholder,
2300
+ initialValue = '',
2301
+ onSubmit,
2302
+ confirmLabel,
2303
+ cancelLabel,
2304
+ destructive = false,
2305
+ inputMolId,
2306
+ confirmMolId,
2307
+ cancelMolId,
2308
+ children,
2309
+ }: PromptDialogProps): JSX.Element
2310
+ ```
2311
+
2312
+ - `props` — Component props (see {@link PromptDialogProps}).
2313
+
2314
+ #### `ResponsiveAppShellContent(props)`
2315
+
2316
+ The shell's `<main>` landmark. Grows to fill the row and may shrink below
2317
+ its content width, so page-level `overflow-x` strips scroll inside the
2318
+ page instead of widening the whole shell.
2319
+
2320
+ ```typescript
2321
+ function ResponsiveAppShellContent({
2322
+ children,
2323
+ className,
2324
+ style,
2325
+ dataMolId = 'shell-content',
2326
+ testId,
2327
+ }: ResponsiveAppShellContentProps): JSX.Element
2328
+ ```
2329
+
2330
+ - `props` — The page content and class/id overrides.
2331
+
2332
+ **Returns:** The main landmark.
2333
+
2334
+ #### `ResponsiveAppShellDrawer(props)`
2335
+
2336
+ The mobile nav drawer (<768px): a left-anchored dialog panel over a
2337
+ backdrop, opened by the menu trigger the TopBar renders.
2338
+
2339
+ Implements the WAI-ARIA APG dialog pattern — focus moves into the panel on
2340
+ open and returns to the previously focused element (the trigger) on close,
2341
+ Tab is trapped inside, Escape and backdrop clicks close, body scroll locks
2342
+ (reference-counted with any stacked `<Modal>`), and the shell closes it on
2343
+ SPA navigation. Renders nothing on desktop or while closed.
2344
+
2345
+ ```typescript
2346
+ function ResponsiveAppShellDrawer({
2347
+ children,
2348
+ header,
2349
+ navLabel,
2350
+ footer,
2351
+ showCloseButton = true,
2352
+ className,
2353
+ dataMolId = 'shell-drawer',
2354
+ closeDataMolId = 'shell-drawer-close',
2355
+ testId,
2356
+ }: ResponsiveAppShellDrawerProps): JSX.Element | null
2357
+ ```
2358
+
2359
+ - `props` — Nav children, header/nav-label/footer slots, close-button and class/id overrides.
2360
+
2361
+ **Returns:** The drawer portal while open on mobile, otherwise `null`.
2362
+
2363
+ #### `ResponsiveAppShellSidebar(props)`
2364
+
2365
+ The desktop sidebar (`<aside>` + `<nav>` landmarks). Renders NOTHING below
2366
+ 768px — the {@link ResponsiveAppShellDrawer} carries the nav there.
2367
+
2368
+ Full viewport height, sticky at the top edge, scrolls internally when its
2369
+ content outgrows the viewport.
2370
+
2371
+ ```typescript
2372
+ function ResponsiveAppShellSidebar({
2373
+ children,
2374
+ navLabel,
2375
+ footer,
2376
+ className,
2377
+ dataMolId = 'shell-sidebar',
2378
+ testId,
2379
+ }: ResponsiveAppShellSidebarProps): JSX.Element | null
2380
+ ```
2381
+
2382
+ - `props` — Nav children, nav label, footer slot, class/id overrides.
2383
+
2384
+ **Returns:** The sidebar landmarks, or `null` below the breakpoint.
2385
+
2386
+ #### `ResponsiveAppShellTopBar(props)`
2387
+
2388
+ The shell's `<header>` landmark: menu trigger (mobile, when a Drawer is
2389
+ composed), brand, and trailing actions.
2390
+
2391
+ Sticks to the top of the viewport by default. The menu trigger renders
2392
+ only while a `ResponsiveAppShell.Drawer` is part of the composition AND
2393
+ the viewport is below the breakpoint.
2394
+
2395
+ ```typescript
2396
+ function ResponsiveAppShellTopBar({
2397
+ brand,
2398
+ actions,
2399
+ mobileOnly = false,
2400
+ className,
2401
+ dataMolId = 'shell-topbar',
2402
+ testId,
2403
+ }: ResponsiveAppShellTopBarProps): JSX.Element | null
2404
+ ```
2405
+
2406
+ - `props` — Brand/actions slots, `mobileOnly`, and class/id overrides.
2407
+
2408
+ **Returns:** The header landmark, or `null` when `mobileOnly` is set on desktop.
2409
+
1947
2410
  #### `SidebarUserCard(props)`
1948
2411
 
1949
2412
  Sidebar-resident user-account card: avatar + name + status line, opens
@@ -2021,6 +2484,27 @@ function ToastProvider({
2021
2484
 
2022
2485
  **Returns:** The rendered provider with toast container.
2023
2486
 
2487
+ #### `useIsDesktop(query)`
2488
+
2489
+ Whether the viewport is at least 768px wide (the fleet's `md` breakpoint).
2490
+
2491
+ Reads `window.matchMedia` synchronously in the state initializer, so the
2492
+ FIRST client render is already correct — no mobile-then-desktop swap frame
2493
+ (this is time-tracking's QA-hardened version; the naive
2494
+ "state starts false, sync in an effect" variant mounts the wrong shell for
2495
+ one frame and double-fetches route data on desktop). Subscribes to
2496
+ `change` events afterwards. Guarded for non-browser environments
2497
+ (SSR/node): returns `false` (the mobile shell) when no `window.matchMedia`
2498
+ exists.
2499
+
2500
+ ```typescript
2501
+ function useIsDesktop(query?: string): boolean
2502
+ ```
2503
+
2504
+ - `query` — Override the media query. Defaults to `(min-width: 768px)`.
2505
+
2506
+ **Returns:** Whether the desktop shell should mount.
2507
+
2024
2508
  #### `usePanelClose()`
2025
2509
 
2026
2510
  Returns the callback that dismisses the drawer the current panel is
@@ -2292,6 +2776,24 @@ const Checkbox: React.ForwardRefExoticComponent<
2292
2776
  >
2293
2777
  ```
2294
2778
 
2779
+ #### `ConfirmButton`
2780
+
2781
+ Two-step destructive-action button: the first click ARMS it ("Confirm?"),
2782
+ the second commits. Auto-disarms after {@link ConfirmButtonProps.disarmSeconds}
2783
+ (default 4s) so an armed-then-abandoned row can't surprise anyone later.
2784
+
2785
+ Replaces the fleet's hand-rolled arm-confirm pattern (previously
2786
+ reimplemented per app — button flips, dialogs, `window.confirm`, or worse,
2787
+ nothing at all) with one accessible, touch-friendly implementation:
2788
+ the whole button is the target (≥36px via the button CVA), the armed
2789
+ state is announced through `aria-live`, and Escape disarms.
2790
+
2791
+ ```typescript
2792
+ const ConfirmButton: React.ForwardRefExoticComponent<
2793
+ ConfirmButtonProps & React.RefAttributes<HTMLButtonElement>
2794
+ >
2795
+ ```
2796
+
2295
2797
  #### `Container`
2296
2798
 
2297
2799
  Container component.
@@ -2517,6 +3019,24 @@ const RadioGroup: React.ForwardRefExoticComponent<
2517
3019
  >
2518
3020
  ```
2519
3021
 
3022
+ #### `ResponsiveAppShell`
3023
+
3024
+ The responsive app shell family — see the {@link ResponsiveAppShellBase |
3025
+ root component} and the module docs for the full contract.
3026
+
3027
+ Consumed as `<ResponsiveAppShell.TopBar />`, `.Sidebar`, `.Drawer` and
3028
+ `.Content` inside `<ResponsiveAppShell>`; each is also exported as a named
3029
+ component (`ResponsiveAppShellTopBar`, …) for star-import consumers.
3030
+
3031
+ ```typescript
3032
+ const ResponsiveAppShell: typeof ResponsiveAppShellBase & {
3033
+ TopBar: typeof ResponsiveAppShellTopBar
3034
+ Sidebar: typeof ResponsiveAppShellSidebar
3035
+ Drawer: typeof ResponsiveAppShellDrawer
3036
+ Content: typeof ResponsiveAppShellContent
3037
+ }
3038
+ ```
3039
+
2520
3040
  #### `Select`
2521
3041
 
2522
3042
  Select component.
@@ -0,0 +1,71 @@
1
+ /**
2
+ * ConfirmButton component.
3
+ *
4
+ * @module
5
+ */
6
+ import React from 'react';
7
+ import type { ButtonProps } from '@molecule/app-ui';
8
+ /**
9
+ * Props for {@link ConfirmButton}.
10
+ */
11
+ export interface ConfirmButtonProps extends Omit<ButtonProps, 'onClick' | 'children' | 'onConfirm' | keyof React.DOMAttributes<HTMLButtonElement>> {
12
+ /**
13
+ * Fired ONLY on the confirming (second) click — i.e. when the action
14
+ * actually commits. Errors should be handled by the caller (render an
15
+ * inline banner); while the returned promise is pending the button stays
16
+ * in its confirming state and ignores further clicks.
17
+ */
18
+ onConfirm: () => void | Promise<void>;
19
+ /**
20
+ * Visible label in the idle (armed-to-be-clicked) state.
21
+ */
22
+ label: React.ReactNode;
23
+ /**
24
+ * Visible label in the armed state — the "click again to confirm" step.
25
+ * Defaults to a localized "Confirm?" via the i18n bond.
26
+ */
27
+ confirmLabel?: React.ReactNode;
28
+ /**
29
+ * Visible label while {@link onConfirm} is pending. Defaults to a
30
+ * localized "Working…".
31
+ */
32
+ pendingLabel?: React.ReactNode;
33
+ /**
34
+ * Seconds before the armed state auto-disarms back to idle. Low-stakes
35
+ * actions tolerate a long window; destructive ones should keep it short.
36
+ * `0` disables auto-disarm (not recommended — a stray click then leaves
37
+ * the button armed forever).
38
+ */
39
+ disarmSeconds?: number;
40
+ /**
41
+ * Disable the control entirely (idle and confirming states).
42
+ */
43
+ disabled?: boolean;
44
+ /**
45
+ * data-mol-id for the button (all states share one element).
46
+ */
47
+ testId?: string;
48
+ }
49
+ /**
50
+ * Two-step destructive-action button: the first click ARMS it ("Confirm?"),
51
+ * the second commits. Auto-disarms after {@link ConfirmButtonProps.disarmSeconds}
52
+ * (default 4s) so an armed-then-abandoned row can't surprise anyone later.
53
+ *
54
+ * Replaces the fleet's hand-rolled arm-confirm pattern (previously
55
+ * reimplemented per app — button flips, dialogs, `window.confirm`, or worse,
56
+ * nothing at all) with one accessible, touch-friendly implementation:
57
+ * the whole button is the target (≥36px via the button CVA), the armed
58
+ * state is announced through `aria-live`, and Escape disarms.
59
+ *
60
+ * @example
61
+ * ```tsx
62
+ * <ConfirmButton
63
+ * label="Delete"
64
+ * confirmLabel="Confirm delete?"
65
+ * onConfirm={() => deleteClient(client.id)}
66
+ * testId="client-delete"
67
+ * />
68
+ * ```
69
+ */
70
+ export declare const ConfirmButton: React.ForwardRefExoticComponent<ConfirmButtonProps & React.RefAttributes<HTMLButtonElement>>;
71
+ //# sourceMappingURL=ConfirmButton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConfirmButton.d.ts","sourceRoot":"","sources":["../../src/components/ConfirmButton.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAkD,MAAM,OAAO,CAAA;AAGtE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAGnD;;GAEG;AACH,MAAM,WAAW,kBAAmB,SAAQ,IAAI,CAC9C,WAAW,EACX,SAAS,GAAG,UAAU,GAAG,WAAW,GAAG,MAAM,KAAK,CAAC,aAAa,CAAC,iBAAiB,CAAC,CACpF;IACC;;;;;OAKG;IACH,SAAS,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACrC;;OAEG;IACH,KAAK,EAAE,KAAK,CAAC,SAAS,CAAA;IACtB;;;OAGG;IACH,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC9B;;;OAGG;IACH,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC9B;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,aAAa,8FA6FzB,CAAA"}