@hjmds/react-native 0.8.2

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 (94) hide show
  1. package/README.md +310 -0
  2. package/dist/actions.d.ts +128 -0
  3. package/dist/actions.d.ts.map +1 -0
  4. package/dist/actions.js +157 -0
  5. package/dist/actions.js.map +1 -0
  6. package/dist/data-display.d.ts +285 -0
  7. package/dist/data-display.d.ts.map +1 -0
  8. package/dist/data-display.js +775 -0
  9. package/dist/data-display.js.map +1 -0
  10. package/dist/date-picker.d.ts +25 -0
  11. package/dist/date-picker.d.ts.map +1 -0
  12. package/dist/date-picker.js +39 -0
  13. package/dist/date-picker.js.map +1 -0
  14. package/dist/evidence.d.ts +954 -0
  15. package/dist/evidence.d.ts.map +1 -0
  16. package/dist/evidence.js +98 -0
  17. package/dist/evidence.js.map +1 -0
  18. package/dist/feedback.d.ts +148 -0
  19. package/dist/feedback.d.ts.map +1 -0
  20. package/dist/feedback.js +559 -0
  21. package/dist/feedback.js.map +1 -0
  22. package/dist/file-picker.d.ts +20 -0
  23. package/dist/file-picker.d.ts.map +1 -0
  24. package/dist/file-picker.js +37 -0
  25. package/dist/file-picker.js.map +1 -0
  26. package/dist/forms.d.ts +170 -0
  27. package/dist/forms.d.ts.map +1 -0
  28. package/dist/forms.js +595 -0
  29. package/dist/forms.js.map +1 -0
  30. package/dist/index.d.ts +16 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +16 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/inputs-public.d.ts +6 -0
  35. package/dist/inputs-public.d.ts.map +1 -0
  36. package/dist/inputs-public.js +6 -0
  37. package/dist/inputs-public.js.map +1 -0
  38. package/dist/inputs.d.ts +258 -0
  39. package/dist/inputs.d.ts.map +1 -0
  40. package/dist/inputs.js +681 -0
  41. package/dist/inputs.js.map +1 -0
  42. package/dist/internal/modal-lifecycle.d.ts +15 -0
  43. package/dist/internal/modal-lifecycle.d.ts.map +1 -0
  44. package/dist/internal/modal-lifecycle.js +17 -0
  45. package/dist/internal/modal-lifecycle.js.map +1 -0
  46. package/dist/internal/state.d.ts +8 -0
  47. package/dist/internal/state.d.ts.map +1 -0
  48. package/dist/internal/state.js +18 -0
  49. package/dist/internal/state.js.map +1 -0
  50. package/dist/internal/styles.d.ts +29 -0
  51. package/dist/internal/styles.d.ts.map +1 -0
  52. package/dist/internal/styles.js +51 -0
  53. package/dist/internal/styles.js.map +1 -0
  54. package/dist/navigation.d.ts +271 -0
  55. package/dist/navigation.d.ts.map +1 -0
  56. package/dist/navigation.js +978 -0
  57. package/dist/navigation.js.map +1 -0
  58. package/dist/number-field.d.ts +58 -0
  59. package/dist/number-field.d.ts.map +1 -0
  60. package/dist/number-field.js +172 -0
  61. package/dist/number-field.js.map +1 -0
  62. package/dist/otp-field.d.ts +2 -0
  63. package/dist/otp-field.d.ts.map +1 -0
  64. package/dist/otp-field.js +2 -0
  65. package/dist/otp-field.js.map +1 -0
  66. package/dist/overlays.d.ts +68 -0
  67. package/dist/overlays.d.ts.map +1 -0
  68. package/dist/overlays.js +757 -0
  69. package/dist/overlays.js.map +1 -0
  70. package/dist/password-field.d.ts +2 -0
  71. package/dist/password-field.d.ts.map +1 -0
  72. package/dist/password-field.js +2 -0
  73. package/dist/password-field.js.map +1 -0
  74. package/dist/primitives.d.ts +132 -0
  75. package/dist/primitives.d.ts.map +1 -0
  76. package/dist/primitives.js +238 -0
  77. package/dist/primitives.js.map +1 -0
  78. package/dist/provider.d.ts +41 -0
  79. package/dist/provider.d.ts.map +1 -0
  80. package/dist/provider.js +78 -0
  81. package/dist/provider.js.map +1 -0
  82. package/dist/slider.d.ts +45 -0
  83. package/dist/slider.d.ts.map +1 -0
  84. package/dist/slider.js +200 -0
  85. package/dist/slider.js.map +1 -0
  86. package/dist/steps.d.ts +13 -0
  87. package/dist/steps.d.ts.map +1 -0
  88. package/dist/steps.js +13 -0
  89. package/dist/steps.js.map +1 -0
  90. package/dist/upload-item.d.ts +13 -0
  91. package/dist/upload-item.d.ts.map +1 -0
  92. package/dist/upload-item.js +25 -0
  93. package/dist/upload-item.js.map +1 -0
  94. package/package.json +166 -0
