@spark-ui/hooks 10.16.1 → 10.17.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.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,17 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [10.17.0](https://github.com/leboncoin/spark-web/compare/v10.16.2...v10.17.0) (2025-08-22)
7
+
8
+ **Note:** Version bump only for package @spark-ui/hooks
9
+
10
+ ## [10.16.2](https://github.com/leboncoin/spark-web/compare/v10.16.1...v10.16.2) (2025-08-21)
11
+
12
+ ### Bug Fixes
13
+
14
+ - **components:** dynamic overflow detection for ScrollingList ([eb7f67e](https://github.com/leboncoin/spark-web/commit/eb7f67ef728efca4977232680e0cb53f0facb6fc))
15
+ - **components:** showcase how to manipulate scroll through ref ([b3642e5](https://github.com/leboncoin/spark-web/commit/b3642e57469268469cf2e1f01b3a62c3bf7ffddf))
16
+
6
17
  ## [10.16.1](https://github.com/leboncoin/spark-web/compare/v10.16.0...v10.16.1) (2025-08-20)
7
18
 
8
19
  **Note:** Version bump only for package @spark-ui/hooks
@@ -6,6 +6,13 @@ interface ScrollOverflow {
6
6
  left: number;
7
7
  right: number;
8
8
  }
9
- declare function useScrollOverflow(scrollRef: RefObject<HTMLElement | null>): ScrollOverflow;
9
+ declare function useScrollOverflow(scrollRef: RefObject<HTMLElement | null>,
10
+ /**
11
+ * Tolerance threshold for floating-point precision issues.
12
+ * Values below this threshold are considered as "no overflow" to handle sub-pixel rendering artifacts.
13
+ */
14
+ { precisionTreshold }?: {
15
+ precisionTreshold?: number;
16
+ }): ScrollOverflow;
10
17
 
11
18
  export { type ScrollOverflow, useScrollOverflow };
@@ -6,6 +6,13 @@ interface ScrollOverflow {
6
6
  left: number;
7
7
  right: number;
8
8
  }
9
- declare function useScrollOverflow(scrollRef: RefObject<HTMLElement | null>): ScrollOverflow;
9
+ declare function useScrollOverflow(scrollRef: RefObject<HTMLElement | null>,
10
+ /**
11
+ * Tolerance threshold for floating-point precision issues.
12
+ * Values below this threshold are considered as "no overflow" to handle sub-pixel rendering artifacts.
13
+ */
14
+ { precisionTreshold }?: {
15
+ precisionTreshold?: number;
16
+ }): ScrollOverflow;
10
17
 
11
18
  export { type ScrollOverflow, useScrollOverflow };
@@ -26,7 +26,7 @@ module.exports = __toCommonJS(use_scroll_overflow_exports);
26
26
 
27
27
  // src/use-scroll-overflow/useScrollOverflow.tsx
28
28
  var import_react = require("react");
29
- function useScrollOverflow(scrollRef) {
29
+ function useScrollOverflow(scrollRef, { precisionTreshold = 0 } = {}) {
30
30
  const [overflow, setOverflow] = (0, import_react.useState)({
31
31
  top: 0,
32
32
  bottom: 0,
@@ -38,11 +38,16 @@ function useScrollOverflow(scrollRef) {
38
38
  const scrollElement2 = scrollRef.current;
39
39
  if (scrollElement2) {
40
40
  const { scrollTop, scrollHeight, clientHeight, scrollLeft, scrollWidth, clientWidth } = scrollElement2;
41
+ const applyPrecision = (value) => {
42
+ return value <= precisionTreshold ? 0 : value;
43
+ };
44
+ const rightOverflow = scrollWidth - (scrollLeft + clientWidth);
45
+ const bottomOverflow = scrollHeight - (scrollTop + clientHeight);
41
46
  setOverflow({
42
- top: scrollTop,
43
- bottom: scrollHeight - (scrollTop + clientHeight),
44
- left: scrollLeft,
45
- right: scrollWidth - (scrollLeft + clientWidth)
47
+ top: applyPrecision(scrollTop),
48
+ bottom: applyPrecision(bottomOverflow),
49
+ left: applyPrecision(scrollLeft),
50
+ right: applyPrecision(rightOverflow)
46
51
  });
47
52
  }
48
53
  };
@@ -55,7 +60,7 @@ function useScrollOverflow(scrollRef) {
55
60
  return () => {
56
61
  if (scrollElement) {
57
62
  scrollElement.removeEventListener("scroll", checkScrollContent);
58
- window.addEventListener("resize", checkScrollContent);
63
+ window.removeEventListener("resize", checkScrollContent);
59
64
  }
60
65
  };
61
66
  }, [scrollRef]);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/use-scroll-overflow/index.ts","../../src/use-scroll-overflow/useScrollOverflow.tsx"],"sourcesContent":["export { useScrollOverflow } from './useScrollOverflow'\n\nexport type { ScrollOverflow } from './useScrollOverflow'\n","import { RefObject, useEffect, useState } from 'react'\n\nexport interface ScrollOverflow {\n top: number\n bottom: number\n left: number\n right: number\n}\n\nexport function useScrollOverflow(scrollRef: RefObject<HTMLElement | null>): ScrollOverflow {\n const [overflow, setOverflow] = useState<ScrollOverflow>({\n top: 0,\n bottom: 0,\n left: 0,\n right: 0,\n })\n\n useEffect(() => {\n const checkScrollContent = () => {\n const scrollElement = scrollRef.current\n\n if (scrollElement) {\n const { scrollTop, scrollHeight, clientHeight, scrollLeft, scrollWidth, clientWidth } =\n scrollElement\n\n setOverflow({\n top: scrollTop,\n bottom: scrollHeight - (scrollTop + clientHeight),\n left: scrollLeft,\n right: scrollWidth - (scrollLeft + clientWidth),\n })\n }\n }\n\n checkScrollContent()\n\n const scrollElement = scrollRef.current\n if (scrollElement) {\n scrollElement.addEventListener('scroll', checkScrollContent)\n window.addEventListener('resize', checkScrollContent)\n }\n\n return () => {\n if (scrollElement) {\n scrollElement.removeEventListener('scroll', checkScrollContent)\n window.addEventListener('resize', checkScrollContent)\n }\n }\n }, [scrollRef])\n\n return overflow\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,mBAA+C;AASxC,SAAS,kBAAkB,WAA0D;AAC1F,QAAM,CAAC,UAAU,WAAW,QAAI,uBAAyB;AAAA,IACvD,KAAK;AAAA,IACL,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,OAAO;AAAA,EACT,CAAC;AAED,8BAAU,MAAM;AACd,UAAM,qBAAqB,MAAM;AAC/B,YAAMA,iBAAgB,UAAU;AAEhC,UAAIA,gBAAe;AACjB,cAAM,EAAE,WAAW,cAAc,cAAc,YAAY,aAAa,YAAY,IAClFA;AAEF,oBAAY;AAAA,UACV,KAAK;AAAA,UACL,QAAQ,gBAAgB,YAAY;AAAA,UACpC,MAAM;AAAA,UACN,OAAO,eAAe,aAAa;AAAA,QACrC,CAAC;AAAA,MACH;AAAA,IACF;AAEA,uBAAmB;AAEnB,UAAM,gBAAgB,UAAU;AAChC,QAAI,eAAe;AACjB,oBAAc,iBAAiB,UAAU,kBAAkB;AAC3D,aAAO,iBAAiB,UAAU,kBAAkB;AAAA,IACtD;AAEA,WAAO,MAAM;AACX,UAAI,eAAe;AACjB,sBAAc,oBAAoB,UAAU,kBAAkB;AAC9D,eAAO,iBAAiB,UAAU,kBAAkB;AAAA,MACtD;AAAA,IACF;AAAA,EACF,GAAG,CAAC,SAAS,CAAC;AAEd,SAAO;AACT;","names":["scrollElement"]}
1
+ {"version":3,"sources":["../../src/use-scroll-overflow/index.ts","../../src/use-scroll-overflow/useScrollOverflow.tsx"],"sourcesContent":["export { useScrollOverflow } from './useScrollOverflow'\n\nexport type { ScrollOverflow } from './useScrollOverflow'\n","import { RefObject, useEffect, useState } from 'react'\n\nexport interface ScrollOverflow {\n top: number\n bottom: number\n left: number\n right: number\n}\n\nexport function useScrollOverflow(\n scrollRef: RefObject<HTMLElement | null>,\n /**\n * Tolerance threshold for floating-point precision issues.\n * Values below this threshold are considered as \"no overflow\" to handle sub-pixel rendering artifacts.\n */\n { precisionTreshold = 0 }: { precisionTreshold?: number } = {}\n): ScrollOverflow {\n const [overflow, setOverflow] = useState<ScrollOverflow>({\n top: 0,\n bottom: 0,\n left: 0,\n right: 0,\n })\n\n useEffect(() => {\n const checkScrollContent = () => {\n const scrollElement = scrollRef.current\n\n if (scrollElement) {\n const { scrollTop, scrollHeight, clientHeight, scrollLeft, scrollWidth, clientWidth } =\n scrollElement\n\n const applyPrecision = (value: number): number => {\n return value <= precisionTreshold ? 0 : value\n }\n\n const rightOverflow = scrollWidth - (scrollLeft + clientWidth)\n const bottomOverflow = scrollHeight - (scrollTop + clientHeight)\n\n setOverflow({\n top: applyPrecision(scrollTop),\n bottom: applyPrecision(bottomOverflow),\n left: applyPrecision(scrollLeft),\n right: applyPrecision(rightOverflow),\n })\n }\n }\n\n checkScrollContent()\n\n const scrollElement = scrollRef.current\n if (scrollElement) {\n scrollElement.addEventListener('scroll', checkScrollContent)\n window.addEventListener('resize', checkScrollContent)\n }\n\n return () => {\n if (scrollElement) {\n scrollElement.removeEventListener('scroll', checkScrollContent)\n window.removeEventListener('resize', checkScrollContent)\n }\n }\n }, [scrollRef])\n\n return overflow\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,mBAA+C;AASxC,SAAS,kBACd,WAKA,EAAE,oBAAoB,EAAE,IAAoC,CAAC,GAC7C;AAChB,QAAM,CAAC,UAAU,WAAW,QAAI,uBAAyB;AAAA,IACvD,KAAK;AAAA,IACL,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,OAAO;AAAA,EACT,CAAC;AAED,8BAAU,MAAM;AACd,UAAM,qBAAqB,MAAM;AAC/B,YAAMA,iBAAgB,UAAU;AAEhC,UAAIA,gBAAe;AACjB,cAAM,EAAE,WAAW,cAAc,cAAc,YAAY,aAAa,YAAY,IAClFA;AAEF,cAAM,iBAAiB,CAAC,UAA0B;AAChD,iBAAO,SAAS,oBAAoB,IAAI;AAAA,QAC1C;AAEA,cAAM,gBAAgB,eAAe,aAAa;AAClD,cAAM,iBAAiB,gBAAgB,YAAY;AAEnD,oBAAY;AAAA,UACV,KAAK,eAAe,SAAS;AAAA,UAC7B,QAAQ,eAAe,cAAc;AAAA,UACrC,MAAM,eAAe,UAAU;AAAA,UAC/B,OAAO,eAAe,aAAa;AAAA,QACrC,CAAC;AAAA,MACH;AAAA,IACF;AAEA,uBAAmB;AAEnB,UAAM,gBAAgB,UAAU;AAChC,QAAI,eAAe;AACjB,oBAAc,iBAAiB,UAAU,kBAAkB;AAC3D,aAAO,iBAAiB,UAAU,kBAAkB;AAAA,IACtD;AAEA,WAAO,MAAM;AACX,UAAI,eAAe;AACjB,sBAAc,oBAAoB,UAAU,kBAAkB;AAC9D,eAAO,oBAAoB,UAAU,kBAAkB;AAAA,MACzD;AAAA,IACF;AAAA,EACF,GAAG,CAAC,SAAS,CAAC;AAEd,SAAO;AACT;","names":["scrollElement"]}
@@ -1,6 +1,6 @@
1
1
  // src/use-scroll-overflow/useScrollOverflow.tsx
2
2
  import { useEffect, useState } from "react";
3
- function useScrollOverflow(scrollRef) {
3
+ function useScrollOverflow(scrollRef, { precisionTreshold = 0 } = {}) {
4
4
  const [overflow, setOverflow] = useState({
5
5
  top: 0,
6
6
  bottom: 0,
@@ -12,11 +12,16 @@ function useScrollOverflow(scrollRef) {
12
12
  const scrollElement2 = scrollRef.current;
13
13
  if (scrollElement2) {
14
14
  const { scrollTop, scrollHeight, clientHeight, scrollLeft, scrollWidth, clientWidth } = scrollElement2;
15
+ const applyPrecision = (value) => {
16
+ return value <= precisionTreshold ? 0 : value;
17
+ };
18
+ const rightOverflow = scrollWidth - (scrollLeft + clientWidth);
19
+ const bottomOverflow = scrollHeight - (scrollTop + clientHeight);
15
20
  setOverflow({
16
- top: scrollTop,
17
- bottom: scrollHeight - (scrollTop + clientHeight),
18
- left: scrollLeft,
19
- right: scrollWidth - (scrollLeft + clientWidth)
21
+ top: applyPrecision(scrollTop),
22
+ bottom: applyPrecision(bottomOverflow),
23
+ left: applyPrecision(scrollLeft),
24
+ right: applyPrecision(rightOverflow)
20
25
  });
21
26
  }
22
27
  };
@@ -29,7 +34,7 @@ function useScrollOverflow(scrollRef) {
29
34
  return () => {
30
35
  if (scrollElement) {
31
36
  scrollElement.removeEventListener("scroll", checkScrollContent);
32
- window.addEventListener("resize", checkScrollContent);
37
+ window.removeEventListener("resize", checkScrollContent);
33
38
  }
34
39
  };
35
40
  }, [scrollRef]);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/use-scroll-overflow/useScrollOverflow.tsx"],"sourcesContent":["import { RefObject, useEffect, useState } from 'react'\n\nexport interface ScrollOverflow {\n top: number\n bottom: number\n left: number\n right: number\n}\n\nexport function useScrollOverflow(scrollRef: RefObject<HTMLElement | null>): ScrollOverflow {\n const [overflow, setOverflow] = useState<ScrollOverflow>({\n top: 0,\n bottom: 0,\n left: 0,\n right: 0,\n })\n\n useEffect(() => {\n const checkScrollContent = () => {\n const scrollElement = scrollRef.current\n\n if (scrollElement) {\n const { scrollTop, scrollHeight, clientHeight, scrollLeft, scrollWidth, clientWidth } =\n scrollElement\n\n setOverflow({\n top: scrollTop,\n bottom: scrollHeight - (scrollTop + clientHeight),\n left: scrollLeft,\n right: scrollWidth - (scrollLeft + clientWidth),\n })\n }\n }\n\n checkScrollContent()\n\n const scrollElement = scrollRef.current\n if (scrollElement) {\n scrollElement.addEventListener('scroll', checkScrollContent)\n window.addEventListener('resize', checkScrollContent)\n }\n\n return () => {\n if (scrollElement) {\n scrollElement.removeEventListener('scroll', checkScrollContent)\n window.addEventListener('resize', checkScrollContent)\n }\n }\n }, [scrollRef])\n\n return overflow\n}\n"],"mappings":";AAAA,SAAoB,WAAW,gBAAgB;AASxC,SAAS,kBAAkB,WAA0D;AAC1F,QAAM,CAAC,UAAU,WAAW,IAAI,SAAyB;AAAA,IACvD,KAAK;AAAA,IACL,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,OAAO;AAAA,EACT,CAAC;AAED,YAAU,MAAM;AACd,UAAM,qBAAqB,MAAM;AAC/B,YAAMA,iBAAgB,UAAU;AAEhC,UAAIA,gBAAe;AACjB,cAAM,EAAE,WAAW,cAAc,cAAc,YAAY,aAAa,YAAY,IAClFA;AAEF,oBAAY;AAAA,UACV,KAAK;AAAA,UACL,QAAQ,gBAAgB,YAAY;AAAA,UACpC,MAAM;AAAA,UACN,OAAO,eAAe,aAAa;AAAA,QACrC,CAAC;AAAA,MACH;AAAA,IACF;AAEA,uBAAmB;AAEnB,UAAM,gBAAgB,UAAU;AAChC,QAAI,eAAe;AACjB,oBAAc,iBAAiB,UAAU,kBAAkB;AAC3D,aAAO,iBAAiB,UAAU,kBAAkB;AAAA,IACtD;AAEA,WAAO,MAAM;AACX,UAAI,eAAe;AACjB,sBAAc,oBAAoB,UAAU,kBAAkB;AAC9D,eAAO,iBAAiB,UAAU,kBAAkB;AAAA,MACtD;AAAA,IACF;AAAA,EACF,GAAG,CAAC,SAAS,CAAC;AAEd,SAAO;AACT;","names":["scrollElement"]}
1
+ {"version":3,"sources":["../../src/use-scroll-overflow/useScrollOverflow.tsx"],"sourcesContent":["import { RefObject, useEffect, useState } from 'react'\n\nexport interface ScrollOverflow {\n top: number\n bottom: number\n left: number\n right: number\n}\n\nexport function useScrollOverflow(\n scrollRef: RefObject<HTMLElement | null>,\n /**\n * Tolerance threshold for floating-point precision issues.\n * Values below this threshold are considered as \"no overflow\" to handle sub-pixel rendering artifacts.\n */\n { precisionTreshold = 0 }: { precisionTreshold?: number } = {}\n): ScrollOverflow {\n const [overflow, setOverflow] = useState<ScrollOverflow>({\n top: 0,\n bottom: 0,\n left: 0,\n right: 0,\n })\n\n useEffect(() => {\n const checkScrollContent = () => {\n const scrollElement = scrollRef.current\n\n if (scrollElement) {\n const { scrollTop, scrollHeight, clientHeight, scrollLeft, scrollWidth, clientWidth } =\n scrollElement\n\n const applyPrecision = (value: number): number => {\n return value <= precisionTreshold ? 0 : value\n }\n\n const rightOverflow = scrollWidth - (scrollLeft + clientWidth)\n const bottomOverflow = scrollHeight - (scrollTop + clientHeight)\n\n setOverflow({\n top: applyPrecision(scrollTop),\n bottom: applyPrecision(bottomOverflow),\n left: applyPrecision(scrollLeft),\n right: applyPrecision(rightOverflow),\n })\n }\n }\n\n checkScrollContent()\n\n const scrollElement = scrollRef.current\n if (scrollElement) {\n scrollElement.addEventListener('scroll', checkScrollContent)\n window.addEventListener('resize', checkScrollContent)\n }\n\n return () => {\n if (scrollElement) {\n scrollElement.removeEventListener('scroll', checkScrollContent)\n window.removeEventListener('resize', checkScrollContent)\n }\n }\n }, [scrollRef])\n\n return overflow\n}\n"],"mappings":";AAAA,SAAoB,WAAW,gBAAgB;AASxC,SAAS,kBACd,WAKA,EAAE,oBAAoB,EAAE,IAAoC,CAAC,GAC7C;AAChB,QAAM,CAAC,UAAU,WAAW,IAAI,SAAyB;AAAA,IACvD,KAAK;AAAA,IACL,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,OAAO;AAAA,EACT,CAAC;AAED,YAAU,MAAM;AACd,UAAM,qBAAqB,MAAM;AAC/B,YAAMA,iBAAgB,UAAU;AAEhC,UAAIA,gBAAe;AACjB,cAAM,EAAE,WAAW,cAAc,cAAc,YAAY,aAAa,YAAY,IAClFA;AAEF,cAAM,iBAAiB,CAAC,UAA0B;AAChD,iBAAO,SAAS,oBAAoB,IAAI;AAAA,QAC1C;AAEA,cAAM,gBAAgB,eAAe,aAAa;AAClD,cAAM,iBAAiB,gBAAgB,YAAY;AAEnD,oBAAY;AAAA,UACV,KAAK,eAAe,SAAS;AAAA,UAC7B,QAAQ,eAAe,cAAc;AAAA,UACrC,MAAM,eAAe,UAAU;AAAA,UAC/B,OAAO,eAAe,aAAa;AAAA,QACrC,CAAC;AAAA,MACH;AAAA,IACF;AAEA,uBAAmB;AAEnB,UAAM,gBAAgB,UAAU;AAChC,QAAI,eAAe;AACjB,oBAAc,iBAAiB,UAAU,kBAAkB;AAC3D,aAAO,iBAAiB,UAAU,kBAAkB;AAAA,IACtD;AAEA,WAAO,MAAM;AACX,UAAI,eAAe;AACjB,sBAAc,oBAAoB,UAAU,kBAAkB;AAC9D,eAAO,oBAAoB,UAAU,kBAAkB;AAAA,MACzD;AAAA,IACF;AAAA,EACF,GAAG,CAAC,SAAS,CAAC;AAEd,SAAO;AACT;","names":["scrollElement"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spark-ui/hooks",
3
- "version": "10.16.1",
3
+ "version": "10.17.0",
4
4
  "description": "Common hooks for Spark UI",
5
5
  "exports": {
6
6
  "./*": {
@@ -49,5 +49,5 @@
49
49
  },
50
50
  "homepage": "https://sparkui.vercel.app",
51
51
  "license": "MIT",
52
- "gitHead": "94fa2b811a14f1d666e0bd90e894afd1f37c94c5"
52
+ "gitHead": "489b5d6da6a41e1411ddb62646cf65b242747a9e"
53
53
  }