@codbex/harmonia 1.10.2 → 1.11.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/harmonia.js CHANGED
@@ -42,6 +42,7 @@
42
42
  var CircleSuccess = 26;
43
43
  var CircleUnknown = 27;
44
44
  var CircleUser = 28;
45
+ var Home = 29;
45
46
  function setCalendarContent(svg) {
46
47
  const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
47
48
  path.setAttributeNS(
@@ -384,6 +385,15 @@
384
385
  );
385
386
  svg.appendChild(path2);
386
387
  }
388
+ function setHomeContent(svg) {
389
+ const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
390
+ path.setAttributeNS(
391
+ null,
392
+ "d",
393
+ "m8 0.8252c-0.51124 0-1.0243 0.19615-1.416 0.58789l-4.4316 4.4297c-0.27162 0.2733-0.65234 0.7207-0.65234 1.6055v5.7266c0 1.108 0.892 2 2 2h9c1.108 0 2-0.892 2-2v-5.7266c0-0.88477-0.38073-1.3322-0.65234-1.6055l-4.4316-4.4297c-0.39174-0.39174-0.90478-0.58789-1.416-0.58789zm0 1.4258c0.25431-2.91e-4 0.5101 0.096117 0.70703 0.29297l4.2207 4.2188v0.00195c0.17404 0.1851 0.27111 0.42951 0.27148 0.68359v5.4277c0 0.554-0.446 1-1 1h-1.5078v-4.1289c0-1.108-0.892-2-2-2h-1.3828c-1.108 0-2 0.892-2 2v4.1289h-1.5078c-0.554 0-1-0.446-1-1v-5.4277c3.752e-4 -0.25408 0.09744-0.4985 0.27148-0.68359v-0.00195l4.2207-4.2188c0.19693-0.19685 0.45273-0.29326 0.70703-0.29297zm-0.58984 6.7949h1.1797c0.44244-4.323e-4 0.80121 0.35834 0.80078 0.80078v4.0293h-2.7812v-4.0293c-4.322e-4 -0.44244 0.35834-0.80121 0.80078-0.80078z"
394
+ );
395
+ svg.appendChild(path);
396
+ }
387
397
  function createSvg({ icon, classes = "size-4", attrs } = {}) {
388
398
  const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
389
399
  svg.setAttributeNS(null, "width", "16");
@@ -484,6 +494,9 @@
484
494
  case CircleUser:
485
495
  setCircleUserContent(svg);
486
496
  break;
497
+ case Home:
498
+ setHomeContent(svg);
499
+ break;
487
500
  default:
488
501
  break;
489
502
  }
@@ -583,6 +596,9 @@
583
596
  case "circle-user":
584
597
  setCircleUserContent(svg);
585
598
  break;
599
+ case "home":
600
+ setHomeContent(svg);
601
+ break;
586
602
  default:
587
603
  break;
588
604
  }
@@ -1017,6 +1033,113 @@
1017
1033
  });
1018
1034
  }
1019
1035
 
