design-token-library 0.1.0 → 0.3.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/CHANGELOG.md +79 -1
- package/README.md +39 -3
- package/dist/lib/css-reflector.d.ts +230 -9
- package/dist/lib/css-reflector.js +217 -29
- package/dist/lib/css-reflector.js.map +1 -1
- package/dist/lib/design-token.d.ts +225 -46
- package/dist/lib/design-token.js +1 -1
- package/dist/lib/design-token.js.map +1 -1
- package/dist/lib/index.d.ts +5 -2
- package/dist/lib/index.js +5 -2
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/library.d.ts +581 -28
- package/dist/lib/library.js +695 -125
- package/dist/lib/library.js.map +1 -1
- package/dist/lib/notifier.js.map +1 -1
- package/dist/lib/public.d.ts +1405 -0
- package/dist/lib/queue.js +10 -1
- package/dist/lib/queue.js.map +1 -1
- package/dist/lib/recipe.d.ts +81 -0
- package/dist/lib/recipe.js +101 -0
- package/dist/lib/recipe.js.map +1 -0
- package/dist/lib/ref.d.ts +91 -0
- package/dist/lib/ref.js +114 -0
- package/dist/lib/ref.js.map +1 -0
- package/dist/lib/tsconfig.tsbuildinfo +1 -0
- package/dist/lib/tsdoc-metadata.json +11 -0
- package/dist/lib/utilities.d.ts +10 -4
- package/dist/lib/utilities.js +10 -0
- package/dist/lib/utilities.js.map +1 -1
- package/dist/lib/values.d.ts +34 -0
- package/dist/lib/values.js +64 -0
- package/dist/lib/values.js.map +1 -0
- package/dist/lib/watcher.js.map +1 -1
- package/package.json +53 -40
- package/design-token-library-0.0.0.tgz +0 -0
package/dist/lib/library.d.ts
CHANGED
|
@@ -1,80 +1,633 @@
|
|
|
1
|
+
import { COMPUTED, RECIPE } from "./recipe.js";
|
|
2
|
+
import { REF } from "./ref.js";
|
|
1
3
|
import { DesignToken } from "./design-token.js";
|
|
2
|
-
|
|
4
|
+
/**
|
|
5
|
+
* The key of the phantom type of a ref: what it resolves to, in a library of
|
|
6
|
+
* what shape. It's never set.
|
|
7
|
+
*/
|
|
8
|
+
declare const RESOLVES: unique symbol;
|
|
9
|
+
/**
|
|
10
|
+
* The key of the phantom type of a computed value, apart from a ref's, so
|
|
11
|
+
* that a ref's type is never inferred from a computed value's.
|
|
12
|
+
*/
|
|
13
|
+
declare const COMPUTES: unique symbol;
|
|
14
|
+
/**
|
|
15
|
+
* The key of the phantom type that marks a token in
|
|
16
|
+
* {@link (Library:namespace).TokenValues}. It's never set.
|
|
17
|
+
*/
|
|
18
|
+
declare const TOKEN: unique symbol;
|
|
3
19
|
/**
|
|
4
20
|
* @public
|
|
5
21
|
*/
|
|
6
22
|
export declare namespace Library {
|
|
7
|
-
interface Library<T extends {}, R extends {} = T> {
|
|
23
|
+
export interface Library<T extends {}, R extends {} = T> {
|
|
8
24
|
tokens: TokenLibrary<T, R>;
|
|
9
25
|
subscribe(subscriber: Library.Subscriber<R>): void;
|
|
10
26
|
unsubscribe(subscriber: Library.Subscriber<R>): void;
|
|
11
|
-
|
|
27
|
+
/**
|
|
28
|
+
* Creates a library with the values of the tokens replaced, and
|
|
29
|
+
* recipes overridden.
|
|
30
|
+
*
|
|
31
|
+
* @remarks
|
|
32
|
+
* This has no tokens to add, so a value is checked against the type
|
|
33
|
+
* of its token wherever the token is.
|
|
34
|
+
*
|
|
35
|
+
* A token of the extension is made when it is first read, and an
|
|
36
|
+
* extension that nothing refers to is collected, along with its
|
|
37
|
+
* subscribers.
|
|
38
|
+
*/
|
|
39
|
+
extend(config: ExtendConfig<T, R>, options?: ExtendOptions): Library<T, R>;
|
|
40
|
+
/**
|
|
41
|
+
* Creates a library with the values of tokens replaced, new tokens,
|
|
42
|
+
* and recipes overridden.
|
|
43
|
+
*
|
|
44
|
+
* @remarks
|
|
45
|
+
* A token of the extension is made when it is first read, and an
|
|
46
|
+
* extension that nothing refers to is collected, along with its
|
|
47
|
+
* subscribers.
|
|
48
|
+
*/
|
|
49
|
+
extend<K extends NoRoot<K> = {}>(config: ExtendConfig<T, R & NewTokens<K, T>> & Config<K, R & NewTokens<K, T>, never, T> & NoInfer<ConfigValueCheck<K, R & NewTokens<K, T>>> & (ConfigTypeHint | {}), options?: ExtendOptions): Library<T & NewTokens<K, T>, R & NewTokens<K, T>>;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* The tokens and groups of `K` that are new relative to a source library
|
|
53
|
+
* of shape `T`. Overrides of tokens in `T` are removed so that they keep
|
|
54
|
+
* the source token's type.
|
|
55
|
+
*
|
|
56
|
+
* @public
|
|
57
|
+
*/
|
|
58
|
+
export type NewTokens<K, T> = {
|
|
59
|
+
[P in keyof K as P extends keyof T ? T[P] extends DesignToken.Shape ? never : P : P]: P extends keyof T ? NewTokens<K[P], T[P]> : K[P];
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* `$root` is the token of a group, so a library cannot have one at its top
|
|
63
|
+
* level, where there is no group to name it for.
|
|
64
|
+
*
|
|
65
|
+
* @public
|
|
66
|
+
*/
|
|
67
|
+
export type NoRoot<T> = {
|
|
68
|
+
[K in keyof T]: K extends "$root" ? never : T[K];
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* Which entries of a library {@link (entriesOf:3)} lists: its tokens, its
|
|
72
|
+
* groups, or both. Each is the `kind` of the entries it lists.
|
|
73
|
+
*
|
|
74
|
+
* @public
|
|
75
|
+
*/
|
|
76
|
+
export type Show = "all" | "token" | "group";
|
|
77
|
+
/**
|
|
78
|
+
* A token of a library, with the path of keys that leads to it from the
|
|
79
|
+
* root. The path of a group's own token ends with `$root`.
|
|
80
|
+
*
|
|
81
|
+
* @public
|
|
82
|
+
*/
|
|
83
|
+
export interface TokenEntry<R extends {}> {
|
|
84
|
+
readonly kind: "token";
|
|
85
|
+
readonly path: readonly string[];
|
|
86
|
+
readonly token: TokenRecord<R>;
|
|
12
87
|
}
|
|
13
|
-
|
|
14
|
-
|
|
88
|
+
/**
|
|
89
|
+
* A group of a library, with the path of keys that leads to it from the
|
|
90
|
+
* root. The group has the `$`-prefixed properties it was configured with.
|
|
91
|
+
*
|
|
92
|
+
* @public
|
|
93
|
+
*/
|
|
94
|
+
export interface GroupEntry {
|
|
95
|
+
readonly kind: "group";
|
|
96
|
+
readonly path: readonly string[];
|
|
97
|
+
readonly group: Readonly<DesignToken.Group>;
|
|
15
98
|
}
|
|
99
|
+
/**
|
|
100
|
+
* The entries that {@link (entriesOf:3)} lists for `S`.
|
|
101
|
+
*
|
|
102
|
+
* @public
|
|
103
|
+
*/
|
|
104
|
+
export type EntryOf<S extends Show, R extends {}> = S extends "token" ? TokenEntry<R> : S extends "group" ? GroupEntry : TokenEntry<R> | GroupEntry;
|
|
105
|
+
/**
|
|
106
|
+
* What a {@link (entriesOf:3)} filter returns for an entry: `true` lists it,
|
|
107
|
+
* `false` leaves it out, and `"reject"` leaves it out along with
|
|
108
|
+
* everything under it.
|
|
109
|
+
*
|
|
110
|
+
* @public
|
|
111
|
+
*/
|
|
112
|
+
export type FilterResult = boolean | "reject";
|
|
113
|
+
/**
|
|
114
|
+
* @public
|
|
115
|
+
*/
|
|
116
|
+
export interface EntriesOptions<S extends Show, R extends {}> {
|
|
117
|
+
/**
|
|
118
|
+
* The kind of entries to list. Groups are visited, and their tokens
|
|
119
|
+
* listed, whichever it is. By default, all.
|
|
120
|
+
*/
|
|
121
|
+
readonly whatToShow?: S;
|
|
122
|
+
/**
|
|
123
|
+
* Called with each entry of the kinds shown, before its children are
|
|
124
|
+
* visited.
|
|
125
|
+
*/
|
|
126
|
+
filter?(entry: EntryOf<S, R>): FilterResult;
|
|
127
|
+
}
|
|
128
|
+
export interface Subscriber<R extends {}> {
|
|
129
|
+
onChange(records: ReadonlyArray<Library.TokenRecord<R>>): void;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* A union of all tokens in a library of shape `T`.
|
|
133
|
+
*
|
|
134
|
+
* @public
|
|
135
|
+
*/
|
|
136
|
+
export type TokensOf<T> = {
|
|
137
|
+
[K in keyof T]-?: T[K] extends DesignToken.Shape ? T[K] : K extends keyof DesignToken.Group ? never : T[K] extends object ? TokensOf<T[K]> : never;
|
|
138
|
+
}[keyof T];
|
|
139
|
+
/**
|
|
140
|
+
* A {@link (Library:namespace).Token} of any token in a library of shape `R`.
|
|
141
|
+
* The union is discriminated by `type`.
|
|
142
|
+
*
|
|
143
|
+
* @public
|
|
144
|
+
*/
|
|
145
|
+
export type TokenRecord<R extends {}> = TokensOf<R> extends infer T ? T extends DesignToken.Shape ? Token<T, R> : never : never;
|
|
16
146
|
/**
|
|
17
147
|
* Defines a token library that can be interacted with
|
|
18
148
|
* to mutate token values.
|
|
19
149
|
*
|
|
150
|
+
* @remarks
|
|
151
|
+
* `G` is the type inherited from ancestor groups.
|
|
152
|
+
*
|
|
153
|
+
* @public
|
|
154
|
+
*/
|
|
155
|
+
export type TokenLibrary<T extends {}, R extends {} = T, G extends string = never> = TokenGroup<T, R, GroupType<T, G>>;
|
|
156
|
+
type TokenGroup<T extends {}, R extends {}, G extends string> = {
|
|
157
|
+
[K in keyof Readonly<T>]: T[K] extends DesignToken.Shape ? Token<T[K], R, G> : K extends keyof DesignToken.Group ? T[K] : T[K] extends {} ? TokenLibrary<T[K], R, G> : never;
|
|
158
|
+
};
|
|
159
|
+
/**
|
|
160
|
+
* The value type of each token of a library of shape `T`, by its path.
|
|
161
|
+
* Refs and computed values are typed by it, so they're given only to a
|
|
162
|
+
* library that has their tokens, with values of the same types, whether
|
|
163
|
+
* its shape is declared or inferred from its config.
|
|
164
|
+
*
|
|
165
|
+
* @public
|
|
166
|
+
*/
|
|
167
|
+
export type TokenValues<T> = {
|
|
168
|
+
[K in keyof T as K extends keyof DesignToken.Group ? never : K]: T[K] extends DesignToken.Shape ? TokenValue<DesignToken.ValueByToken<T[K]>> : T[K] extends object ? TokenValues<T[K]> : never;
|
|
169
|
+
};
|
|
170
|
+
/**
|
|
171
|
+
* A token with a value of type `V`, in
|
|
172
|
+
* {@link (Library:namespace).TokenValues}. It's only a type: it marks
|
|
173
|
+
* where a path ends at a token rather than going into its value.
|
|
174
|
+
*
|
|
175
|
+
* @public
|
|
176
|
+
*/
|
|
177
|
+
export interface TokenValue<V> {
|
|
178
|
+
readonly [TOKEN]: V;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* The dotted path of each token in `T`, the
|
|
182
|
+
* {@link (Library:namespace).TokenValues} of a library, whose value is a
|
|
183
|
+
* `V`. These are the paths {@link ref} takes where a `V` is expected.
|
|
184
|
+
*
|
|
185
|
+
* @public
|
|
186
|
+
*/
|
|
187
|
+
export type TokenPath<T, V> = {
|
|
188
|
+
[K in keyof T & string]: T[K] extends TokenValue<infer W> ? [W] extends [V] ? K : never : `${K}.${TokenPath<T[K], V>}`;
|
|
189
|
+
}[keyof T & string];
|
|
190
|
+
/**
|
|
191
|
+
* A reference to a token whose value is of type `V`, in a library whose
|
|
192
|
+
* token values are `T`. It's resolved to the token's value when the token
|
|
193
|
+
* that has it is read. Made by {@link ref} and {@link refs}.
|
|
194
|
+
*
|
|
195
|
+
* @remarks
|
|
196
|
+
* A ref is data: the path of its token. `T`, the
|
|
197
|
+
* {@link (Library:namespace).TokenValues} of the library, is only in its
|
|
198
|
+
* type, so that a ref can only be given to a library that has its token.
|
|
199
|
+
*
|
|
200
|
+
* @public
|
|
201
|
+
*/
|
|
202
|
+
export interface Ref<V, T> {
|
|
203
|
+
readonly [REF]: readonly string[];
|
|
204
|
+
readonly [RESOLVES]?: (library: T) => V;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* A value of type `V` computed by a {@link (Library:namespace).Recipe}
|
|
208
|
+
* from its arguments, which may refer to the tokens of a library whose
|
|
209
|
+
* {@link (Library:namespace).TokenValues} are `T`. It's computed when the
|
|
210
|
+
* token that has it is read.
|
|
211
|
+
*
|
|
212
|
+
* @remarks
|
|
213
|
+
* A computed value is data: the recipe and its arguments.
|
|
214
|
+
*
|
|
215
|
+
* @public
|
|
216
|
+
*/
|
|
217
|
+
export interface Computed<V, T> {
|
|
218
|
+
readonly [COMPUTED]: {
|
|
219
|
+
readonly recipe: Recipe<any, unknown>;
|
|
220
|
+
readonly args: readonly unknown[];
|
|
221
|
+
};
|
|
222
|
+
readonly [COMPUTES]?: (library: T) => V;
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* A value of type `V` in a configuration: the value, a
|
|
226
|
+
* {@link (Library:namespace).Ref}, a {@link (Library:namespace).Computed}
|
|
227
|
+
* value, or, when `V` is an object or an array, `V` with any of its
|
|
228
|
+
* properties and elements, at any depth, given as one of those.
|
|
229
|
+
*
|
|
230
|
+
* @remarks
|
|
231
|
+
* Its objects and arrays may be readonly, as a token's value is, so a
|
|
232
|
+
* token's value can be given where a config takes a value, as `set()`
|
|
233
|
+
* takes it. A computed value may be readonly, as a recipe's function that
|
|
234
|
+
* takes readonly arguments returns: the library copies and freezes a
|
|
235
|
+
* recipe's result.
|
|
236
|
+
*
|
|
20
237
|
* @public
|
|
21
238
|
*/
|
|
22
|
-
type
|
|
23
|
-
[K in keyof
|
|
239
|
+
export type DeepValue<V, T> = V | Ref<V, T> | Computed<DesignToken.DeepReadonly<V>, T> | (V extends object ? {
|
|
240
|
+
readonly [K in keyof V]: DeepValue<V[K], T>;
|
|
241
|
+
} : never);
|
|
242
|
+
/**
|
|
243
|
+
* The arguments of a {@link (Library:namespace).Recipe} whose function has
|
|
244
|
+
* the parameters `A`. Each may be a ref, a computed value, or a value with
|
|
245
|
+
* them in it.
|
|
246
|
+
*
|
|
247
|
+
* @public
|
|
248
|
+
*/
|
|
249
|
+
export type RecipeArguments<A extends readonly unknown[], T> = {
|
|
250
|
+
[K in keyof A]: DeepValue<A[K], T>;
|
|
24
251
|
};
|
|
25
252
|
/**
|
|
26
|
-
* A
|
|
253
|
+
* A function, made by {@link recipes}, that takes the arguments of a
|
|
254
|
+
* function with parameters `A` and result `V`, any of which may refer to
|
|
255
|
+
* tokens, and returns the {@link (Library:namespace).Computed} result.
|
|
256
|
+
* `T` is the token values of the library its arguments refer to.
|
|
257
|
+
*
|
|
258
|
+
* @remarks
|
|
259
|
+
* A recipe has its name and its function, which a library that extends
|
|
260
|
+
* another can override with {@link override}. The function gets each
|
|
261
|
+
* argument as a token gets its value: a ref's value, and a copy of plain
|
|
262
|
+
* data, which are frozen, and anything else as it is. So its parameters
|
|
263
|
+
* are typed readonly, as in `DesignToken.Values.Readonly.Color`.
|
|
27
264
|
*
|
|
28
265
|
* @public
|
|
29
266
|
*/
|
|
30
|
-
type
|
|
267
|
+
export type Recipe<A extends readonly unknown[], V> = (<T extends {} = {}>(...args: RecipeArguments<A, T>) => Computed<V, T>) & {
|
|
268
|
+
readonly [RECIPE]: {
|
|
269
|
+
readonly name: string;
|
|
270
|
+
readonly fn: (...args: A) => V;
|
|
271
|
+
};
|
|
272
|
+
};
|
|
31
273
|
/**
|
|
32
|
-
*
|
|
33
|
-
*
|
|
274
|
+
* The {@link (Library:namespace).Recipe | recipes} of the functions of `F`,
|
|
275
|
+
* by the same keys. Made by {@link recipes}.
|
|
34
276
|
*
|
|
35
277
|
* @public
|
|
36
278
|
*/
|
|
37
|
-
type
|
|
38
|
-
[K in keyof
|
|
279
|
+
export type Recipes<F extends Record<string, (...args: any[]) => unknown>> = {
|
|
280
|
+
readonly [K in keyof F]: Recipe<Parameters<F[K]>, ReturnType<F[K]>>;
|
|
39
281
|
};
|
|
40
282
|
/**
|
|
41
|
-
*
|
|
283
|
+
* A function that replaces a recipe's in a library made by `extend()`.
|
|
284
|
+
* Made by {@link override}.
|
|
285
|
+
*
|
|
286
|
+
* @public
|
|
287
|
+
*/
|
|
288
|
+
export interface RecipeOverride {
|
|
289
|
+
readonly recipe: Recipe<any, unknown>;
|
|
290
|
+
readonly fn: (...args: any[]) => unknown;
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Options of `extend()`.
|
|
42
294
|
*
|
|
43
295
|
* @public
|
|
44
296
|
*/
|
|
45
|
-
|
|
46
|
-
|
|
297
|
+
export interface ExtendOptions {
|
|
298
|
+
/**
|
|
299
|
+
* Recipes whose function is replaced in the new library, for every
|
|
300
|
+
* token that computes its value with them, including the tokens it
|
|
301
|
+
* doesn't restate.
|
|
302
|
+
*/
|
|
303
|
+
readonly recipes?: readonly RecipeOverride[];
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* A {@link (Library:namespace).Ref} to each token of a library of shape
|
|
307
|
+
* `R`, at the path of the token in `T`, the shape of a group of it. Made by
|
|
308
|
+
* {@link refs}.
|
|
309
|
+
*
|
|
310
|
+
* @public
|
|
311
|
+
*/
|
|
312
|
+
export type Refs<T extends {}, R extends {} = T> = {
|
|
313
|
+
readonly [K in keyof T as K extends keyof DesignToken.Group ? never : K]-?: T[K] extends DesignToken.Shape ? Ref<DesignToken.ValueByToken<T[K]>, TokenValues<R>> : T[K] extends {} ? Refs<T[K], R> : never;
|
|
47
314
|
};
|
|
48
315
|
/**
|
|
49
316
|
* A token in a {@link (Library:namespace).TokenLibrary}
|
|
50
317
|
*
|
|
318
|
+
* @remarks
|
|
319
|
+
* `G` is the type inherited from ancestor groups, used when
|
|
320
|
+
* `T` does not declare a `$type`.
|
|
321
|
+
*
|
|
51
322
|
* @public
|
|
52
323
|
*/
|
|
53
|
-
type Token<T extends DesignToken.
|
|
54
|
-
set(value:
|
|
324
|
+
export type Token<T extends DesignToken.Shape, C extends {}, G extends string = never> = {
|
|
325
|
+
set(value: ConfigTokenValue<T, C> | DesignToken.ReadonlyValueByToken<T>): void;
|
|
326
|
+
/**
|
|
327
|
+
* A JSON representation of the token's name, type, resolved value,
|
|
328
|
+
* description, extensions and deprecation.
|
|
329
|
+
*/
|
|
55
330
|
toString(): string;
|
|
56
|
-
readonly type: DesignToken.TypeByToken<T>;
|
|
57
|
-
readonly extensions: Record<string, any>;
|
|
58
|
-
readonly value: DesignToken.
|
|
59
|
-
readonly description: string;
|
|
331
|
+
readonly $type: DesignToken.TypeByToken<T, G>;
|
|
332
|
+
readonly $extensions: Record<string, any>;
|
|
333
|
+
readonly $value: DesignToken.ReadonlyValueByToken<T>;
|
|
334
|
+
readonly $description: string;
|
|
335
|
+
/**
|
|
336
|
+
* `false`, `true`, or the explanation the token was deprecated with.
|
|
337
|
+
*/
|
|
338
|
+
readonly $deprecated: boolean | string;
|
|
60
339
|
readonly name: string;
|
|
61
340
|
};
|
|
341
|
+
type IsUnion<T, U = T> = T extends unknown ? [U] extends [T] ? false : true : never;
|
|
342
|
+
/**
|
|
343
|
+
* The type a group passes on to its descendant tokens, following
|
|
344
|
+
* {@link https://www.designtokens.org/tr/2025.10/format/#type-1 | DTCG group type inheritance}.
|
|
345
|
+
*
|
|
346
|
+
* @remarks
|
|
347
|
+
* A group passes on its own `$type` only when the group's shape declares a
|
|
348
|
+
* required, single, literal `$type`. A group with an optional or non-literal
|
|
349
|
+
* `$type` may set any type at runtime, so it passes on nothing. A group
|
|
350
|
+
* without a `$type` passes on its ancestor's type, `G`.
|
|
351
|
+
*
|
|
352
|
+
* @public
|
|
353
|
+
*/
|
|
354
|
+
export type GroupType<T, G extends string = never> = "$type" extends keyof T ? {} extends Pick<T, "$type"> ? never : T["$type"] extends string ? string extends T["$type"] ? never : true extends IsUnion<T["$type"]> ? never : T["$type"] : never : G;
|
|
355
|
+
/**
|
|
356
|
+
* The value of a token in a configuration object, in a library of shape
|
|
357
|
+
* `R`: a {@link (Library:namespace).DeepValue} of the token's value type.
|
|
358
|
+
*
|
|
359
|
+
* @public
|
|
360
|
+
*/
|
|
361
|
+
export type ConfigTokenValue<T extends DesignToken.Shape, R extends {}> = DeepValue<DesignToken.ValueByToken<T>, TokenValues<R>>;
|
|
362
|
+
/**
|
|
363
|
+
* A token in a configuration object.
|
|
364
|
+
*
|
|
365
|
+
* @remarks
|
|
366
|
+
* The token's `$type` may only be omitted when it matches the type
|
|
367
|
+
* inherited from ancestor groups, `G`.
|
|
368
|
+
*
|
|
369
|
+
* @public
|
|
370
|
+
*/
|
|
371
|
+
export type ConfigValue<T extends DesignToken.Shape, R extends {}, G extends string = never> = T | (Omit<T, "$type" | "$value"> & ([G] extends [never] ? {
|
|
372
|
+
$type: DesignToken.TypeByToken<T>;
|
|
373
|
+
} : [DesignToken.TypeByToken<T, G>] extends [G] ? {
|
|
374
|
+
$type?: DesignToken.TypeByToken<T, G>;
|
|
375
|
+
} : {
|
|
376
|
+
$type: DesignToken.TypeByToken<T>;
|
|
377
|
+
}) & {
|
|
378
|
+
$value: ConfigTokenValue<T, R>;
|
|
379
|
+
});
|
|
62
380
|
/**
|
|
63
381
|
* A configuration object provided to {@link Library.create}
|
|
64
382
|
*
|
|
383
|
+
* @remarks
|
|
384
|
+
* `G` is the type inherited from ancestor groups. `S` is the shape of a
|
|
385
|
+
* source library being extended: its group types are inherited, and its
|
|
386
|
+
* tokens may be overridden without restating their type.
|
|
387
|
+
*
|
|
65
388
|
* @public
|
|
66
389
|
*/
|
|
67
|
-
type Config<T extends {}, R extends {} = T> =
|
|
68
|
-
|
|
390
|
+
export type Config<T extends {}, R extends {} = T, G extends string = never, S = {}> = ConfigGroup<T, R, GroupType<T, GroupType<S, G>>, S>;
|
|
391
|
+
type ConfigGroup<T extends {}, R extends {}, G extends string, S> = {
|
|
392
|
+
[K in keyof T]: K extends keyof S ? S[K] extends DesignToken.Shape ? unknown : ConfigEntry<T, R, G, S, K> : ConfigEntry<T, R, G, S, K>;
|
|
69
393
|
};
|
|
394
|
+
type ConfigEntry<T extends {}, R extends {}, G extends string, S, K extends keyof T> = T[K] extends DesignToken.Shape ? ConfigValue<T[K], R, G> : K extends keyof DesignToken.Group ? T[K] : T[K] extends {} ? Config<T[K], R, G, K extends keyof S ? S[K] : {}> : T[K] extends null | undefined ? T[K] : never;
|
|
70
395
|
/**
|
|
396
|
+
* Checks the `$value` of each token in a config of shape `T` against
|
|
397
|
+
* its `$type`. It's needed when `T` is inferred from the config, because
|
|
398
|
+
* the inferred `$value` is the config's own value, so
|
|
399
|
+
* {@link (Library:namespace).Config} alone can't reject it.
|
|
400
|
+
*
|
|
401
|
+
* @remarks
|
|
402
|
+
* Only the values of tokens that declare a {@link DesignToken.Type} are
|
|
403
|
+
* checked. A token can't have a child (a key without a `$` prefix).
|
|
404
|
+
*
|
|
405
|
+
* Tokens are found by their keys rather than by `T[K] extends Shape`,
|
|
406
|
+
* which TypeScript doesn't resolve for an inferred `T` with extra keys.
|
|
407
|
+
* An `any` config, such as `Library.create<any>()`, isn't checked.
|
|
408
|
+
*
|
|
71
409
|
* @public
|
|
72
410
|
*/
|
|
73
|
-
type
|
|
74
|
-
|
|
75
|
-
|
|
411
|
+
export type ConfigValueCheck<T, R extends {}> = 0 extends 1 & T ? unknown : {
|
|
412
|
+
[K in keyof T]: 0 extends 1 & T[K] ? unknown : "$value" extends keyof T[K] ? ("$type" extends keyof T[K] ? TokenValueCheck<T[K][Extract<"$type", keyof T[K]>], R> : unknown) & {
|
|
413
|
+
[P in Exclude<keyof T[K], `$${string}`>]?: never;
|
|
414
|
+
} : T[K] extends object ? ConfigValueCheck<T[K], R> : unknown;
|
|
415
|
+
};
|
|
416
|
+
type TokenValueCheck<Type, R extends {}> = [Type] extends [
|
|
417
|
+
keyof DesignToken.ValueByType
|
|
418
|
+
] ? {
|
|
419
|
+
$value: ConfigTokenValue<{
|
|
420
|
+
$type: Type;
|
|
421
|
+
$value: DesignToken.ValueByType[Type];
|
|
422
|
+
}, R>;
|
|
423
|
+
} : unknown;
|
|
424
|
+
/**
|
|
425
|
+
* Gives each `$type` in a config literal a contextual type, so that
|
|
426
|
+
* TypeScript keeps an inferred `$type` literal, such as
|
|
427
|
+
* `DesignToken.Type.Color`, instead of widening it to `DesignToken.Type`.
|
|
428
|
+
* {@link (Library:namespace).ConfigValueCheck} needs the literal.
|
|
429
|
+
*
|
|
430
|
+
* @remarks
|
|
431
|
+
* Configs are typed `ConfigTypeHint | {}`, so a config without an index
|
|
432
|
+
* signature, such as a typed variable, is still accepted.
|
|
433
|
+
*
|
|
434
|
+
* @public
|
|
435
|
+
*/
|
|
436
|
+
export type ConfigTypeHint = {
|
|
437
|
+
readonly [key: string]: ConfigTypeHint | DesignToken.Type | (string & {}) | number | boolean | object | null | undefined;
|
|
438
|
+
};
|
|
439
|
+
/**
|
|
440
|
+
* A configuration object provided to {@link (Library:namespace).Library.(extend:1)}.
|
|
441
|
+
* All tokens and groups of the source library are optional, and token
|
|
442
|
+
* values may be static values, refs or computed values. Token types are inherited
|
|
443
|
+
* from the source library.
|
|
444
|
+
*
|
|
445
|
+
* @public
|
|
446
|
+
*/
|
|
447
|
+
export type ExtendConfig<T extends {}, R extends {} = T> = {
|
|
448
|
+
[K in keyof T]?: T[K] extends DesignToken.Shape ? Omit<T[K], "$type" | "$value"> & {
|
|
449
|
+
$type?: DesignToken.TypeByToken<T[K]>;
|
|
450
|
+
$value: ConfigTokenValue<T[K], R>;
|
|
451
|
+
} : K extends keyof DesignToken.Group ? T[K] : T[K] extends {} ? ExtendConfig<T[K], R> : never;
|
|
452
|
+
};
|
|
76
453
|
/**
|
|
77
454
|
* @public
|
|
78
455
|
*/
|
|
79
|
-
const create: <T extends
|
|
456
|
+
export const create: <T extends NoRoot<T> = any>(config: Library.Config<T, T> & NoInfer<ConfigValueCheck<T, T>> & (ConfigTypeHint | {})) => Library.Library<T>;
|
|
457
|
+
export {};
|
|
80
458
|
}
|
|
459
|
+
/**
|
|
460
|
+
* Thrown when reading a token whose value refers back to itself through
|
|
461
|
+
* one or more refs or computed values.
|
|
462
|
+
*
|
|
463
|
+
* @public
|
|
464
|
+
*/
|
|
465
|
+
export declare class CircularReferenceError extends Error {
|
|
466
|
+
readonly name = "CircularReferenceError";
|
|
467
|
+
/**
|
|
468
|
+
* The names of the tokens in the cycle, starting and ending with the
|
|
469
|
+
* same token.
|
|
470
|
+
*/
|
|
471
|
+
readonly chain: string[];
|
|
472
|
+
constructor(chain: string[]);
|
|
473
|
+
}
|
|
474
|
+
/**
|
|
475
|
+
* A token's value as it was configured, or last given to `set()`, with its
|
|
476
|
+
* refs and computed values unresolved. A token of a library made by
|
|
477
|
+
* `extend()` that isn't given a value has its source token's.
|
|
478
|
+
*
|
|
479
|
+
* @remarks
|
|
480
|
+
* A token's `$value` is resolved, so it can't tell a value that is given from
|
|
481
|
+
* one that is derived from other tokens, or say where in a value a ref is. A
|
|
482
|
+
* tool that reads how a library is configured finds the refs in this value
|
|
483
|
+
* with {@link isRef} and the computed values with {@link isComputed}: a value
|
|
484
|
+
* with neither, at any depth, is given. A converter that writes a ref as a
|
|
485
|
+
* CSS `var()`, rather than its token's value, reads the ref here and its
|
|
486
|
+
* path with {@link pathOf}.
|
|
487
|
+
*
|
|
488
|
+
* It's the value the token holds, not a copy, so it isn't frozen. Changing it
|
|
489
|
+
* doesn't change the token: give a new value to `set()`. Refs and computed
|
|
490
|
+
* values are searched for in plain data, as the library resolves them, and
|
|
491
|
+
* not in a class instance or a function.
|
|
492
|
+
*
|
|
493
|
+
* @example
|
|
494
|
+
* ```ts
|
|
495
|
+
* const isGiven = (value: unknown): boolean =>
|
|
496
|
+
* !isRef(value) &&
|
|
497
|
+
* !isComputed(value) &&
|
|
498
|
+
* (typeof value !== "object" || value === null ||
|
|
499
|
+
* Object.values(value).every(isGiven));
|
|
500
|
+
*
|
|
501
|
+
* isGiven(configuredValueOf(library.tokens.colors.primary)); // true
|
|
502
|
+
* isGiven(configuredValueOf(library.tokens.colors.hover)); // false: a recipe
|
|
503
|
+
* ```
|
|
504
|
+
*
|
|
505
|
+
* @public
|
|
506
|
+
*/
|
|
507
|
+
export declare const configuredValueOf: <T extends DesignToken.Shape, R extends {}, G extends string = never>(token: Library.Token<T, R, G>) => Library.ConfigTokenValue<T, R> | DesignToken.ReadonlyValueByToken<T>;
|
|
508
|
+
/**
|
|
509
|
+
* The tokens that a token's value refers to, through refs anywhere in its
|
|
510
|
+
* configured value, including the arguments of the recipes it's computed
|
|
511
|
+
* with, in the token's library. Each token is listed once, in the order its
|
|
512
|
+
* first ref is in the value.
|
|
513
|
+
*
|
|
514
|
+
* @remarks
|
|
515
|
+
* These are the tokens the value is made from, and not theirs in turn: a
|
|
516
|
+
* tool follows each with `dependenciesOf()` for the whole chain. A value
|
|
517
|
+
* computed by a recipe from literal arguments only has no dependencies,
|
|
518
|
+
* though it's derived: {@link configuredValueOf} tells that apart.
|
|
519
|
+
*
|
|
520
|
+
* It throws when a ref's path isn't a token of the library, as reading the
|
|
521
|
+
* token's `$value` does.
|
|
522
|
+
*
|
|
523
|
+
* @example
|
|
524
|
+
* ```ts
|
|
525
|
+
* // hover: { $value: Recipes.darken(theme.colors.primary, 0.2) }
|
|
526
|
+
* dependenciesOf(library.tokens.colors.hover).map((token) => token.name);
|
|
527
|
+
* // ["colors.primary"]
|
|
528
|
+
* ```
|
|
529
|
+
*
|
|
530
|
+
* @public
|
|
531
|
+
*/
|
|
532
|
+
export declare const dependenciesOf: <T extends DesignToken.Shape, R extends {}, G extends string = never>(token: Library.Token<T, R, G>) => ReadonlyArray<Library.TokenRecord<R>>;
|
|
533
|
+
/**
|
|
534
|
+
* The tokens and groups of a library, each with its path, in the order of
|
|
535
|
+
* the config. A group is listed before the tokens and groups in it.
|
|
536
|
+
*
|
|
537
|
+
* @remarks
|
|
538
|
+
* This is the library's own rule for what is a token and what is a group, and
|
|
539
|
+
* for which keys are children, so a tool that visits every token (an index, a
|
|
540
|
+
* report, a list of the tokens to offer for a property) doesn't walk
|
|
541
|
+
* `library.tokens` and restate it. It walks as a DOM `TreeWalker` does: an
|
|
542
|
+
* entry that `whatToShow` leaves out is not passed to `filter`, but what is
|
|
543
|
+
* under it is still visited, and `filter` can return `"reject"` to leave out
|
|
544
|
+
* a group and everything under it.
|
|
545
|
+
*
|
|
546
|
+
* The library itself isn't listed, as a `TreeWalker`'s root isn't, so its own
|
|
547
|
+
* `$`-prefixed properties are not visited. A group's own token is listed with
|
|
548
|
+
* the path of its group and `$root`.
|
|
549
|
+
*
|
|
550
|
+
* The order is the order of the keys in a JavaScript object, so a name that
|
|
551
|
+
* is an array index (`"0"`, `"123"`) is listed before the other names of its
|
|
552
|
+
* group, in ascending order, whatever its place in the config.
|
|
553
|
+
*
|
|
554
|
+
* The listing is lazy and reads the
|
|
555
|
+
* library as it goes; a token's `$value` is not read.
|
|
556
|
+
*
|
|
557
|
+
* @example
|
|
558
|
+
* ```ts
|
|
559
|
+
* // The names of every token that isn't deprecated, in a group that isn't
|
|
560
|
+
* for (const { token } of entriesOf(library, {
|
|
561
|
+
* whatToShow: "token",
|
|
562
|
+
* filter: ({ token }) => !token.$deprecated,
|
|
563
|
+
* })) {
|
|
564
|
+
* names.push(token.name);
|
|
565
|
+
* }
|
|
566
|
+
*
|
|
567
|
+
* // Everything, leaving out the deprecated groups
|
|
568
|
+
* const entries = [
|
|
569
|
+
* ...entriesOf(library, {
|
|
570
|
+
* filter: (entry) =>
|
|
571
|
+
* entry.kind === "group" && entry.group.$deprecated
|
|
572
|
+
* ? "reject"
|
|
573
|
+
* : true,
|
|
574
|
+
* }),
|
|
575
|
+
* ];
|
|
576
|
+
* ```
|
|
577
|
+
*
|
|
578
|
+
* @public
|
|
579
|
+
*/
|
|
580
|
+
export declare function entriesOf<T extends {}, R extends {}>(library: Library.Library<T, R>, options: Library.EntriesOptions<"token", R> & {
|
|
581
|
+
whatToShow: "token";
|
|
582
|
+
}): Generator<Library.TokenEntry<R>, void, undefined>;
|
|
583
|
+
/** @public */
|
|
584
|
+
export declare function entriesOf<T extends {}, R extends {}>(library: Library.Library<T, R>, options: Library.EntriesOptions<"group", R> & {
|
|
585
|
+
whatToShow: "group";
|
|
586
|
+
}): Generator<Library.GroupEntry, void, undefined>;
|
|
587
|
+
/** @public */
|
|
588
|
+
export declare function entriesOf<T extends {}, R extends {}>(library: Library.Library<T, R>, options?: Library.EntriesOptions<"all", R>): Generator<Library.EntryOf<"all", R>, void, undefined>;
|
|
589
|
+
/**
|
|
590
|
+
* The tokens whose values refer to a token, through refs anywhere in their
|
|
591
|
+
* configured values, including the arguments of their recipes, in the
|
|
592
|
+
* token's library. It is the reverse of {@link dependenciesOf}: each token is
|
|
593
|
+
* listed once, in the order of the library.
|
|
594
|
+
*
|
|
595
|
+
* @remarks
|
|
596
|
+
* These are the tokens that refer to the token directly. A token whose value
|
|
597
|
+
* may change when this one is set is also one that refers to one of those: a
|
|
598
|
+
* tool follows each with `dependentsOf()` for the whole set, as it follows
|
|
599
|
+
* {@link dependenciesOf} for the chain the other way.
|
|
600
|
+
*
|
|
601
|
+
* This reads the configured values and not the values, so it resolves no
|
|
602
|
+
* token, and so it is known of a library whose tokens have not been read. It
|
|
603
|
+
* is found for the whole library once and kept until a token is set to a
|
|
604
|
+
* different value, so each call after the first is a lookup. A value a recipe
|
|
605
|
+
* reads other than through its arguments is not seen, as for
|
|
606
|
+
* {@link dependenciesOf}.
|
|
607
|
+
*
|
|
608
|
+
* It throws when a ref in a token of the library isn't a token of it, as
|
|
609
|
+
* reading the token's `$value` does.
|
|
610
|
+
*
|
|
611
|
+
* @example
|
|
612
|
+
* ```ts
|
|
613
|
+
* // hover: { $value: Recipes.darken(theme.colors.primary, 0.2) }
|
|
614
|
+
* dependentsOf(library.tokens.colors.primary).map((token) => token.name);
|
|
615
|
+
* // ["colors.hover"]
|
|
616
|
+
*
|
|
617
|
+
* // Every token that may change when a token is set
|
|
618
|
+
* const affected = new Set<Library.Token<any, any>>();
|
|
619
|
+
* const visit = (token: Library.Token<any, any>) => {
|
|
620
|
+
* for (const dependent of dependentsOf(token)) {
|
|
621
|
+
* if (!affected.has(dependent)) {
|
|
622
|
+
* affected.add(dependent);
|
|
623
|
+
* visit(dependent);
|
|
624
|
+
* }
|
|
625
|
+
* }
|
|
626
|
+
* };
|
|
627
|
+
* visit(extension.tokens.color.context);
|
|
628
|
+
* ```
|
|
629
|
+
*
|
|
630
|
+
* @public
|
|
631
|
+
*/
|
|
632
|
+
export declare const dependentsOf: <T extends DesignToken.Shape, R extends {}, G extends string = never>(token: Library.Token<T, R, G>) => ReadonlyArray<Library.TokenRecord<R>>;
|
|
633
|
+
export {};
|