Last active
July 19, 2023 23:47
-
-
Save yringler/cffebd0fd56db0ba9a630f0afc3e3d4f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const StyleDictionary = require('style-dictionary'); | |
/** | |
* @description Some tokens are composites, defined with several other tokens. For example, typography. It is convenient to be able to have | |
* a single token which fully defines everything we need, but | |
* 1) Sometimes they can't. For example, css `type` can't define `letter-spacing`. | |
* 2) Sometimes we want to access a particular value separately. For example, the width of a border. | |
* | |
* This base class provides the foundation to extract a single expansion from a particular type of composite token. | |
* In the future, if we need to expand multiple components, we'll add that functionality. | |
*/ | |
class TokenExpander { | |
/** @type {StyleDictionary.Dictionary} */ | |
_dictionary; | |
/** @type {boolean} */ | |
_outputReferences; | |
/** | |
* @description The suffix which should be added to any new tokens. For example, -width might be added to --border-large. | |
* @type {string} | |
*/ | |
_suffix; | |
/** | |
* @description The token type which the expander applies to. For example, "border". | |
* @type {string} | |
*/ | |
_type; | |
constructor(dictionary, outputReferences) { | |
this._dictionary = dictionary; | |
this._outputReferences = outputReferences; | |
} | |
/** | |
* @description Given a composite token, it returns all the css rules which are needed to describe it. | |
* @argument token {StyleDictionary.TransformedToken} | |
* @returns {string} | |
*/ | |
getExpandedToken(token) { | |
if (token.type != this._type) { | |
return null; | |
} | |
const original = token.original; | |
/* | |
* A composite token can either be an object, which defines each part (font size, line height, etc). | |
* Or it might be an alias (a string) which references another token. | |
*/ | |
// If it contains the data we need, use that data. | |
if (typeof original.value == 'object') { | |
return this._getCssRule(token); | |
} else { | |
// If it's a reference, get the value that it's referring to. | |
// Note that if outputReferences is true, instead of returning the source tokens value, it'll return a | |
// var(--...) based on the source tokens name. | |
if (!this._dictionary.usesReference(original.value)) { | |
throw "I thought there must be a reference."; | |
} | |
return this._getCssRule(this._dictionary.getReferences(original.value)[0]); | |
} | |
} | |
/** | |
* @description Converts the token to valid css. Eg `--token-name: 23px;` | |
* @private | |
* @argument token {StyleDictionary.TransformedToken} | |
* @returns {string} | |
*/ | |
_getCssRule(token) { | |
let value = this.getValueToExpand(token.original); | |
// The value we're looking for doesn't necessarily exist. For example, not all typography tokens specify letter spacing. | |
if (!value) { | |
return null; | |
} | |
const name = ` --${token.name}-${this._suffix}`; | |
if (this._dictionary.usesReference(value)) { | |
const source = this._dictionary.getReferences(value)[0]; | |
value = this._outputReferences ? `var(--${source.name})` : source.value; | |
} | |
return `${name}: ${value};`; | |
} | |
/** | |
* @description Get the value which will be used to create the new token. For example, the width of the border `value.width`. | |
* @protected | |
* @argument token {StyleDictionary.DesignToken} | |
*/ | |
getValueToExpand(token) { | |
throw "Not implemented"; | |
} | |
} | |
module.exports = { | |
TokenExpander | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const { TokenExpander } = require("./token-expander"); | |
class TypeExpander extends TokenExpander { | |
/** @inheritdoc */ | |
_suffix = 'letter-spacing'; | |
/** @inheritdoc */ | |
_type = 'typography'; | |
constructor(dictionary, outputReferences) { | |
super(dictionary, outputReferences); | |
} | |
/** | |
* @inheritdoc | |
* @argument token {StyleDictionary.DesignToken} | |
*/ | |
getValueToExpand(token) { | |
return token.value?.letterSpacing || null; | |
} | |
} | |
module.exports = { | |
TypeExpander | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment