@idds/js 1.0.36 → 1.0.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/index.iife.js +305 -238
  2. package/dist/index.js +363 -286
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -109,10 +109,19 @@ function initAccordion(rootSelector = `.${PREFIX}-accordion`) {
109
109
  // src/js/components/stateful/datepicker.js
110
110
  function initDatepicker() {
111
111
  document.querySelectorAll(".ina-date-picker").forEach((datepicker) => {
112
+ const trigger = datepicker.querySelector(".ina-date-picker__trigger");
113
+ const triggerText = trigger.querySelector(".ina-date-picker__trigger-text");
114
+ const panel = datepicker.querySelector(".ina-date-picker__panel");
115
+ let panelContent = panel.querySelector(".ina-date-picker__panel-content");
116
+ if (!panelContent) {
117
+ panelContent = document.createElement("div");
118
+ panelContent.className = "ina-date-picker__panel-content";
119
+ panel.appendChild(panelContent);
120
+ }
112
121
  let currentDate = /* @__PURE__ */ new Date();
113
- let selectedDateTarget = null;
114
122
  let selectedDate = null;
115
- const MONTHS = [
123
+ let isOpen = false;
124
+ const MONTHS_ID = [
116
125
  "Januari",
117
126
  "Februari",
118
127
  "Maret",
@@ -126,267 +135,325 @@ function initDatepicker() {
126
135
  "November",
127
136
  "Desember"
128
137
  ];
129
- const DAYS = ["Min", "Sen", "Sel", "Rab", "Kam", "Jum", "Sab"];
130
- const datepickerTrigger = datepicker.querySelector(
131
- ".ina-date-picker__trigger"
132
- );
133
- const datepickerPopover = datepicker.querySelector(
134
- ".ina-date-picker__popover"
135
- );
136
- const datepickerMonthTrigger = datepicker.querySelector(
137
- ".ina-date-picker__month-trigger"
138
- );
139
- const datepickerMonthPopover = datepicker.querySelector(
140
- ".ina-date-picker__month-popover"
141
- );
142
- const datepickerMonthItem = datepicker.querySelectorAll(
143
- ".ina-date-picker__month-item"
144
- );
145
- const datepickerYearTrigger = datepicker.querySelector(
146
- ".ina-date-picker__year-trigger"
147
- );
148
- const datepickerYearPopover = datepicker.querySelector(
149
- ".ina-date-picker__year-popover"
150
- );
151
- const datepickerYearPrevButton = datepicker.querySelector(
152
- ".ina-date-picker__year-nav-prev"
153
- );
154
- const datepickerYearCurrent = datepicker.querySelector(
155
- ".ina-date-picker__year-current"
156
- );
157
- const datepickerYearNextButton = datepicker.querySelector(
158
- ".ina-date-picker__year-nav-next"
159
- );
160
- const datepickerYearContent = datepicker.querySelector(
161
- ".ina-date-picker__year-content"
162
- );
163
- const datepickerYearItem = datepicker.querySelectorAll(
164
- ".ina-date-picker__year-item"
165
- );
166
- const datepickerContent = datepicker.querySelector(
167
- ".ina-date-picker__content"
168
- );
169
- const prevMonthButton = datepicker.querySelector(
170
- ".ina-date-picker__nav-prev"
171
- );
172
- const nextMonthButton = datepicker.querySelector(
173
- ".ina-date-picker__nav-next"
174
- );
175
- const datepickerSubmitButton = datepicker.querySelector(
176
- ".ina-date-picker__submit"
177
- );
178
- function renderYear(startYear, endYear) {
179
- datepickerYearContent.innerHTML = "";
180
- datepickerYearCurrent.textContent = `${startYear} - ${endYear}`;
181
- for (let y = startYear; y <= endYear; y++) {
182
- const yearEl = document.createElement("button");
183
- yearEl.className = "ina-date-picker__year-item";
184
- yearEl.textContent = y;
185
- yearEl.dataset.year = y;
186
- if (y === currentDate.getFullYear()) {
187
- yearEl.classList.add("selected");
138
+ const MONTHS_SHORT_ID = [
139
+ "Jan",
140
+ "Feb",
141
+ "Mar",
142
+ "Apr",
143
+ "Mei",
144
+ "Jun",
145
+ "Jul",
146
+ "Agu",
147
+ "Sep",
148
+ "Okt",
149
+ "Nov",
150
+ "Des"
151
+ ];
152
+ const DAYS_SHORT = ["Min", "Sen", "Sel", "Rab", "Kam", "Jum", "Sab"];
153
+ function formatDate(date) {
154
+ const day = date.getDate().toString().padStart(2, "0");
155
+ const monthIndex = date.getMonth();
156
+ const year = date.getFullYear();
157
+ return `${day} ${MONTHS_SHORT_ID[monthIndex]} ${year}`;
158
+ }
159
+ function createIcon(name, size = 16) {
160
+ if (name === "chevron-left") {
161
+ 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>`;
162
+ }
163
+ if (name === "chevron-right") {
164
+ 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>`;
165
+ }
166
+ return "";
167
+ }
168
+ function createMonthPicker(initialMonth, onChange) {
169
+ const container = document.createElement("div");
170
+ container.className = "ina-month-picker";
171
+ let currentMonthIdx = initialMonth;
172
+ let isPickerOpen = false;
173
+ const pickerTrigger = document.createElement("button");
174
+ pickerTrigger.type = "button";
175
+ pickerTrigger.className = "ina-month-picker__trigger ina-month-picker__trigger--size-sm";
176
+ const updateTriggerText = () => {
177
+ pickerTrigger.innerHTML = `
178
+ <span class="ina-month-picker__trigger-text">${MONTHS_SHORT_ID[currentMonthIdx]}</span>
179
+ `;
180
+ };
181
+ updateTriggerText();
182
+ pickerTrigger.addEventListener("click", (e) => {
183
+ e.stopPropagation();
184
+ togglePicker(!isPickerOpen);
185
+ });
186
+ const pickerPanel = document.createElement("div");
187
+ pickerPanel.className = "ina-month-picker__panel";
188
+ const grid = document.createElement("div");
189
+ grid.className = "ina-month-picker__grid";
190
+ MONTHS_SHORT_ID.forEach((m, idx) => {
191
+ const btn = document.createElement("button");
192
+ btn.type = "button";
193
+ btn.className = "ina-month-picker__month-option";
194
+ if (idx === currentMonthIdx)
195
+ btn.classList.add("ina-month-picker__month-option--selected");
196
+ btn.textContent = m;
197
+ btn.addEventListener("click", (e) => {
198
+ e.stopPropagation();
199
+ currentMonthIdx = idx;
200
+ updateTriggerText();
201
+ grid.querySelectorAll(".ina-month-picker__month-option").forEach((b, i) => {
202
+ if (i === idx)
203
+ b.classList.add("ina-month-picker__month-option--selected");
204
+ else
205
+ b.classList.remove("ina-month-picker__month-option--selected");
206
+ });
207
+ togglePicker(false);
208
+ onChange(idx);
209
+ });
210
+ grid.appendChild(btn);
211
+ });
212
+ pickerPanel.appendChild(grid);
213
+ container.appendChild(pickerTrigger);
214
+ container.appendChild(pickerPanel);
215
+ function togglePicker(show) {
216
+ isPickerOpen = show;
217
+ if (show) {
218
+ pickerPanel.classList.add("ina-month-picker__panel--open");
219
+ pickerTrigger.setAttribute("aria-expanded", "true");
220
+ } else {
221
+ pickerPanel.classList.remove("ina-month-picker__panel--open");
222
+ pickerTrigger.setAttribute("aria-expanded", "false");
188
223
  }
189
- datepickerYearContent.appendChild(yearEl);
190
224
  }
225
+ document.addEventListener("click", (e) => {
226
+ if (!container.contains(e.target)) togglePicker(false);
227
+ });
228
+ return {
229
+ element: container,
230
+ setMonth: (m) => {
231
+ currentMonthIdx = m;
232
+ updateTriggerText();
233
+ grid.querySelectorAll(".ina-month-picker__month-option").forEach((b, i) => {
234
+ if (i === m)
235
+ b.classList.add("ina-month-picker__month-option--selected");
236
+ else
237
+ b.classList.remove("ina-month-picker__month-option--selected");
238
+ });
239
+ }
240
+ };
191
241
  }
192
- function renderCalendar(year, month) {
193
- datepickerContent.innerHTML = "";
194
- datepickerMonthTrigger.textContent = MONTHS[month].substring(0, 3);
195
- datepickerYearTrigger.textContent = year;
196
- DAYS.forEach((day) => {
197
- const dayNameWrapper = document.createElement("div");
198
- dayNameWrapper.className = "ina-date-picker__dayname-wrapper";
199
- const dayNameEl = document.createElement("span");
200
- dayNameEl.className = "ina-date-picker__dayname";
201
- dayNameEl.textContent = day.substring(0, 3);
202
- dayNameWrapper.appendChild(dayNameEl);
203
- datepickerContent.appendChild(dayNameWrapper);
242
+ function createYearPicker(initialYear, onChange) {
243
+ const container = document.createElement("div");
244
+ container.className = "ina-year-picker";
245
+ let currentYearVal = initialYear;
246
+ let isPickerOpen = false;
247
+ let decadeStart = Math.floor(initialYear / 20) * 20;
248
+ const pickerTrigger = document.createElement("button");
249
+ pickerTrigger.type = "button";
250
+ pickerTrigger.className = "ina-year-picker__trigger ina-year-picker__trigger--size-sm";
251
+ const updateTriggerText = () => {
252
+ pickerTrigger.innerHTML = `
253
+ <span class="ina-year-picker__trigger-text">${currentYearVal}</span>
254
+ `;
255
+ };
256
+ updateTriggerText();
257
+ pickerTrigger.addEventListener("click", (e) => {
258
+ e.stopPropagation();
259
+ togglePicker(!isPickerOpen);
260
+ });
261
+ const pickerPanel = document.createElement("div");
262
+ pickerPanel.className = "ina-year-picker__panel";
263
+ const header = document.createElement("div");
264
+ header.className = "ina-year-picker__header";
265
+ const prevBtn = document.createElement("button");
266
+ prevBtn.type = "button";
267
+ prevBtn.className = "ina-year-picker__nav-button";
268
+ prevBtn.innerHTML = createIcon("chevron-left");
269
+ prevBtn.onclick = (e) => {
270
+ e.stopPropagation();
271
+ decadeStart -= 20;
272
+ renderGrid();
273
+ };
274
+ const nextBtn = document.createElement("button");
275
+ nextBtn.type = "button";
276
+ nextBtn.className = "ina-year-picker__nav-button";
277
+ nextBtn.innerHTML = createIcon("chevron-right");
278
+ nextBtn.onclick = (e) => {
279
+ e.stopPropagation();
280
+ decadeStart += 20;
281
+ renderGrid();
282
+ };
283
+ const rangeText = document.createElement("span");
284
+ rangeText.className = "ina-year-picker__decade-range";
285
+ header.append(prevBtn, rangeText, nextBtn);
286
+ const grid = document.createElement("div");
287
+ grid.className = "ina-year-picker__grid";
288
+ function renderGrid() {
289
+ grid.innerHTML = "";
290
+ rangeText.textContent = `${decadeStart} - ${decadeStart + 19}`;
291
+ for (let y = decadeStart; y < decadeStart + 20; y++) {
292
+ const btn = document.createElement("button");
293
+ btn.type = "button";
294
+ btn.className = "ina-year-picker__year-option";
295
+ if (y === currentYearVal)
296
+ btn.classList.add("ina-year-picker__year-option--selected");
297
+ btn.textContent = y;
298
+ btn.addEventListener("click", (e) => {
299
+ e.stopPropagation();
300
+ currentYearVal = y;
301
+ updateTriggerText();
302
+ togglePicker(false);
303
+ onChange(y);
304
+ });
305
+ grid.appendChild(btn);
306
+ }
307
+ }
308
+ pickerPanel.append(header, grid);
309
+ container.append(pickerTrigger, pickerPanel);
310
+ function togglePicker(show) {
311
+ isPickerOpen = show;
312
+ if (show) {
313
+ decadeStart = Math.floor(currentYearVal / 20) * 20;
314
+ renderGrid();
315
+ pickerPanel.classList.add("ina-year-picker__panel--open");
316
+ pickerTrigger.setAttribute("aria-expanded", "true");
317
+ } else {
318
+ pickerPanel.classList.remove("ina-year-picker__panel--open");
319
+ pickerTrigger.setAttribute("aria-expanded", "false");
320
+ }
321
+ }
322
+ document.addEventListener("click", (e) => {
323
+ if (!container.contains(e.target)) togglePicker(false);
324
+ });
325
+ return {
326
+ element: container,
327
+ setYear: (y) => {
328
+ currentYearVal = y;
329
+ updateTriggerText();
330
+ }
331
+ };
332
+ }
333
+ function renderCalendar() {
334
+ panelContent.innerHTML = "";
335
+ const year = currentDate.getFullYear();
336
+ const month = currentDate.getMonth();
337
+ const calendarContainer = document.createElement("div");
338
+ calendarContainer.className = "ina-date-picker__calendar-container";
339
+ const header = document.createElement("div");
340
+ header.className = "ina-date-picker__calendar-header";
341
+ const prevBtn = document.createElement("button");
342
+ prevBtn.className = "ina-date-picker__nav-button";
343
+ prevBtn.type = "button";
344
+ prevBtn.innerHTML = createIcon("chevron-left", 20);
345
+ prevBtn.addEventListener("click", (e) => {
346
+ e.stopPropagation();
347
+ currentDate.setMonth(month - 1);
348
+ renderCalendar();
349
+ });
350
+ const nextBtn = document.createElement("button");
351
+ nextBtn.className = "ina-date-picker__nav-button";
352
+ nextBtn.type = "button";
353
+ nextBtn.innerHTML = createIcon("chevron-right", 20);
354
+ nextBtn.addEventListener("click", (e) => {
355
+ e.stopPropagation();
356
+ currentDate.setMonth(month + 1);
357
+ renderCalendar();
358
+ });
359
+ const controls = document.createElement("div");
360
+ controls.className = "ina-date-picker__header-controls";
361
+ const monthContainer = document.createElement("div");
362
+ monthContainer.className = "ina-date-picker__dropdown-container";
363
+ const monthPicker = createMonthPicker(month, (newMonth) => {
364
+ currentDate.setMonth(newMonth);
365
+ renderCalendar();
366
+ });
367
+ monthContainer.appendChild(monthPicker.element);
368
+ const yearContainer = document.createElement("div");
369
+ yearContainer.className = "ina-date-picker__dropdown-container";
370
+ const yearPicker = createYearPicker(year, (newYear) => {
371
+ currentDate.setFullYear(newYear);
372
+ renderCalendar();
373
+ });
374
+ yearContainer.appendChild(yearPicker.element);
375
+ controls.append(monthContainer, yearContainer);
376
+ header.append(prevBtn, controls, nextBtn);
377
+ const grid = document.createElement("div");
378
+ grid.className = "ina-date-picker__calendar-grid";
379
+ DAYS_SHORT.forEach((day) => {
380
+ const dh = document.createElement("div");
381
+ dh.className = "ina-date-picker__day-header";
382
+ dh.textContent = day;
383
+ grid.appendChild(dh);
204
384
  });
205
385
  const firstDayOfMonth = new Date(year, month, 1).getDay();
206
386
  const daysInMonth = new Date(year, month + 1, 0).getDate();
207
387
  const daysInPrevMonth = new Date(year, month, 0).getDate();
208
- for (let i = 0; i < firstDayOfMonth; i++) {
209
- const dayEl = document.createElement("button");
210
- dayEl.className = "ina-date-picker__calendar-day outside-month";
211
- dayEl.textContent = daysInPrevMonth - firstDayOfMonth + 1 + i;
212
- dayEl.disabled = true;
213
- datepickerContent.appendChild(dayEl);
388
+ for (let i = firstDayOfMonth - 1; i >= 0; i--) {
389
+ const dayBtn = document.createElement("button");
390
+ dayBtn.type = "button";
391
+ dayBtn.className = "ina-date-picker__day ina-date-picker__day--other-month ina-date-picker__day--disabled";
392
+ dayBtn.textContent = daysInPrevMonth - i;
393
+ grid.appendChild(dayBtn);
214
394
  }
215
395
  const today = /* @__PURE__ */ new Date();
216
396
  for (let i = 1; i <= daysInMonth; i++) {
217
- const dayEl = document.createElement("button");
218
- dayEl.className = "ina-date-picker__calendar-day";
219
- dayEl.textContent = i;
220
- dayEl.dataset.date = new Date(year, month, i).toISOString();
221
- if (year === today.getFullYear() && month === today.getMonth() && i === today.getDate()) {
222
- const marker = document.createElement("span");
223
- marker.className = "ina-date-picker__today-marker";
224
- marker.textContent = "Hari ini";
225
- dayEl.appendChild(marker);
226
- dayEl.classList.add("today");
397
+ const dayBtn = document.createElement("button");
398
+ dayBtn.type = "button";
399
+ dayBtn.className = "ina-date-picker__day";
400
+ dayBtn.textContent = i;
401
+ let isSelected = false;
402
+ if (selectedDate && selectedDate.getDate() === i && selectedDate.getMonth() === month && selectedDate.getFullYear() === year) {
403
+ dayBtn.classList.add("ina-date-picker__day--selected");
404
+ isSelected = true;
227
405
  }
228
- if (selectedDate && year === selectedDate.getFullYear() && month === selectedDate.getMonth() && i === selectedDate.getDate()) {
229
- dayEl.classList.add("selected");
406
+ if (today.getDate() === i && today.getMonth() === month && today.getFullYear() === year) {
407
+ dayBtn.classList.add("ina-date-picker__day--today");
230
408
  }
231
- datepickerContent.appendChild(dayEl);
232
- }
233
- const totalCells = 42;
234
- const cellsRendered = firstDayOfMonth + daysInMonth;
235
- const remainingCells = totalCells - cellsRendered;
236
- for (let i = 1; i <= remainingCells; i++) {
237
- const dayEl = document.createElement("button");
238
- dayEl.className = "ina-date-picker__calendar-day outside-month";
239
- dayEl.textContent = i;
240
- dayEl.disabled = true;
241
- datepickerContent.appendChild(dayEl);
242
- }
243
- datepickerMonthPopover.innerHTML = "";
244
- MONTHS.forEach((monthName, index) => {
245
- const monthEl = document.createElement("button");
246
- monthEl.className = "ina-date-picker__month-item";
247
- monthEl.textContent = monthName.substring(0, 3);
248
- monthEl.dataset.month = index;
249
- if (index === month) {
250
- monthEl.classList.add("selected");
251
- }
252
- datepickerMonthPopover.appendChild(monthEl);
253
- });
254
- datepickerYearContent.innerHTML = "";
255
- const startYear = Math.floor(year / 10) * 10;
256
- const endYear = startYear + 19;
257
- datepickerYearCurrent.textContent = `${startYear} - ${endYear}`;
258
- for (let y = startYear; y <= endYear; y++) {
259
- const yearEl = document.createElement("button");
260
- yearEl.className = "ina-date-picker__year-item";
261
- yearEl.textContent = y;
262
- yearEl.dataset.year = y;
263
- if (y === year) {
264
- yearEl.classList.add("selected");
409
+ if (!isSelected) {
410
+ dayBtn.classList.add("ina-date-picker__day--hover");
265
411
  }
266
- datepickerYearContent.appendChild(yearEl);
412
+ dayBtn.addEventListener("click", (e) => {
413
+ e.stopPropagation();
414
+ selectedDate = new Date(year, month, i);
415
+ triggerText.textContent = formatDate(selectedDate);
416
+ triggerText.classList.add("ina-date-picker__trigger-text--value");
417
+ triggerText.classList.remove(
418
+ "ina-date-picker__trigger-text--placeholder"
419
+ );
420
+ datepicker.dispatchEvent(
421
+ new CustomEvent("date:changed", { detail: { selectedDate } })
422
+ );
423
+ toggle(false);
424
+ });
425
+ grid.appendChild(dayBtn);
267
426
  }
268
- }
269
- function togglePopover() {
270
- if (datepickerPopover.style.display === "none" || datepickerPopover.style.display === "") {
271
- datepickerPopover.style.display = "block";
272
- renderCalendar(currentDate.getFullYear(), currentDate.getMonth());
273
- } else {
274
- datepickerPopover.style.display = "none";
427
+ const currentCells = grid.children.length - 7;
428
+ const remaining = 42 - currentCells;
429
+ for (let i = 1; i <= remaining; i++) {
430
+ const dayBtn = document.createElement("button");
431
+ dayBtn.type = "button";
432
+ dayBtn.className = "ina-date-picker__day ina-date-picker__day--other-month ina-date-picker__day--disabled";
433
+ dayBtn.textContent = i;
434
+ grid.appendChild(dayBtn);
275
435
  }
436
+ calendarContainer.append(header, grid);
437
+ panelContent.appendChild(calendarContainer);
276
438
  }
277
- function toggleMonthPopover() {
278
- if (datepickerMonthPopover.style.display === "none" || datepickerMonthPopover.style.display === "") {
279
- datepickerMonthPopover.style.display = "grid";
439
+ function toggle(show) {
440
+ isOpen = show;
441
+ if (show) {
442
+ panel.classList.add("ina-date-picker__panel--open");
443
+ renderCalendar();
280
444
  } else {
281
- datepickerMonthPopover.style.display = "none";
445
+ panel.classList.remove("ina-date-picker__panel--open");
282
446
  }
283
447
  }
284
- function toggleYearPopover() {
285
- if (datepickerYearPopover.style.display === "none" || datepickerYearPopover.style.display === "") {
286
- datepickerYearPopover.style.display = "block";
287
- } else {
288
- datepickerYearPopover.style.display = "none";
289
- }
290
- }
291
- datepickerTrigger.addEventListener("click", (e) => {
448
+ trigger.addEventListener("click", (e) => {
292
449
  e.stopPropagation();
293
- togglePopover();
294
- });
295
- prevMonthButton.addEventListener("click", () => {
296
- currentDate.setMonth(currentDate.getMonth() - 1);
297
- renderCalendar(currentDate.getFullYear(), currentDate.getMonth());
298
- });
299
- nextMonthButton.addEventListener("click", () => {
300
- currentDate.setMonth(currentDate.getMonth() + 1);
301
- renderCalendar(currentDate.getFullYear(), currentDate.getMonth());
302
- });
303
- datepickerMonthTrigger.addEventListener("click", (e) => {
304
- e.stopPropagation();
305
- toggleMonthPopover();
306
- });
307
- datepickerYearTrigger.addEventListener("click", (e) => {
308
- e.stopPropagation();
309
- toggleYearPopover();
310
- });
311
- document.addEventListener("click", (e) => {
312
- if (!datepickerPopover.contains(e.target) && e.target !== datepickerTrigger && !datepickerTrigger.contains(e.target)) {
313
- datepickerPopover.style.display = "none";
314
- }
450
+ toggle(!isOpen);
315
451
  });
316
452
  document.addEventListener("click", (e) => {
317
- if (!datepickerMonthPopover.contains(e.target) && e.target !== datepickerMonthTrigger && !datepickerMonthTrigger.contains(e.target)) {
318
- datepickerMonthPopover.style.display = "none";
319
- }
453
+ if (!datepicker.contains(e.target)) toggle(false);
320
454
  });
321
- document.addEventListener("click", (e) => {
322
- if (!datepickerYearPopover.contains(e.target) && e.target !== datepickerYearTrigger && !datepickerYearTrigger.contains(e.target)) {
323
- datepickerYearPopover.style.display = "none";
324
- }
325
- });
326
- datepickerMonthPopover.addEventListener("click", (e) => {
327
- e.stopPropagation();
328
- const target = e.target;
329
- if (target.classList.contains("ina-date-picker__month-item")) {
330
- const monthIndex = parseInt(target.dataset.month);
331
- currentDate.setMonth(monthIndex);
332
- renderCalendar(currentDate.getFullYear(), currentDate.getMonth());
333
- datepickerMonthPopover.style.display = "none";
334
- }
335
- });
336
- datepickerYearPopover.addEventListener("click", (e) => {
337
- e.stopPropagation();
338
- const target = e.target;
339
- if (target.classList.contains("ina-date-picker__year-nav-prev")) {
340
- const currentYearRange = datepickerYearCurrent.textContent.split(" - ").map((y) => parseInt(y));
341
- const newStartYear = currentYearRange[0] - 20;
342
- const newEndYear = currentYearRange[1] - 20;
343
- renderYear(newStartYear, newEndYear);
344
- } else if (target.classList.contains("ina-date-picker__year-nav-next")) {
345
- const currentYearRange = datepickerYearCurrent.textContent.split(" - ").map((y) => parseInt(y));
346
- const newStartYear = currentYearRange[0] + 20;
347
- const newEndYear = currentYearRange[1] + 20;
348
- renderYear(newStartYear, newEndYear);
349
- }
350
- });
351
- datepickerYearContent.addEventListener("click", (e) => {
352
- e.stopPropagation();
353
- const target = e.target;
354
- if (target.classList.contains("ina-date-picker__year-item")) {
355
- const yearValue = parseInt(target.dataset.year);
356
- currentDate.setFullYear(yearValue);
357
- renderCalendar(currentDate.getFullYear(), currentDate.getMonth());
358
- datepickerYearPopover.style.display = "none";
359
- }
360
- });
361
- datepickerContent.addEventListener("click", (e) => {
362
- const target = e.target;
363
- if (target.classList.contains("ina-date-picker__calendar-day") && !target.classList.contains("outside-month")) {
364
- if (target.classList.contains("selected")) {
365
- target.classList.remove("selected");
366
- selectedDateTarget = null;
367
- } else {
368
- const selectedDateEl = datepickerContent.querySelector(
369
- ".ina-date-picker__calendar-day.selected"
370
- );
371
- selectedDateEl?.classList.remove("selected");
372
- target.classList.add("selected");
373
- selectedDateTarget = target;
374
- }
375
- }
376
- });
377
- datepickerSubmitButton.addEventListener("click", () => {
378
- selectedDate = selectedDateTarget ? new Date(selectedDateTarget.dataset.date) : null;
379
- currentDate = selectedDate ? new Date(selectedDate) : /* @__PURE__ */ new Date();
380
- datepicker.dispatchEvent(
381
- new CustomEvent("date:changed", { detail: { selectedDate } })
382
- );
383
- datepickerPopover.style.display = "none";
384
- });
385
- renderCalendar(currentDate.getFullYear(), currentDate.getMonth());
386
455
  });
387
456
  }
388
- document.addEventListener("DOMContentLoaded", () => {
389
- });
390
457
 
391
458
  // src/js/components/stateless/modal.js
392
459
  function initModal(rootSelector = `.${PREFIX}-modal`) {
@@ -1193,8 +1260,7 @@ if (typeof window !== void 0) {
1193
1260
 
1194
1261
  // src/js/components/stateful/timepicker.js
1195
1262
  function initTimepicker() {
1196
- const pickers = document.querySelectorAll(".ina-time-picker");
1197
- pickers.forEach((picker) => {
1263
+ document.querySelectorAll(".ina-time-picker").forEach((picker) => {
1198
1264
  if (picker.dataset.initialized === "true") return;
1199
1265
  picker.dataset.initialized = "true";
1200
1266
  const input = picker.querySelector(".ina-time-picker__input");
@@ -1214,33 +1280,48 @@ function initTimepicker() {
1214
1280
  panel.style.display = "none";
1215
1281
  picker.appendChild(panel);
1216
1282
  }
1217
- const content = document.createElement("div");
1218
- content.className = "ina-time-picker__content";
1219
- panel.appendChild(content);
1220
- const actions = document.createElement("div");
1221
- actions.className = "ina-time-picker__actions";
1222
- const confirmBtn = document.createElement("button");
1223
- confirmBtn.type = "button";
1224
- confirmBtn.className = "ina-time-picker__confirm-button";
1225
- confirmBtn.textContent = "Pilih";
1226
- actions.appendChild(confirmBtn);
1227
- panel.appendChild(actions);
1283
+ let content = panel.querySelector(".ina-time-picker__content");
1284
+ if (!content) {
1285
+ content = document.createElement("div");
1286
+ content.className = "ina-time-picker__content";
1287
+ panel.appendChild(content);
1288
+ } else {
1289
+ content.innerHTML = "";
1290
+ }
1291
+ let actions = panel.querySelector(".ina-time-picker__actions");
1292
+ if (!actions) {
1293
+ actions = document.createElement("div");
1294
+ actions.className = "ina-time-picker__actions";
1295
+ const confirmBtn = document.createElement("button");
1296
+ confirmBtn.type = "button";
1297
+ confirmBtn.className = "ina-time-picker__confirm-button";
1298
+ confirmBtn.textContent = "Pilih";
1299
+ confirmBtn.onclick = (e) => {
1300
+ e.stopPropagation();
1301
+ close();
1302
+ };
1303
+ actions.appendChild(confirmBtn);
1304
+ panel.appendChild(actions);
1305
+ }
1228
1306
  const parseTime = (timeStr) => {
1229
1307
  if (!timeStr) return { hours: 0, minutes: 0, seconds: 0, period: "AM" };
1230
- const parts = timeStr.split(":");
1231
1308
  let hours = 0, minutes = 0, seconds = 0, period = "AM";
1232
- if (use12Hours) {
1233
- const timePart = timeStr.split(" ")[0];
1234
- const periodPart = timeStr.split(" ")[1] || "AM";
1235
- const tParts = timePart.split(":");
1236
- hours = parseInt(tParts[0] || "0", 10);
1237
- minutes = parseInt(tParts[1] || "0", 10);
1238
- seconds = parseInt(tParts[2] || "0", 10);
1239
- period = periodPart;
1240
- } else {
1241
- hours = parseInt(parts[0] || "0", 10);
1242
- minutes = parseInt(parts[1] || "0", 10);
1243
- seconds = parseInt(parts[2] || "0", 10);
1309
+ try {
1310
+ if (use12Hours) {
1311
+ const [time, p] = timeStr.split(" ");
1312
+ const [h, m, s] = time.split(":");
1313
+ hours = parseInt(h || "0", 10);
1314
+ minutes = parseInt(m || "0", 10);
1315
+ seconds = parseInt(s || "0", 10);
1316
+ period = p || "AM";
1317
+ } else {
1318
+ const [h, m, s] = timeStr.split(":");
1319
+ hours = parseInt(h || "0", 10);
1320
+ minutes = parseInt(m || "0", 10);
1321
+ seconds = parseInt(s || "0", 10);
1322
+ }
1323
+ } catch (e) {
1324
+ console.warn("Invalid time format", timeStr);
1244
1325
  }
1245
1326
  return { hours, minutes, seconds, period };
1246
1327
  };
@@ -1249,15 +1330,13 @@ function initTimepicker() {
1249
1330
  if (use12Hours) {
1250
1331
  let displayHours = h;
1251
1332
  if (displayHours === 0) displayHours = 12;
1252
- if (showSecond) {
1253
- return `${pad(displayHours)}:${pad(m)}:${pad(s)} ${p}`;
1254
- }
1255
- return `${pad(displayHours)}:${pad(m)} ${p}`;
1333
+ const main = `${pad(displayHours)}:${pad(m)}`;
1334
+ const sec = showSecond ? `:${pad(s)}` : "";
1335
+ return `${main}${sec} ${p}`;
1256
1336
  } else {
1257
- if (showSecond) {
1258
- return `${pad(h)}:${pad(m)}:${pad(s)}`;
1259
- }
1260
- return `${pad(h)}:${pad(m)}`;
1337
+ const main = `${pad(h)}:${pad(m)}`;
1338
+ const sec = showSecond ? `:${pad(s)}` : "";
1339
+ return `${main}${sec}`;
1261
1340
  }
1262
1341
  };
1263
1342
  let currentTime = parseTime(internalValue);
@@ -1277,16 +1356,15 @@ function initTimepicker() {
1277
1356
  let isSelected = false;
1278
1357
  if (type === "hour") {
1279
1358
  isSelected = currentTime.hours === i || use12Hours && currentTime.hours === 0 && i === 12;
1280
- } else if (type === "minute") {
1281
- isSelected = currentTime.minutes === i;
1282
- } else if (type === "second") {
1283
- isSelected = currentTime.seconds === i;
1284
- }
1359
+ } else if (type === "minute") isSelected = currentTime.minutes === i;
1360
+ else if (type === "second") isSelected = currentTime.seconds === i;
1285
1361
  if (isSelected)
1286
1362
  option.classList.add("ina-time-picker__option--selected");
1287
1363
  option.addEventListener("click", (e) => {
1288
1364
  e.stopPropagation();
1289
1365
  const val = parseInt(option.dataset.value, 10);
1366
+ if (type === "hour")
1367
+ currentTime.hours = use12Hours && val === 12 ? 0 : val;
1290
1368
  if (type === "hour") currentTime.hours = val;
1291
1369
  if (type === "minute") currentTime.minutes = val;
1292
1370
  if (type === "second") currentTime.seconds = val;
@@ -1350,6 +1428,9 @@ function initTimepicker() {
1350
1428
  panel.style.display = "block";
1351
1429
  currentTime = parseTime(input.value);
1352
1430
  buildPanel();
1431
+ document.dispatchEvent(
1432
+ new CustomEvent("closeTimePicker", { detail: { exclude: picker } })
1433
+ );
1353
1434
  };
1354
1435
  const close = () => {
1355
1436
  isOpen = false;
@@ -1362,17 +1443,13 @@ function initTimepicker() {
1362
1443
  else open();
1363
1444
  };
1364
1445
  wrapper.addEventListener("click", toggle);
1365
- document.addEventListener("click", (e) => {
1366
- if (!picker.contains(e.target)) {
1367
- close();
1368
- }
1446
+ input.addEventListener("click", (e) => {
1369
1447
  });
1370
- confirmBtn.addEventListener("click", (e) => {
1371
- e.stopPropagation();
1372
- close();
1448
+ document.addEventListener("click", (e) => {
1449
+ if (!picker.contains(e.target)) close();
1373
1450
  });
1374
- input.addEventListener("change", () => {
1375
- currentTime = parseTime(input.value);
1451
+ document.addEventListener("closeTimePicker", (e) => {
1452
+ if (e.detail && e.detail.exclude !== picker) close();
1376
1453
  });
1377
1454
  const clearBtn = picker.querySelector(".ina-time-picker__clear-button");
1378
1455
  if (clearBtn && allowClear) {