@ikas/code-components-mcp 0.94.0 → 0.95.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/data/framework.json +7 -7
- package/data/section-templates.json +323 -108
- package/data/storefront-api.json +1 -717
- package/data/storefront-types.json +1 -1
- package/package.json +1 -1
package/data/framework.json
CHANGED
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"prop-types": {
|
|
36
36
|
"title": "Available Prop Types",
|
|
37
37
|
"description": "All prop types that can be used in ikas.config.json",
|
|
38
|
-
"content": "Props define what the store editor can configure for each component. Each prop has a `type` that determines the editor UI and the TypeScript type received in your component.\n\n| Type | Editor UI | TypeScript Type | Description |\n|------|-----------|----------------|-------------|\n| `TEXT` | Text input | `string` | Single-line text |\n| `RICH_TEXT` | Rich text editor | `string` | HTML rich text content |\n| `NUMBER` | Number input | `number` | Numeric value |\n| `BOOLEAN` | Toggle switch | `boolean` | True/false toggle |\n| `IMAGE` | Image picker | `IkasImage | null` | Image from editor. Use `getDefaultSrc(image)` for URL |\n| `IMAGE_LIST` | Image list picker | `IkasImageList` | Multiple images from editor |\n| `LINK` | Link editor | `IkasNavigationLink` | Navigation link with href, label, subLinks |\n| `LIST_OF_LINK` | Link list editor | `IkasNavigationLinkList` | List of navigation links |\n| `COLOR` | Color picker | `string` | CSS color value (hex, rgb, etc.) |\n| `PRODUCT` | Product picker | `IkasProduct` | Single product reference |\n| `PRODUCT_LIST` | Product list picker | `
|
|
38
|
+
"content": "Props define what the store editor can configure for each component. Each prop has a `type` that determines the editor UI and the TypeScript type received in your component.\n\n| Type | Editor UI | TypeScript Type | Description |\n|------|-----------|----------------|-------------|\n| `TEXT` | Text input | `string` | Single-line text |\n| `RICH_TEXT` | Rich text editor | `string` | HTML rich text content |\n| `NUMBER` | Number input | `number` | Numeric value |\n| `BOOLEAN` | Toggle switch | `boolean` | True/false toggle |\n| `IMAGE` | Image picker | `IkasImage | null` | Image from editor. Use `getDefaultSrc(image)` for URL |\n| `IMAGE_LIST` | Image list picker | `IkasImageList` | Multiple images from editor |\n| `LINK` | Link editor | `IkasNavigationLink` | Navigation link with href, label, subLinks |\n| `LIST_OF_LINK` | Link list editor | `IkasNavigationLinkList` | List of navigation links |\n| `COLOR` | Color picker | `string` | CSS color value (hex, rgb, etc.) |\n| `PRODUCT` | Product picker | `IkasProduct` | Single product reference |\n| `PRODUCT_LIST` | Product list picker | `IkasProductList` | Product list with `.data` (products array), `.filters`, `.sort`, `.page`, etc. |\n| `CATEGORY` | Category picker | `IkasCategory` | Single category reference |\n| `CATEGORY_LIST` | Category list picker | `IkasCategory[]` | Multiple category references |\n| `BRAND` | Brand picker | `IkasBrand` | Single brand reference |\n| `BRAND_LIST` | Brand list picker | `IkasBrand[]` | Multiple brand references |\n| `BLOG` | Blog post picker | `IkasBlog` | Single blog post reference |\n| `BLOG_LIST` | Blog post list picker | `IkasBlog[]` | Multiple blog post references |\n| `BLOG_CATEGORY` | Blog category picker | `IkasBlogCategory` | Single blog category reference |\n| `BLOG_CATEGORY_LIST` | Blog category list picker | `IkasBlogCategoryList` | Multiple blog category references |\n| `FONT_STYLE_TYPE` | Font style editor | `IkasFontStyle` | Font family, size, weight, etc. |\n| `TYPE` | Type selector | Depends on typeId | Structured type (padding, margin, size, etc.). Available for both components and sections (sections have a restricted whitelist). |\n| `ENUM` | Dropdown selector | `string` | Enum-based style type (flex-direction, justify-content, align-items, etc.). Uses `enumTypeId`. Available for both components and sections. |\n| `COMPONENT` | Component slot | `any` | A single child component slot. Store owners can place a component in this slot from the editor. Render with `<IkasComponentRenderer>`. |\n| `COMPONENT_LIST` | Component list slot | `any` | A list of child components. Store owners can add multiple components from the editor. Render with `<IkasComponentRenderer>`. |\n\n### COMPONENT & COMPONENT_LIST props (child component slots)\n\nThese prop types enable **slot-based** architectures where store owners can drag child components into your section/component from the editor.\n\n- `COMPONENT` — a single child component slot\n- `COMPONENT_LIST` — a list of child components\n\n**Rendering:** Use the `<IkasComponentRenderer>` wrapper from `@ikas/bp-storefront`:\n```tsx\nimport { IkasComponentRenderer } from \"@ikas/bp-storefront\";\nimport { Props } from \"./types\";\n\nexport function MySection({ title, cardList, ...props }: Props) {\n return (\n <section>\n <h2>{title}</h2>\n <div className=\"cards\">\n {/* COMPONENT_LIST — render a list of child components */}\n <IkasComponentRenderer\n id=\"card-list\"\n components={cardList as any[]}\n parentProps={props}\n />\n </div>\n </section>\n );\n}\nexport default MySection;\n```\n\n**Key rules:**\n- Always pass `parentProps={props}` so child components can access parent data via dynamic values\n- Cast the prop value: `components={myList as any[]}` for COMPONENT_LIST, `components={[myComp] as any[]}` for COMPONENT\n- `<IkasComponentRenderer>` handles rendering, styling, and reactivity of child components automatically\n\n**Config example (COMPONENT_LIST):**\n```json\n{\n \"name\": \"cardList\",\n \"displayName\": \"Card List\",\n \"type\": \"COMPONENT_LIST\"\n}\n```\n\n**Config example (COMPONENT):**\n```json\n{\n \"name\": \"headerSlot\",\n \"displayName\": \"Header Slot\",\n \"type\": \"COMPONENT\"\n}\n```\n\n### IMAGE type example:\n```json\n{\n \"name\": \"heroImage\",\n \"displayName\": \"Hero Image\",\n \"type\": \"IMAGE\",\n \"required\": false\n}\n```\nAccess in component: `getDefaultSrc(props.heroImage)` (import `getDefaultSrc` from `@ikas/bp-storefront`)\n\n### Prop grouping\nProps can be assigned to groups via `groupId` for organized editor sidebar display. See `get_framework_guide(\"prop-groups\")` for details.\n\n### Style Props: TYPE and ENUM\n\nThere are two prop types for style values:\n\n- **TYPE** — Structured types with numeric values and units (padding, margin, border-radius, sizes, etc.). Uses `typeId`.\n- **ENUM** — Enum types rendered as dropdown selectors (flex-direction, justify-content, align-items, etc.). Uses `enumTypeId`.\n\nBoth are available for components and sections. For sections, TYPE props are limited to a whitelist of style types. Use `list-types --component-type section` to see section-allowed types.\n\n### TYPE prop (structured types)\nThe `TYPE` prop lets you use structured storefront types like PaddingStyleType, MarginStyleType, SizeStyleType, etc. Available for both components and sections (sections have a restricted whitelist of style types).\n\n**Workflow:**\n1. Run `npx ikas-component config list-types` to get available types (requires dev server running with editor connected)\n2. Use the `typeId` from the output when adding the prop\n3. For sections: `npx ikas-component config list-types --component-type section` to see only section-allowed types\n\n**Example config:**\n```json\n{\n \"name\": \"spacing\",\n \"displayName\": \"Spacing\",\n \"type\": \"TYPE\",\n \"typeId\": \"@ikas/bp-storefront-models-PaddingStyleType\"\n}\n```\n\n**Array example** (append `_array` to typeId):\n```json\n{\n \"name\": \"margins\",\n \"displayName\": \"Margins\",\n \"type\": \"TYPE\",\n \"typeId\": \"@ikas/bp-storefront-models-MarginStyleType_array\"\n}\n```\nThis generates `margins?: MarginStyleType[]` in types.ts.\n\n**CLI command:**\n```bash\nnpx ikas-component config add-prop --component MyComp --name spacing --displayName Spacing --type TYPE --typeId \"@ikas/bp-storefront-models-PaddingStyleType\"\n```\n\n### ENUM prop (enum style types)\nThe `ENUM` prop lets you use enum-based types that render as dropdown selectors. All enum types from the editor are available (e.g. FlexDirectionStyleType, JustifyContentStyleType, AlignItemsStyleType, DirectionStyleType, TextAlignStyleType, ObjectFitStyleType, and custom enums).\n\n**Workflow:**\n1. Run `npx ikas-component config list-types` — enum types have `category: \"enum\"` in the output\n2. Use the `enumTypeId` from the output when adding the prop\n\n**Example config:**\n```json\n{\n \"name\": \"direction\",\n \"displayName\": \"Direction\",\n \"type\": \"ENUM\",\n \"enumTypeId\": \"@ikas/bp-storefront-models-FlexDirectionStyleType\"\n}\n```\nThis generates `direction?: string` in types.ts.\n\n**CLI command:**\n```bash\nnpx ikas-component config add-prop --component MyComp --name direction --displayName Direction --type ENUM --enumTypeId \"@ikas/bp-storefront-models-FlexDirectionStyleType\"\n```\n\n**Note:** The `list-types` command connects to the dev server WebSocket, which must have an editor connected for types to be available.",
|
|
39
39
|
"tags": [
|
|
40
40
|
"props",
|
|
41
41
|
"types",
|
|
@@ -246,7 +246,7 @@
|
|
|
246
246
|
"product-detail-patterns": {
|
|
247
247
|
"title": "Product Detail Patterns (Serel Reference)",
|
|
248
248
|
"description": "Serel ProductDetail with 12 child components in two COMPONENT_LIST slots, ProductGallery local component, Breadcrumb navigation, and component slot architecture",
|
|
249
|
-
"content": "## Product Detail Patterns (Serel Reference)\n\nThe serel ProductDetail section is the most complex section in the theme, with **12 child components** distributed across **two COMPONENT_LIST slots** (`components` and `bottomComponents`), plus a local `ProductGallery` component and Breadcrumb navigation.\n\n### Two-Slot Architecture\n\nThe section declares two separate COMPONENT_LIST props:\n\n```json\n{\n \"props\": [\n {\n \"name\": \"components\",\n \"type\": \"COMPONENT_LIST\",\n \"filteredComponentIds\": [\n \"nb34u3yu-product-detail-name-favorite\",\n \"nb34u3yu-product-detail-sku\",\n \"nb34u3yu-product-detail-prices\",\n \"nb34u3yu-product-detail-product-group\",\n \"nb34u3yu-product-detail-variant\",\n \"nb34u3yu-product-detail-add-to-cart\",\n \"nb34u3yu-product-detail-features\",\n \"nb34u3yu-product-detail-description\",\n \"nb34u3yu-product-detail-bundle-product\",\n \"nb34u3yu-product-detail-option-set\",\n \"nb34u3yu-product-detail-offer\",\n \"nb34u3yu-product-detail-bundle-furniture\"\n ]\n },\n {\n \"name\": \"bottomComponents\",\n \"type\": \"COMPONENT_LIST\",\n \"filteredComponentIds\": [\"nb34u3yu-product-detail-description\"]\n }\n ]\n}\n```\n\n### Section Layout\n\n```tsx\nimport { IkasComponentRenderer } from \"@ikas/bp-storefront\";\nimport Breadcrumb from \"../../sub-components/Breadcrumb\";\nimport ProductGallery from \"./ProductGallery\"; // local component\nimport { Props } from \"./types\";\n\nexport function ProductDetail({ product, components, bottomComponents, backgroundColor, ...props }: Props) {\n if (!product) return null;\n return (\n <section className=\"product-detail\" style={backgroundColor ? { backgroundColor } : undefined}>\n <Breadcrumb product={product} />\n <div className=\"product-detail-inner\">\n <div className=\"product-detail-gallery\">\n <ProductGallery product={product} />\n </div>\n <div className=\"product-detail-info\">\n <IkasComponentRenderer components={components} parentProps={props} />\n </div>\n </div>\n <div className=\"product-detail-bottom\">\n <IkasComponentRenderer components={bottomComponents} parentProps={props} />\n </div>\n </section>\n );\n}\nexport default ProductDetail;\n```\n\n### 12 Child Components\n\n| Child Component | Purpose |\n|-----------------|--------|\n| ProductDetailNameFavorite | Product name + favorites toggle |\n| ProductDetailSku | SKU display |\n| ProductDetailPrices | Price display with discounts |\n| ProductDetailProductGroup | Product group/collection links |\n| ProductDetailVariant | Variant selector (size, color) |\n| ProductDetailAddToCart | Quantity selector + add-to-cart button |\n| ProductDetailFeatures | Feature list (uses FeatureItem children) |\n| ProductDetailDescription | Collapsible description (uses CollapsibleContent children) |\n| ProductDetailBundleProduct | Bundle product display |\n| ProductDetailBundleFurniture | Bundle furniture configuration |\n| ProductDetailOptionSet | Custom option sets |\n| ProductDetailOffer | Special offer display |\n\n### ProductGallery (Local Component)\n\nProductGallery is defined locally within the ProductDetail folder (not a registered component or sub-component). It handles image display with thumbnail navigation, zoom, and responsive srcset:\n\n```tsx\nconst images = (variant?.images ?? [])\n .map((pi) => pi.image)\n .filter((img): img is IkasImage => img != null);\n```\n\n### Breadcrumb Navigation\n\nThe Breadcrumb sub-component (from `src/sub-components/Breadcrumb/`) renders category path navigation:\n\n```tsx\nimport { getProductCategoryPath, getIkasCategoryHref } from \"@ikas/bp-storefront\";\nconst categoryPath = getProductCategoryPath(product);\n```\n\n### Key Pattern: Multiple COMPONENT_LIST Slots\n\nUsing two slots (`components` and `bottomComponents`) allows the store owner to arrange child components differently:\n- `components` — displayed next to the gallery in a side panel\n- `bottomComponents` — displayed full-width below the gallery\n\nThis pattern can be applied to any section that needs multiple layout regions.",
|
|
249
|
+
"content": "## Product Detail Patterns (Serel Reference)\n\nThe serel ProductDetail section is the most complex section in the theme, with **12 child components** distributed across **two COMPONENT_LIST slots** (`components` and `bottomComponents`), plus a local `ProductGallery` component and Breadcrumb navigation.\n\n### Two-Slot Architecture\n\nThe section declares two separate COMPONENT_LIST props:\n\n```json\n{\n \"props\": [\n {\n \"name\": \"components\",\n \"type\": \"COMPONENT_LIST\",\n \"filteredComponentIds\": [\n \"nb34u3yu-product-detail-name-favorite\",\n \"nb34u3yu-product-detail-sku\",\n \"nb34u3yu-product-detail-prices\",\n \"nb34u3yu-product-detail-product-group\",\n \"nb34u3yu-product-detail-variant\",\n \"nb34u3yu-product-detail-add-to-cart\",\n \"nb34u3yu-product-detail-features\",\n \"nb34u3yu-product-detail-description\",\n \"nb34u3yu-product-detail-bundle-product\",\n \"nb34u3yu-product-detail-option-set\",\n \"nb34u3yu-product-detail-offer\",\n \"nb34u3yu-product-detail-bundle-furniture\"\n ]\n },\n {\n \"name\": \"bottomComponents\",\n \"type\": \"COMPONENT_LIST\",\n \"filteredComponentIds\": [\"nb34u3yu-product-detail-description\"]\n }\n ]\n}\n```\n\n### Section Layout\n\n```tsx\nimport { IkasComponentRenderer } from \"@ikas/bp-storefront\";\nimport Breadcrumb from \"../../sub-components/Breadcrumb\";\nimport ProductGallery from \"./ProductGallery\"; // local component\nimport { Props } from \"./types\";\n\nexport function ProductDetail({ product, components, bottomComponents, backgroundColor, ...props }: Props) {\n if (!product) return null;\n return (\n <section className=\"product-detail\" style={backgroundColor ? { backgroundColor } : undefined}>\n <Breadcrumb product={product} />\n <div className=\"product-detail-inner\">\n <div className=\"product-detail-gallery\">\n <ProductGallery product={product} />\n </div>\n <div className=\"product-detail-info\">\n <IkasComponentRenderer id=\"product-detail-components\" components={components} parentProps={props} />\n </div>\n </div>\n <div className=\"product-detail-bottom\">\n <IkasComponentRenderer id=\"product-detail-bottom-components\" components={bottomComponents} parentProps={props} />\n </div>\n </section>\n );\n}\nexport default ProductDetail;\n```\n\n### 12 Child Components\n\n| Child Component | Purpose |\n|-----------------|--------|\n| ProductDetailNameFavorite | Product name + favorites toggle |\n| ProductDetailSku | SKU display |\n| ProductDetailPrices | Price display with discounts |\n| ProductDetailProductGroup | Product group/collection links |\n| ProductDetailVariant | Variant selector (size, color) |\n| ProductDetailAddToCart | Quantity selector + add-to-cart button |\n| ProductDetailFeatures | Feature list (uses FeatureItem children) |\n| ProductDetailDescription | Collapsible description (uses CollapsibleContent children) |\n| ProductDetailBundleProduct | Bundle product display |\n| ProductDetailBundleFurniture | Bundle furniture configuration |\n| ProductDetailOptionSet | Custom option sets |\n| ProductDetailOffer | Special offer display |\n\n### ProductGallery (Local Component)\n\nProductGallery is defined locally within the ProductDetail folder (not a registered component or sub-component). It handles image display with thumbnail navigation, zoom, and responsive srcset:\n\n```tsx\nconst images = (variant?.images ?? [])\n .map((pi) => pi.image)\n .filter((img): img is IkasImage => img != null);\n```\n\n### Breadcrumb Navigation\n\nThe Breadcrumb sub-component (from `src/sub-components/Breadcrumb/`) renders category path navigation:\n\n```tsx\nimport { getProductCategoryPath, getIkasCategoryHref } from \"@ikas/bp-storefront\";\nconst categoryPath = getProductCategoryPath(product);\n```\n\n### Key Pattern: Multiple COMPONENT_LIST Slots\n\nUsing two slots (`components` and `bottomComponents`) allows the store owner to arrange child components differently:\n- `components` — displayed next to the gallery in a side panel\n- `bottomComponents` — displayed full-width below the gallery\n\nThis pattern can be applied to any section that needs multiple layout regions.",
|
|
250
250
|
"tags": [
|
|
251
251
|
"product",
|
|
252
252
|
"detail",
|
|
@@ -264,7 +264,7 @@
|
|
|
264
264
|
"product-list-patterns": {
|
|
265
265
|
"title": "Product List & Filtering Patterns",
|
|
266
266
|
"description": "Category pages, product filtering with display-type-aware rendering (swatch, number range, checkbox), sorting, pagination, and search patterns",
|
|
267
|
-
"content": "## Product List & Filtering Patterns\n\nProduct list sections power category pages, search results, and collection displays. They combine filtering, sorting, and pagination.\n\n### Product List Prop Setup\n\nIn `ikas.config.json`, use the `PRODUCT_LIST` prop type:\n```json\n{\n \"name\": \"productList\",\n \"displayName\": \"Product List\",\n \"type\": \"PRODUCT_LIST\",\n \"required\": true\n}\n```\n\nThis provides an `IkasProductList` object with products, filters, sorting, and pagination data.\n\n### Displaying Products\n\n```tsx\nimport {\n IkasProductList,\n getSelectedProductVariant,\n getProductVariantFormattedFinalPrice,\n getProductVariantMainImage,\n getSelectedProductVariantHref,\n getDefaultSrc,\n} from \"@ikas/bp-storefront\";\n\n// In your component:\nconst products = productList?.data ?? [];\n\n{products.map((product) => {\n const variant = getSelectedProductVariant(product);\n const productImage = getProductVariantMainImage(variant);\n const image = productImage?.image ?? null;\n const price = getProductVariantFormattedFinalPrice(variant) as unknown as string;\n const href = getSelectedProductVariantHref(product);\n\n return (\n <a key={product.id} href={href} className=\"product-card\">\n {image && <img src={getDefaultSrc(image)} alt={product.name} />}\n <h3>{product.name}</h3>\n <span>{price}</span>\n </a>\n );\n})}\n```\n\n### Filtering\n\nFilters let customers narrow down products by attributes (size, color, price, etc.). Each filter has a `displayType` that determines how it should be rendered. **Always check the display type and render accordingly** — do not render all filters as checkboxes.\n\n#### Display Types\n\n- **BOX / LIST** — Standard checkbox filters (size, brand, etc.)\n- **SWATCH** — Color/pattern swatches with `fv.colorCode` or thumbnail images\n- **NUMBER_RANGE_LIST** — Predefined price/number range buttons (e.g., $0-$50, $50-$100)\n\n#### Universal Data Pattern\n\nThe data flow is the same for all display types:\n- `getFilterDisplayedValues(filter)` — get sorted filter values (works for ALL types)\n- `handleFilterValueClick(productList, filter, filterValue)` — toggle selection + auto-refetch (works for BOX/LIST/SWATCH)\n- `handleNumberRangeOptionClick(productList, filter, option)` — toggle a range option + auto-refetch (for NUMBER_RANGE_LIST)\n\n#### Imports\n\n```tsx\nimport {\n getFilterDisplayedValues,\n handleFilterValueClick,\n handleNumberRangeOptionClick,\n getProductListFilterCategories,\n isBoxFilter,\n isListFilter,\n isSwatchFilter,\n getIkasFilterThumbnailImage,\n getDefaultSrc,\n IkasProductList,\n IkasProductFilter,\n} from \"@ikas/bp-storefront\";\n```\n\n#### Display-Type-Aware Rendering\n\n```tsx\nconst filters = productList.filters ?? [];\n\n{filters.map((filter) => {\n const values = getFilterDisplayedValues(filter);\n if (values.length === 0 && !filter.numberRangeListOptions?.length) return null;\n\n return (\n <div key={filter.id}>\n <h4>{filter.name}</h4>\n\n {/* SWATCH: render color circles / thumbnail images */}\n {isSwatchFilter(filter) ? (\n <div className=\"swatch-grid\">\n {values.map((fv) => {\n const thumbnail = getIkasFilterThumbnailImage(fv);\n return (\n <button\n key={fv.name}\n className={fv.isSelected === true ? \"swatch selected\" : \"swatch\"}\n onClick={() => handleFilterValueClick(productList, filter, fv)}\n title={fv.name}\n >\n {thumbnail ? (\n <img src={getDefaultSrc(thumbnail)} alt={fv.name} />\n ) : (\n <span\n className=\"swatch-color\"\n style={{ backgroundColor: fv.colorCode ?? \"#ccc\" }}\n />\n )}\n </button>\n );\n })}\n </div>\n ) : (\n /* BOX / LIST: render checkboxes */\n values.map((fv) => (\n <label key={fv.name}>\n <input\n type=\"checkbox\"\n checked={fv.isSelected === true}\n onChange={() => handleFilterValueClick(productList, filter, fv)}\n />\n {fv.name} {fv.
|
|
267
|
+
"content": "## Product List & Filtering Patterns\n\nProduct list sections power category pages, search results, and collection displays. They combine filtering, sorting, and pagination.\n\n### Product List Prop Setup\n\nIn `ikas.config.json`, use the `PRODUCT_LIST` prop type:\n```json\n{\n \"name\": \"productList\",\n \"displayName\": \"Product List\",\n \"type\": \"PRODUCT_LIST\",\n \"required\": true\n}\n```\n\nThis provides an `IkasProductList` object with products, filters, sorting, and pagination data.\n\n### Displaying Products\n\n```tsx\nimport {\n IkasProductList,\n getSelectedProductVariant,\n getProductVariantFormattedFinalPrice,\n getProductVariantMainImage,\n getSelectedProductVariantHref,\n getDefaultSrc,\n} from \"@ikas/bp-storefront\";\n\n// In your component:\nconst products = productList?.data ?? [];\n\n{products.map((product) => {\n const variant = getSelectedProductVariant(product);\n const productImage = getProductVariantMainImage(variant);\n const image = productImage?.image ?? null;\n const price = getProductVariantFormattedFinalPrice(variant) as unknown as string;\n const href = getSelectedProductVariantHref(product);\n\n return (\n <a key={product.id} href={href} className=\"product-card\">\n {image && <img src={getDefaultSrc(image)} alt={product.name} />}\n <h3>{product.name}</h3>\n <span>{price}</span>\n </a>\n );\n})}\n```\n\n### Filtering\n\nFilters let customers narrow down products by attributes (size, color, price, etc.). Each filter has a `displayType` that determines how it should be rendered. **Always check the display type and render accordingly** — do not render all filters as checkboxes.\n\n#### Display Types\n\n- **BOX / LIST** — Standard checkbox filters (size, brand, etc.)\n- **SWATCH** — Color/pattern swatches with `fv.colorCode` or thumbnail images\n- **NUMBER_RANGE_LIST** — Predefined price/number range buttons (e.g., $0-$50, $50-$100)\n\n#### Universal Data Pattern\n\nThe data flow is the same for all display types:\n- `getFilterDisplayedValues(filter)` — get sorted filter values (works for ALL types)\n- `handleFilterValueClick(productList, filter, filterValue)` — toggle selection + auto-refetch (works for BOX/LIST/SWATCH)\n- `handleNumberRangeOptionClick(productList, filter, option)` — toggle a range option + auto-refetch (for NUMBER_RANGE_LIST)\n\n#### Imports\n\n```tsx\nimport {\n getFilterDisplayedValues,\n handleFilterValueClick,\n handleNumberRangeOptionClick,\n getProductListFilterCategories,\n isBoxFilter,\n isListFilter,\n isSwatchFilter,\n getIkasFilterThumbnailImage,\n getDefaultSrc,\n IkasProductList,\n IkasProductFilter,\n} from \"@ikas/bp-storefront\";\n```\n\n#### Display-Type-Aware Rendering\n\n```tsx\nconst filters = productList.filters ?? [];\n\n{filters.map((filter) => {\n const values = getFilterDisplayedValues(filter);\n if (values.length === 0 && !filter.numberRangeListOptions?.length) return null;\n\n return (\n <div key={filter.id}>\n <h4>{filter.name}</h4>\n\n {/* SWATCH: render color circles / thumbnail images */}\n {isSwatchFilter(filter) ? (\n <div className=\"swatch-grid\">\n {values.map((fv) => {\n const thumbnail = getIkasFilterThumbnailImage(fv);\n return (\n <button\n key={fv.name}\n className={fv.isSelected === true ? \"swatch selected\" : \"swatch\"}\n onClick={() => handleFilterValueClick(productList, filter, fv)}\n title={fv.name}\n >\n {thumbnail ? (\n <img src={getDefaultSrc(thumbnail)} alt={fv.name} />\n ) : (\n <span\n className=\"swatch-color\"\n style={{ backgroundColor: fv.colorCode ?? \"#ccc\" }}\n />\n )}\n </button>\n );\n })}\n </div>\n ) : (\n /* BOX / LIST: render checkboxes */\n values.map((fv) => (\n <label key={fv.name}>\n <input\n type=\"checkbox\"\n checked={fv.isSelected === true}\n onChange={() => handleFilterValueClick(productList, filter, fv)}\n />\n {fv.name} {fv.resultCount != null && `(${fv.resultCount})`}\n </label>\n ))\n )}\n\n {/* NUMBER_RANGE_LIST: render predefined range buttons */}\n {filter.numberRangeListOptions?.map((option) => (\n <button\n key={`${option.from}-${option.to}`}\n className={option.isSelected ? \"range-btn selected\" : \"range-btn\"}\n onClick={() => handleNumberRangeOptionClick(productList, filter, option)}\n >\n {option.from} - {option.to ?? \"+\"}\n </button>\n ))}\n </div>\n );\n})}\n```\n\n### Sorting\n\n```tsx\nimport { getProductListSortOptions, setSortType, IkasProductListSortType } from \"@ikas/bp-storefront\";\n\nconst sortOptions = getProductListSortOptions(productList);\n\n<select\n value={productList.sort}\n onChange={(e) => {\n setSortType(productList, (e.target as HTMLSelectElement).value as IkasProductListSortType);\n }}\n>\n {sortOptions.map((opt) => (\n <option key={opt.value} value={opt.value}>{opt.label}</option>\n ))}\n</select>\n```\n\n### Pagination\n\n```tsx\nimport {\n hasProductListNextPage,\n hasProductListPrevPage,\n getProductListNextPage,\n getProductListPrevPage,\n} from \"@ikas/bp-storefront\";\n\nconst hasNext = hasProductListNextPage(productList);\nconst hasPrev = hasProductListPrevPage(productList);\n\n<div className=\"pagination\">\n <button disabled={!hasPrev} onClick={() => getProductListPrevPage(productList)}>\n Previous\n </button>\n <button disabled={!hasNext} onClick={() => getProductListNextPage(productList)}>\n Next\n </button>\n</div>\n```\n\n### Key Functions Reference\n\n| Function | Purpose |\n|----------|---------|\n| `getProductListFilterCategories(list)` | Get available filter categories |\n| `getFilterDisplayedValues(filter)` | Get sorted filter values — works for ALL display types |\n| `handleFilterValueClick(list, filter, value)` | Toggle a filter value + auto-refetch (BOX/LIST/SWATCH) |\n| `handleNumberRangeOptionClick(list, filter, option)` | Toggle a range option + auto-refetch (NUMBER_RANGE_LIST) |\n| `isBoxFilter(filter)` | Check if filter displayType is BOX |\n| `isListFilter(filter)` | Check if filter displayType is LIST |\n| `isSwatchFilter(filter)` | Check if filter displayType is SWATCH |\n| `isCustomValueFilter(filter)` | Check if filter displayType is CUSTOM_VALUE |\n| `getIkasFilterThumbnailImage(fv)` | Get swatch thumbnail IkasImage from a filter value |\n| `getProductListSortOptions(list)` | Get sort dropdown options |\n| `hasProductListNextPage(list)` / `getProductListNextPage(list)` | Next page |\n| `hasProductListPrevPage(list)` / `getProductListPrevPage(list)` | Previous page |",
|
|
268
268
|
"tags": [
|
|
269
269
|
"product-list",
|
|
270
270
|
"filtering",
|
|
@@ -310,7 +310,7 @@
|
|
|
310
310
|
"header-footer-patterns": {
|
|
311
311
|
"title": "Header & Footer Patterns (Serel Reference)",
|
|
312
312
|
"description": "IkasComponentRenderer-based Header with Navbar/Announcements/CookieBar children, Footer with SocialMediaIcon children, Toast system, isHeader/isFooter flags",
|
|
313
|
-
"content": "## Header & Footer Patterns (Serel Reference)\n\nIn the serel theme, the Header and Footer are sections that use `IkasComponentRenderer` to render child components. This is the recommended production pattern.\n\n### Header Architecture\n\nThe serel Header section declares a `COMPONENT_LIST` prop with `filteredComponentIds` restricting it to three child components: **Navbar**, **Announcements**, and **CookieBar**.\n\n```tsx\nimport { IkasComponentRenderer } from \"@ikas/bp-storefront\";\nimport { Props } from \"./types\";\n\nexport function Header({ components, backgroundColor, ...props }: Props) {\n return (\n <header className=\"header\" style={backgroundColor ? { backgroundColor } : undefined}>\n <IkasComponentRenderer components={components} parentProps={props} />\n <ToastContainer />\n </header>\n );\n}\nexport default Header;\n```\n\nConfig setup with `isHeader: true` and `filteredComponentIds`:\n```json\n{\n \"id\": \"nb34u3yu-header\",\n \"name\": \"Header\",\n \"type\": \"section\",\n \"isHeader\": true,\n \"props\": [\n {\n \"name\": \"components\",\n \"type\": \"COMPONENT_LIST\",\n \"filteredComponentIds\": [\"nb34u3yu-navbar\", \"nb34u3yu-announcements\", \"nb34u3yu-cookie-bar\"]\n }\n ]\n}\n```\n\nThe `isHeader: true` flag ensures this section appears on every page automatically.\n\n### Toast Notification System\n\nThe serel Header hosts a `ToastContainer` component. The `useToast` hook provides a global notification system:\n\n```tsx\nimport { useToast } from \"../../hooks/useToast\";\n\n// In any component:\nconst { showToast } = useToast();\nshowToast({ message: \"Added to cart!\", type: \"success\" });\n```\n\nThe ToastContainer renders as a portal to ensure toasts appear above all content. Toasts stack vertically and auto-dismiss after a timeout.\n\n### Navbar Child Component\n\nThe Navbar child component handles: logo display, navigation links (`LIST_OF_LINK`), cart badge (reads `cartStore`), account icon (reads `customerStore`), search functionality, and a mobile hamburger menu. It also has its own `COMPONENT_LIST` slot for product search results using CardProductName/CardProductVariants/CardProductPrice with `privateVarMap` for the product variable.\n\n### Announcements Child Component\n\nThe Announcements child component uses `IkasThemeSlider` for a rotating announcement bar. It has its own child component slot for individual Announcement items.\n\n### CookieBar Child Component\n\nThe CookieBar manages cookie consent with accept/decline actions and persists the choice to localStorage.\n\n### Footer Architecture\n\nThe serel Footer section uses `IkasComponentRenderer` with a `COMPONENT_LIST` filtered to **SocialMediaIcon** children:\n\n```tsx\nimport { IkasComponentRenderer } from \"@ikas/bp-storefront\";\nimport { Props } from \"./types\";\n\nexport function Footer({ components, backgroundColor, ...props }: Props) {\n return (\n <footer className=\"footer\" style={backgroundColor ? { backgroundColor } : undefined}>\n <div className=\"footer-inner\">\n {/* Logo, link columns, contact info */}\n <div className=\"footer-social\">\n <IkasComponentRenderer components={components} parentProps={props} />\n </div>\n {/* Copyright */}\n </div>\n </footer>\n );\n}\nexport default Footer;\n```\n\nConfig with `isFooter: true`:\n```json\n{\n \"id\": \"nb34u3yu-footer\",\n \"name\": \"Footer\",\n \"type\": \"section\",\n \"isFooter\": true,\n \"props\": [\n {\n \"name\": \"components\",\n \"type\": \"COMPONENT_LIST\",\n \"filteredComponentIds\": [\"nb34u3yu-social-media-icon\"]\n }\n ]\n}\n```\n\n### Key Patterns\n\n- Headers and footers use `IkasComponentRenderer` with `filteredComponentIds` for controlled child composition\n- `isHeader: true` / `isFooter: true` flags in config make them appear on all pages\n- Root exports are automatically reactive (cartStore/customerStore tracked by autorun)\n- Toast system lives in the Header for global accessibility\n- `parentProps` passes section data to child components\n- The Navbar child component itself nests additional child components via its own COMPONENT_LIST",
|
|
313
|
+
"content": "## Header & Footer Patterns (Serel Reference)\n\nIn the serel theme, the Header and Footer are sections that use `IkasComponentRenderer` to render child components. This is the recommended production pattern.\n\n### Header Architecture\n\nThe serel Header section declares a `COMPONENT_LIST` prop with `filteredComponentIds` restricting it to three child components: **Navbar**, **Announcements**, and **CookieBar**.\n\n```tsx\nimport { IkasComponentRenderer } from \"@ikas/bp-storefront\";\nimport { Props } from \"./types\";\n\nexport function Header({ components, backgroundColor, ...props }: Props) {\n return (\n <header className=\"header\" style={backgroundColor ? { backgroundColor } : undefined}>\n <IkasComponentRenderer id=\"header-components\" components={components} parentProps={props} />\n <ToastContainer />\n </header>\n );\n}\nexport default Header;\n```\n\nConfig setup with `isHeader: true` and `filteredComponentIds`:\n```json\n{\n \"id\": \"nb34u3yu-header\",\n \"name\": \"Header\",\n \"type\": \"section\",\n \"isHeader\": true,\n \"props\": [\n {\n \"name\": \"components\",\n \"type\": \"COMPONENT_LIST\",\n \"filteredComponentIds\": [\"nb34u3yu-navbar\", \"nb34u3yu-announcements\", \"nb34u3yu-cookie-bar\"]\n }\n ]\n}\n```\n\nThe `isHeader: true` flag ensures this section appears on every page automatically.\n\n### Toast Notification System\n\nThe serel Header hosts a `ToastContainer` component. The `useToast` hook provides a global notification system:\n\n```tsx\nimport { useToast } from \"../../hooks/useToast\";\n\n// In any component:\nconst { showToast } = useToast();\nshowToast({ message: \"Added to cart!\", type: \"success\" });\n```\n\nThe ToastContainer renders as a portal to ensure toasts appear above all content. Toasts stack vertically and auto-dismiss after a timeout.\n\n### Navbar Child Component\n\nThe Navbar child component handles: logo display, navigation links (`LIST_OF_LINK`), cart badge (reads `cartStore`), account icon (reads `customerStore`), search functionality, and a mobile hamburger menu. It also has its own `COMPONENT_LIST` slot for product search results using CardProductName/CardProductVariants/CardProductPrice with `privateVarMap` for the product variable.\n\n### Announcements Child Component\n\nThe Announcements child component uses `IkasThemeSlider` for a rotating announcement bar. It has its own child component slot for individual Announcement items.\n\n### CookieBar Child Component\n\nThe CookieBar manages cookie consent with accept/decline actions and persists the choice to localStorage.\n\n### Footer Architecture\n\nThe serel Footer section uses `IkasComponentRenderer` with a `COMPONENT_LIST` filtered to **SocialMediaIcon** children:\n\n```tsx\nimport { IkasComponentRenderer } from \"@ikas/bp-storefront\";\nimport { Props } from \"./types\";\n\nexport function Footer({ components, backgroundColor, ...props }: Props) {\n return (\n <footer className=\"footer\" style={backgroundColor ? { backgroundColor } : undefined}>\n <div className=\"footer-inner\">\n {/* Logo, link columns, contact info */}\n <div className=\"footer-social\">\n <IkasComponentRenderer id=\"footer-components\" components={components} parentProps={props} />\n </div>\n {/* Copyright */}\n </div>\n </footer>\n );\n}\nexport default Footer;\n```\n\nConfig with `isFooter: true`:\n```json\n{\n \"id\": \"nb34u3yu-footer\",\n \"name\": \"Footer\",\n \"type\": \"section\",\n \"isFooter\": true,\n \"props\": [\n {\n \"name\": \"components\",\n \"type\": \"COMPONENT_LIST\",\n \"filteredComponentIds\": [\"nb34u3yu-social-media-icon\"]\n }\n ]\n}\n```\n\n### Key Patterns\n\n- Headers and footers use `IkasComponentRenderer` with `filteredComponentIds` for controlled child composition\n- `isHeader: true` / `isFooter: true` flags in config make them appear on all pages\n- Root exports are automatically reactive (cartStore/customerStore tracked by autorun)\n- Toast system lives in the Header for global accessibility\n- `parentProps` passes section data to child components\n- The Navbar child component itself nests additional child components via its own COMPONENT_LIST",
|
|
314
314
|
"tags": [
|
|
315
315
|
"header",
|
|
316
316
|
"footer",
|
|
@@ -343,7 +343,7 @@
|
|
|
343
343
|
"slider-overlay-patterns": {
|
|
344
344
|
"title": "Slider & Overlay Patterns (Serel Reference)",
|
|
345
345
|
"description": "Serel HeroSlider + HeroSliderItem pattern with IkasComponentRenderer, IkasThemeSlider for carousels, SliderArrow sub-component, IkasThemeOverlay, IkasThemeInfiniteScroller",
|
|
346
|
-
"content": "## Slider & Overlay Patterns (Serel Reference)\n\n### Serel HeroSlider + HeroSliderItem Pattern\n\nThe serel HeroSlider section uses `IkasComponentRenderer` to render `HeroSliderItem` child components inside an `IkasThemeSlider` carousel. This combines the component slot system with the slider API.\n\n**HeroSlider section:**\n```tsx\nimport { IkasComponentRenderer, IkasThemeSlider } from \"@ikas/bp-storefront\";\nimport SliderArrow from \"../../sub-components/SliderArrow\";\nimport { Props } from \"./types\";\n\nexport function HeroSlider({ components, backgroundColor, ...props }: Props) {\n return (\n <section className=\"hero-slider\" style={backgroundColor ? { backgroundColor } : undefined}>\n <IkasThemeSlider autoplay={true} autoplayInterval={5000} loop={true}>\n {(sliderProps) => {\n const { current, goTo, dotCount } = sliderProps;\n return (\n <div className=\"hero-slider-track\">\n <IkasComponentRenderer components={components} parentProps={{ ...props, current }} />\n <SliderArrow direction=\"prev\" onClick={() => goTo(current - 1)} />\n <SliderArrow direction=\"next\" onClick={() => goTo(current + 1)} />\n <div className=\"hero-slider-dots\">\n {Array.from({ length: dotCount }).map((_, i) => (\n <button key={i} className={i === current ? \"active\" : \"\"} onClick={() => goTo(i)} />\n ))}\n </div>\n </div>\n );\n }}\n </IkasThemeSlider>\n </section>\n );\n}\nexport default HeroSlider;\n```\n\n**Config:**\n```json\n{\n \"id\": \"nb34u3yu-hero-slider\",\n \"name\": \"HeroSlider\",\n \"type\": \"section\",\n \"props\": [\n {\n \"name\": \"components\",\n \"type\": \"COMPONENT_LIST\",\n \"filteredComponentIds\": [\"nb34u3yu-hero-slider-item\"]\n }\n ]\n}\n```\n\n**HeroSliderItem child component:** Each slide item receives props from the editor (IMAGE for background, TEXT for heading/subtitle, LINK for CTA button).\n\n### SliderArrow Sub-Component\n\nThe `SliderArrow` sub-component (in `src/sub-components/SliderArrow/`) renders prev/next navigation arrows with consistent styling across all slider sections.\n\n### IkasThemeSlider API\n\nRender function receives:\n\n| Prop | Type | Description |\n|------|------|-------------|\n| `current` | `number` | Currently visible slide index |\n| `goTo(index)` | `function` | Navigate to specific slide |\n| `dotCount` | `number` | Total number of dots/pages |\n| `itemCount` | `number` | Total number of items |\n\nConfiguration props: `autoplay`, `autoplayInterval`, `loop`.\n\n### IkasThemeOverlay\n\n`IkasThemeOverlay` is a state management type, NOT a JSX component:\n\n```typescript\ninterface IkasThemeOverlay {\n visible: boolean;\n show: () => void;\n hide: () => void;\n}\n```\n\nFor overlays, use `useState` with plain `<div>` elements and CSS `position: fixed; inset: 0;`. The serel theme uses the `useScrollLock` hook to prevent body scrolling when overlays are open.\n\n### IkasThemeInfiniteScroller\n\nUsed in the serel CategoryList section for infinite scroll product loading:\n\n```tsx\nimport { IkasThemeInfiniteScroller } from \"@ikas/bp-storefront\";\n\n<IkasThemeInfiniteScroller\n hasMore={hasProductListNextPage(productList)}\n onLoadMore={async () => { await getProductListNextPage(productList); }}\n>\n {products.map((product) => (\n <ProductCard key={product.id} product={product} />\n ))}\n</IkasThemeInfiniteScroller>\n```\n\nThe serel theme also provides a `useInfiniteScroll` custom hook as an alternative to the built-in component.\n\n### Common Serel Usage\n\n- **HeroSlider**: IkasThemeSlider + IkasComponentRenderer for editor-managed slides\n- **ProductSlider**: IkasThemeSlider for product card carousels\n- **Announcements**: IkasThemeSlider with autoplay for rotating announcement bar\n- **CategoryList**: IkasThemeInfiniteScroller or useInfiniteScroll hook\n- **Mobile menu, modals**: useState + div overlay + useScrollLock hook\n- **ImagePreviewModal**: Sub-component for full-screen image zoom in product gallery",
|
|
346
|
+
"content": "## Slider & Overlay Patterns (Serel Reference)\n\n### Serel HeroSlider + HeroSliderItem Pattern\n\nThe serel HeroSlider section uses `IkasComponentRenderer` to render `HeroSliderItem` child components inside an `IkasThemeSlider` carousel. This combines the component slot system with the slider API.\n\n**HeroSlider section:**\n```tsx\nimport { IkasComponentRenderer, IkasThemeSlider } from \"@ikas/bp-storefront\";\nimport SliderArrow from \"../../sub-components/SliderArrow\";\nimport { Props } from \"./types\";\n\nexport function HeroSlider({ components, backgroundColor, ...props }: Props) {\n return (\n <section className=\"hero-slider\" style={backgroundColor ? { backgroundColor } : undefined}>\n <IkasThemeSlider autoplay={true} autoplayInterval={5000} loop={true}>\n {(sliderProps) => {\n const { current, goTo, dotCount } = sliderProps;\n return (\n <div className=\"hero-slider-track\">\n <IkasComponentRenderer id=\"hero-slider-components\" components={components} parentProps={{ ...props, current }} />\n <SliderArrow direction=\"prev\" onClick={() => goTo(current - 1)} />\n <SliderArrow direction=\"next\" onClick={() => goTo(current + 1)} />\n <div className=\"hero-slider-dots\">\n {Array.from({ length: dotCount }).map((_, i) => (\n <button key={i} className={i === current ? \"active\" : \"\"} onClick={() => goTo(i)} />\n ))}\n </div>\n </div>\n );\n }}\n </IkasThemeSlider>\n </section>\n );\n}\nexport default HeroSlider;\n```\n\n**Config:**\n```json\n{\n \"id\": \"nb34u3yu-hero-slider\",\n \"name\": \"HeroSlider\",\n \"type\": \"section\",\n \"props\": [\n {\n \"name\": \"components\",\n \"type\": \"COMPONENT_LIST\",\n \"filteredComponentIds\": [\"nb34u3yu-hero-slider-item\"]\n }\n ]\n}\n```\n\n**HeroSliderItem child component:** Each slide item receives props from the editor (IMAGE for background, TEXT for heading/subtitle, LINK for CTA button).\n\n### SliderArrow Sub-Component\n\nThe `SliderArrow` sub-component (in `src/sub-components/SliderArrow/`) renders prev/next navigation arrows with consistent styling across all slider sections.\n\n### IkasThemeSlider API\n\nRender function receives:\n\n| Prop | Type | Description |\n|------|------|-------------|\n| `current` | `number` | Currently visible slide index |\n| `goTo(index)` | `function` | Navigate to specific slide |\n| `dotCount` | `number` | Total number of dots/pages |\n| `itemCount` | `number` | Total number of items |\n\nConfiguration props: `autoplay`, `autoplayInterval`, `loop`.\n\n### IkasThemeOverlay\n\n`IkasThemeOverlay` is a state management type, NOT a JSX component:\n\n```typescript\ninterface IkasThemeOverlay {\n visible: boolean;\n show: () => void;\n hide: () => void;\n}\n```\n\nFor overlays, use `useState` with plain `<div>` elements and CSS `position: fixed; inset: 0;`. The serel theme uses the `useScrollLock` hook to prevent body scrolling when overlays are open.\n\n### IkasThemeInfiniteScroller\n\nUsed in the serel CategoryList section for infinite scroll product loading:\n\n```tsx\nimport { IkasThemeInfiniteScroller } from \"@ikas/bp-storefront\";\n\n<IkasThemeInfiniteScroller\n hasMore={hasProductListNextPage(productList)}\n onLoadMore={async () => { await getProductListNextPage(productList); }}\n>\n {products.map((product) => (\n <ProductCard key={product.id} product={product} />\n ))}\n</IkasThemeInfiniteScroller>\n```\n\nThe serel theme also provides a `useInfiniteScroll` custom hook as an alternative to the built-in component.\n\n### Common Serel Usage\n\n- **HeroSlider**: IkasThemeSlider + IkasComponentRenderer for editor-managed slides\n- **ProductSlider**: IkasThemeSlider for product card carousels\n- **Announcements**: IkasThemeSlider with autoplay for rotating announcement bar\n- **CategoryList**: IkasThemeInfiniteScroller or useInfiniteScroll hook\n- **Mobile menu, modals**: useState + div overlay + useScrollLock hook\n- **ImagePreviewModal**: Sub-component for full-screen image zoom in product gallery",
|
|
347
347
|
"tags": [
|
|
348
348
|
"slider",
|
|
349
349
|
"carousel",
|
|
@@ -375,7 +375,7 @@
|
|
|
375
375
|
"navigation-patterns": {
|
|
376
376
|
"title": "Navigation & Routing Patterns",
|
|
377
377
|
"description": "Router.navigate, page navigation, href getters, breadcrumbs, and query parameters",
|
|
378
|
-
"content": "## Navigation & Routing Patterns\n\nikas provides a `Router` utility and various href getter functions for navigation.\n\n### Basic Navigation\n\n```tsx\nimport { Router } from \"@ikas/bp-storefront\";\n\n// Navigate to a URL\nRouter.navigate(\"/products\");\n\n// Navigate to a named page\nRouter.navigateToPage(\"LOGIN\");\nRouter.navigateToPage(\"REGISTER\");\nRouter.navigateToPage(\"FORGOT_PASSWORD\");\nRouter.navigateToPage(\"ACCOUNT\");\nRouter.navigateToPage(\"CART\");\nRouter.navigateToPage(\"CHECKOUT\");\n\n// Navigate with options\nRouter.navigateToPage(\"CATEGORY\", {\n queryParams: { sort: \"price_asc\" },\n shallow: false,\n newTab: false,\n});\n\n// Go back\nRouter.goBack();\n```\n\n### Page Type Constants\n\nAvailable page types for `navigateToPage()`:\n- `INDEX` — Home page\n- `CATEGORY` — Category listing\n- `PRODUCT_DETAIL` — Product detail\n- `BLOG` — Blog listing\n- `BLOG` — Blog post detail\n- `CART` — Shopping cart\n- `CHECKOUT` — Checkout flow\n- `LOGIN` — Login page\n- `REGISTER` — Registration page\n- `FORGOT_PASSWORD` — Password recovery\n- `ACCOUNT` — Customer account\n- `SEARCH` — Search results\n- `CUSTOM` — Custom pages\n\n### Href Getter Functions\n\nThese return URL strings for use in `<a href>` tags:\n\n```tsx\nimport {\n getSelectedProductVariantHref,\n getIkasCategoryHref,\n getIkasOrderHref,\n getIkasBlogHref,\n getIkasBrandHref,\n} from \"@ikas/bp-storefront\";\n\n// Product link\n<a href={getSelectedProductVariantHref(product)}>{product.name}</a>\n\n// Category link\n<a href={getIkasCategoryHref(category)}>{category.name}</a>\n\n// Order link\n<a href={getIkasOrderHref(order)}>Order #{order.orderNumber}</a>\n\n// Blog link\n<a href={getIkasBlogHref(blog)}>{blog.title}</a>\n\n// Brand link\n<a href={getIkasBrandHref(brand)}>{brand.name}</a>\n```\n\n### Breadcrumbs\n\n```tsx\nimport {\n getCategoryPath,\n getProductCategoryPath,\n getIkasCategoryHref,\n} from \"@ikas/bp-storefront\";\n\n// For category pages\nconst categoryPath = getCategoryPath(category);\n\n// For product pages\nconst productPath = getProductCategoryPath(product);\n\n<nav className=\"breadcrumbs\">\n <a href=\"/\">Home</a>\n {categoryPath?.map((cat, i) => (\n <span key={cat.id}>\n <span className=\"separator\">/</span>\n <a href={getIkasCategoryHref(cat)}>{cat.name}</a>\n </span>\n ))}\n</nav>\n```\n\n### Using Links vs Navigation\n\n- Use `<a href={getXxxHref(...)}>` for standard links (SEO-friendly, right-click works)\n- Use `Router.navigate()` for programmatic navigation after form submission or actions\n- Use `Router.navigateToPage()` for navigating to known page types\n- Use `Router.goBack()` for back buttons",
|
|
378
|
+
"content": "## Navigation & Routing Patterns\n\nikas provides a `Router` utility and various href getter functions for navigation.\n\n### Basic Navigation\n\n```tsx\nimport { Router } from \"@ikas/bp-storefront\";\n\n// Navigate to a URL\nRouter.navigate(\"/products\");\n\n// Navigate with options\nRouter.navigate(\"/products\", true); // shallow navigation (no full page reload)\nRouter.navigate(\"/products\", false, true); // open in new tab\n// Signature: Router.navigate(path: string, shallow?: boolean, openInNewTab?: boolean)\n\n// Navigate to a named page\nRouter.navigateToPage(\"LOGIN\");\nRouter.navigateToPage(\"REGISTER\");\nRouter.navigateToPage(\"FORGOT_PASSWORD\");\nRouter.navigateToPage(\"ACCOUNT\");\nRouter.navigateToPage(\"CART\");\nRouter.navigateToPage(\"CHECKOUT\");\n\n// Navigate with options\nRouter.navigateToPage(\"CATEGORY\", {\n queryParams: { sort: \"price_asc\" },\n shallow: false,\n newTab: false,\n});\n\n// Go back\nRouter.goBack();\n```\n\n### Page Type Constants\n\nAvailable page types for `navigateToPage()`:\n- `INDEX` — Home page\n- `CATEGORY` — Category listing\n- `PRODUCT_DETAIL` — Product detail\n- `BLOG` — Blog listing\n- `BLOG` — Blog post detail\n- `CART` — Shopping cart\n- `CHECKOUT` — Checkout flow\n- `LOGIN` — Login page\n- `REGISTER` — Registration page\n- `FORGOT_PASSWORD` — Password recovery\n- `ACCOUNT` — Customer account\n- `SEARCH` — Search results\n- `CUSTOM` — Custom pages\n\n### Href Getter Functions\n\nThese return URL strings for use in `<a href>` tags:\n\n```tsx\nimport {\n getSelectedProductVariantHref,\n getIkasCategoryHref,\n getIkasOrderHref,\n getIkasBlogHref,\n getIkasBrandHref,\n} from \"@ikas/bp-storefront\";\n\n// Product link\n<a href={getSelectedProductVariantHref(product)}>{product.name}</a>\n\n// Category link\n<a href={getIkasCategoryHref(category)}>{category.name}</a>\n\n// Order link\n<a href={getIkasOrderHref(order)}>Order #{order.orderNumber}</a>\n\n// Blog link\n<a href={getIkasBlogHref(blog)}>{blog.title}</a>\n\n// Brand link\n<a href={getIkasBrandHref(brand)}>{brand.name}</a>\n```\n\n### Breadcrumbs\n\n```tsx\nimport {\n getCategoryPath,\n getProductCategoryPath,\n getIkasCategoryHref,\n} from \"@ikas/bp-storefront\";\n\n// For category pages\nconst categoryPath = getCategoryPath(category);\n\n// For product pages\nconst productPath = getProductCategoryPath(product);\n\n<nav className=\"breadcrumbs\">\n <a href=\"/\">Home</a>\n {categoryPath?.map((cat, i) => (\n <span key={cat.id}>\n <span className=\"separator\">/</span>\n <a href={getIkasCategoryHref(cat)}>{cat.name}</a>\n </span>\n ))}\n</nav>\n```\n\n### Using Links vs Navigation\n\n- Use `<a href={getXxxHref(...)}>` for standard links (SEO-friendly, right-click works)\n- Use `Router.navigate()` for programmatic navigation after form submission or actions\n- Use `Router.navigateToPage()` for navigating to known page types\n- Use `Router.goBack()` for back buttons",
|
|
379
379
|
"tags": [
|
|
380
380
|
"navigation",
|
|
381
381
|
"router",
|
|
@@ -421,7 +421,7 @@
|
|
|
421
421
|
"component-renderer-patterns": {
|
|
422
422
|
"title": "IkasComponentRenderer — Component Slot Architecture",
|
|
423
423
|
"description": "How sections declare COMPONENT_LIST slots, filteredComponentIds to restrict children, parentProps for data passing, and multiple slot patterns from the serel theme",
|
|
424
|
-
"content": "## IkasComponentRenderer — Component Slot Architecture\n\n`IkasComponentRenderer` is the core mechanism for sections to render child components. It enables store owners to add, remove, and reorder child components within a section from the editor UI.\n\n### Basic Usage\n\nA section declares a `COMPONENT_LIST` prop, then renders it with `IkasComponentRenderer`:\n\n```tsx\nimport { IkasComponentRenderer } from \"@ikas/bp-storefront\";\nimport { Props } from \"./types\";\n\nexport function MySection({ components, backgroundColor, ...props }: Props) {\n return (\n <section style={backgroundColor ? { backgroundColor } : undefined}>\n <IkasComponentRenderer components={components} parentProps={props} />\n </section>\n );\n}\nexport default MySection;\n```\n\n**Config:**\n```json\n{\n \"name\": \"components\",\n \"displayName\": \"Components\",\n \"type\": \"COMPONENT_LIST\"\n}\n```\n\n### filteredComponentIds — Restricting Allowed Children\n\nBy default, any child component can be placed in a COMPONENT_LIST slot. Use `filteredComponentIds` to restrict which components are allowed:\n\n```json\n{\n \"name\": \"components\",\n \"type\": \"COMPONENT_LIST\",\n \"filteredComponentIds\": [\n \"nb34u3yu-navbar\",\n \"nb34u3yu-announcements\",\n \"nb34u3yu-cookie-bar\"\n ]\n}\n```\n\nThis ensures only Navbar, Announcements, and CookieBar can be placed in the Header's component slot.\n\n### parentProps — Passing Data to Children\n\nAlways spread remaining props into `parentProps` so child components can access section-level data:\n\n```tsx\nexport function ProductSlider({ components, product, ...props }: Props) {\n return (\n <div>\n <IkasComponentRenderer components={components} parentProps={props} />\n </div>\n );\n}\n```\n\nChild components automatically receive data from `parentProps`. Combined with `privateVarMap`, this is how sections expose data (like a product object) to their children.\n\n### Multiple COMPONENT_LIST Slots\n\nSections can have multiple slots for different layout regions. The serel ProductDetail section uses two:\n\n```json\n{\n \"props\": [\n {\n \"name\": \"components\",\n \"type\": \"COMPONENT_LIST\",\n \"filteredComponentIds\": [\"...12 product detail children...\"]\n },\n {\n \"name\": \"bottomComponents\",\n \"type\": \"COMPONENT_LIST\",\n \"filteredComponentIds\": [\"nb34u3yu-product-detail-description\"]\n }\n ]\n}\n```\n\n```tsx\nexport function ProductDetail({ product, components, bottomComponents, ...props }: Props) {\n return (\n <section>\n <div className=\"detail-side-panel\">\n <IkasComponentRenderer components={components} parentProps={props} />\n </div>\n <div className=\"detail-bottom\">\n <IkasComponentRenderer components={bottomComponents} parentProps={props} />\n </div>\n </section>\n );\n}\n```\n\n### Serel Examples of Section-to-Child Relationships\n\n| Section | COMPONENT_LIST children | Notes |\n|---------|------------------------|-------|\n| Header | Navbar, Announcements, CookieBar | `isHeader: true` |\n| HeroSlider | HeroSliderItem | Inside IkasThemeSlider |\n| CategoryImages | CategoryImageItem | Grid layout |\n| Footer | SocialMediaIcon | `isFooter: true` |\n| ProductSlider | CardProductName, CardProductVariants, CardProductPrice | Uses `privateVarMap` for product |\n| CategoryList | CardProductName, CardProductVariants, CardProductPrice | Uses `privateVarMap` for product |\n| ProductDetail | 12 children in 2 slots | Most complex section |\n| Features | FeatureItem | Simple repeating items |\n| AccountInfo | 5 account tab children | Dashboard tabs |\n\n### Key Rules\n\n1. Always pass `parentProps={props}` (spread remaining props after destructuring COMPONENT_LIST)\n2. Cast if needed: `components={components as any[]}`\n3. `filteredComponentIds` uses the full component ID (project prefix + kebab-case name)\n4. Multiple COMPONENT_LIST slots enable multi-region layouts\n5. Sections without COMPONENT_LIST (CartPage, Login, etc.) compose sub-components directly",
|
|
424
|
+
"content": "## IkasComponentRenderer — Component Slot Architecture\n\n`IkasComponentRenderer` is the core mechanism for sections to render child components. It enables store owners to add, remove, and reorder child components within a section from the editor UI.\n\n### Basic Usage\n\nA section declares a `COMPONENT_LIST` prop, then renders it with `IkasComponentRenderer`:\n\n```tsx\nimport { IkasComponentRenderer } from \"@ikas/bp-storefront\";\nimport { Props } from \"./types\";\n\nexport function MySection({ components, backgroundColor, ...props }: Props) {\n return (\n <section style={backgroundColor ? { backgroundColor } : undefined}>\n <IkasComponentRenderer id=\"section-components\" components={components} parentProps={props} />\n </section>\n );\n}\nexport default MySection;\n```\n\n**Config:**\n```json\n{\n \"name\": \"components\",\n \"displayName\": \"Components\",\n \"type\": \"COMPONENT_LIST\"\n}\n```\n\n### filteredComponentIds — Restricting Allowed Children\n\nBy default, any child component can be placed in a COMPONENT_LIST slot. Use `filteredComponentIds` to restrict which components are allowed:\n\n```json\n{\n \"name\": \"components\",\n \"type\": \"COMPONENT_LIST\",\n \"filteredComponentIds\": [\n \"nb34u3yu-navbar\",\n \"nb34u3yu-announcements\",\n \"nb34u3yu-cookie-bar\"\n ]\n}\n```\n\nThis ensures only Navbar, Announcements, and CookieBar can be placed in the Header's component slot.\n\n### parentProps — Passing Data to Children\n\nAlways spread remaining props into `parentProps` so child components can access section-level data:\n\n```tsx\nexport function ProductSlider({ components, product, ...props }: Props) {\n return (\n <div>\n <IkasComponentRenderer id=\"product-slider-components\" components={components} parentProps={props} />\n </div>\n );\n}\n```\n\nChild components automatically receive data from `parentProps`. Combined with `privateVarMap`, this is how sections expose data (like a product object) to their children.\n\n### Multiple COMPONENT_LIST Slots\n\nSections can have multiple slots for different layout regions. The serel ProductDetail section uses two:\n\n```json\n{\n \"props\": [\n {\n \"name\": \"components\",\n \"type\": \"COMPONENT_LIST\",\n \"filteredComponentIds\": [\"...12 product detail children...\"]\n },\n {\n \"name\": \"bottomComponents\",\n \"type\": \"COMPONENT_LIST\",\n \"filteredComponentIds\": [\"nb34u3yu-product-detail-description\"]\n }\n ]\n}\n```\n\n```tsx\nexport function ProductDetail({ product, components, bottomComponents, ...props }: Props) {\n return (\n <section>\n <div className=\"detail-side-panel\">\n <IkasComponentRenderer id=\"detail-components\" components={components} parentProps={props} />\n </div>\n <div className=\"detail-bottom\">\n <IkasComponentRenderer id=\"detail-bottom-components\" components={bottomComponents} parentProps={props} />\n </div>\n </section>\n );\n}\n```\n\n### Serel Examples of Section-to-Child Relationships\n\n| Section | COMPONENT_LIST children | Notes |\n|---------|------------------------|-------|\n| Header | Navbar, Announcements, CookieBar | `isHeader: true` |\n| HeroSlider | HeroSliderItem | Inside IkasThemeSlider |\n| CategoryImages | CategoryImageItem | Grid layout |\n| Footer | SocialMediaIcon | `isFooter: true` |\n| ProductSlider | CardProductName, CardProductVariants, CardProductPrice | Uses `privateVarMap` for product |\n| CategoryList | CardProductName, CardProductVariants, CardProductPrice | Uses `privateVarMap` for product |\n| ProductDetail | 12 children in 2 slots | Most complex section |\n| Features | FeatureItem | Simple repeating items |\n| AccountInfo | 5 account tab children | Dashboard tabs |\n\n### Key Rules\n\n1. Always pass `parentProps={props}` (spread remaining props after destructuring COMPONENT_LIST)\n2. Cast if needed: `components={components as any[]}`\n3. `filteredComponentIds` uses the full component ID (project prefix + kebab-case name)\n4. Multiple COMPONENT_LIST slots enable multi-region layouts\n5. Sections without COMPONENT_LIST (CartPage, Login, etc.) compose sub-components directly",
|
|
425
425
|
"tags": [
|
|
426
426
|
"IkasComponentRenderer",
|
|
427
427
|
"COMPONENT_LIST",
|