react-smart-date-compare 1.0.0

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.
@@ -0,0 +1,8 @@
1
+ (function(J,u){typeof exports=="object"&&typeof module<"u"?u(exports,require("react"),require("react-dom"),require("date-fns")):typeof define=="function"&&define.amd?define(["exports","react","react-dom","date-fns"],u):(J=typeof globalThis<"u"?globalThis:J||self,u(J.ReactSmartDateCompare={},J.React,J.ReactDOM,J.DateFns))})(this,(function(J,u,me,t){"use strict";var ee={exports:{}},K={};var se;function he(){if(se)return K;se=1;var n=Symbol.for("react.transitional.element"),s=Symbol.for("react.fragment");function a(p,i,c){var y=null;if(c!==void 0&&(y=""+c),i.key!==void 0&&(y=""+i.key),"key"in i){c={};for(var g in i)g!=="key"&&(c[g]=i[g])}else c=i;return i=c.ref,{$$typeof:n,type:p,key:y,ref:i!==void 0?i:null,props:c}}return K.Fragment=s,K.jsx=a,K.jsxs=a,K}var $={};var oe;function pe(){return oe||(oe=1,process.env.NODE_ENV!=="production"&&(function(){function n(e){if(e==null)return null;if(typeof e=="function")return e.$$typeof===Z?null:e.displayName||e.name||null;if(typeof e=="string")return e;switch(e){case z:return"Fragment";case S:return"Profiler";case I:return"StrictMode";case G:return"Suspense";case X:return"SuspenseList";case k:return"Activity"}if(typeof e=="object")switch(typeof e.tag=="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),e.$$typeof){case B:return"Portal";case f:return e.displayName||"Context";case U:return(e._context.displayName||"Context")+".Consumer";case j:var o=e.render;return e=e.displayName,e||(e=o.displayName||o.name||"",e=e!==""?"ForwardRef("+e+")":"ForwardRef"),e;case m:return o=e.displayName||null,o!==null?o:n(e.type)||"Memo";case w:o=e._payload,e=e._init;try{return n(e(o))}catch{}}return null}function s(e){return""+e}function a(e){try{s(e);var o=!1}catch{o=!0}if(o){o=console;var l=o.error,h=typeof Symbol=="function"&&Symbol.toStringTag&&e[Symbol.toStringTag]||e.constructor.name||"Object";return l.call(o,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",h),s(e)}}function p(e){if(e===z)return"<>";if(typeof e=="object"&&e!==null&&e.$$typeof===w)return"<...>";try{var o=n(e);return o?"<"+o+">":"<...>"}catch{return"<...>"}}function i(){var e=d.A;return e===null?null:e.getOwner()}function c(){return Error("react-stack-top-frame")}function y(e){if(C.call(e,"key")){var o=Object.getOwnPropertyDescriptor(e,"key").get;if(o&&o.isReactWarning)return!1}return e.key!==void 0}function g(e,o){function l(){_||(_=!0,console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",o))}l.isReactWarning=!0,Object.defineProperty(e,"key",{get:l,configurable:!0})}function M(){var e=n(this.type);return E[e]||(E[e]=!0,console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.")),e=this.props.ref,e!==void 0?e:null}function Y(e,o,l,h,b,W){var v=l.ref;return e={$$typeof:H,type:e,key:o,props:l,_owner:h},(v!==void 0?v:null)!==null?Object.defineProperty(e,"ref",{enumerable:!1,get:M}):Object.defineProperty(e,"ref",{enumerable:!1,value:null}),e._store={},Object.defineProperty(e._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(e,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(e,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:b}),Object.defineProperty(e,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:W}),Object.freeze&&(Object.freeze(e.props),Object.freeze(e)),e}function P(e,o,l,h,b,W){var v=o.children;if(v!==void 0)if(h)if(O(v)){for(h=0;h<v.length;h++)N(v[h]);Object.freeze&&Object.freeze(v)}else console.error("React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.");else N(v);if(C.call(o,"key")){v=n(e);var Q=Object.keys(o).filter(function(re){return re!=="key"});h=0<Q.length?"{key: someKey, "+Q.join(": ..., ")+": ...}":"{key: someKey}",V[v+h]||(Q=0<Q.length?"{"+Q.join(": ..., ")+": ...}":"{}",console.error(`A props object containing a "key" prop is being spread into JSX:
2
+ let props = %s;
3
+ <%s {...props} />
4
+ React keys must be passed directly to JSX without using spread:
5
+ let props = %s;
6
+ <%s key={someKey} {...props} />`,h,v,Q,v),V[v+h]=!0)}if(v=null,l!==void 0&&(a(l),v=""+l),y(o)&&(a(o.key),v=""+o.key),"key"in o){l={};for(var q in o)q!=="key"&&(l[q]=o[q])}else l=o;return v&&g(l,typeof e=="function"?e.displayName||e.name||"Unknown":e),Y(e,v,l,i(),b,W)}function N(e){A(e)?e._store&&(e._store.validated=1):typeof e=="object"&&e!==null&&e.$$typeof===w&&(e._payload.status==="fulfilled"?A(e._payload.value)&&e._payload.value._store&&(e._payload.value._store.validated=1):e._store&&(e._store.validated=1))}function A(e){return typeof e=="object"&&e!==null&&e.$$typeof===H}var T=u,H=Symbol.for("react.transitional.element"),B=Symbol.for("react.portal"),z=Symbol.for("react.fragment"),I=Symbol.for("react.strict_mode"),S=Symbol.for("react.profiler"),U=Symbol.for("react.consumer"),f=Symbol.for("react.context"),j=Symbol.for("react.forward_ref"),G=Symbol.for("react.suspense"),X=Symbol.for("react.suspense_list"),m=Symbol.for("react.memo"),w=Symbol.for("react.lazy"),k=Symbol.for("react.activity"),Z=Symbol.for("react.client.reference"),d=T.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,C=Object.prototype.hasOwnProperty,O=Array.isArray,D=console.createTask?console.createTask:function(){return null};T={react_stack_bottom_frame:function(e){return e()}};var _,E={},R=T.react_stack_bottom_frame.bind(T,c)(),L=D(p(c)),V={};$.Fragment=z,$.jsx=function(e,o,l){var h=1e4>d.recentlyCreatedOwnerStacks++;return P(e,o,l,!1,h?Error("react-stack-top-frame"):R,h?D(p(e)):L)},$.jsxs=function(e,o,l){var h=1e4>d.recentlyCreatedOwnerStacks++;return P(e,o,l,!0,h?Error("react-stack-top-frame"):R,h?D(p(e)):L)}})()),$}var ae;function ye(){return ae||(ae=1,process.env.NODE_ENV==="production"?ee.exports=he():ee.exports=pe()),ee.exports}var r=ye();const xe=(n,s)=>{const a=t.differenceInCalendarDays(s,n)+1;return{compareStart:t.subDays(n,a),compareEnd:t.subDays(s,a)}},be=(n,s)=>{const a=t.differenceInCalendarDays(s,n)+1,p=a%7,i=p===0?a:a+(7-p);return{compareStart:t.subDays(n,i),compareEnd:t.subDays(s,i)}},ve=(n,s)=>({compareStart:t.subYears(n,1),compareEnd:t.subYears(s,1)}),ge=(n,s)=>{const a=t.startOfMonth(n),p=t.endOfMonth(a),i=t.startOfWeek(a,s),c=t.endOfWeek(p,s);return t.eachDayOfInterval({start:i,end:c})};function te(n,s){const a=n.replace("#",""),p=parseInt(a.substring(0,2),16),i=parseInt(a.substring(2,4),16),c=parseInt(a.substring(4,6),16);return`rgba(${p},${i},${c},${s})`}const ke=({month:n,startDate:s,endDate:a,compareStartDate:p,compareEndDate:i,hoverDate:c,onDateClick:y,onDateHover:g,selecting:M,anchorDate:Y,selectionVariant:P="primary",primaryColor:N="#3b82f6",compareColor:A="#f97316",minDate:T,maxDate:H,weekStartsOn:B=0,disabledDates:z,disableFuture:I,disablePast:S,locale:U,classNames:f})=>{const j=u.useMemo(()=>ge(n,{weekStartsOn:B}),[n,B]),G=j.slice(0,7),X=m=>{let w=!1;if(T&&t.isBefore(m,t.startOfDay(T))&&(w=!0),H&&t.isAfter(m,t.startOfDay(H))&&(w=!0),I&&t.isAfter(m,t.startOfDay(new Date))&&(w=!0),S&&t.isBefore(m,t.startOfDay(new Date))&&(w=!0),z?.some(l=>t.isSameDay(m,l))&&(w=!0),w)return{className:"h-8 w-8 flex items-center justify-center text-sm text-gray-300 cursor-not-allowed pointer-events-none"};if(!t.isSameMonth(m,n))return{className:"invisible pointer-events-none h-8 w-8"};const k=m.getTime(),d=["h-8 w-8 flex items-center justify-center text-sm cursor-pointer relative z-10 transition-colors duration-75"];let C={};f?.day&&d.push(f.day);let O=!1,D=!1,_=!1;if(p&&i){const l=t.startOfDay(p).getTime(),h=t.startOfDay(i).getTime(),b=Math.min(l,h),W=Math.max(l,h);O=t.isSameDay(m,p),D=t.isSameDay(m,i),k>=b&&k<=W&&(_=!0)}let E=!1,R=!1,L=!1;if(s&&(E=t.isSameDay(m,s)),a&&(R=t.isSameDay(m,a)),s&&a){const l=t.startOfDay(s).getTime(),h=t.startOfDay(a).getTime();k>=Math.min(l,h)&&k<=Math.max(l,h)&&(L=!0)}const V=Y??(P==="primary"?s:p);let e=!1;if(M&&V&&c){const l=t.startOfDay(V).getTime(),h=t.startOfDay(c).getTime();k>=Math.min(l,h)&&k<=Math.max(l,h)&&(e=!0)}f?.dayInRange&&L&&!E&&!R?d.push(f.dayInRange):f?.dayCompare&&_&&!O&&!D?d.push(f.dayCompare):e?P==="compare"?C={backgroundColor:te(A,.12),color:A}:C={backgroundColor:te(N,.12),color:N}:_&&!O&&!D?f?.dayCompare?d.push(f.dayCompare):C={backgroundColor:te(A,.12),color:A,fontWeight:500}:L&&!E&&!R?f?.dayInRange?d.push(f.dayInRange):C={backgroundColor:te(N,.12),color:N}:!O&&!D&&!E&&!R&&d.push("hover:bg-gray-100 text-gray-700 rounded-full");const o=M&&V&&c&&(t.isSameDay(m,V)||t.isSameDay(m,c));return(O||D||o&&P==="compare")&&(f?.dayCompare?d.push(f.dayCompare):C={backgroundColor:A,color:"#fff",fontWeight:600,boxShadow:"0 1px 4px rgba(0,0,0,0.15)"},O&&d.push("rounded-l-full"),D&&d.push("rounded-r-full"),O&&D&&d.push("rounded-full"),o&&d.push("rounded-full")),(E||R||o&&P==="primary")&&(f?.daySelected?(d.push(f.daySelected),d.push("z-20")):C={backgroundColor:N,color:"#fff",fontWeight:600,boxShadow:"0 1px 4px rgba(0,0,0,0.15)",zIndex:20},E&&d.push("rounded-l-full"),R&&d.push("rounded-r-full"),E&&R&&d.push("rounded-full"),o&&d.push("rounded-full")),{className:d.join(" "),style:Object.keys(C).length?C:void 0}};return r.jsxs("div",{className:`w-64 select-none mr-2 ${f?.calendar||""}`,children:[r.jsx("div",{className:"text-center text-sm font-semibold text-gray-800 mb-2 h-5 first-letter:uppercase",children:t.format(n,"MMMM yyyy",{locale:U})}),r.jsx("div",{className:"grid grid-cols-7 mb-1",children:G.map(m=>r.jsx("div",{className:"text-center text-[10px] text-gray-400 font-medium h-6 flex items-center justify-center uppercase tracking-wide",children:t.format(m,"cccccc",{locale:U})},m.toString()))}),r.jsx("div",{className:"grid grid-cols-7 gap-y-0.5",children:j.map(m=>{const{className:w,style:k}=X(m);return r.jsx("div",{className:w+" text-xs",style:k,onClick:()=>{w.includes("pointer-events-none")||y(m)},onMouseEnter:()=>g(m),children:t.format(m,"d")},m.toISOString())})})]})},le=({preset:n,onSelect:s,activePreset:a,primaryColor:p="#3b82f6",classNames:i,depth:c=0})=>{const y=n.children&&n.children.length>0,g=y?n.children.some(T=>T.value===a):!1,[M,Y]=u.useState(g),P=a===n.value,N=i?.presetActive?void 0:{backgroundColor:`${p}15`,color:p,fontWeight:600},A=i?.presetActive||"";return y?r.jsxs("div",{children:[r.jsxs("button",{className:`w-full flex items-center justify-between px-3 py-2 rounded-md text-xs transition-colors cursor-pointer
7
+ ${g?A:"text-gray-600 hover:bg-gray-100"}`,style:{paddingLeft:`${(c+1)*12}px`,...g?N:{}},onClick:()=>Y(T=>!T),type:"button","aria-expanded":M,children:[r.jsx("span",{children:n.label}),r.jsx("svg",{className:`w-3 h-3 shrink-0 ml-1 text-gray-400 transition-transform duration-200 ${M?"rotate-90":""}`,fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:r.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M9 5l7 7-7 7"})})]}),M&&r.jsx("div",{className:"flex flex-col gap-0.5 mt-0.5 ml-2 pl-2 border-l border-gray-200",children:n.children.map(T=>r.jsx(le,{preset:T,onSelect:s,activePreset:a,primaryColor:p,classNames:i,depth:c+1},T.value))})]}):r.jsx("button",{className:`w-full text-left px-3 py-2 rounded-md text-xs transition-colors cursor-pointer
8
+ ${P?A:"text-gray-600 hover:bg-gray-100"}`,style:{paddingLeft:c>0?`${(c+1)*12}px`:void 0,...P?N:{}},onClick:()=>s(n.value),type:"button",children:n.label})},Se=({presets:n,onSelect:s,activePreset:a,primaryColor:p,classNames:i})=>r.jsx("aside",{className:"flex flex-col gap-0.5 p-2",children:n.map(c=>r.jsx(le,{preset:c,onSelect:s,activePreset:a,primaryColor:p,classNames:i},c.value))}),we=({enabled:n,mode:s,onToggle:a,onModeChange:p,primaryColor:i="#3b82f6",compareColor:c="#f97316"})=>r.jsxs("div",{className:"flex flex-col gap-2 text-sm text-gray-700",children:[r.jsxs("label",{className:"flex items-center gap-2 cursor-pointer select-none",children:[r.jsxs("div",{className:"relative inline-flex h-5 w-9 shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out",style:{backgroundColor:n?i:"#d1d5db"},onClick:()=>a(!n),children:[r.jsx("input",{type:"checkbox",className:"sr-only",checked:n,onChange:y=>a(y.target.checked)}),r.jsx("span",{"aria-hidden":"true",className:`pointer-events-none inline-block h-4 w-4 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out ${n?"translate-x-4":"translate-x-0"}`})]}),r.jsx("span",{className:"font-medium",children:"Compare"})]}),n&&r.jsx("div",{className:"flex flex-col gap-1 mt-2 pl-2",style:{borderLeft:`2px solid ${i}40`},children:[{value:"previousPeriodMatchDay",label:"Previous period (match day of week)"},{value:"previousPeriod",label:"Previous period"},{value:"samePeriodLastYear",label:"Previous year"},{value:"custom",label:"Custom"}].map(y=>{const g=s===y.value;return r.jsx("button",{className:"text-left px-3 py-2 rounded-md text-xs transition-colors cursor-pointer",style:g?{backgroundColor:`${c}15`,color:c,fontWeight:600}:{color:"#6b7280"},onClick:()=>p(y.value),children:y.label},y.value)})})]}),je=n=>{const s=t.startOfToday(),a=t.endOfToday();switch(n){case"today":return{startDate:s,endDate:a};case"yesterday":return{startDate:t.subDays(s,1),endDate:t.subDays(a,1)};case"last7days":return{startDate:t.subDays(s,6),endDate:a};case"thisWeekSunToday":return{startDate:t.startOfWeek(s,{weekStartsOn:0}),endDate:a};case"thisWeekMonToday":return{startDate:t.startOfWeek(s,{weekStartsOn:1}),endDate:a};case"lastWeekSunSat":const i=t.subDays(t.startOfWeek(s,{weekStartsOn:0}),7);return{startDate:i,endDate:t.endOfWeek(i,{weekStartsOn:0})};case"lastWeekMonSun":const c=t.subDays(t.startOfWeek(s,{weekStartsOn:1}),7);return{startDate:c,endDate:t.endOfWeek(c,{weekStartsOn:1})};case"last28Days":return{startDate:t.subDays(s,27),endDate:a};case"last30days":return{startDate:t.subDays(s,29),endDate:a};case"thisMonth":return{startDate:t.startOfMonth(s),endDate:t.endOfMonth(s)};case"lastMonth":const y=t.subMonths(s,1);return{startDate:t.startOfMonth(y),endDate:t.endOfMonth(y)};case"ytd":return{startDate:t.startOfYear(s),endDate:a};default:return{startDate:s,endDate:a}}},ie=[{label:"Today",value:"today"},{label:"Yesterday",value:"yesterday"},{label:"This week",value:"__group_thisWeek",children:[{label:"Sun – Today",value:"thisWeekSunToday"},{label:"Mon – Today",value:"thisWeekMonToday"}]},{label:"Last 7 days",value:"last7days"},{label:"Last week",value:"__group_lastWeek",children:[{label:"Sun – Sat",value:"lastWeekSunSat"},{label:"Mon – Sun",value:"lastWeekMonSun"}]},{label:"Last 28 days",value:"last28Days"},{label:"Last 30 days",value:"last30days"},{label:"This month",value:"thisMonth"},{label:"Last month",value:"lastMonth"},{label:"Year to Date",value:"ytd"},{label:"Custom",value:"custom"}],De=({initialRange:n,initialCompareRange:s,presets:a=ie,onApply:p,onCancel:i,enableCompare:c=!1,activeCompareMode:y="previousPeriod",primaryColor:g="#3b82f6",compareColor:M="#f97316",minDate:Y,maxDate:P,weekStartsOn:N,disabledDates:A,disableFuture:T,disablePast:H,locale:B,labels:z,classNames:I})=>{const[S,U]=u.useState(n?.startDate),[f,j]=u.useState(n?.endDate),[G,X]=u.useState(null),[m,w]=u.useState(!1),[k,Z]=u.useState(c),[d,C]=u.useState(y);u.useEffect(()=>{Z(c)},[c]),u.useEffect(()=>{C(y)},[y]);const[O,D]=u.useState("primary");u.useEffect(()=>{D(k&&d==="custom"?"compare":"primary")},[k,d]);const[_,E]=u.useState(s?.startDate),[R,L]=u.useState(s?.endDate),[V,e]=u.useState(""),[o,l]=u.useState(()=>{const x=n?.endDate||new Date;return t.subMonths(t.startOfMonth(x),1)});u.useEffect(()=>{if(k&&!m&&S&&f&&d!=="custom"){let x;d==="previousPeriod"?x=xe(S,f):d==="previousPeriodMatchDay"?x=be(S,f):d==="samePeriodLastYear"&&(x=ve(S,f)),x&&(E(x.compareStart),L(x.compareEnd))}},[S,f,k,d,m]);const h=x=>{Y&&t.isBefore(x,Y)||P&&t.isBefore(P,x)||(m?(O==="compare"?_&&t.isBefore(x,_)?(E(x),L(_)):L(x):S&&t.isBefore(x,S)?(U(x),j(S)):j(x),w(!1)):(e("custom"),O==="compare"?(E(x),L(void 0)):(U(x),j(void 0)),w(!0)))},b=x=>{m&&X(x)},W=x=>{if(x.startsWith("__group_"))return;const ce=(Re,fe)=>{for(const ne of Re){if(ne.value===fe)return ne;if(ne.children){const de=ce(ne.children,fe);if(de)return de}}},ue=ce(a,x);e(x);let F;ue?.range?F=ue.range():F=je(x),U(F.startDate),j(F.endDate),w(!1),D("primary"),l(t.subMonths(t.startOfMonth(F.endDate),1))},v=()=>l(t.subMonths(o,1)),Q=()=>l(t.addMonths(o,1)),q=()=>{S&&f&&p({startDate:S,endDate:f},k&&_&&R?{startDate:_,endDate:R}:void 0,k?d:void 0)},re=x=>r.jsx(ke,{month:x,startDate:S,endDate:f,compareStartDate:k?_:void 0,compareEndDate:k?R:void 0,hoverDate:G,onDateClick:h,onDateHover:b,selecting:m,anchorDate:m?O==="primary"?S:_:void 0,selectionVariant:O,minDate:Y,maxDate:P,weekStartsOn:N,disabledDates:A,disableFuture:T,disablePast:H,locale:B,classNames:I,primaryColor:g,compareColor:M});return r.jsxs("div",{className:`flex bg-white h-[450px] ${I?.root||""}`,children:[r.jsxs("div",{className:`w-48 bg-gray-50/50 border-r border-gray-100 flex flex-col h-full shrink-0 ${I?.sidebar||""}`,children:[r.jsx("div",{className:"flex-1 overflow-y-auto preset-scrollbar",children:r.jsx(Se,{presets:a,onSelect:W,activePreset:V,primaryColor:g,classNames:I})}),r.jsx("div",{className:"p-3 border-t border-gray-200 bg-gray-50/80 backdrop-blur-sm",children:r.jsx(we,{enabled:k,mode:d,onToggle:Z,onModeChange:C,primaryColor:g,compareColor:M})})]}),r.jsxs("div",{className:"flex flex-col flex-1 h-full overflow-hidden",children:[r.jsxs("div",{className:"flex justify-between items-center px-4 py-2 border-b border-gray-100 shrink-0",children:[r.jsx("button",{className:"p-1.5 rounded-full hover:bg-gray-100 text-gray-500 hover:text-gray-900 transition-colors cursor-pointer",onClick:v,children:r.jsx("svg",{className:"w-5 h-5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:r.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:"2",d:"M15 19l-7-7 7-7"})})}),r.jsxs("div",{className:"text-xs font-medium text-gray-500 flex flex-col items-center",children:[S&&f?r.jsxs("span",{children:[t.format(S,"MMM d, yyyy",{locale:B})," - ",t.format(f,"MMM d, yyyy",{locale:B})]}):r.jsx("span",{children:z?.selectDateRange||"Select date range"}),k&&_&&R&&r.jsxs("span",{className:"text-[10px] font-medium",style:{color:M},children:[z?.vs||"vs"," ",t.format(_,"MMM d, yyyy",{locale:B})," - ",t.format(R,"MMM d, yyyy",{locale:B})]})]}),r.jsx("button",{className:"p-1.5 rounded-full hover:bg-gray-100 text-gray-500 hover:text-gray-900 transition-colors cursor-pointer",onClick:Q,children:r.jsx("svg",{className:"w-5 h-5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:r.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:"2",d:"M9 5l7 7-7 7"})})})]}),r.jsxs("div",{className:`flex flex-col gap-4 p-4 overflow-y-auto flex-1 items-center ${I?.container||""}`,children:[re(o),re(t.addMonths(o,1))]}),r.jsxs("div",{className:`px-4 py-3 border-t border-gray-100 flex items-center justify-between shrink-0 bg-white ${I?.footer||""}`,children:[r.jsx("button",{className:"text-xs font-medium text-gray-500 hover:text-gray-700 underline decoration-gray-300 hover:decoration-gray-500 underline-offset-2 transition-colors cursor-pointer",onClick:()=>{U(void 0),j(void 0),w(!1),e(""),Z(!1)},children:z?.clear||"Reset"}),r.jsxs("div",{className:"flex gap-3",children:[r.jsx("button",{className:`px-3 py-1.5 rounded-md border border-gray-300 bg-white text-xs font-medium text-gray-700 hover:bg-gray-50 transition-colors cursor-pointer ${I?.buttonCancel||""}`,onClick:i,children:z?.cancel||"Cancel"}),r.jsx("button",{className:`px-3 py-1.5 rounded-md border border-transparent text-xs font-medium text-white transition-colors disabled:opacity-50 disabled:cursor-not-allowed shadow-sm cursor-pointer ${I?.buttonApply||""}`,style:{backgroundColor:g},onClick:q,disabled:!S||!f,children:z?.apply||"Apply"})]})]})]})]})},Ee=({value:n,defaultValue:s,onChange:a,onApply:p,onCancel:i,presets:c,primaryColor:y,compareColor:g,enableCompare:M=!1,compareMode:Y="previousPeriod",className:P,style:N,minDate:A,maxDate:T,weekStartsOn:H,disabledDates:B,disableFuture:z,disablePast:I,locale:S,labels:U,classNames:f})=>{const[j,G]=u.useState(!1),[X,m]=u.useState(n||s||{startDate:new Date,endDate:new Date}),[w,k]=u.useState(),[Z,d]=u.useState(M),[C,O]=u.useState(Y),[D,_]=u.useState({top:0,left:0}),E=u.useRef(null),R=u.useRef(null);u.useEffect(()=>{n&&m(n)},[n]),u.useEffect(()=>{d(M)},[M]),u.useEffect(()=>{O(Y)},[Y]);const L=()=>{if(!E.current)return;const b=E.current.getBoundingClientRect();_({top:b.bottom+window.scrollY+4,left:b.left+window.scrollX})},V=()=>{j||L(),G(b=>!b)};u.useEffect(()=>{if(!j)return;const b=()=>L();return window.addEventListener("scroll",b,!0),window.addEventListener("resize",b),()=>{window.removeEventListener("scroll",b,!0),window.removeEventListener("resize",b)}},[j]),u.useEffect(()=>{if(!j)return;const b=W=>{const v=W.target;E.current?.contains(v)||R.current?.contains(v)||(G(!1),i?.())};return document.addEventListener("mousedown",b),()=>document.removeEventListener("mousedown",b)},[j,i]);const e=(b,W,v)=>{m(b),k(W),d(!!W),v&&O(v),G(!1),a?.({startDate:b.startDate,endDate:b.endDate,compareStartDate:W?.startDate,compareEndDate:W?.endDate}),p?.(b,W)},o=()=>{G(!1),i?.()},l=b=>t.format(b,"MMM d, yyyy",{locale:S}),h=`${l(X.startDate)} - ${l(X.endDate)}`;return r.jsxs("div",{ref:E,className:`relative inline-block text-left ${P||""} ${f?.root||""}`,style:{"--sdc-primary-color":y,"--sdc-compare-color":g,...N},children:[r.jsxs("button",{className:`flex items-center justify-between min-w-[240px] px-3 py-2 bg-white border border-gray-300 rounded hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all shadow-sm ${f?.container||""}`,onClick:V,type:"button","aria-haspopup":"dialog","aria-expanded":j,children:[r.jsxs("div",{className:"flex items-center gap-2 text-gray-700",children:[r.jsx("span",{className:"text-gray-400",children:r.jsx("svg",{className:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:r.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:"2",d:"M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"})})}),r.jsx("span",{className:"text-sm font-medium",children:h})]}),w&&r.jsxs("span",{className:`text-xs px-1.5 py-0.5 rounded ml-2 font-medium ${f?.dayCompare||""}`,style:{color:g,backgroundColor:`${g}18`},children:["vs ",l(w.startDate)]}),r.jsx("svg",{className:`w-4 h-4 text-gray-400 transition-transform ${j?"rotate-180":""}`,fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:r.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:"2",d:"M19 9l-7 7-7-7"})})]}),j&&me.createPortal(r.jsx("div",{ref:R,style:{position:"absolute",top:D.top,left:D.left,zIndex:99999},role:"dialog","aria-modal":"true",children:r.jsx("div",{className:`bg-white ring-1 ring-black ring-opacity-5 rounded-lg shadow-2xl overflow-hidden ${f?.calendar||""}`,style:{"--sdc-primary-color":y,"--sdc-compare-color":g},children:r.jsx(De,{initialRange:X,initialCompareRange:w,presets:c,onApply:e,onCancel:o,enableCompare:Z,activeCompareMode:C,primaryColor:y,compareColor:g,minDate:A,maxDate:T,weekStartsOn:H,disabledDates:B,disableFuture:z,disablePast:I,locale:S,labels:U,classNames:f})})}),document.body)]})};J.SmartDateCompare=Ee,J.defaultPresets=ie,Object.defineProperty(J,Symbol.toStringTag,{value:"Module"})}));
package/dist/type.d.ts ADDED
@@ -0,0 +1,69 @@
1
+ export type CompareMode = "previousPeriod" | "previousPeriodMatchDay" | "samePeriodLastYear" | "custom";
2
+ export interface DateRange {
3
+ startDate: Date;
4
+ endDate: Date;
5
+ key?: string;
6
+ }
7
+ export interface Preset {
8
+ label: string;
9
+ value: string;
10
+ range?: () => DateRange;
11
+ /** Sub-options — if provided, this preset acts as a group header with an expand arrow */
12
+ children?: Preset[];
13
+ }
14
+ export interface SmartDateCompareProps {
15
+ value?: DateRange;
16
+ defaultValue?: DateRange;
17
+ onChange?: (data: {
18
+ startDate: Date;
19
+ endDate: Date;
20
+ compareStartDate?: Date;
21
+ compareEndDate?: Date;
22
+ }) => void;
23
+ presets?: Preset[];
24
+ enableCompare?: boolean;
25
+ compareMode?: CompareMode;
26
+ minDate?: Date;
27
+ maxDate?: Date;
28
+ weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
29
+ disabledDates?: Date[];
30
+ disableFuture?: boolean;
31
+ disablePast?: boolean;
32
+ locale?: any;
33
+ labels?: {
34
+ apply?: string;
35
+ cancel?: string;
36
+ compare?: string;
37
+ to?: string;
38
+ custom?: string;
39
+ selectDateRange?: string;
40
+ vs?: string;
41
+ precedingPeriod?: string;
42
+ samePeriodLastYear?: string;
43
+ };
44
+ primaryColor?: string;
45
+ compareColor?: string;
46
+ borderRadius?: string;
47
+ classNames?: {
48
+ root?: string;
49
+ container?: string;
50
+ sidebar?: string;
51
+ calendar?: string;
52
+ day?: string;
53
+ daySelected?: string;
54
+ dayInRange?: string;
55
+ dayCompare?: string;
56
+ footer?: string;
57
+ buttonApply?: string;
58
+ buttonCancel?: string;
59
+ presetActive?: string;
60
+ };
61
+ variant?: "default" | "minimal" | "dashboard" | "enterprise";
62
+ size?: "sm" | "md" | "lg";
63
+ placement?: "bottom-left" | "bottom-right" | "top-left" | "top-right";
64
+ onApply?: (range: DateRange, compareRange?: DateRange) => void;
65
+ onCancel?: () => void;
66
+ className?: string;
67
+ style?: React.CSSProperties;
68
+ }
69
+ //# sourceMappingURL=type.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"type.d.ts","sourceRoot":"","sources":["../src/lib/type.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ export declare const getPreviousPeriod: (start: Date, end: Date) => {
2
+ compareStart: Date;
3
+ compareEnd: Date;
4
+ };
5
+ export declare const getPreviousPeriodMatchDay: (start: Date, end: Date) => {
6
+ compareStart: Date;
7
+ compareEnd: Date;
8
+ };
9
+ export declare const getSamePeriodLastYear: (start: Date, end: Date) => {
10
+ compareStart: Date;
11
+ compareEnd: Date;
12
+ };
13
+ /**
14
+ * Generate a grid of days for a given month, including padding from prev/next months
15
+ * to fill the 6-row or 5-row calendar view.
16
+ */
17
+ export declare const getMonthGrid: (month: Date, options?: {
18
+ weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
19
+ }) => import("date-fns").EachDayOfIntervalResult<{
20
+ start: Date;
21
+ end: Date;
22
+ }, undefined>;
23
+ export declare const isDateInRange: (date: Date, start: Date, end: Date) => boolean;
24
+ //# sourceMappingURL=dateHelpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dateHelpers.d.ts","sourceRoot":"","sources":["../../src/lib/utils/dateHelpers.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,iBAAiB,GAC1B,OAAO,IAAI,EACX,KAAK,IAAI;;;CAOZ,CAAC;AAEF,eAAO,MAAM,yBAAyB,GAClC,OAAO,IAAI,EACX,KAAK,IAAI;;;CAYZ,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAC9B,OAAO,IAAI,EACX,KAAK,IAAI;;;CAMZ,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,YAAY,GAAI,OAAO,IAAI,EAAE,UAAU;IAAE,YAAY,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;CAAE;;;aAe/F,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,MAAM,IAAI,EAAE,OAAO,IAAI,EAAE,KAAK,IAAI,YAE/D,CAAA"}
@@ -0,0 +1,4 @@
1
+ import type { DateRange, Preset } from "../type";
2
+ export declare const getPresetRange: (value: string) => DateRange;
3
+ export declare const defaultPresets: Preset[];
4
+ //# sourceMappingURL=presetHelpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presetHelpers.d.ts","sourceRoot":"","sources":["../../src/lib/utils/presetHelpers.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEjD,eAAO,MAAM,cAAc,GAAI,OAAO,MAAM,KAAG,SAwE9C,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,MAAM,EA2BlC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,69 @@
1
+ {
2
+ "name": "react-smart-date-compare",
3
+ "version": "1.0.0",
4
+ "description": "A highly customizable React date range picker with advanced comparison modes.",
5
+ "type": "module",
6
+ "main": "./dist/react-smart-date-compare.umd.js",
7
+ "module": "./dist/react-smart-date-compare.es.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/react-smart-date-compare.es.js",
13
+ "require": "./dist/react-smart-date-compare.umd.js"
14
+ },
15
+ "./style.css": "./dist/react-smart-date-compare.css"
16
+ },
17
+ "files": [
18
+ "dist"
19
+ ],
20
+ "scripts": {
21
+ "dev": "vite",
22
+ "build": "vite build && tsc -b tsconfig.build.json",
23
+ "lint": "eslint .",
24
+ "preview": "vite preview",
25
+ "prepublishOnly": "npm run build"
26
+ },
27
+ "peerDependencies": {
28
+ "react": "^19.2.0",
29
+ "react-dom": "^19.2.0",
30
+ "date-fns": "^4.1.0"
31
+ },
32
+ "devDependencies": {
33
+ "@eslint/js": "^9.39.1",
34
+ "@tailwindcss/postcss": "^4.2.0",
35
+ "@tailwindcss/vite": "^4.0.5",
36
+ "@types/node": "^24.10.1",
37
+ "@types/react": "^19.2.7",
38
+ "@types/react-dom": "^19.2.3",
39
+ "@vitejs/plugin-react": "^4.3.4",
40
+ "autoprefixer": "^10.4.24",
41
+ "date-fns": "^4.1.0",
42
+ "eslint": "^9.39.1",
43
+ "eslint-plugin-react-hooks": "^7.0.1",
44
+ "eslint-plugin-react-refresh": "^0.4.24",
45
+ "globals": "^16.5.0",
46
+ "postcss": "^8.5.6",
47
+ "react": "^19.2.0",
48
+ "react-dom": "^19.2.0",
49
+ "tailwindcss": "^4.2.0",
50
+ "typescript": "~5.9.3",
51
+ "typescript-eslint": "^8.48.0",
52
+ "vite": "^6.0.0"
53
+ },
54
+ "keywords": [
55
+ "react",
56
+ "date-picker",
57
+ "date-range",
58
+ "comparison",
59
+ "calendar",
60
+ "date-fns",
61
+ "tailwind"
62
+ ],
63
+ "author": "",
64
+ "license": "MIT",
65
+ "repository": {
66
+ "type": "git",
67
+ "url": ""
68
+ }
69
+ }