@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.
- package/dist/index.iife.js +1177 -436
- package/dist/index.js +838 -383
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6,6 +6,12 @@ function initButtonGroup(rootSelector = `.${PREFIX}-button-group`) {
|
|
|
6
6
|
const buttons = buttonGroup.querySelectorAll(
|
|
7
7
|
`.${PREFIX}-button-group__button`
|
|
8
8
|
);
|
|
9
|
+
if (!buttonGroup.hasAttribute("role")) {
|
|
10
|
+
buttonGroup.setAttribute("role", "group");
|
|
11
|
+
}
|
|
12
|
+
if (!buttonGroup.hasAttribute("aria-label")) {
|
|
13
|
+
buttonGroup.setAttribute("aria-label", "Grup tombol");
|
|
14
|
+
}
|
|
9
15
|
const updateState = (clickedButton) => {
|
|
10
16
|
const isDisabled = clickedButton.hasAttribute("disabled") || clickedButton.classList.contains(
|
|
11
17
|
`${PREFIX}-button-group__button--disabled`
|
|
@@ -29,7 +35,7 @@ function initButtonGroup(rootSelector = `.${PREFIX}-button-group`) {
|
|
|
29
35
|
})
|
|
30
36
|
);
|
|
31
37
|
};
|
|
32
|
-
buttons.forEach((button,
|
|
38
|
+
buttons.forEach((button, index) => {
|
|
33
39
|
button.addEventListener("click", (e) => {
|
|
34
40
|
if (button.type !== "submit") {
|
|
35
41
|
e.preventDefault();
|
|
@@ -44,19 +50,19 @@ function initButtonGroup(rootSelector = `.${PREFIX}-button-group`) {
|
|
|
44
50
|
updateState(button);
|
|
45
51
|
} else if (e.key === "ArrowRight" || e.key === "ArrowDown") {
|
|
46
52
|
e.preventDefault();
|
|
47
|
-
let nextIndex = (
|
|
53
|
+
let nextIndex = (index + 1) % buttons.length;
|
|
48
54
|
while ((buttons[nextIndex].hasAttribute("disabled") || buttons[nextIndex].classList.contains(
|
|
49
55
|
`${PREFIX}-button-group__button--disabled`
|
|
50
|
-
)) && nextIndex !==
|
|
56
|
+
)) && nextIndex !== index) {
|
|
51
57
|
nextIndex = (nextIndex + 1) % buttons.length;
|
|
52
58
|
}
|
|
53
59
|
buttons[nextIndex]?.focus();
|
|
54
60
|
} else if (e.key === "ArrowLeft" || e.key === "ArrowUp") {
|
|
55
61
|
e.preventDefault();
|
|
56
|
-
let prevIndex = (
|
|
62
|
+
let prevIndex = (index - 1 + buttons.length) % buttons.length;
|
|
57
63
|
while ((buttons[prevIndex].hasAttribute("disabled") || buttons[prevIndex].classList.contains(
|
|
58
64
|
`${PREFIX}-button-group__button--disabled`
|
|
59
|
-
)) && prevIndex !==
|
|
65
|
+
)) && prevIndex !== index) {
|
|
60
66
|
prevIndex = (prevIndex - 1 + buttons.length) % buttons.length;
|
|
61
67
|
}
|
|
62
68
|
buttons[prevIndex]?.focus();
|
|
@@ -117,18 +123,18 @@ function initTab(rootSelector = `.${PREFIX}-tab`) {
|
|
|
117
123
|
const tabItem = tab.querySelectorAll(`.${PREFIX}-tab-item`);
|
|
118
124
|
tabItem.forEach((tabButton) => {
|
|
119
125
|
function updateState() {
|
|
120
|
-
const
|
|
126
|
+
const index = Array.from(tabItem).indexOf(tabButton);
|
|
121
127
|
tabItem.forEach((tabButton2, i) => {
|
|
122
128
|
tabButton2.classList.remove("active");
|
|
123
129
|
tabButton2.setAttribute("aria-selected", "false");
|
|
124
|
-
if (i ===
|
|
130
|
+
if (i === index) {
|
|
125
131
|
tabButton2.classList.add("active");
|
|
126
132
|
tabButton2.setAttribute("aria-selected", "true");
|
|
127
133
|
}
|
|
128
134
|
});
|
|
129
135
|
tab.dispatchEvent(
|
|
130
136
|
new CustomEvent("tab:change", {
|
|
131
|
-
detail: { activeIndex:
|
|
137
|
+
detail: { activeIndex: index },
|
|
132
138
|
bubbles: true,
|
|
133
139
|
composed: true
|
|
134
140
|
})
|
|
@@ -223,28 +229,28 @@ var AccordionGroup = class {
|
|
|
223
229
|
this.element.__inaAccordionGroup = this;
|
|
224
230
|
}
|
|
225
231
|
registerItem(item) {
|
|
226
|
-
const
|
|
227
|
-
this.items.set(item.id,
|
|
232
|
+
const index = this.items.size;
|
|
233
|
+
this.items.set(item.id, index);
|
|
228
234
|
this.itemsArray.push(item);
|
|
229
235
|
if (item.defaultOpen) {
|
|
230
236
|
if (this.isMultiple) {
|
|
231
|
-
if (!this.openIndexes.includes(
|
|
232
|
-
this.openIndexes.push(
|
|
237
|
+
if (!this.openIndexes.includes(index)) {
|
|
238
|
+
this.openIndexes.push(index);
|
|
233
239
|
}
|
|
234
240
|
} else {
|
|
235
241
|
if (this.openIndexes.length === 0) {
|
|
236
|
-
this.openIndexes.push(
|
|
242
|
+
this.openIndexes.push(index);
|
|
237
243
|
}
|
|
238
244
|
}
|
|
239
245
|
}
|
|
240
|
-
return
|
|
246
|
+
return index;
|
|
241
247
|
}
|
|
242
248
|
unregisterItem(item) {
|
|
243
|
-
const
|
|
244
|
-
if (
|
|
249
|
+
const index = this.items.get(item.id);
|
|
250
|
+
if (index !== void 0) {
|
|
245
251
|
this.items.delete(item.id);
|
|
246
252
|
this.itemsArray = this.itemsArray.filter((i) => i !== item);
|
|
247
|
-
this.openIndexes = this.openIndexes.filter((idx) => idx !==
|
|
253
|
+
this.openIndexes = this.openIndexes.filter((idx) => idx !== index).map((idx) => idx > index ? idx - 1 : idx);
|
|
248
254
|
const newMap = /* @__PURE__ */ new Map();
|
|
249
255
|
this.itemsArray.forEach((itm, newIdx) => {
|
|
250
256
|
newMap.set(itm.id, newIdx);
|
|
@@ -252,22 +258,22 @@ var AccordionGroup = class {
|
|
|
252
258
|
this.items = newMap;
|
|
253
259
|
}
|
|
254
260
|
}
|
|
255
|
-
handleItemToggle(
|
|
261
|
+
handleItemToggle(index, isOpen) {
|
|
256
262
|
const prevIndexes = [...this.openIndexes];
|
|
257
263
|
let nextIndexes = [];
|
|
258
264
|
if (this.isMultiple) {
|
|
259
265
|
if (isOpen) {
|
|
260
|
-
if (!prevIndexes.includes(
|
|
261
|
-
nextIndexes = [...prevIndexes,
|
|
266
|
+
if (!prevIndexes.includes(index)) {
|
|
267
|
+
nextIndexes = [...prevIndexes, index];
|
|
262
268
|
} else {
|
|
263
269
|
nextIndexes = prevIndexes;
|
|
264
270
|
}
|
|
265
271
|
} else {
|
|
266
|
-
nextIndexes = prevIndexes.filter((idx) => idx !==
|
|
272
|
+
nextIndexes = prevIndexes.filter((idx) => idx !== index);
|
|
267
273
|
}
|
|
268
274
|
} else {
|
|
269
275
|
if (isOpen) {
|
|
270
|
-
nextIndexes = [
|
|
276
|
+
nextIndexes = [index];
|
|
271
277
|
} else {
|
|
272
278
|
nextIndexes = [];
|
|
273
279
|
}
|
|
@@ -275,16 +281,16 @@ var AccordionGroup = class {
|
|
|
275
281
|
this.openIndexes = nextIndexes;
|
|
276
282
|
this.notifyItems();
|
|
277
283
|
}
|
|
278
|
-
isItemOpen(
|
|
279
|
-
return this.openIndexes.includes(
|
|
284
|
+
isItemOpen(index) {
|
|
285
|
+
return this.openIndexes.includes(index);
|
|
280
286
|
}
|
|
281
287
|
getItemIndex(itemId) {
|
|
282
288
|
return this.items.get(itemId);
|
|
283
289
|
}
|
|
284
290
|
// Notify all children to update their visual state based on new openIndexes
|
|
285
291
|
notifyItems() {
|
|
286
|
-
this.itemsArray.forEach((item,
|
|
287
|
-
const isOpen = this.openIndexes.includes(
|
|
292
|
+
this.itemsArray.forEach((item, index) => {
|
|
293
|
+
const isOpen = this.openIndexes.includes(index);
|
|
288
294
|
item.setOpenState(isOpen);
|
|
289
295
|
});
|
|
290
296
|
}
|
|
@@ -393,7 +399,7 @@ function initAccordion(rootSelector = `.${PREFIX}-accordion-group`) {
|
|
|
393
399
|
|
|
394
400
|
// src/js/components/stateful/date-picker.js
|
|
395
401
|
var DatePicker = class {
|
|
396
|
-
constructor(selectorOrElement,
|
|
402
|
+
constructor(selectorOrElement, options = {}) {
|
|
397
403
|
this.container = typeof selectorOrElement === "string" ? document.querySelector(selectorOrElement) : selectorOrElement;
|
|
398
404
|
if (!this.container) {
|
|
399
405
|
console.warn("[IDDS DatePicker] Container not found:", selectorOrElement);
|
|
@@ -419,7 +425,11 @@ var DatePicker = class {
|
|
|
419
425
|
onChange: null,
|
|
420
426
|
triggerWidth: "",
|
|
421
427
|
panelMaxHeight: "",
|
|
422
|
-
|
|
428
|
+
allowClear: true,
|
|
429
|
+
// Added allowClear option
|
|
430
|
+
className: "",
|
|
431
|
+
// Added className option
|
|
432
|
+
...options
|
|
423
433
|
};
|
|
424
434
|
this.state = {
|
|
425
435
|
viewDate: /* @__PURE__ */ new Date(),
|
|
@@ -573,6 +583,18 @@ var DatePicker = class {
|
|
|
573
583
|
}
|
|
574
584
|
this.renderPanel();
|
|
575
585
|
}
|
|
586
|
+
getFullDayName(shortName) {
|
|
587
|
+
const map = {
|
|
588
|
+
Min: "Minggu",
|
|
589
|
+
Sen: "Senin",
|
|
590
|
+
Sel: "Selasa",
|
|
591
|
+
Rab: "Rabu",
|
|
592
|
+
Kam: "Kamis",
|
|
593
|
+
Jum: "Jumat",
|
|
594
|
+
Sab: "Sabtu"
|
|
595
|
+
};
|
|
596
|
+
return map[shortName] || shortName;
|
|
597
|
+
}
|
|
576
598
|
initDOM() {
|
|
577
599
|
if (!this.container.classList.contains(`${PREFIX}-date-picker`)) {
|
|
578
600
|
this.container.classList.add(`${PREFIX}-date-picker`);
|
|
@@ -588,6 +610,9 @@ var DatePicker = class {
|
|
|
588
610
|
if (this.options.triggerWidth) {
|
|
589
611
|
trigger.style.width = typeof this.options.triggerWidth === "number" ? `${this.options.triggerWidth}px` : this.options.triggerWidth;
|
|
590
612
|
}
|
|
613
|
+
trigger.setAttribute("aria-haspopup", "dialog");
|
|
614
|
+
trigger.setAttribute("aria-expanded", "false");
|
|
615
|
+
trigger.setAttribute("aria-label", "Pilih Tanggal");
|
|
591
616
|
const textWrapper = document.createElement("span");
|
|
592
617
|
textWrapper.className = `${PREFIX}-date-picker__trigger-text ${PREFIX}-date-picker__trigger-text--placeholder`;
|
|
593
618
|
textWrapper.textContent = "Pilih Tanggal";
|
|
@@ -597,6 +622,26 @@ var DatePicker = class {
|
|
|
597
622
|
trigger.appendChild(textWrapper);
|
|
598
623
|
trigger.appendChild(iconWrapper);
|
|
599
624
|
this.container.appendChild(trigger);
|
|
625
|
+
} else if (trigger) {
|
|
626
|
+
if (!trigger.hasAttribute("aria-haspopup"))
|
|
627
|
+
trigger.setAttribute("aria-haspopup", "dialog");
|
|
628
|
+
if (!trigger.hasAttribute("aria-expanded"))
|
|
629
|
+
trigger.setAttribute("aria-expanded", "false");
|
|
630
|
+
if (!trigger.hasAttribute("aria-label"))
|
|
631
|
+
trigger.setAttribute("aria-label", "Pilih Tanggal");
|
|
632
|
+
}
|
|
633
|
+
if (this.options.allowClear && !this.options.panelOnly) {
|
|
634
|
+
let clearBtn = this.container.querySelector(`.${PREFIX}-date-picker__clear-button`);
|
|
635
|
+
if (!clearBtn) {
|
|
636
|
+
clearBtn = document.createElement("button");
|
|
637
|
+
clearBtn.type = "button";
|
|
638
|
+
clearBtn.className = `${PREFIX}-date-picker__clear-button`;
|
|
639
|
+
clearBtn.setAttribute("aria-label", "Hapus tanggal terpilih");
|
|
640
|
+
clearBtn.innerHTML = this.createIcon("x");
|
|
641
|
+
clearBtn.style.display = "none";
|
|
642
|
+
this.container.appendChild(clearBtn);
|
|
643
|
+
}
|
|
644
|
+
this.elements.clearBtn = clearBtn;
|
|
600
645
|
}
|
|
601
646
|
this.elements.trigger = trigger;
|
|
602
647
|
if (trigger) {
|
|
@@ -891,10 +936,13 @@ var DatePicker = class {
|
|
|
891
936
|
header.appendChild(nextBtn);
|
|
892
937
|
const grid = document.createElement("div");
|
|
893
938
|
grid.className = `${PREFIX}-date-picker__calendar-grid`;
|
|
939
|
+
grid.setAttribute("role", "grid");
|
|
894
940
|
this.DAYS_SHORT.forEach((d) => {
|
|
895
941
|
const dh = document.createElement("div");
|
|
896
942
|
dh.className = `${PREFIX}-date-picker__day-header`;
|
|
897
943
|
dh.textContent = d;
|
|
944
|
+
dh.setAttribute("role", "columnheader");
|
|
945
|
+
dh.setAttribute("aria-label", this.getFullDayName(d));
|
|
898
946
|
grid.appendChild(dh);
|
|
899
947
|
});
|
|
900
948
|
const firstDayOfMonth = new Date(year, month, 1).getDay();
|
|
@@ -1039,6 +1087,7 @@ var DatePicker = class {
|
|
|
1039
1087
|
this.state.isOpen = true;
|
|
1040
1088
|
this.elements.panel.classList.add(`${PREFIX}-date-picker__panel--open`);
|
|
1041
1089
|
this.elements.panel.style.display = "block";
|
|
1090
|
+
if (this.elements.trigger) this.elements.trigger.setAttribute("aria-expanded", "true");
|
|
1042
1091
|
this.renderPanel();
|
|
1043
1092
|
}
|
|
1044
1093
|
close() {
|
|
@@ -1046,6 +1095,7 @@ var DatePicker = class {
|
|
|
1046
1095
|
this.state.isOpen = false;
|
|
1047
1096
|
this.elements.panel.classList.remove(`${PREFIX}-date-picker__panel--open`);
|
|
1048
1097
|
this.elements.panel.style.display = "none";
|
|
1098
|
+
if (this.elements.trigger) this.elements.trigger.setAttribute("aria-expanded", "false");
|
|
1049
1099
|
}
|
|
1050
1100
|
toggle() {
|
|
1051
1101
|
if (this.state.isOpen) this.close();
|
|
@@ -1090,11 +1140,11 @@ var DatePicker = class {
|
|
|
1090
1140
|
return this.state.rangeDate;
|
|
1091
1141
|
}
|
|
1092
1142
|
};
|
|
1093
|
-
function initDatepicker(selectorOrElement,
|
|
1143
|
+
function initDatepicker(selectorOrElement, options = {}) {
|
|
1094
1144
|
const elements = typeof selectorOrElement === "string" ? document.querySelectorAll(selectorOrElement) : selectorOrElement ? typeof selectorOrElement.length !== "undefined" ? selectorOrElement : [selectorOrElement] : document.querySelectorAll(`.${PREFIX}-date-picker`);
|
|
1095
1145
|
const instances = [];
|
|
1096
1146
|
elements.forEach((container) => {
|
|
1097
|
-
const instance = new DatePicker(container,
|
|
1147
|
+
const instance = new DatePicker(container, options);
|
|
1098
1148
|
container.__datepickerAPI = instance;
|
|
1099
1149
|
instances.push(instance);
|
|
1100
1150
|
});
|
|
@@ -1104,7 +1154,7 @@ function initDatepicker(selectorOrElement, options2 = {}) {
|
|
|
1104
1154
|
|
|
1105
1155
|
// src/js/components/stateful/time-picker.js
|
|
1106
1156
|
var TimePicker = class {
|
|
1107
|
-
constructor(selectorOrElement,
|
|
1157
|
+
constructor(selectorOrElement, options = {}) {
|
|
1108
1158
|
this.container = typeof selectorOrElement === "string" ? document.querySelector(selectorOrElement) : selectorOrElement;
|
|
1109
1159
|
if (!this.container) {
|
|
1110
1160
|
console.warn("[IDDS TimePicker] Container not found:", selectorOrElement);
|
|
@@ -1137,7 +1187,7 @@ var TimePicker = class {
|
|
|
1137
1187
|
secondStep: 1,
|
|
1138
1188
|
onChange: null,
|
|
1139
1189
|
size: this.container.dataset.size || "md",
|
|
1140
|
-
...
|
|
1190
|
+
...options
|
|
1141
1191
|
};
|
|
1142
1192
|
this.state = {
|
|
1143
1193
|
isOpen: false,
|
|
@@ -1145,6 +1195,7 @@ var TimePicker = class {
|
|
|
1145
1195
|
internalValue: ""
|
|
1146
1196
|
};
|
|
1147
1197
|
this.elements = {};
|
|
1198
|
+
this.inputId = this.container.id || `time-picker-${Math.random().toString(36).substr(2, 9)}`;
|
|
1148
1199
|
this.initDOM();
|
|
1149
1200
|
this.bindEvents();
|
|
1150
1201
|
if (this.elements.input && this.elements.input.value) {
|
|
@@ -1252,28 +1303,41 @@ var TimePicker = class {
|
|
|
1252
1303
|
if (!wrapper) {
|
|
1253
1304
|
wrapper = document.createElement("div");
|
|
1254
1305
|
wrapper.className = `${PREFIX}-time-picker__wrapper`;
|
|
1306
|
+
wrapper.setAttribute("role", "combobox");
|
|
1307
|
+
wrapper.setAttribute("aria-haspopup", "listbox");
|
|
1308
|
+
wrapper.setAttribute("aria-expanded", "false");
|
|
1255
1309
|
const prefixIcon = document.createElement("div");
|
|
1256
1310
|
prefixIcon.className = `${PREFIX}-time-picker__prefix-icon`;
|
|
1257
1311
|
prefixIcon.innerHTML = this.createIcon("clock");
|
|
1258
1312
|
wrapper.appendChild(prefixIcon);
|
|
1259
1313
|
input = document.createElement("input");
|
|
1260
1314
|
input.type = "text";
|
|
1315
|
+
input.id = this.inputId;
|
|
1261
1316
|
input.className = `${PREFIX}-time-picker__input ${PREFIX}-time-picker__input--size-${this.options.size} ${PREFIX}-time-picker__input--with-prefix`;
|
|
1262
1317
|
if (this.options.allowClear)
|
|
1263
1318
|
input.classList.add(`${PREFIX}-time-picker__input--with-suffix`);
|
|
1264
1319
|
input.placeholder = this.container.getAttribute("placeholder") || "Select time";
|
|
1265
1320
|
if (this.options.disabled) input.disabled = true;
|
|
1266
1321
|
if (this.options.readonly) input.readOnly = true;
|
|
1267
|
-
else input.readOnly = true;
|
|
1268
1322
|
wrapper.appendChild(input);
|
|
1269
1323
|
if (this.options.allowClear) {
|
|
1270
|
-
clearBtn = document.createElement("
|
|
1324
|
+
clearBtn = document.createElement("button");
|
|
1325
|
+
clearBtn.type = "button";
|
|
1271
1326
|
clearBtn.className = `${PREFIX}-time-picker__clear-button`;
|
|
1327
|
+
clearBtn.setAttribute("aria-label", "Hapus waktu");
|
|
1272
1328
|
clearBtn.innerHTML = this.createIcon("x");
|
|
1273
1329
|
clearBtn.style.display = "none";
|
|
1274
1330
|
wrapper.appendChild(clearBtn);
|
|
1275
1331
|
}
|
|
1276
1332
|
this.container.appendChild(wrapper);
|
|
1333
|
+
} else {
|
|
1334
|
+
wrapper.setAttribute("role", "combobox");
|
|
1335
|
+
wrapper.setAttribute("aria-haspopup", "listbox");
|
|
1336
|
+
wrapper.setAttribute("aria-expanded", "false");
|
|
1337
|
+
if (input && !input.id) input.id = this.inputId;
|
|
1338
|
+
if (clearBtn && !clearBtn.hasAttribute("aria-label")) {
|
|
1339
|
+
clearBtn.setAttribute("aria-label", "Hapus waktu");
|
|
1340
|
+
}
|
|
1277
1341
|
}
|
|
1278
1342
|
this.elements.wrapper = wrapper;
|
|
1279
1343
|
this.elements.input = input;
|
|
@@ -1354,24 +1418,24 @@ var TimePicker = class {
|
|
|
1354
1418
|
}
|
|
1355
1419
|
}
|
|
1356
1420
|
generateOptions(type) {
|
|
1357
|
-
const
|
|
1421
|
+
const options = [];
|
|
1358
1422
|
const { use12Hours, hourStep, minuteStep, secondStep } = this.options;
|
|
1359
1423
|
let limit = type === "hour" ? use12Hours ? 12 : 24 : 60;
|
|
1360
1424
|
let step = type === "hour" ? hourStep : type === "minute" ? minuteStep : secondStep;
|
|
1361
1425
|
if (limit === 12) {
|
|
1362
1426
|
for (let i = type === "hour" ? 1 : 0; i <= (type === "hour" ? 12 : 59); i += step) {
|
|
1363
|
-
|
|
1427
|
+
options.push(i);
|
|
1364
1428
|
}
|
|
1365
1429
|
} else if (limit === 24) {
|
|
1366
1430
|
for (let i = 0; i <= 23; i += step) {
|
|
1367
|
-
|
|
1431
|
+
options.push(i);
|
|
1368
1432
|
}
|
|
1369
1433
|
} else {
|
|
1370
1434
|
for (let i = 0; i <= 59; i += step) {
|
|
1371
|
-
|
|
1435
|
+
options.push(i);
|
|
1372
1436
|
}
|
|
1373
1437
|
}
|
|
1374
|
-
return
|
|
1438
|
+
return options;
|
|
1375
1439
|
}
|
|
1376
1440
|
renderColumn(type, optionsArr) {
|
|
1377
1441
|
const column = document.createElement("div");
|
|
@@ -1381,7 +1445,7 @@ var TimePicker = class {
|
|
|
1381
1445
|
column.appendChild(colContent);
|
|
1382
1446
|
const { use12Hours } = this.options;
|
|
1383
1447
|
const { currentTime } = this.state;
|
|
1384
|
-
optionsArr.forEach((optValue) => {
|
|
1448
|
+
optionsArr.forEach((optValue, index) => {
|
|
1385
1449
|
const option = document.createElement("div");
|
|
1386
1450
|
option.className = `${PREFIX}-time-picker__option`;
|
|
1387
1451
|
let isSelected = false;
|
|
@@ -1427,9 +1491,9 @@ var TimePicker = class {
|
|
|
1427
1491
|
option.classList.add(`${PREFIX}-time-picker__option--disabled`);
|
|
1428
1492
|
option.setAttribute("role", "option");
|
|
1429
1493
|
option.setAttribute("aria-selected", isSelected.toString());
|
|
1430
|
-
const isFirstFocusable = index === 0 && !
|
|
1494
|
+
const isFirstFocusable = index === 0 && !optionsArr.some((opt) => {
|
|
1431
1495
|
if (type === "hour") {
|
|
1432
|
-
return use12Hours
|
|
1496
|
+
return (use12Hours && currentTime.hours === 0 ? 12 : currentTime.hours) === opt;
|
|
1433
1497
|
} else if (type === "minute") {
|
|
1434
1498
|
return currentTime.minutes === opt;
|
|
1435
1499
|
} else if (type === "second") {
|
|
@@ -1547,6 +1611,7 @@ var TimePicker = class {
|
|
|
1547
1611
|
this.state.isOpen = true;
|
|
1548
1612
|
this.container.classList.add(`${PREFIX}-time-picker--open`);
|
|
1549
1613
|
this.elements.panel.style.display = "block";
|
|
1614
|
+
this.elements.wrapper.setAttribute("aria-expanded", "true");
|
|
1550
1615
|
this.state.currentTime = this.parseTime(this.elements.input.value);
|
|
1551
1616
|
this.buildPanel();
|
|
1552
1617
|
document.dispatchEvent(
|
|
@@ -1559,6 +1624,7 @@ var TimePicker = class {
|
|
|
1559
1624
|
this.state.isOpen = false;
|
|
1560
1625
|
this.container.classList.remove(`${PREFIX}-time-picker--open`);
|
|
1561
1626
|
this.elements.panel.style.display = "none";
|
|
1627
|
+
this.elements.wrapper.setAttribute("aria-expanded", "false");
|
|
1562
1628
|
}
|
|
1563
1629
|
toggle() {
|
|
1564
1630
|
if (this.state.isOpen) this.close();
|
|
@@ -1567,20 +1633,50 @@ var TimePicker = class {
|
|
|
1567
1633
|
bindEvents() {
|
|
1568
1634
|
this.elements.wrapper.addEventListener("click", (e) => {
|
|
1569
1635
|
e.stopPropagation();
|
|
1570
|
-
|
|
1636
|
+
const target = e.target;
|
|
1637
|
+
if (target === this.elements.wrapper || target.classList.contains(`${PREFIX}-time-picker__suffix-icon`) || target.classList.contains(`${PREFIX}-time-picker__prefix-icon`)) {
|
|
1638
|
+
this.toggle();
|
|
1639
|
+
}
|
|
1571
1640
|
});
|
|
1572
|
-
|
|
1641
|
+
this.elements.input.addEventListener("input", (e) => {
|
|
1642
|
+
const val = e.target.value;
|
|
1643
|
+
this.state.internalValue = val;
|
|
1644
|
+
const timeRegex = this.options.use12Hours ? /^(\d{1,2}):(\d{2})(?::(\d{2}))?\s?(AM|PM|am|pm)?$/ : /^(\d{1,2}):(\d{2})(?::(\d{2}))?$/;
|
|
1645
|
+
if (timeRegex.test(val)) {
|
|
1646
|
+
this.state.currentTime = this.parseTime(val);
|
|
1647
|
+
if (this.state.isOpen) this.buildPanel();
|
|
1648
|
+
}
|
|
1649
|
+
if (this.elements.clearBtn && this.options.allowClear) {
|
|
1650
|
+
this.elements.clearBtn.style.display = val && !this.options.disabled ? "flex" : "none";
|
|
1651
|
+
}
|
|
1652
|
+
if (typeof this.options.onChange === "function") {
|
|
1653
|
+
this.options.onChange(val);
|
|
1654
|
+
}
|
|
1655
|
+
});
|
|
1656
|
+
this.elements.input.addEventListener("click", (e) => {
|
|
1657
|
+
e.stopPropagation();
|
|
1658
|
+
this.open();
|
|
1659
|
+
});
|
|
1660
|
+
this.elements.input.addEventListener("focus", () => {
|
|
1661
|
+
this.open();
|
|
1662
|
+
});
|
|
1663
|
+
this.elements.input.addEventListener("keydown", (e) => {
|
|
1664
|
+
if (e.key === "Enter") {
|
|
1665
|
+
e.preventDefault();
|
|
1666
|
+
if (this.state.internalValue) {
|
|
1667
|
+
this.close();
|
|
1668
|
+
} else {
|
|
1669
|
+
this.toggle();
|
|
1670
|
+
}
|
|
1671
|
+
} else if (e.key === "Escape") {
|
|
1672
|
+
if (this.state.isOpen) this.close();
|
|
1673
|
+
}
|
|
1674
|
+
});
|
|
1675
|
+
if (this.elements.clearBtn) {
|
|
1573
1676
|
this.elements.clearBtn.addEventListener("click", (e) => {
|
|
1574
1677
|
e.stopPropagation();
|
|
1575
|
-
this.elements.input.value = "";
|
|
1576
|
-
this.state.currentTime = {
|
|
1577
|
-
hours: 0,
|
|
1578
|
-
minutes: 0,
|
|
1579
|
-
seconds: 0,
|
|
1580
|
-
period: "AM"
|
|
1581
|
-
};
|
|
1582
|
-
this.container.dataset.value = "";
|
|
1583
1678
|
this.state.internalValue = "";
|
|
1679
|
+
this.elements.input.value = "";
|
|
1584
1680
|
this.elements.clearBtn.style.display = "none";
|
|
1585
1681
|
this.elements.input.dispatchEvent(
|
|
1586
1682
|
new Event("change", { bubbles: true })
|
|
@@ -1589,6 +1685,12 @@ var TimePicker = class {
|
|
|
1589
1685
|
this.options.onChange("");
|
|
1590
1686
|
}
|
|
1591
1687
|
});
|
|
1688
|
+
this.elements.clearBtn.addEventListener("keydown", (e) => {
|
|
1689
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
1690
|
+
e.preventDefault();
|
|
1691
|
+
this.elements.clearBtn.click();
|
|
1692
|
+
}
|
|
1693
|
+
});
|
|
1592
1694
|
}
|
|
1593
1695
|
document.addEventListener("click", (e) => {
|
|
1594
1696
|
if (!this.container.contains(e.target)) this.close();
|
|
@@ -1602,11 +1704,11 @@ var TimePicker = class {
|
|
|
1602
1704
|
return this.state.internalValue;
|
|
1603
1705
|
}
|
|
1604
1706
|
};
|
|
1605
|
-
function initTimepicker(selectorOrElement,
|
|
1707
|
+
function initTimepicker(selectorOrElement, options = {}) {
|
|
1606
1708
|
const elements = typeof selectorOrElement === "string" ? document.querySelectorAll(selectorOrElement) : selectorOrElement ? typeof selectorOrElement.length !== "undefined" ? selectorOrElement : [selectorOrElement] : document.querySelectorAll(`.${PREFIX}-time-picker`);
|
|
1607
1709
|
const instances = [];
|
|
1608
1710
|
elements.forEach((container) => {
|
|
1609
|
-
const instance = new TimePicker(container,
|
|
1711
|
+
const instance = new TimePicker(container, options);
|
|
1610
1712
|
container.__timepickerAPI = instance;
|
|
1611
1713
|
instances.push(instance);
|
|
1612
1714
|
});
|
|
@@ -1649,6 +1751,17 @@ function openModal(modalEl) {
|
|
|
1649
1751
|
modalEl.style.display = "flex";
|
|
1650
1752
|
document.body.style.overflow = "hidden";
|
|
1651
1753
|
modalEl.setAttribute("aria-hidden", "false");
|
|
1754
|
+
modalEl.setAttribute("tabindex", "-1");
|
|
1755
|
+
if (!modalEl.hasAttribute("role")) {
|
|
1756
|
+
modalEl.setAttribute("role", "dialog");
|
|
1757
|
+
}
|
|
1758
|
+
if (!modalEl.hasAttribute("aria-modal")) {
|
|
1759
|
+
modalEl.setAttribute("aria-modal", "true");
|
|
1760
|
+
}
|
|
1761
|
+
const closeBtn = modalEl.querySelector(`.${PREFIX}-modal__close-button`);
|
|
1762
|
+
if (closeBtn && !closeBtn.hasAttribute("aria-label")) {
|
|
1763
|
+
closeBtn.setAttribute("aria-label", "Tutup dialog");
|
|
1764
|
+
}
|
|
1652
1765
|
modalEl.classList.remove(
|
|
1653
1766
|
`${PREFIX}-modal--exit`,
|
|
1654
1767
|
`${PREFIX}-modal--exit-active`
|
|
@@ -1747,6 +1860,19 @@ function initDrawer(rootSelector = `.${PREFIX2}-drawer`) {
|
|
|
1747
1860
|
if (!drawer) return;
|
|
1748
1861
|
drawer.style.display = "flex";
|
|
1749
1862
|
document.body.style.overflow = "hidden";
|
|
1863
|
+
drawer.setAttribute("aria-hidden", "false");
|
|
1864
|
+
drawer.setAttribute("tabindex", "-1");
|
|
1865
|
+
if (!drawer.hasAttribute("role")) {
|
|
1866
|
+
drawer.setAttribute("role", "complementary");
|
|
1867
|
+
}
|
|
1868
|
+
if (!drawer.hasAttribute("aria-modal")) {
|
|
1869
|
+
drawer.setAttribute("aria-modal", "true");
|
|
1870
|
+
}
|
|
1871
|
+
const panel = drawer.querySelector(`.${PREFIX2}-drawer__panel`) || drawer.querySelector(`.${PREFIX2}-drawer__content`) || drawer;
|
|
1872
|
+
const closeBtn = panel.querySelector(`.${PREFIX2}-drawer__close-button`);
|
|
1873
|
+
if (closeBtn && !closeBtn.hasAttribute("aria-label")) {
|
|
1874
|
+
closeBtn.setAttribute("aria-label", "Tutup panel");
|
|
1875
|
+
}
|
|
1750
1876
|
drawer.offsetHeight;
|
|
1751
1877
|
drawer.classList.add(`${PREFIX2}-drawer--open`);
|
|
1752
1878
|
drawer.dispatchEvent(new CustomEvent("drawer:open"));
|
|
@@ -1911,9 +2037,20 @@ function setDropdownState(root, newState) {
|
|
|
1911
2037
|
if (newState.isOpen !== void 0) {
|
|
1912
2038
|
root.setAttribute("data-state", newState.isOpen ? "open" : "closed");
|
|
1913
2039
|
const trigger = root.querySelector(`.${PREFIX4}-select-dropdown__trigger`);
|
|
1914
|
-
if (trigger)
|
|
2040
|
+
if (trigger) {
|
|
2041
|
+
trigger.setAttribute("aria-expanded", newState.isOpen);
|
|
2042
|
+
if (!trigger.hasAttribute("aria-haspopup")) {
|
|
2043
|
+
trigger.setAttribute("aria-haspopup", "listbox");
|
|
2044
|
+
}
|
|
2045
|
+
}
|
|
1915
2046
|
const panel = root.querySelector(`.${PREFIX4}-select-dropdown__panel`);
|
|
1916
2047
|
if (panel) {
|
|
2048
|
+
if (!panel.hasAttribute("role")) {
|
|
2049
|
+
panel.setAttribute("role", "listbox");
|
|
2050
|
+
}
|
|
2051
|
+
if (newState.isMultiple) {
|
|
2052
|
+
panel.setAttribute("aria-multiselectable", "true");
|
|
2053
|
+
}
|
|
1917
2054
|
if (newState.isOpen) {
|
|
1918
2055
|
panel.style.removeProperty("display");
|
|
1919
2056
|
} else {
|
|
@@ -1940,9 +2077,9 @@ function updateTriggerUI(root, values, isMultiple) {
|
|
|
1940
2077
|
`.${PREFIX4}-select-dropdown__trigger-text`
|
|
1941
2078
|
);
|
|
1942
2079
|
const placeholder = input ? input.getAttribute("placeholder") : textSpan ? textSpan.getAttribute("data-placeholder") : "Select...";
|
|
1943
|
-
const
|
|
2080
|
+
const options = root.querySelectorAll(`.${PREFIX4}-select-dropdown__option`);
|
|
1944
2081
|
const getLabel = (val) => {
|
|
1945
|
-
const opt = Array.from(
|
|
2082
|
+
const opt = Array.from(options).find(
|
|
1946
2083
|
(o) => o.getAttribute("data-value") === val
|
|
1947
2084
|
);
|
|
1948
2085
|
return opt ? opt.textContent.trim() : val;
|
|
@@ -1968,7 +2105,7 @@ function updateTriggerUI(root, values, isMultiple) {
|
|
|
1968
2105
|
values.length === 0
|
|
1969
2106
|
);
|
|
1970
2107
|
}
|
|
1971
|
-
|
|
2108
|
+
options.forEach((opt) => {
|
|
1972
2109
|
const val = opt.getAttribute("data-value");
|
|
1973
2110
|
const isSelected = values.includes(val);
|
|
1974
2111
|
if (isMultiple) {
|
|
@@ -1990,6 +2127,10 @@ function updateTriggerUI(root, values, isMultiple) {
|
|
|
1990
2127
|
isSelected
|
|
1991
2128
|
);
|
|
1992
2129
|
}
|
|
2130
|
+
if (!opt.hasAttribute("role")) {
|
|
2131
|
+
opt.setAttribute("role", "option");
|
|
2132
|
+
}
|
|
2133
|
+
opt.setAttribute("aria-selected", isSelected);
|
|
1993
2134
|
});
|
|
1994
2135
|
}
|
|
1995
2136
|
function initSelectDropdown() {
|
|
@@ -2048,13 +2189,13 @@ function initSelectDropdown() {
|
|
|
2048
2189
|
const root = e.target.closest(`.${PREFIX4}-select-dropdown`);
|
|
2049
2190
|
if (root) {
|
|
2050
2191
|
const term = e.target.value.toLowerCase();
|
|
2051
|
-
const
|
|
2192
|
+
const options = root.querySelectorAll(
|
|
2052
2193
|
`.${PREFIX4}-select-dropdown__option`
|
|
2053
2194
|
);
|
|
2054
2195
|
if (root.getAttribute("data-state") !== "open") {
|
|
2055
2196
|
setDropdownState(root, { isOpen: true });
|
|
2056
2197
|
}
|
|
2057
|
-
|
|
2198
|
+
options.forEach((opt) => {
|
|
2058
2199
|
const text = opt.textContent.trim().toLowerCase();
|
|
2059
2200
|
opt.style.display = text.includes(term) ? "" : "none";
|
|
2060
2201
|
});
|
|
@@ -2128,20 +2269,20 @@ function initStepper() {
|
|
|
2128
2269
|
`;
|
|
2129
2270
|
const updateUI = () => {
|
|
2130
2271
|
stepper.dataset.currentStep = currentStep;
|
|
2131
|
-
items.forEach((item,
|
|
2272
|
+
items.forEach((item, index) => {
|
|
2132
2273
|
const iconWrapper = item.querySelector(
|
|
2133
2274
|
`.${PREFIX}-stepper__icon-wrapper`
|
|
2134
2275
|
);
|
|
2135
|
-
const itemNumber =
|
|
2276
|
+
const itemNumber = index + 1;
|
|
2136
2277
|
item.classList.remove(
|
|
2137
2278
|
`${PREFIX}-stepper__item--completed`,
|
|
2138
2279
|
`${PREFIX}-stepper__item--active`
|
|
2139
2280
|
);
|
|
2140
2281
|
if (iconWrapper) iconWrapper.innerHTML = "";
|
|
2141
|
-
if (
|
|
2282
|
+
if (index < currentStep) {
|
|
2142
2283
|
item.classList.add(`${PREFIX}-stepper__item--completed`);
|
|
2143
2284
|
if (iconWrapper) iconWrapper.innerHTML = checkIcon;
|
|
2144
|
-
} else if (
|
|
2285
|
+
} else if (index === currentStep) {
|
|
2145
2286
|
item.classList.add(`${PREFIX}-stepper__item--active`);
|
|
2146
2287
|
if (iconWrapper)
|
|
2147
2288
|
iconWrapper.innerHTML = `<span class="${PREFIX}-stepper__step-number">${itemNumber}</span>`;
|
|
@@ -2150,8 +2291,8 @@ function initStepper() {
|
|
|
2150
2291
|
iconWrapper.innerHTML = `<span class="${PREFIX}-stepper__step-number">${itemNumber}</span>`;
|
|
2151
2292
|
}
|
|
2152
2293
|
});
|
|
2153
|
-
separators.forEach((separator,
|
|
2154
|
-
if (
|
|
2294
|
+
separators.forEach((separator, index) => {
|
|
2295
|
+
if (index < currentStep) {
|
|
2155
2296
|
separator.classList.add(`${PREFIX}-stepper__separator--completed`);
|
|
2156
2297
|
} else {
|
|
2157
2298
|
separator.classList.remove(`${PREFIX}-stepper__separator--completed`);
|
|
@@ -2197,11 +2338,11 @@ function initStepper() {
|
|
|
2197
2338
|
}
|
|
2198
2339
|
});
|
|
2199
2340
|
});
|
|
2200
|
-
items.forEach((item,
|
|
2341
|
+
items.forEach((item, index) => {
|
|
2201
2342
|
if (item.classList.contains(`${PREFIX}-stepper__item--clickable`) || item.hasAttribute("data-clickable")) {
|
|
2202
2343
|
item.addEventListener("click", () => {
|
|
2203
2344
|
if (!item.classList.contains(`${PREFIX}-stepper__item--disabled`)) {
|
|
2204
|
-
currentStep =
|
|
2345
|
+
currentStep = index;
|
|
2205
2346
|
updateUI();
|
|
2206
2347
|
}
|
|
2207
2348
|
});
|
|
@@ -2275,7 +2416,7 @@ function initFileUpload(rootSelector = `.${PREFIX}-file-upload`) {
|
|
|
2275
2416
|
} else {
|
|
2276
2417
|
filesContainer.style.display = "none";
|
|
2277
2418
|
}
|
|
2278
|
-
uploadedFiles.forEach((f,
|
|
2419
|
+
uploadedFiles.forEach((f, index) => {
|
|
2279
2420
|
const fileEl = document.createElement("div");
|
|
2280
2421
|
fileEl.className = `${PREFIX}-file-upload__file`;
|
|
2281
2422
|
let statusClass = "";
|
|
@@ -3099,281 +3240,6 @@ function initRangeDatepicker() {
|
|
|
3099
3240
|
});
|
|
3100
3241
|
}
|
|
3101
3242
|
|
|
3102
|
-
// src/js/components/stateless/img-compare.js
|
|
3103
|
-
function initImgCompare(rootSelector = `.${PREFIX}-img-compare`) {
|
|
3104
|
-
document.querySelectorAll(rootSelector).forEach((imgCompare) => {
|
|
3105
|
-
const sliderEl = document.createElement("input");
|
|
3106
|
-
sliderEl.type = "range";
|
|
3107
|
-
sliderEl.min = "0";
|
|
3108
|
-
sliderEl.max = "100";
|
|
3109
|
-
sliderEl.value = "50";
|
|
3110
|
-
sliderEl.setAttribute("aria-label", "Percentage of the image to show");
|
|
3111
|
-
sliderEl.setAttribute("aria-valuenow", "50");
|
|
3112
|
-
sliderEl.setAttribute("aria-valuemin", "0");
|
|
3113
|
-
sliderEl.setAttribute("aria-valuemax", "100");
|
|
3114
|
-
sliderEl.classList.add("ina-ss-img__slider");
|
|
3115
|
-
sliderEl.addEventListener("input", () => {
|
|
3116
|
-
imgCompare.style.setProperty(
|
|
3117
|
-
`--${PREFIX}-position`,
|
|
3118
|
-
`${sliderEl.value}%`
|
|
3119
|
-
);
|
|
3120
|
-
});
|
|
3121
|
-
const sliderLineEl = document.createElement("div");
|
|
3122
|
-
sliderLineEl.classList.add("ina-ss-img__slider-line");
|
|
3123
|
-
const sliderButtonEl = document.createElement("button");
|
|
3124
|
-
sliderButtonEl.classList.add("ina-ss-img__slider-button");
|
|
3125
|
-
imgCompare.appendChild(sliderEl);
|
|
3126
|
-
imgCompare.appendChild(sliderLineEl);
|
|
3127
|
-
imgCompare.appendChild(sliderButtonEl);
|
|
3128
|
-
});
|
|
3129
|
-
}
|
|
3130
|
-
|
|
3131
|
-
// src/js/components/stateful/chip.js
|
|
3132
|
-
var PREFIX5 = "ina";
|
|
3133
|
-
function initChip(rootSelector = `.${PREFIX5}-chip`) {
|
|
3134
|
-
const chips = document.querySelectorAll(rootSelector);
|
|
3135
|
-
chips.forEach((container) => {
|
|
3136
|
-
if (container.__inaChipInitialized) return;
|
|
3137
|
-
const showCustomization = container.getAttribute("data-show-customization") === "true";
|
|
3138
|
-
const customizationLabel = container.getAttribute("data-customization-label") || "Kustomisasi";
|
|
3139
|
-
const isMultiple = container.getAttribute("data-multiple") === "true";
|
|
3140
|
-
let selectedValue = container.getAttribute("data-selected") || "";
|
|
3141
|
-
const list = container.querySelector(`.${PREFIX5}-chip__list`);
|
|
3142
|
-
const items = list ? list.querySelectorAll(`.${PREFIX5}-chip__item`) : [];
|
|
3143
|
-
let customFieldContainer = container.querySelector(
|
|
3144
|
-
`.${PREFIX5}-chip__custom-field`
|
|
3145
|
-
);
|
|
3146
|
-
const getNormalizedSelected = () => {
|
|
3147
|
-
if (!selectedValue) return [];
|
|
3148
|
-
return isMultiple ? selectedValue.split(",").map((s) => s.trim()).filter(Boolean) : [selectedValue];
|
|
3149
|
-
};
|
|
3150
|
-
const updateUI = () => {
|
|
3151
|
-
const normSelected = getNormalizedSelected();
|
|
3152
|
-
const getInitialFocusIndex = () => {
|
|
3153
|
-
if (normSelected.length > 0) {
|
|
3154
|
-
const standardValues = Array.from(items).filter((item) => item.textContent.trim() !== customizationLabel).map((item) => item.getAttribute("data-value"));
|
|
3155
|
-
const hasCustomVal = normSelected.some(
|
|
3156
|
-
(val) => !standardValues.includes(val) && val !== ""
|
|
3157
|
-
);
|
|
3158
|
-
if (hasCustomVal && showCustomization) {
|
|
3159
|
-
return items.length - 1;
|
|
3160
|
-
}
|
|
3161
|
-
const firstSelectedIndex = Array.from(items).findIndex(
|
|
3162
|
-
(opt) => normSelected.includes(opt.getAttribute("data-value"))
|
|
3163
|
-
);
|
|
3164
|
-
if (firstSelectedIndex !== -1) return firstSelectedIndex;
|
|
3165
|
-
}
|
|
3166
|
-
return 0;
|
|
3167
|
-
};
|
|
3168
|
-
const focusedIndex = getInitialFocusIndex();
|
|
3169
|
-
items.forEach((item, index2) => {
|
|
3170
|
-
const itemValue = item.getAttribute("data-value");
|
|
3171
|
-
const isSelected = normSelected.includes(itemValue) || showCustomization && item.textContent.trim() === customizationLabel && normSelected.some(
|
|
3172
|
-
(val) => !Array.from(items).filter((i) => i.textContent.trim() !== customizationLabel).map((i) => i.getAttribute("data-value")).includes(val) && val !== ""
|
|
3173
|
-
);
|
|
3174
|
-
const isDisabled = item.hasAttribute("disabled");
|
|
3175
|
-
if (isSelected) {
|
|
3176
|
-
item.classList.add(`${PREFIX5}-chip__item--selected`);
|
|
3177
|
-
} else {
|
|
3178
|
-
item.classList.remove(`${PREFIX5}-chip__item--selected`);
|
|
3179
|
-
}
|
|
3180
|
-
if (isDisabled) {
|
|
3181
|
-
item.classList.add(`${PREFIX5}-chip__item--disabled`);
|
|
3182
|
-
}
|
|
3183
|
-
item.setAttribute(
|
|
3184
|
-
"tabindex",
|
|
3185
|
-
index2 === focusedIndex && !isDisabled ? "0" : "-1"
|
|
3186
|
-
);
|
|
3187
|
-
});
|
|
3188
|
-
if (showCustomization) {
|
|
3189
|
-
const isToggleBtn2 = (i) => i.hasAttribute("data-customization-toggle") || i.textContent.trim() === customizationLabel;
|
|
3190
|
-
const standardValues = Array.from(items).filter((item) => !isToggleBtn2(item)).map((item) => item.getAttribute("data-value"));
|
|
3191
|
-
const customValues = normSelected.filter(
|
|
3192
|
-
(val) => !standardValues.includes(val) && val !== ""
|
|
3193
|
-
);
|
|
3194
|
-
const isStandard = customValues.length === 0;
|
|
3195
|
-
const primaryCustomValue = customValues[customValues.length - 1] || "";
|
|
3196
|
-
const toggleBtn = Array.from(items).find(isToggleBtn2);
|
|
3197
|
-
const showInput = toggleBtn && normSelected.includes(toggleBtn.getAttribute("data-value")) || !isStandard && normSelected.length > 0;
|
|
3198
|
-
if (showInput) {
|
|
3199
|
-
if (!customFieldContainer) {
|
|
3200
|
-
customFieldContainer = document.createElement("div");
|
|
3201
|
-
customFieldContainer.className = `${PREFIX5}-chip__custom-field`;
|
|
3202
|
-
container.appendChild(customFieldContainer);
|
|
3203
|
-
}
|
|
3204
|
-
let input = customFieldContainer.querySelector(
|
|
3205
|
-
`.${PREFIX5}-chip__input`
|
|
3206
|
-
);
|
|
3207
|
-
if (!input) {
|
|
3208
|
-
customFieldContainer.innerHTML = `
|
|
3209
|
-
<div class="${PREFIX5}-chip__input-wrapper">
|
|
3210
|
-
<input type="text" class="${PREFIX5}-chip__input" placeholder="Masukkan data yang Anda inginkan" value="${!isStandard ? primaryCustomValue : ""}" />
|
|
3211
|
-
<button type="button" class="${PREFIX5}-chip__clear-button" aria-label="Clear input" style="display: ${!isStandard && primaryCustomValue ? "inline-flex" : "none"};">
|
|
3212
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="${PREFIX5}-chip__clear-icon">
|
|
3213
|
-
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
|
|
3214
|
-
<path d="M18 6l-12 12"></path>
|
|
3215
|
-
<path d="M6 6l12 12"></path>
|
|
3216
|
-
</svg>
|
|
3217
|
-
</button>
|
|
3218
|
-
</div>
|
|
3219
|
-
`;
|
|
3220
|
-
input = customFieldContainer.querySelector("input");
|
|
3221
|
-
const clearBtn = customFieldContainer.querySelector(
|
|
3222
|
-
".ina-chip__clear-button"
|
|
3223
|
-
);
|
|
3224
|
-
input.addEventListener("input", (e) => {
|
|
3225
|
-
clearBtn.style.display = e.target.value ? "inline-flex" : "none";
|
|
3226
|
-
});
|
|
3227
|
-
clearBtn.addEventListener("click", () => {
|
|
3228
|
-
input.value = "";
|
|
3229
|
-
clearBtn.style.display = "none";
|
|
3230
|
-
commitCustomValue(input);
|
|
3231
|
-
});
|
|
3232
|
-
input.addEventListener("blur", (e) => {
|
|
3233
|
-
commitCustomValue(e.target);
|
|
3234
|
-
});
|
|
3235
|
-
input.addEventListener("keydown", (e) => {
|
|
3236
|
-
if (e.key === "Enter") {
|
|
3237
|
-
commitCustomValue(e.target);
|
|
3238
|
-
e.target.blur();
|
|
3239
|
-
}
|
|
3240
|
-
});
|
|
3241
|
-
} else {
|
|
3242
|
-
const inputEl = customFieldContainer.querySelector("input");
|
|
3243
|
-
if (inputEl && document.activeElement !== inputEl) {
|
|
3244
|
-
inputEl.value = !isStandard ? primaryCustomValue : "";
|
|
3245
|
-
}
|
|
3246
|
-
}
|
|
3247
|
-
customFieldContainer.style.display = "block";
|
|
3248
|
-
} else {
|
|
3249
|
-
if (customFieldContainer) {
|
|
3250
|
-
customFieldContainer.style.display = "none";
|
|
3251
|
-
}
|
|
3252
|
-
}
|
|
3253
|
-
}
|
|
3254
|
-
};
|
|
3255
|
-
const handleSelect = (val) => {
|
|
3256
|
-
if (!val) return;
|
|
3257
|
-
let finalVal = val;
|
|
3258
|
-
if (isMultiple) {
|
|
3259
|
-
const normSelected = getNormalizedSelected();
|
|
3260
|
-
let newSelected;
|
|
3261
|
-
if (normSelected.includes(val)) {
|
|
3262
|
-
newSelected = normSelected.filter((v) => v !== val);
|
|
3263
|
-
} else {
|
|
3264
|
-
newSelected = [...normSelected, val];
|
|
3265
|
-
}
|
|
3266
|
-
finalVal = newSelected;
|
|
3267
|
-
selectedValue = newSelected.join(",");
|
|
3268
|
-
} else {
|
|
3269
|
-
const normSelected = getNormalizedSelected();
|
|
3270
|
-
if (normSelected.includes(val)) {
|
|
3271
|
-
selectedValue = "";
|
|
3272
|
-
finalVal = "";
|
|
3273
|
-
} else {
|
|
3274
|
-
selectedValue = val;
|
|
3275
|
-
}
|
|
3276
|
-
}
|
|
3277
|
-
container.setAttribute("data-selected", selectedValue);
|
|
3278
|
-
updateUI();
|
|
3279
|
-
container.dispatchEvent(
|
|
3280
|
-
new CustomEvent("chip:select", {
|
|
3281
|
-
detail: { value: finalVal },
|
|
3282
|
-
bubbles: true
|
|
3283
|
-
})
|
|
3284
|
-
);
|
|
3285
|
-
};
|
|
3286
|
-
let currentFocusedIndex = -1;
|
|
3287
|
-
const setItemFocus = (index2) => {
|
|
3288
|
-
items.forEach((item, i) => {
|
|
3289
|
-
item.setAttribute("tabindex", i === index2 ? "0" : "-1");
|
|
3290
|
-
});
|
|
3291
|
-
if (items[index2]) {
|
|
3292
|
-
items[index2].focus();
|
|
3293
|
-
currentFocusedIndex = index2;
|
|
3294
|
-
}
|
|
3295
|
-
};
|
|
3296
|
-
const commitCustomValue = (inputEl) => {
|
|
3297
|
-
const finalValue = inputEl.value.trim();
|
|
3298
|
-
let normSelected = getNormalizedSelected();
|
|
3299
|
-
const toggleBtn = Array.from(items).find(isToggleBtn);
|
|
3300
|
-
const toggleVal = toggleBtn ? toggleBtn.getAttribute("data-value") : null;
|
|
3301
|
-
const standardValues = Array.from(items).filter((i) => !isToggleBtn(i)).map((i) => i.getAttribute("data-value"));
|
|
3302
|
-
const customValues = normSelected.filter(
|
|
3303
|
-
(val) => !standardValues.includes(val) && val !== "" && val !== toggleVal
|
|
3304
|
-
);
|
|
3305
|
-
const primaryCustomValue = customValues[customValues.length - 1];
|
|
3306
|
-
if (primaryCustomValue) {
|
|
3307
|
-
normSelected = normSelected.filter((v) => v !== primaryCustomValue);
|
|
3308
|
-
}
|
|
3309
|
-
if (finalValue !== "") {
|
|
3310
|
-
if (!normSelected.includes(finalValue)) {
|
|
3311
|
-
normSelected.push(finalValue);
|
|
3312
|
-
}
|
|
3313
|
-
} else {
|
|
3314
|
-
if (toggleVal) {
|
|
3315
|
-
normSelected = normSelected.filter((v) => v !== toggleVal);
|
|
3316
|
-
}
|
|
3317
|
-
}
|
|
3318
|
-
if (isMultiple) {
|
|
3319
|
-
selectedValue = normSelected.join(",");
|
|
3320
|
-
} else {
|
|
3321
|
-
selectedValue = finalValue;
|
|
3322
|
-
}
|
|
3323
|
-
updateUI();
|
|
3324
|
-
const changeEvent = new CustomEvent(`${PREFIX5}-chip:change`, {
|
|
3325
|
-
detail: { value: isMultiple ? getNormalizedSelected() : selectedValue },
|
|
3326
|
-
bubbles: true
|
|
3327
|
-
});
|
|
3328
|
-
container.dispatchEvent(changeEvent);
|
|
3329
|
-
};
|
|
3330
|
-
items.forEach((item, index2) => {
|
|
3331
|
-
item.addEventListener("click", (e) => {
|
|
3332
|
-
if (item.hasAttribute("disabled")) return;
|
|
3333
|
-
currentFocusedIndex = index2;
|
|
3334
|
-
const val = item.getAttribute("data-value");
|
|
3335
|
-
if (showCustomization && isToggleBtn(item)) {
|
|
3336
|
-
const normSelected = getNormalizedSelected();
|
|
3337
|
-
const standardValues = Array.from(items).filter((i) => !isToggleBtn(i)).map((i) => i.getAttribute("data-value"));
|
|
3338
|
-
const customValues = normSelected.filter(
|
|
3339
|
-
(v) => !standardValues.includes(v) && v !== "" && v !== val
|
|
3340
|
-
);
|
|
3341
|
-
const isInputVisible = normSelected.includes(val) || customValues.length > 0;
|
|
3342
|
-
if (!isInputVisible) {
|
|
3343
|
-
handleSelect(val);
|
|
3344
|
-
}
|
|
3345
|
-
} else {
|
|
3346
|
-
handleSelect(val);
|
|
3347
|
-
}
|
|
3348
|
-
});
|
|
3349
|
-
item.addEventListener("keydown", (e) => {
|
|
3350
|
-
if (item.hasAttribute("disabled")) return;
|
|
3351
|
-
if (e.key === "ArrowRight" || e.key === "ArrowDown") {
|
|
3352
|
-
e.preventDefault();
|
|
3353
|
-
let nextIndex = (index2 + 1) % items.length;
|
|
3354
|
-
while (items[nextIndex].hasAttribute("disabled") && nextIndex !== index2) {
|
|
3355
|
-
nextIndex = (nextIndex + 1) % items.length;
|
|
3356
|
-
}
|
|
3357
|
-
setItemFocus(nextIndex);
|
|
3358
|
-
} else if (e.key === "ArrowLeft" || e.key === "ArrowUp") {
|
|
3359
|
-
e.preventDefault();
|
|
3360
|
-
let prevIndex = (index2 - 1 + items.length) % items.length;
|
|
3361
|
-
while (items[prevIndex].hasAttribute("disabled") && prevIndex !== index2) {
|
|
3362
|
-
prevIndex = (prevIndex - 1 + items.length) % items.length;
|
|
3363
|
-
}
|
|
3364
|
-
setItemFocus(prevIndex);
|
|
3365
|
-
}
|
|
3366
|
-
if (e.key === " " || e.key === "Enter") {
|
|
3367
|
-
e.preventDefault();
|
|
3368
|
-
item.click();
|
|
3369
|
-
}
|
|
3370
|
-
});
|
|
3371
|
-
});
|
|
3372
|
-
updateUI();
|
|
3373
|
-
container.__inaChipInitialized = true;
|
|
3374
|
-
});
|
|
3375
|
-
}
|
|
3376
|
-
|
|
3377
3243
|
// src/js/components/stateful/pagination.js
|
|
3378
3244
|
function initPagination() {
|
|
3379
3245
|
document.querySelectorAll(`.${PREFIX}-pagination`).forEach((container) => {
|
|
@@ -3596,6 +3462,573 @@ function initPagination() {
|
|
|
3596
3462
|
});
|
|
3597
3463
|
}
|
|
3598
3464
|
|
|
3465
|
+
// src/js/utils/countries.js
|
|
3466
|
+
var COUNTRIES = [
|
|
3467
|
+
{ code: "ID", name: "Indonesia", dialCode: "+62" },
|
|
3468
|
+
{ code: "AF", name: "Afghanistan", dialCode: "+93" },
|
|
3469
|
+
{ code: "AL", name: "Albania", dialCode: "+355" },
|
|
3470
|
+
{ code: "DZ", name: "Algeria", dialCode: "+213" },
|
|
3471
|
+
{ code: "AS", name: "American Samoa", dialCode: "+1684" },
|
|
3472
|
+
{ code: "AD", name: "Andorra", dialCode: "+376" },
|
|
3473
|
+
{ code: "AO", name: "Angola", dialCode: "+244" },
|
|
3474
|
+
{ code: "AI", name: "Anguilla", dialCode: "+1264" },
|
|
3475
|
+
{ code: "AG", name: "Antigua and Barbuda", dialCode: "+1268" },
|
|
3476
|
+
{ code: "AR", name: "Argentina", dialCode: "+54" },
|
|
3477
|
+
{ code: "AM", name: "Armenia", dialCode: "+374" },
|
|
3478
|
+
{ code: "AW", name: "Aruba", dialCode: "+297" },
|
|
3479
|
+
{ code: "AU", name: "Australia", dialCode: "+61" },
|
|
3480
|
+
{ code: "AT", name: "Austria", dialCode: "+43" },
|
|
3481
|
+
{ code: "AZ", name: "Azerbaijan", dialCode: "+994" },
|
|
3482
|
+
{ code: "BS", name: "Bahamas", dialCode: "+1242" },
|
|
3483
|
+
{ code: "BH", name: "Bahrain", dialCode: "+973" },
|
|
3484
|
+
{ code: "BD", name: "Bangladesh", dialCode: "+880" },
|
|
3485
|
+
{ code: "BB", name: "Barbados", dialCode: "+1246" },
|
|
3486
|
+
{ code: "BY", name: "Belarus", dialCode: "+375" },
|
|
3487
|
+
{ code: "BE", name: "Belgium", dialCode: "+32" },
|
|
3488
|
+
{ code: "BZ", name: "Belize", dialCode: "+501" },
|
|
3489
|
+
{ code: "BJ", name: "Benin", dialCode: "+229" },
|
|
3490
|
+
{ code: "BM", name: "Bermuda", dialCode: "+1441" },
|
|
3491
|
+
{ code: "BT", name: "Bhutan", dialCode: "+975" },
|
|
3492
|
+
{ code: "BO", name: "Bolivia", dialCode: "+591" },
|
|
3493
|
+
{ code: "BA", name: "Bosnia and Herzegovina", dialCode: "+387" },
|
|
3494
|
+
{ code: "BW", name: "Botswana", dialCode: "+267" },
|
|
3495
|
+
{ code: "BR", name: "Brazil", dialCode: "+55" },
|
|
3496
|
+
{ code: "IO", name: "British Indian Ocean Territory", dialCode: "+246" },
|
|
3497
|
+
{ code: "BN", name: "Brunei Darussalam", dialCode: "+673" },
|
|
3498
|
+
{ code: "BG", name: "Bulgaria", dialCode: "+359" },
|
|
3499
|
+
{ code: "BF", name: "Burkina Faso", dialCode: "+226" },
|
|
3500
|
+
{ code: "BI", name: "Burundi", dialCode: "+257" },
|
|
3501
|
+
{ code: "KH", name: "Cambodia", dialCode: "+855" },
|
|
3502
|
+
{ code: "CM", name: "Cameroon", dialCode: "+237" },
|
|
3503
|
+
{ code: "CA", name: "Canada", dialCode: "+1" },
|
|
3504
|
+
{ code: "CV", name: "Cape Verde", dialCode: "+238" },
|
|
3505
|
+
{ code: "KY", name: "Cayman Islands", dialCode: "+1345" },
|
|
3506
|
+
{ code: "CF", name: "Central African Republic", dialCode: "+236" },
|
|
3507
|
+
{ code: "TD", name: "Chad", dialCode: "+235" },
|
|
3508
|
+
{ code: "CL", name: "Chile", dialCode: "+56" },
|
|
3509
|
+
{ code: "CN", name: "China", dialCode: "+86" },
|
|
3510
|
+
{ code: "CX", name: "Christmas Island", dialCode: "+61" },
|
|
3511
|
+
{ code: "CC", name: "Cocos (Keeling) Islands", dialCode: "+61" },
|
|
3512
|
+
{ code: "CO", name: "Colombia", dialCode: "+57" },
|
|
3513
|
+
{ code: "KM", name: "Comoros", dialCode: "+269" },
|
|
3514
|
+
{ code: "CG", name: "Congo", dialCode: "+242" },
|
|
3515
|
+
{ code: "CD", name: "Congo, Democratic Republic of the", dialCode: "+243" },
|
|
3516
|
+
{ code: "CK", name: "Cook Islands", dialCode: "+682" },
|
|
3517
|
+
{ code: "CR", name: "Costa Rica", dialCode: "+506" },
|
|
3518
|
+
{ code: "CI", name: "Cote d'Ivoire", dialCode: "+225" },
|
|
3519
|
+
{ code: "HR", name: "Croatia", dialCode: "+385" },
|
|
3520
|
+
{ code: "CU", name: "Cuba", dialCode: "+53" },
|
|
3521
|
+
{ code: "CY", name: "Cyprus", dialCode: "+357" },
|
|
3522
|
+
{ code: "CZ", name: "Czech Republic", dialCode: "+420" },
|
|
3523
|
+
{ code: "DK", name: "Denmark", dialCode: "+45" },
|
|
3524
|
+
{ code: "DJ", name: "Djibouti", dialCode: "+253" },
|
|
3525
|
+
{ code: "DM", name: "Dominica", dialCode: "+1767" },
|
|
3526
|
+
{ code: "DO", name: "Dominican Republic", dialCode: "+1" },
|
|
3527
|
+
{ code: "EC", name: "Ecuador", dialCode: "+593" },
|
|
3528
|
+
{ code: "EG", name: "Egypt", dialCode: "+20" },
|
|
3529
|
+
{ code: "SV", name: "El Salvador", dialCode: "+503" },
|
|
3530
|
+
{ code: "GQ", name: "Equatorial Guinea", dialCode: "+240" },
|
|
3531
|
+
{ code: "ER", name: "Eritrea", dialCode: "+291" },
|
|
3532
|
+
{ code: "EE", name: "Estonia", dialCode: "+372" },
|
|
3533
|
+
{ code: "ET", name: "Ethiopia", dialCode: "+251" },
|
|
3534
|
+
{ code: "FK", name: "Falkland Islands (Malvinas)", dialCode: "+500" },
|
|
3535
|
+
{ code: "FO", name: "Faroe Islands", dialCode: "+298" },
|
|
3536
|
+
{ code: "FJ", name: "Fiji", dialCode: "+679" },
|
|
3537
|
+
{ code: "FI", name: "Finland", dialCode: "+358" },
|
|
3538
|
+
{ code: "FR", name: "France", dialCode: "+33" },
|
|
3539
|
+
{ code: "GF", name: "French Guiana", dialCode: "+594" },
|
|
3540
|
+
{ code: "PF", name: "French Polynesia", dialCode: "+689" },
|
|
3541
|
+
{ code: "GA", name: "Gabon", dialCode: "+241" },
|
|
3542
|
+
{ code: "GM", name: "Gambia", dialCode: "+220" },
|
|
3543
|
+
{ code: "GE", name: "Georgia", dialCode: "+995" },
|
|
3544
|
+
{ code: "DE", name: "Germany", dialCode: "+49" },
|
|
3545
|
+
{ code: "GH", name: "Ghana", dialCode: "+233" },
|
|
3546
|
+
{ code: "GI", name: "Gibraltar", dialCode: "+350" },
|
|
3547
|
+
{ code: "GR", name: "Greece", dialCode: "+30" },
|
|
3548
|
+
{ code: "GL", name: "Greenland", dialCode: "+299" },
|
|
3549
|
+
{ code: "GD", name: "Grenada", dialCode: "+1473" },
|
|
3550
|
+
{ code: "GP", name: "Guadeloupe", dialCode: "+590" },
|
|
3551
|
+
{ code: "GU", name: "Guam", dialCode: "+1671" },
|
|
3552
|
+
{ code: "GT", name: "Guatemala", dialCode: "+502" },
|
|
3553
|
+
{ code: "GG", name: "Guernsey", dialCode: "+44" },
|
|
3554
|
+
{ code: "GN", name: "Guinea", dialCode: "+224" },
|
|
3555
|
+
{ code: "GW", name: "Guinea-Bissau", dialCode: "+245" },
|
|
3556
|
+
{ code: "GY", name: "Guyana", dialCode: "+592" },
|
|
3557
|
+
{ code: "HT", name: "Haiti", dialCode: "+509" },
|
|
3558
|
+
{ code: "VA", name: "Holy See (Vatican City State)", dialCode: "+379" },
|
|
3559
|
+
{ code: "HN", name: "Honduras", dialCode: "+504" },
|
|
3560
|
+
{ code: "HK", name: "Hong Kong", dialCode: "+852" },
|
|
3561
|
+
{ code: "HU", name: "Hungary", dialCode: "+36" },
|
|
3562
|
+
{ code: "IS", name: "Iceland", dialCode: "+354" },
|
|
3563
|
+
{ code: "IN", name: "India", dialCode: "+91" },
|
|
3564
|
+
{ code: "IR", name: "Iran, Islamic Republic of", dialCode: "+98" },
|
|
3565
|
+
{ code: "IQ", name: "Iraq", dialCode: "+964" },
|
|
3566
|
+
{ code: "IE", name: "Ireland", dialCode: "+353" },
|
|
3567
|
+
{ code: "IM", name: "Isle of Man", dialCode: "+44" },
|
|
3568
|
+
{ code: "IL", name: "Israel", dialCode: "+972" },
|
|
3569
|
+
{ code: "IT", name: "Italy", dialCode: "+39" },
|
|
3570
|
+
{ code: "JM", name: "Jamaica", dialCode: "+1876" },
|
|
3571
|
+
{ code: "JP", name: "Japan", dialCode: "+81" },
|
|
3572
|
+
{ code: "JE", name: "Jersey", dialCode: "+44" },
|
|
3573
|
+
{ code: "JO", name: "Jordan", dialCode: "+962" },
|
|
3574
|
+
{ code: "KZ", name: "Kazakhstan", dialCode: "+7" },
|
|
3575
|
+
{ code: "KE", name: "Kenya", dialCode: "+254" },
|
|
3576
|
+
{ code: "KI", name: "Kiribati", dialCode: "+686" },
|
|
3577
|
+
{ code: "KP", name: "Korea, Democratic People's Republic of", dialCode: "+850" },
|
|
3578
|
+
{ code: "KR", name: "Korea, Republic of", dialCode: "+82" },
|
|
3579
|
+
{ code: "KW", name: "Kuwait", dialCode: "+965" },
|
|
3580
|
+
{ code: "KG", name: "Kyrgyzstan", dialCode: "+996" },
|
|
3581
|
+
{ code: "LA", name: "Laos", dialCode: "+856" },
|
|
3582
|
+
{ code: "LV", name: "Latvia", dialCode: "+371" },
|
|
3583
|
+
{ code: "LB", name: "Lebanon", dialCode: "+961" },
|
|
3584
|
+
{ code: "LS", name: "Lesotho", dialCode: "+266" },
|
|
3585
|
+
{ code: "LR", name: "Liberia", dialCode: "+231" },
|
|
3586
|
+
{ code: "LY", name: "Libyan Arab Jamahiriya", dialCode: "+218" },
|
|
3587
|
+
{ code: "LI", name: "Liechtenstein", dialCode: "+423" },
|
|
3588
|
+
{ code: "LT", name: "Lithuania", dialCode: "+370" },
|
|
3589
|
+
{ code: "LU", name: "Luxembourg", dialCode: "+352" },
|
|
3590
|
+
{ code: "MO", name: "Macao", dialCode: "+853" },
|
|
3591
|
+
{ code: "MK", name: "Macedonia, the Former Yugoslav Republic of", dialCode: "+389" },
|
|
3592
|
+
{ code: "MG", name: "Madagascar", dialCode: "+261" },
|
|
3593
|
+
{ code: "MW", name: "Malawi", dialCode: "+265" },
|
|
3594
|
+
{ code: "MY", name: "Malaysia", dialCode: "+60" },
|
|
3595
|
+
{ code: "MV", name: "Maldives", dialCode: "+960" },
|
|
3596
|
+
{ code: "ML", name: "Mali", dialCode: "+223" },
|
|
3597
|
+
{ code: "MT", name: "Malta", dialCode: "+356" },
|
|
3598
|
+
{ code: "MH", name: "Marshall Islands", dialCode: "+692" },
|
|
3599
|
+
{ code: "MQ", name: "Martinique", dialCode: "+596" },
|
|
3600
|
+
{ code: "MR", name: "Mauritania", dialCode: "+222" },
|
|
3601
|
+
{ code: "MU", name: "Mauritius", dialCode: "+230" },
|
|
3602
|
+
{ code: "YT", name: "Mayotte", dialCode: "+262" },
|
|
3603
|
+
{ code: "MX", name: "Mexico", dialCode: "+52" },
|
|
3604
|
+
{ code: "FM", name: "Micronesia, Federated States of", dialCode: "+691" },
|
|
3605
|
+
{ code: "MD", name: "Moldova, Republic of", dialCode: "+373" },
|
|
3606
|
+
{ code: "MC", name: "Monaco", dialCode: "+377" },
|
|
3607
|
+
{ code: "MN", name: "Mongolia", dialCode: "+976" },
|
|
3608
|
+
{ code: "ME", name: "Montenegro", dialCode: "+382" },
|
|
3609
|
+
{ code: "MS", name: "Montserrat", dialCode: "+1664" },
|
|
3610
|
+
{ code: "MA", name: "Morocco", dialCode: "+212" },
|
|
3611
|
+
{ code: "MZ", name: "Mozambique", dialCode: "+258" },
|
|
3612
|
+
{ code: "MM", name: "Myanmar", dialCode: "+95" },
|
|
3613
|
+
{ code: "NA", name: "Namibia", dialCode: "+264" },
|
|
3614
|
+
{ code: "NR", name: "Nauru", dialCode: "+674" },
|
|
3615
|
+
{ code: "NP", name: "Nepal", dialCode: "+977" },
|
|
3616
|
+
{ code: "NL", name: "Netherlands", dialCode: "+31" },
|
|
3617
|
+
{ code: "NC", name: "New Caledonia", dialCode: "+687" },
|
|
3618
|
+
{ code: "NZ", name: "New Zealand", dialCode: "+64" },
|
|
3619
|
+
{ code: "NI", name: "Nicaragua", dialCode: "+505" },
|
|
3620
|
+
{ code: "NE", name: "Niger", dialCode: "+227" },
|
|
3621
|
+
{ code: "NG", name: "Nigeria", dialCode: "+234" },
|
|
3622
|
+
{ code: "NU", name: "Niue", dialCode: "+683" },
|
|
3623
|
+
{ code: "NF", name: "Norfolk Island", dialCode: "+672" },
|
|
3624
|
+
{ code: "MP", name: "Northern Mariana Islands", dialCode: "+1670" },
|
|
3625
|
+
{ code: "NO", name: "Norway", dialCode: "+47" },
|
|
3626
|
+
{ code: "OM", name: "Oman", dialCode: "+968" },
|
|
3627
|
+
{ code: "PK", name: "Pakistan", dialCode: "+92" },
|
|
3628
|
+
{ code: "PW", name: "Palau", dialCode: "+680" },
|
|
3629
|
+
{ code: "PS", name: "Palestine", dialCode: "+970" },
|
|
3630
|
+
{ code: "PA", name: "Panama", dialCode: "+507" },
|
|
3631
|
+
{ code: "PG", name: "Papua New Guinea", dialCode: "+675" },
|
|
3632
|
+
{ code: "PY", name: "Paraguay", dialCode: "+595" },
|
|
3633
|
+
{ code: "PE", name: "Peru", dialCode: "+51" },
|
|
3634
|
+
{ code: "PH", name: "Philippines", dialCode: "+63" },
|
|
3635
|
+
{ code: "PN", name: "Pitcairn", dialCode: "+870" },
|
|
3636
|
+
{ code: "PL", name: "Poland", dialCode: "+48" },
|
|
3637
|
+
{ code: "PT", name: "Portugal", dialCode: "+351" },
|
|
3638
|
+
{ code: "PR", name: "Puerto Rico", dialCode: "+1939" },
|
|
3639
|
+
{ code: "QA", name: "Qatar", dialCode: "+974" },
|
|
3640
|
+
{ code: "RE", name: "Reunion", dialCode: "+262" },
|
|
3641
|
+
{ code: "RO", name: "Romania", dialCode: "+40" },
|
|
3642
|
+
{ code: "RU", name: "Russian Federation", dialCode: "+7" },
|
|
3643
|
+
{ code: "RW", name: "Rwanda", dialCode: "+250" },
|
|
3644
|
+
{ code: "BL", name: "Saint Barthelemy", dialCode: "+590" },
|
|
3645
|
+
{ code: "SH", name: "Saint Helena", dialCode: "+290" },
|
|
3646
|
+
{ code: "KN", name: "Saint Kitts and Nevis", dialCode: "+1869" },
|
|
3647
|
+
{ code: "LC", name: "Saint Lucia", dialCode: "+1758" },
|
|
3648
|
+
{ code: "MF", name: "Saint Martin", dialCode: "+590" },
|
|
3649
|
+
{ code: "PM", name: "Saint Pierre and Miquelon", dialCode: "+508" },
|
|
3650
|
+
{ code: "VC", name: "Saint Vincent and the Grenadines", dialCode: "+1784" },
|
|
3651
|
+
{ code: "WS", name: "Samoa", dialCode: "+685" },
|
|
3652
|
+
{ code: "SM", name: "San Marino", dialCode: "+378" },
|
|
3653
|
+
{ code: "ST", name: "Sao Tome and Principe", dialCode: "+239" },
|
|
3654
|
+
{ code: "SA", name: "Saudi Arabia", dialCode: "+966" },
|
|
3655
|
+
{ code: "SN", name: "Senegal", dialCode: "+221" },
|
|
3656
|
+
{ code: "RS", name: "Serbia", dialCode: "+381" },
|
|
3657
|
+
{ code: "SC", name: "Seychelles", dialCode: "+248" },
|
|
3658
|
+
{ code: "SL", name: "Sierra Leone", dialCode: "+232" },
|
|
3659
|
+
{ code: "SG", name: "Singapore", dialCode: "+65" },
|
|
3660
|
+
{ code: "SK", name: "Slovakia", dialCode: "+421" },
|
|
3661
|
+
{ code: "SI", name: "Slovenia", dialCode: "+386" },
|
|
3662
|
+
{ code: "SB", name: "Solomon Islands", dialCode: "+677" },
|
|
3663
|
+
{ code: "SO", name: "Somalia", dialCode: "+252" },
|
|
3664
|
+
{ code: "ZA", name: "South Africa", dialCode: "+27" },
|
|
3665
|
+
{ code: "GS", name: "South Georgia and the South Sandwich Islands", dialCode: "+500" },
|
|
3666
|
+
{ code: "ES", name: "Spain", dialCode: "+34" },
|
|
3667
|
+
{ code: "LK", name: "Sri Lanka", dialCode: "+94" },
|
|
3668
|
+
{ code: "SD", name: "Sudan", dialCode: "+249" },
|
|
3669
|
+
{ code: "SR", name: "Suriname", dialCode: "+597" },
|
|
3670
|
+
{ code: "SJ", name: "Svalbard and Jan Mayen", dialCode: "+47" },
|
|
3671
|
+
{ code: "SZ", name: "Swaziland", dialCode: "+268" },
|
|
3672
|
+
{ code: "SE", name: "Sweden", dialCode: "+46" },
|
|
3673
|
+
{ code: "CH", name: "Switzerland", dialCode: "+41" },
|
|
3674
|
+
{ code: "SY", name: "Syrian Arab Republic", dialCode: "+963" },
|
|
3675
|
+
{ code: "TW", name: "Taiwan, Province of China", dialCode: "+886" },
|
|
3676
|
+
{ code: "TJ", name: "Tajikistan", dialCode: "+992" },
|
|
3677
|
+
{ code: "TZ", name: "Tanzania, United Republic of", dialCode: "+255" },
|
|
3678
|
+
{ code: "TH", name: "Thailand", dialCode: "+66" },
|
|
3679
|
+
{ code: "TL", name: "Timor-Leste", dialCode: "+670" },
|
|
3680
|
+
{ code: "TG", name: "Togo", dialCode: "+228" },
|
|
3681
|
+
{ code: "TK", name: "Tokelau", dialCode: "+690" },
|
|
3682
|
+
{ code: "TO", name: "Tonga", dialCode: "+676" },
|
|
3683
|
+
{ code: "TT", name: "Trinidad and Tobago", dialCode: "+1868" },
|
|
3684
|
+
{ code: "TN", name: "Tunisia", dialCode: "+216" },
|
|
3685
|
+
{ code: "TR", name: "Turkey", dialCode: "+90" },
|
|
3686
|
+
{ code: "TM", name: "Turkmenistan", dialCode: "+993" },
|
|
3687
|
+
{ code: "TC", name: "Turks and Caicos Islands", dialCode: "+1649" },
|
|
3688
|
+
{ code: "TV", name: "Tuvalu", dialCode: "+688" },
|
|
3689
|
+
{ code: "UG", name: "Uganda", dialCode: "+256" },
|
|
3690
|
+
{ code: "UA", name: "Ukraine", dialCode: "+380" },
|
|
3691
|
+
{ code: "AE", name: "United Arab Emirates", dialCode: "+971" },
|
|
3692
|
+
{ code: "GB", name: "United Kingdom", dialCode: "+44" },
|
|
3693
|
+
{ code: "US", name: "United States", dialCode: "+1" },
|
|
3694
|
+
{ code: "UY", name: "Uruguay", dialCode: "+598" },
|
|
3695
|
+
{ code: "UZ", name: "Uzbekistan", dialCode: "+998" },
|
|
3696
|
+
{ code: "VU", name: "Vanuatu", dialCode: "+678" },
|
|
3697
|
+
{ code: "VE", name: "Venezuela", dialCode: "+58" },
|
|
3698
|
+
{ code: "VN", name: "Vietnam", dialCode: "+84" },
|
|
3699
|
+
{ code: "VG", name: "Virgin Islands, British", dialCode: "+1284" },
|
|
3700
|
+
{ code: "VI", name: "Virgin Islands, U.S.", dialCode: "+1340" },
|
|
3701
|
+
{ code: "WF", name: "Wallis and Futuna", dialCode: "+681" },
|
|
3702
|
+
{ code: "EH", name: "Western Sahara", dialCode: "+212" },
|
|
3703
|
+
{ code: "YE", name: "Yemen", dialCode: "+967" },
|
|
3704
|
+
{ code: "ZM", name: "Zambia", dialCode: "+260" },
|
|
3705
|
+
{ code: "ZW", name: "Zimbabwe", dialCode: "+263" }
|
|
3706
|
+
];
|
|
3707
|
+
|
|
3708
|
+
// src/js/utils/flags.js
|
|
3709
|
+
var flagCache = {};
|
|
3710
|
+
var getFlag = async (code) => {
|
|
3711
|
+
if (flagCache[code]) {
|
|
3712
|
+
return flagCache[code];
|
|
3713
|
+
}
|
|
3714
|
+
try {
|
|
3715
|
+
const flag = await import(`@idds/styles/assets/flags/${code.toLowerCase()}.svg`);
|
|
3716
|
+
flagCache[code] = flag.default;
|
|
3717
|
+
return flag.default;
|
|
3718
|
+
} catch (error) {
|
|
3719
|
+
console.error(`[IDDS PhoneInput] Failed to load flag for: ${code}`, error);
|
|
3720
|
+
return "";
|
|
3721
|
+
}
|
|
3722
|
+
};
|
|
3723
|
+
|
|
3724
|
+
// src/js/components/stateful/phone-input.js
|
|
3725
|
+
var PhoneInput = class {
|
|
3726
|
+
constructor(selectorOrElement, options = {}) {
|
|
3727
|
+
this.container = typeof selectorOrElement === "string" ? document.querySelector(selectorOrElement) : selectorOrElement;
|
|
3728
|
+
if (!this.container) {
|
|
3729
|
+
console.warn("[IDDS PhoneInput] Container not found:", selectorOrElement);
|
|
3730
|
+
return;
|
|
3731
|
+
}
|
|
3732
|
+
if (this.container.dataset.initialized === "true") {
|
|
3733
|
+
return;
|
|
3734
|
+
}
|
|
3735
|
+
this.container.dataset.initialized = "true";
|
|
3736
|
+
this.options = {
|
|
3737
|
+
modelValue: this.container.dataset.value || "",
|
|
3738
|
+
label: this.container.dataset.label || "",
|
|
3739
|
+
placeholder: this.container.getAttribute("placeholder") || "812-3456-7890",
|
|
3740
|
+
size: this.container.dataset.size || "md",
|
|
3741
|
+
status: this.container.dataset.status || "neutral",
|
|
3742
|
+
disabled: this.container.hasAttribute("disabled") || false,
|
|
3743
|
+
readonly: this.container.hasAttribute("readonly") || false,
|
|
3744
|
+
required: this.container.hasAttribute("required") || false,
|
|
3745
|
+
defaultCountry: this.container.dataset.defaultCountry || "ID",
|
|
3746
|
+
allowClear: this.container.dataset.allowClear !== "false",
|
|
3747
|
+
countries: COUNTRIES,
|
|
3748
|
+
onChange: null,
|
|
3749
|
+
...options
|
|
3750
|
+
};
|
|
3751
|
+
this.state = {
|
|
3752
|
+
isOpen: false,
|
|
3753
|
+
countrySearch: "",
|
|
3754
|
+
selectedCountry: this.options.countries.find((c) => c.code === this.options.defaultCountry) || this.options.countries[0],
|
|
3755
|
+
phoneNumber: ""
|
|
3756
|
+
};
|
|
3757
|
+
this.elements = {};
|
|
3758
|
+
this.inputId = `phone-input-${Math.random().toString(36).substr(2, 9)}`;
|
|
3759
|
+
this.init();
|
|
3760
|
+
}
|
|
3761
|
+
async init() {
|
|
3762
|
+
this.initDOM();
|
|
3763
|
+
this.initEvents();
|
|
3764
|
+
this.syncValueFromOptions();
|
|
3765
|
+
await this.updateFlag();
|
|
3766
|
+
}
|
|
3767
|
+
initDOM() {
|
|
3768
|
+
if (this.options.label) {
|
|
3769
|
+
const label = document.createElement("label");
|
|
3770
|
+
label.className = `${PREFIX}-phone-input__label`;
|
|
3771
|
+
label.setAttribute("for", this.inputId);
|
|
3772
|
+
label.textContent = this.options.label;
|
|
3773
|
+
if (this.options.required) {
|
|
3774
|
+
const asterisk = document.createElement("span");
|
|
3775
|
+
asterisk.className = `${PREFIX}-phone-input__required`;
|
|
3776
|
+
asterisk.textContent = "*";
|
|
3777
|
+
label.appendChild(asterisk);
|
|
3778
|
+
}
|
|
3779
|
+
this.container.appendChild(label);
|
|
3780
|
+
}
|
|
3781
|
+
const wrapper = document.createElement("div");
|
|
3782
|
+
wrapper.className = `${PREFIX}-phone-input__wrapper ${PREFIX}-phone-input__wrapper--size-${this.options.size}`;
|
|
3783
|
+
if (this.options.status !== "neutral") {
|
|
3784
|
+
wrapper.classList.add(`${PREFIX}-phone-input__wrapper--status-${this.options.status}`);
|
|
3785
|
+
}
|
|
3786
|
+
if (this.options.disabled) {
|
|
3787
|
+
wrapper.classList.add(`${PREFIX}-phone-input__wrapper--disabled`);
|
|
3788
|
+
}
|
|
3789
|
+
const selector = document.createElement("div");
|
|
3790
|
+
selector.className = `${PREFIX}-phone-input__country-selector`;
|
|
3791
|
+
const countryBtn = document.createElement("button");
|
|
3792
|
+
countryBtn.type = "button";
|
|
3793
|
+
countryBtn.className = `${PREFIX}-phone-input__country-button`;
|
|
3794
|
+
countryBtn.setAttribute("aria-label", "Pilih negara");
|
|
3795
|
+
countryBtn.setAttribute("aria-haspopup", "listbox");
|
|
3796
|
+
countryBtn.setAttribute("aria-expanded", "false");
|
|
3797
|
+
if (this.options.disabled || this.options.readonly) countryBtn.disabled = true;
|
|
3798
|
+
const flagImg = document.createElement("img");
|
|
3799
|
+
flagImg.className = `${PREFIX}-phone-input__country-flag-img`;
|
|
3800
|
+
flagImg.width = 24;
|
|
3801
|
+
flagImg.height = 18;
|
|
3802
|
+
flagImg.alt = "";
|
|
3803
|
+
const dialCode = document.createElement("span");
|
|
3804
|
+
dialCode.className = `${PREFIX}-phone-input__country-code`;
|
|
3805
|
+
dialCode.textContent = this.state.selectedCountry.dialCode;
|
|
3806
|
+
const chevron = document.createElement("div");
|
|
3807
|
+
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">
|
|
3808
|
+
<path d="M6 9L12 15L18 9" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
3809
|
+
</svg>`;
|
|
3810
|
+
countryBtn.appendChild(flagImg);
|
|
3811
|
+
countryBtn.appendChild(dialCode);
|
|
3812
|
+
countryBtn.appendChild(chevron.firstChild);
|
|
3813
|
+
selector.appendChild(countryBtn);
|
|
3814
|
+
wrapper.appendChild(selector);
|
|
3815
|
+
const divider = document.createElement("div");
|
|
3816
|
+
divider.className = `${PREFIX}-phone-input__divider`;
|
|
3817
|
+
wrapper.appendChild(divider);
|
|
3818
|
+
const input = document.createElement("input");
|
|
3819
|
+
input.type = "tel";
|
|
3820
|
+
input.id = this.inputId;
|
|
3821
|
+
input.placeholder = this.options.placeholder;
|
|
3822
|
+
input.className = `${PREFIX}-phone-input__input`;
|
|
3823
|
+
if (this.options.disabled) input.disabled = true;
|
|
3824
|
+
if (this.options.readonly) input.readOnly = true;
|
|
3825
|
+
wrapper.appendChild(input);
|
|
3826
|
+
if (this.options.allowClear) {
|
|
3827
|
+
const clearBtn = document.createElement("button");
|
|
3828
|
+
clearBtn.type = "button";
|
|
3829
|
+
clearBtn.className = `${PREFIX}-phone-input__clear-button`;
|
|
3830
|
+
clearBtn.setAttribute("aria-label", "Hapus nomor telepon");
|
|
3831
|
+
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">
|
|
3832
|
+
<line x1="18" y1="6" x2="6" y2="18"></line>
|
|
3833
|
+
<line x1="6" y1="6" x2="18" y2="18"></line>
|
|
3834
|
+
</svg>`;
|
|
3835
|
+
clearBtn.style.display = "none";
|
|
3836
|
+
wrapper.appendChild(clearBtn);
|
|
3837
|
+
this.elements.clearBtn = clearBtn;
|
|
3838
|
+
}
|
|
3839
|
+
this.container.appendChild(wrapper);
|
|
3840
|
+
const panel = document.createElement("div");
|
|
3841
|
+
panel.className = `${PREFIX}-phone-input__country-dropdown`;
|
|
3842
|
+
panel.style.display = "none";
|
|
3843
|
+
const searchDiv = document.createElement("div");
|
|
3844
|
+
searchDiv.className = `${PREFIX}-phone-input__country-search`;
|
|
3845
|
+
const searchInput = document.createElement("input");
|
|
3846
|
+
searchInput.type = "text";
|
|
3847
|
+
searchInput.placeholder = "Cari";
|
|
3848
|
+
searchInput.className = `${PREFIX}-phone-input__country-search-input`;
|
|
3849
|
+
searchDiv.appendChild(searchInput);
|
|
3850
|
+
panel.appendChild(searchDiv);
|
|
3851
|
+
const list = document.createElement("div");
|
|
3852
|
+
list.className = `${PREFIX}-phone-input__country-list`;
|
|
3853
|
+
list.setAttribute("role", "listbox");
|
|
3854
|
+
panel.appendChild(list);
|
|
3855
|
+
selector.appendChild(panel);
|
|
3856
|
+
this.elements.wrapper = wrapper;
|
|
3857
|
+
this.elements.countryBtn = countryBtn;
|
|
3858
|
+
this.elements.flagImg = flagImg;
|
|
3859
|
+
this.elements.dialCode = dialCode;
|
|
3860
|
+
this.elements.input = input;
|
|
3861
|
+
this.elements.panel = panel;
|
|
3862
|
+
this.elements.searchInput = searchInput;
|
|
3863
|
+
this.elements.list = list;
|
|
3864
|
+
this.elements.chevron = selector.querySelector(`.${PREFIX}-phone-input__country-chevron`);
|
|
3865
|
+
}
|
|
3866
|
+
initEvents() {
|
|
3867
|
+
this.elements.countryBtn.addEventListener("click", (e) => {
|
|
3868
|
+
e.stopPropagation();
|
|
3869
|
+
this.toggleDropdown();
|
|
3870
|
+
});
|
|
3871
|
+
this.elements.searchInput.addEventListener("input", (e) => {
|
|
3872
|
+
this.state.countrySearch = e.target.value;
|
|
3873
|
+
this.renderCountryList();
|
|
3874
|
+
});
|
|
3875
|
+
this.elements.input.addEventListener("input", (e) => {
|
|
3876
|
+
this.handleInput(e);
|
|
3877
|
+
});
|
|
3878
|
+
if (this.elements.clearBtn) {
|
|
3879
|
+
this.elements.clearBtn.addEventListener("click", () => {
|
|
3880
|
+
this.clear();
|
|
3881
|
+
});
|
|
3882
|
+
this.elements.clearBtn.addEventListener("keydown", (e) => {
|
|
3883
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
3884
|
+
e.preventDefault();
|
|
3885
|
+
this.clear();
|
|
3886
|
+
}
|
|
3887
|
+
});
|
|
3888
|
+
}
|
|
3889
|
+
document.addEventListener("click", (e) => {
|
|
3890
|
+
if (!this.elements.wrapper.contains(e.target)) {
|
|
3891
|
+
this.closeDropdown();
|
|
3892
|
+
}
|
|
3893
|
+
});
|
|
3894
|
+
}
|
|
3895
|
+
async updateFlag() {
|
|
3896
|
+
const url = await getFlag(this.state.selectedCountry.code);
|
|
3897
|
+
this.elements.flagImg.src = url;
|
|
3898
|
+
this.elements.flagImg.alt = this.state.selectedCountry.name;
|
|
3899
|
+
this.elements.dialCode.textContent = this.state.selectedCountry.dialCode;
|
|
3900
|
+
}
|
|
3901
|
+
toggleDropdown() {
|
|
3902
|
+
if (this.state.isOpen) {
|
|
3903
|
+
this.closeDropdown();
|
|
3904
|
+
} else {
|
|
3905
|
+
this.openDropdown();
|
|
3906
|
+
}
|
|
3907
|
+
}
|
|
3908
|
+
openDropdown() {
|
|
3909
|
+
this.state.isOpen = true;
|
|
3910
|
+
this.elements.panel.style.display = "flex";
|
|
3911
|
+
this.elements.countryBtn.setAttribute("aria-expanded", "true");
|
|
3912
|
+
this.elements.chevron.classList.add(`${PREFIX}-phone-input__country-chevron--open`);
|
|
3913
|
+
this.state.countrySearch = "";
|
|
3914
|
+
this.elements.searchInput.value = "";
|
|
3915
|
+
this.renderCountryList();
|
|
3916
|
+
setTimeout(() => this.elements.searchInput.focus(), 0);
|
|
3917
|
+
}
|
|
3918
|
+
closeDropdown() {
|
|
3919
|
+
this.state.isOpen = false;
|
|
3920
|
+
this.elements.panel.style.display = "none";
|
|
3921
|
+
this.elements.countryBtn.setAttribute("aria-expanded", "false");
|
|
3922
|
+
this.elements.chevron.classList.remove(`${PREFIX}-phone-input__country-chevron--open`);
|
|
3923
|
+
}
|
|
3924
|
+
renderCountryList() {
|
|
3925
|
+
const list = this.elements.list;
|
|
3926
|
+
list.innerHTML = "";
|
|
3927
|
+
const filtered = this.options.countries.filter(
|
|
3928
|
+
(c) => c.name.toLowerCase().includes(this.state.countrySearch.toLowerCase()) || c.dialCode.includes(this.state.countrySearch) || c.code.toLowerCase().includes(this.state.countrySearch.toLowerCase())
|
|
3929
|
+
);
|
|
3930
|
+
filtered.forEach(async (country) => {
|
|
3931
|
+
const option = document.createElement("button");
|
|
3932
|
+
option.type = "button";
|
|
3933
|
+
option.className = `${PREFIX}-phone-input__country-option`;
|
|
3934
|
+
if (country.code === this.state.selectedCountry.code) {
|
|
3935
|
+
option.classList.add(`${PREFIX}-phone-input__country-option--selected`);
|
|
3936
|
+
}
|
|
3937
|
+
option.setAttribute("role", "option");
|
|
3938
|
+
option.setAttribute("aria-selected", country.code === this.state.selectedCountry.code ? "true" : "false");
|
|
3939
|
+
const flag = document.createElement("img");
|
|
3940
|
+
flag.className = `${PREFIX}-phone-input__country-flag-img`;
|
|
3941
|
+
flag.width = 20;
|
|
3942
|
+
flag.height = 15;
|
|
3943
|
+
getFlag(country.code).then((url) => flag.src = url);
|
|
3944
|
+
const name = document.createElement("span");
|
|
3945
|
+
name.className = `${PREFIX}-phone-input__country-name`;
|
|
3946
|
+
name.textContent = `${country.name} (${country.code})`;
|
|
3947
|
+
const code = document.createElement("span");
|
|
3948
|
+
code.className = `${PREFIX}-phone-input__country-dial-code`;
|
|
3949
|
+
code.textContent = country.dialCode;
|
|
3950
|
+
option.appendChild(flag);
|
|
3951
|
+
option.appendChild(name);
|
|
3952
|
+
option.appendChild(code);
|
|
3953
|
+
option.addEventListener("click", () => {
|
|
3954
|
+
this.selectCountry(country);
|
|
3955
|
+
});
|
|
3956
|
+
list.appendChild(option);
|
|
3957
|
+
});
|
|
3958
|
+
}
|
|
3959
|
+
selectCountry(country) {
|
|
3960
|
+
this.state.selectedCountry = country;
|
|
3961
|
+
this.updateFlag();
|
|
3962
|
+
this.closeDropdown();
|
|
3963
|
+
this.elements.input.focus();
|
|
3964
|
+
this.triggerChange();
|
|
3965
|
+
}
|
|
3966
|
+
formatPhoneNumber(value) {
|
|
3967
|
+
const clean = value.replace(/\D/g, "");
|
|
3968
|
+
if (clean.length > 7) {
|
|
3969
|
+
return clean.replace(/^(\d{3})(\d{4})(.*)/, "$1-$2-$3");
|
|
3970
|
+
} else if (clean.length > 3) {
|
|
3971
|
+
return clean.replace(/^(\d{3})(.*)/, "$1-$2");
|
|
3972
|
+
}
|
|
3973
|
+
return clean;
|
|
3974
|
+
}
|
|
3975
|
+
handleInput(e) {
|
|
3976
|
+
const value = e.target.value;
|
|
3977
|
+
const formatted = this.formatPhoneNumber(value);
|
|
3978
|
+
e.target.value = formatted;
|
|
3979
|
+
this.state.phoneNumber = formatted;
|
|
3980
|
+
if (this.elements.clearBtn) {
|
|
3981
|
+
this.elements.clearBtn.style.display = formatted ? "flex" : "none";
|
|
3982
|
+
}
|
|
3983
|
+
this.triggerChange();
|
|
3984
|
+
}
|
|
3985
|
+
clear() {
|
|
3986
|
+
this.state.phoneNumber = "";
|
|
3987
|
+
this.elements.input.value = "";
|
|
3988
|
+
if (this.elements.clearBtn) {
|
|
3989
|
+
this.elements.clearBtn.style.display = "none";
|
|
3990
|
+
}
|
|
3991
|
+
this.elements.input.focus();
|
|
3992
|
+
this.triggerChange();
|
|
3993
|
+
}
|
|
3994
|
+
syncValueFromOptions() {
|
|
3995
|
+
if (this.options.modelValue) {
|
|
3996
|
+
let val = this.options.modelValue;
|
|
3997
|
+
const dial = this.state.selectedCountry.dialCode;
|
|
3998
|
+
if (val.startsWith(dial)) {
|
|
3999
|
+
val = val.substring(dial.length);
|
|
4000
|
+
}
|
|
4001
|
+
this.state.phoneNumber = this.formatPhoneNumber(val);
|
|
4002
|
+
this.elements.input.value = this.state.phoneNumber;
|
|
4003
|
+
if (this.elements.clearBtn && this.state.phoneNumber) {
|
|
4004
|
+
this.elements.clearBtn.style.display = "flex";
|
|
4005
|
+
}
|
|
4006
|
+
}
|
|
4007
|
+
}
|
|
4008
|
+
triggerChange() {
|
|
4009
|
+
const cleanLocal = this.state.phoneNumber.replace(/\D/g, "");
|
|
4010
|
+
const cleanNoZero = cleanLocal.startsWith("0") ? cleanLocal.substring(1) : cleanLocal;
|
|
4011
|
+
const fullValue = `${this.state.selectedCountry.dialCode}${cleanNoZero}`;
|
|
4012
|
+
if (this.options.onChange) {
|
|
4013
|
+
this.options.onChange(fullValue);
|
|
4014
|
+
}
|
|
4015
|
+
this.container.dispatchEvent(new CustomEvent("change", {
|
|
4016
|
+
detail: { value: fullValue, country: this.state.selectedCountry }
|
|
4017
|
+
}));
|
|
4018
|
+
}
|
|
4019
|
+
};
|
|
4020
|
+
function initPhoneInput(selectorOrElement, options = {}) {
|
|
4021
|
+
const elements = typeof selectorOrElement === "string" ? document.querySelectorAll(selectorOrElement) : selectorOrElement ? typeof selectorOrElement.length !== "undefined" ? selectorOrElement : [selectorOrElement] : document.querySelectorAll(`.${PREFIX}-phone-input`);
|
|
4022
|
+
const instances = [];
|
|
4023
|
+
elements.forEach((container) => {
|
|
4024
|
+
const instance = new PhoneInput(container, options);
|
|
4025
|
+
container.__phoneInputAPI = instance;
|
|
4026
|
+
instances.push(instance);
|
|
4027
|
+
});
|
|
4028
|
+
if (instances.length === 0) return null;
|
|
4029
|
+
return instances.length === 1 ? instances[0] : instances;
|
|
4030
|
+
}
|
|
4031
|
+
|
|
3599
4032
|
// src/js/components/stateful/tab-vertical.js
|
|
3600
4033
|
function initTabVertical() {
|
|
3601
4034
|
const tabs = document.querySelectorAll(`.${PREFIX}-tab-vertical`);
|
|
@@ -3708,7 +4141,7 @@ function initTabHorizontal() {
|
|
|
3708
4141
|
|
|
3709
4142
|
// src/js/components/stateful/table.js
|
|
3710
4143
|
var Table = class {
|
|
3711
|
-
constructor(selectorOrElement,
|
|
4144
|
+
constructor(selectorOrElement, options = {}) {
|
|
3712
4145
|
this.container = typeof selectorOrElement === "string" ? document.querySelector(selectorOrElement) : selectorOrElement;
|
|
3713
4146
|
if (!this.container) {
|
|
3714
4147
|
console.warn("[IDDS Table] Container not found:", selectorOrElement);
|
|
@@ -3740,7 +4173,7 @@ var Table = class {
|
|
|
3740
4173
|
searchContainer: null,
|
|
3741
4174
|
searchButton: null,
|
|
3742
4175
|
onSearch: null,
|
|
3743
|
-
...
|
|
4176
|
+
...options
|
|
3744
4177
|
};
|
|
3745
4178
|
this.state = {
|
|
3746
4179
|
currentPage: this.options.initialPage,
|
|
@@ -3859,34 +4292,43 @@ var Table = class {
|
|
|
3859
4292
|
if (col.sortable && col.accessor) {
|
|
3860
4293
|
th.classList.add(`${PREFIX}-table__header-cell--sortable`);
|
|
3861
4294
|
th.setAttribute("data-sort", col.accessor);
|
|
4295
|
+
let sortLabel = `Urutkan ${col.header}`;
|
|
4296
|
+
let currentSort = "none";
|
|
4297
|
+
if (this.state.sortField === field) {
|
|
4298
|
+
currentSort = this.state.sortOrder === "asc" ? "ascending" : "descending";
|
|
4299
|
+
}
|
|
4300
|
+
th.setAttribute("aria-sort", currentSort);
|
|
3862
4301
|
let sortControlsHtml = `
|
|
3863
4302
|
<div class="${PREFIX}-table__sort-controls">
|
|
3864
4303
|
${col.header}
|
|
3865
4304
|
<div class="${PREFIX}-table__sort-icon">
|
|
3866
|
-
<div class="${PREFIX}-table__sort-button" data-order="asc">
|
|
4305
|
+
<div class="${PREFIX}-table__sort-button" data-order="asc" role="button" aria-label="Urutkan ${col.header} menaik">
|
|
3867
4306
|
<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>
|
|
3868
4307
|
</div>
|
|
3869
|
-
<div class="${PREFIX}-table__sort-button ${PREFIX}-table__sort-button-right" data-order="desc">
|
|
4308
|
+
<div class="${PREFIX}-table__sort-button ${PREFIX}-table__sort-button-right" data-order="desc" role="button" aria-label="Urutkan ${col.header} menurun">
|
|
3870
4309
|
<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>
|
|
3871
4310
|
</div>
|
|
3872
4311
|
</div>
|
|
3873
4312
|
</div>
|
|
3874
4313
|
`;
|
|
3875
4314
|
th.innerHTML = sortControlsHtml;
|
|
4315
|
+
const ascBtn = th.querySelector('[data-order="asc"]');
|
|
4316
|
+
const descBtn = th.querySelector('[data-order="desc"]');
|
|
4317
|
+
ascBtn.addEventListener("click", (e) => {
|
|
4318
|
+
e.stopPropagation();
|
|
4319
|
+
this.handleHeaderSort(col, "asc");
|
|
4320
|
+
});
|
|
4321
|
+
descBtn.addEventListener("click", (e) => {
|
|
4322
|
+
e.stopPropagation();
|
|
4323
|
+
this.handleHeaderSort(col, "desc");
|
|
4324
|
+
});
|
|
3876
4325
|
th.addEventListener("click", () => {
|
|
3877
|
-
|
|
4326
|
+
let nextOrder = "asc";
|
|
3878
4327
|
if (this.state.sortField === field) {
|
|
3879
|
-
if (this.state.sortOrder === "asc")
|
|
3880
|
-
else
|
|
3881
|
-
this.state.sortField = null;
|
|
3882
|
-
this.state.sortOrder = null;
|
|
3883
|
-
}
|
|
3884
|
-
} else {
|
|
3885
|
-
this.state.sortField = field;
|
|
3886
|
-
this.state.sortOrder = "asc";
|
|
4328
|
+
if (this.state.sortOrder === "asc") nextOrder = "desc";
|
|
4329
|
+
else nextOrder = null;
|
|
3887
4330
|
}
|
|
3888
|
-
this.
|
|
3889
|
-
this.loadData();
|
|
4331
|
+
this.handleHeaderSort(col, nextOrder);
|
|
3890
4332
|
});
|
|
3891
4333
|
} else {
|
|
3892
4334
|
th.textContent = col.header;
|
|
@@ -3945,7 +4387,7 @@ var Table = class {
|
|
|
3945
4387
|
this.updateSelectAllState();
|
|
3946
4388
|
return;
|
|
3947
4389
|
}
|
|
3948
|
-
rowData.forEach((row,
|
|
4390
|
+
rowData.forEach((row, index) => {
|
|
3949
4391
|
const tr = document.createElement("tr");
|
|
3950
4392
|
tr.className = `${PREFIX}-table__row`;
|
|
3951
4393
|
if (this.options.rowClickable) {
|
|
@@ -3956,11 +4398,11 @@ var Table = class {
|
|
|
3956
4398
|
return;
|
|
3957
4399
|
}
|
|
3958
4400
|
if (typeof this.options.onRowClick === "function") {
|
|
3959
|
-
this.options.onRowClick(row,
|
|
4401
|
+
this.options.onRowClick(row, index);
|
|
3960
4402
|
}
|
|
3961
4403
|
});
|
|
3962
4404
|
}
|
|
3963
|
-
const rowKeyStr = String(row[this.options.rowKey] ||
|
|
4405
|
+
const rowKeyStr = String(row[this.options.rowKey] || index);
|
|
3964
4406
|
if (this.options.selectable) {
|
|
3965
4407
|
const td = document.createElement("td");
|
|
3966
4408
|
td.className = `${PREFIX}-table__cell`;
|
|
@@ -3986,7 +4428,7 @@ var Table = class {
|
|
|
3986
4428
|
const td = document.createElement("td");
|
|
3987
4429
|
td.className = `${PREFIX}-table__cell`;
|
|
3988
4430
|
if (typeof col.render === "function") {
|
|
3989
|
-
const content = col.render(row,
|
|
4431
|
+
const content = col.render(row, index);
|
|
3990
4432
|
if (typeof content === "string") {
|
|
3991
4433
|
td.innerHTML = content;
|
|
3992
4434
|
} else if (content instanceof HTMLElement) {
|
|
@@ -4132,6 +4574,13 @@ var Table = class {
|
|
|
4132
4574
|
}
|
|
4133
4575
|
);
|
|
4134
4576
|
}
|
|
4577
|
+
handleHeaderSort(col, order) {
|
|
4578
|
+
const field2 = col.accessor;
|
|
4579
|
+
this.state.sortField = field2 ? order === null ? null : field2 : null;
|
|
4580
|
+
this.state.sortOrder = order;
|
|
4581
|
+
this.state.currentPage = 1;
|
|
4582
|
+
this.loadData();
|
|
4583
|
+
}
|
|
4135
4584
|
updateSortIndicators() {
|
|
4136
4585
|
const btns = this.elements.theadTr.querySelectorAll(
|
|
4137
4586
|
`.${PREFIX}-table__sort-button`
|
|
@@ -4139,10 +4588,15 @@ var Table = class {
|
|
|
4139
4588
|
btns.forEach((btn) => {
|
|
4140
4589
|
const th = btn.closest("th");
|
|
4141
4590
|
if (!th) return;
|
|
4142
|
-
const
|
|
4591
|
+
const field2 = th.getAttribute("data-sort");
|
|
4143
4592
|
const order = btn.getAttribute("data-order");
|
|
4144
|
-
const active = this.state.sortField ===
|
|
4593
|
+
const active = this.state.sortField === field2 && this.state.sortOrder === order;
|
|
4145
4594
|
btn.classList.toggle(`${PREFIX}-table__sort-button--active`, active);
|
|
4595
|
+
let currentSort = "none";
|
|
4596
|
+
if (this.state.sortField === field2) {
|
|
4597
|
+
currentSort = this.state.sortOrder === "asc" ? "ascending" : "descending";
|
|
4598
|
+
}
|
|
4599
|
+
th.setAttribute("aria-sort", currentSort);
|
|
4146
4600
|
});
|
|
4147
4601
|
}
|
|
4148
4602
|
async loadData() {
|
|
@@ -4220,8 +4674,8 @@ var Table = class {
|
|
|
4220
4674
|
this.triggerSelectionChange();
|
|
4221
4675
|
}
|
|
4222
4676
|
toggleAllSelection(checked) {
|
|
4223
|
-
this.state.currentData.forEach((row,
|
|
4224
|
-
const keyStr = String(row[this.options.rowKey] ||
|
|
4677
|
+
this.state.currentData.forEach((row, index) => {
|
|
4678
|
+
const keyStr = String(row[this.options.rowKey] || index);
|
|
4225
4679
|
if (checked) {
|
|
4226
4680
|
this.state.selectedKeys.add(keyStr);
|
|
4227
4681
|
this.state.selectedRows.set(keyStr, row);
|
|
@@ -4302,11 +4756,11 @@ var Table = class {
|
|
|
4302
4756
|
};
|
|
4303
4757
|
}
|
|
4304
4758
|
};
|
|
4305
|
-
function initTable(selectorOrElement,
|
|
4759
|
+
function initTable(selectorOrElement, options = {}) {
|
|
4306
4760
|
const elements = typeof selectorOrElement === "string" ? document.querySelectorAll(selectorOrElement) : selectorOrElement ? typeof selectorOrElement.length !== "undefined" ? selectorOrElement : [selectorOrElement] : document.querySelectorAll(`.${PREFIX}-table`);
|
|
4307
4761
|
const instances = [];
|
|
4308
4762
|
elements.forEach((container) => {
|
|
4309
|
-
const instance = new Table(container,
|
|
4763
|
+
const instance = new Table(container, options);
|
|
4310
4764
|
container.__tableAPI = instance;
|
|
4311
4765
|
instances.push(instance);
|
|
4312
4766
|
});
|
|
@@ -4340,17 +4794,17 @@ function initMonthPicker(rootSelector = `.${PREFIX}-month-picker`) {
|
|
|
4340
4794
|
const trigger = container.querySelector(`.${PREFIX}-month-picker__trigger`);
|
|
4341
4795
|
const panel = container.querySelector(`.${PREFIX}-month-picker__panel`);
|
|
4342
4796
|
const grid = container.querySelector(`.${PREFIX}-month-picker__grid`);
|
|
4343
|
-
const
|
|
4797
|
+
const options = grid ? Array.from(
|
|
4344
4798
|
grid.querySelectorAll(`.${PREFIX}-month-picker__month-option`)
|
|
4345
4799
|
) : [];
|
|
4346
|
-
if (!trigger || !panel || !grid ||
|
|
4800
|
+
if (!trigger || !panel || !grid || options.length === 0) return;
|
|
4347
4801
|
let isPickerOpen = false;
|
|
4348
4802
|
const updateText = () => {
|
|
4349
4803
|
const textEl = trigger.querySelector(
|
|
4350
4804
|
`.${PREFIX}-month-picker__trigger-text`
|
|
4351
4805
|
);
|
|
4352
4806
|
if (textEl) textEl.textContent = MONTHS_SHORT_ID[currentMonthIdx];
|
|
4353
|
-
|
|
4807
|
+
options.forEach((opt, idx) => {
|
|
4354
4808
|
if (idx === currentMonthIdx) {
|
|
4355
4809
|
opt.classList.add(`${PREFIX}-month-picker__month-option--selected`);
|
|
4356
4810
|
opt.setAttribute("aria-selected", "true");
|
|
@@ -4371,7 +4825,7 @@ function initMonthPicker(rootSelector = `.${PREFIX}-month-picker`) {
|
|
|
4371
4825
|
panel.classList.add(`${PREFIX}-month-picker__panel--open`);
|
|
4372
4826
|
trigger.setAttribute("aria-expanded", "true");
|
|
4373
4827
|
setTimeout(() => {
|
|
4374
|
-
const selectedOpt =
|
|
4828
|
+
const selectedOpt = options.find((o) => o.tabIndex === 0);
|
|
4375
4829
|
if (selectedOpt) selectedOpt.focus();
|
|
4376
4830
|
}, 0);
|
|
4377
4831
|
} else {
|
|
@@ -4395,7 +4849,7 @@ function initMonthPicker(rootSelector = `.${PREFIX}-month-picker`) {
|
|
|
4395
4849
|
document.addEventListener("click", (e) => {
|
|
4396
4850
|
if (!container.contains(e.target)) togglePicker(false);
|
|
4397
4851
|
});
|
|
4398
|
-
|
|
4852
|
+
options.forEach((btn, idx) => {
|
|
4399
4853
|
btn.setAttribute("role", "option");
|
|
4400
4854
|
btn.addEventListener("click", (e) => {
|
|
4401
4855
|
if (disabled || readonly) return;
|
|
@@ -4438,8 +4892,8 @@ function initMonthPicker(rootSelector = `.${PREFIX}-month-picker`) {
|
|
|
4438
4892
|
else if (e.key === "ArrowDown")
|
|
4439
4893
|
nextIndex += 3;
|
|
4440
4894
|
else if (e.key === "ArrowUp") nextIndex -= 3;
|
|
4441
|
-
if (
|
|
4442
|
-
|
|
4895
|
+
if (options[nextIndex]) {
|
|
4896
|
+
options[nextIndex].focus();
|
|
4443
4897
|
}
|
|
4444
4898
|
}
|
|
4445
4899
|
});
|
|
@@ -4540,12 +4994,12 @@ function initYearPicker(rootSelector = `.${PREFIX}-year-picker`) {
|
|
|
4540
4994
|
} else if (["ArrowRight", "ArrowLeft", "ArrowDown", "ArrowUp"].includes(e.key)) {
|
|
4541
4995
|
e.preventDefault();
|
|
4542
4996
|
e.stopPropagation();
|
|
4543
|
-
const
|
|
4997
|
+
const options = Array.from(
|
|
4544
4998
|
grid.querySelectorAll(
|
|
4545
4999
|
`.${PREFIX}-year-picker__year-option:not(:disabled)`
|
|
4546
5000
|
)
|
|
4547
5001
|
);
|
|
4548
|
-
const currentIndex =
|
|
5002
|
+
const currentIndex = options.indexOf(btn);
|
|
4549
5003
|
if (currentIndex === -1) return;
|
|
4550
5004
|
let nextIndex = currentIndex;
|
|
4551
5005
|
if (e.key === "ArrowRight") nextIndex += 1;
|
|
@@ -4553,8 +5007,8 @@ function initYearPicker(rootSelector = `.${PREFIX}-year-picker`) {
|
|
|
4553
5007
|
else if (e.key === "ArrowDown")
|
|
4554
5008
|
nextIndex += 4;
|
|
4555
5009
|
else if (e.key === "ArrowUp") nextIndex -= 4;
|
|
4556
|
-
if (
|
|
4557
|
-
|
|
5010
|
+
if (options[nextIndex]) {
|
|
5011
|
+
options[nextIndex].focus();
|
|
4558
5012
|
} else {
|
|
4559
5013
|
}
|
|
4560
5014
|
}
|
|
@@ -4681,7 +5135,7 @@ function createToastElement({ title, message, state, style, actionHtml }) {
|
|
|
4681
5135
|
return { toastItem, toast };
|
|
4682
5136
|
}
|
|
4683
5137
|
function showToast(optionsOrMessage, variant = "default", duration = 5e3) {
|
|
4684
|
-
const
|
|
5138
|
+
const options = typeof optionsOrMessage === "string" ? {
|
|
4685
5139
|
message: optionsOrMessage,
|
|
4686
5140
|
state: variant,
|
|
4687
5141
|
duration
|
|
@@ -4694,7 +5148,7 @@ function showToast(optionsOrMessage, variant = "default", duration = 5e3) {
|
|
|
4694
5148
|
duration: autoCloseDuration = 5e3,
|
|
4695
5149
|
position = "top-right",
|
|
4696
5150
|
actionHtml = ""
|
|
4697
|
-
} =
|
|
5151
|
+
} = options;
|
|
4698
5152
|
const container = getOrCreateContainer(position);
|
|
4699
5153
|
const { toastItem, toast } = createToastElement({
|
|
4700
5154
|
title,
|
|
@@ -4755,7 +5209,6 @@ function setBrandTheme(brandName) {
|
|
|
4755
5209
|
var PREFIX = "ina";
|
|
4756
5210
|
function initAll() {
|
|
4757
5211
|
initAccordion();
|
|
4758
|
-
initBanner();
|
|
4759
5212
|
initButtonGroup();
|
|
4760
5213
|
initCheckbox();
|
|
4761
5214
|
initDatepicker();
|
|
@@ -4776,6 +5229,7 @@ function initAll() {
|
|
|
4776
5229
|
initTab();
|
|
4777
5230
|
initToggle();
|
|
4778
5231
|
initPagination();
|
|
5232
|
+
initPhoneInput();
|
|
4779
5233
|
initChip();
|
|
4780
5234
|
initTabVertical();
|
|
4781
5235
|
initTabHorizontal();
|
|
@@ -4786,6 +5240,7 @@ function initAll() {
|
|
|
4786
5240
|
export {
|
|
4787
5241
|
DatePicker,
|
|
4788
5242
|
PREFIX,
|
|
5243
|
+
PhoneInput,
|
|
4789
5244
|
Table,
|
|
4790
5245
|
TimePicker,
|
|
4791
5246
|
initAll,
|