@vanduo-oss/framework 1.4.1 → 1.4.2

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/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Vanduo Framework v1.4.1
1
+ # Vanduo Framework v1.4.2
2
2
 
3
3
  <p align="center">
4
4
  <img src="vanduo-banner.svg" alt="Vanduo Framework Banner" width="100%">
@@ -29,8 +29,8 @@ Vanduo is a zero-dependency UI framework built with HTML, CSS, and vanilla JavaS
29
29
  ### CDN
30
30
 
31
31
  ```html
32
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/vanduo-oss/framework@v1.4.1/dist/vanduo.min.css">
33
- <script src="https://cdn.jsdelivr.net/gh/vanduo-oss/framework@v1.4.1/dist/vanduo.min.js"></script>
32
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/vanduo-oss/framework@v1.4.2/dist/vanduo.min.css">
33
+ <script src="https://cdn.jsdelivr.net/gh/vanduo-oss/framework@v1.4.2/dist/vanduo.min.js"></script>
34
34
  <script>
35
35
  Vanduo.init();
36
36
  </script>
@@ -46,7 +46,9 @@
46
46
  /* ========== Calendar Popup ========== */
47
47
 
48
48
  .vd-datepicker-popup {
49
- position: absolute;
49
+ position: fixed;
50
+ top: 0;
51
+ left: 0;
50
52
  z-index: var(--vd-dp-z-index);
51
53
  background: var(--vd-dp-bg);
52
54
  border: 1px solid var(--vd-dp-border-color);
@@ -79,6 +79,7 @@
79
79
  outline: 0;
80
80
  opacity: 0;
81
81
  transition: var(--vd-modal-transition);
82
+ --vd-modal-dialog-max-width: var(--vd-modal-width);
82
83
  }
83
84
 
84
85
  .vd-modal.is-open {
@@ -91,9 +92,9 @@
91
92
  /* Modal Dialog */
92
93
  .vd-modal-dialog {
93
94
  position: relative;
94
- width: auto;
95
+ width: min(calc(100% - 3.5rem), var(--vd-modal-dialog-max-width));
95
96
  margin: 1.75rem auto;
96
- max-width: var(--vd-modal-width);
97
+ max-width: var(--vd-modal-dialog-max-width);
97
98
  pointer-events: none;
98
99
  transform: scale(0.95);
99
100
  transition: var(--vd-modal-dialog-transition);
@@ -202,16 +203,19 @@
202
203
  }
203
204
 
204
205
  /* Modal Sizes */
206
+ .vd-modal-dialog.vd-modal-sm,
205
207
  .vd-modal-sm .vd-modal-dialog {
206
- max-width: var(--vd-modal-width-sm);
208
+ --vd-modal-dialog-max-width: var(--vd-modal-width-sm);
207
209
  }
208
210
 
211
+ .vd-modal-dialog.vd-modal-lg,
209
212
  .vd-modal-lg .vd-modal-dialog {
210
- max-width: var(--vd-modal-width-lg);
213
+ --vd-modal-dialog-max-width: var(--vd-modal-width-lg);
211
214
  }
212
215
 
216
+ .vd-modal-dialog.vd-modal-xl,
213
217
  .vd-modal-xl .vd-modal-dialog {
214
- max-width: var(--vd-modal-width-xl);
218
+ --vd-modal-dialog-max-width: var(--vd-modal-width-xl);
215
219
  }
216
220
 
217
221
  .vd-modal-fullscreen .vd-modal-dialog {
@@ -256,6 +260,7 @@
256
260
  @media (max-width: 575.98px) {
257
261
  .vd-modal-dialog {
258
262
  margin: 0.5rem;
263
+ width: calc(100% - 1rem);
259
264
  max-width: calc(100% - 1rem);
260
265
  }
261
266
 
@@ -295,4 +300,3 @@
295
300
  overflow: hidden;
296
301
  padding-right: 0;
297
302
  }
298
-
@@ -36,7 +36,9 @@
36
36
  /* ========== Popup ========== */
37
37
 
38
38
  .vd-timepicker-popup {
39
- position: absolute;
39
+ position: fixed;
40
+ top: 0;
41
+ left: 0;
40
42
  z-index: var(--vd-tp-z-index);
41
43
  background: var(--vd-tp-bg);
42
44
  border: 1px solid var(--vd-tp-border-color);
@@ -1,6 +1,6 @@
1
1
  {
2
- "version": "1.4.1",
3
- "builtAt": "2026-05-23T09:27:52.907Z",
4
- "commit": "4799a84",
2
+ "version": "1.4.2",
3
+ "builtAt": "2026-05-23T19:59:36.731Z",
4
+ "commit": "adbe750",
5
5
  "mode": "development+production"
6
6
  }
@@ -1,4 +1,4 @@
1
- /*! Vanduo v1.4.1 | Built: 2026-05-23T09:27:52.907Z | git:4799a84 | development */
1
+ /*! Vanduo v1.4.2 | Built: 2026-05-23T19:59:36.731Z | git:adbe750 | development */
2
2
  var __defProp = Object.defineProperty;
3
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
@@ -201,7 +201,7 @@ module.exports = __toCommonJS(index_exports);
201
201
  // js/vanduo.js
202
202
  (function() {
203
203
  "use strict";
204
- const VANDUO_VERSION = true ? "1.4.1" : "0.0.0-dev";
204
+ const VANDUO_VERSION = true ? "1.4.2" : "0.0.0-dev";
205
205
  const hasOwn = Object.prototype.hasOwnProperty;
206
206
  const Vanduo2 = {
207
207
  version: VANDUO_VERSION,
@@ -8959,6 +8959,27 @@ module.exports = __toCommonJS(index_exports);
8959
8959
  x.setDate(x.getDate() + (6 - day));
8960
8960
  return x;
8961
8961
  }
8962
+ function positionAnchoredPopup(anchor, popup, gap) {
8963
+ const padding = 8;
8964
+ const offset = gap != null ? gap : 4;
8965
+ const rect = anchor.getBoundingClientRect();
8966
+ popup.style.minWidth = Math.max(rect.width, 0) + "px";
8967
+ let top = rect.bottom + offset;
8968
+ let left = rect.left;
8969
+ popup.style.top = top + "px";
8970
+ popup.style.left = left + "px";
8971
+ const popRect = popup.getBoundingClientRect();
8972
+ if (popRect.bottom > window.innerHeight - padding && rect.top - popRect.height > padding) {
8973
+ top = rect.top - popRect.height - offset;
8974
+ popup.style.top = top + "px";
8975
+ }
8976
+ const alignedRect = popup.getBoundingClientRect();
8977
+ left = rect.left;
8978
+ if (left + alignedRect.width > window.innerWidth - padding) {
8979
+ left = window.innerWidth - alignedRect.width - padding;
8980
+ }
8981
+ popup.style.left = Math.max(padding, left) + "px";
8982
+ }
8962
8983
  const Datepicker = {
8963
8984
  instances: /* @__PURE__ */ new Map(),
8964
8985
  init: function(root) {
@@ -9040,7 +9061,7 @@ module.exports = __toCommonJS(index_exports);
9040
9061
  wrapper.style.display = "inline-block";
9041
9062
  input.parentNode.insertBefore(wrapper, input);
9042
9063
  wrapper.appendChild(input);
9043
- wrapper.appendChild(popup);
9064
+ document.body.appendChild(popup);
9044
9065
  const isSameDay = (a, b) => a && b && a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
9045
9066
  const selectDate = (date) => {
9046
9067
  selectedDate = date;
@@ -9270,6 +9291,9 @@ module.exports = __toCommonJS(index_exports);
9270
9291
  }
9271
9292
  popup.appendChild(grid);
9272
9293
  }
9294
+ if (popup.classList.contains("is-open")) {
9295
+ requestAnimationFrame(positionPopup);
9296
+ }
9273
9297
  };
9274
9298
  const handleGridKeydown = (e) => {
9275
9299
  if (!popup.classList.contains("is-open") || viewMode !== "days") return;
@@ -9337,6 +9361,13 @@ module.exports = __toCommonJS(index_exports);
9337
9361
  render();
9338
9362
  requestAnimationFrame(focusFocusedDay);
9339
9363
  };
9364
+ const positionPopup = () => {
9365
+ if (!popup.classList.contains("is-open")) return;
9366
+ positionAnchoredPopup(input, popup);
9367
+ };
9368
+ const repositionHandler = () => {
9369
+ positionPopup();
9370
+ };
9340
9371
  const open = () => {
9341
9372
  viewMode = "days";
9342
9373
  if (selectedDate) {
@@ -9354,7 +9385,10 @@ module.exports = __toCommonJS(index_exports);
9354
9385
  render();
9355
9386
  popup.classList.add("is-open");
9356
9387
  input.setAttribute("aria-expanded", "true");
9357
- requestAnimationFrame(focusFocusedDay);
9388
+ requestAnimationFrame(() => {
9389
+ positionPopup();
9390
+ focusFocusedDay();
9391
+ });
9358
9392
  };
9359
9393
  const close = () => {
9360
9394
  popup.classList.remove("is-open");
@@ -9369,7 +9403,7 @@ module.exports = __toCommonJS(index_exports);
9369
9403
  open();
9370
9404
  };
9371
9405
  const outsideHandler = (e) => {
9372
- if (!wrapper.contains(e.target)) close();
9406
+ if (!input.contains(e.target) && !popup.contains(e.target)) close();
9373
9407
  };
9374
9408
  const escHandler = (e) => {
9375
9409
  if (e.key === "Escape" && popup.classList.contains("is-open")) {
@@ -9382,6 +9416,8 @@ module.exports = __toCommonJS(index_exports);
9382
9416
  document.addEventListener("click", outsideHandler, true);
9383
9417
  document.addEventListener("keydown", escHandler);
9384
9418
  popup.addEventListener("keydown", handleGridKeydown);
9419
+ window.addEventListener("resize", repositionHandler);
9420
+ window.addEventListener("scroll", repositionHandler, true);
9385
9421
  input.setAttribute("aria-haspopup", "dialog");
9386
9422
  input.setAttribute("aria-expanded", "false");
9387
9423
  input.setAttribute("autocomplete", "off");
@@ -9389,7 +9425,10 @@ module.exports = __toCommonJS(index_exports);
9389
9425
  () => input.removeEventListener("focus", focusHandler),
9390
9426
  () => document.removeEventListener("click", outsideHandler, true),
9391
9427
  () => document.removeEventListener("keydown", escHandler),
9392
- () => popup.removeEventListener("keydown", handleGridKeydown)
9428
+ () => popup.removeEventListener("keydown", handleGridKeydown),
9429
+ () => window.removeEventListener("resize", repositionHandler),
9430
+ () => window.removeEventListener("scroll", repositionHandler, true),
9431
+ () => popup.remove()
9393
9432
  );
9394
9433
  this.instances.set(input, { cleanup, open, close, popup });
9395
9434
  },
@@ -9412,6 +9451,27 @@ module.exports = __toCommonJS(index_exports);
9412
9451
  // js/components/timepicker.js
9413
9452
  (function() {
9414
9453
  "use strict";
9454
+ function positionAnchoredPopup(anchor, popup, gap) {
9455
+ const padding = 8;
9456
+ const offset = gap != null ? gap : 4;
9457
+ const rect = anchor.getBoundingClientRect();
9458
+ popup.style.minWidth = Math.max(rect.width, 0) + "px";
9459
+ let top = rect.bottom + offset;
9460
+ let left = rect.left;
9461
+ popup.style.top = top + "px";
9462
+ popup.style.left = left + "px";
9463
+ const popRect = popup.getBoundingClientRect();
9464
+ if (popRect.bottom > window.innerHeight - padding && rect.top - popRect.height > padding) {
9465
+ top = rect.top - popRect.height - offset;
9466
+ popup.style.top = top + "px";
9467
+ }
9468
+ const alignedRect = popup.getBoundingClientRect();
9469
+ left = rect.left;
9470
+ if (left + alignedRect.width > window.innerWidth - padding) {
9471
+ left = window.innerWidth - alignedRect.width - padding;
9472
+ }
9473
+ popup.style.left = Math.max(padding, left) + "px";
9474
+ }
9415
9475
  const Timepicker = {
9416
9476
  instances: /* @__PURE__ */ new Map(),
9417
9477
  init: function(root) {
@@ -9436,7 +9496,7 @@ module.exports = __toCommonJS(index_exports);
9436
9496
  const popup = document.createElement("div");
9437
9497
  popup.className = "vd-timepicker-popup";
9438
9498
  popup.setAttribute("role", "listbox");
9439
- wrapper.appendChild(popup);
9499
+ document.body.appendChild(popup);
9440
9500
  const times = [];
9441
9501
  for (let h = 0; h < 24; h++) {
9442
9502
  for (let m = 0; m < 60; m += step) {
@@ -9476,12 +9536,22 @@ module.exports = __toCommonJS(index_exports);
9476
9536
  popup.appendChild(item);
9477
9537
  });
9478
9538
  };
9539
+ const positionPopup = () => {
9540
+ if (!popup.classList.contains("is-open")) return;
9541
+ positionAnchoredPopup(input, popup);
9542
+ };
9543
+ const repositionHandler = () => {
9544
+ positionPopup();
9545
+ };
9479
9546
  const open = () => {
9480
9547
  render();
9481
9548
  popup.classList.add("is-open");
9482
9549
  input.setAttribute("aria-expanded", "true");
9483
- const selected = popup.querySelector(".is-selected");
9484
- if (selected) selected.scrollIntoView({ block: "center" });
9550
+ requestAnimationFrame(() => {
9551
+ positionPopup();
9552
+ const selected = popup.querySelector(".is-selected");
9553
+ if (selected) selected.scrollIntoView({ block: "center" });
9554
+ });
9485
9555
  };
9486
9556
  const close = () => {
9487
9557
  popup.classList.remove("is-open");
@@ -9489,7 +9559,7 @@ module.exports = __toCommonJS(index_exports);
9489
9559
  };
9490
9560
  const focusHandler = () => open();
9491
9561
  const outsideHandler = (e) => {
9492
- if (!wrapper.contains(e.target)) close();
9562
+ if (!input.contains(e.target) && !popup.contains(e.target)) close();
9493
9563
  };
9494
9564
  const escHandler = (e) => {
9495
9565
  if (e.key === "Escape") close();
@@ -9497,6 +9567,8 @@ module.exports = __toCommonJS(index_exports);
9497
9567
  input.addEventListener("focus", focusHandler);
9498
9568
  document.addEventListener("click", outsideHandler, true);
9499
9569
  document.addEventListener("keydown", escHandler);
9570
+ window.addEventListener("resize", repositionHandler);
9571
+ window.addEventListener("scroll", repositionHandler, true);
9500
9572
  input.setAttribute("aria-haspopup", "listbox");
9501
9573
  input.setAttribute("aria-expanded", "false");
9502
9574
  input.setAttribute("autocomplete", "off");
@@ -9504,7 +9576,10 @@ module.exports = __toCommonJS(index_exports);
9504
9576
  cleanup.push(
9505
9577
  () => input.removeEventListener("focus", focusHandler),
9506
9578
  () => document.removeEventListener("click", outsideHandler, true),
9507
- () => document.removeEventListener("keydown", escHandler)
9579
+ () => document.removeEventListener("keydown", escHandler),
9580
+ () => window.removeEventListener("resize", repositionHandler),
9581
+ () => window.removeEventListener("scroll", repositionHandler, true),
9582
+ () => popup.remove()
9508
9583
  );
9509
9584
  this.instances.set(input, { cleanup, open, close });
9510
9585
  },