@ghxstship/xos-ui 0.0.0-stage → 4.16.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 (487) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +32 -2
  3. package/package.json +76 -4
  4. package/scripts/generate-stories.mjs +85 -0
  5. package/src/AIDisclosureBadge/README.md +7 -0
  6. package/src/AccessGridMatrix/README.md +3 -0
  7. package/src/Accordion/README.md +7 -0
  8. package/src/ActivityFeedItem/README.md +3 -0
  9. package/src/AgencySlate/README.md +3 -0
  10. package/src/AppShell/README.md +5 -0
  11. package/src/ApplicationForm/README.md +3 -0
  12. package/src/AssertionRankBadge/README.md +5 -0
  13. package/src/AvailabilityCalendar/README.md +3 -0
  14. package/src/Avatar/Avatar.tsx +56 -0
  15. package/src/Avatar/README.md +3 -0
  16. package/src/Avatar/avatar-class.ts +19 -0
  17. package/src/AvatarStack/README.md +3 -0
  18. package/src/Badge/README.md +3 -0
  19. package/src/Banner/README.md +3 -0
  20. package/src/BidSheet/README.md +3 -0
  21. package/src/Board/README.md +6 -0
  22. package/src/BrandMark/BrandMark.tsx +95 -0
  23. package/src/BrandMark/README.md +7 -0
  24. package/src/BrandSlot/README.md +6 -0
  25. package/src/Breadcrumbs/README.md +3 -0
  26. package/src/BudgetGrid/README.md +10 -0
  27. package/src/BulkActionBar/README.md +3 -0
  28. package/src/Button/Button.tsx +100 -0
  29. package/src/Button/README.md +10 -0
  30. package/src/Button/button-class.ts +54 -0
  31. package/src/ButtonLink/README.md +7 -0
  32. package/src/Calendar/README.md +3 -0
  33. package/src/Card/README.md +3 -0
  34. package/src/Chart/README.md +9 -0
  35. package/src/Charts/Calendar.tsx +228 -0
  36. package/src/Charts/Chart.tsx +547 -0
  37. package/src/Charts/Charts.tsx +20 -0
  38. package/src/Charts/Charts.types.ts +40 -0
  39. package/src/Charts/Gallery.tsx +25 -0
  40. package/src/Charts/Heatmap.tsx +116 -0
  41. package/src/Charts/OrgChart.tsx +53 -0
  42. package/src/Charts/ResourceSchedule.tsx +91 -0
  43. package/src/Charts/Sparkline.tsx +59 -0
  44. package/src/Charts/Timeline.tsx +777 -0
  45. package/src/Charts/categories.ts +21 -0
  46. package/src/Charts/timeline-plan.ts +191 -0
  47. package/src/Checkbox/README.md +6 -0
  48. package/src/ChecklistRunner/README.md +3 -0
  49. package/src/Chips/Badge.tsx +27 -0
  50. package/src/Chips/Chips.shared.tsx +34 -0
  51. package/src/Chips/Chips.tsx +21 -0
  52. package/src/Chips/Chips.types.ts +35 -0
  53. package/src/Chips/DepartmentChip.tsx +16 -0
  54. package/src/Chips/PhaseChip.tsx +16 -0
  55. package/src/Chips/PropertyChip.tsx +15 -0
  56. package/src/Chips/RecordKindChip.tsx +14 -0
  57. package/src/Chips/StateChip.tsx +19 -0
  58. package/src/Chips/Tag.tsx +47 -0
  59. package/src/Chips/URIDChip.tsx +14 -0
  60. package/src/Chips/chipClass.tsx +8 -0
  61. package/src/Chips/codeClass.tsx +6 -0
  62. package/src/ClockButton/README.md +6 -0
  63. package/src/CodeSample/README.md +7 -0
  64. package/src/ColorPicker/README.md +5 -0
  65. package/src/Combobox/README.md +7 -0
  66. package/src/CommandMenu/CommandMenu.tsx +179 -0
  67. package/src/CommandMenu/README.md +5 -0
  68. package/src/ComparisonTable/README.md +9 -0
  69. package/src/Compass/ChecklistRunner.tsx +128 -0
  70. package/src/Compass/ClockButton.tsx +57 -0
  71. package/src/Compass/Compass.shared.tsx +58 -0
  72. package/src/Compass/Compass.tsx +26 -0
  73. package/src/Compass/Compass.types.ts +79 -0
  74. package/src/Compass/DaySheetView.tsx +104 -0
  75. package/src/Compass/ForceUpdateScreen.tsx +29 -0
  76. package/src/Compass/LiveActivity.tsx +60 -0
  77. package/src/Compass/OfflineBanner.tsx +31 -0
  78. package/src/Compass/PhotoCapture.tsx +69 -0
  79. package/src/Compass/QuickIncidentSheet.tsx +46 -0
  80. package/src/Compass/ScanSheet.tsx +83 -0
  81. package/src/Compass/ShiftCard.tsx +55 -0
  82. package/src/Compass/SignaturePad.tsx +71 -0
  83. package/src/Compass/SyncConflictSheet.tsx +60 -0
  84. package/src/ConsentBanner/ConsentBanner.tsx +210 -0
  85. package/src/ConsentBanner/ConsentBannerStatic.tsx +163 -0
  86. package/src/ConsentBanner/ConsentSettings.tsx +213 -0
  87. package/src/ConsentBanner/README.md +101 -0
  88. package/src/ConsentBanner/consent.ts +238 -0
  89. package/src/ConsentBanner/index.ts +40 -0
  90. package/src/ConsentBanner/static.ts +11 -0
  91. package/src/ConsentBanner/useConsent.ts +160 -0
  92. package/src/ContextMenu/README.md +3 -0
  93. package/src/CoordinateMatrix/README.md +6 -0
  94. package/src/CredentialBadge/README.md +7 -0
  95. package/src/CurrencyInput/README.md +7 -0
  96. package/src/DataTable/DataTable.tsx +1034 -0
  97. package/src/DataTable/DataTableResizer.tsx +72 -0
  98. package/src/DataTable/DataTableVirtualizer.tsx +58 -0
  99. package/src/DataTable/README.md +9 -0
  100. package/src/DatePicker/README.md +5 -0
  101. package/src/DateRangePicker/README.md +3 -0
  102. package/src/DaySheetView/README.md +3 -0
  103. package/src/DepartmentChip/README.md +3 -0
  104. package/src/DepartmentGlyph/README.md +18 -0
  105. package/src/Dialog/README.md +3 -0
  106. package/src/DiffViewer/README.md +3 -0
  107. package/src/Divider/README.md +3 -0
  108. package/src/Drawer/README.md +3 -0
  109. package/src/DropdownMenu/README.md +3 -0
  110. package/src/EPKViewer/README.md +3 -0
  111. package/src/Editing/ColorPicker.tsx +125 -0
  112. package/src/Editing/DiffViewer.tsx +49 -0
  113. package/src/Editing/Editing.tsx +29 -0
  114. package/src/Editing/Editing.types.ts +71 -0
  115. package/src/Editing/FilterBuilder.tsx +72 -0
  116. package/src/Editing/QuickAdd.tsx +102 -0
  117. package/src/Editing/QuickAddChips.tsx +180 -0
  118. package/src/Editing/contrastRatio.tsx +11 -0
  119. package/src/Editing/parseQuickAdd.tsx +187 -0
  120. package/src/Editing/quickAddCore.ts +204 -0
  121. package/src/Editing/timeShorthand.ts +157 -0
  122. package/src/Editing/useQuickAdd.ts +201 -0
  123. package/src/EmergencyCodeCard/README.md +10 -0
  124. package/src/EmptyState/README.md +5 -0
  125. package/src/EngagementTimeline/README.md +3 -0
  126. package/src/ErrorState/README.md +3 -0
  127. package/src/FAQ/README.md +7 -0
  128. package/src/FeatureGrid/README.md +7 -0
  129. package/src/Feedback/Banner.tsx +40 -0
  130. package/src/Feedback/EmptyState.tsx +32 -0
  131. package/src/Feedback/ErrorState.tsx +32 -0
  132. package/src/Feedback/Feedback.shared.tsx +38 -0
  133. package/src/Feedback/Feedback.tsx +18 -0
  134. package/src/Feedback/Feedback.types.ts +40 -0
  135. package/src/Feedback/InlineAlert.tsx +19 -0
  136. package/src/Feedback/RefusalNotice.tsx +46 -0
  137. package/src/Feedback/RegionBoundary.tsx +102 -0
  138. package/src/Feedback/Toast.tsx +31 -0
  139. package/src/Feedback/ToastRegion.tsx +26 -0
  140. package/src/Feedback/UndoToast.tsx +97 -0
  141. package/src/FeedbackWidget/README.md +3 -0
  142. package/src/Field/Field.tsx +81 -0
  143. package/src/FileDrop/README.md +3 -0
  144. package/src/FilePreviewer/README.md +3 -0
  145. package/src/FilterBuilder/README.md +3 -0
  146. package/src/ForceUpdateScreen/README.md +3 -0
  147. package/src/Forms/Checkbox.tsx +14 -0
  148. package/src/Forms/CurrencyInput.tsx +40 -0
  149. package/src/Forms/Forms.shared.tsx +5 -0
  150. package/src/Forms/Forms.tsx +20 -0
  151. package/src/Forms/Forms.types.ts +33 -0
  152. package/src/Forms/Input.tsx +28 -0
  153. package/src/Forms/Money.tsx +15 -0
  154. package/src/Forms/NumberInput.tsx +85 -0
  155. package/src/Forms/Radio.tsx +31 -0
  156. package/src/Forms/Select.tsx +54 -0
  157. package/src/Forms/Switch.tsx +14 -0
  158. package/src/Forms/Textarea.tsx +30 -0
  159. package/src/Gallery/README.md +5 -0
  160. package/src/GateLifecycleRail/README.md +7 -0
  161. package/src/GateReadinessPanel/README.md +8 -0
  162. package/src/Gateway/AgencySlate.tsx +76 -0
  163. package/src/Gateway/ApplicationForm.tsx +48 -0
  164. package/src/Gateway/AvailabilityCalendar.tsx +82 -0
  165. package/src/Gateway/EPKViewer.tsx +77 -0
  166. package/src/Gateway/EngagementTimeline.tsx +43 -0
  167. package/src/Gateway/Gateway.shared.tsx +5 -0
  168. package/src/Gateway/Gateway.tsx +30 -0
  169. package/src/Gateway/Gateway.types.ts +69 -0
  170. package/src/Gateway/OnboardingPacket.tsx +61 -0
  171. package/src/Gateway/OpportunityCard.tsx +73 -0
  172. package/src/Gateway/OpportunityFilters.tsx +64 -0
  173. package/src/Gateway/PaymentTracker.tsx +71 -0
  174. package/src/Gateway/PayoutDetailsForm.tsx +62 -0
  175. package/src/Gateway/ProfileEditor.tsx +45 -0
  176. package/src/Gateway/ProgressBar.tsx +30 -0
  177. package/src/Gateway/RatingDialog.tsx +83 -0
  178. package/src/Gateway/UpNextCard.tsx +76 -0
  179. package/src/Glyphs/Glyphs.tsx +66 -0
  180. package/src/Grids/BidSheet.tsx +63 -0
  181. package/src/Grids/BudgetGrid.tsx +164 -0
  182. package/src/Grids/Grids.shared.tsx +5 -0
  183. package/src/Grids/Grids.tsx +11 -0
  184. package/src/Grids/Grids.types.ts +38 -0
  185. package/src/Grids/SpreadsheetGrid.tsx +445 -0
  186. package/src/Grids/columnTotal.tsx +14 -0
  187. package/src/Grids/glForCode.tsx +11 -0
  188. package/src/Grids/parseCell.tsx +16 -0
  189. package/src/Help/FeedbackWidget.tsx +89 -0
  190. package/src/Help/Help.tsx +14 -0
  191. package/src/Help/Help.types.ts +51 -0
  192. package/src/Help/HelpPanel.tsx +116 -0
  193. package/src/Help/NotificationCenter.tsx +100 -0
  194. package/src/Help/OnboardingChecklist.tsx +57 -0
  195. package/src/Help/ShortcutEditor.tsx +81 -0
  196. package/src/Help/WhatsNew.tsx +33 -0
  197. package/src/HelpPanel/README.md +5 -0
  198. package/src/HoverCard/README.md +3 -0
  199. package/src/Icon/Icon.tsx +47 -0
  200. package/src/Icon/README.md +9 -0
  201. package/src/IconButton/README.md +6 -0
  202. package/src/Identity/BrandSlot.tsx +20 -0
  203. package/src/Identity/BrandSlotFrame.tsx +38 -0
  204. package/src/Identity/CredentialBadge.tsx +92 -0
  205. package/src/Identity/Identity.tsx +14 -0
  206. package/src/Identity/Identity.types.ts +25 -0
  207. package/src/Identity/PresenceIndicator.tsx +37 -0
  208. package/src/Identity/QRCode.tsx +22 -0
  209. package/src/Identity/WhiteLabelPreview.tsx +33 -0
  210. package/src/Identity/qrPath.tsx +16 -0
  211. package/src/Identity/tokenVariable.tsx +9 -0
  212. package/src/InlineAlert/README.md +3 -0
  213. package/src/Input/README.md +8 -0
  214. package/src/Kbd/Kbd.tsx +30 -0
  215. package/src/Kbd/README.md +6 -0
  216. package/src/Layout/AppShell.tsx +151 -0
  217. package/src/Layout/Layout.tsx +14 -0
  218. package/src/Layout/Layout.types.ts +43 -0
  219. package/src/Layout/PageHeader.tsx +22 -0
  220. package/src/Layout/ResizablePanel.tsx +81 -0
  221. package/src/Layout/ScrollRegion.tsx +107 -0
  222. package/src/Layout/SplitView.tsx +78 -0
  223. package/src/Layout/Stepper.tsx +39 -0
  224. package/src/LegalText/LegalText.tsx +289 -0
  225. package/src/LegalText/README.md +10 -0
  226. package/src/LegalText/index.ts +29 -0
  227. package/src/LegalText/legal-markdown.ts +581 -0
  228. package/src/Link/Link.tsx +25 -0
  229. package/src/Link/README.md +5 -0
  230. package/src/Link/link-class.ts +10 -0
  231. package/src/LiveActivity/README.md +3 -0
  232. package/src/LogoSlotWall/README.md +7 -0
  233. package/src/MapView/README.md +5 -0
  234. package/src/Marketing/AIDisclosureBadge.tsx +31 -0
  235. package/src/Marketing/ButtonLink.tsx +32 -0
  236. package/src/Marketing/CodeSample.tsx +47 -0
  237. package/src/Marketing/ComparisonScroll.tsx +7 -0
  238. package/src/Marketing/ComparisonTable.tsx +104 -0
  239. package/src/Marketing/FAQ.tsx +26 -0
  240. package/src/Marketing/FeatureGrid.tsx +65 -0
  241. package/src/Marketing/GateLifecycleRail.tsx +52 -0
  242. package/src/Marketing/LogoSlotWall.tsx +53 -0
  243. package/src/Marketing/Marketing.tsx +49 -0
  244. package/src/Marketing/Marketing.types.ts +64 -0
  245. package/src/Marketing/MarketingFooter.tsx +88 -0
  246. package/src/Marketing/MarketingHero.tsx +45 -0
  247. package/src/Marketing/MarketingNav.tsx +76 -0
  248. package/src/Marketing/MarketingPoints.tsx +16 -0
  249. package/src/Marketing/MarketingSection.tsx +52 -0
  250. package/src/Marketing/PersonaSwitcher.tsx +137 -0
  251. package/src/Marketing/PriceDisplay.tsx +56 -0
  252. package/src/Marketing/PricingTable.tsx +122 -0
  253. package/src/Marketing/ProofStatStrip.tsx +35 -0
  254. package/src/Marketing/ScreenshotFrame.tsx +56 -0
  255. package/src/Marketing/SurfaceTriptych.tsx +43 -0
  256. package/src/Marketing/Testimonial.tsx +45 -0
  257. package/src/Marketing/marketing-copy.ts +25 -0
  258. package/src/Marketing/provided.tsx +36 -0
  259. package/src/MarketingFooter/README.md +7 -0
  260. package/src/MarketingHero/README.md +7 -0
  261. package/src/MarketingNav/README.md +7 -0
  262. package/src/MarketingSection/README.md +7 -0
  263. package/src/Media/FilePreviewer.tsx +86 -0
  264. package/src/Media/MapView.tsx +200 -0
  265. package/src/Media/Media.tsx +11 -0
  266. package/src/Media/Media.types.ts +47 -0
  267. package/src/Media/RichTextEditor.tsx +198 -0
  268. package/src/Media/toLngLat.tsx +13 -0
  269. package/src/Menus/ContextMenu.tsx +106 -0
  270. package/src/Menus/DropdownMenu.tsx +51 -0
  271. package/src/Menus/Menus.shared.tsx +67 -0
  272. package/src/Menus/Menus.tsx +13 -0
  273. package/src/Menus/Menus.types.ts +49 -0
  274. package/src/Menus/OrgSwitcher.tsx +69 -0
  275. package/src/Menus/compactTriggerClass.tsx +7 -0
  276. package/src/Menus/menuClass.tsx +4 -0
  277. package/src/Menus/menuItemClass.tsx +7 -0
  278. package/src/Menus/orgSwitcherTriggerClass.tsx +7 -0
  279. package/src/Money/README.md +6 -0
  280. package/src/MultiSelect/README.md +3 -0
  281. package/src/Navigation/Accordion.tsx +59 -0
  282. package/src/Navigation/Breadcrumbs.tsx +59 -0
  283. package/src/Navigation/MoreFields.tsx +42 -0
  284. package/src/Navigation/Navigation.shared.tsx +32 -0
  285. package/src/Navigation/Navigation.tsx +21 -0
  286. package/src/Navigation/Navigation.types.ts +63 -0
  287. package/src/Navigation/Pagination.tsx +30 -0
  288. package/src/Navigation/SegmentedControl.tsx +87 -0
  289. package/src/Navigation/Sidebar.tsx +106 -0
  290. package/src/Navigation/TabBar.tsx +61 -0
  291. package/src/Navigation/Tabs.tsx +79 -0
  292. package/src/Navigation/TopNav.tsx +86 -0
  293. package/src/Navigation/sidebar-classes.ts +18 -0
  294. package/src/NotificationCenter/README.md +3 -0
  295. package/src/NumberInput/README.md +3 -0
  296. package/src/OfflineBanner/README.md +3 -0
  297. package/src/OnboardingChecklist/README.md +3 -0
  298. package/src/OnboardingPacket/README.md +3 -0
  299. package/src/OpportunityCard/README.md +5 -0
  300. package/src/OpportunityFilters/README.md +3 -0
  301. package/src/OrgChart/README.md +5 -0
  302. package/src/OrgSwitcher/README.md +3 -0
  303. package/src/Overlays/Dialog.tsx +54 -0
  304. package/src/Overlays/Drawer.tsx +62 -0
  305. package/src/Overlays/HoverCard.tsx +59 -0
  306. package/src/Overlays/Overlays.shared.tsx +12 -0
  307. package/src/Overlays/Overlays.tsx +20 -0
  308. package/src/Overlays/Overlays.types.ts +66 -0
  309. package/src/Overlays/Popover.tsx +70 -0
  310. package/src/Overlays/PropertyList.tsx +19 -0
  311. package/src/Overlays/ShortcutSheet.tsx +62 -0
  312. package/src/Overlays/SidePeek.tsx +117 -0
  313. package/src/Overlays/Tooltip.tsx +73 -0
  314. package/src/Overlays/panelClass.tsx +6 -0
  315. package/src/Overlays/popoverPanelClass.tsx +6 -0
  316. package/src/PageHeader/README.md +3 -0
  317. package/src/Pagination/README.md +3 -0
  318. package/src/PaymentTracker/README.md +3 -0
  319. package/src/PayoutDetailsForm/README.md +3 -0
  320. package/src/PersonaSwitcher/README.md +7 -0
  321. package/src/PhaseChip/README.md +5 -0
  322. package/src/PhaseGlyph/README.md +17 -0
  323. package/src/PhotoCapture/README.md +3 -0
  324. package/src/Pickers/Combobox.tsx +91 -0
  325. package/src/Pickers/DatePicker.tsx +60 -0
  326. package/src/Pickers/DateRangePicker.tsx +78 -0
  327. package/src/Pickers/FileDrop.tsx +84 -0
  328. package/src/Pickers/MultiSelect.tsx +118 -0
  329. package/src/Pickers/Pickers.shared.tsx +337 -0
  330. package/src/Pickers/Pickers.tsx +17 -0
  331. package/src/Pickers/Pickers.types.ts +47 -0
  332. package/src/Pickers/Slider.tsx +59 -0
  333. package/src/Pickers/TimePicker.tsx +68 -0
  334. package/src/Pickers/rankOptions.tsx +12 -0
  335. package/src/Popover/README.md +3 -0
  336. package/src/PresenceIndicator/README.md +3 -0
  337. package/src/PriceDisplay/README.md +7 -0
  338. package/src/PricingTable/README.md +9 -0
  339. package/src/ProfileEditor/README.md +3 -0
  340. package/src/ProgressBar/README.md +3 -0
  341. package/src/ProofStatStrip/README.md +7 -0
  342. package/src/PropertyChip/README.md +3 -0
  343. package/src/ProvenanceBadge/README.md +3 -0
  344. package/src/QRCode/README.md +6 -0
  345. package/src/QuickAdd/README.md +5 -0
  346. package/src/QuickIncidentSheet/README.md +3 -0
  347. package/src/Radio/README.md +3 -0
  348. package/src/RadioChannelTable/README.md +7 -0
  349. package/src/RatingDialog/README.md +3 -0
  350. package/src/ReconciliationTable/README.md +3 -0
  351. package/src/RecordKindChip/README.md +3 -0
  352. package/src/RecordKindGlyph/README.md +34 -0
  353. package/src/RecordRow/README.md +7 -0
  354. package/src/RefusalNotice/README.md +5 -0
  355. package/src/ResizablePanel/README.md +3 -0
  356. package/src/ResourceSchedule/README.md +6 -0
  357. package/src/RichTextEditor/README.md +3 -0
  358. package/src/RichTextEditor/extensions.ts +217 -0
  359. package/src/RunOfShowLive/README.md +5 -0
  360. package/src/ScanSheet/README.md +3 -0
  361. package/src/ScreenshotFrame/README.md +7 -0
  362. package/src/ScrollRegion/README.md +9 -0
  363. package/src/SegmentedControl/README.md +5 -0
  364. package/src/Select/README.md +5 -0
  365. package/src/ShiftCard/README.md +3 -0
  366. package/src/ShortcutEditor/README.md +3 -0
  367. package/src/ShortcutSheet/README.md +3 -0
  368. package/src/SidePeek/README.md +6 -0
  369. package/src/Sidebar/README.md +5 -0
  370. package/src/SignaturePad/README.md +3 -0
  371. package/src/Skeleton/README.md +3 -0
  372. package/src/Slider/README.md +3 -0
  373. package/src/SplitView/README.md +3 -0
  374. package/src/SpreadsheetGrid/README.md +9 -0
  375. package/src/StalenessIndicator/README.md +3 -0
  376. package/src/StatTile/README.md +6 -0
  377. package/src/StateChip/README.md +6 -0
  378. package/src/StateIcon/README.md +6 -0
  379. package/src/StateIcon/StateIcon.tsx +127 -0
  380. package/src/StatusHeatmap/README.md +15 -0
  381. package/src/Stepper/README.md +3 -0
  382. package/src/Surface/Skeleton.tsx +21 -0
  383. package/src/Surface/Surface.tsx +63 -0
  384. package/src/SurfaceTriptych/README.md +7 -0
  385. package/src/Switch/README.md +5 -0
  386. package/src/SyncConflictSheet/README.md +3 -0
  387. package/src/TabBar/README.md +7 -0
  388. package/src/Tabs/README.md +6 -0
  389. package/src/Tag/README.md +3 -0
  390. package/src/TemplateAuth/README.md +6 -0
  391. package/src/TemplateCollection/README.md +6 -0
  392. package/src/TemplateDashboard/README.md +8 -0
  393. package/src/TemplateDocument/README.md +5 -0
  394. package/src/TemplateGatewayShell/README.md +5 -0
  395. package/src/TemplateGridEditor/README.md +3 -0
  396. package/src/TemplateRecord/README.md +3 -0
  397. package/src/TemplateSettings/README.md +5 -0
  398. package/src/TemplateSplitView/README.md +3 -0
  399. package/src/TemplateSystem/README.md +5 -0
  400. package/src/TemplateWizard/README.md +3 -0
  401. package/src/Templates/TemplateAuth.tsx +16 -0
  402. package/src/Templates/TemplateCollection.tsx +35 -0
  403. package/src/Templates/TemplateDashboard.tsx +200 -0
  404. package/src/Templates/TemplateDocument.tsx +24 -0
  405. package/src/Templates/TemplateGatewayShell.tsx +36 -0
  406. package/src/Templates/TemplateGridEditor.tsx +17 -0
  407. package/src/Templates/TemplateRecord.tsx +31 -0
  408. package/src/Templates/TemplateSettings.tsx +26 -0
  409. package/src/Templates/TemplateSplitView.tsx +27 -0
  410. package/src/Templates/TemplateSystem.tsx +19 -0
  411. package/src/Templates/TemplateSystemLink.tsx +55 -0
  412. package/src/Templates/TemplateWizard.tsx +43 -0
  413. package/src/Templates/Templates.tsx +29 -0
  414. package/src/Templates/Templates.types.ts +153 -0
  415. package/src/Testimonial/README.md +7 -0
  416. package/src/Textarea/README.md +3 -0
  417. package/src/TimePicker/README.md +5 -0
  418. package/src/Timeline/README.md +6 -0
  419. package/src/Toast/README.md +3 -0
  420. package/src/Tooltip/README.md +3 -0
  421. package/src/TopNav/README.md +5 -0
  422. package/src/TreeView/README.md +3 -0
  423. package/src/URIDChip/README.md +5 -0
  424. package/src/UndoToast/README.md +3 -0
  425. package/src/UpNextCard/README.md +6 -0
  426. package/src/Views/ActivityFeedItem.tsx +52 -0
  427. package/src/Views/Board.tsx +229 -0
  428. package/src/Views/BulkActionBar.tsx +76 -0
  429. package/src/Views/RecordList.tsx +146 -0
  430. package/src/Views/RecordRow.tsx +132 -0
  431. package/src/Views/StatTile.tsx +88 -0
  432. package/src/Views/TreeView.tsx +161 -0
  433. package/src/Views/Views.tsx +18 -0
  434. package/src/Views/Views.types.ts +99 -0
  435. package/src/WhatsNew/README.md +3 -0
  436. package/src/WhiteLabelPreview/README.md +8 -0
  437. package/src/XOS/AccessGridMatrix.tsx +111 -0
  438. package/src/XOS/AssertionRankBadge.tsx +27 -0
  439. package/src/XOS/CoordinateMatrix.tsx +123 -0
  440. package/src/XOS/EmergencyCodeCard.tsx +109 -0
  441. package/src/XOS/GateReadinessPanel.tsx +100 -0
  442. package/src/XOS/ProvenanceBadge.tsx +19 -0
  443. package/src/XOS/RadioChannelTable.tsx +50 -0
  444. package/src/XOS/ReconciliationTable.tsx +64 -0
  445. package/src/XOS/RunOfShowLive.tsx +97 -0
  446. package/src/XOS/StalenessIndicator.tsx +31 -0
  447. package/src/XOS/StatusHeatmap.tsx +200 -0
  448. package/src/XOS/XOS.shared.tsx +90 -0
  449. package/src/XOS/XOS.tsx +29 -0
  450. package/src/XOS/XOS.types.ts +99 -0
  451. package/src/XOS/resolveStep.tsx +16 -0
  452. package/src/brand/defaults/README.md +13 -0
  453. package/src/brand/defaults/app-icon.svg +6 -0
  454. package/src/brand/defaults/favicon.svg +6 -0
  455. package/src/brand/defaults/logo-dark.svg +6 -0
  456. package/src/brand/defaults/logo-light.svg +6 -0
  457. package/src/brand/defaults/splash.svg +6 -0
  458. package/src/index.ts +606 -0
  459. package/src/lib/context.tsx +156 -0
  460. package/src/lib/cx.ts +4 -0
  461. package/src/lib/format.ts +200 -0
  462. package/src/lib/hooks.ts +187 -0
  463. package/src/lib/i18n.ts +97 -0
  464. package/src/lib/icons.ts +45 -0
  465. package/src/lib/live.ts +92 -0
  466. package/src/lib/preferences.ts +242 -0
  467. package/src/lib/route-transition.tsx +22 -0
  468. package/src/lib/selection.ts +92 -0
  469. package/src/lib/shortcut-targets.ts +125 -0
  470. package/src/lib/theme.ts +50 -0
  471. package/src/lib/undo-stack.ts +125 -0
  472. package/src/marketing.ts +33 -0
  473. package/src/pwa/action-outcome.tsx +81 -0
  474. package/src/pwa/analytics.ts +236 -0
  475. package/src/pwa/browser-push.tsx +132 -0
  476. package/src/pwa/client.ts +126 -0
  477. package/src/pwa/index.ts +40 -0
  478. package/src/pwa/offline-key.ts +18 -0
  479. package/src/pwa/service-worker.ts +229 -0
  480. package/src/static.ts +10 -0
  481. package/src/styles/base.css +208 -0
  482. package/src/styles/components.css +453 -0
  483. package/src/styles/index.css +16 -0
  484. package/src/styles/marketing.css +1260 -0
  485. package/src/styles/reference.css +5792 -0
  486. package/src/types/reference.d.ts +1608 -0
  487. package/tailwind.config.cjs +3 -0
