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