react-select-datepicker 2.1.2 → 3.0.1

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.
Files changed (43) hide show
  1. package/README.md +134 -3
  2. package/dist/_virtual/_tslib.js +1 -1
  3. package/dist/components/OptionsRenderer.js +1 -1
  4. package/dist/components/SelectDatepicker.css.js +1 -0
  5. package/dist/components/SelectDatepicker.js +1 -1
  6. package/dist/components/SelectDatepickerContext.js +1 -0
  7. package/dist/components/SelectDatepickerErrorBoundary.js +1 -0
  8. package/dist/components/SelectDatepickerField.js +1 -0
  9. package/dist/components/SelectRenderer.css.js +1 -0
  10. package/dist/components/SelectRenderer.js +1 -1
  11. package/dist/hooks/useKeyboardNavigation.js +1 -0
  12. package/dist/index.js +1 -1
  13. package/dist/node_modules/style-inject/dist/style-inject.es.js +1 -0
  14. package/dist/src/components/SelectDatepicker.d.ts +5 -0
  15. package/dist/src/components/SelectDatepickerContext.d.ts +23 -0
  16. package/dist/src/components/SelectDatepickerErrorBoundary.d.ts +17 -0
  17. package/dist/src/components/SelectDatepickerField.d.ts +7 -0
  18. package/dist/{components → src/components}/SelectRenderer.d.ts +4 -1
  19. package/dist/src/components/__tests__/SelectDatepicker.test.d.ts +1 -0
  20. package/dist/src/hooks/useKeyboardNavigation.d.ts +23 -0
  21. package/dist/{index.d.ts → src/index.d.ts} +1 -0
  22. package/dist/src/interfaces/ISelectDatePicker.d.ts +39 -0
  23. package/dist/src/types/SelectDatepickerLabels.d.ts +32 -0
  24. package/dist/src/types/SelectDatepickerOrder.d.ts +1 -0
  25. package/dist/src/utils/__tests__/dateUtils.fresh.test.d.ts +1 -0
  26. package/dist/src/utils/__tests__/dateUtils.test.d.ts +1 -0
  27. package/dist/src/utils/__tests__/performance.test.d.ts +1 -0
  28. package/dist/src/utils/dateUtils.d.ts +62 -0
  29. package/dist/{utils → src/utils}/helpers.d.ts +3 -3
  30. package/dist/src/utils/performance.d.ts +38 -0
  31. package/dist/src/utils/validation.d.ts +18 -0
  32. package/dist/utils/dateUtils.js +1 -0
  33. package/dist/utils/helpers.js +1 -1
  34. package/dist/utils/performance.js +1 -0
  35. package/dist/utils/validation.js +1 -0
  36. package/dist/vitest.config.d.ts +2 -0
  37. package/dist/vitest.setup.d.ts +1 -0
  38. package/package.json +35 -29
  39. package/dist/components/SelectDatepicker.d.ts +0 -4
  40. package/dist/interfaces/ISelectDatePicker.d.ts +0 -20
  41. package/dist/types/SelectDatepickerLabels.d.ts +0 -23
  42. package/dist/types/SelectDatepickerOrder.d.ts +0 -1
  43. /package/dist/{components → src/components}/OptionsRenderer.d.ts +0 -0
