storybook-vrhythm 0.3.0 → 0.4.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 +178 -0
- package/dist/index.d.ts +42 -1
- package/dist/index.js +24 -11
- package/dist/index.js.map +1 -1
- package/dist/preview.js +34 -14
- package/dist/preview.js.map +1 -1
- package/package.json +5 -4
package/README.md
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# storybook-vrhythm
|
|
2
|
+
|
|
3
|
+
[![npm version][npm-badge]][npm]
|
|
4
|
+
[![License: MIT][license-badge]][license]
|
|
5
|
+
[](https://bundlephobia.com/package/storybook-vrhythm)
|
|
6
|
+
[](https://www.npmjs.org/package/storybook-vrhythm)
|
|
7
|
+
|
|
8
|
+
> Baseline grid overlay for Storybook. See your vertical rhythm while you build.
|
|
9
|
+
|
|
10
|
+
Stop guessing if your spacing is consistent. `storybook-vrhythm` draws a customizable baseline grid on top of your stories so you can **see** alignment issues as you develop — not after you ship.
|
|
11
|
+
|
|
12
|
+
## Features
|
|
13
|
+
|
|
14
|
+
- **Framework agnostic** — React, Vue, Angular, Svelte, Web Components, HTML
|
|
15
|
+
- **Toolbar toggle** — Show/hide the grid from Storybook's toolbar, no reload needed
|
|
16
|
+
- **Built-in presets** — Material, Tailwind, Bootstrap, and pixel-based grids ready to use
|
|
17
|
+
- **Column grids** — Optional vertical column overlay with configurable gutter width
|
|
18
|
+
- **Fully customizable** — Color, line height, line width, offset, opacity, z-index, max width
|
|
19
|
+
- **Lightweight** — Pure CSS overlay via `linear-gradient`. Zero runtime dependencies
|
|
20
|
+
- **Non-intrusive** — `pointer-events: none` keeps your stories fully interactive
|
|
21
|
+
- **TypeScript first** — Full type safety with Storybook parameter augmentation
|
|
22
|
+
|
|
23
|
+
## Requirements
|
|
24
|
+
|
|
25
|
+
- Node.js 20+
|
|
26
|
+
- Storybook 10+
|
|
27
|
+
|
|
28
|
+
## Quick start
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
pnpm add -D storybook-vrhythm
|
|
32
|
+
# or: npm install --save-dev storybook-vrhythm
|
|
33
|
+
# or: yarn add -D storybook-vrhythm
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Add to `.storybook/main.ts`:
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
const config = {
|
|
40
|
+
addons: ['storybook-vrhythm'],
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export default config;
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Done. A baseline grid overlay is now visible on every story, toggleable from the toolbar.
|
|
47
|
+
|
|
48
|
+
## Configuration
|
|
49
|
+
|
|
50
|
+
### Global defaults
|
|
51
|
+
|
|
52
|
+
Set defaults for all stories in `.storybook/preview.ts`:
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
export const parameters = {
|
|
56
|
+
vrhythm: {
|
|
57
|
+
color: 'rgba(99, 102, 241, 0.2)',
|
|
58
|
+
lineHeight: '8px',
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Per-story overrides
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
export const Compact = {
|
|
67
|
+
parameters: {
|
|
68
|
+
vrhythm: { lineHeight: '4px', color: 'rgba(244, 67, 54, 0.15)' },
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export const NoGrid = {
|
|
73
|
+
parameters: {
|
|
74
|
+
vrhythm: { hide: true },
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Using presets
|
|
80
|
+
|
|
81
|
+
Skip manual configuration with built-in presets that match popular design systems:
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
export const MaterialGrid = {
|
|
85
|
+
parameters: {
|
|
86
|
+
vrhythm: { preset: 'material' },
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
| Preset | Line height | Color | Best for |
|
|
92
|
+
| ----------- | ----------- | -------------------------- | ------------------------- |
|
|
93
|
+
| `4px` | 4px | `rgba(0, 150, 255, 0.15)` | Dense UIs, compact grids |
|
|
94
|
+
| `8px` | 8px | `rgba(0, 150, 255, 0.2)` | Standard 8pt grid systems |
|
|
95
|
+
| `16px` | 16px | `rgba(204, 204, 204, 0.5)` | Body text baseline |
|
|
96
|
+
| `24px` | 24px | `rgba(204, 204, 204, 0.5)` | Heading alignment |
|
|
97
|
+
| `material` | 4px | `rgba(244, 67, 54, 0.15)` | Material Design |
|
|
98
|
+
| `tailwind` | 4px | `rgba(99, 102, 241, 0.15)` | Tailwind CSS |
|
|
99
|
+
| `bootstrap` | 8px | `rgba(13, 110, 253, 0.2)` | Bootstrap |
|
|
100
|
+
|
|
101
|
+
### Column grid
|
|
102
|
+
|
|
103
|
+
Add vertical column lines on top of the horizontal baseline:
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
export const ColumnGrid = {
|
|
107
|
+
parameters: {
|
|
108
|
+
vrhythm: {
|
|
109
|
+
lineHeight: '8px',
|
|
110
|
+
columnWidth: '80px',
|
|
111
|
+
gutterWidth: '16px',
|
|
112
|
+
columnColor: 'rgba(99, 102, 241, 0.1)',
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
};
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Manual decorator
|
|
119
|
+
|
|
120
|
+
If you prefer to opt out of the addon preset:
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
import { withVRhythm } from 'storybook-vrhythm';
|
|
124
|
+
|
|
125
|
+
export const decorators = [withVRhythm];
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Options
|
|
129
|
+
|
|
130
|
+
### Style options
|
|
131
|
+
|
|
132
|
+
| Option | Type | Default | Description |
|
|
133
|
+
| ------------- | ------------------ | ---------------------- | -------------------------------------------------- |
|
|
134
|
+
| `color` | `string` | `'rgb(204, 204, 204)'` | CSS color for horizontal guide lines |
|
|
135
|
+
| `lineHeight` | `string \| number` | `'16px'` | Baseline grid height (`'8px'`, `'1rem'`, etc.) |
|
|
136
|
+
| `lineWidth` | `string \| number` | `'1px'` | Thickness of each horizontal guide line |
|
|
137
|
+
| `offset` | `string \| number` | `0` | Vertical offset from the top of the container |
|
|
138
|
+
| `opacity` | `number` | `1` | Overlay opacity (0–1) |
|
|
139
|
+
| `zIndex` | `number` | `9999` | Stack order of the overlay |
|
|
140
|
+
| `maxWidth` | `string \| number` | — | Centers the overlay with this max width |
|
|
141
|
+
| `columnWidth` | `string \| number` | — | Repeating column width for a vertical column grid |
|
|
142
|
+
| `columnColor` | `string` | — | CSS color for column lines (falls back to `color`) |
|
|
143
|
+
| `gutterWidth` | `string \| number` | — | Gutter between columns (requires `columnWidth`) |
|
|
144
|
+
|
|
145
|
+
### Config options
|
|
146
|
+
|
|
147
|
+
| Option | Type | Default | Description |
|
|
148
|
+
| ----------- | --------- | ------- | ------------------------------------------------------------------ |
|
|
149
|
+
| `hide` | `boolean` | `false` | Hide the overlay for this story (overrides toolbar toggle) |
|
|
150
|
+
| `preset` | `string` | — | Built-in preset name (see table above) |
|
|
151
|
+
| `container` | `string` | — | CSS selector for the overlay's parent element (defaults to `body`) |
|
|
152
|
+
|
|
153
|
+
### Parameter resolution order
|
|
154
|
+
|
|
155
|
+
```text
|
|
156
|
+
DEFAULT_PARAMS → preset styles → story-level parameters
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Later sources override earlier ones. The story-level `hide` param takes precedence over the toolbar toggle.
|
|
160
|
+
|
|
161
|
+
## Why vertical rhythm?
|
|
162
|
+
|
|
163
|
+
Vertical rhythm is the practice of aligning elements to a consistent baseline grid. When text, images, and components share the same vertical cadence, layouts feel cohesive and polished — even if users can't articulate why.
|
|
164
|
+
|
|
165
|
+
This addon makes the invisible grid visible during development, so spacing inconsistencies get caught in Storybook instead of production.
|
|
166
|
+
|
|
167
|
+
## Contributing
|
|
168
|
+
|
|
169
|
+
Contributions are welcome! Feel free to open an [issue](https://github.com/jmlweb/storybook-vrhythm/issues) or submit a pull request.
|
|
170
|
+
|
|
171
|
+
## License
|
|
172
|
+
|
|
173
|
+
[MIT](https://github.com/jmlweb/storybook-vrhythm/blob/master/LICENSE)
|
|
174
|
+
|
|
175
|
+
[npm-badge]: https://img.shields.io/npm/v/storybook-vrhythm.svg
|
|
176
|
+
[npm]: https://www.npmjs.org/package/storybook-vrhythm
|
|
177
|
+
[license-badge]: https://img.shields.io/badge/license-MIT-blue.svg
|
|
178
|
+
[license]: https://github.com/jmlweb/storybook-vrhythm/blob/master/LICENSE
|
package/dist/index.d.ts
CHANGED
|
@@ -1,17 +1,36 @@
|
|
|
1
1
|
import { DecoratorFunction, Renderer } from 'storybook/internal/types';
|
|
2
2
|
|
|
3
3
|
interface StyleProps {
|
|
4
|
+
/** CSS color for the horizontal guide lines. Default: `'rgb(204, 204, 204)'` */
|
|
4
5
|
color?: string;
|
|
6
|
+
/** Baseline grid height (e.g. `'8px'`, `'1rem'`). Default: `'16px'` */
|
|
5
7
|
lineHeight?: string | number;
|
|
8
|
+
/** Thickness of each horizontal guide line. Default: `'1px'` */
|
|
9
|
+
lineWidth?: string | number;
|
|
10
|
+
/** Vertical offset from the top of the container. Default: `0` */
|
|
6
11
|
offset?: string | number;
|
|
12
|
+
/** Overlay opacity (0–1). Default: `1` */
|
|
7
13
|
opacity?: number;
|
|
14
|
+
/** Stack order of the overlay. Default: `9999` */
|
|
8
15
|
zIndex?: number;
|
|
16
|
+
/** When set, centers the overlay horizontally with this max width. */
|
|
17
|
+
maxWidth?: string | number;
|
|
18
|
+
/** Repeating column width for a vertical column grid (e.g. `'80px'`). */
|
|
9
19
|
columnWidth?: string | number;
|
|
20
|
+
/** CSS color for vertical column lines. Falls back to `color` when omitted. */
|
|
10
21
|
columnColor?: string;
|
|
22
|
+
/** Gutter width between columns. Requires `columnWidth` to be set. */
|
|
23
|
+
gutterWidth?: string | number;
|
|
11
24
|
}
|
|
12
25
|
interface ConfigProps {
|
|
26
|
+
/** When `true`, hides the overlay for this story regardless of the toolbar toggle. */
|
|
13
27
|
hide?: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Name of a built-in preset to apply. Story-level params override preset values.
|
|
30
|
+
* Available: `'4px'`, `'8px'`, `'16px'`, `'24px'`, `'material'`, `'tailwind'`, `'bootstrap'`
|
|
31
|
+
*/
|
|
14
32
|
preset?: string;
|
|
33
|
+
/** CSS selector for the overlay's parent element. Defaults to `body`. */
|
|
15
34
|
container?: string;
|
|
16
35
|
}
|
|
17
36
|
|
|
@@ -23,7 +42,8 @@ declare module 'storybook/internal/types' {
|
|
|
23
42
|
}
|
|
24
43
|
declare module 'storybook/internal/csf' {
|
|
25
44
|
interface Globals {
|
|
26
|
-
/** Toolbar toggle for the vertical rhythm overlay
|
|
45
|
+
/** Toolbar toggle/preset selector for the vertical rhythm overlay.
|
|
46
|
+
* Values: `'true'` (show with story params) | `'false'` (hide) | preset name (e.g. `'material'`, `'tailwind'`) | boolean. */
|
|
27
47
|
vrhythm?: string | boolean;
|
|
28
48
|
}
|
|
29
49
|
}
|
|
@@ -61,6 +81,27 @@ declare const presets: {
|
|
|
61
81
|
type PresetName = keyof typeof presets;
|
|
62
82
|
|
|
63
83
|
type VRhythmParams = StyleProps & ConfigProps;
|
|
84
|
+
/**
|
|
85
|
+
* Storybook decorator that injects a vertical rhythm baseline grid overlay into stories.
|
|
86
|
+
*
|
|
87
|
+
* Register globally via the addon preset in `.storybook/main.ts` (recommended):
|
|
88
|
+
* ```ts
|
|
89
|
+
* export default { addons: ['storybook-vrhythm'] };
|
|
90
|
+
* ```
|
|
91
|
+
*
|
|
92
|
+
* Or manually in `.storybook/preview.ts`:
|
|
93
|
+
* ```ts
|
|
94
|
+
* import { withVRhythm } from 'storybook-vrhythm';
|
|
95
|
+
* export const decorators = [withVRhythm];
|
|
96
|
+
* ```
|
|
97
|
+
*
|
|
98
|
+
* Control per story via `parameters.vrhythm`:
|
|
99
|
+
* ```ts
|
|
100
|
+
* export const MyStory = {
|
|
101
|
+
* parameters: { vrhythm: { preset: 'material' } },
|
|
102
|
+
* };
|
|
103
|
+
* ```
|
|
104
|
+
*/
|
|
64
105
|
declare const withVRhythm: DecoratorFunction<Renderer>;
|
|
65
106
|
|
|
66
107
|
export { type ConfigProps, type PresetName, type StyleProps, type VRhythmParams, presets, withVRhythm };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// src/constants.ts
|
|
2
2
|
var DEFAULT_COLOR = "rgb(204, 204, 204)";
|
|
3
3
|
var DEFAULT_LINE_HEIGHT = "16px";
|
|
4
|
+
var DEFAULT_LINE_WIDTH = "1px";
|
|
4
5
|
var DEFAULT_OFFSET = 0;
|
|
5
6
|
var DEFAULT_OPACITY = 1;
|
|
6
7
|
var DEFAULT_Z_INDEX = 9999;
|
|
@@ -11,19 +12,23 @@ var DIV_ID = "storybook-rhythm";
|
|
|
11
12
|
var getStyle = ({
|
|
12
13
|
color = DEFAULT_COLOR,
|
|
13
14
|
lineHeight = DEFAULT_LINE_HEIGHT,
|
|
15
|
+
lineWidth = DEFAULT_LINE_WIDTH,
|
|
14
16
|
offset = DEFAULT_OFFSET,
|
|
15
17
|
opacity = DEFAULT_OPACITY,
|
|
16
18
|
zIndex = DEFAULT_Z_INDEX,
|
|
19
|
+
maxWidth,
|
|
17
20
|
columnWidth,
|
|
18
|
-
columnColor
|
|
21
|
+
columnColor,
|
|
22
|
+
gutterWidth
|
|
19
23
|
}) => {
|
|
20
|
-
const horizontal = `linear-gradient(${color}
|
|
21
|
-
const
|
|
24
|
+
const horizontal = `linear-gradient(${color} ${lineWidth}, transparent ${lineWidth}) left top / ${lineWidth} ${lineHeight}`;
|
|
25
|
+
const columnGradient = columnWidth != null ? gutterWidth != null ? `linear-gradient(90deg, transparent calc(${columnWidth} - ${gutterWidth}), ${columnColor ?? color} calc(${columnWidth} - ${gutterWidth})) left top / ${columnWidth} 100%` : `linear-gradient(90deg, ${columnColor ?? color} ${lineWidth}, transparent ${lineWidth}) left top / ${columnWidth} 100%` : null;
|
|
26
|
+
const background = columnGradient != null ? `${horizontal}, ${columnGradient}` : horizontal;
|
|
27
|
+
const positioning = maxWidth != null ? { left: "50%", width: maxWidth, transform: "translateX(-50%)" } : { left: 0, right: 0 };
|
|
22
28
|
return {
|
|
23
29
|
position: "absolute",
|
|
24
30
|
top: offset,
|
|
25
|
-
|
|
26
|
-
right: 0,
|
|
31
|
+
...positioning,
|
|
27
32
|
bottom: 0,
|
|
28
33
|
background,
|
|
29
34
|
pointerEvents: "none",
|
|
@@ -65,11 +70,16 @@ function removeElement() {
|
|
|
65
70
|
function injectStyle(style, container) {
|
|
66
71
|
const element = getOrCreateElement();
|
|
67
72
|
Object.assign(element.style, style);
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
+
let parent = null;
|
|
74
|
+
try {
|
|
75
|
+
parent = document.querySelector(container ?? PARENT_SELECTOR);
|
|
76
|
+
} catch {
|
|
77
|
+
}
|
|
78
|
+
if (!parent) {
|
|
79
|
+
parent = document.querySelector(PARENT_SELECTOR);
|
|
80
|
+
}
|
|
81
|
+
if (parent && element.parentNode !== parent) {
|
|
82
|
+
parent.append(element);
|
|
73
83
|
}
|
|
74
84
|
}
|
|
75
85
|
|
|
@@ -93,11 +103,14 @@ var withVRhythm = (storyFn, context) => {
|
|
|
93
103
|
...raw
|
|
94
104
|
};
|
|
95
105
|
const globalsVrhythm = context.globals?.vrhythm;
|
|
106
|
+
const globalPresetName = typeof globalsVrhythm === "string" && globalsVrhythm !== "true" && globalsVrhythm !== "false" && globalsVrhythm in presets ? globalsVrhythm : null;
|
|
107
|
+
const globalPresetStyles = globalPresetName ? presets[globalPresetName] : {};
|
|
96
108
|
const isHidden = !!params.hide || globalsVrhythm === false || globalsVrhythm === "false";
|
|
97
109
|
if (isHidden) {
|
|
98
110
|
removeElement();
|
|
99
111
|
} else {
|
|
100
|
-
const
|
|
112
|
+
const finalParams = { ...params, ...globalPresetStyles };
|
|
113
|
+
const style = getStyle(finalParams);
|
|
101
114
|
injectStyle(style, params.container || void 0);
|
|
102
115
|
}
|
|
103
116
|
return storyFn(context);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/constants.ts","../src/getStyle.ts","../src/presets.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,CAAA;AACxB,IAAM,eAAA,GAAkB,IAAA;AACxB,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,cAAA;AAAA,EACT,OAAA,GAAU,eAAA;AAAA,EACV,MAAA,GAAS,eAAA;AAAA,EACT,WAAA;AAAA,EACA;AACF,CAAA,KAA4B;AAC1B,EAAA,MAAM,UAAA,GAAa,CAAA,gBAAA,EAAmB,KAAK,CAAA,sCAAA,EAAyC,UAAU,CAAA,CAAA;AAE9F,EAAA,MAAM,UAAA,GACJ,WAAA,IAAe,IAAA,GACX,CAAA,EAAG,UAAU,4BAA4B,WAAA,IAAe,KAAK,CAAA,kCAAA,EAAqC,WAAW,CAAA,IAAA,CAAA,GAC7G,UAAA;AAEN,EAAA,OAAO;AAAA,IACL,QAAA,EAAU,UAAA;AAAA,IACV,GAAA,EAAK,MAAA;AAAA,IACL,IAAA,EAAM,CAAA;AAAA,IACN,KAAA,EAAO,CAAA;AAAA,IACP,MAAA,EAAQ,CAAA;AAAA,IACR,UAAA;AAAA,IACA,aAAA,EAAe,MAAA;AAAA,IACf,OAAA;AAAA,IACA;AAAA,GACF;AACF,CAAA;;;AClCO,IAAM,OAAA,GAAU;AAAA,EACrB,KAAA,EAAO,EAAE,UAAA,EAAY,KAAA,EAAO,OAAO,yBAAA,EAA0B;AAAA,EAC7D,KAAA,EAAO,EAAE,UAAA,EAAY,KAAA,EAAO,OAAO,wBAAA,EAAyB;AAAA,EAC5D,MAAA,EAAQ,EAAE,UAAA,EAAY,MAAA,EAAQ,OAAO,0BAAA,EAA2B;AAAA,EAChE,MAAA,EAAQ,EAAE,UAAA,EAAY,MAAA,EAAQ,OAAO,0BAAA,EAA2B;AAAA,EAChE,QAAA,EAAU,EAAE,UAAA,EAAY,KAAA,EAAO,OAAO,yBAAA,EAA0B;AAAA,EAChE,QAAA,EAAU,EAAE,UAAA,EAAY,KAAA,EAAO,OAAO,0BAAA,EAA2B;AAAA,EACjE,SAAA,EAAW,EAAE,UAAA,EAAY,KAAA,EAAO,OAAO,yBAAA;AACzC;;;ACPA,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,WAAA,CAAY,OAAiB,SAAA,EAA0B;AACrE,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,SAAA,IAAa,eAAe,CAAA;AAClE,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,MAAA,CAAO,OAAO,OAAO,CAAA;AAAA,IACvB;AAAA,EACF;AACF;;;AChBA,IAAM,cAAA,GAAgC;AAAA,EACpC,IAAA,EAAM,KAAA;AAAA,EACN,MAAA,EAAQ,EAAA;AAAA,EACR,SAAA,EAAW,EAAA;AAAA,EACX,KAAA,EAAO,aAAA;AAAA,EACP,UAAA,EAAY,mBAAA;AAAA,EACZ,MAAA,EAAQ,cAAA;AAAA,EACR,OAAA,EAAS,eAAA;AAAA,EACT,MAAA,EAAQ;AACV,CAAA;AAEO,IAAM,WAAA,GAA2C,CAAC,OAAA,EAAS,OAAA,KAAY;AAC5E,EAAA,MAAM,GAAA,GAAO,QAAQ,UAAA,EACjB,OAAA;AACJ,EAAA,MAAM,YAAA,GACJ,GAAA,EAAK,MAAA,IAAU,GAAA,CAAI,MAAA,IAAU,UACzB,OAAA,CAAQ,GAAA,CAAI,MAAoB,CAAA,GAChC,EAAC;AACP,EAAA,MAAM,MAAA,GAAwB;AAAA,IAC5B,GAAG,cAAA;AAAA,IACH,GAAG,YAAA;AAAA,IACH,GAAG;AAAA,GACL;AAEA,EAAA,MAAM,cAAA,GACJ,QAAQ,OAAA,EACP,OAAA;AACH,EAAA,MAAM,WACJ,CAAC,CAAC,OAAO,IAAA,IAAQ,cAAA,KAAmB,SAAS,cAAA,KAAmB,OAAA;AAElE,EAAA,IAAI,QAAA,EAAU;AACZ,IAAA,aAAA,EAAc;AAAA,EAChB,CAAA,MAAO;AACL,IAAA,MAAM,KAAA,GAAQ,SAAS,MAAM,CAAA;AAC7B,IAAA,WAAA,CAAY,KAAA,EAAO,MAAA,CAAO,SAAA,IAAa,MAAS,CAAA;AAAA,EAClD;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 DEFAULT_OPACITY = 1;\nexport const DEFAULT_Z_INDEX = 9999;\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 DEFAULT_OPACITY,\n DEFAULT_Z_INDEX,\n} from './constants';\n\nexport const getStyle = ({\n color = DEFAULT_COLOR,\n lineHeight = DEFAULT_LINE_HEIGHT,\n offset = DEFAULT_OFFSET,\n opacity = DEFAULT_OPACITY,\n zIndex = DEFAULT_Z_INDEX,\n columnWidth,\n columnColor,\n}: StyleProps): StyleObj => {\n const horizontal = `linear-gradient(${color} 1px, transparent 1px) left top / 1px ${lineHeight}`;\n\n const background =\n columnWidth != null\n ? `${horizontal}, linear-gradient(90deg, ${columnColor ?? color} 1px, transparent 1px) left top / ${columnWidth} 1px`\n : horizontal;\n\n return {\n position: 'absolute',\n top: offset,\n left: 0,\n right: 0,\n bottom: 0,\n background,\n pointerEvents: 'none',\n opacity,\n zIndex,\n };\n};\n","import type { StyleProps } from './types';\n\nexport const presets = {\n '4px': { lineHeight: '4px', color: 'rgba(0, 150, 255, 0.15)' },\n '8px': { lineHeight: '8px', color: 'rgba(0, 150, 255, 0.2)' },\n '16px': { lineHeight: '16px', color: 'rgba(204, 204, 204, 0.5)' },\n '24px': { lineHeight: '24px', color: 'rgba(204, 204, 204, 0.5)' },\n material: { lineHeight: '4px', color: 'rgba(244, 67, 54, 0.15)' },\n tailwind: { lineHeight: '4px', color: 'rgba(99, 102, 241, 0.15)' },\n bootstrap: { lineHeight: '8px', color: 'rgba(13, 110, 253, 0.2)' },\n} as const satisfies Record<string, StyleProps>;\n\nexport type PresetName = keyof typeof presets;\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, container?: string): void {\n const element = getOrCreateElement();\n Object.assign(element.style, style);\n\n if (!element.parentNode) {\n const parent = document.querySelector(container ?? PARENT_SELECTOR);\n if (parent) {\n parent.append(element);\n }\n }\n}\n","import './storybook-parameter-augmentation';\n\nimport type { DecoratorFunction, Renderer } from 'storybook/internal/types';\n\nimport { getStyle } from './getStyle';\nimport { StyleProps, ConfigProps } from './types';\nimport { presets, PresetName } from './presets';\nimport { injectStyle, removeElement } from './utils';\nimport {\n DEFAULT_COLOR,\n DEFAULT_LINE_HEIGHT,\n DEFAULT_OFFSET,\n DEFAULT_OPACITY,\n DEFAULT_Z_INDEX,\n} from './constants';\n\nexport type VRhythmParams = StyleProps & ConfigProps;\n\nconst DEFAULT_PARAMS: VRhythmParams = {\n hide: false,\n preset: '',\n container: '',\n color: DEFAULT_COLOR,\n lineHeight: DEFAULT_LINE_HEIGHT,\n offset: DEFAULT_OFFSET,\n opacity: DEFAULT_OPACITY,\n zIndex: DEFAULT_Z_INDEX,\n};\n\nexport const withVRhythm: DecoratorFunction<Renderer> = (storyFn, context) => {\n const raw = (context.parameters as { vrhythm?: VRhythmParams } | undefined)\n ?.vrhythm;\n const presetStyles =\n raw?.preset && raw.preset in presets\n ? presets[raw.preset as PresetName]\n : {};\n const params: VRhythmParams = {\n ...DEFAULT_PARAMS,\n ...presetStyles,\n ...raw,\n };\n\n const globalsVrhythm = (\n context.globals as { vrhythm?: string | boolean } | undefined\n )?.vrhythm;\n const isHidden =\n !!params.hide || globalsVrhythm === false || globalsVrhythm === 'false';\n\n if (isHidden) {\n removeElement();\n } else {\n const style = getStyle(params);\n injectStyle(style, params.container || undefined);\n }\n\n return storyFn(context);\n};\n\nexport { presets } from './presets';\nexport type { PresetName } from './presets';\nexport type { StyleProps, ConfigProps } from './types';\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/constants.ts","../src/getStyle.ts","../src/presets.ts","../src/utils.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["export const DEFAULT_COLOR = 'rgb(204, 204, 204)';\nexport const DEFAULT_LINE_HEIGHT = '16px';\nexport const DEFAULT_LINE_WIDTH = '1px';\nexport const DEFAULT_OFFSET = 0;\nexport const DEFAULT_OPACITY = 1;\nexport const DEFAULT_Z_INDEX = 9999;\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_LINE_WIDTH,\n DEFAULT_OFFSET,\n DEFAULT_OPACITY,\n DEFAULT_Z_INDEX,\n} from './constants';\n\nexport const getStyle = ({\n color = DEFAULT_COLOR,\n lineHeight = DEFAULT_LINE_HEIGHT,\n lineWidth = DEFAULT_LINE_WIDTH,\n offset = DEFAULT_OFFSET,\n opacity = DEFAULT_OPACITY,\n zIndex = DEFAULT_Z_INDEX,\n maxWidth,\n columnWidth,\n columnColor,\n gutterWidth,\n}: StyleProps): StyleObj => {\n const horizontal = `linear-gradient(${color} ${lineWidth}, transparent ${lineWidth}) left top / ${lineWidth} ${lineHeight}`;\n\n const columnGradient =\n columnWidth != null\n ? gutterWidth != null\n ? `linear-gradient(90deg, transparent calc(${columnWidth} - ${gutterWidth}), ${columnColor ?? color} calc(${columnWidth} - ${gutterWidth})) left top / ${columnWidth} 100%`\n : `linear-gradient(90deg, ${columnColor ?? color} ${lineWidth}, transparent ${lineWidth}) left top / ${columnWidth} 100%`\n : null;\n\n const background =\n columnGradient != null ? `${horizontal}, ${columnGradient}` : horizontal;\n\n const positioning: StyleObj =\n maxWidth != null\n ? { left: '50%', width: maxWidth, transform: 'translateX(-50%)' }\n : { left: 0, right: 0 };\n\n return {\n position: 'absolute',\n top: offset,\n ...positioning,\n bottom: 0,\n background,\n pointerEvents: 'none',\n opacity,\n zIndex,\n };\n};\n","import type { StyleProps } from './types';\n\nexport const presets = {\n '4px': { lineHeight: '4px', color: 'rgba(0, 150, 255, 0.15)' },\n '8px': { lineHeight: '8px', color: 'rgba(0, 150, 255, 0.2)' },\n '16px': { lineHeight: '16px', color: 'rgba(204, 204, 204, 0.5)' },\n '24px': { lineHeight: '24px', color: 'rgba(204, 204, 204, 0.5)' },\n material: { lineHeight: '4px', color: 'rgba(244, 67, 54, 0.15)' },\n tailwind: { lineHeight: '4px', color: 'rgba(99, 102, 241, 0.15)' },\n bootstrap: { lineHeight: '8px', color: 'rgba(13, 110, 253, 0.2)' },\n} as const satisfies Record<string, StyleProps>;\n\nexport type PresetName = keyof typeof presets;\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, container?: string): void {\n const element = getOrCreateElement();\n Object.assign(element.style, style);\n\n let parent: Element | null = null;\n try {\n parent = document.querySelector(container ?? PARENT_SELECTOR);\n } catch {\n // invalid selector string — fall through to body fallback\n }\n\n if (!parent) {\n parent = document.querySelector(PARENT_SELECTOR);\n }\n\n if (parent && element.parentNode !== parent) {\n parent.append(element);\n }\n}\n","import './storybook-parameter-augmentation';\n\nimport type { DecoratorFunction, Renderer } from 'storybook/internal/types';\n\nimport { getStyle } from './getStyle';\nimport { StyleProps, ConfigProps } from './types';\nimport { presets, PresetName } from './presets';\nimport { injectStyle, removeElement } from './utils';\nimport {\n DEFAULT_COLOR,\n DEFAULT_LINE_HEIGHT,\n DEFAULT_OFFSET,\n DEFAULT_OPACITY,\n DEFAULT_Z_INDEX,\n} from './constants';\n\nexport type VRhythmParams = StyleProps & ConfigProps;\n\nconst DEFAULT_PARAMS: VRhythmParams = {\n hide: false,\n preset: '',\n container: '',\n color: DEFAULT_COLOR,\n lineHeight: DEFAULT_LINE_HEIGHT,\n offset: DEFAULT_OFFSET,\n opacity: DEFAULT_OPACITY,\n zIndex: DEFAULT_Z_INDEX,\n};\n\n/**\n * Storybook decorator that injects a vertical rhythm baseline grid overlay into stories.\n *\n * Register globally via the addon preset in `.storybook/main.ts` (recommended):\n * ```ts\n * export default { addons: ['storybook-vrhythm'] };\n * ```\n *\n * Or manually in `.storybook/preview.ts`:\n * ```ts\n * import { withVRhythm } from 'storybook-vrhythm';\n * export const decorators = [withVRhythm];\n * ```\n *\n * Control per story via `parameters.vrhythm`:\n * ```ts\n * export const MyStory = {\n * parameters: { vrhythm: { preset: 'material' } },\n * };\n * ```\n */\nexport const withVRhythm: DecoratorFunction<Renderer> = (storyFn, context) => {\n const raw = (context.parameters as { vrhythm?: VRhythmParams } | undefined)\n ?.vrhythm;\n const presetStyles =\n raw?.preset && raw.preset in presets\n ? presets[raw.preset as PresetName]\n : {};\n const params: VRhythmParams = {\n ...DEFAULT_PARAMS,\n ...presetStyles,\n ...raw,\n };\n\n const globalsVrhythm = (\n context.globals as { vrhythm?: string | boolean } | undefined\n )?.vrhythm;\n\n const globalPresetName =\n typeof globalsVrhythm === 'string' &&\n globalsVrhythm !== 'true' &&\n globalsVrhythm !== 'false' &&\n globalsVrhythm in presets\n ? (globalsVrhythm as PresetName)\n : null;\n\n const globalPresetStyles = globalPresetName ? presets[globalPresetName] : {};\n\n const isHidden =\n !!params.hide || globalsVrhythm === false || globalsVrhythm === 'false';\n\n if (isHidden) {\n removeElement();\n } else {\n const finalParams: VRhythmParams = { ...params, ...globalPresetStyles };\n const style = getStyle(finalParams);\n injectStyle(style, params.container || undefined);\n }\n\n return storyFn(context);\n};\n\nexport { presets } from './presets';\nexport type { PresetName } from './presets';\nexport type { StyleProps, ConfigProps } from './types';\n"]}
|
package/dist/preview.js
CHANGED
|
@@ -5,6 +5,7 @@ import { definePreviewAddon } from 'storybook/internal/csf';
|
|
|
5
5
|
// src/constants.ts
|
|
6
6
|
var DEFAULT_COLOR = "rgb(204, 204, 204)";
|
|
7
7
|
var DEFAULT_LINE_HEIGHT = "16px";
|
|
8
|
+
var DEFAULT_LINE_WIDTH = "1px";
|
|
8
9
|
var DEFAULT_OFFSET = 0;
|
|
9
10
|
var DEFAULT_OPACITY = 1;
|
|
10
11
|
var DEFAULT_Z_INDEX = 9999;
|
|
@@ -15,19 +16,23 @@ var DIV_ID = "storybook-rhythm";
|
|
|
15
16
|
var getStyle = ({
|
|
16
17
|
color = DEFAULT_COLOR,
|
|
17
18
|
lineHeight = DEFAULT_LINE_HEIGHT,
|
|
19
|
+
lineWidth = DEFAULT_LINE_WIDTH,
|
|
18
20
|
offset = DEFAULT_OFFSET,
|
|
19
21
|
opacity = DEFAULT_OPACITY,
|
|
20
22
|
zIndex = DEFAULT_Z_INDEX,
|
|
23
|
+
maxWidth,
|
|
21
24
|
columnWidth,
|
|
22
|
-
columnColor
|
|
25
|
+
columnColor,
|
|
26
|
+
gutterWidth
|
|
23
27
|
}) => {
|
|
24
|
-
const horizontal = `linear-gradient(${color}
|
|
25
|
-
const
|
|
28
|
+
const horizontal = `linear-gradient(${color} ${lineWidth}, transparent ${lineWidth}) left top / ${lineWidth} ${lineHeight}`;
|
|
29
|
+
const columnGradient = columnWidth != null ? gutterWidth != null ? `linear-gradient(90deg, transparent calc(${columnWidth} - ${gutterWidth}), ${columnColor ?? color} calc(${columnWidth} - ${gutterWidth})) left top / ${columnWidth} 100%` : `linear-gradient(90deg, ${columnColor ?? color} ${lineWidth}, transparent ${lineWidth}) left top / ${columnWidth} 100%` : null;
|
|
30
|
+
const background = columnGradient != null ? `${horizontal}, ${columnGradient}` : horizontal;
|
|
31
|
+
const positioning = maxWidth != null ? { left: "50%", width: maxWidth, transform: "translateX(-50%)" } : { left: 0, right: 0 };
|
|
26
32
|
return {
|
|
27
33
|
position: "absolute",
|
|
28
34
|
top: offset,
|
|
29
|
-
|
|
30
|
-
right: 0,
|
|
35
|
+
...positioning,
|
|
31
36
|
bottom: 0,
|
|
32
37
|
background,
|
|
33
38
|
pointerEvents: "none",
|
|
@@ -69,11 +74,16 @@ function removeElement() {
|
|
|
69
74
|
function injectStyle(style, container) {
|
|
70
75
|
const element = getOrCreateElement();
|
|
71
76
|
Object.assign(element.style, style);
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
+
let parent = null;
|
|
78
|
+
try {
|
|
79
|
+
parent = document.querySelector(container ?? PARENT_SELECTOR);
|
|
80
|
+
} catch {
|
|
81
|
+
}
|
|
82
|
+
if (!parent) {
|
|
83
|
+
parent = document.querySelector(PARENT_SELECTOR);
|
|
84
|
+
}
|
|
85
|
+
if (parent && element.parentNode !== parent) {
|
|
86
|
+
parent.append(element);
|
|
77
87
|
}
|
|
78
88
|
}
|
|
79
89
|
|
|
@@ -97,11 +107,14 @@ var withVRhythm = (storyFn, context) => {
|
|
|
97
107
|
...raw
|
|
98
108
|
};
|
|
99
109
|
const globalsVrhythm = context.globals?.vrhythm;
|
|
110
|
+
const globalPresetName = typeof globalsVrhythm === "string" && globalsVrhythm !== "true" && globalsVrhythm !== "false" && globalsVrhythm in presets ? globalsVrhythm : null;
|
|
111
|
+
const globalPresetStyles = globalPresetName ? presets[globalPresetName] : {};
|
|
100
112
|
const isHidden = !!params.hide || globalsVrhythm === false || globalsVrhythm === "false";
|
|
101
113
|
if (isHidden) {
|
|
102
114
|
removeElement();
|
|
103
115
|
} else {
|
|
104
|
-
const
|
|
116
|
+
const finalParams = { ...params, ...globalPresetStyles };
|
|
117
|
+
const style = getStyle(finalParams);
|
|
105
118
|
injectStyle(style, params.container || void 0);
|
|
106
119
|
}
|
|
107
120
|
return storyFn(context);
|
|
@@ -114,11 +127,18 @@ var preview_default = definePreviewAddon({
|
|
|
114
127
|
vrhythm: {
|
|
115
128
|
description: "Toggle vertical rhythm grid overlay",
|
|
116
129
|
toolbar: {
|
|
117
|
-
title: "
|
|
130
|
+
title: "Show vertical rhythm",
|
|
118
131
|
icon: "grid",
|
|
119
132
|
items: [
|
|
120
|
-
{ value: "true", title: "
|
|
121
|
-
{ value: "false", title: "Hide
|
|
133
|
+
{ value: "true", title: "Default (story params)", icon: "eye" },
|
|
134
|
+
{ value: "false", title: "Hide", icon: "eyeclose" },
|
|
135
|
+
{ value: "4px", title: "4px baseline", icon: "grid" },
|
|
136
|
+
{ value: "8px", title: "8px baseline", icon: "grid" },
|
|
137
|
+
{ value: "16px", title: "16px baseline", icon: "grid" },
|
|
138
|
+
{ value: "24px", title: "24px baseline", icon: "grid" },
|
|
139
|
+
{ value: "material", title: "Material Design", icon: "grid" },
|
|
140
|
+
{ value: "tailwind", title: "Tailwind CSS", icon: "grid" },
|
|
141
|
+
{ value: "bootstrap", title: "Bootstrap", icon: "grid" }
|
|
122
142
|
],
|
|
123
143
|
dynamicTitle: true
|
|
124
144
|
}
|
package/dist/preview.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/constants.ts","../src/getStyle.ts","../src/presets.ts","../src/utils.ts","../src/index.ts","../src/preview.ts"],"names":[],"mappings":"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","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 DEFAULT_OPACITY = 1;\nexport const DEFAULT_Z_INDEX = 9999;\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 DEFAULT_OPACITY,\n DEFAULT_Z_INDEX,\n} from './constants';\n\nexport const getStyle = ({\n color = DEFAULT_COLOR,\n lineHeight = DEFAULT_LINE_HEIGHT,\n offset = DEFAULT_OFFSET,\n opacity = DEFAULT_OPACITY,\n zIndex = DEFAULT_Z_INDEX,\n columnWidth,\n columnColor,\n}: StyleProps): StyleObj => {\n const horizontal = `linear-gradient(${color} 1px, transparent 1px) left top / 1px ${lineHeight}`;\n\n const background =\n columnWidth != null\n ? `${horizontal}, linear-gradient(90deg, ${columnColor ?? color} 1px, transparent 1px) left top / ${columnWidth} 1px`\n : horizontal;\n\n return {\n position: 'absolute',\n top: offset,\n left: 0,\n right: 0,\n bottom: 0,\n background,\n pointerEvents: 'none',\n opacity,\n zIndex,\n };\n};\n","import type { StyleProps } from './types';\n\nexport const presets = {\n '4px': { lineHeight: '4px', color: 'rgba(0, 150, 255, 0.15)' },\n '8px': { lineHeight: '8px', color: 'rgba(0, 150, 255, 0.2)' },\n '16px': { lineHeight: '16px', color: 'rgba(204, 204, 204, 0.5)' },\n '24px': { lineHeight: '24px', color: 'rgba(204, 204, 204, 0.5)' },\n material: { lineHeight: '4px', color: 'rgba(244, 67, 54, 0.15)' },\n tailwind: { lineHeight: '4px', color: 'rgba(99, 102, 241, 0.15)' },\n bootstrap: { lineHeight: '8px', color: 'rgba(13, 110, 253, 0.2)' },\n} as const satisfies Record<string, StyleProps>;\n\nexport type PresetName = keyof typeof presets;\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, container?: string): void {\n const element = getOrCreateElement();\n Object.assign(element.style, style);\n\n if (!element.parentNode) {\n const parent = document.querySelector(container ?? PARENT_SELECTOR);\n if (parent) {\n parent.append(element);\n }\n }\n}\n","import './storybook-parameter-augmentation';\n\nimport type { DecoratorFunction, Renderer } from 'storybook/internal/types';\n\nimport { getStyle } from './getStyle';\nimport { StyleProps, ConfigProps } from './types';\nimport { presets, PresetName } from './presets';\nimport { injectStyle, removeElement } from './utils';\nimport {\n DEFAULT_COLOR,\n DEFAULT_LINE_HEIGHT,\n DEFAULT_OFFSET,\n DEFAULT_OPACITY,\n DEFAULT_Z_INDEX,\n} from './constants';\n\nexport type VRhythmParams = StyleProps & ConfigProps;\n\nconst DEFAULT_PARAMS: VRhythmParams = {\n hide: false,\n preset: '',\n container: '',\n color: DEFAULT_COLOR,\n lineHeight: DEFAULT_LINE_HEIGHT,\n offset: DEFAULT_OFFSET,\n opacity: DEFAULT_OPACITY,\n zIndex: DEFAULT_Z_INDEX,\n};\n\nexport const withVRhythm: DecoratorFunction<Renderer> = (storyFn, context) => {\n const raw = (context.parameters as { vrhythm?: VRhythmParams } | undefined)\n ?.vrhythm;\n const presetStyles =\n raw?.preset && raw.preset in presets\n ? presets[raw.preset as PresetName]\n : {};\n const params: VRhythmParams = {\n ...DEFAULT_PARAMS,\n ...presetStyles,\n ...raw,\n };\n\n const globalsVrhythm = (\n context.globals as { vrhythm?: string | boolean } | undefined\n )?.vrhythm;\n const isHidden =\n !!params.hide || globalsVrhythm === false || globalsVrhythm === 'false';\n\n if (isHidden) {\n removeElement();\n } else {\n const style = getStyle(params);\n injectStyle(style, params.container || undefined);\n }\n\n return storyFn(context);\n};\n\nexport { presets } from './presets';\nexport type { PresetName } from './presets';\nexport type { StyleProps, ConfigProps } from './types';\n","import { definePreviewAddon } from 'storybook/internal/csf';\n\nimport { withVRhythm, type VRhythmParams } from './index';\n\nexport default definePreviewAddon<{\n parameters: { vrhythm?: VRhythmParams };\n globals: { vrhythm?: string | boolean };\n}>({\n decorators: [withVRhythm],\n globalTypes: {\n vrhythm: {\n description: 'Toggle vertical rhythm grid overlay',\n toolbar: {\n title: 'V-Rhythm',\n icon: 'grid',\n items: [\n { value: 'true', title: 'Show grid', icon: 'eye' },\n { value: 'false', title: 'Hide grid', icon: 'eyeclose' },\n ],\n dynamicTitle: true,\n },\n },\n },\n initialGlobals: {\n vrhythm: 'true',\n },\n});\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/constants.ts","../src/getStyle.ts","../src/presets.ts","../src/utils.ts","../src/index.ts","../src/preview.ts"],"names":[],"mappings":"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","file":"preview.js","sourcesContent":["export const DEFAULT_COLOR = 'rgb(204, 204, 204)';\nexport const DEFAULT_LINE_HEIGHT = '16px';\nexport const DEFAULT_LINE_WIDTH = '1px';\nexport const DEFAULT_OFFSET = 0;\nexport const DEFAULT_OPACITY = 1;\nexport const DEFAULT_Z_INDEX = 9999;\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_LINE_WIDTH,\n DEFAULT_OFFSET,\n DEFAULT_OPACITY,\n DEFAULT_Z_INDEX,\n} from './constants';\n\nexport const getStyle = ({\n color = DEFAULT_COLOR,\n lineHeight = DEFAULT_LINE_HEIGHT,\n lineWidth = DEFAULT_LINE_WIDTH,\n offset = DEFAULT_OFFSET,\n opacity = DEFAULT_OPACITY,\n zIndex = DEFAULT_Z_INDEX,\n maxWidth,\n columnWidth,\n columnColor,\n gutterWidth,\n}: StyleProps): StyleObj => {\n const horizontal = `linear-gradient(${color} ${lineWidth}, transparent ${lineWidth}) left top / ${lineWidth} ${lineHeight}`;\n\n const columnGradient =\n columnWidth != null\n ? gutterWidth != null\n ? `linear-gradient(90deg, transparent calc(${columnWidth} - ${gutterWidth}), ${columnColor ?? color} calc(${columnWidth} - ${gutterWidth})) left top / ${columnWidth} 100%`\n : `linear-gradient(90deg, ${columnColor ?? color} ${lineWidth}, transparent ${lineWidth}) left top / ${columnWidth} 100%`\n : null;\n\n const background =\n columnGradient != null ? `${horizontal}, ${columnGradient}` : horizontal;\n\n const positioning: StyleObj =\n maxWidth != null\n ? { left: '50%', width: maxWidth, transform: 'translateX(-50%)' }\n : { left: 0, right: 0 };\n\n return {\n position: 'absolute',\n top: offset,\n ...positioning,\n bottom: 0,\n background,\n pointerEvents: 'none',\n opacity,\n zIndex,\n };\n};\n","import type { StyleProps } from './types';\n\nexport const presets = {\n '4px': { lineHeight: '4px', color: 'rgba(0, 150, 255, 0.15)' },\n '8px': { lineHeight: '8px', color: 'rgba(0, 150, 255, 0.2)' },\n '16px': { lineHeight: '16px', color: 'rgba(204, 204, 204, 0.5)' },\n '24px': { lineHeight: '24px', color: 'rgba(204, 204, 204, 0.5)' },\n material: { lineHeight: '4px', color: 'rgba(244, 67, 54, 0.15)' },\n tailwind: { lineHeight: '4px', color: 'rgba(99, 102, 241, 0.15)' },\n bootstrap: { lineHeight: '8px', color: 'rgba(13, 110, 253, 0.2)' },\n} as const satisfies Record<string, StyleProps>;\n\nexport type PresetName = keyof typeof presets;\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, container?: string): void {\n const element = getOrCreateElement();\n Object.assign(element.style, style);\n\n let parent: Element | null = null;\n try {\n parent = document.querySelector(container ?? PARENT_SELECTOR);\n } catch {\n // invalid selector string — fall through to body fallback\n }\n\n if (!parent) {\n parent = document.querySelector(PARENT_SELECTOR);\n }\n\n if (parent && element.parentNode !== parent) {\n parent.append(element);\n }\n}\n","import './storybook-parameter-augmentation';\n\nimport type { DecoratorFunction, Renderer } from 'storybook/internal/types';\n\nimport { getStyle } from './getStyle';\nimport { StyleProps, ConfigProps } from './types';\nimport { presets, PresetName } from './presets';\nimport { injectStyle, removeElement } from './utils';\nimport {\n DEFAULT_COLOR,\n DEFAULT_LINE_HEIGHT,\n DEFAULT_OFFSET,\n DEFAULT_OPACITY,\n DEFAULT_Z_INDEX,\n} from './constants';\n\nexport type VRhythmParams = StyleProps & ConfigProps;\n\nconst DEFAULT_PARAMS: VRhythmParams = {\n hide: false,\n preset: '',\n container: '',\n color: DEFAULT_COLOR,\n lineHeight: DEFAULT_LINE_HEIGHT,\n offset: DEFAULT_OFFSET,\n opacity: DEFAULT_OPACITY,\n zIndex: DEFAULT_Z_INDEX,\n};\n\n/**\n * Storybook decorator that injects a vertical rhythm baseline grid overlay into stories.\n *\n * Register globally via the addon preset in `.storybook/main.ts` (recommended):\n * ```ts\n * export default { addons: ['storybook-vrhythm'] };\n * ```\n *\n * Or manually in `.storybook/preview.ts`:\n * ```ts\n * import { withVRhythm } from 'storybook-vrhythm';\n * export const decorators = [withVRhythm];\n * ```\n *\n * Control per story via `parameters.vrhythm`:\n * ```ts\n * export const MyStory = {\n * parameters: { vrhythm: { preset: 'material' } },\n * };\n * ```\n */\nexport const withVRhythm: DecoratorFunction<Renderer> = (storyFn, context) => {\n const raw = (context.parameters as { vrhythm?: VRhythmParams } | undefined)\n ?.vrhythm;\n const presetStyles =\n raw?.preset && raw.preset in presets\n ? presets[raw.preset as PresetName]\n : {};\n const params: VRhythmParams = {\n ...DEFAULT_PARAMS,\n ...presetStyles,\n ...raw,\n };\n\n const globalsVrhythm = (\n context.globals as { vrhythm?: string | boolean } | undefined\n )?.vrhythm;\n\n const globalPresetName =\n typeof globalsVrhythm === 'string' &&\n globalsVrhythm !== 'true' &&\n globalsVrhythm !== 'false' &&\n globalsVrhythm in presets\n ? (globalsVrhythm as PresetName)\n : null;\n\n const globalPresetStyles = globalPresetName ? presets[globalPresetName] : {};\n\n const isHidden =\n !!params.hide || globalsVrhythm === false || globalsVrhythm === 'false';\n\n if (isHidden) {\n removeElement();\n } else {\n const finalParams: VRhythmParams = { ...params, ...globalPresetStyles };\n const style = getStyle(finalParams);\n injectStyle(style, params.container || undefined);\n }\n\n return storyFn(context);\n};\n\nexport { presets } from './presets';\nexport type { PresetName } from './presets';\nexport type { StyleProps, ConfigProps } from './types';\n","import { definePreviewAddon } from 'storybook/internal/csf';\n\nimport { withVRhythm, type VRhythmParams } from './index';\n\nexport default definePreviewAddon<{\n parameters: { vrhythm?: VRhythmParams };\n globals: { vrhythm?: string | boolean };\n}>({\n decorators: [withVRhythm],\n globalTypes: {\n vrhythm: {\n description: 'Toggle vertical rhythm grid overlay',\n toolbar: {\n title: 'Show vertical rhythm',\n icon: 'grid',\n items: [\n { value: 'true', title: 'Default (story params)', icon: 'eye' },\n { value: 'false', title: 'Hide', icon: 'eyeclose' },\n { value: '4px', title: '4px baseline', icon: 'grid' },\n { value: '8px', title: '8px baseline', icon: 'grid' },\n { value: '16px', title: '16px baseline', icon: 'grid' },\n { value: '24px', title: '24px baseline', icon: 'grid' },\n { value: 'material', title: 'Material Design', icon: 'grid' },\n { value: 'tailwind', title: 'Tailwind CSS', icon: 'grid' },\n { value: 'bootstrap', title: 'Bootstrap', icon: 'grid' },\n ],\n dynamicTitle: true,\n },\n },\n },\n initialGlobals: {\n vrhythm: 'true',\n },\n});\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "storybook-vrhythm",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Baseline grid overlay for Storybook — see your vertical rhythm while you build",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "jmlweb",
|
|
@@ -53,16 +53,17 @@
|
|
|
53
53
|
"node": ">=20"
|
|
54
54
|
},
|
|
55
55
|
"peerDependencies": {
|
|
56
|
-
"storybook": "^10.0.0
|
|
56
|
+
"storybook": "^10.0.0"
|
|
57
57
|
},
|
|
58
58
|
"storybook": {
|
|
59
59
|
"displayName": "Vertical Rhythm Grid",
|
|
60
|
+
"icon": "https://raw.githubusercontent.com/jmlweb/storybook-vrhythm/master/packages/storybook-vrhythm/icon.png",
|
|
60
61
|
"supportedFrameworks": [
|
|
61
62
|
"react",
|
|
62
63
|
"vue",
|
|
63
64
|
"angular",
|
|
64
65
|
"web-components",
|
|
65
|
-
"html
|
|
66
|
+
"html",
|
|
66
67
|
"svelte"
|
|
67
68
|
]
|
|
68
69
|
},
|
|
@@ -72,7 +73,7 @@
|
|
|
72
73
|
"test": "vitest run",
|
|
73
74
|
"test:watch": "vitest",
|
|
74
75
|
"test:coverage": "vitest run --coverage",
|
|
75
|
-
"
|
|
76
|
+
"typecheck": "tsc --noEmit",
|
|
76
77
|
"format": "prettier --write 'src/**/*.ts' 'test/**/*.ts'",
|
|
77
78
|
"format:check": "prettier --check 'src/**/*.ts' 'test/**/*.ts'"
|
|
78
79
|
},
|