@jsenv/dom 0.9.0 → 0.9.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.
Files changed (2) hide show
  1. package/dist/jsenv_dom.js +201 -92
  2. package/package.json +2 -2
package/dist/jsenv_dom.js CHANGED
@@ -385,7 +385,8 @@ const areSameRGBA = (first, second) => {
385
385
  };
386
386
  const resolveCSSColor = (color, element) => {
387
387
  const rgba = parseCSSColor(color, element);
388
- return stringifyCSSColor(rgba);
388
+ const colorString = stringifyCSSColor(rgba);
389
+ return colorString;
389
390
  };
390
391
 
391
392
  /**
@@ -440,19 +441,48 @@ const parseCSSColor = (color, element) => {
440
441
  return color;
441
442
  }
442
443
 
444
+ // oklab(L a b) and oklab(L a b / alpha)
445
+ if (color.startsWith("oklab(")) {
446
+ const oklabMatch = color.match(
447
+ /^oklab\(\s*([\d.]+)\s+(-?[\d.]+)\s+(-?[\d.]+)(?:\s*\/\s*([\d.]+))?\s*\)$/,
448
+ );
449
+ if (oklabMatch) {
450
+ const L = parseFloat(oklabMatch[1]);
451
+ const a = parseFloat(oklabMatch[2]);
452
+ const b = parseFloat(oklabMatch[3]);
453
+ const alpha = oklabMatch[4] !== undefined ? parseFloat(oklabMatch[4]) : 1;
454
+ const [r, g, bChannel] = oklabToRgb(L, a, b);
455
+ return [r, g, bChannel, alpha];
456
+ }
457
+ return color;
458
+ }
459
+
443
460
  // Pass through CSS color functions we don't handle
444
461
  if (
445
- color.startsWith("color(") ||
446
462
  color.startsWith("lch(") ||
447
463
  color.startsWith("oklch(") ||
448
464
  color.startsWith("lab(") ||
449
- color.startsWith("oklab(") ||
450
465
  color.startsWith("hwb(") ||
451
466
  color.includes("color-contrast(")
452
467
  ) {
453
468
  return color;
454
469
  }
455
470
 
471
+ // color(srgb r g b) and color(srgb r g b / a)
472
+ if (color.startsWith("color(")) {
473
+ const srgbMatch = color.match(
474
+ /^color\(\s*srgb\s+([\d.]+)\s+([\d.]+)\s+([\d.]+)(?:\s*\/\s*([\d.]+))?\s*\)$/,
475
+ );
476
+ if (srgbMatch) {
477
+ const r = Math.round(parseFloat(srgbMatch[1]) * 255);
478
+ const g = Math.round(parseFloat(srgbMatch[2]) * 255);
479
+ const b = Math.round(parseFloat(srgbMatch[3]) * 255);
480
+ const a = srgbMatch[4] !== undefined ? parseFloat(srgbMatch[4]) : 1;
481
+ return [r, g, b, a];
482
+ }
483
+ return color;
484
+ }
485
+
456
486
  // Pass through relative color syntax (CSS Color Module Level 5)
457
487
  if (color.includes(" from ")) {
458
488
  return color;
@@ -491,6 +521,27 @@ const parseCSSColor = (color, element) => {
491
521
  const rgba = convertColorToRgba(resolvedColor);
492
522
  return rgba;
493
523
  };
524
+ const oklabToRgb = (L, a, b) => {
525
+ const l_ = L + 0.3963377774 * a + 0.2158037573 * b;
526
+ const m_ = L - 0.1055613458 * a - 0.0638541728 * b;
527
+ const s_ = L - 0.0894841775 * a - 1.291485548 * b;
528
+ const l = l_ * l_ * l_;
529
+ const m = m_ * m_ * m_;
530
+ const s = s_ * s_ * s_;
531
+ const rLinear = 4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s;
532
+ const gLinear = -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s;
533
+ const bLinear = -0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s;
534
+ const toSrgb = (linear) => {
535
+ const clamped = linear < 0 ? 0 : linear > 1 ? 1 : linear;
536
+ const srgb =
537
+ clamped <= 0.0031308
538
+ ? 12.92 * clamped
539
+ : 1.055 * Math.pow(clamped, 1 / 2.4) - 0.055;
540
+ return Math.round(srgb * 255);
541
+ };
542
+ return [toSrgb(rLinear), toSrgb(gLinear), toSrgb(bLinear)];
543
+ };
544
+
494
545
  /**
495
546
  * Converts HSL color to RGB
496
547
  * @param {number} h - Hue (0-360)
@@ -600,8 +651,9 @@ const convertColorToRgba = (color) => {
600
651
  }
601
652
 
602
653
  // Named colors (basic set)
603
- if (namedColors[color]) {
604
- return [...namedColors[color], 1];
654
+ const namedColorRgb = namedColors[color];
655
+ if (namedColorRgb) {
656
+ return [...namedColorRgb, 1];
605
657
  }
606
658
  return null;
607
659
  };
@@ -622,12 +674,10 @@ const stringifyCSSColor = (value) => {
622
674
  }
623
675
  const rgba = value;
624
676
  const [r, g, b, a = 1] = rgba;
625
-
626
677
  // Validate RGB values
627
678
  if (r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255) {
628
679
  return null;
629
680
  }
630
-
631
681
  // Validate alpha value
632
682
  if (a < 0 || a > 1) {
633
683
  return null;
@@ -645,10 +695,7 @@ const stringifyCSSColor = (value) => {
645
695
  return name;
646
696
  }
647
697
  }
648
- }
649
-
650
- // Use rgb() for opaque colors, rgba() for transparent
651
- if (a === 1) {
698
+ // Use rgb() for opaque colors, rgba() for transparent
652
699
  return `rgb(${rInt}, ${gInt}, ${bInt})`;
653
700
  }
654
701
  if (a === 0 && rInt === 0 && gInt === 0 && bInt === 0) {
@@ -3324,46 +3371,60 @@ const createSetMany = (setter) => {
3324
3371
 
3325
3372
  const setAttributes = createSetMany(setAttribute);
3326
3373
 
3374
+ const isSameColor = (color1, color2) => {
3375
+ if (color1 === color2) {
3376
+ return true;
3377
+ }
3378
+ const color1String = String(parseCSSColor(color1));
3379
+ const color2String = String(parseCSSColor(color2));
3380
+ return color1String === color2String;
3381
+ };
3382
+
3327
3383
  /**
3328
- * Chooses between light and dark colors based on which provides better contrast against a background
3329
- * @param {string} backgroundColor - CSS color value (hex, rgb, hsl, CSS variable, etc.) to test against
3330
- * @param {string} [lightColor="white"] - Light color option (typically for dark backgrounds)
3331
- * @param {string} [darkColor="black"] - Dark color option (typically for light backgrounds)
3332
- * @param {Element} [element] - DOM element to resolve CSS variables against
3333
- * @returns {string} The color that provides better contrast (lightColor or darkColor)
3334
- * @example
3335
- * // Choose text color for a dark blue background
3336
- * pickLightOrDark("#1a202c") // returns "white"
3384
+ * Returns `"white"` or `"black"`, whichever provides better contrast against
3385
+ * the given background color mirroring the CSS `contrast-color()` function.
3337
3386
  *
3338
- * // Choose text color for a light background with CSS variable
3339
- * pickLightOrDark("var(--bg-color)", "white", "black", element) // returns "black" or "white"
3387
+ * `"white"` is preferred when both colors yield the same contrast ratio.
3388
+ *
3389
+ * @param {string} backgroundColor - CSS color value (hex, rgb, hsl, CSS variable, …)
3390
+ * @param {Element} [element] - DOM element used to resolve CSS variables / computed styles
3391
+ * @returns {"white"|"black"}
3392
+ * @example
3393
+ * contrastColor("#1a202c") // "white" (dark background)
3394
+ * contrastColor("#f5f5f5") // "black" (light background)
3395
+ * contrastColor("var(--bg)", el) // "white" or "black"
3340
3396
  */
