@reusable-ui/nudible
Version:
Nude variant of UI.
124 lines (123 loc) • 5.58 kB
JavaScript
// cssfn:
import {
// writes css in javascript:
rule, variants, style, vars, cssVars,
// writes complex stylesheets in simpler way:
memoizeStyle, memoizeStyleWithVariants, } from '@cssfn/core'; // writes css in javascript
// reusable-ui features:
import {
// hooks:
usesBorder, } from '@reusable-ui/border'; // border (stroke) stuff of UI
import {
// hooks:
usesPadding, } from '@reusable-ui/padding'; // padding (inner spacing) stuff of UI
// defaults:
const _defaultNude = false;
const [nudibleVars] = cssVars({ prefix: 'nu', minify: false }); // shared variables: ensures the server-side & client-side have the same generated css variable names
// parent is `.nude` -or- current is `.nude`:
export const ifNude = (styles) => rule(':is(.nude&, &.nude)', styles); // specificityWeight = 1 + (parent's specificityWeight)
// parent is not `.nude` -and- current is not `.nude`:
export const ifNotNude = (styles) => rule(':where(&):not(:is(.nude&, &.nude))', styles); // specificityWeight = 1 + (parent's specificityWeight)
const createNudibleRule = (nudeDefinition = defineNude) => {
// dependencies:
// features:
const { borderVars } = usesBorder();
const { paddingVars } = usesPadding();
return style({
// configs:
...vars({
/*
supports for `usesColorable()`:
only reset `nudibleVars.nudeSw = nudibleVars.nudePr` if `nudeDefinition` provided,
so the *modified* `nudibleVars.nudeSw` by `setNude()` still *preserved*,
thus the `usesColorable()` can see the <parent>'s actual [nude] status.
*/
[nudibleVars.nudeSw]: (nudeDefinition || undefined) && nudibleVars.nudePr,
}),
// toggling props:
...variants([
ifNude({
// backgrounds:
// discard background, no valid/invalid animation:
backg: [['none'], '!important'],
// borders:
// discard border stroke:
[borderVars.borderWidth]: '0px',
// discard borderRadius:
// remove rounded corners on top:
[borderVars.borderStartStartRadius]: '0px',
[borderVars.borderStartEndRadius]: '0px',
// remove rounded corners on bottom:
[borderVars.borderEndStartRadius]: '0px',
[borderVars.borderEndEndRadius]: '0px',
// no shadow & no focus animation:
boxShadow: [['none'], '!important'],
// spacings:
// discard padding:
[paddingVars.paddingInline]: '0px',
[paddingVars.paddingBlock]: '0px',
}),
]),
// toggling conditions:
...variants([
nudeDefinition && ifNude(nudeDefinition(true)),
nudeDefinition && ifNotNude(nudeDefinition(false)),
]),
});
};
const getDefaultNudibleRule = memoizeStyle(() => createNudibleRule());
/**
* Uses a toggleable nudeification (removes background, border & padding).
* @param nudeDefinition A callback to create a nudeification rules for each toggle state.
* @returns A `NudibleStuff` represents the nudeification rules.
*/
export const usesNudible = (nudeDefinition = defineNude) => {
return {
nudibleRule: ((nudeDefinition === defineNude)
?
getDefaultNudibleRule
:
() => createNudibleRule(nudeDefinition)),
nudibleVars,
};
};
/**
* Defines a nudeification preference rules for the given `toggle` state.
* @param toggle `true` to activate the nudeification -or- `false` to deactivate -or- `null` to remove previously declared `defineNude`.
* @returns A `CssRule` represents a nudeification rules for the given `toggle` state.
*/
export const defineNude = memoizeStyleWithVariants((toggle) => {
return style({
...vars({
/*
*switch on/off* the `**Tg` prop.
toggle:
true => empty string => do not alter the `**Tg`'s value => activates `**Tg` variable.
false => initial (invalid) => destroy the `**Tg`'s value => deactivates `**Tg` variable.
null => null => remove the prev declaration
*/
[nudibleVars.nudePr]: (typeof (toggle) === 'boolean') ? (toggle ? '' : 'initial') : toggle,
}),
});
});
/**
* Sets the current nudeification state by the given `toggle` state.
* @param toggle `true` to activate the nudeification -or- `false` to deactivate -or- `null` to remove previously declared `setNude`.
* @returns A `CssRule` represents a nudeification rules for the given `toggle` state.
*/
export const setNude = (toggle) => style({
...vars({
/*
*switch on/off* the `**Tg` prop.
toggle:
true => empty string => do not alter the `**Tg`'s value => activates `**Tg` variable.
false => initial (invalid) => destroy the `**Tg`'s value => deactivates `**Tg` variable.
null => null => remove the prev declaration
*/
[nudibleVars.nudeSw]: (typeof (toggle) === 'boolean') ? (toggle ? '' : 'initial') : toggle,
}),
});
export const useNudible = ({ nude = _defaultNude }) => ({
class: (nude || null) && 'nude',
});
//#endregion nudible