@idds/js 1.2.5 → 1.6.1

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 +1177 -436
  2. package/dist/index.js +838 -383
  3. package/package.json +1 -1
@@ -21,19 +21,20 @@ var InaUI = (() => {
21
21
  var bundle_exports = {};
22
22
  __export(bundle_exports, {
23
23
  DatePicker: () => DatePicker,
24
+ PhoneInput: () => PhoneInput,
24
25
  Table: () => Table,
25
26
  TimePicker: () => TimePicker,
26
27
  initAccordion: () => initAccordion,
27
28
  initButtonGroup: () => initButtonGroup,
28
29
  initCheckbox: () => initCheckbox,
29
- initChip: () => initChip,
30
+ initChip: () => initChip2,
30
31
  initDatepicker: () => initDatepicker,
31
32
  initDrawer: () => initDrawer,
32
33
  initDropdown: () => initDropdown,
33
34
  initFileUpload: () => initFileUpload,
34
35
  initFileUploadBase: () => initFileUploadBase,
35
36
  initFileUploadItem: () => initFileUploadItem,
36
- initImgCompare: () => initImgCompare,
37
+ initImgCompare: () => initImgCompare2,
37
38
  initModal: () => initModal,
38
39
  initMonthPicker: () => initMonthPicker,
39
40
  initPagination: () => initPagination,
@@ -103,18 +104,18 @@ var InaUI = (() => {
103
104
  const tabItem = tab.querySelectorAll(`.${PREFIX}-tab-item`);
104
105
  tabItem.forEach((tabButton) => {
105
106
  function updateState() {
106
- const index2 = Array.from(tabItem).indexOf(tabButton);
107
+ const index = Array.from(tabItem).indexOf(tabButton);
107
108
  tabItem.forEach((tabButton2, i) => {
108
109
  tabButton2.classList.remove("active");
109
110
  tabButton2.setAttribute("aria-selected", "false");
110
- if (i === index2) {
111
+ if (i === index) {
111
112
  tabButton2.classList.add("active");
112
113
  tabButton2.setAttribute("aria-selected", "true");
113
114
  }
114
115
  });
115
116
  tab.dispatchEvent(
116
117
  new CustomEvent("tab:change", {
117
- detail: { activeIndex: index2 },
118
+ detail: { activeIndex: index },
118
119
  bubbles: true,
119
120
  composed: true
120
121
  })
@@ -209,28 +210,28 @@ var InaUI = (() => {
209
210
  this.element.__inaAccordionGroup = this;
210
211
  }
211
212
  registerItem(item) {
212
- const index2 = this.items.size;
213
- this.items.set(item.id, index2);
213
+ const index = this.items.size;
214
+ this.items.set(item.id, index);
214
215
  this.itemsArray.push(item);
215
216
  if (item.defaultOpen) {
216
217
  if (this.isMultiple) {
217
- if (!this.openIndexes.includes(index2)) {
218
- this.openIndexes.push(index2);
218
+ if (!this.openIndexes.includes(index)) {
219
+ this.openIndexes.push(index);
219
220
  }
220
221
  } else {
221
222
  if (this.openIndexes.length === 0) {
222
- this.openIndexes.push(index2);
223
+ this.openIndexes.push(index);
223
224
  }
224
225
  }
225
226
  }
226
- return index2;
227
+ return index;
227
228
  }
228
229
  unregisterItem(item) {
229
- const index2 = this.items.get(item.id);
230
- if (index2 !== void 0) {
230
+ const index = this.items.get(item.id);
231
+ if (index !== void 0) {
231
232
  this.items.delete(item.id);
232
233
  this.itemsArray = this.itemsArray.filter((i) => i !== item);
233
- this.openIndexes = this.openIndexes.filter((idx) => idx !== index2).map((idx) => idx > index2 ? idx - 1 : idx);
234
+ this.openIndexes = this.openIndexes.filter((idx) => idx !== index).map((idx) => idx > index ? idx - 1 : idx);
234
235
  const newMap = /* @__PURE__ */ new Map();
235
236
  this.itemsArray.forEach((itm, newIdx) => {
236
237
  newMap.set(itm.id, newIdx);
@@ -238,22 +239,22 @@ var InaUI = (() => {
238
239
  this.items = newMap;
239
240
  }
240
241
  }
241
- handleItemToggle(index2, isOpen) {
242
+ handleItemToggle(index, isOpen) {
242
243
  const prevIndexes = [...this.openIndexes];
243
244
  let nextIndexes = [];
244
245
  if (this.isMultiple) {
245
246
  if (isOpen) {
246
- if (!prevIndexes.includes(index2)) {
247
- nextIndexes = [...prevIndexes, index2];
247
+ if (!prevIndexes.includes(index)) {
248
+ nextIndexes = [...prevIndexes, index];
248
249
  } else {
249
250
  nextIndexes = prevIndexes;
250
251
  }
251
252
  } else {
252
- nextIndexes = prevIndexes.filter((idx) => idx !== index2);
253
+ nextIndexes = prevIndexes.filter((idx) => idx !== index);
253
254
  }
254
255
  } else {
255
256
  if (isOpen) {
256
- nextIndexes = [index2];
257
+ nextIndexes = [index];
257
258
  } else {
258
259
  nextIndexes = [];
259
260
  }
@@ -261,16 +262,16 @@ var InaUI = (() => {
261
262
  this.openIndexes = nextIndexes;
262
263
  this.notifyItems();
263
264
  }
264
- isItemOpen(index2) {
265
- return this.openIndexes.includes(index2);
265
+ isItemOpen(index) {
266
+ return this.openIndexes.includes(index);
266
267
  }
267
268
  getItemIndex(itemId) {
268
269
  return this.items.get(itemId);
269
270
  }
270
271
  // Notify all children to update their visual state based on new openIndexes
271
272
  notifyItems() {
272
- this.itemsArray.forEach((item, index2) => {
273
- const isOpen = this.openIndexes.includes(index2);
273
+ this.itemsArray.forEach((item, index) => {
274
+ const isOpen = this.openIndexes.includes(index);
274
275
  item.setOpenState(isOpen);
275
276
  });
276
277
  }
@@ -379,7 +380,7 @@ var InaUI = (() => {
379
380
 
380
381
  // src/js/components/stateful/date-picker.js
381
382
  var DatePicker = class {
382
- constructor(selectorOrElement, options2 = {}) {
383
+ constructor(selectorOrElement, options = {}) {
383
384
  this.container = typeof selectorOrElement === "string" ? document.querySelector(selectorOrElement) : selectorOrElement;
384
385
  if (!this.container) {
385
386
  console.warn("[IDDS DatePicker] Container not found:", selectorOrElement);
@@ -405,7 +406,11 @@ var InaUI = (() => {
405
406
  onChange: null,
406
407
  triggerWidth: "",
407
408
  panelMaxHeight: "",
408
- ...options2
409
+ allowClear: true,
410
+ // Added allowClear option
411
+ className: "",
412
+ // Added className option
413
+ ...options
409
414
  };
410
415
  this.state = {
411
416
  viewDate: /* @__PURE__ */ new Date(),
@@ -559,6 +564,18 @@ var InaUI = (() => {
559
564
  }
560
565
  this.renderPanel();
561
566
  }
567
+ getFullDayName(shortName) {
568
+ const map = {
569
+ Min: "Minggu",
570
+ Sen: "Senin",
571
+ Sel: "Selasa",
572
+ Rab: "Rabu",
573
+ Kam: "Kamis",
574
+ Jum: "Jumat",
575
+ Sab: "Sabtu"
576
+ };
577
+ return map[shortName] || shortName;
578
+ }
562
579
  initDOM() {
563
580
  if (!this.container.classList.contains(`${PREFIX}-date-picker`)) {
564
581
  this.container.classList.add(`${PREFIX}-date-picker`);
@@ -574,6 +591,9 @@ var InaUI = (() => {
574
591
  if (this.options.triggerWidth) {
575
592
  trigger.style.width = typeof this.options.triggerWidth === "number" ? `${this.options.triggerWidth}px` : this.options.triggerWidth;
576
593
  }
594
+ trigger.setAttribute("aria-haspopup", "dialog");
595
+ trigger.setAttribute("aria-expanded", "false");
596
+ trigger.setAttribute("aria-label", "Pilih Tanggal");
577
597
  const textWrapper = document.createElement("span");
578
598
  textWrapper.className = `${PREFIX}-date-picker__trigger-text ${PREFIX}-date-picker__trigger-text--placeholder`;
579
599
  textWrapper.textContent = "Pilih Tanggal";
@@ -583,6 +603,26 @@ var InaUI = (() => {
583
603
  trigger.appendChild(textWrapper);
584
604
  trigger.appendChild(iconWrapper);
585
605
  this.container.appendChild(trigger);
606
+ } else if (trigger) {
607
+ if (!trigger.hasAttribute("aria-haspopup"))
608
+ trigger.setAttribute("aria-haspopup", "dialog");
609
+ if (!trigger.hasAttribute("aria-expanded"))
610
+ trigger.setAttribute("aria-expanded", "false");
611
+ if (!trigger.hasAttribute("aria-label"))
612
+ trigger.setAttribute("aria-label", "Pilih Tanggal");
613
+ }
614
+ if (this.options.allowClear && !this.options.panelOnly) {
615
+ let clearBtn = this.container.querySelector(`.${PREFIX}-date-picker__clear-button`);
616
+ if (!clearBtn) {
617
+ clearBtn = document.createElement("button");
618
+ clearBtn.type = "button";
619
+ clearBtn.className = `${PREFIX}-date-picker__clear-button`;
620
+ clearBtn.setAttribute("aria-label", "Hapus tanggal terpilih");
621
+ clearBtn.innerHTML = this.createIcon("x");
622
+ clearBtn.style.display = "none";
623
+ this.container.appendChild(clearBtn);
624
+ }
625
+ this.elements.clearBtn = clearBtn;
586
626
  }
587
627
  this.elements.trigger = trigger;
588
628
  if (trigger) {
@@ -877,10 +917,13 @@ var InaUI = (() => {
877
917
  header.appendChild(nextBtn);
878
918
  const grid = document.createElement("div");
879
919
  grid.className = `${PREFIX}-date-picker__calendar-grid`;
920
+ grid.setAttribute("role", "grid");
880
921
  this.DAYS_SHORT.forEach((d) => {
881
922
  const dh = document.createElement("div");
882
923
  dh.className = `${PREFIX}-date-picker__day-header`;
883
924
  dh.textContent = d;
925
+ dh.setAttribute("role", "columnheader");
926
+ dh.setAttribute("aria-label", this.getFullDayName(d));
884
927
  grid.appendChild(dh);
885
928
  });
886
929
  const firstDayOfMonth = new Date(year, month, 1).getDay();
@@ -1025,6 +1068,7 @@ var InaUI = (() => {
1025
1068
  this.state.isOpen = true;
1026
1069
  this.elements.panel.classList.add(`${PREFIX}-date-picker__panel--open`);
1027
1070
  this.elements.panel.style.display = "block";
1071
+ if (this.elements.trigger) this.elements.trigger.setAttribute("aria-expanded", "true");
1028
1072
  this.renderPanel();
1029
1073
  }
1030
1074
  close() {
@@ -1032,6 +1076,7 @@ var InaUI = (() => {
1032
1076
  this.state.isOpen = false;
1033
1077
  this.elements.panel.classList.remove(`${PREFIX}-date-picker__panel--open`);
1034
1078
  this.elements.panel.style.display = "none";
1079
+ if (this.elements.trigger) this.elements.trigger.setAttribute("aria-expanded", "false");
1035
1080
  }
1036
1081
  toggle() {
1037
1082
  if (this.state.isOpen) this.close();
@@ -1076,11 +1121,11 @@ var InaUI = (() => {
1076
1121
  return this.state.rangeDate;
1077
1122
  }
1078
1123
  };
1079
- function initDatepicker(selectorOrElement, options2 = {}) {
1124
+ function initDatepicker(selectorOrElement, options = {}) {
1080
1125
  const elements = typeof selectorOrElement === "string" ? document.querySelectorAll(selectorOrElement) : selectorOrElement ? typeof selectorOrElement.length !== "undefined" ? selectorOrElement : [selectorOrElement] : document.querySelectorAll(`.${PREFIX}-date-picker`);
1081
1126
  const instances = [];
1082
1127
  elements.forEach((container) => {
1083
- const instance = new DatePicker(container, options2);
1128
+ const instance = new DatePicker(container, options);
1084
1129
  container.__datepickerAPI = instance;
1085
1130
  instances.push(instance);
1086
1131
  });
@@ -1090,7 +1135,7 @@ var InaUI = (() => {
1090
1135
 
1091
1136
  // src/js/components/stateful/time-picker.js
1092
1137
  var TimePicker = class {
1093
- constructor(selectorOrElement, options2 = {}) {
1138
+ constructor(selectorOrElement, options = {}) {
1094
1139
  this.container = typeof selectorOrElement === "string" ? document.querySelector(selectorOrElement) : selectorOrElement;
1095
1140
  if (!this.container) {
1096
1141
  console.warn("[IDDS TimePicker] Container not found:", selectorOrElement);
@@ -1123,7 +1168,7 @@ var InaUI = (() => {
1123
1168
  secondStep: 1,
1124
1169
  onChange: null,
1125
1170
  size: this.container.dataset.size || "md",
1126
- ...options2
1171
+ ...options
1127
1172
  };
1128
1173
  this.state = {
1129
1174
  isOpen: false,
@@ -1131,6 +1176,7 @@ var InaUI = (() => {
1131
1176
  internalValue: ""
1132
1177
  };
1133
1178
  this.elements = {};
1179
+ this.inputId = this.container.id || `time-picker-${Math.random().toString(36).substr(2, 9)}`;
1134
1180
  this.initDOM();
1135
1181
  this.bindEvents();
1136
1182
  if (this.elements.input && this.elements.input.value) {
@@ -1238,28 +1284,41 @@ var InaUI = (() => {
1238
1284
  if (!wrapper) {
1239
1285
  wrapper = document.createElement("div");
1240
1286
  wrapper.className = `${PREFIX}-time-picker__wrapper`;
1287
+ wrapper.setAttribute("role", "combobox");
1288
+ wrapper.setAttribute("aria-haspopup", "listbox");
1289
+ wrapper.setAttribute("aria-expanded", "false");
1241
1290
  const prefixIcon = document.createElement("div");
1242
1291
  prefixIcon.className = `${PREFIX}-time-picker__prefix-icon`;
1243
1292
  prefixIcon.innerHTML = this.createIcon("clock");
1244
1293
  wrapper.appendChild(prefixIcon);
1245
1294
  input = document.createElement("input");
1246
1295
  input.type = "text";
1296
+ input.id = this.inputId;
1247
1297
  input.className = `${PREFIX}-time-picker__input ${PREFIX}-time-picker__input--size-${this.options.size} ${PREFIX}-time-picker__input--with-prefix`;
1248
1298
  if (this.options.allowClear)
1249
1299
  input.classList.add(`${PREFIX}-time-picker__input--with-suffix`);
1250
1300
  input.placeholder = this.container.getAttribute("placeholder") || "Select time";
1251
1301
  if (this.options.disabled) input.disabled = true;
1252
1302
  if (this.options.readonly) input.readOnly = true;
1253
- else input.readOnly = true;
1254
1303
  wrapper.appendChild(input);
1255
1304
  if (this.options.allowClear) {
1256
- clearBtn = document.createElement("div");
1305
+ clearBtn = document.createElement("button");
1306
+ clearBtn.type = "button";
1257
1307
  clearBtn.className = `${PREFIX}-time-picker__clear-button`;
1308
+ clearBtn.setAttribute("aria-label", "Hapus waktu");
1258
1309
  clearBtn.innerHTML = this.createIcon("x");
1259
1310
  clearBtn.style.display = "none";
1260
1311
  wrapper.appendChild(clearBtn);
1261
1312
  }
1262
1313
  this.container.appendChild(wrapper);
1314
+ } else {
1315
+ wrapper.setAttribute("role", "combobox");
1316
+ wrapper.setAttribute("aria-haspopup", "listbox");
1317
+ wrapper.setAttribute("aria-expanded", "false");
1318
+ if (input && !input.id) input.id = this.inputId;
1319
+ if (clearBtn && !clearBtn.hasAttribute("aria-label")) {
1320
+ clearBtn.setAttribute("aria-label", "Hapus waktu");
1321
+ }
1263
1322
  }
1264
1323
  this.elements.wrapper = wrapper;
1265
1324
  this.elements.input = input;
@@ -1340,24 +1399,24 @@ var InaUI = (() => {
1340
1399
  }
1341
1400
  }
1342
1401
  generateOptions(type) {
1343
- const options2 = [];
1402
+ const options = [];
1344
1403
  const { use12Hours, hourStep, minuteStep, secondStep } = this.options;
1345
1404
  let limit = type === "hour" ? use12Hours ? 12 : 24 : 60;
1346
1405
  let step = type === "hour" ? hourStep : type === "minute" ? minuteStep : secondStep;
1347
1406
  if (limit === 12) {
1348
1407
  for (let i = type === "hour" ? 1 : 0; i <= (type === "hour" ? 12 : 59); i += step) {
1349
- options2.push(i);
1408
+ options.push(i);
1350
1409
  }
1351
1410
  } else if (limit === 24) {
1352
1411
  for (let i = 0; i <= 23; i += step) {
1353
- options2.push(i);
1412
+ options.push(i);
1354
1413
  }
1355
1414
  } else {
1356
1415
  for (let i = 0; i <= 59; i += step) {
1357
- options2.push(i);
1416
+ options.push(i);
1358
1417
  }
1359
1418
  }
1360
- return options2;
1419
+ return options;
1361
1420
  }
1362
1421
  renderColumn(type, optionsArr) {
1363
1422
  const column = document.createElement("div");
@@ -1367,7 +1426,7 @@ var InaUI = (() => {
1367
1426
  column.appendChild(colContent);
1368
1427
  const { use12Hours } = this.options;
1369
1428
  const { currentTime } = this.state;
1370
- optionsArr.forEach((optValue) => {
1429
+ optionsArr.forEach((optValue, index) => {
1371
1430
  const option = document.createElement("div");
1372
1431
  option.className = `${PREFIX}-time-picker__option`;
1373
1432
  let isSelected = false;
@@ -1413,9 +1472,9 @@ var InaUI = (() => {
1413
1472
  option.classList.add(`${PREFIX}-time-picker__option--disabled`);
1414
1473
  option.setAttribute("role", "option");
1415
1474
  option.setAttribute("aria-selected", isSelected.toString());
1416
- const isFirstFocusable = index === 0 && !options.some((opt) => {
1475
+ const isFirstFocusable = index === 0 && !optionsArr.some((opt) => {
1417
1476
  if (type === "hour") {
1418
- return use12Hours ? (currentTime.hours === 0 ? 12 : currentTime.hours) === opt : currentTime.hours === opt;
1477
+ return (use12Hours && currentTime.hours === 0 ? 12 : currentTime.hours) === opt;
1419
1478
  } else if (type === "minute") {
1420
1479
  return currentTime.minutes === opt;
1421
1480
  } else if (type === "second") {
@@ -1533,6 +1592,7 @@ var InaUI = (() => {
1533
1592
  this.state.isOpen = true;
1534
1593
  this.container.classList.add(`${PREFIX}-time-picker--open`);
1535
1594
  this.elements.panel.style.display = "block";
1595
+ this.elements.wrapper.setAttribute("aria-expanded", "true");
1536
1596
  this.state.currentTime = this.parseTime(this.elements.input.value);
1537
1597
  this.buildPanel();
1538
1598
  document.dispatchEvent(
@@ -1545,6 +1605,7 @@ var InaUI = (() => {
1545
1605
  this.state.isOpen = false;
1546
1606
  this.container.classList.remove(`${PREFIX}-time-picker--open`);
1547
1607
  this.elements.panel.style.display = "none";
1608
+ this.elements.wrapper.setAttribute("aria-expanded", "false");
1548
1609
  }
1549
1610
  toggle() {
1550
1611
  if (this.state.isOpen) this.close();
@@ -1553,20 +1614,50 @@ var InaUI = (() => {
1553
1614
  bindEvents() {
1554
1615
  this.elements.wrapper.addEventListener("click", (e) => {
1555
1616
  e.stopPropagation();
1556
- this.toggle();
1617
+ const target = e.target;
1618
+ if (target === this.elements.wrapper || target.classList.contains(`${PREFIX}-time-picker__suffix-icon`) || target.classList.contains(`${PREFIX}-time-picker__prefix-icon`)) {
1619
+ this.toggle();
1620
+ }
1557
1621
  });
1558
- if (this.elements.clearBtn && this.options.allowClear) {
1622
+ this.elements.input.addEventListener("input", (e) => {
1623
+ const val = e.target.value;
1624
+ this.state.internalValue = val;
1625
+ const timeRegex = this.options.use12Hours ? /^(\d{1,2}):(\d{2})(?::(\d{2}))?\s?(AM|PM|am|pm)?$/ : /^(\d{1,2}):(\d{2})(?::(\d{2}))?$/;
1626
+ if (timeRegex.test(val)) {
1627
+ this.state.currentTime = this.parseTime(val);
1628
+ if (this.state.isOpen) this.buildPanel();
1629
+ }
1630
+ if (this.elements.clearBtn && this.options.allowClear) {
1631
+ this.elements.clearBtn.style.display = val && !this.options.disabled ? "flex" : "none";
1632
+ }
1633
+ if (typeof this.options.onChange === "function") {
1634
+ this.options.onChange(val);
1635
+ }
1636
+ });
1637
+ this.elements.input.addEventListener("click", (e) => {
1638
+ e.stopPropagation();
1639
+ this.open();
1640
+ });
1641
+ this.elements.input.addEventListener("focus", () => {
1642
+ this.open();
1643
+ });
1644
+ this.elements.input.addEventListener("keydown", (e) => {
1645
+ if (e.key === "Enter") {
1646
+ e.preventDefault();
1647
+ if (this.state.internalValue) {
1648
+ this.close();
1649
+ } else {
1650
+ this.toggle();
1651
+ }
1652
+ } else if (e.key === "Escape") {
1653
+ if (this.state.isOpen) this.close();
1654
+ }
1655
+ });
1656
+ if (this.elements.clearBtn) {
1559
1657
  this.elements.clearBtn.addEventListener("click", (e) => {
1560
1658
  e.stopPropagation();
1561
- this.elements.input.value = "";
1562
- this.state.currentTime = {
1563
- hours: 0,
1564
- minutes: 0,
1565
- seconds: 0,
1566
- period: "AM"
1567
- };
1568
- this.container.dataset.value = "";
1569
1659
  this.state.internalValue = "";
1660
+ this.elements.input.value = "";
1570
1661
  this.elements.clearBtn.style.display = "none";
1571
1662
  this.elements.input.dispatchEvent(
1572
1663
  new Event("change", { bubbles: true })
@@ -1575,6 +1666,12 @@ var InaUI = (() => {
1575
1666
  this.options.onChange("");
1576
1667
  }
1577
1668
  });
1669
+ this.elements.clearBtn.addEventListener("keydown", (e) => {
1670
+ if (e.key === "Enter" || e.key === " ") {
1671
+ e.preventDefault();
1672
+ this.elements.clearBtn.click();
1673
+ }
1674
+ });
1578
1675
  }
1579
1676
  document.addEventListener("click", (e) => {
1580
1677
  if (!this.container.contains(e.target)) this.close();
@@ -1588,11 +1685,11 @@ var InaUI = (() => {
1588
1685
  return this.state.internalValue;
1589
1686
  }
1590
1687
  };
1591
- function initTimepicker(selectorOrElement, options2 = {}) {
1688
+ function initTimepicker(selectorOrElement, options = {}) {
1592
1689
  const elements = typeof selectorOrElement === "string" ? document.querySelectorAll(selectorOrElement) : selectorOrElement ? typeof selectorOrElement.length !== "undefined" ? selectorOrElement : [selectorOrElement] : document.querySelectorAll(`.${PREFIX}-time-picker`);
1593
1690
  const instances = [];
1594
1691
  elements.forEach((container) => {
1595
- const instance = new TimePicker(container, options2);
1692
+ const instance = new TimePicker(container, options);
1596
1693
  container.__timepickerAPI = instance;
1597
1694
  instances.push(instance);
1598
1695
  });
@@ -1635,6 +1732,17 @@ var InaUI = (() => {
1635
1732
  modalEl.style.display = "flex";
1636
1733
  document.body.style.overflow = "hidden";
1637
1734
  modalEl.setAttribute("aria-hidden", "false");
1735
+ modalEl.setAttribute("tabindex", "-1");
1736
+ if (!modalEl.hasAttribute("role")) {
1737
+ modalEl.setAttribute("role", "dialog");
1738
+ }
1739
+ if (!modalEl.hasAttribute("aria-modal")) {
1740
+ modalEl.setAttribute("aria-modal", "true");
1741
+ }
1742
+ const closeBtn = modalEl.querySelector(`.${PREFIX}-modal__close-button`);
1743
+ if (closeBtn && !closeBtn.hasAttribute("aria-label")) {
1744
+ closeBtn.setAttribute("aria-label", "Tutup dialog");
1745
+ }
1638
1746
  modalEl.classList.remove(
1639
1747
  `${PREFIX}-modal--exit`,
1640
1748
  `${PREFIX}-modal--exit-active`
@@ -1733,6 +1841,19 @@ var InaUI = (() => {
1733
1841
  if (!drawer) return;
1734
1842
  drawer.style.display = "flex";
1735
1843
  document.body.style.overflow = "hidden";
1844
+ drawer.setAttribute("aria-hidden", "false");
1845
+ drawer.setAttribute("tabindex", "-1");
1846
+ if (!drawer.hasAttribute("role")) {
1847
+ drawer.setAttribute("role", "complementary");
1848
+ }
1849
+ if (!drawer.hasAttribute("aria-modal")) {
1850
+ drawer.setAttribute("aria-modal", "true");
1851
+ }
1852
+ const panel = drawer.querySelector(`.${PREFIX2}-drawer__panel`) || drawer.querySelector(`.${PREFIX2}-drawer__content`) || drawer;
1853
+ const closeBtn = panel.querySelector(`.${PREFIX2}-drawer__close-button`);
1854
+ if (closeBtn && !closeBtn.hasAttribute("aria-label")) {
1855
+ closeBtn.setAttribute("aria-label", "Tutup panel");
1856
+ }
1736
1857
  drawer.offsetHeight;
1737
1858
  drawer.classList.add(`${PREFIX2}-drawer--open`);
1738
1859
  drawer.dispatchEvent(new CustomEvent("drawer:open"));
@@ -1805,9 +1926,20 @@ var InaUI = (() => {
1805
1926
  if (newState.isOpen !== void 0) {
1806
1927
  root.setAttribute("data-state", newState.isOpen ? "open" : "closed");
1807
1928
  const trigger = root.querySelector(`.${PREFIX3}-select-dropdown__trigger`);
1808
- if (trigger) trigger.setAttribute("aria-expanded", newState.isOpen);
1929
+ if (trigger) {
1930
+ trigger.setAttribute("aria-expanded", newState.isOpen);
1931
+ if (!trigger.hasAttribute("aria-haspopup")) {
1932
+ trigger.setAttribute("aria-haspopup", "listbox");
1933
+ }
1934
+ }
1809
1935
  const panel = root.querySelector(`.${PREFIX3}-select-dropdown__panel`);
1810
1936
  if (panel) {
1937
+ if (!panel.hasAttribute("role")) {
1938
+ panel.setAttribute("role", "listbox");
1939
+ }
1940
+ if (newState.isMultiple) {
1941
+ panel.setAttribute("aria-multiselectable", "true");
1942
+ }
1811
1943
  if (newState.isOpen) {
1812
1944
  panel.style.removeProperty("display");
1813
1945
  } else {
@@ -1834,9 +1966,9 @@ var InaUI = (() => {
1834
1966
  `.${PREFIX3}-select-dropdown__trigger-text`
1835
1967
  );
1836
1968
  const placeholder = input ? input.getAttribute("placeholder") : textSpan ? textSpan.getAttribute("data-placeholder") : "Select...";
1837
- const options2 = root.querySelectorAll(`.${PREFIX3}-select-dropdown__option`);
1969
+ const options = root.querySelectorAll(`.${PREFIX3}-select-dropdown__option`);
1838
1970
  const getLabel = (val) => {
1839
- const opt = Array.from(options2).find(
1971
+ const opt = Array.from(options).find(
1840
1972
  (o) => o.getAttribute("data-value") === val
1841
1973
  );
1842
1974
  return opt ? opt.textContent.trim() : val;
@@ -1862,7 +1994,7 @@ var InaUI = (() => {
1862
1994
  values.length === 0
1863
1995
  );
1864
1996
  }
1865
- options2.forEach((opt) => {
1997
+ options.forEach((opt) => {
1866
1998
  const val = opt.getAttribute("data-value");
1867
1999
  const isSelected = values.includes(val);
1868
2000
  if (isMultiple) {
@@ -1884,6 +2016,10 @@ var InaUI = (() => {
1884
2016
  isSelected
1885
2017
  );
1886
2018
  }
2019
+ if (!opt.hasAttribute("role")) {
2020
+ opt.setAttribute("role", "option");
2021
+ }
2022
+ opt.setAttribute("aria-selected", isSelected);
1887
2023
  });
1888
2024
  }
1889
2025
  function initSelectDropdown() {
@@ -1942,13 +2078,13 @@ var InaUI = (() => {
1942
2078
  const root = e.target.closest(`.${PREFIX3}-select-dropdown`);
1943
2079
  if (root) {
1944
2080
  const term = e.target.value.toLowerCase();
1945
- const options2 = root.querySelectorAll(
2081
+ const options = root.querySelectorAll(
1946
2082
  `.${PREFIX3}-select-dropdown__option`
1947
2083
  );
1948
2084
  if (root.getAttribute("data-state") !== "open") {
1949
2085
  setDropdownState(root, { isOpen: true });
1950
2086
  }
1951
- options2.forEach((opt) => {
2087
+ options.forEach((opt) => {
1952
2088
  const text = opt.textContent.trim().toLowerCase();
1953
2089
  opt.style.display = text.includes(term) ? "" : "none";
1954
2090
  });
@@ -2022,20 +2158,20 @@ var InaUI = (() => {
2022
2158
  `;
2023
2159
  const updateUI = () => {
2024
2160
  stepper.dataset.currentStep = currentStep;
2025
- items.forEach((item, index2) => {
2161
+ items.forEach((item, index) => {
2026
2162
  const iconWrapper = item.querySelector(
2027
2163
  `.${PREFIX}-stepper__icon-wrapper`
2028
2164
  );
2029
- const itemNumber = index2 + 1;
2165
+ const itemNumber = index + 1;
2030
2166
  item.classList.remove(
2031
2167
  `${PREFIX}-stepper__item--completed`,
2032
2168
  `${PREFIX}-stepper__item--active`
2033
2169
  );
2034
2170
  if (iconWrapper) iconWrapper.innerHTML = "";
2035
- if (index2 < currentStep) {
2171
+ if (index < currentStep) {
2036
2172
  item.classList.add(`${PREFIX}-stepper__item--completed`);
2037
2173
  if (iconWrapper) iconWrapper.innerHTML = checkIcon;
2038
- } else if (index2 === currentStep) {
2174
+ } else if (index === currentStep) {
2039
2175
  item.classList.add(`${PREFIX}-stepper__item--active`);
2040
2176
  if (iconWrapper)
2041
2177
  iconWrapper.innerHTML = `<span class="${PREFIX}-stepper__step-number">${itemNumber}</span>`;
@@ -2044,8 +2180,8 @@ var InaUI = (() => {
2044
2180
  iconWrapper.innerHTML = `<span class="${PREFIX}-stepper__step-number">${itemNumber}</span>`;
2045
2181
  }
2046
2182
  });
2047
- separators.forEach((separator, index2) => {
2048
- if (index2 < currentStep) {
2183
+ separators.forEach((separator, index) => {
2184
+ if (index < currentStep) {
2049
2185
  separator.classList.add(`${PREFIX}-stepper__separator--completed`);
2050
2186
  } else {
2051
2187
  separator.classList.remove(`${PREFIX}-stepper__separator--completed`);
@@ -2091,11 +2227,11 @@ var InaUI = (() => {
2091
2227
  }
2092
2228
  });
2093
2229
  });
2094
- items.forEach((item, index2) => {
2230
+ items.forEach((item, index) => {
2095
2231
  if (item.classList.contains(`${PREFIX}-stepper__item--clickable`) || item.hasAttribute("data-clickable")) {
2096
2232
  item.addEventListener("click", () => {
2097
2233
  if (!item.classList.contains(`${PREFIX}-stepper__item--disabled`)) {
2098
- currentStep = index2;
2234
+ currentStep = index;
2099
2235
  updateUI();
2100
2236
  }
2101
2237
  });
@@ -2169,7 +2305,7 @@ var InaUI = (() => {
2169
2305
  } else {
2170
2306
  filesContainer.style.display = "none";
2171
2307
  }
2172
- uploadedFiles.forEach((f, index2) => {
2308
+ uploadedFiles.forEach((f, index) => {
2173
2309
  const fileEl = document.createElement("div");
2174
2310
  fileEl.className = `${PREFIX}-file-upload__file`;
2175
2311
  let statusClass = "";
@@ -2993,329 +3129,54 @@ var InaUI = (() => {
2993
3129
  });
2994
3130
  }
2995
3131
 
2996
- // src/js/components/stateless/img-compare.js
2997
- function initImgCompare(rootSelector = `.${PREFIX}-img-compare`) {
2998
- document.querySelectorAll(rootSelector).forEach((imgCompare) => {
2999
- const sliderEl = document.createElement("input");
3000
- sliderEl.type = "range";
3001
- sliderEl.min = "0";
3002
- sliderEl.max = "100";
3003
- sliderEl.value = "50";
3004
- sliderEl.setAttribute("aria-label", "Percentage of the image to show");
3005
- sliderEl.setAttribute("aria-valuenow", "50");
3006
- sliderEl.setAttribute("aria-valuemin", "0");
3007
- sliderEl.setAttribute("aria-valuemax", "100");
3008
- sliderEl.classList.add("ina-ss-img__slider");
3009
- sliderEl.addEventListener("input", () => {
3010
- imgCompare.style.setProperty(
3011
- `--${PREFIX}-position`,
3012
- `${sliderEl.value}%`
3013
- );
3014
- });
3015
- const sliderLineEl = document.createElement("div");
3016
- sliderLineEl.classList.add("ina-ss-img__slider-line");
3017
- const sliderButtonEl = document.createElement("button");
3018
- sliderButtonEl.classList.add("ina-ss-img__slider-button");
3019
- imgCompare.appendChild(sliderEl);
3020
- imgCompare.appendChild(sliderLineEl);
3021
- imgCompare.appendChild(sliderButtonEl);
3022
- });
3023
- }
3024
-
3025
- // src/js/components/stateful/chip.js
3026
- var PREFIX4 = "ina";
3027
- function initChip(rootSelector = `.${PREFIX4}-chip`) {
3028
- const chips = document.querySelectorAll(rootSelector);
3029
- chips.forEach((container) => {
3030
- if (container.__inaChipInitialized) return;
3031
- const showCustomization = container.getAttribute("data-show-customization") === "true";
3032
- const customizationLabel = container.getAttribute("data-customization-label") || "Kustomisasi";
3033
- const isMultiple = container.getAttribute("data-multiple") === "true";
3034
- let selectedValue = container.getAttribute("data-selected") || "";
3035
- const list = container.querySelector(`.${PREFIX4}-chip__list`);
3036
- const items = list ? list.querySelectorAll(`.${PREFIX4}-chip__item`) : [];
3037
- let customFieldContainer = container.querySelector(
3038
- `.${PREFIX4}-chip__custom-field`
3132
+ // src/js/components/stateful/pagination.js
3133
+ function initPagination() {
3134
+ document.querySelectorAll(`.${PREFIX}-pagination`).forEach((container) => {
3135
+ if (container.dataset.initialized === "true") return;
3136
+ container.dataset.initialized = "true";
3137
+ const navButtonsContainer = container.querySelector(
3138
+ `.${PREFIX}-pagination__nav-buttons`
3039
3139
  );
3040
- const getNormalizedSelected = () => {
3041
- if (!selectedValue) return [];
3042
- return isMultiple ? selectedValue.split(",").map((s) => s.trim()).filter(Boolean) : [selectedValue];
3043
- };
3140
+ const pageInfo = container.querySelector(
3141
+ `.${PREFIX}-pagination__page-info`
3142
+ );
3143
+ const firstBtn = container.querySelector('[data-action="first"]');
3144
+ const prevBtn = container.querySelector('[data-action="prev"]');
3145
+ const nextBtn = container.querySelector('[data-action="next"]');
3146
+ const lastBtn = container.querySelector('[data-action="last"]');
3147
+ const pageSizeSelect = container.querySelector('[data-role="page-size"]');
3148
+ if (!navButtonsContainer || !pageInfo) return;
3149
+ let currentPage = parseInt(container.dataset.current || "1", 10);
3150
+ let totalPages = parseInt(container.dataset.total || "10", 10);
3151
+ let pageSize = parseInt(container.dataset.pageSize || "10", 10);
3152
+ let isDisabled = container.dataset.disabled === "true";
3153
+ let pageButtons = [];
3044
3154
  const updateUI = () => {
3045
- const normSelected = getNormalizedSelected();
3046
- const getInitialFocusIndex = () => {
3047
- if (normSelected.length > 0) {
3048
- const standardValues = Array.from(items).filter((item) => item.textContent.trim() !== customizationLabel).map((item) => item.getAttribute("data-value"));
3049
- const hasCustomVal = normSelected.some(
3050
- (val) => !standardValues.includes(val) && val !== ""
3051
- );
3052
- if (hasCustomVal && showCustomization) {
3053
- return items.length - 1;
3054
- }
3055
- const firstSelectedIndex = Array.from(items).findIndex(
3056
- (opt) => normSelected.includes(opt.getAttribute("data-value"))
3057
- );
3058
- if (firstSelectedIndex !== -1) return firstSelectedIndex;
3059
- }
3060
- return 0;
3061
- };
3062
- const focusedIndex = getInitialFocusIndex();
3063
- items.forEach((item, index2) => {
3064
- const itemValue = item.getAttribute("data-value");
3065
- const isSelected = normSelected.includes(itemValue) || showCustomization && item.textContent.trim() === customizationLabel && normSelected.some(
3066
- (val) => !Array.from(items).filter((i) => i.textContent.trim() !== customizationLabel).map((i) => i.getAttribute("data-value")).includes(val) && val !== ""
3067
- );
3068
- const isDisabled = item.hasAttribute("disabled");
3069
- if (isSelected) {
3070
- item.classList.add(`${PREFIX4}-chip__item--selected`);
3071
- } else {
3072
- item.classList.remove(`${PREFIX4}-chip__item--selected`);
3073
- }
3074
- if (isDisabled) {
3075
- item.classList.add(`${PREFIX4}-chip__item--disabled`);
3076
- }
3077
- item.setAttribute(
3078
- "tabindex",
3079
- index2 === focusedIndex && !isDisabled ? "0" : "-1"
3155
+ pageInfo.textContent = `Halaman ${currentPage} dari ${totalPages}`;
3156
+ const isFirst = currentPage === 1;
3157
+ if (firstBtn) {
3158
+ const disabled = isDisabled || isFirst;
3159
+ firstBtn.disabled = disabled;
3160
+ firstBtn.classList.toggle(
3161
+ `${PREFIX}-pagination__nav-button--disabled`,
3162
+ disabled
3080
3163
  );
3081
- });
3082
- if (showCustomization) {
3083
- const isToggleBtn2 = (i) => i.hasAttribute("data-customization-toggle") || i.textContent.trim() === customizationLabel;
3084
- const standardValues = Array.from(items).filter((item) => !isToggleBtn2(item)).map((item) => item.getAttribute("data-value"));
3085
- const customValues = normSelected.filter(
3086
- (val) => !standardValues.includes(val) && val !== ""
3164
+ firstBtn.classList.toggle(
3165
+ `${PREFIX}-pagination__nav-button--enabled`,
3166
+ !disabled
3087
3167
  );
3088
- const isStandard = customValues.length === 0;
3089
- const primaryCustomValue = customValues[customValues.length - 1] || "";
3090
- const toggleBtn = Array.from(items).find(isToggleBtn2);
3091
- const showInput = toggleBtn && normSelected.includes(toggleBtn.getAttribute("data-value")) || !isStandard && normSelected.length > 0;
3092
- if (showInput) {
3093
- if (!customFieldContainer) {
3094
- customFieldContainer = document.createElement("div");
3095
- customFieldContainer.className = `${PREFIX4}-chip__custom-field`;
3096
- container.appendChild(customFieldContainer);
3097
- }
3098
- let input = customFieldContainer.querySelector(
3099
- `.${PREFIX4}-chip__input`
3100
- );
3101
- if (!input) {
3102
- customFieldContainer.innerHTML = `
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>
3112
- </div>
3113
- `;
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
- });
3126
- input.addEventListener("blur", (e) => {
3127
- commitCustomValue(e.target);
3128
- });
3129
- input.addEventListener("keydown", (e) => {
3130
- if (e.key === "Enter") {
3131
- commitCustomValue(e.target);
3132
- e.target.blur();
3133
- }
3134
- });
3135
- } else {
3136
- const inputEl = customFieldContainer.querySelector("input");
3137
- if (inputEl && document.activeElement !== inputEl) {
3138
- inputEl.value = !isStandard ? primaryCustomValue : "";
3139
- }
3140
- }
3141
- customFieldContainer.style.display = "block";
3142
- } else {
3143
- if (customFieldContainer) {
3144
- customFieldContainer.style.display = "none";
3145
- }
3146
- }
3147
3168
  }
3148
- };
3149
- const handleSelect = (val) => {
3150
- if (!val) return;
3151
- let finalVal = val;
3152
- if (isMultiple) {
3153
- const normSelected = getNormalizedSelected();
3154
- let newSelected;
3155
- if (normSelected.includes(val)) {
3156
- newSelected = normSelected.filter((v) => v !== val);
3157
- } else {
3158
- newSelected = [...normSelected, val];
3159
- }
3160
- finalVal = newSelected;
3161
- selectedValue = newSelected.join(",");
3162
- } else {
3163
- const normSelected = getNormalizedSelected();
3164
- if (normSelected.includes(val)) {
3165
- selectedValue = "";
3166
- finalVal = "";
3167
- } else {
3168
- selectedValue = val;
3169
- }
3170
- }
3171
- container.setAttribute("data-selected", selectedValue);
3172
- updateUI();
3173
- container.dispatchEvent(
3174
- new CustomEvent("chip:select", {
3175
- detail: { value: finalVal },
3176
- bubbles: true
3177
- })
3178
- );
3179
- };
3180
- let currentFocusedIndex = -1;
3181
- const setItemFocus = (index2) => {
3182
- items.forEach((item, i) => {
3183
- item.setAttribute("tabindex", i === index2 ? "0" : "-1");
3184
- });
3185
- if (items[index2]) {
3186
- items[index2].focus();
3187
- currentFocusedIndex = index2;
3188
- }
3189
- };
3190
- const commitCustomValue = (inputEl) => {
3191
- const finalValue = inputEl.value.trim();
3192
- let normSelected = getNormalizedSelected();
3193
- const toggleBtn = Array.from(items).find(isToggleBtn);
3194
- const toggleVal = toggleBtn ? toggleBtn.getAttribute("data-value") : null;
3195
- const standardValues = Array.from(items).filter((i) => !isToggleBtn(i)).map((i) => i.getAttribute("data-value"));
3196
- const customValues = normSelected.filter(
3197
- (val) => !standardValues.includes(val) && val !== "" && val !== toggleVal
3198
- );
3199
- const primaryCustomValue = customValues[customValues.length - 1];
3200
- if (primaryCustomValue) {
3201
- normSelected = normSelected.filter((v) => v !== primaryCustomValue);
3202
- }
3203
- if (finalValue !== "") {
3204
- if (!normSelected.includes(finalValue)) {
3205
- normSelected.push(finalValue);
3206
- }
3207
- } else {
3208
- if (toggleVal) {
3209
- normSelected = normSelected.filter((v) => v !== toggleVal);
3210
- }
3211
- }
3212
- if (isMultiple) {
3213
- selectedValue = normSelected.join(",");
3214
- } else {
3215
- selectedValue = finalValue;
3216
- }
3217
- updateUI();
3218
- const changeEvent = new CustomEvent(`${PREFIX4}-chip:change`, {
3219
- detail: { value: isMultiple ? getNormalizedSelected() : selectedValue },
3220
- bubbles: true
3221
- });
3222
- container.dispatchEvent(changeEvent);
3223
- };
3224
- items.forEach((item, index2) => {
3225
- item.addEventListener("click", (e) => {
3226
- if (item.hasAttribute("disabled")) return;
3227
- currentFocusedIndex = index2;
3228
- const val = item.getAttribute("data-value");
3229
- if (showCustomization && isToggleBtn(item)) {
3230
- const normSelected = getNormalizedSelected();
3231
- const standardValues = Array.from(items).filter((i) => !isToggleBtn(i)).map((i) => i.getAttribute("data-value"));
3232
- const customValues = normSelected.filter(
3233
- (v) => !standardValues.includes(v) && v !== "" && v !== val
3234
- );
3235
- const isInputVisible = normSelected.includes(val) || customValues.length > 0;
3236
- if (!isInputVisible) {
3237
- handleSelect(val);
3238
- }
3239
- } else {
3240
- handleSelect(val);
3241
- }
3242
- });
3243
- item.addEventListener("keydown", (e) => {
3244
- if (item.hasAttribute("disabled")) return;
3245
- if (e.key === "ArrowRight" || e.key === "ArrowDown") {
3246
- e.preventDefault();
3247
- let nextIndex = (index2 + 1) % items.length;
3248
- while (items[nextIndex].hasAttribute("disabled") && nextIndex !== index2) {
3249
- nextIndex = (nextIndex + 1) % items.length;
3250
- }
3251
- setItemFocus(nextIndex);
3252
- } else if (e.key === "ArrowLeft" || e.key === "ArrowUp") {
3253
- e.preventDefault();
3254
- let prevIndex = (index2 - 1 + items.length) % items.length;
3255
- while (items[prevIndex].hasAttribute("disabled") && prevIndex !== index2) {
3256
- prevIndex = (prevIndex - 1 + items.length) % items.length;
3257
- }
3258
- setItemFocus(prevIndex);
3259
- }
3260
- if (e.key === " " || e.key === "Enter") {
3261
- e.preventDefault();
3262
- item.click();
3263
- }
3264
- });
3265
- });
3266
- updateUI();
3267
- container.__inaChipInitialized = true;
3268
- });
3269
- }
3270
-
3271
- // src/js/components/stateful/pagination.js
3272
- function initPagination() {
3273
- document.querySelectorAll(`.${PREFIX}-pagination`).forEach((container) => {
3274
- if (container.dataset.initialized === "true") return;
3275
- container.dataset.initialized = "true";
3276
- const navButtonsContainer = container.querySelector(
3277
- `.${PREFIX}-pagination__nav-buttons`
3278
- );
3279
- const pageInfo = container.querySelector(
3280
- `.${PREFIX}-pagination__page-info`
3281
- );
3282
- const firstBtn = container.querySelector('[data-action="first"]');
3283
- const prevBtn = container.querySelector('[data-action="prev"]');
3284
- const nextBtn = container.querySelector('[data-action="next"]');
3285
- const lastBtn = container.querySelector('[data-action="last"]');
3286
- const pageSizeSelect = container.querySelector('[data-role="page-size"]');
3287
- if (!navButtonsContainer || !pageInfo) return;
3288
- let currentPage = parseInt(container.dataset.current || "1", 10);
3289
- let totalPages = parseInt(container.dataset.total || "10", 10);
3290
- let pageSize = parseInt(container.dataset.pageSize || "10", 10);
3291
- let isDisabled = container.dataset.disabled === "true";
3292
- let pageButtons = [];
3293
- const updateUI = () => {
3294
- pageInfo.textContent = `Halaman ${currentPage} dari ${totalPages}`;
3295
- const isFirst = currentPage === 1;
3296
- if (firstBtn) {
3297
- const disabled = isDisabled || isFirst;
3298
- firstBtn.disabled = disabled;
3299
- firstBtn.classList.toggle(
3300
- `${PREFIX}-pagination__nav-button--disabled`,
3301
- disabled
3302
- );
3303
- firstBtn.classList.toggle(
3304
- `${PREFIX}-pagination__nav-button--enabled`,
3305
- !disabled
3306
- );
3307
- }
3308
- if (prevBtn) {
3309
- const disabled = isDisabled || isFirst;
3310
- prevBtn.disabled = disabled;
3311
- prevBtn.classList.toggle(
3312
- `${PREFIX}-pagination__nav-button--disabled`,
3313
- disabled
3314
- );
3315
- prevBtn.classList.toggle(
3316
- `${PREFIX}-pagination__nav-button--enabled`,
3317
- !disabled
3318
- );
3169
+ if (prevBtn) {
3170
+ const disabled = isDisabled || isFirst;
3171
+ prevBtn.disabled = disabled;
3172
+ prevBtn.classList.toggle(
3173
+ `${PREFIX}-pagination__nav-button--disabled`,
3174
+ disabled
3175
+ );
3176
+ prevBtn.classList.toggle(
3177
+ `${PREFIX}-pagination__nav-button--enabled`,
3178
+ !disabled
3179
+ );
3319
3180
  }
3320
3181
  const isLast = currentPage === totalPages;
3321
3182
  if (nextBtn) {
@@ -3490,6 +3351,573 @@ var InaUI = (() => {
3490
3351
  });
3491
3352
  }
3492
3353
 
3354
+ // src/js/utils/countries.js
3355
+ var COUNTRIES = [
3356
+ { code: "ID", name: "Indonesia", dialCode: "+62" },
3357
+ { code: "AF", name: "Afghanistan", dialCode: "+93" },
3358
+ { code: "AL", name: "Albania", dialCode: "+355" },
3359
+ { code: "DZ", name: "Algeria", dialCode: "+213" },
3360
+ { code: "AS", name: "American Samoa", dialCode: "+1684" },
3361
+ { code: "AD", name: "Andorra", dialCode: "+376" },
3362
+ { code: "AO", name: "Angola", dialCode: "+244" },
3363
+ { code: "AI", name: "Anguilla", dialCode: "+1264" },
3364
+ { code: "AG", name: "Antigua and Barbuda", dialCode: "+1268" },
3365
+ { code: "AR", name: "Argentina", dialCode: "+54" },
3366
+ { code: "AM", name: "Armenia", dialCode: "+374" },
3367
+ { code: "AW", name: "Aruba", dialCode: "+297" },
3368
+ { code: "AU", name: "Australia", dialCode: "+61" },
3369
+ { code: "AT", name: "Austria", dialCode: "+43" },
3370
+ { code: "AZ", name: "Azerbaijan", dialCode: "+994" },
3371
+ { code: "BS", name: "Bahamas", dialCode: "+1242" },
3372
+ { code: "BH", name: "Bahrain", dialCode: "+973" },
3373
+ { code: "BD", name: "Bangladesh", dialCode: "+880" },
3374
+ { code: "BB", name: "Barbados", dialCode: "+1246" },
3375
+ { code: "BY", name: "Belarus", dialCode: "+375" },
3376
+ { code: "BE", name: "Belgium", dialCode: "+32" },
3377
+ { code: "BZ", name: "Belize", dialCode: "+501" },
3378
+ { code: "BJ", name: "Benin", dialCode: "+229" },
3379
+ { code: "BM", name: "Bermuda", dialCode: "+1441" },
3380
+ { code: "BT", name: "Bhutan", dialCode: "+975" },
3381
+ { code: "BO", name: "Bolivia", dialCode: "+591" },
3382
+ { code: "BA", name: "Bosnia and Herzegovina", dialCode: "+387" },
3383
+ { code: "BW", name: "Botswana", dialCode: "+267" },
3384
+ { code: "BR", name: "Brazil", dialCode: "+55" },
3385
+ { code: "IO", name: "British Indian Ocean Territory", dialCode: "+246" },
3386
+ { code: "BN", name: "Brunei Darussalam", dialCode: "+673" },
3387
+ { code: "BG", name: "Bulgaria", dialCode: "+359" },
3388
+ { code: "BF", name: "Burkina Faso", dialCode: "+226" },
3389
+ { code: "BI", name: "Burundi", dialCode: "+257" },
3390
+ { code: "KH", name: "Cambodia", dialCode: "+855" },
3391
+ { code: "CM", name: "Cameroon", dialCode: "+237" },
3392
+ { code: "CA", name: "Canada", dialCode: "+1" },
3393
+ { code: "CV", name: "Cape Verde", dialCode: "+238" },
3394
+ { code: "KY", name: "Cayman Islands", dialCode: "+1345" },
3395
+ { code: "CF", name: "Central African Republic", dialCode: "+236" },
3396
+ { code: "TD", name: "Chad", dialCode: "+235" },
3397
+ { code: "CL", name: "Chile", dialCode: "+56" },
3398
+ { code: "CN", name: "China", dialCode: "+86" },
3399
+ { code: "CX", name: "Christmas Island", dialCode: "+61" },
3400
+ { code: "CC", name: "Cocos (Keeling) Islands", dialCode: "+61" },
3401
+ { code: "CO", name: "Colombia", dialCode: "+57" },
3402
+ { code: "KM", name: "Comoros", dialCode: "+269" },
3403
+ { code: "CG", name: "Congo", dialCode: "+242" },
3404
+ { code: "CD", name: "Congo, Democratic Republic of the", dialCode: "+243" },
3405
+ { code: "CK", name: "Cook Islands", dialCode: "+682" },
3406
+ { code: "CR", name: "Costa Rica", dialCode: "+506" },
3407
+ { code: "CI", name: "Cote d'Ivoire", dialCode: "+225" },
3408
+ { code: "HR", name: "Croatia", dialCode: "+385" },
3409
+ { code: "CU", name: "Cuba", dialCode: "+53" },
3410
+ { code: "CY", name: "Cyprus", dialCode: "+357" },
3411
+ { code: "CZ", name: "Czech Republic", dialCode: "+420" },
3412
+ { code: "DK", name: "Denmark", dialCode: "+45" },
3413
+ { code: "DJ", name: "Djibouti", dialCode: "+253" },
3414
+ { code: "DM", name: "Dominica", dialCode: "+1767" },
3415
+ { code: "DO", name: "Dominican Republic", dialCode: "+1" },
3416
+ { code: "EC", name: "Ecuador", dialCode: "+593" },
3417
+ { code: "EG", name: "Egypt", dialCode: "+20" },
3418
+ { code: "SV", name: "El Salvador", dialCode: "+503" },
3419
+ { code: "GQ", name: "Equatorial Guinea", dialCode: "+240" },
3420
+ { code: "ER", name: "Eritrea", dialCode: "+291" },
3421
+ { code: "EE", name: "Estonia", dialCode: "+372" },
3422
+ { code: "ET", name: "Ethiopia", dialCode: "+251" },
3423
+ { code: "FK", name: "Falkland Islands (Malvinas)", dialCode: "+500" },
3424
+ { code: "FO", name: "Faroe Islands", dialCode: "+298" },
3425
+ { code: "FJ", name: "Fiji", dialCode: "+679" },
3426
+ { code: "FI", name: "Finland", dialCode: "+358" },
3427
+ { code: "FR", name: "France", dialCode: "+33" },
3428
+ { code: "GF", name: "French Guiana", dialCode: "+594" },
3429
+ { code: "PF", name: "French Polynesia", dialCode: "+689" },
3430
+ { code: "GA", name: "Gabon", dialCode: "+241" },
3431
+ { code: "GM", name: "Gambia", dialCode: "+220" },
3432
+ { code: "GE", name: "Georgia", dialCode: "+995" },
3433
+ { code: "DE", name: "Germany", dialCode: "+49" },
3434
+ { code: "GH", name: "Ghana", dialCode: "+233" },
3435
+ { code: "GI", name: "Gibraltar", dialCode: "+350" },
3436
+ { code: "GR", name: "Greece", dialCode: "+30" },
3437
+ { code: "GL", name: "Greenland", dialCode: "+299" },
3438
+ { code: "GD", name: "Grenada", dialCode: "+1473" },
3439
+ { code: "GP", name: "Guadeloupe", dialCode: "+590" },
3440
+ { code: "GU", name: "Guam", dialCode: "+1671" },
3441
+ { code: "GT", name: "Guatemala", dialCode: "+502" },
3442
+ { code: "GG", name: "Guernsey", dialCode: "+44" },
3443
+ { code: "GN", name: "Guinea", dialCode: "+224" },
3444
+ { code: "GW", name: "Guinea-Bissau", dialCode: "+245" },
3445
+ { code: "GY", name: "Guyana", dialCode: "+592" },
3446
+ { code: "HT", name: "Haiti", dialCode: "+509" },
3447
+ { code: "VA", name: "Holy See (Vatican City State)", dialCode: "+379" },
3448
+ { code: "HN", name: "Honduras", dialCode: "+504" },
3449
+ { code: "HK", name: "Hong Kong", dialCode: "+852" },
3450
+ { code: "HU", name: "Hungary", dialCode: "+36" },
3451
+ { code: "IS", name: "Iceland", dialCode: "+354" },
3452
+ { code: "IN", name: "India", dialCode: "+91" },
3453
+ { code: "IR", name: "Iran, Islamic Republic of", dialCode: "+98" },
3454
+ { code: "IQ", name: "Iraq", dialCode: "+964" },
3455
+ { code: "IE", name: "Ireland", dialCode: "+353" },
3456
+ { code: "IM", name: "Isle of Man", dialCode: "+44" },
3457
+ { code: "IL", name: "Israel", dialCode: "+972" },
3458
+ { code: "IT", name: "Italy", dialCode: "+39" },
3459
+ { code: "JM", name: "Jamaica", dialCode: "+1876" },
3460
+ { code: "JP", name: "Japan", dialCode: "+81" },
3461
+ { code: "JE", name: "Jersey", dialCode: "+44" },
3462
+ { code: "JO", name: "Jordan", dialCode: "+962" },
3463
+ { code: "KZ", name: "Kazakhstan", dialCode: "+7" },
3464
+ { code: "KE", name: "Kenya", dialCode: "+254" },
3465
+ { code: "KI", name: "Kiribati", dialCode: "+686" },
3466
+ { code: "KP", name: "Korea, Democratic People's Republic of", dialCode: "+850" },
3467
+ { code: "KR", name: "Korea, Republic of", dialCode: "+82" },
3468
+ { code: "KW", name: "Kuwait", dialCode: "+965" },
3469
+ { code: "KG", name: "Kyrgyzstan", dialCode: "+996" },
3470
+ { code: "LA", name: "Laos", dialCode: "+856" },
3471
+ { code: "LV", name: "Latvia", dialCode: "+371" },
3472
+ { code: "LB", name: "Lebanon", dialCode: "+961" },
3473
+ { code: "LS", name: "Lesotho", dialCode: "+266" },
3474
+ { code: "LR", name: "Liberia", dialCode: "+231" },
3475
+ { code: "LY", name: "Libyan Arab Jamahiriya", dialCode: "+218" },
3476
+ { code: "LI", name: "Liechtenstein", dialCode: "+423" },
3477
+ { code: "LT", name: "Lithuania", dialCode: "+370" },
3478
+ { code: "LU", name: "Luxembourg", dialCode: "+352" },
3479
+ { code: "MO", name: "Macao", dialCode: "+853" },
3480
+ { code: "MK", name: "Macedonia, the Former Yugoslav Republic of", dialCode: "+389" },
3481
+ { code: "MG", name: "Madagascar", dialCode: "+261" },
3482
+ { code: "MW", name: "Malawi", dialCode: "+265" },
3483
+ { code: "MY", name: "Malaysia", dialCode: "+60" },
3484
+ { code: "MV", name: "Maldives", dialCode: "+960" },
3485
+ { code: "ML", name: "Mali", dialCode: "+223" },
3486
+ { code: "MT", name: "Malta", dialCode: "+356" },
3487
+ { code: "MH", name: "Marshall Islands", dialCode: "+692" },
3488
+ { code: "MQ", name: "Martinique", dialCode: "+596" },
3489
+ { code: "MR", name: "Mauritania", dialCode: "+222" },
3490
+ { code: "MU", name: "Mauritius", dialCode: "+230" },
3491
+ { code: "YT", name: "Mayotte", dialCode: "+262" },
3492
+ { code: "MX", name: "Mexico", dialCode: "+52" },
3493
+ { code: "FM", name: "Micronesia, Federated States of", dialCode: "+691" },
3494
+ { code: "MD", name: "Moldova, Republic of", dialCode: "+373" },
3495
+ { code: "MC", name: "Monaco", dialCode: "+377" },
3496
+ { code: "MN", name: "Mongolia", dialCode: "+976" },
3497
+ { code: "ME", name: "Montenegro", dialCode: "+382" },
3498
+ { code: "MS", name: "Montserrat", dialCode: "+1664" },
3499
+ { code: "MA", name: "Morocco", dialCode: "+212" },
3500
+ { code: "MZ", name: "Mozambique", dialCode: "+258" },
3501
+ { code: "MM", name: "Myanmar", dialCode: "+95" },
3502
+ { code: "NA", name: "Namibia", dialCode: "+264" },
3503
+ { code: "NR", name: "Nauru", dialCode: "+674" },
3504
+ { code: "NP", name: "Nepal", dialCode: "+977" },
3505
+ { code: "NL", name: "Netherlands", dialCode: "+31" },
3506
+ { code: "NC", name: "New Caledonia", dialCode: "+687" },
3507
+ { code: "NZ", name: "New Zealand", dialCode: "+64" },
3508
+ { code: "NI", name: "Nicaragua", dialCode: "+505" },
3509
+ { code: "NE", name: "Niger", dialCode: "+227" },
3510
+ { code: "NG", name: "Nigeria", dialCode: "+234" },
3511
+ { code: "NU", name: "Niue", dialCode: "+683" },
3512
+ { code: "NF", name: "Norfolk Island", dialCode: "+672" },
3513
+ { code: "MP", name: "Northern Mariana Islands", dialCode: "+1670" },
3514
+ { code: "NO", name: "Norway", dialCode: "+47" },
3515
+ { code: "OM", name: "Oman", dialCode: "+968" },
3516
+ { code: "PK", name: "Pakistan", dialCode: "+92" },
3517
+ { code: "PW", name: "Palau", dialCode: "+680" },
3518
+ { code: "PS", name: "Palestine", dialCode: "+970" },
3519
+ { code: "PA", name: "Panama", dialCode: "+507" },
3520
+ { code: "PG", name: "Papua New Guinea", dialCode: "+675" },
3521
+ { code: "PY", name: "Paraguay", dialCode: "+595" },
3522
+ { code: "PE", name: "Peru", dialCode: "+51" },
3523
+ { code: "PH", name: "Philippines", dialCode: "+63" },
3524
+ { code: "PN", name: "Pitcairn", dialCode: "+870" },
3525
+ { code: "PL", name: "Poland", dialCode: "+48" },
3526
+ { code: "PT", name: "Portugal", dialCode: "+351" },
3527
+ { code: "PR", name: "Puerto Rico", dialCode: "+1939" },
3528
+ { code: "QA", name: "Qatar", dialCode: "+974" },
3529
+ { code: "RE", name: "Reunion", dialCode: "+262" },
3530
+ { code: "RO", name: "Romania", dialCode: "+40" },
3531
+ { code: "RU", name: "Russian Federation", dialCode: "+7" },
3532
+ { code: "RW", name: "Rwanda", dialCode: "+250" },
3533
+ { code: "BL", name: "Saint Barthelemy", dialCode: "+590" },
3534
+ { code: "SH", name: "Saint Helena", dialCode: "+290" },
3535
+ { code: "KN", name: "Saint Kitts and Nevis", dialCode: "+1869" },
3536
+ { code: "LC", name: "Saint Lucia", dialCode: "+1758" },
3537
+ { code: "MF", name: "Saint Martin", dialCode: "+590" },
3538
+ { code: "PM", name: "Saint Pierre and Miquelon", dialCode: "+508" },
3539
+ { code: "VC", name: "Saint Vincent and the Grenadines", dialCode: "+1784" },
3540
+ { code: "WS", name: "Samoa", dialCode: "+685" },
3541
+ { code: "SM", name: "San Marino", dialCode: "+378" },
3542
+ { code: "ST", name: "Sao Tome and Principe", dialCode: "+239" },
3543
+ { code: "SA", name: "Saudi Arabia", dialCode: "+966" },
3544
+ { code: "SN", name: "Senegal", dialCode: "+221" },
3545
+ { code: "RS", name: "Serbia", dialCode: "+381" },
3546
+ { code: "SC", name: "Seychelles", dialCode: "+248" },
3547
+ { code: "SL", name: "Sierra Leone", dialCode: "+232" },
3548
+ { code: "SG", name: "Singapore", dialCode: "+65" },
3549
+ { code: "SK", name: "Slovakia", dialCode: "+421" },
3550
+ { code: "SI", name: "Slovenia", dialCode: "+386" },
3551
+ { code: "SB", name: "Solomon Islands", dialCode: "+677" },
3552
+ { code: "SO", name: "Somalia", dialCode: "+252" },
3553
+ { code: "ZA", name: "South Africa", dialCode: "+27" },
3554
+ { code: "GS", name: "South Georgia and the South Sandwich Islands", dialCode: "+500" },
3555
+ { code: "ES", name: "Spain", dialCode: "+34" },
3556
+ { code: "LK", name: "Sri Lanka", dialCode: "+94" },
3557
+ { code: "SD", name: "Sudan", dialCode: "+249" },
3558
+ { code: "SR", name: "Suriname", dialCode: "+597" },
3559
+ { code: "SJ", name: "Svalbard and Jan Mayen", dialCode: "+47" },
3560
+ { code: "SZ", name: "Swaziland", dialCode: "+268" },
3561
+ { code: "SE", name: "Sweden", dialCode: "+46" },
3562
+ { code: "CH", name: "Switzerland", dialCode: "+41" },
3563
+ { code: "SY", name: "Syrian Arab Republic", dialCode: "+963" },
3564
+ { code: "TW", name: "Taiwan, Province of China", dialCode: "+886" },
3565
+ { code: "TJ", name: "Tajikistan", dialCode: "+992" },
3566
+ { code: "TZ", name: "Tanzania, United Republic of", dialCode: "+255" },
3567
+ { code: "TH", name: "Thailand", dialCode: "+66" },
3568
+ { code: "TL", name: "Timor-Leste", dialCode: "+670" },
3569
+ { code: "TG", name: "Togo", dialCode: "+228" },
3570
+ { code: "TK", name: "Tokelau", dialCode: "+690" },
3571
+ { code: "TO", name: "Tonga", dialCode: "+676" },
3572
+ { code: "TT", name: "Trinidad and Tobago", dialCode: "+1868" },
3573
+ { code: "TN", name: "Tunisia", dialCode: "+216" },
3574
+ { code: "TR", name: "Turkey", dialCode: "+90" },
3575
+ { code: "TM", name: "Turkmenistan", dialCode: "+993" },
3576
+ { code: "TC", name: "Turks and Caicos Islands", dialCode: "+1649" },
3577
+ { code: "TV", name: "Tuvalu", dialCode: "+688" },
3578
+ { code: "UG", name: "Uganda", dialCode: "+256" },
3579
+ { code: "UA", name: "Ukraine", dialCode: "+380" },
3580
+ { code: "AE", name: "United Arab Emirates", dialCode: "+971" },
3581
+ { code: "GB", name: "United Kingdom", dialCode: "+44" },
3582
+ { code: "US", name: "United States", dialCode: "+1" },
3583
+ { code: "UY", name: "Uruguay", dialCode: "+598" },
3584
+ { code: "UZ", name: "Uzbekistan", dialCode: "+998" },
3585
+ { code: "VU", name: "Vanuatu", dialCode: "+678" },
3586
+ { code: "VE", name: "Venezuela", dialCode: "+58" },
3587
+ { code: "VN", name: "Vietnam", dialCode: "+84" },
3588
+ { code: "VG", name: "Virgin Islands, British", dialCode: "+1284" },
3589
+ { code: "VI", name: "Virgin Islands, U.S.", dialCode: "+1340" },
3590
+ { code: "WF", name: "Wallis and Futuna", dialCode: "+681" },
3591
+ { code: "EH", name: "Western Sahara", dialCode: "+212" },
3592
+ { code: "YE", name: "Yemen", dialCode: "+967" },
3593
+ { code: "ZM", name: "Zambia", dialCode: "+260" },
3594
+ { code: "ZW", name: "Zimbabwe", dialCode: "+263" }
3595
+ ];
3596
+
3597
+ // src/js/utils/flags.js
3598
+ var flagCache = {};
3599
+ var getFlag = async (code) => {
3600
+ if (flagCache[code]) {
3601
+ return flagCache[code];
3602
+ }
3603
+ try {
3604
+ const flag = await import(`@idds/styles/assets/flags/${code.toLowerCase()}.svg`);
3605
+ flagCache[code] = flag.default;
3606
+ return flag.default;
3607
+ } catch (error) {
3608
+ console.error(`[IDDS PhoneInput] Failed to load flag for: ${code}`, error);
3609
+ return "";
3610
+ }
3611
+ };
3612
+
3613
+ // src/js/components/stateful/phone-input.js
3614
+ var PhoneInput = class {
3615
+ constructor(selectorOrElement, options = {}) {
3616
+ this.container = typeof selectorOrElement === "string" ? document.querySelector(selectorOrElement) : selectorOrElement;
3617
+ if (!this.container) {
3618
+ console.warn("[IDDS PhoneInput] Container not found:", selectorOrElement);
3619
+ return;
3620
+ }
3621
+ if (this.container.dataset.initialized === "true") {
3622
+ return;
3623
+ }
3624
+ this.container.dataset.initialized = "true";
3625
+ this.options = {
3626
+ modelValue: this.container.dataset.value || "",
3627
+ label: this.container.dataset.label || "",
3628
+ placeholder: this.container.getAttribute("placeholder") || "812-3456-7890",
3629
+ size: this.container.dataset.size || "md",
3630
+ status: this.container.dataset.status || "neutral",
3631
+ disabled: this.container.hasAttribute("disabled") || false,
3632
+ readonly: this.container.hasAttribute("readonly") || false,
3633
+ required: this.container.hasAttribute("required") || false,
3634
+ defaultCountry: this.container.dataset.defaultCountry || "ID",
3635
+ allowClear: this.container.dataset.allowClear !== "false",
3636
+ countries: COUNTRIES,
3637
+ onChange: null,
3638
+ ...options
3639
+ };
3640
+ this.state = {
3641
+ isOpen: false,
3642
+ countrySearch: "",
3643
+ selectedCountry: this.options.countries.find((c) => c.code === this.options.defaultCountry) || this.options.countries[0],
3644
+ phoneNumber: ""
3645
+ };
3646
+ this.elements = {};
3647
+ this.inputId = `phone-input-${Math.random().toString(36).substr(2, 9)}`;
3648
+ this.init();
3649
+ }
3650
+ async init() {
3651
+ this.initDOM();
3652
+ this.initEvents();
3653
+ this.syncValueFromOptions();
3654
+ await this.updateFlag();
3655
+ }
3656
+ initDOM() {
3657
+ if (this.options.label) {
3658
+ const label = document.createElement("label");
3659
+ label.className = `${PREFIX}-phone-input__label`;
3660
+ label.setAttribute("for", this.inputId);
3661
+ label.textContent = this.options.label;
3662
+ if (this.options.required) {
3663
+ const asterisk = document.createElement("span");
3664
+ asterisk.className = `${PREFIX}-phone-input__required`;
3665
+ asterisk.textContent = "*";
3666
+ label.appendChild(asterisk);
3667
+ }
3668
+ this.container.appendChild(label);
3669
+ }
3670
+ const wrapper = document.createElement("div");
3671
+ wrapper.className = `${PREFIX}-phone-input__wrapper ${PREFIX}-phone-input__wrapper--size-${this.options.size}`;
3672
+ if (this.options.status !== "neutral") {
3673
+ wrapper.classList.add(`${PREFIX}-phone-input__wrapper--status-${this.options.status}`);
3674
+ }
3675
+ if (this.options.disabled) {
3676
+ wrapper.classList.add(`${PREFIX}-phone-input__wrapper--disabled`);
3677
+ }
3678
+ const selector = document.createElement("div");
3679
+ selector.className = `${PREFIX}-phone-input__country-selector`;
3680
+ const countryBtn = document.createElement("button");
3681
+ countryBtn.type = "button";
3682
+ countryBtn.className = `${PREFIX}-phone-input__country-button`;
3683
+ countryBtn.setAttribute("aria-label", "Pilih negara");
3684
+ countryBtn.setAttribute("aria-haspopup", "listbox");
3685
+ countryBtn.setAttribute("aria-expanded", "false");
3686
+ if (this.options.disabled || this.options.readonly) countryBtn.disabled = true;
3687
+ const flagImg = document.createElement("img");
3688
+ flagImg.className = `${PREFIX}-phone-input__country-flag-img`;
3689
+ flagImg.width = 24;
3690
+ flagImg.height = 18;
3691
+ flagImg.alt = "";
3692
+ const dialCode = document.createElement("span");
3693
+ dialCode.className = `${PREFIX}-phone-input__country-code`;
3694
+ dialCode.textContent = this.state.selectedCountry.dialCode;
3695
+ const chevron = document.createElement("div");
3696
+ chevron.innerHTML = `<svg class="${PREFIX}-phone-input__country-chevron" width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
3697
+ <path d="M6 9L12 15L18 9" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3698
+ </svg>`;
3699
+ countryBtn.appendChild(flagImg);
3700
+ countryBtn.appendChild(dialCode);
3701
+ countryBtn.appendChild(chevron.firstChild);
3702
+ selector.appendChild(countryBtn);
3703
+ wrapper.appendChild(selector);
3704
+ const divider = document.createElement("div");
3705
+ divider.className = `${PREFIX}-phone-input__divider`;
3706
+ wrapper.appendChild(divider);
3707
+ const input = document.createElement("input");
3708
+ input.type = "tel";
3709
+ input.id = this.inputId;
3710
+ input.placeholder = this.options.placeholder;
3711
+ input.className = `${PREFIX}-phone-input__input`;
3712
+ if (this.options.disabled) input.disabled = true;
3713
+ if (this.options.readonly) input.readOnly = true;
3714
+ wrapper.appendChild(input);
3715
+ if (this.options.allowClear) {
3716
+ const clearBtn = document.createElement("button");
3717
+ clearBtn.type = "button";
3718
+ clearBtn.className = `${PREFIX}-phone-input__clear-button`;
3719
+ clearBtn.setAttribute("aria-label", "Hapus nomor telepon");
3720
+ clearBtn.innerHTML = `<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
3721
+ <line x1="18" y1="6" x2="6" y2="18"></line>
3722
+ <line x1="6" y1="6" x2="18" y2="18"></line>
3723
+ </svg>`;
3724
+ clearBtn.style.display = "none";
3725
+ wrapper.appendChild(clearBtn);
3726
+ this.elements.clearBtn = clearBtn;
3727
+ }
3728
+ this.container.appendChild(wrapper);
3729
+ const panel = document.createElement("div");
3730
+ panel.className = `${PREFIX}-phone-input__country-dropdown`;
3731
+ panel.style.display = "none";
3732
+ const searchDiv = document.createElement("div");
3733
+ searchDiv.className = `${PREFIX}-phone-input__country-search`;
3734
+ const searchInput = document.createElement("input");
3735
+ searchInput.type = "text";
3736
+ searchInput.placeholder = "Cari";
3737
+ searchInput.className = `${PREFIX}-phone-input__country-search-input`;
3738
+ searchDiv.appendChild(searchInput);
3739
+ panel.appendChild(searchDiv);
3740
+ const list = document.createElement("div");
3741
+ list.className = `${PREFIX}-phone-input__country-list`;
3742
+ list.setAttribute("role", "listbox");
3743
+ panel.appendChild(list);
3744
+ selector.appendChild(panel);
3745
+ this.elements.wrapper = wrapper;
3746
+ this.elements.countryBtn = countryBtn;
3747
+ this.elements.flagImg = flagImg;
3748
+ this.elements.dialCode = dialCode;
3749
+ this.elements.input = input;
3750
+ this.elements.panel = panel;
3751
+ this.elements.searchInput = searchInput;
3752
+ this.elements.list = list;
3753
+ this.elements.chevron = selector.querySelector(`.${PREFIX}-phone-input__country-chevron`);
3754
+ }
3755
+ initEvents() {
3756
+ this.elements.countryBtn.addEventListener("click", (e) => {
3757
+ e.stopPropagation();
3758
+ this.toggleDropdown();
3759
+ });
3760
+ this.elements.searchInput.addEventListener("input", (e) => {
3761
+ this.state.countrySearch = e.target.value;
3762
+ this.renderCountryList();
3763
+ });
3764
+ this.elements.input.addEventListener("input", (e) => {
3765
+ this.handleInput(e);
3766
+ });
3767
+ if (this.elements.clearBtn) {
3768
+ this.elements.clearBtn.addEventListener("click", () => {
3769
+ this.clear();
3770
+ });
3771
+ this.elements.clearBtn.addEventListener("keydown", (e) => {
3772
+ if (e.key === "Enter" || e.key === " ") {
3773
+ e.preventDefault();
3774
+ this.clear();
3775
+ }
3776
+ });
3777
+ }
3778
+ document.addEventListener("click", (e) => {
3779
+ if (!this.elements.wrapper.contains(e.target)) {
3780
+ this.closeDropdown();
3781
+ }
3782
+ });
3783
+ }
3784
+ async updateFlag() {
3785
+ const url = await getFlag(this.state.selectedCountry.code);
3786
+ this.elements.flagImg.src = url;
3787
+ this.elements.flagImg.alt = this.state.selectedCountry.name;
3788
+ this.elements.dialCode.textContent = this.state.selectedCountry.dialCode;
3789
+ }
3790
+ toggleDropdown() {
3791
+ if (this.state.isOpen) {
3792
+ this.closeDropdown();
3793
+ } else {
3794
+ this.openDropdown();
3795
+ }
3796
+ }
3797
+ openDropdown() {
3798
+ this.state.isOpen = true;
3799
+ this.elements.panel.style.display = "flex";
3800
+ this.elements.countryBtn.setAttribute("aria-expanded", "true");
3801
+ this.elements.chevron.classList.add(`${PREFIX}-phone-input__country-chevron--open`);
3802
+ this.state.countrySearch = "";
3803
+ this.elements.searchInput.value = "";
3804
+ this.renderCountryList();
3805
+ setTimeout(() => this.elements.searchInput.focus(), 0);
3806
+ }
3807
+ closeDropdown() {
3808
+ this.state.isOpen = false;
3809
+ this.elements.panel.style.display = "none";
3810
+ this.elements.countryBtn.setAttribute("aria-expanded", "false");
3811
+ this.elements.chevron.classList.remove(`${PREFIX}-phone-input__country-chevron--open`);
3812
+ }
3813
+ renderCountryList() {
3814
+ const list = this.elements.list;
3815
+ list.innerHTML = "";
3816
+ const filtered = this.options.countries.filter(
3817
+ (c) => c.name.toLowerCase().includes(this.state.countrySearch.toLowerCase()) || c.dialCode.includes(this.state.countrySearch) || c.code.toLowerCase().includes(this.state.countrySearch.toLowerCase())
3818
+ );
3819
+ filtered.forEach(async (country) => {
3820
+ const option = document.createElement("button");
3821
+ option.type = "button";
3822
+ option.className = `${PREFIX}-phone-input__country-option`;
3823
+ if (country.code === this.state.selectedCountry.code) {
3824
+ option.classList.add(`${PREFIX}-phone-input__country-option--selected`);
3825
+ }
3826
+ option.setAttribute("role", "option");
3827
+ option.setAttribute("aria-selected", country.code === this.state.selectedCountry.code ? "true" : "false");
3828
+ const flag = document.createElement("img");
3829
+ flag.className = `${PREFIX}-phone-input__country-flag-img`;
3830
+ flag.width = 20;
3831
+ flag.height = 15;
3832
+ getFlag(country.code).then((url) => flag.src = url);
3833
+ const name = document.createElement("span");
3834
+ name.className = `${PREFIX}-phone-input__country-name`;
3835
+ name.textContent = `${country.name} (${country.code})`;
3836
+ const code = document.createElement("span");
3837
+ code.className = `${PREFIX}-phone-input__country-dial-code`;
3838
+ code.textContent = country.dialCode;
3839
+ option.appendChild(flag);
3840
+ option.appendChild(name);
3841
+ option.appendChild(code);
3842
+ option.addEventListener("click", () => {
3843
+ this.selectCountry(country);
3844
+ });
3845
+ list.appendChild(option);
3846
+ });
3847
+ }
3848
+ selectCountry(country) {
3849
+ this.state.selectedCountry = country;
3850
+ this.updateFlag();
3851
+ this.closeDropdown();
3852
+ this.elements.input.focus();
3853
+ this.triggerChange();
3854
+ }
3855
+ formatPhoneNumber(value) {
3856
+ const clean = value.replace(/\D/g, "");
3857
+ if (clean.length > 7) {
3858
+ return clean.replace(/^(\d{3})(\d{4})(.*)/, "$1-$2-$3");
3859
+ } else if (clean.length > 3) {
3860
+ return clean.replace(/^(\d{3})(.*)/, "$1-$2");
3861
+ }
3862
+ return clean;
3863
+ }
3864
+ handleInput(e) {
3865
+ const value = e.target.value;
3866
+ const formatted = this.formatPhoneNumber(value);
3867
+ e.target.value = formatted;
3868
+ this.state.phoneNumber = formatted;
3869
+ if (this.elements.clearBtn) {
3870
+ this.elements.clearBtn.style.display = formatted ? "flex" : "none";
3871
+ }
3872
+ this.triggerChange();
3873
+ }
3874
+ clear() {
3875
+ this.state.phoneNumber = "";
3876
+ this.elements.input.value = "";
3877
+ if (this.elements.clearBtn) {
3878
+ this.elements.clearBtn.style.display = "none";
3879
+ }
3880
+ this.elements.input.focus();
3881
+ this.triggerChange();
3882
+ }
3883
+ syncValueFromOptions() {
3884
+ if (this.options.modelValue) {
3885
+ let val = this.options.modelValue;
3886
+ const dial = this.state.selectedCountry.dialCode;
3887
+ if (val.startsWith(dial)) {
3888
+ val = val.substring(dial.length);
3889
+ }
3890
+ this.state.phoneNumber = this.formatPhoneNumber(val);
3891
+ this.elements.input.value = this.state.phoneNumber;
3892
+ if (this.elements.clearBtn && this.state.phoneNumber) {
3893
+ this.elements.clearBtn.style.display = "flex";
3894
+ }
3895
+ }
3896
+ }
3897
+ triggerChange() {
3898
+ const cleanLocal = this.state.phoneNumber.replace(/\D/g, "");
3899
+ const cleanNoZero = cleanLocal.startsWith("0") ? cleanLocal.substring(1) : cleanLocal;
3900
+ const fullValue = `${this.state.selectedCountry.dialCode}${cleanNoZero}`;
3901
+ if (this.options.onChange) {
3902
+ this.options.onChange(fullValue);
3903
+ }
3904
+ this.container.dispatchEvent(new CustomEvent("change", {
3905
+ detail: { value: fullValue, country: this.state.selectedCountry }
3906
+ }));
3907
+ }
3908
+ };
3909
+ function initPhoneInput(selectorOrElement, options = {}) {
3910
+ const elements = typeof selectorOrElement === "string" ? document.querySelectorAll(selectorOrElement) : selectorOrElement ? typeof selectorOrElement.length !== "undefined" ? selectorOrElement : [selectorOrElement] : document.querySelectorAll(`.${PREFIX}-phone-input`);
3911
+ const instances = [];
3912
+ elements.forEach((container) => {
3913
+ const instance = new PhoneInput(container, options);
3914
+ container.__phoneInputAPI = instance;
3915
+ instances.push(instance);
3916
+ });
3917
+ if (instances.length === 0) return null;
3918
+ return instances.length === 1 ? instances[0] : instances;
3919
+ }
3920
+
3493
3921
  // src/js/components/stateful/tab-vertical.js
3494
3922
  function initTabVertical() {
3495
3923
  const tabs = document.querySelectorAll(`.${PREFIX}-tab-vertical`);
@@ -3602,7 +4030,7 @@ var InaUI = (() => {
3602
4030
 
3603
4031
  // src/js/components/stateful/table.js
3604
4032
  var Table = class {
3605
- constructor(selectorOrElement, options2 = {}) {
4033
+ constructor(selectorOrElement, options = {}) {
3606
4034
  this.container = typeof selectorOrElement === "string" ? document.querySelector(selectorOrElement) : selectorOrElement;
3607
4035
  if (!this.container) {
3608
4036
  console.warn("[IDDS Table] Container not found:", selectorOrElement);
@@ -3634,7 +4062,7 @@ var InaUI = (() => {
3634
4062
  searchContainer: null,
3635
4063
  searchButton: null,
3636
4064
  onSearch: null,
3637
- ...options2
4065
+ ...options
3638
4066
  };
3639
4067
  this.state = {
3640
4068
  currentPage: this.options.initialPage,
@@ -3753,34 +4181,43 @@ var InaUI = (() => {
3753
4181
  if (col.sortable && col.accessor) {
3754
4182
  th.classList.add(`${PREFIX}-table__header-cell--sortable`);
3755
4183
  th.setAttribute("data-sort", col.accessor);
4184
+ let sortLabel = `Urutkan ${col.header}`;
4185
+ let currentSort = "none";
4186
+ if (this.state.sortField === field) {
4187
+ currentSort = this.state.sortOrder === "asc" ? "ascending" : "descending";
4188
+ }
4189
+ th.setAttribute("aria-sort", currentSort);
3756
4190
  let sortControlsHtml = `
3757
4191
  <div class="${PREFIX}-table__sort-controls">
3758
4192
  ${col.header}
3759
4193
  <div class="${PREFIX}-table__sort-icon">
3760
- <div class="${PREFIX}-table__sort-button" data-order="asc">
4194
+ <div class="${PREFIX}-table__sort-button" data-order="asc" role="button" aria-label="Urutkan ${col.header} menaik">
3761
4195
  <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"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M12 5l0 14" /><path d="M16 9l-4 -4" /><path d="M8 9l4 -4" /></svg>
3762
4196
  </div>
3763
- <div class="${PREFIX}-table__sort-button ${PREFIX}-table__sort-button-right" data-order="desc">
4197
+ <div class="${PREFIX}-table__sort-button ${PREFIX}-table__sort-button-right" data-order="desc" role="button" aria-label="Urutkan ${col.header} menurun">
3764
4198
  <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"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M12 5l0 14" /><path d="M16 15l-4 4" /><path d="M8 15l4 4" /></svg>
3765
4199
  </div>
3766
4200
  </div>
3767
4201
  </div>
3768
4202
  `;
3769
4203
  th.innerHTML = sortControlsHtml;
4204
+ const ascBtn = th.querySelector('[data-order="asc"]');
4205
+ const descBtn = th.querySelector('[data-order="desc"]');
4206
+ ascBtn.addEventListener("click", (e) => {
4207
+ e.stopPropagation();
4208
+ this.handleHeaderSort(col, "asc");
4209
+ });
4210
+ descBtn.addEventListener("click", (e) => {
4211
+ e.stopPropagation();
4212
+ this.handleHeaderSort(col, "desc");
4213
+ });
3770
4214
  th.addEventListener("click", () => {
3771
- const field = col.accessor;
4215
+ let nextOrder = "asc";
3772
4216
  if (this.state.sortField === field) {
3773
- if (this.state.sortOrder === "asc") this.state.sortOrder = "desc";
3774
- else {
3775
- this.state.sortField = null;
3776
- this.state.sortOrder = null;
3777
- }
3778
- } else {
3779
- this.state.sortField = field;
3780
- this.state.sortOrder = "asc";
4217
+ if (this.state.sortOrder === "asc") nextOrder = "desc";
4218
+ else nextOrder = null;
3781
4219
  }
3782
- this.state.currentPage = 1;
3783
- this.loadData();
4220
+ this.handleHeaderSort(col, nextOrder);
3784
4221
  });
3785
4222
  } else {
3786
4223
  th.textContent = col.header;
@@ -3839,7 +4276,7 @@ var InaUI = (() => {
3839
4276
  this.updateSelectAllState();
3840
4277
  return;
3841
4278
  }
3842
- rowData.forEach((row, index2) => {
4279
+ rowData.forEach((row, index) => {
3843
4280
  const tr = document.createElement("tr");
3844
4281
  tr.className = `${PREFIX}-table__row`;
3845
4282
  if (this.options.rowClickable) {
@@ -3850,11 +4287,11 @@ var InaUI = (() => {
3850
4287
  return;
3851
4288
  }
3852
4289
  if (typeof this.options.onRowClick === "function") {
3853
- this.options.onRowClick(row, index2);
4290
+ this.options.onRowClick(row, index);
3854
4291
  }
3855
4292
  });
3856
4293
  }
3857
- const rowKeyStr = String(row[this.options.rowKey] || index2);
4294
+ const rowKeyStr = String(row[this.options.rowKey] || index);
3858
4295
  if (this.options.selectable) {
3859
4296
  const td = document.createElement("td");
3860
4297
  td.className = `${PREFIX}-table__cell`;
@@ -3880,7 +4317,7 @@ var InaUI = (() => {
3880
4317
  const td = document.createElement("td");
3881
4318
  td.className = `${PREFIX}-table__cell`;
3882
4319
  if (typeof col.render === "function") {
3883
- const content = col.render(row, index2);
4320
+ const content = col.render(row, index);
3884
4321
  if (typeof content === "string") {
3885
4322
  td.innerHTML = content;
3886
4323
  } else if (content instanceof HTMLElement) {
@@ -4026,6 +4463,13 @@ var InaUI = (() => {
4026
4463
  }
4027
4464
  );
4028
4465
  }
4466
+ handleHeaderSort(col, order) {
4467
+ const field2 = col.accessor;
4468
+ this.state.sortField = field2 ? order === null ? null : field2 : null;
4469
+ this.state.sortOrder = order;
4470
+ this.state.currentPage = 1;
4471
+ this.loadData();
4472
+ }
4029
4473
  updateSortIndicators() {
4030
4474
  const btns = this.elements.theadTr.querySelectorAll(
4031
4475
  `.${PREFIX}-table__sort-button`
@@ -4033,10 +4477,15 @@ var InaUI = (() => {
4033
4477
  btns.forEach((btn) => {
4034
4478
  const th = btn.closest("th");
4035
4479
  if (!th) return;
4036
- const field = th.getAttribute("data-sort");
4480
+ const field2 = th.getAttribute("data-sort");
4037
4481
  const order = btn.getAttribute("data-order");
4038
- const active = this.state.sortField === field && this.state.sortOrder === order;
4482
+ const active = this.state.sortField === field2 && this.state.sortOrder === order;
4039
4483
  btn.classList.toggle(`${PREFIX}-table__sort-button--active`, active);
4484
+ let currentSort = "none";
4485
+ if (this.state.sortField === field2) {
4486
+ currentSort = this.state.sortOrder === "asc" ? "ascending" : "descending";
4487
+ }
4488
+ th.setAttribute("aria-sort", currentSort);
4040
4489
  });
4041
4490
  }
4042
4491
  async loadData() {
@@ -4114,8 +4563,8 @@ var InaUI = (() => {
4114
4563
  this.triggerSelectionChange();
4115
4564
  }
4116
4565
  toggleAllSelection(checked) {
4117
- this.state.currentData.forEach((row, index2) => {
4118
- const keyStr = String(row[this.options.rowKey] || index2);
4566
+ this.state.currentData.forEach((row, index) => {
4567
+ const keyStr = String(row[this.options.rowKey] || index);
4119
4568
  if (checked) {
4120
4569
  this.state.selectedKeys.add(keyStr);
4121
4570
  this.state.selectedRows.set(keyStr, row);
@@ -4196,11 +4645,11 @@ var InaUI = (() => {
4196
4645
  };
4197
4646
  }
4198
4647
  };
4199
- function initTable(selectorOrElement, options2 = {}) {
4648
+ function initTable(selectorOrElement, options = {}) {
4200
4649
  const elements = typeof selectorOrElement === "string" ? document.querySelectorAll(selectorOrElement) : selectorOrElement ? typeof selectorOrElement.length !== "undefined" ? selectorOrElement : [selectorOrElement] : document.querySelectorAll(`.${PREFIX}-table`);
4201
4650
  const instances = [];
4202
4651
  elements.forEach((container) => {
4203
- const instance = new Table(container, options2);
4652
+ const instance = new Table(container, options);
4204
4653
  container.__tableAPI = instance;
4205
4654
  instances.push(instance);
4206
4655
  });
@@ -4234,17 +4683,17 @@ var InaUI = (() => {
4234
4683
  const trigger = container.querySelector(`.${PREFIX}-month-picker__trigger`);
4235
4684
  const panel = container.querySelector(`.${PREFIX}-month-picker__panel`);
4236
4685
  const grid = container.querySelector(`.${PREFIX}-month-picker__grid`);
4237
- const options2 = grid ? Array.from(
4686
+ const options = grid ? Array.from(
4238
4687
  grid.querySelectorAll(`.${PREFIX}-month-picker__month-option`)
4239
4688
  ) : [];
4240
- if (!trigger || !panel || !grid || options2.length === 0) return;
4689
+ if (!trigger || !panel || !grid || options.length === 0) return;
4241
4690
  let isPickerOpen = false;
4242
4691
  const updateText = () => {
4243
4692
  const textEl = trigger.querySelector(
4244
4693
  `.${PREFIX}-month-picker__trigger-text`
4245
4694
  );
4246
4695
  if (textEl) textEl.textContent = MONTHS_SHORT_ID[currentMonthIdx];
4247
- options2.forEach((opt, idx) => {
4696
+ options.forEach((opt, idx) => {
4248
4697
  if (idx === currentMonthIdx) {
4249
4698
  opt.classList.add(`${PREFIX}-month-picker__month-option--selected`);
4250
4699
  opt.setAttribute("aria-selected", "true");
@@ -4265,7 +4714,7 @@ var InaUI = (() => {
4265
4714
  panel.classList.add(`${PREFIX}-month-picker__panel--open`);
4266
4715
  trigger.setAttribute("aria-expanded", "true");
4267
4716
  setTimeout(() => {
4268
- const selectedOpt = options2.find((o) => o.tabIndex === 0);
4717
+ const selectedOpt = options.find((o) => o.tabIndex === 0);
4269
4718
  if (selectedOpt) selectedOpt.focus();
4270
4719
  }, 0);
4271
4720
  } else {
@@ -4289,7 +4738,7 @@ var InaUI = (() => {
4289
4738
  document.addEventListener("click", (e) => {
4290
4739
  if (!container.contains(e.target)) togglePicker(false);
4291
4740
  });
4292
- options2.forEach((btn, idx) => {
4741
+ options.forEach((btn, idx) => {
4293
4742
  btn.setAttribute("role", "option");
4294
4743
  btn.addEventListener("click", (e) => {
4295
4744
  if (disabled || readonly) return;
@@ -4332,8 +4781,8 @@ var InaUI = (() => {
4332
4781
  else if (e.key === "ArrowDown")
4333
4782
  nextIndex += 3;
4334
4783
  else if (e.key === "ArrowUp") nextIndex -= 3;
4335
- if (options2[nextIndex]) {
4336
- options2[nextIndex].focus();
4784
+ if (options[nextIndex]) {
4785
+ options[nextIndex].focus();
4337
4786
  }
4338
4787
  }
4339
4788
  });
@@ -4434,12 +4883,12 @@ var InaUI = (() => {
4434
4883
  } else if (["ArrowRight", "ArrowLeft", "ArrowDown", "ArrowUp"].includes(e.key)) {
4435
4884
  e.preventDefault();
4436
4885
  e.stopPropagation();
4437
- const options2 = Array.from(
4886
+ const options = Array.from(
4438
4887
  grid.querySelectorAll(
4439
4888
  `.${PREFIX}-year-picker__year-option:not(:disabled)`
4440
4889
  )
4441
4890
  );
4442
- const currentIndex = options2.indexOf(btn);
4891
+ const currentIndex = options.indexOf(btn);
4443
4892
  if (currentIndex === -1) return;
4444
4893
  let nextIndex = currentIndex;
4445
4894
  if (e.key === "ArrowRight") nextIndex += 1;
@@ -4447,8 +4896,8 @@ var InaUI = (() => {
4447
4896
  else if (e.key === "ArrowDown")
4448
4897
  nextIndex += 4;
4449
4898
  else if (e.key === "ArrowUp") nextIndex -= 4;
4450
- if (options2[nextIndex]) {
4451
- options2[nextIndex].focus();
4899
+ if (options[nextIndex]) {
4900
+ options[nextIndex].focus();
4452
4901
  } else {
4453
4902
  }
4454
4903
  }
@@ -4575,7 +5024,7 @@ var InaUI = (() => {
4575
5024
  return { toastItem, toast };
4576
5025
  }
4577
5026
  function showToast(optionsOrMessage, variant = "default", duration = 5e3) {
4578
- const options2 = typeof optionsOrMessage === "string" ? {
5027
+ const options = typeof optionsOrMessage === "string" ? {
4579
5028
  message: optionsOrMessage,
4580
5029
  state: variant,
4581
5030
  duration
@@ -4588,7 +5037,7 @@ var InaUI = (() => {
4588
5037
  duration: autoCloseDuration = 5e3,
4589
5038
  position = "top-right",
4590
5039
  actionHtml = ""
4591
- } = options2;
5040
+ } = options;
4592
5041
  const container = getOrCreateContainer(position);
4593
5042
  const { toastItem, toast } = createToastElement({
4594
5043
  title,
@@ -4656,6 +5105,12 @@ var InaUI = (() => {
4656
5105
  const buttons = buttonGroup.querySelectorAll(
4657
5106
  `.${PREFIX}-button-group__button`
4658
5107
  );
5108
+ if (!buttonGroup.hasAttribute("role")) {
5109
+ buttonGroup.setAttribute("role", "group");
5110
+ }
5111
+ if (!buttonGroup.hasAttribute("aria-label")) {
5112
+ buttonGroup.setAttribute("aria-label", "Grup tombol");
5113
+ }
4659
5114
  const updateState = (clickedButton) => {
4660
5115
  const isDisabled = clickedButton.hasAttribute("disabled") || clickedButton.classList.contains(
4661
5116
  `${PREFIX}-button-group__button--disabled`
@@ -4679,7 +5134,7 @@ var InaUI = (() => {
4679
5134
  })
4680
5135
  );
4681
5136
  };
4682
- buttons.forEach((button, index2) => {
5137
+ buttons.forEach((button, index) => {
4683
5138
  button.addEventListener("click", (e) => {
4684
5139
  if (button.type !== "submit") {
4685
5140
  e.preventDefault();
@@ -4694,19 +5149,19 @@ var InaUI = (() => {
4694
5149
  updateState(button);
4695
5150
  } else if (e.key === "ArrowRight" || e.key === "ArrowDown") {
4696
5151
  e.preventDefault();
4697
- let nextIndex = (index2 + 1) % buttons.length;
5152
+ let nextIndex = (index + 1) % buttons.length;
4698
5153
  while ((buttons[nextIndex].hasAttribute("disabled") || buttons[nextIndex].classList.contains(
4699
5154
  `${PREFIX}-button-group__button--disabled`
4700
- )) && nextIndex !== index2) {
5155
+ )) && nextIndex !== index) {
4701
5156
  nextIndex = (nextIndex + 1) % buttons.length;
4702
5157
  }
4703
5158
  buttons[nextIndex]?.focus();
4704
5159
  } else if (e.key === "ArrowLeft" || e.key === "ArrowUp") {
4705
5160
  e.preventDefault();
4706
- let prevIndex = (index2 - 1 + buttons.length) % buttons.length;
5161
+ let prevIndex = (index - 1 + buttons.length) % buttons.length;
4707
5162
  while ((buttons[prevIndex].hasAttribute("disabled") || buttons[prevIndex].classList.contains(
4708
5163
  `${PREFIX}-button-group__button--disabled`
4709
- )) && prevIndex !== index2) {
5164
+ )) && prevIndex !== index) {
4710
5165
  prevIndex = (prevIndex - 1 + buttons.length) % buttons.length;
4711
5166
  }
4712
5167
  buttons[prevIndex]?.focus();
@@ -4726,8 +5181,8 @@ var InaUI = (() => {
4726
5181
  const menuItems = menu.querySelectorAll("li[role='option']");
4727
5182
  const menuId = menu.id;
4728
5183
  let activeIndex = -1;
4729
- menuItems.forEach((item, index2) => {
4730
- item.id = `${menuId}-item-${index2}`;
5184
+ menuItems.forEach((item, index) => {
5185
+ item.id = `${menuId}-item-${index}`;
4731
5186
  });
4732
5187
  const toggleMenu = (show) => {
4733
5188
  const isCurrentlyShown = dropdown.classList.contains("show");
@@ -4782,15 +5237,15 @@ var InaUI = (() => {
4782
5237
  }
4783
5238
  toggleMenu(false);
4784
5239
  };
4785
- const setHighlight = (index2) => {
5240
+ const setHighlight = (index) => {
4786
5241
  removeHighlight();
4787
5242
  const visibleItems = menu.querySelectorAll(
4788
5243
  "li[role='option']:not(.hidden)"
4789
5244
  );
4790
5245
  if (visibleItems.length === 0) return;
4791
- if (index2 < 0) index2 = 0;
4792
- else if (index2 >= visibleItems.length) index2 = visibleItems.length - 1;
4793
- const itemToHighlight = visibleItems[index2];
5246
+ if (index < 0) index = 0;
5247
+ else if (index >= visibleItems.length) index = visibleItems.length - 1;
5248
+ const itemToHighlight = visibleItems[index];
4794
5249
  if (itemToHighlight) {
4795
5250
  itemToHighlight.classList.add("highlighted");
4796
5251
  input.setAttribute("aria-activedescendant", itemToHighlight.id);
@@ -4798,7 +5253,7 @@ var InaUI = (() => {
4798
5253
  behavior: "smooth",
4799
5254
  block: "nearest"
4800
5255
  });
4801
- activeIndex = index2;
5256
+ activeIndex = index;
4802
5257
  }
4803
5258
  };
4804
5259
  const removeHighlight = () => {
@@ -4861,6 +5316,291 @@ var InaUI = (() => {
4861
5316
  });
4862
5317
  }
4863
5318
 
5319
+ // src/js/components/stateful/chip.js
5320
+ var PREFIX4 = "ina";
5321
+ function initChip2(rootSelector = `.${PREFIX4}-chip`) {
5322
+ const chips = document.querySelectorAll(rootSelector);
5323
+ chips.forEach((container) => {
5324
+ if (container.__inaChipInitialized) return;
5325
+ const showCustomization = container.getAttribute("data-show-customization") === "true";
5326
+ const customizationLabel = container.getAttribute("data-customization-label") || "Kustomisasi";
5327
+ const isMultiple = container.getAttribute("data-multiple") === "true";
5328
+ let selectedValue = container.getAttribute("data-selected") || "";
5329
+ const list = container.querySelector(`.${PREFIX4}-chip__list`);
5330
+ const items = list ? list.querySelectorAll(`.${PREFIX4}-chip__item`) : [];
5331
+ let customFieldContainer = container.querySelector(
5332
+ `.${PREFIX4}-chip__custom-field`
5333
+ );
5334
+ const getNormalizedSelected = () => {
5335
+ if (!selectedValue) return [];
5336
+ return isMultiple ? selectedValue.split(",").map((s) => s.trim()).filter(Boolean) : [selectedValue];
5337
+ };
5338
+ const updateUI = () => {
5339
+ const normSelected = getNormalizedSelected();
5340
+ const getInitialFocusIndex = () => {
5341
+ if (normSelected.length > 0) {
5342
+ const standardValues = Array.from(items).filter((item) => item.textContent.trim() !== customizationLabel).map((item) => item.getAttribute("data-value"));
5343
+ const hasCustomVal = normSelected.some(
5344
+ (val) => !standardValues.includes(val) && val !== ""
5345
+ );
5346
+ if (hasCustomVal && showCustomization) {
5347
+ return items.length - 1;
5348
+ }
5349
+ const firstSelectedIndex = Array.from(items).findIndex(
5350
+ (opt) => normSelected.includes(opt.getAttribute("data-value"))
5351
+ );
5352
+ if (firstSelectedIndex !== -1) return firstSelectedIndex;
5353
+ }
5354
+ return 0;
5355
+ };
5356
+ const focusedIndex = getInitialFocusIndex();
5357
+ items.forEach((item, index) => {
5358
+ const itemValue = item.getAttribute("data-value");
5359
+ const isSelected = normSelected.includes(itemValue) || showCustomization && item.textContent.trim() === customizationLabel && normSelected.some(
5360
+ (val) => !Array.from(items).filter((i) => i.textContent.trim() !== customizationLabel).map((i) => i.getAttribute("data-value")).includes(val) && val !== ""
5361
+ );
5362
+ const isDisabled = item.hasAttribute("disabled");
5363
+ if (isSelected) {
5364
+ item.classList.add(`${PREFIX4}-chip__item--selected`);
5365
+ } else {
5366
+ item.classList.remove(`${PREFIX4}-chip__item--selected`);
5367
+ }
5368
+ if (isDisabled) {
5369
+ item.classList.add(`${PREFIX4}-chip__item--disabled`);
5370
+ }
5371
+ if (!item.hasAttribute("role")) {
5372
+ item.setAttribute("role", "option");
5373
+ }
5374
+ item.setAttribute("aria-selected", isSelected);
5375
+ item.setAttribute(
5376
+ "tabindex",
5377
+ index === focusedIndex && !isDisabled ? "0" : "-1"
5378
+ );
5379
+ });
5380
+ if (showCustomization) {
5381
+ const isToggleBtn2 = (i) => i.hasAttribute("data-customization-toggle") || i.textContent.trim() === customizationLabel;
5382
+ const standardValues = Array.from(items).filter((item) => !isToggleBtn2(item)).map((item) => item.getAttribute("data-value"));
5383
+ const customValues = normSelected.filter(
5384
+ (val) => !standardValues.includes(val) && val !== ""
5385
+ );
5386
+ const isStandard = customValues.length === 0;
5387
+ const primaryCustomValue = customValues[customValues.length - 1] || "";
5388
+ const toggleBtn = Array.from(items).find(isToggleBtn2);
5389
+ const showInput = toggleBtn && normSelected.includes(toggleBtn.getAttribute("data-value")) || !isStandard && normSelected.length > 0;
5390
+ if (showInput) {
5391
+ if (!customFieldContainer) {
5392
+ customFieldContainer = document.createElement("div");
5393
+ customFieldContainer.className = `${PREFIX4}-chip__custom-field`;
5394
+ container.appendChild(customFieldContainer);
5395
+ }
5396
+ let input = customFieldContainer.querySelector(
5397
+ `.${PREFIX4}-chip__input`
5398
+ );
5399
+ if (!input) {
5400
+ customFieldContainer.innerHTML = `
5401
+ <div class="${PREFIX4}-chip__input-wrapper">
5402
+ <input type="text" class="${PREFIX4}-chip__input" placeholder="Masukkan data yang Anda inginkan" value="${!isStandard ? primaryCustomValue : ""}" />
5403
+ <button type="button" class="${PREFIX4}-chip__clear-button" aria-label="Hapus input" style="display: ${!isStandard && primaryCustomValue ? "inline-flex" : "none"};">
5404
+ <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">
5405
+ <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
5406
+ <path d="M18 6l-12 12"></path>
5407
+ <path d="M6 6l12 12"></path>
5408
+ </svg>
5409
+ </button>
5410
+ </div>
5411
+ `;
5412
+ input = customFieldContainer.querySelector("input");
5413
+ const clearBtn = customFieldContainer.querySelector(
5414
+ ".ina-chip__clear-button"
5415
+ );
5416
+ input.addEventListener("input", (e) => {
5417
+ clearBtn.style.display = e.target.value ? "inline-flex" : "none";
5418
+ });
5419
+ clearBtn.addEventListener("click", () => {
5420
+ input.value = "";
5421
+ clearBtn.style.display = "none";
5422
+ commitCustomValue(input);
5423
+ });
5424
+ input.addEventListener("blur", (e) => {
5425
+ commitCustomValue(e.target);
5426
+ });
5427
+ input.addEventListener("keydown", (e) => {
5428
+ if (e.key === "Enter") {
5429
+ commitCustomValue(e.target);
5430
+ e.target.blur();
5431
+ }
5432
+ });
5433
+ } else {
5434
+ const inputEl = customFieldContainer.querySelector("input");
5435
+ if (inputEl && document.activeElement !== inputEl) {
5436
+ inputEl.value = !isStandard ? primaryCustomValue : "";
5437
+ }
5438
+ }
5439
+ customFieldContainer.style.display = "block";
5440
+ } else {
5441
+ if (customFieldContainer) {
5442
+ customFieldContainer.style.display = "none";
5443
+ }
5444
+ }
5445
+ }
5446
+ };
5447
+ const handleSelect = (val) => {
5448
+ if (!val) return;
5449
+ let finalVal = val;
5450
+ if (isMultiple) {
5451
+ const normSelected = getNormalizedSelected();
5452
+ let newSelected;
5453
+ if (normSelected.includes(val)) {
5454
+ newSelected = normSelected.filter((v) => v !== val);
5455
+ } else {
5456
+ newSelected = [...normSelected, val];
5457
+ }
5458
+ finalVal = newSelected;
5459
+ selectedValue = newSelected.join(",");
5460
+ } else {
5461
+ const normSelected = getNormalizedSelected();
5462
+ if (normSelected.includes(val)) {
5463
+ selectedValue = "";
5464
+ finalVal = "";
5465
+ } else {
5466
+ selectedValue = val;
5467
+ }
5468
+ }
5469
+ container.setAttribute("data-selected", selectedValue);
5470
+ updateUI();
5471
+ container.dispatchEvent(
5472
+ new CustomEvent("chip:select", {
5473
+ detail: { value: finalVal },
5474
+ bubbles: true
5475
+ })
5476
+ );
5477
+ };
5478
+ let currentFocusedIndex = -1;
5479
+ const setItemFocus = (index) => {
5480
+ items.forEach((item, i) => {
5481
+ item.setAttribute("tabindex", i === index ? "0" : "-1");
5482
+ });
5483
+ if (items[index]) {
5484
+ items[index].focus();
5485
+ currentFocusedIndex = index;
5486
+ }
5487
+ };
5488
+ const commitCustomValue = (inputEl) => {
5489
+ const finalValue = inputEl.value.trim();
5490
+ let normSelected = getNormalizedSelected();
5491
+ const toggleBtn = Array.from(items).find(isToggleBtn);
5492
+ const toggleVal = toggleBtn ? toggleBtn.getAttribute("data-value") : null;
5493
+ const standardValues = Array.from(items).filter((i) => !isToggleBtn(i)).map((i) => i.getAttribute("data-value"));
5494
+ const customValues = normSelected.filter(
5495
+ (val) => !standardValues.includes(val) && val !== "" && val !== toggleVal
5496
+ );
5497
+ const primaryCustomValue = customValues[customValues.length - 1];
5498
+ if (primaryCustomValue) {
5499
+ normSelected = normSelected.filter((v) => v !== primaryCustomValue);
5500
+ }
5501
+ if (finalValue !== "") {
5502
+ if (!normSelected.includes(finalValue)) {
5503
+ normSelected.push(finalValue);
5504
+ }
5505
+ } else {
5506
+ if (toggleVal) {
5507
+ normSelected = normSelected.filter((v) => v !== toggleVal);
5508
+ }
5509
+ }
5510
+ if (isMultiple) {
5511
+ selectedValue = normSelected.join(",");
5512
+ } else {
5513
+ selectedValue = finalValue;
5514
+ }
5515
+ updateUI();
5516
+ const changeEvent = new CustomEvent(`${PREFIX4}-chip:change`, {
5517
+ detail: { value: isMultiple ? getNormalizedSelected() : selectedValue },
5518
+ bubbles: true
5519
+ });
5520
+ container.dispatchEvent(changeEvent);
5521
+ };
5522
+ items.forEach((item, index) => {
5523
+ item.addEventListener("click", (e) => {
5524
+ if (item.hasAttribute("disabled")) return;
5525
+ currentFocusedIndex = index;
5526
+ const val = item.getAttribute("data-value");
5527
+ if (showCustomization && isToggleBtn(item)) {
5528
+ const normSelected = getNormalizedSelected();
5529
+ const standardValues = Array.from(items).filter((i) => !isToggleBtn(i)).map((i) => i.getAttribute("data-value"));
5530
+ const customValues = normSelected.filter(
5531
+ (v) => !standardValues.includes(v) && v !== "" && v !== val
5532
+ );
5533
+ const isInputVisible = normSelected.includes(val) || customValues.length > 0;
5534
+ if (!isInputVisible) {
5535
+ handleSelect(val);
5536
+ }
5537
+ } else {
5538
+ handleSelect(val);
5539
+ }
5540
+ });
5541
+ item.addEventListener("keydown", (e) => {
5542
+ if (item.hasAttribute("disabled")) return;
5543
+ if (e.key === "ArrowRight" || e.key === "ArrowDown") {
5544
+ e.preventDefault();
5545
+ let nextIndex = (index + 1) % items.length;
5546
+ while (items[nextIndex].hasAttribute("disabled") && nextIndex !== index) {
5547
+ nextIndex = (nextIndex + 1) % items.length;
5548
+ }
5549
+ setItemFocus(nextIndex);
5550
+ } else if (e.key === "ArrowLeft" || e.key === "ArrowUp") {
5551
+ e.preventDefault();
5552
+ let prevIndex = (index - 1 + items.length) % items.length;
5553
+ while (items[prevIndex].hasAttribute("disabled") && prevIndex !== index) {
5554
+ prevIndex = (prevIndex - 1 + items.length) % items.length;
5555
+ }
5556
+ setItemFocus(prevIndex);
5557
+ }
5558
+ if (e.key === " " || e.key === "Enter") {
5559
+ e.preventDefault();
5560
+ item.click();
5561
+ }
5562
+ });
5563
+ });
5564
+ updateUI();
5565
+ if (list && !list.hasAttribute("role")) {
5566
+ list.setAttribute("role", "listbox");
5567
+ if (isMultiple) {
5568
+ list.setAttribute("aria-multiselectable", "true");
5569
+ }
5570
+ }
5571
+ container.__inaChipInitialized = true;
5572
+ });
5573
+ }
5574
+
5575
+ // src/js/components/stateless/img-compare.js
5576
+ function initImgCompare2(rootSelector = `.${PREFIX}-img-compare`) {
5577
+ document.querySelectorAll(rootSelector).forEach((imgCompare) => {
5578
+ const sliderEl = document.createElement("input");
5579
+ sliderEl.type = "range";
5580
+ sliderEl.min = "0";
5581
+ sliderEl.max = "100";
5582
+ sliderEl.value = "50";
5583
+ sliderEl.setAttribute("aria-label", "Percentage of the image to show");
5584
+ sliderEl.setAttribute("aria-valuenow", "50");
5585
+ sliderEl.setAttribute("aria-valuemin", "0");
5586
+ sliderEl.setAttribute("aria-valuemax", "100");
5587
+ sliderEl.classList.add("ina-ss-img__slider");
5588
+ sliderEl.addEventListener("input", () => {
5589
+ imgCompare.style.setProperty(
5590
+ `--${PREFIX}-position`,
5591
+ `${sliderEl.value}%`
5592
+ );
5593
+ });
5594
+ const sliderLineEl = document.createElement("div");
5595
+ sliderLineEl.classList.add("ina-ss-img__slider-line");
5596
+ const sliderButtonEl = document.createElement("button");
5597
+ sliderButtonEl.classList.add("ina-ss-img__slider-button");
5598
+ imgCompare.appendChild(sliderEl);
5599
+ imgCompare.appendChild(sliderLineEl);
5600
+ imgCompare.appendChild(sliderButtonEl);
5601
+ });
5602
+ }
5603
+
4864
5604
  // src/js/bundle.js
4865
5605
  if (typeof window !== void 0) {
4866
5606
  document.addEventListener("DOMContentLoaded", () => {
@@ -4875,7 +5615,7 @@ var InaUI = (() => {
4875
5615
  initSingleFileUpload();
4876
5616
  initFileUploadBase();
4877
5617
  initFileUploadItem();
4878
- initImgCompare();
5618
+ initImgCompare2();
4879
5619
  initModal();
4880
5620
  initRangeDatepicker();
4881
5621
  initRadioButton();
@@ -4884,12 +5624,13 @@ var InaUI = (() => {
4884
5624
  initToggle();
4885
5625
  initPagination();
4886
5626
  initSelectDropdown();
4887
- initChip();
5627
+ initChip2();
4888
5628
  initTabVertical();
4889
5629
  initTabHorizontal();
4890
5630
  initTable();
4891
5631
  initMonthPicker();
4892
5632
  initYearPicker();
5633
+ initPhoneInput();
4893
5634
  });
4894
5635
  }
4895
5636
  return __toCommonJS(bundle_exports);