solid-tiny-utils 0.7.0 → 0.8.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 (134) hide show
  1. package/README.md +9 -9
  2. package/dist/color/{hex-rgb.d.ts → hex-rgb.d.mts} +5 -3
  3. package/dist/color/hex-rgb.mjs +62 -0
  4. package/dist/color/{oklch-rgb.d.ts → oklch-rgb.d.mts} +9 -8
  5. package/dist/color/oklch-rgb.mjs +101 -0
  6. package/dist/color/{validation.d.ts → validation.d.mts} +5 -3
  7. package/dist/color/validation.mjs +35 -0
  8. package/dist/dom/{css.d.ts → css.d.mts} +6 -4
  9. package/dist/dom/css.mjs +51 -0
  10. package/dist/event/create-click-outside.d.mts +9 -0
  11. package/dist/event/create-click-outside.mjs +33 -0
  12. package/dist/event/{create-event-listener.d.ts → create-event-listener.d.mts} +7 -6
  13. package/dist/event/create-event-listener.mjs +34 -0
  14. package/dist/event/{create-intersection-observer.d.ts → create-intersection-observer.d.mts} +5 -4
  15. package/dist/event/create-intersection-observer.mjs +29 -0
  16. package/dist/event/{create-visibility-observer.d.ts → create-visibility-observer.d.mts} +7 -5
  17. package/dist/event/create-visibility-observer.mjs +46 -0
  18. package/dist/event/index.d.mts +12 -0
  19. package/dist/event/index.mjs +15 -0
  20. package/dist/event/{make-event-listener.d.ts → make-event-listener.d.mts} +8 -7
  21. package/dist/event/make-event-listener.mjs +35 -0
  22. package/dist/event/on-motion-end.d.mts +63 -0
  23. package/dist/event/on-motion-end.mjs +96 -0
  24. package/dist/fn/create-debounce.d.mts +7 -0
  25. package/dist/fn/create-debounce.mjs +20 -0
  26. package/dist/fn/{create-loop-exec.d.ts → create-loop-exec.d.mts} +7 -6
  27. package/dist/fn/create-loop-exec.mjs +59 -0
  28. package/dist/fn/create-throttle.d.mts +7 -0
  29. package/dist/fn/create-throttle.mjs +21 -0
  30. package/dist/fn/index.d.mts +8 -0
  31. package/dist/fn/index.mjs +9 -0
  32. package/dist/index.d.mts +30 -0
  33. package/dist/index.mjs +27 -0
  34. package/dist/jsx/{attrs.d.ts → attrs.d.mts} +3 -2
  35. package/dist/jsx/attrs.mjs +26 -0
  36. package/dist/reactive/access.d.mts +6 -0
  37. package/dist/reactive/access.mjs +9 -0
  38. package/dist/reactive/{create-debounce-watch.d.ts → create-debounce-watch.d.mts} +6 -4
  39. package/dist/reactive/create-debounce-watch.mjs +15 -0
  40. package/dist/reactive/{create-watch.d.ts → create-watch.d.mts} +4 -3
  41. package/dist/reactive/create-watch.mjs +9 -0
  42. package/dist/reactive/index.d.mts +3 -0
  43. package/dist/types/{fn.d.ts → fn.d.mts} +3 -2
  44. package/dist/types/index.d.mts +2 -0
  45. package/dist/types/{maybe.d.ts → maybe.d.mts} +4 -3
  46. package/dist/utils/{array.d.ts → array.d.mts} +3 -2
  47. package/dist/utils/array.mjs +66 -0
  48. package/dist/utils/async.d.mts +8 -0
  49. package/dist/utils/async.mjs +17 -0
  50. package/dist/utils/{is.d.ts → is.d.mts} +3 -2
  51. package/dist/utils/is.mjs +72 -0
  52. package/dist/utils/{number.d.ts → number.d.mts} +3 -2
  53. package/dist/utils/number.mjs +127 -0
  54. package/dist/utils/{random.d.ts → random.d.mts} +3 -2
  55. package/dist/utils/random.mjs +33 -0
  56. package/dist/utils/{str.d.ts → str.d.mts} +4 -3
  57. package/dist/utils/str.mjs +120 -0
  58. package/package.json +22 -19
  59. package/dist/chunk-4L6FK7MF.js +0 -9
  60. package/dist/chunk-6G7GFZV2.js +0 -93
  61. package/dist/chunk-6OVLJ45M.js +0 -51
  62. package/dist/chunk-ACZGS7DG.js +0 -72
  63. package/dist/chunk-AZAXMGEB.js +0 -0
  64. package/dist/chunk-BLX3XSA6.js +0 -0
  65. package/dist/chunk-BT47ISVC.js +0 -36
  66. package/dist/chunk-EZML2DEC.js +0 -0
  67. package/dist/chunk-FFBJP5FE.js +0 -0
  68. package/dist/chunk-II6INKPZ.js +0 -8
  69. package/dist/chunk-KFLH3AZ6.js +0 -40
  70. package/dist/chunk-KKFGUHFR.js +0 -8
  71. package/dist/chunk-KM4Q6THD.js +0 -50
  72. package/dist/chunk-LEWF7QAQ.js +0 -47
  73. package/dist/chunk-LUFOWTRW.js +0 -0
  74. package/dist/chunk-PD6VHMH6.js +0 -26
  75. package/dist/chunk-QPEF6LHH.js +0 -111
  76. package/dist/chunk-QQVSG76Z.js +0 -36
  77. package/dist/chunk-S7U3LZNS.js +0 -23
  78. package/dist/chunk-SK6Y2YH6.js +0 -0
  79. package/dist/chunk-TDJLPDJF.js +0 -66
  80. package/dist/chunk-TGWWPUWD.js +0 -55
  81. package/dist/chunk-U5LQ2AS5.js +0 -0
  82. package/dist/chunk-WJHRONQU.js +0 -54
  83. package/dist/chunk-Y4GYGFIT.js +0 -85
  84. package/dist/chunk-YK5QQQ43.js +0 -12
  85. package/dist/chunk-YXRZ2KMJ.js +0 -0
  86. package/dist/color/hex-rgb.js +0 -15
  87. package/dist/color/index.d.ts +0 -3
  88. package/dist/color/index.js +0 -30
  89. package/dist/color/oklch-rgb.js +0 -15
  90. package/dist/color/validation.js +0 -18
  91. package/dist/dom/css.js +0 -19
  92. package/dist/dom/index.d.ts +0 -2
  93. package/dist/dom/index.js +0 -20
  94. package/dist/event/create-click-outside.d.ts +0 -8
  95. package/dist/event/create-click-outside.js +0 -17
  96. package/dist/event/create-event-listener.js +0 -17
  97. package/dist/event/create-intersection-observer.js +0 -16
  98. package/dist/event/create-visibility-observer.js +0 -16
  99. package/dist/event/index.d.ts +0 -8
  100. package/dist/event/index.js +0 -33
  101. package/dist/event/make-event-listener.js +0 -16
  102. package/dist/fn/create-debounce.d.ts +0 -6
  103. package/dist/fn/create-debounce.js +0 -15
  104. package/dist/fn/create-loop-exec.js +0 -15
  105. package/dist/fn/create-throttle.d.ts +0 -6
  106. package/dist/fn/create-throttle.js +0 -15
  107. package/dist/fn/index.d.ts +0 -9
  108. package/dist/fn/index.js +0 -21
  109. package/dist/index.d.ts +0 -27
  110. package/dist/index.js +0 -166
  111. package/dist/jsx/attrs.js +0 -6
  112. package/dist/jsx/index.d.ts +0 -1
  113. package/dist/jsx/index.js +0 -7
  114. package/dist/reactive/access.d.ts +0 -6
  115. package/dist/reactive/access.js +0 -13
  116. package/dist/reactive/create-debounce-watch.js +0 -15
  117. package/dist/reactive/create-watch.js +0 -6
  118. package/dist/reactive/index.d.ts +0 -5
  119. package/dist/reactive/index.js +0 -21
  120. package/dist/types/fn.js +0 -1
  121. package/dist/types/index.d.ts +0 -3
  122. package/dist/types/index.js +0 -3
  123. package/dist/types/maybe.js +0 -1
  124. package/dist/utils/array.js +0 -13
  125. package/dist/utils/async.d.ts +0 -6
  126. package/dist/utils/async.js +0 -6
  127. package/dist/utils/index.d.ts +0 -6
  128. package/dist/utils/index.js +0 -85
  129. package/dist/utils/is.js +0 -30
  130. package/dist/utils/number.js +0 -14
  131. package/dist/utils/object.d.ts +0 -10
  132. package/dist/utils/object.js +0 -7
  133. package/dist/utils/random.js +0 -14
  134. package/dist/utils/str.js +0 -20
