@m3e/core 1.2.1 → 1.3.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/dist/index.js CHANGED
@@ -154,6 +154,28 @@ class MonitorControllerBase {
154
154
  }
155
155
  _MonitorControllerBase_host = new WeakMap(), _MonitorControllerBase_target = new WeakMap(), _MonitorControllerBase_targets = new WeakMap();
156
156
 
157
+ /**
158
+ * Computes a CSS size expression (var(), %, rem, calc(), etc.) relative to the given host element.
159
+ * @param {HTMLElement} host - The element whose coordinate system and CSS variables should be used to resolve the expression.
160
+ * @param {string} expression - The CSS expression to evaluate.
161
+ * @returns {number} The resolved pixel value.
162
+ */
163
+ function computeCssSize(host, expression) {
164
+ if (!expression) return 0;
165
+ const temp = document.createElement("div");
166
+ temp.style.all = "inherit";
167
+ temp.style.width = expression;
168
+ temp.style.position = "absolute";
169
+ temp.style.visibility = "hidden";
170
+ temp.style.pointerEvents = "none";
171
+ host.appendChild(temp);
172
+ try {
173
+ return parseFloat(getComputedStyle(temp).width);
174
+ } finally {
175
+ temp.remove();
176
+ }
177
+ }
178
+
157
179
  /**
158
180
  * Determines the number of textual lines presented by an element.
159
181
  * @param {HTMLElement} element The element for which to compute the number of lines.
@@ -172,8 +194,12 @@ function computeLineCount(element) {
172
194
  */
