@dxos/react-ui-menu 0.7.5-main.937ce75 → 0.7.5-main.e9bb01b

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.
Files changed (56) hide show
  1. package/dist/lib/browser/index.mjs +322 -115
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/node/index.cjs +320 -103
  5. package/dist/lib/node/index.cjs.map +4 -4
  6. package/dist/lib/node/meta.json +1 -1
  7. package/dist/lib/node-esm/index.mjs +322 -115
  8. package/dist/lib/node-esm/index.mjs.map +4 -4
  9. package/dist/lib/node-esm/meta.json +1 -1
  10. package/dist/types/src/components/DropdownMenu.d.ts +9 -8
  11. package/dist/types/src/components/DropdownMenu.d.ts.map +1 -1
  12. package/dist/types/src/components/MenuContext.d.ts +13 -0
  13. package/dist/types/src/components/MenuContext.d.ts.map +1 -0
  14. package/dist/types/src/components/ToolbarMenu.d.ts +20 -0
  15. package/dist/types/src/components/ToolbarMenu.d.ts.map +1 -0
  16. package/dist/types/src/components/index.d.ts +2 -1
  17. package/dist/types/src/components/index.d.ts.map +1 -1
  18. package/dist/types/src/defs.d.ts +34 -7
  19. package/dist/types/src/defs.d.ts.map +1 -1
  20. package/dist/types/src/hooks.d.ts +17 -0
  21. package/dist/types/src/hooks.d.ts.map +1 -0
  22. package/dist/types/src/index.d.ts +2 -0
  23. package/dist/types/src/index.d.ts.map +1 -1
  24. package/dist/types/src/testing/Menus.stories.d.ts +4 -1
  25. package/dist/types/src/testing/Menus.stories.d.ts.map +1 -1
  26. package/dist/types/src/testing/index.d.ts +6 -6
  27. package/dist/types/src/testing/index.d.ts.map +1 -1
  28. package/dist/types/src/util.d.ts +42 -1
  29. package/dist/types/src/util.d.ts.map +1 -1
  30. package/dist/types/tsconfig.tsbuildinfo +1 -1
  31. package/package.json +15 -12
  32. package/src/components/DropdownMenu.tsx +35 -27
  33. package/src/components/MenuContext.tsx +57 -0
  34. package/src/components/ToolbarMenu.tsx +185 -0
  35. package/src/components/index.ts +2 -1
  36. package/src/defs.ts +38 -7
  37. package/src/hooks.ts +72 -0
  38. package/src/index.ts +2 -0
  39. package/src/testing/Menus.stories.tsx +30 -18
  40. package/src/testing/index.ts +24 -5
  41. package/src/util.ts +58 -1
  42. package/dist/types/src/components/Toolbar/Toolbar.d.ts +0 -4
  43. package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +0 -1
  44. package/dist/types/src/components/Toolbar/ToolbarDropdownMenu.d.ts +0 -4
  45. package/dist/types/src/components/Toolbar/ToolbarDropdownMenu.d.ts.map +0 -1
  46. package/dist/types/src/components/Toolbar/ToolbarToggleGroup.d.ts +0 -4
  47. package/dist/types/src/components/Toolbar/ToolbarToggleGroup.d.ts.map +0 -1
  48. package/dist/types/src/components/Toolbar/defs.d.ts +0 -30
  49. package/dist/types/src/components/Toolbar/defs.d.ts.map +0 -1
  50. package/dist/types/src/components/Toolbar/index.d.ts +0 -3
  51. package/dist/types/src/components/Toolbar/index.d.ts.map +0 -1
  52. package/src/components/Toolbar/Toolbar.tsx +0 -71
  53. package/src/components/Toolbar/ToolbarDropdownMenu.tsx +0 -36
  54. package/src/components/Toolbar/ToolbarToggleGroup.tsx +0 -39
  55. package/src/components/Toolbar/defs.ts +0 -36
  56. package/src/components/Toolbar/index.ts +0 -6
@@ -2,7 +2,7 @@ import { createRequire } from 'node:module';const require = createRequire(import
2
2
 
3
3
  // packages/ui/react-ui-menu/src/components/DropdownMenu.tsx
4
4
  import { useControllableState } from "@radix-ui/react-use-controllable-state";
5
- import React2, { useCallback } from "react";
5
+ import React3, { useCallback } from "react";
6
6
  import { DropdownMenu as NaturalDropdownMenu, Icon } from "@dxos/react-ui";
7
7
 
8
8
  // packages/ui/react-ui-menu/src/components/ActionLabel.tsx
@@ -22,10 +22,61 @@ var translations_default = [
22
22
  ];
23
23
 
24
24
  // packages/ui/react-ui-menu/src/util.ts
25
+ import { ACTION_GROUP_TYPE, ACTION_TYPE, actionGroupSymbol } from "@dxos/app-graph";
25
26
  import { getHostPlatform } from "@dxos/util";
26
27
  var getShortcut = (action) => {
27
28
  return typeof action.properties?.keyBinding === "string" ? action.properties.keyBinding : action.properties?.keyBinding?.[getHostPlatform()];
28
29
  };
30
+ var noop = () => {
31
+ };
32
+ var createMenuAction = (id, properties) => ({
33
+ id,
34
+ type: ACTION_TYPE,
35
+ properties,
36
+ data: noop
37
+ });
38
+ var createMenuItemGroup = (id, properties) => ({
39
+ id,
40
+ type: ACTION_GROUP_TYPE,
41
+ properties,
42
+ data: actionGroupSymbol
43
+ });
44
+ var createGapSeparator = (id = "gap", source = "root") => ({
45
+ nodes: [
46
+ {
47
+ id,
48
+ type: "@dxos/react-ui-toolbar/separator",
49
+ properties: {
50
+ variant: "gap"
51
+ },
52
+ data: void 0
53
+ }
54
+ ],
55
+ edges: [
56
+ {
57
+ source,
58
+ target: id
59
+ }
60
+ ]
61
+ });
62
+ var createLineSeparator = (id = "line", source = "root") => ({
63
+ nodes: [
64
+ {
65
+ id,
66
+ type: "@dxos/react-ui-toolbar/separator",
67
+ properties: {
68
+ variant: "line"
69
+ },
70
+ data: void 0
71
+ }
72
+ ],
73
+ edges: [
74
+ {
75
+ source,
76
+ target: id
77
+ }
78
+ ]
79
+ });
29
80
 
30
81
  // packages/ui/react-ui-menu/src/components/ActionLabel.tsx
31
82
  var ActionLabel = ({ action }) => {
@@ -38,32 +89,67 @@ var ActionLabel = ({ action }) => {
38
89
  }, keySymbols(shortcut).join("")));
39
90
  };
40
91
 
92
+ // packages/ui/react-ui-menu/src/components/MenuContext.tsx
93
+ import { createContextScope } from "@radix-ui/react-context";
94
+ import React2, { useMemo } from "react";
95
+ var MENU_NAME = "GraphMenu";
96
+ var [createMenuContext, createMenuScope] = createContextScope(MENU_NAME, []);
97
+ var [MenuContextProvider, useMenu] = createMenuContext(MENU_NAME);
98
+ var menuContextDefaults = {
99
+ iconSize: 5,
100
+ onAction: () => {
101
+ },
102
+ resolveGroupItems: () => null
103
+ };
104
+ var useMenuScope = createMenuScope();
105
+ var MenuProvider = ({ children, resolveGroupItems = menuContextDefaults.resolveGroupItems, onAction = menuContextDefaults.onAction, iconSize = menuContextDefaults.iconSize, attendableId }) => {
106
+ const { scope } = useMenuScope(void 0);
107
+ return /* @__PURE__ */ React2.createElement(MenuContextProvider, {
108
+ resolveGroupItems,
109
+ onAction,
110
+ iconSize,
111
+ attendableId,
112
+ scope
113
+ }, children);
114
+ };
115
+ var useMenuItems = (group, propsItems, consumerName = "useMenuItemConsumer", __menuScope) => {
116
+ const { resolveGroupItems } = useMenu(consumerName, __menuScope);
117
+ return useMemo(() => propsItems ?? resolveGroupItems?.(group) ?? void 0, [
118
+ propsItems,
119
+ group,
120
+ resolveGroupItems
121
+ ]);
122
+ };
123
+
41
124
  // packages/ui/react-ui-menu/src/components/DropdownMenu.tsx
