|
|
|
|
@ -175,6 +175,27 @@ function validateEidosConfigShape(
|
|
|
|
|
message: 'Eidos config must define a primitives object'
|
|
|
|
|
})
|
|
|
|
|
ok = false
|
|
|
|
|
} else {
|
|
|
|
|
const primitiveKeys = [
|
|
|
|
|
'color',
|
|
|
|
|
'size',
|
|
|
|
|
'space',
|
|
|
|
|
'controlHeight',
|
|
|
|
|
'radius',
|
|
|
|
|
'border',
|
|
|
|
|
'focusRing',
|
|
|
|
|
'layout',
|
|
|
|
|
'density',
|
|
|
|
|
'typography',
|
|
|
|
|
'motion',
|
|
|
|
|
'icon',
|
|
|
|
|
'opacity',
|
|
|
|
|
'zIndex'
|
|
|
|
|
] as const
|
|
|
|
|
|
|
|
|
|
for (const key of primitiveKeys) {
|
|
|
|
|
ok = validateOptionalPlainRecord(input.primitives[key], `primitives.${key}`, issues) && ok
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const semantics = input.semantics
|
|
|
|
|
@ -189,25 +210,61 @@ function validateEidosConfigShape(
|
|
|
|
|
ok = false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (input.themes !== undefined && !isPlainRecord(input.themes)) {
|
|
|
|
|
issues.push({
|
|
|
|
|
path: 'themes',
|
|
|
|
|
message: 'Eidos config themes must be a plain object'
|
|
|
|
|
})
|
|
|
|
|
ok = false
|
|
|
|
|
if (input.themes !== undefined) {
|
|
|
|
|
if (!isPlainRecord(input.themes)) {
|
|
|
|
|
issues.push({
|
|
|
|
|
path: 'themes',
|
|
|
|
|
message: 'Eidos config themes must be a plain object'
|
|
|
|
|
})
|
|
|
|
|
ok = false
|
|
|
|
|
} else {
|
|
|
|
|
for (const [themeId, theme] of Object.entries(input.themes)) {
|
|
|
|
|
if (!isPlainRecord(theme)) {
|
|
|
|
|
issues.push({
|
|
|
|
|
path: `themes.${themeId}`,
|
|
|
|
|
message: 'Eidos config theme entries must be plain objects'
|
|
|
|
|
})
|
|
|
|
|
ok = false
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
ok = validateOptionalPlainRecord(theme.color, `themes.${themeId}.color`, issues) && ok
|
|
|
|
|
ok = validateOptionalPlainRecord(theme.shadow, `themes.${themeId}.shadow`, issues) && ok
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (input.recipes !== undefined && !isPlainRecord(input.recipes)) {
|
|
|
|
|
issues.push({
|
|
|
|
|
path: 'recipes',
|
|
|
|
|
message: 'Eidos config recipes must be a plain object'
|
|
|
|
|
})
|
|
|
|
|
ok = false
|
|
|
|
|
if (input.recipes !== undefined) {
|
|
|
|
|
if (!isPlainRecord(input.recipes)) {
|
|
|
|
|
issues.push({
|
|
|
|
|
path: 'recipes',
|
|
|
|
|
message: 'Eidos config recipes must be a plain object'
|
|
|
|
|
})
|
|
|
|
|
ok = false
|
|
|
|
|
} else {
|
|
|
|
|
for (const [component, tokens] of Object.entries(input.recipes)) {
|
|
|
|
|
ok = validateOptionalPlainRecord(tokens, `recipes.${component}`, issues) && ok
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ok
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function validateOptionalPlainRecord(
|
|
|
|
|
value: unknown,
|
|
|
|
|
path: string,
|
|
|
|
|
issues: EidosValidationIssue[]
|
|
|
|
|
): boolean {
|
|
|
|
|
if (value === undefined) return true
|
|
|
|
|
if (isPlainRecord(value)) return true
|
|
|
|
|
|
|
|
|
|
issues.push({
|
|
|
|
|
path,
|
|
|
|
|
message: 'Eidos config entries must be plain objects'
|
|
|
|
|
})
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function listEidosColorScales(options: EidosConfig): readonly string[] {
|
|
|
|
|
return Object.keys(options.primitives.color?.scales ?? {})
|
|
|
|
|
}
|
|
|
|
|
|