@geoinsight/react-components 0.6.6 → 0.6.8

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.
@@ -334,6 +334,18 @@ transition: var(--transition-bg-cubic-bezier), var(--transition-box-shadow-cubic
334
334
  width: 100%;
335
335
  }
336
336
 
337
+ .input__header {
338
+ align-items: center;
339
+ display: flex;
340
+ justify-content: space-between;
341
+ width: 100%;
342
+ }
343
+
344
+ .input__header--error {
345
+ font-size: 12px;
346
+ color: var(--color-danger);
347
+ }
348
+
337
349
  .input--icon {
338
350
  padding: var(--spacing-16) var(--spacing-40);
339
351
  }
@@ -368,70 +380,96 @@ transition: var(--transition-bg-cubic-bezier), var(--transition-box-shadow-cubic
368
380
  }
369
381
 
370
382
  .input--error {
371
- border: 3px solid var(--color-danger);
383
+ border: 3px solid var(--color-danger) !important;
372
384
  }
373
385
 
374
386
  .input--error:focus {
375
387
  border: 3px solid var(--color-danger);
376
388
  outline: none;
377
389
  }
378
-
379
- .error {
380
- font-size: 12px;
381
- color: var(--color-danger);
390
+ .textarea {
391
+ margin-bottom: var(--spacing-8);
392
+ position: relative;
393
+ width: 100%;
382
394
  }
383
395
 
384
- .loading {
396
+ .textarea__header {
385
397
  align-items: center;
386
398
  display: flex;
387
- flex-direction: column;
388
- height: 100%;
389
- justify-content: center;;
390
- position: relative;
399
+ justify-content: space-between;
400
+ width: 100%;
391
401
  }
392
402
 
393
- .modal-overlay {
394
- background: rgba(0, 0, 0, 0.3);
395
- bottom: 0;
396
- left: 0;
397
- position: fixed;
398
- right: 0;
399
- top: 0;
403
+ .textarea__header--error {
404
+ font-size: 12px;
405
+ color: var(--color-danger);
406
+
400
407
  }
401
408
 
402
- .modal {
403
- background: white;
409
+ .textarea__input {
410
+ background-color: var(--color-white);
411
+ box-sizing: border-box;
404
412
  border-radius: var(--spacing-8);
405
- border: 1px solid var(--color-neutral-600);
413
+ border: 2px solid var(--color-primary);
414
+ cursor: text;
406
415
  color: var(--color-black);
407
- left: 50%;
408
- padding: var(--spacing-4) var(--spacing-4);
409
- position: absolute;
410
- right: var(--spacing-16);
411
- top: 50%;
412
- transform: translate(-50%, -50%);
413
- z-index: 5;
416
+ outline: none;
417
+ padding: var(--spacing-8) var(--spacing-16);
418
+ resize: vertical;
419
+ width: 100%;
414
420
  }
415
421
 
416
- .modal__close {
422
+ .textarea__input--error {
423
+ border: 3px solid var(--color-danger);
424
+ }
425
+
426
+ .textarea__input:enabled:hover {
427
+ box-shadow: 4px 6px 4px 0 var(--color-neutral-400);
428
+ transition: var(--transition-box-shadow-cubic-bezier);
429
+ }
430
+
431
+ .textarea__input:disabled {
432
+ opacity: 0.5;
433
+ }
434
+
435
+ .textarea__button {
436
+ background: var(--color-primary);
437
+ border: 2px solid var(--color-secondary);
438
+ box-shadow: 2px 4px 2px 1px rgba(0, 0, 0, 0.25);
439
+ border-radius: 0px 0px var(--spacing-8) var(--spacing-8);
440
+ bottom: 0;
441
+ cursor: pointer;
442
+ left: 0;
443
+ padding-bottom: -20px;
417
444
  position: absolute;
418
- right: calc(var(--spacing-16) * -1);
419
- top: calc(var(--spacing-16) * -1);
420
- z-index: 5;
445
+ width: 100%;
421
446
  }
422
447
 
423
- .modal__content {
424
- border: 1px solid var(--color-neutral-100);
425
- border-radius: var(--spacing-8);
426
- display: flex;
427
- flex-direction: column;
428
- gap: var(--spacing-16);
429
- padding: 0 var(--spacing-16);
448
+ .textarea__button--error {
449
+ background: var(--color-danger) !important;
450
+ border: 3px solid var(--color-danger);
430
451
  }
431
452
 
432
- .modal__footer {
433
- padding-bottom: var(--spacing-16);
453
+ .textarea__button > svg {
454
+ color: var(--color-neutral-100);
455
+ }
456
+
457
+ .textarea__button:disabled {
458
+ cursor: unset;
459
+ opacity: 0.5;
460
+ pointer-events: none;
434
461
  }
462
+
463
+ .textarea__button:enabled:hover {
464
+ background: var(--color-secondary);
465
+ color: var(--color-neutral-100);
466
+ }
467
+
468
+ .textarea__button--show {
469
+ background: var(--color-primary-700);
470
+ color: var(--color-neutral-100);
471
+ }
472
+
435
473
  .select-group {
436
474
  display: flex;
437
475
  flex-direction: column;
@@ -508,69 +546,54 @@ transition: var(--transition-bg-cubic-bezier), var(--transition-box-shadow-cubic
508
546
  outline: none;
509
547
  }
510
548
 
511
- .error {
512
- font-size: 12px;
513
- color: var(--color-danger);
514
- }
515
-
516
- .textarea {
517
- margin-bottom: var(--spacing-8);
549
+ .loading {
550
+ align-items: center;
551
+ display: flex;
552
+ flex-direction: column;
553
+ height: 100%;
554
+ justify-content: center;;
518
555
  position: relative;
519
- width: 100%;
520
556
  }
521
557
 
522
- .textarea__input {
523
- background-color: var(--color-white);
524
- box-sizing: border-box;
525
- border-radius: var(--spacing-8);
526
- border: 2px solid var(--color-primary);
527
- cursor: text;
528
- color: var(--color-black);
529
- outline: none;
530
- padding: var(--spacing-8) var(--spacing-16);
531
- resize: vertical;
532
- width: 100%;
533
- }
534
-
535
- .textarea__input:enabled:hover {
536
- box-shadow: 4px 6px 4px 0 var(--color-neutral-400);
537
- transition: var(--transition-box-shadow-cubic-bezier);
538
-
539
- }
540
-
541
- .textarea__input:disabled {
542
- opacity: 0.5;
543
- }
544
-
545
- .textarea__button {
546
- background: var(--color-primary);
547
- border: 2px solid var(--color-secondary);
548
- box-shadow: 2px 4px 2px 1px rgba(0, 0, 0, 0.25);
549
- border-radius: 0px 0px var(--spacing-8) var(--spacing-8);
558
+ .modal-overlay {
559
+ background: rgba(0, 0, 0, 0.3);
550
560
  bottom: 0;
551
- cursor: pointer;
552
561
  left: 0;
553
- padding-bottom: -20px;
554
- position: absolute;
555
- width: 100%;
562
+ position: fixed;
563
+ right: 0;
564
+ top: 0;
556
565
  }
557
566
 
558
- .textarea__button > svg {
559
- color: var(--color-neutral-100);
567
+ .modal {
568
+ background: white;
569
+ border-radius: var(--spacing-8);
570
+ border: 1px solid var(--color-neutral-600);
571
+ color: var(--color-black);
572
+ left: 50%;
573
+ padding: var(--spacing-4) var(--spacing-4);
574
+ position: absolute;
575
+ right: var(--spacing-16);
576
+ top: 50%;
577
+ transform: translate(-50%, -50%);
578
+ z-index: 5;
560
579
  }
561
580
 
562
- .textarea__button:disabled {
563
- cursor: unset;
564
- opacity: 0.5;
565
- pointer-events: none;
581
+ .modal__close {
582
+ position: absolute;
583
+ right: calc(var(--spacing-16) * -1);
584
+ top: calc(var(--spacing-16) * -1);
585
+ z-index: 5;
566
586
  }
567
587
 
568
- .textarea__button:enabled:hover {
569
- background: var(--color-secondary);
570
- color: var(--color-neutral-100);
588
+ .modal__content {
589
+ border: 1px solid var(--color-neutral-100);
590
+ border-radius: var(--spacing-8);
591
+ display: flex;
592
+ flex-direction: column;
593
+ gap: var(--spacing-16);
594
+ padding: 0 var(--spacing-16);
571
595
  }
572
596
 
573
- .textarea__button--show {
574
- background: var(--color-primary-700);
575
- color: var(--color-neutral-100);
576
- }
597
+ .modal__footer {
598
+ padding-bottom: var(--spacing-16);
599
+ }
package/dist/cjs/index.js CHANGED
@@ -6,8 +6,8 @@ var clsx = require('clsx');
6
6
  var tfi = require('react-icons/tfi');
7
7
  var bs = require('react-icons/bs');
8
8
  var reactHookForm = require('react-hook-form');
9
- var io5 = require('react-icons/io5');
10
9
  var tb = require('react-icons/tb');
10
+ var io5 = require('react-icons/io5');
11
11
 
12
12
  let uniqueId = (function () {
13
13
  let num = 0;
@@ -190,56 +190,82 @@ const AccordionContent = function AccordionContent({ children, label, toggle, })
190
190
  function Form({ children, onSubmit, submitButton = {
191
191
  label: "Submit",
192
192
  }, ...rest }) {
193
- const { handleSubmit, setValue, control, formState: { errors, isValid }, } = reactHookForm.useForm();
193
+ const methods = reactHookForm.useForm();
194
+ const { formState: { isValid }, } = methods;
194
195
  const [result, setResult] = react.useState({
195
196
  message: "",
196
197
  isSuccess: false,
197
198
  });
198
- return (jsxRuntime.jsxs("form", { className: "form", onSubmit: handleSubmit(async (data) => await onSubmit(data, setResult)), ...rest, children: [react.Children.map(children, (child) => {
199
- const { props: { name, error, isRequired, ...rest }, } = child;
200
- return child.props.name ? (jsxRuntime.jsx(reactHookForm.Controller, { name: name, control: control, rules: {
201
- ...(isRequired
202
- ? {
203
- required: error?.message || "Field is required",
204
- }
205
- : {}),
206
- }, render: ({ field: { onBlur, ...restField } }) => {
207
- return react.cloneElement(child, {
208
- error: {
209
- is: Object.keys(errors).length > 0 && !!errors[name],
210
- message: errors &&
211
- Object.keys(errors).length > 0 &&
212
- errors[name]?.message,
213
- },
214
- setFormSelected: setValue,
215
- onFormBlur: onBlur,
216
- ...restField,
217
- ...rest,
218
- });
219
- } })) : child;
220
- }), result.message && (jsxRuntime.jsxs("div", { className: "form__message", children: [result.isSuccess ? (jsxRuntime.jsx(bs.BsCheckCircleFill, { color: "var(--color-success)", size: 48 })) : (jsxRuntime.jsx(bs.BsXCircleFill, { color: "var(--color-danger)", size: 48 })), result.message] })), jsxRuntime.jsx(Button, { type: "submit", disabled: !isValid, children: submitButton.label })] }));
199
+ return (jsxRuntime.jsx(reactHookForm.FormProvider, { ...methods, children: jsxRuntime.jsxs("form", { className: "form", onSubmit: methods.handleSubmit((data) => onSubmit(data, setResult)), ...rest, children: [children, result.message && (jsxRuntime.jsxs("div", { className: "form__message", children: [result.isSuccess ? (jsxRuntime.jsx(bs.BsCheckCircleFill, { color: "var(--color-success)", size: 48 })) : (jsxRuntime.jsx(bs.BsXCircleFill, { color: "var(--color-danger)", size: 48 })), result.message] })), jsxRuntime.jsx(Button, { type: "submit", disabled: !isValid, children: submitButton.label })] }) }));
221
200
  }
222
201
 
223
202
  function Input({ inputClassName = "", classNameGroup = "", error = {
224
203
  is: false,
225
204
  message: "",
226
205
  }, inputRef, styleGroup, placeholder = "Insert value", label, labelClass, icon, ...rest }) {
227
- return (jsxRuntime.jsxs("div", { className: clsx("input-group", classNameGroup), style: styleGroup, children: [label && jsxRuntime.jsx("label", { className: labelClass, children: label }), jsxRuntime.jsxs("div", { className: "input-subgroup", children: [icon?.element && icon.position === "left" && (jsxRuntime.jsx("div", { className: clsx("input__icon", "input__icon--left", icon.className), children: icon.element })), jsxRuntime.jsx("input", { ref: inputRef, className: clsx("input", error.is ? "input--error" : "", icon?.position === "left" && "input--icon", inputClassName), placeholder: placeholder, ...rest }), icon?.element && icon.position !== "left" && (jsxRuntime.jsx("div", { className: clsx("input__icon", "input__icon--right",
206
+ console.log(error);
207
+ return (jsxRuntime.jsxs("div", { className: clsx("input-group", classNameGroup), style: styleGroup, children: [jsxRuntime.jsxs("div", { className: "input__header", children: [label && jsxRuntime.jsx("label", { className: labelClass, children: label }), error && error.is && (jsxRuntime.jsx("span", { className: "input__header--error", children: error.message }))] }), jsxRuntime.jsxs("div", { className: "input-subgroup", children: [icon?.element && icon.position === "left" && (jsxRuntime.jsx("div", { className: clsx("input__icon", "input__icon--left", icon.className), children: icon.element })), jsxRuntime.jsx("input", { ref: inputRef, className: clsx("input", error.is ? "input--error" : "", icon?.position === "left" && "input--icon", inputClassName), placeholder: placeholder, ...rest }), icon?.element && icon.position !== "left" && (jsxRuntime.jsx("div", { className: clsx("input__icon", "input__icon--right",
228
208
  // `input__icon--${icon.position || "right"}`,
229
- icon.className), children: icon.element }))] }), error && error.is && (jsxRuntime.jsx("span", { className: "error", children: error.message }))] }));
209
+ icon.className), children: icon.element }))] })] }));
230
210
  }
231
211
 
232
- function Loading({ img, children }) {
233
- return (jsxRuntime.jsxs("div", { className: "loading", children: [jsxRuntime.jsx("img", { src: img ? img : "../../stories/assets/loading.gif" }), children] }));
212
+ function FormInput({ name, isRequired, error, ...rest }) {
213
+ const { control } = reactHookForm.useFormContext();
214
+ return (jsxRuntime.jsx(reactHookForm.Controller, { name: name, control: control, rules: {
215
+ ...(isRequired
216
+ ? {
217
+ required: error?.message || "Field is required",
218
+ }
219
+ : {}),
220
+ }, render: ({ field, fieldState: { error } }) => {
221
+ return (jsxRuntime.jsx(Input, { isRequired: true, error: {
222
+ is: !!error,
223
+ message: error?.message,
224
+ }, ...field, ...rest }));
225
+ } }));
234
226
  }
235
227
 
236
- function Modal({ modalref, children, title, subtitle, footer, hasCloseButton = true, handleClose, }) {
237
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: "modal-overlay" }), jsxRuntime.jsxs("div", { ref: modalref, className: "modal", children: [hasCloseButton && (jsxRuntime.jsx(Button, { mode: "secondary", className: "modal__close", size: "small", onClick: handleClose, children: jsxRuntime.jsx(io5.IoClose, {}) })), jsxRuntime.jsxs("div", { className: "modal__content", children: [title && (jsxRuntime.jsxs("div", { className: "modal__header", children: [jsxRuntime.jsx("h3", { children: title }), jsxRuntime.jsx("h6", { children: subtitle })] })), jsxRuntime.jsx("div", { className: "modal__children", children: children }), footer && jsxRuntime.jsx("div", { className: "modal__footer", children: footer })] })] })] }));
228
+ function TextArea({ className = "", disabled = true, hasToggleButton = true, hideHeight = "5rem", placeholder = "Insert value", showHeight = "10rem", style = {}, textareaClassName = "", label, labelClass, error = {
229
+ is: false,
230
+ message: "",
231
+ }, ...rest }) {
232
+ const ref = react.useRef();
233
+ const [isShow, setIsShow] = react.useState(false);
234
+ const handleClickToggle = () => {
235
+ if (ref && ref.current) {
236
+ if (isShow) {
237
+ ref.current.style.height = hideHeight;
238
+ }
239
+ else {
240
+ ref.current.style.height = showHeight; //(48 + ref.current.scrollHeight) + 'px';
241
+ }
242
+ setIsShow((prev) => !prev);
243
+ }
244
+ };
245
+ return (jsxRuntime.jsxs("div", { className: clsx("textarea", className), style: style, children: [jsxRuntime.jsxs("div", { className: "textarea__header", children: [label && jsxRuntime.jsx("label", { className: labelClass, children: label }), error && error.is && (jsxRuntime.jsx("span", { className: "textarea__header--error", children: error.message }))] }), jsxRuntime.jsx("textarea", { ref: ref, className: clsx("textarea__input", error.is && "textarea__input--error", textareaClassName), style: {
246
+ height: hasToggleButton ? hideHeight : showHeight,
247
+ }, placeholder: placeholder, disabled: disabled, ...rest }), hasToggleButton && (jsxRuntime.jsx("button", { type: "button", className: clsx("textarea__button", isShow && "textarea__button--show", error.is && "textarea__button--error"), onClick: handleClickToggle, disabled: disabled, children: jsxRuntime.jsx(tb.TbArrowsDiagonal2, { size: "1.5rem" }) }))] }));
248
+ }
249
+
250
+ function FormTextArea({ name, isRequired, error, ...rest }) {
251
+ const { control } = reactHookForm.useFormContext();
252
+ return (jsxRuntime.jsx(reactHookForm.Controller, { name: name, control: control, rules: {
253
+ ...(isRequired
254
+ ? {
255
+ required: error?.message || "Field is required",
256
+ }
257
+ : {}),
258
+ }, render: ({ field, fieldState: { error } }) => {
259
+ return (jsxRuntime.jsx(TextArea, { isRequired: true, error: {
260
+ is: !!error,
261
+ message: error?.message,
262
+ }, ...field, ...rest }));
263
+ } }));
238
264
  }
239
265
 
240
266
  function Select({ inputClassName = "", classNameGroup = "", options, styleGroup, defaultValue,
241
267
  // inputProps,
242
- setFormSelected, onFormBlur, handleSelect, ...rest }) {
268
+ setFormSelected, clearError, onFormBlur, handleSelect, ...rest }) {
243
269
  const [isOpen, setIsOpen] = react.useState(false);
244
270
  const [value, setValue] = react.useState(defaultValue || (options && options[0]));
245
271
  const [filteredOptions, setFilteredOptions] = react.useState(options);
@@ -261,7 +287,6 @@ setFormSelected, onFormBlur, handleSelect, ...rest }) {
261
287
  };
262
288
  const handleValueChange = (e) => {
263
289
  const { value } = e.target;
264
- console.log(value);
265
290
  setValue(value);
266
291
  // for autocomplete
267
292
  // const { value } = e.target;
@@ -271,6 +296,9 @@ setFormSelected, onFormBlur, handleSelect, ...rest }) {
271
296
  const { name: value } = e.target;
272
297
  if (setFormSelected) {
273
298
  setFormSelected(name, value);
299
+ if (clearError) {
300
+ clearError(name);
301
+ }
274
302
  }
275
303
  else {
276
304
  setValue(value);
@@ -298,23 +326,28 @@ setFormSelected, onFormBlur, handleSelect, ...rest }) {
298
326
  }, onFocus: handleOpen, onBlur: handleInputClose, onChange: handleValueChange, autoComplete: "off", ...rest }), isOpen && (jsxRuntime.jsx("div", { className: "select__box", children: filteredOptions.map((option, index) => (jsxRuntime.jsx(Button, { type: "button", mode: "secondary", className: "select__option", name: option, onMouseDown: handleSelectChange, children: option }, `index-${index}`))) }))] }));
299
327
  }
300
328
 
301
- function TextArea({ className = "", disabled = true, hasToggleButton = true, hideHeight = "5rem", placeholder = "Insert value", showHeight = "10rem", style = {}, textareaClassName = "", label, labelClass, ...rest }) {
302
- const ref = react.useRef();
303
- const [isShow, setIsShow] = react.useState(false);
304
- const handleClickToggle = () => {
305
- if (ref && ref.current) {
306
- if (isShow) {
307
- ref.current.style.height = hideHeight;
308
- }
309
- else {
310
- ref.current.style.height = showHeight; //(48 + ref.current.scrollHeight) + 'px';
311
- }
312
- setIsShow((prev) => !prev);
313
- }
314
- };
315
- return (jsxRuntime.jsxs("div", { className: clsx("textarea", className), style: style, children: [label && jsxRuntime.jsx("label", { className: labelClass, children: label }), jsxRuntime.jsx("textarea", { ref: ref, className: clsx("textarea__input", textareaClassName), style: {
316
- height: hasToggleButton ? hideHeight : showHeight,
317
- }, placeholder: placeholder, disabled: disabled, ...rest }), hasToggleButton && (jsxRuntime.jsx("button", { type: "button", className: clsx("textarea__button", isShow && "textarea__button--show"), onClick: handleClickToggle, disabled: disabled, children: jsxRuntime.jsx(tb.TbArrowsDiagonal2, { size: "1.5rem" }) }))] }));
329
+ function FormSelect({ name, isRequired, error, ...rest }) {
330
+ const { control, setValue, clearErrors } = reactHookForm.useFormContext();
331
+ return (jsxRuntime.jsx(reactHookForm.Controller, { name: name, control: control, rules: {
332
+ ...(isRequired
333
+ ? {
334
+ required: error?.message || "Field is required",
335
+ }
336
+ : {}),
337
+ }, render: ({ field: { onBlur, ...restField }, fieldState: { error } }) => {
338
+ return (jsxRuntime.jsx(Select, { isRequired: true, error: {
339
+ is: !!error,
340
+ message: error?.message,
341
+ }, setFormSelected: setValue, clearError: clearErrors, onFormBlur: onBlur, ...restField, ...rest }));
342
+ } }));
343
+ }
344
+
345
+ function Loading({ img, children }) {
346
+ return (jsxRuntime.jsxs("div", { className: "loading", children: [jsxRuntime.jsx("img", { src: img ? img : "../../stories/assets/loading.gif" }), children] }));
347
+ }
348
+
349
+ function Modal({ modalref, children, title, subtitle, footer, hasCloseButton = true, handleClose, }) {
350
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: "modal-overlay" }), jsxRuntime.jsxs("div", { ref: modalref, className: "modal", children: [hasCloseButton && (jsxRuntime.jsx(Button, { mode: "secondary", className: "modal__close", size: "small", onClick: handleClose, children: jsxRuntime.jsx(io5.IoClose, {}) })), jsxRuntime.jsxs("div", { className: "modal__content", children: [title && (jsxRuntime.jsxs("div", { className: "modal__header", children: [jsxRuntime.jsx("h3", { children: title }), jsxRuntime.jsx("h6", { children: subtitle })] })), jsxRuntime.jsx("div", { className: "modal__children", children: children }), footer && jsxRuntime.jsx("div", { className: "modal__footer", children: footer })] })] })] }));
318
351
  }