package/README.md CHANGED
@@ -1,9 +1,9 @@
1
- # solid-tiny-utils
2
-
3
- Tiny utilities for SolidJS applications.
4
-
5
- ## Installation
6
-
7
- ```bash
8
- pnpm add solid-tiny-utils
9
- ```
1
+ # solid-tiny-utils
2
+
3
+ Tiny utilities for SolidJS applications.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pnpm add solid-tiny-utils
9
+ ```
@@ -1,4 +1,6 @@
1
- import { RGB } from './oklch-rgb.js';
1
+ import { RGB } from "./oklch-rgb.mjs";
2
+
3
+ //#region src/color/hex-rgb.d.ts
2
4
 
3
5
  /**
4
6
  * Converts a hex color string to RGB color values.
@@ -32,5 +34,5 @@ declare function hexToRgb(hex: string): RGB | null;
32
34
  * ```
33
35
  */
34
36
  declare function rgbToHex(rgb: RGB | [number, number, number]): string;
35
-
36
- export { hexToRgb, rgbToHex };
37
+ //#endregion
38
+ export { hexToRgb, rgbToHex };
@@ -0,0 +1,62 @@
1
+ import { isArray } from "../utils/is.mjs";
2
+ import { clamp, toHex } from "../utils/number.mjs";
3
+
4
+ //#region src/color/hex-rgb.ts
5
+ const HEX_PREFIX_REGEX = /^#/;
6
+ const HEX_VALIDATION_REGEX = /^[0-9a-fA-F]{6}$/;
7
+ /**
8
+ * Converts a hex color string to RGB color values.
9
+ *
10
+ * Supports both 3-digit (#rgb) and 6-digit (#rrggbb) hex formats.
11
+ * The hash symbol (#) is optional.
12
+ *
13
+ * @param hex - Hex color string (e.g., "#ffcc00", "ffcc00", "#fc0", "fc0")
14
+ * @returns RGB object with r, g, b values (0-255), or null if invalid
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * hexToRgb("#ffcc00") // => { r: 255, g: 204, b: 0 }
19
+ * hexToRgb("fc0") // => { r: 255, g: 204, b: 0 }
20
+ * hexToRgb("#invalid") // => null
21
+ * ```
22
+ */
23
+ function hexToRgb(hex) {
24
+ if (!hex || typeof hex !== "string") return null;
25
+ let value = hex.trim().replace(HEX_PREFIX_REGEX, "");
26
+ if (value.length === 3) value = value.split("").map((c) => c + c).join("");
27
+ if (!HEX_VALIDATION_REGEX.test(value)) return null;
28
+ return {
29
+ r: Number.parseInt(value.slice(0, 2), 16),
30
+ g: Number.parseInt(value.slice(2, 4), 16),
31
+ b: Number.parseInt(value.slice(4, 6), 16)
32
+ };
33
+ }
34
+ /**
35
+ * Converts RGB color values to a hex color string.
36
+ *
37
+ * RGB values are automatically clamped to the 0-255 range.
38
+ *
39
+ * @param rgb - RGB object with r, g, b values
40
+ * @returns Hex color string with # prefix (e.g., "#ffcc00")
41
+ *
42
+ * @example
43
+ * ```typescript
44
+ * rgbToHex({ r: 255, g: 204, b: 0 }) // => "#ffcc00"
45
+ * rgbToHex({ r: 300, g: -10, b: 128 }) // => "#ff0080" (clamped values)
46
+ * ```
47
+ */
48
+ function rgbToHex(rgb) {
49
+ const c = (v) => Math.round(clamp(v, 0, 255));
50
+ const rgb_ = isArray(rgb) ? rgb : [
51
+ rgb.r,
52
+ rgb.g,
53
+ rgb.b
54
+ ];
55
+ const r = c(rgb_[0]);
56
+ const g = c(rgb_[1]);
57
+ const b = c(rgb_[2]);
58
+ return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
59
+ }
60
+
61
+ //#endregion
62
+ export { hexToRgb, rgbToHex };
@@ -1,12 +1,13 @@
1
+ //#region src/color/oklch-rgb.d.ts
1
2
  interface RGB {
2
- r: number;
3
- g: number;
4
- b: number;
3
+ r: number;
4
+ g: number;
5
+ b: number;
5
6
  }
