ember-headless-form 1.0.0-beta.1 → 1.0.0-beta.3

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 (48) hide show
  1. package/dist/-private/components/control/checkbox.d.ts.map +1 -1
  2. package/dist/-private/components/control/checkbox.js +18 -5
  3. package/dist/-private/components/control/checkbox.js.map +1 -1
  4. package/dist/-private/components/control/input.d.ts +2 -2
  5. package/dist/-private/components/control/input.js +20 -6
  6. package/dist/-private/components/control/input.js.map +1 -1
  7. package/dist/-private/components/control/radio-group/label.d.ts +15 -0
  8. package/dist/-private/components/control/radio-group/label.js +10 -0
  9. package/dist/-private/components/control/radio-group/label.js.map +1 -0
  10. package/dist/-private/components/control/radio-group/radio/input.d.ts +13 -0
  11. package/dist/-private/components/control/radio-group/radio/input.js +26 -0
  12. package/dist/-private/components/control/radio-group/radio/input.js.map +1 -0
  13. package/dist/-private/components/control/{radio.d.ts → radio-group/radio.d.ts} +4 -6
  14. package/dist/-private/components/control/radio-group/radio.js +41 -0
  15. package/dist/-private/components/control/radio-group/radio.js.map +1 -0
  16. package/dist/-private/components/control/radio-group.d.ts +27 -0
  17. package/dist/-private/components/control/radio-group.js +44 -0
  18. package/dist/-private/components/control/radio-group.js.map +1 -0
  19. package/dist/-private/components/control/select/option.js +15 -3
  20. package/dist/-private/components/control/select/option.js.map +1 -1
  21. package/dist/-private/components/control/select.d.ts +2 -3
  22. package/dist/-private/components/control/select.js +29 -10
  23. package/dist/-private/components/control/select.js.map +1 -1
  24. package/dist/-private/components/control/textarea.js +17 -5
  25. package/dist/-private/components/control/textarea.js.map +1 -1
  26. package/dist/-private/components/errors.js +15 -3
  27. package/dist/-private/components/errors.js.map +1 -1
  28. package/dist/-private/components/field.d.ts +5 -4
  29. package/dist/-private/components/field.js +95 -9
  30. package/dist/-private/components/field.js.map +1 -1
  31. package/dist/-private/components/label.d.ts +3 -2
  32. package/dist/-private/components/label.js +9 -5
  33. package/dist/-private/components/label.js.map +1 -1
  34. package/dist/-private/modifiers/capture-events.d.ts +2 -2
  35. package/dist/-private/modifiers/capture-events.js +8 -6
  36. package/dist/-private/modifiers/capture-events.js.map +1 -1
  37. package/dist/-private/utils.d.ts +2 -1
  38. package/dist/-private/utils.js +10 -1
  39. package/dist/-private/utils.js.map +1 -1
  40. package/dist/components/headless-form.d.ts +32 -4
  41. package/dist/components/headless-form.js +104 -18
  42. package/dist/components/headless-form.js.map +1 -1
  43. package/package.json +15 -11
  44. package/dist/-private/components/control/radio/input.d.ts +0 -12
  45. package/dist/-private/components/control/radio/input.js +0 -10
  46. package/dist/-private/components/control/radio/input.js.map +0 -1
  47. package/dist/-private/components/control/radio.js +0 -23
  48. package/dist/-private/components/control/radio.js.map +0 -1
@@ -5,8 +5,9 @@ import '@babel/runtime/helpers/esm/initializerWarningHelper';
5
5
  import { setComponentTemplate } from '@ember/component';
6
6
  import { precompileTemplate } from '@ember/template-compilation';
7
7
  import Component from '@glimmer/component';
8
- import { tracked } from '@glimmer/tracking';
8
+ import { tracked, cached } from '@glimmer/tracking';
9
9
  import { assert, warn } from '@ember/debug';
10
+ import { hash } from '@ember/helper';
10
11
  import { on } from '@ember/modifier';
11
12
  import { action, set } from '@ember/object';
12
13
  import { TrackedAsyncData } from 'ember-async-data';
@@ -15,8 +16,6 @@ import { TrackedObject } from 'tracked-built-ins';
15
16
  import HeadlessFormFieldComponent from '../-private/components/field.js';
16
17
  import { mergeErrorRecord } from '../-private/utils.js';
