@onexapis/cli 1.1.32 → 1.1.36

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.
@@ -24,7 +24,11 @@ import { initializeOnex } from "@onexapis/core";
24
24
  import * as coreHooksAll from "@onexapis/core/hooks";
25
25
  import * as coreInternal from "@onexapis/core/internal";
26
26
  import * as coreTypes from "@onexapis/core/types";
27
- import { CartProvider, FlyToCartProvider } from "@onexapis/core/contexts";
27
+ import {
28
+ CartProvider,
29
+ FlyToCartProvider,
30
+ PageDataProvider,
31
+ } from "@onexapis/core/contexts";
28
32
  import { LocaleProvider } from "@onexapis/core/contexts";
29
33
 
30
34
  // @onexapis/core/hooks is the single source of truth — no manual composition.
@@ -744,7 +748,9 @@ root.render(
744
748
  <LocaleProvider locale={_rootLocale as any}>
745
749
  <CartProvider>
746
750
  <FlyToCartProvider>
747
- <PreviewApp />
751
+ <PageDataProvider data={{}}>
752
+ <PreviewApp />
753
+ </PageDataProvider>
748
754
  </FlyToCartProvider>
749
755
  </CartProvider>
750
756
  </LocaleProvider>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onexapis/cli",
3
- "version": "1.1.32",
3
+ "version": "1.1.36",
4
4
  "description": "CLI tool for OneX theme development - scaffolds themes using @onexapis/core",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -50,7 +50,7 @@
50
50
  },
