@scm-manager/ui-components 3.10.4-20250824-132529 → 4.0.0-REACT18-20250824-143504
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/package.json +45 -50
- package/src/BranchSelector.stories.tsx +60 -11
- package/src/Breadcrumb.stories.tsx +131 -57
- package/src/Breadcrumb.tsx +3 -3
- package/src/CardColumn.stories.tsx +94 -27
- package/src/CardColumnSmall.stories.tsx +102 -27
- package/src/CommaSeparatedList.tsx +2 -2
- package/src/Date.stories.tsx +64 -17
- package/src/Duration.stories.tsx +92 -45
- package/src/ErrorBoundary.tsx +38 -58
- package/src/ErrorNotification.tsx +1 -1
- package/src/Help.stories.tsx +61 -17
- package/src/Help.tsx +5 -11
- package/src/Icon.stories.tsx +93 -13
- package/src/Image.tsx +2 -3
- package/src/LinkPaginator.tsx +9 -6
- package/src/Loading.stories.tsx +26 -6
- package/src/Logo.stories.tsx +44 -13
- package/src/Notification.stories.tsx +111 -23
- package/src/OverviewPageActions.tsx +5 -5
- package/src/Paginator.test.tsx +115 -94
- package/src/PdfViewer.stories.tsx +83 -5
- package/src/PreformattedCodeBlock.stories.tsx +97 -26
- package/src/ProtectedRoute.tsx +14 -39
- package/src/SmallLoadingSpinner.stories.tsx +26 -6
- package/src/SyntaxHighlighter.stories.tsx +122 -40
- package/src/SyntaxHighlighterRenderer.tsx +7 -7
- package/src/Tag.stories.tsx +135 -18
- package/src/Tag.tsx +2 -1
- package/src/Tooltip.stories.tsx +147 -34
- package/src/__snapshots__/storyshots.test.ts.snap +21 -144
- package/src/avatar/Avatar.ts +1 -1
- package/src/avatar/AvatarImage.tsx +2 -2
- package/src/avatar/AvatarWrapper.tsx +2 -2
- package/src/buttons/Button.stories.tsx +159 -0
- package/src/buttons/Button.tsx +5 -5
- package/src/config/ConfigurationBinder.tsx +39 -39
- package/src/config/ConfigurationForm.tsx +2 -1
- package/src/config/TitledSettings.tsx +4 -1
- package/src/forms/AddKeyValueEntryToTableField.stories.tsx +60 -25
- package/src/forms/Checkbox.stories.tsx +165 -27
- package/src/forms/Checkbox.tsx +1 -0
- package/src/forms/DropDown.stories.tsx +81 -35
- package/src/forms/FileInput.stories.tsx +85 -10
- package/src/forms/InputField.stories.tsx +210 -37
- package/src/forms/InputField.tsx +1 -0
- package/src/forms/Radio.stories.tsx +181 -34
- package/src/forms/Radio.tsx +1 -0
- package/src/forms/Select.stories.tsx +266 -46
- package/src/forms/Select.tsx +1 -0
- package/src/forms/Textarea.stories.tsx +99 -53
- package/src/forms/Textarea.tsx +1 -0
- package/src/forms/index.ts +3 -1
- package/src/index.ts +5 -5
- package/src/jest-dom.d.ts +17 -0
- package/src/layout/Footer.stories.tsx +114 -22
- package/src/layout/Footer.tsx +11 -7
- package/src/layout/FooterSection.tsx +1 -0
- package/src/layout/Header.tsx +2 -1
- package/src/layout/Page.tsx +1 -3
- package/src/layout/PrimaryContentColumn.tsx +2 -2
- package/src/layout/SecondaryNavigationColumn.tsx +3 -3
- package/src/layout/SubSubtitle.tsx +2 -1
- package/src/layout/Subtitle.tsx +2 -1
- package/src/layout/Title.tsx +2 -5
- package/src/markdown/LazyMarkdownView.tsx +16 -5
- package/src/markdown/MarkdownHeadingRenderer.test.ts +9 -1
- package/src/markdown/MarkdownHeadingRenderer.tsx +3 -3
- package/src/markdown/MarkdownImageRenderer.test.ts +8 -1
- package/src/markdown/MarkdownImageRenderer.tsx +2 -1
- package/src/markdown/MarkdownLinkRenderer.test.tsx +9 -0
- package/src/markdown/MarkdownLinkRenderer.tsx +6 -4
- package/src/markdown/MarkdownView.stories.tsx +224 -72
- package/src/markdown/markdownExtensions.ts +6 -4
- package/src/modals/ActiveModalCountContextProvider.tsx +2 -2
- package/src/modals/ConfirmAlert.stories.tsx +133 -44
- package/src/modals/ConfirmAlert.tsx +5 -4
- package/src/modals/Modal.stories.tsx +461 -252
- package/src/modals/Modal.tsx +12 -11
- package/src/modals/useRegisterModal.test.tsx +5 -4
- package/src/navigation/MenuContext.tsx +2 -2
- package/src/navigation/NavLink.tsx +4 -7
- package/src/navigation/PrimaryNavigation.tsx +2 -2
- package/src/navigation/PrimaryNavigationLink.tsx +6 -5
- package/src/navigation/RoutingProps.ts +1 -3
- package/src/navigation/SecondaryNavigation.stories.tsx +157 -45
- package/src/navigation/SecondaryNavigation.tsx +17 -16
- package/src/navigation/SecondaryNavigationItem.tsx +2 -1
- package/src/navigation/SubNavigation.tsx +4 -8
- package/src/navigation/useActiveMatch.ts +20 -22
- package/src/navigation/useNavigationLock.ts +1 -0
- package/src/popover/Popover.stories.tsx +111 -41
- package/src/popover/Popover.tsx +2 -5
- package/src/repos/Diff.stories.tsx +418 -223
- package/src/repos/Diff.tsx +1 -5
- package/src/repos/DiffTypes.ts +2 -14
- package/src/repos/HunkExpandDivider.tsx +2 -2
- package/src/repos/LoadingDiff.tsx +11 -6
- package/src/repos/RepositoryEntry.stories.tsx +217 -53
- package/src/repos/RepositoryFlag.tsx +2 -1
- package/src/repos/TokenizedDiffView.tsx +4 -2
- package/src/repos/annotate/Annotate.stories.tsx +225 -111
- package/src/repos/annotate/AnnotateLine.tsx +2 -1
- package/src/repos/changesets/ChangesetAuthor.tsx +4 -4
- package/src/repos/changesets/ChangesetButtonGroup.test.tsx +9 -5
- package/src/repos/changesets/ChangesetDiff.test.ts +10 -2
- package/src/repos/changesets/Changesets.stories.tsx +388 -197
- package/src/repos/changesets/Contributor.tsx +1 -1
- package/src/repos/changesets/ContributorRow.tsx +2 -2
- package/src/repos/changesets/SignatureIcon.tsx +1 -0
- package/src/repos/changesets/SingleChangeset.tsx +0 -1
- package/src/repos/diff/DiffFileTree.tsx +37 -89
- package/src/repos/diff/styledElements.tsx +4 -3
- package/src/repos/index.ts +15 -15
- package/src/search/Hit.tsx +3 -2
- package/src/search/TextHitField.stories.tsx +131 -43
- package/src/search/TextHitField.tsx +3 -2
- package/src/search/index.ts +1 -1
- package/src/storyshots.test.ts +66 -60
- package/src/table/Table.stories.tsx +146 -48
- package/src/table/Table.tsx +7 -8
- package/src/table/TextColumn.tsx +0 -9
- package/src/toast/Toast.tsx +2 -1
- package/src/toast/ToastArea.tsx +2 -2
- package/src/toast/ToastButton.tsx +2 -1
- package/src/toast/ToastButtons.tsx +4 -2
- package/src/toast/ToastNotification.tsx +2 -1
- package/src/toast/index.stories.tsx +144 -39
- package/src/toast/index.ts +1 -1
- package/src/buttons/index.stories.tsx +0 -85
|
@@ -14,15 +14,212 @@
|
|
|
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 Button from "../buttons/Button";
|
|
19
|
+
// import { useForm } from "react-hook-form";
|
|
20
|
+
// import { SubmitButton } from "../buttons";
|
|
21
|
+
// import { storiesOf } from "@storybook/react";
|
|
22
|
+
// import { MemoryRouter } from "react-router-dom";
|
|
23
|
+
// import Select from "./Select";
|
|
24
|
+
//
|
|
25
|
+
// const Ref: FC = () => {
|
|
26
|
+
// const ref = useRef<HTMLSelectElement>(null);
|
|
27
|
+
// const [selected, setSelected] = useState("false");
|
|
28
|
+
// return (
|
|
29
|
+
// <>
|
|
30
|
+
// <Select
|
|
31
|
+
// options={[
|
|
32
|
+
// { label: "foo", value: "true" },
|
|
33
|
+
// { label: "bar", value: "false" },
|
|
34
|
+
// ]}
|
|
35
|
+
// value={selected}
|
|
36
|
+
// label={"Ref Radio Button"}
|
|
37
|
+
// onChange={(e) => setSelected(e.target.value)}
|
|
38
|
+
// ref={ref}
|
|
39
|
+
// />
|
|
40
|
+
// <Button
|
|
41
|
+
// action={() => {
|
|
42
|
+
// if (ref.current) {
|
|
43
|
+
// ref.current.focus();
|
|
44
|
+
// }
|
|
45
|
+
// }}
|
|
46
|
+
// color="primary"
|
|
47
|
+
// >
|
|
48
|
+
// Focus Select Field
|
|
49
|
+
// </Button>
|
|
50
|
+
// {selected}
|
|
51
|
+
// </>
|
|
52
|
+
// );
|
|
53
|
+
// };
|
|
54
|
+
//
|
|
55
|
+
// type Settings = {
|
|
56
|
+
// rememberMe: string;
|
|
57
|
+
// scramblePassword: string;
|
|
58
|
+
// disabled: string;
|
|
59
|
+
// readonly: string;
|
|
60
|
+
// };
|
|
61
|
+
//
|
|
62
|
+
// const ReactHookForm: FC = () => {
|
|
63
|
+
// const { register, handleSubmit } = useForm<Settings>();
|
|
64
|
+
// const [stored, setStored] = useState<Settings>();
|
|
65
|
+
//
|
|
66
|
+
// const onSubmit = (settings: Settings) => {
|
|
67
|
+
// setStored(settings);
|
|
68
|
+
// };
|
|
69
|
+
//
|
|
70
|
+
// return (
|
|
71
|
+
// <>
|
|
72
|
+
// <form onSubmit={handleSubmit(onSubmit)}>
|
|
73
|
+
// <Select
|
|
74
|
+
// options={[
|
|
75
|
+
// { label: "Yes", value: "true" },
|
|
76
|
+
// { label: "No", value: "false" },
|
|
77
|
+
// ]}
|
|
78
|
+
// label="Remember Me"
|
|
79
|
+
// {...register("rememberMe")}
|
|
80
|
+
// />
|
|
81
|
+
// <Select
|
|
82
|
+
// options={[
|
|
83
|
+
// { label: "Yes", value: "true" },
|
|
84
|
+
// { label: "No", value: "false" },
|
|
85
|
+
// ]}
|
|
86
|
+
// label="Scramble Password"
|
|
87
|
+
// {...register("scramblePassword")}
|
|
88
|
+
// />
|
|
89
|
+
// <Select
|
|
90
|
+
// options={[
|
|
91
|
+
// { label: "Yes", value: "true" },
|
|
92
|
+
// { label: "No", value: "false" },
|
|
93
|
+
// ]}
|
|
94
|
+
// label="Disabled wont be submitted"
|
|
95
|
+
// defaultValue="false"
|
|
96
|
+
// disabled={true}
|
|
97
|
+
// {...register("disabled")}
|
|
98
|
+
// />
|
|
99
|
+
// <Select
|
|
100
|
+
// options={[
|
|
101
|
+
// { label: "Yes", value: "true" },
|
|
102
|
+
// { label: "No", value: "false" },
|
|
103
|
+
// ]}
|
|
104
|
+
// label="Readonly will be submitted"
|
|
105
|
+
// readOnly={true}
|
|
106
|
+
// defaultValue="false"
|
|
107
|
+
// {...register("readonly")}
|
|
108
|
+
// />
|
|
109
|
+
//
|
|
110
|
+
// <div className="pt-2">
|
|
111
|
+
// <SubmitButton>Submit</SubmitButton>
|
|
112
|
+
// </div>
|
|
113
|
+
// </form>
|
|
114
|
+
// {stored ? (
|
|
115
|
+
// <div className="mt-5">
|
|
116
|
+
// <pre>
|
|
117
|
+
// <code>{JSON.stringify(stored, null, 2)}</code>
|
|
118
|
+
// </pre>
|
|
119
|
+
// </div>
|
|
120
|
+
// ) : null}
|
|
121
|
+
// </>
|
|
122
|
+
// );
|
|
123
|
+
// };
|
|
124
|
+
//
|
|
125
|
+
// const LegacyEvents: FC = () => {
|
|
126
|
+
// const [value, setValue] = useState<string>();
|
|
127
|
+
// return (
|
|
128
|
+
// <>
|
|
129
|
+
// <Select
|
|
130
|
+
// options={[
|
|
131
|
+
// { label: "Yes", value: "true" },
|
|
132
|
+
// { label: "No", value: "false" },
|
|
133
|
+
// ]}
|
|
134
|
+
// onChange={setValue}
|
|
135
|
+
// />
|
|
136
|
+
// <div className="mt-3">{JSON.stringify(value)}</div>
|
|
137
|
+
// </>
|
|
138
|
+
// );
|
|
139
|
+
// };
|
|
140
|
+
//
|
|
141
|
+
// const AddNoExistingValue: FC = () => {
|
|
142
|
+
// const [value, setValue] = useState<string>("uscss-prometheus");
|
|
143
|
+
//
|
|
144
|
+
// return (
|
|
145
|
+
// <>
|
|
146
|
+
// <Select
|
|
147
|
+
// options={[
|
|
148
|
+
// {
|
|
149
|
+
// label: "Millennium Falcon",
|
|
150
|
+
// value: "millennium-falcon",
|
|
151
|
+
// },
|
|
152
|
+
// {
|
|
153
|
+
// label: "Razor Crest",
|
|
154
|
+
// value: "razor-crest",
|
|
155
|
+
// },
|
|
156
|
+
// ]}
|
|
157
|
+
// onChange={setValue}
|
|
158
|
+
// addValueToOptions={true}
|
|
159
|
+
// value={value}
|
|
160
|
+
// />
|
|
161
|
+
// <div className="mt-3">{value}</div>
|
|
162
|
+
// </>
|
|
163
|
+
// );
|
|
164
|
+
// };
|
|
165
|
+
//
|
|
166
|
+
// const PreselectOption: FC = () => {
|
|
167
|
+
// const [value, setValue] = useState<string>("razor-crest");
|
|
168
|
+
//
|
|
169
|
+
// return (
|
|
170
|
+
// <>
|
|
171
|
+
// <Select
|
|
172
|
+
// options={[
|
|
173
|
+
// {
|
|
174
|
+
// label: "Millennium Falcon",
|
|
175
|
+
// value: "millennium-falcon",
|
|
176
|
+
// },
|
|
177
|
+
// {
|
|
178
|
+
// label: "Razor Crest",
|
|
179
|
+
// value: "razor-crest",
|
|
180
|
+
// },
|
|
181
|
+
// {
|
|
182
|
+
// label: "USCSS Prometheus",
|
|
183
|
+
// value: "uscss-prometheus",
|
|
184
|
+
// },
|
|
185
|
+
// ]}
|
|
186
|
+
// onChange={setValue}
|
|
187
|
+
// value={value}
|
|
188
|
+
// />
|
|
189
|
+
// <div className="mt-3">{value}</div>
|
|
190
|
+
// </>
|
|
191
|
+
// );
|
|
192
|
+
// };
|
|
193
|
+
//
|
|
194
|
+
// storiesOf("Forms/Select", module)
|
|
195
|
+
// .addDecorator((storyFn) => <MemoryRouter>{storyFn()}</MemoryRouter>)
|
|
196
|
+
// .add("Add no existing value", () => <AddNoExistingValue />)
|
|
197
|
+
// .add("Ref", () => <Ref />)
|
|
198
|
+
// .add("Legacy Events", () => <LegacyEvents />)
|
|
199
|
+
// .add("ReactHookForm", () => <ReactHookForm />)
|
|
200
|
+
// .add("Preselect option", () => <PreselectOption />);
|
|
201
|
+
|
|
17
202
|
import React, { FC, useRef, useState } from "react";
|
|
18
|
-
import Button from "../buttons/Button";
|
|
19
|
-
import { useForm } from "react-hook-form";
|
|
20
|
-
import { SubmitButton } from "../buttons";
|
|
21
|
-
import { storiesOf } from "@storybook/react";
|
|
22
203
|
import { MemoryRouter } from "react-router-dom";
|
|
204
|
+
import { useForm } from "react-hook-form";
|
|
205
|
+
import styled from "styled-components";
|
|
206
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
207
|
+
|
|
23
208
|
import Select from "./Select";
|
|
209
|
+
import Button from "../buttons/Button";
|
|
210
|
+
import { SubmitButton } from "../buttons";
|
|
24
211
|
|
|
25
|
-
|
|
212
|
+
// --- Helper Components & Styles (preserved from your original story) ---
|
|
213
|
+
|
|
214
|
+
const Decorator = styled.div`
|
|
215
|
+
padding: 2rem;
|
|
216
|
+
max-width: 30rem;
|
|
217
|
+
display: flex;
|
|
218
|
+
flex-direction: column;
|
|
219
|
+
gap: 1rem;
|
|
220
|
+
`;
|
|
221
|
+
|
|
222
|
+
const RefExample: FC = () => {
|
|
26
223
|
const ref = useRef<HTMLSelectElement>(null);
|
|
27
224
|
const [selected, setSelected] = useState("false");
|
|
28
225
|
return (
|
|
@@ -33,7 +230,7 @@ const Ref: FC = () => {
|
|
|
33
230
|
{ label: "bar", value: "false" },
|
|
34
231
|
]}
|
|
35
232
|
value={selected}
|
|
36
|
-
label={"Ref
|
|
233
|
+
label={"Ref Select Field"}
|
|
37
234
|
onChange={(e) => setSelected(e.target.value)}
|
|
38
235
|
ref={ref}
|
|
39
236
|
/>
|
|
@@ -47,7 +244,7 @@ const Ref: FC = () => {
|
|
|
47
244
|
>
|
|
48
245
|
Focus Select Field
|
|
49
246
|
</Button>
|
|
50
|
-
{selected}
|
|
247
|
+
Selected value: {selected}
|
|
51
248
|
</>
|
|
52
249
|
);
|
|
53
250
|
};
|
|
@@ -59,7 +256,7 @@ type Settings = {
|
|
|
59
256
|
readonly: string;
|
|
60
257
|
};
|
|
61
258
|
|
|
62
|
-
const
|
|
259
|
+
const ReactHookFormExample: FC = () => {
|
|
63
260
|
const { register, handleSubmit } = useForm<Settings>();
|
|
64
261
|
const [stored, setStored] = useState<Settings>();
|
|
65
262
|
|
|
@@ -106,23 +303,22 @@ const ReactHookForm: FC = () => {
|
|
|
106
303
|
defaultValue="false"
|
|
107
304
|
{...register("readonly")}
|
|
108
305
|
/>
|
|
109
|
-
|
|
110
306
|
<div className="pt-2">
|
|
111
307
|
<SubmitButton>Submit</SubmitButton>
|
|
112
308
|
</div>
|
|
113
309
|
</form>
|
|
114
|
-
{stored
|
|
310
|
+
{stored && (
|
|
115
311
|
<div className="mt-5">
|
|
116
312
|
<pre>
|
|
117
313
|
<code>{JSON.stringify(stored, null, 2)}</code>
|
|
118
314
|
</pre>
|
|
119
315
|
</div>
|
|
120
|
-
)
|
|
316
|
+
)}
|
|
121
317
|
</>
|
|
122
318
|
);
|
|
123
319
|
};
|
|
124
320
|
|
|
125
|
-
const
|
|
321
|
+
const OnChangeExample: FC = () => {
|
|
126
322
|
const [value, setValue] = useState<string>();
|
|
127
323
|
return (
|
|
128
324
|
<>
|
|
@@ -133,68 +329,92 @@ const LegacyEvents: FC = () => {
|
|
|
133
329
|
]}
|
|
134
330
|
onChange={setValue}
|
|
135
331
|
/>
|
|
136
|
-
<div className="mt-3">{JSON.stringify(value)}</div>
|
|
332
|
+
<div className="mt-3">Selected value: {JSON.stringify(value)}</div>
|
|
137
333
|
</>
|
|
138
334
|
);
|
|
139
335
|
};
|
|
140
336
|
|
|
141
|
-
const
|
|
337
|
+
const AddNoExistingValueExample: FC = () => {
|
|
142
338
|
const [value, setValue] = useState<string>("uscss-prometheus");
|
|
143
|
-
|
|
144
339
|
return (
|
|
145
340
|
<>
|
|
146
341
|
<Select
|
|
147
342
|
options={[
|
|
148
|
-
{
|
|
149
|
-
|
|
150
|
-
value: "millennium-falcon",
|
|
151
|
-
},
|
|
152
|
-
{
|
|
153
|
-
label: "Razor Crest",
|
|
154
|
-
value: "razor-crest",
|
|
155
|
-
},
|
|
343
|
+
{ label: "Millennium Falcon", value: "millennium-falcon" },
|
|
344
|
+
{ label: "Razor Crest", value: "razor-crest" },
|
|
156
345
|
]}
|
|
157
346
|
onChange={setValue}
|
|
158
347
|
addValueToOptions={true}
|
|
159
348
|
value={value}
|
|
160
349
|
/>
|
|
161
|
-
<div className="mt-3">{value}</div>
|
|
350
|
+
<div className="mt-3">Selected value: {value}</div>
|
|
162
351
|
</>
|
|
163
352
|
);
|
|
164
353
|
};
|
|
165
354
|
|
|
166
|
-
const
|
|
355
|
+
const PreselectOptionExample: FC = () => {
|
|
167
356
|
const [value, setValue] = useState<string>("razor-crest");
|
|
168
|
-
|
|
169
357
|
return (
|
|
170
358
|
<>
|
|
171
359
|
<Select
|
|
172
360
|
options={[
|
|
173
|
-
{
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
},
|
|
177
|
-
{
|
|
178
|
-
label: "Razor Crest",
|
|
179
|
-
value: "razor-crest",
|
|
180
|
-
},
|
|
181
|
-
{
|
|
182
|
-
label: "USCSS Prometheus",
|
|
183
|
-
value: "uscss-prometheus",
|
|
184
|
-
},
|
|
361
|
+
{ label: "Millennium Falcon", value: "millennium-falcon" },
|
|
362
|
+
{ label: "Razor Crest", value: "razor-crest" },
|
|
363
|
+
{ label: "USCSS Prometheus", value: "uscss-prometheus" },
|
|
185
364
|
]}
|
|
186
365
|
onChange={setValue}
|
|
187
366
|
value={value}
|
|
188
367
|
/>
|
|
189
|
-
<div className="mt-3">{value}</div>
|
|
368
|
+
<div className="mt-3">Selected value: {value}</div>
|
|
190
369
|
</>
|
|
191
370
|
);
|
|
192
371
|
};
|
|
193
372
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
373
|
+
// --- Storybook Metadata ---
|
|
374
|
+
|
|
375
|
+
const meta: Meta<typeof Select> = {
|
|
376
|
+
title: "Forms/Select",
|
|
377
|
+
component: Select,
|
|
378
|
+
decorators: [(Story) => <Decorator>{Story()}</Decorator>, (Story) => <MemoryRouter>{Story()}</MemoryRouter>],
|
|
379
|
+
argTypes: {
|
|
380
|
+
onChange: { action: "changed" },
|
|
381
|
+
},
|
|
382
|
+
tags: ["autodocs"],
|
|
383
|
+
};
|
|
384
|
+
|
|
385
|
+
export default meta;
|
|
386
|
+
|
|
387
|
+
// --- Story Definitions ---
|
|
388
|
+
|
|
389
|
+
type Story = StoryObj<typeof meta>;
|
|
390
|
+
|
|
391
|
+
// A new, simple story to show the basic component and enable Controls
|
|
392
|
+
export const Default: Story = {
|
|
393
|
+
args: {
|
|
394
|
+
label: "Starship",
|
|
395
|
+
options: [
|
|
396
|
+
{ label: "Millennium Falcon", value: "millennium-falcon" },
|
|
397
|
+
{ label: "Razor Crest", value: "razor-crest" },
|
|
398
|
+
],
|
|
399
|
+
},
|
|
400
|
+
};
|
|
401
|
+
|
|
402
|
+
export const AddNoExistingValue: Story = {
|
|
403
|
+
render: () => <AddNoExistingValueExample />,
|
|
404
|
+
};
|
|
405
|
+
|
|
406
|
+
export const UsingRefs: Story = {
|
|
407
|
+
render: () => <RefExample />,
|
|
408
|
+
};
|
|
409
|
+
|
|
410
|
+
export const HandlingOnChange: Story = {
|
|
411
|
+
render: () => <OnChangeExample />,
|
|
412
|
+
};
|
|
413
|
+
|
|
414
|
+
export const WithReactHookForm: Story = {
|
|
415
|
+
render: () => <ReactHookFormExample />,
|
|
416
|
+
};
|
|
417
|
+
|
|
418
|
+
export const PreselectingAnOption: Story = {
|
|
419
|
+
render: () => <PreselectOptionExample />,
|
|
420
|
+
};
|
package/src/forms/Select.tsx
CHANGED
|
@@ -140,6 +140,7 @@ const InnerSelect: FC<FieldProps<BaseProps, HTMLSelectElement, string>> = ({
|
|
|
140
140
|
/**
|
|
141
141
|
* @deprecated
|
|
142
142
|
*/
|
|
143
|
+
// @ts-ignore
|
|
143
144
|
const Select: FieldType<BaseProps, HTMLSelectElement, string> = createFormFieldWrapper(InnerSelect);
|
|
144
145
|
|
|
145
146
|
export default Select;
|
|
@@ -15,32 +15,38 @@
|
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
import React, { FC, useRef, useState } from "react";
|
|
18
|
-
import { storiesOf } from "@storybook/react";
|
|
19
18
|
import styled from "styled-components";
|
|
19
|
+
import { useForm } from "react-hook-form";
|
|
20
|
+
import { MemoryRouter } from "react-router-dom";
|
|
21
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
22
|
+
|
|
20
23
|
import Textarea from "./Textarea";
|
|
21
24
|
import Button from "../buttons/Button";
|
|
22
|
-
import { useForm } from "react-hook-form";
|
|
23
25
|
import { SubmitButton } from "../buttons";
|
|
24
|
-
|
|
25
|
-
|
|
26
|
+
|
|
27
|
+
// --- Helper Components & Styles (preserved from your original story) ---
|
|
26
28
|
|
|
27
29
|
const Spacing = styled.div`
|
|
28
30
|
padding: 2em;
|
|
31
|
+
max-width: 40rem;
|
|
32
|
+
display: flex;
|
|
33
|
+
flex-direction: column;
|
|
34
|
+
gap: 1rem;
|
|
29
35
|
`;
|
|
30
36
|
|
|
31
|
-
const
|
|
37
|
+
const OnChangeExample: FC = () => {
|
|
32
38
|
const [value, setValue] = useState("Start typing");
|
|
33
39
|
return (
|
|
34
|
-
|
|
35
|
-
<Textarea value={value} onChange={
|
|
40
|
+
<>
|
|
41
|
+
<Textarea value={value} onChange={setValue} />
|
|
36
42
|
<hr />
|
|
37
43
|
<p>{value}</p>
|
|
38
|
-
|
|
44
|
+
</>
|
|
39
45
|
);
|
|
40
46
|
};
|
|
41
47
|
|
|
42
|
-
const
|
|
43
|
-
const [value, setValue] = useState("Use
|
|
48
|
+
const OnSubmitExample: FC = () => {
|
|
49
|
+
const [value, setValue] = useState("Use ctrl/command + Enter to submit the textarea");
|
|
44
50
|
const [submitted, setSubmitted] = useState("");
|
|
45
51
|
|
|
46
52
|
const submit = () => {
|
|
@@ -49,48 +55,46 @@ const OnSubmitTextare = () => {
|
|
|
49
55
|
};
|
|
50
56
|
|
|
51
57
|
return (
|
|
52
|
-
|
|
53
|
-
<Textarea value={value} onChange={
|
|
58
|
+
<>
|
|
59
|
+
<Textarea value={value} onChange={setValue} onSubmit={submit} />
|
|
54
60
|
<hr />
|
|
55
|
-
<p>
|
|
56
|
-
|
|
61
|
+
<p>
|
|
62
|
+
<strong>Submitted:</strong> {submitted}
|
|
63
|
+
</p>
|
|
64
|
+
</>
|
|
57
65
|
);
|
|
58
66
|
};
|
|
59
67
|
|
|
60
|
-
const
|
|
68
|
+
const OnCancelExample: FC = () => {
|
|
61
69
|
const [value, setValue] = useState("Use the escape key to clear the textarea");
|
|
62
70
|
|
|
63
71
|
const cancel = () => {
|
|
64
72
|
setValue("");
|
|
65
73
|
};
|
|
66
74
|
|
|
67
|
-
return
|
|
68
|
-
<Spacing>
|
|
69
|
-
<Textarea value={value} onChange={(v) => setValue(v)} onCancel={cancel} />
|
|
70
|
-
</Spacing>
|
|
71
|
-
);
|
|
75
|
+
return <Textarea value={value} onChange={setValue} onCancel={cancel} />;
|
|
72
76
|
};
|
|
73
77
|
|
|
74
|
-
const
|
|
78
|
+
const RefExample: FC = () => {
|
|
75
79
|
const ref = useRef<HTMLTextAreaElement>(null);
|
|
76
80
|
return (
|
|
77
81
|
<>
|
|
78
|
-
<Textarea ref={ref} />
|
|
82
|
+
<Textarea ref={ref} placeholder="I will be focused" />
|
|
79
83
|
<Button action={() => ref.current?.focus()} color="primary">
|
|
80
|
-
Focus
|
|
84
|
+
Focus Textarea
|
|
81
85
|
</Button>
|
|
82
86
|
</>
|
|
83
87
|
);
|
|
84
88
|
};
|
|
85
89
|
|
|
86
|
-
const
|
|
90
|
+
const AutoFocusAndRefExample: FC = () => {
|
|
87
91
|
const ref = useRef<HTMLTextAreaElement>(null);
|
|
88
92
|
return (
|
|
89
93
|
<>
|
|
90
|
-
<Textarea ref={ref} autofocus={true} placeholder="
|
|
94
|
+
<Textarea ref={ref} autofocus={true} placeholder="I am focused initially" />
|
|
91
95
|
<Textarea placeholder="Click me to switch focus" />
|
|
92
96
|
<Button action={() => ref.current?.focus()} color="primary">
|
|
93
|
-
Focus First
|
|
97
|
+
Focus First Textarea
|
|
94
98
|
</Button>
|
|
95
99
|
</>
|
|
96
100
|
);
|
|
@@ -103,7 +107,7 @@ type Commit = {
|
|
|
103
107
|
disabled: string;
|
|
104
108
|
};
|
|
105
109
|
|
|
106
|
-
const
|
|
110
|
+
const ReactHookFormExample: FC = () => {
|
|
107
111
|
const {
|
|
108
112
|
register,
|
|
109
113
|
handleSubmit,
|
|
@@ -142,40 +146,82 @@ const ReactHookForm: FC = () => {
|
|
|
142
146
|
<SubmitButton>Submit</SubmitButton>
|
|
143
147
|
</div>
|
|
144
148
|
</form>
|
|
145
|
-
{stored
|
|
149
|
+
{stored && (
|
|
146
150
|
<div className="mt-5">
|
|
147
151
|
<pre>
|
|
148
152
|
<code>{JSON.stringify(stored, null, 2)}</code>
|
|
149
153
|
</pre>
|
|
150
154
|
</div>
|
|
151
|
-
)
|
|
155
|
+
)}
|
|
152
156
|
</>
|
|
153
157
|
);
|
|
154
158
|
};
|
|
155
159
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
160
|
+
// --- Storybook Metadata ---
|
|
161
|
+
|
|
162
|
+
const meta: Meta<typeof Textarea> = {
|
|
163
|
+
title: "Forms/Textarea",
|
|
164
|
+
component: Textarea,
|
|
165
|
+
decorators: [(Story) => <Spacing>{Story()}</Spacing>, (Story) => <MemoryRouter>{Story()}</MemoryRouter>],
|
|
166
|
+
argTypes: {
|
|
167
|
+
onChange: { action: "changed" },
|
|
168
|
+
onSubmit: { action: "submitted" },
|
|
169
|
+
onCancel: { action: "cancelled" },
|
|
170
|
+
},
|
|
171
|
+
tags: ["autodocs"],
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
export default meta;
|
|
175
|
+
|
|
176
|
+
// --- Story Definitions ---
|
|
177
|
+
|
|
178
|
+
type Story = StoryObj<typeof meta>;
|
|
179
|
+
|
|
180
|
+
// Simple stories using `args`
|
|
181
|
+
export const Default: Story = {
|
|
182
|
+
args: {
|
|
183
|
+
label: "Default Textarea",
|
|
184
|
+
placeholder: "Type something...",
|
|
185
|
+
},
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
export const AutoFocus: Story = {
|
|
189
|
+
args: {
|
|
190
|
+
label: "Field with AutoFocus",
|
|
191
|
+
autofocus: true,
|
|
192
|
+
},
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
export const DefaultValue: Story = {
|
|
196
|
+
args: {
|
|
197
|
+
label: "Field with Default Value",
|
|
198
|
+
defaultValue: "I am a text area with so much default value its crazy!",
|
|
199
|
+
},
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
// Complex stories using `render` and helper components
|
|
203
|
+
export const HandlingOnChange: Story = {
|
|
204
|
+
render: () => <OnChangeExample />,
|
|
164
205
|
};
|
|
165
206
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
207
|
+
export const HandlingOnSubmit: Story = {
|
|
208
|
+
render: () => <OnSubmitExample />,
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
export const HandlingOnCancel: Story = {
|
|
212
|
+
render: () => <OnCancelExample />,
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
export const UsingRefs: Story = {
|
|
216
|
+
render: () => <RefExample />,
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
export const WithAutoFocusAndRef: Story = {
|
|
220
|
+
name: "With AutoFocus and Ref",
|
|
221
|
+
render: () => <AutoFocusAndRefExample />,
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
export const WithReactHookForm: Story = {
|
|
225
|
+
name: "With React Hook Form",
|
|
226
|
+
render: () => <ReactHookFormExample />,
|
|
227
|
+
};
|
package/src/forms/Textarea.tsx
CHANGED
|
@@ -129,6 +129,7 @@ const InnerTextarea: FC<FieldProps<BaseProps, HTMLTextAreaElement, string>> = ({
|
|
|
129
129
|
/**
|
|
130
130
|
* @deprecated
|
|
131
131
|
*/
|
|
132
|
+
// @ts-ignore
|
|
132
133
|
const Textarea: FieldType<BaseProps, HTMLTextAreaElement, string> = createFormFieldWrapper(InnerTextarea);
|
|
133
134
|
|
|
134
135
|
export default Textarea;
|
package/src/forms/index.ts
CHANGED
|
@@ -25,10 +25,12 @@ export { default as Checkbox } from "./Checkbox";
|
|
|
25
25
|
export { default as Radio } from "./Radio";
|
|
26
26
|
export { default as FilterInput } from "./FilterInput";
|
|
27
27
|
export { default as InputField } from "./InputField";
|
|
28
|
-
export { default as Select
|
|
28
|
+
export { default as Select } from "./Select";
|
|
29
29
|
export { default as Textarea } from "./Textarea";
|
|
30
30
|
export { default as PasswordConfirmation } from "./PasswordConfirmation";
|
|
31
31
|
export { default as LabelWithHelpIcon } from "./LabelWithHelpIcon";
|
|
32
32
|
export { default as DropDown } from "./DropDown";
|
|
33
33
|
export { default as FileUpload } from "./FileUpload";
|
|
34
34
|
export { default as FileInput } from "./FileInput";
|
|
35
|
+
|
|
36
|
+
export type { SelectItem } from "./Select";
|