@strictly/storybook 0.0.0-stage → 0.0.42

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,88 @@
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
+ // 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
+ // src/LinguiProvider.tsx
37
+ function StorybookLinguiProvider({ children, localeMessages, labelsToLocales, locale = "en" }) {
38
+ (0, react.useEffect)(() => {
39
+ const messages = localeMessages[locale] ?? localeMessages[labelsToLocales[locale]];
40
+ if (messages != null) {
41
+ _lingui_core.i18n.load(locale, messages);
42
+ _lingui_core.i18n.activate(locale);
43
+ }
44
+ return () => {};
45
+ }, [
46
+ locale,
47
+ labelsToLocales,
48
+ localeMessages
49
+ ]);
50
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_lingui_react.I18nProvider, {
51
+ i18n: _lingui_core.i18n,
52
+ children
53
+ });
54
+ }
55
+ // src/preview.tsx
56
+ /**
57
+ * Creates the storybook preview configuration for a package. Every story renders inside mantine and strict mode.
58
+ * Storybook applies decorators innermost first, so the supplied decorators run inside the shared providers.
59
+ *
60
+ * Storybook statically parses the preview file and only understands a default export that is a call whose first
61
+ * argument is an object literal, so callers must always pass one, even if it is empty
62
+ */
63
+ function createStorybookPreview({ args, argTypes, decorators = [] }) {
64
+ (0, mobx.configure)({
65
+ enforceActions: "observed",
66
+ observableRequiresReaction: true,
67
+ reactionRequiresObservable: true
68
+ });
69
+ return {
70
+ parameters: { controls: { matchers: {
71
+ color: /(background|color)$/i,
72
+ date: /Date$/i
73
+ } } },
74
+ argTypes,
75
+ args,
76
+ decorators: [...decorators, function(Story) {
77
+ 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, {}) }) });
78
+ }]
79
+ };
80
+ }
81
+ exports.StorybookLinguiProvider = StorybookLinguiProvider;
82
+ exports.createStorybookPreview = createStorybookPreview;
83
+ exports.expectDefined = expectDefined;
84
+ exports.expectDefinedAndReturn = expectDefinedAndReturn;
85
+ exports.expectEquals = expectEquals;
86
+ exports.expectInstanceOf = expectInstanceOf;
87
+ exports.expectPendingPromise = expectPendingPromise;
88
+ 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,80 @@
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
+ // 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
+ // src/LinguiProvider.tsx
36
+ function StorybookLinguiProvider({ children, localeMessages, labelsToLocales, locale = "en" }) {
37
+ useEffect(() => {
38
+ const messages = localeMessages[locale] ?? localeMessages[labelsToLocales[locale]];
39
+ if (messages != null) {
40
+ i18n.load(locale, messages);
41
+ i18n.activate(locale);
42
+ }
43
+ return () => {};
44
+ }, [
45
+ locale,
46
+ labelsToLocales,
47
+ localeMessages
48
+ ]);
49
+ return /* @__PURE__ */ jsx(I18nProvider, {
50
+ i18n,
51
+ children
52
+ });
53
+ }
54
+ // src/preview.tsx
55
+ /**
56
+ * Creates the storybook preview configuration for a package. Every story renders inside mantine and strict mode.
57
+ * Storybook applies decorators innermost first, so the supplied decorators run inside the shared providers.
58
+ *
59
+ * Storybook statically parses the preview file and only understands a default export that is a call whose first
60
+ * argument is an object literal, so callers must always pass one, even if it is empty
61
+ */
62
+ function createStorybookPreview({ args, argTypes, decorators = [] }) {
63
+ configure({
64
+ enforceActions: "observed",
65
+ observableRequiresReaction: true,
66
+ reactionRequiresObservable: true
67
+ });
68
+ return {
69
+ parameters: { controls: { matchers: {
70
+ color: /(background|color)$/i,
71
+ date: /Date$/i
72
+ } } },
73
+ argTypes,
74
+ args,
75
+ decorators: [...decorators, function(Story) {
76
+ return /* @__PURE__ */ jsx(MantineProvider, { children: /* @__PURE__ */ jsx(StrictMode, { children: /* @__PURE__ */ jsx(Story, {}) }) });
77
+ }]
78
+ };
79
+ }
80
+ export { StorybookLinguiProvider, createStorybookPreview, expectDefined, expectDefinedAndReturn, expectEquals, expectInstanceOf, expectPendingPromise, expectTruthy };
package/dist/main.cjs ADDED
@@ -0,0 +1,39 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ let node_path = require("node:path");
3
+ // 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
+ 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,38 @@
1
+ import { dirname, join } from "node:path";
2
+ // 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
+ export { createStorybookMainConfig };
package/package.json CHANGED
@@ -1,6 +1,85 @@
1
1
  {
2
2
  "name": "@strictly/storybook",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.0.42",
4
+ "description": "Storybook configuration and assertion helpers for React, Mantine, MobX and Lingui",
5
+ "keywords": [
6
+ "storybook"
7
+ ],
8
+ "homepage": "https://github.com/madmaw/strictly/tree/main/support/storybook",
9
+ "license": "MIT",
10
+ "author": "Chris <chris.glover@gmail.com> (@madmaw)",
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/madmaw/strictly.git",
14
+ "directory": "support/storybook"
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "type": "module",
20
+ "main": "./dist/index.js",
21
+ "exports": {
22
+ ".": {
23
+ "import": {
24
+ "types": "./dist/index.d.ts",
25
+ "default": "./dist/index.js"
26
+ },
27
+ "require": {
28
+ "types": "./dist/index.d.cts",
29
+ "default": "./dist/index.cjs"
30
+ }
31
+ },
32
+ "./main": {
33
+ "import": {
34
+ "types": "./dist/main.d.ts",
35
+ "default": "./dist/main.js"
36
+ },
37
+ "require": {
38
+ "types": "./dist/main.d.cts",
39
+ "default": "./dist/main.cjs"
40
+ }
41
+ }
42
+ },
43
+ "publishConfig": {
44
+ "access": "public"
45
+ },
46
+ "devDependencies": {
47
+ "@chromatic-com/storybook": "^5.5.1",
48
+ "@lingui/core": "^6.9.1",
49
+ "@lingui/react": "^6.9.1",
50
+ "@mantine/core": "^9.7.2",
51
+ "@storybook/addon-docs": "^10.6.2",
52
+ "@storybook/addon-links": "^10.6.2",
53
+ "@storybook/react-vite": "^10.6.2",
54
+ "@types/node": "^26.6.5",
55
+ "@types/react": "^19.3.0",
56
+ "@types/react-dom": "^19.3.0",
57
+ "mobx": "^7.0.6",
58
+ "react": "^19.3.1",
59
+ "react-dom": "^19.3.1",
60
+ "storybook": "^10.6.2",
61
+ "vite-plus": "1.4.0",
62
+ "@strictly/vite": "0.0.42",
63
+ "@strictly/typescript": "0.0.42"
64
+ },
65
+ "peerDependencies": {
66
+ "@chromatic-com/storybook": "^5.5.1",
67
+ "@lingui/core": "^6.9.1",
68
+ "@lingui/react": "^6.9.1",
69
+ "@mantine/core": "^9.7.2",
70
+ "@storybook/addon-docs": "^10.6.2",
71
+ "@storybook/addon-links": "^10.6.2",
72
+ "@storybook/react-vite": "^10.6.2",
73
+ "mobx": "^7.0.6",
74
+ "react": "^19.3.1",
75
+ "react-dom": "^19.3.1",
76
+ "storybook": "^10.6.2"
77
+ },
78
+ "scripts": {
79
+ "build": "vp build --configLoader runner",
80
+ "check-types": "tsc -b",
81
+ "clean": "del-cli dist .out",
82
+ "version:patch": "npm version patch --no-git-tag-version"
83
+ },
84
+ "types": "./dist/index.d.ts"
6
85
  }