@dxos/react-ui 0.7.4 → 0.7.5-labs.071a3e2

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.
Files changed (101) hide show
  1. package/dist/lib/browser/index.mjs +510 -347
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/node/index.cjs +766 -614
  5. package/dist/lib/node/index.cjs.map +4 -4
  6. package/dist/lib/node/meta.json +1 -1
  7. package/dist/lib/node-esm/index.mjs +510 -347
  8. package/dist/lib/node-esm/index.mjs.map +4 -4
  9. package/dist/lib/node-esm/meta.json +1 -1
  10. package/dist/types/src/components/Avatars/Avatar.d.ts +5 -9
  11. package/dist/types/src/components/Avatars/Avatar.d.ts.map +1 -1
  12. package/dist/types/src/components/Avatars/Avatar.stories.d.ts +1 -2
  13. package/dist/types/src/components/Avatars/Avatar.stories.d.ts.map +1 -1
  14. package/dist/types/src/components/Buttons/IconButton.d.ts +6 -2
  15. package/dist/types/src/components/Buttons/IconButton.d.ts.map +1 -1
  16. package/dist/types/src/components/Dialogs/AlertDialog.d.ts.map +1 -1
  17. package/dist/types/src/components/Dialogs/Dialog.d.ts.map +1 -1
  18. package/dist/types/src/components/Input/Input.d.ts +5 -6
  19. package/dist/types/src/components/Input/Input.d.ts.map +1 -1
  20. package/dist/types/src/components/Input/Input.stories.d.ts +1 -3
  21. package/dist/types/src/components/Input/Input.stories.d.ts.map +1 -1
  22. package/dist/types/src/components/Lists/List.d.ts +2 -0
  23. package/dist/types/src/components/Lists/List.d.ts.map +1 -1
  24. package/dist/types/src/components/Lists/ListDropIndicator.d.ts +13 -0
  25. package/dist/types/src/components/Lists/ListDropIndicator.d.ts.map +1 -0
  26. package/dist/types/src/components/Lists/Tree.d.ts +2 -0
  27. package/dist/types/src/components/Lists/Tree.d.ts.map +1 -1
  28. package/dist/types/src/components/Lists/TreeDropIndicator.d.ts +8 -0
  29. package/dist/types/src/components/Lists/TreeDropIndicator.d.ts.map +1 -0
  30. package/dist/types/src/components/Main/Main.d.ts +35 -24
  31. package/dist/types/src/components/Main/Main.d.ts.map +1 -1
  32. package/dist/types/src/components/Main/Main.stories.d.ts +1 -1
  33. package/dist/types/src/components/Menus/ContextMenu.d.ts.map +1 -1
  34. package/dist/types/src/components/Menus/DropdownMenu.d.ts +2 -6
  35. package/dist/types/src/components/Menus/DropdownMenu.d.ts.map +1 -1
  36. package/dist/types/src/components/Popover/Popover.d.ts.map +1 -1
  37. package/dist/types/src/components/Select/Select.d.ts.map +1 -1
  38. package/dist/types/src/components/Separator/Separator.d.ts +3 -1
  39. package/dist/types/src/components/Separator/Separator.d.ts.map +1 -1
  40. package/dist/types/src/components/Tag/Tag.d.ts.map +1 -1
  41. package/dist/types/src/components/Tag/Tag.stories.d.ts +12 -5
  42. package/dist/types/src/components/Tag/Tag.stories.d.ts.map +1 -1
  43. package/dist/types/src/components/ThemeProvider/ThemeProvider.d.ts +4 -2
  44. package/dist/types/src/components/ThemeProvider/ThemeProvider.d.ts.map +1 -1
  45. package/dist/types/src/components/ThemeProvider/TranslationsProvider.d.ts +1 -0
  46. package/dist/types/src/components/ThemeProvider/TranslationsProvider.d.ts.map +1 -1
  47. package/dist/types/src/components/Toolbar/Toolbar.d.ts +15 -5
  48. package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -1
  49. package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts +7 -2
  50. package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts.map +1 -1
  51. package/dist/types/src/components/Tooltip/Tooltip.d.ts.map +1 -1
  52. package/dist/types/src/components/Tooltip/Tooltip.stories.d.ts +13 -1
  53. package/dist/types/src/components/Tooltip/Tooltip.stories.d.ts.map +1 -1
  54. package/dist/types/src/hooks/index.d.ts +1 -0
  55. package/dist/types/src/hooks/index.d.ts.map +1 -1
  56. package/dist/types/src/hooks/useSafeArea.d.ts +9 -0
  57. package/dist/types/src/hooks/useSafeArea.d.ts.map +1 -0
  58. package/dist/types/src/hooks/useSafeCollisionPadding.d.ts +10 -0
  59. package/dist/types/src/hooks/useSafeCollisionPadding.d.ts.map +1 -0
  60. package/dist/types/src/hooks/useVisualViewport.d.ts +1 -1
  61. package/dist/types/src/hooks/useVisualViewport.d.ts.map +1 -1
  62. package/dist/types/src/util/ThemedClassName.d.ts +1 -1
  63. package/dist/types/src/util/ThemedClassName.d.ts.map +1 -1
  64. package/dist/types/tsconfig.tsbuildinfo +1 -0
  65. package/package.json +43 -42
  66. package/src/components/Avatars/Avatar.tsx +3 -6
  67. package/src/components/Buttons/IconButton.tsx +25 -7
  68. package/src/components/Clipboard/CopyButton.tsx +1 -1
  69. package/src/components/Dialogs/AlertDialog.tsx +6 -2
  70. package/src/components/Dialogs/Dialog.tsx +7 -11
  71. package/src/components/Input/Input.stories.tsx +4 -6
  72. package/src/components/Input/Input.tsx +29 -44
  73. package/src/components/Lists/List.stories.tsx +2 -2
  74. package/src/components/Lists/List.tsx +3 -0
  75. package/src/components/Lists/ListDropIndicator.tsx +70 -0
  76. package/src/components/Lists/Tree.tsx +3 -0
  77. package/src/components/Lists/TreeDropIndicator.tsx +70 -0
  78. package/src/components/Main/Main.stories.tsx +1 -1
  79. package/src/components/Main/Main.tsx +79 -110
  80. package/src/components/Menus/ContextMenu.tsx +8 -6
  81. package/src/components/Menus/DropdownMenu.tsx +7 -4
  82. package/src/components/Popover/Popover.tsx +8 -2
  83. package/src/components/ScrollArea/ScrollArea.stories.tsx +2 -2
  84. package/src/components/Select/Select.tsx +7 -3
  85. package/src/components/Separator/Separator.tsx +14 -11
  86. package/src/components/Tag/Tag.stories.tsx +20 -31
  87. package/src/components/Tag/Tag.tsx +15 -6
  88. package/src/components/ThemeProvider/ThemeProvider.tsx +13 -5
  89. package/src/components/Toast/Toast.tsx +1 -1
  90. package/src/components/Toolbar/Toolbar.tsx +40 -10
  91. package/src/components/Tooltip/Tooltip.stories.tsx +13 -2
  92. package/src/components/Tooltip/Tooltip.tsx +18 -13
  93. package/src/hooks/index.ts +1 -0
  94. package/src/hooks/useSafeArea.ts +25 -0
  95. package/src/hooks/useSafeCollisionPadding.ts +39 -0
  96. package/src/hooks/useVisualViewport.ts +11 -12
  97. package/src/testing/decorators/withVariants.tsx +4 -4
  98. package/src/util/ThemedClassName.ts +1 -1
  99. package/dist/types/src/playground/Surfaces.stories.d.ts +0 -21
  100. package/dist/types/src/playground/Surfaces.stories.d.ts.map +0 -1
  101. package/src/playground/Surfaces.stories.tsx +0 -73
