yummies 7.19.3 → 7.20.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 (162) hide show
  1. package/assert.cjs +1 -1
  2. package/assert.cjs.map +1 -1
  3. package/assert.js +1 -1
  4. package/assert.js.map +1 -1
  5. package/async.cjs +147 -137
  6. package/async.cjs.map +1 -1
  7. package/async.d.ts +98 -131
  8. package/async.js +147 -137
  9. package/async.js.map +1 -1
  10. package/common.cjs +3 -1
  11. package/common.cjs.map +1 -1
  12. package/common.d.ts +18 -24
  13. package/common.js +3 -1
  14. package/common.js.map +1 -1
  15. package/complex.cjs +1 -0
  16. package/complex.cjs.map +1 -1
  17. package/complex.js +1 -0
  18. package/complex.js.map +1 -1
  19. package/cookie.cjs +1 -1
  20. package/cookie.cjs.map +1 -1
  21. package/cookie.d.ts +0 -18
  22. package/cookie.js +1 -1
  23. package/cookie.js.map +1 -1
  24. package/css-cx.cjs +78 -0
  25. package/css-cx.cjs.map +1 -0
  26. package/css-cx.d.ts +69 -0
  27. package/css-cx.js +74 -0
  28. package/css-cx.js.map +1 -0
  29. package/css.cjs +32 -111
  30. package/css.cjs.map +1 -1
  31. package/css.d.ts +32 -42
  32. package/css.js +30 -107
  33. package/css.js.map +1 -1
  34. package/data.cjs +60 -50
  35. package/data.cjs.map +1 -1
  36. package/data.d.ts +21 -34
  37. package/data.js +60 -50
  38. package/data.js.map +1 -1
  39. package/date-time.cjs +104 -98
  40. package/date-time.cjs.map +1 -1
  41. package/date-time.d.ts +51 -57
  42. package/date-time.js +104 -97
  43. package/date-time.js.map +1 -1
  44. package/device.cjs +14 -19
  45. package/device.cjs.map +1 -1
  46. package/device.d.ts +15 -26
  47. package/device.js +14 -19
  48. package/device.js.map +1 -1
  49. package/encodings.cjs +1 -1
  50. package/encodings.cjs.map +1 -1
  51. package/encodings.d.ts +0 -17
  52. package/encodings.js +1 -1
  53. package/encodings.js.map +1 -1
  54. package/errors.cjs +1 -18
  55. package/errors.cjs.map +1 -1
  56. package/errors.d.ts +0 -17
  57. package/errors.js +1 -17
  58. package/errors.js.map +1 -1
  59. package/file.cjs +3 -17
  60. package/file.cjs.map +1 -1
  61. package/file.d.ts +1 -16
  62. package/file.js +3 -17
  63. package/file.js.map +1 -1
  64. package/format.cjs +1 -1
  65. package/format.cjs.map +1 -1
  66. package/format.js +1 -1
  67. package/format.js.map +1 -1
  68. package/html.cjs +113 -173
  69. package/html.cjs.map +1 -1
  70. package/html.d.ts +68 -58
  71. package/html.js +112 -170
  72. package/html.js.map +1 -1
  73. package/id-nanoid.cjs +36 -0
  74. package/id-nanoid.cjs.map +1 -0
  75. package/id-nanoid.d.ts +26 -0
  76. package/id-nanoid.js +32 -0
  77. package/id-nanoid.js.map +1 -0
  78. package/id.cjs +10 -45
  79. package/id.cjs.map +1 -1
  80. package/id.d.ts +27 -36
  81. package/id.js +6 -40
  82. package/id.js.map +1 -1
  83. package/imports.cjs +3 -18
  84. package/imports.cjs.map +1 -1
  85. package/imports.d.ts +1 -16
  86. package/imports.js +3 -17
  87. package/imports.js.map +1 -1
  88. package/math.cjs +16 -12
  89. package/math.cjs.map +1 -1
  90. package/math.d.ts +9 -24
  91. package/math.js +16 -12
  92. package/math.js.map +1 -1
  93. package/media.cjs +88 -89
  94. package/media.cjs.map +1 -1
  95. package/media.d.ts +72 -80
  96. package/media.js +88 -88
  97. package/media.js.map +1 -1
  98. package/mobx.cjs +0 -1
  99. package/mobx.cjs.map +1 -1
  100. package/mobx.js.map +1 -1
  101. package/ms.cjs +3 -17
  102. package/ms.cjs.map +1 -1
  103. package/ms.d.ts +1 -16
  104. package/ms.js +3 -17
  105. package/ms.js.map +1 -1
  106. package/number.cjs +1 -17
  107. package/number.cjs.map +1 -1
  108. package/number.d.ts +0 -16
  109. package/number.js +1 -17
  110. package/number.js.map +1 -1
  111. package/package.json +6 -6
  112. package/parser.cjs +1 -1
  113. package/parser.cjs.map +1 -1
  114. package/parser.js +1 -1
  115. package/parser.js.map +1 -1
  116. package/price.cjs +1 -1
  117. package/price.cjs.map +1 -1
  118. package/price.d.ts +0 -16
  119. package/price.js +1 -1
  120. package/price.js.map +1 -1
  121. package/random.cjs +37 -39
  122. package/random.cjs.map +1 -1
  123. package/random.d.ts +31 -40
  124. package/random.js +37 -39
  125. package/random.js.map +1 -1
  126. package/react.cjs +0 -1
  127. package/react.cjs.map +1 -1
  128. package/react.js.map +1 -1
  129. package/sanitize-html.cjs +82 -0
  130. package/sanitize-html.cjs.map +1 -0
  131. package/sanitize-html.d.ts +28 -0
  132. package/sanitize-html.js +79 -0
  133. package/sanitize-html.js.map +1 -0
  134. package/sound.cjs +1 -17
  135. package/sound.cjs.map +1 -1
  136. package/sound.d.ts +0 -16
  137. package/sound.js +1 -17
  138. package/sound.js.map +1 -1
  139. package/storage.cjs +7 -5
  140. package/storage.cjs.map +1 -1
  141. package/storage.d.ts +3 -17
  142. package/storage.js +7 -5
  143. package/storage.js.map +1 -1
  144. package/text.cjs +3 -17
  145. package/text.cjs.map +1 -1
  146. package/text.d.ts +1 -16
  147. package/text.js +3 -17
  148. package/text.js.map +1 -1
  149. package/type-guard.cjs +38 -1
  150. package/type-guard.cjs.map +1 -1
  151. package/type-guard.d.ts +38 -0
  152. package/type-guard.js +38 -1
  153. package/type-guard.js.map +1 -1
  154. package/types.d.ts +10 -1
  155. package/types.global.d.ts +9 -0
  156. package/vibrate.cjs +1 -17
  157. package/vibrate.cjs.map +1 -1
  158. package/vibrate.d.ts +0 -16
  159. package/vibrate.js +1 -17
  160. package/vibrate.js.map +1 -1
  161. /package/{chunk-pbuEa-1d.js → chunk-D7D4PA-g.js} +0 -0
  162. /package/{chunk-CZWwpsFl.cjs → chunk-DakpK96I.cjs} +0 -0
package/random.js CHANGED
@@ -1,20 +1,17 @@
1
- //#region src/random.ts
1
+ //#region src/random/get-frequency-value.ts
2
2
  /**
3
- * ---header-docs-section---
4
- * # yummies/random
5
- *
6
- * ## Description
7
- *
8
- * Small RNG helpers for UI demos, games, and sampling: floats, integers, and random choices from
9
- * arrays. They wrap `Math.random` (not cryptographically secure) so prefer platform `crypto` when
10
- * generating secrets, tokens, or lottery outcomes.
11
- *
12
- * ## Usage
3
+ * Returns `true` with the provided probability from `0` to `1`.
13
4
  *
5
+ * @example
14
6
  * ```ts
15
- * import { getRandomInt, getRandomChoice } from "yummies/random";
7
+ * const shouldRun = getFrequencyValue(0.25);
16
8
  * ```
17
9
  */
10
+ var getFrequencyValue = (frequency) => {
11
+ return Math.random() < frequency;
12
+ };
13
+ //#endregion
14
+ //#region src/random/get-random-float.ts
18
15
  /**
19
16
  * Returns a random floating-point number between `min` and `max`.
20
17
  *
@@ -24,6 +21,8 @@
24
21
  * ```
25
22
  */
26
23
  var getRandomFloat = (min = 0, max = 1) => Math.random() * (max - min) + min;
24
+ //#endregion
25
+ //#region src/random/get-random-int.ts
27
26
  /**
28
27
  * Returns a random integer between `min` and `max`.
29
28
  *
@@ -33,24 +32,34 @@ var getRandomFloat = (min = 0, max = 1) => Math.random() * (max - min) + min;
33
32
  * ```
34
33
  */
35
34
  var getRandomInt = (min = 0, max = 1) => min === max ? min : Math.round(getRandomFloat(min, max));
35
+ //#endregion
36
+ //#region src/random/get-major-random-bool.ts
36
37
  /**
37
- * Picks a random element from the provided array.
38
+ * Returns `true` more often than `false`.
38
39
  *
39
40
  * @example
40
41
  * ```ts
41
- * const fruit = getRandomChoice(['apple', 'banana', 'orange']);
42
+ * const value = getMajorRandomBool();
42
43
  * ```
43
44
  */
44
- var getRandomChoice = (arr) => arr[getRandomInt(0, arr.length - 1)];
45
+ var getMajorRandomBool = () => {
46
+ return getRandomInt(0, 10) <= 6;
47
+ };
48
+ //#endregion
49
+ //#region src/random/get-minor-random-bool.ts
45
50
  /**
46
- * Creates an array filled with `null` values using a random length.
51
+ * Returns `true` less often than `false`.
47
52
  *
48
53
  * @example
49
54
  * ```ts
50
- * const items = getRandomSizeArray(2, 5);
55
+ * const value = getMinorRandomBool();
51
56
  * ```
52
57
  */
53
- var getRandomSizeArray = (min = 0, max = 10) => Array.from({ length: getRandomInt(min, max) }).fill(null);
58
+ var getMinorRandomBool = () => {
59
+ return !getMajorRandomBool();
60
+ };
61
+ //#endregion
62
+ //#region src/random/get-random-bool.ts
54
63
  /**
55
64
  * Returns a uniformly random boolean.
56
65
  *
@@ -60,39 +69,28 @@ var getRandomSizeArray = (min = 0, max = 10) => Array.from({ length: getRandomIn
60
69
  * ```
61
70
  */
62
71
  var getRandomBool = () => getRandomInt(0, 1) === 1;
72
+ //#endregion
73
+ //#region src/random/get-random-choice.ts
63
74
  /**
64
- * Returns `true` more often than `false`.
65
- *
66
- * @example
67
- * ```ts
68
- * const value = getMajorRandomBool();
69
- * ```
70
- */
71
- var getMajorRandomBool = () => {
72
- return getRandomInt(0, 10) <= 6;
73
- };
74
- /**
75
- * Returns `true` less often than `false`.
75
+ * Picks a random element from the provided array.
76
76
  *
77
77
  * @example
78
78
  * ```ts
79
- * const value = getMinorRandomBool();
79
+ * const fruit = getRandomChoice(['apple', 'banana', 'orange']);
80
80
  * ```
81
81
  */
82
- var getMinorRandomBool = () => {
83
- return !getMajorRandomBool();
84
- };
82
+ var getRandomChoice = (arr) => arr[getRandomInt(0, arr.length - 1)];
83
+ //#endregion
84
+ //#region src/random/get-random-size-array.ts
85
85
  /**
86
- * Returns `true` with the provided probability from `0` to `1`.
86
+ * Creates an array filled with `null` values using a random length.
87
87
  *
88
88
  * @example
89
89
  * ```ts
90
- * const shouldRun = getFrequencyValue(0.25);
90
+ * const items = getRandomSizeArray(2, 5);
91
91
  * ```
92
92
  */
93
- var getFrequencyValue = (frequency) => {
94
- return Math.random() < frequency;
95
- };
93
+ var getRandomSizeArray = (min = 0, max = 10) => Array.from({ length: getRandomInt(min, max) }).fill(null);
96
94
  //#endregion
97
95
  export { getFrequencyValue, getMajorRandomBool, getMinorRandomBool, getRandomBool, getRandomChoice, getRandomFloat, getRandomInt, getRandomSizeArray };
98
96
 
