UNPKG

reablocks

Version:
1,597 lines (1,596 loc) 355 kB
import * as React from "react"; import { useEffect, createContext, useState, useRef, useLayoutEffect, forwardRef, useImperativeHandle, useCallback, Fragment, useMemo, useContext, createElement, Children, isValidElement, cloneElement, Suspense } from "react"; import { jsx, jsxs, Fragment as Fragment$1 } from "react/jsx-runtime"; import { disableBodyScroll, clearAllBodyScrollLocks } from "body-scroll-lock-upgrade"; import { motion, AnimatePresence, useMotionValue, useTransform } from "motion/react"; import { createPortal } from "react-dom"; import { useFloating, autoUpdate, flip, shift, limitShift, size } from "@floating-ui/react"; import { twMerge } from "tailwind-merge"; import { getHours, getMinutes, getSeconds, setSeconds, setMinutes, setHours, differenceInMinutes, isSameDay, differenceInSeconds, isValid, getDaysInMonth, startOfMonth, getDay, subDays, getDate, getISODay, format, isSameMonth, addDays, startOfDay, endOfDay, min, max, isBefore, isAfter, isWithinInterval, isToday, isSameHour, subWeeks, subMonths, subYears, addWeeks, addMonths, addYears, startOfWeek, endOfWeek, endOfMonth, startOfYear, endOfYear, getMonth, getYear, startOfDecade, endOfDecade, sub, add, setMonth, setYear, parse, formatDistance } from "date-fns"; import FocusTrap from "focus-trap-react"; import getInitials from "name-initials"; import { generateColor } from "@marko19907/string-to-color"; import ellipsize from "ellipsize"; import { keys } from "ctrl-keys"; import classNames from "classnames"; import Highlighter from "react-highlight-words"; import { useFuzzy } from "@reaviz/react-use-fuzzy"; import isEqual from "react-fast-compare"; import TextareaAutosize from "react-textarea-autosize"; import pluralizeLib from "pluralize"; import humanFormat from "human-format"; import coverup from "coverup"; import chroma from "chroma-js"; import creteGlobalStateHook from "create-global-state-hook"; const useExitListener = ({ ref, open = true, onClickOutside, onEscape }) => { 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 = createContext({ close: () => void 0 }); let id = 0; const genId = () => `ref-${++id}`; const useId = (idFromProps) => { const [id2] = useState(idFromProps || genId()); return `${id2}`; }; const useUnmount = (fn) => { const fnRef = useRef(fn); fnRef.current = fn; useLayoutEffect(() => () => fnRef.current(), []); }; const Portal = forwardRef( ({ children, className, style, element = "div", onMount, onUnmount }, ref) => { const elementRef = useRef(null); const mounted = useRef(false); 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]); 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); } }); 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 createPortal(children, elementRef.current); } ); const portals = []; const START_INDEX = 990; const OverlayPortal = forwardRef( ({ className, children, onMount, onUnmount, appendToBody = true, id: id2, style }, ref) => { let portalId = useId(id2); const [portalIndex, setPortalIndex] = useState(null); const [overlayIndex, setOverlayIndex] = useState(null); const portalRef = useRef(null); useImperativeHandle(ref, () => portalRef.current); return /* @__PURE__ */ 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__ */ jsx( 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 = useRef(null); const onBackdropClick = useCallback(() => { if (closeOnBackdropClick) { onClose == null ? void 0 : onClose(); } }, [closeOnBackdropClick, onClose]); useExitListener({ ref: overlayRef, open, onEscape: () => closeOnEscape && (onClose == null ? void 0 : onClose()) }); useEffect(() => { if (open && overlayRef.current !== void 0) { 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 { clearAllBodyScrollLocks(); } return () => { clearAllBodyScrollLocks(); }; }, [children, open]); return /* @__PURE__ */ jsx(OverlayContext.Provider, { value: { close: () => onClose == null ? void 0 : onClose() }, children: /* @__PURE__ */ jsx(AnimatePresence, { children: open && /* @__PURE__ */ jsx(OverlayPortal, { ref: overlayRef, children: ({ overlayIndex, portalIndex }) => /* @__PURE__ */ jsxs(Fragment, { children: [ hasBackdrop && /* @__PURE__ */ jsx( Backdrop, { zIndex: overlayIndex, portalIndex, onClick: onBackdropClick, className: backdropClassName } ), /* @__PURE__ */ jsx("div", { "body-scroll-lock-ignore": "true", children: children({ overlayIndex, portalIndex }) }) ] }) }) }) }); }; const OverlayTrigger = forwardRef( ({ children, className, elementType = "span", trigger = ["click"], onOpen = () => void 0, onClose = () => void 0 }, ref) => { const hasTrigger = useCallback( (type) => { if (Array.isArray(trigger)) { return trigger.includes(type); } else { return type === trigger; } }, [trigger] ); const onFocus = useCallback( (event) => { if (hasTrigger("focus")) { onOpen({ type: "focus", nativeEvent: event }); } }, [onOpen, hasTrigger] ); const onBlur = useCallback( (event) => { if (hasTrigger("focus")) { onClose({ type: "focus", nativeEvent: event }); } }, [onClose, hasTrigger] ); const onMouseEnter = useCallback( (event) => { if (hasTrigger("hover")) { onOpen({ type: "hover", nativeEvent: event }); } }, [onOpen, hasTrigger] ); const onMouseLeave = useCallback( (event) => { if (hasTrigger("hover")) { onClose({ type: "hover", nativeEvent: event }); } }, [onClose, hasTrigger] ); const onClick = useCallback( (event) => { if (hasTrigger("click")) { onOpen({ type: "click", nativeEvent: event }); } if (!hasTrigger("click")) { onClose({ type: "hover", nativeEvent: event }); } }, [onOpen, onClose, hasTrigger] ); const onContextMenu = 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__ */ jsx( Component, { ref, tabIndex, onMouseEnter, onMouseLeave, onFocus, onBlur, onClick, onContextMenu, className, children } ); } ); const usePosition = ({ reference, floating, followCursor, placement = "top", modifiers = [flip(), shift({ limiter: limitShift() })] } = {}) => { const isVirtualElement = useMemo( () => !(reference == null ? void 0 : reference.nodeType), [reference] ); const { refs, floatingStyles, update } = useFloating({ open: true, placement, middleware: modifiers, elements: { reference: isVirtualElement ? null : reference, floating }, whileElementsMounted: autoUpdate }); 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 = useCallback( ({ clientX, clientY }) => { refs.setPositionReference({ getBoundingClientRect() { return { width: 0, height: 0, x: clientX, y: clientY, left: clientX, top: clientY, right: clientX, bottom: clientY }; } }); }, [refs] ); 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 = forwardRef( ({ triggerRef, children, portalClassName, closeOnBodyClick = true, closeOnEscape = true, elementType, appendToBody = true, followCursor, modifiers, placement = "bottom", onClose }, ref) => { const id2 = useId(); const [overlayIndex, setOverlayIndex] = useState(null); const { refs, floatingStyles, update } = usePosition({ reference: triggerRef.current ?? triggerRef, followCursor, modifiers, placement }); useImperativeHandle(ref, () => ({ updatePosition: () => { update(); } })); const onClickOutside = 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 = useCallback(() => { if (closeOnEscape) { onClose == null ? void 0 : onClose(); } }, [closeOnEscape, onClose]); useExitListener({ open: true, ref: refs.floating, onClickOutside, onEscape }); return /* @__PURE__ */ 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 = forwardRef( ({ reference, children, open, content, triggerElement, triggerClassName, trigger = "click", onOpen, onClose, ...rest }, ref) => { const mounted = useRef(false); const overlayTriggerRef = useRef(null); const contentRef = useRef(null); const triggerRef = reference || overlayTriggerRef; useImperativeHandle(ref, () => ({ updatePosition: () => { var _a; (_a = contentRef.current) == null ? void 0 : _a.updatePosition(); } })); useEffect(() => { if (mounted.current) { if (!open) { onClose == null ? void 0 : onClose(); } else { onOpen == null ? void 0 : onOpen(); } } }, [open]); useEffect(() => { if (!mounted.current) { mounted.current = true; } }); const providerValue = useMemo( () => ({ close: () => onClose == null ? void 0 : onClose() }), [onClose] ); return /* @__PURE__ */ jsxs(OverlayContext.Provider, { value: providerValue, children: [ children && /* @__PURE__ */ jsx(Fragment, { children: trigger ? /* @__PURE__ */ jsx( OverlayTrigger, { elementType: triggerElement, ref: overlayTriggerRef, className: triggerClassName, trigger, onOpen, onClose, children } ) : children }), /* @__PURE__ */ jsx(AnimatePresence, { children: open && /* @__PURE__ */ jsx( ConnectedOverlayContent, { ...rest, ref: contentRef, triggerRef, onClose, children: content } ) }) ] }); } ); const useOverlay = () => { const context = 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 = createContext({ variant: null, size: null }); const Button = forwardRef( ({ color = "default", variant = "filled", children, fullWidth, size: size2 = "medium", disableAnimation, className, disableMargins, disablePadding, disabled, startAdornment, endAdornment, theme: customTheme, type = "button", ...rest }, ref) => { const theme2 = useComponentTheme("button", customTheme); const { variant: groupVariant, size: groupSize } = useContext(ButtonGroupContext); const isGroup = !!groupVariant && !!groupSize; return /* @__PURE__ */ jsxs( motion.button, { ...rest, type, disabled, ref, whileTap: { scale: disabled || disableAnimation ? 1 : 0.9 }, "data-variant": groupVariant || variant, className: twMerge( theme2.base, theme2.disabled, fullWidth && theme2.fullWidth, theme2.variants[groupVariant || variant], theme2.colors[color][groupVariant || variant], theme2.sizes[groupSize || size2], isGroup && theme2.group, isGroup && groupVariant === "text" && theme2.groupText, disableMargins && "m-0", disablePadding && "p-0", className ), children: [ startAdornment && /* @__PURE__ */ jsx( "div", { className: twMerge( theme2.adornment.base, theme2.adornment.start, theme2.adornment.sizes[size2] ), children: startAdornment } ), children, endAdornment && /* @__PURE__ */ jsx( "div", { className: twMerge( theme2.adornment.base, theme2.adornment.end, theme2.adornment.sizes[size2] ), children: endAdornment } ) ] } ); } ); const ButtonGroup = ({ children, className, variant, size: size2 }) => { const values = useMemo( () => ({ variant: variant || "filled", size: size2 || "medium" }), [size2, variant] ); return /* @__PURE__ */ jsx(ButtonGroupContext.Provider, { value: values, children: /* @__PURE__ */ jsx("div", { className, children }) }); }; const Chip = forwardRef( ({ children, color = "default", variant = "filled", size: size2 = "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__ */ jsxs( "div", { ...rest, ref, tabIndex: onClick ? 0 : -1, onClick: !disabled ? onClick : void 0, className: 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[size2], 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__ */ jsx( "div", { className: twMerge( theme2.adornment.base, theme2.adornment.start, theme2.adornment.sizes[size2] ), children: start } ), /* @__PURE__ */ jsx("div", { className: "flex items-center", children }), end && /* @__PURE__ */ jsx( "div", { className: twMerge( theme2.adornment.base, theme2.adornment.end, theme2.adornment.sizes[size2] ), 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 (!isValid(date)) { console.warn("Invalid date - setting to today", date); date = /* @__PURE__ */ new Date(); } const daysInMonth = getDaysInMonth(date); let day = startOfMonth(date); let offset = 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 = subDays(day, i); firstWeek.push({ date: offsetDay, dayOfMonth: getDate(offsetDay), isWeekendDay: getISODay(offsetDay) > 5, isPreviousMonth: true, isNextMonth: false, isToday: false, formattedDate: 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: getDate(day), isPreviousMonth: false, isToday: isSameDay(day, current), isNextMonth: !isSameMonth(day, date), isWeekendDay: getISODay(day) > 5, formattedDate: format(day, options.format) }); day = 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 = min(range); const endDate = max(range); return isWithinInterval(date, { start: startDate, end: endDate }); }; const isSelectionStarted = Array.isArray(current) && isValid(current[0]); const isSelectionComplete = isSelectionStarted && isValid(current[1]); if (!isRange && isValid(current)) { isActive = isSameDay(day, current); } else if (!isSelectionStarted) { isActive = isSameDay(day, hover); isRangeStart = isActive; isRangeEnd = isActive; } else if (isSelectionComplete) { const activeRange = [ startOfDay(current[0]), endOfDay(current[1]) ]; isActive = isInRange(day, activeRange); isRangeStart = isSameDay(day, current[0]); isRangeEnd = isSameDay(day, current[1]); } else { const activeRange = [ startOfDay(current[0]), endOfDay(hover ?? current[0]) ]; isActive = isInRange(day, activeRange); isRangeStart = isSameDay(day, min(activeRange)); isRangeEnd = isSameDay(day, max(activeRange)); } return { isActive, isRangeStart, isRangeEnd }; } function isNextWeekEmpty(day, range, hideNextMonth) { const nextWeek = addDays(day, 7); const nextWeekInRange = isBefore(nextWeek, max(range)) || isSameDay(nextWeek, max(range)); return !(nextWeekInRange && (isSameMonth(day, nextWeek) || !hideNextMonth)); } function isPreviousWeekEmpty(day, range, hidePrevMonth) { const prevWeek = addDays(day, -7); const prevWeekInRange = isAfter(prevWeek, min(range)) || isSameDay(prevWeek, min(range)); return !(prevWeekInRange && (isSameMonth(day, prevWeek) || !hidePrevMonth)); } function updateDateTime(currentDate, newDate, isRange = false, rangeStart = false) { let finalDate = newDate; if (currentDate) { const hasTime = getHours(newDate) !== 0 || getMinutes(newDate) !== 0 || getSeconds(newDate) !== 0; if (!hasTime) { if (!isRange) { const originalTimeSource = Array.isArray(currentDate) ? currentDate[0] ?? /* @__PURE__ */ new Date() : currentDate ?? /* @__PURE__ */ new Date(); finalDate = setSeconds( setMinutes( setHours(newDate, getHours(originalTimeSource)), getMinutes(originalTimeSource) ), getSeconds(originalTimeSource) ); } else { if (!rangeStart) { const originalTimeSource = Array.isArray(currentDate) ? currentDate[0] ?? /* @__PURE__ */ new Date() : currentDate ?? /* @__PURE__ */ new Date(); finalDate = setSeconds( setMinutes( setHours(newDate, getHours(originalTimeSource)), getMinutes(originalTimeSource) ), getSeconds(originalTimeSource) ); } else { finalDate = setSeconds(setMinutes(setHours(newDate, 0), 0), 0); } } } } return finalDate; } const isPresetActive = (presetValue, value, includeTime = false) => { if (!value) return false; if (Array.isArray(presetValue) && Array.isArray(value)) { if (includeTime) { const startMinutesDiff = Math.abs( differenceInMinutes(presetValue[0], value[0]) ); const endMinutesDiff = Math.abs( differenceInMinutes(presetValue[1], value[1]) ); return startMinutesDiff === 0 && endMinutesDiff === 0; } return isSameDay(presetValue[0], value[0]) && isSameDay(presetValue[1], value[1]); } if (!Array.isArray(presetValue) && !Array.isArray(value)) { if (includeTime) { return Math.abs(differenceInSeconds(presetValue, value)) === 0; } return isSameDay(presetValue, value); } return false; }; const CalendarDays = ({ value, current, hover = null, isRange, disabled, min: minLimit, max: max2, animated, xAnimation = 0, showDayOfWeek, showToday, showTime, dayOfWeekLabels = daysOfWeek, hidePrevMonthDays, hideNextMonthDays, onChange, onHover, theme: customTheme }) => { const { days } = useComponentTheme("calendar", customTheme); const [hoveringDate, setHoveringDate] = useState(hover); const weeks = useMemo(() => getWeeks(value), [value]); const maxLimit = useMemo(() => max2 === "now" ? /* @__PURE__ */ new Date() : max2, [max2]); const dayChangeHandler = useCallback( (dayDate) => { if (showTime && !isRange && current) { const currentDate = current; let newDate = new Date(dayDate); newDate.setHours(currentDate.getHours()); newDate.setMinutes(currentDate.getMinutes()); newDate.setSeconds(currentDate.getSeconds()); if (isAfter(newDate, maxLimit)) { newDate = maxLimit; } else if (isBefore(newDate, minLimit)) { newDate = minLimit; } onChange(newDate); } else { onChange(dayDate); } }, [showTime, isRange, current, maxLimit, minLimit, onChange] ); const renderDay = useCallback( (day) => { if (day.isPreviousMonth && hidePrevMonthDays || day.isNextMonth && hideNextMonthDays) { return /* @__PURE__ */ jsx("div", {}, day.dayOfMonth); } const handleHover = (value2) => { if (onHover) { onHover(value2); } else { setHoveringDate(value2); } }; const isDisabled = disabled || minLimit && isBefore(startOfDay(day.date), startOfDay(minLimit)) || maxLimit && isAfter(endOfDay(day.date), endOfDay(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__ */ jsx( Button, { className: cn(days.day, { [days.outside]: !isActive && (day.isNextMonth || day.isPreviousMonth), [days.today]: showToday && 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: () => dayChangeHandler(day.date), children: day.dayOfMonth }, day.formattedDate ); }, [ disabled, minLimit, maxLimit, current, hover, isRange, dayChangeHandler, onHover, hoveringDate, days, hideNextMonthDays, hidePrevMonthDays, showToday ] ); return /* @__PURE__ */ jsx(AnimatePresence, { mode: "popLayout", children: /* @__PURE__ */ jsxs( 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__ */ jsx("div", { className: days.header, children: dayOfWeekLabels.map((day) => /* @__PURE__ */ jsx("div", { className: days.dayOfWeek, children: day.substring(0, 2) }, `day-${day}`)) }), weeks.map((week, i) => /* @__PURE__ */ 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__ */ jsx("div", { className: months.root, children: monthNames.map((month, i) => /* @__PURE__ */ 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 = 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__ */ jsx(AnimatePresence, { mode: "popLayout", children: /* @__PURE__ */ jsx( 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__ */ 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 = forwardRef( ({ children, color = "default", variant = "default", disableMargins = false, className, theme: customTheme, ...rest }, ref) => { const theme2 = useComponentTheme("typography", customTheme); return /* @__PURE__ */ jsx( "h1", { ref, className: twMerge( theme2.colors[color], theme2.variant[variant], theme2.pageTitle, disableMargins && theme2.disableMargins, className ), ...rest, children } ); } ); const PrimaryHeading = forwardRef( ({ children, color = "default", variant = "default", disableMargins = false, className, theme: customTheme, ...rest }, ref) => { const theme2 = useComponentTheme( "typography", customTheme ); return /* @__PURE__ */ jsx( "h2", { ref, className: twMerge( theme2.colors[color], theme2.variant[variant], theme2.primaryHeading, disableMargins && theme2.disableMargins, className ), ...rest, children } ); } ); const SecondaryHeading = forwardRef( ({ children, color = "default", variant = "default", disableMargins = false, className, theme: customTheme, ...rest }, ref) => { const theme2 = useComponentTheme( "typography", customTheme ); return /* @__PURE__ */ jsx( "h3", { ref, className: twMerge( theme2.colors[color], theme2.variant[variant], theme2.secondaryHeading, disableMargins && theme2.disableMargins, className ), ...rest, children } ); } ); const SmallHeading = forwardRef( ({ children, color = "default", variant = "default", disableMargins = false, className, theme: customTheme, ...rest }, ref) => { const theme2 = useComponentTheme("typography", customTheme); return /* @__PURE__ */ jsx( "h5", { ref, className: twMerge( theme2.colors[color], theme2.variant[variant], theme2.smallHeading, disableMargins && theme2.disableMargins, className ), ...rest, children } ); } ); const Sub = forwardRef( ({ color = "default", variant = "default", disableMargins = false, children, className, theme: customTheme, ...rest }, ref) => { const theme2 = useComponentTheme("typography", customTheme); return /* @__PURE__ */ jsx( "h6", { ref, className: twMerge( theme2.colors[color], theme2.variant[variant], theme2.sub, disableMargins && theme2.disableMargins, className ), ...rest, children } ); } ); const Text = forwardRef( ({ color = "default", variant = "default", fontStyle = "default", children, className, theme: customTheme, ...rest }, ref) => { const theme2 = useComponentTheme("typography", customTheme); return /* @__PURE__ */ jsx( "span", { ref, className: 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__ */ jsx( "hr", { ...rest, className: 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$F.orientation.horizontal, "my-[var(--divider-spacing)]" ].join(" "), vertical: [ baseTheme$F.orientation.vertical, " mx-[var(--divider-spacing)]" ].join(" ") } }; const TimeColumn = ({ options, value, min: min2, max: max2, theme: theme2, isPM = false, is12HourCycle = false, onSelect }) => { var _a; const containerRef = useRef(null); const selectedRef = useRef(null); const isOptionDisabled = useCallback( (option) => { if (typeof option === "number") { if (options.length === 12 && is12HourCycle) { if (isPM) { const pmOption = option < 12 ? option + 12 : option; return pmOption < min2 || pmOption > max2; } else { return option < min2 || option > max2; } } return option < min2 || option > max2; } else { if (option === "AM" && min2 >= 12 || option === "PM" && max2 < 12) { return true; } return false; } }, [options.length, is12HourCycle, isPM, min2, max2] ); useEffect(() => { if (containerRef.current && selectedRef.current) { const container = containerRef.current; const selected = selectedRef.current; const containerHeight = container.clientHeight; const itemOffsetTop = selected.offsetTop; const itemHeight = selected.offsetHeight; let scrollTop = 0; if (is12HourCycle) { scrollTop = itemOffsetTop; } else { scrollTop = itemOffsetTop - containerHeight / 2 + itemHeight / 2; } container.scrollTo({ top: scrollTop, behavior: "smooth" }); } }, [value, is12HourCycle]); return /* @__PURE__ */ jsx("div", { className: theme2.items.container, children: /* @__PURE__ */ jsx( "ul", { ref: containerRef, className: theme2.items.list, style: { paddingBottom: is12HourCycle && containerRef.current ? ((_a = containerRef.current) == null ? void 0 : _a.clientHeight) - 24 : void 0 }, children: options.map((option) => /* @__PURE__ */ jsx( "li", { ref: value === option ? selectedRef : null, className: cn(theme2.items.item.base, {