@scm-manager/ui-components 4.0.0-REACT18-20250701-125025 → 4.0.0-REACT19

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.
Files changed (124) hide show
  1. package/package.json +46 -51
  2. package/src/BranchSelector.stories.tsx +60 -11
  3. package/src/Breadcrumb.stories.tsx +131 -57
  4. package/src/Breadcrumb.tsx +3 -3
  5. package/src/CardColumn.stories.tsx +94 -27
  6. package/src/CardColumnSmall.stories.tsx +102 -27
  7. package/src/CommaSeparatedList.tsx +2 -2
  8. package/src/Date.stories.tsx +64 -17
  9. package/src/Duration.stories.tsx +92 -45
  10. package/src/ErrorBoundary.tsx +38 -58
  11. package/src/ErrorNotification.tsx +1 -1
  12. package/src/Help.stories.tsx +61 -17
  13. package/src/Help.tsx +5 -11
  14. package/src/Icon.stories.tsx +93 -13
  15. package/src/LinkPaginator.tsx +9 -6
  16. package/src/Loading.stories.tsx +26 -6
  17. package/src/Logo.stories.tsx +44 -13
  18. package/src/Notification.stories.tsx +111 -23
  19. package/src/OverviewPageActions.tsx +5 -5
  20. package/src/Paginator.test.tsx +115 -94
  21. package/src/PdfViewer.stories.tsx +83 -5
  22. package/src/PreformattedCodeBlock.stories.tsx +97 -26
  23. package/src/ProtectedRoute.tsx +14 -39
  24. package/src/SmallLoadingSpinner.stories.tsx +26 -6
  25. package/src/SyntaxHighlighter.stories.tsx +122 -40
  26. package/src/SyntaxHighlighterRenderer.tsx +7 -7
  27. package/src/Tag.stories.tsx +135 -18
  28. package/src/Tag.tsx +2 -1
  29. package/src/Tooltip.stories.tsx +147 -34
  30. package/src/__snapshots__/storyshots.test.ts.snap +6 -112
  31. package/src/avatar/Avatar.ts +1 -1
  32. package/src/avatar/AvatarImage.tsx +1 -1
  33. package/src/avatar/AvatarWrapper.tsx +2 -2
  34. package/src/buttons/Button.stories.tsx +159 -0
  35. package/src/buttons/Button.tsx +5 -5
  36. package/src/config/ConfigurationBinder.tsx +39 -39
  37. package/src/config/ConfigurationForm.tsx +2 -1
  38. package/src/config/TitledSettings.tsx +4 -1
  39. package/src/forms/AddKeyValueEntryToTableField.stories.tsx +60 -25
  40. package/src/forms/Checkbox.stories.tsx +165 -27
  41. package/src/forms/Checkbox.tsx +1 -0
  42. package/src/forms/DropDown.stories.tsx +81 -35
  43. package/src/forms/FileInput.stories.tsx +85 -10
  44. package/src/forms/InputField.stories.tsx +210 -37
  45. package/src/forms/InputField.tsx +1 -0
  46. package/src/forms/Radio.stories.tsx +181 -34
  47. package/src/forms/Radio.tsx +1 -0
  48. package/src/forms/Select.stories.tsx +266 -46
  49. package/src/forms/Select.tsx +1 -0
  50. package/src/forms/Textarea.stories.tsx +99 -53
  51. package/src/forms/Textarea.tsx +1 -0
  52. package/src/forms/index.ts +3 -1
  53. package/src/index.ts +5 -5
  54. package/src/jest-dom.d.ts +17 -0
  55. package/src/layout/Footer.stories.tsx +114 -22
  56. package/src/layout/FooterSection.tsx +1 -0
  57. package/src/layout/Header.tsx +2 -1
  58. package/src/layout/Page.tsx +1 -3
  59. package/src/layout/PrimaryContentColumn.tsx +2 -2
  60. package/src/layout/SecondaryNavigationColumn.tsx +3 -3
  61. package/src/layout/SubSubtitle.tsx +2 -1
  62. package/src/layout/Subtitle.tsx +2 -1
  63. package/src/layout/Title.tsx +2 -5
  64. package/src/markdown/LazyMarkdownView.tsx +16 -5
  65. package/src/markdown/MarkdownHeadingRenderer.test.ts +9 -1
  66. package/src/markdown/MarkdownHeadingRenderer.tsx +3 -3
  67. package/src/markdown/MarkdownImageRenderer.test.ts +8 -1
  68. package/src/markdown/MarkdownImageRenderer.tsx +2 -1
  69. package/src/markdown/MarkdownLinkRenderer.test.tsx +9 -0
  70. package/src/markdown/MarkdownLinkRenderer.tsx +6 -4
  71. package/src/markdown/MarkdownView.stories.tsx +224 -72
  72. package/src/markdown/markdownExtensions.ts +6 -4
  73. package/src/modals/ConfirmAlert.stories.tsx +133 -44
  74. package/src/modals/ConfirmAlert.tsx +5 -4
  75. package/src/modals/Modal.stories.tsx +461 -252
  76. package/src/modals/Modal.tsx +12 -11
  77. package/src/modals/useRegisterModal.test.tsx +5 -4
  78. package/src/navigation/MenuContext.tsx +2 -2
  79. package/src/navigation/NavLink.tsx +4 -7
  80. package/src/navigation/PrimaryNavigation.tsx +2 -2
  81. package/src/navigation/PrimaryNavigationLink.tsx +6 -5
  82. package/src/navigation/RoutingProps.ts +1 -3
  83. package/src/navigation/SecondaryNavigation.stories.tsx +157 -45
  84. package/src/navigation/SecondaryNavigation.tsx +17 -16
  85. package/src/navigation/SecondaryNavigationItem.tsx +2 -1
  86. package/src/navigation/SubNavigation.tsx +4 -8
  87. package/src/navigation/useActiveMatch.ts +20 -22
  88. package/src/navigation/useNavigationLock.ts +1 -0
  89. package/src/popover/Popover.stories.tsx +111 -41
  90. package/src/popover/Popover.tsx +2 -5
  91. package/src/repos/Diff.stories.tsx +418 -223
  92. package/src/repos/Diff.tsx +1 -5
  93. package/src/repos/HunkExpandDivider.tsx +2 -2
  94. package/src/repos/LoadingDiff.tsx +11 -6
  95. package/src/repos/RepositoryEntry.stories.tsx +217 -53
  96. package/src/repos/RepositoryFlag.tsx +2 -1
  97. package/src/repos/TokenizedDiffView.tsx +4 -2
  98. package/src/repos/annotate/Annotate.stories.tsx +225 -111
  99. package/src/repos/annotate/AnnotateLine.tsx +2 -1
  100. package/src/repos/changesets/ChangesetAuthor.tsx +2 -2
  101. package/src/repos/changesets/ChangesetButtonGroup.test.tsx +9 -5
  102. package/src/repos/changesets/ChangesetDiff.test.ts +10 -2
  103. package/src/repos/changesets/Changesets.stories.tsx +388 -197
  104. package/src/repos/changesets/ContributorRow.tsx +2 -2
  105. package/src/repos/changesets/SignatureIcon.tsx +1 -0
  106. package/src/repos/diff/DiffFileTree.tsx +1 -1
  107. package/src/repos/diff/styledElements.tsx +4 -3
  108. package/src/repos/index.ts +15 -15
  109. package/src/search/Hit.tsx +3 -2
  110. package/src/search/TextHitField.stories.tsx +131 -43
  111. package/src/search/TextHitField.tsx +3 -2
  112. package/src/search/index.ts +1 -1
  113. package/src/storyshots.test.ts +66 -60
  114. package/src/table/Table.stories.tsx +146 -48
  115. package/src/table/Table.tsx +7 -8
  116. package/src/table/TextColumn.tsx +0 -9
  117. package/src/toast/Toast.tsx +2 -1
  118. package/src/toast/ToastArea.tsx +2 -2
  119. package/src/toast/ToastButton.tsx +2 -1
  120. package/src/toast/ToastButtons.tsx +4 -2
  121. package/src/toast/ToastNotification.tsx +2 -1
  122. package/src/toast/index.stories.tsx +144 -39
  123. package/src/toast/index.ts +1 -1
  124. package/src/buttons/index.stories.tsx +0 -85
