design-brain-memory 0.9.3 → 0.9.4

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 (125) hide show
  1. package/README.md +273 -0
  2. package/dist/agentBrowser.d.ts +0 -1
  3. package/dist/agentBrowser.js +13 -31
  4. package/dist/agentBrowser.js.map +1 -1
  5. package/dist/aggregate.d.ts +9 -0
  6. package/dist/aggregate.js +53 -0
  7. package/dist/aggregate.js.map +1 -0
  8. package/dist/batch.d.ts +16 -0
  9. package/dist/batch.js +44 -0
  10. package/dist/batch.js.map +1 -0
  11. package/dist/cli.js +250 -216
  12. package/dist/cli.js.map +1 -1
  13. package/dist/commands.d.ts +60 -1
  14. package/dist/commands.js +323 -10
  15. package/dist/commands.js.map +1 -1
  16. package/dist/compare.d.ts +33 -0
  17. package/dist/compare.js +83 -0
  18. package/dist/compare.js.map +1 -0
  19. package/dist/componentGraph.d.ts +22 -0
  20. package/dist/componentGraph.js +106 -0
  21. package/dist/componentGraph.js.map +1 -0
  22. package/dist/contextLayer.d.ts +12 -0
  23. package/dist/contextLayer.js +263 -0
  24. package/dist/contextLayer.js.map +1 -0
  25. package/dist/cssInJs.d.ts +9 -0
  26. package/dist/cssInJs.js +124 -0
  27. package/dist/cssInJs.js.map +1 -0
  28. package/dist/extractFromUrl.d.ts +8 -0
  29. package/dist/extractFromUrl.js +508 -414
  30. package/dist/extractFromUrl.js.map +1 -1
  31. package/dist/graphView.d.ts +21 -0
  32. package/dist/graphView.js +492 -0
  33. package/dist/graphView.js.map +1 -0
  34. package/dist/index.d.ts +26 -11
  35. package/dist/index.js +17 -10
  36. package/dist/index.js.map +1 -1
  37. package/dist/knowledge.d.ts +20 -0
  38. package/dist/knowledge.js +208 -0
  39. package/dist/knowledge.js.map +1 -0
  40. package/dist/liveView.d.ts +15 -0
  41. package/dist/liveView.js +475 -0
  42. package/dist/liveView.js.map +1 -0
  43. package/dist/llm.js +1 -9
  44. package/dist/llm.js.map +1 -1
  45. package/dist/moodboard.d.ts +3 -0
  46. package/dist/moodboard.js +152 -0
  47. package/dist/moodboard.js.map +1 -0
  48. package/dist/persona.d.ts +2 -2
  49. package/dist/persona.js +82 -210
  50. package/dist/persona.js.map +1 -1
  51. package/dist/query.js +1 -6
  52. package/dist/query.js.map +1 -1
  53. package/dist/render.d.ts +2 -10
  54. package/dist/render.js +80 -175
  55. package/dist/render.js.map +1 -1
  56. package/dist/reviewChecklist.d.ts +17 -0
  57. package/dist/reviewChecklist.js +126 -0
  58. package/dist/reviewChecklist.js.map +1 -0
  59. package/dist/scan.d.ts +19 -7
  60. package/dist/scan.js +132 -374
  61. package/dist/scan.js.map +1 -1
  62. package/dist/scorecard.d.ts +53 -0
  63. package/dist/scorecard.js +325 -0
  64. package/dist/scorecard.js.map +1 -0
  65. package/dist/skillPrompt.d.ts +1 -3
  66. package/dist/skillPrompt.js +22 -148
  67. package/dist/skillPrompt.js.map +1 -1
  68. package/dist/store.d.ts +2 -2
  69. package/dist/store.js +7 -9
  70. package/dist/store.js.map +1 -1
  71. package/dist/styleDictionary.d.ts +16 -0
  72. package/dist/styleDictionary.js +89 -0
  73. package/dist/styleDictionary.js.map +1 -0
  74. package/dist/svg.d.ts +5 -0
  75. package/dist/svg.js +162 -0
  76. package/dist/svg.js.map +1 -0
  77. package/dist/systemDiff.d.ts +28 -0
  78. package/dist/systemDiff.js +107 -0
  79. package/dist/systemDiff.js.map +1 -0
  80. package/dist/tailwind.d.ts +2 -0
  81. package/dist/tailwind.js +122 -0
  82. package/dist/tailwind.js.map +1 -0
  83. package/dist/taste.d.ts +3 -2
  84. package/dist/taste.js +349 -536
  85. package/dist/taste.js.map +1 -1
  86. package/dist/tasteRenderer.d.ts +2 -3
  87. package/dist/tasteRenderer.js +123 -119
  88. package/dist/tasteRenderer.js.map +1 -1
  89. package/dist/tokenNaming.d.ts +5 -0
  90. package/dist/tokenNaming.js +229 -0
  91. package/dist/tokenNaming.js.map +1 -0
  92. package/dist/tokens.d.ts +17 -0
  93. package/dist/tokens.js +44 -0
  94. package/dist/tokens.js.map +1 -0
  95. package/dist/trends.d.ts +12 -0
  96. package/dist/trends.js +178 -0
  97. package/dist/trends.js.map +1 -0
  98. package/dist/types.d.ts +47 -101
  99. package/dist/wiki.d.ts +10 -0
  100. package/dist/wiki.js +346 -0
  101. package/dist/wiki.js.map +1 -0
  102. package/dist/writingStyle.d.ts +38 -0
  103. package/dist/writingStyle.js +224 -0
  104. package/dist/writingStyle.js.map +1 -0
  105. package/package.json +5 -4
  106. package/dist/classify.d.ts +0 -21
  107. package/dist/classify.js +0 -205
  108. package/dist/classify.js.map +0 -1
  109. package/dist/scanRenderer.d.ts +0 -2
  110. package/dist/scanRenderer.js +0 -155
  111. package/dist/scanRenderer.js.map +0 -1
  112. package/dist/tasteDiff.d.ts +0 -19
  113. package/dist/tasteDiff.js +0 -340
  114. package/dist/tasteDiff.js.map +0 -1
  115. package/dist/tasteGenerate.d.ts +0 -12
  116. package/dist/tasteGenerate.js +0 -140
  117. package/dist/tasteGenerate.js.map +0 -1
  118. package/dist/tasteRefine.d.ts +0 -13
  119. package/dist/tasteRefine.js +0 -351
  120. package/dist/tasteRefine.js.map +0 -1
  121. package/dist/theatrical.d.ts +0 -5
  122. package/dist/theatrical.js +0 -258
  123. package/dist/theatrical.js.map +0 -1
  124. package/skills/SKILL.md +0 -36
  125. package/skills/design-brain/SKILL.md +0 -77
