### Installing Easyblocks Editor Core Packages (Bash) Source: https://github.com/easyblockshq/easyblocks/blob/main/docs/getting-started.md This command installs the `@easyblocks/editor` and `@easyblocks/core` npm packages, which are essential dependencies for setting up and running the Easyblocks content editor in your project. ```bash npm install @easyblocks/editor @easyblocks/core ``` -------------------------------- ### Installing Project Dependencies with npm Source: https://github.com/easyblockshq/easyblocks/blob/main/apps/page-builder-demo/README.md This command installs all required project dependencies listed in the 'package.json' file. It is a standard first step after cloning a Node.js project to ensure all necessary packages are available for development and execution. ```Shell npm install ``` -------------------------------- ### Configuring Easyblocks Editor with Custom Components and Tokens (TypeScript) Source: https://github.com/easyblockshq/easyblocks/blob/main/docs/getting-started.md This TypeScript code defines the `easyblocksConfig` object, which sets up the Easyblocks Editor with a backend, locales, custom components (like `DummyBanner` with its schema and styles), and design tokens (colors, fonts, space). It also includes the React component `DummyBanner` and the main `EasyblocksEditorPage` component that renders the editor. ```typescript import { EasyblocksEditor } from "@easyblocks/editor"; import { Config, EasyblocksBackend } from "@easyblocks/core"; import { ReactElement } from "react"; const easyblocksConfig: Config = { backend: new EasyblocksBackend({ accessToken: "<<< your access token >>>", // read below how to aquire access token }), locales: [ { code: "en-US", isDefault: true, }, { code: "de-DE", fallback: "en-US", }, ], components: [ { id: "DummyBanner", label: "DummyBanner", schema: [ { prop: "backgroundColor", label: "Background Color", type: "color", }, { prop: "padding", label: "Pading", type: "space", }, { prop: "Title", type: "component", required: true, accepts: ["@easyblocks/rich-text"], }, ], styles: ({ values }) => { return { styled: { Root: { backgroundColor: values.backgroundColor, padding: values.padding, }, }, }; }, }, ], tokens: { colors: [ { id: "black", label: "Black", value: "#000000", isDefault: true, }, { id: "white", label: "White", value: "#ffffff", }, { id: "coral", label: "Coral", value: "#ff7f50", }, ], fonts: [ { id: "body", label: "Body", value: { fontSize: 18, lineHeight: 1.8, fontFamily: "sans-serif", }, isDefault: true, }, { id: "heading", label: "Heading", value: { fontSize: 24, fontFamily: "sans-serif", lineHeight: 1.2, fontWeight: 700, }, }, ], space: [ { id: "0", label: "0", value: "0px", isDefault: true, }, { id: "1", label: "1", value: "1px", }, { id: "2", label: "2", value: "2px", }, { id: "4", label: "4", value: "4px", }, { id: "6", label: "6", value: "6px", }, { id: "8", label: "8", value: "8px", }, { id: "12", label: "12", value: "12px", }, { id: "16", label: "16", value: "16px", }, { id: "24", label: "24", value: "24px", }, { id: "32", label: "32", value: "32px", }, { id: "48", label: "48", value: "48px", }, { id: "64", label: "64", value: "64px", }, { id: "96", label: "96", value: "96px", }, { id: "128", label: "128", value: "128px", }, { id: "160", label: "160", value: "160px", } ], }, hideCloseButton: true, }; export function DummyBanner(props: { Root: ReactElement; Title: ReactElement; }) { const { Root, Title } = props; return ( ); } export default function EasyblocksEditorPage() { return ( ); } ``` -------------------------------- ### Running Development Server in Next.js (Bash) Source: https://github.com/easyblockshq/easyblocks/blob/main/apps/design-system-app/README.md This snippet provides commands to start the development server for a Next.js application. It supports `npm`, `yarn`, and `pnpm` package managers, allowing developers to choose their preferred tool. The server typically runs on `http://localhost:3000` and auto-updates on file changes. ```bash npm run dev # or yarn dev # or pnpm dev ``` -------------------------------- ### Running Development Server with npm Source: https://github.com/easyblockshq/easyblocks/blob/main/apps/page-builder-demo/README.md This command initiates the local development server, typically configured via scripts in the 'package.json' file. It enables features like hot-reloading and provides a local environment for testing and developing the application. ```Shell npm run dev ``` -------------------------------- ### Installing reduce-css-calc via npm Source: https://github.com/easyblockshq/easyblocks/blob/main/packages/reduce-css-calc/README.md This command installs the 'reduce-css-calc' package from npm, making it available for use in your project as a dependency. ```console npm install reduce-css-calc ``` -------------------------------- ### Setting Up Development Environment for reduce-css-calc Source: https://github.com/easyblockshq/easyblocks/blob/main/packages/reduce-css-calc/README.md This sequence of commands outlines the steps to set up the development environment for 'reduce-css-calc', including cloning the repository, creating a new branch, installing dependencies, and running tests, which is essential for contributing bug fixes or new features. ```console git clone https://github.com/MoOx/reduce-css-calc.git git checkout -b patch-1 npm install npm test ``` -------------------------------- ### Defining Custom Backend Interface for Easyblocks in TypeScript Source: https://github.com/easyblockshq/easyblocks/blob/main/docs/essentials/backend.md This TypeScript interface defines the contract for a custom Easyblocks backend service. It specifies the required methods for managing documents (get, create, update) and templates (get, getAll, create, update, delete), along with their respective payload types and return promises. This interface ensures compatibility when implementing a custom backend. ```TypeScript export type Backend = { documents: { get: (payload: { id: string; locale?: string }) => Promise; create: (payload: Omit) => Promise; update: (payload: Omit) => Promise; }; templates: { get(payload: { id: string }): Promise; getAll: () => Promise; create: (payload: { label: string; entry: NoCodeComponentEntry; width?: number; widthAuto?: boolean; }) => Promise; update: (payload: { id: string; label: string; }) => Promise>; delete: (payload: { id: string }) => Promise; }; }; export type Document = { id: string; version: number; entry: NoCodeComponentEntry; }; export type UserDefinedTemplate = { id: string; label: string; thumbnail?: string; thumbnailLabel?: string; entry: NoCodeComponentEntry; isUserDefined: true; width?: number; widthAuto?: boolean; }; ``` -------------------------------- ### Example No-Code Entry JSON Structure Source: https://github.com/easyblockshq/easyblocks/blob/main/docs/essentials/no-code-components/schema.md This snippet illustrates a complete JSON representation of a No-Code Entry, showcasing how visual configurations are stored. It includes various property types such as labels, icons, colors, spacing, and font settings, demonstrating the nested structure and use of responsive values. ```JSON { "Action": [], "variant": "label", "label": { "id": "local.4e69bfb6-45f2-4595-9360-351445cdfbc8", "value": { "en-US": "Click me" }, "widgetId": "@easyblocks/local-text" }, "icon": { "value": "", "widgetId": "@easyblocks/icon" }, "color": { "$res": true, "xl": { "value": "#252525", "tokenId": "grey_05", "widgetId": "@easyblocks/color" } }, "minHeight": { "$res": true, "xl": "42" }, "minWidth": { "$res": true, "xl": "100" }, "horizontalPadding": { "$res": true, "xl": { "value": "16px", "tokenId": "16", "widgetId": "@easyblocks/space" } }, "gap": { "$res": true, "xl": { "value": "6px", "tokenId": "6", "widgetId": "@easyblocks/space" } }, "cornerMode": { "$res": true, "xl": "custom" }, "cornerRadius": { "$res": true, "xl": "12" }, "font": { "$res": true, "xl": { "value": { "fontSize": 13, "lineHeight": 1.8, "fontFamily": "test-soehne-mono" }, "tokenId": "body2" } }, "underline": "off", "underlineOffset": { "$res": true, "xl": "1" }, "iconSize": { "$res": true, "xl": "24" }, "hasBackground": true, "backgroundColor": { "$res": true, "xl": { "value": "#f9f8f3", "tokenId": "grey_01", "widgetId": "@easyblocks/color" } }, "hasBorder": false, "borderWidth": { "$res": true, "xl": "1" }, "borderColor": { "$res": true, "xl": { "value": "#000000", "widgetId": "@easyblocks/color" } }, "boxShadow": { "$res": true, "xl": { "value": "none", "tokenId": "none" } } } ``` -------------------------------- ### Example of Stored No-Code Entry Data (JSON) Source: https://github.com/easyblockshq/easyblocks/blob/main/docs/essentials/external-data.md This JSON object illustrates how product data is stored within a No-Code Entry. Only the unique `id` of the selected product and the `widgetId` are persisted, with the full product details being dynamically provided at runtime. ```json { "product": { "id": "3", "widgetId": "product" } } ``` -------------------------------- ### Configuring Component Field Acceptance by Type - JavaScript Source: https://github.com/easyblockshq/easyblocks/blob/main/docs/essentials/no-code-components/schema.md This example illustrates how to use the `type` property of components to group them and then configure a `component` field to accept all components sharing that specific `type` value, such as 'section'. ```javascript // Section1 definition { id: "Section1", type: "section", schema: [...] } // Section2 definition { id: "Section2", type: "section", schema: [...] } // Component field of "section" type { prop: "Section", type: "component", accepts: ["section"] } ``` -------------------------------- ### Example of EditingInfo Object Structure Source: https://github.com/easyblockshq/easyblocks/blob/main/docs/essentials/no-code-components/editing-function.md This JSON snippet illustrates the structure of the `editingInfo` input argument provided to the `editing` function. It contains details about component fields, including their path, type, visibility, group, and label, as well as information about nested components. ```json { "fields": [ { "path": "backgroundColor", "type": "field", "visible": true, "group": "Properties", "label": "Background Color" }, { "path": "hasBorder", "type": "field", "visible": true, "group": "Properties", "label": "Has Border?" }, { "path": "padding", "type": "field", "visible": true, "group": "Properties", "label": "Pading" }, { "path": "gap", "type": "field", "visible": true, "group": "Properties", "label": "Gap" }, { "path": "buttonsGap", "type": "field", "visible": true, "group": "Properties", "label": "Buttons gap" }, { "path": "Title", "type": "field", "visible": false, "group": "Properties", "label": "Title" } ], "components": { "Title": { "fields": [] }, "Buttons": [] } } ``` -------------------------------- ### Defining Token Scales in Easyblocks Configuration Source: https://github.com/easyblockshq/easyblocks/blob/main/docs/essentials/configuration.md This TypeScript snippet demonstrates how to configure various token scales within the Easyblocks `Config.tokens` property. It includes examples for defining color palettes, spacing units (including responsive values using `vw` units), font styles with responsive breakpoints, and SVG icons. Each token has an `id`, `label`, and a `value` which can be a simple string, a number, or a complex object for responsive or structured values. ```typescript export const config: Config = { // ..., tokens: { colors: [ { id: "grey_05", label: "Dark", value: "#252525" }, { id: "grey_01", label: "Light", value: "#f9f8f3" }, { id: "beige_01", label: "Beige", value: "#f1f0ea" }, { id: "yellow", label: "Lemonade Yellow", value: "#FCF0C5" }, { id: "golden-yellow", label: "Golden Yellow", value: "#FCF0C5" }, { id: "lavender", label: "Lavender", value: "#E1E2ED" }, { id: "olive", label: "Olive", value: "#A9A886" } ], space: [ { id: "0", label: "0", value: "0px" }, { id: "1", label: "1", value: "1px" }, { id: "2", label: "2", value: "2px" }, { id: "4", label: "4", value: "4px" }, { id: "6", label: "6", value: "6px" }, { id: "8", label: "8", value: "8px" }, { id: "12", label: "12", value: "12px" }, { id: "16", label: "16", value: "16px" }, { id: "24", label: "24", value: "24px" }, { id: "32", label: "32", value: "32px" }, { id: "48", label: "48", value: "48px" }, { id: "64", label: "64", value: "64px" }, { id: "96", label: "96", value: "96px" }, { id: "128", label: "128", value: "128px" }, { id: "160", label: "160", value: "160px" }, { id: "containerMargin.standard", label: "Standard", value: { // responsive value $res: true, md: "5vw", // vw units are allowed for "space" type lg: "8vw" } }, { id: "containerMargin.large", label: "Large", value: { // repsonsive value $res: true, xs: "5vw", md: "8vw", lg: "12vw" } } ], fonts: [ { id: "body", label: "Body", value: { fontSize: 20, lineHeight: 1.8, fontFamily: "test-soehne-mono" } }, { id: "body2", label: "Body small", value: { fontSize: 13, lineHeight: 1.8, fontFamily: "test-soehne-mono" } }, { id: "heading1", label: "Heading 1", value: { $res: true, sm: { fontSize: 36, fontFamily: "test-national-2", lineHeight: 1.2, fontWeight: 700 }, md: { fontSize: 48, fontFamily: "test-national-2", lineHeight: 1.2, fontWeight: 700 } } }, { id: "heading2", label: "Heading 2", value: { $res: true, sm: { fontFamily: "test-national-2", fontSize: 24, lineHeight: 1.2, fontWeight: 700 }, md: { fontFamily: "test-national-2", fontSize: 36, lineHeight: 1.2, fontWeight: 700 } } } ], icons: [ { id: "arrowLeft", label: "Arrow left", value: "" }, { id: "arrowRight", label: "Arrow right", value: "" }, { id: "play", label: "Play", value: "" }, { id: "pause", label: "Pause", ``` -------------------------------- ### Defining Custom Types in Easyblocks (TypeScript) Source: https://github.com/easyblockshq/easyblocks/blob/main/docs/essentials/configuration.md This snippet illustrates how to define custom types for referencing external data within the `types` property of the Easyblocks `Config`. It shows an example of a 'shopify.product' type, which can include associated widgets for data presentation. ```TypeScript import type { Config } from '@easyblocks/core'; const config: Config = { ..., types: { "shopify.product": { widgets: [ /* widgets */ ] } } }; ``` -------------------------------- ### Implementing Custom Product Data Fetcher (TSX) Source: https://github.com/easyblockshq/easyblocks/blob/main/docs/essentials/external-data.md This comprehensive example shows a full implementation of the `onExternalDataChange` callback. It filters for 'product' type references, maps them to actual product data from a local array, handles cases where products are not found by reporting an error, and updates the `externalDataValues` state with the resolved data. ```tsx const products = [ { id: "1", title: "Product 1", price: 25.0, }, { id: "2", title: "Product 2", price: 10.0, }, { id: "3", title: "Product 3", price: 50.0, }, { id: "4", title: "Product 4", price: 150.0, }, ]; const [externalDataValues, setExternalDataValues] = useState( {} ); { // (1) const productReferences = Object.entries(externals) .filter(([, reference]) => { // Why do we check `widgetId` instead of `type`? // We could rely on `type` field, but we could have multiple widgets for // the same type and they could be resolved differently. // Why do we check for empty `id`? // Changing from non empty value to empty is also a change return reference.widgetId === 'product' && reference.id !== null; }); const resolvedProducts = Object.fromEntries( productReferences.map(([id, reference]) => { // (2) const product = products.find(p => p.id === reference.id); // (3) if (!product) { // If product wasn't resolved/found, we report an error return [id, { error: new Error( `Product with id ${reference.id} was not found` )}] } // (3) If found, return it as resolved external data return [id, { type: 'product', value: product }]; })); // We inform editor about change by updating `externalDataValues` state variable // with new data setExternalDataValues({ ...externalDataValues, ...resolvedProducts }); }} /> ``` -------------------------------- ### Defining a Basic Component Collection for a Grid in JavaScript Source: https://github.com/easyblockshq/easyblocks/blob/main/docs/essentials/no-code-components/schema.md This snippet demonstrates a basic `component-collection` definition for a `Cards` property in Easyblocks. It configures a simple CSS Grid layout where each card occupies one row and column, setting `display: grid` and `gridTemplateColumns: repeat(4, 1fr)` within the `styles` function. This serves as a foundational example before introducing dynamic sizing. ```javascript { prop: "Cards", type: "component-collection", accepts: ["MyNoCodeCardComponent"], styles() { return { styled: { CardsGrid: { display: "grid"; gridTemplateColumns: repeat(4, 1fr); } } } } } ``` -------------------------------- ### Defining Required and Optional Component Fields within a Schema - JavaScript Source: https://github.com/easyblockshq/easyblocks/blob/main/docs/essentials/no-code-components/schema.md This example demonstrates how to define a component schema where some nested `component` fields are `required` (e.g., 'Heading') while others are optional (e.g., 'Subheading'), using the `required: true` property. ```javascript { id: "Card", schema: [ { prop: "Heading", type: "component", accepts: ["@easyblocks/rich-text"], required: true }, { prop: "Subheading", type: "component", accepts: ["@easyblocks/rich-text"] } ] } ``` -------------------------------- ### Configuring Locales in Easyblocks (TypeScript) Source: https://github.com/easyblockshq/easyblocks/blob/main/docs/essentials/configuration.md This snippet shows how to define available locales using the `locales` property in the Easyblocks `Config`. It includes examples for a default locale (`en-US`) and another locale (`de-DE`) with a specified fallback, emphasizing that one locale must always be set as default. ```TypeScript import type { Config } from '@easyblocks/core'; const config: Config = { ..., locales: [ { code: 'en-US', isDefault: true }, { code: 'de-DE', fallback: 'en-US' } ] }; ``` -------------------------------- ### Configuring Dynamic Card Sizing with `itemFields` in Easyblocks JavaScript Source: https://github.com/easyblockshq/easyblocks/blob/main/docs/essentials/no-code-components/schema.md This example extends the `component-collection` by introducing `itemFields` to allow individual `Card` components to define their `size`. The `size` field is a `select` type with options like '1x1', '2x1', '2x2'. The `styles` function then accesses these `cardSizes` from the `values` prop, enabling the parent component to dynamically calculate and apply the final grid layout based on the children's specified sizes. ```javascript { prop: "Cards", type: "component-collection", accepts: ["MyNoCodeCardComponent"], itemFields: [ { prop: "size", type: "select", label: "Size", params: { options: ["1x1", "2x1", "2x2"] } } ], styles({ values: { Cards } }) { // Now we have full access to each size of card const cardSizes = Cards.map(Card => Card.size); return { styled: { CardsGrid: { display: "grid"; // Calculate the final layout based on card sizes } } } } } ``` -------------------------------- ### Using reduceCSSCalc to Reduce CSS Calc Expressions Source: https://github.com/easyblockshq/easyblocks/blob/main/packages/reduce-css-calc/README.md This snippet demonstrates how to use the 'reduceCSSCalc' function to simplify CSS 'calc()' expressions. It shows various examples including basic arithmetic, precision control, unit handling, percentage calculations, and nested 'calc()' functions. The function takes a string containing a 'calc()' expression and an optional precision parameter, returning the reduced string. ```javascript var reduceCSSCalc = require("reduce-css-calc"); reduceCSSCalc("calc(1 + 1)"); // 2 reduceCSSCalc("calc((6 / 2) - (4 * 2) + 1)"); // -4 reduceCSSCalc("calc(1/3)"); // 0.33333 reduceCSSCalc("calc(1/3)", 10); // 0.3333333333 reduceCSSCalc("calc(3rem * 2 - 1rem)"); // 5rem reduceCSSCalc("calc(2 * 50%)"); // 100% reduceCSSCalc("calc(120% * 50%)"); // 60% reduceCSSCalc("a calc(1 + 1) b calc(1 - 1) c"); // a 2 b 0 c reduceCSSCalc("calc(calc(calc(1rem * 0.75) * 1.5) - 1rem)"); // 0.125rem reduceCSSCalc("calc(calc(calc(1rem * 0.75) * 1.5) - 1px)"); // calc(1.125rem - 1px) reduceCSSCalc("-moz-calc(100px / 2)"); // 50px reduceCSSCalc("-moz-calc(50% - 2em)"); // -moz-calc(50% - 2em) ``` -------------------------------- ### Passing Parameters to Subcomponents via styles function (TypeScript) Source: https://github.com/easyblockshq/easyblocks/blob/main/docs/essentials/no-code-components/styles-function.md This example illustrates how a parent component can pass parameters to its subcomponents using the `components` property within its `styles` function. The child component can then access these passed parameters via the `params` object in its own `styles` function, enabling communication and configuration between nested components. ```TypeScript // Parent component const parentComponentDefinition: NoCodeComponentDefinition = { // ... styles: ({ values }) => { return { styled: { // ... }, components: { ChildComponent: { passedParameter: 10, }, }, }; }, // ... }; // Child component const childComponentDefinition: NoCodeComponentDefinition = { // ... styles: ({ values, params }) => { console.log(params.passedParameter); // 10 return {}; }, }; ``` -------------------------------- ### Configuring Webpack Module Resolution in Next.js for Monorepo Source: https://github.com/easyblockshq/easyblocks/blob/main/apps/README.md This Webpack configuration snippet for a Next.js application modifies the module resolution order. It prepends the application's `node_modules` directory to Webpack's module search paths, ensuring that the app's own dependencies are prioritized. This helps resolve issues where internal packages might otherwise cause duplicate installations of shared 3rd party dependencies like React, preventing context and dispatcher bugs. ```JavaScript const nextConfig = { webpack: (config) => { // This will tell Webpack to first look for modules within the `node_modules` directory of an app config.resolve.modules.unshift(path.resolve(__dirname, "node_modules")); return config; }, }; ``` -------------------------------- ### Configuring Easyblocks with Cloud Backend in TypeScript Source: https://github.com/easyblockshq/easyblocks/blob/main/docs/essentials/backend.md This snippet demonstrates how to configure the Easyblocks frontend to connect to the default cloud backend service using an access token. It initializes `EasyblocksBackend` with the provided `accessToken` as part of the global `Config` object. The access token is a prerequisite for authentication with the cloud service. ```TypeScript import { Config, EasyblocksBackend } from "@easyblocks/core"; export const easyblocksConfig: Config = { backend: new EasyblocksBackend({ accessToken: "<<< your access token >>>", }), // ... }; ``` -------------------------------- ### Building Document with Easyblocks SDK (TypeScript) Source: https://github.com/easyblockshq/easyblocks/blob/main/docs/essentials/rendering-content.md This snippet demonstrates how to use the `buildDocument` function from the `@easyblocks/core` SDK to prepare an Easyblocks document for rendering. It requires a `documentId`, your `easyblockConfig`, and a `locale` code, returning a `renderableDocument` optimized for display. ```TypeScript import { buildDocument } from "@easyblocks/core"; const { renderableDocument } = await buildDocument({ documentId: "", config: easyblockConfig, locale: "" }); ``` -------------------------------- ### Defining Sample Product Data (JSON) Source: https://github.com/easyblockshq/easyblocks/blob/main/docs/essentials/external-data.md This JSON array represents a sample list of products, each with an ID, title, and price. It serves as the external data source that will be connected and displayed within the Easyblocks application. ```json [ { "id": "1", "title": "Product 1", "price": 25.0 }, { "id": "2", "title": "Product 2", "price": 10.0 }, { "id": "3", "title": "Product 3", "price": 50.0 }, { "id": "4", "title": "Product 4", "price": 150.0 } ] ``` -------------------------------- ### Configuring Easyblocks Backend (TypeScript) Source: https://github.com/easyblockshq/easyblocks/blob/main/docs/essentials/configuration.md This snippet shows how to configure the `backend` property of the Easyblocks `Config` object. It sets up an `EasyblocksBackend` instance, responsible for document and template management, requiring an `accessToken` for authentication. ```TypeScript import type { Config, EasyblocksBackend } from "@easyblocks/core"; const config: Config = { backend: new EasyblocksBackend({ accessToken: MY_ACCESS_TOKEN }), // ... }; ``` -------------------------------- ### Defining ProductPage Component with Root Parameters - TypeScript Source: https://github.com/easyblockshq/easyblocks/blob/main/docs/essentials/external-data.md This TypeScript snippet defines an Easyblocks configuration, specifically adding a `ProductPage` component. It configures a `rootParam` named `product` which allows dynamic product data to be supplied during content rendering, making the page reusable for different products. The `widgets` array specifies how the product field can be selected in the editor. ```typescript import type { Config } from "@easyblocks/core"; const easyblocksConfig: Config = { ..., components: [ { id: "ProductPage", schema: [ { prop: "data", type: "component-collection", accepts: ["item"] } ], rootParams: [ { prop: "product", label: "Product", widgets: [{ id: "product", label: "Product" }] }, ] } ] }; ``` -------------------------------- ### Initializing Easyblocks Configuration (TypeScript) Source: https://github.com/easyblockshq/easyblocks/blob/main/docs/essentials/configuration.md This snippet demonstrates the basic structure for initializing the `easyblocksConfig` object, which is the central configuration for Easyblocks applications. It imports the `Config` type from `@easyblocks/core` and defines an empty configuration object. ```TypeScript import type { Config } from "@easyblocks/core"; export const easyblocksConfig: Config = { /* config properties */ }; ``` -------------------------------- ### Configuring Easyblocks Content Templates - TypeScript Source: https://github.com/easyblockshq/easyblocks/blob/main/docs/essentials/configuration.md This TypeScript snippet demonstrates how to configure content templates within the Easyblocks framework. It imports the `Config` type and a specific template JSON file, then registers the template with a unique ID and its entry point. This allows the Easyblocks editor to recognize and utilize custom content structures, enabling modular content creation. ```TypeScript import type { Config } from '@easyblocks/core'; import bannerTemplate1 from "bannerTemplate1.json" const config: Config = { ..., templates: [ { id: "BannerSection", entry: bannerTemplate1 } ] }; ``` -------------------------------- ### Implementing Product Picker Widget with SimplePicker (TSX) Source: https://github.com/easyblockshq/easyblocks/blob/main/docs/essentials/external-data.md This snippet demonstrates how to create a ProductPickerWidget using Easyblocks' SimplePicker component. It shows how to pass value and onChange props, and how to implement getItems for filtering products based on a query and getItemById for fetching a single product. It uses a static products array as a data source. ```tsx import { WidgetComponentProps } from "@easyblocks/core"; import { SimplePicker } from "@easyblocks/design-system"; const products = [ { id: "1", title: "Product 1", price: 25.0, }, { id: "2", title: "Product 2", price: 10.0, }, { id: "3", title: "Product 3", price: 50.0, }, { id: "4", title: "Product 4", price: 150.0, }, ]; function ProductPickerWidget(props: WidgetComponentProps) { return ( { const filteredItems = products.filter((p) => p.title.includes(query)); return filteredItems.map((i) => { return { id: i.id, name: i.title, }; }); }} getItemById={async (id) => { const item = products.find((p) => p.id === id); return { id: item.id, name: item.title, }; }} /> ); } ``` -------------------------------- ### Adding Validation to Custom URL Type in Easyblocks Configuration (JavaScript) Source: https://github.com/easyblockshq/easyblocks/blob/main/docs/essentials/custom-types.md This snippet enhances the custom 'url' type definition by adding a `validate` function. This function ensures that the input value is a string and starts with either 'http://' or 'https://'. The `validate` function is invoked whenever `onChange` is called on the widget, preventing invalid data from being saved. ```javascript const easyblocksConfig: Config = { ..., types: { url: { type: "inline", widget: { id: "url", label: "URL" }, defaultValue: "https://easyblocks.io", validate(value) { return ( typeof value === "string" && (value.startsWith("http://") || value.startsWith("https://")) ); } } } } ``` -------------------------------- ### Defining Easyblocks Visual Configuration (SVG, Aspect Ratios, Box Shadows) - JavaScript/TypeScript Source: https://github.com/easyblockshq/easyblocks/blob/main/docs/essentials/configuration.md This snippet defines various visual configuration options for Easyblocks, including an SVG icon string, predefined aspect ratios (e.g., panoramic, landscape), and a set of box shadow styles with their corresponding CSS values. These configurations are typically used to provide selectable options within the Easyblocks UI for styling elements. ```JavaScript value: ``, }, ], aspectRatios: [ { id: "panoramic", label: "Panoramic (2:1)", value: "2:1", }, { id: "landscape", label: "Landscape (16:9)", value: "16:9", }, { id: "portrait", label: "Portrait (4:5)", value: "4:5", }, { id: "square", label: "Square (1:1)", value: "1:1", }, ], boxShadows: [ { id: "none", label: "None", value: "none", }, { id: "sm", label: "sm", value: "0 1px 2px 0 rgb(0 0 0 / 0.05)", }, { id: "md", label: "md", value: "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)", }, { id: "lg", label: "lg", value: "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)", }, { id: "xl", label: "xl", value: "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)", }, { id: "2xl", label: "2xl", value: "0 25px 50px -12px rgb(0 0 0 / 0.25)", } ] } }; ``` -------------------------------- ### Defining and Registering Product Picker Widget (TSX) Source: https://github.com/easyblockshq/easyblocks/blob/main/docs/essentials/external-data.md This TSX code defines the 'product' widget within the Easyblocks configuration, assigning it an ID and label. It also provides a placeholder React component, `ProductPickerWidget`, which will be responsible for rendering the product selection interface in the editor. The widget is then registered with the `EasyblocksEditor`. ```tsx // Widgets definition const easyblocksConfig: Config = { ..., types: { product: { type: "external", widgets: [ { id: "product", label: "Product" } ], } } } // Widget's component import { WidgetComponentProps } from "@easyblocks/core"; function ProductPickerWidget(props: WidgetComponentProps) { return null; } ``` -------------------------------- ### Dynamically Rendering ProductPage with External Data - TSX Source: https://github.com/easyblockshq/easyblocks/blob/main/docs/essentials/external-data.md This TSX snippet demonstrates how to dynamically render an Easyblocks content page, `ProductPage`, by overriding the `$.product` root parameter. It uses `buildDocument` to fetch the base document and then a custom `myFetcher` to inject dynamic product data based on `params.id`, enabling different product content for each page load. ```tsx import { Easyblocks, buildDocument, RequestedExternalData, } from "@easyblocks/core"; import { easyblocksConfig } from "./path-to-your-easyblocks-config"; async function myFetcher(externalData: RequestedExternalData) { // Your custom fetcher logic } function ProductPage({ params }: Record) { const { renderableDocument, externalData } = await buildDocument({ documentId: "", config: easyblocksConfig, locale: "en-US", }); const fetchedExternalData = await myFetcher({ ...externalData, "$.product": { ...externalData["$.product"], id: params.id, }, }); return ( ); } ``` -------------------------------- ### Returning Compound Product Data (TypeScript) Source: https://github.com/easyblockshq/easyblocks/blob/main/docs/essentials/external-data.md This snippet demonstrates how to return compound data in Easyblocks, allowing for multiple "basic" data types within a single object. It shows an object type containing productTitle (text), productPrimaryImage (image, requiring custom type definition), and self (product) properties, enabling richer data representation. ```typescript { type: "object", value: { productTitle: { type: "text", value: product.title }, productPrimaryImage: { // `image` type isn't a part of Easyblocks and it would require to define // a custom type type: "image", value: product.images[0] }, self: { type: "product", value: product } ] } ``` -------------------------------- ### Basic Product Data Return (TypeScript) Source: https://github.com/easyblockshq/easyblocks/blob/main/docs/essentials/external-data.md This snippet illustrates a basic data structure for returning a single product in Easyblocks. It defines a type as "product" and directly assigns the product object to the value property, representing a simple, non-compound data return. ```typescript { type: "product", value: product } ``` -------------------------------- ### Rendering Content with Easyblocks Component (TSX) Source: https://github.com/easyblockshq/easyblocks/blob/main/docs/essentials/rendering-content.md This snippet illustrates how to render the prepared `renderableDocument` using the `Easyblocks` React component. It takes the `renderableDocument` obtained from `buildDocument` and an object containing your no-code component instances. ```TSX import { Easyblocks } from "@easyblocks/core"; ; ``` -------------------------------- ### Defining a Template Object in Easyblocks Source: https://github.com/easyblockshq/easyblocks/blob/main/docs/essentials/templates.md This snippet illustrates the basic structure of a template object used in Easyblocks. It includes a unique `id`, an optional `label` for UI display, an optional `thumbnail` URL, and the `entry` property which holds the actual no-code configuration for the component instance. These objects are stored in the `Config.templates` array. ```typescript { id: "template_1", // unique id label: "My Super Template", // label displayed in UI (optional) thumbnail: thumbnail_url // URL to the thumbnail image (optional) entry: { ... } // no-code entry } ```