gform-react 2.7.0 → 2.7.5

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 (43) hide show
  1. package/README.md +108 -31
  2. package/dist/cjs/gform-react.development.js +16 -32
  3. package/dist/cjs/gform-react.development.js.map +1 -1
  4. package/dist/cjs/gform-react.production.js +1 -1
  5. package/dist/cjs/gform-react.production.js.map +1 -1
  6. package/dist/esm/GForm.development.js +1 -2
  7. package/dist/esm/GForm.development.js.map +1 -1
  8. package/dist/esm/GForm.production.js +1 -1
  9. package/dist/esm/GForm.production.js.map +1 -1
  10. package/dist/esm/GInput.development.js +3 -2
  11. package/dist/esm/GInput.development.js.map +1 -1
  12. package/dist/esm/GInput.production.js +1 -1
  13. package/dist/esm/GInput.production.js.map +1 -1
  14. package/dist/esm/GValidator.development.js +0 -6
  15. package/dist/esm/GValidator.development.js.map +1 -1
  16. package/dist/esm/GValidator.production.js +1 -1
  17. package/dist/esm/GValidator.production.js.map +1 -1
  18. package/dist/esm/shared.development.js +8 -4
  19. package/dist/esm/shared.development.js.map +1 -1
  20. package/dist/esm/shared.production.js +1 -1
  21. package/dist/esm/shared.production.js.map +1 -1
  22. package/dist/esm/useFormSelector.development.js +1 -2
  23. package/dist/esm/useFormSelector.development.js.map +1 -1
  24. package/dist/esm/useFormSelector.production.js +1 -1
  25. package/dist/index.d.ts +1 -4
  26. package/native/dist/cjs/gform-react.development.js +78 -101
  27. package/native/dist/cjs/gform-react.development.js.map +1 -1
  28. package/native/dist/cjs/gform-react.production.js +1 -1
  29. package/native/dist/cjs/gform-react.production.js.map +1 -1
  30. package/native/dist/esm/RNGForm.development.js +11 -45
  31. package/native/dist/esm/RNGForm.development.js.map +1 -1
  32. package/native/dist/esm/RNGForm.production.js +1 -1
  33. package/native/dist/esm/RNGForm.production.js.map +1 -1
  34. package/native/dist/esm/RNGInput.development.js +12 -6
  35. package/native/dist/esm/RNGInput.development.js.map +1 -1
  36. package/native/dist/esm/RNGInput.production.js +1 -1
  37. package/native/dist/esm/RNGInput.production.js.map +1 -1
  38. package/native/dist/esm/shared.development.js +38 -19
  39. package/native/dist/esm/shared.development.js.map +1 -1
  40. package/native/dist/esm/shared.production.js +1 -1
  41. package/native/dist/esm/shared.production.js.map +1 -1
  42. package/native/dist/index.d.ts +4 -5
  43. package/package.json +9 -3
