rafters 0.0.77 → 0.0.79
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 +1211 -705
- 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) {
|
|
969
|
+
sections.push("");
|
|
970
|
+
sections.push(typographyThemeInline);
|
|
971
|
+
}
|
|
972
|
+
const typographyTsUtility = generateTypographyCompositeUtility(groups["typography-composite"]);
|
|
973
|
+
if (typographyTsUtility) {
|
|
851
974
|
sections.push("");
|
|
852
|
-
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);
|
|
@@ -1306,10 +1443,12 @@ var DEFAULT_SYSTEM_CONFIG = {
|
|
|
1306
1443
|
// 1.2 ratio
|
|
1307
1444
|
fontFamily: "'Noto Sans Variable', sans-serif",
|
|
1308
1445
|
monoFontFamily: "ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospace",
|
|
1309
|
-
// Rafters aesthetic overrides
|
|
1446
|
+
// Rafters aesthetic overrides.
|
|
1447
|
+
// baseRadius and focusRingWidth have NO pin here -- they derive from
|
|
1448
|
+
// baseSpacingUnit (×1.5 and ÷2), and at base 4 the derivation already
|
|
1449
|
+
// produces 6 and 2. A pin would hide the derivation, which is the #2031
|
|
1450
|
+
// defect one layer down.
|
|
1310
1451
|
baseFontSizeOverride: 16,
|
|
1311
|
-
baseRadiusOverride: 6,
|
|
1312
|
-
focusRingWidthOverride: 2,
|
|
1313
1452
|
baseTransitionDurationOverride: 150
|
|
1314
1453
|
};
|
|
1315
1454
|
var COLOR_SCALE_POSITIONS = [
|
|
@@ -1325,42 +1464,6 @@ var COLOR_SCALE_POSITIONS = [
|
|
|
1325
1464
|
"900",
|
|
1326
1465
|
"950"
|
|
1327
1466
|
];
|
|
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
1467
|
var TYPOGRAPHY_SCALE = [
|
|
1365
1468
|
"xs",
|
|
1366
1469
|
"sm",
|
|
@@ -4468,7 +4571,7 @@ function range(color1, color2, options = {}) {
|
|
|
4468
4571
|
let [r, options2] = [color1, color2];
|
|
4469
4572
|
return range(...r.rangeArgs.colors, { ...r.rangeArgs.options, ...options2 });
|
|
4470
4573
|
}
|
|
4471
|
-
let { space, outputSpace, progression
|
|
4574
|
+
let { space, outputSpace, progression, premultiplied } = options;
|
|
4472
4575
|
color1 = getColor(color1);
|
|
4473
4576
|
color2 = getColor(color2);
|
|
4474
4577
|
color1 = clone(color1);
|
|
@@ -4502,7 +4605,7 @@ function range(color1, color2, options = {}) {
|
|
|
4502
4605
|
color2.coords = color2.coords.map((c4) => c4 * color2.alpha);
|
|
4503
4606
|
}
|
|
4504
4607
|
return Object.assign((p2) => {
|
|
4505
|
-
p2 =
|
|
4608
|
+
p2 = progression ? progression(p2) : p2;
|
|
4506
4609
|
let coords = color1.coords.map((start, i) => {
|
|
4507
4610
|
let end = color2.coords[i];
|
|
4508
4611
|
return interpolate(start, end, p2);
|
|
@@ -21891,6 +21994,8 @@ var BindingSchema = external_exports.object({
|
|
|
21891
21994
|
plugin: external_exports.string(),
|
|
21892
21995
|
input: external_exports.unknown()
|
|
21893
21996
|
});
|
|
21997
|
+
var OVERRIDE_KINDS = ["baseline", "preset", "designer"];
|
|
21998
|
+
var OverrideKindSchema = external_exports.enum(OVERRIDE_KINDS);
|
|
21894
21999
|
var TokenSchema = external_exports.object({
|
|
21895
22000
|
// Core token data
|
|
21896
22001
|
name: external_exports.string(),
|
|
@@ -21929,7 +22034,13 @@ var TokenSchema = external_exports.object({
|
|
|
21929
22034
|
// Why was this overridden
|
|
21930
22035
|
reason: external_exports.string(),
|
|
21931
22036
|
// Additional context (e.g. "Q1 marketing campaign", "accessibility audit")
|
|
21932
|
-
context: external_exports.string().optional()
|
|
22037
|
+
context: external_exports.string().optional(),
|
|
22038
|
+
// Who attributed the value. The reason string is for humans; kind is what
|
|
22039
|
+
// machines branch on (preset application skips kind === 'designer').
|
|
22040
|
+
// Optional and never defaulted: absent means the provenance is unknown,
|
|
22041
|
+
// which is the honest state of every override written before this field
|
|
22042
|
+
// existed.
|
|
22043
|
+
kind: OverrideKindSchema.optional()
|
|
21933
22044
|
}).nullable(),
|
|
21934
22045
|
// Computed value from generation rule (before any override)
|
|
21935
22046
|
// Stored so agents can see what the system WOULD produce vs what human chose
|
|
@@ -22589,42 +22700,48 @@ var DEFAULT_SHADOW_DEFINITIONS = {
|
|
|
22589
22700
|
};
|
|
22590
22701
|
var DEFAULT_DURATION_DEFINITIONS = {
|
|
22591
22702
|
instant: {
|
|
22592
|
-
|
|
22703
|
+
range: [0, 0],
|
|
22704
|
+
default: 0,
|
|
22593
22705
|
band: "",
|
|
22594
22706
|
meaning: "No perceptible transition. Cursor changes, text selection, badge counts. Below all perception -- there is nothing to track, so nothing is communicated.",
|
|
22595
22707
|
contexts: ["disabled-motion", "prefers-reduced-motion", "cursor", "badge-count"],
|
|
22596
22708
|
motionIntent: "transition"
|
|
22597
22709
|
},
|
|
22598
22710
|
micro: {
|
|
22599
|
-
|
|
22711
|
+
range: [50, 120],
|
|
22712
|
+
default: 100,
|
|
22600
22713
|
band: "at the instantaneous threshold (Nielsen 0.1s)",
|
|
22601
22714
|
meaning: "Immediate but visible. Focus rings and press feedback. At the instantaneous threshold -- acknowledgment that input landed, not communication of a change.",
|
|
22602
22715
|
contexts: ["focus", "press", "micro-feedback"],
|
|
22603
22716
|
motionIntent: "transition"
|
|
22604
22717
|
},
|
|
22605
22718
|
fast: {
|
|
22606
|
-
|
|
22719
|
+
range: [120, 200],
|
|
22720
|
+
default: 150,
|
|
22607
22721
|
band: "below the communicative window",
|
|
22608
22722
|
meaning: "Hover states. The cursor is already there, so the response must match its speed. Below the communicative window -- acknowledgment, not communication.",
|
|
22609
22723
|
contexts: ["hover", "micro-feedback"],
|
|
22610
22724
|
motionIntent: "transition"
|
|
22611
22725
|
},
|
|
22612
22726
|
moderate: {
|
|
22613
|
-
|
|
22727
|
+
range: [200, 300],
|
|
22728
|
+
default: 250,
|
|
22614
22729
|
band: "communicative (~200-300ms)",
|
|
22615
22730
|
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.",
|
|
22616
22731
|
contexts: ["dropdowns", "tab-switches", "small-reveals"],
|
|
22617
22732
|
motionIntent: "transition"
|
|
22618
22733
|
},
|
|
22619
22734
|
normal: {
|
|
22620
|
-
|
|
22735
|
+
range: [300, 400],
|
|
22736
|
+
default: 350,
|
|
22621
22737
|
band: "communicative, larger movement",
|
|
22622
22738
|
meaning: "The workhorse -- modal entrances, toggles, standard state transitions. The communicative window for larger movement.",
|
|
22623
22739
|
contexts: ["modals", "toggles", "state-changes"],
|
|
22624
22740
|
motionIntent: "enter"
|
|
22625
22741
|
},
|
|
22626
22742
|
slow: {
|
|
22627
|
-
|
|
22743
|
+
range: [400, 500],
|
|
22744
|
+
default: 500,
|
|
22628
22745
|
band: "at the sluggish boundary",
|
|
22629
22746
|
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.",
|
|
22630
22747
|
contexts: ["sheets", "page-transitions", "large-spatial-movement"],
|
|
@@ -22633,10 +22750,10 @@ var DEFAULT_DURATION_DEFINITIONS = {
|
|
|
22633
22750
|
};
|
|
22634
22751
|
var DEFAULT_EASING_DEFINITIONS = {
|
|
22635
22752
|
standard: {
|
|
22636
|
-
curve: [0.
|
|
22637
|
-
meaning: "Precision --
|
|
22753
|
+
curve: [0.4, 0, 0.2, 1],
|
|
22754
|
+
meaning: "Precision -- a responsive start that decelerates into place, engineered rather than thrown. The general-purpose workhorse for state transitions and hover: the fast start matches a cursor already on target, where a symmetric ease would drag.",
|
|
22638
22755
|
contexts: ["state-changes", "hover", "general-purpose"],
|
|
22639
|
-
css: "cubic-bezier(0.
|
|
22756
|
+
css: "cubic-bezier(0.4, 0, 0.2, 1)"
|
|
22640
22757
|
},
|
|
22641
22758
|
enter: {
|
|
22642
22759
|
curve: [0, 0, 0.2, 1],
|
|
@@ -22669,10 +22786,307 @@ var DEFAULT_EASING_DEFINITIONS = {
|
|
|
22669
22786
|
css: "cubic-bezier(0.2, 0.8, 0.2, 1)"
|
|
22670
22787
|
}
|
|
22671
22788
|
};
|
|
22789
|
+
var DEFAULT_KEYFRAME_DEFINITIONS = {
|
|
22790
|
+
"fade-in": {
|
|
22791
|
+
css: () => "from { opacity: 0; } to { opacity: 1; }",
|
|
22792
|
+
meaning: "Fade from transparent to opaque",
|
|
22793
|
+
contexts: ["enter", "appear", "show"]
|
|
22794
|
+
},
|
|
22795
|
+
"fade-out": {
|
|
22796
|
+
css: () => "from { opacity: 1; } to { opacity: 0; }",
|
|
22797
|
+
meaning: "Fade from opaque to transparent",
|
|
22798
|
+
contexts: ["exit", "disappear", "hide"]
|
|
22799
|
+
},
|
|
22800
|
+
"slide-in-from-top": {
|
|
22801
|
+
css: () => "from { transform: translateY(-100%); } to { transform: translateY(0); }",
|
|
22802
|
+
meaning: "Slide in from above",
|
|
22803
|
+
contexts: ["dropdown", "notification", "toast"]
|
|
22804
|
+
},
|
|
22805
|
+
"slide-in-from-bottom": {
|
|
22806
|
+
css: () => "from { transform: translateY(100%); } to { transform: translateY(0); }",
|
|
22807
|
+
meaning: "Slide in from below",
|
|
22808
|
+
contexts: ["sheet", "drawer", "mobile-menu"]
|
|
22809
|
+
},
|
|
22810
|
+
"slide-in-from-left": {
|
|
22811
|
+
css: () => "from { transform: translateX(-100%); } to { transform: translateX(0); }",
|
|
22812
|
+
meaning: "Slide in from left",
|
|
22813
|
+
contexts: ["sidebar", "panel", "drawer"]
|
|
22814
|
+
},
|
|
22815
|
+
"slide-in-from-right": {
|
|
22816
|
+
css: () => "from { transform: translateX(100%); } to { transform: translateX(0); }",
|
|
22817
|
+
meaning: "Slide in from right",
|
|
22818
|
+
contexts: ["sidebar", "panel", "drawer"]
|
|
22819
|
+
},
|
|
22820
|
+
"slide-out-to-top": {
|
|
22821
|
+
css: () => "from { transform: translateY(0); } to { transform: translateY(-100%); }",
|
|
22822
|
+
meaning: "Slide out upward",
|
|
22823
|
+
contexts: ["dropdown-exit", "notification-dismiss"]
|
|
22824
|
+
},
|
|
22825
|
+
"slide-out-to-bottom": {
|
|
22826
|
+
css: () => "from { transform: translateY(0); } to { transform: translateY(100%); }",
|
|
22827
|
+
meaning: "Slide out downward",
|
|
22828
|
+
contexts: ["sheet-exit", "drawer-close"]
|
|
22829
|
+
},
|
|
22830
|
+
"slide-out-to-left": {
|
|
22831
|
+
css: () => "from { transform: translateX(0); } to { transform: translateX(-100%); }",
|
|
22832
|
+
meaning: "Slide out to left",
|
|
22833
|
+
contexts: ["sidebar-close", "panel-exit"]
|
|
22834
|
+
},
|
|
22835
|
+
"slide-out-to-right": {
|
|
22836
|
+
css: () => "from { transform: translateX(0); } to { transform: translateX(100%); }",
|
|
22837
|
+
meaning: "Slide out to right",
|
|
22838
|
+
contexts: ["sidebar-close", "panel-exit"]
|
|
22839
|
+
},
|
|
22840
|
+
"scale-in": {
|
|
22841
|
+
css: () => "from { transform: scale(var(--rafters-extent-pop)); opacity: 0; } to { transform: scale(1); opacity: 1; }",
|
|
22842
|
+
meaning: "Scale up while fading in",
|
|
22843
|
+
contexts: ["modal", "popover", "dialog"]
|
|
22844
|
+
},
|
|
22845
|
+
"scale-out": {
|
|
22846
|
+
css: () => "from { transform: scale(1); opacity: 1; } to { transform: scale(var(--rafters-extent-pop)); opacity: 0; }",
|
|
22847
|
+
meaning: "Scale down while fading out",
|
|
22848
|
+
contexts: ["modal-exit", "popover-close"]
|
|
22849
|
+
},
|
|
22850
|
+
spin: {
|
|
22851
|
+
css: () => "from { transform: rotate(0deg); } to { transform: rotate(360deg); }",
|
|
22852
|
+
meaning: "Continuous rotation",
|
|
22853
|
+
contexts: ["loading", "spinner", "refresh"]
|
|
22854
|
+
},
|
|
22855
|
+
ping: {
|
|
22856
|
+
css: (ctx) => `75%, 100% { transform: scale(${ctx.pingScale}); opacity: 0; }`,
|
|
22857
|
+
meaning: "Expanding pulse that fades out",
|
|
22858
|
+
contexts: ["notification-badge", "attention", "pulse"]
|
|
22859
|
+
},
|
|
22860
|
+
pulse: {
|
|
22861
|
+
css: (ctx) => `0%, 100% { opacity: 1; } 50% { opacity: ${ctx.pulseOpacity}; }`,
|
|
22862
|
+
meaning: "Gentle opacity pulse",
|
|
22863
|
+
contexts: ["skeleton", "loading-placeholder"]
|
|
22864
|
+
},
|
|
22865
|
+
bounce: {
|
|
22866
|
+
// Inline beziers retained deliberately -- see the provenance note above.
|
|
22867
|
+
css: (ctx) => `0%, 100% { transform: translateY(-${ctx.bouncePercent}%); animation-timing-function: cubic-bezier(0.8, 0, 1, 1); } 50% { transform: translateY(0); animation-timing-function: cubic-bezier(0, 0, 0.2, 1); }`,
|
|
22868
|
+
meaning: "Bouncing motion",
|
|
22869
|
+
contexts: ["attention", "scroll-indicator"]
|
|
22870
|
+
},
|
|
22871
|
+
"caret-blink": {
|
|
22872
|
+
css: () => "0%, 70%, 100% { opacity: 1; } 20%, 50% { opacity: 0; }",
|
|
22873
|
+
meaning: "Text cursor blinking",
|
|
22874
|
+
contexts: ["input-caret", "text-cursor"]
|
|
22875
|
+
}
|
|
22876
|
+
};
|
|
22877
|
+
var DEFAULT_ANIMATION_DEFINITIONS = {
|
|
22878
|
+
"fade-in": {
|
|
22879
|
+
keyframe: "fade-in",
|
|
22880
|
+
duration: { tier: "fast" },
|
|
22881
|
+
curve: "enter",
|
|
22882
|
+
meaning: "Fade in animation",
|
|
22883
|
+
contexts: ["enter", "appear"]
|
|
22884
|
+
},
|
|
22885
|
+
"fade-out": {
|
|
22886
|
+
keyframe: "fade-out",
|
|
22887
|
+
duration: { tier: "fast" },
|
|
22888
|
+
curve: "exit",
|
|
22889
|
+
meaning: "Fade out animation",
|
|
22890
|
+
contexts: ["exit", "disappear"]
|
|
22891
|
+
},
|
|
22892
|
+
"slide-in-from-top": {
|
|
22893
|
+
keyframe: "slide-in-from-top",
|
|
22894
|
+
duration: { tier: "normal" },
|
|
22895
|
+
curve: "enter",
|
|
22896
|
+
meaning: "Slide in from top",
|
|
22897
|
+
contexts: ["dropdown", "notification"]
|
|
22898
|
+
},
|
|
22899
|
+
"slide-in-from-bottom": {
|
|
22900
|
+
keyframe: "slide-in-from-bottom",
|
|
22901
|
+
duration: { tier: "normal" },
|
|
22902
|
+
curve: "enter",
|
|
22903
|
+
meaning: "Slide in from bottom",
|
|
22904
|
+
contexts: ["sheet", "drawer"]
|
|
22905
|
+
},
|
|
22906
|
+
"slide-in-from-left": {
|
|
22907
|
+
keyframe: "slide-in-from-left",
|
|
22908
|
+
duration: { tier: "normal" },
|
|
22909
|
+
curve: "enter",
|
|
22910
|
+
meaning: "Slide in from left",
|
|
22911
|
+
contexts: ["sidebar", "panel"]
|
|
22912
|
+
},
|
|
22913
|
+
"slide-in-from-right": {
|
|
22914
|
+
keyframe: "slide-in-from-right",
|
|
22915
|
+
duration: { tier: "normal" },
|
|
22916
|
+
curve: "enter",
|
|
22917
|
+
meaning: "Slide in from right",
|
|
22918
|
+
contexts: ["sidebar", "panel"]
|
|
22919
|
+
},
|
|
22920
|
+
"slide-out-to-top": {
|
|
22921
|
+
keyframe: "slide-out-to-top",
|
|
22922
|
+
duration: { tier: "fast" },
|
|
22923
|
+
curve: "exit",
|
|
22924
|
+
meaning: "Slide out to top",
|
|
22925
|
+
contexts: ["dropdown-exit"]
|
|
22926
|
+
},
|
|
22927
|
+
"slide-out-to-bottom": {
|
|
22928
|
+
keyframe: "slide-out-to-bottom",
|
|
22929
|
+
duration: { tier: "fast" },
|
|
22930
|
+
curve: "exit",
|
|
22931
|
+
meaning: "Slide out to bottom",
|
|
22932
|
+
contexts: ["sheet-exit"]
|
|
22933
|
+
},
|
|
22934
|
+
"slide-out-to-left": {
|
|
22935
|
+
keyframe: "slide-out-to-left",
|
|
22936
|
+
duration: { tier: "fast" },
|
|
22937
|
+
curve: "exit",
|
|
22938
|
+
meaning: "Slide out to left",
|
|
22939
|
+
contexts: ["sidebar-close"]
|
|
22940
|
+
},
|
|
22941
|
+
"slide-out-to-right": {
|
|
22942
|
+
keyframe: "slide-out-to-right",
|
|
22943
|
+
duration: { tier: "fast" },
|
|
22944
|
+
curve: "exit",
|
|
22945
|
+
meaning: "Slide out to right",
|
|
22946
|
+
contexts: ["sidebar-close"]
|
|
22947
|
+
},
|
|
22948
|
+
"scale-in": {
|
|
22949
|
+
keyframe: "scale-in",
|
|
22950
|
+
duration: { tier: "normal" },
|
|
22951
|
+
curve: "spring-snappy",
|
|
22952
|
+
meaning: "Scale in with spring",
|
|
22953
|
+
contexts: ["modal", "popover"]
|
|
22954
|
+
},
|
|
22955
|
+
"scale-out": {
|
|
22956
|
+
keyframe: "scale-out",
|
|
22957
|
+
duration: { tier: "fast" },
|
|
22958
|
+
curve: "exit",
|
|
22959
|
+
meaning: "Scale out",
|
|
22960
|
+
contexts: ["modal-exit"]
|
|
22961
|
+
},
|
|
22962
|
+
spin: {
|
|
22963
|
+
keyframe: "spin",
|
|
22964
|
+
duration: { loopPeriod: "1s" },
|
|
22965
|
+
curve: "linear",
|
|
22966
|
+
iterations: "infinite",
|
|
22967
|
+
meaning: "Continuous spin",
|
|
22968
|
+
contexts: ["loading", "spinner"]
|
|
22969
|
+
},
|
|
22970
|
+
ping: {
|
|
22971
|
+
keyframe: "ping",
|
|
22972
|
+
duration: { loopPeriod: "1s" },
|
|
22973
|
+
curve: "enter",
|
|
22974
|
+
iterations: "infinite",
|
|
22975
|
+
meaning: "Pinging pulse",
|
|
22976
|
+
contexts: ["notification"]
|
|
22977
|
+
},
|
|
22978
|
+
pulse: {
|
|
22979
|
+
keyframe: "pulse",
|
|
22980
|
+
duration: { loopPeriod: "2s" },
|
|
22981
|
+
curve: "standard",
|
|
22982
|
+
iterations: "infinite",
|
|
22983
|
+
meaning: "Gentle pulse",
|
|
22984
|
+
contexts: ["skeleton", "loading"]
|
|
22985
|
+
},
|
|
22986
|
+
bounce: {
|
|
22987
|
+
keyframe: "bounce",
|
|
22988
|
+
duration: { loopPeriod: "1s" },
|
|
22989
|
+
curve: "standard",
|
|
22990
|
+
iterations: "infinite",
|
|
22991
|
+
meaning: "Bouncing",
|
|
22992
|
+
contexts: ["attention"]
|
|
22993
|
+
},
|
|
22994
|
+
"caret-blink": {
|
|
22995
|
+
keyframe: "caret-blink",
|
|
22996
|
+
duration: { loopPeriod: "1.25s" },
|
|
22997
|
+
curve: "enter",
|
|
22998
|
+
iterations: "infinite",
|
|
22999
|
+
meaning: "Caret blinking",
|
|
23000
|
+
contexts: ["input"]
|
|
23001
|
+
}
|
|
23002
|
+
};
|
|
23003
|
+
var DEFAULT_MOTION_CELL_ANIMATIONS = {
|
|
23004
|
+
"dialog-content-open": {
|
|
23005
|
+
keyframe: "scale-in",
|
|
23006
|
+
tier: "normal",
|
|
23007
|
+
curve: "enter",
|
|
23008
|
+
cell: { component: "dialog", part: "content", transition: "closed -> open" },
|
|
23009
|
+
meaning: "A dialog arriving: fade + zoom from the pop extent, on the arrival curve.",
|
|
23010
|
+
contexts: ["dialog", "modal", "alert-dialog"]
|
|
23011
|
+
},
|
|
23012
|
+
"dialog-content-close": {
|
|
23013
|
+
keyframe: "scale-out",
|
|
23014
|
+
tier: "moderate",
|
|
23015
|
+
curve: "exit",
|
|
23016
|
+
cell: { component: "dialog", part: "content", transition: "open -> closed" },
|
|
23017
|
+
meaning: "A dialog leaving: fade + zoom back to the pop extent, on the departure curve.",
|
|
23018
|
+
contexts: ["dialog", "modal", "alert-dialog"]
|
|
23019
|
+
},
|
|
23020
|
+
"popover-content-open": {
|
|
23021
|
+
keyframe: "scale-in",
|
|
23022
|
+
tier: "moderate",
|
|
23023
|
+
curve: "enter",
|
|
23024
|
+
cell: { component: "popover", part: "content", transition: "closed -> open" },
|
|
23025
|
+
meaning: "A popover arriving: smaller and nearer than a dialog, so one tier quicker.",
|
|
23026
|
+
contexts: ["popover", "anchored-popup"]
|
|
23027
|
+
},
|
|
23028
|
+
"popover-content-close": {
|
|
23029
|
+
keyframe: "scale-out",
|
|
23030
|
+
tier: "fast",
|
|
23031
|
+
curve: "exit",
|
|
23032
|
+
cell: { component: "popover", part: "content", transition: "open -> closed" },
|
|
23033
|
+
meaning: "A popover leaving: the user already chose to dismiss it.",
|
|
23034
|
+
contexts: ["popover", "anchored-popup"]
|
|
23035
|
+
},
|
|
23036
|
+
"dropdown-menu-content-open": {
|
|
23037
|
+
keyframe: "scale-in",
|
|
23038
|
+
tier: "moderate",
|
|
23039
|
+
curve: "enter",
|
|
23040
|
+
cell: { component: "dropdown-menu", part: "content", transition: "closed -> open" },
|
|
23041
|
+
meaning: "A menu arriving: same anchored-popup moment as popover, declared separately.",
|
|
23042
|
+
contexts: ["dropdown-menu", "menu", "anchored-popup"]
|
|
23043
|
+
},
|
|
23044
|
+
"dropdown-menu-content-close": {
|
|
23045
|
+
keyframe: "scale-out",
|
|
23046
|
+
tier: "fast",
|
|
23047
|
+
curve: "exit",
|
|
23048
|
+
cell: { component: "dropdown-menu", part: "content", transition: "open -> closed" },
|
|
23049
|
+
meaning: "A menu leaving, after a choice or a dismissal.",
|
|
23050
|
+
contexts: ["dropdown-menu", "menu", "anchored-popup"]
|
|
23051
|
+
}
|
|
23052
|
+
};
|
|
23053
|
+
var DEFAULT_MOTION_COMPOSITE_PRESETS = {
|
|
23054
|
+
"motion-fade-in": {
|
|
23055
|
+
durationTier: "fast",
|
|
23056
|
+
curve: "enter",
|
|
23057
|
+
meaning: "Fade in animation preset",
|
|
23058
|
+
contexts: ["fade-in", "appear"]
|
|
23059
|
+
},
|
|
23060
|
+
"motion-fade-out": {
|
|
23061
|
+
durationTier: "fast",
|
|
23062
|
+
curve: "exit",
|
|
23063
|
+
meaning: "Fade out animation preset",
|
|
23064
|
+
contexts: ["fade-out", "disappear"]
|
|
23065
|
+
},
|
|
23066
|
+
"motion-slide-in": {
|
|
23067
|
+
durationTier: "normal",
|
|
23068
|
+
curve: "enter",
|
|
23069
|
+
meaning: "Slide in animation preset",
|
|
23070
|
+
contexts: ["slide-in", "panel-enter", "modal-enter"]
|
|
23071
|
+
},
|
|
23072
|
+
"motion-slide-out": {
|
|
23073
|
+
durationTier: "fast",
|
|
23074
|
+
curve: "exit",
|
|
23075
|
+
meaning: "Slide out animation preset",
|
|
23076
|
+
contexts: ["slide-out", "panel-exit", "modal-exit"]
|
|
23077
|
+
},
|
|
23078
|
+
"motion-scale-in": {
|
|
23079
|
+
durationTier: "normal",
|
|
23080
|
+
curve: "spring-snappy",
|
|
23081
|
+
meaning: "Scale in with spring animation",
|
|
23082
|
+
contexts: ["pop-in", "button-press", "emphasis"]
|
|
23083
|
+
}
|
|
23084
|
+
};
|
|
22672
23085
|
var DEFAULT_MOTION_SEMANTIC_MAPPINGS = {
|
|
22673
23086
|
hover: {
|
|
22674
23087
|
properties: ["color", "background-color", "border-color"],
|
|
22675
|
-
|
|
23088
|
+
travel: "none",
|
|
23089
|
+
band: "fast",
|
|
22676
23090
|
curve: "standard",
|
|
22677
23091
|
reducedMotion: null,
|
|
22678
23092
|
category: "interaction",
|
|
@@ -22682,7 +23096,8 @@ var DEFAULT_MOTION_SEMANTIC_MAPPINGS = {
|
|
|
22682
23096
|
},
|
|
22683
23097
|
focus: {
|
|
22684
23098
|
properties: ["box-shadow", "outline-color"],
|
|
22685
|
-
|
|
23099
|
+
travel: "none",
|
|
23100
|
+
band: "micro",
|
|
22686
23101
|
curve: "linear",
|
|
22687
23102
|
reducedMotion: null,
|
|
22688
23103
|
category: "interaction",
|
|
@@ -22692,7 +23107,8 @@ var DEFAULT_MOTION_SEMANTIC_MAPPINGS = {
|
|
|
22692
23107
|
},
|
|
22693
23108
|
press: {
|
|
22694
23109
|
properties: ["transform", "color", "background-color"],
|
|
22695
|
-
|
|
23110
|
+
travel: "none",
|
|
23111
|
+
band: "micro",
|
|
22696
23112
|
curve: "spring-snappy",
|
|
22697
23113
|
reducedMotion: { properties: ["color", "background-color"] },
|
|
22698
23114
|
category: "interaction",
|
|
@@ -22702,18 +23118,25 @@ var DEFAULT_MOTION_SEMANTIC_MAPPINGS = {
|
|
|
22702
23118
|
},
|
|
22703
23119
|
toggle: {
|
|
22704
23120
|
properties: ["color", "background-color", "transform"],
|
|
22705
|
-
|
|
22706
|
-
|
|
23121
|
+
travel: "none",
|
|
23122
|
+
band: "moderate",
|
|
23123
|
+
// `standard`, not `spring-snappy`. The 30-site study found 29 of 30 sites
|
|
23124
|
+
// carry zero overshoot curves, and the one that does is the friendly
|
|
23125
|
+
// exemplar -- spring-snappy belongs to friendly and effectively nowhere
|
|
23126
|
+
// else. Efficient is the shipped default intent and is characterised as
|
|
23127
|
+
// zero-overshoot, so a spring here contradicts the intent it ships under.
|
|
23128
|
+
// Matches the recorded ruling: an efficient toggle is crisp; friendly is
|
|
23129
|
+
// the intent that springs a switch.
|
|
23130
|
+
curve: "standard",
|
|
22707
23131
|
reducedMotion: { properties: ["color", "background-color"] },
|
|
22708
23132
|
category: "interaction",
|
|
22709
|
-
sizeReasoning: "A thumb travelling a track is a small, tracked movement -- moderate tier
|
|
23133
|
+
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.",
|
|
22710
23134
|
meaning: "Toggle/switch state change. Shows the new state.",
|
|
22711
23135
|
contexts: ["switch", "toggle", "checkbox"]
|
|
22712
23136
|
},
|
|
22713
23137
|
"dropdown-in": {
|
|
22714
23138
|
properties: ["opacity", "transform"],
|
|
22715
|
-
|
|
22716
|
-
curve: "enter",
|
|
23139
|
+
travel: "short",
|
|
22717
23140
|
reducedMotion: { properties: ["opacity"], ms: 100 },
|
|
22718
23141
|
category: "enter",
|
|
22719
23142
|
sizeReasoning: "A dropdown is small and travels a short distance -- moderate tier, one step below the modal, with the arrival curve.",
|
|
@@ -22722,8 +23145,7 @@ var DEFAULT_MOTION_SEMANTIC_MAPPINGS = {
|
|
|
22722
23145
|
},
|
|
22723
23146
|
"dropdown-out": {
|
|
22724
23147
|
properties: ["opacity", "transform"],
|
|
22725
|
-
|
|
22726
|
-
curve: "exit",
|
|
23148
|
+
travel: "short",
|
|
22727
23149
|
reducedMotion: { properties: ["opacity"], ms: 100 },
|
|
22728
23150
|
category: "exit",
|
|
22729
23151
|
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.",
|
|
@@ -22732,8 +23154,7 @@ var DEFAULT_MOTION_SEMANTIC_MAPPINGS = {
|
|
|
22732
23154
|
},
|
|
22733
23155
|
"modal-in": {
|
|
22734
23156
|
properties: ["opacity", "transform"],
|
|
22735
|
-
|
|
22736
|
-
curve: "enter",
|
|
23157
|
+
travel: "medium",
|
|
22737
23158
|
reducedMotion: { properties: ["opacity"], ms: 150 },
|
|
22738
23159
|
category: "enter",
|
|
22739
23160
|
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.",
|
|
@@ -22742,8 +23163,7 @@ var DEFAULT_MOTION_SEMANTIC_MAPPINGS = {
|
|
|
22742
23163
|
},
|
|
22743
23164
|
"modal-out": {
|
|
22744
23165
|
properties: ["opacity", "transform"],
|
|
22745
|
-
|
|
22746
|
-
curve: "exit",
|
|
23166
|
+
travel: "medium",
|
|
22747
23167
|
reducedMotion: { properties: ["opacity"], ms: 150 },
|
|
22748
23168
|
category: "exit",
|
|
22749
23169
|
sizeReasoning: "The modal exit -- moderate tier (shorter than its normal entrance) with the departure curve.",
|
|
@@ -22752,18 +23172,16 @@ var DEFAULT_MOTION_SEMANTIC_MAPPINGS = {
|
|
|
22752
23172
|
},
|
|
22753
23173
|
"sheet-in": {
|
|
22754
23174
|
properties: ["transform"],
|
|
22755
|
-
|
|
22756
|
-
curve: "spring-smooth",
|
|
23175
|
+
travel: "large",
|
|
22757
23176
|
reducedMotion: { properties: ["opacity"], ms: 250 },
|
|
22758
23177
|
category: "enter",
|
|
22759
|
-
sizeReasoning: "A sheet is
|
|
23178
|
+
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.",
|
|
22760
23179
|
meaning: "Sheet/drawer entrance.",
|
|
22761
23180
|
contexts: ["sheet", "drawer", "side-panel"]
|
|
22762
23181
|
},
|
|
22763
23182
|
"sheet-out": {
|
|
22764
23183
|
properties: ["transform"],
|
|
22765
|
-
|
|
22766
|
-
curve: "exit",
|
|
23184
|
+
travel: "large",
|
|
22767
23185
|
reducedMotion: { properties: ["opacity"], ms: 250 },
|
|
22768
23186
|
category: "exit",
|
|
22769
23187
|
sizeReasoning: "The sheet exit -- normal tier (shorter than its slow entrance) with the departure curve.",
|
|
@@ -22772,8 +23190,7 @@ var DEFAULT_MOTION_SEMANTIC_MAPPINGS = {
|
|
|
22772
23190
|
},
|
|
22773
23191
|
expand: {
|
|
22774
23192
|
properties: ["grid-template-rows", "opacity"],
|
|
22775
|
-
|
|
22776
|
-
curve: "enter",
|
|
23193
|
+
travel: "medium",
|
|
22777
23194
|
reducedMotion: { properties: ["opacity"] },
|
|
22778
23195
|
category: "enter",
|
|
22779
23196
|
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.",
|
|
@@ -22782,8 +23199,7 @@ var DEFAULT_MOTION_SEMANTIC_MAPPINGS = {
|
|
|
22782
23199
|
},
|
|
22783
23200
|
collapse: {
|
|
22784
23201
|
properties: ["grid-template-rows", "opacity"],
|
|
22785
|
-
|
|
22786
|
-
curve: "exit",
|
|
23202
|
+
travel: "medium",
|
|
22787
23203
|
reducedMotion: { properties: ["opacity"] },
|
|
22788
23204
|
category: "exit",
|
|
22789
23205
|
sizeReasoning: "Content folding away -- moderate tier (shorter than its normal expansion) with the departure curve. Reduced motion snaps the rows.",
|
|
@@ -22792,20 +23208,103 @@ var DEFAULT_MOTION_SEMANTIC_MAPPINGS = {
|
|
|
22792
23208
|
},
|
|
22793
23209
|
page: {
|
|
22794
23210
|
properties: ["opacity", "transform"],
|
|
22795
|
-
|
|
22796
|
-
curve: "spring-smooth",
|
|
23211
|
+
travel: "large",
|
|
22797
23212
|
reducedMotion: { properties: ["opacity"], ms: 200 },
|
|
22798
23213
|
category: "enter",
|
|
22799
|
-
sizeReasoning: "A whole-view transition --
|
|
23214
|
+
sizeReasoning: "A whole-view transition -- normal tier with the physical settle of a smooth spring, because the user reorients across a large distance.",
|
|
22800
23215
|
meaning: "Page/route transition.",
|
|
22801
23216
|
contexts: ["page-transition", "route-change", "view-switch"]
|
|
22802
23217
|
}
|
|
22803
23218
|
};
|
|
22804
|
-
var
|
|
22805
|
-
|
|
22806
|
-
|
|
22807
|
-
|
|
22808
|
-
|
|
23219
|
+
var DEFAULT_DELAY_NAMESPACE = {
|
|
23220
|
+
"hover-intent": {
|
|
23221
|
+
value: "200ms",
|
|
23222
|
+
provenance: "observed",
|
|
23223
|
+
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.",
|
|
23224
|
+
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.",
|
|
23225
|
+
contexts: ["tooltip", "hover-card", "navigation-menu"]
|
|
23226
|
+
},
|
|
23227
|
+
linger: {
|
|
23228
|
+
value: "300ms",
|
|
23229
|
+
provenance: "proposed",
|
|
23230
|
+
note: "PROPOSED. The grace window before a hovered surface closes, so a diagonal cursor path to a submenu does not dismiss it.",
|
|
23231
|
+
meaning: "How long a surface stays after the pointer leaves, so a near-miss is forgiven.",
|
|
23232
|
+
contexts: ["hover-card", "navigation-menu", "submenu"]
|
|
23233
|
+
},
|
|
23234
|
+
"choreo-step": {
|
|
23235
|
+
value: "50ms",
|
|
23236
|
+
provenance: "proposed",
|
|
23237
|
+
note: "PROPOSED. The offset between two parts of ONE surface moving together (panel then its content).",
|
|
23238
|
+
meaning: "The beat between choreographed parts of a single surface.",
|
|
23239
|
+
contexts: ["modal-content", "panel-content", "sequenced-parts"]
|
|
23240
|
+
},
|
|
23241
|
+
"stagger-step": {
|
|
23242
|
+
value: "0ms",
|
|
23243
|
+
provenance: "proposed",
|
|
23244
|
+
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.",
|
|
23245
|
+
meaning: "The per-item offset when a list animates in.",
|
|
23246
|
+
contexts: ["staggered-lists", "sequential-elements"]
|
|
23247
|
+
},
|
|
23248
|
+
skip: {
|
|
23249
|
+
value: "300ms",
|
|
23250
|
+
provenance: "proposed",
|
|
23251
|
+
note: "PROPOSED. The warm-reopen window: reopen inside it and the entrance delay is skipped, because the user is already oriented.",
|
|
23252
|
+
meaning: "How long a just-closed surface stays warm enough to reopen without ceremony.",
|
|
23253
|
+
contexts: ["tooltip-reopen", "menu-reopen"]
|
|
23254
|
+
}
|
|
23255
|
+
};
|
|
23256
|
+
var DEFAULT_EXTENT_NAMESPACE = {
|
|
23257
|
+
pop: {
|
|
23258
|
+
value: "0.95",
|
|
23259
|
+
provenance: "proposed",
|
|
23260
|
+
note: "PROPOSED. The scale a surface enters from. Close to 1 so the entrance reads as arrival rather than as a zoom.",
|
|
23261
|
+
meaning: "How far a surface scales up as it arrives.",
|
|
23262
|
+
contexts: ["modal", "popover", "dialog"]
|
|
23263
|
+
},
|
|
23264
|
+
press: {
|
|
23265
|
+
value: "0.97",
|
|
23266
|
+
provenance: "proposed",
|
|
23267
|
+
note: "PROPOSED. Depression under a press. Smaller than `pop` because the finger is the evidence -- the motion only confirms it.",
|
|
23268
|
+
meaning: "How far a control depresses when pressed.",
|
|
23269
|
+
contexts: ["button", "toggle", "press-feedback"]
|
|
23270
|
+
},
|
|
23271
|
+
draw: {
|
|
23272
|
+
value: "1",
|
|
23273
|
+
provenance: "proposed",
|
|
23274
|
+
note: "PROPOSED. The completed fraction of a drawn indicator. 1 is full travel; a value below it is a deliberately incomplete stroke.",
|
|
23275
|
+
meaning: "How far an indicator draws along its track.",
|
|
23276
|
+
contexts: ["tabs-indicator", "underline", "progress-stroke"]
|
|
23277
|
+
}
|
|
23278
|
+
};
|
|
23279
|
+
var DEFAULT_PERIOD_NAMESPACE = {
|
|
23280
|
+
spin: {
|
|
23281
|
+
value: "1s",
|
|
23282
|
+
provenance: "baseline",
|
|
23283
|
+
note: "The shipped loop period of the spin animation.",
|
|
23284
|
+
meaning: "One full rotation of a working indicator.",
|
|
23285
|
+
contexts: ["loading", "spinner", "refresh"]
|
|
23286
|
+
},
|
|
23287
|
+
pulse: {
|
|
23288
|
+
value: "2s",
|
|
23289
|
+
provenance: "baseline",
|
|
23290
|
+
note: "The shipped loop period of the pulse animation.",
|
|
23291
|
+
meaning: "One breath of a skeleton or placeholder.",
|
|
23292
|
+
contexts: ["skeleton", "loading-placeholder"]
|
|
23293
|
+
},
|
|
23294
|
+
blink: {
|
|
23295
|
+
value: "1.25s",
|
|
23296
|
+
provenance: "baseline",
|
|
23297
|
+
note: "The shipped loop period of the caret-blink animation.",
|
|
23298
|
+
meaning: "One blink of a text caret.",
|
|
23299
|
+
contexts: ["input-caret", "text-cursor"]
|
|
23300
|
+
},
|
|
23301
|
+
shimmer: {
|
|
23302
|
+
value: "2s",
|
|
23303
|
+
provenance: "proposed",
|
|
23304
|
+
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.",
|
|
23305
|
+
meaning: "One sweep of a shimmer across a loading surface.",
|
|
23306
|
+
contexts: ["skeleton", "loading-placeholder"]
|
|
23307
|
+
}
|
|
22809
23308
|
};
|
|
22810
23309
|
var DEFAULT_FOCUS_CONFIGS = {
|
|
22811
23310
|
default: {
|
|
@@ -22884,41 +23383,13 @@ var DEFAULT_RADIUS_DEFINITIONS = {
|
|
|
22884
23383
|
contexts: ["avatars", "pill-buttons", "circular-elements"]
|
|
22885
23384
|
}
|
|
22886
23385
|
};
|
|
22887
|
-
var
|
|
22888
|
-
|
|
22889
|
-
|
|
22890
|
-
|
|
22891
|
-
|
|
22892
|
-
|
|
22893
|
-
|
|
22894
|
-
"3": 3,
|
|
22895
|
-
"3.5": 3.5,
|
|
22896
|
-
"4": 4,
|
|
22897
|
-
"5": 5,
|
|
22898
|
-
"6": 6,
|
|
22899
|
-
"7": 7,
|
|
22900
|
-
"8": 8,
|
|
22901
|
-
"9": 9,
|
|
22902
|
-
"10": 10,
|
|
22903
|
-
"11": 11,
|
|
22904
|
-
"12": 12,
|
|
22905
|
-
"14": 14,
|
|
22906
|
-
"16": 16,
|
|
22907
|
-
"20": 20,
|
|
22908
|
-
"24": 24,
|
|
22909
|
-
"28": 28,
|
|
22910
|
-
"32": 32,
|
|
22911
|
-
"36": 36,
|
|
22912
|
-
"40": 40,
|
|
22913
|
-
"44": 44,
|
|
22914
|
-
"48": 48,
|
|
22915
|
-
"52": 52,
|
|
22916
|
-
"56": 56,
|
|
22917
|
-
"60": 60,
|
|
22918
|
-
"64": 64,
|
|
22919
|
-
"72": 72,
|
|
22920
|
-
"80": 80,
|
|
22921
|
-
"96": 96
|
|
23386
|
+
var DEFAULT_SPACING_BOUNDS = {
|
|
23387
|
+
floor: 1,
|
|
23388
|
+
ceiling: 96
|
|
23389
|
+
};
|
|
23390
|
+
var DEFAULT_SHADOW_BOUNDS = {
|
|
23391
|
+
floor: 1,
|
|
23392
|
+
ceiling: 96
|
|
22922
23393
|
};
|
|
22923
23394
|
var DEFAULT_TYPOGRAPHY_SCALE = {
|
|
22924
23395
|
xs: { step: -2, lineHeight: 1.5, letterSpacing: "0.025em" },
|
|
@@ -25020,25 +25491,23 @@ function generateDepthTokens(_config, depthDefs) {
|
|
|
25020
25491
|
}
|
|
25021
25492
|
|
|
25022
25493
|
// ../design-tokens/src/generators/focus.ts
|
|
25023
|
-
function pxToRem(px) {
|
|
25024
|
-
const rem = Math.round(px / 16 * 1e3) / 1e3;
|
|
25025
|
-
return `${rem}rem`;
|
|
25026
|
-
}
|
|
25027
25494
|
function generateFocusTokens(config2, focusConfigs) {
|
|
25028
25495
|
const tokens = [];
|
|
25029
25496
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
25030
|
-
const { focusRingWidth } = config2;
|
|
25031
|
-
const
|
|
25497
|
+
const { focusRingWidth, baseSpacingUnit } = config2;
|
|
25498
|
+
const focusDivisor = focusRingWidth > 0 ? Math.round(baseSpacingUnit / focusRingWidth * 1e3) / 1e3 : 2;
|
|
25499
|
+
const focusWidthValue = `calc(var(--rafters-spacing-base) / ${focusDivisor})`;
|
|
25032
25500
|
tokens.push({
|
|
25033
25501
|
name: "focus-ring-width",
|
|
25034
|
-
value:
|
|
25502
|
+
value: focusWidthValue,
|
|
25035
25503
|
category: "focus",
|
|
25036
25504
|
namespace: "focus",
|
|
25037
|
-
semanticMeaning: "Default focus ring width -
|
|
25505
|
+
semanticMeaning: "Default focus ring width - derives from spacing base",
|
|
25038
25506
|
usageContext: ["focus-indicators", "keyboard-navigation"],
|
|
25039
25507
|
accessibilityLevel: "AA",
|
|
25040
|
-
focusRingWidth:
|
|
25041
|
-
|
|
25508
|
+
focusRingWidth: focusWidthValue,
|
|
25509
|
+
dependsOn: ["spacing-base"],
|
|
25510
|
+
description: `Focus ring width = spacing-base / ${focusDivisor} (${focusRingWidth}px at base ${baseSpacingUnit}). WCAG 2.2 requires minimum 2px.`,
|
|
25042
25511
|
generatedAt: timestamp,
|
|
25043
25512
|
containerQueryAware: false,
|
|
25044
25513
|
userOverride: null,
|
|
@@ -25062,14 +25531,22 @@ function generateFocusTokens(config2, focusConfigs) {
|
|
|
25062
25531
|
highContrastMode: "Highlight",
|
|
25063
25532
|
userOverride: null
|
|
25064
25533
|
});
|
|
25534
|
+
const focusVar = "var(--rafters-focus-ring-width)";
|
|
25535
|
+
const focusCalc = (px) => {
|
|
25536
|
+
const mult = px / focusRingWidth;
|
|
25537
|
+
if (mult === 0) return "0";
|
|
25538
|
+
if (mult === 1) return focusVar;
|
|
25539
|
+
if (mult === -1) return `calc(${focusVar} * -1)`;
|
|
25540
|
+
return `calc(${focusVar} * ${mult})`;
|
|
25541
|
+
};
|
|
25065
25542
|
for (const [name, focusConfig] of Object.entries(focusConfigs)) {
|
|
25066
|
-
const
|
|
25067
|
-
const
|
|
25543
|
+
const widthVal = focusCalc(focusConfig.width);
|
|
25544
|
+
const offsetVal = focusCalc(focusConfig.offset);
|
|
25068
25545
|
tokens.push({
|
|
25069
25546
|
name: name === "default" ? "focus-ring" : `focus-ring-${name}`,
|
|
25070
25547
|
value: JSON.stringify({
|
|
25071
|
-
width:
|
|
25072
|
-
offset:
|
|
25548
|
+
width: widthVal,
|
|
25549
|
+
offset: offsetVal,
|
|
25073
25550
|
style: focusConfig.style,
|
|
25074
25551
|
color: "var(--ring)"
|
|
25075
25552
|
}),
|
|
@@ -25077,13 +25554,13 @@ function generateFocusTokens(config2, focusConfigs) {
|
|
|
25077
25554
|
namespace: "focus",
|
|
25078
25555
|
semanticMeaning: focusConfig.meaning,
|
|
25079
25556
|
usageContext: focusConfig.contexts,
|
|
25080
|
-
focusRingWidth:
|
|
25557
|
+
focusRingWidth: widthVal,
|
|
25081
25558
|
focusRingColor: "var(--ring)",
|
|
25082
|
-
focusRingOffset:
|
|
25559
|
+
focusRingOffset: offsetVal,
|
|
25083
25560
|
focusRingStyle: focusConfig.style,
|
|
25084
25561
|
dependsOn: ["ring", "focus-ring-width"],
|
|
25085
25562
|
accessibilityLevel: focusConfig.width >= 2 ? "AA" : void 0,
|
|
25086
|
-
description: `${focusConfig.meaning}. Width: ${
|
|
25563
|
+
description: `${focusConfig.meaning}. Width: ${widthVal}, Offset: ${offsetVal}.`,
|
|
25087
25564
|
generatedAt: timestamp,
|
|
25088
25565
|
containerQueryAware: false,
|
|
25089
25566
|
highContrastMode: "Highlight",
|
|
@@ -25096,7 +25573,7 @@ function generateFocusTokens(config2, focusConfigs) {
|
|
|
25096
25573
|
]
|
|
25097
25574
|
}
|
|
25098
25575
|
});
|
|
25099
|
-
const outlineValue = `${
|
|
25576
|
+
const outlineValue = `${widthVal} ${focusConfig.style} var(--ring)`;
|
|
25100
25577
|
tokens.push({
|
|
25101
25578
|
name: name === "default" ? "focus-outline" : `focus-outline-${name}`,
|
|
25102
25579
|
value: outlineValue,
|
|
@@ -25104,20 +25581,21 @@ function generateFocusTokens(config2, focusConfigs) {
|
|
|
25104
25581
|
namespace: "focus",
|
|
25105
25582
|
semanticMeaning: `CSS outline shorthand for ${name} focus ring`,
|
|
25106
25583
|
usageContext: ["css-outline-property"],
|
|
25107
|
-
dependsOn: ["ring"],
|
|
25108
|
-
description: `CSS outline value: ${outlineValue}. Use with outline-offset: ${
|
|
25584
|
+
dependsOn: ["ring", "focus-ring-width"],
|
|
25585
|
+
description: `CSS outline value: ${outlineValue}. Use with outline-offset: ${offsetVal}.`,
|
|
25109
25586
|
generatedAt: timestamp,
|
|
25110
25587
|
containerQueryAware: false,
|
|
25111
25588
|
userOverride: null
|
|
25112
25589
|
});
|
|
25113
25590
|
tokens.push({
|
|
25114
25591
|
name: name === "default" ? "focus-offset" : `focus-offset-${name}`,
|
|
25115
|
-
value:
|
|
25592
|
+
value: offsetVal,
|
|
25116
25593
|
category: "focus",
|
|
25117
25594
|
namespace: "focus",
|
|
25118
25595
|
semanticMeaning: `Focus ring offset for ${name} style`,
|
|
25119
|
-
focusRingOffset:
|
|
25120
|
-
|
|
25596
|
+
focusRingOffset: offsetVal,
|
|
25597
|
+
dependsOn: ["focus-ring-width"],
|
|
25598
|
+
description: `Focus offset ${offsetVal} for ${name} focus style.`,
|
|
25121
25599
|
generatedAt: timestamp,
|
|
25122
25600
|
containerQueryAware: false,
|
|
25123
25601
|
userOverride: null
|
|
@@ -25126,7 +25604,7 @@ function generateFocusTokens(config2, focusConfigs) {
|
|
|
25126
25604
|
tokens.push({
|
|
25127
25605
|
name: "focus-within-ring",
|
|
25128
25606
|
value: JSON.stringify({
|
|
25129
|
-
width:
|
|
25607
|
+
width: focusVar,
|
|
25130
25608
|
offset: "0",
|
|
25131
25609
|
style: "solid",
|
|
25132
25610
|
color: "var(--ring)"
|
|
@@ -25135,11 +25613,11 @@ function generateFocusTokens(config2, focusConfigs) {
|
|
|
25135
25613
|
namespace: "focus",
|
|
25136
25614
|
semanticMeaning: "Focus ring for containers with focused descendants",
|
|
25137
25615
|
usageContext: ["form-groups", "card-actions", "list-containers"],
|
|
25138
|
-
focusRingWidth:
|
|
25616
|
+
focusRingWidth: focusVar,
|
|
25139
25617
|
focusRingColor: "var(--ring)",
|
|
25140
25618
|
focusRingOffset: "0",
|
|
25141
25619
|
focusRingStyle: "solid",
|
|
25142
|
-
dependsOn: ["ring"],
|
|
25620
|
+
dependsOn: ["ring", "focus-ring-width"],
|
|
25143
25621
|
description: "Focus indicator for containers using :focus-within pseudo-class.",
|
|
25144
25622
|
generatedAt: timestamp,
|
|
25145
25623
|
containerQueryAware: false,
|
|
@@ -25149,13 +25627,13 @@ function generateFocusTokens(config2, focusConfigs) {
|
|
|
25149
25627
|
never: ["Use as replacement for child focus indicators", "Apply to non-container elements"]
|
|
25150
25628
|
}
|
|
25151
25629
|
});
|
|
25152
|
-
const
|
|
25153
|
-
const
|
|
25630
|
+
const hcWidthVal = `calc(${focusVar} * 1.5)`;
|
|
25631
|
+
const hcOffsetVal = focusVar;
|
|
25154
25632
|
tokens.push({
|
|
25155
25633
|
name: "focus-high-contrast",
|
|
25156
25634
|
value: JSON.stringify({
|
|
25157
|
-
width:
|
|
25158
|
-
offset:
|
|
25635
|
+
width: hcWidthVal,
|
|
25636
|
+
offset: hcOffsetVal,
|
|
25159
25637
|
style: "solid",
|
|
25160
25638
|
color: "Highlight"
|
|
25161
25639
|
}),
|
|
@@ -25163,10 +25641,11 @@ function generateFocusTokens(config2, focusConfigs) {
|
|
|
25163
25641
|
namespace: "focus",
|
|
25164
25642
|
semanticMeaning: "Focus ring for Windows High Contrast Mode",
|
|
25165
25643
|
usageContext: ["high-contrast-mode", "forced-colors"],
|
|
25166
|
-
focusRingWidth:
|
|
25167
|
-
focusRingOffset:
|
|
25644
|
+
focusRingWidth: hcWidthVal,
|
|
25645
|
+
focusRingOffset: hcOffsetVal,
|
|
25168
25646
|
focusRingStyle: "solid",
|
|
25169
25647
|
highContrastMode: "Highlight",
|
|
25648
|
+
dependsOn: ["focus-ring-width"],
|
|
25170
25649
|
description: "High contrast focus ring using system Highlight color.",
|
|
25171
25650
|
generatedAt: timestamp,
|
|
25172
25651
|
containerQueryAware: false,
|
|
@@ -25346,21 +25825,6 @@ function evaluateExpression(expression, options = {}) {
|
|
|
25346
25825
|
}
|
|
25347
25826
|
|
|
25348
25827
|
// ../math-utils/src/progressions.ts
|
|
25349
|
-
var progression = (r, base, step) => base * ratioValue(r) ** step;
|
|
25350
|
-
function generateSequence(r, base, count, options = {}) {
|
|
25351
|
-
const { startStep = 0, includeZero = false } = options;
|
|
25352
|
-
const ratio = ratioValue(r);
|
|
25353
|
-
const result = [];
|
|
25354
|
-
for (let i = 0; i < count; i++) {
|
|
25355
|
-
if (i === 0 && includeZero) {
|
|
25356
|
-
result.push(0);
|
|
25357
|
-
} else {
|
|
25358
|
-
const step = startStep + (includeZero ? i - 1 : i);
|
|
25359
|
-
result.push(base * ratio ** step);
|
|
25360
|
-
}
|
|
25361
|
-
}
|
|
25362
|
-
return result;
|
|
25363
|
-
}
|
|
25364
25828
|
function generateModularScale(r, base, steps2 = 5) {
|
|
25365
25829
|
const ratio = ratioValue(r);
|
|
25366
25830
|
const smaller = [];
|
|
@@ -25422,45 +25886,142 @@ function tryParseUnit(cssValue, registry2 = DEFAULT_UNITS) {
|
|
|
25422
25886
|
}
|
|
25423
25887
|
}
|
|
25424
25888
|
|
|
25425
|
-
// ../design-tokens/src/generators/motion.ts
|
|
25426
|
-
var
|
|
25427
|
-
|
|
25428
|
-
|
|
25429
|
-
|
|
25430
|
-
|
|
25431
|
-
|
|
25889
|
+
// ../design-tokens/src/generators/motion-derivation.ts
|
|
25890
|
+
var BAND_ORDER = ["instant", "micro", "fast", "moderate", "normal", "slow"];
|
|
25891
|
+
var TRAVEL_BAND = {
|
|
25892
|
+
none: "fast",
|
|
25893
|
+
short: "moderate",
|
|
25894
|
+
medium: "normal",
|
|
25895
|
+
large: "slow"
|
|
25896
|
+
};
|
|
25897
|
+
var LARGE_TRAVEL_DISAGREEMENT = {
|
|
25898
|
+
derived: "slow",
|
|
25899
|
+
shipped: "normal",
|
|
25900
|
+
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."
|
|
25901
|
+
};
|
|
25902
|
+
function applyLargeTravelException(band, travel) {
|
|
25903
|
+
return travel === "large" ? LARGE_TRAVEL_DISAGREEMENT.shipped : band;
|
|
25904
|
+
}
|
|
25905
|
+
function shortenForExit(band) {
|
|
25906
|
+
const i = BAND_ORDER.indexOf(band);
|
|
25907
|
+
return BAND_ORDER[Math.max(0, i - 1)];
|
|
25908
|
+
}
|
|
25909
|
+
var INTENT_POSITION = {
|
|
25910
|
+
efficient: null,
|
|
25911
|
+
elegant: 1,
|
|
25912
|
+
friendly: null,
|
|
25913
|
+
technical: null,
|
|
25914
|
+
editorial: null
|
|
25432
25915
|
};
|
|
25433
|
-
|
|
25916
|
+
var LANDMARK_BANDS = /* @__PURE__ */ new Set(["instant", "micro", "fast"]);
|
|
25917
|
+
function deriveDuration(band, intent, durationDefs) {
|
|
25918
|
+
const def = durationDefs[band];
|
|
25919
|
+
if (def === void 0) {
|
|
25920
|
+
throw new Error(
|
|
25921
|
+
`motion derivation: unknown band "${band}". Known bands: ${BAND_ORDER.join(", ")}.`
|
|
25922
|
+
);
|
|
25923
|
+
}
|
|
25924
|
+
if (LANDMARK_BANDS.has(band)) return def.default;
|
|
25925
|
+
const position = INTENT_POSITION[intent];
|
|
25926
|
+
if (position === null) return def.default;
|
|
25927
|
+
const [min, max2] = def.range;
|
|
25928
|
+
return Math.round(min + (max2 - min) * position);
|
|
25929
|
+
}
|
|
25930
|
+
function deriveBand(category, travel, declaredBand) {
|
|
25931
|
+
if (category === "interaction") {
|
|
25932
|
+
if (declaredBand === void 0) {
|
|
25933
|
+
throw new Error(
|
|
25934
|
+
"motion derivation: an interaction mapping must declare its band -- it has no travel to derive from."
|
|
25935
|
+
);
|
|
25936
|
+
}
|
|
25937
|
+
return declaredBand;
|
|
25938
|
+
}
|
|
25939
|
+
const base = applyLargeTravelException(TRAVEL_BAND[travel], travel);
|
|
25940
|
+
if (category === "exit" && travel !== "large") return shortenForExit(base);
|
|
25941
|
+
return base;
|
|
25942
|
+
}
|
|
25943
|
+
function deriveCurve(category, travel, _intent, declaredCurve) {
|
|
25944
|
+
if (category === "exit") return "exit";
|
|
25945
|
+
if (category === "enter") return travel === "large" ? "spring-smooth" : "enter";
|
|
25946
|
+
return declaredCurve ?? "standard";
|
|
25947
|
+
}
|
|
25948
|
+
|
|
25949
|
+
// ../design-tokens/src/generators/motion.ts
|
|
25950
|
+
function requireDef(defs, key, kind, owner) {
|
|
25951
|
+
const def = defs[key];
|
|
25952
|
+
if (def === void 0) {
|
|
25953
|
+
throw new Error(
|
|
25954
|
+
`motion generator: ${owner} references unknown ${kind} "${key}". Known ${kind}s: ${Object.keys(defs).sort().join(", ")}.`
|
|
25955
|
+
);
|
|
25956
|
+
}
|
|
25957
|
+
return def;
|
|
25958
|
+
}
|
|
25959
|
+
function motionNamespaceTokenName(namespace, member) {
|
|
25960
|
+
return `rafters-${namespace}-${member}`;
|
|
25961
|
+
}
|
|
25962
|
+
function namespaceLeaf(input) {
|
|
25963
|
+
const { namespaceName, member, value, provenance, note, meaning, contexts, timestamp } = input;
|
|
25964
|
+
return {
|
|
25965
|
+
name: motionNamespaceTokenName(namespaceName, member),
|
|
25966
|
+
value,
|
|
25967
|
+
category: "motion",
|
|
25968
|
+
namespace: "motion",
|
|
25969
|
+
semanticMeaning: meaning,
|
|
25970
|
+
usageContext: contexts,
|
|
25971
|
+
dependsOn: [],
|
|
25972
|
+
description: `${namespaceName}-${member}: ${value} [provenance: ${provenance}] ${note} ${meaning}`,
|
|
25973
|
+
generatedAt: timestamp,
|
|
25974
|
+
containerQueryAware: false,
|
|
25975
|
+
// Mirrors the exporter's REDUCED_MOTION_ZEROED set: only duration and delay
|
|
25976
|
+
// are zeroed under prefers-reduced-motion. ease/extent are shaped BY a
|
|
25977
|
+
// duration, not zeroed themselves; period is exempt by law (loops slow,
|
|
25978
|
+
// never stop).
|
|
25979
|
+
reducedMotionAware: namespaceName === "duration" || namespaceName === "delay",
|
|
25980
|
+
userOverride: null,
|
|
25981
|
+
usagePatterns: {
|
|
25982
|
+
do: [`Use the generated utility \`${namespaceName}-${member}\``],
|
|
25983
|
+
never: [
|
|
25984
|
+
"Hardcode this value in a component",
|
|
25985
|
+
"Add a second name for the same idea -- one fast, everywhere, always"
|
|
25986
|
+
]
|
|
25987
|
+
}
|
|
25988
|
+
};
|
|
25989
|
+
}
|
|
25990
|
+
function generateMotionTokens(config2, durationDefs, easingDefs, delayDefs, extentDefs, periodDefs, semanticMappings, keyframeDefs, animationDefs, compositePresets, cellAnimations) {
|
|
25434
25991
|
const tokens = [];
|
|
25435
25992
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
25436
25993
|
const { baseTransitionDuration, progressionRatio } = config2;
|
|
25994
|
+
const intent = config2.intent ?? "efficient";
|
|
25437
25995
|
const ratio = resolveRatio(progressionRatio);
|
|
25438
25996
|
const ratioVal = ratioValue(ratio);
|
|
25439
|
-
const computeStep = (base, step) => progression(ratio, base, step);
|
|
25440
25997
|
tokens.push({
|
|
25441
25998
|
name: "motion-duration-base",
|
|
25442
25999
|
value: `${baseTransitionDuration}ms`,
|
|
25443
26000
|
category: "motion",
|
|
25444
26001
|
namespace: "motion",
|
|
25445
|
-
semanticMeaning: "Legacy base transition duration.
|
|
25446
|
-
usageContext: ["calculation-reference"
|
|
26002
|
+
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.",
|
|
26003
|
+
usageContext: ["calculation-reference"],
|
|
25447
26004
|
progressionSystem: progressionRatio,
|
|
25448
|
-
description: `Base duration (${baseTransitionDuration}ms).
|
|
26005
|
+
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.`,
|
|
25449
26006
|
generatedAt: timestamp,
|
|
25450
26007
|
containerQueryAware: false,
|
|
25451
26008
|
reducedMotionAware: true,
|
|
25452
26009
|
userOverride: null,
|
|
25453
26010
|
usagePatterns: {
|
|
25454
26011
|
do: ["Reference as the delay-progression base"],
|
|
25455
|
-
never: [
|
|
26012
|
+
never: [
|
|
26013
|
+
"Assume the perceptual duration tiers derive from this -- they are ranges a designer sets within, bounded by perception, not computed from this base"
|
|
26014
|
+
]
|
|
25456
26015
|
}
|
|
25457
26016
|
});
|
|
25458
26017
|
for (const scale2 of MOTION_DURATION_SCALE) {
|
|
25459
26018
|
const def = durationDefs[scale2];
|
|
25460
26019
|
if (!def) continue;
|
|
25461
26020
|
const scaleIndex = MOTION_DURATION_SCALE.indexOf(scale2);
|
|
25462
|
-
const durationMs =
|
|
26021
|
+
const durationMs = deriveDuration(scale2, intent, durationDefs);
|
|
26022
|
+
const [rangeMin, rangeMax] = def.range;
|
|
25463
26023
|
const bandNote = def.band ? ` Band: ${def.band}.` : "";
|
|
26024
|
+
const rangeNote = rangeMin === rangeMax ? " Fixed." : ` Range: ${rangeMin}-${rangeMax}ms.`;
|
|
25464
26025
|
tokens.push({
|
|
25465
26026
|
name: `motion-duration-${scale2}`,
|
|
25466
26027
|
value: `${durationMs}ms`,
|
|
@@ -25471,9 +26032,9 @@ function generateMotionTokens(config2, durationDefs, easingDefs, delayDefs, sema
|
|
|
25471
26032
|
scalePosition: scaleIndex,
|
|
25472
26033
|
motionIntent: def.motionIntent,
|
|
25473
26034
|
motionDuration: durationMs,
|
|
25474
|
-
mathRelationship: def.band ? `${durationMs}ms (perceptual: ${def.band})` : `${durationMs}ms`,
|
|
26035
|
+
mathRelationship: def.band ? `${durationMs}ms within ${rangeMin}-${rangeMax}ms (perceptual: ${def.band})` : `${durationMs}ms (fixed)`,
|
|
25475
26036
|
dependsOn: [],
|
|
25476
|
-
description: `Duration ${scale2}: ${durationMs}ms.${bandNote} ${def.meaning}`,
|
|
26037
|
+
description: `Duration ${scale2}: ${durationMs}ms.${rangeNote}${bandNote} ${def.meaning}`,
|
|
25477
26038
|
generatedAt: timestamp,
|
|
25478
26039
|
containerQueryAware: false,
|
|
25479
26040
|
reducedMotionAware: true,
|
|
@@ -25510,416 +26071,185 @@ function generateMotionTokens(config2, durationDefs, easingDefs, delayDefs, sema
|
|
|
25510
26071
|
}
|
|
25511
26072
|
});
|
|
25512
26073
|
}
|
|
25513
|
-
for (const
|
|
25514
|
-
|
|
25515
|
-
|
|
25516
|
-
|
|
25517
|
-
|
|
25518
|
-
|
|
25519
|
-
|
|
25520
|
-
|
|
25521
|
-
|
|
26074
|
+
for (const scale2 of MOTION_DURATION_SCALE) {
|
|
26075
|
+
const def = durationDefs[scale2];
|
|
26076
|
+
if (!def) continue;
|
|
26077
|
+
const durationMs = deriveDuration(scale2, intent, durationDefs);
|
|
26078
|
+
tokens.push(
|
|
26079
|
+
namespaceLeaf({
|
|
26080
|
+
namespaceName: "duration",
|
|
26081
|
+
member: scale2,
|
|
26082
|
+
value: `${durationMs}ms`,
|
|
26083
|
+
provenance: "baseline",
|
|
26084
|
+
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.`,
|
|
26085
|
+
meaning: def.meaning,
|
|
26086
|
+
contexts: def.contexts,
|
|
26087
|
+
timestamp
|
|
26088
|
+
})
|
|
26089
|
+
);
|
|
26090
|
+
}
|
|
26091
|
+
for (const curve of EASING_CURVES) {
|
|
26092
|
+
const def = easingDefs[curve];
|
|
26093
|
+
if (!def) continue;
|
|
26094
|
+
tokens.push(
|
|
26095
|
+
namespaceLeaf({
|
|
26096
|
+
namespaceName: "ease",
|
|
26097
|
+
member: curve,
|
|
26098
|
+
value: def.css,
|
|
26099
|
+
provenance: "baseline",
|
|
26100
|
+
note: "Efficient baseline curve.",
|
|
26101
|
+
meaning: def.meaning,
|
|
26102
|
+
contexts: def.contexts,
|
|
26103
|
+
timestamp
|
|
26104
|
+
})
|
|
26105
|
+
);
|
|
26106
|
+
}
|
|
26107
|
+
for (const [namespaceName, members] of [
|
|
26108
|
+
["delay", delayDefs],
|
|
26109
|
+
["extent", extentDefs],
|
|
26110
|
+
["period", periodDefs]
|
|
26111
|
+
]) {
|
|
26112
|
+
for (const [member, def] of Object.entries(members)) {
|
|
26113
|
+
tokens.push(
|
|
26114
|
+
namespaceLeaf({
|
|
26115
|
+
namespaceName,
|
|
26116
|
+
member,
|
|
26117
|
+
value: def.value,
|
|
26118
|
+
provenance: def.provenance,
|
|
26119
|
+
note: def.note,
|
|
26120
|
+
meaning: def.meaning,
|
|
26121
|
+
contexts: def.contexts,
|
|
26122
|
+
timestamp
|
|
26123
|
+
})
|
|
26124
|
+
);
|
|
25522
26125
|
}
|
|
25523
|
-
tokens.push({
|
|
25524
|
-
name: `motion-delay-${name}`,
|
|
25525
|
-
value: delayMs === 0 ? "0ms" : `${delayMs}ms`,
|
|
25526
|
-
category: "motion",
|
|
25527
|
-
namespace: "motion",
|
|
25528
|
-
semanticMeaning: `${name.charAt(0).toUpperCase() + name.slice(1)} animation delay`,
|
|
25529
|
-
usageContext: name === "none" ? ["immediate-response"] : name === "short" ? ["staggered-lists", "sequential-elements"] : name === "medium" ? ["modal-content", "after-transition"] : ["emphasis", "dramatic-reveals"],
|
|
25530
|
-
delayMs,
|
|
25531
|
-
mathRelationship,
|
|
25532
|
-
dependsOn: def.step === "none" ? [] : ["motion-duration-base"],
|
|
25533
|
-
description: `Delay ${name}: ${delayMs}ms. Based on duration progression.`,
|
|
25534
|
-
generatedAt: timestamp,
|
|
25535
|
-
containerQueryAware: false,
|
|
25536
|
-
reducedMotionAware: true,
|
|
25537
|
-
userOverride: null
|
|
25538
|
-
});
|
|
25539
26126
|
}
|
|
25540
26127
|
const ratioValue2 = ratioVal;
|
|
25541
|
-
const scaleStart = Math.round(1 / ratioValue2 ** 0.25 * 100) / 100;
|
|
25542
26128
|
const pingScale = Math.round(ratioValue2 ** 3 * 10) / 10;
|
|
25543
26129
|
const pulseOpacity = Math.round(1 / ratioValue2 ** 4 * 100) / 100;
|
|
25544
26130
|
const bouncePercent = Math.round(100 / ratioValue2 ** 6);
|
|
25545
|
-
const
|
|
25546
|
-
|
|
25547
|
-
|
|
25548
|
-
|
|
25549
|
-
|
|
25550
|
-
|
|
25551
|
-
},
|
|
25552
|
-
{
|
|
25553
|
-
name: "fade-out",
|
|
25554
|
-
css: "from { opacity: 1; } to { opacity: 0; }",
|
|
25555
|
-
meaning: "Fade from opaque to transparent",
|
|
25556
|
-
contexts: ["exit", "disappear", "hide"]
|
|
25557
|
-
},
|
|
25558
|
-
{
|
|
25559
|
-
name: "slide-in-from-top",
|
|
25560
|
-
css: "from { transform: translateY(-100%); } to { transform: translateY(0); }",
|
|
25561
|
-
meaning: "Slide in from above",
|
|
25562
|
-
contexts: ["dropdown", "notification", "toast"]
|
|
25563
|
-
},
|
|
25564
|
-
{
|
|
25565
|
-
name: "slide-in-from-bottom",
|
|
25566
|
-
css: "from { transform: translateY(100%); } to { transform: translateY(0); }",
|
|
25567
|
-
meaning: "Slide in from below",
|
|
25568
|
-
contexts: ["sheet", "drawer", "mobile-menu"]
|
|
25569
|
-
},
|
|
25570
|
-
{
|
|
25571
|
-
name: "slide-in-from-left",
|
|
25572
|
-
css: "from { transform: translateX(-100%); } to { transform: translateX(0); }",
|
|
25573
|
-
meaning: "Slide in from left",
|
|
25574
|
-
contexts: ["sidebar", "panel", "drawer"]
|
|
25575
|
-
},
|
|
25576
|
-
{
|
|
25577
|
-
name: "slide-in-from-right",
|
|
25578
|
-
css: "from { transform: translateX(100%); } to { transform: translateX(0); }",
|
|
25579
|
-
meaning: "Slide in from right",
|
|
25580
|
-
contexts: ["sidebar", "panel", "drawer"]
|
|
25581
|
-
},
|
|
25582
|
-
{
|
|
25583
|
-
name: "slide-out-to-top",
|
|
25584
|
-
css: "from { transform: translateY(0); } to { transform: translateY(-100%); }",
|
|
25585
|
-
meaning: "Slide out upward",
|
|
25586
|
-
contexts: ["dropdown-exit", "notification-dismiss"]
|
|
25587
|
-
},
|
|
25588
|
-
{
|
|
25589
|
-
name: "slide-out-to-bottom",
|
|
25590
|
-
css: "from { transform: translateY(0); } to { transform: translateY(100%); }",
|
|
25591
|
-
meaning: "Slide out downward",
|
|
25592
|
-
contexts: ["sheet-exit", "drawer-close"]
|
|
25593
|
-
},
|
|
25594
|
-
{
|
|
25595
|
-
name: "slide-out-to-left",
|
|
25596
|
-
css: "from { transform: translateX(0); } to { transform: translateX(-100%); }",
|
|
25597
|
-
meaning: "Slide out to left",
|
|
25598
|
-
contexts: ["sidebar-close", "panel-exit"]
|
|
25599
|
-
},
|
|
25600
|
-
{
|
|
25601
|
-
name: "slide-out-to-right",
|
|
25602
|
-
css: "from { transform: translateX(0); } to { transform: translateX(100%); }",
|
|
25603
|
-
meaning: "Slide out to right",
|
|
25604
|
-
contexts: ["sidebar-close", "panel-exit"]
|
|
25605
|
-
},
|
|
25606
|
-
{
|
|
25607
|
-
name: "scale-in",
|
|
25608
|
-
css: `from { transform: scale(${scaleStart}); opacity: 0; } to { transform: scale(1); opacity: 1; }`,
|
|
25609
|
-
meaning: "Scale up while fading in",
|
|
25610
|
-
contexts: ["modal", "popover", "dialog"]
|
|
25611
|
-
},
|
|
25612
|
-
{
|
|
25613
|
-
name: "scale-out",
|
|
25614
|
-
css: `from { transform: scale(1); opacity: 1; } to { transform: scale(${scaleStart}); opacity: 0; }`,
|
|
25615
|
-
meaning: "Scale down while fading out",
|
|
25616
|
-
contexts: ["modal-exit", "popover-close"]
|
|
25617
|
-
},
|
|
25618
|
-
{
|
|
25619
|
-
name: "spin",
|
|
25620
|
-
css: "from { transform: rotate(0deg); } to { transform: rotate(360deg); }",
|
|
25621
|
-
meaning: "Continuous rotation",
|
|
25622
|
-
contexts: ["loading", "spinner", "refresh"]
|
|
25623
|
-
},
|
|
25624
|
-
{
|
|
25625
|
-
name: "ping",
|
|
25626
|
-
css: `75%, 100% { transform: scale(${pingScale}); opacity: 0; }`,
|
|
25627
|
-
meaning: "Expanding pulse that fades out",
|
|
25628
|
-
contexts: ["notification-badge", "attention", "pulse"]
|
|
25629
|
-
},
|
|
25630
|
-
{
|
|
25631
|
-
name: "pulse",
|
|
25632
|
-
css: `0%, 100% { opacity: 1; } 50% { opacity: ${pulseOpacity}; }`,
|
|
25633
|
-
meaning: "Gentle opacity pulse",
|
|
25634
|
-
contexts: ["skeleton", "loading-placeholder"]
|
|
25635
|
-
},
|
|
25636
|
-
{
|
|
25637
|
-
name: "bounce",
|
|
25638
|
-
css: `0%, 100% { transform: translateY(-${bouncePercent}%); animation-timing-function: cubic-bezier(0.8, 0, 1, 1); } 50% { transform: translateY(0); animation-timing-function: cubic-bezier(0, 0, 0.2, 1); }`,
|
|
25639
|
-
meaning: "Bouncing motion",
|
|
25640
|
-
contexts: ["attention", "scroll-indicator"]
|
|
25641
|
-
},
|
|
25642
|
-
{
|
|
25643
|
-
name: "accordion-down",
|
|
25644
|
-
css: "from { height: 0; } to { height: var(--radix-accordion-content-height); }",
|
|
25645
|
-
meaning: "Expand accordion content",
|
|
25646
|
-
contexts: ["accordion", "collapsible", "expand"]
|
|
25647
|
-
},
|
|
25648
|
-
{
|
|
25649
|
-
name: "accordion-up",
|
|
25650
|
-
css: "from { height: var(--radix-accordion-content-height); } to { height: 0; }",
|
|
25651
|
-
meaning: "Collapse accordion content",
|
|
25652
|
-
contexts: ["accordion", "collapsible", "collapse"]
|
|
25653
|
-
},
|
|
25654
|
-
{
|
|
25655
|
-
name: "caret-blink",
|
|
25656
|
-
css: "0%, 70%, 100% { opacity: 1; } 20%, 50% { opacity: 0; }",
|
|
25657
|
-
meaning: "Text cursor blinking",
|
|
25658
|
-
contexts: ["input-caret", "text-cursor"]
|
|
25659
|
-
}
|
|
25660
|
-
];
|
|
25661
|
-
for (const kf of keyframes) {
|
|
26131
|
+
const keyframeContext = {
|
|
26132
|
+
pingScale,
|
|
26133
|
+
pulseOpacity,
|
|
26134
|
+
bouncePercent
|
|
26135
|
+
};
|
|
26136
|
+
for (const [name, kf] of Object.entries(keyframeDefs)) {
|
|
25662
26137
|
tokens.push({
|
|
25663
|
-
name: `motion-keyframe-${
|
|
25664
|
-
value: kf.css,
|
|
26138
|
+
name: `motion-keyframe-${name}`,
|
|
26139
|
+
value: kf.css(keyframeContext),
|
|
25665
26140
|
category: "motion",
|
|
25666
26141
|
namespace: "motion",
|
|
25667
26142
|
semanticMeaning: kf.meaning,
|
|
25668
26143
|
usageContext: kf.contexts,
|
|
25669
|
-
keyframeName:
|
|
25670
|
-
description: `Keyframe ${
|
|
26144
|
+
keyframeName: name,
|
|
26145
|
+
description: `Keyframe ${name}: ${kf.meaning}`,
|
|
25671
26146
|
generatedAt: timestamp,
|
|
25672
26147
|
containerQueryAware: false,
|
|
25673
26148
|
reducedMotionAware: true,
|
|
25674
26149
|
userOverride: null
|
|
25675
26150
|
});
|
|
25676
26151
|
}
|
|
25677
|
-
const
|
|
25678
|
-
{
|
|
25679
|
-
name: "fade-in",
|
|
25680
|
-
keyframe: "fade-in",
|
|
25681
|
-
duration: "fast",
|
|
25682
|
-
easing: "ease-out",
|
|
25683
|
-
meaning: "Fade in animation",
|
|
25684
|
-
contexts: ["enter", "appear"]
|
|
25685
|
-
},
|
|
25686
|
-
{
|
|
25687
|
-
name: "fade-out",
|
|
25688
|
-
keyframe: "fade-out",
|
|
25689
|
-
duration: "fast",
|
|
25690
|
-
easing: "ease-in",
|
|
25691
|
-
meaning: "Fade out animation",
|
|
25692
|
-
contexts: ["exit", "disappear"]
|
|
25693
|
-
},
|
|
25694
|
-
{
|
|
25695
|
-
name: "slide-in-from-top",
|
|
25696
|
-
keyframe: "slide-in-from-top",
|
|
25697
|
-
duration: "normal",
|
|
25698
|
-
easing: "ease-out",
|
|
25699
|
-
meaning: "Slide in from top",
|
|
25700
|
-
contexts: ["dropdown", "notification"]
|
|
25701
|
-
},
|
|
25702
|
-
{
|
|
25703
|
-
name: "slide-in-from-bottom",
|
|
25704
|
-
keyframe: "slide-in-from-bottom",
|
|
25705
|
-
duration: "normal",
|
|
25706
|
-
easing: "ease-out",
|
|
25707
|
-
meaning: "Slide in from bottom",
|
|
25708
|
-
contexts: ["sheet", "drawer"]
|
|
25709
|
-
},
|
|
25710
|
-
{
|
|
25711
|
-
name: "slide-in-from-left",
|
|
25712
|
-
keyframe: "slide-in-from-left",
|
|
25713
|
-
duration: "normal",
|
|
25714
|
-
easing: "ease-out",
|
|
25715
|
-
meaning: "Slide in from left",
|
|
25716
|
-
contexts: ["sidebar", "panel"]
|
|
25717
|
-
},
|
|
25718
|
-
{
|
|
25719
|
-
name: "slide-in-from-right",
|
|
25720
|
-
keyframe: "slide-in-from-right",
|
|
25721
|
-
duration: "normal",
|
|
25722
|
-
easing: "ease-out",
|
|
25723
|
-
meaning: "Slide in from right",
|
|
25724
|
-
contexts: ["sidebar", "panel"]
|
|
25725
|
-
},
|
|
25726
|
-
{
|
|
25727
|
-
name: "slide-out-to-top",
|
|
25728
|
-
keyframe: "slide-out-to-top",
|
|
25729
|
-
duration: "fast",
|
|
25730
|
-
easing: "ease-in",
|
|
25731
|
-
meaning: "Slide out to top",
|
|
25732
|
-
contexts: ["dropdown-exit"]
|
|
25733
|
-
},
|
|
25734
|
-
{
|
|
25735
|
-
name: "slide-out-to-bottom",
|
|
25736
|
-
keyframe: "slide-out-to-bottom",
|
|
25737
|
-
duration: "fast",
|
|
25738
|
-
easing: "ease-in",
|
|
25739
|
-
meaning: "Slide out to bottom",
|
|
25740
|
-
contexts: ["sheet-exit"]
|
|
25741
|
-
},
|
|
25742
|
-
{
|
|
25743
|
-
name: "slide-out-to-left",
|
|
25744
|
-
keyframe: "slide-out-to-left",
|
|
25745
|
-
duration: "fast",
|
|
25746
|
-
easing: "ease-in",
|
|
25747
|
-
meaning: "Slide out to left",
|
|
25748
|
-
contexts: ["sidebar-close"]
|
|
25749
|
-
},
|
|
25750
|
-
{
|
|
25751
|
-
name: "slide-out-to-right",
|
|
25752
|
-
keyframe: "slide-out-to-right",
|
|
25753
|
-
duration: "fast",
|
|
25754
|
-
easing: "ease-in",
|
|
25755
|
-
meaning: "Slide out to right",
|
|
25756
|
-
contexts: ["sidebar-close"]
|
|
25757
|
-
},
|
|
25758
|
-
{
|
|
25759
|
-
name: "scale-in",
|
|
25760
|
-
keyframe: "scale-in",
|
|
25761
|
-
duration: "normal",
|
|
25762
|
-
easing: "spring",
|
|
25763
|
-
meaning: "Scale in with spring",
|
|
25764
|
-
contexts: ["modal", "popover"]
|
|
25765
|
-
},
|
|
25766
|
-
{
|
|
25767
|
-
name: "scale-out",
|
|
25768
|
-
keyframe: "scale-out",
|
|
25769
|
-
duration: "fast",
|
|
25770
|
-
easing: "ease-in",
|
|
25771
|
-
meaning: "Scale out",
|
|
25772
|
-
contexts: ["modal-exit"]
|
|
25773
|
-
},
|
|
25774
|
-
{
|
|
25775
|
-
name: "spin",
|
|
25776
|
-
keyframe: "spin",
|
|
25777
|
-
duration: "1s",
|
|
25778
|
-
easing: "linear",
|
|
25779
|
-
iterations: "infinite",
|
|
25780
|
-
meaning: "Continuous spin",
|
|
25781
|
-
contexts: ["loading", "spinner"]
|
|
25782
|
-
},
|
|
25783
|
-
{
|
|
25784
|
-
name: "ping",
|
|
25785
|
-
keyframe: "ping",
|
|
25786
|
-
duration: "1s",
|
|
25787
|
-
easing: "ease-out",
|
|
25788
|
-
iterations: "infinite",
|
|
25789
|
-
meaning: "Pinging pulse",
|
|
25790
|
-
contexts: ["notification"]
|
|
25791
|
-
},
|
|
25792
|
-
{
|
|
25793
|
-
name: "pulse",
|
|
25794
|
-
keyframe: "pulse",
|
|
25795
|
-
duration: "2s",
|
|
25796
|
-
easing: "ease-in-out",
|
|
25797
|
-
iterations: "infinite",
|
|
25798
|
-
meaning: "Gentle pulse",
|
|
25799
|
-
contexts: ["skeleton", "loading"]
|
|
25800
|
-
},
|
|
25801
|
-
{
|
|
25802
|
-
name: "bounce",
|
|
25803
|
-
keyframe: "bounce",
|
|
25804
|
-
duration: "1s",
|
|
25805
|
-
easing: "ease-in-out",
|
|
25806
|
-
iterations: "infinite",
|
|
25807
|
-
meaning: "Bouncing",
|
|
25808
|
-
contexts: ["attention"]
|
|
25809
|
-
},
|
|
25810
|
-
{
|
|
25811
|
-
name: "accordion-down",
|
|
25812
|
-
keyframe: "accordion-down",
|
|
25813
|
-
duration: "normal",
|
|
25814
|
-
easing: "ease-out",
|
|
25815
|
-
meaning: "Accordion expand",
|
|
25816
|
-
contexts: ["accordion", "collapsible"]
|
|
25817
|
-
},
|
|
25818
|
-
{
|
|
25819
|
-
name: "accordion-up",
|
|
25820
|
-
keyframe: "accordion-up",
|
|
25821
|
-
duration: "normal",
|
|
25822
|
-
easing: "ease-out",
|
|
25823
|
-
meaning: "Accordion collapse",
|
|
25824
|
-
contexts: ["accordion", "collapsible"]
|
|
25825
|
-
},
|
|
25826
|
-
{
|
|
25827
|
-
name: "caret-blink",
|
|
25828
|
-
keyframe: "caret-blink",
|
|
25829
|
-
duration: "1.25s",
|
|
25830
|
-
easing: "ease-out",
|
|
25831
|
-
iterations: "infinite",
|
|
25832
|
-
meaning: "Caret blinking",
|
|
25833
|
-
contexts: ["input"]
|
|
25834
|
-
}
|
|
25835
|
-
];
|
|
25836
|
-
for (const anim of animations) {
|
|
26152
|
+
for (const [name, anim] of Object.entries(animationDefs)) {
|
|
25837
26153
|
let durationValue;
|
|
25838
26154
|
let durationRef;
|
|
25839
|
-
|
|
25840
|
-
|
|
25841
|
-
|
|
26155
|
+
let durationDependency;
|
|
26156
|
+
if ("loopPeriod" in anim.duration) {
|
|
26157
|
+
durationValue = anim.duration.loopPeriod;
|
|
26158
|
+
durationRef = anim.duration.loopPeriod;
|
|
26159
|
+
durationDependency = [];
|
|
25842
26160
|
} else {
|
|
25843
|
-
const durationDef =
|
|
25844
|
-
|
|
25845
|
-
|
|
25846
|
-
|
|
25847
|
-
|
|
25848
|
-
|
|
25849
|
-
|
|
25850
|
-
|
|
25851
|
-
|
|
26161
|
+
const durationDef = requireDef(
|
|
26162
|
+
durationDefs,
|
|
26163
|
+
anim.duration.tier,
|
|
26164
|
+
"duration tier",
|
|
26165
|
+
`animation "${name}"`
|
|
26166
|
+
);
|
|
26167
|
+
durationValue = `${durationDef.default}ms`;
|
|
26168
|
+
durationRef = `var(--rafters-duration-${anim.duration.tier})`;
|
|
26169
|
+
durationDependency = [`rafters-duration-${anim.duration.tier}`];
|
|
26170
|
+
}
|
|
26171
|
+
const easingDef = requireDef(easingDefs, anim.curve, "easing curve", `animation "${name}"`);
|
|
26172
|
+
const easingRef = `var(--rafters-ease-${anim.curve})`;
|
|
25852
26173
|
const iterations = anim.iterations || "";
|
|
25853
26174
|
const animValue = iterations ? `${anim.keyframe} ${durationRef} ${easingRef} ${iterations}` : `${anim.keyframe} ${durationRef} ${easingRef}`;
|
|
25854
26175
|
tokens.push({
|
|
25855
|
-
name: `motion-animation-${
|
|
26176
|
+
name: `motion-animation-${name}`,
|
|
25856
26177
|
value: animValue,
|
|
25857
26178
|
category: "motion",
|
|
25858
26179
|
namespace: "motion",
|
|
25859
26180
|
semanticMeaning: anim.meaning,
|
|
25860
26181
|
usageContext: anim.contexts,
|
|
25861
|
-
animationName:
|
|
26182
|
+
animationName: name,
|
|
25862
26183
|
keyframeName: anim.keyframe,
|
|
25863
26184
|
animationDuration: durationValue,
|
|
25864
26185
|
animationEasing: easingDef.css,
|
|
25865
26186
|
animationIterations: anim.iterations || "1",
|
|
25866
26187
|
dependsOn: [
|
|
25867
26188
|
`motion-keyframe-${anim.keyframe}`,
|
|
25868
|
-
...
|
|
25869
|
-
`
|
|
26189
|
+
...durationDependency,
|
|
26190
|
+
`rafters-ease-${anim.curve}`
|
|
25870
26191
|
],
|
|
25871
|
-
description: `Animation ${
|
|
26192
|
+
description: `Animation ${name}: ${anim.meaning}`,
|
|
25872
26193
|
generatedAt: timestamp,
|
|
25873
26194
|
containerQueryAware: false,
|
|
25874
26195
|
reducedMotionAware: true,
|
|
25875
26196
|
userOverride: null
|
|
25876
26197
|
});
|
|
25877
26198
|
}
|
|
25878
|
-
const
|
|
25879
|
-
{
|
|
25880
|
-
|
|
25881
|
-
|
|
25882
|
-
|
|
25883
|
-
meaning: "Fade in animation preset",
|
|
25884
|
-
contexts: ["fade-in", "appear"]
|
|
25885
|
-
},
|
|
25886
|
-
{
|
|
25887
|
-
name: "motion-fade-out",
|
|
25888
|
-
duration: "fast",
|
|
25889
|
-
easing: "ease-in",
|
|
25890
|
-
meaning: "Fade out animation preset",
|
|
25891
|
-
contexts: ["fade-out", "disappear"]
|
|
25892
|
-
},
|
|
25893
|
-
{
|
|
25894
|
-
name: "motion-slide-in",
|
|
25895
|
-
duration: "normal",
|
|
25896
|
-
easing: "ease-out",
|
|
25897
|
-
meaning: "Slide in animation preset",
|
|
25898
|
-
contexts: ["slide-in", "panel-enter", "modal-enter"]
|
|
25899
|
-
},
|
|
25900
|
-
{
|
|
25901
|
-
name: "motion-slide-out",
|
|
25902
|
-
duration: "fast",
|
|
25903
|
-
easing: "ease-in",
|
|
25904
|
-
meaning: "Slide out animation preset",
|
|
25905
|
-
contexts: ["slide-out", "panel-exit", "modal-exit"]
|
|
25906
|
-
},
|
|
25907
|
-
{
|
|
25908
|
-
name: "motion-scale-in",
|
|
25909
|
-
duration: "normal",
|
|
25910
|
-
easing: "spring",
|
|
25911
|
-
meaning: "Scale in with spring animation",
|
|
25912
|
-
contexts: ["pop-in", "button-press", "emphasis"]
|
|
25913
|
-
}
|
|
25914
|
-
];
|
|
25915
|
-
for (const comp of composites2) {
|
|
25916
|
-
const durationDef = durationDefs[comp.duration];
|
|
25917
|
-
const easingKey = LEGACY_EASING_REMAP[comp.easing] ?? comp.easing;
|
|
25918
|
-
const easingDef = easingDefs[easingKey];
|
|
25919
|
-
if (!durationDef || !easingDef) continue;
|
|
25920
|
-
const durationMs = durationDef.ms;
|
|
26199
|
+
for (const [name, cell] of Object.entries(cellAnimations)) {
|
|
26200
|
+
requireDef(keyframeDefs, cell.keyframe, "keyframe", `motion cell "${name}"`);
|
|
26201
|
+
requireDef(durationDefs, cell.tier, "duration tier", `motion cell "${name}"`);
|
|
26202
|
+
requireDef(easingDefs, cell.curve, "easing curve", `motion cell "${name}"`);
|
|
26203
|
+
const { component, part, transition } = cell.cell;
|
|
25921
26204
|
tokens.push({
|
|
25922
|
-
name:
|
|
26205
|
+
name: `motion-cell-${name}`,
|
|
26206
|
+
value: JSON.stringify({
|
|
26207
|
+
keyframe: cell.keyframe,
|
|
26208
|
+
durationTier: cell.tier,
|
|
26209
|
+
curve: cell.curve
|
|
26210
|
+
}),
|
|
26211
|
+
category: "motion",
|
|
26212
|
+
namespace: "motion",
|
|
26213
|
+
semanticMeaning: cell.meaning,
|
|
26214
|
+
usageContext: cell.contexts,
|
|
26215
|
+
animationName: name,
|
|
26216
|
+
keyframeName: cell.keyframe,
|
|
26217
|
+
generateUtilityClass: true,
|
|
26218
|
+
dependsOn: [
|
|
26219
|
+
`motion-keyframe-${cell.keyframe}`,
|
|
26220
|
+
`rafters-duration-${cell.tier}`,
|
|
26221
|
+
`rafters-ease-${cell.curve}`
|
|
26222
|
+
],
|
|
26223
|
+
description: `Motion cell ${component} / ${part} / ${transition}: ${cell.keyframe} over ${cell.tier} with ${cell.curve}. ${cell.meaning}`,
|
|
26224
|
+
generatedAt: timestamp,
|
|
26225
|
+
containerQueryAware: false,
|
|
26226
|
+
reducedMotionAware: true,
|
|
26227
|
+
userOverride: null,
|
|
26228
|
+
usagePatterns: {
|
|
26229
|
+
do: [`Apply class animate-${name} on the ${component} ${part} for "${transition}"`],
|
|
26230
|
+
never: [
|
|
26231
|
+
"Reuse this cell on a different component -- assignments come from motion.jsonl, one cell at a time",
|
|
26232
|
+
"Add motion-reduce:animate-none alongside it -- animation:none resets the shorthand and discards the zeroed duration"
|
|
26233
|
+
]
|
|
26234
|
+
}
|
|
26235
|
+
});
|
|
26236
|
+
}
|
|
26237
|
+
for (const [name, comp] of Object.entries(compositePresets)) {
|
|
26238
|
+
const durationDef = requireDef(
|
|
26239
|
+
durationDefs,
|
|
26240
|
+
comp.durationTier,
|
|
26241
|
+
"duration tier",
|
|
26242
|
+
`composite preset "${name}"`
|
|
26243
|
+
);
|
|
26244
|
+
const easingDef = requireDef(
|
|
26245
|
+
easingDefs,
|
|
26246
|
+
comp.curve,
|
|
26247
|
+
"easing curve",
|
|
26248
|
+
`composite preset "${name}"`
|
|
26249
|
+
);
|
|
26250
|
+
const durationMs = durationDef.default;
|
|
26251
|
+
tokens.push({
|
|
26252
|
+
name,
|
|
25923
26253
|
value: `${durationMs}ms ${easingDef.css}`,
|
|
25924
26254
|
category: "motion",
|
|
25925
26255
|
namespace: "motion",
|
|
@@ -25927,9 +26257,9 @@ function generateMotionTokens(config2, durationDefs, easingDefs, delayDefs, sema
|
|
|
25927
26257
|
usageContext: comp.contexts,
|
|
25928
26258
|
motionDuration: durationMs,
|
|
25929
26259
|
easingCurve: easingDef.curve,
|
|
25930
|
-
easingName:
|
|
25931
|
-
dependsOn: [`motion-duration-${comp.
|
|
25932
|
-
description: `${comp.meaning}. Combines ${comp.
|
|
26260
|
+
easingName: comp.curve,
|
|
26261
|
+
dependsOn: [`motion-duration-${comp.durationTier}`, `motion-easing-${comp.curve}`],
|
|
26262
|
+
description: `${comp.meaning}. Combines ${comp.durationTier} duration with ${comp.curve} easing.`,
|
|
25933
26263
|
generatedAt: timestamp,
|
|
25934
26264
|
containerQueryAware: false,
|
|
25935
26265
|
reducedMotionAware: true,
|
|
@@ -25937,12 +26267,16 @@ function generateMotionTokens(config2, durationDefs, easingDefs, delayDefs, sema
|
|
|
25937
26267
|
});
|
|
25938
26268
|
}
|
|
25939
26269
|
for (const [name, mapping] of Object.entries(semanticMappings)) {
|
|
26270
|
+
const durationTier = deriveBand(mapping.category, mapping.travel, mapping.band);
|
|
26271
|
+
const curve = deriveCurve(mapping.category, mapping.travel, intent, mapping.curve);
|
|
26272
|
+
requireDef(durationDefs, durationTier, "duration tier", `semantic motion "${name}"`);
|
|
26273
|
+
requireDef(easingDefs, curve, "easing curve", `semantic motion "${name}"`);
|
|
25940
26274
|
tokens.push({
|
|
25941
26275
|
name: `motion-semantic-${name}`,
|
|
25942
26276
|
value: JSON.stringify({
|
|
25943
26277
|
properties: mapping.properties,
|
|
25944
|
-
durationTier
|
|
25945
|
-
curve
|
|
26278
|
+
durationTier,
|
|
26279
|
+
curve,
|
|
25946
26280
|
reducedMotion: mapping.reducedMotion
|
|
25947
26281
|
}),
|
|
25948
26282
|
category: "motion",
|
|
@@ -25951,8 +26285,8 @@ function generateMotionTokens(config2, durationDefs, easingDefs, delayDefs, sema
|
|
|
25951
26285
|
usageContext: mapping.contexts,
|
|
25952
26286
|
motionIntent: mapping.category === "enter" ? "enter" : mapping.category === "exit" ? "exit" : "transition",
|
|
25953
26287
|
generateUtilityClass: true,
|
|
25954
|
-
dependsOn: [`motion-duration-${
|
|
25955
|
-
description: `Semantic motion motion-${name}: ${mapping.properties.join(", ")} over ${
|
|
26288
|
+
dependsOn: [`motion-duration-${durationTier}`, `motion-easing-${curve}`],
|
|
26289
|
+
description: `Semantic motion motion-${name}: ${mapping.properties.join(", ")} over ${durationTier} with ${curve}. ${mapping.sizeReasoning}`,
|
|
25956
26290
|
generatedAt: timestamp,
|
|
25957
26291
|
containerQueryAware: false,
|
|
25958
26292
|
reducedMotionAware: true,
|
|
@@ -25969,12 +26303,13 @@ function generateMotionTokens(config2, durationDefs, easingDefs, delayDefs, sema
|
|
|
25969
26303
|
ratio: progressionRatio,
|
|
25970
26304
|
ratioValue: ratioVal,
|
|
25971
26305
|
baseDuration: baseTransitionDuration,
|
|
25972
|
-
note: "Duration tiers are perceptually derived literals (docs/MOTION.md)
|
|
26306
|
+
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.",
|
|
26307
|
+
ratioDrivenKeyframes: ["ping", "pulse", "bounce"]
|
|
25973
26308
|
}),
|
|
25974
26309
|
category: "motion",
|
|
25975
26310
|
namespace: "motion",
|
|
25976
26311
|
semanticMeaning: "Metadata about the motion system",
|
|
25977
|
-
description: `Duration tiers are perceptual literals;
|
|
26312
|
+
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.`,
|
|
25978
26313
|
generatedAt: timestamp,
|
|
25979
26314
|
containerQueryAware: false,
|
|
25980
26315
|
userOverride: null
|
|
@@ -25998,16 +26333,17 @@ function generateRadiusTokens(config2, radiusDefs) {
|
|
|
25998
26333
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
25999
26334
|
const { baseRadius, progressionRatio } = config2;
|
|
26000
26335
|
const ratioVal = ratioValue(resolveRatio(progressionRatio));
|
|
26001
|
-
const
|
|
26336
|
+
const radiusMultiplier = Math.round(baseRadius / config2.baseSpacingUnit * 1e3) / 1e3;
|
|
26002
26337
|
tokens.push({
|
|
26003
26338
|
name: "radius-base",
|
|
26004
|
-
value:
|
|
26339
|
+
value: `calc(var(--rafters-spacing-base) * ${radiusMultiplier})`,
|
|
26005
26340
|
category: "radius",
|
|
26006
26341
|
namespace: "radius",
|
|
26007
|
-
semanticMeaning: "Base border radius -
|
|
26342
|
+
semanticMeaning: "Base border radius - derives from spacing base",
|
|
26008
26343
|
usageContext: ["calculation-reference"],
|
|
26009
26344
|
progressionSystem: progressionRatio,
|
|
26010
|
-
|
|
26345
|
+
dependsOn: ["spacing-base"],
|
|
26346
|
+
description: `Base radius = spacing-base * ${radiusMultiplier} (${baseRadius}px at base ${config2.baseSpacingUnit}). Scale uses ${progressionRatio} progression (ratio ${ratioVal}).`,
|
|
26011
26347
|
generatedAt: timestamp,
|
|
26012
26348
|
containerQueryAware: false,
|
|
26013
26349
|
userOverride: null,
|
|
@@ -26045,15 +26381,15 @@ function generateRadiusTokens(config2, radiusDefs) {
|
|
|
26045
26381
|
mathRelationship = "infinite (9999px)";
|
|
26046
26382
|
} else if (def.step === 0) {
|
|
26047
26383
|
value = "var(--rafters-radius-base)";
|
|
26048
|
-
mathRelationship =
|
|
26384
|
+
mathRelationship = `spacing-base * ${radiusMultiplier} (base)`;
|
|
26049
26385
|
} else {
|
|
26050
26386
|
const multiplier = Math.round(ratioVal ** def.step * 1e3) / 1e3;
|
|
26051
26387
|
value = `calc(var(--rafters-radius-base) * ${multiplier})`;
|
|
26052
26388
|
mathRelationship = `base \xD7 ${ratioVal}^${def.step} (\xD7${multiplier})`;
|
|
26053
26389
|
}
|
|
26054
|
-
const
|
|
26390
|
+
const scaleName2 = scale2 === "DEFAULT" ? "radius" : `radius-${scale2}`;
|
|
26055
26391
|
tokens.push({
|
|
26056
|
-
name:
|
|
26392
|
+
name: scaleName2,
|
|
26057
26393
|
value,
|
|
26058
26394
|
category: "radius",
|
|
26059
26395
|
namespace: "radius",
|
|
@@ -26242,40 +26578,69 @@ function generateSemanticTokens(_config) {
|
|
|
26242
26578
|
};
|
|
26243
26579
|
}
|
|
26244
26580
|
|
|
26581
|
+
// ../design-tokens/src/generators/progression.ts
|
|
26582
|
+
var NON_ADVANCING = 1;
|
|
26583
|
+
function progressionFrom(floor, ratioVal, ceiling) {
|
|
26584
|
+
if (!(ratioVal > NON_ADVANCING) || !(floor > 0) || !(ceiling >= floor)) return [floor];
|
|
26585
|
+
const out = [];
|
|
26586
|
+
const seen = /* @__PURE__ */ new Set();
|
|
26587
|
+
for (let n2 = 0; ; n2++) {
|
|
26588
|
+
const value = Math.round(floor * ratioVal ** n2);
|
|
26589
|
+
if (value > ceiling) break;
|
|
26590
|
+
if (!seen.has(value)) {
|
|
26591
|
+
seen.add(value);
|
|
26592
|
+
out.push(value);
|
|
26593
|
+
}
|
|
26594
|
+
}
|
|
26595
|
+
return out;
|
|
26596
|
+
}
|
|
26597
|
+
function nearestRung(target, scale2) {
|
|
26598
|
+
let best = scale2[0] ?? target;
|
|
26599
|
+
for (const v of scale2) {
|
|
26600
|
+
if (Math.abs(v - target) < Math.abs(best - target)) best = v;
|
|
26601
|
+
}
|
|
26602
|
+
return best;
|
|
26603
|
+
}
|
|
26604
|
+
|
|
26245
26605
|
// ../design-tokens/src/generators/shadow.ts
|
|
26246
|
-
function
|
|
26606
|
+
function pxToRem(px) {
|
|
26247
26607
|
const rem = Math.round(px / 16 * 1e3) / 1e3;
|
|
26248
26608
|
return `${rem}rem`;
|
|
26249
26609
|
}
|
|
26250
26610
|
var SHADOW_PARTS = ["offset-x", "offset-y", "blur", "spread", "color"];
|
|
26251
|
-
function
|
|
26252
|
-
return
|
|
26611
|
+
function shadowScale(ratioVal, bounds) {
|
|
26612
|
+
return progressionFrom(bounds.floor, ratioVal, bounds.ceiling);
|
|
26613
|
+
}
|
|
26614
|
+
function scalePx(multiplier, baseSpacing, scale2) {
|
|
26615
|
+
if (multiplier === 0) return 0;
|
|
26616
|
+
return nearestRung(multiplier * baseSpacing, scale2);
|
|
26253
26617
|
}
|
|
26254
|
-
function resolveShadowParts(def, baseSpacing) {
|
|
26618
|
+
function resolveShadowParts(def, baseSpacing, scale2) {
|
|
26255
26619
|
return {
|
|
26256
26620
|
// Shadows are vertical-only by design (material elevation model)
|
|
26257
26621
|
"offset-x": "0rem",
|
|
26258
|
-
"offset-y":
|
|
26259
|
-
blur:
|
|
26260
|
-
spread:
|
|
26622
|
+
"offset-y": pxToRem(scalePx(def.yOffset, baseSpacing, scale2)),
|
|
26623
|
+
blur: pxToRem(scalePx(def.blur, baseSpacing, scale2)),
|
|
26624
|
+
spread: pxToRem(scalePx(def.spread, baseSpacing, scale2)),
|
|
26261
26625
|
color: `rgb(0 0 0 / ${def.opacity})`
|
|
26262
26626
|
};
|
|
26263
26627
|
}
|
|
26264
|
-
function generateInnerShadowValue(inner, baseSpacing) {
|
|
26265
|
-
const y =
|
|
26266
|
-
const blur =
|
|
26267
|
-
const spread =
|
|
26628
|
+
function generateInnerShadowValue(inner, baseSpacing, scale2) {
|
|
26629
|
+
const y = pxToRem(scalePx(inner.yOffset, baseSpacing, scale2));
|
|
26630
|
+
const blur = pxToRem(scalePx(inner.blur, baseSpacing, scale2));
|
|
26631
|
+
const spread = pxToRem(scalePx(inner.spread, baseSpacing, scale2));
|
|
26268
26632
|
return `0 ${y} ${blur} ${spread} rgb(0 0 0 / ${inner.opacity})`;
|
|
26269
26633
|
}
|
|
26270
26634
|
function buildCompositeFromVars(prefix, innerValue) {
|
|
26271
26635
|
const primary = SHADOW_PARTS.map((part) => `var(--rafters-${prefix}-${part})`).join(" ");
|
|
26272
26636
|
return innerValue ? `${primary}, ${innerValue}` : primary;
|
|
26273
26637
|
}
|
|
26274
|
-
function generateShadowTokens(config2, shadowDefs) {
|
|
26638
|
+
function generateShadowTokens(config2, shadowDefs, bounds) {
|
|
26275
26639
|
const tokens = [];
|
|
26276
26640
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
26277
26641
|
const { baseSpacingUnit, progressionRatio } = config2;
|
|
26278
26642
|
const ratioVal = ratioValue(resolveRatio(progressionRatio));
|
|
26643
|
+
const geometry = shadowScale(ratioVal, bounds);
|
|
26279
26644
|
const baseSpacingRem = baseSpacingUnit / 16;
|
|
26280
26645
|
tokens.push({
|
|
26281
26646
|
name: "shadow-base-unit",
|
|
@@ -26295,10 +26660,10 @@ function generateShadowTokens(config2, shadowDefs) {
|
|
|
26295
26660
|
const def = shadowDefs[scale2];
|
|
26296
26661
|
if (!def) continue;
|
|
26297
26662
|
const scaleIndex = SHADOW_SCALE.indexOf(scale2);
|
|
26298
|
-
const
|
|
26663
|
+
const scaleName2 = scale2 === "DEFAULT" ? "shadow" : `shadow-${scale2}`;
|
|
26299
26664
|
if (def.opacity === 0) {
|
|
26300
26665
|
tokens.push({
|
|
26301
|
-
name:
|
|
26666
|
+
name: scaleName2,
|
|
26302
26667
|
value: "none",
|
|
26303
26668
|
category: "shadow",
|
|
26304
26669
|
namespace: "shadow",
|
|
@@ -26318,10 +26683,10 @@ function generateShadowTokens(config2, shadowDefs) {
|
|
|
26318
26683
|
});
|
|
26319
26684
|
continue;
|
|
26320
26685
|
}
|
|
26321
|
-
const parts = resolveShadowParts(def, baseSpacingUnit);
|
|
26686
|
+
const parts = resolveShadowParts(def, baseSpacingUnit, geometry);
|
|
26322
26687
|
const partDeps = [];
|
|
26323
26688
|
for (const part of SHADOW_PARTS) {
|
|
26324
|
-
const partName = `${
|
|
26689
|
+
const partName = `${scaleName2}-${part}`;
|
|
26325
26690
|
partDeps.push(partName);
|
|
26326
26691
|
tokens.push({
|
|
26327
26692
|
name: partName,
|
|
@@ -26338,10 +26703,10 @@ function generateShadowTokens(config2, shadowDefs) {
|
|
|
26338
26703
|
userOverride: null
|
|
26339
26704
|
});
|
|
26340
26705
|
}
|
|
26341
|
-
const innerValue = def.innerShadow && def.innerShadow.opacity > 0 ? generateInnerShadowValue(def.innerShadow, baseSpacingUnit) : null;
|
|
26342
|
-
const compositeValue = buildCompositeFromVars(
|
|
26706
|
+
const innerValue = def.innerShadow && def.innerShadow.opacity > 0 ? generateInnerShadowValue(def.innerShadow, baseSpacingUnit, geometry) : null;
|
|
26707
|
+
const compositeValue = buildCompositeFromVars(scaleName2, innerValue);
|
|
26343
26708
|
tokens.push({
|
|
26344
|
-
name:
|
|
26709
|
+
name: scaleName2,
|
|
26345
26710
|
value: compositeValue,
|
|
26346
26711
|
category: "shadow",
|
|
26347
26712
|
namespace: "shadow",
|
|
@@ -26350,7 +26715,7 @@ function generateShadowTokens(config2, shadowDefs) {
|
|
|
26350
26715
|
scalePosition: scaleIndex,
|
|
26351
26716
|
progressionSystem: progressionRatio,
|
|
26352
26717
|
dependsOn: partDeps,
|
|
26353
|
-
description: `Shadow ${scale2}: ${def.meaning}. Composed from var() refs to ${
|
|
26718
|
+
description: `Shadow ${scale2}: ${def.meaning}. Composed from var() refs to ${scaleName2}-* tokens.`,
|
|
26354
26719
|
generatedAt: timestamp,
|
|
26355
26720
|
containerQueryAware: false,
|
|
26356
26721
|
userOverride: null,
|
|
@@ -26423,13 +26788,19 @@ function generateShadowTokens(config2, shadowDefs) {
|
|
|
26423
26788
|
}
|
|
26424
26789
|
|
|
26425
26790
|
// ../design-tokens/src/generators/spacing.ts
|
|
26426
|
-
function
|
|
26791
|
+
function spacingMultipliers(ratioVal, bounds) {
|
|
26792
|
+
return progressionFrom(bounds.floor, ratioVal, bounds.ceiling);
|
|
26793
|
+
}
|
|
26794
|
+
function scaleName(multiplier) {
|
|
26795
|
+
return String(multiplier);
|
|
26796
|
+
}
|
|
26797
|
+
function generateSpacingTokens(config2, bounds) {
|
|
26427
26798
|
const tokens = [];
|
|
26428
26799
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
26429
26800
|
const { baseSpacingUnit, progressionRatio } = config2;
|
|
26430
26801
|
const ratio = resolveRatio(progressionRatio);
|
|
26431
26802
|
const ratioVal = ratioValue(ratio);
|
|
26432
|
-
const
|
|
26803
|
+
const multipliers = spacingMultipliers(ratioVal, bounds);
|
|
26433
26804
|
const baseRem = baseSpacingUnit / 16;
|
|
26434
26805
|
tokens.push({
|
|
26435
26806
|
name: "spacing-base",
|
|
@@ -26454,11 +26825,10 @@ function generateSpacingTokens(config2, spacingMultipliers) {
|
|
|
26454
26825
|
]
|
|
26455
26826
|
}
|
|
26456
26827
|
});
|
|
26457
|
-
for (const
|
|
26458
|
-
const
|
|
26459
|
-
if (multiplier === void 0) continue;
|
|
26828
|
+
for (const multiplier of [0, ...multipliers]) {
|
|
26829
|
+
const scale2 = scaleName(multiplier);
|
|
26460
26830
|
const value = baseSpacingUnit * multiplier;
|
|
26461
|
-
const scaleIndex =
|
|
26831
|
+
const scaleIndex = multipliers.indexOf(multiplier) + 1;
|
|
26462
26832
|
let meaning;
|
|
26463
26833
|
let usageContext;
|
|
26464
26834
|
if (multiplier === 0) {
|
|
@@ -26505,16 +26875,19 @@ function generateSpacingTokens(config2, spacingMultipliers) {
|
|
|
26505
26875
|
}
|
|
26506
26876
|
tokens.push({
|
|
26507
26877
|
name: "spacing-progression",
|
|
26878
|
+
// The scale that actually shipped. Before #2031 this carried a `sample`
|
|
26879
|
+
// computed straight off the ratio while the tokens came from a table --
|
|
26880
|
+
// metadata describing a scale that did not exist.
|
|
26508
26881
|
value: JSON.stringify({
|
|
26509
26882
|
ratio: progressionRatio,
|
|
26510
26883
|
ratioValue: ratioVal,
|
|
26511
26884
|
baseUnit: baseSpacingUnit,
|
|
26512
|
-
|
|
26885
|
+
multipliers
|
|
26513
26886
|
}),
|
|
26514
26887
|
category: "spacing",
|
|
26515
26888
|
namespace: "spacing",
|
|
26516
26889
|
semanticMeaning: "Metadata about the spacing progression system",
|
|
26517
|
-
description: `Spacing
|
|
26890
|
+
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.`,
|
|
26518
26891
|
generatedAt: timestamp,
|
|
26519
26892
|
containerQueryAware: false,
|
|
26520
26893
|
userOverride: null,
|
|
@@ -26851,7 +27224,7 @@ function createGeneratorDefs(colorPaletteBases) {
|
|
|
26851
27224
|
},
|
|
26852
27225
|
{
|
|
26853
27226
|
name: "spacing",
|
|
26854
|
-
generate: (config2) => generateSpacingTokens(config2,
|
|
27227
|
+
generate: (config2) => generateSpacingTokens(config2, DEFAULT_SPACING_BOUNDS)
|
|
26855
27228
|
},
|
|
26856
27229
|
{
|
|
26857
27230
|
name: "typography",
|
|
@@ -26872,7 +27245,7 @@ function createGeneratorDefs(colorPaletteBases) {
|
|
|
26872
27245
|
},
|
|
26873
27246
|
{
|
|
26874
27247
|
name: "shadow",
|
|
26875
|
-
generate: (config2) => generateShadowTokens(config2, DEFAULT_SHADOW_DEFINITIONS)
|
|
27248
|
+
generate: (config2) => generateShadowTokens(config2, DEFAULT_SHADOW_DEFINITIONS, DEFAULT_SHADOW_BOUNDS)
|
|
26876
27249
|
},
|
|
26877
27250
|
{
|
|
26878
27251
|
name: "depth",
|
|
@@ -26884,8 +27257,14 @@ function createGeneratorDefs(colorPaletteBases) {
|
|
|
26884
27257
|
config2,
|
|
26885
27258
|
DEFAULT_DURATION_DEFINITIONS,
|
|
26886
27259
|
DEFAULT_EASING_DEFINITIONS,
|
|
26887
|
-
|
|
26888
|
-
|
|
27260
|
+
DEFAULT_DELAY_NAMESPACE,
|
|
27261
|
+
DEFAULT_EXTENT_NAMESPACE,
|
|
27262
|
+
DEFAULT_PERIOD_NAMESPACE,
|
|
27263
|
+
DEFAULT_MOTION_SEMANTIC_MAPPINGS,
|
|
27264
|
+
DEFAULT_KEYFRAME_DEFINITIONS,
|
|
27265
|
+
DEFAULT_ANIMATION_DEFINITIONS,
|
|
27266
|
+
DEFAULT_MOTION_COMPOSITE_PRESETS,
|
|
27267
|
+
DEFAULT_MOTION_CELL_ANIMATIONS
|
|
26889
27268
|
)
|
|
26890
27269
|
},
|
|
26891
27270
|
{
|
|
@@ -26924,7 +27303,10 @@ function generateBaseSystem(config2 = {}) {
|
|
|
26924
27303
|
var UserOverrideSchema = external_exports.object({
|
|
26925
27304
|
previousValue: external_exports.unknown(),
|
|
26926
27305
|
reason: external_exports.string(),
|
|
26927
|
-
context: external_exports.string().optional()
|
|
27306
|
+
context: external_exports.string().optional(),
|
|
27307
|
+
// Provenance. Optional by design: absent means unknown, which is what every
|
|
27308
|
+
// override written before this field existed actually is.
|
|
27309
|
+
kind: OverrideKindSchema.optional()
|
|
26928
27310
|
});
|
|
26929
27311
|
var BindingSchema2 = external_exports.object({
|
|
26930
27312
|
plugin: external_exports.string(),
|
|
@@ -26969,7 +27351,8 @@ var TokenGraph = class {
|
|
|
26969
27351
|
userOverride: {
|
|
26970
27352
|
previousValue: existing?.value,
|
|
26971
27353
|
reason: options.reason,
|
|
26972
|
-
...options.context ? { context: options.context } : {}
|
|
27354
|
+
...options.context ? { context: options.context } : {},
|
|
27355
|
+
...options.kind ? { kind: options.kind } : {}
|
|
26973
27356
|
},
|
|
26974
27357
|
...existing?.binding ? { binding: existing.binding } : {}
|
|
26975
27358
|
};
|
|
@@ -27535,7 +27918,7 @@ async function regenerateOutputs(registry2, input, hooks2 = {}) {
|
|
|
27535
27918
|
written.push("rafters.standalone.css");
|
|
27536
27919
|
}
|
|
27537
27920
|
if (exports.documentation) {
|
|
27538
|
-
const doc = await registryToDocumentation(registry2);
|
|
27921
|
+
const doc = await registryToDocumentation(registry2, { contentSources });
|
|
27539
27922
|
await writeFile(join2(outputDir2, "rafters.documentation.css"), doc);
|
|
27540
27923
|
written.push("rafters.documentation.css");
|
|
27541
27924
|
}
|
|
@@ -27565,11 +27948,7 @@ var TokenRegistry = class {
|
|
|
27565
27948
|
parsed.push(result.data);
|
|
27566
27949
|
}
|
|
27567
27950
|
for (const t of parsed) {
|
|
27568
|
-
const override = t.userOverride
|
|
27569
|
-
previousValue: t.userOverride.previousValue,
|
|
27570
|
-
reason: t.userOverride.reason,
|
|
27571
|
-
...t.userOverride.context ? { context: t.userOverride.context } : {}
|
|
27572
|
-
} : void 0;
|
|
27951
|
+
const override = toNodeOverride(t.userOverride);
|
|
27573
27952
|
if (t.binding && !override) continue;
|
|
27574
27953
|
this.graph.seed(t.name, t.value, {
|
|
27575
27954
|
...override ? { userOverride: override } : {},
|
|
@@ -27593,11 +27972,7 @@ var TokenRegistry = class {
|
|
|
27593
27972
|
}
|
|
27594
27973
|
const t = result.data;
|
|
27595
27974
|
this.metadata.set(t.name, t);
|
|
27596
|
-
const override = t.userOverride
|
|
27597
|
-
previousValue: t.userOverride.previousValue,
|
|
27598
|
-
reason: t.userOverride.reason,
|
|
27599
|
-
...t.userOverride.context ? { context: t.userOverride.context } : {}
|
|
27600
|
-
} : void 0;
|
|
27975
|
+
const override = toNodeOverride(t.userOverride);
|
|
27601
27976
|
if (t.binding && !override) {
|
|
27602
27977
|
this.graph.bind(t.name, t.binding.plugin, t.binding.input);
|
|
27603
27978
|
} else {
|
|
@@ -27673,6 +28048,15 @@ var TokenParseError = class extends Error {
|
|
|
27673
28048
|
this.name = "TokenParseError";
|
|
27674
28049
|
}
|
|
27675
28050
|
};
|
|
28051
|
+
function toNodeOverride(field) {
|
|
28052
|
+
if (!field) return void 0;
|
|
28053
|
+
return {
|
|
28054
|
+
previousValue: field.previousValue,
|
|
28055
|
+
reason: field.reason,
|
|
28056
|
+
...field.context ? { context: field.context } : {},
|
|
28057
|
+
...field.kind ? { kind: field.kind } : {}
|
|
28058
|
+
};
|
|
28059
|
+
}
|
|
27676
28060
|
function toUserOverrideField(override, baseValue) {
|
|
27677
28061
|
const previousValue = override.previousValue ?? baseValue;
|
|
27678
28062
|
const result = {
|
|
@@ -27680,6 +28064,7 @@ function toUserOverrideField(override, baseValue) {
|
|
|
27680
28064
|
reason: override.reason
|
|
27681
28065
|
};
|
|
27682
28066
|
if (override.context) result.context = override.context;
|
|
28067
|
+
if (override.kind) result.kind = override.kind;
|
|
27683
28068
|
return result;
|
|
27684
28069
|
}
|
|
27685
28070
|
|
|
@@ -28520,15 +28905,37 @@ function log(event) {
|
|
|
28520
28905
|
console.log(` ${event.suggestion}`);
|
|
28521
28906
|
}
|
|
28522
28907
|
break;
|
|
28523
|
-
case "add:complete":
|
|
28524
|
-
|
|
28525
|
-
|
|
28526
|
-
|
|
28527
|
-
|
|
28528
|
-
|
|
28908
|
+
case "add:complete": {
|
|
28909
|
+
const written = event.written;
|
|
28910
|
+
const skippedCount = event.skipped;
|
|
28911
|
+
const untrackedCount = event.untracked;
|
|
28912
|
+
const failedCount = event.failed;
|
|
28913
|
+
const headline = `Wrote ${written} item${written !== 1 ? "s" : ""}`;
|
|
28914
|
+
if (failedCount > 0) {
|
|
28915
|
+
context.spinner?.fail(`${headline}, ${failedCount} failed -- see below`);
|
|
28916
|
+
} else {
|
|
28917
|
+
context.spinner?.succeed(headline);
|
|
28918
|
+
}
|
|
28919
|
+
if (skippedCount > 0) {
|
|
28920
|
+
const names = event.skippedComponents ?? [];
|
|
28921
|
+
console.log(
|
|
28922
|
+
` Skipped: ${skippedCount} (already present; use --update to re-fetch)${names.length > 0 ? ` -- ${names.join(", ")}` : ""}`
|
|
28923
|
+
);
|
|
28924
|
+
}
|
|
28925
|
+
if (untrackedCount > 0) {
|
|
28926
|
+
const names = event.untrackedComponents ?? [];
|
|
28927
|
+
console.log(` Untracked on disk, now tracked: ${untrackedCount} -- ${names.join(", ")}`);
|
|
28928
|
+
}
|
|
28929
|
+
if (failedCount > 0) {
|
|
28930
|
+
const names = event.failedComponents ?? [];
|
|
28931
|
+
console.log(` Failed: ${failedCount} -- ${names.join(", ")}`);
|
|
28529
28932
|
}
|
|
28530
28933
|
console.log("");
|
|
28531
28934
|
break;
|
|
28935
|
+
}
|
|
28936
|
+
case "add:untracked":
|
|
28937
|
+
console.log(` ${event.message}`);
|
|
28938
|
+
break;
|
|
28532
28939
|
case "add:hint":
|
|
28533
28940
|
console.log(`
|
|
28534
28941
|
${event.message}`);
|
|
@@ -28878,6 +29285,51 @@ function resolveReadSet(field, cwd, fallback) {
|
|
|
28878
29285
|
return out;
|
|
28879
29286
|
}
|
|
28880
29287
|
|
|
29288
|
+
// src/utils/reconcile.ts
|
|
29289
|
+
import { readdirSync as readdirSync2 } from "fs";
|
|
29290
|
+
var DISCOVERABLE_KINDS = ["components", "primitives", "composites"];
|
|
29291
|
+
var KIND_PATHS = {
|
|
29292
|
+
components: { field: "componentsPath", fallback: "components/ui" },
|
|
29293
|
+
primitives: { field: "primitivesPath", fallback: "lib/primitives" },
|
|
29294
|
+
composites: { field: "compositesPath", fallback: "composites" }
|
|
29295
|
+
};
|
|
29296
|
+
function hasEntryFor(entries, name) {
|
|
29297
|
+
return entries.some((entry) => entry === name || entry.startsWith(`${name}.`));
|
|
29298
|
+
}
|
|
29299
|
+
function buildUpdateCandidates(tracked, index, entries) {
|
|
29300
|
+
const trackedSet = new Set(tracked);
|
|
29301
|
+
const untracked = /* @__PURE__ */ new Set();
|
|
29302
|
+
if (index) {
|
|
29303
|
+
for (const kind of DISCOVERABLE_KINDS) {
|
|
29304
|
+
for (const name of index[kind]) {
|
|
29305
|
+
if (trackedSet.has(name)) continue;
|
|
29306
|
+
if (hasEntryFor(entries[kind], name)) untracked.add(name);
|
|
29307
|
+
}
|
|
29308
|
+
}
|
|
29309
|
+
}
|
|
29310
|
+
return { tracked: [...trackedSet].sort(), untracked: [...untracked].sort() };
|
|
29311
|
+
}
|
|
29312
|
+
function readInstallRoots(cwd, config2) {
|
|
29313
|
+
const entries = { components: [], primitives: [], composites: [] };
|
|
29314
|
+
for (const kind of DISCOVERABLE_KINDS) {
|
|
29315
|
+
const { field, fallback } = KIND_PATHS[kind];
|
|
29316
|
+
const configured = config2?.[field];
|
|
29317
|
+
const pathField = isPathField(configured) ? configured : fallback;
|
|
29318
|
+
const names = /* @__PURE__ */ new Set();
|
|
29319
|
+
for (const dir of resolveReadSet(pathField, cwd, fallback)) {
|
|
29320
|
+
try {
|
|
29321
|
+
for (const entry of readdirSync2(dir)) names.add(entry);
|
|
29322
|
+
} catch {
|
|
29323
|
+
}
|
|
29324
|
+
}
|
|
29325
|
+
entries[kind] = [...names];
|
|
29326
|
+
}
|
|
29327
|
+
return entries;
|
|
29328
|
+
}
|
|
29329
|
+
function isPathField(value) {
|
|
29330
|
+
return typeof value === "string" || Array.isArray(value);
|
|
29331
|
+
}
|
|
29332
|
+
|
|
28881
29333
|
// src/commands/add.ts
|
|
28882
29334
|
var REGISTRY_PLUGINS = [scalePlugin, contrastPlugin, statePlugin, invertPlugin];
|
|
28883
29335
|
async function regenerateAfterInstall(cwd, config2) {
|
|
@@ -28938,10 +29390,26 @@ function getInstalledNames(config2) {
|
|
|
28938
29390
|
const names = /* @__PURE__ */ new Set([
|
|
28939
29391
|
...config2.installed.components,
|
|
28940
29392
|
...config2.installed.primitives,
|
|
28941
|
-
...config2.installed.composites ?? []
|
|
29393
|
+
...config2.installed.composites ?? [],
|
|
29394
|
+
...config2.installed.rules ?? [],
|
|
29395
|
+
...config2.installed.substrate ?? []
|
|
28942
29396
|
]);
|
|
28943
29397
|
return [...names].sort();
|
|
28944
29398
|
}
|
|
29399
|
+
async function discoverUntrackedNames(cwd, config2, client, tracked) {
|
|
29400
|
+
let index = null;
|
|
29401
|
+
try {
|
|
29402
|
+
index = await client.fetchIndex();
|
|
29403
|
+
} catch (err) {
|
|
29404
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
29405
|
+
log({
|
|
29406
|
+
event: "add:warning",
|
|
29407
|
+
message: `Could not read the registry index to reconcile on-disk components (${message}). Updating tracked components only.`
|
|
29408
|
+
});
|
|
29409
|
+
}
|
|
29410
|
+
const { untracked } = buildUpdateCandidates(tracked, index, readInstallRoots(cwd, config2));
|
|
29411
|
+
return untracked;
|
|
29412
|
+
}
|
|
28945
29413
|
function getComponentTarget(config2) {
|
|
28946
29414
|
return resolveComponentTarget(config2);
|
|
28947
29415
|
}
|
|
@@ -29187,6 +29655,7 @@ async function add(componentArgs, options) {
|
|
|
29187
29655
|
if (options.update) {
|
|
29188
29656
|
options.overwrite = true;
|
|
29189
29657
|
}
|
|
29658
|
+
let untrackedNames = [];
|
|
29190
29659
|
if (options.updateAll) {
|
|
29191
29660
|
options.overwrite = true;
|
|
29192
29661
|
if (!config2) {
|
|
@@ -29194,13 +29663,22 @@ async function add(componentArgs, options) {
|
|
|
29194
29663
|
process.exitCode = 1;
|
|
29195
29664
|
return;
|
|
29196
29665
|
}
|
|
29197
|
-
const
|
|
29198
|
-
|
|
29666
|
+
const trackedNames = getInstalledNames(config2);
|
|
29667
|
+
untrackedNames = await discoverUntrackedNames(cwd, config2, client, trackedNames);
|
|
29668
|
+
const candidates = [.../* @__PURE__ */ new Set([...trackedNames, ...untrackedNames])].sort();
|
|
29669
|
+
if (candidates.length === 0) {
|
|
29199
29670
|
error46("No installed components found. Use 'rafters add <component>' to install first.");
|
|
29200
29671
|
process.exitCode = 1;
|
|
29201
29672
|
return;
|
|
29202
29673
|
}
|
|
29203
|
-
|
|
29674
|
+
if (untrackedNames.length > 0) {
|
|
29675
|
+
log({
|
|
29676
|
+
event: "add:untracked",
|
|
29677
|
+
components: untrackedNames,
|
|
29678
|
+
message: `Found ${untrackedNames.length} component(s) on disk the config never tracked: ${untrackedNames.join(", ")}. Refreshing and tracking them.`
|
|
29679
|
+
});
|
|
29680
|
+
}
|
|
29681
|
+
components = candidates;
|
|
29204
29682
|
}
|
|
29205
29683
|
if (folder === "composites" && components.length === 0) {
|
|
29206
29684
|
components = ["composites"];
|
|
@@ -29251,8 +29729,9 @@ async function add(componentArgs, options) {
|
|
|
29251
29729
|
allItems.filter((item) => item.type === "substrate").map((item) => item.files[0]?.path.split("/")[0]).filter((segment) => Boolean(segment))
|
|
29252
29730
|
)
|
|
29253
29731
|
];
|
|
29254
|
-
const
|
|
29732
|
+
const written = [];
|
|
29255
29733
|
const skipped = [];
|
|
29734
|
+
const failed = [];
|
|
29256
29735
|
const installedItems = [];
|
|
29257
29736
|
const filteredItems = [];
|
|
29258
29737
|
const target = getComponentTarget(config2);
|
|
@@ -29276,7 +29755,7 @@ async function add(componentArgs, options) {
|
|
|
29276
29755
|
try {
|
|
29277
29756
|
const result = await installItem(cwd, item, options, config2, substrateKinds);
|
|
29278
29757
|
if (result.installed) {
|
|
29279
|
-
|
|
29758
|
+
written.push(item.name);
|
|
29280
29759
|
installedItems.push(item);
|
|
29281
29760
|
if (item.type === "ui") {
|
|
29282
29761
|
const selection = selectFilesForFramework(item.files, target);
|
|
@@ -29296,6 +29775,7 @@ async function add(componentArgs, options) {
|
|
|
29296
29775
|
installedItems.push(item);
|
|
29297
29776
|
}
|
|
29298
29777
|
} catch (err) {
|
|
29778
|
+
failed.push(item.name);
|
|
29299
29779
|
if (err instanceof Error) {
|
|
29300
29780
|
log({
|
|
29301
29781
|
event: "add:warning",
|
|
@@ -29353,11 +29833,19 @@ async function add(componentArgs, options) {
|
|
|
29353
29833
|
}
|
|
29354
29834
|
log({
|
|
29355
29835
|
event: "add:complete",
|
|
29356
|
-
|
|
29836
|
+
written: written.length,
|
|
29357
29837
|
skipped: skipped.length,
|
|
29358
|
-
|
|
29359
|
-
|
|
29360
|
-
|
|
29838
|
+
untracked: untrackedNames.length,
|
|
29839
|
+
failed: failed.length,
|
|
29840
|
+
components: written,
|
|
29841
|
+
skippedComponents: skipped,
|
|
29842
|
+
untrackedComponents: untrackedNames,
|
|
29843
|
+
failedComponents: failed
|
|
29844
|
+
});
|
|
29845
|
+
if (failed.length > 0) {
|
|
29846
|
+
process.exitCode = 1;
|
|
29847
|
+
}
|
|
29848
|
+
if (!options.updateAll && skipped.length > 0 && written.length === 0) {
|
|
29361
29849
|
log({
|
|
29362
29850
|
event: "add:hint",
|
|
29363
29851
|
message: "Some components were skipped. Use --update to re-fetch, or --update-all to refresh everything.",
|
|
@@ -30240,6 +30728,24 @@ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
|
30240
30728
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
30241
30729
|
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
30242
30730
|
|
|
30731
|
+
// src/version.ts
|
|
30732
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
30733
|
+
var UNKNOWN_VERSION = "0.0.0-unknown";
|
|
30734
|
+
function readVersion() {
|
|
30735
|
+
try {
|
|
30736
|
+
const parsed = JSON.parse(
|
|
30737
|
+
readFileSync2(new URL("../package.json", import.meta.url), "utf-8")
|
|
30738
|
+
);
|
|
30739
|
+
if (parsed !== null && typeof parsed === "object" && "version" in parsed) {
|
|
30740
|
+
const { version: version2 } = parsed;
|
|
30741
|
+
if (typeof version2 === "string" && version2.length > 0) return version2;
|
|
30742
|
+
}
|
|
30743
|
+
} catch {
|
|
30744
|
+
}
|
|
30745
|
+
return UNKNOWN_VERSION;
|
|
30746
|
+
}
|
|
30747
|
+
var VERSION = readVersion();
|
|
30748
|
+
|
|
30243
30749
|
// src/mcp/tools.ts
|
|
30244
30750
|
import { readFile as readFile6 } from "fs/promises";
|
|
30245
30751
|
import { join as join12 } from "path";
|
|
@@ -30455,7 +30961,7 @@ async function discoverFromDirs(...directories) {
|
|
|
30455
30961
|
}
|
|
30456
30962
|
|
|
30457
30963
|
// src/utils/workspaces.ts
|
|
30458
|
-
import { existsSync as existsSync6, readdirSync as
|
|
30964
|
+
import { existsSync as existsSync6, readdirSync as readdirSync3, readFileSync as readFileSync3, statSync as statSync2 } from "fs";
|
|
30459
30965
|
import { basename, dirname as dirname3, join as join11, resolve as resolve4 } from "path";
|
|
30460
30966
|
|
|
30461
30967
|
// src/utils/discover.ts
|
|
@@ -30483,14 +30989,14 @@ function findMonorepoRoot(startDir, boundary) {
|
|
|
30483
30989
|
for (; ; ) {
|
|
30484
30990
|
const pnpmWorkspace = join11(current, "pnpm-workspace.yaml");
|
|
30485
30991
|
if (existsSync6(pnpmWorkspace)) {
|
|
30486
|
-
const patterns = parsePnpmWorkspaceYaml(
|
|
30992
|
+
const patterns = parsePnpmWorkspaceYaml(readFileSync3(pnpmWorkspace, "utf-8"));
|
|
30487
30993
|
if (patterns.length > 0) {
|
|
30488
30994
|
return { root: current, patterns };
|
|
30489
30995
|
}
|
|
30490
30996
|
}
|
|
30491
30997
|
const pkgJson = join11(current, "package.json");
|
|
30492
30998
|
if (existsSync6(pkgJson)) {
|
|
30493
|
-
const patterns = parsePackageJsonWorkspaces(
|
|
30999
|
+
const patterns = parsePackageJsonWorkspaces(readFileSync3(pkgJson, "utf-8"));
|
|
30494
31000
|
if (patterns.length > 0) {
|
|
30495
31001
|
return { root: current, patterns };
|
|
30496
31002
|
}
|
|
@@ -30546,7 +31052,7 @@ function expandPattern(monorepoRoot, pattern) {
|
|
|
30546
31052
|
const parentRel = trimmed.slice(0, -2);
|
|
30547
31053
|
const parent = join11(monorepoRoot, parentRel);
|
|
30548
31054
|
if (!existsSync6(parent)) return [];
|
|
30549
|
-
return
|
|
31055
|
+
return readdirSync3(parent).map((entry) => join11(parent, entry)).filter((path) => {
|
|
30550
31056
|
try {
|
|
30551
31057
|
return statSync2(path).isDirectory();
|
|
30552
31058
|
} catch {
|
|
@@ -30935,7 +31441,7 @@ async function startMcpServer(workspaces, defaultWorkspace) {
|
|
|
30935
31441
|
const server = new Server(
|
|
30936
31442
|
{
|
|
30937
31443
|
name: "rafters",
|
|
30938
|
-
version:
|
|
31444
|
+
version: VERSION
|
|
30939
31445
|
},
|
|
30940
31446
|
{
|
|
30941
31447
|
capabilities: {
|
|
@@ -31731,7 +32237,7 @@ async function studio() {
|
|
|
31731
32237
|
|
|
31732
32238
|
// src/index.ts
|
|
31733
32239
|
var program = new Command();
|
|
31734
|
-
program.name("rafters").description("Design system CLI - scaffold tokens and serve MCP").version(
|
|
32240
|
+
program.name("rafters").description("Design system CLI - scaffold tokens and serve MCP").version(VERSION);
|
|
31735
32241
|
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(
|
|
31736
32242
|
"--framework <name>",
|
|
31737
32243
|
"Override framework detection (next|vite|remix|react-router|astro|wc|vanilla)"
|