51
51
  "dependencies": {
52
52
  "@aws-sdk/client-s3": "^3.470.0",
53
- "@onexapis/core": "^1.0.5",
53
+ "@onexapis/core": "^1.0.6",
54
54
  "@tanstack/react-query": "^5.90.16",
55
55
  "adm-zip": "^0.5.16",
56
56
  "archiver": "^7.0.1",
@@ -348,69 +348,64 @@ export const mySchema: SectionSchema = {
348
348
  | `url` | URL input | Link href |
349
349
  | `array` / `repeater` | List of repeating items | Feature list, social links |
350
350
 
351
- ## Available Hooks
351
+ ## Available Hooks (44 hooks)
352
352
 
353
- Import from `@onexapis/core/hooks`:
353
+ All hooks import from `@onexapis/core/hooks`. Use `onexthm_list_hooks` MCP tool for full API details.
354
354
 
355
355
  ```tsx
356
356
  import {
357
357
  useProducts,
358
358
  useCart,
359
- useAuth,
359
+ useCheckout,
360
360
  useDesignSystem,
361
361
  } from "@onexapis/core/hooks";
362
362
  ```
363
363
 
364
- ### Commerce Data (React Query)
364
+ ### Quick Reference
365
+
366
+ | Category | Hooks |
367
+ | ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
368
+ | **Commerce** (11) | `useProducts`, `useProductBySlug`, `useProductById`, `useProductCategories`, `useBlogs`, `useBlogBySlug`, `useBlogById`, `useBlogCategories`, `useSettings`, `useProductListing`, `useBlogListing` |
369
+ | **State** (3) | `useCart`, `useAuth`, `useOrders` |
370
+ | **Checkout** (8) | `useCheckout`, `usePayment`, `useOrderLookup`, `useOrderStatus`, `useOrderSuccess`, `useOrderSummary`, `useFinance`, `saveBuyNowItem` |
371
+ | **Products** (3) | `useSearchProducts`, `useAddToCart`, `useProductDetail` |
372
+ | **Theme** (8) | `useDesignSystem`, `useCommerceData`, `useThemeMode`, `useLocale`, `useViewport`, `usePageData`, `useWebsiteSettings`, `useMotion` |
373
+ | **Utilities** (7) | `useDebounce`, `useMediaQuery`, `useIsMobile`, `useIsTablet`, `useIsDesktop`, `useContactForm`, `useCopyToClipboard`, `useFormatPrice`, `formatVndPrice` |
374
+ | **Animation** (1) | `useFlyToCart` |
375
+ | **Server** (4) | `fetchProducts`, `fetchBlogs`, `fetchSettings`, `prefetchSectionData` |
376
+
377
+ ### Most Used Patterns
365
378
 
366
379
  ```tsx
367
- // Products
368
- const { data, isLoading } = useProducts({ limit: 8, page: 0 });
380
+ // Fetch products
381
+ const { data, isLoading } = useProducts({ limit: 8 });
369
382
  const products = data?.data ?? [];
370
383
 
371
- // Single product
372
- const { data: product } = useProductBySlug("blue-t-shirt");
384
+ // Cart
385
+ const { items, addItem, itemCount, subtotal } = useCart();
373
386
 
374
- // Blogs
375
- const { data, isLoading } = useBlogs({ limit: 6 });
376
- const blogs = data?.data ?? [];
387
+ // Auth
388
+ const { user, isAuthenticated, login, logout } = useAuth();
377
389
 
378
- // Website settings
379
- const { data: settings } = useSettings();
380
- ```
390
+ // Checkout (full form)
391
+ const checkout = useCheckout({ paymentRedirectUrl: "/payment" });
392
+ // checkout.fullName, checkout.handleCheckout, checkout.errors
381
393
 
382
- ### State Management
394
+ // Product detail with buy now
395
+ const detail = useProductDetail({ slug: routeParams.slug });
396
+ // detail.product, detail.handleAddToCart, detail.handleBuyNow
383
397
 
384
- ```tsx
385
- // Shopping cart
386
- const { items, addItem, removeItem, totalPrice, clearCart } = useCart();
387
-
388
- // Authentication
389
- const auth = useAuth();
390
- await auth.login(email, password);
391
- await auth.signup({ username, email, password, name });
392
- auth.logout();
393
- await auth.forgotPassword(email);
394
-
395
- // Orders
396
- const { createOrder, getOrders } = useOrders();
397
- ```
398
+ // Search with debounce
399
+ const search = useSearchProducts({ debounceMs: 300 });
400
+ // search.query, search.setQuery, search.results
398
401
 
399
- ### Theme & Context
402
+ // Responsive
403
+ const isMobile = useIsMobile();
404
+ const isDesktop = useIsDesktop();
400
405
 
401
- ```tsx
402
- // Design system tokens
403
- const { colors, typography, colorMode } = useDesignSystem();
404
- // colors.primary, colors.secondary, colors.background, etc.
405
-
406
- // Server-side data from SectionComponentProps.data
407
- const { products, blogs, settings, company } = useCommerceData(data);
408
-
409
- // Other contexts
410
- const { mode, isDark } = useThemeMode();
411
- const { locale, setLocale } = useLocale();
412
- const { isMobile, isDesktop } = useViewport();
413
- const motionTokens = useMotion();
406
+ // Price formatting
407
+ const { formatPrice } = useFormatPrice();
408
+ formatPrice(1250000); // "1.250.000đ"
414
409
  ```
415
410
 
416
411
  ## Color System
@@ -469,44 +464,36 @@ Without these, the editor cannot select sections/blocks for editing.
469
464
 
470
465
  34 built-in components from `@onexapis/core` that render inside sections via `ComponentRenderer`:
471
466
 
472
- | Component | Description | Key Settings |
473
- | ------------------ | ------------------ | --------------------------------------------------------------------- |
474
- | `heading` | H1-H6 text | text, tag, fontSize, fontWeight, colorToken, textAlign |
475
- | `paragraph` | Body text | text, fontSize, color, lineHeight, textAlign |
476
- | `button` | Clickable button | text, url, target, variant (default/outline/ghost/link), size |
477
- | `icon` | Lucide icon | iconName, size (xs-2xl), color, strokeWidth, rotation |
478
- | `badge` | Label/tag | text, variant (default/primary/success/warning/danger), size, rounded |
479
- | `image` | Image display | src, alt, width, height, objectFit, borderRadius, aspectRatio |
480
- | `video` | Video embed | videoType (youtube/vimeo/hosted), videoUrl, autoplay, loop |
481
- | `divider` | Separator line | color, width, style (solid/dashed/dotted) |
482
- | `quote` | Block quote | text, author, color, fontStyle |
483
- | `alert` | Alert box | title, message, type (info/success/warning/error), dismissible |
484
- | `progress` | Progress bar | value (0-100), label, color |
485
- | `rating` | Star rating | value (1-5), readOnly, size |
486
- | `social-links` | Social media links | Reads from WebsiteSettings context |
487
- | `hotline-contacts` | Contact info | Reads from WebsiteSettings context |
488
- | `company-info` | Company details | Reads from WebsiteSettings context |
489
- | `product-card` | Product display | product (Product), showQuickAdd |
490
- | `blog-card` | Blog post card | blog (Blog) |
467
+ | Component | Description | Key Settings |
468
+ | --------- | ----------- | ------------ |
469
+
470
+ **Text:** `heading` (H1-H6), `paragraph`, `quote`
471
+ **Interactive:** `button` (default/outline/ghost/link), `link`, `input`, `textarea`, `checkbox`, `select`
472
+ **Media:** `image`, `video` (youtube/vimeo/hosted), `icon` (Lucide icons), `gallery`
473
+ **Layout:** `divider`, `spacer`, `container`, `grid`, `columns`, `card`
474
+ **Display:** `badge`, `alert`, `progress`, `rating`, `timer`, `list`, `table`, `accordion`, `tabs`, `code`, `map`
475
+ **Special:** `product-card`, `blog-card`, `social-links`, `hotline-contacts`, `company-info`
476
+ **Decorative:** `torn-separator`
477
+
478
+ Use `onexthm://components` MCP resource for full details (content/style fields, slots, examples).
491
479
 
492
480
  Components are rendered via `ComponentRenderer` — you don't import them directly.
493
481
 
494
482
  ## Component Slots
495
483
 
496
- Components use `slot` to semantically identify their role in a section:
484
+ Components use `slot` to identify their role:
497
485
 
498
486
  ```tsx
499
- // In section component
500
487
  const titleComp = components.find((c) => c.slot === "section-title");
501
488
  const ctaButton = components.find((c) => c.slot === "cta-button");
502
- const subtitle = components.find((c) => c.slot === "description");
503
489
  ```
504
490
 
505
- Common slot names: `section-title`, `section-subtitle`, `description`, `cta-button`, `secondary-cta`, `badge`, `icon`, `image`
491
+ Common slots: `section-title`, `section-subtitle`, `description`, `cta-button`, `secondary-cta`, `badge`, `icon`, `image`, `block-title`, `block-description`, `feature-icon`
506
492
 
507
493
  ## Block System
508
494
 
509
- Blocks are nested containers inside sections. They can contain components AND other blocks (recursive):
495
+ Blocks are nested containers inside sections. They hold components and can nest other blocks.
496
+ Use `onexthm://blocks` MCP resource for full block patterns (features, testimonials, pricing, FAQ, team).
510
497
 
511
498
  ```tsx
512
499
  // Section → Blocks → Components
@@ -526,6 +513,68 @@ Blocks are nested containers inside sections. They can contain components AND ot
526
513
 
527
514
  Use `BlockRenderer` to render blocks — it handles recursive nesting automatically.
528
515
 
516
+ ### Defining Blocks in Schema
517
+
518
+ ```tsx
519
+ // In your-section.schema.ts
520
+ export const mySchema: SectionSchema = {
521
+ type: "features",
522
+ // ...settings, defaults...
523
+ blocks: [
524
+ {
525
+ type: "feature-item",
526
+ name: "Feature Item",
527
+ limit: 6, // Max 6 blocks of this type
528
+ settings: [
529
+ {
530
+ id: "backgroundColor",
531
+ type: "color",
532
+ label: "Background",
533
+ default: "#FFFFFF",
534
+ },
535
+ ],
536
+ components: [
537
+ { type: "icon", slot: "feature-icon", label: "Icon" },
538
+ { type: "heading", slot: "block-title", label: "Title" },
539
+ { type: "paragraph", slot: "block-description", label: "Description" },
540
+ ],
541
+ },
542
+ ],
543
+ };
544
+ ```
545
+
546
+ ### Rendering Blocks
547
+
548
+ ```tsx
549
+ const blocks = (section.blocks || []).filter((b) => b.enabled !== false);
550
+
551
+ {
552
+ blocks.map((block) => (
553
+ <div
554
+ key={block.id}
555
+ data-section-id={section.id} // REQUIRED
556
+ data-block-id={block.id} // REQUIRED
557
+ data-block-type={block.type} // REQUIRED
558
+ className="p-6 rounded-xl border"
559
+ >
560
+ <BlockRenderer
561
+ block={block}
562
+ sectionId={section.id}
563
+ isEditing={isEditing}
564
+ />
565
+ </div>
566
+ ));
567
+ }
568
+
569
+ {
570
+ blocks.length === 0 && isEditing && (
571
+ <div className="text-center py-12 border-2 border-dashed border-gray-300 rounded-lg">
572
+ <p className="text-gray-500">Add blocks to populate this section</p>
573
+ </div>
574
+ );
575
+ }
576
+ ```
577
+
529
578
  ## Animation System
530
579
 
531
580
  Sections, blocks, and components support animations via framer-motion: