@clearstory/drywall-react 4.1.4 → 4.2.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/README.md +10 -0
- package/dist/eslint-config/index.d.ts +5 -0
- package/dist/eslint-config/index.js +29 -0
- package/dist/eslint-config/no-system-props.d.ts +3 -0
- package/dist/eslint-config/no-system-props.js +284 -0
- package/dist/eslint-config/no-system-props.test.d.ts +1 -0
- package/package.json +12 -4
package/README.md
CHANGED
|
@@ -35,3 +35,13 @@ function App() {
|
|
|
35
35
|
|
|
36
36
|
export default App;
|
|
37
37
|
```
|
|
38
|
+
|
|
39
|
+
## ESLint Rules
|
|
40
|
+
|
|
41
|
+
This library includes custom ESLint rules to help enforce best practices. Add to your `eslint.config.js`:
|
|
42
|
+
|
|
43
|
+
```js
|
|
44
|
+
import drywallReact from "@clearstory/drywall-react/eslint-config";
|
|
45
|
+
|
|
46
|
+
export default [drywallReact];
|
|
47
|
+
```
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import e from "./no-system-props.js";
|
|
2
|
+
const r = {
|
|
3
|
+
rules: {
|
|
4
|
+
"no-system-props": e
|
|
5
|
+
},
|
|
6
|
+
configs: {}
|
|
7
|
+
};
|
|
8
|
+
r.configs.recommended = {
|
|
9
|
+
name: "@clearstory/drywall-react/recommended",
|
|
10
|
+
plugins: {
|
|
11
|
+
"@clearstory/drywall-react": r
|
|
12
|
+
},
|
|
13
|
+
rules: {
|
|
14
|
+
"@clearstory/drywall-react/no-system-props": "error"
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
const s = {
|
|
18
|
+
name: "@clearstory/drywall-react",
|
|
19
|
+
plugins: {
|
|
20
|
+
"@clearstory/drywall-react": r
|
|
21
|
+
},
|
|
22
|
+
rules: {
|
|
23
|
+
"@clearstory/drywall-react/no-system-props": "error"
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
export {
|
|
27
|
+
s as default,
|
|
28
|
+
r as plugin
|
|
29
|
+
};
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
const b = [
|
|
2
|
+
// borders
|
|
3
|
+
"border",
|
|
4
|
+
"borderTop",
|
|
5
|
+
"borderRight",
|
|
6
|
+
"borderBottom",
|
|
7
|
+
"borderLeft",
|
|
8
|
+
"borderColor",
|
|
9
|
+
"borderTopColor",
|
|
10
|
+
"borderRightColor",
|
|
11
|
+
"borderBottomColor",
|
|
12
|
+
"borderLeftColor",
|
|
13
|
+
"outline",
|
|
14
|
+
"outlineColor",
|
|
15
|
+
"borderRadius",
|
|
16
|
+
// colors
|
|
17
|
+
"color",
|
|
18
|
+
"bgcolor",
|
|
19
|
+
"backgroundColor",
|
|
20
|
+
// spacing
|
|
21
|
+
"p",
|
|
22
|
+
"pt",
|
|
23
|
+
"pr",
|
|
24
|
+
"pb",
|
|
25
|
+
"pl",
|
|
26
|
+
"px",
|
|
27
|
+
"py",
|
|
28
|
+
"padding",
|
|
29
|
+
"paddingTop",
|
|
30
|
+
"paddingRight",
|
|
31
|
+
"paddingBottom",
|
|
32
|
+
"paddingLeft",
|
|
33
|
+
"paddingX",
|
|
34
|
+
"paddingY",
|
|
35
|
+
"paddingInline",
|
|
36
|
+
"paddingInlineStart",
|
|
37
|
+
"paddingInlineEnd",
|
|
38
|
+
"paddingBlock",
|
|
39
|
+
"paddingBlockStart",
|
|
40
|
+
"paddingBlockEnd",
|
|
41
|
+
"m",
|
|
42
|
+
"mt",
|
|
43
|
+
"mr",
|
|
44
|
+
"mb",
|
|
45
|
+
"ml",
|
|
46
|
+
"mx",
|
|
47
|
+
"my",
|
|
48
|
+
"margin",
|
|
49
|
+
"marginTop",
|
|
50
|
+
"marginRight",
|
|
51
|
+
"marginBottom",
|
|
52
|
+
"marginLeft",
|
|
53
|
+
"marginX",
|
|
54
|
+
"marginY",
|
|
55
|
+
"marginInline",
|
|
56
|
+
"marginInlineStart",
|
|
57
|
+
"marginInlineEnd",
|
|
58
|
+
"marginBlock",
|
|
59
|
+
"marginBlockStart",
|
|
60
|
+
"marginBlockEnd",
|
|
61
|
+
// display
|
|
62
|
+
"displayPrint",
|
|
63
|
+
"display",
|
|
64
|
+
"overflow",
|
|
65
|
+
"textOverflow",
|
|
66
|
+
"visibility",
|
|
67
|
+
"whiteSpace",
|
|
68
|
+
// flexbox
|
|
69
|
+
"flexBasis",
|
|
70
|
+
"flexDirection",
|
|
71
|
+
"flexWrap",
|
|
72
|
+
"justifyContent",
|
|
73
|
+
"alignItems",
|
|
74
|
+
"alignContent",
|
|
75
|
+
"order",
|
|
76
|
+
"flex",
|
|
77
|
+
"flexGrow",
|
|
78
|
+
"flexShrink",
|
|
79
|
+
"alignSelf",
|
|
80
|
+
"justifyItems",
|
|
81
|
+
"justifySelf",
|
|
82
|
+
"gap",
|
|
83
|
+
"rowGap",
|
|
84
|
+
"columnGap",
|
|
85
|
+
// grid
|
|
86
|
+
"gridColumn",
|
|
87
|
+
"gridRow",
|
|
88
|
+
"gridAutoFlow",
|
|
89
|
+
"gridAutoColumns",
|
|
90
|
+
"gridAutoRows",
|
|
91
|
+
"gridTemplateColumns",
|
|
92
|
+
"gridTemplateRows",
|
|
93
|
+
"gridTemplateAreas",
|
|
94
|
+
"gridArea",
|
|
95
|
+
// positions
|
|
96
|
+
"position",
|
|
97
|
+
"zIndex",
|
|
98
|
+
"top",
|
|
99
|
+
"right",
|
|
100
|
+
"bottom",
|
|
101
|
+
"left",
|
|
102
|
+
// shadows
|
|
103
|
+
"boxShadow",
|
|
104
|
+
// sizing
|
|
105
|
+
"width",
|
|
106
|
+
"maxWidth",
|
|
107
|
+
"minWidth",
|
|
108
|
+
"height",
|
|
109
|
+
"maxHeight",
|
|
110
|
+
"minHeight",
|
|
111
|
+
"boxSizing",
|
|
112
|
+
// typography
|
|
113
|
+
"font",
|
|
114
|
+
"fontFamily",
|
|
115
|
+
"fontSize",
|
|
116
|
+
"fontStyle",
|
|
117
|
+
"fontWeight",
|
|
118
|
+
"letterSpacing",
|
|
119
|
+
"textTransform",
|
|
120
|
+
"lineHeight",
|
|
121
|
+
"textAlign",
|
|
122
|
+
"typography",
|
|
123
|
+
// other common system props
|
|
124
|
+
"spacing"
|
|
125
|
+
], S = ["Box", "Stack", "Typography", "Link"], w = {
|
|
126
|
+
Typography: ["color"],
|
|
127
|
+
// semantic colors only
|
|
128
|
+
Link: ["color"]
|
|
129
|
+
}, T = {
|
|
130
|
+
meta: {
|
|
131
|
+
type: "problem",
|
|
132
|
+
docs: {
|
|
133
|
+
description: "Disallow system props on @clearstory/drywall-react components",
|
|
134
|
+
category: "Best Practices",
|
|
135
|
+
recommended: !0
|
|
136
|
+
},
|
|
137
|
+
fixable: "code",
|
|
138
|
+
messages: {
|
|
139
|
+
systemProp: 'System prop "{{prop}}" should be moved to the sx prop on {{component}} component'
|
|
140
|
+
},
|
|
141
|
+
schema: []
|
|
142
|
+
},
|
|
143
|
+
create(s) {
|
|
144
|
+
const o = /* @__PURE__ */ new Set(), u = /* @__PURE__ */ new Set(), g = s.getSourceCode();
|
|
145
|
+
return {
|
|
146
|
+
ImportDeclaration(l) {
|
|
147
|
+
const e = l;
|
|
148
|
+
e.source.value === "@clearstory/drywall-react" && e.specifiers.forEach((r) => {
|
|
149
|
+
r.type === "ImportSpecifier" && r.imported && S.includes(r.imported.name) ? o.add(r.local.name) : r.type === "ImportNamespaceSpecifier" && u.add(r.local.name);
|
|
150
|
+
});
|
|
151
|
+
},
|
|
152
|
+
JSXOpeningElement(l) {
|
|
153
|
+
const e = l;
|
|
154
|
+
let r;
|
|
155
|
+
if ("name" in e.name) {
|
|
156
|
+
if (r = e.name.name, !o.has(r))
|
|
157
|
+
return;
|
|
158
|
+
} else if (e.name.type === "JSXMemberExpression") {
|
|
159
|
+
const a = e.name.object.name;
|
|
160
|
+
if (r = e.name.property.name, !u.has(a) || !S.includes(r))
|
|
161
|
+
return;
|
|
162
|
+
} else
|
|
163
|
+
return;
|
|
164
|
+
const p = [];
|
|
165
|
+
let x = null;
|
|
166
|
+
e.attributes.forEach((a) => {
|
|
167
|
+
const t = a;
|
|
168
|
+
if (t.type !== "JSXAttribute" || !t.name)
|
|
169
|
+
return;
|
|
170
|
+
const d = t.name.name;
|
|
171
|
+
if (d === "sx") {
|
|
172
|
+
x = t;
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
if (!b.includes(d))
|
|
176
|
+
return;
|
|
177
|
+
const y = w[r];
|
|
178
|
+
if (y && y.includes(d))
|
|
179
|
+
if (d === "color" && t.value) {
|
|
180
|
+
const h = $(t.value);
|
|
181
|
+
if (C(h))
|
|
182
|
+
return;
|
|
183
|
+
} else
|
|
184
|
+
return;
|
|
185
|
+
p.push(
|
|
186
|
+
t
|
|
187
|
+
);
|
|
188
|
+
}), p.forEach((a) => {
|
|
189
|
+
s.report({
|
|
190
|
+
node: a,
|
|
191
|
+
messageId: "systemProp",
|
|
192
|
+
data: {
|
|
193
|
+
prop: a.name.name,
|
|
194
|
+
component: r
|
|
195
|
+
},
|
|
196
|
+
fix(t) {
|
|
197
|
+
return I(
|
|
198
|
+
t,
|
|
199
|
+
l,
|
|
200
|
+
p,
|
|
201
|
+
x,
|
|
202
|
+
g
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
function $(s) {
|
|
212
|
+
if (!s) return null;
|
|
213
|
+
const o = s;
|
|
214
|
+
if (o.type === "Literal")
|
|
215
|
+
return String(o.value);
|
|
216
|
+
if (o.type === "JSXExpressionContainer" && o.expression) {
|
|
217
|
+
if (o.expression.type === "Literal")
|
|
218
|
+
return String(o.expression.value);
|
|
219
|
+
if (o.expression.type === "Identifier")
|
|
220
|
+
return o.expression.name || null;
|
|
221
|
+
}
|
|
222
|
+
return null;
|
|
223
|
+
}
|
|
224
|
+
function C(s) {
|
|
225
|
+
return [
|
|
226
|
+
"inherit",
|
|
227
|
+
"primary",
|
|
228
|
+
"secondary",
|
|
229
|
+
"error",
|
|
230
|
+
"warning",
|
|
231
|
+
"info",
|
|
232
|
+
"success"
|
|
233
|
+
].includes(s || "");
|
|
234
|
+
}
|
|
235
|
+
function I(s, o, u, g, l) {
|
|
236
|
+
const e = o, r = "name" in e.name ? e.name.name : e.name.type === "JSXMemberExpression" ? `${e.name.object.name}.${e.name.property.name}` : "UnknownComponent", p = u.map((i) => {
|
|
237
|
+
const n = i.name.name, m = i.value;
|
|
238
|
+
if (!m)
|
|
239
|
+
return `${n}: true`;
|
|
240
|
+
const c = m;
|
|
241
|
+
if (c.type === "Literal")
|
|
242
|
+
return `${n}: ${JSON.stringify(c.value)}`;
|
|
243
|
+
if (c.type === "JSXExpressionContainer" && c.expression) {
|
|
244
|
+
const f = l.getText(c.expression);
|
|
245
|
+
return `${n}: ${f}`;
|
|
246
|
+
}
|
|
247
|
+
return `${n}: true`;
|
|
248
|
+
}), x = new Set(
|
|
249
|
+
u.map((i) => i.name.name)
|
|
250
|
+
), a = [];
|
|
251
|
+
e.attributes.forEach((i) => {
|
|
252
|
+
const n = i;
|
|
253
|
+
if (n.type !== "JSXAttribute" || !n.name) {
|
|
254
|
+
a.push(l.getText(i));
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
const m = n.name.name;
|
|
258
|
+
x.has(m) || m === "sx" && g || a.push(l.getText(i));
|
|
259
|
+
});
|
|
260
|
+
let t;
|
|
261
|
+
if (g) {
|
|
262
|
+
const i = l.getText(g.value);
|
|
263
|
+
if (i.startsWith("{") && i.endsWith("}")) {
|
|
264
|
+
const n = i.slice(1, -1).trim();
|
|
265
|
+
if (n.startsWith("{") && n.endsWith("}"))
|
|
266
|
+
t = `sx={{ ${p.join(", ")}, ...${n} }}`;
|
|
267
|
+
else if (n.startsWith("[") && n.endsWith("]"))
|
|
268
|
+
t = `sx={[{ ${p.join(", ")} }, ...${n}]}`;
|
|
269
|
+
else {
|
|
270
|
+
const m = n.trimStart(), f = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(
|
|
271
|
+
m
|
|
272
|
+
) ? m : n;
|
|
273
|
+
t = `sx={[{ ${p.join(", ")} }, ...(Array.isArray(${f}) ? ${f} : [${f}])]}`;
|
|
274
|
+
}
|
|
275
|
+
} else
|
|
276
|
+
t = `sx={{ ${p.join(", ")} }}`;
|
|
277
|
+
} else
|
|
278
|
+
t = `sx={{ ${p.join(", ")} }}`;
|
|
279
|
+
const d = [...a, t], y = d.length > 0 ? " " + d.join(" ") : "", h = `<${r}${y}${e.selfClosing ? " />" : ">"}`;
|
|
280
|
+
return [s.replaceText(o, h)];
|
|
281
|
+
}
|
|
282
|
+
export {
|
|
283
|
+
T as default
|
|
284
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clearstory/drywall-react",
|
|
3
|
-
"version": "4.1
|
|
3
|
+
"version": "4.2.1",
|
|
4
4
|
"license": "UNLICENSED",
|
|
5
5
|
"description": "a Clearstory software design system",
|
|
6
6
|
"type": "module",
|
|
7
|
-
"
|
|
8
|
-
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/main.d.ts",
|
|
10
|
+
"import": "./dist/main.js"
|
|
11
|
+
},
|
|
12
|
+
"./eslint-config": {
|
|
13
|
+
"types": "./dist/eslint-config/index.d.ts",
|
|
14
|
+
"import": "./dist/eslint-config/index.js"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
9
17
|
"publishConfig": {
|
|
10
18
|
"access": "public"
|
|
11
19
|
},
|
|
@@ -78,6 +86,6 @@
|
|
|
78
86
|
"preview": "vite preview",
|
|
79
87
|
"storybook": "storybook dev -p 6006",
|
|
80
88
|
"build-storybook": "storybook build",
|
|
81
|
-
"test": "vitest
|
|
89
|
+
"test": "vitest"
|
|
82
90
|
}
|
|
83
91
|
}
|