Skip to content

Commit

Permalink
scoped portals impl (suggested by Alexis), not sure if it'd work
Browse files Browse the repository at this point in the history
  • Loading branch information
Aslemammad committed Feb 10, 2024
1 parent 45f109f commit 39e1121
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 24 deletions.
2 changes: 1 addition & 1 deletion packages/kitchen-sink/src/examples/context.tsx
Expand Up @@ -56,7 +56,7 @@ const App_1 = _compiledBlock(_props2 => <div>
</div>, {
name: "App_1",
portals: ["v0"],
scoped: ['Context_1']
scoped: ["v0"],
});
const App = () => {
const [theme, setTheme] = useState('light');
Expand Down
1 change: 0 additions & 1 deletion packages/react/block.ts
Expand Up @@ -16,7 +16,6 @@ import { cloneNode$ } from '../million/dom';

experimental_options.noSlot = true;
export const mountContext = createContext<Dispatch<SetStateAction<boolean>> | null>(null)
export const scopedContext = createContext<string[]>([])

export const block = <P extends MillionProps>(
fn: ComponentType<P> | null,
Expand Down
27 changes: 10 additions & 17 deletions packages/react/compiled-block.ts
Expand Up @@ -9,8 +9,8 @@ import {
} from 'react';
import { createPortal } from 'react-dom';
import type { MillionPortal, MillionProps, Options } from '../types';
import { block, mountContext, scopedContext } from './block';
import { renderReactScope } from './utils';
import { block, mountContext } from './block';
import { renderReactScope, scopedContext } from './utils';
import { experimental_options } from '../million/experimental';

function isEqual(a: unknown, b: unknown): boolean {
Expand Down Expand Up @@ -44,19 +44,17 @@ export function compiledBlock(
const blockName = `CompiledBlock(Inner(${options.name}))`;
const RenderBlock = block<MillionProps>((props) => render(props), {
...options,
scoped: undefined,
name: blockName,
shouldUpdate: shouldCompiledBlockUpdate,
});
const scopedBlocks = options.scoped ?? [];

const portalCount = portals?.length || 0;

const Component: ComponentType<MillionProps> =
portals && portalCount > 0
? (props: MillionProps) => {
const scoped = options?.name
? useContext(scopedContext).includes(options.name)
: false;
const scoped = useContext(scopedContext);
const [current] = useState<MillionPortal[]>(() => []);
const [mounted, mount] = useState(false);

Expand All @@ -68,11 +66,10 @@ export function compiledBlock(
derived[index] as JSX.Element,
false,
current,
i
i,
options.scoped?.includes(index)
);
// if (!noSlot) {
derived[index] = scope;
// }
}

const targets: ReactPortal[] = [];
Expand All @@ -82,14 +79,10 @@ export function compiledBlock(
}

return createElement(
scopedContext.Provider,
{ value: scopedBlocks },
createElement(
mountContext.Provider,
{ value: mount },
createElement(RenderBlock, derived),
mounted ? targets : null
)
mountContext.Provider,
{ value: mount },
createElement(RenderBlock, derived),
mounted ? targets : null
);
}
: (props: MillionProps) => createElement(RenderBlock, props);
Expand Down
16 changes: 11 additions & 5 deletions packages/react/utils.ts
@@ -1,15 +1,17 @@
import { Fragment, createElement, isValidElement } from 'react';
import { Fragment, createContext, createElement, isValidElement } from 'react';
import { createPortal } from 'react-dom';
import type { ComponentProps, ReactNode, Ref } from 'react';
import type { VNode } from '../million';
import type { MillionPortal } from '../types';
import { REGISTRY, RENDER_SCOPE } from './constants';

export const scopedContext = createContext<boolean>(false)

// TODO: access perf impact of this
export const processProps = (
props: ComponentProps<any>,
ref: Ref<any>,
portals: MillionPortal[],
portals: MillionPortal[]
): ComponentProps<any> => {
const processedProps: ComponentProps<any> = { ref };

Expand All @@ -25,7 +27,7 @@ export const processProps = (
value,
false,
portals,
currentIndex++,
currentIndex++
);

continue;
Expand All @@ -45,6 +47,7 @@ export const renderReactScope = (
unstable: boolean,
portals: MillionPortal[] | undefined,
currentIndex: number,
scoped?: boolean
) => {
const el = portals?.[currentIndex]?.current;

Expand Down Expand Up @@ -75,7 +78,10 @@ export const renderReactScope = (
}

const current = el ?? document.createElement(RENDER_SCOPE);
const reactPortal = createPortal(vnode, current);
const reactPortal = createPortal(
createElement(scopedContext.Provider, { value: scoped }, vnode),
current
);

const millionPortal = {
foreign: true as const,
Expand Down Expand Up @@ -115,7 +121,7 @@ export const unwrap = (vnode: JSX.Element | null): VNode => {
const children = vnode.props?.children;
if (children !== undefined && children !== null) {
props.children = flatten(vnode.props.children).map((child) =>
unwrap(child),
unwrap(child)
);
}

Expand Down

0 comments on commit 39e1121

Please sign in to comment.