@ctrl-ui/react 0.9.11 → 0.9.13
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 +3 -1
- package/dist/control-variants.d.ts +1 -1
- package/dist/control-variants.js +1 -0
- package/dist/knob-contracts/button-knobs.d.ts +1 -1
- package/dist/knob-contracts/button-knobs.js +11 -5
- package/dist/knob-contracts/dropzone-knobs.d.ts +1 -1
- package/dist/knob-contracts/dropzone-knobs.js +5 -1
- package/dist/knob-contracts/field-knobs.d.ts +1 -1
- package/dist/knob-contracts/field-knobs.js +10 -0
- package/dist/knob-contracts/gradient-editor-knobs.d.ts +1 -1
- package/dist/knob-contracts/gradient-editor-knobs.js +1 -4
- package/dist/knob-contracts/page-layout-knobs.d.ts +1 -1
- package/dist/knob-contracts/page-layout-knobs.js +1 -0
- package/dist/knob-contracts/popup-knobs.d.ts +1 -1
- package/dist/knob-contracts/popup-knobs.js +5 -2
- package/dist/knob-contracts/sidebar-knobs.d.ts +1 -1
- package/dist/knob-contracts/sidebar-knobs.js +1 -0
- package/dist/styles/recipes/avatar.css +2 -0
- package/dist/styles/recipes/button-states.css +43 -0
- package/dist/styles/recipes/button.css +29 -21
- package/dist/styles/recipes/card.css +8 -0
- package/dist/styles/recipes/color-picker-values.css +4 -18
- package/dist/styles/recipes/color-picker.css +3 -4
- package/dist/styles/recipes/dropzone.css +47 -4
- package/dist/styles/recipes/field-parts.css +101 -1
- package/dist/styles/recipes/gradient-editor.css +3 -47
- package/dist/styles/recipes/markdown.css +5 -1
- package/dist/styles/recipes/page-layout.css +8 -1
- package/dist/styles/recipes/popup-controls.css +7 -1
- package/dist/styles/recipes/popup-lists.css +30 -5
- package/dist/styles/recipes/popup.css +5 -6
- package/dist/styles/recipes/sidebar-parts.css +6 -0
- package/dist/styles/recipes/sidebar.css +9 -8
- package/dist/styles/recipes/table.css +29 -0
- package/dist/styles/theme.css +4 -0
- package/dist/ui/autocomplete.d.ts +3 -0
- package/dist/ui/autocomplete.js +17 -2
- package/dist/ui/chart-cartesian.d.ts +60 -57
- package/dist/ui/chart-cartesian.js +7 -7
- package/dist/ui/chart-colors.d.ts +4 -2
- package/dist/ui/chart-colors.js +6 -2
- package/dist/ui/chart-marks.d.ts +4 -4
- package/dist/ui/chart-marks.js +14 -5
- package/dist/ui/chart-series.d.ts +9 -6
- package/dist/ui/chart-series.js +3 -2
- package/dist/ui/color-picker-swatches.d.ts +4 -3
- package/dist/ui/color-picker-swatches.js +7 -8
- package/dist/ui/command.d.ts +12 -0
- package/dist/ui/command.js +32 -2
- package/dist/ui/dropzone.d.ts +4 -1
- package/dist/ui/dropzone.js +16 -8
- package/dist/ui/field.d.ts +4 -1
- package/dist/ui/field.js +4 -2
- package/dist/ui/gradient-editor.d.ts +3 -2
- package/dist/ui/gradient-editor.js +7 -8
- package/dist/ui/markdown-components.d.ts +27 -0
- package/dist/ui/markdown-components.js +57 -0
- package/dist/ui/markdown-elements.d.ts +6 -25
- package/dist/ui/markdown-elements.js +19 -53
- package/dist/ui/markdown.d.ts +2 -7
- package/dist/ui/markdown.js +3 -20
- package/dist/ui/table.d.ts +6 -0
- package/dist/ui/table.js +17 -1
- package/lint/class-policy.mjs +31 -1
- package/lint/eslint-plugin.mjs +48 -4
- package/lint/grit-rules.mjs +52 -11
- package/lint/no-component-style-classes.grit +41 -6
- package/lint/no-raw-type-classes.grit +1 -1
- package/package.json +5 -1
package/dist/ui/table.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { RenderProp } from "../control-props.js";
|
|
1
2
|
import { TableKnobStyle } from "../knob-contracts/table-knobs.js";
|
|
2
3
|
import { CSSProperties, ComponentProps } from "react";
|
|
3
4
|
//#region src/ui/table.d.ts
|
|
@@ -22,6 +23,10 @@ export type TableHeadProps = Omit<ComponentProps<"th">, "style"> & {
|
|
|
22
23
|
export type TableCellProps = ComponentProps<"td"> & {
|
|
23
24
|
style?: CSSProperties & TableKnobStyle;
|
|
24
25
|
};
|
|
26
|
+
export type TableRowLinkProps = Omit<ComponentProps<"button">, "style"> & {
|
|
27
|
+
render?: RenderProp<ComponentProps<"button">>;
|
|
28
|
+
style?: CSSProperties & TableKnobStyle;
|
|
29
|
+
};
|
|
25
30
|
export type TableCaptionProps = Omit<ComponentProps<"caption">, "style"> & {
|
|
26
31
|
style?: CSSProperties & TableKnobStyle;
|
|
27
32
|
};
|
|
@@ -33,4 +38,5 @@ export declare function TableRow({ className, ...props }: TableRowProps): import
|
|
|
33
38
|
export declare function TableHead({ className, ...props }: TableHeadProps): import("react").JSX.Element;
|
|
34
39
|
export declare function TableCell({ className, ...props }: TableCellProps): import("react").JSX.Element;
|
|
35
40
|
export declare function TableCaption({ className, ...props }: TableCaptionProps): import("react").JSX.Element;
|
|
41
|
+
export declare function TableRowLink({ render, ...props }: TableRowLinkProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
36
42
|
//#endregion
|
package/dist/ui/table.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
"use client";
|
|
1
2
|
import { cn } from "../lib/cn.js";
|
|
2
3
|
import { ScrollArea } from "./scroll-area.js";
|
|
4
|
+
import { useRender } from "@base-ui/react/use-render";
|
|
3
5
|
import { jsx } from "react/jsx-runtime";
|
|
4
6
|
//#region src/ui/table.tsx
|
|
5
7
|
function Table({ className, ...props }) {
|
|
@@ -85,5 +87,19 @@ function TableCaption({ className, ...props }) {
|
|
|
85
87
|
...props
|
|
86
88
|
});
|
|
87
89
|
}
|
|
90
|
+
function TableRowLink({ render, ...props }) {
|
|
91
|
+
return useRender({
|
|
92
|
+
defaultTagName: "button",
|
|
93
|
+
render,
|
|
94
|
+
props: {
|
|
95
|
+
type: render ? void 0 : "button",
|
|
96
|
+
...props,
|
|
97
|
+
"data-control-ui": "table",
|
|
98
|
+
"data-control-family": "table",
|
|
99
|
+
"data-slot": "row-link",
|
|
100
|
+
"data-focus-ring": "none"
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
}
|
|
88
104
|
//#endregion
|
|
89
|
-
export { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow };
|
|
105
|
+
export { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, TableRowLink };
|
package/lint/class-policy.mjs
CHANGED
|
@@ -6,7 +6,37 @@ export function controlUiImportPattern(importSources = []) {
|
|
|
6
6
|
return `(?:${[controlUiImportPath, ...importSources.map(escapeRegExp)].join("|")})`;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
const classDelimiter = String.raw`\s"'\x60`;
|
|
10
|
+
const classEnd = `(?:[${classDelimiter}]|$)`;
|
|
11
|
+
|
|
12
|
+
function classSuffixOtherThan(suffixes) {
|
|
13
|
+
const firsts = [...new Set(suffixes.filter(Boolean).map((suffix) => suffix[0]))];
|
|
14
|
+
const alternatives = [
|
|
15
|
+
...(suffixes.includes("") ? [] : [classEnd]),
|
|
16
|
+
`[^${firsts.join("")}${classDelimiter}]`,
|
|
17
|
+
...firsts.map(
|
|
18
|
+
(first) => first + classSuffixOtherThan(suffixes.filter((suffix) => suffix[0] === first).map((suffix) => suffix.slice(1))),
|
|
19
|
+
),
|
|
20
|
+
];
|
|
21
|
+
return `(?:${alternatives.join("|")})`;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const textLayoutSuffixes = [
|
|
25
|
+
"left",
|
|
26
|
+
"center",
|
|
27
|
+
"right",
|
|
28
|
+
"justify",
|
|
29
|
+
"start",
|
|
30
|
+
"end",
|
|
31
|
+
"wrap",
|
|
32
|
+
"nowrap",
|
|
33
|
+
"balance",
|
|
34
|
+
"pretty",
|
|
35
|
+
"ellipsis",
|
|
36
|
+
"clip",
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
export const componentStyleClass = String.raw`[^${classDelimiter}]!${classEnd}|(?:^|[${classDelimiter}])![\w\[-]|(?:^|[^\w-])(?:p[xytrblse]?-|bg-[\w\[]|text-${classSuffixOtherThan(textLayoutSuffixes)}|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|(?: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]*?\]):)`;
|
|
10
40
|
|
|
11
41
|
export const rawTypeClass = String.raw`(?:^|[^\w-])text-(?:micro|caption|label|body|body-lg|heading-[1-4]|display|xs|sm|base|lg|xl|[2-9]xl)\b|(?:^|[^\w-])text-\[\d[^\]]*\]`;
|
|
12
42
|
|
package/lint/eslint-plugin.mjs
CHANGED
|
@@ -11,9 +11,28 @@ function stringsIn(node) {
|
|
|
11
11
|
return Object.entries(node).flatMap(([key, child]) => (key === "parent" ? [] : stringsIn(child)));
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
function referencedNames(node) {
|
|
15
|
+
if (Array.isArray(node)) return node.flatMap(referencedNames);
|
|
16
|
+
if (!node || typeof node !== "object") return [];
|
|
17
|
+
if (node.type === "Identifier") return [node.name];
|
|
18
|
+
if (node.type === "MemberExpression" && !node.computed) return referencedNames(node.object);
|
|
19
|
+
if (node.type === "Property" && !node.computed) return referencedNames(node.value);
|
|
20
|
+
return Object.entries(node).flatMap(([key, child]) => (key === "parent" ? [] : referencedNames(child)));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const classLiteralTypes = new Set(["Literal", "TemplateLiteral", "ObjectExpression"]);
|
|
24
|
+
|
|
25
|
+
function classLiteral(init) {
|
|
26
|
+
const value = init?.type === "TSAsExpression" || init?.type === "TSSatisfiesExpression" ? init.expression : init;
|
|
27
|
+
return classLiteralTypes.has(value?.type) ? value : undefined;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function isClassName(attribute) {
|
|
31
|
+
return attribute.name.name === "className" && Boolean(attribute.value);
|
|
32
|
+
}
|
|
33
|
+
|
|
14
34
|
function classNameMatches(attribute, pattern) {
|
|
15
|
-
|
|
16
|
-
return stringsIn(attribute.value).some((text) => pattern.test(text));
|
|
35
|
+
return isClassName(attribute) && stringsIn(attribute.value).some((text) => pattern.test(text));
|
|
17
36
|
}
|
|
18
37
|
|
|
19
38
|
function elementRootName(name) {
|
|
@@ -22,6 +41,14 @@ function elementRootName(name) {
|
|
|
22
41
|
return undefined;
|
|
23
42
|
}
|
|
24
43
|
|
|
44
|
+
function renderPropOwner(element) {
|
|
45
|
+
const body =
|
|
46
|
+
element.parent.type === "ReturnStatement" && element.parent.parent.type === "BlockStatement" ? element.parent.parent : element;
|
|
47
|
+
const value = body.parent.type === "ArrowFunctionExpression" ? body.parent : element;
|
|
48
|
+
const attribute = value.parent.type === "JSXExpressionContainer" ? value.parent.parent : undefined;
|
|
49
|
+
return attribute?.type === "JSXAttribute" && attribute.name.name === "render" ? attribute.parent : undefined;
|
|
50
|
+
}
|
|
51
|
+
|
|
25
52
|
function controlUiLocalNames(program, controlUiImport) {
|
|
26
53
|
const names = new Set();
|
|
27
54
|
for (const statement of program.body) {
|
|
@@ -48,13 +75,30 @@ const noComponentStyleClasses = {
|
|
|
48
75
|
create(context) {
|
|
49
76
|
const controlUiImport = new RegExp(`^${controlUiImportPattern(context.options[0]?.importSources)}`);
|
|
50
77
|
let controlUiNames = new Set();
|
|
78
|
+
const isControlUi = (element) => element !== undefined && controlUiNames.has(elementRootName(element.name));
|
|
79
|
+
const constantClasses = new Map();
|
|
80
|
+
const componentClassNames = [];
|
|
51
81
|
return {
|
|
52
82
|
Program(program) {
|
|
53
83
|
controlUiNames = controlUiLocalNames(program, controlUiImport);
|
|
54
84
|
},
|
|
85
|
+
VariableDeclarator(declarator) {
|
|
86
|
+
const literal = classLiteral(declarator.init);
|
|
87
|
+
if (declarator.parent.kind !== "const" || declarator.id.type !== "Identifier" || !literal) return;
|
|
88
|
+
constantClasses.set(declarator.id.name, [...(constantClasses.get(declarator.id.name) ?? []), ...stringsIn(literal)]);
|
|
89
|
+
},
|
|
55
90
|
JSXAttribute(attribute) {
|
|
56
|
-
if (!
|
|
57
|
-
|
|
91
|
+
if (!isClassName(attribute)) return;
|
|
92
|
+
const element = attribute.parent;
|
|
93
|
+
if (isControlUi(element) || isControlUi(renderPropOwner(element.parent))) componentClassNames.push(attribute);
|
|
94
|
+
},
|
|
95
|
+
"Program:exit"() {
|
|
96
|
+
for (const attribute of componentClassNames) {
|
|
97
|
+
const constants = referencedNames(attribute.value).flatMap((name) => constantClasses.get(name) ?? []);
|
|
98
|
+
if ([...stringsIn(attribute.value), ...constants].some((text) => componentStyle.test(text))) {
|
|
99
|
+
context.report({ node: attribute, messageId: "componentStyle" });
|
|
100
|
+
}
|
|
101
|
+
}
|
|
58
102
|
},
|
|
59
103
|
};
|
|
60
104
|
},
|
package/lint/grit-rules.mjs
CHANGED
|
@@ -8,24 +8,65 @@ function gritString(text) {
|
|
|
8
8
|
return JSON.stringify(text);
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
const stringTexts =
|
|
11
|
+
const stringTexts = `or { JsxString(), JsStringLiteralExpression(), JsTemplateChunkElement(), JsLiteralMemberName() as $memberName where { $memberName <: r"(?s)[\\"'].*" } }`;
|
|
12
|
+
const classLiterals = "or { JsStringLiteralExpression(), JsTemplateExpression(), JsObjectExpression() }";
|
|
13
|
+
const renderedTag = "or { JsxTagExpression(tag=$tag), JsParenthesizedExpression(expression=JsxTagExpression(tag=$tag)) }";
|
|
14
|
+
|
|
15
|
+
const styled = gritRegex(componentStyleClass);
|
|
16
|
+
const styledClassName = `$attr <: or {
|
|
17
|
+
contains ${stringTexts} as $text where { $text <: ${styled} },
|
|
18
|
+
contains JsReferenceIdentifier() as $reference where {
|
|
19
|
+
$reference <: r"(.+)"($referenced),
|
|
20
|
+
$module <: contains JsVariableDeclaration(declarators=$declarators) as $declaration where {
|
|
21
|
+
$declaration <: r"(?s)const\\s.*",
|
|
22
|
+
$declarators <: some JsVariableDeclarator(id=$referenced, initializer=JsInitializerClause(expression=$value)),
|
|
23
|
+
$value <: or { ${classLiterals}, TsAsExpression(expression=${classLiterals}), TsSatisfiesExpression(expression=${classLiterals}) },
|
|
24
|
+
$value <: contains ${stringTexts} as $constText where { $constText <: ${styled} }
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}`;
|
|
28
|
+
|
|
29
|
+
function importedFromControlUi(component, importSources, suffix = "") {
|
|
30
|
+
return `$module <: contains JsImport() as $import${suffix} where {
|
|
31
|
+
$import${suffix} <: ${gritRegex(String.raw`from\s+['"]${controlUiImportPattern(importSources)}`)},
|
|
32
|
+
$import${suffix} <: contains JsIdentifierBinding() as $binding${suffix} where { $binding${suffix} <: ${component} }
|
|
33
|
+
}`;
|
|
34
|
+
}
|
|
12
35
|
|
|
13
36
|
export function gritRules(importSources = []) {
|
|
14
37
|
return {
|
|
15
38
|
"no-component-style-classes.grit": `language js(typescript, jsx)
|
|
16
39
|
|
|
17
40
|
or {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
$attr <: contains ${stringTexts} as $text where { $text <: ${gritRegex(componentStyleClass)} },
|
|
24
|
-
$element <: within JsModule() as $module,
|
|
25
|
-
$module <: contains JsImport() as $import where {
|
|
26
|
-
$import <: ${gritRegex(String.raw`from\s+['"]${controlUiImportPattern(importSources)}`)},
|
|
27
|
-
$import <: contains JsIdentifierBinding() as $binding where { $binding <: $component }
|
|
41
|
+
or {
|
|
42
|
+
JsxSelfClosingElement(name=$name, attributes=$attributes),
|
|
43
|
+
JsxOpeningElement(name=$name, attributes=$attributes)
|
|
44
|
+
} where {
|
|
45
|
+
$attributes <: some JsxAttribute(name=\`className\`) as $attr
|
|
28
46
|
},
|
|
47
|
+
JsxAttribute(name=\`render\`, initializer=JsxAttributeInitializerClause(value=JsxExpressionAttributeValue(expression=$rendered))) as $render where {
|
|
48
|
+
$rendered <: or {
|
|
49
|
+
JsxTagExpression(tag=$tag),
|
|
50
|
+
JsArrowFunctionExpression(body=or {
|
|
51
|
+
${renderedTag},
|
|
52
|
+
JsFunctionBody(statements=some JsReturnStatement(argument=${renderedTag}))
|
|
53
|
+
})
|
|
54
|
+
},
|
|
55
|
+
$tag <: or {
|
|
56
|
+
JsxSelfClosingElement(name=$renderedName, attributes=$renderedAttributes),
|
|
57
|
+
JsxElement(opening_element=JsxOpeningElement(name=$renderedName, attributes=$renderedAttributes))
|
|
58
|
+
},
|
|
59
|
+
$renderedAttributes <: some JsxAttribute(name=\`className\`) as $attr,
|
|
60
|
+
$render <: within or { JsxSelfClosingElement(name=$name), JsxOpeningElement(name=$name) },
|
|
61
|
+
$render <: within JsModule() as $module,
|
|
62
|
+
$renderedName <: r"([^.]+).*"($renderedComponent),
|
|
63
|
+
not ${importedFromControlUi("$renderedComponent", importSources, "Rendered")}
|
|
64
|
+
}
|
|
65
|
+
} where {
|
|
66
|
+
$name <: r"([A-Z]\\w*)(?:\\.[\\w.]+)?"($component),
|
|
67
|
+
$attr <: within JsModule() as $module,
|
|
68
|
+
${styledClassName},
|
|
69
|
+
${importedFromControlUi("$component", importSources)},
|
|
29
70
|
register_diagnostic(span=$attr, message=${gritString(componentStyleMessage)}, severity="error")
|
|
30
71
|
}
|
|
31
72
|
`,
|
|
@@ -1,13 +1,48 @@
|
|
|
1
1
|
language js(typescript, jsx)
|
|
2
2
|
|
|
3
3
|
or {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
or {
|
|
5
|
+
JsxSelfClosingElement(name=$name, attributes=$attributes),
|
|
6
|
+
JsxOpeningElement(name=$name, attributes=$attributes)
|
|
7
|
+
} where {
|
|
8
|
+
$attributes <: some JsxAttribute(name=`className`) as $attr
|
|
9
|
+
},
|
|
10
|
+
JsxAttribute(name=`render`, initializer=JsxAttributeInitializerClause(value=JsxExpressionAttributeValue(expression=$rendered))) as $render where {
|
|
11
|
+
$rendered <: or {
|
|
12
|
+
JsxTagExpression(tag=$tag),
|
|
13
|
+
JsArrowFunctionExpression(body=or {
|
|
14
|
+
or { JsxTagExpression(tag=$tag), JsParenthesizedExpression(expression=JsxTagExpression(tag=$tag)) },
|
|
15
|
+
JsFunctionBody(statements=some JsReturnStatement(argument=or { JsxTagExpression(tag=$tag), JsParenthesizedExpression(expression=JsxTagExpression(tag=$tag)) }))
|
|
16
|
+
})
|
|
17
|
+
},
|
|
18
|
+
$tag <: or {
|
|
19
|
+
JsxSelfClosingElement(name=$renderedName, attributes=$renderedAttributes),
|
|
20
|
+
JsxElement(opening_element=JsxOpeningElement(name=$renderedName, attributes=$renderedAttributes))
|
|
21
|
+
},
|
|
22
|
+
$renderedAttributes <: some JsxAttribute(name=`className`) as $attr,
|
|
23
|
+
$render <: within or { JsxSelfClosingElement(name=$name), JsxOpeningElement(name=$name) },
|
|
24
|
+
$render <: within JsModule() as $module,
|
|
25
|
+
$renderedName <: r"([^.]+).*"($renderedComponent),
|
|
26
|
+
not $module <: contains JsImport() as $importRendered where {
|
|
27
|
+
$importRendered <: r"(?s).*(?:from\s+['\"](?:(?:@ctrl-ui/react|[^'\"]*components/control-ui)/)).*",
|
|
28
|
+
$importRendered <: contains JsIdentifierBinding() as $bindingRendered where { $bindingRendered <: $renderedComponent }
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
} where {
|
|
7
32
|
$name <: r"([A-Z]\w*)(?:\.[\w.]+)?"($component),
|
|
8
|
-
$
|
|
9
|
-
$attr <:
|
|
10
|
-
|
|
33
|
+
$attr <: within JsModule() as $module,
|
|
34
|
+
$attr <: or {
|
|
35
|
+
contains or { JsxString(), JsStringLiteralExpression(), JsTemplateChunkElement(), JsLiteralMemberName() as $memberName where { $memberName <: r"(?s)[\"'].*" } } as $text where { $text <: 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|(?: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]*?\]):)).*" },
|
|
36
|
+
contains JsReferenceIdentifier() as $reference where {
|
|
37
|
+
$reference <: r"(.+)"($referenced),
|
|
38
|
+
$module <: contains JsVariableDeclaration(declarators=$declarators) as $declaration where {
|
|
39
|
+
$declaration <: r"(?s)const\s.*",
|
|
40
|
+
$declarators <: some JsVariableDeclarator(id=$referenced, initializer=JsInitializerClause(expression=$value)),
|
|
41
|
+
$value <: or { or { JsStringLiteralExpression(), JsTemplateExpression(), JsObjectExpression() }, TsAsExpression(expression=or { JsStringLiteralExpression(), JsTemplateExpression(), JsObjectExpression() }), TsSatisfiesExpression(expression=or { JsStringLiteralExpression(), JsTemplateExpression(), JsObjectExpression() }) },
|
|
42
|
+
$value <: contains or { JsxString(), JsStringLiteralExpression(), JsTemplateChunkElement(), JsLiteralMemberName() as $memberName where { $memberName <: r"(?s)[\"'].*" } } as $constText where { $constText <: 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|(?: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]*?\]):)).*" }
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
},
|
|
11
46
|
$module <: contains JsImport() as $import where {
|
|
12
47
|
$import <: r"(?s).*(?:from\s+['\"](?:(?:@ctrl-ui/react|[^'\"]*components/control-ui)/)).*",
|
|
13
48
|
$import <: contains JsIdentifierBinding() as $binding where { $binding <: $component }
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
language js(typescript, jsx)
|
|
2
2
|
|
|
3
3
|
JsxAttribute(name=`className`) as $attr where {
|
|
4
|
-
$attr <: contains or { JsxString(), JsStringLiteralExpression(), JsTemplateChunkElement() } as $text where { $text <: r"(?s).*(?:(?:^|[^\w-])text-(?:micro|caption|label|body|body-lg|heading-[1-4]|display|xs|sm|base|lg|xl|[2-9]xl)\b|(?:^|[^\w-])text-\[\d[^\]]*\]).*" },
|
|
4
|
+
$attr <: contains or { JsxString(), JsStringLiteralExpression(), JsTemplateChunkElement(), JsLiteralMemberName() as $memberName where { $memberName <: r"(?s)[\"'].*" } } as $text where { $text <: r"(?s).*(?:(?:^|[^\w-])text-(?:micro|caption|label|body|body-lg|heading-[1-4]|display|xs|sm|base|lg|xl|[2-9]xl)\b|(?:^|[^\w-])text-\[\d[^\]]*\]).*" },
|
|
5
5
|
register_diagnostic(span=$attr, message="Text size in className: render text through <Text>/<Heading> on the type scale, or size the control with its size prop or --cui-*-font-size knob.", severity="error")
|
|
6
6
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ctrl-ui/react",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.13",
|
|
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",
|
|
@@ -61,6 +61,7 @@
|
|
|
61
61
|
},
|
|
62
62
|
"peerDependencies": {
|
|
63
63
|
"@base-ui/react": "^1.9.0",
|
|
64
|
+
"@biomejs/biome": ">=2.4.11",
|
|
64
65
|
"@tanstack/charts": "^1.1.0",
|
|
65
66
|
"@tanstack/react-virtual": "^3.14.13",
|
|
66
67
|
"@tiptap/core": "3.31.4",
|
|
@@ -98,6 +99,9 @@
|
|
|
98
99
|
"zod": "^4.6.5"
|
|
99
100
|
},
|
|
100
101
|
"peerDependenciesMeta": {
|
|
102
|
+
"@biomejs/biome": {
|
|
103
|
+
"optional": true
|
|
104
|
+
},
|
|
101
105
|
"@tanstack/charts": {
|
|
102
106
|
"optional": true
|
|
103
107
|
},
|