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,1149 @@
1
+ import type { StyleRule } from '../types.ts'
2
+ import type { DynamicValue } from '../dynamic.ts'
3
+ import { createRule, createDynamicRule } from '../rule.ts'
4
+ import { resolveSpacing } from '../theme/spacing.ts'
5
+ import { isDynamic } from '../dynamic.ts'
6
+
7
+ function resolveSize(value: number | string | DynamicValue): string | DynamicValue {
8
+ if (isDynamic(value)) return value
9
+ if (typeof value === 'string') return value
10
+ return resolveSpacing(value)
11
+ }
12
+
13
+ function sizeRule(prop: string, value: number | string | DynamicValue): StyleRule {
14
+ const v = resolveSize(value)
15
+ if (isDynamic(v)) {
16
+ return createDynamicRule(
17
+ { [prop]: `var(${v.__id})` },
18
+ { [v.__id]: String(v.__value) },
19
+ )
20
+ }
21
+ return createRule({ [prop]: v as string })
22
+ }
23
+
24
+ function sizeRuleMulti(props: string[], value: number | string | DynamicValue): StyleRule {
25
+ const v = resolveSize(value)
26
+ if (isDynamic(v)) {
27
+ const decls: Record<string, string> = {}
28
+ for (const prop of props) decls[prop] = `var(${v.__id})`
29
+ return createDynamicRule(decls, { [v.__id]: String(v.__value) })
30
+ }
31
+ const decls: Record<string, string> = {}
32
+ for (const prop of props) decls[prop] = v as string
33
+ return createRule(decls)
34
+ }
35
+
36
+ /**
37
+ * Sets the element to `display: flex`.
38
+ *
39
+ * Takes no arguments and produces a single flex display declaration.
40
+ *
41
+ * @returns A {@link StyleRule} that sets `display: flex`.
42
+ *
43
+ * @example
44
+ * ```ts
45
+ * import { cx, flex } from 'typewritingclass'
46
+ *
47
+ * cx(flex())
48
+ * // CSS: display: flex;
49
+ * ```
50
+ */
51
+ export function flex(): StyleRule {
52
+ return createRule({ display: 'flex' })
53
+ }
54
+
55
+ /**
56
+ * Sets `flex-direction: column` on a flex container.
57
+ *
58
+ * Takes no arguments. Use with `flex()` to create a column-oriented flex container.
59
+ *
60
+ * @returns A {@link StyleRule} that sets `flex-direction: column`.
61
+ *
62
+ * @example
63
+ * ```ts
64
+ * import { cx, flex, flexCol } from 'typewritingclass'
65
+ *
66
+ * cx(flex(), flexCol())
67
+ * // CSS: display: flex; flex-direction: column;
68
+ * ```
69
+ */
70
+ export function flexCol(): StyleRule {
71
+ return createRule({ 'flex-direction': 'column' })
72
+ }
73
+
74
+ /**
75
+ * Sets `flex-direction: row` on a flex container.
76
+ *
77
+ * Takes no arguments. Use with `flex()` to create a row-oriented flex container.
78
+ *
79
+ * @returns A {@link StyleRule} that sets `flex-direction: row`.
80
+ *
81
+ * @example
82
+ * ```ts
83
+ * import { cx, flex, flexRow } from 'typewritingclass'
84
+ *
85
+ * cx(flex(), flexRow())
86
+ * // CSS: display: flex; flex-direction: row;
87
+ * ```
88
+ */
89
+ export function flexRow(): StyleRule {
90
+ return createRule({ 'flex-direction': 'row' })
91
+ }
92
+
93
+ /**
94
+ * Sets `flex-wrap: wrap` on a flex container to allow children to wrap.
95
+ *
96
+ * Takes no arguments.
97
+ *
98
+ * @returns A {@link StyleRule} that sets `flex-wrap: wrap`.
99
+ *
100
+ * @example
101
+ * ```ts
102
+ * import { cx, flexWrap } from 'typewritingclass'
103
+ *
104
+ * cx(flexWrap())
105
+ * // CSS: flex-wrap: wrap;
106
+ * ```
107
+ */
108
+ export function flexWrap(): StyleRule {
109
+ return createRule({ 'flex-wrap': 'wrap' })
110
+ }
111
+
112
+ /**
113
+ * Sets the element to `display: inline-flex`.
114
+ *
115
+ * Takes no arguments and produces an inline-level flex container.
116
+ *
117
+ * @returns A {@link StyleRule} that sets `display: inline-flex`.
118
+ *
119
+ * @example
120
+ * ```ts
121
+ * import { cx, inlineFlex } from 'typewritingclass'
122
+ *
123
+ * cx(inlineFlex())
124
+ * // CSS: display: inline-flex;
125
+ * ```
126
+ */
127
+ export function inlineFlex(): StyleRule {
128
+ return createRule({ display: 'inline-flex' })
129
+ }
130
+
131
+ /**
132
+ * Sets the element to `display: grid`, optionally defining equal-width columns.
133
+ *
134
+ * When called without arguments, sets only `display: grid`. When called with a
135
+ * column count, also sets `grid-template-columns` with equal-width `1fr` columns.
136
+ *
137
+ * @param cols - Optional number of equal-width columns.
138
+ * @returns A {@link StyleRule} that sets `display: grid` and optionally `grid-template-columns`.
139
+ *
140
+ * @example Grid without columns
141
+ * ```ts
142
+ * import { cx, grid } from 'typewritingclass'
143
+ *
144
+ * cx(grid())
145
+ * // CSS: display: grid;
146
+ * ```
147
+ *
148
+ * @example Grid with columns
149
+ * ```ts
150
+ * cx(grid(3))
151
+ * // CSS: display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
152
+ * ```
153
+ */
154
+ export function grid(cols?: number): StyleRule {
155
+ const decls: Record<string, string> = { display: 'grid' }
156
+ if (cols !== undefined) {
157
+ decls['grid-template-columns'] = `repeat(${cols}, minmax(0, 1fr))`
158
+ }
159
+ return createRule(decls)
160
+ }
161
+
162
+ /**
163
+ * Sets the number of equal-width grid columns.
164
+ *
165
+ * @param n - The number of columns.
166
+ * @returns A {@link StyleRule} that sets `grid-template-columns`.
167
+ *
168
+ * @example
169
+ * ```ts
170
+ * import { cx, gridCols } from 'typewritingclass'
171
+ *
172
+ * cx(gridCols(4))
173
+ * // CSS: grid-template-columns: repeat(4, minmax(0, 1fr));
174
+ * ```
175
+ */
176
+ export function gridCols(n: number): StyleRule {
177
+ return createRule({ 'grid-template-columns': `repeat(${n}, minmax(0, 1fr))` })
178
+ }
179
+
180
+ /**
181
+ * Sets the number of equal-height grid rows.
182
+ *
183
+ * @param n - The number of rows.
184
+ * @returns A {@link StyleRule} that sets `grid-template-rows`.
185
+ *
186
+ * @example
187
+ * ```ts
188
+ * import { cx, gridRows } from 'typewritingclass'
189
+ *
190
+ * cx(gridRows(3))
191
+ * // CSS: grid-template-rows: repeat(3, minmax(0, 1fr));
192
+ * ```
193
+ */
194
+ export function gridRows(n: number): StyleRule {
195
+ return createRule({ 'grid-template-rows': `repeat(${n}, minmax(0, 1fr))` })
196
+ }
197
+
198
+ /**
199
+ * Sets the width of an element.
200
+ *
201
+ * Accepts a theme spacing scale number (maps to the spacing scale), a raw CSS string,
202
+ * or a {@link DynamicValue} for runtime values.
203
+ *
204
+ * @param value - Spacing scale number (`4` -> `1rem`), raw string (`'100%'`), or `dynamic()` value.
205
+ * @returns A {@link StyleRule} that sets `width`.
206
+ *
207
+ * @example Theme scale
208
+ * ```ts
209
+ * import { cx, w } from 'typewritingclass'
210
+ *
211
+ * cx(w(64))
212
+ * // CSS: width: 16rem;
213
+ * ```
214
+ *
215
+ * @example Raw value
216
+ * ```ts
217
+ * cx(w('100%'))
218
+ * // CSS: width: 100%;
219
+ * ```
220
+ *
221
+ * @example Dynamic value
222
+ * ```ts
223
+ * import { dcx, w, dynamic } from 'typewritingclass'
224
+ *
225
+ * const { className, style } = dcx(w(dynamic(width)))
226
+ * // CSS: width: var(--twc-d0);
227
+ * // style: { '--twc-d0': width }
228
+ * ```
229
+ */
230
+ export function w(value: number | string | DynamicValue): StyleRule {
231
+ return sizeRule('width', value)
232
+ }
233
+
234
+ /**
235
+ * Sets the height of an element.
236
+ *
237
+ * Accepts a theme spacing scale number (maps to the spacing scale), a raw CSS string,
238
+ * or a {@link DynamicValue} for runtime values.
239
+ *
240
+ * @param value - Spacing scale number (`4` -> `1rem`), raw string (`'100vh'`), or `dynamic()` value.
241
+ * @returns A {@link StyleRule} that sets `height`.
242
+ *
243
+ * @example Theme scale
244
+ * ```ts
245
+ * import { cx, h } from 'typewritingclass'
246
+ *
247
+ * cx(h(12))
248
+ * // CSS: height: 3rem;
249
+ * ```
250
+ *
251
+ * @example Raw value
252
+ * ```ts
253
+ * cx(h('100vh'))
254
+ * // CSS: height: 100vh;
255
+ * ```
256
+ *
257
+ * @example Dynamic value
258
+ * ```ts
259
+ * import { dcx, h, dynamic } from 'typewritingclass'
260
+ *
261
+ * const { className, style } = dcx(h(dynamic(height)))
262
+ * // CSS: height: var(--twc-d0);
263
+ * // style: { '--twc-d0': height }
264
+ * ```
265
+ */
266
+ export function h(value: number | string | DynamicValue): StyleRule {
267
+ return sizeRule('height', value)
268
+ }
269
+
270
+ /**
271
+ * Sets both width and height of an element to the same value.
272
+ *
273
+ * Accepts a theme spacing scale number (maps to the spacing scale), a raw CSS string,
274
+ * or a {@link DynamicValue} for runtime values.
275
+ *
276
+ * @param value - Spacing scale number (`4` -> `1rem`), raw string (`'48px'`), or `dynamic()` value.
277
+ * @returns A {@link StyleRule} that sets both `width` and `height`.
278
+ *
279
+ * @example Theme scale
280
+ * ```ts
281
+ * import { cx, size } from 'typewritingclass'
282
+ *
283
+ * cx(size(10))
284
+ * // CSS: width: 2.5rem; height: 2.5rem;
285
+ * ```
286
+ *
287
+ * @example Raw value
288
+ * ```ts
289
+ * cx(size('48px'))
290
+ * // CSS: width: 48px; height: 48px;
291
+ * ```
292
+ *
293
+ * @example Dynamic value
294
+ * ```ts
295
+ * import { dcx, size, dynamic } from 'typewritingclass'
296
+ *
297
+ * const { className, style } = dcx(size(dynamic(dim)))
298
+ * // CSS: width: var(--twc-d0); height: var(--twc-d0);
299
+ * // style: { '--twc-d0': dim }
300
+ * ```
301
+ */
302
+ export function size(value: number | string | DynamicValue): StyleRule {
303
+ return sizeRuleMulti(['width', 'height'], value)
304
+ }
305
+
306
+ /**
307
+ * Sets the minimum width of an element.
308
+ *
309
+ * Accepts a theme spacing scale number (maps to the spacing scale), a raw CSS string,
310
+ * or a {@link DynamicValue} for runtime values.
311
+ *
312
+ * @param value - Spacing scale number (`4` -> `1rem`), raw string (`'200px'`), or `dynamic()` value.
313
+ * @returns A {@link StyleRule} that sets `min-width`.
314
+ *
315
+ * @example Theme scale
316
+ * ```ts
317
+ * import { cx, minW } from 'typewritingclass'
318
+ *
319
+ * cx(minW(48))
320
+ * // CSS: min-width: 12rem;
321
+ * ```
322
+ *
323
+ * @example Raw value
324
+ * ```ts
325
+ * cx(minW('0'))
326
+ * // CSS: min-width: 0;
327
+ * ```
328
+ *
329
+ * @example Dynamic value
330
+ * ```ts
331
+ * import { dcx, minW, dynamic } from 'typewritingclass'
332
+ *
333
+ * const { className, style } = dcx(minW(dynamic(minWidth)))
334
+ * // CSS: min-width: var(--twc-d0);
335
+ * // style: { '--twc-d0': minWidth }
336
+ * ```
337
+ */
338
+ export function minW(value: number | string | DynamicValue): StyleRule {
339
+ return sizeRule('min-width', value)
340
+ }
341
+
342
+ /**
343
+ * Sets the minimum height of an element.
344
+ *
345
+ * Accepts a theme spacing scale number (maps to the spacing scale), a raw CSS string,
346
+ * or a {@link DynamicValue} for runtime values.
347
+ *
348
+ * @param value - Spacing scale number (`4` -> `1rem`), raw string (`'100vh'`), or `dynamic()` value.
349
+ * @returns A {@link StyleRule} that sets `min-height`.
350
+ *
351
+ * @example Theme scale
352
+ * ```ts
353
+ * import { cx, minH } from 'typewritingclass'
354
+ *
355
+ * cx(minH(96))
356
+ * // CSS: min-height: 24rem;
357
+ * ```
358
+ *
359
+ * @example Raw value
360
+ * ```ts
361
+ * cx(minH('100vh'))
362
+ * // CSS: min-height: 100vh;
363
+ * ```
364
+ *
365
+ * @example Dynamic value
366
+ * ```ts
367
+ * import { dcx, minH, dynamic } from 'typewritingclass'
368
+ *
369
+ * const { className, style } = dcx(minH(dynamic(minHeight)))
370
+ * // CSS: min-height: var(--twc-d0);
371
+ * // style: { '--twc-d0': minHeight }
372
+ * ```
373
+ */
374
+ export function minH(value: number | string | DynamicValue): StyleRule {
375
+ return sizeRule('min-height', value)
376
+ }
377
+
378
+ /**
379
+ * Sets the maximum width of an element.
380
+ *
381
+ * Accepts a theme spacing scale number (maps to the spacing scale), a raw CSS string,
382
+ * or a {@link DynamicValue} for runtime values.
383
+ *
384
+ * @param value - Spacing scale number (`4` -> `1rem`), raw string (`'768px'`), or `dynamic()` value.
385
+ * @returns A {@link StyleRule} that sets `max-width`.
386
+ *
387
+ * @example Theme scale
388
+ * ```ts
389
+ * import { cx, maxW } from 'typewritingclass'
390
+ *
391
+ * cx(maxW(80))
392
+ * // CSS: max-width: 20rem;
393
+ * ```
394
+ *
395
+ * @example Raw value
396
+ * ```ts
397
+ * cx(maxW('768px'))
398
+ * // CSS: max-width: 768px;
399
+ * ```
400
+ *
401
+ * @example Dynamic value
402
+ * ```ts
403
+ * import { dcx, maxW, dynamic } from 'typewritingclass'
404
+ *
405
+ * const { className, style } = dcx(maxW(dynamic(maxWidth)))
406
+ * // CSS: max-width: var(--twc-d0);
407
+ * // style: { '--twc-d0': maxWidth }
408
+ * ```
409
+ */
410
+ export function maxW(value: number | string | DynamicValue): StyleRule {
411
+ return sizeRule('max-width', value)
412
+ }
413
+
414
+ /**
415
+ * Sets the maximum height of an element.
416
+ *
417
+ * Accepts a theme spacing scale number (maps to the spacing scale), a raw CSS string,
418
+ * or a {@link DynamicValue} for runtime values.
419
+ *
420
+ * @param value - Spacing scale number (`4` -> `1rem`), raw string (`'100vh'`), or `dynamic()` value.
421
+ * @returns A {@link StyleRule} that sets `max-height`.
422
+ *
423
+ * @example Theme scale
424
+ * ```ts
425
+ * import { cx, maxH } from 'typewritingclass'
426
+ *
427
+ * cx(maxH(40))
428
+ * // CSS: max-height: 10rem;
429
+ * ```
430
+ *
431
+ * @example Raw value
432
+ * ```ts
433
+ * cx(maxH('100vh'))
434
+ * // CSS: max-height: 100vh;
435
+ * ```
436
+ *
437
+ * @example Dynamic value
438
+ * ```ts
439
+ * import { dcx, maxH, dynamic } from 'typewritingclass'
440
+ *
441
+ * const { className, style } = dcx(maxH(dynamic(maxHeight)))
442
+ * // CSS: max-height: var(--twc-d0);
443
+ * // style: { '--twc-d0': maxHeight }
444
+ * ```
445
+ */
446
+ export function maxH(value: number | string | DynamicValue): StyleRule {
447
+ return sizeRule('max-height', value)
448
+ }
449
+
450
+ /**
451
+ * Sets the CSS `display` property of an element.
452
+ *
453
+ * Accepts any valid CSS display value as a string.
454
+ *
455
+ * @param value - A CSS display value (`'block'`, `'none'`, `'inline-block'`, etc.).
456
+ * @returns A {@link StyleRule} that sets `display`.
457
+ *
458
+ * @example Block display
459
+ * ```ts
460
+ * import { cx, display } from 'typewritingclass'
461
+ *
462
+ * cx(display('block'))
463
+ * // CSS: display: block;
464
+ * ```
465
+ *
466
+ * @example Hide element
467
+ * ```ts
468
+ * cx(display('none'))
469
+ * // CSS: display: none;
470
+ * ```
471
+ */
472
+ export function display(value: string): StyleRule {
473
+ return createRule({ display: value })
474
+ }
475
+
476
+ /**
477
+ * Sets the `align-items` property on a flex or grid container.
478
+ *
479
+ * Accepts any valid CSS align-items value as a string.
480
+ *
481
+ * @param value - A CSS align-items value (`'center'`, `'flex-start'`, `'stretch'`, etc.).
482
+ * @returns A {@link StyleRule} that sets `align-items`.
483
+ *
484
+ * @example Center alignment
485
+ * ```ts
486
+ * import { cx, items } from 'typewritingclass'
487
+ *
488
+ * cx(items('center'))
489
+ * // CSS: align-items: center;
490
+ * ```
491
+ *
492
+ * @example Start alignment
493
+ * ```ts
494
+ * cx(items('flex-start'))
495
+ * // CSS: align-items: flex-start;
496
+ * ```
497
+ */
498
+ export function items(value: string): StyleRule {
499
+ return createRule({ 'align-items': value })
500
+ }
501
+
502
+ /**
503
+ * Sets the `justify-content` property on a flex or grid container.
504
+ *
505
+ * Accepts any valid CSS justify-content value as a string.
506
+ *
507
+ * @param value - A CSS justify-content value (`'center'`, `'space-between'`, `'flex-end'`, etc.).
508
+ * @returns A {@link StyleRule} that sets `justify-content`.
509
+ *
510
+ * @example Center justification
511
+ * ```ts
512
+ * import { cx, justify } from 'typewritingclass'
513
+ *
514
+ * cx(justify('center'))
515
+ * // CSS: justify-content: center;
516
+ * ```
517
+ *
518
+ * @example Space between
519
+ * ```ts
520
+ * cx(justify('space-between'))
521
+ * // CSS: justify-content: space-between;
522
+ * ```
523
+ */
524
+ export function justify(value: string): StyleRule {
525
+ return createRule({ 'justify-content': value })
526
+ }
527
+
528
+ /**
529
+ * Sets the `align-self` property on a flex or grid child.
530
+ *
531
+ * Accepts any valid CSS align-self value as a string.
532
+ *
533
+ * @param value - A CSS align-self value (`'center'`, `'flex-start'`, `'stretch'`, etc.).
534
+ * @returns A {@link StyleRule} that sets `align-self`.
535
+ *
536
+ * @example Center self-alignment
537
+ * ```ts
538
+ * import { cx, self } from 'typewritingclass'
539
+ *
540
+ * cx(self('center'))
541
+ * // CSS: align-self: center;
542
+ * ```
543
+ *
544
+ * @example End self-alignment
545
+ * ```ts
546
+ * cx(self('flex-end'))
547
+ * // CSS: align-self: flex-end;
548
+ * ```
549
+ */
550
+ export function self(value: string): StyleRule {
551
+ return createRule({ 'align-self': value })
552
+ }
553
+
554
+ /**
555
+ * Sets the `overflow` behavior on both axes of an element.
556
+ *
557
+ * Accepts any valid CSS overflow value as a string.
558
+ *
559
+ * @param value - A CSS overflow value (`'hidden'`, `'auto'`, `'scroll'`, `'visible'`).
560
+ * @returns A {@link StyleRule} that sets `overflow`.
561
+ *
562
+ * @example Hidden overflow
563
+ * ```ts
564
+ * import { cx, overflow } from 'typewritingclass'
565
+ *
566
+ * cx(overflow('hidden'))
567
+ * // CSS: overflow: hidden;
568
+ * ```
569
+ *
570
+ * @example Auto overflow
571
+ * ```ts
572
+ * cx(overflow('auto'))
573
+ * // CSS: overflow: auto;
574
+ * ```
575
+ */
576
+ export function overflow(value: string): StyleRule {
577
+ return createRule({ overflow: value })
578
+ }
579
+
580
+ /**
581
+ * Sets the horizontal overflow behavior of an element.
582
+ *
583
+ * Accepts any valid CSS overflow-x value as a string.
584
+ *
585
+ * @param value - A CSS overflow-x value (`'hidden'`, `'auto'`, `'scroll'`, `'visible'`).
586
+ * @returns A {@link StyleRule} that sets `overflow-x`.
587
+ *
588
+ * @example Auto horizontal scroll
589
+ * ```ts
590
+ * import { cx, overflowX } from 'typewritingclass'
591
+ *
592
+ * cx(overflowX('auto'))
593
+ * // CSS: overflow-x: auto;
594
+ * ```
595
+ *
596
+ * @example Hidden horizontal overflow
597
+ * ```ts
598
+ * cx(overflowX('hidden'))
599
+ * // CSS: overflow-x: hidden;
600
+ * ```
601
+ */
602
+ export function overflowX(value: string): StyleRule {
603
+ return createRule({ 'overflow-x': value })
604
+ }
605
+
606
+ /**
607
+ * Sets the vertical overflow behavior of an element.
608
+ *
609
+ * Accepts any valid CSS overflow-y value as a string.
610
+ *
611
+ * @param value - A CSS overflow-y value (`'hidden'`, `'auto'`, `'scroll'`, `'visible'`).
612
+ * @returns A {@link StyleRule} that sets `overflow-y`.
613
+ *
614
+ * @example Scrollable vertical overflow
615
+ * ```ts
616
+ * import { cx, overflowY } from 'typewritingclass'
617
+ *
618
+ * cx(overflowY('scroll'))
619
+ * // CSS: overflow-y: scroll;
620
+ * ```
621
+ *
622
+ * @example Hidden vertical overflow
623
+ * ```ts
624
+ * cx(overflowY('hidden'))
625
+ * // CSS: overflow-y: hidden;
626
+ * ```
627
+ */
628
+ export function overflowY(value: string): StyleRule {
629
+ return createRule({ 'overflow-y': value })
630
+ }
631
+
632
+ /**
633
+ * Sets the element to `position: relative`.
634
+ *
635
+ * Takes no arguments. Creates a positioning context for absolutely positioned children.
636
+ *
637
+ * @returns A {@link StyleRule} that sets `position: relative`.
638
+ *
639
+ * @example
640
+ * ```ts
641
+ * import { cx, relative } from 'typewritingclass'
642
+ *
643
+ * cx(relative())
644
+ * // CSS: position: relative;
645
+ * ```
646
+ */
647
+ export function relative(): StyleRule {
648
+ return createRule({ position: 'relative' })
649
+ }
650
+
651
+ /**
652
+ * Sets the element to `position: absolute`.
653
+ *
654
+ * Takes no arguments. Removes the element from normal flow and positions it
655
+ * relative to its nearest positioned ancestor.
656
+ *
657
+ * @returns A {@link StyleRule} that sets `position: absolute`.
658
+ *
659
+ * @example
660
+ * ```ts
661
+ * import { cx, absolute } from 'typewritingclass'
662
+ *
663
+ * cx(absolute())
664
+ * // CSS: position: absolute;
665
+ * ```
666
+ */
667
+ export function absolute(): StyleRule {
668
+ return createRule({ position: 'absolute' })
669
+ }
670
+
671
+ /**
672
+ * Sets the element to `position: fixed`.
673
+ *
674
+ * Takes no arguments. Removes the element from normal flow and positions it
675
+ * relative to the viewport.
676
+ *
677
+ * @returns A {@link StyleRule} that sets `position: fixed`.
678
+ *
679
+ * @example
680
+ * ```ts
681
+ * import { cx, fixed } from 'typewritingclass'
682
+ *
683
+ * cx(fixed())
684
+ * // CSS: position: fixed;
685
+ * ```
686
+ */
687
+ export function fixed(): StyleRule {
688
+ return createRule({ position: 'fixed' })
689
+ }
690
+
691
+ /**
692
+ * Sets the element to `position: sticky`.
693
+ *
694
+ * Takes no arguments. The element is treated as relative until it crosses a
695
+ * specified threshold, then treated as fixed.
696
+ *
697
+ * @returns A {@link StyleRule} that sets `position: sticky`.
698
+ *
699
+ * @example
700
+ * ```ts
701
+ * import { cx, sticky } from 'typewritingclass'
702
+ *
703
+ * cx(sticky())
704
+ * // CSS: position: sticky;
705
+ * ```
706
+ */
707
+ export function sticky(): StyleRule {
708
+ return createRule({ position: 'sticky' })
709
+ }
710
+
711
+ /**
712
+ * Sets the `top` position offset of a positioned element.
713
+ *
714
+ * Accepts a theme spacing scale number (maps to the spacing scale), a raw CSS string,
715
+ * or a {@link DynamicValue} for runtime values.
716
+ *
717
+ * @param value - Spacing scale number (`4` -> `1rem`), raw string (`'0'`), or `dynamic()` value.
718
+ * @returns A {@link StyleRule} that sets `top`.
719
+ *
720
+ * @example Theme scale
721
+ * ```ts
722
+ * import { cx, top } from 'typewritingclass'
723
+ *
724
+ * cx(top(0))
725
+ * // CSS: top: 0px;
726
+ * ```
727
+ *
728
+ * @example Raw value
729
+ * ```ts
730
+ * cx(top('50%'))
731
+ * // CSS: top: 50%;
732
+ * ```
733
+ *
734
+ * @example Dynamic value
735
+ * ```ts
736
+ * import { dcx, top, dynamic } from 'typewritingclass'
737
+ *
738
+ * const { className, style } = dcx(top(dynamic(offset)))
739
+ * // CSS: top: var(--twc-d0);
740
+ * // style: { '--twc-d0': offset }
741
+ * ```
742
+ */
743
+ export function top(value: number | string | DynamicValue): StyleRule {
744
+ return sizeRule('top', value)
745
+ }
746
+
747
+ /**
748
+ * Sets the `right` position offset of a positioned element.
749
+ *
750
+ * Accepts a theme spacing scale number (maps to the spacing scale), a raw CSS string,
751
+ * or a {@link DynamicValue} for runtime values.
752
+ *
753
+ * @param value - Spacing scale number (`4` -> `1rem`), raw string (`'0'`), or `dynamic()` value.
754
+ * @returns A {@link StyleRule} that sets `right`.
755
+ *
756
+ * @example Theme scale
757
+ * ```ts
758
+ * import { cx, right } from 'typewritingclass'
759
+ *
760
+ * cx(right(4))
761
+ * // CSS: right: 1rem;
762
+ * ```
763
+ *
764
+ * @example Raw value
765
+ * ```ts
766
+ * cx(right('0'))
767
+ * // CSS: right: 0;
768
+ * ```
769
+ *
770
+ * @example Dynamic value
771
+ * ```ts
772
+ * import { dcx, right, dynamic } from 'typewritingclass'
773
+ *
774
+ * const { className, style } = dcx(right(dynamic(offset)))
775
+ * // CSS: right: var(--twc-d0);
776
+ * // style: { '--twc-d0': offset }
777
+ * ```
778
+ */
779
+ export function right(value: number | string | DynamicValue): StyleRule {
780
+ return sizeRule('right', value)
781
+ }
782
+
783
+ /**
784
+ * Sets the `bottom` position offset of a positioned element.
785
+ *
786
+ * Accepts a theme spacing scale number (maps to the spacing scale), a raw CSS string,
787
+ * or a {@link DynamicValue} for runtime values.
788
+ *
789
+ * @param value - Spacing scale number (`4` -> `1rem`), raw string (`'0'`), or `dynamic()` value.
790
+ * @returns A {@link StyleRule} that sets `bottom`.
791
+ *
792
+ * @example Theme scale
793
+ * ```ts
794
+ * import { cx, bottom } from 'typewritingclass'
795
+ *
796
+ * cx(bottom(0))
797
+ * // CSS: bottom: 0px;
798
+ * ```
799
+ *
800
+ * @example Raw value
801
+ * ```ts
802
+ * cx(bottom('2rem'))
803
+ * // CSS: bottom: 2rem;
804
+ * ```
805
+ *
806
+ * @example Dynamic value
807
+ * ```ts
808
+ * import { dcx, bottom, dynamic } from 'typewritingclass'
809
+ *
810
+ * const { className, style } = dcx(bottom(dynamic(offset)))
811
+ * // CSS: bottom: var(--twc-d0);
812
+ * // style: { '--twc-d0': offset }
813
+ * ```
814
+ */
815
+ export function bottom(value: number | string | DynamicValue): StyleRule {
816
+ return sizeRule('bottom', value)
817
+ }
818
+
819
+ /**
820
+ * Sets the `left` position offset of a positioned element.
821
+ *
822
+ * Accepts a theme spacing scale number (maps to the spacing scale), a raw CSS string,
823
+ * or a {@link DynamicValue} for runtime values.
824
+ *
825
+ * @param value - Spacing scale number (`4` -> `1rem`), raw string (`'0'`), or `dynamic()` value.
826
+ * @returns A {@link StyleRule} that sets `left`.
827
+ *
828
+ * @example Theme scale
829
+ * ```ts
830
+ * import { cx, left } from 'typewritingclass'
831
+ *
832
+ * cx(left(4))
833
+ * // CSS: left: 1rem;
834
+ * ```
835
+ *
836
+ * @example Raw value
837
+ * ```ts
838
+ * cx(left('50%'))
839
+ * // CSS: left: 50%;
840
+ * ```
841
+ *
842
+ * @example Dynamic value
843
+ * ```ts
844
+ * import { dcx, left, dynamic } from 'typewritingclass'
845
+ *
846
+ * const { className, style } = dcx(left(dynamic(offset)))
847
+ * // CSS: left: var(--twc-d0);
848
+ * // style: { '--twc-d0': offset }
849
+ * ```
850
+ */
851
+ export function left(value: number | string | DynamicValue): StyleRule {
852
+ return sizeRule('left', value)
853
+ }
854
+
855
+ /**
856
+ * Sets the `inset` shorthand property (top, right, bottom, left) on a positioned element.
857
+ *
858
+ * Accepts a theme spacing scale number (maps to the spacing scale), a raw CSS string,
859
+ * or a {@link DynamicValue} for runtime values.
860
+ *
861
+ * @param value - Spacing scale number (`0` -> `0px`), raw string (`'0'`), or `dynamic()` value.
862
+ * @returns A {@link StyleRule} that sets `inset`.
863
+ *
864
+ * @example Theme scale
865
+ * ```ts
866
+ * import { cx, inset } from 'typewritingclass'
867
+ *
868
+ * cx(inset(0))
869
+ * // CSS: inset: 0px;
870
+ * ```
871
+ *
872
+ * @example Raw value
873
+ * ```ts
874
+ * cx(inset('0'))
875
+ * // CSS: inset: 0;
876
+ * ```
877
+ *
878
+ * @example Dynamic value
879
+ * ```ts
880
+ * import { dcx, inset, dynamic } from 'typewritingclass'
881
+ *
882
+ * const { className, style } = dcx(inset(dynamic(offset)))
883
+ * // CSS: inset: var(--twc-d0);
884
+ * // style: { '--twc-d0': offset }
885
+ * ```
886
+ */
887
+ export function inset(value: number | string | DynamicValue): StyleRule {
888
+ return sizeRule('inset', value)
889
+ }
890
+
891
+ /**
892
+ * Sets the `z-index` stacking order of an element.
893
+ *
894
+ * Accepts a numeric z-index value, a raw string, or a {@link DynamicValue}
895
+ * for runtime values. Numeric values are converted to strings.
896
+ *
897
+ * @param value - A z-index number (`10`, `50`), raw string (`'auto'`), or `dynamic()` value.
898
+ * @returns A {@link StyleRule} that sets `z-index`.
899
+ *
900
+ * @example Numeric z-index
901
+ * ```ts
902
+ * import { cx, z } from 'typewritingclass'
903
+ *
904
+ * cx(z(10))
905
+ * // CSS: z-index: 10;
906
+ * ```
907
+ *
908
+ * @example String z-index
909
+ * ```ts
910
+ * cx(z('auto'))
911
+ * // CSS: z-index: auto;
912
+ * ```
913
+ *
914
+ * @example Dynamic value
915
+ * ```ts
916
+ * import { dcx, z, dynamic } from 'typewritingclass'
917
+ *
918
+ * const { className, style } = dcx(z(dynamic(zIndex)))
919
+ * // CSS: z-index: var(--twc-d0);
920
+ * // style: { '--twc-d0': zIndex }
921
+ * ```
922
+ */
923
+ export function z(value: number | string | DynamicValue): StyleRule {
924
+ if (isDynamic(value)) {
925
+ return createDynamicRule(
926
+ { 'z-index': `var(${value.__id})` },
927
+ { [value.__id]: String(value.__value) },
928
+ )
929
+ }
930
+ return createRule({ 'z-index': String(value) })
931
+ }
932
+
933
+ // --- Additional layout utilities ---
934
+
935
+ export function aspectRatio(value: string): StyleRule {
936
+ return createRule({ 'aspect-ratio': value })
937
+ }
938
+
939
+ export function columns(value: string | number): StyleRule {
940
+ return createRule({ columns: String(value) })
941
+ }
942
+
943
+ export function breakAfter(value: string): StyleRule {
944
+ return createRule({ 'break-after': value })
945
+ }
946
+
947
+ export function breakBefore(value: string): StyleRule {
948
+ return createRule({ 'break-before': value })
949
+ }
950
+
951
+ export function breakInside(value: string): StyleRule {
952
+ return createRule({ 'break-inside': value })
953
+ }
954
+
955
+ export function boxDecorationBreak(value: string): StyleRule {
956
+ return createRule({ 'box-decoration-break': value })
957
+ }
958
+
959
+ export function boxSizing(value: string): StyleRule {
960
+ return createRule({ 'box-sizing': value })
961
+ }
962
+
963
+ export function float_(value: string): StyleRule {
964
+ return createRule({ float: value })
965
+ }
966
+
967
+ export function clear_(value: string): StyleRule {
968
+ return createRule({ clear: value })
969
+ }
970
+
971
+ export function isolate(): StyleRule {
972
+ return createRule({ isolation: 'isolate' })
973
+ }
974
+
975
+ export function isolationAuto(): StyleRule {
976
+ return createRule({ isolation: 'auto' })
977
+ }
978
+
979
+ export function objectFit(value: string): StyleRule {
980
+ return createRule({ 'object-fit': value })
981
+ }
982
+
983
+ export function objectPosition(value: string): StyleRule {
984
+ return createRule({ 'object-position': value })
985
+ }
986
+
987
+ export function overscrollBehavior(value: string): StyleRule {
988
+ return createRule({ 'overscroll-behavior': value })
989
+ }
990
+
991
+ export function overscrollX(value: string): StyleRule {
992
+ return createRule({ 'overscroll-behavior-x': value })
993
+ }
994
+
995
+ export function overscrollY(value: string): StyleRule {
996
+ return createRule({ 'overscroll-behavior-y': value })
997
+ }
998
+
999
+ export function static_(): StyleRule {
1000
+ return createRule({ position: 'static' })
1001
+ }
1002
+
1003
+ export function insetX(value: number | string | DynamicValue): StyleRule {
1004
+ return sizeRuleMulti(['left', 'right'], value)
1005
+ }
1006
+
1007
+ export function insetY(value: number | string | DynamicValue): StyleRule {
1008
+ return sizeRuleMulti(['top', 'bottom'], value)
1009
+ }
1010
+
1011
+ export function start(value: number | string | DynamicValue): StyleRule {
1012
+ return sizeRule('inset-inline-start', value)
1013
+ }
1014
+
1015
+ export function end(value: number | string | DynamicValue): StyleRule {
1016
+ return sizeRule('inset-inline-end', value)
1017
+ }
1018
+
1019
+ export function visible(): StyleRule {
1020
+ return createRule({ visibility: 'visible' })
1021
+ }
1022
+
1023
+ export function invisible(): StyleRule {
1024
+ return createRule({ visibility: 'hidden' })
1025
+ }
1026
+
1027
+ export function collapse_(): StyleRule {
1028
+ return createRule({ visibility: 'collapse' })
1029
+ }
1030
+
1031
+ export function flexBasis(value: number | string | DynamicValue): StyleRule {
1032
+ return sizeRule('flex-basis', value)
1033
+ }
1034
+
1035
+ export function flexRowReverse(): StyleRule {
1036
+ return createRule({ 'flex-direction': 'row-reverse' })
1037
+ }
1038
+
1039
+ export function flexColReverse(): StyleRule {
1040
+ return createRule({ 'flex-direction': 'column-reverse' })
1041
+ }
1042
+
1043
+ export function flexWrapReverse(): StyleRule {
1044
+ return createRule({ 'flex-wrap': 'wrap-reverse' })
1045
+ }
1046
+
1047
+ export function flexNowrap(): StyleRule {
1048
+ return createRule({ 'flex-wrap': 'nowrap' })
1049
+ }
1050
+
1051
+ export function flex1(): StyleRule {
1052
+ return createRule({ flex: '1 1 0%' })
1053
+ }
1054
+
1055
+ export function flexAuto(): StyleRule {
1056
+ return createRule({ flex: '1 1 auto' })
1057
+ }
1058
+
1059
+ export function flexInitial(): StyleRule {
1060
+ return createRule({ flex: '0 1 auto' })
1061
+ }
1062
+
1063
+ export function flexNone(): StyleRule {
1064
+ return createRule({ flex: 'none' })
1065
+ }
1066
+
1067
+ export function grow(value: string | number = 1): StyleRule {
1068
+ return createRule({ 'flex-grow': String(value) })
1069
+ }
1070
+
1071
+ export function shrink(value: string | number = 1): StyleRule {
1072
+ return createRule({ 'flex-shrink': String(value) })
1073
+ }
1074
+
1075
+ export function order(value: number | string | DynamicValue): StyleRule {
1076
+ if (isDynamic(value)) {
1077
+ return createDynamicRule(
1078
+ { order: `var(${value.__id})` },
1079
+ { [value.__id]: String(value.__value) },
1080
+ )
1081
+ }
1082
+ return createRule({ order: String(value) })
1083
+ }
1084
+
1085
+ export function colSpan(value: number | string): StyleRule {
1086
+ if (value === 'full') return createRule({ 'grid-column': '1 / -1' })
1087
+ return createRule({ 'grid-column': `span ${value} / span ${value}` })
1088
+ }
1089
+
1090
+ export function colStart(value: number | string): StyleRule {
1091
+ return createRule({ 'grid-column-start': String(value) })
1092
+ }
1093
+
1094
+ export function colEnd(value: number | string): StyleRule {
1095
+ return createRule({ 'grid-column-end': String(value) })
1096
+ }
1097
+
1098
+ export function rowSpan(value: number | string): StyleRule {
1099
+ if (value === 'full') return createRule({ 'grid-row': '1 / -1' })
1100
+ return createRule({ 'grid-row': `span ${value} / span ${value}` })
1101
+ }
1102
+
1103
+ export function rowStart(value: number | string): StyleRule {
1104
+ return createRule({ 'grid-row-start': String(value) })
1105
+ }
1106
+
1107
+ export function rowEnd(value: number | string): StyleRule {
1108
+ return createRule({ 'grid-row-end': String(value) })
1109
+ }
1110
+
1111
+ export function gridFlow(value: string): StyleRule {
1112
+ return createRule({ 'grid-auto-flow': value })
1113
+ }
1114
+
1115
+ export function autoCols(value: string): StyleRule {
1116
+ return createRule({ 'grid-auto-columns': value })
1117
+ }
1118
+
1119
+ export function autoRows(value: string): StyleRule {
1120
+ return createRule({ 'grid-auto-rows': value })
1121
+ }
1122
+
1123
+ export function justifyItems(value: string): StyleRule {
1124
+ return createRule({ 'justify-items': value })
1125
+ }
1126
+
1127
+ export function justifySelf(value: string): StyleRule {
1128
+ return createRule({ 'justify-self': value })
1129
+ }
1130
+
1131
+ export function alignContent(value: string): StyleRule {
1132
+ return createRule({ 'align-content': value })
1133
+ }
1134
+
1135
+ export function placeContent(value: string): StyleRule {
1136
+ return createRule({ 'place-content': value })
1137
+ }
1138
+
1139
+ export function placeItems(value: string): StyleRule {
1140
+ return createRule({ 'place-items': value })
1141
+ }
1142
+
1143
+ export function placeSelf(value: string): StyleRule {
1144
+ return createRule({ 'place-self': value })
1145
+ }
1146
+
1147
+ export function container(): StyleRule {
1148
+ return createRule({ width: '100%' })
1149
+ }