@jsenv/dom 0.6.1 → 0.7.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.
Files changed (109) hide show
  1. package/dist/jsenv_dom.js +259 -314
  2. package/package.json +2 -4
  3. package/index.js +0 -124
  4. package/src/attr/add_attribute_effect.js +0 -93
  5. package/src/attr/attributes.js +0 -32
  6. package/src/color/color_constrast.js +0 -69
  7. package/src/color/color_parsing.js +0 -319
  8. package/src/color/color_scheme.js +0 -28
  9. package/src/color/pick_light_or_dark.js +0 -34
  10. package/src/color/resolve_css_color.js +0 -60
  11. package/src/demos/3_columns_resize_demo.html +0 -84
  12. package/src/demos/3_rows_resize_demo.html +0 -89
  13. package/src/demos/aside_and_main_demo.html +0 -93
  14. package/src/demos/coordinates_demo.html +0 -450
  15. package/src/demos/document_autoscroll_demo.html +0 -517
  16. package/src/demos/drag_gesture_constraints_demo.html +0 -701
  17. package/src/demos/drag_gesture_demo.html +0 -1047
  18. package/src/demos/drag_gesture_element_to_impact_demo.html +0 -445
  19. package/src/demos/drag_reference_element_demo.html +0 -480
  20. package/src/demos/flex_details_set_demo.html +0 -302
  21. package/src/demos/flex_details_set_demo_2.html +0 -315
  22. package/src/demos/visible_rect_demo.html +0 -525
  23. package/src/element_signature.js +0 -100
  24. package/src/interaction/drag/constraint_feedback_line.js +0 -92
  25. package/src/interaction/drag/drag_constraint.js +0 -659
  26. package/src/interaction/drag/drag_debug_markers.js +0 -635
  27. package/src/interaction/drag/drag_element_positioner.js +0 -382
  28. package/src/interaction/drag/drag_gesture.js +0 -566
  29. package/src/interaction/drag/drag_resize_demo.html +0 -571
  30. package/src/interaction/drag/drag_to_move.js +0 -301
  31. package/src/interaction/drag/drag_to_resize_gesture.js +0 -68
  32. package/src/interaction/drag/drop_target_detection.js +0 -148
  33. package/src/interaction/drag/sticky_frontiers.js +0 -160
  34. package/src/interaction/event_marker.js +0 -14
  35. package/src/interaction/focus/active_element.js +0 -33
  36. package/src/interaction/focus/arrow_navigation.js +0 -599
  37. package/src/interaction/focus/element_is_focusable.js +0 -57
  38. package/src/interaction/focus/element_visibility.js +0 -111
  39. package/src/interaction/focus/find_focusable.js +0 -21
  40. package/src/interaction/focus/focus_group.js +0 -91
  41. package/src/interaction/focus/focus_group_registry.js +0 -12
  42. package/src/interaction/focus/focus_nav.js +0 -12
  43. package/src/interaction/focus/focus_nav_event_marker.js +0 -14
  44. package/src/interaction/focus/focus_trap.js +0 -105
  45. package/src/interaction/focus/tab_navigation.js +0 -128
  46. package/src/interaction/focus/tests/focus_group_skip_tab_test.html +0 -206
  47. package/src/interaction/focus/tests/tree_focus_test.html +0 -304
  48. package/src/interaction/focus/tests/tree_focus_test.jsx +0 -261
  49. package/src/interaction/focus/tests/tree_focus_test_preact.html +0 -13
  50. package/src/interaction/isolate_interactions.js +0 -161
  51. package/src/interaction/keyboard.js +0 -26
  52. package/src/interaction/scroll/capture_scroll.js +0 -47
  53. package/src/interaction/scroll/is_scrollable.js +0 -159
  54. package/src/interaction/scroll/scroll_container.js +0 -110
  55. package/src/interaction/scroll/scroll_trap.js +0 -44
  56. package/src/interaction/scroll/scrollbar_size.js +0 -20
  57. package/src/interaction/scroll/wheel_through.js +0 -138
  58. package/src/iterable_weak_set.js +0 -66
  59. package/src/position/dom_coords.js +0 -340
  60. package/src/position/offset_parent.js +0 -15
  61. package/src/position/position_fixed.js +0 -15
  62. package/src/position/position_sticky.js +0 -213
  63. package/src/position/sticky_rect.js +0 -79
  64. package/src/position/visible_rect.js +0 -486
  65. package/src/pub_sub.js +0 -31
  66. package/src/size/can_take_size.js +0 -11
  67. package/src/size/details_content_full_height.js +0 -63
  68. package/src/size/flex_details_set.js +0 -974
  69. package/src/size/get_available_height.js +0 -22
  70. package/src/size/get_available_width.js +0 -22
  71. package/src/size/get_border_sizes.js +0 -14
  72. package/src/size/get_height.js +0 -4
  73. package/src/size/get_inner_height.js +0 -15
  74. package/src/size/get_inner_width.js +0 -15
  75. package/src/size/get_margin_sizes.js +0 -10
  76. package/src/size/get_max_height.js +0 -57
  77. package/src/size/get_max_width.js +0 -47
  78. package/src/size/get_min_height.js +0 -14
  79. package/src/size/get_min_width.js +0 -14
  80. package/src/size/get_padding_sizes.js +0 -10
  81. package/src/size/get_width.js +0 -4
  82. package/src/size/hooks/use_available_height.js +0 -27
  83. package/src/size/hooks/use_available_width.js +0 -27
  84. package/src/size/hooks/use_max_height.js +0 -10
  85. package/src/size/hooks/use_max_width.js +0 -10
  86. package/src/size/hooks/use_resize_status.js +0 -62
  87. package/src/size/resize.js +0 -695
  88. package/src/size/resolve_css_size.js +0 -32
  89. package/src/style/dom_styles.js +0 -97
  90. package/src/style/style_composition.js +0 -121
  91. package/src/style/style_controller.js +0 -345
  92. package/src/style/style_default.js +0 -153
  93. package/src/style/style_default_demo.html +0 -128
  94. package/src/style/style_parsing.js +0 -375
  95. package/src/transition/demos/animation_resumption_test.xhtml +0 -500
  96. package/src/transition/demos/height_toggle_test.xhtml +0 -515
  97. package/src/transition/dom_transition.js +0 -254
  98. package/src/transition/easing.js +0 -48
  99. package/src/transition/group_transition.js +0 -261
  100. package/src/transition/transform_style_parser.js +0 -32
  101. package/src/transition/transition_playback.js +0 -366
  102. package/src/transition/transition_timeline.js +0 -79
  103. package/src/traversal.js +0 -247
  104. package/src/ui_transition/demos/content_states_transition_demo.html +0 -628
  105. package/src/ui_transition/demos/smooth_height_transition_demo.html +0 -149
  106. package/src/ui_transition/demos/transition_testing.html +0 -354
  107. package/src/ui_transition/ui_transition.js +0 -1470
  108. package/src/utils.js +0 -69
  109. package/src/value_effect.js +0 -35
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/dom",
3
- "version": "0.6.1",
3
+ "version": "0.7.0",
4
4
  "description": "DOM utilities for writing frontend code",
