@idds/js 1.0.87 → 1.0.89

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 +1008 -651
  2. package/dist/index.js +1011 -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,1015 @@ 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 = true;
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
+ if (!isNextMonth && (mode === "range" || mode === "multiple")) {
764
+ nextBtn.classList.add(`${PREFIX}-date-picker__nav-button--mobile-only`);
765
+ }
766
+ nextBtn.innerHTML = this.createIcon("chevron-right");
590
767
  nextBtn.onclick = (e) => {
591
- decadeStart += 20;
592
- renderGrid();
768
+ e.stopPropagation();
769
+ this.state.viewDate.setMonth(this.state.viewDate.getMonth() + 1);
770
+ this.renderPanel();
593
771
  };
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
- }
772
+ header.appendChild(nextBtn);
773
+ } else if (!isNextMonth) {
774
+ const spacer = document.createElement("div");
775
+ spacer.style.width = "32px";
776
+ header.appendChild(spacer);
777
+ }
778
+ const grid = document.createElement("div");
779
+ grid.className = `${PREFIX}-date-picker__calendar-grid`;
780
+ this.DAYS_SHORT.forEach((d) => {
781
+ const dh = document.createElement("div");
782
+ dh.className = `${PREFIX}-date-picker__day-header`;
783
+ dh.textContent = d;
784
+ grid.appendChild(dh);
785
+ });
786
+ const firstDayOfMonth = new Date(year, month, 1).getDay();
787
+ const daysInMonth = new Date(year, month + 1, 0).getDate();
788
+ const daysInPrevMonth = new Date(year, month, 0).getDate();
789
+ const today = /* @__PURE__ */ new Date();
790
+ for (let i = firstDayOfMonth - 1; i >= 0; i--) {
791
+ const btn = document.createElement("button");
792
+ btn.type = "button";
793
+ btn.className = `${PREFIX}-date-picker__day ${PREFIX}-date-picker__day--other-month ${PREFIX}-date-picker__day--disabled`;
794
+ btn.textContent = daysInPrevMonth - i;
795
+ grid.appendChild(btn);
796
+ }
797
+ for (let i = 1; i <= daysInMonth; i++) {
798
+ const date = new Date(year, month, i);
799
+ const btn = document.createElement("button");
800
+ btn.type = "button";
801
+ btn.className = `${PREFIX}-date-picker__day`;
802
+ btn.textContent = i;
803
+ const disabled = this.isDateDisabled(date);
804
+ if (disabled) {
805
+ btn.classList.add(`${PREFIX}-date-picker__day--disabled`);
806
+ btn.disabled = true;
618
807
  }
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
- }
808
+ let isSelected = false;
809
+ let isInRange = false;
810
+ if (mode === "single" && this.state.selectedDate) {
811
+ if (date.toDateString() === this.state.selectedDate.toDateString())
812
+ isSelected = true;
813
+ } else if (mode === "multiple") {
814
+ if (this.state.selectedDates.some(
815
+ (d) => d.toDateString() === date.toDateString()
816
+ ))
817
+ isSelected = true;
818
+ } else if (mode === "range") {
819
+ const [start, end] = this.state.rangeDate;
820
+ if (start && date.toDateString() === start.toDateString())
821
+ isSelected = true;
822
+ if (end && date.toDateString() === end.toDateString())
823
+ isSelected = true;
824
+ if (start && end && date > start && date < end) isInRange = true;
633
825
  }
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) => {
826
+ if (isSelected) btn.classList.add(`${PREFIX}-date-picker__day--selected`);
827
+ if (isInRange) btn.classList.add(`${PREFIX}-date-picker__day--in-range`);
828
+ if (date.toDateString() === today.toDateString())
829
+ btn.classList.add(`${PREFIX}-date-picker__day--today`);
830
+ if (!isSelected && !isInRange && !disabled)
831
+ btn.classList.add(`${PREFIX}-date-picker__day--hover`);
832
+ if (!disabled && !this.options.readonly) {
833
+ btn.onclick = (e) => {
662
834
  e.stopPropagation();
663
- viewDate.setMonth(viewDate.getMonth() - 1);
664
- render();
835
+ this.handleDateSelect(date);
665
836
  };
666
- header.appendChild(prevBtn);
837
+ }
838
+ grid.appendChild(btn);
839
+ }
840
+ const usedCells = grid.children.length - 7;
841
+ const remaining = 42 - usedCells;
842
+ for (let i = 1; i <= remaining; i++) {
843
+ const btn = document.createElement("button");
844
+ btn.type = "button";
845
+ btn.className = `${PREFIX}-date-picker__day ${PREFIX}-date-picker__day--other-month ${PREFIX}-date-picker__day--disabled`;
846
+ btn.textContent = i;
847
+ grid.appendChild(btn);
848
+ }
849
+ container.append(header, grid);
850
+ return container;
851
+ }
852
+ handleDateSelect(date) {
853
+ const { mode } = this.options;
854
+ if (mode === "single") {
855
+ this.state.selectedDate = date;
856
+ if (!this.options.panelOnly) this.close();
857
+ } else if (mode === "multiple") {
858
+ const existsIdx = this.state.selectedDates.findIndex(
859
+ (d) => d.toDateString() === date.toDateString()
860
+ );
861
+ if (existsIdx >= 0) this.state.selectedDates.splice(existsIdx, 1);
862
+ else this.state.selectedDates.push(date);
863
+ } else if (mode === "range") {
864
+ const [start, end] = this.state.rangeDate;
865
+ if (!start || start && end) {
866
+ this.state.rangeDate = [date, null];
667
867
  } 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);
868
+ if (date < start) {
869
+ this.state.rangeDate = [date, start];
691
870
  } else {
692
- viewDate.setFullYear(y);
871
+ this.state.rangeDate = [start, date];
693
872
  }
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);
873
+ if (!this.options.panelOnly) this.close();
734
874
  }
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;
875
+ }
876
+ this.renderPanel();
877
+ this.updateTrigger();
878
+ this.triggerChange();
879
+ }
880
+ renderPanel() {
881
+ this.elements.panelContent.innerHTML = "";
882
+ const cal1 = this.renderCalendarGrid(this.state.viewDate);
883
+ this.elements.panelContent.appendChild(cal1);
884
+ if (this.options.mode === "range" || this.options.mode === "multiple") {
885
+ const nextMonthDate = new Date(
886
+ this.state.viewDate.getFullYear(),
887
+ this.state.viewDate.getMonth() + 1,
888
+ 1
889
+ );
890
+ const cal2 = this.renderCalendarGrid(nextMonthDate, true);
891
+ this.elements.panelContent.appendChild(cal2);
892
+ }
893
+ }
894
+ open() {
895
+ if (this.options.disabled || this.options.panelOnly) return;
896
+ this.state.isOpen = true;
897
+ this.elements.panel.classList.add(`${PREFIX}-date-picker__panel--open`);
898
+ this.elements.panel.style.display = "block";
899
+ this.renderPanel();
900
+ }
901
+ close() {
902
+ if (this.options.panelOnly) return;
903
+ this.state.isOpen = false;
904
+ this.elements.panel.classList.remove(`${PREFIX}-date-picker__panel--open`);
905
+ this.elements.panel.style.display = "none";
906
+ }
907
+ toggle() {
908
+ if (this.state.isOpen) this.close();
909
+ else this.open();
910
+ }
911
+ bindEvents() {
912
+ if (this.elements.trigger) {
913
+ this.elements.trigger.addEventListener("click", () => this.toggle());
914
+ }
915
+ document.addEventListener("click", (e) => {
916
+ if (!this.container.contains(e.target) && !this.options.panelOnly) {
917
+ this.close();
918
+ }
919
+ });
920
+ if (this.options.panelOnly) {
921
+ this.renderPanel();
922
+ }
923
+ }
924
+ triggerChange() {
925
+ let detailValue;
926
+ if (this.options.mode === "single") detailValue = this.state.selectedDate;
927
+ else if (this.options.mode === "multiple")
928
+ detailValue = this.state.selectedDates;
929
+ else detailValue = this.state.rangeDate;
930
+ this.container.dispatchEvent(
931
+ new CustomEvent("date:changed", {
932
+ bubbles: true,
933
+ composed: true,
934
+ detail: {
935
+ selectedDate: detailValue
756
936
  }
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) => {
937
+ })
938
+ );
939
+ if (typeof this.options.onChange === "function") {
940
+ this.options.onChange(detailValue);
941
+ }
942
+ }
943
+ // --- Public API ---
944
+ getValue() {
945
+ if (this.options.mode === "single") return this.state.selectedDate;
946
+ if (this.options.mode === "multiple") return this.state.selectedDates;
947
+ return this.state.rangeDate;
948
+ }
949
+ };
950
+ function initDatepicker(selectorOrElement, options = {}) {
951
+ const elements = typeof selectorOrElement === "string" ? document.querySelectorAll(selectorOrElement) : selectorOrElement ? typeof selectorOrElement.length !== "undefined" ? selectorOrElement : [selectorOrElement] : document.querySelectorAll(`.${PREFIX}-date-picker`);
952
+ const instances = [];
953
+ elements.forEach((container) => {
954
+ const instance = new DatePicker(container, options);
955
+ container.__datepickerAPI = instance;
956
+ instances.push(instance);
957
+ });
958
+ if (instances.length === 0) return null;
959
+ return instances.length === 1 ? instances[0] : instances;
960
+ }
961
+
962
+ // src/js/components/stateful/time-picker.js
963
+ var TimePicker = class {
964
+ constructor(selectorOrElement, options = {}) {
965
+ this.container = typeof selectorOrElement === "string" ? document.querySelector(selectorOrElement) : selectorOrElement;
966
+ if (!this.container) {
967
+ console.warn("[IDDS TimePicker] Container not found:", selectorOrElement);
968
+ return;
969
+ }
970
+ if (this.container.dataset.initialized === "true") {
971
+ return;
972
+ }
973
+ this.container.dataset.initialized = "true";
974
+ const format = this.container.dataset.format || "HH:mm";
975
+ const use12HoursAttr = this.container.dataset.use12Hours === "true" || this.container.getAttribute("data-use-12-hours") === "true" || /a/i.test(format);
976
+ const showSecondAttr = this.container.dataset.showSecond === "true";
977
+ const allowClearAttr = this.container.dataset.allowClear !== "false";
978
+ const disabledAttr = this.container.classList.contains(
979
+ `${PREFIX}-time-picker--disabled`
980
+ );
981
+ this.options = {
982
+ format,
983
+ use12Hours: use12HoursAttr || false,
984
+ showSecond: showSecondAttr || false,
985
+ allowClear: allowClearAttr,
986
+ disabled: disabledAttr || false,
987
+ readonly: false,
988
+ disabledBackTime: false,
989
+ disabledTimeBefore: null,
990
+ disabledTimeAfter: null,
991
+ showNowButton: false,
992
+ hourStep: 1,
993
+ minuteStep: 1,
994
+ secondStep: 1,
995
+ onChange: null,
996
+ ...options
997
+ };
998
+ this.state = {
999
+ isOpen: false,
1000
+ currentTime: { hours: 0, minutes: 0, seconds: 0, period: "AM" },
1001
+ internalValue: ""
1002
+ };
1003
+ this.elements = {};
1004
+ this.initDOM();
1005
+ this.bindEvents();
1006
+ if (this.elements.input && this.elements.input.value) {
1007
+ this.state.internalValue = this.elements.input.value;
1008
+ this.state.currentTime = this.parseTime(this.state.internalValue);
1009
+ } else if (this.container.dataset.value) {
1010
+ this.state.internalValue = this.container.dataset.value;
1011
+ this.state.currentTime = this.parseTime(this.state.internalValue);
1012
+ this.updateInput();
1013
+ }
1014
+ }
1015
+ createIcon(name, size = 16) {
1016
+ if (name === "clock")
1017
+ 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>`;
1018
+ if (name === "x")
1019
+ 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>`;
1020
+ return "";
1021
+ }
1022
+ parseTime(timeStr) {
1023
+ if (!timeStr) return { hours: 0, minutes: 0, seconds: 0, period: "AM" };
1024
+ let hours = 0, minutes = 0, seconds = 0, period = "AM";
1025
+ try {
1026
+ if (this.options.use12Hours) {
1027
+ const [time, p] = timeStr.split(" ");
1028
+ const [h, m, s] = time.split(":");
1029
+ hours = parseInt(h || "0", 10);
1030
+ minutes = parseInt(m || "0", 10);
1031
+ seconds = parseInt(s || "0", 10);
1032
+ period = p || "AM";
1033
+ } else {
1034
+ const [h, m, s] = timeStr.split(":");
1035
+ hours = parseInt(h || "0", 10);
1036
+ minutes = parseInt(m || "0", 10);
1037
+ seconds = parseInt(s || "0", 10);
1038
+ }
1039
+ } catch (e) {
1040
+ console.warn("[IDDS TimePicker] Invalid time format:", timeStr);
1041
+ }
1042
+ return { hours, minutes, seconds, period };
1043
+ }
1044
+ formatTime(h, m, s, p) {
1045
+ const pad = (n) => n.toString().padStart(2, "0");
1046
+ if (this.options.use12Hours) {
1047
+ let displayHours = h;
1048
+ if (displayHours === 0) displayHours = 12;
1049
+ const main = `${pad(displayHours)}:${pad(m)}`;
1050
+ const sec = this.options.showSecond ? `:${pad(s)}` : "";
1051
+ return `${main}${sec} ${p}`;
1052
+ } else {
1053
+ const main = `${pad(h)}:${pad(m)}`;
1054
+ const sec = this.options.showSecond ? `:${pad(s)}` : "";
1055
+ return `${main}${sec}`;
1056
+ }
1057
+ }
1058
+ parseTimeToMinutes(timeStr) {
1059
+ if (!timeStr) return 0;
1060
+ const parts = timeStr.split(":");
1061
+ const hours = parseInt(parts[0] || "0", 10);
1062
+ const minutes = parseInt(parts[1] || "0", 10);
1063
+ if (this.options.use12Hours && timeStr.includes(" ")) {
1064
+ const period = timeStr.split(" ")[1];
1065
+ let adjustedHours = hours;
1066
+ if (period === "PM" && hours !== 12) adjustedHours = hours + 12;
1067
+ else if (period === "AM" && hours === 12) adjustedHours = 0;
1068
+ return adjustedHours * 60 + minutes;
1069
+ }
1070
+ return hours * 60 + minutes;
1071
+ }
1072
+ isTimeDisabled(hours, minutes, seconds, period, checkOptions = {}) {
1073
+ const timeStr = this.formatTime(hours, minutes, seconds, period);
1074
+ const timeInMinutes = this.parseTimeToMinutes(timeStr);
1075
+ if (this.options.disabledBackTime && !checkOptions.ignoreBefore) {
1076
+ const now = /* @__PURE__ */ new Date();
1077
+ const currentTimeInMinutes = now.getHours() * 60 + now.getMinutes();
1078
+ if (timeInMinutes < currentTimeInMinutes) return true;
1079
+ }
1080
+ if (this.options.disabledTimeBefore && !checkOptions.ignoreBefore) {
1081
+ const beforeTimeInMinutes = this.parseTimeToMinutes(
1082
+ this.options.disabledTimeBefore
1083
+ );
1084
+ if (timeInMinutes < beforeTimeInMinutes) return true;
1085
+ }
1086
+ if (this.options.disabledTimeAfter && !checkOptions.ignoreAfter) {
1087
+ const afterTimeInMinutes = this.parseTimeToMinutes(
1088
+ this.options.disabledTimeAfter
1089
+ );
1090
+ if (timeInMinutes > afterTimeInMinutes) return true;
1091
+ }
1092
+ return false;
1093
+ }
1094
+ initDOM() {
1095
+ if (!this.container.classList.contains(`${PREFIX}-time-picker`)) {
1096
+ this.container.classList.add(`${PREFIX}-time-picker`);
1097
+ }
1098
+ if (this.options.disabled) {
1099
+ this.container.classList.add(`${PREFIX}-time-picker--disabled`);
1100
+ }
1101
+ let wrapper = this.container.querySelector(
1102
+ `.${PREFIX}-time-picker__wrapper`
1103
+ );
1104
+ let input = this.container.querySelector(`.${PREFIX}-time-picker__input`);
1105
+ let clearBtn = this.container.querySelector(
1106
+ `.${PREFIX}-time-picker__clear-button`
1107
+ );
1108
+ if (!wrapper) {
1109
+ wrapper = document.createElement("div");
1110
+ wrapper.className = `${PREFIX}-time-picker__wrapper`;
1111
+ const prefixIcon = document.createElement("div");
1112
+ prefixIcon.className = `${PREFIX}-time-picker__prefix-icon`;
1113
+ prefixIcon.innerHTML = this.createIcon("clock");
1114
+ wrapper.appendChild(prefixIcon);
1115
+ input = document.createElement("input");
1116
+ input.type = "text";
1117
+ input.className = `${PREFIX}-time-picker__input ${PREFIX}-time-picker__input--size-md ${PREFIX}-time-picker__input--with-prefix`;
1118
+ if (this.options.allowClear)
1119
+ input.classList.add(`${PREFIX}-time-picker__input--with-suffix`);
1120
+ input.placeholder = this.container.getAttribute("placeholder") || "Select time";
1121
+ if (this.options.disabled) input.disabled = true;
1122
+ if (this.options.readonly) input.readOnly = true;
1123
+ else input.readOnly = true;
1124
+ wrapper.appendChild(input);
1125
+ if (this.options.allowClear) {
1126
+ clearBtn = document.createElement("div");
1127
+ clearBtn.className = `${PREFIX}-time-picker__clear-button`;
1128
+ clearBtn.innerHTML = this.createIcon("x");
1129
+ clearBtn.style.display = "none";
1130
+ wrapper.appendChild(clearBtn);
1131
+ }
1132
+ this.container.appendChild(wrapper);
1133
+ }
1134
+ this.elements.wrapper = wrapper;
1135
+ this.elements.input = input;
1136
+ this.elements.clearBtn = clearBtn;
1137
+ let panel = this.container.querySelector(`.${PREFIX}-time-picker__panel`);
1138
+ if (!panel) {
1139
+ panel = document.createElement("div");
1140
+ panel.className = `${PREFIX}-time-picker__panel`;
1141
+ panel.style.display = "none";
1142
+ this.container.appendChild(panel);
1143
+ }
1144
+ let content = panel.querySelector(`.${PREFIX}-time-picker__content`);
1145
+ if (!content) {
1146
+ content = document.createElement("div");
1147
+ content.className = `${PREFIX}-time-picker__content`;
1148
+ panel.appendChild(content);
1149
+ }
1150
+ let actions = panel.querySelector(`.${PREFIX}-time-picker__actions`);
1151
+ if (!actions) {
1152
+ actions = document.createElement("div");
1153
+ actions.className = `${PREFIX}-time-picker__actions`;
1154
+ if (this.options.showNowButton) {
1155
+ const nowBtn = document.createElement("button");
1156
+ nowBtn.type = "button";
1157
+ nowBtn.className = `${PREFIX}-time-picker__action-button`;
1158
+ nowBtn.textContent = "Sekarang";
1159
+ nowBtn.onclick = (e) => {
766
1160
  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();
1161
+ const now = /* @__PURE__ */ new Date();
1162
+ let p = "AM";
1163
+ let h = now.getHours();
1164
+ if (this.options.use12Hours) {
1165
+ p = h >= 12 ? "PM" : "AM";
1166
+ h = h % 12 || 12;
789
1167
  }
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
- );
1168
+ this.state.currentTime = {
1169
+ hours: h,
1170
+ minutes: now.getMinutes(),
1171
+ seconds: this.options.showSecond ? now.getSeconds() : 0,
1172
+ period: p
1173
+ };
1174
+ this.updateInput();
1175
+ this.close();
801
1176
  };
802
- grid.appendChild(btn);
1177
+ actions.appendChild(nowBtn);
803
1178
  }
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);
1179
+ const confirmBtn = document.createElement("button");
1180
+ confirmBtn.type = "button";
1181
+ confirmBtn.className = `${PREFIX}-time-picker__confirm-button`;
1182
+ confirmBtn.textContent = "Pilih";
1183
+ confirmBtn.onclick = (e) => {
1184
+ e.stopPropagation();
1185
+ this.close();
1186
+ };
1187
+ actions.appendChild(confirmBtn);
1188
+ panel.appendChild(actions);
1189
+ }
1190
+ this.elements.panel = panel;
1191
+ this.elements.content = content;
1192
+ this.elements.actions = actions;
1193
+ }
1194
+ updateInput() {
1195
+ const val = this.formatTime(
1196
+ this.state.currentTime.hours,
1197
+ this.state.currentTime.minutes,
1198
+ this.state.currentTime.seconds,
1199
+ this.state.currentTime.period
1200
+ );
1201
+ this.state.internalValue = val;
1202
+ this.elements.input.value = val;
1203
+ this.container.dataset.value = val;
1204
+ if (this.elements.clearBtn && this.options.allowClear) {
1205
+ this.elements.clearBtn.style.display = val && !this.options.disabled ? "flex" : "none";
1206
+ }
1207
+ this.elements.input.dispatchEvent(new Event("change", { bubbles: true }));
1208
+ if (typeof this.options.onChange === "function") {
1209
+ this.options.onChange(val);
1210
+ }
1211
+ }
1212
+ generateOptions(type) {
1213
+ const options = [];
1214
+ const { use12Hours, hourStep, minuteStep, secondStep } = this.options;
1215
+ let limit = type === "hour" ? use12Hours ? 12 : 24 : 60;
1216
+ let step = type === "hour" ? hourStep : type === "minute" ? minuteStep : secondStep;
1217
+ if (limit === 12) {
1218
+ for (let i = type === "hour" ? 1 : 0; i <= (type === "hour" ? 12 : 59); i += step) {
1219
+ options.push(i);
812
1220
  }
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);
1221
+ } else if (limit === 24) {
1222
+ for (let i = 0; i <= 23; i += step) {
1223
+ options.push(i);
1224
+ }
1225
+ } else {
1226
+ for (let i = 0; i <= 59; i += step) {
1227
+ options.push(i);
828
1228
  }
829
1229
  }
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";
1230
+ return options;
1231
+ }
1232
+ renderColumn(type, optionsArr) {
1233
+ const column = document.createElement("div");
1234
+ column.className = `${PREFIX}-time-picker__column ${PREFIX}-time-picker__column--${type}`;
1235
+ const colContent = document.createElement("div");
1236
+ colContent.className = `${PREFIX}-time-picker__column-content`;
1237
+ column.appendChild(colContent);
1238
+ const { use12Hours } = this.options;
1239
+ const { currentTime } = this.state;
1240
+ optionsArr.forEach((optValue) => {
1241
+ const option = document.createElement("div");
1242
+ option.className = `${PREFIX}-time-picker__option`;
1243
+ let isSelected = false;
1244
+ let isDisabled = false;
1245
+ if (type === "hour") {
1246
+ isSelected = currentTime.hours === optValue || use12Hours && currentTime.hours === 0 && optValue === 12;
1247
+ const hourValue = use12Hours ? optValue === 12 ? 0 : optValue : optValue;
1248
+ const isTooEarly = this.isTimeDisabled(
1249
+ hourValue,
1250
+ 59,
1251
+ 59,
1252
+ use12Hours ? currentTime.period : void 0,
1253
+ { ignoreAfter: true }
1254
+ );
1255
+ const isTooLate = this.isTimeDisabled(
1256
+ hourValue,
1257
+ 0,
1258
+ 0,
1259
+ use12Hours ? currentTime.period : void 0,
1260
+ { ignoreBefore: true }
1261
+ );
1262
+ isDisabled = isTooEarly || isTooLate;
1263
+ } else if (type === "minute") {
1264
+ isSelected = currentTime.minutes === optValue;
1265
+ isDisabled = this.isTimeDisabled(
1266
+ currentTime.hours,
1267
+ optValue,
1268
+ currentTime.seconds,
1269
+ use12Hours ? currentTime.period : void 0
1270
+ );
1271
+ } else if (type === "second") {
1272
+ isSelected = currentTime.seconds === optValue;
1273
+ isDisabled = this.isTimeDisabled(
1274
+ currentTime.hours,
1275
+ currentTime.minutes,
1276
+ optValue,
1277
+ use12Hours ? currentTime.period : void 0
1278
+ );
1279
+ }
1280
+ if (isSelected)
1281
+ option.classList.add(`${PREFIX}-time-picker__option--selected`);
1282
+ if (isDisabled)
1283
+ option.classList.add(`${PREFIX}-time-picker__option--disabled`);
1284
+ option.textContent = optValue.toString().padStart(2, "0");
1285
+ if (!isDisabled) {
1286
+ option.addEventListener("click", (e) => {
1287
+ e.stopPropagation();
1288
+ const val = parseInt(optValue, 10);
1289
+ if (type === "hour") {
1290
+ this.state.currentTime.hours = use12Hours && val === 12 ? 0 : val;
1291
+ } else if (type === "minute") {
1292
+ this.state.currentTime.minutes = val;
1293
+ } else if (type === "second") {
1294
+ this.state.currentTime.seconds = val;
1295
+ }
1296
+ this.updateInput();
1297
+ this.buildPanel();
1298
+ });
1299
+ }
1300
+ colContent.appendChild(option);
1301
+ });
1302
+ return column;
1303
+ }
1304
+ renderPeriodColumn() {
1305
+ const column = document.createElement("div");
1306
+ column.className = `${PREFIX}-time-picker__column ${PREFIX}-time-picker__column--period`;
1307
+ const colContent = document.createElement("div");
1308
+ colContent.className = `${PREFIX}-time-picker__column-content`;
1309
+ column.appendChild(colContent);
1310
+ ["AM", "PM"].forEach((p) => {
1311
+ const option = document.createElement("div");
1312
+ option.className = `${PREFIX}-time-picker__option`;
1313
+ option.textContent = p;
1314
+ if (this.state.currentTime.period === p) {
1315
+ option.classList.add(`${PREFIX}-time-picker__option--selected`);
1316
+ }
1317
+ const isDisabled = this.isTimeDisabled(
1318
+ this.state.currentTime.hours,
1319
+ this.state.currentTime.minutes,
1320
+ this.state.currentTime.seconds,
1321
+ p
1322
+ );
1323
+ if (isDisabled)
1324
+ option.classList.add(`${PREFIX}-time-picker__option--disabled`);
1325
+ if (!isDisabled) {
1326
+ option.addEventListener("click", (e) => {
1327
+ e.stopPropagation();
1328
+ this.state.currentTime.period = p;
1329
+ this.updateInput();
1330
+ this.buildPanel();
1331
+ });
1332
+ }
1333
+ colContent.appendChild(option);
1334
+ });
1335
+ return column;
1336
+ }
1337
+ buildPanel() {
1338
+ this.elements.content.innerHTML = "";
1339
+ const hourOps = this.generateOptions("hour");
1340
+ const minOps = this.generateOptions("minute");
1341
+ this.elements.content.appendChild(this.renderColumn("hour", hourOps));
1342
+ this.elements.content.appendChild(this.renderColumn("minute", minOps));
1343
+ if (this.options.showSecond) {
1344
+ const secOps = this.generateOptions("second");
1345
+ this.elements.content.appendChild(this.renderColumn("second", secOps));
840
1346
  }
841
- function toggle() {
842
- if (isOpen) close();
843
- else open();
1347
+ if (this.options.use12Hours) {
1348
+ this.elements.content.appendChild(this.renderPeriodColumn());
844
1349
  }
845
- trigger.addEventListener("click", (e) => {
846
- toggle();
1350
+ }
1351
+ open() {
1352
+ if (this.options.disabled || this.state.isOpen) return;
1353
+ this.state.isOpen = true;
1354
+ this.container.classList.add(`${PREFIX}-time-picker--open`);
1355
+ this.elements.panel.style.display = "block";
1356
+ this.state.currentTime = this.parseTime(this.elements.input.value);
1357
+ this.buildPanel();
1358
+ document.dispatchEvent(
1359
+ new CustomEvent("closeTimePicker", {
1360
+ detail: { exclude: this.container }
1361
+ })
1362
+ );
1363
+ }
1364
+ close() {
1365
+ this.state.isOpen = false;
1366
+ this.container.classList.remove(`${PREFIX}-time-picker--open`);
1367
+ this.elements.panel.style.display = "none";
1368
+ }
1369
+ toggle() {
1370
+ if (this.state.isOpen) this.close();
1371
+ else this.open();
1372
+ }
1373
+ bindEvents() {
1374
+ this.elements.wrapper.addEventListener("click", (e) => {
1375
+ e.stopPropagation();
1376
+ this.toggle();
847
1377
  });
1378
+ if (this.elements.clearBtn && this.options.allowClear) {
1379
+ this.elements.clearBtn.addEventListener("click", (e) => {
1380
+ e.stopPropagation();
1381
+ this.elements.input.value = "";
1382
+ this.state.currentTime = {
1383
+ hours: 0,
1384
+ minutes: 0,
1385
+ seconds: 0,
1386
+ period: "AM"
1387
+ };
1388
+ this.container.dataset.value = "";
1389
+ this.state.internalValue = "";
1390
+ this.elements.clearBtn.style.display = "none";
1391
+ this.elements.input.dispatchEvent(
1392
+ new Event("change", { bubbles: true })
1393
+ );
1394
+ if (typeof this.options.onChange === "function") {
1395
+ this.options.onChange("");
1396
+ }
1397
+ });
1398
+ }
848
1399
  document.addEventListener("click", (e) => {
849
- if (!datepicker.contains(e.target)) {
850
- close();
851
- }
1400
+ if (!this.container.contains(e.target)) this.close();
1401
+ });
1402
+ document.addEventListener("closeTimePicker", (e) => {
1403
+ if (e.detail && e.detail.exclude !== this.container) this.close();
852
1404
  });
1405
+ }
1406
+ // --- Public API ---
1407
+ getValue() {
1408
+ return this.state.internalValue;
1409
+ }
1410
+ };
1411
+ function initTimepicker(selectorOrElement, options = {}) {
1412
+ const elements = typeof selectorOrElement === "string" ? document.querySelectorAll(selectorOrElement) : selectorOrElement ? typeof selectorOrElement.length !== "undefined" ? selectorOrElement : [selectorOrElement] : document.querySelectorAll(`.${PREFIX}-time-picker`);
1413
+ const instances = [];
1414
+ elements.forEach((container) => {
1415
+ const instance = new TimePicker(container, options);
1416
+ container.__timepickerAPI = instance;
1417
+ instances.push(instance);
853
1418
  });
1419
+ if (instances.length === 0) return null;
1420
+ return instances.length === 1 ? instances[0] : instances;
854
1421
  }
855
1422
 
856
1423
  // src/js/components/stateless/modal.js
@@ -2275,216 +2842,6 @@ var InaUI = (() => {
2275
2842
  });
2276
2843
  }
2277
2844
 
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
2845
  // src/js/components/stateful/chip.js
2489
2846
  var PREFIX4 = "ina";
2490
2847
  function initChip(rootSelector = `.${PREFIX4}-chip`) {
@@ -3784,6 +4141,7 @@ var InaUI = (() => {
3784
4141
  initButtonGroup();
3785
4142
  initCheckbox();
3786
4143
  initDatepicker();
4144
+ initTimepicker();
3787
4145
  initDropdown();
3788
4146
  initFileUpload();
3789
4147
  initSingleFileUpload();
@@ -3795,7 +4153,6 @@ var InaUI = (() => {
3795
4153
  initRadioButton();
3796
4154
  initStepper();
3797
4155
  initTab();
3798
- initTimepicker();
3799
4156
  initToggle();
3800
4157
  initPagination();
3801
4158
  initSelectDropdown();