1036
+ // src/components/breadcrumb.js
1037
+ function breadcrumb_default(Alpine) {
1038
+ Alpine.directive("h-breadcrumb", (el, _, { Alpine: Alpine2, cleanup }) => {
1039
+ el.classList.add("flex", "items-center", "break-words", "text-sm", "text-muted-foreground", "rounded-control");
1040
+ el.setAttribute("role", "navigation");
1041
+ el.setAttribute("aria-label", "breadcrumb");
1042
+ el.setAttribute("data-slot", "breadcrumb");
1043
+ const variants = {
1044
+ outline: ["border"]
1045
+ };
1046
+ const allVariantClasses = Object.values(variants).flat();
1047
+ const sizes = {
1048
+ default: ["h-9", "px-3"],
1049
+ md: ["h-8", "px-2.5"],
1050
+ sm: ["h-6.5", "px-2"]
1051
+ };
1052
+ const allSizeClasses = Object.values(sizes).flat();
1053
+ function applyClasses() {
1054
+ const variant = el.getAttribute("data-variant");
1055
+ const size3 = el.getAttribute("data-size") ?? "default";
1056
+ el.classList.remove(...allVariantClasses, ...allSizeClasses);
1057
+ if (variant && Object.prototype.hasOwnProperty.call(variants, variant)) {
1058
+ el.classList.add(...variants[variant]);
1059
+ el.classList.add(...sizes[size3] ?? sizes.default);
1060
+ } else {
1061
+ el.classList.add("px-2");
1062
+ }
1063
+ }
1064
+ applyClasses();
1065
+ const observer = new MutationObserver(() => applyClasses());
1066
+ observer.observe(el, { attributes: true, attributeFilter: ["data-variant", "data-size"] });
1067
+ if (el.getAttribute("data-overflow") === "scroll") {
1068
+ el.classList.add("overflow-x-scroll", "scrollbar-none");
1069
+ let preserveScroll = false;
1070
+ const scrollToEnd = () => {
1071
+ el.scrollLeft = el.scrollWidth;
1072
+ };
1073
+ Alpine2.nextTick(scrollToEnd);
1074
+ const handleScroll = () => {
1075
+ preserveScroll = el.scrollLeft < el.scrollWidth - el.clientWidth - 1;
1076
+ };
1077
+ const handleResize = () => {
1078
+ if (!preserveScroll) scrollToEnd();
1079
+ };
1080
+ el.addEventListener("scroll", handleScroll);
1081
+ window.addEventListener("resize", handleResize);
1082
+ cleanup(() => {
1083
+ el.removeEventListener("scroll", handleScroll);
1084
+ window.removeEventListener("resize", handleResize);
1085
+ observer.disconnect();
1086
+ });
1087
+ } else if (el.getAttribute("data-overflow") === "nowrap") {
1088
+ el.classList.add("flex-nowrap");
1089
+ cleanup(() => observer.disconnect());
1090
+ } else {
1091
+ el.classList.add("flex-wrap");
1092
+ cleanup(() => observer.disconnect());
1093
+ }
1094
+ });
1095
+ Alpine.directive("h-breadcrumb-list", (el, _, { Alpine: Alpine2 }) => {
1096
+ el.classList.add("flex", "items-center", "gap-1.5");
1097
+ el.setAttribute("data-slot", "breadcrumb-list");
1098
+ const nav = Alpine2.findClosest(el, (node) => node.getAttribute("data-slot") === "breadcrumb");
1099
+ const overflow = nav?.getAttribute("data-overflow");
1100
+ if (overflow === "scroll" || overflow === "nowrap") {
1101
+ el.classList.add("flex-nowrap");
1102
+ } else {
1103
+ el.classList.add("flex-wrap");
1104
+ }
1105
+ });
1106
+ Alpine.directive("h-breadcrumb-item", (el) => {
1107
+ el.classList.add("group", "inline-flex", "items-center", "gap-1.5");
1108
+ el.setAttribute("data-slot", "breadcrumb-item");
1109
+ const separator = createSvg({
1110
+ icon: ChevronRight,
1111
+ classes: "size-3.5 group-first-of-type:hidden",
1112
+ attrs: { "aria-hidden": "true", role: "presentation" }
1113
+ });
1114
+ el.prepend(separator);
1115
+ });
1116
+ Alpine.directive("h-breadcrumb-link", (el) => {
1117
+ el.classList.add(
1118
+ "cursor-pointer",
1119
+ "hbox",
1120
+ "gap-1.5",
1121
+ "items-center",
1122
+ "whitespace-nowrap",
1123
+ "text-primary",
1124
+ "transition-colors",
1125
+ "underline-offset-4",
1126
+ "hover:underline",
1127
+ "hover:text-primary-hover",
1128
+ "active:text-primary-active",
1129
+ "[&>svg]:size-4",
1130
+ "[&>svg]:text-current"
1131
+ );
1132
+ el.setAttribute("data-slot", "breadcrumb-link");
1133
+ });
1134
+ Alpine.directive("h-breadcrumb-page", (el) => {
1135
+ el.classList.add("hbox", "gap-1.5", "items-center", "whitespace-nowrap", "text-foreground", "font-normal", "[&>svg]:size-4", "[&>svg]:text-current");
1136
+ el.setAttribute("role", "link");
1137
+ el.setAttribute("aria-current", "page");
1138
+ el.setAttribute("aria-disabled", "true");
1139
+ el.setAttribute("data-slot", "breadcrumb-page");
1140
+ });
1141
+ }
1142
+
1020
1143
  // src/components/button.js
