@pandacss/studio 0.0.0-dev-20230613163214

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 (250) hide show
  1. package/LICENSE.md +21 -0
  2. package/astro.config.ts +14 -0
  3. package/dist/studio.d.ts +13 -0
  4. package/dist/studio.js +2089 -0
  5. package/dist/studio.mjs +2087 -0
  6. package/index.ts +1 -0
  7. package/package.json +59 -0
  8. package/panda.config.ts +110 -0
  9. package/public/favicon.svg +13 -0
  10. package/src/components/analyzer/category-utilities.tsx +146 -0
  11. package/src/components/analyzer/data-combobox.tsx +125 -0
  12. package/src/components/analyzer/data-table.tsx +43 -0
  13. package/src/components/analyzer/external-icon.tsx +8 -0
  14. package/src/components/analyzer/file-details.tsx +101 -0
  15. package/src/components/analyzer/get-report-infos-from.ts +80 -0
  16. package/src/components/analyzer/quick-tooltip.tsx +15 -0
  17. package/src/components/analyzer/report-item-columns.tsx +52 -0
  18. package/src/components/analyzer/report-item-link.tsx +98 -0
  19. package/src/components/analyzer/section.tsx +24 -0
  20. package/src/components/analyzer/sort-icon.tsx +7 -0
  21. package/src/components/analyzer/text-with-count.tsx +28 -0
  22. package/src/components/analyzer/token-search-combobox.tsx +39 -0
  23. package/src/components/analyzer/truncated-text.tsx +26 -0
  24. package/src/components/analyzer/utility-details.tsx +312 -0
  25. package/src/components/color-constrast.tsx +131 -0
  26. package/src/components/color-item.tsx +37 -0
  27. package/src/components/color-wrapper.tsx +25 -0
  28. package/src/components/colors.tsx +96 -0
  29. package/src/components/empty-state.tsx +19 -0
  30. package/src/components/font-family.tsx +55 -0
  31. package/src/components/font-tokens.tsx +69 -0
  32. package/src/components/head.astro +35 -0
  33. package/src/components/icons.tsx +207 -0
  34. package/src/components/input.tsx +27 -0
  35. package/src/components/layer-styles.tsx +38 -0
  36. package/src/components/logo.tsx +34 -0
  37. package/src/components/nav-item.tsx +39 -0
  38. package/src/components/overview.tsx +65 -0
  39. package/src/components/radii.tsx +34 -0
  40. package/src/components/semantic-color.tsx +27 -0
  41. package/src/components/side-nav-item.astro +25 -0
  42. package/src/components/side-nav.astro +30 -0
  43. package/src/components/sizes.tsx +53 -0
  44. package/src/components/text-styles.tsx +33 -0
  45. package/src/components/theme-toggle.astro +56 -0
  46. package/src/components/token-analyzer.tsx +390 -0
  47. package/src/components/token-content.tsx +5 -0
  48. package/src/components/token-group.tsx +6 -0
  49. package/src/components/typography-playground.tsx +83 -0
  50. package/src/env.d.ts +1 -0
  51. package/src/icons/moon.tsx +15 -0
  52. package/src/icons/sun.tsx +19 -0
  53. package/src/layouts/Layout.astro +19 -0
  54. package/src/layouts/Sidebar.astro +35 -0
  55. package/src/lib/analysis-data.ts +17 -0
  56. package/src/lib/color-contrast-checker.ts +218 -0
  57. package/src/lib/color.ts +40 -0
  58. package/src/lib/constants.ts +140 -0
  59. package/src/lib/create-context.ts +27 -0
  60. package/src/lib/get-report-item.tsx +41 -0
  61. package/src/lib/group-in.ts +35 -0
  62. package/src/lib/panda.context.ts +23 -0
  63. package/src/lib/pick.ts +24 -0
  64. package/src/lib/sizes-sort.ts +10 -0
  65. package/src/lib/truncate.tsx +7 -0
  66. package/src/lib/use-color-docs.ts +101 -0
  67. package/src/pages/colors.astro +11 -0
  68. package/src/pages/font-sizes.astro +15 -0
  69. package/src/pages/font-weights.astro +15 -0
  70. package/src/pages/fonts.astro +11 -0
  71. package/src/pages/index.astro +8 -0
  72. package/src/pages/layer-styles.astro +11 -0
  73. package/src/pages/letter-spacings.astro +20 -0
  74. package/src/pages/line-heights.astro +21 -0
  75. package/src/pages/playground/contrast-checker.astro +11 -0
  76. package/src/pages/playground/typography.astro +11 -0
  77. package/src/pages/radii.astro +11 -0
  78. package/src/pages/sizes.astro +14 -0
  79. package/src/pages/spacing.astro +14 -0
  80. package/src/pages/text-styles.astro +11 -0
  81. package/src/pages/token-analyzer/file.astro +11 -0
  82. package/src/pages/token-analyzer/index.astro +11 -0
  83. package/src/pages/token-analyzer/utility.astro +11 -0
  84. package/styled-system/chunks/..__core____tests____composition.test.css +2 -0
  85. package/styled-system/chunks/src__components__analyzer__category-utilities.css +97 -0
  86. package/styled-system/chunks/src__components__analyzer__data-combobox.css +77 -0
  87. package/styled-system/chunks/src__components__analyzer__data-table.css +37 -0
  88. package/styled-system/chunks/src__components__analyzer__file-details.css +103 -0
  89. package/styled-system/chunks/src__components__analyzer__quick-tooltip.css +2 -0
  90. package/styled-system/chunks/src__components__analyzer__report-item-columns.css +29 -0
  91. package/styled-system/chunks/src__components__analyzer__report-item-link.css +109 -0
  92. package/styled-system/chunks/src__components__analyzer__section.css +29 -0
  93. package/styled-system/chunks/src__components__analyzer__text-with-count.css +33 -0
  94. package/styled-system/chunks/src__components__analyzer__truncated-text.css +13 -0
  95. package/styled-system/chunks/src__components__analyzer__utility-details.css +125 -0
  96. package/styled-system/chunks/src__components__color-constrast.css +114 -0
  97. package/styled-system/chunks/src__components__color-item.css +21 -0
  98. package/styled-system/chunks/src__components__color-wrapper.css +73 -0
  99. package/styled-system/chunks/src__components__colors.css +97 -0
  100. package/styled-system/chunks/src__components__empty-state.css +45 -0
  101. package/styled-system/chunks/src__components__font-family.css +85 -0
  102. package/styled-system/chunks/src__components__font-tokens.css +61 -0
  103. package/styled-system/chunks/src__components__input.css +68 -0
  104. package/styled-system/chunks/src__components__layer-styles.css +66 -0
  105. package/styled-system/chunks/src__components__nav-item.css +73 -0
  106. package/styled-system/chunks/src__components__overview.css +125 -0
  107. package/styled-system/chunks/src__components__radii.css +49 -0
  108. package/styled-system/chunks/src__components__semantic-color.css +45 -0
  109. package/styled-system/chunks/src__components__side-nav-item.css +33 -0
  110. package/styled-system/chunks/src__components__side-nav.css +49 -0
  111. package/styled-system/chunks/src__components__sizes.css +41 -0
  112. package/styled-system/chunks/src__components__text-styles.css +31 -0
  113. package/styled-system/chunks/src__components__theme-toggle.css +63 -0
  114. package/styled-system/chunks/src__components__token-analyzer.css +227 -0
  115. package/styled-system/chunks/src__components__token-content.css +13 -0
  116. package/styled-system/chunks/src__components__token-group.css +21 -0
  117. package/styled-system/chunks/src__components__token-search-combobox.css +2 -0
  118. package/styled-system/chunks/src__components__typography-playground.css +61 -0
  119. package/styled-system/chunks/src__layouts__Layout.css +2 -0
  120. package/styled-system/chunks/src__layouts__Sidebar.css +113 -0
  121. package/styled-system/chunks/src__pages__colors.css +2 -0
  122. package/styled-system/chunks/src__pages__font-sizes.css +2 -0
  123. package/styled-system/chunks/src__pages__font-weights.css +2 -0
  124. package/styled-system/chunks/src__pages__fonts.css +2 -0
  125. package/styled-system/chunks/src__pages__index.css +2 -0
  126. package/styled-system/chunks/src__pages__layer-styles.css +2 -0
  127. package/styled-system/chunks/src__pages__letter-spacings.css +2 -0
  128. package/styled-system/chunks/src__pages__line-heights.css +2 -0
  129. package/styled-system/chunks/src__pages__playground__contrast-checker.css +2 -0
  130. package/styled-system/chunks/src__pages__playground__typography.css +2 -0
  131. package/styled-system/chunks/src__pages__radii.css +2 -0
  132. package/styled-system/chunks/src__pages__sizes.css +2 -0
  133. package/styled-system/chunks/src__pages__spacing.css +2 -0
  134. package/styled-system/chunks/src__pages__text-styles.css +2 -0
  135. package/styled-system/chunks/src__pages__token-analyzer__file.css +2 -0
  136. package/styled-system/chunks/src__pages__token-analyzer__index.css +2 -0
  137. package/styled-system/chunks/src__pages__token-analyzer__utility.css +2 -0
  138. package/styled-system/css/conditions.mjs +147 -0
  139. package/styled-system/css/css.d.ts +2 -0
  140. package/styled-system/css/css.mjs +391 -0
  141. package/styled-system/css/cva.d.ts +5 -0
  142. package/styled-system/css/cva.mjs +63 -0
  143. package/styled-system/css/cx.d.ts +4 -0
  144. package/styled-system/css/cx.mjs +15 -0
  145. package/styled-system/css/index.d.ts +3 -0
  146. package/styled-system/css/index.mjs +3 -0
  147. package/styled-system/global.css +61 -0
  148. package/styled-system/helpers.mjs +251 -0
  149. package/styled-system/jsx/absolute-center.d.ts +8 -0
  150. package/styled-system/jsx/absolute-center.mjs +9 -0
  151. package/styled-system/jsx/aspect-ratio.d.ts +8 -0
  152. package/styled-system/jsx/aspect-ratio.mjs +9 -0
  153. package/styled-system/jsx/box.d.ts +8 -0
  154. package/styled-system/jsx/box.mjs +8 -0
  155. package/styled-system/jsx/center.d.ts +8 -0
  156. package/styled-system/jsx/center.mjs +9 -0
  157. package/styled-system/jsx/circle.d.ts +8 -0
  158. package/styled-system/jsx/circle.mjs +9 -0
  159. package/styled-system/jsx/container.d.ts +8 -0
  160. package/styled-system/jsx/container.mjs +8 -0
  161. package/styled-system/jsx/divider.d.ts +8 -0
  162. package/styled-system/jsx/divider.mjs +9 -0
  163. package/styled-system/jsx/factory.d.ts +2 -0
  164. package/styled-system/jsx/factory.mjs +59 -0
  165. package/styled-system/jsx/flex.d.ts +8 -0
  166. package/styled-system/jsx/flex.mjs +9 -0
  167. package/styled-system/jsx/float.d.ts +8 -0
  168. package/styled-system/jsx/float.mjs +9 -0
  169. package/styled-system/jsx/grid-item.d.ts +8 -0
  170. package/styled-system/jsx/grid-item.mjs +9 -0
  171. package/styled-system/jsx/grid.d.ts +8 -0
  172. package/styled-system/jsx/grid.mjs +9 -0
  173. package/styled-system/jsx/hstack.d.ts +8 -0
  174. package/styled-system/jsx/hstack.mjs +9 -0
  175. package/styled-system/jsx/index.d.ts +20 -0
  176. package/styled-system/jsx/index.mjs +19 -0
  177. package/styled-system/jsx/is-valid-prop.mjs +1010 -0
  178. package/styled-system/jsx/spacer.d.ts +8 -0
  179. package/styled-system/jsx/spacer.mjs +9 -0
  180. package/styled-system/jsx/square.d.ts +8 -0
  181. package/styled-system/jsx/square.mjs +9 -0
  182. package/styled-system/jsx/stack.d.ts +8 -0
  183. package/styled-system/jsx/stack.mjs +9 -0
  184. package/styled-system/jsx/styled-link.d.ts +8 -0
  185. package/styled-system/jsx/styled-link.mjs +8 -0
  186. package/styled-system/jsx/vstack.d.ts +8 -0
  187. package/styled-system/jsx/vstack.mjs +9 -0
  188. package/styled-system/jsx/wrap.d.ts +8 -0
  189. package/styled-system/jsx/wrap.mjs +9 -0
  190. package/styled-system/patterns/absolute-center.d.ts +14 -0
  191. package/styled-system/patterns/absolute-center.mjs +23 -0
  192. package/styled-system/patterns/aspect-ratio.d.ts +14 -0
  193. package/styled-system/patterns/aspect-ratio.mjs +25 -0
  194. package/styled-system/patterns/box.d.ts +14 -0
  195. package/styled-system/patterns/box.mjs +12 -0
  196. package/styled-system/patterns/center.d.ts +14 -0
  197. package/styled-system/patterns/center.mjs +18 -0
  198. package/styled-system/patterns/circle.d.ts +14 -0
  199. package/styled-system/patterns/circle.mjs +22 -0
  200. package/styled-system/patterns/container.d.ts +14 -0
  201. package/styled-system/patterns/container.mjs +18 -0
  202. package/styled-system/patterns/divider.d.ts +16 -0
  203. package/styled-system/patterns/divider.mjs +21 -0
  204. package/styled-system/patterns/flex.d.ts +20 -0
  205. package/styled-system/patterns/flex.mjs +23 -0
  206. package/styled-system/patterns/float.d.ts +17 -0
  207. package/styled-system/patterns/float.mjs +45 -0
  208. package/styled-system/patterns/grid-item.d.ts +19 -0
  209. package/styled-system/patterns/grid-item.mjs +20 -0
  210. package/styled-system/patterns/grid.d.ts +18 -0
  211. package/styled-system/patterns/grid.mjs +25 -0
  212. package/styled-system/patterns/hstack.d.ts +15 -0
  213. package/styled-system/patterns/hstack.mjs +20 -0
  214. package/styled-system/patterns/index.d.ts +18 -0
  215. package/styled-system/patterns/index.mjs +18 -0
  216. package/styled-system/patterns/spacer.d.ts +14 -0
  217. package/styled-system/patterns/spacer.mjs +18 -0
  218. package/styled-system/patterns/square.d.ts +14 -0
  219. package/styled-system/patterns/square.mjs +21 -0
  220. package/styled-system/patterns/stack.d.ts +17 -0
  221. package/styled-system/patterns/stack.mjs +20 -0
  222. package/styled-system/patterns/styled-link.d.ts +14 -0
  223. package/styled-system/patterns/styled-link.mjs +18 -0
  224. package/styled-system/patterns/vstack.d.ts +15 -0
  225. package/styled-system/patterns/vstack.mjs +20 -0
  226. package/styled-system/patterns/wrap.d.ts +18 -0
  227. package/styled-system/patterns/wrap.mjs +22 -0
  228. package/styled-system/reset.css +190 -0
  229. package/styled-system/static.css +5 -0
  230. package/styled-system/styles.css +938 -0
  231. package/styled-system/tokens/index.css +374 -0
  232. package/styled-system/tokens/index.d.ts +8 -0
  233. package/styled-system/tokens/index.mjs +1590 -0
  234. package/styled-system/tokens/keyframes.css +30 -0
  235. package/styled-system/tokens/tokens.d.ts +56 -0
  236. package/styled-system/types/composition.d.ts +110 -0
  237. package/styled-system/types/conditions.d.ts +135 -0
  238. package/styled-system/types/csstype.d.ts +20748 -0
  239. package/styled-system/types/global.d.ts +15 -0
  240. package/styled-system/types/helpers.d.ts +1 -0
  241. package/styled-system/types/index.d.ts +3 -0
  242. package/styled-system/types/jsx.d.ts +27 -0
  243. package/styled-system/types/parts.d.ts +5 -0
  244. package/styled-system/types/pattern.d.ts +52 -0
  245. package/styled-system/types/prop-type.d.ts +300 -0
  246. package/styled-system/types/recipe.d.ts +79 -0
  247. package/styled-system/types/selectors.d.ts +56 -0
  248. package/styled-system/types/style-props.d.ts +688 -0
  249. package/styled-system/types/system-types.d.ts +76 -0
  250. package/virtual-panda.ts +72 -0
