Validate Eidos static primitives

active-uix
dev 5 months ago
parent 110c5026b9
commit cfee72bfc8

@ -32,10 +32,13 @@ Actualizacion Eidos ecosystem 2026-05-16:
(`DURATION_KEYS`, `EASE_KEYS`, `MOTION_DISTANCE_KEYS`,
`MOTION_SCALE_KEYS`, `ICON_STROKE_WIDTH_KEYS`) se exportan y validan en
runtime antes de generar CSS.
- Primitivas estaticas base reforzadas: `space` valida sufijos CSS abiertos,
`controlHeight` y `radius` usan key sets canonicos, y `focusRing` valida
valores no vacios.
- Validado:
- `npx vitest run src/uix/eidos/active-eidos-config.test.ts` -> 30 tests OK.
- `npx vitest run src/uix/eidos/active-eidos-config.test.ts` -> 31 tests OK.
- `npx vitest run src/uix/eidos/active-eidos.test.ts` -> 19 tests OK.
- `npx vitest run src/uix/eidos` -> 7 archivos, 70 tests OK.
- `npx vitest run src/uix/eidos` -> 7 archivos, 71 tests OK.
- `npm run check` -> 0 errores, 0 warnings.
Actualizacion permutation runner 2026-05-16:

@ -451,6 +451,25 @@ describe('ActiveEidos config', () => {
expect(report.issues.some((issue) => issue.path === 'themes.base-light.shadow.6')).toBe(true)
})
it('validates static primitive keys and focus ring values', () => {
const cfg = structuredClone(THEME_BASE_OPTIONS)
;(cfg.primitives.space as Record<string, string>)['bad space'] = '4px'
delete (cfg.primitives.controlHeight as Record<string, string>)['md']
;(cfg.primitives.radius as Record<string, string>)['huge'] = '32px'
;(cfg.primitives.focusRing as { width: string }).width = ''
const report = createEidos(cfg).validate()
expect(report.ok).toBe(false)
expect(report.issues.some((issue) => issue.path === 'primitives.space.bad space')).toBe(true)
expect(report.issues.some((issue) => issue.path === 'primitives.controlHeight.md')).toBe(
true
)
expect(report.issues.some((issue) => issue.path === 'primitives.radius.huge')).toBe(true)
expect(report.issues.some((issue) => issue.path === 'primitives.focusRing.width')).toBe(true)
})
it('validates layout primitive keys', () => {
const cfg = structuredClone(THEME_BASE_OPTIONS)

@ -185,6 +185,7 @@ export {
MOTION_DISTANCE_KEYS,
MOTION_SCALE_KEYS,
OPACITY_KEYS,
RADIUS_KEYS,
SHADOW_KEYS,
SHADOW_PHYSICAL_KEYS,
SHADOW_SEMANTIC_KEYS,

@ -96,7 +96,8 @@ export interface ColorSemanticSet {
export type ScaleMap<TKey extends string = string> = Record<TKey, string>;
export type ControlHeightKey = Exclude<Size, 'full'>;
export type RadiusKey = 'none' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl' | 'full';
export const RADIUS_KEYS = ['none', 'sm', 'md', 'lg', 'xl', 'xxl', 'full'] as const;
export type RadiusKey = (typeof RADIUS_KEYS)[number];
export const CONTAINER_WIDTH_KEYS = ['sm', 'md', 'lg', 'xl', 'xxl', 'full'] as const;
export const CONTENT_WIDTH_KEYS = ['xs', 'sm', 'md', 'lg', 'xl', 'xxl', 'prose'] as const;

@ -13,6 +13,7 @@ import {
MOTION_DISTANCE_KEYS,
MOTION_SCALE_KEYS,
OPACITY_KEYS,
RADIUS_KEYS,
SHADOW_KEYS,
SIZE_PRIMITIVE_KEYS,
TEXT_SIZES,
@ -56,6 +57,7 @@ const ICON_STROKE_WIDTH_KEY_SET = new Set<string>(ICON_STROKE_WIDTH_KEYS)
const MOTION_DISTANCE_KEY_SET = new Set<string>(MOTION_DISTANCE_KEYS)
const MOTION_SCALE_KEY_SET = new Set<string>(MOTION_SCALE_KEYS)
const OPACITY_KEY_SET = new Set<string>(OPACITY_KEYS)
const RADIUS_KEY_SET = new Set<string>(RADIUS_KEYS)
const SHADOW_KEY_SET = new Set<string>(SHADOW_KEYS)
const SIZE_PRIMITIVE_KEY_SET = new Set<string>(SIZE_PRIMITIVE_KEYS)
const TEXT_SIZE_SET = new Set<string>(TEXT_SIZES)
@ -103,6 +105,7 @@ export function validateEidosConfig(options: EidosConfig): EidosValidationReport
validateColorRoles(options, issues)
validateTypography(options, issues)
validateSizePrimitives(options, issues)
validateStaticPrimitives(options, issues)
validateBorderPrimitives(options, issues)
validateLayoutPrimitives(options, issues)
validateDensityPrimitives(options, issues)
@ -526,6 +529,30 @@ function validateSizePrimitive(
validateNonEmptyCssValue(`${path}.gap`, size.gap, issues)
}
function validateStaticPrimitives(options: EidosConfig, issues: EidosValidationIssue[]): void {
validateOpenScalePrimitive('primitives.space', options.primitives.space, 'space', issues)
validateRecordPrimitive(
'primitives.controlHeight',
options.primitives.controlHeight,
SIZE_PRIMITIVE_KEYS,
SIZE_PRIMITIVE_KEY_SET,
issues
)
validateRecordPrimitive(
'primitives.radius',
options.primitives.radius,
RADIUS_KEYS,
RADIUS_KEY_SET,
issues
)
const focusRing = options.primitives.focusRing
if (!focusRing) return
validateNonEmptyCssValue('primitives.focusRing.offset', focusRing.offset, issues)
validateNonEmptyCssValue('primitives.focusRing.width', focusRing.width, issues)
}
function validateBorderPrimitives(options: EidosConfig, issues: EidosValidationIssue[]): void {
const border = options.primitives.border
if (!border) return
@ -755,6 +782,20 @@ function validateRecordPrimitive(
}
}
function validateOpenScalePrimitive(
path: string,
record: Record<string, string | number> | undefined,
label: string,
issues: EidosValidationIssue[]
): void {
if (!record) return
for (const [key, value] of Object.entries(record)) {
validateCssTokenSuffix(`${path}.${key}`, key, label, issues)
validateNonEmptyCssValue(`${path}.${key}`, String(value), issues)
}
}
function validateTypographySizeValue(
path: string,
value: unknown,

Loading…
Cancel
Save

Powered by TurnKey Linux.