storybook-vrhythm 0.1.0 → 0.2.0
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 +32 -2
- package/dist/index.d.ts +15 -0
- package/dist/index.js +76 -0
- package/dist/index.js.map +1 -0
- package/dist/preset.js +11 -0
- package/dist/preset.js.map +1 -0
- package/dist/preview.d.ts +5 -0
- package/dist/preview.js +82 -0
- package/dist/preview.js.map +1 -0
- package/package.json +75 -27
- package/preset.js +1 -0
package/README.md
CHANGED
|
@@ -48,9 +48,39 @@ yarn add -D storybook-vrhythm
|
|
|
48
48
|
|
|
49
49
|
## 🚀 Usage
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
This package is a **Storybook preset addon**: you can register it in `main` (recommended) or add the decorator manually in `preview`.
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
**Requirements:** Node.js 18+ and Storybook 8 or newer (see `peerDependencies` in `package.json`).
|
|
54
|
+
|
|
55
|
+
### Register as an addon (recommended)
|
|
56
|
+
|
|
57
|
+
Add the package to `addons` in `.storybook/main.ts` (or `main.js`). Storybook loads the preset and applies the vertical rhythm decorator in the preview iframe.
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
import type { StorybookConfig } from '@storybook/react-vite'; // or your framework package
|
|
61
|
+
|
|
62
|
+
const config = {
|
|
63
|
+
addons: ['storybook-vrhythm'],
|
|
64
|
+
} satisfies StorybookConfig;
|
|
65
|
+
|
|
66
|
+
export default config;
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Optional defaults and overrides still use `parameters.vrhythm` in `.storybook/preview.ts`:
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
export const parameters = {
|
|
73
|
+
vrhythm: {
|
|
74
|
+
color: 'rgba(178, 86, 18, 0.5)',
|
|
75
|
+
lineHeight: '16px',
|
|
76
|
+
offset: 0,
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Manual decorator
|
|
82
|
+
|
|
83
|
+
If you prefer not to use the preset, import the decorator in `.storybook/preview.ts`:
|
|
54
84
|
|
|
55
85
|
```typescript
|
|
56
86
|
import { withVRhythm } from 'storybook-vrhythm';
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { DecoratorFunction } from '@storybook/types';
|
|
2
|
+
|
|
3
|
+
interface StyleProps {
|
|
4
|
+
color?: string;
|
|
5
|
+
lineHeight?: string | number;
|
|
6
|
+
offset?: string | number;
|
|
7
|
+
}
|
|
8
|
+
interface ConfigProps {
|
|
9
|
+
hide?: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
type VRhythmParams = StyleProps & ConfigProps;
|
|
13
|
+
declare const withVRhythm: DecoratorFunction;
|
|
14
|
+
|
|
15
|
+
export { type ConfigProps, type StyleProps, type VRhythmParams, withVRhythm };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// src/constants.ts
|
|
2
|
+
var DEFAULT_COLOR = "rgb(204, 204, 204)";
|
|
3
|
+
var DEFAULT_LINE_HEIGHT = "16px";
|
|
4
|
+
var DEFAULT_OFFSET = 0;
|
|
5
|
+
var PARENT_SELECTOR = "body";
|
|
6
|
+
var DIV_ID = "storybook-rhythm";
|
|
7
|
+
|
|
8
|
+
// src/getStyle.ts
|
|
9
|
+
var getStyle = ({
|
|
10
|
+
color = DEFAULT_COLOR,
|
|
11
|
+
lineHeight = DEFAULT_LINE_HEIGHT,
|
|
12
|
+
offset = DEFAULT_OFFSET
|
|
13
|
+
}) => ({
|
|
14
|
+
position: "absolute",
|
|
15
|
+
top: offset,
|
|
16
|
+
left: 0,
|
|
17
|
+
right: 0,
|
|
18
|
+
bottom: 0,
|
|
19
|
+
background: `linear-gradient(${color} 1px, transparent 1px) left top / 1px ${lineHeight}`,
|
|
20
|
+
pointerEvents: "none"
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
// src/utils.ts
|
|
24
|
+
function createElement() {
|
|
25
|
+
const element = document.createElement("div");
|
|
26
|
+
element.setAttribute("id", DIV_ID);
|
|
27
|
+
return element;
|
|
28
|
+
}
|
|
29
|
+
function getOrCreateElement() {
|
|
30
|
+
const existing = document.getElementById(DIV_ID);
|
|
31
|
+
if (existing) {
|
|
32
|
+
return existing;
|
|
33
|
+
}
|
|
34
|
+
return createElement();
|
|
35
|
+
}
|
|
36
|
+
function removeElement() {
|
|
37
|
+
const element = document.getElementById(DIV_ID);
|
|
38
|
+
if (element) {
|
|
39
|
+
element.remove();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function injectStyle(style) {
|
|
43
|
+
const element = getOrCreateElement();
|
|
44
|
+
Object.assign(element.style, style);
|
|
45
|
+
if (!element.parentNode) {
|
|
46
|
+
const parent = document.querySelector(PARENT_SELECTOR);
|
|
47
|
+
if (parent) {
|
|
48
|
+
parent.append(element);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// src/index.ts
|
|
54
|
+
var DEFAULT_PARAMS = {
|
|
55
|
+
hide: false,
|
|
56
|
+
color: DEFAULT_COLOR,
|
|
57
|
+
lineHeight: DEFAULT_LINE_HEIGHT,
|
|
58
|
+
offset: DEFAULT_OFFSET
|
|
59
|
+
};
|
|
60
|
+
var withVRhythm = (storyFn, context) => {
|
|
61
|
+
const params = {
|
|
62
|
+
...DEFAULT_PARAMS,
|
|
63
|
+
...context.parameters?.vrhythm
|
|
64
|
+
};
|
|
65
|
+
if (params.hide) {
|
|
66
|
+
removeElement();
|
|
67
|
+
} else {
|
|
68
|
+
const style = getStyle(params);
|
|
69
|
+
injectStyle(style);
|
|
70
|
+
}
|
|
71
|
+
return storyFn(context);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export { withVRhythm };
|
|
75
|
+
//# sourceMappingURL=index.js.map
|
|
76
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/constants.ts","../src/getStyle.ts","../src/utils.ts","../src/index.ts"],"names":[],"mappings":";AAAO,IAAM,aAAA,GAAgB,oBAAA;AACtB,IAAM,mBAAA,GAAsB,MAAA;AAC5B,IAAM,cAAA,GAAiB,CAAA;AACvB,IAAM,eAAA,GAAkB,MAAA;AACxB,IAAM,MAAA,GAAS,kBAAA;;;ACGf,IAAM,WAAW,CAAC;AAAA,EACvB,KAAA,GAAQ,aAAA;AAAA,EACR,UAAA,GAAa,mBAAA;AAAA,EACb,MAAA,GAAS;AACX,CAAA,MAA6B;AAAA,EAC3B,QAAA,EAAU,UAAA;AAAA,EACV,GAAA,EAAK,MAAA;AAAA,EACL,IAAA,EAAM,CAAA;AAAA,EACN,KAAA,EAAO,CAAA;AAAA,EACP,MAAA,EAAQ,CAAA;AAAA,EACR,UAAA,EAAY,CAAA,gBAAA,EAAmB,KAAK,CAAA,sCAAA,EAAyC,UAAU,CAAA,CAAA;AAAA,EACvF,aAAA,EAAe;AACjB,CAAA,CAAA;;;AChBA,SAAS,aAAA,GAAgC;AACvC,EAAA,MAAM,OAAA,GAAU,QAAA,CAAS,aAAA,CAAc,KAAK,CAAA;AAC5C,EAAA,OAAA,CAAQ,YAAA,CAAa,MAAM,MAAM,CAAA;AACjC,EAAA,OAAO,OAAA;AACT;AAEA,SAAS,kBAAA,GAAqC;AAC5C,EAAA,MAAM,QAAA,GAAW,QAAA,CAAS,cAAA,CAAe,MAAM,CAAA;AAC/C,EAAA,IAAI,QAAA,EAAU;AACZ,IAAA,OAAO,QAAA;AAAA,EACT;AACA,EAAA,OAAO,aAAA,EAAc;AACvB;AAEO,SAAS,aAAA,GAAsB;AACpC,EAAA,MAAM,OAAA,GAAU,QAAA,CAAS,cAAA,CAAe,MAAM,CAAA;AAC9C,EAAA,IAAI,OAAA,EAAS;AACX,IAAA,OAAA,CAAQ,MAAA,EAAO;AAAA,EACjB;AACF;AAEO,SAAS,YAAY,KAAA,EAAuB;AACjD,EAAA,MAAM,UAAU,kBAAA,EAAmB;AACnC,EAAA,MAAA,CAAO,MAAA,CAAO,OAAA,CAAQ,KAAA,EAAO,KAAK,CAAA;AAElC,EAAA,IAAI,CAAC,QAAQ,UAAA,EAAY;AACvB,IAAA,MAAM,MAAA,GAAS,QAAA,CAAS,aAAA,CAAc,eAAe,CAAA;AACrD,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,MAAA,CAAO,OAAO,OAAO,CAAA;AAAA,IACvB;AAAA,EACF;AACF;;;ACrBA,IAAM,cAAA,GAA0C;AAAA,EAC9C,IAAA,EAAM,KAAA;AAAA,EACN,KAAA,EAAO,aAAA;AAAA,EACP,UAAA,EAAY,mBAAA;AAAA,EACZ,MAAA,EAAQ;AACV,CAAA;AAEO,IAAM,WAAA,GAAiC,CAAC,OAAA,EAAS,OAAA,KAAY;AAClE,EAAA,MAAM,MAAA,GAAkC;AAAA,IACtC,GAAG,cAAA;AAAA,IACH,GAAI,QAAQ,UAAA,EAAwD;AAAA,GACtE;AAEA,EAAA,IAAI,OAAO,IAAA,EAAM;AACf,IAAA,aAAA,EAAc;AAAA,EAChB,CAAA,MAAO;AACL,IAAA,MAAM,KAAA,GAAQ,SAAS,MAAM,CAAA;AAC7B,IAAA,WAAA,CAAY,KAAK,CAAA;AAAA,EACnB;AAEA,EAAA,OAAO,QAAQ,OAAO,CAAA;AACxB","file":"index.js","sourcesContent":["export const DEFAULT_COLOR = 'rgb(204, 204, 204)';\nexport const DEFAULT_LINE_HEIGHT = '16px';\nexport const DEFAULT_OFFSET = 0;\nexport const PARENT_SELECTOR = 'body';\nexport const DIV_ID = 'storybook-rhythm';\n","import { StyleObj, StyleProps } from './types';\nimport {\n DEFAULT_COLOR,\n DEFAULT_LINE_HEIGHT,\n DEFAULT_OFFSET,\n} from './constants';\n\nexport const getStyle = ({\n color = DEFAULT_COLOR,\n lineHeight = DEFAULT_LINE_HEIGHT,\n offset = DEFAULT_OFFSET,\n}: StyleProps): StyleObj => ({\n position: 'absolute',\n top: offset,\n left: 0,\n right: 0,\n bottom: 0,\n background: `linear-gradient(${color} 1px, transparent 1px) left top / 1px ${lineHeight}`,\n pointerEvents: 'none',\n});\n","import { PARENT_SELECTOR, DIV_ID } from './constants';\nimport { StyleObj } from './types';\n\nfunction createElement(): HTMLDivElement {\n const element = document.createElement('div');\n element.setAttribute('id', DIV_ID);\n return element;\n}\n\nfunction getOrCreateElement(): HTMLDivElement {\n const existing = document.getElementById(DIV_ID) as HTMLDivElement | null;\n if (existing) {\n return existing;\n }\n return createElement();\n}\n\nexport function removeElement(): void {\n const element = document.getElementById(DIV_ID);\n if (element) {\n element.remove();\n }\n}\n\nexport function injectStyle(style: StyleObj): void {\n const element = getOrCreateElement();\n Object.assign(element.style, style);\n\n if (!element.parentNode) {\n const parent = document.querySelector(PARENT_SELECTOR);\n if (parent) {\n parent.append(element);\n }\n }\n}\n","import type { DecoratorFunction } from '@storybook/types';\n\nimport { getStyle } from './getStyle';\nimport { StyleProps, ConfigProps } from './types';\nimport { injectStyle, removeElement } from './utils';\nimport {\n DEFAULT_COLOR,\n DEFAULT_LINE_HEIGHT,\n DEFAULT_OFFSET,\n} from './constants';\n\nexport type VRhythmParams = StyleProps & ConfigProps;\n\nconst DEFAULT_PARAMS: Required<VRhythmParams> = {\n hide: false,\n color: DEFAULT_COLOR,\n lineHeight: DEFAULT_LINE_HEIGHT,\n offset: DEFAULT_OFFSET,\n};\n\nexport const withVRhythm: DecoratorFunction = (storyFn, context) => {\n const params: Required<VRhythmParams> = {\n ...DEFAULT_PARAMS,\n ...(context.parameters as { vrhythm?: VRhythmParams } | undefined)?.vrhythm,\n };\n\n if (params.hide) {\n removeElement();\n } else {\n const style = getStyle(params);\n injectStyle(style);\n }\n\n return storyFn(context);\n};\n\nexport type { StyleProps, ConfigProps } from './types';\n"]}
|
package/dist/preset.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// src/preset.ts
|
|
2
|
+
import { dirname, join } from "path";
|
|
3
|
+
import { fileURLToPath } from "url";
|
|
4
|
+
var dir = dirname(fileURLToPath(import.meta.url));
|
|
5
|
+
function previewAnnotations(entry = []) {
|
|
6
|
+
return [...entry, join(dir, "preview.js")];
|
|
7
|
+
}
|
|
8
|
+
export {
|
|
9
|
+
previewAnnotations
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=preset.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/preset.ts"],"sourcesContent":["import { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst dir = dirname(fileURLToPath(import.meta.url));\n\nexport function previewAnnotations(entry: string[] = []) {\n return [...entry, join(dir, 'preview.js')];\n}\n"],"mappings":";AAAA,SAAS,SAAS,YAAY;AAC9B,SAAS,qBAAqB;AAE9B,IAAM,MAAM,QAAQ,cAAc,YAAY,GAAG,CAAC;AAE3C,SAAS,mBAAmB,QAAkB,CAAC,GAAG;AACvD,SAAO,CAAC,GAAG,OAAO,KAAK,KAAK,YAAY,CAAC;AAC3C;","names":[]}
|
package/dist/preview.js
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// src/constants.ts
|
|
2
|
+
var DEFAULT_COLOR = "rgb(204, 204, 204)";
|
|
3
|
+
var DEFAULT_LINE_HEIGHT = "16px";
|
|
4
|
+
var DEFAULT_OFFSET = 0;
|
|
5
|
+
var PARENT_SELECTOR = "body";
|
|
6
|
+
var DIV_ID = "storybook-rhythm";
|
|
7
|
+
|
|
8
|
+
// src/getStyle.ts
|
|
9
|
+
var getStyle = ({
|
|
10
|
+
color = DEFAULT_COLOR,
|
|
11
|
+
lineHeight = DEFAULT_LINE_HEIGHT,
|
|
12
|
+
offset = DEFAULT_OFFSET
|
|
13
|
+
}) => ({
|
|
14
|
+
position: "absolute",
|
|
15
|
+
top: offset,
|
|
16
|
+
left: 0,
|
|
17
|
+
right: 0,
|
|
18
|
+
bottom: 0,
|
|
19
|
+
background: `linear-gradient(${color} 1px, transparent 1px) left top / 1px ${lineHeight}`,
|
|
20
|
+
pointerEvents: "none"
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
// src/utils.ts
|
|
24
|
+
function createElement() {
|
|
25
|
+
const element = document.createElement("div");
|
|
26
|
+
element.setAttribute("id", DIV_ID);
|
|
27
|
+
return element;
|
|
28
|
+
}
|
|
29
|
+
function getOrCreateElement() {
|
|
30
|
+
const existing = document.getElementById(DIV_ID);
|
|
31
|
+
if (existing) {
|
|
32
|
+
return existing;
|
|
33
|
+
}
|
|
34
|
+
return createElement();
|
|
35
|
+
}
|
|
36
|
+
function removeElement() {
|
|
37
|
+
const element = document.getElementById(DIV_ID);
|
|
38
|
+
if (element) {
|
|
39
|
+
element.remove();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function injectStyle(style) {
|
|
43
|
+
const element = getOrCreateElement();
|
|
44
|
+
Object.assign(element.style, style);
|
|
45
|
+
if (!element.parentNode) {
|
|
46
|
+
const parent = document.querySelector(PARENT_SELECTOR);
|
|
47
|
+
if (parent) {
|
|
48
|
+
parent.append(element);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// src/index.ts
|
|
54
|
+
var DEFAULT_PARAMS = {
|
|
55
|
+
hide: false,
|
|
56
|
+
color: DEFAULT_COLOR,
|
|
57
|
+
lineHeight: DEFAULT_LINE_HEIGHT,
|
|
58
|
+
offset: DEFAULT_OFFSET
|
|
59
|
+
};
|
|
60
|
+
var withVRhythm = (storyFn, context) => {
|
|
61
|
+
const params = {
|
|
62
|
+
...DEFAULT_PARAMS,
|
|
63
|
+
...context.parameters?.vrhythm
|
|
64
|
+
};
|
|
65
|
+
if (params.hide) {
|
|
66
|
+
removeElement();
|
|
67
|
+
} else {
|
|
68
|
+
const style = getStyle(params);
|
|
69
|
+
injectStyle(style);
|
|
70
|
+
}
|
|
71
|
+
return storyFn(context);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
// src/preview.ts
|
|
75
|
+
var preview = {
|
|
76
|
+
decorators: [withVRhythm]
|
|
77
|
+
};
|
|
78
|
+
var preview_default = preview;
|
|
79
|
+
|
|
80
|
+
export { preview_default as default };
|
|
81
|
+
//# sourceMappingURL=preview.js.map
|
|
82
|
+
//# sourceMappingURL=preview.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/constants.ts","../src/getStyle.ts","../src/utils.ts","../src/index.ts","../src/preview.ts"],"names":[],"mappings":";AAAO,IAAM,aAAA,GAAgB,oBAAA;AACtB,IAAM,mBAAA,GAAsB,MAAA;AAC5B,IAAM,cAAA,GAAiB,CAAA;AACvB,IAAM,eAAA,GAAkB,MAAA;AACxB,IAAM,MAAA,GAAS,kBAAA;;;ACGf,IAAM,WAAW,CAAC;AAAA,EACvB,KAAA,GAAQ,aAAA;AAAA,EACR,UAAA,GAAa,mBAAA;AAAA,EACb,MAAA,GAAS;AACX,CAAA,MAA6B;AAAA,EAC3B,QAAA,EAAU,UAAA;AAAA,EACV,GAAA,EAAK,MAAA;AAAA,EACL,IAAA,EAAM,CAAA;AAAA,EACN,KAAA,EAAO,CAAA;AAAA,EACP,MAAA,EAAQ,CAAA;AAAA,EACR,UAAA,EAAY,CAAA,gBAAA,EAAmB,KAAK,CAAA,sCAAA,EAAyC,UAAU,CAAA,CAAA;AAAA,EACvF,aAAA,EAAe;AACjB,CAAA,CAAA;;;AChBA,SAAS,aAAA,GAAgC;AACvC,EAAA,MAAM,OAAA,GAAU,QAAA,CAAS,aAAA,CAAc,KAAK,CAAA;AAC5C,EAAA,OAAA,CAAQ,YAAA,CAAa,MAAM,MAAM,CAAA;AACjC,EAAA,OAAO,OAAA;AACT;AAEA,SAAS,kBAAA,GAAqC;AAC5C,EAAA,MAAM,QAAA,GAAW,QAAA,CAAS,cAAA,CAAe,MAAM,CAAA;AAC/C,EAAA,IAAI,QAAA,EAAU;AACZ,IAAA,OAAO,QAAA;AAAA,EACT;AACA,EAAA,OAAO,aAAA,EAAc;AACvB;AAEO,SAAS,aAAA,GAAsB;AACpC,EAAA,MAAM,OAAA,GAAU,QAAA,CAAS,cAAA,CAAe,MAAM,CAAA;AAC9C,EAAA,IAAI,OAAA,EAAS;AACX,IAAA,OAAA,CAAQ,MAAA,EAAO;AAAA,EACjB;AACF;AAEO,SAAS,YAAY,KAAA,EAAuB;AACjD,EAAA,MAAM,UAAU,kBAAA,EAAmB;AACnC,EAAA,MAAA,CAAO,MAAA,CAAO,OAAA,CAAQ,KAAA,EAAO,KAAK,CAAA;AAElC,EAAA,IAAI,CAAC,QAAQ,UAAA,EAAY;AACvB,IAAA,MAAM,MAAA,GAAS,QAAA,CAAS,aAAA,CAAc,eAAe,CAAA;AACrD,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,MAAA,CAAO,OAAO,OAAO,CAAA;AAAA,IACvB;AAAA,EACF;AACF;;;ACrBA,IAAM,cAAA,GAA0C;AAAA,EAC9C,IAAA,EAAM,KAAA;AAAA,EACN,KAAA,EAAO,aAAA;AAAA,EACP,UAAA,EAAY,mBAAA;AAAA,EACZ,MAAA,EAAQ;AACV,CAAA;AAEO,IAAM,WAAA,GAAiC,CAAC,OAAA,EAAS,OAAA,KAAY;AAClE,EAAA,MAAM,MAAA,GAAkC;AAAA,IACtC,GAAG,cAAA;AAAA,IACH,GAAI,QAAQ,UAAA,EAAwD;AAAA,GACtE;AAEA,EAAA,IAAI,OAAO,IAAA,EAAM;AACf,IAAA,aAAA,EAAc;AAAA,EAChB,CAAA,MAAO;AACL,IAAA,MAAM,KAAA,GAAQ,SAAS,MAAM,CAAA;AAC7B,IAAA,WAAA,CAAY,KAAK,CAAA;AAAA,EACnB;AAEA,EAAA,OAAO,QAAQ,OAAO,CAAA;AACxB,CAAA;;;AC9BA,IAAM,OAAA,GAAwC;AAAA,EAC5C,UAAA,EAAY,CAAC,WAAW;AAC1B,CAAA;AAEA,IAAO,eAAA,GAAQ","file":"preview.js","sourcesContent":["export const DEFAULT_COLOR = 'rgb(204, 204, 204)';\nexport const DEFAULT_LINE_HEIGHT = '16px';\nexport const DEFAULT_OFFSET = 0;\nexport const PARENT_SELECTOR = 'body';\nexport const DIV_ID = 'storybook-rhythm';\n","import { StyleObj, StyleProps } from './types';\nimport {\n DEFAULT_COLOR,\n DEFAULT_LINE_HEIGHT,\n DEFAULT_OFFSET,\n} from './constants';\n\nexport const getStyle = ({\n color = DEFAULT_COLOR,\n lineHeight = DEFAULT_LINE_HEIGHT,\n offset = DEFAULT_OFFSET,\n}: StyleProps): StyleObj => ({\n position: 'absolute',\n top: offset,\n left: 0,\n right: 0,\n bottom: 0,\n background: `linear-gradient(${color} 1px, transparent 1px) left top / 1px ${lineHeight}`,\n pointerEvents: 'none',\n});\n","import { PARENT_SELECTOR, DIV_ID } from './constants';\nimport { StyleObj } from './types';\n\nfunction createElement(): HTMLDivElement {\n const element = document.createElement('div');\n element.setAttribute('id', DIV_ID);\n return element;\n}\n\nfunction getOrCreateElement(): HTMLDivElement {\n const existing = document.getElementById(DIV_ID) as HTMLDivElement | null;\n if (existing) {\n return existing;\n }\n return createElement();\n}\n\nexport function removeElement(): void {\n const element = document.getElementById(DIV_ID);\n if (element) {\n element.remove();\n }\n}\n\nexport function injectStyle(style: StyleObj): void {\n const element = getOrCreateElement();\n Object.assign(element.style, style);\n\n if (!element.parentNode) {\n const parent = document.querySelector(PARENT_SELECTOR);\n if (parent) {\n parent.append(element);\n }\n }\n}\n","import type { DecoratorFunction } from '@storybook/types';\n\nimport { getStyle } from './getStyle';\nimport { StyleProps, ConfigProps } from './types';\nimport { injectStyle, removeElement } from './utils';\nimport {\n DEFAULT_COLOR,\n DEFAULT_LINE_HEIGHT,\n DEFAULT_OFFSET,\n} from './constants';\n\nexport type VRhythmParams = StyleProps & ConfigProps;\n\nconst DEFAULT_PARAMS: Required<VRhythmParams> = {\n hide: false,\n color: DEFAULT_COLOR,\n lineHeight: DEFAULT_LINE_HEIGHT,\n offset: DEFAULT_OFFSET,\n};\n\nexport const withVRhythm: DecoratorFunction = (storyFn, context) => {\n const params: Required<VRhythmParams> = {\n ...DEFAULT_PARAMS,\n ...(context.parameters as { vrhythm?: VRhythmParams } | undefined)?.vrhythm,\n };\n\n if (params.hide) {\n removeElement();\n } else {\n const style = getStyle(params);\n injectStyle(style);\n }\n\n return storyFn(context);\n};\n\nexport type { StyleProps, ConfigProps } from './types';\n","import type { ProjectAnnotations, Renderer } from '@storybook/types';\n\nimport { withVRhythm } from './index';\n\nconst preview: ProjectAnnotations<Renderer> = {\n decorators: [withVRhythm],\n};\n\nexport default preview;\n"]}
|
package/package.json
CHANGED
|
@@ -1,27 +1,65 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "storybook-vrhythm",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Storybook
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Storybook decorator and preset addon for vertical rhythm baseline guides",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "jmlweb",
|
|
5
7
|
"homepage": "https://github.com/jmlweb/storybook-vrhythm",
|
|
6
|
-
"
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
"
|
|
11
|
-
"
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/jmlweb/storybook-vrhythm.git"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"storybook-addon",
|
|
14
|
+
"style",
|
|
15
|
+
"debug",
|
|
16
|
+
"layout",
|
|
17
|
+
"baseline",
|
|
18
|
+
"vertical-rhythm",
|
|
19
|
+
"storybook",
|
|
20
|
+
"decorator"
|
|
21
|
+
],
|
|
22
|
+
"type": "module",
|
|
23
|
+
"main": "./dist/index.js",
|
|
24
|
+
"module": "./dist/index.js",
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"exports": {
|
|
27
|
+
".": {
|
|
28
|
+
"types": "./dist/index.d.ts",
|
|
29
|
+
"import": "./dist/index.js",
|
|
30
|
+
"default": "./dist/index.js"
|
|
31
|
+
},
|
|
32
|
+
"./preview": {
|
|
33
|
+
"types": "./dist/preview.d.ts",
|
|
34
|
+
"import": "./dist/preview.js",
|
|
35
|
+
"default": "./dist/preview.js"
|
|
36
|
+
},
|
|
37
|
+
"./preset": "./dist/preset.js",
|
|
38
|
+
"./package.json": "./package.json"
|
|
12
39
|
},
|
|
13
40
|
"files": [
|
|
14
|
-
"dist"
|
|
41
|
+
"dist",
|
|
42
|
+
"preset.js"
|
|
15
43
|
],
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
|
|
19
|
-
|
|
44
|
+
"engines": {
|
|
45
|
+
"node": ">=20"
|
|
46
|
+
},
|
|
47
|
+
"peerDependencies": {
|
|
48
|
+
"storybook": "^8.0.0 || ^9.0.0 || ^10.0.0"
|
|
20
49
|
},
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
|
|
24
|
-
|
|
50
|
+
"storybook": {
|
|
51
|
+
"displayName": "Vertical rhythm",
|
|
52
|
+
"supportedFrameworks": [
|
|
53
|
+
"react",
|
|
54
|
+
"vue",
|
|
55
|
+
"angular",
|
|
56
|
+
"web-components",
|
|
57
|
+
"ember",
|
|
58
|
+
"html",
|
|
59
|
+
"svelte",
|
|
60
|
+
"preact",
|
|
61
|
+
"react-native"
|
|
62
|
+
]
|
|
25
63
|
},
|
|
26
64
|
"prettier": {
|
|
27
65
|
"printWidth": 80,
|
|
@@ -30,14 +68,24 @@
|
|
|
30
68
|
"trailingComma": "es5"
|
|
31
69
|
},
|
|
32
70
|
"devDependencies": {
|
|
33
|
-
"@types
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"typescript": "^
|
|
71
|
+
"@storybook/types": "^8.6.14",
|
|
72
|
+
"@types/node": "^25.5.0",
|
|
73
|
+
"@vitest/coverage-v8": "^4.1.2",
|
|
74
|
+
"jsdom": "^29.0.1",
|
|
75
|
+
"prettier": "^3.5.3",
|
|
76
|
+
"storybook": "^8.6.18",
|
|
77
|
+
"tsup": "^8.5.1",
|
|
78
|
+
"typescript": "^5.9.3",
|
|
79
|
+
"vitest": "^4.1.2"
|
|
41
80
|
},
|
|
42
|
-
"
|
|
43
|
-
|
|
81
|
+
"scripts": {
|
|
82
|
+
"build": "tsup",
|
|
83
|
+
"dev": "tsup --watch",
|
|
84
|
+
"test": "vitest run",
|
|
85
|
+
"test:watch": "vitest",
|
|
86
|
+
"test:coverage": "vitest run --coverage",
|
|
87
|
+
"lint": "tsc --noEmit",
|
|
88
|
+
"format": "prettier --write 'src/**/*.ts' 'test/**/*.ts'",
|
|
89
|
+
"format:check": "prettier --check 'src/**/*.ts' 'test/**/*.ts'"
|
|
90
|
+
}
|
|
91
|
+
}
|
package/preset.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './dist/preset.js';
|