funda-ui 4.7.202 → 4.7.212
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 +205 -0
- package/Select/index.d.ts +20 -9
- package/Select/index.js +408 -345
- package/lib/cjs/Select/index.d.ts +20 -9
- package/lib/cjs/Select/index.js +408 -345
- package/lib/esm/Select/index.tsx +45 -18
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -116,6 +116,211 @@ import 'funda-ui/CascadingSelect/index.css';
|
|
|
116
116
|
|
|
117
117
|
|
|
118
118
|
|
|
119
|
+
## Collecting Data
|
|
120
|
+
|
|
121
|
+
### Basic
|
|
122
|
+
|
|
123
|
+
Use `useState()` to store data.
|
|
124
|
+
|
|
125
|
+
```js
|
|
126
|
+
import React, { useState } from 'react';
|
|
127
|
+
import Input from 'funda-ui/Input';
|
|
128
|
+
import Select, { OptionConfig, MultiSelectValue } from 'funda-ui/Select';
|
|
129
|
+
|
|
130
|
+
// component styles
|
|
131
|
+
import 'funda-ui/Select/index.css';
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
interface Config {
|
|
135
|
+
name: string;
|
|
136
|
+
role: boolean;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
export default () => {
|
|
141
|
+
// Consolidated config state
|
|
142
|
+
const [config, setConfig] = useState<Config>({
|
|
143
|
+
name: '',
|
|
144
|
+
role: '',
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
const updateConfig = (newConfig: Partial<Config>) => {
|
|
148
|
+
setConfig(prev => ({ ...prev, ...newConfig }));
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
const handleSubmit = (e: React.MouseEvent<HTMLButtonElement>) => {
|
|
153
|
+
e.preventDefault();
|
|
154
|
+
alert(`Name: ${config.name}, Role: ${config.role}`);
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
return (
|
|
158
|
+
<form onSubmit={handleSubmit}>
|
|
159
|
+
<div>
|
|
160
|
+
|
|
161
|
+
<Input
|
|
162
|
+
name="name"
|
|
163
|
+
label="Name"
|
|
164
|
+
onChange={(e: React.MouseEvent, onComposition: any, el: any, value: string) => {
|
|
165
|
+
updateConfig({ name: value });
|
|
166
|
+
}}
|
|
167
|
+
/>
|
|
168
|
+
</div>
|
|
169
|
+
|
|
170
|
+
<div>
|
|
171
|
+
|
|
172
|
+
<Select
|
|
173
|
+
label="Role"
|
|
174
|
+
placeholder="Select"
|
|
175
|
+
name="role"
|
|
176
|
+
options={[
|
|
177
|
+
{"label": "Admin","value": "admin","queryString": ""},
|
|
178
|
+
{"label": "User","value": "user","queryString": ""}
|
|
179
|
+
]}
|
|
180
|
+
onChange={(e: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>, e2: HTMLElement, val: OptionConfig | MultiSelectValue): void => {
|
|
181
|
+
updateConfig({ role: (val as OptionConfig).value });
|
|
182
|
+
}}
|
|
183
|
+
/>
|
|
184
|
+
|
|
185
|
+
</div>
|
|
186
|
+
|
|
187
|
+
<button className="btn btn-outline-primary btn-sm mb-2" type="submit">Submit</button>
|
|
188
|
+
</form>
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
### Advanced
|
|
198
|
+
|
|
199
|
+
Using vanilla JS to collect the value of name is faster and easier.
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
```js
|
|
203
|
+
import React, { useRef } from "react";
|
|
204
|
+
import Input from 'funda-ui/Input';
|
|
205
|
+
import Select, { OptionConfig, MultiSelectValue } from 'funda-ui/Select';
|
|
206
|
+
|
|
207
|
+
// component styles
|
|
208
|
+
import 'funda-ui/Select/index.css';
|
|
209
|
+
|
|
210
|
+
// utils
|
|
211
|
+
import { serializeArray } from 'funda-ui/Utils/formdata';
|
|
212
|
+
import { isEmpty } from "funda-ui/Utils/validate";
|
|
213
|
+
|
|
214
|
+
interface FormField {
|
|
215
|
+
name: string;
|
|
216
|
+
value: string;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
interface FormData {
|
|
220
|
+
[key: string]: string;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
type CallbackFunction = (formData: FormData) => void;
|
|
224
|
+
type ErrorCallbackFunction = () => void;
|
|
225
|
+
|
|
226
|
+
function customValidate(
|
|
227
|
+
form: HTMLFormElement | HTMLDivElement | null,
|
|
228
|
+
callback?: CallbackFunction,
|
|
229
|
+
errCallback?: ErrorCallbackFunction
|
|
230
|
+
): void {
|
|
231
|
+
if (form === null) return;
|
|
232
|
+
|
|
233
|
+
const formData: FormData = {};
|
|
234
|
+
const fieldsData: FormField[] = serializeArray(form);
|
|
235
|
+
let fieldsCheck: boolean = true;
|
|
236
|
+
let customFieldsCheck: boolean = true;
|
|
237
|
+
|
|
238
|
+
// Step 1: everything is ok
|
|
239
|
+
//-------------
|
|
240
|
+
// required fields
|
|
241
|
+
const emptyFieldsCheck = fieldsData.every((item: FormField) => {
|
|
242
|
+
if (item.name !== null && item.name !== '') {
|
|
243
|
+
formData[item.name] = item.value;
|
|
244
|
+
|
|
245
|
+
const _field = form.querySelector<HTMLElement>(`[name="${item.name}"]`);
|
|
246
|
+
if (!_field) return true;
|
|
247
|
+
|
|
248
|
+
const fieldRequired = _field.getAttribute('required');
|
|
249
|
+
if (fieldRequired !== null && fieldRequired !== 'false') {
|
|
250
|
+
if (item.value === '' || isEmpty(item.value)) {
|
|
251
|
+
const _label = _field.dataset.requiredTitle;
|
|
252
|
+
alert(`${_label} cannot be empty!`);
|
|
253
|
+
return false;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
errCallback?.();
|
|
259
|
+
|
|
260
|
+
return true;
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
// merged result
|
|
264
|
+
fieldsCheck = [emptyFieldsCheck, customFieldsCheck].every((item: boolean) => {
|
|
265
|
+
return item;
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
// Step 2: everything is ok
|
|
269
|
+
//-------------
|
|
270
|
+
if (fieldsCheck) {
|
|
271
|
+
callback?.(formData);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
export default () => {
|
|
278
|
+
const formRef = useRef<HTMLDivElement>(null);
|
|
279
|
+
|
|
280
|
+
const handleSubmit = (e: React.MouseEvent<HTMLButtonElement>) => {
|
|
281
|
+
e.preventDefault();
|
|
282
|
+
|
|
283
|
+
customValidate(
|
|
284
|
+
formRef.current,
|
|
285
|
+
(formData: any[]) => {
|
|
286
|
+
alert(JSON.stringify(formData));
|
|
287
|
+
},
|
|
288
|
+
() => { }
|
|
289
|
+
);
|
|
290
|
+
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
return (
|
|
294
|
+
<div ref={formRef}>
|
|
295
|
+
<div>
|
|
296
|
+
|
|
297
|
+
<Input
|
|
298
|
+
name="name"
|
|
299
|
+
label="Name"
|
|
300
|
+
/>
|
|
301
|
+
</div>
|
|
302
|
+
|
|
303
|
+
<div>
|
|
304
|
+
|
|
305
|
+
<Select
|
|
306
|
+
label="Role"
|
|
307
|
+
placeholder="Select"
|
|
308
|
+
name="role"
|
|
309
|
+
options={[
|
|
310
|
+
{"label": "Admin","value": "admin","queryString": ""},
|
|
311
|
+
{"label": "User","value": "user","queryString": ""}
|
|
312
|
+
]}
|
|
313
|
+
/>
|
|
314
|
+
|
|
315
|
+
</div>
|
|
316
|
+
|
|
317
|
+
<button className="btn btn-outline-primary btn-sm mb-2" type="button" onClick={handleSubmit}>Submit</button>
|
|
318
|
+
</div>
|
|
319
|
+
);
|
|
320
|
+
|
|
321
|
+
}
|
|
322
|
+
```
|
|
323
|
+
|
|
119
324
|
|
|
120
325
|
## Licensing
|
|
121
326
|
|
package/Select/index.d.ts
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
export
|
|
2
|
+
export interface MultiSelectValue {
|
|
3
|
+
items: {
|
|
4
|
+
label: string;
|
|
5
|
+
value: string;
|
|
6
|
+
}[];
|
|
7
|
+
labels: string[];
|
|
8
|
+
values: string[];
|
|
9
|
+
labelsOfString: string;
|
|
10
|
+
valuesOfString: string;
|
|
11
|
+
}
|
|
12
|
+
export declare type SelectOptionChangeFnType = (event: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>, element: HTMLElement, value: OptionConfig | MultiSelectValue) => void | Promise<void>;
|
|
3
13
|
export interface MultiSelectControlValConfig {
|
|
4
14
|
values: string[];
|
|
5
15
|
labels: string[];
|
|
@@ -12,7 +22,8 @@ export interface OptionConfig {
|
|
|
12
22
|
listItemLabel?: string;
|
|
13
23
|
value: string | number | boolean;
|
|
14
24
|
queryString: string | number;
|
|
15
|
-
callback?: () => void
|
|
25
|
+
callback?: () => void | Promise<void>;
|
|
26
|
+
[key: string]: string | number | boolean | any[] | (() => void | Promise<void>) | undefined;
|
|
16
27
|
}
|
|
17
28
|
export interface MultiSelectConfig {
|
|
18
29
|
valid: boolean;
|
|
@@ -82,14 +93,14 @@ export declare type SelectProps = {
|
|
|
82
93
|
fetchFuncAsync?: any;
|
|
83
94
|
fetchFuncMethod?: string;
|
|
84
95
|
fetchFuncMethodParams?: any[];
|
|
85
|
-
fetchCallback?: (data:
|
|
86
|
-
onFetch?: (
|
|
87
|
-
onLoad?: (
|
|
88
|
-
onSelect?: (data:
|
|
96
|
+
fetchCallback?: (data: OptionConfig[]) => OptionConfig[];
|
|
97
|
+
onFetch?: (event: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>, element: HTMLElement, value: string, data: OptionConfig[], incomingData: string | null | undefined) => void;
|
|
98
|
+
onLoad?: (event: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>, element: HTMLElement, value: string | null | undefined) => void;
|
|
99
|
+
onSelect?: (data: OptionConfig) => void | Promise<void>;
|
|
89
100
|
onChange?: SelectOptionChangeFnType | null;
|
|
90
|
-
onBlur?: (
|
|
91
|
-
onFocus?: (
|
|
92
|
-
onKeyPressed?: (
|
|
101
|
+
onBlur?: (event: React.FocusEvent<HTMLElement>) => void;
|
|
102
|
+
onFocus?: (event: React.FocusEvent<HTMLElement>) => void;
|
|
103
|
+
onKeyPressed?: (event: React.KeyboardEvent<HTMLElement>, element: HTMLElement, value: string) => void;
|
|
93
104
|
};
|
|
94
105
|
declare const Select: React.ForwardRefExoticComponent<SelectProps & React.RefAttributes<unknown>>;
|
|
95
106
|
export default Select;
|