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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/dist/lib/browser/index.mjs +63 -58
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/node/index.cjs +58 -53
  5. package/dist/lib/node/index.cjs.map +4 -4
  6. package/dist/lib/node/meta.json +1 -1
  7. package/dist/lib/node-esm/index.mjs +63 -58
  8. package/dist/lib/node-esm/index.mjs.map +4 -4
  9. package/dist/lib/node-esm/meta.json +1 -1
  10. package/dist/types/src/components/ActionLabel.d.ts +4 -8
  11. package/dist/types/src/components/ActionLabel.d.ts.map +1 -1
  12. package/dist/types/src/components/DropdownMenu.d.ts +2 -3
  13. package/dist/types/src/components/DropdownMenu.d.ts.map +1 -1
  14. package/dist/types/src/components/MenuContext.d.ts +13 -4
  15. package/dist/types/src/components/MenuContext.d.ts.map +1 -1
  16. package/dist/types/src/components/ToolbarMenu.d.ts +1 -5
  17. package/dist/types/src/components/ToolbarMenu.d.ts.map +1 -1
  18. package/dist/types/src/{types.d.ts → defs.d.ts} +5 -3
  19. package/dist/types/src/defs.d.ts.map +1 -0
  20. package/dist/types/src/hooks.d.ts +17 -0
  21. package/dist/types/src/hooks.d.ts.map +1 -0
  22. package/dist/types/src/index.d.ts +1 -1
  23. package/dist/types/src/index.d.ts.map +1 -1
  24. package/dist/types/src/{components → testing}/Menus.stories.d.ts +1 -1
  25. package/dist/types/src/testing/Menus.stories.d.ts.map +1 -0
  26. package/dist/types/src/testing/index.d.ts +25 -1
  27. package/dist/types/src/testing/index.d.ts.map +1 -1
  28. package/dist/types/src/util.d.ts +2 -2
  29. package/dist/types/src/util.d.ts.map +1 -1
  30. package/dist/types/tsconfig.tsbuildinfo +1 -1
  31. package/package.json +12 -18
  32. package/src/components/ActionLabel.tsx +8 -11
  33. package/src/components/DropdownMenu.tsx +5 -5
  34. package/src/components/MenuContext.tsx +26 -11
  35. package/src/components/ToolbarMenu.tsx +29 -27
  36. package/src/{types.ts → defs.ts} +5 -2
  37. package/src/{hooks/useMenuActions.ts → hooks.ts} +20 -20
  38. package/src/index.ts +1 -1
  39. package/src/{components → testing}/Menus.stories.tsx +13 -13
  40. package/src/testing/index.ts +107 -1
  41. package/src/util.ts +7 -7
  42. package/dist/types/src/components/Menus.stories.d.ts.map +0 -1
  43. package/dist/types/src/hooks/index.d.ts +0 -2
  44. package/dist/types/src/hooks/index.d.ts.map +0 -1
  45. package/dist/types/src/hooks/useMenuActions.d.ts +0 -12
  46. package/dist/types/src/hooks/useMenuActions.d.ts.map +0 -1
  47. package/dist/types/src/testing/generator.d.ts +0 -26
  48. package/dist/types/src/testing/generator.d.ts.map +0 -1
  49. package/dist/types/src/types.d.ts.map +0 -1
  50. package/src/hooks/index.ts +0 -5
  51. package/src/testing/generator.ts +0 -115
@@ -3,35 +3,38 @@
3
3
  //
4
4
 
5
5
  import '@dxos-theme';
6
- import React, { useCallback, useMemo } from 'react';
6
+ import React, { useCallback } from 'react';
7
7
 
8
8
  import { faker } from '@dxos/random';
9
9
  import { IconButton } from '@dxos/react-ui';
10
10
  import { withLayout, withSignals, withTheme } from '@dxos/storybook-utils';
11
11
 
12
+ import { createActions, createNestedActions, createNestedActionsResolver, useMutateActions } from './index';
12
13
  import { DropdownMenu as NaturalDropdownMenu, ToolbarMenu, MenuProvider } from '../components';
14
+ import { type MenuAction, type MenuActionHandler } from '../defs';
13
15
  import { useMenuActions } from '../hooks';
