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.
Files changed (105) hide show
  1. package/css/tyrell-theme.css +25 -2
  2. package/css/tyrell.css +4 -0
  3. package/dist/tyrell-colors-static.css +1 -316
  4. package/dist/tyrell-theme.css +1 -1443
  5. package/dist/tyrell.css +1 -1390
  6. package/dist/tyrell.js +1 -1
  7. package/lib/base/ty-component.js +196 -196
  8. package/lib/components/button.d.ts +1 -1
  9. package/lib/components/button.js +260 -259
  10. package/lib/components/calendar-month.d.ts +2 -2
  11. package/lib/components/calendar-month.js +426 -416
  12. package/lib/components/calendar-navigation.js +238 -238
  13. package/lib/components/calendar.js +605 -602
  14. package/lib/components/checkbox.d.ts +1 -1
  15. package/lib/components/checkbox.js +273 -272
  16. package/lib/components/copy.d.ts +1 -1
  17. package/lib/components/copy.js +279 -278
  18. package/lib/components/date-picker.d.ts +1 -1
  19. package/lib/components/date-picker.js +1103 -1108
  20. package/lib/components/file-upload.js +404 -404
  21. package/lib/components/icon.js +141 -141
  22. package/lib/components/input.d.ts +1 -1
  23. package/lib/components/input.js +593 -596
  24. package/lib/components/modal.js +319 -319
  25. package/lib/components/option.js +167 -167
  26. package/lib/components/popup.js +233 -233
  27. package/lib/components/radio.d.ts +2 -2
  28. package/lib/components/radio.js +407 -406
  29. package/lib/components/resize-observer.js +67 -67
  30. package/lib/components/scroll-container.js +294 -294
  31. package/lib/components/select.d.ts +33 -2
  32. package/lib/components/select.js +1543 -1532
  33. package/lib/components/selected-tags.js +188 -184
  34. package/lib/components/step.js +62 -62
  35. package/lib/components/switch.d.ts +1 -1
  36. package/lib/components/switch.js +214 -213
  37. package/lib/components/tab.js +62 -62
  38. package/lib/components/tabs.js +507 -509
  39. package/lib/components/tag.d.ts +1 -1
  40. package/lib/components/tag.js +236 -235
  41. package/lib/components/textarea.d.ts +1 -1
  42. package/lib/components/textarea.js +457 -456
  43. package/lib/components/tooltip.js +283 -283
  44. package/lib/components/wizard.js +384 -384
  45. package/lib/icons/heroicons/micro.js +392 -392
  46. package/lib/icons/heroicons/mini.js +382 -382
  47. package/lib/icons/heroicons/outline.js +337 -337
  48. package/lib/icons/heroicons/solid.js +407 -407
  49. package/lib/icons/lucide.js +22843 -22843
  50. package/lib/icons/material/filled.js +9653 -9653
  51. package/lib/icons/material/outlined.js +10271 -10271
  52. package/lib/icons/material/round.js +10495 -10495
  53. package/lib/icons/material/sharp.js +9905 -9905
  54. package/lib/icons/material/two-tone.js +12792 -12792
  55. package/lib/index.js +21 -21
  56. package/lib/styles/button.js +176 -288
  57. package/lib/styles/calendar-month.js +123 -183
  58. package/lib/styles/calendar-navigation.js +60 -79
  59. package/lib/styles/calendar.js +8 -9
  60. package/lib/styles/checkbox.js +45 -72
  61. package/lib/styles/copy.js +67 -91
  62. package/lib/styles/custom-scrollbar.js +80 -100
  63. package/lib/styles/date-picker.js +261 -331
  64. package/lib/styles/field-size.d.ts +6 -0
  65. package/lib/styles/field-size.js +91 -0
  66. package/lib/styles/file-upload.js +139 -169
  67. package/lib/styles/icon.js +92 -156
  68. package/lib/styles/input.js +125 -241
  69. package/lib/styles/modal.js +67 -102
  70. package/lib/styles/option.d.ts +1 -1
  71. package/lib/styles/option.js +47 -67
  72. package/lib/styles/popup.js +34 -65
  73. package/lib/styles/radio.js +69 -96
  74. package/lib/styles/resize-observer.js +2 -5
  75. package/lib/styles/scroll-container.js +100 -130
  76. package/lib/styles/select-base.js +525 -778
  77. package/lib/styles/select.js +140 -228
  78. package/lib/styles/step.js +22 -29
  79. package/lib/styles/switch.js +34 -55
  80. package/lib/styles/tab.js +22 -29
  81. package/lib/styles/tabs.js +171 -252
  82. package/lib/styles/tag.js +135 -188
  83. package/lib/styles/textarea.d.ts +1 -1
  84. package/lib/styles/textarea.js +205 -271
  85. package/lib/styles/tooltip.js +3 -3
  86. package/lib/styles/wizard.js +170 -226
  87. package/lib/types/common.d.ts +2 -0
  88. package/lib/types/common.js +6 -5
  89. package/lib/utils/calendar-utils.js +100 -100
  90. package/lib/utils/custom-scrollbar.js +272 -272
  91. package/lib/utils/flavor-sheet.js +14 -14
  92. package/lib/utils/icon-registry.js +127 -127
  93. package/lib/utils/loader-registry.js +3 -3
  94. package/lib/utils/locale.js +34 -34
  95. package/lib/utils/mobile.js +1 -1
  96. package/lib/utils/number-format.js +54 -54
  97. package/lib/utils/positioning.js +212 -212
  98. package/lib/utils/property-capture.js +36 -36
  99. package/lib/utils/property-manager.js +125 -125
  100. package/lib/utils/resize-observer.js +23 -23
  101. package/lib/utils/scroll-lock.js +57 -57
  102. package/lib/utils/styles.js +17 -17
  103. package/lib/version.d.ts +1 -1
  104. package/lib/version.js +1 -1
  105. 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
- 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
- }
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: string;
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 from tags (ALWAYS reads from DOM)
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;