typewritingclass 0.2.0

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 (53) hide show
  1. package/README.md +107 -0
  2. package/package.json +71 -0
  3. package/src/css.ts +140 -0
  4. package/src/cx.ts +105 -0
  5. package/src/dcx.ts +79 -0
  6. package/src/dynamic.ts +117 -0
  7. package/src/hash.ts +54 -0
  8. package/src/index.ts +137 -0
  9. package/src/inject.ts +86 -0
  10. package/src/layer.ts +81 -0
  11. package/src/modifiers/aria.ts +15 -0
  12. package/src/modifiers/colorScheme.ts +32 -0
  13. package/src/modifiers/data.ts +6 -0
  14. package/src/modifiers/direction.ts +5 -0
  15. package/src/modifiers/group.ts +21 -0
  16. package/src/modifiers/index.ts +17 -0
  17. package/src/modifiers/media.ts +11 -0
  18. package/src/modifiers/peer.ts +24 -0
  19. package/src/modifiers/pseudo.ts +183 -0
  20. package/src/modifiers/pseudoElements.ts +26 -0
  21. package/src/modifiers/responsive.ts +110 -0
  22. package/src/modifiers/supports.ts +6 -0
  23. package/src/registry.ts +171 -0
  24. package/src/rule.ts +202 -0
  25. package/src/runtime.ts +36 -0
  26. package/src/theme/animations.ts +11 -0
  27. package/src/theme/borders.ts +9 -0
  28. package/src/theme/colors.ts +326 -0
  29. package/src/theme/createTheme.ts +238 -0
  30. package/src/theme/filters.ts +20 -0
  31. package/src/theme/index.ts +9 -0
  32. package/src/theme/inject-theme.ts +81 -0
  33. package/src/theme/shadows.ts +8 -0
  34. package/src/theme/sizes.ts +37 -0
  35. package/src/theme/spacing.ts +44 -0
  36. package/src/theme/typography.ts +72 -0
  37. package/src/types.ts +273 -0
  38. package/src/utilities/accessibility.ts +33 -0
  39. package/src/utilities/backgrounds.ts +86 -0
  40. package/src/utilities/borders.ts +610 -0
  41. package/src/utilities/colors.ts +127 -0
  42. package/src/utilities/effects.ts +169 -0
  43. package/src/utilities/filters.ts +96 -0
  44. package/src/utilities/index.ts +57 -0
  45. package/src/utilities/interactivity.ts +253 -0
  46. package/src/utilities/layout.ts +1149 -0
  47. package/src/utilities/spacing.ts +681 -0
  48. package/src/utilities/svg.ts +34 -0
  49. package/src/utilities/tables.ts +54 -0
  50. package/src/utilities/transforms.ts +85 -0
  51. package/src/utilities/transitions.ts +98 -0
  52. package/src/utilities/typography.ts +380 -0
  53. package/src/when.ts +63 -0
