@wix/origami-transforms 0.1.12 → 0.1.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,2 @@
1
+ /** @type {import('../transform/types.js').CssTransformPlugin} */
2
+ export const componentPositionPlugin: import("../transform/types.js").CssTransformPlugin;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/origami-transforms",
3
- "version": "0.1.12",
3
+ "version": "0.1.14",
4
4
  "description": "Babel and PostCSS checks and transforms for Wix origami page files.",
5
5
  "main": "./src/index.js",
6
6
  "files": [
@@ -16,7 +16,7 @@
16
16
  "dependencies": {
17
17
  "@babel/core": "^7.26.0",
18
18
  "@wix/origami-fonts": "1.0.1",
19
- "@wix/origami-system-components": "1.7.0",
19
+ "@wix/origami-system-components": "1.9.0",
20
20
  "postcss": "^8.5.3",
21
21
  "postcss-custom-media": "^12.0.1"
22
22
  },
@@ -58,5 +58,5 @@
58
58
  },
59
59
  "type": "module",
60
60
  "types": "./dist/index.d.ts",
61
- "falconPackageHash": "5339c279d9f83f77637d6772dcd519d52c576f898a610ca35dcdd0df"
61
+ "falconPackageHash": "dcaeecf42c720e3e9a25f95eadad7516666d783eef907ba5f39467f1"
62
62
  }
@@ -0,0 +1,26 @@
1
+ // Gives every component the `position: relative` Thunderbolt gives it by default, so what a component positions
2
+ // against itself (the Menu's dropdown) is placed and sized by the component. See componentPosition.md.
3
+
4
+ import { isLayoutSource } from './layout/parser.js'
5
+
6
+ // One class or id: DM writes `.compId`, and layout.css still accepts `#compId` (see layout/parser.js).
7
+ const SINGLE_CLASS_OR_ID = /^[.#][\w-]+$/
8
+
9
+ /** @type {import('../transform/types.js').CssTransformPlugin} */
10
+ export const componentPositionPlugin = {
11
+ name: 'component-position',
12
+ order: 14,
13
+ transform(root, context) {
14
+ // A component's base rules, by selector: DM may write one class in several rules.
15
+ /** @type {Map<string, import('postcss').Rule[]>} */
16
+ const baseRules = new Map()
17
+ for (const node of root.nodes) {
18
+ if (node.type !== 'rule' || !SINGLE_CLASS_OR_ID.test(node.selector) || !isLayoutSource(node, context)) continue
19
+ baseRules.set(node.selector, [...(baseRules.get(node.selector) ?? []), node])
20
+ }
21
+ for (const rules of baseRules.values()) {
22
+ if (rules.some(rule => rule.nodes.some(node => node.type === 'decl' && node.prop === 'position'))) continue
23
+ rules[0].prepend({ prop: 'position', value: 'relative' })
24
+ }
25
+ },
26
+ }
@@ -0,0 +1,34 @@
1
+ # Components are `position: relative` by default
2
+
3
+ Thunderbolt writes `position: relative` into each component's layout CSS when the component's layout sets no
4
+ position, for the default breakpoint and variant only
5
+ ([responsiveLayoutCompNode.ts](https://github.com/wix-private/thunderbolt/blob/09356e43df04152b47de507f73ce2d8e2a74a97a/packages/thunderbolt-catharsis-extensions/src/features/responsiveLayout/responsiveLayoutCompNode.ts#L165-L173)).
6
+ A component's CSS relies on it: the Menu's dropdown is `position: absolute` and as wide as the nearest positioned
7
+ ancestor, which is the Menu only because of this default.
8
+
9
+ DM's export writes a `position` only when the layout data has one, and a `position: relative` written into
10
+ `layout.css` is imported back as data. So the default is added at build time, never in the source:
11
+
12
+ ```css
13
+ /* layout.css */
14
+ .comp-1 { width: 100%; }
15
+ .comp-2 { position: sticky; }
16
+ @media (max-width: 750px) { .comp-1 { width: 50%; } }
17
+ ```
18
+
19
+ builds to
20
+
21
+ ```css
22
+ .comp-1 { position: relative; width: 100%; }
23
+ .comp-2 { position: sticky; }
24
+ @media (max-width: 750px) { .comp-1 { width: 50%; } }
25
+ ```
26
+
27
+ ## The rules
28
+
29
+ - Only a component's base rule gets it: a top-level rule in a site-owned `layout.css` whose selector is one class
30
+ or id (`.comp-1`, a page's `.c1dmp`, or `#comp-1`, which layout.css still accepts). That is the default breakpoint and variant; the `@media` rules inherit it.
31
+ - A rule that sets `position` keeps its own (sticky, or the `absolute` and `fixed` DM writes for pinned and fixed
32
+ items).
33
+ - The declaration goes into the authored rule, so it has the rule's specificity and wins over the component's own
34
+ class rules, as Thunderbolt's `#main_MF :where(.comp-1)` does.
@@ -11,10 +11,12 @@
11
11
  // authored one. custom-enums runs after mixins as well, so an enum a mixin body sets is resolved, and before presets
12
12
  // and layout move declarations out of the instance's rule. fonts appends the `@font-face` rules that load the Wix fonts
13
13
  // the stylesheet names from Wix's CDN.
14
+ // component-position runs after mixins, so a position a mixin body sets is kept, and before layout compiles the rules.
14
15
  //
15
16
  // `@layer` needs no plugin: cascade layers have been in every browser since March 2022.
16
17
 
17
18
  import { customEnumsPlugin } from './customEnums.js'
19
+ import { componentPositionPlugin } from './componentPosition.js'
18
20
  import { customMediaPlugin } from './customMedia.js'
19
21
  import { fontsPlugin } from './fonts.js'
20
22
  import { mixinsPlugin } from './mixins.js'
@@ -31,6 +33,7 @@ export const cssPlugins = Object.freeze([
31
33
  customEnumsPlugin,
32
34
  stackChildrenPlugin,
33
35
  presetsPlugin,
36
+ componentPositionPlugin,
34
37
  layoutPlugin,
35
38
  spxPlugin,
36
39
  ])