17
18
 
18
- var TEMPLATE = precompileTemplate("<form\n novalidate\n ...attributes\n {{this.registerForm}}\n {{on \'submit\' this.onSubmit}}\n {{(if\n this.fieldValidationEvent\n (modifier this.on this.fieldValidationEvent this.handleFieldValidation)\n )}}\n {{(if\n this.fieldRevalidationEvent\n (modifier this.on this.fieldRevalidationEvent this.handleFieldRevalidation)\n )}}\n>\n {{yield\n (hash\n Field=(component\n (ensure-safe-component this.FieldComponent)\n data=this.internalData\n set=this.set\n errors=this.visibleErrors\n registerField=this.registerField\n unregisterField=this.unregisterField\n triggerValidationFor=this.handleFieldValidation\n fieldValidationEvent=this.fieldValidationEvent\n fieldRevalidationEvent=this.fieldRevalidationEvent\n )\n validationState=this.validationState\n submissionState=this.submissionState\n isInvalid=this.hasValidationErrors\n rawErrors=this.visibleErrors\n )\n }}\n</form>");
19
-
20
19
  var _class, _descriptor, _class3, _descriptor2, _descriptor3, _descriptor4;
21
20
  /**
22
21
  * This internal data structure maintains information about each field that is registered to the form by `registerField`.
@@ -69,20 +68,100 @@ let FieldData = (_class = class FieldData {
69
68
  * </HeadlessForm>
70
69
  * ```
71
70
  */
