@usefragments/core 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (228) hide show
  1. package/LICENSE +21 -0
  2. package/dist/chunk-243QYRUF.js +2145 -0
  3. package/dist/chunk-243QYRUF.js.map +1 -0
  4. package/dist/chunk-3LLRNCPX.js +111 -0
  5. package/dist/chunk-3LLRNCPX.js.map +1 -0
  6. package/dist/chunk-EIYNNS77.js +48 -0
  7. package/dist/chunk-EIYNNS77.js.map +1 -0
  8. package/dist/chunk-JNBFJ34I.js +326 -0
  9. package/dist/chunk-JNBFJ34I.js.map +1 -0
  10. package/dist/chunk-R3X7UBHU.js +228 -0
  11. package/dist/chunk-R3X7UBHU.js.map +1 -0
  12. package/dist/chunk-SH4KPIYH.js +393 -0
  13. package/dist/chunk-SH4KPIYH.js.map +1 -0
  14. package/dist/chunk-V4VQB57N.js +56 -0
  15. package/dist/chunk-V4VQB57N.js.map +1 -0
  16. package/dist/chunk-X34IA4LR.js +319 -0
  17. package/dist/chunk-X34IA4LR.js.map +1 -0
  18. package/dist/chunk-YF65VYRY.js +493 -0
  19. package/dist/chunk-YF65VYRY.js.map +1 -0
  20. package/dist/codes/index.d.ts +40 -0
  21. package/dist/codes/index.js +23 -0
  22. package/dist/codes/index.js.map +1 -0
  23. package/dist/compiled-types/index.d.ts +5 -0
  24. package/dist/compiled-types/index.js +1 -0
  25. package/dist/compiled-types/index.js.map +1 -0
  26. package/dist/generate/index.d.ts +47 -0
  27. package/dist/generate/index.js +11 -0
  28. package/dist/generate/index.js.map +1 -0
  29. package/dist/governance-BOa3KyiJ.d.ts +3279 -0
  30. package/dist/graph/index.d.ts +66 -0
  31. package/dist/graph/index.js +17 -0
  32. package/dist/graph/index.js.map +1 -0
  33. package/dist/index.d.ts +11388 -0
  34. package/dist/index.js +8711 -0
  35. package/dist/index.js.map +1 -0
  36. package/dist/package-identity.d.ts +42 -0
  37. package/dist/package-identity.js +23 -0
  38. package/dist/package-identity.js.map +1 -0
  39. package/dist/preview/index.d.ts +484 -0
  40. package/dist/preview/index.js +1129 -0
  41. package/dist/preview/index.js.map +1 -0
  42. package/dist/react-types.d.ts +22 -0
  43. package/dist/react-types.js +1 -0
  44. package/dist/react-types.js.map +1 -0
  45. package/dist/registry.d.ts +2367 -0
  46. package/dist/registry.js +62 -0
  47. package/dist/registry.js.map +1 -0
  48. package/dist/schemas/index.d.ts +2584 -0
  49. package/dist/schemas/index.js +55 -0
  50. package/dist/schemas/index.js.map +1 -0
  51. package/dist/severity.d.ts +18 -0
  52. package/dist/severity.js +27 -0
  53. package/dist/severity.js.map +1 -0
  54. package/dist/test-utils.d.ts +14 -0
  55. package/dist/test-utils.js +63 -0
  56. package/dist/test-utils.js.map +1 -0
  57. package/dist/topology/index.d.ts +48 -0
  58. package/dist/topology/index.js +7 -0
  59. package/dist/topology/index.js.map +1 -0
  60. package/dist/types-xJ2xyp_G.d.ts +119 -0
  61. package/package.json +120 -0
  62. package/src/__tests__/contract-parser.test.ts +614 -0
  63. package/src/__tests__/dtcg-generators.test.ts +439 -0
  64. package/src/__tests__/dtcg-parser.test.ts +884 -0
  65. package/src/__tests__/preview-runtime.test.tsx +111 -0
  66. package/src/__tests__/schema.test.ts +31 -0
  67. package/src/__tests__/severity.test.ts +34 -0
  68. package/src/__tests__/style-comparison.test.ts +662 -0
  69. package/src/__tests__/tokens-compat.test.ts +51 -0
  70. package/src/agent-format.test.ts +105 -0
  71. package/src/agent-format.ts +141 -0
  72. package/src/bundle.ts +149 -0
  73. package/src/codes/__tests__/codes.test.ts +73 -0
  74. package/src/codes/codes.ts +463 -0
  75. package/src/codes/index.ts +7 -0
  76. package/src/codes/source-finding-bridge.ts +113 -0
  77. package/src/compiled-types/index.ts +293 -0
  78. package/src/component-contract.ts +231 -0
  79. package/src/component-discovery.ts +80 -0
  80. package/src/composition.test.ts +262 -0
  81. package/src/composition.ts +318 -0
  82. package/src/config-paths.test.ts +78 -0
  83. package/src/config-paths.ts +47 -0
  84. package/src/config.ts +18 -0
  85. package/src/conform-prove.test.ts +274 -0
  86. package/src/conform-prove.ts +326 -0
  87. package/src/conform.ts +160 -0
  88. package/src/constants.ts +114 -0
  89. package/src/context.ts +2 -0
  90. package/src/contract/fixture.ts +110 -0
  91. package/src/contract/hash.test.ts +86 -0
  92. package/src/contract/hash.ts +195 -0
  93. package/src/contract/index.ts +43 -0
  94. package/src/contract/preimage.test.ts +254 -0
  95. package/src/contract/preimage.ts +365 -0
  96. package/src/contract/stamp.test.ts +100 -0
  97. package/src/contract/stamp.ts +105 -0
  98. package/src/contract-parser.ts +141 -0
  99. package/src/defineFragment.test.ts +257 -0
  100. package/src/defineFragment.ts +293 -0
  101. package/src/dtcg-generators.ts +324 -0
  102. package/src/dtcg-parser.ts +1 -0
  103. package/src/dtcg.ts +237 -0
  104. package/src/facts/__snapshots__/facts.test.ts.snap +124 -0
  105. package/src/facts/builders.ts +835 -0
  106. package/src/facts/compile.ts +422 -0
  107. package/src/facts/fact-index.ts +394 -0
  108. package/src/facts/facts.test.ts +494 -0
  109. package/src/facts/ids.ts +125 -0
  110. package/src/facts/index.ts +119 -0
  111. package/src/facts/types.ts +614 -0
  112. package/src/figma.ts +263 -0
  113. package/src/fragment-types.ts +214 -0
  114. package/src/generate/generate.test.ts +594 -0
  115. package/src/generate/index.ts +438 -0
  116. package/src/governance-integrity.test.ts +186 -0
  117. package/src/governance-integrity.ts +282 -0
  118. package/src/governance.test.ts +300 -0
  119. package/src/governance.ts +605 -0
  120. package/src/governance.type-test.ts +75 -0
  121. package/src/graph/engine.ts +446 -0
  122. package/src/graph/graph.test.ts +746 -0
  123. package/src/graph/index.ts +32 -0
  124. package/src/graph/serialization.ts +55 -0
  125. package/src/graph/types.ts +178 -0
  126. package/src/index.ts +891 -0
  127. package/src/local-canonical.ts +102 -0
  128. package/src/mcp-snapshot.ts +222 -0
  129. package/src/package-identity-match.ts +33 -0
  130. package/src/package-identity.generated.ts +233 -0
  131. package/src/package-identity.test.ts +99 -0
  132. package/src/package-identity.ts +157 -0
  133. package/src/performance-presets.ts +142 -0
  134. package/src/preview/comparison-artifact.test.ts +228 -0
  135. package/src/preview/comparison-artifact.ts +181 -0
  136. package/src/preview/comparison-context.ts +93 -0
  137. package/src/preview/comparison-evidence.ts +112 -0
  138. package/src/preview/comparison-format.ts +21 -0
  139. package/src/preview/comparison-presentation.ts +187 -0
  140. package/src/preview/comparison-references.test.ts +430 -0
  141. package/src/preview/comparison-references.ts +72 -0
  142. package/src/preview/comparison-score.ts +59 -0
  143. package/src/preview/comparison-styles.ts +197 -0
  144. package/src/preview/comparison.test.ts +559 -0
  145. package/src/preview/comparison.ts +488 -0
  146. package/src/preview/index.ts +10 -0
  147. package/src/preview/types.ts +309 -0
  148. package/src/preview/validation.test.ts +290 -0
  149. package/src/preview/validation.ts +356 -0
  150. package/src/preview-runtime.tsx +144 -0
  151. package/src/raw-html-canonical.test.ts +41 -0
  152. package/src/raw-html-canonical.ts +179 -0
  153. package/src/react-types.ts +21 -0
  154. package/src/registry-install-plan.ts +344 -0
  155. package/src/registry.test.ts +245 -0
  156. package/src/registry.ts +369 -0
  157. package/src/rules/a11y-required-accessible-name.ts +93 -0
  158. package/src/rules/color-math.test.ts +72 -0
  159. package/src/rules/color-math.ts +192 -0
  160. package/src/rules/components-forbidden-prop-value.ts +108 -0
  161. package/src/rules/components-prefer-library.ts +943 -0
  162. package/src/rules/components-unknown-prop.ts +94 -0
  163. package/src/rules/composition-pattern-schema.ts +125 -0
  164. package/src/rules/composition-pattern.test.ts +320 -0
  165. package/src/rules/composition-pattern.ts +271 -0
  166. package/src/rules/emit-gate.test.ts +42 -0
  167. package/src/rules/emit-gate.ts +60 -0
  168. package/src/rules/finding.ts +54 -0
  169. package/src/rules/index.ts +235 -0
  170. package/src/rules/jsx-preferred-component.ts +68 -0
  171. package/src/rules/jsx-preferred-import-path.ts +67 -0
  172. package/src/rules/presets.ts +57 -0
  173. package/src/rules/props-invalid-value.ts +115 -0
  174. package/src/rules/rules.test.ts +3636 -0
  175. package/src/rules/spacing-resolution.ts +184 -0
  176. package/src/rules/styles-no-raw-color.ts +329 -0
  177. package/src/rules/styles-no-raw-dimensions.ts +357 -0
  178. package/src/rules/styles-no-raw-spacing.ts +236 -0
  179. package/src/rules/styles-no-raw-typography.ts +237 -0
  180. package/src/rules/tailwind-arbitrary-color.test.ts +128 -0
  181. package/src/rules/tailwind-arbitrary-color.ts +93 -0
  182. package/src/rules/tailwind-arbitrary-spacing.test.ts +157 -0
  183. package/src/rules/tailwind-arbitrary-spacing.ts +120 -0
  184. package/src/rules/tailwind-forbidden-palette.test.ts +116 -0
  185. package/src/rules/tailwind-forbidden-palette.ts +107 -0
  186. package/src/rules/tailwind-off-scale-spacing-token.test.ts +100 -0
  187. package/src/rules/tailwind-off-scale-spacing-token.ts +108 -0
  188. package/src/rules/tailwind-raw-color-via-token.test.ts +108 -0
  189. package/src/rules/tailwind-raw-color-via-token.ts +82 -0
  190. package/src/rules/tailwind-rule-utils.ts +106 -0
  191. package/src/rules/tailwind-unknown-class.test.ts +157 -0
  192. package/src/rules/tailwind-unknown-class.ts +121 -0
  193. package/src/rules/taxonomy.test.ts +238 -0
  194. package/src/rules/theme-no-theme-coupled-literal.ts +132 -0
  195. package/src/rules/tiers.ts +111 -0
  196. package/src/rules/tokens-css-vars-must-be-defined.test.ts +244 -0
  197. package/src/rules/tokens-css-vars-must-be-defined.ts +156 -0
  198. package/src/rules/tokens-require-dual-fallback.ts +78 -0
  199. package/src/rules/types.ts +27 -0
  200. package/src/rules/utils.test.ts +110 -0
  201. package/src/rules/utils.ts +599 -0
  202. package/src/schema.ts +427 -0
  203. package/src/schemas/index.ts +275 -0
  204. package/src/schemas/schemas.test.ts +124 -0
  205. package/src/severity.ts +54 -0
  206. package/src/storyAdapter.test.ts +571 -0
  207. package/src/storyAdapter.ts +761 -0
  208. package/src/storyFilters.test.ts +350 -0
  209. package/src/storyFilters.ts +253 -0
  210. package/src/storybook-csf.ts +11 -0
  211. package/src/style-comparison.ts +423 -0
  212. package/src/test-utils.ts +68 -0
  213. package/src/token-parser.ts +2 -0
  214. package/src/token-types.ts +287 -0
  215. package/src/tokens/categories.ts +131 -0
  216. package/src/tokens/color.ts +193 -0
  217. package/src/tokens/design-token-parser.test.ts +159 -0
  218. package/src/tokens/design-token-parser.ts +402 -0
  219. package/src/tokens/dtcg.ts +428 -0
  220. package/src/tokens/index.ts +130 -0
  221. package/src/tokens/lookup.ts +19 -0
  222. package/src/tokens/scss.ts +171 -0
  223. package/src/tokens/tailwind-v4.ts +187 -0
  224. package/src/tokens/types.ts +43 -0
  225. package/src/topology/index.ts +9 -0
  226. package/src/topology/resolve-area.test.ts +174 -0
  227. package/src/topology/resolve-area.ts +215 -0
  228. package/src/types.ts +1057 -0
