@nanahoshi/mona-ui 0.18.0 → 0.18.1

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,12 +278,14 @@ 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
  });
282
285
  afterNextRender({
283
286
  read: () => {
284
287
  this.setupResizeObserver();
288
+ this.scheduleSettledGeometryUpdate();
285
289
  }
286
290
  });
287
291
  this.#destroyRef.onDestroy(() => {
@@ -307,6 +311,39 @@ class SegmentedComponent {
307
311
  this.value.set(option.value);
308
312
  this.touch.emit();
309
313
  }
314
+ observeOptionElements(optionElements) {
315
+ if (!this.#resizeObserver) {
316
+ return;
317
+ }
318
+ const elements = optionElements.map(optionElement => optionElement.nativeElement);
319
+ for (const element of this.#observedOptionElements) {
320
+ if (!elements.includes(element)) {
321
+ this.#resizeObserver.unobserve(element);
322
+ }
323
+ }
324
+ for (const element of elements) {
325
+ if (!this.#observedOptionElements.includes(element)) {
326
+ this.#resizeObserver.observe(element);
327
+ }
328
+ }
329
+ this.#observedOptionElements = elements;
330
+ }
331
+ /**
332
+ * Guards against a stale indicator snapshot when the control mounts inside a container that is
333
+ * still transitioning in (e.g. a popup's enter animation): the host's own box may not change once
334
+ * that settles, so the ResizeObserver on it alone would never re-fire to correct the geometry.
335
+ */
336
+ scheduleSettledGeometryUpdate() {
337
+ const win = this.#hostElementRef.nativeElement.ownerDocument.defaultView;
338
+ if (!win) {
339
+ return;
340
+ }
341
+ win.requestAnimationFrame(() => {
342
+ win.requestAnimationFrame(() => {
343
+ this.updateIndicatorGeometry({ suppressTransition: true });
344
+ });
345
+ });
346
+ }
310
347
  setupResizeObserver() {
311
348
  if (typeof ResizeObserver === "undefined") {
312
349
  return;
@@ -315,6 +352,7 @@ class SegmentedComponent {
315
352
  this.updateIndicatorGeometry({ suppressTransition: true });
316
353
  });
317
354
  this.#resizeObserver.observe(this.#hostElementRef.nativeElement);
355
+ this.observeOptionElements(this.optionElements());
318
356
  }
319
357
  updateIndicatorGeometry(options) {
320
358
  const selectedIndex = this.selectedIndex();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nanahoshi/mona-ui",
3
- "version": "0.18.0",
3
+ "version": "0.18.1",
4
4
  "description": "A very light Angular UI framework",
5
5
  "author": "Nanahoshi",
6
6
  "repository": {
@@ -148,6 +148,13 @@ 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;
152
+ /**
153
+ * Guards against a stale indicator snapshot when the control mounts inside a container that is
154
+ * still transitioning in (e.g. a popup's enter animation): the host's own box may not change once
155
+ * that settles, so the ResizeObserver on it alone would never re-fire to correct the geometry.
156
+ */
157
+ private scheduleSettledGeometryUpdate;
151
158
  private setupResizeObserver;
152
159
  private updateIndicatorGeometry;
153
160
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<SegmentedComponent<any>, never>;