@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,73 @@
1
+ import { type ReactElement } from "react";
2
+ import { cx } from "../lib/cx.ts";
3
+ import { useFormat, useT } from "../lib/context.tsx";
4
+ import { Icon } from "../Icon/Icon.tsx";
5
+ import { Button, IconButton } from "../Button/Button.tsx";
6
+ import { BrandMark } from "../BrandMark/BrandMark.tsx";
7
+ import { panelClass } from "./Gateway.shared.tsx";
8
+ import { type OpportunityCardProps } from "./Gateway.types.ts";
9
+
10
+ /** Role, pay, date and place, then a requirements check that shows exactly what is missing. No posted pay reads Rate on Request. */
11
+ export function OpportunityCard({
12
+ org,
13
+ verified,
14
+ role,
15
+ pay,
16
+ date,
17
+ place,
18
+ requirements,
19
+ missingAction,
20
+ deadline,
21
+ saved,
22
+ onApply,
23
+ onSave,
24
+ }: OpportunityCardProps): ReactElement {
25
+ const t = useT();
26
+ const fmt = useFormat();
27
+ const missing = requirements.missing.length > 0;
28
+ return (
29
+ <article className={cx(panelClass, "gap-8 w-(--ui-gateway-aside) p-16 text-text-14")}>
30
+ <header className="flex items-center justify-between gap-8">
31
+ <span className="flex items-center gap-6 min-w-0">
32
+ <BrandMark name={org} size="sm" iconOnly />
33
+ <span className="truncate">{org}</span>
34
+ {verified ? (
35
+ <span className="text-state-scheduled">
36
+ <Icon name="BadgeCheck" size={14} label={t("org.verified")} />
37
+ </span>
38
+ ) : null}
39
+ </span>
40
+ <IconButton
41
+ icon="Bookmark"
42
+ label={saved ? t("action.saved") : t("action.save")}
43
+ aria-pressed={saved ?? false}
44
+ onClick={onSave}
45
+ />
46
+ </header>
47
+ <h3 className="m-0 text-heading-16 font-semibold">{role}</h3>
48
+ <div className="flex flex-wrap gap-x-12 gap-y-4 text-text-secondary">
49
+ <strong className="text-text-primary tabular-nums">
50
+ {pay ?? t("money.rateOnRequest")}
51
+ </strong>
52
+ <span>{date}</span>
53
+ <span>{place}</span>
54
+ </div>
55
+ <div className="flex items-center gap-6 px-8 py-6 rounded-control bg-bg-surface text-text-13">
56
+ <span className={missing ? "text-warning" : "text-success"}>
57
+ <Icon name={missing ? "CircleAlert" : "CircleCheck"} size={14} />
58
+ </span>
59
+ <span>
60
+ {missing
61
+ ? t("opp.missing", { list: fmt.list(requirements.missing) })
62
+ : t("opp.qualified")}
63
+ </span>
64
+ </div>
65
+ <footer className="flex items-center justify-between gap-8">
66
+ <span className="text-text-secondary">{deadline}</span>
67
+ <Button variant="primary" onClick={onApply}>
68
+ {missingAction && missing ? missingAction : t("opp.apply")}
69
+ </Button>
70
+ </footer>
71
+ </article>
72
+ );
73
+ }
@@ -0,0 +1,64 @@
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 { SegmentedControl } from "../Navigation/Navigation.tsx";
6
+ import { type OpportunityFiltersProps } from "./Gateway.types.ts";
7
+
8
+ /** Search, filter chips and the cards or map view. */
9
+ export function OpportunityFilters({
10
+ placeholder: hint,
11
+ chips,
12
+ active = [],
13
+ onSearch,
14
+ onChipsChange,
15
+ onViewChange,
16
+ }: OpportunityFiltersProps): ReactElement {
17
+ const t = useT();
18
+ const [on, setOn] = useState(active);
19
+ return (
20
+ <div role="group" aria-label={t("filter.label")} className="flex flex-wrap items-center gap-8">
21
+ <label className="flex items-center gap-8 w-(--ui-skeleton-inline) min-w-0 grow h-row-default ps-12 pe-8 rounded-control border border-border-control bg-bg-surface focus-within:outline-solid focus-within:outline-stroke-focus focus-within:outline-focus-ring">
22
+ <Icon name="Search" color="var(--color-text-secondary)" />
23
+ <input
24
+ aria-label={t("opp.search")}
25
+ placeholder={hint}
26
+ onChange={(e) => onSearch?.(e.target.value)}
27
+ className="flex-1 min-w-0 bg-transparent border-0 outline-none text-text-primary placeholder:text-text-tertiary pointer-coarse:min-h-target-coarse"
28
+ />
29
+ </label>
30
+ {chips.map((chip) => {
31
+ const pressed = on.includes(chip);
32
+ return (
33
+ <button
34
+ key={chip}
35
+ type="button"
36
+ aria-pressed={pressed}
37
+ onClick={() => {
38
+ const next = pressed ? on.filter((c) => c !== chip) : [...on, chip];
39
+ setOn(next);
40
+ onChipsChange?.(next);
41
+ }}
42
+ className={cx(
43
+ "inline-flex items-center gap-4 h-control-md px-12 rounded-pill border border-border-control bg-transparent cursor-pointer",
44
+ "font-medium text-text-13 text-text-secondary pointer-coarse:min-h-target-coarse",
45
+ "aria-pressed:bg-text-primary aria-pressed:text-bg-canvas aria-pressed:border-text-primary",
46
+ )}
47
+ >
48
+ {pressed ? <Icon name="Check" size={12} /> : null}
49
+ {chip}
50
+ </button>
51
+ );
52
+ })}
53
+ <SegmentedControl
54
+ label={t("view.label")}
55
+ value="cards"
56
+ onChange={(v) => onViewChange?.(v === "map" ? "map" : "cards")}
57
+ options={[
58
+ { value: "cards", label: t("view.cards"), icon: "LayoutGrid" },
59
+ { value: "map", label: t("view.map"), icon: "Map" },
60
+ ]}
61
+ />
62
+ </div>
63
+ );
64
+ }
@@ -0,0 +1,71 @@
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 { Money } from "../Forms/Forms.tsx";
6
+ import { type PaymentTrackerProps } from "./Gateway.types.ts";
7
+
8
+ /** A payment followed like a package: Submitted, Approved, Scheduled, Paid. */
9
+ export function PaymentTracker({
10
+ invoiceKey,
11
+ title,
12
+ amount,
13
+ current,
14
+ dates,
15
+ expected,
16
+ }: PaymentTrackerProps): ReactElement {
17
+ const t = useT();
18
+ const steps = [t("pay.submitted"), t("pay.approved"), t("pay.scheduled"), t("pay.paid")];
19
+ return (
20
+ <section
21
+ aria-label={t("pay.label", { key: invoiceKey })}
22
+ className="flex flex-col gap-16 w-(--ui-alert) max-w-full p-16 box-border rounded-card border border-border-subtle bg-bg-raised"
23
+ >
24
+ <div className="flex items-start justify-between gap-8">
25
+ <div className="flex flex-col">
26
+ <span className="font-mono text-text-12 text-text-secondary">{invoiceKey}</span>
27
+ <strong className="font-semibold">{title}</strong>
28
+ </div>
29
+ <strong className="text-heading-20 font-semibold tabular-nums">
30
+ <Money amount={amount} />
31
+ </strong>
32
+ </div>
33
+ <ol className="grid grid-cols-4 gap-8 m-0 p-0 list-none">
34
+ {steps.map((s, i) => {
35
+ const state = i < current ? "done" : i === current ? "current" : "todo";
36
+ const note =
37
+ dates[i] ??
38
+ (state === "todo" && expected && i === current + 1
39
+ ? t("pay.expected", { date: expected })
40
+ : "");
41
+ return (
42
+ <li
43
+ key={s}
44
+ aria-current={state === "current" ? "step" : undefined}
45
+ className={cx(
46
+ "flex flex-col gap-6 pt-4 text-text-12 border-t-stroke-accent",
47
+ state === "done" && "border-t-success",
48
+ state === "current" && "border-t-accent font-medium",
49
+ state === "todo" && "border-t-border-subtle text-text-secondary",
50
+ )}
51
+ >
52
+ <span
53
+ className={cx(
54
+ "inline-grid place-items-center size-icon-20 rounded-full text-text-11 font-semibold tabular-nums",
55
+ state === "todo" &&
56
+ "ring-(length:--stroke-width-hairline) ring-inset ring-border-strong",
57
+ state === "current" && "bg-accent text-accent-text-on",
58
+ state === "done" && "bg-bg-hover text-success",
59
+ )}
60
+ >
61
+ {state === "done" ? <Icon name="Check" size={12} /> : i + 1}
62
+ </span>
63
+ <span>{s}</span>
64
+ <span className="text-text-secondary tabular-nums">{note}</span>
65
+ </li>
66
+ );
67
+ })}
68
+ </ol>
69
+ </section>
70
+ );
71
+ }
@@ -0,0 +1,62 @@
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 { Button } from "../Button/Button.tsx";
6
+ import { chipClass } from "../Chips/Chips.tsx";
7
+ import { Card } from "../Surface/Surface.tsx";
8
+ import { Input, Select } from "../Forms/Forms.tsx";
9
+ import { type PayoutDetailsFormProps } from "./Gateway.types.ts";
10
+
11
+ /** Bank details in a secure form; after saving only the last four digits are shown. */
12
+ export function PayoutDetailsForm({ rail, onFile, onSave }: PayoutDetailsFormProps): ReactElement {
13
+ const t = useT();
14
+ const [routing, setRouting] = useState("");
15
+ const [account, setAccount] = useState("");
16
+ const [type, setType] = useState("checking");
17
+ return (
18
+ <Card
19
+ title={t("payout.title")}
20
+ meta={rail}
21
+ footer={
22
+ <Button variant="primary" icon="Lock" onClick={() => onSave?.({ routing, account, type })}>
23
+ {t("payout.save")}
24
+ </Button>
25
+ }
26
+ >
27
+ {onFile ? (
28
+ <div className={cx(chipClass, "h-control-lg self-start")}>
29
+ <Icon name="Landmark" size={14} />
30
+ <span>{onFile.bank}</span>
31
+ <span className="font-mono">{t("payout.masked", { last4: onFile.last4 })}</span>
32
+ </div>
33
+ ) : null}
34
+ <Input
35
+ label={t("payout.routing")}
36
+ inputMode="numeric"
37
+ autoComplete="off"
38
+ placeholder={t("payout.routingHint")}
39
+ value={routing}
40
+ onChange={(e) => setRouting(e.target.value)}
41
+ />
42
+ <Input
43
+ label={t("payout.account")}
44
+ inputMode="numeric"
45
+ autoComplete="off"
46
+ type="password"
47
+ help={t("payout.accountHelp")}
48
+ value={account}
49
+ onChange={(e) => setAccount(e.target.value)}
50
+ />
51
+ <Select
52
+ label={t("payout.type")}
53
+ value="checking"
54
+ options={[
55
+ { value: "checking", label: t("payout.checking") },
56
+ { value: "savings", label: t("payout.savings") },
57
+ ]}
58
+ onChange={(e) => setType(e.target.value)}
59
+ />
60
+ </Card>
61
+ );
62
+ }
@@ -0,0 +1,45 @@
1
+ import { type ReactElement } from "react";
2
+ import { useT } from "../lib/context.tsx";
3
+ import { Card } from "../Surface/Surface.tsx";
4
+ import { SegmentedControl } from "../Navigation/Navigation.tsx";
5
+ import { type ProfileEditorProps } from "./Gateway.types.ts";
6
+ import { ProgressBar } from "./ProgressBar.tsx";
7
+
8
+ /** Each field's visibility (Private, On Apply, Public) with a strength meter naming the next step. */
9
+ export function ProfileEditor({
10
+ strength,
11
+ nextStep,
12
+ fields,
13
+ onVisibilityChange,
14
+ }: ProfileEditorProps): ReactElement {
15
+ const t = useT();
16
+ const options = [
17
+ { value: "private", label: t("visibility.private") },
18
+ { value: "application", label: t("visibility.application") },
19
+ { value: "public", label: t("visibility.public") },
20
+ ];
21
+ return (
22
+ <Card title={t("profile.title")} meta={t("profile.complete", { n: strength })}>
23
+ <ProgressBar label={nextStep} value={strength} />
24
+ {fields.map((f) => (
25
+ <div
26
+ key={f.label}
27
+ className="flex flex-wrap items-center gap-12 py-8 border-b border-border-subtle last:border-b-0"
28
+ >
29
+ <div className="flex flex-1 flex-col min-w-0">
30
+ <span className="text-text-12 font-medium text-text-secondary">{f.label}</span>
31
+ <span>{f.value}</span>
32
+ </div>
33
+ <SegmentedControl
34
+ label={f.label}
35
+ value={f.visibility}
36
+ options={options}
37
+ onChange={(v) =>
38
+ onVisibilityChange?.(f.label, v as "private" | "application" | "public")
39
+ }
40
+ />
41
+ </div>
42
+ ))}
43
+ </Card>
44
+ );
45
+ }
@@ -0,0 +1,30 @@
1
+ import { type ReactElement } from "react";
2
+ import { useT } from "../lib/context.tsx";
3
+ import { type ProgressBarProps } from "./Gateway.types.ts";
4
+
5
+ /** Determinate progress with its percentage. */
6
+ export function ProgressBar({ label, value }: ProgressBarProps): ReactElement {
7
+ const t = useT();
8
+ const pct = Math.max(0, Math.min(100, Math.round(value)));
9
+ return (
10
+ <div className="flex flex-col gap-6 w-(--ui-field) max-w-full">
11
+ <div className="flex justify-between text-text-12 text-text-secondary">
12
+ <span>{label}</span>
13
+ <span className="tabular-nums">{t("progress.percent", { n: pct })}</span>
14
+ </div>
15
+ <div
16
+ role="progressbar"
17
+ aria-label={label}
18
+ aria-valuenow={pct}
19
+ aria-valuemin={0}
20
+ aria-valuemax={100}
21
+ className="h-(--space-4) rounded-pill bg-bg-hover overflow-hidden"
22
+ >
23
+ <div
24
+ className="h-full rounded-pill bg-accent forced-colors:bg-[Highlight]"
25
+ style={{ inlineSize: `${pct}%` }}
26
+ />
27
+ </div>
28
+ </div>
29
+ );
30
+ }
@@ -0,0 +1,83 @@
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 { Button } from "../Button/Button.tsx";
6
+ import { Textarea } from "../Forms/Forms.tsx";
7
+ import { Dialog } from "../Overlays/Overlays.tsx";
8
+ import { type RatingDialogProps } from "./Gateway.types.ts";
9
+
10
+ /** A two-sided rating after close-out; stars are a radio group, both ratings release together. */
11
+ export function RatingDialog({
12
+ counterpart,
13
+ value = 0,
14
+ onSubmit,
15
+ onLater,
16
+ open,
17
+ onOpenChange,
18
+ }: RatingDialogProps): ReactElement {
19
+ const t = useT();
20
+ const [rating, setRating] = useState(value);
21
+ const [comment, setComment] = useState("");
22
+ return (
23
+ <Dialog
24
+ title={t("rating.title", { name: counterpart })}
25
+ {...(open === undefined ? {} : { open })}
26
+ {...(onOpenChange ? { onOpenChange } : {})}
27
+ actions={
28
+ <>
29
+ <Button variant="ghost" onClick={onLater}>
30
+ {t("action.later")}
31
+ </Button>
32
+ <Button variant="primary" disabled={!rating} onClick={() => onSubmit?.(rating, comment)}>
33
+ {t("rating.submit")}
34
+ </Button>
35
+ </>
36
+ }
37
+ >
38
+ <div className="flex flex-col gap-12">
39
+ <div role="radiogroup" aria-label={t("rating.label")} className="flex gap-4">
40
+ {[1, 2, 3, 4, 5].map((n) => (
41
+ <button
42
+ key={n}
43
+ type="button"
44
+ role="radio"
45
+ aria-checked={rating === n}
46
+ tabIndex={rating === n || (rating === 0 && n === 1) ? 0 : -1}
47
+ aria-label={t(n === 1 ? "rating.star" : "rating.stars", { n })}
48
+ onClick={() => setRating(n)}
49
+ onKeyDown={(e) => {
50
+ const next =
51
+ e.key === "ArrowRight" || e.key === "ArrowUp"
52
+ ? Math.min(5, n + 1)
53
+ : e.key === "ArrowLeft" || e.key === "ArrowDown"
54
+ ? Math.max(1, n - 1)
55
+ : null;
56
+ if (next === null) return;
57
+ e.preventDefault();
58
+ setRating(next);
59
+ (
60
+ e.currentTarget.parentElement?.children[next - 1] as HTMLElement | undefined
61
+ )?.focus();
62
+ }}
63
+ className={cx(
64
+ "grid place-items-center size-(--density-target-coarse) rounded-control border-0 bg-transparent cursor-pointer text-text-tertiary",
65
+ n <= rating && "text-warning [&_svg]:fill-current",
66
+ )}
67
+ >
68
+ <Icon name="Star" size={24} />
69
+ </button>
70
+ ))}
71
+ </div>
72
+ <Textarea
73
+ label={t("rating.comment")}
74
+ width="100%"
75
+ rows={2}
76
+ value={comment}
77
+ onChange={(e) => setComment(e.target.value)}
78
+ />
79
+ <span className="text-text-12 text-text-secondary">{t("rating.release")}</span>
80
+ </div>
81
+ </Dialog>
82
+ );
83
+ }
@@ -0,0 +1,76 @@
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 { BrandMark } from "../BrandMark/BrandMark.tsx";
7
+ import { PropertyList } from "../Overlays/Overlays.tsx";
8
+ import { panelClass } from "./Gateway.shared.tsx";
9
+ import { type UpNextCardProps } from "./Gateway.types.ts";
10
+
11
+ /** Leads Gateway Home with the next shift: countdown, call time, address and what to bring. */
12
+ export function UpNextCard({
13
+ org,
14
+ countdown,
15
+ title,
16
+ when,
17
+ callTime,
18
+ address,
19
+ parking,
20
+ contact,
21
+ bring,
22
+ onDirections,
23
+ onCalendar,
24
+ onWallet,
25
+ }: UpNextCardProps): ReactElement {
26
+ const t = useT();
27
+ const properties = [
28
+ { label: t("upnext.when"), value: <span className="tabular-nums">{when}</span> },
29
+ { label: t("upnext.call"), value: <span className="tabular-nums">{callTime}</span> },
30
+ { label: t("upnext.where"), value: address },
31
+ ...(parking ? [{ label: t("upnext.parking"), value: parking }] : []),
32
+ ...(contact ? [{ label: t("upnext.contact"), value: contact }] : []),
33
+ ];
34
+ return (
35
+ <article
36
+ aria-label={t("upnext.label")}
37
+ className={cx(panelClass, "gap-12 w-(--ui-gateway-aside) p-16 text-text-14")}
38
+ >
39
+ <header className="flex items-center justify-between gap-8">
40
+ <span className="flex items-center gap-6">
41
+ <BrandMark name={org} size="sm" iconOnly />
42
+ <span className="text-text-12 font-medium text-text-secondary">{t("upnext.label")}</span>
43
+ </span>
44
+ <span className="font-semibold text-accent-text tabular-nums">{countdown}</span>
45
+ </header>
46
+ <h3 className="m-0 text-heading-20 font-semibold">{title}</h3>
47
+ <PropertyList items={properties} />
48
+ {bring && bring.length ? (
49
+ <div className="flex flex-col gap-4">
50
+ <span className="text-text-12 font-medium text-text-secondary">{t("upnext.bring")}</span>
51
+ <ul className="flex flex-col gap-4 m-0 p-0 list-none">
52
+ {bring.map((b) => (
53
+ <li key={b} className="flex items-center gap-6">
54
+ <span className="text-success">
55
+ <Icon name="Check" size={14} />
56
+ </span>
57
+ {b}
58
+ </li>
59
+ ))}
60
+ </ul>
61
+ </div>
62
+ ) : null}
63
+ <footer className="flex flex-wrap items-center gap-8">
64
+ <Button variant="primary" icon="Navigation" onClick={onDirections}>
65
+ {t("upnext.directions")}
66
+ </Button>
67
+ <Button icon="CalendarPlus" onClick={onCalendar}>
68
+ {t("upnext.calendar")}
69
+ </Button>
70
+ <Button icon="Wallet" onClick={onWallet}>
71
+ {t("badge.wallet")}
72
+ </Button>
73
+ </footer>
74
+ </article>
75
+ );
76
+ }
@@ -0,0 +1,66 @@
1
+ import type { ReactElement } from "react";
2
+ import {
3
+ departmentCodes,
4
+ departmentIcon,
5
+ phaseCodes,
6
+ phaseIcon,
7
+ recordKindIcon,
8
+ recordKinds,
9
+ } from "@xos/icons/glyphs";
10
+ import type {
11
+ DepartmentCode,
12
+ DepartmentGlyphProps as ReferenceDepartmentGlyphProps,
13
+ PhaseCode,
14
+ PhaseGlyphProps as ReferencePhaseGlyphProps,
15
+ RecordKind,
16
+ RecordKindGlyphProps as ReferenceRecordKindGlyphProps,
17
+ } from "../types/reference";
18
+ import { Icon } from "../Icon/Icon.tsx";
19
+
20
+ export type DepartmentGlyphProps = ReferenceDepartmentGlyphProps;
21
+ export type PhaseGlyphProps = ReferencePhaseGlyphProps;
22
+ export type RecordKindGlyphProps = ReferenceRecordKindGlyphProps;
23
+
24
+ /** The XOS glyph map (canon code to Lucide name), from @xos/icons so the assignment lives in one place. */
25
+ export const glyphs: {
26
+ departments: Record<DepartmentCode, string>;
27
+ phases: Record<PhaseCode, string>;
28
+ recordKinds: Record<RecordKind, string>;
29
+ } = {
30
+ departments: Object.fromEntries(departmentCodes.map((c) => [c, departmentIcon(c)])) as Record<
31
+ DepartmentCode,
32
+ string
33
+ >,
34
+ phases: Object.fromEntries(phaseCodes.map((c) => [c, phaseIcon(c)])) as Record<PhaseCode, string>,
35
+ recordKinds: Object.fromEntries(recordKinds.map((k) => [k, recordKindIcon(k)])) as Record<
36
+ RecordKind,
37
+ string
38
+ >,
39
+ };
40
+
41
+ function glyphProps(
42
+ size: number | undefined,
43
+ label: string | undefined,
44
+ color: string | undefined,
45
+ ) {
46
+ return {
47
+ ...(size === undefined ? {} : { size }),
48
+ ...(label === undefined ? {} : { label }),
49
+ ...(color === undefined ? {} : { color }),
50
+ };
51
+ }
52
+
53
+ /** Department glyph (`4000` Environment is Tent). Sits beside the plain name; never alone. */
54
+ export function DepartmentGlyph({ code, size, label, color }: DepartmentGlyphProps): ReactElement {
55
+ return <Icon name={glyphs.departments[code] ?? "Circle"} {...glyphProps(size, label, color)} />;
56
+ }
57
+
58
+ /** Phase glyph (`BLD` Build is Hammer). */
59
+ export function PhaseGlyph({ code, size, label, color }: PhaseGlyphProps): ReactElement {
60
+ return <Icon name={glyphs.phases[code] ?? "Circle"} {...glyphProps(size, label, color)} />;
61
+ }
62
+
63
+ /** Record kind glyph (`Task` is SquareCheck). */
64
+ export function RecordKindGlyph({ kind, size, label, color }: RecordKindGlyphProps): ReactElement {
65
+ return <Icon name={glyphs.recordKinds[kind] ?? "Circle"} {...glyphProps(size, label, color)} />;
66
+ }
@@ -0,0 +1,63 @@
1
+ import { type ReactElement } from "react";
2
+ import type { GridColumn } from "../types/reference";
3
+ import { useT } from "../lib/context.tsx";
4
+ import { InlineAlert } from "../Feedback/Feedback.tsx";
5
+ import { type BidSheetProps } from "./Grids.types.ts";
6
+ import { SpreadsheetGrid } from "./SpreadsheetGrid.tsx";
7
+
8
+ /** A sealed line-item bid: unit prices are the only editable cells; extended amounts and the total are derived and stay Unpriced while any line is blank. */
9
+ export function BidSheet({ deadline, lines, onChange }: BidSheetProps): ReactElement {
10
+ const t = useT();
11
+ const columns: GridColumn[] = [
12
+ { key: "line", label: t("bid.line"), type: "code", width: 64 },
13
+ { key: "item", label: t("bid.item") },
14
+ { key: "unit", label: t("bid.unit"), width: 72 },
15
+ { key: "qty", label: t("bid.qty"), type: "number", width: 64 },
16
+ { key: "price", label: t("bid.unitPrice"), type: "money", editable: true },
17
+ {
18
+ key: "ext",
19
+ label: t("bid.extended"),
20
+ type: "money",
21
+ total: true,
22
+ derive: (row) =>
23
+ typeof row["qty"] === "number" && typeof row["price"] === "number"
24
+ ? row["qty"] * row["price"]
25
+ : null,
26
+ },
27
+ ];
28
+ return (
29
+ <div className="flex flex-col gap-12">
30
+ <InlineAlert tone="info" title={t("bid.sealed")}>
31
+ {t("bid.sealedBody", { deadline })}
32
+ </InlineAlert>
33
+ <SpreadsheetGrid
34
+ label={t("bid.lines")}
35
+ columns={columns}
36
+ rows={lines.map((l) => ({
37
+ line: l.line,
38
+ item: l.item,
39
+ unit: l.unit,
40
+ qty: l.qty,
41
+ price: l.price,
42
+ ext: l.ext,
43
+ }))}
44
+ totalsLabel={t("bid.total")}
45
+ onChange={(rows) =>
46
+ onChange?.(
47
+ rows.map((r) => ({
48
+ line: String(r["line"] ?? ""),
49
+ item: String(r["item"] ?? ""),
50
+ unit: String(r["unit"] ?? ""),
51
+ qty: Number(r["qty"] ?? 0),
52
+ price: typeof r["price"] === "number" ? r["price"] : null,
53
+ ext:
54
+ typeof r["qty"] === "number" && typeof r["price"] === "number"
55
+ ? r["qty"] * r["price"]
56
+ : null,
57
+ })),
58
+ )
59
+ }
60
+ />
61
+ </div>
62
+ );
63
+ }