@dxos/react-ui-menu 0.8.2-main.fbd8ed0 → 0.8.2-staging.7ac8446

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 (51) hide show
  1. package/dist/lib/browser/index.mjs +63 -58
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/node/index.cjs +58 -53
  5. package/dist/lib/node/index.cjs.map +4 -4
  6. package/dist/lib/node/meta.json +1 -1
  7. package/dist/lib/node-esm/index.mjs +63 -58
  8. package/dist/lib/node-esm/index.mjs.map +4 -4
  9. package/dist/lib/node-esm/meta.json +1 -1
  10. package/dist/types/src/components/ActionLabel.d.ts +4 -8
  11. package/dist/types/src/components/ActionLabel.d.ts.map +1 -1
  12. package/dist/types/src/components/DropdownMenu.d.ts +2 -3
  13. package/dist/types/src/components/DropdownMenu.d.ts.map +1 -1
  14. package/dist/types/src/components/MenuContext.d.ts +13 -4
  15. package/dist/types/src/components/MenuContext.d.ts.map +1 -1
  16. package/dist/types/src/components/ToolbarMenu.d.ts +1 -5
  17. package/dist/types/src/components/ToolbarMenu.d.ts.map +1 -1
  18. package/dist/types/src/{types.d.ts → defs.d.ts} +5 -3
  19. package/dist/types/src/defs.d.ts.map +1 -0
  20. package/dist/types/src/hooks.d.ts +17 -0
  21. package/dist/types/src/hooks.d.ts.map +1 -0
  22. package/dist/types/src/index.d.ts +1 -1
  23. package/dist/types/src/index.d.ts.map +1 -1
  24. package/dist/types/src/{components → testing}/Menus.stories.d.ts +1 -1
  25. package/dist/types/src/testing/Menus.stories.d.ts.map +1 -0
  26. package/dist/types/src/testing/index.d.ts +25 -1
  27. package/dist/types/src/testing/index.d.ts.map +1 -1
  28. package/dist/types/src/util.d.ts +2 -2
  29. package/dist/types/src/util.d.ts.map +1 -1
  30. package/dist/types/tsconfig.tsbuildinfo +1 -1
  31. package/package.json +12 -18
  32. package/src/components/ActionLabel.tsx +8 -11
  33. package/src/components/DropdownMenu.tsx +5 -5
  34. package/src/components/MenuContext.tsx +26 -11
  35. package/src/components/ToolbarMenu.tsx +29 -27
  36. package/src/{types.ts → defs.ts} +5 -2
  37. package/src/{hooks/useMenuActions.ts → hooks.ts} +20 -20
  38. package/src/index.ts +1 -1
  39. package/src/{components → testing}/Menus.stories.tsx +13 -13
  40. package/src/testing/index.ts +107 -1
  41. package/src/util.ts +7 -7
  42. package/dist/types/src/components/Menus.stories.d.ts.map +0 -1
  43. package/dist/types/src/hooks/index.d.ts +0 -2
  44. package/dist/types/src/hooks/index.d.ts.map +0 -1
  45. package/dist/types/src/hooks/useMenuActions.d.ts +0 -12
  46. package/dist/types/src/hooks/useMenuActions.d.ts.map +0 -1
  47. package/dist/types/src/testing/generator.d.ts +0 -26
  48. package/dist/types/src/testing/generator.d.ts.map +0 -1
  49. package/dist/types/src/types.d.ts.map +0 -1
  50. package/src/hooks/index.ts +0 -5
  51. package/src/testing/generator.ts +0 -115
@@ -60,7 +60,6 @@ var import_react4 = __toESM(require("react"));
60
60
  var import_react_ui3 = require("@dxos/react-ui");
61
61
  var import_react_ui_attention = require("@dxos/react-ui-attention");
62
62
  var import_app_graph2 = require("@dxos/app-graph");
63
- var import_rx_react = require("@effect-rx/rx-react");
64
63
  var import_signals_react = require("@preact/signals-react");
65
64
  var import_react5 = require("react");
66
65
  var import_app_graph3 = require("@dxos/app-graph");
