@dxos/react-ui-mosaic 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.
Files changed (115) hide show
  1. package/dist/lib/chunk-Mosaic.mjs +1024 -0
  2. package/dist/lib/chunk-Mosaic.mjs.map +1 -0
  3. package/dist/lib/index.mjs +653 -0
  4. package/dist/lib/index.mjs.map +1 -0
  5. package/dist/lib/playwright.mjs +200 -0
  6. package/dist/lib/playwright.mjs.map +1 -0
  7. package/dist/lib/testing.mjs +127 -0
  8. package/dist/lib/testing.mjs.map +1 -0
  9. package/dist/lib/translations.mjs +11 -0
  10. package/dist/lib/translations.mjs.map +1 -0
  11. package/dist/types/src/components/Board/Board.d.ts +7 -27
  12. package/dist/types/src/components/Board/Board.d.ts.map +1 -1
  13. package/dist/types/src/components/Board/Board.stories.d.ts.map +1 -1
  14. package/dist/types/src/components/Board/BoardColumnContext.d.ts +10 -0
  15. package/dist/types/src/components/Board/BoardColumnContext.d.ts.map +1 -0
  16. package/dist/types/src/components/Board/BoardContext.d.ts +26 -0
  17. package/dist/types/src/components/Board/BoardContext.d.ts.map +1 -0
  18. package/dist/types/src/components/Board/Column.d.ts +2 -7
  19. package/dist/types/src/components/Board/Column.d.ts.map +1 -1
  20. package/dist/types/src/components/Board/index.d.ts +2 -0
  21. package/dist/types/src/components/Board/index.d.ts.map +1 -1
  22. package/dist/types/src/components/Focus/Focus.d.ts.map +1 -1
  23. package/dist/types/src/components/Mosaic/Container.d.ts +6 -34
  24. package/dist/types/src/components/Mosaic/Container.d.ts.map +1 -1
  25. package/dist/types/src/components/Mosaic/Mosaic.d.ts +10 -15
  26. package/dist/types/src/components/Mosaic/Mosaic.d.ts.map +1 -1
  27. package/dist/types/src/components/Mosaic/MosaicContainerContext.d.ts +34 -0
  28. package/dist/types/src/components/Mosaic/MosaicContainerContext.d.ts.map +1 -0
  29. package/dist/types/src/components/Mosaic/MosaicTileContext.d.ts +31 -0
  30. package/dist/types/src/components/Mosaic/MosaicTileContext.d.ts.map +1 -0
  31. package/dist/types/src/components/Mosaic/Placeholder.d.ts +3 -3
  32. package/dist/types/src/components/Mosaic/Placeholder.d.ts.map +1 -1
  33. package/dist/types/src/components/Mosaic/Stack.d.ts +8 -2
  34. package/dist/types/src/components/Mosaic/Stack.d.ts.map +1 -1
  35. package/dist/types/src/components/Mosaic/Stack.stories.d.ts.map +1 -1
  36. package/dist/types/src/components/Mosaic/Tile.d.ts +6 -32
  37. package/dist/types/src/components/Mosaic/Tile.d.ts.map +1 -1
  38. package/dist/types/src/components/Mosaic/VirtualStackPagination.stories.d.ts +13 -0
  39. package/dist/types/src/components/Mosaic/VirtualStackPagination.stories.d.ts.map +1 -0
  40. package/dist/types/src/components/Mosaic/index.d.ts +0 -1
  41. package/dist/types/src/components/Mosaic/index.d.ts.map +1 -1
  42. package/dist/types/src/components/SearchStack/SearchStack.d.ts +1 -1
  43. package/dist/types/src/components/SearchStack/SearchStack.d.ts.map +1 -1
  44. package/dist/types/src/hooks/index.d.ts +1 -0
  45. package/dist/types/src/hooks/index.d.ts.map +1 -1
  46. package/dist/types/src/hooks/useDefaultColumnEventHandler.d.ts +2 -2
  47. package/dist/types/src/hooks/useDefaultColumnEventHandler.d.ts.map +1 -1
  48. package/dist/types/src/hooks/useEventHandlerAdapter.d.ts +3 -3
  49. package/dist/types/src/hooks/useEventHandlerAdapter.d.ts.map +1 -1
  50. package/dist/types/src/hooks/useVirtualizerPagination.d.ts +60 -0
  51. package/dist/types/src/hooks/useVirtualizerPagination.d.ts.map +1 -0
  52. package/dist/types/src/hooks/useVirtualizerPagination.test.d.ts +2 -0
  53. package/dist/types/src/hooks/useVirtualizerPagination.test.d.ts.map +1 -0
  54. package/dist/types/src/hooks/useVisibleItems.d.ts +2 -2
  55. package/dist/types/src/hooks/useVisibleItems.d.ts.map +1 -1
  56. package/dist/types/tsconfig.tsbuildinfo +1 -1
  57. package/package.json +35 -37
  58. package/src/components/Board/Board.stories.tsx +7 -6
  59. package/src/components/Board/Board.tsx +9 -54
  60. package/src/components/Board/BoardColumnContext.ts +25 -0
  61. package/src/components/Board/BoardContext.ts +43 -0
  62. package/src/components/Board/Column.tsx +13 -27
  63. package/src/components/Board/Item.tsx +2 -2
  64. package/src/components/Board/index.ts +3 -0
  65. package/src/components/Mosaic/Container.tsx +31 -53
  66. package/src/components/Mosaic/DragHandle.tsx +1 -1
  67. package/src/components/Mosaic/{Mosaic.tsx → Mosaic.ts} +5 -16
  68. package/src/components/Mosaic/MosaicContainerContext.ts +44 -0
  69. package/src/components/Mosaic/MosaicTileContext.ts +34 -0
  70. package/src/components/Mosaic/Placeholder.tsx +7 -8
  71. package/src/components/Mosaic/ResizeHandle.stories.tsx +4 -4
  72. package/src/components/Mosaic/ResizeHandle.tsx +2 -2
  73. package/src/components/Mosaic/Stack.stories.tsx +49 -13
  74. package/src/components/Mosaic/Stack.tsx +30 -9
  75. package/src/components/Mosaic/Tile.tsx +33 -33
  76. package/src/components/Mosaic/VirtualStackPagination.stories.tsx +423 -0
  77. package/src/components/Mosaic/index.ts +0 -1
  78. package/src/hooks/index.ts +1 -0
  79. package/src/hooks/useDefaultColumnEventHandler.ts +2 -2
  80. package/src/hooks/useEventHandlerAdapter.ts +4 -5
  81. package/src/hooks/useVirtualizerPagination.test.tsx +105 -0
  82. package/src/hooks/useVirtualizerPagination.ts +473 -0
  83. package/src/hooks/useVisibleItems.ts +2 -2
  84. package/src/playwright/smoke.spec.ts +4 -1
  85. package/src/testing/DefaultStackTile.tsx +1 -1
  86. package/src/testing/decorator.tsx +3 -3
  87. package/dist/lib/browser/chunk-OBVIYZLR.mjs +0 -1119
  88. package/dist/lib/browser/chunk-OBVIYZLR.mjs.map +0 -7
  89. package/dist/lib/browser/index.mjs +0 -701
  90. package/dist/lib/browser/index.mjs.map +0 -7
  91. package/dist/lib/browser/meta.json +0 -1
  92. package/dist/lib/browser/playwright/index.mjs +0 -256
  93. package/dist/lib/browser/playwright/index.mjs.map +0 -7
  94. package/dist/lib/browser/testing/index.mjs +0 -136
  95. package/dist/lib/browser/testing/index.mjs.map +0 -7
  96. package/dist/lib/browser/translations.mjs +0 -18
  97. package/dist/lib/browser/translations.mjs.map +0 -7
  98. package/dist/lib/node-esm/chunk-4IEMCMIV.mjs +0 -1121
  99. package/dist/lib/node-esm/chunk-4IEMCMIV.mjs.map +0 -7
  100. package/dist/lib/node-esm/index.mjs +0 -702
  101. package/dist/lib/node-esm/index.mjs.map +0 -7
  102. package/dist/lib/node-esm/meta.json +0 -1
  103. package/dist/lib/node-esm/playwright/index.mjs +0 -258
  104. package/dist/lib/node-esm/playwright/index.mjs.map +0 -7
  105. package/dist/lib/node-esm/testing/index.mjs +0 -137
  106. package/dist/lib/node-esm/testing/index.mjs.map +0 -7
  107. package/dist/lib/node-esm/translations.mjs +0 -20
  108. package/dist/lib/node-esm/translations.mjs.map +0 -7
  109. package/dist/types/src/components/Mosaic/Root.d.ts +0 -35
  110. package/dist/types/src/components/Mosaic/Root.d.ts.map +0 -1
  111. package/dist/types/src/components/Mosaic/types.d.ts +0 -86
  112. package/dist/types/src/components/Mosaic/types.d.ts.map +0 -1
  113. package/src/components/Mosaic/Root.tsx +0 -288
  114. package/src/components/Mosaic/types.ts +0 -94
  115. /package/src/components/Focus/{Focus.tsx → Focus.ts} +0 -0
