@sovereignfs/ui 0.83.1 → 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/AppsLauncher.module.css +6 -0
- package/dist/Button.module.css +5 -0
- package/dist/Card.module.css +6 -0
- package/dist/CardTile.module.css +6 -0
- package/dist/CheckableListRow.module.css +8 -0
- package/dist/Checkbox.module.css +8 -0
- package/dist/CodeTextarea.module.css +6 -0
- package/dist/ColorPicker.module.css +6 -0
- package/dist/Combobox.module.css +6 -0
- package/dist/Command.module.css +6 -0
- package/dist/ConfirmDialog.module.css +6 -0
- package/dist/DatePicker.module.css +6 -0
- package/dist/Dialog.module.css +1 -1
- package/dist/DragHandleRow.module.css +6 -0
- package/dist/FileDropzone.module.css +25 -1
- package/dist/Header.module.css +6 -0
- package/dist/IconPicker.module.css +14 -4
- package/dist/Input.module.css +6 -0
- package/dist/LegalLinks.module.css +9 -2
- package/dist/Markdown.module.css +5 -0
- package/dist/Message.module.css +9 -0
- package/dist/MobileAppsDrawer.module.css +9 -5
- package/dist/MobileFooter.module.css +6 -0
- package/dist/NavList.module.css +11 -2
- package/dist/NavTabs.module.css +7 -1
- package/dist/NotificationsPanel.module.css +10 -0
- package/dist/QrCode.module.css +17 -0
- package/dist/QuantityStepper.module.css +4 -2
- package/dist/RadioGroup.module.css +6 -0
- package/dist/SegmentedControl.module.css +6 -0
- package/dist/Select.module.css +6 -0
- package/dist/Sheet.module.css +16 -1
- package/dist/SplitPane.module.css +1 -1
- package/dist/StepStrip.module.css +5 -3
- package/dist/SuggestionInput.module.css +12 -1
- package/dist/SwipableMobileCarouselDots.module.css +6 -0
- package/dist/SystemBanner.module.css +6 -0
- package/dist/Tabs.module.css +6 -0
- package/dist/TagInput.module.css +6 -0
- package/dist/Textarea.module.css +6 -0
- package/dist/Toast.module.css +5 -0
- package/dist/Toggle.module.css +7 -0
- package/dist/Tooltip.module.css +6 -0
- package/dist/UserMenu.module.css +5 -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 +121 -43
- package/dist/index.js +1410 -1152
- package/dist/tokens/fonts.css +53 -0
- package/dist/tokens/primitives.css +12 -12
- package/dist/tokens.css +2 -1
- package/package.json +24 -13
- package/src/__tests__/motion.test.tsx +0 -105
- package/src/__tests__/package-json.test.ts +0 -8
- 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/AppsLauncher/AppsLauncher.module.css +0 -96
- package/src/components/AppsLauncher/AppsLauncher.stories.tsx +0 -58
- package/src/components/AppsLauncher/AppsLauncher.tsx +0 -117
- package/src/components/AppsLauncher/__tests__/AppsLauncher.test.tsx +0 -52
- 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 -177
- package/src/components/Badge/Badge.stories.tsx +0 -238
- package/src/components/Badge/Badge.tsx +0 -84
- package/src/components/Badge/__tests__/Badge.test.tsx +0 -90
- 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 -169
- 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/CardTile/CardTile.module.css +0 -181
- package/src/components/CardTile/CardTile.stories.tsx +0 -86
- package/src/components/CardTile/CardTile.tsx +0 -128
- package/src/components/CardTile/__tests__/CardTile.test.tsx +0 -56
- 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/ColorPicker/ColorPicker.module.css +0 -132
- package/src/components/ColorPicker/ColorPicker.stories.tsx +0 -80
- package/src/components/ColorPicker/ColorPicker.tsx +0 -157
- package/src/components/ColorPicker/__tests__/ColorPicker.test.tsx +0 -117
- 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 -150
- package/src/components/ConfirmDialog/__tests__/ConfirmDialog.test.tsx +0 -214
- package/src/components/ConsentPrompt/ConsentPrompt.module.css +0 -21
- package/src/components/ConsentPrompt/ConsentPrompt.stories.tsx +0 -31
- package/src/components/ConsentPrompt/ConsentPrompt.tsx +0 -66
- 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 -335
- package/src/components/Dialog/Dialog.stories.tsx +0 -324
- package/src/components/Dialog/Dialog.tsx +0 -254
- package/src/components/Dialog/__tests__/Dialog.test.tsx +0 -318
- package/src/components/DragHandleRow/DragHandleRow.module.css +0 -57
- package/src/components/DragHandleRow/DragHandleRow.tsx +0 -42
- package/src/components/Drawer/Drawer.module.css +0 -121
- package/src/components/Drawer/Drawer.stories.tsx +0 -132
- package/src/components/Drawer/Drawer.tsx +0 -175
- package/src/components/Drawer/__tests__/Drawer.test.tsx +0 -226
- 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/GripIcon/GripIcon.tsx +0 -27
- package/src/components/Header/Header.module.css +0 -62
- package/src/components/Header/Header.stories.tsx +0 -452
- package/src/components/Header/Header.tsx +0 -102
- package/src/components/Header/__tests__/Header.test.tsx +0 -104
- package/src/components/HeaderFooterLayout/HeaderFooterLayout.module.css +0 -21
- package/src/components/HeaderFooterLayout/HeaderFooterLayout.stories.tsx +0 -111
- package/src/components/HeaderFooterLayout/HeaderFooterLayout.tsx +0 -54
- package/src/components/HeaderFooterLayout/__tests__/HeaderFooterLayout.test.tsx +0 -58
- 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/arrow-left-right.tsx +0 -23
- 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/bold.tsx +0 -20
- 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-chevron-left.tsx +0 -21
- package/src/components/Icon/icons/circle-x.tsx +0 -22
- package/src/components/Icon/icons/code.tsx +0 -21
- package/src/components/Icon/icons/coffee.tsx +0 -23
- package/src/components/Icon/icons/cookie.tsx +0 -25
- package/src/components/Icon/icons/copy.tsx +0 -21
- package/src/components/Icon/icons/credit-card.tsx +0 -21
- package/src/components/Icon/icons/croissant.tsx +0 -24
- package/src/components/Icon/icons/cup-soda.tsx +0 -23
- package/src/components/Icon/icons/database.tsx +0 -22
- package/src/components/Icon/icons/download.tsx +0 -22
- 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-text.tsx +0 -24
- package/src/components/Icon/icons/file.tsx +0 -21
- package/src/components/Icon/icons/fish.tsx +0 -25
- package/src/components/Icon/icons/folder-closed.tsx +0 -21
- package/src/components/Icon/icons/folder-open.tsx +0 -20
- package/src/components/Icon/icons/folder.tsx +0 -20
- package/src/components/Icon/icons/folders.tsx +0 -21
- package/src/components/Icon/icons/grid-2x2.tsx +0 -22
- package/src/components/Icon/icons/hat-glasses.tsx +0 -24
- package/src/components/Icon/icons/history.tsx +0 -22
- package/src/components/Icon/icons/house.tsx +0 -21
- package/src/components/Icon/icons/inbox.tsx +0 -21
- package/src/components/Icon/icons/index.ts +0 -394
- package/src/components/Icon/icons/info.tsx +0 -22
- package/src/components/Icon/icons/italic.tsx +0 -22
- package/src/components/Icon/icons/layers.tsx +0 -22
- package/src/components/Icon/icons/layout-dashboard.tsx +0 -23
- package/src/components/Icon/icons/layout-grid.tsx +0 -23
- package/src/components/Icon/icons/link.tsx +0 -21
- package/src/components/Icon/icons/list-ordered.tsx +0 -25
- package/src/components/Icon/icons/list.tsx +0 -25
- package/src/components/Icon/icons/lock.tsx +0 -21
- package/src/components/Icon/icons/log-out.tsx +0 -22
- package/src/components/Icon/icons/luggage.tsx +0 -24
- package/src/components/Icon/icons/mail.tsx +0 -21
- package/src/components/Icon/icons/map-pin.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/minus.tsx +0 -20
- package/src/components/Icon/icons/package.tsx +0 -23
- package/src/components/Icon/icons/paint-bucket.tsx +0 -23
- package/src/components/Icon/icons/panel-left.tsx +0 -21
- package/src/components/Icon/icons/pencil.tsx +0 -21
- package/src/components/Icon/icons/pin.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/rectangle-ellipsis.tsx +0 -23
- package/src/components/Icon/icons/refresh-cw.tsx +0 -23
- package/src/components/Icon/icons/rotate-ccw.tsx +0 -21
- package/src/components/Icon/icons/rotate-cw.tsx +0 -21
- package/src/components/Icon/icons/route.tsx +0 -22
- package/src/components/Icon/icons/salad.tsx +0 -24
- package/src/components/Icon/icons/search.tsx +0 -21
- package/src/components/Icon/icons/send.tsx +0 -21
- package/src/components/Icon/icons/settings.tsx +0 -21
- package/src/components/Icon/icons/share-2.tsx +0 -24
- package/src/components/Icon/icons/sheet.tsx +0 -24
- 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/square-kanban.tsx +0 -23
- package/src/components/Icon/icons/table.tsx +0 -23
- 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-round-plus.tsx +0 -23
- package/src/components/Icon/icons/user.tsx +0 -21
- package/src/components/Icon/icons/users.tsx +0 -23
- 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 -20
- 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 -73
- package/src/components/Markdown/Markdown.stories.tsx +0 -40
- package/src/components/Markdown/Markdown.tsx +0 -305
- package/src/components/Markdown/__tests__/Markdown.test.tsx +0 -144
- 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 -90
- package/src/components/Menu/Menu.tsx +0 -209
- package/src/components/Menu/__tests__/Menu.test.tsx +0 -227
- 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 -65
- package/src/components/MessageScroller/MessageScroller.stories.tsx +0 -84
- package/src/components/MessageScroller/MessageScroller.tsx +0 -84
- package/src/components/MessageScroller/__tests__/MessageScroller.test.tsx +0 -105
- package/src/components/MobileAppsDrawer/MobileAppsDrawer.module.css +0 -82
- 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 -122
- package/src/components/MobileFooter/__tests__/MobileFooter.test.tsx +0 -129
- package/src/components/MobileHeader/MobileHeader.module.css +0 -76
- package/src/components/MobileHeader/MobileHeader.stories.tsx +0 -57
- package/src/components/MobileHeader/MobileHeader.tsx +0 -90
- package/src/components/MobileHeader/__tests__/MobileHeader.test.tsx +0 -113
- package/src/components/NavList/NavList.module.css +0 -130
- package/src/components/NavList/NavList.tsx +0 -136
- package/src/components/NavList/__tests__/NavList.test.tsx +0 -109
- 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/NotificationsPanel/NotificationsPanel.module.css +0 -258
- package/src/components/NotificationsPanel/NotificationsPanel.stories.tsx +0 -61
- package/src/components/NotificationsPanel/NotificationsPanel.tsx +0 -187
- package/src/components/NotificationsPanel/__tests__/NotificationsPanel.test.tsx +0 -78
- 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 -77
- package/src/components/OverlayHeader/__tests__/OverlayHeader.test.tsx +0 -69
- package/src/components/PageContainer/PageContainer.module.css +0 -82
- package/src/components/PageContainer/PageContainer.tsx +0 -64
- package/src/components/PageContainer/__tests__/PageContainer.test.tsx +0 -70
- package/src/components/PageHeader/PageHeader.module.css +0 -86
- package/src/components/PageHeader/PageHeader.tsx +0 -176
- package/src/components/PageHeader/__tests__/PageHeader.test.tsx +0 -103
- package/src/components/PageLayout/PageLayout.module.css +0 -51
- package/src/components/PageLayout/PageLayout.stories.tsx +0 -73
- package/src/components/PageLayout/PageLayout.tsx +0 -51
- package/src/components/PageLayout/__tests__/PageLayout.test.tsx +0 -34
- 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 -290
- package/src/components/Popover/__tests__/Popover.test.tsx +0 -263
- 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/RootLayout/RootLayout.module.css +0 -12
- package/src/components/RootLayout/RootLayout.stories.tsx +0 -125
- package/src/components/RootLayout/RootLayout.tsx +0 -185
- package/src/components/RootLayout/__tests__/RootLayout.test.tsx +0 -161
- 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 -58
- 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/StepStrip/StepStrip.module.css +0 -53
- package/src/components/StepStrip/StepStrip.tsx +0 -74
- 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 -64
- package/src/components/SwipableMobileCarousel/SwipableMobileCarousel.tsx +0 -243
- 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 -214
- 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 -64
- package/src/components/SwipableMobileCarouselDots/SwipableMobileCarouselDots.tsx +0 -73
- package/src/components/SwipableMobileCarouselDots/__tests__/SwipableMobileCarouselDots.test.tsx +0 -63
- package/src/components/SwipeStack/SwipeStack.module.css +0 -101
- package/src/components/SwipeStack/SwipeStack.tsx +0 -199
- package/src/components/SwipeStack/SwipeStackCard.tsx +0 -22
- package/src/components/SwipeStack/__tests__/SwipeStack.test.tsx +0 -169
- package/src/components/SystemBanner/SystemBanner.module.css +0 -79
- 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 -47
- package/src/components/Textarea/Textarea.tsx +0 -38
- package/src/components/Textarea/__tests__/Textarea.test.tsx +0 -51
- package/src/components/ThreeColumnLayout/ThreeColumnLayout.module.css +0 -35
- package/src/components/ThreeColumnLayout/ThreeColumnLayout.stories.tsx +0 -152
- package/src/components/ThreeColumnLayout/ThreeColumnLayout.tsx +0 -87
- package/src/components/ThreeColumnLayout/__tests__/ThreeColumnLayout.test.tsx +0 -78
- package/src/components/Toast/Toast.module.css +0 -191
- 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/components/UserMenu/UserMenu.module.css +0 -90
- package/src/components/UserMenu/UserMenu.stories.tsx +0 -49
- package/src/components/UserMenu/UserMenu.tsx +0 -132
- package/src/components/UserMenu/__tests__/UserMenu.test.tsx +0 -77
- 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__/usePublishShellChromeHeight.test.tsx +0 -118
- package/src/hooks/__tests__/useReorderSensors.test.ts +0 -26
- package/src/hooks/__tests__/useResponsiveLayout.test.tsx +0 -87
- package/src/hooks/__tests__/useSnapCarousel.test.tsx +0 -175
- package/src/hooks/__tests__/useSwipeReveal.test.tsx +0 -110
- package/src/hooks/__tests__/useSwipeStack.test.tsx +0 -155
- package/src/hooks/index.ts +0 -33
- 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/usePublishShellChromeHeight.ts +0 -96
- package/src/hooks/useReorderSensors.ts +0 -88
- package/src/hooks/useResponsiveLayout.ts +0 -36
- package/src/hooks/useSnapCarousel.ts +0 -284
- package/src/hooks/useSwipeReveal.ts +0 -107
- package/src/hooks/useSwipeStack.ts +0 -235
- package/src/index.ts +0 -311
- package/src/motion.ts +0 -78
- package/src/overlay-shell.ts +0 -159
- 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 -3793
- 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/GripIcon.stories.tsx +0 -29
- package/src/stories/InteractionHooks.stories.tsx +0 -925
- package/src/stories/LayoutSystem.stories.tsx +0 -639
- package/src/stories/MenuEntries.stories.tsx +0 -86
- package/src/stories/MobilePatterns.stories.tsx +0 -1536
- package/src/stories/NavList.stories.tsx +0 -147
- package/src/stories/NavTabs.stories.tsx +0 -53
- package/src/stories/OfflineGate.stories.tsx +0 -42
- package/src/stories/PageContainer.stories.tsx +0 -82
- package/src/stories/PageHeader.stories.tsx +0 -95
- package/src/stories/ResponsiveSurface.stories.tsx +0 -47
- package/src/stories/Spinner.stories.tsx +0 -25
- package/src/stories/StepStrip.stories.tsx +0 -76
- package/src/stories/SwipableMobileCarousel.stories.tsx +0 -362
- package/src/stories/SwipeStack.stories.tsx +0 -200
- package/src/stories/Textarea.stories.tsx +0 -63
- package/src/stories/TokenGallery.stories.tsx +0 -652
- package/src/stories/Tooltip.stories.tsx +0 -59
- package/src/tokens/primitives.css +0 -168
- package/src/tokens/semantic.css +0 -162
- package/src/tokens/theme-presets.css +0 -33
- package/src/tokens/theme-presets.ts +0 -72
- package/src/tokens.css +0 -5
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
// @vitest-environment jsdom
|
|
2
|
-
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
3
|
-
import { useState } from 'react';
|
|
4
|
-
import { act, cleanup, fireEvent, render, screen } from '@testing-library/react';
|
|
5
|
-
import { ConfirmDialog } from '../ConfirmDialog';
|
|
6
|
-
|
|
7
|
-
// jsdom does not implement HTMLDialogElement.showModal()/close() (a
|
|
8
|
-
// long-standing, documented gap) — polyfill the minimum behavior the
|
|
9
|
-
// component depends on: the `open` attribute reflecting visibility, and
|
|
10
|
-
// close() dispatching the native 'close' event ConfirmDialog listens for.
|
|
11
|
-
//
|
|
12
|
-
// Two details matter here beyond the minimum, both load-bearing for the
|
|
13
|
-
// double-onClose regression tests below: (1) a no-op when already closed,
|
|
14
|
-
// matching the HTML spec's own early return, and (2) the 'close' event is
|
|
15
|
-
// queued rather than dispatched synchronously ("queue an element task ... to
|
|
16
|
-
// fire an event named close" per spec) — deferring it means a listener
|
|
17
|
-
// (re-)attached during the SAME synchronous React commit that triggered this
|
|
18
|
-
// close() call is still reachable once the event actually fires, exactly as
|
|
19
|
-
// in a real browser. Dispatching synchronously instead (the simpler version
|
|
20
|
-
// this replaced) fires the event in the middle of React's effect
|
|
21
|
-
// cleanup/setup phase, when no listener happens to be attached yet — which
|
|
22
|
-
// made the double-call bug this file guards against silently unreproducible
|
|
23
|
-
// in jsdom regardless of whether the underlying component bug was present.
|
|
24
|
-
beforeEach(() => {
|
|
25
|
-
HTMLDialogElement.prototype.showModal = function (this: HTMLDialogElement) {
|
|
26
|
-
this.setAttribute('open', '');
|
|
27
|
-
};
|
|
28
|
-
HTMLDialogElement.prototype.close = function (this: HTMLDialogElement) {
|
|
29
|
-
if (!this.hasAttribute('open')) return;
|
|
30
|
-
this.removeAttribute('open');
|
|
31
|
-
queueMicrotask(() => this.dispatchEvent(new Event('close')));
|
|
32
|
-
};
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
// Flushes any chain of queueMicrotask-deferred dispatches and the React
|
|
36
|
-
// state updates/effects they trigger. A single real macrotask tick is
|
|
37
|
-
// enough: the microtask queue always fully drains — including microtasks
|
|
38
|
-
// newly queued from within an already-running one — before a macrotask runs.
|
|
39
|
-
async function flushDeferredDialogEvents() {
|
|
40
|
-
await act(async () => {
|
|
41
|
-
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
describe('ConfirmDialog', () => {
|
|
46
|
-
afterEach(cleanup);
|
|
47
|
-
|
|
48
|
-
it('renders the title and message when open', () => {
|
|
49
|
-
render(
|
|
50
|
-
<ConfirmDialog
|
|
51
|
-
open
|
|
52
|
-
onClose={() => {}}
|
|
53
|
-
onConfirm={() => {}}
|
|
54
|
-
title="Remove passkey"
|
|
55
|
-
message="This cannot be undone."
|
|
56
|
-
/>,
|
|
57
|
-
);
|
|
58
|
-
expect(screen.getByText('Remove passkey')).toBeTruthy();
|
|
59
|
-
expect(screen.getByText('This cannot be undone.')).toBeTruthy();
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
it('renders rich message content', () => {
|
|
63
|
-
render(
|
|
64
|
-
<ConfirmDialog
|
|
65
|
-
open
|
|
66
|
-
onClose={() => {}}
|
|
67
|
-
onConfirm={() => {}}
|
|
68
|
-
title="Remove plugin"
|
|
69
|
-
message={
|
|
70
|
-
<>
|
|
71
|
-
Remove <strong>Example</strong>?
|
|
72
|
-
</>
|
|
73
|
-
}
|
|
74
|
-
/>,
|
|
75
|
-
);
|
|
76
|
-
expect(screen.getByText('Example').tagName).toBe('STRONG');
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
it('calls onClose on Cancel', async () => {
|
|
80
|
-
const onClose = vi.fn();
|
|
81
|
-
render(
|
|
82
|
-
<ConfirmDialog open onClose={onClose} onConfirm={() => {}} title="Remove" message="Sure?" />,
|
|
83
|
-
);
|
|
84
|
-
// Cancel now calls dialogRef.current.close() rather than onClose
|
|
85
|
-
// directly (see ConfirmDialog.tsx) — onClose only fires once the
|
|
86
|
-
// resulting (deferred, see the polyfill above) native 'close' event
|
|
87
|
-
// reaches ConfirmDialog's own listener.
|
|
88
|
-
fireEvent.click(screen.getByRole('button', { name: 'Cancel' }));
|
|
89
|
-
await flushDeferredDialogEvents();
|
|
90
|
-
expect(onClose).toHaveBeenCalledOnce();
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
// Statefully wired, unlike the test above: a real consumer's onClose flips
|
|
94
|
-
// its own `open` state to false, which re-runs ConfirmDialog's internal
|
|
95
|
-
// `if (open) showModal(); else el.close();` effect and calls el.close()
|
|
96
|
-
// itself. Pre-fix, Cancel/backdrop-click also called onClose directly,
|
|
97
|
-
// so this path fired onClose a second time; the test above's static
|
|
98
|
-
// `open` prop never changes, so it can't exercise that second re-render.
|
|
99
|
-
function StatefulConfirmDialog({ onCloseSpy }: { onCloseSpy: () => void }) {
|
|
100
|
-
const [open, setOpen] = useState(true);
|
|
101
|
-
return (
|
|
102
|
-
<ConfirmDialog
|
|
103
|
-
open={open}
|
|
104
|
-
onClose={() => {
|
|
105
|
-
onCloseSpy();
|
|
106
|
-
setOpen(false);
|
|
107
|
-
}}
|
|
108
|
-
onConfirm={() => {}}
|
|
109
|
-
title="Remove"
|
|
110
|
-
message="Sure?"
|
|
111
|
-
/>
|
|
112
|
-
);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
it('calls onClose exactly once when a stateful consumer dismisses via Cancel', async () => {
|
|
116
|
-
const onCloseSpy = vi.fn();
|
|
117
|
-
render(<StatefulConfirmDialog onCloseSpy={onCloseSpy} />);
|
|
118
|
-
fireEvent.click(screen.getByRole('button', { name: 'Cancel' }));
|
|
119
|
-
await flushDeferredDialogEvents();
|
|
120
|
-
expect(onCloseSpy).toHaveBeenCalledOnce();
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
it('calls onClose exactly once when a stateful consumer dismisses via backdrop click', async () => {
|
|
124
|
-
const onCloseSpy = vi.fn();
|
|
125
|
-
render(<StatefulConfirmDialog onCloseSpy={onCloseSpy} />);
|
|
126
|
-
fireEvent.click(screen.getByRole('dialog'));
|
|
127
|
-
await flushDeferredDialogEvents();
|
|
128
|
-
expect(onCloseSpy).toHaveBeenCalledOnce();
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
it('calls onConfirm on the confirm action, without itself closing', () => {
|
|
132
|
-
const onConfirm = vi.fn();
|
|
133
|
-
const onClose = vi.fn();
|
|
134
|
-
render(
|
|
135
|
-
<ConfirmDialog
|
|
136
|
-
open
|
|
137
|
-
onClose={onClose}
|
|
138
|
-
onConfirm={onConfirm}
|
|
139
|
-
title="Remove"
|
|
140
|
-
message="Sure?"
|
|
141
|
-
confirmLabel="Remove"
|
|
142
|
-
/>,
|
|
143
|
-
);
|
|
144
|
-
fireEvent.click(screen.getByRole('button', { name: 'Remove' }));
|
|
145
|
-
expect(onConfirm).toHaveBeenCalledOnce();
|
|
146
|
-
expect(onClose).not.toHaveBeenCalled();
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
it('uses custom confirm/cancel labels', () => {
|
|
150
|
-
render(
|
|
151
|
-
<ConfirmDialog
|
|
152
|
-
open
|
|
153
|
-
onClose={() => {}}
|
|
154
|
-
onConfirm={() => {}}
|
|
155
|
-
title="Sign out"
|
|
156
|
-
message="Sign out of this device?"
|
|
157
|
-
confirmLabel="Sign out"
|
|
158
|
-
cancelLabel="Stay signed in"
|
|
159
|
-
/>,
|
|
160
|
-
);
|
|
161
|
-
expect(screen.getByRole('button', { name: 'Sign out' })).toBeTruthy();
|
|
162
|
-
expect(screen.getByRole('button', { name: 'Stay signed in' })).toBeTruthy();
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
it('disables both actions and shows the error slot when pending', () => {
|
|
166
|
-
render(
|
|
167
|
-
<ConfirmDialog
|
|
168
|
-
open
|
|
169
|
-
onClose={() => {}}
|
|
170
|
-
onConfirm={() => {}}
|
|
171
|
-
title="Remove plugin"
|
|
172
|
-
message="Sure?"
|
|
173
|
-
confirmLabel="Removing…"
|
|
174
|
-
pending
|
|
175
|
-
error="Server error — try again."
|
|
176
|
-
/>,
|
|
177
|
-
);
|
|
178
|
-
expect((screen.getByRole('button', { name: 'Cancel' }) as HTMLButtonElement).disabled).toBe(
|
|
179
|
-
true,
|
|
180
|
-
);
|
|
181
|
-
expect((screen.getByRole('button', { name: 'Removing…' }) as HTMLButtonElement).disabled).toBe(
|
|
182
|
-
true,
|
|
183
|
-
);
|
|
184
|
-
expect(screen.getByText('Server error — try again.')).toBeTruthy();
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
it('renders a destructive confirm action distinctly from the default variant', () => {
|
|
188
|
-
const { rerender } = render(
|
|
189
|
-
<ConfirmDialog
|
|
190
|
-
open
|
|
191
|
-
onClose={() => {}}
|
|
192
|
-
onConfirm={() => {}}
|
|
193
|
-
title="Remove"
|
|
194
|
-
message="Sure?"
|
|
195
|
-
confirmLabel="Remove"
|
|
196
|
-
/>,
|
|
197
|
-
);
|
|
198
|
-
const defaultClass = screen.getByRole('button', { name: 'Remove' }).className;
|
|
199
|
-
|
|
200
|
-
rerender(
|
|
201
|
-
<ConfirmDialog
|
|
202
|
-
open
|
|
203
|
-
onClose={() => {}}
|
|
204
|
-
onConfirm={() => {}}
|
|
205
|
-
title="Remove"
|
|
206
|
-
message="Sure?"
|
|
207
|
-
confirmLabel="Remove"
|
|
208
|
-
destructive
|
|
209
|
-
/>,
|
|
210
|
-
);
|
|
211
|
-
const destructiveClass = screen.getByRole('button', { name: 'Remove' }).className;
|
|
212
|
-
expect(destructiveClass).not.toBe(defaultClass);
|
|
213
|
-
});
|
|
214
|
-
});
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
.root {
|
|
2
|
-
display: flex;
|
|
3
|
-
flex-direction: column;
|
|
4
|
-
gap: var(--sv-space-2);
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
.title {
|
|
8
|
-
font-size: var(--sv-font-size-sm);
|
|
9
|
-
color: var(--sv-color-text-primary);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
.description {
|
|
13
|
-
font-size: var(--sv-font-size-sm);
|
|
14
|
-
color: var(--sv-color-text-muted);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
.actions {
|
|
18
|
-
display: flex;
|
|
19
|
-
gap: var(--sv-space-2);
|
|
20
|
-
margin-top: var(--sv-space-1);
|
|
21
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
-
import { ConsentPrompt } from './ConsentPrompt';
|
|
3
|
-
|
|
4
|
-
const meta = {
|
|
5
|
-
title: 'Components/ConsentPrompt',
|
|
6
|
-
component: ConsentPrompt,
|
|
7
|
-
parameters: { layout: 'padded' },
|
|
8
|
-
args: {
|
|
9
|
-
consumerName: 'Ledger',
|
|
10
|
-
providerName: 'Finance Tracker',
|
|
11
|
-
contract: 'expenses',
|
|
12
|
-
description: 'Monthly expense totals by category, no transaction-level detail.',
|
|
13
|
-
onAllow: () => {},
|
|
14
|
-
onDeny: () => {},
|
|
15
|
-
},
|
|
16
|
-
} satisfies Meta<typeof ConsentPrompt>;
|
|
17
|
-
|
|
18
|
-
export default meta;
|
|
19
|
-
type Story = StoryObj<typeof meta>;
|
|
20
|
-
|
|
21
|
-
// ---------------------------------------------------------------------------
|
|
22
|
-
|
|
23
|
-
export const Default: Story = {};
|
|
24
|
-
|
|
25
|
-
export const NoDescription: Story = {
|
|
26
|
-
args: { description: null },
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
export const Pending: Story = {
|
|
30
|
-
args: { pending: true },
|
|
31
|
-
};
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import { Button } from '../Button/Button';
|
|
2
|
-
import { Card } from '../Card/Card';
|
|
3
|
-
import styles from './ConsentPrompt.module.css';
|
|
4
|
-
|
|
5
|
-
export interface ConsentPromptProps {
|
|
6
|
-
/** The plugin requesting access. */
|
|
7
|
-
consumerName: string;
|
|
8
|
-
/** The plugin whose data would be read. */
|
|
9
|
-
providerName: string;
|
|
10
|
-
/** The named contract being requested (e.g. `"expenses"`). */
|
|
11
|
-
contract: string;
|
|
12
|
-
/**
|
|
13
|
-
* The provider's own manifest-declared explanation of what this contract
|
|
14
|
-
* exposes (`data.provides[].description`) — never caller-supplied at
|
|
15
|
-
* request time, so a consuming plugin can't write its own persuasive copy
|
|
16
|
-
* for what it's asking to read.
|
|
17
|
-
*/
|
|
18
|
-
description?: string | null;
|
|
19
|
-
onAllow: () => void;
|
|
20
|
-
onDeny?: () => void;
|
|
21
|
-
allowLabel?: string;
|
|
22
|
-
denyLabel?: string;
|
|
23
|
-
/** Disables both buttons and shows a busy state on Allow while a request is in flight. */
|
|
24
|
-
pending?: boolean;
|
|
25
|
-
className?: string;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* The consent screen shown before one plugin is allowed to read another
|
|
30
|
-
* plugin's data (RFC 0002 §4) — the step that was previously missing between
|
|
31
|
-
* a `ConsentRequiredError` and a grant actually being created. Presentational
|
|
32
|
-
* only: holds no state of its own, so it renders identically wherever it's
|
|
33
|
-
* used (currently Account → Data's pending-requests list).
|
|
34
|
-
*/
|
|
35
|
-
export function ConsentPrompt({
|
|
36
|
-
consumerName,
|
|
37
|
-
providerName,
|
|
38
|
-
contract,
|
|
39
|
-
description,
|
|
40
|
-
onAllow,
|
|
41
|
-
onDeny,
|
|
42
|
-
allowLabel = 'Allow',
|
|
43
|
-
denyLabel = 'Not now',
|
|
44
|
-
pending = false,
|
|
45
|
-
className,
|
|
46
|
-
}: ConsentPromptProps) {
|
|
47
|
-
return (
|
|
48
|
-
<Card padding="sm" className={[styles.root, className].filter(Boolean).join(' ')}>
|
|
49
|
-
<p className={styles.title}>
|
|
50
|
-
<strong>{consumerName}</strong> wants to read <strong>{contract}</strong> from{' '}
|
|
51
|
-
<strong>{providerName}</strong>
|
|
52
|
-
</p>
|
|
53
|
-
{description ? <p className={styles.description}>{description}</p> : null}
|
|
54
|
-
<div className={styles.actions}>
|
|
55
|
-
<Button variant="primary" size="sm" onClick={onAllow} disabled={pending} loading={pending}>
|
|
56
|
-
{allowLabel}
|
|
57
|
-
</Button>
|
|
58
|
-
{onDeny ? (
|
|
59
|
-
<Button variant="ghost" size="sm" onClick={onDeny} disabled={pending}>
|
|
60
|
-
{denyLabel}
|
|
61
|
-
</Button>
|
|
62
|
-
) : null}
|
|
63
|
-
</div>
|
|
64
|
-
</Card>
|
|
65
|
-
);
|
|
66
|
-
}
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
-
import { ContextMenu } from './ContextMenu';
|
|
3
|
-
|
|
4
|
-
const meta = {
|
|
5
|
-
title: 'Components/ContextMenu',
|
|
6
|
-
component: ContextMenu,
|
|
7
|
-
parameters: {
|
|
8
|
-
layout: 'padded',
|
|
9
|
-
docs: {
|
|
10
|
-
description: {
|
|
11
|
-
component:
|
|
12
|
-
"Right-click menu on desktop, long-press on touch. Desktop positioning reuses Popover's existing collision detection anchored to the click point; touch opens the same items in a Drawer bottom sheet — a floating panel at a touch point isn't a pattern touch interfaces have.",
|
|
13
|
-
},
|
|
14
|
-
},
|
|
15
|
-
},
|
|
16
|
-
args: {
|
|
17
|
-
children: <span />,
|
|
18
|
-
items: [
|
|
19
|
-
{ label: 'Rename', onSelect: () => {} },
|
|
20
|
-
{ label: 'Duplicate', onSelect: () => {} },
|
|
21
|
-
{ type: 'separator' },
|
|
22
|
-
{ label: 'Delete', destructive: true, onSelect: () => {} },
|
|
23
|
-
],
|
|
24
|
-
'aria-label': 'Row actions',
|
|
25
|
-
},
|
|
26
|
-
} satisfies Meta<typeof ContextMenu>;
|
|
27
|
-
|
|
28
|
-
export default meta;
|
|
29
|
-
type Story = StoryObj<typeof meta>;
|
|
30
|
-
|
|
31
|
-
// ---------------------------------------------------------------------------
|
|
32
|
-
|
|
33
|
-
export const Default: Story = {
|
|
34
|
-
render: (args) => (
|
|
35
|
-
<ContextMenu {...args}>
|
|
36
|
-
<div
|
|
37
|
-
style={{
|
|
38
|
-
width: 240,
|
|
39
|
-
padding: 'var(--sv-space-4)',
|
|
40
|
-
border: '1px dashed var(--sv-color-border-strong)',
|
|
41
|
-
borderRadius: 'var(--sv-radius-md)',
|
|
42
|
-
textAlign: 'center',
|
|
43
|
-
fontSize: 14,
|
|
44
|
-
color: 'var(--sv-color-text-muted)',
|
|
45
|
-
}}
|
|
46
|
-
>
|
|
47
|
-
Right-click here (or long-press on touch)
|
|
48
|
-
</div>
|
|
49
|
-
</ContextMenu>
|
|
50
|
-
),
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
export const WithIconsAndChecked: Story = {
|
|
54
|
-
args: {
|
|
55
|
-
items: [
|
|
56
|
-
{ type: 'label', label: 'Sort by' },
|
|
57
|
-
{ label: 'Name', checked: true, onSelect: () => {} },
|
|
58
|
-
{ label: 'Date modified', checked: false, onSelect: () => {} },
|
|
59
|
-
{ type: 'separator' },
|
|
60
|
-
{ label: 'Rename', icon: 'pencil', onSelect: () => {} },
|
|
61
|
-
{ label: 'Delete', icon: 'trash-2', destructive: true, onSelect: () => {} },
|
|
62
|
-
],
|
|
63
|
-
},
|
|
64
|
-
render: (args) => (
|
|
65
|
-
<ContextMenu {...args}>
|
|
66
|
-
<div
|
|
67
|
-
style={{
|
|
68
|
-
width: 240,
|
|
69
|
-
padding: 'var(--sv-space-4)',
|
|
70
|
-
border: '1px dashed var(--sv-color-border-strong)',
|
|
71
|
-
borderRadius: 'var(--sv-radius-md)',
|
|
72
|
-
textAlign: 'center',
|
|
73
|
-
fontSize: 14,
|
|
74
|
-
color: 'var(--sv-color-text-muted)',
|
|
75
|
-
}}
|
|
76
|
-
>
|
|
77
|
-
Right-click here
|
|
78
|
-
</div>
|
|
79
|
-
</ContextMenu>
|
|
80
|
-
),
|
|
81
|
-
};
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { cloneElement, useState } from 'react';
|
|
4
|
-
import type { ReactElement } from 'react';
|
|
5
|
-
import type { MouseEvent as ReactMouseEvent } from 'react';
|
|
6
|
-
import { useIsMobile, useLongPress } from '../../hooks';
|
|
7
|
-
import { Popover } from '../Popover/Popover';
|
|
8
|
-
import { Drawer } from '../Drawer/Drawer';
|
|
9
|
-
import { MenuEntries, type MenuEntry, type MenuItem } from '../Menu/Menu';
|
|
10
|
-
|
|
11
|
-
export interface ContextMenuProps {
|
|
12
|
-
/** The element that gets right-click (desktop) / long-press (touch)
|
|
13
|
-
* behavior — cloned with the trigger handlers, rendered as-is otherwise.
|
|
14
|
-
* Typed with `<any>` props (not a bare `ReactElement`, whose implicit
|
|
15
|
-
* `unknown` props type makes `cloneElement` reject *both* branches of
|
|
16
|
-
* the long-press/onContextMenu union below — an interface value like
|
|
17
|
-
* `LongPressHandlers` isn't assignable to an indexed props type without
|
|
18
|
-
* its own index signature) — the standard, narrowly-scoped escape hatch
|
|
19
|
-
* for "clone an arbitrary child with props not known ahead of time". */
|
|
20
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- see comment above
|
|
21
|
-
children: ReactElement<any>;
|
|
22
|
-
items: MenuEntry[];
|
|
23
|
-
'aria-label': string;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* ContextMenu — right-click menu on desktop, long-press on touch.
|
|
28
|
-
*
|
|
29
|
-
* Desktop positioning reuses `Popover`'s existing collision-detection logic
|
|
30
|
-
* rather than reimplementing it: the panel is wrapped in a zero-size,
|
|
31
|
-
* `position: fixed` anchor placed at the click coordinates, so `Popover`
|
|
32
|
-
* measures and flips against *that* point exactly as it would a normal
|
|
33
|
-
* trigger element.
|
|
34
|
-
*
|
|
35
|
-
* Touch uses `useLongPress` (which already handles the OS's own long-press
|
|
36
|
-
* callout/context-menu suppression) and opens the same items in a `Drawer`
|
|
37
|
-
* bottom sheet — the same adaptive-surface split `Menu` already uses,
|
|
38
|
-
* because a floating panel positioned at a touch point isn't a pattern
|
|
39
|
-
* touch interfaces have in the first place.
|
|
40
|
-
*/
|
|
41
|
-
export function ContextMenu({ children, items, 'aria-label': ariaLabel }: ContextMenuProps) {
|
|
42
|
-
const isMobile = useIsMobile();
|
|
43
|
-
const [open, setOpen] = useState(false);
|
|
44
|
-
const [point, setPoint] = useState({ x: 0, y: 0 });
|
|
45
|
-
|
|
46
|
-
const longPressHandlers = useLongPress({
|
|
47
|
-
onLongPress: () => setOpen(true),
|
|
48
|
-
disabled: !isMobile,
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
function handleContextMenu(e: ReactMouseEvent) {
|
|
52
|
-
e.preventDefault();
|
|
53
|
-
setPoint({ x: e.clientX, y: e.clientY });
|
|
54
|
-
setOpen(true);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const wrappedChild = cloneElement(
|
|
58
|
-
children,
|
|
59
|
-
isMobile ? longPressHandlers : { onContextMenu: handleContextMenu },
|
|
60
|
-
);
|
|
61
|
-
|
|
62
|
-
const list = (
|
|
63
|
-
<MenuEntries
|
|
64
|
-
items={items}
|
|
65
|
-
onSelect={(entry: MenuItem) => {
|
|
66
|
-
setOpen(false);
|
|
67
|
-
entry.onSelect?.();
|
|
68
|
-
}}
|
|
69
|
-
/>
|
|
70
|
-
);
|
|
71
|
-
|
|
72
|
-
if (isMobile) {
|
|
73
|
-
return (
|
|
74
|
-
<>
|
|
75
|
-
{wrappedChild}
|
|
76
|
-
<Drawer open={open} onClose={() => setOpen(false)} aria-label={ariaLabel}>
|
|
77
|
-
{list}
|
|
78
|
-
</Drawer>
|
|
79
|
-
</>
|
|
80
|
-
);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
return (
|
|
84
|
-
<>
|
|
85
|
-
{wrappedChild}
|
|
86
|
-
{open && (
|
|
87
|
-
<div style={{ position: 'fixed', left: point.x, top: point.y, width: 0, height: 0 }}>
|
|
88
|
-
<Popover
|
|
89
|
-
trigger={<span />}
|
|
90
|
-
open={open}
|
|
91
|
-
onClose={() => setOpen(false)}
|
|
92
|
-
aria-label={ariaLabel}
|
|
93
|
-
>
|
|
94
|
-
{list}
|
|
95
|
-
</Popover>
|
|
96
|
-
</div>
|
|
97
|
-
)}
|
|
98
|
-
</>
|
|
99
|
-
);
|
|
100
|
-
}
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
// @vitest-environment jsdom
|
|
2
|
-
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
3
|
-
import { act, cleanup, render, screen, fireEvent } from '@testing-library/react';
|
|
4
|
-
import { ContextMenu } from '../ContextMenu';
|
|
5
|
-
|
|
6
|
-
let isMobileMatches = false;
|
|
7
|
-
|
|
8
|
-
function installMatchMedia() {
|
|
9
|
-
vi.stubGlobal(
|
|
10
|
-
'matchMedia',
|
|
11
|
-
vi.fn().mockImplementation((query: string) => ({
|
|
12
|
-
matches: isMobileMatches,
|
|
13
|
-
media: query,
|
|
14
|
-
addEventListener: vi.fn(),
|
|
15
|
-
removeEventListener: vi.fn(),
|
|
16
|
-
addListener: vi.fn(),
|
|
17
|
-
removeListener: vi.fn(),
|
|
18
|
-
dispatchEvent: vi.fn(),
|
|
19
|
-
})),
|
|
20
|
-
);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const items = [{ label: 'Delete', onSelect: vi.fn() }];
|
|
24
|
-
|
|
25
|
-
describe('ContextMenu', () => {
|
|
26
|
-
beforeEach(() => {
|
|
27
|
-
isMobileMatches = false;
|
|
28
|
-
installMatchMedia();
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
afterEach(() => {
|
|
32
|
-
vi.unstubAllGlobals();
|
|
33
|
-
cleanup();
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
it('does not show the menu before any trigger', () => {
|
|
37
|
-
render(
|
|
38
|
-
<ContextMenu items={items} aria-label="Row actions">
|
|
39
|
-
<div>Row</div>
|
|
40
|
-
</ContextMenu>,
|
|
41
|
-
);
|
|
42
|
-
expect(screen.queryByRole('menu')).toBeNull();
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
it('opens on right-click (desktop) and prevents the native context menu', () => {
|
|
46
|
-
render(
|
|
47
|
-
<ContextMenu items={items} aria-label="Row actions">
|
|
48
|
-
<div>Row</div>
|
|
49
|
-
</ContextMenu>,
|
|
50
|
-
);
|
|
51
|
-
const target = screen.getByText('Row');
|
|
52
|
-
const event = fireEvent.contextMenu(target, { clientX: 100, clientY: 150 });
|
|
53
|
-
expect(event).toBe(false); // fireEvent returns false when preventDefault was called
|
|
54
|
-
expect(screen.getByRole('menu')).toBeDefined();
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
it('selecting an item calls onSelect and closes the menu', () => {
|
|
58
|
-
const onSelect = vi.fn();
|
|
59
|
-
render(
|
|
60
|
-
<ContextMenu items={[{ label: 'Delete', onSelect }]} aria-label="Row actions">
|
|
61
|
-
<div>Row</div>
|
|
62
|
-
</ContextMenu>,
|
|
63
|
-
);
|
|
64
|
-
fireEvent.contextMenu(screen.getByText('Row'), { clientX: 10, clientY: 10 });
|
|
65
|
-
fireEvent.click(screen.getByRole('menuitem', { name: 'Delete' }));
|
|
66
|
-
expect(onSelect).toHaveBeenCalled();
|
|
67
|
-
expect(screen.queryByRole('menu')).toBeNull();
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
it('opens via long-press on touch instead of right-click', () => {
|
|
71
|
-
vi.useFakeTimers();
|
|
72
|
-
isMobileMatches = true;
|
|
73
|
-
installMatchMedia();
|
|
74
|
-
render(
|
|
75
|
-
<ContextMenu items={items} aria-label="Row actions">
|
|
76
|
-
<div>Row</div>
|
|
77
|
-
</ContextMenu>,
|
|
78
|
-
);
|
|
79
|
-
const target = screen.getByText('Row');
|
|
80
|
-
fireEvent.pointerDown(target, { pointerType: 'touch', clientX: 10, clientY: 10 });
|
|
81
|
-
act(() => {
|
|
82
|
-
vi.advanceTimersByTime(600);
|
|
83
|
-
});
|
|
84
|
-
expect(screen.getByRole('menu')).toBeDefined();
|
|
85
|
-
vi.useRealTimers();
|
|
86
|
-
});
|
|
87
|
-
});
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { useState } from 'react';
|
|
2
|
-
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
3
|
-
import { CurrencyInput } from './CurrencyInput';
|
|
4
|
-
|
|
5
|
-
const meta = {
|
|
6
|
-
title: 'Components/CurrencyInput',
|
|
7
|
-
component: CurrencyInput,
|
|
8
|
-
parameters: {
|
|
9
|
-
layout: 'padded',
|
|
10
|
-
docs: {
|
|
11
|
-
description: {
|
|
12
|
-
component:
|
|
13
|
-
'Decimal amount entry that reports its value as integer cents, matching the "amounts are always smallest-unit integers" data-model convention. Preserves in-progress typing (e.g. a trailing decimal point) instead of reformatting on every keystroke.',
|
|
14
|
-
},
|
|
15
|
-
},
|
|
16
|
-
},
|
|
17
|
-
args: {
|
|
18
|
-
valueCents: null,
|
|
19
|
-
onValueChange: () => {},
|
|
20
|
-
},
|
|
21
|
-
} satisfies Meta<typeof CurrencyInput>;
|
|
22
|
-
|
|
23
|
-
export default meta;
|
|
24
|
-
type Story = StoryObj<typeof meta>;
|
|
25
|
-
|
|
26
|
-
function ControlledCurrencyInput({ initialCents }: { initialCents: number | null }) {
|
|
27
|
-
const [cents, setCents] = useState<number | null>(initialCents);
|
|
28
|
-
return (
|
|
29
|
-
<CurrencyInput
|
|
30
|
-
valueCents={cents}
|
|
31
|
-
onValueChange={setCents}
|
|
32
|
-
placeholder="0.00"
|
|
33
|
-
aria-label="Amount"
|
|
34
|
-
/>
|
|
35
|
-
);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export const Empty: Story = {
|
|
39
|
-
render: () => <ControlledCurrencyInput initialCents={null} />,
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
export const Prefilled: Story = {
|
|
43
|
-
render: () => <ControlledCurrencyInput initialCents={4250} />,
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
export const Disabled: Story = {
|
|
47
|
-
render: () => (
|
|
48
|
-
<CurrencyInput valueCents={1000} onValueChange={() => {}} aria-label="Amount" disabled />
|
|
49
|
-
),
|
|
50
|
-
};
|