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 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 declare type SelectOptionChangeFnType = (arg1: any, arg2: any, arg3: any) => void;
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: any) => void;
86
- onFetch?: (e: any, e2: any, value: string, data: any, incomingData: string | null | undefined) => void;
87
- onLoad?: (e: any, e2: any, value: string | null | undefined) => void;
88
- onSelect?: (data: any) => void;
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?: (e: any) => void;
91
- onFocus?: (e: any) => void;
92
- onKeyPressed?: (arg1: any, arg2: any, arg3: any) => void;
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;