@tfehotels/tfe-gatsby-library 1.0.1 → 1.0.2

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.
Files changed (73) hide show
  1. package/package.json +2 -3
  2. package/src/browser/api/button/index.tsx +0 -16
  3. package/src/browser/api/button/types.ts +0 -7
  4. package/src/browser/api/checkbox/index.tsx +0 -74
  5. package/src/browser/api/checkbox/types.tsx +0 -21
  6. package/src/browser/api/country-prefix/index.tsx +0 -150
  7. package/src/browser/api/country-prefix/types.tsx +0 -17
  8. package/src/browser/api/form/index.tsx +0 -330
  9. package/src/browser/api/form/types.ts +0 -31
  10. package/src/browser/api/google-places/index.tsx +0 -90
  11. package/src/browser/api/google-places/types.ts +0 -24
  12. package/src/browser/api/icon/index.tsx +0 -26
  13. package/src/browser/api/icon/types.tsx +0 -24
  14. package/src/browser/api/image/index.tsx +0 -91
  15. package/src/browser/api/image/types.ts +0 -11
  16. package/src/browser/api/input/index.tsx +0 -44
  17. package/src/browser/api/input/types.ts +0 -10
  18. package/src/browser/api/link/index.tsx +0 -54
  19. package/src/browser/api/link/types.ts +0 -24
  20. package/src/browser/api/linklist/index.tsx +0 -17
  21. package/src/browser/api/linklist/types.ts +0 -6
  22. package/src/browser/api/select/index.tsx +0 -99
  23. package/src/browser/api/select/types.ts +0 -24
  24. package/src/browser/api/svg/index.tsx +0 -8
  25. package/src/browser/api/svg/types.ts +0 -8
  26. package/src/browser/api/text/index.tsx +0 -14
  27. package/src/browser/api/text/types.ts +0 -12
  28. package/src/browser/api/textarea/index.tsx +0 -12
  29. package/src/browser/api/title/index.tsx +0 -19
  30. package/src/browser/api/title/types.ts +0 -10
  31. package/src/browser/api/types.ts +0 -245
  32. package/src/browser/carousel/buttons/index.tsx +0 -81
  33. package/src/browser/carousel/buttons/types.ts +0 -15
  34. package/src/browser/carousel/dots/index.tsx +0 -53
  35. package/src/browser/carousel/dots/types.ts +0 -14
  36. package/src/browser/carousel/index.tsx +0 -131
  37. package/src/browser/carousel/types.ts +0 -21
  38. package/src/browser/markdown/index.tsx +0 -41
  39. package/src/browser/markdown/types.ts +0 -11
  40. package/src/browser/modal/index.tsx +0 -35
  41. package/src/browser/modal/types.ts +0 -9
  42. package/src/browser/spinner/index.tsx +0 -19
  43. package/src/browser/spinner/types.ts +0 -5
  44. package/src/browser/toast/index.tsx +0 -84
  45. package/src/browser/use_viewport/index.tsx +0 -34
  46. package/src/browser/use_viewport/types.ts +0 -5
  47. package/src/browser/utils/animation.ts +0 -12
  48. package/src/browser/utils/booking_engine.ts +0 -180
  49. package/src/browser/utils/eclub.ts +0 -30
  50. package/src/browser/utils/forms.ts +0 -76
  51. package/src/browser/utils/hotel.ts +0 -25
  52. package/src/browser/utils/image.ts +0 -63
  53. package/src/browser/utils/location.ts +0 -213
  54. package/src/browser/utils/notifications.tsx +0 -25
  55. package/src/browser/utils/number.ts +0 -6
  56. package/src/browser/utils/requests.ts +0 -2
  57. package/src/browser/utils/search.ts +0 -25
  58. package/src/browser/utils/string.ts +0 -9
  59. package/src/browser/utils/types.ts +0 -106
  60. package/src/browser/utils/url.ts +0 -116
  61. package/src/browser/utils/viewport.ts +0 -59
  62. package/src/index.browser.ts +0 -103
  63. package/src/index.node.ts +0 -16
  64. package/src/node/api/index.ts +0 -174
  65. package/src/node/api/types.ts +0 -19
  66. package/src/node/build/index.ts +0 -142
  67. package/src/node/build/types.ts +0 -5
  68. package/src/node/config/index.ts +0 -149
  69. package/src/node/form/index.ts +0 -23
  70. package/src/node/form/types.ts +0 -3
  71. package/src/node/property/index.ts +0 -78
  72. package/src/node/property/types.ts +0 -25
  73. package/src/node/url/index.ts +0 -8
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tfehotels/tfe-gatsby-library",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Shared functions and utilities for TFE's Gatsby websites.",
5
5
  "main": "./lib/index.node.cjs",
