@webiny/website-builder-react 6.6.0-alpha.0 → 6.6.0-alpha.2
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/components/EditingElementRenderer/EditingElementRenderer.d.ts +2 -2
- package/components/ElementRenderer.d.ts +2 -2
- package/components/LiveElementRenderer.d.ts +2 -2
- package/createComponent.d.ts +1 -3
- package/createComponent.js +1 -32
- package/createComponent.test.js +3 -3
- package/createComponent.test.js.map +1 -1
- package/image/BackgroundImage.d.ts +33 -0
- package/image/BackgroundImage.js +61 -0
- package/image/BackgroundImage.js.map +1 -0
- package/image/Image.d.ts +29 -0
- package/image/Image.js +43 -0
- package/image/Image.js.map +1 -0
- package/image/getImageProps.d.ts +42 -0
- package/image/getImageProps.js +18 -0
- package/image/getImageProps.js.map +1 -0
- package/image/getImageProps.test.d.ts +1 -0
- package/image/getImageProps.test.js +70 -0
- package/image/getImageProps.test.js.map +1 -0
- package/image/index.d.ts +3 -0
- package/image/index.js +3 -0
- package/index.d.ts +2 -2
- package/index.js +1 -2
- package/package.json +6 -6
- package/types.d.ts +2 -4
- package/createComponent.js.map +0 -1
|
@@ -3,7 +3,7 @@ import { type DocumentElement } from "@webiny/website-builder-sdk";
|
|
|
3
3
|
interface PreviewElementRendererProps {
|
|
4
4
|
element: DocumentElement;
|
|
5
5
|
}
|
|
6
|
-
export declare const EditingElementRenderer: ((props: PreviewElementRendererProps) => React.JSX.Element | null) & {
|
|
7
|
-
|
|
6
|
+
export declare const EditingElementRenderer: ((props: PreviewElementRendererProps) => React.JSX.Element | null) & React.NamedExoticComponent<PreviewElementRendererProps> & {
|
|
7
|
+
readonly type: (props: PreviewElementRendererProps) => React.JSX.Element | null;
|
|
8
8
|
};
|
|
9
9
|
export {};
|
|
@@ -2,7 +2,7 @@ import React from "react";
|
|
|
2
2
|
interface ElementRendererProps {
|
|
3
3
|
id: string;
|
|
4
4
|
}
|
|
5
|
-
export declare const ElementRenderer: ((props: ElementRendererProps) => React.JSX.Element | null) & {
|
|
6
|
-
|
|
5
|
+
export declare const ElementRenderer: ((props: ElementRendererProps) => React.JSX.Element | null) & React.NamedExoticComponent<ElementRendererProps> & {
|
|
6
|
+
readonly type: (props: ElementRendererProps) => React.JSX.Element | null;
|
|
7
7
|
};
|
|
8
8
|
export {};
|
|
@@ -4,7 +4,7 @@ interface LiveElementRendererProps {
|
|
|
4
4
|
element: DocumentElement;
|
|
5
5
|
bindings?: DocumentElementBindings;
|
|
6
6
|
}
|
|
7
|
-
export declare const LiveElementRenderer: (({ element }: LiveElementRendererProps) => React.JSX.Element | null) & {
|
|
8
|
-
|
|
7
|
+
export declare const LiveElementRenderer: (({ element }: LiveElementRendererProps) => React.JSX.Element | null) & React.NamedExoticComponent<LiveElementRendererProps> & {
|
|
8
|
+
readonly type: ({ element }: LiveElementRendererProps) => React.JSX.Element | null;
|
|
9
9
|
};
|
|
10
10
|
export {};
|
package/createComponent.d.ts
CHANGED
|
@@ -1,3 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import type { ExtractInputs } from "./types.js";
|
|
3
|
-
export declare function createComponent<TComponent extends (props: any) => any, TInputs extends ExtractInputs<Parameters<TComponent>[0]>>(component: TComponent, manifest: ComponentManifestInput<TInputs>): Component;
|
|
1
|
+
export { createComponent } from "@webiny/website-builder-sdk";
|
package/createComponent.js
CHANGED
|
@@ -1,32 +1 @@
|
|
|
1
|
-
|
|
2
|
-
function createComponent(component, manifest) {
|
|
3
|
-
const inputs = [];
|
|
4
|
-
if (Array.isArray(manifest.inputs)) inputs.push(...manifest.inputs);
|
|
5
|
-
else {
|
|
6
|
-
const inputsObject = manifest.inputs ?? {};
|
|
7
|
-
Object.keys(inputsObject).forEach((name)=>{
|
|
8
|
-
inputs.push({
|
|
9
|
-
...inputsObject[name],
|
|
10
|
-
name
|
|
11
|
-
});
|
|
12
|
-
});
|
|
13
|
-
}
|
|
14
|
-
const acceptsChildren = manifest.acceptsChildren;
|
|
15
|
-
if (acceptsChildren) {
|
|
16
|
-
const hasChildren = inputs.some((input)=>"children" === input.name);
|
|
17
|
-
if (!hasChildren) inputs.push(createSlotInput({
|
|
18
|
-
name: "children"
|
|
19
|
-
}));
|
|
20
|
-
}
|
|
21
|
-
return {
|
|
22
|
-
component,
|
|
23
|
-
manifest: {
|
|
24
|
-
...manifest,
|
|
25
|
-
tags: manifest.tags ?? [],
|
|
26
|
-
inputs
|
|
27
|
-
}
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
export { createComponent };
|
|
31
|
-
|
|
32
|
-
//# sourceMappingURL=createComponent.js.map
|
|
1
|
+
export { createComponent } from "@webiny/website-builder-sdk";
|
package/createComponent.test.js
CHANGED
|
@@ -4,7 +4,7 @@ import { createTextInput } from "./index.js";
|
|
|
4
4
|
import { createSlotInput } from "@webiny/website-builder-sdk";
|
|
5
5
|
describe("Component Manifest", ()=>{
|
|
6
6
|
it("should support input arrays and strict input objects", ()=>{
|
|
7
|
-
const Button = (
|
|
7
|
+
const Button = ({})=>null;
|
|
8
8
|
const button1 = createComponent(Button, {
|
|
9
9
|
name: "Button",
|
|
10
10
|
inputs: [
|
|
@@ -49,7 +49,7 @@ describe("Component Manifest", ()=>{
|
|
|
49
49
|
expect(button2.manifest).toEqual(snapshot);
|
|
50
50
|
});
|
|
51
51
|
it("acceptsChildren should satisfy the `children` input requirement", ()=>{
|
|
52
|
-
const Button = (
|
|
52
|
+
const Button = ({})=>null;
|
|
53
53
|
const { manifest } = createComponent(Button, {
|
|
54
54
|
name: "Button",
|
|
55
55
|
acceptsChildren: true
|
|
@@ -70,7 +70,7 @@ describe("Component Manifest", ()=>{
|
|
|
70
70
|
});
|
|
71
71
|
});
|
|
72
72
|
it("`acceptsChildren` should work alongside other inputs", ()=>{
|
|
73
|
-
const Button = (
|
|
73
|
+
const Button = ({})=>null;
|
|
74
74
|
const button1 = createComponent(Button, {
|
|
75
75
|
name: "Button",
|
|
76
76
|
acceptsChildren: true,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createComponent.test.js","sources":["../src/createComponent.test.ts"],"sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport type { ComponentProps, ExtractInputNames } from \"~/types.js\";\nimport { createComponent } from \"~/createComponent.js\";\nimport { createTextInput } from \"~/index.js\";\nimport { createSlotInput } from \"@webiny/website-builder-sdk\";\n\n/**\n * These tests are aimed at testing TS types rather than functionality itself.\n * // TODO: figure out how to enable typechecking for a single test. Currently it only typechecks at build time.\n */\n\ndescribe(\"Component Manifest\", () => {\n it(\"should support input arrays and strict input objects\", () => {\n const Button = (
|
|
1
|
+
{"version":3,"file":"createComponent.test.js","sources":["../src/createComponent.test.ts"],"sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport type { ComponentProps, ExtractInputNames } from \"~/types.js\";\nimport { createComponent } from \"~/createComponent.js\";\nimport { createTextInput } from \"~/index.js\";\nimport { createSlotInput } from \"@webiny/website-builder-sdk\";\n\n/**\n * These tests are aimed at testing TS types rather than functionality itself.\n * // TODO: figure out how to enable typechecking for a single test. Currently it only typechecks at build time.\n */\n\ndescribe(\"Component Manifest\", () => {\n it(\"should support input arrays and strict input objects\", () => {\n const Button = ({}: ComponentProps<{ title: string; children: React.ReactNode }>) => {\n return null;\n };\n\n type Inputs = ExtractInputNames<typeof Button>;\n\n const button1 = createComponent(Button, {\n name: \"Button\",\n inputs: [\n // Passing a generic narrows down the `name` property and provides autocomplete.\n createTextInput<Inputs>({\n name: \"title\",\n label: \"Title\"\n }),\n // Skipping the generic still performs typechecks, but doesn't provide autocomplete.\n createSlotInput({\n name: \"children\"\n })\n ]\n });\n\n const button2 = createComponent(Button, {\n name: \"Button\",\n inputs: {\n title: createTextInput({\n label: \"Title\"\n }),\n children: createSlotInput({})\n }\n });\n\n const snapshot = {\n name: \"Button\",\n tags: [],\n inputs: [\n {\n type: \"text\",\n label: \"Title\",\n renderer: \"Webiny/Input\",\n name: \"title\"\n },\n {\n type: \"slot\",\n renderer: \"Webiny/Slot\",\n name: \"children\",\n list: true,\n defaultValue: []\n }\n ]\n };\n\n expect(button1.manifest).toEqual(snapshot);\n expect(button2.manifest).toEqual(snapshot);\n });\n\n it(\"acceptsChildren should satisfy the `children` input requirement\", () => {\n const Button = ({}: ComponentProps<{ children: React.ReactNode }>) => {\n return null;\n };\n\n const { manifest } = createComponent(Button, {\n name: \"Button\",\n acceptsChildren: true\n });\n\n expect(manifest).toEqual({\n name: \"Button\",\n acceptsChildren: true,\n tags: [],\n inputs: [\n {\n type: \"slot\",\n list: true,\n renderer: \"Webiny/Slot\",\n name: \"children\",\n defaultValue: []\n }\n ]\n });\n });\n\n it(\"`acceptsChildren` should work alongside other inputs\", () => {\n const Button = ({}: ComponentProps<{ title: string; children: React.ReactNode }>) => {\n return null;\n };\n\n // Inputs as array\n const button1 = createComponent(Button, {\n name: \"Button\",\n acceptsChildren: true,\n inputs: [\n createTextInput({\n name: \"title\",\n label: \"Title\"\n })\n ]\n });\n\n // Inputs as object\n const button2 = createComponent(Button, {\n name: \"Button\",\n acceptsChildren: true,\n inputs: {\n title: createTextInput({\n label: \"Title\"\n })\n }\n });\n\n // Both must produce the same component manifest\n const snapshot = {\n name: \"Button\",\n acceptsChildren: true,\n tags: [],\n inputs: [\n {\n type: \"text\",\n renderer: \"Webiny/Input\",\n name: \"title\",\n label: \"Title\"\n },\n {\n type: \"slot\",\n renderer: \"Webiny/Slot\",\n name: \"children\",\n list: true,\n defaultValue: []\n }\n ]\n };\n\n expect(button1.manifest).toEqual(snapshot);\n expect(button2.manifest).toEqual(snapshot);\n });\n});\n"],"names":["describe","it","Button","button1","createComponent","createTextInput","createSlotInput","button2","snapshot","expect","manifest"],"mappings":";;;;AAWAA,SAAS,sBAAsB;IAC3BC,GAAG,wDAAwD;QACvD,MAAMC,SAAS,CAAC,EAAgE,GACrE;QAKX,MAAMC,UAAUC,gBAAgBF,QAAQ;YACpC,MAAM;YACN,QAAQ;gBAEJG,gBAAwB;oBACpB,MAAM;oBACN,OAAO;gBACX;gBAEAC,gBAAgB;oBACZ,MAAM;gBACV;aACH;QACL;QAEA,MAAMC,UAAUH,gBAAgBF,QAAQ;YACpC,MAAM;YACN,QAAQ;gBACJ,OAAOG,gBAAgB;oBACnB,OAAO;gBACX;gBACA,UAAUC,gBAAgB,CAAC;YAC/B;QACJ;QAEA,MAAME,WAAW;YACb,MAAM;YACN,MAAM,EAAE;YACR,QAAQ;gBACJ;oBACI,MAAM;oBACN,OAAO;oBACP,UAAU;oBACV,MAAM;gBACV;gBACA;oBACI,MAAM;oBACN,UAAU;oBACV,MAAM;oBACN,MAAM;oBACN,cAAc,EAAE;gBACpB;aACH;QACL;QAEAC,OAAON,QAAQ,QAAQ,EAAE,OAAO,CAACK;QACjCC,OAAOF,QAAQ,QAAQ,EAAE,OAAO,CAACC;IACrC;IAEAP,GAAG,mEAAmE;QAClE,MAAMC,SAAS,CAAC,EAAiD,GACtD;QAGX,MAAM,EAAEQ,QAAQ,EAAE,GAAGN,gBAAgBF,QAAQ;YACzC,MAAM;YACN,iBAAiB;QACrB;QAEAO,OAAOC,UAAU,OAAO,CAAC;YACrB,MAAM;YACN,iBAAiB;YACjB,MAAM,EAAE;YACR,QAAQ;gBACJ;oBACI,MAAM;oBACN,MAAM;oBACN,UAAU;oBACV,MAAM;oBACN,cAAc,EAAE;gBACpB;aACH;QACL;IACJ;IAEAT,GAAG,wDAAwD;QACvD,MAAMC,SAAS,CAAC,EAAgE,GACrE;QAIX,MAAMC,UAAUC,gBAAgBF,QAAQ;YACpC,MAAM;YACN,iBAAiB;YACjB,QAAQ;gBACJG,gBAAgB;oBACZ,MAAM;oBACN,OAAO;gBACX;aACH;QACL;QAGA,MAAME,UAAUH,gBAAgBF,QAAQ;YACpC,MAAM;YACN,iBAAiB;YACjB,QAAQ;gBACJ,OAAOG,gBAAgB;oBACnB,OAAO;gBACX;YACJ;QACJ;QAGA,MAAMG,WAAW;YACb,MAAM;YACN,iBAAiB;YACjB,MAAM,EAAE;YACR,QAAQ;gBACJ;oBACI,MAAM;oBACN,UAAU;oBACV,MAAM;oBACN,OAAO;gBACX;gBACA;oBACI,MAAM;oBACN,UAAU;oBACV,MAAM;oBACN,MAAM;oBACN,cAAc,EAAE;gBACpB;aACH;QACL;QAEAC,OAAON,QAAQ,QAAQ,EAAE,OAAO,CAACK;QACjCC,OAAOF,QAAQ,QAAQ,EAAE,OAAO,CAACC;IACrC;AACJ"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { type Asset } from "@webiny/website-builder-sdk";
|
|
3
|
+
export interface BackgroundImageProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "style"> {
|
|
4
|
+
/** The image value (unified `Asset` or a legacy value — both accepted). */
|
|
5
|
+
image: Asset;
|
|
6
|
+
/** Content rendered on top of the background (auto-stacked above the image). */
|
|
7
|
+
children?: React.ReactNode;
|
|
8
|
+
/** Class applied to the wrapper element. */
|
|
9
|
+
className?: string;
|
|
10
|
+
/** Styles merged into the wrapper. Give it a height (e.g. `minHeight`). */
|
|
11
|
+
style?: React.CSSProperties;
|
|
12
|
+
/** Class applied to the background `<img>`. */
|
|
13
|
+
imgClassName?: string;
|
|
14
|
+
/** Explicit alt text; falls back to the image's stored alt. Empty = decorative. */
|
|
15
|
+
alt?: string;
|
|
16
|
+
/** Delivery width requested for the background image. Defaults to 1920. */
|
|
17
|
+
width?: number;
|
|
18
|
+
/**
|
|
19
|
+
* Responsive URL builder — e.g. `({ src, width }) => \`${src}?width=${width}&format=auto\``.
|
|
20
|
+
* When provided, a `srcSet` is generated from `widths`.
|
|
21
|
+
*/
|
|
22
|
+
loader?: (params: {
|
|
23
|
+
src: string;
|
|
24
|
+
width: number;
|
|
25
|
+
}) => string;
|
|
26
|
+
/** Candidate widths for the generated `srcSet`. */
|
|
27
|
+
widths?: number[];
|
|
28
|
+
/** The `sizes` attribute (defaults to `100vw`, since backgrounds are usually full-bleed). */
|
|
29
|
+
sizes?: string;
|
|
30
|
+
/** Native loading strategy for the background image. */
|
|
31
|
+
loading?: "eager" | "lazy";
|
|
32
|
+
}
|
|
33
|
+
export declare function BackgroundImage({ image, children, className, style, imgClassName, alt, width, loader, widths, sizes, loading, ...rest }: BackgroundImageProps): React.JSX.Element;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import react from "react";
|
|
2
|
+
import { normalizeToAsset } from "@webiny/website-builder-sdk";
|
|
3
|
+
const DEFAULT_WIDTHS = [
|
|
4
|
+
640,
|
|
5
|
+
750,
|
|
6
|
+
828,
|
|
7
|
+
1080,
|
|
8
|
+
1200,
|
|
9
|
+
1920,
|
|
10
|
+
2048
|
|
11
|
+
];
|
|
12
|
+
function BackgroundImage({ image, children, className, style, imgClassName, alt, width = 1920, loader, widths = DEFAULT_WIDTHS, sizes = "100vw", loading, ...rest }) {
|
|
13
|
+
const asset = normalizeToAsset(image);
|
|
14
|
+
const src = asset?.src ?? "";
|
|
15
|
+
const focalPoint = asset?.image?.focalPoint ?? {
|
|
16
|
+
x: 0.5,
|
|
17
|
+
y: 0.5
|
|
18
|
+
};
|
|
19
|
+
const resolvedAlt = alt ?? asset?.image?.alt ?? "";
|
|
20
|
+
const resolvedSrc = loader ? loader({
|
|
21
|
+
src,
|
|
22
|
+
width
|
|
23
|
+
}) : src;
|
|
24
|
+
const srcSet = loader ? widths.map((w)=>`${loader({
|
|
25
|
+
src,
|
|
26
|
+
width: w
|
|
27
|
+
})} ${w}w`).join(", ") || void 0 : void 0;
|
|
28
|
+
return /*#__PURE__*/ react.createElement("div", {
|
|
29
|
+
...rest,
|
|
30
|
+
className: className,
|
|
31
|
+
style: {
|
|
32
|
+
position: "relative",
|
|
33
|
+
overflow: "hidden",
|
|
34
|
+
...style
|
|
35
|
+
}
|
|
36
|
+
}, /*#__PURE__*/ react.createElement("img", {
|
|
37
|
+
className: imgClassName,
|
|
38
|
+
src: resolvedSrc,
|
|
39
|
+
srcSet: srcSet,
|
|
40
|
+
sizes: srcSet ? sizes : void 0,
|
|
41
|
+
alt: resolvedAlt,
|
|
42
|
+
"aria-hidden": "" === resolvedAlt ? true : void 0,
|
|
43
|
+
loading: loading,
|
|
44
|
+
style: {
|
|
45
|
+
position: "absolute",
|
|
46
|
+
inset: 0,
|
|
47
|
+
width: "100%",
|
|
48
|
+
height: "100%",
|
|
49
|
+
objectFit: "cover",
|
|
50
|
+
objectPosition: `${100 * focalPoint.x}% ${100 * focalPoint.y}%`
|
|
51
|
+
}
|
|
52
|
+
}), null != children ? /*#__PURE__*/ react.createElement("div", {
|
|
53
|
+
style: {
|
|
54
|
+
position: "relative",
|
|
55
|
+
zIndex: 1
|
|
56
|
+
}
|
|
57
|
+
}, children) : null);
|
|
58
|
+
}
|
|
59
|
+
export { BackgroundImage };
|
|
60
|
+
|
|
61
|
+
//# sourceMappingURL=BackgroundImage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image/BackgroundImage.js","sources":["../../src/image/BackgroundImage.tsx"],"sourcesContent":["import React from \"react\";\nimport { normalizeToAsset, type Asset } from \"@webiny/website-builder-sdk\";\n\nexport interface BackgroundImageProps extends Omit<React.HTMLAttributes<HTMLDivElement>, \"style\"> {\n /** The image value (unified `Asset` or a legacy value — both accepted). */\n image: Asset;\n /** Content rendered on top of the background (auto-stacked above the image). */\n children?: React.ReactNode;\n /** Class applied to the wrapper element. */\n className?: string;\n /** Styles merged into the wrapper. Give it a height (e.g. `minHeight`). */\n style?: React.CSSProperties;\n /** Class applied to the background `<img>`. */\n imgClassName?: string;\n /** Explicit alt text; falls back to the image's stored alt. Empty = decorative. */\n alt?: string;\n /** Delivery width requested for the background image. Defaults to 1920. */\n width?: number;\n /**\n * Responsive URL builder — e.g. `({ src, width }) => \\`${src}?width=${width}&format=auto\\``.\n * When provided, a `srcSet` is generated from `widths`.\n */\n loader?: (params: { src: string; width: number }) => string;\n /** Candidate widths for the generated `srcSet`. */\n widths?: number[];\n /** The `sizes` attribute (defaults to `100vw`, since backgrounds are usually full-bleed). */\n sizes?: string;\n /** Native loading strategy for the background image. */\n loading?: \"eager\" | \"lazy\";\n}\n\nconst DEFAULT_WIDTHS = [640, 750, 828, 1080, 1200, 1920, 2048];\n\nexport function BackgroundImage({\n image,\n children,\n className,\n style,\n imgClassName,\n alt,\n width = 1920,\n loader,\n widths = DEFAULT_WIDTHS,\n sizes = \"100vw\",\n loading,\n ...rest\n}: BackgroundImageProps) {\n const asset = normalizeToAsset(image);\n const src = asset?.src ?? \"\";\n const focalPoint = asset?.image?.focalPoint ?? { x: 0.5, y: 0.5 };\n const resolvedAlt = alt ?? asset?.image?.alt ?? \"\";\n\n const resolvedSrc = loader ? loader({ src, width }) : src;\n const srcSet = loader\n ? widths.map(w => `${loader({ src, width: w })} ${w}w`).join(\", \") || undefined\n : undefined;\n\n return (\n <div\n {...rest}\n className={className}\n style={{ position: \"relative\", overflow: \"hidden\", ...style }}\n >\n <img\n className={imgClassName}\n src={resolvedSrc}\n srcSet={srcSet}\n sizes={srcSet ? sizes : undefined}\n alt={resolvedAlt}\n aria-hidden={resolvedAlt === \"\" ? true : undefined}\n loading={loading}\n style={{\n position: \"absolute\",\n inset: 0,\n width: \"100%\",\n height: \"100%\",\n objectFit: \"cover\",\n objectPosition: `${focalPoint.x * 100}% ${focalPoint.y * 100}%`\n }}\n />\n {children != null ? (\n <div style={{ position: \"relative\", zIndex: 1 }}>{children}</div>\n ) : null}\n </div>\n );\n}\n"],"names":["DEFAULT_WIDTHS","BackgroundImage","image","children","className","style","imgClassName","alt","width","loader","widths","sizes","loading","rest","asset","normalizeToAsset","src","focalPoint","resolvedAlt","resolvedSrc","srcSet","w","undefined"],"mappings":";;AA+BA,MAAMA,iBAAiB;IAAC;IAAK;IAAK;IAAK;IAAM;IAAM;IAAM;CAAK;AAEvD,SAASC,gBAAgB,EAC5BC,KAAK,EACLC,QAAQ,EACRC,SAAS,EACTC,KAAK,EACLC,YAAY,EACZC,GAAG,EACHC,QAAQ,IAAI,EACZC,MAAM,EACNC,SAASV,cAAc,EACvBW,QAAQ,OAAO,EACfC,OAAO,EACP,GAAGC,MACgB;IACnB,MAAMC,QAAQC,iBAAiBb;IAC/B,MAAMc,MAAMF,OAAO,OAAO;IAC1B,MAAMG,aAAaH,OAAO,OAAO,cAAc;QAAE,GAAG;QAAK,GAAG;IAAI;IAChE,MAAMI,cAAcX,OAAOO,OAAO,OAAO,OAAO;IAEhD,MAAMK,cAAcV,SAASA,OAAO;QAAEO;QAAKR;IAAM,KAAKQ;IACtD,MAAMI,SAASX,SACTC,OAAO,GAAG,CAACW,CAAAA,IAAK,GAAGZ,OAAO;YAAEO;YAAK,OAAOK;QAAE,GAAG,CAAC,EAAEA,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,SAASC,SACpEA;IAEN,OAAO,WAAP,GACI,oBAAC;QACI,GAAGT,IAAI;QACR,WAAWT;QACX,OAAO;YAAE,UAAU;YAAY,UAAU;YAAU,GAAGC,KAAK;QAAC;qBAE5D,oBAAC;QACG,WAAWC;QACX,KAAKa;QACL,QAAQC;QACR,OAAOA,SAAST,QAAQW;QACxB,KAAKJ;QACL,eAAaA,AAAgB,OAAhBA,cAAqB,OAAOI;QACzC,SAASV;QACT,OAAO;YACH,UAAU;YACV,OAAO;YACP,OAAO;YACP,QAAQ;YACR,WAAW;YACX,gBAAgB,GAAGK,AAAe,MAAfA,WAAW,CAAC,CAAO,EAAE,EAAEA,AAAe,MAAfA,WAAW,CAAC,CAAO,CAAC,CAAC;QACnE;QAEHd,AAAY,QAAZA,WAAmB,WAAP,GACT,oBAAC;QAAI,OAAO;YAAE,UAAU;YAAY,QAAQ;QAAE;OAAIA,YAClD;AAGhB"}
|
package/image/Image.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { AspectRatioInput, Asset } from "@webiny/website-builder-sdk";
|
|
3
|
+
export interface ImageComponentProps extends Omit<React.ImgHTMLAttributes<HTMLImageElement>, "src" | "width" | "height" | "style" | "alt"> {
|
|
4
|
+
image: Asset;
|
|
5
|
+
/** Target aspect ratio (e.g. `16 / 9` or `{ width, height }`). Omit for the crop's own ratio. */
|
|
6
|
+
aspectRatio?: AspectRatioInput;
|
|
7
|
+
/** Explicit alt text; falls back to the image's stored alt. */
|
|
8
|
+
alt?: string;
|
|
9
|
+
/** Class applied to the wrapper element. */
|
|
10
|
+
className?: string;
|
|
11
|
+
/** Class applied to the `<img>` element. */
|
|
12
|
+
imgClassName?: string;
|
|
13
|
+
/** Extra styles merged into the wrapper (e.g. `maxWidth`). */
|
|
14
|
+
style?: React.CSSProperties;
|
|
15
|
+
/**
|
|
16
|
+
* Optional responsive URL builder — e.g. `({ src, width }) => \`${src}?width=${width}\``.
|
|
17
|
+
* When provided, a `srcSet` is generated from `widths`. This is also the seam for a
|
|
18
|
+
* future server/CDN transform (crop params can be appended here).
|
|
19
|
+
*/
|
|
20
|
+
loader?: (params: {
|
|
21
|
+
src: string;
|
|
22
|
+
width: number;
|
|
23
|
+
}) => string;
|
|
24
|
+
/** Candidate widths for the generated `srcSet` (defaults to a common set). */
|
|
25
|
+
widths?: number[];
|
|
26
|
+
/** The `sizes` attribute for responsive selection. */
|
|
27
|
+
sizes?: string;
|
|
28
|
+
}
|
|
29
|
+
export declare function Image({ image, aspectRatio, alt, className, imgClassName, style, loader, widths, sizes, ...imgProps }: ImageComponentProps): React.JSX.Element;
|
package/image/Image.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import react from "react";
|
|
2
|
+
import { getImageProps } from "./getImageProps.js";
|
|
3
|
+
const DEFAULT_WIDTHS = [
|
|
4
|
+
640,
|
|
5
|
+
750,
|
|
6
|
+
828,
|
|
7
|
+
1080,
|
|
8
|
+
1200,
|
|
9
|
+
1920,
|
|
10
|
+
2048
|
|
11
|
+
];
|
|
12
|
+
function Image({ image, aspectRatio, alt, className, imgClassName, style, loader, widths = DEFAULT_WIDTHS, sizes, ...imgProps }) {
|
|
13
|
+
const { style: containerStyle, imgStyle, src, alt: resolvedAlt, width } = getImageProps(image, {
|
|
14
|
+
aspectRatio,
|
|
15
|
+
alt
|
|
16
|
+
});
|
|
17
|
+
const srcSet = loader ? widths.filter((w)=>!width || w <= width).map((w)=>`${loader({
|
|
18
|
+
src,
|
|
19
|
+
width: w
|
|
20
|
+
})} ${w}w`).join(", ") || void 0 : void 0;
|
|
21
|
+
const resolvedSrc = loader ? loader({
|
|
22
|
+
src,
|
|
23
|
+
width: width || widths[widths.length - 1]
|
|
24
|
+
}) : src;
|
|
25
|
+
return /*#__PURE__*/ react.createElement("div", {
|
|
26
|
+
className: className,
|
|
27
|
+
style: {
|
|
28
|
+
...containerStyle,
|
|
29
|
+
...style
|
|
30
|
+
}
|
|
31
|
+
}, /*#__PURE__*/ react.createElement("img", {
|
|
32
|
+
...imgProps,
|
|
33
|
+
className: imgClassName,
|
|
34
|
+
src: resolvedSrc,
|
|
35
|
+
srcSet: srcSet,
|
|
36
|
+
sizes: sizes,
|
|
37
|
+
alt: resolvedAlt,
|
|
38
|
+
style: imgStyle
|
|
39
|
+
}));
|
|
40
|
+
}
|
|
41
|
+
export { Image };
|
|
42
|
+
|
|
43
|
+
//# sourceMappingURL=Image.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image/Image.js","sources":["../../src/image/Image.tsx"],"sourcesContent":["import React from \"react\";\nimport type { AspectRatioInput, Asset } from \"@webiny/website-builder-sdk\";\nimport { getImageProps } from \"./getImageProps.js\";\n\nexport interface ImageComponentProps extends Omit<\n React.ImgHTMLAttributes<HTMLImageElement>,\n \"src\" | \"width\" | \"height\" | \"style\" | \"alt\"\n> {\n image: Asset;\n /** Target aspect ratio (e.g. `16 / 9` or `{ width, height }`). Omit for the crop's own ratio. */\n aspectRatio?: AspectRatioInput;\n /** Explicit alt text; falls back to the image's stored alt. */\n alt?: string;\n /** Class applied to the wrapper element. */\n className?: string;\n /** Class applied to the `<img>` element. */\n imgClassName?: string;\n /** Extra styles merged into the wrapper (e.g. `maxWidth`). */\n style?: React.CSSProperties;\n /**\n * Optional responsive URL builder — e.g. `({ src, width }) => \\`${src}?width=${width}\\``.\n * When provided, a `srcSet` is generated from `widths`. This is also the seam for a\n * future server/CDN transform (crop params can be appended here).\n */\n loader?: (params: { src: string; width: number }) => string;\n /** Candidate widths for the generated `srcSet` (defaults to a common set). */\n widths?: number[];\n /** The `sizes` attribute for responsive selection. */\n sizes?: string;\n}\n\nconst DEFAULT_WIDTHS = [640, 750, 828, 1080, 1200, 1920, 2048];\n\nexport function Image({\n image,\n aspectRatio,\n alt,\n className,\n imgClassName,\n style,\n loader,\n widths = DEFAULT_WIDTHS,\n sizes,\n ...imgProps\n}: ImageComponentProps) {\n const {\n style: containerStyle,\n imgStyle,\n src,\n alt: resolvedAlt,\n width\n } = getImageProps(image, { aspectRatio, alt });\n\n const srcSet = loader\n ? widths\n .filter(w => !width || w <= width)\n .map(w => `${loader({ src, width: w })} ${w}w`)\n .join(\", \") || undefined\n : undefined;\n\n const resolvedSrc = loader ? loader({ src, width: width || widths[widths.length - 1] }) : src;\n\n return (\n <div className={className} style={{ ...containerStyle, ...style }}>\n <img\n {...imgProps}\n className={imgClassName}\n src={resolvedSrc}\n srcSet={srcSet}\n sizes={sizes}\n alt={resolvedAlt}\n style={imgStyle}\n />\n </div>\n );\n}\n"],"names":["DEFAULT_WIDTHS","Image","image","aspectRatio","alt","className","imgClassName","style","loader","widths","sizes","imgProps","containerStyle","imgStyle","src","resolvedAlt","width","getImageProps","srcSet","w","undefined","resolvedSrc"],"mappings":";;AA+BA,MAAMA,iBAAiB;IAAC;IAAK;IAAK;IAAK;IAAM;IAAM;IAAM;CAAK;AAEvD,SAASC,MAAM,EAClBC,KAAK,EACLC,WAAW,EACXC,GAAG,EACHC,SAAS,EACTC,YAAY,EACZC,KAAK,EACLC,MAAM,EACNC,SAAST,cAAc,EACvBU,KAAK,EACL,GAAGC,UACe;IAClB,MAAM,EACF,OAAOC,cAAc,EACrBC,QAAQ,EACRC,GAAG,EACH,KAAKC,WAAW,EAChBC,KAAK,EACR,GAAGC,cAAcf,OAAO;QAAEC;QAAaC;IAAI;IAE5C,MAAMc,SAASV,SACTC,OACK,MAAM,CAACU,CAAAA,IAAK,CAACH,SAASG,KAAKH,OAC3B,GAAG,CAACG,CAAAA,IAAK,GAAGX,OAAO;YAAEM;YAAK,OAAOK;QAAE,GAAG,CAAC,EAAEA,EAAE,CAAC,CAAC,EAC7C,IAAI,CAAC,SAASC,SACnBA;IAEN,MAAMC,cAAcb,SAASA,OAAO;QAAEM;QAAK,OAAOE,SAASP,MAAM,CAACA,OAAO,MAAM,GAAG,EAAE;IAAC,KAAKK;IAE1F,OAAO,WAAP,GACI,oBAAC;QAAI,WAAWT;QAAW,OAAO;YAAE,GAAGO,cAAc;YAAE,GAAGL,KAAK;QAAC;qBAC5D,oBAAC;QACI,GAAGI,QAAQ;QACZ,WAAWL;QACX,KAAKe;QACL,QAAQH;QACR,OAAOR;QACP,KAAKK;QACL,OAAOF;;AAIvB"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { CSSProperties } from "react";
|
|
2
|
+
import { type AspectRatioInput, type Asset } from "@webiny/website-builder-sdk";
|
|
3
|
+
export interface ImageProps {
|
|
4
|
+
/** Wrapper style: an aspect-ratio box that clips overflow. Spread onto a container. */
|
|
5
|
+
style: CSSProperties;
|
|
6
|
+
/** Image style: absolutely positioned to reveal exactly the cropped/focused region. */
|
|
7
|
+
imgStyle: CSSProperties;
|
|
8
|
+
/** The image URL. */
|
|
9
|
+
src: string;
|
|
10
|
+
/** Resolved alt text (explicit override, else the image's stored alt, else ""). */
|
|
11
|
+
alt: string;
|
|
12
|
+
/** Intrinsic (original) pixel dimensions of the asset. */
|
|
13
|
+
width: number;
|
|
14
|
+
height: number;
|
|
15
|
+
}
|
|
16
|
+
export interface ImageValue {
|
|
17
|
+
id: string;
|
|
18
|
+
name: string;
|
|
19
|
+
size: number;
|
|
20
|
+
mimeType: string;
|
|
21
|
+
src: string;
|
|
22
|
+
width: number;
|
|
23
|
+
height: number;
|
|
24
|
+
}
|
|
25
|
+
export interface GetImagePropsOptions {
|
|
26
|
+
/** Target aspect ratio. Omit to render at the crop's own aspect ratio. */
|
|
27
|
+
aspectRatio?: AspectRatioInput;
|
|
28
|
+
/** Explicit alt text; falls back to the image's stored `image.alt`. */
|
|
29
|
+
alt?: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Compute the props needed to render a Webiny image honoring its crop + focal point,
|
|
33
|
+
* using pure CSS (no image backend). Works with a plain `<img>`, SSR, and static
|
|
34
|
+
* export. Spread `style` onto a wrapper element and `imgStyle` onto the `<img>`.
|
|
35
|
+
*
|
|
36
|
+
* Accepts either the unified {@link Asset} shape or a legacy
|
|
37
|
+
* `ImageValue` (existing page snapshots) — both are normalized transparently.
|
|
38
|
+
*
|
|
39
|
+
* This is the escape hatch for custom rendering; most consumers can use the
|
|
40
|
+
* `<Image>` component instead.
|
|
41
|
+
*/
|
|
42
|
+
export declare function getImageProps(input: Asset | ImageValue, options?: GetImagePropsOptions): ImageProps;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { getAssetImageRenderData, normalizeToAsset } from "@webiny/website-builder-sdk";
|
|
2
|
+
function getImageProps(input, options = {}) {
|
|
3
|
+
const asset = normalizeToAsset(input);
|
|
4
|
+
const data = getAssetImageRenderData({
|
|
5
|
+
image: asset?.image
|
|
6
|
+
}, options.aspectRatio);
|
|
7
|
+
return {
|
|
8
|
+
style: data.container,
|
|
9
|
+
imgStyle: data.image,
|
|
10
|
+
src: asset?.src ?? "",
|
|
11
|
+
alt: options.alt ?? asset?.image?.alt ?? "",
|
|
12
|
+
width: data.intrinsicWidth,
|
|
13
|
+
height: data.intrinsicHeight
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export { getImageProps };
|
|
17
|
+
|
|
18
|
+
//# sourceMappingURL=getImageProps.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image/getImageProps.js","sources":["../../src/image/getImageProps.ts"],"sourcesContent":["import type { CSSProperties } from \"react\";\nimport {\n getAssetImageRenderData,\n normalizeToAsset,\n type AspectRatioInput,\n type Asset\n} from \"@webiny/website-builder-sdk\";\n\nexport interface ImageProps {\n /** Wrapper style: an aspect-ratio box that clips overflow. Spread onto a container. */\n style: CSSProperties;\n /** Image style: absolutely positioned to reveal exactly the cropped/focused region. */\n imgStyle: CSSProperties;\n /** The image URL. */\n src: string;\n /** Resolved alt text (explicit override, else the image's stored alt, else \"\"). */\n alt: string;\n /** Intrinsic (original) pixel dimensions of the asset. */\n width: number;\n height: number;\n}\n\nexport interface ImageValue {\n id: string;\n name: string;\n size: number;\n mimeType: string; // not \"type\"\n src: string;\n width: number; // top-level, not nested in image\n height: number; // top-level\n}\n\nexport interface GetImagePropsOptions {\n /** Target aspect ratio. Omit to render at the crop's own aspect ratio. */\n aspectRatio?: AspectRatioInput;\n /** Explicit alt text; falls back to the image's stored `image.alt`. */\n alt?: string;\n}\n\n/**\n * Compute the props needed to render a Webiny image honoring its crop + focal point,\n * using pure CSS (no image backend). Works with a plain `<img>`, SSR, and static\n * export. Spread `style` onto a wrapper element and `imgStyle` onto the `<img>`.\n *\n * Accepts either the unified {@link Asset} shape or a legacy\n * `ImageValue` (existing page snapshots) — both are normalized transparently.\n *\n * This is the escape hatch for custom rendering; most consumers can use the\n * `<Image>` component instead.\n */\nexport function getImageProps(\n input: Asset | ImageValue,\n options: GetImagePropsOptions = {}\n): ImageProps {\n const asset = normalizeToAsset(input);\n const data = getAssetImageRenderData({ image: asset?.image }, options.aspectRatio);\n\n return {\n style: data.container,\n imgStyle: data.image,\n src: asset?.src ?? \"\",\n alt: options.alt ?? asset?.image?.alt ?? \"\",\n width: data.intrinsicWidth,\n height: data.intrinsicHeight\n };\n}\n"],"names":["getImageProps","input","options","asset","normalizeToAsset","data","getAssetImageRenderData"],"mappings":";AAkDO,SAASA,cACZC,KAAyB,EACzBC,UAAgC,CAAC,CAAC;IAElC,MAAMC,QAAQC,iBAAiBH;IAC/B,MAAMI,OAAOC,wBAAwB;QAAE,OAAOH,OAAO;IAAM,GAAGD,QAAQ,WAAW;IAEjF,OAAO;QACH,OAAOG,KAAK,SAAS;QACrB,UAAUA,KAAK,KAAK;QACpB,KAAKF,OAAO,OAAO;QACnB,KAAKD,QAAQ,GAAG,IAAIC,OAAO,OAAO,OAAO;QACzC,OAAOE,KAAK,cAAc;QAC1B,QAAQA,KAAK,eAAe;IAChC;AACJ"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { getImageProps } from "./getImageProps.js";
|
|
3
|
+
const asset = (overrides = {})=>({
|
|
4
|
+
id: "1",
|
|
5
|
+
name: "photo.jpg",
|
|
6
|
+
size: 1234,
|
|
7
|
+
type: "image/jpeg",
|
|
8
|
+
src: "https://cdn.test/photo.jpg",
|
|
9
|
+
url: "https://cdn.test/photo.jpg",
|
|
10
|
+
image: {
|
|
11
|
+
width: 1600,
|
|
12
|
+
height: 900
|
|
13
|
+
},
|
|
14
|
+
...overrides
|
|
15
|
+
});
|
|
16
|
+
describe("getImageProps", ()=>{
|
|
17
|
+
it("returns wrapper + image styles and passes through src and dimensions", ()=>{
|
|
18
|
+
const props = getImageProps(asset());
|
|
19
|
+
expect(props.src).toBe("https://cdn.test/photo.jpg");
|
|
20
|
+
expect(props.width).toBe(1600);
|
|
21
|
+
expect(props.height).toBe(900);
|
|
22
|
+
expect(props.style.overflow).toBe("hidden");
|
|
23
|
+
expect(props.style.position).toBe("relative");
|
|
24
|
+
expect(props.imgStyle.position).toBe("absolute");
|
|
25
|
+
});
|
|
26
|
+
it("resolves alt from the explicit option first", ()=>{
|
|
27
|
+
const props = getImageProps(asset({
|
|
28
|
+
image: {
|
|
29
|
+
alt: "stored alt"
|
|
30
|
+
}
|
|
31
|
+
}), {
|
|
32
|
+
alt: "explicit alt"
|
|
33
|
+
});
|
|
34
|
+
expect(props.alt).toBe("explicit alt");
|
|
35
|
+
});
|
|
36
|
+
it("falls back to the image's stored alt", ()=>{
|
|
37
|
+
const props = getImageProps(asset({
|
|
38
|
+
image: {
|
|
39
|
+
alt: "stored alt"
|
|
40
|
+
}
|
|
41
|
+
}));
|
|
42
|
+
expect(props.alt).toBe("stored alt");
|
|
43
|
+
});
|
|
44
|
+
it("defaults alt to an empty string", ()=>{
|
|
45
|
+
expect(getImageProps(asset()).alt).toBe("");
|
|
46
|
+
});
|
|
47
|
+
it("produces a wrapper with the requested aspect ratio", ()=>{
|
|
48
|
+
const props = getImageProps(asset(), {
|
|
49
|
+
aspectRatio: 1
|
|
50
|
+
});
|
|
51
|
+
expect(props.style.aspectRatio).toBe("1");
|
|
52
|
+
});
|
|
53
|
+
it("offsets the image to reveal a focal-point-shifted crop region", ()=>{
|
|
54
|
+
const props = getImageProps(asset({
|
|
55
|
+
image: {
|
|
56
|
+
width: 1600,
|
|
57
|
+
height: 900,
|
|
58
|
+
focalPoint: {
|
|
59
|
+
x: 0.9,
|
|
60
|
+
y: 0.5
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}), {
|
|
64
|
+
aspectRatio: 1
|
|
65
|
+
});
|
|
66
|
+
expect(parseFloat(props.imgStyle.left)).toBeLessThan(0);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
//# sourceMappingURL=getImageProps.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image/getImageProps.test.js","sources":["../../src/image/getImageProps.test.ts"],"sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport { getImageProps } from \"./getImageProps.js\";\nimport type { Asset } from \"@webiny/website-builder-sdk\";\n\nconst asset = (overrides: Partial<Asset> = {}): Asset => ({\n id: \"1\",\n name: \"photo.jpg\",\n size: 1234,\n type: \"image/jpeg\",\n src: \"https://cdn.test/photo.jpg\",\n url: \"https://cdn.test/photo.jpg\",\n image: { width: 1600, height: 900 },\n ...overrides\n});\n\ndescribe(\"getImageProps\", () => {\n it(\"returns wrapper + image styles and passes through src and dimensions\", () => {\n const props = getImageProps(asset());\n expect(props.src).toBe(\"https://cdn.test/photo.jpg\");\n expect(props.width).toBe(1600);\n expect(props.height).toBe(900);\n expect(props.style.overflow).toBe(\"hidden\");\n expect(props.style.position).toBe(\"relative\");\n expect(props.imgStyle.position).toBe(\"absolute\");\n });\n\n it(\"resolves alt from the explicit option first\", () => {\n const props = getImageProps(asset({ image: { alt: \"stored alt\" } }), {\n alt: \"explicit alt\"\n });\n expect(props.alt).toBe(\"explicit alt\");\n });\n\n it(\"falls back to the image's stored alt\", () => {\n const props = getImageProps(asset({ image: { alt: \"stored alt\" } }));\n expect(props.alt).toBe(\"stored alt\");\n });\n\n it(\"defaults alt to an empty string\", () => {\n expect(getImageProps(asset()).alt).toBe(\"\");\n });\n\n it(\"produces a wrapper with the requested aspect ratio\", () => {\n const props = getImageProps(asset(), { aspectRatio: 1 });\n expect(props.style.aspectRatio).toBe(\"1\");\n });\n\n it(\"offsets the image to reveal a focal-point-shifted crop region\", () => {\n const props = getImageProps(\n asset({\n image: {\n width: 1600,\n height: 900,\n focalPoint: { x: 0.9, y: 0.5 }\n }\n }),\n { aspectRatio: 1 }\n );\n expect(parseFloat(props.imgStyle.left as string)).toBeLessThan(0);\n });\n});\n"],"names":["asset","overrides","describe","it","props","getImageProps","expect","parseFloat"],"mappings":";;AAIA,MAAMA,QAAQ,CAACC,YAA4B,CAAC,CAAC,GAAa;QACtD,IAAI;QACJ,MAAM;QACN,MAAM;QACN,MAAM;QACN,KAAK;QACL,KAAK;QACL,OAAO;YAAE,OAAO;YAAM,QAAQ;QAAI;QAClC,GAAGA,SAAS;IAChB;AAEAC,SAAS,iBAAiB;IACtBC,GAAG,wEAAwE;QACvE,MAAMC,QAAQC,cAAcL;QAC5BM,OAAOF,MAAM,GAAG,EAAE,IAAI,CAAC;QACvBE,OAAOF,MAAM,KAAK,EAAE,IAAI,CAAC;QACzBE,OAAOF,MAAM,MAAM,EAAE,IAAI,CAAC;QAC1BE,OAAOF,MAAM,KAAK,CAAC,QAAQ,EAAE,IAAI,CAAC;QAClCE,OAAOF,MAAM,KAAK,CAAC,QAAQ,EAAE,IAAI,CAAC;QAClCE,OAAOF,MAAM,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC;IACzC;IAEAD,GAAG,+CAA+C;QAC9C,MAAMC,QAAQC,cAAcL,MAAM;YAAE,OAAO;gBAAE,KAAK;YAAa;QAAE,IAAI;YACjE,KAAK;QACT;QACAM,OAAOF,MAAM,GAAG,EAAE,IAAI,CAAC;IAC3B;IAEAD,GAAG,wCAAwC;QACvC,MAAMC,QAAQC,cAAcL,MAAM;YAAE,OAAO;gBAAE,KAAK;YAAa;QAAE;QACjEM,OAAOF,MAAM,GAAG,EAAE,IAAI,CAAC;IAC3B;IAEAD,GAAG,mCAAmC;QAClCG,OAAOD,cAAcL,SAAS,GAAG,EAAE,IAAI,CAAC;IAC5C;IAEAG,GAAG,sDAAsD;QACrD,MAAMC,QAAQC,cAAcL,SAAS;YAAE,aAAa;QAAE;QACtDM,OAAOF,MAAM,KAAK,CAAC,WAAW,EAAE,IAAI,CAAC;IACzC;IAEAD,GAAG,iEAAiE;QAChE,MAAMC,QAAQC,cACVL,MAAM;YACF,OAAO;gBACH,OAAO;gBACP,QAAQ;gBACR,YAAY;oBAAE,GAAG;oBAAK,GAAG;gBAAI;YACjC;QACJ,IACA;YAAE,aAAa;QAAE;QAErBM,OAAOC,WAAWH,MAAM,QAAQ,CAAC,IAAI,GAAa,YAAY,CAAC;IACnE;AACJ"}
|
package/image/index.d.ts
ADDED
package/image/index.js
ADDED
package/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export * from "./components/index.js";
|
|
2
|
-
export
|
|
3
|
-
export { createTextInput, createLongTextInput, createNumberInput, createBooleanInput, createColorInput, createFileInput, createDateInput, createLexicalInput, createSelectInput, createRadioInput, createObjectInput, createTagsInput, createSlotInput, createInput, createElement, createTheme, contentSdk, environment, setHeadersProvider, getHeadersProvider, registerComponentGroup, type CssProperties, type Document, type DocumentElement, type Breakpoint, type CreateElementParams, type ContentSDKConfig, type ComponentManifest, type ComponentInput, type ComponentConstraint, type WebsiteBuilderThemeInput, StyleSettings } from "@webiny/website-builder-sdk";
|
|
2
|
+
export { createComponent } from "@webiny/website-builder-sdk";
|
|
3
|
+
export { createTextInput, createLongTextInput, createNumberInput, createBooleanInput, createColorInput, createFileInput, createDateInput, createLexicalInput, createSelectInput, createRadioInput, createObjectInput, createTagsInput, createSlotInput, createInput, createElement, createTheme, contentSdk, environment, setHeadersProvider, getHeadersProvider, registerComponentGroup, getPageWithExperiment, resolveVisitorContext, assignVariant, forcedAssignment, registerAnalyticsProvider, getAnalyticsProvider, ASPECT_RATIO_PRESETS, FORCED_VARIANT_PARAM, DEFAULT_VISITOR_COOKIE, CONTROL_VARIANT_ID, type ActiveExperiment, type ActiveExperimentVariant, type VariantContent, type VariantAssignment, type VisitorContext, type DeviceType, type ExperimentTrafficSplit, type ExperimentTargeting, type ExperimentAnalyticsConfig, type ExperimentSdk, type ExperimentRenderResult, type GetPageWithExperimentOptions, type ExperimentCookie, type CssProperties, type Document, type DocumentElement, type Breakpoint, type CreateElementParams, type ContentSDKConfig, type ComponentManifest, type ComponentInput, type ComponentConstraint, type WebsiteBuilderThemeInput, type AssetCrop, type AssetFocalPoint, type Asset, type AssetImage, type AssetDocument, type AssetVideo, type AssetCategory, normalizeToAsset, getAssetCategory, getAssetUrl, getAssetCropParam, type AssetUrlOptions, IMAGE_RESIZE_WIDTHS, getImageSrcSet, getImageDimensions, type ImageSrcSet, type ImageSrcSetOptions, type ImageDimensions, type AspectRatioInput, type AspectRatioPreset, StyleSettings } from "@webiny/website-builder-sdk";
|
|
4
4
|
export type { ComponentProps, ComponentPropsWithChildren, InferManifest, InferComponentChange, InferDescendantChange } from "./types.js";
|
package/index.js
CHANGED
|
@@ -1,3 +1,2 @@
|
|
|
1
1
|
export * from "./components/index.js";
|
|
2
|
-
export
|
|
3
|
-
export { StyleSettings, contentSdk, createBooleanInput, createColorInput, createDateInput, createElement, createFileInput, createInput, createLexicalInput, createLongTextInput, createNumberInput, createObjectInput, createRadioInput, createSelectInput, createSlotInput, createTagsInput, createTextInput, createTheme, environment, getHeadersProvider, registerComponentGroup, setHeadersProvider } from "@webiny/website-builder-sdk";
|
|
2
|
+
export { ASPECT_RATIO_PRESETS, CONTROL_VARIANT_ID, DEFAULT_VISITOR_COOKIE, FORCED_VARIANT_PARAM, IMAGE_RESIZE_WIDTHS, StyleSettings, assignVariant, contentSdk, createBooleanInput, createColorInput, createComponent, createDateInput, createElement, createFileInput, createInput, createLexicalInput, createLongTextInput, createNumberInput, createObjectInput, createRadioInput, createSelectInput, createSlotInput, createTagsInput, createTextInput, createTheme, environment, forcedAssignment, getAnalyticsProvider, getAssetCategory, getAssetCropParam, getAssetUrl, getHeadersProvider, getImageDimensions, getImageSrcSet, getPageWithExperiment, normalizeToAsset, registerAnalyticsProvider, registerComponentGroup, resolveVisitorContext, setHeadersProvider } from "@webiny/website-builder-sdk";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webiny/website-builder-react",
|
|
3
|
-
"version": "6.6.0-alpha.
|
|
3
|
+
"version": "6.6.0-alpha.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -17,18 +17,18 @@
|
|
|
17
17
|
],
|
|
18
18
|
"license": "MIT",
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@webiny/website-builder-sdk": "6.6.0-alpha.
|
|
20
|
+
"@webiny/website-builder-sdk": "6.6.0-alpha.2",
|
|
21
21
|
"deep-equal": "2.2.3",
|
|
22
|
-
"mobx": "
|
|
23
|
-
"mobx-react-lite": "
|
|
22
|
+
"mobx": "7.0.3",
|
|
23
|
+
"mobx-react-lite": "5.0.3",
|
|
24
24
|
"react": "18.3.1",
|
|
25
25
|
"react-dom": "18.3.1"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@types/react": "18.3.31",
|
|
29
|
-
"@webiny/build-tools": "6.6.0-alpha.
|
|
29
|
+
"@webiny/build-tools": "6.6.0-alpha.2",
|
|
30
30
|
"typescript": "7.0.2",
|
|
31
|
-
"vitest": "4.1.
|
|
31
|
+
"vitest": "4.1.11"
|
|
32
32
|
},
|
|
33
33
|
"publishConfig": {
|
|
34
34
|
"access": "public"
|
package/types.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { CssProperties, DocumentElement, ComponentManifestInput, ComponentChangeHandler, DescendantChangeHandler } from "@webiny/website-builder-sdk";
|
|
1
|
+
import type { CssProperties, DocumentElement, ComponentManifestInput, ComponentChangeHandler, DescendantChangeHandler, ExtractInputs } from "@webiny/website-builder-sdk";
|
|
2
|
+
export type { ExtractInputs } from "@webiny/website-builder-sdk";
|
|
2
3
|
export type ComponentProps<TInputs = unknown> = {
|
|
3
4
|
inputs: TInputs;
|
|
4
5
|
styles: CssProperties;
|
|
@@ -8,9 +9,6 @@ export type ComponentProps<TInputs = unknown> = {
|
|
|
8
9
|
export type ComponentPropsWithChildren<TInputs = unknown> = ComponentProps<TInputs & {
|
|
9
10
|
children: React.ReactNode;
|
|
10
11
|
}>;
|
|
11
|
-
export type ExtractInputs<T> = T extends {
|
|
12
|
-
inputs: infer I;
|
|
13
|
-
} ? I : never;
|
|
14
12
|
export type ExtractInputNames<T extends (props: any) => any> = keyof ExtractInputs<Parameters<T>[0]>;
|
|
15
13
|
/**
|
|
16
14
|
* Infer the full typed ComponentManifestInput from a React component.
|
package/createComponent.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"createComponent.js","sources":["../src/createComponent.ts"],"sourcesContent":["import type {\n Component,\n ComponentInput,\n ComponentManifest,\n ComponentManifestInput,\n InputFactory\n} from \"@webiny/website-builder-sdk\";\nimport { createSlotInput } from \"@webiny/website-builder-sdk\";\nimport type { ExtractInputs } from \"~/types.js\";\n\nexport function createComponent<\n TComponent extends (props: any) => any,\n TInputs extends ExtractInputs<Parameters<TComponent>[0]>\n>(component: TComponent, manifest: ComponentManifestInput<TInputs>): Component {\n const inputs: ComponentInput[] = [];\n\n // Normalize inputs to always be an array of objects.\n\n if (Array.isArray(manifest.inputs)) {\n inputs.push(...manifest.inputs);\n } else {\n const inputsObject: Record<string, InputFactory<any>> = manifest.inputs ?? {};\n Object.keys(inputsObject).forEach((name: string) => {\n inputs.push({ ...inputsObject[name], name });\n });\n }\n\n const acceptsChildren = manifest.acceptsChildren;\n\n if (acceptsChildren) {\n const hasChildren = inputs.some(input => input.name === \"children\");\n if (!hasChildren) {\n inputs.push(createSlotInput({ name: \"children\" }));\n }\n }\n\n return {\n component,\n manifest: { ...manifest, tags: manifest.tags ?? [], inputs } as ComponentManifest\n };\n}\n"],"names":["createComponent","component","manifest","inputs","Array","inputsObject","Object","name","acceptsChildren","hasChildren","input","createSlotInput"],"mappings":";AAUO,SAASA,gBAGdC,SAAqB,EAAEC,QAAyC;IAC9D,MAAMC,SAA2B,EAAE;IAInC,IAAIC,MAAM,OAAO,CAACF,SAAS,MAAM,GAC7BC,OAAO,IAAI,IAAID,SAAS,MAAM;SAC3B;QACH,MAAMG,eAAkDH,SAAS,MAAM,IAAI,CAAC;QAC5EI,OAAO,IAAI,CAACD,cAAc,OAAO,CAAC,CAACE;YAC/BJ,OAAO,IAAI,CAAC;gBAAE,GAAGE,YAAY,CAACE,KAAK;gBAAEA;YAAK;QAC9C;IACJ;IAEA,MAAMC,kBAAkBN,SAAS,eAAe;IAEhD,IAAIM,iBAAiB;QACjB,MAAMC,cAAcN,OAAO,IAAI,CAACO,CAAAA,QAASA,AAAe,eAAfA,MAAM,IAAI;QACnD,IAAI,CAACD,aACDN,OAAO,IAAI,CAACQ,gBAAgB;YAAE,MAAM;QAAW;IAEvD;IAEA,OAAO;QACHV;QACA,UAAU;YAAE,GAAGC,QAAQ;YAAE,MAAMA,SAAS,IAAI,IAAI,EAAE;YAAEC;QAAO;IAC/D;AACJ"}
|