@dxos/react-ui-menu 0.8.4-main.84f28bd → 0.8.4-main.8baae0fced
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 +548 -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 +548 -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 +16 -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 +14 -5
- package/dist/types/src/util.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +46 -33
- package/src/builder.test.ts +224 -0
- package/src/builder.ts +76 -26
- package/src/components/ActionLabel.tsx +8 -7
- package/src/components/DropdownMenu.tsx +17 -8
- 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 +169 -101
- package/src/components/index.ts +1 -3
- package/src/hooks/useMenuActions.ts +42 -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 +34 -15
- 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,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 { DropdownMenu as NaturalDropdownMenu, Icon } 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 { mx, descriptionText } 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,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 { useAttention } from "@dxos/react-ui-attention";
|
|
101
|
+
import { composable, composableProps } from "@dxos/ui-theme";
|
|
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,336 +179,508 @@ 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
|
-
iconOnly,
|
|
236
|
-
label: actionLabel(action, t)
|
|
237
|
-
} : {
|
|
238
|
-
children: /* @__PURE__ */ React4.createElement(ActionLabel, {
|
|
239
|
-
action
|
|
240
|
-
})
|
|
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
|
+
}));
|
|
256
223
|
};
|
|
257
|
-
var DropdownMenuToolbarItem = ({ group, items: propsItems
|
|
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
|
-
} finally {
|
|
298
|
-
_effect.f();
|
|
299
|
-
}
|
|
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
|
+
})));
|
|
300
264
|
};
|
|
301
|
-
var ToggleGroupItem = ({ group, action
|
|
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
|
-
|
|
337
|
-
|
|
338
|
-
|
|
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
|
+
}));
|
|
339
304
|
};
|
|
340
|
-
var ToggleGroupToolbarItem = ({ group, items:
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
action
|
|
359
|
-
}))
|
|
360
|
-
)
|
|
361
|
-
);
|
|
362
|
-
} finally {
|
|
363
|
-
_effect.f();
|
|
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);
|
|
364
323
|
}
|
|
365
324
|
};
|
|
366
|
-
var ToolbarMenu = ({ __menuScope,
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
key: i,
|
|
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, {
|
|
386
344
|
variant: item.properties.variant
|
|
387
|
-
})
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
if (isMenuGroup(item)) {
|
|
348
|
+
if (item.properties.variant === "dropdownMenu") {
|
|
349
|
+
return /* @__PURE__ */ React3.createElement(DropdownMenuToolbarItem, {
|
|
350
|
+
__menuScope,
|
|
391
351
|
group: item
|
|
392
|
-
})
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
key: item.id,
|
|
352
|
+
});
|
|
353
|
+
} else {
|
|
354
|
+
return /* @__PURE__ */ React3.createElement(ToggleGroupToolbarItem, {
|
|
355
|
+
__menuScope,
|
|
397
356
|
group: item
|
|
398
|
-
})
|
|
399
|
-
|
|
400
|
-
// TODO(thure): Figure out type narrowing that doesn’t require so much use of `as`.
|
|
401
|
-
/* @__PURE__ */ React4.createElement(ActionToolbarItem, {
|
|
402
|
-
key: item.id,
|
|
403
|
-
action: item
|
|
404
|
-
})
|
|
405
|
-
))));
|
|
406
|
-
} finally {
|
|
407
|
-
_effect.f();
|
|
357
|
+
});
|
|
358
|
+
}
|
|
408
359
|
}
|
|
360
|
+
return /* @__PURE__ */ React3.createElement(ActionToolbarItem, {
|
|
361
|
+
__menuScope,
|
|
362
|
+
action: item
|
|
363
|
+
});
|
|
409
364
|
};
|
|
410
365
|
|
|
411
|
-
// src/
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
var
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
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: () => {
|
|
380
|
+
}
|
|
381
|
+
};
|
|
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;
|
|
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);
|
|
434
|
+
};
|
|
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 });
|
|
422
450
|
}
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
451
|
+
return replacements[0].items;
|
|
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
|
+
];
|
|
462
|
+
};
|
|
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
|
|
428
494
|
}
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
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
|
|
432
513
|
}
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
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;
|
|
436
529
|
}
|
|
437
|
-
|
|
438
|
-
|
|
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
|
+
});
|
|
542
|
+
}
|
|
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)));
|
|
439
554
|
};
|
|
555
|
+
var Menu = {
|
|
556
|
+
Root: MenuRoot,
|
|
557
|
+
Trigger: NaturalDropdownMenu2.Trigger,
|
|
558
|
+
Content: MenuContent,
|
|
559
|
+
VirtualTrigger: NaturalDropdownMenu2.VirtualTrigger,
|
|
560
|
+
Toolbar: ToolbarMenu
|
|
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";
|
|
440
567
|
var useMenuActions = (props) => {
|
|
441
|
-
const registry =
|
|
442
|
-
const menuGraphProps =
|
|
443
|
-
const
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
graph.addNodes(menuGraphProps.nodes);
|
|
450
|
-
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;
|
|
451
576
|
}, [
|
|
577
|
+
registry,
|
|
452
578
|
menuGraphProps
|
|
453
579
|
]);
|
|
454
|
-
const
|
|
455
|
-
|
|
456
|
-
return items;
|
|
580
|
+
const items = useCallback4((group) => {
|
|
581
|
+
return graph.connections(group?.id || Node3.RootId, "child");
|
|
457
582
|
}, [
|
|
458
583
|
graph
|
|
459
584
|
]);
|
|
460
585
|
return {
|
|
461
|
-
|
|
586
|
+
items
|
|
462
587
|
};
|
|
463
588
|
};
|
|
589
|
+
var useMenuBuilder = (build, deps) => {
|
|
590
|
+
const atom = useMemo2(() => Atom2.make(build), deps);
|
|
591
|
+
return useMenuActions(atom);
|
|
592
|
+
};
|
|
464
593
|
|
|
465
594
|
// src/builder.ts
|
|
466
595
|
import { invariant } from "@dxos/invariant";
|
|
467
|
-
var
|
|
468
|
-
var MenuBuilder = Object.freeze({
|
|
469
|
-
make: () => new MenuBuilderImpl({
|
|
470
|
-
nodes: [],
|
|
471
|
-
edges: []
|
|
472
|
-
}, "root")
|
|
473
|
-
});
|
|
596
|
+
var __dxlog_file2 = "/__w/dxos/dxos/packages/ui/react-ui-menu/src/builder.ts";
|
|
474
597
|
var MenuBuilderImpl = class _MenuBuilderImpl {
|
|
598
|
+
_data;
|
|
599
|
+
_rootId;
|
|
600
|
+
_separatorCount = 0;
|
|
475
601
|
constructor(_data, _rootId) {
|
|
476
602
|
this._data = _data;
|
|
477
603
|
this._rootId = _rootId;
|
|
478
604
|
}
|
|
479
|
-
|
|
480
|
-
this.
|
|
605
|
+
root(props) {
|
|
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'"] });
|
|
608
|
+
this._data.nodes.push(createMenuItemGroup("root", props));
|
|
609
|
+
return this;
|
|
610
|
+
}
|
|
611
|
+
build() {
|
|
612
|
+
return this._data;
|
|
613
|
+
}
|
|
614
|
+
action(id, props, invoke) {
|
|
615
|
+
this._data.nodes.push(createMenuAction(id, invoke, props));
|
|
481
616
|
this._data.edges.push({
|
|
482
617
|
source: this._rootId,
|
|
483
|
-
target: id
|
|
618
|
+
target: id,
|
|
619
|
+
relation: "child"
|
|
484
620
|
});
|
|
485
621
|
return this;
|
|
486
622
|
}
|
|
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
|
-
]
|
|
623
|
+
group(id, props, cb) {
|
|
624
|
+
this._data.nodes.push(createMenuItemGroup(id, props));
|
|
625
|
+
this._data.edges.push({
|
|
626
|
+
source: this._rootId,
|
|
627
|
+
target: id,
|
|
628
|
+
relation: "child"
|
|
505
629
|
});
|
|
506
|
-
this._data
|
|
630
|
+
cb(new _MenuBuilderImpl(this._data, id));
|
|
631
|
+
return this;
|
|
632
|
+
}
|
|
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
|
+
}
|
|
507
643
|
return this;
|
|
508
644
|
}
|
|
509
|
-
|
|
510
|
-
this.
|
|
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
|
+
});
|
|
511
655
|
this._data.edges.push({
|
|
512
656
|
source: this._rootId,
|
|
513
|
-
target: id
|
|
657
|
+
target: id,
|
|
658
|
+
relation: "child"
|
|
514
659
|
});
|
|
515
|
-
cb(new _MenuBuilderImpl(this._data, id));
|
|
516
660
|
return this;
|
|
517
661
|
}
|
|
518
|
-
build() {
|
|
519
|
-
return this._data;
|
|
520
|
-
}
|
|
521
662
|
};
|
|
663
|
+
var MenuBuilder = Object.freeze({
|
|
664
|
+
make: () => new MenuBuilderImpl({
|
|
665
|
+
nodes: [],
|
|
666
|
+
edges: []
|
|
667
|
+
}, "root")
|
|
668
|
+
});
|
|
522
669
|
export {
|
|
523
|
-
|
|
670
|
+
Menu,
|
|
524
671
|
MenuBuilder,
|
|
525
|
-
MenuProvider,
|
|
526
672
|
MenuSeparatorType,
|
|
527
|
-
ToolbarMenu,
|
|
528
673
|
createGapSeparator,
|
|
529
674
|
createLineSeparator,
|
|
530
675
|
createMenuAction,
|
|
531
676
|
createMenuItemGroup,
|
|
532
|
-
createMenuScope,
|
|
533
677
|
isMenuGroup,
|
|
534
678
|
isSeparator,
|
|
535
679
|
menuContextDefaults,
|
|
536
|
-
rxFromSignal,
|
|
537
680
|
useMenu,
|
|
538
681
|
useMenuActions,
|
|
539
|
-
|
|
682
|
+
useMenuBuilder,
|
|
683
|
+
useMenuItems,
|
|
684
|
+
useMenuScoped
|
|
540
685
|
};
|
|
541
686
|
//# sourceMappingURL=index.mjs.map
|