@wix/origami-transforms 0.1.15 → 0.1.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cssPlugins/layout/contract.d.ts +1 -0
- package/package.json +3 -3
- package/src/cssPlugins/layout/README.md +15 -9
- package/src/cssPlugins/layout/compiler.js +13 -13
- package/src/cssPlugins/layout/contract.js +1 -0
- package/src/cssPlugins/spx/README.md +15 -8
- package/src/cssPlugins/spx/cascade.js +7 -2
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export const CONTENT: "internal-container-content-wrapper";
|
|
2
2
|
export const OVERFLOW: "internal-container-overflow-wrapper";
|
|
3
|
+
export const DEFAULTS_LAYER: "origami-container-defaults";
|
|
3
4
|
export const targets: Readonly<{
|
|
4
5
|
"internal-container-content-wrapper": Set<string>;
|
|
5
6
|
"internal-container-overflow-wrapper": Set<string>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/origami-transforms",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.16",
|
|
4
4
|
"description": "Babel and PostCSS checks and transforms for Wix origami page files.",
|
|
5
5
|
"main": "./src/index.js",
|
|
6
6
|
"files": [
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"@babel/parser": "^7.25.0",
|
|
19
19
|
"@babel/types": "^7.25.2",
|
|
20
20
|
"@wix/origami-fonts": "1.0.1",
|
|
21
|
-
"@wix/origami-system-components": "1.
|
|
21
|
+
"@wix/origami-system-components": "1.10.0",
|
|
22
22
|
"postcss": "^8.5.3",
|
|
23
23
|
"postcss-custom-media": "^12.0.1"
|
|
24
24
|
},
|
|
@@ -64,5 +64,5 @@
|
|
|
64
64
|
},
|
|
65
65
|
"type": "module",
|
|
66
66
|
"types": "./dist/index.d.ts",
|
|
67
|
-
"falconPackageHash": "
|
|
67
|
+
"falconPackageHash": "74a88e698f17027ba6854f8a4cdcd82fb6e31bdaec6caea30a13b8ac"
|
|
68
68
|
}
|
|
@@ -32,15 +32,21 @@ the outer element.
|
|
|
32
32
|
## What the plugin adds
|
|
33
33
|
|
|
34
34
|
The outer element and overflow wrapper get a one-cell grid so the wrappers fill
|
|
35
|
-
the container. The content wrapper
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
Each container
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
35
|
+
the container. The content wrapper lets pointer events pass through empty space
|
|
36
|
+
while its children stay clickable. Vertical overflow also sets `--sticky-offset`
|
|
37
|
+
to `0px` for `scroll` and resets it for other values.
|
|
38
|
+
|
|
39
|
+
Each container's alignment defaults to center in a separate first CSS layer, so
|
|
40
|
+
authored values always win. Media queries and scopes around a rule still apply.
|
|
41
|
+
|
|
42
|
+
### Content max width
|
|
43
|
+
|
|
44
|
+
Where DM writes `--content-max-width` (usually a section's content wrapper), the
|
|
45
|
+
plugin adds `max-width` and an alignment `margin-left` next to it, and nowhere else.
|
|
46
|
+
|
|
47
|
+
- Those two properties do not inherit, so nested containers are not boxed in.
|
|
48
|
+
- `--content-max-width` does inherit, so nested containers use it as their SPX cap
|
|
49
|
+
(see the SPX plugin README). With none above, SPX is uncapped.
|
|
44
50
|
|
|
45
51
|
## Why validation runs before transformations
|
|
46
52
|
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import postcss from 'postcss'
|
|
2
2
|
import { buildContainerClasses } from '@wix/origami-system-components/layout-contract'
|
|
3
|
-
import { CONTENT } from './contract.js'
|
|
3
|
+
import { CONTENT, DEFAULTS_LAYER } from './contract.js'
|
|
4
4
|
import { isLayoutSource, parseTargets } from './parser.js'
|
|
5
5
|
|
|
6
6
|
const grid = { display: 'grid', 'grid-template-rows': '1fr', 'grid-template-columns': 'minmax(0, 1fr)' }
|
|
7
|
+
const contentMargin =
|
|
8
|
+
'clamp(0px, (100% - var(--content-max-width)) * var(--origami-content-align), 100 * var(--one-unit, 1%))'
|
|
7
9
|
|
|
8
10
|
/** Preserve source locations on every emitted declaration and selector. */
|
|
9
11
|
const ruleFor = (owner, selector, declarations) => {
|
|
@@ -21,12 +23,12 @@ const ruleFor = (owner, selector, declarations) => {
|
|
|
21
23
|
export const compileContainers = (root, context) => {
|
|
22
24
|
const owners = parseTargets(root, context)
|
|
23
25
|
if (!owners.size) return
|
|
24
|
-
//
|
|
25
|
-
//
|
|
26
|
-
//
|
|
26
|
+
// max-width and margin-left are written only where a content max width is set.
|
|
27
|
+
// Alignment is a custom property so it can change independently at breakpoints.
|
|
28
|
+
// That inherits, so each container needs a default to avoid taking its parent's alignment.
|
|
27
29
|
// This first layer keeps defaults weaker than authored rules, including rules in later layers.
|
|
28
30
|
// Clone only conditional/scope envelopes into it so the defaults apply under the same conditions.
|
|
29
|
-
const defaultsLayer = postcss.atRule({ name: 'layer', params:
|
|
31
|
+
const defaultsLayer = postcss.atRule({ name: 'layer', params: DEFAULTS_LAYER })
|
|
30
32
|
if (root.source) defaultsLayer.source = root.source
|
|
31
33
|
root.prepend(defaultsLayer)
|
|
32
34
|
// Source identity prevents a matching selector in another carrier from becoming an owner.
|
|
@@ -64,10 +66,7 @@ export const compileContainers = (root, context) => {
|
|
|
64
66
|
defaultsParent = clone
|
|
65
67
|
}
|
|
66
68
|
defaultsParent.append(
|
|
67
|
-
ruleFor(owner, `:where(${content})`, {
|
|
68
|
-
'--content-max-width': 'none',
|
|
69
|
-
'--origami-content-align': '0.5',
|
|
70
|
-
})
|
|
69
|
+
ruleFor(owner, `:where(${content})`, { '--origami-content-align': '0.5' })
|
|
71
70
|
)
|
|
72
71
|
owner.before(ruleFor(owner, selector, grid))
|
|
73
72
|
owner.before(ruleFor(owner, overflow, { ...grid, position: 'relative', 'align-self': 'stretch' }))
|
|
@@ -76,10 +75,6 @@ export const compileContainers = (root, context) => {
|
|
|
76
75
|
'box-sizing': 'border-box',
|
|
77
76
|
position: 'relative',
|
|
78
77
|
'pointer-events': 'none',
|
|
79
|
-
'max-width': 'var(--content-max-width)',
|
|
80
|
-
'--section-max-width': 'var(--content-max-width)',
|
|
81
|
-
'margin-left':
|
|
82
|
-
'clamp(0px, (100% - var(--content-max-width, 100%)) * var(--origami-content-align), 100 * var(--one-unit, 1%))',
|
|
83
78
|
})
|
|
84
79
|
)
|
|
85
80
|
owner.before(ruleFor(owner, `${content} > *`, { 'pointer-events': 'auto' }))
|
|
@@ -98,6 +93,11 @@ export const compileContainers = (root, context) => {
|
|
|
98
93
|
// Left margin uses none, half or all of the extra space to align the content.
|
|
99
94
|
clone.value = { left: '0', center: '0.5', right: '1' }[clone.value]
|
|
100
95
|
}
|
|
96
|
+
if (clone.prop === '--content-max-width')
|
|
97
|
+
generated.append(
|
|
98
|
+
clone.clone({ prop: 'max-width', value: 'var(--content-max-width)' }),
|
|
99
|
+
clone.clone({ prop: 'margin-left', value: contentMargin })
|
|
100
|
+
)
|
|
101
101
|
if (clone.prop === 'overflow-y')
|
|
102
102
|
generated.append(
|
|
103
103
|
clone.clone({
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// Consumer routing only: component eligibility is validated by DM against JSX.
|
|
3
3
|
export const CONTENT = 'internal-container-content-wrapper'
|
|
4
4
|
export const OVERFLOW = 'internal-container-overflow-wrapper'
|
|
5
|
+
export const DEFAULTS_LAYER = 'origami-container-defaults'
|
|
5
6
|
export const targets = Object.freeze({
|
|
6
7
|
[CONTENT]: new Set([
|
|
7
8
|
'position',
|
|
@@ -29,13 +29,21 @@ styles onto their runtime wrappers; this plugin then converts every `--spx(numbe
|
|
|
29
29
|
In scale mode, the size is approximately:
|
|
30
30
|
|
|
31
31
|
```text
|
|
32
|
-
number × (scaling-factor − scrollbar-width) / spx-ref-width
|
|
32
|
+
number × (clamp(spx-stopper-min, scaling-factor, min(spx-stopper-max, content-max-width)) − scrollbar-width) / spx-ref-width
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
+
This matches DM's `--spx()` in the `theme.css` preamble.
|
|
36
|
+
|
|
37
|
+
- **Stoppers:** DM writes them inside `@layer spx-preamble`, so the viewer's unlayered global CSS
|
|
38
|
+
values (`0px` / `9999px`) win.
|
|
39
|
+
- **Cap:** `--content-max-width`, set by DM on each section's content wrapper and inherited by its
|
|
40
|
+
descendants. With none above, the cap is 99999px. A `--content-max-width` that uses `--spx()` is
|
|
41
|
+
compiled without the cap, since a custom property can't read itself.
|
|
42
|
+
|
|
35
43
|
Nonzero scaled values have a minimum magnitude of 0.5px, preserving their sign.
|
|
36
44
|
In fixed mode, the number is a pixel value, including fractional pixels. Zero stays zero.
|
|
37
45
|
|
|
38
|
-
The plugin keeps reference width, scaling factor
|
|
46
|
+
The plugin keeps reference width, scaling factor, scrollbar width and stoppers as `var()` reads
|
|
39
47
|
inside each expression. It translates `--spx-resolver-type: scale` to a private numeric
|
|
40
48
|
switch of 1, and `fixed` to 0. That switch selects scaled lengths or fixed pixels using
|
|
41
49
|
ordinary CSS arithmetic, without requiring CSS custom functions or style queries.
|
|
@@ -53,9 +61,9 @@ own effective settings. No per-container SPX reset is needed.
|
|
|
53
61
|
|
|
54
62
|
Existing preamble declarations remain in CSS and participate in the normal cascade.
|
|
55
63
|
When settings are absent, expressions fall back to reference width 1280, scale mode,
|
|
56
|
-
viewport width 100vw
|
|
57
|
-
they override them. As with any CSS custom property, an authored
|
|
58
|
-
SPX expression resolves where the
|
|
64
|
+
viewport width 100vw, scrollbar width 0px, stoppers 0px / 99999px and no cap. Nested components inherit settings unless
|
|
65
|
+
they override them. As with any CSS custom property, an authored variable containing an
|
|
66
|
+
SPX expression resolves where the variable is declared; inheriting the variable does not
|
|
59
67
|
re-evaluate it using a child's settings.
|
|
60
68
|
|
|
61
69
|
## Files and boundaries
|
|
@@ -65,9 +73,8 @@ re-evaluate it using a child's settings.
|
|
|
65
73
|
- `calls.js` parses literal numeric SPX calls and rejects unsupported arguments.
|
|
66
74
|
|
|
67
75
|
Reference widths must be positive numbers and resolver modes must be `scale` or `fixed`.
|
|
68
|
-
|
|
69
|
-
`--scaling-factor` supplied by CSS and does not generate Thunderbolt's clamp formula.
|
|
76
|
+
Stoppers and `--content-max-width` are not validated.
|
|
70
77
|
|
|
71
78
|
`test/spx.browser.mjs` checks computed styles for the button example, nested overrides,
|
|
72
|
-
settings in separate stylesheets, cascade priority, fixed fractions, signs and
|
|
79
|
+
settings in separate stylesheets, cascade priority, fixed fractions, signs, zero, stoppers and cap.
|
|
73
80
|
Run it together with the container browser checks using the package's `test:browser` script.
|
|
@@ -3,8 +3,12 @@ import { lowerCalls } from './calls.js'
|
|
|
3
3
|
// Keep arithmetic at the call site: an inherited derived custom property would already
|
|
4
4
|
// be computed against its parent's settings. Only the numeric resolver switch inherits.
|
|
5
5
|
const SCALE = 'var(--origami-spx-scale, 1)'
|
|
6
|
-
const UNIT = `(${SCALE} * (var(--scaling-factor, 100vw) - var(--scrollbar-width, 0px)) / var(--spx-ref-width, 1280) + (1 - ${SCALE}) * 1px)`
|
|
7
6
|
const FLOOR = `calc(0.5px * ${SCALE})`
|
|
7
|
+
/** @param {string} cap */
|
|
8
|
+
const unitCappedAt = cap =>
|
|
9
|
+
`(${SCALE} * (clamp(var(--spx-stopper-min, 0px), var(--scaling-factor, 100vw), min(var(--spx-stopper-max, 99999px), ${cap})) - var(--scrollbar-width, 0px)) / var(--spx-ref-width, 1280) + (1 - ${SCALE}) * 1px)`
|
|
10
|
+
const UNIT = unitCappedAt('var(--content-max-width, 99999px)')
|
|
11
|
+
const UNCAPPED_UNIT = unitCappedAt('99999px')
|
|
8
12
|
|
|
9
13
|
/** Compile settings and calls in place, retaining their cascade and source locations.
|
|
10
14
|
* @param {import('postcss').Declaration} declaration
|
|
@@ -30,11 +34,12 @@ export const compileCascadeDeclaration = declaration => {
|
|
|
30
34
|
) {
|
|
31
35
|
throw declaration.error('SPX reference width must be positive')
|
|
32
36
|
}
|
|
37
|
+
const unit = declaration.prop === '--content-max-width' ? UNCAPPED_UNIT : UNIT
|
|
33
38
|
lowerCalls(
|
|
34
39
|
declaration,
|
|
35
40
|
number => {
|
|
36
41
|
if (number === 0) return '0px'
|
|
37
|
-
return number < 0 ? `min(calc(-1 * ${FLOOR}), ${number} * ${
|
|
42
|
+
return number < 0 ? `min(calc(-1 * ${FLOOR}), ${number} * ${unit})` : `max(${FLOOR}, ${number} * ${unit})`
|
|
38
43
|
},
|
|
39
44
|
() => declaration.error('SPX calls --spx() with a non-literal argument')
|
|
40
45
|
)
|