package/random.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"random.js","names":[],"sources":["../src/random.ts"],"sourcesContent":["/**\n * ---header-docs-section---\n * # yummies/random\n *\n * ## Description\n *\n * Small RNG helpers for UI demos, games, and sampling: floats, integers, and random choices from\n * arrays. They wrap `Math.random` (not cryptographically secure) so prefer platform `crypto` when\n * generating secrets, tokens, or lottery outcomes.\n *\n * ## Usage\n *\n * ```ts\n * import { getRandomInt, getRandomChoice } from \"yummies/random\";\n * ```\n */\n\n/**\n * Returns a random floating-point number between `min` and `max`.\n *\n * @example\n * ```ts\n * const value = getRandomFloat(1, 10);\n * ```\n */\nexport const getRandomFloat = <T extends number = number>(\n min = 0,\n max = 1,\n): T => (Math.random() * (max - min) + min) as T;\n\n/**\n * Returns a random integer between `min` and `max`.\n *\n * @example\n * ```ts\n * const value = getRandomInt(1, 10);\n * ```\n */\nexport const getRandomInt = <T extends number = number>(min = 0, max = 1): T =>\n min === max ? (min as T) : (Math.round(getRandomFloat(min, max)) as T);\n\n/**\n * Picks a random element from the provided array.\n *\n * @example\n * ```ts\n * const fruit = getRandomChoice(['apple', 'banana', 'orange']);\n * ```\n */\nexport const getRandomChoice = <T>(arr: T[]): T =>\n arr[getRandomInt(0, arr.length - 1)];\n\n/**\n * Creates an array filled with `null` values using a random length.\n *\n * @example\n * ```ts\n * const items = getRandomSizeArray(2, 5);\n * ```\n */\nexport const getRandomSizeArray = (min = 0, max = 10) =>\n Array.from({ length: getRandomInt(min, max) }).fill(null);\n\n/**\n * Returns a uniformly random boolean.\n *\n * @example\n * ```ts\n * const value = getRandomBool();\n * ```\n */\nexport const getRandomBool = () => getRandomInt(0, 1) === 1;\n\n/**\n * Returns `true` more often than `false`.\n *\n * @example\n * ```ts\n * const value = getMajorRandomBool();\n * ```\n */\nexport const getMajorRandomBool = () => {\n return getRandomInt(0, 10) <= 6;\n};\n\n/**\n * Returns `true` less often than `false`.\n *\n * @example\n * ```ts\n * const value = getMinorRandomBool();\n * ```\n */\nexport const getMinorRandomBool = () => {\n return !getMajorRandomBool();\n};\n\n/**\n * Returns `true` with the provided probability from `0` to `1`.\n *\n * @example\n * ```ts\n * const shouldRun = getFrequencyValue(0.25);\n * ```\n */\nexport const getFrequencyValue = (frequency: number) => {\n return Math.random() < frequency;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAyBA,IAAa,kBACX,MAAM,GACN,MAAM,MACC,KAAK,QAAQ,IAAI,MAAM,OAAO;;;;;;;;;AAUvC,IAAa,gBAA2C,MAAM,GAAG,MAAM,MACrE,QAAQ,MAAO,MAAa,KAAK,MAAM,eAAe,KAAK,IAAI,CAAC;;;;;;;;;AAUlE,IAAa,mBAAsB,QACjC,IAAI,aAAa,GAAG,IAAI,SAAS,EAAE;;;;;;;;;AAUrC,IAAa,sBAAsB,MAAM,GAAG,MAAM,OAChD,MAAM,KAAK,EAAE,QAAQ,aAAa,KAAK,IAAI,EAAE,CAAC,CAAC,KAAK,KAAK;;;;;;;;;AAU3D,IAAa,sBAAsB,aAAa,GAAG,EAAE,KAAK;;;;;;;;;AAU1D,IAAa,2BAA2B;AACtC,QAAO,aAAa,GAAG,GAAG,IAAI;;;;;;;;;;AAWhC,IAAa,2BAA2B;AACtC,QAAO,CAAC,oBAAoB;;;;;;;;;;AAW9B,IAAa,qBAAqB,cAAsB;AACtD,QAAO,KAAK,QAAQ,GAAG"}
1
+ {"version":3,"file":"random.js","names":[],"sources":["../src/random/get-frequency-value.ts","../src/random/get-random-float.ts","../src/random/get-random-int.ts","../src/random/get-major-random-bool.ts","../src/random/get-minor-random-bool.ts","../src/random/get-random-bool.ts","../src/random/get-random-choice.ts","../src/random/get-random-size-array.ts"],"sourcesContent":["/**\n * Returns `true` with the provided probability from `0` to `1`.\n *\n * @example\n * ```ts\n * const shouldRun = getFrequencyValue(0.25);\n * ```\n */\nexport const getFrequencyValue = (frequency: number) => {\n return Math.random() < frequency;\n};\n","/**\n * Returns a random floating-point number between `min` and `max`.\n *\n * @example\n * ```ts\n * const value = getRandomFloat(1, 10);\n * ```\n */\nexport const getRandomFloat = <T extends number = number>(\n min = 0,\n max = 1,\n): T => (Math.random() * (max - min) + min) as T;\n","import { getRandomFloat } from './get-random-float.js';\n\n/**\n * Returns a random integer between `min` and `max`.\n *\n * @example\n * ```ts\n * const value = getRandomInt(1, 10);\n * ```\n */\nexport const getRandomInt = <T extends number = number>(min = 0, max = 1): T =>\n min === max ? (min as T) : (Math.round(getRandomFloat(min, max)) as T);\n","import { getRandomInt } from './get-random-int.js';\n\n/**\n * Returns `true` more often than `false`.\n *\n * @example\n * ```ts\n * const value = getMajorRandomBool();\n * ```\n */\nexport const getMajorRandomBool = () => {\n return getRandomInt(0, 10) <= 6;\n};\n","import { getMajorRandomBool } from './get-major-random-bool.js';\n\n/**\n * Returns `true` less often than `false`.\n *\n * @example\n * ```ts\n * const value = getMinorRandomBool();\n * ```\n */\nexport const getMinorRandomBool = () => {\n return !getMajorRandomBool();\n};\n","import { getRandomInt } from './get-random-int.js';\n\n/**\n * Returns a uniformly random boolean.\n *\n * @example\n * ```ts\n * const value = getRandomBool();\n * ```\n */\nexport const getRandomBool = () => getRandomInt(0, 1) === 1;\n","import { getRandomInt } from './get-random-int.js';\n\n/**\n * Picks a random element from the provided array.\n *\n * @example\n * ```ts\n * const fruit = getRandomChoice(['apple', 'banana', 'orange']);\n * ```\n */\nexport const getRandomChoice = <T>(arr: T[]): T =>\n arr[getRandomInt(0, arr.length - 1)];\n","import { getRandomInt } from './get-random-int.js';\n\n/**\n * Creates an array filled with `null` values using a random length.\n *\n * @example\n * ```ts\n * const items = getRandomSizeArray(2, 5);\n * ```\n */\nexport const getRandomSizeArray = (min = 0, max = 10) =>\n Array.from({ length: getRandomInt(min, max) }).fill(null);\n"],"mappings":";;;;;;;;;AAQA,IAAa,qBAAqB,cAAsB;CACtD,OAAO,KAAK,OAAO,IAAI;AACzB;;;;;;;;;;;ACFA,IAAa,kBACX,MAAM,GACN,MAAM,MACC,KAAK,OAAO,KAAK,MAAM,OAAO;;;;;;;;;;;ACDvC,IAAa,gBAA2C,MAAM,GAAG,MAAM,MACrE,QAAQ,MAAO,MAAa,KAAK,MAAM,eAAe,KAAK,GAAG,CAAC;;;;;;;;;;;ACDjE,IAAa,2BAA2B;CACtC,OAAO,aAAa,GAAG,EAAE,KAAK;AAChC;;;;;;;;;;;ACFA,IAAa,2BAA2B;CACtC,OAAO,CAAC,mBAAmB;AAC7B;;;;;;;;;;;ACFA,IAAa,sBAAsB,aAAa,GAAG,CAAC,MAAM;;;;;;;;;;;ACA1D,IAAa,mBAAsB,QACjC,IAAI,aAAa,GAAG,IAAI,SAAS,CAAC;;;;;;;;;;;ACDpC,IAAa,sBAAsB,MAAM,GAAG,MAAM,OAChD,MAAM,KAAK,EAAE,QAAQ,aAAa,KAAK,GAAG,EAAE,CAAC,EAAE,KAAK,IAAI"}
package/react.cjs CHANGED
@@ -1,5 +1,4 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- require("./chunk-CZWwpsFl.cjs");
3
2
  let react = require("react");
4
3
  //#region src/react/attach-refs.ts
