@telegraph/postcss-config 0.0.30 → 0.1.0
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/CHANGELOG.md +13 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/interactive-plugin.d.ts +29 -0
- package/dist/interactive-plugin.d.ts.map +1 -0
- package/dist/interactive-plugin.js +156 -0
- package/dist/style-engine-postcss-config.d.ts.map +1 -1
- package/dist/style-engine-postcss-config.js +9 -1
- package/package.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# @telegraph/postcss-config
|
|
2
2
|
|
|
3
|
+
## 0.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#714](https://github.com/knocklabs/telegraph/pull/714) [`627e61c`](https://github.com/knocklabs/telegraph/commit/627e61c3b17ccfc36f5fb835bb5f21a092efca95) Thanks [@kylemcd](https://github.com/kylemcd)! - feat: hover, focus, etc states as component props
|
|
8
|
+
|
|
9
|
+
## 0.0.31
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- Updated dependencies [[`d6c6aa9`](https://github.com/knocklabs/telegraph/commit/d6c6aa9cb0e11ba96df7d7efd479c8e4652fc029)]:
|
|
14
|
+
- @telegraph/tokens@0.1.3
|
|
15
|
+
|
|
3
16
|
## 0.0.30
|
|
4
17
|
|
|
5
18
|
### Patch Changes
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,wBAAwB,EAAE,MAAM,+BAA+B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACpF,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,sBAAsB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.styleEnginePostCssConfig = void 0;
|
|
6
|
+
exports.interactivePlugin = exports.styleEnginePostCssConfig = void 0;
|
|
7
7
|
var style_engine_postcss_config_1 = require("./style-engine-postcss-config");
|
|
8
8
|
Object.defineProperty(exports, "styleEnginePostCssConfig", { enumerable: true, get: function () { return __importDefault(style_engine_postcss_config_1).default; } });
|
|
9
|
+
var interactive_plugin_1 = require("./interactive-plugin");
|
|
10
|
+
Object.defineProperty(exports, "interactivePlugin", { enumerable: true, get: function () { return __importDefault(interactive_plugin_1).default; } });
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { AcceptedPlugin } from "postcss";
|
|
2
|
+
/**
|
|
3
|
+
* PostCSS plugin: @telegraph/interactive
|
|
4
|
+
*
|
|
5
|
+
* Processes `@telegraph interactive(<selector>)` at-rules and auto-generates
|
|
6
|
+
* pseudo-class cascade rules based on the base rule's declarations.
|
|
7
|
+
*
|
|
8
|
+
* Input:
|
|
9
|
+
* .tgph-box {
|
|
10
|
+
* --background-color: none;
|
|
11
|
+
* background-color: var(--background-color);
|
|
12
|
+
* border-color: var(--border-color);
|
|
13
|
+
* }
|
|
14
|
+
* @telegraph interactive(.tgph-box);
|
|
15
|
+
*
|
|
16
|
+
* Output (appended):
|
|
17
|
+
* .tgph-box--interactive:hover {
|
|
18
|
+
* background-color: var(--hover--background-color, var(--background-color));
|
|
19
|
+
* border-color: var(--hover--border-color, var(--border-color));
|
|
20
|
+
* }
|
|
21
|
+
* .tgph-box--interactive:focus-visible { ... }
|
|
22
|
+
* .tgph-box--interactive:active { ... }
|
|
23
|
+
* .tgph-box--interactive:has(:focus-within) { ... }
|
|
24
|
+
* .tgph-box--interactive:disabled,
|
|
25
|
+
* .tgph-box--interactive[aria-disabled="true"] { ... }
|
|
26
|
+
*/
|
|
27
|
+
declare const interactivePlugin: () => AcceptedPlugin;
|
|
28
|
+
export default interactivePlugin;
|
|
29
|
+
//# sourceMappingURL=interactive-plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interactive-plugin.d.ts","sourceRoot":"","sources":["../src/interactive-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAA6B,MAAM,SAAS,CAAC;AAoFzE;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,QAAA,MAAM,iBAAiB,QAAO,cA6E7B,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/**
|
|
4
|
+
* Mapping from pseudo-state names to the CSS variable prefix used in
|
|
5
|
+
* the cascade-fallback pattern.
|
|
6
|
+
*
|
|
7
|
+
* This must stay in sync with PSEUDO_CSS_PREFIX in
|
|
8
|
+
* packages/style-engine/src/helpers/getStyleProp/getStyleProp.ts
|
|
9
|
+
*/
|
|
10
|
+
const PSEUDO_STATE_MAP = {
|
|
11
|
+
hover: "hover",
|
|
12
|
+
focus: "focus",
|
|
13
|
+
active: "active",
|
|
14
|
+
"focus-within": "focus-within",
|
|
15
|
+
disabled: "disabled",
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Maps pseudo-state names to their CSS selectors.
|
|
19
|
+
* Each state may have multiple selector variants (e.g. disabled also matches
|
|
20
|
+
* aria-disabled).
|
|
21
|
+
*/
|
|
22
|
+
const PSEUDO_SELECTORS = {
|
|
23
|
+
hover: [":hover"],
|
|
24
|
+
focus: [":focus-visible"],
|
|
25
|
+
active: [":active"],
|
|
26
|
+
"focus-within": [":has(:focus-within)"],
|
|
27
|
+
disabled: [":disabled", '[aria-disabled="true"]'],
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Extracts declarations from a rule that follow the pattern:
|
|
31
|
+
* property: var(--custom-prop);
|
|
32
|
+
*
|
|
33
|
+
* These are the declarations we'll generate pseudo-state variants for.
|
|
34
|
+
* We only match simple `var(--name)` references (no fallbacks in the base rule)
|
|
35
|
+
* since those are the style-engine-managed properties.
|
|
36
|
+
*/
|
|
37
|
+
function extractInteractiveDeclarations(rule) {
|
|
38
|
+
const declarations = [];
|
|
39
|
+
rule.walkDecls((decl) => {
|
|
40
|
+
// Skip custom property definitions (e.g. --background-color: none).
|
|
41
|
+
// We only want real CSS property declarations like `background-color: var(--background-color)`.
|
|
42
|
+
if (decl.prop.startsWith("--"))
|
|
43
|
+
return;
|
|
44
|
+
// Match `var(--some-name)` — simple variable reference with no fallback
|
|
45
|
+
const match = decl.value.match(/^var\((--[\w-]+)\)$/);
|
|
46
|
+
if (match && match[1]) {
|
|
47
|
+
declarations.push({
|
|
48
|
+
property: decl.prop,
|
|
49
|
+
cssVar: match[1],
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
return declarations;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Builds the pseudo-state selector string for a given base selector and state.
|
|
57
|
+
*
|
|
58
|
+
* Examples:
|
|
59
|
+
* buildSelector(".tgph-box", "hover")
|
|
60
|
+
* => ".tgph-box--interactive:hover"
|
|
61
|
+
* buildSelector(".tgph-box", "disabled")
|
|
62
|
+
* => ".tgph-box--interactive:disabled, .tgph-box--interactive[aria-disabled=\"true\"]"
|
|
63
|
+
*/
|
|
64
|
+
function buildSelector(baseSelector, state) {
|
|
65
|
+
const pseudoSelectors = PSEUDO_SELECTORS[state];
|
|
66
|
+
if (!pseudoSelectors)
|
|
67
|
+
return "";
|
|
68
|
+
return pseudoSelectors
|
|
69
|
+
.map((pseudo) => `${baseSelector}--interactive${pseudo}`)
|
|
70
|
+
.join(",\n");
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* PostCSS plugin: @telegraph/interactive
|
|
74
|
+
*
|
|
75
|
+
* Processes `@telegraph interactive(<selector>)` at-rules and auto-generates
|
|
76
|
+
* pseudo-class cascade rules based on the base rule's declarations.
|
|
77
|
+
*
|
|
78
|
+
* Input:
|
|
79
|
+
* .tgph-box {
|
|
80
|
+
* --background-color: none;
|
|
81
|
+
* background-color: var(--background-color);
|
|
82
|
+
* border-color: var(--border-color);
|
|
83
|
+
* }
|
|
84
|
+
* @telegraph interactive(.tgph-box);
|
|
85
|
+
*
|
|
86
|
+
* Output (appended):
|
|
87
|
+
* .tgph-box--interactive:hover {
|
|
88
|
+
* background-color: var(--hover--background-color, var(--background-color));
|
|
89
|
+
* border-color: var(--hover--border-color, var(--border-color));
|
|
90
|
+
* }
|
|
91
|
+
* .tgph-box--interactive:focus-visible { ... }
|
|
92
|
+
* .tgph-box--interactive:active { ... }
|
|
93
|
+
* .tgph-box--interactive:has(:focus-within) { ... }
|
|
94
|
+
* .tgph-box--interactive:disabled,
|
|
95
|
+
* .tgph-box--interactive[aria-disabled="true"] { ... }
|
|
96
|
+
*/
|
|
97
|
+
const interactivePlugin = () => {
|
|
98
|
+
return {
|
|
99
|
+
postcssPlugin: "@telegraph/interactive",
|
|
100
|
+
Once(root) {
|
|
101
|
+
// Collect all @telegraph interactive(...) directives
|
|
102
|
+
const directives = [];
|
|
103
|
+
root.walkAtRules("telegraph", (atRule) => {
|
|
104
|
+
const match = atRule.params.match(/^interactive\((.+)\)$/);
|
|
105
|
+
if (match && match[1]) {
|
|
106
|
+
directives.push({
|
|
107
|
+
atRule,
|
|
108
|
+
selector: match[1].trim(),
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
if (directives.length === 0)
|
|
113
|
+
return;
|
|
114
|
+
for (const { atRule, selector } of directives) {
|
|
115
|
+
// Find the base rule matching the selector
|
|
116
|
+
let baseRule = null;
|
|
117
|
+
root.walkRules((rule) => {
|
|
118
|
+
if (rule.selector === selector) {
|
|
119
|
+
baseRule = rule;
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
if (!baseRule) {
|
|
123
|
+
throw atRule.error(`@telegraph interactive: could not find base rule "${selector}" in this file.`);
|
|
124
|
+
}
|
|
125
|
+
const declarations = extractInteractiveDeclarations(baseRule);
|
|
126
|
+
if (declarations.length === 0) {
|
|
127
|
+
throw atRule.error(`@telegraph interactive: no "property: var(--name)" declarations found in "${selector}".`);
|
|
128
|
+
}
|
|
129
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
130
|
+
const postcss = require("postcss");
|
|
131
|
+
// Track the last inserted node so rules are appended in order
|
|
132
|
+
let lastInserted = atRule;
|
|
133
|
+
// Generate pseudo-state rules for each state
|
|
134
|
+
for (const state of Object.keys(PSEUDO_STATE_MAP)) {
|
|
135
|
+
const prefix = PSEUDO_STATE_MAP[state];
|
|
136
|
+
const pseudoSelector = buildSelector(selector, state);
|
|
137
|
+
if (!pseudoSelector)
|
|
138
|
+
continue;
|
|
139
|
+
const rule = postcss.rule({ selector: pseudoSelector });
|
|
140
|
+
for (const decl of declarations) {
|
|
141
|
+
rule.append(postcss.decl({
|
|
142
|
+
prop: decl.property,
|
|
143
|
+
value: `var(--${prefix}--${decl.cssVar.replace(/^--/, "")}, var(${decl.cssVar}))`,
|
|
144
|
+
}));
|
|
145
|
+
}
|
|
146
|
+
// Insert after the last inserted node to preserve order
|
|
147
|
+
atRule.parent?.insertAfter(lastInserted, rule);
|
|
148
|
+
lastInserted = rule;
|
|
149
|
+
}
|
|
150
|
+
// Remove the directive
|
|
151
|
+
atRule.remove();
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
};
|
|
155
|
+
};
|
|
156
|
+
exports.default = interactivePlugin;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"style-engine-postcss-config.d.ts","sourceRoot":"","sources":["../src/style-engine-postcss-config.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"style-engine-postcss-config.d.ts","sourceRoot":"","sources":["../src/style-engine-postcss-config.ts"],"names":[],"mappings":";;;AAGA,wBAgBE"}
|
|
@@ -1,13 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
4
|
+
const interactivePlugin = require("./interactive-plugin").default;
|
|
3
5
|
exports.default = {
|
|
4
6
|
plugins: [
|
|
7
|
+
// Must run before other plugins so that the generated rules are available
|
|
8
|
+
// for subsequent processing (e.g. autoprefixer, discard-empty).
|
|
9
|
+
interactivePlugin(),
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
5
11
|
require("postcss-discard-empty"),
|
|
12
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
6
13
|
require("autoprefixer"),
|
|
7
|
-
// eslint-disable-next-line @typescript-eslint/no-
|
|
14
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
8
15
|
require("@csstools/postcss-global-data")({
|
|
9
16
|
module: ["@telegraph/tokens/dist/css/breakpoints.css"],
|
|
10
17
|
}),
|
|
18
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
11
19
|
require("postcss-custom-media"),
|
|
12
20
|
],
|
|
13
21
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@telegraph/postcss-config",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"author": "@knocklabs",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": "https://github.com/knocklabs/telegraph/tree/main/packages/postcss-config",
|
|
@@ -18,10 +18,10 @@
|
|
|
18
18
|
"format:check": "prettier \"src/**/*.{js,ts,tsx}\" --check"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@csstools/postcss-global-data": "^
|
|
22
|
-
"@telegraph/tokens": "^0.1.
|
|
21
|
+
"@csstools/postcss-global-data": "^4.0.0",
|
|
22
|
+
"@telegraph/tokens": "^0.1.4",
|
|
23
23
|
"autoprefixer": "^10.4.21",
|
|
24
|
-
"postcss": "^8.5.
|
|
24
|
+
"postcss": "^8.5.6",
|
|
25
25
|
"postcss-combine-duplicated-selectors": "^10.0.3",
|
|
26
26
|
"postcss-custom-media": "^11.0.6",
|
|
27
27
|
"postcss-discard-empty": "^7.0.1"
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"@knocklabs/eslint-config": "^0.0.5",
|
|
31
31
|
"@knocklabs/typescript-config": "^0.0.2",
|
|
32
32
|
"@telegraph/prettier-config": "^0.0.7",
|
|
33
|
-
"eslint": "^
|
|
34
|
-
"typescript": "^5.9.
|
|
33
|
+
"eslint": "^10.0.2",
|
|
34
|
+
"typescript": "^5.9.3"
|
|
35
35
|
}
|
|
36
36
|
}
|