@jsenv/dom 0.7.4 → 0.8.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.
- package/dist/jsenv_dom.js +98 -27
- package/package.json +3 -3
package/dist/jsenv_dom.js
CHANGED
|
@@ -397,10 +397,14 @@ const createSetMany$1 = (setter) => {
|
|
|
397
397
|
const setStyles = createSetMany$1(setStyle);
|
|
398
398
|
const forceStyles = createSetMany$1(forceStyle);
|
|
399
399
|
|
|
400
|
-
// Properties that
|
|
401
|
-
const
|
|
400
|
+
// Properties that can use px units
|
|
401
|
+
const pxPropertySet = new Set([
|
|
402
402
|
"width",
|
|
403
403
|
"height",
|
|
404
|
+
"minWidth",
|
|
405
|
+
"maxWidth",
|
|
406
|
+
"minHeight",
|
|
407
|
+
"maxHeight",
|
|
404
408
|
"top",
|
|
405
409
|
"left",
|
|
406
410
|
"right",
|
|
@@ -415,14 +419,13 @@ const pxProperties = [
|
|
|
415
419
|
"paddingRight",
|
|
416
420
|
"paddingBottom",
|
|
417
421
|
"paddingLeft",
|
|
418
|
-
"border",
|
|
419
422
|
"borderWidth",
|
|
420
423
|
"borderTopWidth",
|
|
421
424
|
"borderRightWidth",
|
|
422
425
|
"borderBottomWidth",
|
|
423
426
|
"borderLeftWidth",
|
|
424
427
|
"fontSize",
|
|
425
|
-
|
|
428
|
+
// lineHeight intentionally excluded - it should remain unitless when no unit is specified
|
|
426
429
|
"letterSpacing",
|
|
427
430
|
"wordSpacing",
|
|
428
431
|
"translateX",
|
|
@@ -436,10 +439,10 @@ const pxProperties = [
|
|
|
436
439
|
"gap",
|
|
437
440
|
"rowGap",
|
|
438
441
|
"columnGap",
|
|
439
|
-
];
|
|
442
|
+
]);
|
|
440
443
|
|
|
441
444
|
// Properties that need deg units
|
|
442
|
-
const
|
|
445
|
+
const degPropertySet = new Set([
|
|
443
446
|
"rotate",
|
|
444
447
|
"rotateX",
|
|
445
448
|
"rotateY",
|
|
@@ -447,10 +450,10 @@ const degProperties = [
|
|
|
447
450
|
"skew",
|
|
448
451
|
"skewX",
|
|
449
452
|
"skewY",
|
|
450
|
-
];
|
|
453
|
+
]);
|
|
451
454
|
|
|
452
455
|
// Properties that should remain unitless
|
|
453
|
-
const
|
|
456
|
+
const unitlessPropertySet = new Set([
|
|
454
457
|
"opacity",
|
|
455
458
|
"zIndex",
|
|
456
459
|
"flexGrow",
|
|
@@ -461,7 +464,7 @@ const unitlessProperties = [
|
|
|
461
464
|
"scaleX",
|
|
462
465
|
"scaleY",
|
|
463
466
|
"scaleZ",
|
|
464
|
-
];
|
|
467
|
+
]);
|
|
465
468
|
|
|
466
469
|
// Well-known CSS units and keywords that indicate a value already has proper formatting
|
|
467
470
|
const cssSizeUnitSet = new Set([
|
|
@@ -505,15 +508,16 @@ const cssKeywordSet = new Set([
|
|
|
505
508
|
"revert",
|
|
506
509
|
]);
|
|
507
510
|
|
|
508
|
-
|
|
509
|
-
const hasUnit = (value) => {
|
|
511
|
+
const getUnit = (value) => {
|
|
510
512
|
for (const cssUnit of cssUnitSet) {
|
|
511
513
|
if (value.endsWith(cssUnit)) {
|
|
512
|
-
return
|
|
514
|
+
return cssUnit;
|
|
513
515
|
}
|
|
514
516
|
}
|
|
515
|
-
return
|
|
517
|
+
return "";
|
|
516
518
|
};
|
|
519
|
+
// Check if value already has a unit
|
|
520
|
+
const isUnitless = (value) => getUnit(value) === "";
|
|
517
521
|
const isKeyword = (value) => {
|
|
518
522
|
return cssKeywordSet.has(value);
|
|
519
523
|
};
|
|
@@ -589,21 +593,45 @@ const normalizeStyle = (value, propertyName, context = "js") => {
|
|
|
589
593
|
return value;
|
|
590
594
|
}
|
|
591
595
|
|
|
592
|
-
if (
|
|
596
|
+
if (propertyName === "lineHeight") {
|
|
597
|
+
if (context === "js") {
|
|
598
|
+
if (typeof value === "string") {
|
|
599
|
+
const unit = getUnit(value);
|
|
600
|
+
if (unit === "px") {
|
|
601
|
+
const float = parseFloat(value);
|
|
602
|
+
return float;
|
|
603
|
+
}
|
|
604
|
+
if (unit === "") {
|
|
605
|
+
return `${value}em`;
|
|
606
|
+
}
|
|
607
|
+
return value;
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
if (context === "css") {
|
|
611
|
+
if (typeof value === "number") {
|
|
612
|
+
// When line height is converted to a number it means
|
|
613
|
+
// it was in pixels, we must restore the unit
|
|
614
|
+
return `${value}px`;
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
return value;
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
if (pxPropertySet.has(propertyName)) {
|
|
593
621
|
return normalizeNumber(value, {
|
|
594
622
|
propertyName,
|
|
595
623
|
unit: "px",
|
|
596
624
|
preferedType: context === "js" ? "number" : "string",
|
|
597
625
|
});
|
|
598
626
|
}
|
|
599
|
-
if (
|
|
627
|
+
if (degPropertySet.has(propertyName)) {
|
|
600
628
|
return normalizeNumber(value, {
|
|
601
629
|
propertyName,
|
|
602
630
|
unit: "deg",
|
|
603
631
|
preferedType: "string",
|
|
604
632
|
});
|
|
605
633
|
}
|
|
606
|
-
if (
|
|
634
|
+
if (unitlessPropertySet.has(propertyName)) {
|
|
607
635
|
return normalizeNumber(value, {
|
|
608
636
|
propertyName,
|
|
609
637
|
unit: "",
|
|
@@ -617,7 +645,7 @@ const normalizeNumber = (value, { unit, propertyName, preferedType }) => {
|
|
|
617
645
|
if (typeof value === "string") {
|
|
618
646
|
// Keep strings as-is (including %, em, rem, auto, none, etc.)
|
|
619
647
|
if (preferedType === "string") {
|
|
620
|
-
if (unit &&
|
|
648
|
+
if (unit && isUnitless(value) && !isKeyword(value)) {
|
|
621
649
|
return `${value}${unit}`;
|
|
622
650
|
}
|
|
623
651
|
return value;
|
|
@@ -664,6 +692,9 @@ const normalizeStyles = (styles, context = "js", mutate = false) => {
|
|
|
664
692
|
const normalized = {};
|
|
665
693
|
for (const key of Object.keys(styles)) {
|
|
666
694
|
const value = styles[key];
|
|
695
|
+
if (value === undefined) {
|
|
696
|
+
continue;
|
|
697
|
+
}
|
|
667
698
|
normalized[key] = normalizeStyle(value, key, context);
|
|
668
699
|
}
|
|
669
700
|
return normalized;
|
|
@@ -878,7 +909,7 @@ const parseSimple2DMatrix = (a, b, c, d, e, f) => {
|
|
|
878
909
|
};
|
|
879
910
|
|
|
880
911
|
// Merge two style objects, handling special cases like transform
|
|
881
|
-
const
|
|
912
|
+
const mergeTwoStyles = (stylesA, stylesB, context = "js") => {
|
|
882
913
|
if (!stylesA) {
|
|
883
914
|
return normalizeStyles(stylesB, context);
|
|
884
915
|
}
|
|
@@ -1118,7 +1149,7 @@ const createStyleController = (name = "anonymous") => {
|
|
|
1118
1149
|
}
|
|
1119
1150
|
|
|
1120
1151
|
const { styles, animation } = elementData;
|
|
1121
|
-
const mergedStyles =
|
|
1152
|
+
const mergedStyles = mergeTwoStyles(styles, stylesToSet);
|
|
1122
1153
|
elementData.styles = mergedStyles;
|
|
1123
1154
|
updateAnimationStyles(animation, mergedStyles);
|
|
1124
1155
|
};
|
|
@@ -1348,8 +1379,12 @@ const createStyleController = (name = "anonymous") => {
|
|
|
1348
1379
|
return controller;
|
|
1349
1380
|
};
|
|
1350
1381
|
|
|
1382
|
+
const getStyleForKeyframe = (styles) => {
|
|
1383
|
+
const cssStyles = normalizeStyles(styles, "css");
|
|
1384
|
+
return cssStyles;
|
|
1385
|
+
};
|
|
1351
1386
|
const createAnimationForStyles = (element, styles, id) => {
|
|
1352
|
-
const cssStylesToSet =
|
|
1387
|
+
const cssStylesToSet = getStyleForKeyframe(styles);
|
|
1353
1388
|
const animation = element.animate([cssStylesToSet], {
|
|
1354
1389
|
duration: 0,
|
|
1355
1390
|
fill: "forwards",
|
|
@@ -1361,7 +1396,7 @@ const createAnimationForStyles = (element, styles, id) => {
|
|
|
1361
1396
|
};
|
|
1362
1397
|
|
|
1363
1398
|
const updateAnimationStyles = (animation, styles) => {
|
|
1364
|
-
const cssStyles =
|
|
1399
|
+
const cssStyles = getStyleForKeyframe(styles);
|
|
1365
1400
|
animation.effect.setKeyframes([cssStyles]);
|
|
1366
1401
|
animation.play();
|
|
1367
1402
|
animation.pause();
|
|
@@ -2149,6 +2184,11 @@ const resolveCSSColor = (color, element, context = "js") => {
|
|
|
2149
2184
|
}
|
|
2150
2185
|
}
|
|
2151
2186
|
|
|
2187
|
+
if (color.startsWith("--")) {
|
|
2188
|
+
console.warn(`found "${color}". Use "var(${color})" instead.`);
|
|
2189
|
+
return null;
|
|
2190
|
+
}
|
|
2191
|
+
|
|
2152
2192
|
// Parse the resolved color and return in the requested format
|
|
2153
2193
|
const rgba = parseCSSColor(resolvedColor);
|
|
2154
2194
|
|
|
@@ -2161,18 +2201,24 @@ const resolveCSSColor = (color, element, context = "js") => {
|
|
|
2161
2201
|
|
|
2162
2202
|
/**
|
|
2163
2203
|
* Chooses between light and dark colors based on which provides better contrast against a background
|
|
2164
|
-
* @param {
|
|
2165
|
-
* @param {string}
|
|
2166
|
-
* @param {string}
|
|
2167
|
-
* @param {
|
|
2204
|
+
* @param {string} backgroundColor - CSS color value (hex, rgb, hsl, CSS variable, etc.) to test against
|
|
2205
|
+
* @param {string} [lightColor="white"] - Light color option (typically for dark backgrounds)
|
|
2206
|
+
* @param {string} [darkColor="black"] - Dark color option (typically for light backgrounds)
|
|
2207
|
+
* @param {Element} [element] - DOM element to resolve CSS variables against
|
|
2168
2208
|
* @returns {string} The color that provides better contrast (lightColor or darkColor)
|
|
2209
|
+
* @example
|
|
2210
|
+
* // Choose text color for a dark blue background
|
|
2211
|
+
* pickLightOrDark("#1a202c") // returns "white"
|
|
2212
|
+
*
|
|
2213
|
+
* // Choose text color for a light background with CSS variable
|
|
2214
|
+
* pickLightOrDark("var(--bg-color)", "white", "black", element) // returns "black" or "white"
|
|
2169
2215
|
*/
|
|
2170
2216
|
|
|
2171
2217
|
const pickLightOrDark = (
|
|
2172
|
-
element,
|
|
2173
2218
|
backgroundColor,
|
|
2174
2219
|
lightColor = "white",
|
|
2175
2220
|
darkColor = "black",
|
|
2221
|
+
element,
|
|
2176
2222
|
) => {
|
|
2177
2223
|
const resolvedBgColor = resolveCSSColor(backgroundColor, element);
|
|
2178
2224
|
const resolvedLightColor = resolveCSSColor(lightColor, element);
|
|
@@ -2192,6 +2238,31 @@ const pickLightOrDark = (
|
|
|
2192
2238
|
return contrastWithLight > contrastWithDark ? lightColor : darkColor;
|
|
2193
2239
|
};
|
|
2194
2240
|
|
|
2241
|
+
/**
|
|
2242
|
+
* Resolves the luminance value of a CSS color
|
|
2243
|
+
* @param {string} color - CSS color value (hex, rgb, hsl, CSS variable, etc.)
|
|
2244
|
+
* @param {Element} [element] - DOM element to resolve CSS variables against
|
|
2245
|
+
* @returns {number|undefined} Relative luminance (0-1) according to WCAG formula, or undefined if color cannot be resolved
|
|
2246
|
+
* @example
|
|
2247
|
+
* // Get luminance of a hex color
|
|
2248
|
+
* resolveColorLuminance("#ff0000") // returns ~0.213 (red)
|
|
2249
|
+
*
|
|
2250
|
+
* // Get luminance of a CSS variable
|
|
2251
|
+
* resolveColorLuminance("var(--primary-color)", element) // returns luminance value or undefined
|
|
2252
|
+
*
|
|
2253
|
+
* // Use for light/dark classification
|
|
2254
|
+
* const luminance = resolveColorLuminance("#2ecc71");
|
|
2255
|
+
* const isLight = luminance > 0.3; // true for light colors, false for dark
|
|
2256
|
+
*/
|
|
2257
|
+
const resolveColorLuminance = (color, element) => {
|
|
2258
|
+
const resolvedColor = resolveCSSColor(color, element);
|
|
2259
|
+
if (!resolvedColor) {
|
|
2260
|
+
return undefined;
|
|
2261
|
+
}
|
|
2262
|
+
const [r, g, b] = resolvedColor;
|
|
2263
|
+
return getLuminance(r, g, b);
|
|
2264
|
+
};
|
|
2265
|
+
|
|
2195
2266
|
const findAncestor = (node, predicate) => {
|
|
2196
2267
|
let ancestor = node.parentNode;
|
|
2197
2268
|
while (ancestor) {
|
|
@@ -11803,4 +11874,4 @@ const notifyTransitionOverflow = (element, transitionId) => {
|
|
|
11803
11874
|
};
|
|
11804
11875
|
};
|
|
11805
11876
|
|
|
11806
|
-
export { EASING, activeElementSignal, addActiveElementEffect, addAttributeEffect, addWillChange, allowWheelThrough, appendStyles, canInterceptKeys, captureScrollState, createDragGestureController, createDragToMoveGestureController, createHeightTransition, createIterableWeakSet, createOpacityTransition, createPubSub, createStyleController, createTimelineTransition, createTransition, createTranslateXTransition, createValueEffect, createWidthTransition, cubicBezier, dragAfterThreshold, elementIsFocusable, elementIsVisibleForFocus, elementIsVisuallyVisible, findAfter, findAncestor, findBefore, findDescendant, findFocusable, getAvailableHeight, getAvailableWidth, getBorderSizes, getContrastRatio, getDefaultStyles, getDragCoordinates, getDropTargetInfo, getElementSignature, getFirstVisuallyVisibleAncestor, getFocusVisibilityInfo, getHeight, getInnerHeight, getInnerWidth, getMarginSizes, getMaxHeight, getMaxWidth, getMinHeight, getMinWidth, getOpacity, getPaddingSizes, getPositionedParent, getPreferedColorScheme, getScrollContainer, getScrollContainerSet, getScrollRelativeRect, getSelfAndAncestorScrolls, getStyle, getTranslateX, getTranslateY, getVisuallyVisibleInfo, getWidth, initFlexDetailsSet, initFocusGroup, initPositionSticky, initUITransition, isScrollable,
|
|
11877
|
+
export { EASING, activeElementSignal, addActiveElementEffect, addAttributeEffect, addWillChange, allowWheelThrough, appendStyles, canInterceptKeys, captureScrollState, createDragGestureController, createDragToMoveGestureController, createHeightTransition, createIterableWeakSet, createOpacityTransition, createPubSub, createStyleController, createTimelineTransition, createTransition, createTranslateXTransition, createValueEffect, createWidthTransition, cubicBezier, dragAfterThreshold, elementIsFocusable, elementIsVisibleForFocus, elementIsVisuallyVisible, findAfter, findAncestor, findBefore, findDescendant, findFocusable, getAvailableHeight, getAvailableWidth, getBorderSizes, getContrastRatio, getDefaultStyles, getDragCoordinates, getDropTargetInfo, getElementSignature, getFirstVisuallyVisibleAncestor, getFocusVisibilityInfo, getHeight, getInnerHeight, getInnerWidth, getLuminance, getMarginSizes, getMaxHeight, getMaxWidth, getMinHeight, getMinWidth, getOpacity, getPaddingSizes, getPositionedParent, getPreferedColorScheme, getScrollContainer, getScrollContainerSet, getScrollRelativeRect, getSelfAndAncestorScrolls, getStyle, getTranslateX, getTranslateY, getVisuallyVisibleInfo, getWidth, initFlexDetailsSet, initFocusGroup, initPositionSticky, initUITransition, isScrollable, mergeTwoStyles, normalizeStyle, normalizeStyles, parseCSSColor, pickLightOrDark, pickPositionRelativeTo, prefersDarkColors, prefersLightColors, preventFocusNav, preventFocusNavViaKeyboard, resolveCSSColor, resolveCSSSize, resolveColorLuminance, setAttribute, setAttributes, setStyles, startDragToResizeGesture, stickyAsRelativeCoords, stringifyCSSColor, 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.
|
|
3
|
+
"version": "0.8.1",
|
|
4
4
|
"description": "DOM utilities for writing frontend code",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -36,8 +36,8 @@
|
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@jsenv/core": "../../../",
|
|
38
38
|
"@jsenv/navi": "../navi",
|
|
39
|
-
"@preact/signals": "
|
|
40
|
-
"preact": "
|
|
39
|
+
"@preact/signals": "2.4.0",
|
|
40
|
+
"preact": "11.0.0-beta.0"
|
|
41
41
|
},
|
|
42
42
|
"publishConfig": {
|
|
43
43
|
"access": "public"
|