Skip to content

Commit

Permalink
feat(panel): smoother accessing of widgetRenderState (#4558)
Browse files Browse the repository at this point in the history
* WIP

* now it works

* better example

* revert for lower ts used here

* gotta be more generic
  • Loading branch information
Haroenv authored Nov 2, 2020
1 parent 56930d3 commit 73f4fbf
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 25 deletions.
10 changes: 6 additions & 4 deletions src/components/Panel/Panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { useState, useEffect, useRef } from 'preact/hooks';
import cx from 'classnames';
import Template from '../Template/Template';
import { PanelCSSClasses, PanelTemplates } from '../../widgets/panel/panel';
import { RenderOptions } from '../../types';
import { RenderOptions, WidgetFactory } from '../../types';

type PanelComponentCSSClasses = Required<
Omit<
Expand All @@ -17,17 +17,19 @@ type PanelComponentCSSClasses = Required<
>
>;

type PanelProps = {
type PanelProps<TWidget extends WidgetFactory<any, any, any>> = {
hidden: boolean;
collapsible: boolean;
isCollapsed: boolean;
data: RenderOptions;
cssClasses: PanelComponentCSSClasses;
templates: Required<PanelTemplates>;
templates: Required<PanelTemplates<TWidget>>;
bodyElement: HTMLElement;
};

function Panel(props: PanelProps) {
function Panel<TWidget extends WidgetFactory<any, any, any>>(
props: PanelProps<TWidget>
) {
const [isCollapsed, setIsCollapsed] = useState<boolean>(props.isCollapsed);
const [isControlled, setIsControlled] = useState<boolean>(false);
const bodyRef = useRef<HTMLElement | null>(null);
Expand Down
37 changes: 19 additions & 18 deletions src/widgets/panel/panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,16 +59,16 @@ export type PanelCSSClasses = {
footer?: string | string[];
};

export type PanelTemplates = {
export type PanelTemplates<TWidget extends WidgetFactory<any, any, any>> = {
/**
* Template to use for the header.
*/
header?: Template<RenderOptions>;
header?: Template<PanelRenderOptions<TWidget>>;

/**
* Template to use for the footer.
*/
footer?: Template<RenderOptions>;
footer?: Template<PanelRenderOptions<TWidget>>;

/**
* Template to use for collapse button.
Expand All @@ -78,11 +78,11 @@ export type PanelTemplates = {

export type PanelRenderOptions<
TWidget extends WidgetFactory<any, any, any>
> = RenderOptions & {
widgetRenderState: ReturnType<
Exclude<ReturnType<TWidget>['getWidgetRenderState'], undefined>
>;
};
> = RenderOptions & ReturnType<TWidget>['getWidgetRenderState'] extends (
renderOptions: any
) => infer TRenderState
? TRenderState
: Record<string, any>;

export type PanelWidgetOptions<TWidget extends WidgetFactory<any, any, any>> = {
/**
Expand All @@ -100,7 +100,7 @@ export type PanelWidgetOptions<TWidget extends WidgetFactory<any, any, any>> = {
/**
* The templates to use for the widget.
*/
templates?: PanelTemplates;
templates?: PanelTemplates<TWidget>;

/**
* The CSS classes to override.
Expand All @@ -111,14 +111,14 @@ export type PanelWidgetOptions<TWidget extends WidgetFactory<any, any, any>> = {
const withUsage = createDocumentationMessageGenerator({ name: 'panel' });
const suit = component('Panel');

const renderer = ({
const renderer = <TWidget extends WidgetFactory<any, any, any>>({
containerNode,
bodyContainerNode,
cssClasses,
templates,
}) => ({ options, hidden, collapsible, collapsed }) => {
render(
<Panel
<Panel<TWidget>
cssClasses={cssClasses}
hidden={hidden}
collapsible={collapsible}
Expand All @@ -132,12 +132,12 @@ const renderer = ({
};

export type PanelWidget = <TWidget extends WidgetFactory<any, any, any>>(
params?: PanelWidgetOptions<TWidget>
widgetParams?: PanelWidgetOptions<TWidget>
) => <
TWidgetOptions extends { container: HTMLElement | string; [key: string]: any }
TWidgetParams extends { container: HTMLElement | string; [key: string]: any }
>(
widgetFactory: (widgetOptions: TWidgetOptions) => Widget
) => (widgetOptions: TWidgetOptions) => Widget;
widgetFactory: TWidget
) => (widgetOptions: TWidgetParams) => Widget;

/**
* The panel widget wraps other widgets in a consistent panel design.
Expand Down Expand Up @@ -222,7 +222,7 @@ const panel: PanelWidget = widgetParams => {
</svg>`,
};

const renderPanel = renderer({
const renderPanel = renderer<typeof widgetFactory>({
containerNode: getContainerNode(container),
bodyContainerNode,
cssClasses,
Expand Down Expand Up @@ -259,9 +259,10 @@ const panel: PanelWidget = widgetParams => {
const [renderOptions] = args;

const options = {
...(widget.getWidgetRenderState
? widget.getWidgetRenderState(renderOptions)
: {}),
...renderOptions,
widgetRenderState: (widget.getWidgetRenderState?.(renderOptions) ||
{}) as any,
};

renderPanel({
Expand Down
8 changes: 5 additions & 3 deletions stories/panel.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,11 +151,13 @@ storiesOf('Basics/Panel', module)
withHits(
({ search, container }) => {
const breadcrumbInPanel = panel<typeof breadcrumb>({
collapsed({ widgetRenderState }) {
return widgetRenderState.canRefine;
collapsed({ canRefine }) {
return canRefine === false;
},
templates: {
header: 'Collapsible panel',
header({ canRefine }) {
return `Breadcrumb that can${canRefine ? '' : "'t "} refine`;
},
footer:
'The panel collapses if it cannot refine. Click "Home". This panel will collapse and you will not see this footer anymore.',
},
Expand Down

0 comments on commit 73f4fbf

Please sign in to comment.