@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
@@ -20,7 +20,9 @@ var InaUI = (() => {
20
20
  // src/js/bundle.js
21
21
  var bundle_exports = {};
22
22
  __export(bundle_exports, {
23
+ DatePicker: () => DatePicker,
23
24
  Table: () => Table,
25
+ TimePicker: () => TimePicker,
24
26
  initAccordion: () => initAccordion,
25
27
  initButtonGroup: () => initButtonGroup,
26
28
  initCheckbox: () => initCheckbox,
@@ -356,58 +358,44 @@ var InaUI = (() => {
356
358
  });
357
359
  }
358
360
 
359
- // src/js/components/stateful/datepicker.js
360
- function initDatepicker() {
361
- document.querySelectorAll(`.${PREFIX}-date-picker`).forEach((datepicker) => {
362
- if (datepicker.dataset.initialized === "true") return;
363
- datepicker.dataset.initialized = "true";
364
- const mode = datepicker.dataset.mode || "single";
365
- const format = datepicker.dataset.format || "DD/MM/YYYY";
366
- const trigger = datepicker.querySelector(`.${PREFIX}-date-picker__trigger`);
367
- const triggerText = trigger.querySelector(
368
- `.${PREFIX}-date-picker__trigger-text`
369
- );
370
- const panel = datepicker.querySelector(`.${PREFIX}-date-picker__panel`);
371
- panel.style.display = "none";
372
- let panelContent = panel.querySelector(
373
- `.${PREFIX}-date-picker__panel-content`
374
- );
375
- if (!panelContent) {
376
- panelContent = document.createElement("div");
377
- panelContent.className = `${PREFIX}-date-picker__panel-content`;
378
- if (mode === "range" || mode === "multiple") {
379
- panelContent.classList.add(
380
- `${PREFIX}-date-picker__panel-content--dual`
381
- );
382
- }
383
- panel.appendChild(panelContent);
384
- } else {
385
- if (mode === "range" || mode === "multiple") {
386
- panelContent.classList.add(
387
- `${PREFIX}-date-picker__panel-content--dual`
388
- );
389
- }
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;
390
368
  }
391
- let viewDate = /* @__PURE__ */ new Date();
392
- let selectedDate = null;
393
- let selectedDates = [];
394
- let rangeDate = [null, null];
395
- let isOpen = false;
396
- const MONTHS_ID = [
397
- "Januari",
398
- "Februari",
399
- "Maret",
400
- "April",
401
- "Mei",
402
- "Juni",
403
- "Juli",
404
- "Agustus",
405
- "September",
406
- "Oktober",
407
- "November",
408
- "Desember"
409
- ];
410
- 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 = [
411
399
  "Jan",
412
400
  "Feb",
413
401
  "Mar",
@@ -421,436 +409,1012 @@ var InaUI = (() => {
421
409
  "Nov",
422
410
  "Des"
423
411
  ];
424
- const DAYS_SHORT = ["Min", "Sen", "Sel", "Rab", "Kam", "Jum", "Sab"];
425
- function formatDate(date) {
426
- if (!date) return "";
427
- const day = date.getDate().toString().padStart(2, "0");
428
- const month = (date.getMonth() + 1).toString().padStart(2, "0");
429
- const year = date.getFullYear();
430
- return `${day}/${month}/${year}`;
431
- }
432
- function updateTrigger() {
433
- if (mode === "single") {
434
- if (selectedDate) {
435
- triggerText.textContent = formatDate(selectedDate);
436
- triggerText.classList.add(
437
- `${PREFIX}-date-picker__trigger-text--value`
438
- );
439
- triggerText.classList.remove(
440
- `${PREFIX}-date-picker__trigger-text--placeholder`
441
- );
442
- } else {
443
- triggerText.textContent = "Pilih Tanggal";
444
- triggerText.classList.remove(
445
- `${PREFIX}-date-picker__trigger-text--value`
446
- );
447
- triggerText.classList.add(
448
- `${PREFIX}-date-picker__trigger-text--placeholder`
449
- );
450
- }
451
- } else if (mode === "range") {
452
- if (rangeDate[0] && rangeDate[1]) {
453
- const start = formatDate(rangeDate[0]);
454
- const end = formatDate(rangeDate[1]);
455
- triggerText.textContent = `${start} - ${end}`;
456
- triggerText.classList.add(
457
- `${PREFIX}-date-picker__trigger-text--value`
458
- );
459
- triggerText.classList.remove(
460
- `${PREFIX}-date-picker__trigger-text--placeholder`
461
- );
462
- } else if (rangeDate[0]) {
463
- triggerText.textContent = `${formatDate(rangeDate[0])} - ...`;
464
- triggerText.classList.add(
465
- `${PREFIX}-date-picker__trigger-text--value`
466
- );
467
- } else {
468
- triggerText.textContent = "Pilih Rentang Tanggal";
469
- triggerText.classList.remove(
470
- `${PREFIX}-date-picker__trigger-text--value`
471
- );
472
- triggerText.classList.add(
473
- `${PREFIX}-date-picker__trigger-text--placeholder`
474
- );
475
- }
476
- } else if (mode === "multiple") {
477
- if (selectedDates.length > 0) {
478
- triggerText.textContent = `${selectedDates.length} Tanggal Terpilih`;
479
- triggerText.classList.add(
480
- `${PREFIX}-date-picker__trigger-text--value`
481
- );
482
- triggerText.classList.remove(
483
- `${PREFIX}-date-picker__trigger-text--placeholder`
484
- );
485
- } else {
486
- triggerText.textContent = "Pilih Beberapa Tanggal";
487
- triggerText.classList.remove(
488
- `${PREFIX}-date-picker__trigger-text--value`
489
- );
490
- triggerText.classList.add(
491
- `${PREFIX}-date-picker__trigger-text--placeholder`
492
- );
493
- }
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;
494
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);
495
478
  }
496
- function createIcon(name, size = 16) {
497
- if (name === "chevron-left")
498
- 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>`;
499
- if (name === "chevron-right")
500
- 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>`;
501
- return "";
502
- }
503
- function createMonthPicker(initialMonth, onChange) {
504
- const container = document.createElement("div");
505
- container.className = `${PREFIX}-month-picker`;
506
- let currentMonthIdx = initialMonth;
507
- let isPickerOpen = false;
508
- const pickerTrigger = document.createElement("button");
509
- pickerTrigger.type = "button";
510
- pickerTrigger.className = `${PREFIX}-month-picker__trigger ${PREFIX}-month-picker__trigger--size-sm`;
511
- const updateText = () => {
512
- pickerTrigger.innerHTML = `<span class="${PREFIX}-month-picker__trigger-text">${MONTHS_SHORT_ID[currentMonthIdx]}</span>`;
513
- };
514
- updateText();
515
- const pickerPanel = document.createElement("div");
516
- pickerPanel.className = `${PREFIX}-month-picker__panel`;
517
- const grid = document.createElement("div");
518
- grid.className = `${PREFIX}-month-picker__grid`;
519
- 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++) {
520
668
  const btn = document.createElement("button");
521
669
  btn.type = "button";
522
- btn.className = `${PREFIX}-month-picker__month-option`;
523
- if (idx === currentMonthIdx)
524
- btn.classList.add(`${PREFIX}-month-picker__month-option--selected`);
525
- 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;
526
674
  btn.addEventListener("click", (e) => {
527
675
  e.stopPropagation();
528
- currentMonthIdx = idx;
676
+ currentYearVal = y;
529
677
  updateText();
530
678
  togglePicker(false);
531
- onChange(idx);
679
+ onChange(y);
532
680
  });
533
681
  grid.appendChild(btn);
534
- });
535
- pickerPanel.appendChild(grid);
536
- container.append(pickerTrigger, pickerPanel);
537
- pickerTrigger.addEventListener("click", (e) => {
538
- togglePicker(!isPickerOpen);
539
- });
540
- function togglePicker(show) {
541
- isPickerOpen = show;
542
- if (show) {
543
- pickerPanel.classList.add(`${PREFIX}-month-picker__panel--open`);
544
- pickerTrigger.setAttribute("aria-expanded", "true");
545
- } else {
546
- pickerPanel.classList.remove(`${PREFIX}-month-picker__panel--open`);
547
- pickerTrigger.setAttribute("aria-expanded", "false");
548
- }
549
682
  }
550
- document.addEventListener("click", (e) => {
551
- if (!container.contains(e.target)) togglePicker(false);
552
- });
553
- return {
554
- element: container,
555
- setMonth: (m) => {
556
- currentMonthIdx = m;
557
- updateText();
558
- }
559
- };
560
- }
561
- function createYearPicker(initialYear, onChange) {
562
- const container = document.createElement("div");
563
- container.className = `${PREFIX}-year-picker`;
564
- let currentYearVal = initialYear;
565
- let isPickerOpen = false;
566
- let decadeStart = Math.floor(initialYear / 20) * 20;
567
- const pickerTrigger = document.createElement("button");
568
- pickerTrigger.type = "button";
569
- pickerTrigger.className = `${PREFIX}-year-picker__trigger ${PREFIX}-year-picker__trigger--size-sm`;
570
- const updateText = () => {
571
- pickerTrigger.innerHTML = `<span class="${PREFIX}-year-picker__trigger-text">${currentYearVal}</span>`;
572
- };
573
- updateText();
574
- const pickerPanel = document.createElement("div");
575
- pickerPanel.className = `${PREFIX}-year-picker__panel`;
576
- const header = document.createElement("div");
577
- 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) {
578
717
  const prevBtn = document.createElement("button");
579
718
  prevBtn.type = "button";
580
- prevBtn.className = `${PREFIX}-year-picker__nav-button`;
581
- prevBtn.innerHTML = createIcon("chevron-left");
719
+ prevBtn.className = `${PREFIX}-date-picker__nav-button`;
720
+ prevBtn.innerHTML = this.createIcon("chevron-left");
582
721
  prevBtn.onclick = (e) => {
583
- decadeStart -= 20;
584
- renderGrid();
722
+ e.stopPropagation();
723
+ this.state.viewDate.setMonth(this.state.viewDate.getMonth() - 1);
724
+ this.renderPanel();
585
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) {
586
760
  const nextBtn = document.createElement("button");
587
761
  nextBtn.type = "button";
588
- nextBtn.className = `${PREFIX}-year-picker__nav-button`;
589
- nextBtn.innerHTML = createIcon("chevron-right");
762
+ nextBtn.className = `${PREFIX}-date-picker__nav-button`;
763
+ nextBtn.innerHTML = this.createIcon("chevron-right");
590
764
  nextBtn.onclick = (e) => {
591
- decadeStart += 20;
592
- renderGrid();
765
+ e.stopPropagation();
766
+ this.state.viewDate.setMonth(this.state.viewDate.getMonth() + 1);
767
+ this.renderPanel();
593
768
  };
594
- const rangeText = document.createElement("span");
595
- rangeText.className = `${PREFIX}-year-picker__decade-range`;
596
- header.append(prevBtn, rangeText, nextBtn);
597
- const grid = document.createElement("div");
598
- grid.className = `${PREFIX}-year-picker__grid`;
599
- function renderGrid() {
600
- grid.innerHTML = "";
601
- rangeText.textContent = `${decadeStart} - ${decadeStart + 19}`;
602
- for (let y = decadeStart; y < decadeStart + 20; y++) {
603
- const btn = document.createElement("button");
604
- btn.type = "button";
605
- btn.className = `${PREFIX}-year-picker__year-option`;
606
- if (y === currentYearVal)
607
- btn.classList.add(`${PREFIX}-year-picker__year-option--selected`);
608
- btn.textContent = y;
609
- btn.addEventListener("click", (e) => {
610
- e.stopPropagation();
611
- currentYearVal = y;
612
- updateText();
613
- togglePicker(false);
614
- onChange(y);
615
- });
616
- grid.appendChild(btn);
617
- }
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;
618
804
  }
619
- pickerPanel.append(header, grid);
620
- container.append(pickerTrigger, pickerPanel);
621
- pickerTrigger.addEventListener("click", (e) => {
622
- togglePicker(!isPickerOpen);
623
- });
624
- function togglePicker(show) {
625
- isPickerOpen = show;
626
- if (show) {
627
- decadeStart = Math.floor(currentYearVal / 20) * 20;
628
- renderGrid();
629
- pickerPanel.classList.add(`${PREFIX}-year-picker__panel--open`);
630
- } else {
631
- pickerPanel.classList.remove(`${PREFIX}-year-picker__panel--open`);
632
- }
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;
633
822
  }
634
- document.addEventListener("click", (e) => {
635
- if (!container.contains(e.target)) togglePicker(false);
636
- });
637
- return {
638
- element: container,
639
- setYear: (y) => {
640
- currentYearVal = y;
641
- updateText();
642
- }
643
- };
644
- }
645
- function renderCalendarGrid(baseDate, isNextMonth = false) {
646
- const year = baseDate.getFullYear();
647
- const month = baseDate.getMonth();
648
- const container = document.createElement("div");
649
- if (!isNextMonth) {
650
- container.className = `${PREFIX}-date-picker__calendar-container`;
651
- } else {
652
- container.className = `${PREFIX}-date-picker__calendar`;
653
- }
654
- const header = document.createElement("div");
655
- header.className = isNextMonth ? `${PREFIX}-date-picker__next-month-header` : `${PREFIX}-date-picker__calendar-header`;
656
- if (!isNextMonth) {
657
- const prevBtn = document.createElement("button");
658
- prevBtn.type = "button";
659
- prevBtn.className = `${PREFIX}-date-picker__nav-button`;
660
- prevBtn.innerHTML = createIcon("chevron-left");
661
- 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) => {
662
831
  e.stopPropagation();
663
- viewDate.setMonth(viewDate.getMonth() - 1);
664
- render();
832
+ this.handleDateSelect(date);
665
833
  };
666
- 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];
667
864
  } else {
668
- const spacer = document.createElement("div");
669
- spacer.style.width = "32px";
670
- header.appendChild(spacer);
671
- }
672
- const controls = document.createElement("div");
673
- controls.className = isNextMonth ? `${PREFIX}-date-picker__next-month-controls` : `${PREFIX}-date-picker__header-controls`;
674
- controls.className = `${PREFIX}-date-picker__header-controls`;
675
- const monthCont = document.createElement("div");
676
- monthCont.className = `${PREFIX}-date-picker__dropdown-container`;
677
- const monthPicker = createMonthPicker(month, (m) => {
678
- if (isNextMonth) {
679
- viewDate = new Date(year, m - 1, 1);
680
- } else {
681
- viewDate.setMonth(m);
682
- }
683
- render();
684
- });
685
- monthCont.appendChild(monthPicker.element);
686
- const yearCont = document.createElement("div");
687
- yearCont.className = `${PREFIX}-date-picker__dropdown-container`;
688
- const yearPicker = createYearPicker(year, (y) => {
689
- if (isNextMonth) {
690
- viewDate = new Date(y, month - 1, 1);
865
+ if (date < start) {
866
+ this.state.rangeDate = [date, start];
691
867
  } else {
692
- viewDate.setFullYear(y);
868
+ this.state.rangeDate = [start, date];
693
869
  }
694
- render();
695
- });
696
- yearCont.appendChild(yearPicker.element);
697
- controls.append(monthCont, yearCont);
698
- header.appendChild(controls);
699
- const showNextBtn = mode === "single" && !isNextMonth || isNextMonth;
700
- if (showNextBtn) {
701
- const nextBtn = document.createElement("button");
702
- nextBtn.type = "button";
703
- nextBtn.className = `${PREFIX}-date-picker__nav-button`;
704
- nextBtn.innerHTML = createIcon("chevron-right");
705
- nextBtn.onclick = (e) => {
706
- e.stopPropagation();
707
- viewDate.setMonth(viewDate.getMonth() + 1);
708
- render();
709
- };
710
- header.appendChild(nextBtn);
711
- } else if (!isNextMonth) {
712
- const spacer = document.createElement("div");
713
- spacer.style.width = "32px";
714
- header.appendChild(spacer);
715
- }
716
- const grid = document.createElement("div");
717
- grid.className = `${PREFIX}-date-picker__calendar-grid`;
718
- DAYS_SHORT.forEach((d) => {
719
- const dh = document.createElement("div");
720
- dh.className = `${PREFIX}-date-picker__day-header`;
721
- dh.textContent = d;
722
- grid.appendChild(dh);
723
- });
724
- const firstDayOfMonth = new Date(year, month, 1).getDay();
725
- const daysInMonth = new Date(year, month + 1, 0).getDate();
726
- const daysInPrevMonth = new Date(year, month, 0).getDate();
727
- const today = /* @__PURE__ */ new Date();
728
- for (let i = firstDayOfMonth - 1; i >= 0; i--) {
729
- const btn = document.createElement("button");
730
- btn.type = "button";
731
- btn.className = `${PREFIX}-date-picker__day ${PREFIX}-date-picker__day--other-month ${PREFIX}-date-picker__day--disabled`;
732
- btn.textContent = daysInPrevMonth - i;
733
- grid.appendChild(btn);
870
+ if (!this.options.panelOnly) this.close();
734
871
  }
735
- for (let i = 1; i <= daysInMonth; i++) {
736
- const date = new Date(year, month, i);
737
- const btn = document.createElement("button");
738
- btn.type = "button";
739
- btn.className = `${PREFIX}-date-picker__day`;
740
- btn.textContent = i;
741
- let isSelected = false;
742
- let isInRange = false;
743
- if (mode === "single" && selectedDate) {
744
- if (date.toDateString() === selectedDate.toDateString())
745
- isSelected = true;
746
- } else if (mode === "multiple") {
747
- if (selectedDates.some((d) => d.toDateString() === date.toDateString()))
748
- isSelected = true;
749
- } else if (mode === "range") {
750
- const [start, end] = rangeDate;
751
- if (start && date.toDateString() === start.toDateString())
752
- isSelected = true;
753
- if (end && date.toDateString() === end.toDateString())
754
- isSelected = true;
755
- 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
756
933
  }
757
- if (isSelected)
758
- btn.classList.add(`${PREFIX}-date-picker__day--selected`);
759
- if (isInRange)
760
- btn.classList.add(`${PREFIX}-date-picker__day--in-range`);
761
- if (date.toDateString() === today.toDateString())
762
- btn.classList.add(`${PREFIX}-date-picker__day--today`);
763
- if (!isSelected && !isInRange)
764
- btn.classList.add(`${PREFIX}-date-picker__day--hover`);
765
- 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) => {
766
1157
  e.stopPropagation();
767
- if (mode === "single") {
768
- selectedDate = date;
769
- render();
770
- } else if (mode === "multiple") {
771
- const existsIdx = selectedDates.findIndex(
772
- (d) => d.toDateString() === date.toDateString()
773
- );
774
- if (existsIdx >= 0) selectedDates.splice(existsIdx, 1);
775
- else selectedDates.push(date);
776
- render();
777
- } else if (mode === "range") {
778
- const [start, end] = rangeDate;
779
- if (!start || start && end) {
780
- rangeDate = [date, null];
781
- } else {
782
- if (date < start) {
783
- rangeDate = [date, start];
784
- } else {
785
- rangeDate = [start, date];
786
- }
787
- }
788
- 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;
789
1164
  }
790
- updateTrigger();
791
- console.log(`[InaUI] Dispatching date:changed for ${mode}`);
792
- datepicker.dispatchEvent(
793
- new CustomEvent("date:changed", {
794
- bubbles: true,
795
- composed: true,
796
- detail: {
797
- selectedDate: mode === "single" ? selectedDate : mode === "multiple" ? selectedDates : rangeDate
798
- }
799
- })
800
- );
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();
801
1173
  };
802
- grid.appendChild(btn);
1174
+ actions.appendChild(nowBtn);
803
1175
  }
804
- const usedCells = grid.children.length - 7;
805
- const remaining = 42 - usedCells;
806
- for (let i = 1; i <= remaining; i++) {
807
- const btn = document.createElement("button");
808
- btn.type = "button";
809
- btn.className = `${PREFIX}-date-picker__day ${PREFIX}-date-picker__day--other-month ${PREFIX}-date-picker__day--disabled`;
810
- btn.textContent = i;
811
- 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);
812
1217
  }
813
- container.append(header, grid);
814
- return container;
815
- }
816
- function render() {
817
- panelContent.innerHTML = "";
818
- const cal1 = renderCalendarGrid(viewDate);
819
- panelContent.appendChild(cal1);
820
- if (mode === "range" || mode === "multiple") {
821
- const nextMonthDate = new Date(
822
- viewDate.getFullYear(),
823
- viewDate.getMonth() + 1,
824
- 1
825
- );
826
- const cal2 = renderCalendarGrid(nextMonthDate, true);
827
- 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);
828
1225
  }
829
1226
  }
830
- function open() {
831
- isOpen = true;
832
- panel.classList.add(`${PREFIX}-date-picker__panel--open`);
833
- panel.style.display = "block";
834
- render();
835
- }
836
- function close() {
837
- isOpen = false;
838
- panel.classList.remove(`${PREFIX}-date-picker__panel--open`);
839
- 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));
840
1343
  }
841
- function toggle() {
842
- if (isOpen) close();
843
- else open();
1344
+ if (this.options.use12Hours) {
1345
+ this.elements.content.appendChild(this.renderPeriodColumn());
844
1346
  }
845
- trigger.addEventListener("click", (e) => {
846
- 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();
847
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
+ }
848
1396
  document.addEventListener("click", (e) => {
849
- if (!datepicker.contains(e.target)) {
850
- close();
851
- }
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();
852
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);
853
1415
  });
1416
+ if (instances.length === 0) return null;
1417
+ return instances.length === 1 ? instances[0] : instances;
854
1418
  }
855
1419
 
856
1420
  // src/js/components/stateless/modal.js
@@ -2275,216 +2839,6 @@ var InaUI = (() => {
2275
2839
  });
2276
2840
  }
