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.
@@ -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
- import { DeepPartial } from "./utilities.js";
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
- extend<K extends {} = any>(config: DeepPartial<T> & Config<K, R & K>): Library<T & K, R & K>;
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
- interface Subscriber<R extends {}> {
14
- onChange(records: ReadonlyArray<Library.Token<DesignToken.Any, R>>): void;
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 TokenLibrary<T extends {}, R extends {} = T> = {
23
- [K in keyof Readonly<T>]: T[K] extends DesignToken.Any ? Token<T[K], R> : K extends "type" ? DesignToken.Type : T[K] extends {} ? TokenLibrary<T[K], R> : never;
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 token value that serves as an alias to another token value
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 Alias<T extends DesignToken.Any, R extends Context<any>> = (context: R) => T | DesignToken.ValueByToken<T>;
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
- * An {@link (Library:namespace).Alias} that supports complex token value types
33
- * such as {@link DesignToken.Border}
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 DeepAlias<V extends DesignToken.Values.Any, T extends Context<any>> = {
38
- [K in keyof V]: V[K] extends DesignToken.Values.Any ? V[K] | Alias<DesignToken.TokenByValue<V[K]>, T> | DeepAlias<V[K], T> : never;
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
- * Context object provided to {@link (Library:namespace).Alias} values at runtime
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
- type Context<T extends {}, R extends {} = T> = {
46
- [K in keyof Readonly<T>]: T[K] extends DesignToken.Any ? Readonly<T[K]> : K extends "type" ? DesignToken.Type : T[K] extends {} ? Context<T[K], R> : never;
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.Any, C extends {}> = {
54
- set(value: DesignToken.ValueByToken<T> | Alias<T, C>): void;
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.ValueByToken<T>;
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
- [K in keyof T]: T[K] extends DesignToken.Any ? ConfigValue<T[K], R> : T[K] extends {} ? Config<T[K], R> : never;
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 ConfigValue<T extends DesignToken.Any, R extends {}> = T | (Omit<T, "value"> & {
74
- value: Library.Alias<T, Context<R>> | Library.DeepAlias<DesignToken.ValueByToken<T>, Context<R>>;
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 {} = any>(config: Library.Config<T, T>) => Library.Library<T>;
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 {};