@idds/js 1.0.36 → 1.0.38
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 +513 -238
- package/dist/index.js +411 -333
- 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,10 +121,19 @@ var InaUI = (() => {
|
|
|
120
121
|
// src/js/components/stateful/datepicker.js
|
|
121
122
|
function initDatepicker() {
|
|
122
123
|
document.querySelectorAll(".ina-date-picker").forEach((datepicker) => {
|
|
124
|
+
const trigger = datepicker.querySelector(".ina-date-picker__trigger");
|
|
125
|
+
const triggerText = trigger.querySelector(".ina-date-picker__trigger-text");
|
|
126
|
+
const panel = datepicker.querySelector(".ina-date-picker__panel");
|
|
127
|
+
let panelContent = panel.querySelector(".ina-date-picker__panel-content");
|
|
128
|
+
if (!panelContent) {
|
|
129
|
+
panelContent = document.createElement("div");
|
|
130
|
+
panelContent.className = "ina-date-picker__panel-content";
|
|
131
|
+
panel.appendChild(panelContent);
|
|
132
|
+
}
|
|
123
133
|
let currentDate = /* @__PURE__ */ new Date();
|
|
124
|
-
let selectedDateTarget = null;
|
|
125
134
|
let selectedDate = null;
|
|
126
|
-
|
|
135
|
+
let isOpen = false;
|
|
136
|
+
const MONTHS_ID = [
|
|
127
137
|
"Januari",
|
|
128
138
|
"Februari",
|
|
129
139
|
"Maret",
|
|
@@ -137,267 +147,325 @@ var InaUI = (() => {
|
|
|
137
147
|
"November",
|
|
138
148
|
"Desember"
|
|
139
149
|
];
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
"
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
"
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
"
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
"
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
)
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
)
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
)
|
|
171
|
-
|
|
172
|
-
"
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
const
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
150
|
+
const MONTHS_SHORT_ID = [
|
|
151
|
+
"Jan",
|
|
152
|
+
"Feb",
|
|
153
|
+
"Mar",
|
|
154
|
+
"Apr",
|
|
155
|
+
"Mei",
|
|
156
|
+
"Jun",
|
|
157
|
+
"Jul",
|
|
158
|
+
"Agu",
|
|
159
|
+
"Sep",
|
|
160
|
+
"Okt",
|
|
161
|
+
"Nov",
|
|
162
|
+
"Des"
|
|
163
|
+
];
|
|
164
|
+
const DAYS_SHORT = ["Min", "Sen", "Sel", "Rab", "Kam", "Jum", "Sab"];
|
|
165
|
+
function formatDate(date) {
|
|
166
|
+
const day = date.getDate().toString().padStart(2, "0");
|
|
167
|
+
const monthIndex = date.getMonth();
|
|
168
|
+
const year = date.getFullYear();
|
|
169
|
+
return `${day} ${MONTHS_SHORT_ID[monthIndex]} ${year}`;
|
|
170
|
+
}
|
|
171
|
+
function createIcon(name, size = 16) {
|
|
172
|
+
if (name === "chevron-left") {
|
|
173
|
+
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" class="icon icon-tabler icons-tabler-outline icon-tabler-chevron-left"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M15 6l-6 6l6 6" /></svg>`;
|
|
174
|
+
}
|
|
175
|
+
if (name === "chevron-right") {
|
|
176
|
+
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" class="icon icon-tabler icons-tabler-outline icon-tabler-chevron-right"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M9 6l6 6l-6 6" /></svg>`;
|
|
177
|
+
}
|
|
178
|
+
return "";
|
|
179
|
+
}
|
|
180
|
+
function createMonthPicker(initialMonth, onChange) {
|
|
181
|
+
const container = document.createElement("div");
|
|
182
|
+
container.className = "ina-month-picker";
|
|
183
|
+
let currentMonthIdx = initialMonth;
|
|
184
|
+
let isPickerOpen = false;
|
|
185
|
+
const pickerTrigger = document.createElement("button");
|
|
186
|
+
pickerTrigger.type = "button";
|
|
187
|
+
pickerTrigger.className = "ina-month-picker__trigger ina-month-picker__trigger--size-sm";
|
|
188
|
+
const updateTriggerText = () => {
|
|
189
|
+
pickerTrigger.innerHTML = `
|
|
190
|
+
<span class="ina-month-picker__trigger-text">${MONTHS_SHORT_ID[currentMonthIdx]}</span>
|
|
191
|
+
`;
|
|
192
|
+
};
|
|
193
|
+
updateTriggerText();
|
|
194
|
+
pickerTrigger.addEventListener("click", (e) => {
|
|
195
|
+
e.stopPropagation();
|
|
196
|
+
togglePicker(!isPickerOpen);
|
|
197
|
+
});
|
|
198
|
+
const pickerPanel = document.createElement("div");
|
|
199
|
+
pickerPanel.className = "ina-month-picker__panel";
|
|
200
|
+
const grid = document.createElement("div");
|
|
201
|
+
grid.className = "ina-month-picker__grid";
|
|
202
|
+
MONTHS_SHORT_ID.forEach((m, idx) => {
|
|
203
|
+
const btn = document.createElement("button");
|
|
204
|
+
btn.type = "button";
|
|
205
|
+
btn.className = "ina-month-picker__month-option";
|
|
206
|
+
if (idx === currentMonthIdx)
|
|
207
|
+
btn.classList.add("ina-month-picker__month-option--selected");
|
|
208
|
+
btn.textContent = m;
|
|
209
|
+
btn.addEventListener("click", (e) => {
|
|
210
|
+
e.stopPropagation();
|
|
211
|
+
currentMonthIdx = idx;
|
|
212
|
+
updateTriggerText();
|
|
213
|
+
grid.querySelectorAll(".ina-month-picker__month-option").forEach((b, i) => {
|
|
214
|
+
if (i === idx)
|
|
215
|
+
b.classList.add("ina-month-picker__month-option--selected");
|
|
216
|
+
else
|
|
217
|
+
b.classList.remove("ina-month-picker__month-option--selected");
|
|
218
|
+
});
|
|
219
|
+
togglePicker(false);
|
|
220
|
+
onChange(idx);
|
|
221
|
+
});
|
|
222
|
+
grid.appendChild(btn);
|
|
223
|
+
});
|
|
224
|
+
pickerPanel.appendChild(grid);
|
|
225
|
+
container.appendChild(pickerTrigger);
|
|
226
|
+
container.appendChild(pickerPanel);
|
|
227
|
+
function togglePicker(show) {
|
|
228
|
+
isPickerOpen = show;
|
|
229
|
+
if (show) {
|
|
230
|
+
pickerPanel.classList.add("ina-month-picker__panel--open");
|
|
231
|
+
pickerTrigger.setAttribute("aria-expanded", "true");
|
|
232
|
+
} else {
|
|
233
|
+
pickerPanel.classList.remove("ina-month-picker__panel--open");
|
|
234
|
+
pickerTrigger.setAttribute("aria-expanded", "false");
|
|
199
235
|
}
|
|
200
|
-
datepickerYearContent.appendChild(yearEl);
|
|
201
236
|
}
|
|
237
|
+
document.addEventListener("click", (e) => {
|
|
238
|
+
if (!container.contains(e.target)) togglePicker(false);
|
|
239
|
+
});
|
|
240
|
+
return {
|
|
241
|
+
element: container,
|
|
242
|
+
setMonth: (m) => {
|
|
243
|
+
currentMonthIdx = m;
|
|
244
|
+
updateTriggerText();
|
|
245
|
+
grid.querySelectorAll(".ina-month-picker__month-option").forEach((b, i) => {
|
|
246
|
+
if (i === m)
|
|
247
|
+
b.classList.add("ina-month-picker__month-option--selected");
|
|
248
|
+
else
|
|
249
|
+
b.classList.remove("ina-month-picker__month-option--selected");
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
};
|
|
202
253
|
}
|
|
203
|
-
function
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
254
|
+
function createYearPicker(initialYear, onChange) {
|
|
255
|
+
const container = document.createElement("div");
|
|
256
|
+
container.className = "ina-year-picker";
|
|
257
|
+
let currentYearVal = initialYear;
|
|
258
|
+
let isPickerOpen = false;
|
|
259
|
+
let decadeStart = Math.floor(initialYear / 20) * 20;
|
|
260
|
+
const pickerTrigger = document.createElement("button");
|
|
261
|
+
pickerTrigger.type = "button";
|
|
262
|
+
pickerTrigger.className = "ina-year-picker__trigger ina-year-picker__trigger--size-sm";
|
|
263
|
+
const updateTriggerText = () => {
|
|
264
|
+
pickerTrigger.innerHTML = `
|
|
265
|
+
<span class="ina-year-picker__trigger-text">${currentYearVal}</span>
|
|
266
|
+
`;
|
|
267
|
+
};
|
|
268
|
+
updateTriggerText();
|
|
269
|
+
pickerTrigger.addEventListener("click", (e) => {
|
|
270
|
+
e.stopPropagation();
|
|
271
|
+
togglePicker(!isPickerOpen);
|
|
272
|
+
});
|
|
273
|
+
const pickerPanel = document.createElement("div");
|
|
274
|
+
pickerPanel.className = "ina-year-picker__panel";
|
|
275
|
+
const header = document.createElement("div");
|
|
276
|
+
header.className = "ina-year-picker__header";
|
|
277
|
+
const prevBtn = document.createElement("button");
|
|
278
|
+
prevBtn.type = "button";
|
|
279
|
+
prevBtn.className = "ina-year-picker__nav-button";
|
|
280
|
+
prevBtn.innerHTML = createIcon("chevron-left");
|
|
281
|
+
prevBtn.onclick = (e) => {
|
|
282
|
+
e.stopPropagation();
|
|
283
|
+
decadeStart -= 20;
|
|
284
|
+
renderGrid();
|
|
285
|
+
};
|
|
286
|
+
const nextBtn = document.createElement("button");
|
|
287
|
+
nextBtn.type = "button";
|
|
288
|
+
nextBtn.className = "ina-year-picker__nav-button";
|
|
289
|
+
nextBtn.innerHTML = createIcon("chevron-right");
|
|
290
|
+
nextBtn.onclick = (e) => {
|
|
291
|
+
e.stopPropagation();
|
|
292
|
+
decadeStart += 20;
|
|
293
|
+
renderGrid();
|
|
294
|
+
};
|
|
295
|
+
const rangeText = document.createElement("span");
|
|
296
|
+
rangeText.className = "ina-year-picker__decade-range";
|
|
297
|
+
header.append(prevBtn, rangeText, nextBtn);
|
|
298
|
+
const grid = document.createElement("div");
|
|
299
|
+
grid.className = "ina-year-picker__grid";
|
|
300
|
+
function renderGrid() {
|
|
301
|
+
grid.innerHTML = "";
|
|
302
|
+
rangeText.textContent = `${decadeStart} - ${decadeStart + 19}`;
|
|
303
|
+
for (let y = decadeStart; y < decadeStart + 20; y++) {
|
|
304
|
+
const btn = document.createElement("button");
|
|
305
|
+
btn.type = "button";
|
|
306
|
+
btn.className = "ina-year-picker__year-option";
|
|
307
|
+
if (y === currentYearVal)
|
|
308
|
+
btn.classList.add("ina-year-picker__year-option--selected");
|
|
309
|
+
btn.textContent = y;
|
|
310
|
+
btn.addEventListener("click", (e) => {
|
|
311
|
+
e.stopPropagation();
|
|
312
|
+
currentYearVal = y;
|
|
313
|
+
updateTriggerText();
|
|
314
|
+
togglePicker(false);
|
|
315
|
+
onChange(y);
|
|
316
|
+
});
|
|
317
|
+
grid.appendChild(btn);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
pickerPanel.append(header, grid);
|
|
321
|
+
container.append(pickerTrigger, pickerPanel);
|
|
322
|
+
function togglePicker(show) {
|
|
323
|
+
isPickerOpen = show;
|
|
324
|
+
if (show) {
|
|
325
|
+
decadeStart = Math.floor(currentYearVal / 20) * 20;
|
|
326
|
+
renderGrid();
|
|
327
|
+
pickerPanel.classList.add("ina-year-picker__panel--open");
|
|
328
|
+
pickerTrigger.setAttribute("aria-expanded", "true");
|
|
329
|
+
} else {
|
|
330
|
+
pickerPanel.classList.remove("ina-year-picker__panel--open");
|
|
331
|
+
pickerTrigger.setAttribute("aria-expanded", "false");
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
document.addEventListener("click", (e) => {
|
|
335
|
+
if (!container.contains(e.target)) togglePicker(false);
|
|
336
|
+
});
|
|
337
|
+
return {
|
|
338
|
+
element: container,
|
|
339
|
+
setYear: (y) => {
|
|
340
|
+
currentYearVal = y;
|
|
341
|
+
updateTriggerText();
|
|
342
|
+
}
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
function renderCalendar() {
|
|
346
|
+
panelContent.innerHTML = "";
|
|
347
|
+
const year = currentDate.getFullYear();
|
|
348
|
+
const month = currentDate.getMonth();
|
|
349
|
+
const calendarContainer = document.createElement("div");
|
|
350
|
+
calendarContainer.className = "ina-date-picker__calendar-container";
|
|
351
|
+
const header = document.createElement("div");
|
|
352
|
+
header.className = "ina-date-picker__calendar-header";
|
|
353
|
+
const prevBtn = document.createElement("button");
|
|
354
|
+
prevBtn.className = "ina-date-picker__nav-button";
|
|
355
|
+
prevBtn.type = "button";
|
|
356
|
+
prevBtn.innerHTML = createIcon("chevron-left", 20);
|
|
357
|
+
prevBtn.addEventListener("click", (e) => {
|
|
358
|
+
e.stopPropagation();
|
|
359
|
+
currentDate.setMonth(month - 1);
|
|
360
|
+
renderCalendar();
|
|
361
|
+
});
|
|
362
|
+
const nextBtn = document.createElement("button");
|
|
363
|
+
nextBtn.className = "ina-date-picker__nav-button";
|
|
364
|
+
nextBtn.type = "button";
|
|
365
|
+
nextBtn.innerHTML = createIcon("chevron-right", 20);
|
|
366
|
+
nextBtn.addEventListener("click", (e) => {
|
|
367
|
+
e.stopPropagation();
|
|
368
|
+
currentDate.setMonth(month + 1);
|
|
369
|
+
renderCalendar();
|
|
370
|
+
});
|
|
371
|
+
const controls = document.createElement("div");
|
|
372
|
+
controls.className = "ina-date-picker__header-controls";
|
|
373
|
+
const monthContainer = document.createElement("div");
|
|
374
|
+
monthContainer.className = "ina-date-picker__dropdown-container";
|
|
375
|
+
const monthPicker = createMonthPicker(month, (newMonth) => {
|
|
376
|
+
currentDate.setMonth(newMonth);
|
|
377
|
+
renderCalendar();
|
|
378
|
+
});
|
|
379
|
+
monthContainer.appendChild(monthPicker.element);
|
|
380
|
+
const yearContainer = document.createElement("div");
|
|
381
|
+
yearContainer.className = "ina-date-picker__dropdown-container";
|
|
382
|
+
const yearPicker = createYearPicker(year, (newYear) => {
|
|
383
|
+
currentDate.setFullYear(newYear);
|
|
384
|
+
renderCalendar();
|
|
385
|
+
});
|
|
386
|
+
yearContainer.appendChild(yearPicker.element);
|
|
387
|
+
controls.append(monthContainer, yearContainer);
|
|
388
|
+
header.append(prevBtn, controls, nextBtn);
|
|
389
|
+
const grid = document.createElement("div");
|
|
390
|
+
grid.className = "ina-date-picker__calendar-grid";
|
|
391
|
+
DAYS_SHORT.forEach((day) => {
|
|
392
|
+
const dh = document.createElement("div");
|
|
393
|
+
dh.className = "ina-date-picker__day-header";
|
|
394
|
+
dh.textContent = day;
|
|
395
|
+
grid.appendChild(dh);
|
|
215
396
|
});
|
|
216
397
|
const firstDayOfMonth = new Date(year, month, 1).getDay();
|
|
217
398
|
const daysInMonth = new Date(year, month + 1, 0).getDate();
|
|
218
399
|
const daysInPrevMonth = new Date(year, month, 0).getDate();
|
|
219
|
-
for (let i =
|
|
220
|
-
const
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
400
|
+
for (let i = firstDayOfMonth - 1; i >= 0; i--) {
|
|
401
|
+
const dayBtn = document.createElement("button");
|
|
402
|
+
dayBtn.type = "button";
|
|
403
|
+
dayBtn.className = "ina-date-picker__day ina-date-picker__day--other-month ina-date-picker__day--disabled";
|
|
404
|
+
dayBtn.textContent = daysInPrevMonth - i;
|
|
405
|
+
grid.appendChild(dayBtn);
|
|
225
406
|
}
|
|
226
407
|
const today = /* @__PURE__ */ new Date();
|
|
227
408
|
for (let i = 1; i <= daysInMonth; i++) {
|
|
228
|
-
const
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
dayEl.appendChild(marker);
|
|
237
|
-
dayEl.classList.add("today");
|
|
409
|
+
const dayBtn = document.createElement("button");
|
|
410
|
+
dayBtn.type = "button";
|
|
411
|
+
dayBtn.className = "ina-date-picker__day";
|
|
412
|
+
dayBtn.textContent = i;
|
|
413
|
+
let isSelected = false;
|
|
414
|
+
if (selectedDate && selectedDate.getDate() === i && selectedDate.getMonth() === month && selectedDate.getFullYear() === year) {
|
|
415
|
+
dayBtn.classList.add("ina-date-picker__day--selected");
|
|
416
|
+
isSelected = true;
|
|
238
417
|
}
|
|
239
|
-
if (
|
|
240
|
-
|
|
418
|
+
if (today.getDate() === i && today.getMonth() === month && today.getFullYear() === year) {
|
|
419
|
+
dayBtn.classList.add("ina-date-picker__day--today");
|
|
241
420
|
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
const totalCells = 42;
|
|
245
|
-
const cellsRendered = firstDayOfMonth + daysInMonth;
|
|
246
|
-
const remainingCells = totalCells - cellsRendered;
|
|
247
|
-
for (let i = 1; i <= remainingCells; i++) {
|
|
248
|
-
const dayEl = document.createElement("button");
|
|
249
|
-
dayEl.className = "ina-date-picker__calendar-day outside-month";
|
|
250
|
-
dayEl.textContent = i;
|
|
251
|
-
dayEl.disabled = true;
|
|
252
|
-
datepickerContent.appendChild(dayEl);
|
|
253
|
-
}
|
|
254
|
-
datepickerMonthPopover.innerHTML = "";
|
|
255
|
-
MONTHS.forEach((monthName, index) => {
|
|
256
|
-
const monthEl = document.createElement("button");
|
|
257
|
-
monthEl.className = "ina-date-picker__month-item";
|
|
258
|
-
monthEl.textContent = monthName.substring(0, 3);
|
|
259
|
-
monthEl.dataset.month = index;
|
|
260
|
-
if (index === month) {
|
|
261
|
-
monthEl.classList.add("selected");
|
|
421
|
+
if (!isSelected) {
|
|
422
|
+
dayBtn.classList.add("ina-date-picker__day--hover");
|
|
262
423
|
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
datepickerYearContent.appendChild(yearEl);
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
function togglePopover() {
|
|
281
|
-
if (datepickerPopover.style.display === "none" || datepickerPopover.style.display === "") {
|
|
282
|
-
datepickerPopover.style.display = "block";
|
|
283
|
-
renderCalendar(currentDate.getFullYear(), currentDate.getMonth());
|
|
284
|
-
} else {
|
|
285
|
-
datepickerPopover.style.display = "none";
|
|
424
|
+
dayBtn.addEventListener("click", (e) => {
|
|
425
|
+
e.stopPropagation();
|
|
426
|
+
selectedDate = new Date(year, month, i);
|
|
427
|
+
triggerText.textContent = formatDate(selectedDate);
|
|
428
|
+
triggerText.classList.add("ina-date-picker__trigger-text--value");
|
|
429
|
+
triggerText.classList.remove(
|
|
430
|
+
"ina-date-picker__trigger-text--placeholder"
|
|
431
|
+
);
|
|
432
|
+
datepicker.dispatchEvent(
|
|
433
|
+
new CustomEvent("date:changed", { detail: { selectedDate } })
|
|
434
|
+
);
|
|
435
|
+
toggle(false);
|
|
436
|
+
});
|
|
437
|
+
grid.appendChild(dayBtn);
|
|
286
438
|
}
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
439
|
+
const currentCells = grid.children.length - 7;
|
|
440
|
+
const remaining = 42 - currentCells;
|
|
441
|
+
for (let i = 1; i <= remaining; i++) {
|
|
442
|
+
const dayBtn = document.createElement("button");
|
|
443
|
+
dayBtn.type = "button";
|
|
444
|
+
dayBtn.className = "ina-date-picker__day ina-date-picker__day--other-month ina-date-picker__day--disabled";
|
|
445
|
+
dayBtn.textContent = i;
|
|
446
|
+
grid.appendChild(dayBtn);
|
|
293
447
|
}
|
|
448
|
+
calendarContainer.append(header, grid);
|
|
449
|
+
panelContent.appendChild(calendarContainer);
|
|
294
450
|
}
|
|
295
|
-
function
|
|
296
|
-
|
|
297
|
-
|
|
451
|
+
function toggle(show) {
|
|
452
|
+
isOpen = show;
|
|
453
|
+
if (show) {
|
|
454
|
+
panel.classList.add("ina-date-picker__panel--open");
|
|
455
|
+
renderCalendar();
|
|
298
456
|
} else {
|
|
299
|
-
|
|
457
|
+
panel.classList.remove("ina-date-picker__panel--open");
|
|
300
458
|
}
|
|
301
459
|
}
|
|
302
|
-
|
|
303
|
-
e.stopPropagation();
|
|
304
|
-
togglePopover();
|
|
305
|
-
});
|
|
306
|
-
prevMonthButton.addEventListener("click", () => {
|
|
307
|
-
currentDate.setMonth(currentDate.getMonth() - 1);
|
|
308
|
-
renderCalendar(currentDate.getFullYear(), currentDate.getMonth());
|
|
309
|
-
});
|
|
310
|
-
nextMonthButton.addEventListener("click", () => {
|
|
311
|
-
currentDate.setMonth(currentDate.getMonth() + 1);
|
|
312
|
-
renderCalendar(currentDate.getFullYear(), currentDate.getMonth());
|
|
313
|
-
});
|
|
314
|
-
datepickerMonthTrigger.addEventListener("click", (e) => {
|
|
460
|
+
trigger.addEventListener("click", (e) => {
|
|
315
461
|
e.stopPropagation();
|
|
316
|
-
|
|
317
|
-
});
|
|
318
|
-
datepickerYearTrigger.addEventListener("click", (e) => {
|
|
319
|
-
e.stopPropagation();
|
|
320
|
-
toggleYearPopover();
|
|
321
|
-
});
|
|
322
|
-
document.addEventListener("click", (e) => {
|
|
323
|
-
if (!datepickerPopover.contains(e.target) && e.target !== datepickerTrigger && !datepickerTrigger.contains(e.target)) {
|
|
324
|
-
datepickerPopover.style.display = "none";
|
|
325
|
-
}
|
|
326
|
-
});
|
|
327
|
-
document.addEventListener("click", (e) => {
|
|
328
|
-
if (!datepickerMonthPopover.contains(e.target) && e.target !== datepickerMonthTrigger && !datepickerMonthTrigger.contains(e.target)) {
|
|
329
|
-
datepickerMonthPopover.style.display = "none";
|
|
330
|
-
}
|
|
462
|
+
toggle(!isOpen);
|
|
331
463
|
});
|
|
332
464
|
document.addEventListener("click", (e) => {
|
|
333
|
-
if (!
|
|
334
|
-
datepickerYearPopover.style.display = "none";
|
|
335
|
-
}
|
|
336
|
-
});
|
|
337
|
-
datepickerMonthPopover.addEventListener("click", (e) => {
|
|
338
|
-
e.stopPropagation();
|
|
339
|
-
const target = e.target;
|
|
340
|
-
if (target.classList.contains("ina-date-picker__month-item")) {
|
|
341
|
-
const monthIndex = parseInt(target.dataset.month);
|
|
342
|
-
currentDate.setMonth(monthIndex);
|
|
343
|
-
renderCalendar(currentDate.getFullYear(), currentDate.getMonth());
|
|
344
|
-
datepickerMonthPopover.style.display = "none";
|
|
345
|
-
}
|
|
346
|
-
});
|
|
347
|
-
datepickerYearPopover.addEventListener("click", (e) => {
|
|
348
|
-
e.stopPropagation();
|
|
349
|
-
const target = e.target;
|
|
350
|
-
if (target.classList.contains("ina-date-picker__year-nav-prev")) {
|
|
351
|
-
const currentYearRange = datepickerYearCurrent.textContent.split(" - ").map((y) => parseInt(y));
|
|
352
|
-
const newStartYear = currentYearRange[0] - 20;
|
|
353
|
-
const newEndYear = currentYearRange[1] - 20;
|
|
354
|
-
renderYear(newStartYear, newEndYear);
|
|
355
|
-
} else if (target.classList.contains("ina-date-picker__year-nav-next")) {
|
|
356
|
-
const currentYearRange = datepickerYearCurrent.textContent.split(" - ").map((y) => parseInt(y));
|
|
357
|
-
const newStartYear = currentYearRange[0] + 20;
|
|
358
|
-
const newEndYear = currentYearRange[1] + 20;
|
|
359
|
-
renderYear(newStartYear, newEndYear);
|
|
360
|
-
}
|
|
361
|
-
});
|
|
362
|
-
datepickerYearContent.addEventListener("click", (e) => {
|
|
363
|
-
e.stopPropagation();
|
|
364
|
-
const target = e.target;
|
|
365
|
-
if (target.classList.contains("ina-date-picker__year-item")) {
|
|
366
|
-
const yearValue = parseInt(target.dataset.year);
|
|
367
|
-
currentDate.setFullYear(yearValue);
|
|
368
|
-
renderCalendar(currentDate.getFullYear(), currentDate.getMonth());
|
|
369
|
-
datepickerYearPopover.style.display = "none";
|
|
370
|
-
}
|
|
371
|
-
});
|
|
372
|
-
datepickerContent.addEventListener("click", (e) => {
|
|
373
|
-
const target = e.target;
|
|
374
|
-
if (target.classList.contains("ina-date-picker__calendar-day") && !target.classList.contains("outside-month")) {
|
|
375
|
-
if (target.classList.contains("selected")) {
|
|
376
|
-
target.classList.remove("selected");
|
|
377
|
-
selectedDateTarget = null;
|
|
378
|
-
} else {
|
|
379
|
-
const selectedDateEl = datepickerContent.querySelector(
|
|
380
|
-
".ina-date-picker__calendar-day.selected"
|
|
381
|
-
);
|
|
382
|
-
selectedDateEl?.classList.remove("selected");
|
|
383
|
-
target.classList.add("selected");
|
|
384
|
-
selectedDateTarget = target;
|
|
385
|
-
}
|
|
386
|
-
}
|
|
465
|
+
if (!datepicker.contains(e.target)) toggle(false);
|
|
387
466
|
});
|
|
388
|
-
datepickerSubmitButton.addEventListener("click", () => {
|
|
389
|
-
selectedDate = selectedDateTarget ? new Date(selectedDateTarget.dataset.date) : null;
|
|
390
|
-
currentDate = selectedDate ? new Date(selectedDate) : /* @__PURE__ */ new Date();
|
|
391
|
-
datepicker.dispatchEvent(
|
|
392
|
-
new CustomEvent("date:changed", { detail: { selectedDate } })
|
|
393
|
-
);
|
|
394
|
-
datepickerPopover.style.display = "none";
|
|
395
|
-
});
|
|
396
|
-
renderCalendar(currentDate.getFullYear(), currentDate.getMonth());
|
|
397
467
|
});
|
|
398
468
|
}
|
|
399
|
-
document.addEventListener("DOMContentLoaded", () => {
|
|
400
|
-
});
|
|
401
469
|
|
|
402
470
|
// src/js/components/stateless/modal.js
|
|
403
471
|
function initModal(rootSelector = `.${PREFIX}-modal`) {
|
|
@@ -819,6 +887,212 @@ var InaUI = (() => {
|
|
|
819
887
|
});
|
|
820
888
|
}
|
|
821
889
|
|
|
890
|
+
// src/js/components/stateful/timepicker.js
|
|
891
|
+
function initTimepicker() {
|
|
892
|
+
document.querySelectorAll(".ina-time-picker").forEach((picker) => {
|
|
893
|
+
if (picker.dataset.initialized === "true") return;
|
|
894
|
+
picker.dataset.initialized = "true";
|
|
895
|
+
const input = picker.querySelector(".ina-time-picker__input");
|
|
896
|
+
const wrapper = picker.querySelector(".ina-time-picker__wrapper");
|
|
897
|
+
if (!input || !wrapper) return;
|
|
898
|
+
const format = picker.dataset.format || "HH:mm";
|
|
899
|
+
const use12Hours = picker.dataset.use12Hours === "true";
|
|
900
|
+
const showSecond = picker.dataset.showSecond === "true";
|
|
901
|
+
const disabled = picker.classList.contains("ina-time-picker--disabled");
|
|
902
|
+
const allowClear = picker.dataset.allowClear !== "false";
|
|
903
|
+
let isOpen = false;
|
|
904
|
+
let internalValue = input.value || "";
|
|
905
|
+
let panel = picker.querySelector(".ina-time-picker__panel");
|
|
906
|
+
if (!panel) {
|
|
907
|
+
panel = document.createElement("div");
|
|
908
|
+
panel.className = "ina-time-picker__panel";
|
|
909
|
+
panel.style.display = "none";
|
|
910
|
+
picker.appendChild(panel);
|
|
911
|
+
}
|
|
912
|
+
let content = panel.querySelector(".ina-time-picker__content");
|
|
913
|
+
if (!content) {
|
|
914
|
+
content = document.createElement("div");
|
|
915
|
+
content.className = "ina-time-picker__content";
|
|
916
|
+
panel.appendChild(content);
|
|
917
|
+
} else {
|
|
918
|
+
content.innerHTML = "";
|
|
919
|
+
}
|
|
920
|
+
let actions = panel.querySelector(".ina-time-picker__actions");
|
|
921
|
+
if (!actions) {
|
|
922
|
+
actions = document.createElement("div");
|
|
923
|
+
actions.className = "ina-time-picker__actions";
|
|
924
|
+
const confirmBtn = document.createElement("button");
|
|
925
|
+
confirmBtn.type = "button";
|
|
926
|
+
confirmBtn.className = "ina-time-picker__confirm-button";
|
|
927
|
+
confirmBtn.textContent = "Pilih";
|
|
928
|
+
confirmBtn.onclick = (e) => {
|
|
929
|
+
e.stopPropagation();
|
|
930
|
+
close();
|
|
931
|
+
};
|
|
932
|
+
actions.appendChild(confirmBtn);
|
|
933
|
+
panel.appendChild(actions);
|
|
934
|
+
}
|
|
935
|
+
const parseTime = (timeStr) => {
|
|
936
|
+
if (!timeStr) return { hours: 0, minutes: 0, seconds: 0, period: "AM" };
|
|
937
|
+
let hours = 0, minutes = 0, seconds = 0, period = "AM";
|
|
938
|
+
try {
|
|
939
|
+
if (use12Hours) {
|
|
940
|
+
const [time, p] = timeStr.split(" ");
|
|
941
|
+
const [h, m, s] = time.split(":");
|
|
942
|
+
hours = parseInt(h || "0", 10);
|
|
943
|
+
minutes = parseInt(m || "0", 10);
|
|
944
|
+
seconds = parseInt(s || "0", 10);
|
|
945
|
+
period = p || "AM";
|
|
946
|
+
} else {
|
|
947
|
+
const [h, m, s] = timeStr.split(":");
|
|
948
|
+
hours = parseInt(h || "0", 10);
|
|
949
|
+
minutes = parseInt(m || "0", 10);
|
|
950
|
+
seconds = parseInt(s || "0", 10);
|
|
951
|
+
}
|
|
952
|
+
} catch (e) {
|
|
953
|
+
console.warn("Invalid time format", timeStr);
|
|
954
|
+
}
|
|
955
|
+
return { hours, minutes, seconds, period };
|
|
956
|
+
};
|
|
957
|
+
const formatTime = (h, m, s, p) => {
|
|
958
|
+
const pad = (n) => n.toString().padStart(2, "0");
|
|
959
|
+
if (use12Hours) {
|
|
960
|
+
let displayHours = h;
|
|
961
|
+
if (displayHours === 0) displayHours = 12;
|
|
962
|
+
const main = `${pad(displayHours)}:${pad(m)}`;
|
|
963
|
+
const sec = showSecond ? `:${pad(s)}` : "";
|
|
964
|
+
return `${main}${sec} ${p}`;
|
|
965
|
+
} else {
|
|
966
|
+
const main = `${pad(h)}:${pad(m)}`;
|
|
967
|
+
const sec = showSecond ? `:${pad(s)}` : "";
|
|
968
|
+
return `${main}${sec}`;
|
|
969
|
+
}
|
|
970
|
+
};
|
|
971
|
+
let currentTime = parseTime(internalValue);
|
|
972
|
+
const renderColumn = (type, max) => {
|
|
973
|
+
const column = document.createElement("div");
|
|
974
|
+
column.className = `ina-time-picker__column ina-time-picker__column--${type}`;
|
|
975
|
+
const colContent = document.createElement("div");
|
|
976
|
+
colContent.className = "ina-time-picker__column-content";
|
|
977
|
+
column.appendChild(colContent);
|
|
978
|
+
const start = type === "hour" && use12Hours ? 1 : 0;
|
|
979
|
+
const end = type === "hour" && use12Hours ? 12 : max - 1;
|
|
980
|
+
for (let i = start; i <= end; i++) {
|
|
981
|
+
const option = document.createElement("div");
|
|
982
|
+
option.className = "ina-time-picker__option";
|
|
983
|
+
option.textContent = i.toString().padStart(2, "0");
|
|
984
|
+
option.dataset.value = i;
|
|
985
|
+
let isSelected = false;
|
|
986
|
+
if (type === "hour") {
|
|
987
|
+
isSelected = currentTime.hours === i || use12Hours && currentTime.hours === 0 && i === 12;
|
|
988
|
+
} else if (type === "minute") isSelected = currentTime.minutes === i;
|
|
989
|
+
else if (type === "second") isSelected = currentTime.seconds === i;
|
|
990
|
+
if (isSelected)
|
|
991
|
+
option.classList.add("ina-time-picker__option--selected");
|
|
992
|
+
option.addEventListener("click", (e) => {
|
|
993
|
+
e.stopPropagation();
|
|
994
|
+
const val = parseInt(option.dataset.value, 10);
|
|
995
|
+
if (type === "hour")
|
|
996
|
+
currentTime.hours = use12Hours && val === 12 ? 0 : val;
|
|
997
|
+
if (type === "hour") currentTime.hours = val;
|
|
998
|
+
if (type === "minute") currentTime.minutes = val;
|
|
999
|
+
if (type === "second") currentTime.seconds = val;
|
|
1000
|
+
updateInput();
|
|
1001
|
+
colContent.querySelectorAll(".ina-time-picker__option").forEach(
|
|
1002
|
+
(el) => el.classList.remove("ina-time-picker__option--selected")
|
|
1003
|
+
);
|
|
1004
|
+
option.classList.add("ina-time-picker__option--selected");
|
|
1005
|
+
});
|
|
1006
|
+
colContent.appendChild(option);
|
|
1007
|
+
}
|
|
1008
|
+
return column;
|
|
1009
|
+
};
|
|
1010
|
+
const renderPeriodColumn = () => {
|
|
1011
|
+
const column = document.createElement("div");
|
|
1012
|
+
column.className = `ina-time-picker__column ina-time-picker__column--period`;
|
|
1013
|
+
const colContent = document.createElement("div");
|
|
1014
|
+
colContent.className = "ina-time-picker__column-content";
|
|
1015
|
+
column.appendChild(colContent);
|
|
1016
|
+
["AM", "PM"].forEach((p) => {
|
|
1017
|
+
const option = document.createElement("div");
|
|
1018
|
+
option.className = "ina-time-picker__option";
|
|
1019
|
+
option.textContent = p;
|
|
1020
|
+
if (currentTime.period === p)
|
|
1021
|
+
option.classList.add("ina-time-picker__option--selected");
|
|
1022
|
+
option.addEventListener("click", (e) => {
|
|
1023
|
+
e.stopPropagation();
|
|
1024
|
+
currentTime.period = p;
|
|
1025
|
+
updateInput();
|
|
1026
|
+
colContent.querySelectorAll(".ina-time-picker__option").forEach(
|
|
1027
|
+
(el) => el.classList.remove("ina-time-picker__option--selected")
|
|
1028
|
+
);
|
|
1029
|
+
option.classList.add("ina-time-picker__option--selected");
|
|
1030
|
+
});
|
|
1031
|
+
colContent.appendChild(option);
|
|
1032
|
+
});
|
|
1033
|
+
return column;
|
|
1034
|
+
};
|
|
1035
|
+
const updateInput = () => {
|
|
1036
|
+
const val = formatTime(
|
|
1037
|
+
currentTime.hours,
|
|
1038
|
+
currentTime.minutes,
|
|
1039
|
+
currentTime.seconds,
|
|
1040
|
+
currentTime.period
|
|
1041
|
+
);
|
|
1042
|
+
input.value = val;
|
|
1043
|
+
picker.dataset.value = val;
|
|
1044
|
+
input.dispatchEvent(new Event("change", { bubbles: true }));
|
|
1045
|
+
};
|
|
1046
|
+
const buildPanel = () => {
|
|
1047
|
+
content.innerHTML = "";
|
|
1048
|
+
content.appendChild(renderColumn("hour", use12Hours ? 13 : 24));
|
|
1049
|
+
content.appendChild(renderColumn("minute", 60));
|
|
1050
|
+
if (showSecond) content.appendChild(renderColumn("second", 60));
|
|
1051
|
+
if (use12Hours) content.appendChild(renderPeriodColumn());
|
|
1052
|
+
};
|
|
1053
|
+
const open = () => {
|
|
1054
|
+
if (disabled) return;
|
|
1055
|
+
isOpen = true;
|
|
1056
|
+
picker.classList.add("ina-time-picker--open");
|
|
1057
|
+
panel.style.display = "block";
|
|
1058
|
+
currentTime = parseTime(input.value);
|
|
1059
|
+
buildPanel();
|
|
1060
|
+
document.dispatchEvent(
|
|
1061
|
+
new CustomEvent("closeTimePicker", { detail: { exclude: picker } })
|
|
1062
|
+
);
|
|
1063
|
+
};
|
|
1064
|
+
const close = () => {
|
|
1065
|
+
isOpen = false;
|
|
1066
|
+
picker.classList.remove("ina-time-picker--open");
|
|
1067
|
+
panel.style.display = "none";
|
|
1068
|
+
};
|
|
1069
|
+
const toggle = (e) => {
|
|
1070
|
+
e.stopPropagation();
|
|
1071
|
+
if (isOpen) close();
|
|
1072
|
+
else open();
|
|
1073
|
+
};
|
|
1074
|
+
wrapper.addEventListener("click", toggle);
|
|
1075
|
+
input.addEventListener("click", (e) => {
|
|
1076
|
+
});
|
|
1077
|
+
document.addEventListener("click", (e) => {
|
|
1078
|
+
if (!picker.contains(e.target)) close();
|
|
1079
|
+
});
|
|
1080
|
+
document.addEventListener("closeTimePicker", (e) => {
|
|
1081
|
+
if (e.detail && e.detail.exclude !== picker) close();
|
|
1082
|
+
});
|
|
1083
|
+
const clearBtn = picker.querySelector(".ina-time-picker__clear-button");
|
|
1084
|
+
if (clearBtn && allowClear) {
|
|
1085
|
+
clearBtn.addEventListener("click", (e) => {
|
|
1086
|
+
e.stopPropagation();
|
|
1087
|
+
input.value = "";
|
|
1088
|
+
currentTime = { hours: 0, minutes: 0, seconds: 0, period: "AM" };
|
|
1089
|
+
picker.dataset.value = "";
|
|
1090
|
+
input.dispatchEvent(new Event("change", { bubbles: true }));
|
|
1091
|
+
});
|
|
1092
|
+
}
|
|
1093
|
+
});
|
|
1094
|
+
}
|
|
1095
|
+
|
|
822
1096
|
// src/js/index.js
|
|
823
1097
|
var PREFIX = "ina-ss";
|
|
824
1098
|
|
|
@@ -1296,6 +1570,7 @@ var InaUI = (() => {
|
|
|
1296
1570
|
initModal();
|
|
1297
1571
|
initRangeDatepicker();
|
|
1298
1572
|
initTab();
|
|
1573
|
+
initTimepicker();
|
|
1299
1574
|
initToggle();
|
|
1300
1575
|
});
|
|
1301
1576
|
}
|