@@ -75,11 +74,13 @@ var translations_default = [
75
74
  var getShortcut = (action) => {
76
75
  return typeof action.properties?.keyBinding === "string" ? action.properties.keyBinding : action.properties?.keyBinding?.[(0, import_util.getHostPlatform)()];
77
76
  };
78
- var createMenuAction = (id, invoke, properties) => ({
77
+ var noop = () => {
78
+ };
79
+ var createMenuAction = (id, properties) => ({
79
80
  id,
80
81
  type: import_app_graph.ACTION_TYPE,
81
82
  properties,
82
- data: invoke
83
+ data: noop
83
84
  });
84
85
  var createMenuItemGroup = (id, properties) => ({
85
86
  id,
@@ -132,33 +133,32 @@ var ActionLabel = ({ action }) => {
132
133
  className: (0, import_react_ui_theme.mx)("shrink-0", import_react_ui_theme.descriptionText)
133
134
  }, (0, import_keyboard.keySymbols)(shortcut).join("")));
134
135
  };
135
- var actionLabel = (action, t) => {
136
- const shortcut = getShortcut(action);
137
- return `${(0, import_react_ui2.toLocalizedString)(action.properties.label, t)}${shortcut ? ` (${(0, import_keyboard.keySymbols)(shortcut).join("")})` : ""}`;
138
- };
139
136
  var MENU_NAME = "GraphMenu";
140
137
  var [createMenuContext, createMenuScope] = (0, import_react_context.createContextScope)(MENU_NAME, []);
141
138
  var [MenuContextProvider, useMenu] = createMenuContext(MENU_NAME);
142
139
  var menuContextDefaults = {
143
140
  iconSize: 5,
144
- useGroupItems: () => null
141
+ onAction: () => {
142
+ },
143
+ resolveGroupItems: () => null
145
144
  };
146
145
  var useMenuScope = createMenuScope();
147
- var MenuProvider = ({ children, useGroupItems = menuContextDefaults.useGroupItems, iconSize = menuContextDefaults.iconSize, attendableId }) => {
146
+ var MenuProvider = ({ children, resolveGroupItems = menuContextDefaults.resolveGroupItems, onAction = menuContextDefaults.onAction, iconSize = menuContextDefaults.iconSize, attendableId }) => {
148
147
  const { scope } = useMenuScope(void 0);
149
148
  return /* @__PURE__ */ import_react3.default.createElement(MenuContextProvider, {
150
- useGroupItems,
149
+ resolveGroupItems,
150
+ onAction,
151
151
  iconSize,
152
152
  attendableId,
153
153
  scope
154
154
  }, children);
155
155
  };
156
156
  var useMenuItems = (group, propsItems, consumerName = "useMenuItemConsumer", __menuScope) => {
157
- const { useGroupItems } = useMenu(consumerName, __menuScope);
158
- const groupItems = useGroupItems(group);
159
- return (0, import_react3.useMemo)(() => propsItems ?? groupItems ?? void 0, [
157
+ const { resolveGroupItems } = useMenu(consumerName, __menuScope);
158
+ return (0, import_react3.useMemo)(() => propsItems ?? resolveGroupItems?.(group) ?? void 0, [
160
159
  propsItems,
161
- groupItems
160
+ group,
161
+ resolveGroupItems
162
162
  ]);
163
163
  };
164
164
  var DropdownMenuItem = ({ item, onClick, __menuScope }) => {
@@ -182,12 +182,13 @@ var DropdownMenuItem = ({ item, onClick, __menuScope }) => {
182
182
  action
183
183
  }));
184
184
  };
185
- var DropdownMenuRoot = ({ items: propsItems, group, open, defaultOpen, onOpenChange, suppressNextTooltip, caller, children, __menuScope, ...naturalProps }) => {
185
+ var DropdownMenuRoot = ({ items: propsItems, group, open, defaultOpen, onOpenChange, suppressNextTooltip, children, __menuScope, ...naturalProps }) => {
186
186
  const [optionsMenuOpen, setOptionsMenuOpen] = (0, import_react_use_controllable_state.useControllableState)({
187
187
  prop: open,
188
188
  defaultProp: defaultOpen,
189
189
  onChange: onOpenChange
190
190
  });
191
+ const { onAction } = useMenu("DropdownMenuRoot", __menuScope);
191
192
  const handleActionClick = (0, import_react.useCallback)((action, event) => {
192
193
  if (action.properties?.disabled) {
193
194
  return;
@@ -197,14 +198,9 @@ var DropdownMenuRoot = ({ items: propsItems, group, open, defaultOpen, onOpenCha
197
198
  suppressNextTooltip.current = true;
198
199
  }
199
200
  setOptionsMenuOpen(false);
200
- void action.data?.({
201
- parent: group,
202
- caller
203
- });
201
+ onAction?.(action);
204
202
  }, [
205
- suppressNextTooltip,
206
- group,
207
- caller
203
+ onAction
208
204
  ]);
209
205
  const items = useMenuItems(group, propsItems);
210
206
  return /* @__PURE__ */ import_react.default.createElement(import_react_ui.DropdownMenu.Root, {
@@ -231,10 +227,12 @@ var MenuSeparatorType = "@dxos/react-ui-toolbar/separator";
231
227
  var isSeparator = (node) => node.type === MenuSeparatorType;
232
228
  var isMenuGroup = (node) => node.type === import_app_graph2.ACTION_GROUP_TYPE;
233
229
  var ActionToolbarItem = ({ action, __menuScope }) => {
234
- const { iconSize } = useMenu("ActionToolbarItem", __menuScope);
235
- const { t } = (0, import_react_ui3.useTranslation)(translationKey);
236
- const handleClick = (0, import_react4.useCallback)(() => action.data?.(), [
237
- action
230
+ const { onAction, iconSize } = useMenu("ActionToolbarItem", __menuScope);
231
+ const handleClick = (0, import_react4.useCallback)(() => {
232
+ onAction?.(action);
233
+ }, [
234
+ action,
235
+ onAction
238
236
  ]);
239
237
  const { icon, iconOnly = true, disabled, testId, hidden, classNames } = action.properties;
240
238
  const Root = icon ? import_react_ui3.Toolbar.IconButton : import_react_ui3.Toolbar.Button;
@@ -242,7 +240,9 @@ var ActionToolbarItem = ({ action, __menuScope }) => {
242
240
  icon,
243
241
  size: iconSize,
244
242
  iconOnly,
245
- label: actionLabel(action, t)
243
+ label: /* @__PURE__ */ import_react4.default.createElement(ActionLabel, {
244
+ action
245
+ })
246
246
  } : {
247
247
  children: /* @__PURE__ */ import_react4.default.createElement(ActionLabel, {
248
248
  action
@@ -263,25 +263,24 @@ var ActionToolbarItem = ({ action, __menuScope }) => {
263
263
  var DropdownMenuToolbarItem = ({ group, items: propsItems, __menuScope }) => {
264
264
  const { iconOnly, disabled, testId } = group.properties;
265
265
  const suppressNextTooltip = (0, import_react4.useRef)(false);
266
- const { t } = (0, import_react_ui3.useTranslation)(translationKey);
267
266
  const { iconSize } = useMenu("DropdownMenuToolbarItem", __menuScope);
268
267
  const items = useMenuItems(group, propsItems, "DropdownMenuToolbarItem", __menuScope);
269
268
  const activeItem = items?.find((item) => !!item.properties.checked);
270
269
  const icon = group.properties.applyActive && // TODO(thure): Handle other menu item types.
271
270
  activeItem?.properties.icon || group.properties.icon;
272
271
  const Root = icon ? import_react_ui3.Toolbar.IconButton : import_react_ui3.Toolbar.Button;
273
- const labelAction = group.properties.applyActive && activeItem ? activeItem : group;
272
+ const label = /* @__PURE__ */ import_react4.default.createElement(ActionLabel, {
273
+ action: group.properties.applyActive && activeItem ? activeItem : group
274
+ });
274
275
  const rootProps = icon ? {
275
276
  icon,
276
277
  size: iconSize,
277
278
  iconOnly,
278
- label: actionLabel(labelAction, t),
279
+ label,
279
280
  caretDown: true,
280
281
  suppressNextTooltip
281
282
  } : {
282
- children: /* @__PURE__ */ import_react4.default.createElement(import_react4.default.Fragment, null, /* @__PURE__ */ import_react4.default.createElement(ActionLabel, {
283
- action: labelAction
284
- }), /* @__PURE__ */ import_react4.default.createElement(import_react_ui3.Icon, {
283
+ children: /* @__PURE__ */ import_react4.default.createElement(import_react4.default.Fragment, null, label, /* @__PURE__ */ import_react4.default.createElement(import_react_ui3.Icon, {
285
284
  size: 3,
286
285
  icon: "ph--caret-down--bold",
287
286
  classNames: "mis-1"
@@ -302,22 +301,23 @@ var DropdownMenuToolbarItem = ({ group, items: propsItems, __menuScope }) => {
302
301
  }
303
302
  })));
304
303
  };
305
- var ToggleGroupItem = ({ group, action, __menuScope }) => {
306
- const { iconSize } = useMenu("ToggleGroupItem", __menuScope);
307
- const { t } = (0, import_react_ui3.useTranslation)(translationKey);
304
+ var ToggleGroupItem = ({ action, __menuScope }) => {
305
+ const { iconSize, onAction } = useMenu("ToggleGroupItem", __menuScope);
308
306
  const { icon, iconOnly = true, disabled, testId, hidden, classNames } = action.properties;
309
- const handleClick = (0, import_react4.useCallback)(() => action.data?.({
310
- parent: group
311
- }), [
307
+ const handleClick = (0, import_react4.useCallback)(() => {
308
+ onAction?.(action);
309
+ }, [
312
310
  action,
313
- group
311
+ onAction
314
312
  ]);
315
313
  const Root = icon ? import_react_ui3.Toolbar.ToggleGroupIconItem : import_react_ui3.Toolbar.ToggleGroupItem;
316
314
  const rootProps = icon ? {
317
315
  icon,
318
316
  size: iconSize,
319
317
  iconOnly,
320
- label: actionLabel(action, t)
318
+ label: /* @__PURE__ */ import_react4.default.createElement(ActionLabel, {
319
+ action
320
+ })
321
321
  } : {
322
322
  children: /* @__PURE__ */ import_react4.default.createElement(ActionLabel, {
323
323
  action
@@ -351,7 +351,6 @@ var ToggleGroupToolbarItem = ({ group, items: propsItems, __menuScope }) => {
351
351
  // TODO(thure): Handle other menu item types.
352
352
  items.map((action) => /* @__PURE__ */ import_react4.default.createElement(ToggleGroupItem, {
353
353
  key: action.id,
354
- group,
355
354
  action
356
355
  }))
357
356
  )
@@ -364,8 +363,8 @@ var ToolbarMenu = ({ __menuScope, classNames, ...props }) => {
364
363
  return /* @__PURE__ */ import_react4.default.createElement(import_react_ui3.Toolbar.Root, {
365
364
  ...props,
366
365
  classNames: [
367
- "p-1",
368
- !hasAttention && "[&>*]:opacity-20 !bg-transparent",
366
+ "p-0 pointer-fine:p-1 attention-surface",
367
+ !hasAttention && "opacity-20",
369
368
  classNames
370
369
  ]
371
370
  }, items?.map((item, i) => isSeparator(item) ? /* @__PURE__ */ import_react4.default.createElement(import_react_ui3.Toolbar.Separator, {
@@ -414,29 +413,35 @@ var edgesArrayToRecord = (edges) => {
414
413
  targetEdges.inbound.push(source);
415
414
  }
416
415
  return acc;
417
- }, {})));
416
+ }, {})).map(([id, { outbound }]) => [
417
+ id,
418
+ outbound
419
+ ]));
418
420
  };
419
421
  var useMenuActions = (actionCreator) => {
420
- const registry = (0, import_react5.useContext)(import_rx_react.RegistryContext);
421
422
  const initialMenuGraphProps = actionCreator();
422
423
  const [graph] = (0, import_react5.useState)(new import_app_graph3.Graph({
423
- registry,
424
424
  nodes: initialMenuGraphProps.nodes,
425
425
  edges: edgesArrayToRecord(initialMenuGraphProps.edges)
426
426
  }));
427
427
  (0, import_signals_react.useSignalEffect)(() => {
428
428
  const menuGraphProps = actionCreator();
429
- graph.addNodes(menuGraphProps.nodes);
430
- graph.addEdges(menuGraphProps.edges);
429
+ graph._addNodes(menuGraphProps.nodes);
430
+ graph._addEdges(menuGraphProps.edges);
431
431
  });
432
- const useGroupItems = (0, import_react5.useCallback)((sourceNode) => {
433
- const items = (0, import_rx_react.useRxValue)(graph.connections(sourceNode?.id || import_app_graph3.ROOT_ID));
434
- return items;
432
+ const resolveGroupItems = (0, import_react5.useCallback)((sourceNode = graph.root) => {
433
+ if (graph) {
434
+ return graph.nodes(sourceNode, {
435
+ filter: (n) => true
436
+ }) || null;
437
+ } else {
438
+ return null;
439
+ }
435
440
  }, [
436
441
  graph
437
442
  ]);
438
443
  return {
439
- useGroupItems
444
+ resolveGroupItems
440
445
  };
441
446
  };
442
447
  // Annotate the CommonJS export names for ESM import in node:
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../../src/components/DropdownMenu.tsx", "../../../src/components/ActionLabel.tsx", "../../../src/translations.ts", "../../../src/util.ts", "../../../src/components/MenuContext.tsx", "../../../src/components/ToolbarMenu.tsx", "../../../src/types.ts", "../../../src/hooks/useMenuActions.ts"],
4
- "sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport { useControllableState } from '@radix-ui/react-use-controllable-state';\nimport React, { type MouseEvent, type MutableRefObject, useCallback } from 'react';\n\nimport { DropdownMenu as NaturalDropdownMenu, Icon, type DropdownMenuRootProps } from '@dxos/react-ui';\n\nimport { ActionLabel } from './ActionLabel';\nimport { type MenuScopedProps, useMenu, useMenuItems } from './MenuContext';\nimport { type MenuAction, type MenuItem, type MenuItemGroup } from '../types';\n\nexport type DropdownMenuProps = DropdownMenuRootProps & {\n group?: MenuItemGroup;\n items?: MenuItem[];\n suppressNextTooltip?: MutableRefObject<boolean>;\n caller?: string;\n};\n\nconst DropdownMenuItem = ({\n item,\n onClick,\n __menuScope,\n}: MenuScopedProps<{\n item: MenuItem;\n onClick: (action: MenuAction, event: MouseEvent) => void;\n}>) => {\n // TODO(thure): handle other items.\n const action = item as MenuAction;\n const handleClick = useCallback((event: MouseEvent) => onClick(action, event), [action, onClick]);\n const { iconSize } = useMenu('DropdownMenuItem', __menuScope);\n return (\n <NaturalDropdownMenu.Item\n onClick={handleClick}\n classNames='gap-2'\n disabled={action.properties?.disabled}\n {...(action.properties?.testId && { 'data-testid': action.properties.testId })}\n >\n {action.properties?.icon && <Icon icon={action.properties!.icon} size={iconSize} />}\n <ActionLabel action={action} />\n </NaturalDropdownMenu.Item>\n );\n};\n\nconst DropdownMenuRoot = ({\n items: propsItems,\n group,\n open,\n defaultOpen,\n onOpenChange,\n suppressNextTooltip,\n caller,\n children,\n __menuScope,\n ...naturalProps\n}: MenuScopedProps<DropdownMenuProps>) => {\n const [optionsMenuOpen, setOptionsMenuOpen] = useControllableState({\n prop: open,\n defaultProp: defaultOpen,\n onChange: onOpenChange,\n });\n\n const handleActionClick = useCallback(\n (action: MenuAction, event: MouseEvent) => {\n if (action.properties?.disabled) {\n return;\n }\n event.stopPropagation();\n // TODO(thure): Why does Dialog’s modal-ness cause issues if we don’t explicitly close the menu here?\n if (suppressNextTooltip) {\n suppressNextTooltip.current = true;\n }\n setOptionsMenuOpen(false);\n void action.data?.({ parent: group, caller });\n },\n [suppressNextTooltip, group, caller],\n );\n\n const items = useMenuItems(group, propsItems);\n\n return (\n <NaturalDropdownMenu.Root\n {...{\n open: optionsMenuOpen,\n onOpenChange: (nextOpen: boolean) => {\n if (!nextOpen && suppressNextTooltip) {\n suppressNextTooltip.current = true;\n }\n return setOptionsMenuOpen(nextOpen);\n },\n }}\n {...naturalProps}\n >\n {children}\n <NaturalDropdownMenu.Portal>\n <NaturalDropdownMenu.Content>\n <NaturalDropdownMenu.Viewport>\n {items?.map((item) => <DropdownMenuItem key={item.id} item={item} onClick={handleActionClick} />)}\n </NaturalDropdownMenu.Viewport>\n <NaturalDropdownMenu.Arrow />\n </NaturalDropdownMenu.Content>\n </NaturalDropdownMenu.Portal>\n </NaturalDropdownMenu.Root>\n );\n};\n\nexport const DropdownMenu = {\n Root: DropdownMenuRoot,\n Trigger: NaturalDropdownMenu.Trigger,\n VirtualTrigger: NaturalDropdownMenu.VirtualTrigger,\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport React from 'react';\n\nimport { type Action as GraphAction, type ActionGroup } from '@dxos/app-graph';\nimport { keySymbols } from '@dxos/keyboard';\nimport { toLocalizedString, useTranslation, type TFunction } from '@dxos/react-ui';\nimport { mx, descriptionText } from '@dxos/react-ui-theme';\n\nimport { translationKey } from '../translations';\nimport { type MenuActionProperties } from '../types';\nimport { getShortcut } from '../util';\n\ntype Action = GraphAction<MenuActionProperties> | ActionGroup<Omit<MenuActionProperties, 'variant'>>;\n\nexport const ActionLabel = ({ action }: { action: Action }) => {\n const shortcut = getShortcut(action);\n const { t } = useTranslation(translationKey);\n\n return (\n <>\n <span className='grow truncate'>{toLocalizedString(action.properties!.label, t)}</span>\n {shortcut && <span className={mx('shrink-0', descriptionText)}>{keySymbols(shortcut).join('')}</span>}\n </>\n );\n};\n\nexport const actionLabel = (action: Action, t: TFunction) => {\n const shortcut = getShortcut(action);\n return `${toLocalizedString(action.properties!.label, t)}${shortcut ? ` (${keySymbols(shortcut).join('')})` : ''}`;\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nexport const translationKey = 'menus';\n\nexport default [\n {\n 'en-US': {\n [translationKey]: {},\n },\n },\n] as const;\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { ACTION_GROUP_TYPE, ACTION_TYPE, actionGroupSymbol, type ActionLike } from '@dxos/app-graph';\nimport { getHostPlatform } from '@dxos/util';\n\nimport {\n type MenuAction,\n type MenuActionProperties,\n type MenuItemGroup,\n type MenuItemGroupProperties,\n type MenuSeparator,\n} from './types';\n\nexport const getShortcut = (action: ActionLike) => {\n return typeof action.properties?.keyBinding === 'string'\n ? action.properties.keyBinding\n : action.properties?.keyBinding?.[getHostPlatform()];\n};\n\nexport const fallbackIcon = 'ph--placeholder--regular';\n\nexport const createMenuAction = <P extends {} = {}>(\n id: string,\n invoke: () => void,\n properties: P & MenuActionProperties,\n) =>\n ({\n id,\n type: ACTION_TYPE,\n properties,\n data: invoke,\n }) satisfies MenuAction;\n\nexport const createMenuItemGroup = <\n P extends MenuItemGroupProperties = MenuItemGroupProperties & Partial<MenuActionProperties>,\n>(\n id: string,\n properties: P,\n) =>\n ({\n id,\n type: ACTION_GROUP_TYPE,\n properties,\n data: actionGroupSymbol,\n }) satisfies MenuItemGroup;\n\nexport const createGapSeparator = (id: string = 'gap', source: string = 'root') => ({\n nodes: [\n {\n id,\n type: '@dxos/react-ui-toolbar/separator',\n properties: { variant: 'gap' },\n data: undefined as never,\n } satisfies MenuSeparator,\n ],\n edges: [{ source, target: id }],\n});\n\nexport const createLineSeparator = (id: string = 'line', source: string = 'root') => ({\n nodes: [\n {\n id,\n type: '@dxos/react-ui-toolbar/separator',\n properties: { variant: 'line' },\n data: undefined as never,\n } satisfies MenuSeparator,\n ],\n edges: [{ source, target: id }],\n});\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { createContextScope, type Scope } from '@radix-ui/react-context';\nimport React, { type PropsWithChildren, useMemo } from 'react';\n\nimport { type MenuContextValue, type MenuItem, type MenuItemGroup } from '../types';\n\nexport type MenuScopedProps<P> = P & { __menuScope?: Scope };\n\nconst MENU_NAME = 'GraphMenu';\n\nconst [createMenuContext, createMenuScope] = createContextScope(MENU_NAME, []);\n\nconst [MenuContextProvider, useMenu] = createMenuContext<MenuContextValue>(MENU_NAME);\n\nexport const menuContextDefaults: MenuContextValue = {\n iconSize: 5,\n useGroupItems: () => null,\n};\n\nconst useMenuScope = createMenuScope();\n\nconst MenuProvider = ({\n children,\n useGroupItems = menuContextDefaults.useGroupItems,\n iconSize = menuContextDefaults.iconSize,\n attendableId,\n}: PropsWithChildren<Partial<MenuContextValue>>) => {\n const { scope } = useMenuScope(undefined);\n return (\n <MenuContextProvider useGroupItems={useGroupItems} iconSize={iconSize} attendableId={attendableId} scope={scope}>\n {children}\n </MenuContextProvider>\n );\n};\n\nexport const useMenuItems = (\n group?: MenuItemGroup,\n propsItems?: MenuItem[],\n consumerName: string = 'useMenuItemConsumer',\n __menuScope?: Scope,\n) => {\n const { useGroupItems } = useMenu(consumerName, __menuScope);\n const groupItems = useGroupItems(group);\n return useMemo(() => propsItems ?? groupItems ?? undefined, [propsItems, groupItems]);\n};\n\nexport { useMenu, createMenuScope, MenuProvider };\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport React, { useCallback, useRef } from 'react';\n\nimport { Icon, Toolbar as NaturalToolbar, type ToolbarRootProps, useTranslation } from '@dxos/react-ui';\nimport { useAttention } from '@dxos/react-ui-attention';\n\nimport { actionLabel, ActionLabel } from './ActionLabel';\nimport { DropdownMenu } from './DropdownMenu';\nimport { type MenuScopedProps, useMenu, useMenuItems } from './MenuContext';\nimport { translationKey } from '../translations';\nimport {\n type MenuAction,\n type MenuItem,\n isMenuGroup,\n isSeparator,\n type MenuItemGroup,\n type MenuActionProperties,\n type MenuMultipleSelectActionGroup,\n type MenuSingleSelectActionGroup,\n} from '../types';\n\nexport type ToolbarMenuDropdownMenuActionGroup = Omit<MenuActionProperties, 'variant' | 'icon'> & {\n variant: 'dropdownMenu';\n icon: string;\n applyActive?: boolean;\n};\n\nexport type ToolbarMenuToggleGroupActionGroup = Omit<MenuActionProperties, 'variant'> & {\n variant: 'toggleGroup';\n};\n\nexport type ToolbarMenuActionGroupProperties = (\n | ToolbarMenuDropdownMenuActionGroup\n | ToolbarMenuToggleGroupActionGroup\n) &\n (MenuSingleSelectActionGroup | MenuMultipleSelectActionGroup);\n\nexport type ToolbarMenuProps = ToolbarRootProps;\n\nexport type ToolbarMenuActionGroupProps = {\n group: MenuItemGroup<ToolbarMenuActionGroupProperties>;\n items?: MenuItem[];\n};\n\nexport type ToolbarMenuActionProps = {\n group: MenuItemGroup<ToolbarMenuActionGroupProperties>;\n action: MenuAction;\n};\n\nconst ActionToolbarItem = ({ action, __menuScope }: MenuScopedProps<{ action: MenuAction }>) => {\n const { iconSize } = useMenu('ActionToolbarItem', __menuScope);\n const { t } = useTranslation(translationKey);\n const handleClick = useCallback(() => action.data?.(), [action]);\n const { icon, iconOnly = true, disabled, testId, hidden, classNames } = action.properties;\n const Root = icon ? NaturalToolbar.IconButton : NaturalToolbar.Button;\n const rootProps = icon\n ? { icon, size: iconSize, iconOnly, label: actionLabel(action, t) }\n : { children: <ActionLabel action={action} /> };\n return hidden ? null : (\n <Root\n key={action.id}\n disabled={disabled}\n onClick={handleClick}\n variant='ghost'\n {...(testId && { 'data-testid': testId })}\n {...(rootProps as any)}\n classNames={classNames}\n />\n );\n};\n\nconst DropdownMenuToolbarItem = ({\n group,\n items: propsItems,\n __menuScope,\n}: MenuScopedProps<ToolbarMenuActionGroupProps>) => {\n const { iconOnly, disabled, testId } = group.properties;\n const suppressNextTooltip = useRef(false);\n const { t } = useTranslation(translationKey);\n const { iconSize } = useMenu('DropdownMenuToolbarItem', __menuScope);\n const items = useMenuItems(group, propsItems, 'DropdownMenuToolbarItem', __menuScope);\n const activeItem = items?.find((item) => !!(item as MenuAction).properties.checked);\n const icon =\n ((group.properties as any).applyActive &&\n // TODO(thure): Handle other menu item types.\n (activeItem as MenuAction)?.properties.icon) ||\n group.properties.icon;\n const Root = icon ? NaturalToolbar.IconButton : NaturalToolbar.Button;\n const labelAction = (group.properties as any).applyActive && activeItem ? (activeItem as MenuAction) : group;\n const rootProps = icon\n ? { icon, size: iconSize, iconOnly, label: actionLabel(labelAction, t), caretDown: true, suppressNextTooltip }\n : {\n children: (\n <>\n <ActionLabel action={labelAction} />\n <Icon size={3} icon='ph--caret-down--bold' classNames='mis-1' />\n </>\n ),\n };\n return (\n <DropdownMenu.Root group={group} items={items} suppressNextTooltip={suppressNextTooltip}>\n <DropdownMenu.Trigger asChild>\n <Root variant='ghost' disabled={disabled} {...(rootProps as any)} {...(testId && { 'data-testid': testId })} />\n </DropdownMenu.Trigger>\n </DropdownMenu.Root>\n );\n};\n\nconst ToggleGroupItem = ({ group, action, __menuScope }: MenuScopedProps<ToolbarMenuActionProps>) => {\n const { iconSize } = useMenu('ToggleGroupItem', __menuScope);\n const { t } = useTranslation(translationKey);\n const { icon, iconOnly = true, disabled, testId, hidden, classNames } = action.properties;\n const handleClick = useCallback(() => action.data?.({ parent: group }), [action, group]);\n const Root = icon ? NaturalToolbar.ToggleGroupIconItem : NaturalToolbar.ToggleGroupItem;\n const rootProps = icon\n ? { icon, size: iconSize, iconOnly, label: actionLabel(action, t) }\n : { children: <ActionLabel action={action} /> };\n return hidden ? null : (\n <Root\n key={action.id}\n value={action.id as any}\n disabled={disabled}\n onClick={handleClick}\n variant='ghost'\n {...(testId && { 'data-testid': testId })}\n {...(rootProps as any)}\n classNames={classNames}\n />\n );\n};\n\nconst ToggleGroupToolbarItem = ({\n group,\n items: propsItems,\n __menuScope,\n}: MenuScopedProps<ToolbarMenuActionGroupProps>) => {\n const items = useMenuItems(group, propsItems, 'ToggleGroupToolbarItem', __menuScope);\n const { selectCardinality, value } = group.properties;\n return (\n // TODO(thure): The type here is difficult to manage, what do?\n // @ts-ignore\n <NaturalToolbar.ToggleGroup type={selectCardinality} value={value}>\n {\n // TODO(thure): Handle other menu item types.\n (items as MenuAction[]).map((action) => (\n <ToggleGroupItem key={action.id} group={group} action={action} />\n ))\n }\n </NaturalToolbar.ToggleGroup>\n );\n};\n\nexport const ToolbarMenu = ({ __menuScope, classNames, ...props }: MenuScopedProps<ToolbarMenuProps>) => {\n const items = useMenuItems(undefined, undefined, 'ToolbarMenu', __menuScope);\n const { attendableId } = useMenu('ToolbarMenu', __menuScope);\n const { hasAttention } = useAttention(attendableId);\n return (\n <NaturalToolbar.Root\n {...props}\n classNames={['p-1', !hasAttention && '[&>*]:opacity-20 !bg-transparent', classNames]}\n >\n {items?.map((item: MenuItem, i: number) =>\n isSeparator(item) ? (\n <NaturalToolbar.Separator key={i} variant={item.properties.variant} />\n ) : isMenuGroup(item) ? (\n item.properties.variant === 'dropdownMenu' ? (\n // TODO(thure): Figure out type narrowing that doesn’t require so much use of `as`.\n <DropdownMenuToolbarItem key={item.id} group={item as MenuItemGroup<ToolbarMenuActionGroupProperties>} />\n ) : (\n // TODO(thure): Figure out type narrowing that doesn’t require so much use of `as`.\n <ToggleGroupToolbarItem key={item.id} group={item as MenuItemGroup<ToolbarMenuActionGroupProperties>} />\n )\n ) : (\n // TODO(thure): Figure out type narrowing that doesn’t require so much use of `as`.\n <ActionToolbarItem key={item.id} action={item as MenuAction} />\n ),\n )}\n </NaturalToolbar.Root>\n );\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { type Node, type Action, type ActionGroup, ACTION_GROUP_TYPE } from '@dxos/app-graph';\nimport { type ToolbarSeparatorProps, type Label, type IconButtonProps, type ClassNameValue } from '@dxos/react-ui';\n\nexport type MenuActionProperties = {\n label: Label;\n icon?: string;\n value?: string;\n disabled?: boolean;\n hidden?: boolean;\n iconOnly?: boolean;\n testId?: string;\n variant?: 'action' | 'toggle';\n checked?: boolean;\n classNames?: ClassNameValue;\n};\n\nexport type MenuItemGroupProperties = {\n label: Label;\n icon?: string;\n iconOnly?: boolean;\n};\n\nexport type MenuAction<P extends {} = {}> = Action<P & MenuActionProperties>;\n\nexport const MenuSeparatorType = '@dxos/react-ui-toolbar/separator' as const;\n\nexport type MenuSeparator = Node<never, Pick<ToolbarSeparatorProps, 'variant'>> & {\n type: typeof MenuSeparatorType;\n};\n\nexport const isSeparator = (node: Node): node is MenuSeparator => node.type === MenuSeparatorType;\n\nexport type MenuSingleSelectActionGroup = { selectCardinality: 'single'; value: string };\nexport type MenuMultipleSelectActionGroup = { selectCardinality: 'multiple'; value: string[] };\n\nexport type MenuItemGroup<P extends Record<string, any> = Record<string, any>> = ActionGroup<P>;\n\nexport const isMenuGroup = (node: Node): node is MenuItemGroup => node.type === ACTION_GROUP_TYPE;\n\nexport type MenuItem = MenuSeparator | MenuAction | MenuItemGroup;\n\nexport type MenuItemsResolver = (group?: MenuItemGroup) => MenuItem[] | null;\n\nexport type MenuContextValue = {\n useGroupItems: MenuItemsResolver;\n iconSize: IconButtonProps['size'];\n attendableId?: string;\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { RegistryContext, useRxValue } from '@effect-rx/rx-react';\nimport { useSignalEffect } from '@preact/signals-react';\nimport { useCallback, useContext, useState } from 'react';\n\nimport { type Edge, type Edges, Graph, type NodeArg, type Node, ROOT_ID } from '@dxos/app-graph';\n\nimport { type MenuItem, type MenuItemGroup } from '../types';\n\nconst edgesArrayToRecord = (edges: Edge[]): Record<string, Edges> => {\n return Object.fromEntries(\n Object.entries(\n edges.reduce((acc: Record<string, { inbound: string[]; outbound: string[] }>, { source, target }) => {\n if (!acc[source]) {\n acc[source] = { inbound: [], outbound: [] };\n }\n if (!acc[target]) {\n acc[target] = { inbound: [], outbound: [] };\n }\n\n const sourceEdges = acc[source];\n if (!sourceEdges.outbound.includes(target)) {\n sourceEdges.outbound.push(target);\n }\n\n const targetEdges = acc[target];\n if (!targetEdges.inbound.includes(source)) {\n targetEdges.inbound.push(source);\n }\n\n return acc;\n }, {}),\n ),\n );\n};\n\nexport type ActionGraphNodes = NodeArg<any>[];\nexport type ActionGraphEdges = Edge[];\nexport type ActionGraphProps = { nodes: ActionGraphNodes; edges: ActionGraphEdges };\n\nexport const useMenuActions = (actionCreator: () => ActionGraphProps) => {\n const registry = useContext(RegistryContext);\n const initialMenuGraphProps = actionCreator();\n\n const [graph] = useState(\n new Graph({\n registry,\n nodes: initialMenuGraphProps.nodes as Node[],\n edges: edgesArrayToRecord(initialMenuGraphProps.edges),\n }),\n );\n\n // TODO(wittjosiah): Remove dependence on signals.\n useSignalEffect(() => {\n const menuGraphProps = actionCreator();\n graph.addNodes(menuGraphProps.nodes);\n graph.addEdges(menuGraphProps.edges);\n });\n\n const useGroupItems = useCallback(\n (sourceNode?: MenuItemGroup) => {\n const items = useRxValue(graph.connections(sourceNode?.id || ROOT_ID)) as MenuItem[];\n return items;\n },\n [graph],\n );\n\n return { useGroupItems };\n};\n"],
5
- "mappings": "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",
6
- "names": ["import_react", "import_react_ui", "import_app_graph", "translationKey", "getShortcut", "action", "properties", "keyBinding", "getHostPlatform", "createMenuAction", "id", "invoke", "type", "ACTION_TYPE", "data", "createMenuItemGroup", "ACTION_GROUP_TYPE", "actionGroupSymbol", "createGapSeparator", "source", "nodes", "variant", "undefined", "edges", "target", "createLineSeparator", "ActionLabel", "shortcut", "t", "useTranslation", "React", "span", "className", "toLocalizedString", "label", "mx", "descriptionText", "keySymbols", "join", "actionLabel", "MENU_NAME", "createMenuContext", "createMenuScope", "createContextScope", "MenuContextProvider", "useMenu", "menuContextDefaults", "iconSize", "useGroupItems", "useMenuScope", "MenuProvider", "children", "attendableId", "scope", "useMenuItems", "group", "propsItems", "consumerName", "__menuScope", "groupItems", "useMemo", "DropdownMenuItem", "item", "onClick", "handleClick", "useCallback", "event", "NaturalDropdownMenu", "Item", "classNames", "disabled", "testId", "icon", "Icon", "size", "DropdownMenuRoot", "items", "open", "defaultOpen", "onOpenChange", "suppressNextTooltip", "caller", "naturalProps", "optionsMenuOpen", "setOptionsMenuOpen", "useControllableState", "prop", "defaultProp", "onChange", "handleActionClick", "stopPropagation", "current", "parent", "Root", "nextOpen", "Portal", "Content", "Viewport", "map", "key", "Arrow", "DropdownMenu", "Trigger", "VirtualTrigger", "MenuSeparatorType", "isSeparator", "node", "isMenuGroup", "ActionToolbarItem", "iconOnly", "hidden", "NaturalToolbar", "IconButton", "Button", "rootProps", "DropdownMenuToolbarItem", "useRef", "activeItem", "find", "checked", "applyActive", "labelAction", "caretDown", "asChild", "ToggleGroupItem", "ToggleGroupIconItem", "value", "ToggleGroupToolbarItem", "selectCardinality", "ToggleGroup", "ToolbarMenu", "props", "hasAttention", "useAttention", "i", "Separator", "edgesArrayToRecord", "Object", "fromEntries", "entries", "reduce", "acc", "inbound", "outbound", "sourceEdges", "includes", "push", "targetEdges", "useMenuActions", "actionCreator", "registry", "useContext", "RegistryContext", "initialMenuGraphProps", "graph", "useState", "Graph", "useSignalEffect", "menuGraphProps", "addNodes", "addEdges", "sourceNode", "useRxValue", "connections", "ROOT_ID"]
3
+ "sources": ["../../../src/components/DropdownMenu.tsx", "../../../src/components/ActionLabel.tsx", "../../../src/translations.ts", "../../../src/util.ts", "../../../src/components/MenuContext.tsx", "../../../src/components/ToolbarMenu.tsx", "../../../src/defs.ts", "../../../src/hooks.ts"],
4
+ "sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport { useControllableState } from '@radix-ui/react-use-controllable-state';\nimport React, { type MouseEvent, type MutableRefObject, useCallback } from 'react';\n\nimport { DropdownMenu as NaturalDropdownMenu, Icon, type DropdownMenuRootProps } from '@dxos/react-ui';\n\nimport { ActionLabel } from './ActionLabel';\nimport { type MenuScopedProps, useMenu, useMenuItems } from './MenuContext';\nimport { type MenuAction, type MenuItem, type MenuItemGroup } from '../defs';\n\nexport type DropdownMenuProps = DropdownMenuRootProps & {\n group?: MenuItemGroup;\n items?: MenuItem[];\n suppressNextTooltip?: MutableRefObject<boolean>;\n};\n\nconst DropdownMenuItem = ({\n item,\n onClick,\n __menuScope,\n}: MenuScopedProps<{\n item: MenuItem;\n onClick: (action: MenuAction, event: MouseEvent) => void;\n}>) => {\n // TODO(thure): handle other items.\n const action = item as MenuAction;\n const handleClick = useCallback((event: MouseEvent) => onClick(action, event), [action, onClick]);\n const { iconSize } = useMenu('DropdownMenuItem', __menuScope);\n return (\n <NaturalDropdownMenu.Item\n onClick={handleClick}\n classNames='gap-2'\n disabled={action.properties?.disabled}\n {...(action.properties?.testId && { 'data-testid': action.properties.testId })}\n >\n {action.properties?.icon && <Icon icon={action.properties!.icon} size={iconSize} />}\n <ActionLabel action={action} />\n </NaturalDropdownMenu.Item>\n );\n};\n\nconst DropdownMenuRoot = ({\n items: propsItems,\n group,\n open,\n defaultOpen,\n onOpenChange,\n suppressNextTooltip,\n children,\n __menuScope,\n ...naturalProps\n}: MenuScopedProps<DropdownMenuProps>) => {\n const [optionsMenuOpen, setOptionsMenuOpen] = useControllableState({\n prop: open,\n defaultProp: defaultOpen,\n onChange: onOpenChange,\n });\n\n const { onAction } = useMenu('DropdownMenuRoot', __menuScope);\n\n const handleActionClick = useCallback(\n (action: MenuAction, event: MouseEvent) => {\n if (action.properties?.disabled) {\n return;\n }\n event.stopPropagation();\n // TODO(thure): Why does Dialog’s modal-ness cause issues if we don’t explicitly close the menu here?\n if (suppressNextTooltip) {\n suppressNextTooltip.current = true;\n }\n setOptionsMenuOpen(false);\n onAction?.(action);\n },\n [onAction],\n );\n\n const items = useMenuItems(group, propsItems);\n\n return (\n <NaturalDropdownMenu.Root\n {...{\n open: optionsMenuOpen,\n onOpenChange: (nextOpen: boolean) => {\n if (!nextOpen && suppressNextTooltip) {\n suppressNextTooltip.current = true;\n }\n return setOptionsMenuOpen(nextOpen);\n },\n }}\n {...naturalProps}\n >\n {children}\n <NaturalDropdownMenu.Portal>\n <NaturalDropdownMenu.Content>\n <NaturalDropdownMenu.Viewport>\n {items?.map((item) => <DropdownMenuItem key={item.id} item={item} onClick={handleActionClick} />)}\n </NaturalDropdownMenu.Viewport>\n <NaturalDropdownMenu.Arrow />\n </NaturalDropdownMenu.Content>\n </NaturalDropdownMenu.Portal>\n </NaturalDropdownMenu.Root>\n );\n};\n\nexport const DropdownMenu = {\n Root: DropdownMenuRoot,\n Trigger: NaturalDropdownMenu.Trigger,\n VirtualTrigger: NaturalDropdownMenu.VirtualTrigger,\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport React from 'react';\n\nimport { type Action, type ActionGroup } from '@dxos/app-graph';\nimport { keySymbols } from '@dxos/keyboard';\nimport { toLocalizedString, useTranslation } from '@dxos/react-ui';\nimport { mx, descriptionText } from '@dxos/react-ui-theme';\n\nimport { type MenuActionProperties } from '../defs';\nimport { translationKey } from '../translations';\nimport { getShortcut } from '../util';\n\nexport const ActionLabel = ({\n action,\n}: {\n action: Action<MenuActionProperties> | ActionGroup<Omit<MenuActionProperties, 'variant'>>;\n}) => {\n const shortcut = getShortcut(action);\n const { t } = useTranslation(translationKey);\n\n return (\n <>\n <span className='grow truncate'>{toLocalizedString(action.properties!.label, t)}</span>\n {shortcut && <span className={mx('shrink-0', descriptionText)}>{keySymbols(shortcut).join('')}</span>}\n </>\n );\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nexport const translationKey = 'menus';\n\nexport default [\n {\n 'en-US': {\n [translationKey]: {},\n },\n },\n] as const;\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { ACTION_GROUP_TYPE, ACTION_TYPE, actionGroupSymbol, type ActionLike } from '@dxos/app-graph';\nimport { getHostPlatform } from '@dxos/util';\n\nimport {\n type MenuAction,\n type MenuActionProperties,\n type MenuItemGroup,\n type MenuItemGroupProperties,\n type MenuSeparator,\n} from './defs';\n\nexport const getShortcut = (action: ActionLike) => {\n return typeof action.properties?.keyBinding === 'string'\n ? action.properties.keyBinding\n : action.properties?.keyBinding?.[getHostPlatform()];\n};\n\nexport const fallbackIcon = 'ph--placeholder--regular';\n\n// TODO(thure,wittjosiah): This is probably a smell; consider the whether react-ui-menu should use action nodes if the\n// callback in `data` is never used. See https://github.com/dxos/dxos/pull/8506#discussion_r1925855118\nconst noop = () => {};\n\nexport const createMenuAction = <P extends {} = {}>(id: string, properties: P & MenuActionProperties) =>\n ({\n id,\n type: ACTION_TYPE,\n properties,\n data: noop,\n }) satisfies MenuAction;\n\nexport const createMenuItemGroup = <\n P extends MenuItemGroupProperties = MenuItemGroupProperties & Partial<MenuActionProperties>,\n>(\n id: string,\n properties: P,\n) =>\n ({\n id,\n type: ACTION_GROUP_TYPE,\n properties,\n data: actionGroupSymbol,\n }) satisfies MenuItemGroup;\n\nexport const createGapSeparator = (id: string = 'gap', source: string = 'root') => ({\n nodes: [\n {\n id,\n type: '@dxos/react-ui-toolbar/separator',\n properties: { variant: 'gap' },\n data: undefined as never,\n } satisfies MenuSeparator,\n ],\n edges: [{ source, target: id }],\n});\n\nexport const createLineSeparator = (id: string = 'line', source: string = 'root') => ({\n nodes: [\n {\n id,\n type: '@dxos/react-ui-toolbar/separator',\n properties: { variant: 'line' },\n data: undefined as never,\n } satisfies MenuSeparator,\n ],\n edges: [{ source, target: id }],\n});\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { createContextScope, type Scope } from '@radix-ui/react-context';\nimport React, { type PropsWithChildren, useMemo } from 'react';\n\nimport { type Node } from '@dxos/app-graph';\n\nimport {\n type MenuActionHandler,\n type MenuAction,\n type MenuContextValue,\n type MenuItem,\n type MenuItemGroup,\n} from '../defs';\n\nexport type MenuScopedProps<P> = P & { __menuScope?: Scope };\n\nconst MENU_NAME = 'GraphMenu';\n\nconst [createMenuContext, createMenuScope] = createContextScope(MENU_NAME, []);\n\nconst [MenuContextProvider, useMenu] = createMenuContext<MenuContextValue<any>>(MENU_NAME);\n\nexport const menuContextDefaults: MenuContextValue<MenuAction> = {\n iconSize: 5,\n onAction: () => {},\n resolveGroupItems: () => null,\n};\n\nconst useMenuScope = createMenuScope();\n\nconst MenuProvider = <A extends Node = MenuAction>({\n children,\n resolveGroupItems = menuContextDefaults.resolveGroupItems,\n onAction = menuContextDefaults.onAction as MenuActionHandler<A>,\n iconSize = menuContextDefaults.iconSize,\n attendableId,\n}: PropsWithChildren<Partial<MenuContextValue<A>>>) => {\n const { scope } = useMenuScope(undefined);\n return (\n <MenuContextProvider\n resolveGroupItems={resolveGroupItems}\n onAction={onAction}\n iconSize={iconSize}\n attendableId={attendableId}\n scope={scope}\n >\n {children}\n </MenuContextProvider>\n );\n};\n\nexport const useMenuItems = (\n group?: MenuItemGroup,\n propsItems?: MenuItem[],\n consumerName: string = 'useMenuItemConsumer',\n __menuScope?: Scope,\n) => {\n const { resolveGroupItems } = useMenu(consumerName, __menuScope);\n return useMemo(() => propsItems ?? resolveGroupItems?.(group) ?? undefined, [propsItems, group, resolveGroupItems]);\n};\n\nexport { useMenu, createMenuScope, MenuProvider };\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport React, { useCallback, useRef } from 'react';\n\nimport { Icon, type IconButtonProps, Toolbar as NaturalToolbar, type ToolbarRootProps } from '@dxos/react-ui';\nimport { useAttention } from '@dxos/react-ui-attention';\n\nimport { ActionLabel } from './ActionLabel';\nimport { DropdownMenu } from './DropdownMenu';\nimport { type MenuScopedProps, useMenu, useMenuItems } from './MenuContext';\nimport {\n type MenuAction,\n type MenuItem,\n isMenuGroup,\n isSeparator,\n type MenuItemGroup,\n type MenuActionProperties,\n type MenuMultipleSelectActionGroup,\n type MenuSingleSelectActionGroup,\n} from '../defs';\n\nexport type ToolbarMenuDropdownMenuActionGroup = Omit<MenuActionProperties, 'variant' | 'icon'> & {\n variant: 'dropdownMenu';\n icon: string;\n applyActive?: boolean;\n};\n\nexport type ToolbarMenuToggleGroupActionGroup = Omit<MenuActionProperties, 'variant'> & {\n variant: 'toggleGroup';\n};\n\nexport type ToolbarMenuActionGroupProperties = (\n | ToolbarMenuDropdownMenuActionGroup\n | ToolbarMenuToggleGroupActionGroup\n) &\n (MenuSingleSelectActionGroup | MenuMultipleSelectActionGroup);\n\nexport type ToolbarMenuProps = ToolbarRootProps;\n\nexport type ToolbarMenuActionGroupProps = {\n group: MenuItemGroup<ToolbarMenuActionGroupProperties>;\n items?: MenuItem[];\n};\n\nconst ActionToolbarItem = ({ action, __menuScope }: MenuScopedProps<{ action: MenuAction }>) => {\n const { onAction, iconSize } = useMenu('ActionToolbarItem', __menuScope);\n const handleClick = useCallback(() => {\n onAction?.(action);\n }, [action, onAction]);\n const { icon, iconOnly = true, disabled, testId, hidden, classNames } = action.properties;\n const Root = icon ? NaturalToolbar.IconButton : NaturalToolbar.Button;\n const rootProps = icon\n ? { icon, size: iconSize, iconOnly, label: <ActionLabel action={action} /> }\n : { children: <ActionLabel action={action} /> };\n return hidden ? null : (\n <Root\n key={action.id}\n disabled={disabled}\n onClick={handleClick}\n variant='ghost'\n {...(testId && { 'data-testid': testId })}\n {...(rootProps as IconButtonProps)}\n classNames={classNames}\n />\n );\n};\n\nconst DropdownMenuToolbarItem = ({\n group,\n items: propsItems,\n __menuScope,\n}: MenuScopedProps<ToolbarMenuActionGroupProps>) => {\n const { iconOnly, disabled, testId } = group.properties;\n const suppressNextTooltip = useRef(false);\n const { iconSize } = useMenu('DropdownMenuToolbarItem', __menuScope);\n const items = useMenuItems(group, propsItems, 'DropdownMenuToolbarItem', __menuScope);\n const activeItem = items?.find((item) => !!(item as MenuAction).properties.checked);\n const icon =\n ((group.properties as any).applyActive &&\n // TODO(thure): Handle other menu item types.\n (activeItem as MenuAction)?.properties.icon) ||\n group.properties.icon;\n const Root = icon ? NaturalToolbar.IconButton : NaturalToolbar.Button;\n const label = (\n <ActionLabel action={(group.properties as any).applyActive && activeItem ? (activeItem as MenuAction) : group} />\n );\n const rootProps = icon\n ? { icon, size: iconSize, iconOnly, label, caretDown: true, suppressNextTooltip }\n : {\n children: (\n <>\n {label}\n <Icon size={3} icon='ph--caret-down--bold' classNames='mis-1' />\n </>\n ),\n };\n return (\n <DropdownMenu.Root group={group} items={items} suppressNextTooltip={suppressNextTooltip}>\n <DropdownMenu.Trigger asChild>\n <Root\n variant='ghost'\n disabled={disabled}\n {...(rootProps as IconButtonProps)}\n {...(testId && { 'data-testid': testId })}\n />\n </DropdownMenu.Trigger>\n </DropdownMenu.Root>\n );\n};\n\nconst ToggleGroupItem = ({ action, __menuScope }: MenuScopedProps<{ action: MenuAction }>) => {\n const { iconSize, onAction } = useMenu('ToggleGroupItem', __menuScope);\n const { icon, iconOnly = true, disabled, testId, hidden, classNames } = action.properties;\n const handleClick = useCallback(() => {\n onAction?.(action);\n }, [action, onAction]);\n const Root = icon ? NaturalToolbar.ToggleGroupIconItem : NaturalToolbar.ToggleGroupItem;\n const rootProps = icon\n ? { icon, size: iconSize, iconOnly, label: <ActionLabel action={action} /> }\n : { children: <ActionLabel action={action} /> };\n return hidden ? null : (\n <Root\n key={action.id}\n value={action.id as any}\n disabled={disabled}\n onClick={handleClick}\n variant='ghost'\n {...(testId && { 'data-testid': testId })}\n {...(rootProps as IconButtonProps)}\n classNames={classNames}\n />\n );\n};\n\nconst ToggleGroupToolbarItem = ({\n group,\n items: propsItems,\n __menuScope,\n}: MenuScopedProps<ToolbarMenuActionGroupProps>) => {\n const items = useMenuItems(group, propsItems, 'ToggleGroupToolbarItem', __menuScope);\n const { selectCardinality, value } = group.properties;\n return (\n // TODO(thure): The type here is difficult to manage, what do?\n // @ts-ignore\n <NaturalToolbar.ToggleGroup type={selectCardinality} value={value}>\n {\n // TODO(thure): Handle other menu item types.\n (items as MenuAction[]).map((action) => (\n <ToggleGroupItem key={action.id} action={action} />\n ))\n }\n </NaturalToolbar.ToggleGroup>\n );\n};\n\nexport const ToolbarMenu = ({ __menuScope, classNames, ...props }: MenuScopedProps<ToolbarMenuProps>) => {\n const items = useMenuItems(undefined, undefined, 'ToolbarMenu', __menuScope);\n const { attendableId } = useMenu('ToolbarMenu', __menuScope);\n const { hasAttention } = useAttention(attendableId);\n return (\n <NaturalToolbar.Root\n {...props}\n classNames={['p-0 pointer-fine:p-1 attention-surface', !hasAttention && 'opacity-20', classNames]}\n >\n {items?.map((item: MenuItem, i: number) =>\n isSeparator(item) ? (\n <NaturalToolbar.Separator key={i} variant={item.properties.variant} />\n ) : isMenuGroup(item) ? (\n item.properties.variant === 'dropdownMenu' ? (\n // TODO(thure): Figure out type narrowing that doesn’t require so much use of `as`.\n <DropdownMenuToolbarItem key={item.id} group={item as MenuItemGroup<ToolbarMenuActionGroupProperties>} />\n ) : (\n // TODO(thure): Figure out type narrowing that doesn’t require so much use of `as`.\n <ToggleGroupToolbarItem key={item.id} group={item as MenuItemGroup<ToolbarMenuActionGroupProperties>} />\n )\n ) : (\n // TODO(thure): Figure out type narrowing that doesn’t require so much use of `as`.\n <ActionToolbarItem key={item.id} action={item as MenuAction} />\n ),\n )}\n </NaturalToolbar.Root>\n );\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { type Node, type Action, type ActionGroup, ACTION_GROUP_TYPE } from '@dxos/app-graph';\nimport { type ToolbarSeparatorProps, type Label, type IconButtonProps, type ClassNameValue } from '@dxos/react-ui';\n\nexport type MenuActionProperties = {\n label: Label;\n icon?: string;\n value?: string;\n disabled?: boolean;\n hidden?: boolean;\n iconOnly?: boolean;\n testId?: string;\n variant?: 'action' | 'toggle';\n checked?: boolean;\n classNames?: ClassNameValue;\n};\n\nexport type MenuItemGroupProperties = {\n label: Label;\n icon?: string;\n iconOnly?: boolean;\n};\n\nexport type MenuAction<P extends {} = {}> = Action<P & MenuActionProperties>;\n\nexport type MenuActionHandler<A extends Node = MenuAction> = (action: A) => void;\n\nexport const MenuSeparatorType = '@dxos/react-ui-toolbar/separator' as const;\n\nexport type MenuSeparator = Node<never, Pick<ToolbarSeparatorProps, 'variant'>> & {\n type: typeof MenuSeparatorType;\n};\n\nexport const isSeparator = (node: Node): node is MenuSeparator => node.type === MenuSeparatorType;\n\nexport type MenuSingleSelectActionGroup = { selectCardinality: 'single'; value: string };\nexport type MenuMultipleSelectActionGroup = { selectCardinality: 'multiple'; value: string[] };\n\nexport type MenuItemGroup<P extends Record<string, any> = Record<string, any>> = ActionGroup<P>;\n\nexport const isMenuGroup = (node: Node): node is MenuItemGroup => node.type === ACTION_GROUP_TYPE;\n\nexport type MenuItem = MenuSeparator | MenuAction | MenuItemGroup;\n\nexport type MenuItemsResolver = (group?: MenuItemGroup) => MenuItem[] | null;\n\nexport type MenuContextValue<A extends Node = MenuAction> = {\n resolveGroupItems: MenuItemsResolver;\n iconSize: IconButtonProps['size'];\n onAction: MenuActionHandler<A>;\n attendableId?: string;\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { useSignalEffect } from '@preact/signals-react';\nimport { useCallback, useState } from 'react';\n\nimport { Graph, type NodeArg, type Node } from '@dxos/app-graph';\n\nimport { type MenuItem, type MenuItemGroup } from './defs';\n\ntype Edge = { source: string; target: string };\n\nconst edgesArrayToRecord = (edges: { source: string; target: string }[]): Record<string, string[]> => {\n return Object.fromEntries(\n Object.entries(\n edges.reduce((acc: Record<string, { inbound: string[]; outbound: string[] }>, { source, target }) => {\n if (!acc[source]) {\n acc[source] = { inbound: [], outbound: [] };\n }\n if (!acc[target]) {\n acc[target] = { inbound: [], outbound: [] };\n }\n\n const sourceEdges = acc[source];\n if (!sourceEdges.outbound.includes(target)) {\n sourceEdges.outbound.push(target);\n }\n\n const targetEdges = acc[target];\n if (!targetEdges.inbound.includes(source)) {\n targetEdges.inbound.push(source);\n }\n\n return acc;\n }, {}),\n ).map(([id, { outbound }]): [string, string[]] => [id, outbound]),\n );\n};\n\nexport type ActionGraphNodes = NodeArg<any>[];\nexport type ActionGraphEdges = Edge[];\nexport type ActionGraphProps = { nodes: ActionGraphNodes; edges: ActionGraphEdges };\n\nexport const useMenuActions = (actionCreator: () => ActionGraphProps) => {\n const initialMenuGraphProps = actionCreator();\n\n const [graph] = useState(\n new Graph({ nodes: initialMenuGraphProps.nodes as Node[], edges: edgesArrayToRecord(initialMenuGraphProps.edges) }),\n );\n\n useSignalEffect(() => {\n const menuGraphProps = actionCreator();\n // @ts-ignore\n graph._addNodes(menuGraphProps.nodes);\n // @ts-ignore\n graph._addEdges(menuGraphProps.edges);\n });\n\n const resolveGroupItems = useCallback(\n (sourceNode: MenuItemGroup = graph.root as MenuItemGroup) => {\n if (graph) {\n return (graph.nodes(sourceNode, { filter: (n): n is any => true }) || null) as MenuItem[] | null;\n } else {\n return null;\n }\n },\n [graph],\n );\n\n return { resolveGroupItems };\n};\n"],
5
+ "mappings": "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",
6
+ "names": ["import_react", "import_react_ui", "import_app_graph", "translationKey", "getShortcut", "action", "properties", "keyBinding", "getHostPlatform", "noop", "createMenuAction", "id", "type", "ACTION_TYPE", "data", "createMenuItemGroup", "ACTION_GROUP_TYPE", "actionGroupSymbol", "createGapSeparator", "source", "nodes", "variant", "undefined", "edges", "target", "createLineSeparator", "ActionLabel", "shortcut", "t", "useTranslation", "React", "span", "className", "toLocalizedString", "label", "mx", "descriptionText", "keySymbols", "join", "MENU_NAME", "createMenuContext", "createMenuScope", "createContextScope", "MenuContextProvider", "useMenu", "menuContextDefaults", "iconSize", "onAction", "resolveGroupItems", "useMenuScope", "MenuProvider", "children", "attendableId", "scope", "useMenuItems", "group", "propsItems", "consumerName", "__menuScope", "useMemo", "DropdownMenuItem", "item", "onClick", "handleClick", "useCallback", "event", "NaturalDropdownMenu", "Item", "classNames", "disabled", "testId", "icon", "Icon", "size", "DropdownMenuRoot", "items", "open", "defaultOpen", "onOpenChange", "suppressNextTooltip", "naturalProps", "optionsMenuOpen", "setOptionsMenuOpen", "useControllableState", "prop", "defaultProp", "onChange", "handleActionClick", "stopPropagation", "current", "Root", "nextOpen", "Portal", "Content", "Viewport", "map", "key", "Arrow", "DropdownMenu", "Trigger", "VirtualTrigger", "MenuSeparatorType", "isSeparator", "node", "isMenuGroup", "ActionToolbarItem", "iconOnly", "hidden", "NaturalToolbar", "IconButton", "Button", "rootProps", "DropdownMenuToolbarItem", "useRef", "activeItem", "find", "checked", "applyActive", "caretDown", "asChild", "ToggleGroupItem", "ToggleGroupIconItem", "value", "ToggleGroupToolbarItem", "selectCardinality", "ToggleGroup", "ToolbarMenu", "props", "hasAttention", "useAttention", "i", "Separator", "edgesArrayToRecord", "Object", "fromEntries", "entries", "reduce", "acc", "inbound", "outbound", "sourceEdges", "includes", "push", "targetEdges", "useMenuActions", "actionCreator", "initialMenuGraphProps", "graph", "useState", "Graph", "useSignalEffect", "menuGraphProps", "_addNodes", "_addEdges", "sourceNode", "root", "filter", "n"]
7
7
  }
@@ -1 +1 @@
1
- {"inputs":{"packages/ui/react-ui-menu/src/translations.ts":{"bytes":909,"imports":[],"format":"esm"},"packages/ui/react-ui-menu/src/util.ts":{"bytes":5996,"imports":[{"path":"@dxos/app-graph","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"format":"esm"},"packages/ui/react-ui-menu/src/components/ActionLabel.tsx":{"bytes":4200,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/keyboard","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"@dxos/react-ui-theme","kind":"import-statement","external":true},{"path":"packages/ui/react-ui-menu/src/translations.ts","kind":"import-statement","original":"../translations"},{"path":"packages/ui/react-ui-menu/src/util.ts","kind":"import-statement","original":"../util"}],"format":"esm"},"packages/ui/react-ui-menu/src/components/MenuContext.tsx":{"bytes":5088,"imports":[{"path":"@radix-ui/react-context","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true}],"format":"esm"},"packages/ui/react-ui-menu/src/components/DropdownMenu.tsx":{"bytes":11327,"imports":[{"path":"@radix-ui/react-use-controllable-state","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"packages/ui/react-ui-menu/src/components/ActionLabel.tsx","kind":"import-statement","original":"./ActionLabel"},{"path":"packages/ui/react-ui-menu/src/components/MenuContext.tsx","kind":"import-statement","original":"./MenuContext"}],"format":"esm"},"packages/ui/react-ui-menu/src/types.ts":{"bytes":3243,"imports":[{"path":"@dxos/app-graph","kind":"import-statement","external":true}],"format":"esm"},"packages/ui/react-ui-menu/src/components/ToolbarMenu.tsx":{"bytes":22596,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"@dxos/react-ui-attention","kind":"import-statement","external":true},{"path":"packages/ui/react-ui-menu/src/components/ActionLabel.tsx","kind":"import-statement","original":"./ActionLabel"},{"path":"packages/ui/react-ui-menu/src/components/DropdownMenu.tsx","kind":"import-statement","original":"./DropdownMenu"},{"path":"packages/ui/react-ui-menu/src/components/MenuContext.tsx","kind":"import-statement","original":"./MenuContext"},{"path":"packages/ui/react-ui-menu/src/translations.ts","kind":"import-statement","original":"../translations"},{"path":"packages/ui/react-ui-menu/src/types.ts","kind":"import-statement","original":"../types"}],"format":"esm"},"packages/ui/react-ui-menu/src/components/index.ts":{"bytes":718,"imports":[{"path":"packages/ui/react-ui-menu/src/components/DropdownMenu.tsx","kind":"import-statement","original":"./DropdownMenu"},{"path":"packages/ui/react-ui-menu/src/components/ToolbarMenu.tsx","kind":"import-statement","original":"./ToolbarMenu"},{"path":"packages/ui/react-ui-menu/src/components/MenuContext.tsx","kind":"import-statement","original":"./MenuContext"}],"format":"esm"},"packages/ui/react-ui-menu/src/hooks/useMenuActions.ts":{"bytes":7433,"imports":[{"path":"@effect-rx/rx-react","kind":"import-statement","external":true},{"path":"@preact/signals-react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/app-graph","kind":"import-statement","external":true}],"format":"esm"},"packages/ui/react-ui-menu/src/hooks/index.ts":{"bytes":521,"imports":[{"path":"packages/ui/react-ui-menu/src/hooks/useMenuActions.ts","kind":"import-statement","original":"./useMenuActions"}],"format":"esm"},"packages/ui/react-ui-menu/src/index.ts":{"bytes":1114,"imports":[{"path":"packages/ui/react-ui-menu/src/components/index.ts","kind":"import-statement","original":"./components"},{"path":"packages/ui/react-ui-menu/src/hooks/index.ts","kind":"import-statement","original":"./hooks"},{"path":"packages/ui/react-ui-menu/src/types.ts","kind":"import-statement","original":"./types"},{"path":"packages/ui/react-ui-menu/src/util.ts","kind":"import-statement","original":"./util"}],"format":"esm"}},"outputs":{"packages/ui/react-ui-menu/dist/lib/node/index.cjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":31698},"packages/ui/react-ui-menu/dist/lib/node/index.cjs":{"imports":[{"path":"@radix-ui/react-use-controllable-state","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/keyboard","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"@dxos/react-ui-theme","kind":"import-statement","external":true},{"path":"@dxos/app-graph","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true},{"path":"@radix-ui/react-context","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"@dxos/react-ui-attention","kind":"import-statement","external":true},{"path":"@dxos/app-graph","kind":"import-statement","external":true},{"path":"@effect-rx/rx-react","kind":"import-statement","external":true},{"path":"@preact/signals-react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/app-graph","kind":"import-statement","external":true}],"exports":["DropdownMenu","MenuProvider","MenuSeparatorType","ToolbarMenu","createGapSeparator","createLineSeparator","createMenuAction","createMenuItemGroup","createMenuScope","isMenuGroup","isSeparator","menuContextDefaults","useMenu","useMenuActions","useMenuItems"],"entryPoint":"packages/ui/react-ui-menu/src/index.ts","inputs":{"packages/ui/react-ui-menu/src/components/DropdownMenu.tsx":{"bytesInOutput":2562},"packages/ui/react-ui-menu/src/components/ActionLabel.tsx":{"bytesInOutput":862},"packages/ui/react-ui-menu/src/translations.ts":{"bytesInOutput":118},"packages/ui/react-ui-menu/src/util.ts":{"bytesInOutput":1113},"packages/ui/react-ui-menu/src/components/MenuContext.tsx":{"bytesInOutput":1028},"packages/ui/react-ui-menu/src/components/index.ts":{"bytesInOutput":0},"packages/ui/react-ui-menu/src/components/ToolbarMenu.tsx":{"bytesInOutput":5638},"packages/ui/react-ui-menu/src/types.ts":{"bytesInOutput":258},"packages/ui/react-ui-menu/src/index.ts":{"bytesInOutput":0},"packages/ui/react-ui-menu/src/hooks/useMenuActions.ts":{"bytesInOutput":1544},"packages/ui/react-ui-menu/src/hooks/index.ts":{"bytesInOutput":0}},"bytes":14063}}}
1
+ {"inputs":{"packages/ui/react-ui-menu/src/translations.ts":{"bytes":909,"imports":[],"format":"esm"},"packages/ui/react-ui-menu/src/util.ts":{"bytes":6574,"imports":[{"path":"@dxos/app-graph","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"format":"esm"},"packages/ui/react-ui-menu/src/components/ActionLabel.tsx":{"bytes":3310,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/keyboard","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"@dxos/react-ui-theme","kind":"import-statement","external":true},{"path":"packages/ui/react-ui-menu/src/translations.ts","kind":"import-statement","original":"../translations"},{"path":"packages/ui/react-ui-menu/src/util.ts","kind":"import-statement","original":"../util"}],"format":"esm"},"packages/ui/react-ui-menu/src/components/MenuContext.tsx":{"bytes":5704,"imports":[{"path":"@radix-ui/react-context","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true}],"format":"esm"},"packages/ui/react-ui-menu/src/components/DropdownMenu.tsx":{"bytes":11213,"imports":[{"path":"@radix-ui/react-use-controllable-state","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"packages/ui/react-ui-menu/src/components/ActionLabel.tsx","kind":"import-statement","original":"./ActionLabel"},{"path":"packages/ui/react-ui-menu/src/components/MenuContext.tsx","kind":"import-statement","original":"./MenuContext"}],"format":"esm"},"packages/ui/react-ui-menu/src/defs.ts":{"bytes":3442,"imports":[{"path":"@dxos/app-graph","kind":"import-statement","external":true}],"format":"esm"},"packages/ui/react-ui-menu/src/components/ToolbarMenu.tsx":{"bytes":21829,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"@dxos/react-ui-attention","kind":"import-statement","external":true},{"path":"packages/ui/react-ui-menu/src/components/ActionLabel.tsx","kind":"import-statement","original":"./ActionLabel"},{"path":"packages/ui/react-ui-menu/src/components/DropdownMenu.tsx","kind":"import-statement","original":"./DropdownMenu"},{"path":"packages/ui/react-ui-menu/src/components/MenuContext.tsx","kind":"import-statement","original":"./MenuContext"},{"path":"packages/ui/react-ui-menu/src/defs.ts","kind":"import-statement","original":"../defs"}],"format":"esm"},"packages/ui/react-ui-menu/src/components/index.ts":{"bytes":718,"imports":[{"path":"packages/ui/react-ui-menu/src/components/DropdownMenu.tsx","kind":"import-statement","original":"./DropdownMenu"},{"path":"packages/ui/react-ui-menu/src/components/ToolbarMenu.tsx","kind":"import-statement","original":"./ToolbarMenu"},{"path":"packages/ui/react-ui-menu/src/components/MenuContext.tsx","kind":"import-statement","original":"./MenuContext"}],"format":"esm"},"packages/ui/react-ui-menu/src/hooks.ts":{"bytes":7464,"imports":[{"path":"@preact/signals-react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/app-graph","kind":"import-statement","external":true}],"format":"esm"},"packages/ui/react-ui-menu/src/index.ts":{"bytes":1113,"imports":[{"path":"packages/ui/react-ui-menu/src/components/index.ts","kind":"import-statement","original":"./components"},{"path":"packages/ui/react-ui-menu/src/defs.ts","kind":"import-statement","original":"./defs"},{"path":"packages/ui/react-ui-menu/src/hooks.ts","kind":"import-statement","original":"./hooks"},{"path":"packages/ui/react-ui-menu/src/util.ts","kind":"import-statement","original":"./util"}],"format":"esm"}},"outputs":{"packages/ui/react-ui-menu/dist/lib/node/index.cjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":31412},"packages/ui/react-ui-menu/dist/lib/node/index.cjs":{"imports":[{"path":"@radix-ui/react-use-controllable-state","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/keyboard","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"@dxos/react-ui-theme","kind":"import-statement","external":true},{"path":"@dxos/app-graph","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true},{"path":"@radix-ui/react-context","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"@dxos/react-ui-attention","kind":"import-statement","external":true},{"path":"@dxos/app-graph","kind":"import-statement","external":true},{"path":"@preact/signals-react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/app-graph","kind":"import-statement","external":true}],"exports":["DropdownMenu","MenuProvider","MenuSeparatorType","ToolbarMenu","createGapSeparator","createLineSeparator","createMenuAction","createMenuItemGroup","createMenuScope","isMenuGroup","isSeparator","menuContextDefaults","useMenu","useMenuActions","useMenuItems"],"entryPoint":"packages/ui/react-ui-menu/src/index.ts","inputs":{"packages/ui/react-ui-menu/src/components/DropdownMenu.tsx":{"bytesInOutput":2542},"packages/ui/react-ui-menu/src/components/ActionLabel.tsx":{"bytesInOutput":667},"packages/ui/react-ui-menu/src/translations.ts":{"bytesInOutput":118},"packages/ui/react-ui-menu/src/util.ts":{"bytesInOutput":1125},"packages/ui/react-ui-menu/src/components/MenuContext.tsx":{"bytesInOutput":1119},"packages/ui/react-ui-menu/src/components/index.ts":{"bytesInOutput":0},"packages/ui/react-ui-menu/src/components/ToolbarMenu.tsx":{"bytesInOutput":5542},"packages/ui/react-ui-menu/src/defs.ts":{"bytesInOutput":258},"packages/ui/react-ui-menu/src/index.ts":{"bytesInOutput":0},"packages/ui/react-ui-menu/src/hooks.ts":{"bytesInOutput":1519}},"bytes":13814}}}