-
Notifications
You must be signed in to change notification settings - Fork 0
/
schema.ts
70 lines (63 loc) · 1.63 KB
/
schema.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import { useMemo } from 'react';
import { AnySchema, reach } from 'yup';
import { FeatureBase, NoFeature, PartialToken, TokenExtension } from '../token';
const _schema = Symbol('schema');
export interface Schema extends FeatureBase<'Schema', Schema> {
payload: {
readonly [_schema]: AnySchema;
};
childFeatures: {
[P in PropertyKey]: Schema;
};
}
export function addSchema(
schema: AnySchema
): TokenExtension<NoFeature, { add: Schema }> {
return builder =>
builder.addFeature<Schema>({
extend: {
[_schema]: schema as any,
},
extendChildren: (_, parent, property) => {
const parentSchema = getTokenSchema(parent);
const childSchema = parentSchema
? tryReach(parentSchema, String(property))
: undefined;
return {
[_schema]: childSchema,
};
},
});
}
export function getTokenSchema(token: PartialToken<Schema>): AnySchema {
return token[_schema];
}
function tryReach(obj: {}, path: string) {
try {
return reach(obj, path, null, null);
} catch {
return null;
}
}
export interface SchemaInfo {
label?: string;
required?: boolean;
}
////////////////
// React API
////////////////
export function useTokenSchemaInfo(
token: PartialToken<Schema> | undefined
): SchemaInfo {
const schemaDescription = useMemo(() => {
if (!token) return;
const schema = getTokenSchema(token);
if (!schema) return;
return schema.describe();
}, [token]);
if (!schemaDescription) return {};
return {
label: schemaDescription.label,
required: Boolean(schemaDescription.tests.find(t => t.name === 'required')),
};
}