1021
1144
  var buttonVariants = {
1022
1145
  default: [
@@ -4829,6 +4952,10 @@
4829
4952
  }
4830
4953
  function close(closeParent = false, focusTrigger = false) {
4831
4954
  el.pauseKeyEvents = false;
4955
+ if (autoUpdateCleanup) {
4956
+ autoUpdateCleanup();
4957
+ autoUpdateCleanup = null;
4958
+ }
4832
4959
  if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
4833
4960
  el.classList.add("hidden", "scale-95", "opacity-0");
4834
4961
  Object.assign(el.style, {
@@ -4958,6 +5085,7 @@
4958
5085
  }
4959
5086
  }
4960
5087
  }
5088
+ let autoUpdateCleanup;
4961
5089
  function open(parent) {
4962
5090
  if (el.classList.contains("hidden")) {
4963
5091
  let getPlacement = function() {
@@ -4967,41 +5095,52 @@
4967
5095
  return el.getAttribute("data-align") || "bottom-start";
4968
5096
  }
4969
5097
  return "right-start";
5098
+ }, updatePosition = function() {
5099
+ const isFirst = firstOpen;
5100
+ firstOpen = false;
5101
+ computePosition2(parent, el, {
5102
+ placement: getPlacement(),
5103
+ strategy: "fixed",
5104
+ middleware: [
5105
+ offset2(isSubmenu ? 0 : 4),
5106
+ flip2(),
5107
+ shift2({ padding: 4 }),
5108
+ size2({
5109
+ apply({ availableWidth, availableHeight, elements }) {
5110
+ Object.assign(elements.floating.style, {
5111
+ maxWidth: `${Math.max(0, availableWidth) - 4}px`,
5112
+ maxHeight: `${Math.max(0, availableHeight) - 4}px`
5113
+ });
5114
+ }
5115
+ })
5116
+ ]
5117
+ }).then(({ x, y }) => {
5118
+ if (isFirst) {
5119
+ if (!isSubmenu) {
5120
+ Alpine2.nextTick(() => el.focus());
5121
+ listenForTrigger(false);
5122
+ }
5123
+ Alpine2.nextTick(() => {
5124
+ top.addEventListener("contextmenu", onClick);
5125
+ top.addEventListener("click", onClick);
5126
+ el.addEventListener("keydown", onKeyDown);
5127
+ });
5128
+ }
5129
+ Object.assign(el.style, {
5130
+ left: `${x}px`,
5131
+ top: `${y}px`
5132
+ });
5133
+ el.classList.remove("scale-95", "opacity-0");
5134
+ });
4970
5135
  };
4971
5136
  el.classList.remove("hidden");
4972
5137
  el.pauseKeyEvents = false;
4973
- computePosition2(parent, el, {
4974
- placement: getPlacement(),
4975
- strategy: "fixed",
4976
- middleware: [
4977
- offset2(isSubmenu ? 0 : 4),
4978
- flip2(),
4979
- shift2({ padding: 4 }),
4980
- size2({
4981
- apply({ availableWidth, availableHeight, elements }) {
4982
- Object.assign(elements.floating.style, {
4983
- maxWidth: `${Math.max(0, availableWidth) - 4}px`,
4984
- maxHeight: `${Math.max(0, availableHeight) - 4}px`
4985
- });
4986
- }
4987
- })
4988
- ]
4989
- }).then(({ x, y }) => {
4990
- if (!isSubmenu) {
4991
- Alpine2.nextTick(() => el.focus());
4992
- listenForTrigger(false);
4993
- }
4994
- Alpine2.nextTick(() => {
4995
- top.addEventListener("contextmenu", onClick);
4996
- top.addEventListener("click", onClick);
4997
- el.addEventListener("keydown", onKeyDown);
4998
- });
4999
- Object.assign(el.style, {
5000
- left: `${x}px`,
5001
- top: `${y}px`
5002
- });
5003
- el.classList.remove("scale-95", "opacity-0");
5004
- });
5138
+ let firstOpen = true;
5139
+ if (!isSubmenu && menuTrigger._menu_trigger.isDropdown) {
5140
+ autoUpdateCleanup = autoUpdate(parent, el, updatePosition);
5141
+ } else {
5142
+ updatePosition();
5143
+ }
5005
5144
  }
5006
5145
  }