@@ -0,0 +1,111 @@
1
+ import { useState, type ReactElement } from "react";
2
+ import { cx } from "../lib/cx.ts";
3
+ import { useT } from "../lib/context.tsx";
4
+ import { Icon } from "../Icon/Icon.tsx";
5
+ import { ScrollRegion } from "../Layout/Layout.tsx";
6
+ import { useGridFocus } from "./XOS.shared.tsx";
7
+ import { type AccessGridMatrixProps } from "./XOS.types.ts";
8
+
9
+ const CAT: Record<number, string> = {
10
+ 1: cx("bg-viz-cat-1"),
11
+ 2: cx("bg-viz-cat-2"),
12
+ 3: cx("bg-viz-cat-3"),
13
+ 4: cx("bg-viz-cat-4"),
14
+ 5: cx("bg-viz-cat-5"),
15
+ 6: cx("bg-viz-cat-6"),
16
+ 7: cx("bg-viz-cat-7"),
17
+ };
18
+
19
+ /**
20
+ * Which credential categories enter which zones; Compass validates scans against it offline. An
21
+ * ARIA grid: arrows move, Space or Enter toggles a grant.
22
+ */
23
+ export function AccessGridMatrix({
24
+ label,
25
+ zones,
26
+ categories,
27
+ grants,
28
+ onChange,
29
+ }: AccessGridMatrixProps): ReactElement {
30
+ const t = useT();
31
+ const [granted, setGranted] = useState(grants);
32
+ const grid = useGridFocus(categories.length, zones.length);
33
+ const has = (cat: string, zone: string) => granted.includes(`${cat}|${zone}`);
34
+ const toggle = (cat: string, zone: string) => {
35
+ const key = `${cat}|${zone}`;
36
+ const next = has(cat, zone) ? granted.filter((g) => g !== key) : [...granted, key];
37
+ setGranted(next);
38
+ onChange?.(next);
39
+ };
40
+ return (
41
+ <ScrollRegion label={label}>
42
+ <table
43
+ role="grid"
44
+ aria-label={label}
45
+ className="border-separate border-spacing-2 text-text-12"
46
+ >
47
+ <caption className="pb-8 text-start text-text-13 font-semibold">{label}</caption>
48
+ <thead>
49
+ <tr>
50
+ <th scope="col" className="p-4 text-start font-medium text-text-secondary">
51
+ {t("access.credential")}
52
+ </th>
53
+ {zones.map((z) => (
54
+ <th key={z} scope="col" className="p-4 font-medium text-text-secondary">
55
+ {z}
56
+ </th>
57
+ ))}
58
+ </tr>
59
+ </thead>
60
+ <tbody>
61
+ {categories.map((cat, ri) => (
62
+ <tr key={cat.name}>
63
+ <th scope="row" className="pe-12 text-start font-medium whitespace-nowrap">
64
+ <span className="inline-flex items-center gap-6">
65
+ <span
66
+ aria-hidden="true"
67
+ className={cx(
68
+ "inline-block size-(--ui-switch-knob) rounded-mark",
69
+ CAT[cat.color],
70
+ )}
71
+ />
72
+ {cat.name}
73
+ </span>
74
+ </th>
75
+ {zones.map((zone, ci) => {
76
+ const on = has(cat.name, zone);
77
+ return (
78
+ <td
79
+ key={zone}
80
+ ref={grid.register(ri, ci)}
81
+ role="gridcell"
82
+ aria-selected={on}
83
+ aria-label={t(on ? "access.allowed" : "access.denied", { cat: cat.name, zone })}
84
+ tabIndex={grid.tabIndex(ri, ci)}
85
+ onFocus={() => grid.setActive([ri, ci])}
86
+ onClick={() => toggle(cat.name, zone)}
87
+ onKeyDown={(e) => {
88
+ if (e.key === " " || e.key === "Enter") {
89
+ e.preventDefault();
90
+ toggle(cat.name, zone);
91
+ } else grid.onKeyDown(e, ri, ci);
92
+ }}
93
+ className={cx(
94
+ "xos-hit w-(--space-40) h-control-md rounded-chip text-center cursor-pointer",
95
+ on
96
+ ? "bg-bg-hover text-success ring-(length:--stroke-width-hairline) ring-inset ring-success"
97
+ : "bg-bg-surface text-text-tertiary ring-(length:--stroke-width-hairline) ring-inset ring-border-subtle",
98
+ "forced-colors:border",
99
+ )}
100
+ >
101
+ <Icon name={on ? "Check" : "Minus"} size={14} />
102
+ </td>
103
+ );
104
+ })}
105
+ </tr>
106
+ ))}
107
+ </tbody>
108
+ </table>
109
+ </ScrollRegion>
110
+ );
111
+ }
@@ -0,0 +1,27 @@
1
+ import { type ReactElement } from "react";
2
+ import { cx } from "../lib/cx.ts";
3
+ import { useT } from "../lib/context.tsx";
4
+ import { chipClass } from "../Chips/Chips.tsx";
5
+ import { type AssertionRankBadgeProps } from "./XOS.types.ts";
6
+
7
+ /** An assertion value with four pips for its rank from 4 down to 0. */
8
+ export function AssertionRankBadge({ label, rank }: AssertionRankBadgeProps): ReactElement {
9
+ const t = useT();
10
+ const on = rank === 4 ? "bg-success" : rank <= 1 ? "bg-warning" : "bg-text-secondary";
11
+ return (
12
+ <span role="img" aria-label={t("assertion.aria", { label, rank })} className={chipClass}>
13
+ <span aria-hidden="true" className="inline-flex gap-2">
14
+ {[1, 2, 3, 4].map((i) => (
15
+ <span
16
+ key={i}
17
+ className={cx(
18
+ "w-(--ui-pip-inline) h-(--ui-pip-block) rounded-mark",
19
+ i <= rank ? on : "bg-border-strong",
20
+ )}
21
+ />
22
+ ))}
23
+ </span>
24
+ <span aria-hidden="true">{label}</span>
25
+ </span>
26
+ );
27
+ }
@@ -0,0 +1,123 @@
1
+ import { type ReactElement } from "react";
2
+ import { cx } from "../lib/cx.ts";
3
+ import { useFormat, useT } from "../lib/context.tsx";
4
+ import { DepartmentGlyph, PhaseGlyph } from "../Glyphs/Glyphs.tsx";
5
+ import { ScrollRegion } from "../Layout/Layout.tsx";
6
+ import { useGridFocus } from "./XOS.shared.tsx";
7
+ import { type CoordinateMatrixProps } from "./XOS.types.ts";
8
+
9
+ const SEQ: Record<number, string> = {
10
+ 2: cx("bg-viz-seq-2 text-viz-ink"),
11
+ 3: cx("bg-viz-seq-3 text-viz-ink"),
12
+ 4: cx("bg-viz-seq-4 text-viz-ink"),
13
+ 5: cx("bg-viz-seq-5 text-viz-ink"),
14
+ 6: cx("bg-viz-seq-6 text-accent-text-on"),
15
+ 7: cx("bg-viz-seq-7 text-accent-text-on"),
16
+ 8: cx("bg-viz-seq-8 text-accent-text-on"),
17
+ 9: cx("bg-viz-seq-9 text-accent-text-on"),
18
+ };
19
+
20
+ /**
21
+ * The 10 departments crossed with the 9 phases. An ARIA grid: arrows move between cells, Enter
22
+ * drills into a coordinate's records. Empty coordinates are outlined, not filled.
23
+ */
24
+ export function CoordinateMatrix({
25
+ label,
26
+ corner,
27
+ rows,
28
+ cols,
29
+ cells,
30
+ onCellSelect,
31
+ }: CoordinateMatrixProps): ReactElement {
32
+ const t = useT();
33
+ const fmt = useFormat();
34
+ const grid = useGridFocus(rows.length, cols.length);
35
+ const max = Math.max(0, ...Object.values(cells));
36
+ const step = (v: number) => (v ? Math.min(9, 2 + Math.round((v / max) * 6)) : 0);
37
+ return (
38
+ <ScrollRegion label={label}>
39
+ <table
40
+ role="grid"
41
+ aria-label={label}
42
+ className="border-separate border-spacing-2 text-text-12"
43
+ >
44
+ <caption className="pb-8 text-start text-text-13 font-semibold">{label}</caption>
45
+ <thead>
46
+ <tr>
47
+ <th scope="col" className="p-4 text-start font-medium text-text-secondary">
48
+ {corner}
49
+ </th>
50
+ {cols.map((c) => (
51
+ <th
52
+ key={c.code}
53
+ scope="col"
54
+ title={c.name}
55
+ className="p-4 font-medium text-text-secondary text-center"
56
+ >
57
+ <span className="flex flex-col items-center gap-2">
58
+ <PhaseGlyph
59
+ code={c.code}
60
+ size={14}
61
+ label={t("phase.gateName", { n: c.gate, name: c.name })}
62
+ />
63
+ <span aria-hidden="true" className="tabular-nums">
64
+ {c.gate}
65
+ </span>
66
+ </span>
67
+ </th>
68
+ ))}
69
+ </tr>
70
+ </thead>
71
+ <tbody>
72
+ {rows.map((r, ri) => (
73
+ <tr key={r.code}>
74
+ <th scope="row" className="pe-12 text-start font-medium whitespace-nowrap">
75
+ <span className="inline-flex items-center gap-6">
76
+ <DepartmentGlyph code={r.code} size={14} color="var(--color-text-secondary)" />
77
+ <span>{r.name}</span>
78
+ <span className="font-mono text-text-secondary">{r.code}</span>
79
+ </span>
80
+ </th>
81
+ {cols.map((c, ci) => {
82
+ const v = cells[`${r.code}|${c.code}`] ?? 0;
83
+ const s = step(v);
84
+ const name = v
85
+ ? t("matrix.cell", { row: r.name, col: c.name, n: fmt.number(v) })
86
+ : t("matrix.empty", { row: r.name, col: c.name });
87
+ return (
88
+ <td
89
+ key={c.code}
90
+ ref={grid.register(ri, ci)}
91
+ role="gridcell"
92
+ tabIndex={grid.tabIndex(ri, ci)}
93
+ aria-label={name}
94
+ onFocus={() => grid.setActive([ri, ci])}
95
+ onKeyDown={(e) => {
96
+ if ((e.key === "Enter" || e.key === " ") && v) {
97
+ e.preventDefault();
98
+ onCellSelect?.(r.code, c.code);
99
+ } else grid.onKeyDown(e, ri, ci);
100
+ }}
101
+ onClick={() => (v ? onCellSelect?.(r.code, c.code) : undefined)}
102
+ className={cx(
103
+ "xos-hit w-(--space-48) h-control-md rounded-chip text-center font-semibold tabular-nums",
104
+ v
105
+ ? cx(
106
+ SEQ[s],
107
+ "cursor-pointer hover:outline-solid hover:outline-stroke-focus hover:outline-text-primary",
108
+ )
109
+ : "ring-(length:--stroke-width-hairline) ring-inset ring-border-subtle",
110
+ "forced-colors:border",
111
+ )}
112
+ >
113
+ {v ? <span aria-hidden="true">{fmt.number(v)}</span> : null}
114
+ </td>
115
+ );
116
+ })}
117
+ </tr>
118
+ ))}
119
+ </tbody>
120
+ </table>
121
+ </ScrollRegion>
122
+ );
123
+ }
@@ -0,0 +1,109 @@
1
+ import { type ReactElement } from "react";
2
+ import { cx } from "../lib/cx.ts";
3
+ import { useT } from "../lib/context.tsx";
4
+ import { Icon } from "../Icon/Icon.tsx";
5
+ import { SERVICES } from "./XOS.shared.tsx";
6
+ import { type EmergencyCodeCardProps } from "./XOS.types.ts";
7
+ import { resolveStep } from "./resolveStep.tsx";
8
+
9
+ const SWATCH: Record<EmergencyCodeCardProps["swatch"], string> = {
10
+ "ecode-red": cx("bg-ecode-red border-t-ecode-red"),
11
+ "ecode-orange": cx("bg-ecode-orange border-t-ecode-orange"),
12
+ "ecode-yellow": cx("bg-ecode-yellow border-t-ecode-yellow"),
13
+ "ecode-green": cx("bg-ecode-green border-t-ecode-green"),
14
+ "ecode-blue": cx("bg-ecode-blue border-t-ecode-blue"),
15
+ "ecode-purple": cx("bg-ecode-purple border-t-ecode-purple"),
16
+ "ecode-white": cx("bg-ecode-white border-t-ecode-white"),
17
+ "ecode-black": cx("bg-ecode-black border-t-ecode-black"),
18
+ "ecode-pink": cx("bg-ecode-pink border-t-ecode-pink"),
19
+ "ecode-indigo": cx("bg-ecode-indigo border-t-ecode-indigo"),
20
+ "ecode-silver": cx("bg-ecode-silver border-t-ecode-silver"),
21
+ "ecode-grey": cx("bg-ecode-grey border-t-ecode-grey"),
22
+ "ecode-amber": cx("bg-ecode-amber border-t-ecode-amber"),
23
+ "ecode-adam": cx("bg-ecode-adam border-t-ecode-adam"),
24
+ };
25
+
26
+ /**
27
+ * One global emergency code's protocol for one operational domain. The code word is always written;
28
+ * the swatch is for recognition only. Steps name services; the jurisdiction supplies the agencies.
29
+ */
30
+ export function EmergencyCodeCard({
31
+ authorities,
32
+ recordKey,
33
+ code,
34
+ name,
35
+ swatch,
36
+ domain,
37
+ steps,
38
+ channel,
39
+ }: EmergencyCodeCardProps): ReactElement {
40
+ const t = useT();
41
+ const used = SERVICES.filter((s) => steps.some((step) => step.includes(`{${s}}`)));
42
+ const listed = (authorities ?? [])
43
+ .filter((a) => used.includes(a.service))
44
+ .sort((a, b) => SERVICES.indexOf(a.service) - SERVICES.indexOf(b.service));
45
+ const tone = SWATCH[swatch] ?? SWATCH["ecode-red"];
46
+ return (
47
+ <article
48
+ aria-labelledby={`${recordKey ?? code}-title`}
49
+ className={cx(
50
+ "flex flex-col gap-8 w-(--ui-popover) max-w-full p-16 box-border rounded-card bg-bg-raised",
51
+ "border border-border-subtle border-t-stroke-swatch",
52
+ tone.split(" ")[1],
53
+ )}
54
+ >
55
+ <header className="flex items-center gap-8">
56
+ <span
57
+ aria-hidden="true"
58
+ className={cx(
59
+ "flex-none size-icon-24 rounded-chip ring-(length:--stroke-width-hairline) ring-inset ring-border-control",
60
+ tone.split(" ")[0],
61
+ )}
62
+ />
63
+ <div className="flex flex-col">
64
+ <strong id={`${recordKey ?? code}-title`} className="text-heading-16 font-semibold">
65
+ {code}
66
+ </strong>
67
+ <span>{name}</span>
68
+ </div>
69
+ {recordKey ? (
70
+ <span className="ms-auto font-mono text-text-12 text-text-secondary">{recordKey}</span>
71
+ ) : null}
72
+ </header>
73
+ {domain ? (
74
+ <span className="text-text-12 font-medium text-text-secondary">{domain}</span>
75
+ ) : null}
76
+ <ol className="flex flex-col gap-4 m-0 ps-20">
77
+ {steps.map((step, i) => (
78
+ <li key={i}>{resolveStep(step, authorities, t)}</li>
79
+ ))}
80
+ </ol>
81
+ {listed.length ? (
82
+ <dl
83
+ aria-label={t("ecode.authorities")}
84
+ className="flex flex-col gap-4 m-0 pt-8 border-t border-border-subtle"
85
+ >
86
+ {listed.map((a) => (
87
+ <div key={a.service} className="flex gap-8">
88
+ <dt className="flex-none w-(--ui-props-label) text-text-12 font-medium text-text-secondary">
89
+ {t(`ecode.role.${a.service}`)}
90
+ </dt>
91
+ <dd className="m-0">
92
+ {a.agency}
93
+ {a.contact ? (
94
+ <span className="text-text-secondary tabular-nums"> · {a.contact}</span>
95
+ ) : null}
96
+ </dd>
97
+ </div>
98
+ ))}
99
+ </dl>
100
+ ) : null}
101
+ {channel ? (
102
+ <footer className="flex items-center gap-6 text-text-12 text-text-secondary">
103
+ <Icon name="Radio" size={14} />
104
+ <span>{channel}</span>
105
+ </footer>
106
+ ) : null}
107
+ </article>
108
+ );
109
+ }
@@ -0,0 +1,100 @@
1
+ import { type ReactElement } from "react";
2
+ import { cx } from "../lib/cx.ts";
3
+ import { useT } from "../lib/context.tsx";
4
+ import { Icon } from "../Icon/Icon.tsx";
5
+ import { Button } from "../Button/Button.tsx";
6
+ import { PhaseGlyph } from "../Glyphs/Glyphs.tsx";
7
+ import { Tag, chipClass } from "../Chips/Chips.tsx";
8
+ import { cardBodyClass, cardClass, cardFootClass, cardHeadClass } from "../Surface/Surface.tsx";
9
+ import { ResultIcon } from "./XOS.shared.tsx";
10
+ import { type GateReadinessPanelProps } from "./XOS.types.ts";
11
+
12
+ /**
13
+ * A gate's criteria as a checklist with evidence, blocking flags and the action that clears each
14
+ * gap. The next-gate button enables when the last blocking criterion is met.
15
+ */
16
+ export function GateReadinessPanel({
17
+ gate,
18
+ code,
19
+ name,
20
+ nextLabel,
21
+ criteria,
22
+ onAdvance,
23
+ onCriterionAction,
24
+ }: GateReadinessPanelProps): ReactElement {
25
+ const t = useT();
26
+ const met = criteria.filter((c) => c.result === "met").length;
27
+ const blockers = criteria.filter((c) => c.blocking && c.result !== "met").length;
28
+ return (
29
+ <section aria-label={t("gate.readiness")} className={cx(cardClass, "max-w-(--layout-form)")}>
30
+ <header className={cardHeadClass}>
31
+ <span className="flex items-center gap-8">
32
+ <PhaseGlyph code={code} color="var(--color-text-secondary)" />
33
+ <strong className="font-semibold">{t("phase.gateName", { n: gate, name })}</strong>
34
+ </span>
35
+ <span className="text-text-secondary tabular-nums">
36
+ {t("gate.metCount", { met, total: criteria.length })}
37
+ </span>
38
+ </header>
39
+ <div className={cardBodyClass}>
40
+ <div
41
+ role="progressbar"
42
+ aria-label={t("gate.criteriaMet")}
43
+ aria-valuenow={met}
44
+ aria-valuemin={0}
45
+ aria-valuemax={criteria.length}
46
+ className="h-(--space-4) rounded-pill bg-bg-hover overflow-hidden"
47
+ >
48
+ <div
49
+ className="h-full rounded-pill bg-success forced-colors:bg-[Highlight]"
50
+ style={{ inlineSize: `${criteria.length ? (met / criteria.length) * 100 : 0}%` }}
51
+ />
52
+ </div>
53
+ <ul className="xos-criteria m-0 p-0 list-none">
54
+ {criteria.map((c) => (
55
+ <li
56
+ key={c.code ?? c.label}
57
+ className="flex items-center gap-8 min-h-(--space-40) border-b border-border-subtle last:border-b-0"
58
+ >
59
+ <ResultIcon result={c.result} t={t} />
60
+ {c.code ? (
61
+ <span className="font-mono text-text-12 text-text-secondary">{c.code}</span>
62
+ ) : null}
63
+ <span className="xos-criteria-label flex-1">{c.label}</span>
64
+ {c.blocking ? (
65
+ <Tag tone={c.result === "met" ? "neutral" : "danger"}>{t("gate.blocking")}</Tag>
66
+ ) : null}
67
+ {c.evidence ? (
68
+ <span className={chipClass}>
69
+ <Icon name="Paperclip" size={12} />
70
+ {c.evidence}
71
+ </span>
72
+ ) : c.result !== "met" && c.action ? (
73
+ <Button size="sm" onClick={() => onCriterionAction?.(c.code, c.label)}>
74
+ {c.action}
75
+ </Button>
76
+ ) : null}
77
+ </li>
78
+ ))}
79
+ </ul>
80
+ </div>
81
+ {/* On a narrow card the action takes its own full-width line under the count (A59-023). */}
82
+ <footer className={cx(cardFootClass, "justify-between flex-wrap")}>
83
+ <span className="text-text-secondary" aria-live="polite">
84
+ {blockers
85
+ ? t(blockers === 1 ? "gate.openOne" : "gate.openMany", { n: blockers })
86
+ : t("gate.allMet")}
87
+ </span>
88
+ <Button
89
+ variant="primary"
90
+ disabled={blockers > 0}
91
+ shortcut="⌘↵"
92
+ onClick={onAdvance}
93
+ className="max-sm:w-full"
94
+ >
95
+ {nextLabel}
96
+ </Button>
97
+ </footer>
98
+ </section>
99
+ );
100
+ }
@@ -0,0 +1,19 @@
1
+ import { type ReactElement } from "react";
2
+ import { useT } from "../lib/context.tsx";
3
+ import { chipClass, codeClass } from "../Chips/Chips.tsx";
4
+ import { type ProvenanceBadgeProps } from "./XOS.types.ts";
5
+
6
+ /** Who wrote a canon field and its provenance rank. */
7
+ export function ProvenanceBadge({ source, rank }: ProvenanceBadgeProps): ReactElement {
8
+ const t = useT();
9
+ return (
10
+ <span className={chipClass} title={t("provenance.rank", { rank })}>
11
+ <span className="text-text-secondary">{t("provenance.source")}</span>
12
+ <span>{source}</span>
13
+ <span className={codeClass}>
14
+ <span className="sr-only">{t("provenance.rank", { rank })}</span>
15
+ <span aria-hidden="true">{rank}</span>
16
+ </span>
17
+ </span>
18
+ );
19
+ }
@@ -0,0 +1,50 @@
1
+ import { type ReactElement } from "react";
2
+ import { cx } from "../lib/cx.ts";
3
+ import { useT } from "../lib/context.tsx";
4
+ import { codeClass } from "../Chips/Chips.tsx";
5
+ import { ScrollRegion } from "../Layout/Layout.tsx";
6
+ import { tableClass, tdClass, thClass } from "./XOS.shared.tsx";
7
+ import { type RadioChannelTableProps } from "./XOS.types.ts";
8
+
9
+ /** The radio plan, always sorted by zone then channel; notes wrap so it reads on a phone. */
10
+ export function RadioChannelTable({ caption, channels }: RadioChannelTableProps): ReactElement {
11
+ const t = useT();
12
+ const sorted = [...channels].sort((a, b) => a.zone - b.zone || a.channel - b.channel);
13
+ return (
14
+ <ScrollRegion label={caption ?? t("scroll.region")}>
15
+ <table className={tableClass}>
16
+ {caption ? <caption className="pb-8 text-start font-semibold">{caption}</caption> : null}
17
+ <thead>
18
+ <tr>
19
+ {["radio.zone", "radio.channel", "radio.assignment", "radio.notes"].map((k) => (
20
+ <th key={k} scope="col" className={thClass}>
21
+ {t(k)}
22
+ </th>
23
+ ))}
24
+ </tr>
25
+ </thead>
26
+ <tbody>
27
+ {sorted.map((c) => (
28
+ <tr key={`${c.zone}.${c.channel}`}>
29
+ <td className={cx(tdClass, "tabular-nums")}>{c.zone}</td>
30
+ <td className={tdClass}>
31
+ <span className={codeClass}>{c.channel}</span>
32
+ </td>
33
+ <td className={tdClass}>
34
+ <strong className="font-semibold">{c.assignment}</strong>
35
+ </td>
36
+ <td
37
+ className={cx(
38
+ tdClass,
39
+ "whitespace-normal py-8 min-w-(--ui-skeleton-inline) text-text-secondary",
40
+ )}
41
+ >
42
+ {c.notes}
43
+ </td>
44
+ </tr>
45
+ ))}
46
+ </tbody>
47
+ </table>
48
+ </ScrollRegion>
49
+ );
50
+ }
@@ -0,0 +1,64 @@
1
+ import { type ReactElement } from "react";
2
+ import { cx } from "../lib/cx.ts";
3
+ import { useT } from "../lib/context.tsx";
4
+ import { chipClass } from "../Chips/Chips.tsx";
5
+ import { ScrollRegion } from "../Layout/Layout.tsx";
6
+ import { RESULT, ResultIcon, tableClass, tdClass, thClass } from "./XOS.shared.tsx";
7
+ import { type ReconciliationTableProps, type Result } from "./XOS.types.ts";
8
+
9
+ /** A row's outcome as the props carry it: Met, Gap or Unknown. */
10
+ type RowResult = ReconciliationTableProps["rows"][number]["result"];
11
+
12
+ /** Requirements against venue capability as Met, Gap or Unknown, with counts. */
13
+ export function ReconciliationTable({ label, rows }: ReconciliationTableProps): ReactElement {
14
+ const t = useT();
15
+ const counts: Record<RowResult, number> = { Met: 0, Gap: 0, Unknown: 0 };
16
+ for (const r of rows) counts[r.result] += 1;
17
+ const lower = (r: RowResult) => r.toLowerCase() as Result;
18
+ return (
19
+ <div className="flex flex-col gap-12">
20
+ <div className="flex flex-wrap items-center gap-8">
21
+ {(Object.keys(counts) as RowResult[]).map((k) => (
22
+ <span key={k} className={chipClass}>
23
+ <ResultIcon result={lower(k)} t={t} labeled={false} />
24
+ {t(RESULT[lower(k)].key)}
25
+ <span className="tabular-nums text-text-secondary">{counts[k]}</span>
26
+ </span>
27
+ ))}
28
+ </div>
29
+ <ScrollRegion label={label ?? t("scroll.region")}>
30
+ <table className={tableClass}>
31
+ <thead>
32
+ <tr>
33
+ <th scope="col" className={thClass}>
34
+ {t("recon.requirement")}
35
+ </th>
36
+ <th scope="col" className={thClass}>
37
+ {t("recon.capability")}
38
+ </th>
39
+ <th scope="col" className={thClass}>
40
+ {t("recon.result")}
41
+ </th>
42
+ </tr>
43
+ </thead>
44
+ <tbody>
45
+ {rows.map((r, i) => (
46
+ <tr key={`${r.requirement}-${i}`} className="hover:bg-bg-hover">
47
+ <td className={tdClass}>{r.requirement}</td>
48
+ <td className={cx(tdClass, !r.capability && "text-text-secondary")}>
49
+ {r.capability ?? t("recon.notDeclared")}
50
+ </td>
51
+ <td className={tdClass}>
52
+ <span className="inline-flex items-center gap-6">
53
+ <ResultIcon result={lower(r.result)} t={t} labeled={false} />
54
+ {t(RESULT[lower(r.result)].key)}
55
+ </span>
56
+ </td>
57
+ </tr>
58
+ ))}
59
+ </tbody>
60
+ </table>
61
+ </ScrollRegion>
62
+ </div>
63
+ );
64
+ }