persian-date-kit 0.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.
@@ -0,0 +1,47 @@
1
+ import * as React from 'react';
2
+ import type { Control, FieldValues, Path, RegisterOptions } from 'react-hook-form';
3
+ import { type PersianDatePickerProps } from './components/PersianDatePicker';
4
+ export type RHFDateValue = Date | null;
5
+ export type UsePersianDatePickerControllerParams<TFieldValues extends FieldValues> = {
6
+ name: Path<TFieldValues>;
7
+ control: Control<TFieldValues>;
8
+ rules?: RegisterOptions<TFieldValues, Path<TFieldValues>>;
9
+ defaultValue?: RHFDateValue;
10
+ shouldUnregister?: boolean;
11
+ } & Omit<PersianDatePickerProps, 'value' | 'onChange'>;
12
+ /**
13
+ * RHF adapter hook for `PersianDatePicker`.
14
+ *
15
+ * Assumes field value is `Date | null`.
16
+ */
17
+ export declare function usePersianDatePickerController<TFieldValues extends FieldValues>(params: UsePersianDatePickerControllerParams<TFieldValues>): {
18
+ field: import("react-hook-form").ControllerRenderProps<TFieldValues, Path<TFieldValues>>;
19
+ fieldState: import("react-hook-form").ControllerFieldState;
20
+ formState: import("react-hook-form").UseFormStateReturn<TFieldValues>;
21
+ pickerProps: {
22
+ value: RHFDateValue;
23
+ onChange: (date: RHFDateValue) => void;
24
+ disabled: boolean | undefined;
25
+ minDate?: Date | undefined;
26
+ maxDate?: Date | undefined;
27
+ placeholder?: string | undefined;
28
+ open?: boolean | undefined;
29
+ onOpenChange?: ((open: boolean) => void) | undefined;
30
+ mode?: "popover" | "inline" | undefined;
31
+ formatValue?: ((date: Date) => string) | undefined;
32
+ parseValue?: ((text: string) => Date | null) | undefined;
33
+ weekdays?: string[] | undefined;
34
+ monthLabels?: string[] | undefined;
35
+ renderMonthLabel?: ((jy: number, jm: number) => React.ReactNode) | undefined;
36
+ className?: string | undefined;
37
+ classes?: import(".").PersianDatePickerClasses | undefined;
38
+ };
39
+ };
40
+ export type RHF_PersianDatePickerProps<TFieldValues extends FieldValues> = UsePersianDatePickerControllerParams<TFieldValues>;
41
+ /**
42
+ * RHF adapter component for `PersianDatePicker`.
43
+ *
44
+ * Assumes field value is `Date | null`.
45
+ */
46
+ export declare function RHF_PersianDatePicker<TFieldValues extends FieldValues>(props: RHF_PersianDatePickerProps<TFieldValues>): import("react/jsx-runtime").JSX.Element;
47
+ //# sourceMappingURL=react-hook-form.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react-hook-form.d.ts","sourceRoot":"","sources":["../src/react-hook-form.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAElF,OAAO,EAAqB,KAAK,sBAAsB,EAAE,MAAM,gCAAgC,CAAA;AAE/F,MAAM,MAAM,YAAY,GAAG,IAAI,GAAG,IAAI,CAAA;AAEtC,MAAM,MAAM,oCAAoC,CAAC,YAAY,SAAS,WAAW,IAAI;IACnF,IAAI,EAAE,IAAI,CAAC,YAAY,CAAC,CAAA;IACxB,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC,CAAA;IAC9B,KAAK,CAAC,EAAE,eAAe,CAAC,YAAY,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,CAAA;IACzD,YAAY,CAAC,EAAE,YAAY,CAAA;IAC3B,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAC3B,GAAG,IAAI,CAAC,sBAAsB,EAAE,OAAO,GAAG,UAAU,CAAC,CAAA;AAEtD;;;;GAIG;AACH,wBAAgB,8BAA8B,CAAC,YAAY,SAAS,WAAW,EAC7E,MAAM,EAAE,oCAAoC,CAAC,YAAY,CAAC;;;;;;yBAgBjD,YAAY;;;;;;;;;;;;;;;;EAiBtB;AAED,MAAM,MAAM,0BAA0B,CAAC,YAAY,SAAS,WAAW,IAAI,oCAAoC,CAAC,YAAY,CAAC,CAAA;AAE7H;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,YAAY,SAAS,WAAW,EAAE,KAAK,EAAE,0BAA0B,CAAC,YAAY,CAAC,2CAGtH"}
@@ -0,0 +1,38 @@
1
+ import { jsx as P } from "react/jsx-runtime";
2
+ import * as d from "react";
3
+ import { useController as k } from "react-hook-form";
4
+ import { P as C } from "./PersianDatePicker-BicyzfQH.js";
5
+ function g(r) {
6
+ const { name: o, control: n, rules: a, defaultValue: l, shouldUnregister: s, disabled: t, ...i } = r, { field: e, fieldState: u, formState: c } = k({
7
+ name: o,
8
+ control: n,
9
+ rules: a,
10
+ defaultValue: l ?? null,
11
+ shouldUnregister: s,
12
+ disabled: t
13
+ }), f = e.value ?? null, p = d.useCallback(
14
+ (m) => {
15
+ e.onChange(m);
16
+ },
17
+ [e]
18
+ );
19
+ return {
20
+ field: e,
21
+ fieldState: u,
22
+ formState: c,
23
+ pickerProps: {
24
+ ...i,
25
+ value: f,
26
+ onChange: p,
27
+ disabled: t
28
+ }
29
+ };
30
+ }
31
+ function v(r) {
32
+ const { pickerProps: o } = g(r);
33
+ return /* @__PURE__ */ P(C, { ...o });
34
+ }
35
+ export {
36
+ v as RHF_PersianDatePicker,
37
+ g as usePersianDatePickerController
38
+ };
@@ -0,0 +1,234 @@
1
+ :root {
2
+ --dvx-pdp-bg: #ffffff;
3
+ --dvx-pdp-fg: #111827;
4
+ --dvx-pdp-muted: #6b7280;
5
+ --dvx-pdp-border: #e5e7eb;
6
+ --dvx-pdp-shadow: 0 10px 20px rgba(0, 0, 0, 0.08);
7
+ --dvx-pdp-accent: #2563eb;
8
+ --dvx-pdp-accentFg: #ffffff;
9
+ --dvx-pdp-ring: rgba(37, 99, 235, 0.3);
10
+ --dvx-pdp-dayHover: rgba(37, 99, 235, 0.08);
11
+ }
12
+
13
+ @media (prefers-color-scheme: dark) {
14
+ :root {
15
+ --dvx-pdp-bg: #0b1220;
16
+ --dvx-pdp-fg: #e5e7eb;
17
+ --dvx-pdp-muted: #9ca3af;
18
+ --dvx-pdp-border: #243045;
19
+ --dvx-pdp-shadow: 0 10px 20px rgba(0, 0, 0, 0.35);
20
+ --dvx-pdp-accent: #60a5fa;
21
+ --dvx-pdp-accentFg: #0b1220;
22
+ --dvx-pdp-ring: rgba(96, 165, 250, 0.35);
23
+ --dvx-pdp-dayHover: rgba(96, 165, 250, 0.12);
24
+ }
25
+ }
26
+
27
+ .dvx-pdp {
28
+ position: relative;
29
+ display: inline-block;
30
+ direction: rtl;
31
+ color: var(--dvx-pdp-fg);
32
+ font: inherit;
33
+ }
34
+
35
+ .dvx-pdp--inline {
36
+ display: block;
37
+ }
38
+
39
+ .dvx-pdp__control {
40
+ display: flex;
41
+ gap: 8px;
42
+ align-items: center;
43
+ }
44
+
45
+ .dvx-pdp__input {
46
+ width: 160px;
47
+ padding: 8px 10px;
48
+ border-radius: 10px;
49
+ border: 1px solid var(--dvx-pdp-border);
50
+ background: var(--dvx-pdp-bg);
51
+ color: var(--dvx-pdp-fg);
52
+ outline: none;
53
+ }
54
+
55
+ .dvx-pdp__input:focus {
56
+ box-shadow: 0 0 0 4px var(--dvx-pdp-ring);
57
+ border-color: var(--dvx-pdp-accent);
58
+ }
59
+
60
+ .dvx-pdp__button {
61
+ display: inline-flex;
62
+ align-items: center;
63
+ justify-content: center;
64
+ width: 36px;
65
+ height: 36px;
66
+ border-radius: 10px;
67
+ border: 1px solid var(--dvx-pdp-border);
68
+ background: var(--dvx-pdp-bg);
69
+ color: var(--dvx-pdp-fg);
70
+ cursor: pointer;
71
+ }
72
+
73
+ .dvx-pdp__button:disabled,
74
+ .dvx-pdp__input:disabled {
75
+ opacity: 0.6;
76
+ cursor: not-allowed;
77
+ }
78
+
79
+ .dvx-pdp__popover {
80
+ position: absolute;
81
+ top: calc(100% + 8px);
82
+ right: 0;
83
+ z-index: 50;
84
+ }
85
+
86
+ .dvx-pdp__calendar {
87
+ width: 280px;
88
+ border-radius: 14px;
89
+ border: 1px solid var(--dvx-pdp-border);
90
+ background: var(--dvx-pdp-bg);
91
+ box-shadow: var(--dvx-pdp-shadow);
92
+ padding: 10px;
93
+ outline: none;
94
+ }
95
+
96
+ .dvx-pdp__header {
97
+ display: flex;
98
+ align-items: center;
99
+ justify-content: space-between;
100
+ gap: 10px;
101
+ margin-bottom: 10px;
102
+ }
103
+
104
+ .dvx-pdp__monthLabel {
105
+ font-weight: 600;
106
+ font-size: 14px;
107
+ border: 1px solid transparent;
108
+ background: transparent;
109
+ color: var(--dvx-pdp-fg);
110
+ padding: 6px 10px;
111
+ border-radius: 10px;
112
+ cursor: pointer;
113
+ }
114
+
115
+ .dvx-pdp__nav {
116
+ width: 34px;
117
+ height: 34px;
118
+ border-radius: 10px;
119
+ border: 1px solid var(--dvx-pdp-border);
120
+ background: var(--dvx-pdp-bg);
121
+ color: var(--dvx-pdp-fg);
122
+ cursor: pointer;
123
+ }
124
+
125
+ .dvx-pdp__grid {
126
+ display: flex;
127
+ flex-direction: column;
128
+ gap: 6px;
129
+ }
130
+
131
+ .dvx-pdp__weekdays {
132
+ display: grid;
133
+ grid-template-columns: repeat(7, 1fr);
134
+ gap: 6px;
135
+ }
136
+
137
+ .dvx-pdp__weekday {
138
+ text-align: center;
139
+ font-size: 12px;
140
+ color: var(--dvx-pdp-muted);
141
+ user-select: none;
142
+ }
143
+
144
+ .dvx-pdp__days {
145
+ display: flex;
146
+ flex-direction: column;
147
+ gap: 6px;
148
+ }
149
+
150
+ .dvx-pdp__row {
151
+ display: grid;
152
+ grid-template-columns: repeat(7, 1fr);
153
+ gap: 6px;
154
+ }
155
+
156
+ .dvx-pdp__day {
157
+ height: 34px;
158
+ border-radius: 10px;
159
+ border: 1px solid transparent;
160
+ background: transparent;
161
+ color: var(--dvx-pdp-fg);
162
+ cursor: pointer;
163
+ }
164
+
165
+ .dvx-pdp__day:hover {
166
+ background: var(--dvx-pdp-dayHover);
167
+ }
168
+
169
+ .dvx-pdp__day--outside {
170
+ color: var(--dvx-pdp-muted);
171
+ }
172
+
173
+ .dvx-pdp__day--today {
174
+ border-color: var(--dvx-pdp-border);
175
+ }
176
+
177
+ .dvx-pdp__day--selected {
178
+ background: var(--dvx-pdp-accent);
179
+ color: var(--dvx-pdp-accentFg);
180
+ }
181
+
182
+ .dvx-pdp__day--inRange {
183
+ background: var(--dvx-pdp-dayHover);
184
+ }
185
+
186
+ .dvx-pdp__day--rangeStart,
187
+ .dvx-pdp__day--rangeEnd {
188
+ background: var(--dvx-pdp-accent);
189
+ color: var(--dvx-pdp-accentFg);
190
+ }
191
+
192
+ .dvx-pdp__day--disabled {
193
+ opacity: 0.45;
194
+ cursor: not-allowed;
195
+ }
196
+
197
+ .dvx-pdp__day--focused {
198
+ box-shadow: 0 0 0 4px var(--dvx-pdp-ring);
199
+ }
200
+
201
+ .dvx-pdp__panel {
202
+ padding: 2px 0 0;
203
+ }
204
+
205
+ .dvx-pdp__panelGrid {
206
+ display: grid;
207
+ grid-template-columns: repeat(3, 1fr);
208
+ gap: 8px;
209
+ }
210
+
211
+ .dvx-pdp__cell {
212
+ height: 38px;
213
+ border-radius: 12px;
214
+ border: 1px solid var(--dvx-pdp-border);
215
+ background: var(--dvx-pdp-bg);
216
+ color: var(--dvx-pdp-fg);
217
+ cursor: pointer;
218
+ }
219
+
220
+ .dvx-pdp__cell:hover {
221
+ background: var(--dvx-pdp-dayHover);
222
+ }
223
+
224
+ .dvx-pdp__cell:disabled {
225
+ opacity: 0.45;
226
+ cursor: not-allowed;
227
+ }
228
+
229
+ .dvx-pdp__cell--active {
230
+ border-color: var(--dvx-pdp-accent);
231
+ box-shadow: 0 0 0 4px var(--dvx-pdp-ring);
232
+ }
233
+
234
+
@@ -0,0 +1,23 @@
1
+ import { type JalaliParts } from '../adapters/dayjsAdapter';
2
+ export declare function compareDays(a: Date, b: Date): number;
3
+ export declare function isSameDay(a: Date, b: Date): boolean;
4
+ export declare function addDays(date: Date, deltaDays: number): Date;
5
+ export declare function isWithinRange(date: Date, minDate?: Date, maxDate?: Date): boolean;
6
+ export declare function clampToRange(date: Date, minDate?: Date, maxDate?: Date): Date;
7
+ export type CalendarDayCell = {
8
+ gregorian: Date;
9
+ jalali: JalaliParts;
10
+ inCurrentMonth: boolean;
11
+ };
12
+ export type BuildJalaliMonthGridOptions = {
13
+ jy: number;
14
+ jm: number;
15
+ /**
16
+ * 0=Sunday ... 6=Saturday. Defaults to 6 (Saturday), common in Iran.
17
+ */
18
+ weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
19
+ };
20
+ export declare function getJalaliMonthLength(jy: number, jm: number): number;
21
+ export declare function addJalaliMonths(date: Date, deltaMonths: number): Date;
22
+ export declare function buildJalaliMonthGrid(opts: BuildJalaliMonthGridOptions): CalendarDayCell[][];
23
+ //# sourceMappingURL=calendarGrid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calendarGrid.d.ts","sourceRoot":"","sources":["../../src/utils/calendarGrid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkC,KAAK,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAQ3F,wBAAgB,WAAW,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,GAAG,MAAM,CAIpD;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,GAAG,OAAO,CAEnD;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAI3D;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,IAAI,GAAG,OAAO,CAIjF;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,IAAI,GAAG,IAAI,CAI7E;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,SAAS,EAAE,IAAI,CAAA;IACf,MAAM,EAAE,WAAW,CAAA;IACnB,cAAc,EAAE,OAAO,CAAA;CACxB,CAAA;AAED,MAAM,MAAM,2BAA2B,GAAG;IACxC,EAAE,EAAE,MAAM,CAAA;IACV,EAAE,EAAE,MAAM,CAAA;IACV;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;CACzC,CAAA;AAaD,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAKnE;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,CAMrE;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,2BAA2B,GAAG,eAAe,EAAE,EAAE,CAyB3F"}
@@ -0,0 +1,10 @@
1
+ import { type JalaliParts } from '../adapters/dayjsAdapter';
2
+ export type ParseJalaliTextOptions = {
3
+ /**
4
+ * Accept `YYYY/MM/DD` or `YYYY-MM-DD` (any non-digit separator).
5
+ */
6
+ allowLooseSeparators?: boolean;
7
+ };
8
+ export declare function toGregorian(parts: JalaliParts): Date;
9
+ export declare function parseJalaliText(text: string, opts?: ParseJalaliTextOptions): Date | null;
10
+ //# sourceMappingURL=toGregorian.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toGregorian.d.ts","sourceRoot":"","sources":["../../src/utils/toGregorian.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAE5E,MAAM,MAAM,sBAAsB,GAAG;IACnC;;OAEG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAA;CAC/B,CAAA;AAMD,wBAAgB,WAAW,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAEpD;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,sBAA2B,GAAG,IAAI,GAAG,IAAI,CAiB5F"}
@@ -0,0 +1,6 @@
1
+ import { type JalaliParts } from '../adapters/dayjsAdapter';
2
+ export type ToJalaliResult = JalaliParts & {
3
+ formatted: string;
4
+ };
5
+ export declare function toJalali(gregorian: Date): ToJalaliResult;
6
+ //# sourceMappingURL=toJalali.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toJalali.d.ts","sourceRoot":"","sources":["../../src/utils/toJalali.ts"],"names":[],"mappings":"AAAA,OAAO,EAA+B,KAAK,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAExF,MAAM,MAAM,cAAc,GAAG,WAAW,GAAG;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,CAAA;AAEhE,wBAAgB,QAAQ,CAAC,SAAS,EAAE,IAAI,GAAG,cAAc,CAGxD"}
package/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "persian-date-kit",
3
+ "version": "0.0.1",
4
+ "type": "module",
5
+ "main": "./dist/index.cjs",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.cjs"
13
+ },
14
+ "./react-hook-form": {
15
+ "types": "./dist/react-hook-form.d.ts",
16
+ "import": "./dist/react-hook-form.mjs",
17
+ "require": "./dist/react-hook-form.cjs"
18
+ },
19
+ "./styles.css": "./dist/styles.css"
20
+ },
21
+ "files": [
22
+ "dist"
23
+ ],
24
+ "sideEffects": [
25
+ "**/*.css"
26
+ ],
27
+ "scripts": {
28
+ "dev": "vite",
29
+ "build": "vite build && tsc -p tsconfig.build.json && node scripts/copyStyles.mjs",
30
+ "lint": "eslint .",
31
+ "preview": "vite preview"
32
+ },
33
+ "dependencies": {
34
+ "dayjs": "^1.11.13",
35
+ "jalaliday": "^3.1.0"
36
+ },
37
+ "peerDependencies": {
38
+ "react": ">=18",
39
+ "react-dom": ">=18",
40
+ "react-hook-form": ">=7"
41
+ },
42
+ "peerDependenciesMeta": {
43
+ "react-hook-form": {
44
+ "optional": true
45
+ }
46
+ },
47
+ "devDependencies": {
48
+ "@eslint/js": "^9.39.1",
49
+ "@types/node": "^24.10.1",
50
+ "@types/react": "^19.2.5",
51
+ "@types/react-dom": "^19.2.3",
52
+ "@vitejs/plugin-react-swc": "^4.2.2",
53
+ "eslint": "^9.39.1",
54
+ "eslint-plugin-react-hooks": "^7.0.1",
55
+ "eslint-plugin-react-refresh": "^0.4.24",
56
+ "globals": "^16.5.0",
57
+ "react": "^19.2.0",
58
+ "react-dom": "^19.2.0",
59
+ "react-hook-form": "^7.62.0",
60
+ "typescript": "~5.9.3",
61
+ "typescript-eslint": "^8.46.4",
62
+ "vite": "^7.2.4"
63
+ }
64
+ }