5007
5146
  function openDropdown() {
@@ -5045,6 +5184,7 @@
5045
5184
  }
5046
5185
  el.addEventListener("transitionend", onTransitionEnd);
5047
5186
  cleanup(() => {
5187
+ if (autoUpdateCleanup) autoUpdateCleanup();
5048
5188
  if (menuTrigger) listenForTrigger(false);
5049
5189
  top.removeEventListener("click", onClick);
5050
5190
  top.removeEventListener("contextmenu", onClick);
@@ -5084,7 +5224,10 @@
5084
5224
  "data-[inset=true]:pl-8",
5085
5225
  "[&_svg]:pointer-events-none",
5086
5226
  "[&_svg]:shrink-0",
5087
- "[&_svg:not([class*='size-'])]:size-4"
5227
+ "[&_svg:not([class*='size-'])]:size-4",
5228
+ "[&>a]:no-underline",
5229
+ "[&>a]:text-inherit",
5230
+ "[&>a]:size-full"
5088
5231
  );
5089
5232
  el.setAttribute("role", "menuitem");
5090
5233
  el.setAttribute("tabindex", "-1");
@@ -5498,8 +5641,8 @@
5498
5641
  el.setAttribute("aria-atomic", "false");
5499
5642
  el.setAttribute("data-slot", "notification-overlay");
5500
5643
  const commonListClasses = ["flex", "flex-col", "py-4", "p-10", "gap-4", "overflow-visible", "size-full"];
5501
- const commonTopClasses = ["[mask-image:linear-gradient(to_bottom,black_80%,transparent)]", "row-1"];
5502
- const commonBottomClasses = ["[mask-image:linear-gradient(to_top,black_80%,transparent)]", "row-2"];
5644
+ const commonTopClasses = ["mask-[linear-gradient(to_bottom,black_85%,transparent)]", "row-1"];
5645
+ const commonBottomClasses = ["mask-[linear-gradient(to_top,black_85%,transparent)]", "row-2"];
5503
5646
  const olTopLeft = document.createElement("ol");
5504
5647
  olTopLeft.classList.add(...commonListClasses, ...commonTopClasses, "max-lg:hidden", "items-start");
5505
5648
  olTopLeft.setAttribute("tabindex", "-1");
@@ -9152,8 +9295,13 @@
9152
9295
  if (!storageKey) return;
9153
9296
  if (saveTimer) clearTimeout(saveTimer);
9154
9297
  saveTimer = setTimeout(() => {
9298
+ const usable = usableSize();
9299
+ if (usable <= 0) {
9300
+ saveTimer = null;
9301
+ return;
9302
+ }
9155
9303
  const visible = panels.filter((p) => !p.hidden);
9156
- const sizes = visible.map((p) => p.size / usableSize());
9304
+ const sizes = visible.map((p) => p.size / usable);
9157
9305
  localStorage.setItem(storageKey, JSON.stringify(sizes));
9158
9306
  saveTimer = null;
9159
9307
  }, SAVE_DELAY);
@@ -9188,26 +9336,44 @@
9188
9336
  const total = usableSize();
9189
9337
  if (!initialized) {
9190
9338
  initialized = true;
9191
- const visible2 = panels.filter((p) => !p.hidden);
9192
- const stored = loadSizes();
9193
- if (stored && stored.length === visible2.length) {
9194
- visible2.forEach((p, i) => {
9195
- p.size = stored[i] * usableSize();
9196
- p.explicit = true;
9197
- });
9198
- } else {
9199
- const explicitTotal = visible2.filter((p) => p.explicit).reduce((sum, p) => sum + p.declaredSize, 0);
9200
- const autoPanels = visible2.filter((p) => !p.explicit);
9201
- const remaining = total - explicitTotal;
9202
- const share = autoPanels.length ? remaining / autoPanels.length : 0;
9203
- visible2.forEach((p) => {
9204
- if (p.explicit) {
9205
- p.size = p.declaredSize;
9339
+ const anyRestore = visible.some((p) => p.restoreFraction != null);
9340
+ if (anyRestore) {
9341
+ const restoreFractionSum = visible.reduce((sum, p) => sum + (p.restoreFraction ?? 0), 0);
9342
+ const remainingSpace = total * (1 - restoreFractionSum);
9343
+ const nonRestorePanels = visible.filter((p) => p.restoreFraction == null);
9344
+ const nonRestoreDeclaredTotal = nonRestorePanels.reduce((s, p) => s + (p.declaredSize ?? 0), 0);
9345
+ visible.forEach((p) => {
9346
+ if (p.restoreFraction != null) {
9347
+ p.size = p.restoreFraction * total;
9348
+ p.explicit = true;
9349
+ p.restoreFraction = null;
9350
+ } else if (nonRestoreDeclaredTotal > 0) {
9351
+ p.size = (p.declaredSize ?? 0) / nonRestoreDeclaredTotal * remainingSpace;
9206
9352
  } else {
9207
- p.size = share;
9353
+ p.size = nonRestorePanels.length > 0 ? remainingSpace / nonRestorePanels.length : 0;
9208
9354
  }
9209
- p.size = Math.min(Math.max(p.size ?? share, p.min), p.max);
9210
9355
  });
9356
+ } else {
9357
+ const stored = loadSizes();
9358
+ if (stored && stored.length === visible.length) {
9359
+ visible.forEach((p, i) => {
9360
+ p.size = stored[i] * usableSize();
9361
+ p.explicit = true;
9362
+ });
9363
+ } else {
9364
+ const explicitTotal = visible.filter((p) => p.explicit).reduce((sum, p) => sum + p.declaredSize, 0);
9365
+ const autoPanels = visible.filter((p) => !p.explicit);
9366
+ const remaining = total - explicitTotal;
9367
+ const share = autoPanels.length ? remaining / autoPanels.length : 0;
9368
+ visible.forEach((p) => {
9369
+ if (p.explicit) {
9370
+ p.size = p.declaredSize;
9371
+ } else {
9372
+ p.size = share;
9373
+ }
9374
+ p.size = Math.min(Math.max(p.size ?? share, p.min), p.max);
9375
+ });
9376
+ }
9211
9377
  }
9212
9378
  }
9213
9379
  visible.forEach((p) => {
@@ -9220,6 +9386,10 @@
9220
9386
  let delta = total - currentTotal;
9221
9387
  if (Math.abs(delta) < DELTA_ABS) {
9222
9388
  visible.forEach((p) => p.apply());
9389
+ if (total > 0)
9390
+ visible.forEach((p) => {
9391
+ p.savedFraction = p.size / total;
9392
+ });
9223
9393
  return;
9224
9394
  }
9225
9395
  let flexible = visible.filter((p) => {
@@ -9253,6 +9423,10 @@
9253
9423
  if (Math.abs(consumed) < DELTA_ABS) break;
9254
9424
  }
9255
9425
  visible.forEach((p) => p.apply());
9426
+ if (total > 0)
9427
+ visible.forEach((p) => {
9428
+ p.savedFraction = p.size / total;
9429
+ });
9256
9430
  };
9257
9431
  let layoutFrame = null;
9258
9432
  const queueLayout = () => {
@@ -9287,7 +9461,6 @@
9287
9461
  queueLayout();
9288
9462
  },
9289
9463
  panelHidden() {
9290
- initialized = false;
9291
9464
  refreshGutters();
9292
9465
  queueLayout();
9293
9466
  },
@@ -9298,6 +9471,9 @@
9298
9471
  panelChange() {
9299
9472
  queueLayout();
9300
9473
  },
9474
+ resetInit() {
9475
+ initialized = false;
9476
+ },
9301
9477
  normalize,
9302
9478
  saveSizes
9303
9479
  };
@@ -9461,6 +9637,9 @@
9461
9637
  max: split._h_split.normalize(el.getAttribute("data-max")) ?? Infinity,
9462
9638
  collapsed: false,
9463
9639
  prevSize: null,
9640
+ prevHiddenFraction: null,
9641
+ savedFraction: null,
9642
+ restoreFraction: null,
9464
9643
  apply() {
9465
9644
  el.style.flexBasis = `${this.size.toFixed(2)}px`;
9466
9645
  if (split._h_split.state.isBorder) {
@@ -9565,7 +9744,7 @@
9565
9744
  gutter.addEventListener("pointerdown", drag);
9566
9745
  const collapse = () => {
9567
9746
  if (panel.collapsed) return;
9568
- panel.prevSize = panel.size;
9747
+ panel.prevSize = panel.size > (panel.min ?? 0) ? panel.size : panel.declaredSize;
9569
9748
  panel.size = panel.min ?? 0;
9570
9749
  panel.collapsed = true;
9571
9750
  panel.explicit = true;
@@ -9589,19 +9768,32 @@
9589
9768
  panel.explicit = true;
9590
9769
  split._h_split.panelChange();
9591
9770
  };
9771
+ const setState = () => {
9772
+ if (panel.hidden) {
9773
+ el.classList.add("hidden");
9774
+ } else {
9775
+ el.classList.remove("hidden");
9776
+ }
9777
+ split._h_split.panelHidden();
9778
+ };
9779
+ setState();
9592
9780
  const observer = new MutationObserver((mutations) => {
9593
9781
  mutations.forEach((mutation) => {
9594
9782
  if (mutation.attributeName === "data-gutterless") {
9595
9783
  gutterless = el.getAttribute("data-gutterless") === "true";
9596
9784
  split._h_split.gutterHidden();
9597
9785
  } else if (mutation.attributeName === "data-hidden") {
9598
- panel.hidden = el.getAttribute("data-hidden") === "true";
9599
- if (panel.hidden) {
9600
- el.classList.add("hidden");
9601
- } else {
9602
- el.classList.remove("hidden");
9786
+ const newHidden = el.getAttribute("data-hidden") === "true";
9787
+ if (!panel.hidden && newHidden) {
9788
+ panel.prevHiddenFraction = panel.savedFraction;
9789
+ } else if (panel.hidden && !newHidden) {
9790
+ if (panel.prevHiddenFraction != null) {
9791
+ panel.restoreFraction = panel.prevHiddenFraction;
9792
+ }
9793
+ split._h_split.resetInit();
9603
9794
  }
9604
- split._h_split.panelHidden();
9795
+ panel.hidden = newHidden;
9796
+ setState();
9605
9797
  } else if (mutation.attributeName === "data-locked") {
9606
9798
  panel.setLocked();
9607
9799
  } else {
@@ -11574,7 +11766,7 @@
11574
11766
  }
11575
11767
 
11576
11768
  // package.json
11577
- var version = "1.10.2";
11769
+ var version = "1.11.1";
11578
11770
 
11579
11771
  // src/index.js
11580
11772
  window.Harmonia = { getBreakpointListener, addColorSchemeListener, getColorScheme, removeColorSchemeListener, setColorScheme, getSystemColorScheme, version };
@@ -11583,6 +11775,7 @@
11583
11775
  window.Alpine.plugin(alert_default);
11584
11776
  window.Alpine.plugin(avatar_default);
11585
11777
  window.Alpine.plugin(badge_default);
11778
+ window.Alpine.plugin(breadcrumb_default);
11586
11779
  window.Alpine.plugin(button_default);
11587
11780
  window.Alpine.plugin(calendar_default);
11588
11781
  window.Alpine.plugin(card_default);