@superleapai/flow-ui 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/CHANGELOG.md +65 -0
  2. package/LICENSE +21 -0
  3. package/README.md +451 -0
  4. package/components/alert.js +282 -0
  5. package/components/avatar.js +195 -0
  6. package/components/badge.js +135 -0
  7. package/components/button.js +201 -0
  8. package/components/checkbox.js +254 -0
  9. package/components/currency.js +227 -0
  10. package/components/date-time-picker/date-time-picker-utils.js +253 -0
  11. package/components/date-time-picker/date-time-picker.js +532 -0
  12. package/components/duration/duration-constants.js +46 -0
  13. package/components/duration/duration-utils.js +164 -0
  14. package/components/duration/duration.js +448 -0
  15. package/components/enum-multiselect.js +869 -0
  16. package/components/enum-select.js +831 -0
  17. package/components/enumeration.js +213 -0
  18. package/components/file-input.js +533 -0
  19. package/components/icon.js +200 -0
  20. package/components/input.js +259 -0
  21. package/components/label.js +111 -0
  22. package/components/multiselect.js +351 -0
  23. package/components/phone-input/phone-input.js +392 -0
  24. package/components/phone-input/phone-utils.js +157 -0
  25. package/components/popover.js +240 -0
  26. package/components/radio-group.js +435 -0
  27. package/components/record-multiselect.js +956 -0
  28. package/components/record-select.js +930 -0
  29. package/components/select.js +544 -0
  30. package/components/spinner.js +136 -0
  31. package/components/table.js +335 -0
  32. package/components/textarea.js +114 -0
  33. package/components/time-picker.js +357 -0
  34. package/components/toast.js +343 -0
  35. package/core/flow.js +1729 -0
  36. package/core/superleapClient.js +146 -0
  37. package/dist/output.css +2 -0
  38. package/index.d.ts +458 -0
  39. package/index.js +253 -0
  40. package/package.json +70 -0