@@ -0,0 +1,218 @@
1
+ // Credits: https://github.com/bbc/color-contrast-checker
2
+
3
+ type Pair = { colorA: string; colorB: string; fontSize: number }
4
+ type Rgb = { r: number; g: number; b: number }
5
+
6
+ class RgbClass {
7
+ r = 0
8
+ g = 0
9
+ b = 0
10
+ toString = () => {
11
+ return '<r: ' + this.r + ' g: ' + this.g + ' b: ' + this.b + ' >'
12
+ }
13
+ }
14
+
15
+ class Result {
16
+ WCAG_AA = false
17
+ WCAG_AAA = false
18
+ customRatio: number | undefined = undefined
19
+ toString = () => {
20
+ return '< WCAG-AA: ' + (this.WCAG_AA ? 'pass' : 'fail') + ' WCAG-AAA: ' + (this.WCAG_AAA ? 'pass' : 'fail') + ' >'
21
+ }
22
+ }
23
+
24
+ export class ColorContrastChecker {
25
+ fontSize = 14
26
+
27
+ rgbClass = new RgbClass()
28
+
29
+ isValidSixDigitColorCode = (hex: string) => {
30
+ const regSixDigitColorcode = /^(#)?([0-9a-fA-F]{6})?$/
31
+ return regSixDigitColorcode.test(hex)
32
+ }
33
+
34
+ isValidThreeDigitColorCode = (hex: string) => {
35
+ const regThreeDigitColorcode = /^(#)?([0-9a-fA-F]{3})?$/
36
+ return regThreeDigitColorcode.test(hex)
37
+ }
38
+
39
+ isValidColorCode = (hex: string) => {
40
+ return this.isValidSixDigitColorCode(hex) || this.isValidThreeDigitColorCode(hex)
41
+ }
42
+
43
+ isValidRatio = (ratio: unknown) => {
44
+ return typeof ratio === 'number'
45
+ }
46
+
47
+ convertColorToSixDigit = (hex: string) => {
48
+ return '#' + hex[1] + hex[1] + hex[2] + hex[2] + hex[3] + hex[3]
49
+ }
50
+
51
+ hexToLuminance = (color: string) => {
52
+ if (!this.isValidColorCode(color)) {
53
+ throw new Error('Invalid Color :' + color)
54
+ }
55
+
56
+ if (this.isValidThreeDigitColorCode(color)) {
57
+ color = this.convertColorToSixDigit(color)
58
+ }
59
+
60
+ const rgb = this.getRGBFromHex(color)
61
+
62
+ const LRGB = this.calculateLRGB(rgb)
63
+
64
+ return this.calculateLuminance(LRGB)
65
+ }
66
+
67
+ check = (colorA: string, colorB: string, fontSize?: number, customRatio?: number) => {
68
+ if (typeof fontSize !== 'undefined') {
69
+ this.fontSize = fontSize
70
+ }
71
+
72
+ if (!colorA || !colorB) {
73
+ return false
74
+ }
75
+
76
+ const l1 = this.hexToLuminance(colorA) /* higher value */
77
+ const l2 = this.hexToLuminance(colorB) /* lower value */
78
+ const contrastRatio = this.getContrastRatio(l1, l2)
79
+
80
+ if (typeof customRatio !== 'undefined') {
81
+ if (!this.isValidRatio(customRatio)) {
82
+ return false
83
+ }
84
+ return this.verifyCustomContrastRatio(contrastRatio, customRatio)
85
+ } else {
86
+ return this.verifyContrastRatio(contrastRatio)
87
+ }
88
+ }
89
+
90
+ checkPairs = (pairs: Pair[], customRatio?: number) => {
91
+ const results = []
92
+
93
+ for (const i in pairs) {
94
+ const pair = pairs[i]
95
+ if (typeof pair.fontSize !== 'undefined') {
96
+ results.push(this.check(pair.colorA, pair.colorB, pair.fontSize, customRatio))
97
+ } else {
98
+ results.push(this.check(pair.colorA, pair.colorB, void 0, customRatio))
99
+ }
100
+ }
101
+ return results
102
+ }
103
+
104
+ calculateLuminance = (lRGB: Rgb) => {
105
+ return 0.2126 * lRGB.r + 0.7152 * lRGB.g + 0.0722 * lRGB.b
106
+ }
107
+
108
+ isLevelAA = (colorA: string, colorB: string, fontSize: number) => {
109
+ const result = this.check(colorA, colorB, fontSize)
110
+ return result.WCAG_AA
111
+ }
112
+
113
+ isLevelAAA = (colorA: string, colorB: string, fontSize: number) => {
114
+ const result = this.check(colorA, colorB, fontSize)
115
+ return result.WCAG_AAA
116
+ }
117
+
118
+ isLevelCustom = (colorA: string, colorB: string, ratio: number) => {
119
+ const result = this.check(colorA, colorB, undefined, ratio)
120
+ return result.customRatio
121
+ }
122
+
123
+ getRGBFromHex = (color: string) => {
124
+ const rgb = new RgbClass()
125
+
126
+ if (typeof color !== 'string') {
127
+ throw new Error('must use string')
128
+ }
129
+
130
+ const rVal = parseInt(color.slice(1, 3), 16)
131
+ const gVal = parseInt(color.slice(3, 5), 16)
132
+ const bVal = parseInt(color.slice(5, 7), 16)
133
+
134
+ rgb.r = rVal
135
+ rgb.g = gVal
136
+ rgb.b = bVal
137
+
138
+ return rgb
139
+ }
140
+
141
+ calculateSRGB = (rgb: Rgb) => {
142
+ const sRGB = new RgbClass()
143
+
144
+ for (const key in rgb) {
145
+ sRGB[key as keyof Rgb] = parseFloat((rgb[key as keyof Rgb] / 255).toString())
146
+ }
147
+
148
+ return sRGB
149
+ }
150
+
151
+ calculateLRGB = (rgb: Rgb) => {
152
+ const sRGB = this.calculateSRGB(rgb)
153
+ const lRGB = Object.create(this.rgbClass)
154
+ let val = 0
155
+
156
+ for (const key in sRGB) {
157
+ //@ts-ignore
158
+ val = parseFloat(sRGB[key])
159
+ if (val <= 0.03928) {
160
+ lRGB[key] = val / 12.92
161
+ } else {
162
+ lRGB[key] = Math.pow((val + 0.055) / 1.055, 2.4)
163
+ }
164
+ }
165
+
166
+ return lRGB
167
+ }
168
+
169
+ getContrastRatio = (lumA: number, lumB: number) => {
170
+ let lighter: number
171
+ let darker: number
172
+
173
+ if (lumA >= lumB) {
174
+ lighter = lumA
175
+ darker = lumB
176
+ } else {
177
+ lighter = lumB
178
+ darker = lumA
179
+ }
180
+
181
+ const ratio = (lighter + 0.05) / (darker + 0.05)
182
+
183
+ return ratio
184
+ }
185
+
186
+ verifyContrastRatio = (ratio: number) => {
187
+ const WCAG_REQ_RATIO_AA_LG = 3.0,
188
+ WCAG_REQ_RATIO_AA_SM = 4.5,
189
+ WCAG_REQ_RATIO_AAA_LG = 4.5,
190
+ WCAG_REQ_RATIO_AAA_SM = 7.0,
191
+ WCAG_FONT_CUTOFF = 18
192
+
193
+ const results = new Result()
194
+ const fontSize = this.fontSize || 14
195
+
196
+ if (fontSize >= WCAG_FONT_CUTOFF) {
197
+ results.WCAG_AA = ratio >= WCAG_REQ_RATIO_AA_LG
198
+ results.WCAG_AAA = ratio >= WCAG_REQ_RATIO_AAA_LG
199
+ } else {
200
+ results.WCAG_AA = ratio >= WCAG_REQ_RATIO_AA_SM
201
+ results.WCAG_AAA = ratio >= WCAG_REQ_RATIO_AAA_SM
202
+ }
203
+
204
+ return results
205
+ }
206
+
207
+ verifyCustomContrastRatio = (inputRatio: number, checkRatio: number) => {
208
+ const resultsClass = new Result()
209
+ resultsClass.toString = function () {
210
+ return '< Custom Ratio: ' + (this.customRatio ? 'pass' : 'fail') + ' >'
211
+ }
212
+
213
+ const results = Object.create(resultsClass)
214
+
215
+ results.customRatio = inputRatio >= checkRatio
216
+ return results
217
+ }
218
+ }
@@ -0,0 +1,40 @@
1
+ import { ColorContrastChecker } from './color-contrast-checker'
2
+
3
+ export const getContrastPairs = (colorA: string, colorB: string) => {
4
+ const contrastChecker = new ColorContrastChecker()
5
+ let res
6
+ try {
7
+ res = contrastChecker.checkPairs([
8
+ {
9
+ colorA,
10
+ colorB,
11
+ fontSize: 14,
12
+ },
13
+ {
14
+ colorA,
15
+ colorB,
16
+ fontSize: 18,
17
+ },
18
+ ])
19
+ } catch (error) {
20
+ //
21
+ }
22
+
23
+ return res
24
+ }
25
+
26
+ export const getContrastRatio = (colorA: string, colorB: string) => {
27
+ const contrastChecker = new ColorContrastChecker()
28
+ let luminanceA, luminanceB
29
+ let ratio: number | undefined
30
+
31
+ try {
32
+ luminanceA = contrastChecker.hexToLuminance(colorA)
33
+ luminanceB = contrastChecker.hexToLuminance(colorB)
34
+ ratio = contrastChecker.getContrastRatio(luminanceA, luminanceB)
35
+ } catch (error) {
36
+ //
37
+ }
38
+
39
+ return ratio
40
+ }
@@ -0,0 +1,140 @@
1
+ import {
2
+ ColorContrastIcon,
3
+ ColorIcon,
4
+ FontSizesIcon,
5
+ FontWeightIcon,
6
+ LayerStylesIcon,
7
+ LetterSpacingIcon,
8
+ LineHeightIcon,
9
+ SizesIcon,
10
+ SpacingIcon,
11
+ TextStylesIcon,
12
+ TypographyIcon,
13
+ } from '../components/icons'
14
+
15
+ export enum NavKeys {
16
+ RADII = 'radii',
17
+ COLORS = 'colors',
18
+ LETTER_SPACINGS = 'letter-spacings',
19
+ LINE_HEIGHTS = 'line-heights',
20
+ FONT_WEIGHTS = 'font-weights',
21
+ FONT_SIZES = 'font-sizes',
22
+ SIZES = 'sizes',
23
+ SPACING = 'spacing',
24
+ FONTS = 'fonts',
25
+ TEXT_STYLES = 'text-styles',
26
+ LAYER_STYLES = 'layer-styles',
27
+ TOKEN_ANALYZER = 'token-analyzer',
28
+ TYPOGRAPHY_PLAYGROUND = 'playground/typography',
29
+ SPACING_PLAYGROUND = 'playground/spacing',
30
+ CONTRAST_CHECKER = 'playground/contrast-checker',
31
+ }
32
+
33
+ export type NavItemData = {
34
+ label: string
35
+ id: NavKeys
36
+ description: string
37
+ icon: React.ElementType
38
+ type: string
39
+ }
40
+
41
+ export const navItems: NavItemData[] = [
42
+ {
43
+ label: 'Colors',
44
+ id: NavKeys.COLORS,
45
+ description: 'A solid color palette for any context',
46
+ icon: ColorIcon,
47
+ type: 'token',
48
+ },
49
+ {
50
+ label: 'Fonts',
51
+ id: NavKeys.FONTS,
52
+ description: 'Preview your pre configured fonts.',
53
+ icon: FontSizesIcon,
54
+ type: 'token',
55
+ },
56
+ {
57
+ label: 'Letter Spacings',
58
+ id: NavKeys.LETTER_SPACINGS,
59
+ description: 'Letter spacing is the space between text characters.',
60
+ icon: LetterSpacingIcon,
61
+ type: 'token',
62
+ },
63
+ {
64
+ label: 'Line Heights',
65
+ id: NavKeys.LINE_HEIGHTS,
66
+ description: 'Line height is the vertical distance between two lines.',
67
+ icon: LineHeightIcon,
68
+ type: 'token',
69
+ },
70
+ {
71
+ label: 'Font Weights',
72
+ id: NavKeys.FONT_WEIGHTS,
73
+ description: 'Font weight determines how bold or light text appears.',
74
+ icon: FontWeightIcon,
75
+ type: 'token',
76
+ },
77
+ {
78
+ label: 'Font Sizes',
79
+ id: NavKeys.FONT_SIZES,
80
+ description: 'Font size updates the size of a font, and its relative units.',
81
+ icon: FontSizesIcon,
82
+ type: 'token',
83
+ },
84
+ {
85
+ label: 'Sizes',
86
+ id: NavKeys.SIZES,
87
+ description: 'Preview your pre configured sizes.',
88
+ icon: SizesIcon,
89
+ type: 'token',
90
+ },
91
+ {
92
+ label: 'Spacing',
93
+ id: NavKeys.SPACING,
94
+ description: 'Preview your pre configured spacing.',
95
+ icon: SpacingIcon,
96
+ type: 'token',
97
+ },
98
+ {
99
+ label: 'Border Radius',
100
+ id: NavKeys.RADII,
101
+ description: 'Preview your pre configured radii.',
102
+ icon: SizesIcon,
103
+ type: 'token',
104
+ },
105
+ {
106
+ label: 'Text Styles',
107
+ id: NavKeys.TEXT_STYLES,
108
+ description: 'Preview your pre configured text styles.',
109
+ icon: TextStylesIcon,
110
+ type: 'token',
111
+ },
112
+ {
113
+ label: 'Layer Styles',
114
+ id: NavKeys.LAYER_STYLES,
115
+ description: 'Preview your pre configured layer styles.',
116
+ icon: LayerStylesIcon,
117
+ type: 'token',
118
+ },
119
+ // {
120
+ // label: 'Token analyzer',
121
+ // id: NavKeys.TOKEN_ANALYZER,
122
+ // description: 'Visualize your tokens usage in your app.',
123
+ // icon: LayerStylesIcon,
124
+ // type: 'token',
125
+ // },
126
+ {
127
+ label: 'Typography',
128
+ id: NavKeys.TYPOGRAPHY_PLAYGROUND,
129
+ description: 'Visually test font styles with any text.',
130
+ icon: TypographyIcon,
131
+ type: 'playground',
132
+ },
133
+ {
134
+ label: 'Color Contrast',
135
+ id: NavKeys.CONTRAST_CHECKER,
136
+ description: 'Test contrast ratio between two colors.',
137
+ icon: ColorContrastIcon,
138
+ type: 'playground',
139
+ },
140
+ ]
@@ -0,0 +1,27 @@
1
+ import { createContext as createReactContext, useContext as useReactContext } from 'react'
2
+
3
+ function getErrorMessage(hook: string, provider: string) {
4
+ return `${hook} returned \`undefined\`. Seems you forgot to wrap component within ${provider}`
5
+ }
6
+ export function createContext<T>(
7
+ options: { name: string; strict?: boolean; hookName?: string; providerName?: string; errorMessage?: string } = {
8
+ name: '',
9
+ },
10
+ ) {
11
+ const { name, strict = true, hookName = 'useContext', providerName = 'Provider', errorMessage } = options
12
+ const Context = createReactContext<T>(undefined as T)
13
+ Context.displayName = name
14
+
15
+ function useContext() {
16
+ const context = useReactContext(Context)
17
+ if (!context && strict) {
18
+ const error = new Error(errorMessage ?? getErrorMessage(hookName, providerName))
19
+ error.name = 'ContextError'
20
+ Error.captureStackTrace?.(error, useContext)
21
+ throw error
22
+ }
23
+ return context
24
+ }
25
+
26
+ return [Context.Provider, useContext, Context] as const
27
+ }
@@ -0,0 +1,41 @@
1
+ import type { ReportItemJSON } from '@pandacss/types'
2
+ import { analysisData } from './analysis-data'
3
+ import { pick } from './pick'
4
+
5
+ export const getReportItem = (id: ReportItemJSON['id']) =>
6
+ (analysisData.details.byId as Record<string, any>)[id] as ReportItemJSON
7
+
8
+ export type SearchableReportItemAttributes = Partial<
9
+ Pick<ReportItemJSON, 'value' | 'category' | 'propName' | 'filepath' | 'from' | 'isKnown'> & {
10
+ important?: boolean
11
+ }
12
+ >
13
+
14
+ export const getUtilityLink = (reportItem: SearchableReportItemAttributes) => {
15
+ const searchParams = new URLSearchParams(
16
+ pick(reportItem, ['value', 'category', 'propName', 'from', 'filepath', 'isKnown', 'important']) as any,
17
+ )
18
+ return `/token-analyzer/utility?${searchParams.toString()}`
19
+ }
20
+
21
+ export const getFileLink = (reportItem: SearchableReportItemAttributes) => {
22
+ const searchParams = new URLSearchParams(pick(reportItem, ['filepath']) as any)
23
+ return `/token-analyzer/file?${searchParams.toString()}`
24
+ }
25
+
26
+ export const getReportItemFromTokenName = (tokenName: string) => {
27
+ const reportItem = analysisData.details.globalMaps.byTokenName[tokenName]?.[0]
28
+ return getReportItem(reportItem)
29
+ }
30
+
31
+ export const getReportRelativeFilePath = (filePath: string) => filePath.replace(analysisData.cwd + '/', '')
32
+ export const getReportRange = (reportItem: ReportItemJSON) => `:${reportItem.box.line}:${reportItem.box.column}`
33
+
34
+ const openInEditor = (filepath: string, line: number, column: number) => {
35
+ return fetch(`/__open-in-editor?file=${encodeURIComponent(`${filepath}:${line}:${column}`)}`)
36
+ }
37
+
38
+ export const openReportItemInEditor = (reportItem: ReportItemJSON) => {
39
+ console.log(reportItem)
40
+ return openInEditor(reportItem.filepath, reportItem.box.line, reportItem.box.column)
41
+ }
@@ -0,0 +1,35 @@
1
+ export function groupIn<Key extends keyof T, T extends Record<string, any>>(
2
+ array: T[],
3
+ keyOrGetter: Key,
4
+ ): Record<T[Key], T>
5
+ export function groupIn<T, KeyReturnT>(
6
+ array: T[],
7
+ keyOrGetter: (item: T) => KeyReturnT,
8
+ ): KeyReturnT extends string | number ? Record<KeyReturnT, T> : never
9
+ export function groupIn<Key, T>(array: T[], keyOrGetter: Key) {
10
+ let kv
11
+ return array.reduce((r, a) => {
12
+ kv = typeof keyOrGetter === 'function' ? keyOrGetter(a) : a[keyOrGetter as unknown as keyof T]
13
+ // @ts-ignore
14
+ r[kv] = a
15
+ return r
16
+ }, {})
17
+ }
18
+
19
+ export function groupBy<Key extends keyof T, T extends Record<string, any>>(
20
+ array: T[],
21
+ keyOrGetter: Key,
22
+ ): Record<T[Key], T[]>
23
+ export function groupBy<T, KeyReturnT>(
24
+ array: T[],
25
+ keyOrGetter: (item: T) => KeyReturnT,
26
+ ): KeyReturnT extends string | number ? Record<KeyReturnT, T[]> : never
27
+ export function groupBy<Key, T>(array: T[], keyOrGetter: Key) {
28
+ let kv
29
+ return array.reduce((r, a) => {
30
+ kv = typeof keyOrGetter === 'function' ? keyOrGetter(a) : a[keyOrGetter as unknown as keyof T]
31
+ // @ts-ignore
32
+ r[kv] = [...(r[kv] || []), a]
33
+ return r
34
+ }, {})
35
+ }
@@ -0,0 +1,23 @@
1
+ import { flatten } from '@pandacss/shared'
2
+ import { TokenDictionary } from '@pandacss/token-dictionary'
3
+ import type { TokenDataTypes, UserConfig } from '@pandacss/types'
4
+
5
+ // @ts-ignore
6
+ import { config as _config } from 'virtual:panda'
7
+
8
+ const config = _config as UserConfig
9
+
10
+ const { theme } = config
11
+
12
+ const context = {
13
+ tokens: new TokenDictionary(theme ?? {}),
14
+ getCategory(category: keyof TokenDataTypes) {
15
+ return this.tokens.categoryMap.get(category)!
16
+ },
17
+ textStyles: flatten(theme?.textStyles ?? {}),
18
+ layerStyles: flatten(theme?.layerStyles ?? {}),
19
+ logo: config.studio?.logo,
20
+ inject: config.studio?.inject ?? { head: '', body: '' },
21
+ }
22
+
23
+ export default context
@@ -0,0 +1,24 @@
1
+ /** Pick given properties in object */
2
+ export function pick<T, K extends keyof T>(obj: T, paths: K[]): Pick<T, K> {
3
+ const result = {} as Pick<T, K>
4
+
5
+ Object.keys(obj as any).forEach((key) => {
6
+ if (!paths.includes(key as K)) return
7
+ // @ts-expect-error
8
+ result[key] = obj[key]
9
+ })
10
+
11
+ return result as Pick<T, K>
12
+ }
13
+
14
+ /** Omit given properties from object */
15
+ export function omit<T extends Record<string, any>, K extends keyof T>(object: T, keys: K[]) {
16
+ const result: Record<string, any> = {}
17
+
18
+ Object.keys(object).forEach((key) => {
19
+ if (keys.includes(key as K)) return
20
+ result[key] = object[key]
21
+ })
22
+
23
+ return result as Omit<T, K>
24
+ }
@@ -0,0 +1,10 @@
1
+ import { toPx } from '@pandacss/shared'
2
+
3
+ const num = (v: string | undefined) => parseFloat(toPx(v) ?? '-1')
4
+
5
+ export function getSortedSizes(sizes: any[]) {
6
+ return sizes.sort((a, b) => {
7
+ if (!a.originalValue || !b.originalValue) return 0
8
+ return num(a.originalValue) - num(b.originalValue)
9
+ })
10
+ }
@@ -0,0 +1,7 @@
1
+ export const truncate = (str: string, length = 15) => {
2
+ if (str.length > length) {
3
+ return str.substring(0, length) + '...'
4
+ }
5
+
6
+ return str
7
+ }
@@ -0,0 +1,101 @@
1
+ import type { Token } from '@pandacss/types'
2
+ import { useState } from 'react'
3
+ import context from './panda.context'
4
+
5
+ type Color = {
6
+ isConditional?: boolean
7
+ isReference?: boolean
8
+ name: string
9
+ originalValue: string
10
+ path: string[]
11
+ }
12
+
13
+ type ColorToken = Token & Color
14
+
15
+ const UNCATEGORIZED_ID = 'uncategorized' as const
16
+
17
+ const groupByColorPalette = (colors: Map<string, any>, filterMethod?: (token: ColorToken) => boolean) => {
18
+ const values = Array.from(colors.values()).filter((color) => !color.isConditional && !color.extensions.isVirtual)
19
+ return values.reduce((acc, nxt) => {
20
+ if (!filterMethod?.(nxt)) return acc
21
+
22
+ const colorPalette = nxt.extensions.colorPalette || UNCATEGORIZED_ID
23
+ if (!(colorPalette in acc)) acc[colorPalette] = []
24
+ const exists = (acc[colorPalette] as any[]).find((tok) => tok.name === nxt.name)
25
+ if (!exists) acc[colorPalette].push(nxt)
26
+ return acc
27
+ }, {})
28
+ }
29
+
30
+ const getSemanticTokens = (allTokens: ColorToken[], filterMethod?: (token: ColorToken) => boolean) => {
31
+ const semanticTokens = allTokens.filter(
32
+ (token) => token.type === 'color' && token.isConditional && !token.extensions?.isVirtual,
33
+ )
34
+ return semanticTokens
35
+ .reduce((acc, nxt) => {
36
+ if (!filterMethod) {
37
+ acc.push(nxt)
38
+ } else {
39
+ const rawQualified = semanticTokens.filter(filterMethod)
40
+
41
+ if (filterMethod(nxt) || rawQualified.some((tok) => tok.name === nxt.name)) {
42
+ acc.push(nxt)
43
+ }
44
+ }
45
+ return acc
46
+ }, [] as ColorToken[])
47
+ .reduce(
48
+ (acc, nxt) => ({
49
+ ...acc,
50
+ [nxt.extensions?.prop]: {
51
+ //@ts-expect-error
52
+ ...acc[nxt.extensions?.prop],
53
+ [nxt.extensions?.condition]: { value: nxt.value, isReference: nxt.isReference },
54
+ extensions: nxt.extensions,
55
+ },
56
+ }),
57
+ {},
58
+ )
59
+ }
60
+
61
+ const allTokens = context.tokens.allTokens
62
+ const colors = context.getCategory('colors')
63
+
64
+ export const useColorDocs = () => {
65
+ const [filterQuery, setFilterQuery] = useState('')
66
+
67
+ const filterMethod = (token: ColorToken) => {
68
+ return [
69
+ ...token.path,
70
+ token.originalValue,
71
+ token.description,
72
+ token.value,
73
+ token.name,
74
+ token.extensions?.var,
75
+ token.extensions?.prop,
76
+ ...Object.values(token.extensions?.conditions || {}),
77
+ ]
78
+ .filter(Boolean)
79
+ .some((prop) => prop.includes(filterQuery))
80
+ }
81
+
82
+ const colorsInCategories = groupByColorPalette(colors, filterMethod)
83
+ const uncategorizedColors = colorsInCategories[UNCATEGORIZED_ID]
84
+
85
+ const categorizedColors = Object.entries<any[]>(colorsInCategories).filter(
86
+ ([category]) => category !== UNCATEGORIZED_ID,
87
+ )
88
+
89
+ const semanticTokens = Object.entries<Record<string, any>>(getSemanticTokens(allTokens, filterMethod))
90
+ const hasResults =
91
+ !!categorizedColors.length || !!uncategorizedColors?.length || !!Object.values(semanticTokens).length
92
+
93
+ return {
94
+ filterQuery,
95
+ setFilterQuery,
96
+ uncategorizedColors,
97
+ categorizedColors,
98
+ semanticTokens,
99
+ hasResults,
100
+ }
101
+ }
@@ -0,0 +1,11 @@
1
+ ---
2
+ import { Colors } from '../components/colors'
3
+ import Layout from '../layouts/Layout.astro'
4
+ import Sidebar from '../layouts/Sidebar.astro'
5
+ ---
6
+
7
+ <Layout>
8
+ <Sidebar title="Colors">
9
+ <Colors client:load />
10
+ </Sidebar>
11
+ </Layout>