native-document 1.0.70 → 1.0.73

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 (117) hide show
  1. package/components.js +2 -0
  2. package/dist/native-document.components.min.js +5636 -0
  3. package/dist/native-document.dev.js +412 -353
  4. package/dist/native-document.dev.js.map +1 -1
  5. package/dist/native-document.devtools.min.js +1 -1
  6. package/dist/native-document.min.js +1 -1
  7. package/elements.js +3 -3
  8. package/index.js +17 -17
  9. package/package.json +1 -1
  10. package/rollup.config.js +17 -1
  11. package/src/components/fom-control/FormControl.js +247 -0
  12. package/src/components/fom-control/default/DefaultLayout.js +8 -0
  13. package/src/components/fom-control/default/collection/DefaultCollectionLayout.js +12 -0
  14. package/src/components/fom-control/default/collection/DefaultCollectionTemplate.js +6 -0
  15. package/src/components/fom-control/field/DefaultRender.js +91 -0
  16. package/src/components/fom-control/field/Field.js +396 -0
  17. package/src/components/fom-control/field/FieldCollection.js +260 -0
  18. package/src/components/fom-control/field/FieldFactory.js +107 -0
  19. package/src/components/fom-control/field/types/AutocompleteField.js +46 -0
  20. package/src/components/fom-control/field/types/CheckboxField.js +17 -0
  21. package/src/components/fom-control/field/types/CheckboxGroupField.js +78 -0
  22. package/src/components/fom-control/field/types/ColorField.js +39 -0
  23. package/src/components/fom-control/field/types/DateField.js +62 -0
  24. package/src/components/fom-control/field/types/EmailField.js +44 -0
  25. package/src/components/fom-control/field/types/FileField.js +66 -0
  26. package/src/components/fom-control/field/types/HiddenField.js +8 -0
  27. package/src/components/fom-control/field/types/ImageField.js +49 -0
  28. package/src/components/fom-control/field/types/NumberField.js +74 -0
  29. package/src/components/fom-control/field/types/PasswordField.js +72 -0
  30. package/src/components/fom-control/field/types/RadioField.js +44 -0
  31. package/src/components/fom-control/field/types/RangeField.js +17 -0
  32. package/src/components/fom-control/field/types/SearchField.js +17 -0
  33. package/src/components/fom-control/field/types/SelectField.js +41 -0
  34. package/src/components/fom-control/field/types/StringField.js +49 -0
  35. package/src/components/fom-control/field/types/TelField.js +38 -0
  36. package/src/components/fom-control/field/types/TextAreaField.js +56 -0
  37. package/src/components/fom-control/field/types/TimeField.js +45 -0
  38. package/src/components/fom-control/field/types/UrlField.js +53 -0
  39. package/src/components/fom-control/index.js +8 -0
  40. package/src/components/fom-control/merge +0 -0
  41. package/src/components/fom-control/utils.js +17 -0
  42. package/src/components/fom-control/validation/Validation.js +556 -0
  43. package/src/components/table/Column.js +106 -0
  44. package/src/components/table/ColumnGroup.js +54 -0
  45. package/src/components/table/DataTable.js +195 -0
  46. package/src/components/table/SimpleTable.js +184 -0
  47. package/src/components/table/index.js +9 -0
  48. package/src/{data → core/data}/ObservableArray.js +1 -0
  49. package/src/{data → core/data}/ObservableItem.js +49 -3
  50. package/src/{data → core/data}/observable-helpers/computed.js +2 -1
  51. package/src/{elements → core/elements}/anchor.js +32 -32
  52. package/src/{elements → core/elements}/control/for-each-array.js +4 -2
  53. package/src/core/utils/EventEmitter.js +46 -0
  54. package/src/{utils → core/utils}/helpers.js +12 -0
  55. package/src/{utils → core/utils}/validator.js +7 -0
  56. package/src/{wrappers → core/wrappers}/ElementCreator.js +10 -33
  57. package/src/{wrappers → core/wrappers}/NDElement.js +2 -129
  58. package/src/core/wrappers/NdPrototype.js +147 -0
  59. package/src/core/wrappers/TemplateBinding.js +7 -0
  60. package/src/{wrappers → core/wrappers}/TemplateCloner.js +16 -17
  61. package/src/core/wrappers/prototype-extensions.js +56 -0
  62. package/src/devtools/hrm/ComponentRegistry.js +1 -1
  63. package/src/router/Route.js +1 -1
  64. package/src/router/RouteGroupHelper.js +1 -1
  65. package/src/router/Router.js +4 -4
  66. package/src/router/RouterComponent.js +13 -2
  67. package/src/router/link.js +2 -2
  68. package/src/router/modes/HistoryRouter.js +2 -2
  69. package/types/forms.d.ts +2 -1
  70. package/types/validator.ts +2 -1
  71. package/utils.js +3 -3
  72. package/src/wrappers/NdPrototype.js +0 -71
  73. /package/src/{data → core/data}/MemoryManager.js +0 -0
  74. /package/src/{data → core/data}/Observable.js +0 -0
  75. /package/src/{data → core/data}/ObservableChecker.js +0 -0
  76. /package/src/{data → core/data}/ObservableWhen.js +0 -0
  77. /package/src/{data → core/data}/Store.js +0 -0
  78. /package/src/{data → core/data}/observable-helpers/array.js +0 -0
  79. /package/src/{data → core/data}/observable-helpers/batch.js +0 -0
  80. /package/src/{data → core/data}/observable-helpers/object.js +0 -0
  81. /package/src/{elements → core/elements}/content-formatter.js +0 -0
  82. /package/src/{elements → core/elements}/control/for-each.js +0 -0
  83. /package/src/{elements → core/elements}/control/show-if.js +0 -0
  84. /package/src/{elements → core/elements}/control/show-when.js +0 -0
  85. /package/src/{elements → core/elements}/control/switch.js +0 -0
  86. /package/src/{elements → core/elements}/description-list.js +0 -0
  87. /package/src/{elements → core/elements}/form.js +0 -0
  88. /package/src/{elements → core/elements}/html5-semantics.js +0 -0
  89. /package/src/{elements → core/elements}/img.js +0 -0
  90. /package/src/{elements → core/elements}/index.js +0 -0
  91. /package/src/{elements → core/elements}/interactive.js +0 -0
  92. /package/src/{elements → core/elements}/list.js +0 -0
  93. /package/src/{elements → core/elements}/medias.js +0 -0
  94. /package/src/{elements → core/elements}/meta-data.js +0 -0
  95. /package/src/{elements → core/elements}/table.js +0 -0
  96. /package/src/{errors → core/errors}/ArgTypesError.js +0 -0
  97. /package/src/{errors → core/errors}/NativeDocumentError.js +0 -0
  98. /package/src/{errors → core/errors}/RouterError.js +0 -0
  99. /package/src/{utils → core/utils}/args-types.js +0 -0
  100. /package/src/{utils → core/utils}/debug-manager.js +0 -0
  101. /package/src/{utils → core/utils}/events.js +0 -0
  102. /package/src/{utils → core/utils}/filters/date.js +0 -0
  103. /package/src/{utils → core/utils}/filters/index.js +0 -0
  104. /package/src/{utils → core/utils}/filters/standard.js +0 -0
  105. /package/src/{utils → core/utils}/filters/strings.js +0 -0
  106. /package/src/{utils → core/utils}/filters/utils.js +0 -0
  107. /package/src/{utils → core/utils}/memoize.js +0 -0
  108. /package/src/{utils → core/utils}/plugins-manager.js +0 -0
  109. /package/src/{utils → core/utils}/property-accumulator.js +0 -0
  110. /package/src/{utils → core/utils}/prototypes.js +0 -0
  111. /package/src/{utils → core/utils}/service.js +0 -0
  112. /package/src/{wrappers → core/wrappers}/AttributesWrapper.js +0 -0
  113. /package/src/{wrappers → core/wrappers}/DocumentObserver.js +0 -0
  114. /package/src/{wrappers → core/wrappers}/HtmlElementWrapper.js +0 -0
  115. /package/src/{wrappers → core/wrappers}/SingletonView.js +0 -0
  116. /package/src/{wrappers → core/wrappers}/constants.js +0 -0
  117. /package/src/{utils/fetch → fetch}/NativeFetch.js +0 -0
