@dxos/react-ui-menu 0.8.2-staging.7ac8446 → 0.8.2
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 -262
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node/index.cjs +299 -264
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +298 -262
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/components/ActionLabel.d.ts +8 -4
- package/dist/types/src/components/ActionLabel.d.ts.map +1 -1
- package/dist/types/src/components/DropdownMenu.d.ts +4 -4
- package/dist/types/src/components/DropdownMenu.d.ts.map +1 -1
- package/dist/types/src/components/MenuContext.d.ts +4 -13
- package/dist/types/src/components/MenuContext.d.ts.map +1 -1
- package/dist/types/src/{testing → components}/Menus.stories.d.ts +1 -1
- package/dist/types/src/components/Menus.stories.d.ts.map +1 -0
- package/dist/types/src/components/ToolbarMenu.d.ts +5 -1
- package/dist/types/src/components/ToolbarMenu.d.ts.map +1 -1
- package/dist/types/src/hooks/index.d.ts +2 -0
- package/dist/types/src/hooks/index.d.ts.map +1 -0
- package/dist/types/src/hooks/useMenuActions.d.ts +13 -0
- package/dist/types/src/hooks/useMenuActions.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +2 -1
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/testing/generator.d.ts +27 -0
- package/dist/types/src/testing/generator.d.ts.map +1 -0
- package/dist/types/src/testing/index.d.ts +1 -25
- package/dist/types/src/testing/index.d.ts.map +1 -1
- package/dist/types/src/{defs.d.ts → types.d.ts} +3 -5
- package/dist/types/src/types.d.ts.map +1 -0
- package/dist/types/src/util.d.ts +2 -2
- package/dist/types/src/util.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +20 -13
- package/src/components/ActionLabel.tsx +11 -8
- package/src/components/DropdownMenu.tsx +7 -23
- package/src/components/MenuContext.tsx +11 -26
- package/src/{testing → components}/Menus.stories.tsx +13 -13
- package/src/components/ToolbarMenu.tsx +29 -32
- package/src/hooks/index.ts +5 -0
- package/src/hooks/useMenuActions.ts +69 -0
- package/src/index.ts +3 -1
- package/src/testing/generator.ts +116 -0
- package/src/testing/index.ts +1 -107
- package/src/{defs.ts → types.ts} +2 -5
- package/src/util.ts +7 -7
- package/dist/types/src/defs.d.ts.map +0 -1
- package/dist/types/src/hooks.d.ts +0 -17
- package/dist/types/src/hooks.d.ts.map +0 -1
- package/dist/types/src/testing/Menus.stories.d.ts.map +0 -1
- package/src/hooks.ts +0 -72
|
@@ -1,9 +1,14 @@
|
|
|
1
|
+
// packages/ui/react-ui-menu/src/index.ts
|
|
2
|
+
import { rxFromSignal } from "@dxos/app-graph";
|
|
3
|
+
|
|
1
4
|
// packages/ui/react-ui-menu/src/components/DropdownMenu.tsx
|
|
5
|
+
import { useSignals as _useSignals3 } from "@preact-signals/safe-react/tracking";
|
|
2
6
|
import { useControllableState } from "@radix-ui/react-use-controllable-state";
|
|
3
7
|
import React3, { useCallback } from "react";
|
|
4
8
|
import { DropdownMenu as NaturalDropdownMenu, Icon } from "@dxos/react-ui";
|
|
5
9
|
|
|
6
10
|
// packages/ui/react-ui-menu/src/components/ActionLabel.tsx
|
|
11
|
+
import { useSignals as _useSignals } from "@preact-signals/safe-react/tracking";
|
|
7
12
|
import React from "react";
|
|
8
13
|
import { keySymbols } from "@dxos/keyboard";
|
|
9
14
|
import { toLocalizedString, useTranslation } from "@dxos/react-ui";
|
|
@@ -25,13 +30,11 @@ import { getHostPlatform } from "@dxos/util";
|
|
|
25
30
|
var getShortcut = (action) => {
|
|
26
31
|
return typeof action.properties?.keyBinding === "string" ? action.properties.keyBinding : action.properties?.keyBinding?.[getHostPlatform()];
|
|
27
32
|
};
|
|
28
|
-
var
|
|
29
|
-
};
|
|
30
|
-
var createMenuAction = (id, properties) => ({
|
|
33
|
+
var createMenuAction = (id, invoke, properties) => ({
|
|
31
34
|
id,
|
|
32
35
|
type: ACTION_TYPE,
|
|
33
36
|
properties,
|
|
34
|
-
data:
|
|
37
|
+
data: invoke
|
|
35
38
|
});
|
|
36
39
|
var createMenuItemGroup = (id, properties) => ({
|
|
37
40
|
id,
|
|
@@ -78,16 +81,26 @@ var createLineSeparator = (id = "line", source = "root") => ({
|
|
|
78
81
|
|
|
79
82
|
// packages/ui/react-ui-menu/src/components/ActionLabel.tsx
|
|
80
83
|
var ActionLabel = ({ action }) => {
|
|
84
|
+
var _effect = _useSignals();
|
|
85
|
+
try {
|
|
86
|
+
const shortcut = getShortcut(action);
|
|
87
|
+
const { t } = useTranslation(translationKey);
|
|
88
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("span", {
|
|
89
|
+
className: "grow truncate"
|
|
90
|
+
}, toLocalizedString(action.properties.label, t)), shortcut && /* @__PURE__ */ React.createElement("span", {
|
|
91
|
+
className: mx("shrink-0", descriptionText)
|
|
92
|
+
}, keySymbols(shortcut).join("")));
|
|
93
|
+
} finally {
|
|
94
|
+
_effect.f();
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
var actionLabel = (action, t) => {
|
|
81
98
|
const shortcut = getShortcut(action);
|
|
82
|
-
|
|
83
|
-
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("span", {
|
|
84
|
-
className: "grow truncate"
|
|
85
|
-
}, toLocalizedString(action.properties.label, t)), shortcut && /* @__PURE__ */ React.createElement("span", {
|
|
86
|
-
className: mx("shrink-0", descriptionText)
|
|
87
|
-
}, keySymbols(shortcut).join("")));
|
|
99
|
+
return `${toLocalizedString(action.properties.label, t)}${shortcut ? ` (${keySymbols(shortcut).join("")})` : ""}`;
|
|
88
100
|
};
|
|
89
101
|
|
|
90
102
|
// packages/ui/react-ui-menu/src/components/MenuContext.tsx
|
|
103
|
+
import { useSignals as _useSignals2 } from "@preact-signals/safe-react/tracking";
|
|
91
104
|
import { createContextScope } from "@radix-ui/react-context";
|
|
92
105
|
import React2, { useMemo } from "react";
|
|
93
106
|
var MENU_NAME = "GraphMenu";
|
|
@@ -95,87 +108,94 @@ var [createMenuContext, createMenuScope] = createContextScope(MENU_NAME, []);
|
|
|
95
108
|
var [MenuContextProvider, useMenu] = createMenuContext(MENU_NAME);
|
|
96
109
|
var menuContextDefaults = {
|
|
97
110
|
iconSize: 5,
|
|
98
|
-
|
|
99
|
-
},
|
|
100
|
-
resolveGroupItems: () => null
|
|
111
|
+
useGroupItems: () => null
|
|
101
112
|
};
|
|
102
113
|
var useMenuScope = createMenuScope();
|
|
103
|
-
var MenuProvider = ({ children,
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
114
|
+
var MenuProvider = ({ children, useGroupItems = menuContextDefaults.useGroupItems, iconSize = menuContextDefaults.iconSize, attendableId }) => {
|
|
115
|
+
var _effect = _useSignals2();
|
|
116
|
+
try {
|
|
117
|
+
const { scope } = useMenuScope(void 0);
|
|
118
|
+
return /* @__PURE__ */ React2.createElement(MenuContextProvider, {
|
|
119
|
+
useGroupItems,
|
|
120
|
+
iconSize,
|
|
121
|
+
attendableId,
|
|
122
|
+
scope
|
|
123
|
+
}, children);
|
|
124
|
+
} finally {
|
|
125
|
+
_effect.f();
|
|
126
|
+
}
|
|
112
127
|
};
|
|
113
128
|
var useMenuItems = (group, propsItems, consumerName = "useMenuItemConsumer", __menuScope) => {
|
|
114
|
-
const {
|
|
115
|
-
|
|
129
|
+
const { useGroupItems } = useMenu(consumerName, __menuScope);
|
|
130
|
+
const groupItems = useGroupItems(group);
|
|
131
|
+
return useMemo(() => propsItems ?? groupItems ?? void 0, [
|
|
116
132
|
propsItems,
|
|
117
|
-
|
|
118
|
-
resolveGroupItems
|
|
133
|
+
groupItems
|
|
119
134
|
]);
|
|
120
135
|
};
|
|
121
136
|
|
|
122
137
|
// packages/ui/react-ui-menu/src/components/DropdownMenu.tsx
|
|
123
138
|
var DropdownMenuItem = ({ item, onClick, __menuScope }) => {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
action
|
|
127
|
-
onClick
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
139
|
+
var _effect = _useSignals3();
|
|
140
|
+
try {
|
|
141
|
+
const action = item;
|
|
142
|
+
const handleClick = useCallback((event) => onClick(action, event), [
|
|
143
|
+
action,
|
|
144
|
+
onClick
|
|
145
|
+
]);
|
|
146
|
+
const { iconSize } = useMenu("DropdownMenuItem", __menuScope);
|
|
147
|
+
return /* @__PURE__ */ React3.createElement(NaturalDropdownMenu.Item, {
|
|
148
|
+
onClick: handleClick,
|
|
149
|
+
classNames: "gap-2",
|
|
150
|
+
disabled: action.properties?.disabled,
|
|
151
|
+
...action.properties?.testId && {
|
|
152
|
+
"data-testid": action.properties.testId
|
|
153
|
+
}
|
|
154
|
+
}, action.properties?.icon && /* @__PURE__ */ React3.createElement(Icon, {
|
|
155
|
+
icon: action.properties.icon,
|
|
156
|
+
size: iconSize
|
|
157
|
+
}), /* @__PURE__ */ React3.createElement(ActionLabel, {
|
|
158
|
+
action
|
|
159
|
+
}));
|
|
160
|
+
} finally {
|
|
161
|
+
_effect.f();
|
|
162
|
+
}
|
|
143
163
|
};
|
|
144
|
-
var DropdownMenuRoot = ({ items: propsItems, group, open, defaultOpen, onOpenChange,
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
event.stopPropagation();
|
|
156
|
-
if (suppressNextTooltip) {
|
|
157
|
-
suppressNextTooltip.current = true;
|
|
158
|
-
}
|
|
159
|
-
setOptionsMenuOpen(false);
|
|
160
|
-
onAction?.(action);
|
|
161
|
-
}, [
|
|
162
|
-
onAction
|
|
163
|
-
]);
|
|
164
|
-
const items = useMenuItems(group, propsItems);
|
|
165
|
-
return /* @__PURE__ */ React3.createElement(NaturalDropdownMenu.Root, {
|
|
166
|
-
open: optionsMenuOpen,
|
|
167
|
-
onOpenChange: (nextOpen) => {
|
|
168
|
-
if (!nextOpen && suppressNextTooltip) {
|
|
169
|
-
suppressNextTooltip.current = true;
|
|
164
|
+
var DropdownMenuRoot = ({ items: propsItems, group, open, defaultOpen, onOpenChange, caller, children, __menuScope, ...naturalProps }) => {
|
|
165
|
+
var _effect = _useSignals3();
|
|
166
|
+
try {
|
|
167
|
+
const [optionsMenuOpen, setOptionsMenuOpen] = useControllableState({
|
|
168
|
+
prop: open,
|
|
169
|
+
defaultProp: defaultOpen,
|
|
170
|
+
onChange: onOpenChange
|
|
171
|
+
});
|
|
172
|
+
const handleActionClick = useCallback((action, event) => {
|
|
173
|
+
if (action.properties?.disabled) {
|
|
174
|
+
return;
|
|
170
175
|
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
176
|
+
event.stopPropagation();
|
|
177
|
+
setOptionsMenuOpen(false);
|
|
178
|
+
void action.data?.({
|
|
179
|
+
parent: group,
|
|
180
|
+
caller
|
|
181
|
+
});
|
|
182
|
+
}, [
|
|
183
|
+
group,
|
|
184
|
+
caller
|
|
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))));
|
|
196
|
+
} finally {
|
|
197
|
+
_effect.f();
|
|
198
|
+
}
|
|
179
199
|
};
|
|
180
200
|
var DropdownMenu = {
|
|
181
201
|
Root: DropdownMenuRoot,
|
|
@@ -184,11 +204,12 @@ var DropdownMenu = {
|
|
|
184
204
|
};
|
|
185
205
|
|
|
186
206
|
// packages/ui/react-ui-menu/src/components/ToolbarMenu.tsx
|
|
187
|
-
import
|
|
188
|
-
import {
|
|
207
|
+
import { useSignals as _useSignals4 } from "@preact-signals/safe-react/tracking";
|
|
208
|
+
import React4, { useCallback as useCallback2 } from "react";
|
|
209
|
+
import { Icon as Icon2, Toolbar as NaturalToolbar, useTranslation as useTranslation2 } from "@dxos/react-ui";
|
|
189
210
|
import { useAttention } from "@dxos/react-ui-attention";
|
|
190
211
|
|
|
191
|
-
// packages/ui/react-ui-menu/src/
|
|
212
|
+
// packages/ui/react-ui-menu/src/types.ts
|
|
192
213
|
import { ACTION_GROUP_TYPE as ACTION_GROUP_TYPE2 } from "@dxos/app-graph";
|
|
193
214
|
var MenuSeparatorType = "@dxos/react-ui-toolbar/separator";
|
|
194
215
|
var isSeparator = (node) => node.type === MenuSeparatorType;
|
|
@@ -196,174 +217,193 @@ var isMenuGroup = (node) => node.type === ACTION_GROUP_TYPE2;
|
|
|
196
217
|
|
|
197
218
|
// packages/ui/react-ui-menu/src/components/ToolbarMenu.tsx
|
|
198
219
|
var ActionToolbarItem = ({ action, __menuScope }) => {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
action,
|
|
204
|
-
onAction
|
|
205
|
-
]);
|
|
206
|
-
const { icon, iconOnly = true, disabled, testId, hidden, classNames } = action.properties;
|
|
207
|
-
const Root = icon ? NaturalToolbar.IconButton : NaturalToolbar.Button;
|
|
208
|
-
const rootProps = icon ? {
|
|
209
|
-
icon,
|
|
210
|
-
size: iconSize,
|
|
211
|
-
iconOnly,
|
|
212
|
-
label: /* @__PURE__ */ React4.createElement(ActionLabel, {
|
|
213
|
-
action
|
|
214
|
-
})
|
|
215
|
-
} : {
|
|
216
|
-
children: /* @__PURE__ */ React4.createElement(ActionLabel, {
|
|
220
|
+
var _effect = _useSignals4();
|
|
221
|
+
try {
|
|
222
|
+
const { iconSize } = useMenu("ActionToolbarItem", __menuScope);
|
|
223
|
+
const { t } = useTranslation2(translationKey);
|
|
224
|
+
const handleClick = useCallback2(() => action.data?.(), [
|
|
217
225
|
action
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
226
|
+
]);
|
|
227
|
+
const { icon, iconOnly = true, disabled, testId, hidden, classNames } = action.properties;
|
|
228
|
+
const Root = icon ? NaturalToolbar.IconButton : NaturalToolbar.Button;
|
|
229
|
+
const rootProps = icon ? {
|
|
230
|
+
icon,
|
|
231
|
+
size: iconSize,
|
|
232
|
+
iconOnly,
|
|
233
|
+
label: actionLabel(action, t)
|
|
234
|
+
} : {
|
|
235
|
+
children: /* @__PURE__ */ React4.createElement(ActionLabel, {
|
|
236
|
+
action
|
|
237
|
+
})
|
|
238
|
+
};
|
|
239
|
+
return hidden ? null : /* @__PURE__ */ React4.createElement(Root, {
|
|
240
|
+
key: action.id,
|
|
241
|
+
disabled,
|
|
242
|
+
onClick: handleClick,
|
|
243
|
+
variant: "ghost",
|
|
244
|
+
...testId && {
|
|
245
|
+
"data-testid": testId
|
|
246
|
+
},
|
|
247
|
+
...rootProps,
|
|
248
|
+
classNames
|
|
249
|
+
});
|
|
250
|
+
} finally {
|
|
251
|
+
_effect.f();
|
|
252
|
+
}
|
|
231
253
|
};
|
|
232
254
|
var DropdownMenuToolbarItem = ({ group, items: propsItems, __menuScope }) => {
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
255
|
+
var _effect = _useSignals4();
|
|
256
|
+
try {
|
|
257
|
+
const { iconOnly, disabled, testId } = group.properties;
|
|
258
|
+
const { t } = useTranslation2(translationKey);
|
|
259
|
+
const { iconSize } = useMenu("DropdownMenuToolbarItem", __menuScope);
|
|
260
|
+
const items = useMenuItems(group, propsItems, "DropdownMenuToolbarItem", __menuScope);
|
|
261
|
+
const activeItem = items?.find((item) => !!item.properties.checked);
|
|
262
|
+
const icon = group.properties.applyActive && // TODO(thure): Handle other menu item types.
|
|
263
|
+
activeItem?.properties.icon || group.properties.icon;
|
|
264
|
+
const Root = icon ? NaturalToolbar.IconButton : NaturalToolbar.Button;
|
|
265
|
+
const labelAction = group.properties.applyActive && activeItem ? activeItem : group;
|
|
266
|
+
const rootProps = icon ? {
|
|
267
|
+
icon,
|
|
268
|
+
size: iconSize,
|
|
269
|
+
iconOnly,
|
|
270
|
+
label: actionLabel(labelAction, t),
|
|
271
|
+
caretDown: true
|
|
272
|
+
} : {
|
|
273
|
+
children: /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement(ActionLabel, {
|
|
274
|
+
action: labelAction
|
|
275
|
+
}), /* @__PURE__ */ React4.createElement(Icon2, {
|
|
276
|
+
size: 3,
|
|
277
|
+
icon: "ph--caret-down--bold",
|
|
278
|
+
classNames: "mis-1"
|
|
279
|
+
}))
|
|
280
|
+
};
|
|
281
|
+
return /* @__PURE__ */ React4.createElement(DropdownMenu.Root, {
|
|
282
|
+
group,
|
|
283
|
+
items
|
|
284
|
+
}, /* @__PURE__ */ React4.createElement(DropdownMenu.Trigger, {
|
|
285
|
+
asChild: true
|
|
286
|
+
}, /* @__PURE__ */ React4.createElement(Root, {
|
|
287
|
+
variant: "ghost",
|
|
288
|
+
disabled,
|
|
289
|
+
...rootProps,
|
|
290
|
+
...testId && {
|
|
291
|
+
"data-testid": testId
|
|
292
|
+
}
|
|
293
|
+
})));
|
|
294
|
+
} finally {
|
|
295
|
+
_effect.f();
|
|
296
|
+
}
|
|
272
297
|
};
|
|
273
|
-
var ToggleGroupItem = ({ action, __menuScope }) => {
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
action
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
298
|
+
var ToggleGroupItem = ({ group, action, __menuScope }) => {
|
|
299
|
+
var _effect = _useSignals4();
|
|
300
|
+
try {
|
|
301
|
+
const { iconSize } = useMenu("ToggleGroupItem", __menuScope);
|
|
302
|
+
const { t } = useTranslation2(translationKey);
|
|
303
|
+
const { icon, iconOnly = true, disabled, testId, hidden, classNames } = action.properties;
|
|
304
|
+
const handleClick = useCallback2(() => action.data?.({
|
|
305
|
+
parent: group
|
|
306
|
+
}), [
|
|
307
|
+
action,
|
|
308
|
+
group
|
|
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
|
+
});
|
|
333
|
+
} finally {
|
|
334
|
+
_effect.f();
|
|
335
|
+
}
|
|
307
336
|
};
|
|
308
337
|
var ToggleGroupToolbarItem = ({ group, items: propsItems, __menuScope }) => {
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
action
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
338
|
+
var _effect = _useSignals4();
|
|
339
|
+
try {
|
|
340
|
+
const items = useMenuItems(group, propsItems, "ToggleGroupToolbarItem", __menuScope);
|
|
341
|
+
const { selectCardinality, value } = group.properties;
|
|
342
|
+
return (
|
|
343
|
+
// TODO(thure): The type here is difficult to manage, what do?
|
|
344
|
+
// @ts-ignore
|
|
345
|
+
/* @__PURE__ */ React4.createElement(
|
|
346
|
+
NaturalToolbar.ToggleGroup,
|
|
347
|
+
{
|
|
348
|
+
type: selectCardinality,
|
|
349
|
+
value
|
|
350
|
+
},
|
|
351
|
+
// TODO(thure): Handle other menu item types.
|
|
352
|
+
items.map((action) => /* @__PURE__ */ React4.createElement(ToggleGroupItem, {
|
|
353
|
+
key: action.id,
|
|
354
|
+
group,
|
|
355
|
+
action
|
|
356
|
+
}))
|
|
357
|
+
)
|
|
358
|
+
);
|
|
359
|
+
} finally {
|
|
360
|
+
_effect.f();
|
|
361
|
+
}
|
|
327
362
|
};
|
|
328
363
|
var ToolbarMenu = ({ __menuScope, classNames, ...props }) => {
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
364
|
+
var _effect = _useSignals4();
|
|
365
|
+
try {
|
|
366
|
+
const items = useMenuItems(void 0, void 0, "ToolbarMenu", __menuScope);
|
|
367
|
+
const { attendableId } = useMenu("ToolbarMenu", __menuScope);
|
|
368
|
+
const { hasAttention } = useAttention(attendableId);
|
|
369
|
+
return /* @__PURE__ */ React4.createElement(NaturalToolbar.Root, {
|
|
370
|
+
...props,
|
|
371
|
+
classNames: [
|
|
372
|
+
"p-1",
|
|
373
|
+
attendableId && !hasAttention && "[&>*]:opacity-20 !bg-transparent",
|
|
374
|
+
classNames
|
|
375
|
+
]
|
|
376
|
+
}, items?.map((item, i) => isSeparator(item) ? /* @__PURE__ */ React4.createElement(NaturalToolbar.Separator, {
|
|
377
|
+
key: i,
|
|
378
|
+
variant: item.properties.variant
|
|
379
|
+
}) : isMenuGroup(item) ? item.properties.variant === "dropdownMenu" ? (
|
|
380
|
+
// TODO(thure): Figure out type narrowing that doesn’t require so much use of `as`.
|
|
381
|
+
/* @__PURE__ */ React4.createElement(DropdownMenuToolbarItem, {
|
|
382
|
+
key: item.id,
|
|
383
|
+
group: item
|
|
384
|
+
})
|
|
385
|
+
) : (
|
|
386
|
+
// TODO(thure): Figure out type narrowing that doesn’t require so much use of `as`.
|
|
387
|
+
/* @__PURE__ */ React4.createElement(ToggleGroupToolbarItem, {
|
|
388
|
+
key: item.id,
|
|
389
|
+
group: item
|
|
390
|
+
})
|
|
391
|
+
) : (
|
|
392
|
+
// TODO(thure): Figure out type narrowing that doesn’t require so much use of `as`.
|
|
393
|
+
/* @__PURE__ */ React4.createElement(ActionToolbarItem, {
|
|
394
|
+
key: item.id,
|
|
395
|
+
action: item
|
|
396
|
+
})
|
|
397
|
+
)));
|
|
398
|
+
} finally {
|
|
399
|
+
_effect.f();
|
|
400
|
+
}
|
|
361
401
|
};
|
|
362
402
|
|
|
363
|
-
// packages/ui/react-ui-menu/src/hooks.ts
|
|
364
|
-
import {
|
|
365
|
-
import { useCallback as useCallback3, useState } from "react";
|
|
366
|
-
import { Graph } from "@dxos/app-graph";
|
|
403
|
+
// packages/ui/react-ui-menu/src/hooks/useMenuActions.ts
|
|
404
|
+
import { RegistryContext, useRxValue } from "@effect-rx/rx-react";
|
|
405
|
+
import { useCallback as useCallback3, useContext, useEffect, useState } from "react";
|
|
406
|
+
import { Graph, ROOT_ID } from "@dxos/app-graph";
|
|
367
407
|
var edgesArrayToRecord = (edges) => {
|
|
368
408
|
return Object.fromEntries(Object.entries(edges.reduce((acc, { source, target }) => {
|
|
369
409
|
if (!acc[source]) {
|
|
@@ -387,35 +427,30 @@ var edgesArrayToRecord = (edges) => {
|
|
|
387
427
|
targetEdges.inbound.push(source);
|
|
388
428
|
}
|
|
389
429
|
return acc;
|
|
390
|
-
}, {}))
|
|
391
|
-
id,
|
|
392
|
-
outbound
|
|
393
|
-
]));
|
|
430
|
+
}, {})));
|
|
394
431
|
};
|
|
395
|
-
var useMenuActions = (
|
|
396
|
-
const
|
|
432
|
+
var useMenuActions = (props) => {
|
|
433
|
+
const registry = useContext(RegistryContext);
|
|
434
|
+
const menuGraphProps = useRxValue(props);
|
|
397
435
|
const [graph] = useState(new Graph({
|
|
398
|
-
|
|
399
|
-
|
|
436
|
+
registry,
|
|
437
|
+
nodes: menuGraphProps.nodes,
|
|
438
|
+
edges: edgesArrayToRecord(menuGraphProps.edges)
|
|
400
439
|
}));
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
graph.
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
}) || null;
|
|
411
|
-
} else {
|
|
412
|
-
return null;
|
|
413
|
-
}
|
|
440
|
+
useEffect(() => {
|
|
441
|
+
graph.addNodes(menuGraphProps.nodes);
|
|
442
|
+
graph.addEdges(menuGraphProps.edges);
|
|
443
|
+
}, [
|
|
444
|
+
menuGraphProps
|
|
445
|
+
]);
|
|
446
|
+
const useGroupItems = useCallback3((sourceNode) => {
|
|
447
|
+
const items = useRxValue(graph.connections(sourceNode?.id || ROOT_ID));
|
|
448
|
+
return items;
|
|
414
449
|
}, [
|
|
415
450
|
graph
|
|
416
451
|
]);
|
|
417
452
|
return {
|
|
418
|
-
|
|
453
|
+
useGroupItems
|
|
419
454
|
};
|
|
420
455
|
};
|
|
421
456
|
export {
|
|
@@ -431,6 +466,7 @@ export {
|
|
|
431
466
|
isMenuGroup,
|
|
432
467
|
isSeparator,
|
|
433
468
|
menuContextDefaults,
|
|
469
|
+
rxFromSignal,
|
|
434
470
|
useMenu,
|
|
435
471
|
useMenuActions,
|
|
436
472
|
useMenuItems
|