package/README.md CHANGED
@@ -25,19 +25,150 @@ import { SelectDatepicker } from 'react-select-datepicker';
25
25
  export const App = () => {
26
26
  const [value, setValue] = useState<Date | null>();
27
27
 
28
- const onDateChange = useCallback((date: Date) => {
28
+ const onChange = useCallback((date: Date | null) => {
29
29
  setValue(date);
30
30
  }, []);
31
31
 
32
32
  return (
33
33
  <SelectDatepicker
34
- selectedDate={value}
35
- onDateChange={onDateChange}
34
+ value={value}
35
+ onChange={onChange}
36
+ labels={{
37
+ groupLabel: 'Select your date',
38
+ }}
36
39
  />
37
40
  );
38
41
  };
39
42
  ```
40
43
 
44
+ ## API
45
+
46
+ ### Props
47
+
48
+ - `value?: Date | null` — Controlled value (preferred).
49
+ - `onChange?: (date: Date | null) => void` — Change handler (preferred).
50
+ - `selectedDate?: Date | null` — Legacy value prop (still supported).
51
+ - `onDateChange?: (date: Date | null) => void` — Legacy change handler (still supported).
52
+ - `minDate?: Date` / `maxDate?: Date` — Range constraints.
53
+ - `order?: 'month/day/year' | 'day/month/year' | ...` — Order of selects.
54
+ - `reverseYears?: boolean` — Reverse year order.
55
+ - `hideLabels?: boolean` — Hide per-field labels.
56
+ - `disabled?: boolean` — Disable all selects.
57
+ - `hasError?: boolean` — Error state (shows validation message).
58
+ - `labels?: { ... }` — Label and placeholder overrides.
59
+
60
+ ### labels
61
+
62
+ - `groupLabel?: string` — Single label for the entire date picker group.
63
+ - `monthLabel`, `dayLabel`, `yearLabel` — Field labels.
64
+ - `monthPlaceholder`, `dayPlaceholder`, `yearPlaceholder` — Field placeholders.
65
+ - `months?: { 1: string; ... 12: string }` — Custom month names.
66
+
67
+ ## Examples
68
+
69
+ ### Group label
70
+
71
+ ```tsx
72
+ <SelectDatepicker
73
+ value={value}
74
+ onChange={onChange}
75
+ labels={{ groupLabel: 'Select your date' }}
76
+ />
77
+ ```
78
+
79
+ ### Date range
80
+
81
+ ```tsx
82
+ <SelectDatepicker
83
+ value={value}
84
+ onChange={onChange}
85
+ minDate={new Date(2020, 0, 1)}
86
+ maxDate={new Date(2025, 11, 31)}
87
+ />
88
+ ```
89
+
90
+ ### Custom order + reverse years
91
+
92
+ ```tsx
93
+ <SelectDatepicker
94
+ value={value}
95
+ onChange={onChange}
96
+ order="day/month/year"
97
+ reverseYears
98
+ />
99
+ ```
100
+
101
+ ### Custom labels and months
102
+
103
+ ```tsx
104
+ <SelectDatepicker
105
+ value={value}
106
+ onChange={onChange}
107
+ labels={{
108
+ groupLabel: 'Travel date',
109
+ monthLabel: 'Mes',
110
+ dayLabel: 'Día',
111
+ yearLabel: 'Año',
112
+ monthPlaceholder: 'Selecciona mes',
113
+ dayPlaceholder: 'Selecciona día',
114
+ yearPlaceholder: 'Selecciona año',
115
+ months: {
116
+ 1: 'Enero',
117
+ 2: 'Febrero',
118
+ 3: 'Marzo',
119
+ 4: 'Abril',
120
+ 5: 'Mayo',
121
+ 6: 'Junio',
122
+ 7: 'Julio',
123
+ 8: 'Agosto',
124
+ 9: 'Septiembre',
125
+ 10: 'Octubre',
126
+ 11: 'Noviembre',
127
+ 12: 'Diciembre',
128
+ },
129
+ }}
130
+ />
131
+ ```
132
+
133
+ ### Error state
134
+
135
+ ```tsx
136
+ <SelectDatepicker value={value} onChange={onChange} hasError />
137
+ ```
138
+
139
+ ### Theming (CSS variables)
140
+
141
+ ```tsx
142
+ <SelectDatepicker
143
+ value={value}
144
+ onChange={onChange}
145
+ className="my-datepicker-theme"
146
+ />
147
+ ```
148
+
149
+ ```css
150
+ .my-datepicker-theme {
151
+ --rsd-gap: 12px;
152
+ --rsd-select-padding: 10px 12px;
153
+ --rsd-select-border: 1px solid #7c3aed;
154
+ --rsd-select-border-radius: 10px;
155
+ --rsd-select-font-size: 15px;
156
+ --rsd-error-color: #b42318;
157
+ }
158
+ ```
159
+
160
+ ### Error boundary
161
+
162
+ ```tsx
163
+ import { SelectDatepickerErrorBoundary } from 'react-select-datepicker';
164
+
165
+ <SelectDatepickerErrorBoundary
166
+ renderFallback={(error) => <div role="alert">Error: {error.message}</div>}
167
+ >
168
+ <SelectDatepicker value={value} onChange={onChange} />
169
+ </SelectDatepickerErrorBoundary>
170
+ ```
171
+
41
172
  ## License
42
173
 
43
174
  MIT © [JMcAmmond](https://github.com/JMcAmmond)
@@ -12,4 +12,4 @@ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
12
12
  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
13
13
  PERFORMANCE OF THIS SOFTWARE.
14
14
  ***************************************************************************** */
15
- var r=function(){return r=Object.assign||function(r){for(var t,e=1,n=arguments.length;e<n;e++)for(var o in t=arguments[e])Object.prototype.hasOwnProperty.call(t,o)&&(r[o]=t[o]);return r},r.apply(this,arguments)};function t(r,t){var e={};for(var n in r)Object.prototype.hasOwnProperty.call(r,n)&&t.indexOf(n)<0&&(e[n]=r[n]);if(null!=r&&"function"==typeof Object.getOwnPropertySymbols){var o=0;for(n=Object.getOwnPropertySymbols(r);o<n.length;o++)t.indexOf(n[o])<0&&Object.prototype.propertyIsEnumerable.call(r,n[o])&&(e[n[o]]=r[n[o]])}return e}export{r as __assign,t as __rest};
15
+ var t=function(r,o){return t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,r){t.__proto__=r}||function(t,r){for(var o in r)Object.prototype.hasOwnProperty.call(r,o)&&(t[o]=r[o])},t(r,o)};function r(r,o){if("function"!=typeof o&&null!==o)throw new TypeError("Class extends value "+String(o)+" is not a constructor or null");function n(){this.constructor=r}t(r,o),r.prototype=null===o?Object.create(o):(n.prototype=o.prototype,new n)}var o=function(){return o=Object.assign||function(t){for(var r,o=1,n=arguments.length;o<n;o++)for(var e in r=arguments[o])Object.prototype.hasOwnProperty.call(r,e)&&(t[e]=r[e]);return t},o.apply(this,arguments)};function n(t,r){var o={};for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&r.indexOf(n)<0&&(o[n]=t[n]);if(null!=t&&"function"==typeof Object.getOwnPropertySymbols){var e=0;for(n=Object.getOwnPropertySymbols(t);e<n.length;e++)r.indexOf(n[e])<0&&Object.prototype.propertyIsEnumerable.call(t,n[e])&&(o[n[e]]=t[n[e]])}return o}export{o as __assign,r as __extends,n as __rest};
@@ -1 +1 @@
1
- import e,{useMemo as t}from"react";var n=function(n){var r=n.options,a=t((function(){return r.map((function(t,n){return e.createElement("option",{key:t.value,value:t.value},t.label)}))}),[r]);return e.createElement(e.Fragment,null,a)};export{n as OptionsRenderer};
1
+ import e from"react";var t=function(t){var r=t.options;return e.createElement(e.Fragment,null,r.map(function(t){return e.createElement("option",{key:t.value,value:t.value},t.label)}))};export{t as OptionsRenderer};
@@ -0,0 +1 @@
1
+ import r from"../node_modules/style-inject/dist/style-inject.es.js";var e=".rsd__react-select-datepicker {\r\n --rsd-gap: 8px;\r\n --rsd-legend-font-size: 16px;\r\n --rsd-legend-font-weight: 600;\r\n --rsd-legend-margin-bottom: 8px;\r\n --rsd-error-color: #d73a49;\r\n --rsd-error-font-size: 14px;\r\n --rsd-error-margin-top: 8px;\r\n --rsd-required-color: #666;\r\n --rsd-required-margin-left: 4px;\r\n --rsd-label-margin-bottom: 4px;\r\n --rsd-select-padding: 6px 8px;\r\n --rsd-select-border: 1px solid #d0d7de;\r\n --rsd-select-border-radius: 6px;\r\n --rsd-select-font-size: 14px;\r\n --rsd-select-disabled-bg: #f6f8fa;\r\n --rsd-select-disabled-color: #8c959f;\r\n\r\n display: flex;\r\n flex-direction: column;\r\n}\r\n\r\n.rsd__legend {\r\n font-size: var(--rsd-legend-font-size);\r\n font-weight: var(--rsd-legend-font-weight);\r\n margin-bottom: var(--rsd-legend-margin-bottom);\r\n}\r\n\r\n.rsd__select-row {\r\n display: flex;\r\n gap: var(--rsd-gap);\r\n}\r\n\r\n.rsd__error-message {\r\n color: var(--rsd-error-color);\r\n font-size: var(--rsd-error-font-size);\r\n margin-top: var(--rsd-error-margin-top);\r\n}\r\n";r(e);export{e as default};
@@ -1 +1 @@
1
- import{__rest as e,__assign as a}from"../_virtual/_tslib.js";import t,{useState as r,useMemo as n,useCallback as l,useEffect as o}from"react";import{classPrefix as i,getYearsObject as c,getMonthsObject as d,getDaysObject as m}from"../utils/helpers.js";import{OptionsRenderer as u}from"./OptionsRenderer.js";import{SelectRenderer as s}from"./SelectRenderer.js";var h=function(h){var f=h.id,b=h.className,y=h.minDate,v=h.maxDate,p=h.selectedDate,g=h.onDateChange,D=h.disabled,N=void 0!==D&&D,E=h.hasError,L=void 0!==E&&E,R=h.monthRef,P=h.yearRef,j=h.dayRef,C=h.labels,Y=void 0===C?{}:C,x=h.order,O=void 0===x?"month/day/year":x,S=h.reverseYears,H=h.hideLabels,M=e(h,["id","className","minDate","maxDate","selectedDate","onDateChange","disabled","hasError","monthRef","yearRef","dayRef","labels","order","reverseYears","hideLabels"]),_=r(-1),k=_[0],F=_[1],w=r(-1),q=w[0],z=w[1],A=r(-1),B=A[0],G=A[1],I=n((function(){return O?O.split("/"):["month","day","year"]}),[O]),J=n((function(){return["".concat(i,"_react-select-datepicker"),b].join(" ")}),[b]),K=n((function(){return t.createElement(u,{options:c(y,v,S)})}),[v,S,y]),Q=n((function(){return t.createElement(u,{options:d(y,v,k,Y.months)})}),[v,Y.months,y,k]),T=n((function(){return t.createElement(u,{options:m(y,v,q,k)})}),[v,q,y,k]),U=l((function(e){F(Number(e.target.value)),d(y,v,Number(e.target.value)).some((function(e){return e.value===q}))||z(-1),m(y,v,q,Number(e.target.value)).some((function(e){return e.value===B}))||G(-1)}),[B,q,y,v]),V=l((function(e){z(Number(e.target.value)),m(y,v,Number(e.target.value),k).some((function(e){return e.value===B}))||G(-1)}),[B,k,y,v]),W=l((function(e){G(Number(e.target.value))}),[]),X=n((function(){return{day:t.createElement(s,{id:"day",labels:{hide:H,main:Y.dayLabel||"Day",placeholder:Y.dayPlaceholder||"Select Day"},value:B,disabled:N,onChangeHandler:W,selectOptions:T,ref:j}),month:t.createElement(s,{id:"month",labels:{hide:H,main:Y.monthLabel||"Month",placeholder:Y.monthPlaceholder||"Select Month"},value:q,disabled:N,onChangeHandler:V,selectOptions:Q,ref:R}),year:t.createElement(s,{id:"year",labels:{hide:H,main:Y.yearLabel||"Year",placeholder:Y.yearPlaceholder||"Select Year"},value:k,disabled:N,onChangeHandler:U,selectOptions:K,ref:P})}}),[B,T,j,N,W,V,U,H,Y.dayLabel,Y.dayPlaceholder,Y.monthLabel,Y.monthPlaceholder,Y.yearLabel,Y.yearPlaceholder,q,Q,R,k,K,P]);return o((function(){null!=p&&(G(Number(p.getDate())),z(Number(p.getMonth()+1)),F(Number(p.getFullYear())))}),[p]),o((function(){g(-1!==k&&-1!==q&&-1!==B?new Date("".concat(q,"/").concat(B,"/").concat(k)):null)}),[B,q,k]),t.createElement("div",a({},M,{style:{display:"flex"},id:f,className:J},L?{"aria-invalid":!0}:null),I.map((function(e,a){return t.createElement(t.Fragment,{key:"".concat(e,"-").concat(a)},X[e])})))};export{h as SelectDatepicker};
1
+ import{__rest as e,__assign as a}from"../_virtual/_tslib.js";import t,{useState as n,useMemo as r,useRef as o,useEffect as l,useCallback as i}from"react";import{classPrefix as c}from"../utils/helpers.js";import{getCachedYearsObject as s,getCachedMonthsObject as u,getCachedDaysObject as d}from"../utils/performance.js";import{normalizeToLocalMidnight as m,isValidDate as f,createSmartDate as v}from"../utils/dateUtils.js";import{isValidOrder as h,isDate as p,validateDateRange as b,isDateInRange as g}from"../utils/validation.js";import{useFocusManagement as y,useKeyboardNavigation as D}from"../hooks/useKeyboardNavigation.js";import{OptionsRenderer as L}from"./OptionsRenderer.js";import{SelectDatepickerContext as E}from"./SelectDatepickerContext.js";import{SelectDatepickerField as k}from"./SelectDatepickerField.js";import"./SelectDatepicker.css.js";var w=function(w){var N=w.id,C=w.className,S=w.minDate,j=w.maxDate,R=w.selectedDate,_=w.onDateChange,x=w.value,P=w.onChange,O=w.disabled,B=void 0!==O&&O,F=w.hasError,K=void 0!==F&&F,M=w.monthRef,Y=w.yearRef,I=w.dayRef,A=w.labels,U=void 0===A?{}:A,V=w.order,q=void 0===V?"month/day/year":V,z=w.reverseYears,G=w.hideLabels,H=e(w,["id","className","minDate","maxDate","selectedDate","onDateChange","value","onChange","disabled","hasError","monthRef","yearRef","dayRef","labels","order","reverseYears","hideLabels"]),J=n(-1),Q=J[0],T=J[1],W=n(-1),X=W[0],Z=W[1],$=n(-1),ee=$[0],ae=$[1],te=r(function(){return q&&h(q)?q:"month/day/year"},[q]),ne=r(function(){return te.split("/")},[te]),re=o("datepicker-".concat(Math.random().toString(36).substr(2,9))),oe=N||re.current,le=r(function(){var e={};return ne.forEach(function(a){e[a]="".concat(c,"_select-").concat(a,"-").concat(oe)}),e},[ne,oe]),ie=y(ne.map(function(e){return le[e]})),ce=D({onArrowKey:function(e){"right"===e||"down"===e?ie.focusNext():"left"!==e&&"up"!==e||ie.focusPrevious()},enabled:!B}).addKeyboardNavigation;l(function(){var e=[];return ne.forEach(function(a){var t=document.getElementById(le[a]);if(t){var n=ce(t);n&&e.push(n)}}),function(){e.forEach(function(e){return e()})}},[ne,le,ce]);var se=r(function(){return["".concat(c,"_react-select-datepicker"),C].join(" ")},[C]),ue=r(function(){return void 0!==x?x:R},[x,R]),de=r(function(){return null!=P?P:_},[P,_]);l(function(){if("production"!==process.env.NODE_ENV&&(q&&!h(q)&&console.warn('[SelectDatepicker] Invalid order "'.concat(q,'". Falling back to "month/day/year".')),P&&_&&console.warn("[SelectDatepicker] Both onChange and onDateChange provided. onChange will be used."),void 0!==x&&void 0!==R&&console.warn("[SelectDatepicker] Both value and selectedDate provided. value will be used."),de||console.warn("[SelectDatepicker] Missing onChange/onDateChange handler."),S&&!p(S)&&console.warn("[SelectDatepicker] minDate is not a valid Date instance."),j&&!p(j)&&console.warn("[SelectDatepicker] maxDate is not a valid Date instance."),S&&j&&p(S)&&p(j)&&!b(S,j)&&console.warn("[SelectDatepicker] minDate is after maxDate. Range constraints ignored."),null==R||p(R)||console.warn("[SelectDatepicker] selectedDate is not a valid Date instance."),null==U?void 0:U.months)){var e=U.months,a=Array.from({length:12},function(e,a){return a+1}).filter(function(a){return void 0===e[a]});if(a.length>0){var t=a.join(", ");console.warn("[SelectDatepicker] labels.months is missing entries for months: ".concat(t,"."))}}},[q,S,j,R,U,P,_,x,de]);var me=r(function(){return p(S)?m(S):void 0},[S]),fe=r(function(){return p(j)?m(j):void 0},[j]),ve=r(function(){return b(me,fe)},[me,fe]),he=ve?me:void 0,pe=ve?fe:void 0,be=r(function(){return t.createElement(L,{options:s(he,pe,z)})},[pe,he,z]),ge=r(function(){return t.createElement(L,{options:u(he,pe,Q,U.months)})},[pe,he,U.months,Q]),ye=r(function(){return t.createElement(L,{options:d(he,pe,X,Q)})},[pe,he,X,Q]),De=i(function(e){var a=Number(e.target.value);T(a),u(he,pe,a,U.months).some(function(e){return e.value===X})||Z(-1)},[X,he,pe,U.months]),Le=i(function(e){var a=Number(e.target.value);Z(a)},[]),Ee=i(function(e){ae(Number(e.target.value))},[]),ke=r(function(){return{baseId:oe,labels:U,hideLabels:G,disabled:B,hasError:K,day:ee,month:X,year:Q,dayOptions:ye,monthOptions:ge,yearOptions:be,dayRef:I,monthRef:M,yearRef:Y,onDayChange:Ee,onMonthChange:Le,onYearChange:De}},[oe,U,G,B,K,ee,X,Q,ye,ge,be,I,M,Y,Ee,Le,De]);l(function(){null!=ue&&p(ue)&&f(ue)?(ae(Number(ue.getDate())),Z(Number(ue.getMonth()+1)),T(Number(ue.getFullYear()))):(ae(-1),Z(-1),T(-1))},[ue]),l(function(){if(-1!==Q&&-1!==X&&-1!==ee){var e=v(Q,X,ee);g(e,he,pe)?null==de||de(e):null==de||de(null)}else null==de||de(null)},[ee,X,Q,de,he,pe]);var we=r(function(){var e,a,t;if(!K)return null;if(-1===ee&&-1===X&&-1===Q)return"Please select a date";var n=[];return-1===ee&&n.push((null===(e=U.dayLabel)||void 0===e?void 0:e.toLowerCase())||"day"),-1===X&&n.push((null===(a=U.monthLabel)||void 0===a?void 0:a.toLowerCase())||"month"),-1===Q&&n.push((null===(t=U.yearLabel)||void 0===t?void 0:t.toLowerCase())||"year"),1===n.length?"Please select a ".concat(n[0]):2===n.length?"Please select a ".concat(n[0]," and ").concat(n[1]):"Please select all date fields"},[K,ee,X,Q,U.dayLabel,U.monthLabel,U.yearLabel]),Ne="".concat(N||oe,"-legend"),Ce=Boolean(U.groupLabel||!G),Se=U.groupLabel?U.groupLabel:U.yearLabel&&U.monthLabel&&U.dayLabel?"Select ".concat(U.monthLabel,", ").concat(U.dayLabel,", and ").concat(U.yearLabel):"Select date";return t.createElement("div",a({},H,{className:se,id:N,role:"group","aria-labelledby":Ce?Ne:void 0,"aria-describedby":we?"".concat(N||oe,"-error"):void 0,"aria-invalid":K}),Ce&&t.createElement("label",{id:Ne,className:"".concat(c,"_legend")},Se),t.createElement(E.Provider,{value:ke},t.createElement("div",{className:"".concat(c,"_select-row")},ne.map(function(e,a){var n=e;return t.createElement(t.Fragment,{key:"".concat(e,"-").concat(a)},t.createElement(k,{fieldKey:n}))}))),we&&t.createElement("div",{id:"".concat(N||oe,"-error"),className:"".concat(c,"_error-message"),role:"alert","aria-live":"polite"},we))};export{w as SelectDatepicker};
@@ -0,0 +1 @@
1
+ import r from"react";var t=r.createContext(null);export{t as SelectDatepickerContext};
@@ -0,0 +1 @@
1
+ import{__extends as r}from"../_virtual/_tslib.js";import e from"react";var t=function(t){function o(){var r=null!==t&&t.apply(this,arguments)||this;return r.state={hasError:!1},r}return r(o,t),o.getDerivedStateFromError=function(r){return{hasError:!0,error:r}},o.prototype.componentDidCatch=function(r){"production"!==process.env.NODE_ENV&&console.error("[SelectDatepicker] Error boundary caught an error:",r)},o.prototype.render=function(){var r=this.state,t=r.hasError,o=r.error,n=this.props,a=n.children,i=n.fallback,c=n.renderFallback;return t?c&&o?c(o):i||e.createElement("div",{role:"alert",style:{padding:"12px"}},"Something went wrong while rendering the date picker."):a},o}(e.Component);export{t as SelectDatepickerErrorBoundary};
@@ -0,0 +1 @@
1
+ import e,{useContext as a}from"react";import{SelectRenderer as n}from"./SelectRenderer.js";import{SelectDatepickerContext as r}from"./SelectDatepickerContext.js";var l=function(l){var o=l.fieldKey,t=a(r);if(!t)throw new Error("SelectDatepickerField must be used within SelectDatepickerContext");var d=t.baseId,i=t.labels,h=t.hideLabels,c=t.disabled,s=t.hasError,m=t.day,p=t.month,y=t.year,b=t.dayOptions,f=t.monthOptions,u=t.yearOptions,C=t.dayRef,v=t.monthRef,g=t.yearRef,S=t.onDayChange,D=t.onMonthChange,H=t.onYearChange,L={day:{id:"day-".concat(d),value:m,labels:{hide:h,main:i.dayLabel||"Day",placeholder:i.dayPlaceholder||"Select Day"},options:b,onChangeHandler:S,ref:C},month:{id:"month-".concat(d),value:p,labels:{hide:h,main:i.monthLabel||"Month",placeholder:i.monthPlaceholder||"Select Month"},options:f,onChangeHandler:D,ref:v},year:{id:"year-".concat(d),value:y,labels:{hide:h,main:i.yearLabel||"Year",placeholder:i.yearPlaceholder||"Select Year"},options:u,onChangeHandler:H,ref:g}}[o];return e.createElement(n,{id:L.id,labels:L.labels,value:L.value,disabled:c,onChangeHandler:L.onChangeHandler,selectOptions:L.options,ref:L.ref,required:!0,invalid:s})};export{l as SelectDatepickerField};
@@ -0,0 +1 @@
1
+ import r from"../node_modules/style-inject/dist/style-inject.es.js";var e=".rsd__select-container {\r\n display: flex;\r\n flex-direction: column;\r\n}\r\n\r\n.rsd__label {\r\n margin-bottom: var(--rsd-label-margin-bottom);\r\n}\r\n\r\n.rsd__select {\r\n padding: var(--rsd-select-padding);\r\n border: var(--rsd-select-border);\r\n border-radius: var(--rsd-select-border-radius);\r\n font-size: var(--rsd-select-font-size);\r\n}\r\n\r\n.rsd__select:disabled {\r\n background: var(--rsd-select-disabled-bg);\r\n color: var(--rsd-select-disabled-color);\r\n}\r\n\r\n.rsd__required-indicator {\r\n color: var(--rsd-required-color);\r\n margin-left: var(--rsd-required-margin-left);\r\n}\r\n";r(e);export{e as default};
@@ -1 +1 @@
1
- import e from"react";import{classPrefix as t}from"../utils/helpers.js";var a=function(a){var c=a.id,l=a.labels,n=a.value,o=a.disabled,r=a.onChangeHandler,s=a.selectOptions,i=a.ref;return e.createElement("div",{style:{display:"flex",flexDirection:"column"},className:"".concat(t,"_select-container-").concat(c)},!l.hide&&e.createElement("label",{htmlFor:"".concat(t,"_select-").concat(c)},l.main),e.createElement("select",{id:"".concat(t,"_select-").concat(c),value:n,disabled:o,onChange:r,ref:i,className:"".concat(t,"_select-").concat(c)},e.createElement("option",{value:-1,disabled:!0},l.placeholder),s))};export{a as SelectRenderer};
1
+ import e from"react";import{classPrefix as a}from"../utils/helpers.js";import"./SelectRenderer.css.js";var c=function(c){var l=c.id,t=c.labels,n=c.value,r=c.disabled,i=c.onChangeHandler,o=c.selectOptions,s=c.ref,d=c.required,m=void 0!==d&&d,b=c.invalid,v=void 0!==b&&b,u="".concat(a,"_select-").concat(l),p="".concat(a,"_label-").concat(l);return e.createElement("div",{className:"".concat(a,"_select-container ").concat(a,"_select-container-").concat(l)},!t.hide&&e.createElement("label",{id:p,htmlFor:u,className:"".concat(a,"_label ").concat(a,"_label-").concat(l)},t.main,m&&e.createElement("span",{"aria-label":"required",className:"".concat(a,"_required-indicator")},"*")),e.createElement("select",{id:u,value:n,disabled:r,onChange:i,ref:s,className:"".concat(a,"_select ").concat(a,"_select-").concat(l),required:m,"aria-invalid":v,"aria-labelledby":t.hide?void 0:p},e.createElement("option",{value:-1,disabled:!0},t.placeholder),o))};export{c as SelectRenderer};
@@ -0,0 +1 @@
1
+ import{useCallback as e,useRef as n}from"react";var r=function(n){void 0===n&&(n={});var r=n.onEnter,t=n.onEscape,o=n.onArrowKey,c=n.onTab,u=n.enabled,a=void 0===u||u,f=e(function(e){if(a)switch(e.key){case"ArrowLeft":case"ArrowRight":case"ArrowUp":case"ArrowDown":e.preventDefault();var n=e.key.replace("Arrow","").toLowerCase();null==o||o(n);break;case"Enter":e.preventDefault(),null==r||r();break;case"Escape":e.preventDefault(),null==t||t();break;case"Tab":null==c||c(e.shiftKey)}},[a,r,t,o,c]);return{addKeyboardNavigation:e(function(e){if(e&&a)return e.addEventListener("keydown",f),function(){e.removeEventListener("keydown",f)}},[f,a])}},t=function(r){var t=n(0),o=e(function(e){var n=document.getElementById(r[e]);n&&n instanceof HTMLSelectElement&&(n.focus(),t.current=e)},[r]),c=e(function(){var e=(t.current+1)%r.length;o(e)},[r.length,o]),u=e(function(){var e=0===t.current?r.length-1:t.current-1;o(e)},[r.length,o]),a=e(function(){o(0)},[o]),f=e(function(){o(r.length-1)},[r.length,o]),i=e(function(e){var n=r.indexOf(e);-1!==n&&(t.current=n)},[r]);return{focusNext:c,focusPrevious:u,focusFirst:a,focusLast:f,focusElement:o,updateCurrentFocusIndex:i,currentFocusIndex:t.current}};export{t as useFocusManagement,r as useKeyboardNavigation};
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- export{SelectDatepicker}from"./components/SelectDatepicker.js";
1
+ export{SelectDatepicker}from"./components/SelectDatepicker.js";export{SelectDatepickerErrorBoundary}from"./components/SelectDatepickerErrorBoundary.js";
@@ -0,0 +1 @@
1
+ function e(e,t){void 0===t&&(t={});var d=t.insertAt;if(e&&"undefined"!=typeof document){var n=document.head||document.getElementsByTagName("head")[0],s=document.createElement("style");s.type="text/css","top"===d&&n.firstChild?n.insertBefore(s,n.firstChild):n.appendChild(s),s.styleSheet?s.styleSheet.cssText=e:s.appendChild(document.createTextNode(e))}}export{e as default};
@@ -0,0 +1,5 @@
1
+ /// <reference types="react" />
2
+ import { ISelectDatepicker } from '../interfaces/ISelectDatePicker';
3
+ import './SelectDatepicker.css';
4
+ declare const SelectDatepicker: ({ id, className, minDate, maxDate, selectedDate, onDateChange, value, onChange, disabled, hasError, monthRef, yearRef, dayRef, labels, order, reverseYears, hideLabels, ...args }: ISelectDatepicker) => JSX.Element;
5
+ export { SelectDatepicker };
@@ -0,0 +1,23 @@
1
+ import React from 'react';
2
+ import { SelectDatepickerLabels } from '../types/SelectDatepickerLabels';
3
+ export type DatepickerFieldKey = 'day' | 'month' | 'year';
4
+ export interface SelectDatepickerContextValue {
5
+ baseId: string;
6
+ labels: Partial<SelectDatepickerLabels>;
7
+ hideLabels?: boolean;
8
+ disabled?: boolean;
9
+ hasError?: boolean;
10
+ day: number;
11
+ month: number;
12
+ year: number;
13
+ dayOptions: JSX.Element;
14
+ monthOptions: JSX.Element;
15
+ yearOptions: JSX.Element;
16
+ dayRef?: React.LegacyRef<HTMLSelectElement>;
17
+ monthRef?: React.LegacyRef<HTMLSelectElement>;
18
+ yearRef?: React.LegacyRef<HTMLSelectElement>;
19
+ onDayChange: (e: React.ChangeEvent<HTMLSelectElement>) => void;
20
+ onMonthChange: (e: React.ChangeEvent<HTMLSelectElement>) => void;
21
+ onYearChange: (e: React.ChangeEvent<HTMLSelectElement>) => void;
22
+ }
23
+ export declare const SelectDatepickerContext: React.Context<SelectDatepickerContextValue | null>;
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ interface SelectDatepickerErrorBoundaryProps {
3
+ children: React.ReactNode;
4
+ fallback?: React.ReactNode;
5
+ renderFallback?: (error: Error) => React.ReactNode;
6
+ }
7
+ interface SelectDatepickerErrorBoundaryState {
8
+ hasError: boolean;
9
+ error?: Error;
10
+ }
11
+ export declare class SelectDatepickerErrorBoundary extends React.Component<SelectDatepickerErrorBoundaryProps, SelectDatepickerErrorBoundaryState> {
12
+ state: SelectDatepickerErrorBoundaryState;
13
+ static getDerivedStateFromError(error: Error): SelectDatepickerErrorBoundaryState;
14
+ componentDidCatch(error: Error): void;
15
+ render(): React.ReactNode;
16
+ }
17
+ export {};
@@ -0,0 +1,7 @@
1
+ /// <reference types="react" />
2
+ import { DatepickerFieldKey } from './SelectDatepickerContext';
3
+ interface SelectDatepickerFieldProps {
4
+ fieldKey: DatepickerFieldKey;
5
+ }
6
+ export declare const SelectDatepickerField: ({ fieldKey }: SelectDatepickerFieldProps) => JSX.Element;
7
+ export {};
@@ -1,4 +1,5 @@
1
1
  import React from 'react';
2
+ import './SelectRenderer.css';
2
3
  interface ISelectRenderer {
3
4
  id: string;
4
5
  labels: {
@@ -11,6 +12,8 @@ interface ISelectRenderer {
11
12
  onChangeHandler: (e: React.ChangeEvent<HTMLSelectElement>) => void;
12
13
  selectOptions: JSX.Element;
13
14
  ref?: React.LegacyRef<HTMLSelectElement>;
15
+ required?: boolean;
16
+ invalid?: boolean;
14
17
  }
15
- export declare const SelectRenderer: ({ id, labels, value, disabled, onChangeHandler, selectOptions, ref, }: ISelectRenderer) => JSX.Element;
18
+ export declare const SelectRenderer: ({ id, labels, value, disabled, onChangeHandler, selectOptions, ref, required, invalid, }: ISelectRenderer) => JSX.Element;
16
19
  export {};
@@ -0,0 +1,23 @@
1
+ interface KeyboardNavigationOptions {
2
+ onEnter?: () => void;
3
+ onEscape?: () => void;
4
+ onArrowKey?: (direction: 'up' | 'down' | 'left' | 'right') => void;
5
+ onTab?: (shiftKey: boolean) => void;
6
+ enabled?: boolean;
7
+ }
8
+ export declare const useKeyboardNavigation: (options?: KeyboardNavigationOptions) => {
9
+ addKeyboardNavigation: (element: HTMLElement | null) => (() => void) | undefined;
10
+ };
11
+ /**
12
+ * Hook for managing focus between multiple form elements
13
+ */
14
+ export declare const useFocusManagement: (elementIds: string[]) => {
15
+ focusNext: () => void;
16
+ focusPrevious: () => void;
17
+ focusFirst: () => void;
18
+ focusLast: () => void;
19
+ focusElement: (index: number) => void;
20
+ updateCurrentFocusIndex: (elementId: string) => void;
21
+ currentFocusIndex: number;
22
+ };
23
+ export {};
@@ -1,4 +1,5 @@
1
1
  export { SelectDatepicker } from './components/SelectDatepicker';
2
+ export { SelectDatepickerErrorBoundary } from './components/SelectDatepickerErrorBoundary';
2
3
  export { ISelectDatepicker } from './interfaces/ISelectDatePicker';
3
4
  export { SelectDatepickerLabels } from './types/SelectDatepickerLabels';
4
5
  export { SelectDatepickerOrder } from './types/SelectDatepickerOrder';
@@ -0,0 +1,39 @@
1
+ /// <reference types="react" />
2
+ import { SelectDatepickerLabels } from '../types/SelectDatepickerLabels';
3
+ import { SelectDatepickerOrder } from '../types/SelectDatepickerOrder';
4
+ export interface ISelectDatepicker {
5
+ /** Unique identifier for the date picker component */
6
+ id?: string;
7
+ /** Additional CSS class names */
8
+ className?: string;
9
+ /** Minimum selectable date */
10
+ minDate?: Date;
11
+ /** Maximum selectable date */
12
+ maxDate?: Date;
13
+ /** Currently selected date (deprecated: use value) */
14
+ selectedDate?: Date | null;
15
+ /** Callback function called when date changes (deprecated: use onChange) */
16
+ onDateChange?: (date: Date | null) => void;
17
+ /** Controlled value (preferred) */
18
+ value?: Date | null;
19
+ /** Change handler (preferred) */
20
+ onChange?: (date: Date | null) => void;
21
+ /** Custom labels for the date picker */
22
+ labels?: Partial<SelectDatepickerLabels>;
23
+ /** Whether the date picker is disabled */
24
+ disabled?: boolean;
25
+ /** Whether the date picker has an error state */
26
+ hasError?: boolean;
27
+ /** Ref for the month select element */
28
+ monthRef?: React.LegacyRef<HTMLSelectElement>;
29
+ /** Ref for the year select element */
30
+ yearRef?: React.LegacyRef<HTMLSelectElement>;
31
+ /** Ref for the day select element */
32
+ dayRef?: React.LegacyRef<HTMLSelectElement>;
33
+ /** Whether to reverse the order of years in the dropdown */
34
+ reverseYears?: boolean;
35
+ /** Whether to hide labels above the select inputs */
36
+ hideLabels?: boolean;
37
+ /** Order of date selects (defaults to 'month/day/year') */
38
+ order?: SelectDatepickerOrder;
39
+ }
@@ -0,0 +1,32 @@
1
+ export type Months = {
2
+ readonly 1: string;
3
+ readonly 2: string;
4
+ readonly 3: string;
5
+ readonly 4: string;
6
+ readonly 5: string;
7
+ readonly 6: string;
8
+ readonly 7: string;
9
+ readonly 8: string;
10
+ readonly 9: string;
11
+ readonly 10: string;
12
+ readonly 11: string;
13
+ readonly 12: string;
14
+ };
15
+ export type SelectDatepickerLabels = {
16
+ /** Single label for the entire date picker group */
17
+ readonly groupLabel?: string;
18
+ /** Label for the year select field */
19
+ readonly yearLabel?: string;
20
+ /** Label for the month select field */
21
+ readonly monthLabel?: string;
22
+ /** Label for the day select field */
23
+ readonly dayLabel?: string;
24
+ /** Placeholder for the year select field */
25
+ readonly yearPlaceholder?: string;
26
+ /** Placeholder for the month select field */
27
+ readonly monthPlaceholder?: string;
28
+ /** Placeholder for the day select field */
29
+ readonly dayPlaceholder?: string;
30
+ /** Custom month names (1-12 indexed) */
31
+ readonly months?: Months;
32
+ };
@@ -0,0 +1 @@
1
+ export type SelectDatepickerOrder = 'day/month/year' | 'day/year/month' | 'month/day/year' | 'month/year/day' | 'year/month/day' | 'year/day/month';
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Timezone-safe date utilities for react-select-datepicker
3
+ * These functions avoid locale-dependent string parsing
4
+ */
5
+ /**
6
+ * Creates a Date object from year, month, day parameters
7
+ * @param year Full year (e.g., 2024)
8
+ * @param month Month number (1-12)
9
+ * @param day Day number (1-31)
10
+ * @returns Date object in local timezone
11
+ */
12
+ export declare const createSafeDate: (year: number, month: number, day: number) => Date;
13
+ /**
14
+ * Creates a Date object with smart date correction for invalid dates
15
+ * If the day is too large for the month, it clamps to the last day of the month
16
+ * @param year Full year (e.g., 2024)
17
+ * @param month Month number (1-12)
18
+ * @param day Day number (1-31)
19
+ * @returns Date object in local timezone with corrected day if needed
20
+ */
21
+ export declare const createSmartDate: (year: number, month: number, day: number) => Date;
22
+ /**
23
+ * Creates a Date object for the first day of a given month/year
24
+ * @param year Full year (e.g., 2024)
25
+ * @param month Month number (1-12)
26
+ * @returns Date object for the first day of the month
27
+ */
28
+ export declare const createFirstOfMonth: (year: number, month: number) => Date;
29
+ /**
30
+ * Normalizes a Date to local midnight to avoid timezone-related shifts
31
+ * @param date Date to normalize
32
+ * @returns Date at local midnight
33
+ */
34
+ export declare const normalizeToLocalMidnight: (date: Date) => Date;
35
+ /**
36
+ * Checks if a date is valid (not NaN)
37
+ * @param date Date object to check
38
+ * @returns true if date is valid
39
+ */
40
+ export declare const isValidDate: (date: Date) => boolean;
41
+ /**
42
+ * Checks if a specific year/month/day combination is valid
43
+ * @param year Full year (e.g., 2024)
44
+ * @param month Month number (1-12)
45
+ * @param day Day number (1-31)
46
+ * @returns true if the date is valid
47
+ */
48
+ export declare const isValidDateCombination: (year: number, month: number, day: number) => boolean;
49
+ /**
50
+ * Gets the number of days in a specific month/year
51
+ * @param year Full year (e.g., 2024)
52
+ * @param month Month number (1-12)
53
+ * @returns Number of days in the month
54
+ */
55
+ export declare const getDaysInMonth: (year: number, month: number) => number;
56
+ /**
57
+ * Gets all days in a month as an array of numbers
58
+ * @param year Full year (e.g., 2024)
59
+ * @param month Month number (1-12)
60
+ * @returns Array of day numbers (1-31)
61
+ */
62
+ export declare const getAllDaysInMonthSafe: (year: number, month: number) => number[];
@@ -3,17 +3,17 @@ export declare const classPrefix = "rsd_";
3
3
  export declare const range: (start: number, stop: number, step: number) => number[];
4
4
  export declare const getAllDaysInMonth: (year: number, month: number) => number[];
5
5
  export declare const englishMonths: Months;
6
- export declare const getYearsObject: (start?: Date | undefined, end?: Date | undefined, reverse?: boolean | undefined) => {
6
+ export declare const getYearsObject: (start?: Date, end?: Date, reverse?: boolean) => {
7
7
  value: number;
8
8
  label: string;
9
9
  }[];
10
- export declare const getMonthsObject: (start?: Date | undefined, end?: Date | undefined, selectedYear?: number, months?: {
10
+ export declare const getMonthsObject: (start?: Date, end?: Date, selectedYear?: number, months?: {
11
11
  [key: string]: string;
12
12
  }) => {
13
13
  value: number;
14
14
  label: string;
15
15
  }[];
16
- export declare const getDaysObject: (start?: Date | undefined, end?: Date | undefined, selectedMonth?: number, selectedYear?: number) => {
16
+ export declare const getDaysObject: (start?: Date, end?: Date, selectedMonth?: number, selectedYear?: number) => {
17
17
  value: number;
18
18
  label: string;
19
19
  }[];
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Performance optimization utilities for react-select-datepicker
3
+ */
4
+ /**
5
+ * Creates a cache key from multiple parameters
6
+ */
7
+ export declare const createCacheKey: (...args: (string | number | boolean | undefined)[]) => string;
8
+ /**
9
+ * Range generator with better performance than Array.from
10
+ */
11
+ export declare const createRange: (start: number, stop: number, step: number) => number[];
12
+ /**
13
+ * Cached years object generator
14
+ */
15
+ export declare const getCachedYearsObject: (start?: Date, end?: Date, reverse?: boolean) => {
16
+ value: number;
17
+ label: string;
18
+ }[];
19
+ /**
20
+ * Cached months object generator
21
+ */
22
+ export declare const getCachedMonthsObject: (start?: Date, end?: Date, selectedYear?: number, months?: {
23
+ [key: string]: string;
24
+ }) => {
25
+ value: number;
26
+ label: string;
27
+ }[];
28
+ /**
29
+ * Cached days object generator
30
+ */
31
+ export declare const getCachedDaysObject: (start?: Date, end?: Date, selectedMonth?: number, selectedYear?: number) => {
32
+ value: number;
33
+ label: string;
34
+ }[];
35
+ /**
36
+ * Clear all caches (useful for testing or memory management)
37
+ */
38
+ export declare const clearAllCaches: () => void;
@@ -0,0 +1,18 @@
1
+ import { SelectDatepickerOrder } from '../types/SelectDatepickerOrder';
2
+ export declare const VALID_ORDERS: readonly ["day/month/year", "day/year/month", "month/day/year", "month/year/day", "year/month/day", "year/day/month"];
3
+ /**
4
+ * Validates if a string is a valid SelectDatepickerOrder
5
+ */
6
+ export declare function isValidOrder(order: string): order is SelectDatepickerOrder;
7
+ /**
8
+ * Validates date range to ensure minDate is before maxDate
9
+ */
10
+ export declare function validateDateRange(minDate?: Date, maxDate?: Date): boolean;
11
+ /**
12
+ * Validates if a date is within the allowed range
13
+ */
14
+ export declare function isDateInRange(date: Date, minDate?: Date, maxDate?: Date): boolean;
15
+ /**
16
+ * Type guard to check if value is a Date object
17
+ */
18
+ export declare function isDate(value: unknown): value is Date;
@@ -0,0 +1 @@
1
+ var t=function(t,e,n){var a=r(t,e),u=Math.min(n,a);return new Date(t,e-1,u,0,0,0,0)},e=function(t){return new Date(t.getFullYear(),t.getMonth(),t.getDate(),0,0,0,0)},n=function(t){return!isNaN(t.getTime())},r=function(t,e){return new Date(t,e,0).getDate()};export{t as createSmartDate,r as getDaysInMonth,n as isValidDate,e as normalizeToLocalMidnight};
@@ -1 +1 @@
1
- var e="rsd_",t=function(e,t,r){return Array.from({length:(t-e)/r+1},(function(t,n){return e+n*r}))},r=function(e,t){for(var r=new Date("".concat(e,"/").concat(t,"/01")),n=[];r.getMonth()+1===t;)n.push(new Date(r).getDate()),r.setDate(r.getDate()+1);return n},n={1:"January",2:"February",3:"March",4:"April",5:"May",6:"June",7:"July",8:"August",9:"September",10:"October",11:"November",12:"December"},a=function(e,r,n){var a=t(r?r.getFullYear():(new Date).getFullYear(),e?e.getFullYear():1900,-1);return n&&(a=a.reverse()),a.map((function(e,t){return{value:e,label:"".concat(e)}}))},u=function(e,r,a,u){void 0===a&&(a=-1),void 0===u&&(u=n);var l=t(1,12,1);if(r&&-1!==a&&a===r.getFullYear()){var o=r.getMonth()+1;l=l.slice(0,o)}if(e&&-1!==a&&a===e.getFullYear()){var c=e.getMonth()+1;l=l.slice(c-1,l.length)}return l.map((function(e,t){return{value:e,label:u[e]}}))},l=function(e,n,a,u){void 0===a&&(a=-1),void 0===u&&(u=-1);var l=[];if(-1===a)return(l=t(1,31,1)).map((function(e,t){return{value:e,label:"".concat(e)}}));if(l=r(-1===u?1900:u,a),n&&u===n.getFullYear()&&a===n.getMonth()+1){var o=n.getDate();l=l.slice(0,o)}if(e&&u===e.getFullYear()&&a===e.getMonth()+1){var c=e.getDate();l=l.slice(c-1,l.length)}return l.map((function(e,t){return{value:e,label:"".concat(e)}}))};export{e as classPrefix,n as englishMonths,r as getAllDaysInMonth,l as getDaysObject,u as getMonthsObject,a as getYearsObject,t as range};
1
+ var r="rsd_";export{r as classPrefix};
@@ -0,0 +1 @@
1
+ var e=function(){function e(e){void 0===e&&(e=50),this.cache=new Map,this.maxSize=e}return e.prototype.get=function(e){var t=this.cache.get(e);return void 0!==t&&(this.cache.delete(e),this.cache.set(e,t)),t},e.prototype.set=function(e,t){if(this.cache.has(e))this.cache.delete(e);else if(this.cache.size>=this.maxSize){var n=this.cache.keys().next().value;void 0!==n&&this.cache.delete(n)}this.cache.set(e,t)},e.prototype.clear=function(){this.cache.clear()},e}(),t=new e,n=new e,r=new e,a=function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];return e.map(function(e){return String(e||"undefined")}).join("|")},l=function(e,t,n){for(var r=Math.floor((t-e)/n)+1,a=new Array(r),l=0;l<r;l++)a[l]=e+l*n;return a},i=function(e,n,r){var i=a((null==e?void 0:e.getFullYear())||"undefined",(null==n?void 0:n.getFullYear())||(new Date).getFullYear(),r||!1),u=t.get(i);if(u)return u;var o=n?n.getFullYear():(new Date).getFullYear(),c=e?e.getFullYear():1900,h=l(o,c,-1);r&&(h=h.reverse()),u=new Array(h.length);for(var v=0;v<h.length;v++)u[v]={value:h[v],label:"".concat(h[v])};return t.set(i,u),u},u=function(e,t,r,i){void 0===r&&(r=-1),void 0===i&&(i={1:"January",2:"February",3:"March",4:"April",5:"May",6:"June",7:"July",8:"August",9:"September",10:"October",11:"November",12:"December"});var u=Object.keys(i).sort(function(e,t){return Number(e)-Number(t)}).map(function(e){return"".concat(e,":").concat(i[e])}).join(","),o=a((null==e?void 0:e.getFullYear())||"undefined",(null==t?void 0:t.getFullYear())||"undefined",r,u),c=n.get(o);if(c)return c;var h=l(1,12,1);if(t&&-1!==r&&r===t.getFullYear()){var v=t.getMonth()+1;h=h.slice(0,v)}if(e&&-1!==r&&r===e.getFullYear()){var g=e.getMonth()+1;h=h.slice(g-1,h.length)}c=new Array(h.length);for(var f=0;f<h.length;f++){var d=h[f];c[f]={value:d,label:i[d]||"Month ".concat(d)}}return n.set(o,c),c},o=function(e,t,n,i){void 0===n&&(n=-1),void 0===i&&(i=-1);var u=a((null==e?void 0:e.getFullYear())||"undefined",(null==e?void 0:e.getMonth())||"undefined",(null==t?void 0:t.getFullYear())||"undefined",(null==t?void 0:t.getMonth())||"undefined",n,i),o=r.get(u);if(o)return o;var c=[];if(-1===n)c=l(1,31,1);else{var h=new Date(-1===i?1900:i,n,0).getDate();c=l(1,h,1)}if(t&&i===t.getFullYear()&&n===t.getMonth()+1){var v=t.getDate();c=c.slice(0,v)}if(e&&i===e.getFullYear()&&n===e.getMonth()+1){var g=e.getDate();c=c.slice(g-1,c.length)}o=new Array(c.length);for(var f=0;f<c.length;f++)o[f]={value:c[f],label:"".concat(c[f])};return r.set(u,o),o};export{a as createCacheKey,l as createRange,o as getCachedDaysObject,u as getCachedMonthsObject,i as getCachedYearsObject};
@@ -0,0 +1 @@
1
+ import{normalizeToLocalMidnight as n}from"./dateUtils.js";var t=["day/month/year","day/year/month","month/day/year","month/year/day","year/month/day","year/day/month"];function r(n){return t.includes(n)}function a(t,r){return!t||!r||n(t)<=n(r)}function e(t,r,a){var e=n(t);return!(r&&e<n(r))&&!(a&&e>n(a))}function o(n){return n instanceof Date&&!isNaN(n.getTime())}export{t as VALID_ORDERS,o as isDate,e as isDateInRange,r as isValidOrder,a as validateDateRange};
@@ -0,0 +1,2 @@
1
+ declare const _default: import("vite").UserConfig;
2
+ export default _default;
@@ -0,0 +1 @@
1
+ import '@testing-library/jest-dom';
package/package.json CHANGED
@@ -1,10 +1,13 @@
1
1
  {
2
2
  "name": "react-select-datepicker",
3
- "version": "2.1.2",
3
+ "version": "3.0.1",
4
4
  "description": "A simple and reusable dropdown datepicker component for React",
5
5
  "author": "JMcAmmond",
6
6
  "license": "MIT",
7
- "repository": "JMcAmmond/react-select-datepicker",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/JMcAmmond/react-select-datepicker.git"
10
+ },
8
11
  "bugs": {
9
12
  "url": "https://github.com/JMcAmmond/react-select-datepicker/issues"
10
13
  },
@@ -23,44 +26,41 @@
23
26
  "files": [
24
27
  "dist"
25
28
  ],
26
- "dependencies": {},
27
29
  "peerDependencies": {
28
- "react": ">=17.0.2"
30
+ "react": ">=17.0.2 <20",
31
+ "react-dom": ">=17.0.2 <20"
29
32
  },
30
33
  "devDependencies": {
31
34
  "@babel/core": "^7.17.0",
32
35
  "@rollup/plugin-commonjs": "^21.0.2",
33
36
  "@rollup/plugin-node-resolve": "^13.1.3",
34
37
  "@rollup/plugin-url": "^6.1.0",
35
- "@storybook/addon-a11y": "^6.5.12",
36
- "@storybook/addon-actions": "^6.5.12",
37
- "@storybook/addon-essentials": "^6.5.12",
38
- "@storybook/addon-interactions": "^6.5.12",
39
- "@storybook/addon-links": "^6.5.12",
40
- "@storybook/addon-storysource": "^6.5.12",
41
- "@storybook/react": "^6.5.12",
42
- "@storybook/testing-library": "0.0.13",
38
+ "@storybook/addon-a11y": "^10.1.11",
39
+ "@storybook/addon-docs": "^10.1.11",
40
+ "@storybook/addon-links": "^10.1.11",
41
+ "@storybook/manager-api": "^8.6.14",
42
+ "@storybook/react": "^10.1.11",
43
+ "@storybook/react-vite": "^10.1.11",
43
44
  "@svgr/rollup": "^6.2.1",
44
- "@svgr/webpack": "^5.5.0",
45
- "@testing-library/jest-dom": "^5.16.2",
45
+ "@svgr/webpack": "^8.1.0",
46
+ "@testing-library/jest-dom": "^5.17.0",
46
47
  "@testing-library/react": "^12.1.2",
47
48
  "@testing-library/user-event": "^13.5.0",
48
- "@types/jest": "^27.4.0",
49
49
  "@types/node": "^16.11.22",
50
50
  "@types/react": "^17.0.39",
51
51
  "@types/react-dom": "^17.0.11",
52
52
  "@types/styled-components": "^5.1.25",
53
- "@typescript-eslint/eslint-plugin": "^5.12.1",
54
- "@typescript-eslint/parser": "^5.12.1",
53
+ "@typescript-eslint/eslint-plugin": "^6.21.0",
54
+ "@typescript-eslint/parser": "^6.21.0",
55
+ "@vitest/ui": "^4.0.17",
55
56
  "babel-loader": "^8.2.3",
56
- "eslint": "^8.8.0",
57
+ "eslint": "^8.57.0",
57
58
  "eslint-config-airbnb": "^19.0.4",
58
59
  "eslint-config-airbnb-typescript": "^16.1.0",
59
60
  "eslint-config-prettier": "^8.4.0",
60
61
  "eslint-plugin-eslint-comments": "^3.2.0",
61
62
  "eslint-plugin-html": "^6.2.0",
62
63
  "eslint-plugin-import": "^2.25.4",
63
- "eslint-plugin-jest": "^26.1.1",
64
64
  "eslint-plugin-json": "^3.1.0",
65
65
  "eslint-plugin-json-files": "^1.3.0",
66
66
  "eslint-plugin-jsx-a11y": "^6.5.1",
@@ -68,10 +68,10 @@
68
68
  "eslint-plugin-progress": "0.0.1",
69
69
  "eslint-plugin-react": "^7.28.0",
70
70
  "eslint-plugin-react-hooks": "^4.3.0",
71
- "eslint-plugin-storybook": "^0.6.4",
71
+ "eslint-plugin-storybook": "^0.8.0",
72
72
  "eslint-plugin-unused-imports": "^2.0.0",
73
- "gh-pages": "^3.2.3",
74
- "jest": "^27.5.1",
73
+ "gh-pages": "^6.3.0",
74
+ "jsdom": "^27.4.0",
75
75
  "postcss": "^8.4.7",
76
76
  "prettier": "^2.5.1",
77
77
  "react": "^17.0.2",
@@ -82,25 +82,31 @@
82
82
  "rollup-plugin-postcss": "^4.0.2",
83
83
  "rollup-plugin-terser": "^7.0.2",
84
84
  "rollup-plugin-typescript2": "^0.31.2",
85
+ "storybook": "^10.1.11",
85
86
  "styled-components": "^5.3.5",
86
87
  "tslib": "^2.3.1",
87
- "typescript": "^4.6.2",
88
- "url-loader": "^4.1.1"
88
+ "typescript": "^4.9.5",
89
+ "url-loader": "^4.1.1",
90
+ "vite": "^7.3.1",
91
+ "vitest": "^4.0.17"
89
92
  },
90
93
  "scripts": {
91
- "test": "npm run test:eslint && npm run test:conflicts && npm run test:ts",
92
- "test:eslint": "npx eslint --ext .js,.jsx,.json,.html,.ts,.tsx,.mjs --report-unused-disable-directives ./src",
94
+ "test": "npm run test:eslint && npm run test:conflicts && npm run test:ts && npm run test:unit",
95
+ "test:eslint": "npx eslint --config eslint.config.js \"src/**/*.{js,jsx,ts,tsx}\"",
93
96
  "test:conflicts": "eslint-config-prettier .eslint.config.js",
94
97
  "test:ts": "npx tsc -p ./tsconfig.json --noEmit",
95
- "start": "start-storybook -p 6006",
98
+ "test:unit": "vitest run",
99
+ "test:watch": "vitest",
100
+ "test:ui": "vitest --ui",
101
+ "start": "storybook dev -p 6006",
96
102
  "bundle": "rollup -c",
97
103
  "clean": "rm -rf ./dist ./storybook-static",
98
- "build": "npm run clean && build-storybook && npm run bundle",
104
+ "build": "npm run clean && storybook build && npm run bundle",
99
105
  "deploy": "gh-pages -d storybook-static"
100
106
  },
101
107
  "eslintConfig": {
102
108
  "extends": [
103
- "./eslint.config.js"
109
+ "./.eslintrc.cjs"
104
110
  ],
105
111
  "parserOptions": {
106
112
  "project": [
@@ -1,4 +0,0 @@
1
- /// <reference types="react" />
2
- import { ISelectDatepicker } from '../interfaces/ISelectDatePicker';
3
- declare const SelectDatepicker: ({ id, className, minDate, maxDate, selectedDate, onDateChange, disabled, hasError, monthRef, yearRef, dayRef, labels, order, reverseYears, hideLabels, ...args }: ISelectDatepicker) => JSX.Element;
4
- export { SelectDatepicker };
@@ -1,20 +0,0 @@
1
- /// <reference types="react" />
2
- import { SelectDatepickerLabels } from '../types/SelectDatepickerLabels';
3
- import { SelectDatepickerOrder } from '../types/SelectDatepickerOrder';
4
- export interface ISelectDatepicker {
5
- id?: string;
6
- className?: string;
7
- minDate?: Date;
8
- maxDate?: Date;
9
- selectedDate?: Date | null;
10
- onDateChange: (date: Date | null) => void;
11
- labels?: SelectDatepickerLabels;
12
- disabled?: boolean;
13
- hasError?: boolean;
14
- monthRef?: React.LegacyRef<HTMLSelectElement>;
15
- yearRef?: React.LegacyRef<HTMLSelectElement>;
16
- dayRef?: React.LegacyRef<HTMLSelectElement>;
17
- reverseYears?: boolean;
18
- hideLabels?: boolean;
19
- order?: SelectDatepickerOrder;
20
- }
@@ -1,23 +0,0 @@
1
- export declare type Months = {
2
- 1: string;
3
- 2: string;
4
- 3: string;
5
- 4: string;
6
- 5: string;
7
- 6: string;
8
- 7: string;
9
- 8: string;
10
- 9: string;
11
- 10: string;
12
- 11: string;
13
- 12: string;
14
- };
15
- export declare type SelectDatepickerLabels = {
16
- yearLabel?: string;
17
- monthLabel?: string;
18
- dayLabel?: string;
19
- yearPlaceholder?: string;
20
- monthPlaceholder?: string;
21
- dayPlaceholder?: string;
22
- months?: Months;
23
- };
@@ -1 +0,0 @@
1
- export declare type SelectDatepickerOrder = 'day/month/year' | 'day/year/month' | 'month/day/year' | 'month/year/day' | 'year/month/day' | 'year/day/month';