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