@@ -1,137 +0,0 @@
1
- import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
2
- import {
3
- Focus,
4
- Mosaic
5
- } from "../chunk-4IEMCMIV.mjs";
6
-
7
- // src/testing/decorator.tsx
8
- import React from "react";
9
- var withMosaic = () => {
10
- return (Story) => /* @__PURE__ */ React.createElement(Mosaic.Root, null, /* @__PURE__ */ React.createElement(Story, null));
11
- };
12
-
13
- // src/testing/types.ts
14
- import * as Schema from "effect/Schema";
15
- import { DXN, Ref, Type } from "@dxos/echo";
16
- import { EntityId } from "@dxos/keys";
17
- var TestItem = class extends Type.makeObject(DXN.make("com.example.type.item", "0.1.0"))(Schema.Struct({
18
- name: Schema.String,
19
- description: Schema.optional(Schema.String),
20
- label: Schema.optional(Schema.String)
21
- })) {
22
- };
23
- var TestColumn = class extends Type.makeObject(DXN.make("com.example.type.column", "0.1.0"))(Schema.Struct({
24
- id: EntityId,
25
- name: Schema.String,
26
- items: Schema.mutable(Schema.Array(Ref.Ref(TestItem)))
27
- })) {
28
- };
29
-
30
- // src/testing/CardContainer.tsx
31
- import { useControllableState } from "@radix-ui/react-use-controllable-state";
32
- import React2 from "react";
33
- import { Icon, Popover } from "@dxos/react-ui";
34
- import { ResizeHandle, resizeAttributes, sizeStyle } from "@dxos/react-ui-dnd";
35
- var DEFAULT_BLOCK_SIZE = 22;
36
- var MIN_BLOCK_SIZE = 8;
37
- var CardContainer = ({ children, role, icon = "ph--arrow-line-down--regular" }) => {
38
- switch (role) {
39
- case "popover":
40
- return /* @__PURE__ */ React2.createElement("div", {
41
- className: "flex justify-center"
42
- }, /* @__PURE__ */ React2.createElement(PopoverCardContainer, {
43
- icon
44
- }, children));
45
- case "intrinsic":
46
- default:
47
- return /* @__PURE__ */ React2.createElement(IntrinsicCardContainer, null, children);
48
- }
49
- };
50
- var PopoverCardContainer = ({ children, icon = "ph--arrow-line-down--regular" }) => {
51
- return /* @__PURE__ */ React2.createElement(Popover.Root, {
52
- open: true
53
- }, /* @__PURE__ */ React2.createElement(Popover.Trigger, {
54
- asChild: true
55
- }, /* @__PURE__ */ React2.createElement(Icon, {
56
- icon
57
- })), /* @__PURE__ */ React2.createElement(Popover.Portal, null, /* @__PURE__ */ React2.createElement(Popover.Content, {
58
- onOpenAutoFocus: (event) => event.preventDefault()
59
- }, /* @__PURE__ */ React2.createElement(Popover.Viewport, {
60
- classNames: "dx-card-popover"
61
- }, children), /* @__PURE__ */ React2.createElement(Popover.Arrow, null))));
62
- };
63
- var IntrinsicCardContainer = ({ children, defaultSize, size: propSize, onSizeChange }) => {
64
- const [size = DEFAULT_BLOCK_SIZE, setSize] = useControllableState({
65
- prop: propSize,
66
- defaultProp: defaultSize,
67
- onChange: onSizeChange
68
- });
69
- return /* @__PURE__ */ React2.createElement("div", {
70
- className: "relative p-2 grid overflow-hidden border-2 border-dashed border-green-500 rounded-lg",
71
- style: sizeStyle(size, "horizontal"),
72
- ...resizeAttributes
73
- }, /* @__PURE__ */ React2.createElement("div", {
74
- className: "dx-container flex flex-col"
75
- }, children), /* @__PURE__ */ React2.createElement(ResizeHandle, {
76
- side: "inline-end",
77
- fallbackSize: DEFAULT_BLOCK_SIZE,
78
- minSize: MIN_BLOCK_SIZE,
79
- size,
80
- onSizeChange: setSize
81
- }));
82
- };
83
-
84
- // src/testing/DefaultStackTile.tsx
85
- import React3, { useMemo, useRef, useState } from "react";
86
- import { Obj } from "@dxos/echo";
87
- import { Card, IconButton } from "@dxos/react-ui";
88
- import { Menu, createMenuAction } from "@dxos/react-ui-menu";
89
- import { JsonHighlighter } from "@dxos/react-ui-syntax-highlighter";
90
- var DefaultStackTile = (props) => {
91
- const dragHandleRef = useRef(null);
92
- const [open, setOpen] = useState(false);
93
- const menuItems = useMemo(() => [
94
- createMenuAction("toggle-details", () => setOpen((prev) => !prev), {
95
- label: open ? "Hide details" : "Show details",
96
- icon: "ph--circle-dashed--regular"
97
- })
98
- ], [
99
- open
100
- ]);
101
- return /* @__PURE__ */ React3.createElement(Menu.Root, null, /* @__PURE__ */ React3.createElement(Mosaic.Tile, {
102
- ...props,
103
- asChild: true
104
- }, /* @__PURE__ */ React3.createElement(Focus.Item, {
105
- asChild: true
106
- }, /* @__PURE__ */ React3.createElement(Card.Root, {
107
- className: "dx-current dx-hover"
108
- }, /* @__PURE__ */ React3.createElement(Card.Header, null, /* @__PURE__ */ React3.createElement(Card.DragHandle, {
109
- ref: dragHandleRef
110
- }), /* @__PURE__ */ React3.createElement(Card.Title, null, Obj.getLabel(props.data) ?? props.data.id), /* @__PURE__ */ React3.createElement(Card.Block, {
111
- end: true
112
- }, /* @__PURE__ */ React3.createElement(Menu.Trigger, {
113
- asChild: true,
114
- disabled: !menuItems?.length
115
- }, /* @__PURE__ */ React3.createElement(IconButton, {
116
- iconOnly: true,
117
- variant: "ghost",
118
- icon: "ph--dots-three-vertical--regular",
119
- label: "Menu"
120
- }))), /* @__PURE__ */ React3.createElement(Menu.Content, {
121
- items: menuItems
122
- })), open && /* @__PURE__ */ React3.createElement(Card.Row, null, /* @__PURE__ */ React3.createElement(JsonHighlighter, {
123
- data: props.data,
124
- classNames: "text-xs"
125
- }))))));
126
- };
127
- DefaultStackTile.displayName = "DefaultStackTile";
128
- export {
129
- CardContainer,
130
- DefaultStackTile,
131
- IntrinsicCardContainer,
132
- PopoverCardContainer,
133
- TestColumn,
134
- TestItem,
135
- withMosaic
136
- };
137
- //# sourceMappingURL=index.mjs.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../src/testing/decorator.tsx", "../../../../src/testing/types.ts", "../../../../src/testing/CardContainer.tsx", "../../../../src/testing/DefaultStackTile.tsx"],
4
- "sourcesContent": ["//\n// Copyright 2026 DXOS.org\n//\n\nimport { type Decorator } from '@storybook/react-vite';\nimport React from 'react';\n\nimport { Mosaic } from '../components';\n\nexport const withMosaic = (): Decorator => {\n return (Story) => (\n <Mosaic.Root>\n <Story />\n </Mosaic.Root>\n );\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport * as Schema from 'effect/Schema';\n\nimport { DXN, Ref, Type } from '@dxos/echo';\nimport { EntityId } from '@dxos/keys';\n\n//\n// Test Data\n//\n\nexport class TestItem extends Type.makeObject<TestItem>(DXN.make('com.example.type.item', '0.1.0'))(\n Schema.Struct({\n name: Schema.String,\n description: Schema.optional(Schema.String),\n label: Schema.optional(Schema.String),\n }),\n) {}\n\nexport class TestColumn extends Type.makeObject<TestColumn>(DXN.make('com.example.type.column', '0.1.0'))(\n Schema.Struct({\n id: EntityId,\n name: Schema.String,\n items: Schema.mutable(Schema.Array(Ref.Ref(TestItem))),\n }),\n) {}\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { useControllableState } from '@radix-ui/react-use-controllable-state';\nimport React, { type PropsWithChildren } from 'react';\n\nimport { Icon, Popover } from '@dxos/react-ui';\nimport { ResizeHandle, type Size, resizeAttributes, sizeStyle } from '@dxos/react-ui-dnd';\n\nconst DEFAULT_BLOCK_SIZE = 22;\nconst MIN_BLOCK_SIZE = 8;\n\n//\n// Card container.\n//\n\nexport type CardContainerProps = PropsWithChildren<{ role?: 'popover' | 'intrinsic'; icon?: string }>;\n\nexport const CardContainer = ({ children, role, icon = 'ph--arrow-line-down--regular' }: CardContainerProps) => {\n switch (role) {\n case 'popover':\n return (\n <div className='flex justify-center'>\n <PopoverCardContainer icon={icon}>{children}</PopoverCardContainer>\n </div>\n );\n case 'intrinsic':\n default:\n return <IntrinsicCardContainer>{children}</IntrinsicCardContainer>;\n }\n};\n\n//\n// Popover\n//\n\nexport type PopoverCardContainerProps = PropsWithChildren<{ icon?: string }>;\n\nexport const PopoverCardContainer = ({\n children,\n icon = 'ph--arrow-line-down--regular',\n}: PopoverCardContainerProps) => {\n return (\n <Popover.Root open>\n <Popover.Trigger asChild>\n <Icon icon={icon} />\n </Popover.Trigger>\n <Popover.Portal>\n <Popover.Content onOpenAutoFocus={(event: Event) => event.preventDefault()}>\n <Popover.Viewport classNames='dx-card-popover'>{children}</Popover.Viewport>\n <Popover.Arrow />\n </Popover.Content>\n </Popover.Portal>\n </Popover.Root>\n );\n};\n\n//\n// Intrinsic card container (size constrained by card itself).\n//\n\nexport type IntrinsicCardContainerProps = PropsWithChildren<{\n defaultSize?: Size;\n size?: Size;\n onSizeChange?: (size: Size, commit?: boolean) => void;\n}>;\n\nexport const IntrinsicCardContainer = ({\n children,\n defaultSize,\n size: propSize,\n onSizeChange,\n}: IntrinsicCardContainerProps) => {\n const [size = DEFAULT_BLOCK_SIZE, setSize] = useControllableState<Size>({\n prop: propSize,\n defaultProp: defaultSize,\n onChange: onSizeChange,\n });\n\n return (\n <div\n className='relative p-2 grid overflow-hidden border-2 border-dashed border-green-500 rounded-lg'\n style={sizeStyle(size, 'horizontal')}\n {...resizeAttributes}\n >\n <div className='dx-container flex flex-col'>{children}</div>\n <ResizeHandle\n side='inline-end'\n fallbackSize={DEFAULT_BLOCK_SIZE}\n minSize={MIN_BLOCK_SIZE}\n size={size}\n onSizeChange={setSize}\n />\n </div>\n );\n};\n", "//\n// Copyright 2026 DXOS.org\n//\n\nimport React, { useMemo, useRef, useState } from 'react';\n\nimport { Obj } from '@dxos/echo';\nimport { Card, IconButton } from '@dxos/react-ui';\nimport { Menu, createMenuAction } from '@dxos/react-ui-menu';\nimport { JsonHighlighter } from '@dxos/react-ui-syntax-highlighter';\n\nimport { Focus, Mosaic, type MosaicStackTileComponent } from '../components';\n\nexport const DefaultStackTile: MosaicStackTileComponent<Obj.Any> = (props) => {\n const dragHandleRef = useRef<HTMLButtonElement>(null);\n const [open, setOpen] = useState(false);\n const menuItems = useMemo(\n () => [\n createMenuAction('toggle-details', () => setOpen((prev) => !prev), {\n label: open ? 'Hide details' : 'Show details',\n icon: 'ph--circle-dashed--regular',\n }),\n ],\n [open],\n );\n\n return (\n <Menu.Root>\n {/*\n * `Mosaic.Tile` sets `aria-current` from `props.current`, which the\n * Slot composition propagates down to `Card.Root`'s div. That's what\n * makes `dx-current` (an `aria-[current=true]:` utility) actually\n * fire here. See `ui-theme/src/css/components/selected.md`.\n */}\n <Mosaic.Tile {...props} asChild>\n <Focus.Item asChild>\n <Card.Root className='dx-current dx-hover'>\n <Card.Header>\n <Card.DragHandle ref={dragHandleRef} />\n <Card.Title>{Obj.getLabel(props.data) ?? props.data.id}</Card.Title>\n <Card.Block end>\n <Menu.Trigger asChild disabled={!menuItems?.length}>\n <IconButton iconOnly variant='ghost' icon='ph--dots-three-vertical--regular' label='Menu' />\n </Menu.Trigger>\n </Card.Block>\n <Menu.Content items={menuItems} />\n </Card.Header>\n {open && (\n <Card.Row>\n <JsonHighlighter data={props.data} classNames='text-xs' />\n </Card.Row>\n )}\n </Card.Root>\n </Focus.Item>\n </Mosaic.Tile>\n </Menu.Root>\n );\n};\n\nDefaultStackTile.displayName = 'DefaultStackTile';\n"],
5
- "mappings": "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",
6
- "names": ["React", "withMosaic", "Story", "Mosaic", "Root", "Schema", "DXN", "Ref", "Type", "EntityId", "TestItem", "makeObject", "make", "Struct", "name", "String", "description", "optional", "label", "TestColumn", "id", "items", "mutable", "Array", "useControllableState", "React", "Icon", "Popover", "ResizeHandle", "resizeAttributes", "sizeStyle", "DEFAULT_BLOCK_SIZE", "MIN_BLOCK_SIZE", "CardContainer", "children", "role", "icon", "div", "className", "PopoverCardContainer", "IntrinsicCardContainer", "Root", "open", "Trigger", "asChild", "Portal", "Content", "onOpenAutoFocus", "event", "preventDefault", "Viewport", "classNames", "Arrow", "defaultSize", "size", "propSize", "onSizeChange", "setSize", "prop", "defaultProp", "onChange", "style", "side", "fallbackSize", "minSize", "React", "useMemo", "useRef", "useState", "Obj", "Card", "IconButton", "Menu", "createMenuAction", "JsonHighlighter", "DefaultStackTile", "props", "dragHandleRef", "useRef", "open", "setOpen", "useState", "menuItems", "useMemo", "createMenuAction", "prev", "label", "icon", "React", "Menu", "Root", "Mosaic", "Tile", "asChild", "Focus", "Item", "Card", "className", "Header", "DragHandle", "ref", "Title", "Obj", "getLabel", "data", "id", "Block", "end", "Trigger", "disabled", "length", "IconButton", "iconOnly", "variant", "Content", "items", "Row", "JsonHighlighter", "classNames", "displayName"]
7
- }
@@ -1,20 +0,0 @@
1
- import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
2
-
3
- // src/translations.ts
4
- var translationKey = "@dxos/react-ui-mosaic";
5
- var translations = [
6
- {
7
- "en-US": {
8
- [translationKey]: {
9
- "action-menu.label": "Actions",
10
- "add-item.label": "Add item",
11
- "delete-menu.label": "Delete"
12
- }
13
- }
14
- }
15
- ];
16
- export {
17
- translationKey,
18
- translations
19
- };
20
- //# sourceMappingURL=translations.mjs.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/translations.ts"],
4
- "sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { type Resource } from '@dxos/react-ui';\n\nexport const translationKey = '@dxos/react-ui-mosaic';\n\nexport const translations = [\n {\n 'en-US': {\n [translationKey]: {\n 'action-menu.label': 'Actions',\n 'add-item.label': 'Add item',\n 'delete-menu.label': 'Delete',\n },\n },\n },\n] as const satisfies Resource[];\n"],
5
- "mappings": ";;;AAMO,IAAMA,iBAAiB;AAEvB,IAAMC,eAAe;EAC1B;IACE,SAAS;MACP,CAACD,cAAAA,GAAiB;QAChB,qBAAqB;QACrB,kBAAkB;QAClB,qBAAqB;MACvB;IACF;EACF;;",
6
- "names": ["translationKey", "translations"]
7
- }
@@ -1,35 +0,0 @@
1
- import React, { type PropsWithChildren } from 'react';
2
- import { type MosaicData, type MosaicEventHandler, type MosaicTileData } from './types';
3
- type MosaicDraggingSource = {
4
- data: MosaicTileData;
5
- handler?: MosaicEventHandler;
6
- container?: Element;
7
- };
8
- type MosaicDraggingTarget = {
9
- data: MosaicData;
10
- handler?: MosaicEventHandler;
11
- };
12
- type MosaicDraggingState = {
13
- source: MosaicDraggingSource;
14
- target?: MosaicDraggingTarget;
15
- };
16
- type MosaicRootContextValue = {
17
- containers: Record<string, MosaicEventHandler>;
18
- addContainer: (container: MosaicEventHandler) => void;
19
- removeContainer: (id: string) => void;
20
- dragging?: MosaicDraggingState;
21
- };
22
- declare const useMosaicRootContext: (consumerName: string) => MosaicRootContextValue;
23
- type MosaicRootProps = PropsWithChildren<{
24
- asChild?: boolean;
25
- debug?: boolean;
26
- }>;
27
- declare const MosaicRoot: React.ForwardRefExoticComponent<{
28
- asChild?: boolean;
29
- debug?: boolean;
30
- } & {
31
- children?: React.ReactNode | undefined;
32
- } & React.RefAttributes<HTMLDivElement>>;
33
- export { MosaicRoot, useMosaicRootContext };
34
- export type { MosaicDraggingState, MosaicRootProps };
35
- //# sourceMappingURL=Root.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Root.d.ts","sourceRoot":"","sources":["../../../../../src/components/Mosaic/Root.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,EAAE,KAAK,iBAAiB,EAAwD,MAAM,OAAO,CAAC;AAI5G,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,kBAAkB,EAAE,KAAK,cAAc,EAAE,MAAM,SAAS,CAAC;AAMxF,KAAK,oBAAoB,GAAG;IAC1B,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,KAAK,oBAAoB,GAAG;IAC1B,IAAI,EAAE,UAAU,CAAC;IACjB,OAAO,CAAC,EAAE,kBAAkB,CAAC;CAC9B,CAAC;AAEF,KAAK,mBAAmB,GAAG;IACzB,MAAM,EAAE,oBAAoB,CAAC;IAC7B,MAAM,CAAC,EAAE,oBAAoB,CAAC;CAC/B,CAAC;AAEF,KAAK,sBAAsB,GAAG;IAC5B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;IAC/C,YAAY,EAAE,CAAC,SAAS,EAAE,kBAAkB,KAAK,IAAI,CAAC;IACtD,eAAe,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,QAAQ,CAAC,EAAE,mBAAmB,CAAC;CAChC,CAAC;AAEF,QAAA,MAAkC,oBAAoB,kDAAuD,CAAC;AAW9G,KAAK,eAAe,GAAG,iBAAiB,CAAC;IACvC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC,CAAC;AAEH,QAAA,MAAM,UAAU;cAJJ,OAAO;YACT,OAAO;;;wCAgOf,CAAC;AAIH,OAAO,EAAE,UAAU,EAAE,oBAAoB,EAAE,CAAC;AAE5C,YAAY,EAAE,mBAAmB,EAAE,eAAe,EAAE,CAAC"}
@@ -1,86 +0,0 @@
1
- import { type ElementDragPayload } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
2
- export type GetId<TData = any> = (data: TData) => string;
3
- /**
4
- * NOTE: Must implement value equivalence.
5
- */
6
- export type LocationType = string | number;
7
- /**
8
- * Get the source data from the drag payload.
9
- */
10
- export declare const getSourceData: <TData = any, TLocation = any>(source: ElementDragPayload) => MosaicTileData<TData, TLocation> | null;
11
- /**
12
- * Draggable item.
13
- * Tiles may contain arbitrary data (which may not be an ECHO object; e.g., search result).
14
- */
15
- export type MosaicTileData<TData = any, TLocation = any> = {
16
- type: 'tile';
17
- containerId: string;
18
- id: string;
19
- data: TData;
20
- location: TLocation;
21
- bounds?: DOMRect;
22
- };
23
- /**
24
- * Drop target placeholder.
25
- */
26
- export type MosaicPlaceholderData<TLocation = any> = {
27
- type: 'placeholder';
28
- containerId: string;
29
- location: TLocation;
30
- };
31
- /**
32
- * Drop target container.
33
- */
34
- export type MosaicContainerData = {
35
- type: 'container';
36
- id: string;
37
- };
38
- export type MosaicData = MosaicTileData | MosaicPlaceholderData | MosaicContainerData;
39
- export type MosaicTargetData = MosaicTileData | MosaicPlaceholderData;
40
- /**
41
- * Handler implemented by drop containers.
42
- */
43
- export interface MosaicEventHandler<TData = any, TObject = any> {
44
- /**
45
- * Container identifier.
46
- */
47
- id: string;
48
- /**
49
- * Determine if the item can be dropped into this container.
50
- * NOTE: This is continuously called while dragging (doesn't require mouse movement).
51
- */
52
- canDrop?: (props: {
53
- source: MosaicTileData<TData>;
54
- }) => boolean;
55
- /**
56
- * Called during drag for custom visualization.
57
- */
58
- onDrag?: (props: {
59
- source: MosaicTileData<TData>;
60
- position: {
61
- x: number;
62
- y: number;
63
- };
64
- }) => void;
65
- /**
66
- * Insert/rearrange the item at the given location.
67
- */
68
- onDrop?: (props: {
69
- source: MosaicTileData<TData>;
70
- target?: MosaicData;
71
- }) => void;
72
- /**
73
- * Request the object to be dropped.
74
- * This allows the source container to clone/mutate/swap the object before it is dropped.
75
- * If the callback returns true, then the callback may decide to remove the item from the source container,
76
- * completing the transfer.
77
- */
78
- onTake?: (props: {
79
- source: MosaicTileData<TData>;
80
- }, cb: (object: TObject) => Promise<boolean>) => void;
81
- /**
82
- * Dragging ended.
83
- */
84
- onCancel?: () => void;
85
- }
86
- //# sourceMappingURL=types.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../src/components/Mosaic/types.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,mDAAmD,CAAC;AAE5F,MAAM,MAAM,KAAK,CAAC,KAAK,GAAG,GAAG,IAAI,CAAC,IAAI,EAAE,KAAK,KAAK,MAAM,CAAC;AAEzD;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,CAAC;AAE3C;;GAEG;AACH,eAAO,MAAM,aAAa,GAAI,KAAK,GAAG,GAAG,EAAE,SAAS,GAAG,GAAG,UAChD,kBAAkB,KACzB,cAAc,CAAC,KAAK,EAAE,SAAS,CAAC,GAAG,IAErC,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,cAAc,CAAC,KAAK,GAAG,GAAG,EAAE,SAAS,GAAG,GAAG,IAAI;IACzD,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,KAAK,CAAC;IACZ,QAAQ,EAAE,SAAS,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,qBAAqB,CAAC,SAAS,GAAG,GAAG,IAAI;IACnD,IAAI,EAAE,aAAa,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,SAAS,CAAC;CACrB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,WAAW,CAAC;IAClB,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,cAAc,GAAG,qBAAqB,GAAG,mBAAmB,CAAC;AAEtF,MAAM,MAAM,gBAAgB,GAAG,cAAc,GAAG,qBAAqB,CAAC;AAEtE;;GAEG;AACH,MAAM,WAAW,kBAAkB,CAAC,KAAK,GAAG,GAAG,EAAE,OAAO,GAAG,GAAG;IAC5D;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,MAAM,EAAE,cAAc,CAAC,KAAK,CAAC,CAAA;KAAE,KAAK,OAAO,CAAC;IAEhE;;OAEG;IACH,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,MAAM,EAAE,cAAc,CAAC,KAAK,CAAC,CAAC;QAAC,QAAQ,EAAE;YAAE,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,KAAK,IAAI,CAAC;IAEhG;;OAEG;IACH,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,MAAM,EAAE,cAAc,CAAC,KAAK,CAAC,CAAC;QAAC,MAAM,CAAC,EAAE,UAAU,CAAA;KAAE,KAAK,IAAI,CAAC;IAEjF;;;;;OAKG;IACH,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,MAAM,EAAE,cAAc,CAAC,KAAK,CAAC,CAAA;KAAE,EAAE,EAAE,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;IAEvG;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB"}
@@ -1,288 +0,0 @@
1
- //
2
- // Copyright 2025 DXOS.org
3
- //
4
-
5
- import { combine } from '@atlaskit/pragmatic-drag-and-drop/combine';
6
- import { type ElementDragPayload, monitorForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
7
- import { type DragLocationHistory } from '@atlaskit/pragmatic-drag-and-drop/types';
8
- import { useComposedRefs } from '@radix-ui/react-compose-refs';
9
- import { createContext } from '@radix-ui/react-context';
10
- import { Primitive } from '@radix-ui/react-primitive';
11
- import { Slot } from '@radix-ui/react-slot';
12
- import React, { type PropsWithChildren, forwardRef, useCallback, useEffect, useRef, useState } from 'react';
13
-
14
- import { log } from '@dxos/log';
15
-
16
- import { type MosaicData, type MosaicEventHandler, type MosaicTileData } from './types';
17
-
18
- //
19
- // Context
20
- //
21
-
22
- type MosaicDraggingSource = {
23
- data: MosaicTileData;
24
- handler?: MosaicEventHandler;
25
- container?: Element;
26
- };
27
-
28
- type MosaicDraggingTarget = {
29
- data: MosaicData;
30
- handler?: MosaicEventHandler;
31
- };
32
-
33
- type MosaicDraggingState = {
34
- source: MosaicDraggingSource;
35
- target?: MosaicDraggingTarget;
36
- };
37
-
38
- type MosaicRootContextValue = {
39
- containers: Record<string, MosaicEventHandler>;
40
- addContainer: (container: MosaicEventHandler) => void;
41
- removeContainer: (id: string) => void;
42
- dragging?: MosaicDraggingState;
43
- };
44
-
45
- const [MosaicRootContextProvider, useMosaicRootContext] = createContext<MosaicRootContextValue>('MosaicRoot');
46
-
47
- //
48
- // Root
49
- //
50
-
51
- const MOSAIC_ROOT_NAME = 'Mosaic.Root';
52
-
53
- // State attribute: [&:has(>_[data-mosaic-debug=true])]
54
- const MOSAIC_ROOT_DEBUG_ATTR = 'mosaic-debug';
55
-
56
- type MosaicRootProps = PropsWithChildren<{
57
- asChild?: boolean;
58
- debug?: boolean;
59
- }>;
60
-
61
- const MosaicRoot = forwardRef<HTMLDivElement, MosaicRootProps>(({ children, asChild, debug }, forwardedRef) => {
62
- const rootRef = useRef<HTMLDivElement>(null);
63
- const composedRef = useComposedRefs<HTMLDivElement>(rootRef, forwardedRef);
64
- const Comp = asChild ? Slot : Primitive.div;
65
-
66
- const [handlers, setHandlers] = useState<Record<string, MosaicEventHandler>>({});
67
- const [dragging, setDragging] = useState<MosaicDraggingState | undefined>();
68
-
69
- const getSourceHandler = useCallback(
70
- (source: ElementDragPayload): { data: MosaicTileData; handler?: MosaicEventHandler } => {
71
- const data = source.data as MosaicTileData;
72
- return { data, handler: handlers[data.containerId] };
73
- },
74
- [handlers],
75
- );
76
-
77
- const getTargetHandler = useCallback(
78
- (location: DragLocationHistory): { data?: MosaicData; handler?: MosaicEventHandler } => {
79
- for (const target of location.current.dropTargets) {
80
- const data = target.data as MosaicData;
81
- let containerId: string;
82
- switch (data.type) {
83
- case 'tile':
84
- case 'placeholder':
85
- containerId = data.containerId;
86
- break;
87
- case 'container':
88
- containerId = data.id;
89
- break;
90
- }
91
-
92
- const handler = handlers[containerId];
93
- if (handler) {
94
- return { data, handler };
95
- }
96
- }
97
-
98
- return {};
99
- },
100
- [handlers],
101
- );
102
-
103
- useEffect(() => {
104
- const handleChange = ({ source, location }: { source: ElementDragPayload; location: DragLocationHistory }) => {
105
- const { data: sourceData } = getSourceHandler(source);
106
- const { data: targetData, handler } = getTargetHandler(location);
107
- setDragging((dragging) => {
108
- dragging?.target?.handler?.onCancel?.();
109
- return {
110
- source: {
111
- data: sourceData,
112
- handler: handlers[sourceData.containerId],
113
- // TODO(burdon): Check id matches.
114
- container: location.initial.dropTargets.find((target) => target.data.type === 'container')?.element,
115
- },
116
- target: targetData && {
117
- data: targetData,
118
- handler,
119
- },
120
- };
121
- });
122
- };
123
-
124
- const handleCancel = () => {
125
- setDragging((dragging) => {
126
- requestAnimationFrame(() => {
127
- dragging?.target?.handler?.onCancel?.();
128
- dragging?.source?.container?.dispatchEvent(new CustomEvent('dnd:cancel', { bubbles: true }));
129
- });
130
-
131
- return undefined;
132
- });
133
- };
134
-
135
- let noTargetTimeout: NodeJS.Timeout;
136
-
137
- // Main controller.
138
- return combine(
139
- monitorForElements({
140
- // Only monitor Mosaic tile drags; other pragmatic-dnd sources under this root are not ours to handle.
141
- canMonitor: ({ source }) => source.data.type === 'tile',
142
- /**
143
- * Dragging started within any container.
144
- */
145
- onDragStart: ({ source, location }) => {
146
- log('Root.onDragStart', {
147
- source: source.data,
148
- location: location.current.dropTargets.map((target) => target.data),
149
- });
150
-
151
- handleChange({ source, location });
152
- },
153
-
154
- /**
155
- * Dragging entered a new container.
156
- */
157
- onDropTargetChange: ({ source, location }) => {
158
- clearTimeout(noTargetTimeout);
159
- log('Root.onDropTargetChange', {
160
- source: source.data,
161
- location: location.current.dropTargets.map((target) => target.data),
162
- });
163
-
164
- // Stop dragging if there are no drop targets (or we are cancelling).
165
- if (location.current.dropTargets.length === 0) {
166
- noTargetTimeout = setTimeout(() => setDragging(undefined), 1_000);
167
- } else {
168
- handleChange({ source, location });
169
- }
170
- },
171
-
172
- /**
173
- * Dragging within any container.
174
- */
175
- onDrag: ({ source, location }) => {
176
- const { data } = getSourceHandler(source);
177
- const { handler } = getTargetHandler(location);
178
- if (handler) {
179
- const { clientX: x, clientY: y } = location.current.input;
180
- handler.onDrag?.({ source: data, position: { x, y } });
181
- }
182
- },
183
-
184
- /**
185
- * Dragging ended.
186
- */
187
- onDrop: ({ source, location }) => {
188
- log.info('Root.onDrop', {
189
- source: source.data,
190
- location: location.current.dropTargets.map((target) => target.data),
191
- });
192
-
193
- // Get the source container.
194
- const { data: sourceData, handler: sourceHandler } = getSourceHandler(source);
195
- if (!sourceHandler) {
196
- log.warn('invalid source', {
197
- source: sourceData,
198
- handlers: Object.keys(handlers),
199
- });
200
- return;
201
- }
202
-
203
- // NOTE: When dragging is cancelled (e.g., user presses ESC) onDrop is only called after a subsequent event.
204
- // NOTE: pDND blocks ESC event propagation while dragging.
205
- // - ESC only flips internal state.
206
- // - Completion happens on the next processed input event.
207
- // - This avoids reentrancy and keeps pointer/keyboard behavior consistent.
208
- // - We set dragging to undefined in onDropTargetChange after a delay if there are no drop targets.
209
- try {
210
- if (location.current.dropTargets.length === 0) {
211
- log.info('cancelled');
212
- } else {
213
- // Get the target container.
214
- const { data: targetData, handler: targetHandler } = getTargetHandler(location);
215
- if (!targetHandler) {
216
- log.warn('invalid target', {
217
- source: sourceData,
218
- location,
219
- handlers: Object.keys(handlers),
220
- });
221
- return;
222
- }
223
-
224
- // TODO(burdon): Check object doesn't already exist in the collection.
225
- if (sourceHandler === targetHandler) {
226
- targetHandler.onDrop?.({
227
- source: sourceData,
228
- target: targetData,
229
- });
230
- } else {
231
- if (!sourceHandler.onTake) {
232
- log.warn('invalid source', { source: sourceData });
233
- return;
234
- }
235
-
236
- sourceHandler.onTake?.({ source: sourceData }, async (object) => {
237
- targetHandler.onDrop?.({
238
- source: { ...sourceData, data: object },
239
- target: targetData,
240
- });
241
-
242
- return true;
243
- });
244
- }
245
- }
246
- } finally {
247
- handleCancel();
248
- }
249
- },
250
- }),
251
- );
252
- }, [handlers, getSourceHandler, getTargetHandler]);
253
-
254
- return (
255
- <MosaicRootContextProvider
256
- containers={handlers}
257
- addContainer={(container) =>
258
- setHandlers((containers) => ({
259
- ...containers,
260
- [container.id]: container,
261
- }))
262
- }
263
- removeContainer={(id) =>
264
- setHandlers((containers) => {
265
- delete containers[id];
266
- return { ...containers };
267
- })
268
- }
269
- dragging={dragging}
270
- >
271
- <Comp
272
- className='contents group'
273
- {...{
274
- [`data-${MOSAIC_ROOT_DEBUG_ATTR}`]: debug,
275
- }}
276
- ref={composedRef}
277
- >
278
- {children}
279
- </Comp>
280
- </MosaicRootContextProvider>
281
- );
282
- });
283
-
284
- MosaicRoot.displayName = MOSAIC_ROOT_NAME;
285
-
286
- export { MosaicRoot, useMosaicRootContext };
287
-
288
- export type { MosaicDraggingState, MosaicRootProps };