@@ -0,0 +1,532 @@
1
+ /**
2
+ * Date-time-picker Component (vanilla JS)
3
+ * Combines calendar grid, optional time picker, and quick actions (Today, Tomorrow, No date).
4
+ * Uses Popover, Button, Select, TimePicker; depends on date-time-picker-utils.js.
5
+ */
6
+
7
+ (function (global) {
8
+ "use strict";
9
+
10
+ function getDep(name) {
11
+ if (typeof global.FlowUI !== "undefined" && typeof global.FlowUI._getComponent === "function") {
12
+ var c = global.FlowUI._getComponent(name);
13
+ if (c) return c;
14
+ }
15
+ return global[name];
16
+ }
17
+
18
+ var ICON_CALENDAR =
19
+ '<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 d="M8 2v4"/><path d="M16 2v4"/><rect width="18" height="18" x="3" y="4" rx="2"/><path d="M3 10h18"/></svg>';
20
+
21
+ var ICON_CHEVRON_LEFT =
22
+ '<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 d="m15 18-6-6 6-6"/></svg>';
23
+ var ICON_CHEVRON_RIGHT =
24
+ '<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 d="m9 18 6-6-6-6"/></svg>';
25
+ var ICON_CALENDAR_DOT =
26
+ '<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 d="M8 2v4"/><path d="M16 2v4"/><rect width="18" height="18" x="3" y="4" rx="2"/><path d="M3 10h18"/><circle cx="12" cy="15" r="1"/></svg>';
27
+ var ICON_CALENDAR_UP =
28
+ '<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 d="M8 2v4"/><path d="M16 2v4"/><rect width="18" height="18" x="3" y="4" rx="2"/><path d="M3 10h18"/><path d="m12 14 2-2 2 2"/><path d="m12 18 2-2 2 2"/></svg>';
29
+ var ICON_CALENDAR_MINUS =
30
+ '<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 d="M8 2v4"/><path d="M16 2v4"/><rect width="18" height="18" x="3" y="4" rx="2"/><path d="M3 10h18"/><path d="M8 14h8"/></svg>';
31
+ var ICON_CLOCK =
32
+ '<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"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>';
33
+
34
+ function join() {
35
+ return Array.prototype.filter.call(arguments, Boolean).join(" ");
36
+ }
37
+
38
+ /**
39
+ * Create the calendar caption (month + year selects) and nav buttons
40
+ */
41
+ function createCaption(displayMonth, fromDate, toDate, yearRange, onMonthChange, onPrev, onNext) {
42
+ var Utils = global.DateTimePickerUtils;
43
+ if (!Utils) throw new Error("DateTimePickerUtils required");
44
+ var MONTHS = Utils.genMonths();
45
+ var YEARS = Utils.genYears(fromDate, toDate, yearRange);
46
+ var isPrevDisabled = Utils.isPreviousMonthDisabled(displayMonth, fromDate);
47
+ var isNextDisabled = Utils.isNextMonthDisabled(displayMonth, toDate);
48
+
49
+ var captionWrap = document.createElement("div");
50
+ captionWrap.className = "flex justify-between relative items-center p-6";
51
+
52
+ var Select = getDep("Select");
53
+ if (Select && typeof Select.create === "function") {
54
+ var monthValue = displayMonth.getMonth();
55
+ var yearValue = displayMonth.getFullYear();
56
+ var monthOptions = MONTHS.map(function (m) {
57
+ return { value: m.value, label: m.label.slice(0, 3) };
58
+ });
59
+ var yearOptions = YEARS.map(function (y) {
60
+ return { value: y.value, label: y.label };
61
+ });
62
+ var selectWrap = document.createElement("div");
63
+ selectWrap.className = "inline-flex gap-x-8";
64
+ var monthSelect = Select.create({
65
+ options: monthOptions,
66
+ value: monthValue,
67
+ placeholder: "Month",
68
+ size: "small",
69
+ onChange: function (val) {
70
+ var d = new Date(displayMonth.getTime());
71
+ d.setMonth(Number(val));
72
+ onMonthChange(d);
73
+ },
74
+ });
75
+ var yearSelect = Select.create({
76
+ options: yearOptions,
77
+ value: yearValue,
78
+ placeholder: "Year",
79
+ size: "small",
80
+ onChange: function (val) {
81
+ var d = new Date(displayMonth.getTime());
82
+ d.setFullYear(Number(val));
83
+ onMonthChange(d);
84
+ },
85
+ });
86
+ selectWrap.appendChild(monthSelect);
87
+ selectWrap.appendChild(yearSelect);
88
+ captionWrap.appendChild(selectWrap);
89
+ }
90
+
91
+ var Button = getDep("Button");
92
+ if (!Button || typeof Button.create !== "function") {
93
+ var fallbackNav = document.createElement("div");
94
+ fallbackNav.className = "flex items-center gap-x-8";
95
+ fallbackNav.textContent = "Button component required";
96
+ captionWrap.appendChild(fallbackNav);
97
+ return { element: captionWrap, setMonth: function () {} };
98
+ }
99
+ var nav = document.createElement("div");
100
+ nav.className = "flex items-center gap-x-8";
101
+ var prevBtn = Button.create({
102
+ icon: ICON_CHEVRON_LEFT,
103
+ variant: "ghost",
104
+ size: "small",
105
+ label: "Previous month",
106
+ disabled: isPrevDisabled,
107
+ className: "opacity-50 hover:opacity-100",
108
+ onClick: !isPrevDisabled ? onPrev : undefined,
109
+ });
110
+ var nextBtn = Button.create({
111
+ icon: ICON_CHEVRON_RIGHT,
112
+ variant: "ghost",
113
+ size: "small",
114
+ label: "Next month",
115
+ disabled: isNextDisabled,
116
+ className: "opacity-50 hover:opacity-100",
117
+ onClick: !isNextDisabled ? onNext : undefined,
118
+ });
119
+ nav.appendChild(prevBtn);
120
+ nav.appendChild(nextBtn);
121
+ captionWrap.appendChild(nav);
122
+
123
+ return {
124
+ element: captionWrap,
125
+ setMonth: function (d) {
126
+ if (Select && captionWrap.querySelectorAll(".custom-select").length >= 2) {
127
+ var selects = captionWrap.querySelectorAll(".custom-select");
128
+ if (selects[0].updateValue) selects[0].updateValue(d.getMonth());
129
+ if (selects[1].updateValue) selects[1].updateValue(d.getFullYear());
130
+ }
131
+ },
132
+ };
133
+ }
134
+
135
+ /**
136
+ * Build calendar table (weekday headers + day grid)
137
+ */
138
+ function createCalendarGrid(displayMonth, selectedDate, fromDate, toDate, onSelectDay) {
139
+ var Utils = global.DateTimePickerUtils;
140
+ if (!Utils) throw new Error("DateTimePickerUtils required");
141
+ var grid = Utils.getMonthGrid(displayMonth, selectedDate, fromDate, toDate);
142
+ var weekDays = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
143
+
144
+ var tableWrap = document.createElement("div");
145
+ tableWrap.className = "w-full border-collapse border-t-1/2 border-border-primary";
146
+
147
+ var headRow = document.createElement("div");
148
+ headRow.className = "flex gap-x-6 p-6";
149
+ weekDays.forEach(function (wd) {
150
+ var th = document.createElement("div");
151
+ th.className = "text-typography-tertiary-text flex-1 flex items-center justify-center text-reg-12 my-2 text-center";
152
+ th.textContent = wd;
153
+ headRow.appendChild(th);
154
+ });
155
+ tableWrap.appendChild(headRow);
156
+
157
+ var Button = getDep("Button");
158
+ if (!Button || typeof Button.create !== "function") {
159
+ var fallbackRows = document.createElement("div");
160
+ fallbackRows.className = "space-y-0 p-6 text-typography-tertiary-text text-reg-12";
161
+ fallbackRows.textContent = "Button component required";
162
+ tableWrap.appendChild(fallbackRows);
163
+ return tableWrap;
164
+ }
165
+ var rowsWrap = document.createElement("div");
166
+ rowsWrap.className = "space-y-0";
167
+ grid.forEach(function (week) {
168
+ var row = document.createElement("div");
169
+ row.className = "flex gap-x-6 px-6";
170
+ week.forEach(function (cell) {
171
+ var variant = "ghost";
172
+ if (cell.isSelected) {
173
+ variant = "primary";
174
+ } else if (cell.isToday) {
175
+ variant = "outline";
176
+ }
177
+ var btnClassName = join(
178
+ "!text-reg-12 my-2 flex-1 !px-0 !py-0",
179
+ cell.currentMonth ? "" : "text-typography-quaternary-text"
180
+ );
181
+ var btn = Button.create({
182
+ variant: variant,
183
+ size: "small",
184
+ text: String(cell.date.getDate()),
185
+ label: cell.date.toDateString(),
186
+ disabled: cell.disabled,
187
+ className: btnClassName,
188
+ onClick: !cell.disabled ? function () {
189
+ onSelectDay(new Date(cell.date.getTime()));
190
+ } : undefined,
191
+ });
192
+ row.appendChild(btn);
193
+ });
194
+ rowsWrap.appendChild(row);
195
+ });
196
+ tableWrap.appendChild(rowsWrap);
197
+
198
+ return tableWrap;
199
+ }
200
+
201
+ /**
202
+ * Create date-time-picker component
203
+ * @param {Object} config
204
+ * @param {Date} [config.value] - Current value
205
+ * @param {Function} [config.onChange] - (date: Date | undefined) => void
206
+ * @param {boolean} [config.disabled]
207
+ * @param {12|24} [config.hourCycle=12]
208
+ * @param {number} [config.yearRange=50]
209
+ * @param {string} [config.placeholder='Pick a date']
210
+ * @param {'day'|'hour'|'minute'|'second'} [config.granularity='minute']
211
+ * @param {string} [config.variant='default']
212
+ * @param {string} [config.size='default']
213
+ * @param {string} [config.className]
214
+ * @param {Date} [config.fromDate]
215
+ * @param {Date} [config.toDate]
216
+ * @param {string} [config.align='start']
217
+ * @returns {HTMLElement} Container element (trigger + popover instance)
218
+ */
219
+ function create(config) {
220
+ var Utils = global.DateTimePickerUtils;
221
+ if (!Utils) throw new Error("DateTimePickerUtils required");
222
+ var Popover = getDep("Popover");
223
+ var Button = getDep("Button");
224
+ var TimePicker = getDep("TimePicker");
225
+ if (!Popover || typeof Popover.create !== "function" || !Button || typeof Button.create !== "function") {
226
+ throw new Error("Popover and Button required");
227
+ }
228
+
229
+ var value = config.value;
230
+ var onChange = config.onChange;
231
+ var disabled = !!config.disabled;
232
+ var hourCycle = config.hourCycle === 24 ? 24 : 12;
233
+ var yearRange = config.yearRange != null ? config.yearRange : 50;
234
+ var placeholder = config.placeholder != null ? config.placeholder : "Pick a date";
235
+ var granularity = config.granularity || "minute";
236
+ var variant = config.variant || "default";
237
+ var size = config.size || "default";
238
+ var fromDate = config.fromDate;
239
+ var toDate = config.toDate;
240
+ var align = config.align || "start";
241
+
242
+ var validDate = Utils.getValidDate(value, fromDate, toDate);
243
+ var displayMonth = validDate ? new Date(validDate.getTime()) : new Date();
244
+
245
+ var triggerWrapper = document.createElement("div");
246
+ var triggerClasses = join(
247
+ "group flex items-center border-1/2 border-border-primary rounded-4 text-typography-primary-text gap-x-8 w-full transition-all ease-in-out",
248
+ "bg-fill-quarternary-fill-white hover:border-primary-base focus-within:border-primary-base",
249
+ size === "large" ? "px-12 py-8" : size === "small" ? "px-12 py-4" : "px-12 py-6",
250
+ disabled ? "cursor-not-allowed border-border-primary bg-fill-tertiary-fill-light-gray text-typography-quaternary-text hover:border-border-primary" : "cursor-pointer"
251
+ );
252
+ triggerWrapper.className = triggerClasses;
253
+ triggerWrapper.setAttribute("role", "button");
254
+ triggerWrapper.setAttribute("tabindex", disabled ? "-1" : "0");
255
+ triggerWrapper.setAttribute("aria-haspopup", "dialog");
256
+ triggerWrapper.setAttribute("aria-expanded", "false");
257
+
258
+ var triggerText = document.createElement("span");
259
+ triggerText.className = "flex-1 truncate text-left text-reg-13";
260
+ var formatted = Utils.formatDateTime(validDate, hourCycle, granularity);
261
+ triggerText.textContent = formatted || placeholder;
262
+ triggerText.classList.toggle("text-typography-quaternary-text", !formatted);
263
+ triggerWrapper.appendChild(triggerText);
264
+
265
+ var iconWrap = document.createElement("span");
266
+ iconWrap.className = "flex size-16 shrink-0 items-center justify-center text-typography-primary-text [&_svg]:text-typography-primary-text";
267
+ iconWrap.setAttribute("aria-hidden", "true");
268
+ iconWrap.innerHTML = ICON_CALENDAR;
269
+ triggerWrapper.appendChild(iconWrap);
270
+
271
+ var container = document.createElement("div");
272
+ container.className = "date-time-picker relative w-full " + (config.className || "");
273
+ container.appendChild(triggerWrapper);
274
+
275
+ function updateTriggerText() {
276
+ validDate = Utils.getValidDate(value, fromDate, toDate);
277
+ formatted = Utils.formatDateTime(validDate, hourCycle, granularity);
278
+ triggerText.textContent = formatted || placeholder;
279
+ triggerText.classList.toggle("text-typography-quaternary-text", !formatted);
280
+ }
281
+
282
+ function setMonth(d) {
283
+ displayMonth = new Date(d.getTime());
284
+ }
285
+
286
+ var captionEl;
287
+ var calendarEl;
288
+ var timePickerEl;
289
+ var quickRow;
290
+
291
+ function handleSelectDay(dayDate) {
292
+ var out;
293
+ if (granularity === "day") {
294
+ out = Utils.startOfDay(dayDate);
295
+ } else {
296
+ out = new Date(dayDate.getTime());
297
+ if (validDate) {
298
+ out.setHours(validDate.getHours(), validDate.getMinutes(), validDate.getSeconds(), 0);
299
+ }
300
+ }
301
+ value = Utils.getValidDate(out, fromDate, toDate);
302
+ validDate = value;
303
+ updateTriggerText();
304
+ if (onChange) onChange(value);
305
+ setMonth(out);
306
+ if (captionEl && captionEl.setMonth) captionEl.setMonth(displayMonth);
307
+ if (timePickerEl && timePickerEl.updateValue) {
308
+ timePickerEl.updateValue(Utils.getTimeString(value));
309
+ }
310
+ refreshCalendar();
311
+ }
312
+
313
+ function refreshCalendar() {
314
+ var oldCalendar = panelInner.querySelector("[data-dtp-calendar]");
315
+ if (oldCalendar) oldCalendar.remove();
316
+ var calendarWrap = document.createElement("div");
317
+ calendarWrap.setAttribute("data-dtp-calendar", "true");
318
+ calendarEl = createCalendarGrid(
319
+ displayMonth,
320
+ validDate,
321
+ fromDate,
322
+ toDate,
323
+ handleSelectDay
324
+ );
325
+ calendarWrap.appendChild(calendarEl);
326
+ var first = panelInner.firstElementChild;
327
+ if (first) {
328
+ panelInner.insertBefore(calendarWrap, first.nextSibling);
329
+ } else {
330
+ panelInner.appendChild(calendarWrap);
331
+ }
332
+ }
333
+
334
+ var panelInner = document.createElement("div");
335
+ panelInner.className = "px-0";
336
+
337
+ function buildPanelContent() {
338
+ var fragment = document.createDocumentFragment();
339
+
340
+ // Caption (month/year dropdowns then nav chevrons)
341
+ captionEl = createCaption(
342
+ displayMonth,
343
+ fromDate,
344
+ toDate,
345
+ yearRange,
346
+ function (d) {
347
+ setMonth(d);
348
+ refreshCalendar();
349
+ if (captionEl && captionEl.setMonth) captionEl.setMonth(displayMonth);
350
+ },
351
+ function () {
352
+ if (!Utils.isPreviousMonthDisabled(displayMonth, fromDate)) {
353
+ setMonth(Utils.addMonths(displayMonth, -1));
354
+ refreshCalendar();
355
+ if (captionEl && captionEl.setMonth) captionEl.setMonth(displayMonth);
356
+ }
357
+ },
358
+ function () {
359
+ if (!Utils.isNextMonthDisabled(displayMonth, toDate)) {
360
+ setMonth(Utils.addMonths(displayMonth, 1));
361
+ refreshCalendar();
362
+ if (captionEl && captionEl.setMonth) captionEl.setMonth(displayMonth);
363
+ }
364
+ }
365
+ );
366
+ fragment.appendChild(captionEl.element);
367
+
368
+ // Calendar grid (reduced bottom padding to avoid large gap above date/time row)
369
+ var calendarWrap = document.createElement("div");
370
+ calendarWrap.setAttribute("data-dtp-calendar", "true");
371
+ calendarEl = createCalendarGrid(
372
+ displayMonth,
373
+ validDate,
374
+ fromDate,
375
+ toDate,
376
+ handleSelectDay
377
+ );
378
+ calendarWrap.appendChild(calendarEl);
379
+ fragment.appendChild(calendarWrap);
380
+
381
+ // Time row (when granularity !== 'day'): TimePicker only
382
+ if (granularity !== "day" && TimePicker) {
383
+ var timeRow = document.createElement("div");
384
+ timeRow.className = "border-t-1/2 border-border-primary p-6";
385
+
386
+ var timeValue = validDate ? Utils.getTimeString(validDate) : "00:00";
387
+ timePickerEl = TimePicker.create({
388
+ fieldId: "dtp-time",
389
+ value: timeValue,
390
+ placeholder: "Time",
391
+ use24Hour: hourCycle === 24,
392
+ size: "small",
393
+ onChange: function (timeStr) {
394
+ var base = value ? new Date(value.getTime()) : new Date();
395
+ Utils.setTimeFromString(base, timeStr);
396
+ value = Utils.getValidDate(base, fromDate, toDate);
397
+ validDate = value;
398
+ updateTriggerText();
399
+ if (onChange) onChange(value);
400
+ },
401
+ });
402
+ timeRow.appendChild(timePickerEl);
403
+ fragment.appendChild(timeRow);
404
+ }
405
+
406
+ // Quick actions
407
+ var quick = Utils.getQuickSelectionDates(fromDate, toDate);
408
+ quickRow = document.createElement("div");
409
+ quickRow.className = "flex flex-wrap gap-8 border-t-1/2 border-border-primary p-6";
410
+ if (quick.today) {
411
+ var todayBtn = Button.create({
412
+ variant: "outline",
413
+ size: "small",
414
+ text: "Today",
415
+ startIcon: ICON_CALENDAR_DOT,
416
+ onClick: function () {
417
+ var t = granularity === "day" ? Utils.startOfDay(new Date()) : new Date();
418
+ value = Utils.getValidDate(t, fromDate, toDate);
419
+ validDate = value;
420
+ setMonth(value || new Date());
421
+ updateTriggerText();
422
+ if (onChange) onChange(value);
423
+ refreshCalendar();
424
+ if (timePickerEl && timePickerEl.updateValue && value) {
425
+ timePickerEl.updateValue(Utils.getTimeString(value));
426
+ }
427
+ },
428
+ });
429
+ quickRow.appendChild(todayBtn);
430
+ }
431
+ if (quick.tomorrow) {
432
+ var tomorrowBtn = Button.create({
433
+ variant: "outline",
434
+ size: "small",
435
+ text: "Tomorrow",
436
+ startIcon: ICON_CALENDAR_UP,
437
+ onClick: function () {
438
+ var t = Utils.addDays(new Date(), 1);
439
+ t = granularity === "day" ? Utils.startOfDay(t) : t;
440
+ value = Utils.getValidDate(t, fromDate, toDate);
441
+ validDate = value;
442
+ setMonth(value || new Date());
443
+ updateTriggerText();
444
+ if (onChange) onChange(value);
445
+ refreshCalendar();
446
+ if (timePickerEl && timePickerEl.updateValue && value) {
447
+ timePickerEl.updateValue(Utils.getTimeString(value));
448
+ }
449
+ },
450
+ });
451
+ quickRow.appendChild(tomorrowBtn);
452
+ }
453
+ var noDateBtn = Button.create({
454
+ variant: "outline",
455
+ size: "small",
456
+ text: "No date",
457
+ startIcon: ICON_CALENDAR_MINUS,
458
+ onClick: function () {
459
+ value = undefined;
460
+ validDate = undefined;
461
+ setMonth(new Date());
462
+ updateTriggerText();
463
+ if (onChange) onChange(undefined);
464
+ popoverApi.hide();
465
+ },
466
+ });
467
+ quickRow.appendChild(noDateBtn);
468
+ fragment.appendChild(quickRow);
469
+
470
+ return fragment;
471
+ }
472
+
473
+ panelInner.appendChild(buildPanelContent());
474
+
475
+ var popoverApi = Popover.create({
476
+ trigger: triggerWrapper,
477
+ content: panelInner,
478
+ placement: "bottom",
479
+ align: align,
480
+ closeOnClickOutside: true,
481
+ onOpen: function () {
482
+ triggerWrapper.setAttribute("aria-expanded", "true");
483
+ displayMonth = validDate ? new Date(validDate.getTime()) : new Date();
484
+ if (captionEl && captionEl.setMonth) captionEl.setMonth(displayMonth);
485
+ },
486
+ onClose: function () {
487
+ triggerWrapper.setAttribute("aria-expanded", "false");
488
+ },
489
+ });
490
+
491
+ // Popover already toggles on trigger click; we only block when disabled (use capture so we run first)
492
+ triggerWrapper.addEventListener(
493
+ "click",
494
+ function (e) {
495
+ if (disabled) {
496
+ e.preventDefault();
497
+ e.stopImmediatePropagation();
498
+ }
499
+ },
500
+ true
501
+ );
502
+ triggerWrapper.addEventListener("keydown", function (e) {
503
+ if (e.key === "Enter" || e.key === " ") {
504
+ e.preventDefault();
505
+ if (!disabled) triggerWrapper.click();
506
+ }
507
+ });
508
+
509
+ container.getValue = function () {
510
+ return value;
511
+ };
512
+ container.setValue = function (v) {
513
+ value = v;
514
+ validDate = Utils.getValidDate(value, fromDate, toDate);
515
+ displayMonth = validDate ? new Date(validDate.getTime()) : new Date();
516
+ updateTriggerText();
517
+ };
518
+ container.setDisabled = function (d) {
519
+ disabled = !!d;
520
+ triggerWrapper.classList.toggle("cursor-not-allowed", disabled);
521
+ triggerWrapper.classList.toggle("opacity-60", disabled);
522
+ triggerWrapper.setAttribute("tabindex", disabled ? "-1" : "0");
523
+ if (disabled) popoverApi.hide();
524
+ };
525
+
526
+ return container;
527
+ }
528
+
529
+ global.DateTimePicker = {
530
+ create: create,
531
+ };
532
+ })(typeof window !== "undefined" ? window : this);
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Duration component constants: preset durations and wheel definitions.
3
+ */
4
+
5
+ (function (global) {
6
+ "use strict";
7
+
8
+ var PRESET_DURATIONS = [
9
+ {
10
+ title: "Seconds & Minutes",
11
+ presets: [
12
+ { label: "30s", value: 30 },
13
+ { label: "1m", value: 60 },
14
+ { label: "2m", value: 120 },
15
+ { label: "5m", value: 300 },
16
+ { label: "10m", value: 600 },
17
+ { label: "15m", value: 900 },
18
+ { label: "30m", value: 1800 },
19
+ ],
20
+ },
21
+ {
22
+ title: "Hours & Days",
23
+ presets: [
24
+ { label: "1h", value: 3600 },
25
+ { label: "2h", value: 7200 },
26
+ { label: "6h", value: 21600 },
27
+ { label: "12h", value: 43200 },
28
+ { label: "1d", value: 86400 },
29
+ { label: "2d", value: 172800 },
30
+ { label: "7d", value: 604800 },
31
+ ],
32
+ },
33
+ ];
34
+
35
+ var DURATION_WHEELS = [
36
+ { unit: "days", label: "days" },
37
+ { unit: "hours", label: "hours" },
38
+ { unit: "minutes", label: "min" },
39
+ { unit: "seconds", label: "sec" },
40
+ ];
41
+
42
+ global.DurationConstants = {
43
+ PRESET_DURATIONS: PRESET_DURATIONS,
44
+ DURATION_WHEELS: DURATION_WHEELS,
45
+ };
46
+ })(typeof window !== "undefined" ? window : this);