6
6
  "module": "./lib/index.node.esm.js",
@@ -31,8 +31,7 @@
31
31
  "type:gen": "./scripts/typegen.sh"
32
32
  },
33
33
  "files": [
34
- "/lib",
35
- "/src"
34
+ "/lib"
36
35
  ],
37
36
  "dependencies": {
38
37
  "@fortawesome/fontawesome-svg-core": "^6.5.2",
@@ -1,16 +0,0 @@
1
- import React from "react"
2
- import { ButtonPropsType } from "./types"
3
-
4
- const Button: React.FC<ButtonPropsType> = ({ ...props }) => {
5
- return (
6
- <button
7
- className={props.className}
8
- type={props.input_type ?? "button"}
9
- onClick={props.onClick}
10
- >
11
- {props.value}
12
- </button>
13
- )
14
- }
15
-
16
- export default Button;
@@ -1,7 +0,0 @@
1
- import { MouseEventHandler } from "react";
2
- import { ButtonType } from "../types";
3
-
4
- export interface ButtonPropsType extends ButtonType {
5
- className?: string;
6
- onClick?: MouseEventHandler<HTMLButtonElement>;
7
- }
@@ -1,74 +0,0 @@
1
- import React from "react"
2
- import { CheckboxPropsType } from "./types"
3
- import Markdown from "../../markdown"
4
- // import { motion, useMotionValue, useTransform } from "framer-motion"
5
-
6
- // const tickVariants = {
7
- // pressed: (isChecked: boolean) => ({ pathLength: isChecked ? 0.85 : 0.2 }),
8
- // checked: { pathLength: 1 },
9
- // unchecked: { pathLength: 0 },
10
- // }
11
-
12
- // const boxVariants = {
13
- // hover: { scale: 1.05, strokeWidth: 4 },
14
- // pressed: { scale: 0.95, strokeWidth: 4 },
15
- // checked: { stroke: "#b4b2e6" },
16
- // unchecked: { stroke: "#b4b2e6", strokeWidth: 4 },
17
- // }
18
-
19
- export default function Checkbox({
20
- className,
21
- label,
22
- description,
23
- ...props
24
- }: CheckboxPropsType) {
25
- // const pathLength = useMotionValue(0)
26
- // const opacity = useTransform(pathLength, [0.05, 0.15], [0, 1])
27
-
28
- return (
29
- <label
30
- className={`checkbox ${className ? ` ${className}` : ""}`}
31
- onClick={props.onClick}
32
- onChange={props.onChange}
33
- >
34
- {!!label && <span>{label}</span>}
35
- <svg
36
- id={props.id}
37
- // initial={props.value}
38
- // animate={props.value ? "checked" : "unchecked"}
39
- // whileHover="hover"
40
- // whileTap="pressed"
41
- width={props.width ? props.width : 30}
42
- height={props.height ? props.height : 30}
43
- viewBox="0 0 440 440"
44
- >
45
- <path
46
- d="M 72 136 C 72 100.654 100.654 72 136 72 L 304 72 C 339.346 72 368 100.654 368 136 L 368 304 C 368 339.346 339.346 368 304 368 L 136 368 C 100.654 368 72 339.346 72 304 Z"
47
- fill={props.color ? props.color : "#58595b"}
48
- strokeWidth={3}
49
- stroke="#FF008C"
50
- // variants={boxVariants}
51
- />
52
- <path
53
- // d="M 90 110 L 128 240 L 341.808 0"
54
- d="M 160 180 L 210 250 L 340 130"
55
- // transform="translate(54.917 68.947) rotate(-4 170.904 18.687)"
56
- transform="translate(40 65) rotate(-10 70.904 438.687)"
57
- fill="transparent"
58
- strokeWidth={30}
59
- stroke="white"
60
- strokeLinecap="square"
61
- strokeLinejoin="miter"
62
- // variants={tickVariants}
63
- // style={{ pathLength, opacity }}
64
- // custom={props.value}
65
- />
66
- </svg>
67
- {!!description && (
68
- <div>
69
- <Markdown>{description}</Markdown>
70
- </div>
71
- )}
72
- </label>
73
- )
74
- }
@@ -1,21 +0,0 @@
1
- import { MouseEventHandler, ChangeEventHandler } from "react"
2
-
3
- export interface CheckboxPropsType {
4
- onClick?: MouseEventHandler<HTMLLabelElement>
5
- onChange?: ChangeEventHandler<HTMLLabelElement>
6
- className?: string
7
- value: boolean
8
- width?: number
9
- height?: number
10
- id?: string
11
- name?: string
12
- input_name?: string
13
- color?: string
14
- accept?: string
15
- label?: string
16
- description?: string
17
- }
18
-
19
- export interface CheckboxesTypes {
20
- [key: string]: any
21
- }
@@ -1,150 +0,0 @@
1
- import React, {
2
- startTransition,
3
- useCallback,
4
- useEffect,
5
- useRef,
6
- useState,
7
- } from "react"
8
- import { PhonePropsType } from "./types"
9
- import { countryPrefixes } from "../../utils/location"
10
- import { scrollToChild } from "../../utils/viewport"
11
- import Markdown from "../../markdown"
12
-
13
- export default function CountryPrefix({
14
- className,
15
- label,
16
- description,
17
- input_name,
18
- onClick,
19
- onChange,
20
- value,
21
- ...props
22
- }: PhonePropsType) {
23
- const [showOptions, setShowOptions] = useState<boolean>(false)
24
- const [focused, setFocused] = useState<number>(0)
25
- const [input, setInput] = useState("")
26
- const listRef = useRef<HTMLUListElement>(null)
27
-
28
- const handleSelection = useCallback(
29
- (focused: number) => {
30
- onChange?.(countryPrefixes[focused][1] as any)
31
- startTransition(() => {
32
- setShowOptions(false)
33
- setFocused(focused)
34
- })
35
- },
36
- [onChange, countryPrefixes]
37
- )
38
-
39
- const handleKeyDown = (e: React.KeyboardEvent<HTMLUListElement>) => {
40
- e.stopPropagation()
41
- e.preventDefault()
42
- const { key } = e
43
- if (key === "ArrowDown" || key === "ArrowUp") {
44
- // Logic to navigate through the list items
45
- startTransition(() => {
46
- setFocused(
47
- key === "ArrowDown"
48
- ? Math.min(focused + 1, countryPrefixes.length - 1)
49
- : Math.max(focused - 1, 0)
50
- )
51
- setInput("")
52
- })
53
- } else if (key === "Escape") {
54
- startTransition(() => setShowOptions(false))
55
- } else if (key === "Enter") {
56
- handleSelection(focused)
57
- } else if (key === "Backspace") {
58
- startTransition(() => setInput(input.slice(0, -1)))
59
- } else if (/^[ \p{L}]+$/u.test(key)) {
60
- startTransition(() => setInput(input + key))
61
- }
62
- }
63
-
64
- const scrollToFocusedCountry = useCallback(() => {
65
- if (!listRef.current) return
66
- const element = listRef.current.querySelector(
67
- `#${props.name ?? "country-prefix"}__${countryPrefixes[focused][0]}`
68
- )
69
- if (!element) return
70
- scrollToChild(listRef.current, element as HTMLElement)
71
- }, [focused, countryPrefixes])
72
-
73
- // Focus selected option based on input
74
- useEffect(() => {
75
- if (!input) return
76
- let foundIndex = countryPrefixes.findIndex(row =>
77
- row[2].toLowerCase().startsWith(input.toLowerCase())
78
- )
79
- if (foundIndex >= 0) {
80
- startTransition(() => setFocused(foundIndex))
81
- } else {
82
- startTransition(() => setInput(""))
83
- }
84
- }, [input])
85
-
86
- useEffect(() => {
87
- scrollToFocusedCountry()
88
- }, [focused])
89
-
90
- useEffect(() => {
91
- if (!listRef.current) return
92
- if (showOptions) {
93
- // Autofocus on open dropdown
94
- listRef.current.focus()
95
- return
96
- }
97
-
98
- startTransition(() => setInput(""))
99
- }, [showOptions])
100
-
101
- return (
102
- <label
103
- className={`country-prefix ${className ? ` ${className}` : ""}`}
104
- >
105
- {!!label && <span>{label}</span>}
106
- <div
107
- className="selected-prefix"
108
- onClick={() => {
109
- startTransition(() => setShowOptions(true))
110
- listRef?.current?.focus()
111
- }}
112
- >
113
- +{value ?? countryPrefixes[0][1]}
114
- &gt;
115
- </div>
116
- <ul
117
- className={showOptions ? "show" : ""}
118
- ref={listRef}
119
- role="listbox"
120
- tabIndex={-1}
121
- onKeyDown={handleKeyDown}
122
- aria-activedescendant={`${props.name ?? "country-prefix"}__${
123
- countryPrefixes[focused][0]
124
- }`}
125
- >
126
- {countryPrefixes.map(([countryCode, prefix, name], k) => {
127
- return (
128
- <li
129
- className={k === focused ? "selected" : ""}
130
- role="option"
131
- onClick={() => handleSelection(k)}
132
- aria-selected={k === focused}
133
- aria-label={`${name} +${prefix}`}
134
- id={`${props.name ?? "country-prefix"}__${countryCode}`}
135
- key={`${props.name ?? "country-prefix"}__${countryCode}`}
136
- >
137
- {name} +{prefix}
138
- </li>
139
- )
140
- })}
141
- </ul>
142
- <input type="hidden" name={input_name} />
143
- {!!description && (
144
- <div>
145
- <Markdown>{description}</Markdown>
146
- </div>
147
- )}
148
- </label>
149
- )
150
- }
@@ -1,17 +0,0 @@
1
- import { MouseEventHandler, ChangeEventHandler } from "react"
2
-
3
- export interface PhonePropsType {
4
- onClick?: MouseEventHandler<HTMLLabelElement>
5
- onChange?: ChangeEventHandler<HTMLLabelElement>
6
- className?: string
7
- value: string
8
- width?: number
9
- height?: number
10
- id?: string
11
- name?: string
12
- input_name?: string
13
- color?: string
14
- accept?: string
15
- label?: string
16
- description?: string
17
- }
@@ -1,330 +0,0 @@
1
- import { useGoogleReCaptcha } from "react-google-recaptcha-v3"
2
- import React, { startTransition, useCallback, useEffect } from "react"
3
- import { ErrorsType, FormPropsType } from "./types"
4
- import { toastMsg } from "../../utils/notifications"
5
- import {
6
- INPUT_FIELDS,
7
- getInputEventValue,
8
- getInputHumanValue,
9
- json_request,
10
- } from "../../utils/forms"
11
- import type {
12
- FormFieldsType,
13
- FormItemType,
14
- } from "../../utils/types"
15
- import classNames from "classnames"
16
- import Markdown from "../../markdown"
17
- import Spinner from "../../spinner"
18
-
19
- const Element: any = <div/> //React.lazy(() => import(<div/>))
20
-
21
-
22
- export default function Form({
23
- className,
24
- form,
25
- setForm,
26
- errors,
27
- setErrors,
28
- beforeSubmit,
29
- formatParams,
30
- validate,
31
- validateResponse,
32
- onSuccess,
33
- onFocus,
34
- onBlur,
35
- onClick,
36
- onChange,
37
- onError,
38
- afterSubmit,
39
- loading,
40
- }: FormPropsType) {
41
- const { executeRecaptcha } = useGoogleReCaptcha()
42
-
43
- const showErrors = (errors: ErrorsType, showInputName: boolean = true) => (
44
- <div>
45
- <ul className={"error"}>
46
- {Object.entries(errors).map(([input, error], k: number) => (
47
- <li key={`error-form${k}`}>
48
- X
49
- <span>
50
- {showInputName ? <strong>{input}:</strong> : ""} {error}
51
- </span>
52
- </li>
53
- ))}
54
- </ul>
55
- </div>
56
- )
57
-
58
- const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
59
- e.preventDefault()
60
- let errors: any = {}
61
- let params = Object.values(form.fields).reduce((acc, field) => {
62
- if (INPUT_FIELDS.has(field.type)) {
63
- // @ts-ignore
64
- if (field.required && !field.value) {
65
- //@ts-ignore
66
- errors[field.input_name] = `${
67
- //@ts-ignore
68
- field.label ? field.label : field.placeholder
69
- } is required`
70
- return acc
71
- }
72
- // @ts-ignore
73
- // Skip non-checked radio buttons
74
- if (field.input_type === "radio" && !field.checked) {
75
- return acc
76
- }
77
- // @ts-ignore
78
- acc[field.input_name] = getInputHumanValue(field.type, field.value)
79
- }
80
- return acc
81
- }, {} as any)
82
-
83
- // Get reCAPTCHA v3 token
84
- if (form.settings.recaptcha_v3) {
85
- params.recaptcha_token = await verifyRecaptcha()
86
- if (!params.recaptcha_token) {
87
- errors.recaptcha = "reCAPTCHA failed!"
88
- }
89
- }
90
-
91
- // Check recaptcha v2 if it's within the fields
92
- if (form.fields.recaptcha && !params.recaptcha) {
93
- errors.recaptcha = "Recaptcha is mandatory"
94
- }
95
-
96
- if (validate) {
97
- errors = { ...errors, ...validate(form.fields, params) }
98
- }
99
- if (Object.keys(errors).length) {
100
- startTransition(() => {
101
- setErrors(errors)
102
- toastMsg(showErrors(errors, false))
103
- })
104
- return
105
- }
106
-
107
- if (beforeSubmit) {
108
- beforeSubmit(form)
109
- }
110
-
111
- if (formatParams) {
112
- params = formatParams(params)
113
- }
114
-
115
- // If is not an AJAX request, the page will be redirected into the form submit URL
116
- if (!form.settings.form_ajax_request) {
117
- // @ts-ignore
118
- return e.target.submit()
119
- }
120
- const response = await json_request(
121
- form.settings.form_submit,
122
- params,
123
- form.settings.form_method,
124
- form.settings.form_recipient
125
- ? {
126
- "recipient-id": `${form.settings.form_recipient}`,
127
- }
128
- : {}
129
- )
130
- startTransition(() => {
131
- // ON SUCCESS:
132
- if (
133
- response.status === 200 &&
134
- (!validateResponse || validateResponse(response))
135
- ) {
136
- if (onSuccess) {
137
- // Execute onSuccess action when defined:
138
- onSuccess(response, form.settings.form_success_msg)
139
- } else {
140
- // Otherwise just show success message:
141
- toastMsg(
142
- form.settings.form_success_msg ? (
143
- <Markdown>{form.settings.form_success_msg}</Markdown>
144
- ) : (
145
- "Success! Your form has been successfully sent. Thank you for reaching out, we will get back to you as soon as possible."
146
- ),
147
- "success"
148
- )
149
- }
150
-
151
- if (form.settings.form_redirection) {
152
- setTimeout(() => {
153
- window.location.href = form.settings.form_redirection as string
154
- }, 3000)
155
- }
156
-
157
- // Reset all form values:
158
- setForm({
159
- ...form,
160
- fields: Object.entries(form.fields).reduce((acc, [name, field]) => {
161
- acc[name] = INPUT_FIELDS.has(field.type) // @ts-ignore
162
- ? { ...field, value: "" }
163
- : field
164
- return acc
165
- }, {} as FormFieldsType),
166
- })
167
- // ON ERROR:
168
- } else if (onError) {
169
- onError(response)
170
- // ELSE ON ERROR:
171
- } else if (response.errors) {
172
- let newErrors: ErrorsType = Object.entries(response.errors).reduce(
173
- (acc, [inputName, errorList]) => {
174
- acc[inputName] = errorList.join(", ")
175
- return acc
176
- },
177
- {} as ErrorsType
178
- )
179
- toastMsg(showErrors(newErrors))
180
- setErrors(newErrors)
181
- // ELSE ON ERROR:
182
- } else if (response.error) {
183
- toastMsg(
184
- showErrors(
185
- {
186
- failed: response.error ? (
187
- <Markdown>{response.error}</Markdown>
188
- ) : (
189
- "Oops. Something went wrong. Please try again later, or contact us at members@tfehotels.com"
190
- ),
191
- },
192
- false
193
- )
194
- )
195
- }
196
- })
197
-
198
- if (afterSubmit) {
199
- afterSubmit(response)
200
- }
201
- }
202
-
203
- const verifyRecaptcha = useCallback(async () => {
204
- if (!executeRecaptcha) {
205
- console.log("Execute recaptcha not yet available")
206
- return
207
- }
208
- return await executeRecaptcha(form.settings.recaptcha_action)
209
- }, [executeRecaptcha])
210
-
211
- useEffect(() => {
212
- if (form.settings.recaptcha_v3) {
213
- verifyRecaptcha()
214
- }
215
- }, [form.settings.recaptcha_v3, verifyRecaptcha])
216
-
217
- const buildFormElement = (item: FormItemType) => {
218
- if (typeof item === "string") {
219
- const field: any = form.fields[item]
220
- return (
221
- <div
222
- className={`${field.type} ${field.type}-${field.name}`}
223
- key={`ff-${form.settings.pk}-${item}`}
224
- >
225
- {INPUT_FIELDS.has(field.type) ? (
226
- <Element
227
- className={classNames({
228
- [field.data.class]: Boolean(field.data.class),
229
- error: Boolean(errors[item]),
230
- })}
231
- onFocus={(e: React.FocusEvent) => {
232
- if (onFocus) onFocus(e)
233
- }}
234
- onBlur={(e: React.FocusEvent) => {
235
- if (onBlur) onBlur(e)
236
- }}
237
- onClick={(e: React.MouseEvent) => {
238
- // Only for checkboxes/Radios
239
- if (["checkbox", "radio"].includes(field.input_type)) {
240
- let newForm = { ...form }
241
- if (field.input_type === "checkbox") {
242
- newForm.fields = {
243
- ...form.fields,
244
- [item]: { ...field, value: !field.value },
245
- }
246
- } else {
247
- // Radio buttons (sets the "checked" flag on all radio buttons with same name)
248
- newForm.fields = Object.entries(form.fields).reduce(
249
- (acc, [fieldName, attrs]) => {
250
- acc[fieldName] = attrs //@ts-ignore
251
- if (attrs.input_name === field.input_name) {
252
- //@ts-ignore
253
- acc[fieldName].checked = //@ts-ignore
254
- field.value === acc[fieldName].value
255
- }
256
- return acc
257
- },
258
- {} as FormFieldsType
259
- )
260
- }
261
- startTransition(() => {
262
- setForm(newForm)
263
- if (errors[item]) {
264
- setErrors({}) // reset errors
265
- }
266
- })
267
- }
268
- if (onClick) onClick(e)
269
- }}
270
- checked={
271
- field.input_type === "radio" ? !!field.checked : undefined
272
- }
273
- onChange={(e: any) => {
274
- if (!["checkbox", "radio"].includes(field.input_type)) {
275
- startTransition(() => {
276
- setForm({
277
- ...form,
278
- fields: {
279
- ...form.fields,
280
- [item]: {
281
- ...field,
282
- value: getInputEventValue(field.type, e),
283
- data: e.target?.data
284
- ? { ...field.data, ...e.target.data }
285
- : field.data,
286
- },
287
- },
288
- })
289
-
290
- if (errors[item]) {
291
- setErrors({}) // reset errors
292
- }
293
- })
294
- }
295
- if (onChange) onChange(e)
296
- }}
297
- {...{
298
- ...field,
299
- value: field.value ? field.value : "",
300
- }}
301
- />
302
- ) : (
303
- // Display Titles, Texts, Links, etc..
304
- <Element {...field} />
305
- )}
306
- </div>
307
- )
308
- }
309
- // Otherwise is a section
310
- return (
311
- <div
312
- className={`form-section ${item.name}`}
313
- key={`ff-${form.settings.pk}-${item.name}`}
314
- >
315
- {item.children.map(buildFormElement)}
316
- </div>
317
- )
318
- }
319
- return (
320
- <form
321
- className={className}
322
- action={form.settings.form_submit}
323
- method={form.settings.form_method}
324
- onSubmit={e => handleSubmit(e)}
325
- noValidate
326
- >
327
- {loading ? <Spinner color="#00b5ee" /> : form.items.map(buildFormElement)}
328
- </form>
329
- )
330
- }
@@ -1,31 +0,0 @@
1
- import { ReactNode } from "react";
2
- import { InputType } from "../types";
3
- import { FormType } from "../../utils/types";
4
-
5
- export interface InputsType {
6
- [field: string]: InputType;
7
- }
8
-
9
- export interface ErrorsType {
10
- [field: string]: string | ReactNode;
11
- }
12
-
13
- export interface FormPropsType {
14
- className?: string;
15
- form: FormType;
16
- setForm: Function;
17
- errors: ErrorsType;
18
- loading?: boolean;
19
- setErrors: Function;
20
- beforeSubmit?: Function;
21
- formatParams?: Function;
22
- validate?: Function;
23
- validateResponse?: Function;
24
- onSuccess?: Function;
25
- onFocus?: Function;
26
- onBlur?: Function;
27
- onClick?: Function;
28
- onChange?: Function;
29
- onError?: Function;
30
- afterSubmit?: Function;
31
- }