Content Composer
ilinxa/content-composerFreeBlock
Multi-step content authoring shell — each content type is a JSON config composing form, rich text, and media editing steps.
Install it
npx shadcn@latest add https://ui.ilinxa.com/r/content-composer.jsonSource
1"use client";23import * as React from "react";4import type {5 ComposerCtx,6 ComposerDraft,7 ComposerStepCtx,8 ComposerStepValue,9 NewsCardItem,10 ContentComposerHandle,11 ContentComposerProps,12 ExportMetadata,13 GateResult,14 MediaSlotValue,15 SlotHandle,16 SlotKind,17 SlotValueFor,18} from "./types";19import { makeEmptyDraft } from "./lib/reducer";20import { DEFAULT_SUBSTRATES } from "./lib/substrates";21import { evaluateStep } from "./lib/gates";22import { resolveUploader } from "./lib/upload";23import { resolvePublishCtaArms } from "./lib/publish-cta";24import { getAdapter } from "./adapters/adapter-registry";25import { useComposerState } from "./hooks/use-composer-state";26import { useSlotHandles } from "./hooks/use-slot-handles";27import { useAutosave } from "./hooks/use-autosave";28import { ComposerContext, ComposerStepContext } from "./hooks/use-composer-context";29import { ComposerShell } from "./parts/composer-shell";30import { ComposerDialog } from "./parts/composer-dialog";31import { SlotMount } from "./parts/slot-mount";32import { MediaSourceBlobCacheContext } from "./parts/media-substrate";33import {34 CarouselLiveCacheContext,35 carouselDisplacedUrls,36} from "./parts/media-carousel-substrate";37import type { MediaCarouselItem } from "@/registry/components/media/carousel-composer/carousel-composer";38import { PublishBar } from "./parts/publish-bar";3940function errorMessage(e: unknown): string {41 return e instanceof Error ? e.message : String(e);42}4344/**45 * content-composer — the multi-step content-authoring SHELL.46 *47 * One JSON `ComposerConfig` per content type drives the steps; each step's slot48 * is rendered by a substrate (json-form / rich-text-editor / media-editor).49 * The shell owns step navigation + the blocking gates, autosave (draft-level50 * dirty), the draft → publish → schedule FSM, lazy upload-on-publish, and the51 * per-content-type adapter to the backend `NewsCardItem`.52 */53export const ContentComposer = React.forwardRef<54 ContentComposerHandle,55 ContentComposerProps56>(function ContentComposer(props, ref) {57 const { config } = props;5859 // ── Seed (T1): controlled value wins; else defaultValue; else inverse-adapter60 // from initialItem; the body always re-seeds via the separate initialBody leg.61 const [initialDraft] = React.useState<ComposerDraft>(() => {62 const base = props.defaultValue ?? makeEmptyDraft(config.id);63 let seeded = base;64 if (!props.defaultValue && props.initialItem) {65// … truncated
What it pulls in
npm packages
Other registry items
Files it writes
More from ilinxa
All 184 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Account Switcheraccount-switcher | ilinxa | Blocks | Free | 1 dep · 10 files | |
| Account Switcher (deprecated alias)account-switcher-01 | ilinxa | Blocks | Free | no deps | |
| Account Switcher — fixturesaccount-switcher-fixtures | ilinxa | Blocks | Free | no deps | |
| App Sidebarapp-sidebar | ilinxa | Blocks | Free | 1 dep · 37 files | |
| App Sidebar — fixturesapp-sidebar-fixtures | ilinxa | Blocks | Free | no deps | |
| Rich Text Editor (deprecated alias)article-body-01 | ilinxa | Blocks | Free | no deps | |
| Article Metaarticle-meta | ilinxa | Blocks | Free | 1 dep · 4 files | |
| Article Meta (deprecated alias)article-meta-01 | ilinxa | Blocks | Free | no deps |
