@griddo/ax 11.11.8-rc.0 → 11.11.8

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 (104) hide show
  1. package/config/jest/componentsMock.js +5 -7
  2. package/package.json +2 -2
  3. package/src/__tests__/components/Browser/Browser.test.tsx +87 -438
  4. package/src/__tests__/components/ConfigPanel/ConfigPanel.test.tsx +3 -1
  5. package/src/__tests__/components/Fields/Button/Button.test.tsx +27 -29
  6. package/src/__tests__/components/ResizePanel/ResizePanel.test.tsx +1 -1
  7. package/src/components/Browser/index.tsx +139 -301
  8. package/src/components/Browser/style.tsx +6 -75
  9. package/src/components/BrowserContent/index.tsx +2 -2
  10. package/src/components/Button/index.tsx +1 -2
  11. package/src/components/ConfigPanel/Form/ConnectedField/PageConnectedField/Field/index.tsx +4 -2
  12. package/src/components/Fields/AsyncSelect/style.tsx +0 -13
  13. package/src/components/Fields/FieldGroup/index.tsx +2 -5
  14. package/src/components/Fields/FieldGroup/style.tsx +7 -32
  15. package/src/components/Fields/HeadingField/index.tsx +2 -2
  16. package/src/components/Fields/HiddenField/style.tsx +1 -1
  17. package/src/components/Fields/NumberField/index.tsx +16 -15
  18. package/src/components/Fields/NumberField/style.tsx +0 -2
  19. package/src/components/Fields/ReferenceField/index.tsx +1 -1
  20. package/src/components/Fields/Select/index.tsx +1 -5
  21. package/src/components/Fields/Select/style.tsx +0 -56
  22. package/src/components/Fields/SummaryButton/index.tsx +9 -18
  23. package/src/components/Fields/SummaryButton/style.tsx +2 -1
  24. package/src/components/Fields/TagsField/index.tsx +9 -8
  25. package/src/components/Fields/UrlField/index.tsx +27 -26
  26. package/src/components/Fields/index.tsx +0 -2
  27. package/src/components/FloatingPanel/index.tsx +2 -5
  28. package/src/components/FloatingPanel/style.tsx +1 -2
  29. package/src/components/IconAction/index.tsx +1 -1
  30. package/src/components/MainWrapper/AppBar/index.tsx +1 -8
  31. package/src/components/MainWrapper/index.tsx +1 -7
  32. package/src/components/Notification/index.tsx +2 -2
  33. package/src/components/OcassionalToast/index.tsx +8 -1
  34. package/src/components/OcassionalToast/style.tsx +15 -1
  35. package/src/components/PageFinder/index.tsx +1 -1
  36. package/src/components/ResizePanel/index.tsx +3 -4
  37. package/src/components/ResizePanel/style.tsx +1 -1
  38. package/src/components/SearchField/style.tsx +2 -2
  39. package/src/components/SideModal/index.tsx +1 -2
  40. package/src/components/Tabs/index.tsx +4 -13
  41. package/src/components/Tabs/style.tsx +8 -7
  42. package/src/components/Toast/index.tsx +2 -4
  43. package/src/components/Tooltip/index.tsx +3 -4
  44. package/src/components/index.tsx +0 -10
  45. package/src/forms/fields.tsx +68 -70
  46. package/src/hooks/forms.tsx +1 -22
  47. package/src/hooks/index.tsx +3 -13
  48. package/src/hooks/modals.tsx +15 -103
  49. package/src/hooks/users.tsx +8 -25
  50. package/src/modules/Forms/atoms.tsx +2 -2
  51. package/src/modules/FramePreview/index.tsx +16 -55
  52. package/src/modules/FramePreview/style.tsx +2 -34
  53. package/src/modules/GlobalEditor/Editor/index.tsx +3 -37
  54. package/src/modules/GlobalEditor/PageBrowser/index.tsx +2 -19
  55. package/src/modules/GlobalEditor/Preview/index.tsx +2 -0
  56. package/src/modules/GlobalEditor/Preview/style.tsx +1 -1
  57. package/src/modules/GlobalEditor/index.tsx +57 -119
  58. package/src/modules/PageEditor/Editor/index.tsx +2 -33
  59. package/src/modules/PageEditor/PageBrowser/index.tsx +2 -20
  60. package/src/modules/PageEditor/Preview/index.tsx +2 -0
  61. package/src/modules/PageEditor/Preview/style.tsx +1 -1
  62. package/src/modules/PageEditor/atoms.tsx +1 -1
  63. package/src/modules/PageEditor/index.tsx +66 -130
  64. package/src/modules/PublicPreview/index.tsx +5 -8
  65. package/src/schemas/pages/GlobalPage.ts +70 -87
  66. package/src/schemas/pages/Page.ts +70 -87
  67. package/src/types/index.tsx +0 -12
  68. package/src/__tests__/components/Browser/Browser.utils.test.ts +0 -55
  69. package/src/__tests__/components/HeadingsPreviewModal/ErrorsBanner/ErrorItem/ErrorItem.test.tsx +0 -158
  70. package/src/__tests__/components/HeadingsPreviewModal/ErrorsBanner/ErrorsBanner.test.tsx +0 -90
  71. package/src/__tests__/components/HeadingsPreviewModal/HeadingsPreviewModal.test.tsx +0 -178
  72. package/src/__tests__/components/HeadingsPreviewModal/HeadingsPreviewModal.utils.test.tsx +0 -150
  73. package/src/__tests__/components/KeywordsPreviewModal/KeywordItem/KeywordItem.test.tsx +0 -91
  74. package/src/__tests__/components/KeywordsPreviewModal/KeywordsPreviewModal.test.tsx +0 -122
  75. package/src/__tests__/components/KeywordsPreviewModal/KeywordsPreviewModal.utils.test.ts +0 -15
  76. package/src/__tests__/components/KeywordsPreviewModal/atoms.test.tsx +0 -101
  77. package/src/__tests__/modules/FramePreview/FramePreview.test.tsx +0 -318
  78. package/src/__tests__/modules/FramePreview/FramePreview.utils.test.ts +0 -242
  79. package/src/__tests__/modules/FramePreview/HeadingsOverlay/HeadingsOverlay.test.tsx +0 -185
  80. package/src/components/Browser/utils.tsx +0 -13
  81. package/src/components/Fields/SEOPreview/index.tsx +0 -36
  82. package/src/components/Fields/SEOPreview/style.tsx +0 -24
  83. package/src/components/FloatingNote/index.tsx +0 -35
  84. package/src/components/FloatingNote/style.tsx +0 -26
  85. package/src/components/HeadingsPreviewModal/ErrorsBanner/ErrorItem/index.tsx +0 -85
  86. package/src/components/HeadingsPreviewModal/ErrorsBanner/ErrorItem/style.tsx +0 -80
  87. package/src/components/HeadingsPreviewModal/ErrorsBanner/index.tsx +0 -57
  88. package/src/components/HeadingsPreviewModal/ErrorsBanner/style.tsx +0 -82
  89. package/src/components/HeadingsPreviewModal/HeadingItem/index.tsx +0 -71
  90. package/src/components/HeadingsPreviewModal/HeadingItem/style.tsx +0 -77
  91. package/src/components/HeadingsPreviewModal/index.tsx +0 -146
  92. package/src/components/HeadingsPreviewModal/style.tsx +0 -82
  93. package/src/components/HeadingsPreviewModal/utils.tsx +0 -257
  94. package/src/components/KeywordsPreviewModal/KeywordItem/index.tsx +0 -46
  95. package/src/components/KeywordsPreviewModal/KeywordItem/style.tsx +0 -64
  96. package/src/components/KeywordsPreviewModal/atoms.tsx +0 -96
  97. package/src/components/KeywordsPreviewModal/index.tsx +0 -99
  98. package/src/components/KeywordsPreviewModal/style.tsx +0 -87
  99. package/src/components/KeywordsPreviewModal/utils.tsx +0 -22
  100. package/src/components/PageInfoBanner/index.tsx +0 -38
  101. package/src/components/PageInfoBanner/styles.tsx +0 -40
  102. package/src/modules/FramePreview/HeadingsOverlay/index.tsx +0 -113
  103. package/src/modules/FramePreview/HeadingsOverlay/style.tsx +0 -24
  104. package/src/modules/FramePreview/utils.tsx +0 -140
