@hjmds/react 1.30.0 → 1.32.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 (102) hide show
  1. package/dist/auth-screen.d.ts +18 -3
  2. package/dist/auth-screen.d.ts.map +1 -1
  3. package/dist/auth-screen.js +22 -6
  4. package/dist/auth-screen.js.map +1 -1
  5. package/dist/bottom-cta.d.ts +6 -1
  6. package/dist/bottom-cta.d.ts.map +1 -1
  7. package/dist/bottom-cta.js +1 -1
  8. package/dist/bottom-cta.js.map +1 -1
  9. package/dist/bottom-navigation.d.ts +10 -0
  10. package/dist/bottom-navigation.d.ts.map +1 -1
  11. package/dist/bottom-navigation.js +80 -8
  12. package/dist/bottom-navigation.js.map +1 -1
  13. package/dist/carousel.d.ts +29 -1
  14. package/dist/carousel.d.ts.map +1 -1
  15. package/dist/carousel.js +27 -3
  16. package/dist/carousel.js.map +1 -1
  17. package/dist/display.d.ts +8 -2
  18. package/dist/display.d.ts.map +1 -1
  19. package/dist/display.js +12 -7
  20. package/dist/display.js.map +1 -1
  21. package/dist/evidence.d.ts +1 -1
  22. package/dist/evidence.js +1 -1
  23. package/dist/evidence.js.map +1 -1
  24. package/dist/forms.d.ts.map +1 -1
  25. package/dist/forms.js +2 -1
  26. package/dist/forms.js.map +1 -1
  27. package/dist/image-choice.d.ts +20 -2
  28. package/dist/image-choice.d.ts.map +1 -1
  29. package/dist/image-choice.js +60 -7
  30. package/dist/image-choice.js.map +1 -1
  31. package/dist/index.d.ts +3 -3
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +3 -3
  34. package/dist/index.js.map +1 -1
  35. package/dist/internal/field-error.d.ts +19 -0
  36. package/dist/internal/field-error.d.ts.map +1 -0
  37. package/dist/internal/field-error.js +19 -0
  38. package/dist/internal/field-error.js.map +1 -0
  39. package/dist/internal/initial-focus.d.ts.map +1 -1
  40. package/dist/internal/initial-focus.js +49 -7
  41. package/dist/internal/initial-focus.js.map +1 -1
  42. package/dist/internal/media-album.d.ts +70 -0
  43. package/dist/internal/media-album.d.ts.map +1 -0
  44. package/dist/internal/media-album.js +52 -0
  45. package/dist/internal/media-album.js.map +1 -0
  46. package/dist/internal/message-reactions.d.ts +39 -2
  47. package/dist/internal/message-reactions.d.ts.map +1 -1
  48. package/dist/internal/message-reactions.js +31 -6
  49. package/dist/internal/message-reactions.js.map +1 -1
  50. package/dist/layout.d.ts +19 -3
  51. package/dist/layout.d.ts.map +1 -1
  52. package/dist/layout.js +10 -3
  53. package/dist/layout.js.map +1 -1
  54. package/dist/navigation.d.ts +3 -1
  55. package/dist/navigation.d.ts.map +1 -1
  56. package/dist/navigation.js +4 -2
  57. package/dist/navigation.js.map +1 -1
  58. package/dist/number-field.d.ts.map +1 -1
  59. package/dist/number-field.js +2 -1
  60. package/dist/number-field.js.map +1 -1
  61. package/dist/overlays.d.ts +65 -0
  62. package/dist/overlays.d.ts.map +1 -1
  63. package/dist/overlays.js +36 -3
  64. package/dist/overlays.js.map +1 -1
  65. package/dist/pagination.d.ts +13 -11
  66. package/dist/pagination.d.ts.map +1 -1
  67. package/dist/pagination.js +12 -5
  68. package/dist/pagination.js.map +1 -1
  69. package/dist/public-exports.generated.d.ts +8 -0
  70. package/dist/public-exports.generated.d.ts.map +1 -1
  71. package/dist/public-exports.generated.js +24 -0
  72. package/dist/public-exports.generated.js.map +1 -1
  73. package/dist/screen-flows.d.ts +118 -14
  74. package/dist/screen-flows.d.ts.map +1 -1
  75. package/dist/screen-flows.js +95 -23
  76. package/dist/screen-flows.js.map +1 -1
  77. package/dist/screens.d.ts +69 -10
  78. package/dist/screens.d.ts.map +1 -1
  79. package/dist/screens.js +77 -15
  80. package/dist/screens.js.map +1 -1
  81. package/dist/select.d.ts.map +1 -1
  82. package/dist/select.js +2 -1
  83. package/dist/select.js.map +1 -1
  84. package/dist/selection.d.ts.map +1 -1
  85. package/dist/selection.js +3 -2
  86. package/dist/selection.js.map +1 -1
  87. package/dist/steps.d.ts +11 -1
  88. package/dist/steps.d.ts.map +1 -1
  89. package/dist/steps.js +11 -6
  90. package/dist/steps.js.map +1 -1
  91. package/dist/styles.css +181 -22
  92. package/dist/styles.layered.css +181 -22
  93. package/dist/supplemental-display.d.ts.map +1 -1
  94. package/dist/supplemental-display.js +2 -48
  95. package/dist/supplemental-display.js.map +1 -1
  96. package/dist/theme.d.ts.map +1 -1
  97. package/dist/theme.js +1 -0
  98. package/dist/theme.js.map +1 -1
  99. package/dist/toast.d.ts.map +1 -1
  100. package/dist/toast.js +1 -1
  101. package/dist/toast.js.map +1 -1
  102. package/package.json +3 -3
package/dist/screens.d.ts CHANGED
@@ -1,10 +1,13 @@
1
- import { type ScreenInitialFocus } from "@hjmds/design-contracts/screen-patterns";
1
+ import { type ScreenInitialFocus, type IconTileArtwork, type IconTileFrame, type IconTileShape, type IconTileSize } from "@hjmds/design-contracts/screen-patterns";
2
2
  import { type ComposerLengthFeedback } from "@hjmds/design-contracts/communication";
3
3
  import { type DesignProfileScreenPresentation } from "@hjmds/design-contracts/design-profile-layout";
4
4
  import { type MessageMenuAction } from "./internal/message-reactions.js";
5
+ import { type MediaAlbum } from "./internal/media-album.js";
6
+ export type { MediaAlbum, MediaAlbumPageStatusProps } from "./internal/media-album.js";
7
+ export { MediaAlbumPageStatus } from "./internal/media-album.js";
5
8
  import type { ReactionPickerProps } from "./reaction-picker.js";
6
9
  import { type Ref, type ReactNode } from "react";
7
- import { type MessageAttachmentDescriptor, type ChatMessageDescriptor, type MessageComposerDescriptor, type ScreenContentState, type ScreenContentInset } from "@hjmds/design-contracts/screen-patterns";
10
+ import { type MessageAttachmentDescriptor, type ChatReactionSummary, type ChatMessageDescriptor, type MessageComposerDescriptor, type ScreenContentState, type ScreenContentInset } from "@hjmds/design-contracts/screen-patterns";
8
11
  import { type ScreenExit } from "./internal/screen-exit.js";
9
12
  import { type ListRowProps } from "./display.js";
