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