42
- var DropdownMenuItem = ({ action, onClick }) => {
125
+ var DropdownMenuItem = ({ item, onClick, __menuScope }) => {
126
+ const action = item;
43
127
  const handleClick = useCallback((event) => onClick(action, event), [
44
128
  action,
45
129
  onClick
46
130
  ]);
47
- return /* @__PURE__ */ React2.createElement(NaturalDropdownMenu.Item, {
131
+ const { iconSize } = useMenu("DropdownMenuItem", __menuScope);
132
+ return /* @__PURE__ */ React3.createElement(NaturalDropdownMenu.Item, {
48
133
  onClick: handleClick,
49
134
  classNames: "gap-2",
50
135
  disabled: action.properties?.disabled,
51
136
  ...action.properties?.testId && {
52
137
  "data-testid": action.properties.testId
53
138
  }
54
- }, action.properties?.icon && /* @__PURE__ */ React2.createElement(Icon, {
139
+ }, action.properties?.icon && /* @__PURE__ */ React3.createElement(Icon, {
55
140
  icon: action.properties.icon,
56
- size: 4
57
- }), /* @__PURE__ */ React2.createElement(ActionLabel, {
141
+ size: iconSize
142
+ }), /* @__PURE__ */ React3.createElement(ActionLabel, {
58
143
  action
59
144
  }));
60
145
  };
61
- var DropdownMenuRoot = ({ defaultMenuOpen, actions, menuOpen, suppressNextTooltip, onMenuOpenChange, onAction, children }) => {
146
+ var DropdownMenuRoot = ({ items: propsItems, group, open, defaultOpen, onOpenChange, suppressNextTooltip, children, __menuScope, ...naturalProps }) => {
62
147
  const [optionsMenuOpen, setOptionsMenuOpen] = useControllableState({
63
- prop: menuOpen,
64
- defaultProp: defaultMenuOpen,
65
- onChange: onMenuOpenChange
148
+ prop: open,
149
+ defaultProp: defaultOpen,
150
+ onChange: onOpenChange
66
151
  });
152
+ const { onAction } = useMenu("DropdownMenuRoot", __menuScope);
67
153
  const handleActionClick = useCallback((action, event) => {
68
154
  if (action.properties?.disabled) {
69
155
  return;
@@ -77,19 +163,21 @@ var DropdownMenuRoot = ({ defaultMenuOpen, actions, menuOpen, suppressNextToolti
77
163
  }, [
78
164
  onAction
79
165
  ]);
80
- return /* @__PURE__ */ React2.createElement(NaturalDropdownMenu.Root, {
166
+ const items = useMenuItems(group, propsItems);
167
+ return /* @__PURE__ */ React3.createElement(NaturalDropdownMenu.Root, {
81
168
  open: optionsMenuOpen,
82
169
  onOpenChange: (nextOpen) => {
83
170
  if (!nextOpen && suppressNextTooltip) {
84
171
  suppressNextTooltip.current = true;
85
172
  }
86
173
  return setOptionsMenuOpen(nextOpen);
87
- }
88
- }, children, /* @__PURE__ */ React2.createElement(NaturalDropdownMenu.Portal, null, /* @__PURE__ */ React2.createElement(NaturalDropdownMenu.Content, null, /* @__PURE__ */ React2.createElement(NaturalDropdownMenu.Viewport, null, actions?.map((action) => /* @__PURE__ */ React2.createElement(DropdownMenuItem, {
89
- key: action.id,
90
- action,
174
+ },
175
+ ...naturalProps
176
+ }, 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, {
177
+ key: item.id,
178
+ item,
91
179
  onClick: handleActionClick
92
- }))), /* @__PURE__ */ React2.createElement(NaturalDropdownMenu.Arrow, null))));
180
+ }))), /* @__PURE__ */ React3.createElement(NaturalDropdownMenu.Arrow, null))));
93
181
  };
94
182
  var DropdownMenu = {
95
183
  Root: DropdownMenuRoot,
@@ -97,137 +185,256 @@ var DropdownMenu = {
97
185
  VirtualTrigger: NaturalDropdownMenu.VirtualTrigger
98
186
  };
99
187
 
100
- // packages/ui/react-ui-menu/src/components/Toolbar/Toolbar.tsx
101
- import React5, { useCallback as useCallback2 } from "react";
102
- import { Toolbar as NaturalToolbar3 } from "@dxos/react-ui";
188
+ // packages/ui/react-ui-menu/src/components/ToolbarMenu.tsx
189
+ import React4, { useCallback as useCallback2, useRef } from "react";
190
+ import { Icon as Icon2, Toolbar as NaturalToolbar } from "@dxos/react-ui";
191
+ import { useAttention } from "@dxos/react-ui-attention";
103
192
 
104
- // packages/ui/react-ui-menu/src/components/Toolbar/ToolbarDropdownMenu.tsx
105
- import React3, { useMemo, useRef } from "react";
106
- import { Toolbar as NaturalToolbar } from "@dxos/react-ui";
107
- var ToolbarDropdownMenu = ({ actionGroup, graph, onAction, applyActiveIcon }) => {
108
- const menuActions = useMemo(() => graph ? graph.actions(actionGroup) : [], [
109
- actionGroup,
110
- graph
193
+ // packages/ui/react-ui-menu/src/defs.ts
194
+ import { ACTION_GROUP_TYPE as ACTION_GROUP_TYPE2 } from "@dxos/app-graph";
195
+ var MenuSeparatorType = "@dxos/react-ui-toolbar/separator";
196
+ var isSeparator = (node) => node.type === MenuSeparatorType;
197
+ var isMenuGroup = (node) => node.type === ACTION_GROUP_TYPE2;
198
+
199
+ // packages/ui/react-ui-menu/src/components/ToolbarMenu.tsx
200
+ var ActionToolbarItem = ({ action, __menuScope }) => {
201
+ const { onAction, iconSize } = useMenu("ActionToolbarItem", __menuScope);
202
+ const handleClick = useCallback2(() => {
203
+ onAction?.(action);
204
+ }, [
205
+ action,
206
+ onAction
111
207
  ]);
112
- const { icon, iconOnly = true, disabled, testId } = actionGroup.properties;
113
- const suppressNextTooltip = useRef(false);
114
- return /* @__PURE__ */ React3.createElement(DropdownMenu.Root, {
115
- actions: menuActions,
116
- onAction,
117
- suppressNextTooltip
118
- }, /* @__PURE__ */ React3.createElement(DropdownMenu.Trigger, {
119
- asChild: true
120
- }, /* @__PURE__ */ React3.createElement(NaturalToolbar.IconButton, {
121
- size: 5,
122
- variant: "ghost",
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,
123
213
  iconOnly,
214
+ label: /* @__PURE__ */ React4.createElement(ActionLabel, {
215
+ action
216
+ })
217
+ } : {
218
+ children: /* @__PURE__ */ React4.createElement(ActionLabel, {
219
+ action
220
+ })
221
+ };
222
+ return hidden ? null : /* @__PURE__ */ React4.createElement(Root, {
223
+ key: action.id,
124
224
  disabled,
125
- icon: applyActiveIcon && menuActions.find((action) => !!action.properties.checked)?.properties.icon || icon,
126
- label: /* @__PURE__ */ React3.createElement(ActionLabel, {
127
- action: actionGroup
128
- }),
225
+ onClick: handleClick,
226
+ variant: "ghost",
129
227
  ...testId && {
130
228
  "data-testid": testId
131
229
  },
132
- suppressNextTooltip,
133
- caretDown: true
134
- })));
230
+ ...rootProps,
231
+ classNames
232
+ });
135
233
  };
136
-
137
- // packages/ui/react-ui-menu/src/components/Toolbar/ToolbarToggleGroup.tsx
138
- import React4, { useMemo as useMemo2 } from "react";
139
- import { Toolbar as NaturalToolbar2 } from "@dxos/react-ui";
140
- var ToolbarToggleGroupItem = ({ action }) => {
141
- const { icon, iconOnly, disabled } = action.properties;
142
- return /* @__PURE__ */ React4.createElement(NaturalToolbar2.ToggleGroupIconItem, {
143
- key: action.id,
144
- value: action.id,
234
+ var DropdownMenuToolbarItem = ({ group, items: propsItems, __menuScope }) => {
235
+ const { iconOnly, disabled, testId } = group.properties;
236
+ const suppressNextTooltip = useRef(false);
237
+ const { iconSize } = useMenu("DropdownMenuToolbarItem", __menuScope);
238
+ const items = useMenuItems(group, propsItems, "DropdownMenuToolbarItem", __menuScope);
239
+ const activeItem = items?.find((item) => !!item.properties.checked);
240
+ const icon = group.properties.applyActive && // TODO(thure): Handle other menu item types.
241
+ activeItem?.properties.icon || group.properties.icon;
242
+ const Root = icon ? NaturalToolbar.IconButton : NaturalToolbar.Button;
243
+ const label = /* @__PURE__ */ React4.createElement(ActionLabel, {
244
+ action: group.properties.applyActive && activeItem ? activeItem : group
245
+ });
246
+ const rootProps = icon ? {
145
247
  icon,
248
+ size: iconSize,
146
249
  iconOnly,
250
+ label,
251
+ caretDown: true,
252
+ suppressNextTooltip
253
+ } : {
254
+ children: /* @__PURE__ */ React4.createElement(React4.Fragment, null, label, /* @__PURE__ */ React4.createElement(Icon2, {
255
+ size: 3,
256
+ icon: "ph--caret-down--bold",
257
+ classNames: "mis-1"
258
+ }))
259
+ };
260
+ return /* @__PURE__ */ React4.createElement(DropdownMenu.Root, {
261
+ group,
262
+ items,
263
+ suppressNextTooltip
264
+ }, /* @__PURE__ */ React4.createElement(DropdownMenu.Trigger, {
265
+ asChild: true
266
+ }, /* @__PURE__ */ React4.createElement(Root, {
267
+ variant: "ghost",
147
268
  disabled,
148
- label: /* @__PURE__ */ React4.createElement(ActionLabel, {
149
- action
150
- })
151
- });
152
- };
153
- var ToolbarToggleGroup = ({ actionGroup, graph }) => {
154
- const menuActions = useMemo2(() => graph ? graph.actions(actionGroup) : [], [
155
- actionGroup,
156
- graph
157
- ]);
158
- const { selectCardinality, value } = actionGroup.properties;
159
- return (
160
- // TODO(thure): This is extremely difficult to manage, what do?
161
- // @ts-ignore
162
- /* @__PURE__ */ React4.createElement(NaturalToolbar2.ToggleGroup, {
163
- type: selectCardinality,
164
- value
165
- }, menuActions.map((action) => /* @__PURE__ */ React4.createElement(ToolbarToggleGroupItem, {
166
- key: action.id,
167
- action
168
- })))
169
- );
269
+ ...rootProps,
270
+ ...testId && {
271
+ "data-testid": testId
272
+ }
273
+ })));
170
274
  };
171
-
172
- // packages/ui/react-ui-menu/src/components/Toolbar/defs.ts
173
- import { ACTION_GROUP_TYPE } from "@dxos/app-graph";
174
- var ToolbarSeparatorType = "@dxos/react-ui-toolbar/separator";
175
- var isSeparator = (node) => node.type === ToolbarSeparatorType;
176
- var isMenu = (node) => node.type === ACTION_GROUP_TYPE;
177
-
178
- // packages/ui/react-ui-menu/src/components/Toolbar/Toolbar.tsx
179
- var ToolbarItem = ({ iconSize, action, onAction }) => {
275
+ var ToggleGroupItem = ({ action, __menuScope }) => {
276
+ const { iconSize, onAction } = useMenu("ToggleGroupItem", __menuScope);
277
+ const { icon, iconOnly = true, disabled, testId, hidden, classNames } = action.properties;
180
278
  const handleClick = useCallback2(() => {
181
279
  onAction?.(action);
182
280
  }, [
183
281
  action,
184
282
  onAction
185
283
  ]);
186
- const { icon, iconOnly = true, disabled, testId } = action.properties;
187
- return /* @__PURE__ */ React5.createElement(NaturalToolbar3.IconButton, {
188
- key: action.id,
189
- iconOnly,
190
- variant: "ghost",
284
+ const Root = icon ? NaturalToolbar.ToggleGroupIconItem : NaturalToolbar.ToggleGroupItem;
285
+ const rootProps = icon ? {
191
286
  icon,
192
287
  size: iconSize,
193
- label: /* @__PURE__ */ React5.createElement(ActionLabel, {
288
+ iconOnly,
289
+ label: /* @__PURE__ */ React4.createElement(ActionLabel, {
194
290
  action
195
- }),
291
+ })
292
+ } : {
293
+ children: /* @__PURE__ */ React4.createElement(ActionLabel, {
294
+ action
295
+ })
296
+ };
297
+ return hidden ? null : /* @__PURE__ */ React4.createElement(Root, {
298
+ key: action.id,
299
+ value: action.id,
196
300
  disabled,
197
301
  onClick: handleClick,
302
+ variant: "ghost",
198
303
  ...testId && {
199
304
  "data-testid": testId
200
- }
305
+ },
306
+ ...rootProps,
307
+ classNames
201
308
  });
202
309
  };
203
- var Toolbar = ({ actions: items, onAction, iconSize = 5, graph, ...props }) => {
204
- return /* @__PURE__ */ React5.createElement(NaturalToolbar3.Root, props, items?.map((item, i) => isSeparator(item) ? /* @__PURE__ */ React5.createElement(NaturalToolbar3.Separator, {
310
+ var ToggleGroupToolbarItem = ({ group, items: propsItems, __menuScope }) => {
311
+ const items = useMenuItems(group, propsItems, "ToggleGroupToolbarItem", __menuScope);
312
+ const { selectCardinality, value } = group.properties;
313
+ return (
314
+ // TODO(thure): The type here is difficult to manage, what do?
315
+ // @ts-ignore
316
+ /* @__PURE__ */ React4.createElement(
317
+ NaturalToolbar.ToggleGroup,
318
+ {
319
+ type: selectCardinality,
320
+ value
321
+ },
322
+ // TODO(thure): Handle other menu item types.
323
+ items.map((action) => /* @__PURE__ */ React4.createElement(ToggleGroupItem, {
324
+ key: action.id,
325
+ action
326
+ }))
327
+ )
328
+ );
329
+ };
330
+ var ToolbarMenu = ({ __menuScope, classNames, ...props }) => {
331
+ const items = useMenuItems(void 0, void 0, "ToolbarMenu", __menuScope);
332
+ const { attendableId } = useMenu("ToolbarMenu", __menuScope);
333
+ const { hasAttention } = useAttention(attendableId);
334
+ return /* @__PURE__ */ React4.createElement(NaturalToolbar.Root, {
335
+ ...props,
336
+ classNames: [
337
+ "p-0 pointer-fine:p-1 attention-surface",
338
+ !hasAttention && "opacity-20",
339
+ classNames
340
+ ]
341
+ }, items?.map((item, i) => isSeparator(item) ? /* @__PURE__ */ React4.createElement(NaturalToolbar.Separator, {
205
342
  key: i,
206
343
  variant: item.properties.variant
207
- }) : isMenu(item) ? item.properties.variant === "dropdownMenu" ? /* @__PURE__ */ React5.createElement(ToolbarDropdownMenu, {
208
- key: item.id,
209
- actionGroup: item,
210
- onAction,
211
- iconSize,
212
- graph
213
- }) : /* @__PURE__ */ React5.createElement(ToolbarToggleGroup, {
214
- key: item.id,
215
- actionGroup: item,
216
- onAction,
217
- iconSize,
344
+ }) : isMenuGroup(item) ? item.properties.variant === "dropdownMenu" ? (
345
+ // TODO(thure): Figure out type narrowing that doesn’t require so much use of `as`.
346
+ /* @__PURE__ */ React4.createElement(DropdownMenuToolbarItem, {
347
+ key: item.id,
348
+ group: item
349
+ })
350
+ ) : (
351
+ // TODO(thure): Figure out type narrowing that doesn’t require so much use of `as`.
352
+ /* @__PURE__ */ React4.createElement(ToggleGroupToolbarItem, {
353
+ key: item.id,
354
+ group: item
355
+ })
356
+ ) : (
357
+ // TODO(thure): Figure out type narrowing that doesn’t require so much use of `as`.
358
+ /* @__PURE__ */ React4.createElement(ActionToolbarItem, {
359
+ key: item.id,
360
+ action: item
361
+ })
362
+ )));
363
+ };
364
+
365
+ // packages/ui/react-ui-menu/src/hooks.ts
366
+ import { useSignalEffect } from "@preact/signals-react";
367
+ import { useCallback as useCallback3, useState } from "react";
368
+ import { Graph } from "@dxos/app-graph";
369
+ var edgesArrayToRecord = (edges) => {
370
+ return Object.fromEntries(Object.entries(edges.reduce((acc, { source, target }) => {
371
+ if (!acc[source]) {
372
+ acc[source] = {
373
+ inbound: [],
374
+ outbound: []
375
+ };
376
+ }
377
+ if (!acc[target]) {
378
+ acc[target] = {
379
+ inbound: [],
380
+ outbound: []
381
+ };
382
+ }
383
+ const sourceEdges = acc[source];
384
+ if (!sourceEdges.outbound.includes(target)) {
385
+ sourceEdges.outbound.push(target);
386
+ }
387
+ const targetEdges = acc[target];
388
+ if (!targetEdges.inbound.includes(source)) {
389
+ targetEdges.inbound.push(source);
390
+ }
391
+ return acc;
392
+ }, {})).map(([id, { outbound }]) => [
393
+ id,
394
+ outbound
395
+ ]));
396
+ };
397
+ var useMenuActions = (actionCreator) => {
398
+ const initialMenuGraphProps = actionCreator();
399
+ const [graph] = useState(new Graph({
400
+ nodes: initialMenuGraphProps.nodes,
401
+ edges: edgesArrayToRecord(initialMenuGraphProps.edges)
402
+ }));
403
+ useSignalEffect(() => {
404
+ const menuGraphProps = actionCreator();
405
+ graph._addNodes(menuGraphProps.nodes);
406
+ graph._addEdges(menuGraphProps.edges);
407
+ });
408
+ const resolveGroupItems = useCallback3((sourceNode = graph.root) => {
409
+ if (graph) {
410
+ return graph.nodes(sourceNode, {
411
+ filter: (n) => true
412
+ }) || null;
413
+ } else {
414
+ return null;
415
+ }
416
+ }, [
218
417
  graph
219
- }) : /* @__PURE__ */ React5.createElement(ToolbarItem, {
220
- key: item.id,
221
- action: item,
222
- onAction,
223
- iconSize
224
- })));
418
+ ]);
419
+ return {
420
+ resolveGroupItems
421
+ };
225
422
  };
226
423
  export {
227
424
  DropdownMenu,
228
- Toolbar,
229
- ToolbarSeparatorType,
230
- isMenu,
231
- isSeparator
425
+ MenuProvider,
426
+ MenuSeparatorType,
427
+ ToolbarMenu,
428
+ createGapSeparator,
429
+ createLineSeparator,
430
+ createMenuAction,
431
+ createMenuItemGroup,
432
+ createMenuScope,
433
+ isMenuGroup,
434
+ isSeparator,
435
+ menuContextDefaults,
436
+ useMenu,
437
+ useMenuActions,
438
+ useMenuItems
232
439
  };
233
440
  //# sourceMappingURL=index.mjs.map