6
7
  interface OKLCH {
7
- l: number;
8
- c: number;
9
- h: number;
8
+ l: number;
9
+ c: number;
10
+ h: number;
10
11
  }
11
12
  /**
12
13
  * Converts OKLCH color to RGB color space.
@@ -45,5 +46,5 @@ declare function oklchToRgb(oklch: OKLCH): RGB;
45
46
  * ```
46
47
  */
47
48
  declare function rgbToOklch(rgb: RGB): OKLCH;
48
-
49
- export { type OKLCH, type RGB, oklchToRgb, rgbToOklch };
49
+ //#endregion
50
+ export { OKLCH, RGB, oklchToRgb, rgbToOklch };
@@ -0,0 +1,101 @@
1
+ import { clamp, max } from "../utils/number.mjs";
2
+
3
+ //#region src/color/oklch-rgb.ts
4
+ const PI_180 = Math.PI / 180;
5
+ const INV_PI_180 = 180 / Math.PI;
6
+ const linearToSRGB = (x) => x <= .0031308 ? 12.92 * x : 1.055 * x ** (1 / 2.4) - .055;
7
+ const sRGBToLinear = (x) => x <= .04045 ? x / 12.92 : ((x + .055) / 1.055) ** 2.4;
8
+ /**
9
+ * Normalizes hue to 0-360 degree range
10
+ */
11
+ function normalizeHue(hue) {
12
+ return (hue % 360 + 360) % 360;
13
+ }
14
+ /**
15
+ * Converts OKLCH color to RGB color space.
16
+ *
17
+ * OKLCH is a perceptually uniform color space based on OKLab.
18
+ * Input values are automatically clamped to valid ranges.
19
+ *
20
+ * @param oklch - The OKLCH color to convert
21
+ * @param oklch.l - Lightness (0-1, will be clamped)
22
+ * @param oklch.c - Chroma (≥0, will be clamped)
23
+ * @param oklch.h - Hue in degrees (will be normalized to 0-360)
24
+ * @returns RGB color with values 0-255
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * const rgb = oklchToRgb({ l: 0.7, c: 0.1, h: 200 });
29
+ * // => { r: 64, g: 177, b: 183 }
30
+ * ```
31
+ */
32
+ function oklchToRgb(oklch) {
33
+ const { l, c, h } = oklch;
34
+ const clampedL = clamp(l, 0, 1);
35
+ const clampedC = max(0, c);
36
+ const normalizedH = normalizeHue(h);
37
+ const a_ = clampedC * Math.cos(normalizedH * PI_180);
38
+ const b_ = clampedC * Math.sin(normalizedH * PI_180);
39
+ const L = clampedL;
40
+ const A = a_;
41
+ const B = b_;
42
+ const l_ = L + .3963377774 * A + .2158037573 * B;
43
+ const m_ = L - .1055613458 * A - .0638541728 * B;
44
+ const s_ = L - .0894841775 * A - 1.291485548 * B;
45
+ const l3 = l_ ** 3;
46
+ const m3 = m_ ** 3;
47
+ const s3 = s_ ** 3;
48
+ let r = 4.0767416621 * l3 - 3.3077115913 * m3 + .2309699292 * s3;
49
+ let g = -1.2684380046 * l3 + 2.6097574011 * m3 - .3413193965 * s3;
50
+ let b = -.0041960863 * l3 - .7034186147 * m3 + 1.707614701 * s3;
51
+ r = linearToSRGB(r);
52
+ g = linearToSRGB(g);
53
+ b = linearToSRGB(b);
54
+ return {
55
+ r: Math.round(clamp(r) * 255),
56
+ g: Math.round(clamp(g) * 255),
57
+ b: Math.round(clamp(b) * 255)
58
+ };
59
+ }
60
+ /**
61
+ * Converts RGB color to OKLCH color space.
62
+ *
63
+ * RGB values are automatically clamped to 0-255 range.
64
+ *
65
+ * @param rgb - The RGB color to convert
66
+ * @param rgb.r - Red component (0-255, will be clamped)
67
+ * @param rgb.g - Green component (0-255, will be clamped)
68
+ * @param rgb.b - Blue component (0-255, will be clamped)
69
+ * @returns OKLCH color with l∈[0,1], c≥0, h∈[0,360)
70
+ *
71
+ * @example
72
+ * ```typescript
73
+ * const oklch = rgbToOklch({ r: 64, g: 177, b: 183 });
74
+ * // => { l: 0.7, c: 0.1, h: 200 }
75
+ * ```
76
+ */
77
+ function rgbToOklch(rgb) {
78
+ const r = clamp(rgb.r, 0, 255);
79
+ const g = clamp(rgb.g, 0, 255);
80
+ const b = clamp(rgb.b, 0, 255);
81
+ const rLinear = sRGBToLinear(r / 255);
82
+ const gLinear = sRGBToLinear(g / 255);
83
+ const bLinear = sRGBToLinear(b / 255);
84
+ const l_ = Math.cbrt(.4122214708 * rLinear + .5363325363 * gLinear + .0514459929 * bLinear);
85
+ const m_ = Math.cbrt(.2119034982 * rLinear + .6806995451 * gLinear + .1073969566 * bLinear);
86
+ const s_ = Math.cbrt(.0883024619 * rLinear + .2817188376 * gLinear + .6299787005 * bLinear);
87
+ const L = .2104542553 * l_ + .793617785 * m_ - .0040720468 * s_;
88
+ const A = 1.9779984951 * l_ - 2.428592205 * m_ + .4505937099 * s_;
89
+ const B = .0259040371 * l_ + .7827717662 * m_ - .808675766 * s_;
90
+ const c = Math.sqrt(A * A + B * B);
91
+ let h = Math.atan2(B, A) * INV_PI_180;
92
+ if (h < 0) h += 360;
93
+ return {
94
+ l: L,
95
+ c,
96
+ h
97
+ };
98
+ }
99
+
100
+ //#endregion
101
+ export { oklchToRgb, rgbToOklch };
@@ -1,4 +1,6 @@
1
- import { RGB, OKLCH } from './oklch-rgb.js';
1
+ import { OKLCH, RGB } from "./oklch-rgb.mjs";
2
+
3
+ //#region src/color/validation.d.ts
2
4
 
