@decantr/css 1.0.3 → 1.0.5

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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Decantr AI
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/dist/index.d.ts CHANGED
@@ -1,3 +1,13 @@
1
+ /**
2
+ * Decantr CSS Atoms - Direct atom definitions and algorithmic resolution.
3
+ */
4
+ /**
5
+ * Resolve an atom name to its CSS declaration.
6
+ * @param atom - Atom name (e.g., '_flex', '_gap4', '_p2')
7
+ * @returns CSS declaration or null if not recognized
8
+ */
9
+ declare function resolveAtomDecl(atom: string): string | null;
10
+
1
11
  /**
2
12
  * Decantr CSS - Main css() function.
3
13
  */
@@ -40,6 +50,14 @@ declare function inject(className: string, declaration: string, escapedName?: st
40
50
  * @param bp - breakpoint key (sm|md|lg|xl)
41
51
  */
42
52
  declare function injectResponsive(className: string, declaration: string, bp: string): void;
53
+ /**
54
+ * Inject a max-width responsive atom.
55
+ * @param className - e.g., '_mdmax:none' (hide below md)
56
+ * @param declaration - CSS declaration(s)
57
+ * @param bp - breakpoint key (sm|md|lg|xl). The max-width query is (breakpoint - 0.02)px
58
+ * so it doesn't overlap with the matching min-width variant.
59
+ */
60
+ declare function injectResponsiveMax(className: string, declaration: string, bp: string): void;
43
61
  /**
44
62
  * Inject a pseudo-class atom.
45
63
  * @param className - e.g., '_h:bgprimary'
@@ -47,6 +65,22 @@ declare function injectResponsive(className: string, declaration: string, bp: st
47
65
  * @param prefix - 'h'|'f'|'fv'|'a'|'fw'
48
66
  */
49
67
  declare function injectPseudo(className: string, declaration: string, prefix: string): void;
68
+ /**
69
+ * Inject a responsive + pseudo-class atom.
70
+ * @param className - e.g., '_sm:h:bgprimary'
71
+ * @param declaration - CSS declaration(s)
72
+ * @param bp - breakpoint key
73
+ * @param pseudo - pseudo-class name
74
+ */
75
+ declare function injectResponsivePseudo(className: string, declaration: string, bp: string, pseudo: string): void;
76
+ /**
77
+ * Inject a max-width responsive + pseudo-class atom.
78
+ * @param className - e.g., '_mdmax:h:fgmuted'
79
+ * @param declaration - CSS declaration(s)
80
+ * @param bp - breakpoint key (sm|md|lg|xl)
81
+ * @param pseudo - pseudo-class name
82
+ */
83
+ declare function injectResponsiveMaxPseudo(className: string, declaration: string, bp: string, pseudo: string): void;
50
84
  /**
51
85
  * Inject a container query-wrapped atom.
52
86
  * @param className - e.g., '_cq640:gc3'
@@ -81,19 +115,9 @@ declare function getInjectedClasses(): string[];
81
115
  */
82
116
  declare function reset(): void;
83
117
 
84
- /**
85
- * Decantr CSS Atoms - Direct atom definitions and algorithmic resolution.
86
- */
87
- /**
88
- * Resolve an atom name to its CSS declaration.
89
- * @param atom - Atom name (e.g., '_flex', '_gap4', '_p2')
90
- * @returns CSS declaration or null if not recognized
91
- */
92
- declare function resolveAtomDecl(atom: string): string | null;
93
-
94
118
  declare function getAnimations(): boolean;
95
119
  declare function setAnimations(v: boolean): void;
96
120
  declare function getTheme(): string | null;
97
121
  declare function setTheme(id: string | null): void;
98
122
 
99
- export { BREAKPOINTS, CQ_WIDTHS, css, define, extractCSS, getAnimations, getInjectedClasses, getTheme, inject, injectContainer, injectGroupPeer, injectMediaQuery, injectPseudo, injectResponsive, reset, resolveAtomDecl, setAnimations, setTheme };
123
+ export { BREAKPOINTS, CQ_WIDTHS, css, define, extractCSS, getAnimations, getInjectedClasses, getTheme, inject, injectContainer, injectGroupPeer, injectMediaQuery, injectPseudo, injectResponsive, injectResponsiveMax, injectResponsiveMaxPseudo, injectResponsivePseudo, reset, resolveAtomDecl, setAnimations, setTheme };
package/dist/index.js CHANGED
@@ -61,6 +61,11 @@ var DIRECT = {
61
61
  // Sizing
62
62
  wfull: "width:100%",
63
63
  hfull: "height:100%",
64
+ // Hyphenated aliases — DECANTR.md examples used `_w-full` / `_h-full`
65
+ // historically; cold-LLM scaffolds fall back to the doc-spelling. Accept
66
+ // both so the doc and runtime can never silently disagree.
67
+ "w-full": "width:100%",
68
+ "h-full": "height:100%",
64
69
  w100: "width:100%",
65
70
  h100: "height:100%",
66
71
  wscreen: "width:100vw",
@@ -79,6 +84,20 @@ var DIRECT = {
79
84
  maxhfull: "max-height:100%",
80
85
  mw640: "max-width:40rem",
81
86
  mw480: "max-width:30rem",
87
+ // Item alignment aliases — DECANTR.md examples used `_items-center` /
88
+ // `_items-start` etc. (Tailwind-style); accept both alongside the
89
+ // canonical `_aic` / `_aifs` etc. so doc-driven AI scaffolds resolve.
90
+ "items-center": "align-items:center",
91
+ "items-start": "align-items:flex-start",
92
+ "items-end": "align-items:flex-end",
93
+ "items-stretch": "align-items:stretch",
94
+ "items-baseline": "align-items:baseline",
95
+ "justify-center": "justify-content:center",
96
+ "justify-start": "justify-content:flex-start",
97
+ "justify-end": "justify-content:flex-end",
98
+ "justify-between": "justify-content:space-between",
99
+ "justify-around": "justify-content:space-around",
100
+ "justify-evenly": "justify-content:space-evenly",
82
101
  // Overflow
83
102
  overhidden: "overflow:hidden",
84
103
  overauto: "overflow:auto",
@@ -421,6 +440,498 @@ var GRID_SPAN = {
421
440
  rowspan6: "grid-row:span 6/span 6",
422
441
  rowspanfull: "grid-row:1/-1"
423
442
  };
443
+ var TAILWIND_DIRECT = {
444
+ relative: "position:relative",
445
+ absolute: "position:absolute",
446
+ "gap-auto": "gap:var(--d-gap,1rem)",
447
+ "inline-flex": "display:inline-flex",
448
+ "inline-grid": "display:inline-grid",
449
+ center: "align-items:center;justify-content:center",
450
+ "align-center": "align-items:center",
451
+ "align-start": "align-items:flex-start",
452
+ "flex-col": "flex-direction:column",
453
+ "flex-row": "flex-direction:row",
454
+ "col-reverse": "flex-direction:column-reverse",
455
+ "flex-col-reverse": "flex-direction:column-reverse",
456
+ "flex-row-reverse": "flex-direction:row-reverse",
457
+ "flex-wrap": "flex-wrap:wrap",
458
+ flexwrap: "flex-wrap:wrap",
459
+ "flex-nowrap": "flex-wrap:nowrap",
460
+ "flex-wrap-nowrap": "flex-wrap:nowrap",
461
+ "flex-1": "flex:1",
462
+ "flex-auto": "flex:auto",
463
+ "flex-none": "flex:none",
464
+ "grow-0": "flex-grow:0",
465
+ "shrink-0": "flex-shrink:0",
466
+ "items-center": "align-items:center",
467
+ "items-start": "align-items:flex-start",
468
+ "items-end": "align-items:flex-end",
469
+ "items-stretch": "align-items:stretch",
470
+ "items-baseline": "align-items:baseline",
471
+ "justify-center": "justify-content:center",
472
+ "justify-start": "justify-content:flex-start",
473
+ "justify-end": "justify-content:flex-end",
474
+ "justify-between": "justify-content:space-between",
475
+ "justify-around": "justify-content:space-around",
476
+ "justify-evenly": "justify-content:space-evenly",
477
+ "place-items-center": "place-items:center",
478
+ "place-content-center": "place-content:center",
479
+ "self-center": "align-self:center",
480
+ "self-start": "align-self:flex-start",
481
+ "self-end": "align-self:flex-end",
482
+ "overflow-hidden": "overflow:hidden",
483
+ "overflow-auto": "overflow:auto",
484
+ "overflow-visible": "overflow:visible",
485
+ overflowhidden: "overflow:hidden",
486
+ "overflow-x-hidden": "overflow-x:hidden",
487
+ "overflow-x-auto": "overflow-x:auto",
488
+ "overflow-y-hidden": "overflow-y:hidden",
489
+ "overflow-y-auto": "overflow-y:auto",
490
+ "scrollbar-thin": "scrollbar-width:thin",
491
+ "pointer-events-none": "pointer-events:none",
492
+ "pointer-events-auto": "pointer-events:auto",
493
+ "pointer-events-restricted": "pointer-events:none",
494
+ "cursor-pointer": "cursor:pointer",
495
+ "cursor-grab": "cursor:grab",
496
+ "select-none": "user-select:none",
497
+ "whitespace-nowrap": "white-space:nowrap",
498
+ "whitespace-pre": "white-space:pre",
499
+ "whitespace-pre-wrap": "white-space:pre-wrap",
500
+ "break-words": "overflow-wrap:break-word",
501
+ "break-all": "word-break:break-all",
502
+ "sr-only": "position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0",
503
+ "not-sr-only": "position:static;width:auto;height:auto;padding:0;margin:0;overflow:visible;clip:auto;white-space:normal",
504
+ "object-cover": "object-fit:cover",
505
+ "object-contain": "object-fit:contain",
506
+ "object-center": "object-position:center",
507
+ "list-none": "list-style:none",
508
+ mono: "font-family:var(--d-font-mono,ui-monospace,monospace)",
509
+ "aspect-video": "aspect-ratio:16/9",
510
+ "aspect-square": "aspect-ratio:1/1",
511
+ full: "width:100%;height:100%",
512
+ "w-full": "width:100%",
513
+ "h-full": "height:100%",
514
+ "w-screen": "width:100vw",
515
+ "h-screen": "height:100vh",
516
+ "w-auto": "width:auto",
517
+ "h-auto": "height:auto",
518
+ "w-fit": "width:fit-content",
519
+ "h-fit": "height:fit-content",
520
+ "min-w-0": "min-width:0",
521
+ "min-h-0": "min-height:0",
522
+ "min-h-screen": "min-height:100vh",
523
+ "min-h-dvh": "min-height:100dvh",
524
+ "max-w-full": "max-width:100%",
525
+ "max-w-none": "max-width:none",
526
+ "mx-auto": "margin-inline:auto",
527
+ "my-auto": "margin-block:auto",
528
+ "mt-auto": "margin-top:auto",
529
+ "mb-auto": "margin-bottom:auto",
530
+ "ml-auto": "margin-left:auto",
531
+ "mr-auto": "margin-right:auto",
532
+ "inset-0": "inset:0",
533
+ "inset-x-0": "left:0;right:0",
534
+ "inset-y-0": "top:0;bottom:0",
535
+ "top-0": "top:0",
536
+ "right-0": "right:0",
537
+ "bottom-0": "bottom:0",
538
+ "left-0": "left:0",
539
+ "left-1/2": "left:50%",
540
+ "top-1/2": "top:50%",
541
+ "-translate-x-1/2": "translate:-50% 0",
542
+ "-translate-y-1/2": "translate:0 -50%",
543
+ jcs: "justify-content:flex-start",
544
+ jce: "justify-content:flex-end",
545
+ "border": "border:1px solid var(--d-border)",
546
+ "border-t": "border-top:1px solid var(--d-border)",
547
+ "border-r": "border-right:1px solid var(--d-border)",
548
+ "border-b": "border-bottom:1px solid var(--d-border)",
549
+ "border-l": "border-left:1px solid var(--d-border)",
550
+ "border-0": "border:0",
551
+ border2: "border:2px solid var(--d-border)",
552
+ "border-dashed": "border-style:dashed",
553
+ borderb: "border-bottom:1px solid var(--d-border)",
554
+ borderB: "border-bottom:1px solid var(--d-border)",
555
+ borderT: "border-top:1px solid var(--d-border)",
556
+ borderR: "border-right:1px solid var(--d-border)",
557
+ borderL: "border-left:1px solid var(--d-border)",
558
+ bbsolid: "border-bottom:1px solid var(--d-border)",
559
+ rfull: "border-radius:9999px",
560
+ "rounded-full": "border-radius:9999px",
561
+ "rounded-none": "border-radius:0",
562
+ "rounded-sm": "border-radius:0.25rem",
563
+ "rounded-md": "border-radius:0.375rem",
564
+ "rounded-lg": "border-radius:0.5rem",
565
+ "rounded-xl": "border-radius:0.75rem",
566
+ "rounded-2xl": "border-radius:1rem",
567
+ "rounded-3xl": "border-radius:1.5rem",
568
+ "shadow-sm": "box-shadow:0 1px 2px rgba(0,0,0,0.05)",
569
+ "shadow-md": "box-shadow:0 4px 6px rgba(0,0,0,0.1)",
570
+ "shadow-lg": "box-shadow:0 10px 15px rgba(0,0,0,0.1)",
571
+ "shadow-xl": "box-shadow:0 20px 25px rgba(0,0,0,0.1)",
572
+ "shadow-none": "box-shadow:none",
573
+ "backdrop-blur": "backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px)",
574
+ "backdrop-blur-sm": "backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px)",
575
+ "backdrop-blur-md": "backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px)",
576
+ "backdrop-blur-lg": "backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px)",
577
+ "transition": "transition:all 0.15s ease",
578
+ "transition-all": "transition:all 0.15s ease",
579
+ "transition-colors": "transition:color,background-color,border-color 0.15s ease",
580
+ "scroll-smooth": "scroll-behavior:smooth",
581
+ "duration-150": "transition-duration:150ms",
582
+ "duration-200": "transition-duration:200ms",
583
+ "duration-300": "transition-duration:300ms",
584
+ "ease-out": "transition-timing-function:cubic-bezier(0,0,0.2,1)",
585
+ "ease-in-out": "transition-timing-function:cubic-bezier(0.4,0,0.2,1)",
586
+ tc: "text-align:center",
587
+ textCenter: "text-align:center",
588
+ fggreen: "color:#22c55e",
589
+ compact: "gap:0.5rem",
590
+ "auto-rows-fr": "grid-auto-rows:minmax(0,1fr)"
591
+ };
592
+ var TAILWIND_MAX_WIDTH = {
593
+ xs: "20rem",
594
+ sm: "24rem",
595
+ md: "28rem",
596
+ lg: "32rem",
597
+ xl: "36rem",
598
+ "2xl": "42rem",
599
+ "3xl": "48rem",
600
+ "4xl": "56rem",
601
+ "5xl": "64rem",
602
+ "6xl": "72rem",
603
+ "7xl": "80rem",
604
+ full: "100%",
605
+ none: "none",
606
+ "screen-sm": "640px",
607
+ "screen-md": "768px",
608
+ "screen-lg": "1024px",
609
+ "screen-xl": "1280px",
610
+ "screen-2xl": "1536px"
611
+ };
612
+ var TAILWIND_ARBITRARY_PROPS = {
613
+ w: "width",
614
+ h: "height",
615
+ mw: "max-width",
616
+ mh: "max-height",
617
+ maxw: "max-width",
618
+ maxh: "max-height",
619
+ minw: "min-width",
620
+ minh: "min-height",
621
+ "min-w": "min-width",
622
+ "min-h": "min-height",
623
+ "max-w": "max-width",
624
+ "max-h": "max-height",
625
+ p: "padding",
626
+ px: "padding-inline",
627
+ py: "padding-block",
628
+ pt: "padding-top",
629
+ pr: "padding-right",
630
+ pb: "padding-bottom",
631
+ pl: "padding-left",
632
+ m: "margin",
633
+ mx: "margin-inline",
634
+ my: "margin-block",
635
+ mt: "margin-top",
636
+ mr: "margin-right",
637
+ mb: "margin-bottom",
638
+ ml: "margin-left",
639
+ gap: "gap",
640
+ "gap-x": "column-gap",
641
+ "gap-y": "row-gap",
642
+ "grid-cols": "grid-template-columns",
643
+ "grid-rows": "grid-template-rows",
644
+ gc: "grid-template-columns",
645
+ gr: "grid-template-rows",
646
+ "border": "border",
647
+ bb: "border-bottom",
648
+ bt: "border-top",
649
+ "rounded": "border-radius",
650
+ "text": "text-align",
651
+ "bg": "background",
652
+ "z": "z-index",
653
+ "top": "top",
654
+ "right": "right",
655
+ "bottom": "bottom",
656
+ "left": "left",
657
+ "inset": "inset",
658
+ "aspect": "aspect-ratio"
659
+ };
660
+ var TAILWIND_SPACING_PROPS = {
661
+ p: "padding",
662
+ px: "padding-inline",
663
+ py: "padding-block",
664
+ pt: "padding-top",
665
+ pr: "padding-right",
666
+ pb: "padding-bottom",
667
+ pl: "padding-left",
668
+ m: "margin",
669
+ mx: "margin-inline",
670
+ my: "margin-block",
671
+ mt: "margin-top",
672
+ mr: "margin-right",
673
+ mb: "margin-bottom",
674
+ ml: "margin-left",
675
+ gap: "gap",
676
+ "gap-x": "column-gap",
677
+ "gap-y": "row-gap",
678
+ top: "top",
679
+ right: "right",
680
+ bottom: "bottom",
681
+ left: "left",
682
+ inset: "inset"
683
+ };
684
+ var FONT_WEIGHTS = {
685
+ light: "300",
686
+ normal: "400",
687
+ medium: "500",
688
+ semibold: "600",
689
+ bold: "700",
690
+ extrabold: "800"
691
+ };
692
+ var LINE_HEIGHTS = {
693
+ none: "1",
694
+ tight: "1.25",
695
+ snug: "1.375",
696
+ normal: "1.5",
697
+ relaxed: "1.625",
698
+ loose: "2"
699
+ };
700
+ var LETTER_SPACING = {
701
+ tight: "-0.025em",
702
+ normal: "0",
703
+ wide: "0.025em",
704
+ wider: "0.05em",
705
+ widest: "0.1em"
706
+ };
707
+ function spacingValue(token) {
708
+ if (token === "px") return "1px";
709
+ const n = Number(token);
710
+ if (!Number.isFinite(n)) return null;
711
+ return SPACING_SCALE[n] ?? null;
712
+ }
713
+ function fractionValue(token) {
714
+ const match = token.match(/^(\d+)\/(\d+)$/);
715
+ if (!match) return null;
716
+ const numerator = Number(match[1]);
717
+ const denominator = Number(match[2]);
718
+ if (!denominator) return null;
719
+ return `${numerator / denominator * 100}%`;
720
+ }
721
+ function dimensionValue(prop, token) {
722
+ if (token === "full") return "100%";
723
+ if (token === "auto") return "auto";
724
+ if (token === "fit") return "fit-content";
725
+ if (token === "min") return "min-content";
726
+ if (token === "max") return "max-content";
727
+ if (token === "screen") return prop.includes("h") ? "100vh" : "100vw";
728
+ if (token === "dvh" && prop.includes("h")) return "100dvh";
729
+ if (prop === "max-w" && TAILWIND_MAX_WIDTH[token]) return TAILWIND_MAX_WIDTH[token];
730
+ const spacing = spacingValue(token);
731
+ if (spacing) return spacing;
732
+ const fraction = fractionValue(token);
733
+ if (fraction) return fraction;
734
+ if (/^\d+(?:\.\d+)?$/.test(token)) return `${token}px`;
735
+ return null;
736
+ }
737
+ function sanitizeTailwindValue(value) {
738
+ let safe = value.replace(/[{}<>;]/g, "");
739
+ safe = safe.replace(/url\s*\(/gi, "");
740
+ return safe.replace(/_/g, " ");
741
+ }
742
+ function semanticColorValue(token, prop) {
743
+ const key = token.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
744
+ if (key === "transparent") return "transparent";
745
+ if (key === "white") return "#fff";
746
+ if (key === "black") return "#000";
747
+ if (key === "background" || key === "bg" || key === "canvas") return "var(--d-bg)";
748
+ if (key === "surface" || key === "card") return "var(--d-surface)";
749
+ if (key === "surface-subtle" || key === "surface-muted") {
750
+ return "var(--d-surface-1,var(--d-surface))";
751
+ }
752
+ if (key === "surface-raised" || key === "raised" || key === "popover") {
753
+ return "var(--d-surface-raised)";
754
+ }
755
+ if (key === "primary") return "var(--d-primary)";
756
+ if (key === "secondary") return "var(--d-secondary)";
757
+ if (key === "accent") return "var(--d-accent)";
758
+ if (key === "success") return "var(--d-success,#22c55e)";
759
+ if (key === "warning") return "var(--d-warning,#f59e0b)";
760
+ if (key === "danger" || key === "error" || key === "destructive") return "var(--d-error,#ef4444)";
761
+ if (key === "info") return "var(--d-info,#3b82f6)";
762
+ if (key === "green") return "#22c55e";
763
+ if (key === "red") return "#ef4444";
764
+ if (key === "amber" || key === "yellow") return "#f59e0b";
765
+ if (key === "blue") return "#3b82f6";
766
+ if (key === "gray-950") return "#030712";
767
+ if (key === "gray" || key === "slate") return "#64748b";
768
+ if (key === "border" || key === "input") return "var(--d-border)";
769
+ if (key === "text" || key === "foreground" || key === "fg") return "var(--d-text)";
770
+ if (key === "muted") {
771
+ if (prop === "color") return "var(--d-text-muted,var(--d-muted))";
772
+ if (prop === "border-color") return "var(--d-muted,var(--d-border))";
773
+ return "var(--d-muted,var(--d-surface))";
774
+ }
775
+ return null;
776
+ }
777
+ function semanticColorDecl(prop, rawToken) {
778
+ const alphaMatch = rawToken.match(/^(.+)\/(\d+)$/);
779
+ const token = alphaMatch ? alphaMatch[1] : rawToken;
780
+ const value = semanticColorValue(token, prop);
781
+ if (!value) return null;
782
+ if (alphaMatch) {
783
+ const alpha = Number(alphaMatch[2]);
784
+ if (!Number.isFinite(alpha) || alpha < 0 || alpha > 100) return null;
785
+ return `${prop}:color-mix(in srgb,${value} ${alpha}%,transparent)`;
786
+ }
787
+ return `${prop}:${value}`;
788
+ }
789
+ function resolveTailwindishDecl(name) {
790
+ if (TAILWIND_DIRECT[name]) return TAILWIND_DIRECT[name];
791
+ const arbitraryMatch = name.match(/^([a-z]+(?:-[a-z]+)*)-\[([^\]]+)\]$/);
792
+ if (arbitraryMatch) {
793
+ const [, prefix, rawValue] = arbitraryMatch;
794
+ const prop = TAILWIND_ARBITRARY_PROPS[prefix];
795
+ if (!prop) return null;
796
+ const value = sanitizeTailwindValue(rawValue);
797
+ return value ? `${prop}:${value}` : null;
798
+ }
799
+ const compactArbitraryMatch = name.match(/^([a-z]+(?:-[a-z]+)?)\[([^\]]+)\]$/);
800
+ if (compactArbitraryMatch) {
801
+ const [, prefix, rawValue] = compactArbitraryMatch;
802
+ if (prefix === "scale") {
803
+ const value2 = sanitizeTailwindValue(rawValue);
804
+ return value2 ? `transform:scale(${value2})` : null;
805
+ }
806
+ const prop = TAILWIND_ARBITRARY_PROPS[prefix];
807
+ if (!prop) return null;
808
+ const value = sanitizeTailwindValue(rawValue);
809
+ return value ? `${prop}:${value}` : null;
810
+ }
811
+ const dimensionMatch = name.match(/^(w|h|min-w|min-h|max-w|max-h)-(.+)$/);
812
+ if (dimensionMatch) {
813
+ const [, prop, token] = dimensionMatch;
814
+ const cssProp = {
815
+ w: "width",
816
+ h: "height",
817
+ "min-w": "min-width",
818
+ "min-h": "min-height",
819
+ "max-w": "max-width",
820
+ "max-h": "max-height"
821
+ }[prop];
822
+ const value = dimensionValue(prop, token);
823
+ if (cssProp && value) return `${cssProp}:${value}`;
824
+ }
825
+ const spacingMatch = name.match(
826
+ /^(-?)(gap-x|gap-y|gap|px|py|pt|pr|pb|pl|p|mx|my|mt|mr|mb|ml|m|top|right|bottom|left|inset)-(\d+(?:\.\d+)?|px)$/
827
+ );
828
+ if (spacingMatch) {
829
+ const [, negative, prefix, token] = spacingMatch;
830
+ const prop = TAILWIND_SPACING_PROPS[prefix];
831
+ const value = spacingValue(token);
832
+ if (prop && value) {
833
+ const canBeNegative = prop.startsWith("margin") || ["top", "right", "bottom", "left"].includes(prop);
834
+ if (negative && !canBeNegative) return null;
835
+ return `${prop}:${negative ? "-" : ""}${value}`;
836
+ }
837
+ }
838
+ const gridColsMatch = name.match(/^grid-cols-(\d+)$/);
839
+ if (gridColsMatch) {
840
+ return `grid-template-columns:repeat(${gridColsMatch[1]},minmax(0,1fr))`;
841
+ }
842
+ if (name === "grid-cols-auto-fill") {
843
+ return "grid-template-columns:repeat(auto-fill,minmax(16rem,1fr))";
844
+ }
845
+ if (name === "grid-cols-auto") {
846
+ return "grid-template-columns:repeat(auto-fit,minmax(0,1fr))";
847
+ }
848
+ const gridRowsMatch = name.match(/^grid-rows-(\d+)$/);
849
+ if (gridRowsMatch) {
850
+ return `grid-template-rows:repeat(${gridRowsMatch[1]},minmax(0,1fr))`;
851
+ }
852
+ const colSpanMatch = name.match(/^col-span-(\d+|full)$/);
853
+ if (colSpanMatch) {
854
+ const span = colSpanMatch[1];
855
+ return span === "full" ? "grid-column:1/-1" : `grid-column:span ${span}/span ${span}`;
856
+ }
857
+ const rowSpanMatch = name.match(/^row-span-(\d+|full)$/);
858
+ if (rowSpanMatch) {
859
+ const span = rowSpanMatch[1];
860
+ return span === "full" ? "grid-row:1/-1" : `grid-row:span ${span}/span ${span}`;
861
+ }
862
+ const columnsMatch = name.match(/^(?:cols|columns)(\d+)$/);
863
+ if (columnsMatch) return `columns:${columnsMatch[1]}`;
864
+ const textMatch = name.match(/^text-(.+)$/);
865
+ if (textMatch) {
866
+ const token = textMatch[1];
867
+ if (TEXT_SCALE[token]) return TEXT_SCALE[token];
868
+ return semanticColorDecl("color", token);
869
+ }
870
+ const bgMatch = name.match(/^bg-(.+)$/);
871
+ if (bgMatch) return semanticColorDecl("background", bgMatch[1]);
872
+ const borderColorMatch = name.match(/^border-(.+)$/);
873
+ if (borderColorMatch) {
874
+ const decl = semanticColorDecl("border-color", borderColorMatch[1]);
875
+ if (decl) return decl;
876
+ }
877
+ const compactBorderColorMatch = name.match(/^border([a-zA-Z0-9-]+\/?\d*)$/);
878
+ if (compactBorderColorMatch) {
879
+ const decl = semanticColorDecl("border-color", compactBorderColorMatch[1]);
880
+ if (decl) return decl;
881
+ }
882
+ const compactFgMatch = name.match(/^fg([a-zA-Z0-9-]+\/?\d*)$/);
883
+ if (compactFgMatch) return semanticColorDecl("color", compactFgMatch[1]);
884
+ const compactBgMatch = name.match(/^bg([a-zA-Z0-9-]+\/?\d*)$/);
885
+ if (compactBgMatch) return semanticColorDecl("background", compactBgMatch[1]);
886
+ const borderSideWidthMatch = name.match(/^border-([trbl])-(\d+)$/);
887
+ if (borderSideWidthMatch) {
888
+ const side = { t: "top", r: "right", b: "bottom", l: "left" }[borderSideWidthMatch[1]];
889
+ return `border-${side}:${borderSideWidthMatch[2]}px solid var(--d-border)`;
890
+ }
891
+ const roundedSideMatch = name.match(/^rounded-([rltb])-(sm|md|lg|xl|2xl|3xl|full)$/);
892
+ if (roundedSideMatch) {
893
+ const [, side, size] = roundedSideMatch;
894
+ const value = {
895
+ sm: "0.25rem",
896
+ md: "0.375rem",
897
+ lg: "0.5rem",
898
+ xl: "0.75rem",
899
+ "2xl": "1rem",
900
+ "3xl": "1.5rem",
901
+ full: "9999px"
902
+ }[size];
903
+ if (!value) return null;
904
+ if (side === "r") return `border-top-right-radius:${value};border-bottom-right-radius:${value}`;
905
+ if (side === "l") return `border-top-left-radius:${value};border-bottom-left-radius:${value}`;
906
+ if (side === "t") return `border-top-left-radius:${value};border-top-right-radius:${value}`;
907
+ if (side === "b") return `border-bottom-left-radius:${value};border-bottom-right-radius:${value}`;
908
+ }
909
+ const fontMatch = name.match(/^font-(.+)$/);
910
+ if (fontMatch && FONT_WEIGHTS[fontMatch[1]]) return `font-weight:${FONT_WEIGHTS[fontMatch[1]]}`;
911
+ const leadingMatch = name.match(/^leading-(.+)$/);
912
+ if (leadingMatch && LINE_HEIGHTS[leadingMatch[1]]) return `line-height:${LINE_HEIGHTS[leadingMatch[1]]}`;
913
+ const trackingMatch = name.match(/^tracking-(.+)$/);
914
+ if (trackingMatch && LETTER_SPACING[trackingMatch[1]]) {
915
+ return `letter-spacing:${LETTER_SPACING[trackingMatch[1]]}`;
916
+ }
917
+ const opacityMatch = name.match(/^opacity-(\d+)$/);
918
+ if (opacityMatch) {
919
+ const n = Number(opacityMatch[1]);
920
+ if (n >= 0 && n <= 100) return `opacity:${n / 100}`;
921
+ }
922
+ const zMatch = name.match(/^z-(\d+|auto)$/);
923
+ if (zMatch) return zMatch[1] === "auto" ? "z-index:auto" : `z-index:${zMatch[1]}`;
924
+ const compactZMatch = name.match(/^z(\d+)$/);
925
+ if (compactZMatch) return `z-index:${compactZMatch[1]}`;
926
+ const perspectiveMatch = name.match(/^perspective-(\d+)$/);
927
+ if (perspectiveMatch) return `perspective:${perspectiveMatch[1]}px`;
928
+ const negativeSpaceXMatch = name.match(/^-space-x-(\d+(?:\.\d+)?)$/);
929
+ if (negativeSpaceXMatch) {
930
+ const value = spacingValue(negativeSpaceXMatch[1]);
931
+ if (value) return `margin-left:-${value}`;
932
+ }
933
+ return null;
934
+ }
424
935
  function resolveAtomDecl(atom) {
425
936
  const name = atom.startsWith("_") ? atom.slice(1) : atom;
426
937
  if (DIRECT[name]) return DIRECT[name];
@@ -428,6 +939,8 @@ function resolveAtomDecl(atom) {
428
939
  if (GRID_COLS[name]) return GRID_COLS[name];
429
940
  if (GRID_ROWS[name]) return GRID_ROWS[name];
430
941
  if (GRID_SPAN[name]) return GRID_SPAN[name];
942
+ const tailwindish = resolveTailwindishDecl(name);
943
+ if (tailwindish) return tailwindish;
431
944
  if (name.startsWith("text")) {
432
945
  const size = name.slice(4);
433
946
  if (TEXT_SCALE[size]) return TEXT_SCALE[size];
@@ -484,6 +997,17 @@ function resolveAtomDecl(atom) {
484
997
  if (dir === "y") return `margin-block:${value}`;
485
998
  }
486
999
  }
1000
+ const marginAutoMatch = name.match(/^m([trblxy]?)auto$/);
1001
+ if (marginAutoMatch) {
1002
+ const [, dir] = marginAutoMatch;
1003
+ if (!dir || dir === "") return `margin:auto`;
1004
+ if (dir === "t") return `margin-top:auto`;
1005
+ if (dir === "r") return `margin-right:auto`;
1006
+ if (dir === "b") return `margin-bottom:auto`;
1007
+ if (dir === "l") return `margin-left:auto`;
1008
+ if (dir === "x") return `margin-inline:auto`;
1009
+ if (dir === "y") return `margin-block:auto`;
1010
+ }
487
1011
  const negMarginMatch = name.match(/^-m([trblxy]?)(\d+(?:\.\d+)?)$/);
488
1012
  if (negMarginMatch) {
489
1013
  const [, dir, num] = negMarginMatch;
@@ -590,6 +1114,7 @@ function resolveAtomDecl(atom) {
590
1114
  var injected = /* @__PURE__ */ new Set();
591
1115
  var BREAKPOINTS = { sm: 640, md: 768, lg: 1024, xl: 1280 };
592
1116
  var BP_ORDER = ["sm", "md", "lg", "xl"];
1117
+ var BP_MAX_ORDER = ["xlmax", "lgmax", "mdmax", "smmax"];
593
1118
  var CQ_WIDTHS = [320, 480, 640, 768, 1024];
594
1119
  var LAYER_ORDER = "@layer d.base,d.theme,d.atoms,d.user;";
595
1120
  var atomBuffer = [];
@@ -625,6 +1150,12 @@ function flushBuffers() {
625
1150
  bpBuffers[bp] = [];
626
1151
  }
627
1152
  }
1153
+ for (const bp of BP_MAX_ORDER) {
1154
+ if (bpBuffers[bp]?.length) {
1155
+ els[bp].textContent = (els[bp].textContent || "") + bpBuffers[bp].join("");
1156
+ bpBuffers[bp] = [];
1157
+ }
1158
+ }
628
1159
  }
629
1160
  bpBuffers = {};
630
1161
  }
@@ -663,6 +1194,12 @@ function ensureBpElements() {
663
1194
  document.head.appendChild(el);
664
1195
  bpEls[bp] = el;
665
1196
  }
1197
+ for (const bp of BP_MAX_ORDER) {
1198
+ const el = document.createElement("style");
1199
+ el.setAttribute(`data-decantr-${bp}`, "");
1200
+ document.head.appendChild(el);
1201
+ bpEls[bp] = el;
1202
+ }
666
1203
  return bpEls;
667
1204
  }
668
1205
  function ensureCqElement() {
@@ -686,9 +1223,22 @@ function injectResponsive(className, declaration, bp) {
686
1223
  if (injected.has(className)) return;
687
1224
  injected.add(className);
688
1225
  if (typeof document === "undefined") return;
689
- const escaped = className.replace(/:/g, "\\:");
1226
+ const escaped = escapeSelector(className);
690
1227
  if (!bpBuffers[bp]) bpBuffers[bp] = [];
691
- bpBuffers[bp].push(`@layer d.atoms{@media(min-width:${BREAKPOINTS[bp]}px){.${escaped}{${declaration}}}}`);
1228
+ bpBuffers[bp].push(
1229
+ `@layer d.atoms{@media(min-width:${BREAKPOINTS[bp]}px){.${escaped}{${declaration}}}}`
1230
+ );
1231
+ scheduleFlush();
1232
+ }
1233
+ function injectResponsiveMax(className, declaration, bp) {
1234
+ if (injected.has(className)) return;
1235
+ injected.add(className);
1236
+ if (typeof document === "undefined") return;
1237
+ const escaped = escapeSelector(className);
1238
+ const key = `${bp}max`;
1239
+ if (!bpBuffers[key]) bpBuffers[key] = [];
1240
+ const maxPx = BREAKPOINTS[bp] - 0.02;
1241
+ bpBuffers[key].push(`@layer d.atoms{@media(max-width:${maxPx}px){.${escaped}{${declaration}}}}`);
692
1242
  scheduleFlush();
693
1243
  }
694
1244
  function injectPseudo(className, declaration, prefix) {
@@ -713,14 +1263,29 @@ function injectResponsivePseudo(className, declaration, bp, pseudo) {
713
1263
  if (typeof document === "undefined") return;
714
1264
  const escaped = escapeSelector(className);
715
1265
  if (!bpBuffers[bp]) bpBuffers[bp] = [];
716
- bpBuffers[bp].push(`@layer d.atoms{@media(min-width:${BREAKPOINTS[bp]}px){.${escaped}:${pseudo}{${declaration}}}}`);
1266
+ bpBuffers[bp].push(
1267
+ `@layer d.atoms{@media(min-width:${BREAKPOINTS[bp]}px){.${escaped}:${pseudo}{${declaration}}}}`
1268
+ );
1269
+ scheduleFlush();
1270
+ }
1271
+ function injectResponsiveMaxPseudo(className, declaration, bp, pseudo) {
1272
+ if (injected.has(className)) return;
1273
+ injected.add(className);
1274
+ if (typeof document === "undefined") return;
1275
+ const escaped = escapeSelector(className);
1276
+ const key = `${bp}max`;
1277
+ if (!bpBuffers[key]) bpBuffers[key] = [];
1278
+ const maxPx = BREAKPOINTS[bp] - 0.02;
1279
+ bpBuffers[key].push(
1280
+ `@layer d.atoms{@media(max-width:${maxPx}px){.${escaped}:${pseudo}{${declaration}}}}`
1281
+ );
717
1282
  scheduleFlush();
718
1283
  }
719
1284
  function injectContainer(className, declaration, width) {
720
1285
  if (injected.has(className)) return;
721
1286
  injected.add(className);
722
1287
  if (typeof document === "undefined") return;
723
- const escaped = className.replace(/:/g, "\\:");
1288
+ const escaped = escapeSelector(className);
724
1289
  cqBuffer.push(`@layer d.atoms{@container(min-width:${width}px){.${escaped}{${declaration}}}}`);
725
1290
  scheduleFlush();
726
1291
  }
@@ -746,12 +1311,12 @@ function injectMediaQuery(className, declaration, query) {
746
1311
  if (injected.has(className)) return;
747
1312
  injected.add(className);
748
1313
  if (typeof document === "undefined") return;
749
- const escaped = className.replace(/:/g, "\\:");
1314
+ const escaped = escapeSelector(className);
750
1315
  atomBuffer.push(`@layer d.atoms{@media${query}{.${escaped}{${declaration}}}}`);
751
1316
  scheduleFlush();
752
1317
  }
753
1318
  function escapeSelector(className) {
754
- return className.replace(/:/g, "\\:").replace(/\//g, "\\/").replace(/\[/g, "\\[").replace(/\]/g, "\\]").replace(/#/g, "\\#").replace(/%/g, "\\%").replace(/\(/g, "\\(").replace(/\)/g, "\\)").replace(/,/g, "\\,").replace(/\+/g, "\\+");
1319
+ return className.replace(/:/g, "\\:").replace(/\./g, "\\.").replace(/\//g, "\\/").replace(/\[/g, "\\[").replace(/\]/g, "\\]").replace(/#/g, "\\#").replace(/%/g, "\\%").replace(/\(/g, "\\(").replace(/\)/g, "\\)").replace(/,/g, "\\,").replace(/\+/g, "\\+");
755
1320
  }
756
1321
  function extractCSS() {
757
1322
  flushBuffers();
@@ -761,6 +1326,9 @@ function extractCSS() {
761
1326
  for (const bp of BP_ORDER) {
762
1327
  if (bpEls[bp]) css2 += bpEls[bp].textContent || "";
763
1328
  }
1329
+ for (const bp of BP_MAX_ORDER) {
1330
+ if (bpEls[bp]) css2 += bpEls[bp].textContent || "";
1331
+ }
764
1332
  }
765
1333
  if (cqEl) css2 += cqEl.textContent || "";
766
1334
  return css2;
@@ -780,6 +1348,9 @@ function reset() {
780
1348
  for (const bp of BP_ORDER) {
781
1349
  if (bpEls[bp]) bpEls[bp].textContent = "";
782
1350
  }
1351
+ for (const bp of BP_MAX_ORDER) {
1352
+ if (bpEls[bp]) bpEls[bp].textContent = "";
1353
+ }
783
1354
  }
784
1355
  if (cqEl) cqEl.textContent = "";
785
1356
  }
@@ -787,6 +1358,7 @@ function reset() {
787
1358
  // src/css.ts
788
1359
  var customAtoms = /* @__PURE__ */ new Map();
789
1360
  var BP_RE = /^_(sm|md|lg|xl):(.+)$/;
1361
+ var BP_MAX_RE = /^_(sm|md|lg|xl)max:(.+)$/;
790
1362
  var CQ_RE = /^_cq(\d+):(.+)$/;
791
1363
  var GP_RE = /^_(gh|gf|ga|ph|pf|pa):(.+)$/;
792
1364
  var PSEUDO_RE = /^_(h|f|fv|a|fw):(.+)$/;
@@ -810,6 +1382,8 @@ var ARB_PROPS = {
810
1382
  h: "height",
811
1383
  mw: "max-width",
812
1384
  mh: "max-height",
1385
+ maxw: "max-width",
1386
+ maxh: "max-height",
813
1387
  minw: "min-width",
814
1388
  minh: "min-height",
815
1389
  p: "padding",
@@ -834,7 +1408,10 @@ var ARB_PROPS = {
834
1408
  lh: "line-height",
835
1409
  fw: "font-weight",
836
1410
  ls: "letter-spacing",
1411
+ leading: "line-height",
1412
+ tracking: "letter-spacing",
837
1413
  r: "border-radius",
1414
+ rounded: "border-radius",
838
1415
  bg: "background",
839
1416
  fg: "color",
840
1417
  bc: "border-color",
@@ -843,6 +1420,7 @@ var ARB_PROPS = {
843
1420
  bb: "border-bottom",
844
1421
  br: "border-right",
845
1422
  bl: "border-left",
1423
+ border: "border",
846
1424
  z: "z-index",
847
1425
  op: "opacity",
848
1426
  top: "top",
@@ -856,7 +1434,28 @@ var ARB_PROPS = {
856
1434
  trans: "transition",
857
1435
  object: "object-fit",
858
1436
  gc: "grid-template-columns",
859
- gr: "grid-template-rows"
1437
+ gr: "grid-template-rows",
1438
+ // Additional content-observed bracket atoms (P0-3 expansion). The v1
1439
+ // harness report flagged the page-pack Surface emitting atoms the
1440
+ // runtime didn't resolve; same class of silent-failure applies when
1441
+ // pattern JSONs use prefixes not in this map. These additions cover
1442
+ // every bracket prefix observed across the 209 archetype + 80+ pattern
1443
+ // JSONs in decantr-content.
1444
+ overflow: "overflow",
1445
+ pointer: "pointer-events",
1446
+ text: "text-align",
1447
+ whitespace: "white-space",
1448
+ items: "align-items",
1449
+ justify: "justify-content",
1450
+ aspect: "aspect-ratio",
1451
+ snap: "scroll-snap-type",
1452
+ // Note: 'scale' intentionally omitted — use the numeric `_scale95` /
1453
+ // `_scale100` / `_scale105` atoms. Bracket form would need value wrapping
1454
+ // (`scale(1.05)` vs `1.05`) which the generic emitter can't do.
1455
+ display: "display",
1456
+ position: "position",
1457
+ pos: "position",
1458
+ cursor: "cursor"
860
1459
  };
861
1460
  function sanitizeArbValue(val) {
862
1461
  let safe = val.replace(/[{}<>;]/g, "");
@@ -901,7 +1500,7 @@ function resolveAtom(atomPart) {
901
1500
  return null;
902
1501
  }
903
1502
  function escapeClass(cls) {
904
- return cls.replace(/:/g, "\\:").replace(/\//g, "\\/").replace(/\[/g, "\\[").replace(/\]/g, "\\]").replace(/#/g, "\\#").replace(/%/g, "\\%").replace(/\(/g, "\\(").replace(/\)/g, "\\)").replace(/,/g, "\\,").replace(/\+/g, "\\+");
1503
+ return cls.replace(/:/g, "\\:").replace(/\./g, "\\.").replace(/\//g, "\\/").replace(/\[/g, "\\[").replace(/\]/g, "\\]").replace(/#/g, "\\#").replace(/%/g, "\\%").replace(/\(/g, "\\(").replace(/\)/g, "\\)").replace(/,/g, "\\,").replace(/\+/g, "\\+");
905
1504
  }
906
1505
  function css(...classes) {
907
1506
  const result = [];
@@ -941,6 +1540,26 @@ function css(...classes) {
941
1540
  result.push(part);
942
1541
  continue;
943
1542
  }
1543
+ const bpMaxMatch = part.match(BP_MAX_RE);
1544
+ if (bpMaxMatch) {
1545
+ const [, bp, innerAtom] = bpMaxMatch;
1546
+ const pseudoInner = innerAtom.match(/^(h|f|fv|a|fw):(.+)$/);
1547
+ if (pseudoInner) {
1548
+ const [, pseudoPrefix, atomName] = pseudoInner;
1549
+ const resolved3 = resolveAtom(`_${atomName}`);
1550
+ if (resolved3) {
1551
+ injectResponsiveMaxPseudo(part, resolved3.decl, bp, PSEUDO_NAMES[pseudoPrefix]);
1552
+ }
1553
+ result.push(part);
1554
+ continue;
1555
+ }
1556
+ const resolved2 = resolveAtom(`_${innerAtom}`);
1557
+ if (resolved2) {
1558
+ injectResponsiveMax(part, resolved2.decl, bp);
1559
+ }
1560
+ result.push(part);
1561
+ continue;
1562
+ }
944
1563
  const bpMatch = part.match(BP_RE);
945
1564
  if (bpMatch) {
946
1565
  const [, bp, innerAtom] = bpMatch;
@@ -996,8 +1615,12 @@ function css(...classes) {
996
1615
  }
997
1616
  const resolved = resolveAtom(part);
998
1617
  if (resolved) {
999
- const needsEscape = /[/\[\]#%(),+]/.test(resolved.className);
1000
- inject(resolved.className, resolved.decl, needsEscape ? escapeClass(resolved.className) : void 0);
1618
+ const needsEscape = /[./[\]#%(),+]/.test(resolved.className);
1619
+ inject(
1620
+ resolved.className,
1621
+ resolved.decl,
1622
+ needsEscape ? escapeClass(resolved.className) : void 0
1623
+ );
1001
1624
  result.push(part);
1002
1625
  } else {
1003
1626
  result.push(part);
@@ -1040,6 +1663,9 @@ export {
1040
1663
  injectMediaQuery,
1041
1664
  injectPseudo,
1042
1665
  injectResponsive,
1666
+ injectResponsiveMax,
1667
+ injectResponsiveMaxPseudo,
1668
+ injectResponsivePseudo,
1043
1669
  reset,
1044
1670
  resolveAtomDecl,
1045
1671
  setAnimations,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decantr/css",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "Framework-agnostic CSS atom runtime for Decantr projects",
5
5
  "author": "Decantr AI",
6
6
  "bugs": {
@@ -27,12 +27,6 @@
27
27
  "publishConfig": {
28
28
  "access": "public"
29
29
  },
30
- "scripts": {
31
- "build": "tsup src/index.ts --format esm --dts",
32
- "test": "vitest run",
33
- "test:watch": "vitest",
34
- "lint": "tsc --noEmit"
35
- },
36
30
  "keywords": [
37
31
  "decantr",
38
32
  "css",
@@ -46,5 +40,12 @@
46
40
  "tsup": "^8.0.0",
47
41
  "typescript": "^5.0.0",
48
42
  "vitest": "^3.0.0"
43
+ },
44
+ "scripts": {
45
+ "build": "tsup src/index.ts --format esm --dts",
46
+ "test": "vitest run",
47
+ "test:watch": "vitest",
48
+ "lint": "tsc --noEmit",
49
+ "preversion": "pnpm build && pnpm test"
49
50
  }
50
- }
51
+ }