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