rafters 0.0.78 → 0.0.80
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/dist/index.js +947 -358
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -311,6 +311,32 @@ function toDTCG(tokens, options = {}) {
|
|
|
311
311
|
|
|
312
312
|
// ../design-tokens/src/exporters/tailwind.ts
|
|
313
313
|
var SHADOW_PART_SUFFIX = /-(offset-x|offset-y|blur|spread|color)$/;
|
|
314
|
+
var MOTION_NAMESPACE_PROPERTY = {
|
|
315
|
+
duration: "transition-duration",
|
|
316
|
+
ease: "transition-timing-function",
|
|
317
|
+
delay: "transition-delay",
|
|
318
|
+
// Extents are consumed inside transforms, so the utility publishes the chosen
|
|
319
|
+
// extent under a fixed name the consuming rule reads. The name comes from toy
|
|
320
|
+
// 9 (worktree-toy-motion-registry).
|
|
321
|
+
//
|
|
322
|
+
// THIS IS THE UTILITY-SIDE CONTRACT, and it is one of TWO (#2017). A CLASS
|
|
323
|
+
// picks an extent by naming a member (`extent-pop`) and the rule downstream
|
|
324
|
+
// reads `--rafters-consumed-extent` without knowing which member won.
|
|
325
|
+
// KEYFRAME BODIES DO NOT USE THIS ALIAS: they are generator-owned emission and
|
|
326
|
+
// reference the LEAF directly (`var(--rafters-extent-pop)`, see
|
|
327
|
+
// DEFAULT_KEYFRAME_DEFINITIONS). A shape is not a function of whatever extent
|
|
328
|
+
// the consuming class last selected. Do not merge the two contracts.
|
|
329
|
+
extent: "--rafters-consumed-extent",
|
|
330
|
+
period: "animation-duration"
|
|
331
|
+
};
|
|
332
|
+
var MOTION_NAMESPACE_NAMES = Object.keys(MOTION_NAMESPACE_PROPERTY);
|
|
333
|
+
var REDUCED_MOTION_ZEROED = /* @__PURE__ */ new Set(["duration", "delay"]);
|
|
334
|
+
var MOTION_NAMESPACE_TOKEN = new RegExp(`^rafters-(${MOTION_NAMESPACE_NAMES.join("|")})-(.+)$`);
|
|
335
|
+
function motionNamespaceParts(name) {
|
|
336
|
+
const match = MOTION_NAMESPACE_TOKEN.exec(name);
|
|
337
|
+
if (!match?.[1] || !match[2]) return null;
|
|
338
|
+
return { namespace: match[1], member: match[2] };
|
|
339
|
+
}
|
|
314
340
|
function isShadowDecomposedPart(name) {
|
|
315
341
|
return SHADOW_PART_SUFFIX.test(name);
|
|
316
342
|
}
|
|
@@ -507,7 +533,7 @@ function generateThemeBlock(groups) {
|
|
|
507
533
|
const value = tokenValueToCSS(token);
|
|
508
534
|
if (value === null) continue;
|
|
509
535
|
const key = token.name.replace(/^radius-/, "");
|
|
510
|
-
const themeValue = value.replaceAll("var(--rafters-radius-base)", "var(--radius-base)").replaceAll("var(--rafters-radius-tl)", "var(--radius-tl)").replaceAll("var(--rafters-radius-tr)", "var(--radius-tr)").replaceAll("var(--rafters-radius-bl)", "var(--radius-bl)").replaceAll("var(--rafters-radius-br)", "var(--radius-br)");
|
|
536
|
+
const themeValue = value.replaceAll("var(--rafters-spacing-base)", "var(--spacing-base)").replaceAll("var(--rafters-radius-base)", "var(--radius-base)").replaceAll("var(--rafters-radius-tl)", "var(--radius-tl)").replaceAll("var(--rafters-radius-tr)", "var(--radius-tr)").replaceAll("var(--rafters-radius-bl)", "var(--radius-bl)").replaceAll("var(--rafters-radius-br)", "var(--radius-br)");
|
|
511
537
|
lines.push(` --radius-${key}: ${themeValue};`);
|
|
512
538
|
}
|
|
513
539
|
lines.push("");
|
|
@@ -533,32 +559,26 @@ function generateThemeBlock(groups) {
|
|
|
533
559
|
}
|
|
534
560
|
lines.push("");
|
|
535
561
|
}
|
|
562
|
+
const motionNamespaceLines = generateMotionNamespaceVars(groups.motion);
|
|
563
|
+
if (motionNamespaceLines) {
|
|
564
|
+
lines.push(motionNamespaceLines);
|
|
565
|
+
lines.push("");
|
|
566
|
+
}
|
|
536
567
|
if (groups.motion.length > 0) {
|
|
537
568
|
for (const token of groups.motion) {
|
|
538
569
|
if (token.name.startsWith("motion-duration-") && token.name !== "motion-duration-base")
|
|
539
570
|
continue;
|
|
540
571
|
if (token.name.startsWith("motion-easing-")) continue;
|
|
572
|
+
if (motionNamespaceParts(token.name)) continue;
|
|
541
573
|
const value = tokenValueToCSS(token);
|
|
542
574
|
if (value === null) continue;
|
|
543
575
|
lines.push(` --${token.name}: ${value};`);
|
|
544
576
|
}
|
|
545
577
|
lines.push("");
|
|
546
578
|
}
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
const key = token.name.replace("motion-duration-", "");
|
|
551
|
-
const value = tokenValueToCSS(token);
|
|
552
|
-
if (value === null) continue;
|
|
553
|
-
lines.push(` --duration-${key}: ${value};`);
|
|
554
|
-
}
|
|
555
|
-
if (token.name.startsWith("motion-easing-")) {
|
|
556
|
-
const key = token.name.replace("motion-easing-", "");
|
|
557
|
-
const value = tokenValueToCSS(token);
|
|
558
|
-
if (value === null) continue;
|
|
559
|
-
lines.push(` --ease-${key}: ${value};`);
|
|
560
|
-
}
|
|
561
|
-
}
|
|
579
|
+
const bridgeLines = generateMotionBridgeVars(groups.motion);
|
|
580
|
+
if (bridgeLines) {
|
|
581
|
+
lines.push(bridgeLines);
|
|
562
582
|
lines.push("");
|
|
563
583
|
}
|
|
564
584
|
if (groups.breakpoint.length > 0) {
|
|
@@ -574,7 +594,8 @@ function generateThemeBlock(groups) {
|
|
|
574
594
|
for (const token of groups.focus) {
|
|
575
595
|
const value = tokenValueToCSS(token);
|
|
576
596
|
if (value === null) continue;
|
|
577
|
-
|
|
597
|
+
const themeValue = value.replaceAll("var(--rafters-spacing-base)", "var(--spacing-base)").replaceAll("var(--rafters-focus-ring-width)", "var(--focus-ring-width)");
|
|
598
|
+
lines.push(` --${token.name}: ${themeValue};`);
|
|
578
599
|
}
|
|
579
600
|
lines.push("");
|
|
580
601
|
}
|
|
@@ -594,18 +615,18 @@ function generateThemeBlock(groups) {
|
|
|
594
615
|
return lines.join("\n");
|
|
595
616
|
}
|
|
596
617
|
var ARTICLE_ELEMENT_STYLES = [
|
|
597
|
-
// Paragraphs
|
|
598
|
-
["p", "leading-relaxed mb-4"],
|
|
618
|
+
// Paragraphs -- composition for metrics, structural for spacing
|
|
619
|
+
["p", "text-body-medium ts-body-medium leading-relaxed mb-4"],
|
|
599
620
|
["p:last-child", "mb-0"],
|
|
600
|
-
// Headings
|
|
601
|
-
["h1", "text-
|
|
602
|
-
["h2", "text-
|
|
621
|
+
// Headings -- compositions carry size/weight/tracking/leading/family
|
|
622
|
+
["h1", "text-display-medium ts-display-medium mb-4 mt-0 text-accent-foreground"],
|
|
623
|
+
["h2", "text-title-large ts-title-large mb-3 mt-8 text-accent-foreground"],
|
|
603
624
|
["h2:first-child", "mt-0"],
|
|
604
|
-
["h3", "text-
|
|
605
|
-
["h4", "text-
|
|
606
|
-
["h5", "text-
|
|
607
|
-
["h6", "text-
|
|
608
|
-
// Lists
|
|
625
|
+
["h3", "text-title-medium ts-title-medium mb-2 mt-6 text-accent-foreground"],
|
|
626
|
+
["h4", "text-title-small ts-title-small mb-2 mt-4 text-accent-foreground"],
|
|
627
|
+
["h5", "text-title-small ts-title-small mb-2 mt-4 text-accent-foreground"],
|
|
628
|
+
["h6", "text-title-small ts-title-small mb-2 mt-4 text-accent-foreground"],
|
|
629
|
+
// Lists -- structural only (type metrics cascade from parent)
|
|
609
630
|
["ul", "list-disc pl-6 mb-4"],
|
|
610
631
|
["ol", "list-decimal pl-6 mb-4"],
|
|
611
632
|
["li", "mb-1"],
|
|
@@ -615,11 +636,11 @@ var ARTICLE_ELEMENT_STYLES = [
|
|
|
615
636
|
["a:hover", "text-primary/80"],
|
|
616
637
|
// Blockquotes
|
|
617
638
|
["blockquote", "border-l-4 border-muted pl-4 italic my-4"],
|
|
618
|
-
// Code
|
|
619
|
-
["code", "bg-muted px-1.5 py-0.5 rounded
|
|
620
|
-
["pre", "bg-muted p-4 rounded-lg overflow-x-auto my-4
|
|
639
|
+
// Code -- composition for metrics + family, structural for bg/padding/radius
|
|
640
|
+
["code", "text-code-small ts-code-small bg-muted px-1.5 py-0.5 rounded"],
|
|
641
|
+
["pre", "text-code-large ts-code-large bg-muted p-4 rounded-lg overflow-x-auto my-4"],
|
|
621
642
|
["pre code", "bg-transparent p-0 rounded-none text-[inherit]"],
|
|
622
|
-
["kbd", "bg-muted border border-border rounded px-1.5 py-0.5
|
|
643
|
+
["kbd", "text-code-small ts-code-small bg-muted border border-border rounded px-1.5 py-0.5"],
|
|
623
644
|
// Horizontal rules
|
|
624
645
|
["hr", "border-border my-8"],
|
|
625
646
|
// Media
|
|
@@ -627,12 +648,12 @@ var ARTICLE_ELEMENT_STYLES = [
|
|
|
627
648
|
["video", "rounded-lg my-4 max-w-full h-auto"],
|
|
628
649
|
// Tables
|
|
629
650
|
["table", "w-full my-4 border-collapse"],
|
|
630
|
-
["caption", "mt-2 text-
|
|
651
|
+
["caption", "text-label-small ts-label-small mt-2 text-muted-foreground text-left"],
|
|
631
652
|
["th", "border border-border px-3 py-2 text-left font-semibold"],
|
|
632
653
|
["td", "border border-border px-3 py-2"],
|
|
633
654
|
// Figures
|
|
634
655
|
["figure", "my-4"],
|
|
635
|
-
["figcaption", "mt-2 text-
|
|
656
|
+
["figcaption", "text-label-small ts-label-small mt-2 text-muted-foreground"],
|
|
636
657
|
// Definition lists
|
|
637
658
|
["dl", "my-4"],
|
|
638
659
|
["dt", "font-semibold mt-2"],
|
|
@@ -643,7 +664,7 @@ var ARTICLE_ELEMENT_STYLES = [
|
|
|
643
664
|
// Inline formatting
|
|
644
665
|
["strong,\n article b", "font-semibold"],
|
|
645
666
|
["mark", "bg-accent text-accent-foreground px-1 rounded"],
|
|
646
|
-
["small", "text-
|
|
667
|
+
["small", "text-label-small ts-label-small"],
|
|
647
668
|
["sub", "text-xs align-sub"],
|
|
648
669
|
["sup", "text-xs align-super"],
|
|
649
670
|
["abbr[title]", "underline decoration-dotted underline-offset-4 cursor-help"],
|
|
@@ -703,12 +724,21 @@ function generateDepthUtilities(depthTokens) {
|
|
|
703
724
|
}
|
|
704
725
|
return lines.join("\n");
|
|
705
726
|
}
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
727
|
+
var NAMED_TRACKING = {
|
|
728
|
+
tighter: "-0.05em",
|
|
729
|
+
tight: "-0.025em",
|
|
730
|
+
normal: "0em",
|
|
731
|
+
wide: "0.025em",
|
|
732
|
+
wider: "0.05em",
|
|
733
|
+
widest: "0.1em"
|
|
734
|
+
};
|
|
735
|
+
function trackingRef(key) {
|
|
736
|
+
const named = NAMED_TRACKING[key];
|
|
737
|
+
if (named !== void 0) return named;
|
|
738
|
+
return `var(--letter-spacing-${key})`;
|
|
739
|
+
}
|
|
740
|
+
function parseComposites(compositeTokens) {
|
|
741
|
+
return compositeTokens.map((t) => {
|
|
712
742
|
try {
|
|
713
743
|
const parsed = JSON.parse(t.value);
|
|
714
744
|
return { name: t.name, ...parsed };
|
|
@@ -716,40 +746,50 @@ function generateTypographyCompositeUtilities(compositeTokens) {
|
|
|
716
746
|
return null;
|
|
717
747
|
}
|
|
718
748
|
}).filter((m3) => m3 !== null);
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
if (mapping.letterSpacing in namedTrackingValues) {
|
|
734
|
-
lines.push(` letter-spacing: ${namedTrackingValues[mapping.letterSpacing]};`);
|
|
735
|
-
} else {
|
|
736
|
-
lines.push(` letter-spacing: var(--letter-spacing-${mapping.letterSpacing});`);
|
|
737
|
-
}
|
|
738
|
-
if (mapping.responsive) {
|
|
739
|
-
for (const [breakpoint, overrides] of Object.entries(mapping.responsive)) {
|
|
749
|
+
}
|
|
750
|
+
function generateTypographyCompositeThemeInline(compositeTokens) {
|
|
751
|
+
const mappings = parseComposites(compositeTokens);
|
|
752
|
+
if (mappings.length === 0) return "";
|
|
753
|
+
const lines = [];
|
|
754
|
+
lines.push("@theme inline {");
|
|
755
|
+
for (const m3 of mappings) {
|
|
756
|
+
lines.push(` --text-${m3.name}: var(--font-size-${m3.fontSize});`);
|
|
757
|
+
lines.push(` --text-${m3.name}--line-height: var(--font-size-${m3.lineHeight}--line-height);`);
|
|
758
|
+
lines.push(` --text-${m3.name}--letter-spacing: ${trackingRef(m3.letterSpacing)};`);
|
|
759
|
+
lines.push(` --text-${m3.name}--font-weight: var(--font-weight-${m3.fontWeight});`);
|
|
760
|
+
lines.push(` --rafters-ts-${m3.name}: var(--font-${m3.fontFamily});`);
|
|
761
|
+
if (m3.responsive) {
|
|
762
|
+
for (const [bp, overrides] of Object.entries(m3.responsive)) {
|
|
740
763
|
if (overrides.fontSize) {
|
|
741
|
-
|
|
742
|
-
lines.push(
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
lines.push(" }");
|
|
764
|
+
lines.push(` --rafters-ts-${m3.name}-${bp}: var(--font-size-${overrides.fontSize});`);
|
|
765
|
+
lines.push(
|
|
766
|
+
` --rafters-ts-${m3.name}-${bp}-leading: var(--font-size-${overrides.fontSize}--line-height);`
|
|
767
|
+
);
|
|
746
768
|
}
|
|
747
769
|
}
|
|
748
770
|
}
|
|
749
|
-
lines.push("
|
|
771
|
+
lines.push("");
|
|
750
772
|
}
|
|
773
|
+
lines.push("}");
|
|
751
774
|
return lines.join("\n");
|
|
752
775
|
}
|
|
776
|
+
function generateTypographyCompositeUtility(compositeTokens) {
|
|
777
|
+
if (compositeTokens.length === 0) return "";
|
|
778
|
+
return [
|
|
779
|
+
"@utility ts-* {",
|
|
780
|
+
" font-family: --value(--rafters-ts-*);",
|
|
781
|
+
" text-transform: --value(--rafters-ts-*-transform);",
|
|
782
|
+
" @container (min-width: 640px) {",
|
|
783
|
+
" font-size: --value(--rafters-ts-*-md);",
|
|
784
|
+
" line-height: --value(--rafters-ts-*-md-leading);",
|
|
785
|
+
" }",
|
|
786
|
+
" @container (min-width: 1024px) {",
|
|
787
|
+
" font-size: --value(--rafters-ts-*-lg);",
|
|
788
|
+
" line-height: --value(--rafters-ts-*-lg-leading);",
|
|
789
|
+
" }",
|
|
790
|
+
"}"
|
|
791
|
+
].join("\n");
|
|
792
|
+
}
|
|
753
793
|
function generateMotionUtilities(motionTokens) {
|
|
754
794
|
const semanticTokens = motionTokens.filter((t) => t.name.startsWith("motion-semantic-"));
|
|
755
795
|
if (semanticTokens.length === 0) {
|
|
@@ -781,6 +821,82 @@ function generateMotionUtilities(motionTokens) {
|
|
|
781
821
|
}
|
|
782
822
|
return lines.join("\n");
|
|
783
823
|
}
|
|
824
|
+
function generateMotionCellUtilities(motionTokens) {
|
|
825
|
+
const cellTokens = motionTokens.filter((t) => t.name.startsWith("motion-cell-"));
|
|
826
|
+
if (cellTokens.length === 0) return "";
|
|
827
|
+
const lines = [
|
|
828
|
+
"/* Motion cells -- one utility per animated (component, part, transition) */"
|
|
829
|
+
];
|
|
830
|
+
for (const token of cellTokens) {
|
|
831
|
+
if (typeof token.value !== "string") continue;
|
|
832
|
+
let spec = null;
|
|
833
|
+
try {
|
|
834
|
+
spec = JSON.parse(token.value);
|
|
835
|
+
} catch {
|
|
836
|
+
spec = null;
|
|
837
|
+
}
|
|
838
|
+
lines.push(`@utility ${token.name.replace("motion-cell-", "animate-")} {`);
|
|
839
|
+
if (spec === null) {
|
|
840
|
+
lines.push(` animation: ${token.value};`);
|
|
841
|
+
} else {
|
|
842
|
+
lines.push(` animation-name: ${spec.keyframe};`);
|
|
843
|
+
lines.push(` animation-duration: var(--rafters-duration-${spec.durationTier});`);
|
|
844
|
+
lines.push(` animation-timing-function: var(--rafters-ease-${spec.curve});`);
|
|
845
|
+
}
|
|
846
|
+
lines.push(" @media (prefers-reduced-motion: reduce) {");
|
|
847
|
+
lines.push(" animation-duration: 0s;");
|
|
848
|
+
lines.push(" }");
|
|
849
|
+
lines.push("}");
|
|
850
|
+
}
|
|
851
|
+
return lines.join("\n");
|
|
852
|
+
}
|
|
853
|
+
function generateMotionNamespaceVars(motionTokens) {
|
|
854
|
+
const lines = [];
|
|
855
|
+
for (const token of motionTokens) {
|
|
856
|
+
if (!motionNamespaceParts(token.name)) continue;
|
|
857
|
+
const value = tokenValueToCSS(token);
|
|
858
|
+
if (value === null) continue;
|
|
859
|
+
lines.push(` --${token.name}: ${value};`);
|
|
860
|
+
}
|
|
861
|
+
if (lines.length === 0) return "";
|
|
862
|
+
return [
|
|
863
|
+
" /* The five motion namespaces -- system leaves, the values live here */",
|
|
864
|
+
...lines
|
|
865
|
+
].join("\n");
|
|
866
|
+
}
|
|
867
|
+
function generateMotionBridgeVars(motionTokens) {
|
|
868
|
+
const lines = [];
|
|
869
|
+
for (const token of motionTokens) {
|
|
870
|
+
if (token.name.startsWith("motion-duration-") && token.name !== "motion-duration-base") {
|
|
871
|
+
const key = token.name.replace("motion-duration-", "");
|
|
872
|
+
lines.push(` --duration-${key}: var(--rafters-duration-${key});`);
|
|
873
|
+
}
|
|
874
|
+
if (token.name.startsWith("motion-easing-")) {
|
|
875
|
+
const key = token.name.replace("motion-easing-", "");
|
|
876
|
+
lines.push(` --ease-${key}: var(--rafters-ease-${key});`);
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
return lines.join("\n");
|
|
880
|
+
}
|
|
881
|
+
function generateMotionNamespaceUtilities(motionTokens) {
|
|
882
|
+
const lines = ["/* The five motion namespaces -- one utility per member */"];
|
|
883
|
+
let emitted = 0;
|
|
884
|
+
for (const token of motionTokens) {
|
|
885
|
+
const parts = motionNamespaceParts(token.name);
|
|
886
|
+
if (!parts) continue;
|
|
887
|
+
const property = MOTION_NAMESPACE_PROPERTY[parts.namespace];
|
|
888
|
+
emitted++;
|
|
889
|
+
lines.push(`@utility ${parts.namespace}-${parts.member} {`);
|
|
890
|
+
lines.push(` ${property}: var(--${token.name});`);
|
|
891
|
+
if (REDUCED_MOTION_ZEROED.has(parts.namespace)) {
|
|
892
|
+
lines.push(" @media (prefers-reduced-motion: reduce) {");
|
|
893
|
+
lines.push(` ${property}: 0ms;`);
|
|
894
|
+
lines.push(" }");
|
|
895
|
+
}
|
|
896
|
+
lines.push("}");
|
|
897
|
+
}
|
|
898
|
+
return emitted === 0 ? "" : lines.join("\n");
|
|
899
|
+
}
|
|
784
900
|
function overridePropertyToUtility(property, value) {
|
|
785
901
|
switch (property) {
|
|
786
902
|
case "fontFamily":
|
|
@@ -846,21 +962,38 @@ function tokensToTailwind(tokens, options = {}, typographyOverrides = []) {
|
|
|
846
962
|
if (keyframes) {
|
|
847
963
|
sections.push(keyframes);
|
|
848
964
|
}
|
|
849
|
-
const
|
|
850
|
-
|
|
965
|
+
const typographyThemeInline = generateTypographyCompositeThemeInline(
|
|
966
|
+
groups["typography-composite"]
|
|
967
|
+
);
|
|
968
|
+
if (typographyThemeInline) {
|
|
851
969
|
sections.push("");
|
|
852
|
-
sections.push(
|
|
970
|
+
sections.push(typographyThemeInline);
|
|
971
|
+
}
|
|
972
|
+
const typographyTsUtility = generateTypographyCompositeUtility(groups["typography-composite"]);
|
|
973
|
+
if (typographyTsUtility) {
|
|
974
|
+
sections.push("");
|
|
975
|
+
sections.push(typographyTsUtility);
|
|
853
976
|
}
|
|
854
977
|
const depthUtilities = generateDepthUtilities(groups.depth);
|
|
855
978
|
if (depthUtilities) {
|
|
856
979
|
sections.push("");
|
|
857
980
|
sections.push(depthUtilities);
|
|
858
981
|
}
|
|
982
|
+
const namespaceUtilities = generateMotionNamespaceUtilities(groups.motion);
|
|
983
|
+
if (namespaceUtilities) {
|
|
984
|
+
sections.push("");
|
|
985
|
+
sections.push(namespaceUtilities);
|
|
986
|
+
}
|
|
859
987
|
const motionUtilities = generateMotionUtilities(groups.motion);
|
|
860
988
|
if (motionUtilities) {
|
|
861
989
|
sections.push("");
|
|
862
990
|
sections.push(motionUtilities);
|
|
863
991
|
}
|
|
992
|
+
const cellUtilities = generateMotionCellUtilities(groups.motion);
|
|
993
|
+
if (cellUtilities) {
|
|
994
|
+
sections.push("");
|
|
995
|
+
sections.push(cellUtilities);
|
|
996
|
+
}
|
|
864
997
|
const overrideCSS = generateTypographyOverrideCSS(typographyOverrides);
|
|
865
998
|
if (overrideCSS) {
|
|
866
999
|
sections.push("");
|
|
@@ -882,7 +1015,7 @@ async function registryToCompiled(registry2, options = {}) {
|
|
|
882
1015
|
${sourceDirectives}
|
|
883
1016
|
${themeBody}`;
|
|
884
1017
|
const { execFileSync } = await import("child_process");
|
|
885
|
-
const { mkdtempSync, writeFileSync: writeFileSync2, readFileSync:
|
|
1018
|
+
const { mkdtempSync, writeFileSync: writeFileSync2, readFileSync: readFileSync4, rmSync } = await import("fs");
|
|
886
1019
|
const { join: join15, dirname: dirname4 } = await import("path");
|
|
887
1020
|
const { createRequire: createRequire2 } = await import("module");
|
|
888
1021
|
const require2 = createRequire2(import.meta.url);
|
|
@@ -904,7 +1037,7 @@ ${themeBody}`;
|
|
|
904
1037
|
args.push("--minify");
|
|
905
1038
|
}
|
|
906
1039
|
execFileSync("node", args, { stdio: "pipe", timeout: 3e4, cwd: pkgDir });
|
|
907
|
-
return
|
|
1040
|
+
return readFileSync4(tempOutput, "utf-8");
|
|
908
1041
|
} catch (error47) {
|
|
909
1042
|
const message = error47 instanceof Error ? error47.message : String(error47);
|
|
910
1043
|
throw new Error(`Failed to compile CSS: ${message}`);
|
|
@@ -1050,6 +1183,10 @@ function deriveCandidates(themeCSS) {
|
|
|
1050
1183
|
candidates.add(name);
|
|
1051
1184
|
} else if (name.startsWith("animate-")) {
|
|
1052
1185
|
candidates.add(name);
|
|
1186
|
+
} else if (name.startsWith("text-") && !name.includes("--")) {
|
|
1187
|
+
candidates.add(`text-${name.slice(5)}`);
|
|
1188
|
+
} else if (name.startsWith("rafters-ts-") && !name.endsWith("-transform")) {
|
|
1189
|
+
candidates.add(`ts-${name.slice(11)}`);
|
|
1053
1190
|
}
|
|
1054
1191
|
}
|
|
1055
1192
|
const base = [...candidates];
|
|
@@ -1105,8 +1242,8 @@ ${themeBody}`;
|
|
|
1105
1242
|
const args = [binPath, "-i", tempInput, "-o", tempOutput];
|
|
1106
1243
|
if (minify) args.push("--minify");
|
|
1107
1244
|
execFileSync("node", args, { stdio: "pipe", timeout: 6e4, cwd: pkgDir });
|
|
1108
|
-
const { readFileSync:
|
|
1109
|
-
const raw =
|
|
1245
|
+
const { readFileSync: readFileSync4 } = await import("fs");
|
|
1246
|
+
const raw = readFileSync4(tempOutput, "utf-8");
|
|
1110
1247
|
return postProcessDocSheet(raw);
|
|
1111
1248
|
} catch (error47) {
|
|
1112
1249
|
const message = error47 instanceof Error ? error47.message : String(error47);
|
|
@@ -1124,7 +1261,30 @@ function postProcessDocSheet(css) {
|
|
|
1124
1261
|
themeContent = themeContent.replace(/:root,:host/g, ":host");
|
|
1125
1262
|
parts.push(`:host{container-type:inline-size}${themeContent}`);
|
|
1126
1263
|
}
|
|
1127
|
-
const
|
|
1264
|
+
const propertyRe = /@property\s+--[\w-]+\s*\{[^}]*\}/g;
|
|
1265
|
+
let propMatch;
|
|
1266
|
+
while ((propMatch = propertyRe.exec(css)) !== null) {
|
|
1267
|
+
parts.push(propMatch[0]);
|
|
1268
|
+
}
|
|
1269
|
+
const keyframesRe = /@keyframes\s+[\w-]+\s*\{/g;
|
|
1270
|
+
let kfMatch;
|
|
1271
|
+
while ((kfMatch = keyframesRe.exec(css)) !== null) {
|
|
1272
|
+
const start = kfMatch.index;
|
|
1273
|
+
let depth = 0;
|
|
1274
|
+
let end = start;
|
|
1275
|
+
for (let i = start; i < css.length; i++) {
|
|
1276
|
+
if (css[i] === "{") depth++;
|
|
1277
|
+
if (css[i] === "}") {
|
|
1278
|
+
depth--;
|
|
1279
|
+
if (depth === 0) {
|
|
1280
|
+
end = i + 1;
|
|
1281
|
+
break;
|
|
1282
|
+
}
|
|
1283
|
+
}
|
|
1284
|
+
}
|
|
1285
|
+
parts.push(css.slice(start, end));
|
|
1286
|
+
}
|
|
1287
|
+
const layerRe = /@layer (base|components|utilities|properties)\{/g;
|
|
1128
1288
|
let match;
|
|
1129
1289
|
while ((match = layerRe.exec(css)) !== null) {
|
|
1130
1290
|
const start = match.index;
|
|
@@ -1140,7 +1300,14 @@ function postProcessDocSheet(css) {
|
|
|
1140
1300
|
}
|
|
1141
1301
|
}
|
|
1142
1302
|
}
|
|
1143
|
-
|
|
1303
|
+
let block = css.slice(start, end);
|
|
1304
|
+
if (match[1] === "properties") {
|
|
1305
|
+
block = block.replace(
|
|
1306
|
+
/\*\s*,\s*:?:?before\s*,\s*:?:?after\s*,\s*:?:?backdrop/g,
|
|
1307
|
+
":host,*,::before,::after"
|
|
1308
|
+
);
|
|
1309
|
+
}
|
|
1310
|
+
parts.push(block);
|
|
1144
1311
|
}
|
|
1145
1312
|
return parts.join("");
|
|
1146
1313
|
}
|
|
@@ -1306,10 +1473,12 @@ var DEFAULT_SYSTEM_CONFIG = {
|
|
|
1306
1473
|
// 1.2 ratio
|
|
1307
1474
|
fontFamily: "'Noto Sans Variable', sans-serif",
|
|
1308
1475
|
monoFontFamily: "ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospace",
|
|
1309
|
-
// Rafters aesthetic overrides
|
|
1476
|
+
// Rafters aesthetic overrides.
|
|
1477
|
+
// baseRadius and focusRingWidth have NO pin here -- they derive from
|
|
1478
|
+
// baseSpacingUnit (×1.5 and ÷2), and at base 4 the derivation already
|
|
1479
|
+
// produces 6 and 2. A pin would hide the derivation, which is the #2031
|
|
1480
|
+
// defect one layer down.
|
|
1310
1481
|
baseFontSizeOverride: 16,
|
|
1311
|
-
baseRadiusOverride: 6,
|
|
1312
|
-
focusRingWidthOverride: 2,
|
|
1313
1482
|
baseTransitionDurationOverride: 150
|
|
1314
1483
|
};
|
|
1315
1484
|
var COLOR_SCALE_POSITIONS = [
|
|
@@ -1325,42 +1494,6 @@ var COLOR_SCALE_POSITIONS = [
|
|
|
1325
1494
|
"900",
|
|
1326
1495
|
"950"
|
|
1327
1496
|
];
|
|
1328
|
-
var SPACING_SCALE = [
|
|
1329
|
-
"0",
|
|
1330
|
-
"0.5",
|
|
1331
|
-
"1",
|
|
1332
|
-
"1.5",
|
|
1333
|
-
"2",
|
|
1334
|
-
"2.5",
|
|
1335
|
-
"3",
|
|
1336
|
-
"3.5",
|
|
1337
|
-
"4",
|
|
1338
|
-
"5",
|
|
1339
|
-
"6",
|
|
1340
|
-
"7",
|
|
1341
|
-
"8",
|
|
1342
|
-
"9",
|
|
1343
|
-
"10",
|
|
1344
|
-
"11",
|
|
1345
|
-
"12",
|
|
1346
|
-
"14",
|
|
1347
|
-
"16",
|
|
1348
|
-
"20",
|
|
1349
|
-
"24",
|
|
1350
|
-
"28",
|
|
1351
|
-
"32",
|
|
1352
|
-
"36",
|
|
1353
|
-
"40",
|
|
1354
|
-
"44",
|
|
1355
|
-
"48",
|
|
1356
|
-
"52",
|
|
1357
|
-
"56",
|
|
1358
|
-
"60",
|
|
1359
|
-
"64",
|
|
1360
|
-
"72",
|
|
1361
|
-
"80",
|
|
1362
|
-
"96"
|
|
1363
|
-
];
|
|
1364
1497
|
var TYPOGRAPHY_SCALE = [
|
|
1365
1498
|
"xs",
|
|
1366
1499
|
"sm",
|
|
@@ -4468,7 +4601,7 @@ function range(color1, color2, options = {}) {
|
|
|
4468
4601
|
let [r, options2] = [color1, color2];
|
|
4469
4602
|
return range(...r.rangeArgs.colors, { ...r.rangeArgs.options, ...options2 });
|
|
4470
4603
|
}
|
|
4471
|
-
let { space, outputSpace, progression
|
|
4604
|
+
let { space, outputSpace, progression, premultiplied } = options;
|
|
4472
4605
|
color1 = getColor(color1);
|
|
4473
4606
|
color2 = getColor(color2);
|
|
4474
4607
|
color1 = clone(color1);
|
|
@@ -4502,7 +4635,7 @@ function range(color1, color2, options = {}) {
|
|
|
4502
4635
|
color2.coords = color2.coords.map((c4) => c4 * color2.alpha);
|
|
4503
4636
|
}
|
|
4504
4637
|
return Object.assign((p2) => {
|
|
4505
|
-
p2 =
|
|
4638
|
+
p2 = progression ? progression(p2) : p2;
|
|
4506
4639
|
let coords = color1.coords.map((start, i) => {
|
|
4507
4640
|
let end = color2.coords[i];
|
|
4508
4641
|
return interpolate(start, end, p2);
|
|
@@ -21891,6 +22024,8 @@ var BindingSchema = external_exports.object({
|
|
|
21891
22024
|
plugin: external_exports.string(),
|
|
21892
22025
|
input: external_exports.unknown()
|
|
21893
22026
|
});
|
|
22027
|
+
var OVERRIDE_KINDS = ["baseline", "preset", "designer"];
|
|
22028
|
+
var OverrideKindSchema = external_exports.enum(OVERRIDE_KINDS);
|
|
21894
22029
|
var TokenSchema = external_exports.object({
|
|
21895
22030
|
// Core token data
|
|
21896
22031
|
name: external_exports.string(),
|
|
@@ -21929,7 +22064,13 @@ var TokenSchema = external_exports.object({
|
|
|
21929
22064
|
// Why was this overridden
|
|
21930
22065
|
reason: external_exports.string(),
|
|
21931
22066
|
// Additional context (e.g. "Q1 marketing campaign", "accessibility audit")
|
|
21932
|
-
context: external_exports.string().optional()
|
|
22067
|
+
context: external_exports.string().optional(),
|
|
22068
|
+
// Who attributed the value. The reason string is for humans; kind is what
|
|
22069
|
+
// machines branch on (preset application skips kind === 'designer').
|
|
22070
|
+
// Optional and never defaulted: absent means the provenance is unknown,
|
|
22071
|
+
// which is the honest state of every override written before this field
|
|
22072
|
+
// existed.
|
|
22073
|
+
kind: OverrideKindSchema.optional()
|
|
21933
22074
|
}).nullable(),
|
|
21934
22075
|
// Computed value from generation rule (before any override)
|
|
21935
22076
|
// Stored so agents can see what the system WOULD produce vs what human chose
|
|
@@ -22614,7 +22755,7 @@ var DEFAULT_DURATION_DEFINITIONS = {
|
|
|
22614
22755
|
},
|
|
22615
22756
|
moderate: {
|
|
22616
22757
|
range: [200, 300],
|
|
22617
|
-
default:
|
|
22758
|
+
default: 250,
|
|
22618
22759
|
band: "communicative (~200-300ms)",
|
|
22619
22760
|
meaning: "Dropdowns, tab switches, small reveals. The communicative window: fast enough to feel responsive, slow enough for the eye to track a trajectory and build a spatial model.",
|
|
22620
22761
|
contexts: ["dropdowns", "tab-switches", "small-reveals"],
|
|
@@ -22622,7 +22763,7 @@ var DEFAULT_DURATION_DEFINITIONS = {
|
|
|
22622
22763
|
},
|
|
22623
22764
|
normal: {
|
|
22624
22765
|
range: [300, 400],
|
|
22625
|
-
default:
|
|
22766
|
+
default: 350,
|
|
22626
22767
|
band: "communicative, larger movement",
|
|
22627
22768
|
meaning: "The workhorse -- modal entrances, toggles, standard state transitions. The communicative window for larger movement.",
|
|
22628
22769
|
contexts: ["modals", "toggles", "state-changes"],
|
|
@@ -22630,7 +22771,7 @@ var DEFAULT_DURATION_DEFINITIONS = {
|
|
|
22630
22771
|
},
|
|
22631
22772
|
slow: {
|
|
22632
22773
|
range: [400, 500],
|
|
22633
|
-
default:
|
|
22774
|
+
default: 500,
|
|
22634
22775
|
band: "at the sluggish boundary",
|
|
22635
22776
|
meaning: "Sheets, page transitions, large spatial movement where the user needs orientation. At the sluggish boundary -- the ceiling for anything but full-screen spatial transitions.",
|
|
22636
22777
|
contexts: ["sheets", "page-transitions", "large-spatial-movement"],
|
|
@@ -22727,12 +22868,12 @@ var DEFAULT_KEYFRAME_DEFINITIONS = {
|
|
|
22727
22868
|
contexts: ["sidebar-close", "panel-exit"]
|
|
22728
22869
|
},
|
|
22729
22870
|
"scale-in": {
|
|
22730
|
-
css: (
|
|
22871
|
+
css: () => "from { transform: scale(var(--rafters-extent-pop)); opacity: 0; } to { transform: scale(1); opacity: 1; }",
|
|
22731
22872
|
meaning: "Scale up while fading in",
|
|
22732
22873
|
contexts: ["modal", "popover", "dialog"]
|
|
22733
22874
|
},
|
|
22734
22875
|
"scale-out": {
|
|
22735
|
-
css: (
|
|
22876
|
+
css: () => "from { transform: scale(1); opacity: 1; } to { transform: scale(var(--rafters-extent-pop)); opacity: 0; }",
|
|
22736
22877
|
meaning: "Scale down while fading out",
|
|
22737
22878
|
contexts: ["modal-exit", "popover-close"]
|
|
22738
22879
|
},
|
|
@@ -22889,6 +23030,56 @@ var DEFAULT_ANIMATION_DEFINITIONS = {
|
|
|
22889
23030
|
contexts: ["input"]
|
|
22890
23031
|
}
|
|
22891
23032
|
};
|
|
23033
|
+
var DEFAULT_MOTION_CELL_ANIMATIONS = {
|
|
23034
|
+
"dialog-content-open": {
|
|
23035
|
+
keyframe: "scale-in",
|
|
23036
|
+
tier: "normal",
|
|
23037
|
+
curve: "enter",
|
|
23038
|
+
cell: { component: "dialog", part: "content", transition: "closed -> open" },
|
|
23039
|
+
meaning: "A dialog arriving: fade + zoom from the pop extent, on the arrival curve.",
|
|
23040
|
+
contexts: ["dialog", "modal", "alert-dialog"]
|
|
23041
|
+
},
|
|
23042
|
+
"dialog-content-close": {
|
|
23043
|
+
keyframe: "scale-out",
|
|
23044
|
+
tier: "moderate",
|
|
23045
|
+
curve: "exit",
|
|
23046
|
+
cell: { component: "dialog", part: "content", transition: "open -> closed" },
|
|
23047
|
+
meaning: "A dialog leaving: fade + zoom back to the pop extent, on the departure curve.",
|
|
23048
|
+
contexts: ["dialog", "modal", "alert-dialog"]
|
|
23049
|
+
},
|
|
23050
|
+
"popover-content-open": {
|
|
23051
|
+
keyframe: "scale-in",
|
|
23052
|
+
tier: "moderate",
|
|
23053
|
+
curve: "enter",
|
|
23054
|
+
cell: { component: "popover", part: "content", transition: "closed -> open" },
|
|
23055
|
+
meaning: "A popover arriving: smaller and nearer than a dialog, so one tier quicker.",
|
|
23056
|
+
contexts: ["popover", "anchored-popup"]
|
|
23057
|
+
},
|
|
23058
|
+
"popover-content-close": {
|
|
23059
|
+
keyframe: "scale-out",
|
|
23060
|
+
tier: "fast",
|
|
23061
|
+
curve: "exit",
|
|
23062
|
+
cell: { component: "popover", part: "content", transition: "open -> closed" },
|
|
23063
|
+
meaning: "A popover leaving: the user already chose to dismiss it.",
|
|
23064
|
+
contexts: ["popover", "anchored-popup"]
|
|
23065
|
+
},
|
|
23066
|
+
"dropdown-menu-content-open": {
|
|
23067
|
+
keyframe: "scale-in",
|
|
23068
|
+
tier: "moderate",
|
|
23069
|
+
curve: "enter",
|
|
23070
|
+
cell: { component: "dropdown-menu", part: "content", transition: "closed -> open" },
|
|
23071
|
+
meaning: "A menu arriving: same anchored-popup moment as popover, declared separately.",
|
|
23072
|
+
contexts: ["dropdown-menu", "menu", "anchored-popup"]
|
|
23073
|
+
},
|
|
23074
|
+
"dropdown-menu-content-close": {
|
|
23075
|
+
keyframe: "scale-out",
|
|
23076
|
+
tier: "fast",
|
|
23077
|
+
curve: "exit",
|
|
23078
|
+
cell: { component: "dropdown-menu", part: "content", transition: "open -> closed" },
|
|
23079
|
+
meaning: "A menu leaving, after a choice or a dismissal.",
|
|
23080
|
+
contexts: ["dropdown-menu", "menu", "anchored-popup"]
|
|
23081
|
+
}
|
|
23082
|
+
};
|
|
22892
23083
|
var DEFAULT_MOTION_COMPOSITE_PRESETS = {
|
|
22893
23084
|
"motion-fade-in": {
|
|
22894
23085
|
durationTier: "fast",
|
|
@@ -22924,7 +23115,8 @@ var DEFAULT_MOTION_COMPOSITE_PRESETS = {
|
|
|
22924
23115
|
var DEFAULT_MOTION_SEMANTIC_MAPPINGS = {
|
|
22925
23116
|
hover: {
|
|
22926
23117
|
properties: ["color", "background-color", "border-color"],
|
|
22927
|
-
|
|
23118
|
+
travel: "none",
|
|
23119
|
+
band: "fast",
|
|
22928
23120
|
curve: "standard",
|
|
22929
23121
|
reducedMotion: null,
|
|
22930
23122
|
category: "interaction",
|
|
@@ -22934,7 +23126,8 @@ var DEFAULT_MOTION_SEMANTIC_MAPPINGS = {
|
|
|
22934
23126
|
},
|
|
22935
23127
|
focus: {
|
|
22936
23128
|
properties: ["box-shadow", "outline-color"],
|
|
22937
|
-
|
|
23129
|
+
travel: "none",
|
|
23130
|
+
band: "micro",
|
|
22938
23131
|
curve: "linear",
|
|
22939
23132
|
reducedMotion: null,
|
|
22940
23133
|
category: "interaction",
|
|
@@ -22944,7 +23137,8 @@ var DEFAULT_MOTION_SEMANTIC_MAPPINGS = {
|
|
|
22944
23137
|
},
|
|
22945
23138
|
press: {
|
|
22946
23139
|
properties: ["transform", "color", "background-color"],
|
|
22947
|
-
|
|
23140
|
+
travel: "none",
|
|
23141
|
+
band: "micro",
|
|
22948
23142
|
curve: "spring-snappy",
|
|
22949
23143
|
reducedMotion: { properties: ["color", "background-color"] },
|
|
22950
23144
|
category: "interaction",
|
|
@@ -22954,18 +23148,25 @@ var DEFAULT_MOTION_SEMANTIC_MAPPINGS = {
|
|
|
22954
23148
|
},
|
|
22955
23149
|
toggle: {
|
|
22956
23150
|
properties: ["color", "background-color", "transform"],
|
|
22957
|
-
|
|
22958
|
-
|
|
23151
|
+
travel: "none",
|
|
23152
|
+
band: "moderate",
|
|
23153
|
+
// `standard`, not `spring-snappy`. The 30-site study found 29 of 30 sites
|
|
23154
|
+
// carry zero overshoot curves, and the one that does is the friendly
|
|
23155
|
+
// exemplar -- spring-snappy belongs to friendly and effectively nowhere
|
|
23156
|
+
// else. Efficient is the shipped default intent and is characterised as
|
|
23157
|
+
// zero-overshoot, so a spring here contradicts the intent it ships under.
|
|
23158
|
+
// Matches the recorded ruling: an efficient toggle is crisp; friendly is
|
|
23159
|
+
// the intent that springs a switch.
|
|
23160
|
+
curve: "standard",
|
|
22959
23161
|
reducedMotion: { properties: ["color", "background-color"] },
|
|
22960
23162
|
category: "interaction",
|
|
22961
|
-
sizeReasoning: "A thumb travelling a track is a small, tracked movement -- moderate tier
|
|
23163
|
+
sizeReasoning: "A thumb travelling a track is a small, tracked movement -- moderate tier at the standard curve. Reduced motion drops the transform to a colour cross-fade.",
|
|
22962
23164
|
meaning: "Toggle/switch state change. Shows the new state.",
|
|
22963
23165
|
contexts: ["switch", "toggle", "checkbox"]
|
|
22964
23166
|
},
|
|
22965
23167
|
"dropdown-in": {
|
|
22966
23168
|
properties: ["opacity", "transform"],
|
|
22967
|
-
|
|
22968
|
-
curve: "enter",
|
|
23169
|
+
travel: "short",
|
|
22969
23170
|
reducedMotion: { properties: ["opacity"], ms: 100 },
|
|
22970
23171
|
category: "enter",
|
|
22971
23172
|
sizeReasoning: "A dropdown is small and travels a short distance -- moderate tier, one step below the modal, with the arrival curve.",
|
|
@@ -22974,8 +23175,7 @@ var DEFAULT_MOTION_SEMANTIC_MAPPINGS = {
|
|
|
22974
23175
|
},
|
|
22975
23176
|
"dropdown-out": {
|
|
22976
23177
|
properties: ["opacity", "transform"],
|
|
22977
|
-
|
|
22978
|
-
curve: "exit",
|
|
23178
|
+
travel: "short",
|
|
22979
23179
|
reducedMotion: { properties: ["opacity"], ms: 100 },
|
|
22980
23180
|
category: "exit",
|
|
22981
23181
|
sizeReasoning: "The exit of a small element -- fast tier (shorter than its moderate entrance) with the departure curve. The user already chose to dismiss it.",
|
|
@@ -22984,8 +23184,7 @@ var DEFAULT_MOTION_SEMANTIC_MAPPINGS = {
|
|
|
22984
23184
|
},
|
|
22985
23185
|
"modal-in": {
|
|
22986
23186
|
properties: ["opacity", "transform"],
|
|
22987
|
-
|
|
22988
|
-
curve: "enter",
|
|
23187
|
+
travel: "medium",
|
|
22989
23188
|
reducedMotion: { properties: ["opacity"], ms: 150 },
|
|
22990
23189
|
category: "enter",
|
|
22991
23190
|
sizeReasoning: "A modal is larger and travels farther than a dropdown -- normal tier, one step up, with the arrival curve. Size and distance produce the longer duration.",
|
|
@@ -22994,8 +23193,7 @@ var DEFAULT_MOTION_SEMANTIC_MAPPINGS = {
|
|
|
22994
23193
|
},
|
|
22995
23194
|
"modal-out": {
|
|
22996
23195
|
properties: ["opacity", "transform"],
|
|
22997
|
-
|
|
22998
|
-
curve: "exit",
|
|
23196
|
+
travel: "medium",
|
|
22999
23197
|
reducedMotion: { properties: ["opacity"], ms: 150 },
|
|
23000
23198
|
category: "exit",
|
|
23001
23199
|
sizeReasoning: "The modal exit -- moderate tier (shorter than its normal entrance) with the departure curve.",
|
|
@@ -23004,8 +23202,7 @@ var DEFAULT_MOTION_SEMANTIC_MAPPINGS = {
|
|
|
23004
23202
|
},
|
|
23005
23203
|
"sheet-in": {
|
|
23006
23204
|
properties: ["transform"],
|
|
23007
|
-
|
|
23008
|
-
curve: "spring-smooth",
|
|
23205
|
+
travel: "large",
|
|
23009
23206
|
reducedMotion: { properties: ["opacity"], ms: 250 },
|
|
23010
23207
|
category: "enter",
|
|
23011
23208
|
sizeReasoning: "A sheet is a large spatial movement -- normal tier with the physical settle of a smooth spring, because the user must track it into place. Reduced motion becomes a cross-fade.",
|
|
@@ -23014,8 +23211,7 @@ var DEFAULT_MOTION_SEMANTIC_MAPPINGS = {
|
|
|
23014
23211
|
},
|
|
23015
23212
|
"sheet-out": {
|
|
23016
23213
|
properties: ["transform"],
|
|
23017
|
-
|
|
23018
|
-
curve: "exit",
|
|
23214
|
+
travel: "large",
|
|
23019
23215
|
reducedMotion: { properties: ["opacity"], ms: 250 },
|
|
23020
23216
|
category: "exit",
|
|
23021
23217
|
sizeReasoning: "The sheet exit -- normal tier (shorter than its slow entrance) with the departure curve.",
|
|
@@ -23024,8 +23220,7 @@ var DEFAULT_MOTION_SEMANTIC_MAPPINGS = {
|
|
|
23024
23220
|
},
|
|
23025
23221
|
expand: {
|
|
23026
23222
|
properties: ["grid-template-rows", "opacity"],
|
|
23027
|
-
|
|
23028
|
-
curve: "enter",
|
|
23223
|
+
travel: "medium",
|
|
23029
23224
|
reducedMotion: { properties: ["opacity"] },
|
|
23030
23225
|
category: "enter",
|
|
23031
23226
|
sizeReasoning: "Content unfolding to its natural height -- normal tier with the arrival curve. Transitions grid-template-rows (0fr->1fr), the transitionable stand-in for height:auto. Reduced motion snaps the rows and fades opacity.",
|
|
@@ -23034,8 +23229,7 @@ var DEFAULT_MOTION_SEMANTIC_MAPPINGS = {
|
|
|
23034
23229
|
},
|
|
23035
23230
|
collapse: {
|
|
23036
23231
|
properties: ["grid-template-rows", "opacity"],
|
|
23037
|
-
|
|
23038
|
-
curve: "exit",
|
|
23232
|
+
travel: "medium",
|
|
23039
23233
|
reducedMotion: { properties: ["opacity"] },
|
|
23040
23234
|
category: "exit",
|
|
23041
23235
|
sizeReasoning: "Content folding away -- moderate tier (shorter than its normal expansion) with the departure curve. Reduced motion snaps the rows.",
|
|
@@ -23044,8 +23238,7 @@ var DEFAULT_MOTION_SEMANTIC_MAPPINGS = {
|
|
|
23044
23238
|
},
|
|
23045
23239
|
page: {
|
|
23046
23240
|
properties: ["opacity", "transform"],
|
|
23047
|
-
|
|
23048
|
-
curve: "spring-smooth",
|
|
23241
|
+
travel: "large",
|
|
23049
23242
|
reducedMotion: { properties: ["opacity"], ms: 200 },
|
|
23050
23243
|
category: "enter",
|
|
23051
23244
|
sizeReasoning: "A whole-view transition -- normal tier with the physical settle of a smooth spring, because the user reorients across a large distance.",
|
|
@@ -23053,11 +23246,95 @@ var DEFAULT_MOTION_SEMANTIC_MAPPINGS = {
|
|
|
23053
23246
|
contexts: ["page-transition", "route-change", "view-switch"]
|
|
23054
23247
|
}
|
|
23055
23248
|
};
|
|
23056
|
-
var
|
|
23057
|
-
|
|
23058
|
-
|
|
23059
|
-
|
|
23060
|
-
|
|
23249
|
+
var DEFAULT_DELAY_NAMESPACE = {
|
|
23250
|
+
"hover-intent": {
|
|
23251
|
+
value: "200ms",
|
|
23252
|
+
provenance: "observed",
|
|
23253
|
+
note: "Observed in navigation-menu, which hardcoded it before #1995 routed both it and tooltip through the runtime accessor. Observed in working code, not tuned.",
|
|
23254
|
+
meaning: "How long a pointer must rest before the system believes the hover was meant. Long enough to survive a pass-through, short enough that a deliberate hover does not feel ignored.",
|
|
23255
|
+
contexts: ["tooltip", "hover-card", "navigation-menu"]
|
|
23256
|
+
},
|
|
23257
|
+
linger: {
|
|
23258
|
+
value: "300ms",
|
|
23259
|
+
provenance: "proposed",
|
|
23260
|
+
note: "PROPOSED. The grace window before a hovered surface closes, so a diagonal cursor path to a submenu does not dismiss it.",
|
|
23261
|
+
meaning: "How long a surface stays after the pointer leaves, so a near-miss is forgiven.",
|
|
23262
|
+
contexts: ["hover-card", "navigation-menu", "submenu"]
|
|
23263
|
+
},
|
|
23264
|
+
"choreo-step": {
|
|
23265
|
+
value: "50ms",
|
|
23266
|
+
provenance: "proposed",
|
|
23267
|
+
note: "PROPOSED. The offset between two parts of ONE surface moving together (panel then its content).",
|
|
23268
|
+
meaning: "The beat between choreographed parts of a single surface.",
|
|
23269
|
+
contexts: ["modal-content", "panel-content", "sequenced-parts"]
|
|
23270
|
+
},
|
|
23271
|
+
"stagger-step": {
|
|
23272
|
+
value: "0ms",
|
|
23273
|
+
provenance: "proposed",
|
|
23274
|
+
note: "PROPOSED, and zero is a value: efficient does not stagger lists. A non-zero stagger is a character choice a designer makes, not a default.",
|
|
23275
|
+
meaning: "The per-item offset when a list animates in.",
|
|
23276
|
+
contexts: ["staggered-lists", "sequential-elements"]
|
|
23277
|
+
},
|
|
23278
|
+
skip: {
|
|
23279
|
+
value: "300ms",
|
|
23280
|
+
provenance: "proposed",
|
|
23281
|
+
note: "PROPOSED. The warm-reopen window: reopen inside it and the entrance delay is skipped, because the user is already oriented.",
|
|
23282
|
+
meaning: "How long a just-closed surface stays warm enough to reopen without ceremony.",
|
|
23283
|
+
contexts: ["tooltip-reopen", "menu-reopen"]
|
|
23284
|
+
}
|
|
23285
|
+
};
|
|
23286
|
+
var DEFAULT_EXTENT_NAMESPACE = {
|
|
23287
|
+
pop: {
|
|
23288
|
+
value: "0.95",
|
|
23289
|
+
provenance: "proposed",
|
|
23290
|
+
note: "PROPOSED. The scale a surface enters from. Close to 1 so the entrance reads as arrival rather than as a zoom.",
|
|
23291
|
+
meaning: "How far a surface scales up as it arrives.",
|
|
23292
|
+
contexts: ["modal", "popover", "dialog"]
|
|
23293
|
+
},
|
|
23294
|
+
press: {
|
|
23295
|
+
value: "0.97",
|
|
23296
|
+
provenance: "proposed",
|
|
23297
|
+
note: "PROPOSED. Depression under a press. Smaller than `pop` because the finger is the evidence -- the motion only confirms it.",
|
|
23298
|
+
meaning: "How far a control depresses when pressed.",
|
|
23299
|
+
contexts: ["button", "toggle", "press-feedback"]
|
|
23300
|
+
},
|
|
23301
|
+
draw: {
|
|
23302
|
+
value: "1",
|
|
23303
|
+
provenance: "proposed",
|
|
23304
|
+
note: "PROPOSED. The completed fraction of a drawn indicator. 1 is full travel; a value below it is a deliberately incomplete stroke.",
|
|
23305
|
+
meaning: "How far an indicator draws along its track.",
|
|
23306
|
+
contexts: ["tabs-indicator", "underline", "progress-stroke"]
|
|
23307
|
+
}
|
|
23308
|
+
};
|
|
23309
|
+
var DEFAULT_PERIOD_NAMESPACE = {
|
|
23310
|
+
spin: {
|
|
23311
|
+
value: "1s",
|
|
23312
|
+
provenance: "baseline",
|
|
23313
|
+
note: "The shipped loop period of the spin animation.",
|
|
23314
|
+
meaning: "One full rotation of a working indicator.",
|
|
23315
|
+
contexts: ["loading", "spinner", "refresh"]
|
|
23316
|
+
},
|
|
23317
|
+
pulse: {
|
|
23318
|
+
value: "2s",
|
|
23319
|
+
provenance: "baseline",
|
|
23320
|
+
note: "The shipped loop period of the pulse animation.",
|
|
23321
|
+
meaning: "One breath of a skeleton or placeholder.",
|
|
23322
|
+
contexts: ["skeleton", "loading-placeholder"]
|
|
23323
|
+
},
|
|
23324
|
+
blink: {
|
|
23325
|
+
value: "1.25s",
|
|
23326
|
+
provenance: "baseline",
|
|
23327
|
+
note: "The shipped loop period of the caret-blink animation.",
|
|
23328
|
+
meaning: "One blink of a text caret.",
|
|
23329
|
+
contexts: ["input-caret", "text-cursor"]
|
|
23330
|
+
},
|
|
23331
|
+
shimmer: {
|
|
23332
|
+
value: "2s",
|
|
23333
|
+
provenance: "proposed",
|
|
23334
|
+
note: "PROPOSED. No shimmer animation ships yet; the period is here because the namespace is a vocabulary, not a list of what happens to exist.",
|
|
23335
|
+
meaning: "One sweep of a shimmer across a loading surface.",
|
|
23336
|
+
contexts: ["skeleton", "loading-placeholder"]
|
|
23337
|
+
}
|
|
23061
23338
|
};
|
|
23062
23339
|
var DEFAULT_FOCUS_CONFIGS = {
|
|
23063
23340
|
default: {
|
|
@@ -23136,41 +23413,13 @@ var DEFAULT_RADIUS_DEFINITIONS = {
|
|
|
23136
23413
|
contexts: ["avatars", "pill-buttons", "circular-elements"]
|
|
23137
23414
|
}
|
|
23138
23415
|
};
|
|
23139
|
-
var
|
|
23140
|
-
|
|
23141
|
-
|
|
23142
|
-
|
|
23143
|
-
|
|
23144
|
-
|
|
23145
|
-
|
|
23146
|
-
"3": 3,
|
|
23147
|
-
"3.5": 3.5,
|
|
23148
|
-
"4": 4,
|
|
23149
|
-
"5": 5,
|
|
23150
|
-
"6": 6,
|
|
23151
|
-
"7": 7,
|
|
23152
|
-
"8": 8,
|
|
23153
|
-
"9": 9,
|
|
23154
|
-
"10": 10,
|
|
23155
|
-
"11": 11,
|
|
23156
|
-
"12": 12,
|
|
23157
|
-
"14": 14,
|
|
23158
|
-
"16": 16,
|
|
23159
|
-
"20": 20,
|
|
23160
|
-
"24": 24,
|
|
23161
|
-
"28": 28,
|
|
23162
|
-
"32": 32,
|
|
23163
|
-
"36": 36,
|
|
23164
|
-
"40": 40,
|
|
23165
|
-
"44": 44,
|
|
23166
|
-
"48": 48,
|
|
23167
|
-
"52": 52,
|
|
23168
|
-
"56": 56,
|
|
23169
|
-
"60": 60,
|
|
23170
|
-
"64": 64,
|
|
23171
|
-
"72": 72,
|
|
23172
|
-
"80": 80,
|
|
23173
|
-
"96": 96
|
|
23416
|
+
var DEFAULT_SPACING_BOUNDS = {
|
|
23417
|
+
floor: 1,
|
|
23418
|
+
ceiling: 96
|
|
23419
|
+
};
|
|
23420
|
+
var DEFAULT_SHADOW_BOUNDS = {
|
|
23421
|
+
floor: 1,
|
|
23422
|
+
ceiling: 96
|
|
23174
23423
|
};
|
|
23175
23424
|
var DEFAULT_TYPOGRAPHY_SCALE = {
|
|
23176
23425
|
xs: { step: -2, lineHeight: 1.5, letterSpacing: "0.025em" },
|
|
@@ -25272,25 +25521,23 @@ function generateDepthTokens(_config, depthDefs) {
|
|
|
25272
25521
|
}
|
|
25273
25522
|
|
|
25274
25523
|
// ../design-tokens/src/generators/focus.ts
|
|
25275
|
-
function pxToRem(px) {
|
|
25276
|
-
const rem = Math.round(px / 16 * 1e3) / 1e3;
|
|
25277
|
-
return `${rem}rem`;
|
|
25278
|
-
}
|
|
25279
25524
|
function generateFocusTokens(config2, focusConfigs) {
|
|
25280
25525
|
const tokens = [];
|
|
25281
25526
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
25282
|
-
const { focusRingWidth } = config2;
|
|
25283
|
-
const
|
|
25527
|
+
const { focusRingWidth, baseSpacingUnit } = config2;
|
|
25528
|
+
const focusDivisor = focusRingWidth > 0 ? Math.round(baseSpacingUnit / focusRingWidth * 1e3) / 1e3 : 2;
|
|
25529
|
+
const focusWidthValue = `calc(var(--rafters-spacing-base) / ${focusDivisor})`;
|
|
25284
25530
|
tokens.push({
|
|
25285
25531
|
name: "focus-ring-width",
|
|
25286
|
-
value:
|
|
25532
|
+
value: focusWidthValue,
|
|
25287
25533
|
category: "focus",
|
|
25288
25534
|
namespace: "focus",
|
|
25289
|
-
semanticMeaning: "Default focus ring width -
|
|
25535
|
+
semanticMeaning: "Default focus ring width - derives from spacing base",
|
|
25290
25536
|
usageContext: ["focus-indicators", "keyboard-navigation"],
|
|
25291
25537
|
accessibilityLevel: "AA",
|
|
25292
|
-
focusRingWidth:
|
|
25293
|
-
|
|
25538
|
+
focusRingWidth: focusWidthValue,
|
|
25539
|
+
dependsOn: ["spacing-base"],
|
|
25540
|
+
description: `Focus ring width = spacing-base / ${focusDivisor} (${focusRingWidth}px at base ${baseSpacingUnit}). WCAG 2.2 requires minimum 2px.`,
|
|
25294
25541
|
generatedAt: timestamp,
|
|
25295
25542
|
containerQueryAware: false,
|
|
25296
25543
|
userOverride: null,
|
|
@@ -25314,14 +25561,22 @@ function generateFocusTokens(config2, focusConfigs) {
|
|
|
25314
25561
|
highContrastMode: "Highlight",
|
|
25315
25562
|
userOverride: null
|
|
25316
25563
|
});
|
|
25564
|
+
const focusVar = "var(--rafters-focus-ring-width)";
|
|
25565
|
+
const focusCalc = (px) => {
|
|
25566
|
+
const mult = px / focusRingWidth;
|
|
25567
|
+
if (mult === 0) return "0";
|
|
25568
|
+
if (mult === 1) return focusVar;
|
|
25569
|
+
if (mult === -1) return `calc(${focusVar} * -1)`;
|
|
25570
|
+
return `calc(${focusVar} * ${mult})`;
|
|
25571
|
+
};
|
|
25317
25572
|
for (const [name, focusConfig] of Object.entries(focusConfigs)) {
|
|
25318
|
-
const
|
|
25319
|
-
const
|
|
25573
|
+
const widthVal = focusCalc(focusConfig.width);
|
|
25574
|
+
const offsetVal = focusCalc(focusConfig.offset);
|
|
25320
25575
|
tokens.push({
|
|
25321
25576
|
name: name === "default" ? "focus-ring" : `focus-ring-${name}`,
|
|
25322
25577
|
value: JSON.stringify({
|
|
25323
|
-
width:
|
|
25324
|
-
offset:
|
|
25578
|
+
width: widthVal,
|
|
25579
|
+
offset: offsetVal,
|
|
25325
25580
|
style: focusConfig.style,
|
|
25326
25581
|
color: "var(--ring)"
|
|
25327
25582
|
}),
|
|
@@ -25329,13 +25584,13 @@ function generateFocusTokens(config2, focusConfigs) {
|
|
|
25329
25584
|
namespace: "focus",
|
|
25330
25585
|
semanticMeaning: focusConfig.meaning,
|
|
25331
25586
|
usageContext: focusConfig.contexts,
|
|
25332
|
-
focusRingWidth:
|
|
25587
|
+
focusRingWidth: widthVal,
|
|
25333
25588
|
focusRingColor: "var(--ring)",
|
|
25334
|
-
focusRingOffset:
|
|
25589
|
+
focusRingOffset: offsetVal,
|
|
25335
25590
|
focusRingStyle: focusConfig.style,
|
|
25336
25591
|
dependsOn: ["ring", "focus-ring-width"],
|
|
25337
25592
|
accessibilityLevel: focusConfig.width >= 2 ? "AA" : void 0,
|
|
25338
|
-
description: `${focusConfig.meaning}. Width: ${
|
|
25593
|
+
description: `${focusConfig.meaning}. Width: ${widthVal}, Offset: ${offsetVal}.`,
|
|
25339
25594
|
generatedAt: timestamp,
|
|
25340
25595
|
containerQueryAware: false,
|
|
25341
25596
|
highContrastMode: "Highlight",
|
|
@@ -25348,7 +25603,7 @@ function generateFocusTokens(config2, focusConfigs) {
|
|
|
25348
25603
|
]
|
|
25349
25604
|
}
|
|
25350
25605
|
});
|
|
25351
|
-
const outlineValue = `${
|
|
25606
|
+
const outlineValue = `${widthVal} ${focusConfig.style} var(--ring)`;
|
|
25352
25607
|
tokens.push({
|
|
25353
25608
|
name: name === "default" ? "focus-outline" : `focus-outline-${name}`,
|
|
25354
25609
|
value: outlineValue,
|
|
@@ -25356,20 +25611,21 @@ function generateFocusTokens(config2, focusConfigs) {
|
|
|
25356
25611
|
namespace: "focus",
|
|
25357
25612
|
semanticMeaning: `CSS outline shorthand for ${name} focus ring`,
|
|
25358
25613
|
usageContext: ["css-outline-property"],
|
|
25359
|
-
dependsOn: ["ring"],
|
|
25360
|
-
description: `CSS outline value: ${outlineValue}. Use with outline-offset: ${
|
|
25614
|
+
dependsOn: ["ring", "focus-ring-width"],
|
|
25615
|
+
description: `CSS outline value: ${outlineValue}. Use with outline-offset: ${offsetVal}.`,
|
|
25361
25616
|
generatedAt: timestamp,
|
|
25362
25617
|
containerQueryAware: false,
|
|
25363
25618
|
userOverride: null
|
|
25364
25619
|
});
|
|
25365
25620
|
tokens.push({
|
|
25366
25621
|
name: name === "default" ? "focus-offset" : `focus-offset-${name}`,
|
|
25367
|
-
value:
|
|
25622
|
+
value: offsetVal,
|
|
25368
25623
|
category: "focus",
|
|
25369
25624
|
namespace: "focus",
|
|
25370
25625
|
semanticMeaning: `Focus ring offset for ${name} style`,
|
|
25371
|
-
focusRingOffset:
|
|
25372
|
-
|
|
25626
|
+
focusRingOffset: offsetVal,
|
|
25627
|
+
dependsOn: ["focus-ring-width"],
|
|
25628
|
+
description: `Focus offset ${offsetVal} for ${name} focus style.`,
|
|
25373
25629
|
generatedAt: timestamp,
|
|
25374
25630
|
containerQueryAware: false,
|
|
25375
25631
|
userOverride: null
|
|
@@ -25378,7 +25634,7 @@ function generateFocusTokens(config2, focusConfigs) {
|
|
|
25378
25634
|
tokens.push({
|
|
25379
25635
|
name: "focus-within-ring",
|
|
25380
25636
|
value: JSON.stringify({
|
|
25381
|
-
width:
|
|
25637
|
+
width: focusVar,
|
|
25382
25638
|
offset: "0",
|
|
25383
25639
|
style: "solid",
|
|
25384
25640
|
color: "var(--ring)"
|
|
@@ -25387,11 +25643,11 @@ function generateFocusTokens(config2, focusConfigs) {
|
|
|
25387
25643
|
namespace: "focus",
|
|
25388
25644
|
semanticMeaning: "Focus ring for containers with focused descendants",
|
|
25389
25645
|
usageContext: ["form-groups", "card-actions", "list-containers"],
|
|
25390
|
-
focusRingWidth:
|
|
25646
|
+
focusRingWidth: focusVar,
|
|
25391
25647
|
focusRingColor: "var(--ring)",
|
|
25392
25648
|
focusRingOffset: "0",
|
|
25393
25649
|
focusRingStyle: "solid",
|
|
25394
|
-
dependsOn: ["ring"],
|
|
25650
|
+
dependsOn: ["ring", "focus-ring-width"],
|
|
25395
25651
|
description: "Focus indicator for containers using :focus-within pseudo-class.",
|
|
25396
25652
|
generatedAt: timestamp,
|
|
25397
25653
|
containerQueryAware: false,
|
|
@@ -25401,13 +25657,13 @@ function generateFocusTokens(config2, focusConfigs) {
|
|
|
25401
25657
|
never: ["Use as replacement for child focus indicators", "Apply to non-container elements"]
|
|
25402
25658
|
}
|
|
25403
25659
|
});
|
|
25404
|
-
const
|
|
25405
|
-
const
|
|
25660
|
+
const hcWidthVal = `calc(${focusVar} * 1.5)`;
|
|
25661
|
+
const hcOffsetVal = focusVar;
|
|
25406
25662
|
tokens.push({
|
|
25407
25663
|
name: "focus-high-contrast",
|
|
25408
25664
|
value: JSON.stringify({
|
|
25409
|
-
width:
|
|
25410
|
-
offset:
|
|
25665
|
+
width: hcWidthVal,
|
|
25666
|
+
offset: hcOffsetVal,
|
|
25411
25667
|
style: "solid",
|
|
25412
25668
|
color: "Highlight"
|
|
25413
25669
|
}),
|
|
@@ -25415,10 +25671,11 @@ function generateFocusTokens(config2, focusConfigs) {
|
|
|
25415
25671
|
namespace: "focus",
|
|
25416
25672
|
semanticMeaning: "Focus ring for Windows High Contrast Mode",
|
|
25417
25673
|
usageContext: ["high-contrast-mode", "forced-colors"],
|
|
25418
|
-
focusRingWidth:
|
|
25419
|
-
focusRingOffset:
|
|
25674
|
+
focusRingWidth: hcWidthVal,
|
|
25675
|
+
focusRingOffset: hcOffsetVal,
|
|
25420
25676
|
focusRingStyle: "solid",
|
|
25421
25677
|
highContrastMode: "Highlight",
|
|
25678
|
+
dependsOn: ["focus-ring-width"],
|
|
25422
25679
|
description: "High contrast focus ring using system Highlight color.",
|
|
25423
25680
|
generatedAt: timestamp,
|
|
25424
25681
|
containerQueryAware: false,
|
|
@@ -25598,21 +25855,6 @@ function evaluateExpression(expression, options = {}) {
|
|
|
25598
25855
|
}
|
|
25599
25856
|
|
|
25600
25857
|
// ../math-utils/src/progressions.ts
|
|
25601
|
-
var progression = (r, base, step) => base * ratioValue(r) ** step;
|
|
25602
|
-
function generateSequence(r, base, count, options = {}) {
|
|
25603
|
-
const { startStep = 0, includeZero = false } = options;
|
|
25604
|
-
const ratio = ratioValue(r);
|
|
25605
|
-
const result = [];
|
|
25606
|
-
for (let i = 0; i < count; i++) {
|
|
25607
|
-
if (i === 0 && includeZero) {
|
|
25608
|
-
result.push(0);
|
|
25609
|
-
} else {
|
|
25610
|
-
const step = startStep + (includeZero ? i - 1 : i);
|
|
25611
|
-
result.push(base * ratio ** step);
|
|
25612
|
-
}
|
|
25613
|
-
}
|
|
25614
|
-
return result;
|
|
25615
|
-
}
|
|
25616
25858
|
function generateModularScale(r, base, steps2 = 5) {
|
|
25617
25859
|
const ratio = ratioValue(r);
|
|
25618
25860
|
const smaller = [];
|
|
@@ -25674,23 +25916,123 @@ function tryParseUnit(cssValue, registry2 = DEFAULT_UNITS) {
|
|
|
25674
25916
|
}
|
|
25675
25917
|
}
|
|
25676
25918
|
|
|
25919
|
+
// ../design-tokens/src/generators/motion-derivation.ts
|
|
25920
|
+
var BAND_ORDER = ["instant", "micro", "fast", "moderate", "normal", "slow"];
|
|
25921
|
+
var TRAVEL_BAND = {
|
|
25922
|
+
none: "fast",
|
|
25923
|
+
short: "moderate",
|
|
25924
|
+
medium: "normal",
|
|
25925
|
+
large: "slow"
|
|
25926
|
+
};
|
|
25927
|
+
var LARGE_TRAVEL_DISAGREEMENT = {
|
|
25928
|
+
derived: "slow",
|
|
25929
|
+
shipped: "normal",
|
|
25930
|
+
reason: "b864de01 places the sheet pair at normal deliberately -- the one pair without a shortened exit. Unresolved: either the model needs a term that justifies normal, or these move to slow."
|
|
25931
|
+
};
|
|
25932
|
+
function applyLargeTravelException(band, travel) {
|
|
25933
|
+
return travel === "large" ? LARGE_TRAVEL_DISAGREEMENT.shipped : band;
|
|
25934
|
+
}
|
|
25935
|
+
function shortenForExit(band) {
|
|
25936
|
+
const i = BAND_ORDER.indexOf(band);
|
|
25937
|
+
return BAND_ORDER[Math.max(0, i - 1)];
|
|
25938
|
+
}
|
|
25939
|
+
var INTENT_POSITION = {
|
|
25940
|
+
efficient: null,
|
|
25941
|
+
elegant: 1,
|
|
25942
|
+
friendly: null,
|
|
25943
|
+
technical: null,
|
|
25944
|
+
editorial: null
|
|
25945
|
+
};
|
|
25946
|
+
var LANDMARK_BANDS = /* @__PURE__ */ new Set(["instant", "micro", "fast"]);
|
|
25947
|
+
function deriveDuration(band, intent, durationDefs) {
|
|
25948
|
+
const def = durationDefs[band];
|
|
25949
|
+
if (def === void 0) {
|
|
25950
|
+
throw new Error(
|
|
25951
|
+
`motion derivation: unknown band "${band}". Known bands: ${BAND_ORDER.join(", ")}.`
|
|
25952
|
+
);
|
|
25953
|
+
}
|
|
25954
|
+
if (LANDMARK_BANDS.has(band)) return def.default;
|
|
25955
|
+
const position = INTENT_POSITION[intent];
|
|
25956
|
+
if (position === null) return def.default;
|
|
25957
|
+
const [min, max2] = def.range;
|
|
25958
|
+
return Math.round(min + (max2 - min) * position);
|
|
25959
|
+
}
|
|
25960
|
+
function deriveBand(category, travel, declaredBand) {
|
|
25961
|
+
if (category === "interaction") {
|
|
25962
|
+
if (declaredBand === void 0) {
|
|
25963
|
+
throw new Error(
|
|
25964
|
+
"motion derivation: an interaction mapping must declare its band -- it has no travel to derive from."
|
|
25965
|
+
);
|
|
25966
|
+
}
|
|
25967
|
+
return declaredBand;
|
|
25968
|
+
}
|
|
25969
|
+
const base = applyLargeTravelException(TRAVEL_BAND[travel], travel);
|
|
25970
|
+
if (category === "exit" && travel !== "large") return shortenForExit(base);
|
|
25971
|
+
return base;
|
|
25972
|
+
}
|
|
25973
|
+
function deriveCurve(category, travel, _intent, declaredCurve) {
|
|
25974
|
+
if (category === "exit") return "exit";
|
|
25975
|
+
if (category === "enter") return travel === "large" ? "spring-smooth" : "enter";
|
|
25976
|
+
return declaredCurve ?? "standard";
|
|
25977
|
+
}
|
|
25978
|
+
|
|
25677
25979
|
// ../design-tokens/src/generators/motion.ts
|
|
25678
|
-
function
|
|
25980
|
+
function requireDef(defs, key, kind, owner) {
|
|
25981
|
+
const def = defs[key];
|
|
25982
|
+
if (def === void 0) {
|
|
25983
|
+
throw new Error(
|
|
25984
|
+
`motion generator: ${owner} references unknown ${kind} "${key}". Known ${kind}s: ${Object.keys(defs).sort().join(", ")}.`
|
|
25985
|
+
);
|
|
25986
|
+
}
|
|
25987
|
+
return def;
|
|
25988
|
+
}
|
|
25989
|
+
function motionNamespaceTokenName(namespace, member) {
|
|
25990
|
+
return `rafters-${namespace}-${member}`;
|
|
25991
|
+
}
|
|
25992
|
+
function namespaceLeaf(input) {
|
|
25993
|
+
const { namespaceName, member, value, provenance, note, meaning, contexts, timestamp } = input;
|
|
25994
|
+
return {
|
|
25995
|
+
name: motionNamespaceTokenName(namespaceName, member),
|
|
25996
|
+
value,
|
|
25997
|
+
category: "motion",
|
|
25998
|
+
namespace: "motion",
|
|
25999
|
+
semanticMeaning: meaning,
|
|
26000
|
+
usageContext: contexts,
|
|
26001
|
+
dependsOn: [],
|
|
26002
|
+
description: `${namespaceName}-${member}: ${value} [provenance: ${provenance}] ${note} ${meaning}`,
|
|
26003
|
+
generatedAt: timestamp,
|
|
26004
|
+
containerQueryAware: false,
|
|
26005
|
+
// Mirrors the exporter's REDUCED_MOTION_ZEROED set: only duration and delay
|
|
26006
|
+
// are zeroed under prefers-reduced-motion. ease/extent are shaped BY a
|
|
26007
|
+
// duration, not zeroed themselves; period is exempt by law (loops slow,
|
|
26008
|
+
// never stop).
|
|
26009
|
+
reducedMotionAware: namespaceName === "duration" || namespaceName === "delay",
|
|
26010
|
+
userOverride: null,
|
|
26011
|
+
usagePatterns: {
|
|
26012
|
+
do: [`Use the generated utility \`${namespaceName}-${member}\``],
|
|
26013
|
+
never: [
|
|
26014
|
+
"Hardcode this value in a component",
|
|
26015
|
+
"Add a second name for the same idea -- one fast, everywhere, always"
|
|
26016
|
+
]
|
|
26017
|
+
}
|
|
26018
|
+
};
|
|
26019
|
+
}
|
|
26020
|
+
function generateMotionTokens(config2, durationDefs, easingDefs, delayDefs, extentDefs, periodDefs, semanticMappings, keyframeDefs, animationDefs, compositePresets, cellAnimations) {
|
|
25679
26021
|
const tokens = [];
|
|
25680
26022
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
25681
26023
|
const { baseTransitionDuration, progressionRatio } = config2;
|
|
26024
|
+
const intent = config2.intent ?? "efficient";
|
|
25682
26025
|
const ratio = resolveRatio(progressionRatio);
|
|
25683
26026
|
const ratioVal = ratioValue(ratio);
|
|
25684
|
-
const computeStep = (base, step) => progression(ratio, base, step);
|
|
25685
26027
|
tokens.push({
|
|
25686
26028
|
name: "motion-duration-base",
|
|
25687
26029
|
value: `${baseTransitionDuration}ms`,
|
|
25688
26030
|
category: "motion",
|
|
25689
26031
|
namespace: "motion",
|
|
25690
|
-
semanticMeaning: "Legacy base transition duration.
|
|
25691
|
-
usageContext: ["calculation-reference"
|
|
26032
|
+
semanticMeaning: "Legacy base transition duration. Nothing derives from this any more: the perceptual duration scale never did, and the ratio-stepped delay tokens that did were removed in #1991. Retained as a reference value only.",
|
|
26033
|
+
usageContext: ["calculation-reference"],
|
|
25692
26034
|
progressionSystem: progressionRatio,
|
|
25693
|
-
description: `Base duration (${baseTransitionDuration}ms).
|
|
26035
|
+
description: `Base duration (${baseTransitionDuration}ms). A reference value with no dependents: duration tiers are perceptual RANGES a designer sets within, and the delay namespace holds relationships rather than ratio steps.`,
|
|
25694
26036
|
generatedAt: timestamp,
|
|
25695
26037
|
containerQueryAware: false,
|
|
25696
26038
|
reducedMotionAware: true,
|
|
@@ -25706,7 +26048,7 @@ function generateMotionTokens(config2, durationDefs, easingDefs, delayDefs, sema
|
|
|
25706
26048
|
const def = durationDefs[scale2];
|
|
25707
26049
|
if (!def) continue;
|
|
25708
26050
|
const scaleIndex = MOTION_DURATION_SCALE.indexOf(scale2);
|
|
25709
|
-
const durationMs =
|
|
26051
|
+
const durationMs = deriveDuration(scale2, intent, durationDefs);
|
|
25710
26052
|
const [rangeMin, rangeMax] = def.range;
|
|
25711
26053
|
const bandNote = def.band ? ` Band: ${def.band}.` : "";
|
|
25712
26054
|
const rangeNote = rangeMin === rangeMax ? " Fixed." : ` Range: ${rangeMin}-${rangeMax}ms.`;
|
|
@@ -25759,40 +26101,64 @@ function generateMotionTokens(config2, durationDefs, easingDefs, delayDefs, sema
|
|
|
25759
26101
|
}
|
|
25760
26102
|
});
|
|
25761
26103
|
}
|
|
25762
|
-
for (const
|
|
25763
|
-
|
|
25764
|
-
|
|
25765
|
-
|
|
25766
|
-
|
|
25767
|
-
|
|
25768
|
-
|
|
25769
|
-
|
|
25770
|
-
|
|
26104
|
+
for (const scale2 of MOTION_DURATION_SCALE) {
|
|
26105
|
+
const def = durationDefs[scale2];
|
|
26106
|
+
if (!def) continue;
|
|
26107
|
+
const durationMs = deriveDuration(scale2, intent, durationDefs);
|
|
26108
|
+
tokens.push(
|
|
26109
|
+
namespaceLeaf({
|
|
26110
|
+
namespaceName: "duration",
|
|
26111
|
+
member: scale2,
|
|
26112
|
+
value: `${durationMs}ms`,
|
|
26113
|
+
provenance: "baseline",
|
|
26114
|
+
note: def.band ? `Efficient baseline. ${durationMs}ms within the ${def.band} band (${def.range[0]}-${def.range[1]}ms).` : `Efficient baseline. Fixed at ${durationMs}ms.`,
|
|
26115
|
+
meaning: def.meaning,
|
|
26116
|
+
contexts: def.contexts,
|
|
26117
|
+
timestamp
|
|
26118
|
+
})
|
|
26119
|
+
);
|
|
26120
|
+
}
|
|
26121
|
+
for (const curve of EASING_CURVES) {
|
|
26122
|
+
const def = easingDefs[curve];
|
|
26123
|
+
if (!def) continue;
|
|
26124
|
+
tokens.push(
|
|
26125
|
+
namespaceLeaf({
|
|
26126
|
+
namespaceName: "ease",
|
|
26127
|
+
member: curve,
|
|
26128
|
+
value: def.css,
|
|
26129
|
+
provenance: "baseline",
|
|
26130
|
+
note: "Efficient baseline curve.",
|
|
26131
|
+
meaning: def.meaning,
|
|
26132
|
+
contexts: def.contexts,
|
|
26133
|
+
timestamp
|
|
26134
|
+
})
|
|
26135
|
+
);
|
|
26136
|
+
}
|
|
26137
|
+
for (const [namespaceName, members] of [
|
|
26138
|
+
["delay", delayDefs],
|
|
26139
|
+
["extent", extentDefs],
|
|
26140
|
+
["period", periodDefs]
|
|
26141
|
+
]) {
|
|
26142
|
+
for (const [member, def] of Object.entries(members)) {
|
|
26143
|
+
tokens.push(
|
|
26144
|
+
namespaceLeaf({
|
|
26145
|
+
namespaceName,
|
|
26146
|
+
member,
|
|
26147
|
+
value: def.value,
|
|
26148
|
+
provenance: def.provenance,
|
|
26149
|
+
note: def.note,
|
|
26150
|
+
meaning: def.meaning,
|
|
26151
|
+
contexts: def.contexts,
|
|
26152
|
+
timestamp
|
|
26153
|
+
})
|
|
26154
|
+
);
|
|
25771
26155
|
}
|
|
25772
|
-
tokens.push({
|
|
25773
|
-
name: `motion-delay-${name}`,
|
|
25774
|
-
value: delayMs === 0 ? "0ms" : `${delayMs}ms`,
|
|
25775
|
-
category: "motion",
|
|
25776
|
-
namespace: "motion",
|
|
25777
|
-
semanticMeaning: `${name.charAt(0).toUpperCase() + name.slice(1)} animation delay`,
|
|
25778
|
-
usageContext: name === "none" ? ["immediate-response"] : name === "short" ? ["staggered-lists", "sequential-elements"] : name === "medium" ? ["modal-content", "after-transition"] : ["emphasis", "dramatic-reveals"],
|
|
25779
|
-
delayMs,
|
|
25780
|
-
mathRelationship,
|
|
25781
|
-
dependsOn: def.step === "none" ? [] : ["motion-duration-base"],
|
|
25782
|
-
description: `Delay ${name}: ${delayMs}ms. Based on duration progression.`,
|
|
25783
|
-
generatedAt: timestamp,
|
|
25784
|
-
containerQueryAware: false,
|
|
25785
|
-
reducedMotionAware: true,
|
|
25786
|
-
userOverride: null
|
|
25787
|
-
});
|
|
25788
26156
|
}
|
|
25789
26157
|
const ratioValue2 = ratioVal;
|
|
25790
|
-
const scaleStart = Math.round(1 / ratioValue2 ** 0.25 * 100) / 100;
|
|
25791
26158
|
const pingScale = Math.round(ratioValue2 ** 3 * 10) / 10;
|
|
25792
26159
|
const pulseOpacity = Math.round(1 / ratioValue2 ** 4 * 100) / 100;
|
|
25793
26160
|
const bouncePercent = Math.round(100 / ratioValue2 ** 6);
|
|
25794
26161
|
const keyframeContext = {
|
|
25795
|
-
scaleStart,
|
|
25796
26162
|
pingScale,
|
|
25797
26163
|
pulseOpacity,
|
|
25798
26164
|
bouncePercent
|
|
@@ -25822,15 +26188,18 @@ function generateMotionTokens(config2, durationDefs, easingDefs, delayDefs, sema
|
|
|
25822
26188
|
durationRef = anim.duration.loopPeriod;
|
|
25823
26189
|
durationDependency = [];
|
|
25824
26190
|
} else {
|
|
25825
|
-
const durationDef =
|
|
25826
|
-
|
|
26191
|
+
const durationDef = requireDef(
|
|
26192
|
+
durationDefs,
|
|
26193
|
+
anim.duration.tier,
|
|
26194
|
+
"duration tier",
|
|
26195
|
+
`animation "${name}"`
|
|
26196
|
+
);
|
|
25827
26197
|
durationValue = `${durationDef.default}ms`;
|
|
25828
|
-
durationRef = `var(--
|
|
25829
|
-
durationDependency = [`
|
|
26198
|
+
durationRef = `var(--rafters-duration-${anim.duration.tier})`;
|
|
26199
|
+
durationDependency = [`rafters-duration-${anim.duration.tier}`];
|
|
25830
26200
|
}
|
|
25831
|
-
const easingDef = easingDefs
|
|
25832
|
-
|
|
25833
|
-
const easingRef = `var(--motion-easing-${anim.curve})`;
|
|
26201
|
+
const easingDef = requireDef(easingDefs, anim.curve, "easing curve", `animation "${name}"`);
|
|
26202
|
+
const easingRef = `var(--rafters-ease-${anim.curve})`;
|
|
25834
26203
|
const iterations = anim.iterations || "";
|
|
25835
26204
|
const animValue = iterations ? `${anim.keyframe} ${durationRef} ${easingRef} ${iterations}` : `${anim.keyframe} ${durationRef} ${easingRef}`;
|
|
25836
26205
|
tokens.push({
|
|
@@ -25848,7 +26217,7 @@ function generateMotionTokens(config2, durationDefs, easingDefs, delayDefs, sema
|
|
|
25848
26217
|
dependsOn: [
|
|
25849
26218
|
`motion-keyframe-${anim.keyframe}`,
|
|
25850
26219
|
...durationDependency,
|
|
25851
|
-
`
|
|
26220
|
+
`rafters-ease-${anim.curve}`
|
|
25852
26221
|
],
|
|
25853
26222
|
description: `Animation ${name}: ${anim.meaning}`,
|
|
25854
26223
|
generatedAt: timestamp,
|
|
@@ -25857,10 +26226,57 @@ function generateMotionTokens(config2, durationDefs, easingDefs, delayDefs, sema
|
|
|
25857
26226
|
userOverride: null
|
|
25858
26227
|
});
|
|
25859
26228
|
}
|
|
26229
|
+
for (const [name, cell] of Object.entries(cellAnimations)) {
|
|
26230
|
+
requireDef(keyframeDefs, cell.keyframe, "keyframe", `motion cell "${name}"`);
|
|
26231
|
+
requireDef(durationDefs, cell.tier, "duration tier", `motion cell "${name}"`);
|
|
26232
|
+
requireDef(easingDefs, cell.curve, "easing curve", `motion cell "${name}"`);
|
|
26233
|
+
const { component, part, transition } = cell.cell;
|
|
26234
|
+
tokens.push({
|
|
26235
|
+
name: `motion-cell-${name}`,
|
|
26236
|
+
value: JSON.stringify({
|
|
26237
|
+
keyframe: cell.keyframe,
|
|
26238
|
+
durationTier: cell.tier,
|
|
26239
|
+
curve: cell.curve
|
|
26240
|
+
}),
|
|
26241
|
+
category: "motion",
|
|
26242
|
+
namespace: "motion",
|
|
26243
|
+
semanticMeaning: cell.meaning,
|
|
26244
|
+
usageContext: cell.contexts,
|
|
26245
|
+
animationName: name,
|
|
26246
|
+
keyframeName: cell.keyframe,
|
|
26247
|
+
generateUtilityClass: true,
|
|
26248
|
+
dependsOn: [
|
|
26249
|
+
`motion-keyframe-${cell.keyframe}`,
|
|
26250
|
+
`rafters-duration-${cell.tier}`,
|
|
26251
|
+
`rafters-ease-${cell.curve}`
|
|
26252
|
+
],
|
|
26253
|
+
description: `Motion cell ${component} / ${part} / ${transition}: ${cell.keyframe} over ${cell.tier} with ${cell.curve}. ${cell.meaning}`,
|
|
26254
|
+
generatedAt: timestamp,
|
|
26255
|
+
containerQueryAware: false,
|
|
26256
|
+
reducedMotionAware: true,
|
|
26257
|
+
userOverride: null,
|
|
26258
|
+
usagePatterns: {
|
|
26259
|
+
do: [`Apply class animate-${name} on the ${component} ${part} for "${transition}"`],
|
|
26260
|
+
never: [
|
|
26261
|
+
"Reuse this cell on a different component -- assignments come from motion.jsonl, one cell at a time",
|
|
26262
|
+
"Add motion-reduce:animate-none alongside it -- animation:none resets the shorthand and discards the zeroed duration"
|
|
26263
|
+
]
|
|
26264
|
+
}
|
|
26265
|
+
});
|
|
26266
|
+
}
|
|
25860
26267
|
for (const [name, comp] of Object.entries(compositePresets)) {
|
|
25861
|
-
const durationDef =
|
|
25862
|
-
|
|
25863
|
-
|
|
26268
|
+
const durationDef = requireDef(
|
|
26269
|
+
durationDefs,
|
|
26270
|
+
comp.durationTier,
|
|
26271
|
+
"duration tier",
|
|
26272
|
+
`composite preset "${name}"`
|
|
26273
|
+
);
|
|
26274
|
+
const easingDef = requireDef(
|
|
26275
|
+
easingDefs,
|
|
26276
|
+
comp.curve,
|
|
26277
|
+
"easing curve",
|
|
26278
|
+
`composite preset "${name}"`
|
|
26279
|
+
);
|
|
25864
26280
|
const durationMs = durationDef.default;
|
|
25865
26281
|
tokens.push({
|
|
25866
26282
|
name,
|
|
@@ -25881,12 +26297,16 @@ function generateMotionTokens(config2, durationDefs, easingDefs, delayDefs, sema
|
|
|
25881
26297
|
});
|
|
25882
26298
|
}
|
|
25883
26299
|
for (const [name, mapping] of Object.entries(semanticMappings)) {
|
|
26300
|
+
const durationTier = deriveBand(mapping.category, mapping.travel, mapping.band);
|
|
26301
|
+
const curve = deriveCurve(mapping.category, mapping.travel, intent, mapping.curve);
|
|
26302
|
+
requireDef(durationDefs, durationTier, "duration tier", `semantic motion "${name}"`);
|
|
26303
|
+
requireDef(easingDefs, curve, "easing curve", `semantic motion "${name}"`);
|
|
25884
26304
|
tokens.push({
|
|
25885
26305
|
name: `motion-semantic-${name}`,
|
|
25886
26306
|
value: JSON.stringify({
|
|
25887
26307
|
properties: mapping.properties,
|
|
25888
|
-
durationTier
|
|
25889
|
-
curve
|
|
26308
|
+
durationTier,
|
|
26309
|
+
curve,
|
|
25890
26310
|
reducedMotion: mapping.reducedMotion
|
|
25891
26311
|
}),
|
|
25892
26312
|
category: "motion",
|
|
@@ -25895,8 +26315,8 @@ function generateMotionTokens(config2, durationDefs, easingDefs, delayDefs, sema
|
|
|
25895
26315
|
usageContext: mapping.contexts,
|
|
25896
26316
|
motionIntent: mapping.category === "enter" ? "enter" : mapping.category === "exit" ? "exit" : "transition",
|
|
25897
26317
|
generateUtilityClass: true,
|
|
25898
|
-
dependsOn: [`motion-duration-${
|
|
25899
|
-
description: `Semantic motion motion-${name}: ${mapping.properties.join(", ")} over ${
|
|
26318
|
+
dependsOn: [`motion-duration-${durationTier}`, `motion-easing-${curve}`],
|
|
26319
|
+
description: `Semantic motion motion-${name}: ${mapping.properties.join(", ")} over ${durationTier} with ${curve}. ${mapping.sizeReasoning}`,
|
|
25900
26320
|
generatedAt: timestamp,
|
|
25901
26321
|
containerQueryAware: false,
|
|
25902
26322
|
reducedMotionAware: true,
|
|
@@ -25913,12 +26333,13 @@ function generateMotionTokens(config2, durationDefs, easingDefs, delayDefs, sema
|
|
|
25913
26333
|
ratio: progressionRatio,
|
|
25914
26334
|
ratioValue: ratioVal,
|
|
25915
26335
|
baseDuration: baseTransitionDuration,
|
|
25916
|
-
note: "Duration tiers are perceptually derived literals (docs/MOTION.md)
|
|
26336
|
+
note: "Duration tiers are perceptually derived literals (docs/MOTION.md) and the five motion namespaces are authored leaves. The ratio reaches exactly one place: the loop keyframes ping, pulse and bounce, whose shapes are computed from it.",
|
|
26337
|
+
ratioDrivenKeyframes: ["ping", "pulse", "bounce"]
|
|
25917
26338
|
}),
|
|
25918
26339
|
category: "motion",
|
|
25919
26340
|
namespace: "motion",
|
|
25920
26341
|
semanticMeaning: "Metadata about the motion system",
|
|
25921
|
-
description: `Duration tiers are perceptual literals;
|
|
26342
|
+
description: `Duration tiers are perceptual literals; the five motion namespaces (duration, ease, delay, extent, period) are authored leaves. The ${progressionRatio} progression drives the loop keyframes ping, pulse and bounce, and nothing else -- the ${baseTransitionDuration}ms base is recorded for reference and drives no value.`,
|
|
25922
26343
|
generatedAt: timestamp,
|
|
25923
26344
|
containerQueryAware: false,
|
|
25924
26345
|
userOverride: null
|
|
@@ -25942,16 +26363,17 @@ function generateRadiusTokens(config2, radiusDefs) {
|
|
|
25942
26363
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
25943
26364
|
const { baseRadius, progressionRatio } = config2;
|
|
25944
26365
|
const ratioVal = ratioValue(resolveRatio(progressionRatio));
|
|
25945
|
-
const
|
|
26366
|
+
const radiusMultiplier = Math.round(baseRadius / config2.baseSpacingUnit * 1e3) / 1e3;
|
|
25946
26367
|
tokens.push({
|
|
25947
26368
|
name: "radius-base",
|
|
25948
|
-
value:
|
|
26369
|
+
value: `calc(var(--rafters-spacing-base) * ${radiusMultiplier})`,
|
|
25949
26370
|
category: "radius",
|
|
25950
26371
|
namespace: "radius",
|
|
25951
|
-
semanticMeaning: "Base border radius -
|
|
26372
|
+
semanticMeaning: "Base border radius - derives from spacing base",
|
|
25952
26373
|
usageContext: ["calculation-reference"],
|
|
25953
26374
|
progressionSystem: progressionRatio,
|
|
25954
|
-
|
|
26375
|
+
dependsOn: ["spacing-base"],
|
|
26376
|
+
description: `Base radius = spacing-base * ${radiusMultiplier} (${baseRadius}px at base ${config2.baseSpacingUnit}). Scale uses ${progressionRatio} progression (ratio ${ratioVal}).`,
|
|
25955
26377
|
generatedAt: timestamp,
|
|
25956
26378
|
containerQueryAware: false,
|
|
25957
26379
|
userOverride: null,
|
|
@@ -25989,15 +26411,15 @@ function generateRadiusTokens(config2, radiusDefs) {
|
|
|
25989
26411
|
mathRelationship = "infinite (9999px)";
|
|
25990
26412
|
} else if (def.step === 0) {
|
|
25991
26413
|
value = "var(--rafters-radius-base)";
|
|
25992
|
-
mathRelationship =
|
|
26414
|
+
mathRelationship = `spacing-base * ${radiusMultiplier} (base)`;
|
|
25993
26415
|
} else {
|
|
25994
26416
|
const multiplier = Math.round(ratioVal ** def.step * 1e3) / 1e3;
|
|
25995
26417
|
value = `calc(var(--rafters-radius-base) * ${multiplier})`;
|
|
25996
26418
|
mathRelationship = `base \xD7 ${ratioVal}^${def.step} (\xD7${multiplier})`;
|
|
25997
26419
|
}
|
|
25998
|
-
const
|
|
26420
|
+
const scaleName2 = scale2 === "DEFAULT" ? "radius" : `radius-${scale2}`;
|
|
25999
26421
|
tokens.push({
|
|
26000
|
-
name:
|
|
26422
|
+
name: scaleName2,
|
|
26001
26423
|
value,
|
|
26002
26424
|
category: "radius",
|
|
26003
26425
|
namespace: "radius",
|
|
@@ -26186,40 +26608,69 @@ function generateSemanticTokens(_config) {
|
|
|
26186
26608
|
};
|
|
26187
26609
|
}
|
|
26188
26610
|
|
|
26611
|
+
// ../design-tokens/src/generators/progression.ts
|
|
26612
|
+
var NON_ADVANCING = 1;
|
|
26613
|
+
function progressionFrom(floor, ratioVal, ceiling) {
|
|
26614
|
+
if (!(ratioVal > NON_ADVANCING) || !(floor > 0) || !(ceiling >= floor)) return [floor];
|
|
26615
|
+
const out = [];
|
|
26616
|
+
const seen = /* @__PURE__ */ new Set();
|
|
26617
|
+
for (let n2 = 0; ; n2++) {
|
|
26618
|
+
const value = Math.round(floor * ratioVal ** n2);
|
|
26619
|
+
if (value > ceiling) break;
|
|
26620
|
+
if (!seen.has(value)) {
|
|
26621
|
+
seen.add(value);
|
|
26622
|
+
out.push(value);
|
|
26623
|
+
}
|
|
26624
|
+
}
|
|
26625
|
+
return out;
|
|
26626
|
+
}
|
|
26627
|
+
function nearestRung(target, scale2) {
|
|
26628
|
+
let best = scale2[0] ?? target;
|
|
26629
|
+
for (const v of scale2) {
|
|
26630
|
+
if (Math.abs(v - target) < Math.abs(best - target)) best = v;
|
|
26631
|
+
}
|
|
26632
|
+
return best;
|
|
26633
|
+
}
|
|
26634
|
+
|
|
26189
26635
|
// ../design-tokens/src/generators/shadow.ts
|
|
26190
|
-
function
|
|
26636
|
+
function pxToRem(px) {
|
|
26191
26637
|
const rem = Math.round(px / 16 * 1e3) / 1e3;
|
|
26192
26638
|
return `${rem}rem`;
|
|
26193
26639
|
}
|
|
26194
26640
|
var SHADOW_PARTS = ["offset-x", "offset-y", "blur", "spread", "color"];
|
|
26195
|
-
function
|
|
26196
|
-
return
|
|
26641
|
+
function shadowScale(ratioVal, bounds) {
|
|
26642
|
+
return progressionFrom(bounds.floor, ratioVal, bounds.ceiling);
|
|
26197
26643
|
}
|
|
26198
|
-
function
|
|
26644
|
+
function scalePx(multiplier, baseSpacing, scale2) {
|
|
26645
|
+
if (multiplier === 0) return 0;
|
|
26646
|
+
return nearestRung(multiplier * baseSpacing, scale2);
|
|
26647
|
+
}
|
|
26648
|
+
function resolveShadowParts(def, baseSpacing, scale2) {
|
|
26199
26649
|
return {
|
|
26200
26650
|
// Shadows are vertical-only by design (material elevation model)
|
|
26201
26651
|
"offset-x": "0rem",
|
|
26202
|
-
"offset-y":
|
|
26203
|
-
blur:
|
|
26204
|
-
spread:
|
|
26652
|
+
"offset-y": pxToRem(scalePx(def.yOffset, baseSpacing, scale2)),
|
|
26653
|
+
blur: pxToRem(scalePx(def.blur, baseSpacing, scale2)),
|
|
26654
|
+
spread: pxToRem(scalePx(def.spread, baseSpacing, scale2)),
|
|
26205
26655
|
color: `rgb(0 0 0 / ${def.opacity})`
|
|
26206
26656
|
};
|
|
26207
26657
|
}
|
|
26208
|
-
function generateInnerShadowValue(inner, baseSpacing) {
|
|
26209
|
-
const y =
|
|
26210
|
-
const blur =
|
|
26211
|
-
const spread =
|
|
26658
|
+
function generateInnerShadowValue(inner, baseSpacing, scale2) {
|
|
26659
|
+
const y = pxToRem(scalePx(inner.yOffset, baseSpacing, scale2));
|
|
26660
|
+
const blur = pxToRem(scalePx(inner.blur, baseSpacing, scale2));
|
|
26661
|
+
const spread = pxToRem(scalePx(inner.spread, baseSpacing, scale2));
|
|
26212
26662
|
return `0 ${y} ${blur} ${spread} rgb(0 0 0 / ${inner.opacity})`;
|
|
26213
26663
|
}
|
|
26214
26664
|
function buildCompositeFromVars(prefix, innerValue) {
|
|
26215
26665
|
const primary = SHADOW_PARTS.map((part) => `var(--rafters-${prefix}-${part})`).join(" ");
|
|
26216
26666
|
return innerValue ? `${primary}, ${innerValue}` : primary;
|
|
26217
26667
|
}
|
|
26218
|
-
function generateShadowTokens(config2, shadowDefs) {
|
|
26668
|
+
function generateShadowTokens(config2, shadowDefs, bounds) {
|
|
26219
26669
|
const tokens = [];
|
|
26220
26670
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
26221
26671
|
const { baseSpacingUnit, progressionRatio } = config2;
|
|
26222
26672
|
const ratioVal = ratioValue(resolveRatio(progressionRatio));
|
|
26673
|
+
const geometry = shadowScale(ratioVal, bounds);
|
|
26223
26674
|
const baseSpacingRem = baseSpacingUnit / 16;
|
|
26224
26675
|
tokens.push({
|
|
26225
26676
|
name: "shadow-base-unit",
|
|
@@ -26239,10 +26690,10 @@ function generateShadowTokens(config2, shadowDefs) {
|
|
|
26239
26690
|
const def = shadowDefs[scale2];
|
|
26240
26691
|
if (!def) continue;
|
|
26241
26692
|
const scaleIndex = SHADOW_SCALE.indexOf(scale2);
|
|
26242
|
-
const
|
|
26693
|
+
const scaleName2 = scale2 === "DEFAULT" ? "shadow" : `shadow-${scale2}`;
|
|
26243
26694
|
if (def.opacity === 0) {
|
|
26244
26695
|
tokens.push({
|
|
26245
|
-
name:
|
|
26696
|
+
name: scaleName2,
|
|
26246
26697
|
value: "none",
|
|
26247
26698
|
category: "shadow",
|
|
26248
26699
|
namespace: "shadow",
|
|
@@ -26262,10 +26713,10 @@ function generateShadowTokens(config2, shadowDefs) {
|
|
|
26262
26713
|
});
|
|
26263
26714
|
continue;
|
|
26264
26715
|
}
|
|
26265
|
-
const parts = resolveShadowParts(def, baseSpacingUnit);
|
|
26716
|
+
const parts = resolveShadowParts(def, baseSpacingUnit, geometry);
|
|
26266
26717
|
const partDeps = [];
|
|
26267
26718
|
for (const part of SHADOW_PARTS) {
|
|
26268
|
-
const partName = `${
|
|
26719
|
+
const partName = `${scaleName2}-${part}`;
|
|
26269
26720
|
partDeps.push(partName);
|
|
26270
26721
|
tokens.push({
|
|
26271
26722
|
name: partName,
|
|
@@ -26282,10 +26733,10 @@ function generateShadowTokens(config2, shadowDefs) {
|
|
|
26282
26733
|
userOverride: null
|
|
26283
26734
|
});
|
|
26284
26735
|
}
|
|
26285
|
-
const innerValue = def.innerShadow && def.innerShadow.opacity > 0 ? generateInnerShadowValue(def.innerShadow, baseSpacingUnit) : null;
|
|
26286
|
-
const compositeValue = buildCompositeFromVars(
|
|
26736
|
+
const innerValue = def.innerShadow && def.innerShadow.opacity > 0 ? generateInnerShadowValue(def.innerShadow, baseSpacingUnit, geometry) : null;
|
|
26737
|
+
const compositeValue = buildCompositeFromVars(scaleName2, innerValue);
|
|
26287
26738
|
tokens.push({
|
|
26288
|
-
name:
|
|
26739
|
+
name: scaleName2,
|
|
26289
26740
|
value: compositeValue,
|
|
26290
26741
|
category: "shadow",
|
|
26291
26742
|
namespace: "shadow",
|
|
@@ -26294,7 +26745,7 @@ function generateShadowTokens(config2, shadowDefs) {
|
|
|
26294
26745
|
scalePosition: scaleIndex,
|
|
26295
26746
|
progressionSystem: progressionRatio,
|
|
26296
26747
|
dependsOn: partDeps,
|
|
26297
|
-
description: `Shadow ${scale2}: ${def.meaning}. Composed from var() refs to ${
|
|
26748
|
+
description: `Shadow ${scale2}: ${def.meaning}. Composed from var() refs to ${scaleName2}-* tokens.`,
|
|
26298
26749
|
generatedAt: timestamp,
|
|
26299
26750
|
containerQueryAware: false,
|
|
26300
26751
|
userOverride: null,
|
|
@@ -26367,13 +26818,19 @@ function generateShadowTokens(config2, shadowDefs) {
|
|
|
26367
26818
|
}
|
|
26368
26819
|
|
|
26369
26820
|
// ../design-tokens/src/generators/spacing.ts
|
|
26370
|
-
function
|
|
26821
|
+
function spacingMultipliers(ratioVal, bounds) {
|
|
26822
|
+
return progressionFrom(bounds.floor, ratioVal, bounds.ceiling);
|
|
26823
|
+
}
|
|
26824
|
+
function scaleName(multiplier) {
|
|
26825
|
+
return String(multiplier);
|
|
26826
|
+
}
|
|
26827
|
+
function generateSpacingTokens(config2, bounds) {
|
|
26371
26828
|
const tokens = [];
|
|
26372
26829
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
26373
26830
|
const { baseSpacingUnit, progressionRatio } = config2;
|
|
26374
26831
|
const ratio = resolveRatio(progressionRatio);
|
|
26375
26832
|
const ratioVal = ratioValue(ratio);
|
|
26376
|
-
const
|
|
26833
|
+
const multipliers = spacingMultipliers(ratioVal, bounds);
|
|
26377
26834
|
const baseRem = baseSpacingUnit / 16;
|
|
26378
26835
|
tokens.push({
|
|
26379
26836
|
name: "spacing-base",
|
|
@@ -26398,11 +26855,10 @@ function generateSpacingTokens(config2, spacingMultipliers) {
|
|
|
26398
26855
|
]
|
|
26399
26856
|
}
|
|
26400
26857
|
});
|
|
26401
|
-
for (const
|
|
26402
|
-
const
|
|
26403
|
-
if (multiplier === void 0) continue;
|
|
26858
|
+
for (const multiplier of [0, ...multipliers]) {
|
|
26859
|
+
const scale2 = scaleName(multiplier);
|
|
26404
26860
|
const value = baseSpacingUnit * multiplier;
|
|
26405
|
-
const scaleIndex =
|
|
26861
|
+
const scaleIndex = multipliers.indexOf(multiplier) + 1;
|
|
26406
26862
|
let meaning;
|
|
26407
26863
|
let usageContext;
|
|
26408
26864
|
if (multiplier === 0) {
|
|
@@ -26449,16 +26905,19 @@ function generateSpacingTokens(config2, spacingMultipliers) {
|
|
|
26449
26905
|
}
|
|
26450
26906
|
tokens.push({
|
|
26451
26907
|
name: "spacing-progression",
|
|
26908
|
+
// The scale that actually shipped. Before #2031 this carried a `sample`
|
|
26909
|
+
// computed straight off the ratio while the tokens came from a table --
|
|
26910
|
+
// metadata describing a scale that did not exist.
|
|
26452
26911
|
value: JSON.stringify({
|
|
26453
26912
|
ratio: progressionRatio,
|
|
26454
26913
|
ratioValue: ratioVal,
|
|
26455
26914
|
baseUnit: baseSpacingUnit,
|
|
26456
|
-
|
|
26915
|
+
multipliers
|
|
26457
26916
|
}),
|
|
26458
26917
|
category: "spacing",
|
|
26459
26918
|
namespace: "spacing",
|
|
26460
26919
|
semanticMeaning: "Metadata about the spacing progression system",
|
|
26461
|
-
description: `Spacing
|
|
26920
|
+
description: `Spacing is ${baseSpacingUnit}px x ${progressionRatio} (${ratioVal})^n from position 0, rounded to whole pixels: ${multipliers.length} rungs, ${baseSpacingUnit}px to ${Math.round(baseSpacingUnit * (multipliers[multipliers.length - 1] ?? 1))}px.`,
|
|
26462
26921
|
generatedAt: timestamp,
|
|
26463
26922
|
containerQueryAware: false,
|
|
26464
26923
|
userOverride: null,
|
|
@@ -26795,7 +27254,7 @@ function createGeneratorDefs(colorPaletteBases) {
|
|
|
26795
27254
|
},
|
|
26796
27255
|
{
|
|
26797
27256
|
name: "spacing",
|
|
26798
|
-
generate: (config2) => generateSpacingTokens(config2,
|
|
27257
|
+
generate: (config2) => generateSpacingTokens(config2, DEFAULT_SPACING_BOUNDS)
|
|
26799
27258
|
},
|
|
26800
27259
|
{
|
|
26801
27260
|
name: "typography",
|
|
@@ -26816,7 +27275,7 @@ function createGeneratorDefs(colorPaletteBases) {
|
|
|
26816
27275
|
},
|
|
26817
27276
|
{
|
|
26818
27277
|
name: "shadow",
|
|
26819
|
-
generate: (config2) => generateShadowTokens(config2, DEFAULT_SHADOW_DEFINITIONS)
|
|
27278
|
+
generate: (config2) => generateShadowTokens(config2, DEFAULT_SHADOW_DEFINITIONS, DEFAULT_SHADOW_BOUNDS)
|
|
26820
27279
|
},
|
|
26821
27280
|
{
|
|
26822
27281
|
name: "depth",
|
|
@@ -26828,11 +27287,14 @@ function createGeneratorDefs(colorPaletteBases) {
|
|
|
26828
27287
|
config2,
|
|
26829
27288
|
DEFAULT_DURATION_DEFINITIONS,
|
|
26830
27289
|
DEFAULT_EASING_DEFINITIONS,
|
|
26831
|
-
|
|
27290
|
+
DEFAULT_DELAY_NAMESPACE,
|
|
27291
|
+
DEFAULT_EXTENT_NAMESPACE,
|
|
27292
|
+
DEFAULT_PERIOD_NAMESPACE,
|
|
26832
27293
|
DEFAULT_MOTION_SEMANTIC_MAPPINGS,
|
|
26833
27294
|
DEFAULT_KEYFRAME_DEFINITIONS,
|
|
26834
27295
|
DEFAULT_ANIMATION_DEFINITIONS,
|
|
26835
|
-
DEFAULT_MOTION_COMPOSITE_PRESETS
|
|
27296
|
+
DEFAULT_MOTION_COMPOSITE_PRESETS,
|
|
27297
|
+
DEFAULT_MOTION_CELL_ANIMATIONS
|
|
26836
27298
|
)
|
|
26837
27299
|
},
|
|
26838
27300
|
{
|
|
@@ -26871,7 +27333,10 @@ function generateBaseSystem(config2 = {}) {
|
|
|
26871
27333
|
var UserOverrideSchema = external_exports.object({
|
|
26872
27334
|
previousValue: external_exports.unknown(),
|
|
26873
27335
|
reason: external_exports.string(),
|
|
26874
|
-
context: external_exports.string().optional()
|
|
27336
|
+
context: external_exports.string().optional(),
|
|
27337
|
+
// Provenance. Optional by design: absent means unknown, which is what every
|
|
27338
|
+
// override written before this field existed actually is.
|
|
27339
|
+
kind: OverrideKindSchema.optional()
|
|
26875
27340
|
});
|
|
26876
27341
|
var BindingSchema2 = external_exports.object({
|
|
26877
27342
|
plugin: external_exports.string(),
|
|
@@ -26916,7 +27381,8 @@ var TokenGraph = class {
|
|
|
26916
27381
|
userOverride: {
|
|
26917
27382
|
previousValue: existing?.value,
|
|
26918
27383
|
reason: options.reason,
|
|
26919
|
-
...options.context ? { context: options.context } : {}
|
|
27384
|
+
...options.context ? { context: options.context } : {},
|
|
27385
|
+
...options.kind ? { kind: options.kind } : {}
|
|
26920
27386
|
},
|
|
26921
27387
|
...existing?.binding ? { binding: existing.binding } : {}
|
|
26922
27388
|
};
|
|
@@ -27482,7 +27948,7 @@ async function regenerateOutputs(registry2, input, hooks2 = {}) {
|
|
|
27482
27948
|
written.push("rafters.standalone.css");
|
|
27483
27949
|
}
|
|
27484
27950
|
if (exports.documentation) {
|
|
27485
|
-
const doc = await registryToDocumentation(registry2);
|
|
27951
|
+
const doc = await registryToDocumentation(registry2, { contentSources });
|
|
27486
27952
|
await writeFile(join2(outputDir2, "rafters.documentation.css"), doc);
|
|
27487
27953
|
written.push("rafters.documentation.css");
|
|
27488
27954
|
}
|
|
@@ -27512,11 +27978,7 @@ var TokenRegistry = class {
|
|
|
27512
27978
|
parsed.push(result.data);
|
|
27513
27979
|
}
|
|
27514
27980
|
for (const t of parsed) {
|
|
27515
|
-
const override = t.userOverride
|
|
27516
|
-
previousValue: t.userOverride.previousValue,
|
|
27517
|
-
reason: t.userOverride.reason,
|
|
27518
|
-
...t.userOverride.context ? { context: t.userOverride.context } : {}
|
|
27519
|
-
} : void 0;
|
|
27981
|
+
const override = toNodeOverride(t.userOverride);
|
|
27520
27982
|
if (t.binding && !override) continue;
|
|
27521
27983
|
this.graph.seed(t.name, t.value, {
|
|
27522
27984
|
...override ? { userOverride: override } : {},
|
|
@@ -27540,11 +28002,7 @@ var TokenRegistry = class {
|
|
|
27540
28002
|
}
|
|
27541
28003
|
const t = result.data;
|
|
27542
28004
|
this.metadata.set(t.name, t);
|
|
27543
|
-
const override = t.userOverride
|
|
27544
|
-
previousValue: t.userOverride.previousValue,
|
|
27545
|
-
reason: t.userOverride.reason,
|
|
27546
|
-
...t.userOverride.context ? { context: t.userOverride.context } : {}
|
|
27547
|
-
} : void 0;
|
|
28005
|
+
const override = toNodeOverride(t.userOverride);
|
|
27548
28006
|
if (t.binding && !override) {
|
|
27549
28007
|
this.graph.bind(t.name, t.binding.plugin, t.binding.input);
|
|
27550
28008
|
} else {
|
|
@@ -27620,6 +28078,15 @@ var TokenParseError = class extends Error {
|
|
|
27620
28078
|
this.name = "TokenParseError";
|
|
27621
28079
|
}
|
|
27622
28080
|
};
|
|
28081
|
+
function toNodeOverride(field) {
|
|
28082
|
+
if (!field) return void 0;
|
|
28083
|
+
return {
|
|
28084
|
+
previousValue: field.previousValue,
|
|
28085
|
+
reason: field.reason,
|
|
28086
|
+
...field.context ? { context: field.context } : {},
|
|
28087
|
+
...field.kind ? { kind: field.kind } : {}
|
|
28088
|
+
};
|
|
28089
|
+
}
|
|
27623
28090
|
function toUserOverrideField(override, baseValue) {
|
|
27624
28091
|
const previousValue = override.previousValue ?? baseValue;
|
|
27625
28092
|
const result = {
|
|
@@ -27627,6 +28094,7 @@ function toUserOverrideField(override, baseValue) {
|
|
|
27627
28094
|
reason: override.reason
|
|
27628
28095
|
};
|
|
27629
28096
|
if (override.context) result.context = override.context;
|
|
28097
|
+
if (override.kind) result.kind = override.kind;
|
|
27630
28098
|
return result;
|
|
27631
28099
|
}
|
|
27632
28100
|
|
|
@@ -28467,15 +28935,37 @@ function log(event) {
|
|
|
28467
28935
|
console.log(` ${event.suggestion}`);
|
|
28468
28936
|
}
|
|
28469
28937
|
break;
|
|
28470
|
-
case "add:complete":
|
|
28471
|
-
|
|
28472
|
-
|
|
28473
|
-
|
|
28474
|
-
|
|
28475
|
-
|
|
28938
|
+
case "add:complete": {
|
|
28939
|
+
const written = event.written;
|
|
28940
|
+
const skippedCount = event.skipped;
|
|
28941
|
+
const untrackedCount = event.untracked;
|
|
28942
|
+
const failedCount = event.failed;
|
|
28943
|
+
const headline = `Wrote ${written} item${written !== 1 ? "s" : ""}`;
|
|
28944
|
+
if (failedCount > 0) {
|
|
28945
|
+
context.spinner?.fail(`${headline}, ${failedCount} failed -- see below`);
|
|
28946
|
+
} else {
|
|
28947
|
+
context.spinner?.succeed(headline);
|
|
28948
|
+
}
|
|
28949
|
+
if (skippedCount > 0) {
|
|
28950
|
+
const names = event.skippedComponents ?? [];
|
|
28951
|
+
console.log(
|
|
28952
|
+
` Skipped: ${skippedCount} (already present; use --update to re-fetch)${names.length > 0 ? ` -- ${names.join(", ")}` : ""}`
|
|
28953
|
+
);
|
|
28954
|
+
}
|
|
28955
|
+
if (untrackedCount > 0) {
|
|
28956
|
+
const names = event.untrackedComponents ?? [];
|
|
28957
|
+
console.log(` Untracked on disk, now tracked: ${untrackedCount} -- ${names.join(", ")}`);
|
|
28958
|
+
}
|
|
28959
|
+
if (failedCount > 0) {
|
|
28960
|
+
const names = event.failedComponents ?? [];
|
|
28961
|
+
console.log(` Failed: ${failedCount} -- ${names.join(", ")}`);
|
|
28476
28962
|
}
|
|
28477
28963
|
console.log("");
|
|
28478
28964
|
break;
|
|
28965
|
+
}
|
|
28966
|
+
case "add:untracked":
|
|
28967
|
+
console.log(` ${event.message}`);
|
|
28968
|
+
break;
|
|
28479
28969
|
case "add:hint":
|
|
28480
28970
|
console.log(`
|
|
28481
28971
|
${event.message}`);
|
|
@@ -28825,6 +29315,51 @@ function resolveReadSet(field, cwd, fallback) {
|
|
|
28825
29315
|
return out;
|
|
28826
29316
|
}
|
|
28827
29317
|
|
|
29318
|
+
// src/utils/reconcile.ts
|
|
29319
|
+
import { readdirSync as readdirSync2 } from "fs";
|
|
29320
|
+
var DISCOVERABLE_KINDS = ["components", "primitives", "composites"];
|
|
29321
|
+
var KIND_PATHS = {
|
|
29322
|
+
components: { field: "componentsPath", fallback: "components/ui" },
|
|
29323
|
+
primitives: { field: "primitivesPath", fallback: "lib/primitives" },
|
|
29324
|
+
composites: { field: "compositesPath", fallback: "composites" }
|
|
29325
|
+
};
|
|
29326
|
+
function hasEntryFor(entries, name) {
|
|
29327
|
+
return entries.some((entry) => entry === name || entry.startsWith(`${name}.`));
|
|
29328
|
+
}
|
|
29329
|
+
function buildUpdateCandidates(tracked, index, entries) {
|
|
29330
|
+
const trackedSet = new Set(tracked);
|
|
29331
|
+
const untracked = /* @__PURE__ */ new Set();
|
|
29332
|
+
if (index) {
|
|
29333
|
+
for (const kind of DISCOVERABLE_KINDS) {
|
|
29334
|
+
for (const name of index[kind]) {
|
|
29335
|
+
if (trackedSet.has(name)) continue;
|
|
29336
|
+
if (hasEntryFor(entries[kind], name)) untracked.add(name);
|
|
29337
|
+
}
|
|
29338
|
+
}
|
|
29339
|
+
}
|
|
29340
|
+
return { tracked: [...trackedSet].sort(), untracked: [...untracked].sort() };
|
|
29341
|
+
}
|
|
29342
|
+
function readInstallRoots(cwd, config2) {
|
|
29343
|
+
const entries = { components: [], primitives: [], composites: [] };
|
|
29344
|
+
for (const kind of DISCOVERABLE_KINDS) {
|
|
29345
|
+
const { field, fallback } = KIND_PATHS[kind];
|
|
29346
|
+
const configured = config2?.[field];
|
|
29347
|
+
const pathField = isPathField(configured) ? configured : fallback;
|
|
29348
|
+
const names = /* @__PURE__ */ new Set();
|
|
29349
|
+
for (const dir of resolveReadSet(pathField, cwd, fallback)) {
|
|
29350
|
+
try {
|
|
29351
|
+
for (const entry of readdirSync2(dir)) names.add(entry);
|
|
29352
|
+
} catch {
|
|
29353
|
+
}
|
|
29354
|
+
}
|
|
29355
|
+
entries[kind] = [...names];
|
|
29356
|
+
}
|
|
29357
|
+
return entries;
|
|
29358
|
+
}
|
|
29359
|
+
function isPathField(value) {
|
|
29360
|
+
return typeof value === "string" || Array.isArray(value);
|
|
29361
|
+
}
|
|
29362
|
+
|
|
28828
29363
|
// src/commands/add.ts
|
|
28829
29364
|
var REGISTRY_PLUGINS = [scalePlugin, contrastPlugin, statePlugin, invertPlugin];
|
|
28830
29365
|
async function regenerateAfterInstall(cwd, config2) {
|
|
@@ -28885,10 +29420,26 @@ function getInstalledNames(config2) {
|
|
|
28885
29420
|
const names = /* @__PURE__ */ new Set([
|
|
28886
29421
|
...config2.installed.components,
|
|
28887
29422
|
...config2.installed.primitives,
|
|
28888
|
-
...config2.installed.composites ?? []
|
|
29423
|
+
...config2.installed.composites ?? [],
|
|
29424
|
+
...config2.installed.rules ?? [],
|
|
29425
|
+
...config2.installed.substrate ?? []
|
|
28889
29426
|
]);
|
|
28890
29427
|
return [...names].sort();
|
|
28891
29428
|
}
|
|
29429
|
+
async function discoverUntrackedNames(cwd, config2, client, tracked) {
|
|
29430
|
+
let index = null;
|
|
29431
|
+
try {
|
|
29432
|
+
index = await client.fetchIndex();
|
|
29433
|
+
} catch (err) {
|
|
29434
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
29435
|
+
log({
|
|
29436
|
+
event: "add:warning",
|
|
29437
|
+
message: `Could not read the registry index to reconcile on-disk components (${message}). Updating tracked components only.`
|
|
29438
|
+
});
|
|
29439
|
+
}
|
|
29440
|
+
const { untracked } = buildUpdateCandidates(tracked, index, readInstallRoots(cwd, config2));
|
|
29441
|
+
return untracked;
|
|
29442
|
+
}
|
|
28892
29443
|
function getComponentTarget(config2) {
|
|
28893
29444
|
return resolveComponentTarget(config2);
|
|
28894
29445
|
}
|
|
@@ -29134,6 +29685,7 @@ async function add(componentArgs, options) {
|
|
|
29134
29685
|
if (options.update) {
|
|
29135
29686
|
options.overwrite = true;
|
|
29136
29687
|
}
|
|
29688
|
+
let untrackedNames = [];
|
|
29137
29689
|
if (options.updateAll) {
|
|
29138
29690
|
options.overwrite = true;
|
|
29139
29691
|
if (!config2) {
|
|
@@ -29141,13 +29693,22 @@ async function add(componentArgs, options) {
|
|
|
29141
29693
|
process.exitCode = 1;
|
|
29142
29694
|
return;
|
|
29143
29695
|
}
|
|
29144
|
-
const
|
|
29145
|
-
|
|
29696
|
+
const trackedNames = getInstalledNames(config2);
|
|
29697
|
+
untrackedNames = await discoverUntrackedNames(cwd, config2, client, trackedNames);
|
|
29698
|
+
const candidates = [.../* @__PURE__ */ new Set([...trackedNames, ...untrackedNames])].sort();
|
|
29699
|
+
if (candidates.length === 0) {
|
|
29146
29700
|
error46("No installed components found. Use 'rafters add <component>' to install first.");
|
|
29147
29701
|
process.exitCode = 1;
|
|
29148
29702
|
return;
|
|
29149
29703
|
}
|
|
29150
|
-
|
|
29704
|
+
if (untrackedNames.length > 0) {
|
|
29705
|
+
log({
|
|
29706
|
+
event: "add:untracked",
|
|
29707
|
+
components: untrackedNames,
|
|
29708
|
+
message: `Found ${untrackedNames.length} component(s) on disk the config never tracked: ${untrackedNames.join(", ")}. Refreshing and tracking them.`
|
|
29709
|
+
});
|
|
29710
|
+
}
|
|
29711
|
+
components = candidates;
|
|
29151
29712
|
}
|
|
29152
29713
|
if (folder === "composites" && components.length === 0) {
|
|
29153
29714
|
components = ["composites"];
|
|
@@ -29198,8 +29759,9 @@ async function add(componentArgs, options) {
|
|
|
29198
29759
|
allItems.filter((item) => item.type === "substrate").map((item) => item.files[0]?.path.split("/")[0]).filter((segment) => Boolean(segment))
|
|
29199
29760
|
)
|
|
29200
29761
|
];
|
|
29201
|
-
const
|
|
29762
|
+
const written = [];
|
|
29202
29763
|
const skipped = [];
|
|
29764
|
+
const failed = [];
|
|
29203
29765
|
const installedItems = [];
|
|
29204
29766
|
const filteredItems = [];
|
|
29205
29767
|
const target = getComponentTarget(config2);
|
|
@@ -29223,7 +29785,7 @@ async function add(componentArgs, options) {
|
|
|
29223
29785
|
try {
|
|
29224
29786
|
const result = await installItem(cwd, item, options, config2, substrateKinds);
|
|
29225
29787
|
if (result.installed) {
|
|
29226
|
-
|
|
29788
|
+
written.push(item.name);
|
|
29227
29789
|
installedItems.push(item);
|
|
29228
29790
|
if (item.type === "ui") {
|
|
29229
29791
|
const selection = selectFilesForFramework(item.files, target);
|
|
@@ -29243,6 +29805,7 @@ async function add(componentArgs, options) {
|
|
|
29243
29805
|
installedItems.push(item);
|
|
29244
29806
|
}
|
|
29245
29807
|
} catch (err) {
|
|
29808
|
+
failed.push(item.name);
|
|
29246
29809
|
if (err instanceof Error) {
|
|
29247
29810
|
log({
|
|
29248
29811
|
event: "add:warning",
|
|
@@ -29300,11 +29863,19 @@ async function add(componentArgs, options) {
|
|
|
29300
29863
|
}
|
|
29301
29864
|
log({
|
|
29302
29865
|
event: "add:complete",
|
|
29303
|
-
|
|
29866
|
+
written: written.length,
|
|
29304
29867
|
skipped: skipped.length,
|
|
29305
|
-
|
|
29306
|
-
|
|
29307
|
-
|
|
29868
|
+
untracked: untrackedNames.length,
|
|
29869
|
+
failed: failed.length,
|
|
29870
|
+
components: written,
|
|
29871
|
+
skippedComponents: skipped,
|
|
29872
|
+
untrackedComponents: untrackedNames,
|
|
29873
|
+
failedComponents: failed
|
|
29874
|
+
});
|
|
29875
|
+
if (failed.length > 0) {
|
|
29876
|
+
process.exitCode = 1;
|
|
29877
|
+
}
|
|
29878
|
+
if (!options.updateAll && skipped.length > 0 && written.length === 0) {
|
|
29308
29879
|
log({
|
|
29309
29880
|
event: "add:hint",
|
|
29310
29881
|
message: "Some components were skipped. Use --update to re-fetch, or --update-all to refresh everything.",
|
|
@@ -30187,6 +30758,24 @@ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
|
30187
30758
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
30188
30759
|
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
30189
30760
|
|
|
30761
|
+
// src/version.ts
|
|
30762
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
30763
|
+
var UNKNOWN_VERSION = "0.0.0-unknown";
|
|
30764
|
+
function readVersion() {
|
|
30765
|
+
try {
|
|
30766
|
+
const parsed = JSON.parse(
|
|
30767
|
+
readFileSync2(new URL("../package.json", import.meta.url), "utf-8")
|
|
30768
|
+
);
|
|
30769
|
+
if (parsed !== null && typeof parsed === "object" && "version" in parsed) {
|
|
30770
|
+
const { version: version2 } = parsed;
|
|
30771
|
+
if (typeof version2 === "string" && version2.length > 0) return version2;
|
|
30772
|
+
}
|
|
30773
|
+
} catch {
|
|
30774
|
+
}
|
|
30775
|
+
return UNKNOWN_VERSION;
|
|
30776
|
+
}
|
|
30777
|
+
var VERSION = readVersion();
|
|
30778
|
+
|
|
30190
30779
|
// src/mcp/tools.ts
|
|
30191
30780
|
import { readFile as readFile6 } from "fs/promises";
|
|
30192
30781
|
import { join as join12 } from "path";
|
|
@@ -30402,7 +30991,7 @@ async function discoverFromDirs(...directories) {
|
|
|
30402
30991
|
}
|
|
30403
30992
|
|
|
30404
30993
|
// src/utils/workspaces.ts
|
|
30405
|
-
import { existsSync as existsSync6, readdirSync as
|
|
30994
|
+
import { existsSync as existsSync6, readdirSync as readdirSync3, readFileSync as readFileSync3, statSync as statSync2 } from "fs";
|
|
30406
30995
|
import { basename, dirname as dirname3, join as join11, resolve as resolve4 } from "path";
|
|
30407
30996
|
|
|
30408
30997
|
// src/utils/discover.ts
|
|
@@ -30430,14 +31019,14 @@ function findMonorepoRoot(startDir, boundary) {
|
|
|
30430
31019
|
for (; ; ) {
|
|
30431
31020
|
const pnpmWorkspace = join11(current, "pnpm-workspace.yaml");
|
|
30432
31021
|
if (existsSync6(pnpmWorkspace)) {
|
|
30433
|
-
const patterns = parsePnpmWorkspaceYaml(
|
|
31022
|
+
const patterns = parsePnpmWorkspaceYaml(readFileSync3(pnpmWorkspace, "utf-8"));
|
|
30434
31023
|
if (patterns.length > 0) {
|
|
30435
31024
|
return { root: current, patterns };
|
|
30436
31025
|
}
|
|
30437
31026
|
}
|
|
30438
31027
|
const pkgJson = join11(current, "package.json");
|
|
30439
31028
|
if (existsSync6(pkgJson)) {
|
|
30440
|
-
const patterns = parsePackageJsonWorkspaces(
|
|
31029
|
+
const patterns = parsePackageJsonWorkspaces(readFileSync3(pkgJson, "utf-8"));
|
|
30441
31030
|
if (patterns.length > 0) {
|
|
30442
31031
|
return { root: current, patterns };
|
|
30443
31032
|
}
|
|
@@ -30493,7 +31082,7 @@ function expandPattern(monorepoRoot, pattern) {
|
|
|
30493
31082
|
const parentRel = trimmed.slice(0, -2);
|
|
30494
31083
|
const parent = join11(monorepoRoot, parentRel);
|
|
30495
31084
|
if (!existsSync6(parent)) return [];
|
|
30496
|
-
return
|
|
31085
|
+
return readdirSync3(parent).map((entry) => join11(parent, entry)).filter((path) => {
|
|
30497
31086
|
try {
|
|
30498
31087
|
return statSync2(path).isDirectory();
|
|
30499
31088
|
} catch {
|
|
@@ -30882,7 +31471,7 @@ async function startMcpServer(workspaces, defaultWorkspace) {
|
|
|
30882
31471
|
const server = new Server(
|
|
30883
31472
|
{
|
|
30884
31473
|
name: "rafters",
|
|
30885
|
-
version:
|
|
31474
|
+
version: VERSION
|
|
30886
31475
|
},
|
|
30887
31476
|
{
|
|
30888
31477
|
capabilities: {
|
|
@@ -31678,7 +32267,7 @@ async function studio() {
|
|
|
31678
32267
|
|
|
31679
32268
|
// src/index.ts
|
|
31680
32269
|
var program = new Command();
|
|
31681
|
-
program.name("rafters").description("Design system CLI - scaffold tokens and serve MCP").version(
|
|
32270
|
+
program.name("rafters").description("Design system CLI - scaffold tokens and serve MCP").version(VERSION);
|
|
31682
32271
|
program.command("init").description("Initialize .rafters/ with default tokens and config").option("-r, --rebuild", "Regenerate output files from existing tokens").option("--reset", "Re-run generators fresh, replacing persisted tokens").option(
|
|
31683
32272
|
"--framework <name>",
|
|
31684
32273
|
"Override framework detection (next|vite|remix|react-router|astro|wc|vanilla)"
|