@plurid/plurid-ui-components-react
Version:
Plurid User Interface Components for React
1,784 lines (1,598 loc) • 140 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var React = require("react");
var themes = require("@plurid/plurid-themes");
var styled = require("styled-components");
var pluridIconsReact = require("@plurid/plurid-icons-react");
var pluridFunctionsReact = require("@plurid/plurid-functions-react");
var pluridFunctions = require("@plurid/plurid-functions");
var reactRedux = require("react-redux");
var pluridUiStateReact = require("@plurid/plurid-ui-state-react");
function _interopDefault(e) {
return e && e.__esModule ? e : {
default: e
};
}
var React__default = _interopDefault(React);
var themes__default = _interopDefault(themes);
var styled__default = _interopDefault(styled);
const StyledSpinner = styled__default.default.div`
position: absolute;
top: 50%;
left: 50%;
transform: translateX(-50%) translateY(-50%);
`;
const StyledLoader = styled__default.default.div`
display: inline-block;
position: relative;
width: ${props => {
switch (props.size) {
case "small":
return "1rem";
case "normal":
return "1.8rem";
case "large":
return "2.4rem";
default:
return "1.8rem";
}
}};
height: ${props => {
switch (props.size) {
case "small":
return "1rem";
case "normal":
return "1.8rem";
case "large":
return "2.4rem";
default:
return "1.8rem";
}
}};
div {
width: ${props => {
switch (props.size) {
case "small":
return "1rem";
case "normal":
return "1.8rem";
case "large":
return "2.4rem";
default:
return "1.8rem";
}
}};
height: ${props => {
switch (props.size) {
case "small":
return "1rem";
case "normal":
return "1.8rem";
case "large":
return "2.4rem";
default:
return "1.8rem";
}
}};
margin: ${props => {
switch (props.size) {
case "small":
return "0.1rem";
case "normal":
return "0.2rem";
case "large":
return "0.3rem";
default:
return "0.2rem";
}
}};
border: ${props => {
switch (props.size) {
case "small":
return "0.1rem solid " + props.theme.colorPrimary;
case "normal":
return "0.2rem solid " + props.theme.colorPrimary;
case "large":
return "0.3rem solid " + props.theme.colorPrimary;
default:
return "0.2rem solid " + props.theme.colorPrimary;
}
}};
border-color: ${props => props.theme.colorPrimary} transparent transparent transparent;
box-sizing: border-box;
display: block;
position: absolute;
border-radius: 50%;
animation: spinner-rotate 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;
}
div:nth-child(1) {
animation-delay: -0.45s;
}
div:nth-child(2) {
animation-delay: -0.3s;
}
div:nth-child(3) {
animation-delay: -0.15s;
}
@keyframes spinner-rotate {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
`;
const Spinner$1 = properties => {
const {theme: theme, size: size, style: style, className: className} = properties;
const themeValue = theme || themes.plurid;
const sizeValue = size || "normal";
return React__default.default.createElement(StyledSpinner, {
style: {
...style
},
className: className
}, React__default.default.createElement(StyledLoader, {
theme: themeValue,
size: sizeValue
}, React__default.default.createElement("div", null), React__default.default.createElement("div", null), React__default.default.createElement("div", null), React__default.default.createElement("div", null)));
};
const StyledPureButton = styled__default.default.button`
color: ${({theme: theme}) => theme.colorPrimary};
background-color: ${({theme: theme, level: level, isDisabled: isDisabled}) => {
if (isDisabled) {
return theme.backgroundColorPrimaryAlpha;
}
switch (level) {
case 0:
return theme.backgroundColorPrimary;
case 1:
return theme.backgroundColorSecondary;
case 2:
return theme.backgroundColorTertiary;
case 3:
return theme.backgroundColorQuaternary;
default:
return theme.backgroundColorPrimary;
}
}};
box-shadow: 0px 8px 8px 0px ${({theme: theme}) => theme.boxShadowUmbraColor};
box-sizing: border-box;
display: block;
width: 100%;
min-width: ${({size: size}) => {
switch (size) {
case "small":
return "8rem";
case "normal":
return "10rem";
case "large":
return "12rem";
default:
return "10rem";
}
}};
border-radius: ${({size: size}) => {
switch (size) {
case "small":
return "1rem";
case "normal":
return "1.2rem";
case "large":
return "1.4rem";
default:
return "1.2rem";
}
}};
padding: ${({size: size}) => {
switch (size) {
case "small":
return "0 1.2rem";
case "normal":
return "0 1.4rem";
case "large":
return "0 1.6rem";
default:
return "0 1.4rem";
}
}};
font-family: ${({theme: theme}) => theme.fontFamilySansSerif};
font-size: ${({size: size}) => {
switch (size) {
case "small":
return "0.8rem";
case "normal":
return "0.9rem";
case "large":
return "1rem";
default:
return "0.9rem";
}
}};
height: ${({size: size}) => {
switch (size) {
case "small":
return "2rem";
case "normal":
return "2.4rem";
case "large":
return "2.8rem";
default:
return "2.4rem";
}
}};
cursor: ${({isDisabled: isDisabled}) => {
if (isDisabled) {
return "default";
}
return "pointer";
}};
border: none;
outline: none;
user-select: none;
display: grid;
place-content: center;
line-height: 1.2;
font-weight: bold;
transition: box-shadow 200ms linear, background-color 200ms linear;
position: relative;
min-height: 40px;
min-width: 160px;
@media (hover: hover) {
:hover {
background-color: ${({theme: theme, level: level, isDisabled: isDisabled}) => {
if (isDisabled) {
return theme.backgroundColorPrimaryAlpha;
}
switch (level) {
case 0:
return theme.backgroundColorSecondary;
case 1:
return theme.backgroundColorTertiary;
case 2:
return theme.backgroundColorQuaternary;
case 3:
return theme.backgroundColorPrimary;
default:
return theme.backgroundColorSecondary;
}
}};
}
}
:active {
box-shadow: ${({theme: theme, isDisabled: isDisabled}) => {
if (isDisabled) {
return "0px 8px 8px 0px " + theme.boxShadowUmbraColor;
}
return "0px 3px 3px 0px " + theme.boxShadowUmbraColor;
}};
}
`;
const StyledPureButtonDiv = styled__default.default(StyledPureButton).attrs({
as: "div"
})`
background-color: ${({theme: theme, level: level, isDisabled: isDisabled}) => {
if (isDisabled) {
return "";
}
switch (level) {
case 0:
return theme.backgroundColorSecondary;
case 1:
return theme.backgroundColorTertiary;
case 2:
return theme.backgroundColorQuaternary;
case 3:
return theme.backgroundColorPrimary;
default:
return theme.backgroundColorSecondary;
}
}};
box-shadow: 0px 3px 3px 0px ${({theme: theme}) => theme.boxShadowUmbraColor};
`;
const PureButton$1 = properties => {
const {text: text, atClick: atClick, theme: themeProperty, level: levelProperty, size: sizeProperty, disabled: disabled, loading: loading, style: style, className: className} = properties;
const theme = themeProperty || themes.plurid;
const level = levelProperty ?? 0;
const size = sizeProperty || "normal";
if (loading) {
return React__default.default.createElement(StyledPureButtonDiv, {
style: {
...style
},
className: className,
theme: theme,
level: level,
size: size,
isDisabled: disabled
}, React__default.default.createElement(Spinner$1, {
theme: theme,
size: "small"
}));
}
return React__default.default.createElement(StyledPureButton, {
onClick: event => disabled ? null : atClick(event),
style: {
...style
},
className: className,
theme: theme,
level: level,
size: size,
isDisabled: disabled
}, text);
};
const StyledLinkButton = styled__default.default.button`
font-family: ${({theme: theme}) => theme.fontFamilySansSerif};
color: ${({theme: theme, level: level, isDisabled: isDisabled}) => {
if (isDisabled) {
return theme.backgroundColorPrimaryAlpha;
}
switch (level) {
case 0:
return theme.colorPrimary;
case 1:
return theme.colorSecondary;
case 2:
return theme.colorTertiary;
default:
return theme.colorPrimary;
}
}};
margin: ${({inline: inline}) => {
if (inline) {
return "0";
}
return "0 1rem";
}};
padding: ${({inline: inline}) => {
if (inline) {
return "0";
}
return "initial";
}};
font-size: ${({inline: inline}) => {
if (inline) {
return "inherit";
}
return "0.9rem";
}};
display: ${({inline: inline}) => {
if (inline) {
return "inline";
}
return "grid";
}};
cursor: ${({isDisabled: isDisabled}) => {
if (isDisabled) {
return "inherit";
}
return "pointer";
}};
border: none;
border-bottom: 1px solid ${({isActive: isActive, theme: theme}) => {
if (isActive) {
return theme.colorPrimary;
}
return "transparent";
}};
font-weight: bold;
background: transparent;
place-content: center;
user-select: none;
outline: none;
`;
const StyledLinkButtonLoading = styled__default.default.div`
position: relative;
min-height: 1rem;
height: 100%;
width: 100%;
`;
const DEFAULT_LEVEL$1 = 0;
const LinkButton$1 = properties => {
const {text: text, atClick: atClick, theme: themeProperty, level: levelProperty, inline: inline, disabled: disabled, loading: loading, active: active, style: style, className: className} = properties;
const theme = themeProperty || themes.plurid;
const level = levelProperty ?? DEFAULT_LEVEL$1;
if (loading) {
return React__default.default.createElement(StyledLinkButtonLoading, null, React__default.default.createElement(Spinner$1, {
size: "small",
theme: theme
}));
}
return React__default.default.createElement(StyledLinkButton, {
onClick: event => disabled ? null : atClick(event),
style: {
...style
},
className: className,
theme: theme,
level: level,
inline: inline,
isDisabled: disabled,
isActive: active
}, text);
};
const StyledRefreshButton = styled__default.default.div`
`;
const RefreshButton$1 = properties => {
const {atClick: atClick, theme: themeProperty, text: textProperty, disabled: disabled, hideAtClick: hideAtClickProperty, hideTime: hideTimeProperty} = properties;
const theme = themeProperty || themes.plurid;
const text = textProperty || "";
const hideAtClick = hideAtClickProperty ?? true;
const hideTime = hideTimeProperty || 1300;
const isMounted = React.useRef(true);
const [showIconReset, setShowIconReset] = React.useState(true);
const atClickHandler = event => {
if (disabled) {
return;
}
if (hideAtClick) {
setShowIconReset(false);
}
atClick(event);
if (hideAtClick) {
setTimeout((() => {
if (!isMounted.current) {
return;
}
setShowIconReset(true);
}), hideTime);
}
};
React.useEffect((() => () => {
isMounted.current = false;
}), []);
return React__default.default.createElement(StyledRefreshButton, {
theme: theme
}, showIconReset && React__default.default.createElement(pluridIconsReact.PluridIconReset, {
theme: theme,
title: text,
inactive: disabled,
opacity: disabled ? .5 : 1,
atClick: atClickHandler
}));
};
const buttons = {
PureButton: PureButton$1,
LinkButton: LinkButton$1,
RefreshButton: RefreshButton$1
};
const StyledFormbutton = styled__default.default.div`
display: grid;
grid-template-columns: 20px 1fr;
grid-gap: 0.5rem;
align-items: center;
min-height: 2rem;
user-select: none;
text-decoration: none;
padding: 0.3rem 0.7rem;
margin: ${props => {
if (props.devisible) {
return "0";
}
return "initial";
}};
cursor: ${props => {
if (props.inactive) {
return "default";
}
return "pointer";
}};
color: ${props => props.theme.colorPrimary};
:hover {
background-color: ${props => {
if (!props.hoverEffect) {
return "initial";
}
if (props.inactive || props.devisible) {
return "initial";
}
return props.theme.backgroundColorSecondary;
}};
}
`;
const StyledFormbuttonIcon = styled__default.default.div`
justify-self: ${props => props.position};
display: grid;
place-content: center;
`;
const StyledFormbuttonText = styled__default.default.div`
`;
const Formbutton$1 = properties => {
const {text: text, Icon: Icon, atClick: atClick, link: link, target: target, theme: theme, devisible: devisible, level: level, iconPosition: iconPosition, inactive: inactive, hoverEffect: hoverEffectProperty, style: style, className: className} = properties;
const _theme = theme || themes.plurid;
const _level = level ?? 0;
const _devisible = devisible ?? false;
const _iconPosition = iconPosition || "left";
const _inactive = inactive ?? false;
const hoverEffect = hoverEffectProperty ?? true;
const render = () => React__default.default.createElement(React__default.default.Fragment, null, React__default.default.createElement(StyledFormbuttonIcon, {
position: _iconPosition
}, React__default.default.createElement(Icon, {
theme: _theme
})), React__default.default.createElement(StyledFormbuttonText, null, text));
const renderProperties = {
style: {
...style
},
className: className,
theme: _theme,
level: _level,
inactive: _inactive,
devisible: _devisible,
hoverEffect: hoverEffect
};
if (link) {
return React__default.default.createElement(StyledFormbutton, {
onClick: event => !_inactive ? atClick(event) : null,
as: "a",
href: link,
target: target,
...renderProperties
}, render());
}
return React__default.default.createElement(StyledFormbutton, {
onClick: event => !_inactive ? atClick(event) : null,
...renderProperties
}, render());
};
const StyledFormitem = styled__default.default.div`
display: grid;
align-items: center;
min-height: 2rem;
padding: 0.3rem 0.7rem;
user-select: none;
`;
const Formitem$1 = properties => {
const {theme: theme, level: level, style: style, className: className, children: children} = properties;
const _theme = theme || themes.plurid;
const _level = level ?? 0;
return React__default.default.createElement(StyledFormitem, {
style: {
...style
},
className: className,
theme: _theme,
level: _level
}, children);
};
const StyledFormLeftRight = styled__default.default.div`
display: flex;
align-items: center;
justify-content: space-between;
`;
const FormLeftRight$1 = properties => {
const {theme: theme, style: style, className: className, children: children} = properties;
const _theme = theme || themes.plurid;
return React__default.default.createElement(StyledFormLeftRight, {
style: {
...style
},
className: className,
theme: _theme
}, children);
};
const StyledFormline = styled__default.default.div`
display: grid;
grid-template-columns: 1fr 1fr;
align-items: center;
min-height: 2rem;
padding: 0.3rem 0.7rem;
color: ${props => props.theme.colorPrimary};
@media (max-width: 800px) {
grid-template-columns: ${props => {
if (props.responsive) {
return "1fr";
}
return "1fr 1fr";
}};
min-height: ${props => {
if (props.responsive) {
return "2.4rem";
}
return "2rem";
}};
justify-items: ${props => {
if (props.responsive) {
return "center";
}
return "auto";
}};
justify-content: ${props => {
if (props.responsive) {
return "center";
}
return "auto";
}};
}
`;
const StyledFormlineText = styled__default.default.div`
user-select: none;
`;
const StyledFormlineElement = styled__default.default.div`
justify-self: right;
@media (max-width: 800px) {
justify-self: ${props => {
if (props.responsive) {
return "center";
}
return "right";
}};
}
`;
const Formline$1 = properties => {
const {text: text, Element: Element, theme: theme, level: level, responsive: responsive, style: style, className: className, children: children} = properties;
const _theme = theme || themes.plurid;
const _level = level === undefined ? 0 : level;
const _responsive = responsive === undefined ? false : responsive;
return React__default.default.createElement(StyledFormline, {
style: {
...style
},
className: className,
theme: _theme,
level: _level,
responsive: _responsive
}, React__default.default.createElement(StyledFormlineText, null, text), React__default.default.createElement(StyledFormlineElement, {
responsive: _responsive
}, Element ? React__default.default.createElement(Element, null) : React__default.default.createElement(React__default.default.Fragment, null, children)));
};
const StyledFormObliterate = styled__default.default.div`
color: ${properties => properties.theme.colorPrimary};
font-family: ${properties => properties.theme.fontFamilySansSerif};
font-size: 0.8rem;
user-select: none;
`;
const StyledObliterateContainer = styled__default.default.div`
text-align: center;
display: grid;
grid-template-columns: 1fr;
grid-template-rows: 30px 45px 60px;
align-items: center;
max-width: 200px;
margin: 1rem auto;
`;
const FormObliterate$1 = properties => {
const {atObliterate: atObliterate, item: item, theme: theme, devisible: devisible, level: level, style: style, className: className} = properties;
const _theme = theme || themes.plurid;
const _level = level ?? 0;
const _devisible = devisible ?? false;
const [showObliterate, setShowObliterate] = React.useState(false);
const handleObliterate = event => {
setShowObliterate(false);
atObliterate(event);
};
return React__default.default.createElement(StyledFormObliterate, {
theme: _theme,
level: _level,
devisible: _devisible,
style: {
...style
},
className: className
}, !showObliterate && React__default.default.createElement(Formbutton$1, {
theme: _theme,
text: item ? `obliterate ${item}` : "obliterate",
Icon: pluridIconsReact.PluridIconObliterate,
atClick: () => setShowObliterate(true),
devisible: true
}), showObliterate && React__default.default.createElement(StyledObliterateContainer, null, React__default.default.createElement("div", null, "remove forever?"), React__default.default.createElement(LinkButton$1, {
theme: _theme,
text: "cancel",
atClick: () => setShowObliterate(false)
}), React__default.default.createElement(PureButton$1, {
theme: _theme,
text: "Obliterate",
atClick: event => handleObliterate(event)
})));
};
const form = {
Formbutton: Formbutton$1,
Formitem: Formitem$1,
FormLeftRight: FormLeftRight$1,
Formline: Formline$1,
FormObliterate: FormObliterate$1
};
const GlobalStyles$1 = styled.createGlobalStyle`
*, *::after, *::before {
box-sizing: border-box;
}
html {
height: 100%;
min-height: 100vh;
}
body {
font-family: ${({theme: theme}) => theme.fontFamilySansSerif};
height: 100%;
margin: 0;
padding: 0;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: ${({theme: theme}) => {
if (theme.type === "dark") {
return theme.backgroundColorBright;
}
return theme.colorPrimary;
}};
background: ${({theme: theme}) => {
if (theme.type === "dark") {
return theme.backgroundColorDark;
}
return theme.backgroundColorPrimary;
}};
}
`;
const general = {
GlobalStyles: GlobalStyles$1
};
const setNativeValue = (element, value) => {
const valueSetter = Object.getOwnPropertyDescriptor(element, "value").set;
const prototype = Object.getPrototypeOf(element);
const prototypeValueSetter = Object.getOwnPropertyDescriptor(prototype, "value").set;
if (valueSetter && valueSetter !== prototypeValueSetter) {
prototypeValueSetter.call(element, value);
} else {
valueSetter.call(element, value);
}
};
const StyledTextline = styled__default.default.div`
position: relative;
display: inline-block;
width: 100%;
input {
box-sizing: border-box;
border: none;
outline: none;
font-size: 0.8rem;
padding: ${props => {
if (props.devisible) {
return "0";
}
return "0.6rem 1rem";
}};
padding-top: ${props => {
if (props.devisible) {
return "0";
}
return "0.7rem";
}};
min-height: ${props => {
if (props.devisible) {
return "initial";
}
return "36px";
}};
background-color: ${props => {
if (props.devisible) {
return "transparent";
}
switch (props.level) {
case 0:
return props.theme.backgroundColorPrimary;
case 1:
return props.theme.backgroundColorSecondary;
case 2:
return props.theme.backgroundColorTertiary;
case 3:
return props.theme.backgroundColorQuaternary;
default:
return props.theme.backgroundColorPrimary;
}
}};
color: ${props => props.theme.colorPrimary};
box-shadow: inset 0px 4px 4px ${props => {
if (props.devisible) {
return "transparent";
}
return props.theme.boxShadowUmbraColor;
}};
border-radius: ${props => {
if (props.devisible) {
return "0";
}
if (props.round) {
return "1000px";
}
return "0px";
}};
width: ${props => {
if (!props.width) {
return "100%";
}
if (typeof props.width === "number") {
return props.width + "px";
}
return props.width;
}};
text-align: ${props => {
if (props.center) {
return "center";
}
return "left";
}};
::placeholder {
color: ${props => props.theme.colorSecondary};
}
}
`;
const StyledEnterIcon = styled__default.default.div`
position: absolute;
top: 50%;
transform: translateY(-50%);
height: 20px;
width: 20px;
border-radius: 100px;
display: flex;
align-items: center;
justify-content: center;
font-size: 0.9rem;
user-select: none;
cursor: pointer;
border: 1px solid transparent;
right: ${props => {
if (props.left) {
return "auto";
}
return "0.6rem";
}};
left: ${props => {
if (props.left) {
return "0.6rem";
}
return "auto";
}};
color: ${props => props.theme.colorPrimary};
:hover {
border: 1px solid ${props => props.theme.colorPrimary};
}
`;
const StyledErrorLine = styled__default.default.div`
position: absolute;
background-color: #FF0000;
bottom: -2px;
height: ${props => {
if (props.devisible) {
return "2px";
}
return "4px";
}};
left: ${props => {
if (props.devisible) {
return "0";
}
if (!props.round) {
return "0";
}
return "14px";
}};
right: ${props => {
if (props.devisible) {
return "0";
}
if (!props.round) {
return "0";
}
return "14px";
}};
border-radius: ${props => {
if (props.devisible) {
return "0";
}
if (props.round) {
return "10px";
}
return "0px";
}};
box-shadow: 0px 1px 3px 0px ${props => {
if (props.devisible) {
return "initial";
}
return props.theme.boxShadowUmbraColor;
}};
`;
const Textline$1 = React.forwardRef(((properties, reference) => {
const {text: text, atChange: atChange, atKeyDown: atKeyDown, atFocus: atFocus, atBlur: atBlur, type: type, placeholder: placeholder, autoCapitalize: autoCapitalize, autoComplete: autoComplete, autoCorrect: autoCorrect, spellCheck: spellCheck, style: style, className: className, theme: theme, level: level, devisible: devisible, center: center, round: round, width: width, error: error, enterIconLeft: enterIconLeft, enterEmpty: enterEmpty, enterAtClick: enterAtClick, escapeClear: escapeClear, ariaLabel: ariaLabel} = properties;
const _type = type || "text";
const _theme = theme || themes.plurid;
const _level = level ?? 0;
const _round = round ?? true;
const inputElement = React.useRef();
const handleKeyDown = event => {
if (!inputElement.current) {
return;
}
if (atKeyDown) {
atKeyDown(event);
}
if (enterAtClick && event.key === "Enter") {
enterAtClick();
}
if (escapeClear && event.key === "Escape" && inputElement.current) {
setNativeValue(inputElement.current, "");
const _event = new Event("input", {
bubbles: true
});
inputElement.current.dispatchEvent(_event);
}
};
const showEnterIcon = enterAtClick && (text.length > 0 || enterEmpty);
return React__default.default.createElement(StyledTextline, {
theme: _theme,
level: _level,
devisible: devisible,
center: center,
round: _round,
width: width,
className: className
}, React__default.default.createElement("input", {
type: _type,
value: text,
onChange: event => {
atChange(event, event.target.value);
},
onKeyDown: handleKeyDown,
onFocus: atFocus,
onBlur: atBlur,
placeholder: placeholder,
autoCapitalize: autoCapitalize,
autoComplete: autoComplete,
autoCorrect: autoCorrect,
spellCheck: spellCheck,
"aria-label": ariaLabel,
style: {
...style,
paddingRight: showEnterIcon ? "35px" : undefined
},
ref: pluridFunctionsReact.mergeReferences(inputElement, reference)
}), error && React__default.default.createElement(StyledErrorLine, {
theme: _theme,
devisible: devisible,
round: _round
}), showEnterIcon && React__default.default.createElement(StyledEnterIcon, {
theme: _theme,
onClick: () => enterAtClick(),
left: enterIconLeft
}, "➔"));
}));
const StyledDropdown = styled__default.default.div`
color: ${props => props.theme.colorPrimary};
text-align: ${props => {
if (props.left) {
return "left";
}
return "right";
}};
font-size: 1rem;
position: relative;
`;
const StyledDropdownSelected = styled__default.default.div`
cursor: pointer;
user-select: none;
color: ${props => {
if (props.selectedColor) {
return props.selectedColor;
}
return props.theme.colorPrimary;
}};
`;
const StyledDropdownList = styled__default.default.div`
font-size: 0.85rem;
background: ${props => {
switch (props.level) {
case 0:
return props.theme.backgroundColorPrimary;
case 1:
return props.theme.backgroundColorSecondary;
case 2:
return props.theme.backgroundColorTertiary;
case 3:
return props.theme.backgroundColorQuaternary;
default:
return props.theme.backgroundColorPrimary;
}
}};
color: ${props => props.theme.colorPrimary};
position: absolute;
left: ${props => {
if (props.left) {
return "0px";
}
return "auto";
}};
right: ${props => {
if (props.left) {
return "auto";
}
return "0px";
}};
top: ${props => {
if (props.listTop) {
return props.listTop;
}
return "25px";
}};
height: ${props => {
if (props.heightItems) {
const value = props.heightItems * 2 + "rem";
if (props.heightBeyond) {
return `calc(${value} + 1rem)`;
}
return value;
}
return "initial";
}};
overflow: ${props => {
if (props.heightItems) {
return "scroll";
}
return "initial";
}};
/* Hide Scrollbar */
scrollbar-width: none; /* Firefox 64 */
-ms-overflow-style: none; /* Internet Explorer 11 */
::-webkit-scrollbar { /** WebKit */
display: none;
}
width: ${props => {
if (props.width) {
if (typeof props.width === "number") {
return props.width + "px";
}
if (typeof props.width === "string") {
return props.width;
}
}
return "initial";
}};
border-radius: 10px;
min-width: 60px;
z-index: 9998;
box-shadow: 0px 3px 5px 1px hsla(327, 94%, 10%, 0.7);
ul {
margin: 0;
padding: 0;
list-style: none;
}
ul li {
box-sizing: border-box;
padding: 0.3rem 0.6rem;
user-select: none;
cursor: pointer;
min-height: 2rem;
display: grid;
align-items: center;
word-break: break-all;
justify-content: ${props => {
if (props.left) {
return "left";
}
return "right";
}};
}
ul li:hover {
background: ${props => {
if (props.level === 2) {
return props.theme.backgroundColorSecondary;
}
return props.theme.backgroundColorTertiary;
}};
}
ul li:first-child {
border-top-right-radius: 10px;
border-top-left-radius: 10px;
}
ul li:last-child {
border-bottom-right-radius: 10px;
border-bottom-left-radius: 10px;
}
`;
const StyledFilterable = styled__default.default.div`
position: relative;
input {
text-align: ${props => {
if (props.left) {
return "left !important";
}
return "right !important";
}};
}
`;
const StyledFilterUpdate = styled__default.default.div`
position: absolute;
z-index: 9999;
top: 0;
left: ${props => {
if (props.left) {
return "auto";
}
return "0";
}};
right: ${props => {
if (props.left) {
return "0";
}
return "auto";
}};
`;
const Dropdown$1 = properties => {
const {selected: selected, selectables: selectables, atSelect: atSelect, left: left, kind: kind, listTop: listTop, dropdownToggled: dropdownToggled, dropdownSign: dropdownSign, hideAtSelect: hideAtSelect, selectAtHover: selectAtHover, selectedColor: selectedColor, filterable: filterable, style: style, className: className, theme: themeProperty, generalTheme: generalThemeProperty, interactionTheme: interactionThemeProperty, level: level, heightItems: heightItems, width: width, setDropdownToggled: setDropdownToggled, filterUpdate: filterUpdate} = properties;
const _generalTheme = generalThemeProperty === undefined ? themeProperty === undefined ? themes.plurid : themeProperty : generalThemeProperty;
const _interactionTheme = interactionThemeProperty === undefined ? themeProperty === undefined ? themes.plurid : themeProperty : interactionThemeProperty;
const _level = level ?? 0;
const _hideAtSelect = hideAtSelect ?? true;
const _selectAtHover = selectAtHover ?? false;
const _dropdownSign = typeof dropdownSign === "string" ? dropdownSign : !dropdownSign ? "" : "▼";
const isMounted = React.useRef(true);
const filterInput = React.useRef(null);
const [generalTheme, setGeneralTheme] = React.useState(_generalTheme);
const [interactionTheme, setInteractionTheme] = React.useState(_interactionTheme);
const [showList, setShowList] = React.useState(false);
const [selectedBackgroundColor, setSelectedBackgroundColor] = React.useState(interactionTheme.backgroundColorTertiary);
const [filterValue, setFilterValue] = React.useState("");
const [filteredSelectables, setFilteredSelectables] = React.useState([ ...selectables ]);
const [showFilterUpdate, setShowFilterUpdate] = React.useState(!!filterUpdate);
const [arrowIndex, setArrowIndex] = React.useState(-1);
const select = selected => {
kind ? atSelect(selected, kind) : atSelect(selected);
};
const handleSelect = selected => {
select(selected);
if (_hideAtSelect) {
setShowList(false);
}
};
const handleHover = selected => {
if (_selectAtHover) {
select(selected);
}
};
const handleFiltering = event => {
const {value: value} = event.target;
const filterValue = value.toLowerCase();
const filteredSelectables = selectables.filter((selectable => {
if (typeof selectable === "string") {
const filterSelectable = selectable.toLowerCase();
if (selectable.toLowerCase().startsWith(filterValue)) {
return true;
}
const split = filterSelectable.split(" ");
for (const element of split) {
if (element.startsWith(filterValue)) {
return true;
}
}
return false;
}
const filterSelectable = selectable.value.toLowerCase();
if (filterSelectable.startsWith(filterValue)) {
return true;
}
const split = filterSelectable.split(" ");
for (const element of split) {
if (element.startsWith(filterValue)) {
return true;
}
}
return false;
}));
setFilterValue(value);
setFilteredSelectables(filteredSelectables);
itemsReferences.current = filteredSelectables.reduce(((accumulator, _, index) => {
accumulator[index] = React__default.default.createRef();
return accumulator;
}), {});
};
const focusFilterInput = () => {
setTimeout((() => {
if (filterInput.current) {
filterInput.current.focus();
}
}), 100);
};
const itemsReferences = React.useRef(filteredSelectables.reduce(((accumulator, _, index) => {
accumulator[index] = React__default.default.createRef();
return accumulator;
}), {}));
React.useEffect((() => {
if (!dropdownToggled) {
setShowList(false);
}
}), [ dropdownToggled ]);
React.useEffect((() => {
if (_level === 2) {
setSelectedBackgroundColor(interactionTheme.backgroundColorSecondary);
} else {
setSelectedBackgroundColor(interactionTheme.backgroundColorTertiary);
}
}), [ _level, interactionTheme ]);
React.useEffect((() => {
const generalTheme = generalThemeProperty === undefined ? themeProperty === undefined ? themes.plurid : themeProperty : generalThemeProperty;
const interactionTheme = interactionThemeProperty === undefined ? themeProperty === undefined ? themes.plurid : themeProperty : interactionThemeProperty;
setGeneralTheme(generalTheme);
setInteractionTheme(interactionTheme);
}), [ themeProperty, generalThemeProperty, interactionThemeProperty ]);
React.useEffect((() => {
const scrollTo = index => {
if (itemsReferences.current[index].current) {
itemsReferences.current[index].current.scrollIntoView({
behavior: "smooth",
block: "start"
});
}
};
const handleArrows = event => {
if (event.key === "ArrowUp") {
const newIndex = arrowIndex - 1;
if (newIndex >= 0) {
setArrowIndex(newIndex);
scrollTo(newIndex);
}
}
if (event.key === "ArrowDown") {
const newIndex = arrowIndex + 1;
if (newIndex < filteredSelectables.length) {
setArrowIndex(newIndex);
scrollTo(newIndex);
}
}
if (event.key === "Enter") {
const selected = filteredSelectables[arrowIndex];
if (selected) {
atSelect(selected);
setArrowIndex(-1);
if (_hideAtSelect) {
setShowList(false);
}
}
}
};
const handleScroll = () => {
setArrowIndex(-1);
};
if (showList) {
window.addEventListener("keydown", handleArrows);
window.addEventListener("wheel", handleScroll);
} else {
setArrowIndex(-1);
}
return () => {
if (showList) {
window.removeEventListener("keydown", handleArrows);
window.removeEventListener("wheel", handleScroll);
}
};
}), [ arrowIndex, showList ]);
React.useEffect((() => () => {
isMounted.current = false;
}), []);
React.useEffect((() => {
setFilteredSelectables([ ...selectables ]);
}), [ selectables.length ]);
return React__default.default.createElement(StyledDropdown, {
theme: interactionTheme,
left: left,
style: {
...style
},
className: className
}, React__default.default.createElement(StyledDropdownSelected, {
onClick: () => {
setShowList(!showList);
if (setDropdownToggled) {
setDropdownToggled(kind);
}
if (!showList && filterable) {
focusFilterInput();
}
},
theme: generalTheme,
selectedColor: selectedColor
}, typeof selected === "string" ? selected : selected.value, _dropdownSign && React__default.default.createElement(React__default.default.Fragment, null, " ", _dropdownSign)), showList && React__default.default.createElement(StyledDropdownList, {
theme: interactionTheme,
left: left,
listTop: listTop,
level: _level,
heightItems: heightItems && filterable && filteredSelectables.length < heightItems ? filteredSelectables.length + 1 : heightItems,
heightBeyond: filteredSelectables.length > (heightItems || 0),
width: width
}, React__default.default.createElement("ul", null, filterable && React__default.default.createElement("li", {
style: {
backgroundColor: interactionTheme.backgroundColorTertiary,
boxShadow: interactionTheme.boxShadowPenumbraInset
}
}, React__default.default.createElement(StyledFilterable, {
left: left
}, filterUpdate && showFilterUpdate && React__default.default.createElement(StyledFilterUpdate, {
left: left
}, React__default.default.createElement(pluridIconsReact.PluridIconReset, {
theme: interactionTheme,
atClick: () => {
setShowFilterUpdate(false);
filterUpdate();
setTimeout((() => {
if (!isMounted.current) {
return;
}
setShowFilterUpdate(true);
}), 5300);
}
})), React__default.default.createElement(Textline$1, {
ref: filterInput,
theme: interactionTheme,
text: filterValue,
atChange: handleFiltering,
devisible: true,
spellCheck: false,
autoCapitalize: "false",
autoComplete: "false",
autoCorrect: "false",
style: {
padding: !!filterUpdate ? left ? "0 1.3rem 0 0" : "0 0 0 1.3rem" : "0"
}
}))), filteredSelectables.map(((selectable, index) => {
let selectableID = typeof selectable === "string" ? selectable : selectable.id;
let selectableValue = typeof selectable === "string" ? selectable : selectable.value;
let isSelected = false;
if (typeof selected === "string") {
if (selected === selectableID) {
isSelected = true;
}
} else {
if (selected.id === selectableID) {
isSelected = true;
}
}
if (arrowIndex === index) {
isSelected = true;
}
return React__default.default.createElement("li", {
ref: itemsReferences.current[index],
key: selectableID,
onClick: () => handleSelect(selectable),
onMouseEnter: () => handleHover(selectable),
style: {
backgroundColor: isSelected ? selectedBackgroundColor : ""
}
}, selectableValue);
})))));
};
const StyledEntityPill = styled__default.default.div`
background-color: ${({theme: theme}) => theme.backgroundColorTertiary};
box-shadow: ${({theme: theme}) => theme.boxShadowUmbra};
padding: 0.5rem 1rem;
margin: 0.5rem;
border-radius: 20px;
display: flex;
align-items: center;
`;
const EntityPill$1 = properties => {
const {id: id, remove: remove, text: text, theme: theme, style: style} = properties;
const textValue = text || id;
return React__default.default.createElement(StyledEntityPill, {
theme: theme || themes.plurid,
style: {
...style
}
}, React__default.default.createElement("div", {
style: {
marginRight: "0.5rem"
}
}, textValue), React__default.default.createElement(pluridIconsReact.PluridIconDelete, {
theme: theme,
atClick: () => remove(id)
}));
};
const StyledEntityPillGroup = styled__default.default.div`
display: flex;
flex-flow: wrap;
margin: 0 auto;
justify-content: center;
`;
const EntityPillGroup$1 = properties => {
const {entities: entities, remove: remove, keyFix: keyFix, theme: theme, style: style, pillStyle: pillStyle} = properties;
return React__default.default.createElement(StyledEntityPillGroup, {
theme: theme,
style: {
...style
}
}, entities.map((entity => {
const stringEntity = typeof entity === "string";
const id = stringEntity ? entity : entity.id;
const text = stringEntity ? undefined : entity.text;
return React__default.default.createElement(EntityPill$1, {
key: `entity-pill-${id}${keyFix || ""}`,
id: id,
text: text,
remove: remove,
theme: theme || themes.plurid,
style: pillStyle
});
})));
};
const StyledInputDescriptor = styled__default.default.div`
text-align: left;
font-size: 0.9rem;
line-height: 1;
min-height: 1.1rem;
margin-top: 1.3rem;
margin-bottom: 0.4rem;
margin-left: 0.9rem;
font-family: ${({theme: theme}) => theme.fontFamilySansSerif};
color: ${({theme: theme}) => theme.colorPrimary};
`;
const InputDescriptor$1 = properties => {
const {name: name, show: show, theme: themeProperty, style: style, className: className} = properties;
const theme = themeProperty || themes.plurid;
return React__default.default.createElement(StyledInputDescriptor, {
theme: theme,
className: className,
style: {
...style
}
}, show && React__default.default.createElement(React__default.default.Fragment, null, name));
};
const StyledInputBox = styled__default.default.div`
textarea {
box-sizing: border-box;
width: 100%;
min-height: 5rem;
resize: vertical;
outline: none;
border: none;
padding: 0.9rem;
font-size: 0.8rem;
border-radius: 0.9rem;
line-height: 1.5;
font-family: ${({theme: theme}) => theme.fontFamilySansSerif};
color: ${({theme: theme}) => theme.colorPrimary};
background-color: ${({theme: theme}) => theme.backgroundColorTertiary};
box-shadow: inset 0px 4px 4px ${({theme: theme}) => theme.boxShadowUmbraColor};
::placeholder {
color: ${({theme: theme}) => theme.colorSecondary};
}
}
`;
const StyledTextBox = styled__default.default.div`
`;
const InputBox$1 = properties => {
const {text: text, name: name, atChange: atChange, theme: themeProperty, style: style, className: className, atKeyDown: atKeyDown} = properties;
const theme = themeProperty || themes.plurid;
return React__default.default.createElement(StyledInputBox, {
theme: theme,
className: className,
style: {
...style
}
}, React__default.default.createElement(InputDescriptor$1, {
name: name,
show: text !== "",
theme: theme
}), React__default.default.createElement(StyledTextBox, {
theme: theme
}, React__default.default.createElement("textarea", {
value: text,
placeholder: name,
onChange: event => atChange(event),
onKeyDown: event => atKeyDown ? atKeyDown(event) : null,
spellCheck: false,
autoCapitalize: "false",
autoComplete: "false",
autoCorrect: "false"
})));
};
const StyledInputLine = styled__default.default.div`
width: 350px;
`;
const InputLine$1 = properties => {
const {name: name, text: text, atChange: atChange, theme: themeProperty, type: type, error: error, textline: textline, style: style, className: className, atKeyDown: atKeyDown} = properties;
const theme = themeProperty || themes.plurid;
return React__default.default.createElement(StyledInputLine, {
theme: theme,
style: {
...style
},
className: className
}, React__default.default.createElement(InputDescriptor$1, {
name: name,
show: text !== "",
theme: theme
}), React__default.default.createElement(Textline$1, {
text: text,
type: type,
placeholder: name,
theme: theme,
level: 2,
error: error,
spellCheck: false,
autoCapitalize: "false",
autoComplete: "false",
autoCorrect: "false",
atChange: atChange,
atKeyDown: atKeyDown,
...textline
}));
};
const StyledSwitch = styled__default.default.label`
position: relative;
display: inline-block;
width: 60px;
height: 34px;
input {
opacity: 0;
width: 0;
height: 0;
}
`;
const levelBackgroundColor = props => {
switch (props.level) {
case 0:
return props.theme.backgroundColorPrimary;
case 1:
return props.theme.backgroundColorSecondary;
case 2:
return props.theme.backgroundColorTertiary;
case 3:
return props.theme.backgroundColorQuaternary;
default:
return props.theme.backgroundColorPrimary;
}
};
const backgroundColor = props => {
if (props.accent) {
return props.accent;
}
if (props.exclusive && !props.checked) {
switch (props.level) {
case 0:
return props.theme.backgroundColorPrimaryAlpha;
case 1:
return props.theme.backgroundColorSecondaryAlpha;
case 2:
return props.theme.backgroundColorTertiaryAlpha;
case 3:
return props.theme.backgroundColorQuaternaryAlpha;
default:
return props.theme.backgroundColorPrimaryAlpha;
}
}
return levelBackgroundColor(props);
};
const StyledSwitchSlider = styled__default.default.span`
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
transition: .4s ease-in-out;
box-shadow: inset 0 2px 3px black;
background-color: ${props => backgroundColor(props)};
border-radius: ${props => {
if (props.round) {
return "34px";
}
return "0";
}};
:before {
position: absolute;
content: "";
height: 26px;
width: 26px;
left: 4px;
bottom: 4px;
transition: .4s;
background-color: ${props => props.theme.colorPrimary};
border-radius: ${props => {
if (props.round) {
return "50%";
}
return "0";
}};
transform: ${props => {
if (props.checked) {
return "translateX(26px)";
}
return "translateX(0px)";
}};