native-document 1.0.138 → 1.0.140

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 (259) hide show
  1. package/components.js +1 -1
  2. package/devtools/ComponentRegistry.js +3 -2
  3. package/dist/native-document.components.min.css +1 -0
  4. package/dist/native-document.components.min.js +11506 -8566
  5. package/dist/native-document.dev.js +2645 -2166
  6. package/dist/native-document.dev.js.map +1 -1
  7. package/dist/native-document.min.js +1 -1
  8. package/index.js +1 -0
  9. package/package.json +5 -2
  10. package/rollup.config.js +5 -2
  11. package/src/components/$traits/has-draggable/HasDraggable.js +69 -0
  12. package/src/components/$traits/has-draggable/has-draggable.css +8 -0
  13. package/src/components/$traits/{HasItems.js → has-items/HasItems.js} +2 -11
  14. package/src/components/$traits/has-position/HasFullPosition.js +51 -0
  15. package/src/components/$traits/has-position/HasPosition.js +23 -0
  16. package/src/components/$traits/has-resizable/HasResizable.js +113 -0
  17. package/src/components/$traits/has-resizable/has-resizable.css +121 -0
  18. package/src/components/$traits/has-validation/HasValidation.js +86 -0
  19. package/src/components/BaseComponent.js +109 -4
  20. package/src/components/accordion/Accordion.js +37 -31
  21. package/src/components/accordion/AccordionItem.js +14 -21
  22. package/src/components/alert/Alert.js +48 -40
  23. package/src/components/avatar/Avatar.js +4 -3
  24. package/src/components/avatar/AvatarGroup.js +8 -2
  25. package/src/components/badge/Badge.js +7 -7
  26. package/src/components/base-component.css +0 -0
  27. package/src/components/breadcrumb/BreadCrumb.js +30 -21
  28. package/src/components/button/Button.js +3 -14
  29. package/src/components/context-menu/ContextMenu.js +49 -26
  30. package/src/components/dropdown/Dropdown.js +172 -34
  31. package/src/components/dropdown/DropdownDivider.js +4 -3
  32. package/src/components/dropdown/DropdownGroup.js +19 -19
  33. package/src/components/dropdown/DropdownItem.js +24 -18
  34. package/src/components/dropdown/helpers.js +52 -0
  35. package/src/components/form/FormControl.js +207 -108
  36. package/src/components/form/field/Field.js +106 -174
  37. package/src/components/form/field/FieldCollection.js +110 -203
  38. package/src/components/form/field/types/AutocompleteField.js +26 -5
  39. package/src/components/form/field/types/CheckboxField.js +4 -4
  40. package/src/components/form/field/types/CheckboxGroupField.js +11 -5
  41. package/src/components/form/field/types/ColorField.js +4 -4
  42. package/src/components/form/field/types/DateField.js +110 -18
  43. package/src/components/form/field/types/EmailField.js +2 -2
  44. package/src/components/form/field/types/FileField.js +87 -21
  45. package/src/components/form/field/types/HiddenField.js +4 -4
  46. package/src/components/form/field/types/ImageField.js +4 -4
  47. package/src/components/form/field/types/NumberField.js +5 -5
  48. package/src/components/form/field/types/PasswordField.js +28 -6
  49. package/src/components/form/field/types/RadioField.js +12 -8
  50. package/src/components/form/field/types/RangeField.js +29 -5
  51. package/src/components/form/field/types/SearchField.js +4 -4
  52. package/src/components/form/field/types/SelectField.js +75 -8
  53. package/src/components/form/field/types/StringField.js +4 -4
  54. package/src/components/form/field/types/TelField.js +4 -4
  55. package/src/components/form/field/types/TextAreaField.js +7 -5
  56. package/src/components/form/field/types/TimeField.js +52 -6
  57. package/src/components/form/field/types/UrlField.js +4 -5
  58. package/src/components/form/field/types/file-field-mode/FileAvatarMode.js +104 -0
  59. package/src/components/form/field/types/file-field-mode/FileDropzoneMode.js +59 -0
  60. package/src/components/form/field/types/file-field-mode/FileItemPreview.js +74 -0
  61. package/src/components/form/field/types/file-field-mode/FileNativeMode.js +21 -0
  62. package/src/components/form/field/types/file-field-mode/FileUploadButtonMode.js +59 -0
  63. package/src/components/form/field/types/file-field-mode/FileWallMode.js +53 -0
  64. package/src/components/form/index.js +14 -2
  65. package/src/components/form/validation/Validation.js +9 -0
  66. package/src/components/list/List.js +1 -1
  67. package/src/components/list/ListGroup.js +1 -1
  68. package/src/components/menu/HasMenuItem.js +133 -0
  69. package/src/components/menu/Menu.js +47 -56
  70. package/src/components/menu/MenuGroup.js +36 -8
  71. package/src/components/menu/MenuItem.js +24 -10
  72. package/src/components/menu/MenuLink.js +2 -0
  73. package/src/components/modal/Modal.js +153 -23
  74. package/src/components/pagination/Pagination.js +55 -21
  75. package/src/components/popover/Popover.js +127 -40
  76. package/src/components/progress/Progress.js +14 -24
  77. package/src/components/skeleton/Skeleton.js +36 -13
  78. package/src/components/slider/Slider.js +96 -70
  79. package/src/components/spinner/Spinner.js +4 -2
  80. package/src/components/splitter/Splitter.js +15 -8
  81. package/src/components/splitter/SplitterGutter.js +28 -7
  82. package/src/components/splitter/SplitterPanel.js +9 -15
  83. package/src/components/splitter/index.js +3 -1
  84. package/src/components/stacks/AbsoluteStack.js +33 -0
  85. package/src/components/stacks/FixedStack.js +33 -0
  86. package/src/components/stacks/PositionStack.js +146 -0
  87. package/src/components/stacks/RelativeStack.js +33 -0
  88. package/src/components/{layouts → stacks}/Stack.js +22 -3
  89. package/src/components/{layouts → stacks}/index.js +6 -4
  90. package/src/components/stepper/Stepper.js +159 -67
  91. package/src/components/stepper/StepperStep.js +49 -12
  92. package/src/components/switch/Switch.js +59 -29
  93. package/src/components/switch/index.js +6 -0
  94. package/src/components/table/Column.js +22 -26
  95. package/src/components/table/ColumnGroup.js +4 -13
  96. package/src/components/table/DataTable.js +388 -103
  97. package/src/components/table/SimpleTable.js +28 -143
  98. package/src/components/tabs/Tabs.js +142 -44
  99. package/src/components/toast/Toast.js +40 -35
  100. package/src/components/tooltip/Tooltip.js +152 -35
  101. package/src/core/data/ObservableArray.js +94 -30
  102. package/src/core/data/ObservableChecker.js +20 -75
  103. package/src/core/data/ObservableItem.js +35 -3
  104. package/src/core/data/observable-helpers/computed.js +2 -1
  105. package/src/core/data/observable-helpers/object.js +13 -8
  106. package/src/core/data/observable-helpers/observable.is-to.js +196 -0
  107. package/src/core/elements/anchor/anchor.js +3 -2
  108. package/src/core/elements/control/for-each-array.js +44 -30
  109. package/src/core/elements/control/for-each.js +6 -3
  110. package/src/core/elements/control/show-if.js +11 -6
  111. package/src/core/elements/control/switch.js +2 -1
  112. package/src/core/elements/index.js +1 -1
  113. package/src/core/elements/svg.js +61 -0
  114. package/src/core/utils/HasEventEmitter.js +6 -0
  115. package/src/core/utils/debug-manager.js +2 -5
  116. package/src/core/utils/filters/standard.js +2 -1
  117. package/src/core/utils/property-accumulator.js +35 -6
  118. package/src/core/utils/shortcut-manager.js +242 -0
  119. package/src/core/utils/validator.js +1 -1
  120. package/src/core/wrappers/AttributesWrapper.js +41 -4
  121. package/src/core/wrappers/DocumentObserver.js +0 -1
  122. package/src/core/wrappers/HtmlElementWrapper.js +1 -1
  123. package/src/core/wrappers/NDElement.js +15 -2
  124. package/src/core/wrappers/SvgElementWrapper.js +15 -0
  125. package/src/core/wrappers/prototypes/attributes-extensions.js +4 -1
  126. package/src/core/wrappers/prototypes/nd-element-extensions.js +8 -1
  127. package/src/router/Router.js +0 -1
  128. package/src/ui/components/accordion/AccordionItemRender.js +63 -0
  129. package/src/ui/components/accordion/AccordionRender.js +34 -0
  130. package/src/ui/components/accordion/accordion.css +121 -0
  131. package/src/ui/components/alert/AlertRender.js +80 -0
  132. package/src/ui/components/alert/alert.css +163 -0
  133. package/src/ui/components/avatar/avata-group/AvatarGroupRender.js +49 -0
  134. package/src/ui/components/avatar/avata-group/avatar-group.css +38 -0
  135. package/src/ui/components/avatar/avatar/AvatarRender.js +87 -0
  136. package/src/ui/components/avatar/avatar/avatar.css +189 -0
  137. package/src/ui/components/badge/BadgeRender.js +24 -0
  138. package/src/ui/components/badge/badge.css +168 -0
  139. package/src/ui/components/breadcrumb/BreadcrumbRender.js +43 -0
  140. package/src/ui/components/breadcrumb/breadcrumb.css +55 -0
  141. package/src/ui/components/button/ButtonRender.js +65 -0
  142. package/src/ui/components/button/button.css +288 -354
  143. package/src/ui/components/contextmenu/ContextmenuRender.js +70 -0
  144. package/src/ui/components/contextmenu/contextmenu.css +36 -0
  145. package/src/ui/components/divider/DividerRender.js +70 -0
  146. package/src/ui/components/divider/divider.css +70 -0
  147. package/src/ui/components/dropdown/DropdownRender.js +92 -0
  148. package/src/ui/components/dropdown/divider/DropdownDividerRender.js +9 -0
  149. package/src/ui/components/dropdown/divider/dropdown-divider.css +0 -0
  150. package/src/ui/components/dropdown/dropdown.css +179 -0
  151. package/src/ui/components/dropdown/group/DropdownGroupRender.js +23 -0
  152. package/src/ui/components/dropdown/group/dropdown-group.css +0 -0
  153. package/src/ui/components/dropdown/item/DropdownItemRender.js +29 -0
  154. package/src/ui/components/dropdown/item/dropdown-item.css +0 -0
  155. package/src/ui/components/form/FieldCollectionRender.js +110 -0
  156. package/src/ui/components/form/FormControlRender.js +84 -0
  157. package/src/ui/components/form/field-collection.css +55 -0
  158. package/src/ui/components/form/fields/AutocompleteFieldRender.js +143 -0
  159. package/src/ui/components/form/fields/CheckboxFieldRender.js +59 -0
  160. package/src/ui/components/form/fields/CheckboxGroupFieldRender.js +92 -0
  161. package/src/ui/components/form/fields/ColorFieldRender.js +30 -0
  162. package/src/ui/components/form/fields/DateFieldRender.js +154 -0
  163. package/src/ui/components/form/fields/EmailFieldRender.js +5 -0
  164. package/src/ui/components/form/fields/FieldRender.js +117 -0
  165. package/src/ui/components/form/fields/FileFieldRender.js +41 -0
  166. package/src/ui/components/form/fields/HiddenFieldRender.js +14 -0
  167. package/src/ui/components/form/fields/ImageFieldRender.js +0 -0
  168. package/src/ui/components/form/fields/NumberFieldRender.js +52 -0
  169. package/src/ui/components/form/fields/PasswordFieldRender.js +65 -0
  170. package/src/ui/components/form/fields/RadioFieldRender.js +77 -0
  171. package/src/ui/components/form/fields/RangeFieldRender.js +121 -0
  172. package/src/ui/components/form/fields/SelectFieldRender.js +248 -0
  173. package/src/ui/components/form/fields/SliderFieldRender.js +359 -0
  174. package/src/ui/components/form/fields/StringFieldRender.js +6 -0
  175. package/src/ui/components/form/fields/TelFieldRender.js +6 -0
  176. package/src/ui/components/form/fields/TextAreaFieldRender.js +96 -0
  177. package/src/ui/components/form/fields/TimeFieldRender.js +141 -0
  178. package/src/ui/components/form/fields/UrlFieldRender.js +6 -0
  179. package/src/ui/components/form/fields/date-field.css +32 -0
  180. package/src/ui/components/form/fields/field.css +402 -0
  181. package/src/ui/components/form/fields/file-field.css +79 -0
  182. package/src/ui/components/form/fields/password-field.css +50 -0
  183. package/src/ui/components/form/fields/range-field.css +120 -0
  184. package/src/ui/components/form/fields/slider.css +195 -0
  185. package/src/ui/components/form/file-upload-mode/FileAvatarModeRender.js +143 -0
  186. package/src/ui/components/form/file-upload-mode/FileDropzoneModeRender.js +108 -0
  187. package/src/ui/components/form/file-upload-mode/FileNativeModeRender.js +22 -0
  188. package/src/ui/components/form/file-upload-mode/FileUploadButtonModeRender.js +89 -0
  189. package/src/ui/components/form/file-upload-mode/FileWallModeRender.js +91 -0
  190. package/src/ui/components/form/file-upload-mode/file-avatar-mode.css +139 -0
  191. package/src/ui/components/form/file-upload-mode/file-dropzone-mode.css +88 -0
  192. package/src/ui/components/form/file-upload-mode/file-upload-button-mode.css +44 -0
  193. package/src/ui/components/form/file-upload-mode/file-wall-mode.css +88 -0
  194. package/src/ui/components/form/form-control.css +40 -0
  195. package/src/ui/components/form/helpers.js +112 -0
  196. package/src/ui/components/form/index.js +61 -0
  197. package/src/ui/components/menu/MenuDividerRender.js +12 -0
  198. package/src/ui/components/menu/MenuGroupRender.js +60 -0
  199. package/src/ui/components/menu/MenuItemRender.js +57 -0
  200. package/src/ui/components/menu/MenuLinkRender.js +55 -0
  201. package/src/ui/components/menu/MenuRender.js +21 -0
  202. package/src/ui/components/menu/helpers.js +121 -0
  203. package/src/ui/components/menu/menu.css +308 -0
  204. package/src/ui/components/modal/ModalRender.js +119 -0
  205. package/src/ui/components/modal/modal.css +156 -0
  206. package/src/ui/components/pagination/PaginationRender.js +112 -0
  207. package/src/ui/components/pagination/pagination.css +63 -0
  208. package/src/ui/components/popover/PopoverRender.js +234 -0
  209. package/src/ui/components/popover/popover.css +139 -0
  210. package/src/ui/components/progress/ProgressRender.js +168 -0
  211. package/src/ui/components/progress/progress.css +197 -0
  212. package/src/ui/components/skeleton/SkeletonRender.js +79 -0
  213. package/src/ui/components/skeleton/skeleton.css +154 -0
  214. package/src/ui/components/spinner/SpinnerRender.js +46 -0
  215. package/src/ui/components/spinner/spinner.css +152 -0
  216. package/src/ui/components/splitter/SplitterGutterRender.js +94 -0
  217. package/src/ui/components/splitter/SplitterPanelRender.js +38 -0
  218. package/src/ui/components/splitter/SplitterRender.js +74 -0
  219. package/src/ui/components/splitter/splitter.css +128 -0
  220. package/src/ui/components/stacks/PositionStackRender.js +38 -0
  221. package/src/ui/components/stacks/StackRender.js +42 -0
  222. package/src/ui/components/stacks/absolute-stack/AbsoluteStackRender.js +5 -0
  223. package/src/ui/components/stacks/fixed-stack/FixedStackRender.js +5 -0
  224. package/src/ui/components/stacks/h-stack/HStackRender.js +7 -0
  225. package/src/ui/components/stacks/h-stack/h-stack.css +4 -0
  226. package/src/ui/components/stacks/index.js +15 -0
  227. package/src/ui/components/stacks/position-stack.css +62 -0
  228. package/src/ui/components/stacks/relative-stack/RelativeStackRender.js +7 -0
  229. package/src/ui/components/stacks/relative-stack/relative-stack.css +3 -0
  230. package/src/ui/components/stacks/stack.css +78 -0
  231. package/src/ui/components/stacks/v-stack/VStackRender.js +5 -0
  232. package/src/ui/components/stacks/v-stack/v-stack.css +4 -0
  233. package/src/ui/components/stepper/StepperRender.js +70 -0
  234. package/src/ui/components/stepper/StepperStepRender.js +67 -0
  235. package/src/ui/components/stepper/stepper.css +359 -0
  236. package/src/ui/components/switch/SwitchRender.js +82 -0
  237. package/src/ui/components/switch/switch.css +143 -0
  238. package/src/ui/components/table/data-table/DataTableRender.js +49 -0
  239. package/src/ui/components/table/data-table/bulk-actions.js +35 -0
  240. package/src/ui/components/table/data-table/data-table.css +246 -0
  241. package/src/ui/components/table/data-table/pagination.js +56 -0
  242. package/src/ui/components/table/data-table/tables.js +363 -0
  243. package/src/ui/components/table/data-table/toolbar.js +67 -0
  244. package/src/ui/components/table/simple-table/SimpleTableRender.js +188 -0
  245. package/src/ui/components/table/simple-table/simple-table.css +50 -0
  246. package/src/ui/components/tabs/TabsRender.js +226 -0
  247. package/src/ui/components/tabs/tabs.css +253 -0
  248. package/src/ui/components/toast/ToastRender.js +98 -0
  249. package/src/ui/components/toast/toast.css +201 -0
  250. package/src/ui/components/tooltip/TooltipRender.js +8 -0
  251. package/src/ui/components/tooltip/tooltip.css +113 -0
  252. package/src/ui/index.js +82 -0
  253. package/src/ui/tokens/colors-dark.scss +2 -1
  254. package/src/ui/tokens/reset.scss +3 -0
  255. package/types/control-flow.d.ts +2 -2
  256. package/src/components/layouts/ZStack.js +0 -41
  257. package/src/ui/components/button/button.render.js +0 -63
  258. /package/src/components/{layouts → stacks}/HStack.js +0 -0
  259. /package/src/components/{layouts → stacks}/VStack.js +0 -0
