@frontify/guideline-blocks-settings 0.29.17 → 0.30.1

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/CHANGELOG.md +28 -0
  2. package/dist/components/Attachments/AttachmentItem.es.js +73 -79
  3. package/dist/components/Attachments/AttachmentItem.es.js.map +1 -1
  4. package/dist/components/Attachments/Attachments.es.js +103 -96
  5. package/dist/components/Attachments/Attachments.es.js.map +1 -1
  6. package/dist/components/Attachments/AttachmentsButtonTrigger.es.js +21 -0
  7. package/dist/components/Attachments/AttachmentsButtonTrigger.es.js.map +1 -0
  8. package/dist/components/BlockItemWrapper/BlockItemWrapper.es.js +47 -43
  9. package/dist/components/BlockItemWrapper/BlockItemWrapper.es.js.map +1 -1
  10. package/dist/components/BlockItemWrapper/Toolbar/Toolbar.es.js +123 -0
  11. package/dist/components/BlockItemWrapper/Toolbar/Toolbar.es.js.map +1 -0
  12. package/dist/components/BlockItemWrapper/Toolbar/ToolbarAttachments.es.js +27 -0
  13. package/dist/components/BlockItemWrapper/Toolbar/ToolbarAttachments.es.js.map +1 -0
  14. package/dist/components/BlockItemWrapper/Toolbar/ToolbarAttachmentsTrigger.es.js +12 -0
  15. package/dist/components/BlockItemWrapper/Toolbar/ToolbarAttachmentsTrigger.es.js.map +1 -0
  16. package/dist/components/BlockItemWrapper/Toolbar/ToolbarSegment.es.js +6 -0
  17. package/dist/components/BlockItemWrapper/Toolbar/ToolbarSegment.es.js.map +1 -0
  18. package/dist/components/BlockItemWrapper/Toolbar/helpers.es.js +26 -0
  19. package/dist/components/BlockItemWrapper/Toolbar/helpers.es.js.map +1 -0
  20. package/dist/hooks/useAttachments.es.js +43 -20
  21. package/dist/hooks/useAttachments.es.js.map +1 -1
  22. package/dist/index.cjs.js +3 -3
  23. package/dist/index.cjs.js.map +1 -1
  24. package/dist/index.d.ts +95 -8
  25. package/dist/index.es.js +176 -171
  26. package/dist/index.es.js.map +1 -1
  27. package/dist/index.umd.js +3 -3
  28. package/dist/index.umd.js.map +1 -1
  29. package/dist/styles.css +1 -1
  30. package/package.json +3 -3
  31. package/src/components/Attachments/AttachmentItem.tsx +2 -13
  32. package/src/components/Attachments/Attachments.tsx +30 -15
  33. package/src/components/Attachments/AttachmentsButtonTrigger.tsx +22 -0
  34. package/src/components/Attachments/types.ts +10 -2
  35. package/src/components/BlockItemWrapper/BlockItemWrapper.tsx +23 -20
  36. package/src/components/BlockItemWrapper/Toolbar/Toolbar.spec.tsx +127 -0
  37. package/src/components/BlockItemWrapper/Toolbar/Toolbar.tsx +133 -0
  38. package/src/components/BlockItemWrapper/Toolbar/ToolbarAttachments.tsx +29 -0
  39. package/src/components/BlockItemWrapper/Toolbar/ToolbarAttachmentsTrigger.tsx +14 -0
  40. package/src/components/BlockItemWrapper/Toolbar/ToolbarSegment.tsx +9 -0
  41. package/src/components/BlockItemWrapper/Toolbar/helpers.ts +33 -0
  42. package/src/components/BlockItemWrapper/Toolbar/index.ts +4 -0
  43. package/src/components/BlockItemWrapper/Toolbar/types.ts +38 -0
  44. package/src/components/BlockItemWrapper/index.ts +1 -0
  45. package/src/components/BlockItemWrapper/types.ts +11 -34
  46. package/src/hooks/{useAttachments.spec.ts → useAttachments.spec.tsx} +55 -4
  47. package/src/hooks/useAttachments.tsx +95 -0
  48. package/dist/components/BlockItemWrapper/Toolbar.es.js +0 -117
  49. package/dist/components/BlockItemWrapper/Toolbar.es.js.map +0 -1
  50. package/src/components/BlockItemWrapper/Toolbar.tsx +0 -133
  51. package/src/hooks/useAttachments.ts +0 -46