@@ -1,22 +1,23 @@
1
- import { cleanup, fireEvent, render, screen } from "@testing-library/react";
2
- import { mock } from "jest-mock-extended";
1
+ import React from "react";
2
+
3
3
  import { ThemeProvider } from "styled-components";
4
+ import { mock } from "jest-mock-extended";
5
+ import { render, screen, cleanup, fireEvent } from "@testing-library/react";
4
6
  import "@testing-library/jest-dom";
5
7
 
6
- import Button, { type IButtonProps } from "@ax/components/Button";
8
+ import Button, { IButtonProps } from "@ax/components/Button";
7
9
  import { parseTheme } from "@ax/helpers";
8
10
  import globalTheme from "@ax/themes/theme.json";
9
11
 
10
12
  afterEach(cleanup);
11
13
 
12
- const createDefaultProps = (): IButtonProps => mock<IButtonProps>();
14
+ const defaultProps = mock<IButtonProps>();
13
15
 
14
16
  describe("Button component rendering", () => {
15
17
  it("should render the component with the default button and no icon", () => {
16
- const props = createDefaultProps();
17
18
  render(
18
19
  <ThemeProvider theme={parseTheme(globalTheme)}>
19
- <Button {...props} />
20
+ <Button {...defaultProps} />
20
21
  </ThemeProvider>,
21
22
  );
22
23
 
@@ -27,13 +28,12 @@ describe("Button component rendering", () => {
27
28
  });
28
29
 
29
30
  it("should render the component with the text button and an icon", () => {
30
- const props = createDefaultProps();
31
- props.buttonStyle = "text";
32
- props.icon = "delete";
31
+ defaultProps.buttonStyle = "text";
32
+ defaultProps.icon = "delete";
33
33
 
34
34
  render(
35
35
  <ThemeProvider theme={parseTheme(globalTheme)}>
36
- <Button {...props} />
36
+ <Button {...defaultProps} />
37
37
  </ThemeProvider>,
38
38
  );
39
39
 
@@ -44,11 +44,10 @@ describe("Button component rendering", () => {
44
44
  });
45
45
 
46
46
  it("should render the component with the line button", () => {
47
- const props = createDefaultProps();
48
- props.buttonStyle = "line";
47
+ defaultProps.buttonStyle = "line";
49
48
  render(
50
49
  <ThemeProvider theme={parseTheme(globalTheme)}>
51
- <Button {...props} />
50
+ <Button {...defaultProps} />
52
51
  </ThemeProvider>,
53
52
  );
54
53
 
@@ -57,12 +56,10 @@ describe("Button component rendering", () => {
57
56
  });
58
57
 
59
58
  it("should render the component with a className", () => {
60
- const props = createDefaultProps();
61
- props.className = "my-class";
62
- props.buttonStyle = "line";
59
+ defaultProps.className = "my-class";
63
60
  render(
64
61
  <ThemeProvider theme={parseTheme(globalTheme)}>
65
- <Button {...props} />
62
+ <Button {...defaultProps} />
66
63
  </ThemeProvider>,
67
64
  );
68
65
 
@@ -72,11 +69,10 @@ describe("Button component rendering", () => {
72
69
  });
73
70
 
74
71
  it("should render the children", () => {
75
- const props = createDefaultProps();
76
- props.children = "el texto";
72
+ defaultProps.children = "el texto";
77
73
  render(
78
74
  <ThemeProvider theme={parseTheme(globalTheme)}>
79
- <Button {...props} />
75
+ <Button {...defaultProps} />
80
76
  </ThemeProvider>,
81
77
  );
82
78
 
@@ -84,12 +80,13 @@ describe("Button component rendering", () => {
84
80
  });
85
81
 
86
82
  it("should trigger the onClick action", () => {
87
- const props = createDefaultProps();
88
- props.buttonStyle = "lineInverse";
89
- const handleOnClickMock = props.onClick as jest.MockedFunction<(e: React.MouseEvent<HTMLButtonElement>) => void>;
83
+ defaultProps.buttonStyle = "lineInverse";
84
+ const handleOnClickMock = defaultProps.onClick as jest.MockedFunction<
85
+ (e: React.MouseEvent<HTMLButtonElement>) => void
86
+ >;
90
87
  render(
91
88
  <ThemeProvider theme={parseTheme(globalTheme)}>
92
- <Button {...props} />
89
+ <Button {...defaultProps} />
93
90
  </ThemeProvider>,
94
91
  );
95
92
 
@@ -100,13 +97,14 @@ describe("Button component rendering", () => {
100
97
  });
101
98
 
102
99
  it("should not trigger the onClick action if the button is disabled", () => {
103
- const props = createDefaultProps();
104
- props.buttonStyle = "lineInverse";
105
- props.disabled = true;
106
- const handleOnClickMock = props.onClick as jest.MockedFunction<(e: React.MouseEvent<HTMLButtonElement>) => void>;
100
+ defaultProps.buttonStyle = "lineInverse";
101
+ defaultProps.disabled = true;
102
+ const handleOnClickMock = defaultProps.onClick as jest.MockedFunction<
103
+ (e: React.MouseEvent<HTMLButtonElement>) => void
104
+ >;
107
105
  render(
108
106
  <ThemeProvider theme={parseTheme(globalTheme)}>
109
- <Button {...props} />
107
+ <Button {...defaultProps} />
110
108
  </ThemeProvider>,
111
109
  );
112
110
 
@@ -151,6 +151,6 @@ describe("ResizePanel mouse events", () => {
151
151
  fireEvent.mouseUp(window);
152
152
 
153
153
  const width = getComputedStyle(rightPanel).width;
154
- expect(width).toBe("368px");
154
+ expect(width).toBe("344px");
155
155
  });
156
156
  });
@@ -1,36 +1,20 @@
1
- import { useEffect, useMemo, useRef, useState } from "react";
1
+ import { useEffect, useState } from "react";
2
2
 
3
3
  import type { IShareData } from "@ax/api";
4
4
  import { shareToken as shareTokenApi } from "@ax/api";
5
- import { BrowserContent, Icon, PageInfoBanner, Select, SharePageModal, Toast, Tooltip } from "@ax/components";
5
+ import { OcassionalToast } from "@ax/components";
6
6
  import { findByEditorID } from "@ax/forms";
7
- import { copyTextToClipboard, DEV_NOW, getShareTokenInfo } from "@ax/helpers";
7
+ import { DEV_NOW, getShareTokenInfo } from "@ax/helpers";
8
8
  import { useModal, useOnMessageReceivedFromIframe, useToast } from "@ax/hooks";
9
- import type { HeadingFilter } from "@ax/types";
10
9
 
11
- import { calcAutoZoom, calcDefaultResolution } from "./utils";
10
+ import BrowserContent from "../BrowserContent";
11
+ import Icon from "../Icon";
12
+ import SharePageModal from "../SharePageModal";
13
+ import Toast from "../Toast";
14
+ import Tooltip from "../Tooltip";
12
15
 
13
16
  import * as S from "./style";
14
17
 
15
- const DEFAULT_RESOLUTION = "1280px";
16
-
17
- const resolutionOptions = [
18
- { value: "1920px", label: "1920px" },
19
- { value: "1440px", label: "1440px" },
20
- { value: "1280px", label: "1280px" },
21
- { value: "1024px", label: "1024px" },
22
- { value: "768px", label: "768px" },
23
- { value: "360px", label: "360px" },
24
- ];
25
-
26
- const zoomOptions = [
27
- { value: "reset", label: "Reset" },
28
- { value: "100", label: "100%" },
29
- { value: "75", label: "75%" },
30
- { value: "50", label: "50%" },
31
- { value: "25", label: "25%" },
32
- ];
33
-
34
18
  const Browser = (props: IBrowserProps): JSX.Element => {
35
19
  const {
36
20
  url,
@@ -49,27 +33,15 @@ const Browser = (props: IBrowserProps): JSX.Element => {
49
33
  browserRef,
50
34
  actions,
51
35
  editorType = "page",
52
- headingFilter,
53
- keywordsFilter,
54
- toggleHeadingsPreview,
55
- toggleKeywordsPreview,
56
36
  } = props;
57
37
 
58
38
  const { id, entity, haveDraftPage } = content;
59
39
  const domain = window.location.origin;
60
- const headingFilterParam = !headingFilter || headingFilter === "all" ? "" : `&headingFilter=${headingFilter}`;
61
- const keywordsFilterParam = !keywordsFilter || !keywordsFilter.length ? "" : `&keywordFilter=${keywordsFilter}`;
40
+ const urlPreview = `${domain}/editor/page-preview?preview=${!!isPreview}&disabled=${!!disabled}&type=${editorType}`;
62
41
  const isPageEditor = editorType === "page";
63
42
  const isFormEditor = editorType === "form";
64
- const isHeadingsEditor = editorType === "headings";
65
- const isKeywordsEditor = editorType === "keywords";
66
43
 
67
- const frameWrapperRef = useRef<HTMLDivElement>(null);
68
-
69
- const [previewResolution, setPreviewResolution] = useState("desktop");
70
- const [dimensions, setDimensions] = useState({ resolution: DEFAULT_RESOLUTION, zoom: "100" });
71
-
72
- const urlPreview = `${domain}/editor/page-preview?preview=${!!isPreview}&disabled=${!!disabled}&type=${editorType}${headingFilterParam}${keywordsFilterParam}`;
44
+ const [resolution, setResolution] = useState("desktop");
73
45
  const { isVisible, toggleToast, setIsVisible, state: toastState } = useToast();
74
46
  const { isOpen: isShareOpen, toggleModal: toggleSharePageModal } = useModal(false, true);
75
47
  const [shareData, setShareData] = useState<IShareData | null>(null);
@@ -81,24 +53,6 @@ const Browser = (props: IBrowserProps): JSX.Element => {
81
53
  useEffect(() => {
82
54
  localStorage.setItem("selectedID", "0");
83
55
  (window as any).browserRef = null;
84
-
85
- const el = frameWrapperRef.current;
86
- if (!el) return;
87
-
88
- let lastWidth = 0;
89
- const observer = new ResizeObserver(([entry]) => {
90
- const containerWidth = entry.contentRect.width;
91
- if (containerWidth > 0 && Math.abs(containerWidth - lastWidth) > 20) {
92
- lastWidth = containerWidth;
93
- const resolution = calcDefaultResolution(containerWidth, resolutionOptions);
94
- const newZoom = calcAutoZoom(containerWidth, resolution);
95
- setDimensions({ resolution, zoom: newZoom });
96
- }
97
- });
98
-
99
- observer.observe(el);
100
-
101
- return () => observer.disconnect();
102
56
  }, []);
103
57
 
104
58
  // Fetch share data when in preview mode
@@ -131,258 +85,146 @@ const Browser = (props: IBrowserProps): JSX.Element => {
131
85
  }
132
86
  };
133
87
 
134
- const getWidth = (res: string) => {
135
- if (!isPreview) return dimensions.resolution;
136
-
137
- switch (res) {
138
- case "tablet":
139
- return "768px";
140
- case "phone":
141
- return "425px";
142
- default:
143
- return "100%";
144
- }
88
+ const deleteModuleSelected = (editorID: number) => {
89
+ actions?.setSelectedContentAction(0);
90
+ actions?.deleteModuleAction?.([editorID]);
145
91
  };
146
92
 
147
- const copyUrl = () => {
148
- const sharedUrl = `${domain}/page-preview/${id}/${entity}`;
149
- copyTextToClipboard(sharedUrl).then(
150
- () => {
151
- toggleToast("URL Copied");
152
- },
153
- (err) => {
154
- console.error("Could not copy text: ", err);
155
- },
156
- );
93
+ const duplicateModuleSelected = (editorID: number) => {
94
+ const duplicatedEditorID = actions?.duplicateModuleAction?.([editorID]);
95
+ duplicatedEditorID && actions?.setSelectedContentAction(duplicatedEditorID);
157
96
  };
158
97
 
159
- const moduleActions = useMemo(
160
- () => ({
161
- deleteModuleAction: (editorID: number) => {
162
- actions?.setSelectedContentAction(0);
163
- actions?.deleteModuleAction?.([editorID]);
164
- },
165
- duplicateModuleAction: (editorID: number) => {
166
- const duplicatedEditorID = actions?.duplicateModuleAction?.([editorID]);
167
- duplicatedEditorID && actions?.setSelectedContentAction(duplicatedEditorID);
168
- },
169
- copyModuleAction: (editorID: number) => {
170
- const isCopied = actions?.copyModuleAction?.([editorID]);
171
- isCopied && toggleToast("1 module copied to clipboard");
172
- },
173
- }),
174
- [actions, toggleToast],
175
- );
176
-
177
- const maxFittingZoom = parseInt(calcAutoZoom(frameWrapperRef.current?.clientWidth ?? 0, dimensions.resolution));
178
- const zoomOptionsWithDisabled = useMemo(() => {
179
- const isCurrentZoomInOptions = zoomOptions.some((opt) => opt.value === dimensions.zoom);
180
- return [
181
- ...(!isCurrentZoomInOptions ? [{ value: dimensions.zoom, label: `${dimensions.zoom}%` }] : []),
182
- ...zoomOptions.map((option) => ({
183
- ...option,
184
- isDisabled: option.value === "reset" ? !isCurrentZoomInOptions : parseInt(option.value) > maxFittingZoom,
185
- })),
186
- ];
187
- }, [dimensions.zoom, maxFittingZoom]);
188
-
189
- const handleResolutionChange = (resolution: string) => {
190
- const containerWidth = frameWrapperRef.current?.clientWidth ?? 0;
191
- setDimensions({ resolution, zoom: calcAutoZoom(containerWidth, resolution) });
98
+ const copyModuleSelected = (editorID: number) => {
99
+ const isCopied = actions?.copyModuleAction?.([editorID]);
100
+ isCopied && toggleToast("1 module copied to clipboard");
192
101
  };
193
102
 
194
- const handleZoomChange = (zoom: string) => {
195
- if (zoom === "reset") {
196
- const containerWidth = frameWrapperRef.current?.clientWidth ?? 0;
197
- setDimensions((prev) => ({ ...prev, zoom: calcAutoZoom(containerWidth, prev.resolution) }));
198
- } else {
199
- setDimensions((prev) => ({ ...prev, zoom }));
200
- }
103
+ const moduleActions = {
104
+ deleteModuleAction: deleteModuleSelected,
105
+ duplicateModuleAction: duplicateModuleSelected,
106
+ copyModuleAction: copyModuleSelected,
201
107
  };
202
108
 
203
- const scaledWidth = !isPreview
204
- ? Math.floor(parseInt(dimensions.resolution) * (parseInt(dimensions.zoom) / 100))
205
- : undefined;
206
-
207
- const isCompact = scaledWidth !== undefined && scaledWidth <= 400;
208
- const floatingNoteConfig = isHeadingsEditor
209
- ? { label: "Headings", onClick: toggleHeadingsPreview }
210
- : isKeywordsEditor
211
- ? { label: "Keywords", onClick: toggleKeywordsPreview }
212
- : null;
213
-
214
109
  return (
215
- <S.OuterContainer ref={frameWrapperRef}>
216
- <S.BrowserWrapper data-testid="browser-wrapper" ref={browserRef} scaledWidth={scaledWidth} isPreview={isPreview}>
217
- {(isPageEditor || isHeadingsEditor || isKeywordsEditor) && (
218
- <S.NavBar>
219
- <S.NavUrl>{url}</S.NavUrl>
220
- {isPreview ? (
221
- <S.NavActions data-testid="nav-actions-wrapper">
222
- <S.IconWrapper
223
- data-testid="icon-wrapper-browser"
224
- onClick={haveDraftPage ? undefined : toggleSharePageModal}
225
- active={!haveDraftPage}
226
- >
227
- <Tooltip
228
- hideOnClick={!haveDraftPage}
229
- content={
230
- haveDraftPage ? "Only available for drafts. This page already has a public URL." : "Share draft"
231
- }
232
- bottom
233
- >
234
- <Icon name="share" size="24" />
235
- </Tooltip>
236
- </S.IconWrapper>
237
- <S.IconWrapper active={previewResolution === "desktop"} onClick={() => setPreviewResolution("desktop")}>
238
- <Tooltip content="Desktop" bottom>
239
- <Icon name="desktop" size="24" />
240
- </Tooltip>
241
- </S.IconWrapper>
242
- <S.IconWrapper
243
- data-testid="icon-res-tablet"
244
- active={previewResolution === "tablet"}
245
- onClick={() => setPreviewResolution("tablet")}
246
- >
247
- <Tooltip content="Tablet" bottom>
248
- <Icon name="tablet" size="24" />
249
- </Tooltip>
250
- </S.IconWrapper>
251
- <S.IconWrapper
252
- data-testid="icon-res-phone"
253
- active={previewResolution === "phone"}
254
- onClick={() => setPreviewResolution("phone")}
110
+ <S.BrowserWrapper data-testid="browser-wrapper" ref={browserRef}>
111
+ {isPageEditor && (
112
+ <S.NavBar>
113
+ <S.NavUrl>{url}</S.NavUrl>
114
+ {isPreview && (
115
+ <S.NavActions data-testid="nav-actions-wrapper">
116
+ <S.IconWrapper
117
+ data-testid="icon-wrapper-browser"
118
+ onClick={haveDraftPage ? undefined : toggleSharePageModal}
119
+ active={!haveDraftPage}
120
+ >
121
+ <Tooltip
122
+ hideOnClick={!haveDraftPage}
123
+ content={
124
+ haveDraftPage ? "Only available for drafts. This page already has a public URL." : "Share draft"
125
+ }
126
+ bottom
255
127
  >
256
- <Tooltip content="Mobile" bottom>
257
- <Icon name="phone" size="24" />
258
- </Tooltip>
259
- </S.IconWrapper>
260
- </S.NavActions>
261
- ) : (
262
- <S.NavActions data-testid="nav-actions-wrapper">
263
- <S.ResolutionWrapper>
264
- <S.SelectLabel>Screen</S.SelectLabel>
265
- <Select
266
- name="resolution"
267
- options={resolutionOptions}
268
- value={dimensions.resolution}
269
- onChange={handleResolutionChange}
270
- type="round"
271
- offSet="30%"
272
- mandatory
273
- />
274
- </S.ResolutionWrapper>
275
- <S.ZoomWrapper>
276
- <Select
277
- name="zoom"
278
- options={zoomOptionsWithDisabled}
279
- value={dimensions.zoom}
280
- onChange={handleZoomChange}
281
- type="round"
282
- mandatory
283
- />
284
- </S.ZoomWrapper>
285
- </S.NavActions>
286
- )}
287
- </S.NavBar>
288
- )}
289
- {showIframe ? (
290
- <S.ContentWrapper>
291
- {floatingNoteConfig && (
292
- <S.StyledFloatingNote
293
- message={`You are viewing the ${floatingNoteConfig.label} editor${isCompact ? "" : " of this page"}`}
294
- btnText={isCompact ? "Back" : "Back to Page Editor"}
295
- onClick={floatingNoteConfig.onClick}
296
- $compact={isCompact}
297
- />
298
- )}
299
- <S.FrameWrapper
300
- hasBorder={isPageEditor || isHeadingsEditor || isKeywordsEditor}
301
- isFormEditor={isFormEditor}
302
- data-testid="navbar-iframe-wrapper"
303
- >
304
- {isPreview ? (
305
- <iframe
306
- title="Preview"
307
- width={getWidth(previewResolution)}
308
- height="100%"
309
- src={urlPreview}
310
- loading="lazy"
311
- className="frame-content"
312
- />
313
- ) : (
314
- <div
315
- style={{
316
- width: `${scaledWidth}px`,
317
- height: "100%",
318
- overflow: "hidden",
319
- flexShrink: 0,
320
- }}
321
- >
322
- <iframe
323
- title="Preview"
324
- width={dimensions.resolution}
325
- src={urlPreview}
326
- loading="lazy"
327
- className="frame-content"
328
- style={{
329
- display: "block",
330
- transform: `scale(${parseInt(dimensions.zoom) / 100})`,
331
- transformOrigin: "0 0",
332
- height: `${Math.round(100 / (parseInt(dimensions.zoom) / 100))}%`,
333
- }}
334
- />
335
- </div>
336
- )}
337
- </S.FrameWrapper>
338
- </S.ContentWrapper>
339
- ) : (
340
- <S.Wrapper data-testid="browser-content-wrapper" className="browser-content">
341
- <BrowserContent
342
- cloudinaryName={cloudinaryName}
343
- theme={theme}
344
- socials={socials}
345
- siteLangs={siteLangs}
346
- selectEditorID={selectEditorID}
347
- siteID={siteID}
348
- isPage={isPage}
349
- content={content}
350
- header={header}
351
- footer={footer}
352
- languageID={content.language}
353
- pageLanguages={content.pageLanguages}
354
- moduleActions={moduleActions}
355
- renderer="editor"
356
- />
357
- </S.Wrapper>
358
- )}
359
- {isVisible && <Toast message={toastState} setIsVisible={setIsVisible} />}
360
- {isPreview && shareData && tokenInfo && (
361
- <PageInfoBanner
362
- message={
363
- tokenInfo.tokenHasExpired
364
- ? `Access to this draft link expired on ${tokenInfo.tokenExpirationDate}. You need to generate a`
365
- : `This draft link expires on ${tokenInfo.tokenExpirationDate}. ${tokenInfo.tokenCanBeRenewed ? "Renew it" : "Open details"}`
366
- }
367
- actionLabel={tokenInfo.tokenHasExpired ? "new one" : "here"}
368
- icon={tokenInfo.tokenHasExpired ? "hide" : "view"}
369
- onAction={toggleSharePageModal}
128
+ <Icon name="share" size="24" />
129
+ </Tooltip>
130
+ </S.IconWrapper>
131
+ <S.IconWrapper active={resolution === "desktop"} onClick={() => setResolution("desktop")}>
132
+ <Tooltip content="Desktop" bottom>
133
+ <Icon name="desktop" size="24" />
134
+ </Tooltip>
135
+ </S.IconWrapper>
136
+ <S.IconWrapper
137
+ data-testid="icon-res-tablet"
138
+ active={resolution === "tablet"}
139
+ onClick={() => setResolution("tablet")}
140
+ >
141
+ <Tooltip content="Tablet" bottom>
142
+ <Icon name="tablet" size="24" />
143
+ </Tooltip>
144
+ </S.IconWrapper>
145
+ <S.IconWrapper
146
+ data-testid="icon-res-phone"
147
+ active={resolution === "phone"}
148
+ onClick={() => setResolution("phone")}
149
+ >
150
+ <Tooltip content="Mobile" bottom>
151
+ <Icon name="phone" size="24" />
152
+ </Tooltip>
153
+ </S.IconWrapper>
154
+ </S.NavActions>
155
+ )}
156
+ </S.NavBar>
157
+ )}
158
+
159
+ {showIframe ? (
160
+ <S.FrameWrapper hasBorder={isPageEditor} isFormEditor={isFormEditor} data-testid="navbar-iframe-wrapper">
161
+ <iframe
162
+ title="Preview"
163
+ width={getWidth(resolution)}
164
+ height="100%"
165
+ src={urlPreview}
166
+ loading="lazy"
167
+ className="frame-content"
370
168
  />
371
- )}
372
-
373
- {isPreview && (
374
- <SharePageModal
375
- pageTitle={content.title}
376
- isOpen={isShareOpen}
377
- hide={toggleSharePageModal}
378
- pageID={id}
379
- entity={entity}
380
- shareData={shareData}
381
- onShareChange={setShareData}
169
+ </S.FrameWrapper>
170
+ ) : (
171
+ <S.Wrapper
172
+ data-testid="browser-content-wrapper"
173
+ // biome-ignore lint/suspicious/noAssignInExpressions: TODO: fix this
174
+ ref={(ref: any) => ((window as any).browserRef = ref)}
175
+ className="browser-content"
176
+ >
177
+ <BrowserContent
178
+ cloudinaryName={cloudinaryName}
179
+ theme={theme}
180
+ socials={socials}
181
+ siteLangs={siteLangs}
182
+ selectEditorID={selectEditorID}
183
+ siteID={siteID}
184
+ isPage={isPage}
185
+ content={content}
186
+ header={header}
187
+ footer={footer}
188
+ languageID={content.language}
189
+ pageLanguages={content.pageLanguages}
190
+ moduleActions={moduleActions}
191
+ renderer="editor"
382
192
  />
383
- )}
384
- </S.BrowserWrapper>
385
- </S.OuterContainer>
193
+ </S.Wrapper>
194
+ )}
195
+
196
+ {isVisible && <Toast message={toastState} setIsVisible={setIsVisible} />}
197
+
198
+ {isPreview && shareData && tokenInfo && (
199
+ <OcassionalToast
200
+ message={
201
+ <>
202
+ {tokenInfo.tokenHasExpired
203
+ ? `Access to this draft link expired on ${tokenInfo.tokenExpirationDate}. You need to generate a `
204
+ : `This draft link expires on ${tokenInfo.tokenExpirationDate}. ${tokenInfo.tokenCanBeRenewed ? "Renew it" : "Open details"}${" "}`}
205
+ <button type="button" onClick={toggleSharePageModal}>
206
+ <strong style={{ textDecoration: "underline" }}>
207
+ {tokenInfo.tokenHasExpired ? "new one" : "here"}
208
+ </strong>
209
+ </button>
210
+ </>
211
+ }
212
+ icon={tokenInfo.tokenHasExpired ? "hide" : "view"}
213
+ />
214
+ )}
215
+
216
+ {isPreview && (
217
+ <SharePageModal
218
+ pageTitle={content.title}
219
+ isOpen={isShareOpen}
220
+ hide={toggleSharePageModal}
221
+ pageID={id}
222
+ entity={entity}
223
+ shareData={shareData}
224
+ onShareChange={setShareData}
225
+ />
226
+ )}
227
+ </S.BrowserWrapper>
386
228
  );
387
229
  };
388
230
 
@@ -411,11 +253,7 @@ export interface IBrowserProps {
411
253
  isPreview?: boolean;
412
254
  showIframe?: boolean;
413
255
  browserRef?: React.RefObject<HTMLDivElement>;
414
- editorType?: "form" | "page" | "headings" | "keywords";
415
- headingFilter?: HeadingFilter;
416
- keywordsFilter?: string[];
417
- toggleHeadingsPreview?(): void;
418
- toggleKeywordsPreview?(): void;
256
+ editorType?: "form" | "page";
419
257
  actions?: {
420
258
  setSelectedContentAction(editorID: number): void;
421
259
  deleteModuleAction?(editorID: number[]): void;