@@ -0,0 +1,775 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { resolveColorReference } from "@hjmds/design-contracts/color-references";
3
+ import { glyph, radius, spacing } from "@hjmds/design-contracts/foundations";
4
+ import { resolveDescriptionListColumnCount, resolveDescriptionListDescriptor, } from "@hjmds/design-contracts/components/description-list";
5
+ import { resolveStatisticDescriptor, validateStatisticGroup, } from "@hjmds/design-contracts/components/statistic";
6
+ import { resolveTagDescriptor, resolveTagPresentation, tagRecipe, } from "@hjmds/design-contracts/components/tag";
7
+ import { cardRecipe } from "@hjmds/design-contracts/components/card";
8
+ import { imageRecipe, nativeResizeModes, resolveImageAspectRatio, resolveImageDescriptor, resolveImageFallbackAccessibilityLabel, } from "@hjmds/design-contracts/components/image";
9
+ import { resolveTimelineDescriptor, timelineRecipe, } from "@hjmds/design-contracts/components/timeline";
10
+ import { surfaceGeometry } from "@hjmds/design-contracts/recipes/base";
11
+ import { accordionRecipe, counterBadgeRecipe, badgeRecipe, listRecipe, formatCounterBadgeCount, listRowRecipe, statisticRecipe, } from "@hjmds/design-contracts/recipes";
12
+ import { Children, isValidElement, useEffect, useMemo, useState, } from "react";
13
+ import { Image as NativeImage, LayoutAnimation, Pressable, StyleSheet, View, useWindowDimensions, } from "react-native";
14
+ import { useControllableState } from "./internal/state.js";
15
+ import { minimumTargetStyle } from "./internal/styles.js";
16
+ import { Surface, Text, } from "./primitives.js";
17
+ import { useHjmNativeTheme } from "./provider.js";
18
+ export function Badge({ label, tone = badgeRecipe.defaults.tone, size = badgeRecipe.defaults.size, variant = badgeRecipe.defaults.variant, leading, accessibilityLabel, style, labelStyle, ...props }) {
19
+ const theme = useHjmNativeTheme();
20
+ const presentation = badgeRecipe.tones[tone];
21
+ const metrics = badgeRecipe.sizes[size];
22
+ const variantPresentation = badgeRecipe.variants[variant];
23
+ const outlined = !variantPresentation.usesToneBackground;
24
+ const borderColor = presentation.border
25
+ ? resolveColorReference(presentation.border, theme.palette)
26
+ : variantPresentation.borderFallback === null
27
+ ? "transparent"
28
+ : resolveColorReference(variantPresentation.borderFallback, theme.palette);
29
+ return (_jsxs(View, { ...props, accessibilityLabel: accessibilityLabel ?? String(label), accessible: true, style: [
30
+ {
31
+ alignSelf: "flex-start",
32
+ alignItems: "center",
33
+ backgroundColor: outlined
34
+ ? "transparent"
35
+ : resolveColorReference(presentation.background, theme.palette),
36
+ borderColor,
37
+ borderRadius: radius[badgeRecipe.radius],
38
+ borderWidth: presentation.border || variantPresentation.borderFallback
39
+ ? badgeRecipe.borderWidth
40
+ : 0,
41
+ direction: theme.environment.direction,
42
+ flexDirection: "row",
43
+ gap: metrics.gap,
44
+ justifyContent: "center",
45
+ minHeight: metrics.minHeight,
46
+ paddingHorizontal: metrics.paddingHorizontal,
47
+ },
48
+ style,
49
+ ], children: [leading === undefined ? null : (_jsx(View, { accessibilityElementsHidden: true, accessible: false, importantForAccessibility: "no-hide-descendants", children: leading })), _jsx(Text, { accessible: false, align: "center", emphasis: "strong", style: [
50
+ {
51
+ color: resolveColorReference(outlined ? presentation.outlineContent : presentation.content, theme.palette),
52
+ },
53
+ labelStyle,
54
+ ], variant: metrics.textVariant, children: label })] }));
55
+ }
56
+ export function Tag({ children, label, tone, accessibilityLabel, style, labelStyle, ...props }) {
57
+ const theme = useHjmNativeTheme();
58
+ const resolvedLabel = children ?? label;
59
+ if (resolvedLabel === undefined) {
60
+ throw new TypeError("Tag requires children (or the deprecated label prop)");
61
+ }
62
+ const descriptor = resolveTagDescriptor({
63
+ label: resolvedLabel,
64
+ ...(tone === undefined ? {} : { tone }),
65
+ });
66
+ const presentation = resolveTagPresentation(descriptor.tone, theme.palette);
67
+ return (_jsx(View, { ...props, accessibilityLabel: accessibilityLabel ?? descriptor.label, accessible: true, style: [
68
+ {
69
+ alignItems: "center",
70
+ alignSelf: "flex-start",
71
+ backgroundColor: presentation.background,
72
+ borderColor: presentation.border ?? "transparent",
73
+ borderRadius: radius[tagRecipe.radius],
74
+ borderWidth: tagRecipe.borderWidth,
75
+ direction: theme.environment.direction,
76
+ flexDirection: "row",
77
+ gap: tagRecipe.size.gap,
78
+ minHeight: tagRecipe.size.minHeight,
79
+ paddingHorizontal: tagRecipe.size.paddingHorizontal,
80
+ },
81
+ style,
82
+ ], children: _jsx(Text, { align: "center", emphasis: "medium", style: [{ color: presentation.content }, labelStyle], variant: tagRecipe.size.textVariant, children: descriptor.label }) }));
83
+ }
84
+ export function Card({ children, title, description, leading, media, actions, selected = cardRecipe.defaults.selected, tone = cardRecipe.defaults.tone, bordered = cardRecipe.defaults.bordered, padding = cardRecipe.defaults.padding, style, ...props }) {
85
+ const { environment } = useHjmNativeTheme();
86
+ const bodyPadding = typeof padding === "number" ? padding : surfaceGeometry.paddings[padding];
87
+ const hasHeader = leading !== undefined || title !== undefined || description !== undefined;
88
+ return (_jsxs(Surface, { ...props, bordered: bordered, padding: "none", style: [{ overflow: "hidden" }, style], tone: selected ? cardRecipe.selectedTone : tone, children: [media === undefined ? null : _jsx(View, { children: media }), _jsxs(View, { style: { gap: cardRecipe.body.gap, padding: bodyPadding }, children: [hasHeader ? (_jsxs(View, { style: {
89
+ alignItems: "flex-start",
90
+ direction: environment.direction,
91
+ flexDirection: "row",
92
+ gap: cardRecipe.header.gap,
93
+ }, children: [leading === undefined ? null : (_jsx(View, { style: { flexShrink: 0 }, children: leading })), _jsxs(View, { style: { flex: 1, gap: cardRecipe.body.gap, minWidth: 0 }, children: [title === undefined ? null : (_jsx(Text, { accessibilityRole: "header", emphasis: "strong", tone: "primary", variant: "title", children: title })), description === undefined ? null : (_jsx(Text, { emphasis: "regular", tone: "muted", variant: "body", children: description }))] })] })) : null, children === undefined ? null : _jsx(View, { children: children })] }), actions === undefined ? null : (_jsx(View, { style: {
94
+ direction: environment.direction,
95
+ flexDirection: "row",
96
+ flexWrap: "wrap",
97
+ gap: cardRecipe.actions.gap,
98
+ paddingBottom: cardRecipe.actions.paddingBottom,
99
+ paddingHorizontal: cardRecipe.actions.paddingHorizontal,
100
+ }, children: actions }))] }));
101
+ }
102
+ export function ListRow({ title, description, leading, trailing, titleMetadata, badge, trailingAction, trailingText, metadataLabel, trailingLabel, onPress, accessibilityLabel, accessibilityHint, disabled = false, density = listRowRecipe.defaults.density, selected: selectedProp, style, leadingStyle, contentStyle, titleStyle, titleRowStyle, descriptionStyle, trailingStyle, trailingActionStyle, containerProps, accessibilityState, ...props }) {
103
+ const theme = useHjmNativeTheme();
104
+ const metrics = listRowRecipe.density[density];
105
+ const interactive = onPress !== undefined;
106
+ const selected = selectedProp ?? listRowRecipe.defaults.selected;
107
+ const resolvedMetadata = titleMetadata ?? badge;
108
+ const resolvedTrailingLabel = trailingLabel ?? trailingText;
109
+ const composedLabel = accessibilityLabel ?? [
110
+ title,
111
+ metadataLabel,
112
+ description,
113
+ resolvedTrailingLabel,
114
+ ].filter(Boolean).join(", ");
115
+ const visualState = {
116
+ backgroundColor: selected
117
+ ? resolveColorReference(listRowRecipe.states.selectedBackground, theme.palette)
118
+ : "transparent",
119
+ direction: theme.environment.direction,
120
+ minHeight: description ? metrics.twoLineMinHeight : metrics.oneLineMinHeight,
121
+ opacity: disabled ? listRowRecipe.states.disabledOpacity : 1,
122
+ };
123
+ const rowContent = (_jsxs(_Fragment, { children: [leading ? (_jsx(View, { accessible: interactive ? false : undefined, importantForAccessibility: interactive ? "no-hide-descendants" : "auto", style: leadingStyle, children: leading })) : null, _jsxs(View, { style: [{ flex: 1, gap: spacing.xxs, minWidth: 0 }, contentStyle], children: [_jsxs(View, { style: [
124
+ {
125
+ alignItems: "center",
126
+ direction: theme.environment.direction,
127
+ flexDirection: "row",
128
+ flexWrap: "wrap",
129
+ gap: spacing.xxs,
130
+ },
131
+ titleRowStyle,
132
+ ], children: [_jsx(Text, { style: [
133
+ {
134
+ color: resolveColorReference(listRowRecipe.title.color, theme.palette),
135
+ flexShrink: 1,
136
+ fontWeight: listRowRecipe.title.fontWeight,
137
+ },
138
+ titleStyle,
139
+ ], variant: listRowRecipe.title.textVariant, children: title }), resolvedMetadata === undefined ? null : (_jsx(View, { accessible: interactive ? false : undefined, importantForAccessibility: interactive ? "no-hide-descendants" : "auto", children: resolvedMetadata }))] }), description ? (_jsx(Text, { style: [
140
+ { color: resolveColorReference(listRowRecipe.description.color, theme.palette) },
141
+ descriptionStyle,
142
+ ], variant: listRowRecipe.description.textVariant, children: description })) : null] }), trailingText || trailing ? (_jsx(View, { accessible: interactive ? false : undefined, importantForAccessibility: interactive ? "no-hide-descendants" : "auto", style: [{ flexShrink: 0 }, trailingStyle], children: trailingText ? (_jsx(Text, { style: { color: resolveColorReference(listRowRecipe.trailing.textColor, theme.palette) }, variant: listRowRecipe.trailing.textVariant, children: trailingText })) : trailing })) : null] }));
143
+ const contentStyleFor = (pressed) => [
144
+ minimumTargetStyle,
145
+ {
146
+ alignItems: "center",
147
+ backgroundColor: pressed
148
+ ? resolveColorReference(listRowRecipe.states.pressedBackground, theme.palette)
149
+ : trailingAction
150
+ ? "transparent"
151
+ : visualState.backgroundColor,
152
+ direction: visualState.direction,
153
+ flex: trailingAction ? 1 : undefined,
154
+ flexDirection: "row",
155
+ gap: listRowRecipe.gap,
156
+ minHeight: visualState.minHeight,
157
+ opacity: trailingAction ? 1 : visualState.opacity,
158
+ ...(trailingAction
159
+ ? { paddingStart: metrics.paddingHorizontal }
160
+ : { paddingHorizontal: metrics.paddingHorizontal }),
161
+ paddingVertical: metrics.paddingVertical,
162
+ },
163
+ trailingAction ? undefined : style,
164
+ ];
165
+ const main = interactive ? (_jsx(Pressable, { ...props, accessibilityHint: accessibilityHint, accessibilityLabel: composedLabel, accessibilityRole: "button", accessibilityState: {
166
+ ...accessibilityState,
167
+ disabled,
168
+ ...(selectedProp === undefined ? {} : { selected: selectedProp }),
169
+ }, disabled: disabled, onPress: onPress, style: ({ pressed }) => contentStyleFor(pressed), children: rowContent })) : (_jsx(View, { ...props, accessibilityHint: accessibilityHint, accessibilityLabel: accessibilityLabel, accessible: accessibilityLabel === undefined ? undefined : true, style: contentStyleFor(false), children: rowContent }));
170
+ if (trailingAction === undefined || trailingAction === null)
171
+ return main;
172
+ return (_jsxs(View, { ...containerProps, style: [
173
+ {
174
+ alignItems: "center",
175
+ backgroundColor: visualState.backgroundColor,
176
+ direction: visualState.direction,
177
+ flexDirection: "row",
178
+ minHeight: visualState.minHeight,
179
+ opacity: visualState.opacity,
180
+ },
181
+ style,
182
+ ], children: [main, _jsx(View, { style: [
183
+ { flexShrink: 0, paddingEnd: metrics.paddingHorizontal },
184
+ trailingActionStyle,
185
+ ], children: trailingAction })] }));
186
+ }
187
+ function resolveInitials(name, provided) {
188
+ if (provided?.trim())
189
+ return provided.trim().slice(0, 3).toLocaleUpperCase();
190
+ const parts = name.trim().split(/\s+/u).filter(Boolean);
191
+ if (parts.length === 0)
192
+ throw new TypeError("Avatar name must not be empty");
193
+ return `${parts[0][0] ?? ""}${parts.length > 1 ? parts.at(-1)[0] ?? "" : ""}`
194
+ .toLocaleUpperCase();
195
+ }
196
+ export function Avatar({ source, name, initials, size = 44, decorative = false, accessibilityLabel, style, imageStyle, }) {
197
+ if (!Number.isFinite(size) || size < 24)
198
+ throw new RangeError("Avatar size must be at least 24");
199
+ const { colors } = useHjmNativeTheme();
200
+ const [failed, setFailed] = useState(false);
201
+ const fallback = resolveInitials(name, initials);
202
+ const mediaAccessibility = decorative
203
+ ? { accessible: false }
204
+ : { accessible: true, accessibilityLabel, accessibilityRole: "image" };
205
+ return (_jsx(View, { ...mediaAccessibility, style: [
206
+ {
207
+ alignItems: "center",
208
+ backgroundColor: colors.surfaceAccent,
209
+ borderRadius: radius.full,
210
+ height: size,
211
+ justifyContent: "center",
212
+ overflow: "hidden",
213
+ width: size,
214
+ },
215
+ style,
216
+ ], children: source !== undefined && !failed ? (_jsx(NativeImage, { accessible: false, onError: () => setFailed(true), source: source, style: [{ height: size, width: size }, imageStyle] })) : (_jsx(Text, { align: "center", style: { color: colors.contentBrand }, variant: "label", children: fallback })) }));
217
+ }
218
+ export function Divider({ orientation = "horizontal", inset = 0, style }) {
219
+ if (!Number.isFinite(inset) || inset < 0)
220
+ throw new RangeError("Divider inset must be non-negative");
221
+ const { colors } = useHjmNativeTheme();
222
+ return (_jsx(View, { accessible: false, style: [
223
+ orientation === "horizontal"
224
+ ? { backgroundColor: colors.border, height: 1, marginHorizontal: inset, width: "auto" }
225
+ : { alignSelf: "stretch", backgroundColor: colors.border, marginVertical: inset, width: 1 },
226
+ style,
227
+ ] }));
228
+ }
229
+ export function Accordion({ label, items, expandedValues, defaultExpandedValues = [], onExpandedValuesChange, multiple = accordionRecipe.defaults.allowsMultipleExpanded, density = accordionRecipe.defaults.density, renderIndicator, style, itemStyle, triggerStyle, titleStyle, indicatorStyle, panelStyle, }) {
230
+ if (items.length === 0)
231
+ throw new Error("Accordion requires at least one item");
232
+ const itemValues = new Set(items.map((item) => item.value));
233
+ if (itemValues.size !== items.length)
234
+ throw new TypeError("Accordion values must be unique");
235
+ const initial = expandedValues ?? defaultExpandedValues;
236
+ if (initial.some((value) => !itemValues.has(value))) {
237
+ throw new RangeError("Accordion expanded values must match items");
238
+ }
239
+ if (!multiple && initial.length > 1) {
240
+ throw new RangeError("Accordion only accepts one expanded value unless multiple is true");
241
+ }
242
+ const theme = useHjmNativeTheme();
243
+ const metrics = accordionRecipe.density[density];
244
+ const indicatorColor = resolveColorReference(accordionRecipe.indicator.color, theme.palette);
245
+ const [expanded, setExpanded] = useControllableState({
246
+ ...(expandedValues === undefined ? {} : { value: expandedValues }),
247
+ defaultValue: defaultExpandedValues,
248
+ ...(onExpandedValuesChange === undefined ? {} : { onChange: onExpandedValuesChange }),
249
+ });
250
+ return (_jsx(View, { accessibilityLabel: label, accessibilityRole: "list", style: style, children: items.map((item) => {
251
+ const isExpanded = expanded.includes(item.value);
252
+ return (_jsxs(View, { style: [
253
+ {
254
+ borderBottomColor: resolveColorReference(accordionRecipe.divider, theme.palette),
255
+ borderBottomWidth: 1,
256
+ },
257
+ itemStyle,
258
+ ], children: [_jsxs(Pressable, { accessibilityHint: item.accessibilityHint, accessibilityLabel: item.accessibilityLabel ?? item.title, accessibilityRole: "button", accessibilityState: { disabled: item.disabled === true, expanded: isExpanded }, disabled: item.disabled, onPress: () => {
259
+ if (!theme.environment.reducedMotion) {
260
+ LayoutAnimation.configureNext({
261
+ duration: accordionRecipe.transition.duration,
262
+ update: { type: LayoutAnimation.Types.easeInEaseOut },
263
+ });
264
+ }
265
+ if (isExpanded) {
266
+ setExpanded(expanded.filter((value) => value !== item.value));
267
+ }
268
+ else {
269
+ setExpanded(multiple ? [...expanded, item.value] : [item.value]);
270
+ }
271
+ }, style: ({ pressed }) => [
272
+ minimumTargetStyle,
273
+ {
274
+ alignItems: "center",
275
+ backgroundColor: pressed
276
+ ? resolveColorReference(accordionRecipe.states.pressedBackground, theme.palette)
277
+ : "transparent",
278
+ direction: theme.environment.direction,
279
+ flexDirection: "row",
280
+ gap: accordionRecipe.gap,
281
+ minHeight: metrics.triggerMinHeight,
282
+ opacity: item.disabled
283
+ ? accordionRecipe.states.disabledOpacity
284
+ : 1,
285
+ paddingHorizontal: accordionRecipe.paddingHorizontal,
286
+ paddingVertical: metrics.paddingVertical,
287
+ },
288
+ triggerStyle,
289
+ ], children: [_jsxs(View, { style: { flex: 1, gap: spacing.xxs }, children: [_jsx(Text, { style: [
290
+ {
291
+ color: resolveColorReference(accordionRecipe.title.color, theme.palette),
292
+ fontWeight: accordionRecipe.title.fontWeight,
293
+ },
294
+ titleStyle,
295
+ ], variant: accordionRecipe.title.textVariant, children: item.title }), item.description ? _jsx(Text, { tone: "muted", variant: "caption", children: item.description }) : null] }), _jsx(View, { accessible: false, style: indicatorStyle, children: renderIndicator ? (renderIndicator({
296
+ value: item.value,
297
+ expanded: isExpanded,
298
+ disabled: item.disabled === true,
299
+ color: indicatorColor,
300
+ size: glyph[accordionRecipe.indicator.glyph],
301
+ })) : (_jsx(Text, { style: { color: indicatorColor }, children: isExpanded ? "−" : "+" })) })] }), isExpanded ? (_jsx(View, { accessibilityLabel: item.contentAccessibilityLabel, style: [
302
+ {
303
+ paddingBottom: accordionRecipe.panel.paddingBottom,
304
+ paddingStart: accordionRecipe.panel.paddingInlineStart,
305
+ },
306
+ panelStyle,
307
+ ], children: item.content })) : null] }, item.value));
308
+ }) }));
309
+ }
310
+ export function DescriptionList({ label, descriptor, availableWidth, style, itemStyle, onLayout, ...props }) {
311
+ const resolved = resolveDescriptionListDescriptor(descriptor);
312
+ const { width: windowWidth } = useWindowDimensions();
313
+ const { environment } = useHjmNativeTheme();
314
+ const [measuredWidth, setMeasuredWidth] = useState(null);
315
+ const innerWidth = availableWidth ?? measuredWidth ?? windowWidth;
316
+ if (!Number.isFinite(innerWidth) || innerWidth <= 0) {
317
+ throw new RangeError("DescriptionList availableWidth must be positive");
318
+ }
319
+ const columns = resolveDescriptionListColumnCount(innerWidth, resolved.columns, environment.textScale);
320
+ const itemWidth = (innerWidth - spacing.sm * (columns - 1)) / columns;
321
+ const handleLayout = (event) => {
322
+ onLayout?.(event);
323
+ if (availableWidth !== undefined)
324
+ return;
325
+ const nextWidth = event.nativeEvent.layout.width;
326
+ if (Number.isFinite(nextWidth) && nextWidth > 0) {
327
+ setMeasuredWidth((current) => current === nextWidth ? current : nextWidth);
328
+ }
329
+ };
330
+ return (_jsx(View, { ...props, accessibilityLabel: label, accessibilityRole: "list", onLayout: handleLayout, style: [
331
+ {
332
+ direction: environment.direction,
333
+ flexDirection: "row",
334
+ flexWrap: "wrap",
335
+ gap: spacing.sm,
336
+ },
337
+ style,
338
+ ], children: resolved.items.map((item) => (_jsxs(View, { accessibilityLabel: `${item.label}, ${item.value}`, accessible: true, style: [{ gap: spacing.xxs, width: itemWidth }, itemStyle], children: [_jsx(Text, { accessible: false, tone: "muted", variant: "label", children: item.label }), _jsx(Text, { accessible: false, tone: "primary", children: item.value })] }, item.id))) }));
339
+ }
340
+ function resolveLegacyImageSourceKey(source) {
341
+ if (typeof source === "number")
342
+ return `asset:${source}`;
343
+ try {
344
+ return `source:${JSON.stringify(source)}`;
345
+ }
346
+ catch {
347
+ return `source:${String(source)}`;
348
+ }
349
+ }
350
+ function resolveLegacyMedia(decorative, accessibilityLabel) {
351
+ const resolvedDecorative = decorative ?? accessibilityLabel === undefined;
352
+ if (resolvedDecorative) {
353
+ if (accessibilityLabel !== undefined) {
354
+ throw new TypeError("Decorative Image must not provide accessibilityLabel");
355
+ }
356
+ return { decorative: true };
357
+ }
358
+ if (accessibilityLabel === undefined || accessibilityLabel.trim().length === 0) {
359
+ throw new TypeError("Informative Image accessibilityLabel must not be empty");
360
+ }
361
+ return { decorative: false, accessibilityLabel };
362
+ }
363
+ /** Intrinsic-size Native image with canonical fit, accessibility, and fallback semantics. */
364
+ export function Image(imageProps) {
365
+ const { source: legacySource, src, width, height, fit, decorative, accessibilityLabel, sourceAdapter, fallback, onError, onLoad, onLoadStatusChange, renderImage, resizeMode, style, containerStyle, ...nativeProps } = imageProps;
366
+ const theme = useHjmNativeTheme();
367
+ if (src !== undefined && legacySource !== undefined) {
368
+ throw new TypeError("Image accepts either canonical src or legacy source, not both");
369
+ }
370
+ if (src === undefined && legacySource === undefined) {
371
+ throw new TypeError("Image requires src or legacy source");
372
+ }
373
+ const descriptor = src === undefined
374
+ ? undefined
375
+ : resolveImageDescriptor({
376
+ src,
377
+ width: width,
378
+ height: height,
379
+ ...(fit === undefined ? {} : { fit }),
380
+ ...(decorative === undefined ? {} : { decorative }),
381
+ ...(accessibilityLabel === undefined ? {} : { accessibilityLabel }),
382
+ });
383
+ const legacyMedia = descriptor === undefined
384
+ ? resolveLegacyMedia(decorative, accessibilityLabel)
385
+ : undefined;
386
+ const resolvedDecorative = descriptor?.decorative ?? legacyMedia.decorative;
387
+ const resolvedAccessibilityLabel = descriptor?.decorative === false
388
+ ? descriptor.accessibilityLabel
389
+ : legacyMedia?.accessibilityLabel;
390
+ const resolvedFit = descriptor?.fit ?? fit;
391
+ const resolvedResizeMode = descriptor === undefined
392
+ ? resizeMode ?? (resolvedFit === undefined ? undefined : nativeResizeModes[resolvedFit])
393
+ : nativeResizeModes[descriptor.fit];
394
+ const sourceKey = descriptor === undefined
395
+ ? resolveLegacyImageSourceKey(legacySource)
396
+ : `src:${descriptor.src}`;
397
+ const source = useMemo(() => descriptor === undefined
398
+ ? legacySource
399
+ : sourceAdapter?.(descriptor) ?? { uri: descriptor.src }, [
400
+ descriptor?.accessibilityLabel,
401
+ descriptor?.decorative,
402
+ descriptor?.fit,
403
+ descriptor?.height,
404
+ descriptor?.src,
405
+ descriptor?.width,
406
+ legacySource,
407
+ sourceAdapter,
408
+ ]);
409
+ const [state, setState] = useState({ sourceKey, status: "loading" });
410
+ const status = state.sourceKey === sourceKey ? state.status : "loading";
411
+ useEffect(() => {
412
+ setState((current) => current.sourceKey === sourceKey
413
+ ? current
414
+ : { sourceKey, status: "loading" });
415
+ }, [sourceKey]);
416
+ const reportLoad = (event) => {
417
+ setState((current) => current.sourceKey === sourceKey
418
+ ? { sourceKey, status: "loaded" }
419
+ : current);
420
+ onLoadStatusChange?.("loaded");
421
+ onLoad?.(event);
422
+ };
423
+ const reportError = (event) => {
424
+ setState((current) => current.sourceKey === sourceKey
425
+ ? { sourceKey, status: "error" }
426
+ : current);
427
+ onLoadStatusChange?.("error");
428
+ onError?.(event);
429
+ };
430
+ const handleLoad = reportLoad;
431
+ const handleError = reportError;
432
+ const assetStyle = descriptor === undefined
433
+ ? style
434
+ : [StyleSheet.absoluteFill, style];
435
+ const adapterBase = {
436
+ source,
437
+ accessible: !resolvedDecorative,
438
+ ...(!resolvedDecorative && resolvedAccessibilityLabel !== undefined
439
+ ? {
440
+ accessibilityRole: "image",
441
+ accessibilityLabel: resolvedAccessibilityLabel,
442
+ }
443
+ : {}),
444
+ onError: handleError,
445
+ onLoad: handleLoad,
446
+ reportError,
447
+ reportLoad,
448
+ ...(resolvedResizeMode === undefined ? {} : { resizeMode: resolvedResizeMode }),
449
+ status: status === "loaded" ? "loaded" : "loading",
450
+ ...(assetStyle === undefined ? {} : { style: assetStyle }),
451
+ nativeProps: {
452
+ ...nativeProps,
453
+ ...(descriptor === undefined && width !== undefined ? { width } : {}),
454
+ ...(descriptor === undefined && height !== undefined ? { height } : {}),
455
+ ...(resolvedResizeMode === undefined ? {} : { resizeMode: resolvedResizeMode }),
456
+ },
457
+ };
458
+ const placeholderBackground = resolveColorReference(imageRecipe.placeholder.background, theme.palette);
459
+ const fallbackLabel = descriptor === undefined
460
+ ? resolvedAccessibilityLabel
461
+ : resolveImageFallbackAccessibilityLabel(descriptor);
462
+ let visual;
463
+ if (status === "error") {
464
+ visual = (_jsx(View, { ...(resolvedDecorative
465
+ ? {
466
+ accessibilityElementsHidden: true,
467
+ accessible: false,
468
+ importantForAccessibility: "no-hide-descendants",
469
+ }
470
+ : {
471
+ accessible: true,
472
+ accessibilityLabel: fallbackLabel,
473
+ accessibilityRole: "image",
474
+ }), style: StyleSheet.absoluteFill, children: _jsx(View, { accessibilityElementsHidden: true, accessible: false, importantForAccessibility: "no-hide-descendants", style: styles.imageFallbackContent, children: fallback ?? (_jsx(View, { accessible: false, style: [
475
+ styles.imageFallbackIcon,
476
+ { borderColor: theme.colors.textMuted },
477
+ ], children: _jsx(Text, { accessible: false, emphasis: "strong", style: { color: theme.colors.textMuted }, variant: "label", children: "!" }) })) }) }));
478
+ }
479
+ else if (renderImage === undefined) {
480
+ visual = (_jsx(NativeImage, { ...adapterBase.nativeProps, ...(resolvedDecorative
481
+ ? { accessible: false }
482
+ : {
483
+ accessible: true,
484
+ accessibilityLabel: resolvedAccessibilityLabel,
485
+ accessibilityRole: "image",
486
+ }), onError: handleError, onLoad: handleLoad, resizeMode: resolvedResizeMode, source: source, style: assetStyle }));
487
+ }
488
+ else if (descriptor === undefined) {
489
+ visual = renderImage({
490
+ ...adapterBase,
491
+ ...(resolvedFit === undefined ? {} : { fit: resolvedFit }),
492
+ ...(width === undefined ? {} : { width }),
493
+ ...(height === undefined ? {} : { height }),
494
+ legacySource: true,
495
+ });
496
+ }
497
+ else {
498
+ visual = renderImage({
499
+ ...adapterBase,
500
+ descriptor,
501
+ src: descriptor.src,
502
+ width: descriptor.width,
503
+ height: descriptor.height,
504
+ fit: descriptor.fit,
505
+ legacySource: false,
506
+ });
507
+ }
508
+ return (_jsx(View, { style: [
509
+ {
510
+ alignItems: "center",
511
+ backgroundColor: placeholderBackground,
512
+ borderRadius: radius[imageRecipe.radius],
513
+ justifyContent: "center",
514
+ overflow: "hidden",
515
+ ...(descriptor === undefined
516
+ ? {}
517
+ : {
518
+ aspectRatio: resolveImageAspectRatio(descriptor.width, descriptor.height),
519
+ width: descriptor.width,
520
+ }),
521
+ },
522
+ containerStyle,
523
+ ], children: visual }));
524
+ }
525
+ const styles = StyleSheet.create({
526
+ imageFallbackContent: {
527
+ alignItems: "center",
528
+ flex: 1,
529
+ justifyContent: "center",
530
+ },
531
+ imageFallbackIcon: {
532
+ alignItems: "center",
533
+ borderRadius: radius.full,
534
+ borderWidth: 2,
535
+ height: glyph.lg,
536
+ justifyContent: "center",
537
+ width: glyph.lg,
538
+ },
539
+ });
540
+ export function CounterBadge({ count, accessibilityLabel, max = counterBadgeRecipe.defaults.max, tone = counterBadgeRecipe.defaults.tone, size = counterBadgeRecipe.defaults.size, variant = counterBadgeRecipe.defaults.variant, style, }) {
541
+ if (accessibilityLabel !== undefined && !accessibilityLabel.trim()) {
542
+ throw new TypeError("CounterBadge accessibilityLabel must not be empty");
543
+ }
544
+ const visibleLabel = formatCounterBadgeCount(count, max);
545
+ if (visibleLabel === null)
546
+ return null;
547
+ const { colors } = useHjmNativeTheme();
548
+ const presentation = {
549
+ danger: { background: colors.dangerFill, content: colors.onDanger },
550
+ brand: { background: colors.primary, content: colors.onPrimary },
551
+ neutral: { background: colors.textBody, content: colors.bg },
552
+ };
553
+ const metrics = counterBadgeRecipe.sizes[size];
554
+ return (_jsx(View, { accessibilityLabel: accessibilityLabel, accessibilityRole: accessibilityLabel === undefined ? undefined : "text", accessible: accessibilityLabel !== undefined, importantForAccessibility: accessibilityLabel === undefined ? "no-hide-descendants" : "yes", style: [
555
+ {
556
+ alignItems: "center",
557
+ alignSelf: "flex-start",
558
+ backgroundColor: presentation[tone].background,
559
+ borderColor: variant === "floating" ? colors.bg : "transparent",
560
+ borderRadius: radius.full,
561
+ borderWidth: variant === "floating" ? 2 : 0,
562
+ justifyContent: "center",
563
+ minHeight: metrics.height,
564
+ minWidth: metrics.minWidth,
565
+ paddingHorizontal: metrics.paddingHorizontal,
566
+ },
567
+ style,
568
+ ], children: _jsx(Text, { accessible: false, align: "center", style: { color: presentation[tone].content, fontWeight: "700" }, variant: "caption", children: visibleLabel }) }));
569
+ }
570
+ /** Semantic list container that owns separator rhythm around composed rows. */
571
+ export function List({ label, children, separator = listRecipe.defaults.separator, appearance = "plain", style, ...props }) {
572
+ const { colors, environment } = useHjmNativeTheme();
573
+ const items = Children.toArray(children);
574
+ const separatorContract = listRecipe.separators[separator];
575
+ if (!label.trim())
576
+ throw new TypeError("List label must not be empty");
577
+ return (_jsx(View, { ...props, accessibilityLabel: label, accessibilityRole: "list", style: [
578
+ {
579
+ direction: environment.direction,
580
+ ...(appearance === "grouped"
581
+ ? {
582
+ backgroundColor: colors.surface,
583
+ borderRadius: radius.lg,
584
+ overflow: "hidden",
585
+ }
586
+ : {}),
587
+ },
588
+ style,
589
+ ], children: items.map((item, index) => (_jsxs(View, { children: [item, separatorContract && index < items.length - 1 ? (_jsx(View, { accessible: false, style: {
590
+ backgroundColor: colors.border,
591
+ height: 1,
592
+ marginEnd: separatorContract.insetEnd,
593
+ marginStart: separatorContract.insetStart,
594
+ } })) : null] }, isValidElement(item) && item.key !== null ? item.key : `hjm-list-${index}`))) }));
595
+ }
596
+ export function Statistic({ descriptor, density = "comfortable", presentation = "plain", contextLabel, accessibilityLabel, composeAccessibilityLabel, renderTrendMark, style, labelStyle, valueStyle, affixStyle, trendStyle, hintStyle, }) {
597
+ const resolved = resolveStatisticDescriptor(descriptor);
598
+ const theme = useHjmNativeTheme();
599
+ const densityContract = statisticRecipe.density[density];
600
+ const presentationContract = statisticRecipe.presentations[presentation];
601
+ const valueCopy = `${resolved.prefix ?? ""}${resolved.value}${resolved.suffix ?? ""}`;
602
+ if (contextLabel !== undefined && !contextLabel.trim()) {
603
+ throw new TypeError("Statistic contextLabel must not be empty");
604
+ }
605
+ const announcement = accessibilityLabel ?? composeAccessibilityLabel?.({
606
+ ...(contextLabel === undefined ? {} : { contextLabel }),
607
+ descriptor: resolved,
608
+ valueText: valueCopy,
609
+ }) ?? [contextLabel, resolved.label, valueCopy, resolved.trend?.label, resolved.hint]
610
+ .filter(Boolean)
611
+ .join(", ");
612
+ if (!announcement.trim()) {
613
+ throw new TypeError("Statistic accessibility label must not be empty");
614
+ }
615
+ const trendMark = resolved.trend
616
+ ? statisticRecipe.trend.marks[resolved.trend.direction]
617
+ : undefined;
618
+ const trendColor = resolved.trend
619
+ ? resolveColorReference(statisticRecipe.trend.tones[resolved.trend.tone], theme.palette)
620
+ : undefined;
621
+ return (_jsxs(View, { accessibilityLabel: announcement, accessible: true, style: [
622
+ {
623
+ backgroundColor: presentationContract.background
624
+ ? resolveColorReference(presentationContract.background, theme.palette)
625
+ : "transparent",
626
+ borderColor: presentationContract.border
627
+ ? resolveColorReference(presentationContract.border, theme.palette)
628
+ : "transparent",
629
+ borderRadius: radius[presentationContract.radius],
630
+ borderWidth: presentationContract.borderWidth,
631
+ gap: densityContract.gap,
632
+ minWidth: 0,
633
+ padding: densityContract.padding,
634
+ },
635
+ style,
636
+ ], children: [_jsx(Text, { accessible: false, style: [
637
+ {
638
+ color: resolveColorReference(statisticRecipe.label.color, theme.palette),
639
+ fontWeight: statisticRecipe.label.fontWeight,
640
+ },
641
+ labelStyle,
642
+ ], variant: densityContract.labelVariant, children: resolved.label }), _jsxs(View, { accessible: false, style: {
643
+ alignItems: "baseline",
644
+ direction: theme.environment.direction,
645
+ flexDirection: "row",
646
+ flexWrap: "wrap",
647
+ gap: spacing.xxs,
648
+ minWidth: 0,
649
+ }, children: [resolved.prefix ? (_jsx(Text, { accessible: false, style: [
650
+ {
651
+ color: resolveColorReference(statisticRecipe.affix.color, theme.palette),
652
+ fontWeight: statisticRecipe.affix.fontWeight,
653
+ },
654
+ affixStyle,
655
+ ], variant: statisticRecipe.affix.textVariant, children: resolved.prefix })) : null, _jsx(Text, { accessible: false, style: [
656
+ {
657
+ color: resolveColorReference(statisticRecipe.value.color, theme.palette),
658
+ flexShrink: 1,
659
+ fontVariant: ["tabular-nums"],
660
+ fontWeight: statisticRecipe.value.fontWeight,
661
+ },
662
+ valueStyle,
663
+ ], variant: densityContract.valueVariant, children: resolved.value }), resolved.suffix ? (_jsx(Text, { accessible: false, style: [
664
+ {
665
+ color: resolveColorReference(statisticRecipe.affix.color, theme.palette),
666
+ fontWeight: statisticRecipe.affix.fontWeight,
667
+ },
668
+ affixStyle,
669
+ ], variant: statisticRecipe.affix.textVariant, children: resolved.suffix })) : null] }), resolved.trend ? (_jsxs(View, { accessible: false, style: {
670
+ alignItems: "center",
671
+ flexDirection: "row",
672
+ flexWrap: "wrap",
673
+ gap: statisticRecipe.trend.gap,
674
+ minWidth: 0,
675
+ }, children: [renderTrendMark && trendMark && trendColor ? (_jsx(View, { accessible: false, children: renderTrendMark({ name: trendMark, color: trendColor, size: glyph.sm }) })) : (_jsx(Text, { accessible: false, style: { color: trendColor }, variant: "caption", children: resolved.trend.direction === "up" ? "↑" : resolved.trend.direction === "down" ? "↓" : "—" })), _jsx(Text, { accessible: false, style: [
676
+ {
677
+ color: trendColor,
678
+ flexShrink: 1,
679
+ fontWeight: statisticRecipe.trend.fontWeight,
680
+ },
681
+ trendStyle,
682
+ ], variant: statisticRecipe.trend.textVariant, children: resolved.trend.label })] })) : null, resolved.hint ? (_jsx(Text, { accessible: false, style: [
683
+ { color: resolveColorReference(statisticRecipe.hint.color, theme.palette) },
684
+ hintStyle,
685
+ ], variant: statisticRecipe.hint.textVariant, children: resolved.hint })) : null] }));
686
+ }
687
+ export function StatisticGroup({ label, descriptor, availableWidth, density, presentation, composeAccessibilityLabel, renderTrendMark, style, itemStyle, onLayout, ...props }) {
688
+ validateStatisticGroup(descriptor);
689
+ const { width: windowWidth } = useWindowDimensions();
690
+ const { environment } = useHjmNativeTheme();
691
+ const [measuredWidth, setMeasuredWidth] = useState(null);
692
+ const innerWidth = availableWidth ?? measuredWidth ?? windowWidth;
693
+ if (!Number.isFinite(innerWidth) || innerWidth <= 0) {
694
+ throw new RangeError("StatisticGroup availableWidth must be positive");
695
+ }
696
+ const requested = descriptor.columns ?? statisticRecipe.defaults.columns;
697
+ const minItemWidth = statisticRecipe.group.minItemWidth * Math.max(1, environment.textScale);
698
+ let columns = requested;
699
+ while (columns > 1 &&
700
+ (innerWidth - statisticRecipe.group.gap * (columns - 1)) / columns < minItemWidth) {
701
+ columns -= 1;
702
+ }
703
+ const itemWidth = (innerWidth - statisticRecipe.group.gap * (columns - 1)) / columns;
704
+ const remainder = descriptor.items.length % columns;
705
+ const finalRowCount = remainder === 0 ? columns : remainder;
706
+ const finalRowStart = descriptor.items.length - finalRowCount;
707
+ const finalRowItemWidth = finalRowCount === columns
708
+ ? itemWidth
709
+ : (innerWidth - statisticRecipe.group.gap * (finalRowCount - 1)) / finalRowCount;
710
+ const handleLayout = (event) => {
711
+ onLayout?.(event);
712
+ if (availableWidth !== undefined)
713
+ return;
714
+ const nextWidth = event.nativeEvent.layout.width;
715
+ if (Number.isFinite(nextWidth) && nextWidth > 0) {
716
+ setMeasuredWidth((current) => current === nextWidth ? current : nextWidth);
717
+ }
718
+ };
719
+ return (_jsx(View, { ...props, accessibilityLabel: label, accessibilityRole: "list", onLayout: handleLayout, style: [
720
+ {
721
+ direction: environment.direction,
722
+ flexDirection: "row",
723
+ flexWrap: "wrap",
724
+ gap: statisticRecipe.group.gap,
725
+ },
726
+ style,
727
+ ], children: descriptor.items.map((item, index) => (_jsx(Statistic, { contextLabel: label, descriptor: item, ...(composeAccessibilityLabel === undefined ? {} : { composeAccessibilityLabel }), ...(density === undefined ? {} : { density }), ...(presentation === undefined ? {} : { presentation }), ...(renderTrendMark === undefined ? {} : { renderTrendMark }), style: [
728
+ { width: index >= finalRowStart ? finalRowItemWidth : itemWidth },
729
+ itemStyle,
730
+ ] }, item.id))) }));
731
+ }
732
+ /** Ordered record of completed events; unlike Steps it has no current cursor. */
733
+ export function Timeline({ items, composeAccessibleName, style, ...props }) {
734
+ const theme = useHjmNativeTheme();
735
+ const resolved = resolveTimelineDescriptor({ items }, { composeAccessibleName });
736
+ return (_jsx(View, { ...props, style: [{ gap: timelineRecipe.gap }, style], children: resolved.map((item, index) => {
737
+ const tone = timelineRecipe.dot.tones[item.tone];
738
+ const accessibilityLabel = [
739
+ item.accessibleName,
740
+ item.timestamp,
741
+ item.description,
742
+ ]
743
+ .filter(Boolean)
744
+ .join(", ");
745
+ return (_jsxs(View, { accessible: true, accessibilityLabel: accessibilityLabel, style: { flexDirection: "row", gap: spacing.sm }, children: [_jsxs(View, { importantForAccessibility: "no-hide-descendants", style: { alignItems: "center", width: 16 }, children: [_jsx(View, { style: {
746
+ backgroundColor: resolveColorReference(tone.fill, theme.palette),
747
+ borderColor: tone.border
748
+ ? resolveColorReference(tone.border, theme.palette)
749
+ : "transparent",
750
+ borderRadius: radius.full,
751
+ borderWidth: tone.border
752
+ ? timelineRecipe.dot.borderWidth
753
+ : 0,
754
+ height: timelineRecipe.dot.diameter,
755
+ width: timelineRecipe.dot.diameter,
756
+ } }), index < resolved.length - 1 ? (_jsx(View, { style: {
757
+ backgroundColor: resolveColorReference(timelineRecipe.connector.tone, theme.palette),
758
+ flex: 1,
759
+ width: timelineRecipe.connector.width,
760
+ } })) : null] }), _jsxs(View, { importantForAccessibility: "no-hide-descendants", style: { flex: 1, gap: spacing.xxs, minWidth: 0, paddingBottom: spacing.xxs }, children: [_jsxs(View, { style: {
761
+ alignItems: "baseline",
762
+ flexDirection: "row",
763
+ flexWrap: "wrap",
764
+ gap: spacing.xs,
765
+ justifyContent: "space-between",
766
+ }, children: [_jsx(Text, { emphasis: "medium", style: {
767
+ color: resolveColorReference(timelineRecipe.label.color, theme.palette),
768
+ }, variant: timelineRecipe.label.textVariant, children: item.label }), item.timestamp ? (_jsx(Text, { style: {
769
+ color: resolveColorReference(timelineRecipe.timestamp.color, theme.palette),
770
+ }, variant: timelineRecipe.timestamp.textVariant, children: item.timestamp })) : null] }), item.description ? (_jsx(Text, { style: {
771
+ color: resolveColorReference(timelineRecipe.description.color, theme.palette),
772
+ }, variant: timelineRecipe.description.textVariant, children: item.description })) : null] })] }, item.id));
773
+ }) }));
774
+ }
775
+ //# sourceMappingURL=data-display.js.map