@idds/js 1.2.2 → 1.2.4

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 +217 -101
  2. package/dist/index.js +217 -101
  3. package/package.json +1 -1
@@ -297,6 +297,7 @@ var InaUI = (() => {
297
297
  this.index = this.group.registerItem(this);
298
298
  }
299
299
  this.toggle.addEventListener("click", (e) => this.handleClick(e));
300
+ this.toggle.addEventListener("keydown", (e) => this.handleKeyDown(e));
300
301
  if (this.group) {
301
302
  const isOpen = this.group.isItemOpen(this.index);
302
303
  this.setOpenState(isOpen);
@@ -325,6 +326,22 @@ var InaUI = (() => {
325
326
  this.setOpenState(nextState);
326
327
  }
327
328
  }
329
+ handleKeyDown(e) {
330
+ if (e.key === "ArrowDown" || e.key === "ArrowUp") {
331
+ e.preventDefault();
332
+ const currentAccordion = this.element;
333
+ const container = currentAccordion.closest(".ina-accordion-group") || currentAccordion.parentElement;
334
+ if (!container) return;
335
+ const toggles = Array.from(
336
+ container.querySelectorAll(".ina-accordion__toggle:not([disabled])")
337
+ );
338
+ const currentIndex = toggles.indexOf(this.toggle);
339
+ if (currentIndex > -1) {
340
+ const nextIndex = e.key === "ArrowDown" ? (currentIndex + 1) % toggles.length : (currentIndex - 1 + toggles.length) % toggles.length;
341
+ toggles[nextIndex]?.focus();
342
+ }
343
+ }
344
+ }
328
345
  setOpenState(isOpen) {
329
346
  if (isOpen) {
330
347
  this.element.classList.add(`${PREFIX}-accordion--open`);
@@ -392,6 +409,11 @@ var InaUI = (() => {
392
409
  };
393
410
  this.state = {
394
411
  viewDate: /* @__PURE__ */ new Date(),
412
+ nextViewDate: (() => {
413
+ const next = /* @__PURE__ */ new Date();
414
+ next.setMonth(next.getMonth() + 1);
415
+ return next;
416
+ })(),
395
417
  selectedDate: null,
396
418
  selectedDates: [],
397
419
  rangeDate: [null, null],
@@ -444,7 +466,7 @@ var InaUI = (() => {
444
466
  }
445
467
  return false;
446
468
  }
447
- createIcon(name, size = 16) {
469
+ createIcon(name, size = 20) {
448
470
  if (name === "chevron-left")
449
471
  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>`;
450
472
  if (name === "chevron-right")
@@ -453,6 +475,90 @@ var InaUI = (() => {
453
475
  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>`;
454
476
  return "";
455
477
  }
478
+ isLeftGreaterThanRight(leftDate, rightDate) {
479
+ const leftYear = leftDate.getFullYear();
480
+ const leftMonth = leftDate.getMonth();
481
+ const rightYear = rightDate.getFullYear();
482
+ const rightMonth = rightDate.getMonth();
483
+ return leftYear > rightYear || leftYear === rightYear && leftMonth >= rightMonth;
484
+ }
485
+ navigateMonth(isNextMonth, direction) {
486
+ const { mode } = this.options;
487
+ if (isNextMonth) {
488
+ const newDate = new Date(this.state.nextViewDate);
489
+ if (direction === "prev") {
490
+ newDate.setMonth(newDate.getMonth() - 1);
491
+ } else {
492
+ newDate.setMonth(newDate.getMonth() + 1);
493
+ }
494
+ if (mode !== "single" && this.isLeftGreaterThanRight(this.state.viewDate, newDate)) {
495
+ const adjustedLeft = new Date(newDate);
496
+ adjustedLeft.setMonth(adjustedLeft.getMonth() - 1);
497
+ this.state.viewDate = adjustedLeft;
498
+ }
499
+ this.state.nextViewDate = newDate;
500
+ } else {
501
+ const newDate = new Date(this.state.viewDate);
502
+ if (direction === "prev") {
503
+ newDate.setMonth(newDate.getMonth() - 1);
504
+ } else {
505
+ newDate.setMonth(newDate.getMonth() + 1);
506
+ }
507
+ if (mode !== "single" && this.isLeftGreaterThanRight(newDate, this.state.nextViewDate)) {
508
+ const adjustedRight = new Date(newDate);
509
+ adjustedRight.setMonth(adjustedRight.getMonth() + 1);
510
+ this.state.nextViewDate = adjustedRight;
511
+ }
512
+ this.state.viewDate = newDate;
513
+ }
514
+ this.renderPanel();
515
+ }
516
+ setMonthExact(isNextMonth, m) {
517
+ const { mode } = this.options;
518
+ if (isNextMonth) {
519
+ const newDate = new Date(this.state.nextViewDate);
520
+ newDate.setMonth(m);
521
+ if (mode !== "single" && this.isLeftGreaterThanRight(this.state.viewDate, newDate)) {
522
+ const adjustedLeft = new Date(newDate);
523
+ adjustedLeft.setMonth(adjustedLeft.getMonth() - 1);
524
+ this.state.viewDate = adjustedLeft;
525
+ }
526
+ this.state.nextViewDate = newDate;
527
+ } else {
528
+ const newDate = new Date(this.state.viewDate);
529
+ newDate.setMonth(m);
530
+ if (mode !== "single" && this.isLeftGreaterThanRight(newDate, this.state.nextViewDate)) {
531
+ const adjustedRight = new Date(newDate);
532
+ adjustedRight.setMonth(adjustedRight.getMonth() + 1);
533
+ this.state.nextViewDate = adjustedRight;
534
+ }
535
+ this.state.viewDate = newDate;
536
+ }
537
+ this.renderPanel();
538
+ }
539
+ setYearExact(isNextMonth, y) {
540
+ const { mode } = this.options;
541
+ if (isNextMonth) {
542
+ const newDate = new Date(this.state.nextViewDate);
543
+ newDate.setFullYear(y);
544
+ if (mode !== "single" && this.isLeftGreaterThanRight(this.state.viewDate, newDate)) {
545
+ const adjustedLeft = new Date(newDate);
546
+ adjustedLeft.setMonth(adjustedLeft.getMonth() - 1);
547
+ this.state.viewDate = adjustedLeft;
548
+ }
549
+ this.state.nextViewDate = newDate;
550
+ } else {
551
+ const newDate = new Date(this.state.viewDate);
552
+ newDate.setFullYear(y);
553
+ if (mode !== "single" && this.isLeftGreaterThanRight(newDate, this.state.nextViewDate)) {
554
+ const adjustedRight = new Date(newDate);
555
+ adjustedRight.setMonth(adjustedRight.getMonth() + 1);
556
+ this.state.nextViewDate = adjustedRight;
557
+ }
558
+ this.state.viewDate = newDate;
559
+ }
560
+ this.renderPanel();
561
+ }
456
562
  initDOM() {
457
563
  if (!this.container.classList.contains(`${PREFIX}-date-picker`)) {
458
564
  this.container.classList.add(`${PREFIX}-date-picker`);
@@ -718,84 +824,57 @@ var InaUI = (() => {
718
824
  container.className = !isNextMonth ? `${PREFIX}-date-picker__calendar-container` : `${PREFIX}-date-picker__calendar`;
719
825
  const header = document.createElement("div");
720
826
  header.className = isNextMonth ? `${PREFIX}-date-picker__next-month-header` : `${PREFIX}-date-picker__calendar-header`;
721
- if (!isNextMonth) {
722
- const prevBtn = document.createElement("button");
723
- prevBtn.type = "button";
724
- prevBtn.className = `${PREFIX}-date-picker__nav-button`;
725
- prevBtn.innerHTML = this.createIcon("chevron-left");
726
- prevBtn.onclick = (e) => {
827
+ const prevBtn = document.createElement("button");
828
+ prevBtn.type = "button";
829
+ prevBtn.className = `${PREFIX}-date-picker__nav-button`;
830
+ prevBtn.innerHTML = this.createIcon("chevron-left");
831
+ prevBtn.onclick = (e) => {
832
+ e.stopPropagation();
833
+ this.navigateMonth(isNextMonth, "prev");
834
+ };
835
+ prevBtn.onkeydown = (e) => {
836
+ if (e.key === "Enter" || e.key === " ") {
837
+ e.preventDefault();
727
838
  e.stopPropagation();
728
- this.state.viewDate.setMonth(this.state.viewDate.getMonth() - 1);
729
- this.renderPanel();
730
- };
731
- prevBtn.onkeydown = (e) => {
732
- if (e.key === "Enter" || e.key === " ") {
733
- e.preventDefault();
734
- e.stopPropagation();
735
- this.state.viewDate.setMonth(this.state.viewDate.getMonth() - 1);
736
- this.renderPanel();
737
- }
738
- };
739
- header.appendChild(prevBtn);
740
- } else {
741
- const spacer = document.createElement("div");
742
- spacer.style.width = "32px";
743
- header.appendChild(spacer);
744
- }
839
+ this.navigateMonth(isNextMonth, "prev");
840
+ }
841
+ };
842
+ header.appendChild(prevBtn);
745
843
  const controls = document.createElement("div");
746
844
  controls.className = `${PREFIX}-date-picker__header-controls`;
747
845
  const monthCont = document.createElement("div");
748
846
  monthCont.className = `${PREFIX}-date-picker__dropdown-container`;
749
847
  const monthPicker = this.createMonthPicker(month, (m) => {
750
- if (isNextMonth) {
751
- this.state.viewDate = new Date(year, m - 1, 1);
752
- } else {
753
- this.state.viewDate.setMonth(m);
754
- }
755
- this.renderPanel();
848
+ this.setMonthExact(isNextMonth, m);
756
849
  });
757
850
  monthCont.appendChild(monthPicker.element);
758
851
  const yearCont = document.createElement("div");
759
852
  yearCont.className = `${PREFIX}-date-picker__dropdown-container`;
760
853
  const yearPicker = this.createYearPicker(year, (y) => {
761
- if (isNextMonth) {
762
- this.state.viewDate = new Date(y, month - 1, 1);
763
- } else {
764
- this.state.viewDate.setFullYear(y);
765
- }
766
- this.renderPanel();
854
+ this.setYearExact(isNextMonth, y);
767
855
  });
768
856
  yearCont.appendChild(yearPicker.element);
769
857
  controls.append(monthCont, yearCont);
770
858
  header.appendChild(controls);
771
- const showNextBtn = true;
772
- if (showNextBtn) {
773
- const nextBtn = document.createElement("button");
774
- nextBtn.type = "button";
775
- nextBtn.className = `${PREFIX}-date-picker__nav-button`;
776
- if (!isNextMonth && (mode === "range" || mode === "multiple")) {
777
- nextBtn.classList.add(`${PREFIX}-date-picker__nav-button--mobile-only`);
778
- }
779
- nextBtn.innerHTML = this.createIcon("chevron-right");
780
- nextBtn.onclick = (e) => {
781
- e.stopPropagation();
782
- this.state.viewDate.setMonth(this.state.viewDate.getMonth() + 1);
783
- this.renderPanel();
784
- };
785
- nextBtn.onkeydown = (e) => {
786
- if (e.key === "Enter" || e.key === " ") {
787
- e.preventDefault();
788
- e.stopPropagation();
789
- this.state.viewDate.setMonth(this.state.viewDate.getMonth() + 1);
790
- this.renderPanel();
791
- }
792
- };
793
- header.appendChild(nextBtn);
794
- } else if (!isNextMonth) {
795
- const spacer = document.createElement("div");
796
- spacer.style.width = "32px";
797
- header.appendChild(spacer);
859
+ const nextBtn = document.createElement("button");
860
+ nextBtn.type = "button";
861
+ nextBtn.className = `${PREFIX}-date-picker__nav-button`;
862
+ if (!isNextMonth && (mode === "range" || mode === "multiple")) {
863
+ nextBtn.classList.add(`${PREFIX}-date-picker__nav-button--mobile-only`);
798
864
  }
865
+ nextBtn.innerHTML = this.createIcon("chevron-right");
866
+ nextBtn.onclick = (e) => {
867
+ e.stopPropagation();
868
+ this.navigateMonth(isNextMonth, "next");
869
+ };
870
+ nextBtn.onkeydown = (e) => {
871
+ if (e.key === "Enter" || e.key === " ") {
872
+ e.preventDefault();
873
+ e.stopPropagation();
874
+ this.navigateMonth(isNextMonth, "next");
875
+ }
876
+ };
877
+ header.appendChild(nextBtn);
799
878
  const grid = document.createElement("div");
800
879
  grid.className = `${PREFIX}-date-picker__calendar-grid`;
801
880
  this.DAYS_SHORT.forEach((d) => {
@@ -937,12 +1016,7 @@ var InaUI = (() => {
937
1016
  const cal1 = this.renderCalendarGrid(this.state.viewDate);
938
1017
  this.elements.panelContent.appendChild(cal1);
939
1018
  if (this.options.mode === "range" || this.options.mode === "multiple") {
940
- const nextMonthDate = new Date(
941
- this.state.viewDate.getFullYear(),
942
- this.state.viewDate.getMonth() + 1,
943
- 1
944
- );
945
- const cal2 = this.renderCalendarGrid(nextMonthDate, true);
1019
+ const cal2 = this.renderCalendarGrid(this.state.nextViewDate, true);
946
1020
  this.elements.panelContent.appendChild(cal2);
947
1021
  }
948
1022
  }
@@ -3026,13 +3100,29 @@ var InaUI = (() => {
3026
3100
  );
3027
3101
  if (!input) {
3028
3102
  customFieldContainer.innerHTML = `
3029
- <div class="${PREFIX4}-text-field ${PREFIX4}-text-field--size-medium ${PREFIX4}-text-field--variant-outline ${PREFIX4}-chip__input">
3030
- <div class="${PREFIX4}-text-field__wrapper">
3031
- <input type="text" class="${PREFIX4}-text-field__input" placeholder="Masukkan data yang Anda inginkan" value="${!isStandard ? primaryCustomValue : ""}" />
3032
- </div>
3103
+ <div class="${PREFIX4}-chip__input-wrapper">
3104
+ <input type="text" class="${PREFIX4}-chip__input" placeholder="Masukkan data yang Anda inginkan" value="${!isStandard ? primaryCustomValue : ""}" />
3105
+ <button type="button" class="${PREFIX4}-chip__clear-button" aria-label="Clear input" style="display: ${!isStandard && primaryCustomValue ? "inline-flex" : "none"};">
3106
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="${PREFIX4}-chip__clear-icon">
3107
+ <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
3108
+ <path d="M18 6l-12 12"></path>
3109
+ <path d="M6 6l12 12"></path>
3110
+ </svg>
3111
+ </button>
3033
3112
  </div>
3034
3113
  `;
3035
3114
  input = customFieldContainer.querySelector("input");
3115
+ const clearBtn = customFieldContainer.querySelector(
3116
+ ".ina-chip__clear-button"
3117
+ );
3118
+ input.addEventListener("input", (e) => {
3119
+ clearBtn.style.display = e.target.value ? "inline-flex" : "none";
3120
+ });
3121
+ clearBtn.addEventListener("click", () => {
3122
+ input.value = "";
3123
+ clearBtn.style.display = "none";
3124
+ commitCustomValue(input);
3125
+ });
3036
3126
  input.addEventListener("blur", (e) => {
3037
3127
  commitCustomValue(e.target);
3038
3128
  });
@@ -3114,6 +3204,10 @@ var InaUI = (() => {
3114
3204
  if (!normSelected.includes(finalValue)) {
3115
3205
  normSelected.push(finalValue);
3116
3206
  }
3207
+ } else {
3208
+ if (toggleVal) {
3209
+ normSelected = normSelected.filter((v) => v !== toggleVal);
3210
+ }
3117
3211
  }
3118
3212
  if (isMultiple) {
3119
3213
  selectedValue = normSelected.join(",");
@@ -3134,38 +3228,12 @@ var InaUI = (() => {
3134
3228
  const val = item.getAttribute("data-value");
3135
3229
  if (showCustomization && isToggleBtn(item)) {
3136
3230
  const normSelected = getNormalizedSelected();
3137
- let newSelected = [...normSelected];
3138
3231
  const standardValues = Array.from(items).filter((i) => !isToggleBtn(i)).map((i) => i.getAttribute("data-value"));
3139
3232
  const customValues = normSelected.filter(
3140
3233
  (v) => !standardValues.includes(v) && v !== "" && v !== val
3141
3234
  );
3142
- const primaryCustomValue = customValues[customValues.length - 1];
3143
3235
  const isInputVisible = normSelected.includes(val) || customValues.length > 0;
3144
- if (isInputVisible) {
3145
- newSelected = newSelected.filter((v) => v !== val);
3146
- if (primaryCustomValue) {
3147
- if (isMultiple) {
3148
- newSelected = newSelected.filter(
3149
- (v) => v !== primaryCustomValue
3150
- );
3151
- } else {
3152
- newSelected = [];
3153
- }
3154
- }
3155
- if (isMultiple) {
3156
- selectedValue = newSelected.join(",");
3157
- } else {
3158
- selectedValue = newSelected.length ? newSelected[0] : "";
3159
- }
3160
- updateUI();
3161
- const changeEvent = new CustomEvent(`${PREFIX4}-chip:change`, {
3162
- detail: {
3163
- value: isMultiple ? getNormalizedSelected() : selectedValue
3164
- },
3165
- bubbles: true
3166
- });
3167
- container.dispatchEvent(changeEvent);
3168
- } else {
3236
+ if (!isInputVisible) {
3169
3237
  handleSelect(val);
3170
3238
  }
3171
3239
  } else {
@@ -3385,6 +3453,28 @@ var InaUI = (() => {
3385
3453
  lastBtn.addEventListener("click", () => {
3386
3454
  if (!isDisabled && currentPage < totalPages) goToPage(totalPages);
3387
3455
  });
3456
+ if (navButtonsContainer && !navButtonsContainer.__inaKeyboardSet) {
3457
+ navButtonsContainer.addEventListener("keydown", (e) => {
3458
+ if (e.key === "ArrowRight" || e.key === "ArrowLeft") {
3459
+ const focusable = Array.from(
3460
+ navButtonsContainer.querySelectorAll("button:not([disabled])")
3461
+ );
3462
+ if (!focusable.length) return;
3463
+ const currentIndex = focusable.indexOf(document.activeElement);
3464
+ if (currentIndex >= 0) {
3465
+ e.preventDefault();
3466
+ const nextIndex = e.key === "ArrowRight" ? (currentIndex + 1) % focusable.length : (currentIndex - 1 + focusable.length) % focusable.length;
3467
+ focusable[nextIndex]?.focus();
3468
+ }
3469
+ } else if (e.key === "Enter" || e.key === " ") {
3470
+ if (document.activeElement && document.activeElement.tagName === "BUTTON") {
3471
+ e.preventDefault();
3472
+ document.activeElement.click();
3473
+ }
3474
+ }
3475
+ });
3476
+ navButtonsContainer.__inaKeyboardSet = true;
3477
+ }
3388
3478
  if (pageSizeSelect) {
3389
3479
  pageSizeSelect.addEventListener("change", (e) => {
3390
3480
  if (isDisabled) return;
@@ -4589,13 +4679,39 @@ var InaUI = (() => {
4589
4679
  })
4590
4680
  );
4591
4681
  };
4592
- buttons.forEach((button) => {
4682
+ buttons.forEach((button, index2) => {
4593
4683
  button.addEventListener("click", (e) => {
4594
4684
  if (button.type !== "submit") {
4595
4685
  e.preventDefault();
4596
4686
  }
4597
4687
  updateState(button);
4598
4688
  });
4689
+ button.addEventListener("keydown", (e) => {
4690
+ const isDisabled = button.hasAttribute("disabled") || button.classList.contains(`${PREFIX}-button-group__button--disabled`);
4691
+ if (isDisabled) return;
4692
+ if (e.key === "Enter" || e.key === " ") {
4693
+ e.preventDefault();
4694
+ updateState(button);
4695
+ } else if (e.key === "ArrowRight" || e.key === "ArrowDown") {
4696
+ e.preventDefault();
4697
+ let nextIndex = (index2 + 1) % buttons.length;
4698
+ while ((buttons[nextIndex].hasAttribute("disabled") || buttons[nextIndex].classList.contains(
4699
+ `${PREFIX}-button-group__button--disabled`
4700
+ )) && nextIndex !== index2) {
4701
+ nextIndex = (nextIndex + 1) % buttons.length;
4702
+ }
4703
+ buttons[nextIndex]?.focus();
4704
+ } else if (e.key === "ArrowLeft" || e.key === "ArrowUp") {
4705
+ e.preventDefault();
4706
+ let prevIndex = (index2 - 1 + buttons.length) % buttons.length;
4707
+ while ((buttons[prevIndex].hasAttribute("disabled") || buttons[prevIndex].classList.contains(
4708
+ `${PREFIX}-button-group__button--disabled`
4709
+ )) && prevIndex !== index2) {
4710
+ prevIndex = (prevIndex - 1 + buttons.length) % buttons.length;
4711
+ }
4712
+ buttons[prevIndex]?.focus();
4713
+ }
4714
+ });
4599
4715
  });
4600
4716
  buttonGroup.__inaButtonGroupInitialized = true;
4601
4717
  });
package/dist/index.js CHANGED
@@ -29,13 +29,39 @@ function initButtonGroup(rootSelector = `.${PREFIX}-button-group`) {
29
29
  })
30
30
  );
31
31
  };
32
- buttons.forEach((button) => {
32
+ buttons.forEach((button, index2) => {
33
33
  button.addEventListener("click", (e) => {
34
34
  if (button.type !== "submit") {
35
35
  e.preventDefault();
36
36
  }
37
37
  updateState(button);
38
38
  });
39
+ button.addEventListener("keydown", (e) => {
40
+ const isDisabled = button.hasAttribute("disabled") || button.classList.contains(`${PREFIX}-button-group__button--disabled`);
41
+ if (isDisabled) return;
42
+ if (e.key === "Enter" || e.key === " ") {
43
+ e.preventDefault();
44
+ updateState(button);
45
+ } else if (e.key === "ArrowRight" || e.key === "ArrowDown") {
46
+ e.preventDefault();
47
+ let nextIndex = (index2 + 1) % buttons.length;
48
+ while ((buttons[nextIndex].hasAttribute("disabled") || buttons[nextIndex].classList.contains(
49
+ `${PREFIX}-button-group__button--disabled`
50
+ )) && nextIndex !== index2) {
51
+ nextIndex = (nextIndex + 1) % buttons.length;
52
+ }
53
+ buttons[nextIndex]?.focus();
54
+ } else if (e.key === "ArrowLeft" || e.key === "ArrowUp") {
55
+ e.preventDefault();
56
+ let prevIndex = (index2 - 1 + buttons.length) % buttons.length;
57
+ while ((buttons[prevIndex].hasAttribute("disabled") || buttons[prevIndex].classList.contains(
58
+ `${PREFIX}-button-group__button--disabled`
59
+ )) && prevIndex !== index2) {
60
+ prevIndex = (prevIndex - 1 + buttons.length) % buttons.length;
61
+ }
62
+ buttons[prevIndex]?.focus();
63
+ }
64
+ });
39
65
  });
40
66
  buttonGroup.__inaButtonGroupInitialized = true;
41
67
  });
@@ -285,6 +311,7 @@ var Accordion = class {
285
311
  this.index = this.group.registerItem(this);
286
312
  }
287
313
  this.toggle.addEventListener("click", (e) => this.handleClick(e));
314
+ this.toggle.addEventListener("keydown", (e) => this.handleKeyDown(e));
288
315
  if (this.group) {
289
316
  const isOpen = this.group.isItemOpen(this.index);
290
317
  this.setOpenState(isOpen);
@@ -313,6 +340,22 @@ var Accordion = class {
313
340
  this.setOpenState(nextState);
314
341
  }
315
342
  }
343
+ handleKeyDown(e) {
344
+ if (e.key === "ArrowDown" || e.key === "ArrowUp") {
345
+ e.preventDefault();
346
+ const currentAccordion = this.element;
347
+ const container = currentAccordion.closest(".ina-accordion-group") || currentAccordion.parentElement;
348
+ if (!container) return;
349
+ const toggles = Array.from(
350
+ container.querySelectorAll(".ina-accordion__toggle:not([disabled])")
351
+ );
352
+ const currentIndex = toggles.indexOf(this.toggle);
353
+ if (currentIndex > -1) {
354
+ const nextIndex = e.key === "ArrowDown" ? (currentIndex + 1) % toggles.length : (currentIndex - 1 + toggles.length) % toggles.length;
355
+ toggles[nextIndex]?.focus();
356
+ }
357
+ }
358
+ }
316
359
  setOpenState(isOpen) {
317
360
  if (isOpen) {
318
361
  this.element.classList.add(`${PREFIX}-accordion--open`);
@@ -380,6 +423,11 @@ var DatePicker = class {
380
423
  };
381
424
  this.state = {
382
425
  viewDate: /* @__PURE__ */ new Date(),
426
+ nextViewDate: (() => {
427
+ const next = /* @__PURE__ */ new Date();
428
+ next.setMonth(next.getMonth() + 1);
429
+ return next;
430
+ })(),
383
431
  selectedDate: null,
384
432
  selectedDates: [],
385
433
  rangeDate: [null, null],
@@ -432,7 +480,7 @@ var DatePicker = class {
432
480
  }
433
481
  return false;
434
482
  }
435
- createIcon(name, size = 16) {
483
+ createIcon(name, size = 20) {
436
484
  if (name === "chevron-left")
437
485
  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
486
  if (name === "chevron-right")
@@ -441,6 +489,90 @@ var DatePicker = class {
441
489
  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
490
  return "";
443
491
  }
492
+ isLeftGreaterThanRight(leftDate, rightDate) {
493
+ const leftYear = leftDate.getFullYear();
494
+ const leftMonth = leftDate.getMonth();
495
+ const rightYear = rightDate.getFullYear();
496
+ const rightMonth = rightDate.getMonth();
497
+ return leftYear > rightYear || leftYear === rightYear && leftMonth >= rightMonth;
498
+ }
499
+ navigateMonth(isNextMonth, direction) {
500
+ const { mode } = this.options;
501
+ if (isNextMonth) {
502
+ const newDate = new Date(this.state.nextViewDate);
503
+ if (direction === "prev") {
504
+ newDate.setMonth(newDate.getMonth() - 1);
505
+ } else {
506
+ newDate.setMonth(newDate.getMonth() + 1);
507
+ }
508
+ if (mode !== "single" && this.isLeftGreaterThanRight(this.state.viewDate, newDate)) {
509
+ const adjustedLeft = new Date(newDate);
510
+ adjustedLeft.setMonth(adjustedLeft.getMonth() - 1);
511
+ this.state.viewDate = adjustedLeft;
512
+ }
513
+ this.state.nextViewDate = newDate;
514
+ } else {
515
+ const newDate = new Date(this.state.viewDate);
516
+ if (direction === "prev") {
517
+ newDate.setMonth(newDate.getMonth() - 1);
518
+ } else {
519
+ newDate.setMonth(newDate.getMonth() + 1);
520
+ }
521
+ if (mode !== "single" && this.isLeftGreaterThanRight(newDate, this.state.nextViewDate)) {
522
+ const adjustedRight = new Date(newDate);
523
+ adjustedRight.setMonth(adjustedRight.getMonth() + 1);
524
+ this.state.nextViewDate = adjustedRight;
525
+ }
526
+ this.state.viewDate = newDate;
527
+ }
528
+ this.renderPanel();
529
+ }
530
+ setMonthExact(isNextMonth, m) {
531
+ const { mode } = this.options;
532
+ if (isNextMonth) {
533
+ const newDate = new Date(this.state.nextViewDate);
534
+ newDate.setMonth(m);
535
+ if (mode !== "single" && this.isLeftGreaterThanRight(this.state.viewDate, newDate)) {
536
+ const adjustedLeft = new Date(newDate);
537
+ adjustedLeft.setMonth(adjustedLeft.getMonth() - 1);
538
+ this.state.viewDate = adjustedLeft;
539
+ }
540
+ this.state.nextViewDate = newDate;
541
+ } else {
542
+ const newDate = new Date(this.state.viewDate);
543
+ newDate.setMonth(m);
544
+ if (mode !== "single" && this.isLeftGreaterThanRight(newDate, this.state.nextViewDate)) {
545
+ const adjustedRight = new Date(newDate);
546
+ adjustedRight.setMonth(adjustedRight.getMonth() + 1);
547
+ this.state.nextViewDate = adjustedRight;
548
+ }
549
+ this.state.viewDate = newDate;
550
+ }
551
+ this.renderPanel();
552
+ }
553
+ setYearExact(isNextMonth, y) {
554
+ const { mode } = this.options;
555
+ if (isNextMonth) {
556
+ const newDate = new Date(this.state.nextViewDate);
557
+ newDate.setFullYear(y);
558
+ if (mode !== "single" && this.isLeftGreaterThanRight(this.state.viewDate, newDate)) {
559
+ const adjustedLeft = new Date(newDate);
560
+ adjustedLeft.setMonth(adjustedLeft.getMonth() - 1);
561
+ this.state.viewDate = adjustedLeft;
562
+ }
563
+ this.state.nextViewDate = newDate;
564
+ } else {
565
+ const newDate = new Date(this.state.viewDate);
566
+ newDate.setFullYear(y);
567
+ if (mode !== "single" && this.isLeftGreaterThanRight(newDate, this.state.nextViewDate)) {
568
+ const adjustedRight = new Date(newDate);
569
+ adjustedRight.setMonth(adjustedRight.getMonth() + 1);
570
+ this.state.nextViewDate = adjustedRight;
571
+ }
572
+ this.state.viewDate = newDate;
573
+ }
574
+ this.renderPanel();
575
+ }
444
576
  initDOM() {
445
577
  if (!this.container.classList.contains(`${PREFIX}-date-picker`)) {
446
578
  this.container.classList.add(`${PREFIX}-date-picker`);
@@ -706,84 +838,57 @@ var DatePicker = class {
706
838
  container.className = !isNextMonth ? `${PREFIX}-date-picker__calendar-container` : `${PREFIX}-date-picker__calendar`;
707
839
  const header = document.createElement("div");
708
840
  header.className = isNextMonth ? `${PREFIX}-date-picker__next-month-header` : `${PREFIX}-date-picker__calendar-header`;
709
- if (!isNextMonth) {
710
- const prevBtn = document.createElement("button");
711
- prevBtn.type = "button";
712
- prevBtn.className = `${PREFIX}-date-picker__nav-button`;
713
- prevBtn.innerHTML = this.createIcon("chevron-left");
714
- prevBtn.onclick = (e) => {
841
+ const prevBtn = document.createElement("button");
842
+ prevBtn.type = "button";
843
+ prevBtn.className = `${PREFIX}-date-picker__nav-button`;
844
+ prevBtn.innerHTML = this.createIcon("chevron-left");
845
+ prevBtn.onclick = (e) => {
846
+ e.stopPropagation();
847
+ this.navigateMonth(isNextMonth, "prev");
848
+ };
849
+ prevBtn.onkeydown = (e) => {
850
+ if (e.key === "Enter" || e.key === " ") {
851
+ e.preventDefault();
715
852
  e.stopPropagation();
716
- this.state.viewDate.setMonth(this.state.viewDate.getMonth() - 1);
717
- this.renderPanel();
718
- };
719
- prevBtn.onkeydown = (e) => {
720
- if (e.key === "Enter" || e.key === " ") {
721
- e.preventDefault();
722
- e.stopPropagation();
723
- this.state.viewDate.setMonth(this.state.viewDate.getMonth() - 1);
724
- this.renderPanel();
725
- }
726
- };
727
- header.appendChild(prevBtn);
728
- } else {
729
- const spacer = document.createElement("div");
730
- spacer.style.width = "32px";
731
- header.appendChild(spacer);
732
- }
853
+ this.navigateMonth(isNextMonth, "prev");
854
+ }
855
+ };
856
+ header.appendChild(prevBtn);
733
857
  const controls = document.createElement("div");
734
858
  controls.className = `${PREFIX}-date-picker__header-controls`;
735
859
  const monthCont = document.createElement("div");
736
860
  monthCont.className = `${PREFIX}-date-picker__dropdown-container`;
737
861
  const monthPicker = this.createMonthPicker(month, (m) => {
738
- if (isNextMonth) {
739
- this.state.viewDate = new Date(year, m - 1, 1);
740
- } else {
741
- this.state.viewDate.setMonth(m);
742
- }
743
- this.renderPanel();
862
+ this.setMonthExact(isNextMonth, m);
744
863
  });
745
864
  monthCont.appendChild(monthPicker.element);
746
865
  const yearCont = document.createElement("div");
747
866
  yearCont.className = `${PREFIX}-date-picker__dropdown-container`;
748
867
  const yearPicker = this.createYearPicker(year, (y) => {
749
- if (isNextMonth) {
750
- this.state.viewDate = new Date(y, month - 1, 1);
751
- } else {
752
- this.state.viewDate.setFullYear(y);
753
- }
754
- this.renderPanel();
868
+ this.setYearExact(isNextMonth, y);
755
869
  });
756
870
  yearCont.appendChild(yearPicker.element);
757
871
  controls.append(monthCont, yearCont);
758
872
  header.appendChild(controls);
759
- const showNextBtn = true;
760
- if (showNextBtn) {
761
- const nextBtn = document.createElement("button");
762
- nextBtn.type = "button";
763
- nextBtn.className = `${PREFIX}-date-picker__nav-button`;
764
- if (!isNextMonth && (mode === "range" || mode === "multiple")) {
765
- nextBtn.classList.add(`${PREFIX}-date-picker__nav-button--mobile-only`);
766
- }
767
- nextBtn.innerHTML = this.createIcon("chevron-right");
768
- nextBtn.onclick = (e) => {
769
- e.stopPropagation();
770
- this.state.viewDate.setMonth(this.state.viewDate.getMonth() + 1);
771
- this.renderPanel();
772
- };
773
- nextBtn.onkeydown = (e) => {
774
- if (e.key === "Enter" || e.key === " ") {
775
- e.preventDefault();
776
- e.stopPropagation();
777
- this.state.viewDate.setMonth(this.state.viewDate.getMonth() + 1);
778
- this.renderPanel();
779
- }
780
- };
781
- header.appendChild(nextBtn);
782
- } else if (!isNextMonth) {
783
- const spacer = document.createElement("div");
784
- spacer.style.width = "32px";
785
- header.appendChild(spacer);
873
+ const nextBtn = document.createElement("button");
874
+ nextBtn.type = "button";
875
+ nextBtn.className = `${PREFIX}-date-picker__nav-button`;
876
+ if (!isNextMonth && (mode === "range" || mode === "multiple")) {
877
+ nextBtn.classList.add(`${PREFIX}-date-picker__nav-button--mobile-only`);
786
878
  }
879
+ nextBtn.innerHTML = this.createIcon("chevron-right");
880
+ nextBtn.onclick = (e) => {
881
+ e.stopPropagation();
882
+ this.navigateMonth(isNextMonth, "next");
883
+ };
884
+ nextBtn.onkeydown = (e) => {
885
+ if (e.key === "Enter" || e.key === " ") {
886
+ e.preventDefault();
887
+ e.stopPropagation();
888
+ this.navigateMonth(isNextMonth, "next");
889
+ }
890
+ };
891
+ header.appendChild(nextBtn);
787
892
  const grid = document.createElement("div");
788
893
  grid.className = `${PREFIX}-date-picker__calendar-grid`;
789
894
  this.DAYS_SHORT.forEach((d) => {
@@ -925,12 +1030,7 @@ var DatePicker = class {
925
1030
  const cal1 = this.renderCalendarGrid(this.state.viewDate);
926
1031
  this.elements.panelContent.appendChild(cal1);
927
1032
  if (this.options.mode === "range" || this.options.mode === "multiple") {
928
- const nextMonthDate = new Date(
929
- this.state.viewDate.getFullYear(),
930
- this.state.viewDate.getMonth() + 1,
931
- 1
932
- );
933
- const cal2 = this.renderCalendarGrid(nextMonthDate, true);
1033
+ const cal2 = this.renderCalendarGrid(this.state.nextViewDate, true);
934
1034
  this.elements.panelContent.appendChild(cal2);
935
1035
  }
936
1036
  }
@@ -3106,13 +3206,29 @@ function initChip(rootSelector = `.${PREFIX5}-chip`) {
3106
3206
  );
3107
3207
  if (!input) {
3108
3208
  customFieldContainer.innerHTML = `
3109
- <div class="${PREFIX5}-text-field ${PREFIX5}-text-field--size-medium ${PREFIX5}-text-field--variant-outline ${PREFIX5}-chip__input">
3110
- <div class="${PREFIX5}-text-field__wrapper">
3111
- <input type="text" class="${PREFIX5}-text-field__input" placeholder="Masukkan data yang Anda inginkan" value="${!isStandard ? primaryCustomValue : ""}" />
3112
- </div>
3209
+ <div class="${PREFIX5}-chip__input-wrapper">
3210
+ <input type="text" class="${PREFIX5}-chip__input" placeholder="Masukkan data yang Anda inginkan" value="${!isStandard ? primaryCustomValue : ""}" />
3211
+ <button type="button" class="${PREFIX5}-chip__clear-button" aria-label="Clear input" style="display: ${!isStandard && primaryCustomValue ? "inline-flex" : "none"};">
3212
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="${PREFIX5}-chip__clear-icon">
3213
+ <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
3214
+ <path d="M18 6l-12 12"></path>
3215
+ <path d="M6 6l12 12"></path>
3216
+ </svg>
3217
+ </button>
3113
3218
  </div>
3114
3219
  `;
3115
3220
  input = customFieldContainer.querySelector("input");
3221
+ const clearBtn = customFieldContainer.querySelector(
3222
+ ".ina-chip__clear-button"
3223
+ );
3224
+ input.addEventListener("input", (e) => {
3225
+ clearBtn.style.display = e.target.value ? "inline-flex" : "none";
3226
+ });
3227
+ clearBtn.addEventListener("click", () => {
3228
+ input.value = "";
3229
+ clearBtn.style.display = "none";
3230
+ commitCustomValue(input);
3231
+ });
3116
3232
  input.addEventListener("blur", (e) => {
3117
3233
  commitCustomValue(e.target);
3118
3234
  });
@@ -3194,6 +3310,10 @@ function initChip(rootSelector = `.${PREFIX5}-chip`) {
3194
3310
  if (!normSelected.includes(finalValue)) {
3195
3311
  normSelected.push(finalValue);
3196
3312
  }
3313
+ } else {
3314
+ if (toggleVal) {
3315
+ normSelected = normSelected.filter((v) => v !== toggleVal);
3316
+ }
3197
3317
  }
3198
3318
  if (isMultiple) {
3199
3319
  selectedValue = normSelected.join(",");
@@ -3214,38 +3334,12 @@ function initChip(rootSelector = `.${PREFIX5}-chip`) {
3214
3334
  const val = item.getAttribute("data-value");
3215
3335
  if (showCustomization && isToggleBtn(item)) {
3216
3336
  const normSelected = getNormalizedSelected();
3217
- let newSelected = [...normSelected];
3218
3337
  const standardValues = Array.from(items).filter((i) => !isToggleBtn(i)).map((i) => i.getAttribute("data-value"));
3219
3338
  const customValues = normSelected.filter(
3220
3339
  (v) => !standardValues.includes(v) && v !== "" && v !== val
3221
3340
  );
3222
- const primaryCustomValue = customValues[customValues.length - 1];
3223
3341
  const isInputVisible = normSelected.includes(val) || customValues.length > 0;
3224
- if (isInputVisible) {
3225
- newSelected = newSelected.filter((v) => v !== val);
3226
- if (primaryCustomValue) {
3227
- if (isMultiple) {
3228
- newSelected = newSelected.filter(
3229
- (v) => v !== primaryCustomValue
3230
- );
3231
- } else {
3232
- newSelected = [];
3233
- }
3234
- }
3235
- if (isMultiple) {
3236
- selectedValue = newSelected.join(",");
3237
- } else {
3238
- selectedValue = newSelected.length ? newSelected[0] : "";
3239
- }
3240
- updateUI();
3241
- const changeEvent = new CustomEvent(`${PREFIX5}-chip:change`, {
3242
- detail: {
3243
- value: isMultiple ? getNormalizedSelected() : selectedValue
3244
- },
3245
- bubbles: true
3246
- });
3247
- container.dispatchEvent(changeEvent);
3248
- } else {
3342
+ if (!isInputVisible) {
3249
3343
  handleSelect(val);
3250
3344
  }
3251
3345
  } else {
@@ -3465,6 +3559,28 @@ function initPagination() {
3465
3559
  lastBtn.addEventListener("click", () => {
3466
3560
  if (!isDisabled && currentPage < totalPages) goToPage(totalPages);
3467
3561
  });
3562
+ if (navButtonsContainer && !navButtonsContainer.__inaKeyboardSet) {
3563
+ navButtonsContainer.addEventListener("keydown", (e) => {
3564
+ if (e.key === "ArrowRight" || e.key === "ArrowLeft") {
3565
+ const focusable = Array.from(
3566
+ navButtonsContainer.querySelectorAll("button:not([disabled])")
3567
+ );
3568
+ if (!focusable.length) return;
3569
+ const currentIndex = focusable.indexOf(document.activeElement);
3570
+ if (currentIndex >= 0) {
3571
+ e.preventDefault();
3572
+ const nextIndex = e.key === "ArrowRight" ? (currentIndex + 1) % focusable.length : (currentIndex - 1 + focusable.length) % focusable.length;
3573
+ focusable[nextIndex]?.focus();
3574
+ }
3575
+ } else if (e.key === "Enter" || e.key === " ") {
3576
+ if (document.activeElement && document.activeElement.tagName === "BUTTON") {
3577
+ e.preventDefault();
3578
+ document.activeElement.click();
3579
+ }
3580
+ }
3581
+ });
3582
+ navButtonsContainer.__inaKeyboardSet = true;
3583
+ }
3468
3584
  if (pageSizeSelect) {
3469
3585
  pageSizeSelect.addEventListener("change", (e) => {
3470
3586
  if (isDisabled) return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@idds/js",
3
- "version": "1.2.2",
3
+ "version": "1.2.4",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },