@dxos/react-ui 0.10.0 → 0.11.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/dist/lib/chunk-parse-stack.mjs +1566 -0
- package/dist/lib/chunk-parse-stack.mjs.map +1 -0
- package/dist/lib/index.mjs +5220 -0
- package/dist/lib/index.mjs.map +1 -0
- package/dist/lib/testing.mjs +144 -0
- package/dist/lib/testing.mjs.map +1 -0
- package/dist/lib/translations.mjs +38 -0
- package/dist/lib/translations.mjs.map +1 -0
- package/dist/types/src/components/Avatars/Avatar.d.ts +1 -6
- package/dist/types/src/components/Avatars/Avatar.d.ts.map +1 -1
- package/dist/types/src/components/Avatars/AvatarContext.d.ts +9 -0
- package/dist/types/src/components/Avatars/AvatarContext.d.ts.map +1 -0
- package/dist/types/src/components/Avatars/index.d.ts +1 -0
- package/dist/types/src/components/Avatars/index.d.ts.map +1 -1
- package/dist/types/src/components/Breadcrumb/Breadcrumb.d.ts +1 -1
- package/dist/types/src/components/Breadcrumb/Breadcrumb.d.ts.map +1 -1
- package/dist/types/src/components/Breadcrumb/Breadcrumb.stories.d.ts.map +1 -1
- package/dist/types/src/components/Breadcrumb/Breadcrumb.theme.d.ts.map +1 -1
- package/dist/types/src/components/Button/Button.d.ts +1 -6
- package/dist/types/src/components/Button/Button.d.ts.map +1 -1
- package/dist/types/src/components/Button/ButtonGroupContext.d.ts +9 -0
- package/dist/types/src/components/Button/ButtonGroupContext.d.ts.map +1 -0
- package/dist/types/src/components/Button/IconButton.d.ts.map +1 -1
- package/dist/types/src/components/Button/IconButton.stories.d.ts.map +1 -1
- package/dist/types/src/components/Button/IconButton.theme.d.ts +1 -0
- package/dist/types/src/components/Button/IconButton.theme.d.ts.map +1 -1
- package/dist/types/src/components/Button/SystemIconButton.d.ts +1 -1
- package/dist/types/src/components/Button/SystemIconButton.d.ts.map +1 -1
- package/dist/types/src/components/Button/index.d.ts +1 -0
- package/dist/types/src/components/Button/index.d.ts.map +1 -1
- package/dist/types/src/components/Calendar/Calendar.d.ts +0 -2
- package/dist/types/src/components/Calendar/Calendar.d.ts.map +1 -1
- package/dist/types/src/components/Calendar/index.d.ts +1 -0
- package/dist/types/src/components/Calendar/index.d.ts.map +1 -1
- package/dist/types/src/components/Calendar/parse-calendar-date.d.ts +3 -0
- package/dist/types/src/components/Calendar/parse-calendar-date.d.ts.map +1 -0
- package/dist/types/src/components/Card/Card.d.ts +42 -15
- package/dist/types/src/components/Card/Card.d.ts.map +1 -1
- package/dist/types/src/components/Card/Card.theme.d.ts +0 -1
- package/dist/types/src/components/Card/Card.theme.d.ts.map +1 -1
- package/dist/types/src/components/Carousel/Carousel.d.ts +2 -4
- package/dist/types/src/components/Carousel/Carousel.d.ts.map +1 -1
- package/dist/types/src/components/Carousel/CarouselContext.d.ts +8 -0
- package/dist/types/src/components/Carousel/CarouselContext.d.ts.map +1 -0
- package/dist/types/src/components/Carousel/index.d.ts +1 -0
- package/dist/types/src/components/Carousel/index.d.ts.map +1 -1
- package/dist/types/src/components/Clipboard/ClipboardContext.d.ts +7 -0
- package/dist/types/src/components/Clipboard/ClipboardContext.d.ts.map +1 -0
- package/dist/types/src/components/Clipboard/ClipboardProvider.d.ts +0 -6
- package/dist/types/src/components/Clipboard/ClipboardProvider.d.ts.map +1 -1
- package/dist/types/src/components/Clipboard/index.d.ts +1 -1
- package/dist/types/src/components/Clipboard/index.d.ts.map +1 -1
- package/dist/types/src/components/Column/Column.d.ts +7 -12
- package/dist/types/src/components/Column/Column.d.ts.map +1 -1
- package/dist/types/src/components/Column/Column.stories.d.ts +2 -2
- package/dist/types/src/components/Column/Column.theme.d.ts +0 -1
- package/dist/types/src/components/Column/Column.theme.d.ts.map +1 -1
- package/dist/types/src/components/Column/ColumnContext.d.ts +9 -0
- package/dist/types/src/components/Column/ColumnContext.d.ts.map +1 -0
- package/dist/types/src/components/Column/index.d.ts +1 -0
- package/dist/types/src/components/Column/index.d.ts.map +1 -1
- package/dist/types/src/components/Column/withColumn.d.ts +40 -4
- package/dist/types/src/components/Column/withColumn.d.ts.map +1 -1
- package/dist/types/src/components/DatePicker/DatePicker.d.ts +0 -10
- package/dist/types/src/components/DatePicker/DatePicker.d.ts.map +1 -1
- package/dist/types/src/components/DatePicker/DatePickerContext.d.ts +13 -0
- package/dist/types/src/components/DatePicker/DatePickerContext.d.ts.map +1 -0
- package/dist/types/src/components/DatePicker/index.d.ts +1 -0
- package/dist/types/src/components/DatePicker/index.d.ts.map +1 -1
- package/dist/types/src/components/Dialog/AlertDialog.d.ts +3 -3
- package/dist/types/src/components/Dialog/Dialog.d.ts +3 -3
- package/dist/types/src/components/ErrorFallback/ErrorStack.d.ts +5 -10
- package/dist/types/src/components/ErrorFallback/ErrorStack.d.ts.map +1 -1
- package/dist/types/src/components/ErrorFallback/index.d.ts +1 -0
- package/dist/types/src/components/ErrorFallback/index.d.ts.map +1 -1
- package/dist/types/src/components/ErrorFallback/parse-stack.d.ts +8 -0
- package/dist/types/src/components/ErrorFallback/parse-stack.d.ts.map +1 -0
- package/dist/types/src/components/Focus/Focus.d.ts +2 -10
- package/dist/types/src/components/Focus/Focus.d.ts.map +1 -1
- package/dist/types/src/components/Focus/FocusContext.d.ts +10 -0
- package/dist/types/src/components/Focus/FocusContext.d.ts.map +1 -0
- package/dist/types/src/components/Focus/index.d.ts +1 -0
- package/dist/types/src/components/Focus/index.d.ts.map +1 -1
- package/dist/types/src/components/Input/Input.d.ts +9 -10
- package/dist/types/src/components/Input/Input.d.ts.map +1 -1
- package/dist/types/src/components/Input/Input.stories.d.ts +7 -2
- package/dist/types/src/components/Input/Input.stories.d.ts.map +1 -1
- package/dist/types/src/components/Input/Input.theme.d.ts +13 -0
- package/dist/types/src/components/Input/Input.theme.d.ts.map +1 -1
- package/dist/types/src/components/Input/InputTriggerContext.d.ts +15 -0
- package/dist/types/src/components/Input/InputTriggerContext.d.ts.map +1 -0
- package/dist/types/src/components/Input/SegmentedInput.d.ts.map +1 -1
- package/dist/types/src/components/Input/index.d.ts +1 -0
- package/dist/types/src/components/Input/index.d.ts.map +1 -1
- package/dist/types/src/components/Main/Main.d.ts +2 -35
- package/dist/types/src/components/Main/Main.d.ts.map +1 -1
- package/dist/types/src/components/Main/Main.stories.d.ts.map +1 -1
- package/dist/types/src/components/Main/Main.theme.d.ts.map +1 -1
- package/dist/types/src/components/Main/MainContext.d.ts +38 -0
- package/dist/types/src/components/Main/MainContext.d.ts.map +1 -0
- package/dist/types/src/components/Main/index.d.ts +1 -0
- package/dist/types/src/components/Main/index.d.ts.map +1 -1
- package/dist/types/src/components/MediaPlayer/MediaPlayer.d.ts +1 -17
- package/dist/types/src/components/MediaPlayer/MediaPlayer.d.ts.map +1 -1
- package/dist/types/src/components/MediaPlayer/index.d.ts +1 -0
- package/dist/types/src/components/MediaPlayer/index.d.ts.map +1 -1
- package/dist/types/src/components/MediaPlayer/media-kind.d.ts +18 -0
- package/dist/types/src/components/MediaPlayer/media-kind.d.ts.map +1 -0
- package/dist/types/src/components/Menu/DropdownMenu.d.ts +6 -22
- package/dist/types/src/components/Menu/DropdownMenu.d.ts.map +1 -1
- package/dist/types/src/components/Menu/DropdownMenu.stories.d.ts +1 -11
- package/dist/types/src/components/Menu/DropdownMenu.stories.d.ts.map +1 -1
- package/dist/types/src/components/Menu/DropdownMenuContext.d.ts +27 -0
- package/dist/types/src/components/Menu/DropdownMenuContext.d.ts.map +1 -0
- package/dist/types/src/components/Menu/index.d.ts +1 -0
- package/dist/types/src/components/Menu/index.d.ts.map +1 -1
- package/dist/types/src/components/Message/Message.d.ts +11 -6
- package/dist/types/src/components/Message/Message.d.ts.map +1 -1
- package/dist/types/src/components/Message/Message.stories.d.ts +4 -1
- package/dist/types/src/components/Message/Message.stories.d.ts.map +1 -1
- package/dist/types/src/components/Message/Message.theme.d.ts.map +1 -1
- package/dist/types/src/components/Message/index.d.ts +1 -0
- package/dist/types/src/components/Message/index.d.ts.map +1 -1
- package/dist/types/src/components/Message/message-icons.d.ts +3 -0
- package/dist/types/src/components/Message/message-icons.d.ts.map +1 -0
- package/dist/types/src/components/Panel/Panel.d.ts +4 -4
- package/dist/types/src/components/Panel/Panel.stories.d.ts.map +1 -1
- package/dist/types/src/components/Panel/Panel.theme.d.ts +1 -1
- package/dist/types/src/components/Panel/Panel.theme.d.ts.map +1 -1
- package/dist/types/src/components/Popover/Popover.d.ts +6 -10
- package/dist/types/src/components/Popover/Popover.d.ts.map +1 -1
- package/dist/types/src/components/Popover/PopoverContext.d.ts +29 -0
- package/dist/types/src/components/Popover/PopoverContext.d.ts.map +1 -0
- package/dist/types/src/components/Popover/index.d.ts +1 -0
- package/dist/types/src/components/Popover/index.d.ts.map +1 -1
- package/dist/types/src/components/ScrollArea/ScrollArea.d.ts +2 -2
- package/dist/types/src/components/ScrollArea/ScrollArea.stories.d.ts +2 -2
- package/dist/types/src/components/ScrollContainer/ScrollContainer.d.ts +3 -16
- package/dist/types/src/components/ScrollContainer/ScrollContainer.d.ts.map +1 -1
- package/dist/types/src/components/ScrollContainer/ScrollContainerContext.d.ts +16 -0
- package/dist/types/src/components/ScrollContainer/ScrollContainerContext.d.ts.map +1 -0
- package/dist/types/src/components/ScrollContainer/index.d.ts +1 -0
- package/dist/types/src/components/ScrollContainer/index.d.ts.map +1 -1
- package/dist/types/src/components/Slider/Slider.d.ts +25 -0
- package/dist/types/src/components/Slider/Slider.d.ts.map +1 -0
- package/dist/types/src/components/Slider/Slider.stories.d.ts +29 -0
- package/dist/types/src/components/Slider/Slider.stories.d.ts.map +1 -0
- package/dist/types/src/components/Slider/Slider.test.d.ts +2 -0
- package/dist/types/src/components/Slider/Slider.test.d.ts.map +1 -0
- package/dist/types/src/components/Slider/Slider.theme.d.ts +7 -0
- package/dist/types/src/components/Slider/Slider.theme.d.ts.map +1 -0
- package/dist/types/src/components/Slider/index.d.ts +2 -0
- package/dist/types/src/components/Slider/index.d.ts.map +1 -0
- package/dist/types/src/components/Splitter/Splitter.d.ts +3 -3
- package/dist/types/src/components/Status/Status.d.ts.map +1 -1
- package/dist/types/src/components/Toolbar/Toolbar.d.ts +4 -2
- package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -1
- package/dist/types/src/components/Toolbar/Toolbar.theme.d.ts.map +1 -1
- package/dist/types/src/components/Tooltip/TextTooltip.d.ts.map +1 -1
- package/dist/types/src/components/Tooltip/Tooltip.d.ts +2 -23
- package/dist/types/src/components/Tooltip/Tooltip.d.ts.map +1 -1
- package/dist/types/src/components/Tooltip/TooltipContext.d.ts +35 -0
- package/dist/types/src/components/Tooltip/TooltipContext.d.ts.map +1 -0
- package/dist/types/src/components/Tooltip/index.d.ts +1 -0
- package/dist/types/src/components/Tooltip/index.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +1 -0
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/exemplars/generics.stories.d.ts +1 -1
- package/dist/types/src/hooks/useIconHref.d.ts +8 -0
- package/dist/types/src/hooks/useIconHref.d.ts.map +1 -1
- package/dist/types/src/hooks/useThemeContext.d.ts +2 -1
- package/dist/types/src/hooks/useThemeContext.d.ts.map +1 -1
- package/dist/types/src/hooks/useThemeContext.test.d.ts +2 -0
- package/dist/types/src/hooks/useThemeContext.test.d.ts.map +1 -0
- package/dist/types/src/playground/Density.stories.d.ts +11 -0
- package/dist/types/src/playground/Density.stories.d.ts.map +1 -0
- package/dist/types/src/playground/Elevation.stories.d.ts +14 -0
- package/dist/types/src/playground/Elevation.stories.d.ts.map +1 -0
- package/dist/types/src/primitives/Container/Container.d.ts +1 -1
- package/dist/types/src/primitives/Container/Container.d.ts.map +1 -1
- package/dist/types/src/primitives/DensityProvider/DensityContext.d.ts +6 -0
- package/dist/types/src/primitives/DensityProvider/DensityContext.d.ts.map +1 -0
- package/dist/types/src/primitives/DensityProvider/DensityProvider.d.ts +10 -4
- package/dist/types/src/primitives/DensityProvider/DensityProvider.d.ts.map +1 -1
- package/dist/types/src/primitives/DensityProvider/index.d.ts +1 -0
- package/dist/types/src/primitives/DensityProvider/index.d.ts.map +1 -1
- package/dist/types/src/primitives/Flex/Flex.d.ts +1 -1
- package/dist/types/src/primitives/Flex/Flex.d.ts.map +1 -1
- package/dist/types/src/primitives/Grid/Grid.d.ts +1 -1
- package/dist/types/src/primitives/Grid/Grid.d.ts.map +1 -1
- package/dist/types/src/primitives/ThemeProvider/IconRegistry.d.ts +15 -0
- package/dist/types/src/primitives/ThemeProvider/IconRegistry.d.ts.map +1 -0
- package/dist/types/src/primitives/ThemeProvider/ThemeProvider.d.ts +1 -2
- package/dist/types/src/primitives/ThemeProvider/ThemeProvider.d.ts.map +1 -1
- package/dist/types/src/primitives/ThemeProvider/ThemeProvider.stories.d.ts +1 -1
- package/dist/types/src/primitives/ThemeProvider/TranslationsContext.d.ts +112 -0
- package/dist/types/src/primitives/ThemeProvider/TranslationsContext.d.ts.map +1 -0
- package/dist/types/src/primitives/ThemeProvider/TranslationsProvider.d.ts +0 -109
- package/dist/types/src/primitives/ThemeProvider/TranslationsProvider.d.ts.map +1 -1
- package/dist/types/src/primitives/ThemeProvider/icon-registry.d.ts +34 -0
- package/dist/types/src/primitives/ThemeProvider/icon-registry.d.ts.map +1 -0
- package/dist/types/src/primitives/ThemeProvider/index.d.ts +3 -1
- package/dist/types/src/primitives/ThemeProvider/index.d.ts.map +1 -1
- package/dist/types/src/testing/decorators/withTheme.d.ts +1 -1
- package/dist/types/src/testing/decorators/withTheme.d.ts.map +1 -1
- package/dist/types/src/theme/defaultTheme.d.ts.map +1 -1
- package/dist/types/src/theme/index.d.ts +1 -0
- package/dist/types/src/theme/index.d.ts.map +1 -1
- package/dist/types/src/util/slots.d.ts +6 -3
- package/dist/types/src/util/slots.d.ts.map +1 -1
- package/dist/types/src/util/slots.stories.d.ts +14 -0
- package/dist/types/src/util/slots.stories.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +25 -27
- package/src/components/Avatars/Avatar.tsx +1 -11
- package/src/components/Avatars/AvatarContext.ts +16 -0
- package/src/components/Avatars/index.ts +2 -0
- package/src/components/Breadcrumb/Breadcrumb.stories.tsx +27 -25
- package/src/components/Breadcrumb/Breadcrumb.theme.ts +7 -5
- package/src/components/Breadcrumb/Breadcrumb.tsx +2 -2
- package/src/components/Button/Button.tsx +2 -11
- package/src/components/Button/ButtonGroupContext.ts +17 -0
- package/src/components/Button/IconButton.stories.tsx +2 -3
- package/src/components/Button/IconButton.theme.ts +15 -2
- package/src/components/Button/IconButton.tsx +6 -1
- package/src/components/Button/SystemIconButton.tsx +23 -16
- package/src/components/Button/index.ts +2 -0
- package/src/components/Calendar/Calendar.theme.ts +5 -5
- package/src/components/Calendar/Calendar.tsx +1 -3
- package/src/components/Calendar/index.ts +2 -0
- package/src/components/Calendar/parse-calendar-date.ts +9 -0
- package/src/components/Card/Card.theme.ts +48 -38
- package/src/components/Card/Card.tsx +77 -16
- package/src/components/Carousel/Carousel.tsx +4 -11
- package/src/components/Carousel/CarouselContext.ts +17 -0
- package/src/components/Carousel/index.ts +2 -0
- package/src/components/Clipboard/ClipboardContext.ts +20 -0
- package/src/components/Clipboard/ClipboardProvider.tsx +2 -12
- package/src/components/Clipboard/CopyButton.tsx +1 -1
- package/src/components/Clipboard/index.ts +1 -1
- package/src/components/Column/Column.stories.tsx +2 -2
- package/src/components/Column/Column.theme.ts +2 -11
- package/src/components/Column/Column.tsx +35 -57
- package/src/components/Column/ColumnContext.ts +22 -0
- package/src/components/Column/index.ts +2 -0
- package/src/components/Column/withColumn.ts +41 -4
- package/src/components/DatePicker/DatePicker.theme.ts +2 -2
- package/src/components/DatePicker/DatePicker.tsx +1 -14
- package/src/components/DatePicker/DatePickerContext.ts +21 -0
- package/src/components/DatePicker/index.ts +2 -0
- package/src/components/ErrorFallback/ErrorStack.tsx +8 -28
- package/src/components/ErrorFallback/index.ts +1 -0
- package/src/components/ErrorFallback/parse-stack.ts +33 -0
- package/src/components/Focus/Focus.stories.tsx +6 -6
- package/src/components/Focus/Focus.tsx +2 -30
- package/src/components/Focus/FocusContext.ts +22 -0
- package/src/components/Focus/index.ts +2 -0
- package/src/components/Image/Image.tsx +1 -1
- package/src/components/Input/Input.stories.tsx +63 -48
- package/src/components/Input/Input.theme.ts +33 -27
- package/src/components/Input/Input.tsx +46 -43
- package/src/components/Input/InputTriggerContext.ts +45 -0
- package/src/components/Input/SegmentedInput.tsx +2 -1
- package/src/components/Input/index.ts +2 -0
- package/src/components/Main/Main.stories.tsx +2 -1
- package/src/components/Main/Main.theme.ts +10 -1
- package/src/components/Main/Main.tsx +1 -115
- package/src/components/Main/MainContext.ts +126 -0
- package/src/components/Main/index.ts +2 -0
- package/src/components/MediaPlayer/MediaPlayer.tsx +16 -47
- package/src/components/MediaPlayer/index.ts +2 -0
- package/src/components/MediaPlayer/media-kind.ts +41 -0
- package/src/components/Menu/DropdownMenu.tsx +27 -44
- package/src/components/Menu/DropdownMenuContext.ts +35 -0
- package/src/components/Menu/Menu.theme.ts +3 -3
- package/src/components/Menu/index.ts +2 -0
- package/src/components/Message/Message.stories.tsx +32 -15
- package/src/components/Message/Message.theme.ts +8 -2
- package/src/components/Message/Message.tsx +47 -23
- package/src/components/Message/index.ts +2 -0
- package/src/components/Message/message-icons.ts +16 -0
- package/src/components/Panel/Panel.stories.tsx +15 -2
- package/src/components/Panel/Panel.theme.ts +15 -6
- package/src/components/Popover/Popover.theme.ts +1 -1
- package/src/components/Popover/Popover.tsx +22 -37
- package/src/components/Popover/PopoverContext.ts +32 -0
- package/src/components/Popover/index.ts +2 -0
- package/src/components/ScrollContainer/ScrollContainer.stories.tsx +1 -1
- package/src/components/ScrollContainer/ScrollContainer.tsx +1 -18
- package/src/components/ScrollContainer/ScrollContainerContext.ts +25 -0
- package/src/components/ScrollContainer/index.ts +2 -0
- package/src/components/Select/Select.theme.ts +2 -2
- package/src/components/Slider/Slider.stories.tsx +107 -0
- package/src/components/Slider/Slider.test.tsx +105 -0
- package/src/components/Slider/Slider.theme.ts +38 -0
- package/src/components/Slider/Slider.tsx +64 -0
- package/src/components/Slider/index.ts +5 -0
- package/src/components/Status/Status.theme.ts +1 -1
- package/src/components/Status/Status.tsx +0 -1
- package/src/components/Tag/Tag.stories.tsx +1 -1
- package/src/components/Toolbar/Toolbar.theme.ts +14 -5
- package/src/components/Toolbar/Toolbar.tsx +5 -1
- package/src/components/Tooltip/TextTooltip.tsx +2 -1
- package/src/components/Tooltip/Tooltip.tsx +12 -35
- package/src/components/Tooltip/TooltipContext.ts +41 -0
- package/src/components/Tooltip/index.ts +2 -0
- package/src/components/index.ts +1 -0
- package/src/hooks/useIconHref.ts +26 -5
- package/src/hooks/useThemeContext.test.tsx +33 -0
- package/src/hooks/useThemeContext.ts +28 -3
- package/src/playground/Density.stories.tsx +41 -0
- package/src/playground/Elevation.stories.tsx +348 -0
- package/src/primitives/DensityProvider/DensityContext.ts +15 -0
- package/src/primitives/DensityProvider/DensityProvider.tsx +12 -6
- package/src/primitives/DensityProvider/index.ts +1 -0
- package/src/primitives/Flex/Flex.stories.tsx +1 -1
- package/src/primitives/Grid/Grid.stories.tsx +1 -1
- package/src/primitives/ThemeProvider/IconRegistry.tsx +42 -0
- package/src/primitives/ThemeProvider/ThemeProvider.tsx +16 -15
- package/src/primitives/ThemeProvider/TranslationsContext.ts +24 -0
- package/src/primitives/ThemeProvider/TranslationsProvider.tsx +4 -16
- package/src/primitives/ThemeProvider/icon-registry.ts +272 -0
- package/src/primitives/ThemeProvider/index.ts +9 -1
- package/src/testing/decorators/withLayout.tsx +4 -4
- package/src/testing/decorators/withLayoutVariants.tsx +3 -3
- package/src/testing/decorators/withTheme.tsx +1 -2
- package/src/theme/defaultTheme.ts +2 -0
- package/src/theme/index.ts +1 -0
- package/src/util/slots.stories.tsx +80 -0
- package/src/util/slots.ts +14 -5
- package/dist/lib/browser/chunk-CMHHVHX3.mjs +0 -46
- package/dist/lib/browser/chunk-CMHHVHX3.mjs.map +0 -7
- package/dist/lib/browser/chunk-GTHV4WYK.mjs +0 -1499
- package/dist/lib/browser/chunk-GTHV4WYK.mjs.map +0 -7
- package/dist/lib/browser/index.mjs +0 -5632
- package/dist/lib/browser/index.mjs.map +0 -7
- package/dist/lib/browser/meta.json +0 -1
- package/dist/lib/browser/testing/index.mjs +0 -133
- package/dist/lib/browser/testing/index.mjs.map +0 -7
- package/dist/lib/browser/translations.mjs +0 -9
- package/dist/lib/browser/translations.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-3VSKWNCQ.mjs +0 -1501
- package/dist/lib/node-esm/chunk-3VSKWNCQ.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-P4KFQGJI.mjs +0 -48
- package/dist/lib/node-esm/chunk-P4KFQGJI.mjs.map +0 -7
- package/dist/lib/node-esm/index.mjs +0 -5633
- package/dist/lib/node-esm/index.mjs.map +0 -7
- package/dist/lib/node-esm/meta.json +0 -1
- package/dist/lib/node-esm/testing/index.mjs +0 -134
- package/dist/lib/node-esm/testing/index.mjs.map +0 -7
- package/dist/lib/node-esm/translations.mjs +0 -10
- package/dist/lib/node-esm/translations.mjs.map +0 -7
- package/src/components/Column/AUDIT.md +0 -148
- package/src/components/Focus/AUDIT.md +0 -43
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { cleanup, render, screen } from '@testing-library/react';
|
|
6
|
+
import React, { type PropsWithChildren } from 'react';
|
|
7
|
+
import { afterEach, describe, test } from 'vitest';
|
|
8
|
+
|
|
9
|
+
import { ThemeProvider } from '../../primitives';
|
|
10
|
+
import { defaultTx } from '../../theme';
|
|
11
|
+
import { Slider } from './Slider';
|
|
12
|
+
|
|
13
|
+
describe('Slider', () => {
|
|
14
|
+
afterEach(() => {
|
|
15
|
+
cleanup();
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
test('renders one thumb per value with real (non-logical) size utility classes', ({ expect }) => {
|
|
19
|
+
render(<Slider defaultValue={[25, 75]} max={100} step={1} thumbLabels={['Minimum', 'Maximum']} />, {
|
|
20
|
+
wrapper: Wrapper,
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const thumbs = screen.getAllByRole('slider');
|
|
24
|
+
expect(thumbs).toHaveLength(2);
|
|
25
|
+
|
|
26
|
+
// Regression guard for the invisible-thumb bug: `is-4`/`bs-4` are not real Tailwind utilities
|
|
27
|
+
// in this repo's config (no logical inline-/block-size plugin is configured), so they generated
|
|
28
|
+
// no CSS and the thumb collapsed to zero size. happy-dom has no layout engine, so a computed
|
|
29
|
+
// `getBoundingClientRect`/`getComputedStyle` size assertion cannot fail meaningfully here (it
|
|
30
|
+
// would pass or fail independent of the actual applied CSS) — asserting the class list carries
|
|
31
|
+
// real (non-logical) sizing utilities, and never the invalid `is-*`/`bs-*` ones, is the
|
|
32
|
+
// strongest check available in this environment. Matches any size value, not a specific one.
|
|
33
|
+
for (const thumb of thumbs) {
|
|
34
|
+
expect(thumb.className).toMatch(/\bh-\d+\b/);
|
|
35
|
+
expect(thumb.className).toMatch(/\bw-\d+\b/);
|
|
36
|
+
expect(thumb.className).not.toMatch(/\bis-\d+\b/);
|
|
37
|
+
expect(thumb.className).not.toMatch(/\bbs-\d+\b/);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test('keeps the thumb rendered (never removed) when disabled', ({ expect }) => {
|
|
42
|
+
render(<Slider defaultValue={[50]} max={100} step={1} disabled aria-label='Value' />, { wrapper: Wrapper });
|
|
43
|
+
|
|
44
|
+
// Disabled state is expressed via the root's `opacity-50` (visually muted), not by unmounting
|
|
45
|
+
// the thumb — assert it is still present with its sizing classes intact.
|
|
46
|
+
const thumb = screen.getByRole('slider');
|
|
47
|
+
expect(thumb.className).toMatch(/\bh-\d+\b/);
|
|
48
|
+
expect(thumb.className).toMatch(/\bw-\d+\b/);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
test('gives each thumb an accessible name via thumbLabels', ({ expect }) => {
|
|
52
|
+
render(<Slider defaultValue={[25, 75]} max={100} step={1} thumbLabels={['Minimum', 'Maximum']} />, {
|
|
53
|
+
wrapper: Wrapper,
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// `role="slider"` has no visible text an `Input.Label`'s `htmlFor` can reach; `thumbLabels`
|
|
57
|
+
// is the only way to give it a name exposed to assistive tech.
|
|
58
|
+
expect(screen.getByRole('slider', { name: 'Minimum' })).toBeTruthy();
|
|
59
|
+
expect(screen.getByRole('slider', { name: 'Maximum' })).toBeTruthy();
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test('gives a single thumb an accessible name via a plain aria-label', ({ expect }) => {
|
|
63
|
+
render(<Slider defaultValue={[50]} max={100} step={1} aria-label='Volume' />, { wrapper: Wrapper });
|
|
64
|
+
|
|
65
|
+
// Ergonomic shorthand for the common one-thumb case: no need to wrap the label in `thumbLabels`.
|
|
66
|
+
expect(screen.getByRole('slider', { name: 'Volume' })).toBeTruthy();
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test('every rendered thumb, across default and multi-thumb usage, exposes an accessible name', ({ expect }) => {
|
|
70
|
+
const { unmount } = render(<Slider defaultValue={[50]} max={100} step={1} aria-label='Value' />, {
|
|
71
|
+
wrapper: Wrapper,
|
|
72
|
+
});
|
|
73
|
+
for (const thumb of screen.getAllByRole('slider')) {
|
|
74
|
+
expect(thumb.getAttribute('aria-label')).toBeTruthy();
|
|
75
|
+
}
|
|
76
|
+
unmount();
|
|
77
|
+
|
|
78
|
+
render(<Slider defaultValue={[25, 75]} max={100} step={1} thumbLabels={['Minimum', 'Maximum']} />, {
|
|
79
|
+
wrapper: Wrapper,
|
|
80
|
+
});
|
|
81
|
+
for (const thumb of screen.getAllByRole('slider')) {
|
|
82
|
+
expect(thumb.getAttribute('aria-label')).toBeTruthy();
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
test('throws when thumbLabels covers only some of the rendered thumbs', ({ expect }) => {
|
|
87
|
+
// Matching the invariant's own message, not just "it threw": a bare `toThrow()` would also be
|
|
88
|
+
// satisfied by an unrelated render crash, which is exactly what this guard must not accept.
|
|
89
|
+
expect(() =>
|
|
90
|
+
render(<Slider defaultValue={[25, 75]} max={100} step={1} thumbLabels={['Minimum']} />, { wrapper: Wrapper }),
|
|
91
|
+
).toThrow('Slider: thumbLabels has 1 entries but 2 thumb(s) are rendered.');
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
test('throws when a multi-thumb slider is given no labels at all', ({ expect }) => {
|
|
95
|
+
// The other half of the guard: `aria-label` names only a single thumb, so omitting `thumbLabels`
|
|
96
|
+
// on a two-thumb slider would silently leave one thumb unnamed.
|
|
97
|
+
expect(() =>
|
|
98
|
+
render(<Slider defaultValue={[25, 75]} max={100} step={1} aria-label='Range' />, { wrapper: Wrapper }),
|
|
99
|
+
).toThrow('Slider: pass thumbLabels (2 entries) or, for a single thumb, aria-label.');
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
// `ThemeProvider`'s default `tx` is a no-op (`() => undefined`) — pass `defaultTx` explicitly so
|
|
104
|
+
// `tx('slider.thumb', ...)` actually resolves classes, matching `useThemeContext.test.tsx`'s pattern.
|
|
105
|
+
const Wrapper = ({ children }: PropsWithChildren) => <ThemeProvider tx={defaultTx}>{children}</ThemeProvider>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { mx } from '@dxos/ui-theme';
|
|
6
|
+
import { type ComponentFunction, type Theme } from '@dxos/ui-types';
|
|
7
|
+
|
|
8
|
+
export type SliderStyleProps = {
|
|
9
|
+
orientation?: 'horizontal' | 'vertical';
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const root: ComponentFunction<SliderStyleProps> = ({ orientation, disabled }, ...etc) =>
|
|
14
|
+
mx(
|
|
15
|
+
'relative flex touch-none select-none items-center',
|
|
16
|
+
orientation === 'vertical' ? 'h-full w-3 flex-col' : 'w-full h-3',
|
|
17
|
+
disabled && 'opacity-50 pointer-events-none',
|
|
18
|
+
...etc,
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
const track: ComponentFunction<SliderStyleProps> = ({ orientation }, ...etc) =>
|
|
22
|
+
mx(
|
|
23
|
+
'relative grow overflow-hidden rounded-full bg-input-surface',
|
|
24
|
+
orientation === 'vertical' ? 'w-1 h-full' : 'h-1 w-full',
|
|
25
|
+
...etc,
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
const range: ComponentFunction<SliderStyleProps> = ({ orientation }, ...etc) =>
|
|
29
|
+
mx('absolute bg-accent-bg', orientation === 'vertical' ? 'w-full' : 'h-full', ...etc);
|
|
30
|
+
|
|
31
|
+
const thumb: ComponentFunction<SliderStyleProps> = (_props, ...etc) =>
|
|
32
|
+
mx(
|
|
33
|
+
'block h-3 w-3 shrink-0 rounded-full bg-base-surface border-2 border-accent-bg shadow-sm transition-colors dx-focus-ring',
|
|
34
|
+
'hover:bg-hover-surface',
|
|
35
|
+
...etc,
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
export const sliderTheme: Theme<SliderStyleProps> = { root, track, range, thumb };
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import * as SliderPrimitive from '@radix-ui/react-slider';
|
|
6
|
+
import React, { forwardRef } from 'react';
|
|
7
|
+
|
|
8
|
+
import { invariant } from '@dxos/invariant';
|
|
9
|
+
|
|
10
|
+
import { useThemeContext } from '../../hooks';
|
|
11
|
+
import { type ThemedClassName } from '../../util';
|
|
12
|
+
|
|
13
|
+
type SliderProps = ThemedClassName<SliderPrimitive.SliderProps> & {
|
|
14
|
+
/**
|
|
15
|
+
* Accessible name per thumb, by index — `role="slider"` has no visible text a label's `htmlFor`
|
|
16
|
+
* can reach, so this is the only way to name it for assistive tech. Required whenever there is
|
|
17
|
+
* more than one thumb; for the common single-thumb case, a plain `aria-label` works instead.
|
|
18
|
+
*/
|
|
19
|
+
thumbLabels?: string[];
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/** Range input built on the Radix slider primitive; supports one or more thumbs. */
|
|
23
|
+
const Slider = forwardRef<HTMLSpanElement, SliderProps>(
|
|
24
|
+
(
|
|
25
|
+
{ classNames, orientation = 'horizontal', disabled, thumbLabels, 'aria-label': ariaLabel, ...props },
|
|
26
|
+
forwardedRef,
|
|
27
|
+
) => {
|
|
28
|
+
const { tx } = useThemeContext();
|
|
29
|
+
const styleProps = { orientation, disabled };
|
|
30
|
+
const thumbCount = props.value?.length ?? props.defaultValue?.length ?? 1;
|
|
31
|
+
|
|
32
|
+
// Every thumb must expose an accessible name: either one label per thumb, or (for the common
|
|
33
|
+
// single-thumb case) a plain `aria-label` passthrough — never silently render an unnamed thumb.
|
|
34
|
+
invariant(
|
|
35
|
+
thumbLabels ? thumbLabels.length === thumbCount : thumbCount === 1 && ariaLabel !== undefined,
|
|
36
|
+
thumbLabels
|
|
37
|
+
? `Slider: thumbLabels has ${thumbLabels.length} entries but ${thumbCount} thumb(s) are rendered.`
|
|
38
|
+
: `Slider: pass thumbLabels (${thumbCount} entries) or, for a single thumb, aria-label.`,
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
const labelFor = (index: number) => thumbLabels?.[index] ?? ariaLabel;
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<SliderPrimitive.Root
|
|
45
|
+
{...props}
|
|
46
|
+
orientation={orientation}
|
|
47
|
+
disabled={disabled}
|
|
48
|
+
className={tx('slider.root', styleProps, classNames)}
|
|
49
|
+
ref={forwardedRef}
|
|
50
|
+
>
|
|
51
|
+
<SliderPrimitive.Track className={tx('slider.track', styleProps)}>
|
|
52
|
+
<SliderPrimitive.Range className={tx('slider.range', styleProps)} />
|
|
53
|
+
</SliderPrimitive.Track>
|
|
54
|
+
{Array.from({ length: thumbCount }, (_unused, index) => (
|
|
55
|
+
<SliderPrimitive.Thumb key={index} className={tx('slider.thumb', styleProps)} aria-label={labelFor(index)} />
|
|
56
|
+
))}
|
|
57
|
+
</SliderPrimitive.Root>
|
|
58
|
+
);
|
|
59
|
+
},
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
export type { SliderProps };
|
|
63
|
+
|
|
64
|
+
export { Slider };
|
|
@@ -13,7 +13,7 @@ export type StatusStyleProps = {
|
|
|
13
13
|
const root: ComponentFunction<StatusStyleProps> = ({ variant = 'default' }, ...etc) =>
|
|
14
14
|
mx(
|
|
15
15
|
'h-1 relative rounded-full overflow-hidden',
|
|
16
|
-
variant === 'main-bottom' ? 'w-full block' : 'inline-
|
|
16
|
+
variant === 'main-bottom' ? 'w-full block' : 'inline-block bg-base-surface',
|
|
17
17
|
...etc,
|
|
18
18
|
);
|
|
19
19
|
|
|
@@ -26,7 +26,6 @@ const Status = forwardRef<HTMLSpanElement, StatusProps>(
|
|
|
26
26
|
ref={forwardedRef}
|
|
27
27
|
>
|
|
28
28
|
<span
|
|
29
|
-
role='none'
|
|
30
29
|
className={tx('status.bar', { indeterminate, variant }, classNames)}
|
|
31
30
|
{...(!indeterminate && { style: { width: `${Math.round(progress * 100)}%` } })}
|
|
32
31
|
/>
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
6
6
|
import React from 'react';
|
|
7
7
|
|
|
8
|
-
import { hues } from '@dxos/ui-
|
|
8
|
+
import { hues } from '@dxos/ui-types';
|
|
9
9
|
import { type ChromaticPalette, type MessageValence } from '@dxos/ui-types';
|
|
10
10
|
|
|
11
11
|
import { withLayout, withTheme } from '../../testing';
|
|
@@ -14,12 +14,21 @@ export type ToolbarStyleProps = Partial<{
|
|
|
14
14
|
const layout =
|
|
15
15
|
'w-full shrink-0 flex flex-nowrap p-1 gap-1 items-center overflow-x-auto scrollbar-none dx-contain-layout';
|
|
16
16
|
|
|
17
|
+
// The bar declares its density so the shared rule (theme/spacing.css) resizes both the bar and
|
|
18
|
+
// every control inside it; the height then follows the same knob rather than a hard-coded step.
|
|
17
19
|
const root: ComponentFunction<ToolbarStyleProps> = ({ density, disabled, layoutManaged }, ...etc) => {
|
|
18
20
|
return mx(
|
|
19
|
-
'
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
// No shadow here: `Panel.Toolbar` casts the bar's edge shadow, and a toolbar reaches that slot
|
|
22
|
+
// two ways — as a descendant, or merged into it via `asChild`. Only the descendant form can be
|
|
23
|
+
// detected in CSS, so a shadow on this element would double up in the merged form and read as a
|
|
24
|
+
// floating bar. The slot owns it in both.
|
|
25
|
+
'dx-toolbar-surface',
|
|
26
|
+
// As a descendant of a Panel slot the slot has already painted the surface full-width; painting
|
|
27
|
+
// again clamps it to this element, which a `classNames='dx-document'` toolbar renders as a strip
|
|
28
|
+
// floating inside the bar. (Merged via `asChild` there is one element, which must keep it.)
|
|
29
|
+
'[[data-slot=toolbar]_&]:bg-transparent',
|
|
30
|
+
'[[data-slot=statusbar]_&]:bg-transparent',
|
|
31
|
+
density && `dx-density-${density}`,
|
|
23
32
|
disabled && '*:opacity-20',
|
|
24
33
|
!layoutManaged && layout,
|
|
25
34
|
...etc,
|
|
@@ -27,7 +36,7 @@ const root: ComponentFunction<ToolbarStyleProps> = ({ density, disabled, layoutM
|
|
|
27
36
|
};
|
|
28
37
|
|
|
29
38
|
const text: ComponentFunction<ToolbarStyleProps> = (_, ...etc) => {
|
|
30
|
-
return mx('px-2
|
|
39
|
+
return mx('px-2 truncate items-center', ...etc);
|
|
31
40
|
};
|
|
32
41
|
|
|
33
42
|
export const toolbarTheme: Theme<ToolbarStyleProps> = {
|
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
type ToggleGroupItemProps,
|
|
28
28
|
type ToggleProps,
|
|
29
29
|
} from '../Button';
|
|
30
|
+
import { Icon } from '../Icon';
|
|
30
31
|
import { Link, type LinkProps } from '../Link';
|
|
31
32
|
import { DropdownMenu } from '../Menu';
|
|
32
33
|
import { Separator, type SeparatorProps } from '../Separator';
|
|
@@ -303,6 +304,8 @@ ToolbarActionIconButton.displayName = 'Toolbar.ActionIconButton';
|
|
|
303
304
|
|
|
304
305
|
type ToolbarMenuItem<T extends any | void = void> = {
|
|
305
306
|
label: string;
|
|
307
|
+
/** Optional leading icon (e.g. `ph--trash--regular`). */
|
|
308
|
+
icon?: string;
|
|
306
309
|
onClick: (context: T) => void;
|
|
307
310
|
};
|
|
308
311
|
|
|
@@ -329,8 +332,9 @@ function ToolbarMenu<T extends any | void = void>({ context, items }: ToolbarMen
|
|
|
329
332
|
<DropdownMenu.Portal>
|
|
330
333
|
<DropdownMenu.Content>
|
|
331
334
|
<DropdownMenu.Viewport>
|
|
332
|
-
{items?.map(({ label, onClick: onSelect }, index) => (
|
|
335
|
+
{items?.map(({ label, icon, onClick: onSelect }, index) => (
|
|
333
336
|
<DropdownMenu.Item key={index} onSelect={() => onSelect(context as T)}>
|
|
337
|
+
{icon && <Icon icon={icon} />}
|
|
334
338
|
{label}
|
|
335
339
|
</DropdownMenu.Item>
|
|
336
340
|
))}
|
|
@@ -12,7 +12,8 @@ import React, {
|
|
|
12
12
|
useRef,
|
|
13
13
|
} from 'react';
|
|
14
14
|
|
|
15
|
-
import { Tooltip, type
|
|
15
|
+
import { Tooltip, type TooltipTriggerProps } from './Tooltip';
|
|
16
|
+
import { type TooltipScopedProps } from './TooltipContext';
|
|
16
17
|
|
|
17
18
|
export type TextTooltipProps = PropsWithChildren<
|
|
18
19
|
{
|
|
@@ -7,12 +7,10 @@
|
|
|
7
7
|
|
|
8
8
|
import { composeEventHandlers } from '@radix-ui/primitive';
|
|
9
9
|
import { useComposedRefs } from '@radix-ui/react-compose-refs';
|
|
10
|
-
import { createContextScope } from '@radix-ui/react-context';
|
|
11
|
-
import type { Scope } from '@radix-ui/react-context';
|
|
12
10
|
import { DismissableLayer } from '@radix-ui/react-dismissable-layer';
|
|
13
11
|
import { useId } from '@radix-ui/react-id';
|
|
14
12
|
import * as PopperPrimitive from '@radix-ui/react-popper';
|
|
15
|
-
import { type PopperAnchorProps
|
|
13
|
+
import { type PopperAnchorProps } from '@radix-ui/react-popper';
|
|
16
14
|
import { Portal as PortalPrimitive } from '@radix-ui/react-portal';
|
|
17
15
|
import { Presence } from '@radix-ui/react-presence';
|
|
18
16
|
import { Primitive } from '@radix-ui/react-primitive';
|
|
@@ -36,35 +34,16 @@ import React, {
|
|
|
36
34
|
} from 'react';
|
|
37
35
|
|
|
38
36
|
import { useElevationContext, useThemeContext } from '../../hooks';
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
const TOOLTIP_OPEN = 'tooltip.open';
|
|
50
|
-
const TOOLTIP_NAME = 'Tooltip';
|
|
51
|
-
|
|
52
|
-
type TooltipContextValue = {
|
|
53
|
-
contentId: string;
|
|
54
|
-
open: boolean;
|
|
55
|
-
stateAttribute: 'closed' | 'delayed-open' | 'instant-open';
|
|
56
|
-
trigger: TooltipTriggerElement | null;
|
|
57
|
-
onTriggerChange(trigger: TooltipTriggerElement | null, content?: ReactNode, side?: TooltipSide): void;
|
|
58
|
-
onTriggerEnter(): void;
|
|
59
|
-
onTriggerLeave(): void;
|
|
60
|
-
onOpen(): void;
|
|
61
|
-
onClose(): void;
|
|
62
|
-
onPointerInTransitChange(inTransit: boolean): void;
|
|
63
|
-
isPointerInTransitRef: RefObject<boolean>;
|
|
64
|
-
disableHoverableContent: boolean;
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
const [TooltipContextProvider, useTooltipContext] = createTooltipContext<TooltipContextValue>(TOOLTIP_NAME);
|
|
37
|
+
import {
|
|
38
|
+
DEFAULT_DELAY_DURATION,
|
|
39
|
+
TOOLTIP_NAME,
|
|
40
|
+
TOOLTIP_OPEN,
|
|
41
|
+
TooltipContextProvider,
|
|
42
|
+
type TooltipScopedProps,
|
|
43
|
+
createTooltipContext,
|
|
44
|
+
usePopperScope,
|
|
45
|
+
useTooltipContext,
|
|
46
|
+
} from './TooltipContext';
|
|
68
47
|
|
|
69
48
|
type TooltipProviderProps = {
|
|
70
49
|
children?: ReactNode;
|
|
@@ -763,6 +742,4 @@ export const Tooltip = {
|
|
|
763
742
|
Trigger: TooltipTrigger,
|
|
764
743
|
};
|
|
765
744
|
|
|
766
|
-
export {
|
|
767
|
-
|
|
768
|
-
export type { TooltipProviderProps, TooltipScopedProps, TooltipSide, TooltipTriggerProps };
|
|
745
|
+
export type { TooltipProviderProps, TooltipSide, TooltipTriggerElement, TooltipTriggerProps };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { type Scope, createContextScope } from '@radix-ui/react-context';
|
|
6
|
+
import { createPopperScope } from '@radix-ui/react-popper';
|
|
7
|
+
import { type ReactNode, type RefObject } from 'react';
|
|
8
|
+
|
|
9
|
+
import { type TooltipSide, type TooltipTriggerElement } from './Tooltip';
|
|
10
|
+
|
|
11
|
+
// Kept out of `Tooltip.tsx`: react-refresh only fast-refreshes a module whose exports are all
|
|
12
|
+
// components, so a context and its hook exported beside them force a full page reload on every edit.
|
|
13
|
+
|
|
14
|
+
export type TooltipScopedProps<P = {}> = P & { __scopeTooltip?: Scope };
|
|
15
|
+
export const [createTooltipContext, createTooltipScope] = createContextScope('Tooltip', [createPopperScope]);
|
|
16
|
+
export const usePopperScope = createPopperScope();
|
|
17
|
+
|
|
18
|
+
//
|
|
19
|
+
// Tooltip
|
|
20
|
+
//
|
|
21
|
+
|
|
22
|
+
export const DEFAULT_DELAY_DURATION = 700;
|
|
23
|
+
export const TOOLTIP_OPEN = 'tooltip.open';
|
|
24
|
+
export const TOOLTIP_NAME = 'Tooltip';
|
|
25
|
+
|
|
26
|
+
export type TooltipContextValue = {
|
|
27
|
+
contentId: string;
|
|
28
|
+
open: boolean;
|
|
29
|
+
stateAttribute: 'closed' | 'delayed-open' | 'instant-open';
|
|
30
|
+
trigger: TooltipTriggerElement | null;
|
|
31
|
+
onTriggerChange(trigger: TooltipTriggerElement | null, content?: ReactNode, side?: TooltipSide): void;
|
|
32
|
+
onTriggerEnter(): void;
|
|
33
|
+
onTriggerLeave(): void;
|
|
34
|
+
onOpen(): void;
|
|
35
|
+
onClose(): void;
|
|
36
|
+
onPointerInTransitChange(inTransit: boolean): void;
|
|
37
|
+
isPointerInTransitRef: RefObject<boolean>;
|
|
38
|
+
disableHoverableContent: boolean;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export const [TooltipContextProvider, useTooltipContext] = createTooltipContext<TooltipContextValue>(TOOLTIP_NAME);
|
package/src/components/index.ts
CHANGED
package/src/hooks/useIconHref.ts
CHANGED
|
@@ -2,12 +2,33 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { useCallback, useSyncExternalStore } from 'react';
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
import { useIconRegistry } from '../primitives/ThemeProvider/icon-registry';
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Resolves an icon name to a same-document `<use href>`.
|
|
11
|
+
*
|
|
12
|
+
* Returns `undefined` while the icon is not yet present in the in-DOM sprite — kicking off
|
|
13
|
+
* a runtime fetch as a side effect. Once the registry has the symbol (either because the
|
|
14
|
+
* static sprite finished ingesting or because the resolver injected it), the component
|
|
15
|
+
* re-renders via `useSyncExternalStore` and we return `#name`.
|
|
16
|
+
*/
|
|
9
17
|
export const useIconHref = (icon?: string) => {
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
18
|
+
const registry = useIconRegistry();
|
|
19
|
+
|
|
20
|
+
const subscribe = useCallback((listener: () => void) => registry.subscribe(listener), [registry]);
|
|
21
|
+
const getSnapshot = useCallback(() => (icon ? registry.hasIcon(icon) : false), [icon, registry]);
|
|
22
|
+
const getServerSnapshot = useCallback(() => false, []);
|
|
23
|
+
|
|
24
|
+
const hasIcon = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
|
|
25
|
+
|
|
26
|
+
if (!icon) {
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
if (!hasIcon) {
|
|
30
|
+
registry.requestIcon(icon);
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
return `#${icon}`;
|
|
13
34
|
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { renderHook } from '@testing-library/react';
|
|
6
|
+
import React, { type PropsWithChildren } from 'react';
|
|
7
|
+
import { describe, expect, test } from 'vitest';
|
|
8
|
+
|
|
9
|
+
import { ThemeProvider } from '../primitives';
|
|
10
|
+
import { defaultTx } from '../theme';
|
|
11
|
+
import { useThemeContext } from './useThemeContext';
|
|
12
|
+
|
|
13
|
+
describe('useThemeContext', () => {
|
|
14
|
+
// Error-reporting surfaces (e.g. the fatal dialog) must be able to render even
|
|
15
|
+
// when the provider is missing — including the vite dev dual-module case where
|
|
16
|
+
// the provider supplied a different ThemeContext identity than the consumer's.
|
|
17
|
+
test('falls back to the default theme without a provider', () => {
|
|
18
|
+
const { result } = renderHook(() => useThemeContext());
|
|
19
|
+
expect(result.current.tx).toBe(defaultTx);
|
|
20
|
+
expect(result.current.themeMode).toBe('dark');
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test('returns the provider value when present', () => {
|
|
24
|
+
const wrapper = ({ children }: PropsWithChildren) => (
|
|
25
|
+
<ThemeProvider tx={defaultTx} themeMode='light'>
|
|
26
|
+
{children}
|
|
27
|
+
</ThemeProvider>
|
|
28
|
+
);
|
|
29
|
+
const { result } = renderHook(() => useThemeContext(), { wrapper });
|
|
30
|
+
expect(result.current.tx).toBe(defaultTx);
|
|
31
|
+
expect(result.current.themeMode).toBe('light');
|
|
32
|
+
});
|
|
33
|
+
});
|
|
@@ -4,8 +4,33 @@
|
|
|
4
4
|
|
|
5
5
|
import { useContext } from 'react';
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import { log } from '@dxos/log';
|
|
8
8
|
|
|
9
|
-
import { ThemeContext } from '../primitives';
|
|
9
|
+
import { ThemeContext, type ThemeContextValue } from '../primitives';
|
|
10
|
+
import { defaultTx } from '../theme';
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
// Failing soft (rather than throwing) keeps error-reporting surfaces renderable:
|
|
13
|
+
// the fatal dialog itself consumes this hook, and a missing provider — including
|
|
14
|
+
// the vite dev dual-module split, where the mounted ThemeProvider holds a
|
|
15
|
+
// different ThemeContext identity than this consumer — would otherwise crash the
|
|
16
|
+
// dialog meant to report the original error.
|
|
17
|
+
const fallbackContextValue: ThemeContextValue = {
|
|
18
|
+
tx: defaultTx,
|
|
19
|
+
themeMode: 'dark',
|
|
20
|
+
hasIosKeyboard: false,
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
let warned = false;
|
|
24
|
+
|
|
25
|
+
export const useThemeContext = (): ThemeContextValue => {
|
|
26
|
+
const contextValue = useContext(ThemeContext);
|
|
27
|
+
if (!contextValue) {
|
|
28
|
+
if (!warned) {
|
|
29
|
+
warned = true;
|
|
30
|
+
log.warn('Missing ThemeContext; falling back to the default theme.');
|
|
31
|
+
}
|
|
32
|
+
return fallbackContextValue;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return contextValue;
|
|
36
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
6
|
+
import React from 'react';
|
|
7
|
+
|
|
8
|
+
import { IconButton } from '../components/Button';
|
|
9
|
+
import { Input } from '../components/Input';
|
|
10
|
+
import { withLayoutVariants, withTheme } from '../testing';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The three control sizes side by side, across control types — a density change must read the same
|
|
14
|
+
* on a checkbox, a text field and an icon button, since they share the `--dx-control*` knobs.
|
|
15
|
+
*/
|
|
16
|
+
const DensityStory = () => (
|
|
17
|
+
<div className='flex flex-col gap-4'>
|
|
18
|
+
{(['lg', 'md', 'sm'] as const).map((density) => (
|
|
19
|
+
<Input.Root key={density}>
|
|
20
|
+
<Input.Label>{`density="${density}"`}</Input.Label>
|
|
21
|
+
<div className='flex items-center gap-2'>
|
|
22
|
+
<Input.Checkbox size={density === 'lg' ? 5 : 4} />
|
|
23
|
+
<Input.TextInput density={density} classNames='grow' placeholder={`This is a density:${density} input`} />
|
|
24
|
+
<IconButton density={density} iconOnly icon='ph--gear--regular' label='Settings' />
|
|
25
|
+
</div>
|
|
26
|
+
</Input.Root>
|
|
27
|
+
))}
|
|
28
|
+
</div>
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
const meta = {
|
|
32
|
+
title: 'ui/react-ui-core/playground/Density',
|
|
33
|
+
render: DensityStory,
|
|
34
|
+
decorators: [withTheme(), withLayoutVariants()],
|
|
35
|
+
} satisfies Meta<typeof DensityStory>;
|
|
36
|
+
|
|
37
|
+
export default meta;
|
|
38
|
+
|
|
39
|
+
type Story = StoryObj<typeof meta>;
|
|
40
|
+
|
|
41
|
+
export const Default: Story = {};
|