3
5
  /**
4
6
  * Checks if RGB values are in valid range (0-255)
@@ -22,5 +24,5 @@ declare function isValidOKLCH(oklch: OKLCH): boolean;
22
24
  * ```
23
25
  */
24
26
  declare function isValidHex(hex: string): boolean;
25
-
26
- export { isValidHex, isValidOKLCH, isValidRGB };
27
+ //#endregion
28
+ export { isValidHex, isValidOKLCH, isValidRGB };
@@ -0,0 +1,35 @@
1
+ import { inRange } from "../utils/number.mjs";
2
+ import { hexToRgb } from "./hex-rgb.mjs";
3
+
4
+ //#region src/color/validation.ts
5
+ /**
6
+ * Checks if RGB values are in valid range (0-255)
7
+ */
8
+ function isValidRGB(rgb) {
9
+ return Object.values(rgb).every((x) => inRange(x, 0, 255));
10
+ }
11
+ /**
12
+ * Checks if OKLCH values are in valid ranges
13
+ */
14
+ function isValidOKLCH(oklch) {
15
+ return inRange(oklch.l) && oklch.c >= 0 && inRange(oklch.h, 0, 360);
16
+ }
17
+ /**
18
+ * Checks if a string is a valid hex color format.
19
+ *
20
+ * @param hex - String to validate
21
+ * @returns `true` if the string is a valid hex color, `false` otherwise
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * isValidHex("#ffcc00") // => true
26
+ * isValidHex("fc0") // => true
27
+ * isValidHex("#invalid") // => false
28
+ * ```
29
+ */
30
+ function isValidHex(hex) {
31
+ return hexToRgb(hex) !== null;
32
+ }
33
+
34
+ //#endregion
35
+ export { isValidHex, isValidOKLCH, isValidRGB };
@@ -1,4 +1,6 @@
1
- import { JSX } from 'solid-js/jsx-runtime';
1
+ import { JSX } from "solid-js/jsx-runtime";
2
+
3
+ //#region src/dom/css.d.ts
2
4
 