14
- import { createActions, createNestedActions, createNestedActionsResolver, useMutateActions } from '../testing';
15
16
  import translations from '../translations';
16
- import { type MenuAction } from '../types';
17
17
 
18
18
  faker.seed(1234);
19
19
 
20
20
  export default {
21
21
  title: 'ui/react-ui-menu/Menus',
22
22
  component: ToolbarMenu,
23
- decorators: [withTheme, withLayout(), withSignals],
23
+ decorators: [withTheme, withLayout({ tooltips: true }), withSignals],
24
24
  parameters: { translations },
25
25
  };
26
26
 
27
+ const menuActions = createActions() as MenuAction[];
28
+ const nestedMenuActions = createNestedActionsResolver();
29
+
30
+ const handleAction = (action: MenuAction) => console.log('[on action]', action);
31
+
27
32
  export const DropdownMenu = {
28
33
  render: () => {
29
- const menuActions = useMemo(() => createActions() as MenuAction[], []);
30
- const resolveGroupItems = useCallback(() => menuActions, [menuActions]);
31
34
  useMutateActions(menuActions);
32
-
35
+ const resolveGroupItems = useCallback(() => menuActions, []);
33
36
  return (
34
- <MenuProvider useGroupItems={resolveGroupItems}>
37
+ <MenuProvider resolveGroupItems={resolveGroupItems} onAction={handleAction as MenuActionHandler}>
35
38
  <NaturalDropdownMenu.Root>
36
39
  <NaturalDropdownMenu.Trigger asChild>
37
40
  <IconButton icon='ph--list-checks--regular' size={5} label='Options' />
@@ -44,10 +47,8 @@ export const DropdownMenu = {
44
47
 
45
48
  export const Toolbar = {
46
49
  render: () => {
47
- const nestedMenuActions = useMemo(() => createNestedActionsResolver(), []);
48
-
49
50
  return (
50
- <MenuProvider {...nestedMenuActions}>
51
+ <MenuProvider onAction={handleAction as MenuActionHandler} {...nestedMenuActions}>
51
52
  <ToolbarMenu />
52
53
  </MenuProvider>
53
54
  );
@@ -57,9 +58,8 @@ export const Toolbar = {
57
58
  export const UseMenuActionsToolbar = {
58
59
  render: () => {
59
60
  const menu = useMenuActions(createNestedActions);
60
-
61
61
  return (
62
- <MenuProvider {...menu}>
62
+ <MenuProvider onAction={handleAction as MenuActionHandler} {...menu}>
63
63
  <ToolbarMenu />
64
64
  </MenuProvider>
65
65
  );
@@ -2,4 +2,110 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- export * from './generator';
5
+ import { useEffect } from 'react';
6
+
7
+ import { type Action, Graph, type NodeArg, ACTION_TYPE, ACTION_GROUP_TYPE, actionGroupSymbol } from '@dxos/app-graph';
8
+ import { create } from '@dxos/live-object';
9
+ import { faker } from '@dxos/random';
10
+ import { type DeepWriteable } from '@dxos/util';
11
+
12
+ import { type MenuAction, type MenuItemGroup, type MenuItem } from '../defs';
13
+ import { type ActionGraphProps } from '../hooks';
14
+
15
+ export type CreateActionsParams = Partial<{
16
+ type?: typeof ACTION_TYPE | typeof ACTION_GROUP_TYPE;
17
+ callback: () => void;
18
+ count: number;
19
+ }>;
20
+
21
+ const icons = {
22
+ regular: [
23
+ 'ph--text-b--regular',
24
+ 'ph--text-italic--regular',
25
+ 'ph--text-h-five--regular',
26
+ 'ph--chat-text--regular',
27
+ 'ph--clipboard-text--regular',
28
+ 'ph--link-simple--regular',
29
+ ],
30
+ fill: [
31
+ 'ph--text-b--fill',
32
+ 'ph--text-italic--fill',
33
+ 'ph--text-h-five--fill',
34
+ 'ph--chat-text--fill',
35
+ 'ph--clipboard-text--fill',
36
+ 'ph--link-simple--fill',
37
+ ],
38
+ };
39
+
40
+ export const createActions = (params?: CreateActionsParams) => {
41
+ // eslint-disable-next-line no-console
42
+ const { callback = () => console.log('invoke'), count = 12, type = ACTION_TYPE } = params ?? {};
43
+ return faker.helpers.multiple(
44
+ () =>
45
+ create({
46
+ id: faker.string.uuid(),
47
+ type,
48
+ data: type === ACTION_GROUP_TYPE ? actionGroupSymbol : callback,
49
+ properties: {
50
+ label: faker.lorem.words(2),
51
+ icon: faker.helpers.arrayElement(icons[faker.helpers.arrayElement(Object.keys(icons)) as keyof typeof icons]),
52
+ disabled: faker.helpers.arrayElement([true, false]),
53
+ ...(type === ACTION_GROUP_TYPE && { variant: 'dropdownMenu' }),
54
+ },
55
+ }),
56
+ { count },
57
+ );
58
+ };
59
+
60
+ export const createNestedActions = () => {
61
+ const result: ActionGraphProps = { edges: [], nodes: [] };
62
+ const actionGroups = createActions({ type: ACTION_GROUP_TYPE });
63
+ actionGroups.forEach((group) => {
64
+ const actions = createActions();
65
+ result.nodes.push(group, ...actions);
66
+ result.edges.push(
67
+ { source: 'root', target: group.id },
68
+ ...actions.map((action) => ({ source: group.id, target: action.id })),
69
+ );
70
+ });
71
+ return result;
72
+ };
73
+
74
+ export const createNestedActionsResolver = (groupParams?: CreateActionsParams, params?: CreateActionsParams) => {
75
+ const graph = new Graph();
76
+ const actionGroups = createActions({ type: ACTION_GROUP_TYPE, ...groupParams });
77
+ actionGroups.forEach((group) => {
78
+ const actions = createActions(params);
79
+ // TODO(thure): these methods exist on `graph` but are marked as `@internal`; how should consumers properly build
80
+ // graph “islands” for the purposes of these components?
81
+ // @ts-ignore
82
+ graph._addNodes([group as NodeArg<any>, ...(actions as NodeArg<any>[])]);
83
+ // @ts-ignore
84
+ graph._addEdges([
85
+ { source: 'root', target: group.id },
86
+ ...actions.map((action) => ({ source: group.id, target: action.id })),
87
+ ]);
88
+ void graph.expand(group);
89
+ });
90
+ const resolveGroupItems = (groupNode?: MenuItemGroup) =>
91
+ (graph.actions(groupNode ?? graph.root) || null) as MenuItem[] | null;
92
+ return { resolveGroupItems };
93
+ };
94
+
95
+ export const mutateActionsOnInterval = (actions: Action[]) => {
96
+ let cursor = 0;
97
+ return setInterval(() => {
98
+ const action = actions[cursor] as DeepWriteable<Action>;
99
+ action.properties.icon = faker.helpers.arrayElement(
100
+ action.properties.icon.endsWith('regular') ? icons.fill : icons.regular,
101
+ );
102
+ action.properties.disabled = !action.properties.disabled;
103
+ cursor = (cursor + actions.length + 1) % actions.length;
104
+ }, 1_000);
105
+ };
106
+
107
+ export const useMutateActions = (actions: MenuAction[]) =>
108
+ useEffect(() => {
109
+ const interval = mutateActionsOnInterval(actions);
110
+ return () => clearInterval(interval);
111
+ }, []);
package/src/util.ts CHANGED
@@ -11,7 +11,7 @@ import {
11
11
  type MenuItemGroup,
12
12
  type MenuItemGroupProperties,
13
13
  type MenuSeparator,
14
- } from './types';
14
+ } from './defs';
15
15
 
16
16
  export const getShortcut = (action: ActionLike) => {
17
17
  return typeof action.properties?.keyBinding === 'string'
@@ -21,16 +21,16 @@ export const getShortcut = (action: ActionLike) => {
21
21
 
22
22
  export const fallbackIcon = 'ph--placeholder--regular';
23
23
 
24
- export const createMenuAction = <P extends {} = {}>(
25
- id: string,
26
- invoke: () => void,
27
- properties: P & MenuActionProperties,
28
- ) =>
24
+ // TODO(thure,wittjosiah): This is probably a smell; consider the whether react-ui-menu should use action nodes if the
25
+ // callback in `data` is never used. See https://github.com/dxos/dxos/pull/8506#discussion_r1925855118
26
+ const noop = () => {};
27
+
28
+ export const createMenuAction = <P extends {} = {}>(id: string, properties: P & MenuActionProperties) =>
29
29
  ({
30
30
  id,
31
31
  type: ACTION_TYPE,
32
32
  properties,
33
- data: invoke,
33
+ data: noop,
34
34
  }) satisfies MenuAction;
35
35
 
36
36
  export const createMenuItemGroup = <
@@ -1 +0,0 @@
1
- {"version":3,"file":"Menus.stories.d.ts","sourceRoot":"","sources":["../../../../src/components/Menus.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,aAAa,CAAC;AACrB,OAAO,KAA+B,MAAM,OAAO,CAAC;;;;;;;;;;;;;AAcpD,wBAKE;AAEF,eAAO,MAAM,YAAY;;CAgBxB,CAAC;AAEF,eAAO,MAAM,OAAO;;CAUnB,CAAC;AAEF,eAAO,MAAM,qBAAqB;;CAUjC,CAAC"}
@@ -1,2 +0,0 @@
1
- export * from './useMenuActions';
2
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/hooks/index.ts"],"names":[],"mappings":"AAIA,cAAc,kBAAkB,CAAC"}
@@ -1,12 +0,0 @@
1
- import { type Edge, type NodeArg } from '@dxos/app-graph';
2
- import { type MenuItem, type MenuItemGroup } from '../types';
3
- export type ActionGraphNodes = NodeArg<any>[];
4
- export type ActionGraphEdges = Edge[];
5
- export type ActionGraphProps = {
6
- nodes: ActionGraphNodes;
7
- edges: ActionGraphEdges;
8
- };
9
- export declare const useMenuActions: (actionCreator: () => ActionGraphProps) => {
10
- useGroupItems: (sourceNode?: MenuItemGroup) => MenuItem[];
11
- };
12
- //# sourceMappingURL=useMenuActions.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useMenuActions.d.ts","sourceRoot":"","sources":["../../../../src/hooks/useMenuActions.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,KAAK,IAAI,EAAqB,KAAK,OAAO,EAAsB,MAAM,iBAAiB,CAAC;AAEjG,OAAO,EAAE,KAAK,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AA6B7D,MAAM,MAAM,gBAAgB,GAAG,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;AAC9C,MAAM,MAAM,gBAAgB,GAAG,IAAI,EAAE,CAAC;AACtC,MAAM,MAAM,gBAAgB,GAAG;IAAE,KAAK,EAAE,gBAAgB,CAAC;IAAC,KAAK,EAAE,gBAAgB,CAAA;CAAE,CAAC;AAEpF,eAAO,MAAM,cAAc,GAAI,eAAe,MAAM,gBAAgB;iCAoBlD,aAAa;CAQ9B,CAAC"}
@@ -1,26 +0,0 @@
1
- import { type Action, ACTION_TYPE, ACTION_GROUP_TYPE } from '@dxos/app-graph';
2
- import { type ActionGraphProps } from '../hooks/useMenuActions';
3
- import { type MenuAction, type MenuItemGroup, type MenuItem } from '../types';
4
- export type CreateActionsParams = Partial<{
5
- type?: typeof ACTION_TYPE | typeof ACTION_GROUP_TYPE;
6
- callback: () => void;
7
- count: number;
8
- }>;
9
- export declare const createActions: (params?: CreateActionsParams) => import("@dxos/live-object").Live<{
10
- id: string;
11
- type: "dxos.org/type/GraphActionGroup" | "dxos.org/type/GraphAction";
12
- data: symbol | (() => void);
13
- properties: {
14
- variant?: string | undefined;
15
- label: string;
16
- icon: string;
17
- disabled: boolean;
18
- };
19
- }>[];
20
- export declare const createNestedActions: () => ActionGraphProps;
21
- export declare const createNestedActionsResolver: (groupParams?: CreateActionsParams, params?: CreateActionsParams) => {
22
- resolveGroupItems: (groupNode?: MenuItemGroup) => MenuItem[] | null;
23
- };
24
- export declare const mutateActionsOnInterval: (actions: Action[]) => NodeJS.Timeout;
25
- export declare const useMutateActions: (actions: MenuAction[]) => void;
26
- //# sourceMappingURL=generator.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../../../src/testing/generator.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,KAAK,MAAM,EAGX,WAAW,EACX,iBAAiB,EAGlB,MAAM,iBAAiB,CAAC;AAKzB,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,aAAa,EAAE,KAAK,QAAQ,EAAE,MAAM,UAAU,CAAC;AAE9E,MAAM,MAAM,mBAAmB,GAAG,OAAO,CAAC;IACxC,IAAI,CAAC,EAAE,OAAO,WAAW,GAAG,OAAO,iBAAiB,CAAC;IACrD,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC,CAAC;AAqBH,eAAO,MAAM,aAAa,GAAI,SAAS,mBAAmB;;;0BAvBxC,IAAI;;;;;;;IAyCrB,CAAC;AAEF,eAAO,MAAM,mBAAmB,wBAY/B,CAAC;AAEF,eAAO,MAAM,2BAA2B,GAAI,cAAc,mBAAmB,EAAE,SAAS,mBAAmB;oCAYlE,aAAa,KACM,QAAQ,EAAE,GAAG,IAAI;CAE5E,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAAI,SAAS,MAAM,EAAE,mBAUxD,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,SAAS,UAAU,EAAE,SAI9C,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK,MAAM,EAAE,KAAK,WAAW,EAAqB,MAAM,iBAAiB,CAAC;AAC9F,OAAO,EAAE,KAAK,qBAAqB,EAAE,KAAK,KAAK,EAAE,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEnH,MAAM,MAAM,oBAAoB,GAAG;IACjC,KAAK,EAAE,KAAK,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC9B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,cAAc,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACpC,KAAK,EAAE,KAAK,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,EAAE,GAAG,EAAE,IAAI,MAAM,CAAC,CAAC,GAAG,oBAAoB,CAAC,CAAC;AAE7E,eAAO,MAAM,iBAAiB,EAAG,kCAA2C,CAAC;AAE7E,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,qBAAqB,EAAE,SAAS,CAAC,CAAC,GAAG;IAChF,IAAI,EAAE,OAAO,iBAAiB,CAAC;CAChC,CAAC;AAEF,eAAO,MAAM,WAAW,GAAI,MAAM,IAAI,KAAG,IAAI,IAAI,aAAgD,CAAC;AAElG,MAAM,MAAM,2BAA2B,GAAG;IAAE,iBAAiB,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AACzF,MAAM,MAAM,6BAA6B,GAAG;IAAE,iBAAiB,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAE/F,MAAM,MAAM,aAAa,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC;AAEhG,eAAO,MAAM,WAAW,GAAI,MAAM,IAAI,KAAG,IAAI,IAAI,aAAgD,CAAC;AAElG,MAAM,MAAM,QAAQ,GAAG,aAAa,GAAG,UAAU,GAAG,aAAa,CAAC;AAElE,MAAM,MAAM,iBAAiB,GAAG,CAAC,KAAK,CAAC,EAAE,aAAa,KAAK,QAAQ,EAAE,GAAG,IAAI,CAAC;AAE7E,MAAM,MAAM,gBAAgB,GAAG;IAC7B,aAAa,EAAE,iBAAiB,CAAC;IACjC,QAAQ,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC;IAClC,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC"}
@@ -1,5 +0,0 @@
1
- //
2
- // Copyright 2025 DXOS.org
3
- //
4
-
5
- export * from './useMenuActions';
@@ -1,115 +0,0 @@
1
- //
2
- // Copyright 2025 DXOS.org
3
- //
4
-
5
- import { useEffect } from 'react';
6
-
7
- import {
8
- type Action,
9
- Graph,
10
- type NodeArg,
11
- ACTION_TYPE,
12
- ACTION_GROUP_TYPE,
13
- actionGroupSymbol,
14
- ROOT_ID,
15
- } from '@dxos/app-graph';
16
- import { live } from '@dxos/live-object';
17
- import { faker } from '@dxos/random';
18
- import { type DeepWriteable } from '@dxos/util';
19
-
20
- import { type ActionGraphProps } from '../hooks/useMenuActions';
21
- import { type MenuAction, type MenuItemGroup, type MenuItem } from '../types';
22
-
23
- export type CreateActionsParams = Partial<{
24
- type?: typeof ACTION_TYPE | typeof ACTION_GROUP_TYPE;
25
- callback: () => void;
26
- count: number;
27
- }>;
28
-
29
- const icons = {
30
- regular: [
31
- 'ph--text-b--regular',
32
- 'ph--text-italic--regular',
33
- 'ph--text-h-five--regular',
34
- 'ph--chat-text--regular',
35
- 'ph--clipboard-text--regular',
36
- 'ph--link-simple--regular',
37
- ],
38
- fill: [
39
- 'ph--text-b--fill',
40
- 'ph--text-italic--fill',
41
- 'ph--text-h-five--fill',
42
- 'ph--chat-text--fill',
43
- 'ph--clipboard-text--fill',
44
- 'ph--link-simple--fill',
45
- ],
46
- };
47
-
48
- export const createActions = (params?: CreateActionsParams) => {
49
- // eslint-disable-next-line no-console
50
- const { callback = () => console.log('invoke'), count = 12, type = ACTION_TYPE } = params ?? {};
51
- return faker.helpers.multiple(
52
- () =>
53
- live({
54
- id: faker.string.uuid(),
55
- type,
56
- data: type === ACTION_GROUP_TYPE ? actionGroupSymbol : callback,
57
- properties: {
58
- label: faker.lorem.words(2),
59
- icon: faker.helpers.arrayElement(icons[faker.helpers.arrayElement(Object.keys(icons)) as keyof typeof icons]),
60
- disabled: faker.helpers.arrayElement([true, false]),
61
- ...(type === ACTION_GROUP_TYPE && { variant: 'dropdownMenu' }),
62
- },
63
- }),
64
- { count },
65
- );
66
- };
67
-
68
- export const createNestedActions = () => {
69
- const result: ActionGraphProps = { edges: [], nodes: [] };
70
- const actionGroups = createActions({ type: ACTION_GROUP_TYPE });
71
- actionGroups.forEach((group) => {
72
- const actions = createActions();
73
- result.nodes.push(group, ...actions);
74
- result.edges.push(
75
- { source: 'root', target: group.id },
76
- ...actions.map((action) => ({ source: group.id, target: action.id })),
77
- );
78
- });
79
- return result;
80
- };
81
-
82
- export const createNestedActionsResolver = (groupParams?: CreateActionsParams, params?: CreateActionsParams) => {
83
- const graph = new Graph();
84
- const actionGroups = createActions({ type: ACTION_GROUP_TYPE, ...groupParams });
85
- actionGroups.forEach((group) => {
86
- const actions = createActions(params);
87
- graph.addNodes([group as NodeArg<any>, ...(actions as NodeArg<any>[])]);
88
- graph.addEdges([
89
- { source: 'root', target: group.id },
90
- ...actions.map((action) => ({ source: group.id, target: action.id })),
91
- ]);
92
- graph.expand(group.id);
93
- });
94
- const resolveGroupItems = (groupNode?: MenuItemGroup) =>
95
- (graph.getActions(groupNode?.id ?? ROOT_ID) || null) as MenuItem[] | null;
96
- return { resolveGroupItems };
97
- };
98
-
99
- export const mutateActionsOnInterval = (actions: Action[]) => {
100
- let cursor = 0;
101
- return setInterval(() => {
102
- const action = actions[cursor] as DeepWriteable<Action>;
103
- action.properties.icon = faker.helpers.arrayElement(
104
- action.properties.icon.endsWith('regular') ? icons.fill : icons.regular,
105
- );
106
- action.properties.disabled = !action.properties.disabled;
107
- cursor = (cursor + actions.length + 1) % actions.length;
108
- }, 1_000);
109
- };
110
-
111
- export const useMutateActions = (actions: MenuAction[]) =>
112
- useEffect(() => {
113
- const interval = mutateActionsOnInterval(actions);
114
- return () => clearInterval(interval);
115
- }, []);