@dxos/react-ui-stack 0.7.5-main.499c70c → 0.7.5-main.5ae2ba8

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 (50) hide show
  1. package/dist/lib/browser/index.mjs +174 -177
  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 +202 -204
  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 +174 -177
  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/MenuSignifier.d.ts +2 -3
  11. package/dist/types/src/components/MenuSignifier.d.ts.map +1 -1
  12. package/dist/types/src/components/Stack.d.ts +6 -1
  13. package/dist/types/src/components/Stack.d.ts.map +1 -1
  14. package/dist/types/src/components/Stack.stories.d.ts +1 -2
  15. package/dist/types/src/components/Stack.stories.d.ts.map +1 -1
  16. package/dist/types/src/components/StackContext.d.ts +5 -2
  17. package/dist/types/src/components/StackContext.d.ts.map +1 -1
  18. package/dist/types/src/components/StackItem.d.ts +15 -7
  19. package/dist/types/src/components/StackItem.d.ts.map +1 -1
  20. package/dist/types/src/components/StackItemContent.d.ts +35 -2
  21. package/dist/types/src/components/StackItemContent.d.ts.map +1 -1
  22. package/dist/types/src/components/StackItemDragHandle.d.ts +2 -2
  23. package/dist/types/src/components/StackItemDragHandle.d.ts.map +1 -1
  24. package/dist/types/src/components/StackItemHeading.d.ts +1 -1
  25. package/dist/types/src/components/StackItemHeading.d.ts.map +1 -1
  26. package/dist/types/src/components/StackItemResizeHandle.d.ts +1 -2
  27. package/dist/types/src/components/StackItemResizeHandle.d.ts.map +1 -1
  28. package/dist/types/src/components/StackItemSigil.d.ts.map +1 -1
  29. package/dist/types/src/hooks/index.d.ts +2 -0
  30. package/dist/types/src/hooks/index.d.ts.map +1 -0
  31. package/dist/types/src/hooks/useStackDropForElements.d.ts +15 -0
  32. package/dist/types/src/hooks/useStackDropForElements.d.ts.map +1 -0
  33. package/dist/types/tsconfig.tsbuildinfo +1 -1
  34. package/package.json +29 -27
  35. package/src/components/Stack.stories.tsx +1 -1
  36. package/src/components/Stack.tsx +44 -57
  37. package/src/components/StackContext.tsx +6 -4
  38. package/src/components/StackItem.tsx +47 -15
  39. package/src/components/StackItemContent.tsx +48 -28
  40. package/src/components/StackItemHeading.tsx +2 -2
  41. package/src/components/StackItemResizeHandle.tsx +12 -98
  42. package/src/components/StackItemSigil.tsx +90 -103
  43. package/src/hooks/index.ts +5 -0
  44. package/src/hooks/useStackDropForElements.ts +73 -0
  45. package/dist/types/src/playwright/playwright.config.d.ts +0 -3
  46. package/dist/types/src/playwright/playwright.config.d.ts.map +0 -1
  47. package/dist/types/src/testing/EditorContent.d.ts +0 -8
  48. package/dist/types/src/testing/EditorContent.d.ts.map +0 -1
  49. package/src/testing/EditorContent.tsx +0 -60
  50. /package/src/playwright/{playwright.config.ts → playwright.config.cts} +0 -0
@@ -1,8 +1,41 @@
1
1
  import React, { type ComponentPropsWithoutRef } from 'react';
2
2
  import { type ThemedClassName } from '@dxos/react-ui';
3
3
  export type StackItemContentProps = ThemedClassName<ComponentPropsWithoutRef<'div'>> & {
4
- toolbar?: boolean;
4
+ /**
5
+ * This flag is required in order to clarify a developer experience that seemed like it needed extra boilerplate
6
+ * (`row-span-2`) or was buggy. See the description of the StackItem.Content component itself for more information.
7
+ */
8
+ toolbar: boolean;
9
+ /**
10
+ * Whether to provide for the layout of a statusbar after the content.
11
+ */
5
12
  statusbar?: boolean;
13
+ /**
14
+ * Whether to set a certain aspect ratio on the content, including the toolbar and statusbar. This is provided for
15
+ * convenience and consistency; it can instead be specified by the `classNames` or `style` props as needed.
16
+ */
17
+ size?: 'intrinsic' | 'video' | 'square';
6
18
  };
