tyrell-components 1.0.0-TC52 → 1.0.0-TC54
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-theme.css +25 -2
- package/css/tyrell.css +4 -0
- package/dist/tyrell-colors-static.css +1 -316
- package/dist/tyrell-theme.css +1 -1443
- package/dist/tyrell.css +1 -1390
- package/dist/tyrell.js +1 -1
- package/lib/base/ty-component.js +196 -196
- package/lib/components/button.d.ts +1 -1
- package/lib/components/button.js +260 -259
- package/lib/components/calendar-month.d.ts +2 -2
- package/lib/components/calendar-month.js +426 -416
- package/lib/components/calendar-navigation.js +238 -238
- package/lib/components/calendar.js +605 -602
- package/lib/components/checkbox.d.ts +1 -1
- package/lib/components/checkbox.js +273 -272
- package/lib/components/copy.d.ts +1 -1
- package/lib/components/copy.js +279 -278
- package/lib/components/date-picker.d.ts +1 -1
- package/lib/components/date-picker.js +1103 -1108
- package/lib/components/file-upload.js +404 -404
- package/lib/components/icon.js +141 -141
- package/lib/components/input.d.ts +1 -1
- package/lib/components/input.js +593 -596
- package/lib/components/modal.js +319 -319
- package/lib/components/option.js +167 -167
- package/lib/components/popup.js +233 -233
- package/lib/components/radio.d.ts +2 -2
- package/lib/components/radio.js +407 -406
- package/lib/components/resize-observer.js +67 -67
- package/lib/components/scroll-container.js +294 -294
- package/lib/components/select.d.ts +33 -2
- package/lib/components/select.js +1543 -1532
- package/lib/components/selected-tags.js +188 -184
- package/lib/components/step.js +62 -62
- package/lib/components/switch.d.ts +1 -1
- package/lib/components/switch.js +214 -213
- package/lib/components/tab.js +62 -62
- package/lib/components/tabs.js +507 -509
- package/lib/components/tag.d.ts +1 -1
- package/lib/components/tag.js +236 -235
- package/lib/components/textarea.d.ts +1 -1
- package/lib/components/textarea.js +457 -456
- package/lib/components/tooltip.js +283 -283
- package/lib/components/wizard.js +384 -384
- package/lib/icons/heroicons/micro.js +392 -392
- package/lib/icons/heroicons/mini.js +382 -382
- package/lib/icons/heroicons/outline.js +337 -337
- package/lib/icons/heroicons/solid.js +407 -407
- package/lib/icons/lucide.js +22843 -22843
- package/lib/icons/material/filled.js +9653 -9653
- package/lib/icons/material/outlined.js +10271 -10271
- package/lib/icons/material/round.js +10495 -10495
- package/lib/icons/material/sharp.js +9905 -9905
- package/lib/icons/material/two-tone.js +12792 -12792
- package/lib/index.js +21 -21
- package/lib/styles/button.js +176 -288
- package/lib/styles/calendar-month.js +123 -183
- package/lib/styles/calendar-navigation.js +60 -79
- package/lib/styles/calendar.js +8 -9
- package/lib/styles/checkbox.js +45 -72
- package/lib/styles/copy.js +67 -91
- package/lib/styles/custom-scrollbar.js +80 -100
- package/lib/styles/date-picker.js +261 -331
- package/lib/styles/field-size.d.ts +6 -0
- package/lib/styles/field-size.js +91 -0
- package/lib/styles/file-upload.js +139 -169
- package/lib/styles/icon.js +92 -156
- package/lib/styles/input.js +125 -241
- package/lib/styles/modal.js +67 -102
- package/lib/styles/option.d.ts +1 -1
- package/lib/styles/option.js +47 -67
- package/lib/styles/popup.js +34 -65
- package/lib/styles/radio.js +69 -96
- package/lib/styles/resize-observer.js +2 -5
- package/lib/styles/scroll-container.js +100 -130
- package/lib/styles/select-base.js +525 -778
- package/lib/styles/select.js +140 -228
- package/lib/styles/step.js +22 -29
- package/lib/styles/switch.js +34 -55
- package/lib/styles/tab.js +22 -29
- package/lib/styles/tabs.js +171 -252
- package/lib/styles/tag.js +135 -188
- package/lib/styles/textarea.d.ts +1 -1
- package/lib/styles/textarea.js +205 -271
- package/lib/styles/tooltip.js +3 -3
- package/lib/styles/wizard.js +170 -226
- package/lib/types/common.d.ts +2 -0
- package/lib/types/common.js +6 -5
- package/lib/utils/calendar-utils.js +100 -100
- package/lib/utils/custom-scrollbar.js +272 -272
- package/lib/utils/flavor-sheet.js +14 -14
- package/lib/utils/icon-registry.js +127 -127
- package/lib/utils/loader-registry.js +3 -3
- package/lib/utils/locale.js +34 -34
- package/lib/utils/mobile.js +1 -1
- package/lib/utils/number-format.js +54 -54
- package/lib/utils/positioning.js +212 -212
- package/lib/utils/property-capture.js +36 -36
- package/lib/utils/property-manager.js +125 -125
- package/lib/utils/resize-observer.js +23 -23
- package/lib/utils/scroll-lock.js +57 -57
- package/lib/utils/styles.js +17 -17
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/package.json +4 -4
|
@@ -2,299 +2,299 @@ import { ensureStyles } from '../utils/styles.js';
|
|
|
2
2
|
import { scrollContainerStyles } from '../styles/scroll-container.js';
|
|
3
3
|
import { CustomScrollbar } from '../utils/custom-scrollbar.js';
|
|
4
4
|
export class TyScrollContainer extends HTMLElement {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
5
|
+
static get observedAttributes() {
|
|
6
|
+
return ['shadow', 'max-height', 'hide-scrollbar', 'custom-scrollbar', 'overflow-x', 'scroll-anchoring'];
|
|
7
|
+
}
|
|
8
|
+
get shadow() {
|
|
9
|
+
return this.getAttribute('shadow') !== 'false';
|
|
10
|
+
}
|
|
11
|
+
set shadow(value) {
|
|
12
|
+
if (value)
|
|
13
|
+
this.removeAttribute('shadow');
|
|
14
|
+
else
|
|
15
|
+
this.setAttribute('shadow', 'false');
|
|
16
|
+
}
|
|
17
|
+
get maxHeight() {
|
|
18
|
+
return this.getAttribute('max-height');
|
|
19
|
+
}
|
|
20
|
+
set maxHeight(value) {
|
|
21
|
+
if (value)
|
|
22
|
+
this.setAttribute('max-height', value);
|
|
23
|
+
else
|
|
24
|
+
this.removeAttribute('max-height');
|
|
25
|
+
this._updateMaxHeight();
|
|
26
|
+
}
|
|
27
|
+
get hideScrollbar() {
|
|
28
|
+
return this.hasAttribute('hide-scrollbar');
|
|
29
|
+
}
|
|
30
|
+
set hideScrollbar(value) {
|
|
31
|
+
if (value)
|
|
32
|
+
this.setAttribute('hide-scrollbar', '');
|
|
33
|
+
else
|
|
34
|
+
this.removeAttribute('hide-scrollbar');
|
|
35
|
+
}
|
|
36
|
+
get customScrollbar() {
|
|
37
|
+
return this.hasAttribute('custom-scrollbar');
|
|
38
|
+
}
|
|
39
|
+
set customScrollbar(value) {
|
|
40
|
+
if (value)
|
|
41
|
+
this.setAttribute('custom-scrollbar', '');
|
|
42
|
+
else
|
|
43
|
+
this.removeAttribute('custom-scrollbar');
|
|
44
|
+
}
|
|
45
|
+
get overflowX() {
|
|
46
|
+
return this.hasAttribute('overflow-x');
|
|
47
|
+
}
|
|
48
|
+
set overflowX(value) {
|
|
49
|
+
if (value)
|
|
50
|
+
this.setAttribute('overflow-x', '');
|
|
51
|
+
else
|
|
52
|
+
this.removeAttribute('overflow-x');
|
|
53
|
+
}
|
|
54
|
+
get nearEdgeThreshold() {
|
|
55
|
+
const v = parseInt(this.getAttribute('near-edge-threshold') || '', 10);
|
|
56
|
+
return Number.isFinite(v) ? v : 100;
|
|
57
|
+
}
|
|
58
|
+
set nearEdgeThreshold(value) {
|
|
59
|
+
if (value == null)
|
|
60
|
+
this.removeAttribute('near-edge-threshold');
|
|
61
|
+
else
|
|
62
|
+
this.setAttribute('near-edge-threshold', String(value));
|
|
63
|
+
}
|
|
64
|
+
get scrollAnchoring() {
|
|
65
|
+
return this.hasAttribute('scroll-anchoring');
|
|
66
|
+
}
|
|
67
|
+
set scrollAnchoring(value) {
|
|
68
|
+
if (value)
|
|
69
|
+
this.setAttribute('scroll-anchoring', '');
|
|
70
|
+
else
|
|
71
|
+
this.removeAttribute('scroll-anchoring');
|
|
72
|
+
}
|
|
73
|
+
constructor() {
|
|
74
|
+
super();
|
|
75
|
+
this._scrollWrapper = null;
|
|
76
|
+
this._shadowTop = null;
|
|
77
|
+
this._shadowBottom = null;
|
|
78
|
+
this._shadowLeft = null;
|
|
79
|
+
this._shadowRight = null;
|
|
80
|
+
this._scrollbar = null;
|
|
81
|
+
this._resizeObserver = null;
|
|
82
|
+
this._contentObserver = null;
|
|
83
|
+
this._rafId = null;
|
|
84
|
+
this._nearStartFired = false;
|
|
85
|
+
this._nearEndFired = false;
|
|
86
|
+
this._onScroll = () => {
|
|
87
|
+
if (this._rafId !== null)
|
|
88
|
+
return;
|
|
89
|
+
this._rafId = requestAnimationFrame(() => {
|
|
90
|
+
this._rafId = null;
|
|
91
|
+
this._updateShadowState();
|
|
92
|
+
});
|
|
93
|
+
};
|
|
94
|
+
this._onSlotChange = () => {
|
|
95
|
+
this._scrollbar?.update();
|
|
96
|
+
this._updateShadowState();
|
|
97
|
+
};
|
|
98
|
+
const shadow = this.attachShadow({ mode: 'open' });
|
|
99
|
+
ensureStyles(shadow, { css: scrollContainerStyles, id: 'ty-scroll-container' });
|
|
100
|
+
shadow.innerHTML = `
|
|
101
|
+
<div class="scroll-wrapper">
|
|
102
|
+
<slot></slot>
|
|
103
|
+
</div>
|
|
104
|
+
<div class="shadow-overlay">
|
|
105
|
+
<div class="shadow-top"></div>
|
|
106
|
+
<div class="shadow-bottom"></div>
|
|
107
|
+
<div class="shadow-left"></div>
|
|
108
|
+
<div class="shadow-right"></div>
|
|
109
|
+
</div>
|
|
110
|
+
`;
|
|
111
|
+
this._scrollWrapper = shadow.querySelector('.scroll-wrapper');
|
|
112
|
+
this._shadowTop = shadow.querySelector('.shadow-top');
|
|
113
|
+
this._shadowBottom = shadow.querySelector('.shadow-bottom');
|
|
114
|
+
this._shadowLeft = shadow.querySelector('.shadow-left');
|
|
115
|
+
this._shadowRight = shadow.querySelector('.shadow-right');
|
|
116
|
+
}
|
|
117
|
+
connectedCallback() {
|
|
118
|
+
this._scrollWrapper?.addEventListener('scroll', this._onScroll, { passive: true });
|
|
119
|
+
this._resizeObserver = new ResizeObserver(() => {
|
|
120
|
+
this._scrollbar?.update();
|
|
121
|
+
this._updateShadowState();
|
|
122
|
+
});
|
|
123
|
+
if (this._scrollWrapper) {
|
|
124
|
+
this._resizeObserver.observe(this._scrollWrapper);
|
|
125
|
+
const slot = this._scrollWrapper.querySelector('slot');
|
|
126
|
+
if (slot) {
|
|
127
|
+
slot.addEventListener('slotchange', this._onSlotChange);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
this._updateMaxHeight();
|
|
131
|
+
this._updateShadowState();
|
|
132
|
+
this._setupScrollbar();
|
|
133
|
+
this._setupAnchoring();
|
|
134
|
+
}
|
|
135
|
+
disconnectedCallback() {
|
|
136
|
+
this._scrollWrapper?.removeEventListener('scroll', this._onScroll);
|
|
137
|
+
this._destroyScrollbar();
|
|
138
|
+
this._teardownAnchoring();
|
|
139
|
+
if (this._resizeObserver) {
|
|
140
|
+
this._resizeObserver.disconnect();
|
|
141
|
+
this._resizeObserver = null;
|
|
142
|
+
}
|
|
143
|
+
if (this._rafId !== null) {
|
|
144
|
+
cancelAnimationFrame(this._rafId);
|
|
145
|
+
this._rafId = null;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
attributeChangedCallback(name, oldValue, newValue) {
|
|
149
|
+
if (oldValue === newValue)
|
|
150
|
+
return;
|
|
151
|
+
if (name === 'max-height') {
|
|
152
|
+
this._updateMaxHeight();
|
|
153
|
+
this._updateShadowState();
|
|
154
|
+
this._scrollbar?.update();
|
|
155
|
+
}
|
|
156
|
+
if (name === 'custom-scrollbar' || name === 'overflow-x') {
|
|
157
|
+
this._destroyScrollbar();
|
|
158
|
+
this._setupScrollbar();
|
|
159
|
+
this._updateShadowState();
|
|
160
|
+
}
|
|
161
|
+
if (name === 'scroll-anchoring') {
|
|
162
|
+
this._teardownAnchoring();
|
|
163
|
+
this._setupAnchoring();
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
_setupAnchoring() {
|
|
167
|
+
if (this._contentObserver || !this.scrollAnchoring)
|
|
168
|
+
return;
|
|
169
|
+
this._contentObserver = new MutationObserver((records) => {
|
|
170
|
+
const wrap = this._scrollWrapper;
|
|
171
|
+
if (!wrap)
|
|
172
|
+
return;
|
|
173
|
+
const wrapTop = wrap.getBoundingClientRect().top;
|
|
174
|
+
let addedAbove = 0;
|
|
175
|
+
for (const r of records) {
|
|
176
|
+
r.addedNodes.forEach((n) => {
|
|
177
|
+
if (n.nodeType !== Node.ELEMENT_NODE)
|
|
178
|
+
return;
|
|
179
|
+
const rect = n.getBoundingClientRect();
|
|
180
|
+
if (rect.bottom <= wrapTop)
|
|
181
|
+
addedAbove += rect.height;
|
|
182
|
+
else if (rect.top < wrapTop)
|
|
183
|
+
addedAbove += wrapTop - rect.top;
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
if (addedAbove > 0) {
|
|
187
|
+
wrap.scrollTop += addedAbove;
|
|
188
|
+
this._scrollbar?.update();
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
this._contentObserver.observe(this, { childList: true });
|
|
192
|
+
}
|
|
193
|
+
_teardownAnchoring() {
|
|
194
|
+
this._contentObserver?.disconnect();
|
|
195
|
+
this._contentObserver = null;
|
|
196
|
+
}
|
|
197
|
+
_setupScrollbar() {
|
|
198
|
+
if (this._scrollbar)
|
|
199
|
+
return;
|
|
200
|
+
if (!this._scrollWrapper || !this.customScrollbar)
|
|
201
|
+
return;
|
|
202
|
+
this._scrollbar = new CustomScrollbar(this._scrollWrapper, {
|
|
203
|
+
vertical: true,
|
|
204
|
+
horizontal: this.overflowX
|
|
205
|
+
});
|
|
206
|
+
const shadowRoot = this.shadowRoot;
|
|
207
|
+
if (this._scrollbar.trackY)
|
|
208
|
+
shadowRoot.appendChild(this._scrollbar.trackY);
|
|
209
|
+
if (this._scrollbar.trackX)
|
|
210
|
+
shadowRoot.appendChild(this._scrollbar.trackX);
|
|
211
|
+
}
|
|
212
|
+
_destroyScrollbar() {
|
|
213
|
+
if (this._scrollbar) {
|
|
214
|
+
this._scrollbar.trackY?.remove();
|
|
215
|
+
this._scrollbar.trackX?.remove();
|
|
216
|
+
this._scrollbar.destroy();
|
|
217
|
+
this._scrollbar = null;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
_updateMaxHeight() {
|
|
221
|
+
if (this._scrollWrapper) {
|
|
222
|
+
const maxHeight = this.maxHeight;
|
|
223
|
+
if (maxHeight) {
|
|
224
|
+
this._scrollWrapper.style.setProperty('--scroll-max-height', maxHeight);
|
|
225
|
+
this._scrollWrapper.style.maxHeight = maxHeight;
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
this._scrollWrapper.style.removeProperty('--scroll-max-height');
|
|
229
|
+
this._scrollWrapper.style.maxHeight = '';
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
_updateShadowState() {
|
|
234
|
+
if (!this._scrollWrapper)
|
|
235
|
+
return;
|
|
236
|
+
const { scrollTop, scrollLeft, scrollHeight, scrollWidth, clientHeight, clientWidth } = this._scrollWrapper;
|
|
237
|
+
const threshold = 2;
|
|
238
|
+
if (this._shadowTop) {
|
|
239
|
+
this._shadowTop.classList.toggle('visible', scrollTop > threshold);
|
|
240
|
+
}
|
|
241
|
+
if (this._shadowBottom) {
|
|
242
|
+
this._shadowBottom.classList.toggle('visible', scrollTop + clientHeight < scrollHeight - threshold);
|
|
243
|
+
}
|
|
244
|
+
if (this.overflowX) {
|
|
245
|
+
if (this._shadowLeft) {
|
|
246
|
+
this._shadowLeft.classList.toggle('visible', scrollLeft > threshold);
|
|
247
|
+
}
|
|
248
|
+
if (this._shadowRight) {
|
|
249
|
+
this._shadowRight.classList.toggle('visible', scrollLeft + clientWidth < scrollWidth - threshold);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
const scrollable = scrollHeight - clientHeight;
|
|
253
|
+
if (scrollable > 0) {
|
|
254
|
+
const t = this.nearEdgeThreshold;
|
|
255
|
+
const distEnd = scrollable - scrollTop;
|
|
256
|
+
this._nearEndFired = this._maybeEmitEdge('nearend', distEnd, t, this._nearEndFired, { distance: distEnd, scrollTop, scrollHeight, clientHeight });
|
|
257
|
+
this._nearStartFired = this._maybeEmitEdge('nearstart', scrollTop, t, this._nearStartFired, { distance: scrollTop, scrollTop, scrollHeight, clientHeight });
|
|
258
|
+
}
|
|
259
|
+
else {
|
|
260
|
+
this._nearStartFired = false;
|
|
261
|
+
this._nearEndFired = false;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
_maybeEmitEdge(name, distance, threshold, fired, detail) {
|
|
265
|
+
if (distance > threshold)
|
|
266
|
+
return false;
|
|
267
|
+
if (!fired) {
|
|
268
|
+
this.dispatchEvent(new CustomEvent(name, { detail, bubbles: true, composed: true }));
|
|
269
|
+
}
|
|
270
|
+
return true;
|
|
271
|
+
}
|
|
272
|
+
updateShadows() {
|
|
273
|
+
this._updateShadowState();
|
|
274
|
+
this._scrollbar?.update();
|
|
275
|
+
}
|
|
276
|
+
scrollToTop(smooth = true) {
|
|
277
|
+
this._scrollWrapper?.scrollTo({ top: 0, behavior: smooth ? 'smooth' : 'auto' });
|
|
278
|
+
}
|
|
279
|
+
scrollToBottom(smooth = true) {
|
|
280
|
+
if (this._scrollWrapper) {
|
|
281
|
+
this._scrollWrapper.scrollTo({ top: this._scrollWrapper.scrollHeight, behavior: smooth ? 'smooth' : 'auto' });
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
scrollToLeft(smooth = true) {
|
|
285
|
+
this._scrollWrapper?.scrollTo({ left: 0, behavior: smooth ? 'smooth' : 'auto' });
|
|
286
|
+
}
|
|
287
|
+
scrollToRight(smooth = true) {
|
|
288
|
+
if (this._scrollWrapper) {
|
|
289
|
+
this._scrollWrapper.scrollTo({ left: this._scrollWrapper.scrollWidth, behavior: smooth ? 'smooth' : 'auto' });
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
scrollToElement(target, smooth = true) {
|
|
293
|
+
const el = typeof target === 'string' ? this.querySelector(target) : target;
|
|
294
|
+
el?.scrollIntoView({ behavior: smooth ? 'smooth' : 'auto', block: 'nearest' });
|
|
295
|
+
}
|
|
296
|
+
get scrollElement() {
|
|
297
|
+
return this._scrollWrapper;
|
|
298
|
+
}
|
|
299
299
|
}
|
|
300
300
|
customElements.define('ty-scroll-container', TyScrollContainer);
|
|
@@ -127,7 +127,7 @@ export declare class TySelect extends TyComponent<SelectState> {
|
|
|
127
127
|
size: {
|
|
128
128
|
type: "string";
|
|
129
129
|
visual: boolean;
|
|
130
|
-
default:
|
|
130
|
+
default: Size;
|
|
131
131
|
validate: (v: any) => boolean;
|
|
132
132
|
coerce: (v: any) => any;
|
|
133
133
|
};
|
|
@@ -208,6 +208,29 @@ export declare class TySelect extends TyComponent<SelectState> {
|
|
|
208
208
|
private parseValue;
|
|
209
209
|
/** Initialize component state from the value property / pre-selected children. */
|
|
210
210
|
private initializeState;
|
|
211
|
+
/**
|
|
212
|
+
* Declarative init: no `value` attribute, but markup pre-marked one or more
|
|
213
|
+
* options `selected` — native <select> semantics. This is the ONE place
|
|
214
|
+
* selection is read FROM the DOM rather than treated as a rendering of
|
|
215
|
+
* state (see getSelectedValues()): it seeds initial state, once. After
|
|
216
|
+
* this, `value` rules — flipping an option's `selected` property later
|
|
217
|
+
* does nothing, same as native.
|
|
218
|
+
*
|
|
219
|
+
* Called from initializeState() at connect AND from the child observer:
|
|
220
|
+
* a real HTML parser upgrades a custom element the moment its start tag is
|
|
221
|
+
* seen, BEFORE its children exist — `<ty-select>` connects with zero
|
|
222
|
+
* `<ty-option>` children when it's part of the page's own markup (as
|
|
223
|
+
* opposed to an already-built fragment attached via innerHTML/appendChild,
|
|
224
|
+
* where children exist at connect). Calling this only at connect would
|
|
225
|
+
* silently miss every option parsed after that instant, which is the
|
|
226
|
+
* common case for markup that is literally in the page's initial HTML.
|
|
227
|
+
*
|
|
228
|
+
* Safe to call repeatedly: no-ops once `value` has ever been explicitly
|
|
229
|
+
* set (attribute or property) or state is already non-empty — including
|
|
230
|
+
* after a real `.clear()`, which removes `selected` from every option via
|
|
231
|
+
* syncSelectedTags, so there is nothing left here to (re-)seed from.
|
|
232
|
+
*/
|
|
233
|
+
private resolveDeclarativeSelection;
|
|
211
234
|
/**
|
|
212
235
|
* Get all option elements from the component (ty-option preferred, ty-tag accepted)
|
|
213
236
|
*/
|
|
@@ -223,7 +246,15 @@ export declare class TySelect extends TyComponent<SelectState> {
|
|
|
223
246
|
*/
|
|
224
247
|
private deselectTag;
|
|
225
248
|
/**
|
|
226
|
-
* Get array of currently selected values
|
|
249
|
+
* Get the array of currently selected values.
|
|
250
|
+
*
|
|
251
|
+
* Reads STATE (`_state.selectedValues`), not the DOM: `value` is the
|
|
252
|
+
* selection, and an option's `selected` attribute is a rendering of it
|
|
253
|
+
* (written by syncSelectedTags below), never the other way round. This
|
|
254
|
+
* matters whenever options don't fully reflect the selection — external
|
|
255
|
+
* search legitimately has a selected value with no matching option
|
|
256
|
+
* present; a DOM scan would report empty and desync .value, `required`
|
|
257
|
+
* validation and the click-toggle logic from what's actually selected.
|
|
227
258
|
*/
|
|
228
259
|
private getSelectedValues;
|
|
229
260
|
private syncSelectedTags;
|