3
5
  /**
4
6
  * Mounts a style element to the document head.
@@ -13,6 +15,6 @@ import { JSX } from 'solid-js/jsx-runtime';
13
15
  declare function mountStyle(style: string, id: string, refresh?: boolean): void;
14
16
  declare function stringStyleToObject(style: string): JSX.CSSProperties;
15
17
  declare function combineStyle(a: JSX.CSSProperties, b: JSX.CSSProperties | string | undefined): JSX.CSSProperties | string;
16
- declare function combineClass(defaultClass: string, ...otherClass: string[]): string;
17
-
18
- export { combineClass, combineStyle, mountStyle, stringStyleToObject };
18
+ declare function combineClass(defaultClass: string, ...otherClass: (string | undefined | null)[]): string;
19
+ //#endregion
20
+ export { combineClass, combineStyle, mountStyle, stringStyleToObject };
@@ -0,0 +1,51 @@
1
+ import { isClient } from "../utils/is.mjs";
2
+
3
+ //#region src/dom/css.ts
4
+ const alreadyInjected = [];
5
+ /**
6
+ * Mounts a style element to the document head.
7
+ * If the style element with the given id already exists, it updates its content.
8
+ * If `refresh` is true, it will update the style even if it has already been injected.
9
+ * Note: This function should only be called in a client environment or `onMount`
10
+ *
11
+ * @param style - The CSS style to inject.
12
+ * @param id - The id of the style element.
13
+ * @param refresh - Whether to refresh the style if it already exists. Defaults to **false**.
14
+ */
15
+ function mountStyle(style, id, refresh = false) {
16
+ if (!isClient) return;
17
+ if (alreadyInjected.includes(id) && !refresh) return;
18
+ let styleElement = document.querySelector(`style#${id}`);
19
+ if (styleElement) {
20
+ styleElement.innerHTML = style;
21
+ return;
22
+ }
23
+ styleElement = document.createElement("style");
24
+ styleElement.id = id;
25
+ styleElement.innerHTML = style;
26
+ document.head.appendChild(styleElement);
27
+ alreadyInjected.push(id);
28
+ }
29
+ const extractCSSregex = /((?:--)?(?:\w+-?)+)\s*:\s*([^;]*)/g;
30
+ function stringStyleToObject(style) {
31
+ const object = {};
32
+ let match = extractCSSregex.exec(style);
33
+ while (match) {
34
+ if (match[1] && match[2]) object[match[1]] = match[2];
35
+ match = extractCSSregex.exec(style);
36
+ }
37
+ return object;
38
+ }
39
+ function combineStyle(a, b) {
40
+ const bb = typeof b === "string" ? stringStyleToObject(b) : b;
41
+ return {
42
+ ...a,
43
+ ...bb
44
+ };
45
+ }
46
+ function combineClass(defaultClass, ...otherClass) {
47
+ return [defaultClass, ...otherClass].filter(Boolean).join(" ");
48
+ }
49
+
50
+ //#endregion
51
+ export { combineClass, combineStyle, mountStyle, stringStyleToObject };
@@ -0,0 +1,9 @@
1
+ import { MaybeAccessor } from "../types/maybe.mjs";
2
+ import "../types/index.mjs";
3
+
4
+ //#region src/event/create-click-outside.d.ts
5
+ declare function createClickOutside(target: MaybeAccessor<HTMLElement | null | undefined>, handler: (event: PointerEvent) => void, options?: {
6
+ ignore?: MaybeAccessor<HTMLElement | null | undefined>[];
7
+ }): () => void;
8
+ //#endregion
9
+ export { createClickOutside };
@@ -0,0 +1,33 @@
1
+ import { access } from "../reactive/access.mjs";
2
+ import { makeEventListener } from "./make-event-listener.mjs";
3
+
4
+ //#region src/event/create-click-outside.ts
5
+ function createClickOutside(target, handler, options) {
6
+ let shouldListen = false;
7
+ const shouldIgnore = (event) => {
8
+ return (options?.ignore ? options.ignore : []).map(access).some((el) => {
9
+ return el && (event.target === el || event.composedPath().includes(el));
10
+ });
11
+ };
12
+ const listener = (e) => {
13
+ const el = access(target);
14
+ if (!el || el === e.target || e.composedPath().includes(el)) return;
15
+ if (e.detail === 0) shouldListen = !shouldIgnore(e);
16
+ if (!shouldListen) {
17
+ shouldListen = true;
18
+ return;
19
+ }
20
+ handler(e);
21
+ };
22
+ const cleanups = [makeEventListener("click", listener, { passive: true }), makeEventListener("pointerdown", (e) => {
23
+ const el = access(target);
24
+ if (el) shouldListen = !(e.composedPath().includes(el) || shouldIgnore(e));
25
+ }, { passive: true })];
26
+ const stop = () => {
27
+ for (const cleanup of cleanups) cleanup();
28
+ };
29
+ return stop;
30
+ }
31
+
32
+ //#endregion
33
+ export { createClickOutside };
@@ -1,8 +1,9 @@
1
- import { Fn } from '../types/fn.js';
2
- import { MaybeAccessor, MaybeArray } from '../types/maybe.js';
3
- import { WindowEventName, DocumentEventName, GeneralEventListener } from './make-event-listener.js';
4
- import 'solid-js';
1
+ import { Fn } from "../types/fn.mjs";
2
+ import { MaybeAccessor, MaybeArray } from "../types/maybe.mjs";
3
+ import "../types/index.mjs";
4
+ import { DocumentEventName, GeneralEventListener, WindowEventName } from "./make-event-listener.mjs";
5
5
 
