From c41c4d155064008e685734cee73f07afebb57ee7 Mon Sep 17 00:00:00 2001 From: Chris Sauve Date: Mon, 16 Sep 2024 00:44:39 -0400 Subject: [PATCH] Fix Preact component updating --- .changeset/weak-dancers-relax.md | 5 ++ .../clips-react/source/components/Action.tsx | 13 +++-- .../source/components/BlockGrid.tsx | 4 +- .../source/components/BlockStack.tsx | 4 +- .../source/components/Disclosure.tsx | 4 +- .../clips-react/source/components/Footer.tsx | 4 +- .../clips-react/source/components/Grid.tsx | 4 +- .../clips-react/source/components/Header.tsx | 4 +- .../clips-react/source/components/Heading.tsx | 4 +- .../clips-react/source/components/Image.tsx | 4 +- .../source/components/InlineGrid.tsx | 4 +- .../source/components/InlineStack.tsx | 4 +- .../clips-react/source/components/Modal.tsx | 4 +- .../clips-react/source/components/Popover.tsx | 4 +- .../clips-react/source/components/Section.tsx | 4 +- .../clips-react/source/components/Stack.tsx | 4 +- .../clips-react/source/components/Text.tsx | 4 +- .../source/components/TextBlock.tsx | 4 +- .../source/components/TextField.tsx | 4 +- .../clips-react/source/components/View.tsx | 4 +- .../clips-react/source/components/shared.ts | 58 +++++++++++++++++-- 21 files changed, 102 insertions(+), 46 deletions(-) create mode 100644 .changeset/weak-dancers-relax.md diff --git a/.changeset/weak-dancers-relax.md b/.changeset/weak-dancers-relax.md new file mode 100644 index 00000000..827d5878 --- /dev/null +++ b/.changeset/weak-dancers-relax.md @@ -0,0 +1,5 @@ +--- +'@watching/clips-react': patch +--- + +Fix Preact component updating diff --git a/packages/clips-react/source/components/Action.tsx b/packages/clips-react/source/components/Action.tsx index b4d2b019..47b15210 100644 --- a/packages/clips-react/source/components/Action.tsx +++ b/packages/clips-react/source/components/Action.tsx @@ -35,14 +35,15 @@ export const Action = forwardRef(function Action( {overlay, children, onPress, ...props}, ref, ) { - useCustomElementProperties(props, ref); + const allProps: ActionProps = { + onpress: onPress ? (event) => event.respondWith(onPress()) : undefined, + ...props, + }; + + const wrapperRef = useCustomElementProperties(allProps, ref); return ( - event.respondWith(onPress()) : undefined} - > + {children} {overlay && isValidElement(overlay) ? cloneElement(overlay, {slot: 'overlay'}) diff --git a/packages/clips-react/source/components/BlockGrid.tsx b/packages/clips-react/source/components/BlockGrid.tsx index da8fd3b0..116efa87 100644 --- a/packages/clips-react/source/components/BlockGrid.tsx +++ b/packages/clips-react/source/components/BlockGrid.tsx @@ -26,7 +26,7 @@ declare module 'react' { export const BlockGrid = forwardRef( function BlockGrid(props, ref) { - useCustomElementProperties(props, ref); - return ; + const wrapperRef = useCustomElementProperties(props, ref); + return ; }, ); diff --git a/packages/clips-react/source/components/BlockStack.tsx b/packages/clips-react/source/components/BlockStack.tsx index 57be8ea4..08c8a67e 100644 --- a/packages/clips-react/source/components/BlockStack.tsx +++ b/packages/clips-react/source/components/BlockStack.tsx @@ -26,7 +26,7 @@ declare module 'react' { export const BlockStack = forwardRef( function BlockStack(props, ref) { - useCustomElementProperties(props, ref); - return ; + const wrapperRef = useCustomElementProperties(props, ref); + return ; }, ); diff --git a/packages/clips-react/source/components/Disclosure.tsx b/packages/clips-react/source/components/Disclosure.tsx index dd472809..532c991d 100644 --- a/packages/clips-react/source/components/Disclosure.tsx +++ b/packages/clips-react/source/components/Disclosure.tsx @@ -41,10 +41,10 @@ export const Disclosure = forwardRef( } } - useCustomElementProperties(allProps, ref); + const wrapperRef = useCustomElementProperties(allProps, ref); return ( - + {children} {labelElement} diff --git a/packages/clips-react/source/components/Footer.tsx b/packages/clips-react/source/components/Footer.tsx index 7d9a1e07..30dbd30a 100644 --- a/packages/clips-react/source/components/Footer.tsx +++ b/packages/clips-react/source/components/Footer.tsx @@ -24,7 +24,7 @@ declare module 'react' { export const Footer = forwardRef( function Footer(props, ref) { - useCustomElementProperties(props, ref); - return ; + const wrapperRef = useCustomElementProperties(props, ref); + return ; }, ); diff --git a/packages/clips-react/source/components/Grid.tsx b/packages/clips-react/source/components/Grid.tsx index 85d907a0..c0a22245 100644 --- a/packages/clips-react/source/components/Grid.tsx +++ b/packages/clips-react/source/components/Grid.tsx @@ -27,7 +27,7 @@ declare module 'react' { export const Grid = forwardRef( function Grid(props, ref) { - useCustomElementProperties(props, ref); - return ; + const wrapperRef = useCustomElementProperties(props, ref); + return ; }, ); diff --git a/packages/clips-react/source/components/Header.tsx b/packages/clips-react/source/components/Header.tsx index 31ab4b70..11fdb6ee 100644 --- a/packages/clips-react/source/components/Header.tsx +++ b/packages/clips-react/source/components/Header.tsx @@ -21,7 +21,7 @@ declare module 'react' { export const Header = forwardRef( function Header(props, ref) { - useCustomElementProperties(props, ref); - return ; + const wrapperRef = useCustomElementProperties(props, ref); + return ; }, ); diff --git a/packages/clips-react/source/components/Heading.tsx b/packages/clips-react/source/components/Heading.tsx index ca14244b..618181ca 100644 --- a/packages/clips-react/source/components/Heading.tsx +++ b/packages/clips-react/source/components/Heading.tsx @@ -26,7 +26,7 @@ declare module 'react' { export const Heading = forwardRef( function Heading(props, ref) { - useCustomElementProperties(props, ref); - return ; + const wrapperRef = useCustomElementProperties(props, ref); + return ; }, ); diff --git a/packages/clips-react/source/components/Image.tsx b/packages/clips-react/source/components/Image.tsx index 7eefb253..7412360d 100644 --- a/packages/clips-react/source/components/Image.tsx +++ b/packages/clips-react/source/components/Image.tsx @@ -23,7 +23,7 @@ declare module 'react' { export const Image = forwardRef( function Image(props, ref) { - useCustomElementProperties(props, ref); - return ; + const wrapperRef = useCustomElementProperties(props, ref); + return ; }, ); diff --git a/packages/clips-react/source/components/InlineGrid.tsx b/packages/clips-react/source/components/InlineGrid.tsx index 85911fa5..cb027937 100644 --- a/packages/clips-react/source/components/InlineGrid.tsx +++ b/packages/clips-react/source/components/InlineGrid.tsx @@ -26,7 +26,7 @@ declare module 'react' { export const InlineGrid = forwardRef( function InlineGrid(props, ref) { - useCustomElementProperties(props, ref); - return ; + const wrapperRef = useCustomElementProperties(props, ref); + return ; }, ); diff --git a/packages/clips-react/source/components/InlineStack.tsx b/packages/clips-react/source/components/InlineStack.tsx index d58e390c..481fe827 100644 --- a/packages/clips-react/source/components/InlineStack.tsx +++ b/packages/clips-react/source/components/InlineStack.tsx @@ -26,7 +26,7 @@ declare module 'react' { export const InlineStack = forwardRef( function InlineStack(props, ref) { - useCustomElementProperties(props, ref); - return ; + const wrapperRef = useCustomElementProperties(props, ref); + return ; }, ); diff --git a/packages/clips-react/source/components/Modal.tsx b/packages/clips-react/source/components/Modal.tsx index 1b395c83..24f8f00a 100644 --- a/packages/clips-react/source/components/Modal.tsx +++ b/packages/clips-react/source/components/Modal.tsx @@ -23,7 +23,7 @@ declare module 'react' { export const Modal = forwardRef( function Modal(props, ref) { - useCustomElementProperties(props, ref); - return ; + const wrapperRef = useCustomElementProperties(props, ref); + return ; }, ); diff --git a/packages/clips-react/source/components/Popover.tsx b/packages/clips-react/source/components/Popover.tsx index c4a6a788..f1c6c7d5 100644 --- a/packages/clips-react/source/components/Popover.tsx +++ b/packages/clips-react/source/components/Popover.tsx @@ -22,7 +22,7 @@ declare module 'react' { export const Popover = forwardRef( function Popover(props, ref) { - useCustomElementProperties(props, ref); - return ; + const wrapperRef = useCustomElementProperties(props, ref); + return ; }, ); diff --git a/packages/clips-react/source/components/Section.tsx b/packages/clips-react/source/components/Section.tsx index 29c23963..52c17096 100644 --- a/packages/clips-react/source/components/Section.tsx +++ b/packages/clips-react/source/components/Section.tsx @@ -21,7 +21,7 @@ declare module 'react' { export const Section = forwardRef( function Section(props, ref) { - useCustomElementProperties(props, ref); - return ; + const wrapperRef = useCustomElementProperties(props, ref); + return ; }, ); diff --git a/packages/clips-react/source/components/Stack.tsx b/packages/clips-react/source/components/Stack.tsx index 7c8acd4d..623e1ef8 100644 --- a/packages/clips-react/source/components/Stack.tsx +++ b/packages/clips-react/source/components/Stack.tsx @@ -27,7 +27,7 @@ declare module 'react' { export const Stack = forwardRef( function Stack(props, ref) { - useCustomElementProperties(props, ref); - return ; + const wrapperRef = useCustomElementProperties(props, ref); + return ; }, ); diff --git a/packages/clips-react/source/components/Text.tsx b/packages/clips-react/source/components/Text.tsx index d3a19c8e..b3a966e6 100644 --- a/packages/clips-react/source/components/Text.tsx +++ b/packages/clips-react/source/components/Text.tsx @@ -23,7 +23,7 @@ declare module 'react' { export const Text = forwardRef( function Text(props, ref) { - useCustomElementProperties(props, ref); - return ; + const wrapperRef = useCustomElementProperties(props, ref); + return ; }, ); diff --git a/packages/clips-react/source/components/TextBlock.tsx b/packages/clips-react/source/components/TextBlock.tsx index 94194a2a..970e60b0 100644 --- a/packages/clips-react/source/components/TextBlock.tsx +++ b/packages/clips-react/source/components/TextBlock.tsx @@ -22,7 +22,7 @@ declare module 'react' { export const TextBlock = forwardRef( function TextBlock(props, ref) { - useCustomElementProperties(props, ref); - return ; + const wrapperRef = useCustomElementProperties(props, ref); + return ; }, ); diff --git a/packages/clips-react/source/components/TextField.tsx b/packages/clips-react/source/components/TextField.tsx index 80be3da2..44a23e4b 100644 --- a/packages/clips-react/source/components/TextField.tsx +++ b/packages/clips-react/source/components/TextField.tsx @@ -51,10 +51,10 @@ export const TextField = forwardRef( } } - useCustomElementProperties(allProps, ref); + const wrapperRef = useCustomElementProperties(allProps, ref); return ( - + {labelChild} ); diff --git a/packages/clips-react/source/components/View.tsx b/packages/clips-react/source/components/View.tsx index 93393e19..0c691156 100644 --- a/packages/clips-react/source/components/View.tsx +++ b/packages/clips-react/source/components/View.tsx @@ -36,7 +36,7 @@ declare module 'react' { export const View = forwardRef( function View(props, ref) { - useCustomElementProperties(props, ref); - return ; + const wrapperRef = useCustomElementProperties(props, ref); + return ; }, ); diff --git a/packages/clips-react/source/components/shared.ts b/packages/clips-react/source/components/shared.ts index 5356a770..2626d040 100644 --- a/packages/clips-react/source/components/shared.ts +++ b/packages/clips-react/source/components/shared.ts @@ -1,4 +1,10 @@ -import {useLayoutEffect, useRef, type ForwardedRef} from 'react'; +import { + useLayoutEffect, + useRef, + type ForwardedRef, + type RefObject, + type RefCallback, +} from 'react'; export function useCustomElementProperties( props: Record, @@ -7,15 +13,22 @@ export function useCustomElementProperties( const internalsRef = useRef<{ names: Set; values: Record; + ref: WrapperRef; }>(); - internalsRef.current ??= {names: new Set(), values: {}}; + internalsRef.current ??= { + names: new Set(), + values: {}, + ref: new WrapperRef(ref), + }; + + const internals = internalsRef.current; + internals.ref.wrapped = ref; useLayoutEffect(() => { - const internals = internalsRef.current!; const oldNames = new Set(internals.names); const newNames = new Set(Object.keys(props)); - const element = typeof ref === 'function' ? undefined : ref?.current; + const element = internals.ref.current; for (const name of newNames) { const newValue = props[name]; @@ -50,4 +63,41 @@ export function useCustomElementProperties( internals.names = newNames; }); + + return internals.ref.callback; +} + +class WrapperRef implements RefObject { + #wrapped: ForwardedRef; + #current: T | null = null; + + get wrapped() { + return this.#wrapped; + } + + set wrapped(wrapped: ForwardedRef) { + this.#wrapped = wrapped; + } + + get current() { + return this.#current; + } + + set current(value: T | null) { + this.#current = value; + + if (typeof this.#wrapped === 'function') { + this.#wrapped(value); + } else if (this.#wrapped) { + this.#wrapped.current = value; + } + } + + callback: RefCallback = (value) => { + this.current = value; + }; + + constructor(wrapped: ForwardedRef) { + this.#wrapped = wrapped; + } }