@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.
- package/LICENSE +21 -0
- package/README.md +32 -2
- package/package.json +76 -4
- package/scripts/generate-stories.mjs +85 -0
- package/src/AIDisclosureBadge/README.md +7 -0
- package/src/AccessGridMatrix/README.md +3 -0
- package/src/Accordion/README.md +7 -0
- package/src/ActivityFeedItem/README.md +3 -0
- package/src/AgencySlate/README.md +3 -0
- package/src/AppShell/README.md +5 -0
- package/src/ApplicationForm/README.md +3 -0
- package/src/AssertionRankBadge/README.md +5 -0
- package/src/AvailabilityCalendar/README.md +3 -0
- package/src/Avatar/Avatar.tsx +56 -0
- package/src/Avatar/README.md +3 -0
- package/src/Avatar/avatar-class.ts +19 -0
- package/src/AvatarStack/README.md +3 -0
- package/src/Badge/README.md +3 -0
- package/src/Banner/README.md +3 -0
- package/src/BidSheet/README.md +3 -0
- package/src/Board/README.md +6 -0
- package/src/BrandMark/BrandMark.tsx +95 -0
- package/src/BrandMark/README.md +7 -0
- package/src/BrandSlot/README.md +6 -0
- package/src/Breadcrumbs/README.md +3 -0
- package/src/BudgetGrid/README.md +10 -0
- package/src/BulkActionBar/README.md +3 -0
- package/src/Button/Button.tsx +100 -0
- package/src/Button/README.md +10 -0
- package/src/Button/button-class.ts +54 -0
- package/src/ButtonLink/README.md +7 -0
- package/src/Calendar/README.md +3 -0
- package/src/Card/README.md +3 -0
- package/src/Chart/README.md +9 -0
- package/src/Charts/Calendar.tsx +228 -0
- package/src/Charts/Chart.tsx +547 -0
- package/src/Charts/Charts.tsx +20 -0
- package/src/Charts/Charts.types.ts +40 -0
- package/src/Charts/Gallery.tsx +25 -0
- package/src/Charts/Heatmap.tsx +116 -0
- package/src/Charts/OrgChart.tsx +53 -0
- package/src/Charts/ResourceSchedule.tsx +91 -0
- package/src/Charts/Sparkline.tsx +59 -0
- package/src/Charts/Timeline.tsx +777 -0
- package/src/Charts/categories.ts +21 -0
- package/src/Charts/timeline-plan.ts +191 -0
- package/src/Checkbox/README.md +6 -0
- package/src/ChecklistRunner/README.md +3 -0
- package/src/Chips/Badge.tsx +27 -0
- package/src/Chips/Chips.shared.tsx +34 -0
- package/src/Chips/Chips.tsx +21 -0
- package/src/Chips/Chips.types.ts +35 -0
- package/src/Chips/DepartmentChip.tsx +16 -0
- package/src/Chips/PhaseChip.tsx +16 -0
- package/src/Chips/PropertyChip.tsx +15 -0
- package/src/Chips/RecordKindChip.tsx +14 -0
- package/src/Chips/StateChip.tsx +19 -0
- package/src/Chips/Tag.tsx +47 -0
- package/src/Chips/URIDChip.tsx +14 -0
- package/src/Chips/chipClass.tsx +8 -0
- package/src/Chips/codeClass.tsx +6 -0
- package/src/ClockButton/README.md +6 -0
- package/src/CodeSample/README.md +7 -0
- package/src/ColorPicker/README.md +5 -0
- package/src/Combobox/README.md +7 -0
- package/src/CommandMenu/CommandMenu.tsx +179 -0
- package/src/CommandMenu/README.md +5 -0
- package/src/ComparisonTable/README.md +9 -0
- package/src/Compass/ChecklistRunner.tsx +128 -0
- package/src/Compass/ClockButton.tsx +57 -0
- package/src/Compass/Compass.shared.tsx +58 -0
- package/src/Compass/Compass.tsx +26 -0
- package/src/Compass/Compass.types.ts +79 -0
- package/src/Compass/DaySheetView.tsx +104 -0
- package/src/Compass/ForceUpdateScreen.tsx +29 -0
- package/src/Compass/LiveActivity.tsx +60 -0
- package/src/Compass/OfflineBanner.tsx +31 -0
- package/src/Compass/PhotoCapture.tsx +69 -0
- package/src/Compass/QuickIncidentSheet.tsx +46 -0
- package/src/Compass/ScanSheet.tsx +83 -0
- package/src/Compass/ShiftCard.tsx +55 -0
- package/src/Compass/SignaturePad.tsx +71 -0
- package/src/Compass/SyncConflictSheet.tsx +60 -0
- package/src/ConsentBanner/ConsentBanner.tsx +210 -0
- package/src/ConsentBanner/ConsentBannerStatic.tsx +163 -0
- package/src/ConsentBanner/ConsentSettings.tsx +213 -0
- package/src/ConsentBanner/README.md +101 -0
- package/src/ConsentBanner/consent.ts +238 -0
- package/src/ConsentBanner/index.ts +40 -0
- package/src/ConsentBanner/static.ts +11 -0
- package/src/ConsentBanner/useConsent.ts +160 -0
- package/src/ContextMenu/README.md +3 -0
- package/src/CoordinateMatrix/README.md +6 -0
- package/src/CredentialBadge/README.md +7 -0
- package/src/CurrencyInput/README.md +7 -0
- package/src/DataTable/DataTable.tsx +1034 -0
- package/src/DataTable/DataTableResizer.tsx +72 -0
- package/src/DataTable/DataTableVirtualizer.tsx +58 -0
- package/src/DataTable/README.md +9 -0
- package/src/DatePicker/README.md +5 -0
- package/src/DateRangePicker/README.md +3 -0
- package/src/DaySheetView/README.md +3 -0
- package/src/DepartmentChip/README.md +3 -0
- package/src/DepartmentGlyph/README.md +18 -0
- package/src/Dialog/README.md +3 -0
- package/src/DiffViewer/README.md +3 -0
- package/src/Divider/README.md +3 -0
- package/src/Drawer/README.md +3 -0
- package/src/DropdownMenu/README.md +3 -0
- package/src/EPKViewer/README.md +3 -0
- package/src/Editing/ColorPicker.tsx +125 -0
- package/src/Editing/DiffViewer.tsx +49 -0
- package/src/Editing/Editing.tsx +29 -0
- package/src/Editing/Editing.types.ts +71 -0
- package/src/Editing/FilterBuilder.tsx +72 -0
- package/src/Editing/QuickAdd.tsx +102 -0
- package/src/Editing/QuickAddChips.tsx +180 -0
- package/src/Editing/contrastRatio.tsx +11 -0
- package/src/Editing/parseQuickAdd.tsx +187 -0
- package/src/Editing/quickAddCore.ts +204 -0
- package/src/Editing/timeShorthand.ts +157 -0
- package/src/Editing/useQuickAdd.ts +201 -0
- package/src/EmergencyCodeCard/README.md +10 -0
- package/src/EmptyState/README.md +5 -0
- package/src/EngagementTimeline/README.md +3 -0
- package/src/ErrorState/README.md +3 -0
- package/src/FAQ/README.md +7 -0
- package/src/FeatureGrid/README.md +7 -0
- package/src/Feedback/Banner.tsx +40 -0
- package/src/Feedback/EmptyState.tsx +32 -0
- package/src/Feedback/ErrorState.tsx +32 -0
- package/src/Feedback/Feedback.shared.tsx +38 -0
- package/src/Feedback/Feedback.tsx +18 -0
- package/src/Feedback/Feedback.types.ts +40 -0
- package/src/Feedback/InlineAlert.tsx +19 -0
- package/src/Feedback/RefusalNotice.tsx +46 -0
- package/src/Feedback/RegionBoundary.tsx +102 -0
- package/src/Feedback/Toast.tsx +31 -0
- package/src/Feedback/ToastRegion.tsx +26 -0
- package/src/Feedback/UndoToast.tsx +97 -0
- package/src/FeedbackWidget/README.md +3 -0
- package/src/Field/Field.tsx +81 -0
- package/src/FileDrop/README.md +3 -0
- package/src/FilePreviewer/README.md +3 -0
- package/src/FilterBuilder/README.md +3 -0
- package/src/ForceUpdateScreen/README.md +3 -0
- package/src/Forms/Checkbox.tsx +14 -0
- package/src/Forms/CurrencyInput.tsx +40 -0
- package/src/Forms/Forms.shared.tsx +5 -0
- package/src/Forms/Forms.tsx +20 -0
- package/src/Forms/Forms.types.ts +33 -0
- package/src/Forms/Input.tsx +28 -0
- package/src/Forms/Money.tsx +15 -0
- package/src/Forms/NumberInput.tsx +85 -0
- package/src/Forms/Radio.tsx +31 -0
- package/src/Forms/Select.tsx +54 -0
- package/src/Forms/Switch.tsx +14 -0
- package/src/Forms/Textarea.tsx +30 -0
- package/src/Gallery/README.md +5 -0
- package/src/GateLifecycleRail/README.md +7 -0
- package/src/GateReadinessPanel/README.md +8 -0
- package/src/Gateway/AgencySlate.tsx +76 -0
- package/src/Gateway/ApplicationForm.tsx +48 -0
- package/src/Gateway/AvailabilityCalendar.tsx +82 -0
- package/src/Gateway/EPKViewer.tsx +77 -0
- package/src/Gateway/EngagementTimeline.tsx +43 -0
- package/src/Gateway/Gateway.shared.tsx +5 -0
- package/src/Gateway/Gateway.tsx +30 -0
- package/src/Gateway/Gateway.types.ts +69 -0
- package/src/Gateway/OnboardingPacket.tsx +61 -0
- package/src/Gateway/OpportunityCard.tsx +73 -0
- package/src/Gateway/OpportunityFilters.tsx +64 -0
- package/src/Gateway/PaymentTracker.tsx +71 -0
- package/src/Gateway/PayoutDetailsForm.tsx +62 -0
- package/src/Gateway/ProfileEditor.tsx +45 -0
- package/src/Gateway/ProgressBar.tsx +30 -0
- package/src/Gateway/RatingDialog.tsx +83 -0
- package/src/Gateway/UpNextCard.tsx +76 -0
- package/src/Glyphs/Glyphs.tsx +66 -0
- package/src/Grids/BidSheet.tsx +63 -0
- package/src/Grids/BudgetGrid.tsx +164 -0
- package/src/Grids/Grids.shared.tsx +5 -0
- package/src/Grids/Grids.tsx +11 -0
- package/src/Grids/Grids.types.ts +38 -0
- package/src/Grids/SpreadsheetGrid.tsx +445 -0
- package/src/Grids/columnTotal.tsx +14 -0
- package/src/Grids/glForCode.tsx +11 -0
- package/src/Grids/parseCell.tsx +16 -0
- package/src/Help/FeedbackWidget.tsx +89 -0
- package/src/Help/Help.tsx +14 -0
- package/src/Help/Help.types.ts +51 -0
- package/src/Help/HelpPanel.tsx +116 -0
- package/src/Help/NotificationCenter.tsx +100 -0
- package/src/Help/OnboardingChecklist.tsx +57 -0
- package/src/Help/ShortcutEditor.tsx +81 -0
- package/src/Help/WhatsNew.tsx +33 -0
- package/src/HelpPanel/README.md +5 -0
- package/src/HoverCard/README.md +3 -0
- package/src/Icon/Icon.tsx +47 -0
- package/src/Icon/README.md +9 -0
- package/src/IconButton/README.md +6 -0
- package/src/Identity/BrandSlot.tsx +20 -0
- package/src/Identity/BrandSlotFrame.tsx +38 -0
- package/src/Identity/CredentialBadge.tsx +92 -0
- package/src/Identity/Identity.tsx +14 -0
- package/src/Identity/Identity.types.ts +25 -0
- package/src/Identity/PresenceIndicator.tsx +37 -0
- package/src/Identity/QRCode.tsx +22 -0
- package/src/Identity/WhiteLabelPreview.tsx +33 -0
- package/src/Identity/qrPath.tsx +16 -0
- package/src/Identity/tokenVariable.tsx +9 -0
- package/src/InlineAlert/README.md +3 -0
- package/src/Input/README.md +8 -0
- package/src/Kbd/Kbd.tsx +30 -0
- package/src/Kbd/README.md +6 -0
- package/src/Layout/AppShell.tsx +151 -0
- package/src/Layout/Layout.tsx +14 -0
- package/src/Layout/Layout.types.ts +43 -0
- package/src/Layout/PageHeader.tsx +22 -0
- package/src/Layout/ResizablePanel.tsx +81 -0
- package/src/Layout/ScrollRegion.tsx +107 -0
- package/src/Layout/SplitView.tsx +78 -0
- package/src/Layout/Stepper.tsx +39 -0
- package/src/LegalText/LegalText.tsx +289 -0
- package/src/LegalText/README.md +10 -0
- package/src/LegalText/index.ts +29 -0
- package/src/LegalText/legal-markdown.ts +581 -0
- package/src/Link/Link.tsx +25 -0
- package/src/Link/README.md +5 -0
- package/src/Link/link-class.ts +10 -0
- package/src/LiveActivity/README.md +3 -0
- package/src/LogoSlotWall/README.md +7 -0
- package/src/MapView/README.md +5 -0
- package/src/Marketing/AIDisclosureBadge.tsx +31 -0
- package/src/Marketing/ButtonLink.tsx +32 -0
- package/src/Marketing/CodeSample.tsx +47 -0
- package/src/Marketing/ComparisonScroll.tsx +7 -0
- package/src/Marketing/ComparisonTable.tsx +104 -0
- package/src/Marketing/FAQ.tsx +26 -0
- package/src/Marketing/FeatureGrid.tsx +65 -0
- package/src/Marketing/GateLifecycleRail.tsx +52 -0
- package/src/Marketing/LogoSlotWall.tsx +53 -0
- package/src/Marketing/Marketing.tsx +49 -0
- package/src/Marketing/Marketing.types.ts +64 -0
- package/src/Marketing/MarketingFooter.tsx +88 -0
- package/src/Marketing/MarketingHero.tsx +45 -0
- package/src/Marketing/MarketingNav.tsx +76 -0
- package/src/Marketing/MarketingPoints.tsx +16 -0
- package/src/Marketing/MarketingSection.tsx +52 -0
- package/src/Marketing/PersonaSwitcher.tsx +137 -0
- package/src/Marketing/PriceDisplay.tsx +56 -0
- package/src/Marketing/PricingTable.tsx +122 -0
- package/src/Marketing/ProofStatStrip.tsx +35 -0
- package/src/Marketing/ScreenshotFrame.tsx +56 -0
- package/src/Marketing/SurfaceTriptych.tsx +43 -0
- package/src/Marketing/Testimonial.tsx +45 -0
- package/src/Marketing/marketing-copy.ts +25 -0
- package/src/Marketing/provided.tsx +36 -0
- package/src/MarketingFooter/README.md +7 -0
- package/src/MarketingHero/README.md +7 -0
- package/src/MarketingNav/README.md +7 -0
- package/src/MarketingSection/README.md +7 -0
- package/src/Media/FilePreviewer.tsx +86 -0
- package/src/Media/MapView.tsx +200 -0
- package/src/Media/Media.tsx +11 -0
- package/src/Media/Media.types.ts +47 -0
- package/src/Media/RichTextEditor.tsx +198 -0
- package/src/Media/toLngLat.tsx +13 -0
- package/src/Menus/ContextMenu.tsx +106 -0
- package/src/Menus/DropdownMenu.tsx +51 -0
- package/src/Menus/Menus.shared.tsx +67 -0
- package/src/Menus/Menus.tsx +13 -0
- package/src/Menus/Menus.types.ts +49 -0
- package/src/Menus/OrgSwitcher.tsx +69 -0
- package/src/Menus/compactTriggerClass.tsx +7 -0
- package/src/Menus/menuClass.tsx +4 -0
- package/src/Menus/menuItemClass.tsx +7 -0
- package/src/Menus/orgSwitcherTriggerClass.tsx +7 -0
- package/src/Money/README.md +6 -0
- package/src/MultiSelect/README.md +3 -0
- package/src/Navigation/Accordion.tsx +59 -0
- package/src/Navigation/Breadcrumbs.tsx +59 -0
- package/src/Navigation/MoreFields.tsx +42 -0
- package/src/Navigation/Navigation.shared.tsx +32 -0
- package/src/Navigation/Navigation.tsx +21 -0
- package/src/Navigation/Navigation.types.ts +63 -0
- package/src/Navigation/Pagination.tsx +30 -0
- package/src/Navigation/SegmentedControl.tsx +87 -0
- package/src/Navigation/Sidebar.tsx +106 -0
- package/src/Navigation/TabBar.tsx +61 -0
- package/src/Navigation/Tabs.tsx +79 -0
- package/src/Navigation/TopNav.tsx +86 -0
- package/src/Navigation/sidebar-classes.ts +18 -0
- package/src/NotificationCenter/README.md +3 -0
- package/src/NumberInput/README.md +3 -0
- package/src/OfflineBanner/README.md +3 -0
- package/src/OnboardingChecklist/README.md +3 -0
- package/src/OnboardingPacket/README.md +3 -0
- package/src/OpportunityCard/README.md +5 -0
- package/src/OpportunityFilters/README.md +3 -0
- package/src/OrgChart/README.md +5 -0
- package/src/OrgSwitcher/README.md +3 -0
- package/src/Overlays/Dialog.tsx +54 -0
- package/src/Overlays/Drawer.tsx +62 -0
- package/src/Overlays/HoverCard.tsx +59 -0
- package/src/Overlays/Overlays.shared.tsx +12 -0
- package/src/Overlays/Overlays.tsx +20 -0
- package/src/Overlays/Overlays.types.ts +66 -0
- package/src/Overlays/Popover.tsx +70 -0
- package/src/Overlays/PropertyList.tsx +19 -0
- package/src/Overlays/ShortcutSheet.tsx +62 -0
- package/src/Overlays/SidePeek.tsx +117 -0
- package/src/Overlays/Tooltip.tsx +73 -0
- package/src/Overlays/panelClass.tsx +6 -0
- package/src/Overlays/popoverPanelClass.tsx +6 -0
- package/src/PageHeader/README.md +3 -0
- package/src/Pagination/README.md +3 -0
- package/src/PaymentTracker/README.md +3 -0
- package/src/PayoutDetailsForm/README.md +3 -0
- package/src/PersonaSwitcher/README.md +7 -0
- package/src/PhaseChip/README.md +5 -0
- package/src/PhaseGlyph/README.md +17 -0
- package/src/PhotoCapture/README.md +3 -0
- package/src/Pickers/Combobox.tsx +91 -0
- package/src/Pickers/DatePicker.tsx +60 -0
- package/src/Pickers/DateRangePicker.tsx +78 -0
- package/src/Pickers/FileDrop.tsx +84 -0
- package/src/Pickers/MultiSelect.tsx +118 -0
- package/src/Pickers/Pickers.shared.tsx +337 -0
- package/src/Pickers/Pickers.tsx +17 -0
- package/src/Pickers/Pickers.types.ts +47 -0
- package/src/Pickers/Slider.tsx +59 -0
- package/src/Pickers/TimePicker.tsx +68 -0
- package/src/Pickers/rankOptions.tsx +12 -0
- package/src/Popover/README.md +3 -0
- package/src/PresenceIndicator/README.md +3 -0
- package/src/PriceDisplay/README.md +7 -0
- package/src/PricingTable/README.md +9 -0
- package/src/ProfileEditor/README.md +3 -0
- package/src/ProgressBar/README.md +3 -0
- package/src/ProofStatStrip/README.md +7 -0
- package/src/PropertyChip/README.md +3 -0
- package/src/ProvenanceBadge/README.md +3 -0
- package/src/QRCode/README.md +6 -0
- package/src/QuickAdd/README.md +5 -0
- package/src/QuickIncidentSheet/README.md +3 -0
- package/src/Radio/README.md +3 -0
- package/src/RadioChannelTable/README.md +7 -0
- package/src/RatingDialog/README.md +3 -0
- package/src/ReconciliationTable/README.md +3 -0
- package/src/RecordKindChip/README.md +3 -0
- package/src/RecordKindGlyph/README.md +34 -0
- package/src/RecordRow/README.md +7 -0
- package/src/RefusalNotice/README.md +5 -0
- package/src/ResizablePanel/README.md +3 -0
- package/src/ResourceSchedule/README.md +6 -0
- package/src/RichTextEditor/README.md +3 -0
- package/src/RichTextEditor/extensions.ts +217 -0
- package/src/RunOfShowLive/README.md +5 -0
- package/src/ScanSheet/README.md +3 -0
- package/src/ScreenshotFrame/README.md +7 -0
- package/src/ScrollRegion/README.md +9 -0
- package/src/SegmentedControl/README.md +5 -0
- package/src/Select/README.md +5 -0
- package/src/ShiftCard/README.md +3 -0
- package/src/ShortcutEditor/README.md +3 -0
- package/src/ShortcutSheet/README.md +3 -0
- package/src/SidePeek/README.md +6 -0
- package/src/Sidebar/README.md +5 -0
- package/src/SignaturePad/README.md +3 -0
- package/src/Skeleton/README.md +3 -0
- package/src/Slider/README.md +3 -0
- package/src/SplitView/README.md +3 -0
- package/src/SpreadsheetGrid/README.md +9 -0
- package/src/StalenessIndicator/README.md +3 -0
- package/src/StatTile/README.md +6 -0
- package/src/StateChip/README.md +6 -0
- package/src/StateIcon/README.md +6 -0
- package/src/StateIcon/StateIcon.tsx +127 -0
- package/src/StatusHeatmap/README.md +15 -0
- package/src/Stepper/README.md +3 -0
- package/src/Surface/Skeleton.tsx +21 -0
- package/src/Surface/Surface.tsx +63 -0
- package/src/SurfaceTriptych/README.md +7 -0
- package/src/Switch/README.md +5 -0
- package/src/SyncConflictSheet/README.md +3 -0
- package/src/TabBar/README.md +7 -0
- package/src/Tabs/README.md +6 -0
- package/src/Tag/README.md +3 -0
- package/src/TemplateAuth/README.md +6 -0
- package/src/TemplateCollection/README.md +6 -0
- package/src/TemplateDashboard/README.md +8 -0
- package/src/TemplateDocument/README.md +5 -0
- package/src/TemplateGatewayShell/README.md +5 -0
- package/src/TemplateGridEditor/README.md +3 -0
- package/src/TemplateRecord/README.md +3 -0
- package/src/TemplateSettings/README.md +5 -0
- package/src/TemplateSplitView/README.md +3 -0
- package/src/TemplateSystem/README.md +5 -0
- package/src/TemplateWizard/README.md +3 -0
- package/src/Templates/TemplateAuth.tsx +16 -0
- package/src/Templates/TemplateCollection.tsx +35 -0
- package/src/Templates/TemplateDashboard.tsx +200 -0
- package/src/Templates/TemplateDocument.tsx +24 -0
- package/src/Templates/TemplateGatewayShell.tsx +36 -0
- package/src/Templates/TemplateGridEditor.tsx +17 -0
- package/src/Templates/TemplateRecord.tsx +31 -0
- package/src/Templates/TemplateSettings.tsx +26 -0
- package/src/Templates/TemplateSplitView.tsx +27 -0
- package/src/Templates/TemplateSystem.tsx +19 -0
- package/src/Templates/TemplateSystemLink.tsx +55 -0
- package/src/Templates/TemplateWizard.tsx +43 -0
- package/src/Templates/Templates.tsx +29 -0
- package/src/Templates/Templates.types.ts +153 -0
- package/src/Testimonial/README.md +7 -0
- package/src/Textarea/README.md +3 -0
- package/src/TimePicker/README.md +5 -0
- package/src/Timeline/README.md +6 -0
- package/src/Toast/README.md +3 -0
- package/src/Tooltip/README.md +3 -0
- package/src/TopNav/README.md +5 -0
- package/src/TreeView/README.md +3 -0
- package/src/URIDChip/README.md +5 -0
- package/src/UndoToast/README.md +3 -0
- package/src/UpNextCard/README.md +6 -0
- package/src/Views/ActivityFeedItem.tsx +52 -0
- package/src/Views/Board.tsx +229 -0
- package/src/Views/BulkActionBar.tsx +76 -0
- package/src/Views/RecordList.tsx +146 -0
- package/src/Views/RecordRow.tsx +132 -0
- package/src/Views/StatTile.tsx +88 -0
- package/src/Views/TreeView.tsx +161 -0
- package/src/Views/Views.tsx +18 -0
- package/src/Views/Views.types.ts +99 -0
- package/src/WhatsNew/README.md +3 -0
- package/src/WhiteLabelPreview/README.md +8 -0
- package/src/XOS/AccessGridMatrix.tsx +111 -0
- package/src/XOS/AssertionRankBadge.tsx +27 -0
- package/src/XOS/CoordinateMatrix.tsx +123 -0
- package/src/XOS/EmergencyCodeCard.tsx +109 -0
- package/src/XOS/GateReadinessPanel.tsx +100 -0
- package/src/XOS/ProvenanceBadge.tsx +19 -0
- package/src/XOS/RadioChannelTable.tsx +50 -0
- package/src/XOS/ReconciliationTable.tsx +64 -0
- package/src/XOS/RunOfShowLive.tsx +97 -0
- package/src/XOS/StalenessIndicator.tsx +31 -0
- package/src/XOS/StatusHeatmap.tsx +200 -0
- package/src/XOS/XOS.shared.tsx +90 -0
- package/src/XOS/XOS.tsx +29 -0
- package/src/XOS/XOS.types.ts +99 -0
- package/src/XOS/resolveStep.tsx +16 -0
- package/src/brand/defaults/README.md +13 -0
- package/src/brand/defaults/app-icon.svg +6 -0
- package/src/brand/defaults/favicon.svg +6 -0
- package/src/brand/defaults/logo-dark.svg +6 -0
- package/src/brand/defaults/logo-light.svg +6 -0
- package/src/brand/defaults/splash.svg +6 -0
- package/src/index.ts +606 -0
- package/src/lib/context.tsx +156 -0
- package/src/lib/cx.ts +4 -0
- package/src/lib/format.ts +200 -0
- package/src/lib/hooks.ts +187 -0
- package/src/lib/i18n.ts +97 -0
- package/src/lib/icons.ts +45 -0
- package/src/lib/live.ts +92 -0
- package/src/lib/preferences.ts +242 -0
- package/src/lib/route-transition.tsx +22 -0
- package/src/lib/selection.ts +92 -0
- package/src/lib/shortcut-targets.ts +125 -0
- package/src/lib/theme.ts +50 -0
- package/src/lib/undo-stack.ts +125 -0
- package/src/marketing.ts +33 -0
- package/src/pwa/action-outcome.tsx +81 -0
- package/src/pwa/analytics.ts +236 -0
- package/src/pwa/browser-push.tsx +132 -0
- package/src/pwa/client.ts +126 -0
- package/src/pwa/index.ts +40 -0
- package/src/pwa/offline-key.ts +18 -0
- package/src/pwa/service-worker.ts +229 -0
- package/src/static.ts +10 -0
- package/src/styles/base.css +208 -0
- package/src/styles/components.css +453 -0
- package/src/styles/index.css +16 -0
- package/src/styles/marketing.css +1260 -0
- package/src/styles/reference.css +5792 -0
- package/src/types/reference.d.ts +1608 -0
- 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,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,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
|
+
}
|