@@ -0,0 +1,197 @@
1
+ import type {
2
+ PreviewComparisonFinding,
3
+ PreviewComparisonReport,
4
+ PreviewComparisonStyleMap,
5
+ PreviewComparisonThresholds,
6
+ PreviewStyleComparisonItem,
7
+ } from "./comparison";
8
+
9
+ const COLOR_PROPERTIES = new Set([
10
+ "background",
11
+ "backgroundColor",
12
+ "borderColor",
13
+ "color",
14
+ "fill",
15
+ "stroke",
16
+ ]);
17
+
18
+ const NUMERIC_PROPERTIES = new Set([
19
+ "borderRadius",
20
+ "borderWidth",
21
+ "fontSize",
22
+ "gap",
23
+ "height",
24
+ "letterSpacing",
25
+ "lineHeight",
26
+ "margin",
27
+ "opacity",
28
+ "padding",
29
+ "width",
30
+ ]);
31
+
32
+ export function compareStyles(
33
+ design: PreviewComparisonStyleMap | undefined,
34
+ preview: PreviewComparisonStyleMap | undefined,
35
+ thresholds: PreviewComparisonThresholds,
36
+ findings: PreviewComparisonFinding[]
37
+ ): PreviewComparisonReport["styles"] | undefined {
38
+ if (!design || !preview) return undefined;
39
+
40
+ const properties: PreviewStyleComparisonItem[] = [];
41
+
42
+ for (const [property, designValue] of Object.entries(design)) {
43
+ if (designValue === undefined || designValue === "") continue;
44
+
45
+ const previewValue = preview[property] ?? "(not set)";
46
+ const match = compareStyleValue(property, designValue, previewValue, thresholds);
47
+ properties.push({ property, design: designValue, preview: previewValue, match });
48
+
49
+ if (!match) {
50
+ findings.push({
51
+ code: "style-mismatch",
52
+ severity: "warning",
53
+ message: `${property} differs between Figma and the preview.`,
54
+ property,
55
+ designValue,
56
+ previewValue,
57
+ });
58
+ }
59
+ }
60
+
61
+ if (properties.length === 0) return undefined;
62
+
63
+ return {
64
+ match: properties.every((property) => property.match),
65
+ properties,
66
+ };
67
+ }
68
+
69
+ function compareStyleValue(
70
+ property: string,
71
+ designValue: string,
72
+ previewValue: string,
73
+ thresholds: PreviewComparisonThresholds
74
+ ): boolean {
75
+ const design = normalizeStyleValue(designValue);
76
+ const preview = normalizeStyleValue(previewValue);
77
+ if (design === preview) return true;
78
+ if (COLOR_PROPERTIES.has(property)) {
79
+ return compareColors(design, preview, thresholds);
80
+ }
81
+ if (NUMERIC_PROPERTIES.has(property)) {
82
+ return compareNumericValues(design, preview, thresholds.numericPx);
83
+ }
84
+ return false;
85
+ }
86
+
87
+ function normalizeStyleValue(value: string): string {
88
+ return value
89
+ .trim()
90
+ .replace(/\s+/g, " ")
91
+ .replace(/^none$/, "");
92
+ }
93
+
94
+ function compareNumericValues(valueA: string, valueB: string, tolerance: number): boolean {
95
+ const numberA = Number.parseFloat(valueA);
96
+ const numberB = Number.parseFloat(valueB);
97
+ if (Number.isNaN(numberA) || Number.isNaN(numberB)) return valueA === valueB;
98
+ return Math.abs(numberA - numberB) <= tolerance;
99
+ }
100
+
101
+ function compareColors(
102
+ valueA: string,
103
+ valueB: string,
104
+ thresholds: PreviewComparisonThresholds
105
+ ): boolean {
106
+ const colorA = parseColor(valueA);
107
+ const colorB = parseColor(valueB);
108
+ if (!colorA || !colorB) return valueA === valueB;
109
+
110
+ return (
111
+ Math.abs(colorA.r - colorB.r) <= thresholds.colorChannel &&
112
+ Math.abs(colorA.g - colorB.g) <= thresholds.colorChannel &&
113
+ Math.abs(colorA.b - colorB.b) <= thresholds.colorChannel &&
114
+ Math.abs(colorA.a - colorB.a) <= thresholds.alpha
115
+ );
116
+ }
117
+
118
+ function parseColor(value: string): { r: number; g: number; b: number; a: number } | null {
119
+ const normalized = value.trim().toLowerCase();
120
+ if (normalized === "transparent") return { r: 0, g: 0, b: 0, a: 0 };
121
+
122
+ const hex = normalized.match(/^#([0-9a-f]{3}|[0-9a-f]{4}|[0-9a-f]{6}|[0-9a-f]{8})$/);
123
+ if (hex) return parseHexColor(hex[1]);
124
+
125
+ const rgb = normalized.match(/^rgba?\(([^)]+)\)$/);
126
+ if (rgb) return parseRgbColor(rgb[1]);
127
+
128
+ return null;
129
+ }
130
+
131
+ function parseHexColor(raw: string): { r: number; g: number; b: number; a: number } {
132
+ const expanded =
133
+ raw.length === 3 || raw.length === 4
134
+ ? raw
135
+ .split("")
136
+ .map((part) => part + part)
137
+ .join("")
138
+ : raw;
139
+
140
+ return {
141
+ r: Number.parseInt(expanded.slice(0, 2), 16),
142
+ g: Number.parseInt(expanded.slice(2, 4), 16),
143
+ b: Number.parseInt(expanded.slice(4, 6), 16),
144
+ a: expanded.length === 8 ? Number.parseInt(expanded.slice(6, 8), 16) / 255 : 1,
145
+ };
146
+ }
147
+
148
+ function parseRgbColor(value: string): { r: number; g: number; b: number; a: number } | null {
149
+ const channels = splitRgbChannels(value);
150
+ if (channels.length < 3 || channels.length > 4) return null;
151
+
152
+ const [rawR, rawG, rawB, rawA] = channels;
153
+ const r = parseRgbChannel(rawR);
154
+ const g = parseRgbChannel(rawG);
155
+ const b = parseRgbChannel(rawB);
156
+ const a = rawA === undefined ? 1 : parseAlphaChannel(rawA);
157
+ if (r === null || g === null || b === null || a === null) return null;
158
+
159
+ return { r, g, b, a };
160
+ }
161
+
162
+ function splitRgbChannels(value: string): string[] {
163
+ if (value.includes(",")) {
164
+ return value.split(",").map((part) => part.trim());
165
+ }
166
+
167
+ const parts = value
168
+ .replace(/\s*\/\s*/g, " / ")
169
+ .split(/\s+/)
170
+ .filter(Boolean);
171
+ const slashIndex = parts.indexOf("/");
172
+ if (slashIndex === -1) return parts;
173
+
174
+ return [...parts.slice(0, slashIndex), parts[slashIndex + 1]].filter(
175
+ (part): part is string => part !== undefined
176
+ );
177
+ }
178
+
179
+ function parseRgbChannel(value: string): number | null {
180
+ if (value.endsWith("%")) {
181
+ const percentage = Number.parseFloat(value);
182
+ return Number.isFinite(percentage) ? (percentage / 100) * 255 : null;
183
+ }
184
+
185
+ const channel = Number.parseFloat(value);
186
+ return Number.isFinite(channel) ? channel : null;
187
+ }
188
+
189
+ function parseAlphaChannel(value: string): number | null {
190
+ if (value.endsWith("%")) {
191
+ const percentage = Number.parseFloat(value);
192
+ return Number.isFinite(percentage) ? percentage / 100 : null;
193
+ }
194
+
195
+ const alpha = Number.parseFloat(value);
196
+ return Number.isFinite(alpha) ? alpha : null;
197
+ }