Skip to content

Commit

Permalink
Fix Preact component updating
Browse files Browse the repository at this point in the history
  • Loading branch information
lemonmade committed Sep 16, 2024
1 parent ad139f7 commit c41c4d1
Show file tree
Hide file tree
Showing 21 changed files with 102 additions and 46 deletions.
5 changes: 5 additions & 0 deletions .changeset/weak-dancers-relax.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@watching/clips-react': patch
---

Fix Preact component updating
13 changes: 7 additions & 6 deletions packages/clips-react/source/components/Action.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,15 @@ export const Action = forwardRef<ActionElement, ActionProps>(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 (
<ui-action
ref={ref}
{...props}
onpress={onPress ? (event) => event.respondWith(onPress()) : undefined}
>
<ui-action {...allProps} ref={wrapperRef}>
{children}
{overlay && isValidElement(overlay)
? cloneElement<any>(overlay, {slot: 'overlay'})
Expand Down
4 changes: 2 additions & 2 deletions packages/clips-react/source/components/BlockGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ declare module 'react' {

export const BlockGrid = forwardRef<BlockGridElement, BlockGridProps>(
function BlockGrid(props, ref) {
useCustomElementProperties(props, ref);
return <ui-block-grid {...props} ref={ref} />;
const wrapperRef = useCustomElementProperties(props, ref);
return <ui-block-grid {...props} ref={wrapperRef} />;
},
);
4 changes: 2 additions & 2 deletions packages/clips-react/source/components/BlockStack.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ declare module 'react' {

export const BlockStack = forwardRef<BlockStackElement, BlockStackProps>(
function BlockStack(props, ref) {
useCustomElementProperties(props, ref);
return <ui-block-stack {...props} ref={ref} />;
const wrapperRef = useCustomElementProperties(props, ref);
return <ui-block-stack {...props} ref={wrapperRef} />;
},
);
4 changes: 2 additions & 2 deletions packages/clips-react/source/components/Disclosure.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ export const Disclosure = forwardRef<DisclosureElement, DisclosureProps>(
}
}

useCustomElementProperties(allProps, ref);
const wrapperRef = useCustomElementProperties(allProps, ref);

return (
<ui-disclosure {...props} ref={ref}>
<ui-disclosure {...props} ref={wrapperRef}>
{children}
{labelElement}
</ui-disclosure>
Expand Down
4 changes: 2 additions & 2 deletions packages/clips-react/source/components/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ declare module 'react' {

export const Footer = forwardRef<FooterElement, FooterProps>(
function Footer(props, ref) {
useCustomElementProperties(props, ref);
return <ui-footer {...props} ref={ref} />;
const wrapperRef = useCustomElementProperties(props, ref);
return <ui-footer {...props} ref={wrapperRef} />;
},
);
4 changes: 2 additions & 2 deletions packages/clips-react/source/components/Grid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ declare module 'react' {

export const Grid = forwardRef<GridElement, GridProps>(
function Grid(props, ref) {
useCustomElementProperties(props, ref);
return <ui-grid {...props} ref={ref} />;
const wrapperRef = useCustomElementProperties(props, ref);
return <ui-grid {...props} ref={wrapperRef} />;
},
);
4 changes: 2 additions & 2 deletions packages/clips-react/source/components/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ declare module 'react' {

export const Header = forwardRef<HeaderElement, HeaderProps>(
function Header(props, ref) {
useCustomElementProperties(props, ref);
return <ui-header {...props} ref={ref} />;
const wrapperRef = useCustomElementProperties(props, ref);
return <ui-header {...props} ref={wrapperRef} />;
},
);
4 changes: 2 additions & 2 deletions packages/clips-react/source/components/Heading.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ declare module 'react' {

export const Heading = forwardRef<HeadingElement, HeadingProps>(
function Heading(props, ref) {
useCustomElementProperties(props, ref);
return <ui-heading {...props} ref={ref} />;
const wrapperRef = useCustomElementProperties(props, ref);
return <ui-heading {...props} ref={wrapperRef} />;
},
);
4 changes: 2 additions & 2 deletions packages/clips-react/source/components/Image.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ declare module 'react' {

export const Image = forwardRef<ImageElement, ImageProps>(
function Image(props, ref) {
useCustomElementProperties(props, ref);
return <ui-image {...props} ref={ref} />;
const wrapperRef = useCustomElementProperties(props, ref);
return <ui-image {...props} ref={wrapperRef} />;
},
);
4 changes: 2 additions & 2 deletions packages/clips-react/source/components/InlineGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ declare module 'react' {

export const InlineGrid = forwardRef<InlineGridElement, InlineGridProps>(
function InlineGrid(props, ref) {
useCustomElementProperties(props, ref);
return <ui-inline-grid {...props} ref={ref} />;
const wrapperRef = useCustomElementProperties(props, ref);
return <ui-inline-grid {...props} ref={wrapperRef} />;
},
);
4 changes: 2 additions & 2 deletions packages/clips-react/source/components/InlineStack.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ declare module 'react' {

export const InlineStack = forwardRef<InlineStackElement, InlineStackProps>(
function InlineStack(props, ref) {
useCustomElementProperties(props, ref);
return <ui-inline-stack {...props} ref={ref} />;
const wrapperRef = useCustomElementProperties(props, ref);
return <ui-inline-stack {...props} ref={wrapperRef} />;
},
);
4 changes: 2 additions & 2 deletions packages/clips-react/source/components/Modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ declare module 'react' {

export const Modal = forwardRef<ModalElement, ModalProps>(
function Modal(props, ref) {
useCustomElementProperties(props, ref);
return <ui-modal {...props} ref={ref} />;
const wrapperRef = useCustomElementProperties(props, ref);
return <ui-modal {...props} ref={wrapperRef} />;
},
);
4 changes: 2 additions & 2 deletions packages/clips-react/source/components/Popover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ declare module 'react' {

export const Popover = forwardRef<PopoverElement, PopoverProps>(
function Popover(props, ref) {
useCustomElementProperties(props, ref);
return <ui-popover {...props} ref={ref} />;
const wrapperRef = useCustomElementProperties(props, ref);
return <ui-popover {...props} ref={wrapperRef} />;
},
);
4 changes: 2 additions & 2 deletions packages/clips-react/source/components/Section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ declare module 'react' {

export const Section = forwardRef<SectionElement, SectionProps>(
function Section(props, ref) {
useCustomElementProperties(props, ref);
return <ui-section {...props} ref={ref} />;
const wrapperRef = useCustomElementProperties(props, ref);
return <ui-section {...props} ref={wrapperRef} />;
},
);
4 changes: 2 additions & 2 deletions packages/clips-react/source/components/Stack.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ declare module 'react' {

export const Stack = forwardRef<StackElement, StackProps>(
function Stack(props, ref) {
useCustomElementProperties(props, ref);
return <ui-stack {...props} ref={ref} />;
const wrapperRef = useCustomElementProperties(props, ref);
return <ui-stack {...props} ref={wrapperRef} />;
},
);
4 changes: 2 additions & 2 deletions packages/clips-react/source/components/Text.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ declare module 'react' {

export const Text = forwardRef<TextElement, TextProps>(
function Text(props, ref) {
useCustomElementProperties(props, ref);
return <ui-text {...props} ref={ref} />;
const wrapperRef = useCustomElementProperties(props, ref);
return <ui-text {...props} ref={wrapperRef} />;
},
);
4 changes: 2 additions & 2 deletions packages/clips-react/source/components/TextBlock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ declare module 'react' {

export const TextBlock = forwardRef<TextBlockElement, TextBlockProps>(
function TextBlock(props, ref) {
useCustomElementProperties(props, ref);
return <ui-text-block {...props} ref={ref} />;
const wrapperRef = useCustomElementProperties(props, ref);
return <ui-text-block {...props} ref={wrapperRef} />;
},
);
4 changes: 2 additions & 2 deletions packages/clips-react/source/components/TextField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,10 @@ export const TextField = forwardRef<TextFieldElement, TextFieldProps>(
}
}

useCustomElementProperties(allProps, ref);
const wrapperRef = useCustomElementProperties(allProps, ref);

return (
<ui-text-field {...allProps} ref={ref}>
<ui-text-field {...allProps} ref={wrapperRef}>
{labelChild}
</ui-text-field>
);
Expand Down
4 changes: 2 additions & 2 deletions packages/clips-react/source/components/View.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ declare module 'react' {

export const View = forwardRef<ViewElement, ViewProps>(
function View(props, ref) {
useCustomElementProperties(props, ref);
return <ui-view {...props} ref={ref} />;
const wrapperRef = useCustomElementProperties(props, ref);
return <ui-view {...props} ref={wrapperRef} />;
},
);
58 changes: 54 additions & 4 deletions packages/clips-react/source/components/shared.ts
Original file line number Diff line number Diff line change
@@ -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<T extends Element>(
props: Record<string, any>,
Expand All @@ -7,15 +13,22 @@ export function useCustomElementProperties<T extends Element>(
const internalsRef = useRef<{
names: Set<string>;
values: Record<string, any>;
ref: WrapperRef<T>;
}>();
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];
Expand Down Expand Up @@ -50,4 +63,41 @@ export function useCustomElementProperties<T extends Element>(

internals.names = newNames;
});

return internals.ref.callback;
}

class WrapperRef<T> implements RefObject<T> {
#wrapped: ForwardedRef<T>;
#current: T | null = null;

get wrapped() {
return this.#wrapped;
}

set wrapped(wrapped: ForwardedRef<T>) {
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<T> = (value) => {
this.current = value;
};

constructor(wrapped: ForwardedRef<T>) {
this.#wrapped = wrapped;
}
}

0 comments on commit c41c4d1

Please sign in to comment.