medesign 0.0.0-stage → 1.2.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 (82) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +128 -2
  3. package/bin/medesign.js +200 -0
  4. package/integrations/claude-code/SKILL.md +20 -0
  5. package/integrations/cursor/medesign.mdc +26 -0
  6. package/medesign.config.js +46 -0
  7. package/package.json +62 -4
  8. package/presets/apple/design-tokens.css +115 -0
  9. package/presets/apple/guidelines.md +19 -0
  10. package/presets/apple/preset.json +53 -0
  11. package/presets/metha/design-tokens.css +127 -0
  12. package/presets/metha/guidelines.md +23 -0
  13. package/presets/metha/preset.json +53 -0
  14. package/presets/schema.json +102 -0
  15. package/presets/tesla/design-tokens.css +112 -0
  16. package/presets/tesla/guidelines.md +17 -0
  17. package/presets/tesla/preset.json +53 -0
  18. package/references/ai-tells.md +127 -0
  19. package/references/appendices.md +220 -0
  20. package/references/architecture.md +39 -0
  21. package/references/argon-design-archetypes.md +317 -0
  22. package/references/banner-sizes-and-styles.md +118 -0
  23. package/references/block-library.md +61 -0
  24. package/references/brand-design-tokens.md +42 -0
  25. package/references/catalog.json +108 -0
  26. package/references/cip-deliverable-guide.md +95 -0
  27. package/references/cip-design.md +121 -0
  28. package/references/cip-prompt-engineering.md +84 -0
  29. package/references/cip-style-guide.md +68 -0
  30. package/references/cli-architecture.md +146 -0
  31. package/references/components.md +240 -0
  32. package/references/dark-mode.md +23 -0
  33. package/references/design-core.md +42 -0
  34. package/references/design-md-protocol.md +75 -0
  35. package/references/design-routing.md +207 -0
  36. package/references/eng-imagery-content.md +71 -0
  37. package/references/eng-layout.md +28 -0
  38. package/references/eng-other.md +26 -0
  39. package/references/eng-states-theme.md +22 -0
  40. package/references/eng-type-color.md +44 -0
  41. package/references/icon-design.md +122 -0
  42. package/references/image-mockup-direction.md +53 -0
  43. package/references/image-to-code.md +46 -0
  44. package/references/impeccable-polish.md +85 -0
  45. package/references/intake.md +90 -0
  46. package/references/logo-color-psychology.md +101 -0
  47. package/references/logo-design.md +110 -0
  48. package/references/logo-prompt-engineering.md +158 -0
  49. package/references/logo-style-guide.md +109 -0
  50. package/references/mesurv-dna.md +104 -0
  51. package/references/micro-interactions-and-auto-animate.md +71 -0
  52. package/references/modern-craft-invariants.md +332 -0
  53. package/references/motion-tokens.md +99 -0
  54. package/references/preflight.md +110 -0
  55. package/references/proactive-motion.md +167 -0
  56. package/references/quality-gate.md +147 -0
  57. package/references/redesign-audit.md +38 -0
  58. package/references/redesign.md +52 -0
  59. package/references/slides-copywriting-formulas.md +84 -0
  60. package/references/slides-create.md +4 -0
  61. package/references/slides-html-template.md +295 -0
  62. package/references/slides-layout-patterns.md +137 -0
  63. package/references/slides-strategies.md +94 -0
  64. package/references/slides.md +42 -0
  65. package/references/social-photos-design.md +329 -0
  66. package/references/spatial-canvas-engine.md +160 -0
  67. package/references/stitch-system.md +184 -0
  68. package/references/style-extraction.md +17 -0
  69. package/references/styles/brutalist.md +88 -0
  70. package/references/styles/minimalist.md +81 -0
  71. package/references/styles/soft.md +94 -0
  72. package/references/threeui-spatial-engine.md +224 -0
  73. package/references/ui-styling-shadcn.md +336 -0
  74. package/references/ui-ux-vocabulary-vault.json +1223 -0
  75. package/references/ui-ux-vocabulary-vault.md +438 -0
  76. package/references/vocab-protocol.md +52 -0
  77. package/references/vocabulary.md +78 -0
  78. package/scripts/export-tokens.js +403 -0
  79. package/tests/browser-audit.js +442 -0
  80. package/tests/linter.js +412 -0
  81. package/tests/schemas/sarif-2.1.0.schema.json +2915 -0
  82. package/tests/visual-testbed.html +681 -0
