@ctrl-ui/react 0.9.14 → 0.9.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/README.md +1 -0
- package/dist/control-variants.d.ts +1 -1
- package/dist/control-variants.js +2 -1
- package/dist/knob-contracts/button-knobs.d.ts +1 -1
- package/dist/knob-contracts/button-knobs.js +11 -10
- package/dist/knob-contracts/item-knobs.d.ts +1 -1
- package/dist/knob-contracts/item-knobs.js +5 -0
- package/dist/knob-contracts/resize-handle-knobs.d.ts +1 -1
- package/dist/knob-contracts/resize-handle-knobs.js +2 -1
- package/dist/knob-contracts/reveal-knobs.d.ts +4 -0
- package/dist/knob-contracts/reveal-knobs.js +4 -0
- package/dist/knob-contracts/tabs-knobs.d.ts +1 -1
- package/dist/knob-contracts/tabs-knobs.js +2 -0
- package/dist/styles/index.css +1 -0
- package/dist/styles/recipes/badge.css +12 -0
- package/dist/styles/recipes/button-states.css +50 -0
- package/dist/styles/recipes/button.css +19 -52
- package/dist/styles/recipes/card.css +2 -2
- package/dist/styles/recipes/infinite-canvas.css +8 -0
- package/dist/styles/recipes/item.css +73 -6
- package/dist/styles/recipes/resize-handle.css +8 -0
- package/dist/styles/recipes/reveal.css +26 -0
- package/dist/styles/recipes/tabs.css +15 -1
- package/dist/ui/badge.d.ts +1 -1
- package/dist/ui/dropdown-menu.d.ts +6 -4
- package/dist/ui/dropdown-menu.js +2 -1
- package/dist/ui/reveal.d.ts +15 -0
- package/dist/ui/reveal.js +29 -0
- package/dist/ui/typography.d.ts +1 -0
- package/dist/ui/typography.js +2 -1
- package/lint/class-policy.mjs +2 -0
- package/lint/eslint-plugin.mjs +4 -1
- package/lint/grit-rules.mjs +4 -0
- package/lint/no-component-style-classes.grit +2 -0
- package/lint/no-component-style-props.grit +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -54,6 +54,7 @@ These rules keep call sites honest. They come from one policy (`lint/class-polic
|
|
|
54
54
|
- `no-component-style-classes` errors when `className` on a component imported from `@ctrl-ui/react` (or a `components/control-ui` directory) sets what the component owns: colors, type, padding, borders, radius, shadows, filters, state styles such as `hover:` and `data-[…]:`, arbitrary properties that paint (`[background:…]`), or `!important`. Every `text-*` class counts except alignment and wrapping (`text-center`, `text-pretty`, `text-ellipsis`…). The rule also reads string constants the `className` references in the same file, and the `className` of the element passed to the component's `render` prop. On any other element, it errors on classes that reach into a component's parts, such as `[&_[data-slot=trigger]]:` or `*:data-[slot=icon]:`. Layout classes (`flex`, `gap-*`, widths, heights, margins, placement) stay allowed. Restyle through the component's props or its `--cui-*` knobs instead.
|
|
55
55
|
- `no-component-style-props` applies the same boundary to `style`: `--cui-*` knobs and layout keys pass, while paint keys error (`color`, `background`, `font*`, `padding*`, `border*`, `boxShadow`, `opacity`, `filter`…). It also checks same-file constant objects and the element passed to `render`. When the paint is data, such as a user-picked fill, put it on a plain element of your own and let the component inherit it.
|
|
56
56
|
- `no-component-part-css` errors when a stylesheet paints a component part: a rule whose subject is `[data-slot]`, `[data-control-family]`, or another `[data-control…]` attribute, including nested `&` rules and `@apply`. Setting the part's `--cui-*` knobs and layout there stays allowed. The preset skips installed Control UI source under `components/control-ui`.
|
|
57
|
+
- Paint-free components own no look, so both component rules treat them like plain elements: `RevealScope` can be the painted row or card itself, through `className`, `style`, or its `render` element. Part selectors on it still error, and `Reveal` keeps the full rule because its recipe owns opacity.
|
|
57
58
|
- `no-raw-type-classes` errors on text sizes in any `className`: the type rungs, Tailwind's `text-xs`…`text-9xl`, and arbitrary `text-[13px]`. It reaches beyond Control UI, so adopt it folder by folder while you migrate.
|
|
58
59
|
|
|
59
60
|
The Biome rules need Biome 2.5.0 or later: the preset scopes the stylesheet rule with plugin `includes`.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
//#region src/control-variants.d.ts
|
|
2
2
|
export type ControlSize = "xs" | "sm" | "md" | "lg";
|
|
3
|
-
export declare const buttonVariants: readonly ["solid", "surface", "ghost", "quiet", "dashed", "link"];
|
|
3
|
+
export declare const buttonVariants: readonly ["solid", "surface", "ghost", "quiet", "dashed", "link", "scrim"];
|
|
4
4
|
export type ButtonVariant = (typeof buttonVariants)[number];
|
|
5
5
|
export declare const controlTones: readonly ["neutral", "primary", "danger"];
|
|
6
6
|
export type ControlTone = (typeof controlTones)[number];
|
package/dist/control-variants.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
//#region src/knob-contracts/button-knobs.d.ts
|
|
2
|
-
export declare const buttonKnobs: readonly ["--cui-button-press-background", "--cui-button-press-scale", "--cui-button-hover-border-color", "--cui-button-open-border-color", "--cui-button-open-background", "--cui-button-open-foreground", "--cui-button-open-shadow", "--cui-button-
|
|
2
|
+
export declare const buttonKnobs: readonly ["--cui-button-press-background", "--cui-button-press-scale", "--cui-button-hover-border-color", "--cui-button-open-border-color", "--cui-button-open-background", "--cui-button-open-foreground", "--cui-button-open-shadow", "--cui-button-hover-background-image", "--cui-button-hover-background", "--cui-button-hover-foreground", "--cui-button-active-background", "--cui-button-active-foreground", "--cui-button-active-hover-background", "--cui-button-hover-shadow", "--cui-button-press-shadow", "--cui-button-active-shadow", "--cui-button-radius", "--cui-button-gap", "--cui-button-icon", "--cui-button-height", "--cui-button-padding-inline", "--cui-button-padding-block", "--cui-button-icon-padding-inline", "--cui-button-font-size", "--cui-button-font-weight", "--cui-button-background", "--cui-button-background-image", "--cui-button-foreground", "--cui-button-shadow", "--cui-button-border-width", "--cui-button-border-style", "--cui-button-border-color", "--cui-button-backdrop-filter"];
|
|
3
3
|
export type ButtonKnobStyle = Partial<Record<(typeof buttonKnobs)[number], string>>;
|
|
4
4
|
//#endregion
|
|
@@ -7,6 +7,15 @@ const buttonKnobs = [
|
|
|
7
7
|
"--cui-button-open-background",
|
|
8
8
|
"--cui-button-open-foreground",
|
|
9
9
|
"--cui-button-open-shadow",
|
|
10
|
+
"--cui-button-hover-background-image",
|
|
11
|
+
"--cui-button-hover-background",
|
|
12
|
+
"--cui-button-hover-foreground",
|
|
13
|
+
"--cui-button-active-background",
|
|
14
|
+
"--cui-button-active-foreground",
|
|
15
|
+
"--cui-button-active-hover-background",
|
|
16
|
+
"--cui-button-hover-shadow",
|
|
17
|
+
"--cui-button-press-shadow",
|
|
18
|
+
"--cui-button-active-shadow",
|
|
10
19
|
"--cui-button-radius",
|
|
11
20
|
"--cui-button-gap",
|
|
12
21
|
"--cui-button-icon",
|
|
@@ -18,20 +27,12 @@ const buttonKnobs = [
|
|
|
18
27
|
"--cui-button-font-weight",
|
|
19
28
|
"--cui-button-background",
|
|
20
29
|
"--cui-button-background-image",
|
|
21
|
-
"--cui-button-hover-background-image",
|
|
22
30
|
"--cui-button-foreground",
|
|
23
|
-
"--cui-button-hover-background",
|
|
24
|
-
"--cui-button-hover-foreground",
|
|
25
|
-
"--cui-button-active-background",
|
|
26
|
-
"--cui-button-active-foreground",
|
|
27
|
-
"--cui-button-active-hover-background",
|
|
28
31
|
"--cui-button-shadow",
|
|
29
|
-
"--cui-button-hover-shadow",
|
|
30
|
-
"--cui-button-press-shadow",
|
|
31
|
-
"--cui-button-active-shadow",
|
|
32
32
|
"--cui-button-border-width",
|
|
33
33
|
"--cui-button-border-style",
|
|
34
|
-
"--cui-button-border-color"
|
|
34
|
+
"--cui-button-border-color",
|
|
35
|
+
"--cui-button-backdrop-filter"
|
|
35
36
|
];
|
|
36
37
|
//#endregion
|
|
37
38
|
export { buttonKnobs };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
//#region src/knob-contracts/item-knobs.d.ts
|
|
2
|
-
export declare const itemKnobs: readonly ["--cui-item-radius", "--cui-item-hover-background", "--cui-item-current-background", "--cui-item-hover-border-color", "--cui-item-border-width", "--cui-item-active-scale", "--cui-item-gap", "--cui-item-padding-block", "--cui-item-padding-inline", "--cui-item-description-font-size", "--cui-item-description-line-height", "--cui-item-description-foreground", "--cui-item-media-foreground"];
|
|
2
|
+
export declare const itemKnobs: readonly ["--cui-item-radius", "--cui-item-hover-background", "--cui-item-current-background", "--cui-item-foreground", "--cui-item-selected-background", "--cui-item-selected-foreground", "--cui-item-dragging-opacity", "--cui-item-drop-target-shadow", "--cui-item-hover-border-color", "--cui-item-border-width", "--cui-item-active-scale", "--cui-item-gap", "--cui-item-padding-block", "--cui-item-padding-inline", "--cui-item-description-font-size", "--cui-item-description-line-height", "--cui-item-description-foreground", "--cui-item-media-foreground"];
|
|
3
3
|
export type ItemKnobStyle = Partial<Record<(typeof itemKnobs)[number], string>>;
|
|
4
4
|
//#endregion
|
|
@@ -3,6 +3,11 @@ const itemKnobs = [
|
|
|
3
3
|
"--cui-item-radius",
|
|
4
4
|
"--cui-item-hover-background",
|
|
5
5
|
"--cui-item-current-background",
|
|
6
|
+
"--cui-item-foreground",
|
|
7
|
+
"--cui-item-selected-background",
|
|
8
|
+
"--cui-item-selected-foreground",
|
|
9
|
+
"--cui-item-dragging-opacity",
|
|
10
|
+
"--cui-item-drop-target-shadow",
|
|
6
11
|
"--cui-item-hover-border-color",
|
|
7
12
|
"--cui-item-border-width",
|
|
8
13
|
"--cui-item-active-scale",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
//#region src/knob-contracts/resize-handle-knobs.d.ts
|
|
2
|
-
export declare const resizeHandleKnobs: readonly ["--cui-resize-handle-size", "--cui-resize-handle-hit-size", "--cui-resize-handle-background", "--cui-resize-handle-hover-background", "--cui-resize-handle-border-color", "--cui-resize-handle-border-width", "--cui-resize-handle-radius"];
|
|
2
|
+
export declare const resizeHandleKnobs: readonly ["--cui-resize-handle-size", "--cui-resize-handle-hit-size", "--cui-resize-handle-background", "--cui-resize-handle-hover-background", "--cui-resize-handle-border-color", "--cui-resize-handle-border-width", "--cui-resize-handle-radius", "--cui-resize-handle-shadow"];
|
|
3
3
|
export type ResizeHandleKnobStyle = Partial<Record<(typeof resizeHandleKnobs)[number], string>>;
|
|
4
4
|
//#endregion
|
|
@@ -6,7 +6,8 @@ const resizeHandleKnobs = [
|
|
|
6
6
|
"--cui-resize-handle-hover-background",
|
|
7
7
|
"--cui-resize-handle-border-color",
|
|
8
8
|
"--cui-resize-handle-border-width",
|
|
9
|
-
"--cui-resize-handle-radius"
|
|
9
|
+
"--cui-resize-handle-radius",
|
|
10
|
+
"--cui-resize-handle-shadow"
|
|
10
11
|
];
|
|
11
12
|
//#endregion
|
|
12
13
|
export { resizeHandleKnobs };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
//#region src/knob-contracts/tabs-knobs.d.ts
|
|
2
|
-
export declare const tabsKnobs: readonly ["--cui-tabs-surface-background", "--cui-tabs-surface-radius", "--cui-tabs-trigger-padding-inline", "--cui-tabs-trigger-radius", "--cui-tabs-trigger-height", "--cui-tabs-list-padding", "--cui-tabs-list-radius", "--cui-tabs-list-background", "--cui-tabs-list-backdrop-filter", "--cui-tabs-indicator-background", "--cui-tabs-foreground", "--cui-tabs-font-size", "--cui-tabs-font-weight", "--cui-tabs-active-foreground", "--cui-tabs-hover-foreground", "--cui-tabs-indicator-shadow", "--cui-tabs-list-shadow", "--cui-tabs-border-color", "--cui-tabs-border-width", "--cui-tabs-indicator-background-image"];
|
|
2
|
+
export declare const tabsKnobs: readonly ["--cui-tabs-surface-background", "--cui-tabs-surface-radius", "--cui-tabs-trigger-padding-inline", "--cui-tabs-trigger-padding-inline-start", "--cui-tabs-trigger-padding-inline-end", "--cui-tabs-trigger-radius", "--cui-tabs-trigger-height", "--cui-tabs-list-padding", "--cui-tabs-list-radius", "--cui-tabs-list-background", "--cui-tabs-list-backdrop-filter", "--cui-tabs-indicator-background", "--cui-tabs-foreground", "--cui-tabs-font-size", "--cui-tabs-font-weight", "--cui-tabs-active-foreground", "--cui-tabs-hover-foreground", "--cui-tabs-indicator-shadow", "--cui-tabs-list-shadow", "--cui-tabs-border-color", "--cui-tabs-border-width", "--cui-tabs-indicator-background-image"];
|
|
3
3
|
export type TabsKnobStyle = Partial<Record<(typeof tabsKnobs)[number], string>>;
|
|
4
4
|
//#endregion
|
|
@@ -3,6 +3,8 @@ const tabsKnobs = [
|
|
|
3
3
|
"--cui-tabs-surface-background",
|
|
4
4
|
"--cui-tabs-surface-radius",
|
|
5
5
|
"--cui-tabs-trigger-padding-inline",
|
|
6
|
+
"--cui-tabs-trigger-padding-inline-start",
|
|
7
|
+
"--cui-tabs-trigger-padding-inline-end",
|
|
6
8
|
"--cui-tabs-trigger-radius",
|
|
7
9
|
"--cui-tabs-trigger-height",
|
|
8
10
|
"--cui-tabs-list-padding",
|
package/dist/styles/index.css
CHANGED
|
@@ -84,6 +84,7 @@
|
|
|
84
84
|
@import "./recipes/pagination.css";
|
|
85
85
|
@import "./recipes/phone-input.css";
|
|
86
86
|
@import "./recipes/resize-handle.css";
|
|
87
|
+
@import "./recipes/reveal.css";
|
|
87
88
|
@import "./recipes/rich-tooltip.css";
|
|
88
89
|
@import "./recipes/skeleton.css";
|
|
89
90
|
@import "./recipes/stepper.css";
|
|
@@ -46,6 +46,18 @@
|
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
:where([data-control-family="badge"][data-slot="root"][data-color="primary"]) {
|
|
50
|
+
--_badge-color-background: var(--primary);
|
|
51
|
+
--_badge-color-foreground: var(--primary-foreground);
|
|
52
|
+
--_badge-color-border: var(--primary);
|
|
53
|
+
--_badge-color-background-hover: oklch(from var(--primary) calc(l - 0.05) c h);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
:where([data-control-family="badge"][data-slot="root"][data-color="primary"][data-variant="outline"]) {
|
|
57
|
+
--_badge-color-background: oklch(from var(--primary) l c h / var(--badge-fill-alpha));
|
|
58
|
+
--_badge-color-foreground: var(--primary-text);
|
|
59
|
+
}
|
|
60
|
+
|
|
49
61
|
:where([data-control-family="badge"][data-slot="root"][data-color="red"]) {
|
|
50
62
|
--_badge-color-background: var(--badge-red);
|
|
51
63
|
--_badge-color-foreground: var(--badge-red-foreground);
|
|
@@ -125,3 +125,53 @@
|
|
|
125
125
|
syntax: "*";
|
|
126
126
|
inherits: true;
|
|
127
127
|
}
|
|
128
|
+
|
|
129
|
+
@property --cui-button-hover-background-image {
|
|
130
|
+
syntax: "*";
|
|
131
|
+
inherits: true;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
@property --cui-button-hover-background {
|
|
135
|
+
syntax: "<color>";
|
|
136
|
+
inherits: true;
|
|
137
|
+
initial-value: transparent;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
@property --cui-button-hover-foreground {
|
|
141
|
+
syntax: "<color>";
|
|
142
|
+
inherits: true;
|
|
143
|
+
initial-value: transparent;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
@property --cui-button-active-background {
|
|
147
|
+
syntax: "<color>";
|
|
148
|
+
inherits: true;
|
|
149
|
+
initial-value: transparent;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
@property --cui-button-active-foreground {
|
|
153
|
+
syntax: "<color>";
|
|
154
|
+
inherits: true;
|
|
155
|
+
initial-value: transparent;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
@property --cui-button-active-hover-background {
|
|
159
|
+
syntax: "<color>";
|
|
160
|
+
inherits: true;
|
|
161
|
+
initial-value: transparent;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
@property --cui-button-hover-shadow {
|
|
165
|
+
syntax: "*";
|
|
166
|
+
inherits: true;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
@property --cui-button-press-shadow {
|
|
170
|
+
syntax: "*";
|
|
171
|
+
inherits: true;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
@property --cui-button-active-shadow {
|
|
175
|
+
syntax: "*";
|
|
176
|
+
inherits: true;
|
|
177
|
+
}
|
|
@@ -56,10 +56,12 @@
|
|
|
56
56
|
--cui-button-border-color: var(--control-rim);
|
|
57
57
|
--cui-button-hover-border-color: var(--cui-button-border-color);
|
|
58
58
|
--cui-button-open-border-color: var(--cui-button-hover-border-color);
|
|
59
|
+
--cui-button-backdrop-filter: none;
|
|
59
60
|
border: var(--cui-button-border-width) var(--cui-button-border-style) var(--cui-button-border-color);
|
|
60
61
|
border-radius: var(--cui-button-radius);
|
|
61
62
|
background-color: var(--cui-button-background);
|
|
62
63
|
background-image: var(--cui-button-background-image);
|
|
64
|
+
backdrop-filter: var(--cui-button-backdrop-filter);
|
|
63
65
|
box-shadow: var(--cui-button-shadow);
|
|
64
66
|
color: var(--cui-button-foreground);
|
|
65
67
|
cursor: pointer;
|
|
@@ -193,6 +195,16 @@
|
|
|
193
195
|
--cui-button-hover-background: transparent;
|
|
194
196
|
}
|
|
195
197
|
|
|
198
|
+
:where([data-control-family="button"][data-variant="scrim"]) {
|
|
199
|
+
--cui-button-background: oklch(0 0 0 / 0.6);
|
|
200
|
+
--cui-button-foreground: oklch(1 0 0);
|
|
201
|
+
--cui-button-hover-background: oklch(0 0 0 / 0.8);
|
|
202
|
+
--cui-button-hover-foreground: var(--cui-button-foreground);
|
|
203
|
+
--cui-button-active-background: var(--cui-button-foreground);
|
|
204
|
+
--cui-button-active-foreground: oklch(0 0 0);
|
|
205
|
+
--cui-button-backdrop-filter: blur(8px);
|
|
206
|
+
}
|
|
207
|
+
|
|
196
208
|
:where([data-control-family="button"]:is([data-variant="surface"], [data-variant="ghost"], [data-variant="quiet"])) {
|
|
197
209
|
--cui-button-open-background: oklch(from var(--foreground) l c h / 0.07);
|
|
198
210
|
}
|
|
@@ -210,7 +222,7 @@
|
|
|
210
222
|
}
|
|
211
223
|
}
|
|
212
224
|
|
|
213
|
-
:where([data-control-family="button"][data-tone="primary"]:not([data-variant="solid"])) {
|
|
225
|
+
:where([data-control-family="button"][data-tone="primary"]:not([data-variant="solid"], [data-variant="scrim"])) {
|
|
214
226
|
--cui-button-foreground: var(--primary-text);
|
|
215
227
|
--cui-button-hover-foreground: var(--primary-text);
|
|
216
228
|
--cui-button-active-foreground: var(--primary-text);
|
|
@@ -226,7 +238,7 @@
|
|
|
226
238
|
--cui-button-active-hover-background: var(--cui-button-hover-background);
|
|
227
239
|
}
|
|
228
240
|
|
|
229
|
-
:where([data-control-family="button"][data-tone="danger"]:not([data-variant="solid"])) {
|
|
241
|
+
:where([data-control-family="button"][data-tone="danger"]:not([data-variant="solid"], [data-variant="scrim"])) {
|
|
230
242
|
--cui-button-foreground: var(--destructive-text);
|
|
231
243
|
--cui-button-hover-foreground: var(--destructive-text);
|
|
232
244
|
--cui-button-active-foreground: var(--destructive-text);
|
|
@@ -316,67 +328,17 @@
|
|
|
316
328
|
inherits: true;
|
|
317
329
|
}
|
|
318
330
|
|
|
319
|
-
@property --cui-button-hover-background-image {
|
|
320
|
-
syntax: "*";
|
|
321
|
-
inherits: true;
|
|
322
|
-
}
|
|
323
|
-
|
|
324
331
|
@property --cui-button-foreground {
|
|
325
332
|
syntax: "<color>";
|
|
326
333
|
inherits: true;
|
|
327
334
|
initial-value: transparent;
|
|
328
335
|
}
|
|
329
336
|
|
|
330
|
-
@property --cui-button-hover-background {
|
|
331
|
-
syntax: "<color>";
|
|
332
|
-
inherits: true;
|
|
333
|
-
initial-value: transparent;
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
@property --cui-button-hover-foreground {
|
|
337
|
-
syntax: "<color>";
|
|
338
|
-
inherits: true;
|
|
339
|
-
initial-value: transparent;
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
@property --cui-button-active-background {
|
|
343
|
-
syntax: "<color>";
|
|
344
|
-
inherits: true;
|
|
345
|
-
initial-value: transparent;
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
@property --cui-button-active-foreground {
|
|
349
|
-
syntax: "<color>";
|
|
350
|
-
inherits: true;
|
|
351
|
-
initial-value: transparent;
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
@property --cui-button-active-hover-background {
|
|
355
|
-
syntax: "<color>";
|
|
356
|
-
inherits: true;
|
|
357
|
-
initial-value: transparent;
|
|
358
|
-
}
|
|
359
|
-
|
|
360
337
|
@property --cui-button-shadow {
|
|
361
338
|
syntax: "*";
|
|
362
339
|
inherits: true;
|
|
363
340
|
}
|
|
364
341
|
|
|
365
|
-
@property --cui-button-hover-shadow {
|
|
366
|
-
syntax: "*";
|
|
367
|
-
inherits: true;
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
@property --cui-button-press-shadow {
|
|
371
|
-
syntax: "*";
|
|
372
|
-
inherits: true;
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
@property --cui-button-active-shadow {
|
|
376
|
-
syntax: "*";
|
|
377
|
-
inherits: true;
|
|
378
|
-
}
|
|
379
|
-
|
|
380
342
|
@property --cui-button-border-width {
|
|
381
343
|
syntax: "<length>";
|
|
382
344
|
inherits: true;
|
|
@@ -393,3 +355,8 @@
|
|
|
393
355
|
inherits: true;
|
|
394
356
|
initial-value: transparent;
|
|
395
357
|
}
|
|
358
|
+
|
|
359
|
+
@property --cui-button-backdrop-filter {
|
|
360
|
+
syntax: "*";
|
|
361
|
+
inherits: true;
|
|
362
|
+
}
|
|
@@ -84,11 +84,11 @@
|
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
:where([data-control-family="card"][data-slot="root"][data-variant="sectioned"] > [data-slot="content"]) {
|
|
87
|
-
padding-block:
|
|
87
|
+
padding-block: var(--cui-card-padding-block);
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
:where([data-control-family="card"][data-slot="root"][data-variant="sectioned"] > [data-slot="header"]) {
|
|
91
|
-
padding-block: calc(var(--
|
|
91
|
+
padding-block: calc(var(--cui-card-padding-block) - var(--spacing));
|
|
92
92
|
border-block-end: 1px solid oklch(from var(--border) l c h / 0.7);
|
|
93
93
|
}
|
|
94
94
|
|
|
@@ -26,6 +26,14 @@
|
|
|
26
26
|
--focus-ring-offset: calc(var(--focus-ring-width) * -1);
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
:where([data-control-family="infinite-canvas"][data-slot="root"][data-pan-ready]:not([data-panning])) {
|
|
30
|
+
cursor: grab;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
:where([data-control-family="infinite-canvas"][data-slot="root"][data-panning]) {
|
|
34
|
+
cursor: grabbing;
|
|
35
|
+
}
|
|
36
|
+
|
|
29
37
|
:where([data-control-family="infinite-canvas"][data-slot="root"][data-easing]) {
|
|
30
38
|
transition-property: background-position, background-size;
|
|
31
39
|
transition-duration: var(--duration-base);
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
@layer components {
|
|
2
2
|
:where([data-control-family="item"][data-slot="root"]) {
|
|
3
3
|
--cui-item-radius: var(--radius-lg);
|
|
4
|
+
--cui-item-foreground: var(--foreground);
|
|
4
5
|
--cui-item-hover-background: var(--hover-fill);
|
|
5
6
|
--cui-item-current-background: var(--active-fill);
|
|
7
|
+
--cui-item-selected-background: var(--cui-item-current-background);
|
|
8
|
+
--cui-item-selected-foreground: var(--cui-item-foreground);
|
|
9
|
+
--cui-item-dragging-opacity: 0.5;
|
|
10
|
+
--cui-item-drop-target-shadow: inset 0 0 0 var(--focus-ring-width) var(--primary);
|
|
6
11
|
--cui-item-hover-border-color: var(--_item-border-color);
|
|
7
12
|
--cui-item-border-width: 0px;
|
|
8
13
|
--cui-item-active-scale: 0.99;
|
|
@@ -20,7 +25,7 @@
|
|
|
20
25
|
border-radius: var(--cui-item-radius);
|
|
21
26
|
background: var(--_item-background);
|
|
22
27
|
box-shadow: none;
|
|
23
|
-
color: var(--foreground);
|
|
28
|
+
color: var(--cui-item-foreground);
|
|
24
29
|
transition-property: scale;
|
|
25
30
|
transition-duration: var(--duration-fast);
|
|
26
31
|
transition-timing-function: var(--ease-standard);
|
|
@@ -72,11 +77,16 @@
|
|
|
72
77
|
|
|
73
78
|
@media (hover: hover) {
|
|
74
79
|
:where(
|
|
75
|
-
[data-control-family="item"][data-slot="root"]:is(
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
[
|
|
79
|
-
|
|
80
|
+
[data-control-family="item"][data-slot="root"]:is(
|
|
81
|
+
a,
|
|
82
|
+
button,
|
|
83
|
+
[href],
|
|
84
|
+
[role="button"],
|
|
85
|
+
[role="treeitem"],
|
|
86
|
+
[role="option"],
|
|
87
|
+
[role="row"],
|
|
88
|
+
[role="menuitem"]
|
|
89
|
+
):not(:disabled, [data-disabled], [aria-disabled="true"]):hover
|
|
80
90
|
) {
|
|
81
91
|
outline-color: var(--cui-item-hover-border-color);
|
|
82
92
|
background: var(--cui-item-hover-background);
|
|
@@ -84,6 +94,34 @@
|
|
|
84
94
|
}
|
|
85
95
|
}
|
|
86
96
|
|
|
97
|
+
:where([data-control-family="item"][data-slot="root"][aria-selected="true"]) {
|
|
98
|
+
background: var(--cui-item-selected-background);
|
|
99
|
+
color: var(--cui-item-selected-foreground);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
:where([data-control-family="item"][data-slot="root"][data-dragging]) {
|
|
103
|
+
opacity: var(--cui-item-dragging-opacity);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
:where([data-control-family="item"][data-slot="root"][data-drop-target]) {
|
|
107
|
+
box-shadow: var(--cui-item-drop-target-shadow);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
@media (forced-colors: active) {
|
|
111
|
+
:where([data-control-family="item"][data-slot="root"][aria-selected="true"]) {
|
|
112
|
+
--cui-item-description-foreground: HighlightText;
|
|
113
|
+
--cui-item-media-foreground: HighlightText;
|
|
114
|
+
forced-color-adjust: none;
|
|
115
|
+
background: Highlight;
|
|
116
|
+
color: HighlightText;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
:where([data-control-family="item"][data-slot="root"][data-drop-target]) {
|
|
120
|
+
outline: var(--focus-ring-width) solid Highlight;
|
|
121
|
+
outline-offset: calc(var(--focus-ring-width) * -1);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
87
125
|
:where(
|
|
88
126
|
[data-control-family="item"][data-slot="root"]:is(a, button, [href], [role="button"]):not(
|
|
89
127
|
:disabled,
|
|
@@ -138,6 +176,35 @@
|
|
|
138
176
|
initial-value: transparent;
|
|
139
177
|
}
|
|
140
178
|
|
|
179
|
+
@property --cui-item-foreground {
|
|
180
|
+
syntax: "<color>";
|
|
181
|
+
inherits: true;
|
|
182
|
+
initial-value: transparent;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
@property --cui-item-selected-background {
|
|
186
|
+
syntax: "<color>";
|
|
187
|
+
inherits: true;
|
|
188
|
+
initial-value: transparent;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
@property --cui-item-selected-foreground {
|
|
192
|
+
syntax: "<color>";
|
|
193
|
+
inherits: true;
|
|
194
|
+
initial-value: transparent;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
@property --cui-item-dragging-opacity {
|
|
198
|
+
syntax: "<number>";
|
|
199
|
+
inherits: true;
|
|
200
|
+
initial-value: 1;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
@property --cui-item-drop-target-shadow {
|
|
204
|
+
syntax: "*";
|
|
205
|
+
inherits: true;
|
|
206
|
+
}
|
|
207
|
+
|
|
141
208
|
@property --cui-item-hover-border-color {
|
|
142
209
|
syntax: "<color>";
|
|
143
210
|
inherits: true;
|
|
@@ -7,11 +7,13 @@
|
|
|
7
7
|
--cui-resize-handle-border-color: var(--primary);
|
|
8
8
|
--cui-resize-handle-border-width: var(--control-rim-width);
|
|
9
9
|
--cui-resize-handle-radius: 0px;
|
|
10
|
+
--cui-resize-handle-shadow: none;
|
|
10
11
|
inline-size: var(--cui-resize-handle-hit-size);
|
|
11
12
|
block-size: var(--cui-resize-handle-hit-size);
|
|
12
13
|
translate: -50% -50%;
|
|
13
14
|
padding: 0;
|
|
14
15
|
border: 0;
|
|
16
|
+
border-radius: var(--cui-resize-handle-radius);
|
|
15
17
|
background: transparent;
|
|
16
18
|
}
|
|
17
19
|
|
|
@@ -25,6 +27,7 @@
|
|
|
25
27
|
border: var(--cui-resize-handle-border-width) solid var(--cui-resize-handle-border-color);
|
|
26
28
|
border-radius: var(--cui-resize-handle-radius);
|
|
27
29
|
background: var(--cui-resize-handle-background);
|
|
30
|
+
box-shadow: var(--cui-resize-handle-shadow);
|
|
28
31
|
transition: background-color var(--duration-fast) var(--ease-standard);
|
|
29
32
|
}
|
|
30
33
|
|
|
@@ -124,3 +127,8 @@
|
|
|
124
127
|
inherits: true;
|
|
125
128
|
initial-value: 0px;
|
|
126
129
|
}
|
|
130
|
+
|
|
131
|
+
@property --cui-resize-handle-shadow {
|
|
132
|
+
syntax: "*";
|
|
133
|
+
inherits: true;
|
|
134
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
@layer components {
|
|
2
|
+
:where([data-control-family="reveal"][data-slot="scope"]) {
|
|
3
|
+
--cui-reveal-hidden-opacity: 0;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
:where([data-control-family="reveal"][data-slot="content"]) {
|
|
7
|
+
transition-property: opacity;
|
|
8
|
+
transition-duration: var(--duration-fast);
|
|
9
|
+
transition-timing-function: var(--ease-standard);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
@media (hover: hover) and (pointer: fine) {
|
|
13
|
+
:where(
|
|
14
|
+
[data-control-family="reveal"][data-slot="scope"]:not(:hover, :focus-within, :has([data-popup-open]))
|
|
15
|
+
[data-control-family="reveal"][data-slot="content"]
|
|
16
|
+
) {
|
|
17
|
+
opacity: var(--cui-reveal-hidden-opacity);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
@property --cui-reveal-hidden-opacity {
|
|
23
|
+
syntax: "<number>";
|
|
24
|
+
inherits: true;
|
|
25
|
+
initial-value: 1;
|
|
26
|
+
}
|
|
@@ -34,6 +34,8 @@
|
|
|
34
34
|
|
|
35
35
|
:where([data-control-family="tabs"][data-slot="list"]) {
|
|
36
36
|
--cui-tabs-trigger-height: var(--control-h-sm);
|
|
37
|
+
--cui-tabs-trigger-padding-inline-start: var(--cui-tabs-trigger-padding-inline);
|
|
38
|
+
--cui-tabs-trigger-padding-inline-end: var(--cui-tabs-trigger-padding-inline);
|
|
37
39
|
--_tabs-trigger-radius-fit: min(var(--cui-tabs-trigger-radius), calc(var(--cui-tabs-trigger-height) / 2));
|
|
38
40
|
position: relative;
|
|
39
41
|
display: flex;
|
|
@@ -105,7 +107,7 @@
|
|
|
105
107
|
gap: calc(var(--spacing) * 1.5);
|
|
106
108
|
white-space: nowrap;
|
|
107
109
|
border-radius: var(--_tabs-trigger-radius-fit);
|
|
108
|
-
padding-inline: var(--cui-tabs-trigger-padding-inline);
|
|
110
|
+
padding-inline: var(--cui-tabs-trigger-padding-inline-start) var(--cui-tabs-trigger-padding-inline-end);
|
|
109
111
|
color: var(--cui-tabs-foreground);
|
|
110
112
|
font-size: var(--cui-tabs-font-size);
|
|
111
113
|
font-weight: var(--cui-tabs-font-weight);
|
|
@@ -285,6 +287,18 @@
|
|
|
285
287
|
initial-value: 0px;
|
|
286
288
|
}
|
|
287
289
|
|
|
290
|
+
@property --cui-tabs-trigger-padding-inline-start {
|
|
291
|
+
syntax: "<length-percentage>";
|
|
292
|
+
inherits: true;
|
|
293
|
+
initial-value: 0px;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
@property --cui-tabs-trigger-padding-inline-end {
|
|
297
|
+
syntax: "<length-percentage>";
|
|
298
|
+
inherits: true;
|
|
299
|
+
initial-value: 0px;
|
|
300
|
+
}
|
|
301
|
+
|
|
288
302
|
@property --cui-tabs-trigger-radius {
|
|
289
303
|
syntax: "<length-percentage>";
|
|
290
304
|
inherits: true;
|
package/dist/ui/badge.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export type BadgeVariant = (typeof badgeVariants)[number];
|
|
|
7
7
|
export declare const badgeSizes: readonly ["sm", "md"];
|
|
8
8
|
export type BadgeSize = (typeof badgeSizes)[number];
|
|
9
9
|
export declare const BADGE_COLORS: readonly ["neutral", "red", "orange", "yellow", "green", "blue", "purple", "pink"];
|
|
10
|
-
export type BadgeColor = (typeof BADGE_COLORS)[number];
|
|
10
|
+
export type BadgeColor = (typeof BADGE_COLORS)[number] | "primary";
|
|
11
11
|
export type BadgeProps = Omit<ComponentProps<"span">, "style"> & {
|
|
12
12
|
variant?: BadgeVariant;
|
|
13
13
|
size?: BadgeSize;
|
|
@@ -9,10 +9,12 @@ type DropdownMenuStyledProps<PrimitiveProps> = Omit<PrimitiveProps, "className"
|
|
|
9
9
|
className?: string;
|
|
10
10
|
style?: CSSProperties & PopupKnobStyle;
|
|
11
11
|
};
|
|
12
|
-
export type DropdownMenuProps = Menu.Root.Props
|
|
12
|
+
export type DropdownMenuProps<Payload = unknown> = Menu.Root.Props<Payload>;
|
|
13
|
+
export type DropdownMenuHandle<Payload = unknown> = Menu.Handle<Payload>;
|
|
14
|
+
export declare const createDropdownMenuHandle: typeof Menu.createHandle;
|
|
13
15
|
export declare const dropdownMenuTriggerVariants: readonly ["surface", "ghost"];
|
|
14
16
|
export type DropdownMenuTriggerVariant = (typeof dropdownMenuTriggerVariants)[number];
|
|
15
|
-
export type DropdownMenuTriggerProps = Omit<ComponentProps<"button">, "style"> & Pick<
|
|
17
|
+
export type DropdownMenuTriggerProps<Payload = unknown> = Omit<ComponentProps<"button">, "style"> & Pick<Menu.Trigger.Props<Payload>, "nativeButton" | "render" | "handle" | "payload"> & {
|
|
16
18
|
style?: CSSProperties & ButtonKnobStyle;
|
|
17
19
|
} & {
|
|
18
20
|
size?: ControlSize;
|
|
@@ -37,8 +39,8 @@ export type DropdownMenuSeparatorProps = Omit<ComponentProps<"div">, "style"> &
|
|
|
37
39
|
export type DropdownMenuLabelProps = Omit<ComponentProps<"div">, "style"> & {
|
|
38
40
|
style?: CSSProperties & PopupKnobStyle;
|
|
39
41
|
};
|
|
40
|
-
export declare function DropdownMenu({ children, ...props }: DropdownMenuProps): import("react").JSX.Element;
|
|
41
|
-
export declare function DropdownMenuTrigger({ size, iconOnly, variant, className, ...props }: DropdownMenuTriggerProps): import("react").JSX.Element;
|
|
42
|
+
export declare function DropdownMenu<Payload>({ children, ...props }: DropdownMenuProps<Payload>): import("react").JSX.Element;
|
|
43
|
+
export declare function DropdownMenuTrigger<Payload>({ size, iconOnly, variant, className, ...props }: DropdownMenuTriggerProps<Payload>): import("react").JSX.Element;
|
|
42
44
|
export declare function DropdownMenuContent({ className, children, side, sideOffset, align, alignOffset, collisionBoundary, collisionPadding, collisionAvoidance, ...props }: DropdownMenuContentProps): import("react").JSX.Element;
|
|
43
45
|
export declare function DropdownMenuItem({ tone, className, ...props }: DropdownMenuItemProps): import("react").JSX.Element;
|
|
44
46
|
export declare function DropdownMenuSeparator({ className, ...props }: DropdownMenuSeparatorProps): import("react").JSX.Element;
|
package/dist/ui/dropdown-menu.js
CHANGED
|
@@ -9,6 +9,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
9
9
|
import { mergeProps } from "@base-ui/react/merge-props";
|
|
10
10
|
import { Menu } from "@base-ui/react/menu";
|
|
11
11
|
//#region src/ui/dropdown-menu.tsx
|
|
12
|
+
const createDropdownMenuHandle = Menu.createHandle;
|
|
12
13
|
const dropdownMenuTriggerVariants = ["surface", "ghost"];
|
|
13
14
|
function DropdownMenu({ children, ...props }) {
|
|
14
15
|
return /* @__PURE__ */ jsx(Menu.Root, {
|
|
@@ -209,4 +210,4 @@ function DropdownMenuShortcut(props) {
|
|
|
209
210
|
});
|
|
210
211
|
}
|
|
211
212
|
//#endregion
|
|
212
|
-
export { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, dropdownMenuTriggerVariants };
|
|
213
|
+
export { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, createDropdownMenuHandle, dropdownMenuTriggerVariants };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { RenderProp } from "../control-props.js";
|
|
2
|
+
import { RevealKnobStyle } from "../knob-contracts/reveal-knobs.js";
|
|
3
|
+
import { CSSProperties, ComponentProps } from "react";
|
|
4
|
+
//#region src/ui/reveal.d.ts
|
|
5
|
+
export type RevealScopeProps = Omit<ComponentProps<"div">, "style"> & {
|
|
6
|
+
render?: RenderProp<ComponentProps<"div">>;
|
|
7
|
+
style?: CSSProperties & RevealKnobStyle;
|
|
8
|
+
};
|
|
9
|
+
export type RevealProps = Omit<ComponentProps<"span">, "style"> & {
|
|
10
|
+
render?: RenderProp<ComponentProps<"span">>;
|
|
11
|
+
style?: CSSProperties & RevealKnobStyle;
|
|
12
|
+
};
|
|
13
|
+
export declare function RevealScope({ render, ...props }: RevealScopeProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
14
|
+
export declare function Reveal({ render, ...props }: RevealProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
15
|
+
//#endregion
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useRender } from "@base-ui/react/use-render";
|
|
3
|
+
//#region src/ui/reveal.tsx
|
|
4
|
+
function RevealScope({ render, ...props }) {
|
|
5
|
+
return useRender({
|
|
6
|
+
defaultTagName: "div",
|
|
7
|
+
render,
|
|
8
|
+
props: {
|
|
9
|
+
...props,
|
|
10
|
+
"data-control-ui": "reveal",
|
|
11
|
+
"data-control-family": "reveal",
|
|
12
|
+
"data-slot": "scope"
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
function Reveal({ render, ...props }) {
|
|
17
|
+
return useRender({
|
|
18
|
+
defaultTagName: "span",
|
|
19
|
+
render,
|
|
20
|
+
props: {
|
|
21
|
+
...props,
|
|
22
|
+
"data-control-ui": "reveal",
|
|
23
|
+
"data-control-family": "reveal",
|
|
24
|
+
"data-slot": "content"
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
//#endregion
|
|
29
|
+
export { Reveal, RevealScope };
|
package/dist/ui/typography.d.ts
CHANGED
|
@@ -25,6 +25,7 @@ declare const weightClassNames: {
|
|
|
25
25
|
readonly normal: "font-normal";
|
|
26
26
|
readonly medium: "font-medium";
|
|
27
27
|
readonly semibold: "font-semibold";
|
|
28
|
+
readonly bold: "font-bold";
|
|
28
29
|
};
|
|
29
30
|
export type TypeSize = keyof typeof sizeClassNames;
|
|
30
31
|
export type TypeTone = keyof typeof toneClassNames;
|
package/dist/ui/typography.js
CHANGED
package/lint/class-policy.mjs
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
const controlUiImportPath = `(?:@ctrl-ui/react|[^'"]*components/control-ui)/`;
|
|
2
2
|
|
|
3
|
+
export const paintFreeComponents = ["RevealScope"];
|
|
4
|
+
|
|
3
5
|
const escapeRegExp = (text) => text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
4
6
|
|
|
5
7
|
export function controlUiImportPattern(importSources = []) {
|
package/lint/eslint-plugin.mjs
CHANGED
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
componentStyleMessage,
|
|
7
7
|
componentStylePropMessage,
|
|
8
8
|
controlUiImportPattern,
|
|
9
|
+
paintFreeComponents,
|
|
9
10
|
rawTypeClass,
|
|
10
11
|
rawTypeMessage,
|
|
11
12
|
} from "./class-policy.mjs";
|
|
@@ -77,7 +78,9 @@ function controlUiLocalNames(program, controlUiImport) {
|
|
|
77
78
|
for (const statement of program.body) {
|
|
78
79
|
if (statement.type !== "ImportDeclaration" || statement.importKind === "type") continue;
|
|
79
80
|
if (!controlUiImport.test(statement.source.value)) continue;
|
|
80
|
-
for (const specifier of statement.specifiers)
|
|
81
|
+
for (const specifier of statement.specifiers) {
|
|
82
|
+
if (!paintFreeComponents.includes(specifier.imported?.name)) names.add(specifier.local.name);
|
|
83
|
+
}
|
|
81
84
|
}
|
|
82
85
|
return names;
|
|
83
86
|
}
|
package/lint/grit-rules.mjs
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
componentStyleMessage,
|
|
9
9
|
componentStylePropMessage,
|
|
10
10
|
controlUiImportPattern,
|
|
11
|
+
paintFreeComponents,
|
|
11
12
|
paintProperty,
|
|
12
13
|
rawTypeClass,
|
|
13
14
|
rawTypeMessage,
|
|
@@ -30,6 +31,7 @@ const stringTexts = (name) =>
|
|
|
30
31
|
const classLiterals = "or { JsStringLiteralExpression(), JsTemplateExpression(), JsObjectExpression() }";
|
|
31
32
|
const renderedTag = "or { JsxTagExpression(tag=$tag), JsParenthesizedExpression(expression=JsxTagExpression(tag=$tag)) }";
|
|
32
33
|
const componentName = `r"([A-Z]\\w*)(?:\\.[\\w.]+)?"`;
|
|
34
|
+
const paintFreeComponent = gritExactRegex(`(?:${paintFreeComponents.join("|")})`);
|
|
33
35
|
|
|
34
36
|
function constantMatches(reference, literals, offends) {
|
|
35
37
|
return `contains JsReferenceIdentifier() as $${reference} where {
|
|
@@ -97,6 +99,7 @@ function componentAttributePattern({ attribute, offends, message, importSources
|
|
|
97
99
|
}
|
|
98
100
|
} where {
|
|
99
101
|
$name <: ${componentName}($component),
|
|
102
|
+
not $component <: ${paintFreeComponent},
|
|
100
103
|
$attr <: within JsModule() as $module,
|
|
101
104
|
${offends("$attr")},
|
|
102
105
|
${importedFromControlUi("$component", importSources)},
|
|
@@ -115,6 +118,7 @@ function partClassPattern(importSources) {
|
|
|
115
118
|
${classNameMatches("$plainAttr", componentPartClass)},
|
|
116
119
|
not and {
|
|
117
120
|
$plainName <: ${componentName}($plainComponent),
|
|
121
|
+
not $plainComponent <: ${paintFreeComponent},
|
|
118
122
|
${importedFromControlUi("$plainComponent", importSources, "Plain")}
|
|
119
123
|
},
|
|
120
124
|
register_diagnostic(span=$plainAttr, message=${gritString(componentPartMessage)}, severity="error")
|
|
@@ -31,6 +31,7 @@ or {
|
|
|
31
31
|
}
|
|
32
32
|
} where {
|
|
33
33
|
$name <: r"([A-Z]\w*)(?:\.[\w.]+)?"($component),
|
|
34
|
+
not $component <: r"(?:RevealScope)",
|
|
34
35
|
$attr <: within JsModule() as $module,
|
|
35
36
|
$attr <: or {
|
|
36
37
|
contains or { JsxString(), JsStringLiteralExpression(), JsTemplateChunkElement(), JsLiteralMemberName() as $attrMember where { $attrMember <: r"(?s)[\"'].*" } } as $attrText where { $attrText <: r"(?s).*(?:[^\s\"'\x60]!(?:[\s\"'\x60]|$)|(?:^|[\s\"'\x60])![\w\[-]|(?:^|[^\w-])(?:p[xytrblse]?-|bg-[\w\[]|text-(?:(?:[\s\"'\x60]|$)|[^lcrjsewnbp\s\"'\x60]|l(?:(?:[\s\"'\x60]|$)|[^e\s\"'\x60]|e(?:(?:[\s\"'\x60]|$)|[^f\s\"'\x60]|f(?:(?:[\s\"'\x60]|$)|[^t\s\"'\x60]|t(?:[^\s\"'\x60]))))|c(?:(?:[\s\"'\x60]|$)|[^el\s\"'\x60]|e(?:(?:[\s\"'\x60]|$)|[^n\s\"'\x60]|n(?:(?:[\s\"'\x60]|$)|[^t\s\"'\x60]|t(?:(?:[\s\"'\x60]|$)|[^e\s\"'\x60]|e(?:(?:[\s\"'\x60]|$)|[^r\s\"'\x60]|r(?:[^\s\"'\x60])))))|l(?:(?:[\s\"'\x60]|$)|[^i\s\"'\x60]|i(?:(?:[\s\"'\x60]|$)|[^p\s\"'\x60]|p(?:[^\s\"'\x60]))))|r(?:(?:[\s\"'\x60]|$)|[^i\s\"'\x60]|i(?:(?:[\s\"'\x60]|$)|[^g\s\"'\x60]|g(?:(?:[\s\"'\x60]|$)|[^h\s\"'\x60]|h(?:(?:[\s\"'\x60]|$)|[^t\s\"'\x60]|t(?:[^\s\"'\x60])))))|j(?:(?:[\s\"'\x60]|$)|[^u\s\"'\x60]|u(?:(?:[\s\"'\x60]|$)|[^s\s\"'\x60]|s(?:(?:[\s\"'\x60]|$)|[^t\s\"'\x60]|t(?:(?:[\s\"'\x60]|$)|[^i\s\"'\x60]|i(?:(?:[\s\"'\x60]|$)|[^f\s\"'\x60]|f(?:(?:[\s\"'\x60]|$)|[^y\s\"'\x60]|y(?:[^\s\"'\x60])))))))|s(?:(?:[\s\"'\x60]|$)|[^t\s\"'\x60]|t(?:(?:[\s\"'\x60]|$)|[^a\s\"'\x60]|a(?:(?:[\s\"'\x60]|$)|[^r\s\"'\x60]|r(?:(?:[\s\"'\x60]|$)|[^t\s\"'\x60]|t(?:[^\s\"'\x60])))))|e(?:(?:[\s\"'\x60]|$)|[^nl\s\"'\x60]|n(?:(?:[\s\"'\x60]|$)|[^d\s\"'\x60]|d(?:[^\s\"'\x60]))|l(?:(?:[\s\"'\x60]|$)|[^l\s\"'\x60]|l(?:(?:[\s\"'\x60]|$)|[^i\s\"'\x60]|i(?:(?:[\s\"'\x60]|$)|[^p\s\"'\x60]|p(?:(?:[\s\"'\x60]|$)|[^s\s\"'\x60]|s(?:(?:[\s\"'\x60]|$)|[^i\s\"'\x60]|i(?:(?:[\s\"'\x60]|$)|[^s\s\"'\x60]|s(?:[^\s\"'\x60]))))))))|w(?:(?:[\s\"'\x60]|$)|[^r\s\"'\x60]|r(?:(?:[\s\"'\x60]|$)|[^a\s\"'\x60]|a(?:(?:[\s\"'\x60]|$)|[^p\s\"'\x60]|p(?:[^\s\"'\x60]))))|n(?:(?:[\s\"'\x60]|$)|[^o\s\"'\x60]|o(?:(?:[\s\"'\x60]|$)|[^w\s\"'\x60]|w(?:(?:[\s\"'\x60]|$)|[^r\s\"'\x60]|r(?:(?:[\s\"'\x60]|$)|[^a\s\"'\x60]|a(?:(?:[\s\"'\x60]|$)|[^p\s\"'\x60]|p(?:[^\s\"'\x60]))))))|b(?:(?:[\s\"'\x60]|$)|[^a\s\"'\x60]|a(?:(?:[\s\"'\x60]|$)|[^l\s\"'\x60]|l(?:(?:[\s\"'\x60]|$)|[^a\s\"'\x60]|a(?:(?:[\s\"'\x60]|$)|[^n\s\"'\x60]|n(?:(?:[\s\"'\x60]|$)|[^c\s\"'\x60]|c(?:(?:[\s\"'\x60]|$)|[^e\s\"'\x60]|e(?:[^\s\"'\x60])))))))|p(?:(?:[\s\"'\x60]|$)|[^r\s\"'\x60]|r(?:(?:[\s\"'\x60]|$)|[^e\s\"'\x60]|e(?:(?:[\s\"'\x60]|$)|[^t\s\"'\x60]|t(?:(?:[\s\"'\x60]|$)|[^t\s\"'\x60]|t(?:(?:[\s\"'\x60]|$)|[^y\s\"'\x60]|y(?:[^\s\"'\x60])))))))|font-|leading-|tracking-|border|divide-|rounded|shadow|inset-shadow|drop-shadow|ring\b|ring-|inset-ring|outline|opacity-|backdrop-|fill-|stroke-|caret-|accent-|scheme-|mask-|decoration-|underline|no-underline|overline|line-through|italic|not-italic|uppercase|lowercase|capitalize|normal-case|antialiased|subpixel-antialiased|ordinal|slashed-zero|(?:normal|lining|oldstyle|proportional|tabular)-nums|(?:diagonal|stacked)-fractions|blur(?:-|(?:[\s\"'\x60]|$))|brightness-|contrast-[\d\[]|grayscale|hue-rotate-|invert|saturate-|sepia|(?:hover|focus|focus-visible|focus-within|active|disabled|enabled|open|checked|indeterminate|visited|target|invalid|valid|user-invalid|user-valid|required|optional|read-only|autofill|placeholder-shown|in-range|out-of-range|inert|starting|dark|placeholder|selection|marker|file|first-letter|first-line|backdrop|details-content|aria-[^:\s]*|data-[^:\s]*|group-[^:\s]*|peer-[^:\s]*|has-[^:\s]*|\*|\[&[^\s]*?\]):)|(?:^|[^\w-])\[(?:padding|background|color|font|line-height|letter-spacing|border|outline|box-shadow|text-shadow|text-decoration|text-underline|text-transform|opacity|filter|backdrop-filter|fill|stroke|caret-color|accent-color|mask|-webkit-mask|-webkit-font-smoothing|-moz-osx-font-smoothing)(?:-[\w-]*)?:).*" },
|
|
@@ -71,6 +72,7 @@ or {
|
|
|
71
72
|
},
|
|
72
73
|
not and {
|
|
73
74
|
$plainName <: r"([A-Z]\w*)(?:\.[\w.]+)?"($plainComponent),
|
|
75
|
+
not $plainComponent <: r"(?:RevealScope)",
|
|
74
76
|
$module <: contains JsImport() as $importPlain where {
|
|
75
77
|
$importPlain <: r"(?s).*(?:from\s+['\"](?:(?:@ctrl-ui/react|[^'\"]*components/control-ui)/)).*",
|
|
76
78
|
$importPlain <: contains JsIdentifierBinding() as $bindingPlain where { $bindingPlain <: $plainComponent }
|
|
@@ -30,6 +30,7 @@ or {
|
|
|
30
30
|
}
|
|
31
31
|
} where {
|
|
32
32
|
$name <: r"([A-Z]\w*)(?:\.[\w.]+)?"($component),
|
|
33
|
+
not $component <: r"(?:RevealScope)",
|
|
33
34
|
$attr <: within JsModule() as $module,
|
|
34
35
|
$attr <: or {
|
|
35
36
|
contains or { JsPropertyObjectMember(name=$attrKey), JsShorthandPropertyObjectMember(name=$attrKey) } where { $attrKey <: r"[\"']?(?:(?:padding|background|color|font|lineHeight|letterSpacing|border|outline|boxShadow|textShadow|textDecoration|textUnderline|textTransform|opacity|filter|backdropFilter|fill|stroke|caretColor|accentColor|mask|WebkitMask|WebkitFontSmoothing|MozOsxFontSmoothing)(?:[A-Z]\w*)?|(?:padding|background|color|font|line-height|letter-spacing|border|outline|box-shadow|text-shadow|text-decoration|text-underline|text-transform|opacity|filter|backdrop-filter|fill|stroke|caret-color|accent-color|mask|-webkit-mask|-webkit-font-smoothing|-moz-osx-font-smoothing)(?:-[\w-]*)?)[\"']?" },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ctrl-ui/react",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.16",
|
|
4
4
|
"description": "100+ React components for Tailwind CSS and shadcn/ui: pickers, trees, editors, canvases, app templates, and AI chat surfaces, with neutral defaults and consumer-owned themes.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|