@duongthiu/onex-core 0.1.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/THEME_API.md ADDED
@@ -0,0 +1,681 @@
1
+ # OneX Theme API Reference
2
+
3
+ **Version**: 1.0.0
4
+ **Package**: `@onex/core`
5
+ **Status**: Public API
6
+
7
+ ---
8
+
9
+ ## Overview
10
+
11
+ This document defines the **public API contract** for OneX theme developers. All types and interfaces marked with `@public` are stable and follow semantic versioning.
12
+
13
+ ### Stability Guarantee
14
+
15
+ - ✅ **Public API** (`@public` tag): Stable, semantic versioning applies
16
+ - ⚠️ **Internal API** (no tag): May change without notice, do not use
17
+
18
+ ### Breaking Change Policy
19
+
20
+ - **Major version** (2.0.0): Breaking changes to public API
21
+ - **Minor version** (1.1.0): New features, backward compatible
22
+ - **Patch version** (1.0.1): Bug fixes, backward compatible
23
+
24
+ ---
25
+
26
+ ## Public API
27
+
28
+ ### Core Types
29
+
30
+ All types are imported from `@onex/core`:
31
+
32
+ ```typescript
33
+ import type {
34
+ // Theme Contract
35
+ ThemeManifest,
36
+ ThemeModule,
37
+ ThemeConfig,
38
+
39
+ // Section Types
40
+ SectionComponentProps,
41
+ SectionInstance,
42
+ SectionSchema,
43
+ TemplateDefinition,
44
+
45
+ // Component Types
46
+ ComponentInstance,
47
+
48
+ // Block Types
49
+ BlockInstance,
50
+
51
+ // Validation
52
+ ValidationResult,
53
+ ValidationError,
54
+ ValidationWarning,
55
+ } from "@onex/core"
56
+ ```
57
+
58
+ ---
59
+
60
+ ## Theme Manifest
61
+
62
+ **Location**: `packages/core/src/types/theme.ts`
63
+ **Tag**: `@public`
64
+
65
+ The manifest is the primary contract between your theme and the OneX platform.
66
+
67
+ ### Interface
68
+
69
+ ```typescript
70
+ interface ThemeManifest {
71
+ /** Unique theme identifier (lowercase, kebab-case) */
72
+ id: string;
73
+
74
+ /** Human-readable theme name */
75
+ name: string;
76
+
77
+ /** Semantic version (e.g., "1.0.0") */
78
+ version: string;
79
+
80
+ /** Theme description */
81
+ description?: string;
82
+
83
+ /** Theme author information */
84
+ author: {
85
+ name: string;
86
+ email?: string;
87
+ url?: string;
88
+ };
89
+
90
+ /** OneX engine version compatibility (e.g., "^1.0.0") */
91
+ engine: string;
92
+
93
+ /** Required peer dependencies */
94
+ peerDependencies: {
95
+ react: string;
96
+ "react-dom": string;
97
+ "@onex/core"?: string;
98
+ };
99
+
100
+ /** Available sections in this theme */
101
+ sections: string[];
102
+
103
+ /** Theme configuration (colors, typography, etc.) */
104
+ config: ThemeConfig;
105
+
106
+ /** Entry points for the theme bundle */
107
+ exports: {
108
+ main: string;
109
+ types?: string;
110
+ };
111
+
112
+ /** Optional theme preview/screenshot */
113
+ preview?: {
114
+ thumbnail?: string;
115
+ screenshots?: string[];
116
+ };
117
+
118
+ /** Optional license information */
119
+ license?: string;
120
+
121
+ /** Optional homepage/repository */
122
+ repository?: string;
123
+
124
+ /** Optional tags for categorization */
125
+ tags?: string[];
126
+ }
127
+ ```
128
+
129
+ ### Example
130
+
131
+ ```typescript
132
+ export const manifest: ThemeManifest = {
133
+ id: "my-awesome-theme",
134
+ name: "My Awesome Theme",
135
+ version: "1.0.0",
136
+ description: "A beautiful, modern theme for e-commerce",
137
+ author: {
138
+ name: "Your Name",
139
+ email: "you@example.com",
140
+ url: "https://yoursite.com"
141
+ },
142
+ engine: "^1.0.0",
143
+ peerDependencies: {
144
+ react: "^19.0.0",
145
+ "react-dom": "^19.0.0",
146
+ "@onex/core": "^1.0.0"
147
+ },
148
+ sections: ["hero-default", "hero-minimal", "footer-default"],
149
+ config: themeConfig,
150
+ exports: {
151
+ main: "./dist/index.mjs",
152
+ types: "./dist/index.d.ts"
153
+ },
154
+ tags: ["e-commerce", "minimal", "modern"],
155
+ license: "MIT"
156
+ }
157
+ ```
158
+
159
+ ### Validation Rules
160
+
161
+ - `id`: Must be lowercase, kebab-case, 3-50 characters
162
+ - `version`: Must follow semver (e.g., "1.0.0")
163
+ - `engine`: Must be valid semver range (e.g., "^1.0.0", ">=1.0.0 <2.0.0")
164
+ - `sections`: Must match exported section component keys
165
+
166
+ ---
167
+
168
+ ## Theme Module
169
+
170
+ **Tag**: `@public`
171
+
172
+ The structure your theme bundle must export.
173
+
174
+ ### Interface
175
+
176
+ ```typescript
177
+ interface ThemeModule {
178
+ /** Theme manifest */
179
+ manifest: ThemeManifest;
180
+
181
+ /** Section components registry */
182
+ sections: Record<string, React.ComponentType<SectionComponentProps>>;
183
+
184
+ /** Theme configuration */
185
+ config: ThemeConfig;
186
+
187
+ /** Optional theme initialization function */
188
+ init?: () => void | Promise<void>;
189
+ }
190
+ ```
191
+
192
+ ### Example
193
+
194
+ ```typescript
195
+ import type { ThemeModule } from "@onex/core"
196
+ import { HeroDefault, HeroMinimal } from "./sections/hero"
197
+ import { FooterDefault } from "./sections/footer"
198
+
199
+ export const theme: ThemeModule = {
200
+ manifest,
201
+ config,
202
+ sections: {
203
+ "hero-default": HeroDefault,
204
+ "hero-minimal": HeroMinimal,
205
+ "footer-default": FooterDefault,
206
+ },
207
+ init: async () => {
208
+ console.log("Theme initialized")
209
+ }
210
+ }
211
+
212
+ export default theme
213
+ ```
214
+
215
+ ---
216
+
217
+ ## Section Component Props
218
+
219
+ **Location**: `packages/core/src/types/section.ts`
220
+ **Tag**: `@public`
221
+
222
+ Props passed to every section component.
223
+
224
+ ### Interface
225
+
226
+ ```typescript
227
+ interface SectionComponentProps {
228
+ /** Section instance data */
229
+ section: SectionInstance;
230
+
231
+ /** Section schema */
232
+ schema: SectionSchema;
233
+
234
+ /** Selected template definition */
235
+ template: TemplateDefinition;
236
+
237
+ /** Whether in edit mode */
238
+ isEditing?: boolean;
239
+
240
+ /** Optional data for sections (e.g., products, blog posts) */
241
+ data?: Record<string, unknown>;
242
+
243
+ /** Callback when settings change */
244
+ onSettingsChange?: (settings: Settings) => void;
245
+
246
+ /** Component management callbacks */
247
+ onComponentAdd?: (componentType: string) => void;
248
+ onComponentUpdate?: (componentId: string, updates: Partial<ComponentInstance>) => void;
249
+ onComponentRemove?: (componentId: string) => void;
250
+ onComponentReorder?: (componentIds: string[]) => void;
251
+ }
252
+ ```
253
+
254
+ ### Example Section Component
255
+
256
+ ```typescript
257
+ import type { SectionComponentProps } from "@onex/core"
258
+ import { ButtonComponent, Heading } from "@onex/core/client"
259
+
260
+ export function HeroMinimal({ section, isEditing }: SectionComponentProps) {
261
+ const { title, subtitle, ctaText, ctaUrl } = section.settings
262
+
263
+ return (
264
+ <section className="hero">
265
+ <Heading level={1}>{title}</Heading>
266
+ <p>{subtitle}</p>
267
+ <ButtonComponent href={ctaUrl}>{ctaText}</ButtonComponent>
268
+ </section>
269
+ )
270
+ }
271
+ ```
272
+
273
+ ---
274
+
275
+ ## Theme Configuration
276
+
277
+ **Location**: `packages/core/src/types/theme.ts`
278
+ **Tag**: `@public`
279
+
280
+ Design tokens for your theme.
281
+
282
+ ### Interface
283
+
284
+ ```typescript
285
+ interface ThemeConfig {
286
+ id: string;
287
+ name: string;
288
+ version: string;
289
+
290
+ colors: {
291
+ light: ColorPalette;
292
+ dark?: ColorPalette;
293
+ };
294
+
295
+ typography: Typography;
296
+ spacing: Spacing;
297
+ borderRadius: BorderRadius;
298
+ breakpoints: Breakpoints;
299
+
300
+ tokens?: DesignToken[];
301
+ customCss?: string;
302
+ }
303
+ ```
304
+
305
+ ### Example
306
+
307
+ ```typescript
308
+ export const config: ThemeConfig = {
309
+ id: "my-theme",
310
+ name: "My Theme",
311
+ version: "1.0.0",
312
+ colors: {
313
+ light: {
314
+ primary: "#3b82f6",
315
+ secondary: "#8b5cf6",
316
+ background: "#ffffff",
317
+ foreground: "#000000",
318
+ // ... other colors
319
+ }
320
+ },
321
+ typography: {
322
+ fontFamily: {
323
+ heading: "Inter, sans-serif",
324
+ body: "Inter, sans-serif",
325
+ mono: "Fira Code, monospace"
326
+ },
327
+ fontSize: {
328
+ xs: "0.75rem",
329
+ sm: "0.875rem",
330
+ base: "1rem",
331
+ lg: "1.125rem",
332
+ xl: "1.25rem",
333
+ "2xl": "1.5rem",
334
+ "3xl": "1.875rem",
335
+ "4xl": "2.25rem",
336
+ "5xl": "3rem"
337
+ },
338
+ // ... other typography settings
339
+ },
340
+ spacing: {
341
+ xs: "0.25rem",
342
+ sm: "0.5rem",
343
+ md: "1rem",
344
+ lg: "1.5rem",
345
+ xl: "2rem",
346
+ "2xl": "3rem",
347
+ "3xl": "4rem",
348
+ "4xl": "6rem"
349
+ },
350
+ borderRadius: {
351
+ none: "0",
352
+ sm: "0.125rem",
353
+ md: "0.375rem",
354
+ lg: "0.5rem",
355
+ xl: "0.75rem",
356
+ "2xl": "1rem",
357
+ full: "9999px"
358
+ },
359
+ breakpoints: {
360
+ sm: "640px",
361
+ md: "768px",
362
+ lg: "1024px",
363
+ xl: "1280px",
364
+ "2xl": "1536px"
365
+ }
366
+ }
367
+ ```
368
+
369
+ ---
370
+
371
+ ## UI Components
372
+
373
+ **Location**: `packages/core/src/components/`
374
+ **Tag**: `@public`
375
+
376
+ Pre-built UI components available for use in your sections.
377
+
378
+ ### Available Components
379
+
380
+ ```typescript
381
+ import {
382
+ // Layout
383
+ GridContainer,
384
+ FullWidthSection,
385
+ Container,
386
+ Grid,
387
+ Columns,
388
+
389
+ // Text
390
+ Heading,
391
+ Paragraph,
392
+ Quote,
393
+ Badge,
394
+
395
+ // Interactive
396
+ ButtonComponent,
397
+ Link,
398
+ Divider,
399
+ Spacer,
400
+
401
+ // Media
402
+ Image,
403
+ Icon,
404
+ Video,
405
+ Gallery,
406
+ Map,
407
+
408
+ // Forms
409
+ Input,
410
+ Textarea,
411
+ Checkbox,
412
+ Select,
413
+
414
+ // Advanced
415
+ Card,
416
+ Alert,
417
+ Accordion,
418
+ Tabs,
419
+ Rating,
420
+ Progress,
421
+ Timer,
422
+ Table,
423
+ Code
424
+ } from "@onex/core/client"
425
+ ```
426
+
427
+ ### Example Usage
428
+
429
+ ```typescript
430
+ import { Heading, ButtonComponent, Card } from "@onex/core/client"
431
+
432
+ export function MySection({ section }: SectionComponentProps) {
433
+ return (
434
+ <Card>
435
+ <Heading level={2}>Section Title</Heading>
436
+ <ButtonComponent href="/learn-more">Learn More</ButtonComponent>
437
+ </Card>
438
+ )
439
+ }
440
+ ```
441
+
442
+ ---
443
+
444
+ ## Utilities
445
+
446
+ **Location**: `packages/core/src/utils/`
447
+ **Tag**: `@public`
448
+
449
+ Utility functions for common tasks.
450
+
451
+ ### cn() - Class Name Merger
452
+
453
+ Combines Tailwind classes with proper precedence.
454
+
455
+ ```typescript
456
+ import { cn } from "@onex/core/client"
457
+
458
+ const className = cn(
459
+ "text-base",
460
+ "text-lg", // This wins (last one)
461
+ section.settings.customClass
462
+ )
463
+ ```
464
+
465
+ ### generateId() - UUID Generator
466
+
467
+ ```typescript
468
+ import { generateId } from "@onex/core/client"
469
+
470
+ const id = generateId() // "abc123-def456-..."
471
+ ```
472
+
473
+ ---
474
+
475
+ ## Validation
476
+
477
+ **Location**: `packages/core/src/types/theme.ts`
478
+ **Tag**: `@public`
479
+
480
+ Types for theme validation results.
481
+
482
+ ### Interface
483
+
484
+ ```typescript
485
+ interface ValidationResult {
486
+ valid: boolean;
487
+ errors?: ValidationError[];
488
+ warnings?: ValidationWarning[];
489
+ }
490
+
491
+ interface ValidationError {
492
+ code: string;
493
+ message: string;
494
+ path?: string;
495
+ }
496
+
497
+ interface ValidationWarning {
498
+ code: string;
499
+ message: string;
500
+ path?: string;
501
+ }
502
+ ```
503
+
504
+ ### Common Error Codes
505
+
506
+ - `MISSING_MANIFEST`: manifest.json not found
507
+ - `INVALID_MANIFEST`: Manifest schema validation failed
508
+ - `BUNDLE_TOO_LARGE`: ZIP exceeds size limit (10MB)
509
+ - `UNSAFE_EVAL`: eval() detected
510
+ - `UNSAFE_FUNCTION`: Function constructor detected
511
+ - `NODE_API`: Node.js API usage detected
512
+ - `INCOMPATIBLE_ENGINE`: Engine version mismatch
513
+
514
+ ---
515
+
516
+ ## Security Constraints
517
+
518
+ **v1.0.0**: Static validation + runtime error boundaries
519
+
520
+ ### Allowed
521
+
522
+ - ✅ Import from `@onex/core`, `@onex/core/client`
523
+ - ✅ Import from `react`, `react-dom`
524
+ - ✅ Standard JavaScript/TypeScript
525
+ - ✅ Tailwind CSS classes
526
+ - ✅ Fetch API for CDN resources only
527
+
528
+ ### Blocked
529
+
530
+ - ❌ `eval()` or `new Function()`
531
+ - ❌ Node.js APIs (`fs`, `path`, `child_process`, etc.)
532
+ - ❌ Dynamic imports except from CDN
533
+ - ❌ Inline `<script>` tags
534
+ - ❌ Bundle size > 1MB
535
+
536
+ ### Runtime Constraints
537
+
538
+ - ✅ Error boundaries catch render crashes
539
+ - ⚠️ No protection against: infinite loops, memory leaks, network abuse
540
+ - ⚠️ v2.0.0 will add iframe sandbox for stronger isolation
541
+
542
+ ---
543
+
544
+ ## Engine Version Compatibility
545
+
546
+ Themes must specify compatible `@onex/core` versions using semver ranges.
547
+
548
+ ### Examples
549
+
550
+ ```typescript
551
+ // Exact version
552
+ "engine": "1.0.0"
553
+
554
+ // Compatible with 1.x
555
+ "engine": "^1.0.0"
556
+
557
+ // Compatible with 1.2.0 or higher
558
+ "engine": ">=1.2.0"
559
+
560
+ // Compatible with 1.x but not 2.x
561
+ "engine": ">=1.0.0 <2.0.0"
562
+ ```
563
+
564
+ ### Runtime Enforcement
565
+
566
+ The platform will check compatibility before loading your theme:
567
+
568
+ ```typescript
569
+ if (!semver.satisfies(platformVersion, theme.manifest.engine)) {
570
+ throw new Error("Incompatible theme version")
571
+ }
572
+ ```
573
+
574
+ ---
575
+
576
+ ## Versioning Strategy
577
+
578
+ Follow semantic versioning for your theme:
579
+
580
+ - **Major** (2.0.0): Breaking changes to section APIs
581
+ - **Minor** (1.1.0): New sections or features
582
+ - **Patch** (1.0.1): Bug fixes
583
+
584
+ ### Example Changelog
585
+
586
+ ```
587
+ ## 1.1.0 (2026-02-01)
588
+ - Added: hero-split section variant
589
+ - Improved: footer responsive layout
590
+
591
+ ## 1.0.1 (2026-01-25)
592
+ - Fixed: button hover state
593
+ - Fixed: mobile menu alignment
594
+
595
+ ## 1.0.0 (2026-01-20)
596
+ - Initial release
597
+ ```
598
+
599
+ ---
600
+
601
+ ## Best Practices
602
+
603
+ ### 1. Use TypeScript
604
+
605
+ ```typescript
606
+ import type { SectionComponentProps, ThemeManifest } from "@onex/core"
607
+
608
+ export const manifest: ThemeManifest = { ... }
609
+ export function HeroSection(props: SectionComponentProps) { ... }
610
+ ```
611
+
612
+ ### 2. Export Named and Default
613
+
614
+ ```typescript
615
+ export const theme: ThemeModule = { ... }
616
+ export { manifest, config }
617
+ export default theme
618
+ ```
619
+
620
+ ### 3. Handle Edit Mode
621
+
622
+ ```typescript
623
+ export function MySection({ section, isEditing }: SectionComponentProps) {
624
+ return (
625
+ <div>
626
+ {isEditing && <div className="edit-overlay">Edit Mode</div>}
627
+ {/* Your content */}
628
+ </div>
629
+ )
630
+ }
631
+ ```
632
+
633
+ ### 4. Use Theme Config
634
+
635
+ ```typescript
636
+ export function MySection({ section }: SectionComponentProps) {
637
+ const bgColor = section.settings.backgroundColor || config.colors.light.primary
638
+
639
+ return <section style={{ backgroundColor: bgColor }}>...</section>
640
+ }
641
+ ```
642
+
643
+ ### 5. Bundle Optimization
644
+
645
+ ```javascript
646
+ // esbuild.config.js
647
+ module.exports = {
648
+ external: ["@onex/core", "@onex/core/client", "react", "react-dom"],
649
+ minify: true,
650
+ treeShaking: true
651
+ }
652
+ ```
653
+
654
+ ---
655
+
656
+ ## Migration Guide
657
+
658
+ ### From Internal Themes to Marketplace
659
+
660
+ If migrating an existing internal theme:
661
+
662
+ 1. **Create manifest.json** with theme metadata
663
+ 2. **Externalize @onex/core** in build config
664
+ 3. **Export ThemeModule** structure
665
+ 4. **Test engine compatibility** with platform
666
+ 5. **Validate with CLI**: `onex theme validate`
667
+ 6. **Upload**: `onex theme publish`
668
+
669
+ ---
670
+
671
+ ## Support
672
+
673
+ - **Documentation**: https://docs.onex.dev/themes
674
+ - **API Reference**: This document
675
+ - **CLI Help**: `onex theme --help`
676
+ - **Issues**: https://github.com/onex/themes/issues
677
+
678
+ ---
679
+
680
+ *Last Updated: 2026-01-23*
681
+ *API Version: 1.0.0*