@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,11 @@
|
|
|
1
|
+
import type { GLAccount } from "../types/reference";
|
|
2
|
+
|
|
3
|
+
/** The account a role code or URID posts to: its class's one account of the requested type, or null. */
|
|
4
|
+
export function glForCode(
|
|
5
|
+
code: string,
|
|
6
|
+
accounts: GLAccount[],
|
|
7
|
+
type: GLAccount["type"] = "Expense",
|
|
8
|
+
): GLAccount | null {
|
|
9
|
+
const cls = code.split(".")[0];
|
|
10
|
+
return accounts.find((a) => a.classCode === cls && a.type === type) ?? null;
|
|
11
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { GridColumn } from "../types/reference";
|
|
2
|
+
import { isNumeric } from "./Grids.shared.tsx";
|
|
3
|
+
import { type Cell } from "./Grids.types.ts";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A typed cell value: a column's own parse decides first; otherwise blank is null, numbers parse (a trailing x on
|
|
7
|
+
* multipliers is dropped) and text stays text.
|
|
8
|
+
*/
|
|
9
|
+
export function parseCell(c: GridColumn, text: string): Cell {
|
|
10
|
+
if (c.parse) return c.parse(text);
|
|
11
|
+
const trimmed = text.trim();
|
|
12
|
+
if (trimmed === "") return null;
|
|
13
|
+
if (!isNumeric(c)) return trimmed;
|
|
14
|
+
const n = Number(trimmed.replace(/x$/i, "").replace(/[$,\s]/g, ""));
|
|
15
|
+
return Number.isFinite(n) ? n : null;
|
|
16
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { useState, type ReactElement } from "react";
|
|
2
|
+
import { useT } from "../lib/context.tsx";
|
|
3
|
+
import { Icon } from "../Icon/Icon.tsx";
|
|
4
|
+
import { Button } from "../Button/Button.tsx";
|
|
5
|
+
import { Card } from "../Surface/Surface.tsx";
|
|
6
|
+
import { Checkbox, Textarea } from "../Forms/Forms.tsx";
|
|
7
|
+
import { type FeedbackWidgetProps } from "./Help.types.ts";
|
|
8
|
+
|
|
9
|
+
/** Feedback with a privacy note; only what the person chooses is sent. */
|
|
10
|
+
export function FeedbackWidget({
|
|
11
|
+
onSend,
|
|
12
|
+
onCancel,
|
|
13
|
+
screenshotField,
|
|
14
|
+
context,
|
|
15
|
+
thanks,
|
|
16
|
+
}: FeedbackWidgetProps): ReactElement {
|
|
17
|
+
const t = useT();
|
|
18
|
+
const [sent, setSent] = useState(false);
|
|
19
|
+
const [sending, setSending] = useState(false);
|
|
20
|
+
const [failed, setFailed] = useState(false);
|
|
21
|
+
const [text, setText] = useState("");
|
|
22
|
+
const [screenshot, setScreenshot] = useState(false);
|
|
23
|
+
const send = () => {
|
|
24
|
+
const result = onSend?.({ text, screenshot });
|
|
25
|
+
if (!(result instanceof Promise)) {
|
|
26
|
+
setSent(true);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
setSending(true);
|
|
30
|
+
setFailed(false);
|
|
31
|
+
void result.then(
|
|
32
|
+
(ok) => {
|
|
33
|
+
setSending(false);
|
|
34
|
+
setSent(ok);
|
|
35
|
+
setFailed(!ok);
|
|
36
|
+
},
|
|
37
|
+
() => {
|
|
38
|
+
setSending(false);
|
|
39
|
+
setFailed(true);
|
|
40
|
+
},
|
|
41
|
+
);
|
|
42
|
+
};
|
|
43
|
+
return (
|
|
44
|
+
<Card
|
|
45
|
+
title={t("feedback.title")}
|
|
46
|
+
footer={
|
|
47
|
+
sent ? (
|
|
48
|
+
<span role="status" className="flex items-center gap-6">
|
|
49
|
+
<span className="text-success">
|
|
50
|
+
<Icon name="CircleCheck" />
|
|
51
|
+
</span>
|
|
52
|
+
{thanks ?? t("feedback.thanks")}
|
|
53
|
+
</span>
|
|
54
|
+
) : (
|
|
55
|
+
<>
|
|
56
|
+
<Button variant="ghost" onClick={onCancel}>
|
|
57
|
+
{t("action.cancel")}
|
|
58
|
+
</Button>
|
|
59
|
+
<Button variant="primary" disabled={!text.trim() || sending} onClick={send}>
|
|
60
|
+
{t("action.send")}
|
|
61
|
+
</Button>
|
|
62
|
+
</>
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
>
|
|
66
|
+
<Textarea
|
|
67
|
+
label={t("feedback.question")}
|
|
68
|
+
placeholder={t("feedback.hint")}
|
|
69
|
+
width="100%"
|
|
70
|
+
value={text}
|
|
71
|
+
onChange={(e) => setText(e.target.value)}
|
|
72
|
+
/>
|
|
73
|
+
{screenshotField ?? (
|
|
74
|
+
<Checkbox
|
|
75
|
+
label={t("feedback.screenshot")}
|
|
76
|
+
checked={screenshot}
|
|
77
|
+
onChange={(e) => setScreenshot(e.target.checked)}
|
|
78
|
+
/>
|
|
79
|
+
)}
|
|
80
|
+
<span className="text-text-12 text-text-secondary">{t("feedback.privacy")}</span>
|
|
81
|
+
{context ? <div className="text-text-12 text-text-secondary">{context}</div> : null}
|
|
82
|
+
{failed ? (
|
|
83
|
+
<span role="alert" className="text-text-12 text-danger-text">
|
|
84
|
+
{t("feedback.failed")}
|
|
85
|
+
</span>
|
|
86
|
+
) : null}
|
|
87
|
+
</Card>
|
|
88
|
+
);
|
|
89
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export {
|
|
2
|
+
type NotificationCenterProps,
|
|
3
|
+
type OnboardingChecklistProps,
|
|
4
|
+
type WhatsNewProps,
|
|
5
|
+
type FeedbackWidgetProps,
|
|
6
|
+
type ShortcutEditorProps,
|
|
7
|
+
type HelpPanelProps,
|
|
8
|
+
} from "./Help.types.ts";
|
|
9
|
+
export { NotificationCenter } from "./NotificationCenter.tsx";
|
|
10
|
+
export { OnboardingChecklist } from "./OnboardingChecklist.tsx";
|
|
11
|
+
export { WhatsNew } from "./WhatsNew.tsx";
|
|
12
|
+
export { FeedbackWidget } from "./FeedbackWidget.tsx";
|
|
13
|
+
export { ShortcutEditor } from "./ShortcutEditor.tsx";
|
|
14
|
+
export { HelpPanel } from "./HelpPanel.tsx";
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import type {
|
|
3
|
+
FeedbackWidgetProps as ReferenceFeedbackWidgetProps,
|
|
4
|
+
HelpPanelProps as ReferenceHelpPanelProps,
|
|
5
|
+
NotificationCenterProps as ReferenceNotificationCenterProps,
|
|
6
|
+
NotificationItem,
|
|
7
|
+
OnboardingChecklistProps as ReferenceOnboardingChecklistProps,
|
|
8
|
+
ShortcutEditorProps as ReferenceShortcutEditorProps,
|
|
9
|
+
WhatsNewProps as ReferenceWhatsNewProps,
|
|
10
|
+
} from "../types/reference";
|
|
11
|
+
|
|
12
|
+
export type NotificationCenterProps = ReferenceNotificationCenterProps & {
|
|
13
|
+
onAction?: (item: NotificationItem) => void;
|
|
14
|
+
onDone?: (item: NotificationItem) => void;
|
|
15
|
+
onSnooze?: (item: NotificationItem) => void;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export type OnboardingChecklistProps = ReferenceOnboardingChecklistProps & {
|
|
19
|
+
onAction?: (label: string) => void;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export type WhatsNewProps = ReferenceWhatsNewProps;
|
|
23
|
+
|
|
24
|
+
export type FeedbackWidgetProps = ReferenceFeedbackWidgetProps & {
|
|
25
|
+
/**
|
|
26
|
+
* Sends the feedback. A promise holds the widget in its sending state; false keeps the text and says it did not
|
|
27
|
+
* send, so the person can try again.
|
|
28
|
+
*/
|
|
29
|
+
onSend?: (feedback: { text: string; screenshot: boolean }) => Promise<boolean> | undefined;
|
|
30
|
+
onCancel?: () => void;
|
|
31
|
+
/** Replaces the screenshot checkbox, for an app that attaches a file the person chooses (A96). */
|
|
32
|
+
screenshotField?: ReactNode;
|
|
33
|
+
/** What goes with the message, shown under the privacy note so nothing is sent unseen (Section 11.7). */
|
|
34
|
+
context?: ReactNode;
|
|
35
|
+
/** The thanks once sent, for example with the reference the platform team quotes. */
|
|
36
|
+
thanks?: string;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export type ShortcutEditorProps = ReferenceShortcutEditorProps & {
|
|
40
|
+
onChange?: (action: string) => void;
|
|
41
|
+
onReset?: (action: string) => void;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export type HelpPanelProps = ReferenceHelpPanelProps & {
|
|
45
|
+
onSearch?: (query: string) => void;
|
|
46
|
+
onArticle?: (title: string) => void;
|
|
47
|
+
onAsk?: (question: string) => void;
|
|
48
|
+
onWhatsNew?: () => void;
|
|
49
|
+
onContact?: () => void;
|
|
50
|
+
onClose?: () => void;
|
|
51
|
+
};
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { useState, type ReactElement } from "react";
|
|
2
|
+
import { cx } from "../lib/cx.ts";
|
|
3
|
+
import { useT } from "../lib/context.tsx";
|
|
4
|
+
import { Icon } from "../Icon/Icon.tsx";
|
|
5
|
+
import { Button, IconButton } from "../Button/Button.tsx";
|
|
6
|
+
import { Keys } from "../Kbd/Kbd.tsx";
|
|
7
|
+
import { linkClass } from "../Link/Link.tsx";
|
|
8
|
+
import { type HelpPanelProps } from "./Help.types.ts";
|
|
9
|
+
|
|
10
|
+
const searchFieldClass = cx(
|
|
11
|
+
"flex items-center gap-8 h-row-default ps-12 pe-8 rounded-control border border-border-control bg-bg-surface",
|
|
12
|
+
"focus-within:outline-solid focus-within:outline-stroke-focus focus-within:outline-focus-ring",
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
const searchInputClass = cx(
|
|
16
|
+
"flex-1 min-w-0 border-0 bg-transparent outline-none text-text-primary placeholder:text-text-tertiary pointer-coarse:min-h-target-coarse",
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
/** Help for this page: search, articles, its shortcuts, the assistant, What's New and support. */
|
|
20
|
+
export function HelpPanel({
|
|
21
|
+
articles,
|
|
22
|
+
shortcuts,
|
|
23
|
+
assistant = false,
|
|
24
|
+
onSearch,
|
|
25
|
+
onArticle,
|
|
26
|
+
onAsk,
|
|
27
|
+
onWhatsNew,
|
|
28
|
+
onContact,
|
|
29
|
+
onClose,
|
|
30
|
+
}: HelpPanelProps): ReactElement {
|
|
31
|
+
const t = useT();
|
|
32
|
+
const [question, setQuestion] = useState("");
|
|
33
|
+
return (
|
|
34
|
+
<aside
|
|
35
|
+
aria-label={t("help.title")}
|
|
36
|
+
className="flex flex-col w-(--layout-sidebar-max) max-w-full max-md:w-full rounded-card bg-bg-raised shadow-dialog"
|
|
37
|
+
>
|
|
38
|
+
<header className="flex items-center justify-between py-8 ps-20 pe-12 border-b border-border-subtle">
|
|
39
|
+
<h2 className="m-0 text-text-13 font-semibold">{t("help.title")}</h2>
|
|
40
|
+
<IconButton icon="X" label={t("action.close")} shortcut={t("key.esc")} onClick={onClose} />
|
|
41
|
+
</header>
|
|
42
|
+
<div className="flex flex-col gap-16 px-20 pt-16 pb-20">
|
|
43
|
+
<label className={searchFieldClass}>
|
|
44
|
+
<Icon name="Search" color="var(--color-text-secondary)" />
|
|
45
|
+
<input
|
|
46
|
+
type="search"
|
|
47
|
+
aria-label={t("help.search")}
|
|
48
|
+
placeholder={t("help.search")}
|
|
49
|
+
onChange={(e) => onSearch?.(e.target.value)}
|
|
50
|
+
className={searchInputClass}
|
|
51
|
+
/>
|
|
52
|
+
</label>
|
|
53
|
+
<section>
|
|
54
|
+
<h3 className="m-0 mb-6 text-text-12 font-medium text-text-secondary">
|
|
55
|
+
{t("help.forThisPage")}
|
|
56
|
+
</h3>
|
|
57
|
+
<ul className="flex flex-col gap-6 m-0 p-0 list-none">
|
|
58
|
+
{articles.map((a) => (
|
|
59
|
+
<li key={a}>
|
|
60
|
+
<button
|
|
61
|
+
type="button"
|
|
62
|
+
onClick={() => onArticle?.(a)}
|
|
63
|
+
className={cx(linkClass, "p-0 border-0 bg-transparent cursor-pointer text-start")}
|
|
64
|
+
>
|
|
65
|
+
{a}
|
|
66
|
+
</button>
|
|
67
|
+
</li>
|
|
68
|
+
))}
|
|
69
|
+
</ul>
|
|
70
|
+
</section>
|
|
71
|
+
<section>
|
|
72
|
+
<h3 className="m-0 mb-6 text-text-12 font-medium text-text-secondary">
|
|
73
|
+
{t("help.shortcuts")}
|
|
74
|
+
</h3>
|
|
75
|
+
{shortcuts.map((s) => (
|
|
76
|
+
<div key={s.label} className="flex items-center justify-between min-h-control-md">
|
|
77
|
+
<span>{s.label}</span>
|
|
78
|
+
<Keys keys={s.keys} />
|
|
79
|
+
</div>
|
|
80
|
+
))}
|
|
81
|
+
</section>
|
|
82
|
+
{assistant ? (
|
|
83
|
+
<section>
|
|
84
|
+
<h3 className="m-0 mb-6 text-text-12 font-medium text-text-secondary">
|
|
85
|
+
{t("help.assistant")}
|
|
86
|
+
</h3>
|
|
87
|
+
<form
|
|
88
|
+
onSubmit={(e) => {
|
|
89
|
+
e.preventDefault();
|
|
90
|
+
if (question.trim()) onAsk?.(question.trim());
|
|
91
|
+
}}
|
|
92
|
+
className={searchFieldClass}
|
|
93
|
+
>
|
|
94
|
+
<Icon name="Sparkles" color="var(--color-text-secondary)" />
|
|
95
|
+
<input
|
|
96
|
+
aria-label={t("help.ask")}
|
|
97
|
+
placeholder={t("help.ask")}
|
|
98
|
+
value={question}
|
|
99
|
+
onChange={(e) => setQuestion(e.target.value)}
|
|
100
|
+
className={searchInputClass}
|
|
101
|
+
/>
|
|
102
|
+
</form>
|
|
103
|
+
</section>
|
|
104
|
+
) : null}
|
|
105
|
+
<div className="flex flex-wrap gap-8">
|
|
106
|
+
<Button icon="Megaphone" onClick={onWhatsNew}>
|
|
107
|
+
{t("help.whatsNew")}
|
|
108
|
+
</Button>
|
|
109
|
+
<Button icon="LifeBuoy" onClick={onContact}>
|
|
110
|
+
{t("help.contact")}
|
|
111
|
+
</Button>
|
|
112
|
+
</div>
|
|
113
|
+
</div>
|
|
114
|
+
</aside>
|
|
115
|
+
);
|
|
116
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { type KeyboardEvent, type ReactElement } from "react";
|
|
2
|
+
import type { NotificationItem } from "../types/reference";
|
|
3
|
+
import { useT } from "../lib/context.tsx";
|
|
4
|
+
import { singleKeyShortcutsEnabled } from "../lib/preferences.ts";
|
|
5
|
+
import { Icon } from "../Icon/Icon.tsx";
|
|
6
|
+
import { Button, IconButton } from "../Button/Button.tsx";
|
|
7
|
+
import { RecordKindGlyph } from "../Glyphs/Glyphs.tsx";
|
|
8
|
+
import { Tabs } from "../Navigation/Navigation.tsx";
|
|
9
|
+
import { type NotificationCenterProps } from "./Help.types.ts";
|
|
10
|
+
|
|
11
|
+
function NotificationList({
|
|
12
|
+
items,
|
|
13
|
+
onAction,
|
|
14
|
+
onDone,
|
|
15
|
+
onSnooze,
|
|
16
|
+
}: { items: NotificationItem[] } & Omit<NotificationCenterProps, "needsYou" | "fyi">) {
|
|
17
|
+
const t = useT();
|
|
18
|
+
const onKey = (e: KeyboardEvent<HTMLLIElement>, item: NotificationItem) => {
|
|
19
|
+
if (e.target !== e.currentTarget) return;
|
|
20
|
+
const key = singleKeyShortcutsEnabled() ? e.key.toLowerCase() : "";
|
|
21
|
+
if (key === "e") onDone?.(item);
|
|
22
|
+
else if (key === "h") onSnooze?.(item);
|
|
23
|
+
else if (e.key === "Enter") onAction?.(item);
|
|
24
|
+
else return;
|
|
25
|
+
e.preventDefault();
|
|
26
|
+
};
|
|
27
|
+
return (
|
|
28
|
+
<ul className="m-0 p-0 list-none">
|
|
29
|
+
{items.map((item, i) => (
|
|
30
|
+
<li
|
|
31
|
+
key={`${item.title}-${i}`}
|
|
32
|
+
tabIndex={0}
|
|
33
|
+
onKeyDown={(e) => onKey(e, item)}
|
|
34
|
+
className="xos-notif-item flex items-center gap-8 py-8 ps-16 pe-8 border-t border-border-subtle first:border-t-0 focus-visible:outline-offset-[calc(var(--stroke-width-focus)*-1)]"
|
|
35
|
+
>
|
|
36
|
+
{item.kind ? (
|
|
37
|
+
<RecordKindGlyph kind={item.kind} color="var(--color-text-secondary)" />
|
|
38
|
+
) : (
|
|
39
|
+
<Icon name="Bell" />
|
|
40
|
+
)}
|
|
41
|
+
<div className="xos-notif-text flex flex-1 flex-col min-w-0">
|
|
42
|
+
<span className="truncate">{item.title}</span>
|
|
43
|
+
<span className="text-text-secondary">{item.meta}</span>
|
|
44
|
+
</div>
|
|
45
|
+
{item.action ? (
|
|
46
|
+
<Button
|
|
47
|
+
size="sm"
|
|
48
|
+
onClick={() => onAction?.(item)}
|
|
49
|
+
{...(item.actionKey ? { shortcut: item.actionKey } : {})}
|
|
50
|
+
>
|
|
51
|
+
{item.action}
|
|
52
|
+
</Button>
|
|
53
|
+
) : null}
|
|
54
|
+
<IconButton
|
|
55
|
+
icon="Check"
|
|
56
|
+
label={t("action.done")}
|
|
57
|
+
shortcut="E"
|
|
58
|
+
onClick={() => onDone?.(item)}
|
|
59
|
+
/>
|
|
60
|
+
<IconButton
|
|
61
|
+
icon="AlarmClock"
|
|
62
|
+
label={t("action.snooze")}
|
|
63
|
+
shortcut="H"
|
|
64
|
+
onClick={() => onSnooze?.(item)}
|
|
65
|
+
/>
|
|
66
|
+
</li>
|
|
67
|
+
))}
|
|
68
|
+
</ul>
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** Needs You and For Your Information. On a focused item E marks it done, H snoozes it and Enter runs its action. */
|
|
73
|
+
export function NotificationCenter({
|
|
74
|
+
needsYou,
|
|
75
|
+
fyi,
|
|
76
|
+
...handlers
|
|
77
|
+
}: NotificationCenterProps): ReactElement {
|
|
78
|
+
const t = useT();
|
|
79
|
+
return (
|
|
80
|
+
<section
|
|
81
|
+
aria-label={t("inbox.label")}
|
|
82
|
+
className="xos-notif w-(--ui-empty) max-w-full box-border rounded-card border border-border-subtle bg-bg-raised"
|
|
83
|
+
>
|
|
84
|
+
<div className="px-16">
|
|
85
|
+
<Tabs
|
|
86
|
+
label={t("inbox.label")}
|
|
87
|
+
value="needs"
|
|
88
|
+
tabs={[
|
|
89
|
+
{ value: "needs", label: t("inbox.needsYou"), count: needsYou.length },
|
|
90
|
+
{ value: "fyi", label: t("inbox.fyi"), count: fyi.length },
|
|
91
|
+
]}
|
|
92
|
+
panels={{
|
|
93
|
+
needs: <NotificationList items={needsYou} {...handlers} />,
|
|
94
|
+
fyi: <NotificationList items={fyi} {...handlers} />,
|
|
95
|
+
}}
|
|
96
|
+
/>
|
|
97
|
+
</div>
|
|
98
|
+
</section>
|
|
99
|
+
);
|
|
100
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { type ReactElement } from "react";
|
|
2
|
+
import { cx } from "../lib/cx.ts";
|
|
3
|
+
import { useT } from "../lib/context.tsx";
|
|
4
|
+
import { Icon } from "../Icon/Icon.tsx";
|
|
5
|
+
import { Button } from "../Button/Button.tsx";
|
|
6
|
+
import { Card } from "../Surface/Surface.tsx";
|
|
7
|
+
import { type OnboardingChecklistProps } from "./Help.types.ts";
|
|
8
|
+
|
|
9
|
+
/** First-run steps with progress; done steps are struck through. */
|
|
10
|
+
export function OnboardingChecklist({
|
|
11
|
+
title,
|
|
12
|
+
steps,
|
|
13
|
+
onAction,
|
|
14
|
+
}: OnboardingChecklistProps): ReactElement {
|
|
15
|
+
const t = useT();
|
|
16
|
+
const done = steps.filter((s) => s.done).length;
|
|
17
|
+
return (
|
|
18
|
+
<Card title={title} meta={t("count.of", { n: done, total: steps.length })}>
|
|
19
|
+
<div
|
|
20
|
+
role="progressbar"
|
|
21
|
+
aria-label={title}
|
|
22
|
+
aria-valuenow={done}
|
|
23
|
+
aria-valuemin={0}
|
|
24
|
+
aria-valuemax={steps.length}
|
|
25
|
+
className="h-(--space-4) rounded-pill bg-bg-hover overflow-hidden"
|
|
26
|
+
>
|
|
27
|
+
<div
|
|
28
|
+
className="h-full rounded-pill bg-accent"
|
|
29
|
+
style={{ inlineSize: `${steps.length ? (done / steps.length) * 100 : 0}%` }}
|
|
30
|
+
/>
|
|
31
|
+
</div>
|
|
32
|
+
<ol className="flex flex-col m-0 p-0 list-none">
|
|
33
|
+
{steps.map((s) => (
|
|
34
|
+
<li
|
|
35
|
+
key={s.label}
|
|
36
|
+
className="flex items-center gap-8 min-h-(--space-40) border-b border-border-subtle last:border-b-0"
|
|
37
|
+
>
|
|
38
|
+
<span className={s.done ? "text-success" : "text-text-tertiary"}>
|
|
39
|
+
<Icon
|
|
40
|
+
name={s.done ? "CircleCheck" : "Circle"}
|
|
41
|
+
{...(s.done ? { label: t("action.done") } : {})}
|
|
42
|
+
/>
|
|
43
|
+
</span>
|
|
44
|
+
<span className={cx("flex-1", s.done && "text-text-secondary line-through")}>
|
|
45
|
+
{s.label}
|
|
46
|
+
</span>
|
|
47
|
+
{!s.done && s.action ? (
|
|
48
|
+
<Button size="sm" onClick={() => onAction?.(s.label)}>
|
|
49
|
+
{s.action}
|
|
50
|
+
</Button>
|
|
51
|
+
) : null}
|
|
52
|
+
</li>
|
|
53
|
+
))}
|
|
54
|
+
</ol>
|
|
55
|
+
</Card>
|
|
56
|
+
);
|
|
57
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { type ReactElement } from "react";
|
|
2
|
+
import { cx } from "../lib/cx.ts";
|
|
3
|
+
import { useT } from "../lib/context.tsx";
|
|
4
|
+
import { Icon } from "../Icon/Icon.tsx";
|
|
5
|
+
import { Button } from "../Button/Button.tsx";
|
|
6
|
+
import { Keys } from "../Kbd/Kbd.tsx";
|
|
7
|
+
import { ScrollRegion } from "../Layout/Layout.tsx";
|
|
8
|
+
import { type ShortcutEditorProps } from "./Help.types.ts";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Every action's shortcut with conflicts named in place; Change records new keys, Reset restores a
|
|
12
|
+
* custom one. An action without keys reads Not set.
|
|
13
|
+
*/
|
|
14
|
+
export function ShortcutEditor({
|
|
15
|
+
label,
|
|
16
|
+
rows,
|
|
17
|
+
onChange,
|
|
18
|
+
onReset,
|
|
19
|
+
}: ShortcutEditorProps): ReactElement {
|
|
20
|
+
const t = useT();
|
|
21
|
+
const th = cx(
|
|
22
|
+
"h-control-lg px-12 text-start font-medium text-text-12 text-text-secondary bg-bg-surface border-b border-border-subtle",
|
|
23
|
+
);
|
|
24
|
+
const td = cx("h-row-default px-12 border-b border-border-subtle");
|
|
25
|
+
return (
|
|
26
|
+
<ScrollRegion label={label ?? t("shortcuts.title")}>
|
|
27
|
+
<table className="w-full border-collapse text-text-13">
|
|
28
|
+
<thead>
|
|
29
|
+
<tr>
|
|
30
|
+
<th scope="col" className={th}>
|
|
31
|
+
{t("shortcutEditor.action")}
|
|
32
|
+
</th>
|
|
33
|
+
<th scope="col" className={th}>
|
|
34
|
+
{t("shortcutEditor.shortcut")}
|
|
35
|
+
</th>
|
|
36
|
+
<th scope="col" className={th}>
|
|
37
|
+
<span className="sr-only">{t("shortcutEditor.edit")}</span>
|
|
38
|
+
</th>
|
|
39
|
+
</tr>
|
|
40
|
+
</thead>
|
|
41
|
+
<tbody>
|
|
42
|
+
{rows.map((r) => (
|
|
43
|
+
<tr key={r.action}>
|
|
44
|
+
<td className={td}>{r.action}</td>
|
|
45
|
+
<td className={td}>
|
|
46
|
+
<span className="inline-flex flex-wrap items-center gap-8">
|
|
47
|
+
{r.keys.trim() === "" ? (
|
|
48
|
+
<span className="text-text-secondary">{t("shortcutEditor.none")}</span>
|
|
49
|
+
) : (
|
|
50
|
+
<Keys keys={r.keys} />
|
|
51
|
+
)}
|
|
52
|
+
{r.conflict ? (
|
|
53
|
+
<span className="inline-flex items-center gap-4 text-text-12 text-danger-text">
|
|
54
|
+
<Icon name="alert" size={12} />
|
|
55
|
+
{r.conflict}
|
|
56
|
+
</span>
|
|
57
|
+
) : null}
|
|
58
|
+
</span>
|
|
59
|
+
</td>
|
|
60
|
+
<td className={cx(td, "text-end whitespace-nowrap")}>
|
|
61
|
+
<Button
|
|
62
|
+
size="sm"
|
|
63
|
+
variant="ghost"
|
|
64
|
+
aria-pressed={r.recording ?? false}
|
|
65
|
+
onClick={() => onChange?.(r.action)}
|
|
66
|
+
>
|
|
67
|
+
{r.recording ? t("shortcutEditor.press") : t("shortcutEditor.change")}
|
|
68
|
+
</Button>
|
|
69
|
+
{r.custom ? (
|
|
70
|
+
<Button size="sm" variant="ghost" onClick={() => onReset?.(r.action)}>
|
|
71
|
+
{t("action.reset")}
|
|
72
|
+
</Button>
|
|
73
|
+
) : null}
|
|
74
|
+
</td>
|
|
75
|
+
</tr>
|
|
76
|
+
))}
|
|
77
|
+
</tbody>
|
|
78
|
+
</table>
|
|
79
|
+
</ScrollRegion>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { type ReactElement } from "react";
|
|
2
|
+
import { useT } from "../lib/context.tsx";
|
|
3
|
+
import { Tag } from "../Chips/Chips.tsx";
|
|
4
|
+
import { cardBodyClass, cardClass, cardHeadClass } from "../Surface/Surface.tsx";
|
|
5
|
+
import { linkClass } from "../Link/Link.tsx";
|
|
6
|
+
import { type WhatsNewProps } from "./Help.types.ts";
|
|
7
|
+
|
|
8
|
+
/** Recent changes with a link to the full changelog. */
|
|
9
|
+
export function WhatsNew({ changelogHref, entries }: WhatsNewProps): ReactElement {
|
|
10
|
+
const t = useT();
|
|
11
|
+
return (
|
|
12
|
+
<section aria-label={t("whatsNew.title")} className={cardClass}>
|
|
13
|
+
<header className={cardHeadClass}>
|
|
14
|
+
<h2 className="m-0 text-text-13 font-semibold">{t("whatsNew.title")}</h2>
|
|
15
|
+
<a href={changelogHref} className={linkClass}>
|
|
16
|
+
{t("whatsNew.changelog")}
|
|
17
|
+
</a>
|
|
18
|
+
</header>
|
|
19
|
+
<div className={cardBodyClass}>
|
|
20
|
+
{entries.map((e) => (
|
|
21
|
+
<article key={e.title} className="flex flex-col gap-4">
|
|
22
|
+
<div className="flex items-center gap-6">
|
|
23
|
+
<Tag tone={e.tone ?? "accent"}>{e.label}</Tag>
|
|
24
|
+
<span className="text-text-secondary">{e.date}</span>
|
|
25
|
+
</div>
|
|
26
|
+
<h3 className="m-0 text-text-13 font-semibold">{e.title}</h3>
|
|
27
|
+
<p className="m-0 text-text-secondary">{e.body}</p>
|
|
28
|
+
</article>
|
|
29
|
+
))}
|
|
30
|
+
</div>
|
|
31
|
+
</section>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# HelpPanel
|
|
2
|
+
|
|
3
|
+
HelpPanel opens with the Help button or `?` in every shell: articles for the current page, shortcuts, the assistant (when the org turns it on), What's New and Contact Support.
|
|
4
|
+
|
|
5
|
+
- Articles are mapped by route in the help content; canon terms open their Bible definition in a hover card.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { ReactElement } from "react";
|
|
2
|
+
import type { IconProps as ReferenceIconProps } from "../types/reference";
|
|
3
|
+
import { cx } from "../lib/cx.ts";
|
|
4
|
+
import { iconSpriteUrl, iconSymbol, isMirrored } from "../lib/icons.ts";
|
|
5
|
+
|
|
6
|
+
export type IconProps = ReferenceIconProps;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Draws a registered lucide icon at 1.5 stroke, sized from the icon tokens (16 by default), from the
|
|
10
|
+
* cached icon sprite (`<use href>`, ADR 0027), so no icon geometry ships in page JavaScript.
|
|
11
|
+
* Decorative unless `label` says the icon carries meaning alone; a labelled icon is an image named
|
|
12
|
+
* by its title.
|
|
13
|
+
*/
|
|
14
|
+
export function Icon({
|
|
15
|
+
name,
|
|
16
|
+
size = 16,
|
|
17
|
+
label,
|
|
18
|
+
color,
|
|
19
|
+
className,
|
|
20
|
+
strokeWidth = 1.5,
|
|
21
|
+
}: IconProps): ReactElement {
|
|
22
|
+
const a11y = label ? { role: "img", "aria-label": label } : { "aria-hidden": true as const };
|
|
23
|
+
return (
|
|
24
|
+
<svg
|
|
25
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
26
|
+
width={size}
|
|
27
|
+
height={size}
|
|
28
|
+
viewBox="0 0 24 24"
|
|
29
|
+
fill="none"
|
|
30
|
+
stroke="currentColor"
|
|
31
|
+
strokeWidth={strokeWidth}
|
|
32
|
+
strokeLinecap="round"
|
|
33
|
+
strokeLinejoin="round"
|
|
34
|
+
focusable="false"
|
|
35
|
+
{...a11y}
|
|
36
|
+
className={cx(
|
|
37
|
+
"inline-block flex-none align-middle",
|
|
38
|
+
isMirrored(name) && "xos-flip-rtl",
|
|
39
|
+
className,
|
|
40
|
+
)}
|
|
41
|
+
style={color === undefined ? undefined : { color }}
|
|
42
|
+
>
|
|
43
|
+
{label ? <title>{label}</title> : null}
|
|
44
|
+
<use href={`${iconSpriteUrl}#${iconSymbol(name)}`} />
|
|
45
|
+
</svg>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Icon
|
|
2
|
+
|
|
3
|
+
Icon draws a registered lucide icon at 1.5 stroke, sized from the `icon-*` tokens.
|
|
4
|
+
|
|
5
|
+
- `name` takes PascalCase (`Hammer`) or kebab-case (`chevron-right`); a few short aliases are kept: `more`, `alert`, `check-circle`, `pin`, `home`, `undo`.
|
|
6
|
+
- Icons inherit `currentColor`. Pass `label` only when the icon carries meaning alone: the icon is then an image named by its label and a `<title>`. Otherwise it is hidden from screen readers.
|
|
7
|
+
- Icons draw from one SVG sprite (`@xos/icons/sprite.svg`) with `<use href>`, so no icon geometry ships in page JavaScript (ADR 0027). The bundler emits the sprite with a content hash under `/_next/static/media`, and browsers cache it as a static asset.
|
|
8
|
+
- Names come from the `@xos/icons` registry, the closed set the sprite is built from (RRR-70). To draw a new icon by name, add it to `packages/icons/registry/<owner>.txt` and run `pnpm --filter @xos/icons generate:registry`, which rewrites the sprite too. A name outside the registry renders an empty square of the same size and, in development, logs one console warning.
|
|
9
|
+
- For canon objects use DepartmentGlyph, PhaseGlyph and RecordKindGlyph so the assignment stays in one place.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# IconButton
|
|
2
|
+
|
|
3
|
+
IconButton is a square 28 px control with a single 16 px icon and a required accessible label.
|
|
4
|
+
|
|
5
|
+
- `label` becomes `aria-label` and the tooltip text; `shortcut` is appended to the tooltip.
|
|
6
|
+
- Use only for well-known actions (close, more, search, add). Anything else gets a text Button.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type ReactElement } from "react";
|
|
2
|
+
import { useT } from "../lib/context.tsx";
|
|
3
|
+
import { BrandSlotFrame } from "./BrandSlotFrame.tsx";
|
|
4
|
+
import { type BrandSlotProps } from "./Identity.types.ts";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Marks where a tenant uploads a brand file, drawn in proportion (at most 160 by 148) with its
|
|
8
|
+
* delivery size and formats.
|
|
9
|
+
*/
|
|
10
|
+
export function BrandSlot({ width, height, ...slot }: BrandSlotProps): ReactElement {
|
|
11
|
+
const t = useT();
|
|
12
|
+
return (
|
|
13
|
+
<BrandSlotFrame
|
|
14
|
+
{...slot}
|
|
15
|
+
width={width}
|
|
16
|
+
height={height}
|
|
17
|
+
sizeLabel={t("brand.size", { width, height })}
|
|
18
|
+
/>
|
|
19
|
+
);
|
|
20
|
+
}
|