@dxos/react-ui-menu 0.8.4-main.e098934 → 0.8.4-main.e8ec1fe
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/browser/index.mjs +22 -35
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +22 -35
- package/dist/lib/node-esm/index.mjs.map +3 -3
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/components/MenuContext.d.ts +3 -1
- package/dist/types/src/components/MenuContext.d.ts.map +1 -1
- package/dist/types/src/components/ToolbarMenu.d.ts +1 -1
- package/dist/types/src/components/ToolbarMenu.d.ts.map +1 -1
- package/dist/types/src/components/ToolbarMenu.stories.d.ts +1 -2
- package/dist/types/src/components/ToolbarMenu.stories.d.ts.map +1 -1
- package/dist/types/src/hooks/useMenuActions.d.ts +3 -2
- package/dist/types/src/hooks/useMenuActions.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -1
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/testing/generator.d.ts +2 -2
- package/dist/types/src/testing/generator.d.ts.map +1 -1
- package/dist/types/src/util.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +25 -25
- package/src/components/MenuContext.tsx +6 -2
- package/src/components/ToolbarMenu.stories.tsx +2 -4
- package/src/components/ToolbarMenu.tsx +12 -7
- package/src/hooks/useMenuActions.ts +12 -5
- package/src/index.ts +1 -1
- package/src/testing/generator.ts +2 -2
- package/src/util.ts +6 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/react-ui-menu",
|
|
3
|
-
"version": "0.8.4-main.
|
|
3
|
+
"version": "0.8.4-main.e8ec1fe",
|
|
4
4
|
"description": "Components for facilitating reactive and consistent menus.",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
@@ -26,38 +26,38 @@
|
|
|
26
26
|
],
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"@preact-signals/safe-react": "^0.9.0",
|
|
29
|
-
"@preact/signals-react": "^3.
|
|
29
|
+
"@preact/signals-react": "^3.3.0",
|
|
30
30
|
"@radix-ui/react-context": "1.1.1",
|
|
31
31
|
"@radix-ui/react-use-controllable-state": "1.1.0",
|
|
32
|
-
"@dxos/app-graph": "0.8.4-main.
|
|
33
|
-
"@dxos/invariant": "0.8.4-main.
|
|
34
|
-
"@dxos/keyboard": "0.8.4-main.
|
|
35
|
-
"@dxos/react-ui-attention": "0.8.4-main.
|
|
36
|
-
"@dxos/util": "0.8.4-main.
|
|
32
|
+
"@dxos/app-graph": "0.8.4-main.e8ec1fe",
|
|
33
|
+
"@dxos/invariant": "0.8.4-main.e8ec1fe",
|
|
34
|
+
"@dxos/keyboard": "0.8.4-main.e8ec1fe",
|
|
35
|
+
"@dxos/react-ui-attention": "0.8.4-main.e8ec1fe",
|
|
36
|
+
"@dxos/util": "0.8.4-main.e8ec1fe"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"@effect-
|
|
40
|
-
"@effect/platform": "0.
|
|
41
|
-
"@types/react": "~
|
|
42
|
-
"@types/react-dom": "~
|
|
43
|
-
"effect": "3.
|
|
44
|
-
"react": "~
|
|
45
|
-
"react-dom": "~
|
|
46
|
-
"vite": "7.1.
|
|
47
|
-
"@dxos/live-object": "0.8.4-main.
|
|
48
|
-
"@dxos/
|
|
49
|
-
"@dxos/react-ui": "0.8.4-main.
|
|
50
|
-
"@dxos/
|
|
51
|
-
"@dxos/storybook-utils": "0.8.4-main.
|
|
39
|
+
"@effect-atom/atom-react": "^0.3.4",
|
|
40
|
+
"@effect/platform": "0.92.1",
|
|
41
|
+
"@types/react": "~19.2.2",
|
|
42
|
+
"@types/react-dom": "~19.2.2",
|
|
43
|
+
"effect": "3.18.3",
|
|
44
|
+
"react": "~19.2.0",
|
|
45
|
+
"react-dom": "~19.2.0",
|
|
46
|
+
"vite": "7.1.9",
|
|
47
|
+
"@dxos/live-object": "0.8.4-main.e8ec1fe",
|
|
48
|
+
"@dxos/react-ui": "0.8.4-main.e8ec1fe",
|
|
49
|
+
"@dxos/react-ui-theme": "0.8.4-main.e8ec1fe",
|
|
50
|
+
"@dxos/random": "0.8.4-main.e8ec1fe",
|
|
51
|
+
"@dxos/storybook-utils": "0.8.4-main.e8ec1fe"
|
|
52
52
|
},
|
|
53
53
|
"peerDependencies": {
|
|
54
|
-
"@effect-
|
|
54
|
+
"@effect-atom/atom-react": "^0.3.4",
|
|
55
55
|
"@effect/platform": "^0.80.12",
|
|
56
56
|
"effect": "^3.13.3",
|
|
57
|
-
"react": "
|
|
58
|
-
"react-dom": "
|
|
59
|
-
"@dxos/react-ui": "0.8.4-main.
|
|
60
|
-
"@dxos/react-ui-theme": "0.8.4-main.
|
|
57
|
+
"react": "^19.0.0",
|
|
58
|
+
"react-dom": "^19.0.0",
|
|
59
|
+
"@dxos/react-ui": "0.8.4-main.e8ec1fe",
|
|
60
|
+
"@dxos/react-ui-theme": "0.8.4-main.e8ec1fe"
|
|
61
61
|
},
|
|
62
62
|
"publishConfig": {
|
|
63
63
|
"access": "public"
|
|
@@ -9,7 +9,7 @@ import { type MenuContextValue, type MenuItem, type MenuItemGroup } from '../typ
|
|
|
9
9
|
|
|
10
10
|
export type MenuScopedProps<P> = P & { __menuScope?: Scope };
|
|
11
11
|
|
|
12
|
-
const MENU_NAME = '
|
|
12
|
+
const MENU_NAME = 'Menu';
|
|
13
13
|
|
|
14
14
|
const [createMenuContext, createMenuScope] = createContextScope(MENU_NAME, []);
|
|
15
15
|
|
|
@@ -22,12 +22,14 @@ export const menuContextDefaults: MenuContextValue = {
|
|
|
22
22
|
|
|
23
23
|
const useMenuScope = createMenuScope();
|
|
24
24
|
|
|
25
|
+
type MenuProviderProps = PropsWithChildren<Partial<MenuContextValue>>;
|
|
26
|
+
|
|
25
27
|
const MenuProvider = ({
|
|
26
28
|
children,
|
|
27
29
|
useGroupItems = menuContextDefaults.useGroupItems,
|
|
28
30
|
iconSize = menuContextDefaults.iconSize,
|
|
29
31
|
attendableId,
|
|
30
|
-
}:
|
|
32
|
+
}: MenuProviderProps) => {
|
|
31
33
|
const { scope } = useMenuScope(undefined);
|
|
32
34
|
return (
|
|
33
35
|
<MenuContextProvider useGroupItems={useGroupItems} iconSize={iconSize} attendableId={attendableId} scope={scope}>
|
|
@@ -48,3 +50,5 @@ export const useMenuItems = (
|
|
|
48
50
|
};
|
|
49
51
|
|
|
50
52
|
export { useMenu, createMenuScope, MenuProvider };
|
|
53
|
+
|
|
54
|
+
export type { MenuProviderProps };
|
|
@@ -2,14 +2,12 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import '@dxos-theme';
|
|
6
|
-
|
|
7
5
|
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
8
6
|
import React, { useCallback, useMemo } from 'react';
|
|
9
7
|
|
|
10
8
|
import { faker } from '@dxos/random';
|
|
11
9
|
import { IconButton } from '@dxos/react-ui';
|
|
12
|
-
import { withTheme } from '@dxos/
|
|
10
|
+
import { withTheme } from '@dxos/react-ui/testing';
|
|
13
11
|
|
|
14
12
|
import { MenuProvider, DropdownMenu as NaturalDropdownMenu, ToolbarMenu } from '../components';
|
|
15
13
|
import { useMenuActions } from '../hooks';
|
|
@@ -42,7 +40,7 @@ export const DropdownMenu: Story = {
|
|
|
42
40
|
<MenuProvider useGroupItems={resolveGroupItems}>
|
|
43
41
|
<NaturalDropdownMenu.Root>
|
|
44
42
|
<NaturalDropdownMenu.Trigger asChild>
|
|
45
|
-
<IconButton icon='ph--list-checks--regular'
|
|
43
|
+
<IconButton icon='ph--list-checks--regular' label='Options' />
|
|
46
44
|
</NaturalDropdownMenu.Trigger>
|
|
47
45
|
</NaturalDropdownMenu.Root>
|
|
48
46
|
</MenuProvider>
|
|
@@ -6,7 +6,7 @@ import React, { Fragment, useCallback } from 'react';
|
|
|
6
6
|
|
|
7
7
|
import { Icon, Toolbar as NaturalToolbar, type ToolbarRootProps, useTranslation } from '@dxos/react-ui';
|
|
8
8
|
import { useAttention } from '@dxos/react-ui-attention';
|
|
9
|
-
import { mx, textBlockWidth, toolbarLayout } from '@dxos/react-ui-theme';
|
|
9
|
+
import { mx, textBlockWidth, toolbarInactive, toolbarLayout } from '@dxos/react-ui-theme';
|
|
10
10
|
|
|
11
11
|
import { translationKey } from '../translations';
|
|
12
12
|
import {
|
|
@@ -55,13 +55,15 @@ export type ToolbarMenuActionProps = {
|
|
|
55
55
|
const ActionToolbarItem = ({ action, __menuScope }: MenuScopedProps<{ action: MenuAction }>) => {
|
|
56
56
|
const { iconSize } = useMenu('ActionToolbarItem', __menuScope);
|
|
57
57
|
const { t } = useTranslation(translationKey);
|
|
58
|
-
|
|
58
|
+
|
|
59
59
|
const { icon, iconOnly = true, disabled, testId, hidden, classNames } = action.properties;
|
|
60
60
|
const Root = icon ? NaturalToolbar.IconButton : NaturalToolbar.Button;
|
|
61
61
|
const rootProps = icon
|
|
62
62
|
? { icon, size: iconSize, iconOnly, label: actionLabel(action, t) }
|
|
63
63
|
: { children: <ActionLabel action={action} /> };
|
|
64
64
|
|
|
65
|
+
const handleClick = useCallback(() => action.data?.(), [action]);
|
|
66
|
+
|
|
65
67
|
return hidden ? null : (
|
|
66
68
|
<Root
|
|
67
69
|
key={action.id}
|
|
@@ -158,23 +160,26 @@ const ToggleGroupToolbarItem = ({
|
|
|
158
160
|
);
|
|
159
161
|
};
|
|
160
162
|
|
|
163
|
+
// TODO(burdon): Reconcile with react-ui/Toolbar (incl. textBlockWidth)
|
|
161
164
|
export const ToolbarMenu = ({
|
|
162
165
|
__menuScope,
|
|
163
166
|
classNames,
|
|
164
|
-
textBlockWidth:
|
|
167
|
+
textBlockWidth: textBlockWidthParam,
|
|
165
168
|
...props
|
|
166
169
|
}: MenuScopedProps<ToolbarMenuProps>) => {
|
|
167
170
|
const items = useMenuItems(undefined, undefined, 'ToolbarMenu', __menuScope);
|
|
168
171
|
const { attendableId } = useMenu('ToolbarMenu', __menuScope);
|
|
169
172
|
const { hasAttention } = useAttention(attendableId);
|
|
170
|
-
const InnerRoot =
|
|
171
|
-
const innerRootProps =
|
|
173
|
+
const InnerRoot = textBlockWidthParam ? 'div' : Fragment;
|
|
174
|
+
const innerRootProps = textBlockWidthParam
|
|
175
|
+
? { role: 'none', className: mx(textBlockWidth, toolbarLayout, 'bs-full') }
|
|
176
|
+
: {};
|
|
172
177
|
|
|
173
178
|
return (
|
|
174
179
|
<NaturalToolbar.Root
|
|
175
180
|
{...props}
|
|
176
|
-
|
|
177
|
-
|
|
181
|
+
classNames={[attendableId && !hasAttention && toolbarInactive, classNames]}
|
|
182
|
+
layoutManaged={textBlockWidthParam}
|
|
178
183
|
>
|
|
179
184
|
<InnerRoot {...innerRootProps}>
|
|
180
185
|
{items?.map((item: MenuItem, i: number) => (
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { type Atom, RegistryContext, useAtomValue } from '@effect-atom/atom-react';
|
|
6
6
|
import { useCallback, useContext, useEffect, useState } from 'react';
|
|
7
7
|
|
|
8
8
|
import { type Edge, type Edges, Graph, type Node, type NodeArg, ROOT_ID } from '@dxos/app-graph';
|
|
@@ -38,11 +38,18 @@ const edgesArrayToRecord = (edges: Edge[]): Record<string, Edges> => {
|
|
|
38
38
|
|
|
39
39
|
export type ActionGraphNodes = NodeArg<any>[];
|
|
40
40
|
export type ActionGraphEdges = Edge[];
|
|
41
|
-
export type ActionGraphProps = {
|
|
41
|
+
export type ActionGraphProps = {
|
|
42
|
+
nodes: ActionGraphNodes;
|
|
43
|
+
edges: ActionGraphEdges;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export type MenuActions = {
|
|
47
|
+
useGroupItems: (sourceNode?: MenuItemGroup) => MenuItem[];
|
|
48
|
+
};
|
|
42
49
|
|
|
43
|
-
export const useMenuActions = (props:
|
|
50
|
+
export const useMenuActions = (props: Atom.Atom<ActionGraphProps>): MenuActions => {
|
|
44
51
|
const registry = useContext(RegistryContext);
|
|
45
|
-
const menuGraphProps =
|
|
52
|
+
const menuGraphProps = useAtomValue(props);
|
|
46
53
|
|
|
47
54
|
const [graph] = useState(
|
|
48
55
|
new Graph({
|
|
@@ -59,7 +66,7 @@ export const useMenuActions = (props: Rx.Rx<ActionGraphProps>) => {
|
|
|
59
66
|
|
|
60
67
|
const useGroupItems = useCallback(
|
|
61
68
|
(sourceNode?: MenuItemGroup) => {
|
|
62
|
-
const items =
|
|
69
|
+
const items = useAtomValue(graph.connections(sourceNode?.id || ROOT_ID)) as MenuItem[];
|
|
63
70
|
return items;
|
|
64
71
|
},
|
|
65
72
|
[graph],
|
package/src/index.ts
CHANGED
package/src/testing/generator.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { Atom } from '@effect-atom/atom-react';
|
|
6
6
|
import { useEffect } from 'react';
|
|
7
7
|
|
|
8
8
|
import {
|
|
@@ -66,7 +66,7 @@ export const createActions = (params?: CreateActionsParams) => {
|
|
|
66
66
|
);
|
|
67
67
|
};
|
|
68
68
|
|
|
69
|
-
export const createNestedActions =
|
|
69
|
+
export const createNestedActions = Atom.make(() => {
|
|
70
70
|
const result: ActionGraphProps = { edges: [], nodes: [] };
|
|
71
71
|
const actionGroups = createActions({ type: ACTION_GROUP_TYPE });
|
|
72
72
|
actionGroups.forEach((group) => {
|
package/src/util.ts
CHANGED
|
@@ -55,7 +55,12 @@ export const createGapSeparator = (id: string = 'gap', source: string = 'root')
|
|
|
55
55
|
data: undefined as never,
|
|
56
56
|
} satisfies MenuSeparator,
|
|
57
57
|
],
|
|
58
|
-
edges: [
|
|
58
|
+
edges: [
|
|
59
|
+
{
|
|
60
|
+
source,
|
|
61
|
+
target: id,
|
|
62
|
+
},
|
|
63
|
+
],
|
|
59
64
|
});
|
|
60
65
|
|
|
61
66
|
export const createLineSeparator = (id: string = 'line', source: string = 'root') => ({
|