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