@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.
- package/dist/lib/browser/index.mjs +63 -58
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node/index.cjs +58 -53
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +63 -58
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/components/ActionLabel.d.ts +4 -8
- package/dist/types/src/components/ActionLabel.d.ts.map +1 -1
- package/dist/types/src/components/DropdownMenu.d.ts +2 -3
- package/dist/types/src/components/DropdownMenu.d.ts.map +1 -1
- package/dist/types/src/components/MenuContext.d.ts +13 -4
- package/dist/types/src/components/MenuContext.d.ts.map +1 -1
- package/dist/types/src/components/ToolbarMenu.d.ts +1 -5
- package/dist/types/src/components/ToolbarMenu.d.ts.map +1 -1
- package/dist/types/src/{types.d.ts → defs.d.ts} +5 -3
- package/dist/types/src/defs.d.ts.map +1 -0
- package/dist/types/src/hooks.d.ts +17 -0
- package/dist/types/src/hooks.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +1 -1
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/{components → testing}/Menus.stories.d.ts +1 -1
- package/dist/types/src/testing/Menus.stories.d.ts.map +1 -0
- package/dist/types/src/testing/index.d.ts +25 -1
- package/dist/types/src/testing/index.d.ts.map +1 -1
- package/dist/types/src/util.d.ts +2 -2
- package/dist/types/src/util.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +12 -18
- package/src/components/ActionLabel.tsx +8 -11
- package/src/components/DropdownMenu.tsx +5 -5
- package/src/components/MenuContext.tsx +26 -11
- package/src/components/ToolbarMenu.tsx +29 -27
- package/src/{types.ts → defs.ts} +5 -2
- package/src/{hooks/useMenuActions.ts → hooks.ts} +20 -20
- package/src/index.ts +1 -1
- package/src/{components → testing}/Menus.stories.tsx +13 -13
- package/src/testing/index.ts +107 -1
- package/src/util.ts +7 -7
- package/dist/types/src/components/Menus.stories.d.ts.map +0 -1
- package/dist/types/src/hooks/index.d.ts +0 -2
- package/dist/types/src/hooks/index.d.ts.map +0 -1
- package/dist/types/src/hooks/useMenuActions.d.ts +0 -12
- package/dist/types/src/hooks/useMenuActions.d.ts.map +0 -1
- package/dist/types/src/testing/generator.d.ts +0 -26
- package/dist/types/src/testing/generator.d.ts.map +0 -1
- package/dist/types/src/types.d.ts.map +0 -1
- package/src/hooks/index.ts +0 -5
- package/src/testing/generator.ts +0 -115
|
@@ -25,11 +25,13 @@ import { getHostPlatform } from "@dxos/util";
|
|
|
25
25
|
var getShortcut = (action) => {
|
|
26
26
|
return typeof action.properties?.keyBinding === "string" ? action.properties.keyBinding : action.properties?.keyBinding?.[getHostPlatform()];
|
|
27
27
|
};
|
|
28
|
-
var
|
|
28
|
+
var noop = () => {
|
|
29
|
+
};
|
|
30
|
+
var createMenuAction = (id, properties) => ({
|
|
29
31
|
id,
|
|
30
32
|
type: ACTION_TYPE,
|
|
31
33
|
properties,
|
|
32
|
-
data:
|
|
34
|
+
data: noop
|
|
33
35
|
});
|
|
34
36
|
var createMenuItemGroup = (id, properties) => ({
|
|
35
37
|
id,
|
|
@@ -84,10 +86,6 @@ var ActionLabel = ({ action }) => {
|
|
|
84
86
|
className: mx("shrink-0", descriptionText)
|
|
85
87
|
}, keySymbols(shortcut).join("")));
|
|
86
88
|
};
|
|
87
|
-
var actionLabel = (action, t) => {
|
|
88
|
-
const shortcut = getShortcut(action);
|
|
89
|
-
return `${toLocalizedString(action.properties.label, t)}${shortcut ? ` (${keySymbols(shortcut).join("")})` : ""}`;
|
|
90
|
-
};
|
|
91
89
|
|
|
92
90
|
// packages/ui/react-ui-menu/src/components/MenuContext.tsx
|
|
93
91
|
import { createContextScope } from "@radix-ui/react-context";
|
|
@@ -97,24 +95,27 @@ var [createMenuContext, createMenuScope] = createContextScope(MENU_NAME, []);
|
|
|
97
95
|
var [MenuContextProvider, useMenu] = createMenuContext(MENU_NAME);
|
|
98
96
|
var menuContextDefaults = {
|
|
99
97
|
iconSize: 5,
|
|
100
|
-
|
|
98
|
+
onAction: () => {
|
|
99
|
+
},
|
|
100
|
+
resolveGroupItems: () => null
|
|
101
101
|
};
|
|
102
102
|
var useMenuScope = createMenuScope();
|
|
103
|
-
var MenuProvider = ({ children,
|
|
103
|
+
var MenuProvider = ({ children, resolveGroupItems = menuContextDefaults.resolveGroupItems, onAction = menuContextDefaults.onAction, iconSize = menuContextDefaults.iconSize, attendableId }) => {
|
|
104
104
|
const { scope } = useMenuScope(void 0);
|
|
105
105
|
return /* @__PURE__ */ React2.createElement(MenuContextProvider, {
|
|
106
|
-
|
|
106
|
+
resolveGroupItems,
|
|
107
|
+
onAction,
|
|
107
108
|
iconSize,
|
|
108
109
|
attendableId,
|
|
109
110
|
scope
|
|
110
111
|
}, children);
|
|
111
112
|
};
|
|
112
113
|
var useMenuItems = (group, propsItems, consumerName = "useMenuItemConsumer", __menuScope) => {
|
|
113
|
-
const {
|
|
114
|
-
|
|
115
|
-
return useMemo(() => propsItems ?? groupItems ?? void 0, [
|
|
114
|
+
const { resolveGroupItems } = useMenu(consumerName, __menuScope);
|
|
115
|
+
return useMemo(() => propsItems ?? resolveGroupItems?.(group) ?? void 0, [
|
|
116
116
|
propsItems,
|
|
117
|
-
|
|
117
|
+
group,
|
|
118
|
+
resolveGroupItems
|
|
118
119
|
]);
|
|
119
120
|
};
|
|
120
121
|
|
|
@@ -140,12 +141,13 @@ var DropdownMenuItem = ({ item, onClick, __menuScope }) => {
|
|
|
140
141
|
action
|
|
141
142
|
}));
|
|
142
143
|
};
|
|
143
|
-
var DropdownMenuRoot = ({ items: propsItems, group, open, defaultOpen, onOpenChange, suppressNextTooltip,
|
|
144
|
+
var DropdownMenuRoot = ({ items: propsItems, group, open, defaultOpen, onOpenChange, suppressNextTooltip, children, __menuScope, ...naturalProps }) => {
|
|
144
145
|
const [optionsMenuOpen, setOptionsMenuOpen] = useControllableState({
|
|
145
146
|
prop: open,
|
|
146
147
|
defaultProp: defaultOpen,
|
|
147
148
|
onChange: onOpenChange
|
|
148
149
|
});
|
|
150
|
+
const { onAction } = useMenu("DropdownMenuRoot", __menuScope);
|
|
149
151
|
const handleActionClick = useCallback((action, event) => {
|
|
150
152
|
if (action.properties?.disabled) {
|
|
151
153
|
return;
|
|
@@ -155,14 +157,9 @@ var DropdownMenuRoot = ({ items: propsItems, group, open, defaultOpen, onOpenCha
|
|
|
155
157
|
suppressNextTooltip.current = true;
|
|
156
158
|
}
|
|
157
159
|
setOptionsMenuOpen(false);
|
|
158
|
-
|
|
159
|
-
parent: group,
|
|
160
|
-
caller
|
|
161
|
-
});
|
|
160
|
+
onAction?.(action);
|
|
162
161
|
}, [
|
|
163
|
-
|
|
164
|
-
group,
|
|
165
|
-
caller
|
|
162
|
+
onAction
|
|
166
163
|
]);
|
|
167
164
|
const items = useMenuItems(group, propsItems);
|
|
168
165
|
return /* @__PURE__ */ React3.createElement(NaturalDropdownMenu.Root, {
|
|
@@ -188,10 +185,10 @@ var DropdownMenu = {
|
|
|
188
185
|
|
|
189
186
|
// packages/ui/react-ui-menu/src/components/ToolbarMenu.tsx
|
|
190
187
|
import React4, { useCallback as useCallback2, useRef } from "react";
|
|
191
|
-
import { Icon as Icon2, Toolbar as NaturalToolbar
|
|
188
|
+
import { Icon as Icon2, Toolbar as NaturalToolbar } from "@dxos/react-ui";
|
|
192
189
|
import { useAttention } from "@dxos/react-ui-attention";
|
|
193
190
|
|
|
194
|
-
// packages/ui/react-ui-menu/src/
|
|
191
|
+
// packages/ui/react-ui-menu/src/defs.ts
|
|
195
192
|
import { ACTION_GROUP_TYPE as ACTION_GROUP_TYPE2 } from "@dxos/app-graph";
|
|
196
193
|
var MenuSeparatorType = "@dxos/react-ui-toolbar/separator";
|
|
197
194
|
var isSeparator = (node) => node.type === MenuSeparatorType;
|
|
@@ -199,10 +196,12 @@ var isMenuGroup = (node) => node.type === ACTION_GROUP_TYPE2;
|
|
|
199
196
|
|
|
200
197
|
// packages/ui/react-ui-menu/src/components/ToolbarMenu.tsx
|
|
201
198
|
var ActionToolbarItem = ({ action, __menuScope }) => {
|
|
202
|
-
const { iconSize } = useMenu("ActionToolbarItem", __menuScope);
|
|
203
|
-
const
|
|
204
|
-
|
|
205
|
-
|
|
199
|
+
const { onAction, iconSize } = useMenu("ActionToolbarItem", __menuScope);
|
|
200
|
+
const handleClick = useCallback2(() => {
|
|
201
|
+
onAction?.(action);
|
|
202
|
+
}, [
|
|
203
|
+
action,
|
|
204
|
+
onAction
|
|
206
205
|
]);
|
|
207
206
|
const { icon, iconOnly = true, disabled, testId, hidden, classNames } = action.properties;
|
|
208
207
|
const Root = icon ? NaturalToolbar.IconButton : NaturalToolbar.Button;
|
|
@@ -210,7 +209,9 @@ var ActionToolbarItem = ({ action, __menuScope }) => {
|
|
|
210
209
|
icon,
|
|
211
210
|
size: iconSize,
|
|
212
211
|
iconOnly,
|
|
213
|
-
label:
|
|
212
|
+
label: /* @__PURE__ */ React4.createElement(ActionLabel, {
|
|
213
|
+
action
|
|
214
|
+
})
|
|
214
215
|
} : {
|
|
215
216
|
children: /* @__PURE__ */ React4.createElement(ActionLabel, {
|
|
216
217
|
action
|
|
@@ -231,25 +232,24 @@ var ActionToolbarItem = ({ action, __menuScope }) => {
|
|
|
231
232
|
var DropdownMenuToolbarItem = ({ group, items: propsItems, __menuScope }) => {
|
|
232
233
|
const { iconOnly, disabled, testId } = group.properties;
|
|
233
234
|
const suppressNextTooltip = useRef(false);
|
|
234
|
-
const { t } = useTranslation2(translationKey);
|
|
235
235
|
const { iconSize } = useMenu("DropdownMenuToolbarItem", __menuScope);
|
|
236
236
|
const items = useMenuItems(group, propsItems, "DropdownMenuToolbarItem", __menuScope);
|
|
237
237
|
const activeItem = items?.find((item) => !!item.properties.checked);
|
|
238
238
|
const icon = group.properties.applyActive && // TODO(thure): Handle other menu item types.
|
|
239
239
|
activeItem?.properties.icon || group.properties.icon;
|
|
240
240
|
const Root = icon ? NaturalToolbar.IconButton : NaturalToolbar.Button;
|
|
241
|
-
const
|
|
241
|
+
const label = /* @__PURE__ */ React4.createElement(ActionLabel, {
|
|
242
|
+
action: group.properties.applyActive && activeItem ? activeItem : group
|
|
243
|
+
});
|
|
242
244
|
const rootProps = icon ? {
|
|
243
245
|
icon,
|
|
244
246
|
size: iconSize,
|
|
245
247
|
iconOnly,
|
|
246
|
-
label
|
|
248
|
+
label,
|
|
247
249
|
caretDown: true,
|
|
248
250
|
suppressNextTooltip
|
|
249
251
|
} : {
|
|
250
|
-
children: /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement(
|
|
251
|
-
action: labelAction
|
|
252
|
-
}), /* @__PURE__ */ React4.createElement(Icon2, {
|
|
252
|
+
children: /* @__PURE__ */ React4.createElement(React4.Fragment, null, label, /* @__PURE__ */ React4.createElement(Icon2, {
|
|
253
253
|
size: 3,
|
|
254
254
|
icon: "ph--caret-down--bold",
|
|
255
255
|
classNames: "mis-1"
|
|
@@ -270,22 +270,23 @@ var DropdownMenuToolbarItem = ({ group, items: propsItems, __menuScope }) => {
|
|
|
270
270
|
}
|
|
271
271
|
})));
|
|
272
272
|
};
|
|
273
|
-
var ToggleGroupItem = ({
|
|
274
|
-
const { iconSize } = useMenu("ToggleGroupItem", __menuScope);
|
|
275
|
-
const { t } = useTranslation2(translationKey);
|
|
273
|
+
var ToggleGroupItem = ({ action, __menuScope }) => {
|
|
274
|
+
const { iconSize, onAction } = useMenu("ToggleGroupItem", __menuScope);
|
|
276
275
|
const { icon, iconOnly = true, disabled, testId, hidden, classNames } = action.properties;
|
|
277
|
-
const handleClick = useCallback2(() =>
|
|
278
|
-
|
|
279
|
-
}
|
|
276
|
+
const handleClick = useCallback2(() => {
|
|
277
|
+
onAction?.(action);
|
|
278
|
+
}, [
|
|
280
279
|
action,
|
|
281
|
-
|
|
280
|
+
onAction
|
|
282
281
|
]);
|
|
283
282
|
const Root = icon ? NaturalToolbar.ToggleGroupIconItem : NaturalToolbar.ToggleGroupItem;
|
|
284
283
|
const rootProps = icon ? {
|
|
285
284
|
icon,
|
|
286
285
|
size: iconSize,
|
|
287
286
|
iconOnly,
|
|
288
|
-
label:
|
|
287
|
+
label: /* @__PURE__ */ React4.createElement(ActionLabel, {
|
|
288
|
+
action
|
|
289
|
+
})
|
|
289
290
|
} : {
|
|
290
291
|
children: /* @__PURE__ */ React4.createElement(ActionLabel, {
|
|
291
292
|
action
|
|
@@ -319,7 +320,6 @@ var ToggleGroupToolbarItem = ({ group, items: propsItems, __menuScope }) => {
|
|
|
319
320
|
// TODO(thure): Handle other menu item types.
|
|
320
321
|
items.map((action) => /* @__PURE__ */ React4.createElement(ToggleGroupItem, {
|
|
321
322
|
key: action.id,
|
|
322
|
-
group,
|
|
323
323
|
action
|
|
324
324
|
}))
|
|
325
325
|
)
|
|
@@ -332,8 +332,8 @@ var ToolbarMenu = ({ __menuScope, classNames, ...props }) => {
|
|
|
332
332
|
return /* @__PURE__ */ React4.createElement(NaturalToolbar.Root, {
|
|
333
333
|
...props,
|
|
334
334
|
classNames: [
|
|
335
|
-
"p-1",
|
|
336
|
-
!hasAttention && "
|
|
335
|
+
"p-0 pointer-fine:p-1 attention-surface",
|
|
336
|
+
!hasAttention && "opacity-20",
|
|
337
337
|
classNames
|
|
338
338
|
]
|
|
339
339
|
}, items?.map((item, i) => isSeparator(item) ? /* @__PURE__ */ React4.createElement(NaturalToolbar.Separator, {
|
|
@@ -360,11 +360,10 @@ var ToolbarMenu = ({ __menuScope, classNames, ...props }) => {
|
|
|
360
360
|
)));
|
|
361
361
|
};
|
|
362
362
|
|
|
363
|
-
// packages/ui/react-ui-menu/src/hooks
|
|
364
|
-
import { RegistryContext, useRxValue } from "@effect-rx/rx-react";
|
|
363
|
+
// packages/ui/react-ui-menu/src/hooks.ts
|
|
365
364
|
import { useSignalEffect } from "@preact/signals-react";
|
|
366
|
-
import { useCallback as useCallback3,
|
|
367
|
-
import { Graph
|
|
365
|
+
import { useCallback as useCallback3, useState } from "react";
|
|
366
|
+
import { Graph } from "@dxos/app-graph";
|
|
368
367
|
var edgesArrayToRecord = (edges) => {
|
|
369
368
|
return Object.fromEntries(Object.entries(edges.reduce((acc, { source, target }) => {
|
|
370
369
|
if (!acc[source]) {
|
|
@@ -388,29 +387,35 @@ var edgesArrayToRecord = (edges) => {
|
|
|
388
387
|
targetEdges.inbound.push(source);
|
|
389
388
|
}
|
|
390
389
|
return acc;
|
|
391
|
-
}, {})))
|
|
390
|
+
}, {})).map(([id, { outbound }]) => [
|
|
391
|
+
id,
|
|
392
|
+
outbound
|
|
393
|
+
]));
|
|
392
394
|
};
|
|
393
395
|
var useMenuActions = (actionCreator) => {
|
|
394
|
-
const registry = useContext(RegistryContext);
|
|
395
396
|
const initialMenuGraphProps = actionCreator();
|
|
396
397
|
const [graph] = useState(new Graph({
|
|
397
|
-
registry,
|
|
398
398
|
nodes: initialMenuGraphProps.nodes,
|
|
399
399
|
edges: edgesArrayToRecord(initialMenuGraphProps.edges)
|
|
400
400
|
}));
|
|
401
401
|
useSignalEffect(() => {
|
|
402
402
|
const menuGraphProps = actionCreator();
|
|
403
|
-
graph.
|
|
404
|
-
graph.
|
|
403
|
+
graph._addNodes(menuGraphProps.nodes);
|
|
404
|
+
graph._addEdges(menuGraphProps.edges);
|
|
405
405
|
});
|
|
406
|
-
const
|
|
407
|
-
|
|
408
|
-
|
|
406
|
+
const resolveGroupItems = useCallback3((sourceNode = graph.root) => {
|
|
407
|
+
if (graph) {
|
|
408
|
+
return graph.nodes(sourceNode, {
|
|
409
|
+
filter: (n) => true
|
|
410
|
+
}) || null;
|
|
411
|
+
} else {
|
|
412
|
+
return null;
|
|
413
|
+
}
|
|
409
414
|
}, [
|
|
410
415
|
graph
|
|
411
416
|
]);
|
|
412
417
|
return {
|
|
413
|
-
|
|
418
|
+
resolveGroupItems
|
|
414
419
|
};
|
|
415
420
|
};
|
|
416
421
|
export {
|
|
@@ -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/
|
|
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": ";AAIA,SAASA,4BAA4B;AACrC,OAAOC,UAAiDC,mBAAmB;AAE3E,SAASC,gBAAgBC,qBAAqBC,YAAwC;;;ACHtF,OAAOC,WAAW;AAGlB,SAASC,kBAAkB;AAC3B,SAASC,mBAAmBC,
|
|
6
|
-
"names": ["useControllableState", "React", "useCallback", "DropdownMenu", "NaturalDropdownMenu", "Icon", "React", "keySymbols", "toLocalizedString", "useTranslation", "mx", "descriptionText", "translationKey", "ACTION_GROUP_TYPE", "ACTION_TYPE", "actionGroupSymbol", "getHostPlatform", "getShortcut", "action", "properties", "keyBinding", "getHostPlatform", "
|
|
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": ["useControllableState", "React", "useCallback", "DropdownMenu", "NaturalDropdownMenu", "Icon", "React", "keySymbols", "toLocalizedString", "useTranslation", "mx", "descriptionText", "translationKey", "ACTION_GROUP_TYPE", "ACTION_TYPE", "actionGroupSymbol", "getHostPlatform", "getShortcut", "action", "properties", "keyBinding", "getHostPlatform", "noop", "createMenuAction", "id", "properties", "type", "ACTION_TYPE", "data", "createMenuItemGroup", "ACTION_GROUP_TYPE", "actionGroupSymbol", "createGapSeparator", "source", "nodes", "variant", "undefined", "edges", "target", "createLineSeparator", "ActionLabel", "action", "shortcut", "getShortcut", "t", "useTranslation", "translationKey", "span", "className", "toLocalizedString", "properties", "label", "mx", "descriptionText", "keySymbols", "join", "createContextScope", "React", "useMemo", "MENU_NAME", "createMenuContext", "createMenuScope", "createContextScope", "MenuContextProvider", "useMenu", "menuContextDefaults", "iconSize", "onAction", "resolveGroupItems", "useMenuScope", "MenuProvider", "children", "attendableId", "scope", "undefined", "React", "useMenuItems", "group", "propsItems", "consumerName", "__menuScope", "useMemo", "DropdownMenuItem", "item", "onClick", "__menuScope", "action", "handleClick", "useCallback", "event", "iconSize", "useMenu", "React", "NaturalDropdownMenu", "Item", "classNames", "disabled", "properties", "testId", "icon", "Icon", "size", "ActionLabel", "DropdownMenuRoot", "items", "propsItems", "group", "open", "defaultOpen", "onOpenChange", "suppressNextTooltip", "children", "naturalProps", "optionsMenuOpen", "setOptionsMenuOpen", "useControllableState", "prop", "defaultProp", "onChange", "onAction", "handleActionClick", "stopPropagation", "current", "useMenuItems", "Root", "nextOpen", "Portal", "Content", "Viewport", "map", "key", "id", "Arrow", "DropdownMenu", "Trigger", "VirtualTrigger", "React", "useCallback", "useRef", "Icon", "Toolbar", "NaturalToolbar", "useAttention", "ACTION_GROUP_TYPE", "MenuSeparatorType", "isSeparator", "node", "type", "isMenuGroup", "ACTION_GROUP_TYPE", "ActionToolbarItem", "action", "__menuScope", "onAction", "iconSize", "useMenu", "handleClick", "useCallback", "icon", "iconOnly", "disabled", "testId", "hidden", "classNames", "properties", "Root", "NaturalToolbar", "IconButton", "Button", "rootProps", "size", "label", "React", "ActionLabel", "children", "key", "id", "onClick", "variant", "DropdownMenuToolbarItem", "group", "items", "propsItems", "suppressNextTooltip", "useRef", "useMenuItems", "activeItem", "find", "item", "checked", "applyActive", "caretDown", "Icon", "DropdownMenu", "Trigger", "asChild", "ToggleGroupItem", "ToggleGroupIconItem", "value", "ToggleGroupToolbarItem", "selectCardinality", "ToggleGroup", "type", "map", "ToolbarMenu", "props", "undefined", "attendableId", "hasAttention", "useAttention", "i", "isSeparator", "Separator", "isMenuGroup", "useSignalEffect", "useCallback", "useState", "Graph", "edgesArrayToRecord", "edges", "Object", "fromEntries", "entries", "reduce", "acc", "source", "target", "inbound", "outbound", "sourceEdges", "includes", "push", "targetEdges", "map", "id", "useMenuActions", "actionCreator", "initialMenuGraphProps", "graph", "useState", "Graph", "nodes", "useSignalEffect", "menuGraphProps", "_addNodes", "_addEdges", "resolveGroupItems", "useCallback", "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":
|
|
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/browser/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":31412},"packages/ui/react-ui-menu/dist/lib/browser/index.mjs":{"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}}}
|