______ _ _ _
| ___ \ | | | | | |
| |_/ /_ _| |___| |_ ___| | __
| __/ _` | / __| __/ _ \ |/ /
| | | (_| | \__ \ || __/ < _
\_| \__,_|_|___/\__\___|_|\_(_)
>> Palstek - a bunch of useful extensions for react projects.
Why "palstek"? - Because this is one of the most used knots on a sailboat. Just as useful, selected functions should be provided here. Especially designed as extension to functional react projects, react libraries and design systems.
It's designed as zero-dependency; no other packages do come with
palstek
. If you want to use all features (especially the hooks), you need to havereact
package as peerDependency installed.
- Install the package with
npm i palstek
into your project - Use the functions. They support typescript.
Utils contains a random collection of useful functions - often designed to bring in an own pattern into your react project.
You want to build reusable (libary-) components in react and are annoyed by merging your classnames with props.className(s)? This function is here to help. Use it in your components like:
return <div className={resolveClassNames("my-component", props.className, someCondition && "modifier-class")}>{/*...*/}</div>
It will automatically filter out undefineds & falsy values. All valid strings are joined together to get valid multi-classNames. Also works with string arrays and css modules.
Get a string of random letters and numbers with a length, default is 5.
const randomString = getRandomString(7); // will for example create '3udzdaf'
This function is perfect for building atomic library components, where the vanilla props API should be preserved. Example:
type MyButtonProps = { appearance: "CTA" | "default" } & HTMLProps<HTMLButtonElement>;
export MyButton = (props: MyButtonProps) => (
return <button {...filterProps(props, "appearance", "children")}>
{ props.appearance === "CTA" ? <b>{props.children}</b> : props.children }
</button>
)
For a consumer of your library this is now still a full-featured HTML Button with access to it's complete props API. You only care about your feature additions.
This function works similar to the filterProps
function but with one addition: To avoid big lists of custom props, you may want to use this pattern: all custom props begin with an underscore.
Example:
type MyButtonProps = { _appearance: "CTA" | "default" } & HTMLProps<HTMLButtonElement>;
export MyButton = (props: MyButtonProps) => (
return <button {...filterProps(props, "children")}>
{ props._appearance === "CTA" ? <b>{props.children}</b> : props.children }
</button>
)
The autoFilterProps
will automatically remove all members of the props object starting with an underscore. It also filters out following standard props (coming for example from react router):
- history
- location
- match
This function collection is useful to transform strings in several common targets, such as to "kebab-case", "camelCase" and "PascalCase". Example:
const myString = "some-kebab-string";
const newString = stringTransform.toCamelCase(myString); // newString will be "someKebabString"
All functions support special characters (from languages like German or French).
Both functions toCamelCase
and toPascalCase
replace the characters -
, _
, and whitespace by default, but you can pass your own Regexp as optional parameter to modify the function to also replace a .
or a ,
for example.
Lightweight wrapper for sessionStorage.setItem()
, will perform a JSON.stringify()
for the value.
Might get upgraded with custom event in future.
Lightweight wrapper for sessionStorage.getItem()
, will perform a JSON.parse()
for the value.
Lightweight wrapper for localStorage.setItem()
, will perform a JSON.stringify()
for the value.
Might get upgraded with custom event in future.
Lightweight wrapper for localStorage.getItem()
, will perform a JSON.parse()
for the value.
This lightweight reset.css can be imported at first in every project to do some helpful normalizings to your project's styling.
Get access to a state's previous value. This can be helpful to implement a simple undo or to compare old and new values.
Example:
// inside a React Component
const [count, setCount] = useState(0);
const previousCount = usePrevious(count); // will always be the previous value, like a "history - 1"
Provide local values insider your component's code to CSS as CSS Variable (needs browser support).
Example:
const MyComponent = () => {
const [val, setVal] = useCssVar("--my-font-size", "2rem");
return (
<div style={{ fontSize: "var(--my-font-size)" }}>
The value: {val}
<button onClick={() => setVal(`${parseInt(val) + 1}rem`)}>increase</button>
</div>
);
};
Parameters:
- Variable name (has to start with '--')
- Variable value
- optional, an HtmlElement Reference on which to set the variable (default document.body)
Returns (similar to useState):
- The value
- Setter for the value
A useful hook to manage "outside" clicks of DOM Elements. Based on React Ref and Event.composedPath.
This pattern is quite solid and efficient, but does not work as soon as the DOM hierarchy does not represent the visual hierarchy (because of position: absolute
of sub-elements or similar).
Example:
const MyComponent = () => {
const outsideClickHandler = () => {
console.log("outside");
}
const [elementRef] = useOutsideClickHandler(outsideClickHandler);
return (
<div ref={elementRef}>
Dialog / Modal / Popup / ...
</div>
);
};
Parameters:
- Your click handler. Will get triggered once an outside click is detected.
- A condition (boolean). If false, the listener(s) won't get registered and/or unregistered. Default true.
- An optional list of event types, in case you want to listen to additional / other events than "click".
Returns:
- elementRef: The ref of the element which has to be inside the
composedPath
of the click(?) event. It's just a passthrough of React.useRef and works identical. Default'snull
.
A simple helper hook to access localStorage. Works like a useState hook. Listens to "storage" Event on window object, in case another tab/window accesses the same storage area (based on URL/domain).
const initValue = 15;
const [value, setValue] = useLocalStorage("myKey", initValue);
// will store '15' at key 'myKey' in localStorage
A simple helper hook to access sessionStorage. Works like a useState hook.
const initValue = 15;
const [value, setValue] = useSessionStorage("myKey", initValue);
// will store '15' at key 'myKey' in sessionStorage
- Include the possibility to only install single functions instead of the whole package, like
npm i palstek/resolveClassNames
.
If you want to contribute, feel free to do so. Just create your own branch and submit a PR with the changes.
There are inconsistencies when importing typings from node modules. This error should not occur if you use moduleResolution: node
inside your tsconfig.
Credits go to:
- https://www.joshwcomeau.com/css/custom-css-reset/ and https://piccalil.li/blog/a-modern-css-reset/ for inspiration on reset.css
Made with ❤ by @cmmdmx