173
195
  async function focusWhenReady(element, timeout = 200) {
174
196
  element.focus();
197
+ function isFocused(element) {
198
+ const root = element.getRootNode();
199
+ return root instanceof ShadowRoot ? root.activeElement === element : document.activeElement === element;
200
+ }
175
201
  const start = performance.now();
176
- while (element.shadowRoot?.activeElement !== element) {
202
+ while (!isFocused(element)) {
177
203
  if (!element.isConnected || performance.now() - start > timeout) {
178
204
  return false;
179
205
  }
@@ -645,6 +671,52 @@ function scrollIntoViewIfNeeded(element, scrollContainer, options) {
645
671
  }
646
672
  }
647
673
 
674
+ var _VelocityTracker_samples, _VelocityTracker_windowMs;
675
+ /** Utility for computing gesture velocity over a rolling time window. */
676
+ class VelocityTracker {
677
+ /**
678
+ * @param {number} [windowMs = 100] The size of the rolling sampling window in milliseconds.
679
+ */
680
+ constructor(windowMs = 100) {
681
+ /** @private */_VelocityTracker_samples.set(this, []);
682
+ /** @private */
683
+ _VelocityTracker_windowMs.set(this, void 0);
684
+ __classPrivateFieldSet(this, _VelocityTracker_windowMs, windowMs, "f");
685
+ }
686
+ /**
687
+ * Adds a new sample to the tracker.
688
+ * @param {number} value The value in pixels.
689
+ * @param {number} [timestamp=performance.now()] The timestamp when `value` changed.
690
+ */
691
+ add(value, timestamp = performance.now()) {
692
+ __classPrivateFieldGet(this, _VelocityTracker_samples, "f").push({
693
+ y: value,
694
+ t: timestamp
695
+ });
696
+ const cutoff = timestamp - __classPrivateFieldGet(this, _VelocityTracker_windowMs, "f");
697
+ while (__classPrivateFieldGet(this, _VelocityTracker_samples, "f").length > 1 && __classPrivateFieldGet(this, _VelocityTracker_samples, "f")[0].t < cutoff) {
698
+ __classPrivateFieldGet(this, _VelocityTracker_samples, "f").shift();
699
+ }
700
+ }
701
+ /**
702
+ * Computes the current velocity in px/s.
703
+ * @returns The vertical velocity in pixels per second.
704
+ */
705
+ getVelocity() {
706
+ if (__classPrivateFieldGet(this, _VelocityTracker_samples, "f").length < 2) return 0;
707
+ const first = __classPrivateFieldGet(this, _VelocityTracker_samples, "f")[0];
708
+ const last = __classPrivateFieldGet(this, _VelocityTracker_samples, "f")[__classPrivateFieldGet(this, _VelocityTracker_samples, "f").length - 1];
709
+ const dy = last.y - first.y;
710
+ const dt = (last.t - first.t) / 1000;
711
+ return dt > 0 ? dy / dt : 0;
712
+ }
713
+ /** Clears all stored samples. */
714
+ reset() {
715
+ __classPrivateFieldGet(this, _VelocityTracker_samples, "f").length = 0;
716
+ }
717
+ }
718
+ _VelocityTracker_samples = new WeakMap(), _VelocityTracker_windowMs = new WeakMap();
719
+
648
720
  var _FocusController_instances, _FocusController_touch, _FocusController_callback, _FocusController_keyDownHandler, _FocusController_focusInHandler, _FocusController_focusOutHandler, _FocusController_touchStartHandler, _FocusController_touchEndHandler, _FocusController_hadKeydown, _FocusController_windowKeyDownHandler, _FocusController_windowPointerDownHandler, _FocusController_handleKeyDown, _FocusController_handleFocusIn, _FocusController_handleFocusOut;
649
721
  /** A `ReactiveController` used to monitor the focused state of one or more elements. */
650
722
  class FocusController extends MonitorControllerBase {
@@ -1385,6 +1457,75 @@ _ScrollController_debounce = new WeakMap(), _ScrollController_callback = new Wea
1385
1457
  };
1386
1458
  __decorate([debounce(40)], ScrollController.prototype, "_debounceCallback", null);
1387
1459
 
1460
+ var _ScrollLockController_instances, _ScrollLockController_locked, _ScrollLockController_scrollTop, _ScrollLockController_scrollLeft, _ScrollLockController_previousOverflow, _ScrollLockController_previousScrollbarGutter, _ScrollLockController_isVerticallyScrollable;
1461
+ /**
1462
+ * A `ReactiveController` that provides safe, predictable scroll locking for modal UI
1463
+ * surfaces (dialogs, bottom sheets, overlays).
1464
+ */
1465
+ class ScrollLockController {
1466
+ constructor(host) {
1467
+ _ScrollLockController_instances.add(this);
1468
+ /** @private */
1469
+ _ScrollLockController_locked.set(this, false);
1470
+ /** @private */
1471
+ _ScrollLockController_scrollTop.set(this, 0);
1472
+ /** @private */
1473
+ _ScrollLockController_scrollLeft.set(this, 0);
1474
+ /** @private */
1475
+ _ScrollLockController_previousOverflow.set(this, "");
1476
+ /** @private */
1477
+ _ScrollLockController_previousScrollbarGutter.set(this, "");
1478
+ host.addController(this);
1479
+ }
1480
+ /** Locks document scrolling only if scroll actually exists. */
1481
+ lock() {
1482
+ if (__classPrivateFieldGet(this, _ScrollLockController_locked, "f")) return;
1483
+ __classPrivateFieldSet(this, _ScrollLockController_locked, true, "f");
1484
+ // Save scroll position
1485
+ __classPrivateFieldSet(this, _ScrollLockController_scrollTop, window.scrollY, "f");
1486
+ __classPrivateFieldSet(this, _ScrollLockController_scrollLeft, window.scrollX, "f");
1487
+ // Save existing inline styles
1488
+ __classPrivateFieldSet(this, _ScrollLockController_previousOverflow, document.documentElement.style.overflow, "f");
1489
+ __classPrivateFieldSet(this, _ScrollLockController_previousScrollbarGutter, document.documentElement.style.scrollbarGutter, "f");
1490
+ // Only apply gutter if vertical scroll exists
1491
+ if (__classPrivateFieldGet(this, _ScrollLockController_instances, "m", _ScrollLockController_isVerticallyScrollable).call(this)) {
1492
+ document.documentElement.style.scrollbarGutter = "stable";
1493
+ }
1494
+ // Lock scroll
1495
+ document.documentElement.style.overflow = "hidden";
1496
+ // Freeze scroll position
1497
+ window.scrollTo(__classPrivateFieldGet(this, _ScrollLockController_scrollLeft, "f"), __classPrivateFieldGet(this, _ScrollLockController_scrollTop, "f"));
1498
+ }
1499
+ /** Unlocks document scrolling and restores the previous state. */
1500
+ unlock() {
1501
+ if (!__classPrivateFieldGet(this, _ScrollLockController_locked, "f")) return;
1502
+ __classPrivateFieldSet(this, _ScrollLockController_locked, false, "f");
1503
+ // Restore previous inline styles
1504
+ document.documentElement.style.overflow = __classPrivateFieldGet(this, _ScrollLockController_previousOverflow, "f");
1505
+ document.documentElement.style.scrollbarGutter = __classPrivateFieldGet(this, _ScrollLockController_previousScrollbarGutter, "f");
1506
+ // Restore scroll position
1507
+ window.scrollTo(__classPrivateFieldGet(this, _ScrollLockController_scrollLeft, "f"), __classPrivateFieldGet(this, _ScrollLockController_scrollTop, "f"));
1508
+ }
1509
+ /** @inheritdoc */
1510
+ hostDisconnected() {
1511
+ this.unlock();
1512
+ }
1513
+ }
1514
+ _ScrollLockController_locked = new WeakMap(), _ScrollLockController_scrollTop = new WeakMap(), _ScrollLockController_scrollLeft = new WeakMap(), _ScrollLockController_previousOverflow = new WeakMap(), _ScrollLockController_previousScrollbarGutter = new WeakMap(), _ScrollLockController_instances = new WeakSet(), _ScrollLockController_isVerticallyScrollable = function _ScrollLockController_isVerticallyScrollable() {
1515
+ return document.documentElement.scrollHeight > document.documentElement.clientHeight;
1516
+ };
1517
+
1518
+ /** Converts a space-separated attribute in to an array of strings. */
1519
+ const spaceSeparatedStringConverter = {
1520
+ fromAttribute(value) {
1521
+ if (!value) return [];
1522
+ return value.split(/\s+/).map(d => d.trim()).filter(Boolean);
1523
+ },
1524
+ toAttribute(value) {
1525
+ return value.join(" ");
1526
+ }
1527
+ };
1528
+
1388
1529
  /**
1389
1530
  * @license
1390
1531
  * Copyright 2017 Google LLC
@@ -5496,5 +5637,5 @@ __decorate([n$1({
5496
5637
  })], M3eTextHighlightElement.prototype, "caseSensitive", void 0);
5497
5638
  M3eTextHighlightElement = M3eTextHighlightElement_1 = __decorate([t$2("m3e-text-highlight")], M3eTextHighlightElement);
5498
5639
 
5499
- export { ActionElementBase, AnimationLoopController, AttachInternals, Checked, CheckedIndeterminate, ConstraintValidation, DesignToken, Dirty, Disabled, DisabledInteractive, EventAttribute, FocusController, Focusable, FormAssociated, FormSubmitter, HoverController, HtmlFor, IntersectionController, KeyboardClick, Labelled, LinkButton, LongPressController, M3eCollapsibleElement, M3eElevationElement, M3eFocusRingElement, M3ePseudoCheckboxElement, M3ePseudoRadioElement, M3eRippleElement, M3eScrollContainerElement, M3eSlideElement, M3eStateLayerElement, M3eTextHighlightElement, M3eTextOverflowElement, MutationController, PressedController, ReadOnly, Required, RequiredConstraintValidation, ResizeController, Role, ScrollController, Selected, Touched, Vertical, checkOrSelect, computeLineCount, debounce, defaultValue, focusWhenReady, forcedColorsActive, formValue, generateClipPaths, getTextContent, guid, hasAssignedNodes, hasKeys, interceptProperty, internals, isAttachInternalsMixin, isCheckedIndeterminateMixin, isCheckedMixin, isCheckedOrSelected, isCheckedOrSelectedMixin, isConstraintValidationMixin, isDirtyMixin, isDisabledInteractiveMixin, isDisabledMixin, isFormAssociatedMixin, isFormSubmitterMixin, isHtmlForMixin, isLabelledMixin, isLinkButtonMixin, isReadOnlyMixin, isRequiredConstraintValidationMixin, isRequiredMixin, isSelectedMixin, isTouchedMixin, isVerticalMixin, prefersReducedMotion, renderPseudoLink, resolveElementById, resolveFragmentUrl, safeStyleMap, scrollIntoViewIfNeeded, updateLabels, validate };
5640
+ export { ActionElementBase, AnimationLoopController, AttachInternals, Checked, CheckedIndeterminate, ConstraintValidation, DesignToken, Dirty, Disabled, DisabledInteractive, EventAttribute, FocusController, Focusable, FormAssociated, FormSubmitter, HoverController, HtmlFor, IntersectionController, KeyboardClick, Labelled, LinkButton, LongPressController, M3eCollapsibleElement, M3eElevationElement, M3eFocusRingElement, M3ePseudoCheckboxElement, M3ePseudoRadioElement, M3eRippleElement, M3eScrollContainerElement, M3eSlideElement, M3eStateLayerElement, M3eTextHighlightElement, M3eTextOverflowElement, MutationController, PressedController, ReadOnly, Required, RequiredConstraintValidation, ResizeController, Role, ScrollController, ScrollLockController, Selected, Touched, VelocityTracker, Vertical, checkOrSelect, computeCssSize, computeLineCount, debounce, defaultValue, focusWhenReady, forcedColorsActive, formValue, generateClipPaths, getTextContent, guid, hasAssignedNodes, hasKeys, interceptProperty, internals, isAttachInternalsMixin, isCheckedIndeterminateMixin, isCheckedMixin, isCheckedOrSelected, isCheckedOrSelectedMixin, isConstraintValidationMixin, isDirtyMixin, isDisabledInteractiveMixin, isDisabledMixin, isFormAssociatedMixin, isFormSubmitterMixin, isHtmlForMixin, isLabelledMixin, isLinkButtonMixin, isReadOnlyMixin, isRequiredConstraintValidationMixin, isRequiredMixin, isSelectedMixin, isTouchedMixin, isVerticalMixin, prefersReducedMotion, renderPseudoLink, resolveElementById, resolveFragmentUrl, safeStyleMap, scrollIntoViewIfNeeded, spaceSeparatedStringConverter, updateLabels, validate };
5500
5641
  //# sourceMappingURL=index.js.map