@@ -1,5 +1,5 @@
1
1
  import { type ClassNameValue } from '@dxos/react-ui-types';
2
- export type ThemedClassName<P> = Omit<P, 'className'> & {
2
+ export type ThemedClassName<P = {}> = Omit<P, 'className'> & {
3
3
  classNames?: ClassNameValue;
4
4
  };
5
5
  //# sourceMappingURL=ThemedClassName.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ThemedClassName.d.ts","sourceRoot":"","sources":["../../../../src/util/ThemedClassName.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,MAAM,MAAM,eAAe,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,WAAW,CAAC,GAAG;IAAE,UAAU,CAAC,EAAE,cAAc,CAAA;CAAE,CAAC"}
1
+ {"version":3,"file":"ThemedClassName.d.ts","sourceRoot":"","sources":["../../../../src/util/ThemedClassName.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,MAAM,MAAM,eAAe,CAAC,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,CAAC,EAAE,WAAW,CAAC,GAAG;IAAE,UAAU,CAAC,EAAE,cAAc,CAAA;CAAE,CAAC"}
@@ -0,0 +1 @@
1
+ {"version":"5.7.3"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/react-ui",
3
- "version": "0.7.4",
3
+ "version": "0.7.5-labs.071a3e2",
4
4
  "description": "Low-level React components for DXOS, applying a theme to a core group of primitives",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -23,49 +23,50 @@
23
23
  "src"
24
24
  ],
25
25
  "dependencies": {
26
- "@fluentui/react-tabster": "^9.19.0",
27
- "@radix-ui/primitive": "^1.0.0",
28
- "@radix-ui/react-alert-dialog": "^1.0.3",
29
- "@radix-ui/react-avatar": "^1.0.2",
30
- "@radix-ui/react-checkbox": "^1.0.3",
31
- "@radix-ui/react-collapsible": "^1.0.2",
32
- "@radix-ui/react-compose-refs": "^1.0.0",
33
- "@radix-ui/react-context": "^1.0.0",
34
- "@radix-ui/react-context-menu": "^2.1.5",
35
- "@radix-ui/react-dialog": "^1.0.3",
36
- "@radix-ui/react-dismissable-layer": "^1.1.1",
37
- "@radix-ui/react-focus-guards": "^1.1.1",
38
- "@radix-ui/react-focus-scope": "^1.1.0",
39
- "@radix-ui/react-id": "^1.1.0",
40
- "@radix-ui/react-menu": "^2.0.6",
41
- "@radix-ui/react-popper": "^1.1.2",
42
- "@radix-ui/react-portal": "^1.1.2",
43
- "@radix-ui/react-presence": "^1.1.1",
44
- "@radix-ui/react-primitive": "^1.0.2",
45
- "@radix-ui/react-scroll-area": "^1.0.3",
46
- "@radix-ui/react-select": "^1.2.1",
47
- "@radix-ui/react-separator": "^1.0.3",
48
- "@radix-ui/react-slot": "^1.0.1",
49
- "@radix-ui/react-switch": "^1.0.3",
50
- "@radix-ui/react-toast": "^1.2.1",
51
- "@radix-ui/react-toggle": "^1.0.2",
52
- "@radix-ui/react-toggle-group": "^1.0.3",
53
- "@radix-ui/react-toolbar": "^1.0.3",
54
- "@radix-ui/react-tooltip": "^1.1.2",
55
- "@radix-ui/react-use-controllable-state": "^1.0.0",
26
+ "@atlaskit/pragmatic-drag-and-drop-hitbox": "^1.0.3",
27
+ "@fluentui/react-tabster": "9.23.3",
28
+ "@radix-ui/primitive": "1.1.1",
29
+ "@radix-ui/react-alert-dialog": "1.1.6",
30
+ "@radix-ui/react-avatar": "1.1.3",
31
+ "@radix-ui/react-checkbox": "1.1.4",
32
+ "@radix-ui/react-collapsible": "1.1.3",
33
+ "@radix-ui/react-compose-refs": "1.1.1",
34
+ "@radix-ui/react-context": "1.1.1",
35
+ "@radix-ui/react-context-menu": "2.2.6",
36
+ "@radix-ui/react-dialog": "1.1.6",
37
+ "@radix-ui/react-dismissable-layer": "1.1.5",
38
+ "@radix-ui/react-focus-guards": "1.1.1",
39
+ "@radix-ui/react-focus-scope": "1.1.2",
40
+ "@radix-ui/react-id": "1.1.0",
41
+ "@radix-ui/react-menu": "2.1.6",
42
+ "@radix-ui/react-popper": "1.2.2",
43
+ "@radix-ui/react-portal": "1.1.4",
44
+ "@radix-ui/react-presence": "1.1.2",
45
+ "@radix-ui/react-primitive": "2.0.2",
46
+ "@radix-ui/react-scroll-area": "1.2.3",
47
+ "@radix-ui/react-select": "2.1.6",
48
+ "@radix-ui/react-separator": "1.1.2",
49
+ "@radix-ui/react-slot": "1.1.2",
50
+ "@radix-ui/react-switch": "1.1.3",
51
+ "@radix-ui/react-toast": "1.2.6",
52
+ "@radix-ui/react-toggle": "1.1.2",
53
+ "@radix-ui/react-toggle-group": "1.1.2",
54
+ "@radix-ui/react-toolbar": "1.1.2",
55
+ "@radix-ui/react-tooltip": "1.1.8",
56
+ "@radix-ui/react-use-controllable-state": "1.1.0",
56
57
  "aria-hidden": "^1.2.4",
57
58
  "date-fns": "^3.3.1",
58
59
  "i18next": "^21.10.0",
59
60
  "keyborg": "^2.5.0",
60
61
  "react-i18next": "^11.18.6",
61
62
  "react-remove-scroll": "^2.6.0",
62
- "@dxos/debug": "0.7.4",
63
- "@dxos/log": "0.7.4",
64
- "@dxos/react-hooks": "0.7.4",
65
- "@dxos/react-input": "0.7.4",
66
- "@dxos/react-ui-types": "0.7.4",
67
- "@dxos/util": "0.7.4",
68
- "@dxos/react-list": "0.7.4"
63
+ "@dxos/debug": "0.7.5-labs.071a3e2",
64
+ "@dxos/log": "0.7.5-labs.071a3e2",
65
+ "@dxos/react-input": "0.7.5-labs.071a3e2",
66
+ "@dxos/react-list": "0.7.5-labs.071a3e2",
67
+ "@dxos/react-hooks": "0.7.5-labs.071a3e2",
68
+ "@dxos/react-ui-types": "0.7.5-labs.071a3e2",
69
+ "@dxos/util": "0.7.5-labs.071a3e2"
69
70
  },
70
71
  "devDependencies": {
71
72
  "@dnd-kit/core": "^6.0.5",
@@ -77,15 +78,15 @@
77
78
  "react": "~18.2.0",
78
79
  "react-dom": "~18.2.0",
79
80
  "vite": "5.4.7",
80
- "@dxos/random": "0.7.4",
81
- "@dxos/react-ui-theme": "0.7.4",
82
- "@dxos/util": "0.7.4"
81
+ "@dxos/random": "0.7.5-labs.071a3e2",
82
+ "@dxos/react-ui-theme": "0.7.5-labs.071a3e2",
83
+ "@dxos/util": "0.7.5-labs.071a3e2"
83
84
  },
84
85
  "peerDependencies": {
85
86
  "@phosphor-icons/react": "^2.1.5",
86
87
  "react": "~18.2.0",
87
88
  "react-dom": "~18.2.0",
88
- "@dxos/react-ui-theme": "0.7.4"
89
+ "@dxos/react-ui-theme": "0.7.5-labs.071a3e2"
89
90
  },
90
91
  "publishConfig": {
91
92
  "access": "public"
@@ -5,8 +5,8 @@
5
5
  import {
6
6
  Root as AvatarRootPrimitive,
7
7
  type AvatarProps as AvatarRootPrimitiveProps,
8
- type ImageLoadingStatus,
9
8
  Fallback as AvatarFallbackPrimitive,
9
+ type AvatarImageProps as AvatarImagePrimitiveProps,
10
10
  } from '@radix-ui/react-avatar';
11
11
  import { createContext } from '@radix-ui/react-context';
12
12
  import { Primitive } from '@radix-ui/react-primitive';
@@ -243,9 +243,7 @@ const AvatarMaskedText = (props: AvatarMaskedTextProps) => {
243
243
  );
244
244
  };
245
245
 
246
- type AvatarImageProps = ComponentPropsWithRef<'image'> & {
247
- onLoadingStatusChange?: (status: ImageLoadingStatus) => void;
248
- };
246
+ type AvatarImageProps = ComponentPropsWithRef<'image'> & Pick<AvatarImagePrimitiveProps, 'onLoadingStatusChange'>;
249
247
 
250
248
  const AvatarImage = forwardRef<SVGImageElement, AvatarImageProps>(
251
249
  ({ onLoadingStatusChange, ...props }, forwardedRef) => {
@@ -264,8 +262,7 @@ const AvatarImage = forwardRef<SVGImageElement, AvatarImageProps>(
264
262
 
265
263
  type AvatarIconProps = {
266
264
  icon: string;
267
- onLoadingStatusChange?: (status: ImageLoadingStatus) => void;
268
- };
265
+ } & Pick<AvatarImagePrimitiveProps, 'onLoadingStatusChange'>;
269
266
 
270
267
  const AvatarIcon = forwardRef<SVGSVGElement, AvatarIconProps>(({ onLoadingStatusChange, ...props }, forwardedRef) => {
271
268
  const { size } = useAvatarContext('AvatarIcon');
@@ -2,34 +2,48 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import React, { forwardRef } from 'react';
5
+ import React, { forwardRef, type ReactNode, type MutableRefObject, useState } from 'react';
6
6
 
7
7
  import { Button, type ButtonProps } from './Button';
8
8
  import { useThemeContext } from '../../hooks';
9
9
  import { type ThemedClassName } from '../../util';
10
10
  import { Icon, type IconProps } from '../Icon';
11
- import { Tooltip } from '../Tooltip';
11
+ import { Tooltip, type TooltipContentProps } from '../Tooltip';
12
12
 
13
13
  type IconButtonProps = Omit<ButtonProps, 'children'> &
14
14
  Pick<IconProps, 'icon' | 'size'> & {
15
- label: string;
15
+ label: NonNullable<ReactNode>;
16
16
  iconOnly?: boolean;
17
+ caretDown?: boolean;
17
18
  // TODO(burdon): Create slots abstraction?
18
19
  iconClassNames?: ThemedClassName<any>['classNames'];
19
20
  tooltipPortal?: boolean;
20
21
  tooltipZIndex?: string;
22
+ tooltipSide?: TooltipContentProps['side'];
23
+ suppressNextTooltip?: MutableRefObject<boolean>;
21
24
  };
22
25
 
23
26
  const IconOnlyButton = forwardRef<HTMLButtonElement, IconButtonProps>(
24
- ({ tooltipPortal = true, tooltipZIndex: zIndex, ...props }, forwardedRef) => {
27
+ ({ tooltipPortal = true, tooltipZIndex: zIndex, tooltipSide, suppressNextTooltip, ...props }, forwardedRef) => {
28
+ const [triggerTooltipOpen, setTriggerTooltipOpen] = useState(false);
25
29
  const content = (
26
- <Tooltip.Content {...(zIndex && { style: { zIndex } })}>
30
+ <Tooltip.Content {...(zIndex && { style: { zIndex } })} side={tooltipSide}>
27
31
  {props.label}
28
32
  <Tooltip.Arrow />
29
33
  </Tooltip.Content>
30
34
  );
31
35
  return (
32
- <Tooltip.Root>
36
+ <Tooltip.Root
37
+ open={triggerTooltipOpen}
38
+ onOpenChange={(nextOpen) => {
39
+ if (suppressNextTooltip?.current) {
40
+ setTriggerTooltipOpen(false);
41
+ suppressNextTooltip.current = false;
42
+ } else {
43
+ setTriggerTooltipOpen(nextOpen);
44
+ }
45
+ }}
46
+ >
33
47
  <Tooltip.Trigger asChild>
34
48
  <LabelledIconButton {...props} ref={forwardedRef} />
35
49
  </Tooltip.Trigger>
@@ -40,12 +54,16 @@ const IconOnlyButton = forwardRef<HTMLButtonElement, IconButtonProps>(
40
54
  );
41
55
 
42
56
  const LabelledIconButton = forwardRef<HTMLButtonElement, IconButtonProps>(
43
- ({ icon, size, iconOnly, label, classNames, iconClassNames, ...props }, forwardedRef) => {
57
+ (
58
+ { icon, size, iconOnly, label, classNames, iconClassNames, caretDown, suppressNextTooltip, ...props },
59
+ forwardedRef,
60
+ ) => {
44
61
  const { tx } = useThemeContext();
45
62
  return (
46
63
  <Button {...props} classNames={tx('iconButton.root', 'iconButton', {}, classNames)} ref={forwardedRef}>
47
64
  <Icon icon={icon} size={size} classNames={iconClassNames} />
48
65
  <span className={iconOnly ? 'sr-only' : undefined}>{label}</span>
66
+ {caretDown && <Icon size={3} icon='ph--caret-down--bold' />}
49
67
  </Button>
50
68
  );
51
69
  },
@@ -53,7 +53,7 @@ export const CopyButtonIconOnly = ({ value, classNames, iconProps, variant, ...p
53
53
  return (
54
54
  <Tooltip.Root delayDuration={1500} open={open} onOpenChange={setOpen}>
55
55
  <Tooltip.Portal>
56
- <Tooltip.Content side='bottom' sideOffset={12} classNames='z-30'>
56
+ <Tooltip.Content side='bottom' sideOffset={12}>
57
57
  <span>{label}</span>
58
58
  <Tooltip.Arrow />
59
59
  </Tooltip.Content>
@@ -31,7 +31,11 @@ import { ElevationProvider } from '../ElevationProvider';
31
31
 
32
32
  type AlertDialogRootProps = AlertDialogRootPrimitiveProps;
33
33
 
34
- const AlertDialogRoot: FunctionComponent<AlertDialogRootProps> = AlertDialogRootPrimitive;
34
+ const AlertDialogRoot: FunctionComponent<AlertDialogRootProps> = (props) => (
35
+ <ElevationProvider elevation='dialog'>
36
+ <AlertDialogRootPrimitive {...props} />
37
+ </ElevationProvider>
38
+ );
35
39
 
36
40
  type AlertDialogTriggerProps = AlertDialogTriggerPrimitiveProps;
37
41
 
@@ -134,7 +138,7 @@ const AlertDialogContent: ForwardRefExoticComponent<AlertDialogContentProps> = f
134
138
  className={tx('dialog.content', 'dialog--alert', { inOverlayLayout }, classNames)}
135
139
  ref={forwardedRef}
136
140
  >
137
- <ElevationProvider elevation='chrome'>{children}</ElevationProvider>
141
+ {children}
138
142
  </AlertDialogContentPrimitive>
139
143
  );
140
144
  });
@@ -29,7 +29,11 @@ import { ElevationProvider } from '../ElevationProvider';
29
29
 
30
30
  type DialogRootProps = DialogRootPrimitiveProps;
31
31
 
32
- const DialogRoot: FunctionComponent<DialogRootProps> = DialogRootPrimitive;
32
+ const DialogRoot: FunctionComponent<DialogRootProps> = (props) => (
33
+ <ElevationProvider elevation='dialog'>
34
+ <DialogRootPrimitive {...props} />
35
+ </ElevationProvider>
36
+ );
33
37
 
34
38
  type DialogTriggerProps = DialogTriggerPrimitiveProps;
35
39
 
@@ -90,15 +94,7 @@ const DialogOverlay: ForwardRefExoticComponent<DialogOverlayProps> = forwardRef<
90
94
  return (
91
95
  <DialogOverlayPrimitive
92
96
  {...props}
93
- className={tx(
94
- 'dialog.overlay',
95
- 'dialog__overlay',
96
- {},
97
- classNames,
98
- 'data-[block-align=start]:justify-center',
99
- 'data-[block-align=start]:items-start',
100
- 'data-[block-align=center]:place-content-center',
101
- )}
97
+ className={tx('dialog.overlay', 'dialog__overlay', {}, classNames)}
102
98
  ref={forwardedRef}
103
99
  data-block-align={blockAlign}
104
100
  >
@@ -123,7 +119,7 @@ const DialogContent: ForwardRefExoticComponent<DialogContentProps> = forwardRef<
123
119
  className={tx('dialog.content', 'dialog', { inOverlayLayout }, classNames)}
124
120
  ref={forwardedRef}
125
121
  >
126
- <ElevationProvider elevation='chrome'>{children}</ElevationProvider>
122
+ {children}
127
123
  </DialogContentPrimitive>
128
124
  );
129
125
  },
@@ -6,7 +6,7 @@ import '@dxos-theme';
6
6
 
7
7
  import React from 'react';
8
8
 
9
- import { baseSurface, modalSurface, groupSurface, mx, surfaceElevation } from '@dxos/react-ui-theme';
9
+ import { baseSurface, modalSurface, groupSurface, mx, surfaceShadow } from '@dxos/react-ui-theme';
10
10
  import { type MessageValence } from '@dxos/react-ui-types';
11
11
 
12
12
  import { Input } from './Input';
@@ -61,10 +61,10 @@ const StoryInput = (props: StoryInputProps) => {
61
61
  <div className={mx(baseSurface, 'p-4')}>
62
62
  <StoryInputContent {...props} />
63
63
  </div>
64
- <div className={mx(groupSurface, 'p-4 rounded-lg', surfaceElevation({ elevation: 'group' }))}>
64
+ <div className={mx(groupSurface, 'p-4 rounded-lg', surfaceShadow({ elevation: 'positioned' }))}>
65
65
  <StoryInputContent {...props} />
66
66
  </div>
67
- <div className={mx(modalSurface, 'p-4 rounded-lg', surfaceElevation({ elevation: 'chrome' }))}>
67
+ <div className={mx(modalSurface, 'p-4 rounded-lg', surfaceShadow({ elevation: 'dialog' }))}>
68
68
  <StoryInputContent {...props} />
69
69
  </div>
70
70
  </div>
@@ -214,8 +214,6 @@ export const Switch = {
214
214
  args: {
215
215
  label: 'This is a switch',
216
216
  type: 'switch',
217
- description: 'It’s checked, indeterminate, or unchecked',
218
- size: 5,
219
- weight: 'bold',
217
+ description: 'It’s either off... or on.',
220
218
  },
221
219
  };
@@ -2,19 +2,10 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { Check, type IconWeight, Minus } from '@phosphor-icons/react';
6
- import {
7
- Root as CheckboxPrimitive,
8
- type CheckboxProps as CheckboxPrimitiveProps,
9
- Indicator as CheckboxIndicatorPrimitive,
10
- } from '@radix-ui/react-checkbox';
11
- import {
12
- Root as SwitchPrimitive,
13
- Thumb as SwitchThumbPrimitive,
14
- type SwitchProps as SwitchPrimitiveProps,
15
- } from '@radix-ui/react-switch';
5
+ import { type IconWeight } from '@phosphor-icons/react';
6
+ import { Root as CheckboxPrimitive, type CheckboxProps as CheckboxPrimitiveProps } from '@radix-ui/react-checkbox';
16
7
  import { useControllableState } from '@radix-ui/react-use-controllable-state';
17
- import React, { forwardRef, type ForwardRefExoticComponent, Fragment, useCallback } from 'react';
8
+ import React, { type ComponentPropsWithRef, forwardRef, type ForwardRefExoticComponent, useCallback } from 'react';
18
9
 
19
10
  import {
20
11
  InputRoot,
@@ -41,6 +32,7 @@ import { type Density, type Elevation, type ClassNameValue, type Size } from '@d
41
32
 
42
33
  import { useDensityContext, useElevationContext, useThemeContext } from '../../hooks';
43
34
  import { type ThemedClassName } from '../../util';
35
+ import { Icon } from '../Icon';
44
36
 
45
37
  type InputVariant = 'default' | 'subdued';
46
38
 
@@ -262,7 +254,7 @@ const Checkbox: ForwardRefExoticComponent<CheckboxProps> = forwardRef<
262
254
  });
263
255
  const { id, validationValence, descriptionId, errorMessageId } = useInputContext(INPUT_NAME, __inputScope);
264
256
  const { tx } = useThemeContext();
265
- const Icon = checked === 'indeterminate' ? Minus : checked ? Check : Fragment;
257
+
266
258
  return (
267
259
  <CheckboxPrimitive
268
260
  {...{
@@ -279,63 +271,56 @@ const Checkbox: ForwardRefExoticComponent<CheckboxProps> = forwardRef<
279
271
  }}
280
272
  ref={forwardedRef}
281
273
  >
282
- <CheckboxIndicatorPrimitive asChild>
283
- <Icon
284
- {...(checked && {
285
- weight,
286
- className: tx('input.checkboxIndicator', 'input--checkbox__indicator', { size }),
287
- })}
288
- />
289
- </CheckboxIndicatorPrimitive>
274
+ <Icon
275
+ icon={checked === 'indeterminate' ? 'ph--minus--regular' : 'ph--check--regular'}
276
+ classNames={tx('input.checkboxIndicator', 'input--checkbox__indicator', { size, checked })}
277
+ />
290
278
  </CheckboxPrimitive>
291
279
  );
292
280
  },
293
281
  );
294
282
 
295
- type SwitchProps = ThemedClassName<Omit<SwitchPrimitiveProps, 'children'>> & { size?: Size };
283
+ type SwitchProps = ThemedClassName<
284
+ Omit<ComponentPropsWithRef<'input'>, 'children' | 'onChange'> & { onCheckedChange?: (checked: boolean) => void }
285
+ >;
296
286
 
297
- const Switch: ForwardRefExoticComponent<SwitchProps> = forwardRef<HTMLButtonElement, InputScopedProps<SwitchProps>>(
287
+ const Switch = forwardRef<HTMLInputElement, InputScopedProps<SwitchProps>>(
298
288
  (
299
289
  {
300
290
  __inputScope,
301
291
  checked: propsChecked,
302
292
  defaultChecked: propsDefaultChecked,
303
293
  onCheckedChange: propsOnCheckedChange,
304
- size = 5,
305
294
  classNames,
306
295
  ...props
307
296
  },
308
297
  forwardedRef,
309
298
  ) => {
310
- const { tx } = useThemeContext();
311
-
312
299
  const [checked, onCheckedChange] = useControllableState({
313
300
  prop: propsChecked,
314
- defaultProp: propsDefaultChecked,
301
+ defaultProp: propsDefaultChecked ?? false,
315
302
  onChange: propsOnCheckedChange,
316
303
  });
317
304
 
318
305
  const { id, validationValence, descriptionId, errorMessageId } = useInputContext(INPUT_NAME, __inputScope);
306
+
319
307
  return (
320
- <SwitchPrimitive
321
- {...{
322
- ...props,
323
- checked,
324
- onCheckedChange,
325
- id,
326
- 'aria-describedby': descriptionId,
327
- ...(validationValence === 'error' && {
328
- 'aria-invalid': 'true' as const,
329
- 'aria-errormessage': errorMessageId,
330
- }),
331
- className: tx('input.switch', 'input--switch', { size }, classNames),
308
+ <input
309
+ type='checkbox'
310
+ className='dx-checkbox--switch dx-focus-ring'
311
+ checked={checked}
312
+ onChange={(event) => {
313
+ onCheckedChange(event.target.checked);
332
314
  }}
315
+ id={id}
316
+ aria-describedby={descriptionId}
317
+ {...props}
318
+ {...(validationValence === 'error' && {
319
+ 'aria-invalid': 'true' as const,
320
+ 'aria-errormessage': errorMessageId,
321
+ })}
333
322
  ref={forwardedRef}
334
- >
335
- {/* TODO(wittjosiah): Embed icons/text for on/off states.
336
- e.g., https://codepen.io/alvarotrigo/pen/oNoJePo (#13) */}
337
- <SwitchThumbPrimitive className={tx('input.switchThumb', 'input--switch__thumb', { size })} />
338
- </SwitchPrimitive>
323
+ />
339
324
  );
340
325
  },
341
326
  );
@@ -17,7 +17,7 @@ import {
17
17
  ghostSelected,
18
18
  ghostSelectedTrackingInterFromNormal,
19
19
  mx,
20
- surfaceElevation,
20
+ surfaceShadow,
21
21
  } from '@dxos/react-ui-theme';
22
22
 
23
23
  import { List, ListItem, type ListScopedProps } from './List';
@@ -124,7 +124,7 @@ export const ManySizesDraggable = {
124
124
  <p
125
125
  className={mx(
126
126
  index % 3 === 0 ? 'bs-20' : index % 2 === 0 ? 'bs-12' : 'bs-8',
127
- surfaceElevation({ elevation: 'group' }),
127
+ surfaceShadow({ elevation: 'positioned' }),
128
128
  'mbe-2 p-2 bg-white dark:bg-neutral-800 rounded',
129
129
  )}
130
130
  >{`List item ${index + 1}`}</p>
@@ -26,6 +26,7 @@ import {
26
26
  } from '@dxos/react-list';
27
27
  import { type Density } from '@dxos/react-ui-types';
28
28
 
29
+ import { ListDropIndicator } from './ListDropIndicator';
29
30
  import { useDensityContext, useThemeContext } from '../../hooks';
30
31
  import { type ThemedClassName } from '../../util';
31
32
  import { DensityProvider } from '../DensityProvider';
@@ -150,6 +151,7 @@ export const ListItem: {
150
151
  OpenTrigger: ForwardRefExoticComponent<ListItemOpenTriggerProps>;
151
152
  CollapsibleContent: ForwardRefExoticComponent<ListItemCollapsibleContentProps>;
152
153
  MockOpenTrigger: FC<ThemedClassName<Omit<ComponentPropsWithoutRef<'div'>, 'children'>>>;
154
+ DropIndicator: typeof ListDropIndicator;
153
155
  } = {
154
156
  Root: ListItemRoot,
155
157
  Endcap: ListItemEndcap,
@@ -157,6 +159,7 @@ export const ListItem: {
157
159
  OpenTrigger: ListItemOpenTrigger,
158
160
  CollapsibleContent: ListItemCollapsibleContent,
159
161
  MockOpenTrigger: MockListItemOpenTrigger,
162
+ DropIndicator: ListDropIndicator,
160
163
  };
161
164
 
162
165
  export { List, useListContext, useListItemContext, LIST_NAME, LIST_ITEM_NAME };
@@ -0,0 +1,70 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import { type Edge } from '@atlaskit/pragmatic-drag-and-drop-hitbox/types';
6
+ import React, { type CSSProperties, type HTMLAttributes } from 'react';
7
+
8
+ type Orientation = 'horizontal' | 'vertical';
9
+
10
+ const edgeToOrientationMap: Record<Edge, Orientation> = {
11
+ top: 'horizontal',
12
+ bottom: 'horizontal',
13
+ left: 'vertical',
14
+ right: 'vertical',
15
+ };
16
+
17
+ const orientationStyles: Record<Orientation, HTMLAttributes<HTMLElement>['className']> = {
18
+ horizontal:
19
+ 'h-[--line-thickness] left-[calc(var(--line-inset)+var(--terminal-radius))] right-[--line-inset] before:left-[--terminal-inset]',
20
+ vertical:
21
+ 'w-[--line-thickness] top-[calc(var(--line-inset)+var(--terminal-radius))] bottom-[--line-inset] before:top-[--terminal-inset]',
22
+ };
23
+
24
+ const edgeStyles: Record<Edge, HTMLAttributes<HTMLElement>['className']> = {
25
+ top: 'top-[--line-offset] before:top-[--offset-terminal]',
26
+ right: 'right-[--line-offset] before:right-[--offset-terminal]',
27
+ bottom: 'bottom-[--line-offset] before:bottom-[--offset-terminal]',
28
+ left: 'left-[--line-offset] before:left-[--offset-terminal]',
29
+ };
30
+
31
+ const strokeSize = 2;
32
+ const terminalSize = 8;
33
+ const offsetToAlignTerminalWithLine = (strokeSize - terminalSize) / 2;
34
+
35
+ export type DropIndicatorProps = {
36
+ edge: Edge;
37
+ gap?: number;
38
+ terminalInset?: number;
39
+ lineInset?: number;
40
+ };
41
+
42
+ /**
43
+ * This is a tailwind port of `@atlaskit/pragmatic-drag-and-drop-react-drop-indicator/box`
44
+ */
45
+ export const ListDropIndicator = ({
46
+ edge,
47
+ gap = 0,
48
+ lineInset = 0,
49
+ terminalInset = lineInset - terminalSize,
50
+ }: DropIndicatorProps) => {
51
+ const orientation = edgeToOrientationMap[edge];
52
+
53
+ return (
54
+ <div
55
+ role='none'
56
+ style={
57
+ {
58
+ '--line-thickness': `${strokeSize}px`,
59
+ '--line-offset': `calc(-0.5 * (${gap}px + ${strokeSize}px))`,
60
+ '--line-inset': `${lineInset}px`,
61
+ '--terminal-size': `${terminalSize}px`,
62
+ '--terminal-radius': `${terminalSize / 2}px`,
63
+ '--terminal-inset': `${terminalInset}px`,
64
+ '--offset-terminal': `${offsetToAlignTerminalWithLine}px`,
65
+ } as CSSProperties
66
+ }
67
+ className={`absolute z-10 pointer-events-none bg-accentSurface before:content-[''] before:w-[--terminal-size] before:h-[--terminal-size] box-border before:absolute before:border-[length:--line-thickness] before:border-solid before:border-accentSurface before:rounded-full ${orientationStyles[orientation]} ${edgeStyles[edge]}`}
68
+ />
69
+ );
70
+ };
@@ -16,6 +16,7 @@ import {
16
16
  LIST_ITEM_NAME,
17
17
  useListItemContext,
18
18
  } from './List';
19
+ import { TreeDropIndicator } from './TreeDropIndicator';
19
20
  import { type ThemedClassName } from '../../util';
20
21
 
21
22
  type TreeRootProps = ListProps;
@@ -60,12 +61,14 @@ export const TreeItem: {
60
61
  Body: ForwardRefExoticComponent<TreeItemBodyProps>;
61
62
  OpenTrigger: ForwardRefExoticComponent<TreeItemOpenTriggerProps>;
62
63
  MockOpenTrigger: FC<ThemedClassName<Omit<ComponentPropsWithoutRef<'div'>, 'children'>>>;
64
+ DropIndicator: typeof TreeDropIndicator;
63
65
  } = {
64
66
  Root: TreeItemRoot,
65
67
  Heading: TreeItemHeading,
66
68
  Body: TreeItemBody,
67
69
  OpenTrigger: TreeItemOpenTrigger,
68
70
  MockOpenTrigger: MockTreeItemOpenTrigger,
71
+ DropIndicator: TreeDropIndicator,
69
72
  };
70
73
 
71
74
  export type { TreeRootProps, TreeItemProps, TreeItemHeadingProps, TreeItemBodyProps, TreeItemOpenTriggerProps };