reablocks
Version:
Component library for React
1,436 lines • 363 kB
JavaScript
(function(global, factory) {
typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("react"), require("react/jsx-runtime"), require("body-scroll-lock-upgrade"), require("motion/react"), require("react-dom"), require("@floating-ui/react"), require("tailwind-merge"), require("date-fns"), require("focus-trap-react"), require("name-initials"), require("@marko19907/string-to-color"), require("ellipsize"), require("ctrl-keys"), require("classnames"), require("react-highlight-words"), require("@reaviz/react-use-fuzzy"), require("react-fast-compare"), require("react-textarea-autosize"), require("pluralize"), require("human-format"), require("coverup"), require("chroma-js"), require("create-global-state-hook")) : typeof define === "function" && define.amd ? define(["exports", "react", "react/jsx-runtime", "body-scroll-lock-upgrade", "motion/react", "react-dom", "@floating-ui/react", "tailwind-merge", "date-fns", "focus-trap-react", "name-initials", "@marko19907/string-to-color", "ellipsize", "ctrl-keys", "classnames", "react-highlight-words", "@reaviz/react-use-fuzzy", "react-fast-compare", "react-textarea-autosize", "pluralize", "human-format", "coverup", "chroma-js", "create-global-state-hook"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global.reablocks = {}, global.React, global.jsxRuntime, global.bodyScrollLockUpgrade, global.react, global.reactDom, global.react$1, global.tailwindMerge, global.dateFns, global.FocusTrap, global.getInitials, global.stringToColor, global.ellipsize, global.ctrlKeys, global.classNames, global.Highlighter, global.reactUseFuzzy, global.isEqual, global.TextareaAutosize, global.pluralizeLib, global.humanFormat, global.coverup, global.chroma, global.creteGlobalStateHook));
})(this, function(exports2, React, jsxRuntime, bodyScrollLockUpgrade, react, reactDom, react$1, tailwindMerge, dateFns, FocusTrap, getInitials, stringToColor, ellipsize, ctrlKeys, classNames, Highlighter, reactUseFuzzy, isEqual, TextareaAutosize, pluralizeLib, humanFormat, coverup, chroma, creteGlobalStateHook) {
"use strict";
function _interopNamespaceDefault(e) {
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
if (e) {
for (const k in e) {
if (k !== "default") {
const d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: () => e[k]
});
}
}
}
n.default = e;
return Object.freeze(n);
}
const React__namespace = /* @__PURE__ */ _interopNamespaceDefault(React);
const useExitListener = ({
ref,
open = true,
onClickOutside,
onEscape
}) => {
React.useEffect(() => {
if (!open) {
return;
}
const handleClick = (event) => {
if (ref.current && !ref.current.contains(event.target)) {
onClickOutside == null ? void 0 : onClickOutside(event);
}
};
const handleKey = (event) => {
if (event.code === "Escape") {
onEscape == null ? void 0 : onEscape(event);
}
};
if (onClickOutside) {
document.addEventListener("mousedown", handleClick);
document.addEventListener("touchstart", handleClick);
}
if (onEscape) {
document.addEventListener("keydown", handleKey);
}
return () => {
if (onClickOutside) {
document.removeEventListener("mousedown", handleClick);
document.removeEventListener("touchstart", handleClick);
}
if (onEscape) {
document.removeEventListener("keydown", handleKey);
}
};
}, [ref, onClickOutside, onEscape, open]);
};
const OverlayContext = React.createContext({
close: () => void 0
});
let id = 0;
const genId = () => `ref-${++id}`;
const useId = (idFromProps) => {
const [id2] = React.useState(idFromProps || genId());
return `${id2}`;
};
const useUnmount = (fn) => {
const fnRef = React.useRef(fn);
fnRef.current = fn;
React.useLayoutEffect(() => () => fnRef.current(), []);
};
const Portal = React.forwardRef(
({ children, className, style, element = "div", onMount, onUnmount }, ref) => {
const elementRef = React.useRef(null);
const mounted = React.useRef(false);
React.useEffect(() => {
var _a;
if (className && elementRef.current) {
elementRef.current.setAttribute("class", `${className} rdk-portal`);
}
if (style && elementRef.current) {
(_a = Object.keys(style)) == null ? void 0 : _a.forEach(
(key) => {
var _a2;
return (_a2 = elementRef.current.style) == null ? void 0 : _a2.setProperty(key, style[key]);
}
);
}
}, [className, style, elementRef.current]);
React.useLayoutEffect(() => {
elementRef.current = document.createElement(element);
onMount == null ? void 0 : onMount();
}, []);
useUnmount(() => {
onUnmount == null ? void 0 : onUnmount();
const ref2 = elementRef.current;
if (ref2 && document.body.contains(ref2)) {
document.body.removeChild(ref2);
}
});
React.useImperativeHandle(ref, () => elementRef.current);
if (!elementRef.current) {
return null;
}
if (!mounted.current) {
mounted.current = true;
elementRef.current.classList.add("rdk-portal");
document.body.appendChild(elementRef.current);
}
return reactDom.createPortal(children, elementRef.current);
}
);
const portals = [];
const START_INDEX = 990;
const OverlayPortal = React.forwardRef(
({
className,
children,
onMount,
onUnmount,
appendToBody = true,
id: id2,
style
}, ref) => {
let portalId = useId(id2);
const [portalIndex, setPortalIndex] = React.useState(null);
const [overlayIndex, setOverlayIndex] = React.useState(null);
const portalRef = React.useRef(null);
React.useImperativeHandle(ref, () => portalRef.current);
return /* @__PURE__ */ jsxRuntime.jsx(
Portal,
{
className,
ref: portalRef,
style,
appendToBody,
onMount: () => {
portals.push(portalId);
let pidx = portals.indexOf(portalId);
setPortalIndex(pidx);
const overlayIdx = START_INDEX + pidx * 2 + 1;
setOverlayIndex(overlayIdx);
onMount == null ? void 0 : onMount({
portalId,
overlayIndex: overlayIdx,
portalIndex: pidx,
backdropIndex: overlayIdx
});
},
onUnmount: () => {
onUnmount == null ? void 0 : onUnmount();
portals.splice(portals.indexOf(portalId), 1);
setPortalIndex(null);
setOverlayIndex(null);
},
children: children({
overlayIndex,
portalIndex,
backdropIndex: overlayIndex,
portalId
})
}
);
}
);
const Backdrop = ({
zIndex = 998,
portalIndex = 0,
className,
theme: customTheme,
onClick
}) => {
const theme2 = useComponentTheme("backdrop", customTheme);
return /* @__PURE__ */ jsxRuntime.jsx(
react.motion.div,
{
className: cn(theme2.base, className),
initial: { opacity: 0 },
animate: { opacity: theme2.opacity - portalIndex / 10 },
exit: { opacity: 0 },
style: { zIndex },
onClick
}
);
};
const backdropTheme = {
base: "fixed top-0 left-0 w-full h-full opacity-0 select-none bg-black",
opacity: 0.8
};
const legacyBackdropTheme = {
base: "fixed top-0 left-0 w-full h-full opacity-0 select-none bg-[var(--color-layer-transparent)]",
opacity: 0.8
};
const GlobalOverlay = ({
open,
hasBackdrop = true,
closeOnEscape = true,
closeOnBackdropClick = true,
backdropClassName,
children,
onClose
}) => {
const overlayRef = React.useRef(null);
const onBackdropClick = React.useCallback(() => {
if (closeOnBackdropClick) {
onClose == null ? void 0 : onClose();
}
}, [closeOnBackdropClick, onClose]);
useExitListener({
ref: overlayRef,
open,
onEscape: () => closeOnEscape && (onClose == null ? void 0 : onClose())
});
React.useEffect(() => {
if (open && overlayRef.current !== void 0) {
bodyScrollLockUpgrade.disableBodyScroll(overlayRef.current, {
// allowTouchMove determines which elements to allow touchmove events for iOS
// Reference: https://github.com/rick-liruixin/body-scroll-lock-upgrade?tab=readme-ov-file#allowtouchmove
// NOTE: allowTouchMove is typed wrong: https://github.com/rick-liruixin/body-scroll-lock-upgrade/issues/21
allowTouchMove: (el) => {
while (el && el !== document.body) {
if (el.getAttribute("body-scroll-lock-ignore") !== null) {
return true;
}
if (el.parentElement !== null) {
el = el.parentElement;
}
}
return false;
}
});
} else {
bodyScrollLockUpgrade.clearAllBodyScrollLocks();
}
return () => {
bodyScrollLockUpgrade.clearAllBodyScrollLocks();
};
}, [children, open]);
return /* @__PURE__ */ jsxRuntime.jsx(OverlayContext.Provider, { value: { close: () => onClose == null ? void 0 : onClose() }, children: /* @__PURE__ */ jsxRuntime.jsx(react.AnimatePresence, { children: open && /* @__PURE__ */ jsxRuntime.jsx(OverlayPortal, { ref: overlayRef, children: ({ overlayIndex, portalIndex }) => /* @__PURE__ */ jsxRuntime.jsxs(React.Fragment, { children: [
hasBackdrop && /* @__PURE__ */ jsxRuntime.jsx(
Backdrop,
{
zIndex: overlayIndex,
portalIndex,
onClick: onBackdropClick,
className: backdropClassName
}
),
/* @__PURE__ */ jsxRuntime.jsx("div", { "body-scroll-lock-ignore": "true", children: children({ overlayIndex, portalIndex }) })
] }) }) }) });
};
const OverlayTrigger = React.forwardRef(
({
children,
className,
elementType = "span",
trigger = ["click"],
onOpen = () => void 0,
onClose = () => void 0
}, ref) => {
const hasTrigger = React.useCallback(
(type) => {
if (Array.isArray(trigger)) {
return trigger.includes(type);
} else {
return type === trigger;
}
},
[trigger]
);
const onFocus = React.useCallback(
(event) => {
if (hasTrigger("focus")) {
onOpen({ type: "focus", nativeEvent: event });
}
},
[onOpen, hasTrigger]
);
const onBlur = React.useCallback(
(event) => {
if (hasTrigger("focus")) {
onClose({ type: "focus", nativeEvent: event });
}
},
[onClose, hasTrigger]
);
const onMouseEnter = React.useCallback(
(event) => {
if (hasTrigger("hover")) {
onOpen({ type: "hover", nativeEvent: event });
}
},
[onOpen, hasTrigger]
);
const onMouseLeave = React.useCallback(
(event) => {
if (hasTrigger("hover")) {
onClose({ type: "hover", nativeEvent: event });
}
},
[onClose, hasTrigger]
);
const onClick = React.useCallback(
(event) => {
if (hasTrigger("click")) {
onOpen({ type: "click", nativeEvent: event });
}
if (!hasTrigger("click")) {
onClose({ type: "hover", nativeEvent: event });
}
},
[onOpen, onClose, hasTrigger]
);
const onContextMenu = React.useCallback(
(event) => {
if (hasTrigger("contextmenu")) {
event.preventDefault();
onOpen({ type: "contextmenu", nativeEvent: event });
}
},
[hasTrigger, onOpen]
);
const tabIndex = hasTrigger("focus") ? -1 : void 0;
const Component = elementType;
return /* @__PURE__ */ jsxRuntime.jsx(
Component,
{
ref,
tabIndex,
onMouseEnter,
onMouseLeave,
onFocus,
onBlur,
onClick,
onContextMenu,
className,
children
}
);
}
);
const usePosition = ({
reference,
floating,
followCursor,
placement = "top",
modifiers = [react$1.flip(), react$1.shift({ limiter: react$1.limitShift() })]
} = {}) => {
const isVirtualElement = React.useMemo(
() => !(reference == null ? void 0 : reference.nodeType),
[reference]
);
const { refs, floatingStyles, update } = react$1.useFloating({
open: true,
placement,
middleware: modifiers,
elements: {
reference: isVirtualElement ? null : reference,
floating
},
whileElementsMounted: react$1.autoUpdate
});
React.useEffect(() => {
if (isVirtualElement && reference && !followCursor) {
const refObject = reference;
refs.setPositionReference({
getBoundingClientRect() {
return {
width: refObject.width,
height: refObject.height,
x: refObject.left,
y: refObject.top,
left: refObject.left,
top: refObject.top,
right: refObject.left + refObject.width,
bottom: refObject.top + refObject.height
};
}
});
}
}, [reference, refs, isVirtualElement, followCursor]);
const onMouseMove = React.useCallback(
({ clientX, clientY }) => {
refs.setPositionReference({
getBoundingClientRect() {
return {
width: 0,
height: 0,
x: clientX,
y: clientY,
left: clientX,
top: clientY,
right: clientX,
bottom: clientY
};
}
});
},
[refs]
);
React.useLayoutEffect(() => {
if (followCursor) {
window.addEventListener("mousemove", onMouseMove);
}
return () => {
window.removeEventListener("mousemove", onMouseMove);
};
}, [followCursor, onMouseMove]);
return {
refs,
anchorRef: refs.reference,
floatingRef: refs.floating,
floatingStyles,
update
};
};
const ConnectedOverlayContent = React.forwardRef(
({
triggerRef,
children,
portalClassName,
closeOnBodyClick = true,
closeOnEscape = true,
elementType,
appendToBody = true,
followCursor,
modifiers,
placement = "bottom",
onClose
}, ref) => {
const id2 = useId();
const [overlayIndex, setOverlayIndex] = React.useState(null);
const { refs, floatingStyles, update } = usePosition({
reference: triggerRef.current ?? triggerRef,
followCursor,
modifiers,
placement
});
React.useImperativeHandle(ref, () => ({
updatePosition: () => {
update();
}
}));
const onClickOutside = React.useCallback(
(event) => {
if (closeOnBodyClick) {
let ref2 = null;
if (triggerRef.current) {
ref2 = triggerRef.current;
} else if (triggerRef.contains !== void 0) {
ref2 = triggerRef;
}
const container = event.target.closest(".rdk-portal");
const isLast = portals.indexOf(id2) === portals.length - 1;
if (!(ref2 == null ? void 0 : ref2.contains(event.target)) && (isLast || !container)) {
onClose == null ? void 0 : onClose(event);
}
}
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[closeOnBodyClick, onClose]
);
const onEscape = React.useCallback(() => {
if (closeOnEscape) {
onClose == null ? void 0 : onClose();
}
}, [closeOnEscape, onClose]);
useExitListener({
open: true,
ref: refs.floating,
onClickOutside,
onEscape
});
return /* @__PURE__ */ jsxRuntime.jsx(
OverlayPortal,
{
id: id2,
ref: refs.setFloating,
style: { ...floatingStyles, "z-index": overlayIndex },
className: portalClassName,
elementType,
appendToBody,
onMount: (event) => setOverlayIndex(event.overlayIndex),
onUnmount: () => setOverlayIndex(null),
children
}
);
}
);
const ConnectedOverlay = React.forwardRef(
({
reference,
children,
open,
content,
triggerElement,
triggerClassName,
trigger = "click",
onOpen,
onClose,
...rest
}, ref) => {
const mounted = React.useRef(false);
const overlayTriggerRef = React.useRef(null);
const contentRef = React.useRef(null);
const triggerRef = reference || overlayTriggerRef;
React.useImperativeHandle(ref, () => ({
updatePosition: () => {
var _a;
(_a = contentRef.current) == null ? void 0 : _a.updatePosition();
}
}));
React.useEffect(() => {
if (mounted.current) {
if (!open) {
onClose == null ? void 0 : onClose();
} else {
onOpen == null ? void 0 : onOpen();
}
}
}, [open]);
React.useEffect(() => {
if (!mounted.current) {
mounted.current = true;
}
});
const providerValue = React.useMemo(
() => ({
close: () => onClose == null ? void 0 : onClose()
}),
[onClose]
);
return /* @__PURE__ */ jsxRuntime.jsxs(OverlayContext.Provider, { value: providerValue, children: [
children && /* @__PURE__ */ jsxRuntime.jsx(React.Fragment, { children: trigger ? /* @__PURE__ */ jsxRuntime.jsx(
OverlayTrigger,
{
elementType: triggerElement,
ref: overlayTriggerRef,
className: triggerClassName,
trigger,
onOpen,
onClose,
children
}
) : children }),
/* @__PURE__ */ jsxRuntime.jsx(react.AnimatePresence, { children: open && /* @__PURE__ */ jsxRuntime.jsx(
ConnectedOverlayContent,
{
...rest,
ref: contentRef,
triggerRef,
onClose,
children: content
}
) })
] });
}
);
const useOverlay = () => {
const context = React.useContext(OverlayContext);
if (context === void 0) {
throw new Error(
"`useOverlay` hook can only be used inside a overlay component."
);
}
return context;
};
const baseTheme$H = {
base: "inline-flex whitespace-no-wrap select-none items-center justify-center px-2.5 py-1 rounded-xs font-sans cursor-pointer",
disabled: "disabled:cursor-not-allowed",
fullWidth: "flex w-full",
group: "rounded-none first:rounded-s last:rounded-e border-s-0 first:border-s",
groupText: "border border-y-transparent border-l-transparent last:border-r-transparent hover:bg-initial",
adornment: {
base: "flex",
start: "pr-1",
end: "pl-1",
sizes: {
small: "[&>svg]:w-3 [&>svg]:h-3",
medium: "[&>svg]:w-4 [&>svg]:h-4",
large: "[&>svg]:w-5 [&>svg]:h-5"
}
},
sizes: {
small: "text-sm px-2 py-1 leading-[normal]",
medium: "text-base px-4 py-2 leading-[normal]",
large: "text-xl px-5 py-2.5 leading-[normal]"
},
iconSizes: {
small: "px-2 py-1",
medium: "px-4 py-2",
large: "px-5 py-2.5"
}
};
const buttonTheme = {
base: [baseTheme$H.base, "text-text-primary font-semibold"].join(" "),
disabled: [
baseTheme$H.disabled,
"data-[variant=filled]:disabled:bg-gray-600 disabled:text-gray-400 border-gray-500"
].join(" "),
fullWidth: baseTheme$H.fullWidth,
group: baseTheme$H.group,
groupText: baseTheme$H.groupText,
adornment: baseTheme$H.adornment,
sizes: baseTheme$H.sizes,
iconSizes: baseTheme$H.iconSizes,
variants: {
filled: "bg-secondary hover:bg-border-secondary-hover border-secondary light:text-gray-100",
outline: "border-grey border",
text: "border-0"
},
colors: {
default: {
filled: "bg-gray-800 hover:bg-gray-700 border-gray-800",
outline: "border-secondary border",
text: "text-text-primary"
},
primary: {
filled: "bg-primary hover:bg-primary-hover border-primary text-text-primary",
outline: "border border-primary",
text: "text-primary hover:text-primary-hover"
},
secondary: {
filled: "bg-secondary hover:bg-secondary-hover text-text-primary!",
outline: "border border-secondary",
text: "text-secondary hover:text-secondary-hover"
},
success: {
filled: "bg-success hover:bg-success-hover border-success text-text-primary",
outline: "border border-success",
text: "text-success hover:text-success-hover"
},
warning: {
filled: "bg-warning hover:bg-warning-hover border-warning text-text-primary",
outline: "border border-warning",
text: "text-warning hover:text-warning-hover"
},
error: {
filled: "bg-error hover:bg-error-hover border-error text-text-primary",
outline: "border border-error",
text: "text-error hover:text-error-hover"
}
}
};
const legacyButtonTheme = {
base: [
baseTheme$H.base,
"[border:_var(--button-border)] rounded-[var(--button-border)] [font-family:_var(--button-font-family)] [font-weight:_var(--button-font-weight)]"
].join(" "),
disabled: [
baseTheme$H.disabled,
"data-[variant=filled]:disabled:bg-[var(--disabled-background)] disabled:text-[var(--button-disabled-color-on-background)] border-[var(--disabled-background)]"
].join(" "),
fullWidth: baseTheme$H.fullWidth,
group: baseTheme$H.group,
groupText: baseTheme$H.groupText,
sizes: {
small: "[font-size:_var(--font-size-sm)] p-[var(--button-spacing-sm)]",
medium: "[font-size:_var(--font-size-md)] p-[var(--button-spacing-md)]",
large: "[font-size:_var(--font-size-lg)] p-[var(--button-spacing-lg)]"
},
iconSizes: {
small: "[font-size:_var(--font-size-sm)] p-[var(--button-spacing-sm)]",
medium: "[font-size:_var(--font-size-md)] p-[var(--button-spacing-md)]",
large: "[font-size:_var(--font-size-lg)] p-[var(--button-spacing-lg)]"
},
adornment: {
...baseTheme$H.adornment,
start: [
baseTheme$H.adornment.start,
"[padding-right:_calc(var(--list-item-spacing)_/_2)]"
].join(" "),
end: [
baseTheme$H.adornment.start,
"[padding-left:_calc(var(--list-item-spacing)_/_2)]"
].join(" "),
sizes: {
small: "[&>svg]:w-[var(--button-adornment-size-sm)] [&>svg]:h-[var(--button-adornment-size-sm)]",
medium: "[&>svg]:w-[var(--button-adornment-size-md)] [&>svg]:h-[var(--button-adornment-size-md)]",
large: "[&>svg]:w-[var(--button-adornment-size-lg)] [&>svg]:h-[var(--button-adornment-size-lg)]"
}
},
variants: {
filled: "bg-[var(--button-background)] text-[var(--button-color-on-background)] hover:bg-[var(--button-background-hover)] border-[var(--button-background)] hover:border-[var(--button-background-hover)]",
outline: "border-[var(--button-background)] hover:border-[var(--button-background-hover)] text-[var(--button-color)] hover:text-[var(--button-color-hover)] border",
text: "border-0"
},
colors: {
default: {
filled: "bg-[var(--button-background)] text-[var(--button-color-on-background)] hover:bg-[var(--button-background-hover)] border-[var(--button-background)] hover:border-[var(--button-background-hover)]",
outline: "",
text: "text-[var(--button-color)] hover:text-[var(--button-color-hover)]"
},
primary: {
filled: "bg-[var(--primary-background)] hover:bg-[var(--primary-background-hover)] border-[var(--primary-background)] border-[var(--primary-background-hover)] text-[var(--button-color-on-background)]",
outline: "",
text: "text-[var(--primary-color)] hover:text-[var(--primary-color-hover)]"
},
secondary: {
filled: "bg-[var(--secondary-background)] hover:bg-[var(--secondary-background-hover)] border-[var(--secondary-background)] hover:border-[var(--secondary-background-hover)] text-[var(--button-color-on-background)]",
outline: "",
text: "text-[var(--secondary-color)] hover:text-[var(--secondary-color-hover)]"
},
success: {
filled: "bg-[var(--success-background)] hover:bg-[var(--success-background-hover)] border-[var(--success-background)] hover:border-[var(--success-background-hover)] text-[var(--button-color-on-background)]",
outline: "",
text: "text-[var(--success-color)] hover:text-[var(--success-color-hover)]"
},
warning: {
filled: "bg-[var(--warning-background)] hover:bg-[var(--warning-background-hover)] border-[var(--warning-background)] hover:border-[var(--warning-background-hover)] text-[var(--button-color-on-background)]",
outline: "",
text: "text-[var(--warning-color)] hover:text-[var(--warning-color-hover)]"
},
error: {
filled: "bg-[var(--error-background)] hover:bg-[var(--error-background-hover)] border-[var(--error-background)] hover:border-[var(--error-background-hover)] text-[var(--button-color-on-background)]",
outline: "",
text: "text-[var(--error-color)] hover:text-[var(--warning-error-hover)]"
}
}
};
const ButtonGroupContext = React.createContext({
variant: null,
size: null
});
const Button = React.forwardRef(
({
color = "default",
variant = "filled",
children,
fullWidth,
size = "medium",
disableAnimation,
className,
disableMargins,
disablePadding,
disabled,
startAdornment,
endAdornment,
theme: customTheme,
type = "button",
...rest
}, ref) => {
const theme2 = useComponentTheme("button", customTheme);
const { variant: groupVariant, size: groupSize } = React.useContext(ButtonGroupContext);
const isGroup = !!groupVariant && !!groupSize;
return /* @__PURE__ */ jsxRuntime.jsxs(
react.motion.button,
{
...rest,
type,
disabled,
ref,
whileTap: { scale: disabled || disableAnimation ? 1 : 0.9 },
"data-variant": groupVariant || variant,
className: tailwindMerge.twMerge(
theme2.base,
theme2.disabled,
fullWidth && theme2.fullWidth,
theme2.variants[groupVariant || variant],
theme2.colors[color][groupVariant || variant],
theme2.sizes[groupSize || size],
isGroup && theme2.group,
isGroup && groupVariant === "text" && theme2.groupText,
disableMargins && "m-0",
disablePadding && "p-0",
className
),
children: [
startAdornment && /* @__PURE__ */ jsxRuntime.jsx(
"div",
{
className: tailwindMerge.twMerge(
theme2.adornment.base,
theme2.adornment.start,
theme2.adornment.sizes[size]
),
children: startAdornment
}
),
children,
endAdornment && /* @__PURE__ */ jsxRuntime.jsx(
"div",
{
className: tailwindMerge.twMerge(
theme2.adornment.base,
theme2.adornment.end,
theme2.adornment.sizes[size]
),
children: endAdornment
}
)
]
}
);
}
);
const ButtonGroup = ({
children,
className,
variant,
size
}) => {
const values = React.useMemo(
() => ({
variant: variant || "filled",
size: size || "medium"
}),
[size, variant]
);
return /* @__PURE__ */ jsxRuntime.jsx(ButtonGroupContext.Provider, { value: values, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className, children }) });
};
const Chip = React.forwardRef(
({
children,
color = "default",
variant = "filled",
size = "medium",
selected,
disabled,
className,
disableMargins,
start,
end,
onClick,
theme: customTheme,
...rest
}, ref) => {
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
const theme2 = useComponentTheme("chip", customTheme);
return /* @__PURE__ */ jsxRuntime.jsxs(
"div",
{
...rest,
ref,
tabIndex: onClick ? 0 : -1,
onClick: !disabled ? onClick : void 0,
className: tailwindMerge.twMerge(
theme2.base,
theme2.variants[variant],
(_a = theme2.colors[color]) == null ? void 0 : _a.base,
(_c = (_b = theme2.colors[color]) == null ? void 0 : _b.variants) == null ? void 0 : _c[variant],
theme2.sizes[size],
theme2.focus,
!!onClick && !disabled && ((_e = (_d = theme2.colors[color]) == null ? void 0 : _d.selectable) == null ? void 0 : _e.base),
!!onClick && !disabled && ((_i = (_h = (_g = (_f = theme2.colors[color]) == null ? void 0 : _f.selectable) == null ? void 0 : _g.variants) == null ? void 0 : _h[variant]) == null ? void 0 : _i.base),
selected && ((_m = (_l = (_k = (_j = theme2.colors[color]) == null ? void 0 : _j.selectable) == null ? void 0 : _k.variants) == null ? void 0 : _l[variant]) == null ? void 0 : _m.selected),
disableMargins && "m-0",
"transition-colors duration-300 ease [&>svg]:transition-[fill] [&>svg]:will-change-[fill]",
className,
disabled && theme2.disabled
),
"aria-disabled": disabled,
children: [
start && /* @__PURE__ */ jsxRuntime.jsx(
"div",
{
className: tailwindMerge.twMerge(
theme2.adornment.base,
theme2.adornment.start,
theme2.adornment.sizes[size]
),
children: start
}
),
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center", children }),
end && /* @__PURE__ */ jsxRuntime.jsx(
"div",
{
className: tailwindMerge.twMerge(
theme2.adornment.base,
theme2.adornment.end,
theme2.adornment.sizes[size]
),
children: end
}
)
]
}
);
}
);
function getMonthNames(locale, format2 = "short") {
if (!locale && typeof window !== "undefined") {
locale = navigator.language;
}
const formatter = new Intl.DateTimeFormat(locale, {
month: format2,
timeZone: "UTC"
});
const months = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12].map((month) => {
const mm = month < 10 ? `0${month}` : month;
return /* @__PURE__ */ new Date(`2017-${mm}-01T00:00:00+00:00`);
});
return months.map((date) => formatter.format(date));
}
const monthNames = getMonthNames();
function getDayLabels(locale) {
return Array.from({ length: 7 }, (_, i) => {
if (!locale && typeof window !== "undefined") {
locale = navigator.language;
}
return new Intl.DateTimeFormat(locale, {
weekday: "short"
}).format(new Date(1970, 0, 4 + i));
});
}
const daysOfWeek = getDayLabels();
function getWeeks(date, options = { format: "MM/dd/yyyy" }) {
if (!date) {
throw new Error("A date is required");
} else if (!dateFns.isValid(date)) {
console.warn("Invalid date - setting to today", date);
date = /* @__PURE__ */ new Date();
}
const daysInMonth = dateFns.getDaysInMonth(date);
let day = dateFns.startOfMonth(date);
let offset = dateFns.getDay(day);
const numOfWeeks = Math.ceil((daysInMonth + offset) / 7);
const weeks = Array.apply(null, {
length: numOfWeeks
}).map(() => []);
const current = /* @__PURE__ */ new Date();
const [firstWeek] = weeks;
for (let i = offset; i > 0; i--) {
const offsetDay = dateFns.subDays(day, i);
firstWeek.push({
date: offsetDay,
dayOfMonth: dateFns.getDate(offsetDay),
isWeekendDay: dateFns.getISODay(offsetDay) > 5,
isPreviousMonth: true,
isNextMonth: false,
isToday: false,
formattedDate: dateFns.format(offsetDay, options.format)
});
}
for (let i = 0, week = weeks[i]; i < numOfWeeks; i++, week = weeks[i]) {
for (let dayOfWeek = offset; dayOfWeek < 7; dayOfWeek++) {
week.push({
date: day,
dayOfMonth: dateFns.getDate(day),
isPreviousMonth: false,
isToday: dateFns.isSameDay(day, current),
isNextMonth: !dateFns.isSameMonth(day, date),
isWeekendDay: dateFns.getISODay(day) > 5,
formattedDate: dateFns.format(day, options.format)
});
day = dateFns.addDays(day, 1);
}
offset = 0;
}
return weeks;
}
function getDayAttributes(day, current, hover, isRange) {
let isActive = false;
let isRangeStart = false;
let isRangeEnd = false;
const isInRange = (date, range) => {
const startDate = dateFns.min(range);
const endDate = dateFns.max(range);
return dateFns.isWithinInterval(date, { start: startDate, end: endDate });
};
const isSelectionStarted = Array.isArray(current) && dateFns.isValid(current[0]);
const isSelectionComplete = isSelectionStarted && dateFns.isValid(current[1]);
if (!isRange && dateFns.isValid(current)) {
isActive = dateFns.isSameDay(day, current);
} else if (!isSelectionStarted) {
isActive = dateFns.isSameDay(day, hover);
isRangeStart = isActive;
isRangeEnd = isActive;
} else if (isSelectionComplete) {
isActive = isInRange(day, current);
isRangeStart = dateFns.isSameDay(day, current[0]);
isRangeEnd = dateFns.isSameDay(day, current[1]);
} else {
const activeRange = [current[0], hover ?? current[0]];
isActive = isInRange(day, activeRange);
isRangeStart = dateFns.isSameDay(day, dateFns.min(activeRange));
isRangeEnd = dateFns.isSameDay(day, dateFns.max(activeRange));
}
return { isActive, isRangeStart, isRangeEnd };
}
function isNextWeekEmpty(day, range, hideNextMonth) {
const nextWeek = dateFns.addDays(day, 7);
const nextWeekInRange = dateFns.isBefore(nextWeek, dateFns.max(range)) || dateFns.isSameDay(nextWeek, dateFns.max(range));
return !(nextWeekInRange && (dateFns.isSameMonth(day, nextWeek) || !hideNextMonth));
}
function isPreviousWeekEmpty(day, range, hidePrevMonth) {
const prevWeek = dateFns.addDays(day, -7);
const prevWeekInRange = dateFns.isAfter(prevWeek, dateFns.min(range)) || dateFns.isSameDay(prevWeek, dateFns.min(range));
return !(prevWeekInRange && (dateFns.isSameMonth(day, prevWeek) || !hidePrevMonth));
}
const CalendarDays = ({
value,
current,
hover = null,
isRange,
disabled,
min: minLimit,
max,
animated,
xAnimation = 0,
showDayOfWeek,
showToday,
dayOfWeekLabels = daysOfWeek,
hidePrevMonthDays,
hideNextMonthDays,
onChange,
onHover,
theme: customTheme
}) => {
const { days } = useComponentTheme("calendar", customTheme);
const [hoveringDate, setHoveringDate] = React.useState(hover);
const weeks = React.useMemo(() => getWeeks(value), [value]);
const maxLimit = React.useMemo(() => max === "now" ? /* @__PURE__ */ new Date() : max, [max]);
const renderDay = React.useCallback(
(day) => {
if (day.isPreviousMonth && hidePrevMonthDays || day.isNextMonth && hideNextMonthDays) {
return /* @__PURE__ */ jsxRuntime.jsx("div", {}, day.dayOfMonth);
}
const handleHover = (value2) => {
if (onHover) {
onHover(value2);
} else {
setHoveringDate(value2);
}
};
const isDisabled = disabled || minLimit && dateFns.isBefore(day.date, minLimit) || maxLimit && dateFns.isAfter(day.date, maxLimit);
const currentHover = hover || hoveringDate;
const { isActive, isRangeStart, isRangeEnd } = getDayAttributes(
day.date,
current,
currentHover,
isRange
);
const currentRange = Array.isArray(current) ? [current[0], current[1] ?? currentHover] : [current ?? hoveringDate, current ?? hoveringDate];
const isRangeMiddle = isRange && isActive && !isRangeStart && !isRangeEnd;
const rangeConnectsBottom = isRangeStart && isNextWeekEmpty(day.date, currentRange, hideNextMonthDays);
const rangeConnectsTop = isRangeEnd && isPreviousWeekEmpty(day.date, currentRange, hidePrevMonthDays);
const colorVariant = isActive ? "primary" : "default";
const buttonVariant = isActive ? "filled" : "text";
return /* @__PURE__ */ jsxRuntime.jsx(
Button,
{
className: cn(days.day, {
[days.outside]: !isActive && (day.isNextMonth || day.isPreviousMonth),
[days.today]: showToday && dateFns.isToday(day.date),
[days.selected]: isActive,
[days.hover]: day.date === currentHover,
[days.range]: isRangeMiddle,
[days.startRangeDate]: isRange && isRangeStart && !isRangeEnd,
[days.cornerStartDateBottom]: isRange && isActive && !rangeConnectsBottom,
[days.endRangeDate]: isRange && isRangeEnd && !isRangeStart,
[days.cornerEndDateTop]: isRange && isActive && !rangeConnectsTop
}),
onMouseEnter: () => handleHover(day.date),
onMouseLeave: () => handleHover(null),
variant: buttonVariant,
color: colorVariant,
disableMargins: true,
disabled: isDisabled,
title: day.formattedDate,
onClick: () => onChange(day.date),
children: day.dayOfMonth
},
day.formattedDate
);
},
[
disabled,
minLimit,
maxLimit,
current,
hover,
isRange,
onChange,
onHover,
hoveringDate,
days,
hideNextMonthDays,
hidePrevMonthDays,
showToday
]
);
return /* @__PURE__ */ jsxRuntime.jsx(react.AnimatePresence, { mode: "popLayout", children: /* @__PURE__ */ jsxRuntime.jsxs(
react.motion.div,
{
initial: { opacity: 0, x: xAnimation },
animate: { opacity: 1, x: 0 },
transition: {
x: { type: animated ? "keyframes" : false },
opacity: { duration: 0.2, type: animated ? "tween" : false }
},
children: [
showDayOfWeek && /* @__PURE__ */ jsxRuntime.jsx("div", { className: days.header, children: dayOfWeekLabels.map((day) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: days.dayOfWeek, children: day.substring(0, 2) }, `day-${day}`)) }),
weeks.map((week, i) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: days.week, children: week.map(renderDay) }, `week-${i}`))
]
},
value.toString()
) });
};
const CalendarMonths = ({
value,
onChange,
theme: customTheme
}) => {
const { months } = useComponentTheme("calendar", customTheme);
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: months.root, children: monthNames.map((month, i) => /* @__PURE__ */ jsxRuntime.jsx(
Button,
{
className: cn(months.month, { [months.selected]: value === i }),
color: value === i ? "primary" : "default",
variant: value === i ? "filled" : "text",
disableMargins: true,
title: month,
onClick: () => onChange(i),
children: month
},
month
)) });
};
const CalendarYears = ({
decadeStart,
decadeEnd,
value,
animated,
xAnimation = 0,
onChange,
theme: customTheme
}) => {
const { years } = useComponentTheme("calendar", customTheme);
const yearDates = React.useMemo(() => {
const arr = [];
const start = decadeStart.getFullYear();
const end = decadeEnd.getFullYear();
for (let i = start - 1; i < end + 2; i++) {
arr.push(i);
}
return arr;
}, [decadeEnd, decadeStart]);
return /* @__PURE__ */ jsxRuntime.jsx(react.AnimatePresence, { mode: "popLayout", children: /* @__PURE__ */ jsxRuntime.jsx(
react.motion.div,
{
className: years.root,
initial: { opacity: 0, x: xAnimation },
animate: { opacity: 1, x: 0 },
transition: {
x: { type: animated ? "keyframes" : false },
opacity: { duration: 0.2, type: animated ? "tween" : false }
},
children: yearDates.map((year) => /* @__PURE__ */ jsxRuntime.jsx(
Button,
{
className: cn(years.year, { [years.selected]: value === year }),
color: value === year ? "primary" : "default",
variant: value === year ? "filled" : "text",
disableMargins: true,
title: year,
onClick: () => onChange(year),
children: year
},
year
))
},
`${decadeStart.toString()}-${decadeEnd.toString()}`
) });
};
const PageTitle = React.forwardRef(
({
children,
color = "default",
variant = "default",
disableMargins = false,
className,
theme: customTheme,
...rest
}, ref) => {
const theme2 = useComponentTheme("typography", customTheme);
return /* @__PURE__ */ jsxRuntime.jsx(
"h1",
{
ref,
className: tailwindMerge.twMerge(
theme2.colors[color],
theme2.variant[variant],
theme2.pageTitle,
disableMargins && theme2.disableMargins,
className
),
...rest,
children
}
);
}
);
const PrimaryHeading = React.forwardRef(
({
children,
color = "default",
variant = "default",
disableMargins = false,
className,
theme: customTheme,
...rest
}, ref) => {
const theme2 = useComponentTheme(
"typography",
customTheme
);
return /* @__PURE__ */ jsxRuntime.jsx(
"h2",
{
ref,
className: tailwindMerge.twMerge(
theme2.colors[color],
theme2.variant[variant],
theme2.primaryHeading,
disableMargins && theme2.disableMargins,
className
),
...rest,
children
}
);
}
);
const SecondaryHeading = React.forwardRef(
({
children,
color = "default",
variant = "default",
disableMargins = false,
className,
theme: customTheme,
...rest
}, ref) => {
const theme2 = useComponentTheme(
"typography",
customTheme
);
return /* @__PURE__ */ jsxRuntime.jsx(
"h3",
{
ref,
className: tailwindMerge.twMerge(
theme2.colors[color],
theme2.variant[variant],
theme2.secondaryHeading,
disableMargins && theme2.disableMargins,
className
),
...rest,
children
}
);
}
);
const SmallHeading = React.forwardRef(
({
children,
color = "default",
variant = "default",
disableMargins = false,
className,
theme: customTheme,
...rest
}, ref) => {
const theme2 = useComponentTheme("typography", customTheme);
return /* @__PURE__ */ jsxRuntime.jsx(
"h5",
{
ref,
className: tailwindMerge.twMerge(
theme2.colors[color],
theme2.variant[variant],
theme2.smallHeading,
disableMargins && theme2.disableMargins,
className
),
...rest,
children
}
);
}
);
const Sub = React.forwardRef(
({
color = "default",
variant = "default",
disableMargins = false,
children,
className,
theme: customTheme,
...rest
}, ref) => {
const theme2 = useComponentTheme("typography", customTheme);
return /* @__PURE__ */ jsxRuntime.jsx(
"h6",
{
ref,
className: tailwindMerge.twMerge(
theme2.colors[color],
theme2.variant[variant],
theme2.sub,
disableMargins && theme2.disableMargins,
className
),
...rest,
children
}
);
}
);
const Text = React.forwardRef(
({
color = "default",
variant = "default",
fontStyle = "default",
children,
className,
theme: customTheme,
...rest
}, ref) => {
const theme2 = useComponentTheme("typography", customTheme);
return /* @__PURE__ */ jsxRuntime.jsx(
"span",
{
ref,
className: tailwindMerge.twMerge(
theme2.colors[color],
theme2.variant[variant],
theme2.text[fontStyle],
className
),
...rest,
children
}
);
}
);
const baseTheme$G = {
text: {
thin: "font-thin",
bold: "font-semibold",
extraBold: "font-extrabold",
italic: "italic"
},
variant: {
default: "",
mono: "font-mono"
},
colors: {
primary: "text-primary",
secondary: "text-secondary",
success: "text-success",
warning: "text-warning",
error: "text-error",
info: "text-info"
},
sub: "text-sm font-semibold mb-0.5",
smallHeading: "text-base font-normal mb-1",
secondaryHeading: "text-3xl font-normal mb-1",
primaryHeading: "text-3xl font-extrabold mb-1",
pageTitle: "text-[40px] font-semibold mb-5",
disableMargins: "m-0"
};
const typographyTheme = {
...baseTheme$G
};
const legacyTypographyTheme = {
...baseTheme$G,
colors: {
primary: "text-[var(--primary-color)]",
secondary: "text-[var(--secondary-color)]",
success: "text-[var(--success-color)]",
warning: "text-[var(--warning-color)]",
error: "text-[var(--error-color)]",
info: "text-[var(--info-color)]"
},
pageTitle: "[font-family:_var(--font-family)] [font-size:_var(--page-title-font-size)] [font-weight:_var(--page-title-font-weight)] color-[var(--page-title-color)] m-[var(--page-title-margin)]",
primaryHeading: "[font-family:_var(--font-family)] [font-size:_var(--primary-heading-font-size)] [font-weight:_var(--primary-heading-font-weight)] text-[var(--primary-heading-color)] m-[var(--primary-heading-margin)]",
secondaryHeading: "[font-family:_var(--font-family)] [font-size:_var(--secondary-heading-font-size)] [font-weight:_var(--secondary-heading-font-weight)] text-[var(--secondary-heading-color)] m-[var(--secondary-heading-margin)]",
smallHeading: "[font-family:_var(--font-family)] [font-size:_var(--small-heading-font-size)] [font-weight:_var(--small-heading-font-weight)] text-[var(--small-heading-color)] m-[var(--small-heading-margin)]",
sub: "[font-size:_var(--sub-font-size)] [font-weight:_var(--sub-font-weight)] text-[var(--sub-color)] m-[var(--sub-margin)]",
text: {
...baseTheme$G.text,
thin: "[font-weight:_var(--font-weight-thin)]",
bold: "[font-weight:_var(--font-weight-bold)]",
extraBold: "[font-weight:_var(--font-weight-extraBold)]"
}
};
const Divider = ({
className,
disableMargins = false,
orientation = "horizontal",
variant = "primary",
theme: customTheme,
...rest
}) => {
const theme2 = useComponentTheme("divider", customTheme);
return /* @__PURE__ */ jsxRuntime.jsx(
"hr",
{
...rest,
className: tailwindMerge.twMerge(
theme2.base,
theme2.variant[variant],
theme2.orientation[orientation],
disableMargins && theme2.disableMargins,
className
)
}
);
};
const baseTheme$F = {
base: "border-none",
orientation: {
horizontal: "h-px w-full my-2.5",
vertical: "w-px h-full mx-2.5"
},
variant: {
primary: "bg-surface",
secondary: "bg-linear-to-r from-transparent to-transparent via-blue-500"
},
disableMargins: "my-0 mx-0"
};
const dividerTheme = {
...baseTheme$F
};
const legacyDividerTheme = {
...baseTheme$F,
base: [baseTheme$F.base, "bg-[var(--divider-background)]"].join(" "),
orientation: {
horizontal: [
baseTheme$