conductor-figma 3.0.3 → 3.3.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.
- package/README.md +138 -48
- package/figma-plugin/code.js +10 -10
- package/figma-plugin/manifest.json +2 -2
- package/package.json +1 -1
- package/src/design/composer.js +638 -0
- package/src/design/interpreter.js +295 -0
- package/src/server.js +37 -29
- package/src/tools/handlers.js +86 -0
- package/src/tools/registry.js +22 -0
|
@@ -0,0 +1,638 @@
|
|
|
1
|
+
// ═══════════════════════════════════════════
|
|
2
|
+
// CONDUCTOR v3.1 — Composition Engine
|
|
3
|
+
// ═══════════════════════════════════════════
|
|
4
|
+
// Generates rich, multi-layered Figma designs.
|
|
5
|
+
// Each section produces 30-60+ elements.
|
|
6
|
+
|
|
7
|
+
import { snap, semanticColors, componentDefaults, typeScale, SPACING, RADIUS, SHADOWS } from './intelligence.js'
|
|
8
|
+
|
|
9
|
+
// ─── Sequence runner ───
|
|
10
|
+
async function runSequence(bridge, commands) {
|
|
11
|
+
var results = []
|
|
12
|
+
for (var i = 0; i < commands.length; i++) {
|
|
13
|
+
var cmd = commands[i]
|
|
14
|
+
var data = {}
|
|
15
|
+
var src = cmd.data
|
|
16
|
+
for (var k in src) {
|
|
17
|
+
if (src.hasOwnProperty(k)) {
|
|
18
|
+
var v = src[k]
|
|
19
|
+
if (typeof v === 'string' && v.charAt(0) === '$') {
|
|
20
|
+
var refIdx = parseInt(v.replace('$','').replace('.id',''))
|
|
21
|
+
if (results[refIdx] && results[refIdx].id) v = results[refIdx].id
|
|
22
|
+
}
|
|
23
|
+
data[k] = v
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
var result = await bridge.send(cmd.type, data)
|
|
28
|
+
results.push(result)
|
|
29
|
+
} catch (e) {
|
|
30
|
+
results.push({ id: null, error: e.message })
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return results
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// ─── Shorthand builders ───
|
|
37
|
+
function F(name, opts) { opts.name = name; opts.direction = opts.direction || 'VERTICAL'; return { type:'create_frame', data:opts } }
|
|
38
|
+
function H(name, opts) { opts.direction = 'HORIZONTAL'; return F(name, opts) }
|
|
39
|
+
function T(text, opts) { opts.text = text; if (!opts.fontName) opts.fontName = { family:'Inter', style: opts._w || 'Regular' }; delete opts._w; return { type:'create_text', data:opts } }
|
|
40
|
+
function R(name, opts) { opts.name = name; return { type:'create_rectangle', data:opts } }
|
|
41
|
+
function $(idx) { return '$' + idx + '.id' }
|
|
42
|
+
|
|
43
|
+
// ═══════════════════════════════════════════
|
|
44
|
+
// NAVIGATION
|
|
45
|
+
// ═══════════════════════════════════════════
|
|
46
|
+
function composeNav(content, colors, brand, W) {
|
|
47
|
+
var c = [], brandName = (content && content.brand) || 'acme'
|
|
48
|
+
var navItems = (content && content.navItems) || ['Features','Pricing','Docs','Blog']
|
|
49
|
+
|
|
50
|
+
// 0: Nav bar
|
|
51
|
+
c.push(H('Navigation', { width:W, height:64, paddingLeft:40, paddingRight:40, paddingTop:0, paddingBottom:0, gap:0, fill:colors.bg, counterAxisAlignItems:'CENTER' }))
|
|
52
|
+
// 1: Logo mark
|
|
53
|
+
c.push(H('Logo Mark', { parentId:$(0), width:28, height:28, fill:brand, cornerRadius:7, primaryAxisAlignItems:'CENTER', counterAxisAlignItems:'CENTER' }))
|
|
54
|
+
// 2: Logo letter
|
|
55
|
+
c.push(T(brandName.charAt(0).toUpperCase(), { parentId:$(1), fontSize:14, _w:'Bold', color:'#ffffff' }))
|
|
56
|
+
// 3: Brand name
|
|
57
|
+
c.push(T(brandName, { parentId:$(0), fontSize:15, _w:'Semi Bold', color:colors.text1 }))
|
|
58
|
+
// 4: Spacer
|
|
59
|
+
c.push(F('_spacer', { parentId:$(0), width:1, height:1, fill:colors.bg, primaryAxisSizingMode:'FILL' }))
|
|
60
|
+
// 5: Nav links
|
|
61
|
+
c.push(H('Nav Links', { parentId:$(0), gap:28, counterAxisAlignItems:'CENTER' }))
|
|
62
|
+
for (var i = 0; i < navItems.length; i++) {
|
|
63
|
+
c.push(T(navItems[i], { parentId:$(5), fontSize:14, _w:'Medium', color:colors.text3 }))
|
|
64
|
+
}
|
|
65
|
+
// CTA button
|
|
66
|
+
var btnIdx = c.length
|
|
67
|
+
c.push(H('Nav CTA', { parentId:$(0), height:36, paddingLeft:16, paddingRight:16, paddingTop:0, paddingBottom:0, fill:brand, cornerRadius:8, primaryAxisAlignItems:'CENTER', counterAxisAlignItems:'CENTER' }))
|
|
68
|
+
c.push(T('Get started', { parentId:$(btnIdx), fontSize:13, _w:'Semi Bold', color:'#ffffff' }))
|
|
69
|
+
// Divider
|
|
70
|
+
c.push(R('Nav Divider', { parentId:$(0), width:W, height:1, fill:colors.border }))
|
|
71
|
+
return c
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// ═══════════════════════════════════════════
|
|
75
|
+
// HERO
|
|
76
|
+
// ═══════════════════════════════════════════
|
|
77
|
+
function composeHero(content, colors, brand, W) {
|
|
78
|
+
var c = []
|
|
79
|
+
var title = (content && content.title) || 'Ship faster with\nless overhead'
|
|
80
|
+
var subtitle = (content && content.subtitle) || 'The modern platform for teams that move fast.\nEverything you need to build, deploy, and scale.'
|
|
81
|
+
var ctaText = (content && content.cta) || 'Start for free'
|
|
82
|
+
|
|
83
|
+
// 0: Hero section
|
|
84
|
+
c.push(F('Hero Section', { width:W, paddingTop:112, paddingBottom:96, paddingLeft:48, paddingRight:48, gap:28, fill:colors.bg, primaryAxisAlignItems:'CENTER', counterAxisAlignItems:'CENTER' }))
|
|
85
|
+
|
|
86
|
+
// 1: Overline badge
|
|
87
|
+
c.push(H('Badge', { parentId:$(0), paddingLeft:6, paddingRight:14, paddingTop:5, paddingBottom:5, gap:8, fill:colors.surface2, cornerRadius:20, counterAxisAlignItems:'CENTER' }))
|
|
88
|
+
// 2: Badge dot container
|
|
89
|
+
c.push(H('Badge Dot', { parentId:$(1), width:20, height:20, fill:colors.brand, cornerRadius:10, primaryAxisAlignItems:'CENTER', counterAxisAlignItems:'CENTER' }))
|
|
90
|
+
// 3: Dot inner (sparkle)
|
|
91
|
+
c.push(T('✦', { parentId:$(2), fontSize:9, color:'#ffffff' }))
|
|
92
|
+
// 4: Badge text
|
|
93
|
+
c.push(T('Introducing v3 — now with 201 tools', { parentId:$(1), fontSize:12, _w:'Medium', color:colors.text2 }))
|
|
94
|
+
|
|
95
|
+
// 5: Main heading
|
|
96
|
+
c.push(T(title, { parentId:$(0), fontSize:68, _w:'Bold', color:colors.text1, textAlignHorizontal:'CENTER', lineHeight:1.05 }))
|
|
97
|
+
|
|
98
|
+
// 6: Subtitle
|
|
99
|
+
c.push(T(subtitle, { parentId:$(0), fontSize:19, color:colors.text2, textAlignHorizontal:'CENTER', maxWidth:560 }))
|
|
100
|
+
|
|
101
|
+
// 7: Button row
|
|
102
|
+
c.push(H('Buttons', { parentId:$(0), gap:12, paddingTop:8 }))
|
|
103
|
+
// 8: Primary CTA
|
|
104
|
+
c.push(H('Primary CTA', { parentId:$(7), height:52, paddingLeft:28, paddingRight:28, paddingTop:0, paddingBottom:0, fill:brand, cornerRadius:12, primaryAxisAlignItems:'CENTER', counterAxisAlignItems:'CENTER' }))
|
|
105
|
+
// 9: Primary label
|
|
106
|
+
c.push(T(ctaText, { parentId:$(8), fontSize:16, _w:'Semi Bold', color:'#ffffff' }))
|
|
107
|
+
// 10: Secondary CTA
|
|
108
|
+
c.push(H('Secondary CTA', { parentId:$(7), height:52, paddingLeft:28, paddingRight:28, paddingTop:0, paddingBottom:0, fill:colors.surface, cornerRadius:12, primaryAxisAlignItems:'CENTER', counterAxisAlignItems:'CENTER' }))
|
|
109
|
+
// 11: Secondary label
|
|
110
|
+
c.push(T('See how it works →', { parentId:$(10), fontSize:16, _w:'Medium', color:colors.text2 }))
|
|
111
|
+
|
|
112
|
+
// 12: Social proof row
|
|
113
|
+
c.push(H('Social Proof', { parentId:$(0), gap:12, counterAxisAlignItems:'CENTER', paddingTop:12 }))
|
|
114
|
+
// 13: Avatar stack frame
|
|
115
|
+
c.push(H('Avatars', { parentId:$(12), gap:-8 }))
|
|
116
|
+
// 14-18: Five avatar circles
|
|
117
|
+
var avatarColors = [brand, '#10b981', '#f59e0b', '#ef4444', '#6366f1']
|
|
118
|
+
var avatarLetters = ['A','S','M','J','K']
|
|
119
|
+
for (var ai = 0; ai < 5; ai++) {
|
|
120
|
+
var avIdx = c.length
|
|
121
|
+
c.push(H('Avatar', { parentId:$(13), width:28, height:28, fill:avatarColors[ai], cornerRadius:14, primaryAxisAlignItems:'CENTER', counterAxisAlignItems:'CENTER' }))
|
|
122
|
+
c.push(T(avatarLetters[ai], { parentId:$(avIdx), fontSize:11, _w:'Semi Bold', color:'#ffffff' }))
|
|
123
|
+
}
|
|
124
|
+
// Stars
|
|
125
|
+
c.push(T('★★★★★', { parentId:$(12), fontSize:13, color:'#fbbf24' }))
|
|
126
|
+
// Proof text
|
|
127
|
+
c.push(T('Loved by 10,000+ teams', { parentId:$(12), fontSize:13, _w:'Medium', color:colors.text3 }))
|
|
128
|
+
|
|
129
|
+
return c
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// ═══════════════════════════════════════════
|
|
133
|
+
// STATS BAR
|
|
134
|
+
// ═══════════════════════════════════════════
|
|
135
|
+
function composeStats(content, colors, brand, W) {
|
|
136
|
+
var c = [], contentW = 1120
|
|
137
|
+
var stats = (content && content.stats) || [
|
|
138
|
+
{ value:'10,000+', label:'Teams worldwide' },
|
|
139
|
+
{ value:'99.9%', label:'Uptime SLA' },
|
|
140
|
+
{ value:'< 50ms', label:'Global latency' },
|
|
141
|
+
{ value:'4.9/5', label:'Customer rating' },
|
|
142
|
+
]
|
|
143
|
+
|
|
144
|
+
// 0: Stats bar
|
|
145
|
+
c.push(H('Stats Bar', { width:W, paddingTop:48, paddingBottom:48, paddingLeft:48, paddingRight:48, fill:colors.bg2, primaryAxisAlignItems:'CENTER' }))
|
|
146
|
+
// 1: Inner container
|
|
147
|
+
c.push(H('Stats Inner', { parentId:$(0), width:contentW }))
|
|
148
|
+
|
|
149
|
+
for (var si = 0; si < stats.length; si++) {
|
|
150
|
+
var sw = Math.floor(contentW / stats.length)
|
|
151
|
+
var sti = c.length
|
|
152
|
+
// Stat frame
|
|
153
|
+
c.push(F('Stat: ' + stats[si].label, { parentId:$(1), width:sw, paddingTop:16, paddingBottom:16, gap:4, counterAxisAlignItems:'CENTER' }))
|
|
154
|
+
// Value
|
|
155
|
+
c.push(T(stats[si].value, { parentId:$(sti), fontSize:36, _w:'Bold', color:colors.text1, textAlignHorizontal:'CENTER' }))
|
|
156
|
+
// Label
|
|
157
|
+
c.push(T(stats[si].label, { parentId:$(sti), fontSize:13, _w:'Medium', color:colors.text3, textAlignHorizontal:'CENTER' }))
|
|
158
|
+
// Vertical divider (except last)
|
|
159
|
+
if (si < stats.length - 1) {
|
|
160
|
+
c.push(R('Divider', { parentId:$(1), width:1, height:48, fill:colors.border }))
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return c
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// ═══════════════════════════════════════════
|
|
167
|
+
// FEATURES
|
|
168
|
+
// ═══════════════════════════════════════════
|
|
169
|
+
function composeFeatures(content, colors, brand, W) {
|
|
170
|
+
var c = [], contentW = 1120
|
|
171
|
+
var heading = (content && content.title) || 'Everything you need'
|
|
172
|
+
var sub = (content && content.subtitle) || 'Powerful features to help your team ship faster\nand with more confidence.'
|
|
173
|
+
var features = (content && content.features) || [
|
|
174
|
+
{ icon:'⚡', title:'Instant Deploy', desc:'Push to deploy in seconds. Zero config.\nAutomatic HTTPS, global CDN, and instant rollbacks.' },
|
|
175
|
+
{ icon:'📈', title:'Auto Scale', desc:'Scales to millions of requests automatically.\nPay only for what you use. No capacity planning.' },
|
|
176
|
+
{ icon:'🔒', title:'Enterprise Security', desc:'SOC 2 Type II compliant. End-to-end encryption.\nSSO, RBAC, and audit logs built in.' },
|
|
177
|
+
]
|
|
178
|
+
|
|
179
|
+
// 0: Section
|
|
180
|
+
c.push(F('Features Section', { width:W, paddingTop:96, paddingBottom:96, paddingLeft:48, paddingRight:48, gap:56, fill:colors.bg, counterAxisAlignItems:'CENTER' }))
|
|
181
|
+
|
|
182
|
+
// 1: Header group
|
|
183
|
+
c.push(F('Features Header', { parentId:$(0), gap:12, counterAxisAlignItems:'CENTER' }))
|
|
184
|
+
// 2: Overline
|
|
185
|
+
c.push(T('FEATURES', { parentId:$(1), fontSize:11, _w:'Semi Bold', color:brand, letterSpacing:2.5, textAlignHorizontal:'CENTER' }))
|
|
186
|
+
// 3: Heading
|
|
187
|
+
c.push(T(heading, { parentId:$(1), fontSize:44, _w:'Bold', color:colors.text1, textAlignHorizontal:'CENTER' }))
|
|
188
|
+
// 4: Subtitle
|
|
189
|
+
c.push(T(sub, { parentId:$(1), fontSize:18, color:colors.text2, textAlignHorizontal:'CENTER' }))
|
|
190
|
+
|
|
191
|
+
// 5: Card row
|
|
192
|
+
c.push(H('Feature Cards', { parentId:$(0), width:contentW, gap:20 }))
|
|
193
|
+
|
|
194
|
+
for (var fi = 0; fi < features.length; fi++) {
|
|
195
|
+
var f = features[fi]
|
|
196
|
+
var cw = Math.floor((contentW - (features.length - 1) * 20) / features.length)
|
|
197
|
+
var ci = c.length
|
|
198
|
+
|
|
199
|
+
// Card
|
|
200
|
+
c.push(F(f.title, { parentId:$(5), width:cw, paddingTop:32, paddingBottom:32, paddingLeft:28, paddingRight:28, gap:16, fill:colors.surface, cornerRadius:16 }))
|
|
201
|
+
|
|
202
|
+
// Icon circle
|
|
203
|
+
var iconI = c.length
|
|
204
|
+
c.push(H('Icon BG', { parentId:$(ci), width:48, height:48, fill:colors.surface3, cornerRadius:12, primaryAxisAlignItems:'CENTER', counterAxisAlignItems:'CENTER' }))
|
|
205
|
+
c.push(T(f.icon, { parentId:$(iconI), fontSize:22 }))
|
|
206
|
+
|
|
207
|
+
// Title
|
|
208
|
+
c.push(T(f.title, { parentId:$(ci), fontSize:20, _w:'Semi Bold', color:colors.text1 }))
|
|
209
|
+
|
|
210
|
+
// Description
|
|
211
|
+
c.push(T(f.desc, { parentId:$(ci), fontSize:14, color:colors.text2, lineHeight:1.6 }))
|
|
212
|
+
|
|
213
|
+
// Divider inside card
|
|
214
|
+
c.push(R('Card Divider', { parentId:$(ci), width:cw - 56, height:1, fill:colors.border }))
|
|
215
|
+
|
|
216
|
+
// Learn more link
|
|
217
|
+
c.push(T('Learn more →', { parentId:$(ci), fontSize:13, _w:'Medium', color:brand }))
|
|
218
|
+
}
|
|
219
|
+
return c
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// ═══════════════════════════════════════════
|
|
223
|
+
// TESTIMONIALS
|
|
224
|
+
// ═══════════════════════════════════════════
|
|
225
|
+
function composeTestimonials(content, colors, brand, W) {
|
|
226
|
+
var c = [], contentW = 1120
|
|
227
|
+
var testimonials = (content && content.testimonials) || [
|
|
228
|
+
{ quote:'This product transformed how our team works. The speed and reliability are unmatched.', author:'Sarah Chen', role:'CTO, TechCorp', initial:'S' },
|
|
229
|
+
{ quote:'Best tool we adopted this year. Our deployment time dropped by 80%.', author:'Marcus Rivera', role:'VP Engineering, ScaleUp', initial:'M' },
|
|
230
|
+
{ quote:'Finally something that actually understands what good design looks like.', author:'Aria Kim', role:'Design Lead, Craft', initial:'A' },
|
|
231
|
+
]
|
|
232
|
+
|
|
233
|
+
// 0: Section
|
|
234
|
+
c.push(F('Testimonials', { width:W, paddingTop:96, paddingBottom:96, paddingLeft:48, paddingRight:48, gap:56, fill:colors.bg2, counterAxisAlignItems:'CENTER' }))
|
|
235
|
+
// 1: Header
|
|
236
|
+
c.push(F('Testimonials Header', { parentId:$(0), gap:12, counterAxisAlignItems:'CENTER' }))
|
|
237
|
+
c.push(T('TESTIMONIALS', { parentId:$(1), fontSize:11, _w:'Semi Bold', color:brand, letterSpacing:2.5 }))
|
|
238
|
+
c.push(T('Trusted by the best teams', { parentId:$(1), fontSize:44, _w:'Bold', color:colors.text1, textAlignHorizontal:'CENTER' }))
|
|
239
|
+
|
|
240
|
+
// Card row
|
|
241
|
+
var rowIdx = c.length
|
|
242
|
+
c.push(H('Testimonial Cards', { parentId:$(0), width:contentW, gap:16 }))
|
|
243
|
+
|
|
244
|
+
for (var ti = 0; ti < testimonials.length; ti++) {
|
|
245
|
+
var t = testimonials[ti]
|
|
246
|
+
var tw = Math.floor((contentW - (testimonials.length - 1) * 16) / testimonials.length)
|
|
247
|
+
var tidx = c.length
|
|
248
|
+
|
|
249
|
+
// Card
|
|
250
|
+
c.push(F('Testimonial', { parentId:$(rowIdx), width:tw, paddingTop:28, paddingBottom:28, paddingLeft:24, paddingRight:24, gap:16, fill:colors.surface, cornerRadius:16 }))
|
|
251
|
+
|
|
252
|
+
// Stars
|
|
253
|
+
c.push(T('★★★★★', { parentId:$(tidx), fontSize:14, color:'#fbbf24' }))
|
|
254
|
+
|
|
255
|
+
// Quote
|
|
256
|
+
c.push(T('"' + t.quote + '"', { parentId:$(tidx), fontSize:15, color:colors.text1, lineHeight:1.6 }))
|
|
257
|
+
|
|
258
|
+
// Divider
|
|
259
|
+
c.push(R('Divider', { parentId:$(tidx), width:tw - 48, height:1, fill:colors.border }))
|
|
260
|
+
|
|
261
|
+
// Author row
|
|
262
|
+
var authIdx = c.length
|
|
263
|
+
c.push(H('Author', { parentId:$(tidx), gap:10, counterAxisAlignItems:'CENTER' }))
|
|
264
|
+
|
|
265
|
+
// Avatar
|
|
266
|
+
var avIdx = c.length
|
|
267
|
+
c.push(H('Avatar', { parentId:$(authIdx), width:36, height:36, fill:brand, cornerRadius:18, primaryAxisAlignItems:'CENTER', counterAxisAlignItems:'CENTER' }))
|
|
268
|
+
c.push(T(t.initial, { parentId:$(avIdx), fontSize:14, _w:'Semi Bold', color:'#ffffff' }))
|
|
269
|
+
|
|
270
|
+
// Author info
|
|
271
|
+
var infoIdx = c.length
|
|
272
|
+
c.push(F('Author Info', { parentId:$(authIdx), gap:2 }))
|
|
273
|
+
c.push(T(t.author, { parentId:$(infoIdx), fontSize:14, _w:'Semi Bold', color:colors.text1 }))
|
|
274
|
+
c.push(T(t.role, { parentId:$(infoIdx), fontSize:12, color:colors.text3 }))
|
|
275
|
+
}
|
|
276
|
+
return c
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// ═══════════════════════════════════════════
|
|
280
|
+
// PRICING
|
|
281
|
+
// ═══════════════════════════════════════════
|
|
282
|
+
function composePricing(content, colors, brand, W) {
|
|
283
|
+
var c = [], contentW = 1080
|
|
284
|
+
var tiers = (content && content.tiers) || [
|
|
285
|
+
{ name:'Starter', price:'$0', period:'/mo', desc:'For side projects and experiments.', features:['1 project','1,000 API calls/day','Community support','Basic analytics'], cta:'Start free', hl:false },
|
|
286
|
+
{ name:'Pro', price:'$29', period:'/mo', desc:'For growing teams that need more.', features:['Unlimited projects','100,000 API calls/day','Priority support','Advanced analytics','Team collaboration','Custom domains','Webhooks'], cta:'Start free trial', hl:true },
|
|
287
|
+
{ name:'Enterprise', price:'Custom', period:'', desc:'For organizations with advanced needs.', features:['Everything in Pro','Unlimited API calls','Dedicated support','SSO & SAML','99.99% SLA','Custom integrations','On-premise option','Audit logs'], cta:'Contact sales', hl:false },
|
|
288
|
+
]
|
|
289
|
+
|
|
290
|
+
// 0: Section
|
|
291
|
+
c.push(F('Pricing Section', { width:W, paddingTop:96, paddingBottom:96, paddingLeft:48, paddingRight:48, gap:56, fill:colors.bg, counterAxisAlignItems:'CENTER' }))
|
|
292
|
+
// Header
|
|
293
|
+
c.push(F('Pricing Header', { parentId:$(0), gap:12, counterAxisAlignItems:'CENTER' }))
|
|
294
|
+
c.push(T('PRICING', { parentId:$(1), fontSize:11, _w:'Semi Bold', color:brand, letterSpacing:2.5 }))
|
|
295
|
+
c.push(T('Simple, transparent pricing', { parentId:$(1), fontSize:44, _w:'Bold', color:colors.text1, textAlignHorizontal:'CENTER' }))
|
|
296
|
+
c.push(T('No hidden fees. Start free, scale as you grow.', { parentId:$(1), fontSize:18, color:colors.text2, textAlignHorizontal:'CENTER' }))
|
|
297
|
+
|
|
298
|
+
// Tier row
|
|
299
|
+
var rowIdx = c.length
|
|
300
|
+
c.push(H('Tiers', { parentId:$(0), width:contentW, gap:16, counterAxisAlignItems:'STRETCH' }))
|
|
301
|
+
|
|
302
|
+
for (var ti = 0; ti < tiers.length; ti++) {
|
|
303
|
+
var t = tiers[ti]
|
|
304
|
+
var tw = Math.floor((contentW - (tiers.length - 1) * 16) / tiers.length)
|
|
305
|
+
var isHl = t.hl
|
|
306
|
+
var tidx = c.length
|
|
307
|
+
|
|
308
|
+
// Card
|
|
309
|
+
c.push(F(t.name, { parentId:$(rowIdx), width:tw, paddingTop:32, paddingBottom:32, paddingLeft:28, paddingRight:28, gap:16, fill:isHl ? colors.surface2 : colors.surface, cornerRadius:16 }))
|
|
310
|
+
|
|
311
|
+
// Popular badge
|
|
312
|
+
if (isHl) {
|
|
313
|
+
var bidx = c.length
|
|
314
|
+
c.push(H('Popular', { parentId:$(tidx), paddingLeft:10, paddingRight:10, paddingTop:4, paddingBottom:4, fill:brand, cornerRadius:6, primaryAxisAlignItems:'CENTER', counterAxisAlignItems:'CENTER' }))
|
|
315
|
+
c.push(T('MOST POPULAR', { parentId:$(bidx), fontSize:9, _w:'Bold', color:'#ffffff' }))
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// Name
|
|
319
|
+
c.push(T(t.name, { parentId:$(tidx), fontSize:22, _w:'Semi Bold', color:colors.text1 }))
|
|
320
|
+
|
|
321
|
+
// Price row
|
|
322
|
+
var pidx = c.length
|
|
323
|
+
c.push(H('Price', { parentId:$(tidx), gap:4, counterAxisAlignItems:'BASELINE' }))
|
|
324
|
+
c.push(T(t.price, { parentId:$(pidx), fontSize:44, _w:'Bold', color:colors.text1 }))
|
|
325
|
+
if (t.period) {
|
|
326
|
+
c.push(T(t.period, { parentId:$(pidx), fontSize:16, color:colors.text3 }))
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// Description
|
|
330
|
+
c.push(T(t.desc, { parentId:$(tidx), fontSize:14, color:colors.text2 }))
|
|
331
|
+
|
|
332
|
+
// Divider
|
|
333
|
+
c.push(R('Divider', { parentId:$(tidx), width:tw - 56, height:1, fill:colors.border }))
|
|
334
|
+
|
|
335
|
+
// Features list
|
|
336
|
+
var flidx = c.length
|
|
337
|
+
c.push(F('Features', { parentId:$(tidx), gap:10 }))
|
|
338
|
+
for (var fi = 0; fi < t.features.length; fi++) {
|
|
339
|
+
var flrow = c.length
|
|
340
|
+
c.push(H('Feature', { parentId:$(flidx), gap:8, counterAxisAlignItems:'CENTER' }))
|
|
341
|
+
// Checkmark circle
|
|
342
|
+
var chkIdx = c.length
|
|
343
|
+
c.push(H('Check', { parentId:$(flrow), width:18, height:18, fill:isHl ? brand : colors.surface3, cornerRadius:9, primaryAxisAlignItems:'CENTER', counterAxisAlignItems:'CENTER' }))
|
|
344
|
+
c.push(T('✓', { parentId:$(chkIdx), fontSize:10, _w:'Bold', color:isHl ? '#ffffff' : colors.text2 }))
|
|
345
|
+
c.push(T(t.features[fi], { parentId:$(flrow), fontSize:13, color:colors.text2 }))
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// Spacer to push button to bottom
|
|
349
|
+
c.push(F('_grow', { parentId:$(tidx), width:1, height:1, primaryAxisSizingMode:'FILL' }))
|
|
350
|
+
|
|
351
|
+
// CTA button
|
|
352
|
+
var btIdx = c.length
|
|
353
|
+
c.push(H(t.cta, { parentId:$(tidx), height:48, paddingLeft:24, paddingRight:24, paddingTop:0, paddingBottom:0, fill:isHl ? brand : 'transparent', cornerRadius:10, primaryAxisAlignItems:'CENTER', counterAxisAlignItems:'CENTER', primaryAxisSizingMode:'FILL' }))
|
|
354
|
+
c.push(T(t.cta, { parentId:$(btIdx), fontSize:15, _w:'Semi Bold', color:isHl ? '#ffffff' : brand }))
|
|
355
|
+
}
|
|
356
|
+
return c
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// ═══════════════════════════════════════════
|
|
360
|
+
// CTA SECTION
|
|
361
|
+
// ═══════════════════════════════════════════
|
|
362
|
+
function composeCTA(content, colors, brand, W) {
|
|
363
|
+
var c = [], contentW = 1120
|
|
364
|
+
var title = (content && content.ctaTitle) || 'Ready to get started?'
|
|
365
|
+
var sub = (content && content.ctaSub) || 'Join thousands of teams already shipping faster.\nNo credit card required.'
|
|
366
|
+
var btnText = (content && content.cta) || 'Start for free'
|
|
367
|
+
|
|
368
|
+
// 0: Section bg
|
|
369
|
+
c.push(F('CTA Section', { width:W, paddingTop:96, paddingBottom:96, paddingLeft:48, paddingRight:48, fill:colors.bg2, counterAxisAlignItems:'CENTER' }))
|
|
370
|
+
// 1: CTA Card
|
|
371
|
+
c.push(F('CTA Card', { parentId:$(0), width:contentW, paddingTop:72, paddingBottom:72, paddingLeft:48, paddingRight:48, gap:24, fill:colors.surface, cornerRadius:24, primaryAxisAlignItems:'CENTER', counterAxisAlignItems:'CENTER' }))
|
|
372
|
+
// 2: Heading
|
|
373
|
+
c.push(T(title, { parentId:$(1), fontSize:44, _w:'Bold', color:colors.text1, textAlignHorizontal:'CENTER' }))
|
|
374
|
+
// 3: Subtitle
|
|
375
|
+
c.push(T(sub, { parentId:$(1), fontSize:18, color:colors.text2, textAlignHorizontal:'CENTER' }))
|
|
376
|
+
// 4: Button row
|
|
377
|
+
c.push(H('CTA Buttons', { parentId:$(1), gap:12, paddingTop:8 }))
|
|
378
|
+
// 5: Primary
|
|
379
|
+
c.push(H('CTA Primary', { parentId:$(4), height:56, paddingLeft:32, paddingRight:32, paddingTop:0, paddingBottom:0, fill:brand, cornerRadius:12, primaryAxisAlignItems:'CENTER', counterAxisAlignItems:'CENTER' }))
|
|
380
|
+
c.push(T(btnText, { parentId:$(5), fontSize:17, _w:'Semi Bold', color:'#ffffff' }))
|
|
381
|
+
// 7: Secondary
|
|
382
|
+
c.push(H('CTA Secondary', { parentId:$(4), height:56, paddingLeft:32, paddingRight:32, paddingTop:0, paddingBottom:0, fill:colors.surface2, cornerRadius:12, primaryAxisAlignItems:'CENTER', counterAxisAlignItems:'CENTER' }))
|
|
383
|
+
c.push(T('Talk to sales →', { parentId:$(7), fontSize:17, _w:'Medium', color:colors.text2 }))
|
|
384
|
+
|
|
385
|
+
return c
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// ═══════════════════════════════════════════
|
|
389
|
+
// FOOTER
|
|
390
|
+
// ═══════════════════════════════════════════
|
|
391
|
+
function composeFooter(content, colors, brand, W) {
|
|
392
|
+
var c = [], brandName = (content && content.brand) || 'acme'
|
|
393
|
+
var cols = [
|
|
394
|
+
{ title:'Product', links:['Features','Pricing','Docs','Changelog'] },
|
|
395
|
+
{ title:'Company', links:['About','Blog','Careers','Press'] },
|
|
396
|
+
{ title:'Legal', links:['Terms','Privacy','License'] },
|
|
397
|
+
]
|
|
398
|
+
|
|
399
|
+
// 0: Footer top divider
|
|
400
|
+
c.push(R('Footer Divider', { width:W, height:1, fill:colors.border }))
|
|
401
|
+
// 1: Footer frame
|
|
402
|
+
c.push(F('Footer', { width:W, paddingTop:56, paddingBottom:40, paddingLeft:48, paddingRight:48, gap:40, fill:colors.bg }))
|
|
403
|
+
|
|
404
|
+
// 2: Footer columns row
|
|
405
|
+
c.push(H('Footer Columns', { parentId:$(1), gap:0 }))
|
|
406
|
+
|
|
407
|
+
// 3: Brand column (wider)
|
|
408
|
+
c.push(F('Brand Column', { parentId:$(2), width:360, gap:12 }))
|
|
409
|
+
// 4: Brand row
|
|
410
|
+
c.push(H('Brand', { parentId:$(3), gap:8, counterAxisAlignItems:'CENTER' }))
|
|
411
|
+
// Logo mark
|
|
412
|
+
var lmIdx = c.length
|
|
413
|
+
c.push(H('Logo', { parentId:$(4), width:22, height:22, fill:brand, cornerRadius:5, primaryAxisAlignItems:'CENTER', counterAxisAlignItems:'CENTER' }))
|
|
414
|
+
c.push(T(brandName.charAt(0).toUpperCase(), { parentId:$(lmIdx), fontSize:11, _w:'Bold', color:'#ffffff' }))
|
|
415
|
+
c.push(T(brandName, { parentId:$(4), fontSize:14, _w:'Semi Bold', color:colors.text1 }))
|
|
416
|
+
// Description
|
|
417
|
+
c.push(T('Design-intelligent tools for modern teams.\nBuilt with care, shipped with confidence.', { parentId:$(3), fontSize:13, color:colors.text3, lineHeight:1.6 }))
|
|
418
|
+
|
|
419
|
+
// Link columns
|
|
420
|
+
for (var ci2 = 0; ci2 < cols.length; ci2++) {
|
|
421
|
+
var col = cols[ci2]
|
|
422
|
+
var colIdx = c.length
|
|
423
|
+
c.push(F(col.title, { parentId:$(2), width:160, gap:10 }))
|
|
424
|
+
c.push(T(col.title, { parentId:$(colIdx), fontSize:12, _w:'Semi Bold', color:colors.text1 }))
|
|
425
|
+
// Spacer
|
|
426
|
+
c.push(F('_gap', { parentId:$(colIdx), width:1, height:4 }))
|
|
427
|
+
for (var li = 0; li < col.links.length; li++) {
|
|
428
|
+
c.push(T(col.links[li], { parentId:$(colIdx), fontSize:13, color:colors.text3 }))
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
// Bottom bar
|
|
433
|
+
c.push(R('Bottom Divider', { parentId:$(1), width:W - 96, height:1, fill:colors.border }))
|
|
434
|
+
var botIdx = c.length
|
|
435
|
+
c.push(H('Bottom', { parentId:$(1), counterAxisAlignItems:'CENTER' }))
|
|
436
|
+
c.push(T('© 2025 ' + brandName + '. All rights reserved.', { parentId:$(botIdx), fontSize:12, color:colors.text3 }))
|
|
437
|
+
|
|
438
|
+
return c
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
// ═══════════════════════════════════════════
|
|
442
|
+
// DASHBOARD
|
|
443
|
+
// ═══════════════════════════════════════════
|
|
444
|
+
function composeDashboard(content, colors, brand, W) {
|
|
445
|
+
var c = [], sideW = 260
|
|
446
|
+
var metrics = (content && content.metrics) || [
|
|
447
|
+
{ label:'Total Revenue', value:'$48,290', change:'+12.5%', up:true },
|
|
448
|
+
{ label:'Active Users', value:'2,420', change:'+8.3%', up:true },
|
|
449
|
+
{ label:'Conversion', value:'3.24%', change:'-0.8%', up:false },
|
|
450
|
+
{ label:'Avg. Session', value:'4m 32s', change:'+15.2%', up:true },
|
|
451
|
+
]
|
|
452
|
+
var navItems = ['Overview','Analytics','Customers','Products','Settings']
|
|
453
|
+
|
|
454
|
+
// 0: Dashboard root
|
|
455
|
+
c.push(H('Dashboard', { width:W, height:900, fill:colors.bg, gap:0 }))
|
|
456
|
+
|
|
457
|
+
// 1: Sidebar
|
|
458
|
+
c.push(F('Sidebar', { parentId:$(0), width:sideW, height:900, paddingTop:20, paddingBottom:20, paddingLeft:16, paddingRight:16, gap:4, fill:colors.surface }))
|
|
459
|
+
|
|
460
|
+
// 2: Sidebar logo row
|
|
461
|
+
c.push(H('Sidebar Brand', { parentId:$(1), gap:8, counterAxisAlignItems:'CENTER', paddingLeft:8, paddingBottom:16 }))
|
|
462
|
+
var slmIdx = c.length
|
|
463
|
+
c.push(H('Logo', { parentId:$(2), width:24, height:24, fill:brand, cornerRadius:6, primaryAxisAlignItems:'CENTER', counterAxisAlignItems:'CENTER' }))
|
|
464
|
+
c.push(T('C', { parentId:$(slmIdx), fontSize:12, _w:'Bold', color:'#ffffff' }))
|
|
465
|
+
c.push(T('Conductor', { parentId:$(2), fontSize:14, _w:'Semi Bold', color:colors.text1 }))
|
|
466
|
+
|
|
467
|
+
// Nav items
|
|
468
|
+
for (var ni = 0; ni < navItems.length; ni++) {
|
|
469
|
+
var isActive = ni === 0
|
|
470
|
+
var niIdx = c.length
|
|
471
|
+
c.push(H(navItems[ni], { parentId:$(1), height:36, paddingLeft:10, paddingRight:10, paddingTop:0, paddingBottom:0, gap:8, cornerRadius:8, fill:isActive ? colors.surface3 : 'transparent', counterAxisAlignItems:'CENTER', primaryAxisSizingMode:'FILL' }))
|
|
472
|
+
// Dot for active
|
|
473
|
+
if (isActive) {
|
|
474
|
+
c.push(H('Active Dot', { parentId:$(niIdx), width:6, height:6, fill:brand, cornerRadius:3 }))
|
|
475
|
+
}
|
|
476
|
+
c.push(T(navItems[ni], { parentId:$(niIdx), fontSize:13, _w:isActive ? 'Medium' : 'Regular', color:isActive ? colors.text1 : colors.text3 }))
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
// Sidebar divider
|
|
480
|
+
c.push(R('Sidebar Divider', { parentId:$(0), width:1, height:900, fill:colors.border }))
|
|
481
|
+
|
|
482
|
+
// Main area
|
|
483
|
+
var mainIdx = c.length
|
|
484
|
+
c.push(F('Main', { parentId:$(0), height:900, paddingTop:28, paddingBottom:28, paddingLeft:32, paddingRight:32, gap:24, fill:colors.bg, primaryAxisSizingMode:'FILL' }))
|
|
485
|
+
|
|
486
|
+
// Header row
|
|
487
|
+
var hdrIdx = c.length
|
|
488
|
+
c.push(H('Header', { parentId:$(mainIdx), counterAxisAlignItems:'CENTER' }))
|
|
489
|
+
c.push(T('Overview', { parentId:$(hdrIdx), fontSize:24, _w:'Bold', color:colors.text1 }))
|
|
490
|
+
c.push(F('_spacer', { parentId:$(hdrIdx), width:1, height:1, primaryAxisSizingMode:'FILL' }))
|
|
491
|
+
var dlBtnIdx = c.length
|
|
492
|
+
c.push(H('Download', { parentId:$(hdrIdx), height:36, paddingLeft:14, paddingRight:14, paddingTop:0, paddingBottom:0, fill:colors.surface, cornerRadius:8, primaryAxisAlignItems:'CENTER', counterAxisAlignItems:'CENTER' }))
|
|
493
|
+
c.push(T('Export ↓', { parentId:$(dlBtnIdx), fontSize:12, _w:'Medium', color:colors.text2 }))
|
|
494
|
+
|
|
495
|
+
// Metrics row
|
|
496
|
+
var mRowIdx = c.length
|
|
497
|
+
c.push(H('Metrics', { parentId:$(mainIdx), gap:16 }))
|
|
498
|
+
|
|
499
|
+
for (var mi = 0; mi < metrics.length; mi++) {
|
|
500
|
+
var m = metrics[mi]
|
|
501
|
+
var mIdx = c.length
|
|
502
|
+
c.push(F(m.label, { parentId:$(mRowIdx), paddingTop:20, paddingBottom:20, paddingLeft:20, paddingRight:20, gap:8, fill:colors.surface, cornerRadius:12, primaryAxisSizingMode:'FILL' }))
|
|
503
|
+
c.push(T(m.label, { parentId:$(mIdx), fontSize:12, _w:'Medium', color:colors.text3 }))
|
|
504
|
+
c.push(T(m.value, { parentId:$(mIdx), fontSize:28, _w:'Bold', color:colors.text1 }))
|
|
505
|
+
// Change badge
|
|
506
|
+
var chgIdx = c.length
|
|
507
|
+
c.push(H('Change', { parentId:$(mIdx), paddingLeft:6, paddingRight:6, paddingTop:2, paddingBottom:2, fill:m.up ? 'rgba(74,222,128,0.1)' : 'rgba(248,113,113,0.1)', cornerRadius:4 }))
|
|
508
|
+
c.push(T(m.change, { parentId:$(chgIdx), fontSize:11, _w:'Semi Bold', color:m.up ? '#4ade80' : '#f87171' }))
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
// Chart area
|
|
512
|
+
var chartIdx = c.length
|
|
513
|
+
c.push(F('Chart Area', { parentId:$(mainIdx), paddingTop:24, paddingBottom:24, paddingLeft:24, paddingRight:24, gap:16, fill:colors.surface, cornerRadius:12, primaryAxisSizingMode:'FILL' }))
|
|
514
|
+
var chartHdrIdx = c.length
|
|
515
|
+
c.push(H('Chart Header', { parentId:$(chartIdx), counterAxisAlignItems:'CENTER' }))
|
|
516
|
+
c.push(T('Revenue Over Time', { parentId:$(chartHdrIdx), fontSize:16, _w:'Semi Bold', color:colors.text1 }))
|
|
517
|
+
c.push(F('_spacer', { parentId:$(chartHdrIdx), width:1, height:1, primaryAxisSizingMode:'FILL' }))
|
|
518
|
+
// Period pills
|
|
519
|
+
var pillsIdx = c.length
|
|
520
|
+
c.push(H('Period', { parentId:$(chartHdrIdx), gap:4 }))
|
|
521
|
+
var periods = ['7D','30D','90D','1Y']
|
|
522
|
+
for (var pi = 0; pi < periods.length; pi++) {
|
|
523
|
+
var pillIdx = c.length
|
|
524
|
+
c.push(H(periods[pi], { parentId:$(pillsIdx), height:28, paddingLeft:10, paddingRight:10, paddingTop:0, paddingBottom:0, fill:pi === 1 ? colors.surface3 : 'transparent', cornerRadius:6, primaryAxisAlignItems:'CENTER', counterAxisAlignItems:'CENTER' }))
|
|
525
|
+
c.push(T(periods[pi], { parentId:$(pillIdx), fontSize:11, _w:pi === 1 ? 'Medium' : 'Regular', color:pi === 1 ? colors.text1 : colors.text3 }))
|
|
526
|
+
}
|
|
527
|
+
// Chart placeholder
|
|
528
|
+
c.push(R('Chart', { parentId:$(chartIdx), width:800, height:220, fill:colors.surface2, cornerRadius:8 }))
|
|
529
|
+
|
|
530
|
+
return c
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
// ═══════════════════════════════════════════
|
|
534
|
+
// SMART COMPONENTS
|
|
535
|
+
// ═══════════════════════════════════════════
|
|
536
|
+
function composeSmartComponent(type, variant, label, brandColor, mode) {
|
|
537
|
+
var colors = semanticColors(brandColor || '#6366f1', mode || 'dark')
|
|
538
|
+
var brand = brandColor || colors.brand
|
|
539
|
+
var defs = componentDefaults(type, variant)
|
|
540
|
+
if (!defs) return null
|
|
541
|
+
var c = []
|
|
542
|
+
|
|
543
|
+
switch (type) {
|
|
544
|
+
case 'button': {
|
|
545
|
+
c.push(H((label || 'Button') + ' — ' + (variant || 'default'), { height:defs.h, paddingLeft:defs.px, paddingRight:defs.px, paddingTop:0, paddingBottom:0, fill:brand, cornerRadius:defs.radius, primaryAxisAlignItems:'CENTER', counterAxisAlignItems:'CENTER', gap:8 }))
|
|
546
|
+
c.push(T(label || 'Get started', { parentId:$(0), fontSize:defs.fontSize, _w:defs.fontWeight, color:'#ffffff' }))
|
|
547
|
+
break
|
|
548
|
+
}
|
|
549
|
+
case 'input': {
|
|
550
|
+
c.push(F('Input — ' + (variant || 'default'), { gap:6 }))
|
|
551
|
+
c.push(T(label || 'Email address', { parentId:$(0), fontSize:13, _w:'Medium', color:colors.text2 }))
|
|
552
|
+
c.push(H('Input Field', { parentId:$(0), height:defs.h, paddingLeft:defs.px, paddingRight:defs.px, paddingTop:0, paddingBottom:0, fill:colors.surface, cornerRadius:defs.radius, counterAxisAlignItems:'CENTER' }))
|
|
553
|
+
c.push(T('you@example.com', { parentId:$(2), fontSize:defs.fontSize, color:colors.text3 }))
|
|
554
|
+
break
|
|
555
|
+
}
|
|
556
|
+
case 'card': {
|
|
557
|
+
c.push(F(label || 'Card', { paddingTop:defs.py, paddingBottom:defs.py, paddingLeft:defs.px, paddingRight:defs.px, gap:defs.gap, fill:colors.surface, cornerRadius:defs.radius }))
|
|
558
|
+
var icIdx = c.length
|
|
559
|
+
c.push(H('Icon', { parentId:$(0), width:48, height:48, fill:colors.surface3, cornerRadius:12, primaryAxisAlignItems:'CENTER', counterAxisAlignItems:'CENTER' }))
|
|
560
|
+
c.push(T('⚡', { parentId:$(icIdx), fontSize:22 }))
|
|
561
|
+
c.push(T(label || 'Feature title', { parentId:$(0), fontSize:18, _w:'Semi Bold', color:colors.text1 }))
|
|
562
|
+
c.push(T('A short description of this feature and why it matters to your users.', { parentId:$(0), fontSize:14, color:colors.text2, lineHeight:1.6 }))
|
|
563
|
+
c.push(R('Divider', { parentId:$(0), width:200, height:1, fill:colors.border }))
|
|
564
|
+
c.push(T('Learn more →', { parentId:$(0), fontSize:13, _w:'Medium', color:brand }))
|
|
565
|
+
break
|
|
566
|
+
}
|
|
567
|
+
case 'modal': {
|
|
568
|
+
c.push(F('Modal Overlay', { width:1440, height:900, fill:'#00000080', primaryAxisAlignItems:'CENTER', counterAxisAlignItems:'CENTER' }))
|
|
569
|
+
c.push(F('Modal', { parentId:$(0), width:defs.maxW, paddingTop:defs.py, paddingBottom:defs.py, paddingLeft:defs.px, paddingRight:defs.px, gap:defs.gap, fill:colors.surface, cornerRadius:defs.radius }))
|
|
570
|
+
c.push(T(label || 'Confirm action', { parentId:$(1), fontSize:18, _w:'Semi Bold', color:colors.text1 }))
|
|
571
|
+
c.push(T('Are you sure you want to proceed? This action cannot be undone.', { parentId:$(1), fontSize:15, color:colors.text2 }))
|
|
572
|
+
c.push(R('Divider', { parentId:$(1), width:defs.maxW - defs.px * 2, height:1, fill:colors.border }))
|
|
573
|
+
c.push(H('Actions', { parentId:$(1), gap:8, primaryAxisAlignItems:'MAX' }))
|
|
574
|
+
c.push(H('Cancel', { parentId:$(5), height:40, paddingLeft:16, paddingRight:16, paddingTop:0, paddingBottom:0, fill:colors.surface2, cornerRadius:8, primaryAxisAlignItems:'CENTER', counterAxisAlignItems:'CENTER' }))
|
|
575
|
+
c.push(T('Cancel', { parentId:$(6), fontSize:14, _w:'Medium', color:colors.text2 }))
|
|
576
|
+
c.push(H('Confirm', { parentId:$(5), height:40, paddingLeft:16, paddingRight:16, paddingTop:0, paddingBottom:0, fill:brand, cornerRadius:8, primaryAxisAlignItems:'CENTER', counterAxisAlignItems:'CENTER' }))
|
|
577
|
+
c.push(T('Confirm', { parentId:$(8), fontSize:14, _w:'Semi Bold', color:'#ffffff' }))
|
|
578
|
+
break
|
|
579
|
+
}
|
|
580
|
+
case 'avatar': {
|
|
581
|
+
c.push(H('Avatar', { width:defs.size, height:defs.size, fill:brand, cornerRadius:defs.radius, primaryAxisAlignItems:'CENTER', counterAxisAlignItems:'CENTER' }))
|
|
582
|
+
c.push(T((label || 'A').charAt(0).toUpperCase(), { parentId:$(0), fontSize:defs.fontSize, _w:defs.fontWeight, color:'#ffffff' }))
|
|
583
|
+
break
|
|
584
|
+
}
|
|
585
|
+
case 'badge': {
|
|
586
|
+
c.push(H('Badge', { height:defs.h, paddingLeft:defs.px, paddingRight:defs.px, paddingTop:0, paddingBottom:0, fill:colors.surface2, cornerRadius:defs.radius, primaryAxisAlignItems:'CENTER', counterAxisAlignItems:'CENTER' }))
|
|
587
|
+
c.push(T(label || 'New', { parentId:$(0), fontSize:defs.fontSize, _w:defs.fontWeight, color:brand }))
|
|
588
|
+
break
|
|
589
|
+
}
|
|
590
|
+
default: {
|
|
591
|
+
c.push(F(type, { paddingTop:16, paddingBottom:16, paddingLeft:16, paddingRight:16, gap:8, fill:colors.surface, cornerRadius:8 }))
|
|
592
|
+
c.push(T(label || type, { parentId:$(0), fontSize:14, color:colors.text1 }))
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
return c
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
// ═══════════════════════════════════════════
|
|
599
|
+
// SECTION ROUTER
|
|
600
|
+
// ═══════════════════════════════════════════
|
|
601
|
+
function composeSection(type, content, brandColor, mode, width) {
|
|
602
|
+
var W = width || 1440
|
|
603
|
+
var colors = semanticColors(brandColor || '#6366f1', mode || 'dark')
|
|
604
|
+
var brand = brandColor || '#6366f1'
|
|
605
|
+
|
|
606
|
+
switch (type) {
|
|
607
|
+
case 'nav': return composeNav(content, colors, brand, W)
|
|
608
|
+
case 'hero': return composeHero(content, colors, brand, W)
|
|
609
|
+
case 'stats': return composeStats(content, colors, brand, W)
|
|
610
|
+
case 'features': return composeFeatures(content, colors, brand, W)
|
|
611
|
+
case 'testimonials': return composeTestimonials(content, colors, brand, W)
|
|
612
|
+
case 'pricing': return composePricing(content, colors, brand, W)
|
|
613
|
+
case 'cta': return composeCTA(content, colors, brand, W)
|
|
614
|
+
case 'footer': return composeFooter(content, colors, brand, W)
|
|
615
|
+
case 'dashboard': return composeDashboard(content, colors, brand, W)
|
|
616
|
+
default:
|
|
617
|
+
var c = []
|
|
618
|
+
c.push(F(type + ' Section', { width:W, paddingTop:96, paddingBottom:96, paddingLeft:48, paddingRight:48, gap:32, fill:colors.bg, counterAxisAlignItems:'CENTER' }))
|
|
619
|
+
c.push(T((content && content.title) || type, { parentId:$(0), fontSize:40, _w:'Bold', color:colors.text1, textAlignHorizontal:'CENTER' }))
|
|
620
|
+
return c
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
// ═══════════════════════════════════════════
|
|
625
|
+
// PAGE COMPOSER
|
|
626
|
+
// ═══════════════════════════════════════════
|
|
627
|
+
function composePage(type, content, brandColor, mode, width) {
|
|
628
|
+
var sections = []
|
|
629
|
+
switch (type) {
|
|
630
|
+
case 'landing': sections = ['nav','hero','stats','features','testimonials','cta','footer']; break
|
|
631
|
+
case 'pricing': sections = ['nav','pricing','cta','footer']; break
|
|
632
|
+
case 'dashboard': sections = ['dashboard']; break
|
|
633
|
+
default: sections = ['nav','hero','features','cta','footer']
|
|
634
|
+
}
|
|
635
|
+
return { sections:sections, content:content, brand:brandColor || '#6366f1', mode:mode || 'dark', width:width || 1440 }
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
export { runSequence, composeSmartComponent, composeSection, composePage }
|