@webiny/website-builder-nextjs 0.0.0-unstable.8b6c57b569 → 0.0.0-unstable.9f53ea597d

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.
@@ -0,0 +1,4 @@
1
+ import React from "react";
2
+ import { DocumentRenderer as BaseDocumentRenderer } from "@webiny/website-builder-react";
3
+ export type DocumentRendererProps = React.ComponentProps<typeof BaseDocumentRenderer>;
4
+ export declare const DocumentRenderer: ({ document, components, children }: DocumentRendererProps) => React.JSX.Element;
@@ -0,0 +1,16 @@
1
+ import react from "react";
2
+ import { DocumentRenderer } from "@webiny/website-builder-react";
3
+ import { Image } from "./editorComponents/Image.manifest.js";
4
+ const DocumentRenderer_DocumentRenderer = ({ document, components, children })=>{
5
+ const allComponents = [
6
+ Image,
7
+ ...components
8
+ ];
9
+ return /*#__PURE__*/ react.createElement(DocumentRenderer, {
10
+ document: document,
11
+ components: allComponents
12
+ }, children);
13
+ };
14
+ export { DocumentRenderer_DocumentRenderer as DocumentRenderer };
15
+
16
+ //# sourceMappingURL=DocumentRenderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DocumentRenderer.js","sources":["../src/DocumentRenderer.tsx"],"sourcesContent":["import React from \"react\";\nimport { DocumentRenderer as BaseDocumentRenderer } from \"@webiny/website-builder-react\";\nimport { Image } from \"~/editorComponents/Image.manifest.js\";\n\nexport type DocumentRendererProps = React.ComponentProps<typeof BaseDocumentRenderer>;\n\nexport const DocumentRenderer = ({ document, components, children }: DocumentRendererProps) => {\n const allComponents = [Image, ...components];\n return (\n <BaseDocumentRenderer document={document} components={allComponents}>\n {children}\n </BaseDocumentRenderer>\n );\n};\n"],"names":["DocumentRenderer","document","components","children","allComponents","Image","BaseDocumentRenderer"],"mappings":";;;AAMO,MAAMA,oCAAmB,CAAC,EAAEC,QAAQ,EAAEC,UAAU,EAAEC,QAAQ,EAAyB;IACtF,MAAMC,gBAAgB;QAACC;WAAUH;KAAW;IAC5C,OAAO,WAAP,GACI,oBAACI,kBAAoBA;QAAC,UAAUL;QAAU,YAAYG;OACjDD;AAGb"}
package/README.md CHANGED
@@ -1,3 +1,11 @@
1
- # Webiny Website Builder Next.js SDK
1
+ # @webiny/website-builder-nextjs
2
2
 
