@multiplatform.one/components 7.76.0 → 7.77.1

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 (272) hide show
  1. package/dist/cjs/CopyField/CopyMenuButton.cjs +60 -0
  2. package/dist/cjs/CopyField/CopyMenuButton.native.js +69 -0
  3. package/dist/cjs/CopyField/CopyMenuButton.native.js.map +1 -0
  4. package/dist/cjs/CopyField/index.cjs +3 -1
  5. package/dist/cjs/CopyField/index.native.js +3 -1
  6. package/dist/cjs/CopyField/index.native.js.map +1 -1
  7. package/dist/cjs/componentColors.cjs +1 -0
  8. package/dist/cjs/componentColors.native.js +1 -0
  9. package/dist/cjs/componentColors.native.js.map +1 -1
  10. package/dist/cjs/layouts/StatusGlyphStrip.cjs +109 -0
  11. package/dist/cjs/layouts/StatusGlyphStrip.native.js +118 -0
  12. package/dist/cjs/layouts/StatusGlyphStrip.native.js.map +1 -0
  13. package/dist/cjs/layouts/index.cjs +2 -0
  14. package/dist/cjs/layouts/index.native.js +2 -0
  15. package/dist/cjs/layouts/index.native.js.map +1 -1
  16. package/dist/cjs/layouts/sidebar.cjs +2 -0
  17. package/dist/cjs/layouts/sidebar.native.js +2 -0
  18. package/dist/cjs/layouts/sidebar.native.js.map +1 -1
  19. package/dist/esm/Accordion/index.native.js.map +1 -1
  20. package/dist/esm/AnimateHeight/index.native.js.map +1 -1
  21. package/dist/esm/Avatar/getInitials.native.js.map +1 -1
  22. package/dist/esm/Avatar/index.native.js.map +1 -1
  23. package/dist/esm/Badge/index.native.js.map +1 -1
  24. package/dist/esm/Button.native.js.map +1 -1
  25. package/dist/esm/Carousel/index.native.js.map +1 -1
  26. package/dist/esm/Chip/index.native.js.map +1 -1
  27. package/dist/esm/Collapsible.native.js.map +1 -1
  28. package/dist/esm/ContextMenu/index.native.js.map +1 -1
  29. package/dist/esm/CopyField/CopyMenuButton.mjs +35 -0
  30. package/dist/esm/CopyField/CopyMenuButton.mjs.map +1 -0
  31. package/dist/esm/CopyField/CopyMenuButton.native.js +41 -0
  32. package/dist/esm/CopyField/CopyMenuButton.native.js.map +1 -0
  33. package/dist/esm/CopyField/index.mjs +2 -1
  34. package/dist/esm/CopyField/index.mjs.map +1 -1
  35. package/dist/esm/CopyField/index.native.js +2 -1
  36. package/dist/esm/CopyField/index.native.js.map +1 -1
  37. package/dist/esm/Dialog.native.js.map +1 -1
  38. package/dist/esm/DotIndicator/index.native.js.map +1 -1
  39. package/dist/esm/DropdownMenu/index.native.js.map +1 -1
  40. package/dist/esm/DropdownMenu/menuSettle.native.js.map +1 -1
  41. package/dist/esm/ErrorBoundary/index.native.js.map +1 -1
  42. package/dist/esm/Heading.native.js.map +1 -1
  43. package/dist/esm/Kbd/index.native.js.map +1 -1
  44. package/dist/esm/Kbd/keys.native.js.map +1 -1
  45. package/dist/esm/Lightbox/MediaControl.native.js.map +1 -1
  46. package/dist/esm/Lightbox/index.gnome.native.js.map +1 -1
  47. package/dist/esm/Lightbox/shared.native.js.map +1 -1
  48. package/dist/esm/Lightbox/useLightbox.native.js.map +1 -1
  49. package/dist/esm/Material/index.native.js.map +1 -1
  50. package/dist/esm/Meter/index.native.js.map +1 -1
  51. package/dist/esm/Meter/meter.native.js.map +1 -1
  52. package/dist/esm/OverflowRow/index.native.js.map +1 -1
  53. package/dist/esm/Pagination.native.js.map +1 -1
  54. package/dist/esm/Popover.native.js.map +1 -1
  55. package/dist/esm/ProgressSteps/index.native.js.map +1 -1
  56. package/dist/esm/Quote/index.native.js.map +1 -1
  57. package/dist/esm/SchemeToggle/index.native.js.map +1 -1
  58. package/dist/esm/ScrollView/revealFocusedField.native.js.map +1 -1
  59. package/dist/esm/Separator/index.native.js.map +1 -1
  60. package/dist/esm/Sheet.native.js.map +1 -1
  61. package/dist/esm/SheetModal/SheetHeader.native.js.map +1 -1
  62. package/dist/esm/SheetModal/SheetNavigation.native.js.map +1 -1
  63. package/dist/esm/SheetModal/detents.native.js.map +1 -1
  64. package/dist/esm/SheetModal/useSheetFrameFocus.native.js.map +1 -1
  65. package/dist/esm/Skeleton/index.native.js.map +1 -1
  66. package/dist/esm/SkipLink/index.native.js.map +1 -1
  67. package/dist/esm/SortableList/SortableHandle.native.js.map +1 -1
  68. package/dist/esm/SortableList/index.native.js.map +1 -1
  69. package/dist/esm/SortableList/useSortableRows.native.js.map +1 -1
  70. package/dist/esm/Tabs/index.native.js.map +1 -1
  71. package/dist/esm/Text.native.js.map +1 -1
  72. package/dist/esm/ThemePresetPicker/index.native.js.map +1 -1
  73. package/dist/esm/Toast/index.native.js.map +1 -1
  74. package/dist/esm/Toast/store.native.js.map +1 -1
  75. package/dist/esm/Tooltip/nativePress.native.js.map +1 -1
  76. package/dist/esm/Tooltip/tooltipShared.native.js.map +1 -1
  77. package/dist/esm/TreeSelect/index.native.js.map +1 -1
  78. package/dist/esm/TreeSelect/treeSelectModel.native.js.map +1 -1
  79. package/dist/esm/Video/PlayerChrome.native.js.map +1 -1
  80. package/dist/esm/Video/VideoFrame.native.js.map +1 -1
  81. package/dist/esm/Video/types.native.js.map +1 -1
  82. package/dist/esm/Wheel/index.native.js.map +1 -1
  83. package/dist/esm/Wizard/index.native.js.map +1 -1
  84. package/dist/esm/actions/ActionBar.native.js.map +1 -1
  85. package/dist/esm/actions/DangerSection.native.js.map +1 -1
  86. package/dist/esm/actions/DestructiveAction.native.js.map +1 -1
  87. package/dist/esm/actions/HeaderActions.native.js.map +1 -1
  88. package/dist/esm/actions/StandardAction.native.js.map +1 -1
  89. package/dist/esm/actions/devWarn.native.js.map +1 -1
  90. package/dist/esm/actions/index.native.js.map +1 -1
  91. package/dist/esm/actions/severity.native.js.map +1 -1
  92. package/dist/esm/appShell/Dock.native.js.map +1 -1
  93. package/dist/esm/appShell/MpoTabHost.native.js.map +1 -1
  94. package/dist/esm/appShell/ScopeMenu.native.js.map +1 -1
  95. package/dist/esm/appShell/SettingsSplit.native.js.map +1 -1
  96. package/dist/esm/appShell/Springboard.native.js.map +1 -1
  97. package/dist/esm/appShell/SystemBar.native.js.map +1 -1
  98. package/dist/esm/appShell/TabBar.native.js.map +1 -1
  99. package/dist/esm/appShell/appTile.native.js.map +1 -1
  100. package/dist/esm/appShell/bottomChrome.native.js.map +1 -1
  101. package/dist/esm/appShell/index.native.js.map +1 -1
  102. package/dist/esm/charts/Axis.native.js.map +1 -1
  103. package/dist/esm/charts/BarChart.native.js.map +1 -1
  104. package/dist/esm/charts/ChartDataView.native.js.map +1 -1
  105. package/dist/esm/charts/ChartSurface.native.js.map +1 -1
  106. package/dist/esm/charts/LineChart.native.js.map +1 -1
  107. package/dist/esm/charts/PieChart.native.js.map +1 -1
  108. package/dist/esm/charts/Sparkline.native.js.map +1 -1
  109. package/dist/esm/charts/accessibility.native.js.map +1 -1
  110. package/dist/esm/charts/chartHeight.native.js.map +1 -1
  111. package/dist/esm/charts/composeChart.native.js.map +1 -1
  112. package/dist/esm/charts/index.native.js.map +1 -1
  113. package/dist/esm/charts/math.native.js.map +1 -1
  114. package/dist/esm/charts/series.native.js.map +1 -1
  115. package/dist/esm/charts/svg.native.js.map +1 -1
  116. package/dist/esm/charts/types.native.js.map +1 -1
  117. package/dist/esm/charts/useChartTheme.native.js.map +1 -1
  118. package/dist/esm/code/Code/index.native.js.map +1 -1
  119. package/dist/esm/code/CodeBlock/index.native.js.map +1 -1
  120. package/dist/esm/code/HighlightedCode/index.native.js.map +1 -1
  121. package/dist/esm/code/Highlighter/houseSyntaxTheme.native.js.map +1 -1
  122. package/dist/esm/code/Highlighter/index.native.js.map +1 -1
  123. package/dist/esm/code/Highlighter/namedGroupMatchAll.native.js.map +1 -1
  124. package/dist/esm/code/Pre/index.native.js.map +1 -1
  125. package/dist/esm/code/index.native.js.map +1 -1
  126. package/dist/esm/componentColors.mjs +1 -0
  127. package/dist/esm/componentColors.mjs.map +1 -1
  128. package/dist/esm/componentColors.native.js +1 -0
  129. package/dist/esm/componentColors.native.js.map +1 -1
  130. package/dist/esm/feedback/ConfirmDialog.native.js.map +1 -1
  131. package/dist/esm/feedback/NotifyHost.native.js.map +1 -1
  132. package/dist/esm/feedback/copy.native.js.map +1 -1
  133. package/dist/esm/feedback/index.native.js.map +1 -1
  134. package/dist/esm/feedback/notify.native.js.map +1 -1
  135. package/dist/esm/feedback/route.native.js.map +1 -1
  136. package/dist/esm/feedback/store.native.js.map +1 -1
  137. package/dist/esm/formLayouts/FormLayouts.native.js.map +1 -1
  138. package/dist/esm/formLayouts/PreferencePanel.native.js.map +1 -1
  139. package/dist/esm/formLayouts/index.native.js.map +1 -1
  140. package/dist/esm/hooks/index.native.js.map +1 -1
  141. package/dist/esm/hooks/useClipboard.native.js.map +1 -1
  142. package/dist/esm/hooks/useDocumentTitle.native.js.map +1 -1
  143. package/dist/esm/hooks/useHoldCue.native.js.map +1 -1
  144. package/dist/esm/icons/CheckRegular.native.js.map +1 -1
  145. package/dist/esm/icons/MinusRegular.native.js.map +1 -1
  146. package/dist/esm/icons/index.native.js.map +1 -1
  147. package/dist/esm/icons/lucide.native.js.map +1 -1
  148. package/dist/esm/icons/themed.native.js.map +1 -1
  149. package/dist/esm/images/Image/ImageFrame.native.js.map +1 -1
  150. package/dist/esm/images/Image/framing.native.js.map +1 -1
  151. package/dist/esm/images/Image/mediaRadius.native.js.map +1 -1
  152. package/dist/esm/images/Image/shared.native.js.map +1 -1
  153. package/dist/esm/images/Image/types.native.js.map +1 -1
  154. package/dist/esm/images/index.native.js.map +1 -1
  155. package/dist/esm/index.native.js.map +1 -1
  156. package/dist/esm/knobImmuneExports.native.js.map +1 -1
  157. package/dist/esm/layouts/AsyncBoundary.native.js.map +1 -1
  158. package/dist/esm/layouts/Debug/index.native.js.map +1 -1
  159. package/dist/esm/layouts/EmptyState.native.js.map +1 -1
  160. package/dist/esm/layouts/IdentityPlate.native.js.map +1 -1
  161. package/dist/esm/layouts/KeyboardAvoidingWrapper/behavior.native.js.map +1 -1
  162. package/dist/esm/layouts/PageTemplates.native.js.map +1 -1
  163. package/dist/esm/layouts/PaneScaffold.native.js.map +1 -1
  164. package/dist/esm/layouts/SafeAreaWrapper/insets.native.js.map +1 -1
  165. package/dist/esm/layouts/StatusDot.native.js.map +1 -1
  166. package/dist/esm/layouts/StatusGlyphStrip.mjs +84 -0
  167. package/dist/esm/layouts/StatusGlyphStrip.mjs.map +1 -0
  168. package/dist/esm/layouts/StatusGlyphStrip.native.js +90 -0
  169. package/dist/esm/layouts/StatusGlyphStrip.native.js.map +1 -0
  170. package/dist/esm/layouts/ViewSwitcher.native.js.map +1 -1
  171. package/dist/esm/layouts/attachments.native.js.map +1 -1
  172. package/dist/esm/layouts/bottomAccessory.native.js.map +1 -1
  173. package/dist/esm/layouts/breadcrumbs.native.js.map +1 -1
  174. package/dist/esm/layouts/index.mjs +2 -1
  175. package/dist/esm/layouts/index.mjs.map +1 -1
  176. package/dist/esm/layouts/index.native.js +2 -1
  177. package/dist/esm/layouts/index.native.js.map +1 -1
  178. package/dist/esm/layouts/page.native.js.map +1 -1
  179. package/dist/esm/layouts/pageHeadingScope.native.js.map +1 -1
  180. package/dist/esm/layouts/screenScroll.native.js.map +1 -1
  181. package/dist/esm/layouts/shellSidebarSlot.native.js.map +1 -1
  182. package/dist/esm/layouts/sidebar.mjs +2 -0
  183. package/dist/esm/layouts/sidebar.mjs.map +1 -1
  184. package/dist/esm/layouts/sidebar.native.js +2 -0
  185. package/dist/esm/layouts/sidebar.native.js.map +1 -1
  186. package/dist/esm/layouts/tags.native.js.map +1 -1
  187. package/dist/esm/layouts/timeline.native.js.map +1 -1
  188. package/dist/esm/layouts/toolbar.native.js.map +1 -1
  189. package/dist/esm/shared/actionScan.native.js.map +1 -1
  190. package/dist/esm/shared/i18n.native.js.map +1 -1
  191. package/dist/esm/shared/restoreRetries.native.js.map +1 -1
  192. package/dist/esm/shared/t.native.js.map +1 -1
  193. package/dist/esm/shared/textRidesText.native.js.map +1 -1
  194. package/dist/esm/shared/useReturnFocusOnClose.native.js.map +1 -1
  195. package/dist/esm/surfaces.native.js.map +1 -1
  196. package/dist/esm/tamagui.native.js.map +1 -1
  197. package/dist/esm/testSetup.native.js.map +1 -1
  198. package/dist/esm/utils/setTinted.native.js.map +1 -1
  199. package/dist/esm/utils/unwrapText.native.js.map +1 -1
  200. package/dist/esm/views/Calendar.native.js.map +1 -1
  201. package/dist/esm/views/Dashboard.native.js.map +1 -1
  202. package/dist/esm/views/Gantt.native.js.map +1 -1
  203. package/dist/esm/views/GanttDateGrip.native.js.map +1 -1
  204. package/dist/esm/views/ImageGrid.native.js.map +1 -1
  205. package/dist/esm/views/List.native.js.map +1 -1
  206. package/dist/esm/views/ListGroup.native.js.map +1 -1
  207. package/dist/esm/views/ListRow.native.js.map +1 -1
  208. package/dist/esm/views/Matrix.native.js.map +1 -1
  209. package/dist/esm/views/ReportBuilder.native.js.map +1 -1
  210. package/dist/esm/views/ShortcutCard.native.js.map +1 -1
  211. package/dist/esm/views/TreeView.native.js.map +1 -1
  212. package/dist/esm/views/calendarMath.native.js.map +1 -1
  213. package/dist/esm/views/ganttIntervals.native.js.map +1 -1
  214. package/dist/esm/views/ganttMath.native.js.map +1 -1
  215. package/dist/esm/views/index.native.js.map +1 -1
  216. package/dist/esm/views/kanbanDnd.native.js.map +1 -1
  217. package/dist/esm/views/matrixMath.native.js.map +1 -1
  218. package/dist/esm/views/treeViewDnd.native.js.map +1 -1
  219. package/dist/esm/views/treeViewLayout.native.js.map +1 -1
  220. package/dist/esm/views/treeViewMotion.native.js.map +1 -1
  221. package/dist/esm/views/treeViewReveal.native.js.map +1 -1
  222. package/dist/esm/views/widgetChrome.native.js.map +1 -1
  223. package/dist/jsx/CopyField/CopyMenuButton.mjs +35 -0
  224. package/dist/jsx/CopyField/CopyMenuButton.mjs.map +1 -0
  225. package/dist/jsx/CopyField/CopyMenuButton.native.js +69 -0
  226. package/dist/jsx/CopyField/CopyMenuButton.native.js.map +1 -0
  227. package/dist/jsx/CopyField/index.mjs +2 -1
  228. package/dist/jsx/CopyField/index.mjs.map +1 -1
  229. package/dist/jsx/CopyField/index.native.js +3 -1
  230. package/dist/jsx/CopyField/index.native.js.map +1 -1
  231. package/dist/jsx/componentColors.mjs +1 -0
  232. package/dist/jsx/componentColors.mjs.map +1 -1
  233. package/dist/jsx/componentColors.native.js +1 -0
  234. package/dist/jsx/componentColors.native.js.map +1 -1
  235. package/dist/jsx/layouts/StatusGlyphStrip.mjs +84 -0
  236. package/dist/jsx/layouts/StatusGlyphStrip.mjs.map +1 -0
  237. package/dist/jsx/layouts/StatusGlyphStrip.native.js +118 -0
  238. package/dist/jsx/layouts/StatusGlyphStrip.native.js.map +1 -0
  239. package/dist/jsx/layouts/index.mjs +2 -1
  240. package/dist/jsx/layouts/index.mjs.map +1 -1
  241. package/dist/jsx/layouts/index.native.js +2 -0
  242. package/dist/jsx/layouts/index.native.js.map +1 -1
  243. package/dist/jsx/layouts/sidebar.mjs +2 -0
  244. package/dist/jsx/layouts/sidebar.mjs.map +1 -1
  245. package/dist/jsx/layouts/sidebar.native.js +2 -0
  246. package/dist/jsx/layouts/sidebar.native.js.map +1 -1
  247. package/package.json +9 -9
  248. package/src/Card.stories.tsx +82 -54
  249. package/src/CopyField/CopyMenuButton.spec.tsx +28 -0
  250. package/src/CopyField/CopyMenuButton.tsx +50 -0
  251. package/src/CopyField/index.tsx +2 -0
  252. package/src/componentColors.ts +1 -0
  253. package/src/export-surface.spec.tsx +2 -1
  254. package/src/layouts/Sidebar.spec.tsx +9 -0
  255. package/src/layouts/StatusGlyphStrip.spec.tsx +40 -0
  256. package/src/layouts/StatusGlyphStrip.tsx +96 -0
  257. package/src/layouts/index.tsx +1 -0
  258. package/src/layouts/sectionHeadingWeight.native-press.spec.tsx +68 -0
  259. package/src/layouts/sectionHeadingWeight.spec.tsx +48 -0
  260. package/src/layouts/sidebar.tsx +3 -1
  261. package/types/CopyField/CopyMenuButton.d.ts +13 -0
  262. package/types/CopyField/CopyMenuButton.d.ts.map +1 -0
  263. package/types/CopyField/index.d.ts +1 -0
  264. package/types/CopyField/index.d.ts.map +1 -1
  265. package/types/componentColors.d.ts +1 -0
  266. package/types/componentColors.d.ts.map +1 -1
  267. package/types/layouts/StatusGlyphStrip.d.ts +18 -0
  268. package/types/layouts/StatusGlyphStrip.d.ts.map +1 -0
  269. package/types/layouts/index.d.ts +1 -0
  270. package/types/layouts/index.d.ts.map +1 -1
  271. package/types/layouts/sidebar.d.ts +1 -0
  272. package/types/layouts/sidebar.d.ts.map +1 -1
