@trackunit/react-map-adapter-shared 0.0.16 → 0.0.18

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/index.cjs.js CHANGED
@@ -4,6 +4,7 @@ var geoJsonUtils = require('@trackunit/geo-json-utils');
4
4
  var uiDesignTokens = require('@trackunit/ui-design-tokens');
5
5
  var esToolkit = require('es-toolkit');
6
6
  var zod = require('zod');
7
+ var reactMapColorUtils = require('@trackunit/react-map-color-utils');
7
8
 
8
9
  /**
9
10
  * Helper to define an adapter factory with proper type inference.
@@ -556,140 +557,6 @@ const mergeAntimeridianFeatures = (features) => {
556
557
  };
557
558
  };
558
559
 
559
- // TODO (next PR): colorUtils is a generic CSS utility with no adapter-specific knowledge.
560
- // Extract to a standalone utility package so it isn't coupled to the adapter layer.
561
- /**
562
- * Browser-backed color mixing via CSS `color-mix()`.
563
- *
564
- * Uses a hidden DOM element + `getComputedStyle` to resolve expressions,
565
- * cached so each unique expression is computed at most once.
566
- */
567
- const colorCache = new Map();
568
- /**
569
- * Modern browsers return CSS Color Level 4 `color(srgb r g b)` from
570
- * `getComputedStyle`, but Mapbox GL JS only accepts classic formats
571
- * (hex, rgb, rgba, hsl, hsla). Convert to `rgb()`/`rgba()`.
572
- */
573
- const normalizeComputedColor = (color) => {
574
- const m = color.match(/^color\(srgb\s+([\d.e+-]+)\s+([\d.e+-]+)\s+([\d.e+-]+)(?:\s*\/\s*([\d.e+-]+))?\)$/);
575
- if (!m)
576
- return color;
577
- const r = Math.round(parseFloat(m[1] ?? "0") * 255);
578
- const g = Math.round(parseFloat(m[2] ?? "0") * 255);
579
- const b = Math.round(parseFloat(m[3] ?? "0") * 255);
580
- if (m[4] !== undefined) {
581
- return `rgba(${r}, ${g}, ${b}, ${parseFloat(m[4])})`;
582
- }
583
- return `rgb(${r}, ${g}, ${b})`;
584
- };
585
- let probeElement = null;
586
- const getProbeElement = () => {
587
- if (probeElement) {
588
- return probeElement;
589
- }
590
- if (typeof document === "undefined") {
591
- return null;
592
- }
593
- const el = document.createElement("span");
594
- el.style.display = "none";
595
- document.body.appendChild(el);
596
- probeElement = el;
597
- return el;
598
- };
599
- const resolveColorMix = (expression, fallback) => {
600
- const cached = colorCache.get(expression);
601
- if (cached !== undefined) {
602
- return cached;
603
- }
604
- const el = getProbeElement();
605
- if (!el) {
606
- return fallback;
607
- }
608
- el.style.color = "";
609
- el.style.color = expression;
610
- if (!el.style.color) {
611
- return fallback;
612
- }
613
- const computed = getComputedStyle(el).color;
614
- if (!computed) {
615
- return fallback;
616
- }
617
- const normalized = normalizeComputedColor(computed);
618
- colorCache.set(expression, normalized);
619
- return normalized;
620
- };
621
- /**
622
- * Mix two CSS colors using the browser's `color-mix(in srgb)` function.
623
- *
624
- * @param color1 - First color (any valid CSS color string)
625
- * @param color2 - Second color (any valid CSS color string)
626
- * @param percentage - Percentage of `color1` in the mix (0–100)
627
- * @returns Resolved color as an `rgb()` string, or `color1` if resolution fails
628
- */
629
- const mixColor = (color1, color2, percentage) => {
630
- const expression = `color-mix(in srgb, ${color1} ${percentage}%, ${color2})`;
631
- return resolveColorMix(expression, color1);
632
- };
633
- /**
634
- * Darken a CSS color by mixing it with black.
635
- *
636
- * @param color - Any valid CSS color string
637
- * @param amount - Darkening intensity from 0 (no change) to 100 (pure black)
638
- */
639
- const darkenColor = (color, amount) => mixColor(color, "black", 100 - amount);
640
- /**
641
- * Lighten a CSS color by mixing it with white.
642
- *
643
- * @param color - Any valid CSS color string
644
- * @param amount - Lightening intensity from 0 (no change) to 100 (pure white)
645
- */
646
- const lightenColor = (color, amount) => mixColor(color, "white", 100 - amount);
647
- /**
648
- * Resolve a CSS color and apply an opacity multiplier to its alpha channel.
649
- *
650
- * Unlike setting `element.style.opacity`, this only affects the individual
651
- * color value — useful when fill and stroke need independent opacity.
652
- *
653
- * @param color - Any valid CSS color string
654
- * @param opacity - Opacity multiplier from 0 to 1 (multiplied with existing alpha)
655
- * @returns `rgba()` string with the combined alpha, or the original color if resolution fails
656
- */
657
- const colorWithOpacity = (color, opacity) => {
658
- if (opacity >= 1)
659
- return color;
660
- const cacheKey = `${color}@${opacity}`;
661
- const cached = colorCache.get(cacheKey);
662
- if (cached !== undefined)
663
- return cached;
664
- const el = getProbeElement();
665
- if (!el)
666
- return color;
667
- el.style.color = "";
668
- el.style.color = color;
669
- const computed = getComputedStyle(el).color;
670
- if (!computed)
671
- return color;
672
- const normalized = normalizeComputedColor(computed);
673
- const rgbaMatch = normalized.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)$/);
674
- if (!rgbaMatch)
675
- return color;
676
- const existingAlpha = rgbaMatch[4] !== undefined ? parseFloat(rgbaMatch[4]) : 1;
677
- const result = `rgba(${rgbaMatch[1]}, ${rgbaMatch[2]}, ${rgbaMatch[3]}, ${existingAlpha * opacity})`;
678
- colorCache.set(cacheKey, result);
679
- return result;
680
- };
681
- /**
682
- * Clear the resolved-color cache and detach the probe element.
683
- * Exposed for test teardown only — not part of the public API.
684
- */
685
- const resetColorUtilsForTesting = () => {
686
- colorCache.clear();
687
- if (probeElement) {
688
- probeElement.remove();
689
- probeElement = null;
690
- }
691
- };
692
-
693
560
  /**
694
561
  * Web Mercator max latitude in degrees: atan(sinh(π)).
695
562
  * This is where Mercator tiles are cut off to form a square map (EPSG:3857).
@@ -2539,7 +2406,7 @@ const SELECTED_COLOR_SHIFT = 25;
2539
2406
  const resolveHoveredStyle = (base, _shapeType, theme) => {
2540
2407
  const userOverrides = base.hovered;
2541
2408
  const baseStroke = base.stroke ?? "#000000";
2542
- const autoStroke = theme === "dark" ? lightenColor(baseStroke, HOVER_COLOR_SHIFT) : darkenColor(baseStroke, HOVER_COLOR_SHIFT);
2409
+ const autoStroke = theme === "dark" ? reactMapColorUtils.lightenColor(baseStroke, HOVER_COLOR_SHIFT) : reactMapColorUtils.darkenColor(baseStroke, HOVER_COLOR_SHIFT);
2543
2410
  return {
2544
2411
  fill: userOverrides?.fill ?? base.fill,
2545
2412
  fillOpacity: userOverrides?.fillOpacity ?? base.fillOpacity,
@@ -2558,7 +2425,7 @@ const resolveHoveredStyle = (base, _shapeType, theme) => {
2558
2425
  const resolveSelectedStyle = (base, _shapeType, theme) => {
2559
2426
  const userOverrides = base.selected;
2560
2427
  const baseStroke = base.stroke ?? "#000000";
2561
- const autoStroke = theme === "dark" ? lightenColor(baseStroke, SELECTED_COLOR_SHIFT) : darkenColor(baseStroke, SELECTED_COLOR_SHIFT);
2428
+ const autoStroke = theme === "dark" ? reactMapColorUtils.lightenColor(baseStroke, SELECTED_COLOR_SHIFT) : reactMapColorUtils.darkenColor(baseStroke, SELECTED_COLOR_SHIFT);
2562
2429
  return {
2563
2430
  fill: userOverrides?.fill ?? base.fill,
2564
2431
  fillOpacity: userOverrides?.fillOpacity ?? base.fillOpacity,
@@ -2619,14 +2486,12 @@ exports.canPatchAdaptiveViewport = canPatchAdaptiveViewport;
2619
2486
  exports.canPatchMarkerInPlace = canPatchMarkerInPlace;
2620
2487
  exports.clearSafeArea = clearSafeArea;
2621
2488
  exports.collectFeatureIdSet = collectFeatureIdSet;
2622
- exports.colorWithOpacity = colorWithOpacity;
2623
2489
  exports.computeInitialState = computeInitialState;
2624
2490
  exports.computeMarkerDomPortalZIndex = computeMarkerDomPortalZIndex;
2625
2491
  exports.convexHull = convexHull;
2626
2492
  exports.createClusterPinElement = createClusterPinElement;
2627
2493
  exports.createDefaultClusterElement = createDefaultClusterElement;
2628
2494
  exports.createSymbolDotElement = createSymbolDotElement;
2629
- exports.darkenColor = darkenColor;
2630
2495
  exports.defineAdapter = defineAdapter;
2631
2496
  exports.densifyGeodesicFeatures = densifyGeodesicFeatures;
2632
2497
  exports.disableSafeAreaDebug = disableSafeAreaDebug;
@@ -2649,19 +2514,16 @@ exports.intermediatePoint = intermediatePoint;
2649
2514
  exports.isCanvasMarkerMode = isCanvasMarkerMode;
2650
2515
  exports.isEventOfType = isEventOfType;
2651
2516
  exports.isSafeAreaDebugEnabled = isSafeAreaDebugEnabled;
2652
- exports.lightenColor = lightenColor;
2653
2517
  exports.mapAppearanceSchema = mapAppearanceSchema;
2654
2518
  exports.mapStateEquals = mapStateEquals;
2655
2519
  exports.mapThemeSchema = mapThemeSchema;
2656
2520
  exports.mapTypeSchema = mapTypeSchema;
2657
2521
  exports.mercatorCenterFromBounds = mercatorCenterFromBounds;
2658
2522
  exports.mergeAntimeridianFeatures = mergeAntimeridianFeatures;
2659
- exports.mixColor = mixColor;
2660
2523
  exports.patchPortalDescriptors = patchPortalDescriptors;
2661
2524
  exports.pointInPolygon = pointInPolygon;
2662
2525
  exports.removeGoneIndexedMarkers = removeGoneIndexedMarkers;
2663
2526
  exports.renderSafeArea = renderSafeArea;
2664
- exports.resetColorUtilsForTesting = resetColorUtilsForTesting;
2665
2527
  exports.resolveCircleSymbolDefaults = resolveCircleSymbolDefaults;
2666
2528
  exports.resolveHoveredStyle = resolveHoveredStyle;
2667
2529
  exports.resolveSelectedStyle = resolveSelectedStyle;
package/index.esm.js CHANGED
@@ -2,6 +2,7 @@ import { validatePosition, validateBbox, geoJsonBboxSchema } from '@trackunit/ge
2
2
  import { color } from '@trackunit/ui-design-tokens';
3
3
  import { isEqual } from 'es-toolkit';
4
4
  import { z } from 'zod';
5
+ import { lightenColor, darkenColor } from '@trackunit/react-map-color-utils';
5
6
 
6
7
  /**
7
8
  * Helper to define an adapter factory with proper type inference.
@@ -554,140 +555,6 @@ const mergeAntimeridianFeatures = (features) => {
554
555
  };
555
556
  };
556
557
 
557
- // TODO (next PR): colorUtils is a generic CSS utility with no adapter-specific knowledge.
558
- // Extract to a standalone utility package so it isn't coupled to the adapter layer.
559
- /**
560
- * Browser-backed color mixing via CSS `color-mix()`.
561
- *
562
- * Uses a hidden DOM element + `getComputedStyle` to resolve expressions,
563
- * cached so each unique expression is computed at most once.
564
- */
565
- const colorCache = new Map();
566
- /**
567
- * Modern browsers return CSS Color Level 4 `color(srgb r g b)` from
568
- * `getComputedStyle`, but Mapbox GL JS only accepts classic formats
569
- * (hex, rgb, rgba, hsl, hsla). Convert to `rgb()`/`rgba()`.
570
- */
571
- const normalizeComputedColor = (color) => {
572
- const m = color.match(/^color\(srgb\s+([\d.e+-]+)\s+([\d.e+-]+)\s+([\d.e+-]+)(?:\s*\/\s*([\d.e+-]+))?\)$/);
573
- if (!m)
574
- return color;
575
- const r = Math.round(parseFloat(m[1] ?? "0") * 255);
576
- const g = Math.round(parseFloat(m[2] ?? "0") * 255);
577
- const b = Math.round(parseFloat(m[3] ?? "0") * 255);
578
- if (m[4] !== undefined) {
579
- return `rgba(${r}, ${g}, ${b}, ${parseFloat(m[4])})`;
580
- }
581
- return `rgb(${r}, ${g}, ${b})`;
582
- };
583
- let probeElement = null;
584
- const getProbeElement = () => {
585
- if (probeElement) {
586
- return probeElement;
587
- }
588
- if (typeof document === "undefined") {
589
- return null;
590
- }
591
- const el = document.createElement("span");
592
- el.style.display = "none";
593
- document.body.appendChild(el);
594
- probeElement = el;
595
- return el;
596
- };
597
- const resolveColorMix = (expression, fallback) => {
598
- const cached = colorCache.get(expression);
599
- if (cached !== undefined) {
600
- return cached;
601
- }
602
- const el = getProbeElement();
603
- if (!el) {
604
- return fallback;
605
- }
606
- el.style.color = "";
607
- el.style.color = expression;
608
- if (!el.style.color) {
609
- return fallback;
610
- }
611
- const computed = getComputedStyle(el).color;
612
- if (!computed) {
613
- return fallback;
614
- }
615
- const normalized = normalizeComputedColor(computed);
616
- colorCache.set(expression, normalized);
617
- return normalized;
618
- };
619
- /**
620
- * Mix two CSS colors using the browser's `color-mix(in srgb)` function.
621
- *
622
- * @param color1 - First color (any valid CSS color string)
623
- * @param color2 - Second color (any valid CSS color string)
624
- * @param percentage - Percentage of `color1` in the mix (0–100)
625
- * @returns Resolved color as an `rgb()` string, or `color1` if resolution fails
626
- */
627
- const mixColor = (color1, color2, percentage) => {
628
- const expression = `color-mix(in srgb, ${color1} ${percentage}%, ${color2})`;
629
- return resolveColorMix(expression, color1);
630
- };
631
- /**
632
- * Darken a CSS color by mixing it with black.
633
- *
634
- * @param color - Any valid CSS color string
635
- * @param amount - Darkening intensity from 0 (no change) to 100 (pure black)
636
- */
637
- const darkenColor = (color, amount) => mixColor(color, "black", 100 - amount);
638
- /**
639
- * Lighten a CSS color by mixing it with white.
640
- *
641
- * @param color - Any valid CSS color string
642
- * @param amount - Lightening intensity from 0 (no change) to 100 (pure white)
643
- */
644
- const lightenColor = (color, amount) => mixColor(color, "white", 100 - amount);
645
- /**
646
- * Resolve a CSS color and apply an opacity multiplier to its alpha channel.
647
- *
648
- * Unlike setting `element.style.opacity`, this only affects the individual
649
- * color value — useful when fill and stroke need independent opacity.
650
- *
651
- * @param color - Any valid CSS color string
652
- * @param opacity - Opacity multiplier from 0 to 1 (multiplied with existing alpha)
653
- * @returns `rgba()` string with the combined alpha, or the original color if resolution fails
654
- */
655
- const colorWithOpacity = (color, opacity) => {
656
- if (opacity >= 1)
657
- return color;
658
- const cacheKey = `${color}@${opacity}`;
659
- const cached = colorCache.get(cacheKey);
660
- if (cached !== undefined)
661
- return cached;
662
- const el = getProbeElement();
663
- if (!el)
664
- return color;
665
- el.style.color = "";
666
- el.style.color = color;
667
- const computed = getComputedStyle(el).color;
668
- if (!computed)
669
- return color;
670
- const normalized = normalizeComputedColor(computed);
671
- const rgbaMatch = normalized.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)$/);
672
- if (!rgbaMatch)
673
- return color;
674
- const existingAlpha = rgbaMatch[4] !== undefined ? parseFloat(rgbaMatch[4]) : 1;
675
- const result = `rgba(${rgbaMatch[1]}, ${rgbaMatch[2]}, ${rgbaMatch[3]}, ${existingAlpha * opacity})`;
676
- colorCache.set(cacheKey, result);
677
- return result;
678
- };
679
- /**
680
- * Clear the resolved-color cache and detach the probe element.
681
- * Exposed for test teardown only — not part of the public API.
682
- */
683
- const resetColorUtilsForTesting = () => {
684
- colorCache.clear();
685
- if (probeElement) {
686
- probeElement.remove();
687
- probeElement = null;
688
- }
689
- };
690
-
691
558
  /**
692
559
  * Web Mercator max latitude in degrees: atan(sinh(π)).
693
560
  * This is where Mercator tiles are cut off to form a square map (EPSG:3857).
@@ -2582,4 +2449,4 @@ const resolveStrokeColors = (style, shapeType, theme) => {
2582
2449
  };
2583
2450
  };
2584
2451
 
2585
- export { ANCHOR_SELECTOR, CIRCLE_SYMBOL_DEFAULT_DIAMETER_PX, CIRCLE_SYMBOL_DEFAULT_OPACITY, DEFAULT_CENTER, DEFAULT_MAP_APPEARANCE, DEFAULT_ZOOM, GEODESIC_MAX_SEGMENT_KM, HIT_SURFACE_SELECTOR, INITIAL_CAMERA_STATE, INITIAL_INTERACTION_STATE, INITIAL_MAP_STATE, INITIAL_MAP_STATUS, KEYBOARD_PAN_AMOUNT, KEYBOARD_ZOOM_AMOUNT, LAYER_FADE_DURATION_MS, MAP_CURSORS, MAX_ZOOM, MIN_ZOOM, SAFE_AREA_DEFAULT_BUFFER_PX, WORLD_BBOX, allocSafeAreaDebugId, anchorFromBottomCenter, angularDistance, attachSafeAreaHoverListeners, bboxEquals, bufferRectCorners, buildAdaptiveDomEntries, buildAdaptiveDomRenderFn, buildAdaptiveSymbolStyleFn, cameraStateEquals, canPatchAdaptiveMarker, canPatchAdaptiveViewport, canPatchMarkerInPlace, clearSafeArea, collectFeatureIdSet, colorWithOpacity, computeInitialState, computeMarkerDomPortalZIndex, convexHull, createClusterPinElement, createDefaultClusterElement, createSymbolDotElement, darkenColor, defineAdapter, densifyGeodesicFeatures, disableSafeAreaDebug, discriminateRenderResult, enableSafeAreaDebug, estimateZoomFromBounds, extractLineCoordinates, extractPointCoordinates, extractPolygonPaths, extractSourceData, fadeInElement, filterRectsByCursorDirection, geometryTypeToShapeType, getAdaptiveDomFeatureIds, getAnchorRect, getEffectiveRestrictBounds, getHitSurfaceRect, hasSameFeatureIds, intermediatePoint, isCanvasMarkerMode, isEventOfType, isSafeAreaDebugEnabled, lightenColor, mapAppearanceSchema, mapStateEquals, mapThemeSchema, mapTypeSchema, mercatorCenterFromBounds, mergeAntimeridianFeatures, mixColor, patchPortalDescriptors, pointInPolygon, removeGoneIndexedMarkers, renderSafeArea, resetColorUtilsForTesting, resolveCircleSymbolDefaults, resolveHoveredStyle, resolveSelectedStyle, resolveStrokeColors, resolveSymbolDescriptor, safePolygon, toDeg, toRad, validateInitialViewport, watchSafeAreaLeave };
2452
+ export { ANCHOR_SELECTOR, CIRCLE_SYMBOL_DEFAULT_DIAMETER_PX, CIRCLE_SYMBOL_DEFAULT_OPACITY, DEFAULT_CENTER, DEFAULT_MAP_APPEARANCE, DEFAULT_ZOOM, GEODESIC_MAX_SEGMENT_KM, HIT_SURFACE_SELECTOR, INITIAL_CAMERA_STATE, INITIAL_INTERACTION_STATE, INITIAL_MAP_STATE, INITIAL_MAP_STATUS, KEYBOARD_PAN_AMOUNT, KEYBOARD_ZOOM_AMOUNT, LAYER_FADE_DURATION_MS, MAP_CURSORS, MAX_ZOOM, MIN_ZOOM, SAFE_AREA_DEFAULT_BUFFER_PX, WORLD_BBOX, allocSafeAreaDebugId, anchorFromBottomCenter, angularDistance, attachSafeAreaHoverListeners, bboxEquals, bufferRectCorners, buildAdaptiveDomEntries, buildAdaptiveDomRenderFn, buildAdaptiveSymbolStyleFn, cameraStateEquals, canPatchAdaptiveMarker, canPatchAdaptiveViewport, canPatchMarkerInPlace, clearSafeArea, collectFeatureIdSet, computeInitialState, computeMarkerDomPortalZIndex, convexHull, createClusterPinElement, createDefaultClusterElement, createSymbolDotElement, defineAdapter, densifyGeodesicFeatures, disableSafeAreaDebug, discriminateRenderResult, enableSafeAreaDebug, estimateZoomFromBounds, extractLineCoordinates, extractPointCoordinates, extractPolygonPaths, extractSourceData, fadeInElement, filterRectsByCursorDirection, geometryTypeToShapeType, getAdaptiveDomFeatureIds, getAnchorRect, getEffectiveRestrictBounds, getHitSurfaceRect, hasSameFeatureIds, intermediatePoint, isCanvasMarkerMode, isEventOfType, isSafeAreaDebugEnabled, mapAppearanceSchema, mapStateEquals, mapThemeSchema, mapTypeSchema, mercatorCenterFromBounds, mergeAntimeridianFeatures, patchPortalDescriptors, pointInPolygon, removeGoneIndexedMarkers, renderSafeArea, resolveCircleSymbolDefaults, resolveHoveredStyle, resolveSelectedStyle, resolveStrokeColors, resolveSymbolDescriptor, safePolygon, toDeg, toRad, validateInitialViewport, watchSafeAreaLeave };
package/package.json CHANGED
@@ -1,14 +1,15 @@
1
1
  {
2
2
  "name": "@trackunit/react-map-adapter-shared",
3
- "version": "0.0.16",
3
+ "version": "0.0.18",
4
4
  "repository": "https://github.com/Trackunit/manager",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "engines": {
7
7
  "node": ">=24.x"
8
8
  },
9
9
  "dependencies": {
10
- "@trackunit/geo-json-utils": "1.14.35",
11
- "@trackunit/ui-design-tokens": "1.13.32",
10
+ "@trackunit/react-map-color-utils": "0.0.3",
11
+ "@trackunit/geo-json-utils": "1.14.37",
12
+ "@trackunit/ui-design-tokens": "1.13.34",
12
13
  "es-toolkit": "^1.39.10",
13
14
  "zod": "^3.25.76"
14
15
  },
package/src/index.d.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  export * from "./adapterContract";
2
2
  export * from "./antimeridianMerge";
3
- export * from "./colorUtils";
4
3
  export * from "./constants";
5
4
  export * from "./geodesicDensify";
6
5
  export * from "./initialViewportValidation";
@@ -1,39 +0,0 @@
1
- /**
2
- * Mix two CSS colors using the browser's `color-mix(in srgb)` function.
3
- *
4
- * @param color1 - First color (any valid CSS color string)
5
- * @param color2 - Second color (any valid CSS color string)
6
- * @param percentage - Percentage of `color1` in the mix (0–100)
7
- * @returns Resolved color as an `rgb()` string, or `color1` if resolution fails
8
- */
9
- export declare const mixColor: (color1: string, color2: string, percentage: number) => string;
10
- /**
11
- * Darken a CSS color by mixing it with black.
12
- *
13
- * @param color - Any valid CSS color string
14
- * @param amount - Darkening intensity from 0 (no change) to 100 (pure black)
15
- */
16
- export declare const darkenColor: (color: string, amount: number) => string;
17
- /**
18
- * Lighten a CSS color by mixing it with white.
19
- *
20
- * @param color - Any valid CSS color string
21
- * @param amount - Lightening intensity from 0 (no change) to 100 (pure white)
22
- */
23
- export declare const lightenColor: (color: string, amount: number) => string;
24
- /**
25
- * Resolve a CSS color and apply an opacity multiplier to its alpha channel.
26
- *
27
- * Unlike setting `element.style.opacity`, this only affects the individual
28
- * color value — useful when fill and stroke need independent opacity.
29
- *
30
- * @param color - Any valid CSS color string
31
- * @param opacity - Opacity multiplier from 0 to 1 (multiplied with existing alpha)
32
- * @returns `rgba()` string with the combined alpha, or the original color if resolution fails
33
- */
34
- export declare const colorWithOpacity: (color: string, opacity: number) => string;
35
- /**
36
- * Clear the resolved-color cache and detach the probe element.
37
- * Exposed for test teardown only — not part of the public API.
38
- */
39
- export declare const resetColorUtilsForTesting: () => void;