@@ -0,0 +1,29 @@
1
+ /* (c) Copyright Frontify Ltd., all rights reserved. */
2
+
3
+ import { Attachments } from '../../Attachments';
4
+ import { useAttachmentsContext } from '../../../hooks';
5
+
6
+ import { type ToolbarFlyoutState } from './types';
7
+
8
+ import { ToolbarAttachmentsTrigger } from './ToolbarAttachmentsTrigger';
9
+
10
+ export const ToolbarAttachments = ({ isOpen, onOpenChange }: ToolbarFlyoutState) => {
11
+ const { appBridge, attachments, onAttachmentsAdd, onAttachmentDelete, onAttachmentReplace, onAttachmentsSorted } =
12
+ useAttachmentsContext();
13
+
14
+ return (
15
+ <Attachments
16
+ onUpload={onAttachmentsAdd}
17
+ onDelete={onAttachmentDelete}
18
+ onReplaceWithBrowse={onAttachmentReplace}
19
+ onReplaceWithUpload={onAttachmentReplace}
20
+ onSorted={onAttachmentsSorted}
21
+ onBrowse={onAttachmentsAdd}
22
+ items={attachments}
23
+ appBridge={appBridge}
24
+ triggerComponent={ToolbarAttachmentsTrigger}
25
+ isOpen={isOpen}
26
+ onOpenChange={onOpenChange}
27
+ />
28
+ );
29
+ };
@@ -0,0 +1,14 @@
1
+ /* (c) Copyright Frontify Ltd., all rights reserved. */
2
+
3
+ import { IconCaretDown12, IconPaperclip16 } from '@frontify/fondue';
4
+ import { type AttachmentsTriggerProps } from '../../Attachments/types';
5
+
6
+ import { getToolbarButtonClassNames } from './helpers';
7
+
8
+ export const ToolbarAttachmentsTrigger = ({ children, isFlyoutOpen }: AttachmentsTriggerProps) => (
9
+ <div className={getToolbarButtonClassNames('pointer', isFlyoutOpen)}>
10
+ <IconPaperclip16 />
11
+ {children}
12
+ <IconCaretDown12 />
13
+ </div>
14
+ );
@@ -0,0 +1,9 @@
1
+ /* (c) Copyright Frontify Ltd., all rights reserved. */
2
+
3
+ import { type ReactNode } from 'react';
4
+
5
+ export const ToolbarSegment = ({ children }: { children: ReactNode }) => (
6
+ <div className="tw-pointer-events-auto tw-flex tw-flex-shrink-0 tw-gap-px tw-px-px tw-h-[26px] tw-items-center tw-self-start tw-leading-none">
7
+ {children}
8
+ </div>
9
+ );
@@ -0,0 +1,33 @@
1
+ /* (c) Copyright Frontify Ltd., all rights reserved. */
2
+
3
+ import { FOCUS_VISIBLE_STYLE } from '@frontify/fondue';
4
+
5
+ import { joinClassNames } from '../../../utilities';
6
+
7
+ export const getToolbarButtonClassNames = (cursor: 'grab' | 'pointer', forceActiveStyle?: boolean) => {
8
+ const classNames = [
9
+ FOCUS_VISIBLE_STYLE,
10
+ 'tw-relative tw-inline-flex tw-items-center tw-justify-center',
11
+ 'tw-h-6 tw-p-1',
12
+ 'tw-rounded',
13
+ 'tw-text-xs tw-font-medium',
14
+ 'tw-gap-0.5',
15
+ 'focus-visible:tw-z-10',
16
+ ];
17
+
18
+ if (forceActiveStyle) {
19
+ classNames.push(
20
+ 'tw-bg-box-neutral-pressed',
21
+ 'tw-text-box-neutral-inverse-pressed',
22
+ cursor === 'grab' ? 'tw-cursor-grabbing' : 'tw-cursor-pointer',
23
+ );
24
+ } else {
25
+ classNames.push(
26
+ 'hover:tw-bg-box-neutral-hover active:tw-bg-box-neutral-pressed',
27
+ 'tw-text-text-weak hover:tw-text-box-neutral-inverse-hover active:tw-text-box-neutral-inverse-pressed',
28
+ cursor === 'grab' ? 'tw-cursor-grab active:tw-cursor-grabbing' : 'tw-cursor-pointer',
29
+ );
30
+ }
31
+
32
+ return joinClassNames(classNames);
33
+ };
@@ -0,0 +1,4 @@
1
+ /* (c) Copyright Frontify Ltd., all rights reserved. */
2
+
3
+ export * from './Toolbar';
4
+ export * from './types';
@@ -0,0 +1,38 @@
1
+ /* (c) Copyright Frontify Ltd., all rights reserved. */
2
+
3
+ import { type MenuItemStyle } from '@frontify/fondue';
4
+
5
+ export type ToolbarProps = {
6
+ items: ToolbarItem[];
7
+ flyoutMenu: ToolbarFlyoutState & { items: FlyoutToolbarItem[][] };
8
+ attachments: ToolbarFlyoutState & { isEnabled: boolean };
9
+ isDragging?: boolean;
10
+ };
11
+
12
+ export type ToolbarFlyoutState = {
13
+ isOpen: boolean;
14
+ onOpenChange: (isOpen: boolean) => void;
15
+ };
16
+
17
+ type BaseToolbarItem = {
18
+ icon: JSX.Element;
19
+ tooltip?: string;
20
+ };
21
+
22
+ type DraghandleToolbarItem = BaseToolbarItem & {
23
+ draggableProps: Record<string, unknown>;
24
+ setActivatorNodeRef?: (node: HTMLElement | null) => void;
25
+ };
26
+
27
+ type ButtonToolbarItem = BaseToolbarItem & {
28
+ onClick: () => void;
29
+ };
30
+
31
+ export type ToolbarItem = DraghandleToolbarItem | ButtonToolbarItem;
32
+
33
+ export type FlyoutToolbarItem = {
34
+ title: string;
35
+ onClick: () => void;
36
+ icon: JSX.Element;
37
+ style?: MenuItemStyle;
38
+ };
@@ -1,5 +1,6 @@
1
1
  /* (c) Copyright Frontify Ltd., all rights reserved. */
2
2
 
3
3
  export * from './BlockItemWrapper';
4
+ export * from './Toolbar';
4
5
  export * from './types';
5
6
  export * from './constants';
@@ -1,7 +1,10 @@
1
1
  /* (c) Copyright Frontify Ltd., all rights reserved. */
2
2
 
3
- import { MenuItemStyle } from '@frontify/fondue';
4
- import type { ReactNode } from 'react';
3
+ import { type ReactNode } from 'react';
4
+
5
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
6
+ import { type AttachmentsProvider, type withAttachmentsProvider } from '../../hooks/useAttachments';
7
+ import { type FlyoutToolbarItem, type ToolbarItem } from './Toolbar';
5
8
 
6
9
  export type BlockItemWrapperProps = {
7
10
  children: ReactNode;
@@ -13,36 +16,10 @@ export type BlockItemWrapperProps = {
13
16
  shouldFillContainer?: boolean;
14
17
  outlineOffset?: number;
15
18
  shouldBeShown?: boolean;
16
- };
17
-
18
- export type ToolbarProps = {
19
- items: ToolbarItem[];
20
- flyoutItems: FlyoutToolbarItem[][];
21
- isFlyoutOpen: boolean;
22
- setIsFlyoutOpen: (isOpen: boolean) => void;
23
- isDragging?: boolean;
24
- isFlyoutDisabled?: boolean;
25
- };
26
-
27
- type BaseToolbarItem = {
28
- icon: JSX.Element;
29
- tooltip?: string;
30
- };
31
-
32
- type DraghandleToolbarItem = BaseToolbarItem & {
33
- draggableProps: Record<string, unknown>;
34
- setActivatorNodeRef?: (node: HTMLElement | null) => void;
35
- };
36
-
37
- type ButtonToolbarItem = BaseToolbarItem & {
38
- onClick: () => void;
39
- };
40
-
41
- export type ToolbarItem = DraghandleToolbarItem | ButtonToolbarItem;
42
-
43
- export type FlyoutToolbarItem = {
44
- title: string;
45
- onClick: () => void;
46
- icon: JSX.Element;
47
- style?: MenuItemStyle;
19
+ /**
20
+ * When set to true the BlockItemWrapper must be a child of a {@link AttachmentsProvider} component,
21
+ * or the block must be wrapped with a {@link withAttachmentsProvider} HOC.
22
+ * @default false
23
+ */
24
+ showAttachments?: boolean;
48
25
  };
@@ -1,10 +1,10 @@
1
1
  /* (c) Copyright Frontify Ltd., all rights reserved. */
2
2
 
3
3
  import { AssetDummy, getAppBridgeBlockStub } from '@frontify/app-bridge';
4
- import { renderHook, waitFor } from '@testing-library/react';
5
-
4
+ import { render, renderHook, waitFor } from '@testing-library/react';
6
5
  import { describe, expect, it } from 'vitest';
7
- import { useAttachments } from './useAttachments';
6
+
7
+ import { AttachmentsProvider, useAttachments, useAttachmentsContext, withAttachmentsProvider } from './useAttachments';
8
8
 
9
9
  const MOCK_SETTINGS_ID = 'attachments';
10
10
 
@@ -20,7 +20,7 @@ describe('useAttachments', () => {
20
20
  });
21
21
  const { result } = renderHook(() => useAttachments(STUB_WITH_NO_ASSETS, MOCK_SETTINGS_ID));
22
22
 
23
- await result.current.onAddAttachments([AssetDummy.with(1)]);
23
+ await result.current.onAttachmentsAdd([AssetDummy.with(1)]);
24
24
  await waitFor(() => {
25
25
  expect(result.current.attachments).toHaveLength(1);
26
26
  });
@@ -77,3 +77,54 @@ describe('useAttachments', () => {
77
77
  });
78
78
  });
