@sio-group/form-react 0.2.0 → 0.4.0

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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - fix bug in component
8
+
9
+ ## 0.3.0
10
+
11
+ ### Minor Changes
12
+
13
+ - 370b198: Update render method to render buttons outside of container
14
+
3
15
  ## 0.2.0
4
16
 
5
17
  ### Minor Changes
package/dist/index.cjs CHANGED
@@ -75,264 +75,11 @@ var slugify = (string, separator = "_") => {
75
75
  return string.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase().trim().replace(/[^a-z0-9 ]/g, "").replace(/\s+/g, separator);
76
76
  };
77
77
 
78
- // ../form-validation/dist/index.js
79
- var isRequired = (errorMessage) => (val, label = "Dit") => {
80
- const message = errorMessage?.replace("{label}", label) || `${label} is een verplicht veld.`;
81
- if (val === null || val === void 0) {
82
- return message;
83
- }
84
- if (typeof val === "string" && val.trim().length === 0) {
85
- return message;
86
- }
87
- if (typeof val === "boolean" && !val) {
88
- return message;
89
- }
90
- if (Array.isArray(val) && val.length === 0) {
91
- return message;
92
- }
93
- return null;
94
- };
95
- var isEmail = (errorMessage) => (val, label = "Dit") => {
96
- if (val === null || val === void 0) {
97
- return null;
98
- }
99
- if (typeof val !== "string") {
100
- return errorMessage || `${label} is geen geldig e-mailadres.`;
101
- }
102
- const trimmed = val.trim();
103
- if (trimmed.length === 0) {
104
- return null;
105
- }
106
- const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/;
107
- return emailRegex.test(trimmed) ? null : errorMessage || `${label} is geen geldig e-mailadres.`;
108
- };
109
- var isUrl = (allowLocalhost = false, allowFtp = false, secureOnly = true) => (val, label = "Dit") => {
110
- if (val === null || val === void 0) {
111
- return null;
112
- }
113
- if (typeof val !== "string") {
114
- return `${label} is geen geldige URL.`;
115
- }
116
- const trimmed = val.trim();
117
- if (trimmed.length === 0) {
118
- return null;
119
- }
120
- try {
121
- const url = new URL(trimmed);
122
- if (secureOnly && url.protocol !== "https:") {
123
- return `${label} moet https gebruiken.`;
124
- }
125
- if (!allowFtp && url.protocol === "ftp") {
126
- return `${label} mag geen ftp gebruiken.`;
127
- }
128
- if (!allowLocalhost && (url.hostname === "localhost" || url.hostname === "127.0.0.1")) {
129
- return `${label} mag geen localhost zijn.`;
130
- }
131
- return null;
132
- } catch {
133
- return `${label} is geen geldige URL.`;
134
- }
135
- };
136
- var isBiggerThan = (min, errorMessage) => (val, label = "Dit") => {
137
- if (val === null || val === void 0 || val === "") {
138
- return null;
139
- }
140
- const num = Number(val);
141
- if (Number.isNaN(num)) {
142
- return `${label} moet een geldig getal zijn.`;
143
- }
144
- return min <= num ? null : errorMessage?.replace("{label}", label)?.replace("{min}", min.toString()) || `${label} mag niet kleiner zijn dan ${min}.`;
145
- };
146
- var isSmallerThan = (max, errorMessage) => (val, label = "Dit") => {
147
- if (val === null || val === void 0 || val === "") {
148
- return null;
149
- }
150
- const num = Number(val);
151
- if (Number.isNaN(num)) {
152
- return `${label} moet een geldig getal zijn.`;
153
- }
154
- return num <= max ? null : errorMessage?.replace("{label}", label)?.replace("{max}", max.toString()) || `${label} mag niet groter zijn dan ${max}.`;
155
- };
156
- var parseDateValue = (val) => {
157
- if (val instanceof Date) {
158
- return {
159
- type: hasExplicitTime(val) ? "datetime" : "date",
160
- value: isNaN(val.getTime()) ? null : val
161
- };
162
- }
163
- if (typeof val !== "string") {
164
- return { type: "invalid", value: null };
165
- }
166
- const trimmed = val.trim();
167
- if (trimmed === "") {
168
- return { type: "invalid", value: null };
169
- }
170
- const timeRegex = /^([0-1]?[0-9]|2[0-3]):[0-5][0-9](:[0-5][0-9])?$/;
171
- if (timeRegex.test(trimmed)) {
172
- const [hours, minutes, seconds = 0] = trimmed.split(":").map(Number);
173
- const date = /* @__PURE__ */ new Date();
174
- date.setHours(hours, minutes, seconds, 0);
175
- return { type: "time", value: date };
176
- }
177
- const dateRegex = /^\d{4}-\d{2}-\d{2}$/;
178
- if (dateRegex.test(trimmed)) {
179
- const date = /* @__PURE__ */ new Date(trimmed + "T00:00:00.000Z");
180
- return {
181
- type: "date",
182
- value: isNaN(date.getTime()) ? null : date
183
- };
184
- }
185
- const dateTimeRegex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/;
186
- if (dateTimeRegex.test(trimmed)) {
187
- const date = /* @__PURE__ */ new Date(trimmed + ".000Z");
188
- return {
189
- type: "datetime",
190
- value: isNaN(date.getTime()) ? null : date
191
- };
192
- }
193
- return { type: "invalid", value: null };
194
- };
195
- function hasExplicitTime(date) {
196
- return date.getUTCHours() !== 0 || date.getUTCMinutes() !== 0 || date.getUTCSeconds() !== 0 || date.getUTCMilliseconds() !== 0;
197
- }
198
- var dateIsBiggerThan = (min, errorMessage) => (val, label = "Dit") => {
199
- if (val === null || val === void 0 || val === "") {
200
- return null;
201
- }
202
- const parsed = parseDateValue(val);
203
- if (!parsed.value) {
204
- return `${label} moet een geldige ${parsed.type === "time" ? "tijd" : "datum"} zijn.`;
205
- }
206
- let formattedMin;
207
- switch (parsed.type) {
208
- case "time":
209
- formattedMin = min.toLocaleTimeString("nl-NL", {
210
- hour: "2-digit",
211
- minute: "2-digit",
212
- hour12: false,
213
- timeZone: "UTC"
214
- });
215
- break;
216
- case "date":
217
- formattedMin = min.toLocaleDateString("nl-NL", { timeZone: "UTC" });
218
- break;
219
- case "datetime":
220
- formattedMin = min.toLocaleString("nl-NL", {
221
- year: "numeric",
222
- month: "2-digit",
223
- day: "2-digit",
224
- hour: "2-digit",
225
- minute: "2-digit",
226
- hour12: false,
227
- timeZone: "UTC"
228
- });
229
- break;
230
- default:
231
- formattedMin = min.toLocaleDateString("nl-NL", { timeZone: "UTC" });
232
- }
233
- if (parsed.type === "time") {
234
- const timeValue = parsed.value.getHours() * 60 + parsed.value.getMinutes();
235
- const minTime = min.getHours() * 60 + min.getMinutes();
236
- return timeValue >= minTime ? null : errorMessage?.replace("{label}", label)?.replace("{min}", formattedMin) || `${label} mag niet voor ${formattedMin} zijn.`;
237
- }
238
- return min.getTime() <= parsed.value.getTime() ? null : errorMessage?.replace("{label}", label)?.replace("{min}", formattedMin) || `${label} mag niet voor ${formattedMin} zijn.`;
239
- };
240
- var dateIsSmallerThan = (max, errorMessage) => (val, label = "Dit") => {
241
- if (val === null || val === void 0 || val === "") {
242
- return null;
243
- }
244
- const parsed = parseDateValue(val);
245
- if (!parsed.value) {
246
- return `${label} moet een geldige ${parsed.type === "time" ? "tijd" : "datum"} zijn.`;
247
- }
248
- let formattedMax;
249
- switch (parsed.type) {
250
- case "time":
251
- formattedMax = max.toLocaleTimeString("nl-NL", {
252
- hour: "2-digit",
253
- minute: "2-digit",
254
- hour12: false,
255
- timeZone: "UTC"
256
- });
257
- break;
258
- case "date":
259
- formattedMax = max.toLocaleDateString("nl-NL", { timeZone: "UTC" });
260
- break;
261
- case "datetime":
262
- formattedMax = max.toLocaleString("nl-NL", {
263
- year: "numeric",
264
- month: "2-digit",
265
- day: "2-digit",
266
- hour: "2-digit",
267
- minute: "2-digit",
268
- hour12: false,
269
- timeZone: "UTC"
270
- });
271
- break;
272
- default:
273
- formattedMax = max.toLocaleDateString("nl-NL", { timeZone: "UTC" });
274
- }
275
- if (parsed.type === "time") {
276
- const timeValue = parsed.value.getHours() * 60 + parsed.value.getMinutes();
277
- const macTime = max.getHours() * 60 + max.getMinutes();
278
- return macTime >= timeValue ? null : errorMessage?.replace("{label}", label)?.replace("{min}", formattedMax) || `${label} mag niet na ${formattedMax} zijn.`;
279
- }
280
- return parsed.value.getTime() <= max.getTime() ? null : errorMessage?.replace("{label}", label)?.replace("{min}", formattedMax) || `${label} mag niet na ${formattedMax} zijn.`;
281
- };
282
- var isValidFile = (maxSize, accept) => (file) => {
283
- if (!file) {
284
- return null;
285
- }
286
- if (maxSize && file.size / 1024 > maxSize) {
287
- return `${file.name} is te groot (max ${maxSize} KB).`;
288
- }
289
- if (accept) {
290
- const allowed = accept.split(",").map((s) => s.trim().toLowerCase());
291
- const ext = `.${file.name.split(".").pop()?.toLowerCase()}`;
292
- const mime = file.type.toLowerCase();
293
- const valid = allowed.some((pattern) => {
294
- if (pattern === mime) return true;
295
- if (pattern.endsWith("/*")) {
296
- return mime.startsWith(pattern.replace("/*", "/"));
297
- }
298
- return pattern === ext;
299
- });
300
- if (!valid) {
301
- return `${file.name} is niet toegelaten.`;
302
- }
303
- }
304
- return null;
305
- };
306
- var isPattern = (pattern, errorMsg) => (val, label = "Dit") => {
307
- if (val === null || val === void 0 || val === "") {
308
- return null;
309
- }
310
- if (typeof val !== "string") {
311
- return errorMsg || `${label} heeft een ongeldig patroon.`;
312
- }
313
- const trimmed = val.trim();
314
- if (trimmed === "") {
315
- return null;
316
- }
317
- let regex;
318
- if (typeof pattern === "string") {
319
- if (pattern.startsWith("/") && pattern.lastIndexOf("/") > 0) {
320
- const lastSlash = pattern.lastIndexOf("/");
321
- const patternBody = pattern.substring(1, lastSlash);
322
- const flags = pattern.substring(lastSlash + 1);
323
- const safeFlags = flags.replace("g", "");
324
- regex = new RegExp(patternBody, safeFlags);
325
- } else {
326
- regex = new RegExp(pattern);
327
- }
328
- } else {
329
- regex = new RegExp(pattern.source, pattern.flags.replace("g", ""));
330
- }
331
- return regex.test(trimmed) ? null : errorMsg || `${label} heeft een ongeldig patroon.`;
332
- };
78
+ // src/utils/create-field-state.ts
79
+ var import_form_validation = require("@sio-group/form-validation");
333
80
 
