@focus-reactive/payload-plugin-seo 1.0.2 → 1.2.0
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/admin.css +172 -11
- package/dist/components/SeoButton/ScoreBadge.d.ts +9 -0
- package/dist/components/SeoButton/ScoreBadge.d.ts.map +1 -0
- package/dist/components/SeoButton/ScoreBadge.js +20 -0
- package/dist/components/SeoButton/ScoreBadge.js.map +1 -0
- package/dist/components/SeoButton/SeoButtonInner.d.ts +13 -0
- package/dist/components/SeoButton/SeoButtonInner.d.ts.map +1 -0
- package/dist/components/SeoButton/SeoButtonInner.js +68 -0
- package/dist/components/SeoButton/SeoButtonInner.js.map +1 -0
- package/dist/components/SeoButton/index.d.ts +3 -12
- package/dist/components/SeoButton/index.d.ts.map +1 -1
- package/dist/components/SeoButton/index.js +9 -73
- package/dist/components/SeoButton/index.js.map +1 -1
- package/dist/components/SeoButton/isExistingDocument.d.ts +2 -0
- package/dist/components/SeoButton/isExistingDocument.d.ts.map +1 -0
- package/dist/components/SeoButton/isExistingDocument.js +11 -0
- package/dist/components/SeoButton/isExistingDocument.js.map +1 -0
- package/dist/components/SeoDrawer/components/HeadingsSection/HeadingLevelTiles.d.ts +7 -0
- package/dist/components/SeoDrawer/components/HeadingsSection/HeadingLevelTiles.d.ts.map +1 -0
- package/dist/components/SeoDrawer/components/HeadingsSection/HeadingLevelTiles.js +29 -0
- package/dist/components/SeoDrawer/components/HeadingsSection/HeadingLevelTiles.js.map +1 -0
- package/dist/components/SeoDrawer/components/HeadingsSection/HeadingTree/Chevron.d.ts +4 -0
- package/dist/components/SeoDrawer/components/HeadingsSection/HeadingTree/Chevron.d.ts.map +1 -0
- package/dist/components/SeoDrawer/components/HeadingsSection/HeadingTree/Chevron.js +10 -0
- package/dist/components/SeoDrawer/components/HeadingsSection/HeadingTree/Chevron.js.map +1 -0
- package/dist/components/SeoDrawer/components/HeadingsSection/HeadingTree/HeadingTreeGroup.d.ts +10 -0
- package/dist/components/SeoDrawer/components/HeadingsSection/HeadingTree/HeadingTreeGroup.d.ts.map +1 -0
- package/dist/components/SeoDrawer/components/HeadingsSection/HeadingTree/HeadingTreeGroup.js +50 -0
- package/dist/components/SeoDrawer/components/HeadingsSection/HeadingTree/HeadingTreeGroup.js.map +1 -0
- package/dist/components/SeoDrawer/components/HeadingsSection/HeadingTree/HeadingTreeRow.d.ts +15 -0
- package/dist/components/SeoDrawer/components/HeadingsSection/HeadingTree/HeadingTreeRow.d.ts.map +1 -0
- package/dist/components/SeoDrawer/components/HeadingsSection/HeadingTree/HeadingTreeRow.js +38 -0
- package/dist/components/SeoDrawer/components/HeadingsSection/HeadingTree/HeadingTreeRow.js.map +1 -0
- package/dist/components/SeoDrawer/components/HeadingsSection/HeadingTree/headingTreeView.d.ts +3 -0
- package/dist/components/SeoDrawer/components/HeadingsSection/HeadingTree/headingTreeView.d.ts.map +1 -0
- package/dist/components/SeoDrawer/components/HeadingsSection/HeadingTree/headingTreeView.js +17 -0
- package/dist/components/SeoDrawer/components/HeadingsSection/HeadingTree/headingTreeView.js.map +1 -0
- package/dist/components/SeoDrawer/components/HeadingsSection/HeadingTree/index.d.ts +6 -0
- package/dist/components/SeoDrawer/components/HeadingsSection/HeadingTree/index.d.ts.map +1 -0
- package/dist/components/SeoDrawer/components/HeadingsSection/HeadingTree/index.js +41 -0
- package/dist/components/SeoDrawer/components/HeadingsSection/HeadingTree/index.js.map +1 -0
- package/dist/components/SeoDrawer/components/HeadingsSection/HeadingTree/useHeadingRails.d.ts +32 -0
- package/dist/components/SeoDrawer/components/HeadingsSection/HeadingTree/useHeadingRails.d.ts.map +1 -0
- package/dist/components/SeoDrawer/components/HeadingsSection/HeadingTree/useHeadingRails.js +84 -0
- package/dist/components/SeoDrawer/components/HeadingsSection/HeadingTree/useHeadingRails.js.map +1 -0
- package/dist/components/SeoDrawer/components/HeadingsSection/index.d.ts +7 -0
- package/dist/components/SeoDrawer/components/HeadingsSection/index.d.ts.map +1 -0
- package/dist/components/SeoDrawer/components/HeadingsSection/index.js +17 -0
- package/dist/components/SeoDrawer/components/HeadingsSection/index.js.map +1 -0
- package/dist/components/SeoDrawer/tabs/VitalsTab.d.ts.map +1 -1
- package/dist/components/SeoDrawer/tabs/VitalsTab.js +2 -0
- package/dist/components/SeoDrawer/tabs/VitalsTab.js.map +1 -1
- package/dist/engine/runAnalysis/services/derive-vitals/heading-tree.d.ts +7 -0
- package/dist/engine/runAnalysis/services/derive-vitals/heading-tree.d.ts.map +1 -0
- package/dist/engine/runAnalysis/services/derive-vitals/heading-tree.js +41 -0
- package/dist/engine/runAnalysis/services/derive-vitals/heading-tree.js.map +1 -0
- package/dist/engine/runAnalysis/services/derive-vitals/headings.d.ts +8 -0
- package/dist/engine/runAnalysis/services/derive-vitals/headings.d.ts.map +1 -0
- package/dist/engine/runAnalysis/services/derive-vitals/headings.js +50 -0
- package/dist/engine/runAnalysis/services/derive-vitals/headings.js.map +1 -0
- package/dist/engine/runAnalysis/services/derive-vitals/index.d.ts.map +1 -1
- package/dist/engine/runAnalysis/services/derive-vitals/index.js +4 -1
- package/dist/engine/runAnalysis/services/derive-vitals/index.js.map +1 -1
- package/dist/engine/types/analysis.d.ts +17 -0
- package/dist/engine/types/analysis.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Button, useModal } from "@payloadcms/ui";
|
|
4
|
+
import { Gauge } from "lucide-react";
|
|
5
|
+
import { useCallback, useState } from "react";
|
|
6
|
+
import { ScoreBadge } from "./ScoreBadge";
|
|
7
|
+
import { SeoDrawer } from "../SeoDrawer";
|
|
8
|
+
import { isKeyphrasePending } from "../SeoDrawer/keyphrasePending";
|
|
9
|
+
import { useAnalysis } from "../SeoDrawer/useAnalysis";
|
|
10
|
+
import { useLiveDocument } from "../SeoDrawer/useLiveDocument";
|
|
11
|
+
const DRAWER_SLUG = "seo-analytics-drawer";
|
|
12
|
+
function SeoButtonInner({ collectionSlug, fields, site, supportedLocales }) {
|
|
13
|
+
const { openModal } = useModal();
|
|
14
|
+
const [keyphrase, setKeyphrase] = useState("");
|
|
15
|
+
const { signature, getInput, invalidateMedia } = useLiveDocument({
|
|
16
|
+
collectionSlug,
|
|
17
|
+
fields,
|
|
18
|
+
site: { name: site.name, baseUrl: site.baseUrl },
|
|
19
|
+
keyphrase
|
|
20
|
+
});
|
|
21
|
+
const { result, analyzing, analyzedKeyphrase, analyzeNow } = useAnalysis({
|
|
22
|
+
getInput,
|
|
23
|
+
signature,
|
|
24
|
+
supportedLocales
|
|
25
|
+
});
|
|
26
|
+
const keyphrasePending = isKeyphrasePending(keyphrase, analyzedKeyphrase);
|
|
27
|
+
const overall = result?.overall ?? null;
|
|
28
|
+
const open = useCallback(() => {
|
|
29
|
+
invalidateMedia();
|
|
30
|
+
analyzeNow();
|
|
31
|
+
openModal(DRAWER_SLUG);
|
|
32
|
+
}, [analyzeNow, invalidateMedia, openModal]);
|
|
33
|
+
return /* @__PURE__ */ jsxs("span", { className: "relative inline-flex", children: [
|
|
34
|
+
/* @__PURE__ */ jsx(
|
|
35
|
+
Button,
|
|
36
|
+
{
|
|
37
|
+
"aria-label": "SEO Analytics",
|
|
38
|
+
buttonStyle: "none",
|
|
39
|
+
className: "seo-doc-btn m-0 w-[calc(var(--base)*1.6)] h-[calc(var(--base)*1.6)] inline-flex items-center justify-center border border-[var(--theme-elevation-100)] rounded-rs bg-transparent text-neutral-800 transition-[border-color,background-color] duration-100 hover:border-neutral-300 hover:bg-neutral-100",
|
|
40
|
+
extraButtonProps: { title: void 0 },
|
|
41
|
+
icon: /* @__PURE__ */ jsx(Gauge, {}),
|
|
42
|
+
iconStyle: "without-border",
|
|
43
|
+
margin: false,
|
|
44
|
+
onClick: open,
|
|
45
|
+
size: "small",
|
|
46
|
+
tooltip: "SEO Analytics"
|
|
47
|
+
}
|
|
48
|
+
),
|
|
49
|
+
overall && /* @__PURE__ */ jsx(ScoreBadge, { score: overall.seoScore, status: overall.status }),
|
|
50
|
+
/* @__PURE__ */ jsx(
|
|
51
|
+
SeoDrawer,
|
|
52
|
+
{
|
|
53
|
+
analyzeNow,
|
|
54
|
+
analyzing,
|
|
55
|
+
drawerSlug: DRAWER_SLUG,
|
|
56
|
+
keyphrase,
|
|
57
|
+
keyphrasePending,
|
|
58
|
+
result,
|
|
59
|
+
setKeyphrase,
|
|
60
|
+
site
|
|
61
|
+
}
|
|
62
|
+
)
|
|
63
|
+
] });
|
|
64
|
+
}
|
|
65
|
+
export {
|
|
66
|
+
SeoButtonInner
|
|
67
|
+
};
|
|
68
|
+
//# sourceMappingURL=SeoButtonInner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/SeoButton/SeoButtonInner.tsx"],"sourcesContent":["\"use client\";\n\nimport { Button, useModal } from \"@payloadcms/ui\";\nimport { Gauge } from \"lucide-react\";\nimport { useCallback, useState } from \"react\";\nimport { ScoreBadge } from \"./ScoreBadge\";\nimport { SeoDrawer } from \"../SeoDrawer\";\nimport { isKeyphrasePending } from \"../SeoDrawer/keyphrasePending\";\nimport { useAnalysis } from \"../SeoDrawer/useAnalysis\";\nimport { useLiveDocument } from \"../SeoDrawer/useLiveDocument\";\n\nexport interface SeoButtonProps {\n collectionSlug: string;\n fields: Record<string, string>;\n extractContentPath: string | null;\n site: { name: string; baseUrl: string; faviconUrl: string };\n supportedLocales: string[];\n}\n\nconst DRAWER_SLUG = \"seo-analytics-drawer\";\n\nexport function SeoButtonInner({ collectionSlug, fields, site, supportedLocales }: SeoButtonProps) {\n const { openModal } = useModal();\n const [keyphrase, setKeyphrase] = useState(\"\");\n\n const { signature, getInput, invalidateMedia } = useLiveDocument({\n collectionSlug,\n fields,\n site: { name: site.name, baseUrl: site.baseUrl },\n keyphrase,\n });\n const { result, analyzing, analyzedKeyphrase, analyzeNow } = useAnalysis({\n getInput,\n signature,\n supportedLocales,\n });\n\n const keyphrasePending = isKeyphrasePending(keyphrase, analyzedKeyphrase);\n const overall = result?.overall ?? null;\n\n const open = useCallback(() => {\n invalidateMedia();\n analyzeNow();\n openModal(DRAWER_SLUG);\n }, [analyzeNow, invalidateMedia, openModal]);\n\n return (\n <span className=\"relative inline-flex\">\n <Button\n aria-label=\"SEO Analytics\"\n buttonStyle=\"none\"\n className=\"seo-doc-btn m-0 w-[calc(var(--base)*1.6)] h-[calc(var(--base)*1.6)] inline-flex items-center justify-center border border-[var(--theme-elevation-100)] rounded-rs bg-transparent text-neutral-800 transition-[border-color,background-color] duration-100 hover:border-neutral-300 hover:bg-neutral-100\"\n extraButtonProps={{ title: undefined }}\n icon={<Gauge />}\n iconStyle=\"without-border\"\n margin={false}\n onClick={open}\n size=\"small\"\n tooltip=\"SEO Analytics\"\n />\n {overall && <ScoreBadge score={overall.seoScore} status={overall.status} />}\n\n <SeoDrawer\n analyzeNow={analyzeNow}\n analyzing={analyzing}\n drawerSlug={DRAWER_SLUG}\n keyphrase={keyphrase}\n keyphrasePending={keyphrasePending}\n result={result}\n setKeyphrase={setKeyphrase}\n site={site}\n />\n </span>\n );\n}\n"],"mappings":";AA+CI,SAMU,KANV;AA7CJ,SAAS,QAAQ,gBAAgB;AACjC,SAAS,aAAa;AACtB,SAAS,aAAa,gBAAgB;AACtC,SAAS,kBAAkB;AAC3B,SAAS,iBAAiB;AAC1B,SAAS,0BAA0B;AACnC,SAAS,mBAAmB;AAC5B,SAAS,uBAAuB;AAUhC,MAAM,cAAc;AAEb,SAAS,eAAe,EAAE,gBAAgB,QAAQ,MAAM,iBAAiB,GAAmB;AACjG,QAAM,EAAE,UAAU,IAAI,SAAS;AAC/B,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,EAAE;AAE7C,QAAM,EAAE,WAAW,UAAU,gBAAgB,IAAI,gBAAgB;AAAA,IAC/D;AAAA,IACA;AAAA,IACA,MAAM,EAAE,MAAM,KAAK,MAAM,SAAS,KAAK,QAAQ;AAAA,IAC/C;AAAA,EACF,CAAC;AACD,QAAM,EAAE,QAAQ,WAAW,mBAAmB,WAAW,IAAI,YAAY;AAAA,IACvE;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAM,mBAAmB,mBAAmB,WAAW,iBAAiB;AACxE,QAAM,UAAU,QAAQ,WAAW;AAEnC,QAAM,OAAO,YAAY,MAAM;AAC7B,oBAAgB;AAChB,eAAW;AACX,cAAU,WAAW;AAAA,EACvB,GAAG,CAAC,YAAY,iBAAiB,SAAS,CAAC;AAE3C,SACE,qBAAC,UAAK,WAAU,wBACd;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,cAAW;AAAA,QACX,aAAY;AAAA,QACZ,WAAU;AAAA,QACV,kBAAkB,EAAE,OAAO,OAAU;AAAA,QACrC,MAAM,oBAAC,SAAM;AAAA,QACb,WAAU;AAAA,QACV,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,MAAK;AAAA,QACL,SAAQ;AAAA;AAAA,IACV;AAAA,IACC,WAAW,oBAAC,cAAW,OAAO,QAAQ,UAAU,QAAQ,QAAQ,QAAQ;AAAA,IAEzE;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA,YAAY;AAAA,QACZ;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA;AAAA,IACF;AAAA,KACF;AAEJ;","names":[]}
|
|
@@ -1,14 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
extractContentPath: string | null;
|
|
5
|
-
site: {
|
|
6
|
-
name: string;
|
|
7
|
-
baseUrl: string;
|
|
8
|
-
faviconUrl: string;
|
|
9
|
-
};
|
|
10
|
-
supportedLocales: string[];
|
|
11
|
-
}
|
|
12
|
-
export declare function SeoButton({ collectionSlug, fields, site, supportedLocales }: SeoButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
1
|
+
import type { SeoButtonProps } from "./SeoButtonInner";
|
|
2
|
+
export type { SeoButtonProps };
|
|
3
|
+
export declare function SeoButton(props: SeoButtonProps): import("react/jsx-runtime").JSX.Element | null;
|
|
13
4
|
export default SeoButton;
|
|
14
5
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/SeoButton/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/SeoButton/index.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvD,YAAY,EAAE,cAAc,EAAE,CAAC;AAE/B,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,kDAM9C;AAED,eAAe,SAAS,CAAC"}
|
|
@@ -1,77 +1,13 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const DRAWER_SLUG = "seo-analytics-drawer";
|
|
12
|
-
const dotVariants = cva("absolute -top-[2px] -right-[2px] w-[8px] h-[8px] rounded-full border-[1.5px] border-[var(--theme-bg)] pointer-events-none", {
|
|
13
|
-
variants: {
|
|
14
|
-
status: {
|
|
15
|
-
good: "bg-seo-good",
|
|
16
|
-
warn: "bg-seo-warn",
|
|
17
|
-
bad: "bg-seo-bad"
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
});
|
|
21
|
-
function SeoButton({ collectionSlug, fields, site, supportedLocales }) {
|
|
22
|
-
const { openModal } = useModal();
|
|
23
|
-
const [keyphrase, setKeyphrase] = useState("");
|
|
24
|
-
const [activated, setActivated] = useState(false);
|
|
25
|
-
const { signature, getInput, invalidateMedia } = useLiveDocument({
|
|
26
|
-
collectionSlug,
|
|
27
|
-
fields,
|
|
28
|
-
site: { name: site.name, baseUrl: site.baseUrl },
|
|
29
|
-
keyphrase,
|
|
30
|
-
enabled: activated
|
|
31
|
-
});
|
|
32
|
-
const { result, analyzing, analyzedKeyphrase, analyzeNow } = useAnalysis({ getInput, signature, supportedLocales, enabled: activated });
|
|
33
|
-
const keyphrasePending = isKeyphrasePending(keyphrase, analyzedKeyphrase);
|
|
34
|
-
const status = result?.overall.status ?? null;
|
|
35
|
-
const open = useCallback(() => {
|
|
36
|
-
invalidateMedia();
|
|
37
|
-
if (activated) {
|
|
38
|
-
analyzeNow();
|
|
39
|
-
} else {
|
|
40
|
-
setActivated(true);
|
|
41
|
-
}
|
|
42
|
-
openModal(DRAWER_SLUG);
|
|
43
|
-
}, [activated, analyzeNow, invalidateMedia, openModal]);
|
|
44
|
-
return /* @__PURE__ */ jsxs("span", { className: "relative inline-flex", children: [
|
|
45
|
-
/* @__PURE__ */ jsx(
|
|
46
|
-
Button,
|
|
47
|
-
{
|
|
48
|
-
"aria-label": "SEO Analytics",
|
|
49
|
-
buttonStyle: "none",
|
|
50
|
-
className: "seo-doc-btn m-0 w-[calc(var(--base)*1.6)] h-[calc(var(--base)*1.6)] inline-flex items-center justify-center border border-[var(--theme-elevation-100)] rounded-rs bg-transparent text-neutral-800 transition-[border-color,background-color] duration-100 hover:border-neutral-300 hover:bg-neutral-100",
|
|
51
|
-
extraButtonProps: { title: void 0 },
|
|
52
|
-
icon: /* @__PURE__ */ jsx(Gauge, {}),
|
|
53
|
-
iconStyle: "without-border",
|
|
54
|
-
margin: false,
|
|
55
|
-
onClick: open,
|
|
56
|
-
size: "small",
|
|
57
|
-
tooltip: "SEO Analytics"
|
|
58
|
-
}
|
|
59
|
-
),
|
|
60
|
-
status ? /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: dotVariants({ status }) }) : null,
|
|
61
|
-
/* @__PURE__ */ jsx(
|
|
62
|
-
SeoDrawer,
|
|
63
|
-
{
|
|
64
|
-
analyzeNow,
|
|
65
|
-
analyzing,
|
|
66
|
-
drawerSlug: DRAWER_SLUG,
|
|
67
|
-
keyphrase,
|
|
68
|
-
keyphrasePending,
|
|
69
|
-
result,
|
|
70
|
-
setKeyphrase,
|
|
71
|
-
site
|
|
72
|
-
}
|
|
73
|
-
)
|
|
74
|
-
] });
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useDocumentInfo } from "@payloadcms/ui";
|
|
4
|
+
import { isExistingDocument } from "./isExistingDocument";
|
|
5
|
+
import { SeoButtonInner } from "./SeoButtonInner";
|
|
6
|
+
function SeoButton(props) {
|
|
7
|
+
const { id } = useDocumentInfo();
|
|
8
|
+
if (!isExistingDocument(id))
|
|
9
|
+
return null;
|
|
10
|
+
return /* @__PURE__ */ jsx(SeoButtonInner, { ...props });
|
|
75
11
|
}
|
|
76
12
|
var SeoButton_default = SeoButton;
|
|
77
13
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/SeoButton/index.tsx"],"sourcesContent":["\"use client\";\nimport {
|
|
1
|
+
{"version":3,"sources":["../../../src/components/SeoButton/index.tsx"],"sourcesContent":["\"use client\";\n\nimport { useDocumentInfo } from \"@payloadcms/ui\";\nimport { isExistingDocument } from \"./isExistingDocument\";\nimport { SeoButtonInner } from \"./SeoButtonInner\";\nimport type { SeoButtonProps } from \"./SeoButtonInner\";\n\nexport type { SeoButtonProps };\n\nexport function SeoButton(props: SeoButtonProps) {\n const { id } = useDocumentInfo();\n\n if (!isExistingDocument(id)) return null;\n\n return <SeoButtonInner {...props} />;\n}\n\nexport default SeoButton;\n"],"mappings":";AAcS;AAZT,SAAS,uBAAuB;AAChC,SAAS,0BAA0B;AACnC,SAAS,sBAAsB;AAKxB,SAAS,UAAU,OAAuB;AAC/C,QAAM,EAAE,GAAG,IAAI,gBAAgB;AAE/B,MAAI,CAAC,mBAAmB,EAAE;AAAG,WAAO;AAEpC,SAAO,oBAAC,kBAAgB,GAAG,OAAO;AACpC;AAEA,IAAO,oBAAQ;","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"isExistingDocument.d.ts","sourceRoot":"","sources":["../../../src/components/SeoButton/isExistingDocument.ts"],"names":[],"mappings":"AAAA,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAKlF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/SeoButton/isExistingDocument.ts"],"sourcesContent":["export function isExistingDocument(id: string | number | null | undefined): boolean {\n if (id === null || id === undefined) return false;\n if (typeof id === \"string\") return id.trim().length > 0;\n\n return true;\n}\n"],"mappings":"AAAO,SAAS,mBAAmB,IAAiD;AAClF,MAAI,OAAO,QAAQ,OAAO;AAAW,WAAO;AAC5C,MAAI,OAAO,OAAO;AAAU,WAAO,GAAG,KAAK,EAAE,SAAS;AAEtD,SAAO;AACT;","names":[]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { HeadingLevelCount } from "../../../../engine/types/analysis";
|
|
2
|
+
interface HeadingLevelTilesProps {
|
|
3
|
+
levels: HeadingLevelCount[];
|
|
4
|
+
}
|
|
5
|
+
export declare function HeadingLevelTiles({ levels }: HeadingLevelTilesProps): import("react/jsx-runtime").JSX.Element;
|
|
6
|
+
export {};
|
|
7
|
+
//# sourceMappingURL=HeadingLevelTiles.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HeadingLevelTiles.d.ts","sourceRoot":"","sources":["../../../../../src/components/SeoDrawer/components/HeadingsSection/HeadingLevelTiles.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AAG3E,UAAU,sBAAsB;IAC9B,MAAM,EAAE,iBAAiB,EAAE,CAAC;CAC7B;AAED,wBAAgB,iBAAiB,CAAC,EAAE,MAAM,EAAE,EAAE,sBAAsB,2CAqBnE"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { cn } from "../../../../utils/style";
|
|
4
|
+
function HeadingLevelTiles({ levels }) {
|
|
5
|
+
return /* @__PURE__ */ jsx("div", { className: "grid grid-cols-6 gap-[6px] px-[15px] pt-[8px] pb-[12px]", children: levels.map(({ level, count }) => {
|
|
6
|
+
const zero = count === 0;
|
|
7
|
+
return /* @__PURE__ */ jsxs(
|
|
8
|
+
"div",
|
|
9
|
+
{
|
|
10
|
+
className: cn(
|
|
11
|
+
"flex items-baseline justify-center gap-[5px] rounded-rs border px-[2px] py-[7px]",
|
|
12
|
+
zero ? "border-dashed border-neutral-300 bg-neutral-50" : "border-neutral-200 bg-neutral-0"
|
|
13
|
+
),
|
|
14
|
+
children: [
|
|
15
|
+
/* @__PURE__ */ jsxs("span", { className: cn("font-mono text-[12px] font-semibold", zero ? "text-neutral-400" : "text-neutral-500"), children: [
|
|
16
|
+
"H",
|
|
17
|
+
level
|
|
18
|
+
] }),
|
|
19
|
+
/* @__PURE__ */ jsx("span", { className: cn("font-mono text-[12px] font-bold", zero ? "text-neutral-300" : "text-neutral-1000"), children: count })
|
|
20
|
+
]
|
|
21
|
+
},
|
|
22
|
+
level
|
|
23
|
+
);
|
|
24
|
+
}) });
|
|
25
|
+
}
|
|
26
|
+
export {
|
|
27
|
+
HeadingLevelTiles
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=HeadingLevelTiles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../src/components/SeoDrawer/components/HeadingsSection/HeadingLevelTiles.tsx"],"sourcesContent":["\"use client\";\n\nimport type { HeadingLevelCount } from \"../../../../engine/types/analysis\";\nimport { cn } from \"../../../../utils/style\";\n\ninterface HeadingLevelTilesProps {\n levels: HeadingLevelCount[];\n}\n\nexport function HeadingLevelTiles({ levels }: HeadingLevelTilesProps) {\n return (\n <div className=\"grid grid-cols-6 gap-[6px] px-[15px] pt-[8px] pb-[12px]\">\n {levels.map(({ level, count }) => {\n const zero = count === 0;\n\n return (\n <div\n key={level}\n className={cn(\n \"flex items-baseline justify-center gap-[5px] rounded-rs border px-[2px] py-[7px]\",\n zero ? \"border-dashed border-neutral-300 bg-neutral-50\" : \"border-neutral-200 bg-neutral-0\"\n )}\n >\n <span className={cn(\"font-mono text-[12px] font-semibold\", zero ? \"text-neutral-400\" : \"text-neutral-500\")}>H{level}</span>\n <span className={cn(\"font-mono text-[12px] font-bold\", zero ? \"text-neutral-300\" : \"text-neutral-1000\")}>{count}</span>\n </div>\n );\n })}\n </div>\n );\n}\n"],"mappings":";AAuBY,SACA,KADA;AApBZ,SAAS,UAAU;AAMZ,SAAS,kBAAkB,EAAE,OAAO,GAA2B;AACpE,SACE,oBAAC,SAAI,WAAU,2DACZ,iBAAO,IAAI,CAAC,EAAE,OAAO,MAAM,MAAM;AAChC,UAAM,OAAO,UAAU;AAEvB,WACE;AAAA,MAAC;AAAA;AAAA,QAEC,WAAW;AAAA,UACT;AAAA,UACA,OAAO,mDAAmD;AAAA,QAC5D;AAAA,QAEA;AAAA,+BAAC,UAAK,WAAW,GAAG,uCAAuC,OAAO,qBAAqB,kBAAkB,GAAG;AAAA;AAAA,YAAE;AAAA,aAAM;AAAA,UACpH,oBAAC,UAAK,WAAW,GAAG,mCAAmC,OAAO,qBAAqB,mBAAmB,GAAI,iBAAM;AAAA;AAAA;AAAA,MAP3G;AAAA,IAQP;AAAA,EAEJ,CAAC,GACH;AAEJ;","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Chevron.d.ts","sourceRoot":"","sources":["../../../../../../src/components/SeoDrawer/components/HeadingsSection/HeadingTree/Chevron.tsx"],"names":[],"mappings":"AAGA,wBAAgB,OAAO,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,2CAElD"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { ChevronDown } from "lucide-react";
|
|
3
|
+
import { cn } from "../../../../../utils/style";
|
|
4
|
+
function Chevron({ open }) {
|
|
5
|
+
return /* @__PURE__ */ jsx(ChevronDown, { size: 13, strokeWidth: 2.2, "aria-hidden": "true", className: cn("flex-none text-neutral-500 transition-transform duration-150", !open && "-rotate-90") });
|
|
6
|
+
}
|
|
7
|
+
export {
|
|
8
|
+
Chevron
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=Chevron.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../src/components/SeoDrawer/components/HeadingsSection/HeadingTree/Chevron.tsx"],"sourcesContent":["import { ChevronDown } from \"lucide-react\";\nimport { cn } from \"../../../../../utils/style\";\n\nexport function Chevron({ open }: { open: boolean }) {\n return <ChevronDown size={13} strokeWidth={2.2} aria-hidden=\"true\" className={cn(\"flex-none text-neutral-500 transition-transform duration-150\", !open && \"-rotate-90\")} />;\n}\n"],"mappings":"AAIS;AAJT,SAAS,mBAAmB;AAC5B,SAAS,UAAU;AAEZ,SAAS,QAAQ,EAAE,KAAK,GAAsB;AACnD,SAAO,oBAAC,eAAY,MAAM,IAAI,aAAa,KAAK,eAAY,QAAO,WAAW,GAAG,gEAAgE,CAAC,QAAQ,YAAY,GAAG;AAC3K;","names":[]}
|
package/dist/components/SeoDrawer/components/HeadingsSection/HeadingTree/HeadingTreeGroup.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { HeadingNode } from "../../../../../engine/types/analysis";
|
|
2
|
+
interface HeadingTreeGroupProps {
|
|
3
|
+
nodes: HeadingNode[];
|
|
4
|
+
depth: number;
|
|
5
|
+
collapsed: ReadonlySet<string>;
|
|
6
|
+
onToggle: (id: string) => void;
|
|
7
|
+
}
|
|
8
|
+
export declare function HeadingTreeGroup({ nodes, depth, collapsed, onToggle }: HeadingTreeGroupProps): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=HeadingTreeGroup.d.ts.map
|
package/dist/components/SeoDrawer/components/HeadingsSection/HeadingTree/HeadingTreeGroup.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HeadingTreeGroup.d.ts","sourceRoot":"","sources":["../../../../../../src/components/SeoDrawer/components/HeadingsSection/HeadingTree/HeadingTreeGroup.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAC;AAgExE,UAAU,qBAAqB;IAC7B,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC/B,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CAChC;AAED,wBAAgB,gBAAgB,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,qBAAqB,2CAQ5F"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { HeadingTreeRow } from "./HeadingTreeRow";
|
|
4
|
+
import { useHeadingRails } from "./useHeadingRails";
|
|
5
|
+
function HeadingTreeNode({ node, depth, globalFirst, collapsed, onToggle, onBadgeMount }) {
|
|
6
|
+
const hasKids = node.children.length > 0;
|
|
7
|
+
const isOpen = hasKids && !collapsed.has(node.id);
|
|
8
|
+
const { containerRef, setBadgeRef, registerChildBadge, rails } = useHeadingRails({
|
|
9
|
+
node,
|
|
10
|
+
isOpen,
|
|
11
|
+
collapsed,
|
|
12
|
+
onBadgeMount
|
|
13
|
+
});
|
|
14
|
+
return /* @__PURE__ */ jsxs("div", { ref: containerRef, className: "relative", children: [
|
|
15
|
+
rails ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
16
|
+
/* @__PURE__ */ jsx(
|
|
17
|
+
"span",
|
|
18
|
+
{
|
|
19
|
+
className: "absolute w-[1.1px] bg-neutral-150",
|
|
20
|
+
style: {
|
|
21
|
+
left: rails.vertical.left,
|
|
22
|
+
top: rails.vertical.top,
|
|
23
|
+
height: rails.vertical.height
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
),
|
|
27
|
+
rails.elbows.map((elbow) => /* @__PURE__ */ jsx(
|
|
28
|
+
"span",
|
|
29
|
+
{
|
|
30
|
+
className: "absolute h-[1.1px] bg-neutral-150",
|
|
31
|
+
style: {
|
|
32
|
+
left: elbow.left,
|
|
33
|
+
top: elbow.top,
|
|
34
|
+
width: elbow.width
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
elbow.id
|
|
38
|
+
))
|
|
39
|
+
] }) : null,
|
|
40
|
+
/* @__PURE__ */ jsx(HeadingTreeRow, { node, depth, hasKids, isOpen, globalFirst, onToggle, badgeRef: setBadgeRef }),
|
|
41
|
+
isOpen ? /* @__PURE__ */ jsx("div", { children: node.children.map((child) => /* @__PURE__ */ jsx(HeadingTreeNode, { node: child, depth: depth + 1, globalFirst: false, collapsed, onToggle, onBadgeMount: registerChildBadge(child.id) }, child.id)) }) : null
|
|
42
|
+
] });
|
|
43
|
+
}
|
|
44
|
+
function HeadingTreeGroup({ nodes, depth, collapsed, onToggle }) {
|
|
45
|
+
return /* @__PURE__ */ jsx(Fragment, { children: nodes.map((node, i) => /* @__PURE__ */ jsx(HeadingTreeNode, { node, depth, globalFirst: depth === 0 && i === 0, collapsed, onToggle }, node.id)) });
|
|
46
|
+
}
|
|
47
|
+
export {
|
|
48
|
+
HeadingTreeGroup
|
|
49
|
+
};
|
|
50
|
+
//# sourceMappingURL=HeadingTreeGroup.js.map
|
package/dist/components/SeoDrawer/components/HeadingsSection/HeadingTree/HeadingTreeGroup.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../src/components/SeoDrawer/components/HeadingsSection/HeadingTree/HeadingTreeGroup.tsx"],"sourcesContent":["\"use client\";\n\nimport type { HeadingNode } from \"../../../../../engine/types/analysis\";\nimport { HeadingTreeRow } from \"./HeadingTreeRow\";\nimport { useHeadingRails } from \"./useHeadingRails\";\n\ninterface HeadingTreeNodeProps {\n node: HeadingNode;\n depth: number;\n globalFirst: boolean;\n collapsed: ReadonlySet<string>;\n onToggle: (id: string) => void;\n onBadgeMount?: (el: HTMLSpanElement | null) => void;\n}\n\nfunction HeadingTreeNode({ node, depth, globalFirst, collapsed, onToggle, onBadgeMount }: HeadingTreeNodeProps) {\n const hasKids = node.children.length > 0;\n const isOpen = hasKids && !collapsed.has(node.id);\n\n const { containerRef, setBadgeRef, registerChildBadge, rails } = useHeadingRails({\n node,\n isOpen,\n collapsed,\n onBadgeMount,\n });\n\n return (\n <div ref={containerRef} className=\"relative\">\n {rails ? (\n <>\n <span\n className=\"absolute w-[1.1px] bg-neutral-150\"\n style={{\n left: rails.vertical.left,\n top: rails.vertical.top,\n height: rails.vertical.height,\n }}\n />\n\n {rails.elbows.map((elbow) => (\n <span\n key={elbow.id}\n className=\"absolute h-[1.1px] bg-neutral-150\"\n style={{\n left: elbow.left,\n top: elbow.top,\n width: elbow.width,\n }}\n />\n ))}\n </>\n ) : null}\n\n <HeadingTreeRow node={node} depth={depth} hasKids={hasKids} isOpen={isOpen} globalFirst={globalFirst} onToggle={onToggle} badgeRef={setBadgeRef} />\n\n {isOpen ? (\n <div>\n {node.children.map((child) => (\n <HeadingTreeNode key={child.id} node={child} depth={depth + 1} globalFirst={false} collapsed={collapsed} onToggle={onToggle} onBadgeMount={registerChildBadge(child.id)} />\n ))}\n </div>\n ) : null}\n </div>\n );\n}\n\ninterface HeadingTreeGroupProps {\n nodes: HeadingNode[];\n depth: number;\n collapsed: ReadonlySet<string>;\n onToggle: (id: string) => void;\n}\n\nexport function HeadingTreeGroup({ nodes, depth, collapsed, onToggle }: HeadingTreeGroupProps) {\n return (\n <>\n {nodes.map((node, i) => (\n <HeadingTreeNode key={node.id} node={node} depth={depth} globalFirst={depth === 0 && i === 0} collapsed={collapsed} onToggle={onToggle} />\n ))}\n </>\n );\n}\n"],"mappings":";AA6BQ,mBACE,KADF;AA1BR,SAAS,sBAAsB;AAC/B,SAAS,uBAAuB;AAWhC,SAAS,gBAAgB,EAAE,MAAM,OAAO,aAAa,WAAW,UAAU,aAAa,GAAyB;AAC9G,QAAM,UAAU,KAAK,SAAS,SAAS;AACvC,QAAM,SAAS,WAAW,CAAC,UAAU,IAAI,KAAK,EAAE;AAEhD,QAAM,EAAE,cAAc,aAAa,oBAAoB,MAAM,IAAI,gBAAgB;AAAA,IAC/E;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,SACE,qBAAC,SAAI,KAAK,cAAc,WAAU,YAC/B;AAAA,YACC,iCACE;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,WAAU;AAAA,UACV,OAAO;AAAA,YACL,MAAM,MAAM,SAAS;AAAA,YACrB,KAAK,MAAM,SAAS;AAAA,YACpB,QAAQ,MAAM,SAAS;AAAA,UACzB;AAAA;AAAA,MACF;AAAA,MAEC,MAAM,OAAO,IAAI,CAAC,UACjB;AAAA,QAAC;AAAA;AAAA,UAEC,WAAU;AAAA,UACV,OAAO;AAAA,YACL,MAAM,MAAM;AAAA,YACZ,KAAK,MAAM;AAAA,YACX,OAAO,MAAM;AAAA,UACf;AAAA;AAAA,QANK,MAAM;AAAA,MAOb,CACD;AAAA,OACH,IACE;AAAA,IAEJ,oBAAC,kBAAe,MAAY,OAAc,SAAkB,QAAgB,aAA0B,UAAoB,UAAU,aAAa;AAAA,IAEhJ,SACC,oBAAC,SACE,eAAK,SAAS,IAAI,CAAC,UAClB,oBAAC,mBAA+B,MAAM,OAAO,OAAO,QAAQ,GAAG,aAAa,OAAO,WAAsB,UAAoB,cAAc,mBAAmB,MAAM,EAAE,KAAhJ,MAAM,EAA6I,CAC1K,GACH,IACE;AAAA,KACN;AAEJ;AASO,SAAS,iBAAiB,EAAE,OAAO,OAAO,WAAW,SAAS,GAA0B;AAC7F,SACE,gCACG,gBAAM,IAAI,CAAC,MAAM,MAChB,oBAAC,mBAA8B,MAAY,OAAc,aAAa,UAAU,KAAK,MAAM,GAAG,WAAsB,YAA9F,KAAK,EAA6G,CACzI,GACH;AAEJ;","names":[]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Ref } from "react";
|
|
2
|
+
import type { HeadingNode } from "../../../../../engine/types/analysis";
|
|
3
|
+
interface HeadingTreeRowProps {
|
|
4
|
+
node: HeadingNode;
|
|
5
|
+
depth: number;
|
|
6
|
+
hasKids: boolean;
|
|
7
|
+
isOpen: boolean;
|
|
8
|
+
globalFirst: boolean;
|
|
9
|
+
onToggle: (id: string) => void;
|
|
10
|
+
rowRef?: Ref<HTMLDivElement>;
|
|
11
|
+
badgeRef?: Ref<HTMLSpanElement>;
|
|
12
|
+
}
|
|
13
|
+
export declare function HeadingTreeRow({ node, depth, hasKids, isOpen, globalFirst, onToggle, rowRef, badgeRef }: HeadingTreeRowProps): import("react/jsx-runtime").JSX.Element;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=HeadingTreeRow.d.ts.map
|
package/dist/components/SeoDrawer/components/HeadingsSection/HeadingTree/HeadingTreeRow.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HeadingTreeRow.d.ts","sourceRoot":"","sources":["../../../../../../src/components/SeoDrawer/components/HeadingsSection/HeadingTree/HeadingTreeRow.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAC;AAIxE,UAAU,mBAAmB;IAC3B,IAAI,EAAE,WAAW,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,MAAM,CAAC,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;IAC7B,QAAQ,CAAC,EAAE,GAAG,CAAC,eAAe,CAAC,CAAC;CACjC;AAED,wBAAgB,cAAc,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,mBAAmB,2CAuC5H"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../../../../../utils/style";
|
|
3
|
+
import { Chevron } from "./Chevron";
|
|
4
|
+
function HeadingTreeRow({ node, depth, hasKids, isOpen, globalFirst, onToggle, rowRef, badgeRef }) {
|
|
5
|
+
return /* @__PURE__ */ jsxs(
|
|
6
|
+
"div",
|
|
7
|
+
{
|
|
8
|
+
ref: rowRef,
|
|
9
|
+
className: cn("relative flex items-center gap-[9px] h-[34px] box-border", hasKids && "cursor-pointer focus-visible:outline-2 focus-visible:outline-neutral-400 focus-visible:-outline-offset-2"),
|
|
10
|
+
style: { paddingLeft: depth * 20 },
|
|
11
|
+
role: hasKids ? "button" : void 0,
|
|
12
|
+
tabIndex: hasKids ? 0 : void 0,
|
|
13
|
+
"aria-expanded": hasKids ? isOpen : void 0,
|
|
14
|
+
onClick: hasKids ? () => onToggle(node.id) : void 0,
|
|
15
|
+
onKeyDown: hasKids ? (e) => {
|
|
16
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
17
|
+
e.preventDefault();
|
|
18
|
+
onToggle(node.id);
|
|
19
|
+
}
|
|
20
|
+
} : void 0,
|
|
21
|
+
title: hasKids ? isOpen ? "Collapse" : "Expand" : void 0,
|
|
22
|
+
children: [
|
|
23
|
+
/* @__PURE__ */ jsxs("span", { ref: badgeRef, className: "flex-none font-mono text-[9px] font-bold leading-[100%] text-neutral-1000 bg-neutral-150 rounded-rs px-[6px] py-[3px] min-w-[22px] text-center", children: [
|
|
24
|
+
"H",
|
|
25
|
+
node.level
|
|
26
|
+
] }),
|
|
27
|
+
/* @__PURE__ */ jsxs("div", { className: cn("flex-1 min-w-0 flex items-center gap-[9px] h-full", !globalFirst && "border-t border-neutral-150"), children: [
|
|
28
|
+
node.text ? /* @__PURE__ */ jsx("span", { className: "flex-1 min-w-0 truncate text-[12px] font-medium text-neutral-800", title: node.text, children: node.text }) : /* @__PURE__ */ jsx("span", { className: "flex-1 min-w-0 truncate text-[12px] font-medium italic text-neutral-400", children: "(empty heading)" }),
|
|
29
|
+
hasKids ? /* @__PURE__ */ jsx(Chevron, { open: isOpen }) : null
|
|
30
|
+
] })
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
export {
|
|
36
|
+
HeadingTreeRow
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=HeadingTreeRow.js.map
|
package/dist/components/SeoDrawer/components/HeadingsSection/HeadingTree/HeadingTreeRow.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../src/components/SeoDrawer/components/HeadingsSection/HeadingTree/HeadingTreeRow.tsx"],"sourcesContent":["import type { Ref } from \"react\";\nimport type { HeadingNode } from \"../../../../../engine/types/analysis\";\nimport { cn } from \"../../../../../utils/style\";\nimport { Chevron } from \"./Chevron\";\n\ninterface HeadingTreeRowProps {\n node: HeadingNode;\n depth: number;\n hasKids: boolean;\n isOpen: boolean;\n globalFirst: boolean;\n onToggle: (id: string) => void;\n rowRef?: Ref<HTMLDivElement>;\n badgeRef?: Ref<HTMLSpanElement>;\n}\n\nexport function HeadingTreeRow({ node, depth, hasKids, isOpen, globalFirst, onToggle, rowRef, badgeRef }: HeadingTreeRowProps) {\n return (\n <div\n ref={rowRef}\n className={cn(\"relative flex items-center gap-[9px] h-[34px] box-border\", hasKids && \"cursor-pointer focus-visible:outline-2 focus-visible:outline-neutral-400 focus-visible:-outline-offset-2\")}\n style={{ paddingLeft: depth * 20 }}\n role={hasKids ? \"button\" : undefined}\n tabIndex={hasKids ? 0 : undefined}\n aria-expanded={hasKids ? isOpen : undefined}\n onClick={hasKids ? () => onToggle(node.id) : undefined}\n onKeyDown={\n hasKids\n ? (e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onToggle(node.id);\n }\n }\n : undefined\n }\n title={hasKids ? (isOpen ? \"Collapse\" : \"Expand\") : undefined}\n >\n <span ref={badgeRef} className=\"flex-none font-mono text-[9px] font-bold leading-[100%] text-neutral-1000 bg-neutral-150 rounded-rs px-[6px] py-[3px] min-w-[22px] text-center\">\n H{node.level}\n </span>\n\n <div className={cn(\"flex-1 min-w-0 flex items-center gap-[9px] h-full\", !globalFirst && \"border-t border-neutral-150\")}>\n {node.text ? (\n <span className=\"flex-1 min-w-0 truncate text-[12px] font-medium text-neutral-800\" title={node.text}>\n {node.text}\n </span>\n ) : (\n <span className=\"flex-1 min-w-0 truncate text-[12px] font-medium italic text-neutral-400\">(empty heading)</span>\n )}\n\n {hasKids ? <Chevron open={isOpen} /> : null}\n </div>\n </div>\n );\n}\n"],"mappings":"AAsCM,SAMI,KANJ;AApCN,SAAS,UAAU;AACnB,SAAS,eAAe;AAajB,SAAS,eAAe,EAAE,MAAM,OAAO,SAAS,QAAQ,aAAa,UAAU,QAAQ,SAAS,GAAwB;AAC7H,SACE;AAAA,IAAC;AAAA;AAAA,MACC,KAAK;AAAA,MACL,WAAW,GAAG,4DAA4D,WAAW,0GAA0G;AAAA,MAC/L,OAAO,EAAE,aAAa,QAAQ,GAAG;AAAA,MACjC,MAAM,UAAU,WAAW;AAAA,MAC3B,UAAU,UAAU,IAAI;AAAA,MACxB,iBAAe,UAAU,SAAS;AAAA,MAClC,SAAS,UAAU,MAAM,SAAS,KAAK,EAAE,IAAI;AAAA,MAC7C,WACE,UACI,CAAC,MAAM;AACL,YAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,KAAK;AACtC,YAAE,eAAe;AACjB,mBAAS,KAAK,EAAE;AAAA,QAClB;AAAA,MACF,IACA;AAAA,MAEN,OAAO,UAAW,SAAS,aAAa,WAAY;AAAA,MAEpD;AAAA,6BAAC,UAAK,KAAK,UAAU,WAAU,kJAAiJ;AAAA;AAAA,UAC5K,KAAK;AAAA,WACT;AAAA,QAEA,qBAAC,SAAI,WAAW,GAAG,qDAAqD,CAAC,eAAe,6BAA6B,GAClH;AAAA,eAAK,OACJ,oBAAC,UAAK,WAAU,oEAAmE,OAAO,KAAK,MAC5F,eAAK,MACR,IAEA,oBAAC,UAAK,WAAU,2EAA0E,6BAAe;AAAA,UAG1G,UAAU,oBAAC,WAAQ,MAAM,QAAQ,IAAK;AAAA,WACzC;AAAA;AAAA;AAAA,EACF;AAEJ;","names":[]}
|
package/dist/components/SeoDrawer/components/HeadingsSection/HeadingTree/headingTreeView.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"headingTreeView.d.ts","sourceRoot":"","sources":["../../../../../../src/components/SeoDrawer/components/HeadingsSection/HeadingTree/headingTreeView.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAC;AAExE,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,MAAM,EAAE,CAe/D"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
function collectParentIds(nodes) {
|
|
2
|
+
const ids = [];
|
|
3
|
+
const walk = (ns) => {
|
|
4
|
+
for (const n of ns) {
|
|
5
|
+
if (n.children.length > 0) {
|
|
6
|
+
ids.push(n.id);
|
|
7
|
+
walk(n.children);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
walk(nodes);
|
|
12
|
+
return ids;
|
|
13
|
+
}
|
|
14
|
+
export {
|
|
15
|
+
collectParentIds
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=headingTreeView.js.map
|
package/dist/components/SeoDrawer/components/HeadingsSection/HeadingTree/headingTreeView.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../src/components/SeoDrawer/components/HeadingsSection/HeadingTree/headingTreeView.ts"],"sourcesContent":["import type { HeadingNode } from \"../../../../../engine/types/analysis\";\n\nexport function collectParentIds(nodes: HeadingNode[]): string[] {\n const ids: string[] = [];\n\n const walk = (ns: HeadingNode[]) => {\n for (const n of ns) {\n if (n.children.length > 0) {\n ids.push(n.id);\n walk(n.children);\n }\n }\n };\n\n walk(nodes);\n\n return ids;\n}\n"],"mappings":"AAEO,SAAS,iBAAiB,OAAgC;AAC/D,QAAM,MAAgB,CAAC;AAEvB,QAAM,OAAO,CAAC,OAAsB;AAClC,eAAW,KAAK,IAAI;AAClB,UAAI,EAAE,SAAS,SAAS,GAAG;AACzB,YAAI,KAAK,EAAE,EAAE;AACb,aAAK,EAAE,QAAQ;AAAA,MACjB;AAAA,IACF;AAAA,EACF;AAEA,OAAK,KAAK;AAEV,SAAO;AACT;","names":[]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { HeadingNode } from "../../../../../engine/types/analysis";
|
|
2
|
+
export interface HeadingTreeProps {
|
|
3
|
+
tree: HeadingNode[];
|
|
4
|
+
}
|
|
5
|
+
export declare function HeadingTree({ tree }: HeadingTreeProps): import("react/jsx-runtime").JSX.Element;
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/components/SeoDrawer/components/HeadingsSection/HeadingTree/index.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAC;AAKxE,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,WAAW,EAAE,CAAC;CACrB;AAID,wBAAgB,WAAW,CAAC,EAAE,IAAI,EAAE,EAAE,gBAAgB,2CAwCrD"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useMemo, useState } from "react";
|
|
4
|
+
import { cn } from "../../../../../utils/style";
|
|
5
|
+
import { collectParentIds } from "./headingTreeView";
|
|
6
|
+
import { HeadingTreeGroup } from "./HeadingTreeGroup";
|
|
7
|
+
const SUB_LABEL = "text-[9.5px] font-semibold uppercase tracking-[0.05em] text-neutral-500";
|
|
8
|
+
function HeadingTree({ tree }) {
|
|
9
|
+
const parentIds = useMemo(() => collectParentIds(tree), [tree]);
|
|
10
|
+
const [collapsed, setCollapsed] = useState(() => /* @__PURE__ */ new Set());
|
|
11
|
+
const empty = tree.length === 0;
|
|
12
|
+
const allCollapsed = parentIds.length > 0 && parentIds.every((id) => collapsed.has(id));
|
|
13
|
+
const toggleAll = () => setCollapsed(allCollapsed ? /* @__PURE__ */ new Set() : new Set(parentIds));
|
|
14
|
+
const toggle = (id) => setCollapsed((prev) => {
|
|
15
|
+
const next = new Set(prev);
|
|
16
|
+
if (next.has(id))
|
|
17
|
+
next.delete(id);
|
|
18
|
+
else
|
|
19
|
+
next.add(id);
|
|
20
|
+
return next;
|
|
21
|
+
});
|
|
22
|
+
return /* @__PURE__ */ jsxs("div", { className: "px-[15px] pt-[11px] border-t border-neutral-150", children: [
|
|
23
|
+
/* @__PURE__ */ jsxs("div", { className: cn(SUB_LABEL, "flex items-center justify-between"), children: [
|
|
24
|
+
/* @__PURE__ */ jsx("span", { children: "Structure" }),
|
|
25
|
+
!empty && /* @__PURE__ */ jsx(
|
|
26
|
+
"button",
|
|
27
|
+
{
|
|
28
|
+
type: "button",
|
|
29
|
+
onClick: toggleAll,
|
|
30
|
+
className: "text-[11px] font-medium normal-case tracking-normal text-neutral-600 hover:text-neutral-1000 hover:underline underline-offset-2 bg-transparent border-0 p-0 cursor-pointer",
|
|
31
|
+
children: allCollapsed ? "Expand all" : "Collapse all"
|
|
32
|
+
}
|
|
33
|
+
)
|
|
34
|
+
] }),
|
|
35
|
+
empty ? /* @__PURE__ */ jsx("div", { className: "px-[15px] pt-[20px] pb-[24px] text-center text-[12px] text-neutral-500", children: "No headings found in this content." }) : /* @__PURE__ */ jsx("div", { className: "relative pt-[5px] pb-[7px]", children: /* @__PURE__ */ jsx(HeadingTreeGroup, { nodes: tree, depth: 0, collapsed, onToggle: toggle }) })
|
|
36
|
+
] });
|
|
37
|
+
}
|
|
38
|
+
export {
|
|
39
|
+
HeadingTree
|
|
40
|
+
};
|
|
41
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../src/components/SeoDrawer/components/HeadingsSection/HeadingTree/index.tsx"],"sourcesContent":["\"use client\";\n\nimport { useMemo, useState } from \"react\";\nimport type { HeadingNode } from \"../../../../../engine/types/analysis\";\nimport { cn } from \"../../../../../utils/style\";\nimport { collectParentIds } from \"./headingTreeView\";\nimport { HeadingTreeGroup } from \"./HeadingTreeGroup\";\n\nexport interface HeadingTreeProps {\n tree: HeadingNode[];\n}\n\nconst SUB_LABEL = \"text-[9.5px] font-semibold uppercase tracking-[0.05em] text-neutral-500\";\n\nexport function HeadingTree({ tree }: HeadingTreeProps) {\n const parentIds = useMemo(() => collectParentIds(tree), [tree]);\n const [collapsed, setCollapsed] = useState<Set<string>>(() => new Set());\n\n const empty = tree.length === 0;\n const allCollapsed = parentIds.length > 0 && parentIds.every((id) => collapsed.has(id));\n\n const toggleAll = () => setCollapsed(allCollapsed ? new Set() : new Set(parentIds));\n const toggle = (id: string) =>\n setCollapsed((prev) => {\n const next = new Set(prev);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n return next;\n });\n\n return (\n <div className=\"px-[15px] pt-[11px] border-t border-neutral-150\">\n <div className={cn(SUB_LABEL, \"flex items-center justify-between\")}>\n <span>Structure</span>\n\n {!empty && (\n <button\n type=\"button\"\n onClick={toggleAll}\n className=\"text-[11px] font-medium normal-case tracking-normal text-neutral-600 hover:text-neutral-1000 hover:underline underline-offset-2 bg-transparent border-0 p-0 cursor-pointer\"\n >\n {allCollapsed ? \"Expand all\" : \"Collapse all\"}\n </button>\n )}\n </div>\n {empty ? (\n <div className=\"px-[15px] pt-[20px] pb-[24px] text-center text-[12px] text-neutral-500\">No headings found in this content.</div>\n ) : (\n <div className=\"relative pt-[5px] pb-[7px]\">\n <HeadingTreeGroup nodes={tree} depth={0} collapsed={collapsed} onToggle={toggle} />\n </div>\n )}\n </div>\n );\n}\n"],"mappings":";AAgCM,SACE,KADF;AA9BN,SAAS,SAAS,gBAAgB;AAElC,SAAS,UAAU;AACnB,SAAS,wBAAwB;AACjC,SAAS,wBAAwB;AAMjC,MAAM,YAAY;AAEX,SAAS,YAAY,EAAE,KAAK,GAAqB;AACtD,QAAM,YAAY,QAAQ,MAAM,iBAAiB,IAAI,GAAG,CAAC,IAAI,CAAC;AAC9D,QAAM,CAAC,WAAW,YAAY,IAAI,SAAsB,MAAM,oBAAI,IAAI,CAAC;AAEvE,QAAM,QAAQ,KAAK,WAAW;AAC9B,QAAM,eAAe,UAAU,SAAS,KAAK,UAAU,MAAM,CAAC,OAAO,UAAU,IAAI,EAAE,CAAC;AAEtF,QAAM,YAAY,MAAM,aAAa,eAAe,oBAAI,IAAI,IAAI,IAAI,IAAI,SAAS,CAAC;AAClF,QAAM,SAAS,CAAC,OACd,aAAa,CAAC,SAAS;AACrB,UAAM,OAAO,IAAI,IAAI,IAAI;AACzB,QAAI,KAAK,IAAI,EAAE;AAAG,WAAK,OAAO,EAAE;AAAA;AAC3B,WAAK,IAAI,EAAE;AAChB,WAAO;AAAA,EACT,CAAC;AAEH,SACE,qBAAC,SAAI,WAAU,mDACb;AAAA,yBAAC,SAAI,WAAW,GAAG,WAAW,mCAAmC,GAC/D;AAAA,0BAAC,UAAK,uBAAS;AAAA,MAEd,CAAC,SACA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAS;AAAA,UACT,WAAU;AAAA,UAET,yBAAe,eAAe;AAAA;AAAA,MACjC;AAAA,OAEJ;AAAA,IACC,QACC,oBAAC,SAAI,WAAU,0EAAyE,gDAAkC,IAE1H,oBAAC,SAAI,WAAU,8BACb,8BAAC,oBAAiB,OAAO,MAAM,OAAO,GAAG,WAAsB,UAAU,QAAQ,GACnF;AAAA,KAEJ;AAEJ;","names":[]}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { RefObject } from "react";
|
|
2
|
+
import type { HeadingNode } from "../../../../../engine/types/analysis";
|
|
3
|
+
interface VerticalRail {
|
|
4
|
+
left: number;
|
|
5
|
+
top: number;
|
|
6
|
+
height: number;
|
|
7
|
+
}
|
|
8
|
+
interface Elbow {
|
|
9
|
+
id: string;
|
|
10
|
+
left: number;
|
|
11
|
+
top: number;
|
|
12
|
+
width: number;
|
|
13
|
+
}
|
|
14
|
+
export interface RailGeometry {
|
|
15
|
+
vertical: VerticalRail;
|
|
16
|
+
elbows: Elbow[];
|
|
17
|
+
}
|
|
18
|
+
interface UseHeadingRailsParams {
|
|
19
|
+
node: HeadingNode;
|
|
20
|
+
isOpen: boolean;
|
|
21
|
+
collapsed: ReadonlySet<string>;
|
|
22
|
+
onBadgeMount?: (el: HTMLSpanElement | null) => void;
|
|
23
|
+
}
|
|
24
|
+
interface UseHeadingRailsResult {
|
|
25
|
+
containerRef: RefObject<HTMLDivElement | null>;
|
|
26
|
+
setBadgeRef: (el: HTMLSpanElement | null) => void;
|
|
27
|
+
registerChildBadge: (childId: string) => (el: HTMLSpanElement | null) => void;
|
|
28
|
+
rails: RailGeometry | null;
|
|
29
|
+
}
|
|
30
|
+
export declare function useHeadingRails({ node, isOpen, collapsed, onBadgeMount }: UseHeadingRailsParams): UseHeadingRailsResult;
|
|
31
|
+
export {};
|
|
32
|
+
//# sourceMappingURL=useHeadingRails.d.ts.map
|
package/dist/components/SeoDrawer/components/HeadingsSection/HeadingTree/useHeadingRails.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useHeadingRails.d.ts","sourceRoot":"","sources":["../../../../../../src/components/SeoDrawer/components/HeadingsSection/HeadingTree/useHeadingRails.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAC;AAExE,UAAU,YAAY;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,KAAK;IACb,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,YAAY,CAAC;IACvB,MAAM,EAAE,KAAK,EAAE,CAAC;CACjB;AAED,UAAU,qBAAqB;IAC7B,IAAI,EAAE,WAAW,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC/B,YAAY,CAAC,EAAE,CAAC,EAAE,EAAE,eAAe,GAAG,IAAI,KAAK,IAAI,CAAC;CACrD;AAED,UAAU,qBAAqB;IAC7B,YAAY,EAAE,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAC/C,WAAW,EAAE,CAAC,EAAE,EAAE,eAAe,GAAG,IAAI,KAAK,IAAI,CAAC;IAClD,kBAAkB,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,CAAC,EAAE,EAAE,eAAe,GAAG,IAAI,KAAK,IAAI,CAAC;IAC9E,KAAK,EAAE,YAAY,GAAG,IAAI,CAAC;CAC5B;AAED,wBAAgB,eAAe,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,EAAE,qBAAqB,GAAG,qBAAqB,CA6FvH"}
|