5
4
  /**
package/react.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"react.cjs","names":[],"sources":["../src/react/attach-refs.ts","../src/react/hooks/use-constant.ts","../src/react/hooks/use-abort-controller.ts","../src/react/hooks/use-abort-signal.ts","../src/react/hooks/use-sync-ref.ts","../src/react/hooks/use-event-listener.ts","../src/react/hooks/use-click-outside.ts","../src/react/hooks/use-define-ref.ts","../src/react/hooks/use-element-ref.ts","../src/react/hooks/use-event.ts","../src/react/hooks/use-flag.ts","../src/react/hooks/use-force-update.ts","../src/react/hooks/use-initial-height.ts","../src/react/hooks/use-instance.ts","../src/react/hooks/use-intersection-observer.ts","../src/react/hooks/use-last-defined-value.ts","../src/react/hooks/use-last-value-ref.ts","../src/react/hooks/use-life-cycle.ts","../src/react/hooks/use-resize-observer.ts","../src/react/hooks/use-toggle.ts","../src/react/hooks/use-value.ts","../src/react/hooks/use-visibility-state.ts"],"sourcesContent":["import type { LegacyRef, RefObject } from 'react';\nimport type { Maybe } from 'yummies/types';\n\n/**\n * Assigns the same value to multiple React refs, including callback refs.\n *\n * @template T Referenced value type.\n * @param value Value that should be written into every provided ref.\n * @param refs Target refs to update.\n *\n * @example\n * ```ts\n * attachRefs(node, localRef, forwardedRef);\n * ```\n *\n * @example\n * ```ts\n * attachRefs(null, inputRef, (value) => console.log(value));\n * ```\n */\nexport const attachRefs = <T>(\n value: T | null,\n ...refs: Maybe<RefObject<T> | RefObject<T | null> | LegacyRef<T>>[]\n) =>\n refs.forEach((ref) => {\n if (typeof ref === 'function') {\n ref(value);\n } else if (ref && typeof ref !== 'string') {\n // @ts-expect-error\n ref.current = value;\n }\n });\n","import { useRef } from 'react';\n\n/**\n * React hook for creating a value exactly once.\n *\n * Unlike `useMemo`, this guarantees that the initializer is executed only once\n * for the component lifetime.\n *\n * @template T Value type.\n * @param defineValue Function that lazily creates the value.\n * @returns Stable value created on the first render.\n *\n * @example\n * ```ts\n * const id = useConstant(() => crypto.randomUUID());\n * ```\n *\n * @example\n * ```ts\n * const formatter = useConstant(() => new Intl.NumberFormat('en-US'));\n * ```\n */\nexport const useConstant = <T>(defineValue: () => T): T => {\n const ref = useRef<{ value: T }>();\n\n if (!ref.current) {\n ref.current = { value: defineValue() };\n }\n\n return ref.current.value;\n};\n","import { useEffect } from 'react';\n\nimport { useConstant } from './use-constant.js';\n\n/**\n * Creates a single `AbortController` instance for the component lifetime.\n *\n * The controller is aborted automatically during unmount.\n *\n * @returns Stable abort controller instance.\n *\n * @example\n * ```ts\n * const controller = useAbortController();\n * fetch('/api', { signal: controller.signal });\n * ```\n *\n * @example\n * ```ts\n * const controller = useAbortController();\n * controller.abort();\n * ```\n */\nexport const useAbortController = () => {\n const controller = useConstant(() => new AbortController());\n\n useEffect(() => {\n return () => {\n controller.abort();\n };\n }, []);\n\n return controller;\n};\n","import { useAbortController } from './use-abort-controller.js';\n\n/**\n * Returns an `AbortSignal` tied to the component lifecycle.\n *\n * The signal is aborted automatically on unmount.\n *\n * @returns Lifecycle-bound abort signal.\n *\n * @example\n * ```ts\n * const signal = useAbortSignal();\n * fetch('/api/users', { signal });\n * ```\n *\n * @example\n * ```ts\n * const signal = useAbortSignal();\n * someAsyncTask({ signal });\n * ```\n */\nexport const useAbortSignal = () => {\n return useAbortController().signal;\n};\n","import { useRef } from 'react';\n\n/**\n * Returns a ref whose `current` value is synchronized with the latest input\n * on every render.\n *\n * @template T Value type.\n * @param value Current value to expose through the ref.\n * @returns Ref containing the latest value.\n *\n * @example\n * ```ts\n * const latestHandler = useSyncRef(onSubmit);\n * latestHandler.current();\n * ```\n *\n * @example\n * ```ts\n * const latestValue = useSyncRef(props.value);\n * latestValue.current;\n * ```\n */\nexport const useSyncRef = <T>(value: T) => {\n const ref = useRef(value);\n ref.current = value;\n return ref;\n};\n","/* eslint-disable @typescript-eslint/ban-ts-comment */\nimport { useEffect } from 'react';\nimport { useSyncRef } from './use-sync-ref.js';\n\n/**\n * Subscribes to a DOM event and keeps the latest handler without resubscribing\n * on every render.\n *\n * Supports optional debounce and custom effect dependencies.\n *\n * @template EventName DOM event name from `HTMLElementEventMap`.\n * @param config Event subscription configuration.\n *\n * @example\n * ```ts\n * useEventListener({\n * event: 'click',\n * handler: () => console.log('clicked'),\n * });\n * ```\n *\n * @example\n * ```ts\n * useEventListener({\n * event: 'scroll',\n * node: window,\n * debounce: 100,\n * handler: () => console.log('scroll'),\n * });\n * ```\n */\nexport const useEventListener = <EventName extends keyof HTMLElementEventMap>({\n event,\n handler,\n options,\n deps = [],\n debounce,\n node = document,\n}: {\n event: EventName;\n handler: (e: HTMLElementEventMap[EventName]) => void;\n options?: boolean | AddEventListenerOptions;\n deps?: unknown[];\n debounce?: number;\n node?: HTMLElement | Document | Window;\n}) => {\n const handlerRef = useSyncRef(handler);\n\n useEffect(() => {\n let timerId: ReturnType<typeof setTimeout> | undefined;\n\n const handleEvent = (e: HTMLElementEventMap[EventName]) => {\n if (debounce == null) {\n handlerRef.current(e);\n } else {\n clearTimeout(timerId);\n timerId = setTimeout(() => {\n handlerRef.current(e);\n timerId = undefined;\n }, debounce);\n }\n };\n\n // @ts-expect-error\n node.addEventListener(event, handleEvent, options);\n return () => {\n // @ts-expect-error\n node.removeEventListener(event, handleEvent, options);\n clearTimeout(timerId);\n };\n }, deps);\n};\n","import type { MutableRefObject } from 'react';\nimport { useEventListener } from './use-event-listener.js';\n\ntype ClickOutsideInput = {\n contentRef: MutableRefObject<HTMLElement | null>;\n onClick: VoidFunction;\n options?: AddEventListenerOptions;\n};\n\n/**\n * Calls a handler when a pointer interaction happens outside the referenced element.\n *\n * @param input Target element ref, callback and event listener options.\n *\n * @example\n * ```ts\n * useClickOutside({\n * contentRef: modalRef,\n * onClick: () => closeModal(),\n * });\n * ```\n *\n * @example\n * ```ts\n * useClickOutside({\n * contentRef: dropdownRef,\n * onClick: hideDropdown,\n * options: { capture: true },\n * });\n * ```\n */\nexport const useClickOutside = ({\n contentRef,\n onClick,\n options,\n}: ClickOutsideInput) => {\n useEventListener({\n event: 'mousedown',\n handler: (event) => {\n if (\n contentRef.current &&\n !contentRef.current.contains(event.target as Node)\n ) {\n onClick();\n }\n },\n options,\n });\n};\n","import { type MutableRefObject, useRef } from 'react';\n\n/**\n * Creates a mutable ref whose value is initialized exactly once.\n *\n * @template T Ref value type.\n * @param defineFn Function that lazily creates the initial ref value.\n * @returns Mutable ref with a stable initialized value.\n *\n * @example\n * ```ts\n * const cacheRef = useDefineRef(() => new Map());\n * ```\n *\n * @example\n * ```ts\n * const observerRef = useDefineRef(() => new ResizeObserver(() => {}));\n * ```\n */\nexport const useDefineRef = <T>(defineFn: () => T): MutableRefObject<T> => {\n const ref = useRef<T>(void 0 as T);\n\n if (!ref.current) {\n ref.current = defineFn();\n }\n\n return ref;\n};\n","import { useLayoutEffect, useRef } from 'react';\n\n/**\n * Resolves an element once after mount and stores it in a ref.\n *\n * @template T Element type.\n * @param selector Function returning the target element.\n * @returns Ref containing the selected element.\n *\n * @example\n * ```ts\n * const buttonRef = useElementRef(() => document.getElementById('save') as HTMLButtonElement);\n * ```\n *\n * @example\n * ```ts\n * const modalRef = useElementRef(() => document.querySelector('.modal') as HTMLDivElement);\n * ```\n */\nexport const useElementRef = <T extends HTMLElement>(selector: () => T) => {\n const ref = useRef<T>();\n\n useLayoutEffect(() => {\n ref.current = selector();\n }, []);\n\n return ref;\n};\n","import { useCallback, useLayoutEffect, useRef } from 'react';\nimport type { AnyFunction } from 'yummies/types';\n\n/**\n * Creates an event callback with a stable function identity and up-to-date logic.\n *\n * Borrowed from the `useEvent` RFC idea by React contributors.\n *\n * @template H Handler function type.\n * @param handler Latest callback implementation.\n * @returns Stable callback that always delegates to the latest handler.\n *\n * @example\n * ```ts\n * const onClick = useEvent(() => {\n * console.log('clicked');\n * });\n * ```\n *\n * @example\n * ```ts\n * const onSubmit = useEvent((value: string) => save(value));\n * ```\n */\nexport const useEvent = <H extends AnyFunction>(handler: H): H => {\n const handlerRef = useRef<H>(handler);\n\n // In a real implementation, this would run before layout effects\n useLayoutEffect(() => {\n handlerRef.current = handler;\n });\n\n return useCallback((...args: unknown[]) => {\n // In a real implementation, this would throw if called during render\n const fn = handlerRef.current as AnyFunction;\n return fn(...args);\n }, []) as unknown as H;\n};\n","import { useCallback, useRef, useState } from 'react';\n\nexport interface FlagHook {\n enabled: boolean;\n toggle: VoidFunction;\n enable: VoidFunction;\n disable: VoidFunction;\n}\n\n/**\n * Manages a reusable boolean flag object with stable helper methods.\n *\n * @param defaultValue Initial enabled state.\n * @returns Stable object exposing current state and mutators.\n *\n * @example\n * ```ts\n * const modal = useFlag();\n * modal.enable();\n * ```\n *\n * @example\n * ```ts\n * const loading = useFlag(true);\n * loading.disable();\n * ```\n */\nexport const useFlag = (defaultValue = false): FlagHook => {\n const [enabled, setEnabled] = useState(defaultValue);\n\n const toggle = useCallback(() => setEnabled((value) => !value), []);\n const enable = useCallback(() => setEnabled(true), []);\n const disable = useCallback(() => setEnabled(false), []);\n\n const flagObjRef = useRef<FlagHook>({\n enabled,\n toggle,\n enable,\n disable,\n });\n\n flagObjRef.current.enabled = enabled;\n\n return flagObjRef.current;\n};\n","import { useCallback, useState } from 'react';\n\n/**\n * Forces a component re-render by updating an internal dummy state.\n *\n * @returns Stable callback that triggers a re-render.\n *\n * @example\n * ```ts\n * const forceUpdate = useForceUpdate();\n * forceUpdate();\n * ```\n *\n * @example\n * ```ts\n * const rerender = useForceUpdate();\n * setTimeout(rerender, 1000);\n * ```\n */\nexport const useForceUpdate = () => {\n const [, setState] = useState<unknown>(null);\n\n return useCallback(() => {\n setState({});\n }, []);\n};\n","import { useEffect, useRef, useState } from 'react';\n\n/**\n * Captures an element's height the first time its ref becomes available.\n *\n * @template T Element type attached to the returned ref.\n * @returns Ref and the initial measured height.\n *\n * @example\n * ```ts\n * const { ref, initialHeight } = useInitialHeight<HTMLDivElement>();\n * ```\n *\n * @example\n * ```ts\n * const state = useInitialHeight<HTMLTextAreaElement>();\n * state.initialHeight;\n * ```\n */\nexport const useInitialHeight = <T extends HTMLElement>() => {\n const ref = useRef<T | null>(null);\n const [initialHeight, setInitialHeight] = useState<number | undefined>(\n undefined,\n );\n\n useEffect(() => {\n if (ref.current && !initialHeight) {\n setInitialHeight(ref.current.offsetHeight);\n }\n }, [initialHeight]);\n\n return { ref, initialHeight };\n};\n","import { useLayoutEffect } from 'react';\nimport { useAbortSignal } from './use-abort-signal.js';\nimport { useConstant } from './use-constant.js';\n\nexport type InstanceCreateConfig<TPayload, TExtension = {}> = TExtension & {\n abortSignal: AbortSignal;\n payload: TPayload;\n};\n\n/**\n * Builds a custom hook that creates an instance once and wires lifecycle helpers\n * such as an `AbortSignal` and optional extension data into the factory.\n *\n * @template TExtension Extra configuration injected into every factory call.\n * @param extension Optional static extension object merged into the factory config.\n * @returns Hook factory that creates stable instances from a supplied factory.\n *\n * @example\n * ```ts\n * const useStoreInstance = createUseInstanceHook({ api });\n * ```\n *\n * @example\n * ```ts\n * const useService = createUseInstanceHook({ logger });\n * const service = useService(({ logger, payload }) => new Service(logger, payload));\n * ```\n */\nexport const createUseInstanceHook =\n <TExtension = {}>(extension?: TExtension) =>\n <TInstance, TPayload>(\n factory: (\n config: InstanceCreateConfig<NoInfer<TPayload>, TExtension>,\n ) => TInstance,\n config?: {\n payload?: TPayload;\n onUpdate?: (payload: TPayload) => void;\n },\n ) => {\n const abortSignal = useAbortSignal();\n\n const instance = useConstant(() =>\n factory({\n ...(extension as TExtension),\n abortSignal,\n payload: config?.payload as any,\n }),\n );\n\n useLayoutEffect(() => {\n config?.onUpdate?.(config.payload!);\n }, [config?.payload]);\n\n return instance;\n };\n\n/**\n * The `useInstance` hook is used to create and manage an instance of an object\n * that requires access to the root store and an abort signal.\n *\n * You can create YOUR OWN CUSTOM `useInstance` hook using `createUseInstanceHook` if you need\n * to provide some specific data\n *\n * @param factory - A factory function that takes a configuration and returns an instance.\n * @param config - An optional configuration containing additional input parameters and an update function.\n * @returns An instance created by the factory function.\n *\n * @example\n * ```ts\n * const service = useInstance(({ abortSignal }) => new UsersService({ abortSignal }));\n * ```\n *\n * @example\n * ```ts\n * const store = useInstance(\n * ({ payload }) => new UserStore(payload),\n * { payload: userId, onUpdate: (nextId) => console.log(nextId) },\n * );\n * ```\n */\nexport const useInstance = createUseInstanceHook();\n","import { useEffect, useState } from 'react';\n\n/**\n * Creates a single `IntersectionObserver` instance and disposes it on unmount.\n *\n * @param callback Observer callback invoked for intersection changes.\n * @param options Optional observer configuration.\n * @returns Stable `IntersectionObserver` instance.\n *\n * @example\n * ```ts\n * const observer = useIntersectionObserver((entries) => {\n * console.log(entries[0]?.isIntersecting);\n * });\n * ```\n *\n * @example\n * ```ts\n * const observer = useIntersectionObserver(handleIntersect, { threshold: 0.5 });\n * observer.observe(element);\n * ```\n */\nexport const useIntersectionObserver = (\n callback: IntersectionObserverCallback,\n options?: IntersectionObserverInit,\n) => {\n const [intersectionObserver] = useState(\n () => new IntersectionObserver(callback, options),\n );\n\n useEffect(() => {\n return () => {\n intersectionObserver.disconnect();\n };\n }, []);\n\n return intersectionObserver;\n};\n","import { useRef } from 'react';\n\n/**\n * Remembers and returns the last non-nullish value passed to the hook.\n *\n * @template T Value type.\n * @param value Current value that may be `null` or `undefined`.\n * @returns Current value when defined, otherwise the previous defined value.\n *\n * @example\n * ```ts\n * const title = useLastDefinedValue(props.title);\n * ```\n *\n * @example\n * ```ts\n * const user = useLastDefinedValue<User | null>(selectedUser);\n * ```\n */\nexport const useLastDefinedValue = <T>(value: T) => {\n const ref = useRef(value);\n if (value != null) {\n ref.current = value;\n }\n return ref.current;\n};\n","import { useRef } from 'react';\n\n/**\n * Returns a ref that always points to the last non-nullish value.\n *\n * @template T Value type.\n * @param value Current value that may temporarily become `null` or `undefined`.\n * @returns Ref containing the last defined value.\n *\n * @example\n * ```ts\n * const latestUserRef = useLastValueRef(user);\n * latestUserRef.current;\n * ```\n *\n * @example\n * ```ts\n * const latestNodeRef = useLastValueRef<HTMLDivElement | null>(node);\n * ```\n */\nexport const useLastValueRef = <T>(value: T | null | undefined) => {\n const ref = useRef(value);\n\n if (value != null) {\n ref.current = value;\n }\n\n return ref;\n};\n","import { useEffect } from 'react';\nimport { useSyncRef } from './use-sync-ref.js';\n\n/**\n * Runs mount and unmount callbacks returned by a factory function.\n *\n * The latest factory is stored in a ref, while the effect itself is only\n * subscribed once.\n *\n * @param fn Factory returning optional `mount` and `unmount` handlers.\n *\n * @example\n * ```ts\n * useLifeCycle(() => ({\n * mount: () => console.log('mounted'),\n * unmount: () => console.log('unmounted'),\n * }));\n * ```\n *\n * @example\n * ```ts\n * useLifeCycle(() => ({\n * mount: subscribe,\n * unmount: unsubscribe,\n * }));\n * ```\n */\nexport const useLifeCycle = (\n fn: () => {\n mount?: VoidFunction;\n unmount?: VoidFunction;\n },\n) => {\n const fnRef = useSyncRef(fn);\n\n useEffect(() => {\n const fnOperation = fnRef.current();\n fnOperation.mount?.();\n return fnOperation.unmount?.();\n }, []);\n};\n","import { useLayoutEffect } from 'react';\nimport { useDefineRef } from './use-define-ref.js';\n\n/**\n * Creates a stable `ResizeObserver` instance and disconnects it on unmount.\n *\n * @param callback Resize observer callback.\n * @returns Ref containing the observer instance.\n *\n * @example\n * ```ts\n * const observerRef = useResizeObserver((entries) => {\n * console.log(entries[0]?.contentRect.width);\n * });\n * ```\n *\n * @example\n * ```ts\n * const resizeObserver = useResizeObserver(handleResize);\n * resizeObserver.current.observe(element);\n * ```\n */\nexport const useResizeObserver = (callback: ResizeObserverCallback) => {\n const resizeObserverRef = useDefineRef(() => new ResizeObserver(callback));\n\n useLayoutEffect(() => {\n return () => {\n resizeObserverRef.current.disconnect();\n };\n }, []);\n\n return resizeObserverRef;\n};\n","import { useCallback, useState } from 'react';\n\n/**\n * Manages a boolean state and returns helpers to toggle or set it directly.\n *\n * @param initialState Initial boolean value.\n * @returns Tuple with current state, toggle callback and raw setter.\n *\n * @example\n * ```ts\n * const [open, toggleOpen] = useToggle();\n * toggleOpen();\n * ```\n *\n * @example\n * ```ts\n * const [enabled, , setEnabled] = useToggle(true);\n * setEnabled(false);\n * ```\n */\nexport const useToggle = (initialState?: boolean) => {\n const [toggled, setToggled] = useState(!!initialState);\n\n const toggle = useCallback(() => setToggled((toggled) => !toggled), []);\n\n return [toggled, toggle, setToggled] as const;\n};\n","import { useState } from 'react';\n\n/**\n * Wraps `useState` and returns the state value as an object with a `set` method.\n *\n * @template T State value type.\n * @param defaults Initial state value or lazy initializer.\n * @returns Object containing the current value and setter.\n *\n * @example\n * ```ts\n * const counter = useValue(0);\n * counter.set(1);\n * ```\n *\n * @example\n * ```ts\n * const user = useValue(() => ({ name: 'Ann' }));\n * user.value.name;\n * ```\n */\nexport const useValue = <T>(defaults: T | (() => T)) => {\n const [value, setValue] = useState<T>(defaults);\n\n return {\n value,\n set: setValue,\n };\n};\n","import { useEffect, useState } from 'react';\n\n/**\n * Tracks `document.visibilityState` and updates when the page visibility changes.\n *\n * @returns Current document visibility state.\n *\n * @example\n * ```ts\n * const visibility = useVisibilityState();\n * ```\n *\n * @example\n * ```ts\n * const isHidden = useVisibilityState() === 'hidden';\n * ```\n */\nexport const useVisibilityState = () => {\n const [state, setState] = useState<DocumentVisibilityState>();\n\n useEffect(() => {\n const handleVisibilityChange = () => {\n setState(document.visibilityState);\n };\n\n document.addEventListener('visibilitychange', handleVisibilityChange);\n\n return () => {\n document.removeEventListener('visibilitychange', handleVisibilityChange);\n };\n }, []);\n\n return state;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"react.cjs","names":[],"sources":["../src/react/attach-refs.ts","../src/react/hooks/use-constant.ts","../src/react/hooks/use-abort-controller.ts","../src/react/hooks/use-abort-signal.ts","../src/react/hooks/use-sync-ref.ts","../src/react/hooks/use-event-listener.ts","../src/react/hooks/use-click-outside.ts","../src/react/hooks/use-define-ref.ts","../src/react/hooks/use-element-ref.ts","../src/react/hooks/use-event.ts","../src/react/hooks/use-flag.ts","../src/react/hooks/use-force-update.ts","../src/react/hooks/use-initial-height.ts","../src/react/hooks/use-instance.ts","../src/react/hooks/use-intersection-observer.ts","../src/react/hooks/use-last-defined-value.ts","../src/react/hooks/use-last-value-ref.ts","../src/react/hooks/use-life-cycle.ts","../src/react/hooks/use-resize-observer.ts","../src/react/hooks/use-toggle.ts","../src/react/hooks/use-value.ts","../src/react/hooks/use-visibility-state.ts"],"sourcesContent":["import type { LegacyRef, RefObject } from 'react';\nimport type { Maybe } from 'yummies/types';\n\n/**\n * Assigns the same value to multiple React refs, including callback refs.\n *\n * @template T Referenced value type.\n * @param value Value that should be written into every provided ref.\n * @param refs Target refs to update.\n *\n * @example\n * ```ts\n * attachRefs(node, localRef, forwardedRef);\n * ```\n *\n * @example\n * ```ts\n * attachRefs(null, inputRef, (value) => console.log(value));\n * ```\n */\nexport const attachRefs = <T>(\n value: T | null,\n ...refs: Maybe<RefObject<T> | RefObject<T | null> | LegacyRef<T>>[]\n) =>\n refs.forEach((ref) => {\n if (typeof ref === 'function') {\n ref(value);\n } else if (ref && typeof ref !== 'string') {\n // @ts-expect-error\n ref.current = value;\n }\n });\n","import { useRef } from 'react';\n\n/**\n * React hook for creating a value exactly once.\n *\n * Unlike `useMemo`, this guarantees that the initializer is executed only once\n * for the component lifetime.\n *\n * @template T Value type.\n * @param defineValue Function that lazily creates the value.\n * @returns Stable value created on the first render.\n *\n * @example\n * ```ts\n * const id = useConstant(() => crypto.randomUUID());\n * ```\n *\n * @example\n * ```ts\n * const formatter = useConstant(() => new Intl.NumberFormat('en-US'));\n * ```\n */\nexport const useConstant = <T>(defineValue: () => T): T => {\n const ref = useRef<{ value: T }>();\n\n if (!ref.current) {\n ref.current = { value: defineValue() };\n }\n\n return ref.current.value;\n};\n","import { useEffect } from 'react';\n\nimport { useConstant } from './use-constant.js';\n\n/**\n * Creates a single `AbortController` instance for the component lifetime.\n *\n * The controller is aborted automatically during unmount.\n *\n * @returns Stable abort controller instance.\n *\n * @example\n * ```ts\n * const controller = useAbortController();\n * fetch('/api', { signal: controller.signal });\n * ```\n *\n * @example\n * ```ts\n * const controller = useAbortController();\n * controller.abort();\n * ```\n */\nexport const useAbortController = () => {\n const controller = useConstant(() => new AbortController());\n\n useEffect(() => {\n return () => {\n controller.abort();\n };\n }, []);\n\n return controller;\n};\n","import { useAbortController } from './use-abort-controller.js';\n\n/**\n * Returns an `AbortSignal` tied to the component lifecycle.\n *\n * The signal is aborted automatically on unmount.\n *\n * @returns Lifecycle-bound abort signal.\n *\n * @example\n * ```ts\n * const signal = useAbortSignal();\n * fetch('/api/users', { signal });\n * ```\n *\n * @example\n * ```ts\n * const signal = useAbortSignal();\n * someAsyncTask({ signal });\n * ```\n */\nexport const useAbortSignal = () => {\n return useAbortController().signal;\n};\n","import { useRef } from 'react';\n\n/**\n * Returns a ref whose `current` value is synchronized with the latest input\n * on every render.\n *\n * @template T Value type.\n * @param value Current value to expose through the ref.\n * @returns Ref containing the latest value.\n *\n * @example\n * ```ts\n * const latestHandler = useSyncRef(onSubmit);\n * latestHandler.current();\n * ```\n *\n * @example\n * ```ts\n * const latestValue = useSyncRef(props.value);\n * latestValue.current;\n * ```\n */\nexport const useSyncRef = <T>(value: T) => {\n const ref = useRef(value);\n ref.current = value;\n return ref;\n};\n","/* eslint-disable @typescript-eslint/ban-ts-comment */\nimport { useEffect } from 'react';\nimport { useSyncRef } from './use-sync-ref.js';\n\n/**\n * Subscribes to a DOM event and keeps the latest handler without resubscribing\n * on every render.\n *\n * Supports optional debounce and custom effect dependencies.\n *\n * @template EventName DOM event name from `HTMLElementEventMap`.\n * @param config Event subscription configuration.\n *\n * @example\n * ```ts\n * useEventListener({\n * event: 'click',\n * handler: () => console.log('clicked'),\n * });\n * ```\n *\n * @example\n * ```ts\n * useEventListener({\n * event: 'scroll',\n * node: window,\n * debounce: 100,\n * handler: () => console.log('scroll'),\n * });\n * ```\n */\nexport const useEventListener = <EventName extends keyof HTMLElementEventMap>({\n event,\n handler,\n options,\n deps = [],\n debounce,\n node = document,\n}: {\n event: EventName;\n handler: (e: HTMLElementEventMap[EventName]) => void;\n options?: boolean | AddEventListenerOptions;\n deps?: unknown[];\n debounce?: number;\n node?: HTMLElement | Document | Window;\n}) => {\n const handlerRef = useSyncRef(handler);\n\n useEffect(() => {\n let timerId: ReturnType<typeof setTimeout> | undefined;\n\n const handleEvent = (e: HTMLElementEventMap[EventName]) => {\n if (debounce == null) {\n handlerRef.current(e);\n } else {\n clearTimeout(timerId);\n timerId = setTimeout(() => {\n handlerRef.current(e);\n timerId = undefined;\n }, debounce);\n }\n };\n\n // @ts-expect-error\n node.addEventListener(event, handleEvent, options);\n return () => {\n // @ts-expect-error\n node.removeEventListener(event, handleEvent, options);\n clearTimeout(timerId);\n };\n }, deps);\n};\n","import type { MutableRefObject } from 'react';\nimport { useEventListener } from './use-event-listener.js';\n\ntype ClickOutsideInput = {\n contentRef: MutableRefObject<HTMLElement | null>;\n onClick: VoidFunction;\n options?: AddEventListenerOptions;\n};\n\n/**\n * Calls a handler when a pointer interaction happens outside the referenced element.\n *\n * @param input Target element ref, callback and event listener options.\n *\n * @example\n * ```ts\n * useClickOutside({\n * contentRef: modalRef,\n * onClick: () => closeModal(),\n * });\n * ```\n *\n * @example\n * ```ts\n * useClickOutside({\n * contentRef: dropdownRef,\n * onClick: hideDropdown,\n * options: { capture: true },\n * });\n * ```\n */\nexport const useClickOutside = ({\n contentRef,\n onClick,\n options,\n}: ClickOutsideInput) => {\n useEventListener({\n event: 'mousedown',\n handler: (event) => {\n if (\n contentRef.current &&\n !contentRef.current.contains(event.target as Node)\n ) {\n onClick();\n }\n },\n options,\n });\n};\n","import { type MutableRefObject, useRef } from 'react';\n\n/**\n * Creates a mutable ref whose value is initialized exactly once.\n *\n * @template T Ref value type.\n * @param defineFn Function that lazily creates the initial ref value.\n * @returns Mutable ref with a stable initialized value.\n *\n * @example\n * ```ts\n * const cacheRef = useDefineRef(() => new Map());\n * ```\n *\n * @example\n * ```ts\n * const observerRef = useDefineRef(() => new ResizeObserver(() => {}));\n * ```\n */\nexport const useDefineRef = <T>(defineFn: () => T): MutableRefObject<T> => {\n const ref = useRef<T>(void 0 as T);\n\n if (!ref.current) {\n ref.current = defineFn();\n }\n\n return ref;\n};\n","import { useLayoutEffect, useRef } from 'react';\n\n/**\n * Resolves an element once after mount and stores it in a ref.\n *\n * @template T Element type.\n * @param selector Function returning the target element.\n * @returns Ref containing the selected element.\n *\n * @example\n * ```ts\n * const buttonRef = useElementRef(() => document.getElementById('save') as HTMLButtonElement);\n * ```\n *\n * @example\n * ```ts\n * const modalRef = useElementRef(() => document.querySelector('.modal') as HTMLDivElement);\n * ```\n */\nexport const useElementRef = <T extends HTMLElement>(selector: () => T) => {\n const ref = useRef<T>();\n\n useLayoutEffect(() => {\n ref.current = selector();\n }, []);\n\n return ref;\n};\n","import { useCallback, useLayoutEffect, useRef } from 'react';\nimport type { AnyFunction } from 'yummies/types';\n\n/**\n * Creates an event callback with a stable function identity and up-to-date logic.\n *\n * Borrowed from the `useEvent` RFC idea by React contributors.\n *\n * @template H Handler function type.\n * @param handler Latest callback implementation.\n * @returns Stable callback that always delegates to the latest handler.\n *\n * @example\n * ```ts\n * const onClick = useEvent(() => {\n * console.log('clicked');\n * });\n * ```\n *\n * @example\n * ```ts\n * const onSubmit = useEvent((value: string) => save(value));\n * ```\n */\nexport const useEvent = <H extends AnyFunction>(handler: H): H => {\n const handlerRef = useRef<H>(handler);\n\n // In a real implementation, this would run before layout effects\n useLayoutEffect(() => {\n handlerRef.current = handler;\n });\n\n return useCallback((...args: unknown[]) => {\n // In a real implementation, this would throw if called during render\n const fn = handlerRef.current as AnyFunction;\n return fn(...args);\n }, []) as unknown as H;\n};\n","import { useCallback, useRef, useState } from 'react';\n\nexport interface FlagHook {\n enabled: boolean;\n toggle: VoidFunction;\n enable: VoidFunction;\n disable: VoidFunction;\n}\n\n/**\n * Manages a reusable boolean flag object with stable helper methods.\n *\n * @param defaultValue Initial enabled state.\n * @returns Stable object exposing current state and mutators.\n *\n * @example\n * ```ts\n * const modal = useFlag();\n * modal.enable();\n * ```\n *\n * @example\n * ```ts\n * const loading = useFlag(true);\n * loading.disable();\n * ```\n */\nexport const useFlag = (defaultValue = false): FlagHook => {\n const [enabled, setEnabled] = useState(defaultValue);\n\n const toggle = useCallback(() => setEnabled((value) => !value), []);\n const enable = useCallback(() => setEnabled(true), []);\n const disable = useCallback(() => setEnabled(false), []);\n\n const flagObjRef = useRef<FlagHook>({\n enabled,\n toggle,\n enable,\n disable,\n });\n\n flagObjRef.current.enabled = enabled;\n\n return flagObjRef.current;\n};\n","import { useCallback, useState } from 'react';\n\n/**\n * Forces a component re-render by updating an internal dummy state.\n *\n * @returns Stable callback that triggers a re-render.\n *\n * @example\n * ```ts\n * const forceUpdate = useForceUpdate();\n * forceUpdate();\n * ```\n *\n * @example\n * ```ts\n * const rerender = useForceUpdate();\n * setTimeout(rerender, 1000);\n * ```\n */\nexport const useForceUpdate = () => {\n const [, setState] = useState<unknown>(null);\n\n return useCallback(() => {\n setState({});\n }, []);\n};\n","import { useEffect, useRef, useState } from 'react';\n\n/**\n * Captures an element's height the first time its ref becomes available.\n *\n * @template T Element type attached to the returned ref.\n * @returns Ref and the initial measured height.\n *\n * @example\n * ```ts\n * const { ref, initialHeight } = useInitialHeight<HTMLDivElement>();\n * ```\n *\n * @example\n * ```ts\n * const state = useInitialHeight<HTMLTextAreaElement>();\n * state.initialHeight;\n * ```\n */\nexport const useInitialHeight = <T extends HTMLElement>() => {\n const ref = useRef<T | null>(null);\n const [initialHeight, setInitialHeight] = useState<number | undefined>(\n undefined,\n );\n\n useEffect(() => {\n if (ref.current && !initialHeight) {\n setInitialHeight(ref.current.offsetHeight);\n }\n }, [initialHeight]);\n\n return { ref, initialHeight };\n};\n","import { useLayoutEffect } from 'react';\nimport { useAbortSignal } from './use-abort-signal.js';\nimport { useConstant } from './use-constant.js';\n\nexport type InstanceCreateConfig<TPayload, TExtension = {}> = TExtension & {\n abortSignal: AbortSignal;\n payload: TPayload;\n};\n\n/**\n * Builds a custom hook that creates an instance once and wires lifecycle helpers\n * such as an `AbortSignal` and optional extension data into the factory.\n *\n * @template TExtension Extra configuration injected into every factory call.\n * @param extension Optional static extension object merged into the factory config.\n * @returns Hook factory that creates stable instances from a supplied factory.\n *\n * @example\n * ```ts\n * const useStoreInstance = createUseInstanceHook({ api });\n * ```\n *\n * @example\n * ```ts\n * const useService = createUseInstanceHook({ logger });\n * const service = useService(({ logger, payload }) => new Service(logger, payload));\n * ```\n */\nexport const createUseInstanceHook =\n <TExtension = {}>(extension?: TExtension) =>\n <TInstance, TPayload>(\n factory: (\n config: InstanceCreateConfig<NoInfer<TPayload>, TExtension>,\n ) => TInstance,\n config?: {\n payload?: TPayload;\n onUpdate?: (payload: TPayload) => void;\n },\n ) => {\n const abortSignal = useAbortSignal();\n\n const instance = useConstant(() =>\n factory({\n ...(extension as TExtension),\n abortSignal,\n payload: config?.payload as any,\n }),\n );\n\n useLayoutEffect(() => {\n config?.onUpdate?.(config.payload!);\n }, [config?.payload]);\n\n return instance;\n };\n\n/**\n * The `useInstance` hook is used to create and manage an instance of an object\n * that requires access to the root store and an abort signal.\n *\n * You can create YOUR OWN CUSTOM `useInstance` hook using `createUseInstanceHook` if you need\n * to provide some specific data\n *\n * @param factory - A factory function that takes a configuration and returns an instance.\n * @param config - An optional configuration containing additional input parameters and an update function.\n * @returns An instance created by the factory function.\n *\n * @example\n * ```ts\n * const service = useInstance(({ abortSignal }) => new UsersService({ abortSignal }));\n * ```\n *\n * @example\n * ```ts\n * const store = useInstance(\n * ({ payload }) => new UserStore(payload),\n * { payload: userId, onUpdate: (nextId) => console.log(nextId) },\n * );\n * ```\n */\nexport const useInstance = createUseInstanceHook();\n","import { useEffect, useState } from 'react';\n\n/**\n * Creates a single `IntersectionObserver` instance and disposes it on unmount.\n *\n * @param callback Observer callback invoked for intersection changes.\n * @param options Optional observer configuration.\n * @returns Stable `IntersectionObserver` instance.\n *\n * @example\n * ```ts\n * const observer = useIntersectionObserver((entries) => {\n * console.log(entries[0]?.isIntersecting);\n * });\n * ```\n *\n * @example\n * ```ts\n * const observer = useIntersectionObserver(handleIntersect, { threshold: 0.5 });\n * observer.observe(element);\n * ```\n */\nexport const useIntersectionObserver = (\n callback: IntersectionObserverCallback,\n options?: IntersectionObserverInit,\n) => {\n const [intersectionObserver] = useState(\n () => new IntersectionObserver(callback, options),\n );\n\n useEffect(() => {\n return () => {\n intersectionObserver.disconnect();\n };\n }, []);\n\n return intersectionObserver;\n};\n","import { useRef } from 'react';\n\n/**\n * Remembers and returns the last non-nullish value passed to the hook.\n *\n * @template T Value type.\n * @param value Current value that may be `null` or `undefined`.\n * @returns Current value when defined, otherwise the previous defined value.\n *\n * @example\n * ```ts\n * const title = useLastDefinedValue(props.title);\n * ```\n *\n * @example\n * ```ts\n * const user = useLastDefinedValue<User | null>(selectedUser);\n * ```\n */\nexport const useLastDefinedValue = <T>(value: T) => {\n const ref = useRef(value);\n if (value != null) {\n ref.current = value;\n }\n return ref.current;\n};\n","import { useRef } from 'react';\n\n/**\n * Returns a ref that always points to the last non-nullish value.\n *\n * @template T Value type.\n * @param value Current value that may temporarily become `null` or `undefined`.\n * @returns Ref containing the last defined value.\n *\n * @example\n * ```ts\n * const latestUserRef = useLastValueRef(user);\n * latestUserRef.current;\n * ```\n *\n * @example\n * ```ts\n * const latestNodeRef = useLastValueRef<HTMLDivElement | null>(node);\n * ```\n */\nexport const useLastValueRef = <T>(value: T | null | undefined) => {\n const ref = useRef(value);\n\n if (value != null) {\n ref.current = value;\n }\n\n return ref;\n};\n","import { useEffect } from 'react';\nimport { useSyncRef } from './use-sync-ref.js';\n\n/**\n * Runs mount and unmount callbacks returned by a factory function.\n *\n * The latest factory is stored in a ref, while the effect itself is only\n * subscribed once.\n *\n * @param fn Factory returning optional `mount` and `unmount` handlers.\n *\n * @example\n * ```ts\n * useLifeCycle(() => ({\n * mount: () => console.log('mounted'),\n * unmount: () => console.log('unmounted'),\n * }));\n * ```\n *\n * @example\n * ```ts\n * useLifeCycle(() => ({\n * mount: subscribe,\n * unmount: unsubscribe,\n * }));\n * ```\n */\nexport const useLifeCycle = (\n fn: () => {\n mount?: VoidFunction;\n unmount?: VoidFunction;\n },\n) => {\n const fnRef = useSyncRef(fn);\n\n useEffect(() => {\n const fnOperation = fnRef.current();\n fnOperation.mount?.();\n return fnOperation.unmount?.();\n }, []);\n};\n","import { useLayoutEffect } from 'react';\nimport { useDefineRef } from './use-define-ref.js';\n\n/**\n * Creates a stable `ResizeObserver` instance and disconnects it on unmount.\n *\n * @param callback Resize observer callback.\n * @returns Ref containing the observer instance.\n *\n * @example\n * ```ts\n * const observerRef = useResizeObserver((entries) => {\n * console.log(entries[0]?.contentRect.width);\n * });\n * ```\n *\n * @example\n * ```ts\n * const resizeObserver = useResizeObserver(handleResize);\n * resizeObserver.current.observe(element);\n * ```\n */\nexport const useResizeObserver = (callback: ResizeObserverCallback) => {\n const resizeObserverRef = useDefineRef(() => new ResizeObserver(callback));\n\n useLayoutEffect(() => {\n return () => {\n resizeObserverRef.current.disconnect();\n };\n }, []);\n\n return resizeObserverRef;\n};\n","import { useCallback, useState } from 'react';\n\n/**\n * Manages a boolean state and returns helpers to toggle or set it directly.\n *\n * @param initialState Initial boolean value.\n * @returns Tuple with current state, toggle callback and raw setter.\n *\n * @example\n * ```ts\n * const [open, toggleOpen] = useToggle();\n * toggleOpen();\n * ```\n *\n * @example\n * ```ts\n * const [enabled, , setEnabled] = useToggle(true);\n * setEnabled(false);\n * ```\n */\nexport const useToggle = (initialState?: boolean) => {\n const [toggled, setToggled] = useState(!!initialState);\n\n const toggle = useCallback(() => setToggled((toggled) => !toggled), []);\n\n return [toggled, toggle, setToggled] as const;\n};\n","import { useState } from 'react';\n\n/**\n * Wraps `useState` and returns the state value as an object with a `set` method.\n *\n * @template T State value type.\n * @param defaults Initial state value or lazy initializer.\n * @returns Object containing the current value and setter.\n *\n * @example\n * ```ts\n * const counter = useValue(0);\n * counter.set(1);\n * ```\n *\n * @example\n * ```ts\n * const user = useValue(() => ({ name: 'Ann' }));\n * user.value.name;\n * ```\n */\nexport const useValue = <T>(defaults: T | (() => T)) => {\n const [value, setValue] = useState<T>(defaults);\n\n return {\n value,\n set: setValue,\n };\n};\n","import { useEffect, useState } from 'react';\n\n/**\n * Tracks `document.visibilityState` and updates when the page visibility changes.\n *\n * @returns Current document visibility state.\n *\n * @example\n * ```ts\n * const visibility = useVisibilityState();\n * ```\n *\n * @example\n * ```ts\n * const isHidden = useVisibilityState() === 'hidden';\n * ```\n */\nexport const useVisibilityState = () => {\n const [state, setState] = useState<DocumentVisibilityState>();\n\n useEffect(() => {\n const handleVisibilityChange = () => {\n setState(document.visibilityState);\n };\n\n document.addEventListener('visibilitychange', handleVisibilityChange);\n\n return () => {\n document.removeEventListener('visibilitychange', handleVisibilityChange);\n };\n }, []);\n\n return state;\n};\n"],"mappings":"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"}
package/react.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"react.js","names":[],"sources":["../src/react/attach-refs.ts","../src/react/hooks/use-constant.ts","../src/react/hooks/use-abort-controller.ts","../src/react/hooks/use-abort-signal.ts","../src/react/hooks/use-sync-ref.ts","../src/react/hooks/use-event-listener.ts","../src/react/hooks/use-click-outside.ts","../src/react/hooks/use-define-ref.ts","../src/react/hooks/use-element-ref.ts","../src/react/hooks/use-event.ts","../src/react/hooks/use-flag.ts","../src/react/hooks/use-force-update.ts","../src/react/hooks/use-initial-height.ts","../src/react/hooks/use-instance.ts","../src/react/hooks/use-intersection-observer.ts","../src/react/hooks/use-last-defined-value.ts","../src/react/hooks/use-last-value-ref.ts","../src/react/hooks/use-life-cycle.ts","../src/react/hooks/use-resize-observer.ts","../src/react/hooks/use-toggle.ts","../src/react/hooks/use-value.ts","../src/react/hooks/use-visibility-state.ts"],"sourcesContent":["import type { LegacyRef, RefObject } from 'react';\nimport type { Maybe } from 'yummies/types';\n\n/**\n * Assigns the same value to multiple React refs, including callback refs.\n *\n * @template T Referenced value type.\n * @param value Value that should be written into every provided ref.\n * @param refs Target refs to update.\n *\n * @example\n * ```ts\n * attachRefs(node, localRef, forwardedRef);\n * ```\n *\n * @example\n * ```ts\n * attachRefs(null, inputRef, (value) => console.log(value));\n * ```\n */\nexport const attachRefs = <T>(\n value: T | null,\n ...refs: Maybe<RefObject<T> | RefObject<T | null> | LegacyRef<T>>[]\n) =>\n refs.forEach((ref) => {\n if (typeof ref === 'function') {\n ref(value);\n } else if (ref && typeof ref !== 'string') {\n // @ts-expect-error\n ref.current = value;\n }\n });\n","import { useRef } from 'react';\n\n/**\n * React hook for creating a value exactly once.\n *\n * Unlike `useMemo`, this guarantees that the initializer is executed only once\n * for the component lifetime.\n *\n * @template T Value type.\n * @param defineValue Function that lazily creates the value.\n * @returns Stable value created on the first render.\n *\n * @example\n * ```ts\n * const id = useConstant(() => crypto.randomUUID());\n * ```\n *\n * @example\n * ```ts\n * const formatter = useConstant(() => new Intl.NumberFormat('en-US'));\n * ```\n */\nexport const useConstant = <T>(defineValue: () => T): T => {\n const ref = useRef<{ value: T }>();\n\n if (!ref.current) {\n ref.current = { value: defineValue() };\n }\n\n return ref.current.value;\n};\n","import { useEffect } from 'react';\n\nimport { useConstant } from './use-constant.js';\n\n/**\n * Creates a single `AbortController` instance for the component lifetime.\n *\n * The controller is aborted automatically during unmount.\n *\n * @returns Stable abort controller instance.\n *\n * @example\n * ```ts\n * const controller = useAbortController();\n * fetch('/api', { signal: controller.signal });\n * ```\n *\n * @example\n * ```ts\n * const controller = useAbortController();\n * controller.abort();\n * ```\n */\nexport const useAbortController = () => {\n const controller = useConstant(() => new AbortController());\n\n useEffect(() => {\n return () => {\n controller.abort();\n };\n }, []);\n\n return controller;\n};\n","import { useAbortController } from './use-abort-controller.js';\n\n/**\n * Returns an `AbortSignal` tied to the component lifecycle.\n *\n * The signal is aborted automatically on unmount.\n *\n * @returns Lifecycle-bound abort signal.\n *\n * @example\n * ```ts\n * const signal = useAbortSignal();\n * fetch('/api/users', { signal });\n * ```\n *\n * @example\n * ```ts\n * const signal = useAbortSignal();\n * someAsyncTask({ signal });\n * ```\n */\nexport const useAbortSignal = () => {\n return useAbortController().signal;\n};\n","import { useRef } from 'react';\n\n/**\n * Returns a ref whose `current` value is synchronized with the latest input\n * on every render.\n *\n * @template T Value type.\n * @param value Current value to expose through the ref.\n * @returns Ref containing the latest value.\n *\n * @example\n * ```ts\n * const latestHandler = useSyncRef(onSubmit);\n * latestHandler.current();\n * ```\n *\n * @example\n * ```ts\n * const latestValue = useSyncRef(props.value);\n * latestValue.current;\n * ```\n */\nexport const useSyncRef = <T>(value: T) => {\n const ref = useRef(value);\n ref.current = value;\n return ref;\n};\n","/* eslint-disable @typescript-eslint/ban-ts-comment */\nimport { useEffect } from 'react';\nimport { useSyncRef } from './use-sync-ref.js';\n\n/**\n * Subscribes to a DOM event and keeps the latest handler without resubscribing\n * on every render.\n *\n * Supports optional debounce and custom effect dependencies.\n *\n * @template EventName DOM event name from `HTMLElementEventMap`.\n * @param config Event subscription configuration.\n *\n * @example\n * ```ts\n * useEventListener({\n * event: 'click',\n * handler: () => console.log('clicked'),\n * });\n * ```\n *\n * @example\n * ```ts\n * useEventListener({\n * event: 'scroll',\n * node: window,\n * debounce: 100,\n * handler: () => console.log('scroll'),\n * });\n * ```\n */\nexport const useEventListener = <EventName extends keyof HTMLElementEventMap>({\n event,\n handler,\n options,\n deps = [],\n debounce,\n node = document,\n}: {\n event: EventName;\n handler: (e: HTMLElementEventMap[EventName]) => void;\n options?: boolean | AddEventListenerOptions;\n deps?: unknown[];\n debounce?: number;\n node?: HTMLElement | Document | Window;\n}) => {\n const handlerRef = useSyncRef(handler);\n\n useEffect(() => {\n let timerId: ReturnType<typeof setTimeout> | undefined;\n\n const handleEvent = (e: HTMLElementEventMap[EventName]) => {\n if (debounce == null) {\n handlerRef.current(e);\n } else {\n clearTimeout(timerId);\n timerId = setTimeout(() => {\n handlerRef.current(e);\n timerId = undefined;\n }, debounce);\n }\n };\n\n // @ts-expect-error\n node.addEventListener(event, handleEvent, options);\n return () => {\n // @ts-expect-error\n node.removeEventListener(event, handleEvent, options);\n clearTimeout(timerId);\n };\n }, deps);\n};\n","import type { MutableRefObject } from 'react';\nimport { useEventListener } from './use-event-listener.js';\n\ntype ClickOutsideInput = {\n contentRef: MutableRefObject<HTMLElement | null>;\n onClick: VoidFunction;\n options?: AddEventListenerOptions;\n};\n\n/**\n * Calls a handler when a pointer interaction happens outside the referenced element.\n *\n * @param input Target element ref, callback and event listener options.\n *\n * @example\n * ```ts\n * useClickOutside({\n * contentRef: modalRef,\n * onClick: () => closeModal(),\n * });\n * ```\n *\n * @example\n * ```ts\n * useClickOutside({\n * contentRef: dropdownRef,\n * onClick: hideDropdown,\n * options: { capture: true },\n * });\n * ```\n */\nexport const useClickOutside = ({\n contentRef,\n onClick,\n options,\n}: ClickOutsideInput) => {\n useEventListener({\n event: 'mousedown',\n handler: (event) => {\n if (\n contentRef.current &&\n !contentRef.current.contains(event.target as Node)\n ) {\n onClick();\n }\n },\n options,\n });\n};\n","import { type MutableRefObject, useRef } from 'react';\n\n/**\n * Creates a mutable ref whose value is initialized exactly once.\n *\n * @template T Ref value type.\n * @param defineFn Function that lazily creates the initial ref value.\n * @returns Mutable ref with a stable initialized value.\n *\n * @example\n * ```ts\n * const cacheRef = useDefineRef(() => new Map());\n * ```\n *\n * @example\n * ```ts\n * const observerRef = useDefineRef(() => new ResizeObserver(() => {}));\n * ```\n */\nexport const useDefineRef = <T>(defineFn: () => T): MutableRefObject<T> => {\n const ref = useRef<T>(void 0 as T);\n\n if (!ref.current) {\n ref.current = defineFn();\n }\n\n return ref;\n};\n","import { useLayoutEffect, useRef } from 'react';\n\n/**\n * Resolves an element once after mount and stores it in a ref.\n *\n * @template T Element type.\n * @param selector Function returning the target element.\n * @returns Ref containing the selected element.\n *\n * @example\n * ```ts\n * const buttonRef = useElementRef(() => document.getElementById('save') as HTMLButtonElement);\n * ```\n *\n * @example\n * ```ts\n * const modalRef = useElementRef(() => document.querySelector('.modal') as HTMLDivElement);\n * ```\n */\nexport const useElementRef = <T extends HTMLElement>(selector: () => T) => {\n const ref = useRef<T>();\n\n useLayoutEffect(() => {\n ref.current = selector();\n }, []);\n\n return ref;\n};\n","import { useCallback, useLayoutEffect, useRef } from 'react';\nimport type { AnyFunction } from 'yummies/types';\n\n/**\n * Creates an event callback with a stable function identity and up-to-date logic.\n *\n * Borrowed from the `useEvent` RFC idea by React contributors.\n *\n * @template H Handler function type.\n * @param handler Latest callback implementation.\n * @returns Stable callback that always delegates to the latest handler.\n *\n * @example\n * ```ts\n * const onClick = useEvent(() => {\n * console.log('clicked');\n * });\n * ```\n *\n * @example\n * ```ts\n * const onSubmit = useEvent((value: string) => save(value));\n * ```\n */\nexport const useEvent = <H extends AnyFunction>(handler: H): H => {\n const handlerRef = useRef<H>(handler);\n\n // In a real implementation, this would run before layout effects\n useLayoutEffect(() => {\n handlerRef.current = handler;\n });\n\n return useCallback((...args: unknown[]) => {\n // In a real implementation, this would throw if called during render\n const fn = handlerRef.current as AnyFunction;\n return fn(...args);\n }, []) as unknown as H;\n};\n","import { useCallback, useRef, useState } from 'react';\n\nexport interface FlagHook {\n enabled: boolean;\n toggle: VoidFunction;\n enable: VoidFunction;\n disable: VoidFunction;\n}\n\n/**\n * Manages a reusable boolean flag object with stable helper methods.\n *\n * @param defaultValue Initial enabled state.\n * @returns Stable object exposing current state and mutators.\n *\n * @example\n * ```ts\n * const modal = useFlag();\n * modal.enable();\n * ```\n *\n * @example\n * ```ts\n * const loading = useFlag(true);\n * loading.disable();\n * ```\n */\nexport const useFlag = (defaultValue = false): FlagHook => {\n const [enabled, setEnabled] = useState(defaultValue);\n\n const toggle = useCallback(() => setEnabled((value) => !value), []);\n const enable = useCallback(() => setEnabled(true), []);\n const disable = useCallback(() => setEnabled(false), []);\n\n const flagObjRef = useRef<FlagHook>({\n enabled,\n toggle,\n enable,\n disable,\n });\n\n flagObjRef.current.enabled = enabled;\n\n return flagObjRef.current;\n};\n","import { useCallback, useState } from 'react';\n\n/**\n * Forces a component re-render by updating an internal dummy state.\n *\n * @returns Stable callback that triggers a re-render.\n *\n * @example\n * ```ts\n * const forceUpdate = useForceUpdate();\n * forceUpdate();\n * ```\n *\n * @example\n * ```ts\n * const rerender = useForceUpdate();\n * setTimeout(rerender, 1000);\n * ```\n */\nexport const useForceUpdate = () => {\n const [, setState] = useState<unknown>(null);\n\n return useCallback(() => {\n setState({});\n }, []);\n};\n","import { useEffect, useRef, useState } from 'react';\n\n/**\n * Captures an element's height the first time its ref becomes available.\n *\n * @template T Element type attached to the returned ref.\n * @returns Ref and the initial measured height.\n *\n * @example\n * ```ts\n * const { ref, initialHeight } = useInitialHeight<HTMLDivElement>();\n * ```\n *\n * @example\n * ```ts\n * const state = useInitialHeight<HTMLTextAreaElement>();\n * state.initialHeight;\n * ```\n */\nexport const useInitialHeight = <T extends HTMLElement>() => {\n const ref = useRef<T | null>(null);\n const [initialHeight, setInitialHeight] = useState<number | undefined>(\n undefined,\n );\n\n useEffect(() => {\n if (ref.current && !initialHeight) {\n setInitialHeight(ref.current.offsetHeight);\n }\n }, [initialHeight]);\n\n return { ref, initialHeight };\n};\n","import { useLayoutEffect } from 'react';\nimport { useAbortSignal } from './use-abort-signal.js';\nimport { useConstant } from './use-constant.js';\n\nexport type InstanceCreateConfig<TPayload, TExtension = {}> = TExtension & {\n abortSignal: AbortSignal;\n payload: TPayload;\n};\n\n/**\n * Builds a custom hook that creates an instance once and wires lifecycle helpers\n * such as an `AbortSignal` and optional extension data into the factory.\n *\n * @template TExtension Extra configuration injected into every factory call.\n * @param extension Optional static extension object merged into the factory config.\n * @returns Hook factory that creates stable instances from a supplied factory.\n *\n * @example\n * ```ts\n * const useStoreInstance = createUseInstanceHook({ api });\n * ```\n *\n * @example\n * ```ts\n * const useService = createUseInstanceHook({ logger });\n * const service = useService(({ logger, payload }) => new Service(logger, payload));\n * ```\n */\nexport const createUseInstanceHook =\n <TExtension = {}>(extension?: TExtension) =>\n <TInstance, TPayload>(\n factory: (\n config: InstanceCreateConfig<NoInfer<TPayload>, TExtension>,\n ) => TInstance,\n config?: {\n payload?: TPayload;\n onUpdate?: (payload: TPayload) => void;\n },\n ) => {\n const abortSignal = useAbortSignal();\n\n const instance = useConstant(() =>\n factory({\n ...(extension as TExtension),\n abortSignal,\n payload: config?.payload as any,\n }),\n );\n\n useLayoutEffect(() => {\n config?.onUpdate?.(config.payload!);\n }, [config?.payload]);\n\n return instance;\n };\n\n/**\n * The `useInstance` hook is used to create and manage an instance of an object\n * that requires access to the root store and an abort signal.\n *\n * You can create YOUR OWN CUSTOM `useInstance` hook using `createUseInstanceHook` if you need\n * to provide some specific data\n *\n * @param factory - A factory function that takes a configuration and returns an instance.\n * @param config - An optional configuration containing additional input parameters and an update function.\n * @returns An instance created by the factory function.\n *\n * @example\n * ```ts\n * const service = useInstance(({ abortSignal }) => new UsersService({ abortSignal }));\n * ```\n *\n * @example\n * ```ts\n * const store = useInstance(\n * ({ payload }) => new UserStore(payload),\n * { payload: userId, onUpdate: (nextId) => console.log(nextId) },\n * );\n * ```\n */\nexport const useInstance = createUseInstanceHook();\n","import { useEffect, useState } from 'react';\n\n/**\n * Creates a single `IntersectionObserver` instance and disposes it on unmount.\n *\n * @param callback Observer callback invoked for intersection changes.\n * @param options Optional observer configuration.\n * @returns Stable `IntersectionObserver` instance.\n *\n * @example\n * ```ts\n * const observer = useIntersectionObserver((entries) => {\n * console.log(entries[0]?.isIntersecting);\n * });\n * ```\n *\n * @example\n * ```ts\n * const observer = useIntersectionObserver(handleIntersect, { threshold: 0.5 });\n * observer.observe(element);\n * ```\n */\nexport const useIntersectionObserver = (\n callback: IntersectionObserverCallback,\n options?: IntersectionObserverInit,\n) => {\n const [intersectionObserver] = useState(\n () => new IntersectionObserver(callback, options),\n );\n\n useEffect(() => {\n return () => {\n intersectionObserver.disconnect();\n };\n }, []);\n\n return intersectionObserver;\n};\n","import { useRef } from 'react';\n\n/**\n * Remembers and returns the last non-nullish value passed to the hook.\n *\n * @template T Value type.\n * @param value Current value that may be `null` or `undefined`.\n * @returns Current value when defined, otherwise the previous defined value.\n *\n * @example\n * ```ts\n * const title = useLastDefinedValue(props.title);\n * ```\n *\n * @example\n * ```ts\n * const user = useLastDefinedValue<User | null>(selectedUser);\n * ```\n */\nexport const useLastDefinedValue = <T>(value: T) => {\n const ref = useRef(value);\n if (value != null) {\n ref.current = value;\n }\n return ref.current;\n};\n","import { useRef } from 'react';\n\n/**\n * Returns a ref that always points to the last non-nullish value.\n *\n * @template T Value type.\n * @param value Current value that may temporarily become `null` or `undefined`.\n * @returns Ref containing the last defined value.\n *\n * @example\n * ```ts\n * const latestUserRef = useLastValueRef(user);\n * latestUserRef.current;\n * ```\n *\n * @example\n * ```ts\n * const latestNodeRef = useLastValueRef<HTMLDivElement | null>(node);\n * ```\n */\nexport const useLastValueRef = <T>(value: T | null | undefined) => {\n const ref = useRef(value);\n\n if (value != null) {\n ref.current = value;\n }\n\n return ref;\n};\n","import { useEffect } from 'react';\nimport { useSyncRef } from './use-sync-ref.js';\n\n/**\n * Runs mount and unmount callbacks returned by a factory function.\n *\n * The latest factory is stored in a ref, while the effect itself is only\n * subscribed once.\n *\n * @param fn Factory returning optional `mount` and `unmount` handlers.\n *\n * @example\n * ```ts\n * useLifeCycle(() => ({\n * mount: () => console.log('mounted'),\n * unmount: () => console.log('unmounted'),\n * }));\n * ```\n *\n * @example\n * ```ts\n * useLifeCycle(() => ({\n * mount: subscribe,\n * unmount: unsubscribe,\n * }));\n * ```\n */\nexport const useLifeCycle = (\n fn: () => {\n mount?: VoidFunction;\n unmount?: VoidFunction;\n },\n) => {\n const fnRef = useSyncRef(fn);\n\n useEffect(() => {\n const fnOperation = fnRef.current();\n fnOperation.mount?.();\n return fnOperation.unmount?.();\n }, []);\n};\n","import { useLayoutEffect } from 'react';\nimport { useDefineRef } from './use-define-ref.js';\n\n/**\n * Creates a stable `ResizeObserver` instance and disconnects it on unmount.\n *\n * @param callback Resize observer callback.\n * @returns Ref containing the observer instance.\n *\n * @example\n * ```ts\n * const observerRef = useResizeObserver((entries) => {\n * console.log(entries[0]?.contentRect.width);\n * });\n * ```\n *\n * @example\n * ```ts\n * const resizeObserver = useResizeObserver(handleResize);\n * resizeObserver.current.observe(element);\n * ```\n */\nexport const useResizeObserver = (callback: ResizeObserverCallback) => {\n const resizeObserverRef = useDefineRef(() => new ResizeObserver(callback));\n\n useLayoutEffect(() => {\n return () => {\n resizeObserverRef.current.disconnect();\n };\n }, []);\n\n return resizeObserverRef;\n};\n","import { useCallback, useState } from 'react';\n\n/**\n * Manages a boolean state and returns helpers to toggle or set it directly.\n *\n * @param initialState Initial boolean value.\n * @returns Tuple with current state, toggle callback and raw setter.\n *\n * @example\n * ```ts\n * const [open, toggleOpen] = useToggle();\n * toggleOpen();\n * ```\n *\n * @example\n * ```ts\n * const [enabled, , setEnabled] = useToggle(true);\n * setEnabled(false);\n * ```\n */\nexport const useToggle = (initialState?: boolean) => {\n const [toggled, setToggled] = useState(!!initialState);\n\n const toggle = useCallback(() => setToggled((toggled) => !toggled), []);\n\n return [toggled, toggle, setToggled] as const;\n};\n","import { useState } from 'react';\n\n/**\n * Wraps `useState` and returns the state value as an object with a `set` method.\n *\n * @template T State value type.\n * @param defaults Initial state value or lazy initializer.\n * @returns Object containing the current value and setter.\n *\n * @example\n * ```ts\n * const counter = useValue(0);\n * counter.set(1);\n * ```\n *\n * @example\n * ```ts\n * const user = useValue(() => ({ name: 'Ann' }));\n * user.value.name;\n * ```\n */\nexport const useValue = <T>(defaults: T | (() => T)) => {\n const [value, setValue] = useState<T>(defaults);\n\n return {\n value,\n set: setValue,\n };\n};\n","import { useEffect, useState } from 'react';\n\n/**\n * Tracks `document.visibilityState` and updates when the page visibility changes.\n *\n * @returns Current document visibility state.\n *\n * @example\n * ```ts\n * const visibility = useVisibilityState();\n * ```\n *\n * @example\n * ```ts\n * const isHidden = useVisibilityState() === 'hidden';\n * ```\n */\nexport const useVisibilityState = () => {\n const [state, setState] = useState<DocumentVisibilityState>();\n\n useEffect(() => {\n const handleVisibilityChange = () => {\n setState(document.visibilityState);\n };\n\n document.addEventListener('visibilitychange', handleVisibilityChange);\n\n return () => {\n document.removeEventListener('visibilitychange', handleVisibilityChange);\n };\n }, []);\n\n return state;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"react.js","names":[],"sources":["../src/react/attach-refs.ts","../src/react/hooks/use-constant.ts","../src/react/hooks/use-abort-controller.ts","../src/react/hooks/use-abort-signal.ts","../src/react/hooks/use-sync-ref.ts","../src/react/hooks/use-event-listener.ts","../src/react/hooks/use-click-outside.ts","../src/react/hooks/use-define-ref.ts","../src/react/hooks/use-element-ref.ts","../src/react/hooks/use-event.ts","../src/react/hooks/use-flag.ts","../src/react/hooks/use-force-update.ts","../src/react/hooks/use-initial-height.ts","../src/react/hooks/use-instance.ts","../src/react/hooks/use-intersection-observer.ts","../src/react/hooks/use-last-defined-value.ts","../src/react/hooks/use-last-value-ref.ts","../src/react/hooks/use-life-cycle.ts","../src/react/hooks/use-resize-observer.ts","../src/react/hooks/use-toggle.ts","../src/react/hooks/use-value.ts","../src/react/hooks/use-visibility-state.ts"],"sourcesContent":["import type { LegacyRef, RefObject } from 'react';\nimport type { Maybe } from 'yummies/types';\n\n/**\n * Assigns the same value to multiple React refs, including callback refs.\n *\n * @template T Referenced value type.\n * @param value Value that should be written into every provided ref.\n * @param refs Target refs to update.\n *\n * @example\n * ```ts\n * attachRefs(node, localRef, forwardedRef);\n * ```\n *\n * @example\n * ```ts\n * attachRefs(null, inputRef, (value) => console.log(value));\n * ```\n */\nexport const attachRefs = <T>(\n value: T | null,\n ...refs: Maybe<RefObject<T> | RefObject<T | null> | LegacyRef<T>>[]\n) =>\n refs.forEach((ref) => {\n if (typeof ref === 'function') {\n ref(value);\n } else if (ref && typeof ref !== 'string') {\n // @ts-expect-error\n ref.current = value;\n }\n });\n","import { useRef } from 'react';\n\n/**\n * React hook for creating a value exactly once.\n *\n * Unlike `useMemo`, this guarantees that the initializer is executed only once\n * for the component lifetime.\n *\n * @template T Value type.\n * @param defineValue Function that lazily creates the value.\n * @returns Stable value created on the first render.\n *\n * @example\n * ```ts\n * const id = useConstant(() => crypto.randomUUID());\n * ```\n *\n * @example\n * ```ts\n * const formatter = useConstant(() => new Intl.NumberFormat('en-US'));\n * ```\n */\nexport const useConstant = <T>(defineValue: () => T): T => {\n const ref = useRef<{ value: T }>();\n\n if (!ref.current) {\n ref.current = { value: defineValue() };\n }\n\n return ref.current.value;\n};\n","import { useEffect } from 'react';\n\nimport { useConstant } from './use-constant.js';\n\n/**\n * Creates a single `AbortController` instance for the component lifetime.\n *\n * The controller is aborted automatically during unmount.\n *\n * @returns Stable abort controller instance.\n *\n * @example\n * ```ts\n * const controller = useAbortController();\n * fetch('/api', { signal: controller.signal });\n * ```\n *\n * @example\n * ```ts\n * const controller = useAbortController();\n * controller.abort();\n * ```\n */\nexport const useAbortController = () => {\n const controller = useConstant(() => new AbortController());\n\n useEffect(() => {\n return () => {\n controller.abort();\n };\n }, []);\n\n return controller;\n};\n","import { useAbortController } from './use-abort-controller.js';\n\n/**\n * Returns an `AbortSignal` tied to the component lifecycle.\n *\n * The signal is aborted automatically on unmount.\n *\n * @returns Lifecycle-bound abort signal.\n *\n * @example\n * ```ts\n * const signal = useAbortSignal();\n * fetch('/api/users', { signal });\n * ```\n *\n * @example\n * ```ts\n * const signal = useAbortSignal();\n * someAsyncTask({ signal });\n * ```\n */\nexport const useAbortSignal = () => {\n return useAbortController().signal;\n};\n","import { useRef } from 'react';\n\n/**\n * Returns a ref whose `current` value is synchronized with the latest input\n * on every render.\n *\n * @template T Value type.\n * @param value Current value to expose through the ref.\n * @returns Ref containing the latest value.\n *\n * @example\n * ```ts\n * const latestHandler = useSyncRef(onSubmit);\n * latestHandler.current();\n * ```\n *\n * @example\n * ```ts\n * const latestValue = useSyncRef(props.value);\n * latestValue.current;\n * ```\n */\nexport const useSyncRef = <T>(value: T) => {\n const ref = useRef(value);\n ref.current = value;\n return ref;\n};\n","/* eslint-disable @typescript-eslint/ban-ts-comment */\nimport { useEffect } from 'react';\nimport { useSyncRef } from './use-sync-ref.js';\n\n/**\n * Subscribes to a DOM event and keeps the latest handler without resubscribing\n * on every render.\n *\n * Supports optional debounce and custom effect dependencies.\n *\n * @template EventName DOM event name from `HTMLElementEventMap`.\n * @param config Event subscription configuration.\n *\n * @example\n * ```ts\n * useEventListener({\n * event: 'click',\n * handler: () => console.log('clicked'),\n * });\n * ```\n *\n * @example\n * ```ts\n * useEventListener({\n * event: 'scroll',\n * node: window,\n * debounce: 100,\n * handler: () => console.log('scroll'),\n * });\n * ```\n */\nexport const useEventListener = <EventName extends keyof HTMLElementEventMap>({\n event,\n handler,\n options,\n deps = [],\n debounce,\n node = document,\n}: {\n event: EventName;\n handler: (e: HTMLElementEventMap[EventName]) => void;\n options?: boolean | AddEventListenerOptions;\n deps?: unknown[];\n debounce?: number;\n node?: HTMLElement | Document | Window;\n}) => {\n const handlerRef = useSyncRef(handler);\n\n useEffect(() => {\n let timerId: ReturnType<typeof setTimeout> | undefined;\n\n const handleEvent = (e: HTMLElementEventMap[EventName]) => {\n if (debounce == null) {\n handlerRef.current(e);\n } else {\n clearTimeout(timerId);\n timerId = setTimeout(() => {\n handlerRef.current(e);\n timerId = undefined;\n }, debounce);\n }\n };\n\n // @ts-expect-error\n node.addEventListener(event, handleEvent, options);\n return () => {\n // @ts-expect-error\n node.removeEventListener(event, handleEvent, options);\n clearTimeout(timerId);\n };\n }, deps);\n};\n","import type { MutableRefObject } from 'react';\nimport { useEventListener } from './use-event-listener.js';\n\ntype ClickOutsideInput = {\n contentRef: MutableRefObject<HTMLElement | null>;\n onClick: VoidFunction;\n options?: AddEventListenerOptions;\n};\n\n/**\n * Calls a handler when a pointer interaction happens outside the referenced element.\n *\n * @param input Target element ref, callback and event listener options.\n *\n * @example\n * ```ts\n * useClickOutside({\n * contentRef: modalRef,\n * onClick: () => closeModal(),\n * });\n * ```\n *\n * @example\n * ```ts\n * useClickOutside({\n * contentRef: dropdownRef,\n * onClick: hideDropdown,\n * options: { capture: true },\n * });\n * ```\n */\nexport const useClickOutside = ({\n contentRef,\n onClick,\n options,\n}: ClickOutsideInput) => {\n useEventListener({\n event: 'mousedown',\n handler: (event) => {\n if (\n contentRef.current &&\n !contentRef.current.contains(event.target as Node)\n ) {\n onClick();\n }\n },\n options,\n });\n};\n","import { type MutableRefObject, useRef } from 'react';\n\n/**\n * Creates a mutable ref whose value is initialized exactly once.\n *\n * @template T Ref value type.\n * @param defineFn Function that lazily creates the initial ref value.\n * @returns Mutable ref with a stable initialized value.\n *\n * @example\n * ```ts\n * const cacheRef = useDefineRef(() => new Map());\n * ```\n *\n * @example\n * ```ts\n * const observerRef = useDefineRef(() => new ResizeObserver(() => {}));\n * ```\n */\nexport const useDefineRef = <T>(defineFn: () => T): MutableRefObject<T> => {\n const ref = useRef<T>(void 0 as T);\n\n if (!ref.current) {\n ref.current = defineFn();\n }\n\n return ref;\n};\n","import { useLayoutEffect, useRef } from 'react';\n\n/**\n * Resolves an element once after mount and stores it in a ref.\n *\n * @template T Element type.\n * @param selector Function returning the target element.\n * @returns Ref containing the selected element.\n *\n * @example\n * ```ts\n * const buttonRef = useElementRef(() => document.getElementById('save') as HTMLButtonElement);\n * ```\n *\n * @example\n * ```ts\n * const modalRef = useElementRef(() => document.querySelector('.modal') as HTMLDivElement);\n * ```\n */\nexport const useElementRef = <T extends HTMLElement>(selector: () => T) => {\n const ref = useRef<T>();\n\n useLayoutEffect(() => {\n ref.current = selector();\n }, []);\n\n return ref;\n};\n","import { useCallback, useLayoutEffect, useRef } from 'react';\nimport type { AnyFunction } from 'yummies/types';\n\n/**\n * Creates an event callback with a stable function identity and up-to-date logic.\n *\n * Borrowed from the `useEvent` RFC idea by React contributors.\n *\n * @template H Handler function type.\n * @param handler Latest callback implementation.\n * @returns Stable callback that always delegates to the latest handler.\n *\n * @example\n * ```ts\n * const onClick = useEvent(() => {\n * console.log('clicked');\n * });\n * ```\n *\n * @example\n * ```ts\n * const onSubmit = useEvent((value: string) => save(value));\n * ```\n */\nexport const useEvent = <H extends AnyFunction>(handler: H): H => {\n const handlerRef = useRef<H>(handler);\n\n // In a real implementation, this would run before layout effects\n useLayoutEffect(() => {\n handlerRef.current = handler;\n });\n\n return useCallback((...args: unknown[]) => {\n // In a real implementation, this would throw if called during render\n const fn = handlerRef.current as AnyFunction;\n return fn(...args);\n }, []) as unknown as H;\n};\n","import { useCallback, useRef, useState } from 'react';\n\nexport interface FlagHook {\n enabled: boolean;\n toggle: VoidFunction;\n enable: VoidFunction;\n disable: VoidFunction;\n}\n\n/**\n * Manages a reusable boolean flag object with stable helper methods.\n *\n * @param defaultValue Initial enabled state.\n * @returns Stable object exposing current state and mutators.\n *\n * @example\n * ```ts\n * const modal = useFlag();\n * modal.enable();\n * ```\n *\n * @example\n * ```ts\n * const loading = useFlag(true);\n * loading.disable();\n * ```\n */\nexport const useFlag = (defaultValue = false): FlagHook => {\n const [enabled, setEnabled] = useState(defaultValue);\n\n const toggle = useCallback(() => setEnabled((value) => !value), []);\n const enable = useCallback(() => setEnabled(true), []);\n const disable = useCallback(() => setEnabled(false), []);\n\n const flagObjRef = useRef<FlagHook>({\n enabled,\n toggle,\n enable,\n disable,\n });\n\n flagObjRef.current.enabled = enabled;\n\n return flagObjRef.current;\n};\n","import { useCallback, useState } from 'react';\n\n/**\n * Forces a component re-render by updating an internal dummy state.\n *\n * @returns Stable callback that triggers a re-render.\n *\n * @example\n * ```ts\n * const forceUpdate = useForceUpdate();\n * forceUpdate();\n * ```\n *\n * @example\n * ```ts\n * const rerender = useForceUpdate();\n * setTimeout(rerender, 1000);\n * ```\n */\nexport const useForceUpdate = () => {\n const [, setState] = useState<unknown>(null);\n\n return useCallback(() => {\n setState({});\n }, []);\n};\n","import { useEffect, useRef, useState } from 'react';\n\n/**\n * Captures an element's height the first time its ref becomes available.\n *\n * @template T Element type attached to the returned ref.\n * @returns Ref and the initial measured height.\n *\n * @example\n * ```ts\n * const { ref, initialHeight } = useInitialHeight<HTMLDivElement>();\n * ```\n *\n * @example\n * ```ts\n * const state = useInitialHeight<HTMLTextAreaElement>();\n * state.initialHeight;\n * ```\n */\nexport const useInitialHeight = <T extends HTMLElement>() => {\n const ref = useRef<T | null>(null);\n const [initialHeight, setInitialHeight] = useState<number | undefined>(\n undefined,\n );\n\n useEffect(() => {\n if (ref.current && !initialHeight) {\n setInitialHeight(ref.current.offsetHeight);\n }\n }, [initialHeight]);\n\n return { ref, initialHeight };\n};\n","import { useLayoutEffect } from 'react';\nimport { useAbortSignal } from './use-abort-signal.js';\nimport { useConstant } from './use-constant.js';\n\nexport type InstanceCreateConfig<TPayload, TExtension = {}> = TExtension & {\n abortSignal: AbortSignal;\n payload: TPayload;\n};\n\n/**\n * Builds a custom hook that creates an instance once and wires lifecycle helpers\n * such as an `AbortSignal` and optional extension data into the factory.\n *\n * @template TExtension Extra configuration injected into every factory call.\n * @param extension Optional static extension object merged into the factory config.\n * @returns Hook factory that creates stable instances from a supplied factory.\n *\n * @example\n * ```ts\n * const useStoreInstance = createUseInstanceHook({ api });\n * ```\n *\n * @example\n * ```ts\n * const useService = createUseInstanceHook({ logger });\n * const service = useService(({ logger, payload }) => new Service(logger, payload));\n * ```\n */\nexport const createUseInstanceHook =\n <TExtension = {}>(extension?: TExtension) =>\n <TInstance, TPayload>(\n factory: (\n config: InstanceCreateConfig<NoInfer<TPayload>, TExtension>,\n ) => TInstance,\n config?: {\n payload?: TPayload;\n onUpdate?: (payload: TPayload) => void;\n },\n ) => {\n const abortSignal = useAbortSignal();\n\n const instance = useConstant(() =>\n factory({\n ...(extension as TExtension),\n abortSignal,\n payload: config?.payload as any,\n }),\n );\n\n useLayoutEffect(() => {\n config?.onUpdate?.(config.payload!);\n }, [config?.payload]);\n\n return instance;\n };\n\n/**\n * The `useInstance` hook is used to create and manage an instance of an object\n * that requires access to the root store and an abort signal.\n *\n * You can create YOUR OWN CUSTOM `useInstance` hook using `createUseInstanceHook` if you need\n * to provide some specific data\n *\n * @param factory - A factory function that takes a configuration and returns an instance.\n * @param config - An optional configuration containing additional input parameters and an update function.\n * @returns An instance created by the factory function.\n *\n * @example\n * ```ts\n * const service = useInstance(({ abortSignal }) => new UsersService({ abortSignal }));\n * ```\n *\n * @example\n * ```ts\n * const store = useInstance(\n * ({ payload }) => new UserStore(payload),\n * { payload: userId, onUpdate: (nextId) => console.log(nextId) },\n * );\n * ```\n */\nexport const useInstance = createUseInstanceHook();\n","import { useEffect, useState } from 'react';\n\n/**\n * Creates a single `IntersectionObserver` instance and disposes it on unmount.\n *\n * @param callback Observer callback invoked for intersection changes.\n * @param options Optional observer configuration.\n * @returns Stable `IntersectionObserver` instance.\n *\n * @example\n * ```ts\n * const observer = useIntersectionObserver((entries) => {\n * console.log(entries[0]?.isIntersecting);\n * });\n * ```\n *\n * @example\n * ```ts\n * const observer = useIntersectionObserver(handleIntersect, { threshold: 0.5 });\n * observer.observe(element);\n * ```\n */\nexport const useIntersectionObserver = (\n callback: IntersectionObserverCallback,\n options?: IntersectionObserverInit,\n) => {\n const [intersectionObserver] = useState(\n () => new IntersectionObserver(callback, options),\n );\n\n useEffect(() => {\n return () => {\n intersectionObserver.disconnect();\n };\n }, []);\n\n return intersectionObserver;\n};\n","import { useRef } from 'react';\n\n/**\n * Remembers and returns the last non-nullish value passed to the hook.\n *\n * @template T Value type.\n * @param value Current value that may be `null` or `undefined`.\n * @returns Current value when defined, otherwise the previous defined value.\n *\n * @example\n * ```ts\n * const title = useLastDefinedValue(props.title);\n * ```\n *\n * @example\n * ```ts\n * const user = useLastDefinedValue<User | null>(selectedUser);\n * ```\n */\nexport const useLastDefinedValue = <T>(value: T) => {\n const ref = useRef(value);\n if (value != null) {\n ref.current = value;\n }\n return ref.current;\n};\n","import { useRef } from 'react';\n\n/**\n * Returns a ref that always points to the last non-nullish value.\n *\n * @template T Value type.\n * @param value Current value that may temporarily become `null` or `undefined`.\n * @returns Ref containing the last defined value.\n *\n * @example\n * ```ts\n * const latestUserRef = useLastValueRef(user);\n * latestUserRef.current;\n * ```\n *\n * @example\n * ```ts\n * const latestNodeRef = useLastValueRef<HTMLDivElement | null>(node);\n * ```\n */\nexport const useLastValueRef = <T>(value: T | null | undefined) => {\n const ref = useRef(value);\n\n if (value != null) {\n ref.current = value;\n }\n\n return ref;\n};\n","import { useEffect } from 'react';\nimport { useSyncRef } from './use-sync-ref.js';\n\n/**\n * Runs mount and unmount callbacks returned by a factory function.\n *\n * The latest factory is stored in a ref, while the effect itself is only\n * subscribed once.\n *\n * @param fn Factory returning optional `mount` and `unmount` handlers.\n *\n * @example\n * ```ts\n * useLifeCycle(() => ({\n * mount: () => console.log('mounted'),\n * unmount: () => console.log('unmounted'),\n * }));\n * ```\n *\n * @example\n * ```ts\n * useLifeCycle(() => ({\n * mount: subscribe,\n * unmount: unsubscribe,\n * }));\n * ```\n */\nexport const useLifeCycle = (\n fn: () => {\n mount?: VoidFunction;\n unmount?: VoidFunction;\n },\n) => {\n const fnRef = useSyncRef(fn);\n\n useEffect(() => {\n const fnOperation = fnRef.current();\n fnOperation.mount?.();\n return fnOperation.unmount?.();\n }, []);\n};\n","import { useLayoutEffect } from 'react';\nimport { useDefineRef } from './use-define-ref.js';\n\n/**\n * Creates a stable `ResizeObserver` instance and disconnects it on unmount.\n *\n * @param callback Resize observer callback.\n * @returns Ref containing the observer instance.\n *\n * @example\n * ```ts\n * const observerRef = useResizeObserver((entries) => {\n * console.log(entries[0]?.contentRect.width);\n * });\n * ```\n *\n * @example\n * ```ts\n * const resizeObserver = useResizeObserver(handleResize);\n * resizeObserver.current.observe(element);\n * ```\n */\nexport const useResizeObserver = (callback: ResizeObserverCallback) => {\n const resizeObserverRef = useDefineRef(() => new ResizeObserver(callback));\n\n useLayoutEffect(() => {\n return () => {\n resizeObserverRef.current.disconnect();\n };\n }, []);\n\n return resizeObserverRef;\n};\n","import { useCallback, useState } from 'react';\n\n/**\n * Manages a boolean state and returns helpers to toggle or set it directly.\n *\n * @param initialState Initial boolean value.\n * @returns Tuple with current state, toggle callback and raw setter.\n *\n * @example\n * ```ts\n * const [open, toggleOpen] = useToggle();\n * toggleOpen();\n * ```\n *\n * @example\n * ```ts\n * const [enabled, , setEnabled] = useToggle(true);\n * setEnabled(false);\n * ```\n */\nexport const useToggle = (initialState?: boolean) => {\n const [toggled, setToggled] = useState(!!initialState);\n\n const toggle = useCallback(() => setToggled((toggled) => !toggled), []);\n\n return [toggled, toggle, setToggled] as const;\n};\n","import { useState } from 'react';\n\n/**\n * Wraps `useState` and returns the state value as an object with a `set` method.\n *\n * @template T State value type.\n * @param defaults Initial state value or lazy initializer.\n * @returns Object containing the current value and setter.\n *\n * @example\n * ```ts\n * const counter = useValue(0);\n * counter.set(1);\n * ```\n *\n * @example\n * ```ts\n * const user = useValue(() => ({ name: 'Ann' }));\n * user.value.name;\n * ```\n */\nexport const useValue = <T>(defaults: T | (() => T)) => {\n const [value, setValue] = useState<T>(defaults);\n\n return {\n value,\n set: setValue,\n };\n};\n","import { useEffect, useState } from 'react';\n\n/**\n * Tracks `document.visibilityState` and updates when the page visibility changes.\n *\n * @returns Current document visibility state.\n *\n * @example\n * ```ts\n * const visibility = useVisibilityState();\n * ```\n *\n * @example\n * ```ts\n * const isHidden = useVisibilityState() === 'hidden';\n * ```\n */\nexport const useVisibilityState = () => {\n const [state, setState] = useState<DocumentVisibilityState>();\n\n useEffect(() => {\n const handleVisibilityChange = () => {\n setState(document.visibilityState);\n };\n\n document.addEventListener('visibilitychange', handleVisibilityChange);\n\n return () => {\n document.removeEventListener('visibilitychange', handleVisibilityChange);\n };\n }, []);\n\n return state;\n};\n"],"mappings":"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"}
@@ -0,0 +1,82 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_chunk = require("./chunk-DakpK96I.cjs");
3
+ let dompurify = require("dompurify");
4
+ dompurify = require_chunk.__toESM(dompurify, 1);
5
+ //#region src/html/sanitize-html.ts
6
+ /**
7
+ * @internal Separate chunk so DOMPurify is tree-shaken away when `sanitizeHtml` is not used.
8
+ * Consumers import from `yummies/html` — this module is not a public entry point.
9
+ */
10
+ /**
11
+ * Sanitizes HTML using the default allowlist merged with custom DOMPurify config.
12
+ *
13
+ * Default DOMPurify settings are exposed on `sanitizeHtml.defaults` and can be
14
+ * overridden per call via `config`.
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * sanitizeHtml('<img src=x onerror=alert(1) />');
19
+ * ```
20
+ */
21
+ var sanitizeHtml = ((html, config) => {
22
+ return dompurify.default.sanitize(html || "", {
23
+ ...sanitizeHtml.defaults,
24
+ ...config
25
+ });
26
+ });
27
+ sanitizeHtml.defaults = {
28
+ ALLOWED_TAGS: [
29
+ "a",
30
+ "article",
31
+ "b",
32
+ "blockquote",
33
+ "br",
34
+ "caption",
35
+ "code",
36
+ "del",
37
+ "details",
38
+ "div",
39
+ "em",
40
+ "h1",
41
+ "h2",
42
+ "h3",
43
+ "h4",
44
+ "h5",
45
+ "h6",
46
+ "hr",
47
+ "i",
48
+ "img",
49
+ "ins",
50
+ "kbd",
51
+ "li",
52
+ "main",
53
+ "ol",
54
+ "p",
55
+ "pre",
56
+ "section",
57
+ "span",
58
+ "strong",
59
+ "sub",
60
+ "summary",
61
+ "sup",
62
+ "table",
63
+ "tbody",
64
+ "td",
65
+ "th",
66
+ "thead",
67
+ "tr",
68
+ "u",
69
+ "ul"
70
+ ],
71
+ ALLOWED_ATTR: [
72
+ "href",
73
+ "target",
74
+ "name",
75
+ "src",
76
+ "class"
77
+ ]
78
+ };
79
+ //#endregion
80
+ exports.sanitizeHtml = sanitizeHtml;
81
+
82
+ //# sourceMappingURL=sanitize-html.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitize-html.cjs","names":[],"sources":["../src/html/sanitize-html.ts"],"sourcesContent":["/**\n * @internal Separate chunk so DOMPurify is tree-shaken away when `sanitizeHtml` is not used.\n * Consumers import from `yummies/html` — this module is not a public entry point.\n */\n\nimport DOMPurify, { type Config as DOMPurifyConfig } from 'dompurify';\nimport type { Maybe } from 'yummies/types';\n\ntype SanitizeHtmlFn = ((\n html: Maybe<string>,\n config?: DOMPurifyConfig,\n) => string) & {\n /**\n * Default DOMPurify settings\n */\n defaults: DOMPurifyConfig;\n};\n/**\n * Sanitizes HTML using the default allowlist merged with custom DOMPurify config.\n *\n * Default DOMPurify settings are exposed on `sanitizeHtml.defaults` and can be\n * overridden per call via `config`.\n *\n * @example\n * ```ts\n * sanitizeHtml('<img src=x onerror=alert(1) />');\n * ```\n */\nexport const sanitizeHtml = ((\n html: Maybe<string>,\n config?: DOMPurifyConfig,\n) => {\n return DOMPurify.sanitize(html || '', {\n ...sanitizeHtml.defaults,\n ...config,\n });\n}) as SanitizeHtmlFn;\n\nsanitizeHtml.defaults = {\n ALLOWED_TAGS: [\n 'a',\n 'article',\n 'b',\n 'blockquote',\n 'br',\n 'caption',\n 'code',\n 'del',\n 'details',\n 'div',\n 'em',\n 'h1',\n 'h2',\n 'h3',\n 'h4',\n 'h5',\n 'h6',\n 'hr',\n 'i',\n 'img',\n 'ins',\n 'kbd',\n 'li',\n 'main',\n 'ol',\n 'p',\n 'pre',\n 'section',\n 'span',\n 'strong',\n 'sub',\n 'summary',\n 'sup',\n 'table',\n 'tbody',\n 'td',\n 'th',\n 'thead',\n 'tr',\n 'u',\n 'ul',\n ],\n ALLOWED_ATTR: ['href', 'target', 'name', 'src', 'class'],\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA4BA,IAAa,iBACX,MACA,WACG;CACH,OAAO,UAAA,QAAU,SAAS,QAAQ,IAAI;EACpC,GAAG,aAAa;EAChB,GAAG;CACL,CAAC;AACH;AAEA,aAAa,WAAW;CACtB,cAAc;EACZ;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;CACA,cAAc;EAAC;EAAQ;EAAU;EAAQ;EAAO;CAAO;AACzD"}
@@ -0,0 +1,28 @@
1
+ import { Config } from 'dompurify';
2
+ import { Maybe } from 'yummies/types';
3
+
4
+ /**
5
+ * @internal Separate chunk so DOMPurify is tree-shaken away when `sanitizeHtml` is not used.
6
+ * Consumers import from `yummies/html` — this module is not a public entry point.
7
+ */
8
+
9
+ type SanitizeHtmlFn = ((html: Maybe<string>, config?: Config) => string) & {
10
+ /**
11
+ * Default DOMPurify settings
12
+ */
13
+ defaults: Config;
14
+ };
15
+ /**
16
+ * Sanitizes HTML using the default allowlist merged with custom DOMPurify config.
17
+ *
18
+ * Default DOMPurify settings are exposed on `sanitizeHtml.defaults` and can be
19
+ * overridden per call via `config`.
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * sanitizeHtml('<img src=x onerror=alert(1) />');
24
+ * ```
25
+ */
26
+ declare const sanitizeHtml: SanitizeHtmlFn;
27
+
28
+ export { sanitizeHtml };
@@ -0,0 +1,79 @@
1
+ import DOMPurify from "dompurify";
2
+ //#region src/html/sanitize-html.ts
3
+ /**
4
+ * @internal Separate chunk so DOMPurify is tree-shaken away when `sanitizeHtml` is not used.
5
+ * Consumers import from `yummies/html` — this module is not a public entry point.
6
+ */
7
+ /**
8
+ * Sanitizes HTML using the default allowlist merged with custom DOMPurify config.
9
+ *
10
+ * Default DOMPurify settings are exposed on `sanitizeHtml.defaults` and can be
11
+ * overridden per call via `config`.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * sanitizeHtml('<img src=x onerror=alert(1) />');
16
+ * ```
17
+ */
18
+ var sanitizeHtml = ((html, config) => {
19
+ return DOMPurify.sanitize(html || "", {
20
+ ...sanitizeHtml.defaults,
21
+ ...config
22
+ });
23
+ });
24
+ sanitizeHtml.defaults = {
25
+ ALLOWED_TAGS: [
26
+ "a",
27
+ "article",
28
+ "b",
29
+ "blockquote",
30
+ "br",
31
+ "caption",
32
+ "code",
33
+ "del",
34
+ "details",
35
+ "div",
36
+ "em",
37
+ "h1",
38
+ "h2",
39
+ "h3",
40
+ "h4",
41
+ "h5",
42
+ "h6",
43
+ "hr",
44
+ "i",
45
+ "img",
46
+ "ins",
47
+ "kbd",
48
+ "li",
49
+ "main",
50
+ "ol",
51
+ "p",
52
+ "pre",
53
+ "section",
54
+ "span",
55
+ "strong",
56
+ "sub",
57
+ "summary",
58
+ "sup",
59
+ "table",
60
+ "tbody",
61
+ "td",
62
+ "th",
63
+ "thead",
64
+ "tr",
65
+ "u",
66
+ "ul"
67
+ ],
68
+ ALLOWED_ATTR: [
69
+ "href",
70
+ "target",
71
+ "name",
72
+ "src",
73
+ "class"
74
+ ]
75
+ };
76
+ //#endregion
77
+ export { sanitizeHtml };
78
+
79
+ //# sourceMappingURL=sanitize-html.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitize-html.js","names":[],"sources":["../src/html/sanitize-html.ts"],"sourcesContent":["/**\n * @internal Separate chunk so DOMPurify is tree-shaken away when `sanitizeHtml` is not used.\n * Consumers import from `yummies/html` — this module is not a public entry point.\n */\n\nimport DOMPurify, { type Config as DOMPurifyConfig } from 'dompurify';\nimport type { Maybe } from 'yummies/types';\n\ntype SanitizeHtmlFn = ((\n html: Maybe<string>,\n config?: DOMPurifyConfig,\n) => string) & {\n /**\n * Default DOMPurify settings\n */\n defaults: DOMPurifyConfig;\n};\n/**\n * Sanitizes HTML using the default allowlist merged with custom DOMPurify config.\n *\n * Default DOMPurify settings are exposed on `sanitizeHtml.defaults` and can be\n * overridden per call via `config`.\n *\n * @example\n * ```ts\n * sanitizeHtml('<img src=x onerror=alert(1) />');\n * ```\n */\nexport const sanitizeHtml = ((\n html: Maybe<string>,\n config?: DOMPurifyConfig,\n) => {\n return DOMPurify.sanitize(html || '', {\n ...sanitizeHtml.defaults,\n ...config,\n });\n}) as SanitizeHtmlFn;\n\nsanitizeHtml.defaults = {\n ALLOWED_TAGS: [\n 'a',\n 'article',\n 'b',\n 'blockquote',\n 'br',\n 'caption',\n 'code',\n 'del',\n 'details',\n 'div',\n 'em',\n 'h1',\n 'h2',\n 'h3',\n 'h4',\n 'h5',\n 'h6',\n 'hr',\n 'i',\n 'img',\n 'ins',\n 'kbd',\n 'li',\n 'main',\n 'ol',\n 'p',\n 'pre',\n 'section',\n 'span',\n 'strong',\n 'sub',\n 'summary',\n 'sup',\n 'table',\n 'tbody',\n 'td',\n 'th',\n 'thead',\n 'tr',\n 'u',\n 'ul',\n ],\n ALLOWED_ATTR: ['href', 'target', 'name', 'src', 'class'],\n};\n"],"mappings":";;;;;;;;;;;;;;;;;AA4BA,IAAa,iBACX,MACA,WACG;CACH,OAAO,UAAU,SAAS,QAAQ,IAAI;EACpC,GAAG,aAAa;EAChB,GAAG;CACL,CAAC;AACH;AAEA,aAAa,WAAW;CACtB,cAAc;EACZ;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;CACA,cAAc;EAAC;EAAQ;EAAU;EAAQ;EAAO;CAAO;AACzD"}