3341
3397
 
3342
3398
 
3343
- const pickLightOrDark = (
3344
- backgroundColor,
3345
- lightColor = "white",
3346
- darkColor = "black",
3347
- element,
3348
- ) => {
3399
+ const contrastColor = (backgroundColor, element) => {
3349
3400
  const resolvedBgColor = parseCSSColor(backgroundColor, element);
3350
- const resolvedLightColor = parseCSSColor(lightColor, element);
3351
- const resolvedDarkColor = parseCSSColor(darkColor, element);
3352
-
3353
- if (!resolvedBgColor || !resolvedLightColor || !resolvedDarkColor) {
3354
- // Fallback to light color if parsing fails
3355
- return lightColor;
3401
+ if (!resolvedBgColor) {
3402
+ return "white";
3356
3403
  }
3357
3404
 
3358
- const contrastWithLight = getContrastRatio(
3359
- resolvedBgColor,
3360
- resolvedLightColor,
3361
- );
3362
- const contrastWithDark = getContrastRatio(resolvedBgColor, resolvedDarkColor);
3405
+ // Composite against white when the background has transparency so the
3406
+ // luminance reflects what the user actually sees.
3407
+ const [r, g, b] =
3408
+ resolvedBgColor[3] === 1
3409
+ ? resolvedBgColor
3410
+ : compositeColor(resolvedBgColor, WHITE_RGBA);
3363
3411
 
3364
- return contrastWithLight > contrastWithDark ? lightColor : darkColor;
3412
+ const bgLuminance = getLuminance(r, g, b);
3413
+
3414
+ // One luminance comparison replaces two full contrast-ratio computations.
3415
+ // White wins (or ties) when bgLuminance <= the crossover point where both
3416
+ // colors yield identical ratios:
3417
+ // contrastWithWhite = contrastWithBlack
3418
+ // 1.05 / (L + 0.05) = (L + 0.05) / 0.05
3419
+ // L = √(1.05 × 0.05) − 0.05 ≈ 0.179
3420
+ return bgLuminance <= EQUAL_CONTRAST_LUMINANCE ? "white" : "black";
3365
3421
  };
3366
3422
 
3423
+ // Luminance threshold at which white and black yield the same contrast ratio
3424
+ // against a background. Below → white wins or ties; above → black wins.
3425
+ const EQUAL_CONTRAST_LUMINANCE = Math.sqrt(1.05 * 0.05) - 0.05;
3426
+ const WHITE_RGBA = [255, 255, 255, 1];
3427
+
3367
3428
  /**
3368
3429
  * Resolves the luminance value of a CSS color
3369
3430
  * @param {string} color - CSS color value (hex, rgb, hsl, CSS variable, etc.)
@@ -4005,12 +4066,6 @@ const performArrowNavigation = (
4005
4066
  }
4006
4067
 
4007
4068
  const onTargetToFocus = (targetToFocus) => {
4008
- console.debug(
4009
- `Arrow navigation: ${event.key} from`,
4010
- activeElement,
4011
- "to",
4012
- targetToFocus,
4013
- );
4014
4069
  event.preventDefault();
4015
4070
  markFocusNav(event);
4016
4071
  targetToFocus.focus();
@@ -7012,6 +7067,8 @@ installImportMetaCss(import.meta);const setupConstraintFeedbackLine = () => {
7012
7067
  const { grabEvent, dragEvent } = gestureInfo;
7013
7068
  if (
7014
7069
  grabEvent.type === "programmatic" ||
7070
+ // dragEvent can be null when only mousedown without yet any mousemove
7071
+ !dragEvent ||
7015
7072
  dragEvent.type === "programmatic"
7016
7073
  ) {
7017
7074
  // programmatic drag
@@ -8884,31 +8941,48 @@ const initPositionSticky = (element) => {
8884
8941
  const computedStyle = getComputedStyle(element);
8885
8942
  const topCssValue = computedStyle.top;
8886
8943
  const top = parseFloat(topCssValue);
8887
- if (isNaN(top)) {
8888
- return () => {}; // Early return if no valid top value
8944
+ const leftCssValue = computedStyle.left;
8945
+ const left = parseFloat(leftCssValue);
8946
+ const hasTop = !isNaN(top);
8947
+ const hasLeft = !isNaN(left);
8948
+ if (!hasTop && !hasLeft) {
8949
+ return () => {}; // Early return if no valid top or left value
8889
8950
  }
8890
8951
 
8891
8952
  // Skip polyfill if native position:sticky would work (no overflow:auto/hidden parents)
8892
8953
  const scrollContainerSet = getScrollContainerSet(element);
8893
- {
8894
- let hasOverflowHiddenOrAuto = false;
8895
- for (const scrollContainer of scrollContainerSet) {
8896
- const scrollContainerComputedStyle = getComputedStyle(scrollContainer);
8897
- const overflowX = scrollContainerComputedStyle.overflowX;
8898
- if (overflowX === "auto" || overflowX === "hidden") {
8899
- hasOverflowHiddenOrAuto = true;
8900
- break;
8901
- }
8902
- const overflowY = scrollContainerComputedStyle.overflowY;
8903
- if (overflowY === "auto" || overflowY === "hidden") {
8904
- hasOverflowHiddenOrAuto = true;
8905
- break;
8906
- }
8954
+ // Determine per-axis whether an intermediate container blocks native sticky.
8955
+ // Native sticky fails only when there is a scroll container between the element
8956
+ // and the document with overflow set on that axis.
8957
+ let xScrollContainer = null; // first intermediate container blocking horizontal sticky
8958
+ let yScrollContainer = null; // first intermediate container blocking vertical sticky
8959
+ for (const scrollContainer of scrollContainerSet) {
8960
+ if (scrollContainer === document.documentElement) {
8961
+ break;
8962
+ }
8963
+ const style = getComputedStyle(scrollContainer);
8964
+ if (
8965
+ xScrollContainer === null &&
8966
+ (style.overflowX === "auto" ||
8967
+ style.overflowX === "hidden" ||
8968
+ style.overflowX === "scroll")
8969
+ ) {
8970
+ xScrollContainer = scrollContainer;
8907
8971
  }
8908
- if (!hasOverflowHiddenOrAuto) {
8909
- return () => {}; // Native sticky will work fine
8972
+ if (
8973
+ yScrollContainer === null &&
8974
+ (style.overflowY === "auto" ||
8975
+ style.overflowY === "hidden" ||
8976
+ style.overflowY === "scroll")
8977
+ ) {
8978
+ yScrollContainer = scrollContainer;
8910
8979
  }
8911
8980
  }
8981
+ const needsPolyfillX = hasLeft && xScrollContainer !== null;
8982
+ const needsPolyfillY = hasTop && yScrollContainer !== null;
8983
+ if (!needsPolyfillX && !needsPolyfillY) {
8984
+ return () => {}; // Native sticky will work fine on both axes
8985
+ }
8912
8986
 
8913
8987
  const cleanupCallbackSet = new Set();
8914
8988
  const cleanup = () => {
@@ -8954,39 +9028,72 @@ const initPositionSticky = (element) => {
8954
9028
  const placeholderRect = placeholder.getBoundingClientRect();
8955
9029
  const parentRect = parentElement.getBoundingClientRect();
8956
9030
 
8957
- // Calculate left position in viewport coordinates (fixed positioning)
8958
- const leftPosition = placeholderRect.left;
8959
- element.style.left = `${Math.round(leftPosition)}px`;
8960
-
8961
- // Determine if element should be sticky or at its natural position
9031
+ // The CSS `top`/`left` values are offsets from the scroll container's edge.
9032
+ // getBoundingClientRect() always returns viewport coordinates (already accounting
9033
+ // for scroll position of all ancestors), so to convert the CSS offset to a
9034
+ // viewport threshold we add the scroll container's own viewport position.
9035
+ //
9036
+ // Example: main starts at viewport x=250, left=0 → leftThreshold=250.
9037
+ // After scrolling main 670px: placeholderRect.left = 250-670 = -420.
9038
+ // -420 <= 250 → stuck → element.style.left = 250px (main's left edge). ✓
9039
+ //
9040
+ // If no intermediate scroll container exists, use 0 (document/viewport edge).
9041
+ const yContainerRect = yScrollContainer
9042
+ ? yScrollContainer.getBoundingClientRect()
9043
+ : { top: 0 };
9044
+ const xContainerRect = xScrollContainer
9045
+ ? xScrollContainer.getBoundingClientRect()
9046
+ : { left: 0 };
9047
+ const topThreshold = yContainerRect.top + top;
9048
+ const leftThreshold = xContainerRect.left + left;
9049
+
9050
+ // ── Vertical (top) ──────────────────────────────────────────────────────
8962
9051
  let topPosition;
8963
- let isStuck = false;
8964
-
8965
- // Check if we need to stick the element
8966
- if (placeholderRect.top <= top) {
8967
- // Element should be stuck at "top" position in the viewport
8968
- topPosition = top;
8969
- isStuck = true;
8970
-
8971
- // But make sure it doesn't go beyond parent's bottom boundary
8972
- const parentBottom = parentRect.bottom;
8973
- const elementBottom = top + height;
8974
-
8975
- if (elementBottom > parentBottom) {
8976
- // Adjust to stay within parent
8977
- topPosition = parentBottom - height;
9052
+ let isStuckVertically = false;
9053
+ if (hasTop) {
9054
+ if (placeholderRect.top <= topThreshold) {
9055
+ topPosition = topThreshold;
9056
+ isStuckVertically = true;
9057
+ // Don't go beyond parent's bottom boundary
9058
+ const parentBottom = parentRect.bottom;
9059
+ const elementBottom = topThreshold + height;
9060
+ if (elementBottom > parentBottom) {
9061
+ topPosition = parentBottom - height;
9062
+ }
9063
+ } else {
9064
+ topPosition = placeholderRect.top;
8978
9065
  }
8979
9066
  } else {
8980
- // Element should be at its natural position in the flow
8981
9067
  topPosition = placeholderRect.top;
8982
9068
  }
8983
9069
 
9070
+ // ── Horizontal (left) ───────────────────────────────────────────────────
9071
+ let leftPosition;
9072
+ let isStuckHorizontally = false;
9073
+ if (hasLeft) {
9074
+ if (placeholderRect.left <= leftThreshold) {
9075
+ leftPosition = leftThreshold;
9076
+ isStuckHorizontally = true;
9077
+ // Don't go beyond parent's right boundary
9078
+ const parentRight = parentRect.right;
9079
+ const elementRight = leftThreshold + width;
9080
+ if (elementRight > parentRight) {
9081
+ leftPosition = parentRight - width;
9082
+ }
9083
+ } else {
9084
+ leftPosition = placeholderRect.left;
9085
+ }
9086
+ } else {
9087
+ leftPosition = placeholderRect.left;
9088
+ }
9089
+
8984
9090
  element.style.top = `${topPosition}px`;
9091
+ element.style.left = `${Math.round(leftPosition)}px`;
8985
9092
  element.style.width = `${width}px`;
8986
9093
  element.style.height = `${height}px`;
8987
9094
 
8988
9095
  // Set attribute for potential styling
8989
- if (isStuck) {
9096
+ if (isStuckVertically || isStuckHorizontally) {
8990
9097
  element.setAttribute("data-sticky", "");
8991
9098
  } else {
8992
9099
  element.removeAttribute("data-sticky");
@@ -9009,12 +9116,14 @@ const initPositionSticky = (element) => {
9009
9116
  updatePosition();
9010
9117
  };
9011
9118
 
9012
- for (const scrollContainer of scrollContainerSet) {
9013
- scrollContainer.addEventListener("scroll", handleScroll, {
9014
- passive: true,
9015
- });
9119
+ // Listen on all scroll containers (including document) since the element
9120
+ // uses position:fixed and any ancestor scroll changes its apparent position.
9121
+ const listenTargets = new Set(scrollContainerSet);
9122
+ listenTargets.add(document.documentElement);
9123
+ for (const scrollTarget of listenTargets) {
9124
+ scrollTarget.addEventListener("scroll", handleScroll, { passive: true });
9016
9125
  cleanupCallbackSet.add(() => {
9017
- scrollContainer.removeEventListener("scroll", handleScroll, {
9126
+ scrollTarget.removeEventListener("scroll", handleScroll, {
9018
9127
  passive: true,
9019
9128
  });
9020
9129
  });
@@ -12702,4 +12811,4 @@ const useResizeStatus = (elementRef, { as = "number" } = {}) => {
12702
12811
  };
12703
12812
  };
12704
12813
 
12705
- export { EASING, activeElementSignal, addActiveElementEffect, addAttributeEffect, allowWheelThrough, appendStyles, canInterceptKeys, captureScrollState, createBackgroundColorTransition, createBackgroundTransition, createBorderRadiusTransition, createBorderTransition, createDragGestureController, createDragToMoveGestureController, createGroupTransitionController, createHeightTransition, createIterableWeakSet, createOpacityTransition, createPubSub, createStyleController, createTimelineTransition, createTransition, createTranslateXTransition, createValueEffect, createWidthTransition, cubicBezier, dragAfterThreshold, elementIsFocusable, elementIsVisibleForFocus, elementIsVisuallyVisible, findAfter, findAncestor, findBefore, findDescendant, findFocusable, getAvailableHeight, getAvailableWidth, getBackground, getBackgroundColor, getBorder, getBorderRadius, getBorderSizes, getContrastRatio, getDefaultStyles, getDragCoordinates, getDropTargetInfo, getElementSignature, getFirstVisuallyVisibleAncestor, getFocusVisibilityInfo, getHeight, getHeightWithoutTransition, getInnerHeight, getInnerWidth, getLuminance, getMarginSizes, getMaxHeight, getMaxWidth, getMinHeight, getMinWidth, getOpacity, getOpacityWithoutTransition, getPaddingSizes, getPositionedParent, getPreferedColorScheme, getScrollBox, getScrollContainer, getScrollContainerSet, getScrollRelativeRect, getSelfAndAncestorScrolls, getStyle, getTranslateX, getTranslateXWithoutTransition, getTranslateY, getVisuallyVisibleInfo, getWidth, getWidthWithoutTransition, hasCSSSizeUnit, initFlexDetailsSet, initFocusGroup, initPositionSticky, isScrollable, measureScrollbar, mergeOneStyle, mergeTwoStyles, normalizeStyles, parseStyle, pickLightOrDark, pickPositionRelativeTo, prefersDarkColors, prefersLightColors, preventFocusNav, preventFocusNavViaKeyboard, preventIntermediateScrollbar, resolveCSSColor, resolveCSSSize, resolveColorLuminance, setAttribute, setAttributes, setStyles, startDragToResizeGesture, stickyAsRelativeCoords, stringifyStyle, trapFocusInside, trapScrollInside, useActiveElement, useAvailableHeight, useAvailableWidth, useMaxHeight, useMaxWidth, useResizeStatus, visibleRectEffect };
12814
+ export { EASING, activeElementSignal, addActiveElementEffect, addAttributeEffect, allowWheelThrough, appendStyles, canInterceptKeys, captureScrollState, contrastColor, createBackgroundColorTransition, createBackgroundTransition, createBorderRadiusTransition, createBorderTransition, createDragGestureController, createDragToMoveGestureController, createGroupTransitionController, createHeightTransition, createIterableWeakSet, createOpacityTransition, createPubSub, createStyleController, createTimelineTransition, createTransition, createTranslateXTransition, createValueEffect, createWidthTransition, cubicBezier, dragAfterThreshold, elementIsFocusable, elementIsVisibleForFocus, elementIsVisuallyVisible, findAfter, findAncestor, findBefore, findDescendant, findFocusable, getAvailableHeight, getAvailableWidth, getBackground, getBackgroundColor, getBorder, getBorderRadius, getBorderSizes, getContrastRatio, getDefaultStyles, getDragCoordinates, getDropTargetInfo, getElementSignature, getFirstVisuallyVisibleAncestor, getFocusVisibilityInfo, getHeight, getHeightWithoutTransition, getInnerHeight, getInnerWidth, getLuminance, getMarginSizes, getMaxHeight, getMaxWidth, getMinHeight, getMinWidth, getOpacity, getOpacityWithoutTransition, getPaddingSizes, getPositionedParent, getPreferedColorScheme, getScrollBox, getScrollContainer, getScrollContainerSet, getScrollRelativeRect, getSelfAndAncestorScrolls, getStyle, getTranslateX, getTranslateXWithoutTransition, getTranslateY, getVisuallyVisibleInfo, getWidth, getWidthWithoutTransition, hasCSSSizeUnit, initFlexDetailsSet, initFocusGroup, initPositionSticky, isSameColor, isScrollable, measureScrollbar, mergeOneStyle, mergeTwoStyles, normalizeStyles, parseStyle, pickPositionRelativeTo, prefersDarkColors, prefersLightColors, preventFocusNav, preventFocusNavViaKeyboard, preventIntermediateScrollbar, resolveCSSColor, resolveCSSSize, resolveColorLuminance, setAttribute, setAttributes, setStyles, startDragToResizeGesture, stickyAsRelativeCoords, stringifyStyle, trapFocusInside, trapScrollInside, useActiveElement, useAvailableHeight, useAvailableWidth, useMaxHeight, useMaxWidth, useResizeStatus, visibleRectEffect };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/dom",
3
- "version": "0.9.0",
3
+ "version": "0.9.2",
4
4
  "description": "DOM utilities for writing frontend code",
5
5
  "repository": {
6
6
  "type": "git",
@@ -42,7 +42,7 @@
42
42
  "@jsenv/core": "../../../",
43
43
  "@jsenv/navi": "../navi",
44
44
  "@jsenv/snapshot": "../../tooling/snapshot",
45
- "@preact/signals": "2.8.1",
45
+ "@preact/signals": "2.9.0",
46
46
  "preact": "11.0.0-beta.0"
47
47
  },
48
48
  "publishConfig": {