@repobuddy/storybook 2.2.1 → 2.2.2

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/esm/index.d.ts CHANGED
@@ -4,7 +4,6 @@ import { ReactNode } from "react";
4
4
  import * as react_jsx_runtime0 from "react/jsx-runtime";
5
5
  import { ClassNameProps, StyleProps } from "@just-web/css";
6
6
  import { Args, DecoratorFunction, Renderer } from "storybook/internal/csf";
7
- import { ClassValue } from "class-variance-authority/types";
8
7
  import { Decorator, Meta, StoryContext, StoryObj, StrictArgs } from "@storybook/react-vite";
9
8
  export * from "@repobuddy/test";
10
9
 
@@ -56,9 +55,9 @@ type StoryCardProps = {
56
55
  * If a function is provided, it receives the card state and default className,
57
56
  * and should return the final className string.
58
57
  */
59
- className?: ((state: Pick<StoryCardProps, 'status'> & {
58
+ className?: ((state: Required<Pick<StoryCardProps, 'status'>> & {
60
59
  defaultClassName: string;
61
- }) => string) | ClassValue | undefined;
60
+ }) => string) | string | undefined;
62
61
  /**
63
62
  * Content to display in the card body.
64
63
  * Can be any React node (string, JSX, etc.).
@@ -137,6 +136,7 @@ type StoryCardProps = {
137
136
  */
138
137
  declare function withStoryCard<TRenderer extends Renderer = Renderer>({
139
138
  title,
139
+ status,
140
140
  content: contentProp,
141
141
  ...rest
142
142
  }?: StoryCardProps): DecoratorFunction<TRenderer>;
package/esm/index.js CHANGED
@@ -150,7 +150,7 @@ function generateKey(prefix) {
150
150
  * or fall back to the component description.
151
151
  * - Cards are collected and displayed in the order they are defined in the decorators array.
152
152
  */
153
- function withStoryCard({ title, content: contentProp, ...rest } = {}) {
153
+ function withStoryCard({ title, status = "info", content: contentProp, ...rest } = {}) {
154
154
  return (Story, { parameters, viewMode }) => {
155
155
  if (viewMode === "docs") return /* @__PURE__ */ jsx(Story, {});
156
156
  const content = contentProp ?? parameters.docs?.description?.story ?? parameters.docs?.description?.component;
@@ -159,6 +159,7 @@ function withStoryCard({ title, content: contentProp, ...rest } = {}) {
159
159
  Story,
160
160
  content,
161
161
  title,
162
+ status,
162
163
  ...rest
163
164
  });
164
165
  };
@@ -176,47 +177,44 @@ function StoryCardContainer({ children }) {
176
177
  const [cards, setCards] = useState([]);
177
178
  const contextValue = useMemo(() => ({
178
179
  addCard(card) {
179
- const id = generateKey("story-card");
180
+ const key = generateKey("story-card");
180
181
  setCards((cards$1) => [...cards$1, {
181
182
  ...card,
182
- id
183
+ key
183
184
  }]);
184
- return id;
185
+ return key;
185
186
  },
186
- removeCard(id) {
187
- setCards((cards$1) => cards$1.filter((card) => card.id !== id));
187
+ removeCard(key) {
188
+ setCards((cards$1) => cards$1.filter((card) => card.key !== key));
188
189
  }
189
190
  }), []);
190
191
  return /* @__PURE__ */ jsx(StoryCardContext.Provider, {
191
192
  value: contextValue,
192
193
  children: /* @__PURE__ */ jsxs("div", {
193
194
  className: "flex flex-col gap-2",
194
- children: [cards.map(({ id, status, className, content, title }) => /* @__PURE__ */ jsxs("section", {
195
+ children: [cards.map(({ key, status, className, content, title }) => /* @__PURE__ */ jsxs("section", {
195
196
  className: storyCardTheme({ status }, className),
196
197
  children: [title && /* @__PURE__ */ jsx("h2", {
197
198
  className: "text-lg font-bold",
198
199
  children: title
199
200
  }), content]
200
- }, id)), children]
201
+ }, key)), children]
201
202
  })
202
203
  });
203
204
  }
204
- const storyCardTheme = (state, className) => {
205
+ function storyCardTheme(state, className) {
205
206
  const defaultClassName = storyCardVariants(state);
206
207
  if (!className) return defaultClassName;
207
- return twMerge(defaultClassName, typeof className === "function" ? className({
208
+ return typeof className === "function" ? className({
208
209
  ...state,
209
210
  defaultClassName
210
- }) : className);
211
- };
212
- const storyCardVariants = cva("flex flex-col gap-1 py-3 px-4 rounded text-black dark:text-gray-100", {
213
- variants: { status: {
214
- error: "bg-red-100 dark:bg-red-900",
215
- warn: "bg-yellow-100 dark:bg-yellow-900",
216
- info: "bg-sky-100 dark:bg-sky-900"
217
- } },
218
- defaultVariants: { status: "info" }
219
- });
211
+ }) : twMerge(defaultClassName, className);
212
+ }
213
+ const storyCardVariants = cva("flex flex-col gap-1 py-3 px-4 rounded text-black dark:text-gray-100", { variants: { status: {
214
+ error: "bg-red-100 dark:bg-red-900",
215
+ warn: "bg-yellow-100 dark:bg-yellow-900",
216
+ info: "bg-sky-100 dark:bg-sky-900"
217
+ } } });
220
218
  function StoryCardCollector({ Story, title, status, className, content }) {
221
219
  const context = useContext(StoryCardContext);
222
220
  const cardIdRef = useRef(null);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@repobuddy/storybook",
3
- "version": "2.2.1",
3
+ "version": "2.2.2",
4
4
  "description": "Storybook repo buddy",
5
5
  "keywords": [
6
6
  "storybook",
@@ -54,14 +54,15 @@
54
54
  "@repobuddy/test": "^1.0.0",
55
55
  "class-variance-authority": "^0.7.1",
56
56
  "htmlfy": "^1.0.0",
57
- "tailwind-merge": "^3.4.0"
57
+ "tailwind-merge": "^3.4.0",
58
+ "type-plus": "8.0.0-beta.7"
58
59
  },
59
60
  "devDependencies": {
60
61
  "@repobuddy/vitest": "^2.0.0",
61
62
  "@storybook-community/storybook-dark-mode": "^7.0.2",
62
- "@storybook/addon-docs": "^10.0.7",
63
- "@storybook/addon-vitest": "^10.0.7",
64
- "@storybook/react-vite": "^10.0.7",
63
+ "@storybook/addon-docs": "^10.1.10",
64
+ "@storybook/addon-vitest": "^10.1.10",
65
+ "@storybook/react-vite": "^10.1.10",
65
66
  "@tailwindcss/cli": "^4.1.17",
66
67
  "@tailwindcss/vite": "^4.1.17",
67
68
  "@vitest/browser": "^4.0.16",
@@ -72,7 +73,7 @@
72
73
  "react": "^19.2.0",
73
74
  "react-dom": "^19.2.0",
74
75
  "rimraf": "^6.1.0",
75
- "storybook": "^10.0.8",
76
+ "storybook": "^10.1.10",
76
77
  "storybook-addon-tag-badges": "^3.0.2",
77
78
  "tailwindcss": "^4.1.17",
78
79
  "tsdown": "^0.18.0",
@@ -81,7 +82,7 @@
81
82
  },
82
83
  "peerDependencies": {
83
84
  "@storybook-community/storybook-dark-mode": "^7.0.0",
84
- "@storybook/addon-docs": "^10.0.0",
85
+ "@storybook/addon-docs": "^10.1.10",
85
86
  "storybook-addon-tag-badges": "^3.0.2"
86
87
  },
87
88
  "peerDependenciesMeta": {
@@ -1,5 +1,4 @@
1
1
  import { cva } from 'class-variance-authority'
2
- import type { ClassValue } from 'class-variance-authority/types'
3
2
  import {
4
3
  createContext,
5
4
  useContext,
@@ -12,7 +11,8 @@ import {
12
11
  } from 'react'
13
12
  import type { DecoratorFunction, Renderer } from 'storybook/internal/csf'
14
13
  import { twMerge } from 'tailwind-merge'
15
- import { generateKey } from '../utils/generate_key'
14
+ import type { RequiredPick } from 'type-plus'
15
+ import { generateKey } from '../utils/generate_key.js'
16
16
 
17
17
  export type StoryCardProps = {
18
18
  /**
@@ -35,8 +35,8 @@ export type StoryCardProps = {
35
35
  * and should return the final className string.
36
36
  */
37
37
  className?:
38
- | ((state: Pick<StoryCardProps, 'status'> & { defaultClassName: string }) => string)
39
- | ClassValue
38
+ | ((state: Required<Pick<StoryCardProps, 'status'>> & { defaultClassName: string }) => string)
39
+ | string
40
40
  | undefined
41
41
  /**
42
42
  * Content to display in the card body.
@@ -117,6 +117,7 @@ export type StoryCardProps = {
117
117
  */
118
118
  export function withStoryCard<TRenderer extends Renderer = Renderer>({
119
119
  title,
120
+ status = 'info',
120
121
  content: contentProp,
121
122
  ...rest
122
123
  }: StoryCardProps = {}): DecoratorFunction<TRenderer> {
@@ -126,11 +127,11 @@ export function withStoryCard<TRenderer extends Renderer = Renderer>({
126
127
  const content = contentProp ?? parameters.docs?.description?.story ?? parameters.docs?.description?.component
127
128
  if (!content && !title) return <Story />
128
129
 
129
- return <StoryCardContainerWrapper Story={Story} content={content} title={title} {...rest} />
130
+ return <StoryCardContainerWrapper Story={Story} content={content} title={title} status={status} {...rest} />
130
131
  }
131
132
  }
132
133
 
133
- interface StoryCardContainerWrapperProps extends StoryCardProps {
134
+ interface StoryCardContainerWrapperProps extends RequiredPick<StoryCardProps, 'status'> {
134
135
  Story: ComponentType
135
136
  }
136
137
 
@@ -146,17 +147,17 @@ function StoryCardContainerWrapper({ Story, ...props }: StoryCardContainerWrappe
146
147
  }
147
148
 
148
149
  function StoryCardContainer({ children }: { children: ReactNode }) {
149
- const [cards, setCards] = useState<StoryCardWithId[]>([])
150
+ const [cards, setCards] = useState<StoryCardWithKey[]>([])
150
151
 
151
152
  const contextValue: StoryCardContextValue = useMemo(
152
153
  () => ({
153
154
  addCard(card) {
154
- const id = generateKey('story-card')
155
- setCards((cards) => [...cards, { ...card, id }])
156
- return id
155
+ const key = generateKey('story-card')
156
+ setCards((cards) => [...cards, { ...card, key }])
157
+ return key
157
158
  },
158
- removeCard(id) {
159
- setCards((cards) => cards.filter((card) => card.id !== id))
159
+ removeCard(key) {
160
+ setCards((cards) => cards.filter((card) => card.key !== key))
160
161
  }
161
162
  }),
162
163
  []
@@ -165,8 +166,8 @@ function StoryCardContainer({ children }: { children: ReactNode }) {
165
166
  return (
166
167
  <StoryCardContext.Provider value={contextValue}>
167
168
  <div className="flex flex-col gap-2">
168
- {cards.map(({ id, status, className, content, title }) => (
169
- <section key={id} className={storyCardTheme({ status }, className)}>
169
+ {cards.map(({ key, status, className, content, title }) => (
170
+ <section key={key} className={storyCardTheme({ status }, className)}>
170
171
  {title && <h2 className="text-lg font-bold">{title}</h2>}
171
172
  {content}
172
173
  </section>
@@ -177,15 +178,14 @@ function StoryCardContainer({ children }: { children: ReactNode }) {
177
178
  )
178
179
  }
179
180
 
180
- type StoryCardWithId = StoryCardProps & { id: string }
181
+ type StoryCardWithKey = RequiredPick<StoryCardProps, 'status'> & { key: string }
181
182
 
182
- const storyCardTheme = (state: Pick<StoryCardProps, 'status'>, className: StoryCardProps['className']) => {
183
+ function storyCardTheme(state: Required<Pick<StoryCardProps, 'status'>>, className: StoryCardProps['className']) {
183
184
  const defaultClassName = storyCardVariants(state)
184
185
  if (!className) return defaultClassName
185
- return twMerge(
186
- defaultClassName,
187
- typeof className === 'function' ? className({ ...state, defaultClassName }) : className
188
- )
186
+ return typeof className === 'function'
187
+ ? className({ ...state, defaultClassName })
188
+ : twMerge(defaultClassName, className)
189
189
  }
190
190
 
191
191
  const storyCardVariants = cva('flex flex-col gap-1 py-3 px-4 rounded text-black dark:text-gray-100', {
@@ -195,13 +195,10 @@ const storyCardVariants = cva('flex flex-col gap-1 py-3 px-4 rounded text-black
195
195
  warn: 'bg-yellow-100 dark:bg-yellow-900',
196
196
  info: 'bg-sky-100 dark:bg-sky-900'
197
197
  }
198
- },
199
- defaultVariants: {
200
- status: 'info'
201
198
  }
202
199
  })
203
200
 
204
- interface StoryCardCollectorProps extends StoryCardProps {
201
+ interface StoryCardCollectorProps extends RequiredPick<StoryCardProps, 'status'> {
205
202
  Story: ComponentType
206
203
  }
207
204
 
@@ -229,7 +226,7 @@ function StoryCardCollector({ Story, title, status, className, content }: StoryC
229
226
  }
230
227
 
231
228
  interface StoryCardContextValue {
232
- addCard: (card: StoryCardProps) => string
229
+ addCard: (card: RequiredPick<StoryCardProps, 'status'>) => string
233
230
  removeCard: (id: string) => void
234
231
  }
235
232