@@ -0,0 +1,37 @@
1
+ export const full = '100%'
2
+ export const screen = '100vw'
3
+ export const screenH = '100vh'
4
+ export const min = 'min-content'
5
+ export const max = 'max-content'
6
+ export const fit = 'fit-content'
7
+ export const auto = 'auto'
8
+
9
+ // ---------------------------------------------------------------------------
10
+ // Max-width scale (Tailwind v3 defaults)
11
+ // ---------------------------------------------------------------------------
12
+
13
+ export const maxWidths = {
14
+ none: 'none',
15
+ 0: '0rem',
16
+ xs: '20rem',
17
+ sm: '24rem',
18
+ md: '28rem',
19
+ lg: '32rem',
20
+ xl: '36rem',
21
+ '2xl': '42rem',
22
+ '3xl': '48rem',
23
+ '4xl': '56rem',
24
+ '5xl': '64rem',
25
+ '6xl': '72rem',
26
+ '7xl': '80rem',
27
+ full: '100%',
28
+ min: 'min-content',
29
+ max: 'max-content',
30
+ fit: 'fit-content',
31
+ prose: '65ch',
32
+ screenSm: '640px',
33
+ screenMd: '768px',
34
+ screenLg: '1024px',
35
+ screenXl: '1280px',
36
+ screen2xl: '1536px',
37
+ } as const
@@ -0,0 +1,44 @@
1
+ const spacingScale: Record<number, string> = {
2
+ 0: '0px',
3
+ 0.5: '0.125rem',
4
+ 1: '0.25rem',
5
+ 1.5: '0.375rem',
6
+ 2: '0.5rem',
7
+ 2.5: '0.625rem',
8
+ 3: '0.75rem',
9
+ 3.5: '0.875rem',
10
+ 4: '1rem',
11
+ 5: '1.25rem',
12
+ 6: '1.5rem',
13
+ 7: '1.75rem',
14
+ 8: '2rem',
15
+ 9: '2.25rem',
16
+ 10: '2.5rem',
17
+ 11: '2.75rem',
18
+ 12: '3rem',
19
+ 14: '3.5rem',
20
+ 16: '4rem',
21
+ 20: '5rem',
22
+ 24: '6rem',
23
+ 28: '7rem',
24
+ 32: '8rem',
25
+ 36: '9rem',
26
+ 40: '10rem',
27
+ 44: '11rem',
28
+ 48: '12rem',
29
+ 52: '13rem',
30
+ 56: '14rem',
31
+ 60: '15rem',
32
+ 64: '16rem',
33
+ 72: '18rem',
34
+ 80: '20rem',
35
+ 96: '24rem',
36
+ }
37
+
38
+ export function resolveSpacing(value: number | string): string {
39
+ if (typeof value === 'string') return value
40
+ if (value in spacingScale) return spacingScale[value]
41
+ return `${value * 0.25}rem`
42
+ }
43
+
44
+ export { spacingScale }
@@ -0,0 +1,72 @@
1
+ export interface TextSize {
2
+ fontSize: string
3
+ lineHeight: string
4
+ }
5
+
6
+ export const xs: TextSize = { fontSize: '0.75rem', lineHeight: '1rem' }
7
+ export const sm: TextSize = { fontSize: '0.875rem', lineHeight: '1.25rem' }
8
+ export const base: TextSize = { fontSize: '1rem', lineHeight: '1.5rem' }
9
+ export const lg: TextSize = { fontSize: '1.125rem', lineHeight: '1.75rem' }
10
+ export const xl: TextSize = { fontSize: '1.25rem', lineHeight: '1.75rem' }
11
+ export const _2xl: TextSize = { fontSize: '1.5rem', lineHeight: '2rem' }
12
+ export const _3xl: TextSize = { fontSize: '1.875rem', lineHeight: '2.25rem' }
13
+ export const _4xl: TextSize = { fontSize: '2.25rem', lineHeight: '2.5rem' }
14
+ export const _5xl: TextSize = { fontSize: '3rem', lineHeight: '1' }
15
+ export const _6xl: TextSize = { fontSize: '3.75rem', lineHeight: '1' }
16
+ export const _7xl: TextSize = { fontSize: '4.5rem', lineHeight: '1' }
17
+ export const _8xl: TextSize = { fontSize: '6rem', lineHeight: '1' }
18
+ export const _9xl: TextSize = { fontSize: '8rem', lineHeight: '1' }
19
+
20
+ export const thin = '100'
21
+ export const extralight = '200'
22
+ export const light = '300'
23
+ export const normal = '400'
24
+ export const medium = '500'
25
+ export const semibold = '600'
26
+ export const bold = '700'
27
+ export const extrabold = '800'
28
+ export const black_ = '900'
29
+
30
+ // ---------------------------------------------------------------------------
31
+ // Font families (Tailwind v3 defaults)
32
+ // ---------------------------------------------------------------------------
33
+
34
+ export const fontFamilies = {
35
+ sans: 'ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"',
36
+ serif: 'ui-serif, Georgia, Cambria, "Times New Roman", Times, serif',
37
+ mono: 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace',
38
+ } as const
39
+
40
+ // ---------------------------------------------------------------------------
41
+ // Letter spacing / tracking (Tailwind v3 defaults)
42
+ // ---------------------------------------------------------------------------
43
+
44
+ export const letterSpacings = {
45
+ tighter: '-0.05em',
46
+ tight: '-0.025em',
47
+ normal: '0em',
48
+ wide: '0.025em',
49
+ wider: '0.05em',
50
+ widest: '0.1em',
51
+ } as const
52
+
53
+ // ---------------------------------------------------------------------------
54
+ // Line height / leading (Tailwind v3 defaults)
55
+ // ---------------------------------------------------------------------------
56
+
57
+ export const lineHeights = {
58
+ none: '1',
59
+ tight: '1.25',
60
+ snug: '1.375',
61
+ normal: '1.5',
62
+ relaxed: '1.625',
63
+ loose: '2',
64
+ '3': '.75rem',
65
+ '4': '1rem',
66
+ '5': '1.25rem',
67
+ '6': '1.5rem',
68
+ '7': '1.75rem',
69
+ '8': '2rem',
70
+ '9': '2.25rem',
71
+ '10': '2.5rem',
72
+ } as const
package/src/types.ts ADDED
@@ -0,0 +1,273 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Brand infrastructure
3
+ // ---------------------------------------------------------------------------
4
+
5
+ declare const __brand: unique symbol
6
+
7
+ /**
8
+ * Creates a nominal/branded type from a base type.
9
+ *
10
+ * Branded types look like their base type at runtime but are distinct at the
11
+ * type level, preventing accidental misuse (e.g. passing a color where a
12
+ * spacing value is expected).
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * type Meters = Brand<number, 'meters'>
17
+ * type Seconds = Brand<number, 'seconds'>
18
+ *
19
+ * const d: Meters = 5 as Meters
20
+ * const t: Seconds = d // Type error — distinct brands!
21
+ * ```
22
+ */
23
+ export type Brand<T, B extends string> = T & { readonly [__brand]: B }
24
+
25
+ // ---------------------------------------------------------------------------
26
+ // CSS value brands
27
+ // ---------------------------------------------------------------------------
28
+
29
+ /**
30
+ * A branded CSS color value — hex, `rgb()`, `hsl()`, CSS variable, etc.
31
+ *
32
+ * Theme color tokens (e.g. `blue[500]`) carry this brand. Raw color strings
33
+ * are also accepted alongside `CSSColor` since utility functions accept both.
34
+ */
35
+ export type CSSColor = Brand<string, 'css-color'>
36
+
37
+ /**
38
+ * A branded CSS length value — `rem`, `px`, `em`, `%`, `vh`, `vw`, etc.
39
+ *
40
+ * Theme spacing, size, and border-radius tokens carry this brand.
41
+ */
42
+ export type CSSLength = Brand<string, 'css-length'>
43
+
44
+ /**
45
+ * A branded CSS shadow value — `box-shadow` definition string.
46
+ *
47
+ * Theme shadow tokens (e.g. `lg` from `theme/shadows`) carry this brand.
48
+ */
49
+ export type CSSShadow = Brand<string, 'css-shadow'>
50
+
51
+ /**
52
+ * A branded CSS font-weight value — numeric string like `'400'` or `'700'`.
53
+ *
54
+ * Theme font weight tokens (e.g. `bold`, `semibold`) carry this brand.
55
+ */
56
+ export type CSSFontWeight = Brand<string, 'css-font-weight'>
57
+
58
+ // ---------------------------------------------------------------------------
59
+ // Utility input types
60
+ // ---------------------------------------------------------------------------
61
+
62
+ /** Shorthand for any DynamicValue — used in utility input types. */
63
+ type DynamicValueAny = import('./dynamic.ts').DynamicValue
64
+
65
+ /**
66
+ * Input type for color utilities ({@link bg}, {@link textColor}, {@link borderColor}).
67
+ *
68
+ * Accepts theme color tokens (`CSSColor`), raw CSS color strings, or dynamic values.
69
+ */
70
+ export type ColorInput = CSSColor | string | DynamicValueAny
71
+
72
+ /**
73
+ * Input type for spacing utilities ({@link p}, {@link m}, {@link gap}).
74
+ *
75
+ * Accepts a theme scale number (`4` → `1rem`), a raw CSS length string
76
+ * (`'1.5rem'`), a theme length token, or a dynamic value.
77
+ */
78
+ export type SpacingInput = number | CSSLength | string | DynamicValueAny
79
+
80
+ /**
81
+ * Input type for size utilities ({@link w}, {@link h}, {@link minW}).
82
+ *
83
+ * Accepts a theme scale number, a raw CSS string (`'100%'`), a theme size
84
+ * token (`full`, `screen`), or a dynamic value.
85
+ */
86
+ export type SizeInput = number | CSSLength | string | DynamicValueAny
87
+
88
+ /**
89
+ * Input type for border-radius utilities ({@link rounded}).
90
+ *
91
+ * Accepts a theme radius token (`lg`), a raw CSS string, or a dynamic value.
92
+ */
93
+ export type RadiusInput = CSSLength | string | DynamicValueAny
94
+
95
+ /**
96
+ * Input type for shadow utilities ({@link shadow}).
97
+ *
98
+ * Accepts a theme shadow token (`lg`), a raw CSS string, or a dynamic value.
99
+ */
100
+ export type ShadowInput = CSSShadow | string | DynamicValueAny
101
+
102
+ // ---------------------------------------------------------------------------
103
+ // Core types
104
+ // ---------------------------------------------------------------------------
105
+
106
+ /**
107
+ * A self-contained CSS rule produced by utility functions, the {@link css}
108
+ * helper, or modifier composition.
109
+ *
110
+ * `StyleRule` is the fundamental unit of the typewritingclass system. Every
111
+ * utility (`p`, `bg`, `rounded`, ...) returns a `StyleRule`, and composing
112
+ * functions like `cx` and `dcx` consume them to generate class names and
113
+ * register CSS in the global stylesheet.
114
+ *
115
+ * You rarely need to construct a `StyleRule` by hand -- use the provided
116
+ * utilities or the `css` tagged-template helper instead.
117
+ *
118
+ * @example Inspecting a rule returned by a utility
119
+ * ```ts
120
+ * import { p } from 'typewritingclass'
121
+ *
122
+ * const rule = p(4)
123
+ * // rule.declarations => { padding: '1rem' }
124
+ * // rule.selectors => []
125
+ * // rule.mediaQueries => []
126
+ * ```
127
+ *
128
+ * @example A rule wrapped with a modifier
129
+ * ```ts
130
+ * import { p, hover } from 'typewritingclass'
131
+ *
132
+ * const rule = hover(p(4))
133
+ * // rule.selectors => [':hover']
134
+ * // CSS: .className:hover { padding: 1rem; }
135
+ * ```
136
+ */
137
+ export interface StyleRule {
138
+ /** Discriminant tag used for runtime type narrowing. Always `'StyleRule'`. */
139
+ _tag: 'StyleRule'
140
+ /**
141
+ * A map of CSS property-value pairs that this rule will emit.
142
+ *
143
+ * Keys are CSS property names (e.g. `'padding'`, `'background-color'`),
144
+ * and values are their corresponding CSS values (e.g. `'1rem'`, `'#3b82f6'`).
145
+ */
146
+ declarations: Record<string, string>
147
+ /**
148
+ * Pseudo-class or pseudo-element selectors appended to the generated
149
+ * class name (e.g. `[':hover']`, `[':focus', ':active']`).
150
+ *
151
+ * An empty array means the rule applies unconditionally.
152
+ */
153
+ selectors: string[]
154
+ /**
155
+ * Media query strings that wrap the generated rule
156
+ * (e.g. `['(min-width: 768px)']`).
157
+ *
158
+ * An empty array means no `@media` wrapper is emitted.
159
+ */
160
+ mediaQueries: string[]
161
+ /**
162
+ * CSS custom property bindings for dynamic (runtime-changeable) values.
163
+ *
164
+ * When present, the generated CSS references `var(--twc-dN)` and these
165
+ * bindings must be applied as inline `style` on the element (via `dcx`).
166
+ * Keys are CSS custom property names (e.g. `'--twc-d0'`), values are
167
+ * the current runtime values (e.g. `'#ff0000'`).
168
+ */
169
+ dynamicBindings?: Record<string, string>
170
+ /**
171
+ * `@supports` query strings that wrap the generated rule
172
+ * (e.g. `['(display: grid)']`).
173
+ *
174
+ * An empty array means no `@supports` wrapper is emitted.
175
+ */
176
+ supportsQueries: string[]
177
+ /**
178
+ * Optional selector template that wraps the generated class name in a
179
+ * more complex selector pattern. The `&` character is replaced with the
180
+ * generated `.className` at render time.
181
+ *
182
+ * Used for utilities like `spaceX`/`spaceY` (child combinator selectors),
183
+ * `group-*` / `peer-*` modifiers, and `rtl`/`ltr` direction modifiers.
184
+ *
185
+ * @example
186
+ * ```ts
187
+ * // spaceX uses: '& > :not([hidden]) ~ :not([hidden])'
188
+ * // group-hover uses: '.group:hover &'
189
+ * ```
190
+ */
191
+ selectorTemplate?: string
192
+ }
193
+
194
+ /**
195
+ * A function that accepts a design-token value and returns a {@link StyleRule}.
196
+ *
197
+ * Every spacing, color, typography, and layout helper (`p`, `bg`, `text`, ...)
198
+ * satisfies this signature. The `value` parameter is intentionally `any` so
199
+ * that individual utilities can narrow it to their own accepted types
200
+ * (e.g. `number | string | DynamicValue`).
201
+ *
202
+ * @param value - The design-token or raw CSS value to apply.
203
+ * @returns A {@link StyleRule} containing the appropriate CSS declarations.
204
+ *
205
+ * @example
206
+ * ```ts
207
+ * import type { Utility } from 'typewritingclass'
208
+ * import { p } from 'typewritingclass'
209
+ *
210
+ * // `p` satisfies the Utility signature:
211
+ * const myUtility: Utility = p
212
+ * const rule = myUtility(4)
213
+ * // CSS: padding: 1rem;
214
+ * ```
215
+ */
216
+ export type Utility = (value: any) => StyleRule
217
+
218
+ /**
219
+ * A function that transforms a {@link StyleRule} by wrapping it with a
220
+ * pseudo-class selector or a media query.
221
+ *
222
+ * Modifiers are composable -- you can chain them via {@link when} to build
223
+ * multi-condition rules (e.g. "on hover, at medium breakpoint").
224
+ *
225
+ * @param rule - The source {@link StyleRule} to transform.
226
+ * @returns A new {@link StyleRule} with additional selectors or media queries.
227
+ *
228
+ * @example
229
+ * ```ts
230
+ * import type { Modifier } from 'typewritingclass'
231
+ * import { hover, md } from 'typewritingclass'
232
+ *
233
+ * // `hover` and `md` are both Modifiers:
234
+ * const hoverMod: Modifier = hover
235
+ * const mdMod: Modifier = md
236
+ * ```
237
+ */
238
+ export type Modifier = (rule: StyleRule) => StyleRule
239
+
240
+ /**
241
+ * The return value of {@link dcx}, containing both a class string and an
242
+ * inline `style` object for dynamic CSS custom-property bindings.
243
+ *
244
+ * Use this when your styles include runtime-changeable values created with
245
+ * {@link dynamic}. The `className` goes on the element's class attribute, and
246
+ * `style` must be spread onto the element's inline style so the CSS custom
247
+ * properties are set.
248
+ *
249
+ * @example
250
+ * ```ts
251
+ * import { dcx, bg, dynamic } from 'typewritingclass'
252
+ *
253
+ * const color = dynamic('#ff0000')
254
+ * const result = dcx(bg(color))
255
+ * // result.className => "_a1b2c"
256
+ * // result.style => { '--twc-d0': '#ff0000' }
257
+ *
258
+ * // In JSX:
259
+ * // <div className={result.className} style={result.style} />
260
+ * // CSS: .\_a1b2c { background-color: var(--twc-d0); }
261
+ * ```
262
+ */
263
+ export interface DynamicResult {
264
+ /** A space-separated string of generated CSS class names, ready for `className` or `class`. */
265
+ className: string
266
+ /**
267
+ * An object of CSS custom property assignments to apply as inline styles.
268
+ *
269
+ * Keys are custom property names (e.g. `'--twc-d0'`), values are the
270
+ * current runtime values (e.g. `'#ff0000'`, `'1.5rem'`).
271
+ */
272
+ style: Record<string, string>
273
+ }
@@ -0,0 +1,33 @@
1
+ import type { StyleRule } from '../types.ts'
2
+ import { createRule } from '../rule.ts'
3
+
4
+ export function srOnly(): StyleRule {
5
+ return createRule({
6
+ position: 'absolute',
7
+ width: '1px',
8
+ height: '1px',
9
+ padding: '0',
10
+ margin: '-1px',
11
+ overflow: 'hidden',
12
+ clip: 'rect(0, 0, 0, 0)',
13
+ 'white-space': 'nowrap',
14
+ 'border-width': '0',
15
+ })
16
+ }
17
+
18
+ export function notSrOnly(): StyleRule {
19
+ return createRule({
20
+ position: 'static',
21
+ width: 'auto',
22
+ height: 'auto',
23
+ padding: '0',
24
+ margin: '0',
25
+ overflow: 'visible',
26
+ clip: 'auto',
27
+ 'white-space': 'normal',
28
+ })
29
+ }
30
+
31
+ export function forcedColorAdjust(value: string): StyleRule {
32
+ return createRule({ 'forced-color-adjust': value })
33
+ }
@@ -0,0 +1,86 @@
1
+ import type { StyleRule } from '../types.ts'
2
+ import type { DynamicValue } from '../dynamic.ts'
3
+ import { createRule, createDynamicRule } from '../rule.ts'
4
+ import { isDynamic } from '../dynamic.ts'
5
+
6
+ export function bgAttachment(value: string): StyleRule {
7
+ return createRule({ 'background-attachment': value })
8
+ }
9
+
10
+ export function bgClip(value: string): StyleRule {
11
+ return createRule({ 'background-clip': value })
12
+ }
13
+
14
+ export function bgOrigin(value: string): StyleRule {
15
+ return createRule({ 'background-origin': value })
16
+ }
17
+
18
+ export function bgPosition(value: string | DynamicValue): StyleRule {
19
+ if (isDynamic(value)) {
20
+ return createDynamicRule(
21
+ { 'background-position': `var(${value.__id})` },
22
+ { [value.__id]: String(value.__value) },
23
+ )
24
+ }
25
+ return createRule({ 'background-position': value })
26
+ }
27
+
28
+ export function bgRepeat(value: string): StyleRule {
29
+ return createRule({ 'background-repeat': value })
30
+ }
31
+
32
+ export function bgSize(value: string | DynamicValue): StyleRule {
33
+ if (isDynamic(value)) {
34
+ return createDynamicRule(
35
+ { 'background-size': `var(${value.__id})` },
36
+ { [value.__id]: String(value.__value) },
37
+ )
38
+ }
39
+ return createRule({ 'background-size': value })
40
+ }
41
+
42
+ export function bgImage(value: string | DynamicValue): StyleRule {
43
+ if (isDynamic(value)) {
44
+ return createDynamicRule(
45
+ { 'background-image': `var(${value.__id})` },
46
+ { [value.__id]: String(value.__value) },
47
+ )
48
+ }
49
+ return createRule({ 'background-image': value })
50
+ }
51
+
52
+ export function bgGradient(direction: string = 'to right'): StyleRule {
53
+ return createRule({
54
+ 'background-image': `linear-gradient(${direction}, var(--twc-gradient-from, transparent), var(--twc-gradient-via, transparent), var(--twc-gradient-to, transparent))`,
55
+ })
56
+ }
57
+
58
+ export function gradientFrom(color: string | DynamicValue): StyleRule {
59
+ if (isDynamic(color)) {
60
+ return createDynamicRule(
61
+ { '--twc-gradient-from': `var(${color.__id})` },
62
+ { [color.__id]: String(color.__value) },
63
+ )
64
+ }
65
+ return createRule({ '--twc-gradient-from': color })
66
+ }
67
+
68
+ export function gradientVia(color: string | DynamicValue): StyleRule {
69
+ if (isDynamic(color)) {
70
+ return createDynamicRule(
71
+ { '--twc-gradient-via': `var(${color.__id})` },
72
+ { [color.__id]: String(color.__value) },
73
+ )
74
+ }
75
+ return createRule({ '--twc-gradient-via': color })
76
+ }
77
+
78
+ export function gradientTo(color: string | DynamicValue): StyleRule {
79
+ if (isDynamic(color)) {
80
+ return createDynamicRule(
81
+ { '--twc-gradient-to': `var(${color.__id})` },
82
+ { [color.__id]: String(color.__value) },
83
+ )
84
+ }
85
+ return createRule({ '--twc-gradient-to': color })
86
+ }