@dxos/react-ui-menu 0.8.4-main.dedc0f3 → 0.8.4-main.e00bdcdb52

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 (63) hide show
  1. package/dist/lib/browser/index.mjs +533 -420
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/browser/translations.mjs +14 -0
  5. package/dist/lib/browser/translations.mjs.map +7 -0
  6. package/dist/lib/node-esm/index.mjs +533 -420
  7. package/dist/lib/node-esm/index.mjs.map +4 -4
  8. package/dist/lib/node-esm/meta.json +1 -1
  9. package/dist/lib/node-esm/translations.mjs +16 -0
  10. package/dist/lib/node-esm/translations.mjs.map +7 -0
  11. package/dist/types/src/builder.d.ts +27 -2
  12. package/dist/types/src/builder.d.ts.map +1 -1
  13. package/dist/types/src/builder.test.d.ts +2 -0
  14. package/dist/types/src/builder.test.d.ts.map +1 -0
  15. package/dist/types/src/components/ActionLabel.d.ts +3 -3
  16. package/dist/types/src/components/ActionLabel.d.ts.map +1 -1
  17. package/dist/types/src/components/DropdownMenu.d.ts +4 -2
  18. package/dist/types/src/components/DropdownMenu.d.ts.map +1 -1
  19. package/dist/types/src/components/Menu.d.ts +50 -0
  20. package/dist/types/src/components/Menu.d.ts.map +1 -0
  21. package/dist/types/src/components/Menu.stories.d.ts +21 -0
  22. package/dist/types/src/components/Menu.stories.d.ts.map +1 -0
  23. package/dist/types/src/components/Menu.test.d.ts +2 -0
  24. package/dist/types/src/components/Menu.test.d.ts.map +1 -0
  25. package/dist/types/src/components/ToolbarMenu.d.ts +7 -6
  26. package/dist/types/src/components/ToolbarMenu.d.ts.map +1 -1
  27. package/dist/types/src/components/ToolbarMenu.stories.d.ts +4 -3
  28. package/dist/types/src/components/ToolbarMenu.stories.d.ts.map +1 -1
  29. package/dist/types/src/components/index.d.ts +1 -3
  30. package/dist/types/src/components/index.d.ts.map +1 -1
  31. package/dist/types/src/hooks/useMenuActions.d.ts +8 -7
  32. package/dist/types/src/hooks/useMenuActions.d.ts.map +1 -1
  33. package/dist/types/src/index.d.ts +1 -2
  34. package/dist/types/src/index.d.ts.map +1 -1
  35. package/dist/types/src/testing/generator.d.ts +20 -14
  36. package/dist/types/src/testing/generator.d.ts.map +1 -1
  37. package/dist/types/src/translations.d.ts +2 -2
  38. package/dist/types/src/translations.d.ts.map +1 -1
  39. package/dist/types/src/types.d.ts +38 -27
  40. package/dist/types/src/types.d.ts.map +1 -1
  41. package/dist/types/src/util.d.ts +14 -5
  42. package/dist/types/src/util.d.ts.map +1 -1
  43. package/dist/types/tsconfig.tsbuildinfo +1 -1
  44. package/package.json +44 -32
  45. package/src/builder.test.ts +224 -0
  46. package/src/builder.ts +69 -19
  47. package/src/components/ActionLabel.tsx +7 -6
  48. package/src/components/DropdownMenu.tsx +12 -6
  49. package/src/components/Menu.stories.tsx +266 -0
  50. package/src/components/Menu.test.tsx +447 -0
  51. package/src/components/Menu.tsx +348 -0
  52. package/src/components/ToolbarMenu.stories.tsx +39 -31
  53. package/src/components/ToolbarMenu.tsx +140 -90
  54. package/src/components/index.ts +1 -3
  55. package/src/hooks/useMenuActions.ts +30 -53
  56. package/src/index.ts +1 -3
  57. package/src/testing/generator.ts +74 -64
  58. package/src/translations.ts +1 -1
  59. package/src/types.ts +39 -27
  60. package/src/util.ts +34 -15
  61. package/dist/types/src/components/MenuContext.d.ts +0 -13
  62. package/dist/types/src/components/MenuContext.d.ts.map +0 -1
  63. package/src/components/MenuContext.tsx +0 -50
@@ -1,46 +1,37 @@
1
- // src/index.ts
2
- import { rxFromSignal } from "@dxos/app-graph";
3
-
4
- // src/components/DropdownMenu.tsx
5
- import { useSignals as _useSignals3 } from "@preact-signals/safe-react/tracking";
6
- import { useControllableState } from "@radix-ui/react-use-controllable-state";
7
- import React3, { useCallback } from "react";
8
- import { Icon, DropdownMenu as NaturalDropdownMenu } from "@dxos/react-ui";
9
-
10
- // src/components/ActionLabel.tsx
11
- import { useSignals as _useSignals } from "@preact-signals/safe-react/tracking";
12
- import React from "react";
13
- import { keySymbols } from "@dxos/keyboard";
14
- import { toLocalizedString, useTranslation } from "@dxos/react-ui";
15
- import { descriptionText, mx } from "@dxos/react-ui-theme";
16
-
17
- // src/translations.ts
18
- var translationKey = "react-ui-menu";
19
- var translations = [
20
- {
21
- "en-US": {
22
- [translationKey]: {}
23
- }
24
- }
25
- ];
1
+ // src/components/Menu.tsx
2
+ import { Atom, RegistryContext, useAtomValue } from "@effect-atom/atom-react";
3
+ import { createContextScope } from "@radix-ui/react-context";
4
+ import { useControllableState as useControllableState2 } from "@radix-ui/react-use-controllable-state";
5
+ import React4, { createContext, useCallback as useCallback3, useContext, useMemo } from "react";
6
+ import { log } from "@dxos/log";
7
+ import { Icon as Icon3, DropdownMenu as NaturalDropdownMenu2 } from "@dxos/react-ui";
26
8
 
