@dxos/react-ui-menu 0.8.4-main.66e292d → 0.8.4-main.69d29f4
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 +289 -308
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +289 -308
- 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 +1 -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 +3 -3
- 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 +12 -10
- 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 +11 -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 +9 -1
- package/src/components/ToolbarMenu.stories.tsx +16 -8
- package/src/components/ToolbarMenu.tsx +30 -11
- package/src/hooks/useMenuActions.ts +21 -15
- package/src/index.ts +0 -2
- package/src/testing/generator.ts +63 -58
- package/src/translations.ts +1 -1
- package/src/types.ts +12 -26
- package/src/util.ts +26 -13
|
@@ -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 { atomFromSignal } 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,7 +101,6 @@ 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
106
|
var MENU_NAME = "Menu";
|
|
@@ -110,22 +108,19 @@ 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
|
-
}, children);
|
|
126
|
-
} finally {
|
|
127
|
-
_effect.f();
|
|
128
|
-
}
|
|
115
|
+
var MenuProvider = ({ children, useGroupItems = menuContextDefaults.useGroupItems, iconSize = menuContextDefaults.iconSize, attendableId, onAction }) => {
|
|
116
|
+
const { scope } = useMenuScope(void 0);
|
|
117
|
+
return /* @__PURE__ */ React2.createElement(MenuContextProvider, {
|
|
118
|
+
useGroupItems,
|
|
119
|
+
iconSize,
|
|
120
|
+
attendableId,
|
|
121
|
+
onAction,
|
|
122
|
+
scope
|
|
123
|
+
}, children);
|
|
129
124
|
};
|
|
130
125
|
var useMenuItems = (group, propsItems, consumerName = "useMenuItemConsumer", __menuScope) => {
|
|
131
126
|
const { useGroupItems } = useMenu(consumerName, __menuScope);
|
|
@@ -138,66 +133,65 @@ var useMenuItems = (group, propsItems, consumerName = "useMenuItemConsumer", __m
|
|
|
138
133
|
|
|
139
134
|
// src/components/DropdownMenu.tsx
|
|
140
135
|
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
|
-
}
|
|
136
|
+
const action = item;
|
|
137
|
+
const handleClick = useCallback((event) => onClick(action, event), [
|
|
138
|
+
action,
|
|
139
|
+
onClick
|
|
140
|
+
]);
|
|
141
|
+
const { iconSize } = useMenu("DropdownMenuItem", __menuScope);
|
|
142
|
+
return /* @__PURE__ */ React3.createElement(NaturalDropdownMenu.Item, {
|
|
143
|
+
onClick: handleClick,
|
|
144
|
+
classNames: "gap-2",
|
|
145
|
+
disabled: action.properties?.disabled,
|
|
146
|
+
...action.properties?.testId && {
|
|
147
|
+
"data-testid": action.properties.testId
|
|
148
|
+
}
|
|
149
|
+
}, action.properties?.icon && /* @__PURE__ */ React3.createElement(Icon, {
|
|
150
|
+
icon: action.properties.icon,
|
|
151
|
+
size: iconSize
|
|
152
|
+
}), /* @__PURE__ */ React3.createElement(ActionLabel, {
|
|
153
|
+
action
|
|
154
|
+
}));
|
|
165
155
|
};
|
|
166
156
|
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
|
-
|
|
157
|
+
const [optionsMenuOpen, setOptionsMenuOpen] = useControllableState({
|
|
158
|
+
prop: open,
|
|
159
|
+
defaultProp: defaultOpen,
|
|
160
|
+
onChange: onOpenChange
|
|
161
|
+
});
|
|
162
|
+
const { onAction } = useMenu("DropdownMenuRoot", __menuScope);
|
|
163
|
+
const handleActionClick = useCallback((action, event) => {
|
|
164
|
+
if (action.properties?.disabled) {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
event.stopPropagation();
|
|
168
|
+
setOptionsMenuOpen(false);
|
|
169
|
+
if (onAction) {
|
|
170
|
+
onAction(action, {
|
|
181
171
|
parent: group,
|
|
182
172
|
caller
|
|
183
173
|
});
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
}
|
|
174
|
+
} else {
|
|
175
|
+
void executeMenuAction(action, {
|
|
176
|
+
parent: group,
|
|
177
|
+
caller
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
}, [
|
|
181
|
+
group,
|
|
182
|
+
caller,
|
|
183
|
+
onAction
|
|
184
|
+
]);
|
|
185
|
+
const items = useMenuItems(group, propsItems);
|
|
186
|
+
return /* @__PURE__ */ React3.createElement(NaturalDropdownMenu.Root, {
|
|
187
|
+
open: optionsMenuOpen,
|
|
188
|
+
onOpenChange: setOptionsMenuOpen,
|
|
189
|
+
...naturalProps
|
|
190
|
+
}, 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, {
|
|
191
|
+
key: item.id,
|
|
192
|
+
item,
|
|
193
|
+
onClick: handleActionClick
|
|
194
|
+
}))), /* @__PURE__ */ React3.createElement(NaturalDropdownMenu.Arrow, null))));
|
|
201
195
|
};
|
|
202
196
|
var DropdownMenu = {
|
|
203
197
|
Root: DropdownMenuRoot,
|
|
@@ -206,220 +200,205 @@ var DropdownMenu = {
|
|
|
206
200
|
};
|
|
207
201
|
|
|
208
202
|
// src/components/ToolbarMenu.tsx
|
|
209
|
-
import { useSignals as _useSignals4 } from "@preact-signals/safe-react/tracking";
|
|
210
203
|
import React4, { Fragment, useCallback as useCallback2 } from "react";
|
|
211
204
|
import { Icon as Icon2, Toolbar as NaturalToolbar, useTranslation as useTranslation2 } from "@dxos/react-ui";
|
|
212
205
|
import { useAttention } from "@dxos/react-ui-attention";
|
|
213
|
-
import { mx as mx2, textBlockWidth, toolbarInactive, toolbarLayout } from "@dxos/
|
|
206
|
+
import { mx as mx2, textBlockWidth, toolbarInactive, toolbarLayout } from "@dxos/ui-theme";
|
|
214
207
|
|
|
215
208
|
// src/types.ts
|
|
216
|
-
import {
|
|
209
|
+
import { Node as Node2 } from "@dxos/app-graph";
|
|
217
210
|
var MenuSeparatorType = "@dxos/react-ui-toolbar/separator";
|
|
218
211
|
var isSeparator = (node) => node.type === MenuSeparatorType;
|
|
219
|
-
var isMenuGroup = (node) => node.type ===
|
|
212
|
+
var isMenuGroup = (node) => node.type === Node2.ActionGroupType;
|
|
220
213
|
|
|
221
214
|
// src/components/ToolbarMenu.tsx
|
|
222
215
|
var ActionToolbarItem = ({ action, __menuScope }) => {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
} : {
|
|
235
|
-
children: /* @__PURE__ */ React4.createElement(ActionLabel, {
|
|
236
|
-
action
|
|
237
|
-
})
|
|
238
|
-
};
|
|
239
|
-
const handleClick = useCallback2(() => action.data?.(), [
|
|
216
|
+
const { iconSize, onAction } = useMenu("ActionToolbarItem", __menuScope);
|
|
217
|
+
const { t } = useTranslation2(translationKey);
|
|
218
|
+
const { icon, iconOnly = true, disabled, testId, hidden, classNames } = action.properties;
|
|
219
|
+
const Root = icon ? NaturalToolbar.IconButton : NaturalToolbar.Button;
|
|
220
|
+
const rootProps = icon ? {
|
|
221
|
+
icon,
|
|
222
|
+
size: iconSize,
|
|
223
|
+
iconOnly,
|
|
224
|
+
label: actionLabel(action, t)
|
|
225
|
+
} : {
|
|
226
|
+
children: /* @__PURE__ */ React4.createElement(ActionLabel, {
|
|
240
227
|
action
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
228
|
+
})
|
|
229
|
+
};
|
|
230
|
+
const handleClick = useCallback2(() => {
|
|
231
|
+
if (onAction) {
|
|
232
|
+
onAction(action, {});
|
|
233
|
+
} else {
|
|
234
|
+
void executeMenuAction(action);
|
|
235
|
+
}
|
|
236
|
+
}, [
|
|
237
|
+
action,
|
|
238
|
+
onAction
|
|
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
|
+
});
|
|
256
251
|
};
|
|
257
252
|
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
|
-
}
|
|
253
|
+
const { iconOnly, disabled, testId } = group.properties;
|
|
254
|
+
const { t } = useTranslation2(translationKey);
|
|
255
|
+
const { iconSize } = useMenu("DropdownMenuToolbarItem", __menuScope);
|
|
256
|
+
const items = useMenuItems(group, propsItems, "DropdownMenuToolbarItem", __menuScope);
|
|
257
|
+
const activeItem = items?.find((item) => !!item.properties.checked);
|
|
258
|
+
const icon = group.properties.applyActive && // TODO(thure): Handle other menu item types.
|
|
259
|
+
activeItem?.properties.icon || group.properties.icon;
|
|
260
|
+
const Root = icon ? NaturalToolbar.IconButton : NaturalToolbar.Button;
|
|
261
|
+
const labelAction = group.properties.applyActive && activeItem ? activeItem : group;
|
|
262
|
+
const rootProps = icon ? {
|
|
263
|
+
icon,
|
|
264
|
+
size: iconSize,
|
|
265
|
+
iconOnly,
|
|
266
|
+
label: actionLabel(labelAction, t),
|
|
267
|
+
caretDown: true
|
|
268
|
+
} : {
|
|
269
|
+
children: /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement(ActionLabel, {
|
|
270
|
+
action: labelAction
|
|
271
|
+
}), /* @__PURE__ */ React4.createElement(Icon2, {
|
|
272
|
+
size: 3,
|
|
273
|
+
icon: "ph--caret-down--bold",
|
|
274
|
+
classNames: "mis-1"
|
|
275
|
+
}))
|
|
276
|
+
};
|
|
277
|
+
return /* @__PURE__ */ React4.createElement(DropdownMenu.Root, {
|
|
278
|
+
group,
|
|
279
|
+
items
|
|
280
|
+
}, /* @__PURE__ */ React4.createElement(DropdownMenu.Trigger, {
|
|
281
|
+
asChild: true
|
|
282
|
+
}, /* @__PURE__ */ React4.createElement(Root, {
|
|
283
|
+
variant: "ghost",
|
|
284
|
+
disabled,
|
|
285
|
+
...rootProps,
|
|
286
|
+
...testId && {
|
|
287
|
+
"data-testid": testId
|
|
288
|
+
}
|
|
289
|
+
})));
|
|
300
290
|
};
|
|
301
291
|
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
|
-
|
|
292
|
+
const { iconSize, onAction } = useMenu("ToggleGroupItem", __menuScope);
|
|
293
|
+
const { t } = useTranslation2(translationKey);
|
|
294
|
+
const { icon, iconOnly = true, disabled, testId, hidden, classNames } = action.properties;
|
|
295
|
+
const handleClick = useCallback2(() => {
|
|
296
|
+
if (onAction) {
|
|
297
|
+
onAction(action, {
|
|
298
|
+
parent: group
|
|
299
|
+
});
|
|
300
|
+
} else {
|
|
301
|
+
void executeMenuAction(action, {
|
|
302
|
+
parent: group
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
}, [
|
|
306
|
+
action,
|
|
307
|
+
group,
|
|
308
|
+
onAction
|
|
309
|
+
]);
|
|
310
|
+
const Root = icon ? NaturalToolbar.ToggleGroupIconItem : NaturalToolbar.ToggleGroupItem;
|
|
311
|
+
const rootProps = icon ? {
|
|
312
|
+
icon,
|
|
313
|
+
size: iconSize,
|
|
314
|
+
iconOnly,
|
|
315
|
+
label: actionLabel(action, t)
|
|
316
|
+
} : {
|
|
317
|
+
children: /* @__PURE__ */ React4.createElement(ActionLabel, {
|
|
318
|
+
action
|
|
319
|
+
})
|
|
320
|
+
};
|
|
321
|
+
return hidden ? null : /* @__PURE__ */ React4.createElement(Root, {
|
|
322
|
+
key: action.id,
|
|
323
|
+
value: action.id,
|
|
324
|
+
disabled,
|
|
325
|
+
onClick: handleClick,
|
|
326
|
+
variant: "ghost",
|
|
327
|
+
...testId && {
|
|
328
|
+
"data-testid": testId
|
|
329
|
+
},
|
|
330
|
+
...rootProps,
|
|
331
|
+
classNames
|
|
332
|
+
});
|
|
339
333
|
};
|
|
340
334
|
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
|
-
}
|
|
335
|
+
const items = useMenuItems(group, propsItems, "ToggleGroupToolbarItem", __menuScope);
|
|
336
|
+
const { selectCardinality, value } = group.properties;
|
|
337
|
+
return (
|
|
338
|
+
// TODO(thure): Fix.
|
|
339
|
+
// @ts-ignore
|
|
340
|
+
/* @__PURE__ */ React4.createElement(
|
|
341
|
+
NaturalToolbar.ToggleGroup,
|
|
342
|
+
{
|
|
343
|
+
type: selectCardinality,
|
|
344
|
+
value
|
|
345
|
+
},
|
|
346
|
+
// TODO(thure): Handle other menu item types.
|
|
347
|
+
items.map((action) => /* @__PURE__ */ React4.createElement(ToggleGroupItem, {
|
|
348
|
+
key: action.id,
|
|
349
|
+
group,
|
|
350
|
+
action
|
|
351
|
+
}))
|
|
352
|
+
)
|
|
353
|
+
);
|
|
365
354
|
};
|
|
366
|
-
var ToolbarMenu = ({ __menuScope, classNames, textBlockWidth:
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
classNames
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
item
|
|
387
|
-
}))));
|
|
388
|
-
} finally {
|
|
389
|
-
_effect.f();
|
|
390
|
-
}
|
|
355
|
+
var ToolbarMenu = ({ __menuScope, classNames, textBlockWidth: textBlockWidthProp, ...props }) => {
|
|
356
|
+
const items = useMenuItems(void 0, void 0, "ToolbarMenu", __menuScope);
|
|
357
|
+
const { attendableId } = useMenu("ToolbarMenu", __menuScope);
|
|
358
|
+
const { hasAttention } = useAttention(attendableId);
|
|
359
|
+
const InnerRoot = textBlockWidthProp ? "div" : Fragment;
|
|
360
|
+
const innerRootProps = textBlockWidthProp ? {
|
|
361
|
+
role: "none",
|
|
362
|
+
className: mx2(textBlockWidth, toolbarLayout, "bs-full")
|
|
363
|
+
} : {};
|
|
364
|
+
return /* @__PURE__ */ React4.createElement(NaturalToolbar.Root, {
|
|
365
|
+
...props,
|
|
366
|
+
classNames: [
|
|
367
|
+
attendableId && !hasAttention && toolbarInactive,
|
|
368
|
+
classNames
|
|
369
|
+
],
|
|
370
|
+
layoutManaged: textBlockWidthProp
|
|
371
|
+
}, /* @__PURE__ */ React4.createElement(InnerRoot, innerRootProps, items?.map((item, i) => /* @__PURE__ */ React4.createElement(ToolbarMenuItem, {
|
|
372
|
+
key: item.id ?? i,
|
|
373
|
+
item
|
|
374
|
+
}))));
|
|
391
375
|
};
|
|
392
376
|
var ToolbarMenuItem = ({ item }) => {
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
377
|
+
if (isSeparator(item)) {
|
|
378
|
+
return /* @__PURE__ */ React4.createElement(NaturalToolbar.Separator, {
|
|
379
|
+
variant: item.properties.variant
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
if (isMenuGroup(item)) {
|
|
383
|
+
if (item.properties.variant === "dropdownMenu") {
|
|
384
|
+
return /* @__PURE__ */ React4.createElement(DropdownMenuToolbarItem, {
|
|
385
|
+
group: item
|
|
386
|
+
});
|
|
387
|
+
} else {
|
|
388
|
+
return /* @__PURE__ */ React4.createElement(ToggleGroupToolbarItem, {
|
|
389
|
+
group: item
|
|
398
390
|
});
|
|
399
391
|
}
|
|
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
392
|
}
|
|
393
|
+
return /* @__PURE__ */ React4.createElement(ActionToolbarItem, {
|
|
394
|
+
action: item
|
|
395
|
+
});
|
|
417
396
|
};
|
|
418
397
|
|
|
419
398
|
// src/hooks/useMenuActions.ts
|
|
420
399
|
import { RegistryContext, useAtomValue } from "@effect-atom/atom-react";
|
|
421
|
-
import { useCallback as useCallback3, useContext,
|
|
422
|
-
import { Graph,
|
|
400
|
+
import { useCallback as useCallback3, useContext, useRef } from "react";
|
|
401
|
+
import { Graph, Node as Node3 } from "@dxos/app-graph";
|
|
423
402
|
var edgesArrayToRecord = (edges) => {
|
|
424
403
|
return Object.fromEntries(Object.entries(edges.reduce((acc, { source, target }) => {
|
|
425
404
|
if (!acc[source]) {
|
|
@@ -448,19 +427,22 @@ var edgesArrayToRecord = (edges) => {
|
|
|
448
427
|
var useMenuActions = (props) => {
|
|
449
428
|
const registry = useContext(RegistryContext);
|
|
450
429
|
const menuGraphProps = useAtomValue(props);
|
|
451
|
-
const
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
430
|
+
const graphRef = useRef(null);
|
|
431
|
+
if (!graphRef.current) {
|
|
432
|
+
graphRef.current = Graph.make({
|
|
433
|
+
registry,
|
|
434
|
+
nodes: menuGraphProps.nodes,
|
|
435
|
+
edges: edgesArrayToRecord(menuGraphProps.edges)
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
const graph = graphRef.current;
|
|
439
|
+
const prevPropsRef = useRef(menuGraphProps);
|
|
440
|
+
if (prevPropsRef.current !== menuGraphProps) {
|
|
441
|
+
prevPropsRef.current = menuGraphProps;
|
|
442
|
+
graph.pipe(Graph.addNodes(menuGraphProps.nodes), Graph.addEdges(menuGraphProps.edges));
|
|
443
|
+
}
|
|
462
444
|
const useGroupItems = useCallback3((sourceNode) => {
|
|
463
|
-
const items = useAtomValue(graph.connections(sourceNode?.id ||
|
|
445
|
+
const items = useAtomValue(graph.connections(sourceNode?.id || Node3.RootId));
|
|
464
446
|
return items;
|
|
465
447
|
}, [
|
|
466
448
|
graph
|
|
@@ -535,7 +517,6 @@ export {
|
|
|
535
517
|
MenuProvider,
|
|
536
518
|
MenuSeparatorType,
|
|
537
519
|
ToolbarMenu,
|
|
538
|
-
atomFromSignal,
|
|
539
520
|
createGapSeparator,
|
|
540
521
|
createLineSeparator,
|
|
541
522
|
createMenuAction,
|