Skip to content

Commit

Permalink
runtime possible impl
Browse files Browse the repository at this point in the history
  • Loading branch information
Aslemammad committed Feb 10, 2024
1 parent 4a7826c commit 45f109f
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 10 deletions.
3 changes: 2 additions & 1 deletion packages/kitchen-sink/src/examples/context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ const App_1 = _compiledBlock(_props2 => <div>
{_props2.v0}
</div>, {
name: "App_1",
portals: ["v0"]
portals: ["v0"],
scoped: ['Context_1']
});
const App = () => {
const [theme, setTheme] = useState('light');
Expand Down
1 change: 1 addition & 0 deletions packages/react/block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ 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
33 changes: 24 additions & 9 deletions packages/react/compiled-block.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
// The following code are for the compield `block` components
import type { ReactPortal, ComponentType, JSX } from 'react';
import { createElement, useState, Fragment, useEffect } from 'react';
import {
createElement,
useState,
Fragment,
useEffect,
useContext,
} from 'react';
import { createPortal } from 'react-dom';
import type { MillionPortal, MillionProps, Options } from '../types';
import { block, mountContext } from './block';
import { block, mountContext, scopedContext } from './block';
import { renderReactScope } from './utils';
import { experimental_options } from '../million/experimental';

Expand All @@ -28,28 +34,33 @@ function shouldCompiledBlockUpdate(
interface CompiledBlockOptions
extends Omit<Options<MillionProps>, 'shouldUpdate'> {
portals?: string[];
scoped?: string[];
}

export function compiledBlock(
render: (props: MillionProps) => JSX.Element,
{ portals, ...options }: CompiledBlockOptions
): ComponentType<MillionProps> {
const noSlot = options?.experimental_noSlot ?? experimental_options.noSlot;
const blockName = `CompiledBlock(Inner(${options.name}))`;
const RenderBlock = block<MillionProps>((props) => render(props), {
...options,
name: `CompiledBlock(Inner(${options.name}))`,
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 [current] = useState<MillionPortal[]>(() => []);
const [mounted, mount] = useState(false);

let derived = { ...props };
let derived = { ...props, scoped };

for (let i = 0; i < portalCount; i++) {
const index = portals[i]!;
Expand All @@ -71,10 +82,14 @@ export function compiledBlock(
}

return createElement(
mountContext.Provider,
{ value: mount },
createElement(RenderBlock, derived),
mounted ? targets : null
scopedContext.Provider,
{ value: scopedBlocks },
createElement(
mountContext.Provider,
{ value: mount },
createElement(RenderBlock, derived),
mounted ? targets : null
)
);
}
: (props: MillionProps) => createElement(RenderBlock, props);
Expand Down

0 comments on commit 45f109f

Please sign in to comment.