droplinked-editor-configs
v1.9.17
Published
A visual page builder library based on React and Puck Editor for creating and managing configurable e-commerce components. This library provides both an editor component for building pages and renderer components for displaying them.
Readme
Droplinked Designer
A visual page builder library based on React and Puck Editor for creating and managing configurable e-commerce components. This library provides both an editor component for building pages and renderer components for displaying them.
📦 Installation
npm install droplinked-editor-configs🚀 Quick Start
As an Editor
import { Editor, AppStoreProvider, Data } from 'droplinked-editor-configs';
import 'droplinked-editor-configs/dist/index.css';
const initialData: Data = {
root: { props: {} },
content: []
};
function App() {
return (
<Editor
shopName="your-shop-name"
initialData={initialData}
isLive={false}
onPublish={(data) => console.log('Published:', data)}
onDraft={(data) => console.log('Draft saved:', data)}
/>
);
}As a Renderer
import { PageHeader, PageFooter, InnerContent } from 'droplinked-editor-configs';
import { ShopProvider } from 'droplinked-editor-configs';
function MyShop() {
const headerData = { /* your header data */ };
const footerData = { /* your footer data */ };
const contentData = { /* your content data */ };
return (
<ShopProvider shopName="your-shop-name">
<PageHeader
data={headerData}
cartItemCount={5}
onCartClick={() => {}}
handleNavigate={(path) => {}}
/>
<InnerContent
data={contentData}
handleNavigate={(path) => {}}
/>
<PageFooter
data={footerData}
handleNavigate={(path) => {}}
/>
</ShopProvider>
);
}🏗️ Architecture Overview
Core Components
Editor
The main editor component that provides the visual page builder interface. It integrates:
- Puck Editor: The visual drag-and-drop editor
- Shop Data Fetching: Automatically fetches shop configuration based on
shopName - State Management: Uses AppStore for global state management
- React Query: For server state management
Props:
shopName: Name of the shop to load configuration forinitialData: Initial page structureisLive: Whether the editor is in live/preview modeisNewTheme: Flag for new theme creationonPublish: Callback when user publishes changesonDraft: Callback when user saves draftonUpdate: Callback for updatesonChange: Callback on any data changethemeName: Name of the theme being editedpublishLoading: Loading state for publish actiondraftLoading: Loading state for draft actionpermissions: User permissions objectoverrides: UI component overridesiframe: Iframe configuration for previewtoken: Authentication token
PageHeader
Renders the header component with navigation and cart functionality.
Props:
data: Header component data structureonCartClick: Callback for cart icon clickcartItemCount: Number of items in carthandleNavigate: Navigation handler functionprofileDropdownWrapper: Custom profile dropdown component
PageFooter
Renders the footer component with links and social media.
Props:
data: Footer component data structurehandleNavigate: Navigation handler function
InnerContent
Renders the main content area with all configured components.
Props:
data: Content data structurehandleNavigate: Navigation handler function
🧠 State Management
AppStore (Zustand)
The library uses Zustand for global state management with persistence.
Structure:
interface IAppStore {
states: {
cart: { [shopName: string]: ICart }; // Shopping cart state
user: { [shopName: string]: { token: string; user: IUser } } | null; // User authentication
shop: IShop; // Shop configuration
};
methods: {
updateState: (props: { state: string; value: any }) => void;
};
}Usage:
import useAppStore from 'lib/stores/app/appStore';
function MyComponent() {
const { states, methods } = useAppStore();
// Access cart
const cart = states.cart['my-shop'];
// Update state
methods.updateState({ state: 'cart', value: newCart });
}AppStoreProvider:
The AppStoreProvider wraps components and provides AppStore context via React Context API. This is necessary for the Editor component to access global state.
<AppStoreProvider appStoreData={appStoreData}>
<YourComponent />
</AppStoreProvider>ShopProvider
Handles shop data fetching and provides loading state.
<ShopProvider shopName="your-shop-name">
<YourComponents />
</ShopProvider>📁 Project Structure
src/
├── configured-components/ # Component library organized by category
│ ├── blog-posts/ # Blog components
│ ├── button/ # Button variants
│ ├── design-layout/ # Layout containers (grid, vertical, horizontal)
│ ├── hero-section/ # Hero section variants
│ ├── image-with-text/ # Image with text components
│ ├── layout/ # Header & Footer
│ ├── media/ # Image and video components
│ ├── multicolumn/ # Multi-column layouts
│ ├── products/ # Product grid and summary components
│ └── text/ # Text components (heading, body, caption, subtitle)
│
├── components/ # Reusable UI components
│ ├── ui/ # Shadcn UI components
│ ├── legacy-components/ # Legacy components
│ ├── header/ # Header sub-components
│ ├── footer/ # Footer sub-components
│ ├── productGrid/ # Product grid components
│ └── blog-posts/ # Blog post components
│
├── lib/
│ ├── stores/ # Zustand stores
│ │ ├── app/ # AppStore - global state
│ │ └── productQueryStore/ # Product query state
│ ├── models/ # TypeScript interfaces
│ └── utils/ # Utility functions
│
├── apis/ # API services
│ ├── axiosConfig.ts # Axios configuration
│ ├── blogs/ # Blog API services
│ ├── product/ # Product API services
│ └── shop/ # Shop API services
│
├── hooks/ # Custom React hooks
│ ├── useCustomNavigate.ts # Navigation hook
│ ├── useThemeInfo.ts # Theme information hook
│ └── shop/ # Shop-related hooks
│
├── types/ # TypeScript type definitions
│ ├── editorProps.ts # Editor component props
│ └── renderersProps.ts # Renderer component props
│
├── App.tsx # Demo/Example application
├── Editor.tsx # Main editor component
├── PageHeader.tsx # Header renderer
├── PageFooter.tsx # Footer renderer
├── InnerContent.tsx # Content renderer
├── AppStoreProvider.tsx # AppStore context provider
├── ShopProvider.tsx # Shop data provider
├── NavigationContext.tsx # Navigation context
└── index.ts # Library entry point🔧 Component Configuration System
Component Categories
Components are organized into categories:
- Design Layout: Container components (Grid, Vertical, Horizontal)
- Media: Image and video components
- Button: Various button styles
- Text: Typography components
- Layout: Header and Footer
- Hero Section: Hero/banner components
- Image with Text: Combined image-text layouts
- Products: Product display components
- Blog Posts: Blog listing and post components
- Multi Column: Multi-column layouts
Configuration Files
Each component category has:
- Component files (
.tsx): React component implementation - Config files (
*Config.tsx): Puck editor configuration - Interface files (
interface.ts): TypeScript type definitions - Category config (
categoryConfig.ts): Category metadata - Index file (
index.tsx): Exports for the category
🎨 Adding a New Component
1. Create Component Structure
src/configured-components/[category]/[component]/
├── configs/
│ ├── interface.ts # TypeScript interface
│ └── [component]Config.tsx # Puck configuration
├── [Component].tsx # Main component
└── [Component]VisualExample.tsx # Visual preview2. Define the Props Interface
configs/interface.ts:
export interface MyComponentProps {
title: string;
description?: string;
backgroundColor?: string;
id?: string;
}3. Implement the Component
MyComponent.tsx:
import { MyComponentProps } from "./configs/interface";
const MyComponent: React.FC<MyComponentProps> = ({
title,
description,
backgroundColor
}) => {
return (
<div style={{ backgroundColor }}>
<h2>{title}</h2>
{description && <p>{description}</p>}
</div>
);
};
export default MyComponent;4. Create Visual Example
MyComponentVisualExample.tsx:
const MyComponentVisualExample = () => (
<div className="preview-container">
<span>My Component Preview</span>
</div>
);
export default MyComponentVisualExample;5. Define Puck Configuration
configs/myComponentConfig.tsx:
import { Config } from "droplinked-editor-core";
import MyComponent from "../MyComponent";
import MyComponentVisualExample from "../MyComponentVisualExample";
export const myComponentConfig: Config["components"][string] = {
label: "My Component",
visualExample: <MyComponentVisualExample />,
fields: {
title: {
type: "text",
label: "Title"
},
description: {
type: "textarea",
label: "Description"
},
backgroundColor: {
type: "text",
label: "Background Color"
},
},
defaultProps: {
title: "Default Title",
description: "Default description",
backgroundColor: "#ffffff",
},
render: (props) => <MyComponent {...props} />,
};6. Export from Category
src/configured-components/[category]/index.tsx:
import { myComponentConfig } from "./my-component/configs/myComponentConfig";
export const categoryComponents = {
...existingComponents,
myComponent: myComponentConfig,
};7. Add to Category Config
categoryConfig.ts:
export const categoryConfig: Config["categories"] = {
myCategory: {
title: "My Category",
components: ["myComponent", /* other components */],
},
};8. Register in Main Config
src/index.ts:
export const editorMainConfig: Config = {
categories: {
...existingCategories,
...myCategoryConfig,
},
components: {
...existingComponents,
...myCategoryComponents,
}
};🔨 Building & Development
Development Mode
Run the development server with hot reload:
npm install
npm run devAccess at: http://localhost:5173
Build for Production
Build the library for npm distribution:
npm run buildThis creates:
dist/droplinked-editor.es.js- ES module builddist/droplinked-editor.umd.js- UMD builddist/index.d.ts- TypeScript definitionsdist/style.css- Bundled styles
Publishing to npm
- Update version in
package.json - Build the library:
npm run build - Publish:
npm publish
🧩 Advanced Usage
Custom Navigation
Implement custom navigation handler:
const handleNavigate = (path: string) => {
// Your custom navigation logic
router.push(path);
};
<InnerContent
data={contentData}
handleNavigate={handleNavigate}
/>Custom Profile Dropdown
Pass custom profile dropdown wrapper:
const CustomProfileDropdown = ({ children }) => (
<div className="custom-dropdown">
{children}
</div>
);
<PageHeader
data={headerData}
profileDropdownWrapper={CustomProfileDropdown}
// ... other props
/>📚 API Reference
Exports
// Components
export { Editor } // Main editor component
export { PageHeader } // Header renderer
export { PageFooter } // Footer renderer
export { InnerContent } // Content renderer
export { AppStoreProvider } // AppStore context provider
// Configs
export { editorMainConfig } // Full editor configuration
export { innerContentConfig } // Content-only configuration
// Types
export type { Config, Data } // From droplinked-editor-core
export type { EditorProps } // Editor component props
export type { PageHeaderProps, PageFooterProps, innerContentProps }Data Structure
The Data type represents the page structure:
interface Data {
root: {
props: Record<string, any>;
};
content: Array<{
type: string; // Component type
props: {
id: string; // Unique component ID
[key: string]: any; // Component-specific props
};
}>;
}🛠️ Tech Stack
- React 19 - UI library
- TypeScript - Type safety
- Vite - Build tool
- Puck Editor - Visual editor core
- Zustand - State management
- React Query - Server state management
- Axios - HTTP client
- Tailwind CSS - Styling
- Shadcn UI - UI components
- Chakra UI - Additional UI components
- Framer Motion - Animations
📖 Key Concepts
DropZone
Use DropZone from droplinked-editor-core to create droppable areas:
import { DropZone } from "droplinked-editor-core";
<div className="container">
<DropZone zone="content" />
</div>Component IDs
Each component instance requires a unique id prop for identification and updates.
Visual Examples
Always provide a visualExample component for the component picker UI.
Categories
Organize components into categories for better UX in the editor sidebar.
📝 Best Practices
- Type Safety: Always define TypeScript interfaces for component props
- Default Props: Provide sensible defaults in component config
- Visual Examples: Create clear, representative visual examples
- Unique IDs: Ensure component IDs are unique across the page
- Responsive Design: Make components responsive using Tailwind utilities
- Accessibility: Follow accessibility best practices
- Performance: Lazy load heavy components when possible
- State Management: Use AppStore for global state, local state for component-specific data
🤝 Contributing
When adding new components or features:
- Follow the established folder structure
- Create proper TypeScript interfaces
- Add visual examples for editor UI
- Update category configurations
- Export from appropriate index files
- Test in both editor and renderer modes
- Document any new patterns or APIs
📚 Resources & Documentation
- Puck Editor Documentation
- React Documentation
- TypeScript Handbook
- Zustand Documentation
- React Query Documentation
- Vite Documentation
