@diabolic/pointy 1.1.1 → 1.2.0

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/src/pointy.js CHANGED
@@ -49,6 +49,9 @@
49
49
  * - classNames {object} - Full override of class names
50
50
  * - cssVarPrefix {string} - CSS variable prefix (default: classPrefix)
51
51
  * - pointerSvg {string} - Custom SVG for pointer
52
+ * - bubbleBackgroundColor {string} - Custom bubble background color (default: '#0a1551')
53
+ * - bubbleTextColor {string} - Custom bubble text color (default: 'white')
54
+ * - bubbleMaxWidth {string} - Max width for bubble (default: '90vw')
52
55
  * - onStepChange {function} - Callback on step change
53
56
  * - onComplete {function} - Callback on tour complete
54
57
  *
@@ -147,6 +150,7 @@
147
150
  *
148
151
  * Setters (all emit change events):
149
152
  * setEasing(), setAnimationDuration(), setIntroFadeDuration(), setBubbleFadeDuration(),
153
+ * setBubbleBackgroundColor(), setBubbleTextColor(), setBubbleMaxWidth(),
150
154
  * setMessageInterval(), setMessageTransitionDuration(), setOffset(), setZIndex(),
151
155
  * setStayInViewport(enabled, thresholds?), setDirection(direction),
152
156
  * setHorizontalDirection(direction), setVerticalDirection(direction),
@@ -181,7 +185,7 @@ class Pointy {
181
185
  static POINTER_SVG = `
182
186
  <svg xmlns="http://www.w3.org/2000/svg" width="33" height="33" fill="none" viewBox="0 0 33 33">
183
187
  <g filter="url(#pointy-shadow)">
184
- <path fill="#0a1551" d="m18.65 24.262 6.316-14.905c.467-1.103-.645-2.215-1.748-1.747L8.313 13.925c-1.088.461-1.083 2.004.008 2.459l5.049 2.104c.325.135.583.393.718.718l2.104 5.049c.454 1.09 1.997 1.095 2.458.007"/>
188
+ <path fill="currentColor" d="m18.65 24.262 6.316-14.905c.467-1.103-.645-2.215-1.748-1.747L8.313 13.925c-1.088.461-1.083 2.004.008 2.459l5.049 2.104c.325.135.583.393.718.718l2.104 5.049c.454 1.09 1.997 1.095 2.458.007"/>
185
189
  </g>
186
190
  <defs>
187
191
  <filter id="pointy-shadow" width="32.576" height="32.575" x="0" y="0" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse">
@@ -260,6 +264,10 @@ class Pointy {
260
264
  --${vp}-duration: 1000ms;
261
265
  --${vp}-easing: cubic-bezier(0, 0.55, 0.45, 1);
262
266
  --${vp}-bubble-fade: 500ms;
267
+ --${vp}-bubble-bg: #0a1551;
268
+ --${vp}-bubble-color: white;
269
+ --${vp}-bubble-max-width: min(400px, 90vw);
270
+ --${vp}-pointer-color: #0a1551;
263
271
  transition: left var(--${vp}-duration) var(--${vp}-easing), top var(--${vp}-duration) var(--${vp}-easing), opacity 0.3s ease;
264
272
  animation: ${cn.container}-float 3s ease-in-out infinite;
265
273
  }
@@ -280,7 +288,8 @@ class Pointy {
280
288
  .${cn.pointer} {
281
289
  width: 33px;
282
290
  height: 33px;
283
- transition: transform var(--${vp}-duration) var(--${vp}-easing);
291
+ color: var(--${vp}-pointer-color);
292
+ transition: transform var(--${vp}-duration) var(--${vp}-easing), color 0.3s ease;
284
293
  }
285
294
 
286
295
  .${cn.bubble} {
@@ -288,21 +297,23 @@ class Pointy {
288
297
  right: 26px;
289
298
  left: auto;
290
299
  top: 0;
291
- background: #0a1551;
292
- color: white;
300
+ background: var(--${vp}-bubble-bg);
301
+ color: var(--${vp}-bubble-color);
293
302
  padding: 4px 12px;
294
303
  border-radius: 14px;
295
304
  font-size: 14px;
296
305
  line-height: 20px;
297
306
  font-weight: 400;
298
307
  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.25);
299
- white-space: nowrap;
308
+ width: max-content;
309
+ max-width: var(--${vp}-bubble-max-width);
300
310
  overflow: hidden;
301
- transition: width 0.5s cubic-bezier(0.4, 0, 0.2, 1), height 0.5s cubic-bezier(0.4, 0, 0.2, 1), transform var(--${vp}-duration) var(--${vp}-easing), opacity var(--${vp}-bubble-fade) ease, left var(--${vp}-duration) var(--${vp}-easing), right var(--${vp}-duration) var(--${vp}-easing);
311
+ transition: width 0.3s cubic-bezier(0.4, 0, 0.2, 1), height 0.3s cubic-bezier(0.4, 0, 0.2, 1), transform var(--${vp}-duration) var(--${vp}-easing), opacity var(--${vp}-bubble-fade) ease, left var(--${vp}-duration) var(--${vp}-easing), right var(--${vp}-duration) var(--${vp}-easing), background 0.3s ease, color 0.3s ease;
302
312
  }
303
313
 
304
314
  .${cn.bubbleText} {
305
- display: inline-block;
315
+ display: block;
316
+ word-break: break-word;
306
317
  }
307
318
  `;
308
319
  }