@@ -0,0 +1,224 @@
1
+ const ACTION_VERBS = new Set([
2
+ 'get', 'start', 'try', 'buy', 'sign', 'join', 'learn', 'discover',
3
+ 'explore', 'create', 'build', 'download', 'view', 'see', 'read',
4
+ 'watch', 'listen', 'subscribe', 'contact', 'request', 'book',
5
+ 'schedule', 'apply', 'claim', 'unlock', 'activate', 'upgrade',
6
+ 'shop', 'order', 'add', 'continue', 'submit', 'send', 'share',
7
+ ]);
8
+ const TONE_MARKERS = {
9
+ conversational: ['you', "you'll", "you're", "we'll", "we're", "let's", "don't", "it's", "that's"],
10
+ formal: ['therefore', 'furthermore', 'consequently', 'regarding', 'herein', 'pursuant'],
11
+ urgent: ['now', 'today', 'limited', 'hurry', 'last chance', 'don\'t miss', 'act now', 'ending soon'],
12
+ friendly: ['hey', 'awesome', 'love', 'amazing', 'great', 'happy', 'enjoy', 'fun', 'easy'],
13
+ technical: ['api', 'sdk', 'integration', 'deploy', 'configure', 'implement', 'infrastructure'],
14
+ aspirational: ['transform', 'empower', 'revolutionize', 'reimagine', 'elevate', 'unlock potential'],
15
+ };
16
+ function classifyHeadingStyle(text) {
17
+ const trimmed = text.trim();
18
+ if (trimmed.endsWith('?'))
19
+ return 'question';
20
+ const firstWord = trimmed.split(/\s+/)[0]?.toLowerCase() ?? '';
21
+ if (ACTION_VERBS.has(firstWord))
22
+ return 'action';
23
+ if (trimmed.split(/\s+/).length <= 2)
24
+ return 'label';
25
+ return 'statement';
26
+ }
27
+ function extractActionVerb(text) {
28
+ const words = text.toLowerCase().trim().split(/\s+/);
29
+ for (const word of words) {
30
+ if (ACTION_VERBS.has(word))
31
+ return word;
32
+ }
33
+ return words[0] || '';
34
+ }
35
+ function detectTone(allText) {
36
+ const lower = allText.toLowerCase();
37
+ const detected = [];
38
+ for (const [tone, markers] of Object.entries(TONE_MARKERS)) {
39
+ const hits = markers.filter((m) => lower.includes(m)).length;
40
+ const threshold = Math.max(1, Math.floor(markers.length * 0.2));
41
+ if (hits >= threshold)
42
+ detected.push(tone);
43
+ }
44
+ return detected;
45
+ }
46
+ function avgWords(texts) {
47
+ if (texts.length === 0)
48
+ return 0;
49
+ const total = texts.reduce((sum, t) => sum + t.trim().split(/\s+/).filter(Boolean).length, 0);
50
+ return Math.round(total / texts.length);
51
+ }
52
+ export function analyzeWritingStyle(inspo) {
53
+ const components = inspo.analysis.components;
54
+ // Headings
55
+ const headingTags = new Set(['h1', 'h2', 'h3', 'h4', 'h5', 'h6']);
56
+ const headings = [];
57
+ for (const comp of components) {
58
+ if (headingTags.has(comp.tag.toLowerCase()) && comp.text.trim()) {
59
+ headings.push({
60
+ tag: comp.tag.toLowerCase(),
61
+ text: comp.text.trim().slice(0, 120),
62
+ wordCount: comp.text.trim().split(/\s+/).length,
63
+ style: classifyHeadingStyle(comp.text),
64
+ });
65
+ }
66
+ }
67
+ // CTAs — buttons and links with action text
68
+ const ctaTags = new Set(['button', 'a']);
69
+ const ctas = [];
70
+ for (const comp of components) {
71
+ if (!ctaTags.has(comp.tag.toLowerCase()))
72
+ continue;
73
+ const text = comp.text.trim();
74
+ if (!text || text.length > 60)
75
+ continue;
76
+ const verb = extractActionVerb(text);
77
+ if (verb) {
78
+ ctas.push({
79
+ text,
80
+ selector: comp.selector,
81
+ actionVerb: verb,
82
+ });
83
+ }
84
+ }
85
+ // Collect all visible text
86
+ const allTexts = components.map((c) => c.text.trim()).filter((t) => t.length > 3);
87
+ const allText = allTexts.join(' ');
88
+ // Tone detection
89
+ const toneMarkers = detectTone(allText);
90
+ // Text hierarchy — group by tag and compute avg word count
91
+ const tagTexts = new Map();
92
+ for (const comp of components) {
93
+ const tag = comp.tag.toLowerCase();
94
+ if (!comp.text.trim())
95
+ continue;
96
+ const list = tagTexts.get(tag) ?? [];
97
+ list.push(comp.text.trim());
98
+ tagTexts.set(tag, list);
99
+ }
100
+ const textHierarchy = [];
101
+ const hierarchyOrder = ['h1', 'h2', 'h3', 'p', 'span', 'a', 'button', 'li'];
102
+ for (const tag of hierarchyOrder) {
103
+ const texts = tagTexts.get(tag);
104
+ if (texts && texts.length > 0) {
105
+ textHierarchy.push({
106
+ level: tag,
107
+ count: texts.length,
108
+ avgWords: avgWords(texts),
109
+ });
110
+ }
111
+ }
112
+ // Sentence stats
113
+ const sentences = allText.split(/[.!?]+/).filter((s) => s.trim().length > 5);
114
+ const avgSentenceLen = sentences.length > 0
115
+ ? Math.round(sentences.reduce((sum, s) => sum + s.trim().split(/\s+/).length, 0) / sentences.length)
116
+ : 0;
117
+ const words = allText.split(/\s+/).filter(Boolean);
118
+ const avgWordLen = words.length > 0
119
+ ? Math.round((words.reduce((sum, w) => sum + w.length, 0) / words.length) * 10) / 10
120
+ : 0;
121
+ return {
122
+ headings,
123
+ ctas: ctas.slice(0, 20),
124
+ toneMarkers,
125
+ textHierarchy,
126
+ avgSentenceLength: avgSentenceLen,
127
+ avgWordLength: avgWordLen,
128
+ };
129
+ }
130
+ export function aggregateWritingStyles(inspirations) {
131
+ const headingStyleCounts = {};
132
+ const ctaMap = new Map();
133
+ const toneCounts = {};
134
+ let sentLenSum = 0;
135
+ let sentLenCount = 0;
136
+ const levelMap = new Map();
137
+ for (const inspo of inspirations) {
138
+ const style = analyzeWritingStyle(inspo);
139
+ for (const h of style.headings) {
140
+ headingStyleCounts[h.style] = (headingStyleCounts[h.style] ?? 0) + 1;
141
+ }
142
+ for (const cta of style.ctas) {
143
+ const key = cta.text.toLowerCase();
144
+ const existing = ctaMap.get(key) ?? { text: cta.text, verb: cta.actionVerb, count: 0 };
145
+ existing.count += 1;
146
+ ctaMap.set(key, existing);
147
+ }
148
+ for (const tone of style.toneMarkers) {
149
+ toneCounts[tone] = (toneCounts[tone] ?? 0) + 1;
150
+ }
151
+ if (style.avgSentenceLength > 0) {
152
+ sentLenSum += style.avgSentenceLength;
153
+ sentLenCount += 1;
154
+ }
155
+ for (const level of style.textHierarchy) {
156
+ const existing = levelMap.get(level.level) ?? { total: 0, wordSum: 0 };
157
+ existing.total += level.count;
158
+ existing.wordSum += level.avgWords * level.count;
159
+ levelMap.set(level.level, existing);
160
+ }
161
+ }
162
+ const topCtas = [...ctaMap.values()].sort((a, b) => b.count - a.count).slice(0, 15);
163
+ const textLevels = [];
164
+ for (const [level, data] of levelMap) {
165
+ textLevels.push({ level, count: data.total, avgWords: data.total > 0 ? Math.round(data.wordSum / data.total) : 0 });
166
+ }
167
+ return {
168
+ headingStyles: headingStyleCounts,
169
+ topCtas,
170
+ tones: toneCounts,
171
+ avgSentenceLength: sentLenCount > 0 ? Math.round(sentLenSum / sentLenCount) : 0,
172
+ textLevels,
173
+ };
174
+ }
175
+ export function renderWritingStyleMd(styles, projectId) {
176
+ const lines = [];
177
+ lines.push(`# Writing Style Analysis — ${projectId}\n`);
178
+ // Tone
179
+ const toneEntries = Object.entries(styles.tones).sort((a, b) => b[1] - a[1]);
180
+ if (toneEntries.length > 0) {
181
+ lines.push('## Tone\n');
182
+ for (const [tone, count] of toneEntries) {
183
+ lines.push(`- **${tone}** (${count} captures)`);
184
+ }
185
+ lines.push('');
186
+ }
187
+ // Heading styles
188
+ const headingEntries = Object.entries(styles.headingStyles).sort((a, b) => b[1] - a[1]);
189
+ if (headingEntries.length > 0) {
190
+ lines.push('## Heading Patterns\n');
191
+ lines.push('| Style | Count |');
192
+ lines.push('| --- | --- |');
193
+ for (const [style, count] of headingEntries) {
194
+ lines.push(`| ${style} | ${count} |`);
195
+ }
196
+ lines.push('');
197
+ }
198
+ // CTAs
199
+ if (styles.topCtas.length > 0) {
200
+ lines.push('## CTA Patterns\n');
201
+ lines.push('| Text | Action Verb | Occurrences |');
202
+ lines.push('| --- | --- | --- |');
203
+ for (const cta of styles.topCtas) {
204
+ lines.push(`| ${cta.text} | ${cta.verb} | ${cta.count} |`);
205
+ }
206
+ lines.push('');
207
+ }
208
+ // Text hierarchy
209
+ if (styles.textLevels.length > 0) {
210
+ lines.push('## Text Hierarchy\n');
211
+ lines.push('| Element | Count | Avg Words |');
212
+ lines.push('| --- | --- | --- |');
213
+ for (const level of styles.textLevels) {
214
+ lines.push(`| ${level.level} | ${level.count} | ${level.avgWords} |`);
215
+ }
216
+ lines.push('');
217
+ }
218
+ // Readability
219
+ lines.push('## Readability\n');
220
+ lines.push(`- **Avg sentence length:** ${styles.avgSentenceLength} words`);
221
+ lines.push('');
222
+ return lines.join('\n');
223
+ }
224
+ //# sourceMappingURL=writingStyle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"writingStyle.js","sourceRoot":"","sources":["../src/writingStyle.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "design-brain-memory",
3
- "version": "0.9.3",
3
+ "version": "0.9.4",
4
4
  "description": "Relational markdown design memory powered by Agent Browser CLI",
