@usefragments/core 1.5.2 → 1.7.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 (64) hide show
  1. package/dist/chunk-RANPUC6C.js +72 -0
  2. package/dist/chunk-RANPUC6C.js.map +1 -0
  3. package/dist/{chunk-BAHCOAVG.js → chunk-WNMWKUYG.js} +447 -201
  4. package/dist/chunk-WNMWKUYG.js.map +1 -0
  5. package/dist/codes/index.d.ts +2 -2
  6. package/dist/codes/index.js +1 -1
  7. package/dist/compiled-types/index.d.ts +1 -1
  8. package/dist/compiled-types/index.js +8 -0
  9. package/dist/generate/index.d.ts +1 -1
  10. package/dist/{governance-pKrfh517.d.ts → governance-D9KtH-vg.d.ts} +617 -22
  11. package/dist/index.d.ts +800 -179
  12. package/dist/index.js +1003 -237
  13. package/dist/index.js.map +1 -1
  14. package/dist/react-types.d.ts +1 -1
  15. package/dist/registry.d.ts +36 -36
  16. package/dist/schemas/index.d.ts +1 -1
  17. package/dist/test-utils.d.ts +1 -1
  18. package/package.json +2 -1
  19. package/src/__tests__/policy-exclude.test.ts +180 -0
  20. package/src/agent-format.test.ts +13 -0
  21. package/src/agent-format.ts +9 -3
  22. package/src/canonical-bridge.ts +69 -1
  23. package/src/canonical-direction.test.ts +118 -0
  24. package/src/canonical-direction.ts +43 -2
  25. package/src/codes/__tests__/codes.test.ts +14 -2
  26. package/src/codes/codes.ts +41 -2
  27. package/src/compiled-types/index.ts +81 -0
  28. package/src/compiled-types/parse.test.ts +47 -0
  29. package/src/facts/builders.ts +48 -0
  30. package/src/facts/compile.ts +148 -34
  31. package/src/facts/fact-index.ts +15 -2
  32. package/src/facts/facts.test.ts +44 -3
  33. package/src/facts/index.ts +11 -6
  34. package/src/facts/types.ts +60 -9
  35. package/src/governance-integrity.test.ts +272 -4
  36. package/src/governance-integrity.ts +345 -25
  37. package/src/governance.ts +87 -1
  38. package/src/index.ts +46 -1
  39. package/src/policy-exclude.ts +113 -0
  40. package/src/rules/a11y-required-accessible-name.ts +175 -28
  41. package/src/rules/a11y-standard.ts +102 -0
  42. package/src/rules/a11y-utils.ts +7 -0
  43. package/src/rules/components-prefer-library.test.ts +75 -28
  44. package/src/rules/components-prefer-library.ts +35 -15
  45. package/src/rules/components-shadow-component.test.ts +21 -9
  46. package/src/rules/emit-gate.test.ts +74 -4
  47. package/src/rules/emit-gate.ts +24 -9
  48. package/src/rules/families.test.ts +69 -0
  49. package/src/rules/families.ts +52 -0
  50. package/src/rules/fix-availability.ts +1 -0
  51. package/src/rules/index.ts +18 -2
  52. package/src/rules/jsx-preferred-import-path.ts +29 -11
  53. package/src/rules/rules.test.ts +188 -8
  54. package/src/rules/styles-no-raw-color.ts +13 -4
  55. package/src/rules/styles-no-raw-dimensions.ts +13 -4
  56. package/src/rules/styles-no-raw-spacing.ts +12 -4
  57. package/src/rules/styles-no-raw-typography.ts +13 -4
  58. package/src/rules/tiers.ts +1 -0
  59. package/src/rules/utils.ts +39 -0
  60. package/src/tokens/design-token-parser.test.ts +131 -0
  61. package/src/tokens/design-token-parser.ts +362 -49
  62. package/src/types.ts +2 -2
  63. package/dist/chunk-BAHCOAVG.js.map +0 -1
  64. package/dist/{index-DbkPE46t.d.ts → index-hZAlYCli.d.ts} +8 -8