@@ -9,7 +9,6 @@ import {
9
9
  } from "@multiplatform.one/forms";
10
10
  import {
11
11
  CompassIcon,
12
- FileCodeIcon,
13
12
  HouseLineIcon,
14
13
  LinkIcon,
15
14
  ShieldCheckIcon,
@@ -19,8 +18,10 @@ import { XStack, YStack } from "tamagui";
19
18
  import { ActionBar } from "./actions/ActionBar";
20
19
  import { ActionButton } from "./actions/StandardAction";
21
20
  import { Card } from "./Card";
21
+ import { CopyMenuButton } from "./CopyField/CopyMenuButton";
22
+ import { NotifyHost } from "./feedback";
22
23
  import { StatusDot } from "./layouts/StatusDot";
23
- import { reportCopy } from "./feedback/copy";
24
+ import { StatusGlyphStrip, type StatusGlyph } from "./layouts/StatusGlyphStrip";
24
25
  import { Paragraph, SizableText } from "./Text";
25
26
 
26
27
  const meta: Meta<typeof Card> = {
@@ -131,66 +132,93 @@ export const LongContent: Story = {
131
132
  };
132
133
 
133
134
  // ── Sign-on (LC-169, FZ-7970 r3) ───────────────────────────────
134
- // The SHC console's Identity › Sign-on cards rebuilt on MPO parts. Clay on
135
- // the console's: "The shc cards still look like shit. There's no visual
136
- // hairachy it's all just text that runs together", then on round 3: "Good but
137
- // use better hierarchy communication with icons less verbose where possible."
138
- // The three console cards repeated realm master and the same issuer, so the
139
- // shared facts sit once in the first card and the checks card carries only
140
- // what differs: each check's status as a dot and one word. Rows are inline
141
- // (glyph and label leading, value trailing); the URLs stack, mono, cut in the
142
- // middle, with copy.
135
+ // The SHC console's Identity › Sign-on cards rebuilt on MPO parts, round 4.
136
+ // Clay on round 3: "I wonder if you could even get one fewer row." One card,
137
+ // two rows: the realm as an icon-only fact with its three checks trailing as
138
+ // a glyph cluster (the realm's accessory), then the issuer. Names are the
139
+ // glyphs' accessible names and tooltips. The discovery URL derives from the
140
+ // issuer, so it sits behind the issuer's copy menu.
143
141
 
144
142
  const issuer = "https://91-98-47-56.sslip.io/auth/realms/master";
145
143
 
144
+ function SignOnCard({
145
+ checks,
146
+ ...args
147
+ }: { checks: readonly StatusGlyph[] } & Record<string, unknown>) {
148
+ return (
149
+ <Card {...args}>
150
+ <Card.Header status={<StatusDot tone={signOnTone(checks)} />}>Sign-on</Card.Header>
151
+ <DescriptionList
152
+ placement="inline"
153
+ maxWidth="fluid"
154
+ items={[
155
+ {
156
+ icon: <ShieldCheckIcon />,
157
+ term: "Realm",
158
+ value: "master",
159
+ labelHidden: true,
160
+ accessory: <StatusGlyphStrip items={checks} />,
161
+ },
162
+ {
163
+ icon: <LinkIcon />,
164
+ term: "Issuer",
165
+ value: issuer,
166
+ identifier: true,
167
+ labelHidden: true,
168
+ copyAction: (
169
+ <CopyMenuButton
170
+ items={[
171
+ { label: "Copy issuer", value: issuer },
172
+ {
173
+ label: "Copy discovery URL",
174
+ value: `${issuer}/.well-known/openid-configuration`,
175
+ },
176
+ ]}
177
+ />
178
+ ),
179
+ },
180
+ ]}
181
+ />
182
+ </Card>
183
+ );
184
+ }
185
+
186
+ function signOnTone(checks: readonly StatusGlyph[]) {
187
+ if (checks.some((check) => check.tone === "critical")) return "critical" as const;
188
+ if (checks.some((check) => check.tone === "warning")) return "warning" as const;
189
+ return "positive" as const;
190
+ }
191
+
192
+ const healthyChecks: readonly StatusGlyph[] = [
193
+ { icon: <StarIcon />, label: "Default realm", tone: "positive" },
194
+ { icon: <HouseLineIcon />, label: "Realm for this host", tone: "positive" },
195
+ { icon: <CompassIcon />, label: "Discovery", tone: "positive" },
196
+ ];
197
+
146
198
  export const SignOn: Story = {
147
199
  name: "Sign-on (LC-169)",
148
200
  parameters: { layout: "fullscreen" },
149
201
  render: (args) => (
150
202
  <YStack padding="$4" gap="$3" backgroundColor="$background" minHeight="100%">
151
- <Card {...args}>
152
- <Card.Header status={<StatusDot tone="positive">OK</StatusDot>}>Sign-on</Card.Header>
153
- <DescriptionList
154
- placement="inline"
155
- maxWidth="fluid"
156
- onCopyResult={(ok) => reportCopy(ok)}
157
- items={[
158
- { icon: <ShieldCheckIcon />, term: "Realm", value: "master" },
159
- { icon: <LinkIcon />, term: "Issuer", value: issuer, identifier: true },
160
- ]}
161
- />
162
- </Card>
163
- <Card {...args}>
164
- <Card.Header>Checks</Card.Header>
165
- <DescriptionList
166
- placement="inline"
167
- maxWidth="fluid"
168
- onCopyResult={(ok) => reportCopy(ok)}
169
- items={[
170
- {
171
- icon: <StarIcon />,
172
- term: "Default realm",
173
- children: <StatusDot tone="positive">OK</StatusDot>,
174
- },
175
- {
176
- icon: <HouseLineIcon />,
177
- term: "Realm for this host",
178
- children: <StatusDot tone="positive">OK</StatusDot>,
179
- },
180
- {
181
- icon: <CompassIcon />,
182
- term: "Discovery",
183
- children: <StatusDot tone="positive">OK</StatusDot>,
184
- },
185
- {
186
- icon: <FileCodeIcon />,
187
- term: "Configuration",
188
- value: `${issuer}/.well-known/openid-configuration`,
189
- identifier: true,
190
- },
191
- ]}
192
- />
193
- </Card>
203
+ <NotifyHost />
204
+ <SignOnCard {...args} checks={healthyChecks} />
205
+ </YStack>
206
+ ),
207
+ };
208
+
209
+ export const SignOnFailing: Story = {
210
+ name: "Sign-on, a failing check (LC-169)",
211
+ parameters: { layout: "fullscreen" },
212
+ render: (args) => (
213
+ <YStack padding="$4" gap="$3" backgroundColor="$background" minHeight="100%">
214
+ <SignOnCard
215
+ {...args}
216
+ checks={[
217
+ healthyChecks[0]!,
218
+ healthyChecks[1]!,
219
+ { icon: <CompassIcon />, label: "Discovery", tone: "critical", reason: "Timeout" },
220
+ ]}
221
+ />
194
222
  </YStack>
195
223
  ),
196
224
  };
@@ -0,0 +1,28 @@
1
+ /**
2
+ * @vitest-environment jsdom
3
+ */
4
+
5
+ import { fireEvent, waitFor } from "@testing-library/react";
6
+ import { renderWithProviders } from "@multiplatform.one/test-utils";
7
+ import { describe, expect, it } from "vitest";
8
+ import { CopyMenuButton } from "./CopyMenuButton";
9
+
10
+ describe("CopyMenuButton (LC-169)", () => {
11
+ it("one copy glyph opens the value and its derived values as menu items", async () => {
12
+ const result = renderWithProviders(
13
+ <CopyMenuButton
14
+ items={[
15
+ { label: "Copy issuer", value: "https://id.example/realms/master" },
16
+ {
17
+ label: "Copy discovery URL",
18
+ value: "https://id.example/realms/master/.well-known/openid-configuration",
19
+ },
20
+ ]}
21
+ />,
22
+ );
23
+ const trigger = result.getByLabelText("Copy");
24
+ fireEvent.click(trigger);
25
+ await waitFor(() => expect(result.getByText("Copy discovery URL")).toBeTruthy());
26
+ expect(result.getByText("Copy issuer")).toBeTruthy();
27
+ });
28
+ });
@@ -0,0 +1,50 @@
1
+ /**
2
+ * CopyMenuButton — an identifier's copy action when there is more than one
3
+ * thing worth copying (LC-169): the value itself and values derived from it,
4
+ * such as an issuer and its discovery URL. A derived value lives here rather
5
+ * than as its own row, so a card says the identifier once.
6
+ *
7
+ * The glyph never flips; the confirm is notify() (DG-FB-01 / LC-16).
8
+ */
9
+ import { Button } from "@multiplatform.one/forms";
10
+ import { CopyIcon } from "@phosphor-icons/react";
11
+ import { DropdownMenu } from "../DropdownMenu";
12
+ import { useCopyFeedback } from "../feedback/copy";
13
+ import { useTranslation } from "../shared/i18n";
14
+
15
+ export interface CopyMenuItem {
16
+ key?: string;
17
+ /** "Copy issuer", "Copy discovery URL". */
18
+ label: string;
19
+ value: string;
20
+ }
21
+
22
+ export interface CopyMenuButtonProps {
23
+ items: readonly CopyMenuItem[];
24
+ /** The button's accessible name. Default "Copy". */
25
+ "aria-label"?: string;
26
+ }
27
+
28
+ export function CopyMenuButton({ items, "aria-label": ariaLabel }: CopyMenuButtonProps) {
29
+ const { t } = useTranslation();
30
+ const { copy } = useCopyFeedback();
31
+ return (
32
+ <DropdownMenu
33
+ placement="bottom-end"
34
+ items={items.map((item) => ({
35
+ key: item.key ?? item.label,
36
+ label: item.label,
37
+ onSelect: () => void copy(item.value),
38
+ }))}
39
+ >
40
+ <Button
41
+ nested
42
+ chromeless
43
+ circular
44
+ flexShrink={0}
45
+ icon={<CopyIcon />}
46
+ aria-label={ariaLabel ?? t("Copy")}
47
+ />
48
+ </DropdownMenu>
49
+ );
50
+ }
@@ -25,3 +25,5 @@ export function CopyField(props: CopyFieldProps) {
25
25
  </YStack>
26
26
  );
27
27
  }
28
+
29
+ export { CopyMenuButton, type CopyMenuButtonProps, type CopyMenuItem } from "./CopyMenuButton";
@@ -152,5 +152,6 @@ export const componentColors = {
152
152
  export const sectionHeading = {
153
153
  fontFamily: "$heading",
154
154
  size: isWeb ? "$6" : "$5",
155
+ fontWeight: "700",
155
156
  color: "$color12",
156
157
  } as const;
@@ -113,11 +113,12 @@ describe("semantic colour layer is importable by a stable name", () => {
113
113
  expect(pkg.sectionHeading).toBe(sectionHeading);
114
114
  });
115
115
 
116
- it("pins sectionHeading to the prominent step: $heading, primary ink, $6 on web (LC-156)", () => {
116
+ it("pins sectionHeading to the prominent step: $heading, 700, primary ink, $6 on web (LC-156)", () => {
117
117
  // jsdom runs the web branch; native resolves $5 (20 pt over its 17 pt body).
118
118
  expect(sectionHeading).toEqual({
119
119
  fontFamily: "$heading",
120
120
  size: "$6",
121
+ fontWeight: "700",
121
122
  color: "$color12",
122
123
  });
123
124
  });
@@ -94,6 +94,15 @@ describe("Sidebar nesting", () => {
94
94
  });
95
95
  });
96
96
 
97
+ describe("Sidebar item testID", () => {
98
+ it("puts an item's testID on its row", () => {
99
+ const result = renderWithProviders(
100
+ <Sidebar sections={[{ items: [{ value: "a", label: "Alpha", testID: "alpha-row" }] }]} />,
101
+ );
102
+ expect(result.getByTestId("alpha-row").getAttribute("data-sidebar-row")).toBe("true");
103
+ });
104
+ });
105
+
97
106
  describe("Sidebar footer", () => {
98
107
  const sections = [{ items: [{ value: "a", label: "Alpha" }] }];
99
108
 
@@ -0,0 +1,40 @@
1
+ /**
2
+ * @vitest-environment jsdom
3
+ */
4
+
5
+ import { renderWithProviders } from "@multiplatform.one/test-utils";
6
+ import { describe, expect, it } from "vitest";
7
+ import { StatusGlyphStrip } from "./StatusGlyphStrip";
8
+
9
+ describe("StatusGlyphStrip (LC-169)", () => {
10
+ it("each check is a glyph and a dot, named by its label and state, with no printed word when OK", () => {
11
+ const result = renderWithProviders(
12
+ <StatusGlyphStrip
13
+ items={[
14
+ { icon: <span />, label: "Default realm", tone: "positive" },
15
+ { icon: <span />, label: "Discovery", tone: "positive" },
16
+ ]}
17
+ />,
18
+ );
19
+ const glyphs = Array.from(
20
+ result.container.querySelectorAll("[data-mpo-status-glyph]"),
21
+ ) as HTMLElement[];
22
+ expect(glyphs).toHaveLength(2);
23
+ expect(glyphs[0]!.getAttribute("aria-label")).toBe("Default realm: OK");
24
+ expect(glyphs[0]!.getAttribute("role")).toBe("img");
25
+ expect(glyphs[0]!.querySelector("[data-tone='positive']")).not.toBeNull();
26
+ expect(result.container.textContent).not.toContain("Default realm");
27
+ expect(result.container.textContent).not.toContain("OK");
28
+ });
29
+
30
+ it("a failing check prints its one-word reason beside its dot", () => {
31
+ const result = renderWithProviders(
32
+ <StatusGlyphStrip
33
+ items={[{ icon: <span />, label: "Discovery", tone: "critical", reason: "Timeout" }]}
34
+ />,
35
+ );
36
+ const glyph = result.container.querySelector("[data-mpo-status-glyph]") as HTMLElement;
37
+ expect(glyph.getAttribute("aria-label")).toBe("Discovery: Timeout");
38
+ expect(glyph.textContent).toBe("Timeout");
39
+ });
40
+ });
@@ -0,0 +1,96 @@
1
+ /**
2
+ * StatusGlyphStrip — a row of checks as glyphs, each with its own status dot
3
+ * (LC-169 icon-only facts).
4
+ *
5
+ * The glyph names the check, so no word is printed for it: the name is the
6
+ * glyph's accessible name and its tooltip (hover on web, long-press on
7
+ * device). A check that is not OK prints its one-word reason beside its dot,
8
+ * because a failure is what the reader needs without asking.
9
+ */
10
+ import { IconSlot, useGlyphColor, useResolvedKnobs } from "@multiplatform.one/theme";
11
+ import type { ReactNode } from "react";
12
+ import { Text, View, XStack, isWeb } from "tamagui";
13
+ import { useTranslation } from "../shared/i18n";
14
+ import { Tooltip } from "../Tooltip";
15
+ import { StatusMark, statusToneInk, type StatusTone } from "./StatusDot";
16
+
17
+ export interface StatusGlyph {
18
+ key?: string;
19
+ /** The glyph that names the check (a star for "Default realm"). */
20
+ icon: ReactNode;
21
+ /** The check's name: the accessible name and the tooltip. */
22
+ label: string;
23
+ tone: StatusTone;
24
+ /** One word for a check that is not OK ("Missing", "Timeout"). */
25
+ reason?: string;
26
+ }
27
+
28
+ export interface StatusGlyphStripProps {
29
+ items: readonly StatusGlyph[];
30
+ testID?: string;
31
+ }
32
+
33
+ const toneWord: Record<StatusTone, string> = {
34
+ positive: "OK",
35
+ warning: "Warning",
36
+ critical: "Failing",
37
+ neutral: "Unknown",
38
+ };
39
+
40
+ function GlyphCheck({ item }: { item: StatusGlyph }) {
41
+ const { t } = useTranslation();
42
+ const { knobProps } = useResolvedKnobs();
43
+ const ink = useGlyphColor("$color");
44
+ const state = item.reason ?? t(toneWord[item.tone]);
45
+ const name = `${item.label}: ${state}`;
46
+ const showReason = item.tone !== "positive" && item.reason != null;
47
+ return (
48
+ <Tooltip content={name}>
49
+ <XStack
50
+ data-mpo-status-glyph=""
51
+ data-tone={item.tone}
52
+ role="img"
53
+ aria-label={name}
54
+ alignItems="center"
55
+ flexShrink={0}
56
+ {...knobProps.gapSm}
57
+ {...(isWeb ? ({ title: name } as Record<string, unknown>) : { accessible: true })}
58
+ >
59
+ <View
60
+ aria-hidden
61
+ {...(isWeb && ink ? ({ style: { color: ink } } as Record<string, unknown>) : {})}
62
+ >
63
+ <IconSlot icon={item.icon} color={ink} size={20} />
64
+ </View>
65
+ <StatusMark tone={item.tone} />
66
+ {showReason ? (
67
+ <Text
68
+ {...knobProps.textRole.meta}
69
+ color={statusToneInk[item.tone] as never}
70
+ numberOfLines={1}
71
+ >
72
+ {item.reason}
73
+ </Text>
74
+ ) : null}
75
+ </XStack>
76
+ </Tooltip>
77
+ );
78
+ }
79
+
80
+ export function StatusGlyphStrip({ items, testID }: StatusGlyphStripProps) {
81
+ const { knobProps } = useResolvedKnobs();
82
+ return (
83
+ <XStack
84
+ data-mpo-status-glyph-strip=""
85
+ data-testid={testID}
86
+ alignItems="center"
87
+ flexWrap="wrap"
88
+ minWidth={0}
89
+ {...knobProps.gapLg}
90
+ >
91
+ {items.map((item) => (
92
+ <GlyphCheck key={item.key ?? item.label} item={item} />
93
+ ))}
94
+ </XStack>
95
+ );
96
+ }
@@ -40,6 +40,7 @@ export {
40
40
  type StatusDotProps,
41
41
  type StatusTone,
42
42
  } from "./StatusDot";
43
+ export { StatusGlyphStrip, type StatusGlyph, type StatusGlyphStripProps } from "./StatusGlyphStrip";
43
44
  export {
44
45
  AsyncBoundary,
45
46
  AsyncSkeleton,
@@ -0,0 +1,68 @@
1
+ import { createDefaultThemeConfig, Preset } from "@multiplatform.one/theme";
2
+ import { cleanup, render, screen } from "@testing-library/react";
3
+ import type { ReactElement } from "react";
4
+ import { TamaguiProvider, isWeb } from "tamagui";
5
+ import { afterEach, describe, expect, it, vi } from "vitest";
6
+ import { EmptyState } from "./EmptyState";
7
+ import { IdentityPlate } from "./IdentityPlate";
8
+
9
+ vi.mock("@multiplatform.one/platform", async (importOriginal) => ({
10
+ ...(await importOriginal<typeof import("@multiplatform.one/platform")>()),
11
+ isWeb: false,
12
+ isNative: true,
13
+ }));
14
+
15
+ const config = createDefaultThemeConfig();
16
+
17
+ type FaceName = string | { val?: string } | undefined;
18
+ type Face = Record<string, Record<string, FaceName> | undefined>;
19
+
20
+ const headingFace: Face =
21
+ (config.tamagui as unknown as { fonts: Record<string, { face?: Face } | undefined> }).fonts
22
+ .heading?.face ?? {};
23
+
24
+ afterEach(cleanup);
25
+
26
+ function resolvedWeight(el: HTMLElement): string {
27
+ const family = el.style.fontFamily.replace(/["']/g, "").trim();
28
+ for (const [weight, styles] of Object.entries(headingFace)) {
29
+ const name = styles?.normal;
30
+ if ((typeof name === "string" ? name : name?.val) === family) return weight;
31
+ }
32
+ return el.style.fontWeight;
33
+ }
34
+
35
+ function weightOf(node: ReactElement, text: string): string {
36
+ render(
37
+ <TamaguiProvider config={config.tamagui} defaultTheme="light" disableInjectCSS>
38
+ {node}
39
+ </TamaguiProvider>,
40
+ );
41
+ return resolvedWeight(screen.getByText(text));
42
+ }
43
+
44
+ const cases: [string, () => ReactElement, string][] = [
45
+ [
46
+ "IdentityPlate's title",
47
+ () => <IdentityPlate title="affine" status="Running" statusTone="positive" />,
48
+ "affine",
49
+ ],
50
+ ["EmptyState's title", () => <EmptyState title="Nothing is running" />, "Nothing is running"],
51
+ ];
52
+
53
+ describe("section heading weight on native (LC-156, FZ-8633)", () => {
54
+ it("runs tamagui's native build", async () => {
55
+ expect(isWeb).toBe(false);
56
+ expect((await import("@multiplatform.one/platform")).isWeb).toBe(false);
57
+ });
58
+
59
+ it.each(cases)("%s draws at the heading weight, as on web", (_, node, text) => {
60
+ expect(weightOf(node(), text)).toBe("700");
61
+ });
62
+
63
+ it.each(cases)("%s keeps the heading weight on a category heading font", (_, node, text) => {
64
+ expect(weightOf(<Preset overrides={{ headingFont: "serif" }}>{node()}</Preset>, text)).toBe(
65
+ "700",
66
+ );
67
+ });
68
+ });
@@ -0,0 +1,48 @@
1
+ import { createDefaultThemeConfig, Preset } from "@multiplatform.one/theme";
2
+ import { cleanup, render, screen } from "@testing-library/react";
3
+ import type { ReactElement } from "react";
4
+ import { TamaguiProvider } from "tamagui";
5
+ import { afterEach, describe, expect, it } from "vitest";
6
+ import { EmptyState } from "./EmptyState";
7
+ import { IdentityPlate } from "./IdentityPlate";
8
+
9
+ const config = createDefaultThemeConfig();
10
+
11
+ afterEach(cleanup);
12
+
13
+ function computedWeight(el: HTMLElement): string {
14
+ const style = getComputedStyle(el);
15
+ const weight = style.fontWeight;
16
+ const variable = weight.match(/^var\((--[^,)]+)/)?.[1];
17
+ return variable ? style.getPropertyValue(variable).trim() : weight;
18
+ }
19
+
20
+ function weightOf(node: ReactElement, text: string): string {
21
+ render(
22
+ <TamaguiProvider config={config.tamagui} defaultTheme="light">
23
+ {node}
24
+ </TamaguiProvider>,
25
+ );
26
+ return computedWeight(screen.getByText(text));
27
+ }
28
+
29
+ const cases: [string, () => ReactElement, string][] = [
30
+ [
31
+ "IdentityPlate's title",
32
+ () => <IdentityPlate title="affine" status="Running" statusTone="positive" />,
33
+ "affine",
34
+ ],
35
+ ["EmptyState's title", () => <EmptyState title="Nothing is running" />, "Nothing is running"],
36
+ ];
37
+
38
+ describe("section heading weight on web (LC-156, FZ-8633)", () => {
39
+ it.each(cases)("%s draws at the heading weight", (_, node, text) => {
40
+ expect(weightOf(node(), text)).toBe("700");
41
+ });
42
+
43
+ it.each(cases)("%s keeps the heading weight on a category heading font", (_, node, text) => {
44
+ expect(weightOf(<Preset overrides={{ headingFont: "serif" }}>{node()}</Preset>, text)).toBe(
45
+ "700",
46
+ );
47
+ });
48
+ });
@@ -51,6 +51,7 @@ export interface SidebarItem {
51
51
  * indents by one icon column per level, with no extra edge or fill.
52
52
  */
53
53
  depth?: number;
54
+ testID?: string;
54
55
  }
55
56
 
56
57
  export interface SidebarProps {
@@ -179,7 +180,7 @@ export function Sidebar({
179
180
  </YStack>
180
181
  ) : null}
181
182
 
182
- <YStack width="100%">
183
+ <YStack width="100%" data-sidebar-group="">
183
184
  {section.items.map((item, itemIdx, items) => {
184
185
  const position = getGroupPosition(itemIdx, items.length);
185
186
  const corners = stackRadiusProps(position, knobProps.borderRadius.borderRadius);
@@ -209,6 +210,7 @@ export function Sidebar({
209
210
  <XStack
210
211
  data-group-position={position}
211
212
  data-sidebar-row="true"
213
+ testID={item.testID}
212
214
  data-depth={depth > 0 ? depth : undefined}
213
215
  data-active={item.active ? true : undefined}
214
216
  aria-current={item.active ? "page" : undefined}
@@ -0,0 +1,13 @@
1
+ export interface CopyMenuItem {
2
+ key?: string;
3
+ /** "Copy issuer", "Copy discovery URL". */
4
+ label: string;
5
+ value: string;
6
+ }
7
+ export interface CopyMenuButtonProps {
8
+ items: readonly CopyMenuItem[];
9
+ /** The button's accessible name. Default "Copy". */
10
+ "aria-label"?: string;
11
+ }
12
+ export declare function CopyMenuButton({ items, "aria-label": ariaLabel }: CopyMenuButtonProps): import("react/jsx-runtime").JSX.Element;
13
+ //# sourceMappingURL=CopyMenuButton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CopyMenuButton.d.ts","sourceRoot":"","sources":["../../src/CopyField/CopyMenuButton.tsx"],"names":[],"mappings":"AAcA,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,2CAA2C;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,SAAS,YAAY,EAAE,CAAC;IAC/B,oDAAoD;IACpD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,cAAc,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,EAAE,mBAAmB,2CAsBrF"}
@@ -12,4 +12,5 @@
12
12
  import { type InputProps } from "@multiplatform.one/forms";
13
13
  export type CopyFieldProps = Omit<InputProps, "copy" | "onCopyResult" | "secureTextEntry">;
14
14
  export declare function CopyField(props: CopyFieldProps): import("react/jsx-runtime").JSX.Element;
15
+ export { CopyMenuButton, type CopyMenuButtonProps, type CopyMenuItem } from "./CopyMenuButton";
15
16
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/CopyField/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAS,KAAK,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAKlE,MAAM,MAAM,cAAc,GAAG,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,cAAc,GAAG,iBAAiB,CAAC,CAAC;AAE3F,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,2CAQ9C"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/CopyField/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAS,KAAK,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAKlE,MAAM,MAAM,cAAc,GAAG,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,cAAc,GAAG,iBAAiB,CAAC,CAAC;AAE3F,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,2CAQ9C;AAED,OAAO,EAAE,cAAc,EAAE,KAAK,mBAAmB,EAAE,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC"}
@@ -128,6 +128,7 @@ export declare const componentColors: {
128
128
  export declare const sectionHeading: {
129
129
  readonly fontFamily: "$heading";
130
130
  readonly size: "$5" | "$6";
131
+ readonly fontWeight: "700";
131
132
  readonly color: "$color12";
132
133
  };
133
134
  //# sourceMappingURL=componentColors.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"componentColors.d.ts","sourceRoot":"","sources":["../src/componentColors.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AAEH,eAAO,MAAM,eAAe;IAC1B;;;;;;;;OAQG;;;;;IAMH,yEAAyE;;;;;;;IAQzE;;;;;OAKG;;;;;;;;IASH,yBAAyB;;;;;IAczB,yBAAyB;;;;;;;;IASzB;;;;;;;;;;OAUG;;;;;;;;IASH,4BAA4B;;;;;;IAO5B;;2EAEuE;;;;;;;;IASvE;;;+EAG2E;;;;;;IAO3E;;;OAGG;;;;IAKH,+BAA+B;;IAG/B,4BAA4B;;IAG5B;;;;OAIG;;;;;CAKK,CAAC;AAEX;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc;;;;CAIjB,CAAC"}
1
+ {"version":3,"file":"componentColors.d.ts","sourceRoot":"","sources":["../src/componentColors.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AAEH,eAAO,MAAM,eAAe;IAC1B;;;;;;;;OAQG;;;;;IAMH,yEAAyE;;;;;;;IAQzE;;;;;OAKG;;;;;;;;IASH,yBAAyB;;;;;IAczB,yBAAyB;;;;;;;;IASzB;;;;;;;;;;OAUG;;;;;;;;IASH,4BAA4B;;;;;;IAO5B;;2EAEuE;;;;;;;;IASvE;;;+EAG2E;;;;;;IAO3E;;;OAGG;;;;IAKH,+BAA+B;;IAG/B,4BAA4B;;IAG5B;;;;OAIG;;;;;CAKK,CAAC;AAEX;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc;;;;;CAKjB,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { ReactNode } from "react";
2
+ import { type StatusTone } from "./StatusDot";
3
+ export interface StatusGlyph {
4
+ key?: string;
5
+ /** The glyph that names the check (a star for "Default realm"). */
6
+ icon: ReactNode;
7
+ /** The check's name: the accessible name and the tooltip. */
8
+ label: string;
9
+ tone: StatusTone;
10
+ /** One word for a check that is not OK ("Missing", "Timeout"). */
11
+ reason?: string;
12
+ }
13
+ export interface StatusGlyphStripProps {
14
+ items: readonly StatusGlyph[];
15
+ testID?: string;
16
+ }
17
+ export declare function StatusGlyphStrip({ items, testID }: StatusGlyphStripProps): import("react/jsx-runtime").JSX.Element;
18
+ //# sourceMappingURL=StatusGlyphStrip.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StatusGlyphStrip.d.ts","sourceRoot":"","sources":["../../src/layouts/StatusGlyphStrip.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIvC,OAAO,EAA6B,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzE,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,mEAAmE;IACnE,IAAI,EAAE,SAAS,CAAC;IAChB,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,UAAU,CAAC;IACjB,kEAAkE;IAClE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,SAAS,WAAW,EAAE,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAiDD,wBAAgB,gBAAgB,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,qBAAqB,2CAgBxE"}
@@ -19,5 +19,6 @@ export * from "./PaneScaffold";
19
19
  export { EmptyState, type EmptyStateProps } from "./EmptyState";
20
20
  export { IdentityPlate, type IdentityPlateFact, type IdentityPlateProps, type IdentityPlateTone, } from "./IdentityPlate";
21
21
  export { StatusDot, StatusMark, statusToneInk, type StatusDotProps, type StatusTone, } from "./StatusDot";
22
+ export { StatusGlyphStrip, type StatusGlyph, type StatusGlyphStripProps } from "./StatusGlyphStrip";
22
23
  export { AsyncBoundary, AsyncSkeleton, asyncLoadDelayMs, resolveAsyncStatus, useAsyncBoundary, useAsyncCount, __resetAsyncDevWarnSeen, type AsyncBoundaryProps, type AsyncBoundaryLayout, type AsyncBoundaryContextValue, type AsyncStatus, } from "./AsyncBoundary";
23
24
  //# sourceMappingURL=index.d.ts.map