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