@webstudio-is/react-sdk 0.6.1 → 0.7.1
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/lib/arg-types/utils.d.ts +1 -8
- package/lib/arg-types/utils.d.ts.map +1 -1
- package/lib/arg-types/utils.js +18 -7
- package/lib/component-utils/image.d.ts +107 -0
- package/lib/component-utils/image.d.ts.map +1 -0
- package/lib/component-utils/image.js +198 -0
- package/lib/component-utils/image.test.d.ts +2 -0
- package/lib/component-utils/image.test.d.ts.map +1 -0
- package/lib/component-utils/image.test.js +132 -0
- package/lib/components/body.props.json +8 -37
- package/lib/components/bold.props.json +8 -37
- package/lib/components/box.props.json +9 -40
- package/lib/components/button.props.json +10 -45
- package/lib/components/component-type.d.ts +2 -2
- package/lib/components/component-type.d.ts.map +1 -1
- package/lib/components/component-type.js +2 -2
- package/lib/components/form.props.json +8 -37
- package/lib/components/heading.props.json +10 -48
- package/lib/components/image-dev.stories.d.ts +36 -0
- package/lib/components/image-dev.stories.d.ts.map +1 -0
- package/lib/components/image-dev.stories.js +102 -0
- package/lib/components/image.d.ts +11 -0
- package/lib/components/image.d.ts.map +1 -0
- package/lib/components/image.js +52 -0
- package/lib/components/image.props.json +2578 -0
- package/lib/components/image.stories.d.ts +14 -0
- package/lib/components/image.stories.d.ts.map +1 -0
- package/lib/components/image.stories.js +17 -0
- package/lib/components/image.ws.d.ts +5 -0
- package/lib/components/image.ws.d.ts.map +1 -0
- package/lib/components/image.ws.js +29 -0
- package/lib/components/index.d.ts +4 -0
- package/lib/components/index.d.ts.map +1 -1
- package/lib/components/index.js +9 -1
- package/lib/components/index.test.js +1 -1
- package/lib/components/input.props.json +9 -46
- package/lib/components/italic.props.json +8 -37
- package/lib/components/link.d.ts +1 -1
- package/lib/components/link.props.json +9 -40
- package/lib/components/link.stories.d.ts +2 -2
- package/lib/components/meta.d.ts +4 -0
- package/lib/components/meta.d.ts.map +1 -1
- package/lib/components/meta.js +9 -1
- package/lib/components/paragraph.props.json +8 -37
- package/lib/components/span.d.ts +3 -0
- package/lib/components/span.d.ts.map +1 -0
- package/lib/components/span.js +8 -0
- package/lib/components/span.props.json +2205 -0
- package/lib/components/span.stories.d.ts +6 -0
- package/lib/components/span.stories.d.ts.map +1 -0
- package/lib/components/span.stories.js +19 -0
- package/lib/components/span.ws.d.ts +5 -0
- package/lib/components/span.ws.d.ts.map +1 -0
- package/lib/components/span.ws.js +14 -0
- package/lib/components/subscript.d.ts +3 -0
- package/lib/components/subscript.d.ts.map +1 -0
- package/lib/components/subscript.js +8 -0
- package/lib/components/subscript.props.json +2205 -0
- package/lib/components/subscript.stories.d.ts +6 -0
- package/lib/components/subscript.stories.d.ts.map +1 -0
- package/lib/components/subscript.stories.js +19 -0
- package/lib/components/subscript.ws.d.ts +5 -0
- package/lib/components/subscript.ws.d.ts.map +1 -0
- package/lib/components/subscript.ws.js +14 -0
- package/lib/components/superscript.d.ts +3 -0
- package/lib/components/superscript.d.ts.map +1 -0
- package/lib/components/superscript.js +8 -0
- package/lib/components/superscript.props.json +2205 -0
- package/lib/components/superscript.stories.d.ts +6 -0
- package/lib/components/superscript.stories.d.ts.map +1 -0
- package/lib/components/superscript.stories.js +19 -0
- package/lib/components/superscript.ws.d.ts +5 -0
- package/lib/components/superscript.ws.d.ts.map +1 -0
- package/lib/components/superscript.ws.js +14 -0
- package/lib/components/text-block.props.json +8 -37
- package/lib/css/breakpoints.d.ts +1 -1
- package/lib/css/breakpoints.d.ts.map +1 -1
- package/lib/css/categories.d.ts +5 -5
- package/lib/css/get-browser-style.d.ts +1 -1
- package/lib/css/get-browser-style.d.ts.map +1 -1
- package/lib/css/get-browser-style.js +10 -5
- package/lib/css/index.d.ts +0 -5
- package/lib/css/index.d.ts.map +1 -1
- package/lib/css/index.js +0 -5
- package/lib/db/instance.d.ts +2 -2
- package/lib/db/instance.d.ts.map +1 -1
- package/lib/db/instance.js +5 -5
- package/lib/index.d.ts +1 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -2
- package/lib/pubsub/create.d.ts +1 -0
- package/lib/pubsub/create.d.ts.map +1 -1
- package/lib/pubsub/create.js +8 -0
- package/lib/remix/handle-request.server.d.ts +3 -0
- package/lib/remix/handle-request.server.d.ts.map +1 -0
- package/lib/remix/handle-request.server.js +15 -0
- package/lib/remix/index.d.ts +3 -0
- package/lib/remix/index.d.ts.map +1 -0
- package/lib/{canvas → remix}/index.js +2 -1
- package/lib/{canvas/canvas.d.ts → remix/root.d.ts} +1 -1
- package/lib/remix/root.d.ts.map +1 -0
- package/lib/{canvas/canvas.js → remix/root.js} +2 -2
- package/lib/tree/create-elements-tree.d.ts +7 -11
- package/lib/tree/create-elements-tree.d.ts.map +1 -1
- package/lib/tree/create-elements-tree.js +5 -10
- package/lib/tree/root.d.ts +6 -4
- package/lib/tree/root.d.ts.map +1 -1
- package/lib/tree/root.js +1 -10
- package/lib/tree/session-storage-polyfill.d.ts +2 -0
- package/lib/tree/session-storage-polyfill.d.ts.map +1 -0
- package/lib/tree/session-storage-polyfill.js +39 -0
- package/lib/tree/wrapper-component.d.ts +4 -4
- package/lib/tree/wrapper-component.d.ts.map +1 -1
- package/lib/tree/wrapper-component.js +5 -5
- package/lib/user-props/schema.d.ts +3 -2
- package/lib/user-props/schema.d.ts.map +1 -1
- package/lib/user-props/schema.js +3 -3
- package/lib/user-props/types.d.ts +1 -3
- package/lib/user-props/types.d.ts.map +1 -1
- package/lib/user-props/use-user-props.d.ts +1 -1
- package/lib/user-props/use-user-props.d.ts.map +1 -1
- package/package.json +23 -14
- package/lib/canvas/canvas.d.ts.map +0 -1
- package/lib/canvas/index.d.ts +0 -2
- package/lib/canvas/index.d.ts.map +0 -1
- package/lib/css/keyword-values.d.ts +0 -302
- package/lib/css/keyword-values.d.ts.map +0 -1
- package/lib/css/keyword-values.js +0 -7372
- package/lib/css/properties.d.ts +0 -3199
- package/lib/css/properties.d.ts.map +0 -1
- package/lib/css/properties.js +0 -3202
- package/lib/css/schema.d.ts +0 -151
- package/lib/css/schema.d.ts.map +0 -1
- package/lib/css/schema.js +0 -38
- package/lib/css/types.d.ts +0 -15
- package/lib/css/types.d.ts.map +0 -1
- package/lib/css/types.js +0 -2
- package/lib/css/units.d.ts +0 -2
- package/lib/css/units.d.ts.map +0 -1
- package/lib/css/units.js +0 -35
- package/lib/stitches/critical-css.d.ts +0 -4
- package/lib/stitches/critical-css.d.ts.map +0 -1
- package/lib/stitches/critical-css.js +0 -12
- package/lib/stitches/css.d.ts +0 -9
- package/lib/stitches/css.d.ts.map +0 -1
- package/lib/stitches/css.js +0 -33
- package/lib/stitches/index.d.ts +0 -4
- package/lib/stitches/index.d.ts.map +0 -1
- package/lib/stitches/index.js +0 -19
- package/lib/stitches/to-css.d.ts +0 -8
- package/lib/stitches/to-css.d.ts.map +0 -1
- package/lib/stitches/to-css.js +0 -43
- package/lib/stitches/to-css.test.d.ts +0 -2
- package/lib/stitches/to-css.test.d.ts.map +0 -1
- package/lib/stitches/to-css.test.js +0 -63
package/lib/arg-types/utils.d.ts
CHANGED
|
@@ -3,22 +3,15 @@ import { PropItem } from "react-docgen-typescript";
|
|
|
3
3
|
export declare type FilterPredicate = (prop: PropItem) => boolean;
|
|
4
4
|
export declare const propsToArgTypes: (props: Record<string, PropItem>, filter?: FilterPredicate) => ArgTypes;
|
|
5
5
|
export declare const mapControlForType: (propItem: PropItem) => {
|
|
6
|
-
control: {
|
|
7
|
-
type: string;
|
|
8
|
-
};
|
|
9
6
|
defaultValue: any;
|
|
10
|
-
options?: undefined;
|
|
11
|
-
} | {
|
|
12
7
|
control: {
|
|
13
8
|
type: string;
|
|
14
9
|
};
|
|
15
|
-
defaultValue?: undefined;
|
|
16
|
-
options?: undefined;
|
|
17
10
|
} | {
|
|
11
|
+
defaultValue: any;
|
|
18
12
|
control: {
|
|
19
13
|
type: string;
|
|
20
14
|
};
|
|
21
15
|
options: any;
|
|
22
|
-
defaultValue?: undefined;
|
|
23
16
|
} | null | undefined;
|
|
24
17
|
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/arg-types/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAEnD,oBAAY,eAAe,GAAG,CAAC,IAAI,EAAE,QAAQ,KAAK,OAAO,CAAC;AAa1D,eAAO,MAAM,eAAe,UACnB,OAAO,MAAM,EAAE,QAAQ,CAAC,WACtB,eAAe,KACvB,
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/arg-types/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAEnD,oBAAY,eAAe,GAAG,CAAC,IAAI,EAAE,QAAQ,KAAK,OAAO,CAAC;AAa1D,eAAO,MAAM,eAAe,UACnB,OAAO,MAAM,EAAE,QAAQ,CAAC,WACtB,eAAe,KACvB,QAkBF,CAAC;AAOF,eAAO,MAAM,iBAAiB,aAAc,QAAQ;;;;;;;;;;;oBA6DnD,CAAC"}
|
package/lib/arg-types/utils.js
CHANGED
|
@@ -37,30 +37,40 @@ const mapControlForType = (propItem) => {
|
|
|
37
37
|
if (!type) {
|
|
38
38
|
return undefined;
|
|
39
39
|
}
|
|
40
|
+
const overrides = { defaultValue: propItem.defaultValue?.value ?? null };
|
|
40
41
|
// args that end with background or color e.g. iconColor
|
|
41
42
|
if (matchers.color && matchers.color.test(name)) {
|
|
42
43
|
const controlType = propItem.type.name;
|
|
43
44
|
if (controlType === "string") {
|
|
44
45
|
return {
|
|
45
46
|
control: { type: "color" },
|
|
46
|
-
|
|
47
|
+
...overrides,
|
|
47
48
|
};
|
|
48
49
|
}
|
|
49
50
|
}
|
|
50
51
|
// args that end with date e.g. purchaseDate
|
|
51
52
|
if (matchers.date && matchers.date.test(name)) {
|
|
52
|
-
return {
|
|
53
|
+
return {
|
|
54
|
+
control: { type: "date" },
|
|
55
|
+
...overrides,
|
|
56
|
+
};
|
|
53
57
|
}
|
|
54
58
|
switch (type?.name) {
|
|
55
59
|
case "array":
|
|
56
|
-
return {
|
|
60
|
+
return {
|
|
61
|
+
control: { type: "object" },
|
|
62
|
+
...overrides,
|
|
63
|
+
};
|
|
57
64
|
case "boolean":
|
|
58
65
|
case "Booleanish":
|
|
59
|
-
return {
|
|
66
|
+
return {
|
|
67
|
+
control: { type: "boolean" },
|
|
68
|
+
...overrides,
|
|
69
|
+
};
|
|
60
70
|
case "string":
|
|
61
|
-
return { control: { type: "text" } };
|
|
71
|
+
return { control: { type: "text" }, ...overrides };
|
|
62
72
|
case "number":
|
|
63
|
-
return { control: { type: "number" } };
|
|
73
|
+
return { control: { type: "number" }, ...overrides };
|
|
64
74
|
case "enum": {
|
|
65
75
|
const { value } = type;
|
|
66
76
|
// Remove additional quotes from enum values
|
|
@@ -69,13 +79,14 @@ const mapControlForType = (propItem) => {
|
|
|
69
79
|
return {
|
|
70
80
|
control: { type: values?.length <= 5 ? "radio" : "select" },
|
|
71
81
|
options: values,
|
|
82
|
+
...overrides,
|
|
72
83
|
};
|
|
73
84
|
}
|
|
74
85
|
case "function":
|
|
75
86
|
case "symbol":
|
|
76
87
|
return null;
|
|
77
88
|
default:
|
|
78
|
-
return { control: { type: "text" } };
|
|
89
|
+
return { control: { type: "text" }, ...overrides };
|
|
79
90
|
}
|
|
80
91
|
};
|
|
81
92
|
exports.mapControlForType = mapControlForType;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* # Responsive Image component helpers.
|
|
3
|
+
*
|
|
4
|
+
* ## Quick summary about img srcset and sizes attributes:
|
|
5
|
+
*
|
|
6
|
+
* There are 2 ways to define what image will be loaded in the img property srcset.
|
|
7
|
+
*
|
|
8
|
+
* 1. via pixel density descriptor 'x', like `srcset="photo-small.jpg 1x, photo-medium.jpg 1.5x, photo-huge.jpg 2x"`
|
|
9
|
+
* src will be selected depending on `device-pixel-ratio`.
|
|
10
|
+
*
|
|
11
|
+
* 2. via viewport width descriptor 'w' and sizes property containing source size descriptors, like
|
|
12
|
+
* `srcset="photo-small.jpg 320w, photo-medium.jpg 640w, photo-huge.jpg 1280w"`
|
|
13
|
+
* `sizes="(max-width: 600px) 400px, (max-width: 1200px) 70vw, 50vw"`
|
|
14
|
+
*
|
|
15
|
+
* The browser finds the first matching media query from source size descriptors,
|
|
16
|
+
* then use source size value to generate internally srcset
|
|
17
|
+
* with pixel density descriptors dividing width descriptor value by source size value.
|
|
18
|
+
*
|
|
19
|
+
* Using the example above for viewport width 800px.
|
|
20
|
+
* The first matching media query is (max-width: 1200px)
|
|
21
|
+
* source size value is 70vw equal to 800px * 0,7 = 560px
|
|
22
|
+
*
|
|
23
|
+
* browser internal srcset will be (we divide `w` descriptor by source size value):
|
|
24
|
+
* photo-small.jpg 320/560x, photo-medium.jpg 640/560x, photo-huge.jpg 1280/560x =>
|
|
25
|
+
* photo-small.jpg 0.57x, photo-medium.jpg 1.14x, photo-huge.jpg 2.28x
|
|
26
|
+
*
|
|
27
|
+
* Finally same rules as for pixel density descriptor 'x' are applied.
|
|
28
|
+
*
|
|
29
|
+
* ## Algorithm (without optimizations):
|
|
30
|
+
*
|
|
31
|
+
* We have a predefined array of all supported image sizes allSizes, this is the real width of an image in pixels.
|
|
32
|
+
* This is good for caching, as we can cache image with specific width and then use it for different devices.
|
|
33
|
+
*
|
|
34
|
+
* > allSizes array is a tradeoff between cache and the best possible image size you deliver to the user.
|
|
35
|
+
* > If allSizes.length is too small, you will deliver too big images to the user,
|
|
36
|
+
* > if allSizes.length is too big, you will have many caches misses.
|
|
37
|
+
*
|
|
38
|
+
* If img has a defined width property.
|
|
39
|
+
* 1. find the first value from allSizes which is greater or equal to the width property
|
|
40
|
+
* 2. use found value to generate srcset with pixel density descriptor 'x'
|
|
41
|
+
*
|
|
42
|
+
*
|
|
43
|
+
* If img has no defined width property.
|
|
44
|
+
* 1. Generate srcset = allSizes.map((w) => `${getImageSrcAtWidth(w)} ${w}w`)
|
|
45
|
+
* 2. Use sizes property, or if it is not defined use opinionated DEFAULT_SIZES = "(min-width: 1280px) 50vw, 100vw";
|
|
46
|
+
*
|
|
47
|
+
* Optimizations applied now:
|
|
48
|
+
*
|
|
49
|
+
* - If the sizes property is defined, we can exclude from `srcsets` all images
|
|
50
|
+
* which are smaller than the `smallestRatio * smallesDeviceSize`
|
|
51
|
+
*
|
|
52
|
+
* Future (not implemented) optimizations and improvements:
|
|
53
|
+
*
|
|
54
|
+
* - Knowing image size on different viewport widths we can provide nondefault sizes property
|
|
55
|
+
* - Knowledge of Image aspect-ratio would allow cropping images serverside.
|
|
56
|
+
* - Early hints for high priority images https://blog.cloudflare.com/early-hints/
|
|
57
|
+
* - Slow networks optimizations
|
|
58
|
+
* - 404 etc processing with CSS - https://bitsofco.de/styling-broken-images/ (has some opinionated issues) or js solution with custom user fallback.
|
|
59
|
+
*
|
|
60
|
+
* # Attributions
|
|
61
|
+
*
|
|
62
|
+
* The MIT License (MIT)
|
|
63
|
+
*
|
|
64
|
+
* applies to:
|
|
65
|
+
*
|
|
66
|
+
* - https://github.com/vercel/next.js, Copyright (c) 2022 Vercel, Inc.
|
|
67
|
+
*
|
|
68
|
+
* The MIT License (MIT)
|
|
69
|
+
*
|
|
70
|
+
* Copyright (c) 2022 Vercel, Inc.
|
|
71
|
+
*
|
|
72
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
|
73
|
+
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
|
74
|
+
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
|
75
|
+
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
|
|
76
|
+
* is furnished to do so, subject to the following conditions:
|
|
77
|
+
*
|
|
78
|
+
* The above copyright notice and this permission notice shall be included in all copies
|
|
79
|
+
* or substantial portions of the Software.
|
|
80
|
+
*
|
|
81
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
82
|
+
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
83
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
84
|
+
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
85
|
+
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
86
|
+
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
87
|
+
**/
|
|
88
|
+
export declare type ImageLoader = (props: {
|
|
89
|
+
width: number;
|
|
90
|
+
quality: number;
|
|
91
|
+
src: string;
|
|
92
|
+
}) => string;
|
|
93
|
+
export declare const allSizes: number[];
|
|
94
|
+
export declare const getImageAttributes: (props: {
|
|
95
|
+
src: string | undefined;
|
|
96
|
+
srcSet: string | undefined;
|
|
97
|
+
sizes: string | undefined;
|
|
98
|
+
width: string | number | undefined;
|
|
99
|
+
quality: number | undefined;
|
|
100
|
+
loader?: ImageLoader;
|
|
101
|
+
optimize: boolean;
|
|
102
|
+
}) => {
|
|
103
|
+
src: string;
|
|
104
|
+
srcSet: string | undefined;
|
|
105
|
+
sizes: string | undefined;
|
|
106
|
+
} | null;
|
|
107
|
+
//# sourceMappingURL=image.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../src/component-utils/image.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAsFI;AAIJ,oBAAY,WAAW,GAAG,CAAC,KAAK,EAAE;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;CACb,KAAK,MAAM,CAAC;AAQb,eAAO,MAAM,QAAQ,UAAkC,CAAC;AA8HxD,eAAO,MAAM,kBAAkB,UAAW;IACxC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;IACxB,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IACnC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,QAAQ,EAAE,OAAO,CAAC;CACnB,KAAG;IACF,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;CAC3B,GAAG,IA2BH,CAAC"}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* # Responsive Image component helpers.
|
|
4
|
+
*
|
|
5
|
+
* ## Quick summary about img srcset and sizes attributes:
|
|
6
|
+
*
|
|
7
|
+
* There are 2 ways to define what image will be loaded in the img property srcset.
|
|
8
|
+
*
|
|
9
|
+
* 1. via pixel density descriptor 'x', like `srcset="photo-small.jpg 1x, photo-medium.jpg 1.5x, photo-huge.jpg 2x"`
|
|
10
|
+
* src will be selected depending on `device-pixel-ratio`.
|
|
11
|
+
*
|
|
12
|
+
* 2. via viewport width descriptor 'w' and sizes property containing source size descriptors, like
|
|
13
|
+
* `srcset="photo-small.jpg 320w, photo-medium.jpg 640w, photo-huge.jpg 1280w"`
|
|
14
|
+
* `sizes="(max-width: 600px) 400px, (max-width: 1200px) 70vw, 50vw"`
|
|
15
|
+
*
|
|
16
|
+
* The browser finds the first matching media query from source size descriptors,
|
|
17
|
+
* then use source size value to generate internally srcset
|
|
18
|
+
* with pixel density descriptors dividing width descriptor value by source size value.
|
|
19
|
+
*
|
|
20
|
+
* Using the example above for viewport width 800px.
|
|
21
|
+
* The first matching media query is (max-width: 1200px)
|
|
22
|
+
* source size value is 70vw equal to 800px * 0,7 = 560px
|
|
23
|
+
*
|
|
24
|
+
* browser internal srcset will be (we divide `w` descriptor by source size value):
|
|
25
|
+
* photo-small.jpg 320/560x, photo-medium.jpg 640/560x, photo-huge.jpg 1280/560x =>
|
|
26
|
+
* photo-small.jpg 0.57x, photo-medium.jpg 1.14x, photo-huge.jpg 2.28x
|
|
27
|
+
*
|
|
28
|
+
* Finally same rules as for pixel density descriptor 'x' are applied.
|
|
29
|
+
*
|
|
30
|
+
* ## Algorithm (without optimizations):
|
|
31
|
+
*
|
|
32
|
+
* We have a predefined array of all supported image sizes allSizes, this is the real width of an image in pixels.
|
|
33
|
+
* This is good for caching, as we can cache image with specific width and then use it for different devices.
|
|
34
|
+
*
|
|
35
|
+
* > allSizes array is a tradeoff between cache and the best possible image size you deliver to the user.
|
|
36
|
+
* > If allSizes.length is too small, you will deliver too big images to the user,
|
|
37
|
+
* > if allSizes.length is too big, you will have many caches misses.
|
|
38
|
+
*
|
|
39
|
+
* If img has a defined width property.
|
|
40
|
+
* 1. find the first value from allSizes which is greater or equal to the width property
|
|
41
|
+
* 2. use found value to generate srcset with pixel density descriptor 'x'
|
|
42
|
+
*
|
|
43
|
+
*
|
|
44
|
+
* If img has no defined width property.
|
|
45
|
+
* 1. Generate srcset = allSizes.map((w) => `${getImageSrcAtWidth(w)} ${w}w`)
|
|
46
|
+
* 2. Use sizes property, or if it is not defined use opinionated DEFAULT_SIZES = "(min-width: 1280px) 50vw, 100vw";
|
|
47
|
+
*
|
|
48
|
+
* Optimizations applied now:
|
|
49
|
+
*
|
|
50
|
+
* - If the sizes property is defined, we can exclude from `srcsets` all images
|
|
51
|
+
* which are smaller than the `smallestRatio * smallesDeviceSize`
|
|
52
|
+
*
|
|
53
|
+
* Future (not implemented) optimizations and improvements:
|
|
54
|
+
*
|
|
55
|
+
* - Knowing image size on different viewport widths we can provide nondefault sizes property
|
|
56
|
+
* - Knowledge of Image aspect-ratio would allow cropping images serverside.
|
|
57
|
+
* - Early hints for high priority images https://blog.cloudflare.com/early-hints/
|
|
58
|
+
* - Slow networks optimizations
|
|
59
|
+
* - 404 etc processing with CSS - https://bitsofco.de/styling-broken-images/ (has some opinionated issues) or js solution with custom user fallback.
|
|
60
|
+
*
|
|
61
|
+
* # Attributions
|
|
62
|
+
*
|
|
63
|
+
* The MIT License (MIT)
|
|
64
|
+
*
|
|
65
|
+
* applies to:
|
|
66
|
+
*
|
|
67
|
+
* - https://github.com/vercel/next.js, Copyright (c) 2022 Vercel, Inc.
|
|
68
|
+
*
|
|
69
|
+
* The MIT License (MIT)
|
|
70
|
+
*
|
|
71
|
+
* Copyright (c) 2022 Vercel, Inc.
|
|
72
|
+
*
|
|
73
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
|
74
|
+
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
|
75
|
+
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
|
76
|
+
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
|
|
77
|
+
* is furnished to do so, subject to the following conditions:
|
|
78
|
+
*
|
|
79
|
+
* The above copyright notice and this permission notice shall be included in all copies
|
|
80
|
+
* or substantial portions of the Software.
|
|
81
|
+
*
|
|
82
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
83
|
+
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
84
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
85
|
+
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
86
|
+
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
87
|
+
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
88
|
+
**/
|
|
89
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
90
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
91
|
+
};
|
|
92
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
93
|
+
exports.getImageAttributes = exports.allSizes = void 0;
|
|
94
|
+
const warn_once_1 = __importDefault(require("warn-once"));
|
|
95
|
+
/**
|
|
96
|
+
* max(...imageSizes) must be less then min(...deviceSizes)
|
|
97
|
+
**/
|
|
98
|
+
const imageSizes = [16, 32, 48, 64, 96, 128, 256, 384];
|
|
99
|
+
const deviceSizes = [640, 750, 828, 1080, 1200, 1920, 2048, 3840];
|
|
100
|
+
exports.allSizes = [...imageSizes, ...deviceSizes];
|
|
101
|
+
/**
|
|
102
|
+
* https://github.com/vercel/next.js/blob/canary/packages/next/client/image.tsx
|
|
103
|
+
**/
|
|
104
|
+
const getWidths = (width, sizes) => {
|
|
105
|
+
if (sizes) {
|
|
106
|
+
// Find all the "vw" percent sizes used in the sizes prop
|
|
107
|
+
const viewportWidthRe = /(^|\s)(1?\d?\d)vw/g;
|
|
108
|
+
const percentSizes = [];
|
|
109
|
+
for (let match; (match = viewportWidthRe.exec(sizes)); match) {
|
|
110
|
+
percentSizes.push(parseInt(match[2], 10));
|
|
111
|
+
}
|
|
112
|
+
if (percentSizes.length) {
|
|
113
|
+
// we can exclude from srcSets all images which are smaller than the smallestRatio * smallesDeviceSize
|
|
114
|
+
const smallestRatio = Math.min(...percentSizes) * 0.01;
|
|
115
|
+
return {
|
|
116
|
+
widths: exports.allSizes.filter((s) => s >= deviceSizes[0] * smallestRatio),
|
|
117
|
+
kind: "w",
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
return { widths: exports.allSizes, kind: "w" };
|
|
121
|
+
}
|
|
122
|
+
if (width == null) {
|
|
123
|
+
return { widths: deviceSizes, kind: "w" };
|
|
124
|
+
}
|
|
125
|
+
const widths = [
|
|
126
|
+
...new Set([width, width * 2].map((w) => exports.allSizes.find((p) => p >= w) || exports.allSizes[exports.allSizes.length - 1])),
|
|
127
|
+
];
|
|
128
|
+
return { widths, kind: "x" };
|
|
129
|
+
};
|
|
130
|
+
const generateImgAttrs = ({ src, width, quality, sizes, loader, }) => {
|
|
131
|
+
const { widths, kind } = getWidths(width, sizes);
|
|
132
|
+
return {
|
|
133
|
+
sizes: !sizes && kind === "w" ? "100vw" : sizes,
|
|
134
|
+
srcSet: widths
|
|
135
|
+
.map((w, i) => `${loader({ src, quality, width: w })} ${kind === "w" ? w : i + 1}${kind}`)
|
|
136
|
+
.join(", "),
|
|
137
|
+
// Must be last, to prevent Safari to load images twice
|
|
138
|
+
src: loader({
|
|
139
|
+
src,
|
|
140
|
+
quality,
|
|
141
|
+
width: widths[widths.length - 1],
|
|
142
|
+
}),
|
|
143
|
+
};
|
|
144
|
+
};
|
|
145
|
+
/**
|
|
146
|
+
* Default image loader in case of no loader provided
|
|
147
|
+
* https://developers.cloudflare.com/images/image-resizing/url-format/
|
|
148
|
+
**/
|
|
149
|
+
const cloudflareImageLoader = ({ width, src, quality }) => {
|
|
150
|
+
if (process.env.NODE_ENV !== "production") {
|
|
151
|
+
(0, warn_once_1.default)(!exports.allSizes.includes(width), "Width must be only from allowed values");
|
|
152
|
+
}
|
|
153
|
+
const options = `width=${width},quality=${quality},format=auto`;
|
|
154
|
+
// Cloudflare docs say that we don't need to urlencode the path params
|
|
155
|
+
const pathname = `/cdn-cgi/image/${options}/${src}`;
|
|
156
|
+
return pathname;
|
|
157
|
+
};
|
|
158
|
+
const getInt = (value) => {
|
|
159
|
+
if (typeof value === "number") {
|
|
160
|
+
return Math.round(value);
|
|
161
|
+
}
|
|
162
|
+
if (typeof value === "string") {
|
|
163
|
+
const vNum = Number.parseFloat(value);
|
|
164
|
+
if (!Number.isNaN(vNum)) {
|
|
165
|
+
return Math.round(vNum);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return undefined;
|
|
169
|
+
};
|
|
170
|
+
/**
|
|
171
|
+
* DEFAULT_SIZES Just an assumption that most images (except hero and icons) are 100% wide on mobile and 50% on desktop.
|
|
172
|
+
* For icons width are usually set explicitly so DEFAULT_SIZES is not applied.
|
|
173
|
+
* For hero images, we can allow in UI to select sizes=100vw explicitly.
|
|
174
|
+
* Anyway, the best would be to calculate this based on canvas data from different breakpoints.
|
|
175
|
+
* See ../component-utils/image for detailed description
|
|
176
|
+
**/
|
|
177
|
+
const DEFAULT_SIZES = "(min-width: 1280px) 50vw, 100vw";
|
|
178
|
+
const DEFAULT_QUALITY = 80;
|
|
179
|
+
const getImageAttributes = (props) => {
|
|
180
|
+
const width = getInt(props.width);
|
|
181
|
+
const quality = Math.max(Math.min(getInt(props.quality) ?? DEFAULT_QUALITY, 100), 0);
|
|
182
|
+
if (props.src != null && props.src != "") {
|
|
183
|
+
if (props.srcSet == null && props.optimize) {
|
|
184
|
+
const sizes = props.sizes ?? (props.width == null ? DEFAULT_SIZES : undefined);
|
|
185
|
+
const loader = props.loader ?? cloudflareImageLoader;
|
|
186
|
+
return generateImgAttrs({
|
|
187
|
+
src: props.src,
|
|
188
|
+
width,
|
|
189
|
+
quality,
|
|
190
|
+
sizes,
|
|
191
|
+
loader,
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
return { src: props.src, srcSet: props.srcSet, sizes: props.sizes };
|
|
195
|
+
}
|
|
196
|
+
return null;
|
|
197
|
+
};
|
|
198
|
+
exports.getImageAttributes = getImageAttributes;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image.test.d.ts","sourceRoot":"","sources":["../../src/component-utils/image.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const image_1 = require("./image");
|
|
4
|
+
describe("Image optimizations applied", () => {
|
|
5
|
+
test("width is number, create pixel density descriptor 'x'", () => {
|
|
6
|
+
const imgAttr = (0, image_1.getImageAttributes)({
|
|
7
|
+
optimize: true,
|
|
8
|
+
width: 100,
|
|
9
|
+
src: "https://webstudio.is/logo.webp",
|
|
10
|
+
srcSet: undefined,
|
|
11
|
+
sizes: undefined,
|
|
12
|
+
quality: 100,
|
|
13
|
+
});
|
|
14
|
+
expect(imgAttr).toMatchInlineSnapshot(`
|
|
15
|
+
Object {
|
|
16
|
+
"sizes": undefined,
|
|
17
|
+
"src": "/cdn-cgi/image/width=256,quality=100,format=auto/https://webstudio.is/logo.webp",
|
|
18
|
+
"srcSet": "/cdn-cgi/image/width=128,quality=100,format=auto/https://webstudio.is/logo.webp 1x, /cdn-cgi/image/width=256,quality=100,format=auto/https://webstudio.is/logo.webp 2x",
|
|
19
|
+
}
|
|
20
|
+
`);
|
|
21
|
+
});
|
|
22
|
+
test("width is undefined, create 'w' descriptor and sizes prop", () => {
|
|
23
|
+
const imgAttr = (0, image_1.getImageAttributes)({
|
|
24
|
+
optimize: true,
|
|
25
|
+
width: undefined,
|
|
26
|
+
src: "https://webstudio.is/logo.webp",
|
|
27
|
+
srcSet: undefined,
|
|
28
|
+
sizes: undefined,
|
|
29
|
+
quality: 90,
|
|
30
|
+
});
|
|
31
|
+
expect(imgAttr).toMatchInlineSnapshot(`
|
|
32
|
+
Object {
|
|
33
|
+
"sizes": "(min-width: 1280px) 50vw, 100vw",
|
|
34
|
+
"src": "/cdn-cgi/image/width=3840,quality=90,format=auto/https://webstudio.is/logo.webp",
|
|
35
|
+
"srcSet": "/cdn-cgi/image/width=384,quality=90,format=auto/https://webstudio.is/logo.webp 384w, /cdn-cgi/image/width=640,quality=90,format=auto/https://webstudio.is/logo.webp 640w, /cdn-cgi/image/width=750,quality=90,format=auto/https://webstudio.is/logo.webp 750w, /cdn-cgi/image/width=828,quality=90,format=auto/https://webstudio.is/logo.webp 828w, /cdn-cgi/image/width=1080,quality=90,format=auto/https://webstudio.is/logo.webp 1080w, /cdn-cgi/image/width=1200,quality=90,format=auto/https://webstudio.is/logo.webp 1200w, /cdn-cgi/image/width=1920,quality=90,format=auto/https://webstudio.is/logo.webp 1920w, /cdn-cgi/image/width=2048,quality=90,format=auto/https://webstudio.is/logo.webp 2048w, /cdn-cgi/image/width=3840,quality=90,format=auto/https://webstudio.is/logo.webp 3840w",
|
|
36
|
+
}
|
|
37
|
+
`);
|
|
38
|
+
});
|
|
39
|
+
test("width is undefined and size defined, creates 'w' descriptor and use input sizes props", () => {
|
|
40
|
+
const imgAttr = (0, image_1.getImageAttributes)({
|
|
41
|
+
optimize: true,
|
|
42
|
+
width: undefined,
|
|
43
|
+
src: "https://webstudio.is/logo.webp",
|
|
44
|
+
srcSet: undefined,
|
|
45
|
+
sizes: "100vw",
|
|
46
|
+
quality: 70,
|
|
47
|
+
});
|
|
48
|
+
expect(imgAttr).toMatchInlineSnapshot(`
|
|
49
|
+
Object {
|
|
50
|
+
"sizes": "100vw",
|
|
51
|
+
"src": "/cdn-cgi/image/width=3840,quality=70,format=auto/https://webstudio.is/logo.webp",
|
|
52
|
+
"srcSet": "/cdn-cgi/image/width=640,quality=70,format=auto/https://webstudio.is/logo.webp 640w, /cdn-cgi/image/width=750,quality=70,format=auto/https://webstudio.is/logo.webp 750w, /cdn-cgi/image/width=828,quality=70,format=auto/https://webstudio.is/logo.webp 828w, /cdn-cgi/image/width=1080,quality=70,format=auto/https://webstudio.is/logo.webp 1080w, /cdn-cgi/image/width=1200,quality=70,format=auto/https://webstudio.is/logo.webp 1200w, /cdn-cgi/image/width=1920,quality=70,format=auto/https://webstudio.is/logo.webp 1920w, /cdn-cgi/image/width=2048,quality=70,format=auto/https://webstudio.is/logo.webp 2048w, /cdn-cgi/image/width=3840,quality=70,format=auto/https://webstudio.is/logo.webp 3840w",
|
|
53
|
+
}
|
|
54
|
+
`);
|
|
55
|
+
});
|
|
56
|
+
test("custom loader", () => {
|
|
57
|
+
const imgAttr = (0, image_1.getImageAttributes)({
|
|
58
|
+
optimize: true,
|
|
59
|
+
width: undefined,
|
|
60
|
+
src: "https://webstudio.is/logo.webp",
|
|
61
|
+
srcSet: undefined,
|
|
62
|
+
sizes: "100vw",
|
|
63
|
+
quality: 70,
|
|
64
|
+
loader: ({ width, src, quality }) => `${new URL(src).pathname}?w=${width}&q=${quality}`,
|
|
65
|
+
});
|
|
66
|
+
expect(imgAttr).toMatchInlineSnapshot(`
|
|
67
|
+
Object {
|
|
68
|
+
"sizes": "100vw",
|
|
69
|
+
"src": "/logo.webp?w=3840&q=70",
|
|
70
|
+
"srcSet": "/logo.webp?w=640&q=70 640w, /logo.webp?w=750&q=70 750w, /logo.webp?w=828&q=70 828w, /logo.webp?w=1080&q=70 1080w, /logo.webp?w=1200&q=70 1200w, /logo.webp?w=1920&q=70 1920w, /logo.webp?w=2048&q=70 2048w, /logo.webp?w=3840&q=70 3840w",
|
|
71
|
+
}
|
|
72
|
+
`);
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
describe("Image optimizations not applied", () => {
|
|
76
|
+
test("optimize is false", () => {
|
|
77
|
+
const imgAttr = (0, image_1.getImageAttributes)({
|
|
78
|
+
optimize: false,
|
|
79
|
+
width: 100,
|
|
80
|
+
src: "https://webstudio.is/logo.webp",
|
|
81
|
+
srcSet: undefined,
|
|
82
|
+
sizes: undefined,
|
|
83
|
+
quality: 100,
|
|
84
|
+
});
|
|
85
|
+
expect(imgAttr).toMatchInlineSnapshot(`
|
|
86
|
+
Object {
|
|
87
|
+
"sizes": undefined,
|
|
88
|
+
"src": "https://webstudio.is/logo.webp",
|
|
89
|
+
"srcSet": undefined,
|
|
90
|
+
}
|
|
91
|
+
`);
|
|
92
|
+
});
|
|
93
|
+
test("srcSet is defined", () => {
|
|
94
|
+
const imgAttr = (0, image_1.getImageAttributes)({
|
|
95
|
+
optimize: true,
|
|
96
|
+
width: 100,
|
|
97
|
+
src: "https://webstudio.is/logo.webp",
|
|
98
|
+
srcSet: "user-defined-srcset",
|
|
99
|
+
sizes: undefined,
|
|
100
|
+
quality: 100,
|
|
101
|
+
});
|
|
102
|
+
expect(imgAttr).toMatchInlineSnapshot(`
|
|
103
|
+
Object {
|
|
104
|
+
"sizes": undefined,
|
|
105
|
+
"src": "https://webstudio.is/logo.webp",
|
|
106
|
+
"srcSet": "user-defined-srcset",
|
|
107
|
+
}
|
|
108
|
+
`);
|
|
109
|
+
});
|
|
110
|
+
test("src is empty", () => {
|
|
111
|
+
const imgAttr = (0, image_1.getImageAttributes)({
|
|
112
|
+
optimize: true,
|
|
113
|
+
width: 100,
|
|
114
|
+
src: "",
|
|
115
|
+
srcSet: undefined,
|
|
116
|
+
sizes: undefined,
|
|
117
|
+
quality: 100,
|
|
118
|
+
});
|
|
119
|
+
expect(imgAttr).toMatchInlineSnapshot(`null`);
|
|
120
|
+
});
|
|
121
|
+
test("src is undefined", () => {
|
|
122
|
+
const imgAttr = (0, image_1.getImageAttributes)({
|
|
123
|
+
optimize: true,
|
|
124
|
+
width: 100,
|
|
125
|
+
src: undefined,
|
|
126
|
+
srcSet: undefined,
|
|
127
|
+
sizes: undefined,
|
|
128
|
+
quality: 100,
|
|
129
|
+
});
|
|
130
|
+
expect(imgAttr).toMatchInlineSnapshot(`null`);
|
|
131
|
+
});
|
|
132
|
+
});
|
|
@@ -447,10 +447,7 @@
|
|
|
447
447
|
"control": {
|
|
448
448
|
"type": "radio"
|
|
449
449
|
},
|
|
450
|
-
"options": [
|
|
451
|
-
"yes",
|
|
452
|
-
"no"
|
|
453
|
-
]
|
|
450
|
+
"options": ["yes", "no"]
|
|
454
451
|
},
|
|
455
452
|
"radioGroup": {
|
|
456
453
|
"defaultValue": null,
|
|
@@ -739,6 +736,7 @@
|
|
|
739
736
|
}
|
|
740
737
|
},
|
|
741
738
|
"color": {
|
|
739
|
+
"defaultValue": null,
|
|
742
740
|
"description": "",
|
|
743
741
|
"name": "color",
|
|
744
742
|
"parent": {
|
|
@@ -943,10 +941,7 @@
|
|
|
943
941
|
"control": {
|
|
944
942
|
"type": "radio"
|
|
945
943
|
},
|
|
946
|
-
"options": [
|
|
947
|
-
"on",
|
|
948
|
-
"off"
|
|
949
|
-
]
|
|
944
|
+
"options": ["on", "off"]
|
|
950
945
|
},
|
|
951
946
|
"inputMode": {
|
|
952
947
|
"defaultValue": null,
|
|
@@ -1109,12 +1104,7 @@
|
|
|
1109
1104
|
"control": {
|
|
1110
1105
|
"type": "radio"
|
|
1111
1106
|
},
|
|
1112
|
-
"options": [
|
|
1113
|
-
"list",
|
|
1114
|
-
"none",
|
|
1115
|
-
"inline",
|
|
1116
|
-
"both"
|
|
1117
|
-
]
|
|
1107
|
+
"options": ["list", "none", "inline", "both"]
|
|
1118
1108
|
},
|
|
1119
1109
|
"aria-busy": {
|
|
1120
1110
|
"defaultValue": null,
|
|
@@ -1378,14 +1368,7 @@
|
|
|
1378
1368
|
"control": {
|
|
1379
1369
|
"type": "select"
|
|
1380
1370
|
},
|
|
1381
|
-
"options": [
|
|
1382
|
-
"link",
|
|
1383
|
-
"none",
|
|
1384
|
-
"copy",
|
|
1385
|
-
"execute",
|
|
1386
|
-
"move",
|
|
1387
|
-
"popup"
|
|
1388
|
-
]
|
|
1371
|
+
"options": ["link", "none", "copy", "execute", "move", "popup"]
|
|
1389
1372
|
},
|
|
1390
1373
|
"aria-errormessage": {
|
|
1391
1374
|
"defaultValue": null,
|
|
@@ -1662,11 +1645,7 @@
|
|
|
1662
1645
|
"control": {
|
|
1663
1646
|
"type": "radio"
|
|
1664
1647
|
},
|
|
1665
|
-
"options": [
|
|
1666
|
-
"off",
|
|
1667
|
-
"assertive",
|
|
1668
|
-
"polite"
|
|
1669
|
-
]
|
|
1648
|
+
"options": ["off", "assertive", "polite"]
|
|
1670
1649
|
},
|
|
1671
1650
|
"aria-modal": {
|
|
1672
1651
|
"defaultValue": null,
|
|
@@ -1764,10 +1743,7 @@
|
|
|
1764
1743
|
"control": {
|
|
1765
1744
|
"type": "radio"
|
|
1766
1745
|
},
|
|
1767
|
-
"options": [
|
|
1768
|
-
"horizontal",
|
|
1769
|
-
"vertical"
|
|
1770
|
-
]
|
|
1746
|
+
"options": ["horizontal", "vertical"]
|
|
1771
1747
|
},
|
|
1772
1748
|
"aria-owns": {
|
|
1773
1749
|
"defaultValue": null,
|
|
@@ -2136,12 +2112,7 @@
|
|
|
2136
2112
|
"control": {
|
|
2137
2113
|
"type": "radio"
|
|
2138
2114
|
},
|
|
2139
|
-
"options": [
|
|
2140
|
-
"none",
|
|
2141
|
-
"ascending",
|
|
2142
|
-
"descending",
|
|
2143
|
-
"other"
|
|
2144
|
-
]
|
|
2115
|
+
"options": ["none", "ascending", "descending", "other"]
|
|
2145
2116
|
},
|
|
2146
2117
|
"aria-valuemax": {
|
|
2147
2118
|
"defaultValue": null,
|