@lax-wp/design-system 0.14.4 → 0.14.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/forms/date-range/DateRange.cjs.js +3 -3
- package/dist/components/forms/date-range/DateRange.cjs.js.map +1 -1
- package/dist/components/forms/date-range/DateRange.d.ts +6 -1
- package/dist/components/forms/date-range/DateRange.es.js +56 -53
- package/dist/components/forms/date-range/DateRange.es.js.map +1 -1
- package/dist/components/user-avatar/UserAvatar.cjs.js +1 -1
- package/dist/components/user-avatar/UserAvatar.cjs.js.map +1 -1
- package/dist/components/user-avatar/UserAvatar.es.js +11 -1
- package/dist/components/user-avatar/UserAvatar.es.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("react/jsx-runtime"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("react/jsx-runtime"),ne=require("antd"),Y=require("../../../_virtual/index.cjs.js"),r=require("react"),A=require("dayjs"),se=require("../../button/IconButton.cjs.js"),ae=require("../shared/InputLabel.cjs.js"),p=require("../../icon/icons.generated.cjs.js"),{RangePicker:W}=ne.DatePicker,J={ENTER:"Enter"},Q=()=>Math.random().toString(36).substring(2,9),oe=(i,s)=>{const k=r.useRef(s);r.useEffect(()=>{k.current=s},[s]),r.useEffect(()=>{const f=o=>k.current(o);return document.addEventListener(i,f),()=>{document.removeEventListener(i,f)}},[i])},X=({onCalendarChange:i=void 0,onChange:s,required:k,label:f,startDate:o,endDate:d,errorMessage:m,className:M,id:l,disabled:j=!1,dateFormat:v,shouldPopOnParent:B=!0,getPopupContainer:b,maxDateRange:u,open:C,onOpenChange:S,placement:L="bottomLeft",renderAsIconButton:N=!1,iconButtonClassName:Z,iconClassName:G,labelExtra:T,inputEmphasis:F="default",presets:P})=>{const q=F==="modified"&&!m,y=F==="deleted"&&!m,R=F==="success"&&!m,z=q?"var(--Warning-50, #FFFAEB)":y?"var(--Error-50, #FEF2F2)":R?"var(--Success-50, #F0FDF4)":"",E=q?"var(--Warning-200, #FEDF89)":y?"var(--Error-200, #FECACA)":R?"var(--Success-200, #BBF7D0)":"",[D,x]=r.useState(!1),[$,K]=r.useState(!1),h=r.useRef(null),_=r.useRef(null),I=r.useRef(!1),g=r.useRef(!1),a=e=>e?A(e):null,w=`date-range-start-${Q()}`,O=`date-range-end-${Q()}`,ee=()=>{x(!0),setTimeout(()=>{h.current&&h.current.focus()},0)};oe("keydown",e=>{if(e.key===J.ENTER&&document.activeElement instanceof HTMLInputElement){if(document?.activeElement?.id===w){const n=A(document?.activeElement?.value);n.isValid()&&s([n,a(d)])}if(document?.activeElement?.id===O){const n=A(document?.activeElement?.value);n.isValid()&&s([a(o),n])}}});const H=r.useCallback(e=>{const[n,c]=[a(o),a(d)];return u?n?e.isBefore(n.startOf("day"))||e.isAfter(n.add(u,"day").endOf("day")):c?e.isBefore(c.subtract(u,"day").startOf("day"))||e.isAfter(c.endOf("day")):!1:!1},[o,d,u]),U=r.useCallback(e=>{if(e.key===J.ENTER&&!(N?D:C??$)){e.preventDefault(),e.stopPropagation();const c=e.target.closest("form");if(c){const V=c.querySelector('button[type="submit"]');V?V.click():c.requestSubmit()}}},[N,D,C,$]),te=r.useCallback(e=>{if(e&&I.current){I.current=!1,x(!1);return}x(e),e||(I.current=!0,requestAnimationFrame(()=>{h.current?.focus(),requestAnimationFrame(()=>{I.current=!1})}))},[]),re=r.useCallback(e=>{if(e&&g.current){g.current=!1,K(!1),S?.(!1);return}K(e),S?.(e),e||(g.current=!0,requestAnimationFrame(()=>{_.current?.focus(),requestAnimationFrame(()=>{g.current=!1})}))},[S]);return N?t.jsxs("div",{id:l,className:M,onKeyDownCapture:U,children:[t.jsx(se,{onClick:ee,disabled:j,variant:"default",className:Z,children:t.jsx(p.CalendarMonthIcon,{size:20,className:Y("w-5 h-5",G)})}),t.jsx(W,{ref:h,onChange:e=>{s(e),x(!1)},onCalendarChange:i,value:[a(o),a(d)],id:{start:w,end:O},allowClear:!0,format:v||"DD MMM, YYYY",separator:t.jsx(p.CheckIndeterminateSmallFilledIcon,{size:20,className:"text-neutral-400 dark:text-gray-100"}),suffixIcon:t.jsx(p.CalendarMonthIcon,{size:14,className:"text-neutral-400 dark:text-gray-100"}),getPopupContainer:b||(B?e=>e.parentElement:()=>document.body),disabled:j,disabledDate:u?H:void 0,autoComplete:"off",open:D,onOpenChange:te,placement:L,presets:P,style:{position:"absolute",opacity:0,pointerEvents:"none",width:0,height:0}})]}):t.jsxs("div",{id:l,className:Y("flex flex-col",M),onKeyDownCapture:U,children:[(f||T)&&t.jsxs("div",{className:"mb-1 flex items-center justify-between gap-1",children:[t.jsx(ae.InputLabel,{label:f||"",required:k||!1}),T]}),(z||E)&&t.jsx("style",{children:`
|
|
2
2
|
#${l} .ant-picker {
|
|
3
|
-
background-color: ${
|
|
3
|
+
background-color: ${z} !important;
|
|
4
4
|
border-color: ${E} !important;
|
|
5
5
|
}
|
|
6
6
|
#${l} .ant-picker:hover {
|
|
@@ -13,5 +13,5 @@
|
|
|
13
13
|
#${l} .ant-picker .ant-picker-input > input {
|
|
14
14
|
color: ${y?"#475467":R?"#101828":"inherit"};
|
|
15
15
|
}
|
|
16
|
-
`}),t.jsx(
|
|
16
|
+
`}),t.jsx(W,{ref:_,onChange:s,onCalendarChange:i,value:[a(o),a(d)],id:{start:w,end:O},allowClear:!0,format:v||"DD MMM, YYYY",separator:t.jsx(p.CheckIndeterminateSmallFilledIcon,{size:20,className:"text-neutral-400 dark:text-gray-100"}),suffixIcon:t.jsx(p.CalendarMonthIcon,{size:14,className:"text-neutral-400 dark:text-gray-100"}),getPopupContainer:b||(B?e=>e.parentElement:()=>document.body),disabled:j,disabledDate:u?H:void 0,open:C??$,onOpenChange:re,autoComplete:"off",placement:L,presets:P}),m&&t.jsx("p",{className:Y("text-sm font-inter font-normal text-left pt-[6px]","text-red-500"),children:m})]})};X.displayName="DateRange";exports.DateRange=X;
|
|
17
17
|
//# sourceMappingURL=DateRange.cjs.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DateRange.cjs.js","sources":["../../../../src/components/forms/date-range/DateRange.tsx"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { DatePicker } from \"antd\";\nimport cn from \"classnames\";\nimport React from \"react\";\nimport dayjs from \"dayjs\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport IconButton from \"../../button/IconButton\";\nimport { InputLabel } from \"../shared/InputLabel\";\nimport { CalendarMonthIcon, CheckIndeterminateSmallFilledIcon } from '../../icon';\n\nconst { RangePicker } = DatePicker;\n\n// Keyboard keys constant\nconst KEYBOARD_KEYS = {\n ENTER: \"Enter\",\n} as const;\n\n/**\n * Generate a short UUID\n */\nconst generateShortUUID = (): string => {\n return Math.random().toString(36).substring(2, 9);\n};\n\n/**\n * Hook to add event listeners\n */\nconst useEventListener = <K extends keyof DocumentEventMap>(\n eventName: K,\n handler: (event: DocumentEventMap[K]) => void\n) => {\n const savedHandler = useRef(handler);\n\n useEffect(() => {\n savedHandler.current = handler;\n }, [handler]);\n\n useEffect(() => {\n const eventListener = (event: DocumentEventMap[K]) =>\n savedHandler.current(event);\n document.addEventListener(eventName, eventListener);\n return () => {\n document.removeEventListener(eventName, eventListener);\n };\n }, [eventName]);\n};\n\n/**\n * Props for the DateRange component\n * Matches the lax-web-portal implementation for drop-in replacement\n */\nexport type TDateRangeProps = {\n /** Unique identifier for the date range */\n id: string;\n /** Label text to display above the date range */\n label?: string;\n /** Start date value (ISO string or formatted date string) */\n startDate: string;\n /** End date value (ISO string or formatted date string) */\n endDate: string;\n /** Callback function called when date range changes */\n onChange(data: any): void;\n /** Callback function called when calendar selection changes */\n onCalendarChange?(data: any): void;\n /** Whether the field is required */\n required?: boolean;\n /** Error message to display below the date range */\n errorMessage?: string;\n /** Additional CSS classes for the wrapper */\n className?: string;\n /** Whether the date range is disabled */\n disabled?: boolean;\n /** Custom date format */\n dateFormat?: string;\n /** Whether popup should render inside parent element */\n shouldPopOnParent?: boolean;\n /** Custom function to get popup container */\n getPopupContainer?: (trigger: HTMLElement | null) => HTMLElement;\n /** Maximum date range in days */\n maxDateRange?: number;\n /** Whether the picker is open */\n open?: boolean;\n /** Callback function called when open state changes */\n onOpenChange?(open: boolean): void;\n /** Placement of the dropdown */\n placement?: \"bottomLeft\" | \"bottomRight\" | \"topLeft\" | \"topRight\";\n /** Whether to render as an icon button that triggers the date picker */\n renderAsIconButton?: boolean;\n /** Additional CSS classes for the icon button */\n iconButtonClassName?: string;\n /** Additional CSS classes for the calendar icon inside the button */\n iconClassName?: string;\n /** Optional extra content in the label row (e.g. actions, badges) */\n labelExtra?: React.ReactNode;\n /** Input surface style: `'modified'` — Warning colors; `'deleted'` — Error colors; `'success'` — Success colors. */\n inputEmphasis?: \"default\" | \"modified\" | \"deleted\" | \"success\";\n};\n\n/**\n * A date range picker component with label, validation, and styling support.\n * Features proper date handling, validation, and comprehensive prop support.\n * Built on top of Ant Design's RangePicker for advanced functionality.\n *\n * This component is designed as a drop-in replacement for the lax-web-portal\n * DateRange component.\n *\n * @example\n * ```tsx\n * <DateRange\n * id=\"event-dates\"\n * label=\"Event Duration\"\n * startDate={startDate}\n * endDate={endDate}\n * onChange={(dates) => {\n * setStartDate(dates[0]);\n * setEndDate(dates[1]);\n * }}\n * required\n * />\n * ```\n */\nexport const DateRange = ({\n onCalendarChange = undefined,\n onChange,\n required,\n label,\n startDate,\n endDate,\n errorMessage,\n className,\n id,\n disabled = false,\n dateFormat,\n shouldPopOnParent = true,\n getPopupContainer: customGetPopupContainer,\n maxDateRange,\n open,\n onOpenChange,\n placement = \"bottomLeft\",\n renderAsIconButton = false,\n iconButtonClassName,\n iconClassName,\n labelExtra,\n inputEmphasis = \"default\",\n}: TDateRangeProps) => {\n const emphasisModifiedSkin = inputEmphasis === \"modified\" && !errorMessage;\n const emphasisDeletedSkin = inputEmphasis === \"deleted\" && !errorMessage;\n const emphasisSuccessSkin = inputEmphasis === \"success\" && !errorMessage;\n const emphasisBg =\n emphasisModifiedSkin ? \"var(--Warning-50, #FFFAEB)\" :\n emphasisDeletedSkin ? \"var(--Error-50, #FEF2F2)\" :\n emphasisSuccessSkin ? \"var(--Success-50, #F0FDF4)\" : \"\";\n const emphasisBorder =\n emphasisModifiedSkin ? \"var(--Warning-200, #FEDF89)\" :\n emphasisDeletedSkin ? \"var(--Error-200, #FECACA)\" :\n emphasisSuccessSkin ? \"var(--Success-200, #BBF7D0)\" : \"\";\n const [isOpen, setIsOpen] = useState(false);\n const [isNormalPickerOpen, setIsNormalPickerOpen] = useState(false);\n const pickerRef = useRef<any>(null);\n const normalPickerRef = useRef<any>(null);\n const suppressNextIconOpenRef = useRef(false);\n const suppressNextNormalOpenRef = useRef(false);\n\n const parseDate = (str: string | number | Date | dayjs.Dayjs) => {\n if (!str) return null;\n return dayjs(str);\n };\n\n const START_ID = `date-range-start-${generateShortUUID()}`;\n const END_ID = `date-range-end-${generateShortUUID()}`;\n\n const handleIconClick = () => {\n setIsOpen(true);\n setTimeout(() => {\n if (pickerRef.current) {\n pickerRef.current.focus();\n }\n }, 0);\n };\n\n useEventListener(\"keydown\", (e: KeyboardEvent) => {\n if (\n e.key === KEYBOARD_KEYS.ENTER &&\n document.activeElement instanceof HTMLInputElement\n ) {\n if (document?.activeElement?.id === START_ID) {\n const date = dayjs(document?.activeElement?.value);\n if (date.isValid()) {\n onChange([date, parseDate(endDate)]);\n }\n }\n if (document?.activeElement?.id === END_ID) {\n const date = dayjs(document?.activeElement?.value);\n if (date.isValid()) {\n onChange([parseDate(startDate), date]);\n }\n }\n }\n });\n\n const disabledDate = useCallback(\n (current: dayjs.Dayjs) => {\n const [start, end] = [parseDate(startDate), parseDate(endDate)];\n\n if (!maxDateRange) return false;\n\n if (start) {\n return (\n current.isBefore(start.startOf(\"day\")) ||\n current.isAfter(start.add(maxDateRange, \"day\").endOf(\"day\"))\n );\n }\n\n if (end) {\n return (\n current.isBefore(end.subtract(maxDateRange, \"day\").startOf(\"day\")) ||\n current.isAfter(end.endOf(\"day\"))\n );\n }\n\n return false;\n },\n [startDate, endDate, maxDateRange]\n );\n\n const handleKeyDownCapture = useCallback((e: React.KeyboardEvent) => {\n if (e.key === KEYBOARD_KEYS.ENTER) {\n const pickerIsOpen = renderAsIconButton ? isOpen : (open ?? isNormalPickerOpen);\n if (!pickerIsOpen) {\n e.preventDefault();\n e.stopPropagation();\n\n const form = (e.target as HTMLElement).closest('form');\n if (form) {\n const submitBtn = form.querySelector<HTMLButtonElement>('button[type=\"submit\"]');\n if (submitBtn) {\n submitBtn.click();\n } else {\n form.requestSubmit();\n }\n }\n }\n }\n }, [renderAsIconButton, isOpen, open, isNormalPickerOpen]);\n\n const handleIconPickerOpenChange = useCallback((nextOpen: boolean) => {\n if (nextOpen && suppressNextIconOpenRef.current) {\n suppressNextIconOpenRef.current = false;\n setIsOpen(false);\n return;\n }\n\n setIsOpen(nextOpen);\n if (!nextOpen) {\n suppressNextIconOpenRef.current = true;\n requestAnimationFrame(() => {\n pickerRef.current?.focus();\n requestAnimationFrame(() => {\n suppressNextIconOpenRef.current = false;\n });\n });\n }\n }, []);\n\n const handleNormalOpenChange = useCallback((nextOpen: boolean) => {\n if (nextOpen && suppressNextNormalOpenRef.current) {\n suppressNextNormalOpenRef.current = false;\n setIsNormalPickerOpen(false);\n onOpenChange?.(false);\n return;\n }\n\n setIsNormalPickerOpen(nextOpen);\n onOpenChange?.(nextOpen);\n if (!nextOpen) {\n suppressNextNormalOpenRef.current = true;\n requestAnimationFrame(() => {\n normalPickerRef.current?.focus();\n requestAnimationFrame(() => {\n suppressNextNormalOpenRef.current = false;\n });\n });\n }\n }, [onOpenChange]);\n\n if (renderAsIconButton) {\n return (\n <div id={id} className={className} onKeyDownCapture={handleKeyDownCapture}>\n <IconButton\n onClick={handleIconClick}\n disabled={disabled}\n variant=\"default\"\n className={iconButtonClassName}\n >\n <CalendarMonthIcon size={20} className={cn(\"w-5 h-5\", iconClassName)} />\n </IconButton>\n <RangePicker\n ref={pickerRef}\n onChange={(dates) => {\n onChange(dates);\n setIsOpen(false);\n }}\n onCalendarChange={onCalendarChange}\n value={[parseDate(startDate), parseDate(endDate)]}\n id={{ start: START_ID, end: END_ID }}\n allowClear\n format={dateFormat ? dateFormat : \"DD MMM, YYYY\"}\n separator={<CheckIndeterminateSmallFilledIcon size={20} className=\"text-neutral-400 dark:text-gray-100\" />}\n suffixIcon={<CalendarMonthIcon size={14} className=\"text-neutral-400 dark:text-gray-100\" />}\n getPopupContainer={\n customGetPopupContainer\n ? customGetPopupContainer\n : shouldPopOnParent\n ? (trigger) => trigger.parentElement as HTMLElement\n : () => document.body\n }\n disabled={disabled}\n disabledDate={maxDateRange ? disabledDate : undefined}\n autoComplete=\"off\"\n open={isOpen}\n onOpenChange={handleIconPickerOpenChange}\n placement={placement}\n style={{ position: \"absolute\", opacity: 0, pointerEvents: \"none\", width: 0, height: 0 }}\n />\n </div>\n );\n }\n\n return (\n <div id={id} className={cn(\"flex flex-col\", className)} onKeyDownCapture={handleKeyDownCapture}>\n {(label || labelExtra) && (\n <div className=\"mb-1 flex items-center justify-between gap-1\">\n <InputLabel label={label || \"\"} required={required || false} />\n {labelExtra}\n </div>\n )}\n {(emphasisBg || emphasisBorder) && (\n <style>{`\n #${id} .ant-picker {\n background-color: ${emphasisBg} !important;\n border-color: ${emphasisBorder} !important;\n }\n #${id} .ant-picker:hover {\n border-color: ${emphasisBorder} !important;\n }\n #${id} .ant-picker.ant-picker-focused {\n border-color: ${emphasisBorder} !important;\n box-shadow: 0 0 0 2px ${emphasisDeletedSkin ? \"rgba(254,202,202,0.45)\" : emphasisModifiedSkin ? \"rgba(254,223,137,0.45)\" : \"rgba(187,247,208,0.45)\"} !important;\n }\n #${id} .ant-picker .ant-picker-input > input {\n color: ${emphasisDeletedSkin ? \"#475467\" : emphasisSuccessSkin ? \"#101828\" : \"inherit\"};\n }\n `}</style>\n )}\n <RangePicker\n ref={normalPickerRef}\n onChange={onChange}\n onCalendarChange={onCalendarChange}\n value={[parseDate(startDate), parseDate(endDate)]}\n id={{ start: START_ID, end: END_ID }}\n allowClear\n format={dateFormat ? dateFormat : \"DD MMM, YYYY\"}\n separator={\n <CheckIndeterminateSmallFilledIcon size={20} className='text-neutral-400 dark:text-gray-100' />\n }\n suffixIcon={\n <CalendarMonthIcon size={14} className='text-neutral-400 dark:text-gray-100' />\n }\n getPopupContainer={\n customGetPopupContainer\n ? customGetPopupContainer\n : shouldPopOnParent\n ? (trigger) => trigger.parentElement as HTMLElement\n : () => document.body\n }\n disabled={disabled}\n disabledDate={maxDateRange ? disabledDate : undefined}\n open={open ?? isNormalPickerOpen}\n onOpenChange={handleNormalOpenChange}\n autoComplete=\"off\"\n placement={placement}\n />\n {errorMessage && (\n <p\n className={cn(\n \"text-sm font-inter font-normal text-left pt-[6px]\",\n \"text-red-500\"\n )}\n >\n {errorMessage}\n </p>\n )}\n </div>\n );\n};\n\nDateRange.displayName = \"DateRange\";\n\n"],"names":["RangePicker","DatePicker","KEYBOARD_KEYS","generateShortUUID","useEventListener","eventName","handler","savedHandler","useRef","useEffect","eventListener","event","DateRange","onCalendarChange","onChange","required","label","startDate","endDate","errorMessage","className","id","disabled","dateFormat","shouldPopOnParent","customGetPopupContainer","maxDateRange","open","onOpenChange","placement","renderAsIconButton","iconButtonClassName","iconClassName","labelExtra","inputEmphasis","emphasisModifiedSkin","emphasisDeletedSkin","emphasisSuccessSkin","emphasisBg","emphasisBorder","isOpen","setIsOpen","useState","isNormalPickerOpen","setIsNormalPickerOpen","pickerRef","normalPickerRef","suppressNextIconOpenRef","suppressNextNormalOpenRef","parseDate","str","dayjs","START_ID","END_ID","handleIconClick","date","disabledDate","useCallback","current","start","end","handleKeyDownCapture","form","submitBtn","handleIconPickerOpenChange","nextOpen","handleNormalOpenChange","jsxs","jsx","IconButton","CalendarMonthIcon","cn","dates","CheckIndeterminateSmallFilledIcon","trigger","InputLabel"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DateRange.cjs.js","sources":["../../../../src/components/forms/date-range/DateRange.tsx"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { DatePicker } from \"antd\";\nimport cn from \"classnames\";\nimport React from \"react\";\nimport dayjs from \"dayjs\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport IconButton from \"../../button/IconButton\";\nimport { InputLabel } from \"../shared/InputLabel\";\nimport { CalendarMonthIcon, CheckIndeterminateSmallFilledIcon } from '../../icon';\n\nconst { RangePicker } = DatePicker;\n\n// Keyboard keys constant\nconst KEYBOARD_KEYS = {\n ENTER: \"Enter\",\n} as const;\n\n/**\n * Generate a short UUID\n */\nconst generateShortUUID = (): string => {\n return Math.random().toString(36).substring(2, 9);\n};\n\n/**\n * Hook to add event listeners\n */\nconst useEventListener = <K extends keyof DocumentEventMap>(\n eventName: K,\n handler: (event: DocumentEventMap[K]) => void\n) => {\n const savedHandler = useRef(handler);\n\n useEffect(() => {\n savedHandler.current = handler;\n }, [handler]);\n\n useEffect(() => {\n const eventListener = (event: DocumentEventMap[K]) =>\n savedHandler.current(event);\n document.addEventListener(eventName, eventListener);\n return () => {\n document.removeEventListener(eventName, eventListener);\n };\n }, [eventName]);\n};\n\n/**\n * Props for the DateRange component\n * Matches the lax-web-portal implementation for drop-in replacement\n */\nexport type TDateRangeProps = {\n /** Unique identifier for the date range */\n id: string;\n /** Label text to display above the date range */\n label?: string;\n /** Start date value (ISO string or formatted date string) */\n startDate: string;\n /** End date value (ISO string or formatted date string) */\n endDate: string;\n /** Callback function called when date range changes */\n onChange(data: any): void;\n /** Callback function called when calendar selection changes */\n onCalendarChange?(data: any): void;\n /** Whether the field is required */\n required?: boolean;\n /** Error message to display below the date range */\n errorMessage?: string;\n /** Additional CSS classes for the wrapper */\n className?: string;\n /** Whether the date range is disabled */\n disabled?: boolean;\n /** Custom date format */\n dateFormat?: string;\n /** Whether popup should render inside parent element */\n shouldPopOnParent?: boolean;\n /** Custom function to get popup container */\n getPopupContainer?: (trigger: HTMLElement | null) => HTMLElement;\n /** Maximum date range in days */\n maxDateRange?: number;\n /** Whether the picker is open */\n open?: boolean;\n /** Callback function called when open state changes */\n onOpenChange?(open: boolean): void;\n /** Placement of the dropdown */\n placement?: \"bottomLeft\" | \"bottomRight\" | \"topLeft\" | \"topRight\";\n /** Preset date ranges shown in the picker dropdown */\n presets?: { label: React.ReactNode; value: any }[];\n /** Whether to render as an icon button that triggers the date picker */\n renderAsIconButton?: boolean;\n /** Additional CSS classes for the icon button */\n iconButtonClassName?: string;\n /** Additional CSS classes for the calendar icon inside the button */\n iconClassName?: string;\n /** Optional extra content in the label row (e.g. actions, badges) */\n labelExtra?: React.ReactNode;\n /** Input surface style: `'modified'` — Warning colors; `'deleted'` — Error colors; `'success'` — Success colors. */\n inputEmphasis?: \"default\" | \"modified\" | \"deleted\" | \"success\";\n};\n\n/**\n * A date range picker component with label, validation, and styling support.\n * Features proper date handling, validation, and comprehensive prop support.\n * Built on top of Ant Design's RangePicker for advanced functionality.\n *\n * This component is designed as a drop-in replacement for the lax-web-portal\n * DateRange component.\n *\n * @example\n * ```tsx\n * <DateRange\n * id=\"event-dates\"\n * label=\"Event Duration\"\n * startDate={startDate}\n * endDate={endDate}\n * onChange={(dates) => {\n * setStartDate(dates[0]);\n * setEndDate(dates[1]);\n * }}\n * required\n * />\n * ```\n */\nexport const DateRange = ({\n onCalendarChange = undefined,\n onChange,\n required,\n label,\n startDate,\n endDate,\n errorMessage,\n className,\n id,\n disabled = false,\n dateFormat,\n shouldPopOnParent = true,\n getPopupContainer: customGetPopupContainer,\n maxDateRange,\n open,\n onOpenChange,\n placement = \"bottomLeft\",\n renderAsIconButton = false,\n iconButtonClassName,\n iconClassName,\n labelExtra,\n inputEmphasis = \"default\",\n presets,\n}: TDateRangeProps) => {\n const emphasisModifiedSkin = inputEmphasis === \"modified\" && !errorMessage;\n const emphasisDeletedSkin = inputEmphasis === \"deleted\" && !errorMessage;\n const emphasisSuccessSkin = inputEmphasis === \"success\" && !errorMessage;\n const emphasisBg =\n emphasisModifiedSkin ? \"var(--Warning-50, #FFFAEB)\" :\n emphasisDeletedSkin ? \"var(--Error-50, #FEF2F2)\" :\n emphasisSuccessSkin ? \"var(--Success-50, #F0FDF4)\" : \"\";\n const emphasisBorder =\n emphasisModifiedSkin ? \"var(--Warning-200, #FEDF89)\" :\n emphasisDeletedSkin ? \"var(--Error-200, #FECACA)\" :\n emphasisSuccessSkin ? \"var(--Success-200, #BBF7D0)\" : \"\";\n const [isOpen, setIsOpen] = useState(false);\n const [isNormalPickerOpen, setIsNormalPickerOpen] = useState(false);\n const pickerRef = useRef<any>(null);\n const normalPickerRef = useRef<any>(null);\n const suppressNextIconOpenRef = useRef(false);\n const suppressNextNormalOpenRef = useRef(false);\n\n const parseDate = (str: string | number | Date | dayjs.Dayjs) => {\n if (!str) return null;\n return dayjs(str);\n };\n\n const START_ID = `date-range-start-${generateShortUUID()}`;\n const END_ID = `date-range-end-${generateShortUUID()}`;\n\n const handleIconClick = () => {\n setIsOpen(true);\n setTimeout(() => {\n if (pickerRef.current) {\n pickerRef.current.focus();\n }\n }, 0);\n };\n\n useEventListener(\"keydown\", (e: KeyboardEvent) => {\n if (\n e.key === KEYBOARD_KEYS.ENTER &&\n document.activeElement instanceof HTMLInputElement\n ) {\n if (document?.activeElement?.id === START_ID) {\n const date = dayjs(document?.activeElement?.value);\n if (date.isValid()) {\n onChange([date, parseDate(endDate)]);\n }\n }\n if (document?.activeElement?.id === END_ID) {\n const date = dayjs(document?.activeElement?.value);\n if (date.isValid()) {\n onChange([parseDate(startDate), date]);\n }\n }\n }\n });\n\n const disabledDate = useCallback(\n (current: dayjs.Dayjs) => {\n const [start, end] = [parseDate(startDate), parseDate(endDate)];\n\n if (!maxDateRange) return false;\n\n if (start) {\n return (\n current.isBefore(start.startOf(\"day\")) ||\n current.isAfter(start.add(maxDateRange, \"day\").endOf(\"day\"))\n );\n }\n\n if (end) {\n return (\n current.isBefore(end.subtract(maxDateRange, \"day\").startOf(\"day\")) ||\n current.isAfter(end.endOf(\"day\"))\n );\n }\n\n return false;\n },\n [startDate, endDate, maxDateRange]\n );\n\n const handleKeyDownCapture = useCallback((e: React.KeyboardEvent) => {\n if (e.key === KEYBOARD_KEYS.ENTER) {\n const pickerIsOpen = renderAsIconButton ? isOpen : (open ?? isNormalPickerOpen);\n if (!pickerIsOpen) {\n e.preventDefault();\n e.stopPropagation();\n\n const form = (e.target as HTMLElement).closest('form');\n if (form) {\n const submitBtn = form.querySelector<HTMLButtonElement>('button[type=\"submit\"]');\n if (submitBtn) {\n submitBtn.click();\n } else {\n form.requestSubmit();\n }\n }\n }\n }\n }, [renderAsIconButton, isOpen, open, isNormalPickerOpen]);\n\n const handleIconPickerOpenChange = useCallback((nextOpen: boolean) => {\n if (nextOpen && suppressNextIconOpenRef.current) {\n suppressNextIconOpenRef.current = false;\n setIsOpen(false);\n return;\n }\n\n setIsOpen(nextOpen);\n if (!nextOpen) {\n suppressNextIconOpenRef.current = true;\n requestAnimationFrame(() => {\n pickerRef.current?.focus();\n requestAnimationFrame(() => {\n suppressNextIconOpenRef.current = false;\n });\n });\n }\n }, []);\n\n const handleNormalOpenChange = useCallback((nextOpen: boolean) => {\n if (nextOpen && suppressNextNormalOpenRef.current) {\n suppressNextNormalOpenRef.current = false;\n setIsNormalPickerOpen(false);\n onOpenChange?.(false);\n return;\n }\n\n setIsNormalPickerOpen(nextOpen);\n onOpenChange?.(nextOpen);\n if (!nextOpen) {\n suppressNextNormalOpenRef.current = true;\n requestAnimationFrame(() => {\n normalPickerRef.current?.focus();\n requestAnimationFrame(() => {\n suppressNextNormalOpenRef.current = false;\n });\n });\n }\n }, [onOpenChange]);\n\n if (renderAsIconButton) {\n return (\n <div id={id} className={className} onKeyDownCapture={handleKeyDownCapture}>\n <IconButton\n onClick={handleIconClick}\n disabled={disabled}\n variant=\"default\"\n className={iconButtonClassName}\n >\n <CalendarMonthIcon size={20} className={cn(\"w-5 h-5\", iconClassName)} />\n </IconButton>\n <RangePicker\n ref={pickerRef}\n onChange={(dates) => {\n onChange(dates);\n setIsOpen(false);\n }}\n onCalendarChange={onCalendarChange}\n value={[parseDate(startDate), parseDate(endDate)]}\n id={{ start: START_ID, end: END_ID }}\n allowClear\n format={dateFormat ? dateFormat : \"DD MMM, YYYY\"}\n separator={<CheckIndeterminateSmallFilledIcon size={20} className=\"text-neutral-400 dark:text-gray-100\" />}\n suffixIcon={<CalendarMonthIcon size={14} className=\"text-neutral-400 dark:text-gray-100\" />}\n getPopupContainer={\n customGetPopupContainer\n ? customGetPopupContainer\n : shouldPopOnParent\n ? (trigger) => trigger.parentElement as HTMLElement\n : () => document.body\n }\n disabled={disabled}\n disabledDate={maxDateRange ? disabledDate : undefined}\n autoComplete=\"off\"\n open={isOpen}\n onOpenChange={handleIconPickerOpenChange}\n placement={placement}\n presets={presets}\n style={{ position: \"absolute\", opacity: 0, pointerEvents: \"none\", width: 0, height: 0 }}\n />\n </div>\n );\n }\n\n return (\n <div id={id} className={cn(\"flex flex-col\", className)} onKeyDownCapture={handleKeyDownCapture}>\n {(label || labelExtra) && (\n <div className=\"mb-1 flex items-center justify-between gap-1\">\n <InputLabel label={label || \"\"} required={required || false} />\n {labelExtra}\n </div>\n )}\n {(emphasisBg || emphasisBorder) && (\n <style>{`\n #${id} .ant-picker {\n background-color: ${emphasisBg} !important;\n border-color: ${emphasisBorder} !important;\n }\n #${id} .ant-picker:hover {\n border-color: ${emphasisBorder} !important;\n }\n #${id} .ant-picker.ant-picker-focused {\n border-color: ${emphasisBorder} !important;\n box-shadow: 0 0 0 2px ${emphasisDeletedSkin ? \"rgba(254,202,202,0.45)\" : emphasisModifiedSkin ? \"rgba(254,223,137,0.45)\" : \"rgba(187,247,208,0.45)\"} !important;\n }\n #${id} .ant-picker .ant-picker-input > input {\n color: ${emphasisDeletedSkin ? \"#475467\" : emphasisSuccessSkin ? \"#101828\" : \"inherit\"};\n }\n `}</style>\n )}\n <RangePicker\n ref={normalPickerRef}\n onChange={onChange}\n onCalendarChange={onCalendarChange}\n value={[parseDate(startDate), parseDate(endDate)]}\n id={{ start: START_ID, end: END_ID }}\n allowClear\n format={dateFormat ? dateFormat : \"DD MMM, YYYY\"}\n separator={\n <CheckIndeterminateSmallFilledIcon size={20} className='text-neutral-400 dark:text-gray-100' />\n }\n suffixIcon={\n <CalendarMonthIcon size={14} className='text-neutral-400 dark:text-gray-100' />\n }\n getPopupContainer={\n customGetPopupContainer\n ? customGetPopupContainer\n : shouldPopOnParent\n ? (trigger) => trigger.parentElement as HTMLElement\n : () => document.body\n }\n disabled={disabled}\n disabledDate={maxDateRange ? disabledDate : undefined}\n open={open ?? isNormalPickerOpen}\n onOpenChange={handleNormalOpenChange}\n autoComplete=\"off\"\n placement={placement}\n presets={presets}\n />\n {errorMessage && (\n <p\n className={cn(\n \"text-sm font-inter font-normal text-left pt-[6px]\",\n \"text-red-500\"\n )}\n >\n {errorMessage}\n </p>\n )}\n </div>\n );\n};\n\nDateRange.displayName = \"DateRange\";\n\n"],"names":["RangePicker","DatePicker","KEYBOARD_KEYS","generateShortUUID","useEventListener","eventName","handler","savedHandler","useRef","useEffect","eventListener","event","DateRange","onCalendarChange","onChange","required","label","startDate","endDate","errorMessage","className","id","disabled","dateFormat","shouldPopOnParent","customGetPopupContainer","maxDateRange","open","onOpenChange","placement","renderAsIconButton","iconButtonClassName","iconClassName","labelExtra","inputEmphasis","presets","emphasisModifiedSkin","emphasisDeletedSkin","emphasisSuccessSkin","emphasisBg","emphasisBorder","isOpen","setIsOpen","useState","isNormalPickerOpen","setIsNormalPickerOpen","pickerRef","normalPickerRef","suppressNextIconOpenRef","suppressNextNormalOpenRef","parseDate","str","dayjs","START_ID","END_ID","handleIconClick","date","disabledDate","useCallback","current","start","end","handleKeyDownCapture","form","submitBtn","handleIconPickerOpenChange","nextOpen","handleNormalOpenChange","jsxs","jsx","IconButton","CalendarMonthIcon","cn","dates","CheckIndeterminateSmallFilledIcon","trigger","InputLabel"],"mappings":"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"}
|
|
@@ -38,6 +38,11 @@ export type TDateRangeProps = {
|
|
|
38
38
|
onOpenChange?(open: boolean): void;
|
|
39
39
|
/** Placement of the dropdown */
|
|
40
40
|
placement?: "bottomLeft" | "bottomRight" | "topLeft" | "topRight";
|
|
41
|
+
/** Preset date ranges shown in the picker dropdown */
|
|
42
|
+
presets?: {
|
|
43
|
+
label: React.ReactNode;
|
|
44
|
+
value: any;
|
|
45
|
+
}[];
|
|
41
46
|
/** Whether to render as an icon button that triggers the date picker */
|
|
42
47
|
renderAsIconButton?: boolean;
|
|
43
48
|
/** Additional CSS classes for the icon button */
|
|
@@ -73,6 +78,6 @@ export type TDateRangeProps = {
|
|
|
73
78
|
* ```
|
|
74
79
|
*/
|
|
75
80
|
export declare const DateRange: {
|
|
76
|
-
({ onCalendarChange, onChange, required, label, startDate, endDate, errorMessage, className, id, disabled, dateFormat, shouldPopOnParent, getPopupContainer: customGetPopupContainer, maxDateRange, open, onOpenChange, placement, renderAsIconButton, iconButtonClassName, iconClassName, labelExtra, inputEmphasis, }: TDateRangeProps): import("react/jsx-runtime").JSX.Element;
|
|
81
|
+
({ onCalendarChange, onChange, required, label, startDate, endDate, errorMessage, className, id, disabled, dateFormat, shouldPopOnParent, getPopupContainer: customGetPopupContainer, maxDateRange, open, onOpenChange, placement, renderAsIconButton, iconButtonClassName, iconClassName, labelExtra, inputEmphasis, presets, }: TDateRangeProps): import("react/jsx-runtime").JSX.Element;
|
|
77
82
|
displayName: string;
|
|
78
83
|
};
|
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
import { jsxs as R, jsx as t } from "react/jsx-runtime";
|
|
2
|
-
import { DatePicker as
|
|
2
|
+
import { DatePicker as ae } from "antd";
|
|
3
3
|
import q from "../../../_virtual/index.es.js";
|
|
4
|
-
import { useState as
|
|
4
|
+
import { useState as Q, useRef as m, useCallback as I, useEffect as X } from "react";
|
|
5
5
|
import L from "dayjs";
|
|
6
|
-
import
|
|
7
|
-
import { InputLabel as
|
|
8
|
-
import { CalendarMonthIcon as T, CheckIndeterminateSmallFilledIcon as
|
|
9
|
-
const { RangePicker:
|
|
6
|
+
import ce from "../../button/IconButton.es.js";
|
|
7
|
+
import { InputLabel as le } from "../shared/InputLabel.es.js";
|
|
8
|
+
import { CalendarMonthIcon as T, CheckIndeterminateSmallFilledIcon as Z } from "../../icon/icons.generated.es.js";
|
|
9
|
+
const { RangePicker: G } = ae, ee = {
|
|
10
10
|
ENTER: "Enter"
|
|
11
|
-
},
|
|
11
|
+
}, te = () => Math.random().toString(36).substring(2, 9), fe = (a, n) => {
|
|
12
12
|
const p = m(n);
|
|
13
|
-
|
|
13
|
+
X(() => {
|
|
14
14
|
p.current = n;
|
|
15
|
-
}, [n]),
|
|
16
|
-
const f = (
|
|
15
|
+
}, [n]), X(() => {
|
|
16
|
+
const f = (s) => p.current(s);
|
|
17
17
|
return document.addEventListener(a, f), () => {
|
|
18
18
|
document.removeEventListener(a, f);
|
|
19
19
|
};
|
|
20
20
|
}, [a]);
|
|
21
|
-
},
|
|
21
|
+
}, ue = ({
|
|
22
22
|
onCalendarChange: a = void 0,
|
|
23
23
|
onChange: n,
|
|
24
24
|
required: p,
|
|
25
25
|
label: f,
|
|
26
|
-
startDate:
|
|
26
|
+
startDate: s,
|
|
27
27
|
endDate: u,
|
|
28
28
|
errorMessage: d,
|
|
29
29
|
className: M,
|
|
@@ -37,41 +37,42 @@ const { RangePicker: Z } = ie, G = {
|
|
|
37
37
|
onOpenChange: x,
|
|
38
38
|
placement: K = "bottomLeft",
|
|
39
39
|
renderAsIconButton: C = !1,
|
|
40
|
-
iconButtonClassName:
|
|
41
|
-
iconClassName:
|
|
40
|
+
iconButtonClassName: re,
|
|
41
|
+
iconClassName: ne,
|
|
42
42
|
labelExtra: P,
|
|
43
|
-
inputEmphasis: $ = "default"
|
|
43
|
+
inputEmphasis: $ = "default",
|
|
44
|
+
presets: j
|
|
44
45
|
}) => {
|
|
45
|
-
const D = $ === "modified" && !d, y = $ === "deleted" && !d, w = $ === "success" && !d,
|
|
46
|
+
const D = $ === "modified" && !d, y = $ === "deleted" && !d, w = $ === "success" && !d, _ = D ? "var(--Warning-50, #FFFAEB)" : y ? "var(--Error-50, #FEF2F2)" : w ? "var(--Success-50, #F0FDF4)" : "", E = D ? "var(--Warning-200, #FEDF89)" : y ? "var(--Error-200, #FECACA)" : w ? "var(--Success-200, #BBF7D0)" : "", [Y, b] = Q(!1), [A, H] = Q(!1), h = m(null), U = m(null), N = m(!1), g = m(!1), o = (e) => e ? L(e) : null, O = `date-range-start-${te()}`, B = `date-range-end-${te()}`, oe = () => {
|
|
46
47
|
b(!0), setTimeout(() => {
|
|
47
48
|
h.current && h.current.focus();
|
|
48
49
|
}, 0);
|
|
49
50
|
};
|
|
50
|
-
|
|
51
|
-
if (e.key ===
|
|
51
|
+
fe("keydown", (e) => {
|
|
52
|
+
if (e.key === ee.ENTER && document.activeElement instanceof HTMLInputElement) {
|
|
52
53
|
if (document?.activeElement?.id === O) {
|
|
53
54
|
const r = L(document?.activeElement?.value);
|
|
54
|
-
r.isValid() && n([r,
|
|
55
|
+
r.isValid() && n([r, o(u)]);
|
|
55
56
|
}
|
|
56
57
|
if (document?.activeElement?.id === B) {
|
|
57
58
|
const r = L(document?.activeElement?.value);
|
|
58
|
-
r.isValid() && n([s
|
|
59
|
+
r.isValid() && n([o(s), r]);
|
|
59
60
|
}
|
|
60
61
|
}
|
|
61
62
|
});
|
|
62
|
-
const
|
|
63
|
+
const V = I(
|
|
63
64
|
(e) => {
|
|
64
|
-
const [r, i] = [s
|
|
65
|
+
const [r, i] = [o(s), o(u)];
|
|
65
66
|
return l ? r ? e.isBefore(r.startOf("day")) || e.isAfter(r.add(l, "day").endOf("day")) : i ? e.isBefore(i.subtract(l, "day").startOf("day")) || e.isAfter(i.endOf("day")) : !1 : !1;
|
|
66
67
|
},
|
|
67
|
-
[
|
|
68
|
-
),
|
|
69
|
-
if (e.key ===
|
|
68
|
+
[s, u, l]
|
|
69
|
+
), W = I((e) => {
|
|
70
|
+
if (e.key === ee.ENTER && !(C ? Y : S ?? A)) {
|
|
70
71
|
e.preventDefault(), e.stopPropagation();
|
|
71
72
|
const i = e.target.closest("form");
|
|
72
73
|
if (i) {
|
|
73
|
-
const
|
|
74
|
-
|
|
74
|
+
const J = i.querySelector('button[type="submit"]');
|
|
75
|
+
J ? J.click() : i.requestSubmit();
|
|
75
76
|
}
|
|
76
77
|
}
|
|
77
78
|
}, [C, Y, S, A]), se = I((e) => {
|
|
@@ -84,60 +85,61 @@ const { RangePicker: Z } = ie, G = {
|
|
|
84
85
|
N.current = !1;
|
|
85
86
|
});
|
|
86
87
|
}));
|
|
87
|
-
}, []),
|
|
88
|
+
}, []), ie = I((e) => {
|
|
88
89
|
if (e && g.current) {
|
|
89
|
-
g.current = !1,
|
|
90
|
+
g.current = !1, H(!1), x?.(!1);
|
|
90
91
|
return;
|
|
91
92
|
}
|
|
92
|
-
|
|
93
|
-
|
|
93
|
+
H(e), x?.(e), e || (g.current = !0, requestAnimationFrame(() => {
|
|
94
|
+
U.current?.focus(), requestAnimationFrame(() => {
|
|
94
95
|
g.current = !1;
|
|
95
96
|
});
|
|
96
97
|
}));
|
|
97
98
|
}, [x]);
|
|
98
|
-
return C ? /* @__PURE__ */ R("div", { id: c, className: M, onKeyDownCapture:
|
|
99
|
+
return C ? /* @__PURE__ */ R("div", { id: c, className: M, onKeyDownCapture: W, children: [
|
|
99
100
|
/* @__PURE__ */ t(
|
|
100
|
-
|
|
101
|
+
ce,
|
|
101
102
|
{
|
|
102
|
-
onClick:
|
|
103
|
+
onClick: oe,
|
|
103
104
|
disabled: F,
|
|
104
105
|
variant: "default",
|
|
105
|
-
className:
|
|
106
|
-
children: /* @__PURE__ */ t(T, { size: 20, className: q("w-5 h-5",
|
|
106
|
+
className: re,
|
|
107
|
+
children: /* @__PURE__ */ t(T, { size: 20, className: q("w-5 h-5", ne) })
|
|
107
108
|
}
|
|
108
109
|
),
|
|
109
110
|
/* @__PURE__ */ t(
|
|
110
|
-
|
|
111
|
+
G,
|
|
111
112
|
{
|
|
112
113
|
ref: h,
|
|
113
114
|
onChange: (e) => {
|
|
114
115
|
n(e), b(!1);
|
|
115
116
|
},
|
|
116
117
|
onCalendarChange: a,
|
|
117
|
-
value: [s
|
|
118
|
+
value: [o(s), o(u)],
|
|
118
119
|
id: { start: O, end: B },
|
|
119
120
|
allowClear: !0,
|
|
120
121
|
format: k || "DD MMM, YYYY",
|
|
121
|
-
separator: /* @__PURE__ */ t(
|
|
122
|
+
separator: /* @__PURE__ */ t(Z, { size: 20, className: "text-neutral-400 dark:text-gray-100" }),
|
|
122
123
|
suffixIcon: /* @__PURE__ */ t(T, { size: 14, className: "text-neutral-400 dark:text-gray-100" }),
|
|
123
124
|
getPopupContainer: v || (z ? (e) => e.parentElement : () => document.body),
|
|
124
125
|
disabled: F,
|
|
125
|
-
disabledDate: l ?
|
|
126
|
+
disabledDate: l ? V : void 0,
|
|
126
127
|
autoComplete: "off",
|
|
127
128
|
open: Y,
|
|
128
129
|
onOpenChange: se,
|
|
129
130
|
placement: K,
|
|
131
|
+
presets: j,
|
|
130
132
|
style: { position: "absolute", opacity: 0, pointerEvents: "none", width: 0, height: 0 }
|
|
131
133
|
}
|
|
132
134
|
)
|
|
133
|
-
] }) : /* @__PURE__ */ R("div", { id: c, className: q("flex flex-col", M), onKeyDownCapture:
|
|
135
|
+
] }) : /* @__PURE__ */ R("div", { id: c, className: q("flex flex-col", M), onKeyDownCapture: W, children: [
|
|
134
136
|
(f || P) && /* @__PURE__ */ R("div", { className: "mb-1 flex items-center justify-between gap-1", children: [
|
|
135
|
-
/* @__PURE__ */ t(
|
|
137
|
+
/* @__PURE__ */ t(le, { label: f || "", required: p || !1 }),
|
|
136
138
|
P
|
|
137
139
|
] }),
|
|
138
|
-
(
|
|
140
|
+
(_ || E) && /* @__PURE__ */ t("style", { children: `
|
|
139
141
|
#${c} .ant-picker {
|
|
140
|
-
background-color: ${
|
|
142
|
+
background-color: ${_} !important;
|
|
141
143
|
border-color: ${E} !important;
|
|
142
144
|
}
|
|
143
145
|
#${c} .ant-picker:hover {
|
|
@@ -152,24 +154,25 @@ const { RangePicker: Z } = ie, G = {
|
|
|
152
154
|
}
|
|
153
155
|
` }),
|
|
154
156
|
/* @__PURE__ */ t(
|
|
155
|
-
|
|
157
|
+
G,
|
|
156
158
|
{
|
|
157
|
-
ref:
|
|
159
|
+
ref: U,
|
|
158
160
|
onChange: n,
|
|
159
161
|
onCalendarChange: a,
|
|
160
|
-
value: [s
|
|
162
|
+
value: [o(s), o(u)],
|
|
161
163
|
id: { start: O, end: B },
|
|
162
164
|
allowClear: !0,
|
|
163
165
|
format: k || "DD MMM, YYYY",
|
|
164
|
-
separator: /* @__PURE__ */ t(
|
|
166
|
+
separator: /* @__PURE__ */ t(Z, { size: 20, className: "text-neutral-400 dark:text-gray-100" }),
|
|
165
167
|
suffixIcon: /* @__PURE__ */ t(T, { size: 14, className: "text-neutral-400 dark:text-gray-100" }),
|
|
166
168
|
getPopupContainer: v || (z ? (e) => e.parentElement : () => document.body),
|
|
167
169
|
disabled: F,
|
|
168
|
-
disabledDate: l ?
|
|
170
|
+
disabledDate: l ? V : void 0,
|
|
169
171
|
open: S ?? A,
|
|
170
|
-
onOpenChange:
|
|
172
|
+
onOpenChange: ie,
|
|
171
173
|
autoComplete: "off",
|
|
172
|
-
placement: K
|
|
174
|
+
placement: K,
|
|
175
|
+
presets: j
|
|
173
176
|
}
|
|
174
177
|
),
|
|
175
178
|
d && /* @__PURE__ */ t(
|
|
@@ -184,8 +187,8 @@ const { RangePicker: Z } = ie, G = {
|
|
|
184
187
|
)
|
|
185
188
|
] });
|
|
186
189
|
};
|
|
187
|
-
|
|
190
|
+
ue.displayName = "DateRange";
|
|
188
191
|
export {
|
|
189
|
-
|
|
192
|
+
ue as DateRange
|
|
190
193
|
};
|
|
191
194
|
//# sourceMappingURL=DateRange.es.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DateRange.es.js","sources":["../../../../src/components/forms/date-range/DateRange.tsx"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { DatePicker } from \"antd\";\nimport cn from \"classnames\";\nimport React from \"react\";\nimport dayjs from \"dayjs\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport IconButton from \"../../button/IconButton\";\nimport { InputLabel } from \"../shared/InputLabel\";\nimport { CalendarMonthIcon, CheckIndeterminateSmallFilledIcon } from '../../icon';\n\nconst { RangePicker } = DatePicker;\n\n// Keyboard keys constant\nconst KEYBOARD_KEYS = {\n ENTER: \"Enter\",\n} as const;\n\n/**\n * Generate a short UUID\n */\nconst generateShortUUID = (): string => {\n return Math.random().toString(36).substring(2, 9);\n};\n\n/**\n * Hook to add event listeners\n */\nconst useEventListener = <K extends keyof DocumentEventMap>(\n eventName: K,\n handler: (event: DocumentEventMap[K]) => void\n) => {\n const savedHandler = useRef(handler);\n\n useEffect(() => {\n savedHandler.current = handler;\n }, [handler]);\n\n useEffect(() => {\n const eventListener = (event: DocumentEventMap[K]) =>\n savedHandler.current(event);\n document.addEventListener(eventName, eventListener);\n return () => {\n document.removeEventListener(eventName, eventListener);\n };\n }, [eventName]);\n};\n\n/**\n * Props for the DateRange component\n * Matches the lax-web-portal implementation for drop-in replacement\n */\nexport type TDateRangeProps = {\n /** Unique identifier for the date range */\n id: string;\n /** Label text to display above the date range */\n label?: string;\n /** Start date value (ISO string or formatted date string) */\n startDate: string;\n /** End date value (ISO string or formatted date string) */\n endDate: string;\n /** Callback function called when date range changes */\n onChange(data: any): void;\n /** Callback function called when calendar selection changes */\n onCalendarChange?(data: any): void;\n /** Whether the field is required */\n required?: boolean;\n /** Error message to display below the date range */\n errorMessage?: string;\n /** Additional CSS classes for the wrapper */\n className?: string;\n /** Whether the date range is disabled */\n disabled?: boolean;\n /** Custom date format */\n dateFormat?: string;\n /** Whether popup should render inside parent element */\n shouldPopOnParent?: boolean;\n /** Custom function to get popup container */\n getPopupContainer?: (trigger: HTMLElement | null) => HTMLElement;\n /** Maximum date range in days */\n maxDateRange?: number;\n /** Whether the picker is open */\n open?: boolean;\n /** Callback function called when open state changes */\n onOpenChange?(open: boolean): void;\n /** Placement of the dropdown */\n placement?: \"bottomLeft\" | \"bottomRight\" | \"topLeft\" | \"topRight\";\n /** Whether to render as an icon button that triggers the date picker */\n renderAsIconButton?: boolean;\n /** Additional CSS classes for the icon button */\n iconButtonClassName?: string;\n /** Additional CSS classes for the calendar icon inside the button */\n iconClassName?: string;\n /** Optional extra content in the label row (e.g. actions, badges) */\n labelExtra?: React.ReactNode;\n /** Input surface style: `'modified'` — Warning colors; `'deleted'` — Error colors; `'success'` — Success colors. */\n inputEmphasis?: \"default\" | \"modified\" | \"deleted\" | \"success\";\n};\n\n/**\n * A date range picker component with label, validation, and styling support.\n * Features proper date handling, validation, and comprehensive prop support.\n * Built on top of Ant Design's RangePicker for advanced functionality.\n *\n * This component is designed as a drop-in replacement for the lax-web-portal\n * DateRange component.\n *\n * @example\n * ```tsx\n * <DateRange\n * id=\"event-dates\"\n * label=\"Event Duration\"\n * startDate={startDate}\n * endDate={endDate}\n * onChange={(dates) => {\n * setStartDate(dates[0]);\n * setEndDate(dates[1]);\n * }}\n * required\n * />\n * ```\n */\nexport const DateRange = ({\n onCalendarChange = undefined,\n onChange,\n required,\n label,\n startDate,\n endDate,\n errorMessage,\n className,\n id,\n disabled = false,\n dateFormat,\n shouldPopOnParent = true,\n getPopupContainer: customGetPopupContainer,\n maxDateRange,\n open,\n onOpenChange,\n placement = \"bottomLeft\",\n renderAsIconButton = false,\n iconButtonClassName,\n iconClassName,\n labelExtra,\n inputEmphasis = \"default\",\n}: TDateRangeProps) => {\n const emphasisModifiedSkin = inputEmphasis === \"modified\" && !errorMessage;\n const emphasisDeletedSkin = inputEmphasis === \"deleted\" && !errorMessage;\n const emphasisSuccessSkin = inputEmphasis === \"success\" && !errorMessage;\n const emphasisBg =\n emphasisModifiedSkin ? \"var(--Warning-50, #FFFAEB)\" :\n emphasisDeletedSkin ? \"var(--Error-50, #FEF2F2)\" :\n emphasisSuccessSkin ? \"var(--Success-50, #F0FDF4)\" : \"\";\n const emphasisBorder =\n emphasisModifiedSkin ? \"var(--Warning-200, #FEDF89)\" :\n emphasisDeletedSkin ? \"var(--Error-200, #FECACA)\" :\n emphasisSuccessSkin ? \"var(--Success-200, #BBF7D0)\" : \"\";\n const [isOpen, setIsOpen] = useState(false);\n const [isNormalPickerOpen, setIsNormalPickerOpen] = useState(false);\n const pickerRef = useRef<any>(null);\n const normalPickerRef = useRef<any>(null);\n const suppressNextIconOpenRef = useRef(false);\n const suppressNextNormalOpenRef = useRef(false);\n\n const parseDate = (str: string | number | Date | dayjs.Dayjs) => {\n if (!str) return null;\n return dayjs(str);\n };\n\n const START_ID = `date-range-start-${generateShortUUID()}`;\n const END_ID = `date-range-end-${generateShortUUID()}`;\n\n const handleIconClick = () => {\n setIsOpen(true);\n setTimeout(() => {\n if (pickerRef.current) {\n pickerRef.current.focus();\n }\n }, 0);\n };\n\n useEventListener(\"keydown\", (e: KeyboardEvent) => {\n if (\n e.key === KEYBOARD_KEYS.ENTER &&\n document.activeElement instanceof HTMLInputElement\n ) {\n if (document?.activeElement?.id === START_ID) {\n const date = dayjs(document?.activeElement?.value);\n if (date.isValid()) {\n onChange([date, parseDate(endDate)]);\n }\n }\n if (document?.activeElement?.id === END_ID) {\n const date = dayjs(document?.activeElement?.value);\n if (date.isValid()) {\n onChange([parseDate(startDate), date]);\n }\n }\n }\n });\n\n const disabledDate = useCallback(\n (current: dayjs.Dayjs) => {\n const [start, end] = [parseDate(startDate), parseDate(endDate)];\n\n if (!maxDateRange) return false;\n\n if (start) {\n return (\n current.isBefore(start.startOf(\"day\")) ||\n current.isAfter(start.add(maxDateRange, \"day\").endOf(\"day\"))\n );\n }\n\n if (end) {\n return (\n current.isBefore(end.subtract(maxDateRange, \"day\").startOf(\"day\")) ||\n current.isAfter(end.endOf(\"day\"))\n );\n }\n\n return false;\n },\n [startDate, endDate, maxDateRange]\n );\n\n const handleKeyDownCapture = useCallback((e: React.KeyboardEvent) => {\n if (e.key === KEYBOARD_KEYS.ENTER) {\n const pickerIsOpen = renderAsIconButton ? isOpen : (open ?? isNormalPickerOpen);\n if (!pickerIsOpen) {\n e.preventDefault();\n e.stopPropagation();\n\n const form = (e.target as HTMLElement).closest('form');\n if (form) {\n const submitBtn = form.querySelector<HTMLButtonElement>('button[type=\"submit\"]');\n if (submitBtn) {\n submitBtn.click();\n } else {\n form.requestSubmit();\n }\n }\n }\n }\n }, [renderAsIconButton, isOpen, open, isNormalPickerOpen]);\n\n const handleIconPickerOpenChange = useCallback((nextOpen: boolean) => {\n if (nextOpen && suppressNextIconOpenRef.current) {\n suppressNextIconOpenRef.current = false;\n setIsOpen(false);\n return;\n }\n\n setIsOpen(nextOpen);\n if (!nextOpen) {\n suppressNextIconOpenRef.current = true;\n requestAnimationFrame(() => {\n pickerRef.current?.focus();\n requestAnimationFrame(() => {\n suppressNextIconOpenRef.current = false;\n });\n });\n }\n }, []);\n\n const handleNormalOpenChange = useCallback((nextOpen: boolean) => {\n if (nextOpen && suppressNextNormalOpenRef.current) {\n suppressNextNormalOpenRef.current = false;\n setIsNormalPickerOpen(false);\n onOpenChange?.(false);\n return;\n }\n\n setIsNormalPickerOpen(nextOpen);\n onOpenChange?.(nextOpen);\n if (!nextOpen) {\n suppressNextNormalOpenRef.current = true;\n requestAnimationFrame(() => {\n normalPickerRef.current?.focus();\n requestAnimationFrame(() => {\n suppressNextNormalOpenRef.current = false;\n });\n });\n }\n }, [onOpenChange]);\n\n if (renderAsIconButton) {\n return (\n <div id={id} className={className} onKeyDownCapture={handleKeyDownCapture}>\n <IconButton\n onClick={handleIconClick}\n disabled={disabled}\n variant=\"default\"\n className={iconButtonClassName}\n >\n <CalendarMonthIcon size={20} className={cn(\"w-5 h-5\", iconClassName)} />\n </IconButton>\n <RangePicker\n ref={pickerRef}\n onChange={(dates) => {\n onChange(dates);\n setIsOpen(false);\n }}\n onCalendarChange={onCalendarChange}\n value={[parseDate(startDate), parseDate(endDate)]}\n id={{ start: START_ID, end: END_ID }}\n allowClear\n format={dateFormat ? dateFormat : \"DD MMM, YYYY\"}\n separator={<CheckIndeterminateSmallFilledIcon size={20} className=\"text-neutral-400 dark:text-gray-100\" />}\n suffixIcon={<CalendarMonthIcon size={14} className=\"text-neutral-400 dark:text-gray-100\" />}\n getPopupContainer={\n customGetPopupContainer\n ? customGetPopupContainer\n : shouldPopOnParent\n ? (trigger) => trigger.parentElement as HTMLElement\n : () => document.body\n }\n disabled={disabled}\n disabledDate={maxDateRange ? disabledDate : undefined}\n autoComplete=\"off\"\n open={isOpen}\n onOpenChange={handleIconPickerOpenChange}\n placement={placement}\n style={{ position: \"absolute\", opacity: 0, pointerEvents: \"none\", width: 0, height: 0 }}\n />\n </div>\n );\n }\n\n return (\n <div id={id} className={cn(\"flex flex-col\", className)} onKeyDownCapture={handleKeyDownCapture}>\n {(label || labelExtra) && (\n <div className=\"mb-1 flex items-center justify-between gap-1\">\n <InputLabel label={label || \"\"} required={required || false} />\n {labelExtra}\n </div>\n )}\n {(emphasisBg || emphasisBorder) && (\n <style>{`\n #${id} .ant-picker {\n background-color: ${emphasisBg} !important;\n border-color: ${emphasisBorder} !important;\n }\n #${id} .ant-picker:hover {\n border-color: ${emphasisBorder} !important;\n }\n #${id} .ant-picker.ant-picker-focused {\n border-color: ${emphasisBorder} !important;\n box-shadow: 0 0 0 2px ${emphasisDeletedSkin ? \"rgba(254,202,202,0.45)\" : emphasisModifiedSkin ? \"rgba(254,223,137,0.45)\" : \"rgba(187,247,208,0.45)\"} !important;\n }\n #${id} .ant-picker .ant-picker-input > input {\n color: ${emphasisDeletedSkin ? \"#475467\" : emphasisSuccessSkin ? \"#101828\" : \"inherit\"};\n }\n `}</style>\n )}\n <RangePicker\n ref={normalPickerRef}\n onChange={onChange}\n onCalendarChange={onCalendarChange}\n value={[parseDate(startDate), parseDate(endDate)]}\n id={{ start: START_ID, end: END_ID }}\n allowClear\n format={dateFormat ? dateFormat : \"DD MMM, YYYY\"}\n separator={\n <CheckIndeterminateSmallFilledIcon size={20} className='text-neutral-400 dark:text-gray-100' />\n }\n suffixIcon={\n <CalendarMonthIcon size={14} className='text-neutral-400 dark:text-gray-100' />\n }\n getPopupContainer={\n customGetPopupContainer\n ? customGetPopupContainer\n : shouldPopOnParent\n ? (trigger) => trigger.parentElement as HTMLElement\n : () => document.body\n }\n disabled={disabled}\n disabledDate={maxDateRange ? disabledDate : undefined}\n open={open ?? isNormalPickerOpen}\n onOpenChange={handleNormalOpenChange}\n autoComplete=\"off\"\n placement={placement}\n />\n {errorMessage && (\n <p\n className={cn(\n \"text-sm font-inter font-normal text-left pt-[6px]\",\n \"text-red-500\"\n )}\n >\n {errorMessage}\n </p>\n )}\n </div>\n );\n};\n\nDateRange.displayName = \"DateRange\";\n\n"],"names":["RangePicker","DatePicker","KEYBOARD_KEYS","generateShortUUID","useEventListener","eventName","handler","savedHandler","useRef","useEffect","eventListener","event","DateRange","onCalendarChange","onChange","required","label","startDate","endDate","errorMessage","className","id","disabled","dateFormat","shouldPopOnParent","customGetPopupContainer","maxDateRange","open","onOpenChange","placement","renderAsIconButton","iconButtonClassName","iconClassName","labelExtra","inputEmphasis","emphasisModifiedSkin","emphasisDeletedSkin","emphasisSuccessSkin","emphasisBg","emphasisBorder","isOpen","setIsOpen","useState","isNormalPickerOpen","setIsNormalPickerOpen","pickerRef","normalPickerRef","suppressNextIconOpenRef","suppressNextNormalOpenRef","parseDate","str","dayjs","START_ID","END_ID","handleIconClick","date","disabledDate","useCallback","current","start","end","handleKeyDownCapture","form","submitBtn","handleIconPickerOpenChange","nextOpen","handleNormalOpenChange","jsxs","jsx","IconButton","CalendarMonthIcon","cn","dates","CheckIndeterminateSmallFilledIcon","trigger","InputLabel"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DateRange.es.js","sources":["../../../../src/components/forms/date-range/DateRange.tsx"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { DatePicker } from \"antd\";\nimport cn from \"classnames\";\nimport React from \"react\";\nimport dayjs from \"dayjs\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport IconButton from \"../../button/IconButton\";\nimport { InputLabel } from \"../shared/InputLabel\";\nimport { CalendarMonthIcon, CheckIndeterminateSmallFilledIcon } from '../../icon';\n\nconst { RangePicker } = DatePicker;\n\n// Keyboard keys constant\nconst KEYBOARD_KEYS = {\n ENTER: \"Enter\",\n} as const;\n\n/**\n * Generate a short UUID\n */\nconst generateShortUUID = (): string => {\n return Math.random().toString(36).substring(2, 9);\n};\n\n/**\n * Hook to add event listeners\n */\nconst useEventListener = <K extends keyof DocumentEventMap>(\n eventName: K,\n handler: (event: DocumentEventMap[K]) => void\n) => {\n const savedHandler = useRef(handler);\n\n useEffect(() => {\n savedHandler.current = handler;\n }, [handler]);\n\n useEffect(() => {\n const eventListener = (event: DocumentEventMap[K]) =>\n savedHandler.current(event);\n document.addEventListener(eventName, eventListener);\n return () => {\n document.removeEventListener(eventName, eventListener);\n };\n }, [eventName]);\n};\n\n/**\n * Props for the DateRange component\n * Matches the lax-web-portal implementation for drop-in replacement\n */\nexport type TDateRangeProps = {\n /** Unique identifier for the date range */\n id: string;\n /** Label text to display above the date range */\n label?: string;\n /** Start date value (ISO string or formatted date string) */\n startDate: string;\n /** End date value (ISO string or formatted date string) */\n endDate: string;\n /** Callback function called when date range changes */\n onChange(data: any): void;\n /** Callback function called when calendar selection changes */\n onCalendarChange?(data: any): void;\n /** Whether the field is required */\n required?: boolean;\n /** Error message to display below the date range */\n errorMessage?: string;\n /** Additional CSS classes for the wrapper */\n className?: string;\n /** Whether the date range is disabled */\n disabled?: boolean;\n /** Custom date format */\n dateFormat?: string;\n /** Whether popup should render inside parent element */\n shouldPopOnParent?: boolean;\n /** Custom function to get popup container */\n getPopupContainer?: (trigger: HTMLElement | null) => HTMLElement;\n /** Maximum date range in days */\n maxDateRange?: number;\n /** Whether the picker is open */\n open?: boolean;\n /** Callback function called when open state changes */\n onOpenChange?(open: boolean): void;\n /** Placement of the dropdown */\n placement?: \"bottomLeft\" | \"bottomRight\" | \"topLeft\" | \"topRight\";\n /** Preset date ranges shown in the picker dropdown */\n presets?: { label: React.ReactNode; value: any }[];\n /** Whether to render as an icon button that triggers the date picker */\n renderAsIconButton?: boolean;\n /** Additional CSS classes for the icon button */\n iconButtonClassName?: string;\n /** Additional CSS classes for the calendar icon inside the button */\n iconClassName?: string;\n /** Optional extra content in the label row (e.g. actions, badges) */\n labelExtra?: React.ReactNode;\n /** Input surface style: `'modified'` — Warning colors; `'deleted'` — Error colors; `'success'` — Success colors. */\n inputEmphasis?: \"default\" | \"modified\" | \"deleted\" | \"success\";\n};\n\n/**\n * A date range picker component with label, validation, and styling support.\n * Features proper date handling, validation, and comprehensive prop support.\n * Built on top of Ant Design's RangePicker for advanced functionality.\n *\n * This component is designed as a drop-in replacement for the lax-web-portal\n * DateRange component.\n *\n * @example\n * ```tsx\n * <DateRange\n * id=\"event-dates\"\n * label=\"Event Duration\"\n * startDate={startDate}\n * endDate={endDate}\n * onChange={(dates) => {\n * setStartDate(dates[0]);\n * setEndDate(dates[1]);\n * }}\n * required\n * />\n * ```\n */\nexport const DateRange = ({\n onCalendarChange = undefined,\n onChange,\n required,\n label,\n startDate,\n endDate,\n errorMessage,\n className,\n id,\n disabled = false,\n dateFormat,\n shouldPopOnParent = true,\n getPopupContainer: customGetPopupContainer,\n maxDateRange,\n open,\n onOpenChange,\n placement = \"bottomLeft\",\n renderAsIconButton = false,\n iconButtonClassName,\n iconClassName,\n labelExtra,\n inputEmphasis = \"default\",\n presets,\n}: TDateRangeProps) => {\n const emphasisModifiedSkin = inputEmphasis === \"modified\" && !errorMessage;\n const emphasisDeletedSkin = inputEmphasis === \"deleted\" && !errorMessage;\n const emphasisSuccessSkin = inputEmphasis === \"success\" && !errorMessage;\n const emphasisBg =\n emphasisModifiedSkin ? \"var(--Warning-50, #FFFAEB)\" :\n emphasisDeletedSkin ? \"var(--Error-50, #FEF2F2)\" :\n emphasisSuccessSkin ? \"var(--Success-50, #F0FDF4)\" : \"\";\n const emphasisBorder =\n emphasisModifiedSkin ? \"var(--Warning-200, #FEDF89)\" :\n emphasisDeletedSkin ? \"var(--Error-200, #FECACA)\" :\n emphasisSuccessSkin ? \"var(--Success-200, #BBF7D0)\" : \"\";\n const [isOpen, setIsOpen] = useState(false);\n const [isNormalPickerOpen, setIsNormalPickerOpen] = useState(false);\n const pickerRef = useRef<any>(null);\n const normalPickerRef = useRef<any>(null);\n const suppressNextIconOpenRef = useRef(false);\n const suppressNextNormalOpenRef = useRef(false);\n\n const parseDate = (str: string | number | Date | dayjs.Dayjs) => {\n if (!str) return null;\n return dayjs(str);\n };\n\n const START_ID = `date-range-start-${generateShortUUID()}`;\n const END_ID = `date-range-end-${generateShortUUID()}`;\n\n const handleIconClick = () => {\n setIsOpen(true);\n setTimeout(() => {\n if (pickerRef.current) {\n pickerRef.current.focus();\n }\n }, 0);\n };\n\n useEventListener(\"keydown\", (e: KeyboardEvent) => {\n if (\n e.key === KEYBOARD_KEYS.ENTER &&\n document.activeElement instanceof HTMLInputElement\n ) {\n if (document?.activeElement?.id === START_ID) {\n const date = dayjs(document?.activeElement?.value);\n if (date.isValid()) {\n onChange([date, parseDate(endDate)]);\n }\n }\n if (document?.activeElement?.id === END_ID) {\n const date = dayjs(document?.activeElement?.value);\n if (date.isValid()) {\n onChange([parseDate(startDate), date]);\n }\n }\n }\n });\n\n const disabledDate = useCallback(\n (current: dayjs.Dayjs) => {\n const [start, end] = [parseDate(startDate), parseDate(endDate)];\n\n if (!maxDateRange) return false;\n\n if (start) {\n return (\n current.isBefore(start.startOf(\"day\")) ||\n current.isAfter(start.add(maxDateRange, \"day\").endOf(\"day\"))\n );\n }\n\n if (end) {\n return (\n current.isBefore(end.subtract(maxDateRange, \"day\").startOf(\"day\")) ||\n current.isAfter(end.endOf(\"day\"))\n );\n }\n\n return false;\n },\n [startDate, endDate, maxDateRange]\n );\n\n const handleKeyDownCapture = useCallback((e: React.KeyboardEvent) => {\n if (e.key === KEYBOARD_KEYS.ENTER) {\n const pickerIsOpen = renderAsIconButton ? isOpen : (open ?? isNormalPickerOpen);\n if (!pickerIsOpen) {\n e.preventDefault();\n e.stopPropagation();\n\n const form = (e.target as HTMLElement).closest('form');\n if (form) {\n const submitBtn = form.querySelector<HTMLButtonElement>('button[type=\"submit\"]');\n if (submitBtn) {\n submitBtn.click();\n } else {\n form.requestSubmit();\n }\n }\n }\n }\n }, [renderAsIconButton, isOpen, open, isNormalPickerOpen]);\n\n const handleIconPickerOpenChange = useCallback((nextOpen: boolean) => {\n if (nextOpen && suppressNextIconOpenRef.current) {\n suppressNextIconOpenRef.current = false;\n setIsOpen(false);\n return;\n }\n\n setIsOpen(nextOpen);\n if (!nextOpen) {\n suppressNextIconOpenRef.current = true;\n requestAnimationFrame(() => {\n pickerRef.current?.focus();\n requestAnimationFrame(() => {\n suppressNextIconOpenRef.current = false;\n });\n });\n }\n }, []);\n\n const handleNormalOpenChange = useCallback((nextOpen: boolean) => {\n if (nextOpen && suppressNextNormalOpenRef.current) {\n suppressNextNormalOpenRef.current = false;\n setIsNormalPickerOpen(false);\n onOpenChange?.(false);\n return;\n }\n\n setIsNormalPickerOpen(nextOpen);\n onOpenChange?.(nextOpen);\n if (!nextOpen) {\n suppressNextNormalOpenRef.current = true;\n requestAnimationFrame(() => {\n normalPickerRef.current?.focus();\n requestAnimationFrame(() => {\n suppressNextNormalOpenRef.current = false;\n });\n });\n }\n }, [onOpenChange]);\n\n if (renderAsIconButton) {\n return (\n <div id={id} className={className} onKeyDownCapture={handleKeyDownCapture}>\n <IconButton\n onClick={handleIconClick}\n disabled={disabled}\n variant=\"default\"\n className={iconButtonClassName}\n >\n <CalendarMonthIcon size={20} className={cn(\"w-5 h-5\", iconClassName)} />\n </IconButton>\n <RangePicker\n ref={pickerRef}\n onChange={(dates) => {\n onChange(dates);\n setIsOpen(false);\n }}\n onCalendarChange={onCalendarChange}\n value={[parseDate(startDate), parseDate(endDate)]}\n id={{ start: START_ID, end: END_ID }}\n allowClear\n format={dateFormat ? dateFormat : \"DD MMM, YYYY\"}\n separator={<CheckIndeterminateSmallFilledIcon size={20} className=\"text-neutral-400 dark:text-gray-100\" />}\n suffixIcon={<CalendarMonthIcon size={14} className=\"text-neutral-400 dark:text-gray-100\" />}\n getPopupContainer={\n customGetPopupContainer\n ? customGetPopupContainer\n : shouldPopOnParent\n ? (trigger) => trigger.parentElement as HTMLElement\n : () => document.body\n }\n disabled={disabled}\n disabledDate={maxDateRange ? disabledDate : undefined}\n autoComplete=\"off\"\n open={isOpen}\n onOpenChange={handleIconPickerOpenChange}\n placement={placement}\n presets={presets}\n style={{ position: \"absolute\", opacity: 0, pointerEvents: \"none\", width: 0, height: 0 }}\n />\n </div>\n );\n }\n\n return (\n <div id={id} className={cn(\"flex flex-col\", className)} onKeyDownCapture={handleKeyDownCapture}>\n {(label || labelExtra) && (\n <div className=\"mb-1 flex items-center justify-between gap-1\">\n <InputLabel label={label || \"\"} required={required || false} />\n {labelExtra}\n </div>\n )}\n {(emphasisBg || emphasisBorder) && (\n <style>{`\n #${id} .ant-picker {\n background-color: ${emphasisBg} !important;\n border-color: ${emphasisBorder} !important;\n }\n #${id} .ant-picker:hover {\n border-color: ${emphasisBorder} !important;\n }\n #${id} .ant-picker.ant-picker-focused {\n border-color: ${emphasisBorder} !important;\n box-shadow: 0 0 0 2px ${emphasisDeletedSkin ? \"rgba(254,202,202,0.45)\" : emphasisModifiedSkin ? \"rgba(254,223,137,0.45)\" : \"rgba(187,247,208,0.45)\"} !important;\n }\n #${id} .ant-picker .ant-picker-input > input {\n color: ${emphasisDeletedSkin ? \"#475467\" : emphasisSuccessSkin ? \"#101828\" : \"inherit\"};\n }\n `}</style>\n )}\n <RangePicker\n ref={normalPickerRef}\n onChange={onChange}\n onCalendarChange={onCalendarChange}\n value={[parseDate(startDate), parseDate(endDate)]}\n id={{ start: START_ID, end: END_ID }}\n allowClear\n format={dateFormat ? dateFormat : \"DD MMM, YYYY\"}\n separator={\n <CheckIndeterminateSmallFilledIcon size={20} className='text-neutral-400 dark:text-gray-100' />\n }\n suffixIcon={\n <CalendarMonthIcon size={14} className='text-neutral-400 dark:text-gray-100' />\n }\n getPopupContainer={\n customGetPopupContainer\n ? customGetPopupContainer\n : shouldPopOnParent\n ? (trigger) => trigger.parentElement as HTMLElement\n : () => document.body\n }\n disabled={disabled}\n disabledDate={maxDateRange ? disabledDate : undefined}\n open={open ?? isNormalPickerOpen}\n onOpenChange={handleNormalOpenChange}\n autoComplete=\"off\"\n placement={placement}\n presets={presets}\n />\n {errorMessage && (\n <p\n className={cn(\n \"text-sm font-inter font-normal text-left pt-[6px]\",\n \"text-red-500\"\n )}\n >\n {errorMessage}\n </p>\n )}\n </div>\n );\n};\n\nDateRange.displayName = \"DateRange\";\n\n"],"names":["RangePicker","DatePicker","KEYBOARD_KEYS","generateShortUUID","useEventListener","eventName","handler","savedHandler","useRef","useEffect","eventListener","event","DateRange","onCalendarChange","onChange","required","label","startDate","endDate","errorMessage","className","id","disabled","dateFormat","shouldPopOnParent","customGetPopupContainer","maxDateRange","open","onOpenChange","placement","renderAsIconButton","iconButtonClassName","iconClassName","labelExtra","inputEmphasis","presets","emphasisModifiedSkin","emphasisDeletedSkin","emphasisSuccessSkin","emphasisBg","emphasisBorder","isOpen","setIsOpen","useState","isNormalPickerOpen","setIsNormalPickerOpen","pickerRef","normalPickerRef","suppressNextIconOpenRef","suppressNextNormalOpenRef","parseDate","str","dayjs","START_ID","END_ID","handleIconClick","date","disabledDate","useCallback","current","start","end","handleKeyDownCapture","form","submitBtn","handleIconPickerOpenChange","nextOpen","handleNormalOpenChange","jsxs","jsx","IconButton","CalendarMonthIcon","cn","dates","CheckIndeterminateSmallFilledIcon","trigger","InputLabel"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),O=require("@mui/icons-material/EditOutlined"),V=require("@mui/icons-material/WarningRounded"),s=require("../../_virtual/index.cjs.js"),n=require("react"),l=require("../data-display/typography/Typography.cjs.js"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),O=require("@mui/icons-material/EditOutlined"),V=require("@mui/icons-material/WarningRounded"),s=require("../../_virtual/index.cjs.js"),n=require("react"),l=require("../data-display/typography/Typography.cjs.js"),g=require("../data-display/tag/Tag.cjs.js"),D=require("../data-display/skeleton/Skeleton.cjs.js"),ee=require("../../utils/countryFlags.cjs.js"),re=require("./UserAvatarPopper.cjs.js"),ae=require("./StatusInfoRow.cjs.js"),u=require("./constants.cjs.js"),se=require("./PersonIcon.cjs.js"),oe=require("./useDynamicPosition.cjs.js"),ne=require("../icon/icons.generated.cjs.js"),j=({label:t,content:i})=>e.jsxs("div",{className:"flex justify-between items-center",children:[e.jsx(l.Typography,{size:"small",variant:"medium",className:"mr-5",appearance:"body",children:t}),i]}),H=({firstName:t,lastName:i,email:U,profilePic:c,size:v="md",hoverSize:k="lg",containerClassName:F="",enablePopper:P=!0,className:A,userId:C,lastViewedOn:m,isActive:b,statusIndicator:B=!1,userDetails:r,isFetchingUserDetails:$=!1,authToken:z,onHover:G,currentlyEditing:R})=>{if(t==="All"&&i==="Users")return e.jsx("div",{className:"p-1 rounded-full bg-primary-100 dark:bg-black-600 flex items-center justify-center",children:e.jsx(ne.GroupsIcon,{className:"text-primary-600 dark:text-primary-600 w-4 h-4"})});const[W,w]=n.useState(!1),[M,d]=n.useState(!1),_=u.sizeClasses[v],{triggerRef:J,dropdownRef:K,position:f,isVisible:Q,show:S,hide:q}=oe.useDynamicPosition(),N=n.useRef({}),I=n.useMemo(()=>{if(b||!m)return!1;const a=new Date(m);return(new Date().getTime()-a.getTime())/(1e3*60*60)<24},[b,m]),h=b?"bg-primary-600 dark:bg-primary-600":I?"bg-primary-300 dark:bg-primary-300":m?"bg-neutral-400 dark:bg-neutral-400":null,p=b?"border-primary-600 dark:border-primary-600":I?"border-primary-300 dark:border-primary-300":m?"border-neutral-400 dark:border-neutral-400":"border-primary-200 dark:border-neutral-800",X={"2xs":"w-1.5 h-1.5",xs:"w-2 h-2",sm:"w-2.5 h-2.5",md:"w-3 h-3",lg:"w-3.5 h-3.5",xl:"w-4 h-4"};n.useEffect(()=>{if(c)if(N.current[c])d(!0);else{d(!1);const a=new Image,x=z||(typeof localStorage<"u"?localStorage.getItem("token"):null);a.src=c+(x?"?token="+x:""),a.onload=()=>{N.current[c]=a.src,d(!0)},a.onerror=()=>{d(!1)}}else d(!1)},[c,z]),n.useEffect(()=>()=>{o.current&&clearTimeout(o.current)},[]);const y=c?N.current[c]:void 0,o=n.useRef(null),T=n.useRef(null),Y=()=>{G?.(),t&&i&&P&&(o.current&&clearTimeout(o.current),o.current=setTimeout(()=>{w(!0)},300))},L=a=>{o.current&&clearTimeout(o.current),o.current=setTimeout(()=>{T.current&&!T.current.contains(a.relatedTarget)&&w(!1)},200)},Z=e.jsxs("div",{ref:T,className:"bg-white dark:bg-black-800 shadow rounded-lg border border-neutral-200 dark:border-black-700 min-w-[280px]",onMouseEnter:()=>{o.current&&clearTimeout(o.current)},onMouseLeave:a=>L(a),children:[e.jsxs("div",{className:"flex flex-col gap-1 items-center p-5",children:[e.jsxs("div",{className:s("relative",u.sizeClasses[k]),children:[y&&M?e.jsx("img",{src:y,alt:"Profile",className:s("rounded-full border-2 object-cover w-full h-full",p),onError:()=>d(!1)}):e.jsx("div",{className:s("bg-primary-100 dark:bg-primary-950 border-2 flex items-center justify-center rounded-full w-full h-full",p),children:e.jsx(l.Typography,{size:"large",variant:"semibold",appearance:"custom",className:s("text-primary-600",u.initialsFontSizeClasses[k]),children:u.getInitials((t||"")+" "+(i||""))})}),h&&e.jsx("div",{className:s("absolute bottom-0 right-0 rounded-full border-2 border-white dark:border-black-800",X[k],h)})]}),e.jsxs("div",{className:"flex flex-row gap-1 items-center justify-center",children:[e.jsxs(l.Typography,{size:"medium",variant:"semibold",className:"w-full text-center",children:[t||""," ",i||""]}),r?.region&&e.jsx("span",{children:ee.getFlagComponentRectangleMd(r?.region)})]}),e.jsx(l.Typography,{size:"small",variant:"medium",appearance:"body",children:U||r?.email||""})]}),R?e.jsx("div",{className:"px-5 pb-3",children:e.jsxs("div",{className:"flex items-center gap-3 rounded-lg border border-primary-100 dark:border-primary-900 bg-[rgba(230,241,252,0.60)] dark:bg-primary-950/40 px-[13px] py-[7px]",children:[e.jsx("div",{className:"flex items-center justify-center shrink-0 w-7 h-7 rounded-[5px] border-[0.4px] border-primary-100 dark:border-primary-900 bg-primary-50 dark:bg-primary-950",children:e.jsx(O,{sx:{width:13,height:13},className:"text-primary-600 dark:text-primary-500"})}),e.jsxs("div",{className:"flex flex-col min-w-0",children:[e.jsx(l.Typography,{size:"extra-small",variant:"semibold",appearance:"custom",className:"text-2xs leading-4 uppercase tracking-[0.2px] text-primary-600 dark:text-primary-500",children:"Currently editing"}),e.jsx(l.Typography,{size:"extra-small",variant:"semibold",className:"truncate",children:R})]})]})}):null,C&&($?e.jsx("div",{className:"p-5",children:e.jsx(D.Skeleton,{})}):C&&(r?.teams||r?.clearanceLevel||r?.group)?e.jsxs("div",{className:"flex flex-col gap-4 bg-neutral-50 border-t border-neutral-200 dark:bg-black-700 dark:border-none p-5 rounded-b-lg",children:[e.jsx(ae.StatusInfoRow,{isActive:b,lastViewedOn:m}),r.username&&e.jsx(j,{label:"Username",content:e.jsx("div",{className:"flex gap-2",children:e.jsx(l.Typography,{size:"small",variant:"medium",appearance:"body",children:r.username})})}),r?.teams&&r?.teams?.length>0&&e.jsx(j,{label:"Team",content:e.jsxs("div",{className:"flex gap-2",children:[r?.teams?.length>0&&e.jsx(g.Tag,{label:r?.teams[0]?.name,color:r?.teams[0]?.color||"#e38715",size:"md",isHashColor:!0},r?.teams[0]?.id),r?.teams?.length>=2&&e.jsxs("div",{ref:J,className:"relative inline-flex cursor-pointer",onMouseEnter:S,onMouseLeave:q,onClick:a=>a.stopPropagation(),children:[e.jsx(g.Tag,{label:`+ ${r?.teams?.length-1} More`,color:"#004f08",size:"md",isHashColor:!0},1),Q&&e.jsx("div",{ref:K,className:s("absolute w-max bg-white dark:text-black-200 dark:bg-black-800 shadow-md border border-neutral-200 dark:border-black-800 rounded-md px-2 z-10 overflow-y-auto max-h-60",{"top-full":f.vertical==="bottom","bottom-full":f.vertical==="top","left-0":f.horizontal==="left","right-0":f.horizontal==="right"}),onMouseEnter:S,onMouseLeave:q,children:e.jsx("div",{className:"flex flex-wrap gap-2 py-2 max-w-[320px]",children:r?.teams?.slice(1)?.map((a,x)=>e.jsx(g.Tag,{label:a?.name,color:a?.color||"#4A5568",size:"md",isHashColor:!0,className:"w-fit"},a?.id||x))})})]})]})}),r?.group&&e.jsx(j,{label:"Role",content:e.jsx(g.Tag,{label:r?.group,color:"#004094",size:"md",isHashColor:!0},r?.group)}),r?.clearanceLevel&&e.jsx(j,{label:"Clearance Level",content:e.jsx(g.Tag,{label:`Level ${r?.clearanceLevel}`,color:"#b30000",size:"md",isHashColor:!0},String(r?.clearanceLevel))})]}):e.jsx("div",{className:"flex items-center justify-center bg-neutral-50 dark:bg-black-700 border-t border-neutral-200 dark:border-black-700 p-5 rounded-b-lg",children:e.jsxs(l.Typography,{className:"flex items-center justify-center gap-1",size:"extra-small",variant:"medium",appearance:"body",children:[e.jsx(V,{sx:{height:"16px",width:"16px",color:"#F04438"}}),"No other information found!"]})}))]}),E=n.useRef(null);return e.jsxs("div",{onMouseEnter:Y,onMouseLeave:L,className:s("inline-block relative cursor-pointer",A),ref:E,children:[e.jsxs("div",{className:s("relative",F||_),children:[y&&M?e.jsx("img",{src:y,alt:"Profile",className:s("rounded-full border object-cover w-full h-full",p),onError:()=>d(!1)}):t&&i?e.jsx("div",{className:s("bg-primary-100 flex items-center justify-center rounded-full border dark:bg-black-700",u.sizeClasses[v],p),children:e.jsx(l.Typography,{size:"extra-small",variant:"semibold",appearance:"custom",className:s("text-primary-600",u.initialsFontSizeClasses[v]),children:u.getInitials((t||"")+" "+(i||""))})}):e.jsx("div",{className:s(p,"p-1 rounded-full bg-neutral-200 dark:bg-black-600 flex items-center justify-center border w-full h-full"),children:e.jsx(se.PersonIcon,{fill:"#98A2B3"})}),B&&h&&e.jsx("div",{className:s("absolute bottom-0 right-0 rounded-full border border-white dark:border-black-800 w-2 h-2",h)})]}),e.jsx(re.UserAvatarPopper,{isOpen:W,onClose:()=>w(!1),anchorEl:E.current,className:"bg-white dark:bg-black-700 shadow rounded-lg border border-neutral-200 dark:border-black-600",children:Z})]})};H.displayName="UserAvatar";exports.UserAvatar=H;
|
|
2
2
|
//# sourceMappingURL=UserAvatar.cjs.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UserAvatar.cjs.js","sources":["../../../src/components/user-avatar/UserAvatar.tsx"],"sourcesContent":["import EditOutlinedIcon from '@mui/icons-material/EditOutlined';\nimport WarningRoundedIcon from '@mui/icons-material/WarningRounded';\nimport cn from 'classnames';\nimport { type FC, useEffect, useMemo, useRef, useState } from 'react';\n\nimport { Typography } from '../data-display/typography/Typography';\nimport { Tag } from '../data-display/tag/Tag';\nimport { Skeleton } from '../data-display/skeleton/Skeleton';\nimport { getFlagComponentRectangleMd } from '../../utils/countryFlags';\nimport { UserAvatarPopper } from './UserAvatarPopper';\nimport { StatusInfoRow } from './StatusInfoRow';\nimport { sizeClasses, getInitials, initialsFontSizeClasses } from './constants';\nimport { PersonIcon } from './PersonIcon';\nimport { useDynamicPosition } from './useDynamicPosition';\nimport { GroupsIcon } from '../icon';\n\nexport type UserAvatarSize = '2xs' | 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n\nexport type UserDetailsTeam = {\n id?: string;\n name: string;\n color?: string;\n};\n\nexport type UserDetails = {\n email?: string;\n username?: string;\n teams?: UserDetailsTeam[];\n group?: string;\n clearanceLevel?: number | string;\n region?: string;\n};\n\nexport type UserAvatarProps = {\n firstName?: string;\n lastName?: string;\n email?: string;\n enablePopper?: boolean;\n profilePic?: string;\n size?: UserAvatarSize;\n hoverSize?: UserAvatarSize;\n containerClassName?: string;\n className?: string;\n userId?: string;\n lastViewedOn?: string;\n isActive?: boolean;\n statusIndicator?: boolean;\n /** User details to display in the popper - replaces the useTeamMemberFilter hook */\n userDetails?: UserDetails | null;\n /** Whether user details are being fetched */\n isFetchingUserDetails?: boolean;\n /** Optional token for authenticated image loading */\n authToken?: string;\n /** Callback triggered when mouse enters the avatar */\n onHover?: () => void;\n /** Name of the clause / line item the user is currently editing. When set, a highlighted \"Currently editing\" card is shown in the popper. */\n currentlyEditing?: string;\n};\n\nconst InfoRow = ({ label, content }: { label: string; content: React.ReactNode }) => (\n <div className='flex justify-between items-center'>\n <Typography size='small' variant='medium' className='mr-5' appearance='body'>\n {label}\n </Typography>\n {content}\n </div>\n);\n\n/**\n * UserAvatar component for displaying user profile pictures with hover popper\n *\n * @example\n * ```tsx\n * <UserAvatar\n * firstName=\"John\"\n * lastName=\"Doe\"\n * email=\"john@example.com\"\n * profilePic=\"/avatar.jpg\"\n * userDetails={{ teams: [{ name: 'Engineering', color: '#0066cc' }], group: 'Admin' }}\n * />\n * ```\n */\nexport const UserAvatar: FC<UserAvatarProps> = ({\n firstName,\n lastName,\n email,\n profilePic,\n size = 'md',\n hoverSize = 'lg',\n containerClassName = '',\n enablePopper = true,\n className,\n userId,\n lastViewedOn,\n isActive,\n statusIndicator = false,\n userDetails,\n isFetchingUserDetails = false,\n authToken,\n onHover,\n currentlyEditing,\n}) => {\n if (firstName === 'All' && lastName === 'Users') {\n return (\n <div className='p-1 rounded-full bg-primary-100 dark:bg-black-600 flex items-center justify-center'>\n <GroupsIcon className='text-primary-600 dark:text-primary-600 w-4 h-4' />\n </div>\n );\n }\n\n const [visible, setVisible] = useState<boolean>(false);\n const [imageLoaded, setImageLoaded] = useState<boolean>(false);\n\n const avatarSizeClass = sizeClasses[size];\n\n const {\n triggerRef: moreTagRef,\n dropdownRef,\n position: dropdownPosition,\n isVisible: showMore,\n show: handleShowMore,\n hide: handleHideMore,\n } = useDynamicPosition();\n\n const imageCacheRef = useRef<{ [key: string]: string }>({});\n\n const isRecent = useMemo(() => {\n if (isActive || !lastViewedOn) return false;\n const date = new Date(lastViewedOn);\n const now = new Date();\n const diffInHours = (now.getTime() - date.getTime()) / (1000 * 60 * 60);\n return diffInHours < 24;\n }, [isActive, lastViewedOn]);\n\n const getStatusColor = () => {\n if (isActive) return 'bg-primary-600 dark:bg-primary-600';\n if (isRecent) return 'bg-primary-300 dark:bg-primary-300';\n if (lastViewedOn) return 'bg-neutral-400 dark:bg-neutral-400';\n return null;\n };\n\n const statusColor = getStatusColor();\n\n const getBorderColor = () => {\n if (isActive) return 'border-primary-600 dark:border-primary-600';\n if (isRecent) return 'border-primary-300 dark:border-primary-300';\n if (lastViewedOn) return 'border-neutral-400 dark:border-neutral-400';\n return 'border-primary-200 dark:border-neutral-800';\n };\n\n const borderColor = getBorderColor();\n\n const indicatorSizes = {\n '2xs': 'w-1.5 h-1.5',\n xs: 'w-2 h-2',\n sm: 'w-2.5 h-2.5',\n md: 'w-3 h-3',\n lg: 'w-3.5 h-3.5',\n xl: 'w-4 h-4',\n };\n\n useEffect(() => {\n if (profilePic) {\n if (imageCacheRef.current[profilePic]) {\n setImageLoaded(true);\n } else {\n setImageLoaded(false);\n const img = new Image();\n const token = authToken || (typeof localStorage !== 'undefined' ? localStorage.getItem('token') : null);\n img.src = profilePic + (token ? '?token=' + token : '');\n img.onload = () => {\n imageCacheRef.current[profilePic] = img.src;\n setImageLoaded(true);\n };\n img.onerror = () => {\n setImageLoaded(false);\n };\n }\n } else {\n setImageLoaded(false);\n }\n }, [profilePic, authToken]);\n\n useEffect(() => {\n return () => {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n }\n };\n }, []);\n\n const cachedSrc = profilePic ? imageCacheRef.current[profilePic] : undefined;\n\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const popperRef = useRef<HTMLDivElement | null>(null);\n\n const handleMouseEnter = () => {\n onHover?.();\n if (firstName && lastName && enablePopper) {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n }\n timerRef.current = setTimeout(() => {\n setVisible(true);\n }, 300);\n }\n };\n\n const handleMouseLeave = (event: React.MouseEvent) => {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n }\n timerRef.current = setTimeout(() => {\n if (popperRef.current && !popperRef.current.contains(event.relatedTarget as Node)) {\n setVisible(false);\n }\n }, 200);\n };\n\n const popperContent = (\n <div\n ref={popperRef}\n className='bg-white dark:bg-black-800 shadow rounded-lg border border-neutral-200 dark:border-black-700 min-w-[280px]'\n onMouseEnter={() => {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n }\n }}\n onMouseLeave={(event) => handleMouseLeave(event)}\n >\n <div className='flex flex-col gap-1 items-center p-5'>\n <div className={cn('relative', sizeClasses[hoverSize])}>\n {cachedSrc && imageLoaded ? (\n <img\n src={cachedSrc}\n alt='Profile'\n className={cn('rounded-full border-2 object-cover w-full h-full', borderColor)}\n onError={() => setImageLoaded(false)}\n />\n ) : (\n <div\n className={cn(\n 'bg-primary-100 dark:bg-primary-950 border-2 flex items-center justify-center rounded-full w-full h-full',\n borderColor,\n )}\n >\n <Typography\n size='large'\n variant='semibold'\n appearance='custom'\n className={cn('text-primary-600', initialsFontSizeClasses[hoverSize])}\n >\n {getInitials((firstName || '') + ' ' + (lastName || ''))}\n </Typography>\n </div>\n )}\n\n {statusColor && (\n <div\n className={cn(\n 'absolute bottom-0 right-0 rounded-full border-2 border-white dark:border-black-800',\n indicatorSizes[hoverSize],\n statusColor,\n )}\n />\n )}\n </div>\n <div className='flex flex-row gap-1 items-center justify-center'>\n <Typography size='medium' variant='semibold' className='w-full text-center'>\n {firstName || ''} {lastName || ''}\n </Typography>\n {userDetails?.region && <span>{getFlagComponentRectangleMd(userDetails?.region)}</span>}\n </div>\n\n <Typography size='small' variant='medium' appearance='body'>\n {email || userDetails?.email || ''}\n </Typography>\n </div>\n\n {currentlyEditing ? (\n <div className='px-5 pb-3'>\n <div className='flex items-center gap-3 rounded-lg border border-primary-100 dark:border-primary-900 bg-[rgba(230,241,252,0.60)] dark:bg-primary-950/40 px-[13px] py-[7px]'>\n <div className='flex items-center justify-center shrink-0 w-7 h-7 rounded-[5px] border-[0.4px] border-primary-100 dark:border-primary-900 bg-primary-50 dark:bg-primary-950'>\n <EditOutlinedIcon sx={{ width: 13, height: 13 }} className='text-primary-600 dark:text-primary-500' />\n </div>\n <div className='flex flex-col min-w-0'>\n <Typography\n size='extra-small'\n variant='semibold'\n appearance='custom'\n className='text-2xs leading-4 uppercase tracking-[0.2px] text-primary-600 dark:text-primary-500'\n >\n Currently editing\n </Typography>\n <Typography size='extra-small' variant='semibold' className='truncate'>\n {currentlyEditing}\n </Typography>\n </div>\n </div>\n </div>\n ) : null}\n\n {userId &&\n (isFetchingUserDetails ? (\n <div className='p-5'>\n <Skeleton />\n </div>\n ) : userId && (userDetails?.teams || userDetails?.clearanceLevel || userDetails?.group) ? (\n <div className='flex flex-col gap-4 bg-neutral-50 border-t border-neutral-200 dark:bg-black-700 dark:border-none p-5 rounded-b-lg'>\n <StatusInfoRow isActive={isActive} lastViewedOn={lastViewedOn} />\n {userDetails.username && (\n <InfoRow\n label='Username'\n content={\n <div className='flex gap-2'>\n <Typography size='small' variant='medium' appearance='body'>\n {userDetails.username}\n </Typography>\n </div>\n }\n />\n )}\n\n {userDetails?.teams && userDetails?.teams?.length > 0 && (\n <InfoRow\n label='Team'\n content={\n <div className='flex gap-2'>\n {userDetails?.teams?.length > 0 && (\n <Tag\n key={userDetails?.teams[0]?.id}\n label={userDetails?.teams[0]?.name}\n color={userDetails?.teams[0]?.color || '#e38715'}\n size='md'\n isHashColor\n />\n )}\n {userDetails?.teams?.length >= 2 && (\n <div\n ref={moreTagRef}\n className='relative inline-flex cursor-pointer'\n onMouseEnter={handleShowMore}\n onMouseLeave={handleHideMore}\n onClick={(e) => e.stopPropagation()}\n >\n <Tag key={1} label={`+ ${userDetails?.teams?.length - 1} More`} color='#004f08' size='md' isHashColor />\n\n {showMore && (\n <div\n ref={dropdownRef}\n className={cn(\n 'absolute w-max bg-white dark:text-black-200 dark:bg-black-800 shadow-md border border-neutral-200 dark:border-black-800 rounded-md px-2 z-10 overflow-y-auto max-h-60',\n {\n 'top-full': dropdownPosition.vertical === 'bottom',\n 'bottom-full': dropdownPosition.vertical === 'top',\n 'left-0': dropdownPosition.horizontal === 'left',\n 'right-0': dropdownPosition.horizontal === 'right',\n },\n )}\n onMouseEnter={handleShowMore}\n onMouseLeave={handleHideMore}\n >\n {userDetails?.teams?.slice(1)?.map((team, index) => (\n <div key={team?.id || index} className='my-2'>\n <Tag key={team?.id} label={team?.name} color={team?.color || '#4A5568'} size='md' isHashColor className='w-fit' />\n </div>\n ))}\n </div>\n )}\n </div>\n )}\n </div>\n }\n />\n )}\n\n {userDetails?.group && (\n <InfoRow\n label='Role'\n content={<Tag key={userDetails?.group} label={userDetails?.group} color='#004094' size='md' isHashColor />}\n />\n )}\n\n {userDetails?.clearanceLevel && (\n <InfoRow\n label='Clearance Level'\n content={\n <Tag\n key={String(userDetails?.clearanceLevel)}\n label={`Level ${userDetails?.clearanceLevel}`}\n color='#b30000'\n size='md'\n isHashColor\n />\n }\n />\n )}\n </div>\n ) : (\n <div className='flex items-center justify-center bg-neutral-50 dark:bg-black-700 border-t border-neutral-200 dark:border-black-700 p-5 rounded-b-lg'>\n <Typography className='flex items-center justify-center gap-1' size='extra-small' variant='medium' appearance='body'>\n <WarningRoundedIcon\n sx={{\n height: '16px',\n width: '16px',\n color: '#F04438',\n }}\n />\n No other information found!\n </Typography>\n </div>\n ))}\n </div>\n );\n const containerRef = useRef<HTMLDivElement>(null);\n return (\n <div\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n className={cn('inline-block relative cursor-pointer', className)}\n ref={containerRef}\n >\n <div className={cn('relative', containerClassName || avatarSizeClass)}>\n {cachedSrc && imageLoaded ? (\n <img\n src={cachedSrc}\n alt='Profile'\n className={cn('rounded-full border object-cover w-full h-full', borderColor)}\n onError={() => setImageLoaded(false)}\n />\n ) :\n firstName && lastName ? (\n <div\n className={cn(\n 'bg-primary-100 flex items-center justify-center rounded-full border dark:bg-black-700',\n sizeClasses[size],\n borderColor,\n )}\n >\n <Typography\n size='extra-small'\n variant='semibold'\n appearance='custom'\n className={cn('text-primary-600', initialsFontSizeClasses[size])}\n >\n {getInitials((firstName || '') + ' ' + (lastName || ''))}\n </Typography>\n </div>\n ) : (\n <div className={cn(borderColor, 'p-1 rounded-full bg-neutral-200 dark:bg-black-600 flex items-center justify-center border w-full h-full')}>\n <PersonIcon fill='#98A2B3' />\n </div>\n )}\n\n {statusIndicator && statusColor && (\n <div\n className={cn(\n 'absolute bottom-0 right-0 rounded-full border border-white dark:border-black-800 w-2 h-2',\n\n statusColor,\n )}\n />\n )}\n </div>\n <UserAvatarPopper\n isOpen={visible}\n onClose={() => setVisible(false)}\n anchorEl={containerRef.current}\n className='bg-white dark:bg-black-700 shadow rounded-lg border border-neutral-200 dark:border-black-600'\n >\n {popperContent}\n </UserAvatarPopper>\n </div>\n );\n};\n\nUserAvatar.displayName = 'UserAvatar';\n\n"],"names":["InfoRow","label","content","jsxs","jsx","Typography","UserAvatar","firstName","lastName","email","profilePic","size","hoverSize","containerClassName","enablePopper","className","userId","lastViewedOn","isActive","statusIndicator","userDetails","isFetchingUserDetails","authToken","onHover","currentlyEditing","GroupsIcon","visible","setVisible","useState","imageLoaded","setImageLoaded","avatarSizeClass","sizeClasses","moreTagRef","dropdownRef","dropdownPosition","showMore","handleShowMore","handleHideMore","useDynamicPosition","imageCacheRef","useRef","isRecent","useMemo","date","statusColor","borderColor","indicatorSizes","useEffect","img","token","timerRef","cachedSrc","popperRef","handleMouseEnter","handleMouseLeave","event","popperContent","cn","initialsFontSizeClasses","getInitials","getFlagComponentRectangleMd","EditOutlinedIcon","Skeleton","StatusInfoRow","Tag","e","team","index","WarningRoundedIcon","containerRef","PersonIcon","UserAvatarPopper"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"UserAvatar.cjs.js","sources":["../../../src/components/user-avatar/UserAvatar.tsx"],"sourcesContent":["import EditOutlinedIcon from '@mui/icons-material/EditOutlined';\nimport WarningRoundedIcon from '@mui/icons-material/WarningRounded';\nimport cn from 'classnames';\nimport { type FC, useEffect, useMemo, useRef, useState } from 'react';\n\nimport { Typography } from '../data-display/typography/Typography';\nimport { Tag } from '../data-display/tag/Tag';\nimport { Skeleton } from '../data-display/skeleton/Skeleton';\nimport { getFlagComponentRectangleMd } from '../../utils/countryFlags';\nimport { UserAvatarPopper } from './UserAvatarPopper';\nimport { StatusInfoRow } from './StatusInfoRow';\nimport { sizeClasses, getInitials, initialsFontSizeClasses } from './constants';\nimport { PersonIcon } from './PersonIcon';\nimport { useDynamicPosition } from './useDynamicPosition';\nimport { GroupsIcon } from '../icon';\n\nexport type UserAvatarSize = '2xs' | 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n\nexport type UserDetailsTeam = {\n id?: string;\n name: string;\n color?: string;\n};\n\nexport type UserDetails = {\n email?: string;\n username?: string;\n teams?: UserDetailsTeam[];\n group?: string;\n clearanceLevel?: number | string;\n region?: string;\n};\n\nexport type UserAvatarProps = {\n firstName?: string;\n lastName?: string;\n email?: string;\n enablePopper?: boolean;\n profilePic?: string;\n size?: UserAvatarSize;\n hoverSize?: UserAvatarSize;\n containerClassName?: string;\n className?: string;\n userId?: string;\n lastViewedOn?: string;\n isActive?: boolean;\n statusIndicator?: boolean;\n /** User details to display in the popper - replaces the useTeamMemberFilter hook */\n userDetails?: UserDetails | null;\n /** Whether user details are being fetched */\n isFetchingUserDetails?: boolean;\n /** Optional token for authenticated image loading */\n authToken?: string;\n /** Callback triggered when mouse enters the avatar */\n onHover?: () => void;\n /** Name of the clause / line item the user is currently editing. When set, a highlighted \"Currently editing\" card is shown in the popper. */\n currentlyEditing?: string;\n};\n\nconst InfoRow = ({ label, content }: { label: string; content: React.ReactNode }) => (\n <div className='flex justify-between items-center'>\n <Typography size='small' variant='medium' className='mr-5' appearance='body'>\n {label}\n </Typography>\n {content}\n </div>\n);\n\n/**\n * UserAvatar component for displaying user profile pictures with hover popper\n *\n * @example\n * ```tsx\n * <UserAvatar\n * firstName=\"John\"\n * lastName=\"Doe\"\n * email=\"john@example.com\"\n * profilePic=\"/avatar.jpg\"\n * userDetails={{ teams: [{ name: 'Engineering', color: '#0066cc' }], group: 'Admin' }}\n * />\n * ```\n */\nexport const UserAvatar: FC<UserAvatarProps> = ({\n firstName,\n lastName,\n email,\n profilePic,\n size = 'md',\n hoverSize = 'lg',\n containerClassName = '',\n enablePopper = true,\n className,\n userId,\n lastViewedOn,\n isActive,\n statusIndicator = false,\n userDetails,\n isFetchingUserDetails = false,\n authToken,\n onHover,\n currentlyEditing,\n}) => {\n if (firstName === 'All' && lastName === 'Users') {\n return (\n <div className='p-1 rounded-full bg-primary-100 dark:bg-black-600 flex items-center justify-center'>\n <GroupsIcon className='text-primary-600 dark:text-primary-600 w-4 h-4' />\n </div>\n );\n }\n\n const [visible, setVisible] = useState<boolean>(false);\n const [imageLoaded, setImageLoaded] = useState<boolean>(false);\n\n const avatarSizeClass = sizeClasses[size];\n\n const {\n triggerRef: moreTagRef,\n dropdownRef,\n position: dropdownPosition,\n isVisible: showMore,\n show: handleShowMore,\n hide: handleHideMore,\n } = useDynamicPosition();\n\n const imageCacheRef = useRef<{ [key: string]: string }>({});\n\n const isRecent = useMemo(() => {\n if (isActive || !lastViewedOn) return false;\n const date = new Date(lastViewedOn);\n const now = new Date();\n const diffInHours = (now.getTime() - date.getTime()) / (1000 * 60 * 60);\n return diffInHours < 24;\n }, [isActive, lastViewedOn]);\n\n const getStatusColor = () => {\n if (isActive) return 'bg-primary-600 dark:bg-primary-600';\n if (isRecent) return 'bg-primary-300 dark:bg-primary-300';\n if (lastViewedOn) return 'bg-neutral-400 dark:bg-neutral-400';\n return null;\n };\n\n const statusColor = getStatusColor();\n\n const getBorderColor = () => {\n if (isActive) return 'border-primary-600 dark:border-primary-600';\n if (isRecent) return 'border-primary-300 dark:border-primary-300';\n if (lastViewedOn) return 'border-neutral-400 dark:border-neutral-400';\n return 'border-primary-200 dark:border-neutral-800';\n };\n\n const borderColor = getBorderColor();\n\n const indicatorSizes = {\n '2xs': 'w-1.5 h-1.5',\n xs: 'w-2 h-2',\n sm: 'w-2.5 h-2.5',\n md: 'w-3 h-3',\n lg: 'w-3.5 h-3.5',\n xl: 'w-4 h-4',\n };\n\n useEffect(() => {\n if (profilePic) {\n if (imageCacheRef.current[profilePic]) {\n setImageLoaded(true);\n } else {\n setImageLoaded(false);\n const img = new Image();\n const token = authToken || (typeof localStorage !== 'undefined' ? localStorage.getItem('token') : null);\n img.src = profilePic + (token ? '?token=' + token : '');\n img.onload = () => {\n imageCacheRef.current[profilePic] = img.src;\n setImageLoaded(true);\n };\n img.onerror = () => {\n setImageLoaded(false);\n };\n }\n } else {\n setImageLoaded(false);\n }\n }, [profilePic, authToken]);\n\n useEffect(() => {\n return () => {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n }\n };\n }, []);\n\n const cachedSrc = profilePic ? imageCacheRef.current[profilePic] : undefined;\n\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const popperRef = useRef<HTMLDivElement | null>(null);\n\n const handleMouseEnter = () => {\n onHover?.();\n if (firstName && lastName && enablePopper) {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n }\n timerRef.current = setTimeout(() => {\n setVisible(true);\n }, 300);\n }\n };\n\n const handleMouseLeave = (event: React.MouseEvent) => {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n }\n timerRef.current = setTimeout(() => {\n if (popperRef.current && !popperRef.current.contains(event.relatedTarget as Node)) {\n setVisible(false);\n }\n }, 200);\n };\n\n const popperContent = (\n <div\n ref={popperRef}\n className='bg-white dark:bg-black-800 shadow rounded-lg border border-neutral-200 dark:border-black-700 min-w-[280px]'\n onMouseEnter={() => {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n }\n }}\n onMouseLeave={(event) => handleMouseLeave(event)}\n >\n <div className='flex flex-col gap-1 items-center p-5'>\n <div className={cn('relative', sizeClasses[hoverSize])}>\n {cachedSrc && imageLoaded ? (\n <img\n src={cachedSrc}\n alt='Profile'\n className={cn('rounded-full border-2 object-cover w-full h-full', borderColor)}\n onError={() => setImageLoaded(false)}\n />\n ) : (\n <div\n className={cn(\n 'bg-primary-100 dark:bg-primary-950 border-2 flex items-center justify-center rounded-full w-full h-full',\n borderColor,\n )}\n >\n <Typography\n size='large'\n variant='semibold'\n appearance='custom'\n className={cn('text-primary-600', initialsFontSizeClasses[hoverSize])}\n >\n {getInitials((firstName || '') + ' ' + (lastName || ''))}\n </Typography>\n </div>\n )}\n\n {statusColor && (\n <div\n className={cn(\n 'absolute bottom-0 right-0 rounded-full border-2 border-white dark:border-black-800',\n indicatorSizes[hoverSize],\n statusColor,\n )}\n />\n )}\n </div>\n <div className='flex flex-row gap-1 items-center justify-center'>\n <Typography size='medium' variant='semibold' className='w-full text-center'>\n {firstName || ''} {lastName || ''}\n </Typography>\n {userDetails?.region && <span>{getFlagComponentRectangleMd(userDetails?.region)}</span>}\n </div>\n\n <Typography size='small' variant='medium' appearance='body'>\n {email || userDetails?.email || ''}\n </Typography>\n </div>\n\n {currentlyEditing ? (\n <div className='px-5 pb-3'>\n <div className='flex items-center gap-3 rounded-lg border border-primary-100 dark:border-primary-900 bg-[rgba(230,241,252,0.60)] dark:bg-primary-950/40 px-[13px] py-[7px]'>\n <div className='flex items-center justify-center shrink-0 w-7 h-7 rounded-[5px] border-[0.4px] border-primary-100 dark:border-primary-900 bg-primary-50 dark:bg-primary-950'>\n <EditOutlinedIcon sx={{ width: 13, height: 13 }} className='text-primary-600 dark:text-primary-500' />\n </div>\n <div className='flex flex-col min-w-0'>\n <Typography\n size='extra-small'\n variant='semibold'\n appearance='custom'\n className='text-2xs leading-4 uppercase tracking-[0.2px] text-primary-600 dark:text-primary-500'\n >\n Currently editing\n </Typography>\n <Typography size='extra-small' variant='semibold' className='truncate'>\n {currentlyEditing}\n </Typography>\n </div>\n </div>\n </div>\n ) : null}\n\n {userId &&\n (isFetchingUserDetails ? (\n <div className='p-5'>\n <Skeleton />\n </div>\n ) : userId && (userDetails?.teams || userDetails?.clearanceLevel || userDetails?.group) ? (\n <div className='flex flex-col gap-4 bg-neutral-50 border-t border-neutral-200 dark:bg-black-700 dark:border-none p-5 rounded-b-lg'>\n <StatusInfoRow isActive={isActive} lastViewedOn={lastViewedOn} />\n {userDetails.username && (\n <InfoRow\n label='Username'\n content={\n <div className='flex gap-2'>\n <Typography size='small' variant='medium' appearance='body'>\n {userDetails.username}\n </Typography>\n </div>\n }\n />\n )}\n\n {userDetails?.teams && userDetails?.teams?.length > 0 && (\n <InfoRow\n label='Team'\n content={\n <div className='flex gap-2'>\n {userDetails?.teams?.length > 0 && (\n <Tag\n key={userDetails?.teams[0]?.id}\n label={userDetails?.teams[0]?.name}\n color={userDetails?.teams[0]?.color || '#e38715'}\n size='md'\n isHashColor\n />\n )}\n {userDetails?.teams?.length >= 2 && (\n <div\n ref={moreTagRef}\n className='relative inline-flex cursor-pointer'\n onMouseEnter={handleShowMore}\n onMouseLeave={handleHideMore}\n onClick={(e) => e.stopPropagation()}\n >\n <Tag key={1} label={`+ ${userDetails?.teams?.length - 1} More`} color='#004f08' size='md' isHashColor />\n\n {showMore && (\n <div\n ref={dropdownRef}\n className={cn(\n 'absolute w-max bg-white dark:text-black-200 dark:bg-black-800 shadow-md border border-neutral-200 dark:border-black-800 rounded-md px-2 z-10 overflow-y-auto max-h-60',\n {\n 'top-full': dropdownPosition.vertical === 'bottom',\n 'bottom-full': dropdownPosition.vertical === 'top',\n 'left-0': dropdownPosition.horizontal === 'left',\n 'right-0': dropdownPosition.horizontal === 'right',\n },\n )}\n onMouseEnter={handleShowMore}\n onMouseLeave={handleHideMore}\n >\n <div className='flex flex-wrap gap-2 py-2 max-w-[320px]'>\n {userDetails?.teams?.slice(1)?.map((team, index) => (\n <Tag\n key={team?.id || index}\n label={team?.name}\n color={team?.color || '#4A5568'}\n size='md'\n isHashColor\n className='w-fit'\n />\n ))}\n </div>\n </div>\n )}\n </div>\n )}\n </div>\n }\n />\n )}\n\n {userDetails?.group && (\n <InfoRow\n label='Role'\n content={<Tag key={userDetails?.group} label={userDetails?.group} color='#004094' size='md' isHashColor />}\n />\n )}\n\n {userDetails?.clearanceLevel && (\n <InfoRow\n label='Clearance Level'\n content={\n <Tag\n key={String(userDetails?.clearanceLevel)}\n label={`Level ${userDetails?.clearanceLevel}`}\n color='#b30000'\n size='md'\n isHashColor\n />\n }\n />\n )}\n </div>\n ) : (\n <div className='flex items-center justify-center bg-neutral-50 dark:bg-black-700 border-t border-neutral-200 dark:border-black-700 p-5 rounded-b-lg'>\n <Typography className='flex items-center justify-center gap-1' size='extra-small' variant='medium' appearance='body'>\n <WarningRoundedIcon\n sx={{\n height: '16px',\n width: '16px',\n color: '#F04438',\n }}\n />\n No other information found!\n </Typography>\n </div>\n ))}\n </div>\n );\n const containerRef = useRef<HTMLDivElement>(null);\n return (\n <div\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n className={cn('inline-block relative cursor-pointer', className)}\n ref={containerRef}\n >\n <div className={cn('relative', containerClassName || avatarSizeClass)}>\n {cachedSrc && imageLoaded ? (\n <img\n src={cachedSrc}\n alt='Profile'\n className={cn('rounded-full border object-cover w-full h-full', borderColor)}\n onError={() => setImageLoaded(false)}\n />\n ) :\n firstName && lastName ? (\n <div\n className={cn(\n 'bg-primary-100 flex items-center justify-center rounded-full border dark:bg-black-700',\n sizeClasses[size],\n borderColor,\n )}\n >\n <Typography\n size='extra-small'\n variant='semibold'\n appearance='custom'\n className={cn('text-primary-600', initialsFontSizeClasses[size])}\n >\n {getInitials((firstName || '') + ' ' + (lastName || ''))}\n </Typography>\n </div>\n ) : (\n <div className={cn(borderColor, 'p-1 rounded-full bg-neutral-200 dark:bg-black-600 flex items-center justify-center border w-full h-full')}>\n <PersonIcon fill='#98A2B3' />\n </div>\n )}\n\n {statusIndicator && statusColor && (\n <div\n className={cn(\n 'absolute bottom-0 right-0 rounded-full border border-white dark:border-black-800 w-2 h-2',\n\n statusColor,\n )}\n />\n )}\n </div>\n <UserAvatarPopper\n isOpen={visible}\n onClose={() => setVisible(false)}\n anchorEl={containerRef.current}\n className='bg-white dark:bg-black-700 shadow rounded-lg border border-neutral-200 dark:border-black-600'\n >\n {popperContent}\n </UserAvatarPopper>\n </div>\n );\n};\n\nUserAvatar.displayName = 'UserAvatar';\n\n"],"names":["InfoRow","label","content","jsxs","jsx","Typography","UserAvatar","firstName","lastName","email","profilePic","size","hoverSize","containerClassName","enablePopper","className","userId","lastViewedOn","isActive","statusIndicator","userDetails","isFetchingUserDetails","authToken","onHover","currentlyEditing","GroupsIcon","visible","setVisible","useState","imageLoaded","setImageLoaded","avatarSizeClass","sizeClasses","moreTagRef","dropdownRef","dropdownPosition","showMore","handleShowMore","handleHideMore","useDynamicPosition","imageCacheRef","useRef","isRecent","useMemo","date","statusColor","borderColor","indicatorSizes","useEffect","img","token","timerRef","cachedSrc","popperRef","handleMouseEnter","handleMouseLeave","event","popperContent","cn","initialsFontSizeClasses","getInitials","getFlagComponentRectangleMd","EditOutlinedIcon","Skeleton","StatusInfoRow","Tag","e","team","index","WarningRoundedIcon","containerRef","PersonIcon","UserAvatarPopper"],"mappings":"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"}
|
|
@@ -208,7 +208,17 @@ const k = ({ label: i, content: d }) => /* @__PURE__ */ o("div", { className: "f
|
|
|
208
208
|
),
|
|
209
209
|
onMouseEnter: I,
|
|
210
210
|
onMouseLeave: S,
|
|
211
|
-
children:
|
|
211
|
+
children: /* @__PURE__ */ e("div", { className: "flex flex-wrap gap-2 py-2 max-w-[320px]", children: r?.teams?.slice(1)?.map((a, f) => /* @__PURE__ */ e(
|
|
212
|
+
p,
|
|
213
|
+
{
|
|
214
|
+
label: a?.name,
|
|
215
|
+
color: a?.color || "#4A5568",
|
|
216
|
+
size: "md",
|
|
217
|
+
isHashColor: !0,
|
|
218
|
+
className: "w-fit"
|
|
219
|
+
},
|
|
220
|
+
a?.id || f
|
|
221
|
+
)) })
|
|
212
222
|
}
|
|
213
223
|
)
|
|
214
224
|
]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UserAvatar.es.js","sources":["../../../src/components/user-avatar/UserAvatar.tsx"],"sourcesContent":["import EditOutlinedIcon from '@mui/icons-material/EditOutlined';\nimport WarningRoundedIcon from '@mui/icons-material/WarningRounded';\nimport cn from 'classnames';\nimport { type FC, useEffect, useMemo, useRef, useState } from 'react';\n\nimport { Typography } from '../data-display/typography/Typography';\nimport { Tag } from '../data-display/tag/Tag';\nimport { Skeleton } from '../data-display/skeleton/Skeleton';\nimport { getFlagComponentRectangleMd } from '../../utils/countryFlags';\nimport { UserAvatarPopper } from './UserAvatarPopper';\nimport { StatusInfoRow } from './StatusInfoRow';\nimport { sizeClasses, getInitials, initialsFontSizeClasses } from './constants';\nimport { PersonIcon } from './PersonIcon';\nimport { useDynamicPosition } from './useDynamicPosition';\nimport { GroupsIcon } from '../icon';\n\nexport type UserAvatarSize = '2xs' | 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n\nexport type UserDetailsTeam = {\n id?: string;\n name: string;\n color?: string;\n};\n\nexport type UserDetails = {\n email?: string;\n username?: string;\n teams?: UserDetailsTeam[];\n group?: string;\n clearanceLevel?: number | string;\n region?: string;\n};\n\nexport type UserAvatarProps = {\n firstName?: string;\n lastName?: string;\n email?: string;\n enablePopper?: boolean;\n profilePic?: string;\n size?: UserAvatarSize;\n hoverSize?: UserAvatarSize;\n containerClassName?: string;\n className?: string;\n userId?: string;\n lastViewedOn?: string;\n isActive?: boolean;\n statusIndicator?: boolean;\n /** User details to display in the popper - replaces the useTeamMemberFilter hook */\n userDetails?: UserDetails | null;\n /** Whether user details are being fetched */\n isFetchingUserDetails?: boolean;\n /** Optional token for authenticated image loading */\n authToken?: string;\n /** Callback triggered when mouse enters the avatar */\n onHover?: () => void;\n /** Name of the clause / line item the user is currently editing. When set, a highlighted \"Currently editing\" card is shown in the popper. */\n currentlyEditing?: string;\n};\n\nconst InfoRow = ({ label, content }: { label: string; content: React.ReactNode }) => (\n <div className='flex justify-between items-center'>\n <Typography size='small' variant='medium' className='mr-5' appearance='body'>\n {label}\n </Typography>\n {content}\n </div>\n);\n\n/**\n * UserAvatar component for displaying user profile pictures with hover popper\n *\n * @example\n * ```tsx\n * <UserAvatar\n * firstName=\"John\"\n * lastName=\"Doe\"\n * email=\"john@example.com\"\n * profilePic=\"/avatar.jpg\"\n * userDetails={{ teams: [{ name: 'Engineering', color: '#0066cc' }], group: 'Admin' }}\n * />\n * ```\n */\nexport const UserAvatar: FC<UserAvatarProps> = ({\n firstName,\n lastName,\n email,\n profilePic,\n size = 'md',\n hoverSize = 'lg',\n containerClassName = '',\n enablePopper = true,\n className,\n userId,\n lastViewedOn,\n isActive,\n statusIndicator = false,\n userDetails,\n isFetchingUserDetails = false,\n authToken,\n onHover,\n currentlyEditing,\n}) => {\n if (firstName === 'All' && lastName === 'Users') {\n return (\n <div className='p-1 rounded-full bg-primary-100 dark:bg-black-600 flex items-center justify-center'>\n <GroupsIcon className='text-primary-600 dark:text-primary-600 w-4 h-4' />\n </div>\n );\n }\n\n const [visible, setVisible] = useState<boolean>(false);\n const [imageLoaded, setImageLoaded] = useState<boolean>(false);\n\n const avatarSizeClass = sizeClasses[size];\n\n const {\n triggerRef: moreTagRef,\n dropdownRef,\n position: dropdownPosition,\n isVisible: showMore,\n show: handleShowMore,\n hide: handleHideMore,\n } = useDynamicPosition();\n\n const imageCacheRef = useRef<{ [key: string]: string }>({});\n\n const isRecent = useMemo(() => {\n if (isActive || !lastViewedOn) return false;\n const date = new Date(lastViewedOn);\n const now = new Date();\n const diffInHours = (now.getTime() - date.getTime()) / (1000 * 60 * 60);\n return diffInHours < 24;\n }, [isActive, lastViewedOn]);\n\n const getStatusColor = () => {\n if (isActive) return 'bg-primary-600 dark:bg-primary-600';\n if (isRecent) return 'bg-primary-300 dark:bg-primary-300';\n if (lastViewedOn) return 'bg-neutral-400 dark:bg-neutral-400';\n return null;\n };\n\n const statusColor = getStatusColor();\n\n const getBorderColor = () => {\n if (isActive) return 'border-primary-600 dark:border-primary-600';\n if (isRecent) return 'border-primary-300 dark:border-primary-300';\n if (lastViewedOn) return 'border-neutral-400 dark:border-neutral-400';\n return 'border-primary-200 dark:border-neutral-800';\n };\n\n const borderColor = getBorderColor();\n\n const indicatorSizes = {\n '2xs': 'w-1.5 h-1.5',\n xs: 'w-2 h-2',\n sm: 'w-2.5 h-2.5',\n md: 'w-3 h-3',\n lg: 'w-3.5 h-3.5',\n xl: 'w-4 h-4',\n };\n\n useEffect(() => {\n if (profilePic) {\n if (imageCacheRef.current[profilePic]) {\n setImageLoaded(true);\n } else {\n setImageLoaded(false);\n const img = new Image();\n const token = authToken || (typeof localStorage !== 'undefined' ? localStorage.getItem('token') : null);\n img.src = profilePic + (token ? '?token=' + token : '');\n img.onload = () => {\n imageCacheRef.current[profilePic] = img.src;\n setImageLoaded(true);\n };\n img.onerror = () => {\n setImageLoaded(false);\n };\n }\n } else {\n setImageLoaded(false);\n }\n }, [profilePic, authToken]);\n\n useEffect(() => {\n return () => {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n }\n };\n }, []);\n\n const cachedSrc = profilePic ? imageCacheRef.current[profilePic] : undefined;\n\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const popperRef = useRef<HTMLDivElement | null>(null);\n\n const handleMouseEnter = () => {\n onHover?.();\n if (firstName && lastName && enablePopper) {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n }\n timerRef.current = setTimeout(() => {\n setVisible(true);\n }, 300);\n }\n };\n\n const handleMouseLeave = (event: React.MouseEvent) => {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n }\n timerRef.current = setTimeout(() => {\n if (popperRef.current && !popperRef.current.contains(event.relatedTarget as Node)) {\n setVisible(false);\n }\n }, 200);\n };\n\n const popperContent = (\n <div\n ref={popperRef}\n className='bg-white dark:bg-black-800 shadow rounded-lg border border-neutral-200 dark:border-black-700 min-w-[280px]'\n onMouseEnter={() => {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n }\n }}\n onMouseLeave={(event) => handleMouseLeave(event)}\n >\n <div className='flex flex-col gap-1 items-center p-5'>\n <div className={cn('relative', sizeClasses[hoverSize])}>\n {cachedSrc && imageLoaded ? (\n <img\n src={cachedSrc}\n alt='Profile'\n className={cn('rounded-full border-2 object-cover w-full h-full', borderColor)}\n onError={() => setImageLoaded(false)}\n />\n ) : (\n <div\n className={cn(\n 'bg-primary-100 dark:bg-primary-950 border-2 flex items-center justify-center rounded-full w-full h-full',\n borderColor,\n )}\n >\n <Typography\n size='large'\n variant='semibold'\n appearance='custom'\n className={cn('text-primary-600', initialsFontSizeClasses[hoverSize])}\n >\n {getInitials((firstName || '') + ' ' + (lastName || ''))}\n </Typography>\n </div>\n )}\n\n {statusColor && (\n <div\n className={cn(\n 'absolute bottom-0 right-0 rounded-full border-2 border-white dark:border-black-800',\n indicatorSizes[hoverSize],\n statusColor,\n )}\n />\n )}\n </div>\n <div className='flex flex-row gap-1 items-center justify-center'>\n <Typography size='medium' variant='semibold' className='w-full text-center'>\n {firstName || ''} {lastName || ''}\n </Typography>\n {userDetails?.region && <span>{getFlagComponentRectangleMd(userDetails?.region)}</span>}\n </div>\n\n <Typography size='small' variant='medium' appearance='body'>\n {email || userDetails?.email || ''}\n </Typography>\n </div>\n\n {currentlyEditing ? (\n <div className='px-5 pb-3'>\n <div className='flex items-center gap-3 rounded-lg border border-primary-100 dark:border-primary-900 bg-[rgba(230,241,252,0.60)] dark:bg-primary-950/40 px-[13px] py-[7px]'>\n <div className='flex items-center justify-center shrink-0 w-7 h-7 rounded-[5px] border-[0.4px] border-primary-100 dark:border-primary-900 bg-primary-50 dark:bg-primary-950'>\n <EditOutlinedIcon sx={{ width: 13, height: 13 }} className='text-primary-600 dark:text-primary-500' />\n </div>\n <div className='flex flex-col min-w-0'>\n <Typography\n size='extra-small'\n variant='semibold'\n appearance='custom'\n className='text-2xs leading-4 uppercase tracking-[0.2px] text-primary-600 dark:text-primary-500'\n >\n Currently editing\n </Typography>\n <Typography size='extra-small' variant='semibold' className='truncate'>\n {currentlyEditing}\n </Typography>\n </div>\n </div>\n </div>\n ) : null}\n\n {userId &&\n (isFetchingUserDetails ? (\n <div className='p-5'>\n <Skeleton />\n </div>\n ) : userId && (userDetails?.teams || userDetails?.clearanceLevel || userDetails?.group) ? (\n <div className='flex flex-col gap-4 bg-neutral-50 border-t border-neutral-200 dark:bg-black-700 dark:border-none p-5 rounded-b-lg'>\n <StatusInfoRow isActive={isActive} lastViewedOn={lastViewedOn} />\n {userDetails.username && (\n <InfoRow\n label='Username'\n content={\n <div className='flex gap-2'>\n <Typography size='small' variant='medium' appearance='body'>\n {userDetails.username}\n </Typography>\n </div>\n }\n />\n )}\n\n {userDetails?.teams && userDetails?.teams?.length > 0 && (\n <InfoRow\n label='Team'\n content={\n <div className='flex gap-2'>\n {userDetails?.teams?.length > 0 && (\n <Tag\n key={userDetails?.teams[0]?.id}\n label={userDetails?.teams[0]?.name}\n color={userDetails?.teams[0]?.color || '#e38715'}\n size='md'\n isHashColor\n />\n )}\n {userDetails?.teams?.length >= 2 && (\n <div\n ref={moreTagRef}\n className='relative inline-flex cursor-pointer'\n onMouseEnter={handleShowMore}\n onMouseLeave={handleHideMore}\n onClick={(e) => e.stopPropagation()}\n >\n <Tag key={1} label={`+ ${userDetails?.teams?.length - 1} More`} color='#004f08' size='md' isHashColor />\n\n {showMore && (\n <div\n ref={dropdownRef}\n className={cn(\n 'absolute w-max bg-white dark:text-black-200 dark:bg-black-800 shadow-md border border-neutral-200 dark:border-black-800 rounded-md px-2 z-10 overflow-y-auto max-h-60',\n {\n 'top-full': dropdownPosition.vertical === 'bottom',\n 'bottom-full': dropdownPosition.vertical === 'top',\n 'left-0': dropdownPosition.horizontal === 'left',\n 'right-0': dropdownPosition.horizontal === 'right',\n },\n )}\n onMouseEnter={handleShowMore}\n onMouseLeave={handleHideMore}\n >\n {userDetails?.teams?.slice(1)?.map((team, index) => (\n <div key={team?.id || index} className='my-2'>\n <Tag key={team?.id} label={team?.name} color={team?.color || '#4A5568'} size='md' isHashColor className='w-fit' />\n </div>\n ))}\n </div>\n )}\n </div>\n )}\n </div>\n }\n />\n )}\n\n {userDetails?.group && (\n <InfoRow\n label='Role'\n content={<Tag key={userDetails?.group} label={userDetails?.group} color='#004094' size='md' isHashColor />}\n />\n )}\n\n {userDetails?.clearanceLevel && (\n <InfoRow\n label='Clearance Level'\n content={\n <Tag\n key={String(userDetails?.clearanceLevel)}\n label={`Level ${userDetails?.clearanceLevel}`}\n color='#b30000'\n size='md'\n isHashColor\n />\n }\n />\n )}\n </div>\n ) : (\n <div className='flex items-center justify-center bg-neutral-50 dark:bg-black-700 border-t border-neutral-200 dark:border-black-700 p-5 rounded-b-lg'>\n <Typography className='flex items-center justify-center gap-1' size='extra-small' variant='medium' appearance='body'>\n <WarningRoundedIcon\n sx={{\n height: '16px',\n width: '16px',\n color: '#F04438',\n }}\n />\n No other information found!\n </Typography>\n </div>\n ))}\n </div>\n );\n const containerRef = useRef<HTMLDivElement>(null);\n return (\n <div\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n className={cn('inline-block relative cursor-pointer', className)}\n ref={containerRef}\n >\n <div className={cn('relative', containerClassName || avatarSizeClass)}>\n {cachedSrc && imageLoaded ? (\n <img\n src={cachedSrc}\n alt='Profile'\n className={cn('rounded-full border object-cover w-full h-full', borderColor)}\n onError={() => setImageLoaded(false)}\n />\n ) :\n firstName && lastName ? (\n <div\n className={cn(\n 'bg-primary-100 flex items-center justify-center rounded-full border dark:bg-black-700',\n sizeClasses[size],\n borderColor,\n )}\n >\n <Typography\n size='extra-small'\n variant='semibold'\n appearance='custom'\n className={cn('text-primary-600', initialsFontSizeClasses[size])}\n >\n {getInitials((firstName || '') + ' ' + (lastName || ''))}\n </Typography>\n </div>\n ) : (\n <div className={cn(borderColor, 'p-1 rounded-full bg-neutral-200 dark:bg-black-600 flex items-center justify-center border w-full h-full')}>\n <PersonIcon fill='#98A2B3' />\n </div>\n )}\n\n {statusIndicator && statusColor && (\n <div\n className={cn(\n 'absolute bottom-0 right-0 rounded-full border border-white dark:border-black-800 w-2 h-2',\n\n statusColor,\n )}\n />\n )}\n </div>\n <UserAvatarPopper\n isOpen={visible}\n onClose={() => setVisible(false)}\n anchorEl={containerRef.current}\n className='bg-white dark:bg-black-700 shadow rounded-lg border border-neutral-200 dark:border-black-600'\n >\n {popperContent}\n </UserAvatarPopper>\n </div>\n );\n};\n\nUserAvatar.displayName = 'UserAvatar';\n\n"],"names":["InfoRow","label","content","jsxs","jsx","Typography","UserAvatar","firstName","lastName","email","profilePic","size","hoverSize","containerClassName","enablePopper","className","userId","lastViewedOn","isActive","statusIndicator","userDetails","isFetchingUserDetails","authToken","onHover","currentlyEditing","GroupsIcon","visible","setVisible","useState","imageLoaded","setImageLoaded","avatarSizeClass","sizeClasses","moreTagRef","dropdownRef","dropdownPosition","showMore","handleShowMore","handleHideMore","useDynamicPosition","imageCacheRef","useRef","isRecent","useMemo","date","statusColor","borderColor","indicatorSizes","useEffect","img","token","timerRef","cachedSrc","popperRef","handleMouseEnter","handleMouseLeave","event","popperContent","cn","initialsFontSizeClasses","getInitials","getFlagComponentRectangleMd","EditOutlinedIcon","Skeleton","StatusInfoRow","Tag","e","team","index","WarningRoundedIcon","containerRef","PersonIcon","UserAvatarPopper"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"UserAvatar.es.js","sources":["../../../src/components/user-avatar/UserAvatar.tsx"],"sourcesContent":["import EditOutlinedIcon from '@mui/icons-material/EditOutlined';\nimport WarningRoundedIcon from '@mui/icons-material/WarningRounded';\nimport cn from 'classnames';\nimport { type FC, useEffect, useMemo, useRef, useState } from 'react';\n\nimport { Typography } from '../data-display/typography/Typography';\nimport { Tag } from '../data-display/tag/Tag';\nimport { Skeleton } from '../data-display/skeleton/Skeleton';\nimport { getFlagComponentRectangleMd } from '../../utils/countryFlags';\nimport { UserAvatarPopper } from './UserAvatarPopper';\nimport { StatusInfoRow } from './StatusInfoRow';\nimport { sizeClasses, getInitials, initialsFontSizeClasses } from './constants';\nimport { PersonIcon } from './PersonIcon';\nimport { useDynamicPosition } from './useDynamicPosition';\nimport { GroupsIcon } from '../icon';\n\nexport type UserAvatarSize = '2xs' | 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n\nexport type UserDetailsTeam = {\n id?: string;\n name: string;\n color?: string;\n};\n\nexport type UserDetails = {\n email?: string;\n username?: string;\n teams?: UserDetailsTeam[];\n group?: string;\n clearanceLevel?: number | string;\n region?: string;\n};\n\nexport type UserAvatarProps = {\n firstName?: string;\n lastName?: string;\n email?: string;\n enablePopper?: boolean;\n profilePic?: string;\n size?: UserAvatarSize;\n hoverSize?: UserAvatarSize;\n containerClassName?: string;\n className?: string;\n userId?: string;\n lastViewedOn?: string;\n isActive?: boolean;\n statusIndicator?: boolean;\n /** User details to display in the popper - replaces the useTeamMemberFilter hook */\n userDetails?: UserDetails | null;\n /** Whether user details are being fetched */\n isFetchingUserDetails?: boolean;\n /** Optional token for authenticated image loading */\n authToken?: string;\n /** Callback triggered when mouse enters the avatar */\n onHover?: () => void;\n /** Name of the clause / line item the user is currently editing. When set, a highlighted \"Currently editing\" card is shown in the popper. */\n currentlyEditing?: string;\n};\n\nconst InfoRow = ({ label, content }: { label: string; content: React.ReactNode }) => (\n <div className='flex justify-between items-center'>\n <Typography size='small' variant='medium' className='mr-5' appearance='body'>\n {label}\n </Typography>\n {content}\n </div>\n);\n\n/**\n * UserAvatar component for displaying user profile pictures with hover popper\n *\n * @example\n * ```tsx\n * <UserAvatar\n * firstName=\"John\"\n * lastName=\"Doe\"\n * email=\"john@example.com\"\n * profilePic=\"/avatar.jpg\"\n * userDetails={{ teams: [{ name: 'Engineering', color: '#0066cc' }], group: 'Admin' }}\n * />\n * ```\n */\nexport const UserAvatar: FC<UserAvatarProps> = ({\n firstName,\n lastName,\n email,\n profilePic,\n size = 'md',\n hoverSize = 'lg',\n containerClassName = '',\n enablePopper = true,\n className,\n userId,\n lastViewedOn,\n isActive,\n statusIndicator = false,\n userDetails,\n isFetchingUserDetails = false,\n authToken,\n onHover,\n currentlyEditing,\n}) => {\n if (firstName === 'All' && lastName === 'Users') {\n return (\n <div className='p-1 rounded-full bg-primary-100 dark:bg-black-600 flex items-center justify-center'>\n <GroupsIcon className='text-primary-600 dark:text-primary-600 w-4 h-4' />\n </div>\n );\n }\n\n const [visible, setVisible] = useState<boolean>(false);\n const [imageLoaded, setImageLoaded] = useState<boolean>(false);\n\n const avatarSizeClass = sizeClasses[size];\n\n const {\n triggerRef: moreTagRef,\n dropdownRef,\n position: dropdownPosition,\n isVisible: showMore,\n show: handleShowMore,\n hide: handleHideMore,\n } = useDynamicPosition();\n\n const imageCacheRef = useRef<{ [key: string]: string }>({});\n\n const isRecent = useMemo(() => {\n if (isActive || !lastViewedOn) return false;\n const date = new Date(lastViewedOn);\n const now = new Date();\n const diffInHours = (now.getTime() - date.getTime()) / (1000 * 60 * 60);\n return diffInHours < 24;\n }, [isActive, lastViewedOn]);\n\n const getStatusColor = () => {\n if (isActive) return 'bg-primary-600 dark:bg-primary-600';\n if (isRecent) return 'bg-primary-300 dark:bg-primary-300';\n if (lastViewedOn) return 'bg-neutral-400 dark:bg-neutral-400';\n return null;\n };\n\n const statusColor = getStatusColor();\n\n const getBorderColor = () => {\n if (isActive) return 'border-primary-600 dark:border-primary-600';\n if (isRecent) return 'border-primary-300 dark:border-primary-300';\n if (lastViewedOn) return 'border-neutral-400 dark:border-neutral-400';\n return 'border-primary-200 dark:border-neutral-800';\n };\n\n const borderColor = getBorderColor();\n\n const indicatorSizes = {\n '2xs': 'w-1.5 h-1.5',\n xs: 'w-2 h-2',\n sm: 'w-2.5 h-2.5',\n md: 'w-3 h-3',\n lg: 'w-3.5 h-3.5',\n xl: 'w-4 h-4',\n };\n\n useEffect(() => {\n if (profilePic) {\n if (imageCacheRef.current[profilePic]) {\n setImageLoaded(true);\n } else {\n setImageLoaded(false);\n const img = new Image();\n const token = authToken || (typeof localStorage !== 'undefined' ? localStorage.getItem('token') : null);\n img.src = profilePic + (token ? '?token=' + token : '');\n img.onload = () => {\n imageCacheRef.current[profilePic] = img.src;\n setImageLoaded(true);\n };\n img.onerror = () => {\n setImageLoaded(false);\n };\n }\n } else {\n setImageLoaded(false);\n }\n }, [profilePic, authToken]);\n\n useEffect(() => {\n return () => {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n }\n };\n }, []);\n\n const cachedSrc = profilePic ? imageCacheRef.current[profilePic] : undefined;\n\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const popperRef = useRef<HTMLDivElement | null>(null);\n\n const handleMouseEnter = () => {\n onHover?.();\n if (firstName && lastName && enablePopper) {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n }\n timerRef.current = setTimeout(() => {\n setVisible(true);\n }, 300);\n }\n };\n\n const handleMouseLeave = (event: React.MouseEvent) => {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n }\n timerRef.current = setTimeout(() => {\n if (popperRef.current && !popperRef.current.contains(event.relatedTarget as Node)) {\n setVisible(false);\n }\n }, 200);\n };\n\n const popperContent = (\n <div\n ref={popperRef}\n className='bg-white dark:bg-black-800 shadow rounded-lg border border-neutral-200 dark:border-black-700 min-w-[280px]'\n onMouseEnter={() => {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n }\n }}\n onMouseLeave={(event) => handleMouseLeave(event)}\n >\n <div className='flex flex-col gap-1 items-center p-5'>\n <div className={cn('relative', sizeClasses[hoverSize])}>\n {cachedSrc && imageLoaded ? (\n <img\n src={cachedSrc}\n alt='Profile'\n className={cn('rounded-full border-2 object-cover w-full h-full', borderColor)}\n onError={() => setImageLoaded(false)}\n />\n ) : (\n <div\n className={cn(\n 'bg-primary-100 dark:bg-primary-950 border-2 flex items-center justify-center rounded-full w-full h-full',\n borderColor,\n )}\n >\n <Typography\n size='large'\n variant='semibold'\n appearance='custom'\n className={cn('text-primary-600', initialsFontSizeClasses[hoverSize])}\n >\n {getInitials((firstName || '') + ' ' + (lastName || ''))}\n </Typography>\n </div>\n )}\n\n {statusColor && (\n <div\n className={cn(\n 'absolute bottom-0 right-0 rounded-full border-2 border-white dark:border-black-800',\n indicatorSizes[hoverSize],\n statusColor,\n )}\n />\n )}\n </div>\n <div className='flex flex-row gap-1 items-center justify-center'>\n <Typography size='medium' variant='semibold' className='w-full text-center'>\n {firstName || ''} {lastName || ''}\n </Typography>\n {userDetails?.region && <span>{getFlagComponentRectangleMd(userDetails?.region)}</span>}\n </div>\n\n <Typography size='small' variant='medium' appearance='body'>\n {email || userDetails?.email || ''}\n </Typography>\n </div>\n\n {currentlyEditing ? (\n <div className='px-5 pb-3'>\n <div className='flex items-center gap-3 rounded-lg border border-primary-100 dark:border-primary-900 bg-[rgba(230,241,252,0.60)] dark:bg-primary-950/40 px-[13px] py-[7px]'>\n <div className='flex items-center justify-center shrink-0 w-7 h-7 rounded-[5px] border-[0.4px] border-primary-100 dark:border-primary-900 bg-primary-50 dark:bg-primary-950'>\n <EditOutlinedIcon sx={{ width: 13, height: 13 }} className='text-primary-600 dark:text-primary-500' />\n </div>\n <div className='flex flex-col min-w-0'>\n <Typography\n size='extra-small'\n variant='semibold'\n appearance='custom'\n className='text-2xs leading-4 uppercase tracking-[0.2px] text-primary-600 dark:text-primary-500'\n >\n Currently editing\n </Typography>\n <Typography size='extra-small' variant='semibold' className='truncate'>\n {currentlyEditing}\n </Typography>\n </div>\n </div>\n </div>\n ) : null}\n\n {userId &&\n (isFetchingUserDetails ? (\n <div className='p-5'>\n <Skeleton />\n </div>\n ) : userId && (userDetails?.teams || userDetails?.clearanceLevel || userDetails?.group) ? (\n <div className='flex flex-col gap-4 bg-neutral-50 border-t border-neutral-200 dark:bg-black-700 dark:border-none p-5 rounded-b-lg'>\n <StatusInfoRow isActive={isActive} lastViewedOn={lastViewedOn} />\n {userDetails.username && (\n <InfoRow\n label='Username'\n content={\n <div className='flex gap-2'>\n <Typography size='small' variant='medium' appearance='body'>\n {userDetails.username}\n </Typography>\n </div>\n }\n />\n )}\n\n {userDetails?.teams && userDetails?.teams?.length > 0 && (\n <InfoRow\n label='Team'\n content={\n <div className='flex gap-2'>\n {userDetails?.teams?.length > 0 && (\n <Tag\n key={userDetails?.teams[0]?.id}\n label={userDetails?.teams[0]?.name}\n color={userDetails?.teams[0]?.color || '#e38715'}\n size='md'\n isHashColor\n />\n )}\n {userDetails?.teams?.length >= 2 && (\n <div\n ref={moreTagRef}\n className='relative inline-flex cursor-pointer'\n onMouseEnter={handleShowMore}\n onMouseLeave={handleHideMore}\n onClick={(e) => e.stopPropagation()}\n >\n <Tag key={1} label={`+ ${userDetails?.teams?.length - 1} More`} color='#004f08' size='md' isHashColor />\n\n {showMore && (\n <div\n ref={dropdownRef}\n className={cn(\n 'absolute w-max bg-white dark:text-black-200 dark:bg-black-800 shadow-md border border-neutral-200 dark:border-black-800 rounded-md px-2 z-10 overflow-y-auto max-h-60',\n {\n 'top-full': dropdownPosition.vertical === 'bottom',\n 'bottom-full': dropdownPosition.vertical === 'top',\n 'left-0': dropdownPosition.horizontal === 'left',\n 'right-0': dropdownPosition.horizontal === 'right',\n },\n )}\n onMouseEnter={handleShowMore}\n onMouseLeave={handleHideMore}\n >\n <div className='flex flex-wrap gap-2 py-2 max-w-[320px]'>\n {userDetails?.teams?.slice(1)?.map((team, index) => (\n <Tag\n key={team?.id || index}\n label={team?.name}\n color={team?.color || '#4A5568'}\n size='md'\n isHashColor\n className='w-fit'\n />\n ))}\n </div>\n </div>\n )}\n </div>\n )}\n </div>\n }\n />\n )}\n\n {userDetails?.group && (\n <InfoRow\n label='Role'\n content={<Tag key={userDetails?.group} label={userDetails?.group} color='#004094' size='md' isHashColor />}\n />\n )}\n\n {userDetails?.clearanceLevel && (\n <InfoRow\n label='Clearance Level'\n content={\n <Tag\n key={String(userDetails?.clearanceLevel)}\n label={`Level ${userDetails?.clearanceLevel}`}\n color='#b30000'\n size='md'\n isHashColor\n />\n }\n />\n )}\n </div>\n ) : (\n <div className='flex items-center justify-center bg-neutral-50 dark:bg-black-700 border-t border-neutral-200 dark:border-black-700 p-5 rounded-b-lg'>\n <Typography className='flex items-center justify-center gap-1' size='extra-small' variant='medium' appearance='body'>\n <WarningRoundedIcon\n sx={{\n height: '16px',\n width: '16px',\n color: '#F04438',\n }}\n />\n No other information found!\n </Typography>\n </div>\n ))}\n </div>\n );\n const containerRef = useRef<HTMLDivElement>(null);\n return (\n <div\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n className={cn('inline-block relative cursor-pointer', className)}\n ref={containerRef}\n >\n <div className={cn('relative', containerClassName || avatarSizeClass)}>\n {cachedSrc && imageLoaded ? (\n <img\n src={cachedSrc}\n alt='Profile'\n className={cn('rounded-full border object-cover w-full h-full', borderColor)}\n onError={() => setImageLoaded(false)}\n />\n ) :\n firstName && lastName ? (\n <div\n className={cn(\n 'bg-primary-100 flex items-center justify-center rounded-full border dark:bg-black-700',\n sizeClasses[size],\n borderColor,\n )}\n >\n <Typography\n size='extra-small'\n variant='semibold'\n appearance='custom'\n className={cn('text-primary-600', initialsFontSizeClasses[size])}\n >\n {getInitials((firstName || '') + ' ' + (lastName || ''))}\n </Typography>\n </div>\n ) : (\n <div className={cn(borderColor, 'p-1 rounded-full bg-neutral-200 dark:bg-black-600 flex items-center justify-center border w-full h-full')}>\n <PersonIcon fill='#98A2B3' />\n </div>\n )}\n\n {statusIndicator && statusColor && (\n <div\n className={cn(\n 'absolute bottom-0 right-0 rounded-full border border-white dark:border-black-800 w-2 h-2',\n\n statusColor,\n )}\n />\n )}\n </div>\n <UserAvatarPopper\n isOpen={visible}\n onClose={() => setVisible(false)}\n anchorEl={containerRef.current}\n className='bg-white dark:bg-black-700 shadow rounded-lg border border-neutral-200 dark:border-black-600'\n >\n {popperContent}\n </UserAvatarPopper>\n </div>\n );\n};\n\nUserAvatar.displayName = 'UserAvatar';\n\n"],"names":["InfoRow","label","content","jsxs","jsx","Typography","UserAvatar","firstName","lastName","email","profilePic","size","hoverSize","containerClassName","enablePopper","className","userId","lastViewedOn","isActive","statusIndicator","userDetails","isFetchingUserDetails","authToken","onHover","currentlyEditing","GroupsIcon","visible","setVisible","useState","imageLoaded","setImageLoaded","avatarSizeClass","sizeClasses","moreTagRef","dropdownRef","dropdownPosition","showMore","handleShowMore","handleHideMore","useDynamicPosition","imageCacheRef","useRef","isRecent","useMemo","date","statusColor","borderColor","indicatorSizes","useEffect","img","token","timerRef","cachedSrc","popperRef","handleMouseEnter","handleMouseLeave","event","popperContent","cn","initialsFontSizeClasses","getInitials","getFlagComponentRectangleMd","EditOutlinedIcon","Skeleton","StatusInfoRow","Tag","e","team","index","WarningRoundedIcon","containerRef","PersonIcon","UserAvatarPopper"],"mappings":"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"}
|