@ngcorex/css 0.1.5 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -1
- package/dist/config/schema.d.ts +29 -0
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/constraints/radius.d.ts +6 -0
- package/dist/constraints/radius.d.ts.map +1 -0
- package/dist/constraints/radius.js +33 -0
- package/dist/constraints/run-constraints.d.ts.map +1 -1
- package/dist/constraints/run-constraints.js +16 -0
- package/dist/constraints/shadows.d.ts +6 -0
- package/dist/constraints/shadows.d.ts.map +1 -0
- package/dist/constraints/shadows.js +118 -0
- package/dist/constraints/typography.d.ts +11 -0
- package/dist/constraints/typography.d.ts.map +1 -0
- package/dist/constraints/typography.js +84 -0
- package/dist/constraints/z-index.d.ts +6 -0
- package/dist/constraints/z-index.d.ts.map +1 -0
- package/dist/constraints/z-index.js +25 -0
- package/dist/engine/build-css.d.ts.map +1 -1
- package/dist/engine/build-css.js +25 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @ngcorex/css
|
|
2
2
|
|
|
3
|
-
   
|
|
3
|
+
    
|
|
4
4
|
|
|
5
5
|
Core engine for **ngCorex**.
|
|
6
6
|
|
|
@@ -19,6 +19,27 @@ It is intended to be used via the ngCorex CLI, not directly in applications.
|
|
|
19
19
|
npm install @ngcorex/css
|
|
20
20
|
````
|
|
21
21
|
|
|
22
|
+
## Supported Token Categories
|
|
23
|
+
|
|
24
|
+
ngCorex supports the following design token categories:
|
|
25
|
+
|
|
26
|
+
| Category | Description | Example Values |
|
|
27
|
+
| ---------- | ------------- | ---------------- |
|
|
28
|
+
| `spacing` | Spacing scale for margins, padding, gaps | `"4px"`, `"1rem"`, `"0.5em"` |
|
|
29
|
+
| `colors` | Color palette with nested shades | `"#f3f4f6"`, `"rgb(37, 99, 235)"` |
|
|
30
|
+
| `radius` | Border radius values | `"4px"`, `"8px"`, `"16px"`, `"full"` |
|
|
31
|
+
| `zIndex` | Z-index layer values | `"1000"`, `"2000"`, `"3000"` |
|
|
32
|
+
| `typography` | Font properties (fontSize, fontWeight, lineHeight) | See below |
|
|
33
|
+
| `shadows` | Box shadow values | `"0 1px 2px 0 rgba(0,0,0,0.05)"` |
|
|
34
|
+
|
|
35
|
+
### Typography Sub-categories
|
|
36
|
+
|
|
37
|
+
| Sub-category | Description | Example Values |
|
|
38
|
+
| ------------- | ------------- | ---------------- |
|
|
39
|
+
| `fontSize` | Font size values | `"0.75rem"`, `"16px"`, `"1.25em"` |
|
|
40
|
+
| `fontWeight` | Font weight values | `"400"`, `"500"`, `"bold"`, `"700"` |
|
|
41
|
+
| `lineHeight` | Line height values | `"1.25"`, `"1.5"`, `"1.75"` |
|
|
42
|
+
|
|
22
43
|
## Token Source
|
|
23
44
|
|
|
24
45
|
Tokens can be provided either inline via configuration or from an external `tokens.json` file when using the ngCorex CLI.
|
package/dist/config/schema.d.ts
CHANGED
|
@@ -12,16 +12,45 @@ export interface ConstraintConfig {
|
|
|
12
12
|
format?: ConstraintLevel;
|
|
13
13
|
shadeKey?: ConstraintLevel;
|
|
14
14
|
};
|
|
15
|
+
radius?: {
|
|
16
|
+
unit?: ConstraintLevel;
|
|
17
|
+
format?: ConstraintLevel;
|
|
18
|
+
type?: ConstraintLevel;
|
|
19
|
+
};
|
|
20
|
+
zIndex?: {
|
|
21
|
+
format?: ConstraintLevel;
|
|
22
|
+
type?: ConstraintLevel;
|
|
23
|
+
};
|
|
24
|
+
typography?: {
|
|
25
|
+
fontSize?: {
|
|
26
|
+
format?: ConstraintLevel;
|
|
27
|
+
type?: ConstraintLevel;
|
|
28
|
+
};
|
|
29
|
+
fontWeight?: {
|
|
30
|
+
format?: ConstraintLevel;
|
|
31
|
+
type?: ConstraintLevel;
|
|
32
|
+
};
|
|
33
|
+
lineHeight?: {
|
|
34
|
+
format?: ConstraintLevel;
|
|
35
|
+
type?: ConstraintLevel;
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
shadows?: {
|
|
39
|
+
format?: ConstraintLevel;
|
|
40
|
+
type?: ConstraintLevel;
|
|
41
|
+
};
|
|
15
42
|
}
|
|
16
43
|
export interface TokensConfig {
|
|
17
44
|
spacing?: TokenScale;
|
|
18
45
|
colors?: NestedTokenScale;
|
|
19
46
|
radius?: TokenScale;
|
|
47
|
+
zIndex?: TokenScale;
|
|
20
48
|
typography?: {
|
|
21
49
|
fontSize?: TokenScale;
|
|
22
50
|
fontWeight?: TokenScale;
|
|
23
51
|
lineHeight?: TokenScale;
|
|
24
52
|
};
|
|
53
|
+
shadows?: TokenScale;
|
|
25
54
|
}
|
|
26
55
|
export interface UtilitiesConfig {
|
|
27
56
|
spacing?: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,SAAS,GAAG,KAAK,CAAC;AAE1D,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,EAAE;QACR,IAAI,CAAC,EAAE,eAAe,CAAC;QACvB,MAAM,CAAC,EAAE,eAAe,CAAC;QACzB,IAAI,CAAC,EAAE,eAAe,CAAC;KACxB,CAAC;IACF,MAAM,CAAC,EAAE;QACP,IAAI,CAAC,EAAE,eAAe,CAAC;QACvB,MAAM,CAAC,EAAE,eAAe,CAAC;QACzB,QAAQ,CAAC,EAAE,eAAe,CAAC;KAC5B,CAAC;CACH;AAGD,MAAM,WAAW,YAAY;IACzB,OAAO,CAAC,EAAE,UAAU,CAAC;IACrB,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,UAAU,CAAC,EAAE;QACT,QAAQ,CAAC,EAAE,UAAU,CAAC;QACtB,UAAU,CAAC,EAAE,UAAU,CAAC;QACxB,UAAU,CAAC,EAAE,UAAU,CAAC;KAC3B,CAAC;
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ConstraintConfig } from '../config/schema.js';
|
|
2
|
+
/**
|
|
3
|
+
* Validate border radius token constraints
|
|
4
|
+
*/
|
|
5
|
+
export declare function validateRadiusConstraints(radius: Record<string, string>, config?: ConstraintConfig['radius']): void;
|
|
6
|
+
//# sourceMappingURL=radius.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"radius.d.ts","sourceRoot":"","sources":["../../src/constraints/radius.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAE5D;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC9B,MAAM,CAAC,EAAE,gBAAgB,CAAC,QAAQ,CAAC,GAClC,IAAI,CAqCN"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { constraintViolation } from './constraint-error.js';
|
|
2
|
+
import { resolveConstraintLevel } from './resolve-level.js';
|
|
3
|
+
/**
|
|
4
|
+
* Validate border radius token constraints
|
|
5
|
+
*/
|
|
6
|
+
export function validateRadiusConstraints(radius, config) {
|
|
7
|
+
for (const key in radius) {
|
|
8
|
+
const value = radius[key];
|
|
9
|
+
if (typeof value !== 'string') {
|
|
10
|
+
constraintViolation(resolveConstraintLevel(config?.type, 'error'), 'radius.type', `Token radius.${key} is not a string.`, `Change radius.${key} to a string value like "4px" or "0.5rem".`);
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
if (isUnitlessNumber(value)) {
|
|
14
|
+
radius[key] = `${value}px`;
|
|
15
|
+
constraintViolation(resolveConstraintLevel(config?.unit, 'warning'), 'radius.unit', `Token radius.${key} had no unit. Defaulted to "${radius[key]}".`, `Explicitly add a unit (e.g. "px", "rem", "em", "%") to radius.${key}.`);
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
if (isValidRadiusValue(value)) {
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
constraintViolation(resolveConstraintLevel(config?.format, 'error'), 'radius.format', `Token radius.${key} has invalid value "${value}".`, `Use a numeric value with a unit (px, rem, em, %) or the "full" keyword.`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function isUnitlessNumber(value) {
|
|
25
|
+
return /^-?\d*\.?\d+$/.test(value);
|
|
26
|
+
}
|
|
27
|
+
function isValidRadiusValue(value) {
|
|
28
|
+
// Allow units: px, rem, em, %
|
|
29
|
+
// Also allow special values like 'full'
|
|
30
|
+
const unitPattern = /^\d*\.?\d+(px|rem|em|%)$/;
|
|
31
|
+
const specialValues = /^(full|none|inherit|initial|revert|unset)$/;
|
|
32
|
+
return unitPattern.test(value) || specialValues.test(value);
|
|
33
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-constraints.d.ts","sourceRoot":"","sources":["../../src/constraints/run-constraints.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAoB,aAAa,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"run-constraints.d.ts","sourceRoot":"","sources":["../../src/constraints/run-constraints.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAoB,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAQ3E,wBAAgB,cAAc,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CA6B1D"}
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { validateSpacingConstraints } from './spacing.js';
|
|
2
2
|
import { validateColorConstraints } from './colors.js';
|
|
3
|
+
import { validateRadiusConstraints } from './radius.js';
|
|
4
|
+
import { validateZIndexConstraints } from './z-index.js';
|
|
5
|
+
import { validateTypographyConstraints } from './typography.js';
|
|
6
|
+
import { validateShadowConstraints } from './shadows.js';
|
|
3
7
|
export function runConstraints(config) {
|
|
4
8
|
const tokens = config.tokens;
|
|
5
9
|
const rules = config.constraints;
|
|
@@ -11,4 +15,16 @@ export function runConstraints(config) {
|
|
|
11
15
|
if (tokens.colors) {
|
|
12
16
|
validateColorConstraints(tokens.colors, rules?.colors);
|
|
13
17
|
}
|
|
18
|
+
if (tokens.radius) {
|
|
19
|
+
validateRadiusConstraints(tokens.radius, rules?.radius);
|
|
20
|
+
}
|
|
21
|
+
if (tokens.zIndex) {
|
|
22
|
+
validateZIndexConstraints(tokens.zIndex, rules?.zIndex);
|
|
23
|
+
}
|
|
24
|
+
if (tokens.typography) {
|
|
25
|
+
validateTypographyConstraints(tokens.typography, rules?.typography);
|
|
26
|
+
}
|
|
27
|
+
if (tokens.shadows) {
|
|
28
|
+
validateShadowConstraints(tokens.shadows, rules?.shadows);
|
|
29
|
+
}
|
|
14
30
|
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ConstraintConfig } from '../config/schema.js';
|
|
2
|
+
/**
|
|
3
|
+
* Validate shadow token constraints
|
|
4
|
+
*/
|
|
5
|
+
export declare function validateShadowConstraints(shadows: Record<string, string>, config?: ConstraintConfig['shadows']): void;
|
|
6
|
+
//# sourceMappingURL=shadows.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shadows.d.ts","sourceRoot":"","sources":["../../src/constraints/shadows.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAE5D;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,MAAM,CAAC,EAAE,gBAAgB,CAAC,SAAS,CAAC,GACnC,IAAI,CAyBN"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { constraintViolation } from './constraint-error.js';
|
|
2
|
+
import { resolveConstraintLevel } from './resolve-level.js';
|
|
3
|
+
/**
|
|
4
|
+
* Validate shadow token constraints
|
|
5
|
+
*/
|
|
6
|
+
export function validateShadowConstraints(shadows, config) {
|
|
7
|
+
for (const key in shadows) {
|
|
8
|
+
const value = shadows[key];
|
|
9
|
+
if (typeof value !== 'string') {
|
|
10
|
+
constraintViolation(resolveConstraintLevel(config?.type, 'error'), 'shadows.type', `Token shadows.${key} is not a string.`, `Change shadows.${key} to a string value like "0 1px 3px 0 rgba(0,0,0,0.1)".`);
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
if (isValidShadowValue(value)) {
|
|
14
|
+
continue;
|
|
15
|
+
}
|
|
16
|
+
constraintViolation(resolveConstraintLevel(config?.format, 'error'), 'shadows.format', `Token shadows.${key} has invalid value "${value}".`, `Use a valid box-shadow syntax: "offset-x offset-y blur-radius spread-radius color".`);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Validate box-shadow syntax
|
|
21
|
+
* Format: offset-x offset-y blur-radius spread-radius color
|
|
22
|
+
* Examples:
|
|
23
|
+
* - "0 1px 3px 0 rgba(0,0,0,0.1)"
|
|
24
|
+
* - "0 4px 6px -1px rgba(0,0,0,0.1)"
|
|
25
|
+
* - "0 0 0 1px rgba(0,0,0,0.1)"
|
|
26
|
+
* - "none"
|
|
27
|
+
* - "inherit"
|
|
28
|
+
*/
|
|
29
|
+
function isValidShadowValue(value) {
|
|
30
|
+
const specialValues = /^(none|inherit|initial|revert|unset)$/;
|
|
31
|
+
if (specialValues.test(value)) {
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
function splitShadowList(value) {
|
|
35
|
+
const result = [];
|
|
36
|
+
let current = '';
|
|
37
|
+
let depth = 0;
|
|
38
|
+
for (const char of value) {
|
|
39
|
+
if (char === '(')
|
|
40
|
+
depth++;
|
|
41
|
+
if (char === ')')
|
|
42
|
+
depth--;
|
|
43
|
+
if (char === ',' && depth === 0) {
|
|
44
|
+
result.push(current.trim());
|
|
45
|
+
current = '';
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
current += char;
|
|
49
|
+
}
|
|
50
|
+
if (current.trim()) {
|
|
51
|
+
result.push(current.trim());
|
|
52
|
+
}
|
|
53
|
+
return result;
|
|
54
|
+
}
|
|
55
|
+
const shadowParts = splitShadowList(value);
|
|
56
|
+
for (const shadow of shadowParts) {
|
|
57
|
+
if (!isValidSingleShadow(shadow)) {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
function isValidSingleShadow(shadow) {
|
|
64
|
+
// A single box-shadow has the following components:
|
|
65
|
+
// offset-x (required)
|
|
66
|
+
// offset-y (required)
|
|
67
|
+
// blur-radius (optional)
|
|
68
|
+
// spread-radius (optional)
|
|
69
|
+
// color (optional)
|
|
70
|
+
// inset (optional, at the beginning)
|
|
71
|
+
const tokens = shadow.split(/\s+/);
|
|
72
|
+
// Must have at least offset-x and offset-y
|
|
73
|
+
if (tokens.length < 2) {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
let hasInset = false;
|
|
77
|
+
let offsetCount = 0;
|
|
78
|
+
let blurRadius = false;
|
|
79
|
+
let spreadRadius = false;
|
|
80
|
+
let color = false;
|
|
81
|
+
for (const token of tokens) {
|
|
82
|
+
if (token === 'inset') {
|
|
83
|
+
hasInset = true;
|
|
84
|
+
}
|
|
85
|
+
else if (isLengthValue(token)) {
|
|
86
|
+
offsetCount++;
|
|
87
|
+
if (offsetCount > 2) {
|
|
88
|
+
if (!blurRadius) {
|
|
89
|
+
blurRadius = true;
|
|
90
|
+
}
|
|
91
|
+
else if (!spreadRadius) {
|
|
92
|
+
spreadRadius = true;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
else if (isColorValue(token)) {
|
|
97
|
+
color = true;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// Must have at least offset-x and offset-y
|
|
101
|
+
return offsetCount >= 2;
|
|
102
|
+
}
|
|
103
|
+
function isLengthValue(value) {
|
|
104
|
+
// Check for px, rem, em, %, or unitless (0)
|
|
105
|
+
const lengthPattern = /^-?\d*\.?\d+(px|rem|em|%|vh|vw|vmin|vmax|cm|mm|in|pt|pc|ex|ch)?$/;
|
|
106
|
+
return lengthPattern.test(value);
|
|
107
|
+
}
|
|
108
|
+
function isColorValue(value) {
|
|
109
|
+
// Hex colors
|
|
110
|
+
const hex = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;
|
|
111
|
+
// rgb/rgba - handle spaces and decimals properly
|
|
112
|
+
const rgb = /^rgba?\(\s*\d+\s*,\s*\d+\s*,\s*\d+(\s*,\s*[\d.]+)?\s*\)/;
|
|
113
|
+
// hsl/hsla
|
|
114
|
+
const hsl = /^hsla?\(\s*\d+(\.\d+)?\s*(deg|rad|turn)?\s*,\s*\d+%?\s*,\s*\d+%?(\s*,\s*[\d.]+)?\s*\)/;
|
|
115
|
+
// Named colors (basic check) - must be after other checks
|
|
116
|
+
const namedColor = /^[a-zA-Z]+$/;
|
|
117
|
+
return hex.test(value) || rgb.test(value) || hsl.test(value) || namedColor.test(value);
|
|
118
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ConstraintConfig } from '../config/schema.js';
|
|
2
|
+
export interface TypographyTokens {
|
|
3
|
+
fontSize?: Record<string, string>;
|
|
4
|
+
fontWeight?: Record<string, string>;
|
|
5
|
+
lineHeight?: Record<string, string>;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Validate typography token constraints
|
|
9
|
+
*/
|
|
10
|
+
export declare function validateTypographyConstraints(typography: TypographyTokens, config?: ConstraintConfig['typography']): void;
|
|
11
|
+
//# sourceMappingURL=typography.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typography.d.ts","sourceRoot":"","sources":["../../src/constraints/typography.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAG5D,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC;AAED;;GAEG;AACH,wBAAgB,6BAA6B,CAC3C,UAAU,EAAE,gBAAgB,EAC5B,MAAM,CAAC,EAAE,gBAAgB,CAAC,YAAY,CAAC,GACtC,IAAI,CAYN"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { constraintViolation } from './constraint-error.js';
|
|
2
|
+
import { resolveConstraintLevel } from './resolve-level.js';
|
|
3
|
+
/**
|
|
4
|
+
* Validate typography token constraints
|
|
5
|
+
*/
|
|
6
|
+
export function validateTypographyConstraints(typography, config) {
|
|
7
|
+
if (typography.fontSize) {
|
|
8
|
+
validateFontSizeConstraints(typography.fontSize, config?.fontSize);
|
|
9
|
+
}
|
|
10
|
+
if (typography.fontWeight) {
|
|
11
|
+
validateFontWeightConstraints(typography.fontWeight, config?.fontWeight);
|
|
12
|
+
}
|
|
13
|
+
if (typography.lineHeight) {
|
|
14
|
+
validateLineHeightConstraints(typography.lineHeight, config?.lineHeight);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Validate font size constraints
|
|
19
|
+
*/
|
|
20
|
+
function validateFontSizeConstraints(fontSize, config) {
|
|
21
|
+
for (const key in fontSize) {
|
|
22
|
+
const value = fontSize[key];
|
|
23
|
+
if (typeof value !== 'string') {
|
|
24
|
+
constraintViolation(resolveConstraintLevel(config?.type, 'error'), 'typography.fontSize.type', `Token typography.fontSize.${key} is not a string.`, `Change typography.fontSize.${key} to a string value like "16px" or "1rem".`);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (isValidFontSizeValue(value)) {
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
constraintViolation(resolveConstraintLevel(config?.format, 'error'), 'typography.fontSize.format', `Token typography.fontSize.${key} has invalid value "${value}".`, `Use a numeric value with a unit (px, rem, em, %).`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Validate font weight constraints
|
|
35
|
+
*/
|
|
36
|
+
function validateFontWeightConstraints(fontWeight, config) {
|
|
37
|
+
for (const key in fontWeight) {
|
|
38
|
+
const value = fontWeight[key];
|
|
39
|
+
if (typeof value !== 'string') {
|
|
40
|
+
constraintViolation(resolveConstraintLevel(config?.type, 'error'), 'typography.fontWeight.type', `Token typography.fontWeight.${key} is not a string.`, `Change typography.fontWeight.${key} to a string value like "400" or "bold".`);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
if (isValidFontWeightValue(value)) {
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
constraintViolation(resolveConstraintLevel(config?.format, 'error'), 'typography.fontWeight.format', `Token typography.fontWeight.${key} has invalid value "${value}".`, `Use a numeric weight (100-900) or a named weight (normal, bold, etc.).`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Validate line height constraints
|
|
51
|
+
*/
|
|
52
|
+
function validateLineHeightConstraints(lineHeight, config) {
|
|
53
|
+
for (const key in lineHeight) {
|
|
54
|
+
const value = lineHeight[key];
|
|
55
|
+
if (typeof value !== 'string') {
|
|
56
|
+
constraintViolation(resolveConstraintLevel(config?.type, 'error'), 'typography.lineHeight.type', `Token typography.lineHeight.${key} is not a string.`, `Change typography.lineHeight.${key} to a string value like "1.5" or "24px".`);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (isValidLineHeightValue(value)) {
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
constraintViolation(resolveConstraintLevel(config?.format, 'error'), 'typography.lineHeight.format', `Token typography.lineHeight.${key} has invalid value "${value}".`, `Use a unitless number, or a value with a unit (px, rem, em, %).`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function isValidFontSizeValue(value) {
|
|
66
|
+
const unitPattern = /^\d*\.?\d+(px|rem|em|%)$/;
|
|
67
|
+
return unitPattern.test(value);
|
|
68
|
+
}
|
|
69
|
+
function isValidFontWeightValue(value) {
|
|
70
|
+
// Numeric weights: 100, 200, ..., 900
|
|
71
|
+
const numericPattern = /^[1-9]00$/;
|
|
72
|
+
// Named weights
|
|
73
|
+
const namedWeights = /^(normal|bold|bolder|lighter|100|200|300|400|500|600|700|800|900)$/;
|
|
74
|
+
return numericPattern.test(value) || namedWeights.test(value);
|
|
75
|
+
}
|
|
76
|
+
function isValidLineHeightValue(value) {
|
|
77
|
+
// Unitless number (most common for line-height)
|
|
78
|
+
const unitlessPattern = /^\d*\.?\d+$/;
|
|
79
|
+
// With units
|
|
80
|
+
const unitPattern = /^\d*\.?\d+(px|rem|em|%)$/;
|
|
81
|
+
// Special CSS values
|
|
82
|
+
const specialValues = /^(normal|inherit|initial|revert|unset)$/;
|
|
83
|
+
return unitlessPattern.test(value) || unitPattern.test(value) || specialValues.test(value);
|
|
84
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ConstraintConfig } from '../config/schema.js';
|
|
2
|
+
/**
|
|
3
|
+
* Validate z-index token constraints
|
|
4
|
+
*/
|
|
5
|
+
export declare function validateZIndexConstraints(zIndex: Record<string, string>, config?: ConstraintConfig['zIndex']): void;
|
|
6
|
+
//# sourceMappingURL=z-index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"z-index.d.ts","sourceRoot":"","sources":["../../src/constraints/z-index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAE5D;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC9B,MAAM,CAAC,EAAE,gBAAgB,CAAC,QAAQ,CAAC,GAClC,IAAI,CAyBN"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { constraintViolation } from './constraint-error.js';
|
|
2
|
+
import { resolveConstraintLevel } from './resolve-level.js';
|
|
3
|
+
/**
|
|
4
|
+
* Validate z-index token constraints
|
|
5
|
+
*/
|
|
6
|
+
export function validateZIndexConstraints(zIndex, config) {
|
|
7
|
+
for (const key in zIndex) {
|
|
8
|
+
const value = zIndex[key];
|
|
9
|
+
if (typeof value !== 'string') {
|
|
10
|
+
constraintViolation(resolveConstraintLevel(config?.type, 'error'), 'zIndex.type', `Token zIndex.${key} is not a string.`, `Change zIndex.${key} to a string value like "1000" or "auto".`);
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
if (isValidZIndexValue(value)) {
|
|
14
|
+
continue;
|
|
15
|
+
}
|
|
16
|
+
constraintViolation(resolveConstraintLevel(config?.format, 'error'), 'zIndex.format', `Token zIndex.${key} has invalid value "${value}".`, `Use a positive integer string (e.g., "1000", "2000") or the "auto" keyword.`);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function isValidZIndexValue(value) {
|
|
20
|
+
// Allow positive integers
|
|
21
|
+
const integerPattern = /^\d+$/;
|
|
22
|
+
// Allow special CSS values
|
|
23
|
+
const specialValues = /^(auto|inherit|initial|revert|unset)$/;
|
|
24
|
+
return integerPattern.test(value) || specialValues.test(value);
|
|
25
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-css.d.ts","sourceRoot":"","sources":["../../src/engine/build-css.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAazD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"build-css.d.ts","sourceRoot":"","sources":["../../src/engine/build-css.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAazD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CA6GhE"}
|
package/dist/engine/build-css.js
CHANGED
|
@@ -47,7 +47,31 @@ Use one of the available presets or remove it from ngcorex.config.ts`);
|
|
|
47
47
|
if (tokens.colors) {
|
|
48
48
|
Object.assign(allTokens, normalizeColorTokens(tokens.colors));
|
|
49
49
|
}
|
|
50
|
-
// 5.
|
|
50
|
+
// 5. Normalize radius
|
|
51
|
+
if (tokens.radius) {
|
|
52
|
+
Object.assign(allTokens, normalizeTokenScale('radius', tokens.radius));
|
|
53
|
+
}
|
|
54
|
+
// 6. Normalize z-index
|
|
55
|
+
if (tokens.zIndex) {
|
|
56
|
+
Object.assign(allTokens, normalizeTokenScale('zIndex', tokens.zIndex));
|
|
57
|
+
}
|
|
58
|
+
// 7. Normalize typography
|
|
59
|
+
if (tokens.typography) {
|
|
60
|
+
if (tokens.typography.fontSize) {
|
|
61
|
+
Object.assign(allTokens, normalizeTokenScale('fontSize', tokens.typography.fontSize));
|
|
62
|
+
}
|
|
63
|
+
if (tokens.typography.fontWeight) {
|
|
64
|
+
Object.assign(allTokens, normalizeTokenScale('fontWeight', tokens.typography.fontWeight));
|
|
65
|
+
}
|
|
66
|
+
if (tokens.typography.lineHeight) {
|
|
67
|
+
Object.assign(allTokens, normalizeTokenScale('lineHeight', tokens.typography.lineHeight));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// 8. Normalize shadows
|
|
71
|
+
if (tokens.shadows) {
|
|
72
|
+
Object.assign(allTokens, normalizeTokenScale('shadows', tokens.shadows));
|
|
73
|
+
}
|
|
74
|
+
// 9. Generate CSS
|
|
51
75
|
const css = generateCssVariables(allTokens);
|
|
52
76
|
return wrapCss(css, config.output?.layer);
|
|
53
77
|
}
|