@sovereignfs/ui 0.54.0 → 0.89.1
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 +373 -661
- package/NOTICE +8 -0
- package/README.md +4 -6
- package/dist/Accordion.module.css +1 -1
- package/dist/Alert.module.css +1 -1
- package/dist/AppsLauncher.module.css +102 -0
- package/dist/Avatar.module.css +1 -1
- package/dist/Badge.module.css +30 -7
- package/dist/BalanceChip.module.css +1 -1
- package/dist/Button.module.css +23 -2
- package/dist/Card.module.css +7 -1
- package/dist/CardTile.module.css +187 -0
- package/dist/CheckableListRow.module.css +8 -0
- package/dist/Checkbox.module.css +8 -0
- package/dist/CodeTextarea.module.css +7 -1
- package/dist/Collapsible.module.css +1 -1
- package/dist/ColorPicker.module.css +138 -0
- package/dist/Combobox.module.css +8 -2
- package/dist/Command.module.css +7 -1
- package/dist/ConfirmDialog.module.css +8 -2
- package/dist/ConsentPrompt.module.css +21 -0
- package/dist/DatePicker.module.css +7 -1
- package/dist/Dialog.module.css +130 -21
- package/dist/DragHandleRow.module.css +6 -0
- package/dist/Drawer.module.css +36 -7
- package/dist/FileDropzone.module.css +25 -1
- package/dist/Header.module.css +68 -0
- package/dist/HeaderFooterLayout.module.css +21 -0
- package/dist/IconPicker.module.css +15 -5
- package/dist/Input.module.css +7 -1
- package/dist/Kbd.module.css +1 -1
- package/dist/LegalLinks.module.css +9 -2
- package/dist/Markdown.module.css +29 -0
- package/dist/Menu.module.css +1 -0
- package/dist/Message.module.css +10 -1
- package/dist/MessageScroller.module.css +12 -1
- package/dist/MobileAppsDrawer.module.css +19 -14
- package/dist/MobileFooter.module.css +7 -1
- package/dist/MobileHeader.module.css +14 -1
- package/dist/NavList.module.css +139 -0
- package/dist/NavTabs.module.css +8 -2
- package/dist/NotificationsPanel.module.css +268 -0
- package/dist/OverlayHeader.module.css +1 -1
- package/dist/PageContainer.module.css +62 -0
- package/dist/PageHeader.module.css +54 -0
- package/dist/PageLayout.module.css +51 -0
- package/dist/Popover.module.css +1 -1
- package/dist/QrCode.module.css +17 -0
- package/dist/QuantityStepper.module.css +5 -3
- package/dist/RadioGroup.module.css +6 -0
- package/dist/Resizable.module.css +3 -3
- package/dist/RootLayout.module.css +12 -0
- package/dist/SegmentedControl.module.css +7 -1
- package/dist/Select.module.css +7 -1
- package/dist/Sheet.module.css +20 -2
- package/dist/SplitPane.module.css +5 -5
- package/dist/StatusBadge.module.css +1 -1
- package/dist/StepStrip.module.css +55 -0
- package/dist/SuggestionInput.module.css +14 -3
- package/dist/SwipableMobileCarousel.module.css +12 -3
- package/dist/SwipableMobileCarouselDots.module.css +21 -0
- package/dist/SwipeStack.module.css +101 -0
- package/dist/SystemBanner.module.css +16 -0
- package/dist/Table.module.css +2 -2
- package/dist/Tabs.module.css +7 -1
- package/dist/TagInput.module.css +8 -2
- package/dist/Textarea.module.css +15 -1
- package/dist/ThreeColumnLayout.module.css +35 -0
- package/dist/Toast.module.css +67 -3
- package/dist/Toggle.module.css +7 -0
- package/dist/Tooltip.module.css +7 -1
- package/dist/UserMenu.module.css +95 -0
- package/dist/fonts/OFL.txt +93 -0
- package/dist/fonts/hanken-grotesk-cyrillic-ext-wght-normal.woff2 +0 -0
- package/dist/fonts/hanken-grotesk-latin-ext-wght-normal.woff2 +0 -0
- package/dist/fonts/hanken-grotesk-latin-wght-normal.woff2 +0 -0
- package/dist/fonts/hanken-grotesk-vietnamese-wght-normal.woff2 +0 -0
- package/dist/index.d.ts +1156 -76
- package/dist/index.js +4223 -1513
- package/dist/tokens/fonts.css +53 -0
- package/dist/tokens/primitives.css +23 -12
- package/dist/tokens/semantic.css +32 -0
- package/dist/tokens/theme-presets.css +33 -0
- package/dist/tokens.css +2 -1
- package/package.json +46 -19
- package/src/__tests__/motion.test.tsx +0 -105
- package/src/components/Accordion/Accordion.module.css +0 -3
- package/src/components/Accordion/Accordion.stories.tsx +0 -110
- package/src/components/Accordion/Accordion.tsx +0 -53
- package/src/components/Accordion/__tests__/Accordion.test.tsx +0 -61
- package/src/components/Alert/Alert.module.css +0 -62
- package/src/components/Alert/Alert.stories.tsx +0 -96
- package/src/components/Alert/Alert.tsx +0 -58
- package/src/components/Alert/__tests__/Alert.test.tsx +0 -75
- package/src/components/AspectRatio/AspectRatio.module.css +0 -15
- package/src/components/AspectRatio/AspectRatio.stories.tsx +0 -78
- package/src/components/AspectRatio/AspectRatio.tsx +0 -21
- package/src/components/AspectRatio/__tests__/AspectRatio.test.tsx +0 -27
- package/src/components/Avatar/Avatar.module.css +0 -38
- package/src/components/Avatar/Avatar.tsx +0 -42
- package/src/components/Badge/Badge.module.css +0 -154
- package/src/components/Badge/Badge.stories.tsx +0 -226
- package/src/components/Badge/Badge.tsx +0 -81
- package/src/components/Badge/__tests__/Badge.test.tsx +0 -88
- package/src/components/BalanceChip/BalanceChip.module.css +0 -32
- package/src/components/BalanceChip/BalanceChip.stories.tsx +0 -45
- package/src/components/BalanceChip/BalanceChip.tsx +0 -33
- package/src/components/Breadcrumb/Breadcrumb.module.css +0 -49
- package/src/components/Breadcrumb/Breadcrumb.stories.tsx +0 -47
- package/src/components/Breadcrumb/Breadcrumb.tsx +0 -57
- package/src/components/Breadcrumb/__tests__/Breadcrumb.test.tsx +0 -52
- package/src/components/Button/Button.module.css +0 -153
- package/src/components/Button/Button.stories.tsx +0 -83
- package/src/components/Button/Button.tsx +0 -52
- package/src/components/Button/__tests__/Button.test.tsx +0 -66
- package/src/components/ButtonGroup/ButtonGroup.module.css +0 -29
- package/src/components/ButtonGroup/ButtonGroup.stories.tsx +0 -57
- package/src/components/ButtonGroup/ButtonGroup.tsx +0 -27
- package/src/components/ButtonGroup/__tests__/ButtonGroup.test.tsx +0 -29
- package/src/components/Calendar/Calendar.module.css +0 -126
- package/src/components/Calendar/Calendar.tsx +0 -213
- package/src/components/Calendar/__tests__/Calendar.test.tsx +0 -98
- package/src/components/Calendar/dateUtils.ts +0 -97
- package/src/components/Card/Card.module.css +0 -42
- package/src/components/Card/Card.tsx +0 -34
- package/src/components/CheckableListRow/CheckableListRow.module.css +0 -95
- package/src/components/CheckableListRow/CheckableListRow.stories.tsx +0 -99
- package/src/components/CheckableListRow/CheckableListRow.tsx +0 -89
- package/src/components/Checkbox/Checkbox.module.css +0 -111
- package/src/components/Checkbox/Checkbox.tsx +0 -78
- package/src/components/CodeTextarea/CodeTextarea.module.css +0 -53
- package/src/components/CodeTextarea/CodeTextarea.stories.tsx +0 -77
- package/src/components/CodeTextarea/CodeTextarea.tsx +0 -36
- package/src/components/Collapsible/Collapsible.module.css +0 -70
- package/src/components/Collapsible/Collapsible.stories.tsx +0 -62
- package/src/components/Collapsible/Collapsible.tsx +0 -66
- package/src/components/Collapsible/__tests__/Collapsible.test.tsx +0 -71
- package/src/components/Combobox/Combobox.module.css +0 -122
- package/src/components/Combobox/Combobox.stories.tsx +0 -79
- package/src/components/Combobox/Combobox.tsx +0 -186
- package/src/components/Combobox/__tests__/Combobox.test.tsx +0 -158
- package/src/components/Command/Command.module.css +0 -80
- package/src/components/Command/Command.stories.tsx +0 -104
- package/src/components/Command/Command.tsx +0 -168
- package/src/components/Command/__tests__/Command.test.tsx +0 -162
- package/src/components/ConfirmDialog/ConfirmDialog.module.css +0 -113
- package/src/components/ConfirmDialog/ConfirmDialog.tsx +0 -124
- package/src/components/ConfirmDialog/__tests__/ConfirmDialog.test.tsx +0 -146
- package/src/components/ContextMenu/ContextMenu.stories.tsx +0 -81
- package/src/components/ContextMenu/ContextMenu.tsx +0 -100
- package/src/components/ContextMenu/__tests__/ContextMenu.test.tsx +0 -87
- package/src/components/CurrencyInput/CurrencyInput.stories.tsx +0 -50
- package/src/components/CurrencyInput/CurrencyInput.tsx +0 -60
- package/src/components/DataTable/DataTable.module.css +0 -28
- package/src/components/DataTable/DataTable.stories.tsx +0 -74
- package/src/components/DataTable/DataTable.tsx +0 -154
- package/src/components/DataTable/__tests__/DataTable.test.tsx +0 -123
- package/src/components/DatePicker/DatePicker.module.css +0 -61
- package/src/components/DatePicker/DatePicker.tsx +0 -103
- package/src/components/DatePicker/__tests__/DatePicker.test.tsx +0 -89
- package/src/components/DeviceOnlyGate/DeviceOnlyGate.tsx +0 -58
- package/src/components/DeviceOnlyGate/__tests__/DeviceOnlyGate.test.tsx +0 -45
- package/src/components/DeviceStorageKeyGate/DeviceStorageKeyGate.tsx +0 -100
- package/src/components/DeviceStorageKeyGate/__tests__/DeviceStorageKeyGate.test.tsx +0 -119
- package/src/components/Dialog/Dialog.module.css +0 -226
- package/src/components/Dialog/Dialog.stories.tsx +0 -147
- package/src/components/Dialog/Dialog.tsx +0 -160
- package/src/components/Dialog/__tests__/Dialog.test.tsx +0 -137
- package/src/components/DragHandleRow/DragHandleRow.module.css +0 -57
- package/src/components/DragHandleRow/DragHandleRow.tsx +0 -61
- package/src/components/Drawer/Drawer.module.css +0 -92
- package/src/components/Drawer/Drawer.stories.tsx +0 -132
- package/src/components/Drawer/Drawer.tsx +0 -176
- package/src/components/Drawer/__tests__/Drawer.test.tsx +0 -199
- package/src/components/EmptyState/EmptyState.module.css +0 -27
- package/src/components/EmptyState/EmptyState.tsx +0 -27
- package/src/components/FileDropzone/FileDropzone.module.css +0 -63
- package/src/components/FileDropzone/FileDropzone.tsx +0 -109
- package/src/components/FileDropzone/__tests__/FileDropzone.test.tsx +0 -67
- package/src/components/FormField/FormField.module.css +0 -33
- package/src/components/FormField/FormField.tsx +0 -78
- package/src/components/FormField/__tests__/FormField.test.tsx +0 -83
- package/src/components/HoverCard/HoverCard.module.css +0 -3
- package/src/components/HoverCard/HoverCard.stories.tsx +0 -66
- package/src/components/HoverCard/HoverCard.tsx +0 -111
- package/src/components/HoverCard/__tests__/HoverCard.test.tsx +0 -99
- package/src/components/Icon/Icon.module.css +0 -27
- package/src/components/Icon/Icon.stories.tsx +0 -95
- package/src/components/Icon/Icon.tsx +0 -43
- package/src/components/Icon/__tests__/Icon.test.tsx +0 -40
- package/src/components/Icon/icons/activity.tsx +0 -20
- package/src/components/Icon/icons/alert-triangle.tsx +0 -22
- package/src/components/Icon/icons/apple.tsx +0 -21
- package/src/components/Icon/icons/banana.tsx +0 -21
- package/src/components/Icon/icons/beef.tsx +0 -22
- package/src/components/Icon/icons/beer.tsx +0 -24
- package/src/components/Icon/icons/bell.tsx +0 -21
- package/src/components/Icon/icons/calendar.tsx +0 -23
- package/src/components/Icon/icons/candy.tsx +0 -24
- package/src/components/Icon/icons/carrot.tsx +0 -22
- package/src/components/Icon/icons/check.tsx +0 -20
- package/src/components/Icon/icons/chevron-down.tsx +0 -20
- package/src/components/Icon/icons/chevron-left.tsx +0 -20
- package/src/components/Icon/icons/chevron-right.tsx +0 -20
- package/src/components/Icon/icons/chevron-up.tsx +0 -20
- package/src/components/Icon/icons/circle-check.tsx +0 -21
- package/src/components/Icon/icons/circle-x.tsx +0 -22
- package/src/components/Icon/icons/coffee.tsx +0 -23
- package/src/components/Icon/icons/cookie.tsx +0 -25
- package/src/components/Icon/icons/croissant.tsx +0 -24
- package/src/components/Icon/icons/cup-soda.tsx +0 -23
- package/src/components/Icon/icons/drumstick.tsx +0 -21
- package/src/components/Icon/icons/egg.tsx +0 -20
- package/src/components/Icon/icons/ellipsis-vertical.tsx +0 -22
- package/src/components/Icon/icons/external-link.tsx +0 -22
- package/src/components/Icon/icons/eye-off.tsx +0 -23
- package/src/components/Icon/icons/eye.tsx +0 -21
- package/src/components/Icon/icons/file.tsx +0 -21
- package/src/components/Icon/icons/fish.tsx +0 -25
- package/src/components/Icon/icons/grid-2x2.tsx +0 -22
- package/src/components/Icon/icons/house.tsx +0 -21
- package/src/components/Icon/icons/index.ts +0 -234
- package/src/components/Icon/icons/info.tsx +0 -22
- package/src/components/Icon/icons/lock.tsx +0 -21
- package/src/components/Icon/icons/log-out.tsx +0 -22
- package/src/components/Icon/icons/mail.tsx +0 -21
- package/src/components/Icon/icons/menu.tsx +0 -22
- package/src/components/Icon/icons/milk.tsx +0 -22
- package/src/components/Icon/icons/package.tsx +0 -23
- package/src/components/Icon/icons/pencil.tsx +0 -21
- package/src/components/Icon/icons/pizza.tsx +0 -24
- package/src/components/Icon/icons/plus.tsx +0 -21
- package/src/components/Icon/icons/rotate-ccw.tsx +0 -21
- package/src/components/Icon/icons/salad.tsx +0 -24
- package/src/components/Icon/icons/search.tsx +0 -21
- package/src/components/Icon/icons/settings.tsx +0 -21
- package/src/components/Icon/icons/shield.tsx +0 -20
- package/src/components/Icon/icons/shopping-basket.tsx +0 -26
- package/src/components/Icon/icons/sliders-horizontal.tsx +0 -28
- package/src/components/Icon/icons/smartphone.tsx +0 -21
- package/src/components/Icon/icons/snowflake.tsx +0 -31
- package/src/components/Icon/icons/spray-can.tsx +0 -29
- package/src/components/Icon/icons/trash-2.tsx +0 -24
- package/src/components/Icon/icons/upload.tsx +0 -22
- package/src/components/Icon/icons/user.tsx +0 -21
- package/src/components/Icon/icons/wine.tsx +0 -23
- package/src/components/Icon/icons/x.tsx +0 -21
- package/src/components/IconPicker/IconPicker.module.css +0 -63
- package/src/components/IconPicker/IconPicker.stories.tsx +0 -84
- package/src/components/IconPicker/IconPicker.tsx +0 -90
- package/src/components/Input/Input.module.css +0 -52
- package/src/components/Input/Input.stories.tsx +0 -86
- package/src/components/Input/Input.tsx +0 -14
- package/src/components/Input/__tests__/Input.test.tsx +0 -22
- package/src/components/Item/Item.module.css +0 -70
- package/src/components/Item/Item.stories.tsx +0 -62
- package/src/components/Item/Item.tsx +0 -54
- package/src/components/Item/__tests__/Item.test.tsx +0 -39
- package/src/components/Kbd/Kbd.module.css +0 -14
- package/src/components/Kbd/Kbd.stories.tsx +0 -32
- package/src/components/Kbd/Kbd.tsx +0 -12
- package/src/components/Kbd/__tests__/Kbd.test.tsx +0 -14
- package/src/components/Label/Label.module.css +0 -11
- package/src/components/Label/Label.stories.tsx +0 -40
- package/src/components/Label/Label.tsx +0 -24
- package/src/components/Label/__tests__/Label.test.tsx +0 -32
- package/src/components/LegalLinks/LegalLinks.module.css +0 -24
- package/src/components/LegalLinks/LegalLinks.stories.tsx +0 -22
- package/src/components/LegalLinks/LegalLinks.tsx +0 -40
- package/src/components/Markdown/Markdown.module.css +0 -49
- package/src/components/Markdown/Markdown.stories.tsx +0 -30
- package/src/components/Markdown/Markdown.tsx +0 -168
- package/src/components/Marker/Marker.module.css +0 -33
- package/src/components/Marker/Marker.stories.tsx +0 -39
- package/src/components/Marker/Marker.tsx +0 -34
- package/src/components/Marker/__tests__/Marker.test.tsx +0 -23
- package/src/components/MemberMultiSelect/MemberMultiSelect.module.css +0 -27
- package/src/components/MemberMultiSelect/MemberMultiSelect.stories.tsx +0 -74
- package/src/components/MemberMultiSelect/MemberMultiSelect.tsx +0 -67
- package/src/components/Menu/Menu.module.css +0 -89
- package/src/components/Menu/Menu.tsx +0 -159
- package/src/components/Menu/__tests__/Menu.test.tsx +0 -197
- package/src/components/Menubar/Menubar.stories.tsx +0 -52
- package/src/components/Menubar/Menubar.tsx +0 -42
- package/src/components/Menubar/__tests__/Menubar.test.tsx +0 -45
- package/src/components/Message/Message.module.css +0 -99
- package/src/components/Message/Message.stories.tsx +0 -79
- package/src/components/Message/Message.tsx +0 -41
- package/src/components/Message/__tests__/Message.test.tsx +0 -46
- package/src/components/MessageScroller/MessageScroller.module.css +0 -54
- package/src/components/MessageScroller/MessageScroller.stories.tsx +0 -84
- package/src/components/MessageScroller/MessageScroller.tsx +0 -72
- package/src/components/MessageScroller/__tests__/MessageScroller.test.tsx +0 -105
- package/src/components/MobileAppsDrawer/MobileAppsDrawer.module.css +0 -81
- package/src/components/MobileAppsDrawer/MobileAppsDrawer.tsx +0 -78
- package/src/components/MobileAppsDrawer/__tests__/MobileAppsDrawer.test.tsx +0 -80
- package/src/components/MobileFooter/MobileFooter.module.css +0 -73
- package/src/components/MobileFooter/MobileFooter.stories.tsx +0 -47
- package/src/components/MobileFooter/MobileFooter.tsx +0 -109
- package/src/components/MobileFooter/__tests__/MobileFooter.test.tsx +0 -71
- package/src/components/MobileHeader/MobileHeader.module.css +0 -63
- package/src/components/MobileHeader/MobileHeader.stories.tsx +0 -57
- package/src/components/MobileHeader/MobileHeader.tsx +0 -77
- package/src/components/MobileHeader/__tests__/MobileHeader.test.tsx +0 -58
- package/src/components/NavTabs/NavTabs.module.css +0 -50
- package/src/components/NavTabs/NavTabs.tsx +0 -61
- package/src/components/NavigationMenu/NavigationMenu.module.css +0 -53
- package/src/components/NavigationMenu/NavigationMenu.stories.tsx +0 -58
- package/src/components/NavigationMenu/NavigationMenu.tsx +0 -125
- package/src/components/NavigationMenu/__tests__/NavigationMenu.test.tsx +0 -93
- package/src/components/OfflineGate/OfflineGate.tsx +0 -44
- package/src/components/OfflineGate/__tests__/OfflineGate.test.tsx +0 -66
- package/src/components/OverlayHeader/OverlayHeader.module.css +0 -98
- package/src/components/OverlayHeader/OverlayHeader.tsx +0 -62
- package/src/components/OverlayHeader/__tests__/OverlayHeader.test.tsx +0 -51
- package/src/components/PageContainer/PageContainer.module.css +0 -20
- package/src/components/PageContainer/PageContainer.tsx +0 -31
- package/src/components/PageContainer/__tests__/PageContainer.test.tsx +0 -37
- package/src/components/PageHeader/PageHeader.module.css +0 -32
- package/src/components/PageHeader/PageHeader.tsx +0 -35
- package/src/components/Pagination/Pagination.module.css +0 -98
- package/src/components/Pagination/Pagination.stories.tsx +0 -49
- package/src/components/Pagination/Pagination.tsx +0 -87
- package/src/components/Pagination/__tests__/Pagination.test.tsx +0 -56
- package/src/components/Popover/Popover.module.css +0 -74
- package/src/components/Popover/Popover.stories.tsx +0 -357
- package/src/components/Popover/Popover.tsx +0 -208
- package/src/components/Popover/__tests__/Popover.test.tsx +0 -98
- package/src/components/Progress/Progress.module.css +0 -20
- package/src/components/Progress/Progress.stories.tsx +0 -40
- package/src/components/Progress/Progress.tsx +0 -35
- package/src/components/Progress/__tests__/Progress.test.tsx +0 -31
- package/src/components/QuantityStepper/QuantityStepper.module.css +0 -67
- package/src/components/QuantityStepper/QuantityStepper.stories.tsx +0 -79
- package/src/components/QuantityStepper/QuantityStepper.tsx +0 -107
- package/src/components/RadioGroup/RadioGroup.module.css +0 -88
- package/src/components/RadioGroup/RadioGroup.stories.tsx +0 -69
- package/src/components/RadioGroup/RadioGroup.tsx +0 -99
- package/src/components/RadioGroup/__tests__/RadioGroup.test.tsx +0 -59
- package/src/components/Resizable/Resizable.module.css +0 -70
- package/src/components/Resizable/Resizable.stories.tsx +0 -82
- package/src/components/Resizable/Resizable.tsx +0 -313
- package/src/components/Resizable/__tests__/Resizable.test.tsx +0 -128
- package/src/components/ResponsiveSurface/ResponsiveSurface.tsx +0 -24
- package/src/components/ResponsiveSurface/__tests__/ResponsiveSurface.test.tsx +0 -73
- package/src/components/ScrollArea/ScrollArea.module.css +0 -20
- package/src/components/ScrollArea/ScrollArea.stories.tsx +0 -57
- package/src/components/ScrollArea/ScrollArea.tsx +0 -27
- package/src/components/ScrollArea/__tests__/ScrollArea.test.tsx +0 -39
- package/src/components/SegmentedControl/SegmentedControl.module.css +0 -55
- package/src/components/SegmentedControl/SegmentedControl.stories.tsx +0 -118
- package/src/components/SegmentedControl/SegmentedControl.tsx +0 -56
- package/src/components/SegmentedControl/__tests__/SegmentedControl.test.tsx +0 -63
- package/src/components/Select/Select.module.css +0 -82
- package/src/components/Select/Select.stories.tsx +0 -115
- package/src/components/Select/Select.tsx +0 -48
- package/src/components/Select/__tests__/Select.test.tsx +0 -59
- package/src/components/Sheet/Sheet.module.css +0 -55
- package/src/components/Sheet/Sheet.tsx +0 -109
- package/src/components/Sheet/__tests__/Sheet.test.tsx +0 -99
- package/src/components/Slider/Slider.module.css +0 -95
- package/src/components/Slider/Slider.stories.tsx +0 -64
- package/src/components/Slider/Slider.tsx +0 -77
- package/src/components/Slider/__tests__/Slider.test.tsx +0 -45
- package/src/components/Spinner/Spinner.module.css +0 -39
- package/src/components/Spinner/Spinner.tsx +0 -23
- package/src/components/SplitMethodSelector/SplitMethodSelector.stories.tsx +0 -33
- package/src/components/SplitMethodSelector/SplitMethodSelector.tsx +0 -43
- package/src/components/SplitPane/SplitPane.module.css +0 -85
- package/src/components/SplitPane/SplitPane.stories.tsx +0 -160
- package/src/components/SplitPane/SplitPane.tsx +0 -149
- package/src/components/SplitPane/__tests__/SplitPane.test.tsx +0 -51
- package/src/components/StatusBadge/StatusBadge.module.css +0 -59
- package/src/components/StatusBadge/StatusBadge.stories.tsx +0 -74
- package/src/components/StatusBadge/StatusBadge.tsx +0 -65
- package/src/components/SuggestionInput/SuggestionInput.module.css +0 -103
- package/src/components/SuggestionInput/SuggestionInput.stories.tsx +0 -144
- package/src/components/SuggestionInput/SuggestionInput.tsx +0 -207
- package/src/components/SwipableMobileCarousel/SwipableMobileCarousel.module.css +0 -55
- package/src/components/SwipableMobileCarousel/SwipableMobileCarousel.tsx +0 -227
- package/src/components/SwipableMobileCarousel/SwipableMobileCarouselSlide.tsx +0 -35
- package/src/components/SwipableMobileCarousel/SwipableMobileCarouselSlideBody.tsx +0 -42
- package/src/components/SwipableMobileCarousel/SwipableMobileCarouselSlideFooter.tsx +0 -18
- package/src/components/SwipableMobileCarousel/SwipableMobileCarouselSlideHeader.tsx +0 -21
- package/src/components/SwipableMobileCarousel/SwipableMobileCarouselSlideParts.module.css +0 -29
- package/src/components/SwipableMobileCarousel/__tests__/SwipableMobileCarousel.test.tsx +0 -133
- package/src/components/SwipableMobileCarousel/__tests__/SwipableMobileCarouselDevGuard.test.tsx +0 -61
- package/src/components/SwipableMobileCarousel/context.ts +0 -13
- package/src/components/SwipableMobileCarouselDots/SwipableMobileCarouselDots.module.css +0 -49
- package/src/components/SwipableMobileCarouselDots/SwipableMobileCarouselDots.tsx +0 -62
- package/src/components/SwipableMobileCarouselDots/__tests__/SwipableMobileCarouselDots.test.tsx +0 -63
- package/src/components/SystemBanner/SystemBanner.module.css +0 -69
- package/src/components/SystemBanner/SystemBanner.stories.tsx +0 -86
- package/src/components/SystemBanner/SystemBanner.tsx +0 -50
- package/src/components/SystemBanner/__tests__/SystemBanner.test.tsx +0 -50
- package/src/components/Table/Table.module.css +0 -45
- package/src/components/Table/Table.stories.tsx +0 -125
- package/src/components/Table/Table.tsx +0 -51
- package/src/components/Table/__tests__/Table.test.tsx +0 -50
- package/src/components/Tabs/Tabs.module.css +0 -56
- package/src/components/Tabs/Tabs.stories.tsx +0 -100
- package/src/components/Tabs/Tabs.tsx +0 -46
- package/src/components/Tabs/__tests__/Tabs.test.tsx +0 -45
- package/src/components/TagInput/TagInput.module.css +0 -141
- package/src/components/TagInput/TagInput.stories.tsx +0 -109
- package/src/components/TagInput/TagInput.tsx +0 -174
- package/src/components/TagInput/__tests__/TagInput.test.tsx +0 -69
- package/src/components/Textarea/Textarea.module.css +0 -39
- package/src/components/Textarea/Textarea.tsx +0 -15
- package/src/components/Textarea/__tests__/Textarea.test.tsx +0 -29
- package/src/components/Toast/Toast.module.css +0 -132
- package/src/components/Toast/Toast.stories.tsx +0 -191
- package/src/components/Toast/Toast.tsx +0 -139
- package/src/components/Toggle/Toggle.module.css +0 -57
- package/src/components/Toggle/Toggle.stories.tsx +0 -95
- package/src/components/Toggle/Toggle.tsx +0 -39
- package/src/components/Toggle/__tests__/Toggle.test.tsx +0 -47
- package/src/components/Tooltip/Tooltip.module.css +0 -56
- package/src/components/Tooltip/Tooltip.tsx +0 -30
- package/src/components/Typography/Typography.module.css +0 -47
- package/src/components/Typography/Typography.stories.tsx +0 -62
- package/src/components/Typography/Typography.tsx +0 -30
- package/src/components/Typography/__tests__/Typography.test.tsx +0 -34
- package/src/css-modules.d.ts +0 -4
- package/src/hooks/__tests__/useCarouselRouteSync.test.tsx +0 -126
- package/src/hooks/__tests__/useDoubleTap.test.tsx +0 -117
- package/src/hooks/__tests__/useIsMobile.test.tsx +0 -80
- package/src/hooks/__tests__/useIsOffline.test.tsx +0 -53
- package/src/hooks/__tests__/useLongPress.test.tsx +0 -158
- package/src/hooks/__tests__/useOfflineTileState.test.tsx +0 -69
- package/src/hooks/__tests__/useResponsiveLayout.test.tsx +0 -87
- package/src/hooks/__tests__/useSnapCarousel.test.tsx +0 -93
- package/src/hooks/__tests__/useSwipeReveal.test.tsx +0 -110
- package/src/hooks/index.ts +0 -24
- package/src/hooks/useCarouselRouteSync.ts +0 -92
- package/src/hooks/useCommitOnEnterOrBlur.ts +0 -39
- package/src/hooks/useDoubleTap.ts +0 -91
- package/src/hooks/useIsMobile.ts +0 -33
- package/src/hooks/useIsOffline.ts +0 -41
- package/src/hooks/useLongPress.ts +0 -185
- package/src/hooks/useOfflineTileState.ts +0 -45
- package/src/hooks/useResponsiveLayout.ts +0 -36
- package/src/hooks/useSnapCarousel.ts +0 -79
- package/src/hooks/useSwipeReveal.ts +0 -107
- package/src/index.ts +0 -251
- package/src/motion.ts +0 -78
- package/src/overlay-shell.ts +0 -94
- package/src/scroll-lock.ts +0 -22
- package/src/stories/Avatar.stories.tsx +0 -44
- package/src/stories/Card.stories.tsx +0 -35
- package/src/stories/Checkbox.stories.tsx +0 -45
- package/src/stories/DesignSystemOverview.stories.tsx +0 -3187
- package/src/stories/DeviceOnlyGate.stories.tsx +0 -35
- package/src/stories/DeviceStorageKeyGate.stories.tsx +0 -57
- package/src/stories/DragHandleRow.stories.tsx +0 -41
- package/src/stories/EmptyState.stories.tsx +0 -33
- package/src/stories/FileDropzone.stories.tsx +0 -69
- package/src/stories/FormField.stories.tsx +0 -47
- package/src/stories/InteractionHooks.stories.tsx +0 -925
- package/src/stories/MobilePatterns.stories.tsx +0 -1536
- package/src/stories/NavTabs.stories.tsx +0 -53
- package/src/stories/OfflineGate.stories.tsx +0 -42
- package/src/stories/PageContainer.stories.tsx +0 -37
- package/src/stories/PageHeader.stories.tsx +0 -42
- package/src/stories/ResponsiveSurface.stories.tsx +0 -47
- package/src/stories/Spinner.stories.tsx +0 -25
- package/src/stories/SwipableMobileCarousel.stories.tsx +0 -304
- package/src/stories/Textarea.stories.tsx +0 -51
- package/src/stories/TokenGallery.stories.tsx +0 -602
- package/src/stories/Tooltip.stories.tsx +0 -59
- package/src/tokens/primitives.css +0 -157
- package/src/tokens/semantic.css +0 -130
- package/src/tokens.css +0 -5
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
import type { ReactNode } from 'react';
|
|
2
|
-
import { Typography } from '../Typography/Typography';
|
|
3
|
-
import styles from './Markdown.module.css';
|
|
4
|
-
|
|
5
|
-
export interface MarkdownProps {
|
|
6
|
-
/** Raw markdown source. Supports the subset used by Sovereign's own
|
|
7
|
-
* long-form content pages: headings (#/##/###), paragraphs, **bold**,
|
|
8
|
-
* *italic*, `code`, [links](url), unordered lists (-), and blockquotes
|
|
9
|
-
* (>), including soft-wrapped continuation lines within a paragraph or
|
|
10
|
-
* list item. Not a general-purpose CommonMark parser — no tables,
|
|
11
|
-
* images, ordered lists, or nested blocks. */
|
|
12
|
-
content: string;
|
|
13
|
-
className?: string;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
let inlineKey = 0;
|
|
17
|
-
|
|
18
|
-
/** Parses **bold**, *italic*, `code`, and [text](url) within a line of text. */
|
|
19
|
-
function parseInline(text: string): ReactNode[] {
|
|
20
|
-
const nodes: ReactNode[] = [];
|
|
21
|
-
const pattern = /\[([^\]]+)\]\(([^)]+)\)|\*\*([^*]+)\*\*|\*([^*]+)\*|`([^`]+)`/;
|
|
22
|
-
let remaining = text;
|
|
23
|
-
|
|
24
|
-
while (remaining.length > 0) {
|
|
25
|
-
const match = pattern.exec(remaining);
|
|
26
|
-
if (!match) {
|
|
27
|
-
nodes.push(remaining);
|
|
28
|
-
break;
|
|
29
|
-
}
|
|
30
|
-
if (match.index > 0) nodes.push(remaining.slice(0, match.index));
|
|
31
|
-
|
|
32
|
-
const [full, linkText, linkHref, boldText, italicText, codeText] = match;
|
|
33
|
-
const key = `md-inline-${inlineKey++}`;
|
|
34
|
-
if (linkHref !== undefined) {
|
|
35
|
-
nodes.push(
|
|
36
|
-
<a key={key} href={linkHref}>
|
|
37
|
-
{linkText}
|
|
38
|
-
</a>,
|
|
39
|
-
);
|
|
40
|
-
} else if (boldText !== undefined) {
|
|
41
|
-
nodes.push(<strong key={key}>{boldText}</strong>);
|
|
42
|
-
} else if (italicText !== undefined) {
|
|
43
|
-
nodes.push(<em key={key}>{italicText}</em>);
|
|
44
|
-
} else if (codeText !== undefined) {
|
|
45
|
-
nodes.push(<code key={key}>{codeText}</code>);
|
|
46
|
-
}
|
|
47
|
-
remaining = remaining.slice(match.index + full.length);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return nodes;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const isQuote = (l: string) => l.startsWith('> ') || l === '>';
|
|
54
|
-
const isListItem = (l: string) => l.startsWith('- ');
|
|
55
|
-
const isHeading = (l: string) => /^#{1,3}\s+/.test(l);
|
|
56
|
-
/** A line that ends the current *paragraph* run — a blank line, or the
|
|
57
|
-
* start of a heading, quote, or list block. Anything else (including an
|
|
58
|
-
* indented continuation line) is folded into the paragraph, matching how
|
|
59
|
-
* the source markdown soft-wraps prose across lines. */
|
|
60
|
-
const endsParagraph = (l: string) => l.trim() === '' || isHeading(l) || isQuote(l) || isListItem(l);
|
|
61
|
-
/** A line that ends the current *list* run — a blank line, or the start of
|
|
62
|
-
* a heading or quote. Deliberately does NOT include `isListItem`: a list
|
|
63
|
-
* item's own opening line legitimately satisfies `isListItem`, so reusing
|
|
64
|
-
* `endsParagraph` here (which does) would treat the first line of every
|
|
65
|
-
* list as ending the list before it started — the list-collection loop
|
|
66
|
-
* would then never advance, looping forever. */
|
|
67
|
-
const endsList = (l: string) => l.trim() === '' || isHeading(l) || isQuote(l);
|
|
68
|
-
|
|
69
|
-
function parseBlocks(content: string): ReactNode[] {
|
|
70
|
-
const lines = content.replace(/\r\n/g, '\n').split('\n');
|
|
71
|
-
const blocks: ReactNode[] = [];
|
|
72
|
-
let i = 0;
|
|
73
|
-
let blockKey = 0;
|
|
74
|
-
|
|
75
|
-
while (i < lines.length) {
|
|
76
|
-
const line = lines[i] ?? '';
|
|
77
|
-
|
|
78
|
-
if (line.trim() === '') {
|
|
79
|
-
i++;
|
|
80
|
-
continue;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
const heading = /^(#{1,3})\s+(.*)$/.exec(line);
|
|
84
|
-
if (heading) {
|
|
85
|
-
const level = (heading[1]?.length ?? 1) as 1 | 2 | 3;
|
|
86
|
-
blocks.push(
|
|
87
|
-
<div key={blockKey++} className={styles.block} data-heading>
|
|
88
|
-
<Typography variant={`h${level}` as 'h1' | 'h2' | 'h3'}>
|
|
89
|
-
{parseInline(heading[2] ?? '')}
|
|
90
|
-
</Typography>
|
|
91
|
-
</div>,
|
|
92
|
-
);
|
|
93
|
-
i++;
|
|
94
|
-
continue;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
if (isQuote(line)) {
|
|
98
|
-
const quoteLines: string[] = [];
|
|
99
|
-
while (i < lines.length && isQuote(lines[i] ?? '')) {
|
|
100
|
-
quoteLines.push((lines[i] ?? '').slice(2));
|
|
101
|
-
i++;
|
|
102
|
-
}
|
|
103
|
-
blocks.push(
|
|
104
|
-
<div key={blockKey++} className={styles.block}>
|
|
105
|
-
<blockquote className={styles.blockquote}>
|
|
106
|
-
<Typography variant="body" as="p">
|
|
107
|
-
{parseInline(quoteLines.join(' '))}
|
|
108
|
-
</Typography>
|
|
109
|
-
</blockquote>
|
|
110
|
-
</div>,
|
|
111
|
-
);
|
|
112
|
-
continue;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
if (isListItem(line)) {
|
|
116
|
-
const items: string[] = [];
|
|
117
|
-
while (i < lines.length && !endsList(lines[i] ?? '')) {
|
|
118
|
-
const current = lines[i] ?? '';
|
|
119
|
-
if (isListItem(current)) {
|
|
120
|
-
items.push(current.slice(2));
|
|
121
|
-
} else {
|
|
122
|
-
// Continuation of the previous item's wrapped text.
|
|
123
|
-
const lastIndex = items.length - 1;
|
|
124
|
-
items[lastIndex] = `${items[lastIndex] ?? ''} ${current.trim()}`;
|
|
125
|
-
}
|
|
126
|
-
i++;
|
|
127
|
-
}
|
|
128
|
-
blocks.push(
|
|
129
|
-
<div key={blockKey++} className={styles.block}>
|
|
130
|
-
<ul className={styles.list}>
|
|
131
|
-
{items.map((item, idx) => (
|
|
132
|
-
<Typography key={idx} variant="body" as="li">
|
|
133
|
-
{parseInline(item)}
|
|
134
|
-
</Typography>
|
|
135
|
-
))}
|
|
136
|
-
</ul>
|
|
137
|
-
</div>,
|
|
138
|
-
);
|
|
139
|
-
continue;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
const paraLines: string[] = [];
|
|
143
|
-
while (i < lines.length && !endsParagraph(lines[i] ?? '')) {
|
|
144
|
-
paraLines.push((lines[i] ?? '').trim());
|
|
145
|
-
i++;
|
|
146
|
-
}
|
|
147
|
-
blocks.push(
|
|
148
|
-
<div key={blockKey++} className={styles.block}>
|
|
149
|
-
<Typography variant="body" as="p">
|
|
150
|
-
{parseInline(paraLines.join(' '))}
|
|
151
|
-
</Typography>
|
|
152
|
-
</div>,
|
|
153
|
-
);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
return blocks;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
/** Renders a constrained markdown subset (see MarkdownProps) as styled React
|
|
160
|
-
* elements built from Typography — no HTML string injection. Meant for
|
|
161
|
-
* long-form, first-party content pages (privacy policy, terms of service)
|
|
162
|
-
* sourced from a single markdown file, not for rendering arbitrary or
|
|
163
|
-
* user-supplied markdown. */
|
|
164
|
-
export function Markdown({ content, className }: MarkdownProps) {
|
|
165
|
-
return (
|
|
166
|
-
<div className={[styles.root, className].filter(Boolean).join(' ')}>{parseBlocks(content)}</div>
|
|
167
|
-
);
|
|
168
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
.marker {
|
|
2
|
-
display: inline-flex;
|
|
3
|
-
align-items: center;
|
|
4
|
-
justify-content: center;
|
|
5
|
-
min-width: 16px;
|
|
6
|
-
height: 16px;
|
|
7
|
-
padding: 0 4px;
|
|
8
|
-
margin: 0 1px;
|
|
9
|
-
border: none;
|
|
10
|
-
border-radius: var(--sv-radius-full);
|
|
11
|
-
background: var(--sv-color-accent-subtle);
|
|
12
|
-
color: var(--sv-color-accent);
|
|
13
|
-
font-family: var(--sv-font-family);
|
|
14
|
-
font-size: var(--sv-font-size-label);
|
|
15
|
-
font-weight: var(--sv-font-weight-semibold);
|
|
16
|
-
line-height: 1;
|
|
17
|
-
vertical-align: super;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
button.marker {
|
|
21
|
-
cursor: pointer;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
button.marker:focus-visible {
|
|
25
|
-
outline: 2px solid var(--sv-color-focus-ring);
|
|
26
|
-
outline-offset: 1px;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
@media (hover: hover) {
|
|
30
|
-
button.marker:hover {
|
|
31
|
-
background: color-mix(in srgb, var(--sv-color-accent-subtle) 70%, var(--sv-color-accent) 30%);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
-
import { Marker } from './Marker';
|
|
3
|
-
|
|
4
|
-
const meta = {
|
|
5
|
-
title: 'Components/Marker',
|
|
6
|
-
component: Marker,
|
|
7
|
-
parameters: {
|
|
8
|
-
layout: 'padded',
|
|
9
|
-
docs: {
|
|
10
|
-
description: {
|
|
11
|
-
component:
|
|
12
|
-
'Inline citation/reference marker, for attributing part of an assistant answer to a source (Sovereign Harness "source trace").',
|
|
13
|
-
},
|
|
14
|
-
},
|
|
15
|
-
},
|
|
16
|
-
args: { index: 1, label: 'Source: Notes' },
|
|
17
|
-
} satisfies Meta<typeof Marker>;
|
|
18
|
-
|
|
19
|
-
export default meta;
|
|
20
|
-
type Story = StoryObj<typeof meta>;
|
|
21
|
-
|
|
22
|
-
// ---------------------------------------------------------------------------
|
|
23
|
-
|
|
24
|
-
export const Static: Story = {};
|
|
25
|
-
|
|
26
|
-
export const Clickable: Story = {
|
|
27
|
-
args: { onClick: () => {} },
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
export const InContext: Story = {
|
|
31
|
-
render: () => (
|
|
32
|
-
<p style={{ fontSize: 14, maxWidth: 400 }}>
|
|
33
|
-
Your next task deadline is Thursday
|
|
34
|
-
<Marker index={1} label="Source: Tasks" onClick={() => {}} />, and you have two unread
|
|
35
|
-
messages from the team
|
|
36
|
-
<Marker index={2} label="Source: Notes" onClick={() => {}} />.
|
|
37
|
-
</p>
|
|
38
|
-
),
|
|
39
|
-
};
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import styles from './Marker.module.css';
|
|
2
|
-
|
|
3
|
-
export interface MarkerProps {
|
|
4
|
-
/** The number shown in the marker, e.g. 1, 2, 3. */
|
|
5
|
-
index: number;
|
|
6
|
-
/** Accessible label describing the citation, e.g. "Source: Notes". */
|
|
7
|
-
label: string;
|
|
8
|
-
/** Reveals source details (e.g. opens a source trace panel) when given. */
|
|
9
|
-
onClick?: () => void;
|
|
10
|
-
className?: string;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Marker — inline citation/reference marker, for attributing part of an
|
|
15
|
-
* assistant's answer to a source (matches RFC 0040's "source trace" —
|
|
16
|
-
* Harness shows which plugin/data source informed an answer).
|
|
17
|
-
*/
|
|
18
|
-
export function Marker({ index, label, onClick, className }: MarkerProps) {
|
|
19
|
-
const classes = [styles.marker, className].filter(Boolean).join(' ');
|
|
20
|
-
|
|
21
|
-
if (onClick) {
|
|
22
|
-
return (
|
|
23
|
-
<button type="button" onClick={onClick} aria-label={label} className={classes}>
|
|
24
|
-
{index}
|
|
25
|
-
</button>
|
|
26
|
-
);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
return (
|
|
30
|
-
<span aria-label={label} className={classes}>
|
|
31
|
-
{index}
|
|
32
|
-
</span>
|
|
33
|
-
);
|
|
34
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
// @vitest-environment jsdom
|
|
2
|
-
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
3
|
-
import { cleanup, render, screen } from '@testing-library/react';
|
|
4
|
-
import { Marker } from '../Marker';
|
|
5
|
-
|
|
6
|
-
afterEach(cleanup);
|
|
7
|
-
|
|
8
|
-
describe('Marker', () => {
|
|
9
|
-
it('renders as a static span with an accessible label when no onClick is given', () => {
|
|
10
|
-
render(<Marker index={1} label="Source: Notes" />);
|
|
11
|
-
const el = screen.getByLabelText('Source: Notes');
|
|
12
|
-
expect(el.tagName).toBe('SPAN');
|
|
13
|
-
expect(el.textContent).toBe('1');
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
it('renders as a button and fires onClick when given', () => {
|
|
17
|
-
const onClick = vi.fn();
|
|
18
|
-
render(<Marker index={2} label="Source: Tasks" onClick={onClick} />);
|
|
19
|
-
const el = screen.getByRole('button', { name: 'Source: Tasks' });
|
|
20
|
-
el.click();
|
|
21
|
-
expect(onClick).toHaveBeenCalled();
|
|
22
|
-
});
|
|
23
|
-
});
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
.group {
|
|
2
|
-
display: grid;
|
|
3
|
-
gap: var(--sv-space-2);
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
.label {
|
|
7
|
-
font-size: var(--sv-font-size-xs);
|
|
8
|
-
font-weight: var(--sv-font-weight-semibold);
|
|
9
|
-
color: var(--sv-color-text-muted);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
.row {
|
|
13
|
-
display: flex;
|
|
14
|
-
align-items: center;
|
|
15
|
-
justify-content: space-between;
|
|
16
|
-
gap: var(--sv-space-2);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
.trailing {
|
|
20
|
-
flex-shrink: 0;
|
|
21
|
-
max-width: 8rem;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
.hint {
|
|
25
|
-
font-size: var(--sv-font-size-xs);
|
|
26
|
-
color: var(--sv-color-text-muted);
|
|
27
|
-
}
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import { useState } from 'react';
|
|
2
|
-
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
3
|
-
import { CurrencyInput } from '../CurrencyInput/CurrencyInput';
|
|
4
|
-
import { MemberMultiSelect, type MemberMultiSelectOption } from './MemberMultiSelect';
|
|
5
|
-
|
|
6
|
-
const meta = {
|
|
7
|
-
title: 'Components/MemberMultiSelect',
|
|
8
|
-
component: MemberMultiSelect,
|
|
9
|
-
parameters: {
|
|
10
|
-
layout: 'padded',
|
|
11
|
-
docs: {
|
|
12
|
-
description: {
|
|
13
|
-
component:
|
|
14
|
-
'Checkbox list for picking any number of people from an already-resolved set of options. Domain-agnostic about who an option represents — instance users and guest members are both just `{id, label}`, so nothing special is needed to include guests. Not a directory search or invite flow; pair with SuggestionInput for that.',
|
|
15
|
-
},
|
|
16
|
-
},
|
|
17
|
-
},
|
|
18
|
-
args: {
|
|
19
|
-
options: [],
|
|
20
|
-
selectedIds: new Set(),
|
|
21
|
-
onToggle: () => {},
|
|
22
|
-
},
|
|
23
|
-
} satisfies Meta<typeof MemberMultiSelect>;
|
|
24
|
-
|
|
25
|
-
export default meta;
|
|
26
|
-
type Story = StoryObj<typeof meta>;
|
|
27
|
-
|
|
28
|
-
const OPTIONS: MemberMultiSelectOption[] = [
|
|
29
|
-
{ id: '1', label: 'Priya' },
|
|
30
|
-
{ id: '2', label: 'Jamie (guest)' },
|
|
31
|
-
{ id: '3', label: 'Sam' },
|
|
32
|
-
];
|
|
33
|
-
|
|
34
|
-
function ControlledMultiSelect({ withTrailing = false }: { withTrailing?: boolean }) {
|
|
35
|
-
const [selected, setSelected] = useState<Set<string>>(new Set(['1', '3']));
|
|
36
|
-
const [amounts, setAmounts] = useState<Record<string, number | null>>({});
|
|
37
|
-
|
|
38
|
-
return (
|
|
39
|
-
<MemberMultiSelect
|
|
40
|
-
options={OPTIONS}
|
|
41
|
-
selectedIds={selected}
|
|
42
|
-
onToggle={(id, checked) => {
|
|
43
|
-
setSelected((prev) => {
|
|
44
|
-
const next = new Set(prev);
|
|
45
|
-
if (checked) next.add(id);
|
|
46
|
-
else next.delete(id);
|
|
47
|
-
return next;
|
|
48
|
-
});
|
|
49
|
-
}}
|
|
50
|
-
label="Split between"
|
|
51
|
-
hint={withTrailing ? 'Remaining: 0.00' : undefined}
|
|
52
|
-
renderTrailing={
|
|
53
|
-
withTrailing
|
|
54
|
-
? (id) => (
|
|
55
|
-
<CurrencyInput
|
|
56
|
-
valueCents={amounts[id] ?? null}
|
|
57
|
-
onValueChange={(cents) => setAmounts((prev) => ({ ...prev, [id]: cents }))}
|
|
58
|
-
placeholder="0.00"
|
|
59
|
-
aria-label={`Amount for ${OPTIONS.find((o) => o.id === id)?.label}`}
|
|
60
|
-
/>
|
|
61
|
-
)
|
|
62
|
-
: undefined
|
|
63
|
-
}
|
|
64
|
-
/>
|
|
65
|
-
);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export const Default: Story = {
|
|
69
|
-
render: () => <ControlledMultiSelect />,
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
export const WithTrailingAmountInput: Story = {
|
|
73
|
-
render: () => <ControlledMultiSelect withTrailing />,
|
|
74
|
-
};
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import type { ReactNode } from 'react';
|
|
4
|
-
import { Checkbox } from '../Checkbox/Checkbox';
|
|
5
|
-
import styles from './MemberMultiSelect.module.css';
|
|
6
|
-
|
|
7
|
-
export interface MemberMultiSelectOption {
|
|
8
|
-
id: string;
|
|
9
|
-
label: string;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export interface MemberMultiSelectProps {
|
|
13
|
-
options: MemberMultiSelectOption[];
|
|
14
|
-
selectedIds: Set<string>;
|
|
15
|
-
onToggle: (id: string, checked: boolean) => void;
|
|
16
|
-
/** Rendered to the right of a selected row only — e.g. a per-person `CurrencyInput` or share count. */
|
|
17
|
-
renderTrailing?: (id: string) => ReactNode;
|
|
18
|
-
/** Section label above the list, e.g. "Paid by" or "Split between". */
|
|
19
|
-
label?: string;
|
|
20
|
-
/** Helper/validation text below the list, e.g. a running total. */
|
|
21
|
-
hint?: ReactNode;
|
|
22
|
-
className?: string;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* MemberMultiSelect — checkbox list for picking any number of people from an
|
|
27
|
-
* already-resolved set of options (group/project members, collaborators,
|
|
28
|
-
* etc.). Deliberately domain-agnostic about *who* an option represents —
|
|
29
|
-
* instance users and guest members are both just `{id, label}` here, so
|
|
30
|
-
* nothing special is needed to include guests alongside instance users; the
|
|
31
|
-
* caller's `options` array is the only place that distinction exists.
|
|
32
|
-
*
|
|
33
|
-
* Not a directory search or an "add a new guest" flow — pair with
|
|
34
|
-
* `SuggestionInput` (search + add) for that; this component only selects
|
|
35
|
-
* among options already passed in.
|
|
36
|
-
*/
|
|
37
|
-
export function MemberMultiSelect({
|
|
38
|
-
options,
|
|
39
|
-
selectedIds,
|
|
40
|
-
onToggle,
|
|
41
|
-
renderTrailing,
|
|
42
|
-
label,
|
|
43
|
-
hint,
|
|
44
|
-
className,
|
|
45
|
-
}: MemberMultiSelectProps) {
|
|
46
|
-
return (
|
|
47
|
-
<div className={[styles.group, className].filter(Boolean).join(' ')}>
|
|
48
|
-
{label && <span className={styles.label}>{label}</span>}
|
|
49
|
-
{options.map((option) => {
|
|
50
|
-
const checked = selectedIds.has(option.id);
|
|
51
|
-
return (
|
|
52
|
-
<div key={option.id} className={styles.row}>
|
|
53
|
-
<Checkbox
|
|
54
|
-
checked={checked}
|
|
55
|
-
onChange={(next) => onToggle(option.id, next)}
|
|
56
|
-
label={option.label}
|
|
57
|
-
/>
|
|
58
|
-
{checked && renderTrailing && (
|
|
59
|
-
<span className={styles.trailing}>{renderTrailing(option.id)}</span>
|
|
60
|
-
)}
|
|
61
|
-
</div>
|
|
62
|
-
);
|
|
63
|
-
})}
|
|
64
|
-
{hint && <span className={styles.hint}>{hint}</span>}
|
|
65
|
-
</div>
|
|
66
|
-
);
|
|
67
|
-
}
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
/* Menu — the item list shared by both presentations (Popover panel on
|
|
2
|
-
* desktop, Drawer panel on mobile); the presentational chrome around it is
|
|
3
|
-
* entirely owned by those two components, not duplicated here.
|
|
4
|
-
*
|
|
5
|
-
* Sizing audit: reviewed against this scale's other compact controls —
|
|
6
|
-
* --sv-radius-sm (6px) and --sv-font-size-sm (14px) already fit. The 44px
|
|
7
|
-
* min-height is a deliberate design choice, kept unconditional (not gated
|
|
8
|
-
* to pointer:coarse like Button/Checkbox) because this menu doubles as a
|
|
9
|
-
* full Drawer sheet on mobile, where every item must stay comfortably
|
|
10
|
-
* tappable. */
|
|
11
|
-
|
|
12
|
-
.list {
|
|
13
|
-
list-style: none;
|
|
14
|
-
margin: 0;
|
|
15
|
-
padding: var(--sv-space-1);
|
|
16
|
-
display: flex;
|
|
17
|
-
flex-direction: column;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
.item {
|
|
21
|
-
display: flex;
|
|
22
|
-
align-items: center;
|
|
23
|
-
gap: var(--sv-space-2);
|
|
24
|
-
width: 100%;
|
|
25
|
-
/* Min touch target (WCAG 2.5.5 / Apple HIG) — this menu renders as a
|
|
26
|
-
Drawer sheet on mobile, so every item must be comfortably tappable. */
|
|
27
|
-
min-height: var(--sv-touch-target-min, 44px);
|
|
28
|
-
padding: var(--sv-space-2) var(--sv-space-3);
|
|
29
|
-
border: none;
|
|
30
|
-
border-radius: var(--sv-radius-sm);
|
|
31
|
-
background: transparent;
|
|
32
|
-
color: var(--sv-color-text-primary);
|
|
33
|
-
font: inherit;
|
|
34
|
-
font-size: var(--sv-font-size-sm);
|
|
35
|
-
text-align: left;
|
|
36
|
-
cursor: pointer;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
@media (hover: hover) {
|
|
40
|
-
.item:hover:not(:disabled) {
|
|
41
|
-
background: var(--sv-color-surface-sunken);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
.item:focus-visible {
|
|
46
|
-
outline: 2px solid var(--sv-color-focus-ring);
|
|
47
|
-
outline-offset: -2px;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
.item:disabled {
|
|
51
|
-
opacity: 0.5;
|
|
52
|
-
cursor: not-allowed;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
.itemDestructive {
|
|
56
|
-
color: var(--sv-color-error-text);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
@media (hover: hover) {
|
|
60
|
-
.itemDestructive:hover:not(:disabled) {
|
|
61
|
-
background: var(--sv-color-error-surface);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/* Reserved checkmark gutter for a checkable item — sized so unchecked
|
|
66
|
-
siblings in the same group still align with the checked one's icon. */
|
|
67
|
-
.check {
|
|
68
|
-
display: inline-flex;
|
|
69
|
-
flex-shrink: 0;
|
|
70
|
-
width: var(--sv-icon-size-sm);
|
|
71
|
-
height: var(--sv-icon-size-sm);
|
|
72
|
-
align-items: center;
|
|
73
|
-
justify-content: center;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
.label {
|
|
77
|
-
padding: var(--sv-space-2) var(--sv-space-3) var(--sv-space-1);
|
|
78
|
-
font-size: var(--sv-font-size-label);
|
|
79
|
-
font-weight: var(--sv-font-weight-semibold);
|
|
80
|
-
color: var(--sv-color-text-muted);
|
|
81
|
-
text-transform: uppercase;
|
|
82
|
-
letter-spacing: 0.04em;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
.separator {
|
|
86
|
-
height: 1px;
|
|
87
|
-
margin: var(--sv-space-1) var(--sv-space-2);
|
|
88
|
-
background: var(--sv-color-border);
|
|
89
|
-
}
|