tyrell-components 1.0.0-TC56 → 1.0.0-TC58
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/css/tyrell.css +3 -3
- package/dist/tyrell.js +1 -1
- package/dist/tyrell.js.map +1 -0
- package/lib/base/ty-component.d.ts +15 -3
- package/lib/base/ty-component.js +26 -18
- package/lib/components/button.d.ts +4 -0
- package/lib/components/button.js +33 -6
- package/lib/components/calendar-month.js +3 -10
- package/lib/components/calendar.d.ts +5 -1
- package/lib/components/calendar.js +28 -34
- package/lib/components/checkbox.d.ts +3 -1
- package/lib/components/checkbox.js +9 -1
- package/lib/components/date-picker.d.ts +61 -7
- package/lib/components/date-picker.js +274 -133
- package/lib/components/file-upload.d.ts +4 -1
- package/lib/components/file-upload.js +17 -3
- package/lib/components/input.d.ts +82 -3
- package/lib/components/input.js +178 -20
- package/lib/components/modal.d.ts +2 -0
- package/lib/components/modal.js +49 -10
- package/lib/components/option.js +7 -5
- package/lib/components/popup.js +59 -10
- package/lib/components/radio.d.ts +4 -1
- package/lib/components/radio.js +10 -1
- package/lib/components/resize-observer.js +2 -0
- package/lib/components/scroll-container.js +2 -0
- package/lib/components/select.d.ts +34 -3
- package/lib/components/select.js +135 -11
- package/lib/components/selected-tags.d.ts +7 -1
- package/lib/components/selected-tags.js +10 -1
- package/lib/components/switch.d.ts +5 -1
- package/lib/components/switch.js +9 -1
- package/lib/components/textarea.d.ts +46 -2
- package/lib/components/textarea.js +60 -9
- package/lib/styles/button.js +20 -19
- package/lib/styles/date-picker.js +18 -1
- package/lib/styles/file-upload.d.ts +1 -1
- package/lib/styles/file-upload.js +3 -3
- package/lib/styles/icon.d.ts +1 -1
- package/lib/styles/icon.js +2 -2
- package/lib/styles/input.js +1 -1
- package/lib/styles/radio.js +2 -2
- package/lib/styles/select-base.js +26 -0
- package/lib/styles/textarea.d.ts +1 -1
- package/lib/styles/textarea.js +7 -0
- package/lib/utils/error-flavor.d.ts +8 -0
- package/lib/utils/error-flavor.js +1 -0
- package/lib/utils/property-manager.d.ts +6 -0
- package/lib/utils/property-manager.js +15 -5
- package/lib/utils/upgrade-properties.d.ts +21 -0
- package/lib/utils/upgrade-properties.js +47 -0
- package/lib/utils/validity.d.ts +72 -2
- package/lib/utils/validity.js +192 -8
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/package.json +3 -2
- package/lib/base/ty-component.d.ts.map +0 -1
- package/lib/base/ty-component.js.map +0 -1
- package/lib/components/button.d.ts.map +0 -1
- package/lib/components/button.js.map +0 -1
- package/lib/components/calendar-month.d.ts.map +0 -1
- package/lib/components/calendar-month.js.map +0 -1
- package/lib/components/calendar-navigation.d.ts.map +0 -1
- package/lib/components/calendar-navigation.js.map +0 -1
- package/lib/components/calendar.d.ts.map +0 -1
- package/lib/components/calendar.js.map +0 -1
- package/lib/components/checkbox.d.ts.map +0 -1
- package/lib/components/checkbox.js.map +0 -1
- package/lib/components/copy.d.ts.map +0 -1
- package/lib/components/copy.js.map +0 -1
- package/lib/components/date-picker.d.ts.map +0 -1
- package/lib/components/date-picker.js.map +0 -1
- package/lib/components/dropdown.d.ts +0 -403
- package/lib/components/dropdown.d.ts.map +0 -1
- package/lib/components/dropdown.js +0 -1315
- package/lib/components/dropdown.js.map +0 -1
- package/lib/components/icon.d.ts.map +0 -1
- package/lib/components/icon.js.map +0 -1
- package/lib/components/input.d.ts.map +0 -1
- package/lib/components/input.js.map +0 -1
- package/lib/components/modal.d.ts.map +0 -1
- package/lib/components/modal.js.map +0 -1
- package/lib/components/multiselect.d.ts +0 -389
- package/lib/components/multiselect.d.ts.map +0 -1
- package/lib/components/multiselect.js +0 -1301
- package/lib/components/multiselect.js.map +0 -1
- package/lib/components/option.d.ts.map +0 -1
- package/lib/components/option.js.map +0 -1
- package/lib/components/popup.d.ts.map +0 -1
- package/lib/components/popup.js.map +0 -1
- package/lib/components/resize-observer.d.ts.map +0 -1
- package/lib/components/resize-observer.js.map +0 -1
- package/lib/components/scroll-container.d.ts.map +0 -1
- package/lib/components/scroll-container.js.map +0 -1
- package/lib/components/step.d.ts.map +0 -1
- package/lib/components/step.js.map +0 -1
- package/lib/components/tab.d.ts.map +0 -1
- package/lib/components/tab.js.map +0 -1
- package/lib/components/tabs.d.ts.map +0 -1
- package/lib/components/tabs.js.map +0 -1
- package/lib/components/tag.d.ts.map +0 -1
- package/lib/components/tag.js.map +0 -1
- package/lib/components/textarea.d.ts.map +0 -1
- package/lib/components/textarea.js.map +0 -1
- package/lib/components/tooltip.d.ts.map +0 -1
- package/lib/components/tooltip.js.map +0 -1
- package/lib/components/wizard.d.ts.map +0 -1
- package/lib/components/wizard.js.map +0 -1
- package/lib/icons/fontawesome/brands.d.ts.map +0 -1
- package/lib/icons/fontawesome/brands.js.map +0 -1
- package/lib/icons/fontawesome/regular.d.ts.map +0 -1
- package/lib/icons/fontawesome/regular.js.map +0 -1
- package/lib/icons/fontawesome/solid.d.ts.map +0 -1
- package/lib/icons/fontawesome/solid.js.map +0 -1
- package/lib/icons/heroicons/micro.d.ts.map +0 -1
- package/lib/icons/heroicons/micro.js.map +0 -1
- package/lib/icons/heroicons/mini.d.ts.map +0 -1
- package/lib/icons/heroicons/mini.js.map +0 -1
- package/lib/icons/heroicons/outline.d.ts.map +0 -1
- package/lib/icons/heroicons/outline.js.map +0 -1
- package/lib/icons/heroicons/solid.d.ts.map +0 -1
- package/lib/icons/heroicons/solid.js.map +0 -1
- package/lib/icons/lucide.d.ts.map +0 -1
- package/lib/icons/lucide.js.map +0 -1
- package/lib/icons/material/filled.d.ts.map +0 -1
- package/lib/icons/material/filled.js.map +0 -1
- package/lib/icons/material/outlined.d.ts.map +0 -1
- package/lib/icons/material/outlined.js.map +0 -1
- package/lib/icons/material/round.d.ts.map +0 -1
- package/lib/icons/material/round.js.map +0 -1
- package/lib/icons/material/sharp.d.ts.map +0 -1
- package/lib/icons/material/sharp.js.map +0 -1
- package/lib/icons/material/two-tone.d.ts.map +0 -1
- package/lib/icons/material/two-tone.js.map +0 -1
- package/lib/index.d.ts.map +0 -1
- package/lib/index.js.map +0 -1
- package/lib/styles/button.d.ts.map +0 -1
- package/lib/styles/button.js.map +0 -1
- package/lib/styles/calendar-month.d.ts.map +0 -1
- package/lib/styles/calendar-month.js.map +0 -1
- package/lib/styles/calendar-navigation.d.ts.map +0 -1
- package/lib/styles/calendar-navigation.js.map +0 -1
- package/lib/styles/calendar.d.ts.map +0 -1
- package/lib/styles/calendar.js.map +0 -1
- package/lib/styles/copy.d.ts.map +0 -1
- package/lib/styles/copy.js.map +0 -1
- package/lib/styles/date-picker.d.ts.map +0 -1
- package/lib/styles/date-picker.js.map +0 -1
- package/lib/styles/dropdown.d.ts +0 -12
- package/lib/styles/dropdown.d.ts.map +0 -1
- package/lib/styles/dropdown.js +0 -725
- package/lib/styles/dropdown.js.map +0 -1
- package/lib/styles/icon.d.ts.map +0 -1
- package/lib/styles/icon.js.map +0 -1
- package/lib/styles/input.d.ts.map +0 -1
- package/lib/styles/input.js.map +0 -1
- package/lib/styles/modal.d.ts.map +0 -1
- package/lib/styles/modal.js.map +0 -1
- package/lib/styles/multiselect.d.ts +0 -6
- package/lib/styles/multiselect.d.ts.map +0 -1
- package/lib/styles/multiselect.js +0 -568
- package/lib/styles/multiselect.js.map +0 -1
- package/lib/styles/option.d.ts.map +0 -1
- package/lib/styles/option.js.map +0 -1
- package/lib/styles/popup.d.ts.map +0 -1
- package/lib/styles/popup.js.map +0 -1
- package/lib/styles/resize-observer.d.ts.map +0 -1
- package/lib/styles/resize-observer.js.map +0 -1
- package/lib/styles/scroll-container.d.ts.map +0 -1
- package/lib/styles/scroll-container.js.map +0 -1
- package/lib/styles/step.d.ts.map +0 -1
- package/lib/styles/step.js.map +0 -1
- package/lib/styles/tab.d.ts.map +0 -1
- package/lib/styles/tab.js.map +0 -1
- package/lib/styles/tabs.d.ts.map +0 -1
- package/lib/styles/tabs.js.map +0 -1
- package/lib/styles/tag.d.ts.map +0 -1
- package/lib/styles/tag.js.map +0 -1
- package/lib/styles/textarea.d.ts.map +0 -1
- package/lib/styles/textarea.js.map +0 -1
- package/lib/styles/tooltip.d.ts.map +0 -1
- package/lib/styles/tooltip.js.map +0 -1
- package/lib/styles/wizard.d.ts.map +0 -1
- package/lib/styles/wizard.js.map +0 -1
- package/lib/types/common.d.ts.map +0 -1
- package/lib/types/common.js.map +0 -1
- package/lib/utils/calendar-utils.d.ts.map +0 -1
- package/lib/utils/calendar-utils.js.map +0 -1
- package/lib/utils/icon-registry.d.ts.map +0 -1
- package/lib/utils/icon-registry.js.map +0 -1
- package/lib/utils/locale.d.ts.map +0 -1
- package/lib/utils/locale.js.map +0 -1
- package/lib/utils/number-format.d.ts.map +0 -1
- package/lib/utils/number-format.js.map +0 -1
- package/lib/utils/parse-boolean.d.ts +0 -39
- package/lib/utils/parse-boolean.d.ts.map +0 -1
- package/lib/utils/parse-boolean.js +0 -23
- package/lib/utils/parse-boolean.js.map +0 -1
- package/lib/utils/positioning.d.ts.map +0 -1
- package/lib/utils/positioning.js.map +0 -1
- package/lib/utils/property-capture.d.ts.map +0 -1
- package/lib/utils/property-capture.js.map +0 -1
- package/lib/utils/property-manager.d.ts.map +0 -1
- package/lib/utils/property-manager.js.map +0 -1
- package/lib/utils/resize-observer.d.ts.map +0 -1
- package/lib/utils/resize-observer.js.map +0 -1
- package/lib/utils/scroll-lock.d.ts.map +0 -1
- package/lib/utils/scroll-lock.js.map +0 -1
- package/lib/utils/styles.d.ts.map +0 -1
- package/lib/utils/styles.js.map +0 -1
- package/lib/version.d.ts.map +0 -1
- package/lib/version.js.map +0 -1
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
* - Property change events via 'prop:change' (separate from user 'change' events)
|
|
10
10
|
*/
|
|
11
11
|
import { PropertyManager, PropertyConfig, PropertyChange } from '../utils/property-manager.js';
|
|
12
|
+
import { upgradeProperties } from '../utils/upgrade-properties.js';
|
|
13
|
+
export { upgradeProperties };
|
|
12
14
|
/**
|
|
13
15
|
* Base class for all Ty components with unified property lifecycle
|
|
14
16
|
*/
|
|
@@ -20,6 +22,9 @@ export declare abstract class TyComponent<T = any> extends HTMLElement {
|
|
|
20
22
|
private _validity;
|
|
21
23
|
protected _connected: boolean;
|
|
22
24
|
protected _rendered: boolean;
|
|
25
|
+
/** The user edited the field since it was created or its form reset:
|
|
26
|
+
* blur then shows its validation message (like native :user-invalid). */
|
|
27
|
+
protected _userEdited: boolean;
|
|
23
28
|
constructor();
|
|
24
29
|
/**
|
|
25
30
|
* Define which attributes to observe
|
|
@@ -56,10 +61,11 @@ export declare abstract class TyComponent<T = any> extends HTMLElement {
|
|
|
56
61
|
*/
|
|
57
62
|
disconnectedCallback(): void;
|
|
58
63
|
/**
|
|
59
|
-
*
|
|
60
|
-
*
|
|
64
|
+
* upgradeProperties(), plus declared properties without an accessor of
|
|
65
|
+
* their own name (e.g. ty-input's `minlength`): those go straight to
|
|
66
|
+
* setProperty().
|
|
61
67
|
*/
|
|
62
|
-
private
|
|
68
|
+
private _upgradeProperties;
|
|
63
69
|
/**
|
|
64
70
|
* THE CORE LIFECYCLE METHOD
|
|
65
71
|
* All property changes flow through here
|
|
@@ -119,6 +125,9 @@ export declare abstract class TyComponent<T = any> extends HTMLElement {
|
|
|
119
125
|
/** Subclasses report their own validity here, not via _internals directly,
|
|
120
126
|
* so a user's setCustomValidity() survives re-validation. */
|
|
121
127
|
protected applyValidity(flags: ValidityStateFlags, message?: string, anchor?: HTMLElement): void;
|
|
128
|
+
/** Show the field's current validation message in its error display, if
|
|
129
|
+
* it's invalid. Called on blur after the user edited the field. */
|
|
130
|
+
protected revealValidity(): void;
|
|
122
131
|
get validity(): ValidityState | undefined;
|
|
123
132
|
get validationMessage(): string;
|
|
124
133
|
get willValidate(): boolean;
|
|
@@ -154,6 +163,9 @@ export declare abstract class TyComponent<T = any> extends HTMLElement {
|
|
|
154
163
|
* semantics). Non-form state (e.g. a checkbox's submission `value`, a
|
|
155
164
|
* ty-radio's option `value`) is deliberately left alone — the old
|
|
156
165
|
* blanket 'value' reset corrupted radio groups by wiping child values.
|
|
166
|
+
* Like a native control the field also looks untouched again: the
|
|
167
|
+
* validation message it showed is gone (an `error` the author set stays)
|
|
168
|
+
* and a blur shows nothing until the user edits it.
|
|
157
169
|
*/
|
|
158
170
|
formResetCallback(): void;
|
|
159
171
|
/**
|
package/lib/base/ty-component.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { PropertyManager } from '../utils/property-manager.js';
|
|
2
2
|
import { ValidityController } from '../utils/validity.js';
|
|
3
|
+
import { upgradeProperties } from '../utils/upgrade-properties.js';
|
|
4
|
+
export { upgradeProperties };
|
|
3
5
|
export class TyComponent extends HTMLElement {
|
|
4
6
|
constructor() {
|
|
5
7
|
super();
|
|
6
8
|
this._connected = false;
|
|
7
9
|
this._rendered = false;
|
|
10
|
+
this._userEdited = false;
|
|
8
11
|
this._handlingActivationClick = false;
|
|
9
12
|
this._resetDefaults = null;
|
|
10
13
|
const ctor = this.constructor;
|
|
@@ -81,7 +84,6 @@ this._handlePropertyChanges([change]);
|
|
|
81
84
|
}
|
|
82
85
|
}
|
|
83
86
|
connectedCallback() {
|
|
84
|
-
this._connected = true;
|
|
85
87
|
if (!this._resetDefaults) {
|
|
86
88
|
this._resetDefaults = new Map();
|
|
87
89
|
const ctor = this.constructor;
|
|
@@ -89,13 +91,11 @@ for (const [name, config] of Object.entries(ctor.properties)) {
|
|
|
89
91
|
if (!config.formValue)
|
|
90
92
|
continue;
|
|
91
93
|
const attr = this.getAttribute(this._toKebabCase(name));
|
|
92
|
-
this._resetDefaults.set(name, attr ?? config.default ?? null);
|
|
93
|
-
}
|
|
94
|
+
this._resetDefaults.set(name, attr ?? (typeof config.default === 'function' ? config.default() : config.default) ?? null);
|
|
94
95
|
}
|
|
95
|
-
const preSetProps = this._capturePreSetProperties();
|
|
96
|
-
if (preSetProps.length > 0) {
|
|
97
|
-
this._handlePropertyChanges(preSetProps);
|
|
98
96
|
}
|
|
97
|
+
this._upgradeProperties();
|
|
98
|
+
this._connected = true;
|
|
99
99
|
this.onConnect();
|
|
100
100
|
if (!this._rendered) {
|
|
101
101
|
this.render();
|
|
@@ -106,19 +106,20 @@ disconnectedCallback() {
|
|
|
106
106
|
this._connected = false;
|
|
107
107
|
this.onDisconnect();
|
|
108
108
|
}
|
|
109
|
-
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
109
|
+
_upgradeProperties() {
|
|
110
|
+
for (const name of Object.keys(this.constructor.properties)) {
|
|
111
|
+
if (!Object.prototype.hasOwnProperty.call(this, name))
|
|
112
|
+
continue;
|
|
113
|
+
const value = this[name];
|
|
114
|
+
delete this[name];
|
|
115
|
+
if (value === undefined)
|
|
116
|
+
continue;
|
|
117
|
+
if (name in this)
|
|
118
|
+
this[name] = value;
|
|
119
|
+
else
|
|
120
|
+
this.setProperty(name, value);
|
|
120
121
|
}
|
|
121
|
-
|
|
122
|
+
upgradeProperties(this);
|
|
122
123
|
}
|
|
123
124
|
_handlePropertyChanges(changes) {
|
|
124
125
|
if (changes.length === 0)
|
|
@@ -171,6 +172,10 @@ return this.constructor.formAssociated === true;
|
|
|
171
172
|
applyValidity(flags, message, anchor) {
|
|
172
173
|
this._validity.set(flags, message, anchor);
|
|
173
174
|
}
|
|
175
|
+
revealValidity() {
|
|
176
|
+
if (this._validates)
|
|
177
|
+
this._validity.reveal();
|
|
178
|
+
}
|
|
174
179
|
get validity() {
|
|
175
180
|
return this._validates ? this._internals.validity : undefined;
|
|
176
181
|
}
|
|
@@ -216,6 +221,9 @@ queueMicrotask(() => { this._handlingActivationClick = false; });
|
|
|
216
221
|
return false;
|
|
217
222
|
}
|
|
218
223
|
formResetCallback() {
|
|
224
|
+
this._userEdited = false;
|
|
225
|
+
if (this._validates)
|
|
226
|
+
this._validity.reset();
|
|
219
227
|
for (const [name, def] of this._resetDefaults ?? []) {
|
|
220
228
|
this.setProperty(name, def);
|
|
221
229
|
}
|
|
@@ -89,11 +89,15 @@ export declare class TyButton extends TyComponent<ButtonState> implements TyButt
|
|
|
89
89
|
};
|
|
90
90
|
};
|
|
91
91
|
private _structureInitialized;
|
|
92
|
+
private _formDisabled;
|
|
92
93
|
private _customFlavorSheet;
|
|
94
|
+
private _ownClick;
|
|
93
95
|
constructor();
|
|
94
96
|
protected onConnect(): void;
|
|
95
97
|
protected onDisconnect(): void;
|
|
96
98
|
protected onPropertiesChanged(changes: PropertyChange[]): void;
|
|
99
|
+
formDisabledCallback(disabled: boolean): void;
|
|
100
|
+
private get _isDisabled();
|
|
97
101
|
/**
|
|
98
102
|
* Custom flavors: adopt generated per-flavor rules pointed at the user's
|
|
99
103
|
* design tokens (--ty-solid-X / --ty-color-X / --ty-bg-X), falling back to
|
package/lib/components/button.js
CHANGED
|
@@ -8,8 +8,19 @@ export class TyButton extends TyComponent {
|
|
|
8
8
|
constructor() {
|
|
9
9
|
super();
|
|
10
10
|
this._structureInitialized = false;
|
|
11
|
+
this._formDisabled = false;
|
|
11
12
|
this._customFlavorSheet = null;
|
|
13
|
+
this._ownClick = null;
|
|
12
14
|
ensureStyles(this.shadowRoot, { css: buttonStyles, id: "ty-button" });
|
|
15
|
+
this.addEventListener("click", (e) => {
|
|
16
|
+
const button = this.shadowRoot.querySelector("button");
|
|
17
|
+
if (!button || e === this._ownClick)
|
|
18
|
+
return;
|
|
19
|
+
if (e.composedPath().includes(button))
|
|
20
|
+
return;
|
|
21
|
+
e.stopImmediatePropagation();
|
|
22
|
+
button.click();
|
|
23
|
+
}, true);
|
|
13
24
|
}
|
|
14
25
|
onConnect() {
|
|
15
26
|
this._syncCustomFlavor();
|
|
@@ -20,6 +31,14 @@ if (changes.some((c) => c.name === "flavor")) {
|
|
|
20
31
|
this._syncCustomFlavor();
|
|
21
32
|
}
|
|
22
33
|
}
|
|
34
|
+
formDisabledCallback(disabled) {
|
|
35
|
+
this._formDisabled = disabled;
|
|
36
|
+
if (this._structureInitialized)
|
|
37
|
+
this.render();
|
|
38
|
+
}
|
|
39
|
+
get _isDisabled() {
|
|
40
|
+
return this.disabled || this._formDisabled;
|
|
41
|
+
}
|
|
23
42
|
_syncCustomFlavor() {
|
|
24
43
|
const { base } = this.parseFlavor();
|
|
25
44
|
this._customFlavorSheet = syncCustomFlavorSheet(this.shadowRoot, this._customFlavorSheet, base, () => buttonCustomFlavorCss(base));
|
|
@@ -136,7 +155,7 @@ initializeButtonStructure() {
|
|
|
136
155
|
const shadow = this.shadowRoot;
|
|
137
156
|
const classes = this.buildClasses();
|
|
138
157
|
const button = document.createElement("button");
|
|
139
|
-
button.disabled = this.
|
|
158
|
+
button.disabled = this._isDisabled;
|
|
140
159
|
button.className = classes;
|
|
141
160
|
button.setAttribute("part", "button");
|
|
142
161
|
const loader = document.createElement("span");
|
|
@@ -155,15 +174,21 @@ button.appendChild(startSlot);
|
|
|
155
174
|
button.appendChild(defaultSlot);
|
|
156
175
|
button.appendChild(endSlot);
|
|
157
176
|
button.addEventListener("click", (e) => {
|
|
158
|
-
|
|
177
|
+
const path = e.composedPath();
|
|
178
|
+
if (path.slice(0, path.indexOf(button)).some((n) => n instanceof Element && n.localName === "ty-popup"))
|
|
159
179
|
return;
|
|
160
180
|
e.stopPropagation();
|
|
161
|
-
this.
|
|
162
|
-
|
|
181
|
+
if (this._isDisabled || this.loading)
|
|
182
|
+
return;
|
|
183
|
+
const click = new CustomEvent("click", {
|
|
163
184
|
bubbles: true,
|
|
164
185
|
composed: true,
|
|
186
|
+
cancelable: true,
|
|
165
187
|
detail: { originalEvent: e },
|
|
166
|
-
})
|
|
188
|
+
});
|
|
189
|
+
this._ownClick = click;
|
|
190
|
+
if (this.dispatchEvent(click))
|
|
191
|
+
this.handleFormAction();
|
|
167
192
|
});
|
|
168
193
|
this.applyLoadingState(button);
|
|
169
194
|
shadow.appendChild(button);
|
|
@@ -174,12 +199,14 @@ const isLoading = this.loading;
|
|
|
174
199
|
button.classList.toggle("loading", isLoading);
|
|
175
200
|
if (isLoading) {
|
|
176
201
|
button.setAttribute("aria-busy", "true");
|
|
202
|
+
button.setAttribute("aria-disabled", "true");
|
|
177
203
|
const loader = button.querySelector(".loader-icon");
|
|
178
204
|
if (loader)
|
|
179
205
|
loader.innerHTML = getLoaderSvg();
|
|
180
206
|
}
|
|
181
207
|
else {
|
|
182
208
|
button.removeAttribute("aria-busy");
|
|
209
|
+
button.removeAttribute("aria-disabled");
|
|
183
210
|
}
|
|
184
211
|
}
|
|
185
212
|
render() {
|
|
@@ -191,7 +218,7 @@ return;
|
|
|
191
218
|
const classes = this.buildClasses();
|
|
192
219
|
const button = shadow.querySelector("button");
|
|
193
220
|
if (button) {
|
|
194
|
-
button.disabled = this.
|
|
221
|
+
button.disabled = this._isDisabled;
|
|
195
222
|
button.className = classes;
|
|
196
223
|
this.applyLoadingState(button);
|
|
197
224
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ensureStyles } from '../utils/styles.js';
|
|
2
|
+
import { liftProperties, upgradeProperties } from '../utils/upgrade-properties.js';
|
|
2
3
|
import { syncCustomFlavorSheet } from '../utils/flavor-sheet.js';
|
|
3
4
|
import { calendarMonthStyles, calendarMonthCustomFlavorCss } from '../styles/calendar-month.js';
|
|
4
5
|
import { getCalendarMonthDays, getLocalizedWeekdays, parseISODate } from '../utils/calendar-utils.js';
|
|
@@ -53,6 +54,7 @@ const today = new Date();
|
|
|
53
54
|
this._displayYear = today.getFullYear();
|
|
54
55
|
this._displayMonth = today.getMonth() + 1;
|
|
55
56
|
this.attachShadow({ mode: 'open' });
|
|
57
|
+
liftProperties(this);
|
|
56
58
|
}
|
|
57
59
|
connectedCallback() {
|
|
58
60
|
if (!this._displayMonth) {
|
|
@@ -68,16 +70,7 @@ const sizeAttr = this.getAttribute('size');
|
|
|
68
70
|
if (sizeAttr && (sizeAttr === 'sm' || sizeAttr === 'md' || sizeAttr === 'lg')) {
|
|
69
71
|
this._size = sizeAttr;
|
|
70
72
|
}
|
|
71
|
-
|
|
72
|
-
if (plainDayContentFn && !this._dayContentFn) {
|
|
73
|
-
this._dayContentFn = plainDayContentFn;
|
|
74
|
-
delete this.dayContentFn;
|
|
75
|
-
}
|
|
76
|
-
const plainCustomCSS = this.customCSS;
|
|
77
|
-
if (plainCustomCSS && !this._customCSS) {
|
|
78
|
-
this._customCSS = plainCustomCSS;
|
|
79
|
-
delete this.customCSS;
|
|
80
|
-
}
|
|
73
|
+
upgradeProperties(this);
|
|
81
74
|
this._localeObserver = observeLocaleChanges(this, () => {
|
|
82
75
|
this.render();
|
|
83
76
|
});
|
|
@@ -50,6 +50,7 @@ export declare class TyCalendar extends HTMLElement {
|
|
|
50
50
|
private _internals?;
|
|
51
51
|
private _validity?;
|
|
52
52
|
private _initialValue;
|
|
53
|
+
private _valueSets;
|
|
53
54
|
private _localeObserver?;
|
|
54
55
|
static formAssociated: boolean;
|
|
55
56
|
static get observedAttributes(): string[];
|
|
@@ -94,7 +95,8 @@ export declare class TyCalendar extends HTMLElement {
|
|
|
94
95
|
private syncChildComponents;
|
|
95
96
|
private updateFormValue;
|
|
96
97
|
/**
|
|
97
|
-
* Selection outside [min, max] => rangeUnderflow/rangeOverflow
|
|
98
|
+
* Selection outside [min, max] => rangeUnderflow/rangeOverflow, with a
|
|
99
|
+
* native date input's message.
|
|
98
100
|
* UI can't produce this (days are disabled), but programmatic values can.
|
|
99
101
|
*/
|
|
100
102
|
private updateValidity;
|
|
@@ -128,5 +130,7 @@ export declare class TyCalendar extends HTMLElement {
|
|
|
128
130
|
private pickMonth;
|
|
129
131
|
private handleKeydown;
|
|
130
132
|
private focusNavTitle;
|
|
133
|
+
/** Focus the grid's tab stop (the focused day, or month in the month view). */
|
|
134
|
+
focus(options?: FocusOptions): void;
|
|
131
135
|
private focusDayGrid;
|
|
132
136
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { ensureStyles } from '../utils/styles.js';
|
|
2
|
+
import { liftProperties, upgradeProperties } from '../utils/upgrade-properties.js';
|
|
2
3
|
import { calendarStyles } from '../styles/calendar.js';
|
|
3
4
|
import './calendar-month.js';
|
|
4
5
|
import './calendar-navigation.js';
|
|
5
6
|
import { parseISODate, getMonthName } from '../utils/calendar-utils.js';
|
|
6
7
|
import { getEffectiveLocale, observeLocaleChanges } from '../utils/locale.js';
|
|
7
|
-
import { ValidityController } from '../utils/validity.js';
|
|
8
|
+
import { ValidityController, nativeMessage } from '../utils/validity.js';
|
|
8
9
|
function getCurrentDate() {
|
|
9
10
|
const now = new Date();
|
|
10
11
|
return {
|
|
@@ -49,12 +50,14 @@ this._flavor = 'primary';
|
|
|
49
50
|
this._view = 'days';
|
|
50
51
|
this._dayGridHeight = 0;
|
|
51
52
|
this._initialValue = '';
|
|
53
|
+
this._valueSets = 0;
|
|
52
54
|
const current = getCurrentDate();
|
|
53
55
|
this._state = {
|
|
54
56
|
displayYear: current.year,
|
|
55
57
|
displayMonth: current.month,
|
|
56
58
|
};
|
|
57
59
|
this.attachShadow({ mode: 'open' });
|
|
60
|
+
liftProperties(this);
|
|
58
61
|
if ('attachInternals' in this) {
|
|
59
62
|
this._internals = this.attachInternals();
|
|
60
63
|
this._validity = new ValidityController(this, this._internals);
|
|
@@ -62,36 +65,7 @@ this._validity = new ValidityController(this, this._internals);
|
|
|
62
65
|
}
|
|
63
66
|
connectedCallback() {
|
|
64
67
|
this.initializeFromAttributes();
|
|
65
|
-
|
|
66
|
-
if (plainDayContentFn && !this._dayContentFn) {
|
|
67
|
-
this._dayContentFn = plainDayContentFn;
|
|
68
|
-
delete this.dayContentFn;
|
|
69
|
-
}
|
|
70
|
-
const plainCustomCSS = this.customCSS;
|
|
71
|
-
if (plainCustomCSS && !this._customCSS) {
|
|
72
|
-
this._customCSS = plainCustomCSS;
|
|
73
|
-
delete this.customCSS;
|
|
74
|
-
}
|
|
75
|
-
const plainValue = this.value;
|
|
76
|
-
if (plainValue && typeof plainValue === 'string' && plainValue !== this.value) {
|
|
77
|
-
const match = plainValue.match(/^(\d{4})-(\d{2})-(\d{2})$/);
|
|
78
|
-
if (match) {
|
|
79
|
-
const year = parseInt(match[1], 10);
|
|
80
|
-
const month = parseInt(match[2], 10);
|
|
81
|
-
const day = parseInt(match[3], 10);
|
|
82
|
-
this._state.selectedYear = year;
|
|
83
|
-
this._state.selectedMonth = month;
|
|
84
|
-
this._state.selectedDay = day;
|
|
85
|
-
this._state.displayYear = year;
|
|
86
|
-
this._state.displayMonth = month;
|
|
87
|
-
if (!this._stateless) {
|
|
88
|
-
this.setAttribute('year', year.toString());
|
|
89
|
-
this.setAttribute('month', month.toString());
|
|
90
|
-
this.setAttribute('day', day.toString());
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
delete this.value;
|
|
94
|
-
}
|
|
68
|
+
upgradeProperties(this);
|
|
95
69
|
this.render();
|
|
96
70
|
this.updateFormValue();
|
|
97
71
|
this._localeObserver = observeLocaleChanges(this, () => {
|
|
@@ -337,18 +311,24 @@ return formatDateISO(selectedYear, selectedMonth, selectedDay);
|
|
|
337
311
|
return '';
|
|
338
312
|
}
|
|
339
313
|
set value(isoDate) {
|
|
314
|
+
const set = ++this._valueSets;
|
|
315
|
+
const superseded = () => set !== this._valueSets;
|
|
340
316
|
if (!isoDate) {
|
|
341
317
|
delete this._state.selectedYear;
|
|
342
318
|
delete this._state.selectedMonth;
|
|
343
319
|
delete this._state.selectedDay;
|
|
344
320
|
if (!this._stateless) {
|
|
345
321
|
this.removeAttribute('year');
|
|
322
|
+
if (superseded())
|
|
323
|
+
return;
|
|
346
324
|
this.removeAttribute('month');
|
|
325
|
+
if (superseded())
|
|
326
|
+
return;
|
|
347
327
|
this.removeAttribute('day');
|
|
348
328
|
}
|
|
349
329
|
}
|
|
350
330
|
else {
|
|
351
|
-
const match = isoDate.match(/^(\d{4})-(\d{2})-(\d{2})$/);
|
|
331
|
+
const match = typeof isoDate === 'string' && isoDate.match(/^(\d{4})-(\d{2})-(\d{2})$/);
|
|
352
332
|
if (match) {
|
|
353
333
|
const year = parseInt(match[1], 10);
|
|
354
334
|
const month = parseInt(match[2], 10);
|
|
@@ -360,7 +340,11 @@ this._state.displayYear = year;
|
|
|
360
340
|
this._state.displayMonth = month;
|
|
361
341
|
if (!this._stateless) {
|
|
362
342
|
this.setAttribute('year', year.toString());
|
|
343
|
+
if (superseded())
|
|
344
|
+
return;
|
|
363
345
|
this.setAttribute('month', month.toString());
|
|
346
|
+
if (superseded())
|
|
347
|
+
return;
|
|
364
348
|
this.setAttribute('day', day.toString());
|
|
365
349
|
}
|
|
366
350
|
}
|
|
@@ -503,12 +487,13 @@ if (selectedYear && selectedMonth && selectedDay) {
|
|
|
503
487
|
const sel = Date.UTC(selectedYear, selectedMonth - 1, selectedDay);
|
|
504
488
|
const min = this._min ? parseISODate(this._min) : null;
|
|
505
489
|
const max = this._max ? parseISODate(this._max) : null;
|
|
490
|
+
const message = () => nativeMessage('input', { type: 'date', min: this._min, max: this._max }, formatDateISO(selectedYear, selectedMonth, selectedDay));
|
|
506
491
|
if (min && sel < Date.UTC(min.year, min.month - 1, min.day)) {
|
|
507
|
-
this._validity.set({ rangeUnderflow: true },
|
|
492
|
+
this._validity.set({ rangeUnderflow: true }, message());
|
|
508
493
|
return;
|
|
509
494
|
}
|
|
510
495
|
if (max && sel > Date.UTC(max.year, max.month - 1, max.day)) {
|
|
511
|
-
this._validity.set({ rangeOverflow: true },
|
|
496
|
+
this._validity.set({ rangeOverflow: true }, message());
|
|
512
497
|
return;
|
|
513
498
|
}
|
|
514
499
|
}
|
|
@@ -792,6 +777,15 @@ requestAnimationFrame(() => {
|
|
|
792
777
|
this._navigation?.shadowRoot?.querySelector('.nav-title')?.focus();
|
|
793
778
|
});
|
|
794
779
|
}
|
|
780
|
+
focus(options) {
|
|
781
|
+
const cell = this._view === 'months'
|
|
782
|
+
? this._monthGrid?.querySelector('.month-cell[tabindex="0"]')
|
|
783
|
+
: this._monthDisplay?.shadowRoot?.querySelector('.calendar-day-cell[tabindex="0"]');
|
|
784
|
+
if (cell)
|
|
785
|
+
cell.focus(options);
|
|
786
|
+
else
|
|
787
|
+
super.focus(options);
|
|
788
|
+
}
|
|
795
789
|
focusDayGrid() {
|
|
796
790
|
requestAnimationFrame(() => {
|
|
797
791
|
const cell = this._monthDisplay?.shadowRoot?.querySelector('.calendar-day-cell[tabindex="0"]');
|
|
@@ -110,7 +110,9 @@ export declare class TyCheckbox extends TyComponent<CheckboxState> implements Ty
|
|
|
110
110
|
* Label, required asterisk, and error UI are the consumer's responsibility.
|
|
111
111
|
*/
|
|
112
112
|
protected render(): void;
|
|
113
|
-
/**
|
|
113
|
+
/** Focus the checkbox itself (the host is not focusable; its role element is). */
|
|
114
|
+
focus(options?: FocusOptions): void;
|
|
115
|
+
/** required + unchecked => valueMissing (the browser's own message); otherwise valid. */
|
|
114
116
|
private updateValidity;
|
|
115
117
|
get checked(): boolean;
|
|
116
118
|
set checked(value: boolean);
|
|
@@ -3,6 +3,7 @@ import { TyComponent } from "../base/ty-component.js";
|
|
|
3
3
|
import { ensureStyles } from "../utils/styles.js";
|
|
4
4
|
import { syncCustomFlavorSheet } from "../utils/flavor-sheet.js";
|
|
5
5
|
import { checkboxStyles, checkboxCustomFlavorCss } from "../styles/checkbox.js";
|
|
6
|
+
import { nativeMessage } from "../utils/validity.js";
|
|
6
7
|
const CHECK_ICON = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>`;
|
|
7
8
|
const DASH_ICON = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"/></svg>`;
|
|
8
9
|
export class TyCheckbox extends TyComponent {
|
|
@@ -165,6 +166,13 @@ this.setupEventListeners();
|
|
|
165
166
|
this.applyLabelName(checkboxEl);
|
|
166
167
|
this.updateValidity();
|
|
167
168
|
}
|
|
169
|
+
focus(options) {
|
|
170
|
+
const el = this.shadowRoot?.querySelector(".checkbox-container");
|
|
171
|
+
if (el)
|
|
172
|
+
el.focus(options);
|
|
173
|
+
else
|
|
174
|
+
super.focus(options);
|
|
175
|
+
}
|
|
168
176
|
updateValidity() {
|
|
169
177
|
const anchor = this.shadowRoot?.querySelector(".checkbox-container");
|
|
170
178
|
if (this.disabled) {
|
|
@@ -172,7 +180,7 @@ this.applyValidity({});
|
|
|
172
180
|
return;
|
|
173
181
|
}
|
|
174
182
|
if (this.required && !this.checked) {
|
|
175
|
-
this.applyValidity({ valueMissing: true }, "
|
|
183
|
+
this.applyValidity({ valueMissing: true }, nativeMessage("input", { type: "checkbox", required: true }), anchor ?? undefined);
|
|
176
184
|
}
|
|
177
185
|
else {
|
|
178
186
|
this.applyValidity({});
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* TyDatePicker Web Component — read-only input stub + calendar dropdown
|
|
3
3
|
* (modal <dialog>), optional time input, form participation via
|
|
4
|
-
* ElementInternals. Value is UTC
|
|
4
|
+
* ElementInternals. Value is a UTC instant (wall-clock with `native`);
|
|
5
|
+
* display is local.
|
|
5
6
|
*/
|
|
6
7
|
import { type Placement } from '../utils/positioning.js';
|
|
7
8
|
import { TyComponent } from '../base/ty-component.js';
|
|
@@ -16,6 +17,8 @@ interface DateComponents {
|
|
|
16
17
|
day?: number;
|
|
17
18
|
hour?: number;
|
|
18
19
|
minute?: number;
|
|
20
|
+
second?: number;
|
|
21
|
+
epoch?: number;
|
|
19
22
|
}
|
|
20
23
|
/**
|
|
21
24
|
* Internal date picker state
|
|
@@ -99,6 +102,11 @@ export declare class TyDatePicker extends TyComponent<DatePickerState> {
|
|
|
99
102
|
visual: boolean;
|
|
100
103
|
default: boolean;
|
|
101
104
|
};
|
|
105
|
+
error: {
|
|
106
|
+
type: "string";
|
|
107
|
+
visual: boolean;
|
|
108
|
+
default: string;
|
|
109
|
+
};
|
|
102
110
|
format: {
|
|
103
111
|
type: "string";
|
|
104
112
|
visual: boolean;
|
|
@@ -123,12 +131,19 @@ export declare class TyDatePicker extends TyComponent<DatePickerState> {
|
|
|
123
131
|
visual: boolean;
|
|
124
132
|
default: boolean;
|
|
125
133
|
};
|
|
134
|
+
native: {
|
|
135
|
+
type: "boolean";
|
|
136
|
+
visual: boolean;
|
|
137
|
+
default: boolean;
|
|
138
|
+
};
|
|
126
139
|
};
|
|
127
140
|
private _state;
|
|
128
141
|
private _clickListener?;
|
|
129
142
|
private _keydownListener?;
|
|
130
143
|
private _dialogClickListener?;
|
|
131
144
|
private _closeTimestamp;
|
|
145
|
+
private _initialized;
|
|
146
|
+
private _syncing;
|
|
132
147
|
private _timeInput?;
|
|
133
148
|
private _localeObserver?;
|
|
134
149
|
private _customFlavorSheet;
|
|
@@ -142,14 +157,21 @@ export declare class TyDatePicker extends TyComponent<DatePickerState> {
|
|
|
142
157
|
/** Handle state updates BEFORE render. */
|
|
143
158
|
protected onPropertiesChanged(changes: PropertyChange[]): void;
|
|
144
159
|
/**
|
|
145
|
-
* Get form value -
|
|
146
|
-
* TyComponent calls this automatically when
|
|
160
|
+
* Get form value - the submitted string from current state (see
|
|
161
|
+
* componentsToOutputValue). TyComponent calls this automatically when the
|
|
162
|
+
* value property changes.
|
|
147
163
|
*/
|
|
148
164
|
protected getFormValue(): FormDataEntryValue | null;
|
|
165
|
+
private outputValue;
|
|
149
166
|
protected updateFormValue(): void;
|
|
167
|
+
/** The field's focusable element: the stub, or the native input on touch devices. */
|
|
168
|
+
private focusTarget;
|
|
169
|
+
/** Focus the field: the host itself isn't focusable. Disabled: nothing, like a native input. */
|
|
170
|
+
focus(options?: FocusOptions): void;
|
|
150
171
|
/**
|
|
151
172
|
* `required` used to be cosmetic: nothing reported valueMissing, so an empty
|
|
152
173
|
* required picker never blocked its form. Disabled pickers don't validate.
|
|
174
|
+
* The message is a native date (datetime-local with time) input's.
|
|
153
175
|
*/
|
|
154
176
|
private updateValidity;
|
|
155
177
|
private getComponents;
|
|
@@ -171,6 +193,14 @@ export declare class TyDatePicker extends TyComponent<DatePickerState> {
|
|
|
171
193
|
* Compares before setting to prevent circular triggers
|
|
172
194
|
*/
|
|
173
195
|
private syncFormValue;
|
|
196
|
+
/**
|
|
197
|
+
* `error` turns an unflavored field ('default'/'neutral') danger, like
|
|
198
|
+
* ty-input; clearing it puts back exactly the flavor attribute the author
|
|
199
|
+
* had, or none, kept meanwhile in ERROR_FLAVOR. Runs once connected: while
|
|
200
|
+
* the element upgrades, `error` may come before the `flavor` written next
|
|
201
|
+
* to it.
|
|
202
|
+
*/
|
|
203
|
+
private syncErrorFlavor;
|
|
174
204
|
/**
|
|
175
205
|
* Handle time changes from the footer's hour/minute fields
|
|
176
206
|
*/
|
|
@@ -184,6 +214,7 @@ export declare class TyDatePicker extends TyComponent<DatePickerState> {
|
|
|
184
214
|
set placement(v: Placement | '');
|
|
185
215
|
get flavor(): DatePickerFlavor;
|
|
186
216
|
set flavor(v: DatePickerFlavor);
|
|
217
|
+
attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
|
|
187
218
|
get label(): string;
|
|
188
219
|
set label(v: string);
|
|
189
220
|
get placeholder(): string;
|
|
@@ -206,17 +237,23 @@ export declare class TyDatePicker extends TyComponent<DatePickerState> {
|
|
|
206
237
|
set max(v: string);
|
|
207
238
|
get withTime(): boolean;
|
|
208
239
|
set withTime(v: boolean);
|
|
240
|
+
get native(): boolean;
|
|
241
|
+
set native(v: boolean);
|
|
242
|
+
get error(): string;
|
|
243
|
+
set error(v: string);
|
|
209
244
|
/**
|
|
210
|
-
* Get current value
|
|
245
|
+
* Get current value — the string the form submits: a UTC ISO instant, or
|
|
246
|
+
* wall-clock ('YYYY-MM-DD' / 'YYYY-MM-DDTHH:mm') with `native`. null when
|
|
247
|
+
* empty (the form then submits name=, like a native date input).
|
|
211
248
|
*/
|
|
212
249
|
get value(): string | null;
|
|
213
250
|
/**
|
|
214
|
-
* Set value (
|
|
251
|
+
* Set value: any format parseValue() reads, a Date, epoch milliseconds,
|
|
252
|
+
* or null. It's normalized to the submitted form.
|
|
215
253
|
*
|
|
216
254
|
* When set to null/undefined/empty string, the attribute is removed.
|
|
217
|
-
* When set to a valid date, the attribute is set to ISO UTC string.
|
|
218
255
|
*/
|
|
219
|
-
set value(val: string | Date | null);
|
|
256
|
+
set value(val: string | number | Date | null);
|
|
220
257
|
/**
|
|
221
258
|
* Clear the date value programmatically WITH a change event (source:
|
|
222
259
|
* 'clear'). Works regardless of `no-clear` — lets any
|
|
@@ -230,15 +267,32 @@ export declare class TyDatePicker extends TyComponent<DatePickerState> {
|
|
|
230
267
|
/** Footer: clock + "Time" on the left, HH : MM on the right, summary below. */
|
|
231
268
|
private renderTimeSection;
|
|
232
269
|
private renderCalendarDropdown;
|
|
270
|
+
/**
|
|
271
|
+
* Match the popup calendar to the stub's flavor — the one the user set, not
|
|
272
|
+
* the danger an error swapped in. 'default' is the stub's own unstyled
|
|
273
|
+
* state, not a real flavor: the calendar stays on its own default.
|
|
274
|
+
*/
|
|
275
|
+
private calendarFlavor;
|
|
233
276
|
/**
|
|
234
277
|
* Render native date input for mobile touch devices.
|
|
235
278
|
* Uses <input type="date"> or <input type="datetime-local"> when with-time.
|
|
236
279
|
* Reuses .date-picker-stub styling and existing event/state infrastructure.
|
|
237
280
|
*/
|
|
238
281
|
private renderNativeInput;
|
|
282
|
+
/**
|
|
283
|
+
* The touch devices' native input follows the picker: type (date, or
|
|
284
|
+
* datetime-local with time), disabled, required, min/max (datetime-local
|
|
285
|
+
* wants a time suffix) and value — also when they change at runtime.
|
|
286
|
+
*/
|
|
287
|
+
private syncNativeInput;
|
|
239
288
|
private calculateCalendarPosition;
|
|
240
289
|
private renderContainer;
|
|
241
290
|
protected render(): void;
|
|
291
|
+
/**
|
|
292
|
+
* The `error` line under the field — same markup as ty-input's; the field
|
|
293
|
+
* (stub, or the native input on touch devices) is described by it.
|
|
294
|
+
*/
|
|
295
|
+
private syncErrorLine;
|
|
242
296
|
/**
|
|
243
297
|
* Update display without destroying DOM (for open dialog)
|
|
244
298
|
*/
|