design-system-silkhaus 4.0.0-beta.combine-tailwind-config.1 → 4.0.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/dist/app/index.d.ts +35 -3
- package/dist/app/index.js +8 -277
- package/dist/eslint-rules/tailwind/no-hardcoded-colors.js +65 -0
- package/dist/eslint-rules/tailwind/no-restricted-tokens.js +79 -0
- package/dist/{ButtonsGroupSelector-sjBrndhv.js → index-BT5jeJCy.js} +1971 -1568
- package/dist/index.d.ts +86 -1
- package/dist/index.js +7300 -6754
- package/dist/style.css +1 -1
- package/dist/tailwind.config.js +106 -35
- package/package.json +9 -3
package/dist/app/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { default as default_2 } from 'react';
|
|
2
2
|
import { FC } from 'react';
|
|
3
3
|
import { HTMLAttributes } from 'react';
|
|
4
|
+
import { JSX as JSX_2 } from 'react/jsx-runtime';
|
|
4
5
|
import { Placement } from '@floating-ui/react';
|
|
5
6
|
import { PropsWithChildren } from 'react';
|
|
6
7
|
import { ReactNode } from 'react';
|
|
@@ -78,6 +79,24 @@ export declare type DropdownOption = {
|
|
|
78
79
|
disabled?: boolean;
|
|
79
80
|
};
|
|
80
81
|
|
|
82
|
+
export declare const DropdownOption: ({ onClick, option, isSelected, showCheckbox, }: {
|
|
83
|
+
onClick: () => void;
|
|
84
|
+
option: DropdownOption;
|
|
85
|
+
isSelected: boolean;
|
|
86
|
+
showCheckbox?: boolean;
|
|
87
|
+
}) => JSX_2.Element;
|
|
88
|
+
|
|
89
|
+
export declare const DropdownOptions: ({ options, isMultiSelect, value, setValue, setIsOpen, onChange, selectAllOptionLabel, disableSelectAll, }: {
|
|
90
|
+
options: DropdownOption[];
|
|
91
|
+
isMultiSelect?: boolean;
|
|
92
|
+
value: DropdownProps["value"];
|
|
93
|
+
setValue: (value: DropdownProps["value"]) => void;
|
|
94
|
+
setIsOpen: (isOpen: boolean) => void;
|
|
95
|
+
onChange?: DropdownProps["onChange"];
|
|
96
|
+
selectAllOptionLabel?: string;
|
|
97
|
+
disableSelectAll?: boolean;
|
|
98
|
+
}) => JSX_2.Element;
|
|
99
|
+
|
|
81
100
|
export declare interface DropdownProps {
|
|
82
101
|
/**
|
|
83
102
|
* The options of the dropdown
|
|
@@ -94,7 +113,7 @@ export declare interface DropdownProps {
|
|
|
94
113
|
/**
|
|
95
114
|
* Callback when dropdown value is changed
|
|
96
115
|
*/
|
|
97
|
-
onChange?: (selectedOption: DropdownOption | DropdownOption[]) => void;
|
|
116
|
+
onChange?: (selectedOption: DropdownOption | DropdownOption[], isSelectAll?: boolean) => void;
|
|
98
117
|
/**
|
|
99
118
|
* Pass this callback function if you want to override the default selected value display text.
|
|
100
119
|
* By default the dropdown will display the label from the selected option
|
|
@@ -142,10 +161,23 @@ export declare interface DropdownProps {
|
|
|
142
161
|
* @default 'Close'
|
|
143
162
|
*/
|
|
144
163
|
closeButtonLabel?: string;
|
|
164
|
+
/**
|
|
165
|
+
* Pass true to disable the select all option in multi-select dropdown
|
|
166
|
+
* @default false
|
|
167
|
+
*/
|
|
168
|
+
disableSelectAll?: boolean;
|
|
169
|
+
/**
|
|
170
|
+
* The label for Select all option
|
|
171
|
+
* @default 'Select all'
|
|
172
|
+
*/
|
|
173
|
+
selectAllOptionLabel?: string;
|
|
174
|
+
/**
|
|
175
|
+
* The selected value label to show when 'Select All' option is checked
|
|
176
|
+
* @default 'All'
|
|
177
|
+
*/
|
|
178
|
+
allSelectedLabel?: string;
|
|
145
179
|
}
|
|
146
180
|
|
|
147
|
-
export declare const findOptionByValue: (value: string | string[] | undefined, options: DropdownOption[]) => DropdownOption | DropdownOption[] | undefined;
|
|
148
|
-
|
|
149
181
|
export declare const MobileDropdown: FC<PropsWithChildren<DropdownProps>>;
|
|
150
182
|
|
|
151
183
|
declare type OptionType = {
|
package/dist/app/index.js
CHANGED
|
@@ -1,279 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
var L = Object.getOwnPropertyDescriptors;
|
|
3
|
-
var C = Object.getOwnPropertySymbols;
|
|
4
|
-
var Q = Object.prototype.hasOwnProperty, X = Object.prototype.propertyIsEnumerable;
|
|
5
|
-
var I = (s, e, a) => e in s ? J(s, e, { enumerable: !0, configurable: !0, writable: !0, value: a }) : s[e] = a, x = (s, e) => {
|
|
6
|
-
for (var a in e || (e = {}))
|
|
7
|
-
Q.call(e, a) && I(s, a, e[a]);
|
|
8
|
-
if (C)
|
|
9
|
-
for (var a of C(e))
|
|
10
|
-
X.call(e, a) && I(s, a, e[a]);
|
|
11
|
-
return s;
|
|
12
|
-
}, k = (s, e) => K(s, L(e));
|
|
13
|
-
import { j as d, p as Y, u as Z, o as _, i as O, s as ss, r as es, v as ds, d as as, e as ls, f as ts, g as rs, a as m, F as ns, A as is, h as os, D as cs, x as us, C as fs, l as xs, k as ms, n as ps } from "../ButtonsGroupSelector-sjBrndhv.js";
|
|
14
|
-
import { w as ks } from "../ButtonsGroupSelector-sjBrndhv.js";
|
|
15
|
-
import { useState as b } from "react";
|
|
16
|
-
const hs = (s) => window.innerWidth < Y ? /* @__PURE__ */ d.jsx(R, x({}, s)) : /* @__PURE__ */ d.jsx(M, x({}, s));
|
|
17
|
-
hs.displayName = "Dropdown";
|
|
18
|
-
const M = ({
|
|
19
|
-
placement: s = "bottom-start",
|
|
20
|
-
trigger: e,
|
|
21
|
-
triggerContainerClassName: a,
|
|
22
|
-
disabled: l,
|
|
23
|
-
onOpenChange: o,
|
|
24
|
-
adjustHeight: n = !0,
|
|
25
|
-
adjustWidth: t = !0,
|
|
26
|
-
options: r,
|
|
27
|
-
getSelectedValueDisplayText: i = P,
|
|
28
|
-
placeholder: u,
|
|
29
|
-
value: f,
|
|
30
|
-
isMultiSelect: y,
|
|
31
|
-
onChange: w
|
|
32
|
-
}) => {
|
|
33
|
-
const [p, N] = b(), h = typeof f == "undefined" ? p : f, c = typeof f == "undefined" ? N : () => {
|
|
34
|
-
}, [A, F] = b(!1), { refs: g, floatingStyles: B, context: j } = Z({
|
|
35
|
-
open: A,
|
|
36
|
-
onOpenChange: (v) => {
|
|
37
|
-
F(v), o && o(v);
|
|
38
|
-
},
|
|
39
|
-
middleware: [
|
|
40
|
-
_(8),
|
|
41
|
-
O({
|
|
42
|
-
crossAxis: s.includes("-"),
|
|
43
|
-
fallbackAxisSideDirection: "end"
|
|
44
|
-
}),
|
|
45
|
-
ss({ padding: 4 }),
|
|
46
|
-
es({
|
|
47
|
-
apply({ availableWidth: v, availableHeight: q, elements: z }) {
|
|
48
|
-
n && (z.floating.style.maxHeight = `${q - 4}px`), t && (z.floating.style.maxWidth = `${v - 4}px`);
|
|
49
|
-
}
|
|
50
|
-
})
|
|
51
|
-
],
|
|
52
|
-
whileElementsMounted: os,
|
|
53
|
-
placement: s
|
|
54
|
-
}), E = ds(j), W = as(j), $ = ls(j), G = ts(j), { getReferenceProps: T, getFloatingProps: H } = rs([E, W, $, G]);
|
|
55
|
-
return e || (e = /* @__PURE__ */ d.jsx(
|
|
56
|
-
U,
|
|
57
|
-
{
|
|
58
|
-
selectedOption: D(h, r),
|
|
59
|
-
getSelectedValueDisplayText: i,
|
|
60
|
-
placeholder: u
|
|
61
|
-
}
|
|
62
|
-
)), l ? /* @__PURE__ */ d.jsx("div", { className: a, children: e }) : /* @__PURE__ */ d.jsxs(d.Fragment, { children: [
|
|
63
|
-
/* @__PURE__ */ d.jsx(
|
|
64
|
-
"div",
|
|
65
|
-
k(x({
|
|
66
|
-
className: m("ds-cursor-pointer", a),
|
|
67
|
-
ref: g.setReference
|
|
68
|
-
}, T()), {
|
|
69
|
-
children: e
|
|
70
|
-
})
|
|
71
|
-
),
|
|
72
|
-
A && /* @__PURE__ */ d.jsx(ns, { children: /* @__PURE__ */ d.jsx(
|
|
73
|
-
"div",
|
|
74
|
-
k(x({
|
|
75
|
-
ref: g.setFloating,
|
|
76
|
-
style: B
|
|
77
|
-
}, H()), {
|
|
78
|
-
className: m(
|
|
79
|
-
"ds-z-[29999] ds-flex ds-min-w-[200px] ds-flex-col ds-gap-1 ds-rounded ds-bg-white ds-p-2 ds-shadow-md",
|
|
80
|
-
n && "ds-overflow-y-auto",
|
|
81
|
-
t && "ds-overflow-x-auto"
|
|
82
|
-
),
|
|
83
|
-
children: /* @__PURE__ */ d.jsx(
|
|
84
|
-
V,
|
|
85
|
-
{
|
|
86
|
-
isMultiSelect: y,
|
|
87
|
-
options: r,
|
|
88
|
-
value: h,
|
|
89
|
-
setValue: c,
|
|
90
|
-
setIsOpen: F,
|
|
91
|
-
onChange: w
|
|
92
|
-
}
|
|
93
|
-
)
|
|
94
|
-
})
|
|
95
|
-
) })
|
|
96
|
-
] });
|
|
97
|
-
};
|
|
98
|
-
M.displayName = "DesktopDropdown";
|
|
99
|
-
const R = ({
|
|
100
|
-
trigger: s,
|
|
101
|
-
triggerContainerClassName: e,
|
|
102
|
-
disabled: a,
|
|
103
|
-
onOpenChange: l,
|
|
104
|
-
getSelectedValueDisplayText: o = P,
|
|
105
|
-
placeholder: n,
|
|
106
|
-
value: t,
|
|
107
|
-
options: r,
|
|
108
|
-
isMultiSelect: i,
|
|
109
|
-
onChange: u,
|
|
110
|
-
closeButtonLabel: f = "Close"
|
|
111
|
-
}) => {
|
|
112
|
-
const [y, w] = b(), p = typeof t == "undefined" ? y : t, N = typeof t == "undefined" ? w : () => {
|
|
113
|
-
}, [h, c] = b(!1);
|
|
114
|
-
return s || (s = /* @__PURE__ */ d.jsx(
|
|
115
|
-
U,
|
|
116
|
-
{
|
|
117
|
-
selectedOption: D(p, r),
|
|
118
|
-
getSelectedValueDisplayText: o,
|
|
119
|
-
placeholder: n
|
|
120
|
-
}
|
|
121
|
-
)), a ? /* @__PURE__ */ d.jsx("div", { className: e, children: s }) : /* @__PURE__ */ d.jsxs(d.Fragment, { children: [
|
|
122
|
-
/* @__PURE__ */ d.jsx(
|
|
123
|
-
"div",
|
|
124
|
-
{
|
|
125
|
-
className: e,
|
|
126
|
-
onClick: () => {
|
|
127
|
-
c(!0), l && l(!0);
|
|
128
|
-
},
|
|
129
|
-
children: s
|
|
130
|
-
}
|
|
131
|
-
),
|
|
132
|
-
/* @__PURE__ */ d.jsx(
|
|
133
|
-
is,
|
|
134
|
-
{
|
|
135
|
-
animation: "slideUp",
|
|
136
|
-
show: h,
|
|
137
|
-
handleClose: () => {
|
|
138
|
-
c(!1), l && l(!1);
|
|
139
|
-
},
|
|
140
|
-
contentClassName: m("ds-absolute ds-mb-0 ds-w-full"),
|
|
141
|
-
className: "ds-z-[29999]",
|
|
142
|
-
children: /* @__PURE__ */ d.jsx(
|
|
143
|
-
S,
|
|
144
|
-
{
|
|
145
|
-
onClose: () => {
|
|
146
|
-
c(!1), l && l(!1);
|
|
147
|
-
},
|
|
148
|
-
closeButtonLabel: f,
|
|
149
|
-
children: /* @__PURE__ */ d.jsx(
|
|
150
|
-
V,
|
|
151
|
-
{
|
|
152
|
-
isMultiSelect: i,
|
|
153
|
-
options: r,
|
|
154
|
-
value: p,
|
|
155
|
-
setValue: N,
|
|
156
|
-
setIsOpen: c,
|
|
157
|
-
onChange: u
|
|
158
|
-
}
|
|
159
|
-
)
|
|
160
|
-
}
|
|
161
|
-
)
|
|
162
|
-
}
|
|
163
|
-
)
|
|
164
|
-
] });
|
|
165
|
-
};
|
|
166
|
-
R.displayName = "MobileDropdown";
|
|
167
|
-
const S = ({ onClose: s, closeButtonLabel: e, children: a }) => /* @__PURE__ */ d.jsxs("div", { className: "ds-mb-0 ds-flex ds-max-h-dvh ds-w-full ds-flex-col ds-bg-white", children: [
|
|
168
|
-
/* @__PURE__ */ d.jsxs("div", { className: "ds-flex ds-shrink-0 ds-items-center ds-justify-between ds-px-8 ds-py-4", children: [
|
|
169
|
-
/* @__PURE__ */ d.jsx(
|
|
170
|
-
"div",
|
|
171
|
-
{
|
|
172
|
-
onClick: s,
|
|
173
|
-
className: "ds-flex ds-size-5 ds-cursor-pointer ds-items-center ds-justify-center",
|
|
174
|
-
children: /* @__PURE__ */ d.jsx(fs, { className: "ds-size-4" })
|
|
175
|
-
}
|
|
176
|
-
),
|
|
177
|
-
/* @__PURE__ */ d.jsx("div", { className: "ds-size-5" })
|
|
178
|
-
] }),
|
|
179
|
-
/* @__PURE__ */ d.jsx("div", { className: "ds-grow ds-overflow-y-auto ds-p-4 ds-text-xSmallCalloutRegular", children: a }),
|
|
180
|
-
/* @__PURE__ */ d.jsx("div", { className: "ds-px-8 ds-py-4", children: /* @__PURE__ */ d.jsx(
|
|
181
|
-
xs,
|
|
182
|
-
{
|
|
183
|
-
buttonClassName: "ds-py-3",
|
|
184
|
-
onClick: s,
|
|
185
|
-
children: e
|
|
186
|
-
}
|
|
187
|
-
) })
|
|
188
|
-
] });
|
|
189
|
-
S.displayName = "MobilePopoverContentWrapper";
|
|
190
|
-
const U = ({
|
|
191
|
-
selectedOption: s,
|
|
192
|
-
getSelectedValueDisplayText: e,
|
|
193
|
-
placeholder: a
|
|
194
|
-
}) => {
|
|
195
|
-
const l = !s || Array.isArray(s) && s.length === 0 ? a || "" : e(s);
|
|
196
|
-
return /* @__PURE__ */ d.jsx(
|
|
197
|
-
cs,
|
|
198
|
-
{
|
|
199
|
-
color: "secondary",
|
|
200
|
-
endIcon: /* @__PURE__ */ d.jsx(us, { className: "ds-size-4" }),
|
|
201
|
-
buttonClassName: "ds-justify-between",
|
|
202
|
-
children: l
|
|
203
|
-
}
|
|
204
|
-
);
|
|
205
|
-
}, V = ({
|
|
206
|
-
options: s,
|
|
207
|
-
isMultiSelect: e,
|
|
208
|
-
value: a,
|
|
209
|
-
setValue: l,
|
|
210
|
-
setIsOpen: o,
|
|
211
|
-
onChange: n
|
|
212
|
-
}) => s && s.map((t) => /* @__PURE__ */ d.jsx(
|
|
213
|
-
js,
|
|
214
|
-
{
|
|
215
|
-
onClick: () => {
|
|
216
|
-
let r;
|
|
217
|
-
if (e) {
|
|
218
|
-
const i = a || [];
|
|
219
|
-
i.includes(t.value) ? r = i.filter((u) => u !== t.value) : r = [...i, t.value];
|
|
220
|
-
} else
|
|
221
|
-
r = t.value, o(!1);
|
|
222
|
-
l(r), n && n(D(r, s));
|
|
223
|
-
},
|
|
224
|
-
option: t,
|
|
225
|
-
isSelected: Array.isArray(a) ? a.some((r) => r === t.value) : a === t.value,
|
|
226
|
-
showCheckbox: e
|
|
227
|
-
},
|
|
228
|
-
t.value
|
|
229
|
-
)), js = ({
|
|
230
|
-
onClick: s,
|
|
231
|
-
option: e,
|
|
232
|
-
isSelected: a,
|
|
233
|
-
showCheckbox: l
|
|
234
|
-
}) => /* @__PURE__ */ d.jsxs(
|
|
235
|
-
"div",
|
|
236
|
-
{
|
|
237
|
-
onClick: e.disabled ? void 0 : s,
|
|
238
|
-
className: m(
|
|
239
|
-
"ds-group ds-flex ds-min-h-[72px] ds-cursor-pointer ds-items-center ds-gap-4 ds-rounded ds-px-4 ds-py-2 ds-text-mediumSubHeadEmphasized hover:ds-bg-[#F6F8FC] ds-tablet:ds-min-h-[auto] ds-tablet:ds-gap-2 ds-tablet:ds-px-2 ds-desktop:ds-text-mediumFootnoteEmphasized",
|
|
240
|
-
!l && "ds-transition-[padding] ds-duration-300 hover:ds-px-4"
|
|
241
|
-
),
|
|
242
|
-
children: [
|
|
243
|
-
e.thumbnailUrl && /* @__PURE__ */ d.jsx(
|
|
244
|
-
"img",
|
|
245
|
-
{
|
|
246
|
-
src: e.thumbnailUrl,
|
|
247
|
-
className: "ds-h-14 ds-w-14 ds-shrink-0 ds-rounded ds-object-cover group-hover:ds-pr-0 ds-tablet:ds-h-6 ds-tablet:ds-w-9 ds-tablet:ds-rounded-sm"
|
|
248
|
-
}
|
|
249
|
-
),
|
|
250
|
-
e.icon,
|
|
251
|
-
/* @__PURE__ */ d.jsx(
|
|
252
|
-
"div",
|
|
253
|
-
{
|
|
254
|
-
className: m(
|
|
255
|
-
"ds-flex-grow",
|
|
256
|
-
!l && "ds-transition-[padding] ds-duration-300 group-hover:ds-pr-0 ds-tablet:ds-pr-4"
|
|
257
|
-
),
|
|
258
|
-
children: e.label
|
|
259
|
-
}
|
|
260
|
-
),
|
|
261
|
-
a && !l && /* @__PURE__ */ d.jsx(ms, { className: "ds-size-4 ds-shrink-0" }),
|
|
262
|
-
l && /* @__PURE__ */ d.jsx(
|
|
263
|
-
ps,
|
|
264
|
-
{
|
|
265
|
-
isChecked: a,
|
|
266
|
-
disabled: e.disabled
|
|
267
|
-
}
|
|
268
|
-
)
|
|
269
|
-
]
|
|
270
|
-
}
|
|
271
|
-
), D = (s, e) => Array.isArray(s) ? e.filter((a) => s.includes(a.value)) : e.find((a) => a.value === s), P = (s) => Array.isArray(s) ? s.map((e) => e.label).join(", ") : s.label;
|
|
1
|
+
import { B as s, a as n, b as r, D as t, d as a, c as D, M as d } from "../index-BT5jeJCy.js";
|
|
272
2
|
export {
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
D as
|
|
3
|
+
s as Button,
|
|
4
|
+
n as ButtonsGroupSelector,
|
|
5
|
+
r as DesktopDropdown,
|
|
6
|
+
t as Dropdown,
|
|
7
|
+
a as DropdownOption,
|
|
8
|
+
D as DropdownOptions,
|
|
9
|
+
d as MobileDropdown
|
|
279
10
|
};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
meta: {
|
|
3
|
+
type: 'problem',
|
|
4
|
+
docs: {
|
|
5
|
+
description: 'Disallow hardcoded color values like hex, rgb, rgba, hsl, hsla',
|
|
6
|
+
recommended: false,
|
|
7
|
+
},
|
|
8
|
+
messages: {
|
|
9
|
+
hardcodedColor:
|
|
10
|
+
"Do not use hardcoded color value: '{{ color }}'. Use a tailwind class with design token name instead",
|
|
11
|
+
},
|
|
12
|
+
schema: [],
|
|
13
|
+
},
|
|
14
|
+
|
|
15
|
+
create(context) {
|
|
16
|
+
const COLOR_REGEX = new RegExp(
|
|
17
|
+
/#(?:[0-9a-fA-F]{3,8})\b|(rgb|hsl)a?\(\s*\d+\s*,\s*\d+%?\s*,\s*\d+%?(?:\s*,\s*(?:\d+(?:\.\d+)?|\.\d+))?\s*\)/,
|
|
18
|
+
'i',
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
function reportIfHardcodedColor(node, value) {
|
|
22
|
+
const match = value.match(COLOR_REGEX);
|
|
23
|
+
if (match) {
|
|
24
|
+
context.report({
|
|
25
|
+
node,
|
|
26
|
+
messageId: 'hardcodedColor',
|
|
27
|
+
data: {
|
|
28
|
+
color: match[0],
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
Literal(node) {
|
|
36
|
+
if (typeof node.value === 'string') {
|
|
37
|
+
reportIfHardcodedColor(node, node.value);
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
JSXAttribute(node) {
|
|
42
|
+
if (node.name && ['class', 'className', 'style'].includes(node.name.name) && node.value) {
|
|
43
|
+
if (node.value.type === 'Literal' && typeof node.value.value === 'string') {
|
|
44
|
+
reportIfHardcodedColor(node.value, node.value.value);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (
|
|
48
|
+
node.value.type === 'JSXExpressionContainer' &&
|
|
49
|
+
node.value.expression &&
|
|
50
|
+
node.value.expression.type === 'Literal' &&
|
|
51
|
+
typeof node.value.expression.value === 'string'
|
|
52
|
+
) {
|
|
53
|
+
reportIfHardcodedColor(node.value.expression, node.value.expression.value);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
|
|
58
|
+
TemplateLiteral(node) {
|
|
59
|
+
node.quasis.forEach((quasi) => {
|
|
60
|
+
reportIfHardcodedColor(quasi, quasi.value.cooked || '');
|
|
61
|
+
});
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
},
|
|
65
|
+
};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
meta: {
|
|
3
|
+
type: 'problem',
|
|
4
|
+
docs: {
|
|
5
|
+
description: 'Restrict listed names in tailwind tokens',
|
|
6
|
+
recommended: false,
|
|
7
|
+
},
|
|
8
|
+
messages: {
|
|
9
|
+
disallowedToken:
|
|
10
|
+
"Do not use '{{ token }}' in token names. Use a semantic design token name instead.",
|
|
11
|
+
},
|
|
12
|
+
schema: [],
|
|
13
|
+
},
|
|
14
|
+
|
|
15
|
+
create(context) {
|
|
16
|
+
const RESTRICTED_TOKENS = [
|
|
17
|
+
'white',
|
|
18
|
+
'black',
|
|
19
|
+
'red',
|
|
20
|
+
'green',
|
|
21
|
+
'grey',
|
|
22
|
+
'gray',
|
|
23
|
+
'eggplant',
|
|
24
|
+
'carrot',
|
|
25
|
+
'teal',
|
|
26
|
+
'mustard',
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
const regex = new RegExp(`\\b(${RESTRICTED_TOKENS.join('|')})\\b`, 'i');
|
|
30
|
+
|
|
31
|
+
function reportIfTokenUsed(node, value) {
|
|
32
|
+
const match = regex.exec(value);
|
|
33
|
+
if (match) {
|
|
34
|
+
context.report({
|
|
35
|
+
node,
|
|
36
|
+
messageId: 'disallowedToken',
|
|
37
|
+
data: {
|
|
38
|
+
token: match[1],
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
Literal(node) {
|
|
46
|
+
if (typeof node.value === 'string') {
|
|
47
|
+
reportIfTokenUsed(node, node.value);
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
JSXAttribute(node) {
|
|
51
|
+
if (
|
|
52
|
+
node.name &&
|
|
53
|
+
['class', 'className', 'style'].includes(node.name.name) &&
|
|
54
|
+
node.value &&
|
|
55
|
+
node.value.type === 'Literal' &&
|
|
56
|
+
typeof node.value.value === 'string'
|
|
57
|
+
) {
|
|
58
|
+
reportIfTokenUsed(node.value, node.value.value);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Also handle JSXExpressionContainer e.g. className={"my-class red-text"}
|
|
62
|
+
if (
|
|
63
|
+
node.value &&
|
|
64
|
+
node.value.type === 'JSXExpressionContainer' &&
|
|
65
|
+
node.value.expression &&
|
|
66
|
+
node.value.expression.type === 'Literal' &&
|
|
67
|
+
typeof node.value.expression.value === 'string'
|
|
68
|
+
) {
|
|
69
|
+
reportIfTokenUsed(node.value.expression, node.value.expression.value);
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
TemplateLiteral(node) {
|
|
73
|
+
node.quasis.forEach((quasi) => {
|
|
74
|
+
reportIfTokenUsed(quasi, quasi.value.cooked || '');
|
|
75
|
+
});
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
},
|
|
79
|
+
};
|