10
13
  import type { HjmCompositionStyleProp } from "./composition-style.js";
@@ -12,13 +15,22 @@ export type ScreenLayoutProps = Readonly<{
12
15
  title: string;
13
16
  /** The shared header owns badge placement; the product supplies its meaning and label. */
14
17
  titleBadge?: ReactNode;
18
+ /**
19
+ * Identity mark or artwork before the title (team logo, tool artwork). Decorative: the title stays the heading and
20
+ * the accessible name. With `titleVisibility="hidden"` the mark stands alone in the title slot as the heading,
21
+ * named by `title` (2026-10-18: yajalal team detail and Utilverse tool headers rebuilt the header to get this).
22
+ */
23
+ titleLeading?: ReactNode;
15
24
  /** Hide redundant route names while retaining descriptions and a named screen. */
16
25
  titleVisibility?: "visible" | "hidden";
17
26
  /** Centered by default (2026-10-17 user rule); `start` remains available. Extra actions sit at the trailing edge. */
18
27
  headerAlignment?: "start" | "center";
19
28
  /** Preserve host navigation while the shared shell owns content and state. */
20
29
  header?: ReactNode;
21
- /** `none`: host owns every inset. `body-edge`: only the body drops its inline padding so list rows own their inset. */
30
+ /**
31
+ * `none`: host owns every inset. `body-edge`: only the body drops its inline padding so list rows own their inset.
32
+ * `body-bleed`: the body drops every padding (header, notice and footer keep theirs) for an edge-to-edge map or canvas.
33
+ */
22
34
  contentInset?: ScreenContentInset;
23
35
  /** Center a product prompt in the available body without inventing a query state. */
24
36
  contentAlignment?: "start" | "center";
@@ -37,6 +49,8 @@ export type ScreenLayoutProps = Readonly<{
37
49
  footer?: ReactNode;
38
50
  state?: ScreenContentState;
39
51
  stateAction?: ReactNode;
52
+ /** Brand visual for `state.kind === "loading"`; the shared state group keeps copy, centering and announcement (as CompositionLayout). */
53
+ loadingIndicator?: ReactNode;
40
54
  children?: ReactNode;
41
55
  /** A virtualized list must own scrolling; never nest it inside a second scroll container. */
42
56
  scroll?: "screen" | "content";
@@ -57,9 +71,7 @@ export type ScreenLayoutProps = Readonly<{
57
71
  initialFocus?: ScreenInitialFocus;
58
72
  }>;
59
73
  /** Shared screen shell. Routing, data, permission checks and mutation state remain product-owned. */
60
- export declare function ScreenLayout({ title, titleBadge, titleVisibility, headerAlignment, header, contentInset, contentAlignment, surface, presentation: suppliedPresentation, description, exit, actions, notice, footer, state, stateAction, children, scroll, as: Element, className, layoutStyle, initialFocus, hjmTitleLeading }: ScreenLayoutProps & Readonly<{
61
- hjmTitleLeading?: ReactNode;
62
- }>): import("react").JSX.Element;
74
+ export declare function ScreenLayout({ title, titleBadge, titleLeading, titleVisibility, headerAlignment, header, contentInset, contentAlignment, surface, presentation: suppliedPresentation, description, exit, actions, notice, footer, state, stateAction, loadingIndicator, children, scroll, as: Element, className, layoutStyle, initialFocus }: ScreenLayoutProps): import("react").JSX.Element;
63
75
  /**
64
76
  * Style for a product scroller that owns the body with `scroll="content"`: it reaches across the body gutter
65
77
  * (`--hjm-screen-body-inline`) and pads it back, so items stay on the gutter while the clip moves to the screen edges and
@@ -93,7 +105,7 @@ export type NotificationItemProps = Omit<ListRowProps, "description" | "selected
93
105
  description?: ReactNode;
94
106
  }>;
95
107
  export declare function NotificationItem({ read, statusLabel, timestamp, description, title, className, ...props }: NotificationItemProps): import("react").JSX.Element;
96
- export type ChatScreenProps = Omit<ScreenLayoutProps, "footer"> & Readonly<{
108
+ export type ChatScreenProps = Omit<ScreenLayoutProps, "footer" | "titleLeading"> & Readonly<{
97
109
  composer: ReactNode;
98
110
  /** Shown while the reader is away from the latest message; the host owns scroll position and visibility. */
99
111
  jumpToLatest?: Readonly<{
@@ -195,11 +207,24 @@ export type ChatMessageProps = ChatMessageDescriptor & Readonly<{
195
207
  disabled?: boolean;
196
208
  icon?: ReactNode;
197
209
  }>;
210
+ summary?: ChatMessageReactionSummary;
198
211
  }>;
199
212
  /** Canonical layout-only placement on the message row. The swipe offset still owns `transform`. */
200
213
  layoutStyle?: HjmCompositionStyleProp;
214
+ }> & Readonly<{
215
+ /**
216
+ * Paged alternative to `media` (2026-10-18, Utilverse): HJM mounts only the shown photo, so a product that authorizes
217
+ * each image fetches one page at a time. Exclusive with `media` (validated at render): one message has one photo set.
218
+ */
219
+ mediaAlbum?: MediaAlbum;
201
220
  }>;
202
- export declare function ChatMessage({ direction, author, timestamp, timestampPresentation, bubbleTail, groupPosition, deliveryLabel, avatar, reply, replyQuote, media, actions, replyAction, replyLink, reactions, children, interactiveContent, layoutStyle }: ChatMessageProps): import("react").JSX.Element;
221
+ /**
222
+ * Current reactions drawn beside the time as one button that opens the same hold menu (2026-10-18 BurnTok DM, which
223
+ * showed counts as status tags because the menu could not be opened from outside). Counts and the localized
224
+ * accessible name ("Reactions: heart 2. Open menu") come from the product; `items` in display order.
225
+ */
226
+ export type ChatMessageReactionSummary = ChatReactionSummary;
227
+ export declare function ChatMessage({ direction, author, timestamp, timestampPresentation, bubbleTail, groupPosition, deliveryLabel, avatar, reply, replyQuote, media, mediaAlbum, actions, replyAction, replyLink, reactions, children, interactiveContent, layoutStyle }: ChatMessageProps): import("react").JSX.Element;
203
228
  /** Shared structure for embedded compositions. The parent supplies size; this never creates a second scroller. */
204
229
  export type CompositionLayoutProps = Readonly<{
205
230
  title?: string;
@@ -231,12 +256,46 @@ export type NotificationRowProps = Readonly<{
231
256
  /** Router host owns the sole target and localized accessible name, as with ConversationRow. */
232
257
  export declare function NotificationRow({ preview, metadata, avatar, avatarBadge, thumbnail, unread }: NotificationRowProps): import("react").JSX.Element;
233
258
  export type IconTileProps = Readonly<{
234
- icon: ReactNode;
259
+ /**
260
+ * Icon artwork. A function receives the rendered edge (`IconTileArtwork`) so fixed-size artwork such as an image
261
+ * sizes itself to a `size="fill"` icon without the product re-computing the cell clamp.
262
+ */
263
+ icon: ReactNode | ((artwork: IconTileArtwork) => ReactNode);
235
264
  label: string;
236
265
  overlay?: ReactNode;
237
266
  labelLines?: 1 | 2;
238
267
  ghost?: boolean;
268
+ /** `none`: the icon is complete product artwork, so no frame fill or hairline is drawn. */
269
+ frame?: IconTileFrame;
270
+ /** Frame (and ghost outline) corner shape from the product's icon theme. */
271
+ shape?: IconTileShape;
272
+ /** `fill`: the icon spans the grid cell between iconTileRecipe.fillMinSize and fillMaxSize. */
273
+ size?: IconTileSize;
239
274
  }>;
240
275
  /** Presentation shared by launcher and profile grids; the host owns navigation or drag behavior. */
241
- export declare function IconTile({ icon, label, overlay, labelLines, ghost }: IconTileProps): import("react").JSX.Element;
276
+ export declare function IconTile({ icon, label, overlay, labelLines, ghost, frame, shape, size }: IconTileProps): import("react").JSX.Element;
277
+ export type TypingIndicatorProps = Readonly<{
278
+ /** Localized status read by assistive tech ("Seoyeon is typing"); the visible row shows only the dots. */
279
+ label: string;
280
+ /** Typer's photo in a group room, sized like ChatMessage avatars (`chatMessageRecipe.avatarSize`). */
281
+ avatar?: ReactNode;
282
+ layoutStyle?: HjmCompositionStyleProp;
283
+ }>;
284
+ /**
285
+ * Incoming "is typing" row for a ChatScreen timeline (2026-10-18 BurnTok DM drew its own). The host shows it only while
286
+ * presence says someone is typing and places it after the last message; HJM owns the bubble, dots and announcement.
287
+ */
288
+ export declare function TypingIndicator({ label, avatar, layoutStyle }: TypingIndicatorProps): import("react").JSX.Element;
289
+ export type ChatDateSeparatorProps = Readonly<{
290
+ /** Product-formatted date or time ("Today", "Oct 18", "3:04 PM"). */
291
+ label: string;
292
+ /** Machine-readable value for the Web `<time>` element; Native ignores it. */
293
+ dateTime?: string;
294
+ layoutStyle?: HjmCompositionStyleProp;
295
+ }>;
296
+ /**
297
+ * Centered date (or time) row between ChatScreen timeline groups (2026-10-18 Utilverse chat drew a caption). Grouping
298
+ * rules stay with the product; the next message keeps its own group gap, so this row adds only the space before it.
299
+ */
300
+ export declare function ChatDateSeparator({ label, dateTime, layoutStyle }: ChatDateSeparatorProps): import("react").JSX.Element;
242
301
  //# sourceMappingURL=screens.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"screens.d.ts","sourceRoot":"","sources":["../src/screens.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"screens.d.ts","sourceRoot":"","sources":["../src/screens.tsx"],"names":[],"mappings":"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"}
package/dist/screens.js CHANGED
@@ -5,29 +5,34 @@ import { iconButtonRecipe, listRowRecipe } from "@hjmds/design-contracts/recipes
5
5
  import { resolveComposerLimit } from "@hjmds/design-contracts/communication";
6
6
  import { Progress } from "./feedback.js";
7
7
  import { resolveDesignProfileScreen } from "@hjmds/design-contracts/design-profile-layout";
8
- import { MessageReactions } from "./internal/message-reactions.js";
8
+ import { MessageReactions, ReactionSummaryButton, ReactionSummaryText, omitReactionSummary } from "./internal/message-reactions.js";
9
+ import { MediaAlbumView, useMediaAlbumIndex } from "./internal/media-album.js";
10
+ import { validateMediaSetChoice } from "@hjmds/design-contracts/screen-patterns";
11
+ // Loading/failed page rendered inside `mediaAlbum.renderPage` (2026-10-18); comment rows use the same component.
12
+ export { MediaAlbumPageStatus } from "./internal/media-album.js";
9
13
  import { Button, IconButton } from "./actions.js";
10
14
  import { useOptionalHjmTheme } from "./provider.js";
11
15
  import { TextArea } from "./forms.js";
12
16
  import { useId, useLayoutEffect, useRef, useState } from "react";
13
- import { isReplySwipe, timestampRevealOffset, shouldSubmitMessageKey, canSubmitMessage, validateMessageAttachments, resolveScreenContentState, screenPatternRecipe, chatMessageRecipe, composerQuickInsertRecipe, resolveChatMessageGroupDisplay, resolveChatMediaColumns, screenHeaderRecipe, validateScreenExit } from "@hjmds/design-contracts/screen-patterns";
17
+ import { isReplySwipe, timestampRevealOffset, shouldSubmitMessageKey, canSubmitMessage, validateMessageAttachments, resolveScreenContentState, screenPatternRecipe, chatMessageRecipe, composerQuickInsertRecipe, resolveChatMessageGroupDisplay, resolveChatMediaColumns, resolveChatReactionSummary, typingIndicatorRecipe, chatDateSeparatorRecipe, screenHeaderRecipe, validateScreenExit } from "@hjmds/design-contracts/screen-patterns";
14
18
  import { Heading } from "./heading.js";
15
19
  import { Spinner } from "./internal/spinner.js";
16
20
  import { ScreenExitButton } from "./internal/screen-exit.js";
17
21
  import { ScreenFooterContext } from "./internal/screen-footer.js";
18
- import { Section, Stack, Text } from "./layout.js";
22
+ import { Section, Stack, Text, VisuallyHidden } from "./layout.js";
19
23
  import { ListRow } from "./display.js";
20
24
  import { classNames, useDesignProfileDefaults } from "./internal.js";
21
25
  /** Shared screen shell. Routing, data, permission checks and mutation state remain product-owned. */
22
- export function ScreenLayout({ title, titleBadge, titleVisibility = "visible", headerAlignment = "center", header, contentInset = "default", contentAlignment = "start", surface = "default", presentation: suppliedPresentation, description, exit, actions, notice, footer, state = { kind: "ready" }, stateAction, children, scroll = "screen", as: Element = "main", className, layoutStyle, initialFocus = initialFocusDefaults.screen, hjmTitleLeading }) {
26
+ export function ScreenLayout({ title, titleBadge, titleLeading, titleVisibility = "visible", headerAlignment = "center", header, contentInset = "default", contentAlignment = "start", surface = "default", presentation: suppliedPresentation, description, exit, actions, notice, footer, state = { kind: "ready" }, stateAction, loadingIndicator, children, scroll = "screen", as: Element = "main", className, layoutStyle, initialFocus = initialFocusDefaults.screen }) {
23
27
  const id = useId();
24
28
  if (exit)
25
29
  validateScreenExit(exit, false);
26
30
  const leading = exit ? _jsx(ScreenExitButton, { ...exit }) : null;
27
- const showHeader = titleVisibility === "visible" || !!description || !!leading || !!actions;
31
+ const hasMark = titleLeading !== undefined && titleLeading !== null && titleLeading !== false;
32
+ const showHeader = titleVisibility === "visible" || hasMark || !!description || !!leading || !!actions;
28
33
  // Same header band as Native (screenHeaderRecipe): a fixed 52 band (48 icon-only) so the title sits at the same
29
34
  // height with or without exit/actions buttons (2026-10-17: Web grew 58→76 when a 44 button was present).
30
- const compactHeader = header == null && headerAlignment === "center" && titleVisibility === "hidden" && !description;
35
+ const compactHeader = header == null && headerAlignment === "center" && titleVisibility === "hidden" && !hasMark && !description;
31
36
  // Screens historically work with the stylesheet alone. Optional context keeps
32
37
  // that path while inheriting profiles from an enclosing Provider when present.
33
38
  const designProfile = useDesignProfileDefaults();
@@ -50,13 +55,18 @@ export function ScreenLayout({ title, titleBadge, titleVisibility = "visible", h
50
55
  lastBodyFocus.current = null;
51
56
  });
52
57
  const recipe = screenPatternRecipe;
53
- return _jsx(Element, { "aria-labelledby": header || titleVisibility === "hidden" ? undefined : id, "aria-label": header || titleVisibility === "hidden" ? title : undefined, "data-content-inset": contentInset, "data-presentation": presentation, className: classNames("hjm-screen", className), style: { backgroundColor: surface === "transparent" || designProfile?.material.canvas ? "transparent" : undefined, "--hjm-screen-width": `${profileLayout?.maxWidth ?? recipe.maxWidth}px`, "--hjm-screen-padding": `${contentInset === "none" ? 0 : recipe.padding}px`, "--hjm-screen-gap": `${profileLayout?.gap ?? recipe.sectionGap}px`, "--hjm-screen-item-gap": `${recipe.itemGap}px`, "--hjm-screen-state-gap": `${recipe.stateGap}px`, "--hjm-screen-header-min": `${recipe.headerMinWidth}px`, ...layoutStyle }, children: _jsxs(InitialFocusScope, { mode: initialFocus, children: [header ?? (showHeader ? headerAlignment === "center" ? _jsxs("header", { className: "hjm-screen__header", style: { display: "grid", gridTemplateColumns: "1fr minmax(0, auto) 1fr", alignItems: "center", boxSizing: "border-box", minBlockSize: compactHeader ? screenHeaderRecipe.compactMinHeight : screenHeaderRecipe.minHeight, paddingBlock: compactHeader ? screenHeaderRecipe.compactPaddingVertical : screenHeaderRecipe.paddingVertical }, children: [_jsx("div", { children: leading }), _jsxs("div", { className: "hjm-screen__heading", style: { textAlign: "center", minWidth: 0 }, children: [titleVisibility === "visible" && _jsxs(Stack, { axis: "inline", gap: "xs", align: "center", justify: "center", wrap: true, children: [hjmTitleLeading, _jsx(Heading, { level: screenHeaderRecipe.centeredTitleLevel, semanticLevel: 1, id: id, children: title }), titleBadge] }), description ? _jsx(Text, { as: "p", tone: "muted", children: description }) : null] }), _jsx("div", { style: { justifySelf: "end" }, children: actions })] }) : _jsxs("header", { className: "hjm-screen__header", style: profileLayout ? { flexDirection: profileLayout.headerAxis, alignItems: profileLayout.centered ? "center" : undefined, textAlign: profileLayout.centered ? "center" : undefined } : undefined, children: [leading, _jsxs("div", { className: "hjm-screen__heading", children: [titleVisibility === "visible" && _jsxs(Stack, { axis: "inline", gap: "xs", align: "center", justify: profileLayout?.centered ? "center" : "start", wrap: true, children: [_jsx(Heading, { level: screenHeaderRecipe.titleLevel, semanticLevel: 1, id: id, children: title }), titleBadge] }), description ? _jsx(Text, { as: "p", tone: "muted", children: description }) : null] }), actions] }) : null), notice ? _jsx("div", { className: "hjm-screen__notice", children: notice }) : null, _jsx("div", { ref: bodyRef, role: "region", "aria-label": title, tabIndex: bodyScroll === "content" ? -1 : 0, onFocusCapture: event => { lastBodyFocus.current = event.target; }, onBlurCapture: event => {
58
+ // The mark is decorative beside a visible title; standing alone it becomes the heading, named by `title`.
59
+ const mark = hasMark ? _jsx("span", { className: "hjm-screen__title-leading", "aria-hidden": "true", children: titleLeading }) : null;
60
+ const titleRow = (level, justify) => titleVisibility === "visible"
61
+ ? _jsxs(Stack, { axis: "inline", gap: "xs", align: "center", justify: justify, wrap: true, children: [mark, _jsx(Heading, { level: level, semanticLevel: 1, id: id, children: title }), titleBadge] })
62
+ : mark ? _jsx("div", { role: "heading", "aria-level": 1, "aria-label": title, style: { display: "flex", justifyContent: justify === "center" ? "center" : "flex-start" }, children: mark }) : null;
63
+ return _jsx(Element, { "aria-labelledby": header || titleVisibility === "hidden" ? undefined : id, "aria-label": header || titleVisibility === "hidden" ? title : undefined, "data-content-inset": contentInset, "data-presentation": presentation, className: classNames("hjm-screen", className), style: { backgroundColor: surface === "transparent" || designProfile?.material.canvas ? "transparent" : undefined, "--hjm-screen-width": `${profileLayout?.maxWidth ?? recipe.maxWidth}px`, "--hjm-screen-padding": `${contentInset === "none" ? 0 : recipe.padding}px`, "--hjm-screen-gap": `${profileLayout?.gap ?? recipe.sectionGap}px`, "--hjm-screen-item-gap": `${recipe.itemGap}px`, "--hjm-screen-state-gap": `${recipe.stateGap}px`, "--hjm-screen-header-min": `${recipe.headerMinWidth}px`, ...layoutStyle }, children: _jsxs(InitialFocusScope, { mode: initialFocus, children: [header ?? (showHeader ? headerAlignment === "center" ? _jsxs("header", { className: "hjm-screen__header", style: { display: "grid", gridTemplateColumns: "1fr minmax(0, auto) 1fr", alignItems: "center", boxSizing: "border-box", minBlockSize: compactHeader ? screenHeaderRecipe.compactMinHeight : screenHeaderRecipe.minHeight, paddingBlock: compactHeader ? screenHeaderRecipe.compactPaddingVertical : screenHeaderRecipe.paddingVertical }, children: [_jsx("div", { children: leading }), _jsxs("div", { className: "hjm-screen__heading", style: { textAlign: "center", minWidth: 0 }, children: [titleRow(screenHeaderRecipe.centeredTitleLevel, "center"), description ? _jsx(Text, { as: "p", tone: "muted", children: description }) : null] }), _jsx("div", { style: { justifySelf: "end" }, children: actions })] }) : _jsxs("header", { className: "hjm-screen__header", style: profileLayout ? { flexDirection: profileLayout.headerAxis, alignItems: profileLayout.centered ? "center" : undefined, textAlign: profileLayout.centered ? "center" : undefined } : undefined, children: [leading, _jsxs("div", { className: "hjm-screen__heading", children: [titleRow(screenHeaderRecipe.titleLevel, profileLayout?.centered ? "center" : "start"), description ? _jsx(Text, { as: "p", tone: "muted", children: description }) : null] }), actions] }) : null), notice ? _jsx("div", { className: "hjm-screen__notice", children: notice }) : null, _jsx("div", { ref: bodyRef, role: "region", "aria-label": title, tabIndex: bodyScroll === "content" ? -1 : 0, onFocusCapture: event => { lastBodyFocus.current = event.target; }, onBlurCapture: event => {
54
64
  // A connected input blurred to the document intentionally relinquishes
55
65
  // focus too; only removal of the currently focused node needs recovery.
56
66
  if (event.relatedTarget ? !event.currentTarget.contains(event.relatedTarget) : event.target.isConnected) {
57
67
  lastBodyFocus.current = null;
58
68
  }
59
- }, className: "hjm-screen__body", "data-content-alignment": contentAlignment, "data-scroll": bodyScroll, "data-replacement": resolved.replacesContent || undefined, "aria-busy": resolved.busy || undefined, children: state.kind === "ready" ? (contentAlignment === "center" ? _jsx("div", { className: "hjm-screen__centered-content", children: children }) : children) : _jsxs("div", { className: "hjm-screen__state", children: [resolved.busy ? _jsx(Spinner, { label: [state.title, state.description].filter(Boolean).join(". ") }) : _jsx("div", { role: state.kind === "error" ? "alert" : "status", children: _jsxs(Stack, { gap: "sm", align: "center", children: [_jsx(Text, { variant: "title", children: state.title }), state.description ? _jsx(Text, { tone: "muted", children: state.description }) : null] }) }), stateAction] }) }), footer ? _jsx("footer", { className: "hjm-screen__footer", children: _jsx(ScreenFooterContext.Provider, { value: contentInset !== "none", children: footer }) }) : null] }) });
69
+ }, className: "hjm-screen__body", "data-content-alignment": contentAlignment, "data-scroll": bodyScroll, "data-replacement": resolved.replacesContent || undefined, "aria-busy": resolved.busy || undefined, children: state.kind === "ready" ? (contentAlignment === "center" ? _jsx("div", { className: "hjm-screen__centered-content", children: children }) : children) : _jsxs("div", { className: "hjm-screen__state", children: [resolved.busy ? (loadingIndicator ? _jsx("div", { role: "status", "aria-busy": "true", "aria-label": [state.title, state.description].filter(Boolean).join(". "), children: _jsx("div", { "aria-hidden": "true", children: loadingIndicator }) }) : _jsx(Spinner, { label: [state.title, state.description].filter(Boolean).join(". ") })) : _jsx("div", { role: state.kind === "error" ? "alert" : "status", children: _jsxs(Stack, { gap: "sm", align: "center", children: [_jsx(Text, { variant: "title", children: state.title }), state.description ? _jsx(Text, { tone: "muted", children: state.description }) : null] }) }), stateAction] }) }), footer ? _jsx("footer", { className: "hjm-screen__footer", children: _jsx(ScreenFooterContext.Provider, { value: contentInset !== "none", children: footer }) }) : null] }) });
60
70
  }
61
71
  /**
62
72
  * Style for a product scroller that owns the body with `scroll="content"`: it reaches across the body gutter
@@ -83,7 +93,7 @@ export function ChatScreen({ composer, jumpToLatest, avatar, scroll = "content",
83
93
  const showComposer = !props.state || props.state.kind === "ready" || props.state.kind === "empty";
84
94
  // Anchor the jump control to the composer edge so it floats over the timeline without measuring the footer.
85
95
  // Conversations center the peer between back and tools and use the measured 10px timeline gutter (2026-10-16).
86
- return _jsx(ScreenLayout, { ...props, className: classNames("hjm-chat-screen", props.className) ?? "hjm-chat-screen", hjmTitleLeading: avatar, scroll: scroll, footer: showComposer ? _jsxs("div", { className: "hjm-chat-screen__footer", children: [jumpToLatest ? _jsx("div", { className: "hjm-chat-screen__jump", children: _jsx(IconButton, { label: jumpToLatest.label, size: "small", shape: "circle", tone: "secondary", onClick: jumpToLatest.onPress, children: jumpToLatest.icon }) }) : null, composer] }) : null });
96
+ return _jsx(ScreenLayout, { ...props, className: classNames("hjm-chat-screen", props.className) ?? "hjm-chat-screen", titleLeading: avatar, scroll: scroll, footer: showComposer ? _jsxs("div", { className: "hjm-chat-screen__footer", children: [jumpToLatest ? _jsx("div", { className: "hjm-chat-screen__jump", children: _jsx(IconButton, { label: jumpToLatest.label, size: "small", shape: "circle", tone: "secondary", onClick: jumpToLatest.onPress, children: jumpToLatest.icon }) }) : null, composer] }) : null });
87
97
  }
88
98
  export function MessageComposer({ leading, quickInserts, value, label, sendLabel, placeholder = label, description, error, invalid = false, submitMode = "newline", onBlur, disabled = false, pending = false, onValueChange, onSend, maxLength, lengthFeedback, sendDisabled = false, additionalContent = false, leadingAction, inputRef, context, replyTo, sendIcon, sendPresentation = "inline", attachmentAction, attachments = [], onRemoveAttachment, layoutStyle }) {
89
99
  validateMessageAttachments(attachments);
@@ -111,24 +121,33 @@ export function MessageComposer({ leading, quickInserts, value, label, sendLabel
111
121
  } }, onChange: event => { if (!locked)
112
122
  onValueChange(event.currentTarget.value); }, minVisibleLines: screenPatternRecipe.composerMinLines, maxVisibleLines: screenPatternRecipe.composerMaxLines, ...(sendIcon ? { trailing: _jsx("span", { className: "hjm-message-composer__trailing", style: { minInlineSize: sendDiameter, minBlockSize: sendDiameter }, children: _jsx("span", { className: "hjm-message-composer__visible", children: hasContent || pending ? send : attach }) }) } : {}) }), sendIcon ? null : send] })] });
113
123
  const quickRow = quickInserts?.items.length ? _jsx("div", { className: "hjm-message-composer__quick", role: "group", "aria-label": quickInserts.label, style: { "--hjm-quick-size": `${composerQuickInsertRecipe.itemSize}px`, "--hjm-quick-emoji": `${composerQuickInsertRecipe.emojiSize}px` }, children: quickInserts.items.map(item => _jsx("button", { type: "button", className: "hjm-message-composer__quick-item", "aria-label": item.label, disabled: locked, onClick: () => onValueChange(value + item.emoji), children: item.emoji }, item.id)) }) : null;
124
+ // The error is announced by TextArea's shared Field error region (internal/field-error.tsx); no composer-only copy.
114
125
  return _jsxs("div", { className: "hjm-message-composer", "data-send-presentation": sendPresentation, style: { "--hjm-message-composer-gap": `${screenPatternRecipe.itemGap}px`, "--hjm-attachment-size": `${screenPatternRecipe.attachmentSize}px`, "--hjm-attachment-remove-size": `${screenPatternRecipe.attachmentRemoveSize}px`, ...layoutStyle }, children: [context, quickRow, _jsxs("div", { className: "hjm-message-composer__reply-card", "data-replying": replyTo ? true : undefined, children: [replyTo ? _jsxs("div", { className: "hjm-message-composer__reply", children: [_jsxs("div", { className: "hjm-message-composer__reply-text", children: [_jsx(Text, { emphasis: "strong", children: replyTo.author }), _jsx(Text, { variant: "caption", tone: "muted", className: "hjm-message-composer__reply-excerpt", children: replyTo.excerpt })] }), _jsx(IconButton, { label: replyTo.cancelLabel, tone: "secondary", size: "small", shape: "circle", disabled: locked, onClick: replyTo.onCancel, children: _jsx(Text, { children: "\u00D7" }) })] }) : null, composerBody] }), lengthFeedback && limit?.near ? _jsx(Progress, { shape: "circular", label: lengthFeedback.label, value: Math.min(limit.used, limit.max), max: limit.max, valueText: lengthFeedback.formatCount(limit.used, limit.max), children: _jsx(Text, { variant: "caption", children: lengthFeedback.formatCount(limit.used, limit.max) }) }) : null] });
115
126
  }
116
- export function ChatMessage({ direction, author, timestamp, timestampPresentation = "always", bubbleTail = true, groupPosition = "single", deliveryLabel, avatar, reply, replyQuote, media = [], actions, replyAction, replyLink, reactions, children, interactiveContent = false, layoutStyle }) {
127
+ export function ChatMessage({ direction, author, timestamp, timestampPresentation = "always", bubbleTail = true, groupPosition = "single", deliveryLabel, avatar, reply, replyQuote, media = [], mediaAlbum, actions, replyAction, replyLink, reactions, children, interactiveContent = false, layoutStyle }) {
117
128
  const theme = useOptionalHjmTheme();
118
129
  const display = resolveChatMessageGroupDisplay(groupPosition);
119
130
  // A run shows its time once, beside its last bubble; delivery state stays on every bubble.
120
131
  const visibleTime = display.showTimestamp ? timestamp : "";
121
132
  const quote = replyQuote ? _jsxs(_Fragment, { children: [_jsx(Text, { emphasis: "strong", children: replyQuote.title }), _jsx(Text, { tone: "muted", className: "hjm-chat-message__quote-excerpt", children: replyQuote.excerpt })] }) : reply;
122
133
  // The quote stays inside the bubble; with replyLink a click on it jumps to the original (2026-10-16 reference).
123
- const mediaBlock = media.length ? _jsx("div", { className: "hjm-chat-message__media", style: { inlineSize: chatMessageRecipe.mediaWidth, gap: chatMessageRecipe.mediaGap, gridTemplateColumns: `repeat(${resolveChatMediaColumns(media.length)}, minmax(0, 1fr))` }, children: media.map(item => { const style = { aspectRatio: media.length > 1 ? 1 : item.aspectRatio ?? 1 }; return item.onPress ? _jsx("button", { type: "button", className: "hjm-chat-message__media-item", "aria-label": item.label, style: style, onClick: item.onPress, children: item.preview }, item.id) : _jsx("div", { role: "img", "aria-label": item.label, className: "hjm-chat-message__media-item", style: style, children: item.preview }, item.id); }) }) : null;
134
+ validateMediaSetChoice(media.length > 0, mediaAlbum !== undefined);
135
+ const [albumIndex, setAlbumIndex] = useMediaAlbumIndex(mediaAlbum);
136
+ const mediaBlock = mediaAlbum ? _jsx(MediaAlbumView, { album: mediaAlbum, index: albumIndex, onIndexChange: setAlbumIndex, width: chatMessageRecipe.mediaWidth, radius: chatMessageRecipe.bubbleRadius })
137
+ : media.length ? _jsx("div", { className: "hjm-chat-message__media", style: { inlineSize: chatMessageRecipe.mediaWidth, gap: chatMessageRecipe.mediaGap, gridTemplateColumns: `repeat(${resolveChatMediaColumns(media.length)}, minmax(0, 1fr))` }, children: media.map(item => { const style = { aspectRatio: media.length > 1 ? 1 : item.aspectRatio ?? 1 }; return item.onPress ? _jsx("button", { type: "button", className: "hjm-chat-message__media-item", "aria-label": item.label, style: style, onClick: item.onPress, children: item.preview }, item.id) : _jsx("div", { role: "img", "aria-label": item.label, className: "hjm-chat-message__media-item", style: style, children: item.preview }, item.id); }) }) : null;
124
138
  // A photo-only message drops the bubble surface so the photo itself is the message.
125
- const photoOnly = media.length > 0 && !reply && !replyQuote && (children === null || children === undefined || children === false || children === "");
139
+ const photoOnly = (media.length > 0 || mediaAlbum !== undefined) && !reply && !replyQuote && (children === null || children === undefined || children === false || children === "");
126
140
  const quoteBlock = quote ? (replyLink ? _jsx("button", { type: "button", className: "hjm-chat-message__reply hjm-chat-message__quote", "aria-label": replyLink.label, onClick: replyLink.onPress, children: quote }) : _jsx("div", { className: "hjm-chat-message__reply", children: quote })) : null;
127
141
  const revealTime = timestampPresentation === "swipe" && !!timestamp;
128
142
  // Only the pointer that began a drag can finish it; another touch must not reply or cancel it.
129
143
  const start = useRef(null);
130
144
  const [offset, setOffset] = useState(0);
131
145
  const finish = () => { start.current = null; setOffset(0); };
146
+ const menu = useRef(null);
147
+ const summary = reactions?.summary;
148
+ const reactionMenu = reactions ? omitReactionSummary(reactions) : undefined;
149
+ const summaryItems = summary ? resolveChatReactionSummary(summary) : [];
150
+ const summaryButton = reactions && summary && summaryItems.length ? (summary.readOnly ? _jsx(ReactionSummaryText, { label: summary.label, items: summaryItems }) : _jsx(ReactionSummaryButton, { label: summary.label, items: summaryItems, selected: reactions.value, disabled: reactions.disabled ?? false, onPress: () => menu.current?.open() })) : null;
132
151
  return _jsxs("article", { tabIndex: replyAction && !replyAction.disabled ? 0 : undefined, "aria-keyshortcuts": replyAction ? "Alt+ArrowLeft Alt+ArrowRight" : undefined, "aria-description": replyAction?.label, onKeyDown: event => { if (event.target === event.currentTarget && event.altKey && (event.key === "ArrowLeft" || event.key === "ArrowRight") && replyAction && !replyAction.disabled) {
133
152
  event.preventDefault();
134
153
  replyAction.onPress();
@@ -146,7 +165,7 @@ export function ChatMessage({ direction, author, timestamp, timestampPresentatio
146
165
  finish(); }, onPointerLeave: event => { if (start.current?.pointerId === event.pointerId)
147
166
  finish(); }, style: { ...layoutStyle, position: "relative", overflow: "hidden", marginBlockStart: display.spacingBefore,
148
167
  // Reserve tip room only where it protrudes (own trailing edge, or leading edge without an avatar column).
149
- ...(bubbleTail ? (direction === "outgoing" ? { paddingInlineEnd: chatMessageRecipe.tailWidth } : avatar ? {} : { paddingInlineStart: chatMessageRecipe.tailWidth }) : {}), touchAction: revealTime || replyAction ? "pan-y" : undefined }, "aria-label": author, children: [revealTime ? _jsx("time", { style: { position: "absolute", ...(direction === "outgoing" ? { right: 0, justifyContent: "flex-end" } : { left: 0 }), top: 0, bottom: 0, width: 80, display: "flex", alignItems: "center", opacity: offset !== 0 ? 1 : 0, pointerEvents: "none" }, children: _jsx(Text, { variant: "caption", tone: "muted", children: timestamp }) }) : null, _jsxs("div", { className: "hjm-chat-message", style: { transform: `translateX(${offset}px)`, transition: start.current || theme?.environment.reducedMotion ? "none" : "transform var(--hjm-motion-normal, 200ms) ease-out", "--hjm-message-max-width": screenPatternRecipe.messageMaxWidth, "--hjm-chat-avatar-size": `${chatMessageRecipe.avatarSize}px` }, "data-direction": direction, "data-tail": (bubbleTail && display.showTail) || undefined, children: [avatar ? _jsx("div", { className: "hjm-chat-message__avatar", "aria-hidden": display.showAvatar ? undefined : true, children: display.showAvatar ? avatar : null }) : null, _jsxs("div", { className: "hjm-chat-message__content", children: [author && display.showAuthor && direction !== "outgoing" ? _jsx(Text, { variant: "caption", tone: "muted", children: author }) : null, _jsxs("div", { className: "hjm-chat-message__body", children: [reactions ? _jsxs(MessageReactions, { ...reactions, interactiveContent: interactiveContent, ...(timestamp ? { menuTitle: timestamp } : {}), ...(replyAction && !replyAction.disabled ? { replyAction } : {}), children: [quoteBlock, mediaBlock, photoOnly ? null : children] }) : _jsxs("div", { className: "hjm-chat-message__bubble", "data-photo-only": photoOnly || undefined, children: [quoteBlock, mediaBlock, photoOnly ? null : children] }), (!revealTime && visibleTime) || deliveryLabel || actions ? _jsxs("div", { className: "hjm-chat-message__meta", children: [(!revealTime && visibleTime) || deliveryLabel ? _jsx(Text, { variant: "caption", tone: "muted", children: [revealTime ? "" : visibleTime, deliveryLabel].filter(Boolean).join(" · ") }) : null, actions] }) : null] })] })] })] });
168
+ ...(bubbleTail ? (direction === "outgoing" ? { paddingInlineEnd: chatMessageRecipe.tailWidth } : avatar ? {} : { paddingInlineStart: chatMessageRecipe.tailWidth }) : {}), touchAction: revealTime || replyAction ? "pan-y" : undefined }, "aria-label": author, children: [revealTime ? _jsx("time", { style: { position: "absolute", ...(direction === "outgoing" ? { right: 0, justifyContent: "flex-end" } : { left: 0 }), top: 0, bottom: 0, width: 80, display: "flex", alignItems: "center", opacity: offset !== 0 ? 1 : 0, pointerEvents: "none" }, children: _jsx(Text, { variant: "caption", tone: "muted", children: timestamp }) }) : null, _jsxs("div", { className: "hjm-chat-message", style: { transform: `translateX(${offset}px)`, transition: start.current || theme?.environment.reducedMotion ? "none" : "transform var(--hjm-motion-normal, 200ms) ease-out", "--hjm-message-max-width": screenPatternRecipe.messageMaxWidth, "--hjm-chat-avatar-size": `${chatMessageRecipe.avatarSize}px` }, "data-direction": direction, "data-tail": (bubbleTail && display.showTail) || undefined, children: [avatar ? _jsx("div", { className: "hjm-chat-message__avatar", "aria-hidden": display.showAvatar ? undefined : true, children: display.showAvatar ? avatar : null }) : null, _jsxs("div", { className: "hjm-chat-message__content", children: [author && display.showAuthor && direction !== "outgoing" ? _jsx(Text, { variant: "caption", tone: "muted", children: author }) : null, _jsxs("div", { className: "hjm-chat-message__body", children: [reactionMenu ? _jsxs(MessageReactions, { ...reactionMenu, menuRef: menu, interactiveContent: interactiveContent || mediaAlbum !== undefined, ...(timestamp ? { menuTitle: timestamp } : {}), ...(replyAction && !replyAction.disabled ? { replyAction } : {}), children: [quoteBlock, mediaBlock, photoOnly ? null : children] }) : _jsxs("div", { className: "hjm-chat-message__bubble", "data-photo-only": photoOnly || undefined, children: [quoteBlock, mediaBlock, photoOnly ? null : children] }), (!revealTime && visibleTime) || deliveryLabel || actions || summaryButton ? _jsxs("div", { className: "hjm-chat-message__meta", children: [summaryButton, (!revealTime && visibleTime) || deliveryLabel ? _jsx(Text, { variant: "caption", tone: "muted", children: [revealTime ? "" : visibleTime, deliveryLabel].filter(Boolean).join(" · ") }) : null, actions] }) : null] })] })] })] });
150
169
  }
151
170
  export function CompositionLayout({ title, headingLevel = 3, description, badge, leading, actions, notice, children, footer, state = { kind: "ready" }, stateAction, loadingIndicator, layoutStyle }) {
152
171
  const resolved = resolveScreenContentState(state);
@@ -158,8 +177,51 @@ export function NotificationRow({ preview, metadata, avatar, avatarBadge, thumbn
158
177
  return _jsxs("span", { "aria-hidden": "true", "data-hjm-notification-row": "true", style: { display: "flex", alignItems: "center", gap: r.gap, padding: `${r.paddingBlock}px ${r.paddingInline}px`, width: "100%", minWidth: 0, boxSizing: "border-box" }, children: [_jsxs("span", { style: { position: "relative", width: r.avatarSize, height: r.avatarSize, flexShrink: 0 }, children: [_jsx("span", { style: { display: "flex", width: "100%", height: "100%", overflow: "hidden", borderRadius: "50%" }, children: avatar }), avatarBadge ? _jsx("span", { style: { position: "absolute", bottom: 0, right: 0, display: "flex", alignItems: "center", justifyContent: "center", width: r.avatarBadgeSize, height: r.avatarBadgeSize, borderRadius: "50%", background: "var(--hjm-color-surface)", border: "2px solid var(--hjm-color-surface)", boxSizing: "border-box" }, children: avatarBadge }) : null] }), _jsxs("span", { style: { flex: 1, minWidth: 0, display: "flex", flexDirection: "column", gap: r.contentGap }, children: [_jsx(Text, { style: { display: "-webkit-box", WebkitBoxOrient: "vertical", WebkitLineClamp: r.previewLines, overflow: "hidden" }, children: preview }), _jsxs("span", { style: { display: "flex", alignItems: "center", gap: r.contentGap }, children: [_jsx(Text, { variant: "caption", tone: "muted", children: metadata }), unread ? _jsx("span", { "data-hjm-unread-dot": "true", style: { width: r.unreadSize, height: r.unreadSize, borderRadius: "50%", flexShrink: 0, background: "var(--hjm-color-content-brand)" } }) : null] })] }), thumbnail ? _jsx("span", { style: { width: r.thumbnailSize, height: r.thumbnailSize, flexShrink: 0, overflow: "hidden", borderRadius: "var(--hjm-radius-sm)" }, children: thumbnail }) : null] });
159
178
  }
160
179
  /** Presentation shared by launcher and profile grids; the host owns navigation or drag behavior. */
161
- export function IconTile({ icon, label, overlay, labelLines = 1, ghost = false }) {
180
+ export function IconTile({ icon, label, overlay, labelLines = 1, ghost = false, frame = iconTileRecipe.defaults.frame, shape = iconTileRecipe.defaults.shape, size = iconTileRecipe.defaults.size }) {
162
181
  const r = iconTileRecipe;
163
- return _jsxs("span", { "data-hjm-icon-tile": "true", style: { display: "flex", flexDirection: "column", alignItems: "center", gap: r.gap, minWidth: 0, width: "100%", overflow: "visible" }, children: [_jsxs("span", { style: { position: "relative", display: "flex", alignItems: "center", justifyContent: "center", width: r.iconSize, height: r.iconSize, flexShrink: 0, borderRadius: r.iconRadius, background: "var(--hjm-color-surface-alt)", color: "var(--hjm-color-text)", boxShadow: ghost ? undefined : "0 0 0 1px var(--hjm-color-border)", outline: ghost ? "1px dashed var(--hjm-color-text-muted)" : undefined, opacity: ghost ? r.ghostOpacity : 1, fontSize: 32 }, children: [icon, overlay] }), _jsx(Text, { variant: "caption", style: { display: "-webkit-box", WebkitBoxOrient: "vertical", WebkitLineClamp: labelLines, width: "100%", maxWidth: labelLines === 2 ? r.multilineLabelMaxWidth : r.labelMaxWidth, minHeight: labelLines === 2 ? r.multilineLabelMinHeight : undefined, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "normal", overflowWrap: "anywhere", textAlign: "center", fontWeight: 500 }, children: label })] });
182
+ const framed = frame === "surface";
183
+ // Percent radius follows the rendered size, so a filling icon keeps its shape at every cell width.
184
+ const dimensions = size === "fill" ? { width: "100%", minWidth: r.fillMinSize, maxWidth: r.fillMaxSize, aspectRatio: "1" } : { width: r.iconSize, height: r.iconSize };
185
+ // A render-function icon needs the filling edge as a number. It is read before paint and on every resize; the
186
+ // computed width ignores transforms (a host's press scale) and keeps fractional cell widths.
187
+ const frameRef = useRef(null);
188
+ const measureEdge = size === "fill" && typeof icon === "function";
189
+ const [fillEdge, setFillEdge] = useState(r.fillMinSize);
190
+ useLayoutEffect(() => {
191
+ const element = frameRef.current;
192
+ if (!measureEdge || !element)
193
+ return;
194
+ setFillEdge(Number.parseFloat(getComputedStyle(element).width) || r.fillMinSize);
195
+ if (typeof ResizeObserver === "undefined")
196
+ return;
197
+ const observer = new ResizeObserver(([entry]) => { const width = entry?.borderBoxSize?.[0]?.inlineSize; if (width)
198
+ setFillEdge(width); });
199
+ observer.observe(element);
200
+ return () => observer.disconnect();
201
+ }, [measureEdge, r.fillMinSize]);
202
+ const edge = size === "fill" ? fillEdge : r.iconSize;
203
+ return _jsxs("span", { "data-hjm-icon-tile": "true", "data-frame": frame, "data-shape": shape, "data-size": size, style: { display: "flex", flexDirection: "column", alignItems: "center", gap: r.gap, minWidth: 0, width: "100%", overflow: "visible" }, children: [_jsxs("span", { ref: frameRef, style: { position: "relative", display: "flex", alignItems: "center", justifyContent: "center", ...dimensions, boxSizing: "border-box", flexShrink: 0, borderRadius: `${Math.round(r.shapes[shape] * 100)}%`, background: framed ? "var(--hjm-color-surface-alt)" : undefined, color: "var(--hjm-color-text)", boxShadow: ghost || !framed ? undefined : "0 0 0 1px var(--hjm-color-border)", outline: ghost ? "1px dashed var(--hjm-color-text-muted)" : undefined, opacity: ghost ? r.ghostOpacity : 1, fontSize: 32 }, children: [typeof icon === "function" ? icon({ edge }) : icon, overlay] }), _jsx(Text, { variant: "caption", style: { display: "-webkit-box", WebkitBoxOrient: "vertical", WebkitLineClamp: labelLines, width: "100%", maxWidth: labelLines === 2 ? r.multilineLabelMaxWidth : r.labelMaxWidth, minHeight: labelLines === 2 ? r.multilineLabelMinHeight : undefined, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "normal", overflowWrap: "anywhere", textAlign: "center", fontWeight: 500 }, children: label })] });
204
+ }
205
+ /**
206
+ * Incoming "is typing" row for a ChatScreen timeline (2026-10-18 BurnTok DM drew its own). The host shows it only while
207
+ * presence says someone is typing and places it after the last message; HJM owns the bubble, dots and announcement.
208
+ */
209
+ export function TypingIndicator({ label, avatar, layoutStyle }) {
210
+ if (!label.trim())
211
+ throw new TypeError("TypingIndicator requires a localized label");
212
+ const theme = useOptionalHjmTheme();
213
+ const r = typingIndicatorRecipe, m = chatMessageRecipe;
214
+ // A polite status: appearing is announced once without interrupting, and the dots stay hidden from assistive tech.
215
+ return _jsxs("div", { role: "status", className: "hjm-typing-indicator", "data-reduced-motion": theme?.environment.reducedMotion || undefined, style: { display: "flex", alignItems: "flex-start", gap: m.avatarGap, marginBlockStart: m.groupGap, paddingInlineStart: avatar ? 0 : m.tailWidth, ...layoutStyle, "--hjm-typing-dot": `${r.dotSize}px`, "--hjm-typing-cycle": `${r.cycleMs}ms`, "--hjm-typing-rest": r.restOpacity }, children: [avatar ? _jsx("span", { "aria-hidden": "true", style: { display: "flex", justifyContent: "center", flex: `0 0 ${m.avatarSize}px`, inlineSize: m.avatarSize }, children: avatar }) : null, _jsx("span", { "aria-hidden": "true", className: "hjm-typing-indicator__bubble", style: { display: "inline-flex", alignItems: "center", gap: r.dotGap, boxSizing: "border-box", minBlockSize: `calc(var(--hjm-type-body-line-height) + ${m.bubblePaddingBlock * 2}px)`, paddingBlock: m.bubblePaddingBlock, paddingInline: m.bubblePaddingInline, borderRadius: m.bubbleRadius, background: "var(--hjm-color-surface)" }, children: [0, 1, 2].map(index => _jsx("span", { className: "hjm-typing-indicator__dot", style: { animationDelay: `${index * r.staggerMs}ms` } }, index)) }), _jsx(VisuallyHidden, { children: label })] });
216
+ }
217
+ /**
218
+ * Centered date (or time) row between ChatScreen timeline groups (2026-10-18 Utilverse chat drew a caption). Grouping
219
+ * rules stay with the product; the next message keeps its own group gap, so this row adds only the space before it.
220
+ */
221
+ export function ChatDateSeparator({ label, dateTime, layoutStyle }) {
222
+ if (!label.trim())
223
+ throw new TypeError("ChatDateSeparator requires a localized label");
224
+ const r = chatDateSeparatorRecipe;
225
+ return _jsx("div", { className: "hjm-chat-date-separator", style: { display: "flex", justifyContent: "center", textAlign: "center", paddingBlockStart: r.paddingTop, paddingBlockEnd: r.paddingBottom, ...layoutStyle }, children: _jsx(Text, { variant: r.textVariant, tone: r.tone, children: dateTime ? _jsx("time", { dateTime: dateTime, children: label }) : label }) });
164
226
  }
165
227
  //# sourceMappingURL=screens.js.map