@idds/js 1.0.87 → 1.0.88

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 +1005 -651
  2. package/dist/index.js +1008 -654
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -348,58 +348,44 @@ function initAccordion(rootSelector = `.${PREFIX}-accordion-group`) {
348
348
  });
349
349
  }
350
350
 
351
- // src/js/components/stateful/datepicker.js
352
- function initDatepicker() {
353
- document.querySelectorAll(`.${PREFIX}-date-picker`).forEach((datepicker) => {
354
- if (datepicker.dataset.initialized === "true") return;
355
- datepicker.dataset.initialized = "true";
356
- const mode = datepicker.dataset.mode || "single";
357
- const format = datepicker.dataset.format || "DD/MM/YYYY";
358
- const trigger = datepicker.querySelector(`.${PREFIX}-date-picker__trigger`);
359
- const triggerText = trigger.querySelector(
360
- `.${PREFIX}-date-picker__trigger-text`
361
- );
362
- const panel = datepicker.querySelector(`.${PREFIX}-date-picker__panel`);
363
- panel.style.display = "none";
364
- let panelContent = panel.querySelector(
365
- `.${PREFIX}-date-picker__panel-content`
366
- );
367
- if (!panelContent) {
368
- panelContent = document.createElement("div");
369
- panelContent.className = `${PREFIX}-date-picker__panel-content`;
370
- if (mode === "range" || mode === "multiple") {
371
- panelContent.classList.add(
372
- `${PREFIX}-date-picker__panel-content--dual`
373
- );
374
- }
375
- panel.appendChild(panelContent);
376
- } else {
377
- if (mode === "range" || mode === "multiple") {
378
- panelContent.classList.add(
379
- `${PREFIX}-date-picker__panel-content--dual`
380
- );
381
- }
351
+ // src/js/components/stateful/date-picker.js
352
+ var DatePicker = class {
353
+ constructor(selectorOrElement, options = {}) {
354
+ this.container = typeof selectorOrElement === "string" ? document.querySelector(selectorOrElement) : selectorOrElement;
355
+ if (!this.container) {
356
+ console.warn("[IDDS DatePicker] Container not found:", selectorOrElement);
357
+ return;
382
358
  }
383
- let viewDate = /* @__PURE__ */ new Date();
384
- let selectedDate = null;
385
- let selectedDates = [];
386
- let rangeDate = [null, null];
387
- let isOpen = false;
388
- const MONTHS_ID = [
389
- "Januari",
390
- "Februari",
391
- "Maret",
392
- "April",
393
- "Mei",
394
- "Juni",
395
- "Juli",
396
- "Agustus",
397
- "September",
398
- "Oktober",
399
- "November",
400
- "Desember"
401
- ];
402
- const MONTHS_SHORT_ID = [
359
+ if (this.container.dataset.initialized === "true") {
360
+ return;
361
+ }
362
+ this.container.dataset.initialized = "true";
363
+ const dataMode = this.container.dataset.mode;
364
+ const dataFormat = this.container.dataset.format;
365
+ this.options = {
366
+ mode: dataMode || "single",
367
+ // 'single' | 'multiple' | 'range'
368
+ format: dataFormat || "DD/MM/YYYY",
369
+ disabledBackDate: false,
370
+ disabledFutureDate: false,
371
+ disabledDateBefore: null,
372
+ disabledDateAfter: null,
373
+ disabled: false,
374
+ readonly: false,
375
+ panelOnly: false,
376
+ onChange: null,
377
+ triggerWidth: "",
378
+ panelMaxHeight: "",
379
+ ...options
380
+ };
381
+ this.state = {
382
+ viewDate: /* @__PURE__ */ new Date(),
383
+ selectedDate: null,
384
+ selectedDates: [],
385
+ rangeDate: [null, null],
386
+ isOpen: false
387
+ };
388
+ this.MONTHS_SHORT_ID = [
403
389
  "Jan",
404
390
  "Feb",
405
391
  "Mar",
@@ -413,436 +399,1012 @@ function initDatepicker() {
413
399
  "Nov",
414
400
  "Des"
415
401
  ];
416
- const DAYS_SHORT = ["Min", "Sen", "Sel", "Rab", "Kam", "Jum", "Sab"];
417
- function formatDate(date) {
418
- if (!date) return "";
419
- const day = date.getDate().toString().padStart(2, "0");
420
- const month = (date.getMonth() + 1).toString().padStart(2, "0");
421
- const year = date.getFullYear();
422
- return `${day}/${month}/${year}`;
423
- }
424
- function updateTrigger() {
425
- if (mode === "single") {
426
- if (selectedDate) {
427
- triggerText.textContent = formatDate(selectedDate);
428
- triggerText.classList.add(
429
- `${PREFIX}-date-picker__trigger-text--value`
430
- );
431
- triggerText.classList.remove(
432
- `${PREFIX}-date-picker__trigger-text--placeholder`
433
- );
434
- } else {
435
- triggerText.textContent = "Pilih Tanggal";
436
- triggerText.classList.remove(
437
- `${PREFIX}-date-picker__trigger-text--value`
438
- );
439
- triggerText.classList.add(
440
- `${PREFIX}-date-picker__trigger-text--placeholder`
441
- );
442
- }
443
- } else if (mode === "range") {
444
- if (rangeDate[0] && rangeDate[1]) {
445
- const start = formatDate(rangeDate[0]);
446
- const end = formatDate(rangeDate[1]);
447
- triggerText.textContent = `${start} - ${end}`;
448
- triggerText.classList.add(
449
- `${PREFIX}-date-picker__trigger-text--value`
450
- );
451
- triggerText.classList.remove(
452
- `${PREFIX}-date-picker__trigger-text--placeholder`
453
- );
454
- } else if (rangeDate[0]) {
455
- triggerText.textContent = `${formatDate(rangeDate[0])} - ...`;
456
- triggerText.classList.add(
457
- `${PREFIX}-date-picker__trigger-text--value`
458
- );
459
- } else {
460
- triggerText.textContent = "Pilih Rentang Tanggal";
461
- triggerText.classList.remove(
462
- `${PREFIX}-date-picker__trigger-text--value`
463
- );
464
- triggerText.classList.add(
465
- `${PREFIX}-date-picker__trigger-text--placeholder`
466
- );
467
- }
468
- } else if (mode === "multiple") {
469
- if (selectedDates.length > 0) {
470
- triggerText.textContent = `${selectedDates.length} Tanggal Terpilih`;
471
- triggerText.classList.add(
472
- `${PREFIX}-date-picker__trigger-text--value`
473
- );
474
- triggerText.classList.remove(
475
- `${PREFIX}-date-picker__trigger-text--placeholder`
476
- );
477
- } else {
478
- triggerText.textContent = "Pilih Beberapa Tanggal";
479
- triggerText.classList.remove(
480
- `${PREFIX}-date-picker__trigger-text--value`
481
- );
482
- triggerText.classList.add(
483
- `${PREFIX}-date-picker__trigger-text--placeholder`
484
- );
485
- }
402
+ this.DAYS_SHORT = ["Min", "Sen", "Sel", "Rab", "Kam", "Jum", "Sab"];
403
+ this.elements = {};
404
+ this.initDOM();
405
+ this.bindEvents();
406
+ this.updateTrigger();
407
+ }
408
+ formatDate(date) {
409
+ if (!date) return "";
410
+ const day = date.getDate().toString().padStart(2, "0");
411
+ const month = (date.getMonth() + 1).toString().padStart(2, "0");
412
+ const year = date.getFullYear();
413
+ return `${day}/${month}/${year}`;
414
+ }
415
+ isDateDisabled(date) {
416
+ if (this.options.disabled || this.options.readonly) return true;
417
+ const today = /* @__PURE__ */ new Date();
418
+ today.setHours(0, 0, 0, 0);
419
+ const d = new Date(date);
420
+ d.setHours(0, 0, 0, 0);
421
+ if (this.options.disabledBackDate && d < today) return true;
422
+ if (this.options.disabledFutureDate && d > today) return true;
423
+ if (this.options.disabledDateBefore) {
424
+ const before = new Date(this.options.disabledDateBefore);
425
+ before.setHours(0, 0, 0, 0);
426
+ if (d < before) return true;
427
+ }
428
+ if (this.options.disabledDateAfter) {
429
+ const after = new Date(this.options.disabledDateAfter);
430
+ after.setHours(0, 0, 0, 0);
431
+ if (d > after) return true;
432
+ }
433
+ return false;
434
+ }
435
+ createIcon(name, size = 16) {
436
+ if (name === "chevron-left")
437
+ 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>`;
438
+ if (name === "chevron-right")
439
+ 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>`;
440
+ if (name === "calendar")
441
+ 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"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect><line x1="16" y1="2" x2="16" y2="6"></line><line x1="8" y1="2" x2="8" y2="6"></line><line x1="3" y1="10" x2="21" y2="10"></line></svg>`;
442
+ return "";
443
+ }
444
+ initDOM() {
445
+ if (!this.container.classList.contains(`${PREFIX}-date-picker`)) {
446
+ this.container.classList.add(`${PREFIX}-date-picker`);
447
+ }
448
+ let trigger = this.container.querySelector(
449
+ `.${PREFIX}-date-picker__trigger`
450
+ );
451
+ if (!trigger && !this.options.panelOnly) {
452
+ trigger = document.createElement("button");
453
+ trigger.type = "button";
454
+ trigger.className = `${PREFIX}-date-picker__trigger ${PREFIX}-date-picker__trigger--size-md`;
455
+ if (this.options.disabled) trigger.disabled = true;
456
+ if (this.options.triggerWidth) {
457
+ trigger.style.width = typeof this.options.triggerWidth === "number" ? `${this.options.triggerWidth}px` : this.options.triggerWidth;
458
+ }
459
+ const textWrapper = document.createElement("span");
460
+ textWrapper.className = `${PREFIX}-date-picker__trigger-text ${PREFIX}-date-picker__trigger-text--placeholder`;
461
+ textWrapper.textContent = "Pilih Tanggal";
462
+ const iconWrapper = document.createElement("span");
463
+ iconWrapper.className = `${PREFIX}-date-picker__trigger-icon`;
464
+ iconWrapper.innerHTML = this.createIcon("calendar");
465
+ trigger.appendChild(textWrapper);
466
+ trigger.appendChild(iconWrapper);
467
+ this.container.appendChild(trigger);
468
+ }
469
+ this.elements.trigger = trigger;
470
+ if (trigger) {
471
+ this.elements.triggerText = trigger.querySelector(
472
+ `.${PREFIX}-date-picker__trigger-text`
473
+ );
474
+ }
475
+ let panel = this.container.querySelector(`.${PREFIX}-date-picker__panel`);
476
+ if (!panel) {
477
+ panel = document.createElement("div");
478
+ panel.className = `${PREFIX}-date-picker__panel`;
479
+ if (this.options.panelMaxHeight) {
480
+ panel.style.maxHeight = typeof this.options.panelMaxHeight === "number" ? `${this.options.panelMaxHeight}px` : this.options.panelMaxHeight;
481
+ panel.style.overflowY = "auto";
486
482
  }
483
+ this.container.appendChild(panel);
487
484
  }
488
- function createIcon(name, size = 16) {
489
- if (name === "chevron-left")
490
- 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>`;
491
- if (name === "chevron-right")
492
- 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>`;
493
- return "";
494
- }
495
- function createMonthPicker(initialMonth, onChange) {
496
- const container = document.createElement("div");
497
- container.className = `${PREFIX}-month-picker`;
498
- let currentMonthIdx = initialMonth;
499
- let isPickerOpen = false;
500
- const pickerTrigger = document.createElement("button");
501
- pickerTrigger.type = "button";
502
- pickerTrigger.className = `${PREFIX}-month-picker__trigger ${PREFIX}-month-picker__trigger--size-sm`;
503
- const updateText = () => {
504
- pickerTrigger.innerHTML = `<span class="${PREFIX}-month-picker__trigger-text">${MONTHS_SHORT_ID[currentMonthIdx]}</span>`;
505
- };
506
- updateText();
507
- const pickerPanel = document.createElement("div");
508
- pickerPanel.className = `${PREFIX}-month-picker__panel`;
509
- const grid = document.createElement("div");
510
- grid.className = `${PREFIX}-month-picker__grid`;
511
- MONTHS_SHORT_ID.forEach((m, idx) => {
485
+ this.elements.panel = panel;
486
+ if (!this.options.panelOnly) {
487
+ panel.style.display = "none";
488
+ panel.style.position = "absolute";
489
+ } else {
490
+ panel.style.display = "block";
491
+ panel.style.position = "relative";
492
+ panel.classList.add(`${PREFIX}-date-picker__panel--open`);
493
+ }
494
+ let panelContent = panel.querySelector(
495
+ `.${PREFIX}-date-picker__panel-content`
496
+ );
497
+ if (!panelContent) {
498
+ panelContent = document.createElement("div");
499
+ panelContent.className = `${PREFIX}-date-picker__panel-content`;
500
+ panel.appendChild(panelContent);
501
+ }
502
+ if (this.options.mode === "range" || this.options.mode === "multiple") {
503
+ panelContent.classList.add(`${PREFIX}-date-picker__panel-content--dual`);
504
+ }
505
+ this.elements.panelContent = panelContent;
506
+ }
507
+ updateTrigger() {
508
+ if (this.options.panelOnly || !this.elements.triggerText) return;
509
+ const { mode } = this.options;
510
+ const textEl = this.elements.triggerText;
511
+ if (mode === "single") {
512
+ if (this.state.selectedDate) {
513
+ textEl.textContent = this.formatDate(this.state.selectedDate);
514
+ textEl.classList.add(`${PREFIX}-date-picker__trigger-text--value`);
515
+ textEl.classList.remove(
516
+ `${PREFIX}-date-picker__trigger-text--placeholder`
517
+ );
518
+ } else {
519
+ textEl.textContent = "Pilih Tanggal";
520
+ textEl.classList.remove(`${PREFIX}-date-picker__trigger-text--value`);
521
+ textEl.classList.add(
522
+ `${PREFIX}-date-picker__trigger-text--placeholder`
523
+ );
524
+ }
525
+ } else if (mode === "range") {
526
+ if (this.state.rangeDate[0] && this.state.rangeDate[1]) {
527
+ const start = this.formatDate(this.state.rangeDate[0]);
528
+ const end = this.formatDate(this.state.rangeDate[1]);
529
+ textEl.textContent = `${start} - ${end}`;
530
+ textEl.classList.add(`${PREFIX}-date-picker__trigger-text--value`);
531
+ textEl.classList.remove(
532
+ `${PREFIX}-date-picker__trigger-text--placeholder`
533
+ );
534
+ } else if (this.state.rangeDate[0]) {
535
+ textEl.textContent = `${this.formatDate(this.state.rangeDate[0])} - ...`;
536
+ textEl.classList.add(`${PREFIX}-date-picker__trigger-text--value`);
537
+ } else {
538
+ textEl.textContent = "Pilih Rentang Tanggal";
539
+ textEl.classList.remove(`${PREFIX}-date-picker__trigger-text--value`);
540
+ textEl.classList.add(
541
+ `${PREFIX}-date-picker__trigger-text--placeholder`
542
+ );
543
+ }
544
+ } else if (mode === "multiple") {
545
+ if (this.state.selectedDates.length > 0) {
546
+ textEl.textContent = `${this.state.selectedDates.length} Tanggal Terpilih`;
547
+ textEl.classList.add(`${PREFIX}-date-picker__trigger-text--value`);
548
+ textEl.classList.remove(
549
+ `${PREFIX}-date-picker__trigger-text--placeholder`
550
+ );
551
+ } else {
552
+ textEl.textContent = "Pilih Beberapa Tanggal";
553
+ textEl.classList.remove(`${PREFIX}-date-picker__trigger-text--value`);
554
+ textEl.classList.add(
555
+ `${PREFIX}-date-picker__trigger-text--placeholder`
556
+ );
557
+ }
558
+ }
559
+ }
560
+ createMonthPicker(initialMonth, onChange) {
561
+ const container = document.createElement("div");
562
+ container.className = `${PREFIX}-month-picker`;
563
+ let currentMonthIdx = initialMonth;
564
+ let isPickerOpen = false;
565
+ const pickerTrigger = document.createElement("button");
566
+ pickerTrigger.type = "button";
567
+ pickerTrigger.className = `${PREFIX}-month-picker__trigger ${PREFIX}-month-picker__trigger--size-sm`;
568
+ const updateText = () => {
569
+ pickerTrigger.innerHTML = `<span class="${PREFIX}-month-picker__trigger-text">${this.MONTHS_SHORT_ID[currentMonthIdx]}</span>`;
570
+ };
571
+ updateText();
572
+ const pickerPanel = document.createElement("div");
573
+ pickerPanel.className = `${PREFIX}-month-picker__panel`;
574
+ const grid = document.createElement("div");
575
+ grid.className = `${PREFIX}-month-picker__grid`;
576
+ this.MONTHS_SHORT_ID.forEach((m, idx) => {
577
+ const btn = document.createElement("button");
578
+ btn.type = "button";
579
+ btn.className = `${PREFIX}-month-picker__month-option`;
580
+ if (idx === currentMonthIdx)
581
+ btn.classList.add(`${PREFIX}-month-picker__month-option--selected`);
582
+ btn.textContent = m;
583
+ btn.addEventListener("click", (e) => {
584
+ e.stopPropagation();
585
+ currentMonthIdx = idx;
586
+ updateText();
587
+ togglePicker(false);
588
+ onChange(idx);
589
+ });
590
+ grid.appendChild(btn);
591
+ });
592
+ pickerPanel.appendChild(grid);
593
+ container.append(pickerTrigger, pickerPanel);
594
+ pickerTrigger.addEventListener("click", (e) => togglePicker(!isPickerOpen));
595
+ const togglePicker = (show) => {
596
+ isPickerOpen = show;
597
+ if (show) {
598
+ pickerPanel.classList.add(`${PREFIX}-month-picker__panel--open`);
599
+ pickerTrigger.setAttribute("aria-expanded", "true");
600
+ } else {
601
+ pickerPanel.classList.remove(`${PREFIX}-month-picker__panel--open`);
602
+ pickerTrigger.setAttribute("aria-expanded", "false");
603
+ }
604
+ };
605
+ document.addEventListener("click", (e) => {
606
+ if (!container.contains(e.target)) togglePicker(false);
607
+ });
608
+ return {
609
+ element: container,
610
+ setMonth: (m) => {
611
+ currentMonthIdx = m;
612
+ updateText();
613
+ }
614
+ };
615
+ }
616
+ createYearPicker(initialYear, onChange) {
617
+ const container = document.createElement("div");
618
+ container.className = `${PREFIX}-year-picker`;
619
+ let currentYearVal = initialYear;
620
+ let isPickerOpen = false;
621
+ let decadeStart = Math.floor(initialYear / 20) * 20;
622
+ const pickerTrigger = document.createElement("button");
623
+ pickerTrigger.type = "button";
624
+ pickerTrigger.className = `${PREFIX}-year-picker__trigger ${PREFIX}-year-picker__trigger--size-sm`;
625
+ const updateText = () => {
626
+ pickerTrigger.innerHTML = `<span class="${PREFIX}-year-picker__trigger-text">${currentYearVal}</span>`;
627
+ };
628
+ updateText();
629
+ const pickerPanel = document.createElement("div");
630
+ pickerPanel.className = `${PREFIX}-year-picker__panel`;
631
+ const header = document.createElement("div");
632
+ header.className = `${PREFIX}-year-picker__header`;
633
+ const prevBtn = document.createElement("button");
634
+ prevBtn.type = "button";
635
+ prevBtn.className = `${PREFIX}-year-picker__nav-button`;
636
+ prevBtn.innerHTML = this.createIcon("chevron-left");
637
+ prevBtn.onclick = () => {
638
+ decadeStart -= 20;
639
+ renderGrid();
640
+ };
641
+ const nextBtn = document.createElement("button");
642
+ nextBtn.type = "button";
643
+ nextBtn.className = `${PREFIX}-year-picker__nav-button`;
644
+ nextBtn.innerHTML = this.createIcon("chevron-right");
645
+ nextBtn.onclick = () => {
646
+ decadeStart += 20;
647
+ renderGrid();
648
+ };
649
+ const rangeText = document.createElement("span");
650
+ rangeText.className = `${PREFIX}-year-picker__decade-range`;
651
+ header.append(prevBtn, rangeText, nextBtn);
652
+ const grid = document.createElement("div");
653
+ grid.className = `${PREFIX}-year-picker__grid`;
654
+ const renderGrid = () => {
655
+ grid.innerHTML = "";
656
+ rangeText.textContent = `${decadeStart} - ${decadeStart + 19}`;
657
+ for (let y = decadeStart; y < decadeStart + 20; y++) {
512
658
  const btn = document.createElement("button");
513
659
  btn.type = "button";
514
- btn.className = `${PREFIX}-month-picker__month-option`;
515
- if (idx === currentMonthIdx)
516
- btn.classList.add(`${PREFIX}-month-picker__month-option--selected`);
517
- btn.textContent = m;
660
+ btn.className = `${PREFIX}-year-picker__year-option`;
661
+ if (y === currentYearVal)
662
+ btn.classList.add(`${PREFIX}-year-picker__year-option--selected`);
663
+ btn.textContent = y;
518
664
  btn.addEventListener("click", (e) => {
519
665
  e.stopPropagation();
520
- currentMonthIdx = idx;
666
+ currentYearVal = y;
521
667
  updateText();
522
668
  togglePicker(false);
523
- onChange(idx);
669
+ onChange(y);
524
670
  });
525
671
  grid.appendChild(btn);
526
- });
527
- pickerPanel.appendChild(grid);
528
- container.append(pickerTrigger, pickerPanel);
529
- pickerTrigger.addEventListener("click", (e) => {
530
- togglePicker(!isPickerOpen);
531
- });
532
- function togglePicker(show) {
533
- isPickerOpen = show;
534
- if (show) {
535
- pickerPanel.classList.add(`${PREFIX}-month-picker__panel--open`);
536
- pickerTrigger.setAttribute("aria-expanded", "true");
537
- } else {
538
- pickerPanel.classList.remove(`${PREFIX}-month-picker__panel--open`);
539
- pickerTrigger.setAttribute("aria-expanded", "false");
540
- }
541
672
  }
542
- document.addEventListener("click", (e) => {
543
- if (!container.contains(e.target)) togglePicker(false);
544
- });
545
- return {
546
- element: container,
547
- setMonth: (m) => {
548
- currentMonthIdx = m;
549
- updateText();
550
- }
551
- };
552
- }
553
- function createYearPicker(initialYear, onChange) {
554
- const container = document.createElement("div");
555
- container.className = `${PREFIX}-year-picker`;
556
- let currentYearVal = initialYear;
557
- let isPickerOpen = false;
558
- let decadeStart = Math.floor(initialYear / 20) * 20;
559
- const pickerTrigger = document.createElement("button");
560
- pickerTrigger.type = "button";
561
- pickerTrigger.className = `${PREFIX}-year-picker__trigger ${PREFIX}-year-picker__trigger--size-sm`;
562
- const updateText = () => {
563
- pickerTrigger.innerHTML = `<span class="${PREFIX}-year-picker__trigger-text">${currentYearVal}</span>`;
564
- };
565
- updateText();
566
- const pickerPanel = document.createElement("div");
567
- pickerPanel.className = `${PREFIX}-year-picker__panel`;
568
- const header = document.createElement("div");
569
- header.className = `${PREFIX}-year-picker__header`;
673
+ };
674
+ pickerPanel.append(header, grid);
675
+ container.append(pickerTrigger, pickerPanel);
676
+ pickerTrigger.addEventListener("click", () => togglePicker(!isPickerOpen));
677
+ const togglePicker = (show) => {
678
+ isPickerOpen = show;
679
+ if (show) {
680
+ decadeStart = Math.floor(currentYearVal / 20) * 20;
681
+ renderGrid();
682
+ pickerPanel.classList.add(`${PREFIX}-year-picker__panel--open`);
683
+ } else {
684
+ pickerPanel.classList.remove(`${PREFIX}-year-picker__panel--open`);
685
+ }
686
+ };
687
+ document.addEventListener("click", (e) => {
688
+ if (!container.contains(e.target)) togglePicker(false);
689
+ });
690
+ return {
691
+ element: container,
692
+ setYear: (y) => {
693
+ currentYearVal = y;
694
+ updateText();
695
+ }
696
+ };
697
+ }
698
+ renderCalendarGrid(baseDate, isNextMonth = false) {
699
+ const year = baseDate.getFullYear();
700
+ const month = baseDate.getMonth();
701
+ const { mode } = this.options;
702
+ const container = document.createElement("div");
703
+ container.className = !isNextMonth ? `${PREFIX}-date-picker__calendar-container` : `${PREFIX}-date-picker__calendar`;
704
+ const header = document.createElement("div");
705
+ header.className = isNextMonth ? `${PREFIX}-date-picker__next-month-header` : `${PREFIX}-date-picker__calendar-header`;
706
+ if (!isNextMonth) {
570
707
  const prevBtn = document.createElement("button");
571
708
  prevBtn.type = "button";
572
- prevBtn.className = `${PREFIX}-year-picker__nav-button`;
573
- prevBtn.innerHTML = createIcon("chevron-left");
709
+ prevBtn.className = `${PREFIX}-date-picker__nav-button`;
710
+ prevBtn.innerHTML = this.createIcon("chevron-left");
574
711
  prevBtn.onclick = (e) => {
575
- decadeStart -= 20;
576
- renderGrid();
712
+ e.stopPropagation();
713
+ this.state.viewDate.setMonth(this.state.viewDate.getMonth() - 1);
714
+ this.renderPanel();
577
715
  };
716
+ header.appendChild(prevBtn);
717
+ } else {
718
+ const spacer = document.createElement("div");
719
+ spacer.style.width = "32px";
720
+ header.appendChild(spacer);
721
+ }
722
+ const controls = document.createElement("div");
723
+ controls.className = `${PREFIX}-date-picker__header-controls`;
724
+ const monthCont = document.createElement("div");
725
+ monthCont.className = `${PREFIX}-date-picker__dropdown-container`;
726
+ const monthPicker = this.createMonthPicker(month, (m) => {
727
+ if (isNextMonth) {
728
+ this.state.viewDate = new Date(year, m - 1, 1);
729
+ } else {
730
+ this.state.viewDate.setMonth(m);
731
+ }
732
+ this.renderPanel();
733
+ });
734
+ monthCont.appendChild(monthPicker.element);
735
+ const yearCont = document.createElement("div");
736
+ yearCont.className = `${PREFIX}-date-picker__dropdown-container`;
737
+ const yearPicker = this.createYearPicker(year, (y) => {
738
+ if (isNextMonth) {
739
+ this.state.viewDate = new Date(y, month - 1, 1);
740
+ } else {
741
+ this.state.viewDate.setFullYear(y);
742
+ }
743
+ this.renderPanel();
744
+ });
745
+ yearCont.appendChild(yearPicker.element);
746
+ controls.append(monthCont, yearCont);
747
+ header.appendChild(controls);
748
+ const showNextBtn = mode === "single" && !isNextMonth || isNextMonth;
749
+ if (showNextBtn) {
578
750
  const nextBtn = document.createElement("button");
579
751
  nextBtn.type = "button";
580
- nextBtn.className = `${PREFIX}-year-picker__nav-button`;
581
- nextBtn.innerHTML = createIcon("chevron-right");
752
+ nextBtn.className = `${PREFIX}-date-picker__nav-button`;
753
+ nextBtn.innerHTML = this.createIcon("chevron-right");
582
754
  nextBtn.onclick = (e) => {
583
- decadeStart += 20;
584
- renderGrid();
585
- };
586
- const rangeText = document.createElement("span");
587
- rangeText.className = `${PREFIX}-year-picker__decade-range`;
588
- header.append(prevBtn, rangeText, nextBtn);
589
- const grid = document.createElement("div");
590
- grid.className = `${PREFIX}-year-picker__grid`;
591
- function renderGrid() {
592
- grid.innerHTML = "";
593
- rangeText.textContent = `${decadeStart} - ${decadeStart + 19}`;
594
- for (let y = decadeStart; y < decadeStart + 20; y++) {
595
- const btn = document.createElement("button");
596
- btn.type = "button";
597
- btn.className = `${PREFIX}-year-picker__year-option`;
598
- if (y === currentYearVal)
599
- btn.classList.add(`${PREFIX}-year-picker__year-option--selected`);
600
- btn.textContent = y;
601
- btn.addEventListener("click", (e) => {
602
- e.stopPropagation();
603
- currentYearVal = y;
604
- updateText();
605
- togglePicker(false);
606
- onChange(y);
607
- });
608
- grid.appendChild(btn);
609
- }
610
- }
611
- pickerPanel.append(header, grid);
612
- container.append(pickerTrigger, pickerPanel);
613
- pickerTrigger.addEventListener("click", (e) => {
614
- togglePicker(!isPickerOpen);
615
- });
616
- function togglePicker(show) {
617
- isPickerOpen = show;
618
- if (show) {
619
- decadeStart = Math.floor(currentYearVal / 20) * 20;
620
- renderGrid();
621
- pickerPanel.classList.add(`${PREFIX}-year-picker__panel--open`);
622
- } else {
623
- pickerPanel.classList.remove(`${PREFIX}-year-picker__panel--open`);
624
- }
625
- }
626
- document.addEventListener("click", (e) => {
627
- if (!container.contains(e.target)) togglePicker(false);
628
- });
629
- return {
630
- element: container,
631
- setYear: (y) => {
632
- currentYearVal = y;
633
- updateText();
634
- }
755
+ e.stopPropagation();
756
+ this.state.viewDate.setMonth(this.state.viewDate.getMonth() + 1);
757
+ this.renderPanel();
635
758
  };
759
+ header.appendChild(nextBtn);
760
+ } else if (!isNextMonth) {
761
+ const spacer = document.createElement("div");
762
+ spacer.style.width = "32px";
763
+ header.appendChild(spacer);
764
+ }
765
+ const grid = document.createElement("div");
766
+ grid.className = `${PREFIX}-date-picker__calendar-grid`;
767
+ this.DAYS_SHORT.forEach((d) => {
768
+ const dh = document.createElement("div");
769
+ dh.className = `${PREFIX}-date-picker__day-header`;
770
+ dh.textContent = d;
771
+ grid.appendChild(dh);
772
+ });
773
+ const firstDayOfMonth = new Date(year, month, 1).getDay();
774
+ const daysInMonth = new Date(year, month + 1, 0).getDate();
775
+ const daysInPrevMonth = new Date(year, month, 0).getDate();
776
+ const today = /* @__PURE__ */ new Date();
777
+ for (let i = firstDayOfMonth - 1; i >= 0; i--) {
778
+ const btn = document.createElement("button");
779
+ btn.type = "button";
780
+ btn.className = `${PREFIX}-date-picker__day ${PREFIX}-date-picker__day--other-month ${PREFIX}-date-picker__day--disabled`;
781
+ btn.textContent = daysInPrevMonth - i;
782
+ grid.appendChild(btn);
636
783
  }
637
- function renderCalendarGrid(baseDate, isNextMonth = false) {
638
- const year = baseDate.getFullYear();
639
- const month = baseDate.getMonth();
640
- const container = document.createElement("div");
641
- if (!isNextMonth) {
642
- container.className = `${PREFIX}-date-picker__calendar-container`;
643
- } else {
644
- container.className = `${PREFIX}-date-picker__calendar`;
645
- }
646
- const header = document.createElement("div");
647
- header.className = isNextMonth ? `${PREFIX}-date-picker__next-month-header` : `${PREFIX}-date-picker__calendar-header`;
648
- if (!isNextMonth) {
649
- const prevBtn = document.createElement("button");
650
- prevBtn.type = "button";
651
- prevBtn.className = `${PREFIX}-date-picker__nav-button`;
652
- prevBtn.innerHTML = createIcon("chevron-left");
653
- prevBtn.onclick = (e) => {
784
+ for (let i = 1; i <= daysInMonth; i++) {
785
+ const date = new Date(year, month, i);
786
+ const btn = document.createElement("button");
787
+ btn.type = "button";
788
+ btn.className = `${PREFIX}-date-picker__day`;
789
+ btn.textContent = i;
790
+ const disabled = this.isDateDisabled(date);
791
+ if (disabled) {
792
+ btn.classList.add(`${PREFIX}-date-picker__day--disabled`);
793
+ btn.disabled = true;
794
+ }
795
+ let isSelected = false;
796
+ let isInRange = false;
797
+ if (mode === "single" && this.state.selectedDate) {
798
+ if (date.toDateString() === this.state.selectedDate.toDateString())
799
+ isSelected = true;
800
+ } else if (mode === "multiple") {
801
+ if (this.state.selectedDates.some(
802
+ (d) => d.toDateString() === date.toDateString()
803
+ ))
804
+ isSelected = true;
805
+ } else if (mode === "range") {
806
+ const [start, end] = this.state.rangeDate;
807
+ if (start && date.toDateString() === start.toDateString())
808
+ isSelected = true;
809
+ if (end && date.toDateString() === end.toDateString())
810
+ isSelected = true;
811
+ if (start && end && date > start && date < end) isInRange = true;
812
+ }
813
+ if (isSelected) btn.classList.add(`${PREFIX}-date-picker__day--selected`);
814
+ if (isInRange) btn.classList.add(`${PREFIX}-date-picker__day--in-range`);
815
+ if (date.toDateString() === today.toDateString())
816
+ btn.classList.add(`${PREFIX}-date-picker__day--today`);
817
+ if (!isSelected && !isInRange && !disabled)
818
+ btn.classList.add(`${PREFIX}-date-picker__day--hover`);
819
+ if (!disabled && !this.options.readonly) {
820
+ btn.onclick = (e) => {
654
821
  e.stopPropagation();
655
- viewDate.setMonth(viewDate.getMonth() - 1);
656
- render();
822
+ this.handleDateSelect(date);
657
823
  };
658
- header.appendChild(prevBtn);
824
+ }
825
+ grid.appendChild(btn);
826
+ }
827
+ const usedCells = grid.children.length - 7;
828
+ const remaining = 42 - usedCells;
829
+ for (let i = 1; i <= remaining; i++) {
830
+ const btn = document.createElement("button");
831
+ btn.type = "button";
832
+ btn.className = `${PREFIX}-date-picker__day ${PREFIX}-date-picker__day--other-month ${PREFIX}-date-picker__day--disabled`;
833
+ btn.textContent = i;
834
+ grid.appendChild(btn);
835
+ }
836
+ container.append(header, grid);
837
+ return container;
838
+ }
839
+ handleDateSelect(date) {
840
+ const { mode } = this.options;
841
+ if (mode === "single") {
842
+ this.state.selectedDate = date;
843
+ if (!this.options.panelOnly) this.close();
844
+ } else if (mode === "multiple") {
845
+ const existsIdx = this.state.selectedDates.findIndex(
846
+ (d) => d.toDateString() === date.toDateString()
847
+ );
848
+ if (existsIdx >= 0) this.state.selectedDates.splice(existsIdx, 1);
849
+ else this.state.selectedDates.push(date);
850
+ } else if (mode === "range") {
851
+ const [start, end] = this.state.rangeDate;
852
+ if (!start || start && end) {
853
+ this.state.rangeDate = [date, null];
659
854
  } else {
660
- const spacer = document.createElement("div");
661
- spacer.style.width = "32px";
662
- header.appendChild(spacer);
663
- }
664
- const controls = document.createElement("div");
665
- controls.className = isNextMonth ? `${PREFIX}-date-picker__next-month-controls` : `${PREFIX}-date-picker__header-controls`;
666
- controls.className = `${PREFIX}-date-picker__header-controls`;
667
- const monthCont = document.createElement("div");
668
- monthCont.className = `${PREFIX}-date-picker__dropdown-container`;
669
- const monthPicker = createMonthPicker(month, (m) => {
670
- if (isNextMonth) {
671
- viewDate = new Date(year, m - 1, 1);
672
- } else {
673
- viewDate.setMonth(m);
674
- }
675
- render();
676
- });
677
- monthCont.appendChild(monthPicker.element);
678
- const yearCont = document.createElement("div");
679
- yearCont.className = `${PREFIX}-date-picker__dropdown-container`;
680
- const yearPicker = createYearPicker(year, (y) => {
681
- if (isNextMonth) {
682
- viewDate = new Date(y, month - 1, 1);
855
+ if (date < start) {
856
+ this.state.rangeDate = [date, start];
683
857
  } else {
684
- viewDate.setFullYear(y);
858
+ this.state.rangeDate = [start, date];
685
859
  }
686
- render();
687
- });
688
- yearCont.appendChild(yearPicker.element);
689
- controls.append(monthCont, yearCont);
690
- header.appendChild(controls);
691
- const showNextBtn = mode === "single" && !isNextMonth || isNextMonth;
692
- if (showNextBtn) {
693
- const nextBtn = document.createElement("button");
694
- nextBtn.type = "button";
695
- nextBtn.className = `${PREFIX}-date-picker__nav-button`;
696
- nextBtn.innerHTML = createIcon("chevron-right");
697
- nextBtn.onclick = (e) => {
698
- e.stopPropagation();
699
- viewDate.setMonth(viewDate.getMonth() + 1);
700
- render();
701
- };
702
- header.appendChild(nextBtn);
703
- } else if (!isNextMonth) {
704
- const spacer = document.createElement("div");
705
- spacer.style.width = "32px";
706
- header.appendChild(spacer);
707
- }
708
- const grid = document.createElement("div");
709
- grid.className = `${PREFIX}-date-picker__calendar-grid`;
710
- DAYS_SHORT.forEach((d) => {
711
- const dh = document.createElement("div");
712
- dh.className = `${PREFIX}-date-picker__day-header`;
713
- dh.textContent = d;
714
- grid.appendChild(dh);
715
- });
716
- const firstDayOfMonth = new Date(year, month, 1).getDay();
717
- const daysInMonth = new Date(year, month + 1, 0).getDate();
718
- const daysInPrevMonth = new Date(year, month, 0).getDate();
719
- const today = /* @__PURE__ */ new Date();
720
- for (let i = firstDayOfMonth - 1; i >= 0; i--) {
721
- const btn = document.createElement("button");
722
- btn.type = "button";
723
- btn.className = `${PREFIX}-date-picker__day ${PREFIX}-date-picker__day--other-month ${PREFIX}-date-picker__day--disabled`;
724
- btn.textContent = daysInPrevMonth - i;
725
- grid.appendChild(btn);
860
+ if (!this.options.panelOnly) this.close();
726
861
  }
727
- for (let i = 1; i <= daysInMonth; i++) {
728
- const date = new Date(year, month, i);
729
- const btn = document.createElement("button");
730
- btn.type = "button";
731
- btn.className = `${PREFIX}-date-picker__day`;
732
- btn.textContent = i;
733
- let isSelected = false;
734
- let isInRange = false;
735
- if (mode === "single" && selectedDate) {
736
- if (date.toDateString() === selectedDate.toDateString())
737
- isSelected = true;
738
- } else if (mode === "multiple") {
739
- if (selectedDates.some((d) => d.toDateString() === date.toDateString()))
740
- isSelected = true;
741
- } else if (mode === "range") {
742
- const [start, end] = rangeDate;
743
- if (start && date.toDateString() === start.toDateString())
744
- isSelected = true;
745
- if (end && date.toDateString() === end.toDateString())
746
- isSelected = true;
747
- if (start && end && date > start && date < end) isInRange = true;
748
- }
749
- if (isSelected)
750
- btn.classList.add(`${PREFIX}-date-picker__day--selected`);
751
- if (isInRange)
752
- btn.classList.add(`${PREFIX}-date-picker__day--in-range`);
753
- if (date.toDateString() === today.toDateString())
754
- btn.classList.add(`${PREFIX}-date-picker__day--today`);
755
- if (!isSelected && !isInRange)
756
- btn.classList.add(`${PREFIX}-date-picker__day--hover`);
757
- btn.onclick = (e) => {
862
+ }
863
+ this.renderPanel();
864
+ this.updateTrigger();
865
+ this.triggerChange();
866
+ }
867
+ renderPanel() {
868
+ this.elements.panelContent.innerHTML = "";
869
+ const cal1 = this.renderCalendarGrid(this.state.viewDate);
870
+ this.elements.panelContent.appendChild(cal1);
871
+ if (this.options.mode === "range" || this.options.mode === "multiple") {
872
+ const nextMonthDate = new Date(
873
+ this.state.viewDate.getFullYear(),
874
+ this.state.viewDate.getMonth() + 1,
875
+ 1
876
+ );
877
+ const cal2 = this.renderCalendarGrid(nextMonthDate, true);
878
+ this.elements.panelContent.appendChild(cal2);
879
+ }
880
+ }
881
+ open() {
882
+ if (this.options.disabled || this.options.panelOnly) return;
883
+ this.state.isOpen = true;
884
+ this.elements.panel.classList.add(`${PREFIX}-date-picker__panel--open`);
885
+ this.elements.panel.style.display = "block";
886
+ this.renderPanel();
887
+ }
888
+ close() {
889
+ if (this.options.panelOnly) return;
890
+ this.state.isOpen = false;
891
+ this.elements.panel.classList.remove(`${PREFIX}-date-picker__panel--open`);
892
+ this.elements.panel.style.display = "none";
893
+ }
894
+ toggle() {
895
+ if (this.state.isOpen) this.close();
896
+ else this.open();
897
+ }
898
+ bindEvents() {
899
+ if (this.elements.trigger) {
900
+ this.elements.trigger.addEventListener("click", () => this.toggle());
901
+ }
902
+ document.addEventListener("click", (e) => {
903
+ if (!this.container.contains(e.target) && !this.options.panelOnly) {
904
+ this.close();
905
+ }
906
+ });
907
+ if (this.options.panelOnly) {
908
+ this.renderPanel();
909
+ }
910
+ }
911
+ triggerChange() {
912
+ let detailValue;
913
+ if (this.options.mode === "single") detailValue = this.state.selectedDate;
914
+ else if (this.options.mode === "multiple")
915
+ detailValue = this.state.selectedDates;
916
+ else detailValue = this.state.rangeDate;
917
+ this.container.dispatchEvent(
918
+ new CustomEvent("date:changed", {
919
+ bubbles: true,
920
+ composed: true,
921
+ detail: {
922
+ selectedDate: detailValue
923
+ }
924
+ })
925
+ );
926
+ if (typeof this.options.onChange === "function") {
927
+ this.options.onChange(detailValue);
928
+ }
929
+ }
930
+ // --- Public API ---
931
+ getValue() {
932
+ if (this.options.mode === "single") return this.state.selectedDate;
933
+ if (this.options.mode === "multiple") return this.state.selectedDates;
934
+ return this.state.rangeDate;
935
+ }
936
+ };
937
+ function initDatepicker(selectorOrElement, options = {}) {
938
+ const elements = typeof selectorOrElement === "string" ? document.querySelectorAll(selectorOrElement) : selectorOrElement ? typeof selectorOrElement.length !== "undefined" ? selectorOrElement : [selectorOrElement] : document.querySelectorAll(`.${PREFIX}-date-picker`);
939
+ const instances = [];
940
+ elements.forEach((container) => {
941
+ const instance = new DatePicker(container, options);
942
+ container.__datepickerAPI = instance;
943
+ instances.push(instance);
944
+ });
945
+ if (instances.length === 0) return null;
946
+ return instances.length === 1 ? instances[0] : instances;
947
+ }
948
+
949
+ // src/js/components/stateful/time-picker.js
950
+ var TimePicker = class {
951
+ constructor(selectorOrElement, options = {}) {
952
+ this.container = typeof selectorOrElement === "string" ? document.querySelector(selectorOrElement) : selectorOrElement;
953
+ if (!this.container) {
954
+ console.warn("[IDDS TimePicker] Container not found:", selectorOrElement);
955
+ return;
956
+ }
957
+ if (this.container.dataset.initialized === "true") {
958
+ return;
959
+ }
960
+ this.container.dataset.initialized = "true";
961
+ const format = this.container.dataset.format || "HH:mm";
962
+ const use12HoursAttr = this.container.dataset.use12Hours === "true" || this.container.getAttribute("data-use-12-hours") === "true" || /a/i.test(format);
963
+ const showSecondAttr = this.container.dataset.showSecond === "true";
964
+ const allowClearAttr = this.container.dataset.allowClear !== "false";
965
+ const disabledAttr = this.container.classList.contains(
966
+ `${PREFIX}-time-picker--disabled`
967
+ );
968
+ this.options = {
969
+ format,
970
+ use12Hours: use12HoursAttr || false,
971
+ showSecond: showSecondAttr || false,
972
+ allowClear: allowClearAttr,
973
+ disabled: disabledAttr || false,
974
+ readonly: false,
975
+ disabledBackTime: false,
976
+ disabledTimeBefore: null,
977
+ disabledTimeAfter: null,
978
+ showNowButton: false,
979
+ hourStep: 1,
980
+ minuteStep: 1,
981
+ secondStep: 1,
982
+ onChange: null,
983
+ ...options
984
+ };
985
+ this.state = {
986
+ isOpen: false,
987
+ currentTime: { hours: 0, minutes: 0, seconds: 0, period: "AM" },
988
+ internalValue: ""
989
+ };
990
+ this.elements = {};
991
+ this.initDOM();
992
+ this.bindEvents();
993
+ if (this.elements.input && this.elements.input.value) {
994
+ this.state.internalValue = this.elements.input.value;
995
+ this.state.currentTime = this.parseTime(this.state.internalValue);
996
+ } else if (this.container.dataset.value) {
997
+ this.state.internalValue = this.container.dataset.value;
998
+ this.state.currentTime = this.parseTime(this.state.internalValue);
999
+ this.updateInput();
1000
+ }
1001
+ }
1002
+ createIcon(name, size = 16) {
1003
+ if (name === "clock")
1004
+ 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"><circle cx="12" cy="12" r="10"></circle><polyline points="12 6 12 12 16 14"></polyline></svg>`;
1005
+ if (name === "x")
1006
+ 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"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>`;
1007
+ return "";
1008
+ }
1009
+ parseTime(timeStr) {
1010
+ if (!timeStr) return { hours: 0, minutes: 0, seconds: 0, period: "AM" };
1011
+ let hours = 0, minutes = 0, seconds = 0, period = "AM";
1012
+ try {
1013
+ if (this.options.use12Hours) {
1014
+ const [time, p] = timeStr.split(" ");
1015
+ const [h, m, s] = time.split(":");
1016
+ hours = parseInt(h || "0", 10);
1017
+ minutes = parseInt(m || "0", 10);
1018
+ seconds = parseInt(s || "0", 10);
1019
+ period = p || "AM";
1020
+ } else {
1021
+ const [h, m, s] = timeStr.split(":");
1022
+ hours = parseInt(h || "0", 10);
1023
+ minutes = parseInt(m || "0", 10);
1024
+ seconds = parseInt(s || "0", 10);
1025
+ }
1026
+ } catch (e) {
1027
+ console.warn("[IDDS TimePicker] Invalid time format:", timeStr);
1028
+ }
1029
+ return { hours, minutes, seconds, period };
1030
+ }
1031
+ formatTime(h, m, s, p) {
1032
+ const pad = (n) => n.toString().padStart(2, "0");
1033
+ if (this.options.use12Hours) {
1034
+ let displayHours = h;
1035
+ if (displayHours === 0) displayHours = 12;
1036
+ const main = `${pad(displayHours)}:${pad(m)}`;
1037
+ const sec = this.options.showSecond ? `:${pad(s)}` : "";
1038
+ return `${main}${sec} ${p}`;
1039
+ } else {
1040
+ const main = `${pad(h)}:${pad(m)}`;
1041
+ const sec = this.options.showSecond ? `:${pad(s)}` : "";
1042
+ return `${main}${sec}`;
1043
+ }
1044
+ }
1045
+ parseTimeToMinutes(timeStr) {
1046
+ if (!timeStr) return 0;
1047
+ const parts = timeStr.split(":");
1048
+ const hours = parseInt(parts[0] || "0", 10);
1049
+ const minutes = parseInt(parts[1] || "0", 10);
1050
+ if (this.options.use12Hours && timeStr.includes(" ")) {
1051
+ const period = timeStr.split(" ")[1];
1052
+ let adjustedHours = hours;
1053
+ if (period === "PM" && hours !== 12) adjustedHours = hours + 12;
1054
+ else if (period === "AM" && hours === 12) adjustedHours = 0;
1055
+ return adjustedHours * 60 + minutes;
1056
+ }
1057
+ return hours * 60 + minutes;
1058
+ }
1059
+ isTimeDisabled(hours, minutes, seconds, period, checkOptions = {}) {
1060
+ const timeStr = this.formatTime(hours, minutes, seconds, period);
1061
+ const timeInMinutes = this.parseTimeToMinutes(timeStr);
1062
+ if (this.options.disabledBackTime && !checkOptions.ignoreBefore) {
1063
+ const now = /* @__PURE__ */ new Date();
1064
+ const currentTimeInMinutes = now.getHours() * 60 + now.getMinutes();
1065
+ if (timeInMinutes < currentTimeInMinutes) return true;
1066
+ }
1067
+ if (this.options.disabledTimeBefore && !checkOptions.ignoreBefore) {
1068
+ const beforeTimeInMinutes = this.parseTimeToMinutes(
1069
+ this.options.disabledTimeBefore
1070
+ );
1071
+ if (timeInMinutes < beforeTimeInMinutes) return true;
1072
+ }
1073
+ if (this.options.disabledTimeAfter && !checkOptions.ignoreAfter) {
1074
+ const afterTimeInMinutes = this.parseTimeToMinutes(
1075
+ this.options.disabledTimeAfter
1076
+ );
1077
+ if (timeInMinutes > afterTimeInMinutes) return true;
1078
+ }
1079
+ return false;
1080
+ }
1081
+ initDOM() {
1082
+ if (!this.container.classList.contains(`${PREFIX}-time-picker`)) {
1083
+ this.container.classList.add(`${PREFIX}-time-picker`);
1084
+ }
1085
+ if (this.options.disabled) {
1086
+ this.container.classList.add(`${PREFIX}-time-picker--disabled`);
1087
+ }
1088
+ let wrapper = this.container.querySelector(
1089
+ `.${PREFIX}-time-picker__wrapper`
1090
+ );
1091
+ let input = this.container.querySelector(`.${PREFIX}-time-picker__input`);
1092
+ let clearBtn = this.container.querySelector(
1093
+ `.${PREFIX}-time-picker__clear-button`
1094
+ );
1095
+ if (!wrapper) {
1096
+ wrapper = document.createElement("div");
1097
+ wrapper.className = `${PREFIX}-time-picker__wrapper`;
1098
+ const prefixIcon = document.createElement("div");
1099
+ prefixIcon.className = `${PREFIX}-time-picker__prefix-icon`;
1100
+ prefixIcon.innerHTML = this.createIcon("clock");
1101
+ wrapper.appendChild(prefixIcon);
1102
+ input = document.createElement("input");
1103
+ input.type = "text";
1104
+ input.className = `${PREFIX}-time-picker__input ${PREFIX}-time-picker__input--size-md ${PREFIX}-time-picker__input--with-prefix`;
1105
+ if (this.options.allowClear)
1106
+ input.classList.add(`${PREFIX}-time-picker__input--with-suffix`);
1107
+ input.placeholder = this.container.getAttribute("placeholder") || "Select time";
1108
+ if (this.options.disabled) input.disabled = true;
1109
+ if (this.options.readonly) input.readOnly = true;
1110
+ else input.readOnly = true;
1111
+ wrapper.appendChild(input);
1112
+ if (this.options.allowClear) {
1113
+ clearBtn = document.createElement("div");
1114
+ clearBtn.className = `${PREFIX}-time-picker__clear-button`;
1115
+ clearBtn.innerHTML = this.createIcon("x");
1116
+ clearBtn.style.display = "none";
1117
+ wrapper.appendChild(clearBtn);
1118
+ }
1119
+ this.container.appendChild(wrapper);
1120
+ }
1121
+ this.elements.wrapper = wrapper;
1122
+ this.elements.input = input;
1123
+ this.elements.clearBtn = clearBtn;
1124
+ let panel = this.container.querySelector(`.${PREFIX}-time-picker__panel`);
1125
+ if (!panel) {
1126
+ panel = document.createElement("div");
1127
+ panel.className = `${PREFIX}-time-picker__panel`;
1128
+ panel.style.display = "none";
1129
+ this.container.appendChild(panel);
1130
+ }
1131
+ let content = panel.querySelector(`.${PREFIX}-time-picker__content`);
1132
+ if (!content) {
1133
+ content = document.createElement("div");
1134
+ content.className = `${PREFIX}-time-picker__content`;
1135
+ panel.appendChild(content);
1136
+ }
1137
+ let actions = panel.querySelector(`.${PREFIX}-time-picker__actions`);
1138
+ if (!actions) {
1139
+ actions = document.createElement("div");
1140
+ actions.className = `${PREFIX}-time-picker__actions`;
1141
+ if (this.options.showNowButton) {
1142
+ const nowBtn = document.createElement("button");
1143
+ nowBtn.type = "button";
1144
+ nowBtn.className = `${PREFIX}-time-picker__action-button`;
1145
+ nowBtn.textContent = "Sekarang";
1146
+ nowBtn.onclick = (e) => {
758
1147
  e.stopPropagation();
759
- if (mode === "single") {
760
- selectedDate = date;
761
- render();
762
- } else if (mode === "multiple") {
763
- const existsIdx = selectedDates.findIndex(
764
- (d) => d.toDateString() === date.toDateString()
765
- );
766
- if (existsIdx >= 0) selectedDates.splice(existsIdx, 1);
767
- else selectedDates.push(date);
768
- render();
769
- } else if (mode === "range") {
770
- const [start, end] = rangeDate;
771
- if (!start || start && end) {
772
- rangeDate = [date, null];
773
- } else {
774
- if (date < start) {
775
- rangeDate = [date, start];
776
- } else {
777
- rangeDate = [start, date];
778
- }
779
- }
780
- render();
1148
+ const now = /* @__PURE__ */ new Date();
1149
+ let p = "AM";
1150
+ let h = now.getHours();
1151
+ if (this.options.use12Hours) {
1152
+ p = h >= 12 ? "PM" : "AM";
1153
+ h = h % 12 || 12;
781
1154
  }
782
- updateTrigger();
783
- console.log(`[InaUI] Dispatching date:changed for ${mode}`);
784
- datepicker.dispatchEvent(
785
- new CustomEvent("date:changed", {
786
- bubbles: true,
787
- composed: true,
788
- detail: {
789
- selectedDate: mode === "single" ? selectedDate : mode === "multiple" ? selectedDates : rangeDate
790
- }
791
- })
792
- );
1155
+ this.state.currentTime = {
1156
+ hours: h,
1157
+ minutes: now.getMinutes(),
1158
+ seconds: this.options.showSecond ? now.getSeconds() : 0,
1159
+ period: p
1160
+ };
1161
+ this.updateInput();
1162
+ this.close();
793
1163
  };
794
- grid.appendChild(btn);
795
- }
796
- const usedCells = grid.children.length - 7;
797
- const remaining = 42 - usedCells;
798
- for (let i = 1; i <= remaining; i++) {
799
- const btn = document.createElement("button");
800
- btn.type = "button";
801
- btn.className = `${PREFIX}-date-picker__day ${PREFIX}-date-picker__day--other-month ${PREFIX}-date-picker__day--disabled`;
802
- btn.textContent = i;
803
- grid.appendChild(btn);
804
- }
805
- container.append(header, grid);
806
- return container;
807
- }
808
- function render() {
809
- panelContent.innerHTML = "";
810
- const cal1 = renderCalendarGrid(viewDate);
811
- panelContent.appendChild(cal1);
812
- if (mode === "range" || mode === "multiple") {
813
- const nextMonthDate = new Date(
814
- viewDate.getFullYear(),
815
- viewDate.getMonth() + 1,
816
- 1
817
- );
818
- const cal2 = renderCalendarGrid(nextMonthDate, true);
819
- panelContent.appendChild(cal2);
1164
+ actions.appendChild(nowBtn);
820
1165
  }
1166
+ const confirmBtn = document.createElement("button");
1167
+ confirmBtn.type = "button";
1168
+ confirmBtn.className = `${PREFIX}-time-picker__confirm-button`;
1169
+ confirmBtn.textContent = "Pilih";
1170
+ confirmBtn.onclick = (e) => {
1171
+ e.stopPropagation();
1172
+ this.close();
1173
+ };
1174
+ actions.appendChild(confirmBtn);
1175
+ panel.appendChild(actions);
821
1176
  }
822
- function open() {
823
- isOpen = true;
824
- panel.classList.add(`${PREFIX}-date-picker__panel--open`);
825
- panel.style.display = "block";
826
- render();
1177
+ this.elements.panel = panel;
1178
+ this.elements.content = content;
1179
+ this.elements.actions = actions;
1180
+ }
1181
+ updateInput() {
1182
+ const val = this.formatTime(
1183
+ this.state.currentTime.hours,
1184
+ this.state.currentTime.minutes,
1185
+ this.state.currentTime.seconds,
1186
+ this.state.currentTime.period
1187
+ );
1188
+ this.state.internalValue = val;
1189
+ this.elements.input.value = val;
1190
+ this.container.dataset.value = val;
1191
+ if (this.elements.clearBtn && this.options.allowClear) {
1192
+ this.elements.clearBtn.style.display = val && !this.options.disabled ? "flex" : "none";
827
1193
  }
828
- function close() {
829
- isOpen = false;
830
- panel.classList.remove(`${PREFIX}-date-picker__panel--open`);
831
- panel.style.display = "none";
1194
+ this.elements.input.dispatchEvent(new Event("change", { bubbles: true }));
1195
+ if (typeof this.options.onChange === "function") {
1196
+ this.options.onChange(val);
832
1197
  }
833
- function toggle() {
834
- if (isOpen) close();
835
- else open();
1198
+ }
1199
+ generateOptions(type) {
1200
+ const options = [];
1201
+ const { use12Hours, hourStep, minuteStep, secondStep } = this.options;
1202
+ let limit = type === "hour" ? use12Hours ? 12 : 24 : 60;
1203
+ let step = type === "hour" ? hourStep : type === "minute" ? minuteStep : secondStep;
1204
+ if (limit === 12) {
1205
+ for (let i = type === "hour" ? 1 : 0; i <= (type === "hour" ? 12 : 59); i += step) {
1206
+ options.push(i);
1207
+ }
1208
+ } else if (limit === 24) {
1209
+ for (let i = 0; i <= 23; i += step) {
1210
+ options.push(i);
1211
+ }
1212
+ } else {
1213
+ for (let i = 0; i <= 59; i += step) {
1214
+ options.push(i);
1215
+ }
836
1216
  }
837
- trigger.addEventListener("click", (e) => {
838
- toggle();
1217
+ return options;
1218
+ }
1219
+ renderColumn(type, optionsArr) {
1220
+ const column = document.createElement("div");
1221
+ column.className = `${PREFIX}-time-picker__column ${PREFIX}-time-picker__column--${type}`;
1222
+ const colContent = document.createElement("div");
1223
+ colContent.className = `${PREFIX}-time-picker__column-content`;
1224
+ column.appendChild(colContent);
1225
+ const { use12Hours } = this.options;
1226
+ const { currentTime } = this.state;
1227
+ optionsArr.forEach((optValue) => {
1228
+ const option = document.createElement("div");
1229
+ option.className = `${PREFIX}-time-picker__option`;
1230
+ let isSelected = false;
1231
+ let isDisabled = false;
1232
+ if (type === "hour") {
1233
+ isSelected = currentTime.hours === optValue || use12Hours && currentTime.hours === 0 && optValue === 12;
1234
+ const hourValue = use12Hours ? optValue === 12 ? 0 : optValue : optValue;
1235
+ const isTooEarly = this.isTimeDisabled(
1236
+ hourValue,
1237
+ 59,
1238
+ 59,
1239
+ use12Hours ? currentTime.period : void 0,
1240
+ { ignoreAfter: true }
1241
+ );
1242
+ const isTooLate = this.isTimeDisabled(
1243
+ hourValue,
1244
+ 0,
1245
+ 0,
1246
+ use12Hours ? currentTime.period : void 0,
1247
+ { ignoreBefore: true }
1248
+ );
1249
+ isDisabled = isTooEarly || isTooLate;
1250
+ } else if (type === "minute") {
1251
+ isSelected = currentTime.minutes === optValue;
1252
+ isDisabled = this.isTimeDisabled(
1253
+ currentTime.hours,
1254
+ optValue,
1255
+ currentTime.seconds,
1256
+ use12Hours ? currentTime.period : void 0
1257
+ );
1258
+ } else if (type === "second") {
1259
+ isSelected = currentTime.seconds === optValue;
1260
+ isDisabled = this.isTimeDisabled(
1261
+ currentTime.hours,
1262
+ currentTime.minutes,
1263
+ optValue,
1264
+ use12Hours ? currentTime.period : void 0
1265
+ );
1266
+ }
1267
+ if (isSelected)
1268
+ option.classList.add(`${PREFIX}-time-picker__option--selected`);
1269
+ if (isDisabled)
1270
+ option.classList.add(`${PREFIX}-time-picker__option--disabled`);
1271
+ option.textContent = optValue.toString().padStart(2, "0");
1272
+ if (!isDisabled) {
1273
+ option.addEventListener("click", (e) => {
1274
+ e.stopPropagation();
1275
+ const val = parseInt(optValue, 10);
1276
+ if (type === "hour") {
1277
+ this.state.currentTime.hours = use12Hours && val === 12 ? 0 : val;
1278
+ } else if (type === "minute") {
1279
+ this.state.currentTime.minutes = val;
1280
+ } else if (type === "second") {
1281
+ this.state.currentTime.seconds = val;
1282
+ }
1283
+ this.updateInput();
1284
+ this.buildPanel();
1285
+ });
1286
+ }
1287
+ colContent.appendChild(option);
839
1288
  });
840
- document.addEventListener("click", (e) => {
841
- if (!datepicker.contains(e.target)) {
842
- close();
1289
+ return column;
1290
+ }
1291
+ renderPeriodColumn() {
1292
+ const column = document.createElement("div");
1293
+ column.className = `${PREFIX}-time-picker__column ${PREFIX}-time-picker__column--period`;
1294
+ const colContent = document.createElement("div");
1295
+ colContent.className = `${PREFIX}-time-picker__column-content`;
1296
+ column.appendChild(colContent);
1297
+ ["AM", "PM"].forEach((p) => {
1298
+ const option = document.createElement("div");
1299
+ option.className = `${PREFIX}-time-picker__option`;
1300
+ option.textContent = p;
1301
+ if (this.state.currentTime.period === p) {
1302
+ option.classList.add(`${PREFIX}-time-picker__option--selected`);
1303
+ }
1304
+ const isDisabled = this.isTimeDisabled(
1305
+ this.state.currentTime.hours,
1306
+ this.state.currentTime.minutes,
1307
+ this.state.currentTime.seconds,
1308
+ p
1309
+ );
1310
+ if (isDisabled)
1311
+ option.classList.add(`${PREFIX}-time-picker__option--disabled`);
1312
+ if (!isDisabled) {
1313
+ option.addEventListener("click", (e) => {
1314
+ e.stopPropagation();
1315
+ this.state.currentTime.period = p;
1316
+ this.updateInput();
1317
+ this.buildPanel();
1318
+ });
843
1319
  }
1320
+ colContent.appendChild(option);
1321
+ });
1322
+ return column;
1323
+ }
1324
+ buildPanel() {
1325
+ this.elements.content.innerHTML = "";
1326
+ const hourOps = this.generateOptions("hour");
1327
+ const minOps = this.generateOptions("minute");
1328
+ this.elements.content.appendChild(this.renderColumn("hour", hourOps));
1329
+ this.elements.content.appendChild(this.renderColumn("minute", minOps));
1330
+ if (this.options.showSecond) {
1331
+ const secOps = this.generateOptions("second");
1332
+ this.elements.content.appendChild(this.renderColumn("second", secOps));
1333
+ }
1334
+ if (this.options.use12Hours) {
1335
+ this.elements.content.appendChild(this.renderPeriodColumn());
1336
+ }
1337
+ }
1338
+ open() {
1339
+ if (this.options.disabled || this.state.isOpen) return;
1340
+ this.state.isOpen = true;
1341
+ this.container.classList.add(`${PREFIX}-time-picker--open`);
1342
+ this.elements.panel.style.display = "block";
1343
+ this.state.currentTime = this.parseTime(this.elements.input.value);
1344
+ this.buildPanel();
1345
+ document.dispatchEvent(
1346
+ new CustomEvent("closeTimePicker", {
1347
+ detail: { exclude: this.container }
1348
+ })
1349
+ );
1350
+ }
1351
+ close() {
1352
+ this.state.isOpen = false;
1353
+ this.container.classList.remove(`${PREFIX}-time-picker--open`);
1354
+ this.elements.panel.style.display = "none";
1355
+ }
1356
+ toggle() {
1357
+ if (this.state.isOpen) this.close();
1358
+ else this.open();
1359
+ }
1360
+ bindEvents() {
1361
+ this.elements.wrapper.addEventListener("click", (e) => {
1362
+ e.stopPropagation();
1363
+ this.toggle();
1364
+ });
1365
+ if (this.elements.clearBtn && this.options.allowClear) {
1366
+ this.elements.clearBtn.addEventListener("click", (e) => {
1367
+ e.stopPropagation();
1368
+ this.elements.input.value = "";
1369
+ this.state.currentTime = {
1370
+ hours: 0,
1371
+ minutes: 0,
1372
+ seconds: 0,
1373
+ period: "AM"
1374
+ };
1375
+ this.container.dataset.value = "";
1376
+ this.state.internalValue = "";
1377
+ this.elements.clearBtn.style.display = "none";
1378
+ this.elements.input.dispatchEvent(
1379
+ new Event("change", { bubbles: true })
1380
+ );
1381
+ if (typeof this.options.onChange === "function") {
1382
+ this.options.onChange("");
1383
+ }
1384
+ });
1385
+ }
1386
+ document.addEventListener("click", (e) => {
1387
+ if (!this.container.contains(e.target)) this.close();
844
1388
  });
1389
+ document.addEventListener("closeTimePicker", (e) => {
1390
+ if (e.detail && e.detail.exclude !== this.container) this.close();
1391
+ });
1392
+ }
1393
+ // --- Public API ---
1394
+ getValue() {
1395
+ return this.state.internalValue;
1396
+ }
1397
+ };
1398
+ function initTimepicker(selectorOrElement, options = {}) {
1399
+ const elements = typeof selectorOrElement === "string" ? document.querySelectorAll(selectorOrElement) : selectorOrElement ? typeof selectorOrElement.length !== "undefined" ? selectorOrElement : [selectorOrElement] : document.querySelectorAll(`.${PREFIX}-time-picker`);
1400
+ const instances = [];
1401
+ elements.forEach((container) => {
1402
+ const instance = new TimePicker(container, options);
1403
+ container.__timepickerAPI = instance;
1404
+ instances.push(instance);
845
1405
  });
1406
+ if (instances.length === 0) return null;
1407
+ return instances.length === 1 ? instances[0] : instances;
846
1408
  }
847
1409
 
848
1410
  // src/js/components/stateless/modal.js
@@ -2359,216 +2921,6 @@ function initImgCompare(rootSelector = `.${PREFIX}-img-compare`) {
2359
2921
  });
2360
2922
  }
2361
2923
 
2362
- // src/js/components/stateful/timepicker.js
2363
- function initTimepicker() {
2364
- document.querySelectorAll(`.${PREFIX}-time-picker`).forEach((picker) => {
2365
- if (picker.dataset.initialized === "true") return;
2366
- picker.dataset.initialized = "true";
2367
- const input = picker.querySelector(`.${PREFIX}-time-picker__input`);
2368
- const wrapper = picker.querySelector(`.${PREFIX}-time-picker__wrapper`);
2369
- if (!input || !wrapper) return;
2370
- const format = picker.dataset.format || "HH:mm";
2371
- const use12Hours = picker.dataset.use12Hours === "true" || picker.getAttribute("data-use-12-hours") === "true" || /a/i.test(format);
2372
- const showSecond = picker.dataset.showSecond === "true";
2373
- const disabled = picker.classList.contains(
2374
- `${PREFIX}-time-picker--disabled`
2375
- );
2376
- const allowClear = picker.dataset.allowClear !== "false";
2377
- let isOpen = false;
2378
- let internalValue = input.value || "";
2379
- let panel = picker.querySelector(`.${PREFIX}-time-picker__panel`);
2380
- if (!panel) {
2381
- panel = document.createElement("div");
2382
- panel.className = `${PREFIX}-time-picker__panel`;
2383
- panel.style.display = "none";
2384
- picker.appendChild(panel);
2385
- }
2386
- let content = panel.querySelector(`.${PREFIX}-time-picker__content`);
2387
- if (!content) {
2388
- content = document.createElement("div");
2389
- content.className = `${PREFIX}-time-picker__content`;
2390
- panel.appendChild(content);
2391
- } else {
2392
- content.innerHTML = "";
2393
- }
2394
- let actions = panel.querySelector(`.${PREFIX}-time-picker__actions`);
2395
- if (!actions) {
2396
- actions = document.createElement("div");
2397
- actions.className = `${PREFIX}-time-picker__actions`;
2398
- const confirmBtn = document.createElement("button");
2399
- confirmBtn.type = "button";
2400
- confirmBtn.className = `${PREFIX}-time-picker__confirm-button`;
2401
- confirmBtn.textContent = "Pilih";
2402
- confirmBtn.onclick = (e) => {
2403
- e.stopPropagation();
2404
- close();
2405
- };
2406
- actions.appendChild(confirmBtn);
2407
- panel.appendChild(actions);
2408
- }
2409
- const parseTime = (timeStr) => {
2410
- if (!timeStr) return { hours: 0, minutes: 0, seconds: 0, period: "AM" };
2411
- let hours = 0, minutes = 0, seconds = 0, period = "AM";
2412
- try {
2413
- if (use12Hours) {
2414
- const [time, p] = timeStr.split(" ");
2415
- const [h, m, s] = time.split(":");
2416
- hours = parseInt(h || "0", 10);
2417
- minutes = parseInt(m || "0", 10);
2418
- seconds = parseInt(s || "0", 10);
2419
- period = p || "AM";
2420
- } else {
2421
- const [h, m, s] = timeStr.split(":");
2422
- hours = parseInt(h || "0", 10);
2423
- minutes = parseInt(m || "0", 10);
2424
- seconds = parseInt(s || "0", 10);
2425
- }
2426
- } catch (e) {
2427
- console.warn("Invalid time format", timeStr);
2428
- }
2429
- return { hours, minutes, seconds, period };
2430
- };
2431
- const formatTime = (h, m, s, p) => {
2432
- const pad = (n) => n.toString().padStart(2, "0");
2433
- if (use12Hours) {
2434
- let displayHours = h;
2435
- if (displayHours === 0) displayHours = 12;
2436
- const main = `${pad(displayHours)}:${pad(m)}`;
2437
- const sec = showSecond ? `:${pad(s)}` : "";
2438
- return `${main}${sec} ${p}`;
2439
- } else {
2440
- const main = `${pad(h)}:${pad(m)}`;
2441
- const sec = showSecond ? `:${pad(s)}` : "";
2442
- return `${main}${sec}`;
2443
- }
2444
- };
2445
- let currentTime = parseTime(internalValue);
2446
- const renderColumn = (type, max) => {
2447
- const column = document.createElement("div");
2448
- column.className = `${PREFIX}-time-picker__column ${PREFIX}-time-picker__column--${type}`;
2449
- const colContent = document.createElement("div");
2450
- colContent.className = `${PREFIX}-time-picker__column-content`;
2451
- column.appendChild(colContent);
2452
- const start = type === "hour" && use12Hours ? 1 : 0;
2453
- const end = type === "hour" && use12Hours ? 12 : max - 1;
2454
- for (let i = start; i <= end; i++) {
2455
- const option = document.createElement("div");
2456
- option.className = `${PREFIX}-time-picker__option`;
2457
- option.textContent = i.toString().padStart(2, "0");
2458
- option.dataset.value = i;
2459
- let isSelected = false;
2460
- if (type === "hour") {
2461
- isSelected = currentTime.hours === i || use12Hours && currentTime.hours === 0 && i === 12;
2462
- } else if (type === "minute") isSelected = currentTime.minutes === i;
2463
- else if (type === "second") isSelected = currentTime.seconds === i;
2464
- if (isSelected)
2465
- option.classList.add(`${PREFIX}-time-picker__option--selected`);
2466
- option.addEventListener("click", (e) => {
2467
- e.stopPropagation();
2468
- const val = parseInt(option.dataset.value, 10);
2469
- if (type === "hour")
2470
- currentTime.hours = use12Hours && val === 12 ? 0 : val;
2471
- if (type === "hour") currentTime.hours = val;
2472
- if (type === "minute") currentTime.minutes = val;
2473
- if (type === "second") currentTime.seconds = val;
2474
- updateInput();
2475
- colContent.querySelectorAll(`.${PREFIX}-time-picker__option`).forEach(
2476
- (el) => el.classList.remove(`${PREFIX}-time-picker__option--selected`)
2477
- );
2478
- option.classList.add(`${PREFIX}-time-picker__option--selected`);
2479
- });
2480
- colContent.appendChild(option);
2481
- }
2482
- return column;
2483
- };
2484
- const renderPeriodColumn = () => {
2485
- const column = document.createElement("div");
2486
- column.className = `${PREFIX}-time-picker__column ${PREFIX}-time-picker__column--period`;
2487
- const colContent = document.createElement("div");
2488
- colContent.className = `${PREFIX}-time-picker__column-content`;
2489
- column.appendChild(colContent);
2490
- ["AM", "PM"].forEach((p) => {
2491
- const option = document.createElement("div");
2492
- option.className = `${PREFIX}-time-picker__option`;
2493
- option.textContent = p;
2494
- if (currentTime.period === p)
2495
- option.classList.add(`${PREFIX}-time-picker__option--selected`);
2496
- option.addEventListener("click", (e) => {
2497
- e.stopPropagation();
2498
- currentTime.period = p;
2499
- updateInput();
2500
- colContent.querySelectorAll(`.${PREFIX}-time-picker__option`).forEach(
2501
- (el) => el.classList.remove(`${PREFIX}-time-picker__option--selected`)
2502
- );
2503
- option.classList.add(`${PREFIX}-time-picker__option--selected`);
2504
- });
2505
- colContent.appendChild(option);
2506
- });
2507
- return column;
2508
- };
2509
- const updateInput = () => {
2510
- const val = formatTime(
2511
- currentTime.hours,
2512
- currentTime.minutes,
2513
- currentTime.seconds,
2514
- currentTime.period
2515
- );
2516
- input.value = val;
2517
- picker.dataset.value = val;
2518
- input.dispatchEvent(new Event("change", { bubbles: true }));
2519
- };
2520
- const buildPanel = () => {
2521
- content.innerHTML = "";
2522
- content.appendChild(renderColumn("hour", use12Hours ? 13 : 24));
2523
- content.appendChild(renderColumn("minute", 60));
2524
- if (showSecond) content.appendChild(renderColumn("second", 60));
2525
- if (use12Hours) content.appendChild(renderPeriodColumn());
2526
- };
2527
- const open = () => {
2528
- if (disabled) return;
2529
- isOpen = true;
2530
- picker.classList.add(`${PREFIX}-time-picker--open`);
2531
- panel.style.display = "block";
2532
- currentTime = parseTime(input.value);
2533
- buildPanel();
2534
- document.dispatchEvent(
2535
- new CustomEvent("closeTimePicker", { detail: { exclude: picker } })
2536
- );
2537
- };
2538
- const close = () => {
2539
- isOpen = false;
2540
- picker.classList.remove(`${PREFIX}-time-picker--open`);
2541
- panel.style.display = "none";
2542
- };
2543
- const toggle = (e) => {
2544
- e.stopPropagation();
2545
- if (isOpen) close();
2546
- else open();
2547
- };
2548
- wrapper.addEventListener("click", toggle);
2549
- input.addEventListener("click", (e) => {
2550
- });
2551
- document.addEventListener("click", (e) => {
2552
- if (!picker.contains(e.target)) close();
2553
- });
2554
- document.addEventListener("closeTimePicker", (e) => {
2555
- if (e.detail && e.detail.exclude !== picker) close();
2556
- });
2557
- const clearBtn = picker.querySelector(
2558
- `.${PREFIX}-time-picker__clear-button`
2559
- );
2560
- if (clearBtn && allowClear) {
2561
- clearBtn.addEventListener("click", (e) => {
2562
- e.stopPropagation();
2563
- input.value = "";
2564
- currentTime = { hours: 0, minutes: 0, seconds: 0, period: "AM" };
2565
- picker.dataset.value = "";
2566
- input.dispatchEvent(new Event("change", { bubbles: true }));
2567
- });
2568
- }
2569
- });
2570
- }
2571
-
2572
2924
  // src/js/components/stateful/chip.js
2573
2925
  var PREFIX5 = "ina";
2574
2926
  function initChip(rootSelector = `.${PREFIX5}-chip`) {
@@ -3678,6 +4030,7 @@ function initAll() {
3678
4030
  initButtonGroup();
3679
4031
  initCheckbox();
3680
4032
  initDatepicker();
4033
+ initTimepicker();
3681
4034
  initDrawer();
3682
4035
  initBasicDropdown();
3683
4036
  initActionDropdown();
@@ -3693,7 +4046,6 @@ function initAll() {
3693
4046
  initRangeDatepicker();
3694
4047
  initTab();
3695
4048
  initToggle();
3696
- initTimepicker();
3697
4049
  initPagination();
3698
4050
  initChip();
3699
4051
  initTabVertical();
@@ -3701,8 +4053,10 @@ function initAll() {
3701
4053
  initTable();
3702
4054
  }
3703
4055
  export {
4056
+ DatePicker,
3704
4057
  PREFIX,
3705
4058
  Table,
4059
+ TimePicker,
3706
4060
  initAll,
3707
4061
  setBrandTheme,
3708
4062
  showToast