@strictly/storybook 0.0.0-stage → 0.0.41

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,3 +1,21 @@
1
- # Temporary Holding Version
1
+ # @strictly/storybook
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Storybook configuration for React packages built with Mantine, MobX and Lingui, along with the type narrowing assertions from `@strictly/vitest`, backed by `storybook/test`.
4
+
5
+ ```ts
6
+ // .storybook/main.ts
7
+ import { createStorybookMainConfig } from '@strictly/storybook/main'
8
+ import { createRequire } from 'node:module'
9
+
10
+ export default createStorybookMainConfig(createRequire(import.meta.url))
11
+ ```
12
+
13
+ ```tsx
14
+ // .storybook/preview.tsx
15
+ import { createStorybookPreview } from '@strictly/storybook'
16
+
17
+ // storybook statically parses this call, so always pass an object literal
18
+ export default createStorybookPreview({})
19
+ ```
20
+
21
+ Every story renders inside a `MantineProvider` and `StrictMode`, with MobX's strict warnings turned on. `StorybookLinguiProvider` loads and activates a locale's messages for a decorator to wrap stories in.
package/dist/index.cjs ADDED
@@ -0,0 +1,91 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ let storybook_test = require("storybook/test");
3
+ let _lingui_core = require("@lingui/core");
4
+ let _lingui_react = require("@lingui/react");
5
+ let react = require("react");
6
+ let react_jsx_runtime = require("react/jsx-runtime");
7
+ require("@mantine/core/styles.css");
8
+ let _mantine_core = require("@mantine/core");
9
+ let mobx = require("mobx");
10
+ //#region src/expect.ts
11
+ function expectEquals(v1, v2) {
12
+ (0, storybook_test.expect)(v1).toEqual(v2);
13
+ }
14
+ function expectTruthy(b) {
15
+ (0, storybook_test.expect)(b).toBeTruthy();
16
+ }
17
+ function expectDefined(v) {
18
+ (0, storybook_test.expect)(v).toBeDefined();
19
+ }
20
+ function expectInstanceOf(instance, constructor) {
21
+ (0, storybook_test.expect)(instance).toBeInstanceOf(constructor);
22
+ }
23
+ function expectDefinedAndReturn(v) {
24
+ expectDefined(v);
25
+ return v;
26
+ }
27
+ function pendingAfter(milliseconds) {
28
+ return new Promise((resolve) => {
29
+ setTimeout(() => resolve("pending"), milliseconds);
30
+ });
31
+ }
32
+ async function expectPendingPromise(p, timeoutMilliseconds = 500) {
33
+ const state = await Promise.race([p.then(() => "fulfilled", () => "rejected"), pendingAfter(timeoutMilliseconds)]);
34
+ await (0, storybook_test.expect)(state).toBe("pending");
35
+ }
36
+ //#endregion
37
+ //#region src/LinguiProvider.tsx
38
+ function StorybookLinguiProvider({ children, localeMessages, labelsToLocales, locale = "en" }) {
39
+ (0, react.useEffect)(() => {
40
+ const messages = localeMessages[locale] ?? localeMessages[labelsToLocales[locale]];
41
+ if (messages != null) {
42
+ _lingui_core.i18n.load(locale, messages);
43
+ _lingui_core.i18n.activate(locale);
44
+ }
45
+ return () => {};
46
+ }, [
47
+ locale,
48
+ labelsToLocales,
49
+ localeMessages
50
+ ]);
51
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_lingui_react.I18nProvider, {
52
+ i18n: _lingui_core.i18n,
53
+ children
54
+ });
55
+ }
56
+ //#endregion
57
+ //#region src/preview.tsx
58
+ /**
59
+ * Creates the storybook preview configuration for a package. Every story renders inside mantine and strict mode.
60
+ * Storybook applies decorators innermost first, so the supplied decorators run inside the shared providers.
61
+ *
62
+ * Storybook statically parses the preview file and only understands a default export that is a call whose first
63
+ * argument is an object literal, so callers must always pass one, even if it is empty
64
+ */
65
+ function createStorybookPreview({ args, argTypes, decorators = [] }) {
66
+ (0, mobx.configure)({
67
+ enforceActions: "observed",
68
+ observableRequiresReaction: true,
69
+ reactionRequiresObservable: true
70
+ });
71
+ return {
72
+ parameters: { controls: { matchers: {
73
+ color: /(background|color)$/i,
74
+ date: /Date$/i
75
+ } } },
76
+ argTypes,
77
+ args,
78
+ decorators: [...decorators, function(Story) {
79
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_mantine_core.MantineProvider, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react.StrictMode, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Story, {}) }) });
80
+ }]
81
+ };
82
+ }
83
+ //#endregion
84
+ exports.StorybookLinguiProvider = StorybookLinguiProvider;
85
+ exports.createStorybookPreview = createStorybookPreview;
86
+ exports.expectDefined = expectDefined;
87
+ exports.expectDefinedAndReturn = expectDefinedAndReturn;
88
+ exports.expectEquals = expectEquals;
89
+ exports.expectInstanceOf = expectInstanceOf;
90
+ exports.expectPendingPromise = expectPendingPromise;
91
+ exports.expectTruthy = expectTruthy;
@@ -0,0 +1,59 @@
1
+ import { Decorator } from '@storybook/react-vite';
2
+ import { InputType } from 'storybook/internal/types';
3
+ import { JSX } from 'react';
4
+ import { Messages } from '@lingui/core';
5
+ import { Preview } from '@storybook/react-vite';
6
+ import { PropsWithChildren } from 'react';
7
+
8
+ /**
9
+ * Creates the storybook preview configuration for a package. Every story renders inside mantine and strict mode.
10
+ * Storybook applies decorators innermost first, so the supplied decorators run inside the shared providers.
11
+ *
12
+ * Storybook statically parses the preview file and only understands a default export that is a call whose first
13
+ * argument is an object literal, so callers must always pass one, even if it is empty
14
+ */
15
+ export declare function createStorybookPreview({ args, argTypes, decorators, }: Pick<Preview, 'args' | 'argTypes'> & {
16
+ readonly decorators?: readonly Decorator[];
17
+ }): Preview;
18
+
19
+ export declare function expectDefined<V>(v: V): asserts v is NonNullable<V>;
20
+
21
+ export declare function expectDefinedAndReturn<V>(v: V): NonNullable<V>;
22
+
23
+ export declare function expectEquals<V1, V2 extends V1>(v1: V1, v2: V2): asserts v1 is V2;
24
+
25
+ export declare function expectInstanceOf<V1, V2 extends V1>(instance: V1, constructor: abstract new (...args: never[]) => V2): asserts instance is V2;
26
+
27
+ export declare function expectPendingPromise<V>(p: Promise<V>, timeoutMilliseconds?: number): Promise<void>;
28
+
29
+ export declare function expectTruthy(b: boolean): asserts b is true;
30
+
31
+ export declare type MetaArgsAndArgTypes<P, ArgTypes extends MetaArgTypesOf<P>, Args extends MetaArgsOf<ArgTypes> = MetaArgsOf<ArgTypes>> = {
32
+ args: Partial<Args>;
33
+ argTypes: Partial<ArgTypes>;
34
+ };
35
+
36
+ export declare type MetaArgsOf<Types extends MetaArgTypesOf<any>> = {
37
+ [k in keyof Types]: Types[k]['mapping'] extends undefined ? Required<Types[k]['t']> : keyof Types[k]['mapping'];
38
+ };
39
+
40
+ declare type MetaArgType<T> = InputType & {
41
+ t?: T;
42
+ };
43
+
44
+ export declare type MetaArgTypesOf<P> = {
45
+ [k in keyof P]: MetaArgType<P[k]>;
46
+ };
47
+
48
+ export declare type MetaPropsAndArgTypes<P> = {
49
+ args: Partial<P>;
50
+ argTypes: Partial<MetaArgTypesOf<P>>;
51
+ };
52
+
53
+ export declare function StorybookLinguiProvider<LocaleMessages extends Readonly<Record<string, Messages | undefined>>>({ children, localeMessages, labelsToLocales, locale, }: PropsWithChildren<{
54
+ localeMessages: LocaleMessages;
55
+ labelsToLocales: Readonly<Record<string, keyof LocaleMessages>>;
56
+ locale?: keyof LocaleMessages;
57
+ }>): JSX.Element;
58
+
59
+ export { }
@@ -0,0 +1,59 @@
1
+ import { Decorator } from '@storybook/react-vite';
2
+ import { InputType } from 'storybook/internal/types';
3
+ import { JSX } from 'react';
4
+ import { Messages } from '@lingui/core';
5
+ import { Preview } from '@storybook/react-vite';
6
+ import { PropsWithChildren } from 'react';
7
+
8
+ /**
9
+ * Creates the storybook preview configuration for a package. Every story renders inside mantine and strict mode.
10
+ * Storybook applies decorators innermost first, so the supplied decorators run inside the shared providers.
11
+ *
12
+ * Storybook statically parses the preview file and only understands a default export that is a call whose first
13
+ * argument is an object literal, so callers must always pass one, even if it is empty
14
+ */
15
+ export declare function createStorybookPreview({ args, argTypes, decorators, }: Pick<Preview, 'args' | 'argTypes'> & {
16
+ readonly decorators?: readonly Decorator[];
17
+ }): Preview;
18
+
19
+ export declare function expectDefined<V>(v: V): asserts v is NonNullable<V>;
20
+
21
+ export declare function expectDefinedAndReturn<V>(v: V): NonNullable<V>;
22
+
23
+ export declare function expectEquals<V1, V2 extends V1>(v1: V1, v2: V2): asserts v1 is V2;
24
+
25
+ export declare function expectInstanceOf<V1, V2 extends V1>(instance: V1, constructor: abstract new (...args: never[]) => V2): asserts instance is V2;
26
+
27
+ export declare function expectPendingPromise<V>(p: Promise<V>, timeoutMilliseconds?: number): Promise<void>;
28
+
29
+ export declare function expectTruthy(b: boolean): asserts b is true;
30
+
31
+ export declare type MetaArgsAndArgTypes<P, ArgTypes extends MetaArgTypesOf<P>, Args extends MetaArgsOf<ArgTypes> = MetaArgsOf<ArgTypes>> = {
32
+ args: Partial<Args>;
33
+ argTypes: Partial<ArgTypes>;
34
+ };
35
+
36
+ export declare type MetaArgsOf<Types extends MetaArgTypesOf<any>> = {
37
+ [k in keyof Types]: Types[k]['mapping'] extends undefined ? Required<Types[k]['t']> : keyof Types[k]['mapping'];
38
+ };
39
+
40
+ declare type MetaArgType<T> = InputType & {
41
+ t?: T;
42
+ };
43
+
44
+ export declare type MetaArgTypesOf<P> = {
45
+ [k in keyof P]: MetaArgType<P[k]>;
46
+ };
47
+
48
+ export declare type MetaPropsAndArgTypes<P> = {
49
+ args: Partial<P>;
50
+ argTypes: Partial<MetaArgTypesOf<P>>;
51
+ };
52
+
53
+ export declare function StorybookLinguiProvider<LocaleMessages extends Readonly<Record<string, Messages | undefined>>>({ children, localeMessages, labelsToLocales, locale, }: PropsWithChildren<{
54
+ localeMessages: LocaleMessages;
55
+ labelsToLocales: Readonly<Record<string, keyof LocaleMessages>>;
56
+ locale?: keyof LocaleMessages;
57
+ }>): JSX.Element;
58
+
59
+ export { }
package/dist/index.js ADDED
@@ -0,0 +1,83 @@
1
+ import { expect } from "storybook/test";
2
+ import { i18n } from "@lingui/core";
3
+ import { I18nProvider } from "@lingui/react";
4
+ import { StrictMode, useEffect } from "react";
5
+ import { jsx } from "react/jsx-runtime";
6
+ import "@mantine/core/styles.css";
7
+ import { MantineProvider } from "@mantine/core";
8
+ import { configure } from "mobx";
9
+ //#region src/expect.ts
10
+ function expectEquals(v1, v2) {
11
+ expect(v1).toEqual(v2);
12
+ }
13
+ function expectTruthy(b) {
14
+ expect(b).toBeTruthy();
15
+ }
16
+ function expectDefined(v) {
17
+ expect(v).toBeDefined();
18
+ }
19
+ function expectInstanceOf(instance, constructor) {
20
+ expect(instance).toBeInstanceOf(constructor);
21
+ }
22
+ function expectDefinedAndReturn(v) {
23
+ expectDefined(v);
24
+ return v;
25
+ }
26
+ function pendingAfter(milliseconds) {
27
+ return new Promise((resolve) => {
28
+ setTimeout(() => resolve("pending"), milliseconds);
29
+ });
30
+ }
31
+ async function expectPendingPromise(p, timeoutMilliseconds = 500) {
32
+ const state = await Promise.race([p.then(() => "fulfilled", () => "rejected"), pendingAfter(timeoutMilliseconds)]);
33
+ await expect(state).toBe("pending");
34
+ }
35
+ //#endregion
36
+ //#region src/LinguiProvider.tsx
37
+ function StorybookLinguiProvider({ children, localeMessages, labelsToLocales, locale = "en" }) {
38
+ useEffect(() => {
39
+ const messages = localeMessages[locale] ?? localeMessages[labelsToLocales[locale]];
40
+ if (messages != null) {
41
+ i18n.load(locale, messages);
42
+ i18n.activate(locale);
43
+ }
44
+ return () => {};
45
+ }, [
46
+ locale,
47
+ labelsToLocales,
48
+ localeMessages
49
+ ]);
50
+ return /* @__PURE__ */ jsx(I18nProvider, {
51
+ i18n,
52
+ children
53
+ });
54
+ }
55
+ //#endregion
56
+ //#region src/preview.tsx
57
+ /**
58
+ * Creates the storybook preview configuration for a package. Every story renders inside mantine and strict mode.
59
+ * Storybook applies decorators innermost first, so the supplied decorators run inside the shared providers.
60
+ *
61
+ * Storybook statically parses the preview file and only understands a default export that is a call whose first
62
+ * argument is an object literal, so callers must always pass one, even if it is empty
63
+ */
64
+ function createStorybookPreview({ args, argTypes, decorators = [] }) {
65
+ configure({
66
+ enforceActions: "observed",
67
+ observableRequiresReaction: true,
68
+ reactionRequiresObservable: true
69
+ });
70
+ return {
71
+ parameters: { controls: { matchers: {
72
+ color: /(background|color)$/i,
73
+ date: /Date$/i
74
+ } } },
75
+ argTypes,
76
+ args,
77
+ decorators: [...decorators, function(Story) {
78
+ return /* @__PURE__ */ jsx(MantineProvider, { children: /* @__PURE__ */ jsx(StrictMode, { children: /* @__PURE__ */ jsx(Story, {}) }) });
79
+ }]
80
+ };
81
+ }
82
+ //#endregion
83
+ export { StorybookLinguiProvider, createStorybookPreview, expectDefined, expectDefinedAndReturn, expectEquals, expectInstanceOf, expectPendingPromise, expectTruthy };
package/dist/main.cjs ADDED
@@ -0,0 +1,40 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ let node_path = require("node:path");
3
+ //#region src/main.ts
4
+ var hiddenSegmentPattern = new RegExp(`/(?:${["specs"].join("|")})(?=/|$)`, "g");
5
+ /**
6
+ * Creates the storybook main configuration for a package. The caller must pass its own `require` so packages resolve
7
+ * relative to the calling package rather than this one
8
+ */
9
+ function createStorybookMainConfig(require$1, { stories = ["../**/*.stories.@(ts|tsx)"], viteConfigPath = "./vitest.config.mts" } = {}) {
10
+ /**
11
+ * This function is used to resolve the absolute path of a package.
12
+ * It is needed in projects that use Yarn PnP or are set up within a monorepo.
13
+ */
14
+ function getAbsolutePath(value) {
15
+ return (0, node_path.dirname)(require$1.resolve((0, node_path.join)(value, "package.json")));
16
+ }
17
+ return {
18
+ stories,
19
+ experimental_indexers: (existing) => (existing ?? []).map((indexer) => ({
20
+ ...indexer,
21
+ createIndex: async (fileName, options) => {
22
+ return (await indexer.createIndex(fileName, options)).map((entry) => ({
23
+ ...entry,
24
+ title: options.makeTitle(entry.title).replace(hiddenSegmentPattern, "")
25
+ }));
26
+ }
27
+ })),
28
+ addons: [
29
+ getAbsolutePath("@storybook/addon-links"),
30
+ getAbsolutePath("@storybook/addon-docs"),
31
+ getAbsolutePath("@chromatic-com/storybook")
32
+ ],
33
+ framework: {
34
+ name: getAbsolutePath("@storybook/react-vite"),
35
+ options: { builder: { viteConfigPath } }
36
+ }
37
+ };
38
+ }
39
+ //#endregion
40
+ exports.createStorybookMainConfig = createStorybookMainConfig;
@@ -0,0 +1,12 @@
1
+ import { StorybookConfig } from '@storybook/react-vite';
2
+
3
+ /**
4
+ * Creates the storybook main configuration for a package. The caller must pass its own `require` so packages resolve
5
+ * relative to the calling package rather than this one
6
+ */
7
+ export declare function createStorybookMainConfig(require: NodeJS.Require, { stories, viteConfigPath, }?: {
8
+ readonly stories?: string[];
9
+ readonly viteConfigPath?: string;
10
+ }): StorybookConfig;
11
+
12
+ export { }
package/dist/main.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ import { StorybookConfig } from '@storybook/react-vite';
2
+
3
+ /**
4
+ * Creates the storybook main configuration for a package. The caller must pass its own `require` so packages resolve
5
+ * relative to the calling package rather than this one
6
+ */
7
+ export declare function createStorybookMainConfig(require: NodeJS.Require, { stories, viteConfigPath, }?: {
8
+ readonly stories?: string[];
9
+ readonly viteConfigPath?: string;
10
+ }): StorybookConfig;
11
+
12
+ export { }
package/dist/main.js ADDED
@@ -0,0 +1,39 @@
1
+ import { dirname, join } from "node:path";
2
+ //#region src/main.ts
3
+ var hiddenSegmentPattern = new RegExp(`/(?:${["specs"].join("|")})(?=/|$)`, "g");
4
+ /**
5
+ * Creates the storybook main configuration for a package. The caller must pass its own `require` so packages resolve
6
+ * relative to the calling package rather than this one
7
+ */
8
+ function createStorybookMainConfig(require, { stories = ["../**/*.stories.@(ts|tsx)"], viteConfigPath = "./vitest.config.mts" } = {}) {
9
+ /**
10
+ * This function is used to resolve the absolute path of a package.
11
+ * It is needed in projects that use Yarn PnP or are set up within a monorepo.
12
+ */
13
+ function getAbsolutePath(value) {
14
+ return dirname(require.resolve(join(value, "package.json")));
15
+ }
16
+ return {
17
+ stories,
18
+ experimental_indexers: (existing) => (existing ?? []).map((indexer) => ({
19
+ ...indexer,
20
+ createIndex: async (fileName, options) => {
21
+ return (await indexer.createIndex(fileName, options)).map((entry) => ({
22
+ ...entry,
23
+ title: options.makeTitle(entry.title).replace(hiddenSegmentPattern, "")
24
+ }));
25
+ }
26
+ })),
27
+ addons: [
28
+ getAbsolutePath("@storybook/addon-links"),
29
+ getAbsolutePath("@storybook/addon-docs"),
30
+ getAbsolutePath("@chromatic-com/storybook")
31
+ ],
32
+ framework: {
33
+ name: getAbsolutePath("@storybook/react-vite"),
34
+ options: { builder: { viteConfigPath } }
35
+ }
36
+ };
37
+ }
38
+ //#endregion
39
+ export { createStorybookMainConfig };
package/package.json CHANGED
@@ -1,6 +1,84 @@
1
1
  {
2
+ "author": "Chris <chris.glover@gmail.com> (@madmaw)",
3
+ "description": "Storybook configuration and assertion helpers for React, Mantine, MobX and Lingui",
4
+ "devDependencies": {
5
+ "@chromatic-com/storybook": "^5.3.1",
6
+ "@lingui/core": "^6.8.0",
7
+ "@lingui/react": "^6.8.0",
8
+ "@mantine/core": "^9.0.0",
9
+ "@storybook/addon-docs": "^10.6.0",
10
+ "@storybook/addon-links": "^10.6.0",
11
+ "@storybook/react-vite": "^10.6.0",
12
+ "@types/node": "^24.0.0",
13
+ "@types/react": "^19.3.0",
14
+ "@types/react-dom": "^19.3.0",
15
+ "mobx": "^7.0.0",
16
+ "react": "^19.2.0",
17
+ "react-dom": "^19.2.0",
18
+ "storybook": "^10.6.0",
19
+ "vite-plus": "1.0.0",
20
+ "@strictly/typescript": "0.0.41",
21
+ "@strictly/vite": "0.0.41"
22
+ },
23
+ "exports": {
24
+ ".": {
25
+ "import": {
26
+ "types": "./dist/index.d.ts",
27
+ "default": "./dist/index.js"
28
+ },
29
+ "require": {
30
+ "types": "./dist/index.d.cts",
31
+ "default": "./dist/index.cjs"
32
+ }
33
+ },
34
+ "./main": {
35
+ "import": {
36
+ "types": "./dist/main.d.ts",
37
+ "default": "./dist/main.js"
38
+ },
39
+ "require": {
40
+ "types": "./dist/main.d.cts",
41
+ "default": "./dist/main.cjs"
42
+ }
43
+ }
44
+ },
45
+ "files": [
46
+ "dist"
47
+ ],
48
+ "homepage": "https://github.com/madmaw/strictly/tree/main/support/storybook",
49
+ "keywords": [
50
+ "storybook"
51
+ ],
52
+ "license": "MIT",
53
+ "main": "./dist/index.js",
2
54
  "name": "@strictly/storybook",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
55
+ "peerDependencies": {
56
+ "@chromatic-com/storybook": "^5.3.1",
57
+ "@lingui/core": "^6.8.0",
58
+ "@lingui/react": "^6.8.0",
59
+ "@mantine/core": "^9.0.0",
60
+ "@storybook/addon-docs": "^10.6.0",
61
+ "@storybook/addon-links": "^10.6.0",
62
+ "@storybook/react-vite": "^10.6.0",
63
+ "mobx": "^7.0.0",
64
+ "react": "^19.2.0",
65
+ "react-dom": "^19.2.0",
66
+ "storybook": "^10.6.0"
67
+ },
68
+ "publishConfig": {
69
+ "access": "public"
70
+ },
71
+ "repository": {
72
+ "directory": "support/storybook",
73
+ "type": "git",
74
+ "url": "git+https://github.com/madmaw/strictly.git"
75
+ },
76
+ "type": "module",
77
+ "version": "0.0.41",
78
+ "scripts": {
79
+ "build": "vp build --configLoader runner",
80
+ "check-types": "tsc -b",
81
+ "clean": "del-cli dist .out"
82
+ },
83
+ "types": "./dist/index.d.ts"
6
84
  }