2277
2841
 
2278
- // src/js/components/stateful/timepicker.js
2279
- function initTimepicker() {
2280
- document.querySelectorAll(`.${PREFIX}-time-picker`).forEach((picker) => {
2281
- if (picker.dataset.initialized === "true") return;
2282
- picker.dataset.initialized = "true";
2283
- const input = picker.querySelector(`.${PREFIX}-time-picker__input`);
2284
- const wrapper = picker.querySelector(`.${PREFIX}-time-picker__wrapper`);
2285
- if (!input || !wrapper) return;
2286
- const format = picker.dataset.format || "HH:mm";
2287
- const use12Hours = picker.dataset.use12Hours === "true" || picker.getAttribute("data-use-12-hours") === "true" || /a/i.test(format);
2288
- const showSecond = picker.dataset.showSecond === "true";
2289
- const disabled = picker.classList.contains(
2290
- `${PREFIX}-time-picker--disabled`
2291
- );
2292
- const allowClear = picker.dataset.allowClear !== "false";
2293
- let isOpen = false;
2294
- let internalValue = input.value || "";
2295
- let panel = picker.querySelector(`.${PREFIX}-time-picker__panel`);
2296
- if (!panel) {
2297
- panel = document.createElement("div");
2298
- panel.className = `${PREFIX}-time-picker__panel`;
2299
- panel.style.display = "none";
2300
- picker.appendChild(panel);
2301
- }
2302
- let content = panel.querySelector(`.${PREFIX}-time-picker__content`);
2303
- if (!content) {
2304
- content = document.createElement("div");
2305
- content.className = `${PREFIX}-time-picker__content`;
2306
- panel.appendChild(content);
2307
- } else {
2308
- content.innerHTML = "";
2309
- }
2310
- let actions = panel.querySelector(`.${PREFIX}-time-picker__actions`);
2311
- if (!actions) {
2312
- actions = document.createElement("div");
2313
- actions.className = `${PREFIX}-time-picker__actions`;
2314
- const confirmBtn = document.createElement("button");
2315
- confirmBtn.type = "button";
2316
- confirmBtn.className = `${PREFIX}-time-picker__confirm-button`;
2317
- confirmBtn.textContent = "Pilih";
2318
- confirmBtn.onclick = (e) => {
2319
- e.stopPropagation();
2320
- close();
2321
- };
2322
- actions.appendChild(confirmBtn);
2323
- panel.appendChild(actions);
2324
- }
2325
- const parseTime = (timeStr) => {
2326
- if (!timeStr) return { hours: 0, minutes: 0, seconds: 0, period: "AM" };
2327
- let hours = 0, minutes = 0, seconds = 0, period = "AM";
2328
- try {
2329
- if (use12Hours) {
2330
- const [time, p] = timeStr.split(" ");
2331
- const [h, m, s] = time.split(":");
2332
- hours = parseInt(h || "0", 10);
2333
- minutes = parseInt(m || "0", 10);
2334
- seconds = parseInt(s || "0", 10);
2335
- period = p || "AM";
2336
- } else {
2337
- const [h, m, s] = timeStr.split(":");
2338
- hours = parseInt(h || "0", 10);
2339
- minutes = parseInt(m || "0", 10);
2340
- seconds = parseInt(s || "0", 10);
2341
- }
2342
- } catch (e) {
2343
- console.warn("Invalid time format", timeStr);
2344
- }
2345
- return { hours, minutes, seconds, period };
2346
- };
2347
- const formatTime = (h, m, s, p) => {
2348
- const pad = (n) => n.toString().padStart(2, "0");
2349
- if (use12Hours) {
2350
- let displayHours = h;
2351
- if (displayHours === 0) displayHours = 12;
2352
- const main = `${pad(displayHours)}:${pad(m)}`;
2353
- const sec = showSecond ? `:${pad(s)}` : "";
2354
- return `${main}${sec} ${p}`;
2355
- } else {
2356
- const main = `${pad(h)}:${pad(m)}`;
2357
- const sec = showSecond ? `:${pad(s)}` : "";
2358
- return `${main}${sec}`;
2359
- }
2360
- };
2361
- let currentTime = parseTime(internalValue);
2362
- const renderColumn = (type, max) => {
2363
- const column = document.createElement("div");
2364
- column.className = `${PREFIX}-time-picker__column ${PREFIX}-time-picker__column--${type}`;
2365
- const colContent = document.createElement("div");
2366
- colContent.className = `${PREFIX}-time-picker__column-content`;
2367
- column.appendChild(colContent);
2368
- const start = type === "hour" && use12Hours ? 1 : 0;
2369
- const end = type === "hour" && use12Hours ? 12 : max - 1;
2370
- for (let i = start; i <= end; i++) {
2371
- const option = document.createElement("div");
2372
- option.className = `${PREFIX}-time-picker__option`;
2373
- option.textContent = i.toString().padStart(2, "0");
2374
- option.dataset.value = i;
2375
- let isSelected = false;
2376
- if (type === "hour") {
2377
- isSelected = currentTime.hours === i || use12Hours && currentTime.hours === 0 && i === 12;
2378
- } else if (type === "minute") isSelected = currentTime.minutes === i;
2379
- else if (type === "second") isSelected = currentTime.seconds === i;
2380
- if (isSelected)
2381
- option.classList.add(`${PREFIX}-time-picker__option--selected`);
2382
- option.addEventListener("click", (e) => {
2383
- e.stopPropagation();
2384
- const val = parseInt(option.dataset.value, 10);
2385
- if (type === "hour")
2386
- currentTime.hours = use12Hours && val === 12 ? 0 : val;
2387
- if (type === "hour") currentTime.hours = val;
2388
- if (type === "minute") currentTime.minutes = val;
2389
- if (type === "second") currentTime.seconds = val;
2390
- updateInput();
2391
- colContent.querySelectorAll(`.${PREFIX}-time-picker__option`).forEach(
2392
- (el) => el.classList.remove(`${PREFIX}-time-picker__option--selected`)
2393
- );
2394
- option.classList.add(`${PREFIX}-time-picker__option--selected`);
2395
- });
2396
- colContent.appendChild(option);
2397
- }
2398
- return column;
2399
- };
2400
- const renderPeriodColumn = () => {
2401
- const column = document.createElement("div");
2402
- column.className = `${PREFIX}-time-picker__column ${PREFIX}-time-picker__column--period`;
2403
- const colContent = document.createElement("div");
2404
- colContent.className = `${PREFIX}-time-picker__column-content`;
2405
- column.appendChild(colContent);
2406
- ["AM", "PM"].forEach((p) => {
2407
- const option = document.createElement("div");
2408
- option.className = `${PREFIX}-time-picker__option`;
2409
- option.textContent = p;
2410
- if (currentTime.period === p)
2411
- option.classList.add(`${PREFIX}-time-picker__option--selected`);
2412
- option.addEventListener("click", (e) => {
2413
- e.stopPropagation();
2414
- currentTime.period = p;
2415
- updateInput();
2416
- colContent.querySelectorAll(`.${PREFIX}-time-picker__option`).forEach(
2417
- (el) => el.classList.remove(`${PREFIX}-time-picker__option--selected`)
2418
- );
2419
- option.classList.add(`${PREFIX}-time-picker__option--selected`);
2420
- });
2421
- colContent.appendChild(option);
2422
- });
2423
- return column;
2424
- };
2425
- const updateInput = () => {
2426
- const val = formatTime(
2427
- currentTime.hours,
2428
- currentTime.minutes,
2429
- currentTime.seconds,
2430
- currentTime.period
2431
- );
2432
- input.value = val;
2433
- picker.dataset.value = val;
2434
- input.dispatchEvent(new Event("change", { bubbles: true }));
2435
- };
2436
- const buildPanel = () => {
2437
- content.innerHTML = "";
2438
- content.appendChild(renderColumn("hour", use12Hours ? 13 : 24));
2439
- content.appendChild(renderColumn("minute", 60));
2440
- if (showSecond) content.appendChild(renderColumn("second", 60));
2441
- if (use12Hours) content.appendChild(renderPeriodColumn());
2442
- };
2443
- const open = () => {
2444
- if (disabled) return;
2445
- isOpen = true;
2446
- picker.classList.add(`${PREFIX}-time-picker--open`);
2447
- panel.style.display = "block";
2448
- currentTime = parseTime(input.value);
2449
- buildPanel();
2450
- document.dispatchEvent(
2451
- new CustomEvent("closeTimePicker", { detail: { exclude: picker } })
2452
- );
2453
- };
2454
- const close = () => {
2455
- isOpen = false;
2456
- picker.classList.remove(`${PREFIX}-time-picker--open`);
2457
- panel.style.display = "none";
2458
- };
2459
- const toggle = (e) => {
2460
- e.stopPropagation();
2461
- if (isOpen) close();
2462
- else open();
2463
- };
2464
- wrapper.addEventListener("click", toggle);
2465
- input.addEventListener("click", (e) => {
2466
- });
2467
- document.addEventListener("click", (e) => {
2468
- if (!picker.contains(e.target)) close();
2469
- });
2470
- document.addEventListener("closeTimePicker", (e) => {
2471
- if (e.detail && e.detail.exclude !== picker) close();
2472
- });
2473
- const clearBtn = picker.querySelector(
2474
- `.${PREFIX}-time-picker__clear-button`
2475
- );
2476
- if (clearBtn && allowClear) {
2477
- clearBtn.addEventListener("click", (e) => {
2478
- e.stopPropagation();
2479
- input.value = "";
2480
- currentTime = { hours: 0, minutes: 0, seconds: 0, period: "AM" };
2481
- picker.dataset.value = "";
2482
- input.dispatchEvent(new Event("change", { bubbles: true }));
2483
- });
2484
- }
2485
- });
2486
- }
2487
-
2488
2842
  // src/js/components/stateful/chip.js
2489
2843
  var PREFIX4 = "ina";
2490
2844
  function initChip(rootSelector = `.${PREFIX4}-chip`) {
@@ -3784,6 +4138,7 @@ var InaUI = (() => {
3784
4138
  initButtonGroup();
3785
4139
  initCheckbox();
3786
4140
  initDatepicker();
4141
+ initTimepicker();
3787
4142
  initDropdown();
3788
4143
  initFileUpload();
3789
4144
  initSingleFileUpload();
@@ -3795,7 +4150,6 @@ var InaUI = (() => {
3795
4150
  initRadioButton();
3796
4151
  initStepper();
3797
4152
  initTab();
3798
- initTimepicker();
3799
4153
  initToggle();
3800
4154
  initPagination();
3801
4155
  initSelectDropdown();