@dxos/react-ui-menu 0.8.4-main.406dc2a → 0.8.4-main.422d1c7879

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