@julseb-lib/react 1.0.46 → 1.0.47
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/dist/index.cjs +63 -36
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -11
- package/dist/index.d.ts +15 -11
- package/dist/index.js +63 -36
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -532,28 +532,32 @@ declare const usePagination: ({ currentPage, setCurrentPage, totalPages, }: ILib
|
|
|
532
532
|
};
|
|
533
533
|
|
|
534
534
|
/**
|
|
535
|
-
* Hook for calculating the number of lines text will occupy in a
|
|
535
|
+
* Hook for calculating the number of visual lines text will occupy in a textarea or input element based on actual rendered dimensions and styling.
|
|
536
536
|
*
|
|
537
537
|
* @hook
|
|
538
538
|
*
|
|
539
539
|
* @example
|
|
540
|
-
* const
|
|
541
|
-
*
|
|
542
|
-
*
|
|
543
|
-
*
|
|
544
|
-
*
|
|
540
|
+
* const { visualLines, elementRef } = useTextLineCount("Long text content", 16)
|
|
541
|
+
*
|
|
542
|
+
* return (
|
|
543
|
+
* <textarea
|
|
544
|
+
* ref={elementRef}
|
|
545
|
+
* value={text}
|
|
546
|
+
* style={{ height: `${visualLines * 1.5}rem` }}
|
|
547
|
+
* />
|
|
545
548
|
* )
|
|
546
549
|
*
|
|
547
550
|
* @param {string} text - The text content to measure for line count.
|
|
548
|
-
* @param {number}
|
|
549
|
-
* @param {number} [fontSize=16] - The font size in pixels. Default: 16.
|
|
550
|
-
* @param {string} [fontFamily="lato"] - The font family to use for measurement. Default: "system-ui".
|
|
551
|
+
* @param {number} [fontSize=16] - The font size in pixels for fallback calculations. Default: 16.
|
|
551
552
|
*
|
|
552
|
-
* @returns {number}
|
|
553
|
+
* @returns {{ visualLines: number; elementRef: React.RefObject<HTMLTextAreaElement | HTMLInputElement> }} Object containing the calculated visual line count and element ref to attach to the target element.
|
|
553
554
|
*
|
|
554
555
|
* @see https://doc-julseb-lib-react.vercel.app/hooks/use-text-line-count
|
|
555
556
|
*/
|
|
556
|
-
declare const useTextLineCount: (text: string,
|
|
557
|
+
declare const useTextLineCount: (text: string, fontSize?: number) => {
|
|
558
|
+
visualLines: number;
|
|
559
|
+
elementRef: react.RefObject<HTMLTextAreaElement | HTMLInputElement | null>;
|
|
560
|
+
};
|
|
557
561
|
|
|
558
562
|
/**
|
|
559
563
|
* Hook to detect if the current device supports touch screen interaction.
|
package/dist/index.d.ts
CHANGED
|
@@ -532,28 +532,32 @@ declare const usePagination: ({ currentPage, setCurrentPage, totalPages, }: ILib
|
|
|
532
532
|
};
|
|
533
533
|
|
|
534
534
|
/**
|
|
535
|
-
* Hook for calculating the number of lines text will occupy in a
|
|
535
|
+
* Hook for calculating the number of visual lines text will occupy in a textarea or input element based on actual rendered dimensions and styling.
|
|
536
536
|
*
|
|
537
537
|
* @hook
|
|
538
538
|
*
|
|
539
539
|
* @example
|
|
540
|
-
* const
|
|
541
|
-
*
|
|
542
|
-
*
|
|
543
|
-
*
|
|
544
|
-
*
|
|
540
|
+
* const { visualLines, elementRef } = useTextLineCount("Long text content", 16)
|
|
541
|
+
*
|
|
542
|
+
* return (
|
|
543
|
+
* <textarea
|
|
544
|
+
* ref={elementRef}
|
|
545
|
+
* value={text}
|
|
546
|
+
* style={{ height: `${visualLines * 1.5}rem` }}
|
|
547
|
+
* />
|
|
545
548
|
* )
|
|
546
549
|
*
|
|
547
550
|
* @param {string} text - The text content to measure for line count.
|
|
548
|
-
* @param {number}
|
|
549
|
-
* @param {number} [fontSize=16] - The font size in pixels. Default: 16.
|
|
550
|
-
* @param {string} [fontFamily="lato"] - The font family to use for measurement. Default: "system-ui".
|
|
551
|
+
* @param {number} [fontSize=16] - The font size in pixels for fallback calculations. Default: 16.
|
|
551
552
|
*
|
|
552
|
-
* @returns {number}
|
|
553
|
+
* @returns {{ visualLines: number; elementRef: React.RefObject<HTMLTextAreaElement | HTMLInputElement> }} Object containing the calculated visual line count and element ref to attach to the target element.
|
|
553
554
|
*
|
|
554
555
|
* @see https://doc-julseb-lib-react.vercel.app/hooks/use-text-line-count
|
|
555
556
|
*/
|
|
556
|
-
declare const useTextLineCount: (text: string,
|
|
557
|
+
declare const useTextLineCount: (text: string, fontSize?: number) => {
|
|
558
|
+
visualLines: number;
|
|
559
|
+
elementRef: react.RefObject<HTMLTextAreaElement | HTMLInputElement | null>;
|
|
560
|
+
};
|
|
557
561
|
|
|
558
562
|
/**
|
|
559
563
|
* Hook to detect if the current device supports touch screen interaction.
|
package/dist/index.js
CHANGED
|
@@ -2312,48 +2312,75 @@ var usePagination = ({
|
|
|
2312
2312
|
|
|
2313
2313
|
// src/lib/hooks/useTextLineCount.tsx
|
|
2314
2314
|
import { useState as useState8, useRef, useCallback, useEffect as useEffect7 } from "react";
|
|
2315
|
-
var useTextLineCount = (text,
|
|
2316
|
-
const [
|
|
2317
|
-
const
|
|
2315
|
+
var useTextLineCount = (text, fontSize = 16) => {
|
|
2316
|
+
const [visualLines, setVisualLines] = useState8(1);
|
|
2317
|
+
const elementRef = useRef(
|
|
2318
|
+
null
|
|
2319
|
+
);
|
|
2318
2320
|
const measureLines = useCallback(() => {
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
+
const element = elementRef.current;
|
|
2322
|
+
if (!element || !text) {
|
|
2323
|
+
setVisualLines(1);
|
|
2324
|
+
return;
|
|
2321
2325
|
}
|
|
2322
|
-
const
|
|
2323
|
-
const
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
+
const computedStyle = getComputedStyle(element);
|
|
2327
|
+
const paddingLeft = parseInt(computedStyle.paddingLeft) || 0;
|
|
2328
|
+
const paddingRight = parseInt(computedStyle.paddingRight) || 0;
|
|
2329
|
+
const borderLeft = parseInt(computedStyle.borderLeftWidth) || 0;
|
|
2330
|
+
const borderRight = parseInt(computedStyle.borderRightWidth) || 0;
|
|
2331
|
+
const actualWidth = element.offsetWidth - paddingLeft - paddingRight - borderLeft - borderRight;
|
|
2332
|
+
if (actualWidth <= 0) {
|
|
2333
|
+
setVisualLines(1);
|
|
2326
2334
|
return;
|
|
2327
2335
|
}
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2336
|
+
try {
|
|
2337
|
+
const hiddenDiv = document.createElement("div");
|
|
2338
|
+
hiddenDiv.style.position = "absolute";
|
|
2339
|
+
hiddenDiv.style.visibility = "hidden";
|
|
2340
|
+
hiddenDiv.style.height = "auto";
|
|
2341
|
+
hiddenDiv.style.width = `${actualWidth}px`;
|
|
2342
|
+
hiddenDiv.style.fontSize = computedStyle.fontSize || `${fontSize}px`;
|
|
2343
|
+
hiddenDiv.style.fontFamily = computedStyle.fontFamily || "system-ui";
|
|
2344
|
+
hiddenDiv.style.lineHeight = computedStyle.lineHeight || "1.2";
|
|
2345
|
+
hiddenDiv.style.wordWrap = "break-word";
|
|
2346
|
+
hiddenDiv.style.whiteSpace = "pre-wrap";
|
|
2347
|
+
hiddenDiv.style.padding = "0";
|
|
2348
|
+
hiddenDiv.style.margin = "0";
|
|
2349
|
+
hiddenDiv.style.border = "none";
|
|
2350
|
+
document.body.appendChild(hiddenDiv);
|
|
2351
|
+
hiddenDiv.textContent = text;
|
|
2352
|
+
const elementHeight = hiddenDiv.offsetHeight;
|
|
2353
|
+
const lineHeight = parseInt(getComputedStyle(hiddenDiv).lineHeight) || fontSize * 1.2;
|
|
2354
|
+
const calculatedLines = Math.max(
|
|
2355
|
+
1,
|
|
2356
|
+
Math.round(elementHeight / lineHeight)
|
|
2357
|
+
);
|
|
2358
|
+
document.body.removeChild(hiddenDiv);
|
|
2359
|
+
setVisualLines(calculatedLines);
|
|
2360
|
+
} catch (error) {
|
|
2361
|
+
console.warn("Element line count measurement failed:", error);
|
|
2362
|
+
setVisualLines(text.split("\n").length);
|
|
2363
|
+
}
|
|
2364
|
+
}, [text, fontSize]);
|
|
2353
2365
|
useEffect7(() => {
|
|
2354
|
-
measureLines
|
|
2366
|
+
const timer = setTimeout(measureLines, 50);
|
|
2367
|
+
return () => clearTimeout(timer);
|
|
2355
2368
|
}, [measureLines]);
|
|
2356
|
-
|
|
2369
|
+
useEffect7(() => {
|
|
2370
|
+
const element = elementRef.current;
|
|
2371
|
+
if (!element) return;
|
|
2372
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
2373
|
+
measureLines();
|
|
2374
|
+
});
|
|
2375
|
+
resizeObserver.observe(element);
|
|
2376
|
+
return () => {
|
|
2377
|
+
resizeObserver.disconnect();
|
|
2378
|
+
};
|
|
2379
|
+
}, [measureLines]);
|
|
2380
|
+
return {
|
|
2381
|
+
visualLines,
|
|
2382
|
+
elementRef
|
|
2383
|
+
};
|
|
2357
2384
|
};
|
|
2358
2385
|
|
|
2359
2386
|
// src/lib/hooks/useTouchScreen.tsx
|