@@ -0,0 +1,52 @@
1
+ ## 7. World-Class 50+4 Category Vocabulary Vault & Smart Questioning / Auto-Inspector Protocol
2
+
3
+ ### 📚 คลังคำศัพท์และแม่แบบระดับโลกที่บันทึกในเครื่อง (50+4 หมวดหมู่ · 750+ คำศัพท์ & Patterns — ผู้ใช้ไม่ต้องจำศัพท์เอง)
4
+ - **Markdown Reference:** `references/ui-ux-vocabulary-vault.md`
5
+ - **Structured JSON:** `references/ui-ux-vocabulary-vault.json`
6
+ - **Interactive Localhost Explorer:** `http://localhost:3333/vocab`
7
+ - **ขอบเขตเนื้อหา 4 ชั้น (ครบ 50+4 หมวดหมู่):**
8
+ 1. **หมวดที่ 1–20 (Core UI/UX Architecture):** Website Structure, Navigation, Layout, Spacing, UI Components, Information Components, Dashboard Design, Micro-interactions, Motion, Responsive, Typography, Visual Design, Design System, Modern UI Styles, UX Vocabulary, A11y, UX States, Web Layout Patterns, UX Patterns, Performance
9
+ 2. **หมวดที่ 21–33 (Extended World-Class & WebGIS UI):** Advanced Visual Effects, Color System, Complete Interactive States Matrix, Advanced Layout Techniques, Data Visualization UI, **GIS-Specific UI (Map Canvas, Basemap, Vector/Raster Layers, Extent/Fit Bounds, Scale Bar, Spatial Query, Snapping/Vertex Editing)**, Premium UI Patterns, Modern Design Trends, Performance & Optimization, Detailed A11y, Design Handoff, Professional Jargon, AI Prompt-Friendly Terms
10
+ 3. **หมวดที่ 34–50 (17 หมวดความรู้เสริม & Missing Mastery Patterns):**
11
+ - `34` Visual Rhythm & Eye-Tracking Flow (`F-Pattern`, `Z-Pattern`, `Layer-Cake`, `Spotted`, `Gutenberg Diagram`)
12
+ - `35` Grid Sophistication (`Compound 4+3 Grid`, `Asymmetric 8:4 / 7:5`, `Golden Ratio 1:1.618`, `Exposed 1px Swiss Grid`)
13
+ - `36` Typography Mastery (`1.200 / 1.250 Modular Scale`, `Tabular Lining Figures`, `Slashed Zero`, `text-wrap: balance`)
14
+ - `37` Color Psychology & `60-30-10` Rule (`60%` Canvas `#f3f1eb`/`#050505` : `30%` Surface `#fff`/`#111` : `10%` Accent `#15803d`/`#34d399`)
15
+ - `38` Spacing System (`8pt Spatial Grid` + `4pt Micro-Grid` + `Internal <= External Proximity Rule`)
16
+ - `39` Complete 9-State Component Checklist (`Default`, `Hover`, `Focus-Visible`, `Active scale(0.97)`, `Disabled`, `Loading`, `Empty + 1-Click Sample Loader`, `Error + Recovery`, `Success/Verified`)
17
+ - `40` Animation Principles (`150ms–200ms Micro-Response`, `GPU-Safe transform/opacity`, `Zero Hover Bounce`)
18
+ - `41` Professional Layout Terminology (`Above the Fold`, `Eyebrow/Kicker`, `Chrome vs Canvas Ratio 12:88`)
19
+ - `42` Advanced Interaction Patterns (`Synchronized Table ↔ Map Highlighting`, `Inline Direct Editing`, `Smart Excel/CSV Paste`)
20
+ - `43` Dashboard-Specific Patterns (`Co-located Action Bar`, `Pinned Summary/Misclosure Row`, `KPI with Tolerance Badge`)
21
+ - `44` Responsive Priority+ (`Priority+ Top Nav`, `Desktop Split → Mobile Tabs`, `Sticky Station Column`)
22
+ - `45` Error Prevention & Recovery (`1-Click Sample Data Cure`, `Explicit Unit Headers`, `localStorage Persistence`)
23
+ - `46` Performance Budget (`CLS = 0`, `Instant CSS Variable Theme Switch`, `60fps Inline SVG`)
24
+ - `47` A11y Pre-Flight Checklist (`Outdoor AAA Contrast >12:1`, `Icon + Text + Color Redundancy`)
25
+ - `48` 3-Tier Design Tokens (`Tier 1 Primitive` → `Tier 2 Semantic` → `Tier 3 Component`)
26
+ - `49` 6-Part AI Design Prompt Formula & Component Spec Blueprint
27
+ - `50` 10 Anti-Patterns & 12-Point Pre-Delivery QA Gate
28
+ 4. **หมวดลับ `EXP-01` ถึง `EXP-04` (Expert Design Engineer Vocabulary):** Surface Physics, Typographic Micro-Mechanics, Spatial Topology, High-Craft Interaction Density
29
+
30
+ ### 🧠 กฎเหล็กสำหรับผู้ใช้ที่ไม่จำคำศัพท์ (Recognition over Recall & Auto-Context Inspection)
31
+ เมื่อผู้ใช้สั่ง `/medesign` ให้ปฏิบัติตาม 2 โหมดอัจฉริยะนี้เสมอ:
32
+
33
+ 1. **โหมดสร้างอัตโนมัติจากข้อมูลที่มีโดยไม่ต้องถาม (`Zero-Question Auto-Context Inspector — Q-01`):**
34
+ - เมื่อผู้ใช้ส่งรายละเอียดงาน โค้ดเดิม หรือสั่งให้จัดการจากข้อมูลที่มีอยู่ **ห้ามยิงคำถามจุกจิกซ้ำซาก**
35
+ - ให้ AI แปลงคำสั่งสั้นๆ เข้าสู่ **6-Part Master Prompt Formula (หมวด 49)** และสรุป **Coverage Audit 3 ส่วน** ทันทีก่อนลงมือสร้าง:
36
+ 1. **หัวข้อหลักที่ตรวจพบ (Detected Primary Sections):** สกัดว่าหน้านี้ต้องมีหัวข้อหลัก ตาราง กราฟ หรือส่วนแสดงผลอะไรบ้างจากข้อมูลที่ให้มา
37
+ 2. **ส่วนสำคัญที่ระบบเติมให้อัตโนมัติ (Auto-Completed Missing Essentials — หมวด 39, 43, 45):** ตรวจสอบว่ายังขาดองค์ประกอบสำคัญอะไรที่ทำให้ใช้งานจริงได้สมบูรณ์ (เช่น ปุ่ม `📥 โหลดข้อมูลตัวอย่าง 1 คลิก` สำหรับแก้ปัญหาหน้าโล่ง, แถวสรุปผลรวมท้ายตาราง `Pinned Totals / Misclosure Row`, ป้ายสถานะเกณฑ์มาตรฐาน `Pass/Fail Badge`, แถบปุ่ม `ส่งออก CSV/GeoJSON` ที่วางติดกับหัวตาราง, ระบบสลับธีม `Fieldbook ↔ Terminal`) แล้วเติมให้ครบอัตโนมัติทันที
38
+ 3. **กฎดีไซน์ระดับโลกจาก DNA & 12-Point QA Gate (หมวด 34–50):** บังคับใช้ `Zero-Sidebar Top-Nav`, `Underline 2px Tabs`, `Z/F-Pattern Flow`, `60-30-10 Color Rule`, `8pt Spacing`, `Geist Mono Tabular Numerals`, `3-Tier CSS Tokens` และบล็อก Anti-Slop ทั้ง 10 ข้อโดยอัตโนมัติ
39
+
40
+ 2. **โหมดยิงคำถามระดับ Expert สำหรับเวลาที่ต้องการให้ผู้ใช้เลือก (`Expert Visual Questioning — Q-02 ถึง Q-06`):**
41
+ - **ห้ามถามด้วยคำศัพท์เทคนิคดิบๆ** (เช่น ห้ามถามลอยๆ ว่า *"ต้องการ Tonal Layering หรือ Glassmorphism?"*)
42
+ - ต้องแปลเป็น **"ภาษาคนเข้าใจง่าย + บอกผลลัพธ์ทางสายตาและการใช้งานจริง"** พร้อมใส่ `(Recommended ตาม DNA)` ไว้ที่ตัวเลือกแรกเสมอ
43
+ - สามารถเปิด **Localhost Interactive Questioner Templates (`http://localhost:3333/wizard/1` ถึง `/wizard/6`)** ให้ผู้ใช้คลิกเลือกจากภาพจริงได้ทั้ง 6 รูปแบบ:
44
+ - `Q-01` (`/wizard/1`): **Zero-Question Auto-Context Inspector** — สแกนข้อมูล ตรวจเช็กหัวข้อหลัก เติมส่วนที่ขาด (ครบ 9 States & 12 QA Gate) และสร้างหน้าเว็บสดทันที
45
+ - `Q-02` (`/wizard/2`): **Visual Anatomy Card Deck** — ไพ่ภาพจำลองขนาดจิ๋วเปรียบเทียบสดครบ 4 มิติ ไม่ต้องจำศัพท์
46
+ - `Q-03` (`/wizard/3`): **Split-Screen Tactile Equalizer** — เลื่อนสไลเดอร์และสวิตช์เปิด/ปิดหัวข้อหลักทางซ้าย ดูหน้าเว็บเปลี่ยนสดทางขวา
47
+ - `Q-04` (`/wizard/4`): **Smart 3-Step Triage** — ล็อก DNA 80% แล้วถามเฉพาะเป้าหมายหลักของหน้า (พร้อมปุ่มข้ามคำถามทั้งหมด)
48
+ - `Q-05` (`/wizard/5`): **Component A/B/C Shootout** — วางชิ้นส่วน UI ของจริงเทียบกันครบ 3 ท่อน (แถบเมนูบน, การ์ด KPI, ตารางคู่ผังกราฟิก) ให้กดโหวตเลือกแล้วประกอบร่างสด
49
+ - `Q-06` (`/wizard/6`): **Swiss Engineering Blueprint Matrix** — แผงพิมพ์เขียวตารางเส้นคม 1px ควบคุมครบทุกหมวดพร้อม 12-Point Pre-Delivery QA Gate ในหน้าเดียว
50
+
51
+ ---
52
+
@@ -0,0 +1,78 @@
1
+ ## 10. REFERENCE VOCABULARY (Pattern Names the Agent Should Know)
2
+
3
+ This is a vocabulary, not a library. The agent should KNOW these pattern names to communicate about them, design with them in mind, and reach for them when the design read calls for them. **Implementations and code sketches live in the Block Library (Section 12), which is populated iteratively.**
4
+
5
+ ### Hero Paradigms
6
+ * **Asymmetric Split Hero** - Text on one side, asset on the other, generous white space.
7
+ * **Editorial Manifesto Hero** - Large type, no asset, almost-poster.
8
+ * **Video / Media Mask Hero** - Type cut out as mask over video background.
9
+ * **Kinetic-Type Hero** - Animated typography as the primary visual.
10
+ * **Curtain-Reveal Hero** - Hero parts on scroll like a curtain.
11
+ * **Scroll-Pinned Hero** - Hero stays pinned while content scrolls behind.
12
+
13
+ ### Navigation & Menus
14
+ * **Mac OS Dock Magnification** - Edge nav, icons scale fluidly on hover.
15
+ * **Magnetic Button** - Pulls toward cursor.
16
+ * **Gooey Menu** - Sub-items detach like viscous liquid.
17
+ * **Dynamic Island** - Morphing pill for status / alerts.
18
+ * **Contextual Radial Menu** - Circular menu expanding at click point.
19
+ * **Floating Speed Dial** - FAB springing into curved secondary actions.
20
+ * **Mega Menu Reveal** - Full-screen dropdown, stagger-fade content.
21
+
22
+ ### Layout & Grids
23
+ * **Bento Grid** - Asymmetric tile grouping (Apple Control Center).
24
+ * **Masonry Layout** - Staggered grid, no fixed row height.
25
+ * **Chroma Grid** - Borders / tiles with subtle animating gradients.
26
+ * **Split-Screen Scroll** - Two halves sliding in opposite directions.
27
+ * **Sticky-Stack Sections** - Sections that pin and stack on scroll.
28
+
29
+ ### Cards & Containers
30
+ * **Parallax Tilt Card** - 3D tilt tracking mouse coordinates.
31
+ * **Spotlight Border Card** - Borders illuminate under cursor.
32
+ * **Glassmorphism Panel** - Frosted glass with inner refraction.
33
+ * **Holographic Foil Card** - Iridescent rainbow shift on hover.
34
+ * **Tinder Swipe Stack** - Physical card stack, swipe-away.
35
+ * **Morphing Modal** - Button expands into its own dialog.
36
+
37
+ ### Scroll Animations
38
+ * **Sticky Scroll Stack** - Cards stick and physically stack.
39
+ * **Horizontal Scroll Hijack** - Vertical scroll → horizontal pan.
40
+ * **Locomotive / Sequence Scroll** - Video / 3D sequence tied to scrollbar.
41
+ * **Zoom Parallax** - Central background image zooming on scroll.
42
+ * **Scroll Progress Path** - SVG line drawing along scroll.
43
+ * **Liquid Swipe Transition** - Page transition like viscous liquid.
44
+
45
+ ### Galleries & Media
46
+ * **Dome Gallery** - 3D panoramic gallery.
47
+ * **Coverflow Carousel** - 3D carousel with angled edges.
48
+ * **Drag-to-Pan Grid** - Boundless draggable canvas.
49
+ * **Accordion Image Slider** - Narrow strips expanding on hover.
50
+ * **Hover Image Trail** - Mouse leaves popping image trail.
51
+ * **Glitch Effect Image** - RGB-channel shift on hover.
52
+
53
+ ### Typography & Text
54
+ * **Kinetic Marquee** - Endless text bands reversing on scroll.
55
+ * **Text Mask Reveal** - Massive type as transparent window to video.
56
+ * **Text Scramble Effect** - Matrix-style decoding on load / hover.
57
+ * **Circular Text Path** - Text curving along spinning circle.
58
+ * **Gradient Stroke Animation** - Outlined text with running gradient.
59
+ * **Kinetic Typography Grid** - Letters dodging the cursor.
60
+
61
+ ### Micro-Interactions & Effects
62
+ * **Particle Explosion Button** - CTA shatters into particles on success.
63
+ * **Liquid Pull-to-Refresh** - Reload indicator like detaching droplets.
64
+ * **Skeleton Shimmer** - Shifting light reflection across placeholders.
65
+ * **Directional Hover-Aware Button** - Fill enters from cursor's exact side.
66
+ * **Ripple Click Effect** - Wave from click coordinates.
67
+ * **Animated SVG Line Drawing** - Vectors drawing themselves in real time.
68
+ * **Mesh Gradient Background** - Organic lava-lamp blobs.
69
+ * **Lens Blur Depth** - Background UI blurred to focus foreground action.
70
+
71
+ ### Animation Library Choice
72
+ * **Motion (`motion/react`)** - default for UI / Bento / state-change motion.
73
+ * **GSAP + ScrollTrigger** - for full-page scrolltelling and scroll hijacks. Isolate in dedicated leaf components with `useEffect` cleanup.
74
+ * **Three.js / WebGL** - for canvas backgrounds and 3D scenes. Same isolation rule.
75
+ * **NEVER mix GSAP / Three.js with Motion in the same component tree.** They fight over the same frames.
76
+
77
+ ---
78
+
@@ -0,0 +1,403 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * ME-DESIGN Token Exporter
5
+ * Converts preset design tokens into industry standard formats:
6
+ * 1. Tailwind CSS v4 `@theme` block
7
+ * 2. W3C Design Tokens Community Group (DTCG) standard specification JSON
8
+ * 3. Standard CSS Custom Properties (:root { ... })
9
+ *
10
+ * Usage:
11
+ * node scripts/export-tokens.js [--preset <name|all>] [--format <tailwind|dtcg|css|all>] [--out <dir>]
12
+ */
13
+
14
+ const fs = require('fs');
15
+ const path = require('path');
16
+
17
+ const presetsDir = path.join(__dirname, '..', 'presets');
18
+
19
+ // Parse CLI Arguments
20
+ const args = process.argv.slice(2);
21
+ let targetPreset = 'all';
22
+ let targetFormat = 'all';
23
+ let outDir = null;
24
+
25
+ for (let i = 0; i < args.length; i++) {
26
+ if (args[i] === '--preset' && args[i + 1]) {
27
+ targetPreset = args[++i].toLowerCase();
28
+ } else if (args[i] === '--format' && args[i + 1]) {
29
+ targetFormat = args[++i].toLowerCase();
30
+ } else if (args[i] === '--out' && args[i + 1]) {
31
+ outDir = args[++i];
32
+ }
33
+ }
34
+
35
+ // Discover available presets
36
+ const presetFolders = fs.readdirSync(presetsDir, { withFileTypes: true })
37
+ .filter(d => d.isDirectory())
38
+ .map(d => d.name)
39
+ .filter(name => fs.existsSync(path.join(presetsDir, name, 'preset.json')));
40
+
41
+ const selectedPresets = targetPreset === 'all'
42
+ ? presetFolders
43
+ : presetFolders.filter(p => p.toLowerCase() === targetPreset);
44
+
45
+ if (selectedPresets.length === 0) {
46
+ console.error(`Error: Preset '${targetPreset}' not found. Available presets: ${presetFolders.join(', ')}`);
47
+ process.exit(1);
48
+ }
49
+
50
+ // Format 1: Tailwind CSS v4 @theme Generator
51
+ function toTailwindV4Theme(preset) {
52
+ const lines = ['/* Tailwind CSS v4 @theme configuration */', '/* Generated by ME-DESIGN Token Engine */', '@theme {'];
53
+
54
+ // Colors
55
+ if (preset.color) {
56
+ if (preset.color.canvas) lines.push(` --color-canvas: ${preset.color.canvas};`);
57
+ if (preset.color.surfaceRaised) lines.push(` --color-surface-raised: ${preset.color.surfaceRaised};`);
58
+ if (preset.color.surfaceInset) lines.push(` --color-surface-inset: ${preset.color.surfaceInset};`);
59
+ if (preset.color.borderSubtle) lines.push(` --color-border-subtle: ${preset.color.borderSubtle};`);
60
+ if (preset.color.borderFocus) lines.push(` --color-border-focus: ${preset.color.borderFocus};`);
61
+ if (preset.color.accent) lines.push(` --color-accent: ${preset.color.accent};`);
62
+ if (preset.color.accentForeground) lines.push(` --color-accent-foreground: ${preset.color.accentForeground};`);
63
+
64
+ if (preset.color.status) {
65
+ Object.entries(preset.color.status).forEach(([k, v]) => {
66
+ lines.push(` --color-status-${k}: ${v};`);
67
+ });
68
+ }
69
+ }
70
+
71
+ // Typography
72
+ if (preset.typography) {
73
+ if (preset.typography.display) lines.push(` --font-display: ${preset.typography.display};`);
74
+ if (preset.typography.sans) lines.push(` --font-sans: ${preset.typography.sans};`);
75
+ if (preset.typography.mono) lines.push(` --font-mono: ${preset.typography.mono};`);
76
+ if (preset.typography.headingTracking) lines.push(` --tracking-heading: ${preset.typography.headingTracking};`);
77
+ if (preset.typography.uiLineHeight) lines.push(` --leading-ui: ${preset.typography.uiLineHeight};`);
78
+ if (preset.typography.proseLineHeight) lines.push(` --leading-prose: ${preset.typography.proseLineHeight};`);
79
+ }
80
+
81
+ // Geometry
82
+ if (preset.geometry) {
83
+ if (preset.geometry.radiusBase) lines.push(` --radius-base: ${preset.geometry.radiusBase};`);
84
+ if (preset.geometry.radiusOuter) lines.push(` --radius-outer: ${preset.geometry.radiusOuter};`);
85
+ if (preset.geometry.hitTargetMinTouch) lines.push(` --hit-target-min: ${preset.geometry.hitTargetMinTouch};`);
86
+ }
87
+
88
+ // Motion
89
+ if (preset.motion) {
90
+ if (preset.motion.easingEntry) lines.push(` --ease-entry: ${preset.motion.easingEntry};`);
91
+ if (preset.motion.easingExit) lines.push(` --ease-exit: ${preset.motion.easingExit};`);
92
+ if (preset.motion.durationEntry) lines.push(` --duration-entry: ${preset.motion.durationEntry};`);
93
+ if (preset.motion.durationExit) lines.push(` --duration-exit: ${preset.motion.durationExit};`);
94
+ }
95
+
96
+ lines.push('}');
97
+ return lines.join('\n');
98
+ }
99
+
100
+ function oklchToLinearRgb(l, c, h) {
101
+ const rad = h * Math.PI / 180;
102
+ const a = c * Math.cos(rad);
103
+ const b = c * Math.sin(rad);
104
+
105
+ const l1 = l + 0.3963377774 * a + 0.2158037573 * b;
106
+ const m1 = l - 0.1055613458 * a - 0.0638541728 * b;
107
+ const s1 = l - 0.0894841775 * a - 1.2914855480 * b;
108
+
109
+ const l_c = l1 * l1 * l1;
110
+ const m_c = m1 * m1 * m1;
111
+ const s_c = s1 * s1 * s1;
112
+
113
+ const r_lin = +4.0767434721 * l_c - 3.3077115913 * m_c + 0.2309699292 * s_c;
114
+ const g_lin = -1.2684380046 * l_c + 2.6097574011 * m_c - 0.3413193965 * s_c;
115
+ const b_lin = -0.0041960863 * l_c - 0.7034186147 * m_c + 1.7076147010 * s_c;
116
+
117
+ return [r_lin, g_lin, b_lin];
118
+ }
119
+
120
+ function inGamut(r, g, b, eps = 0.0001) {
121
+ return r >= -eps && r <= 1 + eps &&
122
+ g >= -eps && g <= 1 + eps &&
123
+ b >= -eps && b <= 1 + eps;
124
+ }
125
+
126
+ // Convert OKLCH to sRGB Hex using CSS Color 4 Gamut Mapping (binary search chroma reduction)
127
+ function oklchToHex(colorStr) {
128
+ if (!colorStr || !colorStr.startsWith('oklch(')) return null;
129
+ const match = colorStr.match(/oklch\(\s*([\d.]+)\s+([\d.]+)\s+([\d.]+)/i);
130
+ if (!match) return null;
131
+ const l = parseFloat(match[1]);
132
+ const c = parseFloat(match[2]);
133
+ const h = parseFloat(match[3]);
134
+
135
+ const [r0, g0, b0] = oklchToLinearRgb(l, c, h);
136
+ let bestRgb = [r0, g0, b0];
137
+
138
+ // If outside sRGB gamut, reduce chroma via binary search while preserving lightness and hue angle
139
+ if (!inGamut(r0, g0, b0)) {
140
+ let cLow = 0;
141
+ let cHigh = c;
142
+ for (let i = 0; i < 25; i++) {
143
+ const cMid = (cLow + cHigh) / 2;
144
+ const rgb = oklchToLinearRgb(l, cMid, h);
145
+ if (inGamut(rgb[0], rgb[1], rgb[2])) {
146
+ cLow = cMid;
147
+ bestRgb = rgb;
148
+ } else {
149
+ cHigh = cMid;
150
+ }
151
+ }
152
+ }
153
+
154
+ const gamma = (x) => x <= 0.0031308 ? 12.92 * x : 1.055 * Math.pow(Math.max(0, x), 1 / 2.4) - 0.055;
155
+ const R = Math.min(255, Math.max(0, Math.round(gamma(bestRgb[0]) * 255)));
156
+ const G = Math.min(255, Math.max(0, Math.round(gamma(bestRgb[1]) * 255)));
157
+ const B = Math.min(255, Math.max(0, Math.round(gamma(bestRgb[2]) * 255)));
158
+
159
+ return '#' + [R, G, B].map(x => x.toString(16).padStart(2, '0')).join('');
160
+ }
161
+
162
+ // Format 2: W3C Design Tokens Community Group (DTCG) Generator
163
+ // Supports 'oklch' (modern CSS Color 4) or 'srgb' (hex tokens for Figma / legacy tools)
164
+ function toDtcgTokens(preset, colorSpace = 'oklch') {
165
+ const dtcg = {
166
+ $name: preset.name,
167
+ $description: preset.description,
168
+ $version: '2024.1.0',
169
+ color: {},
170
+ fontFamily: {},
171
+ dimension: {},
172
+ duration: {},
173
+ cubicBezier: {}
174
+ };
175
+
176
+ // Colors
177
+ if (preset.color) {
178
+ Object.entries(preset.color).forEach(([k, v]) => {
179
+ if (typeof v === 'string') {
180
+ const tokenVal = colorSpace === 'srgb' ? (oklchToHex(v) || v) : v;
181
+ dtcg.color[k] = {
182
+ $value: tokenVal,
183
+ $type: 'color',
184
+ $description: `${k} color token for ${preset.name}`
185
+ };
186
+ } else if (typeof v === 'object') {
187
+ dtcg.color[k] = {};
188
+ Object.entries(v).forEach(([subK, subV]) => {
189
+ const tokenVal = colorSpace === 'srgb' ? (oklchToHex(subV) || subV) : subV;
190
+ dtcg.color[k][subK] = {
191
+ $value: tokenVal,
192
+ $type: 'color',
193
+ $description: `${k}.${subK} color token for ${preset.name}`
194
+ };
195
+ });
196
+ }
197
+ });
198
+ }
199
+
200
+ // Typography
201
+ if (preset.typography) {
202
+ ['display', 'sans', 'mono'].forEach(fontKey => {
203
+ if (preset.typography[fontKey]) {
204
+ dtcg.fontFamily[fontKey] = {
205
+ $value: preset.typography[fontKey],
206
+ $type: 'fontFamily',
207
+ $description: `${fontKey} font stack`
208
+ };
209
+ }
210
+ });
211
+ if (preset.typography.headingTracking) {
212
+ dtcg.dimension.headingTracking = {
213
+ $value: preset.typography.headingTracking,
214
+ $type: 'dimension',
215
+ $description: 'Optical negative tracking for headings'
216
+ };
217
+ }
218
+ }
219
+
220
+ // Geometry
221
+ if (preset.geometry) {
222
+ if (preset.geometry.radiusBase) {
223
+ dtcg.dimension.radiusBase = {
224
+ $value: preset.geometry.radiusBase,
225
+ $type: 'dimension',
226
+ $description: 'Base corner radius'
227
+ };
228
+ }
229
+ if (preset.geometry.radiusOuter) {
230
+ dtcg.dimension.radiusOuter = {
231
+ $value: preset.geometry.radiusOuter,
232
+ $type: 'dimension',
233
+ $description: 'Outer card corner radius'
234
+ };
235
+ }
236
+ if (preset.geometry.hitTargetMinTouch) {
237
+ dtcg.dimension.hitTargetMin = {
238
+ $value: preset.geometry.hitTargetMinTouch,
239
+ $type: 'dimension',
240
+ $description: 'WCAG 2.5.8 / HIG minimum touch target dimension (44px)'
241
+ };
242
+ }
243
+ }
244
+
245
+ // Motion
246
+ if (preset.motion) {
247
+ if (preset.motion.durationEntry) {
248
+ dtcg.duration.entry = {
249
+ $value: preset.motion.durationEntry,
250
+ $type: 'duration',
251
+ $description: 'Entry motion timing'
252
+ };
253
+ }
254
+ if (preset.motion.durationExit) {
255
+ dtcg.duration.exit = {
256
+ $value: preset.motion.durationExit,
257
+ $type: 'duration',
258
+ $description: 'Exit motion timing (asymmetric 0.65x)'
259
+ };
260
+ }
261
+ if (preset.motion.easingEntry) {
262
+ dtcg.cubicBezier.entry = {
263
+ $value: preset.motion.easingEntry,
264
+ $type: 'cubicBezier',
265
+ $description: 'Entry cubic-bezier timing function'
266
+ };
267
+ }
268
+ if (preset.motion.easingExit) {
269
+ dtcg.cubicBezier.exit = {
270
+ $value: preset.motion.easingExit,
271
+ $type: 'cubicBezier',
272
+ $description: 'Exit cubic-bezier timing function'
273
+ };
274
+ }
275
+ }
276
+
277
+ return JSON.stringify(dtcg, null, 2);
278
+ }
279
+
280
+ // Format 3: CSS Custom Properties Generator (:root { ... })
281
+ function toCssVariables(preset) {
282
+ const lines = ['/* Standard CSS Custom Properties */', '/* Generated by ME-DESIGN Token Engine */', ':root {'];
283
+
284
+ if (preset.color) {
285
+ Object.entries(preset.color).forEach(([k, v]) => {
286
+ if (typeof v === 'string') {
287
+ const cssKey = k.replace(/([A-Z])/g, '-$1').toLowerCase();
288
+ lines.push(` --color-${cssKey}: ${v};`);
289
+ } else if (typeof v === 'object') {
290
+ Object.entries(v).forEach(([subK, subV]) => {
291
+ lines.push(` --color-${k}-${subK}: ${subV};`);
292
+ });
293
+ }
294
+ });
295
+ }
296
+
297
+ if (preset.typography) {
298
+ if (preset.typography.sans) lines.push(` --font-sans: ${preset.typography.sans};`);
299
+ if (preset.typography.mono) lines.push(` --font-mono: ${preset.typography.mono};`);
300
+ if (preset.typography.uiLineHeight) lines.push(` --line-height-ui: ${preset.typography.uiLineHeight};`);
301
+ if (preset.typography.proseLineHeight) lines.push(` --line-height-prose: ${preset.typography.proseLineHeight};`);
302
+ }
303
+
304
+ if (preset.geometry) {
305
+ if (preset.geometry.radiusBase) lines.push(` --radius-base: ${preset.geometry.radiusBase};`);
306
+ if (preset.geometry.radiusOuter) lines.push(` --radius-outer: ${preset.geometry.radiusOuter};`);
307
+ if (preset.geometry.hitTargetMinTouch) lines.push(` --hit-target-min: ${preset.geometry.hitTargetMinTouch};`);
308
+ }
309
+
310
+ lines.push('}');
311
+ return lines.join('\n');
312
+ }
313
+
314
+ // Execution CLI Guard
315
+ if (require.main === module) {
316
+ const results = [];
317
+
318
+ selectedPresets.forEach(presetId => {
319
+ const jsonPath = path.join(presetsDir, presetId, 'preset.json');
320
+ const preset = JSON.parse(fs.readFileSync(jsonPath, 'utf8'));
321
+
322
+ const exportItem = {
323
+ preset: presetId,
324
+ name: preset.name,
325
+ outputs: {}
326
+ };
327
+
328
+ if (targetFormat === 'tailwind' || targetFormat === 'all') {
329
+ exportItem.outputs.tailwind = toTailwindV4Theme(preset);
330
+ }
331
+ if (targetFormat === 'dtcg' || targetFormat === 'all') {
332
+ exportItem.outputs.dtcgOklch = toDtcgTokens(preset, 'oklch');
333
+ exportItem.outputs.dtcgSrgb = toDtcgTokens(preset, 'srgb');
334
+ exportItem.outputs.dtcg = exportItem.outputs.dtcgOklch;
335
+ }
336
+ if (targetFormat === 'css' || targetFormat === 'all') {
337
+ exportItem.outputs.css = toCssVariables(preset);
338
+ }
339
+
340
+ results.push(exportItem);
341
+ });
342
+
343
+ // Output Handling
344
+ if (outDir) {
345
+ if (!fs.existsSync(outDir)) {
346
+ fs.mkdirSync(outDir, { recursive: true });
347
+ }
348
+
349
+ results.forEach(res => {
350
+ if (res.outputs.tailwind) {
351
+ fs.writeFileSync(path.join(outDir, `${res.preset}-theme.css`), res.outputs.tailwind, 'utf8');
352
+ }
353
+ if (res.outputs.dtcgOklch) {
354
+ fs.writeFileSync(path.join(outDir, `${res.preset}-tokens.oklch.json`), res.outputs.dtcgOklch, 'utf8');
355
+ fs.writeFileSync(path.join(outDir, `${res.preset}-tokens.dtcg.json`), res.outputs.dtcgOklch, 'utf8');
356
+ }
357
+ if (res.outputs.dtcgSrgb) {
358
+ fs.writeFileSync(path.join(outDir, `${res.preset}-tokens.srgb.json`), res.outputs.dtcgSrgb, 'utf8');
359
+ }
360
+ if (res.outputs.css) {
361
+ fs.writeFileSync(path.join(outDir, `${res.preset}-tokens.css`), res.outputs.css, 'utf8');
362
+ }
363
+ });
364
+
365
+ console.log(`Successfully exported tokens for [${selectedPresets.join(', ')}] into '${outDir}'.`);
366
+ } else {
367
+ // Stdout
368
+ results.forEach(res => {
369
+ console.log(`\n========================================`);
370
+ console.log(`PRESET: ${res.name} (${res.preset})`);
371
+ console.log(`========================================\n`);
372
+ if (res.outputs.tailwind) {
373
+ console.log(`--- [Tailwind v4 @theme] ---`);
374
+ console.log(res.outputs.tailwind);
375
+ console.log('');
376
+ }
377
+ if (res.outputs.dtcgOklch) {
378
+ console.log(`--- [W3C DTCG Format JSON (OKLCH Native)] ---`);
379
+ console.log(res.outputs.dtcgOklch);
380
+ console.log('');
381
+ }
382
+ if (res.outputs.dtcgSrgb) {
383
+ console.log(`--- [W3C DTCG Format JSON (sRGB Gamut-Mapped Hex)] ---`);
384
+ console.log(res.outputs.dtcgSrgb);
385
+ console.log('');
386
+ }
387
+ if (res.outputs.css) {
388
+ console.log(`--- [CSS Custom Properties] ---`);
389
+ console.log(res.outputs.css);
390
+ console.log('');
391
+ }
392
+ });
393
+ }
394
+ }
395
+
396
+ module.exports = {
397
+ oklchToHex,
398
+ oklchToLinearRgb,
399
+ inGamut,
400
+ toTailwindV4Theme,
401
+ toDtcgTokens,
402
+ toCssVariables
403
+ };