From d10f1b2a4b189859008bb83a817b45f07a1018c3 Mon Sep 17 00:00:00 2001 From: Mirco Date: Thu, 14 Mar 2024 11:35:30 +0100 Subject: [PATCH 1/8] feat(tailwind-config): first test implementation of a tailwind-config generator --- build.ts | 51 +++++++- package.json | 2 + yarn.lock | 360 ++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 404 insertions(+), 9 deletions(-) diff --git a/build.ts b/build.ts index 9c1afc66..f81a3399 100644 --- a/build.ts +++ b/build.ts @@ -1,13 +1,60 @@ import { FormatterArguments } from 'style-dictionary/types/Format'; import { config } from './config'; import StyleDictionaryBase, { TransformedToken } from 'style-dictionary'; - -const StyleDictionary = StyleDictionaryBase.extend(config); +import { makeSdTailwindConfig } from 'sd-tailwindcss-transformer'; + +const StyleDictionary = StyleDictionaryBase.extend(config).extend( + makeSdTailwindConfig({ + tailwind: { content: ['./src/**/*.{ts,tsx,html}'] }, + buildPath: 'dist/tailwind/', + type: 'all', + transforms: ['attribute/cti', 'name/cti/kebab', 'custom/tailwind/organizeprops'], + isVariables: true, + prefix: 'sbb', + }), +); const fileHeader = StyleDictionary.formatHelpers.fileHeader; console.log('Build started...'); console.log('\n=============================================='); +StyleDictionary.registerTransform({ + type: 'attribute', + name: 'custom/tailwind/organizeprops', + transformer: (token) => { + const [rootCategory, secondCategory] = token.path; + if (rootCategory === 'color') { + token.path[0] = 'colors'; + } else if (rootCategory === 'breakpoint') { + token.path[0] = 'screens'; + } else if (rootCategory === 'animation' && secondCategory === 'duration') { + token.path.splice(0, 2, 'transitionDuration'); + } else if (rootCategory === 'animation' && secondCategory === 'easing') { + token.path.splice(0, 2, 'transitionTimingFunction'); + } else if (rootCategory === 'border' && secondCategory === 'width') { + token.path.splice(0, 2, 'borderWidth'); + } else if (rootCategory === 'border' && secondCategory === 'radius') { + token.path.splice(0, 2, 'borderRadius'); + } else if (rootCategory === 'focus' && secondCategory === 'outline') { + token.path.splice(0, 3, 'outlineOffset'); + } else if (rootCategory === 'spacing' && secondCategory === 'responsive') { + // remove "responsive" + token.path.splice(1, 1); + // remove "xxxs" etc. + token.path.splice(2, 1); + // remove media query value at the end + token.name = token.name.split('-').slice(0, -1).join('-'); + } else if (rootCategory === 'spacing' && secondCategory === 'fixed') { + token.path.splice(1, 1); + } else if (rootCategory === 'shadow' && secondCategory === 'elevation') { + // remove "level" and (e.g. 3) + token.path.splice(2, 2, 'lvl' + token.path[3]); + } + + return token; + }, +}); + StyleDictionary.registerFormat({ formatter: ({ file, dictionary, options }: FormatterArguments) => { const symbols = dictionary.allProperties.map(cssTemplate).join('') + '\n'; diff --git a/package.json b/package.json index f4cd1db6..547204f2 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,9 @@ "husky": "9.0.11", "lint-staged": "15.2.2", "prettier": "3.2.5", + "sd-tailwindcss-transformer": "1.4.1", "style-dictionary": "3.9.2", + "tailwindcss": "3.4.1", "tsx": "4.7.1", "typescript": "5.4.2" }, diff --git a/yarn.lock b/yarn.lock index b7c6ef85..b1b75bff 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7,6 +7,11 @@ resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== +"@alloc/quick-lru@^5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@alloc/quick-lru/-/quick-lru-5.2.0.tgz#7bf68b20c0a350f936915fcae06f58e32007ce30" + integrity sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw== + "@babel/code-frame@^7.0.0": version "7.23.5" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244" @@ -362,6 +367,38 @@ wrap-ansi "^8.1.0" wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" +"@jridgewell/gen-mapping@^0.3.2": + version "0.3.5" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" + integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg== + dependencies: + "@jridgewell/set-array" "^1.2.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.24" + +"@jridgewell/resolve-uri@^3.1.0": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== + +"@jridgewell/set-array@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" + integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== + +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": + version "1.4.15" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" + integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + +"@jridgewell/trace-mapping@^0.3.24": + version "0.3.25" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" + integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -584,6 +621,24 @@ ansi-styles@^6.0.0, ansi-styles@^6.1.0, ansi-styles@^6.2.1: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== +any-promise@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" + integrity sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A== + +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +arg@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c" + integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg== + argparse@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" @@ -604,6 +659,11 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -619,7 +679,7 @@ brace-expansion@^2.0.1: dependencies: balanced-match "^1.0.0" -braces@^3.0.2: +braces@^3.0.2, braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== @@ -639,6 +699,11 @@ camel-case@^4.1.2: pascal-case "^3.1.2" tslib "^2.0.3" +camelcase-css@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5" + integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA== + capital-case@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/capital-case/-/capital-case-1.0.4.tgz#9d130292353c9249f6b00fa5852bee38a717e669" @@ -688,6 +753,21 @@ change-case@^4.1.2: snake-case "^3.0.4" tslib "^2.0.3" +chokidar@^3.5.3: + version "3.6.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + cli-cursor@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-4.0.0.tgz#3cecfe3734bf4fe02a8361cbdc0f6fe28c6a57ea" @@ -754,6 +834,11 @@ commander@11.1.0: resolved "https://registry.yarnpkg.com/commander/-/commander-11.1.0.tgz#62fdce76006a68e5c1ab3314dc92e800eb83d906" integrity sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ== +commander@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" + integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== + commander@^8.3.0: version "8.3.0" resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" @@ -843,6 +928,11 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: shebang-command "^2.0.0" which "^2.0.1" +cssesc@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" + integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== + dargs@^8.0.0: version "8.1.0" resolved "https://registry.yarnpkg.com/dargs/-/dargs-8.1.0.tgz#a34859ea509cbce45485e5aa356fef70bfcc7272" @@ -865,6 +955,11 @@ deep-is@^0.1.3: resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== +didyoumean@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037" + integrity sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw== + dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -872,6 +967,11 @@ dir-glob@^3.0.1: dependencies: path-type "^4.0.0" +dlv@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79" + integrity sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA== + doctrine@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" @@ -1141,7 +1241,7 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-glob@^3.2.9: +fast-glob@^3.2.9, fast-glob@^3.3.0: version "3.3.2" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== @@ -1236,11 +1336,16 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== -fsevents@~2.3.3: +fsevents@~2.3.2, fsevents@~2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" @@ -1272,7 +1377,7 @@ git-raw-commits@^4.0.0: meow "^12.0.1" split2 "^4.0.0" -glob-parent@^5.1.2: +glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== @@ -1355,6 +1460,13 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== +hasown@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + header-case@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/header-case/-/header-case-2.0.4.tgz#5a42e63b55177349cf405beb8d775acabb92c063" @@ -1430,6 +1542,20 @@ is-arrayish@^0.2.1: resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-core-module@^2.13.0: + version "2.13.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" + integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== + dependencies: + hasown "^2.0.0" + is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" @@ -1452,7 +1578,7 @@ is-fullwidth-code-point@^5.0.0: dependencies: get-east-asian-width "^1.0.0" -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== @@ -1604,6 +1730,16 @@ lilconfig@3.0.0: resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.0.0.tgz#f8067feb033b5b74dab4602a5f5029420be749bc" integrity sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g== +lilconfig@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52" + integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ== + +lilconfig@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.1.1.tgz#9d8a246fa753106cfc205fd2d77042faca56e5e3" + integrity sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ== + lines-and-columns@^1.1.6: version "1.2.4" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" @@ -1746,7 +1882,7 @@ merge2@^1.3.0, merge2@^1.4.1: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== -micromatch@4.0.5, micromatch@^4.0.4: +micromatch@4.0.5, micromatch@^4.0.4, micromatch@^4.0.5: version "4.0.5" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== @@ -1800,6 +1936,20 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== +mz@^2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" + integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q== + dependencies: + any-promise "^1.0.0" + object-assign "^4.0.1" + thenify-all "^1.0.0" + +nanoid@^3.3.7: + version "3.3.7" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" + integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== + natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" @@ -1813,6 +1963,11 @@ no-case@^3.0.4: lower-case "^2.0.2" tslib "^2.0.3" +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + npm-run-path@^5.1.0: version "5.3.0" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-5.3.0.tgz#e23353d0ebb9317f174e93417e4a4d82d0249e9f" @@ -1820,6 +1975,16 @@ npm-run-path@^5.1.0: dependencies: path-key "^4.0.0" +object-assign@^4.0.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + +object-hash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9" + integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw== + once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -1947,6 +2112,11 @@ path-key@^4.0.0: resolved "https://registry.yarnpkg.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18" integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ== +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + path-scurry@^1.10.1: version "1.10.1" resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.10.1.tgz#9ba6bf5aa8500fe9fd67df4f0d9483b2b0bfc698" @@ -1960,7 +2130,12 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== -picomatch@^2.3.1: +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== @@ -1970,6 +2145,69 @@ pidtree@0.6.0: resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.6.0.tgz#90ad7b6d42d5841e69e0a2419ef38f8883aa057c" integrity sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g== +pify@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog== + +pirates@^4.0.1: + version "4.0.6" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" + integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== + +postcss-import@^15.1.0: + version "15.1.0" + resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-15.1.0.tgz#41c64ed8cc0e23735a9698b3249ffdbf704adc70" + integrity sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew== + dependencies: + postcss-value-parser "^4.0.0" + read-cache "^1.0.0" + resolve "^1.1.7" + +postcss-js@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-js/-/postcss-js-4.0.1.tgz#61598186f3703bab052f1c4f7d805f3991bee9d2" + integrity sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw== + dependencies: + camelcase-css "^2.0.1" + +postcss-load-config@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-4.0.2.tgz#7159dcf626118d33e299f485d6afe4aff7c4a3e3" + integrity sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ== + dependencies: + lilconfig "^3.0.0" + yaml "^2.3.4" + +postcss-nested@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-6.0.1.tgz#f83dc9846ca16d2f4fa864f16e9d9f7d0961662c" + integrity sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ== + dependencies: + postcss-selector-parser "^6.0.11" + +postcss-selector-parser@^6.0.11: + version "6.0.16" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz#3b88b9f5c5abd989ef4e2fc9ec8eedd34b20fb04" + integrity sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw== + dependencies: + cssesc "^3.0.0" + util-deprecate "^1.0.2" + +postcss-value-parser@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" + integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== + +postcss@^8.4.23: + version "8.4.35" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.35.tgz#60997775689ce09011edf083a549cea44aabe2f7" + integrity sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA== + dependencies: + nanoid "^3.3.7" + picocolors "^1.0.0" + source-map-js "^1.0.2" + prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" @@ -1990,6 +2228,13 @@ queue-microtask@^1.2.2: resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== +read-cache@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/read-cache/-/read-cache-1.0.0.tgz#e664ef31161166c9751cdbe8dbcf86b5fb58f774" + integrity sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA== + dependencies: + pify "^2.3.0" + readable-stream@1.1: version "1.1.13" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.13.tgz#f6eef764f514c89e2b9e23146a75ba106756d23e" @@ -2000,6 +2245,13 @@ readable-stream@1.1: isarray "0.0.1" string_decoder "~0.10.x" +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" @@ -2025,6 +2277,15 @@ resolve-pkg-maps@^1.0.0: resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== +resolve@^1.1.7, resolve@^1.22.2: + version "1.22.8" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" + integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + restore-cursor@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-4.0.0.tgz#519560a4318975096def6e609d44100edaa4ccb9" @@ -2057,6 +2318,11 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" +sd-tailwindcss-transformer@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/sd-tailwindcss-transformer/-/sd-tailwindcss-transformer-1.4.1.tgz#40403243bdaee6b1c78a4d12cc59e2dea3f59075" + integrity sha512-g/CbF9vj9zZUGUsj7QrCLckCDLNhG0w+ppssmN+uT/u7FCUV9EPE42uwjVghNBrb0ggqxrZcVoc/4Kl+tqDeSQ== + semver@^7.5.4, semver@^7.6.0: version "7.6.0" resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d" @@ -2124,6 +2390,11 @@ snake-case@^3.0.4: dot-case "^3.0.4" tslib "^2.0.3" +source-map-js@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" + integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== + split2@^4.0.0: version "4.2.0" resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4" @@ -2226,6 +2497,19 @@ style-dictionary@3.9.2: lodash "^4.17.15" tinycolor2 "^1.4.1" +sucrase@^3.32.0: + version "3.35.0" + resolved "https://registry.yarnpkg.com/sucrase/-/sucrase-3.35.0.tgz#57f17a3d7e19b36d8995f06679d121be914ae263" + integrity sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA== + dependencies: + "@jridgewell/gen-mapping" "^0.3.2" + commander "^4.0.0" + glob "^10.3.10" + lines-and-columns "^1.1.6" + mz "^2.7.0" + pirates "^4.0.1" + ts-interface-checker "^0.1.9" + supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -2240,6 +2524,39 @@ supports-color@^7.1.0: dependencies: has-flag "^4.0.0" +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +tailwindcss@^3.4.1: + version "3.4.1" + resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.4.1.tgz#f512ca5d1dd4c9503c7d3d28a968f1ad8f5c839d" + integrity sha512-qAYmXRfk3ENzuPBakNK0SRrUDipP8NQnEY6772uDhflcQz5EhRdD7JNZxyrFHVQNCwULPBn6FNPp9brpO7ctcA== + dependencies: + "@alloc/quick-lru" "^5.2.0" + arg "^5.0.2" + chokidar "^3.5.3" + didyoumean "^1.2.2" + dlv "^1.1.3" + fast-glob "^3.3.0" + glob-parent "^6.0.2" + is-glob "^4.0.3" + jiti "^1.19.1" + lilconfig "^2.1.0" + micromatch "^4.0.5" + normalize-path "^3.0.0" + object-hash "^3.0.0" + picocolors "^1.0.0" + postcss "^8.4.23" + postcss-import "^15.1.0" + postcss-js "^4.0.1" + postcss-load-config "^4.0.1" + postcss-nested "^6.0.1" + postcss-selector-parser "^6.0.11" + resolve "^1.22.2" + sucrase "^3.32.0" + text-extensions@^2.0.0: version "2.4.0" resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-2.4.0.tgz#a1cfcc50cf34da41bfd047cc744f804d1680ea34" @@ -2250,6 +2567,20 @@ text-table@^0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== +thenify-all@^1.0.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" + integrity sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA== + dependencies: + thenify ">= 3.1.0 < 4" + +"thenify@>= 3.1.0 < 4": + version "3.3.1" + resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.1.tgz#8932e686a4066038a016dd9e2ca46add9838a95f" + integrity sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw== + dependencies: + any-promise "^1.0.0" + "through@>=2.2.7 <3": version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" @@ -2272,6 +2603,11 @@ ts-api-utils@^1.0.1: resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1" integrity sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ== +ts-interface-checker@^0.1.9: + version "0.1.13" + resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699" + integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA== + tslib@^2.0.3: version "2.6.2" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" @@ -2345,6 +2681,11 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" +util-deprecate@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + which@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" @@ -2408,6 +2749,11 @@ yaml@2.3.4: resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.4.tgz#53fc1d514be80aabf386dc6001eb29bf3b7523b2" integrity sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA== +yaml@^2.3.4: + version "2.4.1" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.4.1.tgz#2e57e0b5e995292c25c75d2658f0664765210eed" + integrity sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg== + yargs-parser@^21.1.1: version "21.1.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" From 2d1aa2cb2ce1847f86581cf84f21cee11cb44863 Mon Sep 17 00:00:00 2001 From: Mirco Date: Thu, 14 Mar 2024 15:04:23 +0100 Subject: [PATCH 2/8] feat(tailwind-config): switch to custom format --- build.ts | 52 ++-------------------- config.ts | 11 +++++ createTailwindConfig.ts | 99 +++++++++++++++++++++++++++++++++++++++++ package.json | 1 - yarn.lock | 16 +------ 5 files changed, 116 insertions(+), 63 deletions(-) create mode 100644 createTailwindConfig.ts diff --git a/build.ts b/build.ts index f81a3399..169c8706 100644 --- a/build.ts +++ b/build.ts @@ -1,59 +1,15 @@ import { FormatterArguments } from 'style-dictionary/types/Format'; import { config } from './config'; import StyleDictionaryBase, { TransformedToken } from 'style-dictionary'; -import { makeSdTailwindConfig } from 'sd-tailwindcss-transformer'; - -const StyleDictionary = StyleDictionaryBase.extend(config).extend( - makeSdTailwindConfig({ - tailwind: { content: ['./src/**/*.{ts,tsx,html}'] }, - buildPath: 'dist/tailwind/', - type: 'all', - transforms: ['attribute/cti', 'name/cti/kebab', 'custom/tailwind/organizeprops'], - isVariables: true, - prefix: 'sbb', - }), -); +import { createTailwindSdFormatter } from './createTailwindConfig'; + +const StyleDictionary = StyleDictionaryBase.extend(config); const fileHeader = StyleDictionary.formatHelpers.fileHeader; console.log('Build started...'); console.log('\n=============================================='); -StyleDictionary.registerTransform({ - type: 'attribute', - name: 'custom/tailwind/organizeprops', - transformer: (token) => { - const [rootCategory, secondCategory] = token.path; - if (rootCategory === 'color') { - token.path[0] = 'colors'; - } else if (rootCategory === 'breakpoint') { - token.path[0] = 'screens'; - } else if (rootCategory === 'animation' && secondCategory === 'duration') { - token.path.splice(0, 2, 'transitionDuration'); - } else if (rootCategory === 'animation' && secondCategory === 'easing') { - token.path.splice(0, 2, 'transitionTimingFunction'); - } else if (rootCategory === 'border' && secondCategory === 'width') { - token.path.splice(0, 2, 'borderWidth'); - } else if (rootCategory === 'border' && secondCategory === 'radius') { - token.path.splice(0, 2, 'borderRadius'); - } else if (rootCategory === 'focus' && secondCategory === 'outline') { - token.path.splice(0, 3, 'outlineOffset'); - } else if (rootCategory === 'spacing' && secondCategory === 'responsive') { - // remove "responsive" - token.path.splice(1, 1); - // remove "xxxs" etc. - token.path.splice(2, 1); - // remove media query value at the end - token.name = token.name.split('-').slice(0, -1).join('-'); - } else if (rootCategory === 'spacing' && secondCategory === 'fixed') { - token.path.splice(1, 1); - } else if (rootCategory === 'shadow' && secondCategory === 'elevation') { - // remove "level" and (e.g. 3) - token.path.splice(2, 2, 'lvl' + token.path[3]); - } - - return token; - }, -}); +StyleDictionary.registerFormat(createTailwindSdFormatter()); StyleDictionary.registerFormat({ formatter: ({ file, dictionary, options }: FormatterArguments) => { diff --git a/config.ts b/config.ts index 51458f28..8f1c8427 100644 --- a/config.ts +++ b/config.ts @@ -80,6 +80,17 @@ export const config: Config = { transformGroup: 'js', transforms: ['attribute/cti', 'name/cti/kebab', 'color/css'], }, + tailwind: { + buildPath: 'dist/tailwind/', + prefix: 'sbb', + files: [ + { + destination: 'tailwind.config.json', + format: 'custom/tailwind', + }, + ], + transforms: ['name/cti/kebab'], + }, scss: { buildPath: 'dist/scss/', prefix: 'sbb', diff --git a/createTailwindConfig.ts b/createTailwindConfig.ts new file mode 100644 index 00000000..3d598aca --- /dev/null +++ b/createTailwindConfig.ts @@ -0,0 +1,99 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ + +import { Format, Named, TransformedToken } from 'style-dictionary'; +import * as SBBTokens from './designTokens'; +import { Config, CustomThemeConfig } from 'tailwindcss/types/config'; + +export function createTailwindSdFormatter(): Named { + return { + name: 'custom/tailwind', + formatter: (args) => { + return createTailwindConfig(args.dictionary.allTokens); + }, + }; +} + +export function createTailwindConfig(tokens: TransformedToken[]) { + const sbbTokens = unnestObjects(tokens) as Record>; + + // map colors and respective transparency variants to a common color + // e.g. "black" and "blackAlpha" will get merged into one color object, with the value of "black" as the default + const colors = sbbTokens.color; + Object.keys(colors).forEach((color) => { + if (color.endsWith('Alpha') && typeof colors[color] === 'object') { + const realColorName = color.replace('Alpha', ''); + colors[realColorName] = withTwDefault(colors[realColorName], colors[color]); + delete colors[color]; + } + }); + + const { fixed, responsive } = sbbTokens.spacing; + + // TODO: implement appropriate media queries (like currently done in lyne-components) + const responsiveSizes = Object.fromEntries( + Object.keys(responsive).map((size) => { + const breakpoint = 'zero'; + const variableName = responsive[size][breakpoint].replace(`-${breakpoint}`, ''); + return [size, variableName]; + }), + ); + + const fixedSizes = removeDashPrefix(fixed); + + const spacing = { ...fixedSizes, ...responsiveSizes }; + + const tailwindTheme: Partial = { + colors: { transparent: 'transparent', current: 'currentColor', ...colors }, + screens: sbbTokens.breakpoint, + transitionDuration: removeDashPrefix(sbbTokens.animation.duration), + transitionTimingFunction: withTwDefault(sbbTokens.animation.easing), + borderRadius: sbbTokens.border.radius, + borderWidth: sbbTokens.border.width, + outlineOffset: withTwDefault(sbbTokens.focus.outline.offset), + spacing, + // TODO: + // font + // shadow + // grid layout + }; + + return JSON.stringify({ theme: tailwindTheme } as Config, null, 2); +} +const withTwDefault = (defaultValue: V, obj = {} as T) => ({ + ...obj, + DEFAULT: defaultValue, +}); +// remove the dash prefix from the keys +// e.g. "-1x" becomes "1x" in the key + +const removeDashPrefix = (obj: Record) => + Object.fromEntries( + Object.entries(obj).map(([key, value]) => [ + key.startsWith('-') ? key.substring(1) : key, + value, + ]), + ); + +function unnestObjects(objects: TransformedToken[]): object { + const nestedObject: any = {}; + + for (const obj of objects) { + let currentObject = nestedObject; + const path = obj.path; + + for (let i = 0; i < path.length - 1; i++) { + const key = path[i]; + + if (!(key in currentObject)) { + currentObject[key] = {}; + } + + currentObject = currentObject[key]; + } + + const finalKey = path[path.length - 1]; + currentObject[finalKey] = `var(--${obj.name})`; + } + + return nestedObject; +} diff --git a/package.json b/package.json index 547204f2..350b5df4 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,6 @@ "husky": "9.0.11", "lint-staged": "15.2.2", "prettier": "3.2.5", - "sd-tailwindcss-transformer": "1.4.1", "style-dictionary": "3.9.2", "tailwindcss": "3.4.1", "tsx": "4.7.1", diff --git a/yarn.lock b/yarn.lock index b1b75bff..bff89fd2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -437,14 +437,7 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== -"@types/node@*": - version "20.11.25" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.25.tgz#0f50d62f274e54dd7a49f7704cc16bfbcccaf49f" - integrity sha512-TBHyJxk2b7HceLVGFcpAUjsa5zIdsPWlR6XHfyGzd0SFu+/NFgQgMAl96MSDZgQDvJAvV6BKsFOrt6zIL09JDw== - dependencies: - undici-types "~5.26.4" - -"@types/node@20.11.27": +"@types/node@*", "@types/node@20.11.27": version "20.11.27" resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.27.tgz#debe5cfc8a507dd60fe2a3b4875b1604f215c2ac" integrity sha512-qyUZfMnCg1KEz57r7pzFtSGt49f6RPkPBis3Vo4PbS7roQEDn22hiHzl/Lo1q4i4hDEgBJmBF/NTNg2XR0HbFg== @@ -2318,11 +2311,6 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" -sd-tailwindcss-transformer@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/sd-tailwindcss-transformer/-/sd-tailwindcss-transformer-1.4.1.tgz#40403243bdaee6b1c78a4d12cc59e2dea3f59075" - integrity sha512-g/CbF9vj9zZUGUsj7QrCLckCDLNhG0w+ppssmN+uT/u7FCUV9EPE42uwjVghNBrb0ggqxrZcVoc/4Kl+tqDeSQ== - semver@^7.5.4, semver@^7.6.0: version "7.6.0" resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d" @@ -2529,7 +2517,7 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== -tailwindcss@^3.4.1: +tailwindcss@3.4.1: version "3.4.1" resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.4.1.tgz#f512ca5d1dd4c9503c7d3d28a968f1ad8f5c839d" integrity sha512-qAYmXRfk3ENzuPBakNK0SRrUDipP8NQnEY6772uDhflcQz5EhRdD7JNZxyrFHVQNCwULPBn6FNPp9brpO7ctcA== From 7b5ce12979676eaffe699938ba7536bce372e226 Mon Sep 17 00:00:00 2001 From: Mirco Date: Tue, 19 Mar 2024 16:43:23 +0100 Subject: [PATCH 3/8] feat(tailwind-config): add comment with actual value behind variable for better DX --- config.ts | 9 ++++++++- createTailwindConfig.ts | 3 ++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/config.ts b/config.ts index 8f1c8427..ec82bda0 100644 --- a/config.ts +++ b/config.ts @@ -89,7 +89,14 @@ export const config: Config = { format: 'custom/tailwind', }, ], - transforms: ['name/cti/kebab'], + transforms: [ + 'attribute/cti', + 'name/cti/kebab', + 'time/seconds', + 'content/icon', + 'color/css', + 'size/px', + ], }, scss: { buildPath: 'dist/scss/', diff --git a/createTailwindConfig.ts b/createTailwindConfig.ts index 3d598aca..f606f0ab 100644 --- a/createTailwindConfig.ts +++ b/createTailwindConfig.ts @@ -92,7 +92,8 @@ function unnestObjects(objects: TransformedToken[]): object { } const finalKey = path[path.length - 1]; - currentObject[finalKey] = `var(--${obj.name})`; + // add the actual value behind the variable as a comment for a better developer experience + currentObject[finalKey] = `var(--${obj.name}) /* ${obj.value} */`; } return nestedObject; From 2d0bbc2609fbf655bbe757051655692741af50e9 Mon Sep 17 00:00:00 2001 From: Mirco Date: Wed, 3 Apr 2024 12:08:19 +0200 Subject: [PATCH 4/8] feat(tailwind-config): change breakpoints to min-width queries instead of fixed range --- config.ts | 3 ++- createTailwindConfig.ts | 31 +++++++++++++++++++++++++------ designTokens/animation.ts | 4 ++-- designTokens/border.ts | 4 ++-- designTokens/breakpoint.ts | 4 ++-- 5 files changed, 33 insertions(+), 13 deletions(-) diff --git a/config.ts b/config.ts index ec82bda0..6256e3b8 100644 --- a/config.ts +++ b/config.ts @@ -95,7 +95,8 @@ export const config: Config = { 'time/seconds', 'content/icon', 'color/css', - 'size/px', + 'size/pxToRem', + 'size/rem', ], }, scss: { diff --git a/createTailwindConfig.ts b/createTailwindConfig.ts index f606f0ab..41ca2194 100644 --- a/createTailwindConfig.ts +++ b/createTailwindConfig.ts @@ -14,7 +14,7 @@ export function createTailwindSdFormatter(): Named { } export function createTailwindConfig(tokens: TransformedToken[]) { - const sbbTokens = unnestObjects(tokens) as Record>; + const sbbTokens = unnestObjects(tokens); // map colors and respective transparency variants to a common color // e.g. "black" and "blackAlpha" will get merged into one color object, with the value of "black" as the default @@ -42,9 +42,15 @@ export function createTailwindConfig(tokens: TransformedToken[]) { const spacing = { ...fixedSizes, ...responsiveSizes }; + // ignore the max values from the breakpoint and only use the min sizes, + // since min-width media queries are to be used + const screens = Object.fromEntries( + Object.entries(sbbTokens.breakpoint).map(([bpName, range]) => [bpName, range.min]), + ); + const tailwindTheme: Partial = { colors: { transparent: 'transparent', current: 'currentColor', ...colors }, - screens: sbbTokens.breakpoint, + screens, transitionDuration: removeDashPrefix(sbbTokens.animation.duration), transitionTimingFunction: withTwDefault(sbbTokens.animation.easing), borderRadius: sbbTokens.border.radius, @@ -63,9 +69,9 @@ const withTwDefault = (defaultValue: V, obj = {} as T) => ( ...obj, DEFAULT: defaultValue, }); + // remove the dash prefix from the keys // e.g. "-1x" becomes "1x" in the key - const removeDashPrefix = (obj: Record) => Object.fromEntries( Object.entries(obj).map(([key, value]) => [ @@ -74,7 +80,13 @@ const removeDashPrefix = (obj: Record) => ]), ); -function unnestObjects(objects: TransformedToken[]): object { +// this type recursively unnests objects that have a "value" property +// e.g. recursively transforms objects like { a: { value: "b" } } to { a: "b" } +type UnnestValue = { + [K in keyof T]: T[K] extends { value: any } ? T[K]['value'] : UnnestValue; +}; + +function unnestObjects(objects: TransformedToken[]): UnnestValue { const nestedObject: any = {}; for (const obj of objects) { @@ -92,8 +104,15 @@ function unnestObjects(objects: TransformedToken[]): object { } const finalKey = path[path.length - 1]; - // add the actual value behind the variable as a comment for a better developer experience - currentObject[finalKey] = `var(--${obj.name}) /* ${obj.value} */`; + + if (path[0] === 'breakpoint') { + // breakpoints don't support css variables, we need to use the actual value of the variable instead + currentObject[finalKey] = `${obj.value} /* var(--${obj.name}) */`; + } else { + // add the actual value behind the variable as a comment for a better developer experience + currentObject[finalKey] = + `var(--${obj.name}) /* ${obj.attributes?.category === 'size' ? obj.original.value + 'px' : obj.value} */`; + } } return nestedObject; diff --git a/designTokens/animation.ts b/designTokens/animation.ts index 67937f7c..cfb08d2e 100644 --- a/designTokens/animation.ts +++ b/designTokens/animation.ts @@ -9,7 +9,7 @@ const attributes = () => }, }; -export const animation: DesignTokens = { +export const animation = { duration: { '-1x': { value: duration(1), @@ -43,4 +43,4 @@ export const animation: DesignTokens = { easing: { value: 'cubic-bezier(.47, .1, 1, .63)', }, -}; +} satisfies DesignTokens; diff --git a/designTokens/border.ts b/designTokens/border.ts index 34316de6..a8f1ae5d 100644 --- a/designTokens/border.ts +++ b/designTokens/border.ts @@ -13,7 +13,7 @@ const attributes = () => }, }; -export const border: DesignTokens = { +export const border = { width: { '1x': { value: borderWidth(1), @@ -45,5 +45,5 @@ export const border: DesignTokens = { value: borderRadius(16), ...attributes(), }, - }, + } satisfies DesignTokens, }; diff --git a/designTokens/breakpoint.ts b/designTokens/breakpoint.ts index 19cfa359..a09a9554 100644 --- a/designTokens/breakpoint.ts +++ b/designTokens/breakpoint.ts @@ -7,7 +7,7 @@ const attributes = () => }, }; -export const breakpoint: DesignTokens = { +export const breakpoint = { zero: { min: { value: 0, @@ -78,4 +78,4 @@ export const breakpoint: DesignTokens = { ...attributes(), }, }, -}; +} satisfies DesignTokens; From 8d88649b4edabb7456f155229407d678a4a5dbb8 Mon Sep 17 00:00:00 2001 From: Mirco Date: Wed, 3 Apr 2024 14:23:35 +0200 Subject: [PATCH 5/8] feat(tailwind-config): add 0px spacing variant --- createTailwindConfig.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/createTailwindConfig.ts b/createTailwindConfig.ts index 41ca2194..838ad68e 100644 --- a/createTailwindConfig.ts +++ b/createTailwindConfig.ts @@ -40,7 +40,7 @@ export function createTailwindConfig(tokens: TransformedToken[]) { const fixedSizes = removeDashPrefix(fixed); - const spacing = { ...fixedSizes, ...responsiveSizes }; + const spacing = { ...fixedSizes, ...responsiveSizes, '0': '0px' }; // ignore the max values from the breakpoint and only use the min sizes, // since min-width media queries are to be used From 48d077d4bd0832a29322146afed8de94679383a8 Mon Sep 17 00:00:00 2001 From: Mirco Date: Tue, 14 May 2024 11:08:12 +0200 Subject: [PATCH 6/8] feat(tailwind-config): add some zero values, add max-width queries, start with fonts --- createTailwindConfig.ts | 38 +++++++++++++++++++++++++++++++++----- designTokens/typo.ts | 5 +++-- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/createTailwindConfig.ts b/createTailwindConfig.ts index 838ad68e..4b5ee17d 100644 --- a/createTailwindConfig.ts +++ b/createTailwindConfig.ts @@ -40,23 +40,51 @@ export function createTailwindConfig(tokens: TransformedToken[]) { const fixedSizes = removeDashPrefix(fixed); - const spacing = { ...fixedSizes, ...responsiveSizes, '0': '0px' }; + const spacing = { ...fixedSizes, ...responsiveSizes, '0': '0' }; // ignore the max values from the breakpoint and only use the min sizes, // since min-width media queries are to be used - const screens = Object.fromEntries( + const minWidthScreens = Object.fromEntries( Object.entries(sbbTokens.breakpoint).map(([bpName, range]) => [bpName, range.min]), ); + const maxWidthScreens = Object.fromEntries( + Object.entries(sbbTokens.breakpoint).map(([bpName, range]) => [ + `max-${bpName}`, + { max: range.max }, + ]), + ); + + const typeFaces = sbbTokens.typo.typeFace; + + const fontFamily: CustomThemeConfig['fontFamily'] = { + roman: typeFaces.sbbRoman, + bold: typeFaces.sbbBold, + light: typeFaces.sbbLight, + }; + + // const fontSize = + + // Object.fromEntries( + // Object.entries(sbbTokens.typo.typeFace).map(([name, value]) => { + // if (name.startsWith('sbb')) name = name.substring(0, 3); + // return [name, ]; + // }), + // ); + + // const font: CustomThemeConfig["fontFamily"] + const tailwindTheme: Partial = { colors: { transparent: 'transparent', current: 'currentColor', ...colors }, - screens, + screens: { ...minWidthScreens, ...maxWidthScreens }, transitionDuration: removeDashPrefix(sbbTokens.animation.duration), transitionTimingFunction: withTwDefault(sbbTokens.animation.easing), - borderRadius: sbbTokens.border.radius, - borderWidth: sbbTokens.border.width, + borderRadius: { ...sbbTokens.border.radius, '0': '0', full: '9999px' }, + borderWidth: { ...sbbTokens.border.width, '0': '0' }, outlineOffset: withTwDefault(sbbTokens.focus.outline.offset), spacing, + fontFamily, + // TODO: // font // shadow diff --git a/designTokens/typo.ts b/designTokens/typo.ts index 920366c1..06d9bfe5 100644 --- a/designTokens/typo.ts +++ b/designTokens/typo.ts @@ -10,7 +10,7 @@ const attributes = () => }, }; -export const typo: DesignTokens = { +export const typo = { fontFamilyFallback: { value: '"Helvetica Neue", Helvetica, Arial, sans-serif', }, @@ -24,6 +24,7 @@ export const typo: DesignTokens = { sbbBold: { value: '"SBBWeb Bold", {typo.fontFamilyFallback.value}', }, + // is this necessary? i18n: { traditionalChinese: { value: '"Example for possible i18n structure"', @@ -96,4 +97,4 @@ export const typo: DesignTokens = { ...attributes(), }, }, -}; +} satisfies DesignTokens; From 9c81ace0a4e1929b7d9803e844a3cccdd331ffba Mon Sep 17 00:00:00 2001 From: Mirco Date: Thu, 16 May 2024 15:59:19 +0200 Subject: [PATCH 7/8] feat(tailwind-config): add font tokens --- build.ts | 2 +- .../createTailwindConfig.ts | 87 +++++++++---------- 2 files changed, 40 insertions(+), 49 deletions(-) rename createTailwindConfig.ts => tailwind/createTailwindConfig.ts (57%) diff --git a/build.ts b/build.ts index fd6328e9..127fe675 100644 --- a/build.ts +++ b/build.ts @@ -1,7 +1,7 @@ import { FormatterArguments } from 'style-dictionary/types/Format'; import { config } from './config'; import StyleDictionaryBase, { TransformedToken } from 'style-dictionary'; -import { createTailwindSdFormatter } from './createTailwindConfig'; +import { createTailwindSdFormatter } from './tailwind/createTailwindConfig'; import * as fs from 'fs'; const StyleDictionary = StyleDictionaryBase.extend(config); diff --git a/createTailwindConfig.ts b/tailwind/createTailwindConfig.ts similarity index 57% rename from createTailwindConfig.ts rename to tailwind/createTailwindConfig.ts index a53b7806..7ed90fba 100644 --- a/createTailwindConfig.ts +++ b/tailwind/createTailwindConfig.ts @@ -1,8 +1,7 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ - import { Format, Named, TransformedToken } from 'style-dictionary'; -import * as SBBTokens from './designTokens'; -import { Config, CustomThemeConfig } from 'tailwindcss/types/config'; +import * as SBBTokens from '../designTokens'; +import { Config } from 'tailwindcss/types/config'; export function createTailwindSdFormatter(): Named { return { @@ -12,9 +11,10 @@ export function createTailwindSdFormatter(): Named { }, }; } +type SbbTokens = typeof SBBTokens; export function createTailwindConfig(tokens: TransformedToken[]) { - const sbbTokens = unnestObjects(tokens); + const sbbTokens = unnestObjects(tokens); // map colors and respective transparency variants to a common color // e.g. "black" and "blackAlpha" will get merged into one color object, with the value of "black" as the default @@ -22,17 +22,26 @@ export function createTailwindConfig(tokens: TransformedToken[]) { Object.keys(colors).forEach((color) => { if (color.endsWith('Alpha') && typeof colors[color] === 'object') { const realColorName = color.replace('Alpha', ''); - colors[realColorName] = withTwDefault(colors[realColorName], colors[color]); + colors[realColorName] = withDefault(colors[realColorName], colors[color]); delete colors[color]; } }); const { fixed, responsive } = sbbTokens.spacing; - // TODO: implement appropriate media queries (like currently done in lyne-components) + // the css variables for the responsive sizes in the design tokens look like this: + // --sbb-spacing-responsive-xxl-zero + // this is because the spacings are dependent on breakpoints. this variable contains + // the value that the spacing "xxl" should have on breakpoint "zero". + // to achieve this, there are some css media queries, that define a new variable + // for each size, without the breakpoint name at the end ("--sbb-spacing-responsive-xxl" in this case), + // that will set the value of this variable based on the current breakpoint. + // so to work with the responsive sizes, we can just use the variable names without + // the breakpoint name, and the correct value will be set by the css in "composed-variables.css" const responsiveSizes = Object.fromEntries( Object.keys(responsive).map((size) => { - const breakpoint = 'zero'; + // it doesn't really matter which breakpoint we choose, any one will work + const breakpoint: keyof SbbTokens['breakpoint'] = 'zero'; const variableName = responsive[size][breakpoint].replace(`-${breakpoint}`, ''); return [size, variableName]; }), @@ -40,10 +49,6 @@ export function createTailwindConfig(tokens: TransformedToken[]) { const fixedSizes = removeDashPrefix(fixed); - const spacing = { ...fixedSizes, ...responsiveSizes, '0': '0' }; - - // ignore the max values from the breakpoint and only use the min sizes, - // since min-width media queries are to be used const minWidthScreens = Object.fromEntries( Object.entries(sbbTokens.breakpoint).map(([bpName, range]) => [bpName, range.min]), ); @@ -55,45 +60,31 @@ export function createTailwindConfig(tokens: TransformedToken[]) { ]), ); - // const typeFaces = sbbTokens.typo.typeFace; - - // const fontFamily: CustomThemeConfig['fontFamily'] = { - // roman: typeFaces.sbbRoman, - // bold: typeFaces.sbbBold, - // light: typeFaces.sbbLight, - // }; - - // const fontSize = - - // Object.fromEntries( - // Object.entries(sbbTokens.typo.typeFace).map(([name, value]) => { - // if (name.startsWith('sbb')) name = name.substring(0, 3); - // return [name, ]; - // }), - // ); - - // const font: CustomThemeConfig["fontFamily"] - - const tailwindTheme: Partial = { - colors: { transparent: 'transparent', current: 'currentColor', ...colors }, - screens: { ...minWidthScreens, ...maxWidthScreens }, - transitionDuration: removeDashPrefix(sbbTokens.animation.duration), - transitionTimingFunction: withTwDefault(sbbTokens.animation.easing), - borderRadius: { ...sbbTokens.border.radius, '0': '0', full: '9999px' }, - borderWidth: { ...sbbTokens.border.width, '0': '0' }, - outlineOffset: withTwDefault(sbbTokens.focus.outline.offset), - spacing, - // fontFamily, - - // TODO: - // font - // shadow - // grid layout + const { default: defaultFontSize, ...otherFontSizes } = sbbTokens.typo.scale; + + const tailwindConfig: Partial = { + theme: { + colors: { transparent: 'transparent', current: 'currentColor', ...colors }, + screens: { ...minWidthScreens, ...maxWidthScreens }, + transitionDuration: removeDashPrefix(sbbTokens.animation.duration), + transitionTimingFunction: withDefault(sbbTokens.animation.easing), + borderRadius: { ...sbbTokens.border.radius, '0': '0', full: '9999px' }, + borderWidth: { ...sbbTokens.border.width, '0': '0' }, + outlineOffset: withDefault(sbbTokens.focus.outline.offset), + spacing: { ...fixedSizes, ...responsiveSizes, '0': '0' }, + letterSpacing: sbbTokens.typo.letterSpacing, + lineHeight: sbbTokens.typo.lineHeight, + fontFamily: withDefault(sbbTokens.typo.fontFamily), + fontSize: withDefault(defaultFontSize, otherFontSizes), + // TODO: + // shadow + // grid layout + }, }; - - return JSON.stringify({ theme: tailwindTheme } as Config, null, 2); + return JSON.stringify(tailwindConfig, null, 2); } -const withTwDefault = (defaultValue: V, obj = {} as T) => ({ + +const withDefault = (defaultValue: V, obj = {} as T) => ({ ...obj, DEFAULT: defaultValue, }); From 92d036cead1016e99ae77a97dd8b3dd0cc0d033e Mon Sep 17 00:00:00 2001 From: Nick Weyermann Date: Tue, 21 May 2024 14:27:07 +0200 Subject: [PATCH 8/8] feat(tailwind-config): added box-shadow --- tailwind/createTailwindConfig.ts | 36 ++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/tailwind/createTailwindConfig.ts b/tailwind/createTailwindConfig.ts index 7ed90fba..4c90127e 100644 --- a/tailwind/createTailwindConfig.ts +++ b/tailwind/createTailwindConfig.ts @@ -16,6 +16,7 @@ type SbbTokens = typeof SBBTokens; export function createTailwindConfig(tokens: TransformedToken[]) { const sbbTokens = unnestObjects(tokens); + // #region colors // map colors and respective transparency variants to a common color // e.g. "black" and "blackAlpha" will get merged into one color object, with the value of "black" as the default const colors = sbbTokens.color; @@ -26,9 +27,10 @@ export function createTailwindConfig(tokens: TransformedToken[]) { delete colors[color]; } }); + // #endregion colors + // #region spacing const { fixed, responsive } = sbbTokens.spacing; - // the css variables for the responsive sizes in the design tokens look like this: // --sbb-spacing-responsive-xxl-zero // this is because the spacings are dependent on breakpoints. this variable contains @@ -38,7 +40,7 @@ export function createTailwindConfig(tokens: TransformedToken[]) { // that will set the value of this variable based on the current breakpoint. // so to work with the responsive sizes, we can just use the variable names without // the breakpoint name, and the correct value will be set by the css in "composed-variables.css" - const responsiveSizes = Object.fromEntries( + const responsiveSpacing = Object.fromEntries( Object.keys(responsive).map((size) => { // it doesn't really matter which breakpoint we choose, any one will work const breakpoint: keyof SbbTokens['breakpoint'] = 'zero'; @@ -46,9 +48,10 @@ export function createTailwindConfig(tokens: TransformedToken[]) { return [size, variableName]; }), ); + const fixedSpacing = removeDashPrefix(fixed); + // #endregion spacing - const fixedSizes = removeDashPrefix(fixed); - + // #region screens const minWidthScreens = Object.fromEntries( Object.entries(sbbTokens.breakpoint).map(([bpName, range]) => [bpName, range.min]), ); @@ -59,8 +62,29 @@ export function createTailwindConfig(tokens: TransformedToken[]) { { max: range.max }, ]), ); + // #endregion screens + // #region fontSize const { default: defaultFontSize, ...otherFontSizes } = sbbTokens.typo.scale; + // #endregion fontSize + + // #region boxShadow + const boxShadows = Object.entries>(sbbTokens.shadow.elevation.level).reduce( + (prev, [key, value]) => { + function getShadowDefinition(number: number, type: 'soft' | 'hard') { + return `${value.shadow[number].offset.x} ${value.shadow[number].offset.y} ${value.shadow[number].blur} ${value.shadow[number].spread} ${value[type][number].color}`; + } + + return { + ...prev, + [`${key}s`]: `${getShadowDefinition(1, 'soft')}, ${getShadowDefinition(2, 'soft')}`, + [`${key}h`]: `${getShadowDefinition(1, 'hard')}, ${getShadowDefinition(2, 'hard')}`, + }; + }, + {} as Record, + ); + const defaultBoxShadow = Object.values(boxShadows)[0]; + // #endregion boxShadow const tailwindConfig: Partial = { theme: { @@ -71,13 +95,13 @@ export function createTailwindConfig(tokens: TransformedToken[]) { borderRadius: { ...sbbTokens.border.radius, '0': '0', full: '9999px' }, borderWidth: { ...sbbTokens.border.width, '0': '0' }, outlineOffset: withDefault(sbbTokens.focus.outline.offset), - spacing: { ...fixedSizes, ...responsiveSizes, '0': '0' }, + spacing: { ...fixedSpacing, ...responsiveSpacing, '0': '0' }, letterSpacing: sbbTokens.typo.letterSpacing, lineHeight: sbbTokens.typo.lineHeight, fontFamily: withDefault(sbbTokens.typo.fontFamily), fontSize: withDefault(defaultFontSize, otherFontSizes), + boxShadow: withDefault(defaultBoxShadow, boxShadows), // TODO: - // shadow // grid layout }, };