Skip to content

Commit

Permalink
convert useSlot
Browse files Browse the repository at this point in the history
  • Loading branch information
torounit committed Jun 10, 2023
1 parent 5ffe804 commit 5f2c520
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 21 deletions.
4 changes: 2 additions & 2 deletions packages/components/src/slot-fill/context.ts
Expand Up @@ -12,8 +12,8 @@ const initialValue: BaseSlotFillContext = {
unregisterSlot: () => {},
registerFill: () => {},
unregisterFill: () => {},
getSlot: () => {},
getFills: () => {},
getSlot: () => undefined,
getFills: () => [],
subscribe: () => () => {},
};
export const SlotFillContext = createContext( initialValue );
Expand Down
29 changes: 22 additions & 7 deletions packages/components/src/slot-fill/provider.tsx
Expand Up @@ -7,19 +7,26 @@ import type { Component } from '@wordpress/element';
* Internal dependencies
*/
import SlotFillContext from './context';
import type { BaseFillObject, BaseSlotFillContext } from './types';
import type {
BaseFillObject,
BaseSlotFillContext,
SlotComponentProps,
} from './types';
import { useState } from '@wordpress/element';
/**
* External dependencies
*/
import type { ReactNode } from 'react';

export function createSlotRegistory(): BaseSlotFillContext {
const slots: Record< string, Component > = {};
const fills: Record< string, unknown[] > = {};
const slots: Record< string, Component< SlotComponentProps > > = {};
const fills: Record< string, BaseFillObject[] > = {};
let listeners: Array< () => void > = [];

function registerSlot( name: string, slot: Component ) {
function registerSlot(
name: string,
slot: Component< SlotComponentProps >
) {
const previousSlot = slots[ name ];
slots[ name ] = slot;
triggerListeners();
Expand All @@ -42,7 +49,10 @@ export function createSlotRegistory(): BaseSlotFillContext {
forceUpdateSlot( name );
}

function unregisterSlot( name: string, instance: Component ) {
function unregisterSlot(
name: string,
instance: Component< SlotComponentProps >
) {
// If a previous instance of a Slot by this name unmounts, do nothing,
// as the slot and its fills should only be removed for the current
// known instance.
Expand All @@ -60,11 +70,16 @@ export function createSlotRegistory(): BaseSlotFillContext {
forceUpdateSlot( name );
}

function getSlot( name: string ) {
function getSlot(
name: string
): Component< SlotComponentProps > | undefined {
return slots[ name ];
}

function getFills( name: string, slotInstance: Component ) {
function getFills(
name: string,
slotInstance: Component< SlotComponentProps >
): BaseFillObject[] {
// Fills should only be returned for the current instance of the slot
// in which they occupy.
if ( slots[ name ] !== slotInstance ) {
Expand Down
34 changes: 26 additions & 8 deletions packages/components/src/slot-fill/types.ts
Expand Up @@ -4,13 +4,22 @@
import type { Component, ReactNode, ReactElement } from 'react';

export type BaseSlotFillContext = {
registerSlot: ( name: string, slot: Component ) => void;
unregisterSlot: ( name: string, slot: Component ) => void;
registerSlot: (
name: string,
slot: Component< SlotComponentProps >
) => void;
unregisterSlot: (
name: string,
slot: Component< SlotComponentProps >
) => void;
registerFill: ( name: string, instance: BaseFillObject ) => void;
unregisterFill: ( name: string, instance: BaseFillObject ) => void;
getSlot: ( name: string ) => any;
getFills: ( name: string, slotInstance: any ) => any;
subscribe: ( listener: () => {} ) => () => void;
getSlot: ( name: string ) => Component< SlotComponentProps > | undefined;
getFills: (
name: string,
slotInstance: Component< SlotComponentProps >
) => BaseFillObject[];
subscribe: ( listener: () => void ) => () => void;
};

export type BaseSlotProps = {
Expand All @@ -20,9 +29,18 @@ export type BaseSlotProps = {
};

export type SlotComponentProps = {
registerSlot: ( name: string, slot: Component ) => void;
unregisterSlot: ( name: string, slot: Component ) => void;
getFills: ( name: string, slotInstance: Component ) => BaseFillObject[];
registerSlot: (
name: string,
slot: Component< SlotComponentProps >
) => void;
unregisterSlot: (
name: string,
slot: Component< SlotComponentProps >
) => void;
getFills: (
name: string,
slotInstance: Component< SlotComponentProps >
) => BaseFillObject[];
} & BaseSlotProps;

export type BaseFillObject = {
Expand Down
@@ -1,4 +1,8 @@
// @ts-nocheck
/**
* External dependencies
*/
import type { Component } from 'react';

/**
* WordPress dependencies
*/
Expand All @@ -13,11 +17,11 @@ import SlotFillContext from './context';
* React hook returning the active slot given a name.
*
* @param {string} name Slot name.
* @return {Object} Slot object.
* @return {Component|undefined} Slot object.
*/
const useSlot = ( name ) => {
const useSlot = ( name: string ) => {
const { getSlot, subscribe } = useContext( SlotFillContext );
return useSyncExternalStore(
return useSyncExternalStore< Component | undefined >(
subscribe,
() => getSlot( name ),
() => getSlot( name )
Expand Down

0 comments on commit 5f2c520

Please sign in to comment.