Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@pluralsight/react-utils

Package Overview
Dependencies
Maintainers
1
Versions
1213
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@pluralsight/react-utils - npm Package Compare versions

Comparing version 0.7.1-next-f09ded to 0.7.1-next-f24c2e

5

build/legacy/_tsup-dts-rollup.d.ts

@@ -112,7 +112,2 @@ import { ChangeEvent } from 'react';

export declare function useTheme<T extends string>(initialTheme?: CustomThemes<T>): {
theme: CustomThemes<T>;
updateTheme: (theme: CustomThemes<T>) => void;
};
export { }

40

build/legacy/helpers/createResource.js

@@ -1,7 +0,35 @@

import {
createPreloadedImgResource,
createResource,
resourceCache
} from "../chunk-D4SRYCOP.js";
import "../chunk-MRY5H4GP.js";
// src/helpers/createResource.ts
import { loadImage, preloadImgResource } from "./loaders.js";
var resourceCache = /* @__PURE__ */ new Map();
function createResource(promise) {
let status = "pending";
let result = promise.then(
(resolved) => {
status = "success";
result = resolved;
},
(rejected) => {
status = "error";
result = rejected;
}
);
return {
read: () => {
switch (status) {
case "error":
throw result;
case "pending":
case "success":
return result;
default:
throw new Error("This should be impossible.");
}
}
};
}
function createPreloadedImgResource(imgOptions) {
const data = createResource(preloadImgResource(imgOptions));
const img = createResource(loadImage(imgOptions));
return { data, img };
}
export {

@@ -8,0 +36,0 @@ createPreloadedImgResource,

@@ -1,6 +0,41 @@

import {
loadImage,
preloadImgResource,
preloadResource
} from "../chunk-MRY5H4GP.js";
// src/helpers/loaders.ts
function preloadResource(resourceOptions) {
return new Promise((resolve, reject) => {
const link = document.createElement("link");
link.rel = "preload";
link.as = resourceOptions.as;
link.media = resourceOptions.media ?? "all";
link.href = resourceOptions.href;
link.onload = resolve;
link.onerror = reject;
document.body.appendChild(link);
});
}
function preloadImgResource(imgOptions) {
const { srcSet } = imgOptions;
return new Promise((resolve, reject) => {
const link = document.createElement("link");
if (srcSet) {
link.imageSrcset = srcSet;
}
link.rel = "preload";
link.as = "image";
link.href = imgOptions.src ?? "";
link.onload = resolve;
link.onerror = reject;
document.body.appendChild(link);
});
}
function loadImage(imgOptions) {
const { src, srcSet } = imgOptions;
return new Promise((resolve, reject) => {
const img = document.createElement("img");
if (srcSet) {
img.srcset = srcSet;
}
img.src = src ?? "";
img.onload = () => resolve(imgOptions);
img.onerror = reject;
});
}
export {

@@ -7,0 +42,0 @@ loadImage,

@@ -1,7 +0,30 @@

import {
THEME_KEY,
getAppliedTheme,
getCachedTheme,
setCachedTheme
} from "../chunk-SO6SAJGK.js";
// src/helpers/themeHelpers.ts
var THEME_KEY = "pandoTheme";
var DARK = "dark";
var LIGHT = "light";
var SYSTEM = "system";
function getAppliedTheme(userPreference) {
const choseSystem = userPreference === SYSTEM;
if (userPreference === LIGHT) {
return LIGHT;
}
if (userPreference === DARK) {
return DARK;
}
if (choseSystem && (window == null ? void 0 : window.matchMedia("(prefers-color-scheme: light)").matches)) {
return LIGHT;
}
if (choseSystem && (window == null ? void 0 : window.matchMedia("(prefers-color-scheme: dark)").matches)) {
return DARK;
}
return choseSystem ? DARK : userPreference;
}
function getCachedTheme() {
const cachedTheme = (window == null ? void 0 : window.localStorage.getItem(THEME_KEY)) ?? DARK;
return cachedTheme;
}
function setCachedTheme(theme) {
document == null ? void 0 : document.documentElement.setAttribute("data-theme", getAppliedTheme(theme));
window == null ? void 0 : window.localStorage.setItem(THEME_KEY, theme);
}
export {

@@ -8,0 +31,0 @@ THEME_KEY,

"use client";
// src/hooks/useAutoFormatDate.ts
import {
useAutoFormatDate
} from "../chunk-MJ3R5LPV.js";
useCallback,
useState,
useMemo
} from "react";
var DELIMITER = "/";
function useAutoFormatDate(options) {
const { pattern, value } = defaultAutoFormatOptions(options);
const [formattedDate, setFormattedDate] = useState(value);
const blocks = useMemo(() => getBlocks(pattern), [pattern]);
const template = useMemo(
() => getTemplate(pattern, blocks),
[pattern, blocks]
);
const handleDateChange = useCallback(
(e) => {
return setFormattedDate((prev) => {
const userInput = e.target.value;
const startingCursor = e.target.selectionStart ?? userInput.length;
const { formattedDate: formattedDate2, cursorPosition } = formatDateInput({
blocks,
cursorPosition: startingCursor,
pattern,
value: userInput,
prevValue: prev
});
if (startingCursor !== userInput.length) {
setCursorPosition(e.target, cursorPosition);
}
return formattedDate2;
});
},
[blocks, pattern]
);
const handleDateBlur = useCallback(
(e) => {
return setFormattedDate(
(prev) => formatDateInput({
blocks,
cursorPosition: e.target.value.length,
pattern,
prevValue: prev,
value: e.target.value
}).formattedDate
);
},
[blocks, pattern]
);
return useMemo(
() => ({
onBlur: handleDateBlur,
onChange: handleDateChange,
placeholder: template,
maxLength: template.length,
value: formattedDate
}),
[handleDateBlur, handleDateChange, template, formattedDate]
);
}
function defaultAutoFormatOptions(options) {
return {
pattern: (options == null ? void 0 : options.pattern) ?? ["m", "d", "Y"],
value: (options == null ? void 0 : options.value) ?? ""
};
}
function setCursorPosition(element, position) {
requestAnimationFrame(() => element.setSelectionRange(position, position));
}
function formatDateInput(options) {
const { blocks, cursorPosition, pattern, prevValue, value } = options;
const template = getTemplate(pattern, blocks);
if ((prevValue == null ? void 0 : prevValue.length) > value.length) {
return {
formattedDate: value,
cursorPosition
};
}
if (value.length > template.length || getCharCount(DELIMITER, value) > pattern.length - 1) {
return {
formattedDate: prevValue,
cursorPosition: cursorPosition - (value.length - (prevValue == null ? void 0 : prevValue.length))
};
}
const { formattedDateParts, cursor } = getFormattedDateParts(options);
if (Object.values(formattedDateParts).join(DELIMITER).length === template.length) {
const correctedDateParts = getCorrectedDateParts(formattedDateParts);
return {
formattedDate: combineDateParts(correctedDateParts, pattern),
cursorPosition: cursor
};
}
return {
formattedDate: combineDateParts(formattedDateParts, pattern),
cursorPosition: cursor
};
}
function getCharCount(char, str) {
return (str.match(new RegExp(char, "g")) || []).length;
}
function strToInt(value) {
return parseInt(value, 10);
}
function getFormattedDateParts(options) {
const { blocks, cursorPosition, pattern, value } = options;
const chars = value.split("");
let cursor = cursorPosition;
let currentBlock = pattern[0];
const dateParts = {
d: "",
m: "",
Y: ""
};
for (let i = 0; i < chars.length && currentBlock !== null; i += 1) {
if (chars[i] !== DELIMITER) {
dateParts[currentBlock] += chars[i];
}
const formatted = formatDateBlock(
currentBlock,
dateParts[currentBlock],
chars[i] === DELIMITER && cursorPosition > i
);
cursor += getCursorOffset(
cursorPosition,
i,
formatted.length - dateParts[currentBlock].length
);
dateParts[currentBlock] = formatted;
if (isDatePartComplete(
dateParts[currentBlock],
currentBlock,
blocks,
pattern
) || isBlockEndedByDelimiter(
chars[i],
dateParts[currentBlock],
getNextBlock(currentBlock, pattern)
)) {
currentBlock = getNextBlock(currentBlock, pattern);
}
}
return {
formattedDateParts: dateParts,
cursor
};
}
function getCursorOffset(cursor, index, value) {
if (cursor > index) {
return value;
}
return 0;
}
function isDatePartComplete(datePart, block, blocks, pattern) {
return datePart.length === blocks[pattern.indexOf(block)];
}
function isBlockEndedByDelimiter(currentChar, datePart, nextBlock) {
return currentChar === DELIMITER && datePart.length && nextBlock !== null;
}
function getNextBlock(current, pattern) {
return pattern[pattern.indexOf(current) + 1] ?? null;
}
function formatDateBlock(blockId, value, complete) {
const cleanValue = getSanitizedNumericString(value);
if (!cleanValue) {
return cleanValue;
}
switch (blockId) {
case "m":
return formatMonth(cleanValue, complete);
case "d":
return formatDay(cleanValue, complete);
default:
return cleanValue;
}
}
function formatDay(value, complete) {
const numericValue = parseInt(value, 10);
if (value.length === 1) {
if (complete || numericValue * 10 > 31) {
return `0${Math.max(numericValue, 1)}`;
}
} else {
if (numericValue > 31) {
return "31";
} else if (numericValue < 1) {
return "01";
}
}
return value;
}
function formatMonth(value, complete) {
const numericValue = parseInt(value, 10);
if (value.length === 1) {
if (complete || numericValue * 10 > 12) {
return `0${Math.max(numericValue, 1)}`;
}
} else {
if (numericValue > 12) {
return "12";
} else if (numericValue < 1) {
return "01";
}
}
return value;
}
function getSanitizedNumericString(value) {
return value.replace(/[^0-9]/g, "");
}
function combineDateParts(dateParts, pattern) {
const blocks = getBlocks(pattern);
return pattern.map((block) => {
const nextBlock = getNextBlock(block, pattern);
const blockIdx = pattern.indexOf(block);
const insertDelimiter = nextBlock && (dateParts[nextBlock] || dateParts[block].length === blocks[blockIdx]);
if (insertDelimiter) {
return dateParts[block] + DELIMITER;
} else {
return dateParts[block];
}
}).join("");
}
function getBlocks(pattern) {
const blocks = [];
pattern.forEach(function(value) {
if (value === "Y") {
blocks.push(4);
} else {
blocks.push(2);
}
});
return blocks;
}
function getTemplate(pattern, blocks) {
return pattern.map((letter, idx) => {
const count = blocks[idx];
return letter.repeat(count).toUpperCase();
}).join("/");
}
function getCorrectedDateParts(dateParts) {
const correctedDay = correctDayForMonth(
strToInt(dateParts.d),
strToInt(dateParts.m),
strToInt(dateParts.Y)
);
return {
d: formatDay(correctedDay.toString(), true),
m: dateParts.m,
Y: dateParts.Y
};
}
function correctDayForMonth(day, month, year) {
day = Math.min(day, 31);
month = Math.min(month, 12);
year = parseInt(String(year || 0), 10);
if (month < 7 && month % 2 === 0 || month > 8 && month % 2 === 1) {
const leapDay = isLeapYear(year) ? 29 : 28;
return Math.min(day, month === 2 ? leapDay : 30);
}
return day;
}
function isLeapYear(year) {
return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
}
export {

@@ -6,0 +267,0 @@ useAutoFormatDate

"use client";
import {
useEscToClose
} from "../chunk-VYA2NVJ4.js";
// src/hooks/useEscToClose.ts
import { useEffect } from "react";
function useEscToClose(onClose) {
useEffect(() => {
function handleEscClose(event) {
if (event.key === "Escape") {
event.stopPropagation();
event.preventDefault();
onClose();
}
}
window.addEventListener("keydown", handleEscClose, false);
return () => {
window.removeEventListener("keydown", handleEscClose, false);
};
}, [onClose]);
return null;
}
export {

@@ -6,0 +22,0 @@ useEscToClose

"use client";
// src/hooks/useFocusTrap.ts
import {
useFocusTrap
} from "../chunk-2AC32EVF.js";
useCallback,
useEffect
} from "react";
function useFocusTrap(dialogRef) {
const selectorList = 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';
const getFocusItems = useCallback(() => {
var _a;
const focusableItems = ((_a = dialogRef == null ? void 0 : dialogRef.current) == null ? void 0 : _a.querySelectorAll(selectorList)) ?? [];
return {
firstItem: focusableItems[0],
lastItem: focusableItems[focusableItems.length - 1]
};
}, [dialogRef]);
const handleFocus = useCallback(
(event) => {
const { activeElement } = document;
const { firstItem, lastItem } = getFocusItems();
if (event.key !== "Tab") {
return;
}
if (event.shiftKey) {
if (activeElement === firstItem) {
event.preventDefault();
lastItem.focus();
}
} else {
if (activeElement === lastItem) {
event.preventDefault();
firstItem.focus();
}
}
},
[getFocusItems]
);
const handleInitFocusTrap = useCallback(() => {
if ((dialogRef == null ? void 0 : dialogRef.current) != null) {
const { firstItem } = getFocusItems();
if (document.activeElement !== firstItem) {
firstItem == null ? void 0 : firstItem.focus();
}
}
}, [dialogRef, getFocusItems]);
useEffect(() => {
handleInitFocusTrap();
}, [handleInitFocusTrap]);
return {
onKeyDown: handleFocus
};
}
export {

@@ -6,0 +55,0 @@ useFocusTrap

"use client";
import {
useIsIndeterminate
} from "../chunk-HWPTZ2IF.js";
// src/hooks/useIsIndeterminate.ts
import { useMemo } from "react";
function useIsIndeterminate(checkboxOptions) {
const checkedItems = Object.keys(checkboxOptions).map(
(optionItem) => checkboxOptions[optionItem]
);
const allChecked = checkedItems.every(Boolean);
return useMemo(
() => (checkedItems.some(Boolean) && !allChecked) ?? false,
[allChecked, checkedItems]
);
}
export {

@@ -6,0 +16,0 @@ useIsIndeterminate

"use client";
// src/hooks/usePreloadedImg.ts
import { useEffect, useState, useTransition } from "react";
import {
usePreloadedImg
} from "../chunk-S6QQHARX.js";
import "../chunk-D4SRYCOP.js";
import "../chunk-MRY5H4GP.js";
resourceCache,
createPreloadedImgResource
} from "../helpers/createResource.js";
function getPreloadedImgResource(imgOptions) {
const { src } = imgOptions;
let resource = resourceCache.get(src);
if (!resource) {
resource = createPreloadedImgResource(imgOptions);
resourceCache.set(src, resource);
}
return resource;
}
function usePreloadedImg(imgOptions) {
const { src, srcSet } = imgOptions;
const [, startTransition] = useTransition();
const [resource, setResource] = useState(null);
useEffect(() => {
if (resource) {
return;
}
startTransition(() => {
setResource(getPreloadedImgResource({ src, srcSet }));
});
}, [resource, src, srcSet, startTransition]);
return resource;
}
export {

@@ -8,0 +33,0 @@ usePreloadedImg

@@ -1,22 +0,8 @@

import {
useEscToClose
} from "./chunk-VYA2NVJ4.js";
import {
useFocusTrap
} from "./chunk-2AC32EVF.js";
import {
useIsIndeterminate
} from "./chunk-HWPTZ2IF.js";
import {
usePreloadedImg
} from "./chunk-S6QQHARX.js";
import "./chunk-D4SRYCOP.js";
import "./chunk-MRY5H4GP.js";
import {
getCachedTheme,
setCachedTheme
} from "./chunk-SO6SAJGK.js";
import {
useAutoFormatDate
} from "./chunk-MJ3R5LPV.js";
// src/index.ts
import { getCachedTheme, setCachedTheme } from "./helpers/themeHelpers.js";
import { useAutoFormatDate } from "./hooks/useAutoFormatDate.js";
import { useEscToClose } from "./hooks/useEscToClose.js";
import { useFocusTrap } from "./hooks/useFocusTrap.js";
import { useIsIndeterminate } from "./hooks/useIsIndeterminate.js";
import { usePreloadedImg } from "./hooks/usePreloadedImg.js";
export {

@@ -23,0 +9,0 @@ getCachedTheme,

@@ -112,7 +112,2 @@ import { ChangeEvent } from 'react';

export declare function useTheme<T extends string>(initialTheme?: CustomThemes<T>): {
theme: CustomThemes<T>;
updateTheme: (theme: CustomThemes<T>) => void;
};
export { }

@@ -1,7 +0,35 @@

import {
createPreloadedImgResource,
createResource,
resourceCache
} from "../chunk-D4SRYCOP.js";
import "../chunk-MRY5H4GP.js";
// src/helpers/createResource.ts
import { loadImage, preloadImgResource } from "./loaders.js";
var resourceCache = /* @__PURE__ */ new Map();
function createResource(promise) {
let status = "pending";
let result = promise.then(
(resolved) => {
status = "success";
result = resolved;
},
(rejected) => {
status = "error";
result = rejected;
}
);
return {
read: () => {
switch (status) {
case "error":
throw result;
case "pending":
case "success":
return result;
default:
throw new Error("This should be impossible.");
}
}
};
}
function createPreloadedImgResource(imgOptions) {
const data = createResource(preloadImgResource(imgOptions));
const img = createResource(loadImage(imgOptions));
return { data, img };
}
export {

@@ -8,0 +36,0 @@ createPreloadedImgResource,

@@ -1,6 +0,41 @@

import {
loadImage,
preloadImgResource,
preloadResource
} from "../chunk-MRY5H4GP.js";
// src/helpers/loaders.ts
function preloadResource(resourceOptions) {
return new Promise((resolve, reject) => {
const link = document.createElement("link");
link.rel = "preload";
link.as = resourceOptions.as;
link.media = resourceOptions.media ?? "all";
link.href = resourceOptions.href;
link.onload = resolve;
link.onerror = reject;
document.body.appendChild(link);
});
}
function preloadImgResource(imgOptions) {
const { srcSet } = imgOptions;
return new Promise((resolve, reject) => {
const link = document.createElement("link");
if (srcSet) {
link.imageSrcset = srcSet;
}
link.rel = "preload";
link.as = "image";
link.href = imgOptions.src ?? "";
link.onload = resolve;
link.onerror = reject;
document.body.appendChild(link);
});
}
function loadImage(imgOptions) {
const { src, srcSet } = imgOptions;
return new Promise((resolve, reject) => {
const img = document.createElement("img");
if (srcSet) {
img.srcset = srcSet;
}
img.src = src ?? "";
img.onload = () => resolve(imgOptions);
img.onerror = reject;
});
}
export {

@@ -7,0 +42,0 @@ loadImage,

@@ -1,7 +0,30 @@

import {
THEME_KEY,
getAppliedTheme,
getCachedTheme,
setCachedTheme
} from "../chunk-J6CAGWHA.js";
// src/helpers/themeHelpers.ts
var THEME_KEY = "pandoTheme";
var DARK = "dark";
var LIGHT = "light";
var SYSTEM = "system";
function getAppliedTheme(userPreference) {
const choseSystem = userPreference === SYSTEM;
if (userPreference === LIGHT) {
return LIGHT;
}
if (userPreference === DARK) {
return DARK;
}
if (choseSystem && window?.matchMedia("(prefers-color-scheme: light)").matches) {
return LIGHT;
}
if (choseSystem && window?.matchMedia("(prefers-color-scheme: dark)").matches) {
return DARK;
}
return choseSystem ? DARK : userPreference;
}
function getCachedTheme() {
const cachedTheme = window?.localStorage.getItem(THEME_KEY) ?? DARK;
return cachedTheme;
}
function setCachedTheme(theme) {
document?.documentElement.setAttribute("data-theme", getAppliedTheme(theme));
window?.localStorage.setItem(THEME_KEY, theme);
}
export {

@@ -8,0 +31,0 @@ THEME_KEY,

"use client";
// src/hooks/useAutoFormatDate.ts
import {
useAutoFormatDate
} from "../chunk-7E4QK6S2.js";
useCallback,
useState,
useMemo
} from "react";
var DELIMITER = "/";
function useAutoFormatDate(options) {
const { pattern, value } = defaultAutoFormatOptions(options);
const [formattedDate, setFormattedDate] = useState(value);
const blocks = useMemo(() => getBlocks(pattern), [pattern]);
const template = useMemo(
() => getTemplate(pattern, blocks),
[pattern, blocks]
);
const handleDateChange = useCallback(
(e) => {
return setFormattedDate((prev) => {
const userInput = e.target.value;
const startingCursor = e.target.selectionStart ?? userInput.length;
const { formattedDate: formattedDate2, cursorPosition } = formatDateInput({
blocks,
cursorPosition: startingCursor,
pattern,
value: userInput,
prevValue: prev
});
if (startingCursor !== userInput.length) {
setCursorPosition(e.target, cursorPosition);
}
return formattedDate2;
});
},
[blocks, pattern]
);
const handleDateBlur = useCallback(
(e) => {
return setFormattedDate(
(prev) => formatDateInput({
blocks,
cursorPosition: e.target.value.length,
pattern,
prevValue: prev,
value: e.target.value
}).formattedDate
);
},
[blocks, pattern]
);
return useMemo(
() => ({
onBlur: handleDateBlur,
onChange: handleDateChange,
placeholder: template,
maxLength: template.length,
value: formattedDate
}),
[handleDateBlur, handleDateChange, template, formattedDate]
);
}
function defaultAutoFormatOptions(options) {
return {
pattern: options?.pattern ?? ["m", "d", "Y"],
value: options?.value ?? ""
};
}
function setCursorPosition(element, position) {
requestAnimationFrame(() => element.setSelectionRange(position, position));
}
function formatDateInput(options) {
const { blocks, cursorPosition, pattern, prevValue, value } = options;
const template = getTemplate(pattern, blocks);
if (prevValue?.length > value.length) {
return {
formattedDate: value,
cursorPosition
};
}
if (value.length > template.length || getCharCount(DELIMITER, value) > pattern.length - 1) {
return {
formattedDate: prevValue,
cursorPosition: cursorPosition - (value.length - prevValue?.length)
};
}
const { formattedDateParts, cursor } = getFormattedDateParts(options);
if (Object.values(formattedDateParts).join(DELIMITER).length === template.length) {
const correctedDateParts = getCorrectedDateParts(formattedDateParts);
return {
formattedDate: combineDateParts(correctedDateParts, pattern),
cursorPosition: cursor
};
}
return {
formattedDate: combineDateParts(formattedDateParts, pattern),
cursorPosition: cursor
};
}
function getCharCount(char, str) {
return (str.match(new RegExp(char, "g")) || []).length;
}
function strToInt(value) {
return parseInt(value, 10);
}
function getFormattedDateParts(options) {
const { blocks, cursorPosition, pattern, value } = options;
const chars = value.split("");
let cursor = cursorPosition;
let currentBlock = pattern[0];
const dateParts = {
d: "",
m: "",
Y: ""
};
for (let i = 0; i < chars.length && currentBlock !== null; i += 1) {
if (chars[i] !== DELIMITER) {
dateParts[currentBlock] += chars[i];
}
const formatted = formatDateBlock(
currentBlock,
dateParts[currentBlock],
chars[i] === DELIMITER && cursorPosition > i
);
cursor += getCursorOffset(
cursorPosition,
i,
formatted.length - dateParts[currentBlock].length
);
dateParts[currentBlock] = formatted;
if (isDatePartComplete(
dateParts[currentBlock],
currentBlock,
blocks,
pattern
) || isBlockEndedByDelimiter(
chars[i],
dateParts[currentBlock],
getNextBlock(currentBlock, pattern)
)) {
currentBlock = getNextBlock(currentBlock, pattern);
}
}
return {
formattedDateParts: dateParts,
cursor
};
}
function getCursorOffset(cursor, index, value) {
if (cursor > index) {
return value;
}
return 0;
}
function isDatePartComplete(datePart, block, blocks, pattern) {
return datePart.length === blocks[pattern.indexOf(block)];
}
function isBlockEndedByDelimiter(currentChar, datePart, nextBlock) {
return currentChar === DELIMITER && datePart.length && nextBlock !== null;
}
function getNextBlock(current, pattern) {
return pattern[pattern.indexOf(current) + 1] ?? null;
}
function formatDateBlock(blockId, value, complete) {
const cleanValue = getSanitizedNumericString(value);
if (!cleanValue) {
return cleanValue;
}
switch (blockId) {
case "m":
return formatMonth(cleanValue, complete);
case "d":
return formatDay(cleanValue, complete);
default:
return cleanValue;
}
}
function formatDay(value, complete) {
const numericValue = parseInt(value, 10);
if (value.length === 1) {
if (complete || numericValue * 10 > 31) {
return `0${Math.max(numericValue, 1)}`;
}
} else {
if (numericValue > 31) {
return "31";
} else if (numericValue < 1) {
return "01";
}
}
return value;
}
function formatMonth(value, complete) {
const numericValue = parseInt(value, 10);
if (value.length === 1) {
if (complete || numericValue * 10 > 12) {
return `0${Math.max(numericValue, 1)}`;
}
} else {
if (numericValue > 12) {
return "12";
} else if (numericValue < 1) {
return "01";
}
}
return value;
}
function getSanitizedNumericString(value) {
return value.replace(/[^0-9]/g, "");
}
function combineDateParts(dateParts, pattern) {
const blocks = getBlocks(pattern);
return pattern.map((block) => {
const nextBlock = getNextBlock(block, pattern);
const blockIdx = pattern.indexOf(block);
const insertDelimiter = nextBlock && (dateParts[nextBlock] || dateParts[block].length === blocks[blockIdx]);
if (insertDelimiter) {
return dateParts[block] + DELIMITER;
} else {
return dateParts[block];
}
}).join("");
}
function getBlocks(pattern) {
const blocks = [];
pattern.forEach(function(value) {
if (value === "Y") {
blocks.push(4);
} else {
blocks.push(2);
}
});
return blocks;
}
function getTemplate(pattern, blocks) {
return pattern.map((letter, idx) => {
const count = blocks[idx];
return letter.repeat(count).toUpperCase();
}).join("/");
}
function getCorrectedDateParts(dateParts) {
const correctedDay = correctDayForMonth(
strToInt(dateParts.d),
strToInt(dateParts.m),
strToInt(dateParts.Y)
);
return {
d: formatDay(correctedDay.toString(), true),
m: dateParts.m,
Y: dateParts.Y
};
}
function correctDayForMonth(day, month, year) {
day = Math.min(day, 31);
month = Math.min(month, 12);
year = parseInt(String(year || 0), 10);
if (month < 7 && month % 2 === 0 || month > 8 && month % 2 === 1) {
const leapDay = isLeapYear(year) ? 29 : 28;
return Math.min(day, month === 2 ? leapDay : 30);
}
return day;
}
function isLeapYear(year) {
return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
}
export {

@@ -6,0 +267,0 @@ useAutoFormatDate

"use client";
import {
useEscToClose
} from "../chunk-VYA2NVJ4.js";
// src/hooks/useEscToClose.ts
import { useEffect } from "react";
function useEscToClose(onClose) {
useEffect(() => {
function handleEscClose(event) {
if (event.key === "Escape") {
event.stopPropagation();
event.preventDefault();
onClose();
}
}
window.addEventListener("keydown", handleEscClose, false);
return () => {
window.removeEventListener("keydown", handleEscClose, false);
};
}, [onClose]);
return null;
}
export {

@@ -6,0 +22,0 @@ useEscToClose

"use client";
// src/hooks/useFocusTrap.ts
import {
useFocusTrap
} from "../chunk-4DMM3XQ3.js";
useCallback,
useEffect
} from "react";
function useFocusTrap(dialogRef) {
const selectorList = 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';
const getFocusItems = useCallback(() => {
const focusableItems = dialogRef?.current?.querySelectorAll(selectorList) ?? [];
return {
firstItem: focusableItems[0],
lastItem: focusableItems[focusableItems.length - 1]
};
}, [dialogRef]);
const handleFocus = useCallback(
(event) => {
const { activeElement } = document;
const { firstItem, lastItem } = getFocusItems();
if (event.key !== "Tab") {
return;
}
if (event.shiftKey) {
if (activeElement === firstItem) {
event.preventDefault();
lastItem.focus();
}
} else {
if (activeElement === lastItem) {
event.preventDefault();
firstItem.focus();
}
}
},
[getFocusItems]
);
const handleInitFocusTrap = useCallback(() => {
if (dialogRef?.current != null) {
const { firstItem } = getFocusItems();
if (document.activeElement !== firstItem) {
firstItem?.focus();
}
}
}, [dialogRef, getFocusItems]);
useEffect(() => {
handleInitFocusTrap();
}, [handleInitFocusTrap]);
return {
onKeyDown: handleFocus
};
}
export {

@@ -6,0 +54,0 @@ useFocusTrap

"use client";
import {
useIsIndeterminate
} from "../chunk-HWPTZ2IF.js";
// src/hooks/useIsIndeterminate.ts
import { useMemo } from "react";
function useIsIndeterminate(checkboxOptions) {
const checkedItems = Object.keys(checkboxOptions).map(
(optionItem) => checkboxOptions[optionItem]
);
const allChecked = checkedItems.every(Boolean);
return useMemo(
() => (checkedItems.some(Boolean) && !allChecked) ?? false,
[allChecked, checkedItems]
);
}
export {

@@ -6,0 +16,0 @@ useIsIndeterminate

"use client";
// src/hooks/usePreloadedImg.ts
import { useEffect, useState, useTransition } from "react";
import {
usePreloadedImg
} from "../chunk-S6QQHARX.js";
import "../chunk-D4SRYCOP.js";
import "../chunk-MRY5H4GP.js";
resourceCache,
createPreloadedImgResource
} from "../helpers/createResource.js";
function getPreloadedImgResource(imgOptions) {
const { src } = imgOptions;
let resource = resourceCache.get(src);
if (!resource) {
resource = createPreloadedImgResource(imgOptions);
resourceCache.set(src, resource);
}
return resource;
}
function usePreloadedImg(imgOptions) {
const { src, srcSet } = imgOptions;
const [, startTransition] = useTransition();
const [resource, setResource] = useState(null);
useEffect(() => {
if (resource) {
return;
}
startTransition(() => {
setResource(getPreloadedImgResource({ src, srcSet }));
});
}, [resource, src, srcSet, startTransition]);
return resource;
}
export {

@@ -8,0 +33,0 @@ usePreloadedImg

@@ -1,22 +0,8 @@

import {
useEscToClose
} from "./chunk-VYA2NVJ4.js";
import {
useFocusTrap
} from "./chunk-4DMM3XQ3.js";
import {
useIsIndeterminate
} from "./chunk-HWPTZ2IF.js";
import {
usePreloadedImg
} from "./chunk-S6QQHARX.js";
import "./chunk-D4SRYCOP.js";
import "./chunk-MRY5H4GP.js";
import {
getCachedTheme,
setCachedTheme
} from "./chunk-J6CAGWHA.js";
import {
useAutoFormatDate
} from "./chunk-7E4QK6S2.js";
// src/index.ts
import { getCachedTheme, setCachedTheme } from "./helpers/themeHelpers.js";
import { useAutoFormatDate } from "./hooks/useAutoFormatDate.js";
import { useEscToClose } from "./hooks/useEscToClose.js";
import { useFocusTrap } from "./hooks/useFocusTrap.js";
import { useIsIndeterminate } from "./hooks/useIsIndeterminate.js";
import { usePreloadedImg } from "./hooks/usePreloadedImg.js";
export {

@@ -23,0 +9,0 @@ getCachedTheme,

{
"name": "@pluralsight/react-utils",
"version": "0.7.1-next-f09ded",
"version": "0.7.1-next-f24c2e",
"description": "A set of React custom hooks for Pando.",

@@ -60,3 +60,3 @@ "browserslist": "> 0.25%, not dead",

"license": "Apache 2.0",
"packageManager": "bun@1.0.14",
"packageManager": "pnpm@8.15.1",
"scripts": {

@@ -63,0 +63,0 @@ "build": "tsup --experimental-dts",

@@ -30,7 +30,7 @@ # React utils

This project uses bun so there are no setup commands needed. If you get any errors, you may need to run an initial `bun install` or ensure you are using Node >= 18.
This project uses pnPm so there are no setup commands needed. If you get any errors, you may need to run an initial `pnpm install` or ensure you are using Node >= 18.
## Development
There is no development sandbox for this specific project, but most of the time, we import the hooks into the [Headless Styles sandbox](https://github.com/pluralsight/pando/tree/main/packages/headless-styles/sandbox) which is [just as easy](https://github.com/pluralsight/pando/blob/main/packages/headless-styles/sandbox/src/components/Tabs.jsx#L2-L8).
There is no development sandbox for this specific project, but most of the time, we import the hooks into the [Headless Styles sandbox](https://github.com/ps-dev/pando/tree/main/packages/headless-styles/sandbox) which is [just as easy](https://github.com/ps-dev/pando/blob/main/packages/headless-styles/sandbox/src/components/Tabs.jsx#L2-L8).

@@ -40,3 +40,3 @@ From the **root directory of the project**, run:

```bash
bun run start:sandbox
pnpm run start:sandbox
```

@@ -49,3 +49,3 @@

```bash
bun test packages/react-utils/tests
pnpm test packages/react-utils/tests
```

@@ -55,2 +55,2 @@

If you plan on contributing to this project, please take time to read our [CONTRIBUTING.md](https://github.com/pluralsight/pando/blob/main/CONTRIBUTING.md). Pull requests that do not adhere to the requirements in this doc will automatically be flagged and closed.
If you plan on contributing to this project, please take time to read our [CONTRIBUTING.md](https://github.com/ps-dev/pando/blob/main/CONTRIBUTING.md). Pull requests that do not adhere to the requirements in this doc will automatically be flagged and closed.

@@ -1,2 +0,2 @@

import { loadImage, preloadImgResource } from './loaders.ts'
import { loadImage, preloadImgResource } from './loaders'
import type { ImgProps } from './types'

@@ -24,6 +24,6 @@

switch (status) {
case 'pending':
case 'error':
throw result
case 'pending':
case 'success':

@@ -30,0 +30,0 @@ return result

@@ -7,3 +7,3 @@ 'use client'

createPreloadedImgResource,
} from '../helpers/createResource.ts'
} from '../helpers/createResource'
import type { ImgProps, ImgResource } from '../helpers/types'

@@ -10,0 +10,0 @@

@@ -1,9 +0,9 @@

export { getCachedTheme, setCachedTheme } from './helpers/themeHelpers.ts'
export { getCachedTheme, setCachedTheme } from './helpers/themeHelpers'
// hooks
export { useAutoFormatDate } from './hooks/useAutoFormatDate.ts'
export { useEscToClose } from './hooks/useEscToClose.ts'
export { useFocusTrap } from './hooks/useFocusTrap.ts'
export { useIsIndeterminate } from './hooks/useIsIndeterminate.ts'
export { usePreloadedImg } from './hooks/usePreloadedImg.ts'
export { useAutoFormatDate } from './hooks/useAutoFormatDate'
export { useEscToClose } from './hooks/useEscToClose'
export { useFocusTrap } from './hooks/useFocusTrap'
export { useIsIndeterminate } from './hooks/useIsIndeterminate'
export { usePreloadedImg } from './hooks/usePreloadedImg'

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc