@nadicodeai/ui 0.20.0 → 0.21.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/AGENTS.md +2 -0
- package/dist/components/brand-icons/apple.d.ts +18 -0
- package/dist/components/brand-icons/apple.d.ts.map +1 -0
- package/dist/components/brand-icons/apple.js +22 -0
- package/dist/components/brand-icons/brand-icon.d.ts +22 -0
- package/dist/components/brand-icons/brand-icon.d.ts.map +1 -0
- package/dist/components/brand-icons/brand-icon.js +26 -0
- package/dist/components/brand-icons/linux.d.ts +18 -0
- package/dist/components/brand-icons/linux.d.ts.map +1 -0
- package/dist/components/brand-icons/linux.js +25 -0
- package/dist/components/brand-icons/windows.d.ts +18 -0
- package/dist/components/brand-icons/windows.d.ts.map +1 -0
- package/dist/components/brand-icons/windows.js +22 -0
- package/dist/components/brand-icons.d.ts +5 -0
- package/dist/components/brand-icons.d.ts.map +1 -0
- package/dist/components/brand-icons.js +10 -0
- package/dist/components/button.js +1 -1
- package/dist/components/card-marketing.js +2 -2
- package/dist/components/card.d.ts +4 -3
- package/dist/components/card.d.ts.map +1 -1
- package/dist/components/card.js +12 -2
- package/dist/components/chart-breakdown-table.js +1 -1
- package/dist/components/chart-bullet-bar.d.ts +18 -2
- package/dist/components/chart-bullet-bar.d.ts.map +1 -1
- package/dist/components/chart-bullet-bar.js +62 -9
- package/dist/components/chart-date-range-control.d.ts +11 -1
- package/dist/components/chart-date-range-control.d.ts.map +1 -1
- package/dist/components/chart-date-range-control.js +13 -3
- package/dist/components/chart-entity-colors.d.ts +7 -1
- package/dist/components/chart-entity-colors.d.ts.map +1 -1
- package/dist/components/chart-entity-colors.js +7 -1
- package/dist/components/chart-kpi-stat.d.ts.map +1 -1
- package/dist/components/chart-kpi-stat.js +1 -1
- package/dist/components/chart-time-series.d.ts.map +1 -1
- package/dist/components/chart-time-series.js +62 -4
- package/dist/components/chart.js +2 -2
- package/dist/components/code-editor-mockup.js +1 -1
- package/dist/components/nav-bar.js +1 -1
- package/dist/components/radio-group.d.ts +1 -1
- package/dist/components/radio-group.d.ts.map +1 -1
- package/dist/components/radio-group.js +2 -2
- package/dist/components/theme-mode-switcher.d.ts +10 -3
- package/dist/components/theme-mode-switcher.d.ts.map +1 -1
- package/dist/components/theme-mode-switcher.js +14 -7
- package/dist/eslint/index.js +91 -0
- package/dist/eslint/rules/jsx-class-utility.js +231 -0
- package/dist/eslint/rules/no-deprecated-zod-api.js +156 -0
- package/dist/eslint/rules/no-design-system-src-import.js +11 -0
- package/dist/eslint/rules/no-invalid-token-utility.js +46 -0
- package/dist/eslint/rules/no-native-visible-control.js +86 -0
- package/dist/eslint/rules/no-raw-color-utility.js +109 -0
- package/dist/eslint/rules/no-raw-focus-ring-width.js +30 -0
- package/dist/eslint/rules/no-raw-logo-import.js +41 -0
- package/dist/eslint/rules/no-shadcn-appearance-override.js +191 -0
- package/dist/eslint/rules/no-token-category-bypass.js +53 -0
- package/dist/eslint/rules/no-ui-src-import.js +10 -0
- package/dist/eslint/rules/no-unpinned-vercel-functions-import.js +100 -0
- package/dist/eslint/rules/src-import-boundary.js +207 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/docs/consuming-cross-repo.md +23 -0
- package/docs/contract.md +10 -0
- package/package.json +9 -3
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
|
|
3
|
+
import { tokenUtilityVisitors } from "./jsx-class-utility.js";
|
|
4
|
+
|
|
5
|
+
const require = createRequire(import.meta.url);
|
|
6
|
+
const borderRadius = require("@nadicodeai/design-system/tailwind").theme.extend.borderRadius;
|
|
7
|
+
const radiusNameByValue = new Map(
|
|
8
|
+
Object.entries(borderRadius).map(([name, value]) => [value, name]),
|
|
9
|
+
);
|
|
10
|
+
const ARBITRARY_RADIUS = /^(rounded(?:-(?:t|r|b|l|s|e|ss|se|ee|es|tl|tr|br|bl))?)-\[(.+)\]$/;
|
|
11
|
+
const CANONICAL_RADIUS_VARIABLE = /^var\(--(?:nc-rounded|radius)-([a-z0-9-]+)\)$/;
|
|
12
|
+
|
|
13
|
+
function canonicalRadiusReplacement(utility) {
|
|
14
|
+
const variantBoundary = utility.lastIndexOf(":") + 1;
|
|
15
|
+
const variants = utility.slice(0, variantBoundary);
|
|
16
|
+
const unqualified = utility.slice(variantBoundary);
|
|
17
|
+
const match = ARBITRARY_RADIUS.exec(unqualified);
|
|
18
|
+
if (!match) return undefined;
|
|
19
|
+
|
|
20
|
+
const [, prefix, rawValue] = match;
|
|
21
|
+
const value = rawValue.trim();
|
|
22
|
+
const variable = CANONICAL_RADIUS_VARIABLE.exec(value);
|
|
23
|
+
const token = variable?.[1] ?? radiusNameByValue.get(value);
|
|
24
|
+
if (!token || !(token in borderRadius)) return undefined;
|
|
25
|
+
|
|
26
|
+
return `${variants}${prefix}-${token}`;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export const noTokenCategoryBypass = {
|
|
30
|
+
meta: {
|
|
31
|
+
type: "problem",
|
|
32
|
+
docs: {
|
|
33
|
+
description:
|
|
34
|
+
"Disallow arbitrary radius values when the generated design system provides an exact utility",
|
|
35
|
+
},
|
|
36
|
+
schema: [],
|
|
37
|
+
messages: {
|
|
38
|
+
canonicalTokenUtility:
|
|
39
|
+
"Replace {{utility}} with the generated design-system utility {{replacement}}.",
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
create(context) {
|
|
43
|
+
return tokenUtilityVisitors(context, (node, utility) => {
|
|
44
|
+
const replacement = canonicalRadiusReplacement(utility);
|
|
45
|
+
if (!replacement) return;
|
|
46
|
+
context.report({
|
|
47
|
+
node,
|
|
48
|
+
messageId: "canonicalTokenUtility",
|
|
49
|
+
data: { replacement, utility },
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
},
|
|
53
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { bannedSourceRootMatcher, createSrcImportRule } from "./src-import-boundary.js";
|
|
2
|
+
|
|
3
|
+
/** @type {import('eslint').Rule.RuleModule} */
|
|
4
|
+
export const noUiSrcImport = createSrcImportRule({
|
|
5
|
+
description: "Disallow deep imports from @nadicodeai/ui/src/* in consumer apps",
|
|
6
|
+
bannedMessage: "Import @nadicodeai/ui through package exports only, not {{value}}.",
|
|
7
|
+
// The package sits at a repo-root dir literally named `@nadicodeai/ui/`, so
|
|
8
|
+
// relative paths carry the full `@nadicodeai/ui/src` marker too.
|
|
9
|
+
isBanned: bannedSourceRootMatcher("@nadicodeai/ui/src"),
|
|
10
|
+
});
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
const PACKAGE_NAME = "@vercel/functions";
|
|
2
|
+
|
|
3
|
+
// Third-party helpers stay behind owned, single-purpose capability seams. Pin
|
|
4
|
+
// the full workspace-relative suffix so a same-named file in another workspace
|
|
5
|
+
// cannot acquire a platform dependency by shadowing an allowed module.
|
|
6
|
+
const ALLOWED_IMPORTS = new Map([
|
|
7
|
+
["portal/src/lib/server/db.ts", new Set(["attachDatabasePool"])],
|
|
8
|
+
["portal/src/lib/server/deferred-work.ts", new Set(["waitUntil"])],
|
|
9
|
+
]);
|
|
10
|
+
|
|
11
|
+
function matchesPackage(value) {
|
|
12
|
+
return (
|
|
13
|
+
typeof value === "string" && (value === PACKAGE_NAME || value.startsWith(`${PACKAGE_NAME}/`))
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function allowedSymbolsFor(filename) {
|
|
18
|
+
const normalized = filename.replaceAll("\\", "/");
|
|
19
|
+
for (const [suffix, symbols] of ALLOWED_IMPORTS) {
|
|
20
|
+
if (normalized.endsWith(suffix)) {
|
|
21
|
+
return symbols;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function importedName(specifier) {
|
|
28
|
+
if (specifier.type !== "ImportSpecifier") {
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
return specifier.imported.type === "Identifier"
|
|
32
|
+
? specifier.imported.name
|
|
33
|
+
: specifier.imported.value;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** @type {import('eslint').Rule.RuleModule} */
|
|
37
|
+
export const noUnpinnedVercelFunctionsImport = {
|
|
38
|
+
meta: {
|
|
39
|
+
type: "problem",
|
|
40
|
+
docs: {
|
|
41
|
+
description: "Confine @vercel/functions imports to pinned edge modules and symbols",
|
|
42
|
+
},
|
|
43
|
+
messages: {
|
|
44
|
+
banned:
|
|
45
|
+
"@vercel/functions duck-types its inputs and ipAddress() crashed production once (docs/solutions/portal-device-authorize-vercel-headers-crash.md). Its use is pinned per module and per symbol; amend the allowlist deliberately or keep the dependency out (found {{value}}).",
|
|
46
|
+
},
|
|
47
|
+
schema: [],
|
|
48
|
+
},
|
|
49
|
+
create(context) {
|
|
50
|
+
const allowedSymbols = allowedSymbolsFor(context.filename);
|
|
51
|
+
|
|
52
|
+
function report(node, value) {
|
|
53
|
+
context.report({
|
|
54
|
+
node,
|
|
55
|
+
messageId: "banned",
|
|
56
|
+
data: { value },
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
ImportDeclaration(node) {
|
|
62
|
+
if (!matchesPackage(node.source.value)) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const importsOnlyPinnedSymbols =
|
|
67
|
+
allowedSymbols &&
|
|
68
|
+
node.specifiers.length > 0 &&
|
|
69
|
+
node.specifiers.every((specifier) => {
|
|
70
|
+
const name = importedName(specifier);
|
|
71
|
+
return name !== undefined && allowedSymbols.has(name);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
if (!importsOnlyPinnedSymbols) {
|
|
75
|
+
report(node, node.source.value);
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
// Everything except a static import is judged by the quoted reference
|
|
79
|
+
// itself, whatever expression carries it: dynamic import(), require in
|
|
80
|
+
// any callee shape (bare, module.require, createRequire), export ...
|
|
81
|
+
// from, or a bare string that smuggles the specifier to a loader. Only
|
|
82
|
+
// static named imports can prove which symbols they bind, so only they
|
|
83
|
+
// get the allowlist path above.
|
|
84
|
+
Literal(node) {
|
|
85
|
+
if (!matchesPackage(node.value)) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
if (node.parent.type === "ImportDeclaration") {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
report(node, node.value);
|
|
92
|
+
},
|
|
93
|
+
TemplateLiteral(node) {
|
|
94
|
+
if (node.expressions.length === 0 && matchesPackage(node.quasis[0]?.value.cooked)) {
|
|
95
|
+
report(node, node.quasis[0].value.cooked);
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
},
|
|
100
|
+
};
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared machinery for the source-import boundary rules
|
|
3
|
+
* (`no-ui-src-import`, `no-design-system-src-import`). Both resolve a module
|
|
4
|
+
* specifier — static string, template/concatenation, const-propagated
|
|
5
|
+
* identifier, TS type assertion — and report when a banned package source
|
|
6
|
+
* path appears in it, across static imports, dynamic `import()`,
|
|
7
|
+
* `require()`/`module.require()`, and TypeScript `import type`/`import =`.
|
|
8
|
+
* Factoring it here keeps the two rules from drifting apart.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Match a banned source root anywhere in the specifier, at a path boundary:
|
|
13
|
+
* the root followed by `/` (a deep import) or at the end of the string (the
|
|
14
|
+
* root itself). Substring-anywhere so relative paths (`../../@scope/pkg/src/x`),
|
|
15
|
+
* node_modules paths, and loader-prefixed specifiers (`!!raw-loader!…/src/x`)
|
|
16
|
+
* are all caught.
|
|
17
|
+
* @param {string} root
|
|
18
|
+
* @returns {(value: string) => boolean}
|
|
19
|
+
*/
|
|
20
|
+
export function bannedSourceRootMatcher(root) {
|
|
21
|
+
return (value) => {
|
|
22
|
+
const index = value.indexOf(root);
|
|
23
|
+
if (index === -1) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
const nextChar = value[index + root.length];
|
|
27
|
+
return nextChar === undefined || nextChar === "/";
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @param {object} options
|
|
33
|
+
* @param {string} options.description
|
|
34
|
+
* @param {string} options.bannedMessage
|
|
35
|
+
* @param {(value: string) => boolean} options.isBanned
|
|
36
|
+
* @returns {import('eslint').Rule.RuleModule}
|
|
37
|
+
*/
|
|
38
|
+
export function createSrcImportRule({ description, bannedMessage, isBanned }) {
|
|
39
|
+
return {
|
|
40
|
+
meta: {
|
|
41
|
+
type: "problem",
|
|
42
|
+
docs: { description },
|
|
43
|
+
messages: { banned: bannedMessage },
|
|
44
|
+
schema: [],
|
|
45
|
+
},
|
|
46
|
+
create(context) {
|
|
47
|
+
const sourceCode = context.sourceCode;
|
|
48
|
+
|
|
49
|
+
function findVariable(node, name) {
|
|
50
|
+
for (let scope = sourceCode.getScope(node); scope; scope = scope.upper) {
|
|
51
|
+
const variable = scope.set.get(name);
|
|
52
|
+
if (variable) {
|
|
53
|
+
return variable;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return undefined;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function isUnshadowed(node, name) {
|
|
60
|
+
const variable = findVariable(node, name);
|
|
61
|
+
return !variable || variable.defs.length === 0;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// `const require = createRequire(import.meta.url)` is the only real
|
|
65
|
+
// require in this all-ESM repo, so it must not be treated as a shadow.
|
|
66
|
+
function isCreateRequireInit(init) {
|
|
67
|
+
if (init?.type !== "CallExpression") {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
const callee = init.callee;
|
|
71
|
+
if (callee.type === "Identifier") {
|
|
72
|
+
return callee.name === "createRequire";
|
|
73
|
+
}
|
|
74
|
+
return (
|
|
75
|
+
callee.type === "MemberExpression" &&
|
|
76
|
+
!callee.computed &&
|
|
77
|
+
callee.property.type === "Identifier" &&
|
|
78
|
+
callee.property.name === "createRequire"
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function isRequire(node, name) {
|
|
83
|
+
const variable = findVariable(node, name);
|
|
84
|
+
if (!variable || variable.defs.length === 0) {
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
if (variable.defs.length === 1) {
|
|
88
|
+
const definition = variable.defs[0];
|
|
89
|
+
if (
|
|
90
|
+
definition.type === "Variable" &&
|
|
91
|
+
definition.parent?.kind === "const" &&
|
|
92
|
+
definition.node.id?.type === "Identifier" &&
|
|
93
|
+
isCreateRequireInit(definition.node.init)
|
|
94
|
+
) {
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function staticSpecifier(node, seenVariables = new Set()) {
|
|
102
|
+
if (node?.type === "Literal" && typeof node.value === "string") {
|
|
103
|
+
return node.value;
|
|
104
|
+
}
|
|
105
|
+
if (node?.type === "TemplateLiteral") {
|
|
106
|
+
let value = node.quasis[0]?.value.cooked ?? "";
|
|
107
|
+
for (let index = 0; index < node.expressions.length; index += 1) {
|
|
108
|
+
const expressionValue = staticSpecifier(node.expressions[index], seenVariables);
|
|
109
|
+
const followingText = node.quasis[index + 1]?.value.cooked;
|
|
110
|
+
if (expressionValue === undefined || followingText === undefined) {
|
|
111
|
+
return undefined;
|
|
112
|
+
}
|
|
113
|
+
value += expressionValue + followingText;
|
|
114
|
+
}
|
|
115
|
+
return value;
|
|
116
|
+
}
|
|
117
|
+
if (node?.type === "BinaryExpression" && node.operator === "+") {
|
|
118
|
+
const left = staticSpecifier(node.left, seenVariables);
|
|
119
|
+
const right = staticSpecifier(node.right, seenVariables);
|
|
120
|
+
return left === undefined || right === undefined ? undefined : left + right;
|
|
121
|
+
}
|
|
122
|
+
if (node?.type === "Identifier") {
|
|
123
|
+
const variable = findVariable(node, node.name);
|
|
124
|
+
const definition = variable?.defs.length === 1 ? variable.defs[0] : undefined;
|
|
125
|
+
if (
|
|
126
|
+
!variable ||
|
|
127
|
+
seenVariables.has(variable) ||
|
|
128
|
+
definition?.type !== "Variable" ||
|
|
129
|
+
definition.parent?.kind !== "const" ||
|
|
130
|
+
definition.node.id?.type !== "Identifier" ||
|
|
131
|
+
!definition.node.init
|
|
132
|
+
) {
|
|
133
|
+
return undefined;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const nextSeenVariables = new Set(seenVariables);
|
|
137
|
+
nextSeenVariables.add(variable);
|
|
138
|
+
return staticSpecifier(definition.node.init, nextSeenVariables);
|
|
139
|
+
}
|
|
140
|
+
if (
|
|
141
|
+
node?.type === "TSAsExpression" ||
|
|
142
|
+
node?.type === "TSSatisfiesExpression" ||
|
|
143
|
+
node?.type === "TSNonNullExpression"
|
|
144
|
+
) {
|
|
145
|
+
return staticSpecifier(node.expression, seenVariables);
|
|
146
|
+
}
|
|
147
|
+
return undefined;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function checkValue(node, value) {
|
|
151
|
+
if (typeof value === "string" && isBanned(value)) {
|
|
152
|
+
context.report({
|
|
153
|
+
node,
|
|
154
|
+
messageId: "banned",
|
|
155
|
+
data: { value },
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function check(node) {
|
|
161
|
+
checkValue(node, staticSpecifier(node.source));
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function memberPropertyName(node) {
|
|
165
|
+
if (!node.computed && node.property.type === "Identifier") {
|
|
166
|
+
return node.property.name;
|
|
167
|
+
}
|
|
168
|
+
return staticSpecifier(node.property);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function checkRequire(node) {
|
|
172
|
+
const isBareRequire =
|
|
173
|
+
node.callee.type === "Identifier" &&
|
|
174
|
+
node.callee.name === "require" &&
|
|
175
|
+
isRequire(node.callee, "require");
|
|
176
|
+
const isModuleRequire =
|
|
177
|
+
node.callee.type === "MemberExpression" &&
|
|
178
|
+
node.callee.object.type === "Identifier" &&
|
|
179
|
+
node.callee.object.name === "module" &&
|
|
180
|
+
isUnshadowed(node.callee.object, "module") &&
|
|
181
|
+
memberPropertyName(node.callee) === "require";
|
|
182
|
+
|
|
183
|
+
if (isBareRequire || isModuleRequire) {
|
|
184
|
+
checkValue(node, staticSpecifier(node.arguments[0]));
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function checkTypeScriptImportEquals(node) {
|
|
189
|
+
if (node.moduleReference.type === "TSExternalModuleReference") {
|
|
190
|
+
checkValue(node, staticSpecifier(node.moduleReference.expression));
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return {
|
|
195
|
+
ImportDeclaration: check,
|
|
196
|
+
ImportExpression: check,
|
|
197
|
+
CallExpression: checkRequire,
|
|
198
|
+
// `export { X } from "…/src/…"` and `export * from …` are consumer deep
|
|
199
|
+
// imports too; a source-less `export {}` has no node.source.
|
|
200
|
+
ExportNamedDeclaration: check,
|
|
201
|
+
ExportAllDeclaration: check,
|
|
202
|
+
TSImportType: check,
|
|
203
|
+
TSImportEqualsDeclaration: checkTypeScriptImportEquals,
|
|
204
|
+
};
|
|
205
|
+
},
|
|
206
|
+
};
|
|
207
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -19,6 +19,7 @@ export * from "./components/benefits-bento";
|
|
|
19
19
|
export * from "./components/bento";
|
|
20
20
|
export * from "./components/brand";
|
|
21
21
|
export * from "./components/brand-field";
|
|
22
|
+
export * from "./components/brand-icons";
|
|
22
23
|
export * from "./components/breadcrumb";
|
|
23
24
|
export * from "./components/bubble";
|
|
24
25
|
export * from "./components/button";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yBAAyB,CAAC;AACxC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kCAAkC,CAAC;AACjD,cAAc,oBAAoB,CAAC;AACnC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yBAAyB,CAAC;AACxC,cAAc,iCAAiC,CAAC;AAChD,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,uBAAuB,CAAC;AACtC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oCAAoC,CAAC;AACnD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,uCAAuC,CAAC;AACtD,cAAc,0BAA0B,CAAC;AACzC,cAAc,kCAAkC,CAAC;AACjD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,uBAAuB,CAAC;AACtC,cAAc,iCAAiC,CAAC;AAChD,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC;AACvC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,qBAAqB,CAAC;AACpC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,oBAAoB,CAAC;AACnC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,wBAAwB,CAAC;AACvC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,oBAAoB,CAAC;AACnC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,mBAAmB,CAAC;AAClC,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,sBAAsB,CAAC;AACrC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,mCAAmC,CAAC;AAClD,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,oBAAoB,CAAC;AACnC,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uBAAuB,CAAC;AACtC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,kCAAkC,CAAC;AACjD,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iCAAiC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -19,6 +19,7 @@ export * from "./components/benefits-bento.js";
|
|
|
19
19
|
export * from "./components/bento.js";
|
|
20
20
|
export * from "./components/brand.js";
|
|
21
21
|
export * from "./components/brand-field.js";
|
|
22
|
+
export * from "./components/brand-icons.js";
|
|
22
23
|
export * from "./components/breadcrumb.js";
|
|
23
24
|
export * from "./components/bubble.js";
|
|
24
25
|
export * from "./components/button.js";
|
|
@@ -51,6 +51,29 @@ winner. Import files under `@nadicodeai/design-system/assets/fonts/*` only when
|
|
|
51
51
|
the consumer wants the faces without the CSS module; that is one of the
|
|
52
52
|
intentional direct-API cases described above.
|
|
53
53
|
|
|
54
|
+
## Strict ESLint interface
|
|
55
|
+
|
|
56
|
+
The package exports the same design-system rules used by this repository. Add
|
|
57
|
+
the flat config after the consumer's framework and TypeScript configs:
|
|
58
|
+
|
|
59
|
+
```js
|
|
60
|
+
import nadicodeai from "@nadicodeai/ui/eslint";
|
|
61
|
+
|
|
62
|
+
export default [
|
|
63
|
+
// Framework, parser, and TypeScript configs first.
|
|
64
|
+
...nadicodeai.configs["flat/strict"],
|
|
65
|
+
];
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Every rule in this config is an error. The config rejects generated `nc-*`
|
|
69
|
+
utilities that do not exist in the installed design-system release, arbitrary
|
|
70
|
+
radius values that exactly duplicate a generated token, source deep imports,
|
|
71
|
+
raw design values, native visible controls, and appearance overrides on shared
|
|
72
|
+
UI primitives. An arbitrary radius remains valid when no generated radius has
|
|
73
|
+
the same value. Consumers may compose domain-specific components from the
|
|
74
|
+
public UI package; the rules govern package boundaries and design values, not
|
|
75
|
+
the shape of a consumer's JSX tree.
|
|
76
|
+
|
|
54
77
|
## NadicodeAI logo
|
|
55
78
|
|
|
56
79
|
React surfaces that need both the mark and readable company name use the
|
package/docs/contract.md
CHANGED
|
@@ -26,6 +26,7 @@ Agent work surfaces (chat, composer, tool approval, artifacts, threads, diffs, t
|
|
|
26
26
|
- **Auth routes are consumer-owned shadcn block work.** Login, signup, OTP, two-factor, magic-link, and provider-button flows start from the selected shadcn block/example in the consuming app, with app-owned Better Auth behavior. Do not ship generic auth, signup, OTP, federated-login, or provider abstractions from this package unless a later explicit boundary decision replaces the selected shadcn block.
|
|
27
27
|
- **Reusable sections and compositions live here after proof.** Bento grids, media mounts, demo surfaces, page frames, section intros, CTA bands, proof slots, benefits grids, generic shells, and homepage/use-case sections belong in `@nadicodeai/ui` when a second concrete consumer, a plan-approved shared component, or a named validation slice proves the package boundary. Website, portal, and sibling Nadia routes pass data and media children into existing compositions instead of rebuilding layout locally.
|
|
28
28
|
- **Brand renderers live here for React consumers.** Logo geometry, asset generation, and usage semantics are owned by [`design-system/DESIGN.md`, "Brand media authority"](../../../design-system/DESIGN.md#brand-media-authority). `BrandLockup` supplies the approved horizontal lockup. `BrandMark` serves tight spaces and `BrandWordmark` serves placements where the name must read by itself. All three render the package's public neutral geometry seam with React-scoped SVG ids, dynamic theme paint, and accessible names. Consuming routes use these adapters; they never import raw logo assets, draw brand SVG inline, mask or recolor assets, or create another lockup rule.
|
|
29
|
+
- **Third-party brand marks are generated, never hand-drawn and never hand-edited.** Other companies' marks live in `@nadicodeai/ui/src/components/brand-icons/`, emitted from an explicit allow-list by `@nadicodeai/ui/scripts/build-brand-icons.mjs` and exported through the `@nadicodeai/ui/components/brand-icons` subpath. They are identity images, not UI icons: a brand mark is exempt from the currentColor stroke system and from the raw-literal rule, it never stands in for a UI icon, and a UI icon never stands in for a brand. Marks drawn as one silhouette are stripped to `currentColor` by the generator; every other mark keeps its official colors verbatim. To add a brand, edit the generator's allow-list and run `npm run generate:brand-icons -w @nadicodeai/ui`; hand edits to the generated directory are lost and `@nadicodeai/ui/tests/guards/brand-icons-codegen.test.ts` fails on them. Use is nominative only — naming a platform, an integration, or a provider — never adjacent to endorsement or partnership wording. The full decision, including the licensing and trademark posture, is [ADR 0042](../../../docs/adr/0042-third-party-brand-marks-are-generated-identity-images.md).
|
|
29
30
|
- **No fake proof APIs.** Components may support future testimonials, logos, stats, and proof slots, but they must render nothing public when the proof is absent. Do not ship placeholder customer names, metrics, or logos.
|
|
30
31
|
|
|
31
32
|
## Accessibility Invariant
|
|
@@ -43,3 +44,12 @@ Consumers own routing, auth, app data, server actions, runtime adapters, permiss
|
|
|
43
44
|
App source composes layout, data, behavior, and semantic content around package components. It does not restyle an imported component root: appearance changes enter through the component's typed variant or are added to the owning package component. App `className` values on package components are limited to structural layout and sizing. App source uses semantic roles such as `bg-background` and `text-foreground`; raw Tailwind palette colors and canonical `nc-*` color utilities stay behind package-owned primitives such as `BrandField`. Visible controls come from `@nadicodeai/ui`, while hidden inputs remain valid form transport. The root ESLint rules `nadicodeai/no-shadcn-appearance-override`, `nadicodeai/no-raw-color-utility`, and `nadicodeai/no-native-visible-control` enforce this boundary.
|
|
44
45
|
|
|
45
46
|
When this package is read from an installed npm package, follow the [consumer setup guide](consuming-cross-repo.md) for setup and public import paths. The styling invariant above remains the authority for component implementation.
|
|
47
|
+
|
|
48
|
+
The public strict ESLint config enforces only properties that can be decided
|
|
49
|
+
from one source file and the installed generated tokens. It does not infer
|
|
50
|
+
that two JSX trees represent the same product pattern. Repeated patterns stay
|
|
51
|
+
governed by a named owning component, typed variants or slots, and explicit
|
|
52
|
+
package or Portal-kit imports. A new repeated pattern is consolidated at its
|
|
53
|
+
owner and pinned with a focused source or rendering test; generic JSX
|
|
54
|
+
similarity warnings are outside this contract because they cannot distinguish
|
|
55
|
+
valid domain composition from a fork without false positives.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nadicodeai/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
"import": "./dist/index.js"
|
|
15
15
|
},
|
|
16
16
|
"./globals.css": "./dist/styles/globals.css",
|
|
17
|
+
"./eslint": "./dist/eslint/index.js",
|
|
17
18
|
"./ai-elements": {
|
|
18
19
|
"types": "./dist/ai-elements.d.ts",
|
|
19
20
|
"import": "./dist/ai-elements.js"
|
|
@@ -53,8 +54,9 @@
|
|
|
53
54
|
],
|
|
54
55
|
"scripts": {
|
|
55
56
|
"dev": "node scripts/dev-build.mjs --watch",
|
|
56
|
-
"build": "rm -rf dist && tsc -p tsconfig.build.json && node scripts/fix-dist-imports.mjs && node scripts/build-styles.mjs",
|
|
57
|
+
"build": "rm -rf dist && tsc -p tsconfig.build.json && node scripts/fix-dist-imports.mjs && node scripts/build-styles.mjs && node scripts/build-eslint.mjs",
|
|
57
58
|
"build:fast": "node scripts/dev-build.mjs",
|
|
59
|
+
"generate:brand-icons": "node scripts/build-brand-icons.mjs",
|
|
58
60
|
"prepack": "npm run build",
|
|
59
61
|
"lint": "eslint --max-warnings=0",
|
|
60
62
|
"typecheck": "tsc --noEmit",
|
|
@@ -63,7 +65,7 @@
|
|
|
63
65
|
},
|
|
64
66
|
"dependencies": {
|
|
65
67
|
"@base-ui/react": "^1.6.0",
|
|
66
|
-
"@nadicodeai/design-system": "0.
|
|
68
|
+
"@nadicodeai/design-system": "0.21.0",
|
|
67
69
|
"@rive-app/react-webgl2": "^4.29.1",
|
|
68
70
|
"@streamdown/cjk": "^1.0.3",
|
|
69
71
|
"@streamdown/code": "^1.1.1",
|
|
@@ -102,6 +104,10 @@
|
|
|
102
104
|
"tailwindcss": "^4.3.1"
|
|
103
105
|
},
|
|
104
106
|
"devDependencies": {
|
|
107
|
+
"@iconify-json/logos": "^1.2.11",
|
|
108
|
+
"@iconify/utils": "^3.1.4",
|
|
109
|
+
"@stryker-mutator/core": "9.6.1",
|
|
110
|
+
"@stryker-mutator/vitest-runner": "9.6.1",
|
|
105
111
|
"@tailwindcss/postcss": "^4.3.1",
|
|
106
112
|
"@testing-library/react": "^16.3.2",
|
|
107
113
|
"@types/react": "^19",
|