@dxos/react-ui-menu 0.8.4-main.72ec0f3 → 0.8.4-main.7996785055
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 +537 -387
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +537 -387
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/builder.d.ts +7 -1
- package/dist/types/src/builder.d.ts.map +1 -1
- package/dist/types/src/components/ActionLabel.d.ts +3 -3
- package/dist/types/src/components/ActionLabel.d.ts.map +1 -1
- package/dist/types/src/components/DropdownMenu.d.ts +4 -2
- package/dist/types/src/components/DropdownMenu.d.ts.map +1 -1
- package/dist/types/src/components/Menu.d.ts +54 -0
- package/dist/types/src/components/Menu.d.ts.map +1 -0
- package/dist/types/src/components/Menu.stories.d.ts +21 -0
- package/dist/types/src/components/Menu.stories.d.ts.map +1 -0
- package/dist/types/src/components/Menu.test.d.ts +2 -0
- package/dist/types/src/components/Menu.test.d.ts.map +1 -0
- package/dist/types/src/components/ToolbarMenu.d.ts +11 -6
- package/dist/types/src/components/ToolbarMenu.d.ts.map +1 -1
- package/dist/types/src/components/ToolbarMenu.stories.d.ts +8 -2
- package/dist/types/src/components/ToolbarMenu.stories.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +1 -3
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useMenuActions.d.ts +5 -5
- package/dist/types/src/hooks/useMenuActions.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +0 -1
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/testing/generator.d.ts +19 -13
- package/dist/types/src/testing/generator.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +2 -2
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types.d.ts +37 -26
- package/dist/types/src/types.d.ts.map +1 -1
- package/dist/types/src/util.d.ts +14 -5
- package/dist/types/src/util.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +35 -29
- package/src/builder.ts +36 -9
- package/src/components/ActionLabel.tsx +5 -5
- package/src/components/DropdownMenu.tsx +12 -5
- package/src/components/Menu.stories.tsx +265 -0
- package/src/components/Menu.test.tsx +448 -0
- package/src/components/Menu.tsx +349 -0
- package/src/components/ToolbarMenu.stories.tsx +34 -25
- package/src/components/ToolbarMenu.tsx +136 -91
- package/src/components/index.ts +1 -3
- package/src/hooks/useMenuActions.ts +21 -51
- package/src/index.ts +0 -2
- package/src/testing/generator.ts +72 -62
- package/src/translations.ts +1 -1
- package/src/types.ts +39 -27
- package/src/util.ts +28 -14
- package/dist/types/src/components/MenuContext.d.ts +0 -15
- package/dist/types/src/components/MenuContext.d.ts.map +0 -1
- package/src/components/MenuContext.tsx +0 -54
|
@@ -1,48 +1,39 @@
|
|
|
1
1
|
import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
|
|
2
2
|
|
|
3
|
-
// src/
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import
|
|
10
|
-
import { Icon, DropdownMenu as NaturalDropdownMenu } from "@dxos/react-ui";
|
|
11
|
-
|
|
12
|
-
// src/components/ActionLabel.tsx
|
|
13
|
-
import { useSignals as _useSignals } from "@preact-signals/safe-react/tracking";
|
|
14
|
-
import React from "react";
|
|
15
|
-
import { keySymbols } from "@dxos/keyboard";
|
|
16
|
-
import { toLocalizedString, useTranslation } from "@dxos/react-ui";
|
|
17
|
-
import { descriptionText, mx } from "@dxos/react-ui-theme";
|
|
18
|
-
|
|
19
|
-
// src/translations.ts
|
|
20
|
-
var translationKey = "react-ui-menu";
|
|
21
|
-
var translations = [
|
|
22
|
-
{
|
|
23
|
-
"en-US": {
|
|
24
|
-
[translationKey]: {}
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
];
|
|
3
|
+
// src/components/Menu.tsx
|
|
4
|
+
import { Atom, RegistryContext, useAtomValue } from "@effect-atom/atom-react";
|
|
5
|
+
import { createContextScope } from "@radix-ui/react-context";
|
|
6
|
+
import { useControllableState as useControllableState2 } from "@radix-ui/react-use-controllable-state";
|
|
7
|
+
import React4, { createContext, useCallback as useCallback3, useContext, useMemo } from "react";
|
|
8
|
+
import { log } from "@dxos/log";
|
|
9
|
+
import { Icon as Icon3, DropdownMenu as NaturalDropdownMenu2 } from "@dxos/react-ui";
|
|
28
10
|
|
|
29
11
|
// src/util.ts
|
|
30
|
-
import
|
|
12
|
+
import * as Effect from "effect/Effect";
|
|
13
|
+
import { Node } from "@dxos/app-graph";
|
|
14
|
+
import { runAndForwardErrors } from "@dxos/effect";
|
|
31
15
|
import { getHostPlatform } from "@dxos/util";
|
|
16
|
+
var executeMenuAction = async (action, params = {}) => {
|
|
17
|
+
let effect = action.data(params);
|
|
18
|
+
if (action._actionContext) {
|
|
19
|
+
effect = effect.pipe(Effect.provide(action._actionContext));
|
|
20
|
+
}
|
|
21
|
+
await runAndForwardErrors(effect);
|
|
22
|
+
};
|
|
32
23
|
var getShortcut = (action) => {
|
|
33
24
|
return typeof action.properties?.keyBinding === "string" ? action.properties.keyBinding : action.properties?.keyBinding?.[getHostPlatform()];
|
|
34
25
|
};
|
|
35
26
|
var createMenuAction = (id, invoke, properties) => ({
|
|
36
27
|
id,
|
|
37
|
-
type:
|
|
28
|
+
type: Node.ActionType,
|
|
38
29
|
properties,
|
|
39
|
-
data: invoke
|
|
30
|
+
data: () => Effect.sync(invoke)
|
|
40
31
|
});
|
|
41
32
|
var createMenuItemGroup = (id, properties) => ({
|
|
42
33
|
id,
|
|
43
|
-
type:
|
|
34
|
+
type: Node.ActionGroupType,
|
|
44
35
|
properties,
|
|
45
|
-
data: actionGroupSymbol
|
|
36
|
+
data: Node.actionGroupSymbol
|
|
46
37
|
});
|
|
47
38
|
var createGapSeparator = (id = "gap", source = "root") => ({
|
|
48
39
|
nodes: [
|
|
@@ -58,7 +49,8 @@ var createGapSeparator = (id = "gap", source = "root") => ({
|
|
|
58
49
|
edges: [
|
|
59
50
|
{
|
|
60
51
|
source,
|
|
61
|
-
target: id
|
|
52
|
+
target: id,
|
|
53
|
+
relation: "child"
|
|
62
54
|
}
|
|
63
55
|
]
|
|
64
56
|
});
|
|
@@ -76,128 +68,119 @@ var createLineSeparator = (id = "line", source = "root") => ({
|
|
|
76
68
|
edges: [
|
|
77
69
|
{
|
|
78
70
|
source,
|
|
79
|
-
target: id
|
|
71
|
+
target: id,
|
|
72
|
+
relation: "child"
|
|
80
73
|
}
|
|
81
74
|
]
|
|
82
75
|
});
|
|
83
76
|
|
|
84
77
|
// src/components/ActionLabel.tsx
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
78
|
+
import React from "react";
|
|
79
|
+
import { keySymbols } from "@dxos/keyboard";
|
|
80
|
+
import { toLocalizedString, useTranslation } from "@dxos/react-ui";
|
|
81
|
+
import { mx } from "@dxos/ui-theme";
|
|
82
|
+
|
|
83
|
+
// src/translations.ts
|
|
84
|
+
var translationKey = "@dxos/react-ui-menu";
|
|
85
|
+
var translations = [
|
|
86
|
+
{
|
|
87
|
+
"en-US": {
|
|
88
|
+
[translationKey]: {}
|
|
89
|
+
}
|
|
97
90
|
}
|
|
91
|
+
];
|
|
92
|
+
|
|
93
|
+
// src/components/ActionLabel.tsx
|
|
94
|
+
var ActionLabel = ({ action }) => {
|
|
95
|
+
const { t } = useTranslation(translationKey);
|
|
96
|
+
const shortcut = getShortcut(action);
|
|
97
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("span", {
|
|
98
|
+
className: "grow truncate"
|
|
99
|
+
}, toLocalizedString(action.properties.label, t)), shortcut && /* @__PURE__ */ React.createElement("span", {
|
|
100
|
+
className: mx("shrink-0", "text-description")
|
|
101
|
+
}, keySymbols(shortcut).join("")));
|
|
98
102
|
};
|
|
99
103
|
var actionLabel = (action, t) => {
|
|
100
104
|
const shortcut = getShortcut(action);
|
|
101
105
|
return `${toLocalizedString(action.properties.label, t)}${shortcut ? ` (${keySymbols(shortcut).join("")})` : ""}`;
|
|
102
106
|
};
|
|
103
107
|
|
|
104
|
-
// src/components/
|
|
105
|
-
import {
|
|
106
|
-
import {
|
|
107
|
-
import
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
var useMenuScope = createMenuScope();
|
|
116
|
-
var MenuProvider = ({ children, useGroupItems = menuContextDefaults.useGroupItems, iconSize = menuContextDefaults.iconSize, attendableId }) => {
|
|
117
|
-
var _effect = _useSignals2();
|
|
118
|
-
try {
|
|
119
|
-
const { scope } = useMenuScope(void 0);
|
|
120
|
-
return /* @__PURE__ */ React2.createElement(MenuContextProvider, {
|
|
121
|
-
useGroupItems,
|
|
122
|
-
iconSize,
|
|
123
|
-
attendableId,
|
|
124
|
-
scope
|
|
125
|
-
}, children);
|
|
126
|
-
} finally {
|
|
127
|
-
_effect.f();
|
|
128
|
-
}
|
|
129
|
-
};
|
|
130
|
-
var useMenuItems = (group, propsItems, consumerName = "useMenuItemConsumer", __menuScope) => {
|
|
131
|
-
const { useGroupItems } = useMenu(consumerName, __menuScope);
|
|
132
|
-
const groupItems = useGroupItems(group);
|
|
133
|
-
return useMemo(() => propsItems ?? groupItems ?? void 0, [
|
|
134
|
-
propsItems,
|
|
135
|
-
groupItems
|
|
136
|
-
]);
|
|
137
|
-
};
|
|
108
|
+
// src/components/ToolbarMenu.tsx
|
|
109
|
+
import React3, { useCallback as useCallback2 } from "react";
|
|
110
|
+
import { Icon as Icon2, Toolbar as NaturalToolbar, useTranslation as useTranslation2 } from "@dxos/react-ui";
|
|
111
|
+
import { useAttention } from "@dxos/react-ui-attention";
|
|
112
|
+
import { composable, composableProps } from "@dxos/ui-theme";
|
|
113
|
+
|
|
114
|
+
// src/types.ts
|
|
115
|
+
import { Node as Node2 } from "@dxos/app-graph";
|
|
116
|
+
var MenuSeparatorType = "@dxos/react-ui-toolbar/separator";
|
|
117
|
+
var isSeparator = (node) => node.type === MenuSeparatorType;
|
|
118
|
+
var isMenuGroup = (node) => node.type === Node2.ActionGroupType;
|
|
138
119
|
|
|
139
120
|
// src/components/DropdownMenu.tsx
|
|
121
|
+
import { useControllableState } from "@radix-ui/react-use-controllable-state";
|
|
122
|
+
import React2, { useCallback } from "react";
|
|
123
|
+
import { Icon, DropdownMenu as NaturalDropdownMenu } from "@dxos/react-ui";
|
|
140
124
|
var DropdownMenuItem = ({ item, onClick, __menuScope }) => {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
action
|
|
161
|
-
}));
|
|
162
|
-
} finally {
|
|
163
|
-
_effect.f();
|
|
164
|
-
}
|
|
125
|
+
const action = item;
|
|
126
|
+
const handleClick = useCallback((event) => onClick(action, event), [
|
|
127
|
+
action,
|
|
128
|
+
onClick
|
|
129
|
+
]);
|
|
130
|
+
const { iconSize } = useMenuScoped("DropdownMenuItem", __menuScope);
|
|
131
|
+
return /* @__PURE__ */ React2.createElement(NaturalDropdownMenu.Item, {
|
|
132
|
+
onClick: handleClick,
|
|
133
|
+
classNames: "gap-2",
|
|
134
|
+
disabled: action.properties?.disabled,
|
|
135
|
+
...action.properties?.testId && {
|
|
136
|
+
"data-testid": action.properties.testId
|
|
137
|
+
}
|
|
138
|
+
}, action.properties?.icon && /* @__PURE__ */ React2.createElement(Icon, {
|
|
139
|
+
icon: action.properties.icon,
|
|
140
|
+
size: iconSize
|
|
141
|
+
}), /* @__PURE__ */ React2.createElement(ActionLabel, {
|
|
142
|
+
action
|
|
143
|
+
}));
|
|
165
144
|
};
|
|
166
145
|
var DropdownMenuRoot = ({ items: propsItems, group, open, defaultOpen, onOpenChange, caller, children, __menuScope, ...naturalProps }) => {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
146
|
+
const [optionsMenuOpen, setOptionsMenuOpen] = useControllableState({
|
|
147
|
+
prop: open,
|
|
148
|
+
defaultProp: defaultOpen,
|
|
149
|
+
onChange: onOpenChange
|
|
150
|
+
});
|
|
151
|
+
const { onAction } = useMenuScoped("DropdownMenuRoot", __menuScope);
|
|
152
|
+
const handleActionClick = useCallback((action, event) => {
|
|
153
|
+
if (action.properties?.disabled) {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
event.stopPropagation();
|
|
157
|
+
setOptionsMenuOpen(false);
|
|
158
|
+
if (onAction) {
|
|
159
|
+
onAction(action, {
|
|
181
160
|
parent: group,
|
|
182
161
|
caller
|
|
183
162
|
});
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
}
|
|
163
|
+
} else {
|
|
164
|
+
void executeMenuAction(action, {
|
|
165
|
+
parent: group,
|
|
166
|
+
caller
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
}, [
|
|
170
|
+
group,
|
|
171
|
+
caller,
|
|
172
|
+
onAction
|
|
173
|
+
]);
|
|
174
|
+
const items = useMenuItems(group, propsItems);
|
|
175
|
+
return /* @__PURE__ */ React2.createElement(NaturalDropdownMenu.Root, {
|
|
176
|
+
open: optionsMenuOpen,
|
|
177
|
+
onOpenChange: setOptionsMenuOpen,
|
|
178
|
+
...naturalProps
|
|
179
|
+
}, children, /* @__PURE__ */ React2.createElement(NaturalDropdownMenu.Portal, null, /* @__PURE__ */ React2.createElement(NaturalDropdownMenu.Content, null, /* @__PURE__ */ React2.createElement(NaturalDropdownMenu.Viewport, null, items?.map((item) => /* @__PURE__ */ React2.createElement(DropdownMenuItem, {
|
|
180
|
+
key: item.id,
|
|
181
|
+
item,
|
|
182
|
+
onClick: handleActionClick
|
|
183
|
+
}))), /* @__PURE__ */ React2.createElement(NaturalDropdownMenu.Arrow, null))));
|
|
201
184
|
};
|
|
202
185
|
var DropdownMenu = {
|
|
203
186
|
Root: DropdownMenuRoot,
|
|
@@ -206,290 +189,430 @@ var DropdownMenu = {
|
|
|
206
189
|
};
|
|
207
190
|
|
|
208
191
|
// src/components/ToolbarMenu.tsx
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
children: /* @__PURE__ */ React4.createElement(ActionLabel, {
|
|
236
|
-
action
|
|
237
|
-
})
|
|
238
|
-
};
|
|
239
|
-
const handleClick = useCallback2(() => action.data?.(), [
|
|
240
|
-
action
|
|
241
|
-
]);
|
|
242
|
-
return hidden ? null : /* @__PURE__ */ React4.createElement(Root, {
|
|
243
|
-
key: action.id,
|
|
244
|
-
disabled,
|
|
245
|
-
onClick: handleClick,
|
|
246
|
-
variant: "ghost",
|
|
247
|
-
...testId && {
|
|
248
|
-
"data-testid": testId
|
|
249
|
-
},
|
|
250
|
-
...rootProps,
|
|
251
|
-
classNames
|
|
252
|
-
});
|
|
253
|
-
} finally {
|
|
254
|
-
_effect.f();
|
|
192
|
+
var ActionToolbarItem = ({ __menuScope, action }) => {
|
|
193
|
+
const { iconSize, onAction } = useMenuScoped("ActionToolbarItem", __menuScope);
|
|
194
|
+
const { t } = useTranslation2(translationKey);
|
|
195
|
+
const { icon, iconOnly = true, disabled, testId, hidden, classNames } = action.properties;
|
|
196
|
+
const buttonVariant = action.properties.variant === "primary" ? "primary" : "ghost";
|
|
197
|
+
const handleClick = useCallback2(() => {
|
|
198
|
+
if (onAction) {
|
|
199
|
+
onAction(action, {});
|
|
200
|
+
} else {
|
|
201
|
+
void executeMenuAction(action);
|
|
202
|
+
}
|
|
203
|
+
}, [
|
|
204
|
+
action,
|
|
205
|
+
onAction
|
|
206
|
+
]);
|
|
207
|
+
const commonProps = {
|
|
208
|
+
variant: buttonVariant,
|
|
209
|
+
disabled,
|
|
210
|
+
classNames,
|
|
211
|
+
onClick: handleClick,
|
|
212
|
+
...testId && {
|
|
213
|
+
"data-testid": testId
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
if (hidden) {
|
|
217
|
+
return null;
|
|
255
218
|
}
|
|
219
|
+
return icon ? /* @__PURE__ */ React3.createElement(NaturalToolbar.IconButton, {
|
|
220
|
+
key: action.id,
|
|
221
|
+
...commonProps,
|
|
222
|
+
icon,
|
|
223
|
+
size: iconSize,
|
|
224
|
+
iconOnly,
|
|
225
|
+
label: actionLabel(action, t)
|
|
226
|
+
}) : /* @__PURE__ */ React3.createElement(NaturalToolbar.Button, {
|
|
227
|
+
key: action.id,
|
|
228
|
+
...commonProps
|
|
229
|
+
}, /* @__PURE__ */ React3.createElement(ActionLabel, {
|
|
230
|
+
action
|
|
231
|
+
}));
|
|
232
|
+
};
|
|
233
|
+
var DropdownMenuToolbarItem = ({ __menuScope, group, items: propsItems }) => {
|
|
234
|
+
const { iconOnly, disabled, testId } = group.properties;
|
|
235
|
+
const { t } = useTranslation2(translationKey);
|
|
236
|
+
const { iconSize } = useMenuScoped("DropdownMenuToolbarItem", __menuScope);
|
|
237
|
+
const items = useMenuItems(group, propsItems, "DropdownMenuToolbarItem", __menuScope);
|
|
238
|
+
const activeItem = items?.find((item) => !!item.properties.checked);
|
|
239
|
+
const icon = group.properties.applyActive && // TODO(thure): Handle other menu item types.
|
|
240
|
+
activeItem?.properties.icon || group.properties.icon;
|
|
241
|
+
const Root = icon ? NaturalToolbar.IconButton : NaturalToolbar.Button;
|
|
242
|
+
const labelAction = group.properties.applyActive && activeItem ? activeItem : group;
|
|
243
|
+
const rootProps = icon ? {
|
|
244
|
+
icon,
|
|
245
|
+
size: iconSize,
|
|
246
|
+
iconOnly,
|
|
247
|
+
label: actionLabel(labelAction, t),
|
|
248
|
+
caretDown: true
|
|
249
|
+
} : {
|
|
250
|
+
children: /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(ActionLabel, {
|
|
251
|
+
action: labelAction
|
|
252
|
+
}), /* @__PURE__ */ React3.createElement(Icon2, {
|
|
253
|
+
size: 3,
|
|
254
|
+
icon: "ph--caret-down--bold",
|
|
255
|
+
classNames: "ms-1"
|
|
256
|
+
}))
|
|
257
|
+
};
|
|
258
|
+
return /* @__PURE__ */ React3.createElement(DropdownMenu.Root, {
|
|
259
|
+
group,
|
|
260
|
+
items
|
|
261
|
+
}, /* @__PURE__ */ React3.createElement(DropdownMenu.Trigger, {
|
|
262
|
+
asChild: true
|
|
263
|
+
}, /* @__PURE__ */ React3.createElement(Root, {
|
|
264
|
+
variant: "ghost",
|
|
265
|
+
disabled,
|
|
266
|
+
...rootProps,
|
|
267
|
+
...testId && {
|
|
268
|
+
"data-testid": testId
|
|
269
|
+
}
|
|
270
|
+
})));
|
|
271
|
+
};
|
|
272
|
+
var ToggleGroupItem = ({ __menuScope, group, action }) => {
|
|
273
|
+
const { iconSize, onAction } = useMenuScoped("ToggleGroupItem", __menuScope);
|
|
274
|
+
const { t } = useTranslation2(translationKey);
|
|
275
|
+
const { icon, iconOnly = true, disabled, testId, hidden, classNames } = action.properties;
|
|
276
|
+
const handleClick = useCallback2(() => {
|
|
277
|
+
if (onAction) {
|
|
278
|
+
onAction(action, {
|
|
279
|
+
parent: group
|
|
280
|
+
});
|
|
281
|
+
} else {
|
|
282
|
+
void executeMenuAction(action, {
|
|
283
|
+
parent: group
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
}, [
|
|
287
|
+
action,
|
|
288
|
+
group,
|
|
289
|
+
onAction
|
|
290
|
+
]);
|
|
291
|
+
const commonProps = {
|
|
292
|
+
value: action.id,
|
|
293
|
+
disabled,
|
|
294
|
+
variant: "ghost",
|
|
295
|
+
classNames,
|
|
296
|
+
onClick: handleClick,
|
|
297
|
+
...testId && {
|
|
298
|
+
"data-testid": testId
|
|
299
|
+
}
|
|
300
|
+
};
|
|
301
|
+
return hidden ? null : icon ? /* @__PURE__ */ React3.createElement(NaturalToolbar.ToggleGroupIconItem, {
|
|
302
|
+
...commonProps,
|
|
303
|
+
icon,
|
|
304
|
+
size: iconSize,
|
|
305
|
+
iconOnly,
|
|
306
|
+
label: actionLabel(action, t)
|
|
307
|
+
}) : /* @__PURE__ */ React3.createElement(NaturalToolbar.ToggleGroupItem, commonProps, /* @__PURE__ */ React3.createElement(ActionLabel, {
|
|
308
|
+
action
|
|
309
|
+
}));
|
|
256
310
|
};
|
|
257
|
-
var
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
} : {
|
|
276
|
-
children: /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement(ActionLabel, {
|
|
277
|
-
action: labelAction
|
|
278
|
-
}), /* @__PURE__ */ React4.createElement(Icon2, {
|
|
279
|
-
size: 3,
|
|
280
|
-
icon: "ph--caret-down--bold",
|
|
281
|
-
classNames: "mis-1"
|
|
282
|
-
}))
|
|
283
|
-
};
|
|
284
|
-
return /* @__PURE__ */ React4.createElement(DropdownMenu.Root, {
|
|
285
|
-
group,
|
|
286
|
-
items
|
|
287
|
-
}, /* @__PURE__ */ React4.createElement(DropdownMenu.Trigger, {
|
|
288
|
-
asChild: true
|
|
289
|
-
}, /* @__PURE__ */ React4.createElement(Root, {
|
|
290
|
-
variant: "ghost",
|
|
291
|
-
disabled,
|
|
292
|
-
...rootProps,
|
|
293
|
-
...testId && {
|
|
294
|
-
"data-testid": testId
|
|
295
|
-
}
|
|
296
|
-
})));
|
|
297
|
-
} finally {
|
|
298
|
-
_effect.f();
|
|
311
|
+
var ToggleGroupToolbarItem = ({ __menuScope, group, items: itemsProp }) => {
|
|
312
|
+
const items = useMenuItems(group, itemsProp, "ToggleGroupToolbarItem", __menuScope);
|
|
313
|
+
const { selectCardinality } = group.properties;
|
|
314
|
+
const children = items.map((action) => /* @__PURE__ */ React3.createElement(ToggleGroupItem, {
|
|
315
|
+
key: action.id,
|
|
316
|
+
group,
|
|
317
|
+
action
|
|
318
|
+
}));
|
|
319
|
+
if (selectCardinality === "multiple") {
|
|
320
|
+
return /* @__PURE__ */ React3.createElement(NaturalToolbar.ToggleGroup, {
|
|
321
|
+
type: "multiple",
|
|
322
|
+
value: group.properties.value
|
|
323
|
+
}, children);
|
|
324
|
+
} else {
|
|
325
|
+
return /* @__PURE__ */ React3.createElement(NaturalToolbar.ToggleGroup, {
|
|
326
|
+
type: "single",
|
|
327
|
+
value: group.properties.value
|
|
328
|
+
}, children);
|
|
299
329
|
}
|
|
300
330
|
};
|
|
301
|
-
var
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
action
|
|
322
|
-
})
|
|
323
|
-
};
|
|
324
|
-
return hidden ? null : /* @__PURE__ */ React4.createElement(Root, {
|
|
325
|
-
key: action.id,
|
|
326
|
-
value: action.id,
|
|
327
|
-
disabled,
|
|
328
|
-
onClick: handleClick,
|
|
329
|
-
variant: "ghost",
|
|
330
|
-
...testId && {
|
|
331
|
-
"data-testid": testId
|
|
332
|
-
},
|
|
333
|
-
...rootProps,
|
|
334
|
-
classNames
|
|
331
|
+
var ToolbarMenu = composable(({ __menuScope, children, ...props }, forwardedRef) => {
|
|
332
|
+
const items = useMenuItems(void 0, void 0, "ToolbarMenu", __menuScope);
|
|
333
|
+
const { attendableId, alwaysActive } = useMenuScoped("ToolbarMenu", __menuScope);
|
|
334
|
+
const { hasAttention } = useAttention(attendableId);
|
|
335
|
+
return /* @__PURE__ */ React3.createElement(NaturalToolbar.Root, {
|
|
336
|
+
...composableProps(props, {
|
|
337
|
+
classNames: attendableId
|
|
338
|
+
}),
|
|
339
|
+
disabled: !alwaysActive && !hasAttention,
|
|
340
|
+
ref: forwardedRef
|
|
341
|
+
}, items?.map((item) => /* @__PURE__ */ React3.createElement(ToolbarMenuItem, {
|
|
342
|
+
key: item.id,
|
|
343
|
+
__menuScope,
|
|
344
|
+
item
|
|
345
|
+
})), children);
|
|
346
|
+
});
|
|
347
|
+
var ToolbarMenuItem = ({ __menuScope, item }) => {
|
|
348
|
+
if (isSeparator(item)) {
|
|
349
|
+
return /* @__PURE__ */ React3.createElement(NaturalToolbar.Separator, {
|
|
350
|
+
variant: item.properties.variant
|
|
335
351
|
});
|
|
336
|
-
} finally {
|
|
337
|
-
_effect.f();
|
|
338
352
|
}
|
|
353
|
+
if (isMenuGroup(item)) {
|
|
354
|
+
if (item.properties.variant === "dropdownMenu") {
|
|
355
|
+
return /* @__PURE__ */ React3.createElement(DropdownMenuToolbarItem, {
|
|
356
|
+
__menuScope,
|
|
357
|
+
group: item
|
|
358
|
+
});
|
|
359
|
+
} else {
|
|
360
|
+
return /* @__PURE__ */ React3.createElement(ToggleGroupToolbarItem, {
|
|
361
|
+
__menuScope,
|
|
362
|
+
group: item
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
return /* @__PURE__ */ React3.createElement(ActionToolbarItem, {
|
|
367
|
+
__menuScope,
|
|
368
|
+
action: item
|
|
369
|
+
});
|
|
339
370
|
};
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
items.map((action) => /* @__PURE__ */ React4.createElement(ToggleGroupItem, {
|
|
356
|
-
key: action.id,
|
|
357
|
-
group,
|
|
358
|
-
action
|
|
359
|
-
}))
|
|
360
|
-
)
|
|
361
|
-
);
|
|
362
|
-
} finally {
|
|
363
|
-
_effect.f();
|
|
371
|
+
|
|
372
|
+
// src/components/Menu.tsx
|
|
373
|
+
var __dxlog_file = "/__w/dxos/dxos/packages/ui/react-ui-menu/src/components/Menu.tsx";
|
|
374
|
+
var MENU_NAME = "Menu";
|
|
375
|
+
var [createMenuContext, createMenuScope] = createContextScope(MENU_NAME, []);
|
|
376
|
+
var nullItemsAtom = Atom.make(null);
|
|
377
|
+
var defaultItemsAccessor = () => nullItemsAtom;
|
|
378
|
+
var menuContextDefaults = {
|
|
379
|
+
iconSize: 5,
|
|
380
|
+
items: defaultItemsAccessor,
|
|
381
|
+
onAction: void 0,
|
|
382
|
+
menuItemsAtom: Atom.make(/* @__PURE__ */ new Map()),
|
|
383
|
+
addMenuItems: () => {
|
|
384
|
+
},
|
|
385
|
+
removeMenuItems: () => {
|
|
364
386
|
}
|
|
365
387
|
};
|
|
366
|
-
var
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
const { attendableId } = useMenu("ToolbarMenu", __menuScope);
|
|
371
|
-
const { hasAttention } = useAttention(attendableId);
|
|
372
|
-
const InnerRoot = textBlockWidthParam ? "div" : Fragment;
|
|
373
|
-
const innerRootProps = textBlockWidthParam ? {
|
|
374
|
-
role: "none",
|
|
375
|
-
className: mx2(textBlockWidth, toolbarLayout, "bs-full")
|
|
376
|
-
} : {};
|
|
377
|
-
return /* @__PURE__ */ React4.createElement(NaturalToolbar.Root, {
|
|
378
|
-
...props,
|
|
379
|
-
classNames: [
|
|
380
|
-
attendableId && !hasAttention && toolbarInactive,
|
|
381
|
-
classNames
|
|
382
|
-
],
|
|
383
|
-
layoutManaged: textBlockWidthParam
|
|
384
|
-
}, /* @__PURE__ */ React4.createElement(InnerRoot, innerRootProps, items?.map((item, i) => /* @__PURE__ */ React4.createElement(ToolbarMenuItem, {
|
|
385
|
-
key: item.id ?? i,
|
|
386
|
-
item
|
|
387
|
-
}))));
|
|
388
|
-
} finally {
|
|
389
|
-
_effect.f();
|
|
388
|
+
var [MenuContextProvider, useMenuScoped] = createMenuContext(MENU_NAME, menuContextDefaults);
|
|
389
|
+
var useMenuScope = createMenuScope();
|
|
390
|
+
var MenuDropdownContext = /* @__PURE__ */ createContext({
|
|
391
|
+
closeMenu: () => {
|
|
390
392
|
}
|
|
393
|
+
});
|
|
394
|
+
var DEFAULT_PRIORITY = 100;
|
|
395
|
+
var sortMenuItems = (items) => [
|
|
396
|
+
...items
|
|
397
|
+
].sort((a, b) => {
|
|
398
|
+
if (a.priority !== b.priority) {
|
|
399
|
+
return a.priority - b.priority;
|
|
400
|
+
}
|
|
401
|
+
return a.id.localeCompare(b.id);
|
|
402
|
+
});
|
|
403
|
+
var MenuProvider = ({ children, items = menuContextDefaults.items, iconSize = menuContextDefaults.iconSize, attendableId, alwaysActive, onAction }) => {
|
|
404
|
+
const { scope } = useMenuScope(void 0);
|
|
405
|
+
const registry = useContext(RegistryContext);
|
|
406
|
+
const menuItemsAtom = useMemo(() => Atom.make(/* @__PURE__ */ new Map()).pipe(Atom.keepAlive), []);
|
|
407
|
+
const addMenuItems = useCallback3((props) => {
|
|
408
|
+
const priority = props.priority ?? DEFAULT_PRIORITY;
|
|
409
|
+
const prev = registry.get(menuItemsAtom);
|
|
410
|
+
const next = new Map(prev);
|
|
411
|
+
next.set(props.id, {
|
|
412
|
+
...props,
|
|
413
|
+
priority
|
|
414
|
+
});
|
|
415
|
+
registry.set(menuItemsAtom, next);
|
|
416
|
+
}, [
|
|
417
|
+
registry,
|
|
418
|
+
menuItemsAtom
|
|
419
|
+
]);
|
|
420
|
+
const removeMenuItems = useCallback3((id) => {
|
|
421
|
+
const prev = registry.get(menuItemsAtom);
|
|
422
|
+
const next = new Map(prev);
|
|
423
|
+
next.delete(id);
|
|
424
|
+
registry.set(menuItemsAtom, next);
|
|
425
|
+
}, [
|
|
426
|
+
registry,
|
|
427
|
+
menuItemsAtom
|
|
428
|
+
]);
|
|
429
|
+
return /* @__PURE__ */ React4.createElement(MenuContextProvider, {
|
|
430
|
+
items,
|
|
431
|
+
iconSize,
|
|
432
|
+
attendableId,
|
|
433
|
+
alwaysActive,
|
|
434
|
+
menuItemsAtom,
|
|
435
|
+
addMenuItems,
|
|
436
|
+
removeMenuItems,
|
|
437
|
+
onAction,
|
|
438
|
+
scope
|
|
439
|
+
}, children);
|
|
391
440
|
};
|
|
392
|
-
var
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
441
|
+
var resolveItems = (baseItems, group, entries) => {
|
|
442
|
+
const applicable = [
|
|
443
|
+
...entries.values()
|
|
444
|
+
].filter((entry) => !entry.groupFilter || entry.groupFilter(group));
|
|
445
|
+
if (applicable.length === 0) {
|
|
446
|
+
return baseItems;
|
|
447
|
+
}
|
|
448
|
+
const sorted = sortMenuItems(applicable);
|
|
449
|
+
const replacements = sorted.filter((entry) => entry.mode === "replacement");
|
|
450
|
+
if (replacements.length > 0) {
|
|
451
|
+
if (replacements.length > 1) {
|
|
452
|
+
log.warn("multiple replacement entries found", {
|
|
453
|
+
ids: replacements.map((r) => r.id).join(", "),
|
|
454
|
+
using: replacements[0].id
|
|
455
|
+
}, {
|
|
456
|
+
F: __dxlog_file,
|
|
457
|
+
L: 152,
|
|
458
|
+
S: void 0,
|
|
459
|
+
C: (f, a) => f(...a)
|
|
398
460
|
});
|
|
399
461
|
}
|
|
400
|
-
|
|
401
|
-
if (item.properties.variant === "dropdownMenu") {
|
|
402
|
-
return /* @__PURE__ */ React4.createElement(DropdownMenuToolbarItem, {
|
|
403
|
-
group: item
|
|
404
|
-
});
|
|
405
|
-
} else {
|
|
406
|
-
return /* @__PURE__ */ React4.createElement(ToggleGroupToolbarItem, {
|
|
407
|
-
group: item
|
|
408
|
-
});
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
return /* @__PURE__ */ React4.createElement(ActionToolbarItem, {
|
|
412
|
-
action: item
|
|
413
|
-
});
|
|
414
|
-
} finally {
|
|
415
|
-
_effect.f();
|
|
462
|
+
return replacements[0].items;
|
|
416
463
|
}
|
|
464
|
+
const additive = sorted.filter((entry) => entry.mode === "additive");
|
|
465
|
+
const additiveItems = additive.flatMap((entry) => entry.items);
|
|
466
|
+
if (!baseItems || baseItems.length === 0) {
|
|
467
|
+
return additiveItems.length > 0 ? additiveItems : null;
|
|
468
|
+
}
|
|
469
|
+
return [
|
|
470
|
+
...baseItems,
|
|
471
|
+
...additiveItems
|
|
472
|
+
];
|
|
417
473
|
};
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
474
|
+
var useMenuItems = (group, propsItems, consumerName = "useMenuItemConsumer", __menuScope) => {
|
|
475
|
+
const { items, menuItemsAtom } = useMenuScoped(consumerName, __menuScope);
|
|
476
|
+
const groupItems = useAtomValue(items(group));
|
|
477
|
+
const entries = useAtomValue(menuItemsAtom) ?? /* @__PURE__ */ new Map();
|
|
478
|
+
const baseItems = useMemo(() => propsItems ?? groupItems ?? null, [
|
|
479
|
+
propsItems,
|
|
480
|
+
groupItems
|
|
481
|
+
]);
|
|
482
|
+
const resolved = useMemo(() => resolveItems(baseItems, group, entries), [
|
|
483
|
+
baseItems,
|
|
484
|
+
group,
|
|
485
|
+
entries
|
|
486
|
+
]);
|
|
487
|
+
return resolved ?? void 0;
|
|
488
|
+
};
|
|
489
|
+
var useMenu = (consumerName) => {
|
|
490
|
+
return useMenuScoped(consumerName, void 0);
|
|
491
|
+
};
|
|
492
|
+
var MenuRoot = ({ children, open, defaultOpen, onOpenChange, caller, ...props }) => {
|
|
493
|
+
const [menuOpen, setMenuOpen] = useControllableState2({
|
|
494
|
+
prop: open,
|
|
495
|
+
defaultProp: defaultOpen,
|
|
496
|
+
onChange: onOpenChange
|
|
497
|
+
});
|
|
498
|
+
const closeMenu = useCallback3(() => setMenuOpen(false), [
|
|
499
|
+
setMenuOpen
|
|
500
|
+
]);
|
|
501
|
+
return /* @__PURE__ */ React4.createElement(MenuProvider, props, /* @__PURE__ */ React4.createElement(MenuDropdownContext.Provider, {
|
|
502
|
+
value: {
|
|
503
|
+
closeMenu,
|
|
504
|
+
caller
|
|
430
505
|
}
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
506
|
+
}, /* @__PURE__ */ React4.createElement(NaturalDropdownMenu2.Root, {
|
|
507
|
+
open: menuOpen,
|
|
508
|
+
onOpenChange: setMenuOpen
|
|
509
|
+
}, children)));
|
|
510
|
+
};
|
|
511
|
+
var MenuContentItem = ({ item, onClick, __menuScope }) => {
|
|
512
|
+
const action = item;
|
|
513
|
+
const handleClick = useCallback3((event) => onClick(action, event), [
|
|
514
|
+
action,
|
|
515
|
+
onClick
|
|
516
|
+
]);
|
|
517
|
+
const { iconSize } = useMenuScoped("MenuContentItem", __menuScope);
|
|
518
|
+
return /* @__PURE__ */ React4.createElement(NaturalDropdownMenu2.Item, {
|
|
519
|
+
onClick: handleClick,
|
|
520
|
+
classNames: "gap-2",
|
|
521
|
+
disabled: action.properties?.disabled,
|
|
522
|
+
...action.properties?.testId && {
|
|
523
|
+
"data-testid": action.properties.testId
|
|
436
524
|
}
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
525
|
+
}, action.properties?.icon && /* @__PURE__ */ React4.createElement(Icon3, {
|
|
526
|
+
icon: action.properties.icon,
|
|
527
|
+
size: iconSize
|
|
528
|
+
}), /* @__PURE__ */ React4.createElement(ActionLabel, {
|
|
529
|
+
action
|
|
530
|
+
}));
|
|
531
|
+
};
|
|
532
|
+
var MenuContent = ({ group, items: propsItems, caller: callerOverride, __menuScope }) => {
|
|
533
|
+
const { closeMenu, caller: contextCaller } = useContext(MenuDropdownContext);
|
|
534
|
+
const caller = callerOverride ?? contextCaller;
|
|
535
|
+
const { onAction } = useMenuScoped("MenuContent", __menuScope);
|
|
536
|
+
const resolvedItems = useMenuItems(group, propsItems, "MenuContent", __menuScope);
|
|
537
|
+
const handleActionClick = useCallback3((action, event) => {
|
|
538
|
+
if (action.properties?.disabled) {
|
|
539
|
+
return;
|
|
440
540
|
}
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
541
|
+
event.stopPropagation();
|
|
542
|
+
closeMenu();
|
|
543
|
+
if (onAction) {
|
|
544
|
+
onAction(action, {
|
|
545
|
+
parent: group,
|
|
546
|
+
caller
|
|
547
|
+
});
|
|
548
|
+
} else {
|
|
549
|
+
void executeMenuAction(action, {
|
|
550
|
+
parent: group,
|
|
551
|
+
caller
|
|
552
|
+
});
|
|
444
553
|
}
|
|
445
|
-
|
|
446
|
-
|
|
554
|
+
}, [
|
|
555
|
+
group,
|
|
556
|
+
caller,
|
|
557
|
+
onAction,
|
|
558
|
+
closeMenu
|
|
559
|
+
]);
|
|
560
|
+
return /* @__PURE__ */ React4.createElement(NaturalDropdownMenu2.Portal, null, /* @__PURE__ */ React4.createElement(NaturalDropdownMenu2.Content, null, /* @__PURE__ */ React4.createElement(NaturalDropdownMenu2.Viewport, null, resolvedItems?.map((item) => /* @__PURE__ */ React4.createElement(MenuContentItem, {
|
|
561
|
+
key: item.id,
|
|
562
|
+
item,
|
|
563
|
+
onClick: handleActionClick
|
|
564
|
+
}))), /* @__PURE__ */ React4.createElement(NaturalDropdownMenu2.Arrow, null)));
|
|
447
565
|
};
|
|
566
|
+
var Menu = {
|
|
567
|
+
Root: MenuRoot,
|
|
568
|
+
Trigger: NaturalDropdownMenu2.Trigger,
|
|
569
|
+
Content: MenuContent,
|
|
570
|
+
VirtualTrigger: NaturalDropdownMenu2.VirtualTrigger,
|
|
571
|
+
Toolbar: ToolbarMenu
|
|
572
|
+
};
|
|
573
|
+
|
|
574
|
+
// src/hooks/useMenuActions.ts
|
|
575
|
+
import { RegistryContext as RegistryContext2, useAtomValue as useAtomValue2 } from "@effect-atom/atom-react";
|
|
576
|
+
import { useCallback as useCallback4, useContext as useContext2, useMemo as useMemo2 } from "react";
|
|
577
|
+
import { Graph, Node as Node3 } from "@dxos/app-graph";
|
|
448
578
|
var useMenuActions = (props) => {
|
|
449
|
-
const registry =
|
|
450
|
-
const menuGraphProps =
|
|
451
|
-
const
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
graph.addNodes(menuGraphProps.nodes);
|
|
458
|
-
graph.addEdges(menuGraphProps.edges);
|
|
579
|
+
const registry = useContext2(RegistryContext2);
|
|
580
|
+
const menuGraphProps = useAtomValue2(props);
|
|
581
|
+
const graph = useMemo2(() => {
|
|
582
|
+
const newGraph = Graph.make({
|
|
583
|
+
registry
|
|
584
|
+
});
|
|
585
|
+
newGraph.pipe(Graph.addNodes(menuGraphProps.nodes), Graph.addEdges(menuGraphProps.edges));
|
|
586
|
+
return newGraph;
|
|
459
587
|
}, [
|
|
588
|
+
registry,
|
|
460
589
|
menuGraphProps
|
|
461
590
|
]);
|
|
462
|
-
const
|
|
463
|
-
|
|
464
|
-
return items;
|
|
591
|
+
const items = useCallback4((group) => {
|
|
592
|
+
return graph.connections(group?.id || Node3.RootId, "child");
|
|
465
593
|
}, [
|
|
466
594
|
graph
|
|
467
595
|
]);
|
|
468
596
|
return {
|
|
469
|
-
|
|
597
|
+
items
|
|
470
598
|
};
|
|
471
599
|
};
|
|
472
600
|
|
|
473
601
|
// src/builder.ts
|
|
474
602
|
import { invariant } from "@dxos/invariant";
|
|
475
|
-
var
|
|
476
|
-
var MenuBuilder = Object.freeze({
|
|
477
|
-
make: () => new MenuBuilderImpl({
|
|
478
|
-
nodes: [],
|
|
479
|
-
edges: []
|
|
480
|
-
}, "root")
|
|
481
|
-
});
|
|
603
|
+
var __dxlog_file2 = "/__w/dxos/dxos/packages/ui/react-ui-menu/src/builder.ts";
|
|
482
604
|
var MenuBuilderImpl = class _MenuBuilderImpl {
|
|
483
605
|
_data;
|
|
484
606
|
_rootId;
|
|
607
|
+
_separatorCount = 0;
|
|
485
608
|
constructor(_data, _rootId) {
|
|
486
609
|
this._data = _data;
|
|
487
610
|
this._rootId = _rootId;
|
|
488
611
|
}
|
|
489
612
|
root(props) {
|
|
490
613
|
invariant(this._rootId === "root", "Root group can only be at the top level", {
|
|
491
|
-
F:
|
|
492
|
-
L:
|
|
614
|
+
F: __dxlog_file2,
|
|
615
|
+
L: 41,
|
|
493
616
|
S: this,
|
|
494
617
|
A: [
|
|
495
618
|
"this._rootId === 'root'",
|
|
@@ -497,8 +620,8 @@ var MenuBuilderImpl = class _MenuBuilderImpl {
|
|
|
497
620
|
]
|
|
498
621
|
});
|
|
499
622
|
invariant(this._data.nodes.find((node) => node.id === "root") === void 0, "Root group can only be created once", {
|
|
500
|
-
F:
|
|
501
|
-
L:
|
|
623
|
+
F: __dxlog_file2,
|
|
624
|
+
L: 42,
|
|
502
625
|
S: this,
|
|
503
626
|
A: [
|
|
504
627
|
"this._data.nodes.find((node) => node.id === 'root') === undefined",
|
|
@@ -508,11 +631,15 @@ var MenuBuilderImpl = class _MenuBuilderImpl {
|
|
|
508
631
|
this._data.nodes.push(createMenuItemGroup("root", props));
|
|
509
632
|
return this;
|
|
510
633
|
}
|
|
634
|
+
build() {
|
|
635
|
+
return this._data;
|
|
636
|
+
}
|
|
511
637
|
action(id, props, invoke) {
|
|
512
638
|
this._data.nodes.push(createMenuAction(id, invoke, props));
|
|
513
639
|
this._data.edges.push({
|
|
514
640
|
source: this._rootId,
|
|
515
|
-
target: id
|
|
641
|
+
target: id,
|
|
642
|
+
relation: "child"
|
|
516
643
|
});
|
|
517
644
|
return this;
|
|
518
645
|
}
|
|
@@ -520,32 +647,55 @@ var MenuBuilderImpl = class _MenuBuilderImpl {
|
|
|
520
647
|
this._data.nodes.push(createMenuItemGroup(id, props));
|
|
521
648
|
this._data.edges.push({
|
|
522
649
|
source: this._rootId,
|
|
523
|
-
target: id
|
|
650
|
+
target: id,
|
|
651
|
+
relation: "child"
|
|
524
652
|
});
|
|
525
653
|
cb(new _MenuBuilderImpl(this._data, id));
|
|
526
654
|
return this;
|
|
527
655
|
}
|
|
528
|
-
|
|
529
|
-
|
|
656
|
+
subgraph(subgraph) {
|
|
657
|
+
this._data.nodes.push(...subgraph.nodes);
|
|
658
|
+
this._data.edges.push(...subgraph.edges);
|
|
659
|
+
return this;
|
|
660
|
+
}
|
|
661
|
+
separator(id, variant = "gap") {
|
|
662
|
+
id ??= `separator-${++this._separatorCount}`;
|
|
663
|
+
this._data.nodes.push({
|
|
664
|
+
id,
|
|
665
|
+
type: MenuSeparatorType,
|
|
666
|
+
properties: {
|
|
667
|
+
variant
|
|
668
|
+
},
|
|
669
|
+
data: void 0
|
|
670
|
+
});
|
|
671
|
+
this._data.edges.push({
|
|
672
|
+
source: this._rootId,
|
|
673
|
+
target: id,
|
|
674
|
+
relation: "child"
|
|
675
|
+
});
|
|
676
|
+
return this;
|
|
530
677
|
}
|
|
531
678
|
};
|
|
679
|
+
var MenuBuilder = Object.freeze({
|
|
680
|
+
make: () => new MenuBuilderImpl({
|
|
681
|
+
nodes: [],
|
|
682
|
+
edges: []
|
|
683
|
+
}, "root")
|
|
684
|
+
});
|
|
532
685
|
export {
|
|
533
|
-
|
|
686
|
+
Menu,
|
|
534
687
|
MenuBuilder,
|
|
535
|
-
MenuProvider,
|
|
536
688
|
MenuSeparatorType,
|
|
537
|
-
ToolbarMenu,
|
|
538
|
-
atomFromSignal,
|
|
539
689
|
createGapSeparator,
|
|
540
690
|
createLineSeparator,
|
|
541
691
|
createMenuAction,
|
|
542
692
|
createMenuItemGroup,
|
|
543
|
-
createMenuScope,
|
|
544
693
|
isMenuGroup,
|
|
545
694
|
isSeparator,
|
|
546
695
|
menuContextDefaults,
|
|
547
696
|
useMenu,
|
|
548
697
|
useMenuActions,
|
|
549
|
-
useMenuItems
|
|
698
|
+
useMenuItems,
|
|
699
|
+
useMenuScoped
|
|
550
700
|
};
|
|
551
701
|
//# sourceMappingURL=index.mjs.map
|