Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | 1x 1x 1x 1x 1x 1x 3x 3x 3x 3x | // src/remix/index.js
//
// Public entry point for @coherent.js/integrations/remix. Provides SSR
// integration and loader utilities for Remix projects.
//
// Remix (and therefore React) must be installed as a peer dependency to use
// this integration.
//
// Usage:
// import { createRemixAdapter } from '@coherent.js/integrations/remix';
import { createElement } from 'react';
import { render } from '@coherent.js/core';
/**
* Create a Remix adapter for Coherent.js
*
* @param {Object} [options] - Adapter options
* @param {boolean} [options.hydrate] - Enable client-side hydration
* @returns {Object} Remix adapter utilities
*
* @example
* const adapter = createRemixAdapter();
* const html = adapter.renderComponent(MyComponent, { title: 'Hello' });
*/
export function createRemixAdapter(_options = {}) {
return {
/**
* Render a Coherent.js component to HTML
*/
renderComponent(component, props = {}) {
const def = typeof component === 'function' ? component(props) : component;
return render(def);
},
/**
* Create a Remix loader that renders a Coherent.js component
*/
createLoader(component, getProps) {
return async ({ request, params, context }) => {
const props = getProps
? await getProps({ request, params, context })
: { request, params };
const def = typeof component === 'function' ? component(props) : component;
const html = render(def);
return new Response(html, {
headers: { 'Content-Type': 'text/html; charset=utf-8' }
});
};
},
/**
* Create a Remix action handler that processes form data
* and renders a Coherent.js component with the result
*/
createAction(component, handler) {
return async ({ request, params, context }) => {
const formData = await request.formData();
const data = Object.fromEntries(formData);
const result = await handler({ data, request, params, context });
if (result instanceof Response) return result;
const def = typeof component === 'function' ? component(result) : component;
const html = render(def);
return new Response(html, {
headers: { 'Content-Type': 'text/html; charset=utf-8' }
});
};
}
};
}
/**
* HOC: Wrap a Coherent.js component for use in Remix routes
*
* Returns a React component that renders the Coherent.js markup inside a
* wrapper element via `dangerouslySetInnerHTML`. Returning the HTML string
* itself would make React escape it and show the tags as text. The
* Coherent.js renderer escapes text and attribute values, so only markup the
* component describes (or passes through its explicit `html` field) is raw.
*
* @param {Function|Object} Component - Coherent.js component function or object
* @param {Object} [options] - Wrapper options
* @param {string} [options.as='div'] - Tag name of the wrapper element
* @returns {Function} Remix-compatible React component
*/
export function withCoherent(Component, options = {}) {
const { as = 'div' } = options;
return function CoherentRemixComponent(props) {
const def = typeof Component === 'function' ? Component(props) : Component;
return createElement(as, { dangerouslySetInnerHTML: { __html: render(def) } });
};
}
|