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