7
- export declare const StackItemContent: ({ children, toolbar, statusbar, classNames, ...props }: StackItemContentProps) => React.JSX.Element;
19
+ /**
20
+ * This component should be used by plugins for rendering content within a stack item, a.k.a. a “plank” or “section”.
21
+ * The `toolbar` flag must be provided since this component provides for the layout of content with the toolbar.
22
+ */
23
+ export declare const StackItemContent: React.ForwardRefExoticComponent<Omit<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref">, "className"> & {
24
+ classNames?: import("@dxos/react-ui-types").ClassNameValue;
25
+ } & {
26
+ /**
27
+ * This flag is required in order to clarify a developer experience that seemed like it needed extra boilerplate
28
+ * (`row-span-2`) or was buggy. See the description of the StackItem.Content component itself for more information.
29
+ */
30
+ toolbar: boolean;
31
+ /**
32
+ * Whether to provide for the layout of a statusbar after the content.
33
+ */
34
+ statusbar?: boolean;
35
+ /**
36
+ * Whether to set a certain aspect ratio on the content, including the toolbar and statusbar. This is provided for
37
+ * convenience and consistency; it can instead be specified by the `classNames` or `style` props as needed.
38
+ */
39
+ size?: "intrinsic" | "video" | "square";
40
+ } & React.RefAttributes<HTMLDivElement>>;
8
41
  //# sourceMappingURL=StackItemContent.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"StackItemContent.d.ts","sourceRoot":"","sources":["../../../../src/components/StackItemContent.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,EAAE,KAAK,wBAAwB,EAAE,MAAM,OAAO,CAAC;AAE7D,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAKtD,MAAM,MAAM,qBAAqB,GAAG,eAAe,CAAC,wBAAwB,CAAC,KAAK,CAAC,CAAC,GAAG;IACrF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,eAAO,MAAM,gBAAgB,2DAM1B,qBAAqB,sBAmBvB,CAAC"}
