@idds/js 1.0.35 → 1.0.37
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 +371 -263
- package/dist/index.js +513 -239
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -108,11 +108,20 @@ function initAccordion(rootSelector = `.${PREFIX}-accordion`) {
|
|
|
108
108
|
|
|
109
109
|
// src/js/components/stateful/datepicker.js
|
|
110
110
|
function initDatepicker() {
|
|
111
|
-
document.querySelectorAll(
|
|
111
|
+
document.querySelectorAll(".ina-date-picker").forEach((datepicker) => {
|
|
112
|
+
const trigger = datepicker.querySelector(".ina-date-picker__trigger");
|
|
113
|
+
const triggerText = trigger.querySelector(".ina-date-picker__trigger-text");
|
|
114
|
+
const panel = datepicker.querySelector(".ina-date-picker__panel");
|
|
115
|
+
let panelContent = panel.querySelector(".ina-date-picker__panel-content");
|
|
116
|
+
if (!panelContent) {
|
|
117
|
+
panelContent = document.createElement("div");
|
|
118
|
+
panelContent.className = "ina-date-picker__panel-content";
|
|
119
|
+
panel.appendChild(panelContent);
|
|
120
|
+
}
|
|
112
121
|
let currentDate = /* @__PURE__ */ new Date();
|
|
113
|
-
let selectedDateTarget = null;
|
|
114
122
|
let selectedDate = null;
|
|
115
|
-
|
|
123
|
+
let isOpen = false;
|
|
124
|
+
const MONTHS_ID = [
|
|
116
125
|
"Januari",
|
|
117
126
|
"Februari",
|
|
118
127
|
"Maret",
|
|
@@ -126,267 +135,325 @@ function initDatepicker() {
|
|
|
126
135
|
"November",
|
|
127
136
|
"Desember"
|
|
128
137
|
];
|
|
129
|
-
const
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
)
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
)
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
)
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
const
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
138
|
+
const MONTHS_SHORT_ID = [
|
|
139
|
+
"Jan",
|
|
140
|
+
"Feb",
|
|
141
|
+
"Mar",
|
|
142
|
+
"Apr",
|
|
143
|
+
"Mei",
|
|
144
|
+
"Jun",
|
|
145
|
+
"Jul",
|
|
146
|
+
"Agu",
|
|
147
|
+
"Sep",
|
|
148
|
+
"Okt",
|
|
149
|
+
"Nov",
|
|
150
|
+
"Des"
|
|
151
|
+
];
|
|
152
|
+
const DAYS_SHORT = ["Min", "Sen", "Sel", "Rab", "Kam", "Jum", "Sab"];
|
|
153
|
+
function formatDate(date) {
|
|
154
|
+
const day = date.getDate().toString().padStart(2, "0");
|
|
155
|
+
const monthIndex = date.getMonth();
|
|
156
|
+
const year = date.getFullYear();
|
|
157
|
+
return `${day} ${MONTHS_SHORT_ID[monthIndex]} ${year}`;
|
|
158
|
+
}
|
|
159
|
+
function createIcon(name, size = 16) {
|
|
160
|
+
if (name === "chevron-left") {
|
|
161
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" width="${size}" height="${size}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-chevron-left"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M15 6l-6 6l6 6" /></svg>`;
|
|
162
|
+
}
|
|
163
|
+
if (name === "chevron-right") {
|
|
164
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" width="${size}" height="${size}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-chevron-right"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M9 6l6 6l-6 6" /></svg>`;
|
|
165
|
+
}
|
|
166
|
+
return "";
|
|
167
|
+
}
|
|
168
|
+
function createMonthPicker(initialMonth, onChange) {
|
|
169
|
+
const container = document.createElement("div");
|
|
170
|
+
container.className = "ina-month-picker";
|
|
171
|
+
let currentMonthIdx = initialMonth;
|
|
172
|
+
let isPickerOpen = false;
|
|
173
|
+
const pickerTrigger = document.createElement("button");
|
|
174
|
+
pickerTrigger.type = "button";
|
|
175
|
+
pickerTrigger.className = "ina-month-picker__trigger ina-month-picker__trigger--size-sm";
|
|
176
|
+
const updateTriggerText = () => {
|
|
177
|
+
pickerTrigger.innerHTML = `
|
|
178
|
+
<span class="ina-month-picker__trigger-text">${MONTHS_SHORT_ID[currentMonthIdx]}</span>
|
|
179
|
+
`;
|
|
180
|
+
};
|
|
181
|
+
updateTriggerText();
|
|
182
|
+
pickerTrigger.addEventListener("click", (e) => {
|
|
183
|
+
e.stopPropagation();
|
|
184
|
+
togglePicker(!isPickerOpen);
|
|
185
|
+
});
|
|
186
|
+
const pickerPanel = document.createElement("div");
|
|
187
|
+
pickerPanel.className = "ina-month-picker__panel";
|
|
188
|
+
const grid = document.createElement("div");
|
|
189
|
+
grid.className = "ina-month-picker__grid";
|
|
190
|
+
MONTHS_SHORT_ID.forEach((m, idx) => {
|
|
191
|
+
const btn = document.createElement("button");
|
|
192
|
+
btn.type = "button";
|
|
193
|
+
btn.className = "ina-month-picker__month-option";
|
|
194
|
+
if (idx === currentMonthIdx)
|
|
195
|
+
btn.classList.add("ina-month-picker__month-option--selected");
|
|
196
|
+
btn.textContent = m;
|
|
197
|
+
btn.addEventListener("click", (e) => {
|
|
198
|
+
e.stopPropagation();
|
|
199
|
+
currentMonthIdx = idx;
|
|
200
|
+
updateTriggerText();
|
|
201
|
+
grid.querySelectorAll(".ina-month-picker__month-option").forEach((b, i) => {
|
|
202
|
+
if (i === idx)
|
|
203
|
+
b.classList.add("ina-month-picker__month-option--selected");
|
|
204
|
+
else
|
|
205
|
+
b.classList.remove("ina-month-picker__month-option--selected");
|
|
206
|
+
});
|
|
207
|
+
togglePicker(false);
|
|
208
|
+
onChange(idx);
|
|
209
|
+
});
|
|
210
|
+
grid.appendChild(btn);
|
|
211
|
+
});
|
|
212
|
+
pickerPanel.appendChild(grid);
|
|
213
|
+
container.appendChild(pickerTrigger);
|
|
214
|
+
container.appendChild(pickerPanel);
|
|
215
|
+
function togglePicker(show) {
|
|
216
|
+
isPickerOpen = show;
|
|
217
|
+
if (show) {
|
|
218
|
+
pickerPanel.classList.add("ina-month-picker__panel--open");
|
|
219
|
+
pickerTrigger.setAttribute("aria-expanded", "true");
|
|
220
|
+
} else {
|
|
221
|
+
pickerPanel.classList.remove("ina-month-picker__panel--open");
|
|
222
|
+
pickerTrigger.setAttribute("aria-expanded", "false");
|
|
188
223
|
}
|
|
189
|
-
datepickerYearContent.appendChild(yearEl);
|
|
190
224
|
}
|
|
225
|
+
document.addEventListener("click", (e) => {
|
|
226
|
+
if (!container.contains(e.target)) togglePicker(false);
|
|
227
|
+
});
|
|
228
|
+
return {
|
|
229
|
+
element: container,
|
|
230
|
+
setMonth: (m) => {
|
|
231
|
+
currentMonthIdx = m;
|
|
232
|
+
updateTriggerText();
|
|
233
|
+
grid.querySelectorAll(".ina-month-picker__month-option").forEach((b, i) => {
|
|
234
|
+
if (i === m)
|
|
235
|
+
b.classList.add("ina-month-picker__month-option--selected");
|
|
236
|
+
else
|
|
237
|
+
b.classList.remove("ina-month-picker__month-option--selected");
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
};
|
|
191
241
|
}
|
|
192
|
-
function
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
242
|
+
function createYearPicker(initialYear, onChange) {
|
|
243
|
+
const container = document.createElement("div");
|
|
244
|
+
container.className = "ina-year-picker";
|
|
245
|
+
let currentYearVal = initialYear;
|
|
246
|
+
let isPickerOpen = false;
|
|
247
|
+
let decadeStart = Math.floor(initialYear / 20) * 20;
|
|
248
|
+
const pickerTrigger = document.createElement("button");
|
|
249
|
+
pickerTrigger.type = "button";
|
|
250
|
+
pickerTrigger.className = "ina-year-picker__trigger ina-year-picker__trigger--size-sm";
|
|
251
|
+
const updateTriggerText = () => {
|
|
252
|
+
pickerTrigger.innerHTML = `
|
|
253
|
+
<span class="ina-year-picker__trigger-text">${currentYearVal}</span>
|
|
254
|
+
`;
|
|
255
|
+
};
|
|
256
|
+
updateTriggerText();
|
|
257
|
+
pickerTrigger.addEventListener("click", (e) => {
|
|
258
|
+
e.stopPropagation();
|
|
259
|
+
togglePicker(!isPickerOpen);
|
|
260
|
+
});
|
|
261
|
+
const pickerPanel = document.createElement("div");
|
|
262
|
+
pickerPanel.className = "ina-year-picker__panel";
|
|
263
|
+
const header = document.createElement("div");
|
|
264
|
+
header.className = "ina-year-picker__header";
|
|
265
|
+
const prevBtn = document.createElement("button");
|
|
266
|
+
prevBtn.type = "button";
|
|
267
|
+
prevBtn.className = "ina-year-picker__nav-button";
|
|
268
|
+
prevBtn.innerHTML = createIcon("chevron-left");
|
|
269
|
+
prevBtn.onclick = (e) => {
|
|
270
|
+
e.stopPropagation();
|
|
271
|
+
decadeStart -= 20;
|
|
272
|
+
renderGrid();
|
|
273
|
+
};
|
|
274
|
+
const nextBtn = document.createElement("button");
|
|
275
|
+
nextBtn.type = "button";
|
|
276
|
+
nextBtn.className = "ina-year-picker__nav-button";
|
|
277
|
+
nextBtn.innerHTML = createIcon("chevron-right");
|
|
278
|
+
nextBtn.onclick = (e) => {
|
|
279
|
+
e.stopPropagation();
|
|
280
|
+
decadeStart += 20;
|
|
281
|
+
renderGrid();
|
|
282
|
+
};
|
|
283
|
+
const rangeText = document.createElement("span");
|
|
284
|
+
rangeText.className = "ina-year-picker__decade-range";
|
|
285
|
+
header.append(prevBtn, rangeText, nextBtn);
|
|
286
|
+
const grid = document.createElement("div");
|
|
287
|
+
grid.className = "ina-year-picker__grid";
|
|
288
|
+
function renderGrid() {
|
|
289
|
+
grid.innerHTML = "";
|
|
290
|
+
rangeText.textContent = `${decadeStart} - ${decadeStart + 19}`;
|
|
291
|
+
for (let y = decadeStart; y < decadeStart + 20; y++) {
|
|
292
|
+
const btn = document.createElement("button");
|
|
293
|
+
btn.type = "button";
|
|
294
|
+
btn.className = "ina-year-picker__year-option";
|
|
295
|
+
if (y === currentYearVal)
|
|
296
|
+
btn.classList.add("ina-year-picker__year-option--selected");
|
|
297
|
+
btn.textContent = y;
|
|
298
|
+
btn.addEventListener("click", (e) => {
|
|
299
|
+
e.stopPropagation();
|
|
300
|
+
currentYearVal = y;
|
|
301
|
+
updateTriggerText();
|
|
302
|
+
togglePicker(false);
|
|
303
|
+
onChange(y);
|
|
304
|
+
});
|
|
305
|
+
grid.appendChild(btn);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
pickerPanel.append(header, grid);
|
|
309
|
+
container.append(pickerTrigger, pickerPanel);
|
|
310
|
+
function togglePicker(show) {
|
|
311
|
+
isPickerOpen = show;
|
|
312
|
+
if (show) {
|
|
313
|
+
decadeStart = Math.floor(currentYearVal / 20) * 20;
|
|
314
|
+
renderGrid();
|
|
315
|
+
pickerPanel.classList.add("ina-year-picker__panel--open");
|
|
316
|
+
pickerTrigger.setAttribute("aria-expanded", "true");
|
|
317
|
+
} else {
|
|
318
|
+
pickerPanel.classList.remove("ina-year-picker__panel--open");
|
|
319
|
+
pickerTrigger.setAttribute("aria-expanded", "false");
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
document.addEventListener("click", (e) => {
|
|
323
|
+
if (!container.contains(e.target)) togglePicker(false);
|
|
324
|
+
});
|
|
325
|
+
return {
|
|
326
|
+
element: container,
|
|
327
|
+
setYear: (y) => {
|
|
328
|
+
currentYearVal = y;
|
|
329
|
+
updateTriggerText();
|
|
330
|
+
}
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
function renderCalendar() {
|
|
334
|
+
panelContent.innerHTML = "";
|
|
335
|
+
const year = currentDate.getFullYear();
|
|
336
|
+
const month = currentDate.getMonth();
|
|
337
|
+
const calendarContainer = document.createElement("div");
|
|
338
|
+
calendarContainer.className = "ina-date-picker__calendar-container";
|
|
339
|
+
const header = document.createElement("div");
|
|
340
|
+
header.className = "ina-date-picker__calendar-header";
|
|
341
|
+
const prevBtn = document.createElement("button");
|
|
342
|
+
prevBtn.className = "ina-date-picker__nav-button";
|
|
343
|
+
prevBtn.type = "button";
|
|
344
|
+
prevBtn.innerHTML = createIcon("chevron-left", 20);
|
|
345
|
+
prevBtn.addEventListener("click", (e) => {
|
|
346
|
+
e.stopPropagation();
|
|
347
|
+
currentDate.setMonth(month - 1);
|
|
348
|
+
renderCalendar();
|
|
349
|
+
});
|
|
350
|
+
const nextBtn = document.createElement("button");
|
|
351
|
+
nextBtn.className = "ina-date-picker__nav-button";
|
|
352
|
+
nextBtn.type = "button";
|
|
353
|
+
nextBtn.innerHTML = createIcon("chevron-right", 20);
|
|
354
|
+
nextBtn.addEventListener("click", (e) => {
|
|
355
|
+
e.stopPropagation();
|
|
356
|
+
currentDate.setMonth(month + 1);
|
|
357
|
+
renderCalendar();
|
|
358
|
+
});
|
|
359
|
+
const controls = document.createElement("div");
|
|
360
|
+
controls.className = "ina-date-picker__header-controls";
|
|
361
|
+
const monthContainer = document.createElement("div");
|
|
362
|
+
monthContainer.className = "ina-date-picker__dropdown-container";
|
|
363
|
+
const monthPicker = createMonthPicker(month, (newMonth) => {
|
|
364
|
+
currentDate.setMonth(newMonth);
|
|
365
|
+
renderCalendar();
|
|
366
|
+
});
|
|
367
|
+
monthContainer.appendChild(monthPicker.element);
|
|
368
|
+
const yearContainer = document.createElement("div");
|
|
369
|
+
yearContainer.className = "ina-date-picker__dropdown-container";
|
|
370
|
+
const yearPicker = createYearPicker(year, (newYear) => {
|
|
371
|
+
currentDate.setFullYear(newYear);
|
|
372
|
+
renderCalendar();
|
|
373
|
+
});
|
|
374
|
+
yearContainer.appendChild(yearPicker.element);
|
|
375
|
+
controls.append(monthContainer, yearContainer);
|
|
376
|
+
header.append(prevBtn, controls, nextBtn);
|
|
377
|
+
const grid = document.createElement("div");
|
|
378
|
+
grid.className = "ina-date-picker__calendar-grid";
|
|
379
|
+
DAYS_SHORT.forEach((day) => {
|
|
380
|
+
const dh = document.createElement("div");
|
|
381
|
+
dh.className = "ina-date-picker__day-header";
|
|
382
|
+
dh.textContent = day;
|
|
383
|
+
grid.appendChild(dh);
|
|
204
384
|
});
|
|
205
385
|
const firstDayOfMonth = new Date(year, month, 1).getDay();
|
|
206
386
|
const daysInMonth = new Date(year, month + 1, 0).getDate();
|
|
207
387
|
const daysInPrevMonth = new Date(year, month, 0).getDate();
|
|
208
|
-
for (let i =
|
|
209
|
-
const
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
388
|
+
for (let i = firstDayOfMonth - 1; i >= 0; i--) {
|
|
389
|
+
const dayBtn = document.createElement("button");
|
|
390
|
+
dayBtn.type = "button";
|
|
391
|
+
dayBtn.className = "ina-date-picker__day ina-date-picker__day--other-month ina-date-picker__day--disabled";
|
|
392
|
+
dayBtn.textContent = daysInPrevMonth - i;
|
|
393
|
+
grid.appendChild(dayBtn);
|
|
214
394
|
}
|
|
215
395
|
const today = /* @__PURE__ */ new Date();
|
|
216
396
|
for (let i = 1; i <= daysInMonth; i++) {
|
|
217
|
-
const
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
dayEl.appendChild(marker);
|
|
226
|
-
dayEl.classList.add("today");
|
|
397
|
+
const dayBtn = document.createElement("button");
|
|
398
|
+
dayBtn.type = "button";
|
|
399
|
+
dayBtn.className = "ina-date-picker__day";
|
|
400
|
+
dayBtn.textContent = i;
|
|
401
|
+
let isSelected = false;
|
|
402
|
+
if (selectedDate && selectedDate.getDate() === i && selectedDate.getMonth() === month && selectedDate.getFullYear() === year) {
|
|
403
|
+
dayBtn.classList.add("ina-date-picker__day--selected");
|
|
404
|
+
isSelected = true;
|
|
227
405
|
}
|
|
228
|
-
if (
|
|
229
|
-
|
|
406
|
+
if (today.getDate() === i && today.getMonth() === month && today.getFullYear() === year) {
|
|
407
|
+
dayBtn.classList.add("ina-date-picker__day--today");
|
|
230
408
|
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
const totalCells = 42;
|
|
234
|
-
const cellsRendered = firstDayOfMonth + daysInMonth;
|
|
235
|
-
const remainingCells = totalCells - cellsRendered;
|
|
236
|
-
for (let i = 1; i <= remainingCells; i++) {
|
|
237
|
-
const dayEl = document.createElement("button");
|
|
238
|
-
dayEl.className = `${PREFIX}-datepicker__calendar-day outside-month`;
|
|
239
|
-
dayEl.textContent = i;
|
|
240
|
-
dayEl.disabled = true;
|
|
241
|
-
datepickerContent.appendChild(dayEl);
|
|
242
|
-
}
|
|
243
|
-
datepickerMonthPopover.innerHTML = "";
|
|
244
|
-
MONTHS.forEach((monthName, index) => {
|
|
245
|
-
const monthEl = document.createElement("button");
|
|
246
|
-
monthEl.className = `${PREFIX}-datepicker__month-item`;
|
|
247
|
-
monthEl.textContent = monthName.substring(0, 3);
|
|
248
|
-
monthEl.dataset.month = index;
|
|
249
|
-
if (index === month) {
|
|
250
|
-
monthEl.classList.add("selected");
|
|
409
|
+
if (!isSelected) {
|
|
410
|
+
dayBtn.classList.add("ina-date-picker__day--hover");
|
|
251
411
|
}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
datepickerYearContent.appendChild(yearEl);
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
function togglePopover() {
|
|
270
|
-
if (datepickerPopover.style.display === "none" || datepickerPopover.style.display === "") {
|
|
271
|
-
datepickerPopover.style.display = "block";
|
|
272
|
-
renderCalendar(currentDate.getFullYear(), currentDate.getMonth());
|
|
273
|
-
} else {
|
|
274
|
-
datepickerPopover.style.display = "none";
|
|
412
|
+
dayBtn.addEventListener("click", (e) => {
|
|
413
|
+
e.stopPropagation();
|
|
414
|
+
selectedDate = new Date(year, month, i);
|
|
415
|
+
triggerText.textContent = formatDate(selectedDate);
|
|
416
|
+
triggerText.classList.add("ina-date-picker__trigger-text--value");
|
|
417
|
+
triggerText.classList.remove(
|
|
418
|
+
"ina-date-picker__trigger-text--placeholder"
|
|
419
|
+
);
|
|
420
|
+
datepicker.dispatchEvent(
|
|
421
|
+
new CustomEvent("date:changed", { detail: { selectedDate } })
|
|
422
|
+
);
|
|
423
|
+
toggle(false);
|
|
424
|
+
});
|
|
425
|
+
grid.appendChild(dayBtn);
|
|
275
426
|
}
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
427
|
+
const currentCells = grid.children.length - 7;
|
|
428
|
+
const remaining = 42 - currentCells;
|
|
429
|
+
for (let i = 1; i <= remaining; i++) {
|
|
430
|
+
const dayBtn = document.createElement("button");
|
|
431
|
+
dayBtn.type = "button";
|
|
432
|
+
dayBtn.className = "ina-date-picker__day ina-date-picker__day--other-month ina-date-picker__day--disabled";
|
|
433
|
+
dayBtn.textContent = i;
|
|
434
|
+
grid.appendChild(dayBtn);
|
|
282
435
|
}
|
|
436
|
+
calendarContainer.append(header, grid);
|
|
437
|
+
panelContent.appendChild(calendarContainer);
|
|
283
438
|
}
|
|
284
|
-
function
|
|
285
|
-
|
|
286
|
-
|
|
439
|
+
function toggle(show) {
|
|
440
|
+
isOpen = show;
|
|
441
|
+
if (show) {
|
|
442
|
+
panel.classList.add("ina-date-picker__panel--open");
|
|
443
|
+
renderCalendar();
|
|
287
444
|
} else {
|
|
288
|
-
|
|
445
|
+
panel.classList.remove("ina-date-picker__panel--open");
|
|
289
446
|
}
|
|
290
447
|
}
|
|
291
|
-
|
|
448
|
+
trigger.addEventListener("click", (e) => {
|
|
292
449
|
e.stopPropagation();
|
|
293
|
-
|
|
294
|
-
});
|
|
295
|
-
prevMonthButton.addEventListener("click", () => {
|
|
296
|
-
currentDate.setMonth(currentDate.getMonth() - 1);
|
|
297
|
-
renderCalendar(currentDate.getFullYear(), currentDate.getMonth());
|
|
298
|
-
});
|
|
299
|
-
nextMonthButton.addEventListener("click", () => {
|
|
300
|
-
currentDate.setMonth(currentDate.getMonth() + 1);
|
|
301
|
-
renderCalendar(currentDate.getFullYear(), currentDate.getMonth());
|
|
302
|
-
});
|
|
303
|
-
datepickerMonthTrigger.addEventListener("click", (e) => {
|
|
304
|
-
e.stopPropagation();
|
|
305
|
-
toggleMonthPopover();
|
|
306
|
-
});
|
|
307
|
-
datepickerYearTrigger.addEventListener("click", (e) => {
|
|
308
|
-
e.stopPropagation();
|
|
309
|
-
toggleYearPopover();
|
|
310
|
-
});
|
|
311
|
-
document.addEventListener("click", (e) => {
|
|
312
|
-
if (!datepickerPopover.contains(e.target) && e.target !== datepickerTrigger && !datepickerTrigger.contains(e.target)) {
|
|
313
|
-
datepickerPopover.style.display = "none";
|
|
314
|
-
}
|
|
315
|
-
});
|
|
316
|
-
document.addEventListener("click", (e) => {
|
|
317
|
-
if (!datepickerMonthPopover.contains(e.target) && e.target !== datepickerMonthTrigger && !datepickerMonthTrigger.contains(e.target)) {
|
|
318
|
-
datepickerMonthPopover.style.display = "none";
|
|
319
|
-
}
|
|
450
|
+
toggle(!isOpen);
|
|
320
451
|
});
|
|
321
452
|
document.addEventListener("click", (e) => {
|
|
322
|
-
if (!
|
|
323
|
-
datepickerYearPopover.style.display = "none";
|
|
324
|
-
}
|
|
325
|
-
});
|
|
326
|
-
datepickerMonthPopover.addEventListener("click", (e) => {
|
|
327
|
-
e.stopPropagation();
|
|
328
|
-
const target = e.target;
|
|
329
|
-
if (target.classList.contains(`${PREFIX}-datepicker__month-item`)) {
|
|
330
|
-
const monthIndex = parseInt(target.dataset.month);
|
|
331
|
-
currentDate.setMonth(monthIndex);
|
|
332
|
-
renderCalendar(currentDate.getFullYear(), currentDate.getMonth());
|
|
333
|
-
datepickerMonthPopover.style.display = "none";
|
|
334
|
-
}
|
|
335
|
-
});
|
|
336
|
-
datepickerYearPopover.addEventListener("click", (e) => {
|
|
337
|
-
e.stopPropagation();
|
|
338
|
-
const target = e.target;
|
|
339
|
-
if (target.classList.contains(`${PREFIX}-datepicker__year-nav-prev`)) {
|
|
340
|
-
const currentYearRange = datepickerYearCurrent.textContent.split(" - ").map((y) => parseInt(y));
|
|
341
|
-
const newStartYear = currentYearRange[0] - 20;
|
|
342
|
-
const newEndYear = currentYearRange[1] - 20;
|
|
343
|
-
renderYear(newStartYear, newEndYear);
|
|
344
|
-
} else if (target.classList.contains(`${PREFIX}-datepicker__year-nav-next`)) {
|
|
345
|
-
const currentYearRange = datepickerYearCurrent.textContent.split(" - ").map((y) => parseInt(y));
|
|
346
|
-
const newStartYear = currentYearRange[0] + 20;
|
|
347
|
-
const newEndYear = currentYearRange[1] + 20;
|
|
348
|
-
renderYear(newStartYear, newEndYear);
|
|
349
|
-
}
|
|
350
|
-
});
|
|
351
|
-
datepickerYearContent.addEventListener("click", (e) => {
|
|
352
|
-
e.stopPropagation();
|
|
353
|
-
const target = e.target;
|
|
354
|
-
if (target.classList.contains(`${PREFIX}-datepicker__year-item`)) {
|
|
355
|
-
const yearValue = parseInt(target.dataset.year);
|
|
356
|
-
currentDate.setFullYear(yearValue);
|
|
357
|
-
renderCalendar(currentDate.getFullYear(), currentDate.getMonth());
|
|
358
|
-
datepickerYearPopover.style.display = "none";
|
|
359
|
-
}
|
|
360
|
-
});
|
|
361
|
-
datepickerContent.addEventListener("click", (e) => {
|
|
362
|
-
const target = e.target;
|
|
363
|
-
if (target.classList.contains(`${PREFIX}-datepicker__calendar-day`) && !target.classList.contains("outside-month")) {
|
|
364
|
-
if (target.classList.contains("selected")) {
|
|
365
|
-
target.classList.remove("selected");
|
|
366
|
-
selectedDateTarget = null;
|
|
367
|
-
} else {
|
|
368
|
-
const selectedDateEl = datepickerContent.querySelector(
|
|
369
|
-
`.${PREFIX}-datepicker__calendar-day.selected`
|
|
370
|
-
);
|
|
371
|
-
selectedDateEl?.classList.remove("selected");
|
|
372
|
-
target.classList.add("selected");
|
|
373
|
-
selectedDateTarget = target;
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
});
|
|
377
|
-
datepickerSubmitButton.addEventListener("click", () => {
|
|
378
|
-
selectedDate = selectedDateTarget ? new Date(selectedDateTarget.dataset.date) : null;
|
|
379
|
-
currentDate = selectedDate ? new Date(selectedDate) : /* @__PURE__ */ new Date();
|
|
380
|
-
datepicker.dispatchEvent(
|
|
381
|
-
new CustomEvent("date:changed", { detail: { selectedDate } })
|
|
382
|
-
);
|
|
383
|
-
datepickerPopover.style.display = "none";
|
|
453
|
+
if (!datepicker.contains(e.target)) toggle(false);
|
|
384
454
|
});
|
|
385
|
-
renderCalendar(currentDate.getFullYear(), currentDate.getMonth());
|
|
386
455
|
});
|
|
387
456
|
}
|
|
388
|
-
document.addEventListener("DOMContentLoaded", () => {
|
|
389
|
-
});
|
|
390
457
|
|
|
391
458
|
// src/js/components/stateless/modal.js
|
|
392
459
|
function initModal(rootSelector = `.${PREFIX}-modal`) {
|
|
@@ -1191,6 +1258,212 @@ if (typeof window !== void 0) {
|
|
|
1191
1258
|
});
|
|
1192
1259
|
}
|
|
1193
1260
|
|
|
1261
|
+
// src/js/components/stateful/timepicker.js
|
|
1262
|
+
function initTimepicker() {
|
|
1263
|
+
document.querySelectorAll(".ina-time-picker").forEach((picker) => {
|
|
1264
|
+
if (picker.dataset.initialized === "true") return;
|
|
1265
|
+
picker.dataset.initialized = "true";
|
|
1266
|
+
const input = picker.querySelector(".ina-time-picker__input");
|
|
1267
|
+
const wrapper = picker.querySelector(".ina-time-picker__wrapper");
|
|
1268
|
+
if (!input || !wrapper) return;
|
|
1269
|
+
const format = picker.dataset.format || "HH:mm";
|
|
1270
|
+
const use12Hours = picker.dataset.use12Hours === "true";
|
|
1271
|
+
const showSecond = picker.dataset.showSecond === "true";
|
|
1272
|
+
const disabled = picker.classList.contains("ina-time-picker--disabled");
|
|
1273
|
+
const allowClear = picker.dataset.allowClear !== "false";
|
|
1274
|
+
let isOpen = false;
|
|
1275
|
+
let internalValue = input.value || "";
|
|
1276
|
+
let panel = picker.querySelector(".ina-time-picker__panel");
|
|
1277
|
+
if (!panel) {
|
|
1278
|
+
panel = document.createElement("div");
|
|
1279
|
+
panel.className = "ina-time-picker__panel";
|
|
1280
|
+
panel.style.display = "none";
|
|
1281
|
+
picker.appendChild(panel);
|
|
1282
|
+
}
|
|
1283
|
+
let content = panel.querySelector(".ina-time-picker__content");
|
|
1284
|
+
if (!content) {
|
|
1285
|
+
content = document.createElement("div");
|
|
1286
|
+
content.className = "ina-time-picker__content";
|
|
1287
|
+
panel.appendChild(content);
|
|
1288
|
+
} else {
|
|
1289
|
+
content.innerHTML = "";
|
|
1290
|
+
}
|
|
1291
|
+
let actions = panel.querySelector(".ina-time-picker__actions");
|
|
1292
|
+
if (!actions) {
|
|
1293
|
+
actions = document.createElement("div");
|
|
1294
|
+
actions.className = "ina-time-picker__actions";
|
|
1295
|
+
const confirmBtn = document.createElement("button");
|
|
1296
|
+
confirmBtn.type = "button";
|
|
1297
|
+
confirmBtn.className = "ina-time-picker__confirm-button";
|
|
1298
|
+
confirmBtn.textContent = "Pilih";
|
|
1299
|
+
confirmBtn.onclick = (e) => {
|
|
1300
|
+
e.stopPropagation();
|
|
1301
|
+
close();
|
|
1302
|
+
};
|
|
1303
|
+
actions.appendChild(confirmBtn);
|
|
1304
|
+
panel.appendChild(actions);
|
|
1305
|
+
}
|
|
1306
|
+
const parseTime = (timeStr) => {
|
|
1307
|
+
if (!timeStr) return { hours: 0, minutes: 0, seconds: 0, period: "AM" };
|
|
1308
|
+
let hours = 0, minutes = 0, seconds = 0, period = "AM";
|
|
1309
|
+
try {
|
|
1310
|
+
if (use12Hours) {
|
|
1311
|
+
const [time, p] = timeStr.split(" ");
|
|
1312
|
+
const [h, m, s] = time.split(":");
|
|
1313
|
+
hours = parseInt(h || "0", 10);
|
|
1314
|
+
minutes = parseInt(m || "0", 10);
|
|
1315
|
+
seconds = parseInt(s || "0", 10);
|
|
1316
|
+
period = p || "AM";
|
|
1317
|
+
} else {
|
|
1318
|
+
const [h, m, s] = timeStr.split(":");
|
|
1319
|
+
hours = parseInt(h || "0", 10);
|
|
1320
|
+
minutes = parseInt(m || "0", 10);
|
|
1321
|
+
seconds = parseInt(s || "0", 10);
|
|
1322
|
+
}
|
|
1323
|
+
} catch (e) {
|
|
1324
|
+
console.warn("Invalid time format", timeStr);
|
|
1325
|
+
}
|
|
1326
|
+
return { hours, minutes, seconds, period };
|
|
1327
|
+
};
|
|
1328
|
+
const formatTime = (h, m, s, p) => {
|
|
1329
|
+
const pad = (n) => n.toString().padStart(2, "0");
|
|
1330
|
+
if (use12Hours) {
|
|
1331
|
+
let displayHours = h;
|
|
1332
|
+
if (displayHours === 0) displayHours = 12;
|
|
1333
|
+
const main = `${pad(displayHours)}:${pad(m)}`;
|
|
1334
|
+
const sec = showSecond ? `:${pad(s)}` : "";
|
|
1335
|
+
return `${main}${sec} ${p}`;
|
|
1336
|
+
} else {
|
|
1337
|
+
const main = `${pad(h)}:${pad(m)}`;
|
|
1338
|
+
const sec = showSecond ? `:${pad(s)}` : "";
|
|
1339
|
+
return `${main}${sec}`;
|
|
1340
|
+
}
|
|
1341
|
+
};
|
|
1342
|
+
let currentTime = parseTime(internalValue);
|
|
1343
|
+
const renderColumn = (type, max) => {
|
|
1344
|
+
const column = document.createElement("div");
|
|
1345
|
+
column.className = `ina-time-picker__column ina-time-picker__column--${type}`;
|
|
1346
|
+
const colContent = document.createElement("div");
|
|
1347
|
+
colContent.className = "ina-time-picker__column-content";
|
|
1348
|
+
column.appendChild(colContent);
|
|
1349
|
+
const start = type === "hour" && use12Hours ? 1 : 0;
|
|
1350
|
+
const end = type === "hour" && use12Hours ? 12 : max - 1;
|
|
1351
|
+
for (let i = start; i <= end; i++) {
|
|
1352
|
+
const option = document.createElement("div");
|
|
1353
|
+
option.className = "ina-time-picker__option";
|
|
1354
|
+
option.textContent = i.toString().padStart(2, "0");
|
|
1355
|
+
option.dataset.value = i;
|
|
1356
|
+
let isSelected = false;
|
|
1357
|
+
if (type === "hour") {
|
|
1358
|
+
isSelected = currentTime.hours === i || use12Hours && currentTime.hours === 0 && i === 12;
|
|
1359
|
+
} else if (type === "minute") isSelected = currentTime.minutes === i;
|
|
1360
|
+
else if (type === "second") isSelected = currentTime.seconds === i;
|
|
1361
|
+
if (isSelected)
|
|
1362
|
+
option.classList.add("ina-time-picker__option--selected");
|
|
1363
|
+
option.addEventListener("click", (e) => {
|
|
1364
|
+
e.stopPropagation();
|
|
1365
|
+
const val = parseInt(option.dataset.value, 10);
|
|
1366
|
+
if (type === "hour")
|
|
1367
|
+
currentTime.hours = use12Hours && val === 12 ? 0 : val;
|
|
1368
|
+
if (type === "hour") currentTime.hours = val;
|
|
1369
|
+
if (type === "minute") currentTime.minutes = val;
|
|
1370
|
+
if (type === "second") currentTime.seconds = val;
|
|
1371
|
+
updateInput();
|
|
1372
|
+
colContent.querySelectorAll(".ina-time-picker__option").forEach(
|
|
1373
|
+
(el) => el.classList.remove("ina-time-picker__option--selected")
|
|
1374
|
+
);
|
|
1375
|
+
option.classList.add("ina-time-picker__option--selected");
|
|
1376
|
+
});
|
|
1377
|
+
colContent.appendChild(option);
|
|
1378
|
+
}
|
|
1379
|
+
return column;
|
|
1380
|
+
};
|
|
1381
|
+
const renderPeriodColumn = () => {
|
|
1382
|
+
const column = document.createElement("div");
|
|
1383
|
+
column.className = `ina-time-picker__column ina-time-picker__column--period`;
|
|
1384
|
+
const colContent = document.createElement("div");
|
|
1385
|
+
colContent.className = "ina-time-picker__column-content";
|
|
1386
|
+
column.appendChild(colContent);
|
|
1387
|
+
["AM", "PM"].forEach((p) => {
|
|
1388
|
+
const option = document.createElement("div");
|
|
1389
|
+
option.className = "ina-time-picker__option";
|
|
1390
|
+
option.textContent = p;
|
|
1391
|
+
if (currentTime.period === p)
|
|
1392
|
+
option.classList.add("ina-time-picker__option--selected");
|
|
1393
|
+
option.addEventListener("click", (e) => {
|
|
1394
|
+
e.stopPropagation();
|
|
1395
|
+
currentTime.period = p;
|
|
1396
|
+
updateInput();
|
|
1397
|
+
colContent.querySelectorAll(".ina-time-picker__option").forEach(
|
|
1398
|
+
(el) => el.classList.remove("ina-time-picker__option--selected")
|
|
1399
|
+
);
|
|
1400
|
+
option.classList.add("ina-time-picker__option--selected");
|
|
1401
|
+
});
|
|
1402
|
+
colContent.appendChild(option);
|
|
1403
|
+
});
|
|
1404
|
+
return column;
|
|
1405
|
+
};
|
|
1406
|
+
const updateInput = () => {
|
|
1407
|
+
const val = formatTime(
|
|
1408
|
+
currentTime.hours,
|
|
1409
|
+
currentTime.minutes,
|
|
1410
|
+
currentTime.seconds,
|
|
1411
|
+
currentTime.period
|
|
1412
|
+
);
|
|
1413
|
+
input.value = val;
|
|
1414
|
+
picker.dataset.value = val;
|
|
1415
|
+
input.dispatchEvent(new Event("change", { bubbles: true }));
|
|
1416
|
+
};
|
|
1417
|
+
const buildPanel = () => {
|
|
1418
|
+
content.innerHTML = "";
|
|
1419
|
+
content.appendChild(renderColumn("hour", use12Hours ? 13 : 24));
|
|
1420
|
+
content.appendChild(renderColumn("minute", 60));
|
|
1421
|
+
if (showSecond) content.appendChild(renderColumn("second", 60));
|
|
1422
|
+
if (use12Hours) content.appendChild(renderPeriodColumn());
|
|
1423
|
+
};
|
|
1424
|
+
const open = () => {
|
|
1425
|
+
if (disabled) return;
|
|
1426
|
+
isOpen = true;
|
|
1427
|
+
picker.classList.add("ina-time-picker--open");
|
|
1428
|
+
panel.style.display = "block";
|
|
1429
|
+
currentTime = parseTime(input.value);
|
|
1430
|
+
buildPanel();
|
|
1431
|
+
document.dispatchEvent(
|
|
1432
|
+
new CustomEvent("closeTimePicker", { detail: { exclude: picker } })
|
|
1433
|
+
);
|
|
1434
|
+
};
|
|
1435
|
+
const close = () => {
|
|
1436
|
+
isOpen = false;
|
|
1437
|
+
picker.classList.remove("ina-time-picker--open");
|
|
1438
|
+
panel.style.display = "none";
|
|
1439
|
+
};
|
|
1440
|
+
const toggle = (e) => {
|
|
1441
|
+
e.stopPropagation();
|
|
1442
|
+
if (isOpen) close();
|
|
1443
|
+
else open();
|
|
1444
|
+
};
|
|
1445
|
+
wrapper.addEventListener("click", toggle);
|
|
1446
|
+
input.addEventListener("click", (e) => {
|
|
1447
|
+
});
|
|
1448
|
+
document.addEventListener("click", (e) => {
|
|
1449
|
+
if (!picker.contains(e.target)) close();
|
|
1450
|
+
});
|
|
1451
|
+
document.addEventListener("closeTimePicker", (e) => {
|
|
1452
|
+
if (e.detail && e.detail.exclude !== picker) close();
|
|
1453
|
+
});
|
|
1454
|
+
const clearBtn = picker.querySelector(".ina-time-picker__clear-button");
|
|
1455
|
+
if (clearBtn && allowClear) {
|
|
1456
|
+
clearBtn.addEventListener("click", (e) => {
|
|
1457
|
+
e.stopPropagation();
|
|
1458
|
+
input.value = "";
|
|
1459
|
+
currentTime = { hours: 0, minutes: 0, seconds: 0, period: "AM" };
|
|
1460
|
+
picker.dataset.value = "";
|
|
1461
|
+
input.dispatchEvent(new Event("change", { bubbles: true }));
|
|
1462
|
+
});
|
|
1463
|
+
}
|
|
1464
|
+
});
|
|
1465
|
+
}
|
|
1466
|
+
|
|
1194
1467
|
// src/js/index.js
|
|
1195
1468
|
var PREFIX = "ina-ss";
|
|
1196
1469
|
function initAll() {
|
|
@@ -1206,6 +1479,7 @@ function initAll() {
|
|
|
1206
1479
|
initRangeDatepicker();
|
|
1207
1480
|
initTab();
|
|
1208
1481
|
initToggle();
|
|
1482
|
+
initTimepicker();
|
|
1209
1483
|
}
|
|
1210
1484
|
export {
|
|
1211
1485
|
PREFIX,
|