Skip to content

Commit

Permalink
feat: add annotations support for addons (#612)
Browse files Browse the repository at this point in the history
* Add preview support

* preview re-export

* omit dist

* add deep controls (#1)

* bump storybook-addon-deep-controls

* fix: add more examples and show output

* fix: enhancers to work for a list

* fix: addon file resolution

* fix

* fix

* fix: update version

---------

Co-authored-by: Daniel Williams <[email protected]>
  • Loading branch information
onmotion and dannyhw authored Nov 1, 2024
1 parent 201e393 commit 467b40b
Show file tree
Hide file tree
Showing 12 changed files with 153 additions and 14 deletions.
1 change: 1 addition & 0 deletions examples/expo-example/.storybook-web/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const main: ServerStorybookConfig = {
'@storybook/addon-react-native-web',
// note why does this break with get absolute?
'@storybook/addon-react-native-server',
'storybook-addon-deep-controls',
],
// logLevel: 'debug',
framework: getAbsolutePath('@storybook/react-webpack5'),
Expand Down
1 change: 1 addition & 0 deletions examples/expo-example/.storybook/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const main: StorybookConfig = {
'@storybook/addon-ondevice-backgrounds',
'@storybook/addon-ondevice-actions',
'@storybook/addon-ondevice-notes',
'storybook-addon-deep-controls',
],
reactNative: {
playFn: false,
Expand Down
4 changes: 3 additions & 1 deletion examples/expo-example/.storybook/storybook.requires.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import "@storybook/addon-ondevice-controls/register";
import "@storybook/addon-ondevice-backgrounds/register";
import "@storybook/addon-ondevice-actions/register";
import "@storybook/addon-ondevice-notes/register";
import "storybook-addon-deep-controls/register";

const normalizedStories = [
{
Expand Down Expand Up @@ -57,7 +58,8 @@ declare global {
const annotations = [
require("./preview"),
require("@storybook/react-native/preview"),
require("@storybook/addon-actions/preview"),
require("@storybook/addon-ondevice-actions/preview"),
require("storybook-addon-deep-controls/preview"),
];

global.STORIES = normalizedStories;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { Meta, StoryObj } from '@storybook/react';
import { Text, View } from 'react-native';

const DeepControls = ({
objectArg,
}: {
objectArg: {
string: string;
number: number;
boolean: boolean;
enumString: string;
nested: { number: number; boolean: boolean };
};
}) => {
return (
<View style={{ gap: 10 }}>
<Text>Testing story with deep controls (storybook-addon-deep-controls)</Text>
<Text>{JSON.stringify(objectArg, null, 2)}</Text>
</View>
);
};

export default {
title: 'DeepControls',
component: DeepControls,
} satisfies Meta<typeof DeepControls>;

export const Basic: StoryObj<typeof DeepControls> = {
parameters: {
deepControls: { enabled: true },
},
args: {
objectArg: {
string: 'foo',
number: 42,
boolean: true,
enumString: 'value2', // we only want specific values for this
nested: {
number: 222,
boolean: false,
},
},
},
argTypes: {
// so we define an argType for the property to use a radio control with specific values
// @ts-expect-error
'objectArg.enumString': {
control: 'radio',
options: ['value1', 'value2', 'value3'],
},

'objectArg.boolean': {
control: 'boolean',
},

'objectArg.number': {
control: 'number',
},

'objectArg.string': {
control: 'text',
},

'objectArg.nested.boolean': {
control: 'boolean',
},

'objectArg.nested.number': {
control: 'number',
},
},
};
1 change: 1 addition & 0 deletions examples/expo-example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
"react-native-web": "~0.19.13",
"react-router": "^6.26.2",
"storybook": "^8.4.0",
"storybook-addon-deep-controls": "^0.9.2",
"ws": "^8.18.0"
},
"devDependencies": {
Expand Down
1 change: 1 addition & 0 deletions packages/ondevice-actions/preview.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from '@storybook/addon-actions/preview';
1 change: 1 addition & 0 deletions packages/ondevice-actions/src/preview.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from '@storybook/addon-actions/preview';
3 changes: 2 additions & 1 deletion packages/react-native/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@
"dev": "npx --yes tsx buildscripts/gendtsdev.ts && tsup --watch",
"prepare": "rm -rf dist/ && tsup",
"test": "jest",
"test:ci": "jest"
"test:ci": "jest",
"test:update": "jest --updateSnapshot"
},
"dependencies": {
"@storybook/core": "^8.4.0",
Expand Down
15 changes: 10 additions & 5 deletions packages/react-native/scripts/__snapshots__/generate.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import "@storybook/addon-ondevice-controls/register";
import "@storybook/addon-ondevice-backgrounds/register";
import "@storybook/addon-ondevice-actions/register";
const normalizedStories = [{
titlePrefix: "",
directory: "./scripts/mocks/file-extensions",
Expand All @@ -27,7 +28,7 @@ import "@storybook/addon-ondevice-actions/register";
}
const annotations = [require('./preview'),require("@storybook/react-native/preview"), require('@storybook/addon-actions/preview')];
const annotations = [require('./preview'), require("@storybook/react-native/preview"), require('@storybook/addon-ondevice-actions/preview')];
global.STORIES = normalizedStories;
Expand Down Expand Up @@ -61,6 +62,7 @@ import "@storybook/addon-ondevice-controls/register";
import "@storybook/addon-ondevice-backgrounds/register";
import "@storybook/addon-ondevice-actions/register";
const normalizedStories = [{
titlePrefix: "ComponentsPrefix",
directory: "./scripts/mocks/configuration-objects/components",
Expand All @@ -77,7 +79,7 @@ import "@storybook/addon-ondevice-actions/register";
}
const annotations = [require('./preview'),require("@storybook/react-native/preview"), require('@storybook/addon-actions/preview')];
const annotations = [require('./preview'), require("@storybook/react-native/preview"), require('@storybook/addon-ondevice-actions/preview')];
global.STORIES = normalizedStories;
Expand Down Expand Up @@ -111,6 +113,7 @@ import "@storybook/addon-ondevice-controls/register";
import "@storybook/addon-ondevice-backgrounds/register";
import "@storybook/addon-ondevice-actions/register";
const normalizedStories = [{
titlePrefix: "",
directory: "./scripts/mocks/all-config-files",
Expand All @@ -127,7 +130,7 @@ import "@storybook/addon-ondevice-actions/register";
}
const annotations = [require('./preview'),require("@storybook/react-native/preview"), require('@storybook/addon-actions/preview')];
const annotations = [require('./preview'), require("@storybook/react-native/preview"), require('@storybook/addon-ondevice-actions/preview')];
global.STORIES = normalizedStories;
Expand Down Expand Up @@ -161,6 +164,7 @@ import "@storybook/addon-ondevice-controls/register";
import "@storybook/addon-ondevice-backgrounds/register";
import "@storybook/addon-ondevice-actions/register";
const normalizedStories = [{
titlePrefix: "",
directory: "./scripts/mocks/no-preview",
Expand All @@ -177,7 +181,7 @@ import "@storybook/addon-ondevice-actions/register";
}
const annotations = [require("@storybook/react-native/preview"), require('@storybook/addon-actions/preview')];
const annotations = [require("@storybook/react-native/preview"), require('@storybook/addon-ondevice-actions/preview')];
global.STORIES = normalizedStories;
Expand Down Expand Up @@ -211,6 +215,7 @@ import "@storybook/addon-ondevice-controls/register";
import "@storybook/addon-ondevice-backgrounds/register";
import "@storybook/addon-ondevice-actions/register";
const normalizedStories = [{
titlePrefix: "",
directory: "./scripts/mocks/all-config-files",
Expand All @@ -222,7 +227,7 @@ import "@storybook/addon-ondevice-actions/register";
const annotations = [require('./preview'),require("@storybook/react-native/preview"), require('@storybook/addon-actions/preview')];
const annotations = [require('./preview'), require("@storybook/react-native/preview"), require('@storybook/addon-ondevice-actions/preview')];
global.STORIES = normalizedStories;
Expand Down
23 changes: 23 additions & 0 deletions packages/react-native/scripts/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,34 @@ function getPreviewExists({ configPath }) {
return !!getFilePathExtension({ configPath }, 'preview');
}

function resolveAddonFile(addon, file, extensions = ['js', 'mjs', 'ts']) {
try {
const basePath = path.join(addon, file);

require.resolve(basePath);

return basePath;
} catch (error) {}

for (const ext of extensions) {
try {
const filePath = path.join(addon, `${file}.${ext}`);

require.resolve(filePath);

return filePath;
} catch (error) {}
}

return null;
}

module.exports = {
toRequireContext,
requireUncached,
getFilePathExtension,
getMain,
ensureRelativePathHasDot,
getPreviewExists,
resolveAddonFile,
};
33 changes: 26 additions & 7 deletions packages/react-native/scripts/generate.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const {
ensureRelativePathHasDot,
getMain,
getPreviewExists,
resolveAddonFile,
} = require('./common');
const { normalizeStories, globToRegexp } = require('@storybook/core/common');
const fs = require('fs');
Expand Down Expand Up @@ -46,14 +47,28 @@ function generate({ configPath, absolute = false, useJs = false }) {
}`;
});

const registerAddons = main.addons?.map((addon) => `import "${addon}/register";`).join('\n');
let registerAddons = '';

const doctools = 'require("@storybook/react-native/preview")';
for (const addon of main.addons) {
const registerPath = resolveAddonFile(addon, 'register', ['js', 'mjs', 'jsx', 'ts', 'tsx']);

// TODO: implement presets or something similar
const enhancer = main.addons?.includes('@storybook/addon-ondevice-actions')
? "require('@storybook/addon-actions/preview')"
: '';
if (registerPath) {
registerAddons += `import "${registerPath}";\n`;
}
}

const docTools = 'require("@storybook/react-native/preview")';

const enhancers = [docTools];

for (const addon of main.addons) {
const previewPath = resolveAddonFile(addon, 'preview', ['js', 'mjs', 'jsx', 'ts', 'tsx']);

if (previewPath) {
enhancers.push(`require('${previewPath}')`);
continue;
}
}

let options = '';
let optionsVar = '';
Expand All @@ -66,7 +81,11 @@ function generate({ configPath, absolute = false, useJs = false }) {

const previewExists = getPreviewExists({ configPath });

const annotations = `[${previewExists ? "require('./preview')," : ''}${doctools}, ${enhancer}]`;
if (previewExists) {
enhancers.unshift("require('./preview')");
}

const annotations = `[${enhancers.join(', ')}]`;

const globalTypes = `
declare global {
Expand Down
12 changes: 12 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -9949,6 +9949,7 @@ __metadata:
react-native-web: "npm:~0.19.13"
react-router: "npm:^6.26.2"
storybook: "npm:^8.4.0"
storybook-addon-deep-controls: "npm:^0.9.2"
typescript: "npm:^5.3.3"
ws: "npm:^8.18.0"
languageName: unknown
Expand Down Expand Up @@ -17498,6 +17499,17 @@ __metadata:
languageName: node
linkType: hard

"storybook-addon-deep-controls@npm:^0.9.2":
version: 0.9.2
resolution: "storybook-addon-deep-controls@npm:0.9.2"
peerDependencies:
"@storybook/addon-controls": 7.x.x || 8.x.x
"@storybook/types": 7.x.x || 8.x.x
storybook: 7.x.x || 8.x.x
checksum: 10/458c401195d34559afd637fdd2fbe5bfe447d5400b80abdd0a600a34a51671d27762c2476b654be45878590eb5124fcf809bafb3cd591abcd92f922fe287db5a
languageName: node
linkType: hard

"storybook@npm:^8.4.0":
version: 8.4.0
resolution: "storybook@npm:8.4.0"
Expand Down

0 comments on commit 467b40b

Please sign in to comment.