5
5
  "repository": {
6
6
  "type": "git",
@@ -16,15 +16,16 @@
16
16
  "design-brain-memory": "dist/cli.js"
17
17
  },
18
18
  "files": [
19
- "dist",
20
- "skills"
19
+ "dist"
21
20
  ],
22
21
  "scripts": {
23
22
  "build": "tsc -p tsconfig.json",
24
23
  "clean": "rm -rf dist",
25
24
  "dev": "tsx src/cli.ts",
26
25
  "test": "npm run build && node --test tests/*.test.mjs",
27
- "pack:dry": "npm pack --dry-run"
26
+ "pack:dry": "npm pack --dry-run",
27
+ "release:check": "npm run clean && npm run test && npm run pack:dry",
28
+ "prepublishOnly": "npm run release:check"
28
29
  },
29
30
  "keywords": [
30
31
  "design",
@@ -1,21 +0,0 @@
1
- import type { AnimationToken, KeyframeStop, PhysicsParams, AnimationGroup } from './types.js';
2
- /**
3
- * Classify the motion intent of an animation based on its keyframe properties.
4
- */
5
- export declare function classifyMotionIntent(keyframes: KeyframeStop[]): AnimationToken['motionIntent'];
6
- /**
7
- * Detect physics-based motion (spring/bounce) from keyframe value progressions.
8
- * Looks for overshoot and oscillation around the final value.
9
- */
10
- export declare function detectPhysics(keyframes: KeyframeStop[], trackProperty: string): PhysicsParams | null;
11
- /**
12
- * Map GSAP easing string to physics params when applicable.
13
- */
14
- export declare function classifyGsapEasing(easeString: string | undefined | null): PhysicsParams | null;
15
- /**
16
- * Detect animation groups (staggered sequences) by matching tokens
17
- * with the same motionIntent, library, duration, and easing but different delays.
18
- */
19
- export declare function detectAnimationGroups<T extends Pick<AnimationToken, 'selector' | 'motionIntent' | 'library' | 'timing' | 'keyframes' | 'trigger'>>(tokens: T[]): Array<T & {
20
- group?: AnimationGroup;
21
- }>;
package/dist/classify.js DELETED
@@ -1,205 +0,0 @@
1
- /**
2
- * Classify the motion intent of an animation based on its keyframe properties.
3
- */
4
- export function classifyMotionIntent(keyframes) {
5
- if (keyframes.length === 0)
6
- return 'complex';
7
- const allProps = new Set();
8
- for (const kf of keyframes) {
9
- for (const prop of Object.keys(kf.properties)) {
10
- allProps.add(prop);
11
- }
12
- }
13
- const hasOpacity = allProps.has('opacity');
14
- const hasTransform = allProps.has('transform');
15
- const hasColor = allProps.has('backgroundColor') || allProps.has('color') || allProps.has('borderColor');
16
- const hasClipPath = allProps.has('clipPath');
17
- const hasWidthHeight = allProps.has('width') || allProps.has('height');
18
- const categories = [];
19
- if (hasOpacity)
20
- categories.push('opacity');
21
- if (hasTransform)
22
- categories.push('transform');
23
- if (hasColor)
24
- categories.push('color');
25
- if (hasClipPath || hasWidthHeight)
26
- categories.push('reveal');
27
- if (categories.length > 1)
28
- return 'complex';
29
- if (categories.length === 0)
30
- return 'complex';
31
- if (hasOpacity && !hasTransform)
32
- return 'fade';
33
- if (hasColor)
34
- return 'color-shift';
35
- if (hasClipPath || hasWidthHeight)
36
- return 'reveal';
37
- if (hasTransform) {
38
- return classifyTransformIntent(keyframes);
39
- }
40
- return 'complex';
41
- }
42
- function classifyTransformIntent(keyframes) {
43
- const transforms = keyframes
44
- .map((kf) => kf.properties.transform ?? '')
45
- .filter(Boolean);
46
- const hasTranslate = transforms.some((t) => /translate[XY]?\s*\(/.test(t));
47
- const hasScale = transforms.some((t) => /scale[XY]?\s*\(/.test(t));
48
- const hasRotate = transforms.some((t) => /rotate[XYZ]?\s*\(/.test(t));
49
- const count = [hasTranslate, hasScale, hasRotate].filter(Boolean).length;
50
- if (count > 1)
51
- return 'complex';
52
- if (hasTranslate)
53
- return 'slide';
54
- if (hasScale)
55
- return 'scale';
56
- if (hasRotate)
57
- return 'rotate';
58
- return 'complex';
59
- }
60
- /**
61
- * Extract a numeric value from a transform function string.
62
- * e.g., "translateX(100px)" → 100
63
- */
64
- function extractNumericFromTransform(transformStr, fnName) {
65
- const re = new RegExp(`${fnName}\\s*\\(\\s*(-?[\\d.]+)`);
66
- const match = transformStr.match(re);
67
- return match ? parseFloat(match[1]) : null;
68
- }
69
- /**
70
- * Detect physics-based motion (spring/bounce) from keyframe value progressions.
71
- * Looks for overshoot and oscillation around the final value.
72
- */
73
- export function detectPhysics(keyframes, trackProperty) {
74
- if (keyframes.length < 3)
75
- return null;
76
- const values = [];
77
- for (const kf of keyframes) {
78
- const transformStr = kf.properties.transform ?? kf.properties[trackProperty] ?? '';
79
- const numericVal = extractNumericFromTransform(transformStr, trackProperty)
80
- ?? parseFloat(transformStr);
81
- if (Number.isNaN(numericVal))
82
- return null;
83
- values.push(numericVal);
84
- }
85
- if (values.length < 3)
86
- return null;
87
- const finalValue = values[values.length - 1];
88
- const startValue = values[0];
89
- const range = Math.abs(finalValue - startValue);
90
- if (range === 0)
91
- return null;
92
- // Count zero-crossings relative to final value
93
- let crossings = 0;
94
- let maxOvershoot = 0;
95
- for (let i = 1; i < values.length - 1; i++) {
96
- const prevDelta = values[i - 1] - finalValue;
97
- const currDelta = values[i] - finalValue;
98
- if (prevDelta * currDelta < 0) {
99
- crossings++;
100
- }
101
- const overshoot = Math.abs(currDelta);
102
- if (overshoot > maxOvershoot) {
103
- maxOvershoot = overshoot;
104
- }
105
- }
106
- // Check if any intermediate value overshoots the final value
107
- const overshoots = values.some((v, i) => {
108
- if (i === 0 || i === values.length - 1)
109
- return false;
110
- if (finalValue > startValue)
111
- return v > finalValue;
112
- return v < finalValue;
113
- });
114
- if (!overshoots)
115
- return null;
116
- const overshootPercent = Math.round((maxOvershoot / range) * 100);
117
- if (crossings >= 2) {
118
- return {
119
- type: 'spring',
120
- oscillationCount: crossings,
121
- overshootPercent,
122
- };
123
- }
124
- return {
125
- type: 'bounce',
126
- oscillationCount: crossings || 1,
127
- overshootPercent,
128
- };
129
- }
130
- /**
131
- * Map GSAP easing string to physics params when applicable.
132
- */
133
- export function classifyGsapEasing(easeString) {
134
- if (!easeString)
135
- return null;
136
- const lower = easeString.toLowerCase();
137
- if (lower.includes('elastic')) {
138
- return { type: 'spring', oscillationCount: 3 };
139
- }
140
- if (lower.includes('bounce')) {
141
- return { type: 'bounce', oscillationCount: 4 };
142
- }
143
- if (lower.includes('back')) {
144
- return { type: 'spring', oscillationCount: 1, overshootPercent: 10 };
145
- }
146
- return null;
147
- }
148
- /**
149
- * Detect animation groups (staggered sequences) by matching tokens
150
- * with the same motionIntent, library, duration, and easing but different delays.
151
- */
152
- export function detectAnimationGroups(tokens) {
153
- if (tokens.length < 2) {
154
- return tokens.map((t) => ({ ...t }));
155
- }
156
- // Group candidates by signature (same intent, library, duration, easing)
157
- const buckets = new Map();
158
- for (let i = 0; i < tokens.length; i++) {
159
- const t = tokens[i];
160
- if (!t.timing)
161
- continue;
162
- const sig = `${t.motionIntent}|${t.library}|${t.timing.duration}|${t.timing.easing}|${keyframeSignature(t.keyframes)}`;
163
- const bucket = buckets.get(sig) ?? [];
164
- bucket.push({ index: i, delay: t.timing.delay });
165
- buckets.set(sig, bucket);
166
- }
167
- const result = tokens.map((t) => ({ ...t }));
168
- let groupCounter = 0;
169
- for (const [, bucket] of buckets) {
170
- if (bucket.length < 2)
171
- continue;
172
- // Sort by delay
173
- bucket.sort((a, b) => a.delay - b.delay);
174
- // Check if delays form a stagger pattern (roughly equal increments)
175
- const deltas = [];
176
- for (let i = 1; i < bucket.length; i++) {
177
- deltas.push(bucket[i].delay - bucket[i - 1].delay);
178
- }
179
- const avgDelta = deltas.reduce((sum, d) => sum + d, 0) / deltas.length;
180
- const isStagger = avgDelta > 0 && deltas.every((d) => Math.abs(d - avgDelta) <= avgDelta * 0.5);
181
- if (!isStagger)
182
- continue;
183
- groupCounter++;
184
- const groupId = `group-${groupCounter}`;
185
- const leadDelay = bucket[0].delay;
186
- for (let i = 0; i < bucket.length; i++) {
187
- const entry = bucket[i];
188
- result[entry.index] = {
189
- ...result[entry.index],
190
- group: {
191
- groupId,
192
- role: i === 0 ? 'lead' : 'follower',
193
- staggerDelay: i === 0 ? 0 : entry.delay - leadDelay,
194
- },
195
- };
196
- }
197
- }
198
- return result;
199
- }
200
- function keyframeSignature(keyframes) {
201
- if (!keyframes || keyframes.length === 0)
202
- return '';
203
- return keyframes.map((kf) => Object.keys(kf.properties).sort().join(',')).join('|');
204
- }
205
- //# sourceMappingURL=classify.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"classify.js","sourceRoot":"","sources":["../src/classify.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- import type { ScanResult } from './types.js';
2
- export declare function renderScanResults(result: ScanResult): void;
@@ -1,155 +0,0 @@
1
- /* ─── ANSI helpers ─── */
2
- const USE_COLOR = process.stdout.isTTY !== false;
3
- const RESET = USE_COLOR ? '\x1b[0m' : '';
4
- const BOLD = USE_COLOR ? '\x1b[1m' : '';
5
- const DIM = USE_COLOR ? '\x1b[2m' : '';
6
- const GREEN = USE_COLOR ? '\x1b[32m' : '';
7
- const CYAN = USE_COLOR ? '\x1b[36m' : '';
8
- const YELLOW = USE_COLOR ? '\x1b[33m' : '';
9
- const WHITE = USE_COLOR ? '\x1b[37m' : '';
10
- const MAGENTA = USE_COLOR ? '\x1b[35m' : '';
11
- /* ─── Box drawing ─── */
12
- const BOX_WIDTH = 48;
13
- function topBorder(title) {
14
- if (title) {
15
- const label = `\u2500 ${title} `;
16
- const rest = '\u2500'.repeat(Math.max(0, BOX_WIDTH - label.length - 1));
17
- return ` ${DIM}\u250c${label}${rest}\u2510${RESET}`;
18
- }
19
- return ` ${DIM}\u250c${'\u2500'.repeat(BOX_WIDTH)}\u2510${RESET}`;
20
- }
21
- function bottomBorder() {
22
- return ` ${DIM}\u2514${'\u2500'.repeat(BOX_WIDTH)}\u2518${RESET}`;
23
- }
24
- function boxLine(content, rawLength) {
25
- const padding = Math.max(0, BOX_WIDTH - rawLength);
26
- return ` ${DIM}\u2502${RESET} ${content}${' '.repeat(padding - 1)}${DIM}\u2502${RESET}`;
27
- }
28
- function emptyBoxLine() {
29
- return ` ${DIM}\u2502${' '.repeat(BOX_WIDTH)}\u2502${RESET}`;
30
- }
31
- /* ─── Score bar ─── */
32
- function scoreBar(label, value, max) {
33
- const barWidth = 16;
34
- const filled = Math.round((value / max) * barWidth);
35
- const empty = barWidth - filled;
36
- const bar = `${GREEN}\u2588${RESET}`.repeat(filled) + `${DIM}\u2591${RESET}`.repeat(empty);
37
- const paddedLabel = label.padEnd(22);
38
- const valueStr = `${value}`.padStart(2);
39
- return `${paddedLabel}${bar} ${BOLD}${valueStr}${RESET}`;
40
- }
41
- function scoreBarRaw(label, value, max) {
42
- // Raw length without ANSI
43
- return label.padEnd(22).length + 16 + 2 + `${value}`.padStart(2).length;
44
- }
45
- /* ─── Checkmark lines ─── */
46
- function check(text) {
47
- return ` ${GREEN}\u2714${RESET} ${text}`;
48
- }
49
- /* ─── Framework display name ─── */
50
- function frameworkName(fw) {
51
- if (!fw)
52
- return 'None detected';
53
- const names = {
54
- tailwind: 'Tailwind CSS',
55
- chakra: 'Chakra UI',
56
- mui: 'Material UI',
57
- };
58
- return names[fw] ?? fw;
59
- }
60
- /* ─── Main renderer ─── */
61
- export function renderScanResults(result) {
62
- const { tokens, score, persona, filesScanned, framework } = result;
63
- console.log('');
64
- // Header box
65
- console.log(topBorder());
66
- console.log(emptyBoxLine());
67
- const title = `${BOLD}${CYAN}design-brain${RESET} v0.9.3`;
68
- console.log(boxLine(title, 'design-brain v0.9.3'.length));
69
- const subtitle = `${DIM}Relational design memory${RESET}`;
70
- console.log(boxLine(subtitle, 'Relational design memory'.length));
71
- console.log(emptyBoxLine());
72
- console.log(bottomBorder());
73
- console.log('');
74
- // Checkmark summary
75
- const isUrl = result.path.startsWith('http://') || result.path.startsWith('https://');
76
- if (isUrl) {
77
- console.log(check(`Scanned ${BOLD}${result.path}${RESET} (live site)`));
78
- }
79
- else {
80
- console.log(check(`Scanned ${BOLD}${filesScanned}${RESET} files`));
81
- }
82
- console.log(check(`Found ${BOLD}${tokens.colors.length}${RESET} colors, ` +
83
- `${BOLD}${tokens.fontFamilies.length}${RESET} fonts, ` +
84
- `${BOLD}${tokens.spacingValues.length}${RESET} spacing values, ` +
85
- `${BOLD}${tokens.transitions.length}${RESET} transitions`));
86
- if (framework) {
87
- console.log(check(`Detected framework: ${BOLD}${frameworkName(framework)}${RESET}`));
88
- }
89
- console.log(check(`Design Health Score: ${BOLD}${scoreColor(score.total)}${score.total}/100${RESET}`));
90
- console.log('');
91
- // Score breakdown box
92
- console.log(topBorder('Design Health'));
93
- console.log(emptyBoxLine());
94
- const categories = [
95
- ['Color Discipline', score.colorDiscipline, 25],
96
- ['Typography System', score.typographySystem, 25],
97
- ['Spacing & Layout', score.spacingLayout, 25],
98
- ['Motion & Polish', score.motionPolish, 25],
99
- ];
100
- for (const [label, value, max] of categories) {
101
- const bar = scoreBar(label, value, max);
102
- const rawLen = scoreBarRaw(label, value, max);
103
- console.log(boxLine(bar, rawLen));
104
- }
105
- console.log(emptyBoxLine());
106
- const totalBar = scoreBar('Total', score.total, 100);
107
- const totalRawLen = scoreBarRaw('Total', score.total, 100);
108
- console.log(boxLine(totalBar, totalRawLen));
109
- console.log(emptyBoxLine());
110
- console.log(bottomBorder());
111
- console.log('');
112
- // Persona box
113
- console.log(topBorder('Your Design Persona'));
114
- console.log(emptyBoxLine());
115
- const personaLine = `${MAGENTA}\u{1f3a8}${RESET} ${BOLD}${persona.name}${RESET}`;
116
- console.log(boxLine(personaLine, `\u{1f3a8} ${persona.name}`.length + 1));
117
- // Tagline (wrapped)
118
- const tagline = `${DIM}"${persona.tagline}"${RESET}`;
119
- console.log(boxLine(tagline, `"${persona.tagline}"`.length));
120
- console.log(emptyBoxLine());
121
- // Reasoning (word-wrap to box width)
122
- const reasonLines = wordWrap(persona.reasoning, BOX_WIDTH - 4);
123
- for (const line of reasonLines) {
124
- console.log(boxLine(`${DIM}${line}${RESET}`, line.length));
125
- }
126
- console.log(emptyBoxLine());
127
- console.log(bottomBorder());
128
- console.log('');
129
- }
130
- function scoreColor(total) {
131
- if (total >= 75)
132
- return GREEN;
133
- if (total >= 50)
134
- return YELLOW;
135
- return '\x1b[31m'; // red
136
- }
137
- function wordWrap(text, maxWidth) {
138
- const words = text.split(' ');
139
- const lines = [];
140
- let current = '';
141
- for (const word of words) {
142
- if (current.length + word.length + 1 > maxWidth) {
143
- if (current)
144
- lines.push(current);
145
- current = word;
146
- }
147
- else {
148
- current = current ? `${current} ${word}` : word;
149
- }
150
- }
151
- if (current)
152
- lines.push(current);
153
- return lines;
154
- }
155
- //# sourceMappingURL=scanRenderer.js.map