27
9
  // src/util.ts
28
- import { ACTION_GROUP_TYPE, ACTION_TYPE, actionGroupSymbol } from "@dxos/app-graph";
10
+ import * as Effect from "effect/Effect";
11
+ import { Node } from "@dxos/app-graph";
12
+ import { runAndForwardErrors } from "@dxos/effect";
29
13
  import { getHostPlatform } from "@dxos/util";
14
+ var executeMenuAction = async (action, params = {}) => {
15
+ let effect = action.data(params);
16
+ if (action._actionContext) {
17
+ effect = effect.pipe(Effect.provide(action._actionContext));
18
+ }
19
+ await runAndForwardErrors(effect);
20
+ };
30
21
  var getShortcut = (action) => {
31
22
  return typeof action.properties?.keyBinding === "string" ? action.properties.keyBinding : action.properties?.keyBinding?.[getHostPlatform()];
32
23
  };
33
24
  var createMenuAction = (id, invoke, properties) => ({
34
25
  id,
35
- type: ACTION_TYPE,
26
+ type: Node.ActionType,
36
27
  properties,
37
- data: invoke
28
+ data: () => Effect.sync(invoke)
38
29
  });
39
30
  var createMenuItemGroup = (id, properties) => ({
40
31
  id,
41
- type: ACTION_GROUP_TYPE,
32
+ type: Node.ActionGroupType,
42
33
  properties,
43
- data: actionGroupSymbol
34
+ data: Node.actionGroupSymbol
44
35
  });
45
36
  var createGapSeparator = (id = "gap", source = "root") => ({
46
37
  nodes: [
@@ -56,7 +47,8 @@ var createGapSeparator = (id = "gap", source = "root") => ({
56
47
  edges: [
57
48
  {
58
49
  source,
59
- target: id
50
+ target: id,
51
+ relation: "child"
60
52
  }
61
53
  ]
62
54
  });
@@ -74,128 +66,109 @@ var createLineSeparator = (id = "line", source = "root") => ({
74
66
  edges: [
75
67
  {
76
68
  source,
77
- target: id
69
+ target: id,
70
+ relation: "child"
78
71
  }
79
72
  ]
80
73
  });
81
74
 
82
75
  // src/components/ActionLabel.tsx
76
+ import React from "react";
77
+ import { keySymbols } from "@dxos/keyboard";
78
+ import { toLocalizedString, useTranslation } from "@dxos/react-ui";
79
+ import { mx } from "@dxos/ui-theme";
80
+ import { translationKey } from "#translations";
83
81
  var ActionLabel = ({ action }) => {
84
- var _effect = _useSignals();
85
- try {
86
- const { t } = useTranslation(translationKey);
87
- const shortcut = getShortcut(action);
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
- }
82
+ const { t } = useTranslation(translationKey);
83
+ const shortcut = getShortcut(action);
84
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("span", {
85
+ className: "grow truncate"
86
+ }, toLocalizedString(action.properties.label, t)), shortcut && /* @__PURE__ */ React.createElement("span", {
87
+ className: mx("shrink-0", "text-description")
88
+ }, keySymbols(shortcut).join("")));
96
89
  };
97
90
  var actionLabel = (action, t) => {
98
91
  const shortcut = getShortcut(action);
99
92
  return `${toLocalizedString(action.properties.label, t)}${shortcut ? ` (${keySymbols(shortcut).join("")})` : ""}`;
100
93
  };
101
94
 
102
- // src/components/MenuContext.tsx
103
- import { useSignals as _useSignals2 } from "@preact-signals/safe-react/tracking";
104
- import { createContextScope } from "@radix-ui/react-context";
105
- import React2, { useMemo } from "react";
106
- var MENU_NAME = "GraphMenu";
107
- var [createMenuContext, createMenuScope] = createContextScope(MENU_NAME, []);
108
- var [MenuContextProvider, useMenu] = createMenuContext(MENU_NAME);
109
- var menuContextDefaults = {
110
- iconSize: 5,
111
- useGroupItems: () => null
112
- };
113
- var useMenuScope = createMenuScope();
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
- }
127
- };
128
- var useMenuItems = (group, propsItems, consumerName = "useMenuItemConsumer", __menuScope) => {
129
- const { useGroupItems } = useMenu(consumerName, __menuScope);
130
- const groupItems = useGroupItems(group);
131
- return useMemo(() => propsItems ?? groupItems ?? void 0, [
132
- propsItems,
133
- groupItems
134
- ]);
135
- };
95
+ // src/components/ToolbarMenu.tsx
96
+ import React3, { useCallback as useCallback2 } from "react";
97
+ import { Icon as Icon2, Toolbar as NaturalToolbar, useTranslation as useTranslation2 } from "@dxos/react-ui";
98
+ import { useAttention } from "@dxos/react-ui-attention";
99
+ import { composable, composableProps } from "@dxos/ui-theme";
100
+ import { translationKey as translationKey2 } from "#translations";
101
+
102
+ // src/types.ts
103
+ import { Node as Node2 } from "@dxos/app-graph";
104
+ var MenuSeparatorType = "@dxos/react-ui-toolbar/separator";
105
+ var isSeparator = (node) => node.type === MenuSeparatorType;
106
+ var isMenuGroup = (node) => node.type === Node2.ActionGroupType;
136
107
 
137
108
  // src/components/DropdownMenu.tsx
109
+ import { useControllableState } from "@radix-ui/react-use-controllable-state";
110
+ import React2, { useCallback } from "react";
111
+ import { Icon, DropdownMenu as NaturalDropdownMenu } from "@dxos/react-ui";
138
112
  var DropdownMenuItem = ({ item, onClick, __menuScope }) => {
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
- }
113
+ const action = item;
114
+ const handleClick = useCallback((event) => onClick(action, event), [
115
+ action,
116
+ onClick
117
+ ]);
118
+ const { iconSize } = useMenuScoped("DropdownMenuItem", __menuScope);
119
+ return /* @__PURE__ */ React2.createElement(NaturalDropdownMenu.Item, {
120
+ onClick: handleClick,
121
+ classNames: "gap-2",
122
+ disabled: action.properties?.disabled,
123
+ ...action.properties?.testId && {
124
+ "data-testid": action.properties.testId
125
+ }
126
+ }, action.properties?.icon && /* @__PURE__ */ React2.createElement(Icon, {
127
+ icon: action.properties.icon,
128
+ size: iconSize
129
+ }), /* @__PURE__ */ React2.createElement(ActionLabel, {
130
+ action
131
+ }));
163
132
  };
