cursedbelt 5.19.0 → 5.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/react/components/DataTable/ColumnChecklist.js +1 -1
- package/dist/react/components/DataTable/ColumnChecklist.js.map +1 -1
- package/dist/react/components/DataTable/SearchBox.js +1 -1
- package/dist/react/components/DataTable/SearchBox.js.map +1 -1
- package/dist/react/components/DataTable/TableFilterBuilder.js +1 -1
- package/dist/react/components/DataTable/TableFilterBuilder.js.map +1 -1
- package/dist/react/components/DataTable/ViewOptionsMenu.js +1 -1
- package/dist/react/components/DataTable/ViewOptionsMenu.js.map +1 -1
- package/dist/react/components/SearchInput.js +1 -1
- package/dist/react/components/SearchInput.js.map +1 -1
- package/dist/scripts/guardrailsEnforce.d.ts +2 -0
- package/dist/scripts/guardrailsEnforce.d.ts.map +1 -1
- package/dist/styles-areas/analytics.css +18 -18
- package/dist/styles-areas/data-table.css +20 -20
- package/dist/styles-areas/fields.css +2 -2
- package/dist/styles-utilities.css +9 -0
- package/package.json +1 -1
- package/scripts/guardrailsEnforce.spec.ts +52 -0
- package/scripts/guardrailsEnforce.ts +106 -0
- package/src/react/components/DataTable/ColumnChecklist.tsx +1 -1
- package/src/react/components/DataTable/SearchBox.tsx +1 -1
- package/src/react/components/DataTable/TableFilterBuilder.tsx +1 -1
- package/src/react/components/DataTable/ViewOptionsMenu.tsx +1 -1
- package/src/react/components/SearchInput.tsx +1 -1
- package/src/styles-areas/analytics.css +18 -18
- package/src/styles-areas/data-table.css +20 -20
- package/src/styles-areas/fields.css +2 -2
- package/src/styles-utilities.css +9 -0
- package/src/themeColorsResolve.spec.ts +62 -0
|
@@ -29,6 +29,6 @@ export function ColumnChecklist({ items, onToggle, onSelectAll, onSelectNone, se
|
|
|
29
29
|
// guardrails-ignore no-raw-action-button: view-state bulk toggle, not a mutating action.
|
|
30
30
|
type: 'button', onClick: onSelectNone, disabled: allOff, className: 'rounded px-1.5 py-1 text-caption font-semibold uppercase tracking-wide text-muted-foreground transition-colors hover:text-foreground disabled:cursor-not-allowed disabled:opacity-40', children: selectNoneLabel })] }), _jsx("div", { className: 'max-h-64 overflow-y-auto', children: items.map((item) => (_jsxs("button", {
|
|
31
31
|
// guardrails-ignore no-raw-action-button: view-state checkbox row, not a mutating action.
|
|
32
|
-
type: 'button', role: 'menuitemcheckbox', "aria-checked": item.checked, disabled: item.disabled, onClick: () => onToggle(item.key), className: cn('flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-sm transition-colors', 'hover:bg-muted focus-visible:bg-muted focus-visible:outline-none', TAP_TARGET_HEIGHT, item.disabled && 'cursor-not-allowed opacity-50'), children: [_jsx("span", { "aria-hidden": true, className: cn('flex size-4 shrink-0 items-center justify-center rounded border', item.checked ? 'border-
|
|
32
|
+
type: 'button', role: 'menuitemcheckbox', "aria-checked": item.checked, disabled: item.disabled, onClick: () => onToggle(item.key), className: cn('flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-sm transition-colors', 'hover:bg-muted focus-visible:bg-muted focus-visible:outline-none', TAP_TARGET_HEIGHT, item.disabled && 'cursor-not-allowed opacity-50'), children: [_jsx("span", { "aria-hidden": true, className: cn('flex size-4 shrink-0 items-center justify-center rounded border', item.checked ? 'border-accent-solid bg-accent-solid text-accent-solid-foreground' : 'border-border'), children: item.checked ? _jsx(Check, { className: 'size-3' }) : null }), _jsx("span", { className: 'min-w-0 truncate', children: item.label })] }, item.key))) })] }));
|
|
33
33
|
}
|
|
34
34
|
//# sourceMappingURL=ColumnChecklist.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ColumnChecklist.js","sourceRoot":"","sources":["../../../../src/react/components/DataTable/ColumnChecklist.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AACrC,OAAO,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAC;AACrC,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAsB3D;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,eAAe,CAAC,EAC9B,KAAK,EACL,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,cAAc,GAAG,YAAY,EAC7B,eAAe,GAAG,cAAc,EAChC,YAAY,EAAE,SAAS,EACvB,SAAS,GACY;IACrB,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC1D,MAAM,KAAK,GAAG,UAAU,CAAC,MAAM,GAAG,CAAC,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAChF,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAEzD,OAAO,CAIL,oBAAU,SAAS,EAAE,EAAE,CAAC,mDAAmD,EAAE,SAAS,CAAC,gBAAc,SAAS,aAC5G,eAAK,SAAS,EAAC,uDAAuD,aACpE;wBACE,yFAAyF;wBACzF,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,WAAW,EACpB,QAAQ,EAAE,KAAK,EACf,SAAS,EAAC,sLAAsL,YAE/L,cAAc,GACR,EACT,oCAAkB,SAAS,EAAC,uBAAuB,uBAE5C,EACP;wBACE,yFAAyF;wBACzF,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,YAAY,EACrB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAC,sLAAsL,YAE/L,eAAe,GACT,IACL,EAKN,cAAK,SAAS,EAAC,0BAA0B,YACtC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CACnB;oBACE,0FAA0F;oBAC1F,IAAI,EAAC,QAAQ,EAEb,IAAI,EAAC,kBAAkB,kBACT,IAAI,CAAC,OAAO,EAC1B,QAAQ,EAAE,IAAI,CAAC,QAAQ,EACvB,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,EACjC,SAAS,EAAE,EAAE,CACX,2FAA2F,EAC3F,kEAAkE,EAClE,iBAAiB,EACjB,IAAI,CAAC,QAAQ,IAAI,+BAA+B,CACjD,aAED,oCAEE,SAAS,EAAE,EAAE,CACX,iEAAiE,EACjE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"ColumnChecklist.js","sourceRoot":"","sources":["../../../../src/react/components/DataTable/ColumnChecklist.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AACrC,OAAO,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAC;AACrC,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAsB3D;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,eAAe,CAAC,EAC9B,KAAK,EACL,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,cAAc,GAAG,YAAY,EAC7B,eAAe,GAAG,cAAc,EAChC,YAAY,EAAE,SAAS,EACvB,SAAS,GACY;IACrB,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC1D,MAAM,KAAK,GAAG,UAAU,CAAC,MAAM,GAAG,CAAC,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAChF,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAEzD,OAAO,CAIL,oBAAU,SAAS,EAAE,EAAE,CAAC,mDAAmD,EAAE,SAAS,CAAC,gBAAc,SAAS,aAC5G,eAAK,SAAS,EAAC,uDAAuD,aACpE;wBACE,yFAAyF;wBACzF,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,WAAW,EACpB,QAAQ,EAAE,KAAK,EACf,SAAS,EAAC,sLAAsL,YAE/L,cAAc,GACR,EACT,oCAAkB,SAAS,EAAC,uBAAuB,uBAE5C,EACP;wBACE,yFAAyF;wBACzF,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,YAAY,EACrB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAC,sLAAsL,YAE/L,eAAe,GACT,IACL,EAKN,cAAK,SAAS,EAAC,0BAA0B,YACtC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CACnB;oBACE,0FAA0F;oBAC1F,IAAI,EAAC,QAAQ,EAEb,IAAI,EAAC,kBAAkB,kBACT,IAAI,CAAC,OAAO,EAC1B,QAAQ,EAAE,IAAI,CAAC,QAAQ,EACvB,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,EACjC,SAAS,EAAE,EAAE,CACX,2FAA2F,EAC3F,kEAAkE,EAClE,iBAAiB,EACjB,IAAI,CAAC,QAAQ,IAAI,+BAA+B,CACjD,aAED,oCAEE,SAAS,EAAE,EAAE,CACX,iEAAiE,EACjE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,kEAAkE,CAAC,CAAC,CAAC,eAAe,CACpG,YAEA,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,KAAC,KAAK,IAAC,SAAS,EAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,IAAI,GAC9C,EACP,eAAM,SAAS,EAAC,kBAAkB,YAAE,IAAI,CAAC,KAAK,GAAQ,KArBjD,IAAI,CAAC,GAAG,CAsBN,CACV,CAAC,GACE,IACG,CACZ,CAAC;AACJ,CAAC"}
|
|
@@ -58,7 +58,7 @@ export function SearchBox({ value, onChange, columns, scope, onScopeChange, plac
|
|
|
58
58
|
'inline-flex h-9 shrink-0 items-center gap-1 rounded-md border border-border px-2 text-caption transition-colors pointer-coarse:h-11', 'hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
|
|
59
59
|
// Narrowed scope reads as ACTIVE state, not as another grey
|
|
60
60
|
// control — the whole point is that it cannot hide.
|
|
61
|
-
isAll ? 'text-muted-foreground' : 'border-
|
|
61
|
+
isAll ? 'text-muted-foreground' : 'border-accent/60 bg-accent/10 text-foreground'), children: [_jsx("span", { className: 'max-w-32 truncate', children: scopeLabel }), _jsx(ChevronDown, { className: 'size-3 shrink-0', "aria-hidden": true })] }), children: _jsxs("div", { className: 'flex flex-col gap-1.5', children: [_jsx("span", { className: 'cb-meta-label', children: "Search in" }), _jsx(ColumnChecklist, { "aria-label": 'Columns to search', items: columns.map((c) => ({
|
|
62
62
|
key: c.key,
|
|
63
63
|
label: c.label,
|
|
64
64
|
checked: chosen.includes(c.key),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SearchBox.js","sourceRoot":"","sources":["../../../../src/react/components/DataTable/SearchBox.tsx"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"SearchBox.js","sourceRoot":"","sources":["../../../../src/react/components/DataTable/SearchBox.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAC;AACrC,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAmBvD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,UAAU,SAAS,CAAC,EACxB,KAAK,EACL,QAAQ,EACR,OAAO,EACP,KAAK,EACL,aAAa,EACb,WAAW,GAAG,SAAS,EACvB,SAAS,GACM;IACf,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,KAAK,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAClD,MAAM,KAAK,GAAG,KAAK,KAAK,IAAI,IAAI,MAAM,CAAC,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC;IACjE,MAAM,UAAU,GAAG,KAAK;QACtB,CAAC,CAAC,aAAa;QACf,CAAC,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC;YACnB,CAAC,CAAC,YAAY;YACd,CAAC,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC;gBAClB,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,EAAE,KAAK,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;gBAClF,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,UAAU,CAAC;IAEnC,MAAM,MAAM,GAAG,CAAC,GAAW,EAAE,EAAE;QAC7B,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,EAAE,GAAG,CAAC,CAAC;QACvF,6EAA6E;QAC7E,aAAa,CAAC,IAAI,CAAC,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC9D,CAAC,CAAC;IAEF,OAAO,CACL,eAAK,SAAS,EAAE,EAAE,CAAC,iCAAiC,EAAE,SAAS,CAAC,aAC9D,eAAK,SAAS,EAAC,kCAAkC,aAC/C,KAAC,MAAM,IACL,SAAS,EAAC,6FAA6F,wBAEvG,EACF,KAAC,KAAK,IACJ,IAAI,EAAC,QAAQ,gBACF,QAAQ,EACnB,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EACzC,WAAW,EAAE,WAAW,EACxB,SAAS,EAAC,UAAU,GACpB,IACE,EACL,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CACpB,KAAC,OAAO,IACN,IAAI,EAAE,IAAI,EACV,YAAY,EAAE,OAAO,EACrB,KAAK,EAAC,OAAO,EACb,KAAK,EAAE,KAAK,EACZ,OAAO,EACL;oBACE,oFAAoF;oBACpF,IAAI,EAAC,QAAQ,gBACD,iBAAiB,UAAU,EAAE,EACzC,SAAS,EAAE,EAAE;oBACX,4EAA4E;oBAC5E,yEAAyE;oBACzE,qIAAqI,EACrI,wFAAwF;oBACxF,4DAA4D;oBAC5D,oDAAoD;oBACpD,KAAK,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,+CAA+C,CAClF,aAED,eAAM,SAAS,EAAC,mBAAmB,YAAE,UAAU,GAAQ,EACvD,KAAC,WAAW,IAAC,SAAS,EAAC,iBAAiB,wBAAe,IAChD,YAGX,eAAK,SAAS,EAAC,uBAAuB,aACpC,eAAM,SAAS,EAAC,eAAe,0BAAiB,EAChD,KAAC,eAAe,kBACH,mBAAmB,EAC9B,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gCACzB,GAAG,EAAE,CAAC,CAAC,GAAG;gCACV,KAAK,EAAE,CAAC,CAAC,KAAK;gCACd,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC;6BAChC,CAAC,CAAC,EACH,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,EACtC,YAAY,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,GACrC,IACE,GACE,CACX,CAAC,CAAC,CAAC,IAAI,IACJ,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -69,7 +69,7 @@ export function TableFilterBuilder({ columns, value, onChange, className, }) {
|
|
|
69
69
|
});
|
|
70
70
|
if (columns.length === 0)
|
|
71
71
|
return null;
|
|
72
|
-
return (_jsx(Popover, { open: open, onOpenChange: setOpen, align: 'start', width: 520, arrow: false, trigger: _jsxs(Button, { size: 'sm', variant: activeCount > 0 ? 'secondary' : 'ghost', leftIcon: _jsx(Filter, {}), tooltip: activeCount > 0 ? describeFilterQuery(value, labelOf) : 'Build a filter', children: ["Filter", activeCount > 0 ? (_jsx("span", { className: 'ml-1.5 rounded-full bg-
|
|
72
|
+
return (_jsx(Popover, { open: open, onOpenChange: setOpen, align: 'start', width: 520, arrow: false, trigger: _jsxs(Button, { size: 'sm', variant: activeCount > 0 ? 'secondary' : 'ghost', leftIcon: _jsx(Filter, {}), tooltip: activeCount > 0 ? describeFilterQuery(value, labelOf) : 'Build a filter', children: ["Filter", activeCount > 0 ? (_jsx("span", { className: 'ml-1.5 rounded-full bg-accent-solid px-1.5 py-0.5 text-caption font-bold text-accent-solid-foreground', children: activeCount })) : null] }), children: _jsxs("div", { className: 'flex flex-col gap-2', children: [_jsxs("div", { className: 'flex items-center justify-between gap-2', children: [_jsx("span", { className: 'cb-meta-label', children: "Filter" }), _jsx("button", {
|
|
73
73
|
// guardrails-ignore no-raw-action-button: clears view state, mutates no record.
|
|
74
74
|
type: 'button', onClick: () => onChange(EMPTY_FILTER_QUERY), disabled: value.groups.length === 0, className: 'rounded px-1.5 py-1 text-caption font-semibold uppercase tracking-wide text-muted-foreground transition-colors hover:text-foreground disabled:cursor-not-allowed disabled:opacity-40', children: "Clear all" })] }), value.groups.length === 0 ? (_jsxs("p", { className: 'px-1 py-2 text-sm text-muted-foreground', children: ["Match rows on any number of columns. Conditions inside a group must all match; add a second group to match ", _jsx("strong", { className: 'font-semibold text-foreground', children: "either" }), ' ', "set."] })) : null, _jsx("div", { className: 'flex max-h-[22rem] flex-col gap-2 overflow-y-auto', children: value.groups.map((group, groupIndex) => (_jsxs("div", { children: [groupIndex > 0 ? (_jsxs("div", { className: 'flex items-center gap-2 py-1.5', children: [_jsx("span", { className: 'h-px flex-1 bg-border' }), _jsx("span", { className: 'rounded-full border border-border bg-muted px-2 py-0.5 text-caption font-bold uppercase tracking-wider text-muted-foreground', children: "or" }), _jsx("span", { className: 'h-px flex-1 bg-border' })] })) : null, _jsxs("div", { className: 'rounded-lg border border-border bg-muted/30 p-2', children: [_jsx("div", { className: 'flex flex-col gap-1.5', children: group.conditions.map((condition, conditionIndex) => (_jsxs("div", { className: 'flex items-center gap-1.5', children: [_jsx("span", { className: 'w-9 shrink-0 text-right text-caption font-semibold uppercase tracking-wide text-muted-foreground', children: conditionIndex === 0 ? 'Where' : 'and' }), _jsx(NativeSelect, { size: 'sm', "aria-label": 'Column', className: 'min-w-0 flex-1', wrapperClassName: 'min-w-0 flex-1', value: condition.column, options: columns.map((c) => ({ value: c.key, label: c.label })), onChange: (e) => patchGroup(group.id, (list) => list.map((c) => (c.id === condition.id ? { ...c, column: e.target.value } : c))) }), _jsx(NativeSelect, { size: 'sm', "aria-label": 'Condition', className: 'min-w-0', wrapperClassName: 'w-40 shrink-0', value: condition.op, options: OP_OPTIONS, onChange: (e) => patchGroup(group.id, (list) => list.map((c) => c.id === condition.id ? { ...c, op: e.target.value } : c)) }), VALUELESS_OPS.has(condition.op) ? (_jsx("span", { "aria-hidden": true, className: 'w-36 shrink-0' })) : (_jsx(Input, { "aria-label": 'Value', className: 'h-8 w-36 shrink-0', value: condition.value, placeholder: 'value', onChange: (e) => patchGroup(group.id, (list) => list.map((c) => (c.id === condition.id ? { ...c, value: e.target.value } : c))) })), _jsx("button", {
|
|
75
75
|
// guardrails-ignore no-raw-action-button: removes a filter row, mutates no record.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TableFilterBuilder.js","sourceRoot":"","sources":["../../../../src/react/components/DataTable/TableFilterBuilder.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EACL,qBAAqB,EACrB,mBAAmB,EACnB,kBAAkB,EAClB,gBAAgB,EAIhB,YAAY,EACZ,QAAQ,EACR,aAAa,GACd,MAAM,kBAAkB,CAAC;AAc1B,MAAM,UAAU,GAAI,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAgB,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;IAC5E,KAAK,EAAE,EAAE;IACT,KAAK,EAAE,gBAAgB,CAAC,EAAE,CAAC;CAC5B,CAAC,CAAC,CAAC;AAEJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AACH,MAAM,UAAU,kBAAkB,CAAC,EACjC,OAAO,EACP,KAAK,EACL,QAAQ,EACR,SAAS,GACe;IACxB,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,WAAW,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;IACjD,MAAM,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC;IAC1C,MAAM,OAAO,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,EAAE,KAAK,IAAI,GAAG,CAAC;IAElF,MAAM,UAAU,GAAG,CAAC,OAAe,EAAE,IAA0D,EAAE,EAAE,CACjG,QAAQ,CAAC;QACP,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CACjC,KAAK,CAAC,EAAE,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAChF;KACF,CAAC,CAAC;IAEL,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAEtC,OAAO,CACL,KAAC,OAAO,IACN,IAAI,EAAE,IAAI,EACV,YAAY,EAAE,OAAO,EACrB,KAAK,EAAC,OAAO,EACb,KAAK,EAAE,GAAG,EACV,KAAK,EAAE,KAAK,EACZ,OAAO,EACL,MAAC,MAAM,IACL,IAAI,EAAC,IAAI,EACT,OAAO,EAAE,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,EAChD,QAAQ,EAAE,KAAC,MAAM,KAAG,EACpB,OAAO,EAAE,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,gBAAgB,uBAGhF,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,CACjB,eAAM,SAAS,EAAC,
|
|
1
|
+
{"version":3,"file":"TableFilterBuilder.js","sourceRoot":"","sources":["../../../../src/react/components/DataTable/TableFilterBuilder.tsx"],"names":[],"mappings":"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"}
|
|
@@ -26,7 +26,7 @@ export function ViewOptionsMenu({ table, label = 'Columns' }) {
|
|
|
26
26
|
if (!columns.length)
|
|
27
27
|
return null;
|
|
28
28
|
const hiddenCount = columns.filter((c) => !c.getIsVisible()).length;
|
|
29
|
-
return (_jsx(Popover, { open: open, onOpenChange: setOpen, align: 'end', arrow: false, trigger: _jsxs(Button, { size: 'sm', variant: hiddenCount > 0 ? 'secondary' : 'ghost', leftIcon: _jsx(Columns3, {}), tooltip: hiddenCount > 0 ? `${hiddenCount} column(s) hidden` : label, children: [label, hiddenCount > 0 ? (_jsx("span", { className: 'ml-1.5 rounded-full bg-
|
|
29
|
+
return (_jsx(Popover, { open: open, onOpenChange: setOpen, align: 'end', arrow: false, trigger: _jsxs(Button, { size: 'sm', variant: hiddenCount > 0 ? 'secondary' : 'ghost', leftIcon: _jsx(Columns3, {}), tooltip: hiddenCount > 0 ? `${hiddenCount} column(s) hidden` : label, children: [label, hiddenCount > 0 ? (_jsx("span", { className: 'ml-1.5 rounded-full bg-accent-solid px-1.5 py-0.5 text-caption font-bold text-accent-solid-foreground', children: hiddenCount })) : null] }), children: _jsxs("div", { className: 'flex flex-col gap-1.5', children: [_jsx("span", { className: 'cb-meta-label', children: "Columns" }), _jsx(ColumnChecklist, { "aria-label": 'Visible columns', selectAllLabel: 'Show all', selectNoneLabel: 'Hide all', items: columns.map((col) => ({
|
|
30
30
|
key: col.id,
|
|
31
31
|
label: col.columnDef.meta?.label ?? col.id,
|
|
32
32
|
checked: col.getIsVisible(),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ViewOptionsMenu.js","sourceRoot":"","sources":["../../../../src/react/components/DataTable/ViewOptionsMenu.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAOvD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,eAAe,CAAO,EAAE,KAAK,EAAE,KAAK,GAAG,SAAS,EAA8B;IAC5F,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,OAAO,GAAG,KAAK,CAAC,aAAa,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC;IACpE,IAAI,CAAC,OAAO,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACjC,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC,MAAM,CAAC;IAEpE,OAAO,CACL,KAAC,OAAO,IACN,IAAI,EAAE,IAAI,EACV,YAAY,EAAE,OAAO,EACrB,KAAK,EAAC,KAAK,EACX,KAAK,EAAE,KAAK,EACZ,OAAO,EACL,MAAC,MAAM,IACL,IAAI,EAAC,IAAI,EACT,OAAO,EAAE,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,EAChD,QAAQ,EAAE,KAAC,QAAQ,KAAG,EACtB,OAAO,EAAE,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,WAAW,mBAAmB,CAAC,CAAC,CAAC,KAAK,aAEnE,KAAK,EACL,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,CACjB,eAAM,SAAS,EAAC,
|
|
1
|
+
{"version":3,"file":"ViewOptionsMenu.js","sourceRoot":"","sources":["../../../../src/react/components/DataTable/ViewOptionsMenu.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAOvD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,eAAe,CAAO,EAAE,KAAK,EAAE,KAAK,GAAG,SAAS,EAA8B;IAC5F,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,OAAO,GAAG,KAAK,CAAC,aAAa,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC;IACpE,IAAI,CAAC,OAAO,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACjC,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC,MAAM,CAAC;IAEpE,OAAO,CACL,KAAC,OAAO,IACN,IAAI,EAAE,IAAI,EACV,YAAY,EAAE,OAAO,EACrB,KAAK,EAAC,KAAK,EACX,KAAK,EAAE,KAAK,EACZ,OAAO,EACL,MAAC,MAAM,IACL,IAAI,EAAC,IAAI,EACT,OAAO,EAAE,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,EAChD,QAAQ,EAAE,KAAC,QAAQ,KAAG,EACtB,OAAO,EAAE,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,WAAW,mBAAmB,CAAC,CAAC,CAAC,KAAK,aAEnE,KAAK,EACL,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,CACjB,eAAM,SAAS,EAAC,uGAAuG,YACpH,WAAW,GACP,CACR,CAAC,CAAC,CAAC,IAAI,IACD,YAGX,eAAK,SAAS,EAAC,uBAAuB,aACpC,eAAM,SAAS,EAAC,eAAe,wBAAe,EAC9C,KAAC,eAAe,kBACH,iBAAiB,EAC5B,cAAc,EAAC,UAAU,EACzB,eAAe,EAAC,UAAU,EAC1B,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;wBAC3B,GAAG,EAAE,GAAG,CAAC,EAAE;wBACX,KAAK,EAAE,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,KAAK,IAAI,GAAG,CAAC,EAAE;wBAC1C,OAAO,EAAE,GAAG,CAAC,YAAY,EAAE;qBAC5B,CAAC,CAAC,EACH,QAAQ,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,gBAAgB,EAAE,EAC3D,WAAW,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,uBAAuB,CAAC,IAAI,CAAC,EACtD,YAAY,EAAE,GAAG,EAAE;wBACjB,8DAA8D;wBAC9D,oEAAoE;wBACpE,kEAAkE;wBAClE,sCAAsC;wBACtC,KAAK,MAAM,GAAG,IAAI,OAAO;4BAAE,GAAG,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;oBACzD,CAAC,GACD,IACE,GACE,CACX,CAAC;AACJ,CAAC"}
|
|
@@ -45,6 +45,6 @@ export function SearchInput({ value, onChange, syntax, showSyntaxBadge = true, c
|
|
|
45
45
|
const pattern = useMemo(() => parseSearchPattern(value, syntax === false ? PLAIN_ONLY : syntax), [value, syntax]);
|
|
46
46
|
const badge = showSyntaxBadge ? badgeFor(pattern) : null;
|
|
47
47
|
const invalid = pattern.kind === 'invalid';
|
|
48
|
-
return (_jsxs("div", { className: cn('relative min-w-0', className), children: [_jsx(Search, { "aria-hidden": true, className: '-translate-y-1/2 pointer-events-none absolute top-1/2 left-2.5 size-4 text-muted-foreground' }), _jsx(Input, { ...inputProps, type: 'search', value: value, onChange: (event) => onChange(event.target.value), placeholder: placeholder, "aria-label": ariaLabel ?? (typeof placeholder === 'string' ? placeholder : 'Search'), "aria-invalid": invalid || undefined, className: cn('pl-8', badge && 'pr-9', inputClassName) }), badge ? (_jsx(Tooltip, { content: badge.tip, side: 'bottom', multiline: true, children: _jsx("span", { role: 'img', "aria-label": badge.label, "data-testid": 'search-syntax-badge', "data-kind": pattern.kind, className: cn('-translate-y-1/2 absolute top-1/2 right-2 inline-flex size-6 items-center justify-center rounded-full', invalid ? 'bg-destructive/15 text-destructive' : 'bg-
|
|
48
|
+
return (_jsxs("div", { className: cn('relative min-w-0', className), children: [_jsx(Search, { "aria-hidden": true, className: '-translate-y-1/2 pointer-events-none absolute top-1/2 left-2.5 size-4 text-muted-foreground' }), _jsx(Input, { ...inputProps, type: 'search', value: value, onChange: (event) => onChange(event.target.value), placeholder: placeholder, "aria-label": ariaLabel ?? (typeof placeholder === 'string' ? placeholder : 'Search'), "aria-invalid": invalid || undefined, className: cn('pl-8', badge && 'pr-9', inputClassName) }), badge ? (_jsx(Tooltip, { content: badge.tip, side: 'bottom', multiline: true, children: _jsx("span", { role: 'img', "aria-label": badge.label, "data-testid": 'search-syntax-badge', "data-kind": pattern.kind, className: cn('-translate-y-1/2 absolute top-1/2 right-2 inline-flex size-6 items-center justify-center rounded-full', invalid ? 'bg-destructive/15 text-destructive' : 'bg-accent/15 text-accent-strong'), children: _jsx(badge.icon, { className: 'size-3.5', "aria-hidden": true }) }) })) : null] }));
|
|
49
49
|
}
|
|
50
50
|
//# sourceMappingURL=SearchInput.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SearchInput.js","sourceRoot":"","sources":["../../../src/react/components/SearchInput.tsx"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"SearchInput.js","sourceRoot":"","sources":["../../../src/react/components/SearchInput.tsx"],"names":[],"mappings":"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"}
|
|
@@ -15,6 +15,8 @@ interface Rule {
|
|
|
15
15
|
check: (filePath: string, source: string) => Violation[];
|
|
16
16
|
}
|
|
17
17
|
export declare function walk(dir: string, out?: string[]): string[];
|
|
18
|
+
/** Set the stylesheets this scan resolves against; the belt's `theme.css` is always included. */
|
|
19
|
+
export declare function setThemeCss(appCss: readonly string[]): void;
|
|
18
20
|
export declare function setReimplementedNames(names: readonly string[]): void;
|
|
19
21
|
export declare function setPositionedClasses(compounds: readonly (readonly string[])[]): void;
|
|
20
22
|
export declare function positionedClassesFromCss(css: string): string[][];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guardrailsEnforce.d.ts","sourceRoot":"","sources":["../../scripts/guardrailsEnforce.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"guardrailsEnforce.d.ts","sourceRoot":"","sources":["../../scripts/guardrailsEnforce.ts"],"names":[],"mappings":";AAwNA,UAAU,SAAS;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB;;;sEAGkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,IAAI;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,SAAS,EAAE,CAAC;CACzD;AAED,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,GAAE,MAAM,EAAO,GAAG,MAAM,EAAE,CA6B9D;AAu5BD,iGAAiG;AACjG,wBAAgB,WAAW,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAE3D;AAmHD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAEpE;AA4tBD,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,SAAS,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,GAAG,IAAI,CAEpF;AAID,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,CAoBhE;AA8CD,eAAO,MAAM,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAuBtC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,EAAE,WAAW,CAAC,MAAM,CAAuC,CAAC;AAE5F,0EAA0E;AAC1E,eAAO,MAAM,SAAS,EAAE,SAAS,MAAM,EAAwE,CAAC;AAShH,eAAO,MAAM,uBAAuB,aAAkD,CAAC;AAGvF,MAAM,WAAW,SAAS;IACzB,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACb;AAED;2FAC2F;AAC3F,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CA0C3F;AAED,YAAY,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;AAmGhC,wBAAgB,0BAA0B,CAAC,SAAS,GAAE,MAAwB,GAAG,MAAM,EAAE,CAyBxF"}
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* after an app's responsive variant (task 2124). An app that imports every area gets exactly
|
|
19
19
|
* what `cursedbelt/styles-utilities.css` emits — proved rule by rule in
|
|
20
20
|
* src/stylesAreas.spec.ts, which is also what fails when this file is stale.
|
|
21
|
-
*
|
|
21
|
+
* 128 candidate(s).
|
|
22
22
|
*
|
|
23
23
|
* Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
|
|
24
24
|
* `bun run build` runs. The map of what is in which area, and why the areas are
|
|
@@ -27,23 +27,23 @@
|
|
|
27
27
|
@source inline("-m-1 -mt-6 -mx-1 -my-2.5 @3xl:block @3xl:hidden @xl:block @xl:hidden [&_svg]:size-3");
|
|
28
28
|
@source inline("[overflow-wrap:anywhere] active:cursor-grabbing appearance appearance-none");
|
|
29
29
|
@source inline("bg-[var(--cb-frozen-bg)] bg-card/95 bg-gradient-to-t bg-muted/30 bg-muted/40 bg-muted/50");
|
|
30
|
-
@source inline("border-0 border-field-error border-l border-r cursor-grab
|
|
31
|
-
@source inline("data-[ending-style]:opacity-0 data-[ending-style]:scale-95
|
|
32
|
-
@source inline("data-[highlighted]:
|
|
33
|
-
@source inline("data-[starting-style]:
|
|
34
|
-
@source inline("data-[state=closed]:slide-out-to-
|
|
35
|
-
@source inline("data-[state=
|
|
36
|
-
@source inline("data-[state=open]:slide-in-from-right disabled:opacity-40
|
|
37
|
-
@source inline("focus-visible:bg-muted focus-visible:ring-field-ring/40
|
|
38
|
-
@source inline("focus-within:ring-2 focus-within:ring-field-ring/30 font-sans
|
|
39
|
-
@source inline("has-[[aria-invalid=true]]:border-field-error hover:bg-background
|
|
40
|
-
@source inline("hover:bg-muted/40 hover:border-field-ring hover:text-warning italic
|
|
41
|
-
@source inline("last:border-0 left-0 left-2.5 line-clamp-2 list-none max-h-64 max-h-[22rem]
|
|
42
|
-
@source inline("max-h-[65dvh] max-h-[85dvh] max-w-32 max-w-36 max-w-48 max-w-[180px] max-w-[240px]
|
|
43
|
-
@source inline("min-w-24 min-w-52 min-w-[5rem] min-w-[var(--anchor-width)] ml-1.5 mr-2 mt-1.5 mt-3 mt-4");
|
|
30
|
+
@source inline("border-0 border-accent-solid border-accent/60 border-field-error border-l border-r cursor-grab");
|
|
31
|
+
@source inline("cursor-not-allowed data-[ending-style]:opacity-0 data-[ending-style]:scale-95");
|
|
32
|
+
@source inline("data-[highlighted]:bg-accent/10 data-[highlighted]:text-accent-strong");
|
|
33
|
+
@source inline("data-[starting-style]:opacity-0 data-[starting-style]:scale-95");
|
|
34
|
+
@source inline("data-[state=closed]:slide-out-to-bottom data-[state=closed]:slide-out-to-left");
|
|
35
|
+
@source inline("data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-bottom");
|
|
36
|
+
@source inline("data-[state=open]:slide-in-from-left data-[state=open]:slide-in-from-right disabled:opacity-40");
|
|
37
|
+
@source inline("duration duration-100 fade-in focus-visible:bg-muted focus-visible:ring-field-ring/40");
|
|
38
|
+
@source inline("focus-within:border-field-ring focus-within:ring-2 focus-within:ring-field-ring/30 font-sans");
|
|
39
|
+
@source inline("from-card h-[420px] has-[[aria-invalid=true]]:border-field-error hover:bg-background");
|
|
40
|
+
@source inline("hover:bg-border hover:bg-muted/40 hover:border-field-ring hover:text-warning italic");
|
|
41
|
+
@source inline("justify-self-end last:border-0 left-0 left-2.5 line-clamp-2 list-none max-h-64 max-h-[22rem]");
|
|
42
|
+
@source inline("max-h-[40dvh] max-h-[65dvh] max-h-[85dvh] max-w-32 max-w-36 max-w-48 max-w-[180px] max-w-[240px]");
|
|
43
|
+
@source inline("min-h-20 min-w-24 min-w-52 min-w-[5rem] min-w-[var(--anchor-width)] ml-1.5 mr-2 mt-1.5 mt-3 mt-4");
|
|
44
44
|
@source inline("not-italic ordinal pb-1.5 pl-1.5 pl-2 pr-0.5 pr-1 pr-10 pr-16 pr-3 pr-9 pt-1 resize-none");
|
|
45
45
|
@source inline("resize-y right-3 ring-field-error/30 rounded-l-xl rounded-r-xl rounded-t-xl self-center");
|
|
46
46
|
@source inline("self-stretch shadow-[1px_0_0_0_var(--color-border)] shrink-[2] size-2 size-7 slide-in-from-top-1");
|
|
47
|
-
@source inline("table-fixed text-field-placeholder text-muted-foreground/60
|
|
48
|
-
@source inline("text-xl to-transparent top-2 top-3 tracking-wider
|
|
49
|
-
@source inline("w-40 w-[352px]");
|
|
47
|
+
@source inline("table-fixed text-accent-solid-foreground text-field-placeholder text-muted-foreground/60");
|
|
48
|
+
@source inline("text-right text-success text-warning text-xl to-transparent top-2 top-3 tracking-wider");
|
|
49
|
+
@source inline("transition-[transform,opacity] w-20 w-28 w-36 w-40 w-[352px]");
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* after an app's responsive variant (task 2124). An app that imports every area gets exactly
|
|
19
19
|
* what `cursedbelt/styles-utilities.css` emits — proved rule by rule in
|
|
20
20
|
* src/stylesAreas.spec.ts, which is also what fails when this file is stale.
|
|
21
|
-
*
|
|
21
|
+
* 124 candidate(s).
|
|
22
22
|
*
|
|
23
23
|
* Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
|
|
24
24
|
* `bun run build` runs. The map of what is in which area, and why the areas are
|
|
@@ -27,23 +27,23 @@
|
|
|
27
27
|
@source inline("-m-1 -mt-6 -mx-1 -my-2.5 @3xl:block @3xl:hidden @xl:block @xl:hidden [&_svg]:size-3");
|
|
28
28
|
@source inline("[overflow-wrap:anywhere] active:cursor-grabbing appearance appearance-none");
|
|
29
29
|
@source inline("bg-[var(--cb-frozen-bg)] bg-card/95 bg-gradient-to-t bg-muted/30 bg-muted/50 border-0");
|
|
30
|
-
@source inline("border-field-error border-l border-r cursor-grab
|
|
31
|
-
@source inline("data-[ending-style]:opacity-0 data-[ending-style]:scale-95
|
|
32
|
-
@source inline("data-[highlighted]:
|
|
33
|
-
@source inline("data-[starting-style]:
|
|
34
|
-
@source inline("data-[state=closed]:slide-out-to-
|
|
35
|
-
@source inline("data-[state=
|
|
36
|
-
@source inline("data-[state=open]:slide-in-from-right disabled:opacity-40
|
|
37
|
-
@source inline("focus-visible:bg-muted focus-visible:ring-field-ring/40
|
|
38
|
-
@source inline("focus-within:ring-2 focus-within:ring-field-ring/30 font-sans
|
|
39
|
-
@source inline("has-[[aria-invalid=true]]:border-field-error hover:bg-background
|
|
40
|
-
@source inline("hover:bg-muted/40 hover:border-field-ring hover:text-warning justify-self-end
|
|
41
|
-
@source inline("left-0 left-2.5 line-clamp-2 list-none max-h-64 max-h-[22rem] max-h-[40dvh]
|
|
42
|
-
@source inline("max-h-[85dvh] max-w-32 max-w-36 max-w-48 max-w-[180px] max-w-[240px] min-h-20
|
|
43
|
-
@source inline("min-w-[var(--anchor-width)] ml-1.5 mr-2 mt-1.5 mt-3 mt-4 not-italic ordinal
|
|
44
|
-
@source inline("pr-0.5 pr-1 pr-10 pr-16 pr-3 pr-9 pt-1 resize-none resize-y right-3
|
|
45
|
-
@source inline("rounded-l-xl rounded-r-xl rounded-t-xl self-center self-stretch");
|
|
30
|
+
@source inline("border-accent-solid border-accent/60 border-field-error border-l border-r cursor-grab");
|
|
31
|
+
@source inline("cursor-not-allowed data-[ending-style]:opacity-0 data-[ending-style]:scale-95");
|
|
32
|
+
@source inline("data-[highlighted]:bg-accent/10 data-[highlighted]:text-accent-strong");
|
|
33
|
+
@source inline("data-[starting-style]:opacity-0 data-[starting-style]:scale-95");
|
|
34
|
+
@source inline("data-[state=closed]:slide-out-to-bottom data-[state=closed]:slide-out-to-left");
|
|
35
|
+
@source inline("data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-bottom");
|
|
36
|
+
@source inline("data-[state=open]:slide-in-from-left data-[state=open]:slide-in-from-right disabled:opacity-40");
|
|
37
|
+
@source inline("duration duration-100 fade-in focus-visible:bg-muted focus-visible:ring-field-ring/40");
|
|
38
|
+
@source inline("focus-within:border-field-ring focus-within:ring-2 focus-within:ring-field-ring/30 font-sans");
|
|
39
|
+
@source inline("from-card h-[420px] has-[[aria-invalid=true]]:border-field-error hover:bg-background");
|
|
40
|
+
@source inline("hover:bg-border hover:bg-muted/40 hover:border-field-ring hover:text-warning justify-self-end");
|
|
41
|
+
@source inline("last:border-0 left-0 left-2.5 line-clamp-2 list-none max-h-64 max-h-[22rem] max-h-[40dvh]");
|
|
42
|
+
@source inline("max-h-[65dvh] max-h-[85dvh] max-w-32 max-w-36 max-w-48 max-w-[180px] max-w-[240px] min-h-20");
|
|
43
|
+
@source inline("min-w-24 min-w-52 min-w-[var(--anchor-width)] ml-1.5 mr-2 mt-1.5 mt-3 mt-4 not-italic ordinal");
|
|
44
|
+
@source inline("pb-1.5 pl-1.5 pl-2 pr-0.5 pr-1 pr-10 pr-16 pr-3 pr-9 pt-1 resize-none resize-y right-3");
|
|
45
|
+
@source inline("ring-field-error/30 rounded-l-xl rounded-r-xl rounded-t-xl self-center self-stretch");
|
|
46
46
|
@source inline("shadow-[1px_0_0_0_var(--color-border)] size-2 size-7 slide-in-from-top-1 table-fixed");
|
|
47
|
-
@source inline("text-field-placeholder text-muted-foreground/60 text-right
|
|
48
|
-
@source inline("to-transparent top-2 top-3 tracking-wider
|
|
49
|
-
@source inline("w-[352px]");
|
|
47
|
+
@source inline("text-accent-solid-foreground text-field-placeholder text-muted-foreground/60 text-right");
|
|
48
|
+
@source inline("text-success text-warning text-xl to-transparent top-2 top-3 tracking-wider");
|
|
49
|
+
@source inline("transition-[transform,opacity] w-20 w-28 w-36 w-40 w-[352px]");
|
|
@@ -18,14 +18,14 @@
|
|
|
18
18
|
* after an app's responsive variant (task 2124). An app that imports every area gets exactly
|
|
19
19
|
* what `cursedbelt/styles-utilities.css` emits — proved rule by rule in
|
|
20
20
|
* src/stylesAreas.spec.ts, which is also what fails when this file is stale.
|
|
21
|
-
*
|
|
21
|
+
* 116 candidate(s).
|
|
22
22
|
*
|
|
23
23
|
* Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
|
|
24
24
|
* `bun run build` runs. The map of what is in which area, and why the areas are
|
|
25
25
|
* import closures rather than a hand-written list, is scripts/styleAreas.ts.
|
|
26
26
|
*/
|
|
27
27
|
@source inline("-mx-1 [&::-webkit-scrollbar]:hidden [&_svg]:size-3 [scrollbar-width:none] appearance");
|
|
28
|
-
@source inline("appearance-none bg-surface-sunken/80 bg-warning/10 border-accent border-border/40");
|
|
28
|
+
@source inline("appearance-none bg-accent/15 bg-surface-sunken/80 bg-warning/10 border-accent border-border/40");
|
|
29
29
|
@source inline("border-field-error border-l border-r caret-transparent cursor-not-allowed cursor-text");
|
|
30
30
|
@source inline("data-[ending-style]:opacity-0 data-[ending-style]:scale-95 data-[highlighted]:bg-accent/10");
|
|
31
31
|
@source inline("data-[highlighted]:text-accent-strong data-[starting-style]:opacity-0");
|
|
@@ -1612,6 +1612,12 @@
|
|
|
1612
1612
|
border-color: color-mix(in oklab, var(--accent) 50%, transparent);
|
|
1613
1613
|
}
|
|
1614
1614
|
}
|
|
1615
|
+
.border-accent\/60 {
|
|
1616
|
+
border-color: var(--accent);
|
|
1617
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
1618
|
+
border-color: color-mix(in oklab, var(--accent) 60%, transparent);
|
|
1619
|
+
}
|
|
1620
|
+
}
|
|
1615
1621
|
.border-accent\/70 {
|
|
1616
1622
|
border-color: var(--accent);
|
|
1617
1623
|
@supports (color: color-mix(in lab, red, red)) {
|
|
@@ -2626,6 +2632,9 @@
|
|
|
2626
2632
|
.text-accent {
|
|
2627
2633
|
color: var(--accent);
|
|
2628
2634
|
}
|
|
2635
|
+
.text-accent-solid-foreground {
|
|
2636
|
+
color: var(--accent-solid-foreground);
|
|
2637
|
+
}
|
|
2629
2638
|
.text-accent-strong {
|
|
2630
2639
|
color: var(--accent-strong);
|
|
2631
2640
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cursedbelt",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.20.0",
|
|
4
4
|
"license": "ISC",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "The React design system of the cursedbelt split — components, styles, theme. cursedbelt-core below it; server tier in cursedbelt-server.",
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
RULES,
|
|
17
17
|
setPositionedClasses,
|
|
18
18
|
setReimplementedNames,
|
|
19
|
+
setThemeCss,
|
|
19
20
|
walk,
|
|
20
21
|
} from './guardrailsEnforce';
|
|
21
22
|
|
|
@@ -588,6 +589,57 @@ describe('no-tailwind-palette', () => {
|
|
|
588
589
|
});
|
|
589
590
|
});
|
|
590
591
|
|
|
592
|
+
describe('theme-colours-resolve (task 2240)', () => {
|
|
593
|
+
const REGISTERS_PRIMARY = '@theme inline {\n --color-primary: var(--primary);\n}\n';
|
|
594
|
+
afterEach(() => setThemeCss([]));
|
|
595
|
+
|
|
596
|
+
test('🔴 a colour the belt DEFINES but nothing registers is flagged — bg-primary drew nothing in flix', () => {
|
|
597
|
+
setThemeCss([]);
|
|
598
|
+
const found = check('theme-colours-resolve', '<span className="bg-primary/10 text-primary-foreground" />');
|
|
599
|
+
expect(found.map((v) => v.snippet.split(' — ')[0])).toEqual(['bg-primary/10', 'text-primary-foreground']);
|
|
600
|
+
});
|
|
601
|
+
|
|
602
|
+
test("the app's own @theme registering it makes it resolve", () => {
|
|
603
|
+
setThemeCss([REGISTERS_PRIMARY]);
|
|
604
|
+
expect(check('theme-colours-resolve', '<span className="bg-primary/10 border-primary/60" />')).toHaveLength(0);
|
|
605
|
+
expect(check('theme-colours-resolve', '<span className="text-primary-foreground" />')).toHaveLength(1);
|
|
606
|
+
});
|
|
607
|
+
|
|
608
|
+
test("an app's own custom property is checked the same way", () => {
|
|
609
|
+
setThemeCss([':root { --brand: #123456; }\n']);
|
|
610
|
+
expect(check('theme-colours-resolve', '<b className="text-brand" />')).toHaveLength(1);
|
|
611
|
+
setThemeCss([':root { --brand: #123456; }\n@theme {\n --color-brand: var(--brand);\n}\n']);
|
|
612
|
+
expect(check('theme-colours-resolve', '<b className="text-brand" />')).toHaveLength(0);
|
|
613
|
+
});
|
|
614
|
+
|
|
615
|
+
test("Tailwind's own names, the registered tokens and a CSS file are not its business", () => {
|
|
616
|
+
setThemeCss([]);
|
|
617
|
+
expect(check('theme-colours-resolve', '<p className="text-sm border-2 bg-accent/15 text-accent-strong border-border" />')).toHaveLength(0);
|
|
618
|
+
expect(RULES['theme-colours-resolve'].check('a.css', '.x { border-radius: var(--radius); }')).toHaveLength(0);
|
|
619
|
+
});
|
|
620
|
+
|
|
621
|
+
test('takes the opt-out comment, and a comment is not a class', () => {
|
|
622
|
+
setThemeCss([]);
|
|
623
|
+
expect(check('theme-colours-resolve', '// guardrails-ignore theme-colours-resolve: an @apply target\n<i className="bg-primary" />')).toHaveLength(0);
|
|
624
|
+
expect(check('theme-colours-resolve', '// we used to write bg-primary here\n<i />')).toHaveLength(0);
|
|
625
|
+
});
|
|
626
|
+
|
|
627
|
+
test('🔴 end to end: an app registering the colour OUTSIDE its scanned root still resolves', async () => {
|
|
628
|
+
const rows = JSON.stringify(Object.fromEntries(APP_RULES.map((name) => [name, 0])));
|
|
629
|
+
const app = { 'scripts/baseline.json': rows, 'src/Badge.tsx': 'export const B = () => <span className="bg-primary" />;\n' };
|
|
630
|
+
await withFixture(app, async (dir) => {
|
|
631
|
+
const { code, report } = await runCli(dir, ['--all-app-rules', '--baseline', 'scripts/baseline.json', 'src']);
|
|
632
|
+
expect(report).toContain('bg-primary');
|
|
633
|
+
expect(code).toBe(1);
|
|
634
|
+
});
|
|
635
|
+
await withFixture({ ...app, 'styles/globals.css': REGISTERS_PRIMARY }, async (dir) => {
|
|
636
|
+
const { code, report } = await runCli(dir, ['--all-app-rules', '--baseline', 'scripts/baseline.json', 'src']);
|
|
637
|
+
expect(report).toContain('✓ theme-colours-resolve: 0 violation(s)');
|
|
638
|
+
expect(code).toBe(0);
|
|
639
|
+
});
|
|
640
|
+
});
|
|
641
|
+
});
|
|
642
|
+
|
|
591
643
|
describe('no-raw-title-attr', () => {
|
|
592
644
|
test('flags title= on a DOM element', () => {
|
|
593
645
|
expect(check('no-raw-title-attr', '<button title="Delete"><Trash /></button>')).toHaveLength(1);
|
|
@@ -89,6 +89,11 @@
|
|
|
89
89
|
// `text-muted-foreground`), arbitrary token values (`bg-[var(--surface-2)]`) and
|
|
90
90
|
// `white`/`black`/`transparent`/`current` are not matched.
|
|
91
91
|
//
|
|
92
|
+
// theme-colours-resolve — task 2240: a colour utility (`bg-primary`) must name a colour an
|
|
93
|
+
// `@theme` REGISTERS (`--color-primary`), not merely a custom property some stylesheet
|
|
94
|
+
// defines — otherwise Tailwind emits nothing and the element draws no colour. Resolved
|
|
95
|
+
// against the belt's `theme.css` plus every `.css` in the app package. See its block.
|
|
96
|
+
//
|
|
92
97
|
// no-raw-title-attr — DESIGN.md §4 ("Help Context Disclosing"): no native `title=""`
|
|
93
98
|
// on a DOM element. It does not exist on a touch device, waits ~500ms, cannot be
|
|
94
99
|
// themed, and reads inconsistently to a screen reader. Use cursedbelt's `Tooltip`,
|
|
@@ -1116,6 +1121,102 @@ const noTailwindPalette: Rule = makeValueRule(
|
|
|
1116
1121
|
TAILWIND_PALETTE_RE,
|
|
1117
1122
|
);
|
|
1118
1123
|
|
|
1124
|
+
// ── theme-colours-resolve (task 2240) ───────────────────────────────────────
|
|
1125
|
+
// A colour utility must name a colour Tailwind can GENERATE, not merely a CSS variable that
|
|
1126
|
+
// exists. `theme.css` defined `--primary` as an alias but registered no `--color-primary` in
|
|
1127
|
+
// its `@theme`, so `bg-primary` compiled to nothing: no error, the class is simply absent from
|
|
1128
|
+
// the built CSS. Measured in flix on 2026-09-28 — SearchInput's badge background read
|
|
1129
|
+
// `rgba(0, 0, 0, 0)` off Chromium — and four DataTable components carried the same classes.
|
|
1130
|
+
// `src/themeColorsResolve.spec.ts` holds the belt's own components to this since 5.19.1; this
|
|
1131
|
+
// rule is the same check for an app, whose classes resolve against its own stylesheet too.
|
|
1132
|
+
//
|
|
1133
|
+
// The rule: a colour prefix (`bg-`, `text-`, `border-`, …) plus a name some stylesheet DEFINES
|
|
1134
|
+
// as a custom property (`--primary: …`) must have `--color-<name>` (or `--<prefix>-<name>`)
|
|
1135
|
+
// REGISTERED in an `@theme` block. Defined and registered are both read from the belt's
|
|
1136
|
+
// `theme.css` plus every `.css` in the app package (`setThemeCss`, from `main()`), because an
|
|
1137
|
+
// app's `@theme` need not sit under the roots it scans — binary-server's is `styles/globals.css`.
|
|
1138
|
+
// A name no stylesheet defines (`text-sm`, `border-2`, `bg-slate-800`) is Tailwind's own and is
|
|
1139
|
+
// another rule's business. `.css` files are not scanned: `border-radius:` and `outline-offset:`
|
|
1140
|
+
// are properties, not utilities, and would read as `border-` + a defined `--radius`.
|
|
1141
|
+
const THEME_COLOUR_PREFIXES = [
|
|
1142
|
+
"bg", "text", "border", "ring", "outline", "fill", "stroke", "from", "via", "to",
|
|
1143
|
+
"divide", "decoration", "placeholder", "caret", "ring-offset",
|
|
1144
|
+
];
|
|
1145
|
+
const THEME_COLOUR_CLASS_RE = new RegExp(
|
|
1146
|
+
`(?<![\\w-])(${THEME_COLOUR_PREFIXES.join("|")})-([a-z][a-z0-9-]*?)(?:/\\d+)?(?![\\w/-])`,
|
|
1147
|
+
"g",
|
|
1148
|
+
);
|
|
1149
|
+
const BELT_THEME_CSS = join(import.meta.dir, "..", "src", "theme.css");
|
|
1150
|
+
|
|
1151
|
+
interface ThemeIndex {
|
|
1152
|
+
/** Every `--x` an `@theme` block registers — what Tailwind can make utilities from. */
|
|
1153
|
+
registered: Set<string>;
|
|
1154
|
+
/** Every custom property defined anywhere — the names a utility could be MISTAKEN for. */
|
|
1155
|
+
defined: Set<string>;
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1158
|
+
/** Index `@theme` registrations and custom-property definitions across stylesheets. */
|
|
1159
|
+
function themeIndexFromCss(sources: readonly string[]): ThemeIndex {
|
|
1160
|
+
const registered = new Set<string>();
|
|
1161
|
+
const defined = new Set<string>();
|
|
1162
|
+
for (const raw of sources) {
|
|
1163
|
+
const css = raw.replace(/\/\*[\s\S]*?\*\//g, " ");
|
|
1164
|
+
for (const block of css.matchAll(/@theme[^{]*\{([\s\S]*?)\n\}/g)) {
|
|
1165
|
+
for (const m of (block[1] ?? "").matchAll(/--([a-z0-9-]+)\s*:/g)) registered.add(m[1] ?? "");
|
|
1166
|
+
}
|
|
1167
|
+
for (const m of css.matchAll(/--([a-z0-9-]+)\s*:/g)) defined.add(m[1] ?? "");
|
|
1168
|
+
}
|
|
1169
|
+
return { registered, defined };
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
/** The belt's own `theme.css` — the index a caller outside `main()` gets by default. */
|
|
1173
|
+
function beltThemeCss(): string[] {
|
|
1174
|
+
try {
|
|
1175
|
+
return [readFileSync(BELT_THEME_CSS, "utf8")];
|
|
1176
|
+
} catch {
|
|
1177
|
+
return [];
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
let THEME_INDEX: ThemeIndex | undefined;
|
|
1182
|
+
/** Set the stylesheets this scan resolves against; the belt's `theme.css` is always included. */
|
|
1183
|
+
export function setThemeCss(appCss: readonly string[]): void {
|
|
1184
|
+
THEME_INDEX = themeIndexFromCss([...beltThemeCss(), ...appCss]);
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
/** The utilities in `source` that name a defined-but-unregistered colour, with their offsets. */
|
|
1188
|
+
function unresolvedThemeColours(source: string, index: ThemeIndex): { cls: string; at: number }[] {
|
|
1189
|
+
const out: { cls: string; at: number }[] = [];
|
|
1190
|
+
THEME_COLOUR_CLASS_RE.lastIndex = 0;
|
|
1191
|
+
for (const m of source.matchAll(THEME_COLOUR_CLASS_RE)) {
|
|
1192
|
+
const name = m[2] ?? "";
|
|
1193
|
+
if (!index.defined.has(name)) continue;
|
|
1194
|
+
if (index.registered.has(`color-${name}`) || index.registered.has(`${m[1]}-${name}`)) continue;
|
|
1195
|
+
out.push({ cls: m[0], at: m.index ?? 0 });
|
|
1196
|
+
}
|
|
1197
|
+
return out;
|
|
1198
|
+
}
|
|
1199
|
+
|
|
1200
|
+
const THEME_COLOURS_IGNORE_RE = /guardrails-ignore\s+theme-colours-resolve\s*:/;
|
|
1201
|
+
|
|
1202
|
+
const themeColoursResolve: Rule = {
|
|
1203
|
+
name: "theme-colours-resolve",
|
|
1204
|
+
description:
|
|
1205
|
+
"a colour utility (bg-primary, text-primary-foreground, …) names a CSS variable no @theme registers as --color-<name>, so Tailwind generates NOTHING for it and the element draws no colour. Register `--color-<name>: var(--<name>);` in the app's @theme, or use a colour the theme registers.",
|
|
1206
|
+
check(filePath, source) {
|
|
1207
|
+
if (extname(filePath) === ".css") return [];
|
|
1208
|
+
THEME_INDEX ??= themeIndexFromCss(beltThemeCss());
|
|
1209
|
+
const violations: Violation[] = [];
|
|
1210
|
+
const lines = source.split("\n");
|
|
1211
|
+
for (const { cls, at } of unresolvedThemeColours(blankComments(source), THEME_INDEX)) {
|
|
1212
|
+
const line = lineOf(source, at);
|
|
1213
|
+
if (THEME_COLOURS_IGNORE_RE.test(lines.slice(Math.max(0, line - 3), line).join("\n"))) continue;
|
|
1214
|
+
violations.push({ file: filePath, line, snippet: `${cls} — ${lines[line - 1]?.trim() ?? ""}` });
|
|
1215
|
+
}
|
|
1216
|
+
return violations;
|
|
1217
|
+
},
|
|
1218
|
+
};
|
|
1219
|
+
|
|
1119
1220
|
// ── no-raw-title-attr (DESIGN.md §4 "Help Context Disclosing") ──────────────
|
|
1120
1221
|
// A native `title=""` is the cheapest possible tooltip and it is four separate
|
|
1121
1222
|
// failures at once: it does not exist on a touch device (there is no hover), it
|
|
@@ -2013,6 +2114,7 @@ export const RULES: Record<string, Rule> = {
|
|
|
2013
2114
|
[noRawZindex.name]: noRawZindex,
|
|
2014
2115
|
[noRawDataTable.name]: noRawDataTable,
|
|
2015
2116
|
[noTailwindPalette.name]: noTailwindPalette,
|
|
2117
|
+
[themeColoursResolve.name]: themeColoursResolve,
|
|
2016
2118
|
[noRawTitleAttr.name]: noRawTitleAttr,
|
|
2017
2119
|
[noLocalReimplementation.name]: noLocalReimplementation,
|
|
2018
2120
|
[microTypographyFloor.name]: microTypographyFloor,
|
|
@@ -2356,6 +2458,10 @@ function main() {
|
|
|
2356
2458
|
const sourcesByFile = new Map<string, string>();
|
|
2357
2459
|
for (const file of files) sourcesByFile.set(file, readFileSync(file, "utf8"));
|
|
2358
2460
|
|
|
2461
|
+
// `theme-colours-resolve` resolves against every stylesheet in the package, not only the
|
|
2462
|
+
// scanned roots — an app's `@theme` can live beside `src/` (binary-server's `styles/`).
|
|
2463
|
+
setThemeCss(walk(".").filter((file) => extname(file) === ".css").map((file) => readFileSync(file, "utf8")));
|
|
2464
|
+
|
|
2359
2465
|
// `no-raw-popover` sees a popup its app's stylesheet positions — see that rule.
|
|
2360
2466
|
setPositionedClasses(
|
|
2361
2467
|
[...sourcesByFile].filter(([file]) => extname(file) === ".css").flatMap(([, css]) => positionedClassesFromCss(css)),
|
|
@@ -106,7 +106,7 @@ export function ColumnChecklist({
|
|
|
106
106
|
aria-hidden
|
|
107
107
|
className={cn(
|
|
108
108
|
'flex size-4 shrink-0 items-center justify-center rounded border',
|
|
109
|
-
item.checked ? 'border-
|
|
109
|
+
item.checked ? 'border-accent-solid bg-accent-solid text-accent-solid-foreground' : 'border-border',
|
|
110
110
|
)}
|
|
111
111
|
>
|
|
112
112
|
{item.checked ? <Check className='size-3' /> : null}
|
|
@@ -111,7 +111,7 @@ export function SearchBox({
|
|
|
111
111
|
'hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
|
|
112
112
|
// Narrowed scope reads as ACTIVE state, not as another grey
|
|
113
113
|
// control — the whole point is that it cannot hide.
|
|
114
|
-
isAll ? 'text-muted-foreground' : 'border-
|
|
114
|
+
isAll ? 'text-muted-foreground' : 'border-accent/60 bg-accent/10 text-foreground',
|
|
115
115
|
)}
|
|
116
116
|
>
|
|
117
117
|
<span className='max-w-32 truncate'>{scopeLabel}</span>
|
|
@@ -119,7 +119,7 @@ export function TableFilterBuilder({
|
|
|
119
119
|
>
|
|
120
120
|
Filter
|
|
121
121
|
{activeCount > 0 ? (
|
|
122
|
-
<span className='ml-1.5 rounded-full bg-
|
|
122
|
+
<span className='ml-1.5 rounded-full bg-accent-solid px-1.5 py-0.5 text-caption font-bold text-accent-solid-foreground'>
|
|
123
123
|
{activeCount}
|
|
124
124
|
</span>
|
|
125
125
|
) : null}
|
|
@@ -47,7 +47,7 @@ export function ViewOptionsMenu<TRow>({ table, label = 'Columns' }: ViewOptionsM
|
|
|
47
47
|
>
|
|
48
48
|
{label}
|
|
49
49
|
{hiddenCount > 0 ? (
|
|
50
|
-
<span className='ml-1.5 rounded-full bg-
|
|
50
|
+
<span className='ml-1.5 rounded-full bg-accent-solid px-1.5 py-0.5 text-caption font-bold text-accent-solid-foreground'>
|
|
51
51
|
{hiddenCount}
|
|
52
52
|
</span>
|
|
53
53
|
) : null}
|
|
@@ -105,7 +105,7 @@ export function SearchInput({
|
|
|
105
105
|
data-kind={pattern.kind}
|
|
106
106
|
className={cn(
|
|
107
107
|
'-translate-y-1/2 absolute top-1/2 right-2 inline-flex size-6 items-center justify-center rounded-full',
|
|
108
|
-
invalid ? 'bg-destructive/15 text-destructive' : 'bg-
|
|
108
|
+
invalid ? 'bg-destructive/15 text-destructive' : 'bg-accent/15 text-accent-strong',
|
|
109
109
|
)}
|
|
110
110
|
>
|
|
111
111
|
<badge.icon className='size-3.5' aria-hidden />
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* after an app's responsive variant (task 2124). An app that imports every area gets exactly
|
|
19
19
|
* what `cursedbelt/styles-utilities.css` emits — proved rule by rule in
|
|
20
20
|
* src/stylesAreas.spec.ts, which is also what fails when this file is stale.
|
|
21
|
-
*
|
|
21
|
+
* 128 candidate(s).
|
|
22
22
|
*
|
|
23
23
|
* Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
|
|
24
24
|
* `bun run build` runs. The map of what is in which area, and why the areas are
|
|
@@ -27,23 +27,23 @@
|
|
|
27
27
|
@source inline("-m-1 -mt-6 -mx-1 -my-2.5 @3xl:block @3xl:hidden @xl:block @xl:hidden [&_svg]:size-3");
|
|
28
28
|
@source inline("[overflow-wrap:anywhere] active:cursor-grabbing appearance appearance-none");
|
|
29
29
|
@source inline("bg-[var(--cb-frozen-bg)] bg-card/95 bg-gradient-to-t bg-muted/30 bg-muted/40 bg-muted/50");
|
|
30
|
-
@source inline("border-0 border-field-error border-l border-r cursor-grab
|
|
31
|
-
@source inline("data-[ending-style]:opacity-0 data-[ending-style]:scale-95
|
|
32
|
-
@source inline("data-[highlighted]:
|
|
33
|
-
@source inline("data-[starting-style]:
|
|
34
|
-
@source inline("data-[state=closed]:slide-out-to-
|
|
35
|
-
@source inline("data-[state=
|
|
36
|
-
@source inline("data-[state=open]:slide-in-from-right disabled:opacity-40
|
|
37
|
-
@source inline("focus-visible:bg-muted focus-visible:ring-field-ring/40
|
|
38
|
-
@source inline("focus-within:ring-2 focus-within:ring-field-ring/30 font-sans
|
|
39
|
-
@source inline("has-[[aria-invalid=true]]:border-field-error hover:bg-background
|
|
40
|
-
@source inline("hover:bg-muted/40 hover:border-field-ring hover:text-warning italic
|
|
41
|
-
@source inline("last:border-0 left-0 left-2.5 line-clamp-2 list-none max-h-64 max-h-[22rem]
|
|
42
|
-
@source inline("max-h-[65dvh] max-h-[85dvh] max-w-32 max-w-36 max-w-48 max-w-[180px] max-w-[240px]
|
|
43
|
-
@source inline("min-w-24 min-w-52 min-w-[5rem] min-w-[var(--anchor-width)] ml-1.5 mr-2 mt-1.5 mt-3 mt-4");
|
|
30
|
+
@source inline("border-0 border-accent-solid border-accent/60 border-field-error border-l border-r cursor-grab");
|
|
31
|
+
@source inline("cursor-not-allowed data-[ending-style]:opacity-0 data-[ending-style]:scale-95");
|
|
32
|
+
@source inline("data-[highlighted]:bg-accent/10 data-[highlighted]:text-accent-strong");
|
|
33
|
+
@source inline("data-[starting-style]:opacity-0 data-[starting-style]:scale-95");
|
|
34
|
+
@source inline("data-[state=closed]:slide-out-to-bottom data-[state=closed]:slide-out-to-left");
|
|
35
|
+
@source inline("data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-bottom");
|
|
36
|
+
@source inline("data-[state=open]:slide-in-from-left data-[state=open]:slide-in-from-right disabled:opacity-40");
|
|
37
|
+
@source inline("duration duration-100 fade-in focus-visible:bg-muted focus-visible:ring-field-ring/40");
|
|
38
|
+
@source inline("focus-within:border-field-ring focus-within:ring-2 focus-within:ring-field-ring/30 font-sans");
|
|
39
|
+
@source inline("from-card h-[420px] has-[[aria-invalid=true]]:border-field-error hover:bg-background");
|
|
40
|
+
@source inline("hover:bg-border hover:bg-muted/40 hover:border-field-ring hover:text-warning italic");
|
|
41
|
+
@source inline("justify-self-end last:border-0 left-0 left-2.5 line-clamp-2 list-none max-h-64 max-h-[22rem]");
|
|
42
|
+
@source inline("max-h-[40dvh] max-h-[65dvh] max-h-[85dvh] max-w-32 max-w-36 max-w-48 max-w-[180px] max-w-[240px]");
|
|
43
|
+
@source inline("min-h-20 min-w-24 min-w-52 min-w-[5rem] min-w-[var(--anchor-width)] ml-1.5 mr-2 mt-1.5 mt-3 mt-4");
|
|
44
44
|
@source inline("not-italic ordinal pb-1.5 pl-1.5 pl-2 pr-0.5 pr-1 pr-10 pr-16 pr-3 pr-9 pt-1 resize-none");
|
|
45
45
|
@source inline("resize-y right-3 ring-field-error/30 rounded-l-xl rounded-r-xl rounded-t-xl self-center");
|
|
46
46
|
@source inline("self-stretch shadow-[1px_0_0_0_var(--color-border)] shrink-[2] size-2 size-7 slide-in-from-top-1");
|
|
47
|
-
@source inline("table-fixed text-field-placeholder text-muted-foreground/60
|
|
48
|
-
@source inline("text-xl to-transparent top-2 top-3 tracking-wider
|
|
49
|
-
@source inline("w-40 w-[352px]");
|
|
47
|
+
@source inline("table-fixed text-accent-solid-foreground text-field-placeholder text-muted-foreground/60");
|
|
48
|
+
@source inline("text-right text-success text-warning text-xl to-transparent top-2 top-3 tracking-wider");
|
|
49
|
+
@source inline("transition-[transform,opacity] w-20 w-28 w-36 w-40 w-[352px]");
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* after an app's responsive variant (task 2124). An app that imports every area gets exactly
|
|
19
19
|
* what `cursedbelt/styles-utilities.css` emits — proved rule by rule in
|
|
20
20
|
* src/stylesAreas.spec.ts, which is also what fails when this file is stale.
|
|
21
|
-
*
|
|
21
|
+
* 124 candidate(s).
|
|
22
22
|
*
|
|
23
23
|
* Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
|
|
24
24
|
* `bun run build` runs. The map of what is in which area, and why the areas are
|
|
@@ -27,23 +27,23 @@
|
|
|
27
27
|
@source inline("-m-1 -mt-6 -mx-1 -my-2.5 @3xl:block @3xl:hidden @xl:block @xl:hidden [&_svg]:size-3");
|
|
28
28
|
@source inline("[overflow-wrap:anywhere] active:cursor-grabbing appearance appearance-none");
|
|
29
29
|
@source inline("bg-[var(--cb-frozen-bg)] bg-card/95 bg-gradient-to-t bg-muted/30 bg-muted/50 border-0");
|
|
30
|
-
@source inline("border-field-error border-l border-r cursor-grab
|
|
31
|
-
@source inline("data-[ending-style]:opacity-0 data-[ending-style]:scale-95
|
|
32
|
-
@source inline("data-[highlighted]:
|
|
33
|
-
@source inline("data-[starting-style]:
|
|
34
|
-
@source inline("data-[state=closed]:slide-out-to-
|
|
35
|
-
@source inline("data-[state=
|
|
36
|
-
@source inline("data-[state=open]:slide-in-from-right disabled:opacity-40
|
|
37
|
-
@source inline("focus-visible:bg-muted focus-visible:ring-field-ring/40
|
|
38
|
-
@source inline("focus-within:ring-2 focus-within:ring-field-ring/30 font-sans
|
|
39
|
-
@source inline("has-[[aria-invalid=true]]:border-field-error hover:bg-background
|
|
40
|
-
@source inline("hover:bg-muted/40 hover:border-field-ring hover:text-warning justify-self-end
|
|
41
|
-
@source inline("left-0 left-2.5 line-clamp-2 list-none max-h-64 max-h-[22rem] max-h-[40dvh]
|
|
42
|
-
@source inline("max-h-[85dvh] max-w-32 max-w-36 max-w-48 max-w-[180px] max-w-[240px] min-h-20
|
|
43
|
-
@source inline("min-w-[var(--anchor-width)] ml-1.5 mr-2 mt-1.5 mt-3 mt-4 not-italic ordinal
|
|
44
|
-
@source inline("pr-0.5 pr-1 pr-10 pr-16 pr-3 pr-9 pt-1 resize-none resize-y right-3
|
|
45
|
-
@source inline("rounded-l-xl rounded-r-xl rounded-t-xl self-center self-stretch");
|
|
30
|
+
@source inline("border-accent-solid border-accent/60 border-field-error border-l border-r cursor-grab");
|
|
31
|
+
@source inline("cursor-not-allowed data-[ending-style]:opacity-0 data-[ending-style]:scale-95");
|
|
32
|
+
@source inline("data-[highlighted]:bg-accent/10 data-[highlighted]:text-accent-strong");
|
|
33
|
+
@source inline("data-[starting-style]:opacity-0 data-[starting-style]:scale-95");
|
|
34
|
+
@source inline("data-[state=closed]:slide-out-to-bottom data-[state=closed]:slide-out-to-left");
|
|
35
|
+
@source inline("data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-bottom");
|
|
36
|
+
@source inline("data-[state=open]:slide-in-from-left data-[state=open]:slide-in-from-right disabled:opacity-40");
|
|
37
|
+
@source inline("duration duration-100 fade-in focus-visible:bg-muted focus-visible:ring-field-ring/40");
|
|
38
|
+
@source inline("focus-within:border-field-ring focus-within:ring-2 focus-within:ring-field-ring/30 font-sans");
|
|
39
|
+
@source inline("from-card h-[420px] has-[[aria-invalid=true]]:border-field-error hover:bg-background");
|
|
40
|
+
@source inline("hover:bg-border hover:bg-muted/40 hover:border-field-ring hover:text-warning justify-self-end");
|
|
41
|
+
@source inline("last:border-0 left-0 left-2.5 line-clamp-2 list-none max-h-64 max-h-[22rem] max-h-[40dvh]");
|
|
42
|
+
@source inline("max-h-[65dvh] max-h-[85dvh] max-w-32 max-w-36 max-w-48 max-w-[180px] max-w-[240px] min-h-20");
|
|
43
|
+
@source inline("min-w-24 min-w-52 min-w-[var(--anchor-width)] ml-1.5 mr-2 mt-1.5 mt-3 mt-4 not-italic ordinal");
|
|
44
|
+
@source inline("pb-1.5 pl-1.5 pl-2 pr-0.5 pr-1 pr-10 pr-16 pr-3 pr-9 pt-1 resize-none resize-y right-3");
|
|
45
|
+
@source inline("ring-field-error/30 rounded-l-xl rounded-r-xl rounded-t-xl self-center self-stretch");
|
|
46
46
|
@source inline("shadow-[1px_0_0_0_var(--color-border)] size-2 size-7 slide-in-from-top-1 table-fixed");
|
|
47
|
-
@source inline("text-field-placeholder text-muted-foreground/60 text-right
|
|
48
|
-
@source inline("to-transparent top-2 top-3 tracking-wider
|
|
49
|
-
@source inline("w-[352px]");
|
|
47
|
+
@source inline("text-accent-solid-foreground text-field-placeholder text-muted-foreground/60 text-right");
|
|
48
|
+
@source inline("text-success text-warning text-xl to-transparent top-2 top-3 tracking-wider");
|
|
49
|
+
@source inline("transition-[transform,opacity] w-20 w-28 w-36 w-40 w-[352px]");
|
|
@@ -18,14 +18,14 @@
|
|
|
18
18
|
* after an app's responsive variant (task 2124). An app that imports every area gets exactly
|
|
19
19
|
* what `cursedbelt/styles-utilities.css` emits — proved rule by rule in
|
|
20
20
|
* src/stylesAreas.spec.ts, which is also what fails when this file is stale.
|
|
21
|
-
*
|
|
21
|
+
* 116 candidate(s).
|
|
22
22
|
*
|
|
23
23
|
* Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
|
|
24
24
|
* `bun run build` runs. The map of what is in which area, and why the areas are
|
|
25
25
|
* import closures rather than a hand-written list, is scripts/styleAreas.ts.
|
|
26
26
|
*/
|
|
27
27
|
@source inline("-mx-1 [&::-webkit-scrollbar]:hidden [&_svg]:size-3 [scrollbar-width:none] appearance");
|
|
28
|
-
@source inline("appearance-none bg-surface-sunken/80 bg-warning/10 border-accent border-border/40");
|
|
28
|
+
@source inline("appearance-none bg-accent/15 bg-surface-sunken/80 bg-warning/10 border-accent border-border/40");
|
|
29
29
|
@source inline("border-field-error border-l border-r caret-transparent cursor-not-allowed cursor-text");
|
|
30
30
|
@source inline("data-[ending-style]:opacity-0 data-[ending-style]:scale-95 data-[highlighted]:bg-accent/10");
|
|
31
31
|
@source inline("data-[highlighted]:text-accent-strong data-[starting-style]:opacity-0");
|
package/src/styles-utilities.css
CHANGED
|
@@ -1612,6 +1612,12 @@
|
|
|
1612
1612
|
border-color: color-mix(in oklab, var(--accent) 50%, transparent);
|
|
1613
1613
|
}
|
|
1614
1614
|
}
|
|
1615
|
+
.border-accent\/60 {
|
|
1616
|
+
border-color: var(--accent);
|
|
1617
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
1618
|
+
border-color: color-mix(in oklab, var(--accent) 60%, transparent);
|
|
1619
|
+
}
|
|
1620
|
+
}
|
|
1615
1621
|
.border-accent\/70 {
|
|
1616
1622
|
border-color: var(--accent);
|
|
1617
1623
|
@supports (color: color-mix(in lab, red, red)) {
|
|
@@ -2626,6 +2632,9 @@
|
|
|
2626
2632
|
.text-accent {
|
|
2627
2633
|
color: var(--accent);
|
|
2628
2634
|
}
|
|
2635
|
+
.text-accent-solid-foreground {
|
|
2636
|
+
color: var(--accent-solid-foreground);
|
|
2637
|
+
}
|
|
2629
2638
|
.text-accent-strong {
|
|
2630
2639
|
color: var(--accent-strong);
|
|
2631
2640
|
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A colour utility must name a colour Tailwind can GENERATE — not merely a CSS variable
|
|
3
|
+
* that exists.
|
|
4
|
+
*
|
|
5
|
+
* ── The measurement this exists because of (2026-09-28) ─────────────────────
|
|
6
|
+
* `theme.css` defines `--primary` and `--primary-foreground` as ALIASES — `var(--primary)`
|
|
7
|
+
* works — but registers no `--color-primary` in its `@theme`, so Tailwind emits nothing for
|
|
8
|
+
* `bg-primary`, `text-primary` or `border-primary/60`. Nothing fails: the class is simply
|
|
9
|
+
* absent from the built CSS. Read off Chromium in flix the day SearchInput shipped, its
|
|
10
|
+
* badge's background was `rgba(0, 0, 0, 0)`. The same vocabulary had been in the DataTable
|
|
11
|
+
* for weeks — the column checklist's CHECKED box had no fill, the Filter and Columns count
|
|
12
|
+
* badges no background, and SearchBox's "narrowed scope" highlight (whose own comment says
|
|
13
|
+
* "the whole point is that it cannot hide") was invisible. Five files, one gap.
|
|
14
|
+
*
|
|
15
|
+
* ── The rule ─────────────────────────────────────────────────────────────────
|
|
16
|
+
* For every colour-taking prefix (`bg-`, `text-`, `border-`, `ring-`, …) followed by a
|
|
17
|
+
* name that `theme.css` defines as a custom property, the `@theme` block must register
|
|
18
|
+
* `--<namespace>-<name>` for it. A name `theme.css` never defines (`text-sm`, `border-2`)
|
|
19
|
+
* is Tailwind's own and out of scope; a Tailwind PALETTE colour is `no-tailwind-palette`'s.
|
|
20
|
+
*/
|
|
21
|
+
import { describe, expect, test } from 'bun:test';
|
|
22
|
+
import { readdirSync, readFileSync, statSync } from 'node:fs';
|
|
23
|
+
import { join } from 'node:path';
|
|
24
|
+
import { RULES, setThemeCss } from '../scripts/guardrailsEnforce';
|
|
25
|
+
|
|
26
|
+
const ROOT = join(import.meta.dir, 'react');
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The utilities in `source` that name a defined-but-unregistered colour. One implementation:
|
|
30
|
+
* this is the guardrail rule `theme-colours-resolve`, which holds apps to the same check. With
|
|
31
|
+
* no app stylesheet it resolves against `theme.css` alone — exactly the belt's own situation.
|
|
32
|
+
*/
|
|
33
|
+
function unresolvedColours(source: string): string[] {
|
|
34
|
+
setThemeCss([]);
|
|
35
|
+
return RULES['theme-colours-resolve'].check('x.tsx', source).map((v) => v.snippet.split(' — ')[0] ?? '');
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function files(dir: string): string[] {
|
|
39
|
+
return readdirSync(dir).flatMap((name) => {
|
|
40
|
+
const path = join(dir, name);
|
|
41
|
+
if (statSync(path).isDirectory()) return files(path);
|
|
42
|
+
return /\.tsx?$/.test(name) && !/\.spec\.tsx?$/.test(name) ? [path] : [];
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
describe('every colour utility the belt uses resolves to a registered theme colour', () => {
|
|
47
|
+
test('the check sees the 2026-09-28 shape, and passes the canonical names', () => {
|
|
48
|
+
expect(unresolvedColours("'border-primary/60 bg-primary/10 text-primary-foreground'")).toEqual([
|
|
49
|
+
'border-primary/60',
|
|
50
|
+
'bg-primary/10',
|
|
51
|
+
'text-primary-foreground',
|
|
52
|
+
]);
|
|
53
|
+
expect(unresolvedColours("'bg-accent/15 text-accent-strong border-border text-caption text-sm'")).toEqual([]);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test('no component names one', () => {
|
|
57
|
+
const found = files(ROOT).flatMap((path) =>
|
|
58
|
+
unresolvedColours(readFileSync(path, 'utf8')).map((cls) => `${path.slice(ROOT.length + 1)}: ${cls}`),
|
|
59
|
+
);
|
|
60
|
+
expect(found).toEqual([]);
|
|
61
|
+
});
|
|
62
|
+
});
|