@samline/forms 2.2.2 → 2.3.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/README.md +3 -3
- package/dist/browser/global.d.ts +16 -5
- package/dist/browser/global.global.js +179 -88
- package/dist/browser/global.global.js.map +1 -1
- package/dist/index.cjs +179 -88
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +16 -5
- package/dist/index.d.ts +16 -5
- package/dist/index.js +179 -88
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -42,10 +42,10 @@ Requires Node 20+ when bundling. Runtime target is ES2020.
|
|
|
42
42
|
Use the browser build when you do not have a bundler and need to run the package directly in HTML, Shopify, WordPress, or any traditional template.
|
|
43
43
|
|
|
44
44
|
```html
|
|
45
|
-
<script src="https://unpkg.com/@samline/forms@2.
|
|
45
|
+
<script src="https://unpkg.com/@samline/forms@2.3.0/dist/browser/global.global.js"></script>
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
-
> Pin the version in production. Replace `2.
|
|
48
|
+
> Pin the version in production. Replace `2.3.0` with the version you ship.
|
|
49
49
|
|
|
50
50
|
The browser bundle exposes a single global: `window.Forms`.
|
|
51
51
|
|
|
@@ -55,7 +55,7 @@ The browser bundle exposes a single global: `window.Forms`.
|
|
|
55
55
|
<button type="submit">Send</button>
|
|
56
56
|
</form>
|
|
57
57
|
|
|
58
|
-
<script src="https://unpkg.com/@samline/forms@2.
|
|
58
|
+
<script src="https://unpkg.com/@samline/forms@2.3.0/dist/browser/global.global.js"></script>
|
|
59
59
|
<script>
|
|
60
60
|
const contactForm = window.Forms.newForm({ id: 'contact-form' })
|
|
61
61
|
|
package/dist/browser/global.d.ts
CHANGED
|
@@ -2,14 +2,25 @@ type FormatType = 'general' | 'phone' | 'numeral' | 'date' | 'time' | 'creditCar
|
|
|
2
2
|
interface FieldFormatConfig {
|
|
3
3
|
/** One of the supported `@samline/formatter` `FormatType` values. */
|
|
4
4
|
type: FormatType;
|
|
5
|
-
/**
|
|
5
|
+
/**
|
|
6
|
+
* Canonical name of the formatted field. The value the backend
|
|
7
|
+
* ultimately receives (the `raw` output of the formatter) is
|
|
8
|
+
* exposed under this name; the formatter is responsible for
|
|
9
|
+
* keeping it in sync with the visible input.
|
|
10
|
+
*/
|
|
6
11
|
field: string | string[];
|
|
7
12
|
/**
|
|
8
|
-
*
|
|
9
|
-
* `${fieldName}
|
|
10
|
-
*
|
|
13
|
+
* Name of the visible input that shows the formatted value to
|
|
14
|
+
* the user. Defaults to `${fieldName}_displayed`.
|
|
15
|
+
*
|
|
16
|
+
* The visible is **renamed** from `field` to `displayField` on
|
|
17
|
+
* the first `format()` call (idempotent on re-binding). A hidden
|
|
18
|
+
* `<input type="hidden" name="<field>">` is created next to it
|
|
19
|
+
* to carry the raw value. Both names are first-class in the
|
|
20
|
+
* controller's API (`getValue`, `getField`, `setValue`, `watch`,
|
|
21
|
+
* `getData`) — see `docs/api/format.md` for the full contract.
|
|
11
22
|
*/
|
|
12
|
-
|
|
23
|
+
displayField?: string;
|
|
13
24
|
/**
|
|
14
25
|
* Format-specific options forwarded to `@samline/formatter`.
|
|
15
26
|
* Any key documented for the chosen `type` is accepted (e.g.
|
|
@@ -4665,50 +4665,75 @@ var Forms = (() => {
|
|
|
4665
4665
|
}
|
|
4666
4666
|
return value.replace(/([!"#$%&'()*+,./:;<=>?@\[\\\]^`{|}~])/g, "\\$1");
|
|
4667
4667
|
};
|
|
4668
|
-
var
|
|
4668
|
+
var findVisibleField = (form2, displayName) => {
|
|
4669
|
+
const node = form2.querySelector(
|
|
4670
|
+
`[name="${cssEscape(displayName)}"]:not([type="hidden"])`
|
|
4671
|
+
);
|
|
4672
|
+
if (node instanceof HTMLInputElement || node instanceof HTMLTextAreaElement) {
|
|
4673
|
+
return node;
|
|
4674
|
+
}
|
|
4675
|
+
return null;
|
|
4676
|
+
};
|
|
4677
|
+
var findHiddenMirror = (form2, fieldName) => {
|
|
4669
4678
|
const byAttr = form2.querySelector(
|
|
4670
4679
|
`[${FORMATTER_RAW_ATTRIBUTE}="${cssEscape(fieldName)}"]`
|
|
4671
4680
|
);
|
|
4672
4681
|
if (byAttr) return byAttr;
|
|
4673
4682
|
const byName = form2.querySelector(
|
|
4674
|
-
`[name="${cssEscape(
|
|
4683
|
+
`input[type="hidden"][name="${cssEscape(fieldName)}"]`
|
|
4675
4684
|
);
|
|
4676
4685
|
if (byName) return byName;
|
|
4677
|
-
const byNameOld = form2.querySelector(
|
|
4678
|
-
`[name="${cssEscape(`${fieldName}Raw`)}"]`
|
|
4679
|
-
);
|
|
4680
|
-
if (byNameOld) return byNameOld;
|
|
4681
4686
|
return null;
|
|
4682
4687
|
};
|
|
4683
|
-
var
|
|
4684
|
-
const existing =
|
|
4688
|
+
var ensureHiddenMirror = (form2, fieldName) => {
|
|
4689
|
+
const existing = findHiddenMirror(form2, fieldName);
|
|
4685
4690
|
if (existing) return existing;
|
|
4686
4691
|
const input = document.createElement("input");
|
|
4687
4692
|
input.type = "hidden";
|
|
4688
|
-
input.name =
|
|
4693
|
+
input.name = fieldName;
|
|
4689
4694
|
input.setAttribute("aria-hidden", "true");
|
|
4690
4695
|
input.tabIndex = -1;
|
|
4691
4696
|
input.setAttribute(FORMATTER_RAW_ATTRIBUTE, fieldName);
|
|
4692
4697
|
form2.appendChild(input);
|
|
4693
4698
|
return input;
|
|
4694
4699
|
};
|
|
4695
|
-
var
|
|
4700
|
+
var renameVisibleField = (visible, displayName) => {
|
|
4701
|
+
if (visible.name === displayName) return;
|
|
4702
|
+
visible.name = displayName;
|
|
4703
|
+
};
|
|
4704
|
+
var restoreVisibleName = (visible, originalName) => {
|
|
4705
|
+
visible.name = originalName;
|
|
4706
|
+
};
|
|
4707
|
+
var applyFormattedValue = (visible, mirror, formatted, raw, inputType) => {
|
|
4696
4708
|
const rawInput = visible.value;
|
|
4697
4709
|
const caret = clamp(
|
|
4698
4710
|
visible.selectionStart ?? rawInput.length,
|
|
4699
4711
|
0,
|
|
4700
4712
|
rawInput.length
|
|
4701
4713
|
);
|
|
4714
|
+
if (mirror && mirror.value !== raw) mirror.value = raw;
|
|
4702
4715
|
if (rawInput === formatted) {
|
|
4703
|
-
|
|
4704
|
-
|
|
4716
|
+
const newCaret2 = pullCaretPastLeadingDelimiter(caret, formatted, inputType);
|
|
4717
|
+
if (newCaret2 !== caret) restoreCursor(visible, newCaret2);
|
|
4718
|
+
return newCaret2;
|
|
4705
4719
|
}
|
|
4706
4720
|
visible.value = formatted;
|
|
4707
|
-
|
|
4708
|
-
|
|
4721
|
+
const newCaret = pullCaretPastLeadingDelimiter(
|
|
4722
|
+
computeCursorPosition(caret, rawInput, formatted),
|
|
4723
|
+
formatted,
|
|
4724
|
+
inputType
|
|
4725
|
+
);
|
|
4709
4726
|
restoreCursor(visible, newCaret);
|
|
4710
4727
|
return newCaret;
|
|
4711
4728
|
};
|
|
4729
|
+
var pullCaretPastLeadingDelimiter = (caret, value, inputType) => {
|
|
4730
|
+
if (!inputType || !inputType.startsWith("delete")) return caret;
|
|
4731
|
+
let cursor = caret;
|
|
4732
|
+
while (cursor > 0 && isFormatChar(value[cursor - 1])) {
|
|
4733
|
+
cursor -= 1;
|
|
4734
|
+
}
|
|
4735
|
+
return cursor;
|
|
4736
|
+
};
|
|
4712
4737
|
var clamp = (value, min, max) => Math.max(min, Math.min(max, value));
|
|
4713
4738
|
var computeCursorPosition = (caretPos, rawInput, newValue) => {
|
|
4714
4739
|
if (newValue.length === 0) return 0;
|
|
@@ -4796,6 +4821,7 @@ var Forms = (() => {
|
|
|
4796
4821
|
};
|
|
4797
4822
|
|
|
4798
4823
|
// src/api/format.ts
|
|
4824
|
+
var UNBOUND = null;
|
|
4799
4825
|
var registry = /* @__PURE__ */ new WeakMap();
|
|
4800
4826
|
var getRegistry = (state2) => {
|
|
4801
4827
|
let bucket = registry.get(state2);
|
|
@@ -4806,94 +4832,128 @@ var Forms = (() => {
|
|
|
4806
4832
|
return bucket;
|
|
4807
4833
|
};
|
|
4808
4834
|
var resolveFieldNames = (config) => Array.isArray(config.field) ? config.field : [config.field];
|
|
4809
|
-
var addListener = (state2, target, type, handler) => {
|
|
4810
|
-
|
|
4811
|
-
|
|
4835
|
+
var addListener = (state2, target, type, handler, useCapture) => {
|
|
4836
|
+
if (useCapture) {
|
|
4837
|
+
target.addEventListener(type, handler, { capture: true });
|
|
4838
|
+
} else {
|
|
4839
|
+
target.addEventListener(type, handler);
|
|
4840
|
+
}
|
|
4841
|
+
const entry = { element: target, type, handler };
|
|
4842
|
+
if (useCapture !== void 0) entry.capture = useCapture;
|
|
4843
|
+
state2.listeners.push(entry);
|
|
4844
|
+
};
|
|
4845
|
+
var readInputType = (event) => {
|
|
4846
|
+
const candidate = event;
|
|
4847
|
+
return typeof candidate.inputType === "string" ? candidate.inputType : void 0;
|
|
4812
4848
|
};
|
|
4813
|
-
var buildHandler = (
|
|
4849
|
+
var buildHandler = (visible, mirror, formatFn, formatType, formatOptions) => {
|
|
4814
4850
|
const handler = (event) => {
|
|
4815
|
-
if (!
|
|
4816
|
-
|
|
4817
|
-
const
|
|
4851
|
+
if (!visible.isConnected || !mirror.isConnected) return;
|
|
4852
|
+
const isVisible = event.target === visible;
|
|
4853
|
+
const isMirror = event.target === mirror;
|
|
4854
|
+
if (!isVisible && !isMirror) return;
|
|
4855
|
+
const rawInput = isMirror ? mirror.value : visible.value;
|
|
4856
|
+
const inputType = readInputType(event);
|
|
4818
4857
|
const { formatted, raw } = formatFn(rawInput, formatType, formatOptions);
|
|
4819
4858
|
if (!formatted && !raw) {
|
|
4820
|
-
|
|
4821
|
-
if (mirror
|
|
4859
|
+
visible.value = "";
|
|
4860
|
+
if (mirror.value !== "") mirror.value = "";
|
|
4822
4861
|
return;
|
|
4823
4862
|
}
|
|
4824
|
-
applyFormattedValue(
|
|
4825
|
-
void mirrorFieldName;
|
|
4863
|
+
applyFormattedValue(visible, mirror, formatted, raw, inputType);
|
|
4826
4864
|
};
|
|
4827
4865
|
return handler;
|
|
4828
4866
|
};
|
|
4829
4867
|
var applyFormat = async (state2, helpers, config) => {
|
|
4830
4868
|
if (!state2.element || !state2.api) return;
|
|
4831
|
-
const formatter = await loadFormatter();
|
|
4832
|
-
if (!formatter) return;
|
|
4833
4869
|
const formatType = config.type;
|
|
4834
4870
|
const formatOptions = config.options;
|
|
4835
4871
|
const fieldNames = resolveFieldNames(config);
|
|
4836
4872
|
const bucket = getRegistry(state2);
|
|
4837
4873
|
for (const fieldName of fieldNames) {
|
|
4838
|
-
const
|
|
4839
|
-
|
|
4840
|
-
const
|
|
4841
|
-
(f2) => f2 instanceof HTMLInputElement && f2.type !== "
|
|
4874
|
+
const displayName = config.displayField ?? `${fieldName}_displayed`;
|
|
4875
|
+
const canonicalFields = helpers.getFieldsByName(fieldName);
|
|
4876
|
+
const candidates = canonicalFields.filter(
|
|
4877
|
+
(f2) => f2 instanceof HTMLInputElement && f2.type !== "hidden" || f2 instanceof HTMLTextAreaElement
|
|
4842
4878
|
);
|
|
4843
|
-
|
|
4844
|
-
|
|
4845
|
-
|
|
4846
|
-
|
|
4847
|
-
|
|
4848
|
-
|
|
4849
|
-
|
|
4850
|
-
|
|
4851
|
-
|
|
4852
|
-
|
|
4853
|
-
|
|
4854
|
-
|
|
4855
|
-
|
|
4856
|
-
|
|
4857
|
-
|
|
4858
|
-
|
|
4859
|
-
});
|
|
4860
|
-
const current = field.value;
|
|
4861
|
-
if (current !== "") {
|
|
4862
|
-
const { formatted, raw } = formatter.format(current, formatType, formatOptions);
|
|
4863
|
-
applyFormattedValue(field, mirror, formatted, raw);
|
|
4864
|
-
}
|
|
4865
|
-
continue;
|
|
4866
|
-
}
|
|
4867
|
-
const handler = buildHandler(
|
|
4868
|
-
field,
|
|
4869
|
-
mirror,
|
|
4870
|
-
formatter.format,
|
|
4871
|
-
formatType,
|
|
4872
|
-
formatOptions,
|
|
4873
|
-
trackerMirrorName
|
|
4874
|
-
);
|
|
4875
|
-
addListener(state2, state2.element, "input", handler);
|
|
4876
|
-
bucket.set(fieldName, {
|
|
4877
|
-
fields: /* @__PURE__ */ new Set([field]),
|
|
4878
|
-
mirrorName: trackerMirrorName,
|
|
4879
|
-
handler,
|
|
4879
|
+
let visible = candidates[0] ?? null;
|
|
4880
|
+
if (!visible) {
|
|
4881
|
+
visible = findVisibleField(state2.element, displayName);
|
|
4882
|
+
}
|
|
4883
|
+
if (!visible) continue;
|
|
4884
|
+
const existing = bucket.get(fieldName);
|
|
4885
|
+
let mirror = findHiddenMirror(state2.element, fieldName);
|
|
4886
|
+
const mirrorIsOwned = !mirror;
|
|
4887
|
+
if (!mirror) mirror = ensureHiddenMirror(state2.element, fieldName);
|
|
4888
|
+
renameVisibleField(visible, displayName);
|
|
4889
|
+
if (existing) {
|
|
4890
|
+
existing.displayName = displayName;
|
|
4891
|
+
existing.mirrorIsOwned = mirrorIsOwned;
|
|
4892
|
+
state2.formattedFields.set(fieldName, {
|
|
4893
|
+
config,
|
|
4894
|
+
displayName,
|
|
4880
4895
|
mirrorIsOwned
|
|
4881
4896
|
});
|
|
4897
|
+
} else {
|
|
4898
|
+
bucket.set(fieldName, {
|
|
4899
|
+
canonicalName: fieldName,
|
|
4900
|
+
displayName,
|
|
4901
|
+
visible,
|
|
4902
|
+
mirror,
|
|
4903
|
+
mirrorIsOwned,
|
|
4904
|
+
handler: UNBOUND
|
|
4905
|
+
});
|
|
4882
4906
|
state2.formattedFields.set(fieldName, {
|
|
4883
4907
|
config,
|
|
4884
|
-
|
|
4908
|
+
displayName,
|
|
4885
4909
|
mirrorIsOwned
|
|
4886
4910
|
});
|
|
4887
|
-
|
|
4888
|
-
|
|
4889
|
-
|
|
4890
|
-
|
|
4891
|
-
|
|
4892
|
-
|
|
4911
|
+
}
|
|
4912
|
+
}
|
|
4913
|
+
const formatter = await loadFormatter();
|
|
4914
|
+
if (!formatter) {
|
|
4915
|
+
rollbackPhase1(bucket, state2.formattedFields);
|
|
4916
|
+
return;
|
|
4917
|
+
}
|
|
4918
|
+
for (const [, entry] of bucket) {
|
|
4919
|
+
if (entry.handler !== UNBOUND) {
|
|
4920
|
+
const current = entry.visible.value;
|
|
4921
|
+
if (current !== "") {
|
|
4922
|
+
const { formatted, raw } = formatter.format(current, formatType, formatOptions);
|
|
4923
|
+
applyFormattedValue(entry.visible, entry.mirror, formatted, raw);
|
|
4893
4924
|
}
|
|
4925
|
+
continue;
|
|
4926
|
+
}
|
|
4927
|
+
const handler = buildHandler(
|
|
4928
|
+
entry.visible,
|
|
4929
|
+
entry.mirror,
|
|
4930
|
+
formatter.format,
|
|
4931
|
+
formatType,
|
|
4932
|
+
formatOptions
|
|
4933
|
+
);
|
|
4934
|
+
addListener(state2, state2.element, "input", handler, true);
|
|
4935
|
+
entry.handler = handler;
|
|
4936
|
+
const initial = entry.visible.value;
|
|
4937
|
+
if (initial !== "") {
|
|
4938
|
+
const { formatted, raw } = formatter.format(initial, formatType, formatOptions);
|
|
4939
|
+
applyFormattedValue(entry.visible, entry.mirror, formatted, raw);
|
|
4940
|
+
} else if (entry.mirrorIsOwned && entry.mirror.value !== "") {
|
|
4941
|
+
entry.mirror.value = "";
|
|
4894
4942
|
}
|
|
4895
4943
|
}
|
|
4896
4944
|
};
|
|
4945
|
+
var rollbackPhase1 = (bucket, registry2) => {
|
|
4946
|
+
for (const [fieldName, entry] of bucket) {
|
|
4947
|
+
if (entry.visible.isConnected) {
|
|
4948
|
+
restoreVisibleName(entry.visible, fieldName);
|
|
4949
|
+
}
|
|
4950
|
+
if (entry.mirrorIsOwned && entry.mirror.isConnected) {
|
|
4951
|
+
entry.mirror.remove();
|
|
4952
|
+
}
|
|
4953
|
+
bucket.delete(fieldName);
|
|
4954
|
+
registry2.delete(fieldName);
|
|
4955
|
+
}
|
|
4956
|
+
};
|
|
4897
4957
|
var createFormat = (state2, helpers) => (config) => {
|
|
4898
4958
|
if (state2.isDestroyed) return state2.api;
|
|
4899
4959
|
if (!state2.element) return state2.api;
|
|
@@ -4901,6 +4961,14 @@ var Forms = (() => {
|
|
|
4901
4961
|
return state2.api;
|
|
4902
4962
|
};
|
|
4903
4963
|
var createFormatAll = createFormat;
|
|
4964
|
+
var resolveCanonicalForName = (state2, name) => {
|
|
4965
|
+
const bucket = registry.get(state2);
|
|
4966
|
+
if (!bucket) return null;
|
|
4967
|
+
for (const [canonical, entry] of bucket) {
|
|
4968
|
+
if (canonical === name || entry.displayName === name) return canonical;
|
|
4969
|
+
}
|
|
4970
|
+
return null;
|
|
4971
|
+
};
|
|
4904
4972
|
var cleanupFormatRegistry = (state2) => {
|
|
4905
4973
|
if (!state2.element) {
|
|
4906
4974
|
registry.delete(state2);
|
|
@@ -4912,10 +4980,14 @@ var Forms = (() => {
|
|
|
4912
4980
|
return;
|
|
4913
4981
|
}
|
|
4914
4982
|
for (const [fieldName, entry] of bucket) {
|
|
4915
|
-
|
|
4916
|
-
|
|
4917
|
-
|
|
4918
|
-
|
|
4983
|
+
if (entry.handler !== UNBOUND) {
|
|
4984
|
+
state2.element.removeEventListener("input", entry.handler, true);
|
|
4985
|
+
}
|
|
4986
|
+
if (entry.visible.isConnected) {
|
|
4987
|
+
restoreVisibleName(entry.visible, fieldName);
|
|
4988
|
+
}
|
|
4989
|
+
if (entry.mirrorIsOwned && entry.mirror.isConnected) {
|
|
4990
|
+
entry.mirror.remove();
|
|
4919
4991
|
}
|
|
4920
4992
|
bucket.delete(fieldName);
|
|
4921
4993
|
state2.formattedFields.delete(fieldName);
|
|
@@ -4928,7 +5000,12 @@ var Forms = (() => {
|
|
|
4928
5000
|
if (state2.isDestroyed) return;
|
|
4929
5001
|
state2.isDestroyed = true;
|
|
4930
5002
|
for (const listener of state2.listeners) {
|
|
4931
|
-
listener.
|
|
5003
|
+
const options = listener.capture ? { capture: true } : void 0;
|
|
5004
|
+
if (options) {
|
|
5005
|
+
listener.element.removeEventListener(listener.type, listener.handler, options);
|
|
5006
|
+
} else {
|
|
5007
|
+
listener.element.removeEventListener(listener.type, listener.handler);
|
|
5008
|
+
}
|
|
4932
5009
|
}
|
|
4933
5010
|
state2.listeners.length = 0;
|
|
4934
5011
|
if (state2.autoSubmitTimer) {
|
|
@@ -5365,9 +5442,15 @@ var Forms = (() => {
|
|
|
5365
5442
|
const snapshot = state2.api.getState();
|
|
5366
5443
|
state2.subscribers.forEach((listener) => listener(snapshot));
|
|
5367
5444
|
};
|
|
5368
|
-
const addListener2 = (node, type, handler) => {
|
|
5369
|
-
|
|
5370
|
-
|
|
5445
|
+
const addListener2 = (node, type, handler, capture) => {
|
|
5446
|
+
if (capture) {
|
|
5447
|
+
node.addEventListener(type, handler, { capture: true });
|
|
5448
|
+
} else {
|
|
5449
|
+
node.addEventListener(type, handler);
|
|
5450
|
+
}
|
|
5451
|
+
const entry = { element: node, type, handler };
|
|
5452
|
+
if (capture !== void 0) entry.capture = capture;
|
|
5453
|
+
state2.listeners.push(entry);
|
|
5371
5454
|
};
|
|
5372
5455
|
const clearFieldCache = () => state2.fieldCache.clear();
|
|
5373
5456
|
const getFieldsByName = (name) => {
|
|
@@ -5383,6 +5466,12 @@ var Forms = (() => {
|
|
|
5383
5466
|
for (const field of getNamedFields(state2.element)) {
|
|
5384
5467
|
names.add(field.name);
|
|
5385
5468
|
}
|
|
5469
|
+
for (const [canonical, entry] of state2.formattedFields) {
|
|
5470
|
+
names.add(canonical);
|
|
5471
|
+
if (entry.displayName && entry.displayName !== canonical) {
|
|
5472
|
+
names.add(entry.displayName);
|
|
5473
|
+
}
|
|
5474
|
+
}
|
|
5386
5475
|
return Array.from(names);
|
|
5387
5476
|
};
|
|
5388
5477
|
const getValues = () => {
|
|
@@ -5468,14 +5557,16 @@ var Forms = (() => {
|
|
|
5468
5557
|
const name = target2.name;
|
|
5469
5558
|
if (!name) return;
|
|
5470
5559
|
clearFieldCache();
|
|
5560
|
+
const canonical = resolveCanonicalForName(state2, name) ?? name;
|
|
5471
5561
|
if (normalizedOptions.clearManualErrorsOnChange) {
|
|
5472
|
-
delete state2.manualErrors[
|
|
5562
|
+
delete state2.manualErrors[canonical];
|
|
5473
5563
|
}
|
|
5474
|
-
syncVisualState([
|
|
5475
|
-
if (state2.isValidated && state2.validators[
|
|
5476
|
-
validateNames([
|
|
5564
|
+
syncVisualState([canonical]);
|
|
5565
|
+
if (state2.isValidated && state2.validators[canonical]) {
|
|
5566
|
+
validateNames([canonical]);
|
|
5477
5567
|
}
|
|
5478
|
-
emitFieldWatchers(
|
|
5568
|
+
emitFieldWatchers(canonical);
|
|
5569
|
+
if (canonical !== name) emitFieldWatchers(name);
|
|
5479
5570
|
notifySubscribers();
|
|
5480
5571
|
scheduleAutoSubmit();
|
|
5481
5572
|
};
|