@nanahoshi/mona-ui 0.18.0 → 0.18.2
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.
|
@@ -132,6 +132,7 @@ class SegmentedComponent {
|
|
|
132
132
|
#lastAnimatedIndex;
|
|
133
133
|
#lastOptions;
|
|
134
134
|
#lastSize;
|
|
135
|
+
#observedOptionElements;
|
|
135
136
|
#resizeObserver;
|
|
136
137
|
constructor() {
|
|
137
138
|
this.#destroyRef = inject(DestroyRef);
|
|
@@ -139,6 +140,7 @@ class SegmentedComponent {
|
|
|
139
140
|
this.#lastAnimatedIndex = null;
|
|
140
141
|
this.#lastOptions = null;
|
|
141
142
|
this.#lastSize = null;
|
|
143
|
+
this.#observedOptionElements = [];
|
|
142
144
|
this.#resizeObserver = null;
|
|
143
145
|
this.containerClasses = computed(() => {
|
|
144
146
|
const classes = segmentedContainerThemeVariants({ alignment: this.alignment(), rounded: this.rounded() });
|
|
@@ -265,7 +267,7 @@ class SegmentedComponent {
|
|
|
265
267
|
afterRenderEffect({
|
|
266
268
|
read: () => {
|
|
267
269
|
this.selectedIndex();
|
|
268
|
-
this.optionElements();
|
|
270
|
+
const optionElements = this.optionElements();
|
|
269
271
|
this.alignment();
|
|
270
272
|
this.rounded();
|
|
271
273
|
this.animate();
|
|
@@ -276,6 +278,7 @@ class SegmentedComponent {
|
|
|
276
278
|
const suppressTransition = isSizeChange || isOptionsChange;
|
|
277
279
|
this.#lastSize = size;
|
|
278
280
|
this.#lastOptions = options;
|
|
281
|
+
this.observeOptionElements(optionElements);
|
|
279
282
|
this.updateIndicatorGeometry({ suppressTransition });
|
|
280
283
|
}
|
|
281
284
|
});
|
|
@@ -307,6 +310,23 @@ class SegmentedComponent {
|
|
|
307
310
|
this.value.set(option.value);
|
|
308
311
|
this.touch.emit();
|
|
309
312
|
}
|
|
313
|
+
observeOptionElements(optionElements) {
|
|
314
|
+
if (!this.#resizeObserver) {
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
const elements = optionElements.map(optionElement => optionElement.nativeElement);
|
|
318
|
+
for (const element of this.#observedOptionElements) {
|
|
319
|
+
if (!elements.includes(element)) {
|
|
320
|
+
this.#resizeObserver.unobserve(element);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
for (const element of elements) {
|
|
324
|
+
if (!this.#observedOptionElements.includes(element)) {
|
|
325
|
+
this.#resizeObserver.observe(element);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
this.#observedOptionElements = elements;
|
|
329
|
+
}
|
|
310
330
|
setupResizeObserver() {
|
|
311
331
|
if (typeof ResizeObserver === "undefined") {
|
|
312
332
|
return;
|
|
@@ -315,6 +335,7 @@ class SegmentedComponent {
|
|
|
315
335
|
this.updateIndicatorGeometry({ suppressTransition: true });
|
|
316
336
|
});
|
|
317
337
|
this.#resizeObserver.observe(this.#hostElementRef.nativeElement);
|
|
338
|
+
this.observeOptionElements(this.optionElements());
|
|
318
339
|
}
|
|
319
340
|
updateIndicatorGeometry(options) {
|
|
320
341
|
const selectedIndex = this.selectedIndex();
|
|
@@ -332,14 +353,18 @@ class SegmentedComponent {
|
|
|
332
353
|
this.indicatorTransitionEnabled.set(false);
|
|
333
354
|
return;
|
|
334
355
|
}
|
|
335
|
-
const host = this.#hostElementRef.nativeElement;
|
|
336
356
|
const option = selectedElementRef.nativeElement;
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
357
|
+
// `offsetLeft`/`offsetTop`/`offsetWidth`/`offsetHeight` are pure layout values, relative to
|
|
358
|
+
// the nearest positioned ancestor (the host, which is `position: relative` and the option's
|
|
359
|
+
// direct parent). Unlike `getBoundingClientRect()`, they are unaffected by any CSS transform
|
|
360
|
+
// an ancestor applies — e.g. the scale animation `mona-popup` plays while opening. Measuring
|
|
361
|
+
// with `getBoundingClientRect()` there could capture a mid-transition (e.g. 95%-scaled)
|
|
362
|
+
// snapshot that never gets corrected once the animation settles, undersizing/misplacing the
|
|
363
|
+
// indicator relative to the option's real, final box.
|
|
364
|
+
const x = option.offsetLeft;
|
|
365
|
+
const y = option.offsetTop;
|
|
366
|
+
const width = option.offsetWidth;
|
|
367
|
+
const height = option.offsetHeight;
|
|
343
368
|
const shouldAnimate = !options?.suppressTransition &&
|
|
344
369
|
this.animate() &&
|
|
345
370
|
this.indicatorInitialized() &&
|
package/package.json
CHANGED
|
@@ -148,6 +148,7 @@ declare class SegmentedComponent<T extends SegmentedValue = SegmentedValue> impl
|
|
|
148
148
|
protected createOptionContext(option: SegmentedOption<T>, index: number): SegmentedItemTemplateContext<T>;
|
|
149
149
|
protected onOptionBlur(): void;
|
|
150
150
|
protected onOptionChange(option: SegmentedOption<T>): void;
|
|
151
|
+
private observeOptionElements;
|
|
151
152
|
private setupResizeObserver;
|
|
152
153
|
private updateIndicatorGeometry;
|
|
153
154
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<SegmentedComponent<any>, never>;
|