@@ -1,280 +1,187 @@
1
- import { Observable as $, Validator } from "../../../../index";
2
- import NativeDocumentError from "../../../../src/core/errors/NativeDocumentError";
3
- import {Validation} from "../validation/Validation";
4
- import {resolveParams} from "../utils";
5
1
  import BaseComponent from "../../BaseComponent";
2
+ import HasEventEmitter from "../../../core/utils/HasEventEmitter";
3
+ import HasValidation from "../../$traits/has-validation/HasValidation";
4
+ import {Validator, $} from "../../../../index";
5
+ import NativeDocumentError from "../../../core/errors/NativeDocumentError";
6
6
 
7
- export default function FieldCollection(name, config) {
7
+ export default function FieldCollection(name, props = {}) {
8
8
  if(!(this instanceof FieldCollection)) {
9
- return new FieldCollection(name, config);
9
+ return new FieldCollection(name, props);
10
10
  }
11
+
12
+ BaseComponent.call(this, props);
13
+
11
14
  this.$description = {
12
15
  name: name,
16
+ value: $.array([]),
17
+ rules: [],
18
+ fields: {},
19
+ hasErrors: $(false),
20
+ errors: $.array(),
21
+ showErrors: $(true),
13
22
  defaultItem: null,
14
- value: (config?.data && Validator.isObservable(config.data))
15
- ? config.data
16
- : $.array(config?.data || []),
17
- rules: null,
18
- layout: null,
19
- template: null,
20
- ...config
23
+ fieldBuilder: null,
24
+ renderItem: null,
25
+ renderAdd: null,
26
+ transition: null,
27
+ props
21
28
  };
22
29
 
23
- this.$items = null;
24
- this.$currentRefId = 0;
30
+ this.$description.value.interceptMutations((items) =>
31
+ items.map(item => Validator.isObservable(item) ? item : $.object(item))
32
+ );
25
33
  }
26
34
 
27
35
  BaseComponent.extends(FieldCollection);
36
+ BaseComponent.use(FieldCollection, HasEventEmitter);
37
+ BaseComponent.use(FieldCollection, HasValidation);
28
38
 
29
- FieldCollection.defaultLayoutTemplate = null;
30
39
  FieldCollection.defaultTemplate = null;
31
40
 
32
41
  FieldCollection.use = function(template) {
33
- FieldCollection.defaultTemplate = template.fieldCollection;
34
- FieldCollection.defaultLayoutTemplate = template.fieldCollectionLayout;
42
+ FieldCollection.defaultTemplate = template;
35
43
  };
36
44
 
37
-
38
- const setFieldValue = (field, name, proxyData) => {
39
- const value = field.$model();
40
-
41
- const data = proxyData[name];
42
- if(value != null) {
43
- value.set(data);
44
- return;
45
- }
46
- if(Validator.isObservable(data)) {
47
- field.model(data);
48
- return;
49
- }
50
- if(typeof field.checked === 'function') {
51
- field.checked(data);
52
- return;
45
+ FieldCollection.prototype.fields = function(fieldBuilder) {
46
+ if(typeof fieldBuilder !== 'function') {
47
+ throw new NativeDocumentError('FieldCollection.fields() expects a function');
53
48
  }
54
- field.value(data);
55
- };
56
-
57
- Object.defineProperty(FieldCollection.prototype, 'items', {
58
- get() { return this.$items; }
59
- });
60
-
61
- FieldCollection.prototype.data = function(data) {
62
- this.$description.defaultItem = data;
49
+ this.$description.fieldBuilder = fieldBuilder;
63
50
  return this;
64
51
  };
65
52
 
66
- FieldCollection.prototype.isEmpty = function() {
67
- return this.$description.value.val().length === 0;
53
+ FieldCollection.prototype.data = function(defaultItem) {
54
+ if(typeof defaultItem !== 'function') {
55
+ throw new NativeDocumentError('FieldCollection.data() expects a factory function');
56
+ }
57
+ this.$description.defaultItem = defaultItem;
58
+ return this;
68
59
  };
69
60
 
70
- FieldCollection.prototype.count = function() {
71
- return this.$description.value.val().length;
61
+ FieldCollection.prototype.renderItem = function(fn) {
62
+ this.$description.renderItem = fn;
63
+ return this;
72
64
  };
73
65
 
74
- FieldCollection.prototype.addRule = function(validationFn, params, message) {
75
- this.$description.rules = this.$description.rules || [];
76
- this.$description.rules.push({
77
- fn: validationFn,
78
- params: params || [],
79
- message
80
- });
66
+ FieldCollection.prototype.renderAdd = function(fn) {
67
+ this.$description.renderAdd = fn;
81
68
  return this;
82
69
  };
83
70
 
84
- FieldCollection.prototype.fields = function(fieldBuilder) {
85
- if(typeof fieldBuilder !== "function") {
86
- throw new NativeDocumentError('Field builder must be a function');
87
- }
88
- this.$fieldBuilder = fieldBuilder;
71
+ FieldCollection.prototype.transition = function(transitionName) {
72
+ this.$description.transition = transitionName;
89
73
  return this;
90
74
  };
91
75
 
92
- FieldCollection.prototype.template = function(template) {
93
- if(typeof template !== "function") {
94
- throw new NativeDocumentError('Template must be a function');
76
+ FieldCollection.prototype.model = function(observable) {
77
+ if(Validator.isObservable(observable)) {
78
+ this.$description.value = observable;
79
+ this.$description.value.interceptMutations((items) =>
80
+ items.map(item => Validator.isObservable(item) ? item : $.object(item))
81
+ );
82
+ return this;
95
83
  }
96
- this.$description.template = function(item, index) {
97
- const fields = this.items.get(item).fields;
98
- return template.call(this, item, index, { collection: this, fields });
99
- };
84
+ this.$description.value.set(observable);
100
85
  return this;
101
86
  };
102
87
 
103
- FieldCollection.prototype.add = function(...args) {
104
- if (!this.$fieldBuilder) {
105
- throw new NativeDocumentError('Field builder not defined');
106
- }
107
-
108
- const defaultItem = this.$description.defaultItem;
109
- let defaultItemData = (typeof defaultItem === 'function' ? defaultItem(...args) : defaultItem) || '';
110
- defaultItemData = Validator.isObservable(defaultItemData)
111
- ? defaultItemData
112
- : Validator.isObject(defaultItemData)
113
- ? $.init(defaultItemData)
114
- : $(defaultItemData);
115
-
116
- this.$items = this.$items || new WeakMap();
117
-
118
- const refId = this.$currentRefId++;
119
- const createdFields = this.$fieldBuilder(refId, defaultItemData);
120
- let fields = {};
121
- if(Array.isArray(createdFields)) {
122
- createdFields.forEach(field => {
123
- const name = field.$description.name.split('.').pop();
124
- setFieldValue(field, name, defaultItemData);
125
- fields[name] = field;
126
- });
127
- } else {
128
- Object.entries(createdFields).forEach(([name, field]) => {
129
- setFieldValue(field, name, defaultItemData);
130
- fields[name] = field;
131
- })
88
+ FieldCollection.prototype.add = function() {
89
+ if(!this.$description.fieldBuilder) {
90
+ throw new NativeDocumentError('FieldCollection: fields() must be defined before add()');
132
91
  }
92
+ const raw = this.$description.defaultItem
93
+ ? this.$description.defaultItem()
94
+ : {};
95
+ const item = Validator.isObservable(raw) ? raw : $.object(raw);
133
96
 
134
- this.$items.set(defaultItemData, {
135
- refId,
136
- fields
137
- });
138
-
139
- this.$description.value.push(defaultItemData);
97
+ this.$description.value.push(item);
98
+ this.emit('add', item);
140
99
  return this;
141
-
142
100
  };
143
101
 
144
102
  FieldCollection.prototype.remove = function(item) {
145
103
  this.$description.value.removeItem(item);
146
- this.$items?.delete(item);
104
+ this.emit('remove', item);
147
105
  return this;
148
106
  };
149
107
 
150
108
  FieldCollection.prototype.clear = function() {
151
- this.$description.value.forEach((item) => {
152
- this.$items.delete(item);
153
- })
154
109
  this.$description.value.clear();
110
+ return this;
155
111
  };
156
112
 
157
- FieldCollection.prototype.model = function(newValue) {
158
- if(Validator.isObservable(newValue)) {
159
- this.$description.value?.cleanup?.();
160
- this.$description.value = newValue;
161
- return this;
162
- }
163
- this.$description.value.set(newValue);
113
+ FieldCollection.prototype.reset = function() {
114
+ this.clear();
164
115
  return this;
165
116
  };
166
117
 
167
118
  FieldCollection.prototype.value = function() {
168
- return this.$description.value.map((item) => {
169
- return Validator.isObservable(item) ? item.val() : item;
170
- });
119
+ return this.$description.value.map(item =>
120
+ Validator.isObservable(item) ? item.val() : item
121
+ );
171
122
  };
172
123
 
173
- FieldCollection.prototype.validate = function(allValues) {
174
- const errors = [];
175
- const rowsValues = [];
176
-
177
- if(this.$items) {
178
- this.$description.value.forEach((dataItem) => {
179
- const row = this.$items.get(dataItem);
180
- const fields = Object.entries(row.fields);
181
- const itemValue = dataItem.val();
182
- rowsValues.push(itemValue);
183
-
184
- for(const [_, field] of fields) {
185
- const fieldErrors = field.validate({ ...itemValue, $parent: allValues });
186
- if(fieldErrors && fieldErrors.length) {
187
- errors.push(fieldErrors);
188
- }
189
- }
190
- });
191
- }
192
-
193
- if(this.$description.rules) {
194
- for(const rule of this.$description.rules) {
195
- const paramsResolved = resolveParams(rule, allValues);
196
- console.log({ rule, paramsResolved });
197
- const result = rule.fn(rowsValues, ...paramsResolved, allValues);
198
-
199
- if (!result.valid) {
200
- errors.push(rule.message || result.message);
201
- }
202
- }
203
- }
204
-
205
- return errors;
124
+ FieldCollection.prototype.count = function() {
125
+ return this.$description.value.val().length;
206
126
  };
207
127
 
208
- FieldCollection.prototype.min = function(minCount, message) {
209
- if (typeof minCount !== 'number' || minCount < 0) {
210
- throw new NativeDocumentError('min() expects a positive number');
211
- }
212
-
213
- this.addRule(
214
- (values) => {
215
- const isValid = values.length >= minCount;
216
- return {
217
- valid: isValid,
218
- message: `Minimum ${minCount} item(s) required`
219
- };
220
- },
221
- [],
222
- message || `${this.$description.name} must have at least ${minCount} item(s)`
223
- );
128
+ FieldCollection.prototype.isEmpty = function() {
129
+ return this.$description.value.val().length === 0;
130
+ };
224
131
 
132
+ FieldCollection.prototype.onChange = function(handler) {
133
+ this.on('change', handler);
225
134
  return this;
226
135
  };
227
136
 
228
- FieldCollection.prototype.max = function(maxCount, message) {
229
- if (typeof maxCount !== 'number' || maxCount < 0) {
230
- throw new NativeDocumentError('max() expects a positive number');
231
- }
232
-
233
- this.addRule(
234
- (values) => {
235
- const isValid = values.length <= maxCount;
236
- return {
237
- valid: isValid,
238
- message: `Maximum ${maxCount} item(s) allowed`
239
- };
240
- },
241
- [],
242
- message || `${this.$description.name} must have at most ${maxCount} item(s)`
243
- );
244
-
137
+ FieldCollection.prototype.onAdd = function(handler) {
138
+ this.on('add', handler);
245
139
  return this;
246
140
  };
247
141
 
248
- FieldCollection.prototype.required = function(message = '') {
249
- this.addRule(Validation.required, [], message || this.name+' is required');
142
+ FieldCollection.prototype.onRemove = function(handler) {
143
+ this.on('remove', handler);
250
144
  return this;
251
145
  };
252
146
 
253
- FieldCollection.prototype.reset = function() {
254
- this.clear();
255
- return this;
147
+ FieldCollection.prototype.min = function(minCount, message) {
148
+ return this.addRule(
149
+ (values) => ({
150
+ valid: values.length >= minCount,
151
+ message: `Minimum ${minCount} item(s) required`,
152
+ }),
153
+ [],
154
+ message
155
+ );
256
156
  };
257
157
 
258
- FieldCollection.prototype.layout = function(layout) {
259
- if(typeof layout !== 'function') {
260
- throw new NativeDocumentError(this.name+' FieldCollection Layout must be a function');
261
- }
262
- this.$description.layout = layout;
263
- return this;
158
+ FieldCollection.prototype.max = function(maxCount, message) {
159
+ return this.addRule(
160
+ (values) => ({
161
+ valid: values.length <= maxCount,
162
+ message: `Maximum ${maxCount} item(s) allowed`,
163
+ }),
164
+ [],
165
+ message
166
+ );
264
167
  };
265
168
 
169
+ // Override validate
170
+ FieldCollection.prototype.validate = function(allValues) {
171
+ const errors = [];
172
+ const rowsValues = this.value();
266
173
 
267
- FieldCollection.prototype.$build = function() {
268
- const layout = this.$description.layout || FieldCollection.defaultLayoutTemplate;
269
- if (!layout) {
270
- throw new NativeDocumentError(`Layout not defined for collection "${this.$description.name}"`);
174
+ if(this.$description.rules) {
175
+ for(const rule of this.$description.rules) {
176
+ const result = rule.fn(rowsValues, allValues);
177
+ if(!result.valid) {
178
+ errors.push(rule.message || result.message);
179
+ }
180
+ }
271
181
  }
272
182
 
273
- const template = this.$description.template || FieldCollection.defaultTemplate;
183
+ this.$description.errors.set(errors);
184
+ this.$description.hasErrors.set(errors.length > 0);
274
185
 
275
- return layout({
276
- collection: this,
277
- data: this.$description.value,
278
- Template: template ? template.bind(this) : null
279
- });
186
+ return errors;
280
187
  };
@@ -1,24 +1,27 @@
1
1
  import StringField from "./StringField";
2
2
 
3
- export default function AutocompleteField(name, defaultConfig) {
3
+ export default function AutocompleteField(name, props) {
4
4
  if(!(this instanceof AutocompleteField)) {
5
- return new AutocompleteField(name, defaultConfig);
5
+ return new AutocompleteField(name, props);
6
6
  }
7
7
 
8
- StringField.call(this, name, 'autocomplete', defaultConfig);
8
+ StringField.call(this, name, 'autocomplete', props);
9
9
 
10
10
  Object.assign(this.$description, {
11
11
  source: null,
12
12
  minChars: 2,
13
13
  debounce: 300,
14
- maxResults: 10
14
+ maxResults: 10,
15
+ valueKey: 'id',
16
+ labelKey: 'label',
17
+ renderItem: null,
15
18
  });
16
19
  }
17
20
 
18
21
  AutocompleteField.defaultTemplate = null;
19
22
 
20
23
  AutocompleteField.use = function(template) {
21
- AutocompleteField.defaultTemplate = template.autoCompleteField;
24
+ AutocompleteField.defaultTemplate = template;
22
25
  };
23
26
 
24
27
 
@@ -54,4 +57,22 @@ AutocompleteField.prototype.oneOf = function(allowedValues, message) {
54
57
  message: message || `Must be one of: ${allowedValues.join(', ')}`
55
58
  });
56
59
  return this;
60
+ };
61
+
62
+ AutocompleteField.prototype.valueKey = function(key) {
63
+ this.$description.valueKey = key;
64
+ return this;
65
+ };
66
+
67
+ AutocompleteField.prototype.labelKey = function(key) {
68
+ this.$description.labelKey = key;
69
+ return this;
70
+ };
71
+ AutocompleteField.prototype.onSelect = function(handler) {
72
+ this.on('select', handler);
73
+ return this;
74
+ };
75
+ AutocompleteField.prototype.renderItem = function(callback) {
76
+ this.$description.renderItem = callback;
77
+ return this;
57
78
  };
@@ -1,12 +1,12 @@
1
1
  import Field from "../Field";
2
2
  import {Validator} from "../../../../../index";
3
3
 
4
- export default function CheckboxField(name, defaultConfig) {
4
+ export default function CheckboxField(name, props) {
5
5
  if(!(this instanceof CheckboxField)) {
6
- return new CheckboxField(name, defaultConfig);
6
+ return new CheckboxField(name, props);
7
7
  }
8
8
 
9
- Field.call(this, name, 'checkbox', defaultConfig);
9
+ Field.call(this, name, 'checkbox', props);
10
10
 
11
11
  Object.assign(this.$description, {
12
12
  checked: false,
@@ -16,7 +16,7 @@ export default function CheckboxField(name, defaultConfig) {
16
16
  CheckboxField.defaultTemplate = null;
17
17
 
18
18
  CheckboxField.use = function(template) {
19
- CheckboxField.defaultTemplate = template.checkboxField;
19
+ CheckboxField.defaultTemplate = template;
20
20
  };
21
21
 
22
22
  CheckboxField.prototype = Object.create(Field.prototype);
@@ -1,15 +1,16 @@
1
1
  import Field from "../Field";
2
2
 
3
- export default function CheckboxGroupField(name, options, defaultConfig) {
3
+ export default function CheckboxGroupField(name, props) {
4
4
  if(!(this instanceof CheckboxGroupField)) {
5
- return new CheckboxGroupField(name, defaultConfig);
5
+ return new CheckboxGroupField(name, props);
6
6
  }
7
7
 
8
- Field.call(this, name, 'checkbox-group', defaultConfig);
8
+ Field.call(this, name, 'checkbox-group', props);
9
9
 
10
10
  Object.assign(this.$description, {
11
- options: options || [],
11
+ options: [],
12
12
  layout: 'vertical',
13
+ validateOn: 'change',
13
14
  defaultValue: []
14
15
  });
15
16
  }
@@ -17,7 +18,7 @@ export default function CheckboxGroupField(name, options, defaultConfig) {
17
18
  CheckboxGroupField.defaultTemplate = null;
18
19
 
19
20
  CheckboxGroupField.use = function(template) {
20
- CheckboxGroupField.defaultTemplate = template.checkboxGroupField;
21
+ CheckboxGroupField.defaultTemplate = template;
21
22
  };
22
23
 
23
24
  CheckboxGroupField.prototype = Object.create(Field.prototype);
@@ -28,6 +29,11 @@ CheckboxGroupField.prototype.options = function(opts) {
28
29
  return this;
29
30
  };
30
31
 
32
+ CheckboxGroupField.prototype.option = function(value, label, props = {}) {
33
+ this.$description.options.push({ value, label, props });
34
+ return this;
35
+ };
36
+
31
37
  CheckboxGroupField.prototype.layout = function(value) {
32
38
  const allowedLayouts = ['vertical', 'horizontal', 'grid'];
33
39
 
@@ -2,12 +2,12 @@
2
2
  import Field from "../Field";
3
3
  import {Validation} from "../../validation/Validation";
4
4
 
5
- export default function ColorField(name, defaultConfig) {
5
+ export default function ColorField(name, props) {
6
6
  if(!(this instanceof ColorField)) {
7
- return new ColorField(name, defaultConfig);
7
+ return new ColorField(name, props);
8
8
  }
9
9
 
10
- Field.call(this, name, 'color', defaultConfig);
10
+ Field.call(this, name, 'color', props);
11
11
 
12
12
  Object.assign(this.$description, {
13
13
  format: 'hex',
@@ -18,7 +18,7 @@ export default function ColorField(name, defaultConfig) {
18
18
  ColorField.defaultTemplate = null;
19
19
 
20
20
  ColorField.use = function(template) {
21
- ColorField.defaultTemplate = template.colorField;
21
+ ColorField.defaultTemplate = template;
22
22
  };
23
23
 
24
24
  ColorField.prototype = Object.create(Field.prototype);