@idds/js 1.0.97 → 1.0.99

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.
@@ -35,6 +35,7 @@ var InaUI = (() => {
35
35
  initFileUploadItem: () => initFileUploadItem,
36
36
  initImgCompare: () => initImgCompare,
37
37
  initModal: () => initModal,
38
+ initMonthPicker: () => initMonthPicker,
38
39
  initPagination: () => initPagination,
39
40
  initRadioButton: () => initRadioButton,
40
41
  initRangeDatepicker: () => initRangeDatepicker,
@@ -47,6 +48,7 @@ var InaUI = (() => {
47
48
  initTable: () => initTable,
48
49
  initTimepicker: () => initTimepicker,
49
50
  initToggle: () => initToggle,
51
+ initYearPicker: () => initYearPicker,
50
52
  setBrandTheme: () => setBrandTheme,
51
53
  showToast: () => showToast
52
54
  });
@@ -726,6 +728,14 @@ var InaUI = (() => {
726
728
  this.state.viewDate.setMonth(this.state.viewDate.getMonth() - 1);
727
729
  this.renderPanel();
728
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
+ };
729
739
  header.appendChild(prevBtn);
730
740
  } else {
731
741
  const spacer = document.createElement("div");
@@ -772,6 +782,14 @@ var InaUI = (() => {
772
782
  this.state.viewDate.setMonth(this.state.viewDate.getMonth() + 1);
773
783
  this.renderPanel();
774
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
+ };
775
793
  header.appendChild(nextBtn);
776
794
  } else if (!isNextMonth) {
777
795
  const spacer = document.createElement("div");
@@ -803,6 +821,8 @@ var InaUI = (() => {
803
821
  btn.type = "button";
804
822
  btn.className = `${PREFIX}-date-picker__day`;
805
823
  btn.textContent = i;
824
+ btn.setAttribute("role", "gridcell");
825
+ btn.tabIndex = -1;
806
826
  const disabled = this.isDateDisabled(date);
807
827
  if (disabled) {
808
828
  btn.classList.add(`${PREFIX}-date-picker__day--disabled`);
@@ -826,6 +846,7 @@ var InaUI = (() => {
826
846
  isSelected = true;
827
847
  if (start && end && date > start && date < end) isInRange = true;
828
848
  }
849
+ btn.setAttribute("aria-selected", isSelected.toString());
829
850
  if (isSelected) btn.classList.add(`${PREFIX}-date-picker__day--selected`);
830
851
  if (isInRange) btn.classList.add(`${PREFIX}-date-picker__day--in-range`);
831
852
  if (date.toDateString() === today.toDateString())
@@ -837,6 +858,24 @@ var InaUI = (() => {
837
858
  e.stopPropagation();
838
859
  this.handleDateSelect(date);
839
860
  };
861
+ btn.onkeydown = (e) => {
862
+ if (disabled || this.options.readonly) return;
863
+ if (e.key === "Enter" || e.key === " ") {
864
+ e.preventDefault();
865
+ this.handleDateSelect(date);
866
+ } else if (["ArrowRight", "ArrowLeft", "ArrowDown", "ArrowUp"].includes(e.key)) {
867
+ e.preventDefault();
868
+ const buttons = Array.from(grid.querySelectorAll("button"));
869
+ const currentIndex = buttons.indexOf(btn);
870
+ let nextIndex = currentIndex;
871
+ if (e.key === "ArrowRight") nextIndex += 1;
872
+ else if (e.key === "ArrowLeft") nextIndex -= 1;
873
+ else if (e.key === "ArrowDown") nextIndex += 7;
874
+ else if (e.key === "ArrowUp") nextIndex -= 7;
875
+ const targetBtn = buttons[nextIndex];
876
+ if (targetBtn) targetBtn.focus();
877
+ }
878
+ };
840
879
  }
841
880
  grid.appendChild(btn);
842
881
  }
@@ -849,6 +888,19 @@ var InaUI = (() => {
849
888
  btn.textContent = i;
850
889
  grid.appendChild(btn);
851
890
  }
891
+ setTimeout(() => {
892
+ const allButtons = Array.from(
893
+ grid.querySelectorAll("button:not(.ina-date-picker__day--other-month)")
894
+ );
895
+ const selectedBtn = allButtons.find(
896
+ (b) => b.classList.contains(`${PREFIX}-date-picker__day--selected`)
897
+ );
898
+ const todayBtn = allButtons.find(
899
+ (b) => b.classList.contains(`${PREFIX}-date-picker__day--today`) && !b.disabled
900
+ );
901
+ const focusableBtn = selectedBtn || todayBtn || allButtons.find((b) => !b.disabled);
902
+ if (focusableBtn) focusableBtn.tabIndex = 0;
903
+ }, 0);
852
904
  container.append(header, grid);
853
905
  return container;
854
906
  }
@@ -3923,6 +3975,330 @@ var InaUI = (() => {
3923
3975
  return instances.length === 1 ? instances[0] : instances;
3924
3976
  }
3925
3977
 
3978
+ // src/js/components/stateful/month-picker.js
3979
+ var MONTHS_SHORT_ID = [
3980
+ "Jan",
3981
+ "Feb",
3982
+ "Mar",
3983
+ "Apr",
3984
+ "Mei",
3985
+ "Jun",
3986
+ "Jul",
3987
+ "Agu",
3988
+ "Sep",
3989
+ "Okt",
3990
+ "Nov",
3991
+ "Des"
3992
+ ];
3993
+ function initMonthPicker(rootSelector = `.${PREFIX}-month-picker`) {
3994
+ const pickers = document.querySelectorAll(rootSelector);
3995
+ pickers.forEach((container) => {
3996
+ if (container.dataset.initialized === "true") return;
3997
+ container.dataset.initialized = "true";
3998
+ let currentMonthIdx = parseInt(container.dataset.value || "0", 10);
3999
+ const disabled = container.hasAttribute("disabled");
4000
+ const readonly = container.hasAttribute("readonly");
4001
+ const trigger = container.querySelector(`.${PREFIX}-month-picker__trigger`);
4002
+ const panel = container.querySelector(`.${PREFIX}-month-picker__panel`);
4003
+ const grid = container.querySelector(`.${PREFIX}-month-picker__grid`);
4004
+ const options2 = grid ? Array.from(
4005
+ grid.querySelectorAll(`.${PREFIX}-month-picker__month-option`)
4006
+ ) : [];
4007
+ if (!trigger || !panel || !grid || options2.length === 0) return;
4008
+ let isPickerOpen = false;
4009
+ const updateText = () => {
4010
+ const textEl = trigger.querySelector(
4011
+ `.${PREFIX}-month-picker__trigger-text`
4012
+ );
4013
+ if (textEl) textEl.textContent = MONTHS_SHORT_ID[currentMonthIdx];
4014
+ options2.forEach((opt, idx) => {
4015
+ if (idx === currentMonthIdx) {
4016
+ opt.classList.add(`${PREFIX}-month-picker__month-option--selected`);
4017
+ opt.setAttribute("aria-selected", "true");
4018
+ opt.tabIndex = 0;
4019
+ } else {
4020
+ opt.classList.remove(
4021
+ `${PREFIX}-month-picker__month-option--selected`
4022
+ );
4023
+ opt.setAttribute("aria-selected", "false");
4024
+ opt.tabIndex = -1;
4025
+ }
4026
+ });
4027
+ };
4028
+ const togglePicker = (show) => {
4029
+ if (disabled || readonly) return;
4030
+ isPickerOpen = show;
4031
+ if (show) {
4032
+ panel.classList.add(`${PREFIX}-month-picker__panel--open`);
4033
+ trigger.setAttribute("aria-expanded", "true");
4034
+ setTimeout(() => {
4035
+ const selectedOpt = options2.find((o) => o.tabIndex === 0);
4036
+ if (selectedOpt) selectedOpt.focus();
4037
+ }, 0);
4038
+ } else {
4039
+ panel.classList.remove(`${PREFIX}-month-picker__panel--open`);
4040
+ trigger.setAttribute("aria-expanded", "false");
4041
+ }
4042
+ };
4043
+ updateText();
4044
+ trigger.addEventListener("click", (e) => {
4045
+ e.stopPropagation();
4046
+ e.preventDefault();
4047
+ togglePicker(!isPickerOpen);
4048
+ });
4049
+ trigger.addEventListener("keydown", (e) => {
4050
+ if (e.key === "Enter" || e.key === " ") {
4051
+ e.preventDefault();
4052
+ e.stopPropagation();
4053
+ togglePicker(!isPickerOpen);
4054
+ }
4055
+ });
4056
+ document.addEventListener("click", (e) => {
4057
+ if (!container.contains(e.target)) togglePicker(false);
4058
+ });
4059
+ options2.forEach((btn, idx) => {
4060
+ btn.setAttribute("role", "option");
4061
+ btn.addEventListener("click", (e) => {
4062
+ if (disabled || readonly) return;
4063
+ e.stopPropagation();
4064
+ e.preventDefault();
4065
+ currentMonthIdx = idx;
4066
+ updateText();
4067
+ togglePicker(false);
4068
+ trigger.focus();
4069
+ container.dispatchEvent(
4070
+ new CustomEvent("change", {
4071
+ detail: { value: currentMonthIdx },
4072
+ bubbles: true,
4073
+ composed: true
4074
+ })
4075
+ );
4076
+ });
4077
+ btn.addEventListener("keydown", (e) => {
4078
+ if (disabled || readonly) return;
4079
+ if (e.key === "Enter" || e.key === " ") {
4080
+ e.preventDefault();
4081
+ e.stopPropagation();
4082
+ currentMonthIdx = idx;
4083
+ updateText();
4084
+ togglePicker(false);
4085
+ trigger.focus();
4086
+ container.dispatchEvent(
4087
+ new CustomEvent("change", {
4088
+ detail: { value: currentMonthIdx },
4089
+ bubbles: true,
4090
+ composed: true
4091
+ })
4092
+ );
4093
+ } else if (["ArrowRight", "ArrowLeft", "ArrowDown", "ArrowUp"].includes(e.key)) {
4094
+ e.preventDefault();
4095
+ e.stopPropagation();
4096
+ let nextIndex = idx;
4097
+ if (e.key === "ArrowRight") nextIndex += 1;
4098
+ else if (e.key === "ArrowLeft") nextIndex -= 1;
4099
+ else if (e.key === "ArrowDown")
4100
+ nextIndex += 3;
4101
+ else if (e.key === "ArrowUp") nextIndex -= 3;
4102
+ if (options2[nextIndex]) {
4103
+ options2[nextIndex].focus();
4104
+ }
4105
+ }
4106
+ });
4107
+ });
4108
+ });
4109
+ }
4110
+
4111
+ // src/js/components/stateful/year-picker.js
4112
+ function initYearPicker(rootSelector = `.${PREFIX}-year-picker`) {
4113
+ const pickers = document.querySelectorAll(rootSelector);
4114
+ pickers.forEach((container) => {
4115
+ if (container.dataset.initialized === "true") return;
4116
+ container.dataset.initialized = "true";
4117
+ let currentYearVal = parseInt(
4118
+ container.dataset.value || (/* @__PURE__ */ new Date()).getFullYear().toString(),
4119
+ 10
4120
+ );
4121
+ const disabled = container.hasAttribute("disabled");
4122
+ const readonly = container.hasAttribute("readonly");
4123
+ const maxYear = container.dataset.max ? parseInt(container.dataset.max, 10) : 2100;
4124
+ const minYear = container.dataset.min ? parseInt(container.dataset.min, 10) : 1900;
4125
+ let isPickerOpen = false;
4126
+ let decadeSize = 20;
4127
+ const trigger = container.querySelector(`.${PREFIX}-year-picker__trigger`);
4128
+ const panel = container.querySelector(`.${PREFIX}-year-picker__panel`);
4129
+ const grid = container.querySelector(`.${PREFIX}-year-picker__grid`);
4130
+ const prevBtn = container.querySelector(
4131
+ `.${PREFIX}-year-picker__nav-button[aria-label="Previous decade"]`
4132
+ );
4133
+ const nextBtn = container.querySelector(
4134
+ `.${PREFIX}-year-picker__nav-button[aria-label="Next decade"]`
4135
+ );
4136
+ const rangeText = container.querySelector(
4137
+ `.${PREFIX}-year-picker__decade-range`
4138
+ );
4139
+ if (!trigger || !panel || !grid) return;
4140
+ let decadeStart = Math.floor(currentYearVal / decadeSize) * decadeSize;
4141
+ const renderGrid = () => {
4142
+ grid.innerHTML = "";
4143
+ if (rangeText) {
4144
+ rangeText.textContent = `${decadeStart} - ${decadeStart + decadeSize - 1}`;
4145
+ }
4146
+ if (prevBtn) {
4147
+ prevBtn.disabled = disabled || readonly || decadeStart <= minYear;
4148
+ }
4149
+ if (nextBtn) {
4150
+ nextBtn.disabled = disabled || readonly || decadeStart + decadeSize > maxYear;
4151
+ }
4152
+ for (let y = decadeStart; y < decadeStart + decadeSize; y++) {
4153
+ const btn = document.createElement("button");
4154
+ btn.type = "button";
4155
+ btn.className = `${PREFIX}-year-picker__year-option`;
4156
+ if (y === currentYearVal) {
4157
+ btn.classList.add(`${PREFIX}-year-picker__year-option--selected`);
4158
+ btn.setAttribute("aria-selected", "true");
4159
+ btn.tabIndex = 0;
4160
+ } else {
4161
+ btn.setAttribute("aria-selected", "false");
4162
+ btn.tabIndex = -1;
4163
+ }
4164
+ if (y < minYear || y > maxYear) {
4165
+ btn.disabled = true;
4166
+ btn.classList.add(`${PREFIX}-year-picker__year-option--disabled`);
4167
+ }
4168
+ btn.textContent = y.toString();
4169
+ btn.setAttribute("role", "option");
4170
+ btn.addEventListener("click", (e) => {
4171
+ if (disabled || readonly || btn.disabled) return;
4172
+ e.stopPropagation();
4173
+ currentYearVal = y;
4174
+ updateText();
4175
+ togglePicker(false);
4176
+ trigger.focus();
4177
+ container.dispatchEvent(
4178
+ new CustomEvent("change", {
4179
+ detail: { value: currentYearVal },
4180
+ bubbles: true,
4181
+ composed: true
4182
+ })
4183
+ );
4184
+ });
4185
+ btn.addEventListener("keydown", (e) => {
4186
+ if (disabled || readonly || btn.disabled) return;
4187
+ if (e.key === "Enter" || e.key === " ") {
4188
+ e.preventDefault();
4189
+ e.stopPropagation();
4190
+ currentYearVal = y;
4191
+ updateText();
4192
+ togglePicker(false);
4193
+ trigger.focus();
4194
+ container.dispatchEvent(
4195
+ new CustomEvent("change", {
4196
+ detail: { value: currentYearVal },
4197
+ bubbles: true,
4198
+ composed: true
4199
+ })
4200
+ );
4201
+ } else if (["ArrowRight", "ArrowLeft", "ArrowDown", "ArrowUp"].includes(e.key)) {
4202
+ e.preventDefault();
4203
+ e.stopPropagation();
4204
+ const options2 = Array.from(
4205
+ grid.querySelectorAll(
4206
+ `.${PREFIX}-year-picker__year-option:not(:disabled)`
4207
+ )
4208
+ );
4209
+ const currentIndex = options2.indexOf(btn);
4210
+ if (currentIndex === -1) return;
4211
+ let nextIndex = currentIndex;
4212
+ if (e.key === "ArrowRight") nextIndex += 1;
4213
+ else if (e.key === "ArrowLeft") nextIndex -= 1;
4214
+ else if (e.key === "ArrowDown")
4215
+ nextIndex += 4;
4216
+ else if (e.key === "ArrowUp") nextIndex -= 4;
4217
+ if (options2[nextIndex]) {
4218
+ options2[nextIndex].focus();
4219
+ } else {
4220
+ }
4221
+ }
4222
+ });
4223
+ grid.appendChild(btn);
4224
+ }
4225
+ };
4226
+ const updateText = () => {
4227
+ const textEl = trigger.querySelector(
4228
+ `.${PREFIX}-year-picker__trigger-text`
4229
+ );
4230
+ if (textEl) textEl.textContent = currentYearVal.toString();
4231
+ };
4232
+ const togglePicker = (show) => {
4233
+ if (disabled || readonly) return;
4234
+ isPickerOpen = show;
4235
+ if (show) {
4236
+ decadeStart = Math.floor(currentYearVal / decadeSize) * decadeSize;
4237
+ renderGrid();
4238
+ panel.classList.add(`${PREFIX}-year-picker__panel--open`);
4239
+ trigger.setAttribute("aria-expanded", "true");
4240
+ setTimeout(() => {
4241
+ const selectedOpt = grid.querySelector(
4242
+ `.${PREFIX}-year-picker__year-option--selected`
4243
+ );
4244
+ if (selectedOpt) selectedOpt.focus();
4245
+ else if (grid.firstElementChild) grid.firstElementChild.focus();
4246
+ }, 0);
4247
+ } else {
4248
+ panel.classList.remove(`${PREFIX}-year-picker__panel--open`);
4249
+ trigger.setAttribute("aria-expanded", "false");
4250
+ }
4251
+ };
4252
+ updateText();
4253
+ renderGrid();
4254
+ trigger.addEventListener("click", (e) => {
4255
+ e.stopPropagation();
4256
+ e.preventDefault();
4257
+ togglePicker(!isPickerOpen);
4258
+ });
4259
+ trigger.addEventListener("keydown", (e) => {
4260
+ if (e.key === "Enter" || e.key === " ") {
4261
+ e.preventDefault();
4262
+ e.stopPropagation();
4263
+ togglePicker(!isPickerOpen);
4264
+ }
4265
+ });
4266
+ document.addEventListener("click", (e) => {
4267
+ if (!container.contains(e.target)) togglePicker(false);
4268
+ });
4269
+ if (prevBtn) {
4270
+ prevBtn.addEventListener("click", (e) => {
4271
+ e.stopPropagation();
4272
+ decadeStart -= decadeSize;
4273
+ renderGrid();
4274
+ });
4275
+ prevBtn.addEventListener("keydown", (e) => {
4276
+ if (e.key === "Enter" || e.key === " ") {
4277
+ e.preventDefault();
4278
+ e.stopPropagation();
4279
+ decadeStart -= decadeSize;
4280
+ renderGrid();
4281
+ }
4282
+ });
4283
+ }
4284
+ if (nextBtn) {
4285
+ nextBtn.addEventListener("click", (e) => {
4286
+ e.stopPropagation();
4287
+ decadeStart += decadeSize;
4288
+ renderGrid();
4289
+ });
4290
+ nextBtn.addEventListener("keydown", (e) => {
4291
+ if (e.key === "Enter" || e.key === " ") {
4292
+ e.preventDefault();
4293
+ e.stopPropagation();
4294
+ decadeStart += decadeSize;
4295
+ renderGrid();
4296
+ }
4297
+ });
4298
+ }
4299
+ });
4300
+ }
4301
+
3926
4302
  // src/js/components/stateless/toast.js
3927
4303
  var ICONS3 = {
3928
4304
  default: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" 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"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg>`,
@@ -4253,6 +4629,8 @@ var InaUI = (() => {
4253
4629
  initTabVertical();
4254
4630
  initTabHorizontal();
4255
4631
  initTable();
4632
+ initMonthPicker();
4633
+ initYearPicker();
4256
4634
  });
4257
4635
  }
4258
4636
  return __toCommonJS(bundle_exports);
package/dist/index.js CHANGED
@@ -716,6 +716,14 @@ var DatePicker = class {
716
716
  this.state.viewDate.setMonth(this.state.viewDate.getMonth() - 1);
717
717
  this.renderPanel();
718
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
+ };
719
727
  header.appendChild(prevBtn);
720
728
  } else {
721
729
  const spacer = document.createElement("div");
@@ -762,6 +770,14 @@ var DatePicker = class {
762
770
  this.state.viewDate.setMonth(this.state.viewDate.getMonth() + 1);
763
771
  this.renderPanel();
764
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
+ };
765
781
  header.appendChild(nextBtn);
766
782
  } else if (!isNextMonth) {
767
783
  const spacer = document.createElement("div");
@@ -793,6 +809,8 @@ var DatePicker = class {
793
809
  btn.type = "button";
794
810
  btn.className = `${PREFIX}-date-picker__day`;
795
811
  btn.textContent = i;
812
+ btn.setAttribute("role", "gridcell");
813
+ btn.tabIndex = -1;
796
814
  const disabled = this.isDateDisabled(date);
797
815
  if (disabled) {
798
816
  btn.classList.add(`${PREFIX}-date-picker__day--disabled`);
@@ -816,6 +834,7 @@ var DatePicker = class {
816
834
  isSelected = true;
817
835
  if (start && end && date > start && date < end) isInRange = true;
818
836
  }
837
+ btn.setAttribute("aria-selected", isSelected.toString());
819
838
  if (isSelected) btn.classList.add(`${PREFIX}-date-picker__day--selected`);
820
839
  if (isInRange) btn.classList.add(`${PREFIX}-date-picker__day--in-range`);
821
840
  if (date.toDateString() === today.toDateString())
@@ -827,6 +846,24 @@ var DatePicker = class {
827
846
  e.stopPropagation();
828
847
  this.handleDateSelect(date);
829
848
  };
849
+ btn.onkeydown = (e) => {
850
+ if (disabled || this.options.readonly) return;
851
+ if (e.key === "Enter" || e.key === " ") {
852
+ e.preventDefault();
853
+ this.handleDateSelect(date);
854
+ } else if (["ArrowRight", "ArrowLeft", "ArrowDown", "ArrowUp"].includes(e.key)) {
855
+ e.preventDefault();
856
+ const buttons = Array.from(grid.querySelectorAll("button"));
857
+ const currentIndex = buttons.indexOf(btn);
858
+ let nextIndex = currentIndex;
859
+ if (e.key === "ArrowRight") nextIndex += 1;
860
+ else if (e.key === "ArrowLeft") nextIndex -= 1;
861
+ else if (e.key === "ArrowDown") nextIndex += 7;
862
+ else if (e.key === "ArrowUp") nextIndex -= 7;
863
+ const targetBtn = buttons[nextIndex];
864
+ if (targetBtn) targetBtn.focus();
865
+ }
866
+ };
830
867
  }
831
868
  grid.appendChild(btn);
832
869
  }
@@ -839,6 +876,19 @@ var DatePicker = class {
839
876
  btn.textContent = i;
840
877
  grid.appendChild(btn);
841
878
  }
879
+ setTimeout(() => {
880
+ const allButtons = Array.from(
881
+ grid.querySelectorAll("button:not(.ina-date-picker__day--other-month)")
882
+ );
883
+ const selectedBtn = allButtons.find(
884
+ (b) => b.classList.contains(`${PREFIX}-date-picker__day--selected`)
885
+ );
886
+ const todayBtn = allButtons.find(
887
+ (b) => b.classList.contains(`${PREFIX}-date-picker__day--today`) && !b.disabled
888
+ );
889
+ const focusableBtn = selectedBtn || todayBtn || allButtons.find((b) => !b.disabled);
890
+ if (focusableBtn) focusableBtn.tabIndex = 0;
891
+ }, 0);
842
892
  container.append(header, grid);
843
893
  return container;
844
894
  }
@@ -4005,6 +4055,330 @@ function initTable(selectorOrElement, options2 = {}) {
4005
4055
  return instances.length === 1 ? instances[0] : instances;
4006
4056
  }
4007
4057
 
4058
+ // src/js/components/stateful/month-picker.js
4059
+ var MONTHS_SHORT_ID = [
4060
+ "Jan",
4061
+ "Feb",
4062
+ "Mar",
4063
+ "Apr",
4064
+ "Mei",
4065
+ "Jun",
4066
+ "Jul",
4067
+ "Agu",
4068
+ "Sep",
4069
+ "Okt",
4070
+ "Nov",
4071
+ "Des"
4072
+ ];
4073
+ function initMonthPicker(rootSelector = `.${PREFIX}-month-picker`) {
4074
+ const pickers = document.querySelectorAll(rootSelector);
4075
+ pickers.forEach((container) => {
4076
+ if (container.dataset.initialized === "true") return;
4077
+ container.dataset.initialized = "true";
4078
+ let currentMonthIdx = parseInt(container.dataset.value || "0", 10);
4079
+ const disabled = container.hasAttribute("disabled");
4080
+ const readonly = container.hasAttribute("readonly");
4081
+ const trigger = container.querySelector(`.${PREFIX}-month-picker__trigger`);
4082
+ const panel = container.querySelector(`.${PREFIX}-month-picker__panel`);
4083
+ const grid = container.querySelector(`.${PREFIX}-month-picker__grid`);
4084
+ const options2 = grid ? Array.from(
4085
+ grid.querySelectorAll(`.${PREFIX}-month-picker__month-option`)
4086
+ ) : [];
4087
+ if (!trigger || !panel || !grid || options2.length === 0) return;
4088
+ let isPickerOpen = false;
4089
+ const updateText = () => {
4090
+ const textEl = trigger.querySelector(
4091
+ `.${PREFIX}-month-picker__trigger-text`
4092
+ );
4093
+ if (textEl) textEl.textContent = MONTHS_SHORT_ID[currentMonthIdx];
4094
+ options2.forEach((opt, idx) => {
4095
+ if (idx === currentMonthIdx) {
4096
+ opt.classList.add(`${PREFIX}-month-picker__month-option--selected`);
4097
+ opt.setAttribute("aria-selected", "true");
4098
+ opt.tabIndex = 0;
4099
+ } else {
4100
+ opt.classList.remove(
4101
+ `${PREFIX}-month-picker__month-option--selected`
4102
+ );
4103
+ opt.setAttribute("aria-selected", "false");
4104
+ opt.tabIndex = -1;
4105
+ }
4106
+ });
4107
+ };
4108
+ const togglePicker = (show) => {
4109
+ if (disabled || readonly) return;
4110
+ isPickerOpen = show;
4111
+ if (show) {
4112
+ panel.classList.add(`${PREFIX}-month-picker__panel--open`);
4113
+ trigger.setAttribute("aria-expanded", "true");
4114
+ setTimeout(() => {
4115
+ const selectedOpt = options2.find((o) => o.tabIndex === 0);
4116
+ if (selectedOpt) selectedOpt.focus();
4117
+ }, 0);
4118
+ } else {
4119
+ panel.classList.remove(`${PREFIX}-month-picker__panel--open`);
4120
+ trigger.setAttribute("aria-expanded", "false");
4121
+ }
4122
+ };
4123
+ updateText();
4124
+ trigger.addEventListener("click", (e) => {
4125
+ e.stopPropagation();
4126
+ e.preventDefault();
4127
+ togglePicker(!isPickerOpen);
4128
+ });
4129
+ trigger.addEventListener("keydown", (e) => {
4130
+ if (e.key === "Enter" || e.key === " ") {
4131
+ e.preventDefault();
4132
+ e.stopPropagation();
4133
+ togglePicker(!isPickerOpen);
4134
+ }
4135
+ });
4136
+ document.addEventListener("click", (e) => {
4137
+ if (!container.contains(e.target)) togglePicker(false);
4138
+ });
4139
+ options2.forEach((btn, idx) => {
4140
+ btn.setAttribute("role", "option");
4141
+ btn.addEventListener("click", (e) => {
4142
+ if (disabled || readonly) return;
4143
+ e.stopPropagation();
4144
+ e.preventDefault();
4145
+ currentMonthIdx = idx;
4146
+ updateText();
4147
+ togglePicker(false);
4148
+ trigger.focus();
4149
+ container.dispatchEvent(
4150
+ new CustomEvent("change", {
4151
+ detail: { value: currentMonthIdx },
4152
+ bubbles: true,
4153
+ composed: true
4154
+ })
4155
+ );
4156
+ });
4157
+ btn.addEventListener("keydown", (e) => {
4158
+ if (disabled || readonly) return;
4159
+ if (e.key === "Enter" || e.key === " ") {
4160
+ e.preventDefault();
4161
+ e.stopPropagation();
4162
+ currentMonthIdx = idx;
4163
+ updateText();
4164
+ togglePicker(false);
4165
+ trigger.focus();
4166
+ container.dispatchEvent(
4167
+ new CustomEvent("change", {
4168
+ detail: { value: currentMonthIdx },
4169
+ bubbles: true,
4170
+ composed: true
4171
+ })
4172
+ );
4173
+ } else if (["ArrowRight", "ArrowLeft", "ArrowDown", "ArrowUp"].includes(e.key)) {
4174
+ e.preventDefault();
4175
+ e.stopPropagation();
4176
+ let nextIndex = idx;
4177
+ if (e.key === "ArrowRight") nextIndex += 1;
4178
+ else if (e.key === "ArrowLeft") nextIndex -= 1;
4179
+ else if (e.key === "ArrowDown")
4180
+ nextIndex += 3;
4181
+ else if (e.key === "ArrowUp") nextIndex -= 3;
4182
+ if (options2[nextIndex]) {
4183
+ options2[nextIndex].focus();
4184
+ }
4185
+ }
4186
+ });
4187
+ });
4188
+ });
4189
+ }
4190
+
4191
+ // src/js/components/stateful/year-picker.js
4192
+ function initYearPicker(rootSelector = `.${PREFIX}-year-picker`) {
4193
+ const pickers = document.querySelectorAll(rootSelector);
4194
+ pickers.forEach((container) => {
4195
+ if (container.dataset.initialized === "true") return;
4196
+ container.dataset.initialized = "true";
4197
+ let currentYearVal = parseInt(
4198
+ container.dataset.value || (/* @__PURE__ */ new Date()).getFullYear().toString(),
4199
+ 10
4200
+ );
4201
+ const disabled = container.hasAttribute("disabled");
4202
+ const readonly = container.hasAttribute("readonly");
4203
+ const maxYear = container.dataset.max ? parseInt(container.dataset.max, 10) : 2100;
4204
+ const minYear = container.dataset.min ? parseInt(container.dataset.min, 10) : 1900;
4205
+ let isPickerOpen = false;
4206
+ let decadeSize = 20;
4207
+ const trigger = container.querySelector(`.${PREFIX}-year-picker__trigger`);
4208
+ const panel = container.querySelector(`.${PREFIX}-year-picker__panel`);
4209
+ const grid = container.querySelector(`.${PREFIX}-year-picker__grid`);
4210
+ const prevBtn = container.querySelector(
4211
+ `.${PREFIX}-year-picker__nav-button[aria-label="Previous decade"]`
4212
+ );
4213
+ const nextBtn = container.querySelector(
4214
+ `.${PREFIX}-year-picker__nav-button[aria-label="Next decade"]`
4215
+ );
4216
+ const rangeText = container.querySelector(
4217
+ `.${PREFIX}-year-picker__decade-range`
4218
+ );
4219
+ if (!trigger || !panel || !grid) return;
4220
+ let decadeStart = Math.floor(currentYearVal / decadeSize) * decadeSize;
4221
+ const renderGrid = () => {
4222
+ grid.innerHTML = "";
4223
+ if (rangeText) {
4224
+ rangeText.textContent = `${decadeStart} - ${decadeStart + decadeSize - 1}`;
4225
+ }
4226
+ if (prevBtn) {
4227
+ prevBtn.disabled = disabled || readonly || decadeStart <= minYear;
4228
+ }
4229
+ if (nextBtn) {
4230
+ nextBtn.disabled = disabled || readonly || decadeStart + decadeSize > maxYear;
4231
+ }
4232
+ for (let y = decadeStart; y < decadeStart + decadeSize; y++) {
4233
+ const btn = document.createElement("button");
4234
+ btn.type = "button";
4235
+ btn.className = `${PREFIX}-year-picker__year-option`;
4236
+ if (y === currentYearVal) {
4237
+ btn.classList.add(`${PREFIX}-year-picker__year-option--selected`);
4238
+ btn.setAttribute("aria-selected", "true");
4239
+ btn.tabIndex = 0;
4240
+ } else {
4241
+ btn.setAttribute("aria-selected", "false");
4242
+ btn.tabIndex = -1;
4243
+ }
4244
+ if (y < minYear || y > maxYear) {
4245
+ btn.disabled = true;
4246
+ btn.classList.add(`${PREFIX}-year-picker__year-option--disabled`);
4247
+ }
4248
+ btn.textContent = y.toString();
4249
+ btn.setAttribute("role", "option");
4250
+ btn.addEventListener("click", (e) => {
4251
+ if (disabled || readonly || btn.disabled) return;
4252
+ e.stopPropagation();
4253
+ currentYearVal = y;
4254
+ updateText();
4255
+ togglePicker(false);
4256
+ trigger.focus();
4257
+ container.dispatchEvent(
4258
+ new CustomEvent("change", {
4259
+ detail: { value: currentYearVal },
4260
+ bubbles: true,
4261
+ composed: true
4262
+ })
4263
+ );
4264
+ });
4265
+ btn.addEventListener("keydown", (e) => {
4266
+ if (disabled || readonly || btn.disabled) return;
4267
+ if (e.key === "Enter" || e.key === " ") {
4268
+ e.preventDefault();
4269
+ e.stopPropagation();
4270
+ currentYearVal = y;
4271
+ updateText();
4272
+ togglePicker(false);
4273
+ trigger.focus();
4274
+ container.dispatchEvent(
4275
+ new CustomEvent("change", {
4276
+ detail: { value: currentYearVal },
4277
+ bubbles: true,
4278
+ composed: true
4279
+ })
4280
+ );
4281
+ } else if (["ArrowRight", "ArrowLeft", "ArrowDown", "ArrowUp"].includes(e.key)) {
4282
+ e.preventDefault();
4283
+ e.stopPropagation();
4284
+ const options2 = Array.from(
4285
+ grid.querySelectorAll(
4286
+ `.${PREFIX}-year-picker__year-option:not(:disabled)`
4287
+ )
4288
+ );
4289
+ const currentIndex = options2.indexOf(btn);
4290
+ if (currentIndex === -1) return;
4291
+ let nextIndex = currentIndex;
4292
+ if (e.key === "ArrowRight") nextIndex += 1;
4293
+ else if (e.key === "ArrowLeft") nextIndex -= 1;
4294
+ else if (e.key === "ArrowDown")
4295
+ nextIndex += 4;
4296
+ else if (e.key === "ArrowUp") nextIndex -= 4;
4297
+ if (options2[nextIndex]) {
4298
+ options2[nextIndex].focus();
4299
+ } else {
4300
+ }
4301
+ }
4302
+ });
4303
+ grid.appendChild(btn);
4304
+ }
4305
+ };
4306
+ const updateText = () => {
4307
+ const textEl = trigger.querySelector(
4308
+ `.${PREFIX}-year-picker__trigger-text`
4309
+ );
4310
+ if (textEl) textEl.textContent = currentYearVal.toString();
4311
+ };
4312
+ const togglePicker = (show) => {
4313
+ if (disabled || readonly) return;
4314
+ isPickerOpen = show;
4315
+ if (show) {
4316
+ decadeStart = Math.floor(currentYearVal / decadeSize) * decadeSize;
4317
+ renderGrid();
4318
+ panel.classList.add(`${PREFIX}-year-picker__panel--open`);
4319
+ trigger.setAttribute("aria-expanded", "true");
4320
+ setTimeout(() => {
4321
+ const selectedOpt = grid.querySelector(
4322
+ `.${PREFIX}-year-picker__year-option--selected`
4323
+ );
4324
+ if (selectedOpt) selectedOpt.focus();
4325
+ else if (grid.firstElementChild) grid.firstElementChild.focus();
4326
+ }, 0);
4327
+ } else {
4328
+ panel.classList.remove(`${PREFIX}-year-picker__panel--open`);
4329
+ trigger.setAttribute("aria-expanded", "false");
4330
+ }
4331
+ };
4332
+ updateText();
4333
+ renderGrid();
4334
+ trigger.addEventListener("click", (e) => {
4335
+ e.stopPropagation();
4336
+ e.preventDefault();
4337
+ togglePicker(!isPickerOpen);
4338
+ });
4339
+ trigger.addEventListener("keydown", (e) => {
4340
+ if (e.key === "Enter" || e.key === " ") {
4341
+ e.preventDefault();
4342
+ e.stopPropagation();
4343
+ togglePicker(!isPickerOpen);
4344
+ }
4345
+ });
4346
+ document.addEventListener("click", (e) => {
4347
+ if (!container.contains(e.target)) togglePicker(false);
4348
+ });
4349
+ if (prevBtn) {
4350
+ prevBtn.addEventListener("click", (e) => {
4351
+ e.stopPropagation();
4352
+ decadeStart -= decadeSize;
4353
+ renderGrid();
4354
+ });
4355
+ prevBtn.addEventListener("keydown", (e) => {
4356
+ if (e.key === "Enter" || e.key === " ") {
4357
+ e.preventDefault();
4358
+ e.stopPropagation();
4359
+ decadeStart -= decadeSize;
4360
+ renderGrid();
4361
+ }
4362
+ });
4363
+ }
4364
+ if (nextBtn) {
4365
+ nextBtn.addEventListener("click", (e) => {
4366
+ e.stopPropagation();
4367
+ decadeStart += decadeSize;
4368
+ renderGrid();
4369
+ });
4370
+ nextBtn.addEventListener("keydown", (e) => {
4371
+ if (e.key === "Enter" || e.key === " ") {
4372
+ e.preventDefault();
4373
+ e.stopPropagation();
4374
+ decadeStart += decadeSize;
4375
+ renderGrid();
4376
+ }
4377
+ });
4378
+ }
4379
+ });
4380
+ }
4381
+
4008
4382
  // src/js/components/stateless/toast.js
4009
4383
  var ICONS3 = {
4010
4384
  default: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" 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"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg>`,
@@ -4147,6 +4521,8 @@ function initAll() {
4147
4521
  initTabVertical();
4148
4522
  initTabHorizontal();
4149
4523
  initTable();
4524
+ initMonthPicker();
4525
+ initYearPicker();
4150
4526
  }
4151
4527
  export {
4152
4528
  DatePicker,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@idds/js",
3
- "version": "1.0.97",
3
+ "version": "1.0.99",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },