funda-ui 4.7.202 → 4.7.222

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/Date/index.js CHANGED
@@ -5424,9 +5424,14 @@ var src_Date = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_reac
5424
5424
 
5425
5425
  e.target.select();
5426
5426
  resetDefauleValueExist();
5427
- var _date = "".concat(splitVals[0], "-").concat(splitVals[1], "-").concat(splitVals[2]);
5428
- var _full = "".concat(_date, " ").concat(splitVals[3], ":").concat(splitVals[4], ":").concat(splitVals[5]);
5429
- _onChange === null || _onChange === void 0 ? void 0 : _onChange(inputRef.current, valueResConverter(_full), (0,cjs_date.isValidDate)(_full), getAllSplittingInputs());
5427
+
5428
+ // If there is no valid default value in the input field,
5429
+ // onChange should be triggered only after the resetDefauleValueExist() function is processed
5430
+ if (!dateDefaultValueExist) {
5431
+ var _date = "".concat(splitVals[0], "-").concat(splitVals[1], "-").concat(splitVals[2]);
5432
+ var _full = "".concat(_date, " ").concat(splitVals[3], ":").concat(splitVals[4], ":").concat(splitVals[5]);
5433
+ _onChange === null || _onChange === void 0 ? void 0 : _onChange(inputRef.current, valueResConverter(_full), (0,cjs_date.isValidDate)(_full), getAllSplittingInputs());
5434
+ }
5430
5435
  }
5431
5436
  function handleKeyPressed(_x2) {
5432
5437
  return _handleKeyPressed.apply(this, arguments);
@@ -5461,17 +5466,19 @@ var src_Date = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_reac
5461
5466
  }
5462
5467
  function _handleKeyPressedForSplitInputs() {
5463
5468
  _handleKeyPressedForSplitInputs = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(event) {
5464
- var key, btnMark, move;
5469
+ var key, btnMark, isLeftArrow, isRightArrow, move;
5465
5470
  return _regeneratorRuntime().wrap(function _callee2$(_context2) {
5466
5471
  while (1) switch (_context2.prev = _context2.next) {
5467
5472
  case 0:
5468
5473
  key = event.code;
5469
- btnMark = event.target.dataset.mark;
5470
- move = function move(key) {
5474
+ btnMark = event.target.dataset.mark; // Check for both regular arrow keys and numpad arrow keys
5475
+ isLeftArrow = key === 'ArrowLeft' || key === 'Numpad4';
5476
+ isRightArrow = key === 'ArrowRight' || key === 'Numpad6';
5477
+ move = function move(direction) {
5471
5478
  var currentIndex = splitInputsIds.findIndex(function (s) {
5472
5479
  return s === btnMark;
5473
5480
  });
5474
- var nextIndex = key === 'ArrowLeft' ? currentIndex === splitInputsIds.length - 1 ? 0 : currentIndex - 1 : currentIndex === splitInputsIds.length - 1 ? 0 : currentIndex + 1;
5481
+ var nextIndex = direction === 'left' ? currentIndex === 0 ? splitInputsIds.length - 1 : currentIndex - 1 : currentIndex === splitInputsIds.length - 1 ? 0 : currentIndex + 1;
5475
5482
  var nextOption = splitInputsIds.at(nextIndex);
5476
5483
  if (nextOption) {
5477
5484
  setTimeout(function () {
@@ -5481,13 +5488,13 @@ var src_Date = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_reac
5481
5488
  setFocusableSplitInputId(nextOption);
5482
5489
  }
5483
5490
  };
5484
- if (key === 'ArrowLeft') {
5485
- move('ArrowLeft');
5491
+ if (isLeftArrow) {
5492
+ move('left');
5486
5493
  }
5487
- if (key === 'ArrowRight') {
5488
- move('ArrowRight');
5494
+ if (isRightArrow) {
5495
+ move('right');
5489
5496
  }
5490
- case 5:
5497
+ case 7:
5491
5498
  case "end":
5492
5499
  return _context2.stop();
5493
5500
  }
@@ -5500,6 +5507,7 @@ var src_Date = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_reac
5500
5507
  _onChange === null || _onChange === void 0 ? void 0 : _onChange(inputRef.current, '', false, getAllSplittingInputs());
5501
5508
  }
5502
5509
  function resetDefauleValueExist() {
5510
+ // Does the current input box have a "valid default value"?
5503
5511
  if (!dateDefaultValueExist) setDateDefaultValueExist(true);
5504
5512
  }
5505
5513
  function resetPopupBlurStatus() {
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;