@@ -0,0 +1,556 @@
1
+ import {Validator} from "../../../../index";
2
+
3
+ export const Validation = {
4
+
5
+ required(value) {
6
+ const valid = value !== null && value !== undefined && value !== '';
7
+ return {
8
+ valid,
9
+ message: 'This field is required'
10
+ };
11
+ },
12
+
13
+ minLength(value, min) {
14
+ if (!value) return { valid: true };
15
+ const valid = value.length >= min;
16
+ return {
17
+ valid,
18
+ message: `Minimum ${min} characters required`
19
+ };
20
+ },
21
+
22
+ maxLength(value, max) {
23
+ if (!value) return { valid: true };
24
+ const valid = value.length <= max;
25
+ return {
26
+ valid,
27
+ message: `Maximum ${max} characters allowed`
28
+ };
29
+ },
30
+
31
+ length(value, length) {
32
+ if (!value) return { valid: true };
33
+ const valid = value.length === length;
34
+ return {
35
+ valid,
36
+ message: `Must be exactly ${length} characters`
37
+ };
38
+ },
39
+
40
+ email(value) {
41
+ if (!value) return { valid: true };
42
+ const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
43
+ const valid = regex.test(value);
44
+ return {
45
+ valid,
46
+ message: 'Invalid email address'
47
+ };
48
+ },
49
+
50
+ pattern(value, regex) {
51
+ if (!value) return { valid: true };
52
+ const valid = regex.test(value);
53
+ return {
54
+ valid,
55
+ message: 'Invalid format'
56
+ };
57
+ },
58
+
59
+ alphaOnly(value) {
60
+ if (!value) return { valid: true };
61
+ const valid = /^[a-zA-Z]+$/.test(value);
62
+ return {
63
+ valid,
64
+ message: 'Only letters allowed'
65
+ };
66
+ },
67
+
68
+ numericOnly(value) {
69
+ if (!value) return { valid: true };
70
+ const valid = /^[0-9]+$/.test(value);
71
+ return {
72
+ valid,
73
+ message: 'Only numbers allowed'
74
+ };
75
+ },
76
+
77
+ alphaNumeric(value) {
78
+ if (!value) return { valid: true };
79
+ const valid = /^[a-zA-Z0-9]+$/.test(value);
80
+ return {
81
+ valid,
82
+ message: 'Only letters and numbers allowed'
83
+ };
84
+ },
85
+
86
+ min(value, min) {
87
+ if (value === null || value === undefined || value === '') return { valid: true };
88
+ const valid = Number(value) >= min;
89
+ return {
90
+ valid,
91
+ message: `Minimum value is ${min}`
92
+ };
93
+ },
94
+
95
+ max(value, max) {
96
+ if (value === null || value === undefined || value === '') return { valid: true };
97
+ const valid = Number(value) <= max;
98
+ return {
99
+ valid,
100
+ message: `Maximum value is ${max}`
101
+ };
102
+ },
103
+
104
+ between(value, min, max) {
105
+ if (value === null || value === undefined || value === '') return { valid: true };
106
+ const num = Number(value);
107
+ const valid = num >= min && num <= max;
108
+ return {
109
+ valid,
110
+ message: `Value must be between ${min} and ${max}`
111
+ };
112
+ },
113
+
114
+ integer(value) {
115
+ if (!value) return { valid: true };
116
+ const valid = /^-?\d+$/.test(value);
117
+ return {
118
+ valid,
119
+ message: 'Must be an integer'
120
+ };
121
+ },
122
+
123
+ positive(value) {
124
+ if (value === null || value === undefined || value === '') return { valid: true };
125
+ const valid = Number(value) > 0;
126
+ return {
127
+ valid,
128
+ message: 'Must be positive'
129
+ };
130
+ },
131
+
132
+ negative(value) {
133
+ if (value === null || value === undefined || value === '') return { valid: true };
134
+ const valid = Number(value) < 0;
135
+ return {
136
+ valid,
137
+ message: 'Must be negative'
138
+ };
139
+ },
140
+
141
+ same(value, otherValue) {
142
+ const valid = value === otherValue;
143
+ return {
144
+ valid,
145
+ message: 'Values must match'
146
+ };
147
+ },
148
+
149
+ different(value, otherValue) {
150
+ const valid = value !== otherValue;
151
+ return {
152
+ valid,
153
+ message: 'Values must be different'
154
+ };
155
+ },
156
+
157
+ url(value) {
158
+ if (!value) return { valid: true };
159
+ try {
160
+ new URL(value);
161
+ return { valid: true };
162
+ } catch {
163
+ return {
164
+ valid: false,
165
+ message: 'Invalid URL'
166
+ };
167
+ }
168
+ },
169
+
170
+ phone(value) {
171
+ if (!value) return { valid: true };
172
+ // International phone format
173
+ const regex = /^[+]?[(]?[0-9]{1,4}[)]?[-\s.]?[(]?[0-9]{1,4}[)]?[-\s.]?[0-9]{1,9}$/;
174
+ const valid = regex.test(value);
175
+ return {
176
+ valid,
177
+ message: 'Invalid phone number'
178
+ };
179
+ },
180
+
181
+ date(value) {
182
+ if (!value) return { valid: true };
183
+ const date = new Date(value);
184
+ const valid = !isNaN(date.getTime());
185
+ return {
186
+ valid,
187
+ message: 'Invalid date'
188
+ };
189
+ },
190
+
191
+ after(value, afterDate) {
192
+ if (!value) return { valid: true };
193
+ const date = new Date(value);
194
+ const compareDate = new Date(afterDate);
195
+ const valid = date > compareDate;
196
+ return {
197
+ valid,
198
+ message: `Date must be after ${afterDate}`
199
+ };
200
+ },
201
+
202
+ before(value, beforeDate) {
203
+ if (!value) return { valid: true };
204
+ const date = new Date(value);
205
+ const compareDate = new Date(beforeDate);
206
+ const valid = date < compareDate;
207
+ return {
208
+ valid,
209
+ message: `Date must be before ${beforeDate}`
210
+ };
211
+ },
212
+
213
+ maxSize(file, maxBytes) {
214
+ if (!file) return { valid: true };
215
+ const valid = file.size <= maxBytes;
216
+ const mb = (maxBytes / (1024 * 1024)).toFixed(2);
217
+ return {
218
+ valid,
219
+ message: `File size must not exceed ${mb}MB`
220
+ };
221
+ },
222
+
223
+ mimeTypes(file, allowedTypes) {
224
+ if (!file) return { valid: true };
225
+ const valid = allowedTypes.includes(file.type);
226
+ return {
227
+ valid,
228
+ message: `Allowed types: ${allowedTypes.join(', ')}`
229
+ };
230
+ },
231
+
232
+ lowercase(value) {
233
+ if (!value) return { valid: true };
234
+ const valid = value === value.toLowerCase();
235
+ return {
236
+ valid,
237
+ message: 'Must be lowercase'
238
+ };
239
+ },
240
+
241
+ uppercase(value) {
242
+ if (!value) return { valid: true };
243
+ const valid = value === value.toUpperCase();
244
+ return {
245
+ valid,
246
+ message: 'Must be uppercase'
247
+ };
248
+ },
249
+
250
+ noSpaces(value) {
251
+ if (!value) return { valid: true };
252
+ const valid = !/\s/.test(value);
253
+ return {
254
+ valid,
255
+ message: 'Spaces not allowed'
256
+ };
257
+ },
258
+ afterDate(value, afterDate) {
259
+ if (!value) return { valid: true };
260
+ const date = new Date(value);
261
+ const compareDate = new Date(afterDate);
262
+ const valid = date > compareDate;
263
+ return {
264
+ valid,
265
+ message: `Date must be after ${new Date(afterDate).toLocaleDateString()}`
266
+ };
267
+ },
268
+
269
+ beforeDate(value, beforeDate) {
270
+ if (!value) return { valid: true };
271
+ const date = new Date(value);
272
+ const compareDate = new Date(beforeDate);
273
+ const valid = date < compareDate;
274
+ return {
275
+ valid,
276
+ message: `Date must be before ${new Date(beforeDate).toLocaleDateString()}`
277
+ };
278
+ },
279
+
280
+ betweenDates(value, startDate, endDate) {
281
+ if (!value) return { valid: true };
282
+ const date = new Date(value);
283
+ const start = new Date(startDate);
284
+ const end = new Date(endDate);
285
+ const valid = date >= start && date <= end;
286
+ return {
287
+ valid,
288
+ message: `Date must be between ${start.toLocaleDateString()} and ${end.toLocaleDateString()}`
289
+ };
290
+ },
291
+
292
+ afterTime(value, afterTime) {
293
+ if (!value) return { valid: true };
294
+ const getSeconds = (time) => {
295
+ const [hours, minutes] = time.split(':').map(Number);
296
+ return hours * 3600 + minutes * 60;
297
+ };
298
+ const valid = getSeconds(value) > getSeconds(afterTime);
299
+ return {
300
+ valid,
301
+ message: `Time must be after ${afterTime}`
302
+ };
303
+ },
304
+
305
+ beforeTime(value, beforeTime) {
306
+ if (!value) return { valid: true };
307
+ const getSeconds = (time) => {
308
+ const [hours, minutes] = time.split(':').map(Number);
309
+ return hours * 3600 + minutes * 60;
310
+ };
311
+ const valid = getSeconds(value) < getSeconds(beforeTime);
312
+ return {
313
+ valid,
314
+ message: `Time must be before ${beforeTime}`
315
+ };
316
+ },
317
+
318
+ betweenTimes(value, startTime, endTime) {
319
+ if (!value) return { valid: true };
320
+ const getSeconds = (time) => {
321
+ const [hours, minutes] = time.split(':').map(Number);
322
+ return hours * 3600 + minutes * 60;
323
+ };
324
+ const seconds = getSeconds(value);
325
+ const start = getSeconds(startTime);
326
+ const end = getSeconds(endTime);
327
+ const valid = seconds >= start && seconds <= end;
328
+ return {
329
+ valid,
330
+ message: `Time must be between ${startTime} and ${endTime}`
331
+ };
332
+ },
333
+
334
+ hexColor(value) {
335
+ if (!value) return { valid: true };
336
+ const valid = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(value);
337
+ return {
338
+ valid,
339
+ message: 'Invalid hex color format'
340
+ };
341
+ },
342
+
343
+ rgbColor(value) {
344
+ if (!value) return { valid: true };
345
+ const valid = /^rgb\(\s*\d{1,3}\s*,\s*\d{1,3}\s*,\s*\d{1,3}\s*\)$/.test(value);
346
+ return {
347
+ valid,
348
+ message: 'Invalid RGB color format'
349
+ };
350
+ },
351
+
352
+ dimensions(file, width, height) {
353
+ if (!file) return { valid: true };
354
+
355
+ return new Promise((resolve) => {
356
+ const img = new Image();
357
+ img.onload = () => {
358
+ const valid = img.width === width && img.height === height;
359
+ resolve({
360
+ valid,
361
+ message: `Image must be exactly ${width}x${height}px`
362
+ });
363
+ };
364
+ img.onerror = () => {
365
+ resolve({
366
+ valid: false,
367
+ message: 'Invalid image file'
368
+ });
369
+ };
370
+ img.src = URL.createObjectURL(file);
371
+ });
372
+ },
373
+
374
+ maxDimensions(file, maxWidth, maxHeight) {
375
+ if (!file) return { valid: true };
376
+
377
+ return new Promise((resolve) => {
378
+ const img = new Image();
379
+ img.onload = () => {
380
+ const valid = img.width <= maxWidth && img.height <= maxHeight;
381
+ resolve({
382
+ valid,
383
+ message: `Image must not exceed ${maxWidth}x${maxHeight}px`
384
+ });
385
+ };
386
+ img.onerror = () => {
387
+ resolve({
388
+ valid: false,
389
+ message: 'Invalid image file'
390
+ });
391
+ };
392
+ img.src = URL.createObjectURL(file);
393
+ });
394
+ },
395
+
396
+ minDimensions(file, minWidth, minHeight) {
397
+ if (!file) return { valid: true };
398
+
399
+ return new Promise((resolve) => {
400
+ const img = new Image();
401
+ img.onload = () => {
402
+ const valid = img.width >= minWidth && img.height >= minHeight;
403
+ resolve({
404
+ valid,
405
+ message: `Image must be at least ${minWidth}x${minHeight}px`
406
+ });
407
+ };
408
+ img.onerror = () => {
409
+ resolve({
410
+ valid: false,
411
+ message: 'Invalid image file'
412
+ });
413
+ };
414
+ img.src = URL.createObjectURL(file);
415
+ });
416
+ },
417
+
418
+ aspectRatio(file, ratio) {
419
+ if (!file) return { valid: true };
420
+
421
+ return new Promise((resolve) => {
422
+ const img = new Image();
423
+ img.onload = () => {
424
+ const imageRatio = img.width / img.height;
425
+ const valid = Math.abs(imageRatio - ratio) < 0.01;
426
+ resolve({
427
+ valid,
428
+ message: `Image aspect ratio must be ${ratio}`
429
+ });
430
+ };
431
+ img.onerror = () => {
432
+ resolve({
433
+ valid: false,
434
+ message: 'Invalid image file'
435
+ });
436
+ };
437
+ img.src = URL.createObjectURL(file);
438
+ });
439
+ },
440
+ maxFileSize(file, maxBytes) {
441
+ if (!file) return { valid: true };
442
+
443
+ // Support File object ou array de Files
444
+ if (Array.isArray(file)) {
445
+ const allValid = file.every(f => f.size <= maxBytes);
446
+ if (!allValid) {
447
+ const mb = (maxBytes / (1024 * 1024)).toFixed(2);
448
+ return {
449
+ valid: false,
450
+ message: `Each file must not exceed ${mb}MB`
451
+ };
452
+ }
453
+ return { valid: true };
454
+ }
455
+
456
+ const valid = file.size <= maxBytes;
457
+ const mb = (maxBytes / (1024 * 1024)).toFixed(2);
458
+ return {
459
+ valid,
460
+ message: `File size must not exceed ${mb}MB`
461
+ };
462
+ },
463
+
464
+ minFileSize(file, minBytes) {
465
+ if (!file) return { valid: true };
466
+
467
+ if (Array.isArray(file)) {
468
+ const allValid = file.every(f => f.size >= minBytes);
469
+ if (!allValid) {
470
+ const kb = (minBytes / 1024).toFixed(2);
471
+ return {
472
+ valid: false,
473
+ message: `Each file must be at least ${kb}KB`
474
+ };
475
+ }
476
+ return { valid: true };
477
+ }
478
+
479
+ const valid = file.size >= minBytes;
480
+ const kb = (minBytes / 1024).toFixed(2);
481
+ return {
482
+ valid,
483
+ message: `File must be at least ${kb}KB`
484
+ };
485
+ },
486
+
487
+ extensions(file, allowedExts) {
488
+ if (!file) return { valid: true };
489
+
490
+ const checkExtension = (f) => {
491
+ const ext = f.name.split('.').pop().toLowerCase();
492
+ return allowedExts.map(e => e.toLowerCase()).includes(ext);
493
+ };
494
+
495
+ if (Array.isArray(file)) {
496
+ const allValid = file.every(checkExtension);
497
+ if (!allValid) {
498
+ return {
499
+ valid: false,
500
+ message: `Allowed extensions: ${allowedExts.join(', ')}`
501
+ };
502
+ }
503
+ return { valid: true };
504
+ }
505
+
506
+ const valid = checkExtension(file);
507
+ return {
508
+ valid,
509
+ message: `Allowed extensions: ${allowedExts.join(', ')}`
510
+ };
511
+ },
512
+
513
+ maxFiles(files, max) {
514
+ if (!files) return { valid: true };
515
+ if (!Array.isArray(files)) return { valid: true };
516
+
517
+ const valid = files.length <= max;
518
+ return {
519
+ valid,
520
+ message: `Maximum ${max} file${max > 1 ? 's' : ''} allowed`
521
+ };
522
+ },
523
+
524
+ minFiles(files, min) {
525
+ if (!files) return { valid: false, message: `At least ${min} file${min > 1 ? 's' : ''} required` };
526
+ if (!Array.isArray(files)) return { valid: false, message: `At least ${min} file${min > 1 ? 's' : ''} required` };
527
+
528
+ const valid = files.length >= min;
529
+ return {
530
+ valid,
531
+ message: `At least ${min} file${min > 1 ? 's' : ''} required`
532
+ };
533
+ },
534
+
535
+ requiredIf(value, condition, allValues = {}) {
536
+ let isRequired;
537
+
538
+ if(typeof condition === 'string' && Object.keys(allValues).includes(condition)) {
539
+ isRequired = !!allValues[condition];
540
+ }
541
+ else if (typeof condition === 'function') {
542
+ isRequired = condition(allValues);
543
+ } else if (Validator.isObservable(condition)) {
544
+ isRequired = condition.val();
545
+ } else {
546
+ isRequired = !!condition;
547
+ }
548
+
549
+ if (!isRequired) {
550
+ return { valid: true };
551
+ }
552
+
553
+ return Validation.required(value);
554
+ }
555
+
556
+ };
@@ -0,0 +1,106 @@
1
+
2
+ export default function Column(key, configs = {}) {
3
+ this.$description = {
4
+ key,
5
+ align: null,
6
+ searchable: null,
7
+ visible: null,
8
+ header: null,
9
+ render: null,
10
+ colspan: null,
11
+ rowspan: null,
12
+ ...configs
13
+ };
14
+ }
15
+
16
+ Column.defaultRender = null;
17
+ Column.defaultHeader = null;
18
+
19
+ Column.use = function(template) {
20
+ Column.defaultRender = template.render || Column.defaultRender;
21
+ Column.defaultHeader = template.header || Column.defaultHeader;
22
+ };
23
+
24
+ Column.prototype.isColumn = true;
25
+
26
+ Column.prototype.sortable = function(customSortFn = null) {
27
+ this.$description.sortable = customSortFn;
28
+ };
29
+
30
+ Column.prototype.searchable = function() {
31
+ this.$description.searchable = true;
32
+ return this;
33
+ };
34
+
35
+ Column.prototype.hidden = function() {
36
+ this.$description.visible = false;
37
+ return this;
38
+ };
39
+
40
+ Column.prototype.visible = function(condition = true) {
41
+ this.$description.visible = condition;
42
+ return this;
43
+ };
44
+
45
+ Column.prototype.align = function(align) {
46
+ this.$description.align = align;
47
+ return this;
48
+ };
49
+
50
+ Column.prototype.center = function() {
51
+ return this.align('center');
52
+ };
53
+
54
+ Column.prototype.right = function() {
55
+ return this.align('right');
56
+ };
57
+
58
+ Column.prototype.header = function(template) {
59
+ this.$description.header = template;
60
+ return this;
61
+ };
62
+
63
+ Column.prototype.colspan = function(count) {
64
+ this.$description.colspan = count;
65
+ return this;
66
+ };
67
+
68
+ Column.prototype.rowspan = function(count) {
69
+ this.$description.rowspan = count;
70
+ return this;
71
+ };
72
+
73
+ Column.prototype.title = function(title) {
74
+ this.$description.header = title;
75
+ return this;
76
+ };
77
+
78
+ Column.prototype.render = function(render) {
79
+ this.$description.render = render;
80
+ return this;
81
+ };
82
+
83
+ Column.prototype.value = function(value) {
84
+ this.$description.value = value;
85
+ return this;
86
+ };
87
+
88
+
89
+ Column.prototype.buildHeader = function(rowSpan = null) {
90
+ const header = this.$description.header;
91
+ if(typeof header === 'function') {
92
+ return header(this);
93
+ }
94
+ return THeadCell({ rowspan: rowSpan }, header);
95
+ };
96
+
97
+ Column.prototype.buildCell = function(rowData) {
98
+ const render = this.$description.render || Column.defaultRender;
99
+ if(typeof render === 'string' && rowData[render] !== undefined) {
100
+ return rowData[render];
101
+ }
102
+ if(typeof render === 'function') {
103
+ return render(rowData, this);
104
+ }
105
+ return rowData[this.$description.key] ?? null;
106
+ };
@@ -0,0 +1,54 @@
1
+ import Column from "./Column";
2
+ import { THeadCell } from "../../../elements";
3
+
4
+ export default function ColumnGroup(title, configs = {}) {
5
+ this.$description = {
6
+ header: title,
7
+ columns: [],
8
+ align: null,
9
+ ...configs
10
+ };
11
+ };
12
+
13
+ ColumnGroup.defaultHeader = null;
14
+ ColumnGroup.use = function(template) {
15
+ ColumnGroup.defaultHeader = template.header || ColumnGroup.defaultHeader;
16
+ };
17
+
18
+ ColumnGroup.prototype.isGroup = true;
19
+
20
+ ColumnGroup.prototype.column = function(key, title, callback) {
21
+ const column = new Column(key);
22
+ column.title(title);
23
+ callback && callback(column);
24
+ this.$description.columns.push(column);
25
+ return this;
26
+ };
27
+
28
+ ColumnGroup.prototype.title = function(title) {
29
+ this.$description.header = title;
30
+ return this;
31
+ };
32
+
33
+ ColumnGroup.prototype.columns = function() {
34
+ return this.$description.columns;
35
+ };
36
+
37
+ ColumnGroup.prototype.header = function(title) {
38
+ this.$description.header = title;
39
+ return this;
40
+ };
41
+
42
+ ColumnGroup.prototype.align = function(align) {
43
+ this.$description.align = align;
44
+ return this;
45
+ };
46
+
47
+
48
+ ColumnGroup.prototype.buildHeader = function() {
49
+ const header = this.$description.header || ColumnGroup.defaultHeader;
50
+ if(typeof header === 'function') {
51
+ return header(this);
52
+ }
53
+ return THeadCell({ colspan: this.$description.columns.length }, header);
54
+ };