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,127 @@
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
+ /**
7
+ * Sets the background color of an element.
8
+ *
9
+ * Accepts a raw CSS color string or a {@link DynamicValue} for runtime values.
10
+ *
11
+ * @param color - CSS color string (e.g. `'#3b82f6'`, `'red'`, `'rgb(59, 130, 246)'`) or `dynamic()` value.
12
+ * @returns A {@link StyleRule} that sets `background-color`.
13
+ *
14
+ * @example CSS color string
15
+ * ```ts
16
+ * import { cx, bg } from 'typewritingclass'
17
+ *
18
+ * cx(bg('#3b82f6'))
19
+ * // CSS: background-color: #3b82f6;
20
+ * ```
21
+ *
22
+ * @example Named color
23
+ * ```ts
24
+ * cx(bg('transparent'))
25
+ * // CSS: background-color: transparent;
26
+ * ```
27
+ *
28
+ * @example Dynamic value
29
+ * ```ts
30
+ * import { dcx, bg, dynamic } from 'typewritingclass'
31
+ *
32
+ * const { className, style } = dcx(bg(dynamic(themeColor)))
33
+ * // CSS: background-color: var(--twc-d0);
34
+ * // style: { '--twc-d0': themeColor }
35
+ * ```
36
+ */
37
+ export function bg(color: string | DynamicValue): StyleRule {
38
+ if (isDynamic(color)) {
39
+ return createDynamicRule(
40
+ { 'background-color': `var(${color.__id})` },
41
+ { [color.__id]: String(color.__value) },
42
+ )
43
+ }
44
+ return createRule({ 'background-color': color })
45
+ }
46
+
47
+ /**
48
+ * Sets the text color of an element.
49
+ *
50
+ * Accepts a raw CSS color string or a {@link DynamicValue} for runtime values.
51
+ *
52
+ * @param color - CSS color string (e.g. `'#111827'`, `'white'`, `'rgb(17, 24, 39)'`) or `dynamic()` value.
53
+ * @returns A {@link StyleRule} that sets `color`.
54
+ *
55
+ * @example CSS color string
56
+ * ```ts
57
+ * import { cx, textColor } from 'typewritingclass'
58
+ *
59
+ * cx(textColor('#111827'))
60
+ * // CSS: color: #111827;
61
+ * ```
62
+ *
63
+ * @example Named color
64
+ * ```ts
65
+ * cx(textColor('inherit'))
66
+ * // CSS: color: inherit;
67
+ * ```
68
+ *
69
+ * @example Dynamic value
70
+ * ```ts
71
+ * import { dcx, textColor, dynamic } from 'typewritingclass'
72
+ *
73
+ * const { className, style } = dcx(textColor(dynamic(themeColor)))
74
+ * // CSS: color: var(--twc-d0);
75
+ * // style: { '--twc-d0': themeColor }
76
+ * ```
77
+ */
78
+ export function textColor(color: string | DynamicValue): StyleRule {
79
+ if (isDynamic(color)) {
80
+ return createDynamicRule(
81
+ { color: `var(${color.__id})` },
82
+ { [color.__id]: String(color.__value) },
83
+ )
84
+ }
85
+ return createRule({ color })
86
+ }
87
+
88
+ /**
89
+ * Sets the border color of an element.
90
+ *
91
+ * Accepts a raw CSS color string or a {@link DynamicValue} for runtime values.
92
+ *
93
+ * @param color - CSS color string (e.g. `'#e5e7eb'`, `'red'`, `'rgb(229, 231, 235)'`) or `dynamic()` value.
94
+ * @returns A {@link StyleRule} that sets `border-color`.
95
+ *
96
+ * @example CSS color string
97
+ * ```ts
98
+ * import { cx, borderColor } from 'typewritingclass'
99
+ *
100
+ * cx(borderColor('#e5e7eb'))
101
+ * // CSS: border-color: #e5e7eb;
102
+ * ```
103
+ *
104
+ * @example Named color
105
+ * ```ts
106
+ * cx(borderColor('currentColor'))
107
+ * // CSS: border-color: currentColor;
108
+ * ```
109
+ *
110
+ * @example Dynamic value
111
+ * ```ts
112
+ * import { dcx, borderColor, dynamic } from 'typewritingclass'
113
+ *
114
+ * const { className, style } = dcx(borderColor(dynamic(themeColor)))
115
+ * // CSS: border-color: var(--twc-d0);
116
+ * // style: { '--twc-d0': themeColor }
117
+ * ```
118
+ */
119
+ export function borderColor(color: string | DynamicValue): StyleRule {
120
+ if (isDynamic(color)) {
121
+ return createDynamicRule(
122
+ { 'border-color': `var(${color.__id})` },
123
+ { [color.__id]: String(color.__value) },
124
+ )
125
+ }
126
+ return createRule({ 'border-color': color })
127
+ }
@@ -0,0 +1,169 @@
1
+ import type { StyleRule } from '../types.ts'
2
+ import type { DynamicValue } from '../dynamic.ts'
3
+ import { createRule, createDynamicRule } from '../rule.ts'
4
+ import { DEFAULT as defaultShadow } from '../theme/shadows.ts'
5
+ import { isDynamic } from '../dynamic.ts'
6
+
7
+ /**
8
+ * Sets the `box-shadow` of an element.
9
+ *
10
+ * When called without arguments, uses the default shadow from the shadows theme
11
+ * (`0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)`).
12
+ * Accepts an optional raw CSS string or a {@link DynamicValue} for runtime values.
13
+ *
14
+ * @param value - Optional CSS box-shadow string or `dynamic()` value. Defaults to the theme's `DEFAULT` shadow.
15
+ * @returns A {@link StyleRule} that sets `box-shadow`.
16
+ *
17
+ * @example Default shadow
18
+ * ```ts
19
+ * import { cx, shadow } from 'typewritingclass'
20
+ *
21
+ * cx(shadow())
22
+ * // CSS: box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
23
+ * ```
24
+ *
25
+ * @example Custom shadow
26
+ * ```ts
27
+ * cx(shadow('0 4px 6px -1px rgb(0 0 0 / 0.1)'))
28
+ * // CSS: box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1);
29
+ * ```
30
+ *
31
+ * @example No shadow
32
+ * ```ts
33
+ * cx(shadow('none'))
34
+ * // CSS: box-shadow: none;
35
+ * ```
36
+ *
37
+ * @example Dynamic value
38
+ * ```ts
39
+ * import { dcx, shadow, dynamic } from 'typewritingclass'
40
+ *
41
+ * const { className, style } = dcx(shadow(dynamic(shadowValue)))
42
+ * // CSS: box-shadow: var(--twc-d0);
43
+ * // style: { '--twc-d0': shadowValue }
44
+ * ```
45
+ */
46
+ export function shadow(value?: string | DynamicValue): StyleRule {
47
+ if (isDynamic(value)) {
48
+ return createDynamicRule(
49
+ { 'box-shadow': `var(${value.__id})` },
50
+ { [value.__id]: String(value.__value) },
51
+ )
52
+ }
53
+ return createRule({ 'box-shadow': (value as string | undefined) ?? defaultShadow })
54
+ }
55
+
56
+ /**
57
+ * Sets the `opacity` of an element.
58
+ *
59
+ * Accepts a numeric opacity value (between `0` and `1`) or a {@link DynamicValue}
60
+ * for runtime values. The numeric value is converted to a string for the CSS declaration.
61
+ *
62
+ * @param value - A numeric opacity (`0` to `1`) or `dynamic()` value.
63
+ * @returns A {@link StyleRule} that sets `opacity`.
64
+ *
65
+ * @example Fully opaque
66
+ * ```ts
67
+ * import { cx, opacity } from 'typewritingclass'
68
+ *
69
+ * cx(opacity(1))
70
+ * // CSS: opacity: 1;
71
+ * ```
72
+ *
73
+ * @example Semi-transparent
74
+ * ```ts
75
+ * cx(opacity(0.5))
76
+ * // CSS: opacity: 0.5;
77
+ * ```
78
+ *
79
+ * @example Hidden
80
+ * ```ts
81
+ * cx(opacity(0))
82
+ * // CSS: opacity: 0;
83
+ * ```
84
+ *
85
+ * @example Dynamic value
86
+ * ```ts
87
+ * import { dcx, opacity, dynamic } from 'typewritingclass'
88
+ *
89
+ * const { className, style } = dcx(opacity(dynamic(opacityValue)))
90
+ * // CSS: opacity: var(--twc-d0);
91
+ * // style: { '--twc-d0': opacityValue }
92
+ * ```
93
+ */
94
+ export function opacity(value: number | DynamicValue): StyleRule {
95
+ if (isDynamic(value)) {
96
+ return createDynamicRule(
97
+ { opacity: `var(${value.__id})` },
98
+ { [value.__id]: String(value.__value) },
99
+ )
100
+ }
101
+ return createRule({ opacity: String(value) })
102
+ }
103
+
104
+ /**
105
+ * Sets the `backdrop-filter` CSS property on an element.
106
+ *
107
+ * Applies graphical effects (such as blurring or color shifting) to the area
108
+ * behind the element. Accepts a raw CSS backdrop-filter string or a
109
+ * {@link DynamicValue} for runtime values.
110
+ *
111
+ * @param value - A CSS backdrop-filter string (`'blur(8px)'`, `'saturate(180%)'`) or `dynamic()` value.
112
+ * @returns A {@link StyleRule} that sets `backdrop-filter`.
113
+ *
114
+ * @example Blur backdrop
115
+ * ```ts
116
+ * import { cx, backdrop } from 'typewritingclass'
117
+ *
118
+ * cx(backdrop('blur(8px)'))
119
+ * // CSS: backdrop-filter: blur(8px);
120
+ * ```
121
+ *
122
+ * @example Saturate backdrop
123
+ * ```ts
124
+ * cx(backdrop('saturate(180%)'))
125
+ * // CSS: backdrop-filter: saturate(180%);
126
+ * ```
127
+ *
128
+ * @example Combined filters
129
+ * ```ts
130
+ * cx(backdrop('blur(12px) saturate(150%)'))
131
+ * // CSS: backdrop-filter: blur(12px) saturate(150%);
132
+ * ```
133
+ *
134
+ * @example Dynamic value
135
+ * ```ts
136
+ * import { dcx, backdrop, dynamic } from 'typewritingclass'
137
+ *
138
+ * const { className, style } = dcx(backdrop(dynamic(filterValue)))
139
+ * // CSS: backdrop-filter: var(--twc-d0);
140
+ * // style: { '--twc-d0': filterValue }
141
+ * ```
142
+ */
143
+ export function backdrop(value: string | DynamicValue): StyleRule {
144
+ if (isDynamic(value)) {
145
+ return createDynamicRule(
146
+ { 'backdrop-filter': `var(${value.__id})` },
147
+ { [value.__id]: String(value.__value) },
148
+ )
149
+ }
150
+ return createRule({ 'backdrop-filter': value })
151
+ }
152
+
153
+ export function shadowColor(value: string | DynamicValue): StyleRule {
154
+ if (isDynamic(value)) {
155
+ return createDynamicRule(
156
+ { '--twc-shadow-color': `var(${value.__id})` },
157
+ { [value.__id]: String(value.__value) },
158
+ )
159
+ }
160
+ return createRule({ '--twc-shadow-color': value })
161
+ }
162
+
163
+ export function mixBlendMode(value: string): StyleRule {
164
+ return createRule({ 'mix-blend-mode': value })
165
+ }
166
+
167
+ export function bgBlendMode(value: string): StyleRule {
168
+ return createRule({ 'background-blend-mode': value })
169
+ }
@@ -0,0 +1,96 @@
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
+ function filterRule(fn: string, value: string | DynamicValue, prop: 'filter' | 'backdrop-filter' = 'filter'): StyleRule {
7
+ if (isDynamic(value)) {
8
+ return createDynamicRule(
9
+ { [prop]: `${fn}(var(${value.__id}))` },
10
+ { [value.__id]: String(value.__value) },
11
+ )
12
+ }
13
+ return createRule({ [prop]: `${fn}(${value})` })
14
+ }
15
+
16
+ // --- Filter utilities ---
17
+
18
+ export function blur(value: string | DynamicValue = '8px'): StyleRule {
19
+ return filterRule('blur', value)
20
+ }
21
+
22
+ export function brightness(value: string | DynamicValue): StyleRule {
23
+ return filterRule('brightness', value)
24
+ }
25
+
26
+ export function contrast(value: string | DynamicValue): StyleRule {
27
+ return filterRule('contrast', value)
28
+ }
29
+
30
+ export function dropShadow(value: string | DynamicValue): StyleRule {
31
+ if (isDynamic(value)) {
32
+ return createDynamicRule(
33
+ { filter: `drop-shadow(var(${value.__id}))` },
34
+ { [value.__id]: String(value.__value) },
35
+ )
36
+ }
37
+ return createRule({ filter: `drop-shadow(${value})` })
38
+ }
39
+
40
+ export function grayscale(value: string | DynamicValue = '100%'): StyleRule {
41
+ return filterRule('grayscale', value)
42
+ }
43
+
44
+ export function hueRotate(value: string | DynamicValue): StyleRule {
45
+ return filterRule('hue-rotate', value)
46
+ }
47
+
48
+ export function invert(value: string | DynamicValue = '100%'): StyleRule {
49
+ return filterRule('invert', value)
50
+ }
51
+
52
+ export function saturate(value: string | DynamicValue): StyleRule {
53
+ return filterRule('saturate', value)
54
+ }
55
+
56
+ export function sepia(value: string | DynamicValue = '100%'): StyleRule {
57
+ return filterRule('sepia', value)
58
+ }
59
+
60
+ // --- Backdrop filter utilities ---
61
+
62
+ export function backdropBlur(value: string | DynamicValue = '8px'): StyleRule {
63
+ return filterRule('blur', value, 'backdrop-filter')
64
+ }
65
+
66
+ export function backdropBrightness(value: string | DynamicValue): StyleRule {
67
+ return filterRule('brightness', value, 'backdrop-filter')
68
+ }
69
+
70
+ export function backdropContrast(value: string | DynamicValue): StyleRule {
71
+ return filterRule('contrast', value, 'backdrop-filter')
72
+ }
73
+
74
+ export function backdropGrayscale(value: string | DynamicValue = '100%'): StyleRule {
75
+ return filterRule('grayscale', value, 'backdrop-filter')
76
+ }
77
+
78
+ export function backdropHueRotate(value: string | DynamicValue): StyleRule {
79
+ return filterRule('hue-rotate', value, 'backdrop-filter')
80
+ }
81
+
82
+ export function backdropInvert(value: string | DynamicValue = '100%'): StyleRule {
83
+ return filterRule('invert', value, 'backdrop-filter')
84
+ }
85
+
86
+ export function backdropOpacity(value: string | DynamicValue): StyleRule {
87
+ return filterRule('opacity', value, 'backdrop-filter')
88
+ }
89
+
90
+ export function backdropSaturate(value: string | DynamicValue): StyleRule {
91
+ return filterRule('saturate', value, 'backdrop-filter')
92
+ }
93
+
94
+ export function backdropSepia(value: string | DynamicValue = '100%'): StyleRule {
95
+ return filterRule('sepia', value, 'backdrop-filter')
96
+ }
@@ -0,0 +1,57 @@
1
+ export { p, px, py, pt, pr, pb, pl, m, mx, my, mt, mr, mb, ml, gap, gapX, gapY, ps, pe, ms, me, spaceX, spaceY, spaceXReverse, spaceYReverse } from './spacing.ts'
2
+ export { bg, textColor, borderColor } from './colors.ts'
3
+ export { text, font, tracking, leading, textAlign, fontFamily, antialiased, subpixelAntialiased, italic, notItalic, normalNums, ordinal, slashedZero, liningNums, oldstyleNums, proportionalNums, tabularNums, diagonalFractions, stackedFractions, lineClamp, listStyleImage, listStylePosition, listStyleType, textDecoration, textDecorationColor, textDecorationStyle, textDecorationThickness, textUnderlineOffset, textTransform, textOverflow, textWrap, textIndent, verticalAlign, whitespace, wordBreak, hyphens, content_, truncate } from './typography.ts'
4
+ export {
5
+ flex, flexCol, flexRow, flexWrap, inlineFlex,
6
+ grid, gridCols, gridRows,
7
+ w, h, size, minW, minH, maxW, maxH,
8
+ display, items, justify, self,
9
+ overflow, overflowX, overflowY,
10
+ relative, absolute, fixed, sticky,
11
+ top, right, bottom, left, inset,
12
+ z,
13
+ aspectRatio, columns, breakAfter, breakBefore, breakInside,
14
+ boxDecorationBreak, boxSizing, float_, clear_, isolate, isolationAuto,
15
+ objectFit, objectPosition, overscrollBehavior, overscrollX, overscrollY,
16
+ static_, insetX, insetY, start, end,
17
+ visible, invisible, collapse_,
18
+ flexBasis, flexRowReverse, flexColReverse, flexWrapReverse, flexNowrap,
19
+ flex1, flexAuto, flexInitial, flexNone,
20
+ grow, shrink, order,
21
+ colSpan, colStart, colEnd, rowSpan, rowStart, rowEnd,
22
+ gridFlow, autoCols, autoRows,
23
+ justifyItems, justifySelf, alignContent, placeContent, placeItems, placeSelf,
24
+ container,
25
+ } from './layout.ts'
26
+ export {
27
+ rounded, roundedT, roundedB, roundedL, roundedR, border, borderT, borderR, borderB, borderL, ring,
28
+ roundedTL, roundedTR, roundedBR, roundedBL, roundedSS, roundedSE, roundedEE, roundedES,
29
+ borderX, borderY, borderS, borderE, borderStyle,
30
+ outlineWidth, outlineColor, outlineStyle, outlineOffset, outline, outlineNone,
31
+ ringColor, ringOffsetWidth, ringOffsetColor, ringInset,
32
+ divideX, divideY, divideColor, divideStyle, divideXReverse, divideYReverse,
33
+ } from './borders.ts'
34
+ export { shadow, opacity, backdrop, shadowColor, mixBlendMode, bgBlendMode } from './effects.ts'
35
+ export {
36
+ cursor, select, pointerEvents,
37
+ accentColor, appearance, caretColor, resize,
38
+ scrollBehavior, scrollMargin, scrollMarginX, scrollMarginY,
39
+ scrollMarginT, scrollMarginR, scrollMarginB, scrollMarginL,
40
+ scrollPadding, scrollPaddingX, scrollPaddingY,
41
+ scrollPaddingT, scrollPaddingR, scrollPaddingB, scrollPaddingL,
42
+ snapAlign, snapStop, snapType, touchAction, willChange,
43
+ } from './interactivity.ts'
44
+ export {
45
+ blur, brightness, contrast, dropShadow, grayscale, hueRotate, invert, saturate, sepia,
46
+ backdropBlur, backdropBrightness, backdropContrast, backdropGrayscale, backdropHueRotate,
47
+ backdropInvert, backdropOpacity, backdropSaturate, backdropSepia,
48
+ } from './filters.ts'
49
+ export { scale, scaleX, scaleY, rotate, translateX, translateY, skewX, skewY, transformOrigin, transformGpu, transformNone } from './transforms.ts'
50
+ export {
51
+ transition, transitionAll, transitionColors, transitionOpacity, transitionShadow, transitionTransform, transitionNone,
52
+ duration, ease, delay, animate,
53
+ } from './transitions.ts'
54
+ export { borderCollapse, borderSeparate, borderSpacing, borderSpacingX, borderSpacingY, tableLayout, captionSide } from './tables.ts'
55
+ export { fill, stroke, strokeWidth } from './svg.ts'
56
+ export { srOnly, notSrOnly, forcedColorAdjust } from './accessibility.ts'
57
+ export { bgAttachment, bgClip, bgOrigin, bgPosition, bgRepeat, bgSize, bgImage, bgGradient, gradientFrom, gradientVia, gradientTo } from './backgrounds.ts'
@@ -0,0 +1,253 @@
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
+ import { resolveSpacing } from '../theme/spacing.ts'
6
+
7
+ /**
8
+ * Sets the `cursor` style of an element.
9
+ *
10
+ * Accepts a raw CSS cursor string or a {@link DynamicValue} for runtime values.
11
+ *
12
+ * @param value - A CSS cursor value (`'pointer'`, `'grab'`, `'not-allowed'`, etc.) or `dynamic()` value.
13
+ * @returns A {@link StyleRule} that sets `cursor`.
14
+ *
15
+ * @example Pointer cursor
16
+ * ```ts
17
+ * import { cx, cursor } from 'typewritingclass'
18
+ *
19
+ * cx(cursor('pointer'))
20
+ * // CSS: cursor: pointer;
21
+ * ```
22
+ *
23
+ * @example Not-allowed cursor
24
+ * ```ts
25
+ * cx(cursor('not-allowed'))
26
+ * // CSS: cursor: not-allowed;
27
+ * ```
28
+ *
29
+ * @example Dynamic value
30
+ * ```ts
31
+ * import { dcx, cursor, dynamic } from 'typewritingclass'
32
+ *
33
+ * const { className, style } = dcx(cursor(dynamic(cursorType)))
34
+ * // CSS: cursor: var(--twc-d0);
35
+ * // style: { '--twc-d0': cursorType }
36
+ * ```
37
+ */
38
+ export function cursor(value: string | DynamicValue): StyleRule {
39
+ if (isDynamic(value)) {
40
+ return createDynamicRule(
41
+ { cursor: `var(${value.__id})` },
42
+ { [value.__id]: String(value.__value) },
43
+ )
44
+ }
45
+ return createRule({ cursor: value })
46
+ }
47
+
48
+ /**
49
+ * Sets the `user-select` behavior of an element.
50
+ *
51
+ * Controls whether the user can select text within the element.
52
+ * Accepts a raw CSS user-select string.
53
+ *
54
+ * @param value - A CSS user-select value (`'none'`, `'text'`, `'all'`, `'auto'`).
55
+ * @returns A {@link StyleRule} that sets `user-select`.
56
+ *
57
+ * @example Prevent selection
58
+ * ```ts
59
+ * import { cx, select } from 'typewritingclass'
60
+ *
61
+ * cx(select('none'))
62
+ * // CSS: user-select: none;
63
+ * ```
64
+ *
65
+ * @example Allow text selection
66
+ * ```ts
67
+ * cx(select('text'))
68
+ * // CSS: user-select: text;
69
+ * ```
70
+ *
71
+ * @example Select all on click
72
+ * ```ts
73
+ * cx(select('all'))
74
+ * // CSS: user-select: all;
75
+ * ```
76
+ */
77
+ export function select(value: string): StyleRule {
78
+ return createRule({ 'user-select': value })
79
+ }
80
+
81
+ /**
82
+ * Sets the `pointer-events` behavior of an element.
83
+ *
84
+ * Controls whether the element can be the target of pointer events (clicks, hovers, etc.).
85
+ * Accepts a raw CSS pointer-events string.
86
+ *
87
+ * @param value - A CSS pointer-events value (`'none'`, `'auto'`).
88
+ * @returns A {@link StyleRule} that sets `pointer-events`.
89
+ *
90
+ * @example Disable pointer events
91
+ * ```ts
92
+ * import { cx, pointerEvents } from 'typewritingclass'
93
+ *
94
+ * cx(pointerEvents('none'))
95
+ * // CSS: pointer-events: none;
96
+ * ```
97
+ *
98
+ * @example Enable pointer events
99
+ * ```ts
100
+ * cx(pointerEvents('auto'))
101
+ * // CSS: pointer-events: auto;
102
+ * ```
103
+ */
104
+ export function pointerEvents(value: string): StyleRule {
105
+ return createRule({ 'pointer-events': value })
106
+ }
107
+
108
+ export function accentColor(value: string | DynamicValue): StyleRule {
109
+ if (isDynamic(value)) {
110
+ return createDynamicRule(
111
+ { 'accent-color': `var(${value.__id})` },
112
+ { [value.__id]: String(value.__value) },
113
+ )
114
+ }
115
+ return createRule({ 'accent-color': value })
116
+ }
117
+
118
+ export function appearance(value: string): StyleRule {
119
+ return createRule({ appearance: value })
120
+ }
121
+
122
+ export function caretColor(value: string | DynamicValue): StyleRule {
123
+ if (isDynamic(value)) {
124
+ return createDynamicRule(
125
+ { 'caret-color': `var(${value.__id})` },
126
+ { [value.__id]: String(value.__value) },
127
+ )
128
+ }
129
+ return createRule({ 'caret-color': value })
130
+ }
131
+
132
+ export function resize(value: string): StyleRule {
133
+ return createRule({ resize: value })
134
+ }
135
+
136
+ export function scrollBehavior(value: string): StyleRule {
137
+ return createRule({ 'scroll-behavior': value })
138
+ }
139
+
140
+ function scrollSpacingRule(prop: string, value: number | string | DynamicValue): StyleRule {
141
+ if (isDynamic(value)) {
142
+ return createDynamicRule(
143
+ { [prop]: `var(${value.__id})` },
144
+ { [value.__id]: String(value.__value) },
145
+ )
146
+ }
147
+ const v = typeof value === 'number' ? resolveSpacing(value) : value
148
+ return createRule({ [prop]: v })
149
+ }
150
+
151
+ export function scrollMargin(value: number | string | DynamicValue): StyleRule {
152
+ return scrollSpacingRule('scroll-margin', value)
153
+ }
154
+
155
+ export function scrollMarginX(value: number | string | DynamicValue): StyleRule {
156
+ if (isDynamic(value)) {
157
+ return createDynamicRule(
158
+ { 'scroll-margin-left': `var(${value.__id})`, 'scroll-margin-right': `var(${value.__id})` },
159
+ { [value.__id]: String(value.__value) },
160
+ )
161
+ }
162
+ const v = typeof value === 'number' ? resolveSpacing(value) : String(value)
163
+ return createRule({ 'scroll-margin-left': v, 'scroll-margin-right': v })
164
+ }
165
+
166
+ export function scrollMarginY(value: number | string | DynamicValue): StyleRule {
167
+ if (isDynamic(value)) {
168
+ return createDynamicRule(
169
+ { 'scroll-margin-top': `var(${value.__id})`, 'scroll-margin-bottom': `var(${value.__id})` },
170
+ { [value.__id]: String(value.__value) },
171
+ )
172
+ }
173
+ const v = typeof value === 'number' ? resolveSpacing(value) : String(value)
174
+ return createRule({ 'scroll-margin-top': v, 'scroll-margin-bottom': v })
175
+ }
176
+
177
+ export function scrollMarginT(value: number | string | DynamicValue): StyleRule {
178
+ return scrollSpacingRule('scroll-margin-top', value)
179
+ }
180
+
181
+ export function scrollMarginR(value: number | string | DynamicValue): StyleRule {
182
+ return scrollSpacingRule('scroll-margin-right', value)
183
+ }
184
+
185
+ export function scrollMarginB(value: number | string | DynamicValue): StyleRule {
186
+ return scrollSpacingRule('scroll-margin-bottom', value)
187
+ }
188
+
189
+ export function scrollMarginL(value: number | string | DynamicValue): StyleRule {
190
+ return scrollSpacingRule('scroll-margin-left', value)
191
+ }
192
+
193
+ export function scrollPadding(value: number | string | DynamicValue): StyleRule {
194
+ return scrollSpacingRule('scroll-padding', value)
195
+ }
196
+
197
+ export function scrollPaddingX(value: number | string | DynamicValue): StyleRule {
198
+ if (isDynamic(value)) {
199
+ return createDynamicRule(
200
+ { 'scroll-padding-left': `var(${value.__id})`, 'scroll-padding-right': `var(${value.__id})` },
201
+ { [value.__id]: String(value.__value) },
202
+ )
203
+ }
204
+ const v = typeof value === 'number' ? resolveSpacing(value) : String(value)
205
+ return createRule({ 'scroll-padding-left': v, 'scroll-padding-right': v })
206
+ }
207
+
208
+ export function scrollPaddingY(value: number | string | DynamicValue): StyleRule {
209
+ if (isDynamic(value)) {
210
+ return createDynamicRule(
211
+ { 'scroll-padding-top': `var(${value.__id})`, 'scroll-padding-bottom': `var(${value.__id})` },
212
+ { [value.__id]: String(value.__value) },
213
+ )
214
+ }
215
+ const v = typeof value === 'number' ? resolveSpacing(value) : String(value)
216
+ return createRule({ 'scroll-padding-top': v, 'scroll-padding-bottom': v })
217
+ }
218
+
219
+ export function scrollPaddingT(value: number | string | DynamicValue): StyleRule {
220
+ return scrollSpacingRule('scroll-padding-top', value)
221
+ }
222
+
223
+ export function scrollPaddingR(value: number | string | DynamicValue): StyleRule {
224
+ return scrollSpacingRule('scroll-padding-right', value)
225
+ }
226
+
227
+ export function scrollPaddingB(value: number | string | DynamicValue): StyleRule {
228
+ return scrollSpacingRule('scroll-padding-bottom', value)
229
+ }
230
+
231
+ export function scrollPaddingL(value: number | string | DynamicValue): StyleRule {
232
+ return scrollSpacingRule('scroll-padding-left', value)
233
+ }
234
+
235
+ export function snapAlign(value: string): StyleRule {
236
+ return createRule({ 'scroll-snap-align': value })
237
+ }
238
+
239
+ export function snapStop(value: string): StyleRule {
240
+ return createRule({ 'scroll-snap-stop': value })
241
+ }
242
+
243
+ export function snapType(value: string): StyleRule {
244
+ return createRule({ 'scroll-snap-type': value })
245
+ }
246
+
247
+ export function touchAction(value: string): StyleRule {
248
+ return createRule({ 'touch-action': value })
249
+ }
250
+
251
+ export function willChange(value: string): StyleRule {
252
+ return createRule({ 'will-change': value })
253
+ }