3
- A Next.js integration SDK for Webiny Website Builder.
3
+ > [!NOTE]
4
+ > This package is part of the [Webiny](https://www.webiny.com) monorepo.
5
+ > It’s **included in every Webiny project by default** and is not meant to be used as a standalone package.
6
+
7
+ 📘 **Documentation:** [https://www.webiny.com/docs](https://www.webiny.com/docs)
8
+
9
+ ---
10
+
11
+ _This README file is automatically generated during the publish process._
@@ -0,0 +1,10 @@
1
+ import React from "react";
2
+ import type { ComponentProps, Asset } from "@webiny/website-builder-react";
3
+ type ImageProps = ComponentProps<{
4
+ title: string;
5
+ altText: string;
6
+ highPriority: boolean;
7
+ image: Asset;
8
+ }>;
9
+ export declare const ImageComponent: (props: ImageProps) => React.JSX.Element;
10
+ export {};
@@ -0,0 +1,81 @@
1
+ import react from "react";
2
+ import next_image from "next/image";
3
+ import { getAssetUrl, getImageDimensions, getImageSrcSet, normalizeToAsset } from "@webiny/website-builder-react";
4
+ const ImageComponent = (props)=>{
5
+ const { title = "", altText, image, highPriority } = props.inputs;
6
+ const asset = normalizeToAsset(image);
7
+ if (!asset?.src) return /*#__PURE__*/ react.createElement(ImagePlaceholder, {
8
+ style: props.styles
9
+ });
10
+ const alt = altText || asset.image?.alt || "";
11
+ if (asset.src.endsWith(".svg")) return /*#__PURE__*/ react.createElement("object", {
12
+ style: {
13
+ maxWidth: "100%",
14
+ ...props.styles
15
+ },
16
+ title: title,
17
+ data: asset.src
18
+ });
19
+ const loader = ({ width })=>getAssetUrl(asset, {
20
+ width,
21
+ format: "auto"
22
+ });
23
+ const { width, height } = getImageDimensions(asset);
24
+ const style = {
25
+ maxWidth: "100%",
26
+ height: "auto",
27
+ ...props.styles
28
+ };
29
+ if (!width || !height) {
30
+ const { src, srcSet } = getImageSrcSet(asset, {
31
+ format: "auto",
32
+ cssWidth: props.styles?.width
33
+ });
34
+ return /*#__PURE__*/ react.createElement("img", {
35
+ src: src,
36
+ srcSet: srcSet,
37
+ sizes: "100vw",
38
+ alt: alt,
39
+ title: title || void 0,
40
+ loading: highPriority ? "eager" : "lazy",
41
+ style: style
42
+ });
43
+ }
44
+ return /*#__PURE__*/ react.createElement(next_image, {
45
+ src: asset.src,
46
+ loader: loader,
47
+ alt: alt,
48
+ title: title || void 0,
49
+ width: width,
50
+ height: height,
51
+ sizes: "100vw",
52
+ priority: highPriority,
53
+ style: style
54
+ });
55
+ };
56
+ const ImagePlaceholder = ({ style })=>/*#__PURE__*/ react.createElement("div", {
57
+ style: {
58
+ display: "flex",
59
+ height: "200px",
60
+ backgroundColor: "#f4f4f4",
61
+ justifyContent: "center",
62
+ alignItems: "center",
63
+ fill: "#ffffff",
64
+ ...style
65
+ }
66
+ }, /*#__PURE__*/ react.createElement("svg", {
67
+ style: {
68
+ width: "70px",
69
+ height: "70px",
70
+ filter: "drop-shadow(rgba(0, 0, 0, 0.16) 0px 1px 0px)"
71
+ },
72
+ xmlns: "http://www.w3.org/2000/svg",
73
+ height: "24px",
74
+ viewBox: "0 -960 960 960",
75
+ width: "24px"
76
+ }, /*#__PURE__*/ react.createElement("path", {
77
+ d: "M200-120q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h560q33 0 56.5 23.5T840-760v560q0 33-23.5 56.5T760-120H200Zm0-80h560v-560H200v560Zm40-80h480L570-480 450-320l-90-120-120 160Zm-40 80v-560 560Z"
78
+ })));
79
+ export { ImageComponent };
80
+
81
+ //# sourceMappingURL=Image.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"editorComponents/Image.js","sources":["../../src/editorComponents/Image.tsx"],"sourcesContent":["import React from \"react\";\nimport NextImage from \"next/image\";\nimport type { ComponentProps, CssProperties, Asset } from \"@webiny/website-builder-react\";\nimport {\n getAssetUrl,\n getImageDimensions,\n getImageSrcSet,\n normalizeToAsset\n} from \"@webiny/website-builder-react\";\n\ntype ImageProps = ComponentProps<{\n title: string;\n altText: string;\n highPriority: boolean;\n // Accepts the unified asset shape or a legacy value (existing pages).\n image: Asset;\n}>;\n\nexport const ImageComponent = (props: ImageProps) => {\n const { title = \"\", altText, image, highPriority } = props.inputs;\n const asset = normalizeToAsset(image);\n\n if (!asset?.src) {\n return <ImagePlaceholder style={props.styles} />;\n }\n\n const alt = altText || asset.image?.alt || \"\";\n\n // SVGs are vector — nothing to crop, resize, or re-encode.\n if (asset.src.endsWith(\".svg\")) {\n return (\n <object style={{ maxWidth: \"100%\", ...props.styles }} title={title} data={asset.src} />\n );\n }\n\n // The delivery bakes the per-usage crop (`?crop`), resizes (`?width`), and serves\n // a modern format negotiated from Accept (`?format=auto`). We hand `next/image` a\n // loader that builds that URL, and it drives the responsive `srcSet`.\n const loader = ({ width }: { width: number }) => getAssetUrl(asset, { width, format: \"auto\" });\n\n // Intrinsic size of the *delivered* (cropped) image, so next/image lays out at\n // the correct aspect ratio. Falls back to a plain <img> when dimensions are\n // unknown (next/image requires width + height unless `fill`).\n const { width, height } = getImageDimensions(asset);\n\n const style: CssProperties = { maxWidth: \"100%\", height: \"auto\", ...props.styles };\n\n if (!width || !height) {\n // No intrinsic size to lay out with — fall back to a plain <img>, still\n // responsive via the SDK's framework-agnostic srcSet (crop/format baked in).\n const { src, srcSet } = getImageSrcSet(asset, {\n format: \"auto\",\n cssWidth: props.styles?.width\n });\n // eslint-disable-next-line @next/next/no-img-element\n return (\n <img\n src={src}\n srcSet={srcSet}\n sizes=\"100vw\"\n alt={alt}\n title={title || undefined}\n loading={highPriority ? \"eager\" : \"lazy\"}\n style={style}\n />\n );\n }\n\n return (\n <NextImage\n src={asset.src}\n loader={loader}\n alt={alt}\n title={title || undefined}\n width={width}\n height={height}\n sizes={\"100vw\"}\n priority={highPriority}\n style={style}\n />\n );\n};\n\nconst ImagePlaceholder = ({ style }: { style: CssProperties }) => {\n return (\n <div\n style={{\n display: \"flex\",\n height: \"200px\",\n backgroundColor: \"#f4f4f4\",\n justifyContent: \"center\",\n alignItems: \"center\",\n fill: \"#ffffff\",\n ...style\n }}\n >\n <svg\n style={{\n width: \"70px\",\n height: \"70px\",\n filter: \"drop-shadow(rgba(0, 0, 0, 0.16) 0px 1px 0px)\"\n }}\n xmlns=\"http://www.w3.org/2000/svg\"\n height=\"24px\"\n viewBox=\"0 -960 960 960\"\n width=\"24px\"\n >\n <path d=\"M200-120q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h560q33 0 56.5 23.5T840-760v560q0 33-23.5 56.5T760-120H200Zm0-80h560v-560H200v560Zm40-80h480L570-480 450-320l-90-120-120 160Zm-40 80v-560 560Z\" />\n </svg>\n </div>\n );\n};\n"],"names":["ImageComponent","props","title","altText","image","highPriority","asset","normalizeToAsset","ImagePlaceholder","alt","loader","width","getAssetUrl","height","getImageDimensions","style","src","srcSet","getImageSrcSet","undefined","NextImage"],"mappings":";;;AAkBO,MAAMA,iBAAiB,CAACC;IAC3B,MAAM,EAAEC,QAAQ,EAAE,EAAEC,OAAO,EAAEC,KAAK,EAAEC,YAAY,EAAE,GAAGJ,MAAM,MAAM;IACjE,MAAMK,QAAQC,iBAAiBH;IAE/B,IAAI,CAACE,OAAO,KACR,OAAO,WAAP,GAAO,oBAACE,kBAAgBA;QAAC,OAAOP,MAAM,MAAM;;IAGhD,MAAMQ,MAAMN,WAAWG,MAAM,KAAK,EAAE,OAAO;IAG3C,IAAIA,MAAM,GAAG,CAAC,QAAQ,CAAC,SACnB,OAAO,WAAP,GACI,oBAAC;QAAO,OAAO;YAAE,UAAU;YAAQ,GAAGL,MAAM,MAAM;QAAC;QAAG,OAAOC;QAAO,MAAMI,MAAM,GAAG;;IAO3F,MAAMI,SAAS,CAAC,EAAEC,KAAK,EAAqB,GAAKC,YAAYN,OAAO;YAAEK;YAAO,QAAQ;QAAO;IAK5F,MAAM,EAAEA,KAAK,EAAEE,MAAM,EAAE,GAAGC,mBAAmBR;IAE7C,MAAMS,QAAuB;QAAE,UAAU;QAAQ,QAAQ;QAAQ,GAAGd,MAAM,MAAM;IAAC;IAEjF,IAAI,CAACU,SAAS,CAACE,QAAQ;QAGnB,MAAM,EAAEG,GAAG,EAAEC,MAAM,EAAE,GAAGC,eAAeZ,OAAO;YAC1C,QAAQ;YACR,UAAUL,MAAM,MAAM,EAAE;QAC5B;QAEA,OAAO,WAAP,GACI,oBAAC;YACG,KAAKe;YACL,QAAQC;YACR,OAAM;YACN,KAAKR;YACL,OAAOP,SAASiB;YAChB,SAASd,eAAe,UAAU;YAClC,OAAOU;;IAGnB;IAEA,OAAO,WAAP,GACI,oBAACK,YAASA;QACN,KAAKd,MAAM,GAAG;QACd,QAAQI;QACR,KAAKD;QACL,OAAOP,SAASiB;QAChB,OAAOR;QACP,QAAQE;QACR,OAAO;QACP,UAAUR;QACV,OAAOU;;AAGnB;AAEA,MAAMP,mBAAmB,CAAC,EAAEO,KAAK,EAA4B,GAClD,WAAP,GACI,oBAAC;QACG,OAAO;YACH,SAAS;YACT,QAAQ;YACR,iBAAiB;YACjB,gBAAgB;YAChB,YAAY;YACZ,MAAM;YACN,GAAGA,KAAK;QACZ;qBAEA,oBAAC;QACG,OAAO;YACH,OAAO;YACP,QAAQ;YACR,QAAQ;QACZ;QACA,OAAM;QACN,QAAO;QACP,SAAQ;QACR,OAAM;qBAEN,oBAAC;QAAK,GAAE"}
@@ -0,0 +1 @@
1
+ export declare const Image: import("@webiny/website-builder-sdk/types.js").Component;
@@ -0,0 +1,45 @@
1
+ "use client";
2
+ import { createBooleanInput, createComponent, createFileInput, createTextInput } from "@webiny/website-builder-react";
3
+ import { ImageComponent } from "./Image.js";
4
+ const Image = createComponent(ImageComponent, {
5
+ name: "Webiny/Image",
6
+ label: "Image",
7
+ group: "basic",
8
+ image: '<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px"><path d="M200-120q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h560q33 0 56.5 23.5T840-760v560q0 33-23.5 56.5T760-120H200Zm0-80h560v-560H200v560Zm40-80h480L570-480 450-320l-90-120-120 160Zm-40 80v-560 560Z"/></svg>',
9
+ autoApplyStyles: false,
10
+ inputs: {
11
+ image: createFileInput({
12
+ label: "Image",
13
+ allowedFileTypes: [
14
+ "image/*"
15
+ ],
16
+ onChange: ({ inputs })=>{
17
+ if (inputs.image) {
18
+ inputs.title = inputs.image.name;
19
+ inputs.altText = inputs.image.name;
20
+ }
21
+ }
22
+ }),
23
+ title: createTextInput({
24
+ label: "Title",
25
+ description: "Title of the image"
26
+ }),
27
+ altText: createTextInput({
28
+ label: "Alternate Text",
29
+ description: "Shown when the user has disabled images"
30
+ }),
31
+ highPriority: createBooleanInput({
32
+ label: "High Priority",
33
+ description: "Prioritize this image loading over other images on the page",
34
+ defaultValue: false
35
+ })
36
+ },
37
+ defaults: {
38
+ styles: {
39
+ width: "100%"
40
+ }
41
+ }
42
+ });
43
+ export { Image };
44
+
45
+ //# sourceMappingURL=Image.manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"editorComponents/Image.manifest.js","sources":["../../src/editorComponents/Image.manifest.ts"],"sourcesContent":["\"use client\";\nimport {\n createFileInput,\n createTextInput,\n createBooleanInput,\n createComponent\n} from \"@webiny/website-builder-react\";\nimport { ImageComponent } from \"./Image.js\";\n\nexport const Image = createComponent(ImageComponent, {\n name: \"Webiny/Image\",\n label: \"Image\",\n group: \"basic\",\n image: `<svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\" viewBox=\"0 -960 960 960\" width=\"24px\"><path d=\"M200-120q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h560q33 0 56.5 23.5T840-760v560q0 33-23.5 56.5T760-120H200Zm0-80h560v-560H200v560Zm40-80h480L570-480 450-320l-90-120-120 160Zm-40 80v-560 560Z\"/></svg>`,\n autoApplyStyles: false,\n inputs: {\n image: createFileInput({\n label: \"Image\",\n allowedFileTypes: [\"image/*\"],\n onChange: ({ inputs }) => {\n if (inputs.image) {\n inputs.title = inputs.image.name;\n inputs.altText = inputs.image.name;\n }\n }\n }),\n title: createTextInput({\n label: \"Title\",\n description: \"Title of the image\"\n }),\n altText: createTextInput({\n label: \"Alternate Text\",\n description: \"Shown when the user has disabled images\"\n }),\n highPriority: createBooleanInput({\n label: \"High Priority\",\n description: \"Prioritize this image loading over other images on the page\",\n defaultValue: false\n })\n },\n defaults: {\n styles: {\n width: \"100%\"\n }\n }\n});\n"],"names":["Image","createComponent","ImageComponent","createFileInput","inputs","createTextInput","createBooleanInput"],"mappings":";;;AASO,MAAMA,QAAQC,gBAAgBC,gBAAgB;IACjD,MAAM;IACN,OAAO;IACP,OAAO;IACP,OAAO;IACP,iBAAiB;IACjB,QAAQ;QACJ,OAAOC,gBAAgB;YACnB,OAAO;YACP,kBAAkB;gBAAC;aAAU;YAC7B,UAAU,CAAC,EAAEC,MAAM,EAAE;gBACjB,IAAIA,OAAO,KAAK,EAAE;oBACdA,OAAO,KAAK,GAAGA,OAAO,KAAK,CAAC,IAAI;oBAChCA,OAAO,OAAO,GAAGA,OAAO,KAAK,CAAC,IAAI;gBACtC;YACJ;QACJ;QACA,OAAOC,gBAAgB;YACnB,OAAO;YACP,aAAa;QACjB;QACA,SAASA,gBAAgB;YACrB,OAAO;YACP,aAAa;QACjB;QACA,cAAcC,mBAAmB;YAC7B,OAAO;YACP,aAAa;YACb,cAAc;QAClB;IACJ;IACA,UAAU;QACN,QAAQ;YACJ,OAAO;QACX;IACJ;AACJ"}
package/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  export * from "@webiny/website-builder-react";
2
- export * from "./useCss";
2
+ export { DocumentRenderer } from "./DocumentRenderer.js";
package/index.js CHANGED
@@ -1,13 +1,9 @@
1
- export * from "@webiny/website-builder-react";
2
- export * from "./useCss";
3
1
  import { setHeadersProvider } from "@webiny/website-builder-react";
4
- setHeadersProvider(async () => {
5
- // Settings @ts-expect-error breaks the build if the dependency is installed in the repo.
6
- // @ts-ignore This is a peer dependency.
7
- const {
8
- headers
9
- } = await import("next/headers");
10
- return await headers();
2
+ export * from "@webiny/website-builder-react";
3
+ setHeadersProvider(async ()=>{
4
+ const { headers } = await import("next/headers.js");
5
+ return await headers();
11
6
  });
7
+ export { DocumentRenderer } from "./DocumentRenderer.js";
12
8
 
13
9
  //# sourceMappingURL=index.js.map
package/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"names":["setHeadersProvider","headers"],"sources":["index.ts"],"sourcesContent":["export * from \"@webiny/website-builder-react\";\nexport * from \"./useCss\";\n\nimport { setHeadersProvider } from \"@webiny/website-builder-react\";\n\nsetHeadersProvider(async () => {\n // Settings @ts-expect-error breaks the build if the dependency is installed in the repo.\n // @ts-ignore This is a peer dependency.\n const { headers } = await import(\"next/headers\");\n return await headers();\n});\n"],"mappings":"AAAA,cAAc,+BAA+B;AAC7C;AAEA,SAASA,kBAAkB,QAAQ,+BAA+B;AAElEA,kBAAkB,CAAC,YAAY;EAC3B;EACA;EACA,MAAM;IAAEC;EAAQ,CAAC,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC;EAChD,OAAO,MAAMA,OAAO,CAAC,CAAC;AAC1B,CAAC,CAAC","ignoreList":[]}
1
+ {"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["export * from \"@webiny/website-builder-react\";\nexport { DocumentRenderer } from \"./DocumentRenderer.js\";\n\nimport { setHeadersProvider } from \"@webiny/website-builder-react\";\n\nsetHeadersProvider(async () => {\n // Settings @ts-expect-error breaks the build if the dependency is installed in the repo.\n // @ts-ignore This is a peer dependency.\n const { headers } = await import(\"next/headers.js\");\n return await headers();\n});\n"],"names":["setHeadersProvider","headers"],"mappings":";;AAKAA,mBAAmB;IAGf,MAAM,EAAEC,OAAO,EAAE,GAAG,MAAM,MAAM,CAAC;IACjC,OAAO,MAAMA;AACjB"}
package/lexical.css ADDED
@@ -0,0 +1,379 @@
1
+ .wb-lx-ltr {
2
+ text-align: inherit;
3
+ }
4
+ .wb-lx-rtl {
5
+ text-align: inherit;
6
+ }
7
+ .wb-lx-paragraph {
8
+ }
9
+
10
+ .wb-lx-quote {
11
+ }
12
+
13
+ .wb-lx-h1,
14
+ .wb-lx-h2,
15
+ .wb-lx-h3,
16
+ .wb-lx-h4,
17
+ .wb-lx-h5,
18
+ .wb-lx-h6 {
19
+ }
20
+
21
+ .wb-lx-textBold {
22
+ font-weight: bold;
23
+ }
24
+
25
+ .wb-lx-textItalic {
26
+ font-style: italic;
27
+ }
28
+ .wb-lx-textUnderline {
29
+ text-decoration: underline;
30
+ }
31
+ .wb-lx-textStrikethrough {
32
+ text-decoration: line-through;
33
+ }
34
+ .wb-lx-textUnderlineStrikethrough {
35
+ text-decoration: underline line-through;
36
+ }
37
+
38
+ .wb-lx-textSubscript {
39
+ font-size: 0.8em;
40
+ vertical-align: sub !important;
41
+ }
42
+
43
+ .wb-lx-textSuperscript {
44
+ font-size: 0.8em;
45
+ vertical-align: super;
46
+ }
47
+
48
+ .wb-lx-textCode {
49
+ background-color: rgb(240, 242, 245);
50
+ padding: 1px 0.25rem;
51
+ font-family: Menlo, Consolas, Monaco, monospace;
52
+ font-size: 94%;
53
+ }
54
+ .wb-lx-hashtag {
55
+ background-color: rgba(88, 144, 255, 0.15);
56
+ border-bottom: 1px solid rgba(88, 144, 255, 0.3);
57
+ }
58
+ .wb-lx-link {
59
+ color: var(--wb-theme-color1);
60
+ text-decoration: none;
61
+ > * {
62
+ color: inherit !important;
63
+ }
64
+ }
65
+ .wb-lx-link:hover {
66
+ text-decoration: underline;
67
+ }
68
+ .wb-lx-code {
69
+ background-color: rgb(240, 242, 245);
70
+ font-family: Menlo, Consolas, Monaco, monospace;
71
+ display: block;
72
+ padding: 8px 8px 8px 52px;
73
+ line-height: 1.53;
74
+ font-size: 13px;
75
+ margin: 8px 0;
76
+ tab-size: 2;
77
+ /* white-space: pre; */
78
+ overflow-x: auto;
79
+ position: relative;
80
+ }
81
+ .wb-lx-code:before {
82
+ content: attr(data-gutter);
83
+ position: absolute;
84
+ background-color: #eee;
85
+ left: 0;
86
+ top: 0;
87
+ border-right: 1px solid #ccc;
88
+ padding: 8px;
89
+ color: #777;
90
+ white-space: pre-wrap;
91
+ text-align: right;
92
+ min-width: 25px;
93
+ }
94
+ .wb-lx-table {
95
+ border-collapse: collapse;
96
+ border-spacing: 0;
97
+ max-width: 100%;
98
+ overflow-y: scroll;
99
+ table-layout: fixed;
100
+ width: calc(100% - 25px);
101
+ margin: 30px 0;
102
+ }
103
+ .wb-lx-tableSelected {
104
+ outline: 2px solid rgb(60, 132, 244);
105
+ }
106
+ .wb-lx-tableCell {
107
+ border: 1px solid #bbb;
108
+ min-width: 75px;
109
+ vertical-align: top;
110
+ text-align: start;
111
+ padding: 6px 8px;
112
+ position: relative;
113
+ cursor: default;
114
+ outline: none;
115
+ }
116
+ .wb-lx-tableCellSortedIndicator {
117
+ display: block;
118
+ opacity: 0.5;
119
+ position: absolute;
120
+ bottom: 0;
121
+ left: 0;
122
+ width: 100%;
123
+ height: 4px;
124
+ background-color: #999;
125
+ }
126
+ .wb-lx-tableCellResizer {
127
+ position: absolute;
128
+ right: -4px;
129
+ height: 100%;
130
+ width: 8px;
131
+ cursor: ew-resize;
132
+ z-index: 10;
133
+ top: 0;
134
+ }
135
+ .wb-lx-tableCellHeader {
136
+ background-color: #f2f3f5;
137
+ text-align: start;
138
+ }
139
+ .wb-lx-tableCellSelected {
140
+ background-color: #c9dbf0;
141
+ }
142
+ .wb-lx-tableCellPrimarySelected {
143
+ border: 2px solid rgb(60, 132, 244);
144
+ display: block;
145
+ height: calc(100% - 2px);
146
+ position: absolute;
147
+ width: calc(100% - 2px);
148
+ left: -1px;
149
+ top: -1px;
150
+ z-index: 2;
151
+ }
152
+ .wb-lx-tableCellEditing {
153
+ box-shadow: 0 0 5px rgba(0, 0, 0, 0.4);
154
+ border-radius: 3px;
155
+ }
156
+ .wb-lx-tableAddColumns {
157
+ position: absolute;
158
+ top: 0;
159
+ width: 20px;
160
+ background-color: #eee;
161
+ height: 100%;
162
+ right: 0;
163
+ animation: table-controls 0.2s ease;
164
+ border: 0;
165
+ cursor: pointer;
166
+ }
167
+
168
+ .wb-lx-tableAddColumns:hover {
169
+ background-color: #c9dbf0;
170
+ }
171
+ .wb-lx-tableAddRows {
172
+ position: absolute;
173
+ bottom: -25px;
174
+ width: calc(100% - 25px);
175
+ background-color: #eee;
176
+ height: 20px;
177
+ left: 0;
178
+ animation: table-controls 0.2s ease;
179
+ border: 0;
180
+ cursor: pointer;
181
+ }
182
+ .wb-lx-tableAddRows:hover {
183
+ background-color: #c9dbf0;
184
+ }
185
+ @keyframes table-controls {
186
+ 0% {
187
+ opacity: 0;
188
+ }
189
+ 100% {
190
+ opacity: 1;
191
+ }
192
+ }
193
+ .wb-lx-tableCellResizeRuler {
194
+ display: block;
195
+ position: absolute;
196
+ width: 1px;
197
+ background-color: rgb(60, 132, 244);
198
+ height: 100%;
199
+ top: 0;
200
+ }
201
+ .wb-lx-tableCellActionButtonContainer {
202
+ display: block;
203
+ right: 5px;
204
+ top: 6px;
205
+ position: absolute;
206
+ z-index: 4;
207
+ width: 20px;
208
+ height: 20px;
209
+ }
210
+ .wb-lx-tableCellActionButton {
211
+ background-color: #eee;
212
+ display: block;
213
+ border: 0;
214
+ border-radius: 20px;
215
+ width: 20px;
216
+ height: 20px;
217
+ color: #222;
218
+ cursor: pointer;
219
+ }
220
+ .wb-lx-tableCellActionButton:hover {
221
+ background-color: #ddd;
222
+ }
223
+ .wb-lx-characterLimit {
224
+ display: inline;
225
+ background-color: #ffbbbb !important;
226
+ }
227
+ .wb-lx-ol1 {
228
+ padding: 0;
229
+ margin: 0 0 0 16px;
230
+ list-style: inside;
231
+ }
232
+ .wb-lx-ol2 {
233
+ padding: 0;
234
+ margin: 0 0 0 16px;
235
+ list-style: upper-alpha inside;
236
+ }
237
+ .wb-lx-ol3 {
238
+ list-style: initial;
239
+ list-style: auto;
240
+ padding: 0;
241
+ margin: 0 0 0 16px;
242
+ list-style-type: lower-alpha;
243
+ list-style-position: inside;
244
+ }
245
+ .wb-lx-ol4 {
246
+ padding: 0;
247
+ margin: 0 0 0 16px;
248
+ list-style: upper-roman inside;
249
+ }
250
+ .wb-lx-ol5 {
251
+ padding: 0;
252
+ margin: 0 0 0 16px;
253
+ list-style: lower-roman inside;
254
+ }
255
+ .wb-lx-ul {
256
+ padding: 0;
257
+ margin: 0 0 0 16px;
258
+ list-style: inside;
259
+ }
260
+ .wb-lx-listItem {
261
+ margin: 0 32px;
262
+ }
263
+ .wb-lx-listItemChecked,
264
+ .wb-lx-listItemUnchecked {
265
+ position: relative;
266
+ margin-left: 8px;
267
+ margin-right: 8px;
268
+ padding-left: 24px;
269
+ padding-right: 24px;
270
+ list-style-type: none;
271
+ outline: none;
272
+ }
273
+ .wb-lx-listItemChecked {
274
+ text-decoration: line-through;
275
+ }
276
+ .wb-lx-listItemUnchecked:before,
277
+ .wb-lx-listItemChecked:before {
278
+ content: "";
279
+ width: 16px;
280
+ height: 16px;
281
+ top: 2px;
282
+ left: 0;
283
+ cursor: pointer;
284
+ display: block;
285
+ background-size: cover;
286
+ position: absolute;
287
+ }
288
+ .wb-lx-listItemUnchecked[dir="rtl"]:before,
289
+ .wb-lx-listItemChecked[dir="rtl"]:before {
290
+ left: auto;
291
+ right: 0;
292
+ }
293
+ .wb-lx-listItemUnchecked:focus:before,
294
+ .wb-lx-listItemChecked:focus:before {
295
+ box-shadow: 0 0 0 2px #a6cdfe;
296
+ border-radius: 2px;
297
+ }
298
+ .wb-lx-listItemUnchecked:before {
299
+ border: 1px solid #999;
300
+ border-radius: 2px;
301
+ }
302
+ .wb-lx-listItemChecked:before {
303
+ border: 1px solid rgb(61, 135, 245);
304
+ border-radius: 2px;
305
+ background-color: #3d87f5;
306
+ background-repeat: no-repeat;
307
+ }
308
+ .wb-lx-listItemChecked:after {
309
+ content: "";
310
+ cursor: pointer;
311
+ border-color: #fff;
312
+ border-style: solid;
313
+ position: absolute;
314
+ display: block;
315
+ top: 6px;
316
+ width: 3px;
317
+ left: 7px;
318
+ height: 6px;
319
+ transform: rotate(45deg);
320
+ border-width: 0 2px 2px 0;
321
+ }
322
+ .wb-lx-nestedListItem {
323
+ list-style-type: none;
324
+ }
325
+ .wb-lx-nestedListItem:before,
326
+ .wb-lx-nestedListItem:after {
327
+ display: none;
328
+ }
329
+ .wb-lx-tokenComment {
330
+ color: slategray;
331
+ }
332
+ .wb-lx-tokenPunctuation {
333
+ color: #999;
334
+ }
335
+ .wb-lx-tokenProperty {
336
+ color: #905;
337
+ }
338
+ .wb-lx-tokenSelector {
339
+ color: #690;
340
+ }
341
+ .wb-lx-tokenOperator {
342
+ color: #9a6e3a;
343
+ }
344
+ .wb-lx-tokenAttr {
345
+ color: #07a;
346
+ }
347
+ .wb-lx-tokenVariable {
348
+ color: #e90;
349
+ }
350
+ .wb-lx-tokenFunction {
351
+ color: #dd4a68;
352
+ }
353
+ .wb-lx-mark {
354
+ background: rgba(255, 212, 0, 0.14);
355
+ border-bottom: 2px solid rgba(255, 212, 0, 0.3);
356
+ padding-bottom: 2px;
357
+ }
358
+ .wb-lx-markOverlap {
359
+ background: rgba(255, 212, 0, 0.3);
360
+ border-bottom: 2px solid rgba(255, 212, 0, 0.7);
361
+ }
362
+ .wb-lx-mark.selected {
363
+ background: rgba(255, 212, 0, 0.5);
364
+ border-bottom: 2px solid rgba(255, 212, 0, 1);
365
+ }
366
+ .wb-lx-markOverlap.selected {
367
+ background: rgba(255, 212, 0, 0.7);
368
+ border-bottom: 2px solid rgba(255, 212, 0, 0.7);
369
+ }
370
+ .wb-lx-embedBlock {
371
+ user-select: none;
372
+ }
373
+ .wb-lx-embedBlockFocus {
374
+ outline: 2px solid rgb(60, 132, 244);
375
+ }
376
+
377
+ .wb-lx-placeholder {
378
+ text-align: left;
379
+ }
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Next.js middleware for Website Builder.
3
+ *
4
+ * Handles the two request-time concerns an app would otherwise hand-write:
5
+ * - **Preview / draft mode** — routes `?wb.preview`/`?wb.editing` requests through the draft-mode
6
+ * route and disables caching while previewing; exits preview when the flag is gone.
7
+ * - **A/B visitor cookie** — sets a stable, PII-free `wb_ab_vid` cookie so variant bucketing is
8
+ * deterministic across visits.
9
+ *
10
+ * `next` is a peer dependency and is imported dynamically so building this package never requires
11
+ * it. Drop into a project as:
12
+ *
13
+ * // middleware.ts
14
+ * export { middleware, config } from "@webiny/website-builder-nextjs/middleware";
15
+ */
16
+ interface MiddlewareRequest {
17
+ url: string;
18
+ nextUrl: {
19
+ searchParams: URLSearchParams;
20
+ pathname: string;
21
+ };
22
+ headers: Headers;
23
+ cookies: {
24
+ get(name: string): {
25
+ value: string;
26
+ } | undefined;
27
+ };
28
+ }
29
+ export interface WebsiteBuilderMiddlewareOptions {
30
+ /** Route that enables Next.js draft mode for preview. Defaults to `/api/preview`. */
31
+ previewRoute?: string;
32
+ /** A/B bucketing cookie name. Defaults to `wb_ab_vid`. */
33
+ visitorCookieName?: string;
34
+ /** A/B bucketing cookie max-age in seconds. Defaults to one year. */
35
+ visitorCookieMaxAge?: number;
36
+ }
37
+ export declare function createWebsiteBuilderMiddleware(options?: WebsiteBuilderMiddlewareOptions): (request: MiddlewareRequest) => Promise<import("next/server").NextResponse<unknown>>;
38
+ /** Turnkey middleware with default options. */
39
+ export declare const middleware: (request: MiddlewareRequest) => Promise<import("next/server").NextResponse<unknown>>;
40
+ /** Default matcher: everything except Next internals, API routes, and static assets. */
41
+ export declare const config: {
42
+ matcher: string[];
43
+ };
44
+ export {};
package/middleware.js ADDED
@@ -0,0 +1,58 @@
1
+ const DEFAULT_PREVIEW_ROUTE = "/api/preview";
2
+ const DEFAULT_VISITOR_COOKIE = "wb_ab_vid";
3
+ const ONE_YEAR_SECONDS = 31536000;
4
+ function createWebsiteBuilderMiddleware(options = {}) {
5
+ const previewRoute = options.previewRoute ?? DEFAULT_PREVIEW_ROUTE;
6
+ const cookieName = options.visitorCookieName ?? DEFAULT_VISITOR_COOKIE;
7
+ const cookieMaxAge = options.visitorCookieMaxAge ?? ONE_YEAR_SECONDS;
8
+ return async function(request) {
9
+ const { NextResponse } = await import("next/server");
10
+ const { draftMode } = await import("next/headers");
11
+ const { searchParams } = request.nextUrl;
12
+ const previewRequested = "true" === searchParams.get("wb.preview") || "true" === searchParams.get("wb.editing");
13
+ const requestHeaders = new Headers(request.headers);
14
+ requestHeaders.set("X-Tenant", searchParams.get("wb.tenant") ?? "root");
15
+ const previewMode = await draftMode();
16
+ if (previewRequested) {
17
+ if (previewMode.isEnabled) {
18
+ const response = NextResponse.next({
19
+ request: {
20
+ headers: requestHeaders
21
+ }
22
+ });
23
+ response.headers.set("X-Preview-Params", searchParams.toString());
24
+ response.headers.set("Cache-Control", "no-store, no-cache, must-revalidate, proxy-revalidate");
25
+ response.headers.set("Pragma", "no-cache");
26
+ response.headers.set("Expires", "0");
27
+ return response;
28
+ }
29
+ const url = new URL(request.url);
30
+ url.pathname = previewRoute;
31
+ return NextResponse.redirect(url);
32
+ }
33
+ if (previewMode.isEnabled) {
34
+ previewMode.disable();
35
+ return NextResponse.redirect(request.url);
36
+ }
37
+ const response = NextResponse.next({
38
+ request: {
39
+ headers: requestHeaders
40
+ }
41
+ });
42
+ if (!request.cookies.get(cookieName)) response.cookies.set(cookieName, crypto.randomUUID(), {
43
+ maxAge: cookieMaxAge,
44
+ path: "/",
45
+ sameSite: "lax"
46
+ });
47
+ return response;
48
+ };
49
+ }
50
+ const middleware_middleware = createWebsiteBuilderMiddleware();
51
+ const config = {
52
+ matcher: [
53
+ "/((?!_next|api|static|favicon.ico|.well-known).*)"
54
+ ]
55
+ };
56
+ export { config, createWebsiteBuilderMiddleware, middleware_middleware as middleware };
57
+
58
+ //# sourceMappingURL=middleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.js","sources":["../src/middleware.ts"],"sourcesContent":["/**\n * Next.js middleware for Website Builder.\n *\n * Handles the two request-time concerns an app would otherwise hand-write:\n * - **Preview / draft mode** — routes `?wb.preview`/`?wb.editing` requests through the draft-mode\n * route and disables caching while previewing; exits preview when the flag is gone.\n * - **A/B visitor cookie** — sets a stable, PII-free `wb_ab_vid` cookie so variant bucketing is\n * deterministic across visits.\n *\n * `next` is a peer dependency and is imported dynamically so building this package never requires\n * it. Drop into a project as:\n *\n * // middleware.ts\n * export { middleware, config } from \"@webiny/website-builder-nextjs/middleware\";\n */\n\nconst DEFAULT_PREVIEW_ROUTE = \"/api/preview\";\nconst DEFAULT_VISITOR_COOKIE = \"wb_ab_vid\";\nconst ONE_YEAR_SECONDS = 60 * 60 * 24 * 365;\n\n// Minimal structural view of NextRequest — avoids a static `next` type import.\ninterface MiddlewareRequest {\n url: string;\n nextUrl: { searchParams: URLSearchParams; pathname: string };\n headers: Headers;\n cookies: { get(name: string): { value: string } | undefined };\n}\n\nexport interface WebsiteBuilderMiddlewareOptions {\n /** Route that enables Next.js draft mode for preview. Defaults to `/api/preview`. */\n previewRoute?: string;\n /** A/B bucketing cookie name. Defaults to `wb_ab_vid`. */\n visitorCookieName?: string;\n /** A/B bucketing cookie max-age in seconds. Defaults to one year. */\n visitorCookieMaxAge?: number;\n}\n\nexport function createWebsiteBuilderMiddleware(options: WebsiteBuilderMiddlewareOptions = {}) {\n const previewRoute = options.previewRoute ?? DEFAULT_PREVIEW_ROUTE;\n const cookieName = options.visitorCookieName ?? DEFAULT_VISITOR_COOKIE;\n const cookieMaxAge = options.visitorCookieMaxAge ?? ONE_YEAR_SECONDS;\n\n return async function middleware(request: MiddlewareRequest) {\n // @ts-ignore Peer dependency, resolved from the host app.\n const { NextResponse } = await import(\"next/server\");\n // @ts-ignore Peer dependency, resolved from the host app.\n const { draftMode } = await import(\"next/headers\");\n\n const { searchParams } = request.nextUrl;\n const previewRequested =\n searchParams.get(\"wb.preview\") === \"true\" || searchParams.get(\"wb.editing\") === \"true\";\n\n // Forward the tenant so downstream reads resolve against the right tenant.\n const requestHeaders = new Headers(request.headers);\n requestHeaders.set(\"X-Tenant\", searchParams.get(\"wb.tenant\") ?? \"root\");\n\n const previewMode = await draftMode();\n\n if (previewRequested) {\n if (previewMode.isEnabled) {\n // Already in draft mode — pass the preview params through and disable caching.\n const response = NextResponse.next({ request: { headers: requestHeaders } });\n response.headers.set(\"X-Preview-Params\", searchParams.toString());\n response.headers.set(\n \"Cache-Control\",\n \"no-store, no-cache, must-revalidate, proxy-revalidate\"\n );\n response.headers.set(\"Pragma\", \"no-cache\");\n response.headers.set(\"Expires\", \"0\");\n return response;\n }\n // Not in draft mode yet — hand off to the route that enables it, keeping all params.\n const url = new URL(request.url);\n url.pathname = previewRoute;\n return NextResponse.redirect(url);\n }\n\n if (previewMode.isEnabled) {\n // Preview flag gone but draft mode still on — exit preview.\n previewMode.disable();\n return NextResponse.redirect(request.url);\n }\n\n const response = NextResponse.next({ request: { headers: requestHeaders } });\n\n // Stable visitor id for deterministic A/B bucketing (functional cookie, no PII). Remove or\n // gate this if your consent policy requires opt-in — bucketing still works per-request\n // without it, just not stably across visits.\n if (!request.cookies.get(cookieName)) {\n response.cookies.set(cookieName, crypto.randomUUID(), {\n maxAge: cookieMaxAge,\n path: \"/\",\n sameSite: \"lax\"\n });\n }\n\n return response;\n };\n}\n\n/** Turnkey middleware with default options. */\nexport const middleware = createWebsiteBuilderMiddleware();\n\n/** Default matcher: everything except Next internals, API routes, and static assets. */\nexport const config = {\n matcher: [\"/((?!_next|api|static|favicon.ico|.well-known).*)\"]\n};\n"],"names":["DEFAULT_PREVIEW_ROUTE","DEFAULT_VISITOR_COOKIE","ONE_YEAR_SECONDS","createWebsiteBuilderMiddleware","options","previewRoute","cookieName","cookieMaxAge","request","NextResponse","draftMode","searchParams","previewRequested","requestHeaders","Headers","previewMode","response","url","URL","crypto","middleware","config"],"mappings":"AAgBA,MAAMA,wBAAwB;AAC9B,MAAMC,yBAAyB;AAC/B,MAAMC,mBAAmB;AAmBlB,SAASC,+BAA+BC,UAA2C,CAAC,CAAC;IACxF,MAAMC,eAAeD,QAAQ,YAAY,IAAIJ;IAC7C,MAAMM,aAAaF,QAAQ,iBAAiB,IAAIH;IAChD,MAAMM,eAAeH,QAAQ,mBAAmB,IAAIF;IAEpD,OAAO,eAA0BM,OAA0B;QAEvD,MAAM,EAAEC,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC;QAEtC,MAAM,EAAEC,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC;QAEnC,MAAM,EAAEC,YAAY,EAAE,GAAGH,QAAQ,OAAO;QACxC,MAAMI,mBACFD,AAAmC,WAAnCA,aAAa,GAAG,CAAC,iBAA4BA,AAAmC,WAAnCA,aAAa,GAAG,CAAC;QAGlE,MAAME,iBAAiB,IAAIC,QAAQN,QAAQ,OAAO;QAClDK,eAAe,GAAG,CAAC,YAAYF,aAAa,GAAG,CAAC,gBAAgB;QAEhE,MAAMI,cAAc,MAAML;QAE1B,IAAIE,kBAAkB;YAClB,IAAIG,YAAY,SAAS,EAAE;gBAEvB,MAAMC,WAAWP,aAAa,IAAI,CAAC;oBAAE,SAAS;wBAAE,SAASI;oBAAe;gBAAE;gBAC1EG,SAAS,OAAO,CAAC,GAAG,CAAC,oBAAoBL,aAAa,QAAQ;gBAC9DK,SAAS,OAAO,CAAC,GAAG,CAChB,iBACA;gBAEJA,SAAS,OAAO,CAAC,GAAG,CAAC,UAAU;gBAC/BA,SAAS,OAAO,CAAC,GAAG,CAAC,WAAW;gBAChC,OAAOA;YACX;YAEA,MAAMC,MAAM,IAAIC,IAAIV,QAAQ,GAAG;YAC/BS,IAAI,QAAQ,GAAGZ;YACf,OAAOI,aAAa,QAAQ,CAACQ;QACjC;QAEA,IAAIF,YAAY,SAAS,EAAE;YAEvBA,YAAY,OAAO;YACnB,OAAON,aAAa,QAAQ,CAACD,QAAQ,GAAG;QAC5C;QAEA,MAAMQ,WAAWP,aAAa,IAAI,CAAC;YAAE,SAAS;gBAAE,SAASI;YAAe;QAAE;QAK1E,IAAI,CAACL,QAAQ,OAAO,CAAC,GAAG,CAACF,aACrBU,SAAS,OAAO,CAAC,GAAG,CAACV,YAAYa,OAAO,UAAU,IAAI;YAClD,QAAQZ;YACR,MAAM;YACN,UAAU;QACd;QAGJ,OAAOS;IACX;AACJ;AAGO,MAAMI,wBAAajB;AAGnB,MAAMkB,SAAS;IAClB,SAAS;QAAC;KAAoD;AAClE"}
package/package.json CHANGED
@@ -1,13 +1,15 @@
1
1
  {
2
2
  "name": "@webiny/website-builder-nextjs",
3
- "version": "0.0.0-unstable.8b6c57b569",
4
- "main": "index.js",
3
+ "version": "0.0.0-unstable.9f53ea597d",
4
+ "type": "module",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "https://github.com/webiny/webiny-js.git"
8
8
  },
9
9
  "exports": {
10
- ".": "./index.js"
10
+ ".": "./index.js",
11
+ "./middleware": "./middleware.js",
12
+ "./webpack": "./webpack.js"
11
13
  },
12
14
  "description": "A Next.js integration SDK for Webiny Website Builder.",
13
15
  "contributors": [
@@ -17,32 +19,33 @@
17
19
  ],
18
20
  "license": "MIT",
19
21
  "dependencies": {
20
- "@webiny/website-builder-react": "0.0.0-unstable.8b6c57b569",
21
- "postcss": "8.5.6"
22
- },
23
- "peerDependencies": {
24
- "next": "^15"
22
+ "@webiny/website-builder-react": "0.0.0-unstable.9f53ea597d",
23
+ "postcss": "8.5.21",
24
+ "postcss-import": "16.1.1"
25
25
  },
26
26
  "devDependencies": {
27
- "@webiny/project-utils": "0.0.0-unstable.8b6c57b569",
28
- "typescript": "5.3.3"
27
+ "@types/postcss-import": "14.0.3",
28
+ "@webiny/build-tools": "0.0.0-unstable.9f53ea597d",
29
+ "typescript": "7.0.2",
30
+ "vitest": "4.1.10",
31
+ "webpack": "5.108.4"
29
32
  },
30
- "publishConfig": {
31
- "access": "public",
32
- "directory": "dist"
33
+ "peerDependencies": {
34
+ "next": "16.2.11"
33
35
  },
34
- "scripts": {
35
- "build": "node ../cli/bin.js run build",
36
- "watch": "node ../cli/bin.js run watch"
36
+ "publishConfig": {
37
+ "access": "public"
37
38
  },
38
39
  "adio": {
39
40
  "ignore": {
40
41
  "dependencies": [
41
42
  "postcss",
42
- "next",
43
+ "postcss-import",
43
44
  "@webiny/website-builder-react"
44
45
  ]
45
46
  }
46
47
  },
47
- "gitHead": "8b6c57b56947ee57acf428f703bc1b8c35617a95"
48
+ "webiny": {
49
+ "publishFrom": "dist"
50
+ }
48
51
  }
package/webpack.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ import type { WebpackPluginInstance } from "webpack";
2
+ import type { NextConfig } from "next";
3
+ type WebpackConfigContext = Parameters<NonNullable<NextConfig["webpack"]>>[1];
4
+ export declare const injectThemeCss: (entry: string, variableName?: string) => Promise<{
5
+ getPlugins: (context: WebpackConfigContext) => WebpackPluginInstance[];
6
+ }>;
7
+ export {};
package/webpack.js ADDED
@@ -0,0 +1,44 @@
1
+ import fs from "fs";
2
+ import postcss from "postcss";
3
+ import postcss_import from "postcss-import";
4
+ const buildThemeCss = async (entry)=>{
5
+ const raw = fs.readFileSync(entry, "utf8");
6
+ const result = await postcss([
7
+ postcss_import()
8
+ ]).process(raw, {
9
+ from: entry
10
+ });
11
+ return result.css;
12
+ };
13
+ const injectThemeCss = async (entry, variableName)=>{
14
+ const defineKey = variableName ?? "__THEME_CSS__";
15
+ const initialCss = await buildThemeCss(entry);
16
+ let definePlugin;
17
+ const getPlugins = (context)=>{
18
+ const { dev, webpack } = context;
19
+ if (!definePlugin) definePlugin = new webpack.DefinePlugin({
20
+ [defineKey]: JSON.stringify(initialCss)
21
+ });
22
+ const plugins = [
23
+ definePlugin
24
+ ];
25
+ if (dev) plugins.push({
26
+ apply (compiler) {
27
+ compiler.hooks.afterCompile.tapPromise("WatchThemeCss", async (compilation)=>{
28
+ compilation.fileDependencies.add(entry);
29
+ });
30
+ compiler.hooks.beforeCompile.tapPromise("UpdateThemeCss", async ()=>{
31
+ const cssValue = await buildThemeCss(entry);
32
+ definePlugin.definitions[defineKey] = JSON.stringify(cssValue);
33
+ });
34
+ }
35
+ });
36
+ return plugins;
37
+ };
38
+ return {
39
+ getPlugins
40
+ };
41
+ };
42
+ export { injectThemeCss };
43
+
44
+ //# sourceMappingURL=webpack.js.map
package/webpack.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webpack.js","sources":["../src/webpack.ts"],"sourcesContent":["import fs from \"fs\";\nimport type { WebpackPluginInstance } from \"webpack\";\nimport type { AcceptedPlugin } from \"postcss\";\nimport postcss from \"postcss\";\nimport postcssImport from \"postcss-import\";\nimport type { NextConfig } from \"next\";\n\n// We're inferring the type from Next's config type.\ntype WebpackConfigContext = Parameters<NonNullable<NextConfig[\"webpack\"]>>[1];\n\nconst buildThemeCss = async (entry: string) => {\n // Read CSS entry file.\n const raw = fs.readFileSync(entry, \"utf8\");\n\n // Inline local imports.\n const result = await postcss([postcssImport() as AcceptedPlugin]).process(raw, {\n from: entry\n });\n\n return result.css;\n};\n\nexport const injectThemeCss = async (entry: string, variableName?: string) => {\n const defineKey = variableName ?? \"__THEME_CSS__\";\n\n const initialCss = await buildThemeCss(entry);\n\n // Inject as a global constant available in your app.\n let definePlugin: WebpackPluginInstance;\n\n const getPlugins = (context: WebpackConfigContext) => {\n const { dev, webpack } = context;\n\n if (!definePlugin) {\n definePlugin = new webpack.DefinePlugin({ [defineKey]: JSON.stringify(initialCss) });\n }\n\n const plugins: WebpackPluginInstance[] = [definePlugin];\n\n if (dev) {\n // Watch for changes and update plugin definitions\n plugins.push({\n apply(compiler) {\n compiler.hooks.afterCompile.tapPromise(\"WatchThemeCss\", async compilation => {\n compilation.fileDependencies.add(entry);\n });\n\n compiler.hooks.beforeCompile.tapPromise(\"UpdateThemeCss\", async () => {\n const cssValue = await buildThemeCss(entry);\n // Update the definitions on our specific plugin\n definePlugin.definitions[defineKey] = JSON.stringify(cssValue);\n });\n }\n });\n }\n\n return plugins;\n };\n\n return { getPlugins };\n};\n"],"names":["buildThemeCss","entry","raw","fs","result","postcss","postcssImport","injectThemeCss","variableName","defineKey","initialCss","definePlugin","getPlugins","context","dev","webpack","JSON","plugins","compiler","compilation","cssValue"],"mappings":";;;AAUA,MAAMA,gBAAgB,OAAOC;IAEzB,MAAMC,MAAMC,GAAG,YAAY,CAACF,OAAO;IAGnC,MAAMG,SAAS,MAAMC,QAAQ;QAACC;KAAkC,EAAE,OAAO,CAACJ,KAAK;QAC3E,MAAMD;IACV;IAEA,OAAOG,OAAO,GAAG;AACrB;AAEO,MAAMG,iBAAiB,OAAON,OAAeO;IAChD,MAAMC,YAAYD,gBAAgB;IAElC,MAAME,aAAa,MAAMV,cAAcC;IAGvC,IAAIU;IAEJ,MAAMC,aAAa,CAACC;QAChB,MAAM,EAAEC,GAAG,EAAEC,OAAO,EAAE,GAAGF;QAEzB,IAAI,CAACF,cACDA,eAAe,IAAII,QAAQ,YAAY,CAAC;YAAE,CAACN,UAAU,EAAEO,KAAK,SAAS,CAACN;QAAY;QAGtF,MAAMO,UAAmC;YAACN;SAAa;QAEvD,IAAIG,KAEAG,QAAQ,IAAI,CAAC;YACT,OAAMC,QAAQ;gBACVA,SAAS,KAAK,CAAC,YAAY,CAAC,UAAU,CAAC,iBAAiB,OAAMC;oBAC1DA,YAAY,gBAAgB,CAAC,GAAG,CAAClB;gBACrC;gBAEAiB,SAAS,KAAK,CAAC,aAAa,CAAC,UAAU,CAAC,kBAAkB;oBACtD,MAAME,WAAW,MAAMpB,cAAcC;oBAErCU,aAAa,WAAW,CAACF,UAAU,GAAGO,KAAK,SAAS,CAACI;gBACzD;YACJ;QACJ;QAGJ,OAAOH;IACX;IAEA,OAAO;QAAEL;IAAW;AACxB"}
package/CssInliner.d.ts DELETED
@@ -1,6 +0,0 @@
1
- export declare class CSSInliner {
2
- private seen;
3
- load(entryPath: string): Promise<string>;
4
- private inlineFile;
5
- private createImportInlinerPlugin;
6
- }
package/CssInliner.js DELETED
@@ -1,70 +0,0 @@
1
- import postcss from "postcss";
2
- import path from "path";
3
- import { readFile } from "fs";
4
- import { promisify } from "util";
5
- const readFileAsync = promisify(readFile);
6
- export class CSSInliner {
7
- seen = new Set();
8
- async load(entryPath) {
9
- const result = await this.inlineFile(entryPath);
10
- return result.css;
11
- }
12
- async inlineFile(filePath) {
13
- const absolutePath = path.resolve(filePath);
14
- if (this.seen.has(absolutePath)) {
15
- return postcss().process("", {
16
- from: undefined
17
- });
18
- }
19
- this.seen.add(absolutePath);
20
- const css = await readFileAsync(absolutePath, "utf8");
21
- return postcss([this.createImportInlinerPlugin(path.dirname(absolutePath))]).process(css, {
22
- from: absolutePath
23
- });
24
- }
25
- createImportInlinerPlugin(currentDir) {
26
- return {
27
- postcssPlugin: "css-inliner",
28
- AtRule: async atRule => {
29
- if (atRule.name !== "import") {
30
- return;
31
- }
32
- const importPath = atRule.params.replace(/^url\(|\)$|['"]/g, "").trim();
33
- let importedCSS;
34
- let from;
35
- try {
36
- if (importPath.startsWith("http://") || importPath.startsWith("https://")) {
37
- // Leave remote @import untouched
38
- return;
39
- } else {
40
- const resolvedPath = path.resolve(currentDir, importPath);
41
- if (this.seen.has(resolvedPath)) {
42
- atRule.remove();
43
- return;
44
- }
45
- this.seen.add(resolvedPath);
46
- importedCSS = await readFileAsync(resolvedPath, "utf8");
47
- from = resolvedPath;
48
- }
49
- } catch (err) {
50
- console.warn(`⚠️ Failed to inline import: ${importPath}`, err);
51
- return;
52
- }
53
- const result = await postcss([this.createImportInlinerPlugin(from ? path.dirname(from) : currentDir)]).process(importedCSS, {
54
- from
55
- });
56
- const root = postcss.parse(result.css);
57
- if (atRule.parent?.type === "atrule" && atRule.parent.name === "media") {
58
- atRule.replaceWith(root);
59
- } else {
60
- atRule.replaceWith(root.nodes);
61
- }
62
- }
63
- };
64
- }
65
- }
66
-
67
- // @ts-expect-error `postcss` requires this to treat the function as a valid plugin.
68
- CSSInliner.prototype.createImportInlinerPlugin.postcss = true;
69
-
70
- //# sourceMappingURL=CssInliner.js.map
package/CssInliner.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"names":["postcss","path","readFile","promisify","readFileAsync","CSSInliner","seen","Set","load","entryPath","result","inlineFile","css","filePath","absolutePath","resolve","has","process","from","undefined","add","createImportInlinerPlugin","dirname","currentDir","postcssPlugin","AtRule","atRule","name","importPath","params","replace","trim","importedCSS","startsWith","resolvedPath","remove","err","console","warn","root","parse","parent","type","replaceWith","nodes","prototype"],"sources":["CssInliner.ts"],"sourcesContent":["import postcss, { type AtRule } from \"postcss\";\nimport path from \"path\";\nimport { readFile } from \"fs\";\nimport { promisify } from \"util\";\n\nconst readFileAsync = promisify(readFile);\n\nexport class CSSInliner {\n private seen = new Set<string>();\n\n async load(entryPath: string): Promise<string> {\n const result = await this.inlineFile(entryPath);\n return result.css;\n }\n\n private async inlineFile(filePath: string): Promise<postcss.Result> {\n const absolutePath = path.resolve(filePath);\n\n if (this.seen.has(absolutePath)) {\n return postcss().process(\"\", { from: undefined });\n }\n\n this.seen.add(absolutePath);\n const css = await readFileAsync(absolutePath, \"utf8\");\n\n return postcss([this.createImportInlinerPlugin(path.dirname(absolutePath))]).process(css, {\n from: absolutePath\n });\n }\n\n private createImportInlinerPlugin(currentDir: string) {\n return {\n postcssPlugin: \"css-inliner\",\n AtRule: async (atRule: AtRule) => {\n if (atRule.name !== \"import\") {\n return;\n }\n\n const importPath = atRule.params.replace(/^url\\(|\\)$|['\"]/g, \"\").trim();\n\n let importedCSS: string;\n let from: string | undefined;\n\n try {\n if (importPath.startsWith(\"http://\") || importPath.startsWith(\"https://\")) {\n // Leave remote @import untouched\n return;\n } else {\n const resolvedPath = path.resolve(currentDir, importPath);\n\n if (this.seen.has(resolvedPath)) {\n atRule.remove();\n return;\n }\n\n this.seen.add(resolvedPath);\n importedCSS = await readFileAsync(resolvedPath, \"utf8\");\n from = resolvedPath;\n }\n } catch (err) {\n console.warn(`⚠️ Failed to inline import: ${importPath}`, err);\n return;\n }\n\n const result = await postcss([\n this.createImportInlinerPlugin(from ? path.dirname(from) : currentDir)\n ]).process(importedCSS, { from });\n\n const root = postcss.parse(result.css);\n\n if (atRule.parent?.type === \"atrule\" && atRule.parent.name === \"media\") {\n atRule.replaceWith(root);\n } else {\n atRule.replaceWith(root.nodes);\n }\n }\n };\n }\n}\n\n// @ts-expect-error `postcss` requires this to treat the function as a valid plugin.\nCSSInliner.prototype.createImportInlinerPlugin.postcss = true;\n"],"mappings":"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","ignoreList":[]}
package/useCss.d.ts DELETED
@@ -1 +0,0 @@
1
- export declare function useCss(cssFile?: string): Promise<string>;
package/useCss.js DELETED
@@ -1,13 +0,0 @@
1
- "use server";
2
-
3
- import path from "path";
4
- export async function useCss(cssFile) {
5
- const {
6
- CSSInliner
7
- } = await import("./CssInliner");
8
- const entryCss = cssFile ?? path.resolve(process.cwd(), "src/theme/theme.css");
9
- const inliner = new CSSInliner();
10
- return await inliner.load(entryCss);
11
- }
12
-
13
- //# sourceMappingURL=useCss.js.map
package/useCss.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"names":["path","useCss","cssFile","CSSInliner","entryCss","resolve","process","cwd","inliner","load"],"sources":["useCss.ts"],"sourcesContent":["\"use server\";\nimport path from \"path\";\n\nexport async function useCss(cssFile?: string) {\n const { CSSInliner } = await import(\"~/CssInliner\");\n const entryCss = cssFile ?? path.resolve(process.cwd(), \"src/theme/theme.css\");\n\n const inliner = new CSSInliner();\n return await inliner.load(entryCss);\n}\n"],"mappings":"AAAA,YAAY;;AACZ,OAAOA,IAAI,MAAM,MAAM;AAEvB,OAAO,eAAeC,MAAMA,CAACC,OAAgB,EAAE;EAC3C,MAAM;IAAEC;EAAW,CAAC,GAAG,MAAM,MAAM,eAAe,CAAC;EACnD,MAAMC,QAAQ,GAAGF,OAAO,IAAIF,IAAI,CAACK,OAAO,CAACC,OAAO,CAACC,GAAG,CAAC,CAAC,EAAE,qBAAqB,CAAC;EAE9E,MAAMC,OAAO,GAAG,IAAIL,UAAU,CAAC,CAAC;EAChC,OAAO,MAAMK,OAAO,CAACC,IAAI,CAACL,QAAQ,CAAC;AACvC","ignoreList":[]}