319
352
 
320
353
  const LoadingContext = react.createContext(undefined);
@@ -444,6 +477,9 @@ exports.AccordionContent = AccordionContent;
444
477
  exports.AccordionItem = AccordionItem;
445
478
  exports.Button = Button;
446
479
  exports.Form = Form;
480
+ exports.FormInput = FormInput;
481
+ exports.FormSelect = FormSelect;
482
+ exports.FormTextArea = FormTextArea;
447
483
  exports.Input = Input;
448
484
  exports.Loading = Loading;
449
485
  exports.LoadingContext = LoadingContext;
@@ -334,6 +334,18 @@ transition: var(--transition-bg-cubic-bezier), var(--transition-box-shadow-cubic
334
334
  width: 100%;
335
335
  }
336
336
 
337
+ .input__header {
338
+ align-items: center;
339
+ display: flex;
340
+ justify-content: space-between;
341
+ width: 100%;
342
+ }
343
+
344
+ .input__header--error {
345
+ font-size: 12px;
346
+ color: var(--color-danger);
347
+ }
348
+
337
349
  .input--icon {
338
350
  padding: var(--spacing-16) var(--spacing-40);
339
351
  }
@@ -368,70 +380,96 @@ transition: var(--transition-bg-cubic-bezier), var(--transition-box-shadow-cubic
368
380
  }