6
+ //#region src/event/create-event-listener.d.ts
6
7
  /**
7
8
  * Overload 2: Explicitly Window target
8
9
  */
@@ -19,5 +20,5 @@ declare function createEventListener<T extends HTMLElement, E extends keyof HTML
19
20
  * Overload 6: Custom event target fallback
20
21
  */
21
22
  declare function createEventListener<EventType = Event>(target: MaybeAccessor<EventTarget | undefined | null>, event: MaybeAccessor<MaybeArray<string>>, listener: MaybeArray<GeneralEventListener<EventType>>, options?: MaybeAccessor<boolean | AddEventListenerOptions | undefined>): Fn;
22
-
23
- export { createEventListener };
23
+ //#endregion
24
+ export { createEventListener };
@@ -0,0 +1,34 @@
1
+ import { isArray } from "../utils/is.mjs";
2
+ import { clearArray } from "../utils/array.mjs";
3
+ import { access } from "../reactive/access.mjs";
4
+ import { noop } from "../fn/index.mjs";
5
+ import { createWatch } from "../reactive/create-watch.mjs";
6
+ import { makeEventListener } from "./make-event-listener.mjs";
7
+
8
+ //#region src/event/create-event-listener.ts
9
+ /** biome-ignore-all lint/suspicious/noExplicitAny: I need any */
10
+ function createEventListener(...args) {
11
+ const target = args[0];
12
+ const events = args[1];
13
+ let listeners = args[2];
14
+ const options = args[3] ?? noop;
15
+ if (!isArray(listeners)) listeners = [listeners];
16
+ const cleanups = [];
17
+ const cleanup = () => {
18
+ for (const c of cleanups) c();
19
+ clearArray(cleanups);
20
+ };
21
+ createWatch(() => [
22
+ access(target),
23
+ access(events),
24
+ access(options)
25
+ ], ([tars, evs, opts]) => {
26
+ cleanup();
27
+ if (!(tars && evs)) return;
28
+ cleanups.push(makeEventListener(tars, evs, listeners, opts));
29
+ });
30
+ return cleanup;
31
+ }
32
+
33
+ //#endregion
34
+ export { createEventListener };
@@ -1,6 +1,7 @@
1
- import { MaybeAccessor } from '../types/maybe.js';
2
- import 'solid-js';
1
+ import { MaybeAccessor } from "../types/maybe.mjs";
2
+ import "../types/index.mjs";
3
3
 