1
+ {"version":3,"file":"StackItemContent.d.ts","sourceRoot":"","sources":["../../../../src/components/StackItemContent.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,EAAE,KAAK,wBAAwB,EAAc,MAAM,OAAO,CAAC;AAEzE,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAKtD,MAAM,MAAM,qBAAqB,GAAG,eAAe,CAAC,wBAAwB,CAAC,KAAK,CAAC,CAAC,GAAG;IACrF;;;OAGG;IACH,OAAO,EAAE,OAAO,CAAC;IAEjB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;OAGG;IACH,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,GAAG,QAAQ,CAAC;CACzC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,gBAAgB;;;IAtB3B;;;OAGG;aACM,OAAO;IAEhB;;OAEG;gBACS,OAAO;IAEnB;;;OAGG;WACI,WAAW,GAAG,OAAO,GAAG,QAAQ;wCAkCxC,CAAC"}
@@ -1,6 +1,6 @@
1
- import React, { type ComponentPropsWithoutRef } from 'react';
1
+ import { type ComponentPropsWithoutRef } from 'react';
2
2
  export type StackItemDragHandleProps = ComponentPropsWithoutRef<'button'> & {
3
3
  asChild: boolean;
4
4
  };
5
- export declare const StackItemDragHandle: ({ asChild, children }: StackItemDragHandleProps) => React.JSX.Element;
5
+ export declare const StackItemDragHandle: ({ asChild, children }: StackItemDragHandleProps) => import("react/jsx-runtime").JSX.Element;
6
6
  //# sourceMappingURL=StackItemDragHandle.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"StackItemDragHandle.d.ts","sourceRoot":"","sources":["../../../../src/components/StackItemDragHandle.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,EAAE,KAAK,wBAAwB,EAAE,MAAM,OAAO,CAAC;AAI7D,MAAM,MAAM,wBAAwB,GAAG,wBAAwB,CAAC,QAAQ,CAAC,GAAG;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC;AAEjG,eAAO,MAAM,mBAAmB,0BAA2B,wBAAwB,sBAUlF,CAAC"}
1
+ {"version":3,"file":"StackItemDragHandle.d.ts","sourceRoot":"","sources":["../../../../src/components/StackItemDragHandle.tsx"],"names":[],"mappings":"AAKA,OAAc,EAAE,KAAK,wBAAwB,EAAE,MAAM,OAAO,CAAC;AAI7D,MAAM,MAAM,wBAAwB,GAAG,wBAAwB,CAAC,QAAQ,CAAC,GAAG;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC;AAEjG,eAAO,MAAM,mBAAmB,0BAA2B,wBAAwB,4CAUlF,CAAC"}
@@ -2,7 +2,7 @@ import React, { type ComponentPropsWithoutRef, type ComponentPropsWithRef } from
2
2
  import { type ThemedClassName } from '@dxos/react-ui';
3
3
  import { type AttendableId, type Related } from '@dxos/react-ui-attention';
4
4
  export type StackItemHeadingProps = ThemedClassName<ComponentPropsWithoutRef<'div'>>;
5
- export declare const StackItemHeading: ({ children, classNames, ...props }: StackItemHeadingProps) => React.JSX.Element;
5
+ export declare const StackItemHeading: ({ children, classNames, ...props }: StackItemHeadingProps) => import("react/jsx-runtime").JSX.Element;
6
6
  export type StackItemHeadingLabelProps = ThemedClassName<ComponentPropsWithRef<'h1'>> & AttendableId & Related;
7
7
  export declare const StackItemHeadingLabel: React.ForwardRefExoticComponent<Omit<StackItemHeadingLabelProps, "ref"> & React.RefAttributes<HTMLHeadingElement>>;
8
8
  //# sourceMappingURL=StackItemHeading.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"StackItemHeading.d.ts","sourceRoot":"","sources":["../../../../src/components/StackItemHeading.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,EAAE,KAAK,wBAAwB,EAAE,KAAK,qBAAqB,EAAc,MAAM,OAAO,CAAC;AAErG,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAgB,KAAK,YAAY,EAAE,KAAK,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAKzF,MAAM,MAAM,qBAAqB,GAAG,eAAe,CAAC,wBAAwB,CAAC,KAAK,CAAC,CAAC,CAAC;AAErF,eAAO,MAAM,gBAAgB,uCAAwC,qBAAqB,sBAkBzF,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG,eAAe,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC,GAAG,YAAY,GAAG,OAAO,CAAC;AAE/G,eAAO,MAAM,qBAAqB,oHAejC,CAAC"}
1
+ {"version":3,"file":"StackItemHeading.d.ts","sourceRoot":"","sources":["../../../../src/components/StackItemHeading.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,EAAE,KAAK,wBAAwB,EAAE,KAAK,qBAAqB,EAAc,MAAM,OAAO,CAAC;AAErG,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAgB,KAAK,YAAY,EAAE,KAAK,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAKzF,MAAM,MAAM,qBAAqB,GAAG,eAAe,CAAC,wBAAwB,CAAC,KAAK,CAAC,CAAC,CAAC;AAErF,eAAO,MAAM,gBAAgB,uCAAwC,qBAAqB,4CAkBzF,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG,eAAe,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC,GAAG,YAAY,GAAG,OAAO,CAAC;AAE/G,eAAO,MAAM,qBAAqB,oHAejC,CAAC"}
@@ -1,4 +1,3 @@
1
- import React from 'react';
2
1
  export type StackItemResizeHandleProps = {};
3
- export declare const StackItemResizeHandle: () => React.JSX.Element;
2
+ export declare const StackItemResizeHandle: () => import("react/jsx-runtime").JSX.Element;
4
3
  //# sourceMappingURL=StackItemResizeHandle.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"StackItemResizeHandle.d.ts","sourceRoot":"","sources":["../../../../src/components/StackItemResizeHandle.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAkC,MAAM,OAAO,CAAC;AAoBvD,MAAM,MAAM,0BAA0B,GAAG,EAAE,CAAC;AAE5C,eAAO,MAAM,qBAAqB,yBAmEjC,CAAC"}
1
+ {"version":3,"file":"StackItemResizeHandle.d.ts","sourceRoot":"","sources":["../../../../src/components/StackItemResizeHandle.tsx"],"names":[],"mappings":"AAcA,MAAM,MAAM,0BAA0B,GAAG,EAAE,CAAC;AAE5C,eAAO,MAAM,qBAAqB,+CAajC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"StackItemSigil.d.ts","sourceRoot":"","sources":["../../../../src/components/StackItemSigil.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,EAAY,KAAK,iBAAiB,EAAgC,MAAM,OAAO,CAAC;AAE9F,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,OAAO,EAEL,KAAK,WAAW,EAMjB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,OAAO,EAAgB,MAAM,0BAA0B,CAAC;AAOzF,MAAM,MAAM,UAAU,GAAG;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG,IAAI,CAAC,UAAU,EAAE,IAAI,GAAG,YAAY,GAAG,MAAM,CAAC,CAAC;AAElF,MAAM,MAAM,yBAAyB,GAAG,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,GAAG,YAAY,GAAG,OAAO,CAAC;AAE9F,eAAO,MAAM,oBAAoB,kHAgBhC,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,iBAAiB,CACjD;IACE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,oBAAoB,EAAE,EAAE,CAAC;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,oBAAoB,KAAK,IAAI,CAAC;CACnD,GAAG,OAAO,CACZ,CAAC;AAEF,eAAO,MAAM,cAAc;mBARR,MAAM;kBACP,MAAM;cACV,oBAAoB,EAAE,EAAE;UAC5B,MAAM;eACD,CAAC,MAAM,EAAE,oBAAoB,KAAK,IAAI;;;2CA6GpD,CAAC"}
1
+ {"version":3,"file":"StackItemSigil.d.ts","sourceRoot":"","sources":["../../../../src/components/StackItemSigil.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,EAAY,KAAK,iBAAiB,EAAgC,MAAM,OAAO,CAAC;AAE9F,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,OAAO,EAAU,KAAK,WAAW,EAAyD,MAAM,gBAAgB,CAAC;AACjH,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,OAAO,EAAgB,MAAM,0BAA0B,CAAC;AAOzF,MAAM,MAAM,UAAU,GAAG;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG,IAAI,CAAC,UAAU,EAAE,IAAI,GAAG,YAAY,GAAG,MAAM,CAAC,CAAC;AAElF,MAAM,MAAM,yBAAyB,GAAG,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,GAAG,YAAY,GAAG,OAAO,CAAC;AAE9F,eAAO,MAAM,oBAAoB,kHAgBhC,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,iBAAiB,CACjD;IACE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,oBAAoB,EAAE,EAAE,CAAC;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,oBAAoB,KAAK,IAAI,CAAC;CACnD,GAAG,OAAO,CACZ,CAAC;AAEF,eAAO,MAAM,cAAc;mBARR,MAAM;kBACP,MAAM;cACV,oBAAoB,EAAE,EAAE;UAC5B,MAAM;eACD,CAAC,MAAM,EAAE,oBAAoB,KAAK,IAAI;;;2CAwGpD,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { useStackDropForElements } from './useStackDropForElements';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/hooks/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { type Orientation } from '../components/Stack';
2
+ import { type StackItemRearrangeHandler } from '../components/StackContext';
3
+ /**
4
+ * Hook to handle drag and drop functionality for Stack components.
5
+ */
6
+ export declare const useStackDropForElements: ({ element, selfDroppable, orientation, id, onRearrange, }: {
7
+ element: HTMLDivElement | null;
8
+ selfDroppable: boolean;
9
+ orientation: Orientation;
10
+ id?: string;
11
+ onRearrange?: StackItemRearrangeHandler;
12
+ }) => {
13
+ dropping: boolean;
14
+ };
15
+ //# sourceMappingURL=useStackDropForElements.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useStackDropForElements.d.ts","sourceRoot":"","sources":["../../../../src/hooks/useStackDropForElements.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,KAAK,yBAAyB,EAAsB,MAAM,4BAA4B,CAAC;AAEhG;;GAEG;AACH,eAAO,MAAM,uBAAuB,8DAMjC;IACD,OAAO,EAAE,cAAc,GAAG,IAAI,CAAC;IAC/B,aAAa,EAAE,OAAO,CAAC;IACvB,WAAW,EAAE,WAAW,CAAC;IACzB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,WAAW,CAAC,EAAE,yBAAyB,CAAC;CACzC;;CA4CA,CAAC"}
@@ -1 +1 @@
1
- {"version":"5.7.2"}
1
+ {"version":"5.7.3"}
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "@dxos/react-ui-stack",
3
- "version": "0.7.5-main.499c70c",
3
+ "version": "0.7.5-main.5ae2ba8",
4
4
  "description": "A stack component.",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
7
7
  "license": "MIT",
8
8
  "author": "DXOS.org",
9
9
  "sideEffects": true,
10
+ "type": "module",
10
11
  "exports": {
11
12
  ".": {
12
13
  "types": "./dist/types/src/index.d.ts",
@@ -36,22 +37,23 @@
36
37
  ],
37
38
  "dependencies": {
38
39
  "@atlaskit/pragmatic-drag-and-drop": "^1.4.0",
40
+ "@atlaskit/pragmatic-drag-and-drop-auto-scroll": "^2.1.0",
39
41
  "@atlaskit/pragmatic-drag-and-drop-hitbox": "^1.0.3",
40
42
  "@effect/schema": "^0.75.5",
41
- "@fluentui/react-tabster": "^9.19.0",
42
- "@radix-ui/primitive": "^1.0.0",
43
- "@radix-ui/react-compose-refs": "^1.0.0",
44
- "@radix-ui/react-context": "^1.0.0",
45
- "@radix-ui/react-menu": "^2.0.6",
46
- "@radix-ui/react-slot": "^1.0.1",
47
- "@radix-ui/react-use-controllable-state": "^1.0.0",
43
+ "@fluentui/react-tabster": "9.23.3",
44
+ "@radix-ui/primitive": "1.1.1",
45
+ "@radix-ui/react-compose-refs": "1.1.1",
46
+ "@radix-ui/react-context": "1.1.1",
47
+ "@radix-ui/react-menu": "2.1.6",
48
+ "@radix-ui/react-slot": "1.1.2",
49
+ "@radix-ui/react-use-controllable-state": "1.1.0",
48
50
  "react-resize-detector": "^11.0.1",
49
- "@dxos/echo-schema": "0.7.5-main.499c70c",
50
- "@dxos/keyboard": "0.7.5-main.499c70c",
51
- "@dxos/react-ui-attention": "0.7.5-main.499c70c",
52
- "@dxos/util": "0.7.5-main.499c70c",
53
- "@dxos/react-ui-mosaic": "0.7.5-main.499c70c",
54
- "@dxos/live-object": "0.7.5-main.499c70c"
51
+ "@dxos/echo-schema": "0.7.5-main.5ae2ba8",
52
+ "@dxos/live-object": "0.7.5-main.5ae2ba8",
53
+ "@dxos/keyboard": "0.7.5-main.5ae2ba8",
54
+ "@dxos/react-ui-attention": "0.7.5-main.5ae2ba8",
55
+ "@dxos/react-ui-dnd": "0.7.5-main.5ae2ba8",
56
+ "@dxos/util": "0.7.5-main.5ae2ba8"
55
57
  },
56
58
  "devDependencies": {
57
59
  "@phosphor-icons/react": "^2.1.5",
@@ -60,24 +62,24 @@
60
62
  "react": "~18.2.0",
61
63
  "react-dom": "~18.2.0",
62
64
  "vite": "5.4.7",
63
- "@dxos/app-graph": "0.7.5-main.499c70c",
64
- "@dxos/client": "0.7.5-main.499c70c",
65
- "@dxos/echo-schema": "0.7.5-main.499c70c",
66
- "@dxos/random": "0.7.5-main.499c70c",
67
- "@dxos/react-ui": "0.7.5-main.499c70c",
68
- "@dxos/react-ui-theme": "0.7.5-main.499c70c",
69
- "@dxos/react-ui-editor": "0.7.5-main.499c70c",
70
- "@dxos/storybook-utils": "0.7.5-main.499c70c",
71
- "@dxos/test-utils": "0.7.5-main.499c70c"
65
+ "@dxos/app-graph": "0.7.5-main.5ae2ba8",
66
+ "@dxos/client": "0.7.5-main.5ae2ba8",
67
+ "@dxos/echo-schema": "0.7.5-main.5ae2ba8",
68
+ "@dxos/random": "0.7.5-main.5ae2ba8",
69
+ "@dxos/react-ui": "0.7.5-main.5ae2ba8",
70
+ "@dxos/react-ui-editor": "0.7.5-main.5ae2ba8",
71
+ "@dxos/react-ui-theme": "0.7.5-main.5ae2ba8",
72
+ "@dxos/storybook-utils": "0.7.5-main.5ae2ba8",
73
+ "@dxos/test-utils": "0.7.5-main.5ae2ba8"
72
74
  },
73
75
  "peerDependencies": {
74
76
  "@phosphor-icons/react": "^2.1.5",
75
77
  "react": "~18.2.0",
76
78
  "react-dom": "~18.2.0",
77
- "@dxos/client": "0.7.5-main.499c70c",
78
- "@dxos/react-ui": "0.7.5-main.499c70c",
79
- "@dxos/random": "0.7.5-main.499c70c",
80
- "@dxos/react-ui-theme": "0.7.5-main.499c70c"
79
+ "@dxos/client": "0.7.5-main.5ae2ba8",
80
+ "@dxos/random": "0.7.5-main.5ae2ba8",
81
+ "@dxos/react-ui-theme": "0.7.5-main.5ae2ba8",
82
+ "@dxos/react-ui": "0.7.5-main.5ae2ba8"
81
83
  },
82
84
  "publishConfig": {
83
85
  "access": "public"
@@ -126,7 +126,7 @@ export const Default: Story = {
126
126
  };
127
127
 
128
128
  const meta: Meta<typeof StorybookStack> = {
129
- title: 'ui/react-ui-stack-next/Stack',
129
+ title: 'ui/react-ui-stack/Stack',
130
130
  component: StorybookStack,
131
131
  decorators: [withTheme],
132
132
  argTypes: { orientation: { control: 'radio', options: ['horizontal', 'vertical'] } },
@@ -1,34 +1,34 @@
1
1
  //
2
- // Copyright 2024 DXOS.org
2
+ // Copyright 2025 DXOS.org
3
3
  //
4
- import { dropTargetForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
5
- import { attachClosestEdge, extractClosestEdge } from '@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge';
4
+
6
5
  import { useArrowNavigationGroup } from '@fluentui/react-tabster';
7
6
  import { composeRefs } from '@radix-ui/react-compose-refs';
8
- import React, {
9
- Children,
10
- type CSSProperties,
11
- type ComponentPropsWithRef,
12
- forwardRef,
13
- useLayoutEffect,
14
- useState,
15
- } from 'react';
7
+ import React, { Children, type CSSProperties, type ComponentPropsWithRef, forwardRef, useState, useMemo } from 'react';
16
8
 
17
9
  import { type ThemedClassName, ListItem } from '@dxos/react-ui';
18
10
  import { mx } from '@dxos/react-ui-theme';
19
11
 
20
- import { type StackContextValue, StackContext, type StackItemData } from './StackContext';
12
+ import { type StackContextValue, StackContext } from './StackContext';
13
+ import { useStackDropForElements } from '../hooks';
21
14
 
22
15
  export type Orientation = 'horizontal' | 'vertical';
23
- export type Size = 'intrinsic' | 'contain';
16
+ export type Size = 'intrinsic' | 'contain' | 'contain-fit-content';
24
17
 
25
18
  export type StackProps = Omit<ThemedClassName<ComponentPropsWithRef<'div'>>, 'aria-orientation'> &
26
19
  Partial<StackContextValue> & { itemsCount?: number };
27
20
 
28
21
  export const railGridHorizontal = 'grid-rows-[[rail-start]_var(--rail-size)_[content-start]_1fr_[content-end]]';
29
-
30
22
  export const railGridVertical = 'grid-cols-[[rail-start]_var(--rail-size)_[content-start]_1fr_[content-end]]';
31
23
 
24
+ // TODO(ZaymonFC): Magic 2px to stop overflow (tabster dummies... ask @thure).
25
+ export const railGridHorizontalContainFitContent =
26
+ 'grid-rows-[[rail-start]_var(--rail-size)_[content-start]_fit-content(calc(100%-var(--rail-size)*2+2px))_[content-end]]';
27
+ export const railGridVerticalContainFitContent =
28
+ 'grid-cols-[[rail-start]_var(--rail-size)_[content-start]_fit-content(calc(100%-var(--rail-size)*2+2px))_[content-end]]';
29
+
30
+ export const autoScrollRootAttributes = { 'data-drag-autoscroll': 'idle' };
31
+
32
32
  export const Stack = forwardRef<HTMLDivElement, StackProps>(
33
33
  (
34
34
  {
@@ -46,49 +46,34 @@ export const Stack = forwardRef<HTMLDivElement, StackProps>(
46
46
  ) => {
47
47
  const [stackElement, stackRef] = useState<HTMLDivElement | null>(null);
48
48
  const composedItemRef = composeRefs<HTMLDivElement>(stackRef, forwardedRef);
49
- const [dropping, setDropping] = useState(false);
50
-
51
49
  const arrowNavigationGroup = useArrowNavigationGroup({ axis: orientation });
52
50
 
53
51
  const styles: CSSProperties = {
54
- [orientation === 'horizontal' ? 'gridTemplateColumns' : 'gridTemplateRows']: `repeat(${itemsCount}, min-content)`,
52
+ [orientation === 'horizontal' ? 'gridTemplateColumns' : 'gridTemplateRows']:
53
+ `repeat(${itemsCount}, min-content) [tabster-dummies] 0`,
55
54
  ...style,
56
55
  };
57
56
 
58
57
  const selfDroppable = !!(itemsCount < 1 && onRearrange && props.id);
59
58
 
60
- useLayoutEffect(() => {
61
- if (!stackElement || !selfDroppable) {
62
- return;
59
+ const { dropping } = useStackDropForElements({
60
+ id: props.id,
61
+ element: stackElement,
62
+ selfDroppable,
63
+ orientation,
64
+ onRearrange,
65
+ });
66
+
67
+ const gridClasses = useMemo(() => {
68
+ if (!rail) {
69
+ return orientation === 'horizontal' ? 'grid-rows-1 pli-1' : 'grid-cols-1 plb-1';
63
70
  }
64
- const acceptSourceType = orientation === 'horizontal' ? 'column' : 'card';
65
- return dropTargetForElements({
66
- element: stackElement,
67
- getData: ({ input, element }) => {
68
- return attachClosestEdge(
69
- { id: props.id, type: orientation === 'horizontal' ? 'card' : 'column' },
70
- { input, element, allowedEdges: [orientation === 'horizontal' ? 'left' : 'top'] },
71
- );
72
- },
73
- onDragEnter: ({ source }) => {
74
- if (source.data.type === acceptSourceType) {
75
- setDropping(true);
76
- }
77
- },
78
- onDrag: ({ source }) => {
79
- if (source.data.type === acceptSourceType) {
80
- setDropping(true);
81
- }
82
- },
83
- onDragLeave: () => setDropping(false),
84
- onDrop: ({ self, source }) => {
85
- setDropping(false);
86
- if (source.data.type === acceptSourceType && selfDroppable) {
87
- onRearrange(source.data as StackItemData, self.data as StackItemData, extractClosestEdge(self.data));
88
- }
89
- },
90
- });
91
- }, [stackElement, selfDroppable]);
71
+ if (orientation === 'horizontal') {
72
+ return size === 'contain-fit-content' ? railGridHorizontalContainFitContent : railGridHorizontal;
73
+ } else {
74
+ return size === 'contain-fit-content' ? railGridVerticalContainFitContent : railGridVertical;
75
+ }
76
+ }, [rail, orientation, size]);
92
77
 
93
78
  return (
94
79
  <StackContext.Provider value={{ orientation, rail, size, onRearrange }}>
@@ -97,25 +82,27 @@ export const Stack = forwardRef<HTMLDivElement, StackProps>(
97
82
  {...arrowNavigationGroup}
98
83
  className={mx(
99
84
  'grid relative',
100
- rail
101
- ? orientation === 'horizontal'
102
- ? railGridHorizontal
103
- : railGridVertical
104
- : orientation === 'horizontal'
105
- ? 'grid-rows-1'
106
- : 'grid-cols-1',
107
- size === 'contain' &&
85
+ gridClasses,
86
+ (size === 'contain' || size === 'contain-fit-content') &&
108
87
  (orientation === 'horizontal'
109
88
  ? 'overflow-x-auto min-bs-0 bs-full max-bs-full'
110
89
  : 'overflow-y-auto min-is-0 is-full max-is-full'),
111
90
  classNames,
112
91
  )}
92
+ data-rail={rail}
113
93
  aria-orientation={orientation}
114
94
  style={styles}
115
95
  ref={composedItemRef}
116
96
  >
117
97
  {children}
118
- {selfDroppable && dropping && <ListItem.DropIndicator edge={orientation === 'horizontal' ? 'left' : 'top'} />}
98
+ {selfDroppable && dropping && (
99
+ <ListItem.DropIndicator
100
+ lineInset={8}
101
+ terminalInset={-8}
102
+ gap={-8}
103
+ edge={orientation === 'horizontal' ? 'left' : 'top'}
104
+ />
105
+ )}
119
106
  </div>
120
107
  </StackContext.Provider>
121
108
  );
@@ -5,15 +5,17 @@
5
5
  import type { Edge } from '@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge';
6
6
  import { createContext, useContext } from 'react';
7
7
 
8
+ import { type Size as DndSize } from '@dxos/react-ui-dnd';
9
+
8
10
  import { type Orientation, type Size } from './Stack';
9
11
 
10
- export type StackItemSize = number | 'min-content';
12
+ export type StackItemSize = DndSize;
11
13
 
12
14
  export type StackItemData = { id: string; type: 'column' | 'card' };
13
15
 
14
- export type StackItemRearrangeHandler = (
15
- source: StackItemData,
16
- target: StackItemData,
16
+ export type StackItemRearrangeHandler<Data extends { id: string } = StackItemData> = (
17
+ source: Data,
18
+ target: Data,
17
19
  closestEdge: Edge | null,
18
20
  ) => void;
19
21
 
@@ -4,8 +4,8 @@
4
4
 
5
5
  import { combine } from '@atlaskit/pragmatic-drag-and-drop/combine';
6
6
  import { draggable, dropTargetForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
7
- import { disableNativeDragPreview } from '@atlaskit/pragmatic-drag-and-drop/element/disable-native-drag-preview';
8
- import { preventUnhandled } from '@atlaskit/pragmatic-drag-and-drop/prevent-unhandled';
7
+ import { preserveOffsetOnSource } from '@atlaskit/pragmatic-drag-and-drop/element/preserve-offset-on-source';
8
+ import { scrollJustEnoughIntoView } from '@atlaskit/pragmatic-drag-and-drop/element/scroll-just-enough-into-view';
9
9
  import {
10
10
  attachClosestEdge,
11
11
  extractClosestEdge,
@@ -16,6 +16,7 @@ import { composeRefs } from '@radix-ui/react-compose-refs';
16
16
  import React, { forwardRef, useLayoutEffect, useState, type ComponentPropsWithRef, useCallback } from 'react';
17
17
 
18
18
  import { type ThemedClassName, ListItem } from '@dxos/react-ui';
19
+ import { resizeAttributes, sizeStyle } from '@dxos/react-ui-dnd';
19
20
  import { mx } from '@dxos/react-ui-theme';
20
21
 
21
22
  import { useStack, StackItemContext, type StackItemSize, type StackItemData } from './StackContext';
@@ -36,7 +37,8 @@ import {
36
37
  StackItemSigilButton,
37
38
  } from './StackItemSigil';
38
39
 
39
- export const DEFAULT_HORIZONTAL_SIZE = 44 satisfies StackItemSize;
40
+ // NOTE: 48rem fills the screen on a MacbookPro with the sidebars closed.
41
+ export const DEFAULT_HORIZONTAL_SIZE = 48 satisfies StackItemSize;
40
42
  export const DEFAULT_VERTICAL_SIZE = 'min-content' satisfies StackItemSize;
41
43
  export const DEFAULT_EXTRINSIC_SIZE = DEFAULT_HORIZONTAL_SIZE satisfies StackItemSize;
42
44
 
@@ -46,10 +48,27 @@ export type StackItemRootProps = ThemedClassName<ComponentPropsWithRef<'div'>> &
46
48
  size?: StackItemSize;
47
49
  onSizeChange?: (nextSize: StackItemSize) => void;
48
50
  role?: 'article' | 'section';
51
+ disableRearrange?: boolean;
52
+ focusIndicatorVariant?: 'over-all' | 'group';
49
53
  };
50
54
 
51
55
  const StackItemRoot = forwardRef<HTMLDivElement, StackItemRootProps>(
52
- ({ item, children, classNames, size: propsSize, onSizeChange, role, order, style, ...props }, forwardedRef) => {
56
+ (
57
+ {
58
+ item,
59
+ children,
60
+ classNames,
61
+ size: propsSize,
62
+ onSizeChange,
63
+ role,
64
+ order,
65
+ style,
66
+ disableRearrange,
67
+ focusIndicatorVariant = 'over-all',
68
+ ...props
69
+ },
70
+ forwardedRef,
71
+ ) => {
53
72
  const [itemElement, itemRef] = useState<HTMLDivElement | null>(null);
54
73
  const [selfDragHandleElement, selfDragHandleRef] = useState<HTMLDivElement | null>(null);
55
74
  const [closestEdge, setEdge] = useState<Edge | null>(null);
@@ -74,7 +93,7 @@ const StackItemRoot = forwardRef<HTMLDivElement, StackItemRootProps>(
74
93
  const type = orientation === 'horizontal' ? 'column' : 'card';
75
94
 
76
95
  useLayoutEffect(() => {
77
- if (!itemElement || !onRearrange) {
96
+ if (!itemElement || !onRearrange || disableRearrange) {
78
97
  return;
79
98
  }
80
99
  return combine(
@@ -82,10 +101,20 @@ const StackItemRoot = forwardRef<HTMLDivElement, StackItemRootProps>(
82
101
  element: itemElement,
83
102
  ...(selfDragHandleElement && { dragHandle: selfDragHandleElement }),
84
103
  getInitialData: () => ({ id: item.id, type }),
85
- // TODO(thure): tabster focus honeypots are causing the preview to render with the wrong dimensions; what do?
86
- onGenerateDragPreview: ({ nativeSetDragImage }) => {
87
- disableNativeDragPreview({ nativeSetDragImage });
88
- preventUnhandled.start();
104
+ onGenerateDragPreview: ({ nativeSetDragImage, source, location }) => {
105
+ document.body.setAttribute('data-drag-preview', 'true');
106
+ scrollJustEnoughIntoView({ element: source.element });
107
+ const { x, y } = preserveOffsetOnSource({ element: source.element, input: location.current.input })({
108
+ container: (source.element.offsetParent ?? document.body) as HTMLElement,
109
+ });
110
+ nativeSetDragImage?.(source.element, x, y);
111
+ },
112
+ onDragStart: () => {
113
+ document.body.removeAttribute('data-drag-preview');
114
+ itemElement?.closest('[data-drag-autoscroll]')?.setAttribute('data-drag-autoscroll', 'active');
115
+ },
116
+ onDrop: () => {
117
+ itemElement?.closest('[data-drag-autoscroll]')?.setAttribute('data-drag-autoscroll', 'idle');
89
118
  },
90
119
  }),
91
120
  dropTargetForElements({
@@ -126,17 +155,20 @@ const StackItemRoot = forwardRef<HTMLDivElement, StackItemRootProps>(
126
155
  tabIndex={0}
127
156
  {...focusGroupAttrs}
128
157
  className={mx(
129
- 'group/stack-item grid relative ch-focus-ring-inset-over-all',
130
- size === 'min-content' && (orientation === 'horizontal' ? 'is-min' : 'bs-min'),
158
+ 'group/stack-item grid relative',
159
+ focusIndicatorVariant === 'over-all'
160
+ ? 'dx-focus-ring-inset-over-all'
161
+ : orientation === 'horizontal'
162
+ ? 'dx-focus-ring-group-x'
163
+ : 'dx-focus-ring-group-y',
131
164
  orientation === 'horizontal' ? 'grid-rows-subgrid' : 'grid-cols-subgrid',
132
165
  rail && (orientation === 'horizontal' ? 'row-span-2' : 'col-span-2'),
133
166
  classNames,
134
167
  )}
135
168
  data-dx-stack-item
169
+ {...resizeAttributes}
136
170
  style={{
137
- ...(size !== 'min-content' && {
138
- [orientation === 'horizontal' ? 'inlineSize' : 'blockSize']: `${size}rem`,
139
- }),
171
+ ...sizeStyle(size, orientation),
140
172
  ...(Number.isFinite(order) && {
141
173
  [orientation === 'horizontal' ? 'gridColumn' : 'gridRow']: `${order}`,
142
174
  }),
@@ -145,7 +177,7 @@ const StackItemRoot = forwardRef<HTMLDivElement, StackItemRootProps>(
145
177
  ref={composedItemRef}
146
178
  >
147
179
  {children}
148
- {closestEdge && <ListItem.DropIndicator edge={closestEdge} />}
180
+ {closestEdge && <ListItem.DropIndicator lineInset={8} terminalInset={-8} edge={closestEdge} />}
149
181
  </Root>
150
182
  </StackItemContext.Provider>
151
183
  );
@@ -2,7 +2,7 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import React, { type ComponentPropsWithoutRef } from 'react';
5
+ import React, { type ComponentPropsWithoutRef, forwardRef } from 'react';
6
6
 
7
7
  import { type ThemedClassName } from '@dxos/react-ui';
8
8
  import { mx } from '@dxos/react-ui-theme';
@@ -10,33 +10,53 @@ import { mx } from '@dxos/react-ui-theme';
10
10
  import { useStack } from './StackContext';
11
11
 
12
12
  export type StackItemContentProps = ThemedClassName<ComponentPropsWithoutRef<'div'>> & {
13
- toolbar?: boolean;
13
+ /**
14
+ * This flag is required in order to clarify a developer experience that seemed like it needed extra boilerplate
15
+ * (`row-span-2`) or was buggy. See the description of the StackItem.Content component itself for more information.
16
+ */
17
+ toolbar: boolean;
18
+
19
+ /**
20
+ * Whether to provide for the layout of a statusbar after the content.
21
+ */
14
22
  statusbar?: boolean;
15
- };
16
23
 
17
- export const StackItemContent = ({
18
- children,
19
- toolbar = true,
20
- statusbar,
21
- classNames,
22
- ...props
23
- }: StackItemContentProps) => {
24
- const { size } = useStack();
25
-
26
- return (
27
- <div
28
- role='none'
29
- {...props}
30
- className={mx('group grid grid-cols-[100%]', size === 'contain' && 'min-bs-0 overflow-hidden', classNames)}
31
- style={{
32
- gridTemplateRows: [
33
- ...(toolbar ? ['var(--rail-action)'] : []),
34
- '1fr',
35
- ...(statusbar ? ['var(--statusbar-size)'] : []),
36
- ].join(' '),
37
- }}
38
- >
39
- {children}
40
- </div>
41
- );
24
+ /**
25
+ * Whether to set a certain aspect ratio on the content, including the toolbar and statusbar. This is provided for
26
+ * convenience and consistency; it can instead be specified by the `classNames` or `style` props as needed.
27
+ */
28
+ size?: 'intrinsic' | 'video' | 'square';
42
29
  };
30
+
31
+ /**
32
+ * This component should be used by plugins for rendering content within a stack item, a.k.a. a “plank” or “section”.
33
+ * The `toolbar` flag must be provided since this component provides for the layout of content with the toolbar.
34
+ */
35
+ export const StackItemContent = forwardRef<HTMLDivElement, StackItemContentProps>(
36
+ ({ children, toolbar, statusbar, classNames, size = 'intrinsic', ...props }, forwardedRef) => {
37
+ const { size: stackItemSize } = useStack();
38
+
39
+ return (
40
+ <div
41
+ role='none'
42
+ {...props}
43
+ className={mx(
44
+ 'group grid grid-cols-[100%]',
45
+ stackItemSize === 'contain' && 'min-bs-0 overflow-hidden',
46
+ size === 'video' ? 'aspect-video' : size === 'square' && 'aspect-square',
47
+ classNames,
48
+ )}
49
+ style={{
50
+ gridTemplateRows: [
51
+ ...(toolbar ? ['var(--rail-action)'] : []),
52
+ '1fr',
53
+ ...(statusbar ? ['var(--statusbar-size)'] : []),
54
+ ].join(' '),
55
+ }}
56
+ ref={forwardedRef}
57
+ >
58
+ {children}
59
+ </div>
60
+ );
61
+ },
62
+ );