@jsenv/dom 0.8.8 → 0.9.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 +131 -73
- package/package.json +2 -2
package/dist/jsenv_dom.js
CHANGED
|
@@ -104,29 +104,31 @@ const getElementSignature = (element) => {
|
|
|
104
104
|
if (element.nodeType === Node.TEXT_NODE) {
|
|
105
105
|
return `#text(${getElementSignature(element.nodeValue)})`;
|
|
106
106
|
}
|
|
107
|
+
if (element instanceof HTMLElement) {
|
|
108
|
+
const tagName = element.tagName.toLowerCase();
|
|
109
|
+
const dataUIName = element.getAttribute("data-ui-name");
|
|
110
|
+
if (dataUIName) {
|
|
111
|
+
return `${tagName}[data-ui-name="${dataUIName}"]`;
|
|
112
|
+
}
|
|
113
|
+
if (element === document.body) {
|
|
114
|
+
return "<body>";
|
|
115
|
+
}
|
|
116
|
+
if (element === document.documentElement) {
|
|
117
|
+
return "<html>";
|
|
118
|
+
}
|
|
119
|
+
const elementId = element.id;
|
|
120
|
+
if (elementId) {
|
|
121
|
+
return `${tagName}#${elementId}`;
|
|
122
|
+
}
|
|
123
|
+
const className = element.className;
|
|
124
|
+
if (className) {
|
|
125
|
+
return `${tagName}.${className.split(" ").join(".")}`;
|
|
126
|
+
}
|
|
107
127
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
if (dataUIName) {
|
|
111
|
-
return `${tagName}[data-ui-name="${dataUIName}"]`;
|
|
128
|
+
const parentSignature = getElementSignature(element.parentElement);
|
|
129
|
+
return `${parentSignature} > ${tagName}`;
|
|
112
130
|
}
|
|
113
|
-
|
|
114
|
-
return "<body>";
|
|
115
|
-
}
|
|
116
|
-
if (element === document.documentElement) {
|
|
117
|
-
return "<html>";
|
|
118
|
-
}
|
|
119
|
-
const elementId = element.id;
|
|
120
|
-
if (elementId) {
|
|
121
|
-
return `${tagName}#${elementId}`;
|
|
122
|
-
}
|
|
123
|
-
const className = element.className;
|
|
124
|
-
if (className) {
|
|
125
|
-
return `${tagName}.${className.split(" ").join(".")}`;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
const parentSignature = getElementSignature(element.parentElement);
|
|
129
|
-
return `${parentSignature} > ${tagName}`;
|
|
131
|
+
return String(element);
|
|
130
132
|
};
|
|
131
133
|
|
|
132
134
|
const createIterableWeakSet = () => {
|
|
@@ -440,7 +442,6 @@ const parseCSSColor = (color, element) => {
|
|
|
440
442
|
|
|
441
443
|
// Pass through CSS color functions we don't handle
|
|
442
444
|
if (
|
|
443
|
-
color.startsWith("color(") ||
|
|
444
445
|
color.startsWith("lch(") ||
|
|
445
446
|
color.startsWith("oklch(") ||
|
|
446
447
|
color.startsWith("lab(") ||
|
|
@@ -451,6 +452,21 @@ const parseCSSColor = (color, element) => {
|
|
|
451
452
|
return color;
|
|
452
453
|
}
|
|
453
454
|
|
|
455
|
+
// color(srgb r g b) and color(srgb r g b / a)
|
|
456
|
+
if (color.startsWith("color(")) {
|
|
457
|
+
const srgbMatch = color.match(
|
|
458
|
+
/^color\(\s*srgb\s+([\d.]+)\s+([\d.]+)\s+([\d.]+)(?:\s*\/\s*([\d.]+))?\s*\)$/,
|
|
459
|
+
);
|
|
460
|
+
if (srgbMatch) {
|
|
461
|
+
const r = Math.round(parseFloat(srgbMatch[1]) * 255);
|
|
462
|
+
const g = Math.round(parseFloat(srgbMatch[2]) * 255);
|
|
463
|
+
const b = Math.round(parseFloat(srgbMatch[3]) * 255);
|
|
464
|
+
const a = srgbMatch[4] !== undefined ? parseFloat(srgbMatch[4]) : 1;
|
|
465
|
+
return [r, g, b, a];
|
|
466
|
+
}
|
|
467
|
+
return color;
|
|
468
|
+
}
|
|
469
|
+
|
|
454
470
|
// Pass through relative color syntax (CSS Color Module Level 5)
|
|
455
471
|
if (color.includes(" from ")) {
|
|
456
472
|
return color;
|
|
@@ -598,8 +614,9 @@ const convertColorToRgba = (color) => {
|
|
|
598
614
|
}
|
|
599
615
|
|
|
600
616
|
// Named colors (basic set)
|
|
601
|
-
|
|
602
|
-
|
|
617
|
+
const namedColorRgb = namedColors[color];
|
|
618
|
+
if (namedColorRgb) {
|
|
619
|
+
return [...namedColorRgb, 1];
|
|
603
620
|
}
|
|
604
621
|
return null;
|
|
605
622
|
};
|
|
@@ -3322,46 +3339,60 @@ const createSetMany = (setter) => {
|
|
|
3322
3339
|
|
|
3323
3340
|
const setAttributes = createSetMany(setAttribute);
|
|
3324
3341
|
|
|
3342
|
+
const isSameColor = (color1, color2) => {
|
|
3343
|
+
if (color1 === color2) {
|
|
3344
|
+
return true;
|
|
3345
|
+
}
|
|
3346
|
+
const color1String = String(parseCSSColor(color1));
|
|
3347
|
+
const color2String = String(parseCSSColor(color2));
|
|
3348
|
+
return color1String === color2String;
|
|
3349
|
+
};
|
|
3350
|
+
|
|
3325
3351
|
/**
|
|
3326
|
-
*
|
|
3327
|
-
*
|
|
3328
|
-
*
|
|
3329
|
-
*
|
|
3330
|
-
* @param {Element} [element] - DOM element to resolve CSS variables against
|
|
3331
|
-
* @returns {string} The color that provides better contrast (lightColor or darkColor)
|
|
3332
|
-
* @example
|
|
3333
|
-
* // Choose text color for a dark blue background
|
|
3334
|
-
* pickLightOrDark("#1a202c") // returns "white"
|
|
3352
|
+
* Returns `"white"` or `"black"`, whichever provides better contrast against
|
|
3353
|
+
* the given background color — mirroring the CSS `contrast-color()` function.
|
|
3354
|
+
*
|
|
3355
|
+
* `"white"` is preferred when both colors yield the same contrast ratio.
|
|
3335
3356
|
*
|
|
3336
|
-
*
|
|
3337
|
-
*
|
|
3357
|
+
* @param {string} backgroundColor - CSS color value (hex, rgb, hsl, CSS variable, …)
|
|
3358
|
+
* @param {Element} [element] - DOM element used to resolve CSS variables / computed styles
|
|
3359
|
+
* @returns {"white"|"black"}
|
|
3360
|
+
* @example
|
|
3361
|
+
* contrastColor("#1a202c") // "white" (dark background)
|
|
3362
|
+
* contrastColor("#f5f5f5") // "black" (light background)
|
|
3363
|
+
* contrastColor("var(--bg)", el) // "white" or "black"
|
|
3338
3364
|
*/
|
|
3339
3365
|
|
|
3340
3366
|
|
|
3341
|
-
const
|
|
3342
|
-
backgroundColor,
|
|
3343
|
-
lightColor = "white",
|
|
3344
|
-
darkColor = "black",
|
|
3345
|
-
element,
|
|
3346
|
-
) => {
|
|
3367
|
+
const contrastColor = (backgroundColor, element) => {
|
|
3347
3368
|
const resolvedBgColor = parseCSSColor(backgroundColor, element);
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
if (!resolvedBgColor || !resolvedLightColor || !resolvedDarkColor) {
|
|
3352
|
-
// Fallback to light color if parsing fails
|
|
3353
|
-
return lightColor;
|
|
3369
|
+
if (!resolvedBgColor) {
|
|
3370
|
+
return "white";
|
|
3354
3371
|
}
|
|
3355
3372
|
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3373
|
+
// Composite against white when the background has transparency so the
|
|
3374
|
+
// luminance reflects what the user actually sees.
|
|
3375
|
+
const [r, g, b] =
|
|
3376
|
+
resolvedBgColor[3] === 1
|
|
3377
|
+
? resolvedBgColor
|
|
3378
|
+
: compositeColor(resolvedBgColor, WHITE_RGBA);
|
|
3379
|
+
|
|
3380
|
+
const bgLuminance = getLuminance(r, g, b);
|
|
3361
3381
|
|
|
3362
|
-
|
|
3382
|
+
// One luminance comparison replaces two full contrast-ratio computations.
|
|
3383
|
+
// White wins (or ties) when bgLuminance <= the crossover point where both
|
|
3384
|
+
// colors yield identical ratios:
|
|
3385
|
+
// contrastWithWhite = contrastWithBlack
|
|
3386
|
+
// 1.05 / (L + 0.05) = (L + 0.05) / 0.05
|
|
3387
|
+
// L = √(1.05 × 0.05) − 0.05 ≈ 0.179
|
|
3388
|
+
return bgLuminance <= EQUAL_CONTRAST_LUMINANCE ? "white" : "black";
|
|
3363
3389
|
};
|
|
3364
3390
|
|
|
3391
|
+
// Luminance threshold at which white and black yield the same contrast ratio
|
|
3392
|
+
// against a background. Below → white wins or ties; above → black wins.
|
|
3393
|
+
const EQUAL_CONTRAST_LUMINANCE = Math.sqrt(1.05 * 0.05) - 0.05;
|
|
3394
|
+
const WHITE_RGBA = [255, 255, 255, 1];
|
|
3395
|
+
|
|
3365
3396
|
/**
|
|
3366
3397
|
* Resolves the luminance value of a CSS color
|
|
3367
3398
|
* @param {string} color - CSS color value (hex, rgb, hsl, CSS variable, etc.)
|
|
@@ -9991,7 +10022,6 @@ const createTransition = ({
|
|
|
9991
10022
|
`Debug breakpoint hit at ${(breakpoint * 100).toFixed(1)}% progress`,
|
|
9992
10023
|
);
|
|
9993
10024
|
const notifyDebuggerEnd = notifyDebuggerStart();
|
|
9994
|
-
debugger;
|
|
9995
10025
|
notifyDebuggerEnd();
|
|
9996
10026
|
}
|
|
9997
10027
|
if (effect === "pause") {
|
|
@@ -11615,7 +11645,7 @@ const initFlexDetailsSet = (
|
|
|
11615
11645
|
}
|
|
11616
11646
|
};
|
|
11617
11647
|
|
|
11618
|
-
const applyAllocatedSpaces = (
|
|
11648
|
+
const applyAllocatedSpaces = ({ reason, animated }) => {
|
|
11619
11649
|
const changeSet = new Set();
|
|
11620
11650
|
let maxChange = 0;
|
|
11621
11651
|
|
|
@@ -11623,9 +11653,8 @@ const initFlexDetailsSet = (
|
|
|
11623
11653
|
const allocatedSpace = allocatedSpaceMap.get(child);
|
|
11624
11654
|
const allocatedSize = spaceToSize(allocatedSpace, child);
|
|
11625
11655
|
const space = spaceMap.get(child);
|
|
11626
|
-
const size = spaceToSize(space, child);
|
|
11656
|
+
const size = spaceToSize(space === undefined ? 0 : space, child);
|
|
11627
11657
|
const sizeChange = Math.abs(size - allocatedSize);
|
|
11628
|
-
|
|
11629
11658
|
if (size === allocatedSize) {
|
|
11630
11659
|
continue;
|
|
11631
11660
|
}
|
|
@@ -11658,16 +11687,18 @@ const initFlexDetailsSet = (
|
|
|
11658
11687
|
}
|
|
11659
11688
|
|
|
11660
11689
|
// Don't animate if changes are too small (avoids imperceptible animations that hide scrollbars)
|
|
11661
|
-
const shouldAnimate =
|
|
11662
|
-
resizeDetails.animated && maxChange >= ANIMATION_THRESHOLD_PX;
|
|
11690
|
+
const shouldAnimate = animated && maxChange >= ANIMATION_THRESHOLD_PX;
|
|
11663
11691
|
|
|
11664
|
-
if (debug &&
|
|
11692
|
+
if (debug && animated && !shouldAnimate) {
|
|
11665
11693
|
console.debug(
|
|
11666
11694
|
`🚫 Skipping animation: max change ${maxChange.toFixed(2)}px < ${ANIMATION_THRESHOLD_PX}px threshold`,
|
|
11667
11695
|
);
|
|
11668
11696
|
}
|
|
11669
11697
|
|
|
11670
11698
|
if (!shouldAnimate) {
|
|
11699
|
+
if (debug) {
|
|
11700
|
+
console.debug(`Applying size changes without animation`);
|
|
11701
|
+
}
|
|
11671
11702
|
const sizeChangeEntries = [];
|
|
11672
11703
|
for (const { element, target, sideEffect } of changeSet) {
|
|
11673
11704
|
element.style.height = `${target}px`;
|
|
@@ -11677,19 +11708,26 @@ const initFlexDetailsSet = (
|
|
|
11677
11708
|
}
|
|
11678
11709
|
sizeChangeEntries.push({ element, value: target });
|
|
11679
11710
|
}
|
|
11680
|
-
onSizeChange?.(sizeChangeEntries,
|
|
11711
|
+
onSizeChange?.(sizeChangeEntries, { reason, animated });
|
|
11681
11712
|
return;
|
|
11682
11713
|
}
|
|
11683
11714
|
|
|
11715
|
+
if (debug) {
|
|
11716
|
+
console.debug(`Start animating size changes`);
|
|
11717
|
+
}
|
|
11684
11718
|
// Create height animations for each element in changeSet
|
|
11685
11719
|
const transitions = Array.from(changeSet).map(({ element, target }) => {
|
|
11686
11720
|
const transition = createHeightTransition(element, target, {
|
|
11687
11721
|
duration: HEIGHT_TRANSITION_DURATION,
|
|
11722
|
+
// because we also set inline height when we don't want animation and it should win
|
|
11723
|
+
// we could also commit styles for animation or cancel any animation so that when we explicitely set height
|
|
11724
|
+
// sync the transition gets overriden
|
|
11725
|
+
styleSynchronizer: "inline_style",
|
|
11688
11726
|
});
|
|
11689
11727
|
return transition;
|
|
11690
11728
|
});
|
|
11691
11729
|
|
|
11692
|
-
const transition = transitionController.
|
|
11730
|
+
const transition = transitionController.update(transitions, {
|
|
11693
11731
|
onChange: (changeEntries, isLast) => {
|
|
11694
11732
|
// Apply side effects for each animated element
|
|
11695
11733
|
for (const { transition, value } of changeEntries) {
|
|
@@ -11713,7 +11751,7 @@ const initFlexDetailsSet = (
|
|
|
11713
11751
|
);
|
|
11714
11752
|
onSizeChange(
|
|
11715
11753
|
sizeChangeEntries,
|
|
11716
|
-
isLast ? {
|
|
11754
|
+
isLast ? { reason, animated: false } : { reason, animated },
|
|
11717
11755
|
);
|
|
11718
11756
|
}
|
|
11719
11757
|
},
|
|
@@ -11958,23 +11996,23 @@ const initFlexDetailsSet = (
|
|
|
11958
11996
|
}
|
|
11959
11997
|
};
|
|
11960
11998
|
|
|
11961
|
-
const updateSpaceDistribution = (
|
|
11999
|
+
const updateSpaceDistribution = ({ reason, animated }) => {
|
|
11962
12000
|
if (debug) {
|
|
11963
|
-
console.group(`updateSpaceDistribution: ${
|
|
12001
|
+
console.group(`updateSpaceDistribution: ${reason}`);
|
|
11964
12002
|
}
|
|
11965
12003
|
prepareSpaceDistribution();
|
|
11966
|
-
distributeAvailableSpace(
|
|
12004
|
+
distributeAvailableSpace(reason);
|
|
11967
12005
|
distributeRemainingSpace({
|
|
11968
12006
|
childToGrow: openedDetailsArray[openedDetailsArray.length - 1],
|
|
11969
12007
|
childToShrinkFrom: lastChild,
|
|
11970
12008
|
});
|
|
11971
12009
|
if (
|
|
11972
|
-
|
|
11973
|
-
|
|
12010
|
+
reason === "initial_space_distribution" ||
|
|
12011
|
+
reason === "content_change"
|
|
11974
12012
|
) {
|
|
11975
12013
|
spaceMap.clear(); // force to set size at start
|
|
11976
12014
|
}
|
|
11977
|
-
applyAllocatedSpaces(
|
|
12015
|
+
applyAllocatedSpaces({ reason, animated });
|
|
11978
12016
|
saveCurrentSizeAsRequestedSizes();
|
|
11979
12017
|
if (debug) {
|
|
11980
12018
|
console.groupEnd();
|
|
@@ -12015,6 +12053,19 @@ const initFlexDetailsSet = (
|
|
|
12015
12053
|
}
|
|
12016
12054
|
}
|
|
12017
12055
|
if (someNew || someOld) {
|
|
12056
|
+
for (const child of container.children) {
|
|
12057
|
+
if (!child.dispatchEvent) {
|
|
12058
|
+
// ignore text nodes
|
|
12059
|
+
continue;
|
|
12060
|
+
}
|
|
12061
|
+
child.dispatchEvent(
|
|
12062
|
+
new CustomEvent("resizablechange", {
|
|
12063
|
+
detail: {
|
|
12064
|
+
resizable: resizableDetailsIdSet.has(child.id),
|
|
12065
|
+
},
|
|
12066
|
+
}),
|
|
12067
|
+
);
|
|
12068
|
+
}
|
|
12018
12069
|
onResizableDetailsChange?.(resizableDetailsIdSet);
|
|
12019
12070
|
}
|
|
12020
12071
|
};
|
|
@@ -12231,11 +12282,18 @@ const initFlexDetailsSet = (
|
|
|
12231
12282
|
if (currentAllocatedSpaceMap) {
|
|
12232
12283
|
allocatedSpaceMap = currentAllocatedSpaceMap;
|
|
12233
12284
|
saveCurrentSizeAsRequestedSizes({ replaceExistingAttributes: true });
|
|
12234
|
-
|
|
12235
|
-
|
|
12236
|
-
|
|
12285
|
+
for (const [child, allocatedSpace] of allocatedSpaceMap) {
|
|
12286
|
+
const size = spaceToSize(allocatedSpace, child);
|
|
12287
|
+
if (onRequestedSizeChange) {
|
|
12237
12288
|
onRequestedSizeChange(child, size);
|
|
12238
12289
|
}
|
|
12290
|
+
child.dispatchEvent(
|
|
12291
|
+
new CustomEvent("resizeend", {
|
|
12292
|
+
detail: {
|
|
12293
|
+
size,
|
|
12294
|
+
},
|
|
12295
|
+
}),
|
|
12296
|
+
);
|
|
12239
12297
|
}
|
|
12240
12298
|
onMouseResizeEnd?.();
|
|
12241
12299
|
}
|
|
@@ -12673,4 +12731,4 @@ const useResizeStatus = (elementRef, { as = "number" } = {}) => {
|
|
|
12673
12731
|
};
|
|
12674
12732
|
};
|
|
12675
12733
|
|
|
12676
|
-
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,
|
|
12734
|
+
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.
|
|
3
|
+
"version": "0.9.1",
|
|
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.
|
|
45
|
+
"@preact/signals": "2.8.1",
|
|
46
46
|
"preact": "11.0.0-beta.0"
|
|
47
47
|
},
|
|
48
48
|
"publishConfig": {
|