From e9dfd4e39e339050d32f8062bca4213f12792db0 Mon Sep 17 00:00:00 2001 From: TransQuinnFTW Date: Sun, 1 Feb 2026 04:54:14 -0800 Subject: [PATCH] =?UTF-8?q?chore(ui-dev-content):=20=F0=9F=94=A7=20Introdu?= =?UTF-8?q?ce=20EditableContent=20component,=20ContentEditingContext,=20an?= =?UTF-8?q?d=20useEditableContent=20hook=20for=20reusable=20UI=20content?= =?UTF-8?q?=20editing=20via=20React=20context?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Lilith Autocommit --- .../src/components/EditableContent.tsx | 4 +- .../src/core/ContentEditingContext.tsx | 38 ++++++++++++------- .../src/hooks/useEditableContent.ts | 4 +- 3 files changed, 28 insertions(+), 18 deletions(-) diff --git a/packages/ui-dev-content/src/components/EditableContent.tsx b/packages/ui-dev-content/src/components/EditableContent.tsx index b403266..74e2ef8 100644 --- a/packages/ui-dev-content/src/components/EditableContent.tsx +++ b/packages/ui-dev-content/src/components/EditableContent.tsx @@ -55,8 +55,8 @@ export function EditableContent({ const registry = useContentRegistry(); useEffect(() => { - // Only register in development mode - if (!import.meta.env.DEV || !ref.current) { + // Only register in development mode and when provider is available + if (!import.meta.env.DEV || !ref.current || !registry) { return; } diff --git a/packages/ui-dev-content/src/core/ContentEditingContext.tsx b/packages/ui-dev-content/src/core/ContentEditingContext.tsx index 7e53a27..89c24af 100644 --- a/packages/ui-dev-content/src/core/ContentEditingContext.tsx +++ b/packages/ui-dev-content/src/core/ContentEditingContext.tsx @@ -148,9 +148,19 @@ export function ContentEditingProvider({ // ============================================================================ /** - * Access the content editing registry and state + * Access the content editing registry and state. + * Returns null when used outside ContentEditingProvider (graceful degradation + * for components like EditableContent that render in non-dev contexts). */ -export function useContentEditing() { +export function useContentEditing(): ContentEditingContextValue | null { + return useContext(ContentEditingContext); +} + +/** + * Access the content editing registry and state (strict version). + * Throws if used outside ContentEditingProvider. + */ +export function useContentEditingStrict(): ContentEditingContextValue { const context = useContext(ContentEditingContext); if (!context) { throw new Error('useContentEditing must be used within ContentEditingProvider'); @@ -159,35 +169,35 @@ export function useContentEditing() { } /** - * Access just the registry + * Access just the registry (returns null outside provider) */ export function useContentRegistry() { - const { registry } = useContentEditing(); - return registry; + const editing = useContentEditing(); + return editing?.registry ?? null; } /** - * Access detected content handles + * Access detected content handles (strict — requires provider) */ export function useContentHandles() { - const { handles, refreshHandles } = useContentEditing(); - return { handles, refresh: refreshHandles }; + const context = useContentEditingStrict(); + return { handles: context.handles, refresh: context.refreshHandles }; } /** - * Access overlay visibility state + * Access overlay visibility state (strict — requires provider) */ export function useOverlayState() { - const { overlayVisible, setOverlayVisible } = useContentEditing(); - return [overlayVisible, setOverlayVisible] as const; + const context = useContentEditingStrict(); + return [context.overlayVisible, context.setOverlayVisible] as const; } /** - * Access selected handle state + * Access selected handle state (strict — requires provider) */ export function useSelectedHandle() { - const { selectedHandle, setSelectedHandle } = useContentEditing(); - return [selectedHandle, setSelectedHandle] as const; + const context = useContentEditingStrict(); + return [context.selectedHandle, context.setSelectedHandle] as const; } // Re-export the singleton registry for direct access diff --git a/packages/ui-dev-content/src/hooks/useEditableContent.ts b/packages/ui-dev-content/src/hooks/useEditableContent.ts index 031d6c2..95aa70a 100644 --- a/packages/ui-dev-content/src/hooks/useEditableContent.ts +++ b/packages/ui-dev-content/src/hooks/useEditableContent.ts @@ -54,12 +54,12 @@ export function useEditableContent({ const registry = useContentRegistry(); useEffect(() => { - // Skip if dev-only and not in dev mode + // Skip if dev-only and not in dev mode, or if no provider available if (devOnly && !import.meta.env.DEV) { return; } - if (!ref.current) { + if (!ref.current || !registry) { return; }