Skip to content

Commit

Permalink
Added Surface Layouts Definition
Browse files Browse the repository at this point in the history
  • Loading branch information
ggazzo committed Jun 9, 2021
1 parent 5bcd10d commit 9529f84
Show file tree
Hide file tree
Showing 15 changed files with 161 additions and 72 deletions.
5 changes: 2 additions & 3 deletions packages/ui-kit/src/blocks/isTextObject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,5 @@ import { Block } from './Block';
import { TextObject } from './TextObject';
import { TextObjectType } from './TextObjectType';

export const isTextObject = (block: Block): block is TextObject => {
return (Object.values(TextObjectType) as string[]).includes(block.type);
};
export const isTextObject = (block: Block): block is TextObject =>
(Object.values(TextObjectType) as string[]).includes(block.type);
21 changes: 12 additions & 9 deletions packages/ui-kit/src/blocks/layout/ActionsBlock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,17 @@ import { MultiStaticSelectElement } from '../elements/MultiStaticSelectElement';
import { OverflowElement } from '../elements/OverflowElement';
import { StaticSelectElement } from '../elements/StaticSelectElement';

export type ActionsBlock = Layout<{
type ActionsBlockElements =
| ButtonElement
| StaticSelectElement
| MultiStaticSelectElement
| OverflowElement
| DatePickerElement
| LinearScaleElement;

export type ActionsBlock<
Elements extends ActionsBlockElements = ActionsBlockElements
> = Layout<{
type: `${LayoutBlockType.ACTIONS}`;
elements: (
| ButtonElement
| StaticSelectElement
| MultiStaticSelectElement
| OverflowElement
| DatePickerElement
| LinearScaleElement
)[];
elements: Elements[];
}>;
7 changes: 5 additions & 2 deletions packages/ui-kit/src/blocks/layout/ContextBlock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ import { LayoutBlockType } from '../LayoutBlockType';
import { TextObject } from '../TextObject';
import { ImageElement } from '../elements/ImageElement';

export type ContextBlock = Layout<{
type ContextBlockElements = TextObject | ImageElement;
export type ContextBlock<
Elements extends ContextBlockElements = ContextBlockElements
> = Layout<{
type: `${LayoutBlockType.CONTEXT}`;
elements: (TextObject | ImageElement)[];
elements: Elements[];
}>;
24 changes: 14 additions & 10 deletions packages/ui-kit/src/blocks/layout/InputBlock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,22 @@ import { StaticSelectElement } from '../elements/StaticSelectElement';
import { UsersSelectElement } from '../elements/UsersSelectElement';
import { PlainText } from '../text/PlainText';

export type InputBlock = Layout<{
type InputBlockElement =
| ChannelsSelectElement
| ConversationsSelectElement
| DatePickerElement
| LinearScaleElement
| MultiStaticSelectElement
| PlainTextInputElement
| StaticSelectElement
| UsersSelectElement;

export type InputBlock<
Element extends InputBlockElement = InputBlockElement
> = Layout<{
type: `${LayoutBlockType.INPUT}`;
label: PlainText;
element:
| ChannelsSelectElement
| ConversationsSelectElement
| DatePickerElement
| LinearScaleElement
| MultiStaticSelectElement
| PlainTextInputElement
| StaticSelectElement
| UsersSelectElement;
element: Element;
hint?: PlainText;
optional?: boolean;
}>;
20 changes: 12 additions & 8 deletions packages/ui-kit/src/blocks/layout/SectionBlock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,19 @@ import { MultiStaticSelectElement } from '../elements/MultiStaticSelectElement';
import { OverflowElement } from '../elements/OverflowElement';
import { StaticSelectElement } from '../elements/StaticSelectElement';

export type SectionBlock = Layout<{
type SectionBlockAcessory =
| ButtonElement
| DatePickerElement
| ImageElement
| MultiStaticSelectElement
| OverflowElement
| StaticSelectElement;

export type SectionBlock<
Acessory extends SectionBlockAcessory = SectionBlockAcessory
> = Layout<{
type: 'section';
text?: TextObject;
fields?: TextObject[];
accessory?:
| ButtonElement
| DatePickerElement
| ImageElement
| MultiStaticSelectElement
| OverflowElement
| StaticSelectElement;
accessory?: Acessory;
}>;
15 changes: 12 additions & 3 deletions packages/ui-kit/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,15 @@ export { uiKitBanner } from './rendering/surfaces/uiKitBanner';
export { uiKitMessage } from './rendering/surfaces/uiKitMessage';
export { uiKitModal } from './rendering/surfaces/uiKitModal';

export { UiKitParserBanner } from './rendering/surfaces/UiKitParserBanner';
export { UiKitParserMessage } from './rendering/surfaces/UiKitParserMessage';
export { UiKitParserModal } from './rendering/surfaces/UiKitParserModal';
export {
UiKitParserBanner,
BannerSurfaceLayout,
} from './rendering/surfaces/UiKitParserBanner';
export {
UiKitParserMessage,
MessageSurfaceLayout,
} from './rendering/surfaces/UiKitParserMessage';
export {
UiKitParserModal,
ModalSurfaceLayout,
} from './rendering/surfaces/UiKitParserModal';
45 changes: 28 additions & 17 deletions packages/ui-kit/src/rendering/BaseSurfaceRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,22 @@ import { renderLayoutBlock } from './renderLayoutBlock';
import { renderTextObject } from './renderTextObject';
import { resolveConditionalBlocks } from './resolveConditionalBlocks';

export abstract class BaseSurfaceRenderer<OutputElement>
implements ISurfaceRenderer<OutputElement> {
public constructor(
public allowedLayoutBlockTypes?: Exclude<
LayoutBlock,
ConditionalBlock
>['type'][]
) {}

public render(blocks: readonly Block[], conditions?: Conditions) {
export type PossibleAllowedLayouts = Exclude<
LayoutBlock,
ConditionalBlock
>['type'];
export abstract class BaseSurfaceRenderer<
OutputElement,
AllowedLayoutItems extends PossibleAllowedLayouts = PossibleAllowedLayouts
> implements ISurfaceRenderer<OutputElement> {
public constructor(readonly allowedLayoutBlockTypes?: AllowedLayoutItems[]) {
this.allowedLayoutBlockTypes = allowedLayoutBlockTypes;
}

public render(
blocks: readonly Block[],
conditions?: Conditions
): OutputElement[] {
if (!Array.isArray(blocks)) {
return [];
}
Expand All @@ -60,8 +66,9 @@ export abstract class BaseSurfaceRenderer<OutputElement>
index: number
): OutputElement | null {
if (
this.allowedLayoutBlockTypes?.includes(LayoutBlockType.ACTIONS) ===
false &&
(this.allowedLayoutBlockTypes as string[])?.includes(
LayoutBlockType.ACTIONS
) === false &&
!isActionsBlockElement(block)
) {
return null;
Expand All @@ -85,8 +92,9 @@ export abstract class BaseSurfaceRenderer<OutputElement>
index: number
): OutputElement | null {
if (
this.allowedLayoutBlockTypes?.includes(LayoutBlockType.CONTEXT) ===
false &&
(this.allowedLayoutBlockTypes as string[])?.includes(
LayoutBlockType.CONTEXT
) === false &&
!isContextBlockElement(block)
) {
return null;
Expand Down Expand Up @@ -114,7 +122,9 @@ export abstract class BaseSurfaceRenderer<OutputElement>
index: number
): OutputElement | null {
if (
this.allowedLayoutBlockTypes?.includes(LayoutBlockType.INPUT) === false &&
(this.allowedLayoutBlockTypes as string[])?.includes(
LayoutBlockType.INPUT
) === false &&
!isInputBlockElement(block)
) {
return null;
Expand All @@ -138,8 +148,9 @@ export abstract class BaseSurfaceRenderer<OutputElement>
index: number
): OutputElement | null {
if (
this.allowedLayoutBlockTypes?.includes(LayoutBlockType.SECTION) ===
false &&
(this.allowedLayoutBlockTypes as string[])?.includes(
LayoutBlockType.SECTION
) === false &&
!isSectionBlockAccessoryElement(block)
) {
return null;
Expand Down
14 changes: 10 additions & 4 deletions packages/ui-kit/src/rendering/createSurfaceRenderer.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import { Block } from '../blocks/Block';
import { BaseSurfaceRenderer } from './BaseSurfaceRenderer';
import {
BaseSurfaceRenderer,
PossibleAllowedLayouts,
} from './BaseSurfaceRenderer';
import { Conditions } from './Conditions';

export const createSurfaceRenderer = <OutputElement>() => (
surfaceRenderer: BaseSurfaceRenderer<OutputElement>,
export const createSurfaceRenderer = <
OutputElement,
AllowedBlockTypes extends PossibleAllowedLayouts
>() => (
surfaceRenderer: BaseSurfaceRenderer<OutputElement, AllowedBlockTypes>,
conditions?: Conditions
) => (blocks: readonly { type: string }[]) =>
) => (blocks: readonly Pick<Block, 'type'>[]): OutputElement[] =>
surfaceRenderer.render(blocks as Block[], conditions);
9 changes: 3 additions & 6 deletions packages/ui-kit/src/rendering/isAllowedLayoutBlock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@ import { ConditionalBlock } from '../blocks/layout/ConditionalBlock';

export const isAllowedLayoutBlock = (
allowedLayoutBlockTypes?: Exclude<LayoutBlock, ConditionalBlock>['type'][]
) => (block: Block): block is Exclude<LayoutBlock, ConditionalBlock> => {
return (
(allowedLayoutBlockTypes as string[] | undefined)?.includes(block.type) ??
true
);
};
) => (block: Block): block is Exclude<LayoutBlock, ConditionalBlock> =>
(allowedLayoutBlockTypes as string[] | undefined)?.includes(block.type) ??
true;
5 changes: 2 additions & 3 deletions packages/ui-kit/src/rendering/renderLayoutBlock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@ import { LayoutBlockRenderer } from './LayoutBlockRenderer';
const getLayoutBlockRenderer = <OutputElement>(
renderers: ISurfaceRenderer<OutputElement>,
type: Exclude<LayoutBlock, ConditionalBlock>['type']
): LayoutBlockRenderer<OutputElement> | undefined => {
return renderers[type] as LayoutBlockRenderer<OutputElement> | undefined;
};
): LayoutBlockRenderer<OutputElement> | undefined =>
renderers[type] as LayoutBlockRenderer<OutputElement> | undefined;

export const renderLayoutBlock = <OutputElement>(
renderers: ISurfaceRenderer<OutputElement>
Expand Down
20 changes: 20 additions & 0 deletions packages/ui-kit/src/rendering/surfaces/GenericSurfaceLayout.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { LayoutBlockMap } from '../../blocks/LayoutBlock';

type Override<T1, T2> = Omit<T1, keyof T2> & T2;

export type OverrideLayout<
T extends Partial<LayoutBlockMap>,
D = Override<LayoutBlockMap, T>
> = D;

type AllowedLayoutsFiltered<
AllowedLayoutsTypes extends keyof LayoutBlockMap,
D,
S = { [P in keyof D]: P extends AllowedLayoutsTypes ? D[P] : never },
R = S[keyof S]
> = R;

export type GenericSurfaceLayout<
AllowedLayoutsTypes extends keyof LayoutBlockMap,
T extends Partial<LayoutBlockMap> = LayoutBlockMap
> = AllowedLayoutsFiltered<AllowedLayoutsTypes, OverrideLayout<T>>[];
12 changes: 11 additions & 1 deletion packages/ui-kit/src/rendering/surfaces/UiKitParserBanner.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
import { LayoutBlockType } from '../../blocks/LayoutBlockType';
import { BaseSurfaceRenderer } from '../BaseSurfaceRenderer';
import { GenericSurfaceLayout } from './GenericSurfaceLayout';

type AllowedLayoutBanner =
| LayoutBlockType.ACTIONS
| LayoutBlockType.CONTEXT
| LayoutBlockType.DIVIDER
| LayoutBlockType.IMAGE
| LayoutBlockType.INPUT
| LayoutBlockType.SECTION;
export abstract class UiKitParserBanner<
OutputElement
> extends BaseSurfaceRenderer<OutputElement> {
> extends BaseSurfaceRenderer<OutputElement, AllowedLayoutBanner> {
public constructor() {
super([
LayoutBlockType.ACTIONS,
Expand All @@ -15,3 +23,5 @@ export abstract class UiKitParserBanner<
]);
}
}

export type BannerSurfaceLayout = GenericSurfaceLayout<AllowedLayoutBanner>;
12 changes: 11 additions & 1 deletion packages/ui-kit/src/rendering/surfaces/UiKitParserMessage.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
import { LayoutBlockType } from '../../blocks/LayoutBlockType';
import { BaseSurfaceRenderer } from '../BaseSurfaceRenderer';
import { GenericSurfaceLayout } from './GenericSurfaceLayout';

type AllowedLayoutsMessage =
| LayoutBlockType.ACTIONS
| LayoutBlockType.CONTEXT
| LayoutBlockType.DIVIDER
| LayoutBlockType.IMAGE
| LayoutBlockType.SECTION;

export abstract class UiKitParserMessage<
OutputElement
> extends BaseSurfaceRenderer<OutputElement> {
> extends BaseSurfaceRenderer<OutputElement, AllowedLayoutsMessage> {
public constructor() {
super([
LayoutBlockType.ACTIONS,
Expand All @@ -14,3 +22,5 @@ export abstract class UiKitParserMessage<
]);
}
}

export type MessageSurfaceLayout = GenericSurfaceLayout<AllowedLayoutsMessage>;
13 changes: 12 additions & 1 deletion packages/ui-kit/src/rendering/surfaces/UiKitParserModal.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
import { LayoutBlockType } from '../../blocks/LayoutBlockType';
import { BaseSurfaceRenderer } from '../BaseSurfaceRenderer';
import { GenericSurfaceLayout } from './GenericSurfaceLayout';

type AllowedLayoutsModal =
| LayoutBlockType.ACTIONS
| LayoutBlockType.CONTEXT
| LayoutBlockType.DIVIDER
| LayoutBlockType.IMAGE
| LayoutBlockType.INPUT
| LayoutBlockType.SECTION;

export abstract class UiKitParserModal<
OutputElement
> extends BaseSurfaceRenderer<OutputElement> {
> extends BaseSurfaceRenderer<OutputElement, AllowedLayoutsModal> {
public constructor() {
super([
LayoutBlockType.ACTIONS,
Expand All @@ -15,3 +24,5 @@ export abstract class UiKitParserModal<
]);
}
}

export type ModalSurfaceLayout = GenericSurfaceLayout<AllowedLayoutsModal>;
11 changes: 7 additions & 4 deletions packages/ui-kit/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
{
"compilerOptions": {
"target": "ES5",
"lib": ["ES2018"],
"sourceMap": true,
"module": "ES2020",
"lib": ["ES2020"],
"downlevelIteration": true,
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"outDir": "./dist/esm/",
"strict": true,
"esModuleInterop": true,
"resolveJsonModule": true,
"skipLibCheck": true
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"moduleResolution": "node",
"resolveJsonModule": true
},
"exclude": ["dist/", "src/**/*.spec.ts"]
}

0 comments on commit 9529f84

Please sign in to comment.