334
81
  // src/utils/parse-date.ts
335
- var parseDateValue2 = (val) => {
82
+ var parseDateValue = (val) => {
336
83
  if (val instanceof Date) {
337
84
  return isNaN(val.getTime()) ? null : val;
338
85
  }
@@ -402,31 +149,31 @@ function getDefaultValue(config) {
402
149
  function getDefaultValidations(config) {
403
150
  const validations = [];
404
151
  if (config.config?.required) {
405
- validations.push(isRequired());
152
+ validations.push((0, import_form_validation.isRequired)());
406
153
  }
407
154
  switch (config.type) {
408
155
  case "email":
409
- validations.push(isEmail());
156
+ validations.push((0, import_form_validation.isEmail)());
410
157
  break;
411
158
  case "number":
412
159
  case "range":
413
- if (config.config?.min) validations.push(isBiggerThan(config.config?.min));
414
- if (config.config?.max) validations.push(isSmallerThan(config.config?.max));
160
+ if (config.config?.min) validations.push((0, import_form_validation.isBiggerThan)(config.config?.min));
161
+ if (config.config?.max) validations.push((0, import_form_validation.isSmallerThan)(config.config?.max));
415
162
  break;
416
163
  case "date":
417
164
  case "datetime-local":
418
165
  case "time":
419
166
  const min = config.config?.min;
420
167
  const max = config.config?.max;
421
- const parsedMin = parseDateValue2(min);
422
- const parsedMax = parseDateValue2(max);
423
- if (parsedMin) validations.push(dateIsBiggerThan(parsedMin));
424
- if (parsedMax) validations.push(dateIsSmallerThan(parsedMax));
168
+ const parsedMin = parseDateValue(min);
169
+ const parsedMax = parseDateValue(max);
170
+ if (parsedMin) validations.push((0, import_form_validation.dateIsBiggerThan)(parsedMin));
171
+ if (parsedMax) validations.push((0, import_form_validation.dateIsSmallerThan)(parsedMax));
425
172
  break;
426
173
  case "url":
427
- if (config.config?.pattern) validations.push(isPattern(config.config.pattern));
174
+ if (config.config?.pattern) validations.push((0, import_form_validation.isPattern)(config.config.pattern));
428
175
  validations.push(
429
- isUrl(
176
+ (0, import_form_validation.isUrl)(
430
177
  config.config?.allowLocalhost || false,
431
178
  config.config?.allowFtp || false,
432
179
  config.config?.secureOnly || !(config.config?.allowLocalhost || config.config?.allowFtp)
@@ -435,7 +182,7 @@ function getDefaultValidations(config) {
435
182
  break;
436
183
  case "text":
437
184
  case "tel":
438
- if (config.config?.pattern) validations.push(isPattern(config.config.pattern));
185
+ if (config.config?.pattern) validations.push((0, import_form_validation.isPattern)(config.config.pattern));
439
186
  break;
440
187
  }
441
188
  return validations;
@@ -1368,6 +1115,9 @@ var DateInput = ({
1368
1115
  );
1369
1116
  };
1370
1117
 
1118
+ // src/components/Fields/Input/FileInput/index.tsx
1119
+ var import_form_validation2 = require("@sio-group/form-validation");
1120
+
1371
1121
  // src/utils/get-accept-string.ts
1372
1122
  var getAccept = (accept) => {
1373
1123
  if (Array.isArray(accept)) {
@@ -1498,7 +1248,7 @@ var FileInput = ({
1498
1248
  };
1499
1249
  const handleChange = (e) => {
1500
1250
  const files = Array.from(e.target.files ?? []);
1501
- const validator = isValidFile(filesize, getAccept(accept));
1251
+ const validator = (0, import_form_validation2.isValidFile)(filesize, getAccept(accept));
1502
1252
  let fileList = [...currentFiles];
1503
1253
  const errorList = [];
1504
1254
  for (let file of files) {
@@ -2026,7 +1776,7 @@ var Link = import_react7.default.memo(LinkComponent);
2026
1776
  // src/components/Form.tsx
2027
1777
  var import_jsx_runtime16 = require("react/jsx-runtime");
2028
1778
  var import_react9 = require("react");
2029
- var DefaultContainer = ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("form", { ...props, noValidate: true, children });
1779
+ var DefaultContainer = ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { children });
2030
1780
  var DefaultButtonContainer = ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "btn-group", children });
2031
1781
  var Form = ({
2032
1782
  fields,
@@ -2145,8 +1895,8 @@ var Form = ({
2145
1895
  buttons?.map(renderButton)
2146
1896
  ] }) : null;
2147
1897
  };
2148
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Container, { className, style, noValidate: true, children: [
2149
- renderFields(),
1898
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("form", { className, style, noValidate: true, children: [
1899
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Container, { children: renderFields() }),
2150
1900
  renderButtons()
2151
1901
  ] });
2152
1902
  };
package/dist/index.d.cts CHANGED
@@ -1,8 +1,8 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import React, { CSSProperties, ComponentType, ComponentPropsWithoutRef, HTMLAttributes } from 'react';
3
- import { LayoutType, FormField, IconType, AcceptType, CaptureType, SpinnerVariant, SelectOption, Option, FieldConfigMap } from '@sio/form-types';
3
+ import { LayoutType, FormField, IconType, AcceptType, CaptureType, SpinnerVariant, SelectOption, Option, FieldConfigMap } from '@sio-group/form-types';
4
4
  import { Properties } from 'csstype';
5
- import { ValidationRule } from '@sio/form-types/src/core/valudation-rule';
5
+ import { ValidationRule } from '@sio-group/form-types/src/core/valudation-rule';
6
6
 
7
7
  interface FormLayout {
8
8
  fields: string[];
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import React, { CSSProperties, ComponentType, ComponentPropsWithoutRef, HTMLAttributes } from 'react';
3
- import { LayoutType, FormField, IconType, AcceptType, CaptureType, SpinnerVariant, SelectOption, Option, FieldConfigMap } from '@sio/form-types';
3
+ import { LayoutType, FormField, IconType, AcceptType, CaptureType, SpinnerVariant, SelectOption, Option, FieldConfigMap } from '@sio-group/form-types';
4
4
  import { Properties } from 'csstype';
5
- import { ValidationRule } from '@sio/form-types/src/core/valudation-rule';
5
+ import { ValidationRule } from '@sio-group/form-types/src/core/valudation-rule';
6
6
 
7
7
  interface FormLayout {
8
8
  fields: string[];
package/dist/index.js CHANGED
@@ -26,264 +26,20 @@ var slugify = (string, separator = "_") => {
26
26
  return string.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase().trim().replace(/[^a-z0-9 ]/g, "").replace(/\s+/g, separator);
27
27
  };
28
28
 
29
- // ../form-validation/dist/index.js
30
- var isRequired = (errorMessage) => (val, label = "Dit") => {
31
- const message = errorMessage?.replace("{label}", label) || `${label} is een verplicht veld.`;
32
- if (val === null || val === void 0) {
33
- return message;
34
- }
35
- if (typeof val === "string" && val.trim().length === 0) {
36
- return message;
37
- }
38
- if (typeof val === "boolean" && !val) {
39
- return message;
40
- }
41
- if (Array.isArray(val) && val.length === 0) {
42
- return message;
43
- }
44
- return null;
45
- };
46
- var isEmail = (errorMessage) => (val, label = "Dit") => {
47
- if (val === null || val === void 0) {
48
- return null;
49
- }
50
- if (typeof val !== "string") {
51
- return errorMessage || `${label} is geen geldig e-mailadres.`;
52
- }
53
- const trimmed = val.trim();
54
- if (trimmed.length === 0) {
55
- return null;
56
- }
57
- const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/;
58
- return emailRegex.test(trimmed) ? null : errorMessage || `${label} is geen geldig e-mailadres.`;
59
- };
60
- var isUrl = (allowLocalhost = false, allowFtp = false, secureOnly = true) => (val, label = "Dit") => {
61
- if (val === null || val === void 0) {
62
- return null;
63
- }
64
- if (typeof val !== "string") {
65
- return `${label} is geen geldige URL.`;
66
- }
67
- const trimmed = val.trim();
68
- if (trimmed.length === 0) {
69
- return null;
70
- }
71
- try {
72
- const url = new URL(trimmed);
73
- if (secureOnly && url.protocol !== "https:") {
74
- return `${label} moet https gebruiken.`;
75
- }
76
- if (!allowFtp && url.protocol === "ftp") {
77
- return `${label} mag geen ftp gebruiken.`;
78
- }
79
- if (!allowLocalhost && (url.hostname === "localhost" || url.hostname === "127.0.0.1")) {
80
- return `${label} mag geen localhost zijn.`;
81
- }
82
- return null;
83
- } catch {
84
- return `${label} is geen geldige URL.`;
85
- }
86
- };
87
- var isBiggerThan = (min, errorMessage) => (val, label = "Dit") => {
88
- if (val === null || val === void 0 || val === "") {
89
- return null;
90
- }
91
- const num = Number(val);
92
- if (Number.isNaN(num)) {
93
- return `${label} moet een geldig getal zijn.`;
94
- }
95
- return min <= num ? null : errorMessage?.replace("{label}", label)?.replace("{min}", min.toString()) || `${label} mag niet kleiner zijn dan ${min}.`;
96
- };
97
- var isSmallerThan = (max, errorMessage) => (val, label = "Dit") => {
98
- if (val === null || val === void 0 || val === "") {
99
- return null;
100
- }
101
- const num = Number(val);
102
- if (Number.isNaN(num)) {
103
- return `${label} moet een geldig getal zijn.`;
104
- }
105
- return num <= max ? null : errorMessage?.replace("{label}", label)?.replace("{max}", max.toString()) || `${label} mag niet groter zijn dan ${max}.`;
106
- };
107
- var parseDateValue = (val) => {
108
- if (val instanceof Date) {
109
- return {
110
- type: hasExplicitTime(val) ? "datetime" : "date",
111
- value: isNaN(val.getTime()) ? null : val
112
- };
113
- }
114
- if (typeof val !== "string") {
115
- return { type: "invalid", value: null };
116
- }
117
- const trimmed = val.trim();
118
- if (trimmed === "") {
119
- return { type: "invalid", value: null };
120
- }
121
- const timeRegex = /^([0-1]?[0-9]|2[0-3]):[0-5][0-9](:[0-5][0-9])?$/;
122
- if (timeRegex.test(trimmed)) {
123
- const [hours, minutes, seconds = 0] = trimmed.split(":").map(Number);
124
- const date = /* @__PURE__ */ new Date();
125
- date.setHours(hours, minutes, seconds, 0);
126
- return { type: "time", value: date };
127
- }
128
- const dateRegex = /^\d{4}-\d{2}-\d{2}$/;
129
- if (dateRegex.test(trimmed)) {
130
- const date = /* @__PURE__ */ new Date(trimmed + "T00:00:00.000Z");
131
- return {
132
- type: "date",
133
- value: isNaN(date.getTime()) ? null : date
134
- };
135
- }
136
- const dateTimeRegex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/;
137
- if (dateTimeRegex.test(trimmed)) {
138
- const date = /* @__PURE__ */ new Date(trimmed + ".000Z");
139
- return {
140
- type: "datetime",
141
- value: isNaN(date.getTime()) ? null : date
142
- };
143
- }
144
- return { type: "invalid", value: null };
145
- };
146
- function hasExplicitTime(date) {
147
- return date.getUTCHours() !== 0 || date.getUTCMinutes() !== 0 || date.getUTCSeconds() !== 0 || date.getUTCMilliseconds() !== 0;
148
- }
149
- var dateIsBiggerThan = (min, errorMessage) => (val, label = "Dit") => {
150
- if (val === null || val === void 0 || val === "") {
151
- return null;
152
- }
153
- const parsed = parseDateValue(val);
154
- if (!parsed.value) {
155
- return `${label} moet een geldige ${parsed.type === "time" ? "tijd" : "datum"} zijn.`;
156
- }
157
- let formattedMin;
158
- switch (parsed.type) {
159
- case "time":
160
- formattedMin = min.toLocaleTimeString("nl-NL", {
161
- hour: "2-digit",
162
- minute: "2-digit",
163
- hour12: false,
164
- timeZone: "UTC"
165
- });
166
- break;
167
- case "date":
168
- formattedMin = min.toLocaleDateString("nl-NL", { timeZone: "UTC" });
169
- break;
170
- case "datetime":
171
- formattedMin = min.toLocaleString("nl-NL", {
172
- year: "numeric",
173
- month: "2-digit",
174
- day: "2-digit",
175
- hour: "2-digit",
176
- minute: "2-digit",
177
- hour12: false,
178
- timeZone: "UTC"
179
- });
180
- break;
181
- default:
182
- formattedMin = min.toLocaleDateString("nl-NL", { timeZone: "UTC" });
183
- }
184
- if (parsed.type === "time") {
185
- const timeValue = parsed.value.getHours() * 60 + parsed.value.getMinutes();
186
- const minTime = min.getHours() * 60 + min.getMinutes();
187
- return timeValue >= minTime ? null : errorMessage?.replace("{label}", label)?.replace("{min}", formattedMin) || `${label} mag niet voor ${formattedMin} zijn.`;
188
- }
189
- return min.getTime() <= parsed.value.getTime() ? null : errorMessage?.replace("{label}", label)?.replace("{min}", formattedMin) || `${label} mag niet voor ${formattedMin} zijn.`;
190
- };
191
- var dateIsSmallerThan = (max, errorMessage) => (val, label = "Dit") => {
192
- if (val === null || val === void 0 || val === "") {
193
- return null;
194
- }
195
- const parsed = parseDateValue(val);
196
- if (!parsed.value) {
197
- return `${label} moet een geldige ${parsed.type === "time" ? "tijd" : "datum"} zijn.`;
198
- }
199
- let formattedMax;
200
- switch (parsed.type) {
201
- case "time":
202
- formattedMax = max.toLocaleTimeString("nl-NL", {
203
- hour: "2-digit",
204
- minute: "2-digit",
205
- hour12: false,
206
- timeZone: "UTC"
207
- });
208
- break;
209
- case "date":
210
- formattedMax = max.toLocaleDateString("nl-NL", { timeZone: "UTC" });
211
- break;
212
- case "datetime":
213
- formattedMax = max.toLocaleString("nl-NL", {
214
- year: "numeric",
215
- month: "2-digit",
216
- day: "2-digit",
217
- hour: "2-digit",
218
- minute: "2-digit",
219
- hour12: false,
220
- timeZone: "UTC"
221
- });
222
- break;
223
- default:
224
- formattedMax = max.toLocaleDateString("nl-NL", { timeZone: "UTC" });
225
- }
226
- if (parsed.type === "time") {
227
- const timeValue = parsed.value.getHours() * 60 + parsed.value.getMinutes();
228
- const macTime = max.getHours() * 60 + max.getMinutes();
229
- return macTime >= timeValue ? null : errorMessage?.replace("{label}", label)?.replace("{min}", formattedMax) || `${label} mag niet na ${formattedMax} zijn.`;
230
- }
231
- return parsed.value.getTime() <= max.getTime() ? null : errorMessage?.replace("{label}", label)?.replace("{min}", formattedMax) || `${label} mag niet na ${formattedMax} zijn.`;
232
- };
233
- var isValidFile = (maxSize, accept) => (file) => {
234
- if (!file) {
235
- return null;
236
- }
237
- if (maxSize && file.size / 1024 > maxSize) {
238
- return `${file.name} is te groot (max ${maxSize} KB).`;
239
- }
240
- if (accept) {
241
- const allowed = accept.split(",").map((s) => s.trim().toLowerCase());
242
- const ext = `.${file.name.split(".").pop()?.toLowerCase()}`;
243
- const mime = file.type.toLowerCase();
244
- const valid = allowed.some((pattern) => {
245
- if (pattern === mime) return true;
246
- if (pattern.endsWith("/*")) {
247
- return mime.startsWith(pattern.replace("/*", "/"));
248
- }
249
- return pattern === ext;
250
- });
251
- if (!valid) {
252
- return `${file.name} is niet toegelaten.`;
253
- }
254
- }
255
- return null;
256
- };
257
- var isPattern = (pattern, errorMsg) => (val, label = "Dit") => {
258
- if (val === null || val === void 0 || val === "") {
259
- return null;
260
- }
261
- if (typeof val !== "string") {
262
- return errorMsg || `${label} heeft een ongeldig patroon.`;
263
- }
264
- const trimmed = val.trim();
265
- if (trimmed === "") {
266
- return null;
267
- }
268
- let regex;
269
- if (typeof pattern === "string") {
270
- if (pattern.startsWith("/") && pattern.lastIndexOf("/") > 0) {
271
- const lastSlash = pattern.lastIndexOf("/");
272
- const patternBody = pattern.substring(1, lastSlash);
273
- const flags = pattern.substring(lastSlash + 1);
274
- const safeFlags = flags.replace("g", "");
275
- regex = new RegExp(patternBody, safeFlags);
276
- } else {
277
- regex = new RegExp(pattern);
278
- }
279
- } else {
280
- regex = new RegExp(pattern.source, pattern.flags.replace("g", ""));
281
- }
282
- return regex.test(trimmed) ? null : errorMsg || `${label} heeft een ongeldig patroon.`;
283
- };
29
+ // src/utils/create-field-state.ts
30
+ import {
31
+ dateIsBiggerThan,
32
+ dateIsSmallerThan,
33
+ isBiggerThan,
34
+ isEmail,
35
+ isPattern,
36
+ isRequired,
37
+ isSmallerThan,
38
+ isUrl
39
+ } from "@sio-group/form-validation";
284
40
 
285
41
  // src/utils/parse-date.ts
286
- var parseDateValue2 = (val) => {
42
+ var parseDateValue = (val) => {
287
43
  if (val instanceof Date) {
288
44
  return isNaN(val.getTime()) ? null : val;
289
45
  }
@@ -369,8 +125,8 @@ function getDefaultValidations(config) {
369
125
  case "time":
370
126
  const min = config.config?.min;
371
127
  const max = config.config?.max;
372
- const parsedMin = parseDateValue2(min);
373
- const parsedMax = parseDateValue2(max);
128
+ const parsedMin = parseDateValue(min);
129
+ const parsedMax = parseDateValue(max);
374
130
  if (parsedMin) validations.push(dateIsBiggerThan(parsedMin));
375
131
  if (parsedMax) validations.push(dateIsSmallerThan(parsedMax));
376
132
  break;
@@ -1319,6 +1075,9 @@ var DateInput = ({
1319
1075
  );
1320
1076
  };
1321
1077
 
1078
+ // src/components/Fields/Input/FileInput/index.tsx
1079
+ import { isValidFile } from "@sio-group/form-validation";
1080
+
1322
1081
  // src/utils/get-accept-string.ts
1323
1082
  var getAccept = (accept) => {
1324
1083
  if (Array.isArray(accept)) {
@@ -1977,7 +1736,7 @@ var Link = React4.memo(LinkComponent);
1977
1736
  // src/components/Form.tsx
1978
1737
  import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
1979
1738
  import { createElement } from "react";
1980
- var DefaultContainer = ({ children, ...props }) => /* @__PURE__ */ jsx16("form", { ...props, noValidate: true, children });
1739
+ var DefaultContainer = ({ children }) => /* @__PURE__ */ jsx16("div", { children });
1981
1740
  var DefaultButtonContainer = ({ children }) => /* @__PURE__ */ jsx16("div", { className: "btn-group", children });
1982
1741
  var Form = ({
1983
1742
  fields,
@@ -2096,8 +1855,8 @@ var Form = ({
2096
1855
  buttons?.map(renderButton)
2097
1856
  ] }) : null;
2098
1857
  };
2099
- return /* @__PURE__ */ jsxs14(Container, { className, style, noValidate: true, children: [
2100
- renderFields(),
1858
+ return /* @__PURE__ */ jsxs14("form", { className, style, noValidate: true, children: [
1859
+ /* @__PURE__ */ jsx16(Container, { children: renderFields() }),
2101
1860
  renderButtons()
2102
1861
  ] });
2103
1862
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sio-group/form-react",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -8,8 +8,8 @@ import { Checkbox, Input, Radio, Select, Textarea } from "./Fields";
8
8
  import { Link } from "./Link";
9
9
  import { Button } from "./Button";
10
10
 
11
- const DefaultContainer: React.FC<FormContainerProps> = ({ children, ...props }) => (
12
- <form {...props} noValidate>{children}</form>
11
+ const DefaultContainer: React.FC<FormContainerProps> = ({ children }) => (
12
+ <div>{children}</div>
13
13
  );
14
14
 
15
15
  const DefaultButtonContainer: React.FC<ButtonContainerProps> = ({ children }) => (
@@ -155,9 +155,11 @@ export const Form = ({
155
155
  };
156
156
 
157
157
  return (
158
- <Container className={className} style={style} noValidate>
159
- {renderFields()}
158
+ <form className={className} style={style} noValidate>
159
+ <Container>
160
+ {renderFields()}
161
+ </Container>
160
162
  {renderButtons()}
161
- </Container>
163
+ </form>
162
164
  );
163
165
  }
@@ -1 +1 @@
1
- {"root":["./src/index.ts","./src/hooks/useconnectionstatus.ts","./src/hooks/useform.ts","./src/types/field-props.d.ts","./src/types/field-setters.d.ts","./src/types/field-state.d.ts","./src/types/form-config.d.ts","./src/types/form-layout.d.ts","./src/types/index.ts","./src/types/ui-props.d.ts","./src/types/use-form-options.d.ts","./src/utils/create-field-props.ts","./src/utils/create-field-state.ts","./src/utils/file-type-icon.ts","./src/utils/get-accept-string.ts","./src/utils/get-column-classes.ts","./src/utils/get-file-size.ts","./src/utils/parse-date.ts","./src/utils/slugify.ts","./src/components/form.tsx","./src/components/button/index.tsx","./src/components/fields/index.tsx","./src/components/fields/checkbox/index.tsx","./src/components/fields/input/input.tsx","./src/components/fields/input/dateinput/index.tsx","./src/components/fields/input/fileinput/index.tsx","./src/components/fields/input/numberinput/index.tsx","./src/components/fields/input/rangeinput/index.tsx","./src/components/fields/input/textinput/index.tsx","./src/components/fields/inputwrapper/index.tsx","./src/components/fields/radio/index.tsx","./src/components/fields/select/index.tsx","./src/components/fields/textarea/index.tsx","./src/components/icon/index.tsx","./src/components/link/index.tsx","./src/utils/custom-icons.tsx"],"version":"5.9.3"}
1
+ {"root":["./src/index.ts","./src/hooks/useconnectionstatus.ts","./src/hooks/useform.ts","./src/types/field-props.d.ts","./src/types/field-setters.d.ts","./src/types/field-state.d.ts","./src/types/form-config.d.ts","./src/types/form-layout.d.ts","./src/types/index.ts","./src/types/ui-props.d.ts","./src/types/use-form-options.d.ts","./src/utils/create-field-props.ts","./src/utils/create-field-state.ts","./src/utils/file-type-icon.ts","./src/utils/get-accept-string.ts","./src/utils/get-column-classes.ts","./src/utils/get-file-size.ts","./src/utils/parse-date.ts","./src/utils/slugify.ts","./src/components/form.tsx","./src/components/button/index.tsx","./src/components/fields/index.tsx","./src/components/fields/checkbox/index.tsx","./src/components/fields/input/input.tsx","./src/components/fields/input/dateinput/index.tsx","./src/components/fields/input/fileinput/index.tsx","./src/components/fields/input/numberinput/index.tsx","./src/components/fields/input/rangeinput/index.tsx","./src/components/fields/input/textinput/index.tsx","./src/components/fields/inputwrapper/index.tsx","./src/components/fields/radio/index.tsx","./src/components/fields/select/index.tsx","./src/components/fields/textarea/index.tsx","./src/components/icon/index.tsx","./src/components/link/index.tsx","./src/utils/custom-icons.tsx"],"errors":true,"version":"5.9.3"}