@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/dist/vanduo.js CHANGED
@@ -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
  (() => {
3
3
  // js/utils/lifecycle.js
4
4
  (function() {
@@ -176,7 +176,7 @@
176
176
  // js/vanduo.js
177
177
  (function() {
178
178
  "use strict";
179
- const VANDUO_VERSION = true ? "1.4.1" : "0.0.0-dev";
179
+ const VANDUO_VERSION = true ? "1.4.2" : "0.0.0-dev";
180
180
  const hasOwn = Object.prototype.hasOwnProperty;
181
181
  const Vanduo2 = {
182
182
  version: VANDUO_VERSION,
@@ -8934,6 +8934,27 @@
8934
8934
  x.setDate(x.getDate() + (6 - day));
8935
8935
  return x;
8936
8936
  }
8937
+ function positionAnchoredPopup(anchor, popup, gap) {
8938
+ const padding = 8;
8939
+ const offset = gap != null ? gap : 4;
8940
+ const rect = anchor.getBoundingClientRect();
8941
+ popup.style.minWidth = Math.max(rect.width, 0) + "px";
8942
+ let top = rect.bottom + offset;
8943
+ let left = rect.left;
8944
+ popup.style.top = top + "px";
8945
+ popup.style.left = left + "px";
8946
+ const popRect = popup.getBoundingClientRect();
8947
+ if (popRect.bottom > window.innerHeight - padding && rect.top - popRect.height > padding) {
8948
+ top = rect.top - popRect.height - offset;
8949
+ popup.style.top = top + "px";
8950
+ }
8951
+ const alignedRect = popup.getBoundingClientRect();
8952
+ left = rect.left;
8953
+ if (left + alignedRect.width > window.innerWidth - padding) {
8954
+ left = window.innerWidth - alignedRect.width - padding;
8955
+ }
8956
+ popup.style.left = Math.max(padding, left) + "px";
8957
+ }
8937
8958
  const Datepicker = {
8938
8959
  instances: /* @__PURE__ */ new Map(),
8939
8960
  init: function(root) {
@@ -9015,7 +9036,7 @@
9015
9036
  wrapper.style.display = "inline-block";
9016
9037
  input.parentNode.insertBefore(wrapper, input);
9017
9038
  wrapper.appendChild(input);
9018
- wrapper.appendChild(popup);
9039
+ document.body.appendChild(popup);
9019
9040
  const isSameDay = (a, b) => a && b && a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
9020
9041
  const selectDate = (date) => {
9021
9042
  selectedDate = date;
@@ -9245,6 +9266,9 @@
9245
9266
  }
9246
9267
  popup.appendChild(grid);
9247
9268
  }
9269
+ if (popup.classList.contains("is-open")) {
9270
+ requestAnimationFrame(positionPopup);
9271
+ }
9248
9272
  };
9249
9273
  const handleGridKeydown = (e) => {
9250
9274
  if (!popup.classList.contains("is-open") || viewMode !== "days") return;
@@ -9312,6 +9336,13 @@
9312
9336
  render();
9313
9337
  requestAnimationFrame(focusFocusedDay);
9314
9338
  };
9339
+ const positionPopup = () => {
9340
+ if (!popup.classList.contains("is-open")) return;
9341
+ positionAnchoredPopup(input, popup);
9342
+ };
9343
+ const repositionHandler = () => {
9344
+ positionPopup();
9345
+ };
9315
9346
  const open = () => {
9316
9347
  viewMode = "days";
9317
9348
  if (selectedDate) {
@@ -9329,7 +9360,10 @@
9329
9360
  render();
9330
9361
  popup.classList.add("is-open");
9331
9362
  input.setAttribute("aria-expanded", "true");
9332
- requestAnimationFrame(focusFocusedDay);
9363
+ requestAnimationFrame(() => {
9364
+ positionPopup();
9365
+ focusFocusedDay();
9366
+ });
9333
9367
  };
9334
9368
  const close = () => {
9335
9369
  popup.classList.remove("is-open");
@@ -9344,7 +9378,7 @@
9344
9378
  open();
9345
9379
  };
9346
9380
  const outsideHandler = (e) => {
9347
- if (!wrapper.contains(e.target)) close();
9381
+ if (!input.contains(e.target) && !popup.contains(e.target)) close();
9348
9382
  };
9349
9383
  const escHandler = (e) => {
9350
9384
  if (e.key === "Escape" && popup.classList.contains("is-open")) {
@@ -9357,6 +9391,8 @@
9357
9391
  document.addEventListener("click", outsideHandler, true);
9358
9392
  document.addEventListener("keydown", escHandler);
9359
9393
  popup.addEventListener("keydown", handleGridKeydown);
9394
+ window.addEventListener("resize", repositionHandler);
9395
+ window.addEventListener("scroll", repositionHandler, true);
9360
9396
  input.setAttribute("aria-haspopup", "dialog");
9361
9397
  input.setAttribute("aria-expanded", "false");
9362
9398
  input.setAttribute("autocomplete", "off");
@@ -9364,7 +9400,10 @@
9364
9400
  () => input.removeEventListener("focus", focusHandler),
9365
9401
  () => document.removeEventListener("click", outsideHandler, true),
9366
9402
  () => document.removeEventListener("keydown", escHandler),
9367
- () => popup.removeEventListener("keydown", handleGridKeydown)
9403
+ () => popup.removeEventListener("keydown", handleGridKeydown),
9404
+ () => window.removeEventListener("resize", repositionHandler),
9405
+ () => window.removeEventListener("scroll", repositionHandler, true),
9406
+ () => popup.remove()
9368
9407
  );
9369
9408
  this.instances.set(input, { cleanup, open, close, popup });
9370
9409
  },
@@ -9387,6 +9426,27 @@
9387
9426
  // js/components/timepicker.js
9388
9427
  (function() {
9389
9428
  "use strict";
9429
+ function positionAnchoredPopup(anchor, popup, gap) {
9430
+ const padding = 8;
9431
+ const offset = gap != null ? gap : 4;
9432
+ const rect = anchor.getBoundingClientRect();
9433
+ popup.style.minWidth = Math.max(rect.width, 0) + "px";
9434
+ let top = rect.bottom + offset;
9435
+ let left = rect.left;
9436
+ popup.style.top = top + "px";
9437
+ popup.style.left = left + "px";
9438
+ const popRect = popup.getBoundingClientRect();
9439
+ if (popRect.bottom > window.innerHeight - padding && rect.top - popRect.height > padding) {
9440
+ top = rect.top - popRect.height - offset;
9441
+ popup.style.top = top + "px";
9442
+ }
9443
+ const alignedRect = popup.getBoundingClientRect();
9444
+ left = rect.left;
9445
+ if (left + alignedRect.width > window.innerWidth - padding) {
9446
+ left = window.innerWidth - alignedRect.width - padding;
9447
+ }
9448
+ popup.style.left = Math.max(padding, left) + "px";
9449
+ }
9390
9450
  const Timepicker = {
9391
9451
  instances: /* @__PURE__ */ new Map(),
9392
9452
  init: function(root) {
@@ -9411,7 +9471,7 @@
9411
9471
  const popup = document.createElement("div");
9412
9472
  popup.className = "vd-timepicker-popup";
9413
9473
  popup.setAttribute("role", "listbox");
9414
- wrapper.appendChild(popup);
9474
+ document.body.appendChild(popup);
9415
9475
  const times = [];
9416
9476
  for (let h = 0; h < 24; h++) {
9417
9477
  for (let m = 0; m < 60; m += step) {
@@ -9451,12 +9511,22 @@
9451
9511
  popup.appendChild(item);
9452
9512
  });
9453
9513
  };
9514
+ const positionPopup = () => {
9515
+ if (!popup.classList.contains("is-open")) return;
9516
+ positionAnchoredPopup(input, popup);
9517
+ };
9518
+ const repositionHandler = () => {
9519
+ positionPopup();
9520
+ };
9454
9521
  const open = () => {
9455
9522
  render();
9456
9523
  popup.classList.add("is-open");
9457
9524
  input.setAttribute("aria-expanded", "true");
9458
- const selected = popup.querySelector(".is-selected");
9459
- if (selected) selected.scrollIntoView({ block: "center" });
9525
+ requestAnimationFrame(() => {
9526
+ positionPopup();
9527
+ const selected = popup.querySelector(".is-selected");
9528
+ if (selected) selected.scrollIntoView({ block: "center" });
9529
+ });
9460
9530
  };
9461
9531
  const close = () => {
9462
9532
  popup.classList.remove("is-open");
@@ -9464,7 +9534,7 @@
9464
9534
  };
9465
9535
  const focusHandler = () => open();
9466
9536
  const outsideHandler = (e) => {
9467
- if (!wrapper.contains(e.target)) close();
9537
+ if (!input.contains(e.target) && !popup.contains(e.target)) close();
9468
9538
  };
9469
9539
  const escHandler = (e) => {
9470
9540
  if (e.key === "Escape") close();
@@ -9472,6 +9542,8 @@
9472
9542
  input.addEventListener("focus", focusHandler);
9473
9543
  document.addEventListener("click", outsideHandler, true);
9474
9544
  document.addEventListener("keydown", escHandler);
9545
+ window.addEventListener("resize", repositionHandler);
9546
+ window.addEventListener("scroll", repositionHandler, true);
9475
9547
  input.setAttribute("aria-haspopup", "listbox");
9476
9548
  input.setAttribute("aria-expanded", "false");
9477
9549
  input.setAttribute("autocomplete", "off");
@@ -9479,7 +9551,10 @@
9479
9551
  cleanup.push(
9480
9552
  () => input.removeEventListener("focus", focusHandler),
9481
9553
  () => document.removeEventListener("click", outsideHandler, true),
9482
- () => document.removeEventListener("keydown", escHandler)
9554
+ () => document.removeEventListener("keydown", escHandler),
9555
+ () => window.removeEventListener("resize", repositionHandler),
9556
+ () => window.removeEventListener("scroll", repositionHandler, true),
9557
+ () => popup.remove()
9483
9558
  );
9484
9559
  this.instances.set(input, { cleanup, open, close });
9485
9560
  },