4
+ //#region src/event/create-intersection-observer.d.ts
4
5
  declare function createIntersectionObserver(targets: MaybeAccessor<HTMLElement | null | undefined>[], callback: IntersectionObserverCallback, options?: IntersectionObserverInit): () => void;
5
-
6
- export { createIntersectionObserver };
6
+ //#endregion
7
+ export { createIntersectionObserver };
@@ -0,0 +1,29 @@
1
+ import { clearArray } from "../utils/array.mjs";
2
+ import { access } from "../reactive/access.mjs";
3
+ import { noop } from "../fn/index.mjs";
4
+ import { createWatch } from "../reactive/create-watch.mjs";
5
+ import { isServer } from "solid-js/web";
6
+ import { onCleanup } from "solid-js";
7
+
8
+ //#region src/event/create-intersection-observer.ts
9
+ function createIntersectionObserver(targets, callback, options = {}) {
10
+ if (isServer) return noop;
11
+ const io = new IntersectionObserver(callback, options);
12
+ onCleanup(() => io.disconnect());
13
+ const cleanups = [];
14
+ const cleanup = () => {
15
+ for (const c of cleanups) c();
16
+ clearArray(cleanups);
17
+ };
18
+ createWatch(() => targets.map(access), (elements) => {
19
+ cleanup();
20
+ for (const element of elements) if (element) {
21
+ io.observe(element);
22
+ cleanups.push(() => io.unobserve(element));
23
+ }
24
+ });
25
+ return () => io.disconnect();
26
+ }
27
+
28
+ //#endregion
29
+ export { createIntersectionObserver };
@@ -1,12 +1,14 @@
1
- import { Accessor } from 'solid-js';
2
- import { MaybeNullableAccessor } from '../types/maybe.js';
1
+ import { MaybeNullableAccessor } from "../types/maybe.mjs";
2
+ import "../types/index.mjs";
3
+ import { Accessor } from "solid-js";
3
4
 
5
+ //#region src/event/create-visibility-observer.d.ts
4
6
  type UseVisibilityObserverFn = (target: MaybeNullableAccessor<HTMLElement>) => Accessor<boolean>;
5
7
  type CreateVisibilityObserverOption = IntersectionObserverInit & {
6
- initialValue?: boolean;
8
+ initialValue?: boolean;
7
9
  };
8
10
  type EntryCallback = (entry: IntersectionObserverEntry, instance: IntersectionObserver) => void;
9
11
  declare function createVisibilityObserver(options?: CreateVisibilityObserverOption): UseVisibilityObserverFn;
10
12
  declare function createVisibilityObserver(target: MaybeNullableAccessor<HTMLElement>, options?: CreateVisibilityObserverOption): Accessor<boolean>;
11
-
12
- export { type CreateVisibilityObserverOption, type EntryCallback, type UseVisibilityObserverFn, createVisibilityObserver };
13
+ //#endregion
14
+ export { CreateVisibilityObserverOption, EntryCallback, UseVisibilityObserverFn, createVisibilityObserver };
@@ -0,0 +1,46 @@
1
+ import { isObject } from "../utils/is.mjs";
2
+ import { access } from "../reactive/access.mjs";
3
+ import { createWatch } from "../reactive/create-watch.mjs";
4
+ import { createSignal, onCleanup } from "solid-js";
5
+
6
+ //#region src/event/create-visibility-observer.ts
7
+ function createVisibilityObserver(arg1, arg2) {
8
+ let target;
9
+ let options;
10
+ if (arg1 && !isObject(arg1)) {
11
+ target = arg1;
12
+ options = arg2 ?? {};
13
+ } else options = arg1 ?? {};
14
+ const callbacks = /* @__PURE__ */ new WeakMap();
15
+ const io = new IntersectionObserver((entries, instance) => {
16
+ for (const entry of entries) callbacks.get(entry.target)?.(entry, instance);
17
+ }, options);
18
+ onCleanup(() => io.disconnect());
19
+ const addEntry = (el, callback) => {
20
+ io.observe(el);
21
+ callbacks.set(el, callback);
22
+ };
23
+ const removeEntry = (el) => {
24
+ io.unobserve(el);
25
+ callbacks.delete(el);
26
+ };
27
+ const useVisibilityObserverFn = (element) => {
28
+ const [isVisible, setVisible] = createSignal(options?.initialValue ?? false);
29
+ let prevEl;
30
+ createWatch(() => access(element), (el) => {
31
+ if (prevEl) removeEntry(prevEl);
32
+ if (el) {
33
+ addEntry(el, (entry) => {
34
+ setVisible(entry.isIntersecting);
35
+ });
36
+ prevEl = el;
37
+ }
38
+ });
39
+ return isVisible;
40
+ };
41
+ if (target) return useVisibilityObserverFn(target);
42
+ return useVisibilityObserverFn;
43
+ }
44
+
45
+ //#endregion
46
+ export { createVisibilityObserver };
@@ -0,0 +1,12 @@
1
+ import { createClickOutside } from "./create-click-outside.mjs";
2
+ import { DocumentEventName, GeneralEventListener, WindowEventName, makeEventListener } from "./make-event-listener.mjs";
3
+ import { createEventListener } from "./create-event-listener.mjs";
4
+ import { createIntersectionObserver } from "./create-intersection-observer.mjs";
5
+ import { CreateVisibilityObserverOption, EntryCallback, UseVisibilityObserverFn, createVisibilityObserver } from "./create-visibility-observer.mjs";
6
+ import { OnMotionEndOptions, OnMotionEndType, createOnMotionEnd, makeOnMotionEnd } from "./on-motion-end.mjs";
7
+ import { JSX } from "solid-js/jsx-runtime";
8
+
9
+ //#region src/event/index.d.ts
10
+ declare function runSolidEventHandler<T, E extends Event, EHandler extends JSX.EventHandler<T, any> = JSX.EventHandler<T, E>>(event: E, handler?: EHandler | JSX.BoundEventHandler<T, E, EHandler>): void;
11
+ //#endregion
12
+ export { runSolidEventHandler };
@@ -0,0 +1,15 @@
1
+ import { makeEventListener } from "./make-event-listener.mjs";
2
+ import { createClickOutside } from "./create-click-outside.mjs";
3
+ import { createEventListener } from "./create-event-listener.mjs";
4
+ import { createIntersectionObserver } from "./create-intersection-observer.mjs";
5
+ import { createVisibilityObserver } from "./create-visibility-observer.mjs";
6
+ import { createOnMotionEnd, makeOnMotionEnd } from "./on-motion-end.mjs";
7
+
8
+ //#region src/event/index.ts
9
+ function runSolidEventHandler(event, handler) {
10
+ if (typeof handler === "function") handler(event);
11
+ if (Array.isArray(handler)) handler[0](handler[1], event);
12
+ }
13
+
14
+ //#endregion
15
+ export { runSolidEventHandler };
@@ -1,10 +1,11 @@
1
- import { Fn } from '../types/fn.js';
2
- import { MaybeArray } from '../types/maybe.js';
3
- import 'solid-js';
1
+ import { Fn } from "../types/fn.mjs";
2
+ import { MaybeArray } from "../types/maybe.mjs";
3
+ import "../types/index.mjs";
4
4
 
