Skip to content

Commit 11ef4bb

Browse files
committed
revert derived tokens PR
1 parent 58eb814 commit 11ef4bb

File tree

7 files changed

+106
-131
lines changed

7 files changed

+106
-131
lines changed

doc-site/docs/getting-started.md

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ const myLibraryConfig: Library.Config<IMyLibrary> = {
6161
body: {
6262
type: DesignToken.Type.Typography
6363
value: {
64-
fontFamily: (tokens) => tokens.typography.fonts.base, // Alias
64+
fontFamily: Library.derive((tokens) => tokens.typography.fonts.base), // Alias
6565
fontSize: "14px",
6666
fontWeight: 400;
6767
letterSpacing: "0px";
@@ -74,13 +74,13 @@ const myLibraryConfig: Library.Config<IMyLibrary> = {
7474

7575
### Tokens
7676

77-
Each token in the library must have a `value` property, and groups must not have a value. Tokens can be assigned three types of values: **static**, **alias**, and **computed**.
77+
Each token in the library must have a `value` property, and groups must not have a value. Tokens can be assigned three types of values: **static**, **alias**, and **derived**.
7878

7979
```ts
8080
interface Colors {
8181
static: DesignToken.Color;
8282
alias: DesignToken.Color;
83-
computed: DesignToken.Color;
83+
derived: DesignToken.Color;
8484
}
8585

8686
const config: Library.Config<Colors> = {
@@ -90,12 +90,12 @@ const config: Library.Config<Colors> = {
9090
},
9191
alias: {
9292
type: DesignToken.Type.Color,
93-
value: (tokens) => tokens.static, // alias to the 'static' token
93+
value: Library.derive((tokens) => tokens.static), // alias to the 'static' token
9494
},
95-
computed: {
95+
derived: {
9696
type: DesignToken.Type.Color,
9797
// Operate on the value of the 'alias' token
98-
value: (tokens) => darken(tokens.alias.value, 0.3),
98+
value: Library.derive((tokens) => darken(tokens.alias.value, 0.3)),
9999
},
100100
};
101101
```
@@ -106,7 +106,7 @@ In alignment with the [DTCG Group](https://design-tokens.github.io/community-gro
106106

107107
## Creating a Library
108108

109-
With the configuration defined, the library can be created. The purpose of the library is to enable changes to token values, notify subscribers to changes, and reconciling alias and computed values with those changes.
109+
With the configuration defined, the library can be created. The purpose of the library is to enable changes to token values, notify subscribers to changes, and reconciling alias and derived values with those changes.
110110

111111
```ts
112112
const library = Library.create(myLibraryConfig);
@@ -144,12 +144,15 @@ library.subscribe(subscriber);
144144
library.tokens.foreground.set("#878787");
145145
```
146146

147-
Change notifications are batched and subscribers get notified each microtask. It's important to note that token values are lazily evaluated. If a computed or alias token has not been accessed, it will **not** notify itself to subscribers even if it's dependencies change:
147+
Change notifications are batched and subscribers get notified each microtask. It's important to note that token values are lazily evaluated. If a derived token has not been accessed, it will **not** notify itself to subscribers even if it's dependencies change:
148148

149149
```ts
150150
const library = Library.create({
151151
a: { type: DesignToken.Type.Color, value: "#000000" },
152-
b: { type: DesignToken.Type.Color, value: (tokens) => tokens.a },
152+
b: {
153+
type: DesignToken.Type.Color,
154+
value: Library.derive((tokens) => tokens.a),
155+
},
153156
});
154157

155158
library.subscribe({

src/lib/design-token.ts

Lines changed: 0 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -190,38 +190,6 @@ export namespace DesignToken {
190190
| Typography;
191191
}
192192

193-
/**
194-
* @internal
195-
*/
196-
export type TokenByType<T extends DesignToken.Type> =
197-
T extends DesignToken.Type.Border
198-
? DesignToken.Border
199-
: T extends DesignToken.Type.Color
200-
? DesignToken.Color
201-
: T extends DesignToken.Type.CubicBezier
202-
? DesignToken.CubicBezier
203-
: T extends DesignToken.Type.Dimension
204-
? DesignToken.Dimension
205-
: T extends DesignToken.Type.Duration
206-
? DesignToken.Duration
207-
: T extends DesignToken.Type.FontFamily
208-
? DesignToken.FontFamily
209-
: T extends DesignToken.Type.FontWeight
210-
? DesignToken.FontWeight
211-
: T extends DesignToken.Type.Gradient
212-
? DesignToken.Gradient
213-
: T extends DesignToken.Type.Number
214-
? DesignToken.Number
215-
: T extends DesignToken.Type.Shadow
216-
? DesignToken.Shadow
217-
: T extends DesignToken.Type.StrokeStyle
218-
? DesignToken.StrokeStyle
219-
: T extends DesignToken.Type.Transition
220-
? DesignToken.Transition
221-
: T extends DesignToken.Type.Typography
222-
? DesignToken.Typography
223-
: never;
224-
225193
/**
226194
* @internal
227195
*/
@@ -285,37 +253,6 @@ export namespace DesignToken {
285253
? DesignToken.Typography
286254
: never;
287255

288-
/**
289-
* @internal
290-
*/
291-
export type ValueByType<T> = T extends DesignToken.Values.Border
292-
? DesignToken.Type.Border
293-
: T extends DesignToken.Values.Color
294-
? DesignToken.Type.Color
295-
: T extends DesignToken.Values.CubicBezier
296-
? DesignToken.Type.CubicBezier
297-
: T extends DesignToken.Values.Dimension
298-
? DesignToken.Type.Dimension
299-
: T extends DesignToken.Values.Duration
300-
? DesignToken.Type.Duration
301-
: T extends DesignToken.Values.FontFamily
302-
? DesignToken.Type.FontFamily
303-
: T extends DesignToken.Values.FontWeight
304-
? DesignToken.Type.FontWeight
305-
: T extends DesignToken.Values.Gradient
306-
? DesignToken.Type.Gradient
307-
: T extends DesignToken.Values.Number
308-
? DesignToken.Type.Number
309-
: T extends DesignToken.Values.Shadow
310-
? DesignToken.Type.Shadow
311-
: T extends DesignToken.Values.StrokeStyle
312-
? DesignToken.Type.StrokeStyle
313-
: T extends DesignToken.Values.Transition
314-
? DesignToken.Type.Transition
315-
: T extends DesignToken.Values.Typography
316-
? DesignToken.Type.Typography
317-
: never;
318-
319256
/**
320257
* @internal
321258
*/

src/lib/library.ts

Lines changed: 48 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -37,32 +37,53 @@ export namespace Library {
3737
: never;
3838
};
3939

40+
export const DerivedSymbol = Symbol.for("design-token-library::derived");
41+
4042
/**
41-
* A token value that serves as an alias to another token value
43+
* A token value that derives a value from context
4244
*
4345
* @public
4446
*/
45-
export type Alias<T extends DesignToken.Any, R extends Context<any>> = (
46-
context: R
47-
) => T | DesignToken.ValueByToken<T>;
47+
export type DerivedSource<
48+
T extends DesignToken.Any,
49+
R extends Context<any>
50+
> = (context: R) => T | DesignToken.ValueByToken<T>;
51+
export type Derived<
52+
T extends DesignToken.Any,
53+
R extends Context<any>
54+
> = DerivedSource<T, R> & { [DerivedSymbol]: typeof DerivedSymbol };
55+
56+
export function derive<T extends DesignToken.Any, R extends Context<any>>(
57+
value: DerivedSource<T, R>
58+
): Derived<T, R> {
59+
if (isDerived<T, R>(value)) {
60+
return value;
61+
}
62+
63+
Reflect.defineProperty(value, DerivedSymbol, {
64+
value: DerivedSymbol,
65+
});
66+
67+
return value as Derived<T, R>;
68+
}
4869

4970
/**
50-
* An {@link (Library:namespace).Alias} that supports complex token value types
71+
* An {@link (Library:namespace).Derived} that supports complex token value types
5172
* such as {@link DesignToken.Border}
5273
*
5374
* @public
5475
*/
55-
export type DeepAlias<
76+
export type DeepDerived<
5677
V extends DesignToken.Values.Any,
5778
T extends Context<any>
5879
> = {
5980
[K in keyof V]: V[K] extends DesignToken.Values.Any
60-
? V[K] | Alias<DesignToken.TokenByValue<V[K]>, T> | DeepAlias<V[K], T>
81+
? V[K] | Derived<DesignToken.TokenByValue<V[K]>, T> | DeepDerived<V[K], T>
6182
: never;
6283
};
6384

6485
/**
65-
* Context object provided to {@link (Library:namespace).Alias} values at runtime
86+
* Context object provided to {@link (Library:namespace).Derived} values at runtime
6687
*
6788
* @public
6889
*/
@@ -82,7 +103,7 @@ export namespace Library {
82103
* @public
83104
*/
84105
export type Token<T extends DesignToken.Any, C extends {}> = {
85-
set(value: DesignToken.ValueByToken<T> | Alias<T, C>): void;
106+
set(value: DesignToken.ValueByToken<T> | Derived<T, C>): void;
86107
toString(): string;
87108
readonly type: DesignToken.TypeByToken<T>;
88109
readonly extensions: Record<string, any>;
@@ -114,8 +135,8 @@ export namespace Library {
114135
// in Library.create is untyped, it cannot be inferred, so use T | ...
115136
| (Omit<T, "value"> & {
116137
value:
117-
| Library.Alias<T, Context<R>>
118-
| Library.DeepAlias<DesignToken.ValueByToken<T>, Context<R>>;
138+
| Library.Derived<T, Context<R>>
139+
| Library.DeepDerived<DesignToken.ValueByToken<T>, Context<R>>;
119140
});
120141

121142
/**
@@ -147,10 +168,14 @@ const isGroup = (
147168
return isObject(value) && !isToken(value);
148169
};
149170

150-
const isAlias = <T extends DesignToken.Any, K extends {}>(
171+
const isDerived = <T extends DesignToken.Any, K extends {}>(
151172
value: any
152-
): value is Library.Alias<T, K> => {
153-
return typeof value === "function";
173+
): value is Library.Derived<T, K> => {
174+
try {
175+
return Reflect.get(value, Library.DerivedSymbol) === Library.DerivedSymbol;
176+
} catch (e) {
177+
return false;
178+
}
154179
};
155180

156181
const recurseCreate = (
@@ -201,8 +226,8 @@ const recurseCreate = (
201226
);
202227
Reflect.defineProperty(library, key, {
203228
get() {
204-
// Token access needs to be tracked because an alias token
205-
// is a function that returns a token
229+
// Token access needs to be tracked because derived values
230+
// are a function that returns a token
206231
Watcher.track(token);
207232
return token;
208233
},
@@ -282,7 +307,7 @@ const recurseExtend = (
282307
);
283308
Reflect.defineProperty(extendedTokens, key, {
284309
get() {
285-
// Token access needs to be tracked because an alias token
310+
// Token access needs to be tracked because a derived value
286311
// is a function that returns a token
287312
Watcher.track(token);
288313
return token;
@@ -333,7 +358,7 @@ const recurseResolve = (value: any, context: Library.Context<any>) => {
333358
for (const key in value) {
334359
let v = value[key];
335360

336-
if (isAlias(v)) {
361+
if (isDerived(v)) {
337362
v = v(context);
338363
}
339364

@@ -387,16 +412,16 @@ class LibraryImpl<T extends {} = any> implements Library.Library<T> {
387412
class LibraryToken<T extends DesignToken.Any>
388413
implements
389414
Library.Token<any, any>,
390-
ISubscriber<Library.Alias<T, any>>,
415+
ISubscriber<Library.Derived<T, any>>,
391416
IWatcher
392417
{
393-
private raw: DesignToken.ValueByToken<T> | Library.Alias<T, any>;
418+
private raw: DesignToken.ValueByToken<T> | Library.Derived<T, any>;
394419
private cached: DesignToken.ValueByToken<T> | typeof empty = empty;
395420
private subscriptions: Set<INotifier<any>> = new Set();
396421

397422
constructor(
398423
public readonly name: string,
399-
value: DesignToken.ValueByToken<T> | Library.Alias<T, any>,
424+
value: DesignToken.ValueByToken<T> | Library.Derived<T, any>,
400425
private readonly _type: DesignToken.TypeByToken<T>,
401426
private readonly context: Library.Context<any>,
402427
private readonly _description: string,
@@ -429,7 +454,7 @@ class LibraryToken<T extends DesignToken.Any>
429454

430455
this.disconnect();
431456
const stopWatching = Watcher.use(this);
432-
const raw = isAlias(this.raw) ? this.raw(this.context) : this.raw;
457+
const raw = isDerived(this.raw) ? this.raw(this.context) : this.raw;
433458
const normalized = isToken(raw) ? raw.value : raw;
434459

435460
const value = isObject(normalized)
@@ -442,7 +467,7 @@ class LibraryToken<T extends DesignToken.Any>
442467
return value;
443468
}
444469

445-
public set(value: DesignToken.ValueByToken<T> | Library.Alias<T, any>) {
470+
public set(value: DesignToken.ValueByToken<T> | Library.Derived<T, any>) {
446471
this.raw = value;
447472
this.onChange();
448473
}

0 commit comments

Comments
 (0)