@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,29 @@
1
+ export {
2
+ type TemplateCollectionProps,
3
+ type TemplateRecordProps,
4
+ type TemplateSplitViewProps,
5
+ type TemplateDashboardProps,
6
+ type DashboardTile,
7
+ type DashboardSpans,
8
+ type DashboardResize,
9
+ type TemplateSettingsProps,
10
+ type TemplateWizardProps,
11
+ type TemplateGridEditorProps,
12
+ type TemplateDocumentProps,
13
+ type TemplateAuthProps,
14
+ type TemplateGatewayShellProps,
15
+ type TemplateSystemProps,
16
+ type TemplateSystemLinkProps,
17
+ } from "./Templates.types.ts";
18
+ export { TemplateCollection } from "./TemplateCollection.tsx";
19
+ export { TemplateRecord } from "./TemplateRecord.tsx";
20
+ export { TemplateSplitView } from "./TemplateSplitView.tsx";
21
+ export { TemplateDashboard, clampSpan, spansOf } from "./TemplateDashboard.tsx";
22
+ export { TemplateSettings } from "./TemplateSettings.tsx";
23
+ export { TemplateWizard } from "./TemplateWizard.tsx";
24
+ export { TemplateGridEditor } from "./TemplateGridEditor.tsx";
25
+ export { TemplateDocument } from "./TemplateDocument.tsx";
26
+ export { TemplateAuth } from "./TemplateAuth.tsx";
27
+ export { TemplateGatewayShell } from "./TemplateGatewayShell.tsx";
28
+ export { TemplateSystem } from "./TemplateSystem.tsx";
29
+ export { TemplateSystemLink } from "./TemplateSystemLink.tsx";
@@ -0,0 +1,153 @@
1
+ import type { ReactNode } from "react";
2
+
3
+ /*
4
+ * Page templates (design reference, Templates group). Each is a layout with named slots; the screens
5
+ * compose components into the slots. Every template collapses to one column on small screens, and
6
+ * the order of the source is the reading order.
7
+ */
8
+
9
+ export interface TemplateCollectionProps {
10
+ /** PageHeader: title, count, view switcher and the one primary action. */
11
+ header: ReactNode;
12
+ /** FilterBuilder or saved filters. */
13
+ filters?: ReactNode;
14
+ /** The view body: RecordList, DataTable, Board, Timeline or Calendar. */
15
+ children: ReactNode;
16
+ /** A SidePeek for the selected record. */
17
+ peek?: ReactNode;
18
+ /** BulkActionBar while records are selected. */
19
+ bulk?: ReactNode;
20
+ }
21
+
22
+ export interface TemplateRecordProps {
23
+ /** Title row: key, kind, state and actions. */
24
+ header: ReactNode;
25
+ /** Content and activity. */
26
+ children: ReactNode;
27
+ /** The 320 px property column. */
28
+ properties: ReactNode;
29
+ related?: ReactNode;
30
+ /** Names the property column for assistive technology. */
31
+ propertiesLabel?: string;
32
+ }
33
+
34
+ export interface TemplateSplitViewProps {
35
+ list: ReactNode;
36
+ detail: ReactNode;
37
+ /** List width in pixels; resizable between 240 and 480. */
38
+ listWidth?: number;
39
+ listLabel?: string;
40
+ }
41
+
42
+ /** One tile on the dashboard grid. */
43
+ export interface DashboardTile {
44
+ /** Stable id; a saved layout names tiles by it. */
45
+ id: string;
46
+ /** Names the tile for its resize handle and announcements. */
47
+ label: string;
48
+ /** Columns of the 12-column grid the tile spans by default. */
49
+ span: number;
50
+ /** The fewest columns it may shrink to; 3 by default. */
51
+ minSpan?: number;
52
+ /** StatTile, Chart or Card content. */
53
+ content: ReactNode;
54
+ }
55
+
56
+ /** Spans by tile id, as a person arranged them. */
57
+ export type DashboardSpans = Readonly<Record<string, number>>;
58
+
59
+ /**
60
+ * Resizing in grid units. Copy arrives from the app, so the library ships no strings for it; without
61
+ * this prop tiles keep their spans.
62
+ */
63
+ export interface DashboardResize {
64
+ /** The handle's name, such as "Resize Alerts". */
65
+ label: (tile: string) => string;
66
+ /** What a screen reader hears after a change, such as "Alerts, 6 of 12 columns". */
67
+ describe: (tile: string, span: number) => string;
68
+ /** Called with every tile's span once a drag ends or a key changes one. */
69
+ onChange: (spans: DashboardSpans) => void;
70
+ }
71
+
72
+ export interface TemplateDashboardProps {
73
+ /** PageHeader with the title. */
74
+ header: ReactNode;
75
+ /** The date range and scope picker, at the end of the header row. */
76
+ controls?: ReactNode;
77
+ /** Tiles on the 12-column grid, in reading order. */
78
+ tiles?: readonly DashboardTile[];
79
+ /** The person's saved spans; a tile without one keeps its default. */
80
+ spans?: DashboardSpans;
81
+ resize?: DashboardResize;
82
+ /** Names the grid for assistive technology. */
83
+ label?: string;
84
+ /** Free content on the grid; each child spans 4 columns at lg. */
85
+ children?: ReactNode;
86
+ }
87
+
88
+ export interface TemplateSettingsProps {
89
+ /** The section list. */
90
+ sections: ReactNode;
91
+ /** The form column, 640 px at most. */
92
+ children: ReactNode;
93
+ /** A sticky save bar shown while there are unsaved changes. */
94
+ saveBar?: ReactNode;
95
+ }
96
+
97
+ export interface TemplateWizardProps {
98
+ steps: string[];
99
+ current: number;
100
+ title: ReactNode;
101
+ children: ReactNode;
102
+ onBack?: () => void;
103
+ onNext?: () => void;
104
+ /** Label of the last step's button; Done by default. */
105
+ finishLabel?: string;
106
+ nextDisabled?: boolean;
107
+ }
108
+
109
+ export interface TemplateGridEditorProps {
110
+ header: ReactNode;
111
+ /** SpreadsheetGrid, BudgetGrid or AccessGridMatrix. */
112
+ children: ReactNode;
113
+ toolbar?: ReactNode;
114
+ }
115
+
116
+ export interface TemplateDocumentProps {
117
+ /** The outline, hidden below lg. */
118
+ outline: ReactNode;
119
+ children: ReactNode;
120
+ /** Required acknowledgments at the end of the document. */
121
+ acknowledgments?: ReactNode;
122
+ }
123
+
124
+ export interface TemplateAuthProps {
125
+ brand?: ReactNode;
126
+ children: ReactNode;
127
+ }
128
+
129
+ export interface TemplateGatewayShellProps {
130
+ /** TopNav on desktop. */
131
+ topNav: ReactNode;
132
+ /** Up Next and the side column, beside the feed on desktop. */
133
+ aside?: ReactNode;
134
+ children: ReactNode;
135
+ /** TabBar below md. */
136
+ tabBar?: ReactNode;
137
+ }
138
+
139
+ export interface TemplateSystemProps {
140
+ icon: string;
141
+ title: string;
142
+ sentence: string;
143
+ actionLabel: string;
144
+ onAction?: () => void;
145
+ /** A support reference such as an error id. */
146
+ reference?: string;
147
+ }
148
+
149
+ /** TemplateSystem whose action is a link, for server components (`@xos/ui/static`). */
150
+ export interface TemplateSystemLinkProps extends Omit<TemplateSystemProps, "onAction"> {
151
+ /** Where the action goes. */
152
+ href: string;
153
+ }
@@ -0,0 +1,7 @@
1
+ # Testimonial
2
+
3
+ Testimonial shows a customer's words with a required disclosure line.
4
+
5
+ `disclosure` is required and states the speaker's connection to the publisher: a customer, a partner, or someone who received anything of value. A testimonial runs only when a real customer said it and consented in writing; nothing here is invented, bought or written by staff. Until such a statement exists, the page ships without this component.
6
+
7
+ The preview uses the fictional tenant Northwind Live, as every XOS preview does, and its disclosure line says so.
@@ -0,0 +1,3 @@
1
+ # Textarea
2
+
3
+ Textarea takes multi-line text with the same label, help and error pattern as Input.
@@ -0,0 +1,5 @@
1
+ # TimePicker
2
+
3
+ TimePicker is zone-aware: the venue time zone is always shown beside the time.
4
+
5
+ - Times display in 12-hour format with AM and PM; storage is UTC.
@@ -0,0 +1,6 @@
1
+ # Timeline
2
+
3
+ Timeline is the Gantt view: bars by state, baselines underneath, dependencies, gate markers, today and the critical path.
4
+
5
+ - Dragging previews dependent shifts before release.
6
+ - Has an accessible table alternative.
@@ -0,0 +1,3 @@
1
+ # Toast
2
+
3
+ Toast confirms a completed action; destructive actions show an Undo toast for 8 seconds.
@@ -0,0 +1,3 @@
1
+ # Tooltip
2
+
3
+ Tooltip shows an icon control's label and shortcut after 500 ms hover or on focus; never interactive content.
@@ -0,0 +1,5 @@
1
+ # TopNav
2
+
3
+ TopNav is the Gateway shell's top bar on desktop: brand, the five destinations, search, help and the avatar menu.
4
+
5
+ - On an org's custom domain the brand is that org's; on the platform domain it is the platform's, through BrandMark.
@@ -0,0 +1,3 @@
1
+ # TreeView
2
+
3
+ TreeView shows the scope tree: engagement root, standing venues and shows, with keyboard expand and collapse.
@@ -0,0 +1,5 @@
1
+ # URIDChip
2
+
3
+ URIDChip pairs a plain name with its URID in JetBrains Mono, at discipline or category grain.
4
+
5
+ - Canon disciplines and categories hold .01 to .49; adopter extensions hold .50 to .99 and are scoped to their org. The preview's second chip, Northwind Line Array Kit (5000.01.50), is a Northwind Live extension under canon discipline Audio (5000.01).
@@ -0,0 +1,3 @@
1
+ # UndoToast
2
+
3
+ UndoToast replaces confirmations for reversible actions; it stays 8 seconds with a visible timer and Cmd or Ctrl+Z.
@@ -0,0 +1,6 @@
1
+ # UpNextCard
2
+
3
+ UpNextCard leads Gateway Home with the person's next shift, set time, delivery or deadline: countdown, call time, address, parking, contact and what to bring.
4
+
5
+ - Directions, Add to Calendar and Add to Wallet are one tap each.
6
+ - Every engagement detail is reachable from Home in one tap.
@@ -0,0 +1,52 @@
1
+ import { type ReactElement } from "react";
2
+ import { cx } from "../lib/cx.ts";
3
+ import { Icon } from "../Icon/Icon.tsx";
4
+ import { Avatar } from "../Avatar/Avatar.tsx";
5
+ import { chipClass } from "../Chips/Chips.tsx";
6
+ import { type ActivityFeedItemProps } from "./Views.types.ts";
7
+
8
+ /** One event or comment in a feed; reactions are glyph buttons with their counts. */
9
+ export function ActivityFeedItem({
10
+ actor,
11
+ action,
12
+ target,
13
+ time,
14
+ comment,
15
+ reactions,
16
+ onReact,
17
+ }: ActivityFeedItemProps): ReactElement {
18
+ return (
19
+ <article className="flex items-start gap-12 max-w-(--layout-peek)">
20
+ <Avatar name={actor} />
21
+ <div className="flex flex-1 flex-col gap-4 min-w-0">
22
+ <p className="m-0">
23
+ <strong className="font-semibold">{actor}</strong>{" "}
24
+ <span className="text-text-secondary">{action}</span>{" "}
25
+ {target ? <span className="font-mono text-text-12">{target}</span> : null}{" "}
26
+ <time className="text-text-secondary">{time}</time>
27
+ </p>
28
+ {comment ? (
29
+ <div className="px-12 py-8 rounded-card border border-border-subtle bg-bg-surface">
30
+ {comment}
31
+ </div>
32
+ ) : null}
33
+ {reactions ? (
34
+ <div className="flex flex-wrap gap-4">
35
+ {reactions.map((r) => (
36
+ <button
37
+ key={r.label}
38
+ type="button"
39
+ aria-label={`${r.label} ${r.count}`}
40
+ onClick={() => onReact?.(r.label)}
41
+ className={cx(chipClass, "xos-hit cursor-pointer hover:bg-bg-hover")}
42
+ >
43
+ <Icon name={r.icon} size={12} />
44
+ <span className="tabular-nums">{r.count}</span>
45
+ </button>
46
+ ))}
47
+ </div>
48
+ ) : null}
49
+ </div>
50
+ </article>
51
+ );
52
+ }
@@ -0,0 +1,229 @@
1
+ import { useRef, useState, type DragEvent, type KeyboardEvent, type ReactElement } from "react";
2
+ import { Direction } from "radix-ui";
3
+ import { cx } from "../lib/cx.ts";
4
+ import { useFormat, useT } from "../lib/context.tsx";
5
+ import { isMenuKey, useItemSelection } from "../lib/selection.ts";
6
+ import { Icon } from "../Icon/Icon.tsx";
7
+ import { buttonClass } from "../Button/Button.tsx";
8
+ import { Avatar } from "../Avatar/Avatar.tsx";
9
+ import { PropertyChip, RecordKindChip } from "../Chips/Chips.tsx";
10
+ import { StateIcon } from "../StateIcon/StateIcon.tsx";
11
+ import { ScrollRegion } from "../Layout/ScrollRegion.tsx";
12
+ import { type BoardProps, type Card } from "./Views.types.ts";
13
+
14
+ /** How the selection and menus name a card. */
15
+ const idOf = (card: Card) => card.id ?? card.key;
16
+
17
+ /**
18
+ * Records grouped into columns by state. Cards move by drag or by keyboard: Space picks a card up,
19
+ * Arrow Left and Right carry it across columns, Space drops it and Esc puts it back. With
20
+ * `selection`, cards select as rows of a list do (X and Shift+X, Cmd or Ctrl+click, Shift+click,
21
+ * Cmd or Ctrl+A, Esc), in reading order down each column. Right-click, Shift+F10 or the Context Menu
22
+ * key on a card calls `onItemContextMenu`. A card's key and title carry `data-column`, and the card
23
+ * its `data-item` id, so a page can preview them (hover cards).
24
+ */
25
+ export function Board({
26
+ addLabel,
27
+ readOnly = false,
28
+ columns,
29
+ selection,
30
+ onItemContextMenu,
31
+ onMove,
32
+ onAdd,
33
+ onOpen,
34
+ }: BoardProps): ReactElement {
35
+ const t = useT();
36
+ const fmt = useFormat();
37
+ const dir = Direction.useDirection();
38
+ const [cols, setCols] = useState(columns);
39
+ const [held, setHeld] = useState<{ key: string; origin: number; at: number } | null>(null);
40
+ const [announcement, setAnnouncement] = useState("");
41
+ const cardRefs = useRef(new Map<string, HTMLElement>());
42
+ const ids = () => cols.flatMap((col) => col.cards.map(idOf));
43
+ const select = useItemSelection(selection, ids);
44
+ const selectedCount = selection ? ids().filter(select.isSelected).length : 0;
45
+
46
+ const move = (key: string, from: number, to: number) => {
47
+ if (from === to) return;
48
+ setCols((current) => {
49
+ const card = current[from]?.cards.find((c) => c.key === key);
50
+ if (!card) return current;
51
+ return current.map((col, i) =>
52
+ i === from
53
+ ? { ...col, cards: col.cards.filter((c) => c.key !== key) }
54
+ : i === to
55
+ ? { ...col, cards: [...col.cards, card] }
56
+ : col,
57
+ );
58
+ });
59
+ requestAnimationFrame(() => cardRefs.current.get(key)?.focus());
60
+ };
61
+
62
+ const onCardKey = (e: KeyboardEvent<HTMLElement>, card: Card, colIndex: number) => {
63
+ if (held === null && e.target === e.currentTarget) {
64
+ if (onItemContextMenu && isMenuKey(e)) {
65
+ e.preventDefault();
66
+ onItemContextMenu(idOf(card), null, e.currentTarget);
67
+ return;
68
+ }
69
+ if (select.onKey(e, idOf(card))) return;
70
+ }
71
+ if (readOnly) {
72
+ if (e.key === "Enter") onOpen?.(card.key);
73
+ return;
74
+ }
75
+ const forward = dir === "rtl" ? "ArrowLeft" : "ArrowRight";
76
+ const back = dir === "rtl" ? "ArrowRight" : "ArrowLeft";
77
+ if (e.key === " ") {
78
+ e.preventDefault();
79
+ if (held === null) {
80
+ setHeld({ key: card.key, origin: colIndex, at: colIndex });
81
+ setAnnouncement(
82
+ t("board.picked", { title: card.title, column: cols[colIndex]?.label ?? "" }),
83
+ );
84
+ } else {
85
+ const from = cols[held.origin]?.state;
86
+ const to = cols[held.at]?.state;
87
+ if (from && to && held.origin !== held.at) onMove?.(held.key, from, to);
88
+ setAnnouncement(
89
+ t("board.dropped", { title: card.title, column: cols[held.at]?.label ?? "" }),
90
+ );
91
+ setHeld(null);
92
+ }
93
+ } else if (held && (e.key === forward || e.key === back)) {
94
+ e.preventDefault();
95
+ const to = Math.max(0, Math.min(cols.length - 1, held.at + (e.key === forward ? 1 : -1)));
96
+ move(held.key, held.at, to);
97
+ setHeld({ ...held, at: to });
98
+ setAnnouncement(t("board.moved", { title: card.title, column: cols[to]?.label ?? "" }));
99
+ } else if (held && e.key === "Escape") {
100
+ e.preventDefault();
101
+ move(held.key, held.at, held.origin);
102
+ setAnnouncement(
103
+ t("board.returned", { title: card.title, column: cols[held.origin]?.label ?? "" }),
104
+ );
105
+ setHeld(null);
106
+ } else if (e.key === "Enter" && !held) {
107
+ onOpen?.(card.key);
108
+ }
109
+ };
110
+
111
+ const onDrop = (e: DragEvent<HTMLElement>, to: number) => {
112
+ e.preventDefault();
113
+ const [key, fromText] = e.dataTransfer.getData("text/plain").split("|");
114
+ const from = Number(fromText);
115
+ if (!key || Number.isNaN(from)) return;
116
+ move(key, from, to);
117
+ const fromState = cols[from]?.state;
118
+ const toState = cols[to]?.state;
119
+ if (fromState && toState && from !== to) onMove?.(key, fromState, toState);
120
+ };
121
+
122
+ // Columns that do not fit scroll sideways in a region whose cut-off edge fades (A59-012).
123
+ return (
124
+ <ScrollRegion label={t("scroll.region")}>
125
+ <div className="flex items-start gap-12 w-max min-w-full">
126
+ {cols.map((col, ci) => (
127
+ <section
128
+ key={col.state}
129
+ aria-label={col.label}
130
+ onDragOver={readOnly ? undefined : (e) => e.preventDefault()}
131
+ onDrop={readOnly ? undefined : (e) => onDrop(e, ci)}
132
+ className="flex flex-none flex-col gap-8 w-(--ui-board-col) p-8 rounded-card bg-bg-surface"
133
+ >
134
+ <header className="flex items-center gap-6 p-4">
135
+ <StateIcon state={col.state} />
136
+ <h2 className="m-0 text-text-13 font-semibold">{col.label}</h2>
137
+ <span className="text-text-secondary tabular-nums">{col.cards.length}</span>
138
+ </header>
139
+ {col.cards.map((card) => {
140
+ const selected = select.isSelected(idOf(card));
141
+ return (
142
+ <div
143
+ key={card.key}
144
+ ref={(el) => {
145
+ if (el) cardRefs.current.set(card.key, el);
146
+ else cardRefs.current.delete(card.key);
147
+ }}
148
+ role="button"
149
+ tabIndex={0}
150
+ aria-pressed={held?.key === card.key ? true : undefined}
151
+ data-item={idOf(card)}
152
+ data-selected={selected ? "" : undefined}
153
+ draggable={!readOnly}
154
+ onDragStart={(e) => e.dataTransfer.setData("text/plain", `${card.key}|${ci}`)}
155
+ onKeyDown={(e) => onCardKey(e, card, ci)}
156
+ onDoubleClick={() => onOpen?.(card.key)}
157
+ {...(selection
158
+ ? {
159
+ onClick: (e) => select.onClick(e, idOf(card)),
160
+ onMouseDown: (e) => {
161
+ // Shift+click selects a range, not the text between.
162
+ if (e.shiftKey) e.preventDefault();
163
+ },
164
+ }
165
+ : {})}
166
+ {...(onItemContextMenu
167
+ ? {
168
+ onContextMenu: (e) => {
169
+ e.preventDefault();
170
+ onItemContextMenu(
171
+ idOf(card),
172
+ { x: e.clientX, y: e.clientY },
173
+ e.currentTarget,
174
+ );
175
+ },
176
+ }
177
+ : {})}
178
+ className={cx(
179
+ "flex flex-col gap-8 p-12 rounded-card border border-border-subtle bg-bg-raised",
180
+ "hover:border-border-strong aria-pressed:border-accent aria-pressed:ring-(length:--stroke-width-focus) aria-pressed:ring-accent",
181
+ "data-selected:border-accent data-selected:bg-bg-hover",
182
+ readOnly ? "cursor-pointer" : "cursor-grab",
183
+ "forced-colors:border-[CanvasText]",
184
+ )}
185
+ >
186
+ <div className="flex items-center justify-between gap-6">
187
+ <span data-column="key" className="font-mono text-text-12 text-text-secondary">
188
+ {card.key}
189
+ </span>
190
+ {card.owner ? <Avatar name={card.owner} /> : null}
191
+ </div>
192
+ <span data-column="title">{card.title}</span>
193
+ {selected ? <span className="sr-only">{t("bulk.itemSelected")}</span> : null}
194
+ {card.meta ? (
195
+ <span className="text-text-12 text-text-secondary">{card.meta}</span>
196
+ ) : null}
197
+ {card.kind || card.due ? (
198
+ <div className="flex flex-wrap items-center gap-4">
199
+ {card.kind ? <RecordKindChip kind={card.kind} /> : null}
200
+ {card.due ? <PropertyChip icon="Calendar" value={card.due} /> : null}
201
+ </div>
202
+ ) : null}
203
+ </div>
204
+ );
205
+ })}
206
+ {readOnly ? null : (
207
+ <button
208
+ type="button"
209
+ onClick={() => onAdd?.(col.state)}
210
+ className={cx(buttonClass("ghost"), "justify-start")}
211
+ >
212
+ <Icon name="Plus" size={14} />
213
+ {addLabel ?? t("board.add")}
214
+ </button>
215
+ )}
216
+ </section>
217
+ ))}
218
+ </div>
219
+ <span aria-live="assertive" className="sr-only">
220
+ {announcement}
221
+ </span>
222
+ {selection ? (
223
+ <span role="status" className="sr-only">
224
+ {selectedCount > 0 ? t("bulk.selected", { n: fmt.number(selectedCount) }) : ""}
225
+ </span>
226
+ ) : null}
227
+ </ScrollRegion>
228
+ );
229
+ }
@@ -0,0 +1,76 @@
1
+ import { type ReactElement } from "react";
2
+ import { Toolbar as RToolbar } from "radix-ui";
3
+ import { cx } from "../lib/cx.ts";
4
+ import { useFormat, useT } from "../lib/context.tsx";
5
+ import { Icon } from "../Icon/Icon.tsx";
6
+ import { buttonClass, iconButtonClass } from "../Button/Button.tsx";
7
+ import { Keys } from "../Kbd/Kbd.tsx";
8
+ import { type BulkActionBarProps } from "./Views.types.ts";
9
+
10
+ /**
11
+ * Appears with a selection: the count and at most five actions every selected item allows. A
12
+ * toolbar: arrow keys move between actions, Esc clears the selection.
13
+ */
14
+ export function BulkActionBar({
15
+ count,
16
+ actions,
17
+ onClear,
18
+ onMore,
19
+ announce = true,
20
+ }: BulkActionBarProps): ReactElement {
21
+ const t = useT();
22
+ const fmt = useFormat();
23
+ return (
24
+ <RToolbar.Root
25
+ aria-label={t("bulk.label")}
26
+ onKeyDown={(e) => {
27
+ if (e.key === "Escape" && onClear) {
28
+ e.preventDefault();
29
+ onClear();
30
+ }
31
+ }}
32
+ className={cx(
33
+ "xos-anim-fade inline-flex flex-wrap items-center gap-4 max-w-full py-4 ps-12 pe-4",
34
+ "rounded-card bg-bg-raised shadow-menu print:hidden forced-colors:border",
35
+ )}
36
+ >
37
+ <span className="tabular-nums" {...(announce ? { "aria-live": "polite" as const } : {})}>
38
+ {t("bulk.selected", { n: fmt.number(count) })}
39
+ </span>
40
+ <RToolbar.Separator className="w-(--stroke-width-hairline) h-(--space-16) mx-4 bg-border-strong" />
41
+ {actions.slice(0, 5).map((action) => (
42
+ <RToolbar.Button
43
+ key={action.label}
44
+ className={buttonClass("ghost", "sm")}
45
+ onClick={action.onSelect}
46
+ >
47
+ {action.icon ? <Icon name={action.icon} size={14} /> : null}
48
+ {action.label}
49
+ {action.shortcut ? (
50
+ <span className="ms-4 inline-flex">
51
+ <Keys keys={action.shortcut} />
52
+ </span>
53
+ ) : null}
54
+ </RToolbar.Button>
55
+ ))}
56
+ {onMore ? (
57
+ <RToolbar.Button
58
+ className={iconButtonClass()}
59
+ aria-label={t("menu.more")}
60
+ title={t("menu.more")}
61
+ onClick={onMore}
62
+ >
63
+ <Icon name="Ellipsis" />
64
+ </RToolbar.Button>
65
+ ) : null}
66
+ <RToolbar.Button
67
+ className={iconButtonClass()}
68
+ aria-label={t("bulk.clear")}
69
+ title={t("tooltip.withShortcut", { label: t("bulk.clear"), shortcut: t("key.esc") })}
70
+ onClick={onClear}
71
+ >
72
+ <Icon name="X" />
73
+ </RToolbar.Button>
74
+ </RToolbar.Root>
75
+ );
76
+ }