@@ -342,16 +353,20 @@ class Pointy {
342
353
  static animateText(element, newContent, duration = 500, bubble = null, onComplete = null) {
343
354
  const hideTime = duration * 0.4;
344
355
  const revealTime = duration * 0.6;
356
+ const resizeTime = 300; // Match CSS transition
345
357
 
346
358
  // Measure new content dimensions using a hidden container
347
359
  let newWidth = null;
348
360
  let newHeight = null;
349
361
  if (bubble) {
362
+ // Get bubble's max-width for proper measurement of multi-line content
363
+ const bubbleStyles = window.getComputedStyle(bubble);
364
+ const maxWidth = bubbleStyles.maxWidth;
365
+
350
366
  const measureDiv = document.createElement('div');
351
- measureDiv.style.cssText = 'visibility: hidden; position: absolute; padding: 4px 12px;';
367
+ measureDiv.style.cssText = `visibility: hidden; position: absolute; padding: 4px 12px; width: max-content; max-width: ${maxWidth};`;
352
368
  Pointy.renderContent(measureDiv, newContent);
353
369
  bubble.appendChild(measureDiv);
354
- // Add horizontal padding (12px left + 12px right = 24px)
355
370
  newWidth = measureDiv.offsetWidth;
356
371
  newHeight = measureDiv.offsetHeight;
357
372
  bubble.removeChild(measureDiv);
@@ -361,22 +376,26 @@ class Pointy {
361
376
  const currentHeight = bubble.offsetHeight;
362
377
  bubble.style.width = currentWidth + 'px';
363
378
  bubble.style.height = currentHeight + 'px';
379
+
380
+ // Force reflow
381
+ bubble.offsetHeight;
382
+
383
+ // Start resizing bubble to new size immediately
384
+ bubble.style.width = newWidth + 'px';
385
+ bubble.style.height = newHeight + 'px';
364
386
  }
365
387
 
366
388
  // Phase 1: Hide old text (clip from left, disappears to right)
367
389
  element.style.transition = `clip-path ${hideTime}ms ease-in`;
368
390
  element.style.clipPath = 'inset(0 0 0 100%)';
369
391
 
392
+ // Wait for bubble resize AND text hide, then change content
393
+ const contentChangeDelay = Math.max(hideTime, resizeTime);
394
+
370
395
  setTimeout(() => {
371
- // Change content while fully clipped
396
+ // Change content while fully clipped AND bubble is at new size
372
397
  Pointy.renderContent(element, newContent);
373
398
 
374
- // Animate bubble to new size
375
- if (bubble && newWidth !== null) {
376
- bubble.style.width = newWidth + 'px';
377
- bubble.style.height = newHeight + 'px';
378
- }
379
-
380
399
  // Prepare for reveal (start fully clipped from right)
381
400
  element.style.transition = 'none';
382
401
  element.style.clipPath = 'inset(0 100% 0 0)';
@@ -388,16 +407,16 @@ class Pointy {
388
407
  element.style.transition = `clip-path ${revealTime}ms ease-out`;
389
408
  element.style.clipPath = 'inset(0 0 0 0)';
390
409
 
391
- // Clear dimensions after transition so it can auto-size
410
+ // Clear explicit dimensions after reveal so bubble can auto-size
392
411
  if (bubble) {
393
412
  setTimeout(() => {
394
413
  bubble.style.width = '';
395
414
  bubble.style.height = '';
396
- }, revealTime + 100);
415
+ }, revealTime + 50);
397
416
  }
398
417
 
399
418
  if (onComplete) onComplete();
400
- }, hideTime);
419
+ }, contentChangeDelay);
401
420
  }