72
- let HeadlessFormComponent = (_class3 = class HeadlessFormComponent extends Component {
71
+ let HeadlessFormComponent = setComponentTemplate(precompileTemplate(`
72
+ <form
73
+ novalidate
74
+ ...attributes
75
+ {{this.registerForm}}
76
+ {{on "submit" this.onSubmit}}
77
+ {{on "reset" this.onReset}}
78
+ {{this.onValidation this.fieldValidationEvent this.handleFieldValidation}}
79
+ {{this.onValidation
80
+ this.fieldRevalidationEvent
81
+ this.handleFieldRevalidation
82
+ }}
83
+ >
84
+ {{yield
85
+ (hash
86
+ Field=(component
87
+ this.FieldComponent
88
+ data=this.effectiveData
89
+ set=this.set
90
+ errors=this.visibleErrors
91
+ registerField=this.registerField
92
+ unregisterField=this.unregisterField
93
+ triggerValidationFor=this.handleFieldValidation
94
+ fieldValidationEvent=this.fieldValidationEvent
95
+ fieldRevalidationEvent=this.fieldRevalidationEvent
96
+ )
97
+ validationState=this.validationState
98
+ submissionState=this.submissionState
99
+ isInvalid=this.hasValidationErrors
100
+ rawErrors=this.visibleErrors
101
+ submit=this.onSubmit
102
+ reset=this.onReset
103
+ )
104
+ }}
105
+ </form>
106
+ `, {
107
+ strictMode: true,
108
+ scope: () => ({
109
+ on,
110
+ hash
111
+ })
112
+ }), (_class3 = class HeadlessFormComponent extends Component {
73
113
  constructor(...args) {
74
114
  super(...args);
75
115
  _defineProperty(this, "FieldComponent", HeadlessFormFieldComponent);
76
- _defineProperty(this, "on", on);
77
116
  _defineProperty(this, "formElement", void 0);
78
117
  _defineProperty(this, "registerForm", modifier((el, _p) => {
79
118
  this.formElement = el;
80
119
  }));
81
- _defineProperty(this, "internalData", this.args.dataMode == 'mutable' && this.args.data ? this.args.data : new TrackedObject(this.args.data ?? {}));
120
+ _defineProperty(this, "internalData", new TrackedObject({}));
82
121
  _defineProperty(this, "fields", new Map());
83
122
  _initializerDefineProperty(this, "validationState", _descriptor2, this);
84
123
  _initializerDefineProperty(this, "submissionState", _descriptor3, this);
85
124
  _initializerDefineProperty(this, "showAllValidations", _descriptor4, this);
125
+ _defineProperty(this, "onValidation", modifier((el, [eventName, handler]) => {
126
+ if (eventName) {
127
+ el.addEventListener(eventName, handler);
128
+ return () => el.removeEventListener(eventName, handler);
129
+ }
130
+ }));
131
+ }
132
+ get effectiveData() {
133
+ const obj = this.args.data ?? {};
134
+ if (this.args.dataMode === 'mutable') {
135
+ return obj;
136
+ }
137
+ const {
138
+ internalData
139
+ } = this;
140
+ return new Proxy(obj, {
141
+ get(target, prop) {
142
+ return prop in internalData ? internalData[prop] : Reflect.get(target, prop);
143
+ },
144
+ set(target, property, value) {
145
+ return Reflect.set(internalData, property, value);
146
+ },
147
+ has(target, prop) {
148
+ return prop in internalData ? true : Reflect.has(target, prop);
149
+ },
150
+ getOwnPropertyDescriptor(target, prop) {
151
+ return Reflect.getOwnPropertyDescriptor(prop in internalData ? internalData : target, prop);
152
+ },
153
+ ownKeys(target) {
154
+ return [...Reflect.ownKeys(target), ...Reflect.ownKeys(internalData)]
155
+ // return only unique values
156
+ .filter((value, index, array) => array.indexOf(value) === index);
157
+ },
158
+ deleteProperty(target, prop) {
159
+ if (prop in internalData) {
160
+ delete internalData[prop];
161
+ }
162
+ return true;
163
+ }
164
+ });
86
165
  }
87
166
  get validateOn() {
88
167
  return this.args.validateOn ?? 'submit';
@@ -134,11 +213,11 @@ let HeadlessFormComponent = (_class3 = class HeadlessFormComponent extends Compo
134
213
  * Call the passed validation callbacks, defined both on the whole form as well as on field level, and return the merged result for all fields.
135
214
  */
136
215
  async validate() {
137
- const nativeValidation = this.validateNative();
138
- const customFormValidation = await this.args.validate?.(this.internalData, Array.from(this.fields.keys()));
216
+ const nativeValidation = this.args.ignoreNativeValidation !== true ? this.validateNative() : {};
217
+ const customFormValidation = await this.args.validate?.(this.effectiveData, Array.from(this.fields.keys()));
139
218
  const customFieldValidations = [];
140
219
  for (const [name, field] of this.fields) {
141
- const fieldValidationResult = await field.validate?.(this.internalData[name], name, this.internalData);
220
+ const fieldValidationResult = await field.validate?.(this.effectiveData[name], name, this.effectiveData);
142
221
  if (fieldValidationResult) {
143
222
  customFieldValidations.push({
144
223
  [name]: fieldValidationResult
@@ -169,7 +248,7 @@ let HeadlessFormComponent = (_class3 = class HeadlessFormComponent extends Compo
169
248
  if (this.fields.has(name)) {
170
249
  errors[name] = [{
171
250
  type: 'native',
172
- value: this.internalData[name],
251
+ value: this.effectiveData[name],
173
252
  message: el.validationMessage
174
253
  }];
175
254
  } else {
@@ -206,17 +285,25 @@ let HeadlessFormComponent = (_class3 = class HeadlessFormComponent extends Compo
206
285
  return this.showAllValidations || (this.fields.get(field)?.validationEnabled ?? false);
207
286
  }
208
287
  async onSubmit(e) {
209
- e.preventDefault();
288
+ e?.preventDefault();
210
289
  await this._validate();
211
290
  this.showAllValidations = true;
212
291
  if (!this.hasValidationErrors) {
213
292
  if (this.args.onSubmit) {
214
- this.submissionState = new TrackedAsyncData(this.args.onSubmit(this.internalData), this);
293
+ this.submissionState = new TrackedAsyncData(this.args.onSubmit(this.effectiveData), this);
215
294
  }
216
295
  } else {
217
296
  assert('Validation errors expected to be present. If you see this, please report it as a bug to ember-headless-form!', this.validationState?.isResolved);
218
- this.args.onInvalid?.(this.internalData, this.validationState.value);
297
+ this.args.onInvalid?.(this.effectiveData, this.validationState.value);
298
+ }
299
+ }
300
+ async onReset(e) {
301
+ e?.preventDefault();
302
+ for (const key of Object.keys(this.internalData)) {
303
+ delete this.internalData[key];
219
304
  }
305
+ this.validationState = undefined;
306
+ this.submissionState = undefined;
220
307
  }
221
308
  registerField(name, field) {
222
309
  assert(`You passed @name="${String(name)}" to the form field, but this is already in use. Names of form fields must be unique!`, !this.fields.has(name));
@@ -226,8 +313,8 @@ let HeadlessFormComponent = (_class3 = class HeadlessFormComponent extends Compo
226
313
  this.fields.delete(name);
227
314
  }
228
315
  set(key, value) {
229
- // when @mutableData is set, our internalData is something we don't control, i.e. might require old-school set() to be on the safe side
230
- set(this.internalData, key, value);
316
+ // when @mutableData is set, our effectiveData is something we don't control, i.e. might require old-school set() to be on the safe side
317
+ set(this.effectiveData, key, value);
231
318
  }
232
319
 
233
320
  /**
@@ -282,7 +369,7 @@ let HeadlessFormComponent = (_class3 = class HeadlessFormComponent extends Compo
282
369
  });
283
370
  }
284
371
  }
285
- }, (_descriptor2 = _applyDecoratedDescriptor(_class3.prototype, "validationState", [tracked], {
372
+ }, (_applyDecoratedDescriptor(_class3.prototype, "effectiveData", [cached], Object.getOwnPropertyDescriptor(_class3.prototype, "effectiveData"), _class3.prototype), _descriptor2 = _applyDecoratedDescriptor(_class3.prototype, "validationState", [tracked], {
286
373
  configurable: true,
287
374
  enumerable: true,
288
375
  writable: true,
@@ -299,8 +386,7 @@ let HeadlessFormComponent = (_class3 = class HeadlessFormComponent extends Compo
299
386
  initializer: function () {
300
387
  return false;
301
388
  }
302
- }), _applyDecoratedDescriptor(_class3.prototype, "onSubmit", [action], Object.getOwnPropertyDescriptor(_class3.prototype, "onSubmit"), _class3.prototype), _applyDecoratedDescriptor(_class3.prototype, "registerField", [action], Object.getOwnPropertyDescriptor(_class3.prototype, "registerField"), _class3.prototype), _applyDecoratedDescriptor(_class3.prototype, "unregisterField", [action], Object.getOwnPropertyDescriptor(_class3.prototype, "unregisterField"), _class3.prototype), _applyDecoratedDescriptor(_class3.prototype, "set", [action], Object.getOwnPropertyDescriptor(_class3.prototype, "set"), _class3.prototype), _applyDecoratedDescriptor(_class3.prototype, "handleFieldValidation", [action], Object.getOwnPropertyDescriptor(_class3.prototype, "handleFieldValidation"), _class3.prototype), _applyDecoratedDescriptor(_class3.prototype, "handleFieldRevalidation", [action], Object.getOwnPropertyDescriptor(_class3.prototype, "handleFieldRevalidation"), _class3.prototype)), _class3);
303
- setComponentTemplate(TEMPLATE, HeadlessFormComponent);
389
+ }), _applyDecoratedDescriptor(_class3.prototype, "onSubmit", [action], Object.getOwnPropertyDescriptor(_class3.prototype, "onSubmit"), _class3.prototype), _applyDecoratedDescriptor(_class3.prototype, "onReset", [action], Object.getOwnPropertyDescriptor(_class3.prototype, "onReset"), _class3.prototype), _applyDecoratedDescriptor(_class3.prototype, "registerField", [action], Object.getOwnPropertyDescriptor(_class3.prototype, "registerField"), _class3.prototype), _applyDecoratedDescriptor(_class3.prototype, "unregisterField", [action], Object.getOwnPropertyDescriptor(_class3.prototype, "unregisterField"), _class3.prototype), _applyDecoratedDescriptor(_class3.prototype, "set", [action], Object.getOwnPropertyDescriptor(_class3.prototype, "set"), _class3.prototype), _applyDecoratedDescriptor(_class3.prototype, "handleFieldValidation", [action], Object.getOwnPropertyDescriptor(_class3.prototype, "handleFieldValidation"), _class3.prototype), _applyDecoratedDescriptor(_class3.prototype, "handleFieldRevalidation", [action], Object.getOwnPropertyDescriptor(_class3.prototype, "handleFieldRevalidation"), _class3.prototype)), _class3));
304
390
 
305
391
  export { HeadlessFormComponent as default };
306
392
  //# sourceMappingURL=headless-form.js.map