164
133
  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;
175
- }
176
- event.stopPropagation();
177
- setOptionsMenuOpen(false);
178
- void action.data?.({
134
+ const [optionsMenuOpen, setOptionsMenuOpen] = useControllableState({
135
+ prop: open,
136
+ defaultProp: defaultOpen,
137
+ onChange: onOpenChange
138
+ });
139
+ const { onAction } = useMenuScoped("DropdownMenuRoot", __menuScope);
140
+ const handleActionClick = useCallback((action, event) => {
141
+ if (action.properties?.disabled) {
142
+ return;
143
+ }
144
+ event.stopPropagation();
145
+ setOptionsMenuOpen(false);
146
+ if (onAction) {
147
+ onAction(action, {
179
148
  parent: group,
180
149
  caller
181
150
  });
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
- }
151
+ } else {
152
+ void executeMenuAction(action, {
153
+ parent: group,
154
+ caller
155
+ });
156
+ }
157
+ }, [
158
+ group,
159
+ caller,
160
+ onAction
161
+ ]);
162
+ const items = useMenuItems(group, propsItems);
163
+ return /* @__PURE__ */ React2.createElement(NaturalDropdownMenu.Root, {
164
+ open: optionsMenuOpen,
165
+ onOpenChange: setOptionsMenuOpen,
166
+ ...naturalProps
167
+ }, children, /* @__PURE__ */ React2.createElement(NaturalDropdownMenu.Portal, null, /* @__PURE__ */ React2.createElement(NaturalDropdownMenu.Content, null, /* @__PURE__ */ React2.createElement(NaturalDropdownMenu.Viewport, null, items?.map((item) => /* @__PURE__ */ React2.createElement(DropdownMenuItem, {
168
+ key: item.id,
169
+ item,
170
+ onClick: handleActionClick
171
+ }))), /* @__PURE__ */ React2.createElement(NaturalDropdownMenu.Arrow, null))));
199
172
  };
