@dxos/react-ui-menu 0.8.4-main.ead640a → 0.8.4-main.ef1bc66f44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/browser/index.mjs +298 -355
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +298 -355
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/builder.d.ts +1 -1
- package/dist/types/src/builder.d.ts.map +1 -1
- package/dist/types/src/components/ActionLabel.d.ts +3 -3
- package/dist/types/src/components/ActionLabel.d.ts.map +1 -1
- package/dist/types/src/components/DropdownMenu.d.ts.map +1 -1
- package/dist/types/src/components/MenuContext.d.ts +3 -1
- package/dist/types/src/components/MenuContext.d.ts.map +1 -1
- package/dist/types/src/components/ToolbarMenu.d.ts +3 -2
- package/dist/types/src/components/ToolbarMenu.d.ts.map +1 -1
- package/dist/types/src/components/ToolbarMenu.stories.d.ts +2 -2
- package/dist/types/src/components/ToolbarMenu.stories.d.ts.map +1 -1
- package/dist/types/src/hooks/useMenuActions.d.ts +5 -5
- package/dist/types/src/hooks/useMenuActions.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +0 -1
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/testing/generator.d.ts +13 -11
- 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 +13 -24
- package/dist/types/src/types.d.ts.map +1 -1
- package/dist/types/src/util.d.ts +12 -5
- package/dist/types/src/util.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +31 -28
- package/src/builder.ts +1 -1
- package/src/components/ActionLabel.tsx +4 -4
- package/src/components/DropdownMenu.tsx +10 -3
- package/src/components/MenuContext.tsx +17 -3
- package/src/components/ToolbarMenu.stories.tsx +17 -9
- package/src/components/ToolbarMenu.tsx +38 -13
- package/src/hooks/useMenuActions.ts +20 -47
- package/src/index.ts +0 -2
- package/src/testing/generator.ts +63 -58
- package/src/translations.ts +1 -1
- package/src/types.ts +14 -26
- package/src/util.ts +32 -14
|
@@ -1,48 +1,36 @@
|
|
|
1
1
|
import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
|
|
2
2
|
|
|
3
|
-
// src/index.ts
|
|
4
|
-
import { rxFromSignal } from "@dxos/app-graph";
|
|
5
|
-
|
|
6
3
|
// src/components/DropdownMenu.tsx
|
|
7
|
-
import { useSignals as _useSignals3 } from "@preact-signals/safe-react/tracking";
|
|
8
4
|
import { useControllableState } from "@radix-ui/react-use-controllable-state";
|
|
9
5
|
import React3, { useCallback } from "react";
|
|
10
6
|
import { Icon, DropdownMenu as NaturalDropdownMenu } from "@dxos/react-ui";
|
|
11
7
|
|
|
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
|
-
];
|
|
28
|
-
|
|
29
8
|
// src/util.ts
|
|
30
|
-
import
|
|
9
|
+
import * as Effect from "effect/Effect";
|
|
10
|
+
import { Node } from "@dxos/app-graph";
|
|
11
|
+
import { runAndForwardErrors } from "@dxos/effect";
|
|
31
12
|
import { getHostPlatform } from "@dxos/util";
|
|
13
|
+
var executeMenuAction = async (action, params = {}) => {
|
|
14
|
+
let effect = action.data(params);
|
|
15
|
+
if (action._actionContext) {
|
|
16
|
+
effect = effect.pipe(Effect.provide(action._actionContext));
|
|
17
|
+
}
|
|
18
|
+
await runAndForwardErrors(effect);
|
|
19
|
+
};
|
|
32
20
|
var getShortcut = (action) => {
|
|
33
21
|
return typeof action.properties?.keyBinding === "string" ? action.properties.keyBinding : action.properties?.keyBinding?.[getHostPlatform()];
|
|
34
22
|
};
|
|
35
23
|
var createMenuAction = (id, invoke, properties) => ({
|
|
36
24
|
id,
|
|
37
|
-
type:
|
|
25
|
+
type: Node.ActionType,
|
|
38
26
|
properties,
|
|
39
|
-
data: invoke
|
|
27
|
+
data: () => Effect.sync(invoke)
|
|
40
28
|
});
|
|
41
29
|
var createMenuItemGroup = (id, properties) => ({
|
|
42
30
|
id,
|
|
43
|
-
type:
|
|
31
|
+
type: Node.ActionGroupType,
|
|
44
32
|
properties,
|
|
45
|
-
data: actionGroupSymbol
|
|
33
|
+
data: Node.actionGroupSymbol
|
|
46
34
|
});
|
|
47
35
|
var createGapSeparator = (id = "gap", source = "root") => ({
|
|
48
36
|
nodes: [
|
|
@@ -82,19 +70,30 @@ var createLineSeparator = (id = "line", source = "root") => ({
|
|
|
82
70
|
});
|
|
83
71
|
|
|
84
72
|
// src/components/ActionLabel.tsx
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
73
|
+
import React from "react";
|
|
74
|
+
import { keySymbols } from "@dxos/keyboard";
|
|
75
|
+
import { toLocalizedString, useTranslation } from "@dxos/react-ui";
|
|
76
|
+
import { descriptionText, mx } from "@dxos/ui-theme";
|
|
77
|
+
|
|
78
|
+
// src/translations.ts
|
|
79
|
+
var translationKey = "@dxos/react-ui-menu";
|
|
80
|
+
var translations = [
|
|
81
|
+
{
|
|
82
|
+
"en-US": {
|
|
83
|
+
[translationKey]: {}
|
|
84
|
+
}
|
|
97
85
|
}
|
|
86
|
+
];
|
|
87
|
+
|
|
88
|
+
// src/components/ActionLabel.tsx
|
|
89
|
+
var ActionLabel = ({ action }) => {
|
|
90
|
+
const { t } = useTranslation(translationKey);
|
|
91
|
+
const shortcut = getShortcut(action);
|
|
92
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("span", {
|
|
93
|
+
className: "grow truncate"
|
|
94
|
+
}, toLocalizedString(action.properties.label, t)), shortcut && /* @__PURE__ */ React.createElement("span", {
|
|
95
|
+
className: mx("shrink-0", descriptionText)
|
|
96
|
+
}, keySymbols(shortcut).join("")));
|
|
98
97
|
};
|
|
99
98
|
var actionLabel = (action, t) => {
|
|
100
99
|
const shortcut = getShortcut(action);
|
|
@@ -102,30 +101,27 @@ var actionLabel = (action, t) => {
|
|
|
102
101
|
};
|
|
103
102
|
|
|
104
103
|
// src/components/MenuContext.tsx
|
|
105
|
-
import { useSignals as _useSignals2 } from "@preact-signals/safe-react/tracking";
|
|
106
104
|
import { createContextScope } from "@radix-ui/react-context";
|
|
107
105
|
import React2, { useMemo } from "react";
|
|
108
|
-
var MENU_NAME = "
|
|
106
|
+
var MENU_NAME = "Menu";
|
|
109
107
|
var [createMenuContext, createMenuScope] = createContextScope(MENU_NAME, []);
|
|
110
108
|
var [MenuContextProvider, useMenu] = createMenuContext(MENU_NAME);
|
|
111
109
|
var menuContextDefaults = {
|
|
112
110
|
iconSize: 5,
|
|
113
|
-
useGroupItems: () => null
|
|
111
|
+
useGroupItems: () => null,
|
|
112
|
+
onAction: void 0
|
|
114
113
|
};
|
|
115
114
|
var useMenuScope = createMenuScope();
|
|
116
|
-
var MenuProvider = ({ children, useGroupItems = menuContextDefaults.useGroupItems, iconSize = menuContextDefaults.iconSize, attendableId }) => {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
} finally {
|
|
127
|
-
_effect.f();
|
|
128
|
-
}
|
|
115
|
+
var MenuProvider = ({ children, useGroupItems = menuContextDefaults.useGroupItems, iconSize = menuContextDefaults.iconSize, attendableId, alwaysActive, onAction }) => {
|
|
116
|
+
const { scope } = useMenuScope(void 0);
|
|
117
|
+
return /* @__PURE__ */ React2.createElement(MenuContextProvider, {
|
|
118
|
+
useGroupItems,
|
|
119
|
+
iconSize,
|
|
120
|
+
attendableId,
|
|
121
|
+
alwaysActive,
|
|
122
|
+
onAction,
|
|
123
|
+
scope
|
|
124
|
+
}, children);
|
|
129
125
|
};
|
|
130
126
|
var useMenuItems = (group, propsItems, consumerName = "useMenuItemConsumer", __menuScope) => {
|
|
131
127
|
const { useGroupItems } = useMenu(consumerName, __menuScope);
|
|
@@ -138,66 +134,65 @@ var useMenuItems = (group, propsItems, consumerName = "useMenuItemConsumer", __m
|
|
|
138
134
|
|
|
139
135
|
// src/components/DropdownMenu.tsx
|
|
140
136
|
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
|
-
}
|
|
137
|
+
const action = item;
|
|
138
|
+
const handleClick = useCallback((event) => onClick(action, event), [
|
|
139
|
+
action,
|
|
140
|
+
onClick
|
|
141
|
+
]);
|
|
142
|
+
const { iconSize } = useMenu("DropdownMenuItem", __menuScope);
|
|
143
|
+
return /* @__PURE__ */ React3.createElement(NaturalDropdownMenu.Item, {
|
|
144
|
+
onClick: handleClick,
|
|
145
|
+
classNames: "gap-2",
|
|
146
|
+
disabled: action.properties?.disabled,
|
|
147
|
+
...action.properties?.testId && {
|
|
148
|
+
"data-testid": action.properties.testId
|
|
149
|
+
}
|
|
150
|
+
}, action.properties?.icon && /* @__PURE__ */ React3.createElement(Icon, {
|
|
151
|
+
icon: action.properties.icon,
|
|
152
|
+
size: iconSize
|
|
153
|
+
}), /* @__PURE__ */ React3.createElement(ActionLabel, {
|
|
154
|
+
action
|
|
155
|
+
}));
|
|
165
156
|
};
|
|
166
157
|
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
|
-
|
|
158
|
+
const [optionsMenuOpen, setOptionsMenuOpen] = useControllableState({
|
|
159
|
+
prop: open,
|
|
160
|
+
defaultProp: defaultOpen,
|
|
161
|
+
onChange: onOpenChange
|
|
162
|
+
});
|
|
163
|
+
const { onAction } = useMenu("DropdownMenuRoot", __menuScope);
|
|
164
|
+
const handleActionClick = useCallback((action, event) => {
|
|
165
|
+
if (action.properties?.disabled) {
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
event.stopPropagation();
|
|
169
|
+
setOptionsMenuOpen(false);
|
|
170
|
+
if (onAction) {
|
|
171
|
+
onAction(action, {
|
|
181
172
|
parent: group,
|
|
182
173
|
caller
|
|
183
174
|
});
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
}
|
|
175
|
+
} else {
|
|
176
|
+
void executeMenuAction(action, {
|
|
177
|
+
parent: group,
|
|
178
|
+
caller
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
}, [
|
|
182
|
+
group,
|
|
183
|
+
caller,
|
|
184
|
+
onAction
|
|
185
|
+
]);
|
|
186
|
+
const items = useMenuItems(group, propsItems);
|
|
187
|
+
return /* @__PURE__ */ React3.createElement(NaturalDropdownMenu.Root, {
|
|
188
|
+
open: optionsMenuOpen,
|
|
189
|
+
onOpenChange: setOptionsMenuOpen,
|
|
190
|
+
...naturalProps
|
|
191
|
+
}, children, /* @__PURE__ */ React3.createElement(NaturalDropdownMenu.Portal, null, /* @__PURE__ */ React3.createElement(NaturalDropdownMenu.Content, null, /* @__PURE__ */ React3.createElement(NaturalDropdownMenu.Viewport, null, items?.map((item) => /* @__PURE__ */ React3.createElement(DropdownMenuItem, {
|
|
192
|
+
key: item.id,
|
|
193
|
+
item,
|
|
194
|
+
onClick: handleActionClick
|
|
195
|
+
}))), /* @__PURE__ */ React3.createElement(NaturalDropdownMenu.Arrow, null))));
|
|
201
196
|
};
|
|
202
197
|
var DropdownMenu = {
|
|
203
198
|
Root: DropdownMenuRoot,
|
|
@@ -206,261 +201,223 @@ var DropdownMenu = {
|
|
|
206
201
|
};
|
|
207
202
|
|
|
208
203
|
// src/components/ToolbarMenu.tsx
|
|
209
|
-
import { useSignals as _useSignals4 } from "@preact-signals/safe-react/tracking";
|
|
210
204
|
import React4, { Fragment, useCallback as useCallback2 } from "react";
|
|
211
205
|
import { Icon as Icon2, Toolbar as NaturalToolbar, useTranslation as useTranslation2 } from "@dxos/react-ui";
|
|
212
206
|
import { useAttention } from "@dxos/react-ui-attention";
|
|
213
|
-
import { mx as mx2, textBlockWidth, toolbarLayout } from "@dxos/
|
|
207
|
+
import { mx as mx2, textBlockWidth, toolbarLayout } from "@dxos/ui-theme";
|
|
214
208
|
|
|
215
209
|
// src/types.ts
|
|
216
|
-
import {
|
|
210
|
+
import { Node as Node2 } from "@dxos/app-graph";
|
|
217
211
|
var MenuSeparatorType = "@dxos/react-ui-toolbar/separator";
|
|
218
212
|
var isSeparator = (node) => node.type === MenuSeparatorType;
|
|
219
|
-
var isMenuGroup = (node) => node.type ===
|
|
213
|
+
var isMenuGroup = (node) => node.type === Node2.ActionGroupType;
|
|
220
214
|
|
|
221
215
|
// src/components/ToolbarMenu.tsx
|
|
222
216
|
var ActionToolbarItem = ({ action, __menuScope }) => {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
217
|
+
const { iconSize, onAction } = useMenu("ActionToolbarItem", __menuScope);
|
|
218
|
+
const { t } = useTranslation2(translationKey);
|
|
219
|
+
const { icon, iconOnly = true, disabled, testId, hidden, classNames } = action.properties;
|
|
220
|
+
const Root = icon ? NaturalToolbar.IconButton : NaturalToolbar.Button;
|
|
221
|
+
const rootProps = icon ? {
|
|
222
|
+
icon,
|
|
223
|
+
size: iconSize,
|
|
224
|
+
iconOnly,
|
|
225
|
+
label: actionLabel(action, t)
|
|
226
|
+
} : {
|
|
227
|
+
children: /* @__PURE__ */ React4.createElement(ActionLabel, {
|
|
228
228
|
action
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
});
|
|
253
|
-
} finally {
|
|
254
|
-
_effect.f();
|
|
255
|
-
}
|
|
229
|
+
})
|
|
230
|
+
};
|
|
231
|
+
const handleClick = useCallback2(() => {
|
|
232
|
+
if (onAction) {
|
|
233
|
+
onAction(action, {});
|
|
234
|
+
} else {
|
|
235
|
+
void executeMenuAction(action);
|
|
236
|
+
}
|
|
237
|
+
}, [
|
|
238
|
+
action,
|
|
239
|
+
onAction
|
|
240
|
+
]);
|
|
241
|
+
return hidden ? null : /* @__PURE__ */ React4.createElement(Root, {
|
|
242
|
+
key: action.id,
|
|
243
|
+
disabled,
|
|
244
|
+
onClick: handleClick,
|
|
245
|
+
variant: "ghost",
|
|
246
|
+
...testId && {
|
|
247
|
+
"data-testid": testId
|
|
248
|
+
},
|
|
249
|
+
...rootProps,
|
|
250
|
+
classNames
|
|
251
|
+
});
|
|
256
252
|
};
|
|
257
253
|
var DropdownMenuToolbarItem = ({ group, items: propsItems, __menuScope }) => {
|
|
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
|
-
}
|
|
254
|
+
const { iconOnly, disabled, testId } = group.properties;
|
|
255
|
+
const { t } = useTranslation2(translationKey);
|
|
256
|
+
const { iconSize } = useMenu("DropdownMenuToolbarItem", __menuScope);
|
|
257
|
+
const items = useMenuItems(group, propsItems, "DropdownMenuToolbarItem", __menuScope);
|
|
258
|
+
const activeItem = items?.find((item) => !!item.properties.checked);
|
|
259
|
+
const icon = group.properties.applyActive && // TODO(thure): Handle other menu item types.
|
|
260
|
+
activeItem?.properties.icon || group.properties.icon;
|
|
261
|
+
const Root = icon ? NaturalToolbar.IconButton : NaturalToolbar.Button;
|
|
262
|
+
const labelAction = group.properties.applyActive && activeItem ? activeItem : group;
|
|
263
|
+
const rootProps = icon ? {
|
|
264
|
+
icon,
|
|
265
|
+
size: iconSize,
|
|
266
|
+
iconOnly,
|
|
267
|
+
label: actionLabel(labelAction, t),
|
|
268
|
+
caretDown: true
|
|
269
|
+
} : {
|
|
270
|
+
children: /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement(ActionLabel, {
|
|
271
|
+
action: labelAction
|
|
272
|
+
}), /* @__PURE__ */ React4.createElement(Icon2, {
|
|
273
|
+
size: 3,
|
|
274
|
+
icon: "ph--caret-down--bold",
|
|
275
|
+
classNames: "mis-1"
|
|
276
|
+
}))
|
|
277
|
+
};
|
|
278
|
+
return /* @__PURE__ */ React4.createElement(DropdownMenu.Root, {
|
|
279
|
+
group,
|
|
280
|
+
items
|
|
281
|
+
}, /* @__PURE__ */ React4.createElement(DropdownMenu.Trigger, {
|
|
282
|
+
asChild: true
|
|
283
|
+
}, /* @__PURE__ */ React4.createElement(Root, {
|
|
284
|
+
variant: "ghost",
|
|
285
|
+
disabled,
|
|
286
|
+
...rootProps,
|
|
287
|
+
...testId && {
|
|
288
|
+
"data-testid": testId
|
|
289
|
+
}
|
|
290
|
+
})));
|
|
300
291
|
};
|
|
301
292
|
var ToggleGroupItem = ({ group, action, __menuScope }) => {
|
|
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
|
-
|
|
293
|
+
const { iconSize, onAction } = useMenu("ToggleGroupItem", __menuScope);
|
|
294
|
+
const { t } = useTranslation2(translationKey);
|
|
295
|
+
const { icon, iconOnly = true, disabled, testId, hidden, classNames } = action.properties;
|
|
296
|
+
const handleClick = useCallback2(() => {
|
|
297
|
+
if (onAction) {
|
|
298
|
+
onAction(action, {
|
|
299
|
+
parent: group
|
|
300
|
+
});
|
|
301
|
+
} else {
|
|
302
|
+
void executeMenuAction(action, {
|
|
303
|
+
parent: group
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
}, [
|
|
307
|
+
action,
|
|
308
|
+
group,
|
|
309
|
+
onAction
|
|
310
|
+
]);
|
|
311
|
+
const Root = icon ? NaturalToolbar.ToggleGroupIconItem : NaturalToolbar.ToggleGroupItem;
|
|
312
|
+
const rootProps = icon ? {
|
|
313
|
+
icon,
|
|
314
|
+
size: iconSize,
|
|
315
|
+
iconOnly,
|
|
316
|
+
label: actionLabel(action, t)
|
|
317
|
+
} : {
|
|
318
|
+
children: /* @__PURE__ */ React4.createElement(ActionLabel, {
|
|
319
|
+
action
|
|
320
|
+
})
|
|
321
|
+
};
|
|
322
|
+
return hidden ? null : /* @__PURE__ */ React4.createElement(Root, {
|
|
323
|
+
key: action.id,
|
|
324
|
+
value: action.id,
|
|
325
|
+
disabled,
|
|
326
|
+
onClick: handleClick,
|
|
327
|
+
variant: "ghost",
|
|
328
|
+
...testId && {
|
|
329
|
+
"data-testid": testId
|
|
330
|
+
},
|
|
331
|
+
...rootProps,
|
|
332
|
+
classNames
|
|
333
|
+
});
|
|
339
334
|
};
|
|
340
335
|
var ToggleGroupToolbarItem = ({ group, items: propsItems, __menuScope }) => {
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
)
|
|
361
|
-
);
|
|
362
|
-
} finally {
|
|
363
|
-
_effect.f();
|
|
364
|
-
}
|
|
336
|
+
const items = useMenuItems(group, propsItems, "ToggleGroupToolbarItem", __menuScope);
|
|
337
|
+
const { selectCardinality, value } = group.properties;
|
|
338
|
+
return (
|
|
339
|
+
// TODO(thure): Fix.
|
|
340
|
+
// @ts-ignore
|
|
341
|
+
/* @__PURE__ */ React4.createElement(
|
|
342
|
+
NaturalToolbar.ToggleGroup,
|
|
343
|
+
{
|
|
344
|
+
type: selectCardinality,
|
|
345
|
+
value
|
|
346
|
+
},
|
|
347
|
+
// TODO(thure): Handle other menu item types.
|
|
348
|
+
items.map((action) => /* @__PURE__ */ React4.createElement(ToggleGroupItem, {
|
|
349
|
+
key: action.id,
|
|
350
|
+
group,
|
|
351
|
+
action
|
|
352
|
+
}))
|
|
353
|
+
)
|
|
354
|
+
);
|
|
365
355
|
};
|
|
366
|
-
var ToolbarMenu = ({ __menuScope, classNames, textBlockWidth:
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
}))));
|
|
388
|
-
} finally {
|
|
389
|
-
_effect.f();
|
|
390
|
-
}
|
|
356
|
+
var ToolbarMenu = ({ __menuScope, classNames, textBlockWidth: textBlockWidthProp, ...props }) => {
|
|
357
|
+
const items = useMenuItems(void 0, void 0, "ToolbarMenu", __menuScope);
|
|
358
|
+
const { attendableId, alwaysActive } = useMenu("ToolbarMenu", __menuScope);
|
|
359
|
+
const { hasAttention } = useAttention(attendableId);
|
|
360
|
+
const InnerRoot = textBlockWidthProp ? "div" : Fragment;
|
|
361
|
+
const innerRootProps = textBlockWidthProp ? {
|
|
362
|
+
role: "none",
|
|
363
|
+
className: mx2(textBlockWidth, toolbarLayout, "bs-full")
|
|
364
|
+
} : {};
|
|
365
|
+
return /* @__PURE__ */ React4.createElement(NaturalToolbar.Root, {
|
|
366
|
+
...props,
|
|
367
|
+
classNames: [
|
|
368
|
+
attendableId,
|
|
369
|
+
classNames
|
|
370
|
+
],
|
|
371
|
+
disabled: !alwaysActive && !hasAttention,
|
|
372
|
+
layoutManaged: textBlockWidthProp
|
|
373
|
+
}, /* @__PURE__ */ React4.createElement(InnerRoot, innerRootProps, items?.map((item, i) => /* @__PURE__ */ React4.createElement(ToolbarMenuItem, {
|
|
374
|
+
key: item.id ?? i,
|
|
375
|
+
item
|
|
376
|
+
}))));
|
|
391
377
|
};
|
|
392
378
|
var ToolbarMenuItem = ({ item }) => {
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
379
|
+
if (isSeparator(item)) {
|
|
380
|
+
return /* @__PURE__ */ React4.createElement(NaturalToolbar.Separator, {
|
|
381
|
+
variant: item.properties.variant
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
if (isMenuGroup(item)) {
|
|
385
|
+
if (item.properties.variant === "dropdownMenu") {
|
|
386
|
+
return /* @__PURE__ */ React4.createElement(DropdownMenuToolbarItem, {
|
|
387
|
+
group: item
|
|
388
|
+
});
|
|
389
|
+
} else {
|
|
390
|
+
return /* @__PURE__ */ React4.createElement(ToggleGroupToolbarItem, {
|
|
391
|
+
group: item
|
|
398
392
|
});
|
|
399
393
|
}
|
|
400
|
-
if (isMenuGroup(item)) {
|
|
401
|
-
if (item.properties.variant === "dropdownMenu") {
|
|
402
|
-
return /* @__PURE__ */ React4.createElement(DropdownMenuToolbarItem, {
|
|
403
|
-
group: item
|
|
404
|
-
});
|
|
405
|
-
} else {
|
|
406
|
-
return /* @__PURE__ */ React4.createElement(ToggleGroupToolbarItem, {
|
|
407
|
-
group: item
|
|
408
|
-
});
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
return /* @__PURE__ */ React4.createElement(ActionToolbarItem, {
|
|
412
|
-
action: item
|
|
413
|
-
});
|
|
414
|
-
} finally {
|
|
415
|
-
_effect.f();
|
|
416
394
|
}
|
|
395
|
+
return /* @__PURE__ */ React4.createElement(ActionToolbarItem, {
|
|
396
|
+
action: item
|
|
397
|
+
});
|
|
417
398
|
};
|
|
418
399
|
|
|
419
400
|
// src/hooks/useMenuActions.ts
|
|
420
|
-
import { RegistryContext,
|
|
421
|
-
import { useCallback as useCallback3, useContext,
|
|
422
|
-
import { Graph,
|
|
423
|
-
var edgesArrayToRecord = (edges) => {
|
|
424
|
-
return Object.fromEntries(Object.entries(edges.reduce((acc, { source, target }) => {
|
|
425
|
-
if (!acc[source]) {
|
|
426
|
-
acc[source] = {
|
|
427
|
-
inbound: [],
|
|
428
|
-
outbound: []
|
|
429
|
-
};
|
|
430
|
-
}
|
|
431
|
-
if (!acc[target]) {
|
|
432
|
-
acc[target] = {
|
|
433
|
-
inbound: [],
|
|
434
|
-
outbound: []
|
|
435
|
-
};
|
|
436
|
-
}
|
|
437
|
-
const sourceEdges = acc[source];
|
|
438
|
-
if (!sourceEdges.outbound.includes(target)) {
|
|
439
|
-
sourceEdges.outbound.push(target);
|
|
440
|
-
}
|
|
441
|
-
const targetEdges = acc[target];
|
|
442
|
-
if (!targetEdges.inbound.includes(source)) {
|
|
443
|
-
targetEdges.inbound.push(source);
|
|
444
|
-
}
|
|
445
|
-
return acc;
|
|
446
|
-
}, {})));
|
|
447
|
-
};
|
|
401
|
+
import { RegistryContext, useAtomValue } from "@effect-atom/atom-react";
|
|
402
|
+
import { useCallback as useCallback3, useContext, useRef } from "react";
|
|
403
|
+
import { Graph, Node as Node3 } from "@dxos/app-graph";
|
|
448
404
|
var useMenuActions = (props) => {
|
|
449
405
|
const registry = useContext(RegistryContext);
|
|
450
|
-
const menuGraphProps =
|
|
451
|
-
const
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
406
|
+
const menuGraphProps = useAtomValue(props);
|
|
407
|
+
const graphRef = useRef(null);
|
|
408
|
+
if (!graphRef.current || graphRef.current.props !== menuGraphProps) {
|
|
409
|
+
const newGraph = Graph.make({
|
|
410
|
+
registry
|
|
411
|
+
});
|
|
412
|
+
newGraph.pipe(Graph.addNodes(menuGraphProps.nodes), Graph.addEdges(menuGraphProps.edges));
|
|
413
|
+
graphRef.current = {
|
|
414
|
+
graph: newGraph,
|
|
415
|
+
props: menuGraphProps
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
const graph = graphRef.current.graph;
|
|
462
419
|
const useGroupItems = useCallback3((sourceNode) => {
|
|
463
|
-
const items =
|
|
420
|
+
const items = useAtomValue(graph.connections(sourceNode?.id || Node3.RootId));
|
|
464
421
|
return items;
|
|
465
422
|
}, [
|
|
466
423
|
graph
|
|
@@ -472,19 +429,6 @@ var useMenuActions = (props) => {
|
|
|
472
429
|
|
|
473
430
|
// src/builder.ts
|
|
474
431
|
import { invariant } from "@dxos/invariant";
|
|
475
|
-
function _define_property(obj, key, value) {
|
|
476
|
-
if (key in obj) {
|
|
477
|
-
Object.defineProperty(obj, key, {
|
|
478
|
-
value,
|
|
479
|
-
enumerable: true,
|
|
480
|
-
configurable: true,
|
|
481
|
-
writable: true
|
|
482
|
-
});
|
|
483
|
-
} else {
|
|
484
|
-
obj[key] = value;
|
|
485
|
-
}
|
|
486
|
-
return obj;
|
|
487
|
-
}
|
|
488
432
|
var __dxlog_file = "/__w/dxos/dxos/packages/ui/react-ui-menu/src/builder.ts";
|
|
489
433
|
var MenuBuilder = Object.freeze({
|
|
490
434
|
make: () => new MenuBuilderImpl({
|
|
@@ -493,6 +437,12 @@ var MenuBuilder = Object.freeze({
|
|
|
493
437
|
}, "root")
|
|
494
438
|
});
|
|
495
439
|
var MenuBuilderImpl = class _MenuBuilderImpl {
|
|
440
|
+
_data;
|
|
441
|
+
_rootId;
|
|
442
|
+
constructor(_data, _rootId) {
|
|
443
|
+
this._data = _data;
|
|
444
|
+
this._rootId = _rootId;
|
|
445
|
+
}
|
|
496
446
|
root(props) {
|
|
497
447
|
invariant(this._rootId === "root", "Root group can only be at the top level", {
|
|
498
448
|
F: __dxlog_file,
|
|
@@ -535,12 +485,6 @@ var MenuBuilderImpl = class _MenuBuilderImpl {
|
|
|
535
485
|
build() {
|
|
536
486
|
return this._data;
|
|
537
487
|
}
|
|
538
|
-
constructor(_data, _rootId) {
|
|
539
|
-
_define_property(this, "_data", void 0);
|
|
540
|
-
_define_property(this, "_rootId", void 0);
|
|
541
|
-
this._data = _data;
|
|
542
|
-
this._rootId = _rootId;
|
|
543
|
-
}
|
|
544
488
|
};
|
|
545
489
|
export {
|
|
546
490
|
DropdownMenu,
|
|
@@ -556,7 +500,6 @@ export {
|
|
|
556
500
|
isMenuGroup,
|
|
557
501
|
isSeparator,
|
|
558
502
|
menuContextDefaults,
|
|
559
|
-
rxFromSignal,
|
|
560
503
|
useMenu,
|
|
561
504
|
useMenuActions,
|
|
562
505
|
useMenuItems
|