369
381
 
370
382
  .input--error {
371
- border: 3px solid var(--color-danger);
383
+ border: 3px solid var(--color-danger) !important;
372
384
  }
373
385
 
374
386
  .input--error:focus {
375
387
  border: 3px solid var(--color-danger);
376
388
  outline: none;
377
389
  }
378
-
379
- .error {
380
- font-size: 12px;
381
- color: var(--color-danger);
390
+ .textarea {
391
+ margin-bottom: var(--spacing-8);
392
+ position: relative;
393
+ width: 100%;
382
394
  }
383
395
 
384
- .loading {
396
+ .textarea__header {
385
397
  align-items: center;
386
398
  display: flex;
387
- flex-direction: column;
388
- height: 100%;
389
- justify-content: center;;
390
- position: relative;
399
+ justify-content: space-between;
400
+ width: 100%;
391
401
  }
392
402
 
393
- .modal-overlay {
394
- background: rgba(0, 0, 0, 0.3);
395
- bottom: 0;
396
- left: 0;
397
- position: fixed;
398
- right: 0;
399
- top: 0;
403
+ .textarea__header--error {
404
+ font-size: 12px;
405
+ color: var(--color-danger);
406
+
400
407
  }
401
408
 
402
- .modal {
403
- background: white;
409
+ .textarea__input {
410
+ background-color: var(--color-white);
411
+ box-sizing: border-box;
404
412
  border-radius: var(--spacing-8);
405
- border: 1px solid var(--color-neutral-600);
413
+ border: 2px solid var(--color-primary);
414
+ cursor: text;
406
415
  color: var(--color-black);
407
- left: 50%;
408
- padding: var(--spacing-4) var(--spacing-4);
409
- position: absolute;
410
- right: var(--spacing-16);
411
- top: 50%;
412
- transform: translate(-50%, -50%);
413
- z-index: 5;
416
+ outline: none;
417
+ padding: var(--spacing-8) var(--spacing-16);
418
+ resize: vertical;
419
+ width: 100%;
414
420
  }
415
421
 
416
- .modal__close {
422
+ .textarea__input--error {
423
+ border: 3px solid var(--color-danger);
424
+ }
425
+
426
+ .textarea__input:enabled:hover {
427
+ box-shadow: 4px 6px 4px 0 var(--color-neutral-400);
428
+ transition: var(--transition-box-shadow-cubic-bezier);
429
+ }
430
+
431
+ .textarea__input:disabled {
432
+ opacity: 0.5;
433
+ }
434
+
435
+ .textarea__button {
436
+ background: var(--color-primary);
437
+ border: 2px solid var(--color-secondary);
438
+ box-shadow: 2px 4px 2px 1px rgba(0, 0, 0, 0.25);
439
+ border-radius: 0px 0px var(--spacing-8) var(--spacing-8);
440
+ bottom: 0;
441
+ cursor: pointer;
442
+ left: 0;
443
+ padding-bottom: -20px;
417
444
  position: absolute;
418
- right: calc(var(--spacing-16) * -1);
419
- top: calc(var(--spacing-16) * -1);
420
- z-index: 5;
445
+ width: 100%;
421
446
  }
422
447
 
423
- .modal__content {
424
- border: 1px solid var(--color-neutral-100);
425
- border-radius: var(--spacing-8);
426
- display: flex;
427
- flex-direction: column;
428
- gap: var(--spacing-16);
429
- padding: 0 var(--spacing-16);
448
+ .textarea__button--error {
449
+ background: var(--color-danger) !important;
450
+ border: 3px solid var(--color-danger);
430
451
  }
431
452
 
432
- .modal__footer {
433
- padding-bottom: var(--spacing-16);
453
+ .textarea__button > svg {
454
+ color: var(--color-neutral-100);
455
+ }
456
+
457
+ .textarea__button:disabled {
458
+ cursor: unset;
459
+ opacity: 0.5;
460
+ pointer-events: none;
434
461
  }
462
+
463
+ .textarea__button:enabled:hover {
464
+ background: var(--color-secondary);
465
+ color: var(--color-neutral-100);
466
+ }
467
+
468
+ .textarea__button--show {
469
+ background: var(--color-primary-700);
470
+ color: var(--color-neutral-100);
471
+ }
472
+
435
473
  .select-group {
436
474
  display: flex;
437
475
  flex-direction: column;
@@ -508,69 +546,54 @@ transition: var(--transition-bg-cubic-bezier), var(--transition-box-shadow-cubic
508
546
  outline: none;
509
547
  }
510
548
 
511
- .error {
512
- font-size: 12px;
513
- color: var(--color-danger);
514
- }
515
-
516
- .textarea {
517
- margin-bottom: var(--spacing-8);
549
+ .loading {
550
+ align-items: center;
551
+ display: flex;
552
+ flex-direction: column;
553
+ height: 100%;
554
+ justify-content: center;;
518
555
  position: relative;
519
- width: 100%;
520
556
  }
521
557
 
522
- .textarea__input {
523
- background-color: var(--color-white);
524
- box-sizing: border-box;
525
- border-radius: var(--spacing-8);
526
- border: 2px solid var(--color-primary);
527
- cursor: text;
528
- color: var(--color-black);
529
- outline: none;
530
- padding: var(--spacing-8) var(--spacing-16);
531
- resize: vertical;
532
- width: 100%;
533
- }
534
-
535
- .textarea__input:enabled:hover {
536
- box-shadow: 4px 6px 4px 0 var(--color-neutral-400);
537
- transition: var(--transition-box-shadow-cubic-bezier);
538
-
539
- }
540
-
541
- .textarea__input:disabled {
542
- opacity: 0.5;
543
- }
544
-
545
- .textarea__button {
546
- background: var(--color-primary);
547
- border: 2px solid var(--color-secondary);
548
- box-shadow: 2px 4px 2px 1px rgba(0, 0, 0, 0.25);
549
- border-radius: 0px 0px var(--spacing-8) var(--spacing-8);
558
+ .modal-overlay {
559
+ background: rgba(0, 0, 0, 0.3);
550
560
  bottom: 0;
551
- cursor: pointer;
552
561
  left: 0;
553
- padding-bottom: -20px;
554
- position: absolute;
555
- width: 100%;
562
+ position: fixed;
563
+ right: 0;
564
+ top: 0;
556
565
  }
557
566
 
558
- .textarea__button > svg {
559
- color: var(--color-neutral-100);
567
+ .modal {
568
+ background: white;
569
+ border-radius: var(--spacing-8);
570
+ border: 1px solid var(--color-neutral-600);
571
+ color: var(--color-black);
572
+ left: 50%;
573
+ padding: var(--spacing-4) var(--spacing-4);
574
+ position: absolute;
575
+ right: var(--spacing-16);
576
+ top: 50%;
577
+ transform: translate(-50%, -50%);
578
+ z-index: 5;
560
579
  }
561
580
 
562
- .textarea__button:disabled {
563
- cursor: unset;
564
- opacity: 0.5;
565
- pointer-events: none;
581
+ .modal__close {
582
+ position: absolute;
583
+ right: calc(var(--spacing-16) * -1);
584
+ top: calc(var(--spacing-16) * -1);
585
+ z-index: 5;
566
586
  }
567
587
 
568
- .textarea__button:enabled:hover {
569
- background: var(--color-secondary);
570
- color: var(--color-neutral-100);
588
+ .modal__content {
589
+ border: 1px solid var(--color-neutral-100);
590
+ border-radius: var(--spacing-8);
591
+ display: flex;
592
+ flex-direction: column;
593
+ gap: var(--spacing-16);
594
+ padding: 0 var(--spacing-16);
571
595
  }
572
596
 
573
- .textarea__button--show {
574
- background: var(--color-primary-700);
575
- color: var(--color-neutral-100);
576
- }
597
+ .modal__footer {
598
+ padding-bottom: var(--spacing-16);
599
+ }
package/dist/esm/index.js CHANGED
@@ -3,9 +3,9 @@ import { Children, isValidElement, cloneElement, createContext, useMemo, useStat
3
3
  import clsx from 'clsx';
4
4
  import { TfiAngleDown, TfiAngleUp } from 'react-icons/tfi';
5
5
  import { BsCheckCircleFill, BsXCircleFill } from 'react-icons/bs';
6
- import { useForm, Controller } from 'react-hook-form';
7
- import { IoClose } from 'react-icons/io5';
6
+ import { useForm, FormProvider, useFormContext, Controller } from 'react-hook-form';
8
7
  import { TbArrowsDiagonal2 } from 'react-icons/tb';
8
+ import { IoClose } from 'react-icons/io5';
9
9
 
10
10
  let uniqueId = (function () {
11
11
  let num = 0;
@@ -188,56 +188,82 @@ const AccordionContent = function AccordionContent({ children, label, toggle, })
188
188
  function Form({ children, onSubmit, submitButton = {
189
189
  label: "Submit",
190
190
  }, ...rest }) {
191
- const { handleSubmit, setValue, control, formState: { errors, isValid }, } = useForm();
191
+ const methods = useForm();
192
+ const { formState: { isValid }, } = methods;
192
193
  const [result, setResult] = useState({
193
194
  message: "",
194
195
  isSuccess: false,
195
196
  });
196
- return (jsxs("form", { className: "form", onSubmit: handleSubmit(async (data) => await onSubmit(data, setResult)), ...rest, children: [Children.map(children, (child) => {
197
- const { props: { name, error, isRequired, ...rest }, } = child;
198
- return child.props.name ? (jsx(Controller, { name: name, control: control, rules: {
199
- ...(isRequired
200
- ? {
201
- required: error?.message || "Field is required",
202
- }
203
- : {}),
204
- }, render: ({ field: { onBlur, ...restField } }) => {
205
- return cloneElement(child, {
206
- error: {
207
- is: Object.keys(errors).length > 0 && !!errors[name],
208
- message: errors &&
209
- Object.keys(errors).length > 0 &&
210
- errors[name]?.message,
211
- },
212
- setFormSelected: setValue,
213
- onFormBlur: onBlur,
214
- ...restField,
215
- ...rest,
216
- });
217
- } })) : child;
218
- }), result.message && (jsxs("div", { className: "form__message", children: [result.isSuccess ? (jsx(BsCheckCircleFill, { color: "var(--color-success)", size: 48 })) : (jsx(BsXCircleFill, { color: "var(--color-danger)", size: 48 })), result.message] })), jsx(Button, { type: "submit", disabled: !isValid, children: submitButton.label })] }));
197
+ return (jsx(FormProvider, { ...methods, children: jsxs("form", { className: "form", onSubmit: methods.handleSubmit((data) => onSubmit(data, setResult)), ...rest, children: [children, result.message && (jsxs("div", { className: "form__message", children: [result.isSuccess ? (jsx(BsCheckCircleFill, { color: "var(--color-success)", size: 48 })) : (jsx(BsXCircleFill, { color: "var(--color-danger)", size: 48 })), result.message] })), jsx(Button, { type: "submit", disabled: !isValid, children: submitButton.label })] }) }));
219
198
  }
220
199
 
221
200
  function Input({ inputClassName = "", classNameGroup = "", error = {
222
201
  is: false,
223
202
  message: "",
224
203
  }, inputRef, styleGroup, placeholder = "Insert value", label, labelClass, icon, ...rest }) {
225
- return (jsxs("div", { className: clsx("input-group", classNameGroup), style: styleGroup, children: [label && jsx("label", { className: labelClass, children: label }), jsxs("div", { className: "input-subgroup", children: [icon?.element && icon.position === "left" && (jsx("div", { className: clsx("input__icon", "input__icon--left", icon.className), children: icon.element })), jsx("input", { ref: inputRef, className: clsx("input", error.is ? "input--error" : "", icon?.position === "left" && "input--icon", inputClassName), placeholder: placeholder, ...rest }), icon?.element && icon.position !== "left" && (jsx("div", { className: clsx("input__icon", "input__icon--right",
204
+ console.log(error);
205
+ return (jsxs("div", { className: clsx("input-group", classNameGroup), style: styleGroup, children: [jsxs("div", { className: "input__header", children: [label && jsx("label", { className: labelClass, children: label }), error && error.is && (jsx("span", { className: "input__header--error", children: error.message }))] }), jsxs("div", { className: "input-subgroup", children: [icon?.element && icon.position === "left" && (jsx("div", { className: clsx("input__icon", "input__icon--left", icon.className), children: icon.element })), jsx("input", { ref: inputRef, className: clsx("input", error.is ? "input--error" : "", icon?.position === "left" && "input--icon", inputClassName), placeholder: placeholder, ...rest }), icon?.element && icon.position !== "left" && (jsx("div", { className: clsx("input__icon", "input__icon--right",
226
206
  // `input__icon--${icon.position || "right"}`,
227
- icon.className), children: icon.element }))] }), error && error.is && (jsx("span", { className: "error", children: error.message }))] }));
207
+ icon.className), children: icon.element }))] })] }));
228
208
  }
229
209
 
230
- function Loading({ img, children }) {
231
- return (jsxs("div", { className: "loading", children: [jsx("img", { src: img ? img : "../../stories/assets/loading.gif" }), children] }));
210
+ function FormInput({ name, isRequired, error, ...rest }) {
211
+ const { control } = useFormContext();
212
+ return (jsx(Controller, { name: name, control: control, rules: {
213
+ ...(isRequired
214
+ ? {
215
+ required: error?.message || "Field is required",
216
+ }
217
+ : {}),
218
+ }, render: ({ field, fieldState: { error } }) => {
219
+ return (jsx(Input, { isRequired: true, error: {
220
+ is: !!error,
221
+ message: error?.message,
222
+ }, ...field, ...rest }));
223
+ } }));
232
224
  }
233
225
 
234
- function Modal({ modalref, children, title, subtitle, footer, hasCloseButton = true, handleClose, }) {
235
- return (jsxs(Fragment, { children: [jsx("div", { className: "modal-overlay" }), jsxs("div", { ref: modalref, className: "modal", children: [hasCloseButton && (jsx(Button, { mode: "secondary", className: "modal__close", size: "small", onClick: handleClose, children: jsx(IoClose, {}) })), jsxs("div", { className: "modal__content", children: [title && (jsxs("div", { className: "modal__header", children: [jsx("h3", { children: title }), jsx("h6", { children: subtitle })] })), jsx("div", { className: "modal__children", children: children }), footer && jsx("div", { className: "modal__footer", children: footer })] })] })] }));
226
+ function TextArea({ className = "", disabled = true, hasToggleButton = true, hideHeight = "5rem", placeholder = "Insert value", showHeight = "10rem", style = {}, textareaClassName = "", label, labelClass, error = {
227
+ is: false,
228
+ message: "",
229
+ }, ...rest }) {
230
+ const ref = useRef();
231
+ const [isShow, setIsShow] = useState(false);
232
+ const handleClickToggle = () => {
233
+ if (ref && ref.current) {
234
+ if (isShow) {
235
+ ref.current.style.height = hideHeight;
236
+ }
237
+ else {
238
+ ref.current.style.height = showHeight; //(48 + ref.current.scrollHeight) + 'px';
239
+ }
240
+ setIsShow((prev) => !prev);
241
+ }
242
+ };
243
+ return (jsxs("div", { className: clsx("textarea", className), style: style, children: [jsxs("div", { className: "textarea__header", children: [label && jsx("label", { className: labelClass, children: label }), error && error.is && (jsx("span", { className: "textarea__header--error", children: error.message }))] }), jsx("textarea", { ref: ref, className: clsx("textarea__input", error.is && "textarea__input--error", textareaClassName), style: {
244
+ height: hasToggleButton ? hideHeight : showHeight,
245
+ }, placeholder: placeholder, disabled: disabled, ...rest }), hasToggleButton && (jsx("button", { type: "button", className: clsx("textarea__button", isShow && "textarea__button--show", error.is && "textarea__button--error"), onClick: handleClickToggle, disabled: disabled, children: jsx(TbArrowsDiagonal2, { size: "1.5rem" }) }))] }));
246
+ }
247
+
248
+ function FormTextArea({ name, isRequired, error, ...rest }) {
249
+ const { control } = useFormContext();
250
+ return (jsx(Controller, { name: name, control: control, rules: {
251
+ ...(isRequired
252
+ ? {
253
+ required: error?.message || "Field is required",
254
+ }
255
+ : {}),
256
+ }, render: ({ field, fieldState: { error } }) => {
257
+ return (jsx(TextArea, { isRequired: true, error: {
258
+ is: !!error,
259
+ message: error?.message,
260
+ }, ...field, ...rest }));
261
+ } }));
236
262
  }
237
263
 
238
264
  function Select({ inputClassName = "", classNameGroup = "", options, styleGroup, defaultValue,
239
265
  // inputProps,
240
- setFormSelected, onFormBlur, handleSelect, ...rest }) {
266
+ setFormSelected, clearError, onFormBlur, handleSelect, ...rest }) {
241
267
  const [isOpen, setIsOpen] = useState(false);
242
268
  const [value, setValue] = useState(defaultValue || (options && options[0]));
243
269
  const [filteredOptions, setFilteredOptions] = useState(options);
@@ -259,7 +285,6 @@ setFormSelected, onFormBlur, handleSelect, ...rest }) {
259
285
  };
260
286
  const handleValueChange = (e) => {
261
287
  const { value } = e.target;
262
- console.log(value);
263
288
  setValue(value);
264
289
  // for autocomplete
265
290
  // const { value } = e.target;
@@ -269,6 +294,9 @@ setFormSelected, onFormBlur, handleSelect, ...rest }) {
269
294
  const { name: value } = e.target;
270
295
  if (setFormSelected) {
271
296
  setFormSelected(name, value);
297
+ if (clearError) {
298
+ clearError(name);
299
+ }
272
300
  }
273
301
  else {
274
302
  setValue(value);
@@ -296,23 +324,28 @@ setFormSelected, onFormBlur, handleSelect, ...rest }) {
296
324
  }, onFocus: handleOpen, onBlur: handleInputClose, onChange: handleValueChange, autoComplete: "off", ...rest }), isOpen && (jsx("div", { className: "select__box", children: filteredOptions.map((option, index) => (jsx(Button, { type: "button", mode: "secondary", className: "select__option", name: option, onMouseDown: handleSelectChange, children: option }, `index-${index}`))) }))] }));
297
325
  }
298
326
 
299
- function TextArea({ className = "", disabled = true, hasToggleButton = true, hideHeight = "5rem", placeholder = "Insert value", showHeight = "10rem", style = {}, textareaClassName = "", label, labelClass, ...rest }) {
300
- const ref = useRef();
301
- const [isShow, setIsShow] = useState(false);
302
- const handleClickToggle = () => {
303
- if (ref && ref.current) {
304
- if (isShow) {
305
- ref.current.style.height = hideHeight;
306
- }
307
- else {
308
- ref.current.style.height = showHeight; //(48 + ref.current.scrollHeight) + 'px';
309
- }
310
- setIsShow((prev) => !prev);
311
- }
312
- };
313
- return (jsxs("div", { className: clsx("textarea", className), style: style, children: [label && jsx("label", { className: labelClass, children: label }), jsx("textarea", { ref: ref, className: clsx("textarea__input", textareaClassName), style: {
314
- height: hasToggleButton ? hideHeight : showHeight,
315
- }, placeholder: placeholder, disabled: disabled, ...rest }), hasToggleButton && (jsx("button", { type: "button", className: clsx("textarea__button", isShow && "textarea__button--show"), onClick: handleClickToggle, disabled: disabled, children: jsx(TbArrowsDiagonal2, { size: "1.5rem" }) }))] }));
327
+ function FormSelect({ name, isRequired, error, ...rest }) {
328
+ const { control, setValue, clearErrors } = useFormContext();
329
+ return (jsx(Controller, { name: name, control: control, rules: {
330
+ ...(isRequired
331
+ ? {
332
+ required: error?.message || "Field is required",
333
+ }
334
+ : {}),
335
+ }, render: ({ field: { onBlur, ...restField }, fieldState: { error } }) => {
336
+ return (jsx(Select, { isRequired: true, error: {
337
+ is: !!error,
338
+ message: error?.message,
339
+ }, setFormSelected: setValue, clearError: clearErrors, onFormBlur: onBlur, ...restField, ...rest }));
340
+ } }));
341
+ }
342
+
343
+ function Loading({ img, children }) {
344
+ return (jsxs("div", { className: "loading", children: [jsx("img", { src: img ? img : "../../stories/assets/loading.gif" }), children] }));
345
+ }
346
+
347
+ function Modal({ modalref, children, title, subtitle, footer, hasCloseButton = true, handleClose, }) {
348
+ return (jsxs(Fragment, { children: [jsx("div", { className: "modal-overlay" }), jsxs("div", { ref: modalref, className: "modal", children: [hasCloseButton && (jsx(Button, { mode: "secondary", className: "modal__close", size: "small", onClick: handleClose, children: jsx(IoClose, {}) })), jsxs("div", { className: "modal__content", children: [title && (jsxs("div", { className: "modal__header", children: [jsx("h3", { children: title }), jsx("h6", { children: subtitle })] })), jsx("div", { className: "modal__children", children: children }), footer && jsx("div", { className: "modal__footer", children: footer })] })] })] }));
316
349
  }
317
350
 
318
351
  const LoadingContext = createContext(undefined);
@@ -436,4 +469,4 @@ function useModal({} = {}) {
436
469
  return context;
437
470
  }
438
471
 
439
- export { Accordion, AccordionButton, AccordionContent, AccordionItem, Button, Form, Input, Loading, LoadingContext, LoadingProvider, Modal, ModalContext, ModalProvider, Select, TextArea, ThemeContext, ThemeProvider, useLoading, useModal, useTheme };
472
+ export { Accordion, AccordionButton, AccordionContent, AccordionItem, Button, Form, FormInput, FormSelect, FormTextArea, Input, Loading, LoadingContext, LoadingProvider, Modal, ModalContext, ModalProvider, Select, TextArea, ThemeContext, ThemeProvider, useLoading, useModal, useTheme };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geoinsight/react-components",
3
- "version": "0.6.6",
3
+ "version": "0.6.8",
4
4
  "description": "This library is the main UI component library for geoinsight",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",