@@ -0,0 +1,72 @@
1
+ // src/compiled-types/index.ts
2
+ var CompiledFragmentsFileValidationError = class extends Error {
3
+ constructor(source, issues) {
4
+ super(`Invalid compiled Fragments catalog at ${source}: ${issues.join("; ")}`);
5
+ this.source = source;
6
+ this.issues = issues;
7
+ this.name = "CompiledFragmentsFileValidationError";
8
+ }
9
+ source;
10
+ issues;
11
+ };
12
+ function parseCompiledFragmentsFile(input, source = "fragments.json") {
13
+ let value = input;
14
+ if (typeof input === "string") {
15
+ try {
16
+ value = JSON.parse(input);
17
+ } catch (error) {
18
+ throw new CompiledFragmentsFileValidationError(source, [
19
+ `invalid JSON (${error instanceof Error ? error.message : String(error)})`
20
+ ]);
21
+ }
22
+ }
23
+ const issues = [];
24
+ if (!isRecord(value)) {
25
+ throw new CompiledFragmentsFileValidationError(source, ["root must be an object"]);
26
+ }
27
+ if (typeof value.version !== "string" || value.version.length === 0) {
28
+ issues.push("version must be a non-empty string");
29
+ }
30
+ if (typeof value.generatedAt !== "string" || value.generatedAt.length === 0) {
31
+ issues.push("generatedAt must be a non-empty string");
32
+ }
33
+ if (!isRecord(value.fragments)) {
34
+ issues.push("fragments must be an object");
35
+ } else {
36
+ for (const [key, fragment] of Object.entries(value.fragments)) {
37
+ validateCompiledFragment(key, fragment, issues);
38
+ }
39
+ }
40
+ if (value.graph !== void 0) {
41
+ if (!isRecord(value.graph) || !Array.isArray(value.graph.nodes) || !Array.isArray(value.graph.edges) || !isRecord(value.graph.health)) {
42
+ issues.push("graph must contain nodes[], edges[], and health");
43
+ }
44
+ }
45
+ if (issues.length > 0) throw new CompiledFragmentsFileValidationError(source, issues);
46
+ return value;
47
+ }
48
+ function validateCompiledFragment(key, value, issues) {
49
+ const path = `fragments.${key}`;
50
+ if (!isRecord(value)) {
51
+ issues.push(`${path} must be an object`);
52
+ return;
53
+ }
54
+ if (typeof value.filePath !== "string") issues.push(`${path}.filePath must be a string`);
55
+ if (!isRecord(value.meta) || typeof value.meta.name !== "string") {
56
+ issues.push(`${path}.meta.name must be a string`);
57
+ }
58
+ if (!isRecord(value.props)) issues.push(`${path}.props must be an object`);
59
+ if (!Array.isArray(value.variants)) issues.push(`${path}.variants must be an array`);
60
+ if (!isRecord(value.usage) || !Array.isArray(value.usage.when) || !Array.isArray(value.usage.whenNot)) {
61
+ issues.push(`${path}.usage must contain when[] and whenNot[]`);
62
+ }
63
+ }
64
+ function isRecord(value) {
65
+ return value !== null && typeof value === "object" && !Array.isArray(value);
66
+ }
67
+
68
+ export {
69
+ CompiledFragmentsFileValidationError,
70
+ parseCompiledFragmentsFile
71
+ };
72
+ //# sourceMappingURL=chunk-RANPUC6C.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/compiled-types/index.ts"],"sourcesContent":["/**\n * Compiled fragment types — shared between CLI and MCP packages.\n *\n * These are the JSON-serializable types used in fragments.json and consumed\n * by AI agents, MCP servers, and context generators.\n */\n\nimport type { ComponentGovernanceRecord } from '../governance.js';\n\n/**\n * Component metadata\n */\nexport interface FragmentMeta {\n name: string;\n description: string;\n category: string;\n tags?: string[];\n status?: \"stable\" | \"beta\" | \"deprecated\" | \"experimental\";\n since?: string;\n dependencies?: Array<{ name: string; version: string; reason?: string }>;\n figma?: string;\n figmaProps?: Record<string, unknown>;\n}\n\n/**\n * Usage guidelines for AI agents and developers\n */\nexport interface FragmentUsage {\n when: string[];\n whenNot: string[];\n guidelines?: string[];\n accessibility?: string[];\n}\n\n/**\n * Definition for a single prop\n */\nexport interface PropDefinition {\n type: string;\n values?: readonly string[];\n default?: unknown;\n description: string;\n required?: boolean;\n constraints?: string[];\n typeDetails?: Record<string, unknown>;\n controlType?: string;\n controlOptions?: {\n min?: number;\n max?: number;\n step?: number;\n presetColors?: string[];\n };\n}\n\n/**\n * Relationship to another component\n */\nexport interface ComponentRelation {\n component: string;\n relationship: string;\n note: string;\n}\n\n/**\n * Agent-optimized contract metadata\n */\nexport interface FragmentContract {\n propsSummary?: string[];\n a11yRules?: string[];\n bans?: Array<{ pattern: string; message: string }>;\n scenarioTags?: string[];\n /** Per-component performance budget override in bytes (gzipped) */\n performanceBudget?: number;\n /** Sub-component slot metadata for compound components */\n compoundChildren?: Record<string, {\n required?: boolean;\n accepts?: string[];\n description?: string;\n }>;\n /** Canonical JSX usage examples showing how to assemble the component */\n canonicalUsage?: string[];\n}\n\n/**\n * Provenance tracking for generated fragments\n */\nexport interface FragmentGenerated {\n source: \"storybook\" | \"manual\" | \"ai\" | \"extracted\" | \"merged\" | \"migrated\";\n sourceFile?: string;\n /** @deprecated Use provenance.verified instead */\n confidence?: number;\n verified?: boolean;\n timestamp?: string;\n}\n\n/**\n * AI-specific metadata\n */\nexport interface AIMetadata {\n compositionPattern?: \"compound\" | \"simple\" | \"controlled\" | \"wrapper\";\n subComponents?: string[];\n requiredChildren?: string[];\n commonPatterns?: string[];\n}\n\n/**\n * Performance data for a component (from bundle size measurement)\n */\n/**\n * A single import contributing to bundle size\n */\nexport interface ImportEntry {\n /** Resolved file path (relative to project root) */\n path: string;\n /** Bytes contributed to the bundle */\n bytes: number;\n /** Percentage of total bundle size */\n percent: number;\n}\n\nexport interface PerformanceData {\n /** Gzipped bundle size in bytes */\n bundleSize: number;\n /** Raw (minified, not gzipped) bundle size in bytes */\n rawSize: number;\n /** Complexity classification */\n complexity: 'lightweight' | 'moderate' | 'heavy';\n /** Percentage of budget used (0-100+) */\n budgetPercent: number;\n /** Whether the component exceeds its budget */\n overBudget: boolean;\n /** ISO timestamp when measured */\n measuredAt: string;\n /** Top imports by size (largest first) */\n imports?: ImportEntry[];\n}\n\nexport interface ObservedUsageProp {\n name: string;\n kind: 'static' | 'dynamic' | 'spread' | 'jsx' | 'boolean' | 'null';\n value?: string | number | boolean | null;\n}\n\nexport interface ObservedComponentUsage {\n /** Source file path relative to the fragments config root */\n file: string;\n /** 1-indexed source line */\n line: number;\n /** 0-indexed source column */\n column: number;\n props: ObservedUsageProp[];\n parentElement?: string;\n conditional?: boolean;\n}\n\n/**\n * Compiled fragment data (JSON-serializable for AI consumption)\n */\nexport interface CompiledFragment {\n filePath: string;\n meta: FragmentMeta;\n /** Canonical v2 guidance. `usage` is retained for compatibility. */\n guidance?: FragmentUsage;\n usage: FragmentUsage;\n props: Record<string, PropDefinition>;\n /** Normalized component governance records emitted from *.fragment.ts. */\n governance?: ComponentGovernanceRecord[];\n relations?: ComponentRelation[];\n variants: Array<{\n name: string;\n description: string;\n code?: string;\n figma?: string;\n args?: Record<string, unknown>;\n }>;\n contract?: FragmentContract;\n ai?: AIMetadata;\n /** Framework hint from contract, used by preview adapters and Cloud */\n framework?: string;\n /** Top-level compact prop summaries for agent first-pass */\n propsSummary?: string[];\n /** Source file path relative to config root (for contract-sourced fragments) */\n sourcePath?: string;\n /** Named export for preview adapter resolution */\n exportName?: string;\n /** Clean provenance tracking (V2) */\n provenance?: {\n source: string;\n verified: boolean;\n frameworkSupport?: string;\n sourceHash?: string;\n extractedAt?: string;\n };\n /** Component performance data from bundle size measurement */\n performance?: PerformanceData;\n /** Observed JSX call sites captured during `fragments scan` */\n usages?: ObservedComponentUsage[];\n _generated?: FragmentGenerated;\n}\n\n/**\n * Compiled block data (JSON-serializable for AI consumption)\n */\nexport interface CompiledBlock {\n filePath: string;\n name: string;\n description: string;\n category: string;\n components: string[];\n code: string;\n tags?: string[];\n}\n\n/**\n * A single token entry in the compiled output\n */\nexport interface CompiledTokenEntry {\n name: string;\n value?: string;\n description?: string;\n}\n\n/**\n * Compiled token data stored in fragments.json\n */\nexport interface CompiledTokenData {\n prefix: string;\n total: number;\n categories: Record<string, CompiledTokenEntry[]>;\n}\n\n/**\n * Performance summary across all components\n */\nexport interface PerformanceSummary {\n /** Preset name used */\n preset: string;\n /** Budget applied in bytes */\n budget: number;\n /** Total components measured */\n total: number;\n /** Number of components over budget */\n overBudget: number;\n /** Distribution by tier */\n tiers: Record<string, number>;\n}\n\n/**\n * The compiled fragments.json structure\n */\nexport interface CompiledFragmentsFile {\n version: string;\n generatedAt: string;\n /** CLI version that produced this file, used for freshness checks */\n generatorVersion?: string;\n /** Relative source/config inputs used to build this file, used for freshness checks */\n buildInputs?: string[];\n packageName?: string;\n fragments: Record<string, CompiledFragment>;\n blocks?: Record<string, CompiledBlock>;\n tokens?: CompiledTokenData;\n /** Component relationship graph for AI structural queries */\n graph?: import('../graph/types.js').SerializedComponentGraph;\n /** Performance measurement summary */\n performanceSummary?: PerformanceSummary;\n /** @deprecated Use blocks instead */\n recipes?: Record<string, CompiledBlock>;\n}\n\nexport class CompiledFragmentsFileValidationError extends Error {\n constructor(\n readonly source: string,\n readonly issues: string[]\n ) {\n super(`Invalid compiled Fragments catalog at ${source}: ${issues.join(\"; \")}`);\n this.name = \"CompiledFragmentsFileValidationError\";\n }\n}\n\nexport function parseCompiledFragmentsFile(\n input: string | unknown,\n source = \"fragments.json\"\n): CompiledFragmentsFile {\n let value: unknown = input;\n if (typeof input === \"string\") {\n try {\n value = JSON.parse(input);\n } catch (error) {\n throw new CompiledFragmentsFileValidationError(source, [\n `invalid JSON (${error instanceof Error ? error.message : String(error)})`,\n ]);\n }\n }\n\n const issues: string[] = [];\n if (!isRecord(value)) {\n throw new CompiledFragmentsFileValidationError(source, [\"root must be an object\"]);\n }\n if (typeof value.version !== \"string\" || value.version.length === 0) {\n issues.push(\"version must be a non-empty string\");\n }\n if (typeof value.generatedAt !== \"string\" || value.generatedAt.length === 0) {\n issues.push(\"generatedAt must be a non-empty string\");\n }\n if (!isRecord(value.fragments)) {\n issues.push(\"fragments must be an object\");\n } else {\n for (const [key, fragment] of Object.entries(value.fragments)) {\n validateCompiledFragment(key, fragment, issues);\n }\n }\n if (value.graph !== undefined) {\n if (\n !isRecord(value.graph) ||\n !Array.isArray(value.graph.nodes) ||\n !Array.isArray(value.graph.edges) ||\n !isRecord(value.graph.health)\n ) {\n issues.push(\"graph must contain nodes[], edges[], and health\");\n }\n }\n if (issues.length > 0) throw new CompiledFragmentsFileValidationError(source, issues);\n return value as unknown as CompiledFragmentsFile;\n}\n\nfunction validateCompiledFragment(key: string, value: unknown, issues: string[]): void {\n const path = `fragments.${key}`;\n if (!isRecord(value)) {\n issues.push(`${path} must be an object`);\n return;\n }\n if (typeof value.filePath !== \"string\") issues.push(`${path}.filePath must be a string`);\n if (!isRecord(value.meta) || typeof value.meta.name !== \"string\") {\n issues.push(`${path}.meta.name must be a string`);\n }\n if (!isRecord(value.props)) issues.push(`${path}.props must be an object`);\n if (!Array.isArray(value.variants)) issues.push(`${path}.variants must be an array`);\n if (\n !isRecord(value.usage) ||\n !Array.isArray(value.usage.when) ||\n !Array.isArray(value.usage.whenNot)\n ) {\n issues.push(`${path}.usage must contain when[] and whenNot[]`);\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\n/**\n * Theme identifier\n */\nexport type Theme = \"light\" | \"dark\";\n\n/**\n * Verification result\n */\nexport interface VerifyResult {\n verdict: \"pass\" | \"fail\" | \"error\";\n matches: boolean;\n diffPercentage: number;\n screenshot: string;\n baseline: string;\n diffImage?: string;\n notes: string[];\n error?: string;\n timing: {\n renderMs: number;\n captureMs: number;\n diffMs: number;\n totalMs: number;\n };\n}\n"],"mappings":";AA6QO,IAAM,uCAAN,cAAmD,MAAM;AAAA,EAC9D,YACW,QACA,QACT;AACA,UAAM,yCAAyC,MAAM,KAAK,OAAO,KAAK,IAAI,CAAC,EAAE;AAHpE;AACA;AAGT,SAAK,OAAO;AAAA,EACd;AAAA,EALW;AAAA,EACA;AAKb;AAEO,SAAS,2BACd,OACA,SAAS,kBACc;AACvB,MAAI,QAAiB;AACrB,MAAI,OAAO,UAAU,UAAU;AAC7B,QAAI;AACF,cAAQ,KAAK,MAAM,KAAK;AAAA,IAC1B,SAAS,OAAO;AACd,YAAM,IAAI,qCAAqC,QAAQ;AAAA,QACrD,iBAAiB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,MACzE,CAAC;AAAA,IACH;AAAA,EACF;AAEA,QAAM,SAAmB,CAAC;AAC1B,MAAI,CAAC,SAAS,KAAK,GAAG;AACpB,UAAM,IAAI,qCAAqC,QAAQ,CAAC,wBAAwB,CAAC;AAAA,EACnF;AACA,MAAI,OAAO,MAAM,YAAY,YAAY,MAAM,QAAQ,WAAW,GAAG;AACnE,WAAO,KAAK,oCAAoC;AAAA,EAClD;AACA,MAAI,OAAO,MAAM,gBAAgB,YAAY,MAAM,YAAY,WAAW,GAAG;AAC3E,WAAO,KAAK,wCAAwC;AAAA,EACtD;AACA,MAAI,CAAC,SAAS,MAAM,SAAS,GAAG;AAC9B,WAAO,KAAK,6BAA6B;AAAA,EAC3C,OAAO;AACL,eAAW,CAAC,KAAK,QAAQ,KAAK,OAAO,QAAQ,MAAM,SAAS,GAAG;AAC7D,+BAAyB,KAAK,UAAU,MAAM;AAAA,IAChD;AAAA,EACF;AACA,MAAI,MAAM,UAAU,QAAW;AAC7B,QACE,CAAC,SAAS,MAAM,KAAK,KACrB,CAAC,MAAM,QAAQ,MAAM,MAAM,KAAK,KAChC,CAAC,MAAM,QAAQ,MAAM,MAAM,KAAK,KAChC,CAAC,SAAS,MAAM,MAAM,MAAM,GAC5B;AACA,aAAO,KAAK,iDAAiD;AAAA,IAC/D;AAAA,EACF;AACA,MAAI,OAAO,SAAS,EAAG,OAAM,IAAI,qCAAqC,QAAQ,MAAM;AACpF,SAAO;AACT;AAEA,SAAS,yBAAyB,KAAa,OAAgB,QAAwB;AACrF,QAAM,OAAO,aAAa,GAAG;AAC7B,MAAI,CAAC,SAAS,KAAK,GAAG;AACpB,WAAO,KAAK,GAAG,IAAI,oBAAoB;AACvC;AAAA,EACF;AACA,MAAI,OAAO,MAAM,aAAa,SAAU,QAAO,KAAK,GAAG,IAAI,4BAA4B;AACvF,MAAI,CAAC,SAAS,MAAM,IAAI,KAAK,OAAO,MAAM,KAAK,SAAS,UAAU;AAChE,WAAO,KAAK,GAAG,IAAI,6BAA6B;AAAA,EAClD;AACA,MAAI,CAAC,SAAS,MAAM,KAAK,EAAG,QAAO,KAAK,GAAG,IAAI,0BAA0B;AACzE,MAAI,CAAC,MAAM,QAAQ,MAAM,QAAQ,EAAG,QAAO,KAAK,GAAG,IAAI,4BAA4B;AACnF,MACE,CAAC,SAAS,MAAM,KAAK,KACrB,CAAC,MAAM,QAAQ,MAAM,MAAM,IAAI,KAC/B,CAAC,MAAM,QAAQ,MAAM,MAAM,OAAO,GAClC;AACA,WAAO,KAAK,GAAG,IAAI,0CAA0C;AAAA,EAC/D;AACF;AAEA,SAAS,SAAS,OAAkD;AAClE,SAAO,UAAU,QAAQ,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK;AAC5E;","names":[]}