package/README.md CHANGED
@@ -1,42 +1,119 @@
1
- # GForm
2
-
3
- ![gform-react](https://gform-react.onrender.com/gform-logo.png)
4
-
5
- ![npm bundle size](https://img.shields.io/bundlephobia/min/gform-react?label=minified%20size&color=darkergreen)
6
- ![npm bundle size](https://img.shields.io/bundlephobia/minzip/gform-react?label=gzip%20size&color=darkergreen)
7
- ![npm peer dependency version](https://img.shields.io/npm/dependency-version/gform-react/peer/react)
8
- ![npm peer dependency version](https://img.shields.io/npm/dependency-version/gform-react/peer/react-dom)
9
- [![NPM](https://img.shields.io/npm/l/gform-react)](https://unpkg.com/gform-react@latest/LICENSE.md)
10
-
11
- #### build generic forms with validations for react-based applications.
12
- it doesn't matter which UI library you're using,
13
- it only cares about the form and the inputs inside.
14
-
15
- ## Pros
16
- * Lightweight
17
- * Based on native form and constraint validations (can also add custom and async validations)
18
- * Can be used with any UI library that preserves native form controls (input, button, etc. can also be adjusted to non-native controls)
19
- * Tree shakeable
20
- * Accessibility semi-automatic (required inputs and invalid inputs automatically sets aria-required and aria-invalid)
21
- * React Native support
22
- * Supports React 19, Next.js 15
23
-
24
- ## Docs
25
- https://gform-react.onrender.com
1
+ <div align="center">
2
+ <a href="https://gform-react.onrender.com" title="GForm React – A lightweight React form library built for performance, validation, and clean form logic">
3
+ <img src="https://gform-react.onrender.com/gform-logo.png" alt="gform-react logo" />
4
+ </a>
5
+ <h1>gform-react</h1>
6
+ <p>A lightweight React form library built for <b>performance</b>, <b>validation</b>, and clean <b>form logic</b></p>
7
+ </div>
8
+
9
+ ## Features
10
+
11
+ - **Lightweight**
12
+ - **Tree‑shakeable**
13
+ - **Minimal re-renders** only updates fields that change
14
+ - **Native HTML Constraint Validations**
15
+ - **Custom Validations**
16
+ - **Custom Async Validations**
17
+ - **Supports Yup, Zod, and more**
18
+ - **Dynamic forms** add/remove fields on the fly
19
+ - **Accessibility‑friendly**
20
+ Automatically sets `aria-required` and `aria-invalid`
21
+ - **React Native support**
22
+
23
+ <br/>
24
+ <div align="center">
25
+ <a href="https://bundlephobia.com/package/gform-react">
26
+ <img src="https://img.shields.io/bundlephobia/min/gform-react?label=minified%20size&color=darkergreen" alt="Minified size">
27
+ </a>
28
+
29
+ <a href="https://bundlephobia.com/package/gform-react">
30
+ <img src="https://img.shields.io/bundlephobia/minzip/gform-react?label=gzip%20size&color=darkergreen" alt="Gzip size">
31
+ </a>
32
+
33
+ <img src="https://img.shields.io/npm/dm/gform-react" alt="npm downloads">
34
+
35
+ <img src="https://img.shields.io/npm/dependency-version/gform-react/peer/react" alt="React peer dependency">
36
+
37
+ <img src="https://img.shields.io/npm/dependency-version/gform-react/peer/react-dom" alt="React DOM peer dependency">
38
+
39
+ <a href="https://unpkg.com/gform-react@latest/LICENSE.md">
40
+ <img src="https://img.shields.io/npm/l/gform-react" alt="MIT License">
41
+ </a>
42
+ </div>
43
+ <br/>
44
+
45
+ ## QuickStart
46
+ ```tsx
47
+ import {GForm, GInput, GValidator, type GValidators} from "gform-react";
26
48
 
27
- ## Demo:
28
- https://codesandbox.io/p/sandbox/gifted-elbakyan-fs5g2c
49
+ interface SignInForm {
50
+ username: string;
51
+ password: string;
52
+ }
53
+
54
+ const baseValidator = new GValidator().withRequiredMessage('this field is required');
55
+
56
+ const validators: GValidators<SignInForm> = {
57
+ '*': baseValidator, // a default validator for all other fields in the form
58
+
59
+ password: new GValidator(baseValidator)
60
+ .withMinLengthMessage((input) => `${input.formKey} must contain atleast ${input.minLength} chars`),
61
+ };
62
+
63
+ const App: FC = () => {
64
+ return (
65
+ <GForm<SignInForm> className='some-class'
66
+ validators={validators}
67
+ onSubmit={(formState, e) => { //can be used with native `action` or with Next.js `server actions`
68
+ e.preventDefault();
69
+ console.log(formState);
70
+ }}>
71
+ <GInput formKey='username'
72
+ required
73
+ element={(input, props) => <div>
74
+ <input {...props} placeholder='username'/>
75
+ {input.error && <small className="p-error">{input.errorText}</small>}
76
+ </div>}
77
+ />
78
+ <GInput formKey='password'
79
+ type='password'
80
+ required
81
+ minLength={5}
82
+ element={(input, props) => <div>
83
+ <input {...props} placeholder='password'/>
84
+ {input.error && <small className="p-error">{input.errorText}</small>}
85
+ </div>}
86
+ />
87
+ <button>Submit</button>
88
+ </GForm>
89
+ );
90
+ };
91
+ ```
92
+
93
+ ## Documentation
94
+
95
+ Full documentation, examples, and API reference:
96
+
97
+ https://gform-react.onrender.com
29
98
 
30
99
  ## Installation
100
+
31
101
  npm:
32
- ```shell
102
+
103
+ ```sh
33
104
  npm install gform-react
34
105
  ```
35
106
 
36
107
  yarn:
37
- ```shell
108
+
109
+ ```sh
38
110
  yarn add gform-react
39
111
  ```
40
112
 
41
- #### NOTE:
42
- react >=16.8.0, react-dom >=16.8.0 are peer dependencies
113
+ ## Peer dependencies
114
+ react >=16.8.0, react-dom >=16.8.0 are peer dependencies
115
+
116
+ ## License
117
+
118
+ MIT © Tal
119
+ https://www.npmjs.com/package/gform-react
@@ -2,7 +2,6 @@
2
2
 
3
3
  var _extends = require('@babel/runtime/helpers/extends');
4
4
  var React = require('react');
5
- var _defineProperty = require('@babel/runtime/helpers/defineProperty');
6
5
 
7
6
  const isObject = o => o && typeof o === 'object' && !Array.isArray(o);
8
7
  const defaultFieldProps = {
@@ -108,8 +107,7 @@ const _findValidityKey = (validity, exclude = []) => {
108
107
  }
109
108
  };
110
109
  const _checkTypeMismatch = input => {
111
- var _input$value;
112
- const value = (_input$value = input.value) === null || _input$value === void 0 ? void 0 : _input$value.toString().trim();
110
+ const value = input.value?.toString().trim();
113
111
  if (!value) return false;
114
112
  switch (input.type) {
115
113
  case 'email':
@@ -150,19 +148,15 @@ const _toRawData = (fields, options = {}) => {
150
148
  transform
151
149
  } = options;
152
150
  if (include) {
153
- include.forEach(key => {
154
- var _fields$key;
155
- return data[key] = (_fields$key = fields[key]) === null || _fields$key === void 0 ? void 0 : _fields$key.value;
156
- });
151
+ include.forEach(key => data[key] = fields[key]?.value);
157
152
  } else for (const f in fields) {
158
153
  data[f] = fields[f].value;
159
154
  }
160
- exclude === null || exclude === void 0 || exclude.forEach(key => delete data[key]);
155
+ exclude?.forEach(key => delete data[key]);
161
156
  if (transform) {
162
157
  for (const key in transform) {
163
- var _fields$key2;
164
158
  const set = transform[key];
165
- data[key] = set(((_fields$key2 = fields[key]) === null || _fields$key2 === void 0 ? void 0 : _fields$key2.value) || fields[key]);
159
+ data[key] = set(fields[key]?.value || fields[key]);
166
160
  }
167
161
  }
168
162
  return data;
@@ -181,19 +175,15 @@ function _toURLSearchParams(options) {
181
175
  } = options;
182
176
  if (include) {
183
177
  data = {};
184
- include.forEach(key => {
185
- var _this$key;
186
- return data[key] = (_this$key = this[key]) === null || _this$key === void 0 ? void 0 : _this$key.value;
187
- });
178
+ include.forEach(key => data[key] = this[key]?.value);
188
179
  } else {
189
180
  data = this.toRawData();
190
- exclude === null || exclude === void 0 || exclude.forEach(key => delete data[key]);
181
+ exclude?.forEach(key => delete data[key]);
191
182
  }
192
183
  if (transform) {
193
184
  for (const key in transform) {
194
- var _this$key2;
195
185
  const set = transform[key];
196
- data[key] = set((_this$key2 = this[key]) === null || _this$key2 === void 0 ? void 0 : _this$key2.value);
186
+ data[key] = set(this[key]?.value);
197
187
  }
198
188
  }
199
189
  } else data = this.toRawData();
@@ -201,8 +191,7 @@ function _toURLSearchParams(options) {
201
191
  }
202
192
  function __debounce(timeout, id) {
203
193
  return new Promise(resolve => {
204
- var _this$id;
205
- if ((_this$id = this[id]) !== null && _this$id !== void 0 && _this$id.timerId) clearTimeout(this[id].timerId);
194
+ if (this[id]?.timerId) clearTimeout(this[id].timerId);
206
195
  const timerId = setTimeout(() => resolve(), timeout);
207
196
  if (this[id]) {
208
197
  this[id].timerId = timerId;
@@ -213,11 +202,11 @@ function __debounce(timeout, id) {
213
202
  }
214
203
  const _debounce = __debounce.bind({});
215
204
  const _extractValue = (e, unknown) => {
216
- if (e !== null && e !== void 0 && e.target) {
205
+ if (e?.target) {
217
206
  if (Object.hasOwn(typeValueDict, e.target.type)) return e.target[typeValueDict[e.target.type]];
218
207
  return e.target.value;
219
208
  }
220
- return (e === null || e === void 0 ? void 0 : e.value) || (isObject(unknown) ? unknown.value : unknown);
209
+ return e?.value || (isObject(unknown) ? unknown.value : unknown);
221
210
  };
222
211
  const _checkResult = (handlerResult, value) => typeof handlerResult === 'boolean' ? handlerResult : typeof value === 'string' ? typeof handlerResult === 'string' ? !new RegExp(handlerResult).test(value) : !handlerResult.test(value) : false;
223
212
  const _merge = (target = {}, ...nodes) => {
@@ -303,26 +292,21 @@ class GValidator {
303
292
  return this._asyncHandlers;
304
293
  }
305
294
  constructor(baseValidator) {
306
- _defineProperty(this, "_handlers", void 0);
307
- _defineProperty(this, "_constraintHandlers", void 0);
308
- _defineProperty(this, "_asyncHandlers", void 0);
309
- _defineProperty(this, "track", void 0);
310
- const baseHandlers = (baseValidator === null || baseValidator === void 0 ? void 0 : baseValidator.handlers) || [];
311
- const baseConstraintHandlers = (baseValidator === null || baseValidator === void 0 ? void 0 : baseValidator.constraintHandlers) || [];
312
- const baseHandlersAsync = (baseValidator === null || baseValidator === void 0 ? void 0 : baseValidator.asyncHandlers) || [];
295
+ const baseHandlers = baseValidator?.handlers || [];
296
+ const baseConstraintHandlers = baseValidator?.constraintHandlers || [];
297
+ const baseHandlersAsync = baseValidator?.asyncHandlers || [];
313
298
  this._handlers = [].concat(baseHandlers);
314
299
  this._constraintHandlers = [].concat(baseConstraintHandlers);
315
300
  this._asyncHandlers = [].concat(baseHandlersAsync);
316
301
  {
317
302
  this.track = [];
318
- if (baseValidator !== null && baseValidator !== void 0 && baseValidator.track) {
303
+ if (baseValidator?.track) {
319
304
  this.track = this.track.concat(baseValidator.track);
320
305
  }
321
306
  }
322
307
  }
323
308
  hasConstraint(constraint) {
324
- var _this$track;
325
- return ((_this$track = this.track) === null || _this$track === void 0 ? void 0 : _this$track.includes(constraint)) || false;
309
+ return this.track?.includes(constraint) || false;
326
310
  }
327
311
  withRequiredMessage(message) {
328
312
  return this.__addConstraintValidationHandler('valueMissing', message);
@@ -432,7 +416,7 @@ const useFormHandlers = (getState, setState, validators = {}, optimized = false)
432
416
  const _validateInput = (input, validityKey, setValidity) => {
433
417
  const inputValidator = validators[input.validatorKey || input.formKey] || validators['*'];
434
418
  {
435
- if (validityKey && !(inputValidator !== null && inputValidator !== void 0 && inputValidator.hasConstraint(validityKey))) {
419
+ if (validityKey && !inputValidator?.hasConstraint(validityKey)) {
436
420
  if (validityKey === 'typeMismatch') console.warn(`DEV ONLY - [Missing Validator] - the input '${input.formKey}' has described the constraint '${validityMap[validityKey]}' however, a correspond validator/custom validation/pattern validator is missing.\nadd '${handlersMap[validityMap[validityKey]]}' or 'withCustomValidation' or '${handlersMap[validityMap.patternMismatch]}' to the input validator.\nexample:\nconst validators: GValidators = {\n\temail: new GValidator().withPatternMismatchMessage('pattern mismatch'),\n\t...\n}\n\nor either remove the constraint '${validityMap[validityKey]}' from the input props`);else console.warn(`DEV ONLY - [Missing Validator] - the input '${input.formKey}' has described the constraint '${validityMap[validityKey]}' however, a correspond validator is missing.\nadd '${handlersMap[validityMap[validityKey]]}' to the input validator.\nexample:\nconst validators: GValidators = {\n\temail: new GValidator().withPatternMismatchMessage('pattern mismatch'),\n\t...\n}\n\nor either remove the constraint '${validityMap[validityKey]}' from the input props`);
437
421
  }
438
422
  }