200
173
  var DropdownMenu = {
201
174
  Root: DropdownMenuRoot,
@@ -204,320 +177,436 @@ var DropdownMenu = {
204
177
  };
205
178
 
206
179
  // src/components/ToolbarMenu.tsx
207
- import { useSignals as _useSignals4 } from "@preact-signals/safe-react/tracking";
208
- import React4, { Fragment, useCallback as useCallback2 } from "react";
209
- import { Icon as Icon2, Toolbar as NaturalToolbar, useTranslation as useTranslation2 } from "@dxos/react-ui";
210
- import { useAttention } from "@dxos/react-ui-attention";
211
- import { mx as mx2, textBlockWidth, toolbarLayout } from "@dxos/react-ui-theme";
212
-
213
- // src/types.ts
214
- import { ACTION_GROUP_TYPE as ACTION_GROUP_TYPE2 } from "@dxos/app-graph";
215
- var MenuSeparatorType = "@dxos/react-ui-toolbar/separator";
216
- var isSeparator = (node) => node.type === MenuSeparatorType;
217
- var isMenuGroup = (node) => node.type === ACTION_GROUP_TYPE2;
218
-
219
- // src/components/ToolbarMenu.tsx
220
- var ActionToolbarItem = ({ action, __menuScope }) => {
221
- var _effect = _useSignals4();
222
- try {
223
- const { iconSize } = useMenu("ActionToolbarItem", __menuScope);
224
- const { t } = useTranslation2(translationKey);
225
- const handleClick = useCallback2(() => action.data?.(), [
226
- action
227
- ]);
228
- const { icon, iconOnly = true, disabled, testId, hidden, classNames } = action.properties;
229
- const Root = icon ? NaturalToolbar.IconButton : NaturalToolbar.Button;
230
- const rootProps = icon ? {
231
- icon,
232
- size: iconSize,
233
- iconOnly,
234
- label: actionLabel(action, t)
235
- } : {
236
- children: /* @__PURE__ */ React4.createElement(ActionLabel, {
237
- action
238
- })
239
- };
240
- return hidden ? null : /* @__PURE__ */ React4.createElement(Root, {
241
- key: action.id,
242
- disabled,
243
- onClick: handleClick,
244
- variant: "ghost",
245
- ...testId && {
246
- "data-testid": testId
247
- },
248
- ...rootProps,
249
- classNames
250
- });
251
- } finally {
252
- _effect.f();
180
+ var ActionToolbarItem = ({ __menuScope, action }) => {
181
+ const { iconSize, onAction } = useMenuScoped("ActionToolbarItem", __menuScope);
182
+ const { t } = useTranslation2(translationKey2);
183
+ const { icon, iconOnly = true, disabled, testId, hidden, classNames } = action.properties;
184
+ const buttonVariant = action.properties.variant === "primary" ? "primary" : "ghost";
185
+ const handleClick = useCallback2(() => {
186
+ if (onAction) {
187
+ onAction(action, {});
188
+ } else {
189
+ void executeMenuAction(action);
190
+ }
191
+ }, [
192
+ action,
193
+ onAction
194
+ ]);
195
+ const commonProps = {
196
+ variant: buttonVariant,
197
+ disabled,
198
+ classNames,
199
+ onClick: handleClick,
200
+ ...testId && {
201
+ "data-testid": testId
202
+ }
203
+ };
204
+ if (hidden) {
205
+ return null;
253
206
  }
207
+ return icon ? /* @__PURE__ */ React3.createElement(NaturalToolbar.IconButton, {
208
+ key: action.id,
209
+ ...commonProps,
210
+ icon,
211
+ size: iconSize,
212
+ iconOnly,
213
+ label: actionLabel(action, t)
214
+ }) : /* @__PURE__ */ React3.createElement(NaturalToolbar.Button, {
215
+ key: action.id,
216
+ ...commonProps
217
+ }, /* @__PURE__ */ React3.createElement(ActionLabel, {
218
+ action
219
+ }));
220
+ };
221
+ var DropdownMenuToolbarItem = ({ __menuScope, group, items: propsItems }) => {
222
+ const { iconOnly, disabled, testId } = group.properties;
223
+ const { t } = useTranslation2(translationKey2);
224
+ const { iconSize } = useMenuScoped("DropdownMenuToolbarItem", __menuScope);
225
+ const items = useMenuItems(group, propsItems, "DropdownMenuToolbarItem", __menuScope);
226
+ const activeItem = items?.find((item) => !!item.properties.checked);
227
+ const icon = group.properties.applyActive && // TODO(thure): Handle other menu item types.
228
+ activeItem?.properties.icon || group.properties.icon;
229
+ const Root = icon ? NaturalToolbar.IconButton : NaturalToolbar.Button;
230
+ const labelAction = group.properties.applyActive && activeItem ? activeItem : group;
231
+ const rootProps = icon ? {
232
+ icon,
233
+ size: iconSize,
234
+ iconOnly,
235
+ label: actionLabel(labelAction, t),
236
+ caretDown: true
237
+ } : {
238
+ children: /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(ActionLabel, {
239
+ action: labelAction
240
+ }), /* @__PURE__ */ React3.createElement(Icon2, {
241
+ size: 3,
242
+ icon: "ph--caret-down--bold",
243
+ classNames: "ms-1"
244
+ }))
245
+ };
246
+ return /* @__PURE__ */ React3.createElement(DropdownMenu.Root, {
247
+ group,
248
+ items
249
+ }, /* @__PURE__ */ React3.createElement(DropdownMenu.Trigger, {
250
+ asChild: true
251
+ }, /* @__PURE__ */ React3.createElement(Root, {
252
+ variant: "ghost",
253
+ disabled,
254
+ ...rootProps,
255
+ ...testId && {
256
+ "data-testid": testId
257
+ }
258
+ })));
254
259
  };
255
- var DropdownMenuToolbarItem = ({ group, items: propsItems, __menuScope }) => {
256
- var _effect = _useSignals4();
257
- try {
258
- const { iconOnly, disabled, testId } = group.properties;
259
- const { t } = useTranslation2(translationKey);
260
- const { iconSize } = useMenu("DropdownMenuToolbarItem", __menuScope);
261
- const items = useMenuItems(group, propsItems, "DropdownMenuToolbarItem", __menuScope);
262
- const activeItem = items?.find((item) => !!item.properties.checked);
263
- const icon = group.properties.applyActive && // TODO(thure): Handle other menu item types.
264
- activeItem?.properties.icon || group.properties.icon;
265
- const Root = icon ? NaturalToolbar.IconButton : NaturalToolbar.Button;
266
- const labelAction = group.properties.applyActive && activeItem ? activeItem : group;
267
- const rootProps = icon ? {
268
- icon,
269
- size: iconSize,
270
- iconOnly,
271
- label: actionLabel(labelAction, t),
272
- caretDown: true
273
- } : {
274
- children: /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement(ActionLabel, {
275
- action: labelAction
276
- }), /* @__PURE__ */ React4.createElement(Icon2, {
277
- size: 3,
278
- icon: "ph--caret-down--bold",
279
- classNames: "mis-1"
280
- }))
281
- };
282
- return /* @__PURE__ */ React4.createElement(DropdownMenu.Root, {
283
- group,
284
- items
285
- }, /* @__PURE__ */ React4.createElement(DropdownMenu.Trigger, {
286
- asChild: true
287
- }, /* @__PURE__ */ React4.createElement(Root, {
288
- variant: "ghost",
289
- disabled,
290
- ...rootProps,
291
- ...testId && {
292
- "data-testid": testId
293
- }
294
- })));
295
- } finally {
296
- _effect.f();
260
+ var ToggleGroupItem = ({ __menuScope, group, action }) => {
261
+ const { iconSize, onAction } = useMenuScoped("ToggleGroupItem", __menuScope);
262
+ const { t } = useTranslation2(translationKey2);
263
+ const { icon, iconOnly = true, disabled, testId, hidden, classNames } = action.properties;
264
+ const handleClick = useCallback2(() => {
265
+ if (onAction) {
266
+ onAction(action, {
267
+ parent: group
268
+ });
269
+ } else {
270
+ void executeMenuAction(action, {
271
+ parent: group
272
+ });
273
+ }
274
+ }, [
275
+ action,
276
+ group,
277
+ onAction
278
+ ]);
279
+ const commonProps = {
280
+ value: action.id,
281
+ disabled,
282
+ variant: "ghost",
283
+ classNames,
284
+ onClick: handleClick,
285
+ ...testId && {
286
+ "data-testid": testId
287
+ }
288
+ };
289
+ return hidden ? null : icon ? /* @__PURE__ */ React3.createElement(NaturalToolbar.ToggleGroupIconItem, {
290
+ ...commonProps,
291
+ icon,
292
+ size: iconSize,
293
+ iconOnly,
294
+ label: actionLabel(action, t)
295
+ }) : /* @__PURE__ */ React3.createElement(NaturalToolbar.ToggleGroupItem, commonProps, /* @__PURE__ */ React3.createElement(ActionLabel, {
296
+ action
297
+ }));
298
+ };
299
+ var ToggleGroupToolbarItem = ({ __menuScope, group, items: itemsProp }) => {
300
+ const items = useMenuItems(group, itemsProp, "ToggleGroupToolbarItem", __menuScope);
301
+ const { selectCardinality } = group.properties;
302
+ const children = items.map((action) => /* @__PURE__ */ React3.createElement(ToggleGroupItem, {
303
+ key: action.id,
304
+ group,
305
+ action
306
+ }));
307
+ if (selectCardinality === "multiple") {
308
+ return /* @__PURE__ */ React3.createElement(NaturalToolbar.ToggleGroup, {
309
+ type: "multiple",
310
+ value: group.properties.value
311
+ }, children);
312
+ } else {
313
+ return /* @__PURE__ */ React3.createElement(NaturalToolbar.ToggleGroup, {
314
+ type: "single",
315
+ value: group.properties.value
316
+ }, children);
297
317
  }
298
318
  };
299
- var ToggleGroupItem = ({ group, action, __menuScope }) => {
300
- var _effect = _useSignals4();
301
- try {
302
- const { iconSize } = useMenu("ToggleGroupItem", __menuScope);
303
- const { t } = useTranslation2(translationKey);
304
- const { icon, iconOnly = true, disabled, testId, hidden, classNames } = action.properties;
305
- const handleClick = useCallback2(() => action.data?.({
306
- parent: group
307
- }), [
308
- action,
309
- group
310
- ]);
311
- const Root = icon ? NaturalToolbar.ToggleGroupIconItem : NaturalToolbar.ToggleGroupItem;
312
- const rootProps = icon ? {
313
- icon,
314
- size: iconSize,
315
- iconOnly,
316
- label: actionLabel(action, t)
317
- } : {
318
- children: /* @__PURE__ */ React4.createElement(ActionLabel, {
319
- action
320
- })
321
- };
322
- return hidden ? null : /* @__PURE__ */ React4.createElement(Root, {
323
- key: action.id,
324
- value: action.id,
325
- disabled,
326
- onClick: handleClick,
327
- variant: "ghost",
328
- ...testId && {
329
- "data-testid": testId
330
- },
331
- ...rootProps,
332
- classNames
319
+ var ToolbarMenu = composable(({ __menuScope, children, ...props }, forwardedRef) => {
320
+ const items = useMenuItems(void 0, void 0, "ToolbarMenu", __menuScope);
321
+ const { attendableId, alwaysActive } = useMenuScoped("ToolbarMenu", __menuScope);
322
+ const { hasAttention } = useAttention(attendableId);
323
+ return /* @__PURE__ */ React3.createElement(NaturalToolbar.Root, {
324
+ ...composableProps(props, {
325
+ classNames: attendableId
326
+ }),
327
+ disabled: !alwaysActive && !hasAttention,
328
+ ref: forwardedRef
329
+ }, items?.map((item) => /* @__PURE__ */ React3.createElement(ToolbarMenuItem, {
330
+ key: item.id,
331
+ __menuScope,
332
+ item
333
+ })), children);
334
+ });
335
+ var ToolbarMenuItem = ({ __menuScope, item }) => {
336
+ if (isSeparator(item)) {
337
+ return /* @__PURE__ */ React3.createElement(NaturalToolbar.Separator, {
338
+ variant: item.properties.variant
333
339
  });
334
- } finally {
335
- _effect.f();
336
340
  }
341
+ if (isMenuGroup(item)) {
342
+ if (item.properties.variant === "dropdownMenu") {
343
+ return /* @__PURE__ */ React3.createElement(DropdownMenuToolbarItem, {
344
+ __menuScope,
345
+ group: item
346
+ });
347
+ } else {
348
+ return /* @__PURE__ */ React3.createElement(ToggleGroupToolbarItem, {
349
+ __menuScope,
350
+ group: item
351
+ });
352
+ }
353
+ }
354
+ return /* @__PURE__ */ React3.createElement(ActionToolbarItem, {
355
+ __menuScope,
356
+ action: item
357
+ });
337
358
  };
338
- var ToggleGroupToolbarItem = ({ group, items: propsItems, __menuScope }) => {
339
- var _effect = _useSignals4();
340
- try {
341
- const items = useMenuItems(group, propsItems, "ToggleGroupToolbarItem", __menuScope);
342
- const { selectCardinality, value } = group.properties;
343
- return (
344
- // TODO(thure): Fix.
345
- // @ts-ignore
346
- /* @__PURE__ */ React4.createElement(
347
- NaturalToolbar.ToggleGroup,
348
- {
349
- type: selectCardinality,
350
- value
351
- },
352
- // TODO(thure): Handle other menu item types.
353
- items.map((action) => /* @__PURE__ */ React4.createElement(ToggleGroupItem, {
354
- key: action.id,
355
- group,
356
- action
357
- }))
358
- )
359
- );
360
- } finally {
361
- _effect.f();
359
+
360
+ // src/components/Menu.tsx
361
+ var __dxlog_file = "/__w/dxos/dxos/packages/ui/react-ui-menu/src/components/Menu.tsx";
362
+ var MENU_NAME = "Menu";
363
+ var [createMenuContext, createMenuScope] = createContextScope(MENU_NAME, []);
364
+ var nullItemsAtom = Atom.make(null);
365
+ var defaultItemsAccessor = () => nullItemsAtom;
366
+ var menuContextDefaults = {
367
+ iconSize: 5,
368
+ items: defaultItemsAccessor,
369
+ onAction: void 0,
370
+ menuItemsAtom: Atom.make(/* @__PURE__ */ new Map()),
371
+ addMenuItems: () => {
372
+ },
373
+ removeMenuItems: () => {
362
374
  }
363
375
  };
364
- var ToolbarMenu = ({ __menuScope, classNames, textBlockWidth: wrapContents, ...props }) => {
365
- var _effect = _useSignals4();
366
- try {
367
- const items = useMenuItems(void 0, void 0, "ToolbarMenu", __menuScope);
368
- const { attendableId } = useMenu("ToolbarMenu", __menuScope);
369
- const { hasAttention } = useAttention(attendableId);
370
- const InnerRoot = wrapContents ? "div" : Fragment;
371
- const innerRootProps = wrapContents ? {
372
- role: "none",
373
- className: mx2(textBlockWidth, toolbarLayout, "bs-full")
374
- } : {};
375
- return /* @__PURE__ */ React4.createElement(NaturalToolbar.Root, {
376
- ...props,
377
- layoutManaged: wrapContents,
378
- classNames: [
379
- attendableId && !hasAttention && "*:opacity-20 !bg-transparent",
380
- classNames
381
- ]
382
- }, /* @__PURE__ */ React4.createElement(InnerRoot, innerRootProps, items?.map((item, i) => /* @__PURE__ */ React4.createElement(ToolbarMenuItem, {
383
- key: item.id ?? i,
384
- item
385
- }))));
386
- } finally {
387
- _effect.f();
376
+ var [MenuContextProvider, useMenuScoped] = createMenuContext(MENU_NAME, menuContextDefaults);
377
+ var useMenuScope = createMenuScope();
378
+ var MenuDropdownContext = /* @__PURE__ */ createContext({
379
+ closeMenu: () => {
388
380
  }
381
+ });
382
+ var DEFAULT_PRIORITY = 100;
383
+ var sortMenuItems = (items) => [
384
+ ...items
385
+ ].sort((a, b) => {
386
+ if (a.priority !== b.priority) {
387
+ return a.priority - b.priority;
388
+ }
389
+ return a.id.localeCompare(b.id);
390
+ });
391
+ var MenuProvider = ({ children, items = menuContextDefaults.items, iconSize = menuContextDefaults.iconSize, attendableId, alwaysActive, onAction }) => {
392
+ const { scope } = useMenuScope(void 0);
393
+ const registry = useContext(RegistryContext);
394
+ const menuItemsAtom = useMemo(() => Atom.make(/* @__PURE__ */ new Map()).pipe(Atom.keepAlive), []);
395
+ const addMenuItems = useCallback3((props) => {
396
+ const priority = props.priority ?? DEFAULT_PRIORITY;
397
+ const prev = registry.get(menuItemsAtom);
398
+ const next = new Map(prev);
399
+ next.set(props.id, {
400
+ ...props,
401
+ priority
402
+ });
403
+ registry.set(menuItemsAtom, next);
404
+ }, [
405
+ registry,
406
+ menuItemsAtom
407
+ ]);
408
+ const removeMenuItems = useCallback3((id) => {
409
+ const prev = registry.get(menuItemsAtom);
410
+ const next = new Map(prev);
411
+ next.delete(id);
412
+ registry.set(menuItemsAtom, next);
413
+ }, [
414
+ registry,
415
+ menuItemsAtom
416
+ ]);
417
+ return /* @__PURE__ */ React4.createElement(MenuContextProvider, {
418
+ items,
419
+ iconSize,
420
+ attendableId,
421
+ alwaysActive,
422
+ menuItemsAtom,
423
+ addMenuItems,
424
+ removeMenuItems,
425
+ onAction,
426
+ scope
427
+ }, children);
389
428
  };
390
- var ToolbarMenuItem = ({ item }) => {
391
- var _effect = _useSignals4();
392
- try {
393
- if (isSeparator(item)) {
394
- return /* @__PURE__ */ React4.createElement(NaturalToolbar.Separator, {
395
- variant: item.properties.variant
396
- });
397
- }
398
- if (isMenuGroup(item)) {
399
- if (item.properties.variant === "dropdownMenu") {
400
- return /* @__PURE__ */ React4.createElement(DropdownMenuToolbarItem, {
401
- group: item
402
- });
403
- } else {
404
- return /* @__PURE__ */ React4.createElement(ToggleGroupToolbarItem, {
405
- group: item
406
- });
407
- }
429
+ var resolveItems = (baseItems, group, entries) => {
430
+ const applicable = [
431
+ ...entries.values()
432
+ ].filter((entry) => !entry.groupFilter || entry.groupFilter(group));
433
+ if (applicable.length === 0) {
434
+ return baseItems;
435
+ }
436
+ const sorted = sortMenuItems(applicable);
437
+ const replacements = sorted.filter((entry) => entry.mode === "replacement");
438
+ if (replacements.length > 0) {
439
+ if (replacements.length > 1) {
440
+ log.warn("multiple replacement entries found", {
441
+ ids: replacements.map((r) => r.id).join(", "),
442
+ using: replacements[0].id
443
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 94, S: void 0 });
408
444
  }
409
- return /* @__PURE__ */ React4.createElement(ActionToolbarItem, {
410
- action: item
411
- });
412
- } finally {
413
- _effect.f();
445
+ return replacements[0].items;
446
+ }
447
+ const additive = sorted.filter((entry) => entry.mode === "additive");
448
+ const additiveItems = additive.flatMap((entry) => entry.items);
449
+ if (!baseItems || baseItems.length === 0) {
450
+ return additiveItems.length > 0 ? additiveItems : null;
414
451
  }
452
+ return [
453
+ ...baseItems,
454
+ ...additiveItems
455
+ ];
415
456
  };
416
-
417
- // src/hooks/useMenuActions.ts
418
- import { RegistryContext, useRxValue } from "@effect-rx/rx-react";
419
- import { useCallback as useCallback3, useContext, useEffect, useState } from "react";
420
- import { Graph, ROOT_ID } from "@dxos/app-graph";
421
- var edgesArrayToRecord = (edges) => {
422
- return Object.fromEntries(Object.entries(edges.reduce((acc, { source, target }) => {
423
- if (!acc[source]) {
424
- acc[source] = {
425
- inbound: [],
426
- outbound: []
427
- };
457
+ var useMenuItems = (group, propsItems, consumerName = "useMenuItemConsumer", __menuScope) => {
458
+ const { items, menuItemsAtom } = useMenuScoped(consumerName, __menuScope);
459
+ const groupItems = useAtomValue(items(group));
460
+ const entries = useAtomValue(menuItemsAtom) ?? /* @__PURE__ */ new Map();
461
+ const baseItems = useMemo(() => propsItems ?? groupItems ?? null, [
462
+ propsItems,
463
+ groupItems
464
+ ]);
465
+ const resolved = useMemo(() => resolveItems(baseItems, group, entries), [
466
+ baseItems,
467
+ group,
468
+ entries
469
+ ]);
470
+ return resolved ?? void 0;
471
+ };
472
+ var useMenu = (consumerName) => {
473
+ return useMenuScoped(consumerName, void 0);
474
+ };
475
+ var MenuRoot = ({ children, open, defaultOpen, onOpenChange, caller, ...props }) => {
476
+ const [menuOpen, setMenuOpen] = useControllableState2({
477
+ prop: open,
478
+ defaultProp: defaultOpen,
479
+ onChange: onOpenChange
480
+ });
481
+ const closeMenu = useCallback3(() => setMenuOpen(false), [
482
+ setMenuOpen
483
+ ]);
484
+ return /* @__PURE__ */ React4.createElement(MenuProvider, props, /* @__PURE__ */ React4.createElement(MenuDropdownContext.Provider, {
485
+ value: {
486
+ closeMenu,
487
+ caller
428
488
  }
429
- if (!acc[target]) {
430
- acc[target] = {
431
- inbound: [],
432
- outbound: []
433
- };
489
+ }, /* @__PURE__ */ React4.createElement(NaturalDropdownMenu2.Root, {
490
+ open: menuOpen,
491
+ onOpenChange: setMenuOpen
492
+ }, children)));
493
+ };
494
+ var MenuContentItem = ({ item, onClick, __menuScope }) => {
495
+ const action = item;
496
+ const handleClick = useCallback3((event) => onClick(action, event), [
497
+ action,
498
+ onClick
499
+ ]);
500
+ const { iconSize } = useMenuScoped("MenuContentItem", __menuScope);
501
+ return /* @__PURE__ */ React4.createElement(NaturalDropdownMenu2.Item, {
502
+ onClick: handleClick,
503
+ classNames: "gap-2",
504
+ disabled: action.properties?.disabled,
505
+ ...action.properties?.testId && {
506
+ "data-testid": action.properties.testId
434
507
  }
435
- const sourceEdges = acc[source];
436
- if (!sourceEdges.outbound.includes(target)) {
437
- sourceEdges.outbound.push(target);
508
+ }, action.properties?.icon && /* @__PURE__ */ React4.createElement(Icon3, {
509
+ icon: action.properties.icon,
510
+ size: iconSize
511
+ }), /* @__PURE__ */ React4.createElement(ActionLabel, {
512
+ action
513
+ }));
514
+ };
515
+ var MenuContent = ({ group, items: propsItems, caller: callerOverride, __menuScope }) => {
516
+ const { closeMenu, caller: contextCaller } = useContext(MenuDropdownContext);
517
+ const caller = callerOverride ?? contextCaller;
518
+ const { onAction } = useMenuScoped("MenuContent", __menuScope);
519
+ const resolvedItems = useMenuItems(group, propsItems, "MenuContent", __menuScope);
520
+ const handleActionClick = useCallback3((action, event) => {
521
+ if (action.properties?.disabled) {
522
+ return;
438
523
  }
439
- const targetEdges = acc[target];
440
- if (!targetEdges.inbound.includes(source)) {
441
- targetEdges.inbound.push(source);
524
+ event.stopPropagation();
525
+ closeMenu();
526
+ if (onAction) {
527
+ onAction(action, {
528
+ parent: group,
529
+ caller
530
+ });
531
+ } else {
532
+ void executeMenuAction(action, {
533
+ parent: group,
534
+ caller
535
+ });
442
536
  }
443
- return acc;
444
- }, {})));
537
+ }, [
538
+ group,
539
+ caller,
540
+ onAction,
541
+ closeMenu
542
+ ]);
543
+ return /* @__PURE__ */ React4.createElement(NaturalDropdownMenu2.Portal, null, /* @__PURE__ */ React4.createElement(NaturalDropdownMenu2.Content, null, /* @__PURE__ */ React4.createElement(NaturalDropdownMenu2.Viewport, null, resolvedItems?.map((item) => /* @__PURE__ */ React4.createElement(MenuContentItem, {
544
+ key: item.id,
545
+ item,
546
+ onClick: handleActionClick
547
+ }))), /* @__PURE__ */ React4.createElement(NaturalDropdownMenu2.Arrow, null)));
548
+ };
549
+ var Menu = {
550
+ Root: MenuRoot,
551
+ Trigger: NaturalDropdownMenu2.Trigger,
552
+ Content: MenuContent,
553
+ VirtualTrigger: NaturalDropdownMenu2.VirtualTrigger,
554
+ Toolbar: ToolbarMenu
445
555
  };
556
+
557
+ // src/hooks/useMenuActions.ts
558
+ import { RegistryContext as RegistryContext2, useAtomValue as useAtomValue2 } from "@effect-atom/atom-react";
559
+ import { useCallback as useCallback4, useContext as useContext2, useMemo as useMemo2 } from "react";
560
+ import { Graph, Node as Node3 } from "@dxos/app-graph";
446
561
  var useMenuActions = (props) => {
447
- const registry = useContext(RegistryContext);
448
- const menuGraphProps = useRxValue(props);
449
- const [graph] = useState(new Graph({
450
- registry,
451
- nodes: menuGraphProps.nodes,
452
- edges: edgesArrayToRecord(menuGraphProps.edges)
453
- }));
454
- useEffect(() => {
455
- graph.addNodes(menuGraphProps.nodes);
456
- graph.addEdges(menuGraphProps.edges);
562
+ const registry = useContext2(RegistryContext2);
563
+ const menuGraphProps = useAtomValue2(props);
564
+ const graph = useMemo2(() => {
565
+ const newGraph = Graph.make({
566
+ registry
567
+ });
568
+ newGraph.pipe(Graph.addNodes(menuGraphProps.nodes), Graph.addEdges(menuGraphProps.edges));
569
+ return newGraph;
457
570
  }, [
571
+ registry,
458
572
  menuGraphProps
459
573
  ]);
460
- const useGroupItems = useCallback3((sourceNode) => {
461
- const items = useRxValue(graph.connections(sourceNode?.id || ROOT_ID));
462
- return items;
574
+ const items = useCallback4((group) => {
575
+ return graph.connections(group?.id || Node3.RootId, "child");
463
576
  }, [
464
577
  graph
465
578
  ]);
466
579
  return {
467
- useGroupItems
580
+ items
468
581
  };
469
582
  };
470
583
 
471
584
  // src/builder.ts
472
585
  import { invariant } from "@dxos/invariant";
473
- function _define_property(obj, key, value) {
474
- if (key in obj) {
475
- Object.defineProperty(obj, key, {
476
- value,
477
- enumerable: true,
478
- configurable: true,
479
- writable: true
480
- });
481
- } else {
482
- obj[key] = value;
483
- }
484
- return obj;
485
- }
486
- var __dxlog_file = "/__w/dxos/dxos/packages/ui/react-ui-menu/src/builder.ts";
487
- var MenuBuilder = Object.freeze({
488
- make: () => new MenuBuilderImpl({
489
- nodes: [],
490
- edges: []
491
- }, "root")
492
- });
586
+ var __dxlog_file2 = "/__w/dxos/dxos/packages/ui/react-ui-menu/src/builder.ts";
493
587
  var MenuBuilderImpl = class _MenuBuilderImpl {
588
+ _data;
589
+ _rootId;
590
+ _separatorCount = 0;
591
+ constructor(_data, _rootId) {
592
+ this._data = _data;
593
+ this._rootId = _rootId;
594
+ }
494
595
  root(props) {
495
- invariant(this._rootId === "root", "Root group can only be at the top level", {
496
- F: __dxlog_file,
497
- L: 36,
498
- S: this,
499
- A: [
500
- "this._rootId === 'root'",
501
- "'Root group can only be at the top level'"
502
- ]
503
- });
504
- invariant(this._data.nodes.find((node) => node.id === "root") === void 0, "Root group can only be created once", {
505
- F: __dxlog_file,
506
- L: 37,
507
- S: this,
508
- A: [
509
- "this._data.nodes.find((node) => node.id === 'root') === undefined",
510
- "'Root group can only be created once'"
511
- ]
512
- });
596
+ invariant(this._rootId === "root", "Root group can only be at the top level", { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 16, S: this, A: ["this._rootId === 'root'", "'Root group can only be at the top level'"] });
597
+ invariant(this._data.nodes.find((node) => node.id === "root") === void 0, "Root group can only be created once", { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 17, S: this, A: ["this._data.nodes.find((node)=>node.id === 'root') === undefined", "'Root group can only be created once'"] });
513
598
  this._data.nodes.push(createMenuItemGroup("root", props));
514
599
  return this;
515
600
  }
601
+ build() {
602
+ return this._data;
603
+ }
516
604
  action(id, props, invoke) {
517
605
  this._data.nodes.push(createMenuAction(id, invoke, props));
518
606
  this._data.edges.push({
519
607
  source: this._rootId,
520
- target: id
608
+ target: id,
609
+ relation: "child"
521
610
  });
522
611
  return this;
523
612
  }
@@ -525,38 +614,62 @@ var MenuBuilderImpl = class _MenuBuilderImpl {
525
614
  this._data.nodes.push(createMenuItemGroup(id, props));
526
615
  this._data.edges.push({
527
616
  source: this._rootId,
528
- target: id
617
+ target: id,
618
+ relation: "child"
529
619
  });
530
620
  cb(new _MenuBuilderImpl(this._data, id));
531
621
  return this;
532
622
  }
533
- build() {
534
- return this._data;
623
+ subgraph(subgraphOrCb) {
624
+ if (!subgraphOrCb) {
625
+ return this;
626
+ }
627
+ if (typeof subgraphOrCb === "function") {
628
+ subgraphOrCb(new _MenuBuilderImpl(this._data, this._rootId));
629
+ } else {
630
+ this._data.nodes.push(...subgraphOrCb.nodes);
631
+ this._data.edges.push(...subgraphOrCb.edges);
632
+ }
633
+ return this;
535
634
  }
536
- constructor(_data, _rootId) {
537
- _define_property(this, "_data", void 0);
538
- _define_property(this, "_rootId", void 0);
539
- this._data = _data;
540
- this._rootId = _rootId;
635
+ separator(variant = "gap") {
636
+ const id = `separator-${++this._separatorCount}`;
637
+ this._data.nodes.push({
638
+ id,
639
+ type: MenuSeparatorType,
640
+ properties: {
641
+ variant
642
+ },
643
+ data: void 0
644
+ });
645
+ this._data.edges.push({
646
+ source: this._rootId,
647
+ target: id,
648
+ relation: "child"
649
+ });
650
+ return this;
541
651
  }
542
652
  };
653
+ var MenuBuilder = Object.freeze({
654
+ make: () => new MenuBuilderImpl({
655
+ nodes: [],
656
+ edges: []
657
+ }, "root")
658
+ });
543
659
  export {
544
- DropdownMenu,
660
+ Menu,
545
661
  MenuBuilder,
546
- MenuProvider,
547
662
  MenuSeparatorType,
548
- ToolbarMenu,
549
663
  createGapSeparator,
550
664
  createLineSeparator,
551
665
  createMenuAction,
552
666
  createMenuItemGroup,
553
- createMenuScope,
554
667
  isMenuGroup,
555
668
  isSeparator,
556
669
  menuContextDefaults,
557
- rxFromSignal,
558
670
  useMenu,
559
671
  useMenuActions,
560
- useMenuItems
672
+ useMenuItems,
673
+ useMenuScoped
561
674
  };
562
675
  //# sourceMappingURL=index.mjs.map