@primer/primitives 7.16.0 → 7.17.0-rc.1685583f

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.
Files changed (259) hide show
  1. package/dist/styleLint/base/size/size.json +427 -0
  2. package/dist/styleLint/base/typography/typography.json +54 -0
  3. package/dist/styleLint/functional/motion/motion.json +47 -0
  4. package/dist/styleLint/functional/size/border.json +234 -0
  5. package/dist/styleLint/functional/size/breakpoints.json +152 -0
  6. package/dist/styleLint/functional/size/size-coarse.json +41 -0
  7. package/dist/styleLint/functional/size/size-fine.json +41 -0
  8. package/dist/styleLint/functional/size/size.json +1838 -0
  9. package/dist/styleLint/functional/size/viewport.json +80 -0
  10. package/dist/styleLint/functional/themes/dark-colorblind.json +16155 -0
  11. package/dist/styleLint/functional/themes/dark-dimmed.json +16159 -0
  12. package/dist/styleLint/functional/themes/dark-high-contrast.json +16175 -0
  13. package/dist/styleLint/functional/themes/dark-tritanopia.json +16161 -0
  14. package/dist/styleLint/functional/themes/dark.json +16159 -0
  15. package/dist/styleLint/functional/themes/light-colorblind.json +16123 -0
  16. package/dist/styleLint/functional/themes/light-high-contrast.json +16125 -0
  17. package/dist/styleLint/functional/themes/light-tritanopia.json +16115 -0
  18. package/dist/styleLint/functional/themes/light.json +16113 -0
  19. package/dist/styleLint/functional/typography/typography.json +663 -0
  20. package/package.json +11 -9
  21. package/src/PrimerStyleDictionary.ts +226 -0
  22. package/src/filters/index.ts +12 -0
  23. package/src/filters/isBorder.ts +10 -0
  24. package/src/filters/isColor.ts +10 -0
  25. package/src/filters/isColorWithAlpha.ts +11 -0
  26. package/src/filters/isColorWithMix.ts +33 -0
  27. package/src/filters/isDeprecated.ts +10 -0
  28. package/src/filters/isDimension.ts +10 -0
  29. package/src/filters/isDuration.ts +10 -0
  30. package/src/filters/isFontFamily.ts +10 -0
  31. package/src/filters/isFontWeight.ts +10 -0
  32. package/src/filters/isFromFile.ts +12 -0
  33. package/src/filters/isShadow.ts +10 -0
  34. package/src/filters/isSource.ts +10 -0
  35. package/src/filters/isTypography.ts +10 -0
  36. package/src/formats/cssCustomMedia.ts +24 -0
  37. package/src/formats/cssThemed.ts +35 -0
  38. package/src/formats/cssVariables.ts +25 -0
  39. package/src/formats/cssWrapMediaQuery.ts +29 -0
  40. package/src/formats/index.ts +11 -0
  41. package/src/formats/javascriptCommonJs.ts +21 -0
  42. package/src/formats/javascriptEsm.ts +21 -0
  43. package/src/formats/jsonFigma.ts +131 -0
  44. package/src/formats/jsonNestedPrefixed.ts +23 -0
  45. package/src/formats/jsonOneDimensional.ts +18 -0
  46. package/src/formats/jsonPostCssFallback.ts +16 -0
  47. package/src/formats/typescriptExportDefinition.ts +170 -0
  48. package/src/formats/utilities/jsonToFlat.ts +10 -0
  49. package/src/formats/utilities/jsonToNestedValue.ts +20 -0
  50. package/src/formats/utilities/prefixTokens.ts +17 -0
  51. package/src/parsers/index.ts +1 -0
  52. package/src/parsers/w3cJsonParser.ts +25 -0
  53. package/src/platforms/css.ts +93 -0
  54. package/src/platforms/deprecatedJson.ts +16 -0
  55. package/src/platforms/docJson.ts +34 -0
  56. package/src/platforms/fallbacks.ts +34 -0
  57. package/src/platforms/figma.ts +48 -0
  58. package/src/platforms/index.ts +10 -0
  59. package/src/platforms/javascript.ts +30 -0
  60. package/src/platforms/json.ts +32 -0
  61. package/src/platforms/styleLint.ts +34 -0
  62. package/src/platforms/typeDefinitions.ts +30 -0
  63. package/src/platforms/typescript.ts +30 -0
  64. package/src/schemas/alphaValue.ts +12 -0
  65. package/src/schemas/baseToken.ts +7 -0
  66. package/src/schemas/borderToken.ts +19 -0
  67. package/src/schemas/collections.ts +47 -0
  68. package/src/schemas/colorHexValue.ts +18 -0
  69. package/src/schemas/colorToken.ts +50 -0
  70. package/src/schemas/designToken.ts +38 -0
  71. package/src/schemas/dimensionToken.ts +22 -0
  72. package/src/schemas/dimensionValue.ts +16 -0
  73. package/src/schemas/durationToken.ts +12 -0
  74. package/src/schemas/durationValue.ts +9 -0
  75. package/src/schemas/fontFamilyToken.ts +11 -0
  76. package/src/schemas/fontWeightToken.ts +12 -0
  77. package/src/schemas/fontWeightValue.ts +14 -0
  78. package/src/schemas/numberToken.ts +11 -0
  79. package/src/schemas/referenceValue.ts +12 -0
  80. package/src/schemas/scopes.ts +16 -0
  81. package/src/schemas/shadowToken.ts +45 -0
  82. package/src/schemas/stringToken.ts +11 -0
  83. package/src/schemas/tokenName.ts +12 -0
  84. package/src/schemas/tokenType.ts +4 -0
  85. package/src/schemas/typographyToken.ts +20 -0
  86. package/src/schemas/validTokenType.ts +44 -0
  87. package/src/schemas/viewportRangeToken.ts +11 -0
  88. package/src/test-utilities/getMockDictionary.ts +22 -0
  89. package/src/test-utilities/getMockFormatterArguments.ts +21 -0
  90. package/src/test-utilities/getMockParserInput.ts +72 -0
  91. package/src/test-utilities/getMockToken.ts +25 -0
  92. package/src/test-utilities/index.ts +4 -0
  93. package/src/tokens/base/color/dark/dark.dimmed.json5 +1326 -0
  94. package/src/tokens/base/color/dark/dark.high-contrast.json5 +856 -0
  95. package/src/tokens/base/color/dark/dark.json5 +866 -0
  96. package/src/tokens/base/color/dark/display-dark.json5 +1774 -0
  97. package/src/tokens/base/color/light/display-light.json5 +1774 -0
  98. package/src/tokens/base/color/light/light.high-contrast.json5 +847 -0
  99. package/src/tokens/base/color/light/light.json5 +866 -0
  100. package/src/tokens/base/size/size.json +176 -0
  101. package/src/tokens/base/typography/typography.json +24 -0
  102. package/src/tokens/fallback/color-fallbacks.json +260 -0
  103. package/src/tokens/functional/border/dark.json5 +12 -0
  104. package/src/tokens/functional/border/light.json5 +12 -0
  105. package/src/tokens/functional/color/dark/app-dark.json5 +554 -0
  106. package/src/tokens/functional/color/dark/data-vis-dark.json5 +144 -0
  107. package/src/tokens/functional/color/dark/display-dark.json5 +1060 -0
  108. package/src/tokens/functional/color/dark/overrides/dark.dimmed.json5 +57 -0
  109. package/src/tokens/functional/color/dark/overrides/dark.high-contrast.json5 +390 -0
  110. package/src/tokens/functional/color/dark/overrides/dark.protanopia-deuteranopia.json5 +314 -0
  111. package/src/tokens/functional/color/dark/overrides/dark.tritanopia.json5 +229 -0
  112. package/src/tokens/functional/color/dark/patterns-dark.json5 +3073 -0
  113. package/src/tokens/functional/color/dark/primitives-dark.json5 +1206 -0
  114. package/src/tokens/functional/color/dark/syntax-dark.json5 +559 -0
  115. package/src/tokens/functional/color/light/app-light.json5 +551 -0
  116. package/src/tokens/functional/color/light/data-vis-light.json5 +144 -0
  117. package/src/tokens/functional/color/light/display-light.json5 +1060 -0
  118. package/src/tokens/functional/color/light/overrides/light.high-contrast.json5 +440 -0
  119. package/src/tokens/functional/color/light/overrides/light.protanopia-deuteranopia.json5 +340 -0
  120. package/src/tokens/functional/color/light/overrides/light.tritanopia.json5 +249 -0
  121. package/src/tokens/functional/color/light/patterns-light.json5 +3070 -0
  122. package/src/tokens/functional/color/light/primitives-light.json5 +1196 -0
  123. package/src/tokens/functional/color/light/syntax-light.json5 +559 -0
  124. package/src/tokens/functional/motion/loading.json5 +17 -0
  125. package/src/tokens/functional/motion/patterns.json5 +28 -0
  126. package/src/tokens/functional/shadow/dark.json5 +383 -0
  127. package/src/tokens/functional/shadow/light.json5 +376 -0
  128. package/src/tokens/functional/size/border.json +98 -0
  129. package/src/tokens/functional/size/breakpoints.json +64 -0
  130. package/src/tokens/functional/size/size-coarse.json +28 -0
  131. package/src/tokens/functional/size/size-fine.json +28 -0
  132. package/src/tokens/functional/size/size.json +802 -0
  133. package/src/tokens/functional/size/viewport.json +28 -0
  134. package/src/tokens/functional/typography/typography.json +279 -0
  135. package/src/tokens/removed/color.json +421 -0
  136. package/src/transformers/borderToCss.ts +38 -0
  137. package/src/transformers/colorToHex.ts +16 -0
  138. package/src/transformers/colorToHexAlpha.ts +23 -0
  139. package/src/transformers/colorToHexMix.ts +19 -0
  140. package/src/transformers/colorToRgbAlpha.ts +19 -0
  141. package/src/transformers/colorToRgbaFloat.ts +45 -0
  142. package/src/transformers/dimensionToPixelUnitless.ts +60 -0
  143. package/src/transformers/dimensionToRem.ts +56 -0
  144. package/src/transformers/dimensionToRemPxArray.ts +60 -0
  145. package/src/transformers/durationToCss.ts +29 -0
  146. package/src/transformers/figmaAttributes.ts +55 -0
  147. package/src/transformers/fontFamilyToCss.ts +38 -0
  148. package/src/transformers/fontWeightToNumber.ts +53 -0
  149. package/src/transformers/index.ts +21 -0
  150. package/src/transformers/jsonDeprecated.ts +15 -0
  151. package/src/transformers/namePathToCamelCase.ts +14 -0
  152. package/src/transformers/namePathToDotNotation.ts +34 -0
  153. package/src/transformers/namePathToFigma.ts +28 -0
  154. package/src/transformers/namePathToKebabCase.ts +19 -0
  155. package/src/transformers/namePathToSlashNotation.ts +19 -0
  156. package/src/transformers/shadowToCss.ts +37 -0
  157. package/src/transformers/typographyToCss.ts +31 -0
  158. package/src/transformers/utilities/alpha.ts +23 -0
  159. package/src/transformers/utilities/checkRequiredTokenProperties.ts +16 -0
  160. package/src/transformers/utilities/getTokenValue.ts +18 -0
  161. package/src/transformers/utilities/hexToRgbaFloat.ts +31 -0
  162. package/src/transformers/utilities/invalidTokenError.ts +34 -0
  163. package/src/transformers/utilities/isRgbaFloat.ts +29 -0
  164. package/src/transformers/utilities/mix.ts +46 -0
  165. package/src/transformers/utilities/rgbaFloatToHex.ts +15 -0
  166. package/src/types/Border.d.ts +5 -0
  167. package/src/types/BorderTokenValue.d.ts +10 -0
  168. package/src/types/ColorHex.d.ts +4 -0
  169. package/src/types/PlatformInitializer.d.ts +11 -0
  170. package/src/types/Shadow.d.ts +5 -0
  171. package/src/types/ShadowTokenValue.d.ts +14 -0
  172. package/src/types/SizeEm.d.ts +4 -0
  173. package/src/types/SizePx.d.ts +4 -0
  174. package/src/types/SizeRem.d.ts +4 -0
  175. package/src/types/StyleDictionaryConfigGenerator.d.ts +15 -0
  176. package/src/types/TokenBuildInput.d.ts +8 -0
  177. package/src/types/TypographyTokenValue.d.ts +12 -0
  178. package/src/types/w3cTransformedToken.d.ts +8 -0
  179. package/src/utilities/copyFromDir.ts +21 -0
  180. package/src/utilities/getFlag.ts +12 -0
  181. package/src/utilities/index.ts +3 -0
  182. package/src/utilities/joinFriendly.ts +2 -0
  183. package/src/utilities/schemaErrorMessage.ts +2 -0
  184. package/src/utilities/toCamelCase.ts +29 -0
  185. package/src/utilities/treeWalker.ts +27 -0
  186. package/src/utilities/upperCaseFirstCharacter.ts +10 -0
  187. package/src/utils-v1.ts +36 -0
  188. package/tokens-next-private/styleLint/base/size/size.json +427 -0
  189. package/tokens-next-private/styleLint/base/typography/typography.json +54 -0
  190. package/tokens-next-private/styleLint/functional/motion/motion.json +47 -0
  191. package/tokens-next-private/styleLint/functional/size/border.json +234 -0
  192. package/tokens-next-private/styleLint/functional/size/breakpoints.json +152 -0
  193. package/tokens-next-private/styleLint/functional/size/size-coarse.json +41 -0
  194. package/tokens-next-private/styleLint/functional/size/size-fine.json +41 -0
  195. package/tokens-next-private/styleLint/functional/size/size.json +1838 -0
  196. package/tokens-next-private/styleLint/functional/size/viewport.json +80 -0
  197. package/tokens-next-private/styleLint/functional/themes/dark-colorblind.json +16155 -0
  198. package/tokens-next-private/styleLint/functional/themes/dark-dimmed.json +16159 -0
  199. package/tokens-next-private/styleLint/functional/themes/dark-high-contrast.json +16175 -0
  200. package/tokens-next-private/styleLint/functional/themes/dark-tritanopia.json +16161 -0
  201. package/tokens-next-private/styleLint/functional/themes/dark.json +16159 -0
  202. package/tokens-next-private/styleLint/functional/themes/light-colorblind.json +16123 -0
  203. package/tokens-next-private/styleLint/functional/themes/light-high-contrast.json +16125 -0
  204. package/tokens-next-private/styleLint/functional/themes/light-tritanopia.json +16115 -0
  205. package/tokens-next-private/styleLint/functional/themes/light.json +16113 -0
  206. package/tokens-next-private/styleLint/functional/typography/typography.json +663 -0
  207. package/tokens-v2-private/css/tokens/base/size/size.css +1 -1
  208. package/tokens-v2-private/css/tokens/base/typography/typography.css +1 -1
  209. package/tokens-v2-private/css/tokens/functional/size/border.css +1 -1
  210. package/tokens-v2-private/css/tokens/functional/size/breakpoints.css +1 -1
  211. package/tokens-v2-private/css/tokens/functional/size/size-coarse.css +1 -1
  212. package/tokens-v2-private/css/tokens/functional/size/size-fine.css +1 -1
  213. package/tokens-v2-private/css/tokens/functional/size/size.css +1 -1
  214. package/tokens-v2-private/css/tokens/functional/typography/typography.css +1 -1
  215. package/tokens-v2-private/js/module/tokens/base/size/size.js +1 -1
  216. package/tokens-v2-private/js/module/tokens/base/typography/typography.js +1 -1
  217. package/tokens-v2-private/js/module/tokens/functional/size/border.js +1 -1
  218. package/tokens-v2-private/js/module/tokens/functional/size/breakpoints.js +1 -1
  219. package/tokens-v2-private/js/module/tokens/functional/size/size-coarse.js +1 -1
  220. package/tokens-v2-private/js/module/tokens/functional/size/size-fine.js +1 -1
  221. package/tokens-v2-private/js/module/tokens/functional/size/size.js +1 -1
  222. package/tokens-v2-private/js/module/tokens/functional/size/viewport.js +1 -1
  223. package/tokens-v2-private/js/module/tokens/functional/typography/typography.js +1 -1
  224. package/tokens-v2-private/js/tokens/base/size/size.js +1 -1
  225. package/tokens-v2-private/js/tokens/base/typography/typography.js +1 -1
  226. package/tokens-v2-private/js/tokens/functional/size/border.js +1 -1
  227. package/tokens-v2-private/js/tokens/functional/size/breakpoints.js +1 -1
  228. package/tokens-v2-private/js/tokens/functional/size/size-coarse.js +1 -1
  229. package/tokens-v2-private/js/tokens/functional/size/size-fine.js +1 -1
  230. package/tokens-v2-private/js/tokens/functional/size/size.js +1 -1
  231. package/tokens-v2-private/js/tokens/functional/size/viewport.js +1 -1
  232. package/tokens-v2-private/js/tokens/functional/typography/typography.js +1 -1
  233. package/tokens-v2-private/scss/tokens/base/size/size.scss +1 -1
  234. package/tokens-v2-private/scss/tokens/base/typography/typography.scss +1 -1
  235. package/tokens-v2-private/scss/tokens/functional/size/border.scss +1 -1
  236. package/tokens-v2-private/scss/tokens/functional/size/breakpoints.scss +1 -1
  237. package/tokens-v2-private/scss/tokens/functional/size/size-coarse.scss +1 -1
  238. package/tokens-v2-private/scss/tokens/functional/size/size-fine.scss +1 -1
  239. package/tokens-v2-private/scss/tokens/functional/size/size.scss +1 -1
  240. package/tokens-v2-private/scss/tokens/functional/size/viewport.scss +1 -1
  241. package/tokens-v2-private/scss/tokens/functional/typography/typography.scss +1 -1
  242. package/tokens-v2-private/ts/tokens/base/size/size.d.ts +1 -1
  243. package/tokens-v2-private/ts/tokens/base/size/size.js +1 -1
  244. package/tokens-v2-private/ts/tokens/base/typography/typography.d.ts +1 -1
  245. package/tokens-v2-private/ts/tokens/base/typography/typography.js +1 -1
  246. package/tokens-v2-private/ts/tokens/functional/size/border.d.ts +1 -1
  247. package/tokens-v2-private/ts/tokens/functional/size/border.js +1 -1
  248. package/tokens-v2-private/ts/tokens/functional/size/breakpoints.d.ts +1 -1
  249. package/tokens-v2-private/ts/tokens/functional/size/breakpoints.js +1 -1
  250. package/tokens-v2-private/ts/tokens/functional/size/size-coarse.d.ts +1 -1
  251. package/tokens-v2-private/ts/tokens/functional/size/size-coarse.js +1 -1
  252. package/tokens-v2-private/ts/tokens/functional/size/size-fine.d.ts +1 -1
  253. package/tokens-v2-private/ts/tokens/functional/size/size-fine.js +1 -1
  254. package/tokens-v2-private/ts/tokens/functional/size/size.d.ts +1 -1
  255. package/tokens-v2-private/ts/tokens/functional/size/size.js +1 -1
  256. package/tokens-v2-private/ts/tokens/functional/size/viewport.d.ts +1 -1
  257. package/tokens-v2-private/ts/tokens/functional/size/viewport.js +1 -1
  258. package/tokens-v2-private/ts/tokens/functional/typography/typography.d.ts +1 -1
  259. package/tokens-v2-private/ts/tokens/functional/typography/typography.js +1 -1
@@ -0,0 +1,131 @@
1
+ import StyleDictionary from 'style-dictionary'
2
+ import {format} from 'prettier'
3
+ import type {FormatterArguments} from 'style-dictionary/types/Format'
4
+ import {transformNamePathToFigma} from '../transformers/namePathToFigma'
5
+ import type {ShadowTokenValue} from '../types/ShadowTokenValue'
6
+ import {hexToRgbaFloat} from '../transformers/utilities/hexToRgbaFloat'
7
+ import type {RgbaFloat} from '../transformers/utilities/isRgbaFloat'
8
+ import {isRgbaFloat} from '../transformers/utilities/isRgbaFloat'
9
+ const {sortByReference} = StyleDictionary.formatHelpers
10
+
11
+ const isReference = (string: string): boolean => /^\{([^\\]*)\}$/g.test(string)
12
+
13
+ const getReference = (
14
+ dictionary: StyleDictionary.Dictionary,
15
+ refString: string,
16
+ platform: StyleDictionary.Platform,
17
+ ) => {
18
+ if (isReference(refString)) {
19
+ // retrieve reference token
20
+ const refToken = dictionary.getReferences(refString)[0]
21
+ // return full reference
22
+ return [refToken.attributes?.collection, transformNamePathToFigma(refToken, platform)].filter(Boolean).join('/')
23
+ }
24
+ }
25
+
26
+ const getFigmaType = (type: string): string => {
27
+ const validTypes = {
28
+ color: 'COLOR',
29
+ dimension: 'FLOAT',
30
+ }
31
+ if (type in validTypes) return validTypes[type as keyof typeof validTypes]
32
+ throw new Error(`Invalid type: ${type}`)
33
+ }
34
+
35
+ const shadowToVariables = (
36
+ name: string,
37
+ values: Omit<ShadowTokenValue, 'color'> & {color: string | RgbaFloat},
38
+ token: StyleDictionary.TransformedToken,
39
+ ) => {
40
+ // floatValue
41
+ const floatValue = (property: 'offsetX' | 'offsetY' | 'blur' | 'spread') => ({
42
+ name: `${name}/${property}`,
43
+ value: parseInt(values[property].replace('px', '')),
44
+ type: 'FLOAT',
45
+ scopes: ['EFFECT_FLOAT'],
46
+ mode,
47
+ collection,
48
+ group,
49
+ })
50
+
51
+ const {attributes} = token
52
+ const {mode, collection, group} = attributes || {}
53
+
54
+ return [
55
+ floatValue('offsetX'),
56
+ floatValue('offsetY'),
57
+ floatValue('blur'),
58
+ floatValue('spread'),
59
+ {
60
+ name: `${name}/color`,
61
+ value: isRgbaFloat(values.color)
62
+ ? {...values.color, ...(values.alpha ? {a: values.alpha} : {})}
63
+ : hexToRgbaFloat(values.color, values.alpha),
64
+ type: 'COLOR',
65
+ scopes: ['EFFECT_COLOR'],
66
+ mode,
67
+ collection,
68
+ group,
69
+ },
70
+ ]
71
+ }
72
+
73
+ /**
74
+ * @description Converts `StyleDictionary.dictionary.tokens` to javascript esm (javascript export statement)
75
+ * @param arguments [FormatterArguments](https://github.com/amzn/style-dictionary/blob/main/types/Format.d.ts)
76
+ * @returns formatted `string`
77
+ */
78
+ export const jsonFigma: StyleDictionary.Formatter = ({dictionary, file: _file, platform}: FormatterArguments) => {
79
+ // array to store tokens in
80
+ const tokens: Record<string, unknown>[] = []
81
+ // loop through tokens sorted by reference
82
+ for (const token of dictionary.allTokens.sort(sortByReference(dictionary))) {
83
+ // deconstruct token
84
+ const {attributes, value, $type, comment: description, original, alpha, mix} = token
85
+ const {mode, collection, scopes, group, codeSyntax} = attributes || {}
86
+ // shadows need to be specifically dealt with
87
+ if ($type === 'shadow') {
88
+ const shadowValues = !Array.isArray(value) ? [value] : value
89
+ // if only one set of shadow values is present
90
+ if (shadowValues.length === 1) {
91
+ tokens.push(
92
+ ...shadowToVariables(token.name, shadowValues[0], {
93
+ ...token,
94
+ ...(platform.mode ? {mode: platform.mode} : {}),
95
+ }),
96
+ )
97
+ } else {
98
+ // if multiple shadow sets values are present we need loop through them and add the index to the name
99
+ for (const [index, stepValue] of shadowValues.entries()) {
100
+ tokens.push(
101
+ ...shadowToVariables(`${token.name}/${index + 1}`, stepValue, {
102
+ ...token,
103
+ ...(platform.mode ? {mode: platform.mode} : {}),
104
+ }),
105
+ )
106
+ }
107
+ }
108
+ // other tokens just get added to tokens array
109
+ } else {
110
+ tokens.push({
111
+ name: token.name,
112
+ value,
113
+ type: getFigmaType($type),
114
+ alpha,
115
+ isMix: mix ? true : undefined,
116
+ description,
117
+ refId: [collection, token.name].filter(Boolean).join('/'),
118
+ reference: getReference(dictionary, original.value, platform),
119
+ collection,
120
+ mode,
121
+ group,
122
+ scopes,
123
+ codeSyntax,
124
+ })
125
+ }
126
+ }
127
+ // add file header and convert output
128
+ const output = JSON.stringify(tokens, null, 2)
129
+ // return prettified
130
+ return format(output, {parser: 'json', printWidth: 500})
131
+ }
@@ -0,0 +1,23 @@
1
+ import type StyleDictionary from 'style-dictionary'
2
+ import {format} from 'prettier'
3
+ import {prefixTokens} from './utilities/prefixTokens'
4
+ import {jsonToNestedValue} from './utilities/jsonToNestedValue'
5
+
6
+ /**
7
+ * @description Takes a style dictionary token dictionary and converts it to a nested json string.
8
+ * In contrast to the `json/nested` this formatter does add a prefix if provided
9
+ * @param StyleDictionary.FormatterArguments
10
+ * @returns formatted json `string`
11
+ */
12
+ export const jsonNestedPrefixed: StyleDictionary.Formatter = ({dictionary, file: _file, options, platform}) => {
13
+ const {outputVerbose} = options
14
+ // add prefix if defined
15
+ let tokens = prefixTokens(dictionary.tokens, platform)
16
+ if (!outputVerbose) {
17
+ tokens = jsonToNestedValue(tokens)
18
+ }
19
+ // add file header and convert output
20
+ const output = JSON.stringify(tokens, null, 2)
21
+ // return prettified
22
+ return format(output, {parser: 'json', printWidth: 500})
23
+ }
@@ -0,0 +1,18 @@
1
+ import type StyleDictionary from 'style-dictionary'
2
+ import {format} from 'prettier'
3
+ import {jsonToFlat} from './utilities/jsonToFlat'
4
+ /**
5
+ * @description Takes a style dictionary token dictionary and converts it to a one dimensional json object.
6
+ * @param StyleDictionary.FormatterArguments
7
+ * @param options.nameSeparator - separator to use for nested token name
8
+ * @returns formatted json `string`
9
+ */
10
+ export const jsonOneDimensional: StyleDictionary.Formatter = ({dictionary, file: _file, options}) => {
11
+ // option to allow verbose output (object) or just the value
12
+ const {outputVerbose} = options
13
+ const tokens = jsonToFlat(dictionary.allTokens, outputVerbose)
14
+ // add file header and convert output
15
+ const output = JSON.stringify(tokens, null, 2)
16
+ // return prettified
17
+ return format(output, {parser: 'json', printWidth: 500})
18
+ }
@@ -0,0 +1,16 @@
1
+ import type StyleDictionary from 'style-dictionary'
2
+ import {format} from 'prettier'
3
+
4
+ /**
5
+ * @description Takes a style dictionary token dictionary and converts it to a one dimensional json object.
6
+ * @param StyleDictionary.FormatterArguments
7
+ * @param options.nameSeparator - separator to use for nested token name
8
+ * @returns formatted json `string`
9
+ */
10
+ export const jsonPostCssFallback: StyleDictionary.Formatter = ({dictionary, file: _file}) => {
11
+ const tokens = Object.fromEntries(dictionary.allTokens.map(token => [`--${token.name}`, token.value]))
12
+ // add file header and convert output
13
+ const output = JSON.stringify(tokens, null, 2)
14
+ // return prettified
15
+ return format(output, {parser: 'json', printWidth: 500})
16
+ }
@@ -0,0 +1,170 @@
1
+ import StyleDictionary from 'style-dictionary'
2
+ import {format} from 'prettier'
3
+ import fs = require('fs')
4
+ import path = require('path')
5
+ import {treeWalker} from '../utilities/treeWalker'
6
+
7
+ import type {FormatterArguments} from 'style-dictionary/types/Format'
8
+ import type {w3cTransformedToken} from '../types/w3cTransformedToken'
9
+ import {prefixTokens} from './utilities/prefixTokens'
10
+
11
+ const {fileHeader} = StyleDictionary.formatHelpers
12
+
13
+ /**
14
+ * unquoteTypes
15
+ * @description extract types from designTokenTypes (string with type definitions from file) and replace quoted types "Color" with unquoted Color
16
+ * @param output
17
+ * @param designTokenTypes
18
+ * @returns string with unquoted types
19
+ */
20
+ const unquoteTypes = (output: string, designTokenTypes: string[]): string => {
21
+ // join types for replacement
22
+ const regex = `"(${['number', 'string', 'any', ...designTokenTypes].join('|')})"`
23
+ // remove strings
24
+ return output.replace(new RegExp(regex, 'g'), '$1')
25
+ }
26
+
27
+ /**
28
+ * getTokenType
29
+ * @description extract content from token files
30
+ * @param path string
31
+ */
32
+ const getTokenType = (tokenTypesPath: string): string => {
33
+ try {
34
+ const designTokenType = fs.readFileSync(path.resolve(tokenTypesPath), {encoding: 'utf-8'})
35
+ return designTokenType
36
+ } catch (e) {
37
+ // eslint-disable-next-line no-console
38
+ throw new Error(`Error trying to load design token type from file "${tokenTypesPath}".`)
39
+ }
40
+ }
41
+
42
+ /**
43
+ * @description throws an error stating the token name, type and invalid value
44
+ * @param token w3cTransformedToken
45
+ */
46
+ const invalidTokenValueError = (token: w3cTransformedToken) => {
47
+ throw new Error(`Invalid token: "${token.name}" with type "${token.$type}" can not have a value of "${token.value}"`)
48
+ }
49
+ /**
50
+ * convertPropToType
51
+ * @description return take type attribute and return correct typescript type as string
52
+ * @param type
53
+ * @returns
54
+ */
55
+ const convertPropToType = (tree: w3cTransformedToken): string => {
56
+ if (!Object.prototype.hasOwnProperty.call(tree, 'value')) {
57
+ throw new Error(`Invalid token: ${tree}`)
58
+ }
59
+ switch (tree.$type) {
60
+ case 'color':
61
+ if (typeof tree.value === 'string' && tree.value[0] === '#') {
62
+ return 'ColorHex'
63
+ }
64
+ return invalidTokenValueError(tree)
65
+ case 'dimension':
66
+ if (typeof tree.value === 'string' && tree.value.substring(tree.value.length - 3) === 'rem') return 'SizeRem'
67
+ if (typeof tree.value === 'string' && tree.value.substring(tree.value.length - 2) === 'em') return 'SizeEm'
68
+ if (typeof tree.value === 'string' && tree.value.substring(tree.value.length - 2) === 'px') return 'SizePx'
69
+ return invalidTokenValueError(tree)
70
+ case 'shadow':
71
+ return 'Shadow'
72
+ case 'border':
73
+ return 'Border'
74
+ default:
75
+ if (typeof tree.value === 'number') return 'number'
76
+ if (typeof tree.value === 'string') return 'string'
77
+ if (typeof tree.value === 'boolean') return 'boolean'
78
+ return 'any'
79
+ }
80
+ }
81
+ /**
82
+ * a valid token node has a `value` property
83
+ * @param item object
84
+ * @returns boolean
85
+ */
86
+ const validTokenNode = (item: w3cTransformedToken | unknown): item is w3cTransformedToken => {
87
+ return typeof item === 'object' && item !== null && 'value' in item
88
+ }
89
+ /**
90
+ * returns a set with every used token type
91
+ * @param item object
92
+ * @param validTypes array, all other types will be removed
93
+ * @returns set of all used token types
94
+ */
95
+ const getUsedTokenTypes = (tokens: StyleDictionary.DesignTokens, validTypes: string[]): Set<string> => {
96
+ // using a set to assure every value only exists once
97
+ const usedTypes = new Set<string>()
98
+ // adds type to set
99
+ const callback = (tree: unknown) => usedTypes.add(convertPropToType(tree as w3cTransformedToken))
100
+ // tree walker adds to usedTypes
101
+ treeWalker(tokens, callback, validTokenNode)
102
+ // clean up types
103
+ for (const type of usedTypes) {
104
+ if (!validTypes.includes(type)) {
105
+ usedTypes.delete(type)
106
+ }
107
+ }
108
+ return usedTypes
109
+ }
110
+ /**
111
+ * returns the entire token object structure but instead of token values each token just has a typescript type
112
+ * @param item object
113
+ * @returns object
114
+ */
115
+ const getTokenObjectWithTypes = (tokens: StyleDictionary.DesignTokens): Record<string, unknown> => {
116
+ // TODO: FIX typescript issues
117
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
118
+ // @ts-ignore
119
+ return treeWalker(tokens, convertPropToType, validTokenNode) as Record<string, unknown>
120
+ }
121
+ /**
122
+ * getTypeDefinition
123
+ * @description returns type definitions as string
124
+ * @param tokens
125
+ * @param moduleName
126
+ * @param tokenTypesPath
127
+ * @returns string
128
+ */
129
+ const getTypeDefinition = (
130
+ tokens: StyleDictionary.DesignTokens,
131
+ moduleName: string,
132
+ tokenTypesPath: string,
133
+ ): string => {
134
+ const usedTypes = getUsedTokenTypes(tokens, ['ColorHex', 'Shadow', 'Border', 'SizeEm', 'SizeRem', 'SizePx'])
135
+ const tokenObjectWithTypes = getTokenObjectWithTypes(tokens)
136
+ // get token type declaration from file
137
+ const designTokenTypes: string[] = []
138
+ for (const type of usedTypes) {
139
+ // path to type files without trailing slash
140
+ const typePath = tokenTypesPath.replace(new RegExp(/\/$/, 'g'), '')
141
+
142
+ designTokenTypes.push(getTokenType(`${typePath}/${type}.d.ts`))
143
+ }
144
+ // build output
145
+ const output = `${designTokenTypes.join('\n')}
146
+ export type ${moduleName} = ${JSON.stringify(tokenObjectWithTypes, null, 2)}`
147
+
148
+ // JSON stringify will quote strings, because this is a type we need it unquoted.
149
+ return unquoteTypes(output, [...usedTypes])
150
+ }
151
+ /**
152
+ * @description Converts `StyleDictionary.dictionary.tokens` to typescript definition
153
+ * @param arguments [FormatterArguments](https://github.com/amzn/style-dictionary/blob/main/types/Format.d.ts)
154
+ * @returns formatted `string`
155
+ */
156
+ export const typescriptExportDefinition: StyleDictionary.Formatter = ({
157
+ dictionary,
158
+ file,
159
+ options = {},
160
+ platform,
161
+ }: FormatterArguments): string => {
162
+ // extract options
163
+ const {moduleName = `tokens`, tokenTypesPath = `./src/types/`} = options
164
+ // add prefix if defined
165
+ const tokens = prefixTokens(dictionary.tokens, platform)
166
+ // add file header and convert output
167
+ const output = `${fileHeader({file})}\n${getTypeDefinition(tokens, moduleName, tokenTypesPath)}\n`
168
+ // return prettified
169
+ return format(output, {parser: 'typescript', printWidth: 500})
170
+ }
@@ -0,0 +1,10 @@
1
+ import type StyleDictionary from 'style-dictionary'
2
+ /**
3
+ * jsonToFlat
4
+ * @description creates a one dimensional json structure with either a single value or an token object as the value
5
+ * @param token StyleDictionary.DesignToken
6
+ * @param returnObject - boolean
7
+ * @returns flat json three
8
+ */
9
+ export const jsonToFlat = (tokens: StyleDictionary.TransformedToken[], returnObject = false) =>
10
+ Object.fromEntries(tokens.map(token => [token.name, returnObject ? token : token.value]))
@@ -0,0 +1,20 @@
1
+ import type StyleDictionary from 'style-dictionary'
2
+ /**
3
+ * jsonToNestedValue
4
+ * @description creates a nested json tree where every final value is the `.value` prop
5
+ * @param token StyleDictionary.DesignToken
6
+ * @returns nested json three
7
+ */
8
+ export const jsonToNestedValue = (token: StyleDictionary.DesignToken | Record<string, unknown>) => {
9
+ // is non-object value
10
+ if (typeof token !== 'object') return token
11
+ // is design token
12
+ if ('value' in token) return token.value
13
+ // is obj
14
+ const nextObj = {}
15
+ for (const [prop, value] of Object.entries(token)) {
16
+ // @ts-expect-error: can't predict type
17
+ nextObj[prop] = jsonToNestedValue(value)
18
+ }
19
+ return nextObj
20
+ }
@@ -0,0 +1,17 @@
1
+ import type StyleDictionary from 'style-dictionary'
2
+ /**
3
+ * @description extract prefix from platform and add to tokens array if defined
4
+ * @param tokens StyleDictionary.TransformedTokens
5
+ * @param platform StyleDictionary.Platform
6
+ * @return StyleDictionary.TransformedTokens
7
+ */
8
+ export const prefixTokens = (
9
+ tokens: StyleDictionary.TransformedTokens,
10
+ platform: StyleDictionary.Platform = {},
11
+ ): StyleDictionary.TransformedTokens => {
12
+ const {prefix} = platform
13
+ if (typeof prefix === 'string') {
14
+ tokens = {[prefix]: tokens}
15
+ }
16
+ return tokens
17
+ }
@@ -0,0 +1 @@
1
+ export {w3cJsonParser} from './w3cJsonParser'
@@ -0,0 +1,25 @@
1
+ import {parse as json5Parse} from 'json5'
2
+ import type StyleDictionary from 'style-dictionary'
3
+
4
+ /**
5
+ * @description Parses a valid [json5](https://json5.org) file and replaces `$value` with `value` and `$description` with `comment` to make a w3c standard file compatible with style dictionary
6
+ * @pattern supported file extensions `.json` or `.json5`
7
+ */
8
+ export const w3cJsonParser: StyleDictionary.Parser = {
9
+ pattern: /\.json5?$/,
10
+ parse: ({filePath, contents}: {filePath: string; contents: string}) => {
11
+ // replace $value with value so that style dictionary recognizes it
12
+ try {
13
+ contents = contents
14
+ .replace(/["|']?\$value["|']?:/g, '"value":')
15
+ // convert $description to comment
16
+ .replace(/["|']?\$?description["|']?:/g, '"comment":')
17
+ .replace(/["|']?\$?type["|']?:/g, '"$type":')
18
+ .replace(/["|']?\$?extensions["|']?:/g, '"$extensions":')
19
+ //
20
+ return json5Parse(contents)
21
+ } catch (e) {
22
+ throw new Error(`Invalid json5 file "${filePath}".`)
23
+ }
24
+ },
25
+ }
@@ -0,0 +1,93 @@
1
+ import {isFromFile, isSource} from '../filters'
2
+ import type StyleDictionary from 'style-dictionary'
3
+ import type {PlatformInitializer} from '../types/PlatformInitializer'
4
+
5
+ const getCssSelectors = (outputFile: string): {selector: string; selectorLight: string; selectorDark: string} => {
6
+ // check for dark in the beginning of the output filename
7
+ const lastSlash = outputFile.lastIndexOf('/')
8
+ const outputBasename = outputFile.substring(lastSlash + 1, outputFile.indexOf('.'))
9
+ const themeName = outputBasename.replace(/-/g, '_')
10
+ const mode = outputBasename.substring(0, 4) === 'dark' ? 'dark' : 'light'
11
+
12
+ return {
13
+ selector: `[data-color-mode="${mode}"][data-${mode}-theme="${themeName}"], [data-color-mode="${mode}"][data-${mode}-theme="${themeName}"] ::backdrop`,
14
+ selectorLight: `[data-color-mode="auto"][data-light-theme="${themeName}"], [data-color-mode="auto"][data-light-theme="${themeName}"] ::backdrop`,
15
+ selectorDark: `[data-color-mode="auto"][data-dark-theme="${themeName}"], [data-color-mode="auto"][data-dark-theme="${themeName}"] ::backdrop`,
16
+ }
17
+ }
18
+
19
+ export const css: PlatformInitializer = (outputFile, prefix, buildPath, options): StyleDictionary.Platform => {
20
+ const {selector, selectorLight, selectorDark} = getCssSelectors(outputFile)
21
+ return {
22
+ prefix,
23
+ buildPath,
24
+ transforms: [
25
+ 'name/pathToKebabCase',
26
+ 'color/hex',
27
+ 'color/hexAlpha',
28
+ 'color/hexMix',
29
+ 'dimension/rem',
30
+ 'duration/css',
31
+ 'shadow/css',
32
+ 'border/css',
33
+ 'typography/css',
34
+ 'fontFamily/css',
35
+ 'fontWeight/number',
36
+ ],
37
+ options: {
38
+ basePxFontSize: 16,
39
+ },
40
+ files: [
41
+ {
42
+ destination: `${outputFile}`,
43
+ format: `css/themed`,
44
+ filter: token => isSource(token) && options?.themed === true,
45
+ options: {
46
+ showFileHeader: false,
47
+ outputReferences: false,
48
+ descriptions: false,
49
+ selector,
50
+ selectorLight,
51
+ selectorDark,
52
+ ...options?.options,
53
+ },
54
+ },
55
+ {
56
+ destination: `${outputFile}`,
57
+ format: `css/variables`,
58
+ filter: token => isSource(token) && options?.themed !== true,
59
+ options: {
60
+ showFileHeader: false,
61
+ descriptions: false,
62
+ ...options?.options,
63
+ },
64
+ },
65
+ {
66
+ destination: `${outputFile}`,
67
+ format: `css/customMedia`,
68
+ filter: token => isSource(token) && options?.themed !== true && token.$type === 'custom-viewportRange',
69
+ options: {
70
+ showFileHeader: false,
71
+ },
72
+ },
73
+ {
74
+ destination: `${outputFile}`,
75
+ format: `css/wrapMediaQuery`,
76
+ filter: token =>
77
+ isSource(token) &&
78
+ isFromFile(token, [
79
+ 'src/tokens/functional/size/size-coarse.json',
80
+ 'src/tokens/functional/size/size-fine.json',
81
+ ]),
82
+ options: {
83
+ descriptions: false,
84
+ showFileHeader: false,
85
+ mediaQuery: {
86
+ 'css/functional/size/size-fine.css': '(pointer: fine)',
87
+ 'css/functional/size/size-coarse.css': '(pointer: coarse)',
88
+ },
89
+ },
90
+ },
91
+ ],
92
+ }
93
+ }
@@ -0,0 +1,16 @@
1
+ import type StyleDictionary from 'style-dictionary'
2
+ import type {PlatformInitializer} from '../types/PlatformInitializer'
3
+ import {isDeprecated} from '../filters'
4
+
5
+ export const deprecatedJson: PlatformInitializer = (outputFile, prefix, buildPath): StyleDictionary.Platform => ({
6
+ prefix,
7
+ buildPath,
8
+ transforms: ['name/pathToDotNotation', 'json/deprecated'],
9
+ files: [
10
+ {
11
+ destination: outputFile,
12
+ format: `json/flat`,
13
+ filter: isDeprecated,
14
+ },
15
+ ],
16
+ })
@@ -0,0 +1,34 @@
1
+ import type StyleDictionary from 'style-dictionary'
2
+ import type {PlatformInitializer} from '../types/PlatformInitializer'
3
+ import {isSource} from '../filters'
4
+
5
+ export const docJson: PlatformInitializer = (outputFile, prefix, buildPath): StyleDictionary.Platform => ({
6
+ prefix,
7
+ buildPath,
8
+ transforms: [
9
+ 'name/pathToKebabCase',
10
+ 'color/hex',
11
+ 'color/hexMix',
12
+ 'color/hexAlpha',
13
+ 'dimension/rem',
14
+ 'shadow/css',
15
+ 'border/css',
16
+ 'typography/css',
17
+ 'fontFamily/css',
18
+ 'fontWeight/number',
19
+ ],
20
+ options: {
21
+ basePxFontSize: 16,
22
+ },
23
+ files: [
24
+ {
25
+ destination: outputFile,
26
+ format: `json/one-dimensional`,
27
+ filter: isSource,
28
+ options: {
29
+ outputReferences: false,
30
+ outputVerbose: true,
31
+ },
32
+ },
33
+ ],
34
+ })
@@ -0,0 +1,34 @@
1
+ import type StyleDictionary from 'style-dictionary'
2
+ import type {PlatformInitializer} from '../types/PlatformInitializer'
3
+ import {isSource} from '../filters'
4
+
5
+ export const fallbacks: PlatformInitializer = (outputFile, prefix, buildPath): StyleDictionary.Platform => ({
6
+ prefix,
7
+ buildPath,
8
+ transforms: [
9
+ 'name/pathToKebabCase',
10
+ 'color/hex',
11
+ 'color/hexMix',
12
+ 'color/hexAlpha',
13
+ 'dimension/rem',
14
+ 'shadow/css',
15
+ 'border/css',
16
+ 'typography/css',
17
+ 'fontFamily/css',
18
+ 'fontWeight/number',
19
+ ],
20
+ options: {
21
+ basePxFontSize: 16,
22
+ },
23
+ files: [
24
+ {
25
+ destination: outputFile,
26
+ format: `json/postCss-fallback`,
27
+ filter: isSource,
28
+ options: {
29
+ outputReferences: false,
30
+ outputVerbose: true,
31
+ },
32
+ },
33
+ ],
34
+ })
@@ -0,0 +1,48 @@
1
+ import type StyleDictionary from 'style-dictionary'
2
+ import type {PlatformInitializer} from '../types/PlatformInitializer'
3
+ import {isSource} from '../filters'
4
+
5
+ const validFigmaToken = (token: StyleDictionary.TransformedToken) => {
6
+ const validTypes = ['color', 'dimension', 'shadow']
7
+ // is a siource token, not an included one
8
+ if (!isSource(token)) return false
9
+ // has a collection attribute
10
+ if (
11
+ !('$extensions' in token) ||
12
+ !('org.primer.figma' in token.$extensions) ||
13
+ !('collection' in token.$extensions['org.primer.figma'])
14
+ )
15
+ return false
16
+ // is a color or dimension type
17
+ return validTypes.includes(token.$type)
18
+ }
19
+
20
+ export const figma: PlatformInitializer = (outputFile, prefix, buildPath, options): StyleDictionary.Platform => ({
21
+ prefix,
22
+ buildPath,
23
+ transforms: [
24
+ 'color/rgbaFloat',
25
+ 'name/pathToFigma',
26
+ // 'name/pathToSlashNotation',
27
+ 'figma/attributes',
28
+ 'dimension/pixelUnitless',
29
+ // 'border/figma',
30
+ // 'typography/figma',
31
+ 'fontWeight/number',
32
+ ],
33
+ options: {
34
+ basePxFontSize: 16,
35
+ ...options,
36
+ },
37
+ files: [
38
+ {
39
+ destination: outputFile,
40
+ filter: validFigmaToken,
41
+ format: `json/figma`,
42
+ options: {
43
+ outputReferences: true,
44
+ mode: options?.mode,
45
+ },
46
+ },
47
+ ],
48
+ })