@dxos/react-ui-menu 0.8.4-main.f5c0578 → 0.8.4-main.fcfe5033a5

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