Skip to content
This repository has been archived by the owner on May 11, 2023. It is now read-only.

feat: support jsx condition #3

Open
wants to merge 2 commits into
base: next
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion app/rax/src/client/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
export type { DecoratorFn } from './preview';
export {
storiesOf,
setAddon,
addDecorator,
addParameters,
configure,
getStorybook,
forceReRender,
raw,
forceReRender,
} from './preview';

export * from './preview/types-6-3';

if (module && module.hot && module.hot.decline) {
module.hot.decline();
}
22 changes: 0 additions & 22 deletions app/rax/src/client/preview/index.ts

This file was deleted.

66 changes: 66 additions & 0 deletions app/rax/src/client/preview/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/* eslint-disable prefer-destructuring */
import React, { createElement } from 'rax';
import { start } from '@storybook/core/client';
// eslint-disable-next-line import/no-extraneous-dependencies
import { ClientStoryApi, Loadable } from '@storybook/addons';
import { IStorybookSection, StoryFnReactReturnType } from './types';
import { Story } from './types-6-3';
import './globals';
import render from './render';

const framework = 'rax';

// @ts-ignore
const globalRender: Story = (args, { parameters }) => {
const Component = parameters.component;
return <Component {...args} />;
};

interface ClientApi extends ClientStoryApi<StoryFnReactReturnType> {
setAddon(addon: any): void;
configure(loader: Loadable, module: NodeModule): void;
getStorybook(): IStorybookSection[];
clearDecorators(): void;
forceReRender(): void;
raw: () => any; // todo add type
}

const api = start(render);

// @ts-ignore
api.clientApi.globalRender = globalRender;

export const storiesOf: ClientApi['storiesOf'] = (kind, m) => {
return (api.clientApi.storiesOf(kind, m) as ReturnType<ClientApi['storiesOf']>).addParameters({
framework,
});
};

export const configure: ClientApi['configure'] = (...args) => api.configure(framework, ...args);
export const addDecorator: ClientApi['addDecorator'] = api.clientApi
.addDecorator as ClientApi['addDecorator'];
export type DecoratorFn = Parameters<typeof addDecorator>[0];
export const addParameters: ClientApi['addParameters'] = api.clientApi
.addParameters as ClientApi['addParameters'];
export const clearDecorators: ClientApi['clearDecorators'] = api.clientApi.clearDecorators;
export const setAddon: ClientApi['setAddon'] = api.clientApi.setAddon;
export const forceReRender: ClientApi['forceReRender'] = api.forceReRender;
export const getStorybook: ClientApi['getStorybook'] = api.clientApi.getStorybook;
export const raw: ClientApi['raw'] = api.clientApi.raw;

// const { configure: coreConfigure, clientApi, forceReRender } = start(render);

// export const {
// setAddon,
// addDecorator,
// addParameters,
// clearDecorators,
// getStorybook,
// raw,
// } = clientApi;

// export const storiesOf = (kind: string, m: any) =>
// clientApi.storiesOf(kind, m).addParameters({ framework });
// export const configure = (loadable: any, m: any) => coreConfigure(framework, loadable, m);

// export { forceReRender };
45 changes: 0 additions & 45 deletions app/rax/src/client/preview/render.ts

This file was deleted.

61 changes: 61 additions & 0 deletions app/rax/src/client/preview/render.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { createElement, render, Component } from 'rax';
import * as DriverDOM from 'driver-dom';
import dedent from 'ts-dedent';

import { document } from 'global';
import { RenderContext } from './types';

const rootElement = document ? document.getElementById('root') : null;

const renderDom = (node: any, el: Element, driver: any) =>
new Promise((resolve) => {
render(node, el, driver, resolve);
});

class ErrorBoundary extends Component<{
showException: (err: Error) => void;
showMain: () => void;
}> {
state = { hasError: false };

static getDerivedStateFromError() {
return { hasError: true };
}

componentDidMount() {
const { hasError } = this.state;
const { showMain } = this.props;
if (!hasError) {
showMain();
}
}

componentDidCatch(err: Error) {
const { showException } = this.props;
// message partially duplicates stack, strip it
showException(err);
}

render() {
const { hasError } = this.state;
const { children } = this.props;

return hasError ? null : children;
}
}

export default async function renderMain({
args,
storyFn,
showMain,
}: RenderContext) {
showMain();

// There is something miscellaneous here, for now, more precisely on L23,
// as we are using the storyFn directly and not calling it, so `Element` is a
// function but according to `createElement` types, there is no signature
// taking a function as input.
await renderDom(createElement(storyFn, args), rootElement, {
driver: DriverDOM,
});
}
24 changes: 24 additions & 0 deletions app/rax/src/client/preview/types-6-0.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { ComponentType } from 'rax';
import { Args as DefaultArgs, Annotations, BaseMeta, BaseStory } from '@storybook/addons';
import { StoryFnReactReturnType } from './types';

