@rushdi94/hijri-datepicker 1.0.1 → 2.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.
- package/README.md +106 -39
- package/dist/hijri-datepicker.cjs.js +401 -237
- package/dist/hijri-datepicker.cjs.js.map +1 -1
- package/dist/hijri-datepicker.esm.js +396 -238
- package/dist/hijri-datepicker.esm.js.map +1 -1
- package/dist/hijri-datepicker.umd.js +401 -237
- package/dist/hijri-datepicker.umd.js.map +1 -1
- package/dist/types/HijriDatePicker.d.ts +56 -28
- package/dist/types/hijri-calendar.d.ts +11 -0
- package/dist/types/index.d.ts +3 -3
- package/dist/types/styles.d.ts +1 -1
- package/package.json +1 -1
|
@@ -11,8 +11,13 @@
|
|
|
11
11
|
'جمادى الأولى', 'جمادى الآخرة', 'رجب', 'شعبان',
|
|
12
12
|
'رمضان', 'شوال', 'ذو القعدة', 'ذو الحجة',
|
|
13
13
|
];
|
|
14
|
-
|
|
14
|
+
const GREGORIAN_MONTHS_EN = [
|
|
15
|
+
'January', 'February', 'March', 'April', 'May', 'June',
|
|
16
|
+
'July', 'August', 'September', 'October', 'November', 'December',
|
|
17
|
+
];
|
|
18
|
+
// Sunday → Saturday
|
|
15
19
|
const WEEKDAY_AR = ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'];
|
|
20
|
+
const WEEKDAY_EN = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
|
|
16
21
|
// ── calendar arithmetic ──────────────────────────────────────────────────────
|
|
17
22
|
function gToJDN(y, m, d) {
|
|
18
23
|
const a = Math.floor((14 - m) / 12);
|
|
@@ -63,7 +68,7 @@
|
|
|
63
68
|
const year = 30 * n + j - 30;
|
|
64
69
|
return [year, month, day];
|
|
65
70
|
}
|
|
66
|
-
// ──
|
|
71
|
+
// ── Hijri helpers ─────────────────────────────────────────────────────────────
|
|
67
72
|
function toHijri(date) {
|
|
68
73
|
const [year, month, day] = jdnToH(gToJDN(date.getFullYear(), date.getMonth() + 1, date.getDate()));
|
|
69
74
|
return { year, month, day };
|
|
@@ -78,7 +83,7 @@
|
|
|
78
83
|
return hToJDN(ny, nm, 1) - hToJDN(year, month, 1);
|
|
79
84
|
}
|
|
80
85
|
function firstWeekday(year, month) {
|
|
81
|
-
return toGregorian(year, month, 1).getDay();
|
|
86
|
+
return toGregorian(year, month, 1).getDay();
|
|
82
87
|
}
|
|
83
88
|
function todayHijri() {
|
|
84
89
|
return toHijri(new Date());
|
|
@@ -108,79 +113,80 @@
|
|
|
108
113
|
return null;
|
|
109
114
|
}
|
|
110
115
|
}
|
|
116
|
+
// ── Gregorian helpers ─────────────────────────────────────────────────────────
|
|
117
|
+
function daysInMonthGregorian(year, month) {
|
|
118
|
+
return new Date(year, month, 0).getDate();
|
|
119
|
+
}
|
|
120
|
+
function firstWeekdayGregorian(year, month) {
|
|
121
|
+
return new Date(year, month - 1, 1).getDay();
|
|
122
|
+
}
|
|
123
|
+
function todayGregorian() {
|
|
124
|
+
const d = new Date();
|
|
125
|
+
return { year: d.getFullYear(), month: d.getMonth() + 1, day: d.getDate() };
|
|
126
|
+
}
|
|
127
|
+
function formatGregorian(g, fmt = 'DD/MM/YYYY') {
|
|
128
|
+
return fmt
|
|
129
|
+
.replace('YYYY', String(g.year))
|
|
130
|
+
.replace('MM', String(g.month).padStart(2, '0'))
|
|
131
|
+
.replace('DD', String(g.day).padStart(2, '0'))
|
|
132
|
+
.replace('M', String(g.month))
|
|
133
|
+
.replace('D', String(g.day));
|
|
134
|
+
}
|
|
111
135
|
|
|
112
136
|
const CSS = /* css */ `
|
|
113
137
|
/* ── HijriDatePicker ─────────────────────────────────────────────────────── */
|
|
114
|
-
.hdp,
|
|
115
|
-
.hdp *,
|
|
116
|
-
.hdp *::before,
|
|
117
|
-
.hdp *::after {
|
|
138
|
+
.hdp, .hdp *, .hdp *::before, .hdp *::after {
|
|
118
139
|
box-sizing: border-box;
|
|
119
140
|
font-family: system-ui, -apple-system, 'Segoe UI', Tahoma, Arial, sans-serif;
|
|
120
141
|
}
|
|
121
142
|
|
|
122
|
-
/* wrapper */
|
|
123
143
|
.hdp-wrapper { position: relative; display: inline-block; }
|
|
124
144
|
|
|
125
|
-
/* input */
|
|
145
|
+
/* ── input ───────────────────────────────────────────────────────────────── */
|
|
126
146
|
.hdp-input-wrap { position: relative; display: block; }
|
|
127
147
|
.hdp-input {
|
|
128
|
-
width: 100%;
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
font-size: 14px;
|
|
133
|
-
cursor: pointer;
|
|
134
|
-
background: #fff;
|
|
135
|
-
outline: none;
|
|
136
|
-
color: #333;
|
|
137
|
-
min-width: 210px;
|
|
148
|
+
width: 100%; padding: 9px 14px 9px 38px;
|
|
149
|
+
border: 1.5px solid #d1d5db; border-radius: 8px;
|
|
150
|
+
font-size: 14px; cursor: pointer; background: #fff;
|
|
151
|
+
outline: none; color: #333; min-width: 210px;
|
|
138
152
|
transition: border-color .2s, box-shadow .2s;
|
|
139
|
-
caret-color: transparent;
|
|
140
|
-
text-align: inherit;
|
|
153
|
+
caret-color: transparent; text-align: inherit;
|
|
141
154
|
}
|
|
142
155
|
[dir="rtl"] .hdp-input { padding: 9px 14px 9px 38px; text-align: right; }
|
|
143
156
|
[dir="ltr"] .hdp-input { padding: 9px 38px 9px 14px; text-align: left; }
|
|
144
157
|
.hdp-input::placeholder { color: #aaa; }
|
|
145
|
-
.hdp-input:focus,
|
|
146
|
-
.hdp-input.open {
|
|
158
|
+
.hdp-input:focus, .hdp-input.open {
|
|
147
159
|
border-color: var(--hdp-primary, #8b1a2e);
|
|
148
160
|
box-shadow: 0 0 0 3px rgba(139,26,46,.14);
|
|
149
161
|
}
|
|
150
162
|
.hdp-input-icon {
|
|
151
|
-
position: absolute;
|
|
152
|
-
|
|
153
|
-
transform: translateY(-50%);
|
|
154
|
-
pointer-events: none;
|
|
155
|
-
color: #9ca3af;
|
|
156
|
-
width: 18px;
|
|
157
|
-
height: 18px;
|
|
163
|
+
position: absolute; top: 50%; transform: translateY(-50%);
|
|
164
|
+
pointer-events: none; color: #9ca3af; width: 18px; height: 18px;
|
|
158
165
|
}
|
|
159
166
|
[dir="rtl"] .hdp-input-icon { left: 10px; right: auto; }
|
|
160
167
|
[dir="ltr"] .hdp-input-icon { right: 10px; left: auto; }
|
|
161
168
|
|
|
162
169
|
/* ── popup ───────────────────────────────────────────────────────────────── */
|
|
163
170
|
.hdp-popup {
|
|
164
|
-
position: absolute;
|
|
165
|
-
|
|
166
|
-
z-index: 99999;
|
|
167
|
-
}
|
|
168
|
-
[dir="rtl"] .hdp-popup { right: 0; left: auto; }
|
|
169
|
-
[dir="ltr"] .hdp-popup { left: 0; right: auto; }
|
|
170
|
-
.hdp-popup {
|
|
171
|
-
width: 312px;
|
|
172
|
-
border-radius: 12px;
|
|
173
|
-
overflow: visible;
|
|
171
|
+
position: absolute; top: calc(100% + 8px); z-index: 99999;
|
|
172
|
+
width: 312px; border-radius: 12px; overflow: visible;
|
|
174
173
|
box-shadow: 0 8px 32px rgba(0,0,0,.18), 0 2px 8px rgba(0,0,0,.08);
|
|
175
174
|
background: var(--hdp-body-bg, #fff);
|
|
176
175
|
animation: _hdpIn .15s cubic-bezier(.2,.8,.4,1);
|
|
177
176
|
}
|
|
177
|
+
[dir="rtl"] .hdp-popup { right: 0; left: auto; }
|
|
178
|
+
[dir="ltr"] .hdp-popup { left: 0; right: auto; }
|
|
179
|
+
@keyframes _hdpIn {
|
|
180
|
+
from { opacity: 0; transform: translateY(-8px) scale(.97); }
|
|
181
|
+
to { opacity: 1; transform: translateY(0) scale(1); }
|
|
182
|
+
}
|
|
183
|
+
.hdp-popup.hdp-inline {
|
|
184
|
+
position: static; box-shadow: 0 2px 16px rgba(0,0,0,.1); animation: none;
|
|
185
|
+
}
|
|
178
186
|
|
|
179
|
-
/*
|
|
187
|
+
/* caret pointing up to input */
|
|
180
188
|
.hdp-popup:not(.hdp-inline)::before {
|
|
181
|
-
content: '';
|
|
182
|
-
position: absolute;
|
|
183
|
-
top: -8px;
|
|
189
|
+
content: ''; position: absolute; top: -8px;
|
|
184
190
|
width: 0; height: 0;
|
|
185
191
|
border-left: 9px solid transparent;
|
|
186
192
|
border-right: 9px solid transparent;
|
|
@@ -189,192 +195,158 @@
|
|
|
189
195
|
}
|
|
190
196
|
[dir="rtl"] .hdp-popup:not(.hdp-inline)::before { right: 18px; left: auto; }
|
|
191
197
|
[dir="ltr"] .hdp-popup:not(.hdp-inline)::before { left: 18px; right: auto; }
|
|
192
|
-
@keyframes _hdpIn {
|
|
193
|
-
from { opacity: 0; transform: translateY(-8px) scale(.97); }
|
|
194
|
-
to { opacity: 1; transform: translateY(0) scale(1); }
|
|
195
|
-
}
|
|
196
|
-
.hdp-popup.hdp-inline {
|
|
197
|
-
position: static;
|
|
198
|
-
box-shadow: 0 2px 16px rgba(0,0,0,.1);
|
|
199
|
-
animation: none;
|
|
200
|
-
}
|
|
201
198
|
|
|
202
199
|
/* ── header ──────────────────────────────────────────────────────────────── */
|
|
203
200
|
.hdp-header {
|
|
204
201
|
background: var(--hdp-primary, #8b1a2e);
|
|
205
202
|
color: var(--hdp-on-primary, #fff);
|
|
206
|
-
|
|
207
|
-
flex-direction: row;
|
|
208
|
-
align-items: stretch;
|
|
209
|
-
height: 44px;
|
|
203
|
+
border-radius: 12px 12px 0 0;
|
|
204
|
+
display: flex; flex-direction: row;
|
|
205
|
+
align-items: stretch; height: 44px;
|
|
210
206
|
user-select: none;
|
|
211
207
|
}
|
|
212
208
|
|
|
213
|
-
/* prev / next month arrows */
|
|
214
209
|
.hdp-nav {
|
|
215
|
-
flex-shrink: 0;
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
background:
|
|
219
|
-
color: var(--hdp-on-primary, #fff);
|
|
220
|
-
cursor: pointer;
|
|
221
|
-
display: flex; align-items: center; justify-content: center;
|
|
222
|
-
font-size: 18px;
|
|
223
|
-
transition: background .15s;
|
|
224
|
-
line-height: 1;
|
|
210
|
+
flex-shrink: 0; width: 32px; border: none;
|
|
211
|
+
background: transparent; color: var(--hdp-on-primary, #fff);
|
|
212
|
+
cursor: pointer; display: flex; align-items: center; justify-content: center;
|
|
213
|
+
font-size: 18px; transition: background .15s; line-height: 1;
|
|
225
214
|
}
|
|
226
215
|
.hdp-nav:hover { background: rgba(255,255,255,.18); }
|
|
227
216
|
|
|
228
|
-
/*
|
|
217
|
+
/* month half */
|
|
229
218
|
.hdp-month-half {
|
|
230
|
-
flex: 1;
|
|
231
|
-
|
|
232
|
-
align-items: center;
|
|
233
|
-
justify-content: center;
|
|
234
|
-
border-right: 1px solid rgba(255,255,255,.2);
|
|
235
|
-
padding: 0 4px;
|
|
236
|
-
min-width: 0;
|
|
219
|
+
flex: 1; display: flex; align-items: center; justify-content: center;
|
|
220
|
+
border-right: 1px solid rgba(255,255,255,.2); padding: 0 4px; min-width: 0;
|
|
237
221
|
}
|
|
238
|
-
|
|
239
222
|
.hdp-month-select {
|
|
240
|
-
width: 100%;
|
|
241
|
-
appearance: none;
|
|
242
|
-
-webkit-appearance: none;
|
|
223
|
+
width: 100%; appearance: none; -webkit-appearance: none;
|
|
243
224
|
background: transparent url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%23ffffff' stroke-width='1.8' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat right 8px center;
|
|
244
|
-
border: none;
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
color: var(--hdp-on-primary, #fff);
|
|
248
|
-
cursor: pointer;
|
|
249
|
-
outline: none;
|
|
250
|
-
text-align: center;
|
|
251
|
-
text-align-last: center;
|
|
252
|
-
letter-spacing: .2px;
|
|
253
|
-
}
|
|
254
|
-
[dir="rtl"] .hdp-month-select {
|
|
255
|
-
background-position: left 8px center;
|
|
256
|
-
padding: 6px 10px 6px 26px;
|
|
225
|
+
border: none; padding: 6px 26px 6px 10px;
|
|
226
|
+
font-size: 13px; font-weight: 700; color: var(--hdp-on-primary, #fff);
|
|
227
|
+
cursor: pointer; outline: none; text-align: center; text-align-last: center;
|
|
257
228
|
}
|
|
229
|
+
[dir="rtl"] .hdp-month-select { background-position: left 8px center; padding: 6px 10px 6px 26px; }
|
|
258
230
|
.hdp-month-select:hover { background-color: rgba(255,255,255,.12); border-radius: 6px; }
|
|
259
231
|
.hdp-month-select option { background: #fff; color: #111; font-weight: 600; }
|
|
260
232
|
|
|
261
|
-
/*
|
|
233
|
+
/* year half */
|
|
262
234
|
.hdp-year-half {
|
|
263
|
-
flex: 1;
|
|
264
|
-
|
|
265
|
-
align-items: center;
|
|
266
|
-
justify-content: center;
|
|
267
|
-
padding: 0 6px;
|
|
268
|
-
min-width: 0;
|
|
235
|
+
flex: 1; display: flex; align-items: center; justify-content: center;
|
|
236
|
+
padding: 0 6px; min-width: 0;
|
|
269
237
|
}
|
|
270
|
-
|
|
271
|
-
/* inner wrapper: year number + arrows in a row */
|
|
272
|
-
.hdp-year-inner {
|
|
273
|
-
display: flex;
|
|
274
|
-
align-items: center;
|
|
275
|
-
gap: 3px;
|
|
276
|
-
}
|
|
277
|
-
|
|
238
|
+
.hdp-year-inner { display: flex; align-items: center; gap: 3px; }
|
|
278
239
|
.hdp-year-display {
|
|
279
|
-
font-size: 15px; font-weight: 800;
|
|
280
|
-
|
|
281
|
-
letter-spacing: .4px;
|
|
282
|
-
line-height: 1;
|
|
283
|
-
white-space: nowrap;
|
|
240
|
+
font-size: 15px; font-weight: 800; color: var(--hdp-on-primary, #fff);
|
|
241
|
+
letter-spacing: .4px; line-height: 1; white-space: nowrap;
|
|
284
242
|
}
|
|
285
|
-
|
|
286
|
-
/* arrows: collapsed (width 0) when not hovered, slide in on hover */
|
|
287
243
|
.hdp-year-arrows {
|
|
288
|
-
display: flex;
|
|
289
|
-
|
|
290
|
-
gap: 2px;
|
|
291
|
-
max-width: 0;
|
|
292
|
-
overflow: hidden;
|
|
293
|
-
opacity: 0;
|
|
294
|
-
pointer-events: none;
|
|
244
|
+
display: flex; flex-direction: column; gap: 2px;
|
|
245
|
+
max-width: 0; overflow: hidden; opacity: 0; pointer-events: none;
|
|
295
246
|
transition: max-width .18s ease, opacity .18s ease;
|
|
296
247
|
}
|
|
297
|
-
.hdp-year-half:hover .hdp-year-arrows {
|
|
298
|
-
max-width: 22px;
|
|
299
|
-
opacity: 1;
|
|
300
|
-
pointer-events: auto;
|
|
301
|
-
}
|
|
302
|
-
|
|
248
|
+
.hdp-year-half:hover .hdp-year-arrows { max-width: 22px; opacity: 1; pointer-events: auto; }
|
|
303
249
|
.hdp-year-arrow {
|
|
304
|
-
background: none;
|
|
305
|
-
|
|
306
|
-
color: var(--hdp-on-primary, #fff);
|
|
307
|
-
cursor: pointer;
|
|
308
|
-
width: 18px; height: 13px;
|
|
250
|
+
background: none; border: none; color: var(--hdp-on-primary, #fff);
|
|
251
|
+
cursor: pointer; width: 18px; height: 13px;
|
|
309
252
|
display: flex; align-items: center; justify-content: center;
|
|
310
|
-
font-size: 7px;
|
|
311
|
-
|
|
312
|
-
padding: 0;
|
|
313
|
-
line-height: 1;
|
|
314
|
-
flex-shrink: 0;
|
|
315
|
-
transition: background .12s;
|
|
253
|
+
font-size: 7px; border-radius: 3px; padding: 0; flex-shrink: 0;
|
|
254
|
+
line-height: 1; transition: background .12s;
|
|
316
255
|
}
|
|
317
256
|
.hdp-year-arrow:hover { background: rgba(255,255,255,.25); }
|
|
318
257
|
|
|
258
|
+
/* calendar mode toggle */
|
|
259
|
+
.hdp-mode-btn {
|
|
260
|
+
flex-shrink: 0; background: rgba(255,255,255,.15);
|
|
261
|
+
border: 1px solid rgba(255,255,255,.3); border-radius: 5px;
|
|
262
|
+
color: var(--hdp-on-primary, #fff); cursor: pointer;
|
|
263
|
+
font-size: 11px; font-weight: 800;
|
|
264
|
+
padding: 0 7px; margin: 8px 6px; height: 28px;
|
|
265
|
+
transition: background .15s; line-height: 1; white-space: nowrap;
|
|
266
|
+
}
|
|
267
|
+
.hdp-mode-btn:hover { background: rgba(255,255,255,.3); }
|
|
268
|
+
|
|
319
269
|
/* ── weekday row ─────────────────────────────────────────────────────────── */
|
|
320
270
|
.hdp-weekdays {
|
|
321
|
-
display: grid;
|
|
322
|
-
|
|
323
|
-
background: var(--hdp-primary, #8b1a2e);
|
|
324
|
-
padding: 0 10px 10px;
|
|
271
|
+
display: grid; grid-template-columns: repeat(7, 1fr);
|
|
272
|
+
background: var(--hdp-primary, #8b1a2e); padding: 0 10px 10px;
|
|
325
273
|
}
|
|
326
274
|
.hdp-wday {
|
|
327
|
-
text-align: center;
|
|
328
|
-
font-
|
|
329
|
-
color: var(--hdp-on-primary, #fff);
|
|
330
|
-
opacity: .82;
|
|
331
|
-
font-weight: 500;
|
|
332
|
-
padding: 3px 0;
|
|
275
|
+
text-align: center; font-size: 11.5px; color: var(--hdp-on-primary, #fff);
|
|
276
|
+
opacity: .82; font-weight: 500; padding: 3px 0;
|
|
333
277
|
}
|
|
334
278
|
|
|
335
279
|
/* ── days ────────────────────────────────────────────────────────────────── */
|
|
336
280
|
.hdp-days {
|
|
337
|
-
display: grid;
|
|
338
|
-
|
|
339
|
-
padding: 8px 8px 12px;
|
|
340
|
-
gap: 2px;
|
|
341
|
-
border-radius: 0 0 12px 12px;
|
|
281
|
+
display: grid; grid-template-columns: repeat(7, 1fr);
|
|
282
|
+
padding: 8px 8px 12px; gap: 2px;
|
|
342
283
|
background: var(--hdp-body-bg, #fff);
|
|
343
284
|
}
|
|
344
285
|
.hdp-day {
|
|
345
|
-
aspect-ratio: 1;
|
|
346
|
-
|
|
347
|
-
border-radius: 50%;
|
|
348
|
-
font-size: 13.5px;
|
|
349
|
-
cursor: pointer;
|
|
286
|
+
aspect-ratio: 1; display: flex; align-items: center; justify-content: center;
|
|
287
|
+
border-radius: 50%; font-size: 13.5px; cursor: pointer;
|
|
350
288
|
color: var(--hdp-day-color, #1f2937);
|
|
351
289
|
transition: background .12s, color .12s, transform .08s;
|
|
352
|
-
font-weight: 400;
|
|
353
|
-
border: 2px solid transparent;
|
|
354
|
-
}
|
|
355
|
-
.hdp-day:not(.hdp-empty):hover {
|
|
356
|
-
background: var(--hdp-hover-bg, rgba(139,26,46,.1));
|
|
357
|
-
transform: scale(1.08);
|
|
290
|
+
font-weight: 400; border: 2px solid transparent;
|
|
358
291
|
}
|
|
292
|
+
.hdp-day:not(.hdp-empty):hover { background: var(--hdp-hover-bg); transform: scale(1.08); }
|
|
359
293
|
.hdp-day.hdp-today:not(.hdp-selected) {
|
|
360
|
-
border-color: var(--hdp-primary, #8b1a2e);
|
|
361
|
-
color: var(--hdp-primary, #8b1a2e);
|
|
362
|
-
font-weight: 700;
|
|
294
|
+
border-color: var(--hdp-primary, #8b1a2e); color: var(--hdp-primary, #8b1a2e); font-weight: 700;
|
|
363
295
|
}
|
|
364
296
|
.hdp-day.hdp-selected {
|
|
365
297
|
background: var(--hdp-primary, #8b1a2e) !important;
|
|
366
298
|
color: var(--hdp-on-primary, #fff) !important;
|
|
367
|
-
font-weight: 700;
|
|
368
|
-
border-color: transparent !important;
|
|
369
|
-
transform: scale(1.1);
|
|
299
|
+
font-weight: 700; border-color: transparent !important; transform: scale(1.1);
|
|
370
300
|
}
|
|
371
|
-
.hdp-day.hdp-empty {
|
|
372
|
-
|
|
373
|
-
|
|
301
|
+
.hdp-day.hdp-empty { cursor: default; pointer-events: none; }
|
|
302
|
+
|
|
303
|
+
/* ── time section ────────────────────────────────────────────────────────── */
|
|
304
|
+
.hdp-time-section {
|
|
305
|
+
display: flex; align-items: center; justify-content: center; gap: 6px;
|
|
306
|
+
padding: 10px 16px 14px;
|
|
307
|
+
border-top: 1px solid #f0f0f0;
|
|
308
|
+
background: #f9fafb;
|
|
309
|
+
border-radius: 0 0 12px 12px;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
.hdp-spinner {
|
|
313
|
+
display: flex; flex-direction: column; align-items: center; gap: 2px;
|
|
314
|
+
}
|
|
315
|
+
.hdp-spinner-btn {
|
|
316
|
+
background: none; border: none; color: #999; cursor: pointer;
|
|
317
|
+
width: 38px; height: 18px;
|
|
318
|
+
display: flex; align-items: center; justify-content: center;
|
|
319
|
+
font-size: 8px; border-radius: 4px; padding: 0; line-height: 1;
|
|
320
|
+
transition: background .12s, color .12s;
|
|
374
321
|
}
|
|
322
|
+
.hdp-spinner-btn:hover { background: var(--hdp-hover-bg); color: var(--hdp-primary, #8b1a2e); }
|
|
323
|
+
.hdp-spinner-val {
|
|
324
|
+
font-size: 26px; font-weight: 700;
|
|
325
|
+
color: var(--hdp-day-color, #1f2937);
|
|
326
|
+
min-width: 38px; text-align: center; line-height: 1;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
.hdp-time-colon {
|
|
330
|
+
font-size: 24px; font-weight: 700;
|
|
331
|
+
color: var(--hdp-day-color, #1f2937);
|
|
332
|
+
margin-top: 18px; line-height: 1;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
.hdp-ampm {
|
|
336
|
+
display: flex; flex-direction: column; gap: 4px; margin-top: 18px;
|
|
337
|
+
}
|
|
338
|
+
.hdp-ampm-btn {
|
|
339
|
+
background: #e5e7eb; border: none; border-radius: 6px;
|
|
340
|
+
padding: 5px 10px; font-size: 11px; font-weight: 700;
|
|
341
|
+
color: #555; cursor: pointer; transition: background .12s, color .12s;
|
|
342
|
+
}
|
|
343
|
+
.hdp-ampm-btn.hdp-ampm-active {
|
|
344
|
+
background: var(--hdp-primary, #8b1a2e); color: var(--hdp-on-primary, #fff);
|
|
345
|
+
}
|
|
346
|
+
.hdp-ampm-btn:not(.hdp-ampm-active):hover { background: #d1d5db; }
|
|
375
347
|
`;
|
|
376
348
|
|
|
377
|
-
// ── style injection
|
|
349
|
+
// ── style injection ───────────────────────────────────────────────────────────
|
|
378
350
|
let _stylesInjected = false;
|
|
379
351
|
function ensureStyles() {
|
|
380
352
|
if (_stylesInjected || typeof document === 'undefined')
|
|
@@ -385,14 +357,16 @@
|
|
|
385
357
|
el.textContent = CSS;
|
|
386
358
|
document.head.appendChild(el);
|
|
387
359
|
}
|
|
388
|
-
// ──
|
|
360
|
+
// ── defaults ──────────────────────────────────────────────────────────────────
|
|
389
361
|
const DEFAULT_WEEKDAYS_AR = [...WEEKDAY_AR];
|
|
390
362
|
const DEFAULT_WEEKDAYS_EN = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
|
|
363
|
+
// ── component ─────────────────────────────────────────────────────────────────
|
|
391
364
|
class HijriDatePicker {
|
|
392
365
|
// ── constructor ────────────────────────────────────────────────────────────
|
|
393
366
|
constructor(options) {
|
|
394
367
|
var _a;
|
|
395
|
-
this.
|
|
368
|
+
this.selectedHijri = null;
|
|
369
|
+
this.selectedGregorian = null;
|
|
396
370
|
// ── event handlers ─────────────────────────────────────────────────────────
|
|
397
371
|
this._onDocClick = (e) => {
|
|
398
372
|
if (!this.root.contains(e.target))
|
|
@@ -409,15 +383,19 @@
|
|
|
409
383
|
const defaults = {
|
|
410
384
|
inline: false,
|
|
411
385
|
dir,
|
|
412
|
-
placeholder: dir === 'rtl' ? 'اختر تاريخاً هجرياً' : 'Select
|
|
386
|
+
placeholder: dir === 'rtl' ? 'اختر تاريخاً هجرياً' : 'Select date',
|
|
413
387
|
weekdayLabels: dir === 'rtl' ? DEFAULT_WEEKDAYS_AR : DEFAULT_WEEKDAYS_EN,
|
|
414
388
|
monthLabels: [...HIJRI_MONTHS_AR],
|
|
389
|
+
gregorianMonthLabels: [...GREGORIAN_MONTHS_EN],
|
|
415
390
|
primaryColor: '#8b1a2e',
|
|
416
391
|
onPrimaryColor: '#ffffff',
|
|
417
392
|
bodyBg: '#ffffff',
|
|
418
393
|
dayColor: '#1f2937',
|
|
419
394
|
format: 'DD/MM/YYYY',
|
|
420
395
|
initialDate: today,
|
|
396
|
+
initialMode: 'hijri',
|
|
397
|
+
showTime: false,
|
|
398
|
+
use24h: false,
|
|
421
399
|
editable: false,
|
|
422
400
|
container: options.container,
|
|
423
401
|
onSelect: () => undefined,
|
|
@@ -426,8 +404,19 @@
|
|
|
426
404
|
};
|
|
427
405
|
this.opts = { ...defaults, ...options, dir };
|
|
428
406
|
this.isRTL = this.opts.dir === 'rtl';
|
|
429
|
-
this.
|
|
430
|
-
this.
|
|
407
|
+
this.calMode = this.opts.initialMode;
|
|
408
|
+
if (this.calMode === 'hijri') {
|
|
409
|
+
this.viewYear = this.opts.initialDate.year;
|
|
410
|
+
this.viewMonth = this.opts.initialDate.month;
|
|
411
|
+
}
|
|
412
|
+
else {
|
|
413
|
+
const g = todayGregorian();
|
|
414
|
+
this.viewYear = g.year;
|
|
415
|
+
this.viewMonth = g.month;
|
|
416
|
+
}
|
|
417
|
+
this.hour = this.opts.use24h ? 0 : 12;
|
|
418
|
+
this.minute = 0;
|
|
419
|
+
this.ampm = 'AM';
|
|
431
420
|
ensureStyles();
|
|
432
421
|
this._mount();
|
|
433
422
|
}
|
|
@@ -477,8 +466,13 @@
|
|
|
477
466
|
if (this.opts.editable) {
|
|
478
467
|
this.inputEl.addEventListener('input', () => {
|
|
479
468
|
const parsed = parseHijri(this.inputEl.value, this.opts.format);
|
|
480
|
-
if (parsed)
|
|
481
|
-
|
|
469
|
+
if (parsed) {
|
|
470
|
+
const gDate = toGregorian(parsed.year, parsed.month, parsed.day);
|
|
471
|
+
const gregorian = {
|
|
472
|
+
year: gDate.getFullYear(), month: gDate.getMonth() + 1, day: gDate.getDate(),
|
|
473
|
+
};
|
|
474
|
+
this._applySelection(parsed, gregorian, false);
|
|
475
|
+
}
|
|
482
476
|
});
|
|
483
477
|
}
|
|
484
478
|
const icon = document.createElement('span');
|
|
@@ -504,38 +498,34 @@
|
|
|
504
498
|
popup.style.left = '0';
|
|
505
499
|
}
|
|
506
500
|
popup.setAttribute('role', 'dialog');
|
|
507
|
-
popup.setAttribute('aria-label', this.isRTL ? 'منتقي التاريخ
|
|
501
|
+
popup.setAttribute('aria-label', this.isRTL ? 'منتقي التاريخ' : 'Date Picker');
|
|
508
502
|
popup.appendChild(this._buildHeader());
|
|
509
503
|
popup.appendChild(this._buildWeekdays());
|
|
510
504
|
this.daysGrid = this._buildDaysGrid();
|
|
511
505
|
popup.appendChild(this.daysGrid);
|
|
506
|
+
if (this.opts.showTime) {
|
|
507
|
+
popup.appendChild(this._buildTimeSection());
|
|
508
|
+
}
|
|
512
509
|
return popup;
|
|
513
510
|
}
|
|
514
511
|
// ── header ─────────────────────────────────────────────────────────────────
|
|
515
512
|
_buildHeader() {
|
|
516
513
|
const hdr = document.createElement('div');
|
|
517
514
|
hdr.className = 'hdp-header';
|
|
518
|
-
//
|
|
515
|
+
// Month half (left)
|
|
519
516
|
const monthHalf = document.createElement('div');
|
|
520
517
|
monthHalf.className = 'hdp-month-half';
|
|
521
518
|
this.monthSelectEl = document.createElement('select');
|
|
522
519
|
this.monthSelectEl.className = 'hdp-month-select';
|
|
523
|
-
this.
|
|
524
|
-
this.opts.monthLabels.forEach((name, i) => {
|
|
525
|
-
const opt = document.createElement('option');
|
|
526
|
-
opt.value = String(i + 1);
|
|
527
|
-
opt.textContent = name;
|
|
528
|
-
this.monthSelectEl.appendChild(opt);
|
|
529
|
-
});
|
|
520
|
+
this._rebuildMonthOptions();
|
|
530
521
|
this.monthSelectEl.addEventListener('change', () => {
|
|
531
522
|
this.viewMonth = Number(this.monthSelectEl.value);
|
|
532
523
|
this._renderDays();
|
|
533
524
|
});
|
|
534
525
|
monthHalf.appendChild(this.monthSelectEl);
|
|
535
|
-
//
|
|
526
|
+
// Year half (right)
|
|
536
527
|
const yearHalf = document.createElement('div');
|
|
537
528
|
yearHalf.className = 'hdp-year-half';
|
|
538
|
-
// Inner group: year number + arrows side by side
|
|
539
529
|
const yearInner = document.createElement('div');
|
|
540
530
|
yearInner.className = 'hdp-year-inner';
|
|
541
531
|
this.yearDisplayEl = document.createElement('span');
|
|
@@ -545,31 +535,25 @@
|
|
|
545
535
|
const yearUp = document.createElement('button');
|
|
546
536
|
yearUp.className = 'hdp-year-arrow';
|
|
547
537
|
yearUp.innerHTML = '▲';
|
|
548
|
-
yearUp.
|
|
549
|
-
yearUp.addEventListener('click', () => {
|
|
550
|
-
this.viewYear++;
|
|
551
|
-
this._syncHeader();
|
|
552
|
-
this._renderDays();
|
|
553
|
-
});
|
|
538
|
+
yearUp.addEventListener('click', () => { this.viewYear++; this._syncHeader(); this._renderDays(); });
|
|
554
539
|
const yearDown = document.createElement('button');
|
|
555
540
|
yearDown.className = 'hdp-year-arrow';
|
|
556
541
|
yearDown.innerHTML = '▼';
|
|
557
|
-
yearDown.
|
|
558
|
-
yearDown.addEventListener('click', () => {
|
|
559
|
-
this.viewYear--;
|
|
560
|
-
this._syncHeader();
|
|
561
|
-
this._renderDays();
|
|
562
|
-
});
|
|
542
|
+
yearDown.addEventListener('click', () => { this.viewYear--; this._syncHeader(); this._renderDays(); });
|
|
563
543
|
yearArrows.appendChild(yearUp);
|
|
564
544
|
yearArrows.appendChild(yearDown);
|
|
565
545
|
yearInner.appendChild(this.yearDisplayEl);
|
|
566
546
|
yearInner.appendChild(yearArrows);
|
|
567
547
|
yearHalf.appendChild(yearInner);
|
|
568
|
-
//
|
|
548
|
+
// Calendar mode toggle button
|
|
549
|
+
this.modeBtnEl = document.createElement('button');
|
|
550
|
+
this.modeBtnEl.className = 'hdp-mode-btn';
|
|
551
|
+
this.modeBtnEl.addEventListener('click', () => this._switchMode());
|
|
569
552
|
hdr.appendChild(this._navBtn('‹', -1));
|
|
570
553
|
hdr.appendChild(monthHalf);
|
|
571
554
|
hdr.appendChild(yearHalf);
|
|
572
555
|
hdr.appendChild(this._navBtn('›', 1));
|
|
556
|
+
hdr.appendChild(this.modeBtnEl);
|
|
573
557
|
this._syncHeader();
|
|
574
558
|
return hdr;
|
|
575
559
|
}
|
|
@@ -577,13 +561,45 @@
|
|
|
577
561
|
const btn = document.createElement('button');
|
|
578
562
|
btn.className = 'hdp-nav';
|
|
579
563
|
btn.innerHTML = symbol;
|
|
580
|
-
btn.setAttribute('aria-label', delta > 0 ? '
|
|
564
|
+
btn.setAttribute('aria-label', delta > 0 ? 'Next month' : 'Previous month');
|
|
581
565
|
btn.addEventListener('click', () => this._navigate(delta));
|
|
582
566
|
return btn;
|
|
583
567
|
}
|
|
584
568
|
_syncHeader() {
|
|
585
569
|
this.monthSelectEl.value = String(this.viewMonth);
|
|
586
570
|
this.yearDisplayEl.textContent = String(this.viewYear);
|
|
571
|
+
this.modeBtnEl.textContent = this.calMode === 'hijri' ? 'G' : 'ه';
|
|
572
|
+
this.modeBtnEl.title = this.calMode === 'hijri' ? 'Switch to Gregorian' : 'Switch to Hijri';
|
|
573
|
+
}
|
|
574
|
+
_rebuildMonthOptions() {
|
|
575
|
+
const labels = this.calMode === 'hijri'
|
|
576
|
+
? this.opts.monthLabels
|
|
577
|
+
: this.opts.gregorianMonthLabels;
|
|
578
|
+
this.monthSelectEl.innerHTML = '';
|
|
579
|
+
labels.forEach((name, i) => {
|
|
580
|
+
const opt = document.createElement('option');
|
|
581
|
+
opt.value = String(i + 1);
|
|
582
|
+
opt.textContent = name;
|
|
583
|
+
this.monthSelectEl.appendChild(opt);
|
|
584
|
+
});
|
|
585
|
+
this.monthSelectEl.value = String(this.viewMonth);
|
|
586
|
+
}
|
|
587
|
+
_switchMode() {
|
|
588
|
+
if (this.calMode === 'hijri') {
|
|
589
|
+
const gDate = toGregorian(this.viewYear, this.viewMonth, 1);
|
|
590
|
+
this.viewYear = gDate.getFullYear();
|
|
591
|
+
this.viewMonth = gDate.getMonth() + 1;
|
|
592
|
+
this.calMode = 'gregorian';
|
|
593
|
+
}
|
|
594
|
+
else {
|
|
595
|
+
const h = toHijri(new Date(this.viewYear, this.viewMonth - 1, 1));
|
|
596
|
+
this.viewYear = h.year;
|
|
597
|
+
this.viewMonth = h.month;
|
|
598
|
+
this.calMode = 'hijri';
|
|
599
|
+
}
|
|
600
|
+
this._rebuildMonthOptions();
|
|
601
|
+
this._syncHeader();
|
|
602
|
+
this._renderDays();
|
|
587
603
|
}
|
|
588
604
|
// ── weekdays ───────────────────────────────────────────────────────────────
|
|
589
605
|
_buildWeekdays() {
|
|
@@ -607,9 +623,15 @@
|
|
|
607
623
|
_renderDays(grid) {
|
|
608
624
|
const g = grid !== null && grid !== void 0 ? grid : this.daysGrid;
|
|
609
625
|
g.innerHTML = '';
|
|
610
|
-
const
|
|
611
|
-
const
|
|
612
|
-
const
|
|
626
|
+
const isHijri = this.calMode === 'hijri';
|
|
627
|
+
const todayH = todayHijri();
|
|
628
|
+
const todayG = todayGregorian();
|
|
629
|
+
const total = isHijri
|
|
630
|
+
? daysInMonth(this.viewYear, this.viewMonth)
|
|
631
|
+
: daysInMonthGregorian(this.viewYear, this.viewMonth);
|
|
632
|
+
const start = isHijri
|
|
633
|
+
? firstWeekday(this.viewYear, this.viewMonth)
|
|
634
|
+
: firstWeekdayGregorian(this.viewYear, this.viewMonth);
|
|
613
635
|
for (let i = 0; i < start; i++) {
|
|
614
636
|
const blank = document.createElement('div');
|
|
615
637
|
blank.className = 'hdp-day hdp-empty';
|
|
@@ -621,12 +643,14 @@
|
|
|
621
643
|
cell.textContent = String(d);
|
|
622
644
|
cell.setAttribute('role', 'button');
|
|
623
645
|
cell.setAttribute('tabindex', '0');
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
this.
|
|
629
|
-
|
|
646
|
+
const isToday = isHijri
|
|
647
|
+
? (d === todayH.day && this.viewMonth === todayH.month && this.viewYear === todayH.year)
|
|
648
|
+
: (d === todayG.day && this.viewMonth === todayG.month && this.viewYear === todayG.year);
|
|
649
|
+
const isSel = isHijri
|
|
650
|
+
? (this.selectedHijri !== null && d === this.selectedHijri.day &&
|
|
651
|
+
this.viewMonth === this.selectedHijri.month && this.viewYear === this.selectedHijri.year)
|
|
652
|
+
: (this.selectedGregorian !== null && d === this.selectedGregorian.day &&
|
|
653
|
+
this.viewMonth === this.selectedGregorian.month && this.viewYear === this.selectedGregorian.year);
|
|
630
654
|
if (isToday)
|
|
631
655
|
cell.classList.add('hdp-today');
|
|
632
656
|
if (isSel)
|
|
@@ -641,6 +665,78 @@
|
|
|
641
665
|
g.appendChild(cell);
|
|
642
666
|
}
|
|
643
667
|
}
|
|
668
|
+
// ── time section ───────────────────────────────────────────────────────────
|
|
669
|
+
_buildTimeSection() {
|
|
670
|
+
const section = document.createElement('div');
|
|
671
|
+
section.className = 'hdp-time-section';
|
|
672
|
+
const { el: hourEl, display: hourDisp } = this._buildSpinner(() => {
|
|
673
|
+
this.hour = this.opts.use24h ? (this.hour + 1) % 24 : (this.hour === 12 ? 1 : this.hour + 1);
|
|
674
|
+
this._syncTime();
|
|
675
|
+
}, () => {
|
|
676
|
+
this.hour = this.opts.use24h ? (this.hour - 1 + 24) % 24 : (this.hour === 1 ? 12 : this.hour - 1);
|
|
677
|
+
this._syncTime();
|
|
678
|
+
});
|
|
679
|
+
this.hourDisplayEl = hourDisp;
|
|
680
|
+
const colon = document.createElement('span');
|
|
681
|
+
colon.className = 'hdp-time-colon';
|
|
682
|
+
colon.textContent = ':';
|
|
683
|
+
const { el: minEl, display: minDisp } = this._buildSpinner(() => { this.minute = (this.minute + 1) % 60; this._syncTime(); }, () => { this.minute = (this.minute - 1 + 60) % 60; this._syncTime(); });
|
|
684
|
+
this.minuteDisplayEl = minDisp;
|
|
685
|
+
section.appendChild(hourEl);
|
|
686
|
+
section.appendChild(colon);
|
|
687
|
+
section.appendChild(minEl);
|
|
688
|
+
if (!this.opts.use24h) {
|
|
689
|
+
const ampm = document.createElement('div');
|
|
690
|
+
ampm.className = 'hdp-ampm';
|
|
691
|
+
const amBtn = document.createElement('button');
|
|
692
|
+
amBtn.className = 'hdp-ampm-btn';
|
|
693
|
+
amBtn.textContent = 'AM';
|
|
694
|
+
amBtn.addEventListener('click', () => { this.ampm = 'AM'; this._syncTime(); });
|
|
695
|
+
const pmBtn = document.createElement('button');
|
|
696
|
+
pmBtn.className = 'hdp-ampm-btn';
|
|
697
|
+
pmBtn.textContent = 'PM';
|
|
698
|
+
pmBtn.addEventListener('click', () => { this.ampm = 'PM'; this._syncTime(); });
|
|
699
|
+
ampm.appendChild(amBtn);
|
|
700
|
+
ampm.appendChild(pmBtn);
|
|
701
|
+
this.ampmContainerEl = ampm;
|
|
702
|
+
section.appendChild(ampm);
|
|
703
|
+
}
|
|
704
|
+
this._syncTime();
|
|
705
|
+
return section;
|
|
706
|
+
}
|
|
707
|
+
_buildSpinner(onUp, onDown) {
|
|
708
|
+
const el = document.createElement('div');
|
|
709
|
+
el.className = 'hdp-spinner';
|
|
710
|
+
const upBtn = document.createElement('button');
|
|
711
|
+
upBtn.className = 'hdp-spinner-btn';
|
|
712
|
+
upBtn.innerHTML = '▲';
|
|
713
|
+
upBtn.addEventListener('click', onUp);
|
|
714
|
+
const display = document.createElement('span');
|
|
715
|
+
display.className = 'hdp-spinner-val';
|
|
716
|
+
const downBtn = document.createElement('button');
|
|
717
|
+
downBtn.className = 'hdp-spinner-btn';
|
|
718
|
+
downBtn.innerHTML = '▼';
|
|
719
|
+
downBtn.addEventListener('click', onDown);
|
|
720
|
+
el.appendChild(upBtn);
|
|
721
|
+
el.appendChild(display);
|
|
722
|
+
el.appendChild(downBtn);
|
|
723
|
+
return { el, display };
|
|
724
|
+
}
|
|
725
|
+
_syncTime() {
|
|
726
|
+
this.hourDisplayEl.textContent = String(this.hour).padStart(2, '0');
|
|
727
|
+
this.minuteDisplayEl.textContent = String(this.minute).padStart(2, '0');
|
|
728
|
+
if (!this.opts.use24h && this.ampmContainerEl) {
|
|
729
|
+
const btns = this.ampmContainerEl.querySelectorAll('.hdp-ampm-btn');
|
|
730
|
+
btns[0].classList.toggle('hdp-ampm-active', this.ampm === 'AM');
|
|
731
|
+
btns[1].classList.toggle('hdp-ampm-active', this.ampm === 'PM');
|
|
732
|
+
}
|
|
733
|
+
if (this.selectedHijri && this.selectedGregorian) {
|
|
734
|
+
const fmt = this._buildFormatted(this.selectedHijri, this.selectedGregorian);
|
|
735
|
+
if (this.inputEl)
|
|
736
|
+
this.inputEl.value = fmt;
|
|
737
|
+
this.opts.onSelect({ hijri: this.selectedHijri, gregorian: this.selectedGregorian, time: { hour: this.hour, minute: this.minute, ampm: this.ampm } }, fmt);
|
|
738
|
+
}
|
|
739
|
+
}
|
|
644
740
|
// ── navigation ─────────────────────────────────────────────────────────────
|
|
645
741
|
_navigate(delta) {
|
|
646
742
|
this.viewMonth += delta;
|
|
@@ -657,21 +753,44 @@
|
|
|
657
753
|
}
|
|
658
754
|
// ── selection ──────────────────────────────────────────────────────────────
|
|
659
755
|
_pickDay(day) {
|
|
660
|
-
|
|
756
|
+
let hijri;
|
|
757
|
+
let gregorian;
|
|
758
|
+
if (this.calMode === 'hijri') {
|
|
759
|
+
hijri = { year: this.viewYear, month: this.viewMonth, day };
|
|
760
|
+
const gDate = toGregorian(hijri.year, hijri.month, hijri.day);
|
|
761
|
+
gregorian = { year: gDate.getFullYear(), month: gDate.getMonth() + 1, day: gDate.getDate() };
|
|
762
|
+
}
|
|
763
|
+
else {
|
|
764
|
+
gregorian = { year: this.viewYear, month: this.viewMonth, day };
|
|
765
|
+
hijri = toHijri(new Date(gregorian.year, gregorian.month - 1, gregorian.day));
|
|
766
|
+
}
|
|
767
|
+
this._applySelection(hijri, gregorian, true);
|
|
661
768
|
}
|
|
662
|
-
_applySelection(
|
|
663
|
-
this.
|
|
664
|
-
this.
|
|
665
|
-
this.
|
|
666
|
-
|
|
769
|
+
_applySelection(hijri, gregorian, closeAfter) {
|
|
770
|
+
this.selectedHijri = { ...hijri };
|
|
771
|
+
this.selectedGregorian = { ...gregorian };
|
|
772
|
+
this.viewYear = this.calMode === 'hijri' ? hijri.year : gregorian.year;
|
|
773
|
+
this.viewMonth = this.calMode === 'hijri' ? hijri.month : gregorian.month;
|
|
774
|
+
const fmt = this._buildFormatted(hijri, gregorian);
|
|
667
775
|
if (this.inputEl)
|
|
668
776
|
this.inputEl.value = fmt;
|
|
669
777
|
this._syncHeader();
|
|
670
778
|
this._renderDays();
|
|
671
|
-
this.opts.onSelect(
|
|
672
|
-
if (closeAfter && !this.opts.inline)
|
|
779
|
+
this.opts.onSelect({ hijri, gregorian, time: this.opts.showTime ? { hour: this.hour, minute: this.minute, ampm: this.ampm } : null }, fmt);
|
|
780
|
+
if (closeAfter && !this.opts.inline && !this.opts.showTime)
|
|
673
781
|
this._close();
|
|
674
782
|
}
|
|
783
|
+
_buildFormatted(hijri, gregorian) {
|
|
784
|
+
const dateStr = this.calMode === 'hijri'
|
|
785
|
+
? formatHijri(hijri, this.opts.format)
|
|
786
|
+
: formatGregorian(gregorian, this.opts.format);
|
|
787
|
+
if (!this.opts.showTime)
|
|
788
|
+
return dateStr;
|
|
789
|
+
const hh = String(this.hour).padStart(2, '0');
|
|
790
|
+
const mm = String(this.minute).padStart(2, '0');
|
|
791
|
+
const timeStr = this.opts.use24h ? ` ${hh}:${mm}` : ` ${hh}:${mm} ${this.ampm}`;
|
|
792
|
+
return dateStr + timeStr;
|
|
793
|
+
}
|
|
675
794
|
// ── open / close ───────────────────────────────────────────────────────────
|
|
676
795
|
_open() {
|
|
677
796
|
var _a;
|
|
@@ -690,17 +809,62 @@
|
|
|
690
809
|
this.opts.onClose();
|
|
691
810
|
}
|
|
692
811
|
// ── public API ─────────────────────────────────────────────────────────────
|
|
693
|
-
/** Get the currently selected
|
|
812
|
+
/** Get the currently selected date/time value */
|
|
694
813
|
getValue() {
|
|
695
|
-
|
|
814
|
+
if (!this.selectedHijri || !this.selectedGregorian)
|
|
815
|
+
return null;
|
|
816
|
+
return {
|
|
817
|
+
hijri: { ...this.selectedHijri },
|
|
818
|
+
gregorian: { ...this.selectedGregorian },
|
|
819
|
+
time: this.opts.showTime ? { hour: this.hour, minute: this.minute, ampm: this.ampm } : null,
|
|
820
|
+
};
|
|
696
821
|
}
|
|
697
|
-
/**
|
|
822
|
+
/** Set a Hijri date programmatically */
|
|
698
823
|
setValue(date) {
|
|
699
|
-
|
|
824
|
+
const gDate = toGregorian(date.year, date.month, date.day);
|
|
825
|
+
const gregorian = {
|
|
826
|
+
year: gDate.getFullYear(), month: gDate.getMonth() + 1, day: gDate.getDate(),
|
|
827
|
+
};
|
|
828
|
+
if (this.calMode === 'hijri') {
|
|
829
|
+
this.viewYear = date.year;
|
|
830
|
+
this.viewMonth = date.month;
|
|
831
|
+
}
|
|
832
|
+
else {
|
|
833
|
+
this.viewYear = gregorian.year;
|
|
834
|
+
this.viewMonth = gregorian.month;
|
|
835
|
+
}
|
|
836
|
+
this._applySelection(date, gregorian, false);
|
|
837
|
+
}
|
|
838
|
+
/** Set a Gregorian date programmatically */
|
|
839
|
+
setValueGregorian(date) {
|
|
840
|
+
const hijri = toHijri(new Date(date.year, date.month - 1, date.day));
|
|
841
|
+
if (this.calMode === 'gregorian') {
|
|
842
|
+
this.viewYear = date.year;
|
|
843
|
+
this.viewMonth = date.month;
|
|
844
|
+
}
|
|
845
|
+
else {
|
|
846
|
+
this.viewYear = hijri.year;
|
|
847
|
+
this.viewMonth = hijri.month;
|
|
848
|
+
}
|
|
849
|
+
this._applySelection(hijri, date, false);
|
|
850
|
+
}
|
|
851
|
+
/** Set the time programmatically */
|
|
852
|
+
setTime(hour, minute, ampm = 'AM') {
|
|
853
|
+
this.hour = hour;
|
|
854
|
+
this.minute = minute;
|
|
855
|
+
this.ampm = ampm;
|
|
856
|
+
if (this.opts.showTime)
|
|
857
|
+
this._syncTime();
|
|
858
|
+
}
|
|
859
|
+
/** Switch calendar display mode */
|
|
860
|
+
setMode(mode) {
|
|
861
|
+
if (this.calMode !== mode)
|
|
862
|
+
this._switchMode();
|
|
700
863
|
}
|
|
701
864
|
/** Clear the selected date */
|
|
702
865
|
clear() {
|
|
703
|
-
this.
|
|
866
|
+
this.selectedHijri = null;
|
|
867
|
+
this.selectedGregorian = null;
|
|
704
868
|
if (this.inputEl)
|
|
705
869
|
this.inputEl.value = '';
|
|
706
870
|
this._renderDays();
|
|
@@ -718,14 +882,8 @@
|
|
|
718
882
|
this._applyVars(this.root);
|
|
719
883
|
this._renderDays();
|
|
720
884
|
}
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
this._open();
|
|
724
|
-
}
|
|
725
|
-
/** Close the picker programmatically */
|
|
726
|
-
close() {
|
|
727
|
-
this._close();
|
|
728
|
-
}
|
|
885
|
+
open() { this._open(); }
|
|
886
|
+
close() { this._close(); }
|
|
729
887
|
/** Remove the picker from the DOM and clean up listeners */
|
|
730
888
|
destroy() {
|
|
731
889
|
document.removeEventListener('click', this._onDocClick, true);
|
|
@@ -734,15 +892,21 @@
|
|
|
734
892
|
}
|
|
735
893
|
}
|
|
736
894
|
|
|
895
|
+
exports.GREGORIAN_MONTHS_EN = GREGORIAN_MONTHS_EN;
|
|
737
896
|
exports.HIJRI_MONTHS_AR = HIJRI_MONTHS_AR;
|
|
738
897
|
exports.HijriDatePicker = HijriDatePicker;
|
|
739
898
|
exports.WEEKDAY_AR = WEEKDAY_AR;
|
|
899
|
+
exports.WEEKDAY_EN = WEEKDAY_EN;
|
|
740
900
|
exports.daysInMonth = daysInMonth;
|
|
901
|
+
exports.daysInMonthGregorian = daysInMonthGregorian;
|
|
741
902
|
exports.firstWeekday = firstWeekday;
|
|
903
|
+
exports.firstWeekdayGregorian = firstWeekdayGregorian;
|
|
904
|
+
exports.formatGregorian = formatGregorian;
|
|
742
905
|
exports.formatHijri = formatHijri;
|
|
743
906
|
exports.parseHijri = parseHijri;
|
|
744
907
|
exports.toGregorian = toGregorian;
|
|
745
908
|
exports.toHijri = toHijri;
|
|
909
|
+
exports.todayGregorian = todayGregorian;
|
|
746
910
|
exports.todayHijri = todayHijri;
|
|
747
911
|
|
|
748
912
|
}));
|