Skip to Content
SumX EditorPortal integration

Portal integration

How to wire @sumx/sumx-editor into the SumX Client Portal (or any Next.js 14+ Pages Router app).

Dependencies

package.json (feed semver example):

{ "dependencies": { "@sumx/sumx-editor": "0.1.0", "@sumx/ui": "0.1.2", "suneditor": "^3.1.1", "react-easy-crop": "^5.5.0" }, "devDependencies": { "@sumx/ui": "0.1.2" } }

Use pnpm run sumx:local / sumx:vendor / sumx:feed per Consume in your app.

Next.js config

Add the editor package to transpilePackages so Next compiles kit output correctly:

// next.config.js const nextConfig = { transpilePackages: [ '@sumx/ssr-auth-core', '@sumx/http-client', '@sumx/sumx-editor', ], };

Styles

Global SCSS — editor chrome, variable chips, list classes:

/* src/styles/globals.scss */ @import '@sumx/sumx-editor/styles.scss';

Tailwind — scan kit class names (border-gray-gray, text-black-soft, etc.) with the portal theme:

/* src/styles/tailwind.css */ @source "../../node_modules/@sumx/ui/dist"; @source "../../node_modules/@sumx/ui/src"; @source "../../node_modules/@sumx/sumx-editor/dist"; @source "../../node_modules/@sumx/sumx-editor/src";

Theme tokens live in the host tailwind.config.js (gray.gray, black.soft, primary, …). The editor uses those names, not generic zinc-* scales.

Permission provider

SumXEditor uses @sumx/ui (Button, Dialog, Input, DropdownMenu). Wrap the app with your portal SumxUiPermissionProvider (or any PermissionProvider) the same as for auth dialogs — see Permissions.

Dynamic import for route-level code splitting

For heavy screens, lazy-load the editor shell (the package already avoids SSR for SunEditor internally):

import dynamic from 'next/dynamic'; const SumXEditor = dynamic(() => import('@sumx/sumx-editor'), { ssr: false, loading: () => ( <div className="min-h-[120px] animate-pulse rounded-md border border-gray-gray bg-gray-lighter/40" aria-hidden /> ), });

Do not statically import suneditor or sumx-editor-core from files that Next executes on the server.

Feature module pattern

LayerResponsibility
schemas/Zod — store string HTML from the editor
services/API — send/receive HTML as provided by backend
components/SumXEditor + onChange bound to form state
Detail / list previewsRichTextContent from @sumx/sumx-editor/rich-text-content

React Hook Form example:

import { Controller, useFormContext } from 'react-hook-form'; import SumXEditor from '@sumx/sumx-editor'; function BodyField() { const { control } = useFormContext<{ body: string }>(); return ( <Controller name="body" control={control} render={({ field }) => ( <SumXEditor value={field.value ?? ''} onChange={field.onChange} toolbarPreset="standard" invalid={/* from formState.errors.body */} /> )} /> ); }

Sanitizer re-export (optional)

Portal keeps a thin shim so existing imports keep working:

// src/shared/lib/sanitize-rich-html.ts export { RICH_HTML_SANITIZE_CONFIG, sanitizeRichHtml, } from '@sumx/sumx-editor/sanitize-rich-html';

Prefer @sumx/sumx-editor/sanitize-rich-html in new code.

Portal feature examples

Typical imports in the client portal:

FeatureEditorRead view
Notifications / announcements@sumx/sumx-editor@sumx/sumx-editor/rich-text-content
Email composer@sumx/sumx-editor
Manual invoice / standard textdynamic(() => import('@sumx/sumx-editor'))rich-text-content
Bill processing email logrich-text-content

@sumx/ui version

@sumx/sumx-editor@0.1.0 requires @sumx/ui ≥ 0.1.2 (Input, Label, Slider, DropdownMenu moved from editor into UI). Keep both on the same feed/local/vendor mode.