@dxos/react-ui-menu 0.8.3 → 0.8.4-main.f9ba587
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 +75 -16
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +75 -16
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/builder.d.ts +14 -0
- package/dist/types/src/builder.d.ts.map +1 -0
- package/dist/types/src/components/ActionLabel.d.ts.map +1 -1
- package/dist/types/src/components/Menus.stories.d.ts +2 -2
- package/dist/types/src/components/Menus.stories.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +3 -4
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +17 -16
- package/src/builder.ts +62 -0
- package/src/components/ActionLabel.tsx +1 -2
- package/src/components/Menus.stories.tsx +6 -4
- package/src/components/ToolbarMenu.tsx +1 -1
- package/src/index.ts +1 -0
- package/src/translations.ts +5 -3
- package/dist/lib/node/index.cjs +0 -506
- package/dist/lib/node/index.cjs.map +0 -7
- package/dist/lib/node/meta.json +0 -1
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
//
|
|
1
|
+
// src/index.ts
|
|
2
2
|
import { rxFromSignal } from "@dxos/app-graph";
|
|
3
3
|
|
|
4
|
-
//
|
|
4
|
+
// src/components/DropdownMenu.tsx
|
|
5
5
|
import { useSignals as _useSignals3 } from "@preact-signals/safe-react/tracking";
|
|
6
6
|
import { useControllableState } from "@radix-ui/react-use-controllable-state";
|
|
7
7
|
import React3, { useCallback } from "react";
|
|
8
8
|
import { DropdownMenu as NaturalDropdownMenu, Icon } from "@dxos/react-ui";
|
|
9
9
|
|
|
10
|
-
//
|
|
10
|
+
// src/components/ActionLabel.tsx
|
|
11
11
|
import { useSignals as _useSignals } from "@preact-signals/safe-react/tracking";
|
|
12
12
|
import React from "react";
|
|
13
13
|
import { keySymbols } from "@dxos/keyboard";
|
|
14
14
|
import { toLocalizedString, useTranslation } from "@dxos/react-ui";
|
|
15
15
|
import { mx, descriptionText } from "@dxos/react-ui-theme";
|
|
16
16
|
|
|
17
|
-
//
|
|
18
|
-
var translationKey = "
|
|
19
|
-
var
|
|
17
|
+
// src/translations.ts
|
|
18
|
+
var translationKey = "react-ui-menu";
|
|
19
|
+
var translations = [
|
|
20
20
|
{
|
|
21
21
|
"en-US": {
|
|
22
22
|
[translationKey]: {}
|
|
@@ -24,7 +24,7 @@ var translations_default = [
|
|
|
24
24
|
}
|
|
25
25
|
];
|
|
26
26
|
|
|
27
|
-
//
|
|
27
|
+
// src/util.ts
|
|
28
28
|
import { ACTION_GROUP_TYPE, ACTION_TYPE, actionGroupSymbol } from "@dxos/app-graph";
|
|
29
29
|
import { getHostPlatform } from "@dxos/util";
|
|
30
30
|
var getShortcut = (action) => {
|
|
@@ -79,12 +79,12 @@ var createLineSeparator = (id = "line", source = "root") => ({
|
|
|
79
79
|
]
|
|
80
80
|
});
|
|
81
81
|
|
|
82
|
-
//
|
|
82
|
+
// src/components/ActionLabel.tsx
|
|
83
83
|
var ActionLabel = ({ action }) => {
|
|
84
84
|
var _effect = _useSignals();
|
|
85
85
|
try {
|
|
86
|
-
const shortcut = getShortcut(action);
|
|
87
86
|
const { t } = useTranslation(translationKey);
|
|
87
|
+
const shortcut = getShortcut(action);
|
|
88
88
|
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("span", {
|
|
89
89
|
className: "grow truncate"
|
|
90
90
|
}, toLocalizedString(action.properties.label, t)), shortcut && /* @__PURE__ */ React.createElement("span", {
|
|
@@ -99,7 +99,7 @@ var actionLabel = (action, t) => {
|
|
|
99
99
|
return `${toLocalizedString(action.properties.label, t)}${shortcut ? ` (${keySymbols(shortcut).join("")})` : ""}`;
|
|
100
100
|
};
|
|
101
101
|
|
|
102
|
-
//
|
|
102
|
+
// src/components/MenuContext.tsx
|
|
103
103
|
import { useSignals as _useSignals2 } from "@preact-signals/safe-react/tracking";
|
|
104
104
|
import { createContextScope } from "@radix-ui/react-context";
|
|
105
105
|
import React2, { useMemo } from "react";
|
|
@@ -134,7 +134,7 @@ var useMenuItems = (group, propsItems, consumerName = "useMenuItemConsumer", __m
|
|
|
134
134
|
]);
|
|
135
135
|
};
|
|
136
136
|
|
|
137
|
-
//
|
|
137
|
+
// src/components/DropdownMenu.tsx
|
|
138
138
|
var DropdownMenuItem = ({ item, onClick, __menuScope }) => {
|
|
139
139
|
var _effect = _useSignals3();
|
|
140
140
|
try {
|
|
@@ -203,20 +203,20 @@ var DropdownMenu = {
|
|
|
203
203
|
VirtualTrigger: NaturalDropdownMenu.VirtualTrigger
|
|
204
204
|
};
|
|
205
205
|
|
|
206
|
-
//
|
|
206
|
+
// src/components/ToolbarMenu.tsx
|
|
207
207
|
import { useSignals as _useSignals4 } from "@preact-signals/safe-react/tracking";
|
|
208
208
|
import React4, { Fragment, useCallback as useCallback2 } from "react";
|
|
209
209
|
import { Icon as Icon2, Toolbar as NaturalToolbar, useTranslation as useTranslation2 } from "@dxos/react-ui";
|
|
210
210
|
import { useAttention } from "@dxos/react-ui-attention";
|
|
211
211
|
import { mx as mx2, textBlockWidth, toolbarLayout } from "@dxos/react-ui-theme";
|
|
212
212
|
|
|
213
|
-
//
|
|
213
|
+
// src/types.ts
|
|
214
214
|
import { ACTION_GROUP_TYPE as ACTION_GROUP_TYPE2 } from "@dxos/app-graph";
|
|
215
215
|
var MenuSeparatorType = "@dxos/react-ui-toolbar/separator";
|
|
216
216
|
var isSeparator = (node) => node.type === MenuSeparatorType;
|
|
217
217
|
var isMenuGroup = (node) => node.type === ACTION_GROUP_TYPE2;
|
|
218
218
|
|
|
219
|
-
//
|
|
219
|
+
// src/components/ToolbarMenu.tsx
|
|
220
220
|
var ActionToolbarItem = ({ action, __menuScope }) => {
|
|
221
221
|
var _effect = _useSignals4();
|
|
222
222
|
try {
|
|
@@ -370,7 +370,7 @@ var ToolbarMenu = ({ __menuScope, classNames, textBlockWidth: wrapContents, ...p
|
|
|
370
370
|
const InnerRoot = wrapContents ? "div" : Fragment;
|
|
371
371
|
const innerRootProps = wrapContents ? {
|
|
372
372
|
role: "none",
|
|
373
|
-
className: mx2(textBlockWidth, toolbarLayout)
|
|
373
|
+
className: mx2(textBlockWidth, toolbarLayout, "bs-full")
|
|
374
374
|
} : {};
|
|
375
375
|
return /* @__PURE__ */ React4.createElement(NaturalToolbar.Root, {
|
|
376
376
|
...props,
|
|
@@ -406,7 +406,7 @@ var ToolbarMenu = ({ __menuScope, classNames, textBlockWidth: wrapContents, ...p
|
|
|
406
406
|
}
|
|
407
407
|
};
|
|
408
408
|
|
|
409
|
-
//
|
|
409
|
+
// src/hooks/useMenuActions.ts
|
|
410
410
|
import { RegistryContext, useRxValue } from "@effect-rx/rx-react";
|
|
411
411
|
import { useCallback as useCallback3, useContext, useEffect, useState } from "react";
|
|
412
412
|
import { Graph, ROOT_ID } from "@dxos/app-graph";
|
|
@@ -459,8 +459,67 @@ var useMenuActions = (props) => {
|
|
|
459
459
|
useGroupItems
|
|
460
460
|
};
|
|
461
461
|
};
|
|
462
|
+
|
|
463
|
+
// src/builder.ts
|
|
464
|
+
import { invariant } from "@dxos/invariant";
|
|
465
|
+
var __dxlog_file = "/__w/dxos/dxos/packages/ui/react-ui-menu/src/builder.ts";
|
|
466
|
+
var MenuBuilder = Object.freeze({
|
|
467
|
+
make: () => new MenuBuilderImpl({
|
|
468
|
+
nodes: [],
|
|
469
|
+
edges: []
|
|
470
|
+
}, "root")
|
|
471
|
+
});
|
|
472
|
+
var MenuBuilderImpl = class _MenuBuilderImpl {
|
|
473
|
+
constructor(_data, _rootId) {
|
|
474
|
+
this._data = _data;
|
|
475
|
+
this._rootId = _rootId;
|
|
476
|
+
}
|
|
477
|
+
action(id, invoke, properties) {
|
|
478
|
+
this._data.nodes.push(createMenuAction(id, invoke, properties));
|
|
479
|
+
this._data.edges.push({
|
|
480
|
+
source: this._rootId,
|
|
481
|
+
target: id
|
|
482
|
+
});
|
|
483
|
+
return this;
|
|
484
|
+
}
|
|
485
|
+
root(props) {
|
|
486
|
+
invariant(this._rootId === "root", "Root group can only be at the top level", {
|
|
487
|
+
F: __dxlog_file,
|
|
488
|
+
L: 42,
|
|
489
|
+
S: this,
|
|
490
|
+
A: [
|
|
491
|
+
"this._rootId === 'root'",
|
|
492
|
+
"'Root group can only be at the top level'"
|
|
493
|
+
]
|
|
494
|
+
});
|
|
495
|
+
invariant(this._data.nodes.find((node) => node.id === "root") === void 0, "Root group can only be created once", {
|
|
496
|
+
F: __dxlog_file,
|
|
497
|
+
L: 43,
|
|
498
|
+
S: this,
|
|
499
|
+
A: [
|
|
500
|
+
"this._data.nodes.find((node) => node.id === 'root') === undefined",
|
|
501
|
+
"'Root group can only be created once'"
|
|
502
|
+
]
|
|
503
|
+
});
|
|
504
|
+
this._data.nodes.push(createMenuItemGroup("root", props));
|
|
505
|
+
return this;
|
|
506
|
+
}
|
|
507
|
+
group(id, properties, cb) {
|
|
508
|
+
this._data.nodes.push(createMenuItemGroup(id, properties));
|
|
509
|
+
this._data.edges.push({
|
|
510
|
+
source: this._rootId,
|
|
511
|
+
target: id
|
|
512
|
+
});
|
|
513
|
+
cb(new _MenuBuilderImpl(this._data, id));
|
|
514
|
+
return this;
|
|
515
|
+
}
|
|
516
|
+
build() {
|
|
517
|
+
return this._data;
|
|
518
|
+
}
|
|
519
|
+
};
|
|
462
520
|
export {
|
|
463
521
|
DropdownMenu,
|
|
522
|
+
MenuBuilder,
|
|
464
523
|
MenuProvider,
|
|
465
524
|
MenuSeparatorType,
|
|
466
525
|
ToolbarMenu,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../../../src/index.ts", "../../../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 2024 DXOS.org\n//\n\nexport { rxFromSignal } from '@dxos/app-graph';\n\nexport * from './components';\nexport * from './hooks';\nexport * from './types';\nexport { createMenuAction, createMenuItemGroup, createLineSeparator, createGapSeparator } from './util';\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { useControllableState } from '@radix-ui/react-use-controllable-state';\nimport React, { type MouseEvent, 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 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 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 setOptionsMenuOpen(false);\n void action.data?.({ parent: group, caller });\n },\n [group, caller],\n );\n\n const items = useMenuItems(group, propsItems);\n\n return (\n <NaturalDropdownMenu.Root open={optionsMenuOpen} onOpenChange={setOptionsMenuOpen} {...naturalProps}>\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, { Fragment, useCallback } from 'react';\n\nimport { Icon, Toolbar as NaturalToolbar, type ToolbarRootProps, useTranslation } from '@dxos/react-ui';\nimport { useAttention } from '@dxos/react-ui-attention';\nimport { mx, textBlockWidth, toolbarLayout } from '@dxos/react-ui-theme';\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 & { textBlockWidth?: boolean };\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 { 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 }\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}>\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 = ({\n __menuScope,\n classNames,\n textBlockWidth: wrapContents,\n ...props\n}: MenuScopedProps<ToolbarMenuProps>) => {\n const items = useMenuItems(undefined, undefined, 'ToolbarMenu', __menuScope);\n const { attendableId } = useMenu('ToolbarMenu', __menuScope);\n const { hasAttention } = useAttention(attendableId);\n const InnerRoot = wrapContents ? 'div' : Fragment;\n const innerRootProps = wrapContents ? { role: 'none', className: mx(textBlockWidth, toolbarLayout) } : {};\n return (\n <NaturalToolbar.Root\n {...props}\n layoutManaged={wrapContents}\n classNames={[attendableId && !hasAttention && '*:opacity-20 !bg-transparent', classNames]}\n >\n <InnerRoot {...innerRootProps}>\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 </InnerRoot>\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, type Rx, useRxValue } from '@effect-rx/rx-react';\nimport { useCallback, useContext, useEffect, 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 = (props: Rx.Rx<ActionGraphProps>) => {\n const registry = useContext(RegistryContext);\n const menuGraphProps = useRxValue(props);\n\n const [graph] = useState(\n new Graph({\n registry,\n nodes: menuGraphProps.nodes as Node[],\n edges: edgesArrayToRecord(menuGraphProps.edges),\n }),\n );\n\n useEffect(() => {\n graph.addNodes(menuGraphProps.nodes);\n graph.addEdges(menuGraphProps.edges);\n }, [menuGraphProps]);\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,oBAAoB;;;;ACA7B,SAASC,4BAA4B;AACrC,OAAOC,UAA0BC,mBAAmB;AAEpD,SAASC,gBAAgBC,qBAAqBC,YAAwC;;;;ACHtF,OAAOC,WAAW;AAGlB,SAASC,kBAAkB;AAC3B,SAASC,mBAAmBC,sBAAsC;AAClE,SAASC,IAAIC,uBAAuB;;;
|
|
6
|
-
"names": ["rxFromSignal", "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", "createMenuAction", "id", "invoke", "properties", "type", "ACTION_TYPE", "data", "createMenuItemGroup", "ACTION_GROUP_TYPE", "actionGroupSymbol", "createGapSeparator", "source", "nodes", "variant", "undefined", "edges", "target", "createLineSeparator", "ActionLabel", "action", "
|
|
3
|
+
"sources": ["../../../src/index.ts", "../../../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", "../../../src/builder.ts"],
|
|
4
|
+
"sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nexport { rxFromSignal } from '@dxos/app-graph';\n\nexport * from './components';\nexport * from './hooks';\nexport * from './types';\nexport { createMenuAction, createMenuItemGroup, createLineSeparator, createGapSeparator } from './util';\nexport { MenuBuilder } from './builder';\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { useControllableState } from '@radix-ui/react-use-controllable-state';\nimport React, { type MouseEvent, 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 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 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 setOptionsMenuOpen(false);\n void action.data?.({ parent: group, caller });\n },\n [group, caller],\n );\n\n const items = useMenuItems(group, propsItems);\n\n return (\n <NaturalDropdownMenu.Root open={optionsMenuOpen} onOpenChange={setOptionsMenuOpen} {...naturalProps}>\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 { t } = useTranslation(translationKey);\n const shortcut = getShortcut(action);\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\nimport { type Resource } from '@dxos/react-ui';\n\nexport const translationKey = 'react-ui-menu';\n\nexport const translations = [\n {\n 'en-US': {\n [translationKey]: {},\n },\n },\n] as const satisfies Resource[];\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, { Fragment, useCallback } from 'react';\n\nimport { Icon, Toolbar as NaturalToolbar, type ToolbarRootProps, useTranslation } from '@dxos/react-ui';\nimport { useAttention } from '@dxos/react-ui-attention';\nimport { mx, textBlockWidth, toolbarLayout } from '@dxos/react-ui-theme';\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 & { textBlockWidth?: boolean };\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 { 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 }\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}>\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 = ({\n __menuScope,\n classNames,\n textBlockWidth: wrapContents,\n ...props\n}: MenuScopedProps<ToolbarMenuProps>) => {\n const items = useMenuItems(undefined, undefined, 'ToolbarMenu', __menuScope);\n const { attendableId } = useMenu('ToolbarMenu', __menuScope);\n const { hasAttention } = useAttention(attendableId);\n const InnerRoot = wrapContents ? 'div' : Fragment;\n const innerRootProps = wrapContents ? { role: 'none', className: mx(textBlockWidth, toolbarLayout, 'bs-full') } : {};\n return (\n <NaturalToolbar.Root\n {...props}\n layoutManaged={wrapContents}\n classNames={[attendableId && !hasAttention && '*:opacity-20 !bg-transparent', classNames]}\n >\n <InnerRoot {...innerRootProps}>\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 </InnerRoot>\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, type Rx, useRxValue } from '@effect-rx/rx-react';\nimport { useCallback, useContext, useEffect, 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 = (props: Rx.Rx<ActionGraphProps>) => {\n const registry = useContext(RegistryContext);\n const menuGraphProps = useRxValue(props);\n\n const [graph] = useState(\n new Graph({\n registry,\n nodes: menuGraphProps.nodes as Node[],\n edges: edgesArrayToRecord(menuGraphProps.edges),\n }),\n );\n\n useEffect(() => {\n graph.addNodes(menuGraphProps.nodes);\n graph.addEdges(menuGraphProps.edges);\n }, [menuGraphProps]);\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", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { invariant } from '@dxos/invariant';\n\nimport type { ActionGraphProps } from './hooks';\nimport type { MenuActionProperties, MenuItemGroupProperties } from './types';\nimport { createMenuAction, createMenuItemGroup } from './util';\n\nexport interface ActionGroupBuilder {\n action<P extends {} = {}>(id: string, invoke: () => void, properties: P & MenuActionProperties): this;\n group<P extends {} = {}>(\n id: string,\n properties: P & MenuItemGroupProperties,\n cb: (builder: ActionGroupBuilder) => void,\n ): this;\n}\n\nexport interface MenuBuilder extends ActionGroupBuilder {\n root(props: MenuItemGroupProperties): this;\n build(): ActionGraphProps;\n}\n\nexport const MenuBuilder = Object.freeze({\n make: (): MenuBuilder => new MenuBuilderImpl({ nodes: [], edges: [] }, 'root'),\n});\n\nclass MenuBuilderImpl implements MenuBuilder {\n constructor(\n private readonly _data: ActionGraphProps,\n private readonly _rootId: string,\n ) {}\n\n action<P extends {} = {}>(id: string, invoke: () => void, properties: P & MenuActionProperties): this {\n this._data.nodes.push(createMenuAction(id, invoke, properties));\n this._data.edges.push({ source: this._rootId, target: id });\n return this;\n }\n\n root(props: MenuItemGroupProperties): this {\n invariant(this._rootId === 'root', 'Root group can only be at the top level');\n invariant(this._data.nodes.find((node) => node.id === 'root') === undefined, 'Root group can only be created once');\n this._data.nodes.push(createMenuItemGroup('root', props));\n return this;\n }\n\n group<P extends {} = {}>(\n id: string,\n properties: P & MenuItemGroupProperties,\n cb: (builder: ActionGroupBuilder) => void,\n ): this {\n this._data.nodes.push(createMenuItemGroup(id, properties));\n this._data.edges.push({ source: this._rootId, target: id });\n cb(new MenuBuilderImpl(this._data, id));\n return this;\n }\n\n build(): ActionGraphProps {\n return this._data;\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["rxFromSignal", "useControllableState", "React", "useCallback", "DropdownMenu", "NaturalDropdownMenu", "Icon", "React", "keySymbols", "toLocalizedString", "useTranslation", "mx", "descriptionText", "translationKey", "translations", "ACTION_GROUP_TYPE", "ACTION_TYPE", "actionGroupSymbol", "getHostPlatform", "getShortcut", "action", "properties", "keyBinding", "getHostPlatform", "createMenuAction", "id", "invoke", "properties", "type", "ACTION_TYPE", "data", "createMenuItemGroup", "ACTION_GROUP_TYPE", "actionGroupSymbol", "createGapSeparator", "source", "nodes", "variant", "undefined", "edges", "target", "createLineSeparator", "ActionLabel", "action", "t", "useTranslation", "translationKey", "shortcut", "getShortcut", "span", "className", "toLocalizedString", "properties", "label", "mx", "descriptionText", "keySymbols", "join", "actionLabel", "createContextScope", "React", "useMemo", "MENU_NAME", "createMenuContext", "createMenuScope", "createContextScope", "MenuContextProvider", "useMenu", "menuContextDefaults", "iconSize", "useGroupItems", "useMenuScope", "MenuProvider", "children", "attendableId", "scope", "undefined", "React", "useMenuItems", "group", "propsItems", "consumerName", "__menuScope", "groupItems", "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", "caller", "children", "naturalProps", "optionsMenuOpen", "setOptionsMenuOpen", "useControllableState", "prop", "defaultProp", "onChange", "handleActionClick", "stopPropagation", "data", "parent", "useMenuItems", "Root", "Portal", "Content", "Viewport", "map", "key", "id", "Arrow", "DropdownMenu", "Trigger", "VirtualTrigger", "React", "Fragment", "useCallback", "Icon", "Toolbar", "NaturalToolbar", "useTranslation", "useAttention", "mx", "textBlockWidth", "toolbarLayout", "ACTION_GROUP_TYPE", "MenuSeparatorType", "isSeparator", "node", "type", "isMenuGroup", "ACTION_GROUP_TYPE", "ActionToolbarItem", "action", "__menuScope", "iconSize", "useMenu", "t", "useTranslation", "translationKey", "handleClick", "useCallback", "data", "icon", "iconOnly", "disabled", "testId", "hidden", "classNames", "properties", "Root", "NaturalToolbar", "IconButton", "Button", "rootProps", "size", "label", "actionLabel", "children", "React", "ActionLabel", "key", "id", "onClick", "variant", "DropdownMenuToolbarItem", "group", "items", "propsItems", "useMenuItems", "activeItem", "find", "item", "checked", "applyActive", "labelAction", "caretDown", "Icon", "DropdownMenu", "Trigger", "asChild", "ToggleGroupItem", "parent", "ToggleGroupIconItem", "value", "ToggleGroupToolbarItem", "selectCardinality", "ToggleGroup", "type", "map", "ToolbarMenu", "textBlockWidth", "wrapContents", "props", "undefined", "attendableId", "hasAttention", "useAttention", "InnerRoot", "Fragment", "innerRootProps", "role", "className", "mx", "toolbarLayout", "layoutManaged", "i", "isSeparator", "Separator", "isMenuGroup", "RegistryContext", "useRxValue", "useCallback", "useContext", "useEffect", "useState", "Graph", "ROOT_ID", "edgesArrayToRecord", "edges", "Object", "fromEntries", "entries", "reduce", "acc", "source", "target", "inbound", "outbound", "sourceEdges", "includes", "push", "targetEdges", "useMenuActions", "props", "registry", "useContext", "RegistryContext", "menuGraphProps", "useRxValue", "graph", "useState", "Graph", "nodes", "useEffect", "addNodes", "addEdges", "useGroupItems", "useCallback", "sourceNode", "items", "connections", "id", "ROOT_ID", "invariant", "MenuBuilder", "Object", "freeze", "make", "MenuBuilderImpl", "nodes", "edges", "_data", "_rootId", "action", "id", "invoke", "properties", "push", "createMenuAction", "source", "target", "root", "props", "invariant", "find", "node", "undefined", "createMenuItemGroup", "group", "cb", "build"]
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"inputs":{"
|
|
1
|
+
{"inputs":{"src/translations.ts":{"bytes":1041,"imports":[],"format":"esm"},"src/util.ts":{"bytes":5883,"imports":[{"path":"@dxos/app-graph","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"format":"esm"},"src/components/ActionLabel.tsx":{"bytes":4313,"imports":[{"path":"@preact-signals/safe-react/tracking","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":"src/translations.ts","kind":"import-statement","original":"../translations"},{"path":"src/util.ts","kind":"import-statement","original":"../util"}],"format":"esm"},"src/components/MenuContext.tsx":{"bytes":5209,"imports":[{"path":"@preact-signals/safe-react/tracking","kind":"import-statement","external":true},{"path":"@radix-ui/react-context","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true}],"format":"esm"},"src/components/DropdownMenu.tsx":{"bytes":10490,"imports":[{"path":"@preact-signals/safe-react/tracking","kind":"import-statement","external":true},{"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":"src/components/ActionLabel.tsx","kind":"import-statement","original":"./ActionLabel"},{"path":"src/components/MenuContext.tsx","kind":"import-statement","original":"./MenuContext"}],"format":"esm"},"src/types.ts":{"bytes":3194,"imports":[{"path":"@dxos/app-graph","kind":"import-statement","external":true}],"format":"esm"},"src/components/ToolbarMenu.tsx":{"bytes":24582,"imports":[{"path":"@preact-signals/safe-react/tracking","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/react-ui-theme","kind":"import-statement","external":true},{"path":"src/components/ActionLabel.tsx","kind":"import-statement","original":"./ActionLabel"},{"path":"src/components/DropdownMenu.tsx","kind":"import-statement","original":"./DropdownMenu"},{"path":"src/components/MenuContext.tsx","kind":"import-statement","original":"./MenuContext"},{"path":"src/translations.ts","kind":"import-statement","original":"../translations"},{"path":"src/types.ts","kind":"import-statement","original":"../types"}],"format":"esm"},"src/components/index.ts":{"bytes":673,"imports":[{"path":"src/components/DropdownMenu.tsx","kind":"import-statement","original":"./DropdownMenu"},{"path":"src/components/ToolbarMenu.tsx","kind":"import-statement","original":"./ToolbarMenu"},{"path":"src/components/MenuContext.tsx","kind":"import-statement","original":"./MenuContext"}],"format":"esm"},"src/hooks/useMenuActions.ts":{"bytes":6878,"imports":[{"path":"@effect-rx/rx-react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/app-graph","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/index.ts":{"bytes":476,"imports":[{"path":"src/hooks/useMenuActions.ts","kind":"import-statement","original":"./useMenuActions"}],"format":"esm"},"src/builder.ts":{"bytes":6629,"imports":[{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"src/util.ts","kind":"import-statement","original":"./util"}],"format":"esm"},"src/index.ts":{"bytes":1394,"imports":[{"path":"@dxos/app-graph","kind":"import-statement","external":true},{"path":"src/components/index.ts","kind":"import-statement","original":"./components"},{"path":"src/hooks/index.ts","kind":"import-statement","original":"./hooks"},{"path":"src/types.ts","kind":"import-statement","original":"./types"},{"path":"src/util.ts","kind":"import-statement","original":"./util"},{"path":"src/builder.ts","kind":"import-statement","original":"./builder"}],"format":"esm"}},"outputs":{"dist/lib/browser/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":35316},"dist/lib/browser/index.mjs":{"imports":[{"path":"@dxos/app-graph","kind":"import-statement","external":true},{"path":"@preact-signals/safe-react/tracking","kind":"import-statement","external":true},{"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":"@preact-signals/safe-react/tracking","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":"@preact-signals/safe-react/tracking","kind":"import-statement","external":true},{"path":"@radix-ui/react-context","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@preact-signals/safe-react/tracking","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/react-ui-theme","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":"react","kind":"import-statement","external":true},{"path":"@dxos/app-graph","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true}],"exports":["DropdownMenu","MenuBuilder","MenuProvider","MenuSeparatorType","ToolbarMenu","createGapSeparator","createLineSeparator","createMenuAction","createMenuItemGroup","createMenuScope","isMenuGroup","isSeparator","menuContextDefaults","rxFromSignal","useMenu","useMenuActions","useMenuItems"],"entryPoint":"src/index.ts","inputs":{"src/index.ts":{"bytesInOutput":48},"src/components/DropdownMenu.tsx":{"bytesInOutput":2621},"src/components/ActionLabel.tsx":{"bytesInOutput":1031},"src/translations.ts":{"bytesInOutput":118},"src/util.ts":{"bytesInOutput":1113},"src/components/MenuContext.tsx":{"bytesInOutput":1199},"src/components/index.ts":{"bytesInOutput":0},"src/components/ToolbarMenu.tsx":{"bytesInOutput":6700},"src/types.ts":{"bytesInOutput":258},"src/hooks/useMenuActions.ts":{"bytesInOutput":1447},"src/hooks/index.ts":{"bytesInOutput":0},"src/builder.ts":{"bytesInOutput":1535}},"bytes":16791}}}
|
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
|
|
2
2
|
|
|
3
|
-
//
|
|
3
|
+
// src/index.ts
|
|
4
4
|
import { rxFromSignal } from "@dxos/app-graph";
|
|
5
5
|
|
|
6
|
-
//
|
|
6
|
+
// src/components/DropdownMenu.tsx
|
|
7
7
|
import { useSignals as _useSignals3 } from "@preact-signals/safe-react/tracking";
|
|
8
8
|
import { useControllableState } from "@radix-ui/react-use-controllable-state";
|
|
9
9
|
import React3, { useCallback } from "react";
|
|
10
10
|
import { DropdownMenu as NaturalDropdownMenu, Icon } from "@dxos/react-ui";
|
|
11
11
|
|
|
12
|
-
//
|
|
12
|
+
// src/components/ActionLabel.tsx
|
|
13
13
|
import { useSignals as _useSignals } from "@preact-signals/safe-react/tracking";
|
|
14
14
|
import React from "react";
|
|
15
15
|
import { keySymbols } from "@dxos/keyboard";
|
|
16
16
|
import { toLocalizedString, useTranslation } from "@dxos/react-ui";
|
|
17
17
|
import { mx, descriptionText } from "@dxos/react-ui-theme";
|
|
18
18
|
|
|
19
|
-
//
|
|
20
|
-
var translationKey = "
|
|
21
|
-
var
|
|
19
|
+
// src/translations.ts
|
|
20
|
+
var translationKey = "react-ui-menu";
|
|
21
|
+
var translations = [
|
|
22
22
|
{
|
|
23
23
|
"en-US": {
|
|
24
24
|
[translationKey]: {}
|
|
@@ -26,7 +26,7 @@ var translations_default = [
|
|
|
26
26
|
}
|
|
27
27
|
];
|
|
28
28
|
|
|
29
|
-
//
|
|
29
|
+
// src/util.ts
|
|
30
30
|
import { ACTION_GROUP_TYPE, ACTION_TYPE, actionGroupSymbol } from "@dxos/app-graph";
|
|
31
31
|
import { getHostPlatform } from "@dxos/util";
|
|
32
32
|
var getShortcut = (action) => {
|
|
@@ -81,12 +81,12 @@ var createLineSeparator = (id = "line", source = "root") => ({
|
|
|
81
81
|
]
|
|
82
82
|
});
|
|
83
83
|
|
|
84
|
-
//
|
|
84
|
+
// src/components/ActionLabel.tsx
|
|
85
85
|
var ActionLabel = ({ action }) => {
|
|
86
86
|
var _effect = _useSignals();
|
|
87
87
|
try {
|
|
88
|
-
const shortcut = getShortcut(action);
|
|
89
88
|
const { t } = useTranslation(translationKey);
|
|
89
|
+
const shortcut = getShortcut(action);
|
|
90
90
|
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("span", {
|
|
91
91
|
className: "grow truncate"
|
|
92
92
|
}, toLocalizedString(action.properties.label, t)), shortcut && /* @__PURE__ */ React.createElement("span", {
|
|
@@ -101,7 +101,7 @@ var actionLabel = (action, t) => {
|
|
|
101
101
|
return `${toLocalizedString(action.properties.label, t)}${shortcut ? ` (${keySymbols(shortcut).join("")})` : ""}`;
|
|
102
102
|
};
|
|
103
103
|
|
|
104
|
-
//
|
|
104
|
+
// src/components/MenuContext.tsx
|
|
105
105
|
import { useSignals as _useSignals2 } from "@preact-signals/safe-react/tracking";
|
|
106
106
|
import { createContextScope } from "@radix-ui/react-context";
|
|
107
107
|
import React2, { useMemo } from "react";
|
|
@@ -136,7 +136,7 @@ var useMenuItems = (group, propsItems, consumerName = "useMenuItemConsumer", __m
|
|
|
136
136
|
]);
|
|
137
137
|
};
|
|
138
138
|
|
|
139
|
-
//
|
|
139
|
+
// src/components/DropdownMenu.tsx
|
|
140
140
|
var DropdownMenuItem = ({ item, onClick, __menuScope }) => {
|
|
141
141
|
var _effect = _useSignals3();
|
|
142
142
|
try {
|
|
@@ -205,20 +205,20 @@ var DropdownMenu = {
|
|
|
205
205
|
VirtualTrigger: NaturalDropdownMenu.VirtualTrigger
|
|
206
206
|
};
|
|
207
207
|
|
|
208
|
-
//
|
|
208
|
+
// src/components/ToolbarMenu.tsx
|
|
209
209
|
import { useSignals as _useSignals4 } from "@preact-signals/safe-react/tracking";
|
|
210
210
|
import React4, { Fragment, useCallback as useCallback2 } from "react";
|
|
211
211
|
import { Icon as Icon2, Toolbar as NaturalToolbar, useTranslation as useTranslation2 } from "@dxos/react-ui";
|
|
212
212
|
import { useAttention } from "@dxos/react-ui-attention";
|
|
213
213
|
import { mx as mx2, textBlockWidth, toolbarLayout } from "@dxos/react-ui-theme";
|
|
214
214
|
|
|
215
|
-
//
|
|
215
|
+
// src/types.ts
|
|
216
216
|
import { ACTION_GROUP_TYPE as ACTION_GROUP_TYPE2 } from "@dxos/app-graph";
|
|
217
217
|
var MenuSeparatorType = "@dxos/react-ui-toolbar/separator";
|
|
218
218
|
var isSeparator = (node) => node.type === MenuSeparatorType;
|
|
219
219
|
var isMenuGroup = (node) => node.type === ACTION_GROUP_TYPE2;
|
|
220
220
|
|
|
221
|
-
//
|
|
221
|
+
// src/components/ToolbarMenu.tsx
|
|
222
222
|
var ActionToolbarItem = ({ action, __menuScope }) => {
|
|
223
223
|
var _effect = _useSignals4();
|
|
224
224
|
try {
|
|
@@ -372,7 +372,7 @@ var ToolbarMenu = ({ __menuScope, classNames, textBlockWidth: wrapContents, ...p
|
|
|
372
372
|
const InnerRoot = wrapContents ? "div" : Fragment;
|
|
373
373
|
const innerRootProps = wrapContents ? {
|
|
374
374
|
role: "none",
|
|
375
|
-
className: mx2(textBlockWidth, toolbarLayout)
|
|
375
|
+
className: mx2(textBlockWidth, toolbarLayout, "bs-full")
|
|
376
376
|
} : {};
|
|
377
377
|
return /* @__PURE__ */ React4.createElement(NaturalToolbar.Root, {
|
|
378
378
|
...props,
|
|
@@ -408,7 +408,7 @@ var ToolbarMenu = ({ __menuScope, classNames, textBlockWidth: wrapContents, ...p
|
|
|
408
408
|
}
|
|
409
409
|
};
|
|
410
410
|
|
|
411
|
-
//
|
|
411
|
+
// src/hooks/useMenuActions.ts
|
|
412
412
|
import { RegistryContext, useRxValue } from "@effect-rx/rx-react";
|
|
413
413
|
import { useCallback as useCallback3, useContext, useEffect, useState } from "react";
|
|
414
414
|
import { Graph, ROOT_ID } from "@dxos/app-graph";
|
|
@@ -461,8 +461,67 @@ var useMenuActions = (props) => {
|
|
|
461
461
|
useGroupItems
|
|
462
462
|
};
|
|
463
463
|
};
|
|
464
|
+
|
|
465
|
+
// src/builder.ts
|
|
466
|
+
import { invariant } from "@dxos/invariant";
|
|
467
|
+
var __dxlog_file = "/__w/dxos/dxos/packages/ui/react-ui-menu/src/builder.ts";
|
|
468
|
+
var MenuBuilder = Object.freeze({
|
|
469
|
+
make: () => new MenuBuilderImpl({
|
|
470
|
+
nodes: [],
|
|
471
|
+
edges: []
|
|
472
|
+
}, "root")
|
|
473
|
+
});
|
|
474
|
+
var MenuBuilderImpl = class _MenuBuilderImpl {
|
|
475
|
+
constructor(_data, _rootId) {
|
|
476
|
+
this._data = _data;
|
|
477
|
+
this._rootId = _rootId;
|
|
478
|
+
}
|
|
479
|
+
action(id, invoke, properties) {
|
|
480
|
+
this._data.nodes.push(createMenuAction(id, invoke, properties));
|
|
481
|
+
this._data.edges.push({
|
|
482
|
+
source: this._rootId,
|
|
483
|
+
target: id
|
|
484
|
+
});
|
|
485
|
+
return this;
|
|
486
|
+
}
|
|
487
|
+
root(props) {
|
|
488
|
+
invariant(this._rootId === "root", "Root group can only be at the top level", {
|
|
489
|
+
F: __dxlog_file,
|
|
490
|
+
L: 42,
|
|
491
|
+
S: this,
|
|
492
|
+
A: [
|
|
493
|
+
"this._rootId === 'root'",
|
|
494
|
+
"'Root group can only be at the top level'"
|
|
495
|
+
]
|
|
496
|
+
});
|
|
497
|
+
invariant(this._data.nodes.find((node) => node.id === "root") === void 0, "Root group can only be created once", {
|
|
498
|
+
F: __dxlog_file,
|
|
499
|
+
L: 43,
|
|
500
|
+
S: this,
|
|
501
|
+
A: [
|
|
502
|
+
"this._data.nodes.find((node) => node.id === 'root') === undefined",
|
|
503
|
+
"'Root group can only be created once'"
|
|
504
|
+
]
|
|
505
|
+
});
|
|
506
|
+
this._data.nodes.push(createMenuItemGroup("root", props));
|
|
507
|
+
return this;
|
|
508
|
+
}
|
|
509
|
+
group(id, properties, cb) {
|
|
510
|
+
this._data.nodes.push(createMenuItemGroup(id, properties));
|
|
511
|
+
this._data.edges.push({
|
|
512
|
+
source: this._rootId,
|
|
513
|
+
target: id
|
|
514
|
+
});
|
|
515
|
+
cb(new _MenuBuilderImpl(this._data, id));
|
|
516
|
+
return this;
|
|
517
|
+
}
|
|
518
|
+
build() {
|
|
519
|
+
return this._data;
|
|
520
|
+
}
|
|
521
|
+
};
|
|
464
522
|
export {
|
|
465
523
|
DropdownMenu,
|
|
524
|
+
MenuBuilder,
|
|
466
525
|
MenuProvider,
|
|
467
526
|
MenuSeparatorType,
|
|
468
527
|
ToolbarMenu,
|