79
79
  });
80
+
81
+ describe('useAttachmentsContext', () => {
82
+ it('should throw an error when not a child of a provider', async () => {
83
+ expect(() => renderHook(() => useAttachmentsContext())).toThrowError();
84
+ });
85
+
86
+ it('should return correct info', async () => {
87
+ const STUB_WITH_NO_ASSETS = getAppBridgeBlockStub({
88
+ blockId: 1,
89
+ blockAssets: { [MOCK_SETTINGS_ID]: [AssetDummy.with(1)] },
90
+ });
91
+ const { result } = renderHook(useAttachmentsContext, {
92
+ wrapper: ({ children }) => (
93
+ <AttachmentsProvider appBridge={STUB_WITH_NO_ASSETS} assetId={MOCK_SETTINGS_ID}>
94
+ {children}
95
+ </AttachmentsProvider>
96
+ ),
97
+ });
98
+
99
+ expect(result.current.appBridge).toEqual(STUB_WITH_NO_ASSETS);
100
+ await waitFor(() => {
101
+ expect(result.current.attachments).toHaveLength(1);
102
+ });
103
+ });
104
+ });
105
+
106
+ describe('withAttachmentsProvider', () => {
107
+ it('should provide correct info to context consumer', async () => {
108
+ const STUB_WITH_THREE_ASSETS = getAppBridgeBlockStub({
109
+ blockId: 2,
110
+ blockAssets: { [MOCK_SETTINGS_ID]: [AssetDummy.with(1), AssetDummy.with(2), AssetDummy.with(3)] },
111
+ });
112
+
113
+ const Component = withAttachmentsProvider(() => {
114
+ const context = useAttachmentsContext();
115
+ return (
116
+ <ul>
117
+ {context.attachments.map((attachment) => (
118
+ <li key={attachment.id} role="list">
119
+ {attachment.id}
120
+ </li>
121
+ ))}
122
+ </ul>
123
+ );
124
+ }, MOCK_SETTINGS_ID);
125
+
126
+ const { getAllByRole } = render(<Component appBridge={STUB_WITH_THREE_ASSETS} />);
127
+
128
+ await waitFor(() => expect(getAllByRole('list')).toHaveLength(3));
129
+ });
130
+ });
@@ -0,0 +1,95 @@
1
+ /* (c) Copyright Frontify Ltd., all rights reserved. */
2
+
3
+ import { AppBridgeBlock, Asset, useBlockAssets } from '@frontify/app-bridge';
4
+ import { type ReactNode, createContext, useContext } from 'react';
5
+
6
+ import { type BlockProps } from '../index';
7
+
8
+ export const useAttachments = (appBridge: AppBridgeBlock, assetId: string) => {
9
+ const { blockAssets, updateAssetIdsFromKey } = useBlockAssets(appBridge);
10
+ const attachments = blockAssets?.[assetId] || [];
11
+
12
+ const onAttachmentsAdd = async (newAssets: Asset[]) => {
13
+ const newAssetIds = attachments.map((attachment) => attachment.id);
14
+ for (const asset of newAssets) {
15
+ newAssetIds.push(asset.id);
16
+ }
17
+ await updateAssetIdsFromKey(assetId, newAssetIds);
18
+ };
19
+
20
+ const onAttachmentDelete = async (assetToDelete: Asset) => {
21
+ const newAssetIds = attachments
22
+ .filter((attachment) => attachment.id !== assetToDelete.id)
23
+ .map((attachment) => attachment.id);
24
+
25
+ await updateAssetIdsFromKey(assetId, newAssetIds);
26
+ };
27
+
28
+ const onAttachmentReplace = async (attachmentToReplace: Asset, newAsset: Asset) => {
29
+ const newAssetIds = attachments.map((attachment) =>
30
+ attachment.id === attachmentToReplace.id ? newAsset.id : attachment.id,
31
+ );
32
+
33
+ await updateAssetIdsFromKey(assetId, newAssetIds);
34
+ };
35
+
36
+ const onAttachmentsSorted = async (assets: Asset[]) => {
37
+ const newAssetIds = assets.map((asset) => asset.id);
38
+
39
+ await updateAssetIdsFromKey(assetId, newAssetIds);
40
+ };
41
+
42
+ return {
43
+ onAttachmentsAdd,
44
+ onAttachmentDelete,
45
+ onAttachmentReplace,
46
+ onAttachmentsSorted,
47
+ attachments,
48
+ appBridge,
49
+ };
50
+ };
51
+
52
+ const AttachmentsContext = createContext<ReturnType<typeof useAttachments> | null>(null);
53
+
54
+ export const AttachmentsProvider = ({
55
+ appBridge,
56
+ children,
57
+ assetId,
58
+ }: {
59
+ appBridge: AppBridgeBlock;
60
+ children: ReactNode;
61
+ assetId: string;
62
+ }) => {
63
+ const attachmentContext = useAttachments(appBridge, assetId);
64
+
65
+ return <AttachmentsContext.Provider value={attachmentContext}>{children}</AttachmentsContext.Provider>;
66
+ };
67
+
68
+ export const useAttachmentsContext = () => {
69
+ const context = useContext(AttachmentsContext);
70
+
71
+ if (!context) {
72
+ throw new Error(
73
+ "No AttachmentsContext Provided. Component must be wrapped in an 'AttachmentsProvider' or the 'withAttachmentsProvider' HOC",
74
+ );
75
+ }
76
+
77
+ return context;
78
+ };
79
+
80
+ /**
81
+ * Block-level HOC for cases when there is only one attachment asset field related to the block.
82
+ * Recommended for most cases.
83
+ * If finer control is required over attachments, use {@link AttachmentsProvider} component.
84
+ */
85
+ export const withAttachmentsProvider = <T extends BlockProps>(Component: (props: T) => ReactNode, assetId: string) => {
86
+ const wrappedComponent = (props: T) => (
87
+ <AttachmentsProvider appBridge={props.appBridge} assetId={assetId}>
88
+ <Component {...props} />
89
+ </AttachmentsProvider>
90
+ );
91
+
92
+ wrappedComponent.displayName = 'withAttachmentsProvider';
93
+
94
+ return wrappedComponent;
95
+ };
@@ -1,117 +0,0 @@
1
- import { jsx as e, jsxs as u } from "react/jsx-runtime";
2
- import { LegacyTooltip as l, TooltipPosition as n, FOCUS_VISIBLE_STYLE as a, Flyout as v, IconDotsHorizontal16 as m, ActionMenu as f, MenuItemContentSize as x } from "@frontify/fondue";
3
- import { DEFAULT_DRAGGING_TOOLTIP as g, DEFAULT_DRAG_TOOLTIP as y } from "./constants.es.js";
4
- import { joinClassNames as c } from "../../utilities/react/joinClassNames.es.js";
5
- const C = ({
6
- items: d,
7
- flyoutItems: s,
8
- isFlyoutOpen: b,
9
- setIsFlyoutOpen: w,
10
- isDragging: r,
11
- isFlyoutDisabled: p
12
- }) => /* @__PURE__ */ e("div", { "data-test-id": "block-item-wrapper-toolbar", className: "tw-flex tw-justify-end", children: /* @__PURE__ */ u("div", { className: "tw-bg-white tw-isolate tw-text-box-selected-inverse tw-pointer-events-auto tw-flex tw-flex-shrink-0 tw-gap-[2px] tw-px-[1px] tw-spacing tw-items-center tw-h-7 tw-self-start tw-border tw-border-box-selected-inverse tw-rounded", children: [
13
- d.map(
14
- (t, o) => "draggableProps" in t ? /* @__PURE__ */ e(
15
- l,
16
- {
17
- withArrow: !0,
18
- hoverDelay: 0,
19
- enterDelay: 300,
20
- open: r,
21
- position: n.Top,
22
- content: /* @__PURE__ */ e("div", { children: r ? g : t.tooltip ?? y }),
23
- triggerElement: /* @__PURE__ */ e(
24
- "button",
25
- {
26
- ref: t.setActivatorNodeRef,
27
- "data-test-id": "block-item-wrapper-toolbar-btn",
28
- ...t.draggableProps,
29
- className: c([
30
- a,
31
- "tw-bg-base tw-relative tw-inline-flex tw-items-center tw-justify-center tw-w-6 tw-h-6 tw-rounded-sm focus-visible:tw-z-10",
32
- r ? "tw-cursor-grabbing tw-bg-box-selected-pressed" : "tw-cursor-grab hover:tw-bg-box-selected-hover"
33
- ]),
34
- children: t.icon
35
- }
36
- )
37
- },
38
- o
39
- ) : /* @__PURE__ */ e(
40
- l,
41
- {
42
- withArrow: !0,
43
- enterDelay: 300,
44
- hoverDelay: 0,
45
- disabled: r,
46
- position: n.Top,
47
- content: /* @__PURE__ */ e("div", { children: t.tooltip ?? "" }),
48
- triggerElement: /* @__PURE__ */ e(
49
- "button",
50
- {
51
- "data-test-id": "block-item-wrapper-toolbar-btn",
52
- onClick: t.onClick,
53
- className: c([
54
- "tw-bg-base tw-relative hover:tw-bg-box-selected-hover active:tw-bg-box-selected-pressed tw-cursor-pointer tw-inline-flex tw-items-center tw-justify-center tw-w-6 tw-h-6 tw-rounded-sm focus-visible:tw-z-10",
55
- a
56
- ]),
57
- children: t.icon
58
- }
59
- )
60
- },
61
- o
62
- )
63
- ),
64
- s.length > 0 && /* @__PURE__ */ e("div", { className: "tw-flex tw-flex-shrink-0 tw-flex-1 tw-h-6 tw-relative", children: /* @__PURE__ */ e(
65
- v,
66
- {
67
- isOpen: b && !r,
68
- isTriggerDisabled: p,
69
- legacyFooter: !1,
70
- fitContent: !0,
71
- hug: !1,
72
- onOpenChange: w,
73
- trigger: /* @__PURE__ */ e(
74
- l,
75
- {
76
- withArrow: !0,
77
- hoverDelay: 0,
78
- enterDelay: 300,
79
- disabled: r,
80
- position: n.Top,
81
- content: /* @__PURE__ */ e("div", { children: "Options" }),
82
- triggerElement: /* @__PURE__ */ e(
83
- "div",
84
- {
85
- "data-test-id": "block-item-wrapper-toolbar-flyout",
86
- className: "tw-bg-base hover:tw-bg-box-selected-hover active:tw-bg-box-selected-pressed tw-cursor-pointer tw-inline-flex tw-items-center tw-justify-center tw-w-6 tw-h-6 tw-rounded-sm tw-relative",
87
- children: /* @__PURE__ */ e(m, {})
88
- }
89
- )
90
- }
91
- ),
92
- children: /* @__PURE__ */ e(
93
- f,
94
- {
95
- menuBlocks: s.map((t, o) => ({
96
- id: o.toString(),
97
- menuItems: t.map((i, h) => ({
98
- id: o.toString() + h.toString(),
99
- size: x.XSmall,
100
- title: i.title,
101
- style: i.style,
102
- onClick: () => {
103
- w(!1), i.onClick();
104
- },
105
- initialValue: !0,
106
- decorator: /* @__PURE__ */ e("div", { className: "tw-mr-2", children: i.icon })
107
- }))
108
- }))
109
- }
110
- )
111
- }
112
- ) })
113
- ] }) });
114
- export {
115
- C as Toolbar
116
- };
117
- //# sourceMappingURL=Toolbar.es.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Toolbar.es.js","sources":["../../../src/components/BlockItemWrapper/Toolbar.tsx"],"sourcesContent":["/* (c) Copyright Frontify Ltd., all rights reserved. */\n\nimport {\n ActionMenu,\n FOCUS_VISIBLE_STYLE,\n Flyout,\n IconDotsHorizontal16,\n MenuItemContentSize,\n LegacyTooltip as Tooltip,\n TooltipPosition,\n} from '@frontify/fondue';\nimport { ToolbarProps } from './types';\nimport { joinClassNames } from '../../utilities';\nimport { DEFAULT_DRAGGING_TOOLTIP, DEFAULT_DRAG_TOOLTIP } from './constants';\n\nexport const Toolbar = ({\n items,\n flyoutItems,\n isFlyoutOpen,\n setIsFlyoutOpen,\n isDragging,\n isFlyoutDisabled,\n}: ToolbarProps) => {\n return (\n <div data-test-id=\"block-item-wrapper-toolbar\" className=\"tw-flex tw-justify-end\">\n <div className=\"tw-bg-white tw-isolate tw-text-box-selected-inverse tw-pointer-events-auto tw-flex tw-flex-shrink-0 tw-gap-[2px] tw-px-[1px] tw-spacing tw-items-center tw-h-7 tw-self-start tw-border tw-border-box-selected-inverse tw-rounded\">\n {items.map((item, i) =>\n 'draggableProps' in item ? (\n <Tooltip\n key={i}\n withArrow\n hoverDelay={0}\n enterDelay={300}\n open={isDragging}\n position={TooltipPosition.Top}\n content={\n <div>\n {isDragging ? DEFAULT_DRAGGING_TOOLTIP : item.tooltip ?? DEFAULT_DRAG_TOOLTIP}\n </div>\n }\n triggerElement={\n <button\n ref={item.setActivatorNodeRef}\n data-test-id=\"block-item-wrapper-toolbar-btn\"\n {...item.draggableProps}\n className={joinClassNames([\n FOCUS_VISIBLE_STYLE,\n 'tw-bg-base tw-relative tw-inline-flex tw-items-center tw-justify-center tw-w-6 tw-h-6 tw-rounded-sm focus-visible:tw-z-10',\n isDragging\n ? 'tw-cursor-grabbing tw-bg-box-selected-pressed'\n : 'tw-cursor-grab hover:tw-bg-box-selected-hover',\n ])}\n >\n {item.icon}\n </button>\n }\n />\n ) : (\n <Tooltip\n key={i}\n withArrow\n enterDelay={300}\n hoverDelay={0}\n disabled={isDragging}\n position={TooltipPosition.Top}\n content={<div>{item.tooltip ?? ''}</div>}\n triggerElement={\n <button\n data-test-id=\"block-item-wrapper-toolbar-btn\"\n onClick={item.onClick}\n className={joinClassNames([\n 'tw-bg-base tw-relative hover:tw-bg-box-selected-hover active:tw-bg-box-selected-pressed tw-cursor-pointer tw-inline-flex tw-items-center tw-justify-center tw-w-6 tw-h-6 tw-rounded-sm focus-visible:tw-z-10',\n FOCUS_VISIBLE_STYLE,\n ])}\n >\n {item.icon}\n </button>\n }\n />\n ),\n )}\n {flyoutItems.length > 0 && (\n <div className=\"tw-flex tw-flex-shrink-0 tw-flex-1 tw-h-6 tw-relative\">\n <Flyout\n isOpen={isFlyoutOpen && !isDragging}\n isTriggerDisabled={isFlyoutDisabled}\n legacyFooter={false}\n fitContent\n hug={false}\n onOpenChange={setIsFlyoutOpen}\n trigger={\n <Tooltip\n withArrow\n hoverDelay={0}\n enterDelay={300}\n disabled={isDragging}\n position={TooltipPosition.Top}\n content={<div>Options</div>}\n triggerElement={\n <div\n data-test-id=\"block-item-wrapper-toolbar-flyout\"\n className=\"tw-bg-base hover:tw-bg-box-selected-hover active:tw-bg-box-selected-pressed tw-cursor-pointer tw-inline-flex tw-items-center tw-justify-center tw-w-6 tw-h-6 tw-rounded-sm tw-relative\"\n >\n <IconDotsHorizontal16 />\n </div>\n }\n />\n }\n >\n <ActionMenu\n menuBlocks={flyoutItems.map((block, blockIndex) => ({\n id: blockIndex.toString(),\n menuItems: block.map((item, itemIndex) => ({\n id: blockIndex.toString() + itemIndex.toString(),\n size: MenuItemContentSize.XSmall,\n title: item.title,\n style: item.style,\n onClick: () => {\n setIsFlyoutOpen(false);\n item.onClick();\n },\n initialValue: true,\n decorator: <div className=\"tw-mr-2\">{item.icon}</div>,\n })),\n }))}\n />\n </Flyout>\n </div>\n )}\n </div>\n </div>\n );\n};\n"],"names":["Toolbar","items","flyoutItems","isFlyoutOpen","setIsFlyoutOpen","isDragging","isFlyoutDisabled","jsx","jsxs","item","i","Tooltip","TooltipPosition","DEFAULT_DRAGGING_TOOLTIP","DEFAULT_DRAG_TOOLTIP","joinClassNames","FOCUS_VISIBLE_STYLE","Flyout","IconDotsHorizontal16","ActionMenu","block","blockIndex","itemIndex","MenuItemContentSize"],"mappings":"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"}
@@ -1,133 +0,0 @@
1
- /* (c) Copyright Frontify Ltd., all rights reserved. */
2
-
3
- import {
4
- ActionMenu,
5
- FOCUS_VISIBLE_STYLE,
6
- Flyout,
7
- IconDotsHorizontal16,
8
- MenuItemContentSize,
9
- LegacyTooltip as Tooltip,
10
- TooltipPosition,
11
- } from '@frontify/fondue';
12
- import { ToolbarProps } from './types';
13
- import { joinClassNames } from '../../utilities';
14
- import { DEFAULT_DRAGGING_TOOLTIP, DEFAULT_DRAG_TOOLTIP } from './constants';
15
-
16
- export const Toolbar = ({
17
- items,
18
- flyoutItems,
19
- isFlyoutOpen,
20
- setIsFlyoutOpen,
21
- isDragging,
22
- isFlyoutDisabled,
23
- }: ToolbarProps) => {
24
- return (
25
- <div data-test-id="block-item-wrapper-toolbar" className="tw-flex tw-justify-end">
26
- <div className="tw-bg-white tw-isolate tw-text-box-selected-inverse tw-pointer-events-auto tw-flex tw-flex-shrink-0 tw-gap-[2px] tw-px-[1px] tw-spacing tw-items-center tw-h-7 tw-self-start tw-border tw-border-box-selected-inverse tw-rounded">
27
- {items.map((item, i) =>
28
- 'draggableProps' in item ? (
29
- <Tooltip
30
- key={i}
31
- withArrow
32
- hoverDelay={0}
33
- enterDelay={300}
34
- open={isDragging}
35
- position={TooltipPosition.Top}
36
- content={
37
- <div>
38
- {isDragging ? DEFAULT_DRAGGING_TOOLTIP : item.tooltip ?? DEFAULT_DRAG_TOOLTIP}
39
- </div>
40
- }
41
- triggerElement={
42
- <button
43
- ref={item.setActivatorNodeRef}
44
- data-test-id="block-item-wrapper-toolbar-btn"
45
- {...item.draggableProps}
46
- className={joinClassNames([
47
- FOCUS_VISIBLE_STYLE,
48
- 'tw-bg-base tw-relative tw-inline-flex tw-items-center tw-justify-center tw-w-6 tw-h-6 tw-rounded-sm focus-visible:tw-z-10',
49
- isDragging
50
- ? 'tw-cursor-grabbing tw-bg-box-selected-pressed'
51
- : 'tw-cursor-grab hover:tw-bg-box-selected-hover',
52
- ])}
53
- >
54
- {item.icon}
55
- </button>
56
- }
57
- />
58
- ) : (
59
- <Tooltip
60
- key={i}
61
- withArrow
62
- enterDelay={300}
63
- hoverDelay={0}
64
- disabled={isDragging}
65
- position={TooltipPosition.Top}
66
- content={<div>{item.tooltip ?? ''}</div>}
67
- triggerElement={
68
- <button
69
- data-test-id="block-item-wrapper-toolbar-btn"
70
- onClick={item.onClick}
71
- className={joinClassNames([
72
- 'tw-bg-base tw-relative hover:tw-bg-box-selected-hover active:tw-bg-box-selected-pressed tw-cursor-pointer tw-inline-flex tw-items-center tw-justify-center tw-w-6 tw-h-6 tw-rounded-sm focus-visible:tw-z-10',
73
- FOCUS_VISIBLE_STYLE,
74
- ])}
75
- >
76
- {item.icon}
77
- </button>
78
- }
79
- />
80
- ),
81
- )}
82
- {flyoutItems.length > 0 && (
83
- <div className="tw-flex tw-flex-shrink-0 tw-flex-1 tw-h-6 tw-relative">
84
- <Flyout
85
- isOpen={isFlyoutOpen && !isDragging}
86
- isTriggerDisabled={isFlyoutDisabled}
87
- legacyFooter={false}
88
- fitContent
89
- hug={false}
90
- onOpenChange={setIsFlyoutOpen}
91
- trigger={
92
- <Tooltip
93
- withArrow
94
- hoverDelay={0}
95
- enterDelay={300}
96
- disabled={isDragging}
97
- position={TooltipPosition.Top}
98
- content={<div>Options</div>}
99
- triggerElement={
100
- <div
101
- data-test-id="block-item-wrapper-toolbar-flyout"
102
- className="tw-bg-base hover:tw-bg-box-selected-hover active:tw-bg-box-selected-pressed tw-cursor-pointer tw-inline-flex tw-items-center tw-justify-center tw-w-6 tw-h-6 tw-rounded-sm tw-relative"
103
- >
104
- <IconDotsHorizontal16 />
105
- </div>
106
- }
107
- />
108
- }
109
- >
110
- <ActionMenu
111
- menuBlocks={flyoutItems.map((block, blockIndex) => ({
112
- id: blockIndex.toString(),
113
- menuItems: block.map((item, itemIndex) => ({
114
- id: blockIndex.toString() + itemIndex.toString(),
115
- size: MenuItemContentSize.XSmall,
116
- title: item.title,
117
- style: item.style,
118
- onClick: () => {
119
- setIsFlyoutOpen(false);
120
- item.onClick();
121
- },
122
- initialValue: true,
123
- decorator: <div className="tw-mr-2">{item.icon}</div>,
124
- })),
125
- }))}
126
- />
127
- </Flyout>
128
- </div>
129
- )}
130
- </div>
131
- </div>
132
- );
133
- };