@idds/js 1.0.37 → 1.0.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.iife.js +464 -138
- package/dist/index.js +304 -185
- package/package.json +1 -1
package/dist/index.iife.js
CHANGED
|
@@ -31,6 +31,7 @@ var InaUI = (() => {
|
|
|
31
31
|
initModal: () => initModal,
|
|
32
32
|
initRangeDatepicker: () => initRangeDatepicker,
|
|
33
33
|
initTab: () => initTab,
|
|
34
|
+
initTimepicker: () => initTimepicker,
|
|
34
35
|
initToggle: () => initToggle,
|
|
35
36
|
showToast: () => showToast
|
|
36
37
|
});
|
|
@@ -120,17 +121,24 @@ var InaUI = (() => {
|
|
|
120
121
|
// src/js/components/stateful/datepicker.js
|
|
121
122
|
function initDatepicker() {
|
|
122
123
|
document.querySelectorAll(".ina-date-picker").forEach((datepicker) => {
|
|
124
|
+
if (datepicker.dataset.initialized === "true") return;
|
|
125
|
+
datepicker.dataset.initialized = "true";
|
|
126
|
+
const mode = datepicker.dataset.mode || "single";
|
|
127
|
+
const format = datepicker.dataset.format || "d MMMM yyyy";
|
|
123
128
|
const trigger = datepicker.querySelector(".ina-date-picker__trigger");
|
|
124
129
|
const triggerText = trigger.querySelector(".ina-date-picker__trigger-text");
|
|
125
130
|
const panel = datepicker.querySelector(".ina-date-picker__panel");
|
|
131
|
+
panel.style.display = "none";
|
|
126
132
|
let panelContent = panel.querySelector(".ina-date-picker__panel-content");
|
|
127
133
|
if (!panelContent) {
|
|
128
134
|
panelContent = document.createElement("div");
|
|
129
135
|
panelContent.className = "ina-date-picker__panel-content";
|
|
130
136
|
panel.appendChild(panelContent);
|
|
131
137
|
}
|
|
132
|
-
let
|
|
138
|
+
let viewDate = /* @__PURE__ */ new Date();
|
|
133
139
|
let selectedDate = null;
|
|
140
|
+
let selectedDates = [];
|
|
141
|
+
let rangeDate = [null, null];
|
|
134
142
|
let isOpen = false;
|
|
135
143
|
const MONTHS_ID = [
|
|
136
144
|
"Januari",
|
|
@@ -162,18 +170,67 @@ var InaUI = (() => {
|
|
|
162
170
|
];
|
|
163
171
|
const DAYS_SHORT = ["Min", "Sen", "Sel", "Rab", "Kam", "Jum", "Sab"];
|
|
164
172
|
function formatDate(date) {
|
|
173
|
+
if (!date) return "";
|
|
165
174
|
const day = date.getDate().toString().padStart(2, "0");
|
|
166
175
|
const monthIndex = date.getMonth();
|
|
167
176
|
const year = date.getFullYear();
|
|
168
177
|
return `${day} ${MONTHS_SHORT_ID[monthIndex]} ${year}`;
|
|
169
178
|
}
|
|
170
|
-
function
|
|
171
|
-
if (
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
179
|
+
function updateTrigger() {
|
|
180
|
+
if (mode === "single") {
|
|
181
|
+
if (selectedDate) {
|
|
182
|
+
triggerText.textContent = formatDate(selectedDate);
|
|
183
|
+
triggerText.classList.add("ina-date-picker__trigger-text--value");
|
|
184
|
+
triggerText.classList.remove(
|
|
185
|
+
"ina-date-picker__trigger-text--placeholder"
|
|
186
|
+
);
|
|
187
|
+
} else {
|
|
188
|
+
triggerText.textContent = "Pilih Tanggal";
|
|
189
|
+
triggerText.classList.remove("ina-date-picker__trigger-text--value");
|
|
190
|
+
triggerText.classList.add(
|
|
191
|
+
"ina-date-picker__trigger-text--placeholder"
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
} else if (mode === "range") {
|
|
195
|
+
if (rangeDate[0] && rangeDate[1]) {
|
|
196
|
+
const start = formatDate(rangeDate[0]);
|
|
197
|
+
const end = formatDate(rangeDate[1]);
|
|
198
|
+
triggerText.textContent = `${start} - ${end}`;
|
|
199
|
+
triggerText.classList.add("ina-date-picker__trigger-text--value");
|
|
200
|
+
triggerText.classList.remove(
|
|
201
|
+
"ina-date-picker__trigger-text--placeholder"
|
|
202
|
+
);
|
|
203
|
+
} else if (rangeDate[0]) {
|
|
204
|
+
triggerText.textContent = `${formatDate(rangeDate[0])} - ...`;
|
|
205
|
+
triggerText.classList.add("ina-date-picker__trigger-text--value");
|
|
206
|
+
} else {
|
|
207
|
+
triggerText.textContent = "Pilih Rentang Tanggal";
|
|
208
|
+
triggerText.classList.remove("ina-date-picker__trigger-text--value");
|
|
209
|
+
triggerText.classList.add(
|
|
210
|
+
"ina-date-picker__trigger-text--placeholder"
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
} else if (mode === "multiple") {
|
|
214
|
+
if (selectedDates.length > 0) {
|
|
215
|
+
triggerText.textContent = `${selectedDates.length} Tanggal Terpilih`;
|
|
216
|
+
triggerText.classList.add("ina-date-picker__trigger-text--value");
|
|
217
|
+
triggerText.classList.remove(
|
|
218
|
+
"ina-date-picker__trigger-text--placeholder"
|
|
219
|
+
);
|
|
220
|
+
} else {
|
|
221
|
+
triggerText.textContent = "Pilih Beberapa Tanggal";
|
|
222
|
+
triggerText.classList.remove("ina-date-picker__trigger-text--value");
|
|
223
|
+
triggerText.classList.add(
|
|
224
|
+
"ina-date-picker__trigger-text--placeholder"
|
|
225
|
+
);
|
|
226
|
+
}
|
|
176
227
|
}
|
|
228
|
+
}
|
|
229
|
+
function createIcon(name, size = 16) {
|
|
230
|
+
if (name === "chevron-left")
|
|
231
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" width="${size}" height="${size}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 6l-6 6l6 6" /></svg>`;
|
|
232
|
+
if (name === "chevron-right")
|
|
233
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" width="${size}" height="${size}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 6l6 6l-6 6" /></svg>`;
|
|
177
234
|
return "";
|
|
178
235
|
}
|
|
179
236
|
function createMonthPicker(initialMonth, onChange) {
|
|
@@ -184,16 +241,10 @@ var InaUI = (() => {
|
|
|
184
241
|
const pickerTrigger = document.createElement("button");
|
|
185
242
|
pickerTrigger.type = "button";
|
|
186
243
|
pickerTrigger.className = "ina-month-picker__trigger ina-month-picker__trigger--size-sm";
|
|
187
|
-
const
|
|
188
|
-
pickerTrigger.innerHTML =
|
|
189
|
-
<span class="ina-month-picker__trigger-text">${MONTHS_SHORT_ID[currentMonthIdx]}</span>
|
|
190
|
-
`;
|
|
244
|
+
const updateText = () => {
|
|
245
|
+
pickerTrigger.innerHTML = `<span class="ina-month-picker__trigger-text">${MONTHS_SHORT_ID[currentMonthIdx]}</span>`;
|
|
191
246
|
};
|
|
192
|
-
|
|
193
|
-
pickerTrigger.addEventListener("click", (e) => {
|
|
194
|
-
e.stopPropagation();
|
|
195
|
-
togglePicker(!isPickerOpen);
|
|
196
|
-
});
|
|
247
|
+
updateText();
|
|
197
248
|
const pickerPanel = document.createElement("div");
|
|
198
249
|
pickerPanel.className = "ina-month-picker__panel";
|
|
199
250
|
const grid = document.createElement("div");
|
|
@@ -208,21 +259,18 @@ var InaUI = (() => {
|
|
|
208
259
|
btn.addEventListener("click", (e) => {
|
|
209
260
|
e.stopPropagation();
|
|
210
261
|
currentMonthIdx = idx;
|
|
211
|
-
|
|
212
|
-
grid.querySelectorAll(".ina-month-picker__month-option").forEach((b, i) => {
|
|
213
|
-
if (i === idx)
|
|
214
|
-
b.classList.add("ina-month-picker__month-option--selected");
|
|
215
|
-
else
|
|
216
|
-
b.classList.remove("ina-month-picker__month-option--selected");
|
|
217
|
-
});
|
|
262
|
+
updateText();
|
|
218
263
|
togglePicker(false);
|
|
219
264
|
onChange(idx);
|
|
220
265
|
});
|
|
221
266
|
grid.appendChild(btn);
|
|
222
267
|
});
|
|
223
268
|
pickerPanel.appendChild(grid);
|
|
224
|
-
container.
|
|
225
|
-
|
|
269
|
+
container.append(pickerTrigger, pickerPanel);
|
|
270
|
+
pickerTrigger.addEventListener("click", (e) => {
|
|
271
|
+
e.stopPropagation();
|
|
272
|
+
togglePicker(!isPickerOpen);
|
|
273
|
+
});
|
|
226
274
|
function togglePicker(show) {
|
|
227
275
|
isPickerOpen = show;
|
|
228
276
|
if (show) {
|
|
@@ -240,13 +288,7 @@ var InaUI = (() => {
|
|
|
240
288
|
element: container,
|
|
241
289
|
setMonth: (m) => {
|
|
242
290
|
currentMonthIdx = m;
|
|
243
|
-
|
|
244
|
-
grid.querySelectorAll(".ina-month-picker__month-option").forEach((b, i) => {
|
|
245
|
-
if (i === m)
|
|
246
|
-
b.classList.add("ina-month-picker__month-option--selected");
|
|
247
|
-
else
|
|
248
|
-
b.classList.remove("ina-month-picker__month-option--selected");
|
|
249
|
-
});
|
|
291
|
+
updateText();
|
|
250
292
|
}
|
|
251
293
|
};
|
|
252
294
|
}
|
|
@@ -259,16 +301,10 @@ var InaUI = (() => {
|
|
|
259
301
|
const pickerTrigger = document.createElement("button");
|
|
260
302
|
pickerTrigger.type = "button";
|
|
261
303
|
pickerTrigger.className = "ina-year-picker__trigger ina-year-picker__trigger--size-sm";
|
|
262
|
-
const
|
|
263
|
-
pickerTrigger.innerHTML =
|
|
264
|
-
<span class="ina-year-picker__trigger-text">${currentYearVal}</span>
|
|
265
|
-
`;
|
|
304
|
+
const updateText = () => {
|
|
305
|
+
pickerTrigger.innerHTML = `<span class="ina-year-picker__trigger-text">${currentYearVal}</span>`;
|
|
266
306
|
};
|
|
267
|
-
|
|
268
|
-
pickerTrigger.addEventListener("click", (e) => {
|
|
269
|
-
e.stopPropagation();
|
|
270
|
-
togglePicker(!isPickerOpen);
|
|
271
|
-
});
|
|
307
|
+
updateText();
|
|
272
308
|
const pickerPanel = document.createElement("div");
|
|
273
309
|
pickerPanel.className = "ina-year-picker__panel";
|
|
274
310
|
const header = document.createElement("div");
|
|
@@ -309,7 +345,7 @@ var InaUI = (() => {
|
|
|
309
345
|
btn.addEventListener("click", (e) => {
|
|
310
346
|
e.stopPropagation();
|
|
311
347
|
currentYearVal = y;
|
|
312
|
-
|
|
348
|
+
updateText();
|
|
313
349
|
togglePicker(false);
|
|
314
350
|
onChange(y);
|
|
315
351
|
});
|
|
@@ -318,16 +354,18 @@ var InaUI = (() => {
|
|
|
318
354
|
}
|
|
319
355
|
pickerPanel.append(header, grid);
|
|
320
356
|
container.append(pickerTrigger, pickerPanel);
|
|
357
|
+
pickerTrigger.addEventListener("click", (e) => {
|
|
358
|
+
e.stopPropagation();
|
|
359
|
+
togglePicker(!isPickerOpen);
|
|
360
|
+
});
|
|
321
361
|
function togglePicker(show) {
|
|
322
362
|
isPickerOpen = show;
|
|
323
363
|
if (show) {
|
|
324
364
|
decadeStart = Math.floor(currentYearVal / 20) * 20;
|
|
325
365
|
renderGrid();
|
|
326
366
|
pickerPanel.classList.add("ina-year-picker__panel--open");
|
|
327
|
-
pickerTrigger.setAttribute("aria-expanded", "true");
|
|
328
367
|
} else {
|
|
329
368
|
pickerPanel.classList.remove("ina-year-picker__panel--open");
|
|
330
|
-
pickerTrigger.setAttribute("aria-expanded", "false");
|
|
331
369
|
}
|
|
332
370
|
}
|
|
333
371
|
document.addEventListener("click", (e) => {
|
|
@@ -337,131 +375,212 @@ var InaUI = (() => {
|
|
|
337
375
|
element: container,
|
|
338
376
|
setYear: (y) => {
|
|
339
377
|
currentYearVal = y;
|
|
340
|
-
|
|
378
|
+
updateText();
|
|
341
379
|
}
|
|
342
380
|
};
|
|
343
381
|
}
|
|
344
|
-
function
|
|
345
|
-
|
|
346
|
-
const
|
|
347
|
-
const
|
|
348
|
-
|
|
349
|
-
|
|
382
|
+
function renderCalendarGrid(baseDate, isNextMonth = false) {
|
|
383
|
+
const year = baseDate.getFullYear();
|
|
384
|
+
const month = baseDate.getMonth();
|
|
385
|
+
const container = document.createElement("div");
|
|
386
|
+
if (!isNextMonth) {
|
|
387
|
+
container.className = "ina-date-picker__calendar-container";
|
|
388
|
+
} else {
|
|
389
|
+
container.className = "ina-date-picker__calendar";
|
|
390
|
+
}
|
|
350
391
|
const header = document.createElement("div");
|
|
351
|
-
header.className = "ina-date-picker__calendar-header";
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
392
|
+
header.className = isNextMonth ? "ina-date-picker__next-month-header" : "ina-date-picker__calendar-header";
|
|
393
|
+
if (!isNextMonth) {
|
|
394
|
+
const prevBtn = document.createElement("button");
|
|
395
|
+
prevBtn.type = "button";
|
|
396
|
+
prevBtn.className = "ina-date-picker__nav-button";
|
|
397
|
+
prevBtn.innerHTML = createIcon("chevron-left");
|
|
398
|
+
prevBtn.onclick = (e) => {
|
|
399
|
+
e.stopPropagation();
|
|
400
|
+
viewDate.setMonth(viewDate.getMonth() - 1);
|
|
401
|
+
render();
|
|
402
|
+
};
|
|
403
|
+
header.appendChild(prevBtn);
|
|
404
|
+
} else {
|
|
405
|
+
const spacer = document.createElement("div");
|
|
406
|
+
spacer.style.width = "32px";
|
|
407
|
+
header.appendChild(spacer);
|
|
408
|
+
}
|
|
409
|
+
if (!isNextMonth) {
|
|
410
|
+
const controls = document.createElement("div");
|
|
411
|
+
controls.className = "ina-date-picker__header-controls";
|
|
412
|
+
const monthCont = document.createElement("div");
|
|
413
|
+
monthCont.className = "ina-date-picker__dropdown-container";
|
|
414
|
+
const monthPicker = createMonthPicker(month, (m) => {
|
|
415
|
+
viewDate.setMonth(m);
|
|
416
|
+
render();
|
|
417
|
+
});
|
|
418
|
+
monthCont.appendChild(monthPicker.element);
|
|
419
|
+
const yearCont = document.createElement("div");
|
|
420
|
+
yearCont.className = "ina-date-picker__dropdown-container";
|
|
421
|
+
const yearPicker = createYearPicker(year, (y) => {
|
|
422
|
+
viewDate.setFullYear(y);
|
|
423
|
+
render();
|
|
424
|
+
});
|
|
425
|
+
yearCont.appendChild(yearPicker.element);
|
|
426
|
+
controls.append(monthCont, yearCont);
|
|
427
|
+
header.appendChild(controls);
|
|
428
|
+
} else {
|
|
429
|
+
const title = document.createElement("div");
|
|
430
|
+
title.className = "ina-date-picker__calendar-title";
|
|
431
|
+
title.textContent = `${MONTHS_ID[month]} ${year}`;
|
|
432
|
+
header.appendChild(title);
|
|
433
|
+
}
|
|
434
|
+
const showNextBtn = mode === "single" && !isNextMonth || isNextMonth;
|
|
435
|
+
if (showNextBtn) {
|
|
436
|
+
const nextBtn = document.createElement("button");
|
|
437
|
+
nextBtn.type = "button";
|
|
438
|
+
nextBtn.className = "ina-date-picker__nav-button";
|
|
439
|
+
nextBtn.innerHTML = createIcon("chevron-right");
|
|
440
|
+
nextBtn.onclick = (e) => {
|
|
441
|
+
e.stopPropagation();
|
|
442
|
+
viewDate.setMonth(viewDate.getMonth() + 1);
|
|
443
|
+
render();
|
|
444
|
+
};
|
|
445
|
+
header.appendChild(nextBtn);
|
|
446
|
+
} else if (!isNextMonth) {
|
|
447
|
+
const spacer = document.createElement("div");
|
|
448
|
+
spacer.style.width = "32px";
|
|
449
|
+
header.appendChild(spacer);
|
|
450
|
+
}
|
|
388
451
|
const grid = document.createElement("div");
|
|
389
452
|
grid.className = "ina-date-picker__calendar-grid";
|
|
390
|
-
DAYS_SHORT.forEach((
|
|
453
|
+
DAYS_SHORT.forEach((d) => {
|
|
391
454
|
const dh = document.createElement("div");
|
|
392
455
|
dh.className = "ina-date-picker__day-header";
|
|
393
|
-
dh.textContent =
|
|
456
|
+
dh.textContent = d;
|
|
394
457
|
grid.appendChild(dh);
|
|
395
458
|
});
|
|
396
459
|
const firstDayOfMonth = new Date(year, month, 1).getDay();
|
|
397
460
|
const daysInMonth = new Date(year, month + 1, 0).getDate();
|
|
398
461
|
const daysInPrevMonth = new Date(year, month, 0).getDate();
|
|
462
|
+
const today = /* @__PURE__ */ new Date();
|
|
399
463
|
for (let i = firstDayOfMonth - 1; i >= 0; i--) {
|
|
400
|
-
const
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
grid.appendChild(
|
|
464
|
+
const btn = document.createElement("button");
|
|
465
|
+
btn.type = "button";
|
|
466
|
+
btn.className = "ina-date-picker__day ina-date-picker__day--other-month ina-date-picker__day--disabled";
|
|
467
|
+
btn.textContent = daysInPrevMonth - i;
|
|
468
|
+
grid.appendChild(btn);
|
|
405
469
|
}
|
|
406
|
-
const today = /* @__PURE__ */ new Date();
|
|
407
470
|
for (let i = 1; i <= daysInMonth; i++) {
|
|
408
|
-
const
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
471
|
+
const date = new Date(year, month, i);
|
|
472
|
+
const btn = document.createElement("button");
|
|
473
|
+
btn.type = "button";
|
|
474
|
+
btn.className = "ina-date-picker__day";
|
|
475
|
+
btn.textContent = i;
|
|
412
476
|
let isSelected = false;
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
477
|
+
let isInRange = false;
|
|
478
|
+
if (mode === "single" && selectedDate) {
|
|
479
|
+
if (date.toDateString() === selectedDate.toDateString())
|
|
480
|
+
isSelected = true;
|
|
481
|
+
} else if (mode === "multiple") {
|
|
482
|
+
if (selectedDates.some((d) => d.toDateString() === date.toDateString()))
|
|
483
|
+
isSelected = true;
|
|
484
|
+
} else if (mode === "range") {
|
|
485
|
+
const [start, end] = rangeDate;
|
|
486
|
+
if (start && date.toDateString() === start.toDateString())
|
|
487
|
+
isSelected = true;
|
|
488
|
+
if (end && date.toDateString() === end.toDateString())
|
|
489
|
+
isSelected = true;
|
|
490
|
+
if (start && end && date > start && date < end) isInRange = true;
|
|
419
491
|
}
|
|
420
|
-
if (
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
492
|
+
if (isSelected) btn.classList.add("ina-date-picker__day--selected");
|
|
493
|
+
if (isInRange) btn.classList.add("ina-date-picker__day--in-range");
|
|
494
|
+
if (date.toDateString() === today.toDateString())
|
|
495
|
+
btn.classList.add("ina-date-picker__day--today");
|
|
496
|
+
if (!isSelected && !isInRange)
|
|
497
|
+
btn.classList.add("ina-date-picker__day--hover");
|
|
498
|
+
btn.onclick = (e) => {
|
|
424
499
|
e.stopPropagation();
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
500
|
+
if (mode === "single") {
|
|
501
|
+
selectedDate = date;
|
|
502
|
+
close();
|
|
503
|
+
} else if (mode === "multiple") {
|
|
504
|
+
const existsIdx = selectedDates.findIndex(
|
|
505
|
+
(d) => d.toDateString() === date.toDateString()
|
|
506
|
+
);
|
|
507
|
+
if (existsIdx >= 0) selectedDates.splice(existsIdx, 1);
|
|
508
|
+
else selectedDates.push(date);
|
|
509
|
+
render();
|
|
510
|
+
} else if (mode === "range") {
|
|
511
|
+
const [start, end] = rangeDate;
|
|
512
|
+
if (!start || start && end) {
|
|
513
|
+
rangeDate = [date, null];
|
|
514
|
+
} else {
|
|
515
|
+
if (date < start) {
|
|
516
|
+
rangeDate = [date, start];
|
|
517
|
+
} else {
|
|
518
|
+
rangeDate = [start, date];
|
|
519
|
+
}
|
|
520
|
+
close();
|
|
521
|
+
}
|
|
522
|
+
render();
|
|
523
|
+
}
|
|
524
|
+
updateTrigger();
|
|
431
525
|
datepicker.dispatchEvent(
|
|
432
|
-
new CustomEvent("date:changed", {
|
|
526
|
+
new CustomEvent("date:changed", {
|
|
527
|
+
detail: {
|
|
528
|
+
selectedDate: mode === "single" ? selectedDate : mode === "multiple" ? selectedDates : rangeDate
|
|
529
|
+
}
|
|
530
|
+
})
|
|
433
531
|
);
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
grid.appendChild(dayBtn);
|
|
532
|
+
};
|
|
533
|
+
grid.appendChild(btn);
|
|
437
534
|
}
|
|
438
|
-
const
|
|
439
|
-
const remaining = 42 -
|
|
535
|
+
const usedCells = grid.children.length - 7;
|
|
536
|
+
const remaining = 42 - usedCells;
|
|
440
537
|
for (let i = 1; i <= remaining; i++) {
|
|
441
|
-
const
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
grid.appendChild(
|
|
538
|
+
const btn = document.createElement("button");
|
|
539
|
+
btn.type = "button";
|
|
540
|
+
btn.className = "ina-date-picker__day ina-date-picker__day--other-month ina-date-picker__day--disabled";
|
|
541
|
+
btn.textContent = i;
|
|
542
|
+
grid.appendChild(btn);
|
|
446
543
|
}
|
|
447
|
-
|
|
448
|
-
|
|
544
|
+
container.append(header, grid);
|
|
545
|
+
return container;
|
|
449
546
|
}
|
|
450
|
-
function
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
547
|
+
function render() {
|
|
548
|
+
panelContent.innerHTML = "";
|
|
549
|
+
const cal1 = renderCalendarGrid(viewDate);
|
|
550
|
+
panelContent.appendChild(cal1);
|
|
551
|
+
if (mode === "range" || mode === "multiple") {
|
|
552
|
+
const nextMonthDate = new Date(
|
|
553
|
+
viewDate.getFullYear(),
|
|
554
|
+
viewDate.getMonth() + 1,
|
|
555
|
+
1
|
|
556
|
+
);
|
|
557
|
+
const cal2 = renderCalendarGrid(nextMonthDate, true);
|
|
558
|
+
panelContent.appendChild(cal2);
|
|
457
559
|
}
|
|
458
560
|
}
|
|
561
|
+
function open() {
|
|
562
|
+
isOpen = true;
|
|
563
|
+
panel.classList.add("ina-date-picker__panel--open");
|
|
564
|
+
panel.style.display = "block";
|
|
565
|
+
render();
|
|
566
|
+
}
|
|
567
|
+
function close() {
|
|
568
|
+
isOpen = false;
|
|
569
|
+
panel.classList.remove("ina-date-picker__panel--open");
|
|
570
|
+
panel.style.display = "none";
|
|
571
|
+
}
|
|
572
|
+
function toggle() {
|
|
573
|
+
if (isOpen) close();
|
|
574
|
+
else open();
|
|
575
|
+
}
|
|
459
576
|
trigger.addEventListener("click", (e) => {
|
|
460
577
|
e.stopPropagation();
|
|
461
|
-
toggle(
|
|
578
|
+
toggle();
|
|
462
579
|
});
|
|
463
580
|
document.addEventListener("click", (e) => {
|
|
464
|
-
if (!datepicker.contains(e.target))
|
|
581
|
+
if (!datepicker.contains(e.target)) {
|
|
582
|
+
close();
|
|
583
|
+
}
|
|
465
584
|
});
|
|
466
585
|
});
|
|
467
586
|
}
|
|
@@ -886,6 +1005,212 @@ var InaUI = (() => {
|
|
|
886
1005
|
});
|
|
887
1006
|
}
|
|
888
1007
|
|
|
1008
|
+
// src/js/components/stateful/timepicker.js
|
|
1009
|
+
function initTimepicker() {
|
|
1010
|
+
document.querySelectorAll(".ina-time-picker").forEach((picker) => {
|
|
1011
|
+
if (picker.dataset.initialized === "true") return;
|
|
1012
|
+
picker.dataset.initialized = "true";
|
|
1013
|
+
const input = picker.querySelector(".ina-time-picker__input");
|
|
1014
|
+
const wrapper = picker.querySelector(".ina-time-picker__wrapper");
|
|
1015
|
+
if (!input || !wrapper) return;
|
|
1016
|
+
const format = picker.dataset.format || "HH:mm";
|
|
1017
|
+
const use12Hours = picker.dataset.use12Hours === "true";
|
|
1018
|
+
const showSecond = picker.dataset.showSecond === "true";
|
|
1019
|
+
const disabled = picker.classList.contains("ina-time-picker--disabled");
|
|
1020
|
+
const allowClear = picker.dataset.allowClear !== "false";
|
|
1021
|
+
let isOpen = false;
|
|
1022
|
+
let internalValue = input.value || "";
|
|
1023
|
+
let panel = picker.querySelector(".ina-time-picker__panel");
|
|
1024
|
+
if (!panel) {
|
|
1025
|
+
panel = document.createElement("div");
|
|
1026
|
+
panel.className = "ina-time-picker__panel";
|
|
1027
|
+
panel.style.display = "none";
|
|
1028
|
+
picker.appendChild(panel);
|
|
1029
|
+
}
|
|
1030
|
+
let content = panel.querySelector(".ina-time-picker__content");
|
|
1031
|
+
if (!content) {
|
|
1032
|
+
content = document.createElement("div");
|
|
1033
|
+
content.className = "ina-time-picker__content";
|
|
1034
|
+
panel.appendChild(content);
|
|
1035
|
+
} else {
|
|
1036
|
+
content.innerHTML = "";
|
|
1037
|
+
}
|
|
1038
|
+
let actions = panel.querySelector(".ina-time-picker__actions");
|
|
1039
|
+
if (!actions) {
|
|
1040
|
+
actions = document.createElement("div");
|
|
1041
|
+
actions.className = "ina-time-picker__actions";
|
|
1042
|
+
const confirmBtn = document.createElement("button");
|
|
1043
|
+
confirmBtn.type = "button";
|
|
1044
|
+
confirmBtn.className = "ina-time-picker__confirm-button";
|
|
1045
|
+
confirmBtn.textContent = "Pilih";
|
|
1046
|
+
confirmBtn.onclick = (e) => {
|
|
1047
|
+
e.stopPropagation();
|
|
1048
|
+
close();
|
|
1049
|
+
};
|
|
1050
|
+
actions.appendChild(confirmBtn);
|
|
1051
|
+
panel.appendChild(actions);
|
|
1052
|
+
}
|
|
1053
|
+
const parseTime = (timeStr) => {
|
|
1054
|
+
if (!timeStr) return { hours: 0, minutes: 0, seconds: 0, period: "AM" };
|
|
1055
|
+
let hours = 0, minutes = 0, seconds = 0, period = "AM";
|
|
1056
|
+
try {
|
|
1057
|
+
if (use12Hours) {
|
|
1058
|
+
const [time, p] = timeStr.split(" ");
|
|
1059
|
+
const [h, m, s] = time.split(":");
|
|
1060
|
+
hours = parseInt(h || "0", 10);
|
|
1061
|
+
minutes = parseInt(m || "0", 10);
|
|
1062
|
+
seconds = parseInt(s || "0", 10);
|
|
1063
|
+
period = p || "AM";
|
|
1064
|
+
} else {
|
|
1065
|
+
const [h, m, s] = timeStr.split(":");
|
|
1066
|
+
hours = parseInt(h || "0", 10);
|
|
1067
|
+
minutes = parseInt(m || "0", 10);
|
|
1068
|
+
seconds = parseInt(s || "0", 10);
|
|
1069
|
+
}
|
|
1070
|
+
} catch (e) {
|
|
1071
|
+
console.warn("Invalid time format", timeStr);
|
|
1072
|
+
}
|
|
1073
|
+
return { hours, minutes, seconds, period };
|
|
1074
|
+
};
|
|
1075
|
+
const formatTime = (h, m, s, p) => {
|
|
1076
|
+
const pad = (n) => n.toString().padStart(2, "0");
|
|
1077
|
+
if (use12Hours) {
|
|
1078
|
+
let displayHours = h;
|
|
1079
|
+
if (displayHours === 0) displayHours = 12;
|
|
1080
|
+
const main = `${pad(displayHours)}:${pad(m)}`;
|
|
1081
|
+
const sec = showSecond ? `:${pad(s)}` : "";
|
|
1082
|
+
return `${main}${sec} ${p}`;
|
|
1083
|
+
} else {
|
|
1084
|
+
const main = `${pad(h)}:${pad(m)}`;
|
|
1085
|
+
const sec = showSecond ? `:${pad(s)}` : "";
|
|
1086
|
+
return `${main}${sec}`;
|
|
1087
|
+
}
|
|
1088
|
+
};
|
|
1089
|
+
let currentTime = parseTime(internalValue);
|
|
1090
|
+
const renderColumn = (type, max) => {
|
|
1091
|
+
const column = document.createElement("div");
|
|
1092
|
+
column.className = `ina-time-picker__column ina-time-picker__column--${type}`;
|
|
1093
|
+
const colContent = document.createElement("div");
|
|
1094
|
+
colContent.className = "ina-time-picker__column-content";
|
|
1095
|
+
column.appendChild(colContent);
|
|
1096
|
+
const start = type === "hour" && use12Hours ? 1 : 0;
|
|
1097
|
+
const end = type === "hour" && use12Hours ? 12 : max - 1;
|
|
1098
|
+
for (let i = start; i <= end; i++) {
|
|
1099
|
+
const option = document.createElement("div");
|
|
1100
|
+
option.className = "ina-time-picker__option";
|
|
1101
|
+
option.textContent = i.toString().padStart(2, "0");
|
|
1102
|
+
option.dataset.value = i;
|
|
1103
|
+
let isSelected = false;
|
|
1104
|
+
if (type === "hour") {
|
|
1105
|
+
isSelected = currentTime.hours === i || use12Hours && currentTime.hours === 0 && i === 12;
|
|
1106
|
+
} else if (type === "minute") isSelected = currentTime.minutes === i;
|
|
1107
|
+
else if (type === "second") isSelected = currentTime.seconds === i;
|
|
1108
|
+
if (isSelected)
|
|
1109
|
+
option.classList.add("ina-time-picker__option--selected");
|
|
1110
|
+
option.addEventListener("click", (e) => {
|
|
1111
|
+
e.stopPropagation();
|
|
1112
|
+
const val = parseInt(option.dataset.value, 10);
|
|
1113
|
+
if (type === "hour")
|
|
1114
|
+
currentTime.hours = use12Hours && val === 12 ? 0 : val;
|
|
1115
|
+
if (type === "hour") currentTime.hours = val;
|
|
1116
|
+
if (type === "minute") currentTime.minutes = val;
|
|
1117
|
+
if (type === "second") currentTime.seconds = val;
|
|
1118
|
+
updateInput();
|
|
1119
|
+
colContent.querySelectorAll(".ina-time-picker__option").forEach(
|
|
1120
|
+
(el) => el.classList.remove("ina-time-picker__option--selected")
|
|
1121
|
+
);
|
|
1122
|
+
option.classList.add("ina-time-picker__option--selected");
|
|
1123
|
+
});
|
|
1124
|
+
colContent.appendChild(option);
|
|
1125
|
+
}
|
|
1126
|
+
return column;
|
|
1127
|
+
};
|
|
1128
|
+
const renderPeriodColumn = () => {
|
|
1129
|
+
const column = document.createElement("div");
|
|
1130
|
+
column.className = `ina-time-picker__column ina-time-picker__column--period`;
|
|
1131
|
+
const colContent = document.createElement("div");
|
|
1132
|
+
colContent.className = "ina-time-picker__column-content";
|
|
1133
|
+
column.appendChild(colContent);
|
|
1134
|
+
["AM", "PM"].forEach((p) => {
|
|
1135
|
+
const option = document.createElement("div");
|
|
1136
|
+
option.className = "ina-time-picker__option";
|
|
1137
|
+
option.textContent = p;
|
|
1138
|
+
if (currentTime.period === p)
|
|
1139
|
+
option.classList.add("ina-time-picker__option--selected");
|
|
1140
|
+
option.addEventListener("click", (e) => {
|
|
1141
|
+
e.stopPropagation();
|
|
1142
|
+
currentTime.period = p;
|
|
1143
|
+
updateInput();
|
|
1144
|
+
colContent.querySelectorAll(".ina-time-picker__option").forEach(
|
|
1145
|
+
(el) => el.classList.remove("ina-time-picker__option--selected")
|
|
1146
|
+
);
|
|
1147
|
+
option.classList.add("ina-time-picker__option--selected");
|
|
1148
|
+
});
|
|
1149
|
+
colContent.appendChild(option);
|
|
1150
|
+
});
|
|
1151
|
+
return column;
|
|
1152
|
+
};
|
|
1153
|
+
const updateInput = () => {
|
|
1154
|
+
const val = formatTime(
|
|
1155
|
+
currentTime.hours,
|
|
1156
|
+
currentTime.minutes,
|
|
1157
|
+
currentTime.seconds,
|
|
1158
|
+
currentTime.period
|
|
1159
|
+
);
|
|
1160
|
+
input.value = val;
|
|
1161
|
+
picker.dataset.value = val;
|
|
1162
|
+
input.dispatchEvent(new Event("change", { bubbles: true }));
|
|
1163
|
+
};
|
|
1164
|
+
const buildPanel = () => {
|
|
1165
|
+
content.innerHTML = "";
|
|
1166
|
+
content.appendChild(renderColumn("hour", use12Hours ? 13 : 24));
|
|
1167
|
+
content.appendChild(renderColumn("minute", 60));
|
|
1168
|
+
if (showSecond) content.appendChild(renderColumn("second", 60));
|
|
1169
|
+
if (use12Hours) content.appendChild(renderPeriodColumn());
|
|
1170
|
+
};
|
|
1171
|
+
const open = () => {
|
|
1172
|
+
if (disabled) return;
|
|
1173
|
+
isOpen = true;
|
|
1174
|
+
picker.classList.add("ina-time-picker--open");
|
|
1175
|
+
panel.style.display = "block";
|
|
1176
|
+
currentTime = parseTime(input.value);
|
|
1177
|
+
buildPanel();
|
|
1178
|
+
document.dispatchEvent(
|
|
1179
|
+
new CustomEvent("closeTimePicker", { detail: { exclude: picker } })
|
|
1180
|
+
);
|
|
1181
|
+
};
|
|
1182
|
+
const close = () => {
|
|
1183
|
+
isOpen = false;
|
|
1184
|
+
picker.classList.remove("ina-time-picker--open");
|
|
1185
|
+
panel.style.display = "none";
|
|
1186
|
+
};
|
|
1187
|
+
const toggle = (e) => {
|
|
1188
|
+
e.stopPropagation();
|
|
1189
|
+
if (isOpen) close();
|
|
1190
|
+
else open();
|
|
1191
|
+
};
|
|
1192
|
+
wrapper.addEventListener("click", toggle);
|
|
1193
|
+
input.addEventListener("click", (e) => {
|
|
1194
|
+
});
|
|
1195
|
+
document.addEventListener("click", (e) => {
|
|
1196
|
+
if (!picker.contains(e.target)) close();
|
|
1197
|
+
});
|
|
1198
|
+
document.addEventListener("closeTimePicker", (e) => {
|
|
1199
|
+
if (e.detail && e.detail.exclude !== picker) close();
|
|
1200
|
+
});
|
|
1201
|
+
const clearBtn = picker.querySelector(".ina-time-picker__clear-button");
|
|
1202
|
+
if (clearBtn && allowClear) {
|
|
1203
|
+
clearBtn.addEventListener("click", (e) => {
|
|
1204
|
+
e.stopPropagation();
|
|
1205
|
+
input.value = "";
|
|
1206
|
+
currentTime = { hours: 0, minutes: 0, seconds: 0, period: "AM" };
|
|
1207
|
+
picker.dataset.value = "";
|
|
1208
|
+
input.dispatchEvent(new Event("change", { bubbles: true }));
|
|
1209
|
+
});
|
|
1210
|
+
}
|
|
1211
|
+
});
|
|
1212
|
+
}
|
|
1213
|
+
|
|
889
1214
|
// src/js/index.js
|
|
890
1215
|
var PREFIX = "ina-ss";
|
|
891
1216
|
|
|
@@ -1363,6 +1688,7 @@ var InaUI = (() => {
|
|
|
1363
1688
|
initModal();
|
|
1364
1689
|
initRangeDatepicker();
|
|
1365
1690
|
initTab();
|
|
1691
|
+
initTimepicker();
|
|
1366
1692
|
initToggle();
|
|
1367
1693
|
});
|
|
1368
1694
|
}
|