@freelygive/canvas-utils
v0.3.4
Published
Canvas utility components and test helpers for Drupal Canvas projects.
Readme
@freelygive/canvas-utils
Canvas utility components and test helpers for Drupal Canvas projects.
Components
Utility components are scaffolded into your project via @freelygive/npm-scaffold.
| Component | Description |
|---------------------|-------------------------------------------------------------------------------------------|
| utils_editor_note | Editor note component, isCanvasEditorMode() detection, and useEditorFullHeight() hook |
| utils_slots | getSlotChildren() for parsing Canvas slot content |
| utils_entity | useMainEntity() hook for fetching the page's main entity |
useEditorFullHeight(enabled)
Canvas editor mode renders components inside an iframe whose height is stretched
to fit content, which breaks min-h-screen / h-screen CSS. This hook reads
the actual browser viewport height and returns a { minHeight } style object
set to 80% of the viewport. Returns undefined when not in editor mode, so CSS
handles it normally.
import {
isCanvasEditorMode,
useEditorFullHeight,
} from '@/components/utils_editor_note';
const MyComponent = () => {
const editorStyle = useEditorFullHeight(isCanvasEditorMode());
return (
<div className="min-h-screen" style={editorStyle}>
...
</div>
);
};Test Helpers
Built JS entry points for use in Storybook test stories.
Simulating Canvas Slots
Canvas delivers slot content as HTML containing <canvas-island> custom
elements. In Storybook, use the canvas-slots helpers to replicate this format so
components can be tested under realistic conditions.
import {
createCanvasIsland,
createCanvasSlot,
} from '@freelygive/canvas-utils/testing/canvas-slots';
// Build the HTML that Canvas would produce for a slot containing two items
const slotHtml = [
createCanvasIsland({ heading: 'First item', text: '<p>Content one.</p>' }),
createCanvasIsland({ heading: 'Second item', text: '<p>Content two.</p>' }),
].join('');
// Wrap it in a React element that getSlotChildren() can parse
const canvasContent = createCanvasSlot(slotHtml);
// Pass to the component as the slot prop
export const WithCanvasSlot: Story = {
args: {
content: canvasContent,
},
};rawProp(value) is also exported for cases where you need to construct the
["raw", value] tuple format manually.
Simulating Editor Mode
Canvas editor mode changes component behaviour (e.g. expanding all accordion
items for editing). Use the withEditorMode decorator to enable editor mode for
the lifetime of a story:
import { withEditorMode } from '@freelygive/canvas-utils/testing/editor-mode';
export const InEditorMode: Story = {
args: { /* ... */ },
decorators: [withEditorMode],
};The decorator enables editor mode before the first render and cleans up on
unmount via useEffect, so state is restored even when tests are interrupted or
Storybook navigates away.
enableEditorMode() and disableEditorMode() are also exported for cases that
need direct control.
Setup
Add the package and configure npm-scaffold in your project's package.json:
{
"dependencies": {
"@freelygive/canvas-utils": "^0.1.0"
},
"scripts": {
"postinstall": "npm-scaffold"
},
"npmScaffold": {
"allowed-packages": ["@freelygive/canvas-utils"],
"base-path": "src"
}
}Running npm install will scaffold the utility components into
src/components/ as symlinks and add them to .gitignore.
API Reference
canvas-slots
| Export | Description |
|-----------------------------|-----------------------------------------------------------------------------------|
| rawProp(value) | Wraps a value in the ["raw", value] tuple format used by Canvas island props |
| createCanvasIsland(props) | Creates a <canvas-island> HTML string from a props object |
| createCanvasSlot(html) | Creates a React element simulating a Canvas slot for getSlotChildren() to parse |
editor-mode
| Export | Description |
|-----------------------|-------------------------------------------------------------------------------|
| withEditorMode | Storybook decorator — enables editor mode before render, cleans up on unmount |
| enableEditorMode() | Sets window.drupalSettings.canvas to simulate Canvas editor mode |
| disableEditorMode() | Removes window.drupalSettings.canvas |
