@griddo/ax 11.12.1-rc.2 → 11.12.1-rc.4
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/package.json +2 -2
- package/src/__tests__/components/Browser/Browser.test.tsx +1 -1
- package/src/components/Browser/index.tsx +11 -15
- package/src/components/HeadingsPreviewModal/ErrorsBanner/ErrorItem/index.tsx +8 -2
- package/src/components/HeadingsPreviewModal/ErrorsBanner/index.tsx +19 -4
- package/src/components/HeadingsPreviewModal/utils.tsx +5 -6
- package/src/components/KeywordsPreviewModal/index.tsx +13 -2
- package/src/hooks/modals.tsx +4 -4
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@griddo/ax",
|
|
3
3
|
"description": "Griddo Author Experience",
|
|
4
|
-
"version": "11.12.1-rc.
|
|
4
|
+
"version": "11.12.1-rc.4",
|
|
5
5
|
"authors": [
|
|
6
6
|
"Álvaro Sánchez' <alvaro.sanches@secuoyas.com>",
|
|
7
7
|
"Diego M. Béjar <diego.bejar@secuoyas.com>",
|
|
@@ -217,5 +217,5 @@
|
|
|
217
217
|
"publishConfig": {
|
|
218
218
|
"access": "public"
|
|
219
219
|
},
|
|
220
|
-
"gitHead": "
|
|
220
|
+
"gitHead": "da2037760c929e2ba660fda8abb67611be1bea0a"
|
|
221
221
|
}
|
|
@@ -70,7 +70,7 @@ describe("Browser component rendering", () => {
|
|
|
70
70
|
|
|
71
71
|
renderBrowser(defaultProps);
|
|
72
72
|
|
|
73
|
-
expect(screen.
|
|
73
|
+
expect(screen.queryByTestId("nav-actions-wrapper")).not.toBeInTheDocument();
|
|
74
74
|
expect(screen.queryByTestId("navbar-iframe-wrapper")).not.toBeInTheDocument();
|
|
75
75
|
expect(screen.getByTestId("browser-content-wrapper")).toBeInTheDocument();
|
|
76
76
|
});
|
|
@@ -63,6 +63,7 @@ const Browser = (props: IBrowserProps): JSX.Element => {
|
|
|
63
63
|
const isFormEditor = editorType === "form";
|
|
64
64
|
const isHeadingsEditor = editorType === "headings";
|
|
65
65
|
const isKeywordsEditor = editorType === "keywords";
|
|
66
|
+
const isZoomEditor = isPageEditor || isHeadingsEditor || isKeywordsEditor;
|
|
66
67
|
|
|
67
68
|
const frameWrapperRef = useRef<HTMLDivElement>(null);
|
|
68
69
|
|
|
@@ -82,8 +83,7 @@ const Browser = (props: IBrowserProps): JSX.Element => {
|
|
|
82
83
|
localStorage.setItem("selectedID", "0");
|
|
83
84
|
(window as any).browserRef = null;
|
|
84
85
|
|
|
85
|
-
|
|
86
|
-
if (!isPageEditor) return;
|
|
86
|
+
if (!isZoomEditor) return;
|
|
87
87
|
|
|
88
88
|
const el = frameWrapperRef.current;
|
|
89
89
|
if (!el) return;
|
|
@@ -102,7 +102,7 @@ const Browser = (props: IBrowserProps): JSX.Element => {
|
|
|
102
102
|
observer.observe(el);
|
|
103
103
|
|
|
104
104
|
return () => observer.disconnect();
|
|
105
|
-
}, [
|
|
105
|
+
}, [isZoomEditor]);
|
|
106
106
|
|
|
107
107
|
// Fetch share data when in preview mode
|
|
108
108
|
useEffect(() => {
|
|
@@ -191,7 +191,7 @@ const Browser = (props: IBrowserProps): JSX.Element => {
|
|
|
191
191
|
}
|
|
192
192
|
};
|
|
193
193
|
|
|
194
|
-
const scaledWidth =
|
|
194
|
+
const scaledWidth = isZoomEditor
|
|
195
195
|
? Math.floor(parseInt(dimensions.resolution) * (parseInt(dimensions.zoom) / 100))
|
|
196
196
|
: undefined;
|
|
197
197
|
|
|
@@ -208,9 +208,9 @@ const Browser = (props: IBrowserProps): JSX.Element => {
|
|
|
208
208
|
data-testid="browser-wrapper"
|
|
209
209
|
ref={browserRef}
|
|
210
210
|
scaledWidth={scaledWidth}
|
|
211
|
-
isPreview={!
|
|
211
|
+
isPreview={!isZoomEditor}
|
|
212
212
|
>
|
|
213
|
-
{
|
|
213
|
+
{isZoomEditor && (
|
|
214
214
|
<S.NavBar>
|
|
215
215
|
<S.NavUrl>{url}</S.NavUrl>
|
|
216
216
|
{isPreview ? (
|
|
@@ -296,11 +296,7 @@ const Browser = (props: IBrowserProps): JSX.Element => {
|
|
|
296
296
|
$compact={isCompact}
|
|
297
297
|
/>
|
|
298
298
|
)}
|
|
299
|
-
<S.FrameWrapper
|
|
300
|
-
hasBorder={isPageEditor || isHeadingsEditor || isKeywordsEditor}
|
|
301
|
-
isFormEditor={isFormEditor}
|
|
302
|
-
data-testid="navbar-iframe-wrapper"
|
|
303
|
-
>
|
|
299
|
+
<S.FrameWrapper hasBorder={isZoomEditor} isFormEditor={isFormEditor} data-testid="navbar-iframe-wrapper">
|
|
304
300
|
{isPreview ? (
|
|
305
301
|
<iframe
|
|
306
302
|
title="Preview"
|
|
@@ -316,20 +312,20 @@ const Browser = (props: IBrowserProps): JSX.Element => {
|
|
|
316
312
|
width: scaledWidth !== undefined ? `${scaledWidth}px` : "100%",
|
|
317
313
|
height: "100%",
|
|
318
314
|
overflow: "hidden",
|
|
319
|
-
flexShrink:
|
|
315
|
+
flexShrink: isZoomEditor ? 0 : "unset",
|
|
320
316
|
}}
|
|
321
317
|
>
|
|
322
318
|
<iframe
|
|
323
319
|
title="Preview"
|
|
324
|
-
width={
|
|
320
|
+
width={isZoomEditor ? dimensions.resolution : "100%"}
|
|
325
321
|
src={urlPreview}
|
|
326
322
|
loading="lazy"
|
|
327
323
|
className="frame-content"
|
|
328
324
|
style={{
|
|
329
325
|
display: "block",
|
|
330
|
-
transform:
|
|
326
|
+
transform: isZoomEditor ? `scale(${parseInt(dimensions.zoom) / 100})` : "scale(1)",
|
|
331
327
|
transformOrigin: "0 0",
|
|
332
|
-
height:
|
|
328
|
+
height: isZoomEditor ? `${Math.round(100 / (parseInt(dimensions.zoom) / 100))}%` : "100%",
|
|
333
329
|
}}
|
|
334
330
|
/>
|
|
335
331
|
</div>
|
|
@@ -7,7 +7,7 @@ import type { IHeadingError } from "../../utils";
|
|
|
7
7
|
import * as S from "./style";
|
|
8
8
|
|
|
9
9
|
const ErrorsItem = (props: IErrorsItemProps) => {
|
|
10
|
-
const { error, onSelectHeading } = props;
|
|
10
|
+
const { error, onSelectHeading, onDelete } = props;
|
|
11
11
|
const { message, description, headingIds } = error;
|
|
12
12
|
|
|
13
13
|
const [isOpen, setIsOpen] = useState(false);
|
|
@@ -54,7 +54,12 @@ const ErrorsItem = (props: IErrorsItemProps) => {
|
|
|
54
54
|
<Icon name={isOpen ? "UpArrow" : "DownArrow"} size="16" />
|
|
55
55
|
</S.IconWrapper>
|
|
56
56
|
)}
|
|
57
|
-
<S.IconWrapper
|
|
57
|
+
<S.IconWrapper
|
|
58
|
+
onClick={() => {
|
|
59
|
+
setIsDeleted(true);
|
|
60
|
+
onDelete();
|
|
61
|
+
}}
|
|
62
|
+
>
|
|
58
63
|
<Icon name="close" size="16" />
|
|
59
64
|
</S.IconWrapper>
|
|
60
65
|
</S.ErrorActions>
|
|
@@ -80,6 +85,7 @@ const ErrorsItem = (props: IErrorsItemProps) => {
|
|
|
80
85
|
interface IErrorsItemProps {
|
|
81
86
|
error: IHeadingError;
|
|
82
87
|
onSelectHeading: (id: number) => () => void;
|
|
88
|
+
onDelete: () => void;
|
|
83
89
|
}
|
|
84
90
|
|
|
85
91
|
export default ErrorsItem;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useState } from "react";
|
|
1
|
+
import { useMemo, useState } from "react";
|
|
2
2
|
|
|
3
3
|
import { Icon } from "@ax/components";
|
|
4
4
|
|
|
@@ -11,8 +11,18 @@ const ErrorsBanner = (props: IErrorsBannerProps) => {
|
|
|
11
11
|
const { errors, onSelectHeading, isOpen, setIsOpen, resetKey } = props;
|
|
12
12
|
|
|
13
13
|
const [isDeleted, setIsDeleted] = useState(false);
|
|
14
|
+
const [deletedErrorIndices, setDeletedErrorIndices] = useState<Set<number>>(new Set());
|
|
14
15
|
|
|
15
|
-
|
|
16
|
+
const allErrorsDeleted = useMemo(
|
|
17
|
+
() => deletedErrorIndices.size === errors.length && errors.length > 0,
|
|
18
|
+
[deletedErrorIndices.size, errors.length],
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
const handleErrorDelete = (index: number) => {
|
|
22
|
+
setDeletedErrorIndices((prev) => new Set([...prev, index]));
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
if (isDeleted || allErrorsDeleted) {
|
|
16
26
|
return <></>;
|
|
17
27
|
}
|
|
18
28
|
|
|
@@ -37,8 +47,13 @@ const ErrorsBanner = (props: IErrorsBannerProps) => {
|
|
|
37
47
|
Review <strong>suggestions and warnings</strong> to enhance your page's search engine optimization.
|
|
38
48
|
</S.Description>
|
|
39
49
|
<S.ErrorListWrapper>
|
|
40
|
-
{errors.map((error) => (
|
|
41
|
-
<ErrorItem
|
|
50
|
+
{errors.map((error, index) => (
|
|
51
|
+
<ErrorItem
|
|
52
|
+
key={`${error.message}-${resetKey}`}
|
|
53
|
+
error={error}
|
|
54
|
+
onSelectHeading={onSelectHeading}
|
|
55
|
+
onDelete={() => handleErrorDelete(index)}
|
|
56
|
+
/>
|
|
42
57
|
))}
|
|
43
58
|
</S.ErrorListWrapper>
|
|
44
59
|
</S.ErrorsContent>
|
|
@@ -67,17 +67,16 @@ const analyzeHeadings = (headings: HeadingNode[], isFiltering = false): IHeading
|
|
|
67
67
|
|
|
68
68
|
// 2. Check for incorrect nesting (skipped levels)
|
|
69
69
|
const nestingErrorIds: number[] = [];
|
|
70
|
-
let
|
|
71
|
-
for (let i =
|
|
70
|
+
let lastValidLevel = flatHeadings[0].level;
|
|
71
|
+
for (let i = 1; i < flatHeadings.length; i++) {
|
|
72
72
|
const currLevel = flatHeadings[i].level;
|
|
73
73
|
|
|
74
|
-
if (currLevel >
|
|
74
|
+
if (currLevel > lastValidLevel + 1) {
|
|
75
75
|
// Heading skips levels - mark as error
|
|
76
76
|
nestingErrorIds.push(flatHeadings[i].id);
|
|
77
|
-
// Don't update expectedMaxLevel - stay strict on what we expect next
|
|
78
77
|
} else {
|
|
79
|
-
// Correct nesting - update
|
|
80
|
-
|
|
78
|
+
// Correct nesting - update last valid level
|
|
79
|
+
lastValidLevel = currLevel;
|
|
81
80
|
}
|
|
82
81
|
}
|
|
83
82
|
if (nestingErrorIds.length > 0) {
|
|
@@ -39,11 +39,22 @@ const KeywordsPreviewModal = (props: IKeywordsPreviewProps) => {
|
|
|
39
39
|
const handleDeleteKeyword = (value: string) => {
|
|
40
40
|
setDeletedKeyword(value);
|
|
41
41
|
deleteKeyword(value);
|
|
42
|
+
setKeywordsFilter([]);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const handleCloseModal = () => {
|
|
46
|
+
setKeywordsFilter([]);
|
|
47
|
+
toggleModal();
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const handleAddKeywords = (value: string[]) => {
|
|
51
|
+
setKeywordsFilter([]);
|
|
52
|
+
addKeywords(value);
|
|
42
53
|
};
|
|
43
54
|
|
|
44
55
|
return (
|
|
45
56
|
<S.Wrapper>
|
|
46
|
-
<FloatingPanel title="Keywords" toggleModal={
|
|
57
|
+
<FloatingPanel title="Keywords" toggleModal={handleCloseModal} closeOnOutsideClick={false} isOpen={isOpen} width={358}>
|
|
47
58
|
{isOpen && (
|
|
48
59
|
<S.KeywordsWrapper>
|
|
49
60
|
{keywordsFilter.length > 0 && (
|
|
@@ -79,7 +90,7 @@ const KeywordsPreviewModal = (props: IKeywordsPreviewProps) => {
|
|
|
79
90
|
</S.KeywordsWrapper>
|
|
80
91
|
)}
|
|
81
92
|
</FloatingPanel>
|
|
82
|
-
<AddKeywordsModal isOpen={isAddOpen} toggleModal={toggleAddModal} addNewKeyword={
|
|
93
|
+
<AddKeywordsModal isOpen={isAddOpen} toggleModal={toggleAddModal} addNewKeyword={handleAddKeywords} />
|
|
83
94
|
{isVisible && <Toast message={toastState} setIsVisible={setIsVisible} />}
|
|
84
95
|
</S.Wrapper>
|
|
85
96
|
);
|
package/src/hooks/modals.tsx
CHANGED
|
@@ -13,14 +13,14 @@ const useModal = (initialState?: boolean, bodyBlock = true) => {
|
|
|
13
13
|
}
|
|
14
14
|
return () => {
|
|
15
15
|
// Solo eliminar si no hay otros modales abiertos
|
|
16
|
-
const modals = document.querySelectorAll('[data-testid="modal-wrapper"]');
|
|
16
|
+
const modals = document.querySelectorAll('[data-testid="modal-wrapper"], [data-testid="floating-panel"]');
|
|
17
17
|
if (modals.length <= 1) {
|
|
18
18
|
document.body.classList.remove("modal-open");
|
|
19
19
|
}
|
|
20
20
|
};
|
|
21
21
|
} else if (!bodyBlock || !isOpen) {
|
|
22
22
|
// Solo eliminar si no hay modales abiertos
|
|
23
|
-
const modals = document.querySelectorAll('[data-testid="modal-wrapper"]');
|
|
23
|
+
const modals = document.querySelectorAll('[data-testid="modal-wrapper"], [data-testid="floating-panel"]');
|
|
24
24
|
if (modals.length === 0) {
|
|
25
25
|
document.body.classList.remove("modal-open");
|
|
26
26
|
}
|
|
@@ -72,14 +72,14 @@ const useModals = <T extends string>(modalKeys: readonly T[], bodyBlock = true)
|
|
|
72
72
|
}
|
|
73
73
|
return () => {
|
|
74
74
|
// Solo eliminar si no hay otros modales abiertos
|
|
75
|
-
const modals = document.querySelectorAll('[data-testid="modal-wrapper"]');
|
|
75
|
+
const modals = document.querySelectorAll('[data-testid="modal-wrapper"], [data-testid="floating-panel"]');
|
|
76
76
|
if (modals.length <= 1) {
|
|
77
77
|
document.body.classList.remove("modal-open");
|
|
78
78
|
}
|
|
79
79
|
};
|
|
80
80
|
}
|
|
81
81
|
// Solo eliminar si no hay modales abiertos
|
|
82
|
-
const modals = document.querySelectorAll('[data-testid="modal-wrapper"]');
|
|
82
|
+
const modals = document.querySelectorAll('[data-testid="modal-wrapper"], [data-testid="floating-panel"]');
|
|
83
83
|
if (modals.length === 0) {
|
|
84
84
|
document.body.classList.remove("modal-open");
|
|
85
85
|
}
|