Catalogue Designer
A React design editor for building catalogues, and a viewer for showing them on any website.
- Design editor: create and edit catalogue pages.
- Catalogue viewer: show a finished catalogue, either as a React component or with a script tag.
The editor and the viewer use separate license keys. The editor key only opens the editor, and the viewer key only opens the viewer. A missing or wrong key shows an error message instead of the component.
Installation
npm install @anubhav1ks/catalogue-designer
# or
yarn add @anubhav1ks/catalogue-designer
Peer dependencies: react and react-dom (18). CKEditor is installed automatically with the package.
Design editor
import DesignEditor, { DesignEditorContext } from '@anubhav1ks/catalogue-designer';
import '@anubhav1ks/catalogue-designer/css/design-editor.css';
export default function App() {
return (
<DesignEditorContext.Provider
value={{
viewerScriptUrl: 'https://your-site.com/catalogue-viewer.js',
viewerLicenseKey: 'YOUR-VIEWER-LICENSE-KEY',
}}
>
<div style={{ height: '100vh' }}>
<DesignEditor
licenseKey="YOUR-EDITOR-LICENSE-KEY"
value={design}
onChange={(next) => save(next)}
/>
</div>
</DesignEditorContext.Provider>
);
}
Editor props
| Prop | Type | Default | Description |
|---|---|---|---|
licenseKey | string | — | Required. Editor license key. |
value | IDesign | — | Design to open. |
onChange | (design: IDesign) => void | — | Called whenever the design changes. |
storageKey | string | false | — | Key for saving to the browser. false turns saving off. |
height | number | string | '100%' | Editor height. |
minHeight | number | string | 600 | Minimum editor height. |
className | string | — | Extra CSS class. |
style | CSSProperties | — | Extra inline styles. |
Editor settings (DesignEditorContext)
| Field | Type | Description |
|---|---|---|
templates | any[] | Templates shown in the editor. |
shapes | any[] | Extra shapes. |
viewerScriptUrl | string | URL of catalogue-viewer.js. Turns on "Open preview in new tab". |
viewerLicenseKey | string | Viewer key, added to the preview page and the embed code snippets. |
plan | number | Current plan level. |
planConfig | Partial<PlanConfig> | Plans and which features each plan unlocks. |
uploadFile | (file: File) => Promise<string> | Uploads a file and returns its URL. |
Other exports: usePlan, DEFAULT_PLAN_CONFIG, clearSavedDesign, designStorageKey, parseCatalogueJson.
Catalogue viewer
Download the catalogue JSON from the editor (Preview & embed → Download catalogue JSON) and pass it to the viewer.
The viewer fills 100% of the width and height of its container, so give the parent element a height.
React
import { CatalogueViewer } from '@anubhav1ks/catalogue-designer/viewer';
<div style={{ height: 600 }}>
<CatalogueViewer
licenseKey="YOUR-VIEWER-LICENSE-KEY"
design={catalogue}
type="full"
inView={true}
/>
</div>;
Single view
Shows only the pages, one at a time, with no toolbar, arrows or thumbnails. Visitors change pages by swiping, with the arrow keys, or with links on the page.
<div style={{ height: 600 }}>
<CatalogueViewer
licenseKey="YOUR-VIEWER-LICENSE-KEY"
design={catalogue}
type="single"
inView={true}
startPage={0}
/>
</div>
Animations and video (inView)
inView={true}plays page animations and autoplays videos.inView={false}stops animations and pauses all videos and audio, including YouTube embeds.
Use it to pause catalogues the visitor can't see, for example in a carousel or a scrolling list:
const [visible, setVisible] = useState(false);
const ref = useRef<HTMLDivElement>(null);
useEffect(() => {
const io = new IntersectionObserver(([entry]) => setVisible(entry.isIntersecting));
if (ref.current) io.observe(ref.current);
return () => io.disconnect();
}, []);
<div ref={ref} style={{ height: 500 }}>
<CatalogueViewer
licenseKey="YOUR-VIEWER-LICENSE-KEY"
design={catalogue}
type="single"
inView={visible}
/>
</div>;
Page-jump links (onPageJump)
By default, page-jump links on a page (next, previous, first, last, go to page) turn the viewer's own page.
Pass onPageJump to handle them yourself, for example when each slide of your carousel is its own viewer:
<CatalogueViewer
licenseKey="YOUR-VIEWER-LICENSE-KEY"
design={catalogue}
type="single"
startPage={index}
inView={index === activeSlide}
onPageJump={(page) => setActiveSlide(page)}
/>
page is 0-based and already limited to the catalogue's pages. The second argument is the link's original
target: a page number, or 'prev', 'next', 'first' or 'last'.
Viewer props
| Prop | Type | Default | Description |
|---|---|---|---|
licenseKey | string | — | Required. Viewer license key. |
design | IDesign | string | — | Catalogue JSON, as an object or a string. |
src | string | — | URL to load the catalogue JSON from (used when design is not given). |
type | 'full' | 'single' | 'full' | full = toolbar, arrows, spreads, thumbnails. single = pages only. |
inView | boolean | true | true plays animations and video, false stops them. |
width | number | string | '100%' | Viewer width. |
height | number | string | '100%' | Viewer height. |
mode | 'auto' | 'book' | 'single' | 'auto' | Page layout in full view. auto uses spreads on wide screens. |
theme | 'light' | 'dark' | 'light' | Colour theme. |
startPage | number | 0 | Page to open on (0 = first page). |
showThumbnails | boolean | false | Open with the thumbnail strip showing (full view only). |
linkColor | string | — | Colour of link hotspots. |
flipOnClick | boolean | false | Clicking the left or right half of a page turns the page. |
className | string | — | Extra CSS class. |
style | CSSProperties | — | Extra inline styles. |
onLoad | (design) => void | — | Called when the catalogue has loaded. |
onError | (error) => void | — | Called when the catalogue can't be loaded. |
onPageJump | (page, target) => void | — | Called when a page-jump link is clicked, with the 0-based page to go to. When set, the viewer does not change page itself. |
Script tag (no React)
Add catalogue-viewer.js (from dist/) to your page. Every element with data-catalogue-src or data-catalogue becomes a viewer.
<div
data-catalogue-src="/catalogue.json"
data-license-key="YOUR-VIEWER-LICENSE-KEY"
data-type="single"
data-in-view="true"
style="height: 600px"
></div>
<script src="https://your-site.com/catalogue-viewer.js" defer></script>
You can also put the JSON inside the element:
<div data-catalogue data-license-key="YOUR-VIEWER-LICENSE-KEY" data-height="700">
<script type="application/json">
{ ...catalogue JSON... }
</script>
</div>
| Attribute | Same as prop |
|---|---|
data-license-key | licenseKey |
data-catalogue-src | src |
data-type | type |
data-in-view | inView ("false" to pause) |
data-width | width |
data-height | height |
data-mode | mode |
data-theme | theme |
data-start-page | startPage (starts at 1) |
data-thumbnails | showThumbnails |
data-link-color | linkColor |
data-flip-on-click | flipOnClick |
If the element has no height, it gets 640px.
JavaScript API
const viewer = window.CatalogueViewer.mount(element, {
licenseKey: 'YOUR-VIEWER-LICENSE-KEY',
src: '/catalogue.json',
type: 'full',
});
viewer.update({ inView: false }); // change any prop later
viewer.unmount();
window.CatalogueViewer.autoMount(); // mount elements added to the page later