export type { Args, ArgTypes, Parameters, StoryContext } from '@storybook/addons';

type ReactComponent = ComponentType<any>;
type ReactReturnType = StoryFnReactReturnType;

/**
* Metadata to configure the stories for a component.
*
* @see [Default export](https://storybook.js.org/docs/formats/component-story-format/#default-export)
*/
export type Meta<Args = DefaultArgs> = BaseMeta<ReactComponent> &
Annotations<Args, ReactReturnType>;

/**
* Story function that represents a component example.
*
* @see [Named Story exports](https://storybook.js.org/docs/formats/component-story-format/#named-story-exports)
*/
export type Story<Args = DefaultArgs> = BaseStory<Args, ReactReturnType> &
Annotations<Args, ReactReturnType>;
26 changes: 26 additions & 0 deletions app/rax/src/client/preview/types-6-3.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { ComponentProps, JSXElementConstructor } from 'rax';
import type { Story, Meta } from './types-6-0';

export * from './types-6-0';

/**
* For the common case where a component's stories are simple components that receives args as props:
*
* ```tsx
* export default { ... } as ComponentMeta<typeof Button>;
* ```
*/
export type ComponentMeta<
T extends keyof JSX.IntrinsicElements | JSXElementConstructor<any>
> = Meta<ComponentProps<T>>;

/**
* For the common case where a story is a simple component that receives args as props:
*
* ```tsx
* const Template: ComponentStory<typeof Button> = (args) => <Button {...args} />
* ```
*/
export type ComponentStory<
T extends keyof JSX.IntrinsicElements | JSXElementConstructor<any>
> = Story<ComponentProps<T>>;
22 changes: 22 additions & 0 deletions app/rax/src/client/preview/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { RaxElement } from 'rax';

// eslint-disable-next-line import/no-extraneous-dependencies
export type { RenderContext } from '@storybook/client-api';
export type { StoryContext } from '@storybook/addons';

export interface ShowErrorArgs {
title: string;
description: string;
}

export type StoryFnReactReturnType = RaxElement<unknown>;

export interface IStorybookStory {
name: string;
render: () => any;
}

export interface IStorybookSection {
kind: string;
stories: IStorybookStory[];
}
64 changes: 64 additions & 0 deletions app/rax/src/server/framework-preset-rax.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
/* eslint-disable import/no-extraneous-dependencies */
import { TransformOptions } from '@babel/core';
import { Configuration } from 'webpack';
import MiniCssExtractPlugin from 'mini-css-extract-plugin';

export function babelDefault(config: TransformOptions) {
return {
Expand All @@ -10,5 +13,66 @@ export function babelDefault(config: TransformOptions) {
{ development: process.env.BABEL_ENV === 'development' },
],
],
plugins: [
...config.plugins,
['@babel/plugin-transform-react-jsx', { pragma: 'createElement' }],
'babel-plugin-transform-jsx-list',
'babel-plugin-transform-jsx-condition',
'babel-plugin-transform-jsx-memo',
'babel-plugin-transform-jsx-slot',
'babel-plugin-transform-jsx-fragment',
'babel-plugin-transform-jsx-class',
['babel-plugin-transform-jsx-stylesheet', { retainClassName: true }],
],
};
}

export function webpackFinal(config: Configuration) {
const cssRuleIndex = config.module.rules.findIndex(
(rule) => rule.test.toString() === '/\\.css$/'
);
if (cssRuleIndex) {
config.module.rules.splice(cssRuleIndex, 1);
}

const stylesLoaders = [
'css-loader',
'postcss-loader',
{
loader: 'webpack-rpx',
options: {
width: 750,
unit: 'rpx',
},
},
];

const lessLoaders = [
MiniCssExtractPlugin.loader,
'css-loader',
'less-loader',
'postcss-loader',
{
loader: 'webpack-rpx',
options: {
width: 750,
unit: 'rpx',
},
},
];

config.module.rules.push({
test: /\.css$/,
use: stylesLoaders,
});

config.module.rules.push({
test: /\.less$/,
use: lessLoaders,
});

return {
...config,
plugins: [...config.plugins, new MiniCssExtractPlugin()],
};
}
7 changes: 5 additions & 2 deletions app/rax/src/server/options.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { sync } from 'read-pkg-up';
import { LoadOptions } from '@storybook/core-common';

export default {
packageJson: sync({ cwd: __dirname }).packageJson,
framework: 'rax',
frameworkPresets: [require.resolve('./framework-preset-rax.js')],
};
frameworkPresets: [
require.resolve('./framework-preset-rax.js'),
],
} as LoadOptions;
1 change: 1 addition & 0 deletions app/rax/src/typings.d.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
declare module 'global';
declare module 'mini-css-extract-plugin'
Loading