5
+ //#region src/event/make-event-listener.d.ts
5
6
  interface InferEventTarget<Events> {
6
- addEventListener: (event: Events, fn?: any, options?: any) => any;
7
- removeEventListener: (event: Events, fn?: any, options?: any) => any;
7
+ addEventListener: (event: Events, fn?: any, options?: any) => any;
8
+ removeEventListener: (event: Events, fn?: any, options?: any) => any;
8
9
  }
9
10
  type WindowEventName = keyof WindowEventMap;
10
11
  type DocumentEventName = keyof DocumentEventMap;
@@ -45,5 +46,5 @@ declare function makeEventListener<Names extends string, EventType = Event>(targ
45
46
  * Overload 6: Custom event target fallback
46
47
  */
47
48
  declare function makeEventListener<EventType = Event>(target: EventTarget, event: MaybeArray<string>, listener: MaybeArray<GeneralEventListener<EventType>>, options?: boolean | AddEventListenerOptions): Fn;
48
-
49
- export { type DocumentEventName, type GeneralEventListener, type WindowEventName, makeEventListener };
49
+ //#endregion
50
+ export { DocumentEventName, GeneralEventListener, WindowEventName, makeEventListener };
@@ -0,0 +1,35 @@
1
+ import { isArray } from "../utils/is.mjs";
2
+ import { clearArray } from "../utils/array.mjs";
3
+ import { noop } from "../fn/index.mjs";
4
+ import { onCleanup } from "solid-js";
5
+
6
+ //#region src/event/make-event-listener.ts
7
+ /** biome-ignore-all lint/suspicious/noExplicitAny: I need any */
8
+ function makeEventListener(...args) {
9
+ let target;
10
+ let events;
11
+ let listeners;
12
+ let options;
13
+ if (typeof args[0] === "string" || isArray(args[0])) {
14
+ [events, listeners, options] = args;
15
+ target = window;
16
+ } else [target, events, listeners, options] = args;
17
+ if (!target) return noop;
18
+ if (!isArray(events)) events = [events];
19
+ if (!isArray(listeners)) listeners = [listeners];
20
+ const cleanups = [];
21
+ const cleanup = () => {
22
+ for (const c of cleanups) c();
23
+ clearArray(cleanups);
24
+ };
25
+ const register = (el, event, listener, opts) => {
26
+ el.addEventListener(event, listener, opts);
27
+ return () => el.removeEventListener(event, listener, opts);
28
+ };
29
+ cleanups.push(...events.flatMap((event) => listeners.map((listener) => register(target, event, listener, options))));
30
+ onCleanup(cleanup);
31
+ return cleanup;
32
+ }
33
+
34
+ //#endregion
35
+ export { makeEventListener };