@@ -14,23 +14,135 @@
14
14
  * along with this program. If not, see https://www.gnu.org/licenses/.
15
15
  */
16
16
 
17
+ // import React, { FC, useRef, useState } from "react";
18
+ // import { storiesOf } from "@storybook/react";
19
+ // import Checkbox from "./Checkbox";
20
+ // import styled from "styled-components";
21
+ // import Button from "../buttons/Button";
22
+ // import { useForm } from "react-hook-form";
23
+ // import { SubmitButton } from "../buttons";
24
+ // import { MemoryRouter } from "react-router-dom";
25
+ //
26
+ // const Spacing = styled.div`
27
+ // padding: 2em;
28
+ // `;
29
+ //
30
+ // const Ref: FC = () => {
31
+ // const ref = useRef<HTMLInputElement>(null);
32
+ // return (
33
+ // <>
34
+ // <Checkbox label={"Ref Checkbox"} checked={false} ref={ref} />
35
+ // <Button
36
+ // action={() => {
37
+ // if (ref.current) {
38
+ // ref.current.checked = !ref.current.checked;
39
+ // }
40
+ // }}
41
+ // color="primary"
42
+ // >
43
+ // Toggle Checkbox
44
+ // </Button>
45
+ // </>
46
+ // );
47
+ // };
48
+ //
49
+ // type Settings = {
50
+ // rememberMe: string;
51
+ // scramblePassword: string;
52
+ // readonly: boolean;
53
+ // disabled: boolean;
54
+ // };
55
+ //
56
+ // const ReactHookForm: FC = () => {
57
+ // const { register, handleSubmit } = useForm<Settings>({
58
+ // defaultValues: {
59
+ // disabled: true,
60
+ // readonly: true,
61
+ // },
62
+ // });
63
+ // const [stored, setStored] = useState<Settings>();
64
+ //
65
+ // const onSubmit = (settings: Settings) => {
66
+ // setStored(settings);
67
+ // };
68
+ //
69
+ // return (
70
+ // <>
71
+ // <form onSubmit={handleSubmit(onSubmit)}>
72
+ // <Checkbox label="Remember Me" {...register("rememberMe")} />
73
+ // <Checkbox label="Scramble Password" {...register("scramblePassword")} />
74
+ // <Checkbox label="Disabled wont be submitted" disabled={true} {...register("disabled")} />
75
+ // <Checkbox label="Readonly will be submitted" readOnly={true} {...register("readonly")} />
76
+ // <div className="pt-2">
77
+ // <SubmitButton>Submit</SubmitButton>
78
+ // </div>
79
+ // </form>
80
+ // {stored ? (
81
+ // <div className="mt-5">
82
+ // <pre>
83
+ // <code>{JSON.stringify(stored, null, 2)}</code>
84
+ // </pre>
85
+ // </div>
86
+ // ) : null}
87
+ // </>
88
+ // );
89
+ // };
90
+ //
91
+ // const LegacyEvents: FC = () => {
92
+ // const [value, setValue] = useState<boolean>(false);
93
+ // return (
94
+ // <>
95
+ // <Checkbox checked={value} onChange={setValue} />
96
+ // <div className="mt-3">{JSON.stringify(value)}</div>
97
+ // </>
98
+ // );
99
+ // };
100
+ //
101
+ // storiesOf("Forms/Checkbox", module)
102
+ // .addDecorator((storyFn) => <MemoryRouter>{storyFn()}</MemoryRouter>)
103
+ // .add("Default", () => (
104
+ // <Spacing>
105
+ // <Checkbox label="Not checked" checked={false} />
106
+ // <Checkbox label="Checked" checked={true} />
107
+ // <Checkbox label="Indeterminate" checked={true} indeterminate={true} />
108
+ // </Spacing>
109
+ // ))
110
+ // .add("Disabled", () => (
111
+ // <Spacing>
112
+ // <Checkbox label="Checked but disabled" checked={true} disabled={true} />
113
+ // </Spacing>
114
+ // ))
115
+ // .add("With HelpText", () => (
116
+ // <Spacing>
117
+ // <Checkbox label="Classic helpText" checked={false} helpText="This is a classic help text." />
118
+ // <Checkbox
119
+ // label="Long helpText"
120
+ // checked={true}
121
+ // helpText="Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet."
122
+ // />
123
+ // </Spacing>
124
+ // ))
125
+ // .add("Ref", () => <Ref />)
126
+ // .add("Legacy Events", () => <LegacyEvents />)
127
+ // .add("ReactHookForm", () => <ReactHookForm />);
128
+
17
129
  import React, { FC, useRef, useState } from "react";
18
- import { storiesOf } from "@storybook/react";
19
- import Checkbox from "./Checkbox";
20
130
  import styled from "styled-components";
21
- import Button from "../buttons/Button";
22
131
  import { useForm } from "react-hook-form";
132
+ import type { Meta, StoryObj } from "@storybook/react";
133
+
134
+ import Checkbox from "./Checkbox";
135
+ import Button from "../buttons/Button";
23
136
  import { SubmitButton } from "../buttons";
24
- import { MemoryRouter } from "react-router-dom";
25
137
 
26
138
  const Spacing = styled.div`
27
139
  padding: 2em;
28
140
  `;
29
141
 
30
- const Ref: FC = () => {
142
+ const RefExample: FC = () => {
31
143
  const ref = useRef<HTMLInputElement>(null);
32
144
  return (
33
- <>
145
+ <Spacing>
34
146
  <Checkbox label={"Ref Checkbox"} checked={false} ref={ref} />
35
147
  <Button
36
148
  action={() => {
@@ -42,7 +154,7 @@ const Ref: FC = () => {
42
154
  >
43
155
  Toggle Checkbox
44
156
  </Button>
45
- </>
157
+ </Spacing>
46
158
  );
47
159
  };
48
160
 
@@ -53,7 +165,7 @@ type Settings = {
53
165
  disabled: boolean;
54
166
  };
55
167
 
56
- const ReactHookForm: FC = () => {
168
+ const ReactHookFormExample: FC = () => {
57
169
  const { register, handleSubmit } = useForm<Settings>({
58
170
  defaultValues: {
59
171
  disabled: true,
@@ -67,7 +179,7 @@ const ReactHookForm: FC = () => {
67
179
  };
68
180
 
69
181
  return (
70
- <>
182
+ <Spacing>
71
183
  <form onSubmit={handleSubmit(onSubmit)}>
72
184
  <Checkbox label="Remember Me" {...register("rememberMe")} />
73
185
  <Checkbox label="Scramble Password" {...register("scramblePassword")} />
@@ -77,42 +189,58 @@ const ReactHookForm: FC = () => {
77
189
  <SubmitButton>Submit</SubmitButton>
78
190
  </div>
79
191
  </form>
80
- {stored ? (
192
+ {stored && (
81
193
  <div className="mt-5">
82
194
  <pre>
83
195
  <code>{JSON.stringify(stored, null, 2)}</code>
84
196
  </pre>
85
197
  </div>
86
- ) : null}
87
- </>
198
+ )}
199
+ </Spacing>
88
200
  );
89
201
  };
90
202
 
91
- const LegacyEvents: FC = () => {
92
- const [value, setValue] = useState<boolean>(false);
203
+ const OnChangeExample: FC = () => {
204
+ const [value, setValue] = useState(false);
93
205
  return (
94
- <>
206
+ <Spacing>
95
207
  <Checkbox checked={value} onChange={setValue} />
96
208
  <div className="mt-3">{JSON.stringify(value)}</div>
97
- </>
209
+ </Spacing>
98
210
  );
99
211
  };
100
212
 
101
- storiesOf("Forms/Checkbox", module)
102
- .addDecorator((storyFn) => <MemoryRouter>{storyFn()}</MemoryRouter>)
103
- .add("Default", () => (
213
+ const meta: Meta<typeof Checkbox> = {
214
+ title: "Forms/Checkbox",
215
+ component: Checkbox,
216
+ decorators: [(Story) => Story()],
217
+ tags: ["autodocs"],
218
+ };
219
+
220
+ export default meta;
221
+
222
+ type Story = StoryObj<typeof meta>;
223
+
224
+ export const Default: Story = {
225
+ render: () => (
104
226
  <Spacing>
105
227
  <Checkbox label="Not checked" checked={false} />
106
228
  <Checkbox label="Checked" checked={true} />
107
229
  <Checkbox label="Indeterminate" checked={true} indeterminate={true} />
108
230
  </Spacing>
109
- ))
110
- .add("Disabled", () => (
231
+ ),
232
+ };
233
+
234
+ export const Disabled: Story = {
235
+ render: () => (
111
236
  <Spacing>
112
237
  <Checkbox label="Checked but disabled" checked={true} disabled={true} />
113
238
  </Spacing>
114
- ))
115
- .add("With HelpText", () => (
239
+ ),
240
+ };
241
+
242
+ export const WithHelpText: Story = {
243
+ render: () => (
116
244
  <Spacing>
117
245
  <Checkbox label="Classic helpText" checked={false} helpText="This is a classic help text." />
118
246
  <Checkbox
@@ -121,7 +249,17 @@ storiesOf("Forms/Checkbox", module)
121
249
  helpText="Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet."
122
250
  />
123
251
  </Spacing>
124
- ))
125
- .add("Ref", () => <Ref />)
126
- .add("Legacy Events", () => <LegacyEvents />)
127
- .add("ReactHookForm", () => <ReactHookForm />);
252
+ ),
253
+ };
254
+
255
+ export const UsingRefs: Story = {
256
+ render: () => <RefExample />,
257
+ };
258
+
259
+ export const HandlingOnChange: Story = {
260
+ render: () => <OnChangeExample />,
261
+ };
262
+
263
+ export const WithReactHookForm: Story = {
264
+ render: () => <ReactHookFormExample />,
265
+ };
@@ -139,6 +139,7 @@ const InnerCheckbox: FC<FieldProps<BaseProps, HTMLInputElement, boolean>> = ({
139
139
  /**
140
140
  * @deprecated
141
141
  */
142
+ // @ts-ignore
142
143
  const Checkbox: FieldType<BaseProps, HTMLInputElement, boolean> = createFormFieldWrapper(InnerCheckbox);
143
144
 
144
145
  export default Checkbox;
@@ -14,41 +14,87 @@
14
14
  * along with this program. If not, see https://www.gnu.org/licenses/.
15
15
  */
16
16
 
17
+ // import React from "react";
18
+ // import { storiesOf } from "@storybook/react";
19
+ // import DropDown from "./DropDown";
20
+ //
21
+ // storiesOf("Forms/DropDown", module)
22
+ // .add("Default", () => (
23
+ // <DropDown
24
+ // options={["en", "de", "es"]}
25
+ // preselectedOption={"de"}
26
+ // optionSelected={() => {
27
+ // // nothing to do
28
+ // }}
29
+ // />
30
+ // ))
31
+ // .add("With Translation", () => (
32
+ // <DropDown
33
+ // optionValues={["hg2g", "dirk", "liff"]}
34
+ // options={[
35
+ // "The Hitchhiker's Guide to the Galaxy",
36
+ // "Dirk Gently’s Holistic Detective Agency",
37
+ // "The Meaning Of Liff",
38
+ // ]}
39
+ // preselectedOption={"dirk"}
40
+ // optionSelected={(selection) => {
41
+ // // nothing to do
42
+ // }}
43
+ // />
44
+ // ))
45
+ // .add("Add preselect if missing in options", () => (
46
+ // <DropDown
47
+ // optionValues={["alpha", "beta", "gamma"]}
48
+ // options={["A", "B", "C"]}
49
+ // preselectedOption={"D"}
50
+ // optionSelected={(selection) => {
51
+ // // nothing to do
52
+ // }}
53
+ // />
54
+ // ));
55
+
17
56
  import React from "react";
18
- import { storiesOf } from "@storybook/react";
57
+ import type { Meta, StoryObj } from "@storybook/react";
58
+
19
59
  import DropDown from "./DropDown";
20
60
 
21
- storiesOf("Forms/DropDown", module)
22
- .add("Default", () => (
23
- <DropDown
24
- options={["en", "de", "es"]}
25
- preselectedOption={"de"}
26
- optionSelected={() => {
27
- // nothing to do
28
- }}
29
- />
30
- ))
31
- .add("With Translation", () => (
32
- <DropDown
33
- optionValues={["hg2g", "dirk", "liff"]}
34
- options={[
35
- "The Hitchhiker's Guide to the Galaxy",
36
- "Dirk Gently’s Holistic Detective Agency",
37
- "The Meaning Of Liff",
38
- ]}
39
- preselectedOption={"dirk"}
40
- optionSelected={(selection) => {
41
- // nothing to do
42
- }}
43
- />
44
- ))
45
- .add("Add preselect if missing in options", () => (
46
- <DropDown
47
- optionValues={["alpha", "beta", "gamma"]}
48
- options={["A", "B", "C"]}
49
- preselectedOption={"D"}
50
- optionSelected={(selection) => {
51
- // nothing to do
52
- }}
53
- />
54
- ));
61
+ const meta: Meta<typeof DropDown> = {
62
+ title: "Forms/DropDown",
63
+ component: DropDown,
64
+ parameters: {
65
+ layout: "centered",
66
+ },
67
+ argTypes: {
68
+ optionSelected: { action: "optionSelected" },
69
+ },
70
+ tags: ["autodocs"],
71
+ };
72
+
73
+ export default meta;
74
+
75
+ type Story = StoryObj<typeof meta>;
76
+
77
+ export const Default: Story = {
78
+ args: {
79
+ options: ["en", "de", "es"],
80
+ preselectedOption: "de",
81
+ },
82
+ };
83
+
84
+ export const WithDisplayValues: Story = {
85
+ name: "With Custom Display Values",
86
+ args: {
87
+ optionValues: ["hg2g", "dirk", "liff"],
88
+ options: ["The Hitchhiker's Guide to the Galaxy", "Dirk Gently’s Holistic Detective Agency", "The Meaning Of Liff"],
89
+ preselectedOption: "dirk",
90
+ },
91
+ };
92
+
93
+ export const PreselectedOptionNotInList: Story = {
94
+ name: "Preselected Value Not In Options",
95
+ args: {
96
+ optionValues: ["alpha", "beta", "gamma"],
97
+ options: ["A", "B", "C"],
98
+ preselectedOption: "D",
99
+ },
100
+ };
@@ -14,13 +14,61 @@
14
14
  * along with this program. If not, see https://www.gnu.org/licenses/.
15
15
  */
16
16
 
17
+ // import React, { FC, useState } from "react";
18
+ // import { MemoryRouter } from "react-router-dom";
19
+ // import { useForm } from "react-hook-form";
20
+ // import { storiesOf } from "@storybook/react";
21
+ // import { Level, SubmitButton } from "../index";
22
+ // import FileInput from "./FileInput";
23
+ // import styled from "styled-components";
24
+ //
25
+ // const Decorator = styled.div`
26
+ // padding: 2rem;
27
+ // max-width: 40rem;
28
+ // `;
29
+ //
30
+ // type Settings = {
31
+ // uploadFile: string;
32
+ // };
33
+ //
34
+ // const ReactHookForm: FC = () => {
35
+ // const { register, handleSubmit } = useForm<Settings>();
36
+ // const [stored, setStored] = useState<Settings>();
37
+ //
38
+ // const onSubmit = (settings: Settings) => {
39
+ // setStored(settings);
40
+ // };
41
+ //
42
+ // return (
43
+ // <>
44
+ // <form onSubmit={handleSubmit(onSubmit)}>
45
+ // <FileInput label="Upload File" helpText="Select your most loved file" {...register("uploadFile")} />
46
+ // <Level right={<SubmitButton>Submit</SubmitButton>} />
47
+ // </form>
48
+ // {stored ? (
49
+ // <div className="mt-5">
50
+ // <pre>
51
+ // <code>{JSON.stringify(stored, null, 2)}</code>
52
+ // </pre>
53
+ // </div>
54
+ // ) : null}
55
+ // </>
56
+ // );
57
+ // };
58
+ //
59
+ // storiesOf("Forms/FileInput", module)
60
+ // .addDecorator((storyFn) => <Decorator>{storyFn()}</Decorator>)
61
+ // .addDecorator((storyFn) => <MemoryRouter>{storyFn()}</MemoryRouter>)
62
+ // .add("Default", () => <ReactHookForm />);
63
+
17
64
  import React, { FC, useState } from "react";
18
65
  import { MemoryRouter } from "react-router-dom";
19
66
  import { useForm } from "react-hook-form";
20
- import { storiesOf } from "@storybook/react";
21
- import { Level, SubmitButton } from "../index";
22
- import FileInput from "./FileInput";
23
67
  import styled from "styled-components";
68
+ import type { Meta, StoryObj } from "@storybook/react";
69
+
70
+ import FileInput from "./FileInput";
71
+ import { Level, SubmitButton } from "../index";
24
72
 
25
73
  const Decorator = styled.div`
26
74
  padding: 2rem;
@@ -31,7 +79,7 @@ type Settings = {
31
79
  uploadFile: string;
32
80
  };
33
81
 
34
- const ReactHookForm: FC = () => {
82
+ const ReactHookFormExample: FC = () => {
35
83
  const { register, handleSubmit } = useForm<Settings>();
36
84
  const [stored, setStored] = useState<Settings>();
37
85
 
@@ -45,18 +93,45 @@ const ReactHookForm: FC = () => {
45
93
  <FileInput label="Upload File" helpText="Select your most loved file" {...register("uploadFile")} />
46
94
  <Level right={<SubmitButton>Submit</SubmitButton>} />
47
95
  </form>
48
- {stored ? (
96
+ {stored && (
49
97
  <div className="mt-5">
50
98
  <pre>
51
99
  <code>{JSON.stringify(stored, null, 2)}</code>
52
100
  </pre>
53
101
  </div>
54
- ) : null}
102
+ )}
55
103
  </>
56
104
  );
57
105
  };
58
106
 
59
- storiesOf("Forms/FileInput", module)
60
- .addDecorator((storyFn) => <Decorator>{storyFn()}</Decorator>)
61
- .addDecorator((storyFn) => <MemoryRouter>{storyFn()}</MemoryRouter>)
62
- .add("Default", () => <ReactHookForm />);
107
+ // --- Storybook Metadata ---
108
+
109
+ const meta: Meta<typeof FileInput> = {
110
+ title: "Forms/FileInput",
111
+ component: FileInput,
112
+ decorators: [(Story) => <Decorator>{Story()}</Decorator>, (Story) => <MemoryRouter>{Story()}</MemoryRouter>],
113
+ tags: ["autodocs"],
114
+ };
115
+
116
+ export default meta;
117
+
118
+ type Story = StoryObj<typeof meta>;
119
+
120
+ export const Default: Story = {
121
+ args: {
122
+ label: "Default File Input",
123
+ helpText: "Please select a file.",
124
+ },
125
+ };
126
+
127
+ export const Disabled: Story = {
128
+ args: {
129
+ ...Default.args,
130
+ label: "Disabled File Input",
131
+ disabled: true,
132
+ },
133
+ };
134
+
135
+ export const WithReactHookForm: Story = {
136
+ render: () => <ReactHookFormExample />,
137
+ };