402
421
 
403
422
  /**
@@ -480,6 +499,10 @@ class Pointy {
480
499
  this.autoplayWaitForMessages = options.autoplayWaitForMessages !== undefined ? options.autoplayWaitForMessages : true; // Wait for all messages before advancing
481
500
  this.hideOnComplete = options.hideOnComplete !== undefined ? options.hideOnComplete : true; // Auto-hide after tour completes
482
501
  this.hideOnCompleteDelay = options.hideOnCompleteDelay !== undefined ? options.hideOnCompleteDelay : null; // Delay before hide (null = use animationDuration)
502
+ this.bubbleBackgroundColor = options.bubbleBackgroundColor || null; // Custom bubble background color
503
+ this.bubbleTextColor = options.bubbleTextColor || null; // Custom bubble text color
504
+ this.bubbleMaxWidth = options.bubbleMaxWidth || null; // Max width for bubble (default: min(400px, 90vw))
505
+ this.pointerColor = options.pointerColor || null; // Custom pointer/cursor color
483
506
  this._autoplayTimeoutId = null;
484
507
  this._autoplayPaused = false;
485
508
  this._messagesCompletedForStep = false; // Track if all messages have been shown
@@ -504,6 +527,10 @@ class Pointy {
504
527
  this._lastDirectionChangeTime = 0; // Debounce direction changes
505
528
  this.manualHorizontalDirection = null; // 'left', 'right', or null (auto)
506
529
  this.manualVerticalDirection = null; // 'up', 'down', or null (auto)
530
+ this._autoDirectionLocked = false; // Lock auto-direction after first calculation per target
531
+ this._lastTargetElement = null; // Track target changes to recalculate direction
532
+ this._bubbleConstraintApplied = false; // Track if bubble constraint has been calculated
533
+ this._cachedBubbleNaturalWidth = null; // Cache bubble's natural width before constraint
507
534
  this.moveTimeout = null;
508
535
  this._hasShownBefore = false; // For intro animation
509
536
 
@@ -520,6 +547,20 @@ class Pointy {
520
547
  this.container.style.setProperty(`--${this.cssVarPrefix}-easing`, this._resolveEasing(this.easing));
521
548
  this.container.style.setProperty(`--${this.cssVarPrefix}-bubble-fade`, `${this.bubbleFadeDuration}ms`);
522
549
 
550
+ // Apply custom bubble colors if provided
551
+ if (this.bubbleBackgroundColor) {
552
+ this.container.style.setProperty(`--${this.cssVarPrefix}-bubble-bg`, this.bubbleBackgroundColor);
553
+ }
554
+ if (this.bubbleTextColor) {
555
+ this.container.style.setProperty(`--${this.cssVarPrefix}-bubble-color`, this.bubbleTextColor);
556
+ }
557
+ if (this.bubbleMaxWidth) {
558
+ this.container.style.setProperty(`--${this.cssVarPrefix}-bubble-max-width`, this.bubbleMaxWidth);
559
+ }
560
+ if (this.pointerColor) {
561
+ this.container.style.setProperty(`--${this.cssVarPrefix}-pointer-color`, this.pointerColor);
562
+ }
563
+
523
564
  // Apply floating animation setting
524
565
  if (!this.floatingAnimation) {
525
566
  this.container.style.animationPlayState = 'paused';
@@ -655,46 +696,47 @@ class Pointy {
655
696
  this.lastTargetY = currentTargetY;
656
697
  }
657
698
 
658
- // Stay in viewport: check if bubble would go off-screen and flip accordingly
659
- // Only auto-flip directions that are not manually set
660
- if (this.stayInViewport) {
699
+ // Check if target changed - if so, unlock auto direction and bubble constraint
700
+ if (this._lastTargetElement !== this.targetElement) {
701
+ this._autoDirectionLocked = false;
702
+ this._bubbleConstraintApplied = false;
703
+ this._cachedBubbleNaturalWidth = null;
704
+ this.bubble.style.maxWidth = ''; // Reset constraint for new target
705
+ this._lastTargetElement = this.targetElement;
706
+ }
707
+
708
+ // Stay in viewport: calculate optimal direction ONCE per target, then lock it
709
+ // This prevents flip-flopping during animations and tracking
710
+ if (this.stayInViewport && !this._autoDirectionLocked) {
661
711
  const prevIsPointingLeft = this.isPointingLeft;
662
712
  const prevIsPointingUp = this.isPointingUp;
663
713
 
664
- // Horizontal flip check (only if not manually set)
714
+ // Horizontal direction (only if not manually set)
665
715
  if (this.manualHorizontalDirection === null) {
666
- const bubbleLeftIfPointingLeft = targetRect.left - bubbleWidth - this.viewportThresholdX;
667
- const bubbleRightIfPointingRight = targetRect.right + bubbleWidth + this.viewportThresholdX;
716
+ // Calculate available space on each side
717
+ const spaceOnLeft = targetRect.left - this.viewportThresholdX;
718
+ const spaceOnRight = viewportWidth - targetRect.right - this.viewportThresholdX;
668
719
 
669
- // Flip to right side if bubble goes off left edge
670
- if (bubbleLeftIfPointingLeft < 0 && this.isPointingLeft) {
671
- this.isPointingLeft = false;
672
- }
673
- // Flip to left side if bubble goes off right edge
674
- else if (bubbleRightIfPointingRight > viewportWidth && !this.isPointingLeft) {
675
- this.isPointingLeft = true;
676
- }
677
- // Return to default (left) if there's room
678
- else if (bubbleLeftIfPointingLeft >= 0 && !this.isPointingLeft) {
679
- this.isPointingLeft = true;
680
- }
720
+ // Pick the side with more space
721
+ // Add a small preference for left (default) when spaces are similar
722
+ const leftPreference = 20;
723
+ this.isPointingLeft = spaceOnLeft + leftPreference >= spaceOnRight;
681
724
  }
682
725
 
683
- // Vertical flip check (only if not manually set)
726
+ // Vertical direction (only if not manually set)
684
727
  if (this.manualVerticalDirection === null) {
685
- const bubbleBottomIfPointingUp = targetRect.bottom + bubbleHeight + this.viewportThresholdY;
686
- const bubbleTopIfPointingDown = targetRect.top - bubbleHeight - this.viewportThresholdY;
728
+ // Calculate available space above and below
729
+ const spaceBelow = viewportHeight - targetRect.bottom - this.viewportThresholdY;
730
+ const spaceAbove = targetRect.top - this.viewportThresholdY;
687
731
 
688
- // Flip to pointing down if bubble goes off bottom edge
689
- if (bubbleBottomIfPointingUp > viewportHeight && this.isPointingUp) {
690
- this.isPointingUp = false;
691
- }
692
- // Flip to pointing up if bubble goes off top edge
693
- else if (bubbleTopIfPointingDown < 0 && !this.isPointingUp) {
694
- this.isPointingUp = true;
695
- }
732
+ // Pick the side with more space, slight preference for below (pointing up)
733
+ const belowPreference = 10;
734
+ this.isPointingUp = spaceBelow + belowPreference >= spaceAbove;
696
735
  }
697
736
 
737
+ // Lock direction - won't recalculate until target changes
738
+ this._autoDirectionLocked = true;
739
+
698
740
  // Emit flip events if direction changed
699
741
  if (prevIsPointingLeft !== this.isPointingLeft) {
700
742
  this._emit('flipHorizontal', {
@@ -756,8 +798,77 @@ class Pointy {
756
798
 
757
799
  this.pointer.style.transform = pointerRotation;
758
800
  this.bubble.style.transform = bubbleTransform;
801
+
802
+ // Clamp container position to keep pointer visible in viewport
803
+ const minLeft = scrollX + 8;
804
+ const maxLeft = scrollX + viewportWidth - 40;
805
+ left = Math.max(minLeft, Math.min(left, maxLeft));
806
+
759
807
  this.container.style.left = `${left}px`;
760
808
  this.container.style.top = `${top}px`;
809
+
810
+ // Ensure bubble doesn't overflow viewport horizontally
811
+ // Pass the viewport-relative position for constraint calculation
812
+ const viewportLeft = left - scrollX;
813
+ this._constrainBubbleToViewport(viewportLeft, viewportWidth);
814
+ }
815
+
816
+ /**
817
+ * Constrain bubble width and position to prevent horizontal viewport overflow
818
+ * @private
819
+ */
820
+ _constrainBubbleToViewport(containerLeft, viewportWidth) {
821
+ // Only calculate constraint once per target to prevent oscillation
822
+ if (this._bubbleConstraintApplied) return;
823
+
824
+ const padding = 8; // Minimum padding from viewport edge
825
+
826
+ // Temporarily remove any existing constraint to measure natural width
827
+ const previousMaxWidth = this.bubble.style.maxWidth;
828
+ this.bubble.style.maxWidth = '';
829
+
830
+ // Force layout reflow to get accurate measurement
831
+ const bubbleNaturalWidth = this.bubble.offsetWidth || 100;
832
+
833
+ // Cache the natural width
834
+ this._cachedBubbleNaturalWidth = bubbleNaturalWidth;
835
+
836
+ let needsConstraint = false;
837
+ let constrainedWidth = 0;
838
+
839
+ if (this.isPointingLeft) {
840
+ // Bubble extends to the left of pointer
841
+ // Bubble's left edge = containerLeft - bubbleWidth + 26 (right offset of bubble)
842
+ const bubbleLeftEdge = containerLeft - bubbleNaturalWidth + 26;
843
+
844
+ if (bubbleLeftEdge < padding) {
845
+ // Bubble would overflow left edge - constrain its width
846
+ const availableWidth = containerLeft + 26 - padding;
847
+ constrainedWidth = Math.max(availableWidth, 80);
848
+ needsConstraint = true;
849
+ }
850
+ } else {
851
+ // Bubble extends to the right of pointer
852
+ // Bubble's right edge = containerLeft + 26 + bubbleWidth
853
+ const bubbleRightEdge = containerLeft + 26 + bubbleNaturalWidth;
854
+
855
+ if (bubbleRightEdge > viewportWidth - padding) {
856
+ // Bubble would overflow right edge - constrain its width
857
+ const availableWidth = viewportWidth - containerLeft - 26 - padding;
858
+ constrainedWidth = Math.max(availableWidth, 80);
859
+ needsConstraint = true;
860
+ }
861
+ }
862
+
863
+ if (needsConstraint) {
864
+ this.bubble.style.maxWidth = `${constrainedWidth}px`;
865
+ } else {
866
+ // Restore previous or let CSS variable handle it
867
+ this.bubble.style.maxWidth = previousMaxWidth || '';
868
+ }
869
+
870
+ // Mark constraint as applied for this target
871
+ this._bubbleConstraintApplied = true;
761
872
  }
762
873
 
763
874
  show() {
@@ -1044,6 +1155,10 @@ class Pointy {
1044
1155
  this.currentMessages = Array.isArray(firstStep.content) ? firstStep.content : [firstStep.content];
1045
1156
  this.currentMessageIndex = 0;
1046
1157
  Pointy.renderContent(this.bubbleText, this.currentMessages[0]);
1158
+ this._autoDirectionLocked = false; // Unlock direction for recalculation
1159
+ this._bubbleConstraintApplied = false;
1160
+ this._cachedBubbleNaturalWidth = null;
1161
+ this.bubble.style.maxWidth = '';
1047
1162
  }
1048
1163
 
1049
1164
  // After animation completes
@@ -1685,6 +1800,74 @@ class Pointy {
1685
1800
  this._emit('bubbleFadeDurationChange', { from: oldDuration, to: duration });
1686
1801
  }
1687
1802
 
1803
+ /**
1804
+ * Set the bubble background color
1805
+ * @param {string} color - CSS color value (hex, rgb, etc.)
1806
+ */
1807
+ setBubbleBackgroundColor(color) {
1808
+ const oldColor = this.bubbleBackgroundColor;
1809
+ if (oldColor === color) return;
1810
+
1811
+ this.bubbleBackgroundColor = color;
1812
+ if (color) {
1813
+ this.container.style.setProperty(`--${this.cssVarPrefix}-bubble-bg`, color);
1814
+ } else {
1815
+ this.container.style.removeProperty(`--${this.cssVarPrefix}-bubble-bg`);
1816
+ }
1817
+ this._emit('bubbleBackgroundColorChange', { from: oldColor, to: color });
1818
+ }
1819
+
1820
+ /**
1821
+ * Set the bubble text color
1822
+ * @param {string} color - CSS color value (hex, rgb, etc.)
1823
+ */
1824
+ setBubbleTextColor(color) {
1825
+ const oldColor = this.bubbleTextColor;
1826
+ if (oldColor === color) return;
1827
+
1828
+ this.bubbleTextColor = color;
1829
+ if (color) {
1830
+ this.container.style.setProperty(`--${this.cssVarPrefix}-bubble-color`, color);
1831
+ } else {
1832
+ this.container.style.removeProperty(`--${this.cssVarPrefix}-bubble-color`);
1833
+ }
1834
+ this._emit('bubbleTextColorChange', { from: oldColor, to: color });
1835
+ }
1836
+
1837
+ /**
1838
+ * Set the bubble max width
1839
+ * @param {string} width - CSS width value (e.g., '90vw', '300px')
1840
+ */
1841
+ setBubbleMaxWidth(width) {
1842
+ const oldWidth = this.bubbleMaxWidth;
1843
+ if (oldWidth === width) return;
1844
+
1845
+ this.bubbleMaxWidth = width;
1846
+ if (width) {
1847
+ this.container.style.setProperty(`--${this.cssVarPrefix}-bubble-max-width`, width);
1848
+ } else {
1849
+ this.container.style.removeProperty(`--${this.cssVarPrefix}-bubble-max-width`);
1850
+ }
1851
+ this._emit('bubbleMaxWidthChange', { from: oldWidth, to: width });
1852
+ }
1853
+
1854
+ /**
1855
+ * Set the pointer/cursor color
1856
+ * @param {string} color - CSS color value (hex, rgb, etc.)
1857
+ */
1858
+ setPointerColor(color) {
1859
+ const oldColor = this.pointerColor;
1860
+ if (oldColor === color) return;
1861
+
1862
+ this.pointerColor = color;
1863
+ if (color) {
1864
+ this.container.style.setProperty(`--${this.cssVarPrefix}-pointer-color`, color);
1865
+ } else {
1866
+ this.container.style.removeProperty(`--${this.cssVarPrefix}-pointer-color`);
1867
+ }
1868
+ this._emit('pointerColorChange', { from: oldColor, to: color });
1869
+ }
1870
+
1688
1871
  /**
1689
1872
  * Get the initial position coordinates based on initialPosition setting
1690
1873
  * @returns {{x: number, y: number, isPointingUp?: boolean}} - Position coordinates and optional direction
@@ -1962,9 +2145,13 @@ class Pointy {
1962
2145
  // Parse direction: can be 'up', 'down', 'left', 'right', 'up-left', 'down-right', etc.
1963
2146
  this._parseDirection(step.direction);
1964
2147
 
1965
- // Reset velocity tracking for new target
2148
+ // Reset velocity tracking and direction lock for new target
1966
2149
  this._targetYHistory = [];
1967
2150
  this.lastTargetY = null;
2151
+ this._autoDirectionLocked = false;
2152
+ this._bubbleConstraintApplied = false;
2153
+ this._cachedBubbleNaturalWidth = null;
2154
+ this.bubble.style.maxWidth = '';
1968
2155
 
1969
2156
  // Pause floating animation during movement
1970
2157
  this.container.classList.add(this.classNames.moving);
@@ -2286,9 +2473,13 @@ class Pointy {
2286
2473
  // Parse direction (null means auto)
2287
2474
  this._parseDirection(direction);
2288
2475
 
2289
- // Reset velocity tracking for new target
2476
+ // Reset velocity tracking and direction lock for new target
2290
2477
  this._targetYHistory = [];
2291
2478
  this.lastTargetY = null;
2479
+ this._autoDirectionLocked = false;
2480
+ this._bubbleConstraintApplied = false;
2481
+ this._cachedBubbleNaturalWidth = null;
2482
+ this.bubble.style.maxWidth = '';
2292
2483
 
2293
2484
  // Pause floating animation during movement
2294
2485
  this.container.classList.add(this.classNames.moving);