5
5
  "repository": {
6
6
  "type": "git",
@@ -26,9 +26,7 @@
26
26
  "./resize": "./src/size/resize.js"
27
27
  },
28
28
  "files": [
29
- "/dist/",
30
- "/src/",
31
- "/index.js"
29
+ "/dist/"
32
30
  ],
33
31
  "scripts": {
34
32
  "build": "node ./scripts/build.mjs",
package/index.js DELETED
@@ -1,124 +0,0 @@
1
- export { getElementSignature } from "./src/element_signature.js";
2
-
3
- // state management
4
- export { createIterableWeakSet } from "./src/iterable_weak_set.js";
5
- export { createPubSub } from "./src/pub_sub.js";
6
- export { createValueEffect } from "./src/value_effect.js";
7
-
8
- // style
9
- export { addWillChange, getStyle, setStyles } from "./src/style/dom_styles.js";
10
- export { appendStyles, mergeStyles } from "./src/style/style_composition.js";
11
- export { createStyleController } from "./src/style/style_controller.js";
12
- export { getDefaultStyles } from "./src/style/style_default.js";
13
- export { normalizeStyles } from "./src/style/style_parsing.js";
14
-
15
- // attributes
16
- export { addAttributeEffect } from "./src/attr/add_attribute_effect.js";
17
- export { setAttribute, setAttributes } from "./src/attr/attributes.js";
18
-
19
- // colors
20
- export { getContrastRatio } from "./src/color/color_constrast.js";
21
- export { parseCSSColor, stringifyCSSColor } from "./src/color/color_parsing.js";
22
- export {
23
- getPreferedColorScheme,
24
- prefersDarkColors,
25
- prefersLightColors,
26
- } from "./src/color/color_scheme.js";
27
- export { pickLightOrDark } from "./src/color/pick_light_or_dark.js";
28
- export { resolveCSSColor } from "./src/color/resolve_css_color.js";
29
-
30
- // traversal
31
- export {
32
- findAfter,
33
- findAncestor,
34
- findBefore,
35
- findDescendant,
36
- } from "./src/traversal.js";
37
-
38
- // interaction/focus
39
- export {
40
- activeElementSignal,
41
- addActiveElementEffect,
42
- useActiveElement,
43
- } from "./src/interaction/focus/active_element.js";
44
- export { elementIsFocusable } from "./src/interaction/focus/element_is_focusable.js";
45
- export {
46
- elementIsVisibleForFocus,
47
- elementIsVisuallyVisible,
48
- getFirstVisuallyVisibleAncestor,
49
- getFocusVisibilityInfo,
50
- getVisuallyVisibleInfo,
51
- } from "./src/interaction/focus/element_visibility.js";
52
- export { findFocusable } from "./src/interaction/focus/find_focusable.js";
53
- export { initFocusGroup } from "./src/interaction/focus/focus_group.js";
54
- export { preventFocusNavViaKeyboard } from "./src/interaction/focus/focus_nav.js";
55
- export { preventFocusNav } from "./src/interaction/focus/focus_nav_event_marker.js";
56
- export { trapFocusInside } from "./src/interaction/focus/focus_trap.js";
57
- // interaction/keyboard
58
- export { canInterceptKeys } from "./src/interaction/keyboard.js";
59
- // interaction/scroll
60
- export { captureScrollState } from "./src/interaction/scroll/capture_scroll.js";
61
- export { isScrollable } from "./src/interaction/scroll/is_scrollable.js";
62
- export {
63
- getScrollContainer,
64
- getScrollContainerSet,
65
- getSelfAndAncestorScrolls,
66
- } from "./src/interaction/scroll/scroll_container.js";
67
- export { trapScrollInside } from "./src/interaction/scroll/scroll_trap.js";
68
- export { allowWheelThrough } from "./src/interaction/scroll/wheel_through.js";
69
- // interaction/drag
70
- export { getDragCoordinates } from "./src/interaction/drag/drag_element_positioner.js";
71
- export {
72
- createDragGestureController,
73
- dragAfterThreshold,
74
- } from "./src/interaction/drag/drag_gesture.js";
75
- export { createDragToMoveGestureController } from "./src/interaction/drag/drag_to_move.js";
76
- export { startDragToResizeGesture } from "./src/interaction/drag/drag_to_resize_gesture.js";
77
- export { getDropTargetInfo } from "./src/interaction/drag/drop_target_detection.js";
78
-
79
- // position
80
- export { getScrollRelativeRect } from "./src/position/dom_coords.js";
81
- export { getPositionedParent } from "./src/position/offset_parent.js";
82
- export { initPositionSticky } from "./src/position/position_sticky.js";
83
- export { stickyAsRelativeCoords } from "./src/position/sticky_rect.js";
84
- export {
85
- pickPositionRelativeTo,
86
- visibleRectEffect,
87
- } from "./src/position/visible_rect.js";
88
-
89
- // size
90
- export { initFlexDetailsSet } from "./src/size/flex_details_set.js";
91
- export { getAvailableHeight } from "./src/size/get_available_height.js";
92
- export { getAvailableWidth } from "./src/size/get_available_width.js";
93
- export { getBorderSizes } from "./src/size/get_border_sizes.js";
94
- export { getHeight } from "./src/size/get_height.js";
95
- export { getInnerHeight } from "./src/size/get_inner_height.js";
96
- export { getInnerWidth } from "./src/size/get_inner_width.js";
97
- export { getMarginSizes } from "./src/size/get_margin_sizes.js";
98
- export { getMaxHeight } from "./src/size/get_max_height.js";
99
- export { getMaxWidth } from "./src/size/get_max_width.js";
100
- export { getMinHeight } from "./src/size/get_min_height.js";
101
- export { getMinWidth } from "./src/size/get_min_width.js";
102
- export { getPaddingSizes } from "./src/size/get_padding_sizes.js";
103
- export { getWidth } from "./src/size/get_width.js";
104
- export { resolveCSSSize } from "./src/size/resolve_css_size.js";
105
- // size hooks
106
- export { useAvailableHeight } from "./src/size/hooks/use_available_height.js";
107
- export { useAvailableWidth } from "./src/size/hooks/use_available_width.js";
108
- export { useMaxHeight } from "./src/size/hooks/use_max_height.js";
109
- export { useMaxWidth } from "./src/size/hooks/use_max_width.js";
110
- export { useResizeStatus } from "./src/size/hooks/use_resize_status.js";
111
-
112
- // transition
113
- export {
114
- createHeightTransition,
115
- createOpacityTransition,
116
- createTranslateXTransition,
117
- createWidthTransition,
118
- } from "./src/transition/dom_transition.js";
119
- export { EASING, cubicBezier } from "./src/transition/easing.js";
120
- export {
121
- createTimelineTransition,
122
- createTransition,
123
- } from "./src/transition/transition_playback.js";
124
- export { initUITransition } from "./src/ui_transition/ui_transition.js";
@@ -1,93 +0,0 @@
1
- export const addAttributeEffect = (attributeName, effect) => {
2
- const cleanupWeakMap = new WeakMap();
3
- const applyEffect = (element) => {
4
- const cleanup = effect(element);
5
- cleanupWeakMap.set(
6
- element,
7
- typeof cleanup === "function" ? cleanup : () => {},
8
- );
9
- };
10
-
11
- const cleanupEffect = (element) => {
12
- const cleanup = cleanupWeakMap.get(element);
13
- if (cleanup) {
14
- cleanup();
15
- cleanupWeakMap.delete(element);
16
- }
17
- };
18
-
19
- const checkElement = (element) => {
20
- if (element.hasAttribute(attributeName)) {
21
- applyEffect(element);
22
- }
23
- const elementWithAttributeCollection = element.querySelectorAll(
24
- `[${attributeName}]`,
25
- );
26
- for (const elementWithAttribute of elementWithAttributeCollection) {
27
- applyEffect(elementWithAttribute);
28
- }
29
- };
30
-
31
- checkElement(document.body);
32
- const mutationObserver = new MutationObserver((mutations) => {
33
- for (const mutation of mutations) {
34
- if (mutation.type === "childList") {
35
- for (const addedNode of mutation.addedNodes) {
36
- if (addedNode.nodeType !== Node.ELEMENT_NODE) {
37
- continue;
38
- }
39
- checkElement(addedNode);
40
- }
41
-
42
- for (const removedNode of mutation.removedNodes) {
43
- if (removedNode.nodeType !== Node.ELEMENT_NODE) {
44
- continue;
45
- }
46
-
47
- // Clean up the removed node itself if it had the attribute
48
- if (
49
- removedNode.hasAttribute &&
50
- removedNode.hasAttribute(attributeName)
51
- ) {
52
- cleanupEffect(removedNode);
53
- }
54
-
55
- // Clean up any children of the removed node that had the attribute
56
- if (removedNode.querySelectorAll) {
57
- const elementsWithAttribute = removedNode.querySelectorAll(
58
- `[${attributeName}]`,
59
- );
60
- for (const element of elementsWithAttribute) {
61
- cleanupEffect(element);
62
- }
63
- }
64
- }
65
- }
66
- if (
67
- mutation.type === "attributes" &&
68
- mutation.attributeName === attributeName
69
- ) {
70
- const element = mutation.target;
71
- if (element.hasAttribute(attributeName)) {
72
- applyEffect(element);
73
- } else {
74
- cleanupEffect(element);
75
- }
76
- }
77
- }
78
- });
79
- mutationObserver.observe(document.body, {
80
- childList: true,
81
- subtree: true,
82
- attributes: true,
83
- attributeFilter: [attributeName],
84
- });
85
-
86
- return () => {
87
- mutationObserver.disconnect();
88
- for (const cleanup of cleanupWeakMap.values()) {
89
- cleanup();
90
- }
91
- cleanupWeakMap.clear();
92
- };
93
- };
@@ -1,32 +0,0 @@
1
- export const setAttribute = (element, name, value) => {
2
- if (element.hasAttribute(name)) {
3
- const prevValue = element.getAttribute(name);
4
- element.setAttribute(name, value);
5
- return () => {
6
- element.setAttribute(name, prevValue);
7
- };
8
- }
9
- element.setAttribute(name, value);
10
- return () => {
11
- element.removeAttribute(name);
12
- };
13
- };
14
-
15
- const createSetMany = (setter) => {
16
- return (element, description) => {
17
- const cleanupCallbackSet = new Set();
18
- for (const name of Object.keys(description)) {
19
- const value = description[name];
20
- const restoreStyle = setter(element, name, value);
21
- cleanupCallbackSet.add(restoreStyle);
22
- }
23
- return () => {
24
- for (const cleanupCallback of cleanupCallbackSet) {
25
- cleanupCallback();
26
- }
27
- cleanupCallbackSet.clear();
28
- };
29
- };
30
- };
31
-
32
- export const setAttributes = createSetMany(setAttribute);
@@ -1,69 +0,0 @@
1
- /**
2
- * Calculates the contrast ratio between two RGBA colors
3
- * Based on WCAG 2.1 specification
4
- * @param {Array<number>} rgba1 - [r, g, b, a] values for first color
5
- * @param {Array<number>} rgba2 - [r, g, b, a] values for second color
6
- * @param {Array<number>} [background=[255, 255, 255, 1]] - Background color to composite against when colors have transparency
7
- * @returns {number} Contrast ratio (1-21)
8
- */
9
- export const getContrastRatio = (
10
- rgba1,
11
- rgba2,
12
- background = [255, 255, 255, 1],
13
- ) => {
14
- // When colors have transparency (alpha < 1), we need to composite them
15
- // against a background to get their effective appearance
16
- const composited1 = compositeColor(rgba1, background);
17
- const composited2 = compositeColor(rgba2, background);
18
-
19
- const lum1 = getLuminance(composited1[0], composited1[1], composited1[2]);
20
- const lum2 = getLuminance(composited2[0], composited2[1], composited2[2]);
21
- const brightest = Math.max(lum1, lum2);
22
- const darkest = Math.min(lum1, lum2);
23
- return (brightest + 0.05) / (darkest + 0.05);
24
- };
25
-
26
- /**
27
- * Composites a color with alpha over a background color
28
- * @param {Array<number>} foreground - [r, g, b, a] foreground color
29
- * @param {Array<number>} background - [r, g, b, a] background color
30
- * @returns {Array<number>} [r, g, b] composited color (alpha is flattened)
31
- */
32
- const compositeColor = (foreground, background) => {
33
- const [fr, fg, fb, fa] = foreground;
34
- const [br, bg, bb, ba] = background;
35
-
36
- // No transparency: return the foreground color as-is
37
- if (fa === 1) {
38
- return [fr, fg, fb];
39
- }
40
-
41
- // Alpha compositing formula: C = αA * CA + αB * (1 - αA) * CB
42
- const alpha = fa + ba * (1 - fa);
43
-
44
- if (alpha === 0) {
45
- return [0, 0, 0];
46
- }
47
-
48
- const r = (fa * fr + ba * (1 - fa) * br) / alpha;
49
- const g = (fa * fg + ba * (1 - fa) * bg) / alpha;
50
- const b = (fa * fb + ba * (1 - fa) * bb) / alpha;
51
-
52
- return [Math.round(r), Math.round(g), Math.round(b)];
53
- };
54
-
55
- /**
56
- * Calculates the relative luminance of an RGB color
57
- * Based on WCAG 2.1 specification
58
- * @param {number} r - Red component (0-255)
59
- * @param {number} g - Green component (0-255)
60
- * @param {number} b - Blue component (0-255)
61
- * @returns {number} Relative luminance (0-1)
62
- */
63
- const getLuminance = (r, g, b) => {
64
- const [rs, gs, bs] = [r, g, b].map((c) => {
65
- c = c / 255;
66
- return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
67
- });
68
- return 0.2126 * rs + 0.7152 * gs + 0.0722 * bs;
69
- };
@@ -1,319 +0,0 @@
1
- /**
2
- * Parses a CSS color string into RGBA values
3
- * Supports hex (#rgb, #rrggbb, #rrggbbaa), rgb(), rgba(), hsl(), hsla()
4
- * @param {string} color - CSS color string
5
- * @returns {Array<number>|null} [r, g, b, a] values or null if parsing fails
6
- */
7
- export const parseCSSColor = (color) => {
8
- if (!color || typeof color !== "string") {
9
- return null;
10
- }
11
-
12
- color = color.trim().toLowerCase();
13
-
14
- // Hex colors
15
- if (color.startsWith("#")) {
16
- const hex = color.slice(1);
17
- if (hex.length === 3) {
18
- // #rgb -> #rrggbb
19
- const r = parseInt(hex[0] + hex[0], 16);
20
- const g = parseInt(hex[1] + hex[1], 16);
21
- const b = parseInt(hex[2] + hex[2], 16);
22
- return [r, g, b, 1];
23
- }
24
- if (hex.length === 6) {
25
- // #rrggbb
26
- const r = parseInt(hex.slice(0, 2), 16);
27
- const g = parseInt(hex.slice(2, 4), 16);
28
- const b = parseInt(hex.slice(4, 6), 16);
29
- return [r, g, b, 1];
30
- }
31
- if (hex.length === 8) {
32
- // #rrggbbaa
33
- const r = parseInt(hex.slice(0, 2), 16);
34
- const g = parseInt(hex.slice(2, 4), 16);
35
- const b = parseInt(hex.slice(4, 6), 16);
36
- const a = parseInt(hex.slice(6, 8), 16) / 255;
37
- return [r, g, b, a];
38
- }
39
- }
40
-
41
- // RGB/RGBA colors
42
- const rgbMatch = color.match(/rgba?\(([^)]+)\)/);
43
- if (rgbMatch) {
44
- const values = rgbMatch[1].split(",").map((v) => parseFloat(v.trim()));
45
- if (values.length >= 3) {
46
- const r = values[0];
47
- const g = values[1];
48
- const b = values[2];
49
- const a = values.length >= 4 ? values[3] : 1;
50
- return [r, g, b, a];
51
- }
52
- }
53
-
54
- // HSL/HSLA colors - convert to RGB
55
- const hslMatch = color.match(/hsla?\(([^)]+)\)/);
56
- if (hslMatch) {
57
- const values = hslMatch[1].split(",").map((v) => parseFloat(v.trim()));
58
- if (values.length >= 3) {
59
- const [h, s, l] = values;
60
- const a = values.length >= 4 ? values[3] : 1;
61
- const [r, g, b] = hslToRgb(h, s / 100, l / 100);
62
- return [r, g, b, a];
63
- }
64
- }
65
-
66
- // Named colors (basic set)
67
- if (namedColors[color]) {
68
- return [...namedColors[color], 1];
69
- }
70
- return null;
71
- };
72
-
73
- /**
74
- * Converts RGBA values back to a CSS color string
75
- * Prefers named colors when possible, then rgb() for opaque colors, rgba() for transparent
76
- * @param {Array<number>} rgba - [r, g, b, a] values
77
- * @returns {string|null} CSS color string or null if invalid input
78
- */
79
- export const stringifyCSSColor = (rgba) => {
80
- if (!Array.isArray(rgba) || rgba.length < 3) {
81
- return null;
82
- }
83
-
84
- const [r, g, b, a = 1] = rgba;
85
-
86
- // Validate RGB values
87
- if (r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255) {
88
- return null;
89
- }
90
-
91
- // Validate alpha value
92
- if (a < 0 || a > 1) {
93
- return null;
94
- }
95
-
96
- // Round RGB values to integers
97
- const rInt = Math.round(r);
98
- const gInt = Math.round(g);
99
- const bInt = Math.round(b);
100
-
101
- // Check for named colors (only for fully opaque colors)
102
- if (a === 1) {
103
- for (const [name, [nameR, nameG, nameB]] of Object.entries(namedColors)) {
104
- if (rInt === nameR && gInt === nameG && bInt === nameB) {
105
- return name;
106
- }
107
- }
108
- }
109
-
110
- // Use rgb() for opaque colors, rgba() for transparent
111
- if (a === 1) {
112
- return `rgb(${rInt}, ${gInt}, ${bInt})`;
113
- }
114
- return `rgba(${rInt}, ${gInt}, ${bInt}, ${a})`;
115
- };
116
-
117
- const namedColors = {
118
- // Basic colors
119
- black: [0, 0, 0],
120
- white: [255, 255, 255],
121
- red: [255, 0, 0],
122
- green: [0, 128, 0],
123
- blue: [0, 0, 255],
124
- yellow: [255, 255, 0],
125
- cyan: [0, 255, 255],
126
- magenta: [255, 0, 255],
127
-
128
- // Gray variations
129
- silver: [192, 192, 192],
130
- gray: [128, 128, 128],
131
- grey: [128, 128, 128],
132
- darkgray: [169, 169, 169],
133
- darkgrey: [169, 169, 169],
134
- lightgray: [211, 211, 211],
135
- lightgrey: [211, 211, 211],
136
- dimgray: [105, 105, 105],
137
- dimgrey: [105, 105, 105],
138
- gainsboro: [220, 220, 220],
139
- whitesmoke: [245, 245, 245],
140
-
141
- // Extended basic colors
142
- maroon: [128, 0, 0],
143
- olive: [128, 128, 0],
144
- lime: [0, 255, 0],
145
- aqua: [0, 255, 255],
146
- teal: [0, 128, 128],
147
- navy: [0, 0, 128],
148
- fuchsia: [255, 0, 255],
149
- purple: [128, 0, 128],
150
-
151
- // Red variations
152
- darkred: [139, 0, 0],
153
- firebrick: [178, 34, 34],
154
- crimson: [220, 20, 60],
155
- indianred: [205, 92, 92],
156
- lightcoral: [240, 128, 128],
157
- salmon: [250, 128, 114],
158
- darksalmon: [233, 150, 122],
159
- lightsalmon: [255, 160, 122],
160
-
161
- // Pink variations
162
- pink: [255, 192, 203],
163
- lightpink: [255, 182, 193],
164
- hotpink: [255, 105, 180],
165
- deeppink: [255, 20, 147],
166
- mediumvioletred: [199, 21, 133],
167
- palevioletred: [219, 112, 147],
168
-
169
- // Orange variations
170
- orange: [255, 165, 0],
171
- darkorange: [255, 140, 0],
172
- orangered: [255, 69, 0],
173
- tomato: [255, 99, 71],
174
- coral: [255, 127, 80],
175
-
176
- // Yellow variations
177
- gold: [255, 215, 0],
178
- lightyellow: [255, 255, 224],
179
- lemonchiffon: [255, 250, 205],
180
- lightgoldenrodyellow: [250, 250, 210],
181
- papayawhip: [255, 239, 213],
182
- moccasin: [255, 228, 181],
183
- peachpuff: [255, 218, 185],
184
- palegoldenrod: [238, 232, 170],
185
- khaki: [240, 230, 140],
186
- darkkhaki: [189, 183, 107],
187
-
188
- // Green variations
189
- darkgreen: [0, 100, 0],
190
- forestgreen: [34, 139, 34],
191
- seagreen: [46, 139, 87],
192
- mediumseagreen: [60, 179, 113],
193
- springgreen: [0, 255, 127],
194
- mediumspringgreen: [0, 250, 154],
195
- lawngreen: [124, 252, 0],
196
- chartreuse: [127, 255, 0],
197
- greenyellow: [173, 255, 47],
198
- limegreen: [50, 205, 50],
199
- palegreen: [152, 251, 152],
200
- lightgreen: [144, 238, 144],
201
- mediumaquamarine: [102, 205, 170],
202
- aquamarine: [127, 255, 212],
203
- darkolivegreen: [85, 107, 47],
204
- olivedrab: [107, 142, 35],
205
- yellowgreen: [154, 205, 50],
206
-
207
- // Blue variations
208
- darkblue: [0, 0, 139],
209
- mediumblue: [0, 0, 205],
210
- royalblue: [65, 105, 225],
211
- steelblue: [70, 130, 180],
212
- dodgerblue: [30, 144, 255],
213
- deepskyblue: [0, 191, 255],
214
- skyblue: [135, 206, 235],
215
- lightskyblue: [135, 206, 250],
216
- lightblue: [173, 216, 230],
217
- powderblue: [176, 224, 230],
218
- lightcyan: [224, 255, 255],
219
- paleturquoise: [175, 238, 238],
220
- darkturquoise: [0, 206, 209],
221
- mediumturquoise: [72, 209, 204],
222
- turquoise: [64, 224, 208],
223
- cadetblue: [95, 158, 160],
224
- darkcyan: [0, 139, 139],
225
- lightseagreen: [32, 178, 170],
226
-
227
- // Purple variations
228
- indigo: [75, 0, 130],
229
- darkviolet: [148, 0, 211],
230
- blueviolet: [138, 43, 226],
231
- mediumpurple: [147, 112, 219],
232
- mediumslateblue: [123, 104, 238],
233
- slateblue: [106, 90, 205],
234
- darkslateblue: [72, 61, 139],
235
- lavender: [230, 230, 250],
236
- thistle: [216, 191, 216],
237
- plum: [221, 160, 221],
238
- violet: [238, 130, 238],
239
- orchid: [218, 112, 214],
240
- mediumorchid: [186, 85, 211],
241
- darkorchid: [153, 50, 204],
242
- darkmagenta: [139, 0, 139],
243
-
244
- // Brown variations
245
- brown: [165, 42, 42],
246
- saddlebrown: [139, 69, 19],
247
- sienna: [160, 82, 45],
248
- chocolate: [210, 105, 30],
249
- darkgoldenrod: [184, 134, 11],
250
- peru: [205, 133, 63],
251
- rosybrown: [188, 143, 143],
252
- goldenrod: [218, 165, 32],
253
- sandybrown: [244, 164, 96],
254
- tan: [210, 180, 140],
255
- burlywood: [222, 184, 135],
256
- wheat: [245, 222, 179],
257
- navajowhite: [255, 222, 173],
258
- bisque: [255, 228, 196],
259
- blanchedalmond: [255, 235, 205],
260
- cornsilk: [255, 248, 220],
261
-
262
- // Special colors
263
- transparent: [0, 0, 0], // Note: alpha will be 0 for transparent
264
- aliceblue: [240, 248, 255],
265
- antiquewhite: [250, 235, 215],
266
- azure: [240, 255, 255],
267
- beige: [245, 245, 220],
268
- honeydew: [240, 255, 240],
269
- ivory: [255, 255, 240],
270
- lavenderblush: [255, 240, 245],
271
- linen: [250, 240, 230],
272
- mintcream: [245, 255, 250],
273
- mistyrose: [255, 228, 225],
274
- oldlace: [253, 245, 230],
275
- seashell: [255, 245, 238],
276
- snow: [255, 250, 250],
277
- };
278
-
279
- /**
280
- * Converts HSL color to RGB
281
- * @param {number} h - Hue (0-360)
282
- * @param {number} s - Saturation (0-1)
283
- * @param {number} l - Lightness (0-1)
284
- * @returns {Array<number>} [r, g, b] values
285
- */
286
- const hslToRgb = (h, s, l) => {
287
- h = h % 360;
288
- const c = (1 - Math.abs(2 * l - 1)) * s;
289
- const x = c * (1 - Math.abs(((h / 60) % 2) - 1));
290
- const m = l - c / 2;
291
- const createRgb = (r, g, b) => {
292
- return [
293
- Math.round((r + m) * 255),
294
- Math.round((g + m) * 255),
295
- Math.round((b + m) * 255),
296
- ];
297
- };
298
-
299
- if (h >= 0 && h < 60) {
300
- return createRgb(c, x, 0);
301
- }
302
- if (h >= 60 && h < 120) {
303
- return createRgb(x, c, 0);
304
- }
305
- if (h >= 120 && h < 180) {
306
- return createRgb(0, c, x);
307
- }
308
- if (h >= 180 && h < 240) {
309
- return createRgb(0, x, c);
310
- }
311
- if (h >= 240 && h < 300) {
312
- return createRgb(x, 0, c);
313
- }
314
- if (h >= 300 && h < 360) {
315
- return createRgb(c, 0, x);
316
- }
317
-
318
- return createRgb(0, 0, 0);
319
- };
@@ -1,28 +0,0 @@
1
- /**
2
- * Determines if the current color scheme is dark mode
3
- * @param {Element} [element] - DOM element to check color-scheme against (optional)
4
- * @returns {boolean} True if dark mode is active
5
- */
6
- export const prefersDarkColors = (element) => {
7
- const colorScheme = getPreferedColorScheme(element);
8
- return colorScheme.includes("dark");
9
- };
10
-
11
- export const prefersLightColors = (element) => {
12
- return !prefersDarkColors(element);
13
- };
14
-
15
- export const getPreferedColorScheme = (element) => {
16
- const computedStyle = getComputedStyle(element || document.documentElement);
17
- const colorScheme = computedStyle.colorScheme;
18
-
19
- // If no explicit color-scheme is set, or it's "normal",
20
- // fall back to prefers-color-scheme media query
21
- if (!colorScheme || colorScheme === "normal") {
22
- return window.matchMedia("(prefers-color-scheme: dark)").matches
23
- ? "dark"
24
- : "light";
25
- }
26
-
27
- return colorScheme;
28
- };