@fluix-ui/vanilla 0.0.8 → 0.0.9
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.cjs +1059 -1220
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -16
- package/dist/index.d.ts +1 -16
- package/dist/index.global.js +1235 -1283
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +1060 -1221
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.global.js
CHANGED
|
@@ -68,7 +68,7 @@ var Fluix = (function (exports) {
|
|
|
68
68
|
samples.push([t, 1]);
|
|
69
69
|
return samples;
|
|
70
70
|
}
|
|
71
|
-
function animateSpring(
|
|
71
|
+
function animateSpring(el2, properties, config) {
|
|
72
72
|
const samples = simulateSpring(config);
|
|
73
73
|
const totalTime = samples[samples.length - 1][0];
|
|
74
74
|
const durationMs = Math.round(totalTime * 1e3);
|
|
@@ -85,7 +85,7 @@ var Fluix = (function (exports) {
|
|
|
85
85
|
keyframes.push(frame);
|
|
86
86
|
}
|
|
87
87
|
try {
|
|
88
|
-
return
|
|
88
|
+
return el2.animate(keyframes, {
|
|
89
89
|
duration: durationMs,
|
|
90
90
|
fill: "forwards",
|
|
91
91
|
easing: "linear"
|
|
@@ -216,13 +216,17 @@ var Fluix = (function (exports) {
|
|
|
216
216
|
});
|
|
217
217
|
}
|
|
218
218
|
function dismiss(id) {
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
219
|
+
let shouldScheduleRemoval = false;
|
|
220
|
+
store.update((prev) => {
|
|
221
|
+
const item = prev.toasts.find((t) => t.id === id);
|
|
222
|
+
if (!item || item.exiting) return prev;
|
|
223
|
+
shouldScheduleRemoval = true;
|
|
224
|
+
return {
|
|
225
|
+
...prev,
|
|
226
|
+
toasts: prev.toasts.map((t) => t.id === id ? { ...t, exiting: true } : t)
|
|
227
|
+
};
|
|
228
|
+
});
|
|
229
|
+
if (!shouldScheduleRemoval) return;
|
|
226
230
|
const timer = setTimeout(() => {
|
|
227
231
|
exitTimers.delete(id);
|
|
228
232
|
store.update((prev) => ({
|
|
@@ -233,16 +237,20 @@ var Fluix = (function (exports) {
|
|
|
233
237
|
exitTimers.set(id, timer);
|
|
234
238
|
}
|
|
235
239
|
function clear(position) {
|
|
236
|
-
store.update((prev) =>
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
+
store.update((prev) => {
|
|
241
|
+
if (prev.toasts.length === 0) return prev;
|
|
242
|
+
const filtered = position ? prev.toasts.filter((t) => t.position !== position) : [];
|
|
243
|
+
if (filtered.length === prev.toasts.length) return prev;
|
|
244
|
+
return { ...prev, toasts: filtered };
|
|
245
|
+
});
|
|
240
246
|
}
|
|
241
247
|
function configure(config) {
|
|
242
|
-
store.update((prev) =>
|
|
243
|
-
...prev,
|
|
244
|
-
|
|
245
|
-
|
|
248
|
+
store.update((prev) => {
|
|
249
|
+
const merged = { ...prev.config, ...config };
|
|
250
|
+
const keys = Object.keys(merged);
|
|
251
|
+
if (keys.every((k) => prev.config[k] === merged[k])) return prev;
|
|
252
|
+
return { ...prev, config: merged };
|
|
253
|
+
});
|
|
246
254
|
}
|
|
247
255
|
function destroy() {
|
|
248
256
|
for (const timer of exitTimers.values()) clearTimeout(timer);
|
|
@@ -492,7 +500,12 @@ var Fluix = (function (exports) {
|
|
|
492
500
|
});
|
|
493
501
|
}
|
|
494
502
|
function configure(config) {
|
|
495
|
-
store.update((prev) =>
|
|
503
|
+
store.update((prev) => {
|
|
504
|
+
const merged = { ...prev.config, ...config };
|
|
505
|
+
const keys = Object.keys(merged);
|
|
506
|
+
if (keys.every((k) => prev.config[k] === merged[k])) return prev;
|
|
507
|
+
return { ...prev, config: merged };
|
|
508
|
+
});
|
|
496
509
|
}
|
|
497
510
|
function destroy() {
|
|
498
511
|
}
|
|
@@ -694,7 +707,11 @@ var Fluix = (function (exports) {
|
|
|
694
707
|
if (!a || !b) return false;
|
|
695
708
|
return a.x === b.x && a.y === b.y && a.width === b.width && a.height === b.height && a.radius === b.radius && a.visible === b.visible;
|
|
696
709
|
}
|
|
710
|
+
var springCache = /* @__PURE__ */ new Map();
|
|
697
711
|
function simulateSpringValues(config) {
|
|
712
|
+
const key = `${config.stiffness}-${config.damping}-${config.mass}`;
|
|
713
|
+
const cached = springCache.get(key);
|
|
714
|
+
if (cached) return cached;
|
|
698
715
|
const { stiffness, damping, mass } = config;
|
|
699
716
|
const dt = 1 / 120;
|
|
700
717
|
const maxDuration = 3;
|
|
@@ -714,6 +731,7 @@ var Fluix = (function (exports) {
|
|
|
714
731
|
if (Math.abs(position - 1) < 1e-3 && Math.abs(velocity) < 1e-3) break;
|
|
715
732
|
}
|
|
716
733
|
samples.push(1);
|
|
734
|
+
springCache.set(key, samples);
|
|
717
735
|
return samples;
|
|
718
736
|
}
|
|
719
737
|
function lerp(a, b, t) {
|
|
@@ -923,74 +941,146 @@ var Fluix = (function (exports) {
|
|
|
923
941
|
requestAnimationFrame(tick);
|
|
924
942
|
return handle;
|
|
925
943
|
}
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
944
|
+
function setRectAttrs(el2, x, y, w, h, r) {
|
|
945
|
+
el2.setAttribute("x", String(x));
|
|
946
|
+
el2.setAttribute("y", String(y));
|
|
947
|
+
el2.setAttribute("width", String(Math.max(0, w)));
|
|
948
|
+
el2.setAttribute("height", String(Math.max(0, h)));
|
|
949
|
+
el2.setAttribute("rx", String(Math.max(0, r)));
|
|
950
|
+
el2.setAttribute("ry", String(Math.max(0, r)));
|
|
951
|
+
}
|
|
952
|
+
function animatePillMorph(rect, ghost, from, to, spring, _orientation) {
|
|
953
|
+
const growSamples = simulateSpringValues({
|
|
954
|
+
stiffness: spring.stiffness * 1.4,
|
|
955
|
+
damping: spring.damping * 1.2,
|
|
934
956
|
mass: spring.mass
|
|
935
957
|
});
|
|
936
|
-
const
|
|
937
|
-
const
|
|
938
|
-
const totalMs =
|
|
958
|
+
const growCount = growSamples.length;
|
|
959
|
+
const growMs = growCount / 120 * 1e3;
|
|
960
|
+
const totalMs = growMs;
|
|
961
|
+
const ghostDuration = totalMs * 0.8;
|
|
939
962
|
const startTime = performance.now();
|
|
940
963
|
let cancelled = false;
|
|
941
964
|
const handle = {
|
|
942
965
|
onfinish: null,
|
|
943
966
|
cancel() {
|
|
944
967
|
cancelled = true;
|
|
968
|
+
if (ghost) ghost.setAttribute("opacity", "0");
|
|
945
969
|
}
|
|
946
970
|
};
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
rect.setAttribute("width", String(w));
|
|
951
|
-
rect.setAttribute("height", String(h));
|
|
952
|
-
rect.setAttribute("rx", String(r));
|
|
953
|
-
rect.setAttribute("ry", String(r));
|
|
971
|
+
if (ghost) {
|
|
972
|
+
setRectAttrs(ghost, from.x, from.y, from.width, from.height, from.radius);
|
|
973
|
+
ghost.setAttribute("opacity", "1");
|
|
954
974
|
}
|
|
975
|
+
const toCx = to.x + to.width / 2;
|
|
976
|
+
const toCy = to.y + to.height / 2;
|
|
977
|
+
setRectAttrs(rect, toCx, toCy, 0, 0, 0);
|
|
955
978
|
function tick() {
|
|
956
979
|
if (cancelled) return;
|
|
957
980
|
const elapsed = performance.now() - startTime;
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
)
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
lerp(
|
|
976
|
-
to.height,
|
|
977
|
-
|
|
978
|
-
|
|
981
|
+
const progress = Math.min(elapsed / totalMs, 1);
|
|
982
|
+
const idx = Math.min(Math.floor(progress * (growCount - 1)), growCount - 1);
|
|
983
|
+
const gt = growSamples[idx];
|
|
984
|
+
setRectAttrs(
|
|
985
|
+
rect,
|
|
986
|
+
lerp(toCx, to.x, gt),
|
|
987
|
+
lerp(toCy, to.y, gt),
|
|
988
|
+
lerp(0, to.width, gt),
|
|
989
|
+
lerp(0, to.height, gt),
|
|
990
|
+
lerp(0, to.radius, gt)
|
|
991
|
+
);
|
|
992
|
+
if (ghost) {
|
|
993
|
+
if (elapsed < ghostDuration) {
|
|
994
|
+
const raw = elapsed / ghostDuration;
|
|
995
|
+
const shrink = raw * raw;
|
|
996
|
+
const scale = 1 - shrink;
|
|
997
|
+
const drift = easeOutCubic(raw) * 0.25;
|
|
998
|
+
const cx = lerp(from.x + from.width / 2, to.x + to.width / 2, drift);
|
|
999
|
+
const cy = lerp(from.y + from.height / 2, to.y + to.height / 2, drift);
|
|
1000
|
+
const w = from.width * scale;
|
|
1001
|
+
const h = from.height * scale;
|
|
1002
|
+
setRectAttrs(
|
|
1003
|
+
ghost,
|
|
1004
|
+
cx - w / 2,
|
|
1005
|
+
cy - h / 2,
|
|
1006
|
+
w,
|
|
1007
|
+
h,
|
|
1008
|
+
from.radius * scale
|
|
1009
|
+
);
|
|
1010
|
+
} else {
|
|
1011
|
+
ghost.setAttribute("opacity", "0");
|
|
1012
|
+
}
|
|
979
1013
|
}
|
|
980
|
-
if (
|
|
1014
|
+
if (progress < 1) {
|
|
981
1015
|
requestAnimationFrame(tick);
|
|
982
1016
|
} else {
|
|
1017
|
+
if (ghost) ghost.setAttribute("opacity", "0");
|
|
983
1018
|
handle.onfinish?.();
|
|
984
1019
|
}
|
|
985
1020
|
}
|
|
986
1021
|
requestAnimationFrame(tick);
|
|
987
1022
|
return handle;
|
|
988
1023
|
}
|
|
1024
|
+
function buildPillWaypoints(root, oldId, newId, padding, variant, orientation, from, to) {
|
|
1025
|
+
if (!oldId || !newId) return [from, to];
|
|
1026
|
+
const items = Array.from(root.querySelectorAll(ITEM_SELECTOR));
|
|
1027
|
+
const ids = items.map((el2) => el2.dataset["menuId"] ?? "");
|
|
1028
|
+
const oldIdx = ids.indexOf(oldId);
|
|
1029
|
+
const newIdx = ids.indexOf(newId);
|
|
1030
|
+
if (oldIdx === -1 || newIdx === -1 || Math.abs(newIdx - oldIdx) <= 1) {
|
|
1031
|
+
return [from, to];
|
|
1032
|
+
}
|
|
1033
|
+
const step = newIdx > oldIdx ? 1 : -1;
|
|
1034
|
+
const waypoints = [from];
|
|
1035
|
+
for (let i = oldIdx + step; i !== newIdx; i += step) {
|
|
1036
|
+
const id = ids[i];
|
|
1037
|
+
const frame = readItemFrame(root, id, padding, variant, orientation);
|
|
1038
|
+
if (frame) waypoints.push(frame);
|
|
1039
|
+
}
|
|
1040
|
+
waypoints.push(to);
|
|
1041
|
+
return waypoints;
|
|
1042
|
+
}
|
|
1043
|
+
function chainPillMorphs(rect, ghost, waypoints, spring, orientation) {
|
|
1044
|
+
if (waypoints.length <= 2) {
|
|
1045
|
+
return animatePillMorph(rect, ghost, waypoints[0], waypoints[waypoints.length - 1], spring);
|
|
1046
|
+
}
|
|
1047
|
+
const steps = waypoints.length - 1;
|
|
1048
|
+
let currentStep = 0;
|
|
1049
|
+
let activeAnim = null;
|
|
1050
|
+
const stepSpring = {
|
|
1051
|
+
stiffness: spring.stiffness * (1 + steps * 0.6),
|
|
1052
|
+
damping: spring.damping * (1 + steps * 0.3),
|
|
1053
|
+
mass: spring.mass
|
|
1054
|
+
};
|
|
1055
|
+
const handle = {
|
|
1056
|
+
onfinish: null,
|
|
1057
|
+
cancel() {
|
|
1058
|
+
activeAnim?.cancel();
|
|
1059
|
+
activeAnim = null;
|
|
1060
|
+
}
|
|
1061
|
+
};
|
|
1062
|
+
function runStep() {
|
|
1063
|
+
if (currentStep >= steps) {
|
|
1064
|
+
handle.onfinish?.();
|
|
1065
|
+
return;
|
|
1066
|
+
}
|
|
1067
|
+
const from = waypoints[currentStep];
|
|
1068
|
+
const to = waypoints[currentStep + 1];
|
|
1069
|
+
activeAnim = animatePillMorph(rect, ghost, from, to, stepSpring);
|
|
1070
|
+
activeAnim.onfinish = () => {
|
|
1071
|
+
currentStep++;
|
|
1072
|
+
setRectAttrs(rect, to.x, to.y, to.width, to.height, to.radius);
|
|
1073
|
+
runStep();
|
|
1074
|
+
};
|
|
1075
|
+
}
|
|
1076
|
+
runStep();
|
|
1077
|
+
return handle;
|
|
1078
|
+
}
|
|
989
1079
|
function connectMenu(options) {
|
|
990
1080
|
const spring = options.spring ?? FLUIX_SPRING;
|
|
991
|
-
const padding = options.padding ?? 6;
|
|
992
1081
|
const variant = options.variant;
|
|
993
1082
|
const orientation = options.orientation;
|
|
1083
|
+
const padding = options.padding ?? (variant === "pill" ? 0 : 6);
|
|
994
1084
|
const cleanups = [];
|
|
995
1085
|
let currentAnimation = null;
|
|
996
1086
|
let lastFrame = null;
|
|
@@ -1002,11 +1092,11 @@ var Fluix = (function (exports) {
|
|
|
1002
1092
|
let animNewId = null;
|
|
1003
1093
|
let animPhase = null;
|
|
1004
1094
|
function setItemState(id, state) {
|
|
1005
|
-
const
|
|
1095
|
+
const el2 = options.root.querySelector(
|
|
1006
1096
|
`${ITEM_SELECTOR}[data-menu-id="${CSS.escape(id)}"]`
|
|
1007
1097
|
);
|
|
1008
|
-
if (
|
|
1009
|
-
|
|
1098
|
+
if (el2 && el2.dataset["state"] !== state) {
|
|
1099
|
+
el2.dataset["state"] = state;
|
|
1010
1100
|
}
|
|
1011
1101
|
}
|
|
1012
1102
|
function enforceAnimStates() {
|
|
@@ -1026,6 +1116,9 @@ var Fluix = (function (exports) {
|
|
|
1026
1116
|
}
|
|
1027
1117
|
function apply(frame) {
|
|
1028
1118
|
applyFrame(options.indicator, frame, variant, orientation);
|
|
1119
|
+
if (options.ghostIndicator) {
|
|
1120
|
+
options.ghostIndicator.setAttribute("opacity", "0");
|
|
1121
|
+
}
|
|
1029
1122
|
}
|
|
1030
1123
|
const updateIndicator = (immediate = false) => {
|
|
1031
1124
|
const activeId = options.getActiveId();
|
|
@@ -1138,11 +1231,23 @@ var Fluix = (function (exports) {
|
|
|
1138
1231
|
onEnterStart
|
|
1139
1232
|
);
|
|
1140
1233
|
} else {
|
|
1141
|
-
|
|
1142
|
-
options.
|
|
1234
|
+
const waypoints = buildPillWaypoints(
|
|
1235
|
+
options.root,
|
|
1236
|
+
oldActiveId,
|
|
1237
|
+
newActiveId,
|
|
1238
|
+
padding,
|
|
1239
|
+
variant,
|
|
1240
|
+
orientation,
|
|
1143
1241
|
from,
|
|
1144
|
-
to
|
|
1145
|
-
|
|
1242
|
+
to
|
|
1243
|
+
);
|
|
1244
|
+
const springConfig = { stiffness: spring.stiffness ?? 170, damping: spring.damping ?? 18, mass: spring.mass ?? 1 };
|
|
1245
|
+
const ghost = options.ghostIndicator ?? null;
|
|
1246
|
+
animation = chainPillMorphs(
|
|
1247
|
+
options.indicator,
|
|
1248
|
+
ghost,
|
|
1249
|
+
waypoints,
|
|
1250
|
+
springConfig
|
|
1146
1251
|
);
|
|
1147
1252
|
}
|
|
1148
1253
|
if (!animation) {
|
|
@@ -1167,7 +1272,7 @@ var Fluix = (function (exports) {
|
|
|
1167
1272
|
}
|
|
1168
1273
|
};
|
|
1169
1274
|
};
|
|
1170
|
-
const
|
|
1275
|
+
const sync2 = (immediate = false) => {
|
|
1171
1276
|
cancelAnimationFrame(rafId);
|
|
1172
1277
|
rafId = requestAnimationFrame(() => updateIndicator(immediate));
|
|
1173
1278
|
};
|
|
@@ -1185,7 +1290,7 @@ var Fluix = (function (exports) {
|
|
|
1185
1290
|
cleanups.push(() => options.root.removeEventListener("click", handleClick));
|
|
1186
1291
|
const scheduleSync = () => {
|
|
1187
1292
|
if (animPhase) return;
|
|
1188
|
-
|
|
1293
|
+
sync2(false);
|
|
1189
1294
|
};
|
|
1190
1295
|
resizeObserver = new ResizeObserver(scheduleSync);
|
|
1191
1296
|
resizeObserver.observe(options.root);
|
|
@@ -1196,18 +1301,24 @@ var Fluix = (function (exports) {
|
|
|
1196
1301
|
resizeObserver?.disconnect();
|
|
1197
1302
|
resizeObserver = null;
|
|
1198
1303
|
});
|
|
1199
|
-
|
|
1200
|
-
if (animPhase) {
|
|
1201
|
-
enforceAnimStates();
|
|
1202
|
-
return;
|
|
1203
|
-
}
|
|
1304
|
+
function rebuildResizeObserver() {
|
|
1204
1305
|
if (!resizeObserver) return;
|
|
1205
1306
|
resizeObserver.disconnect();
|
|
1206
1307
|
resizeObserver.observe(options.root);
|
|
1207
1308
|
for (const item of options.root.querySelectorAll(ITEM_SELECTOR)) {
|
|
1208
1309
|
resizeObserver.observe(item);
|
|
1209
1310
|
}
|
|
1210
|
-
|
|
1311
|
+
}
|
|
1312
|
+
mutationObserver = new MutationObserver((mutations) => {
|
|
1313
|
+
if (animPhase) {
|
|
1314
|
+
enforceAnimStates();
|
|
1315
|
+
return;
|
|
1316
|
+
}
|
|
1317
|
+
const hasStructuralChange = mutations.some((m) => m.type === "childList");
|
|
1318
|
+
if (hasStructuralChange) {
|
|
1319
|
+
rebuildResizeObserver();
|
|
1320
|
+
}
|
|
1321
|
+
sync2(false);
|
|
1211
1322
|
});
|
|
1212
1323
|
mutationObserver.observe(options.root, {
|
|
1213
1324
|
childList: true,
|
|
@@ -1219,9 +1330,9 @@ var Fluix = (function (exports) {
|
|
|
1219
1330
|
mutationObserver?.disconnect();
|
|
1220
1331
|
mutationObserver = null;
|
|
1221
1332
|
});
|
|
1222
|
-
|
|
1333
|
+
sync2(true);
|
|
1223
1334
|
return {
|
|
1224
|
-
sync,
|
|
1335
|
+
sync: sync2,
|
|
1225
1336
|
destroy() {
|
|
1226
1337
|
cancelAnimationFrame(rafId);
|
|
1227
1338
|
if (currentAnimation) {
|
|
@@ -1234,125 +1345,99 @@ var Fluix = (function (exports) {
|
|
|
1234
1345
|
};
|
|
1235
1346
|
}
|
|
1236
1347
|
|
|
1237
|
-
// src/
|
|
1238
|
-
var WIDTH = 350;
|
|
1239
|
-
var HEIGHT = 40;
|
|
1240
|
-
var PILL_PADDING = 10;
|
|
1241
|
-
var MIN_EXPAND_RATIO = 2.25;
|
|
1242
|
-
var HEADER_EXIT_MS = 600 * 0.7;
|
|
1243
|
-
var BODY_MERGE_OVERLAP = 6;
|
|
1348
|
+
// src/shared.ts
|
|
1244
1349
|
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
1350
|
+
var GOO_MATRIX = "1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 20 -10";
|
|
1351
|
+
function applyAttrs(el2, attrs) {
|
|
1352
|
+
for (const [key, value] of Object.entries(attrs)) {
|
|
1353
|
+
el2.setAttribute(key, value);
|
|
1354
|
+
}
|
|
1355
|
+
}
|
|
1356
|
+
function clearChildren(el2) {
|
|
1357
|
+
while (el2.firstChild) el2.removeChild(el2.firstChild);
|
|
1358
|
+
}
|
|
1359
|
+
function createGooeyFilter(filterId, blur2) {
|
|
1360
|
+
const defs = document.createElementNS(SVG_NS, "defs");
|
|
1361
|
+
const filter = document.createElementNS(SVG_NS, "filter");
|
|
1362
|
+
filter.setAttribute("id", filterId);
|
|
1363
|
+
for (const [k, v] of Object.entries({ x: "-50%", y: "-50%", width: "200%", height: "200%" })) {
|
|
1364
|
+
filter.setAttribute(k, v);
|
|
1365
|
+
}
|
|
1366
|
+
filter.setAttribute("color-interpolation-filters", "sRGB");
|
|
1367
|
+
const feBlur = document.createElementNS(SVG_NS, "feGaussianBlur");
|
|
1368
|
+
feBlur.setAttribute("in", "SourceGraphic");
|
|
1369
|
+
feBlur.setAttribute("stdDeviation", String(blur2));
|
|
1370
|
+
feBlur.setAttribute("result", "blur");
|
|
1371
|
+
const feCM = document.createElementNS(SVG_NS, "feColorMatrix");
|
|
1372
|
+
feCM.setAttribute("in", "blur");
|
|
1373
|
+
feCM.setAttribute("type", "matrix");
|
|
1374
|
+
feCM.setAttribute("values", GOO_MATRIX);
|
|
1375
|
+
feCM.setAttribute("result", "goo");
|
|
1376
|
+
const feComp = document.createElementNS(SVG_NS, "feComposite");
|
|
1377
|
+
feComp.setAttribute("in", "SourceGraphic");
|
|
1378
|
+
feComp.setAttribute("in2", "goo");
|
|
1379
|
+
feComp.setAttribute("operator", "atop");
|
|
1380
|
+
filter.appendChild(feBlur);
|
|
1381
|
+
filter.appendChild(feCM);
|
|
1382
|
+
filter.appendChild(feComp);
|
|
1383
|
+
defs.appendChild(filter);
|
|
1384
|
+
const g = document.createElementNS(SVG_NS, "g");
|
|
1385
|
+
g.setAttribute("filter", `url(#${filterId})`);
|
|
1386
|
+
return { g, defs, feBlur };
|
|
1387
|
+
}
|
|
1388
|
+
function zeroRect(el2) {
|
|
1389
|
+
for (const attr of ["x", "y", "width", "height", "rx", "ry"]) {
|
|
1390
|
+
el2.setAttribute(attr, "0");
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
|
|
1394
|
+
// src/toast/icons.ts
|
|
1395
|
+
function el(tag, attrs) {
|
|
1396
|
+
return { tag, attrs };
|
|
1397
|
+
}
|
|
1398
|
+
function line(x1, y1, x2, y2) {
|
|
1399
|
+
return el("line", { x1, y1, x2, y2 });
|
|
1400
|
+
}
|
|
1401
|
+
var ICON_DEFS = {
|
|
1402
|
+
success: { children: [el("polyline", { points: "20 6 9 17 4 12" })] },
|
|
1403
|
+
error: { children: [line("18", "6", "6", "18"), line("6", "6", "18", "18")] },
|
|
1404
|
+
warning: { children: [
|
|
1405
|
+
el("path", { d: "M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z" }),
|
|
1406
|
+
line("12", "9", "12", "13"),
|
|
1407
|
+
line("12", "17", "12.01", "17")
|
|
1408
|
+
] },
|
|
1409
|
+
info: { children: [
|
|
1410
|
+
el("circle", { cx: "12", cy: "12", r: "10" }),
|
|
1411
|
+
line("12", "16", "12", "12"),
|
|
1412
|
+
line("12", "8", "12.01", "8")
|
|
1413
|
+
] },
|
|
1414
|
+
loading: { spin: true, children: [
|
|
1415
|
+
line("12", "2", "12", "6"),
|
|
1416
|
+
line("12", "18", "12", "22"),
|
|
1417
|
+
line("4.93", "4.93", "7.76", "7.76"),
|
|
1418
|
+
line("16.24", "16.24", "19.07", "19.07"),
|
|
1419
|
+
line("2", "12", "6", "12"),
|
|
1420
|
+
line("18", "12", "22", "12"),
|
|
1421
|
+
line("4.93", "19.07", "7.76", "16.24"),
|
|
1422
|
+
line("16.24", "7.76", "19.07", "4.93")
|
|
1423
|
+
] },
|
|
1424
|
+
action: { children: [
|
|
1425
|
+
el("circle", { cx: "12", cy: "12", r: "10" }),
|
|
1426
|
+
el("polygon", { points: "10 8 16 12 10 16 10 8", fill: "currentColor", stroke: "none" })
|
|
1427
|
+
] }
|
|
1428
|
+
};
|
|
1245
1429
|
function createSvgIcon(state) {
|
|
1430
|
+
const def = ICON_DEFS[state];
|
|
1431
|
+
if (!def) return null;
|
|
1246
1432
|
const svg = document.createElementNS(SVG_NS, "svg");
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
svg.setAttribute("
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
svg.setAttribute("aria-hidden", "true");
|
|
1256
|
-
switch (state) {
|
|
1257
|
-
case "success": {
|
|
1258
|
-
const p = document.createElementNS(SVG_NS, "polyline");
|
|
1259
|
-
p.setAttribute("points", "20 6 9 17 4 12");
|
|
1260
|
-
svg.appendChild(p);
|
|
1261
|
-
break;
|
|
1262
|
-
}
|
|
1263
|
-
case "error": {
|
|
1264
|
-
const l1 = document.createElementNS(SVG_NS, "line");
|
|
1265
|
-
l1.setAttribute("x1", "18");
|
|
1266
|
-
l1.setAttribute("y1", "6");
|
|
1267
|
-
l1.setAttribute("x2", "6");
|
|
1268
|
-
l1.setAttribute("y2", "18");
|
|
1269
|
-
const l2 = document.createElementNS(SVG_NS, "line");
|
|
1270
|
-
l2.setAttribute("x1", "6");
|
|
1271
|
-
l2.setAttribute("y1", "6");
|
|
1272
|
-
l2.setAttribute("x2", "18");
|
|
1273
|
-
l2.setAttribute("y2", "18");
|
|
1274
|
-
svg.appendChild(l1);
|
|
1275
|
-
svg.appendChild(l2);
|
|
1276
|
-
break;
|
|
1277
|
-
}
|
|
1278
|
-
case "warning": {
|
|
1279
|
-
const path = document.createElementNS(SVG_NS, "path");
|
|
1280
|
-
path.setAttribute(
|
|
1281
|
-
"d",
|
|
1282
|
-
"M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"
|
|
1283
|
-
);
|
|
1284
|
-
const l1 = document.createElementNS(SVG_NS, "line");
|
|
1285
|
-
l1.setAttribute("x1", "12");
|
|
1286
|
-
l1.setAttribute("y1", "9");
|
|
1287
|
-
l1.setAttribute("x2", "12");
|
|
1288
|
-
l1.setAttribute("y2", "13");
|
|
1289
|
-
const l2 = document.createElementNS(SVG_NS, "line");
|
|
1290
|
-
l2.setAttribute("x1", "12");
|
|
1291
|
-
l2.setAttribute("y1", "17");
|
|
1292
|
-
l2.setAttribute("x2", "12.01");
|
|
1293
|
-
l2.setAttribute("y2", "17");
|
|
1294
|
-
svg.appendChild(path);
|
|
1295
|
-
svg.appendChild(l1);
|
|
1296
|
-
svg.appendChild(l2);
|
|
1297
|
-
break;
|
|
1298
|
-
}
|
|
1299
|
-
case "info": {
|
|
1300
|
-
const c = document.createElementNS(SVG_NS, "circle");
|
|
1301
|
-
c.setAttribute("cx", "12");
|
|
1302
|
-
c.setAttribute("cy", "12");
|
|
1303
|
-
c.setAttribute("r", "10");
|
|
1304
|
-
const l1 = document.createElementNS(SVG_NS, "line");
|
|
1305
|
-
l1.setAttribute("x1", "12");
|
|
1306
|
-
l1.setAttribute("y1", "16");
|
|
1307
|
-
l1.setAttribute("x2", "12");
|
|
1308
|
-
l1.setAttribute("y2", "12");
|
|
1309
|
-
const l2 = document.createElementNS(SVG_NS, "line");
|
|
1310
|
-
l2.setAttribute("x1", "12");
|
|
1311
|
-
l2.setAttribute("y1", "8");
|
|
1312
|
-
l2.setAttribute("x2", "12.01");
|
|
1313
|
-
l2.setAttribute("y2", "8");
|
|
1314
|
-
svg.appendChild(c);
|
|
1315
|
-
svg.appendChild(l1);
|
|
1316
|
-
svg.appendChild(l2);
|
|
1317
|
-
break;
|
|
1318
|
-
}
|
|
1319
|
-
case "loading": {
|
|
1320
|
-
svg.setAttribute("data-fluix-icon", "spin");
|
|
1321
|
-
const lines = [
|
|
1322
|
-
["12", "2", "12", "6"],
|
|
1323
|
-
["12", "18", "12", "22"],
|
|
1324
|
-
["4.93", "4.93", "7.76", "7.76"],
|
|
1325
|
-
["16.24", "16.24", "19.07", "19.07"],
|
|
1326
|
-
["2", "12", "6", "12"],
|
|
1327
|
-
["18", "12", "22", "12"],
|
|
1328
|
-
["4.93", "19.07", "7.76", "16.24"],
|
|
1329
|
-
["16.24", "7.76", "19.07", "4.93"]
|
|
1330
|
-
];
|
|
1331
|
-
for (const [x1, y1, x2, y2] of lines) {
|
|
1332
|
-
const l = document.createElementNS(SVG_NS, "line");
|
|
1333
|
-
l.setAttribute("x1", x1);
|
|
1334
|
-
l.setAttribute("y1", y1);
|
|
1335
|
-
l.setAttribute("x2", x2);
|
|
1336
|
-
l.setAttribute("y2", y2);
|
|
1337
|
-
svg.appendChild(l);
|
|
1338
|
-
}
|
|
1339
|
-
break;
|
|
1340
|
-
}
|
|
1341
|
-
case "action": {
|
|
1342
|
-
const c = document.createElementNS(SVG_NS, "circle");
|
|
1343
|
-
c.setAttribute("cx", "12");
|
|
1344
|
-
c.setAttribute("cy", "12");
|
|
1345
|
-
c.setAttribute("r", "10");
|
|
1346
|
-
const poly = document.createElementNS(SVG_NS, "polygon");
|
|
1347
|
-
poly.setAttribute("points", "10 8 16 12 10 16 10 8");
|
|
1348
|
-
poly.setAttribute("fill", "currentColor");
|
|
1349
|
-
poly.setAttribute("stroke", "none");
|
|
1350
|
-
svg.appendChild(c);
|
|
1351
|
-
svg.appendChild(poly);
|
|
1352
|
-
break;
|
|
1353
|
-
}
|
|
1354
|
-
default:
|
|
1355
|
-
return null;
|
|
1433
|
+
for (const [k, v] of Object.entries({ width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2.5", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true" })) {
|
|
1434
|
+
svg.setAttribute(k, v);
|
|
1435
|
+
}
|
|
1436
|
+
if (def.spin) svg.setAttribute("data-fluix-icon", "spin");
|
|
1437
|
+
for (const child of def.children) {
|
|
1438
|
+
const node = document.createElementNS(SVG_NS, child.tag);
|
|
1439
|
+
for (const [k, v] of Object.entries(child.attrs)) node.setAttribute(k, v);
|
|
1440
|
+
svg.appendChild(node);
|
|
1356
1441
|
}
|
|
1357
1442
|
return svg;
|
|
1358
1443
|
}
|
|
@@ -1372,77 +1457,27 @@ var Fluix = (function (exports) {
|
|
|
1372
1457
|
const svgIcon = createSvgIcon(state);
|
|
1373
1458
|
if (svgIcon) container.appendChild(svgIcon);
|
|
1374
1459
|
}
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
for (const [key, value] of Object.entries(attrs)) {
|
|
1382
|
-
el.setAttribute(key, value);
|
|
1383
|
-
}
|
|
1384
|
-
}
|
|
1385
|
-
function resolveOffsetValue(v) {
|
|
1386
|
-
return typeof v === "number" ? `${v}px` : v;
|
|
1387
|
-
}
|
|
1388
|
-
function applyViewportOffset(el, offset, position) {
|
|
1389
|
-
el.style.top = "";
|
|
1390
|
-
el.style.right = "";
|
|
1391
|
-
el.style.bottom = "";
|
|
1392
|
-
el.style.left = "";
|
|
1393
|
-
el.style.paddingLeft = "";
|
|
1394
|
-
el.style.paddingRight = "";
|
|
1395
|
-
if (offset == null) return;
|
|
1396
|
-
let top;
|
|
1397
|
-
let right;
|
|
1398
|
-
let bottom;
|
|
1399
|
-
let left;
|
|
1400
|
-
if (typeof offset === "number" || typeof offset === "string") {
|
|
1401
|
-
const v = resolveOffsetValue(offset);
|
|
1402
|
-
top = v;
|
|
1403
|
-
right = v;
|
|
1404
|
-
bottom = v;
|
|
1405
|
-
left = v;
|
|
1406
|
-
} else {
|
|
1407
|
-
if (offset.top != null) top = resolveOffsetValue(offset.top);
|
|
1408
|
-
if (offset.right != null) right = resolveOffsetValue(offset.right);
|
|
1409
|
-
if (offset.bottom != null) bottom = resolveOffsetValue(offset.bottom);
|
|
1410
|
-
if (offset.left != null) left = resolveOffsetValue(offset.left);
|
|
1411
|
-
}
|
|
1412
|
-
if (position.startsWith("top") && top) el.style.top = top;
|
|
1413
|
-
if (position.startsWith("bottom") && bottom) el.style.bottom = bottom;
|
|
1414
|
-
if (position.endsWith("right") && right) el.style.right = right;
|
|
1415
|
-
if (position.endsWith("left") && left) el.style.left = left;
|
|
1416
|
-
if (position.endsWith("center")) {
|
|
1417
|
-
if (left) el.style.paddingLeft = left;
|
|
1418
|
-
if (right) el.style.paddingRight = right;
|
|
1419
|
-
}
|
|
1420
|
-
}
|
|
1421
|
-
function setTimer(inst, fn, ms) {
|
|
1422
|
-
const id = setTimeout(() => {
|
|
1423
|
-
inst.timers.delete(id);
|
|
1424
|
-
fn();
|
|
1425
|
-
}, ms);
|
|
1426
|
-
inst.timers.add(id);
|
|
1427
|
-
return id;
|
|
1428
|
-
}
|
|
1460
|
+
|
|
1461
|
+
// src/toast/update.ts
|
|
1462
|
+
var PILL_PADDING = 10;
|
|
1463
|
+
var MIN_EXPAND_RATIO = 2.25;
|
|
1464
|
+
var HEADER_EXIT_MS = 600 * 0.7;
|
|
1465
|
+
var BODY_MERGE_OVERLAP = 6;
|
|
1429
1466
|
function computeLayout(item, inst) {
|
|
1430
1467
|
const { ready, expanded: isExpanded } = inst.localState;
|
|
1431
1468
|
const roundness = item.roundness ?? TOAST_DEFAULTS.roundness;
|
|
1432
|
-
const
|
|
1469
|
+
const blur2 = Math.min(10, Math.max(6, roundness * 0.45));
|
|
1433
1470
|
const hasDesc = Boolean(item.description) || Boolean(item.button);
|
|
1434
1471
|
const isLoading = item.state === "loading";
|
|
1435
1472
|
const open = hasDesc && isExpanded && !isLoading;
|
|
1436
|
-
const position =
|
|
1473
|
+
const position = getPillAlignLocal(item.position);
|
|
1437
1474
|
const edge = item.position.startsWith("top") ? "bottom" : "top";
|
|
1438
1475
|
const resolvedPillWidth = Math.max(inst.pillWidth || HEIGHT, HEIGHT);
|
|
1439
|
-
const pillHeight = HEIGHT +
|
|
1476
|
+
const pillHeight = HEIGHT + blur2 * 3;
|
|
1440
1477
|
const pillX = position === "right" ? WIDTH - resolvedPillWidth : position === "center" ? (WIDTH - resolvedPillWidth) / 2 : 0;
|
|
1441
1478
|
const minExpanded = HEIGHT * MIN_EXPAND_RATIO;
|
|
1442
1479
|
const rawExpanded = hasDesc ? Math.max(minExpanded, HEIGHT + inst.contentHeight) : minExpanded;
|
|
1443
|
-
if (open)
|
|
1444
|
-
inst.frozenExpanded = rawExpanded;
|
|
1445
|
-
}
|
|
1480
|
+
if (open) inst.frozenExpanded = rawExpanded;
|
|
1446
1481
|
const expanded = open ? rawExpanded : inst.frozenExpanded;
|
|
1447
1482
|
const expandedContent = Math.max(0, expanded - HEIGHT);
|
|
1448
1483
|
const svgHeight = hasDesc ? Math.max(expanded, minExpanded) : HEIGHT;
|
|
@@ -1450,7 +1485,7 @@ var Fluix = (function (exports) {
|
|
|
1450
1485
|
ready,
|
|
1451
1486
|
isExpanded,
|
|
1452
1487
|
roundness,
|
|
1453
|
-
blur,
|
|
1488
|
+
blur: blur2,
|
|
1454
1489
|
hasDesc,
|
|
1455
1490
|
isLoading,
|
|
1456
1491
|
open,
|
|
@@ -1465,244 +1500,19 @@ var Fluix = (function (exports) {
|
|
|
1465
1500
|
svgHeight
|
|
1466
1501
|
};
|
|
1467
1502
|
}
|
|
1468
|
-
function
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
const initialSvgHeight = hasDesc ? minExpanded : HEIGHT;
|
|
1479
|
-
const svg = document.createElementNS(SVG_NS, "svg");
|
|
1480
|
-
svg.setAttribute("data-fluix-svg", "");
|
|
1481
|
-
svg.setAttribute("width", String(WIDTH));
|
|
1482
|
-
svg.setAttribute("height", String(initialSvgHeight));
|
|
1483
|
-
svg.setAttribute("viewBox", `0 0 ${WIDTH} ${initialSvgHeight}`);
|
|
1484
|
-
svg.setAttribute("aria-hidden", "true");
|
|
1485
|
-
const defs = document.createElementNS(SVG_NS, "defs");
|
|
1486
|
-
const filter = document.createElementNS(SVG_NS, "filter");
|
|
1487
|
-
filter.setAttribute("id", filterId);
|
|
1488
|
-
filter.setAttribute("x", "-20%");
|
|
1489
|
-
filter.setAttribute("y", "-20%");
|
|
1490
|
-
filter.setAttribute("width", "140%");
|
|
1491
|
-
filter.setAttribute("height", "140%");
|
|
1492
|
-
filter.setAttribute("color-interpolation-filters", "sRGB");
|
|
1493
|
-
const feBlur = document.createElementNS(SVG_NS, "feGaussianBlur");
|
|
1494
|
-
feBlur.setAttribute("in", "SourceGraphic");
|
|
1495
|
-
feBlur.setAttribute("stdDeviation", String(blur));
|
|
1496
|
-
feBlur.setAttribute("result", "blur");
|
|
1497
|
-
const feCM = document.createElementNS(SVG_NS, "feColorMatrix");
|
|
1498
|
-
feCM.setAttribute("in", "blur");
|
|
1499
|
-
feCM.setAttribute("type", "matrix");
|
|
1500
|
-
feCM.setAttribute("values", "1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 20 -10");
|
|
1501
|
-
feCM.setAttribute("result", "goo");
|
|
1502
|
-
const feComp = document.createElementNS(SVG_NS, "feComposite");
|
|
1503
|
-
feComp.setAttribute("in", "SourceGraphic");
|
|
1504
|
-
feComp.setAttribute("in2", "goo");
|
|
1505
|
-
feComp.setAttribute("operator", "atop");
|
|
1506
|
-
filter.appendChild(feBlur);
|
|
1507
|
-
filter.appendChild(feCM);
|
|
1508
|
-
filter.appendChild(feComp);
|
|
1509
|
-
defs.appendChild(filter);
|
|
1510
|
-
svg.appendChild(defs);
|
|
1511
|
-
const g = document.createElementNS(SVG_NS, "g");
|
|
1512
|
-
g.setAttribute("filter", `url(#${filterId})`);
|
|
1513
|
-
const initialPillX = getPillAlign2(item.position) === "right" ? WIDTH - HEIGHT : getPillAlign2(item.position) === "center" ? (WIDTH - HEIGHT) / 2 : 0;
|
|
1514
|
-
const pillEl = document.createElementNS(SVG_NS, "rect");
|
|
1515
|
-
pillEl.setAttribute("data-fluix-pill", "");
|
|
1516
|
-
pillEl.setAttribute("x", String(initialPillX));
|
|
1517
|
-
pillEl.setAttribute("y", "0");
|
|
1518
|
-
pillEl.setAttribute("width", String(HEIGHT));
|
|
1519
|
-
pillEl.setAttribute("height", String(HEIGHT));
|
|
1520
|
-
pillEl.setAttribute("rx", String(roundness));
|
|
1521
|
-
pillEl.setAttribute("ry", String(roundness));
|
|
1522
|
-
pillEl.setAttribute("fill", item.fill ?? "var(--fluix-surface-contrast)");
|
|
1523
|
-
const bodyEl = document.createElementNS(SVG_NS, "rect");
|
|
1524
|
-
bodyEl.setAttribute("data-fluix-body", "");
|
|
1525
|
-
bodyEl.setAttribute("x", "0");
|
|
1526
|
-
bodyEl.setAttribute("y", String(HEIGHT));
|
|
1527
|
-
bodyEl.setAttribute("width", String(WIDTH));
|
|
1528
|
-
bodyEl.setAttribute("height", "0");
|
|
1529
|
-
bodyEl.setAttribute("rx", String(roundness));
|
|
1530
|
-
bodyEl.setAttribute("ry", String(roundness));
|
|
1531
|
-
bodyEl.setAttribute("fill", item.fill ?? "var(--fluix-surface-contrast)");
|
|
1532
|
-
bodyEl.setAttribute("opacity", "0");
|
|
1533
|
-
g.appendChild(pillEl);
|
|
1534
|
-
g.appendChild(bodyEl);
|
|
1535
|
-
svg.appendChild(g);
|
|
1536
|
-
canvasDiv.appendChild(svg);
|
|
1537
|
-
el.appendChild(canvasDiv);
|
|
1538
|
-
const headerEl = document.createElement("div");
|
|
1539
|
-
const headerStackEl = document.createElement("div");
|
|
1540
|
-
headerStackEl.setAttribute("data-fluix-header-stack", "");
|
|
1541
|
-
const innerEl = document.createElement("div");
|
|
1542
|
-
innerEl.setAttribute("data-fluix-header-inner", "");
|
|
1543
|
-
innerEl.setAttribute("data-layer", "current");
|
|
1544
|
-
const badgeEl = document.createElement("div");
|
|
1545
|
-
renderIconInto(badgeEl, item.icon, item.state);
|
|
1546
|
-
const titleEl = document.createElement("span");
|
|
1547
|
-
titleEl.textContent = item.title ?? item.state;
|
|
1548
|
-
innerEl.appendChild(badgeEl);
|
|
1549
|
-
innerEl.appendChild(titleEl);
|
|
1550
|
-
headerStackEl.appendChild(innerEl);
|
|
1551
|
-
headerEl.appendChild(headerStackEl);
|
|
1552
|
-
el.appendChild(headerEl);
|
|
1553
|
-
let contentEl = null;
|
|
1554
|
-
let descriptionEl = null;
|
|
1555
|
-
if (hasDesc) {
|
|
1556
|
-
contentEl = document.createElement("div");
|
|
1557
|
-
descriptionEl = document.createElement("div");
|
|
1558
|
-
if (item.styles?.description) {
|
|
1559
|
-
descriptionEl.className = item.styles.description;
|
|
1560
|
-
}
|
|
1561
|
-
if (item.description != null) {
|
|
1562
|
-
if (typeof item.description === "string") {
|
|
1563
|
-
descriptionEl.textContent = item.description;
|
|
1564
|
-
} else if (item.description instanceof HTMLElement) {
|
|
1565
|
-
descriptionEl.appendChild(item.description);
|
|
1566
|
-
}
|
|
1567
|
-
}
|
|
1568
|
-
if (item.button) {
|
|
1569
|
-
const btn = document.createElement("button");
|
|
1570
|
-
btn.type = "button";
|
|
1571
|
-
btn.textContent = item.button.title;
|
|
1572
|
-
if (item.styles?.button) {
|
|
1573
|
-
btn.className = item.styles.button;
|
|
1574
|
-
}
|
|
1575
|
-
btn.addEventListener("click", (e) => {
|
|
1576
|
-
e.stopPropagation();
|
|
1577
|
-
item.button?.onClick();
|
|
1578
|
-
});
|
|
1579
|
-
descriptionEl.appendChild(btn);
|
|
1580
|
-
}
|
|
1581
|
-
contentEl.appendChild(descriptionEl);
|
|
1582
|
-
el.appendChild(contentEl);
|
|
1583
|
-
}
|
|
1584
|
-
const attrs = Toaster.getAttrs(item, localState);
|
|
1585
|
-
applyAttrs(el, attrs.root);
|
|
1586
|
-
applyAttrs(canvasDiv, attrs.canvas);
|
|
1587
|
-
applyAttrs(headerEl, attrs.header);
|
|
1588
|
-
applyAttrs(badgeEl, attrs.badge);
|
|
1589
|
-
if (item.styles?.badge) badgeEl.className = item.styles.badge;
|
|
1590
|
-
applyAttrs(titleEl, attrs.title);
|
|
1591
|
-
if (item.styles?.title) titleEl.className = item.styles.title;
|
|
1592
|
-
if (contentEl) applyAttrs(contentEl, attrs.content);
|
|
1593
|
-
if (descriptionEl) applyAttrs(descriptionEl, attrs.description);
|
|
1594
|
-
if (item.button && descriptionEl) {
|
|
1595
|
-
const btnEl = descriptionEl.querySelector("button");
|
|
1596
|
-
if (btnEl) applyAttrs(btnEl, attrs.button);
|
|
1597
|
-
}
|
|
1598
|
-
const headerKey = `${item.state}-${item.title ?? item.state}`;
|
|
1599
|
-
const inst = {
|
|
1600
|
-
el,
|
|
1601
|
-
pillEl,
|
|
1602
|
-
bodyEl,
|
|
1603
|
-
svgEl: svg,
|
|
1604
|
-
headerEl,
|
|
1605
|
-
innerEl,
|
|
1606
|
-
headerStackEl,
|
|
1607
|
-
contentEl,
|
|
1608
|
-
descriptionEl,
|
|
1609
|
-
localState,
|
|
1610
|
-
pillWidth: 0,
|
|
1611
|
-
contentHeight: 0,
|
|
1612
|
-
frozenExpanded: HEIGHT * MIN_EXPAND_RATIO,
|
|
1613
|
-
hovering: false,
|
|
1614
|
-
pendingDismiss: false,
|
|
1615
|
-
dismissRequested: false,
|
|
1616
|
-
pillRo: null,
|
|
1617
|
-
contentRo: null,
|
|
1618
|
-
pillAnim: null,
|
|
1619
|
-
prevPill: { x: initialPillX, width: HEIGHT, height: HEIGHT },
|
|
1620
|
-
pillFirst: true,
|
|
1621
|
-
headerKey,
|
|
1622
|
-
headerPad: null,
|
|
1623
|
-
connectHandle: null,
|
|
1624
|
-
timers: /* @__PURE__ */ new Set(),
|
|
1625
|
-
item
|
|
1626
|
-
};
|
|
1627
|
-
inst.pillRo = new ResizeObserver(() => {
|
|
1628
|
-
requestAnimationFrame(() => {
|
|
1629
|
-
measurePillWidth(inst);
|
|
1630
|
-
applyVars(inst, inst.item);
|
|
1631
|
-
animatePill(inst, inst.item);
|
|
1632
|
-
});
|
|
1633
|
-
});
|
|
1634
|
-
inst.pillRo.observe(innerEl);
|
|
1635
|
-
if (descriptionEl) {
|
|
1636
|
-
inst.contentRo = new ResizeObserver(() => {
|
|
1637
|
-
requestAnimationFrame(() => {
|
|
1638
|
-
const h = descriptionEl.scrollHeight;
|
|
1639
|
-
if (h !== inst.contentHeight) {
|
|
1640
|
-
inst.contentHeight = h;
|
|
1641
|
-
applyVars(inst, inst.item);
|
|
1642
|
-
}
|
|
1643
|
-
});
|
|
1644
|
-
});
|
|
1645
|
-
inst.contentRo.observe(descriptionEl);
|
|
1646
|
-
}
|
|
1647
|
-
inst.connectHandle = Toaster.connect(
|
|
1648
|
-
el,
|
|
1649
|
-
{
|
|
1650
|
-
onExpand: () => {
|
|
1651
|
-
if (inst.item.exiting || inst.dismissRequested) return;
|
|
1652
|
-
inst.localState.expanded = true;
|
|
1653
|
-
applyUpdate(inst, inst.item);
|
|
1654
|
-
},
|
|
1655
|
-
onCollapse: () => {
|
|
1656
|
-
if (inst.item.exiting || inst.dismissRequested) return;
|
|
1657
|
-
if (inst.item.autopilot !== false) return;
|
|
1658
|
-
inst.localState.expanded = false;
|
|
1659
|
-
applyUpdate(inst, inst.item);
|
|
1660
|
-
},
|
|
1661
|
-
onDismiss: () => {
|
|
1662
|
-
if (inst.dismissRequested) return;
|
|
1663
|
-
inst.dismissRequested = true;
|
|
1664
|
-
machine2.dismiss(item.id);
|
|
1665
|
-
},
|
|
1666
|
-
onHoverStart: () => {
|
|
1667
|
-
inst.hovering = true;
|
|
1668
|
-
},
|
|
1669
|
-
onHoverEnd: () => {
|
|
1670
|
-
inst.hovering = false;
|
|
1671
|
-
if (inst.pendingDismiss) {
|
|
1672
|
-
inst.pendingDismiss = false;
|
|
1673
|
-
if (inst.dismissRequested) return;
|
|
1674
|
-
inst.dismissRequested = true;
|
|
1675
|
-
machine2.dismiss(inst.item.id);
|
|
1676
|
-
}
|
|
1677
|
-
}
|
|
1678
|
-
},
|
|
1679
|
-
item
|
|
1680
|
-
);
|
|
1681
|
-
applyVars(inst, item);
|
|
1682
|
-
setTimer(
|
|
1683
|
-
inst,
|
|
1684
|
-
() => {
|
|
1685
|
-
inst.localState.ready = true;
|
|
1686
|
-
applyUpdate(inst, inst.item);
|
|
1687
|
-
setupAutopilot(inst, inst.item);
|
|
1688
|
-
},
|
|
1689
|
-
32
|
|
1690
|
-
);
|
|
1691
|
-
setupAutoDismiss(inst, item, machine2);
|
|
1692
|
-
measurePillWidth(inst);
|
|
1693
|
-
return inst;
|
|
1694
|
-
}
|
|
1695
|
-
function measurePillWidth(inst) {
|
|
1696
|
-
if (!inst.el.isConnected) return;
|
|
1697
|
-
if (inst.headerPad === null) {
|
|
1698
|
-
const cs = getComputedStyle(inst.headerEl);
|
|
1699
|
-
inst.headerPad = Number.parseFloat(cs.paddingLeft) + Number.parseFloat(cs.paddingRight);
|
|
1700
|
-
}
|
|
1701
|
-
const intrinsicWidth = inst.innerEl.getBoundingClientRect().width;
|
|
1702
|
-
const w = intrinsicWidth + inst.headerPad + PILL_PADDING;
|
|
1703
|
-
if (w > PILL_PADDING && w !== inst.pillWidth) {
|
|
1704
|
-
inst.pillWidth = w;
|
|
1503
|
+
function getPillAlignLocal(position) {
|
|
1504
|
+
if (position.includes("right")) return "right";
|
|
1505
|
+
if (position.includes("center")) return "center";
|
|
1506
|
+
return "left";
|
|
1507
|
+
}
|
|
1508
|
+
function measurePillWidth(inst) {
|
|
1509
|
+
if (!inst.el.isConnected) return;
|
|
1510
|
+
if (inst.headerPad === null) {
|
|
1511
|
+
const cs = getComputedStyle(inst.headerEl);
|
|
1512
|
+
inst.headerPad = Number.parseFloat(cs.paddingLeft) + Number.parseFloat(cs.paddingRight);
|
|
1705
1513
|
}
|
|
1514
|
+
const w = inst.innerEl.getBoundingClientRect().width + inst.headerPad + PILL_PADDING;
|
|
1515
|
+
if (w > PILL_PADDING && w !== inst.pillWidth) inst.pillWidth = w;
|
|
1706
1516
|
}
|
|
1707
1517
|
function applyVars(inst, item) {
|
|
1708
1518
|
const layout = computeLayout(item, inst);
|
|
@@ -1719,15 +1529,12 @@ var Fluix = (function (exports) {
|
|
|
1719
1529
|
"--_bh": `${open ? expandedContent : 0}px`,
|
|
1720
1530
|
"--_bo": `${open ? 1 : 0}`
|
|
1721
1531
|
};
|
|
1722
|
-
for (const [key, value] of Object.entries(vars))
|
|
1723
|
-
inst.el.style.setProperty(key, value);
|
|
1724
|
-
}
|
|
1532
|
+
for (const [key, value] of Object.entries(vars)) inst.el.style.setProperty(key, value);
|
|
1725
1533
|
inst.svgEl.setAttribute("height", String(svgHeight));
|
|
1726
1534
|
inst.svgEl.setAttribute("viewBox", `0 0 ${WIDTH} ${svgHeight}`);
|
|
1727
1535
|
}
|
|
1728
1536
|
function animatePill(inst, item) {
|
|
1729
|
-
const
|
|
1730
|
-
const { open, resolvedPillWidth, pillX, pillHeight } = layout;
|
|
1537
|
+
const { open, resolvedPillWidth, pillX, pillHeight } = computeLayout(item, inst);
|
|
1731
1538
|
const prev = inst.prevPill;
|
|
1732
1539
|
const next = { x: pillX, width: resolvedPillWidth, height: open ? pillHeight : HEIGHT };
|
|
1733
1540
|
if (prev.x === next.x && prev.width === next.width && prev.height === next.height) return;
|
|
@@ -1740,88 +1547,59 @@ var Fluix = (function (exports) {
|
|
|
1740
1547
|
inst.prevPill = next;
|
|
1741
1548
|
return;
|
|
1742
1549
|
}
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
{
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
height: { from: prev.height, to: next.height, unit: "px" }
|
|
1749
|
-
},
|
|
1750
|
-
FLUIX_SPRING
|
|
1751
|
-
);
|
|
1752
|
-
inst.pillAnim = anim;
|
|
1550
|
+
inst.pillAnim = animateSpring(inst.pillEl, {
|
|
1551
|
+
x: { from: prev.x, to: next.x, unit: "px" },
|
|
1552
|
+
width: { from: prev.width, to: next.width, unit: "px" },
|
|
1553
|
+
height: { from: prev.height, to: next.height, unit: "px" }
|
|
1554
|
+
}, FLUIX_SPRING);
|
|
1753
1555
|
inst.prevPill = next;
|
|
1754
1556
|
}
|
|
1557
|
+
function setTimer(inst, fn, ms) {
|
|
1558
|
+
const id = setTimeout(() => {
|
|
1559
|
+
inst.timers.delete(id);
|
|
1560
|
+
fn();
|
|
1561
|
+
}, ms);
|
|
1562
|
+
inst.timers.add(id);
|
|
1563
|
+
return id;
|
|
1564
|
+
}
|
|
1755
1565
|
function setupAutoDismiss(inst, item, machine2) {
|
|
1756
1566
|
const duration = item.duration;
|
|
1757
1567
|
if (duration == null || duration <= 0) return;
|
|
1758
|
-
setTimer(
|
|
1759
|
-
inst
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
inst.
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
return;
|
|
1774
|
-
}
|
|
1775
|
-
inst.pendingDismiss = false;
|
|
1776
|
-
inst.dismissRequested = true;
|
|
1777
|
-
machine2.dismiss(item.id);
|
|
1778
|
-
},
|
|
1779
|
-
duration
|
|
1780
|
-
);
|
|
1568
|
+
setTimer(inst, () => {
|
|
1569
|
+
if (inst.hovering) {
|
|
1570
|
+
inst.pendingDismiss = true;
|
|
1571
|
+
setTimer(inst, () => {
|
|
1572
|
+
if (inst.dismissRequested) return;
|
|
1573
|
+
inst.dismissRequested = true;
|
|
1574
|
+
inst.pendingDismiss = false;
|
|
1575
|
+
machine2.dismiss(item.id);
|
|
1576
|
+
}, 1200);
|
|
1577
|
+
return;
|
|
1578
|
+
}
|
|
1579
|
+
inst.pendingDismiss = false;
|
|
1580
|
+
inst.dismissRequested = true;
|
|
1581
|
+
machine2.dismiss(item.id);
|
|
1582
|
+
}, duration);
|
|
1781
1583
|
}
|
|
1782
1584
|
function setupAutopilot(inst, item, machine2) {
|
|
1783
1585
|
if (item.autoExpandDelayMs != null && item.autoExpandDelayMs > 0) {
|
|
1784
|
-
setTimer(
|
|
1785
|
-
inst
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
}
|
|
1791
|
-
},
|
|
1792
|
-
item.autoExpandDelayMs
|
|
1793
|
-
);
|
|
1586
|
+
setTimer(inst, () => {
|
|
1587
|
+
if (!inst.hovering) {
|
|
1588
|
+
inst.localState.expanded = true;
|
|
1589
|
+
applyUpdate(inst, inst.item);
|
|
1590
|
+
}
|
|
1591
|
+
}, item.autoExpandDelayMs);
|
|
1794
1592
|
}
|
|
1795
1593
|
if (item.autoCollapseDelayMs != null && item.autoCollapseDelayMs > 0) {
|
|
1796
|
-
setTimer(
|
|
1797
|
-
inst
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
}
|
|
1803
|
-
},
|
|
1804
|
-
item.autoCollapseDelayMs
|
|
1805
|
-
);
|
|
1594
|
+
setTimer(inst, () => {
|
|
1595
|
+
if (!inst.hovering) {
|
|
1596
|
+
inst.localState.expanded = false;
|
|
1597
|
+
applyUpdate(inst, inst.item);
|
|
1598
|
+
}
|
|
1599
|
+
}, item.autoCollapseDelayMs);
|
|
1806
1600
|
}
|
|
1807
1601
|
}
|
|
1808
|
-
function
|
|
1809
|
-
inst.item = item;
|
|
1810
|
-
const attrs = Toaster.getAttrs(item, inst.localState);
|
|
1811
|
-
applyAttrs(inst.el, attrs.root);
|
|
1812
|
-
const canvasEl = inst.el.querySelector("[data-fluix-canvas]");
|
|
1813
|
-
if (canvasEl) applyAttrs(canvasEl, attrs.canvas);
|
|
1814
|
-
applyAttrs(inst.headerEl, attrs.header);
|
|
1815
|
-
const badgeEl = inst.innerEl.querySelector("[data-fluix-badge]");
|
|
1816
|
-
if (badgeEl) {
|
|
1817
|
-
applyAttrs(badgeEl, attrs.badge);
|
|
1818
|
-
if (item.styles?.badge) badgeEl.className = item.styles.badge;
|
|
1819
|
-
}
|
|
1820
|
-
const titleEl = inst.innerEl.querySelector("[data-fluix-title]");
|
|
1821
|
-
if (titleEl) {
|
|
1822
|
-
applyAttrs(titleEl, attrs.title);
|
|
1823
|
-
if (item.styles?.title) titleEl.className = item.styles.title;
|
|
1824
|
-
}
|
|
1602
|
+
function updateDescription(inst, item, attrs) {
|
|
1825
1603
|
const hasDesc = Boolean(item.description) || Boolean(item.button);
|
|
1826
1604
|
if (hasDesc && !inst.contentEl) {
|
|
1827
1605
|
const contentEl = document.createElement("div");
|
|
@@ -1842,37 +1620,50 @@ var Fluix = (function (exports) {
|
|
|
1842
1620
|
inst.contentRo.observe(descriptionEl);
|
|
1843
1621
|
}
|
|
1844
1622
|
if (inst.contentEl) applyAttrs(inst.contentEl, attrs.content);
|
|
1845
|
-
if (inst.descriptionEl)
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
inst.descriptionEl.textContent =
|
|
1852
|
-
if (item.description
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1623
|
+
if (!inst.descriptionEl) return;
|
|
1624
|
+
applyAttrs(inst.descriptionEl, attrs.description);
|
|
1625
|
+
if (item.styles?.description) inst.descriptionEl.className = item.styles.description;
|
|
1626
|
+
const existingBtn = inst.descriptionEl.querySelector("[data-fluix-button]");
|
|
1627
|
+
inst.descriptionEl.textContent = "";
|
|
1628
|
+
if (item.description != null) {
|
|
1629
|
+
if (typeof item.description === "string") inst.descriptionEl.textContent = item.description;
|
|
1630
|
+
else if (item.description instanceof HTMLElement) inst.descriptionEl.appendChild(item.description);
|
|
1631
|
+
}
|
|
1632
|
+
if (item.button) {
|
|
1633
|
+
let btnEl = existingBtn;
|
|
1634
|
+
if (!btnEl) {
|
|
1635
|
+
btnEl = document.createElement("button");
|
|
1636
|
+
btnEl.type = "button";
|
|
1637
|
+
}
|
|
1638
|
+
btnEl.textContent = item.button.title;
|
|
1639
|
+
if (item.styles?.button) btnEl.className = item.styles.button;
|
|
1640
|
+
applyAttrs(btnEl, attrs.button);
|
|
1641
|
+
const newBtn = btnEl.cloneNode(true);
|
|
1642
|
+
newBtn.addEventListener("click", (e) => {
|
|
1643
|
+
e.stopPropagation();
|
|
1644
|
+
item.button?.onClick();
|
|
1645
|
+
});
|
|
1646
|
+
inst.descriptionEl.appendChild(newBtn);
|
|
1647
|
+
}
|
|
1648
|
+
}
|
|
1649
|
+
function applyUpdate(inst, item, _machine) {
|
|
1650
|
+
inst.item = item;
|
|
1651
|
+
const attrs = Toaster.getAttrs(item, inst.localState);
|
|
1652
|
+
applyAttrs(inst.el, attrs.root);
|
|
1653
|
+
const canvasEl = inst.el.querySelector("[data-fluix-canvas]");
|
|
1654
|
+
if (canvasEl) applyAttrs(canvasEl, attrs.canvas);
|
|
1655
|
+
applyAttrs(inst.headerEl, attrs.header);
|
|
1656
|
+
const badgeEl = inst.innerEl.querySelector("[data-fluix-badge]");
|
|
1657
|
+
if (badgeEl) {
|
|
1658
|
+
applyAttrs(badgeEl, attrs.badge);
|
|
1659
|
+
if (item.styles?.badge) badgeEl.className = item.styles.badge;
|
|
1660
|
+
}
|
|
1661
|
+
const titleEl = inst.innerEl.querySelector("[data-fluix-title]");
|
|
1662
|
+
if (titleEl) {
|
|
1663
|
+
applyAttrs(titleEl, attrs.title);
|
|
1664
|
+
if (item.styles?.title) titleEl.className = item.styles.title;
|
|
1875
1665
|
}
|
|
1666
|
+
updateDescription(inst, item, attrs);
|
|
1876
1667
|
inst.pillEl.setAttribute("fill", item.fill ?? "var(--fluix-surface-contrast)");
|
|
1877
1668
|
inst.bodyEl.setAttribute("fill", item.fill ?? "var(--fluix-surface-contrast)");
|
|
1878
1669
|
const newHeaderKey = `${item.state}-${item.title ?? item.state}`;
|
|
@@ -1904,13 +1695,9 @@ var Fluix = (function (exports) {
|
|
|
1904
1695
|
inst.innerEl = newInner;
|
|
1905
1696
|
inst.pillRo.unobserve(oldInner);
|
|
1906
1697
|
inst.pillRo.observe(newInner);
|
|
1907
|
-
setTimer(
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
oldInner.remove();
|
|
1911
|
-
},
|
|
1912
|
-
HEADER_EXIT_MS
|
|
1913
|
-
);
|
|
1698
|
+
setTimer(inst, () => {
|
|
1699
|
+
oldInner.remove();
|
|
1700
|
+
}, HEADER_EXIT_MS);
|
|
1914
1701
|
requestAnimationFrame(() => {
|
|
1915
1702
|
measurePillWidth(inst);
|
|
1916
1703
|
applyVars(inst, inst.item);
|
|
@@ -1926,560 +1713,874 @@ var Fluix = (function (exports) {
|
|
|
1926
1713
|
inst.connectHandle.destroy();
|
|
1927
1714
|
inst.el.remove();
|
|
1928
1715
|
}
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1716
|
+
|
|
1717
|
+
// src/toast/instance.ts
|
|
1718
|
+
var WIDTH = 350;
|
|
1719
|
+
var HEIGHT = 40;
|
|
1720
|
+
var MIN_EXPAND_RATIO2 = 2.25;
|
|
1721
|
+
function getPillAlign2(position) {
|
|
1722
|
+
if (position.includes("right")) return "right";
|
|
1723
|
+
if (position.includes("center")) return "center";
|
|
1724
|
+
return "left";
|
|
1725
|
+
}
|
|
1726
|
+
function buildInstanceSvg(item, roundness, blur2) {
|
|
1727
|
+
const filterId = `fluix-gooey-${item.id.replace(/[^a-z0-9-]/gi, "-")}`;
|
|
1728
|
+
const hasDesc = Boolean(item.description) || Boolean(item.button);
|
|
1729
|
+
const initialSvgHeight = hasDesc ? HEIGHT * MIN_EXPAND_RATIO2 : HEIGHT;
|
|
1730
|
+
const svg = document.createElementNS(SVG_NS, "svg");
|
|
1731
|
+
svg.setAttribute("data-fluix-svg", "");
|
|
1732
|
+
svg.setAttribute("width", String(WIDTH));
|
|
1733
|
+
svg.setAttribute("height", String(initialSvgHeight));
|
|
1734
|
+
svg.setAttribute("viewBox", `0 0 ${WIDTH} ${initialSvgHeight}`);
|
|
1735
|
+
svg.setAttribute("aria-hidden", "true");
|
|
1736
|
+
const { g, defs } = createGooeyFilter(filterId, blur2);
|
|
1737
|
+
svg.appendChild(defs);
|
|
1738
|
+
const initialPillX = getPillAlign2(item.position) === "right" ? WIDTH - HEIGHT : getPillAlign2(item.position) === "center" ? (WIDTH - HEIGHT) / 2 : 0;
|
|
1739
|
+
const fill = item.fill ?? "var(--fluix-surface-contrast)";
|
|
1740
|
+
const pillEl = document.createElementNS(SVG_NS, "rect");
|
|
1741
|
+
pillEl.setAttribute("data-fluix-pill", "");
|
|
1742
|
+
for (const [k, v] of Object.entries({ x: initialPillX, y: 0, width: HEIGHT, height: HEIGHT, rx: roundness, ry: roundness })) {
|
|
1743
|
+
pillEl.setAttribute(k, String(v));
|
|
1946
1744
|
}
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
}
|
|
1745
|
+
pillEl.setAttribute("fill", fill);
|
|
1746
|
+
const bodyEl = document.createElementNS(SVG_NS, "rect");
|
|
1747
|
+
bodyEl.setAttribute("data-fluix-body", "");
|
|
1748
|
+
for (const [k, v] of Object.entries({ x: 0, y: HEIGHT, width: WIDTH, height: 0, rx: roundness, ry: roundness })) {
|
|
1749
|
+
bodyEl.setAttribute(k, String(v));
|
|
1953
1750
|
}
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1751
|
+
bodyEl.setAttribute("fill", fill);
|
|
1752
|
+
bodyEl.setAttribute("opacity", "0");
|
|
1753
|
+
g.appendChild(pillEl);
|
|
1754
|
+
g.appendChild(bodyEl);
|
|
1755
|
+
svg.appendChild(g);
|
|
1756
|
+
return { svg, pillEl, bodyEl, initialPillX };
|
|
1757
|
+
}
|
|
1758
|
+
function buildInstanceContent(item) {
|
|
1759
|
+
let contentEl = null;
|
|
1760
|
+
let descriptionEl = null;
|
|
1761
|
+
const hasDesc = Boolean(item.description) || Boolean(item.button);
|
|
1762
|
+
if (!hasDesc) return { contentEl, descriptionEl };
|
|
1763
|
+
contentEl = document.createElement("div");
|
|
1764
|
+
descriptionEl = document.createElement("div");
|
|
1765
|
+
if (item.styles?.description) descriptionEl.className = item.styles.description;
|
|
1766
|
+
if (item.description != null) {
|
|
1767
|
+
if (typeof item.description === "string") descriptionEl.textContent = item.description;
|
|
1768
|
+
else if (item.description instanceof HTMLElement) descriptionEl.appendChild(item.description);
|
|
1769
|
+
}
|
|
1770
|
+
if (item.button) {
|
|
1771
|
+
const btn = document.createElement("button");
|
|
1772
|
+
btn.type = "button";
|
|
1773
|
+
btn.textContent = item.button.title;
|
|
1774
|
+
if (item.styles?.button) btn.className = item.styles.button;
|
|
1775
|
+
btn.addEventListener("click", (e) => {
|
|
1776
|
+
e.stopPropagation();
|
|
1777
|
+
item.button?.onClick();
|
|
1778
|
+
});
|
|
1779
|
+
descriptionEl.appendChild(btn);
|
|
1780
|
+
}
|
|
1781
|
+
contentEl.appendChild(descriptionEl);
|
|
1782
|
+
return { contentEl, descriptionEl };
|
|
1783
|
+
}
|
|
1784
|
+
function buildHeader(item) {
|
|
1785
|
+
const headerEl = document.createElement("div");
|
|
1786
|
+
const headerStackEl = document.createElement("div");
|
|
1787
|
+
headerStackEl.setAttribute("data-fluix-header-stack", "");
|
|
1788
|
+
const innerEl = document.createElement("div");
|
|
1789
|
+
innerEl.setAttribute("data-fluix-header-inner", "");
|
|
1790
|
+
innerEl.setAttribute("data-layer", "current");
|
|
1791
|
+
const badgeEl = document.createElement("div");
|
|
1792
|
+
renderIconInto(badgeEl, item.icon, item.state);
|
|
1793
|
+
const titleEl = document.createElement("span");
|
|
1794
|
+
titleEl.textContent = item.title ?? item.state;
|
|
1795
|
+
innerEl.appendChild(badgeEl);
|
|
1796
|
+
innerEl.appendChild(titleEl);
|
|
1797
|
+
headerStackEl.appendChild(innerEl);
|
|
1798
|
+
headerEl.appendChild(headerStackEl);
|
|
1799
|
+
return { headerEl, headerStackEl, innerEl, badgeEl, titleEl };
|
|
1800
|
+
}
|
|
1801
|
+
function createInstance(item, machine2) {
|
|
1802
|
+
const localState = { ready: false, expanded: false };
|
|
1803
|
+
const roundness = item.roundness ?? TOAST_DEFAULTS.roundness;
|
|
1804
|
+
const blur2 = Math.min(10, Math.max(6, roundness * 0.45));
|
|
1805
|
+
const el2 = document.createElement("button");
|
|
1806
|
+
el2.type = "button";
|
|
1807
|
+
const canvasDiv = document.createElement("div");
|
|
1808
|
+
const { svg, pillEl, bodyEl, initialPillX } = buildInstanceSvg(item, roundness, blur2);
|
|
1809
|
+
canvasDiv.appendChild(svg);
|
|
1810
|
+
el2.appendChild(canvasDiv);
|
|
1811
|
+
const { headerEl, headerStackEl, innerEl, badgeEl, titleEl } = buildHeader(item);
|
|
1812
|
+
el2.appendChild(headerEl);
|
|
1813
|
+
const { contentEl, descriptionEl } = buildInstanceContent(item);
|
|
1814
|
+
if (contentEl) el2.appendChild(contentEl);
|
|
1815
|
+
const attrs = Toaster.getAttrs(item, localState);
|
|
1816
|
+
applyAttrs(el2, attrs.root);
|
|
1817
|
+
applyAttrs(canvasDiv, attrs.canvas);
|
|
1818
|
+
applyAttrs(headerEl, attrs.header);
|
|
1819
|
+
applyAttrs(badgeEl, attrs.badge);
|
|
1820
|
+
if (item.styles?.badge) badgeEl.className = item.styles.badge;
|
|
1821
|
+
applyAttrs(titleEl, attrs.title);
|
|
1822
|
+
if (item.styles?.title) titleEl.className = item.styles.title;
|
|
1823
|
+
if (contentEl) applyAttrs(contentEl, attrs.content);
|
|
1824
|
+
if (descriptionEl) applyAttrs(descriptionEl, attrs.description);
|
|
1825
|
+
if (item.button && descriptionEl) {
|
|
1826
|
+
const btnEl = descriptionEl.querySelector("button");
|
|
1827
|
+
if (btnEl) applyAttrs(btnEl, attrs.button);
|
|
1828
|
+
}
|
|
1829
|
+
const inst = {
|
|
1830
|
+
el: el2,
|
|
1831
|
+
pillEl,
|
|
1832
|
+
bodyEl,
|
|
1833
|
+
svgEl: svg,
|
|
1834
|
+
headerEl,
|
|
1835
|
+
innerEl,
|
|
1836
|
+
headerStackEl,
|
|
1837
|
+
contentEl,
|
|
1838
|
+
descriptionEl,
|
|
1839
|
+
localState,
|
|
1840
|
+
pillWidth: 0,
|
|
1841
|
+
contentHeight: 0,
|
|
1842
|
+
frozenExpanded: HEIGHT * MIN_EXPAND_RATIO2,
|
|
1843
|
+
hovering: false,
|
|
1844
|
+
pendingDismiss: false,
|
|
1845
|
+
dismissRequested: false,
|
|
1846
|
+
pillRo: null,
|
|
1847
|
+
contentRo: null,
|
|
1848
|
+
pillAnim: null,
|
|
1849
|
+
prevPill: { x: initialPillX, width: HEIGHT, height: HEIGHT },
|
|
1850
|
+
pillFirst: true,
|
|
1851
|
+
headerKey: `${item.state}-${item.title ?? item.state}`,
|
|
1852
|
+
headerPad: null,
|
|
1853
|
+
connectHandle: null,
|
|
1854
|
+
timers: /* @__PURE__ */ new Set(),
|
|
1855
|
+
item
|
|
1856
|
+
};
|
|
1857
|
+
wireObservers(inst);
|
|
1858
|
+
wireConnect(inst, item, machine2);
|
|
1859
|
+
applyVars(inst, item);
|
|
1860
|
+
setTimer(inst, () => {
|
|
1861
|
+
inst.localState.ready = true;
|
|
1862
|
+
applyUpdate(inst, inst.item);
|
|
1863
|
+
setupAutopilot(inst, inst.item);
|
|
1864
|
+
}, 32);
|
|
1865
|
+
setupAutoDismiss(inst, item, machine2);
|
|
1866
|
+
measurePillWidth(inst);
|
|
1867
|
+
return inst;
|
|
1868
|
+
}
|
|
1869
|
+
function wireObservers(inst, _item) {
|
|
1870
|
+
inst.pillRo = new ResizeObserver(() => {
|
|
1871
|
+
requestAnimationFrame(() => {
|
|
1872
|
+
measurePillWidth(inst);
|
|
1873
|
+
applyVars(inst, inst.item);
|
|
1874
|
+
});
|
|
1875
|
+
});
|
|
1876
|
+
inst.pillRo.observe(inst.innerEl);
|
|
1877
|
+
if (inst.descriptionEl) {
|
|
1878
|
+
const descEl = inst.descriptionEl;
|
|
1879
|
+
inst.contentRo = new ResizeObserver(() => {
|
|
1880
|
+
requestAnimationFrame(() => {
|
|
1881
|
+
const h = descEl.scrollHeight;
|
|
1882
|
+
if (h !== inst.contentHeight) {
|
|
1883
|
+
inst.contentHeight = h;
|
|
1884
|
+
applyVars(inst, inst.item);
|
|
1983
1885
|
}
|
|
1886
|
+
});
|
|
1887
|
+
});
|
|
1888
|
+
inst.contentRo.observe(descEl);
|
|
1889
|
+
}
|
|
1890
|
+
}
|
|
1891
|
+
function wireConnect(inst, item, machine2) {
|
|
1892
|
+
inst.connectHandle = Toaster.connect(inst.el, {
|
|
1893
|
+
onExpand: () => {
|
|
1894
|
+
if (inst.item.exiting || inst.dismissRequested) return;
|
|
1895
|
+
inst.localState.expanded = true;
|
|
1896
|
+
applyUpdate(inst, inst.item);
|
|
1897
|
+
},
|
|
1898
|
+
onCollapse: () => {
|
|
1899
|
+
if (inst.item.exiting || inst.dismissRequested) return;
|
|
1900
|
+
if (inst.item.autopilot !== false) return;
|
|
1901
|
+
inst.localState.expanded = false;
|
|
1902
|
+
applyUpdate(inst, inst.item);
|
|
1903
|
+
},
|
|
1904
|
+
onDismiss: () => {
|
|
1905
|
+
if (inst.dismissRequested) return;
|
|
1906
|
+
inst.dismissRequested = true;
|
|
1907
|
+
machine2.dismiss(item.id);
|
|
1908
|
+
},
|
|
1909
|
+
onHoverStart: () => {
|
|
1910
|
+
inst.hovering = true;
|
|
1911
|
+
},
|
|
1912
|
+
onHoverEnd: () => {
|
|
1913
|
+
inst.hovering = false;
|
|
1914
|
+
if (inst.pendingDismiss) {
|
|
1915
|
+
inst.pendingDismiss = false;
|
|
1916
|
+
if (inst.dismissRequested) return;
|
|
1917
|
+
inst.dismissRequested = true;
|
|
1918
|
+
machine2.dismiss(inst.item.id);
|
|
1984
1919
|
}
|
|
1985
1920
|
}
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1921
|
+
}, item);
|
|
1922
|
+
}
|
|
1923
|
+
|
|
1924
|
+
// src/toast/index.ts
|
|
1925
|
+
function resolveOffsetValue(v) {
|
|
1926
|
+
return typeof v === "number" ? `${v}px` : v;
|
|
1927
|
+
}
|
|
1928
|
+
function applyViewportOffset(el2, offset, position) {
|
|
1929
|
+
el2.style.top = "";
|
|
1930
|
+
el2.style.right = "";
|
|
1931
|
+
el2.style.bottom = "";
|
|
1932
|
+
el2.style.left = "";
|
|
1933
|
+
el2.style.paddingLeft = "";
|
|
1934
|
+
el2.style.paddingRight = "";
|
|
1935
|
+
if (offset == null) return;
|
|
1936
|
+
let top, right, bottom, left;
|
|
1937
|
+
if (typeof offset === "number" || typeof offset === "string") {
|
|
1938
|
+
const v = resolveOffsetValue(offset);
|
|
1939
|
+
top = v;
|
|
1940
|
+
right = v;
|
|
1941
|
+
bottom = v;
|
|
1942
|
+
left = v;
|
|
1943
|
+
} else {
|
|
1944
|
+
if (offset.top != null) top = resolveOffsetValue(offset.top);
|
|
1945
|
+
if (offset.right != null) right = resolveOffsetValue(offset.right);
|
|
1946
|
+
if (offset.bottom != null) bottom = resolveOffsetValue(offset.bottom);
|
|
1947
|
+
if (offset.left != null) left = resolveOffsetValue(offset.left);
|
|
1948
|
+
}
|
|
1949
|
+
if (position.startsWith("top") && top) el2.style.top = top;
|
|
1950
|
+
if (position.startsWith("bottom") && bottom) el2.style.bottom = bottom;
|
|
1951
|
+
if (position.endsWith("right") && right) el2.style.right = right;
|
|
1952
|
+
if (position.endsWith("left") && left) el2.style.left = left;
|
|
1953
|
+
if (position.endsWith("center")) {
|
|
1954
|
+
if (left) el2.style.paddingLeft = left;
|
|
1955
|
+
if (right) el2.style.paddingRight = right;
|
|
1956
|
+
}
|
|
1957
|
+
}
|
|
1958
|
+
function ensureViewport(state, position, layout, offset) {
|
|
1959
|
+
let vp = state.viewports.get(position);
|
|
1960
|
+
if (!vp) {
|
|
1961
|
+
vp = document.createElement("section");
|
|
1962
|
+
applyAttrs(vp, Toaster.getViewportAttrs(position, layout));
|
|
1963
|
+
applyViewportOffset(vp, offset, position);
|
|
1964
|
+
document.body.appendChild(vp);
|
|
1965
|
+
state.viewports.set(position, vp);
|
|
1966
|
+
}
|
|
1967
|
+
return vp;
|
|
1968
|
+
}
|
|
1969
|
+
function sync(state) {
|
|
1970
|
+
const next = state.machine.store.getSnapshot();
|
|
1971
|
+
const layout = next.config?.layout ?? state.currentConfig?.layout ?? "stack";
|
|
1972
|
+
const offset = next.config?.offset ?? state.currentConfig?.offset;
|
|
1973
|
+
const activePositions = /* @__PURE__ */ new Set();
|
|
1974
|
+
const nextIds = new Set(next.toasts.map((t) => t.id));
|
|
1975
|
+
for (const [id, inst] of state.instances) {
|
|
1976
|
+
if (!nextIds.has(id)) {
|
|
1977
|
+
destroyInstance(inst);
|
|
1978
|
+
state.instances.delete(id);
|
|
1979
|
+
}
|
|
1980
|
+
}
|
|
1981
|
+
for (const item of next.toasts) {
|
|
1982
|
+
activePositions.add(item.position);
|
|
1983
|
+
const vp = ensureViewport(state, item.position, layout, offset);
|
|
1984
|
+
const existing = state.instances.get(item.id);
|
|
1985
|
+
if (!existing) {
|
|
1986
|
+
const inst = createInstance(item, state.machine);
|
|
1987
|
+
state.instances.set(item.id, inst);
|
|
1988
|
+
vp.appendChild(inst.el);
|
|
1989
|
+
} else if (existing.item.instanceId !== item.instanceId) {
|
|
1990
|
+
destroyInstance(existing);
|
|
1991
|
+
const inst = createInstance(item, state.machine);
|
|
1992
|
+
state.instances.set(item.id, inst);
|
|
1993
|
+
vp.appendChild(inst.el);
|
|
1994
|
+
} else {
|
|
1995
|
+
applyUpdate(existing, item);
|
|
1996
|
+
if (existing.el.parentElement !== vp) vp.appendChild(existing.el);
|
|
1990
1997
|
}
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1998
|
+
}
|
|
1999
|
+
for (const [position, vp] of state.viewports) {
|
|
2000
|
+
applyAttrs(vp, Toaster.getViewportAttrs(position, layout));
|
|
2001
|
+
applyViewportOffset(vp, offset, position);
|
|
2002
|
+
}
|
|
2003
|
+
for (const [position] of state.viewports) {
|
|
2004
|
+
if (!activePositions.has(position)) {
|
|
2005
|
+
state.viewports.get(position)?.remove();
|
|
2006
|
+
state.viewports.delete(position);
|
|
1995
2007
|
}
|
|
1996
2008
|
}
|
|
1997
|
-
|
|
1998
|
-
|
|
2009
|
+
}
|
|
2010
|
+
function createToaster(config) {
|
|
2011
|
+
const state = {
|
|
2012
|
+
machine: Toaster.getMachine(),
|
|
2013
|
+
instances: /* @__PURE__ */ new Map(),
|
|
2014
|
+
viewports: /* @__PURE__ */ new Map(),
|
|
2015
|
+
currentConfig: config
|
|
2016
|
+
};
|
|
2017
|
+
if (config) state.machine.configure(config);
|
|
2018
|
+
sync(state);
|
|
2019
|
+
const unsubscribe = state.machine.store.subscribe(() => sync(state));
|
|
1999
2020
|
return {
|
|
2000
2021
|
destroy() {
|
|
2001
2022
|
unsubscribe();
|
|
2002
|
-
for (const inst of instances.values())
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
for (const vp of viewports.values()) {
|
|
2007
|
-
vp.remove();
|
|
2008
|
-
}
|
|
2009
|
-
viewports.clear();
|
|
2023
|
+
for (const inst of state.instances.values()) destroyInstance(inst);
|
|
2024
|
+
state.instances.clear();
|
|
2025
|
+
for (const vp of state.viewports.values()) vp.remove();
|
|
2026
|
+
state.viewports.clear();
|
|
2010
2027
|
},
|
|
2011
2028
|
update(newConfig) {
|
|
2012
|
-
currentConfig = newConfig;
|
|
2013
|
-
|
|
2029
|
+
state.currentConfig = newConfig;
|
|
2030
|
+
state.machine.configure(newConfig);
|
|
2014
2031
|
}
|
|
2015
2032
|
};
|
|
2016
2033
|
}
|
|
2017
2034
|
|
|
2018
|
-
// src/notch.ts
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2035
|
+
// src/notch/highlight.ts
|
|
2036
|
+
function setBlobAttrs(el2, x, y, w, h, rx, opacity) {
|
|
2037
|
+
el2.setAttribute("x", String(x));
|
|
2038
|
+
el2.setAttribute("y", String(y));
|
|
2039
|
+
el2.setAttribute("width", String(w));
|
|
2040
|
+
el2.setAttribute("height", String(h));
|
|
2041
|
+
el2.setAttribute("rx", String(rx));
|
|
2042
|
+
el2.setAttribute("ry", String(rx));
|
|
2043
|
+
el2.setAttribute("opacity", opacity);
|
|
2044
|
+
}
|
|
2045
|
+
function springBlob(el2, from, to, sc) {
|
|
2046
|
+
return animateSpring(el2, {
|
|
2047
|
+
x: { from: from.x, to: to.x, unit: "px" },
|
|
2048
|
+
y: { from: from.y, to: to.y, unit: "px" },
|
|
2049
|
+
width: { from: from.w, to: to.w, unit: "px" },
|
|
2050
|
+
height: { from: from.h, to: to.h, unit: "px" },
|
|
2051
|
+
rx: { from: from.rx, to: to.rx, unit: "px" },
|
|
2052
|
+
ry: { from: from.rx, to: to.rx, unit: "px" }
|
|
2053
|
+
}, { ...sc, stiffness: (sc.stiffness ?? 300) * 1.2 });
|
|
2054
|
+
}
|
|
2055
|
+
function createHighlightTracker(el2, springConfig) {
|
|
2056
|
+
let anim = null;
|
|
2057
|
+
const prev = { x: 0, y: 0, w: 0, h: 0, visible: false };
|
|
2058
|
+
function finish(a, x, y, w, h, rx, opacity) {
|
|
2059
|
+
if (a) {
|
|
2060
|
+
anim = a;
|
|
2061
|
+
a.onfinish = () => {
|
|
2062
|
+
anim = null;
|
|
2063
|
+
setBlobAttrs(el2, x, y, w, h, rx, opacity);
|
|
2064
|
+
};
|
|
2065
|
+
} else {
|
|
2066
|
+
setBlobAttrs(el2, x, y, w, h, rx, opacity);
|
|
2067
|
+
}
|
|
2023
2068
|
}
|
|
2069
|
+
return {
|
|
2070
|
+
onItemEnter(e, rootEl, isOpen, roundness) {
|
|
2071
|
+
const target = e.target.closest("a, button");
|
|
2072
|
+
if (!target || !isOpen) return;
|
|
2073
|
+
const rootRect = rootEl.getBoundingClientRect();
|
|
2074
|
+
const itemRect = target.getBoundingClientRect();
|
|
2075
|
+
const padX = 8, padY = 4;
|
|
2076
|
+
const overshoot = Math.max(6, roundness * 0.35);
|
|
2077
|
+
const toW = target.offsetWidth + padX * 2;
|
|
2078
|
+
const toH = Math.max(target.offsetHeight + padY * 2, rootRect.height + overshoot * 2);
|
|
2079
|
+
const toX = itemRect.left + itemRect.width / 2 - rootRect.left - toW / 2;
|
|
2080
|
+
const toY = itemRect.top + itemRect.height / 2 - rootRect.top - toH / 2;
|
|
2081
|
+
if (anim) {
|
|
2082
|
+
anim.cancel();
|
|
2083
|
+
anim = null;
|
|
2084
|
+
}
|
|
2085
|
+
const from = {
|
|
2086
|
+
x: prev.visible ? prev.x : toX + toW / 2,
|
|
2087
|
+
y: prev.visible ? prev.y : toY + toH / 2,
|
|
2088
|
+
w: prev.visible ? prev.w : 0,
|
|
2089
|
+
h: prev.visible ? prev.h : 0,
|
|
2090
|
+
rx: prev.visible ? prev.h / 2 : 0
|
|
2091
|
+
};
|
|
2092
|
+
finish(springBlob(el2, from, { x: toX, y: toY, w: toW, h: toH, rx: toH / 2 }, springConfig()), toX, toY, toW, toH, toH / 2, "1");
|
|
2093
|
+
el2.setAttribute("opacity", "1");
|
|
2094
|
+
prev.x = toX;
|
|
2095
|
+
prev.y = toY;
|
|
2096
|
+
prev.w = toW;
|
|
2097
|
+
prev.h = toH;
|
|
2098
|
+
prev.visible = true;
|
|
2099
|
+
},
|
|
2100
|
+
onItemLeave() {
|
|
2101
|
+
if (!prev.visible) return;
|
|
2102
|
+
const cx = prev.x + prev.w / 2, cy = prev.y + prev.h / 2;
|
|
2103
|
+
finish(springBlob(el2, { x: prev.x, y: prev.y, w: prev.w, h: prev.h, rx: prev.h / 2 }, { x: cx, y: cy, w: 0, h: 0, rx: 0 }, springConfig()), cx, cy, 0, 0, 0, "0");
|
|
2104
|
+
prev.visible = false;
|
|
2105
|
+
},
|
|
2106
|
+
reset(rootW, rootH) {
|
|
2107
|
+
if (anim) {
|
|
2108
|
+
anim.cancel();
|
|
2109
|
+
anim = null;
|
|
2110
|
+
}
|
|
2111
|
+
setBlobAttrs(el2, rootW / 2, rootH / 2, 0, 0, 0, "0");
|
|
2112
|
+
prev.visible = false;
|
|
2113
|
+
},
|
|
2114
|
+
cancelAnim() {
|
|
2115
|
+
anim?.cancel();
|
|
2116
|
+
}
|
|
2117
|
+
};
|
|
2024
2118
|
}
|
|
2119
|
+
|
|
2120
|
+
// src/notch/dom.ts
|
|
2025
2121
|
function resolveContent(source) {
|
|
2026
2122
|
if (source instanceof HTMLElement) return source;
|
|
2027
2123
|
const span = document.createElement("span");
|
|
2028
2124
|
span.textContent = source;
|
|
2029
2125
|
return span;
|
|
2030
2126
|
}
|
|
2031
|
-
function
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
const
|
|
2044
|
-
const
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
const
|
|
2054
|
-
const
|
|
2055
|
-
const
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
const rootH = () => Math.max(expandedH(), collapsedH());
|
|
2064
|
-
const prev = { w: 0, h: 0, initialized: false };
|
|
2065
|
-
let currentAnim = null;
|
|
2066
|
-
let highlightAnim = null;
|
|
2067
|
-
const hlPrev = { x: 0, y: 0, w: 0, h: 0, visible: false };
|
|
2127
|
+
function buildNotchSvg(rW, rH, collW, collH, blurVal, fill) {
|
|
2128
|
+
const svg = document.createElementNS(SVG_NS, "svg");
|
|
2129
|
+
svg.setAttribute("xmlns", "http://www.w3.org/2000/svg");
|
|
2130
|
+
for (const [k, v] of Object.entries({ width: String(rW), height: String(rH), viewBox: `0 0 ${rW} ${rH}`, "aria-hidden": "true" })) svg.setAttribute(k, v);
|
|
2131
|
+
const { g, defs, feBlur } = createGooeyFilter("fluix-notch-goo", blurVal);
|
|
2132
|
+
svg.appendChild(defs);
|
|
2133
|
+
const effectiveFill = fill ?? "var(--fluix-notch-bg)";
|
|
2134
|
+
const svgRectEl = document.createElementNS(SVG_NS, "rect");
|
|
2135
|
+
const cx = (rW - collW) / 2, cy = (rH - collH) / 2;
|
|
2136
|
+
for (const [k, v] of Object.entries({ x: cx, y: cy, width: collW, height: collH, rx: collW / 2, ry: collH / 2 })) svgRectEl.setAttribute(k, String(v));
|
|
2137
|
+
svgRectEl.setAttribute("fill", effectiveFill);
|
|
2138
|
+
g.appendChild(svgRectEl);
|
|
2139
|
+
const hoverBlobEl = document.createElementNS(SVG_NS, "rect");
|
|
2140
|
+
for (const [k, v] of Object.entries({ x: cx, y: cy, width: 0, height: 0, rx: 0, ry: 0, opacity: "0" })) hoverBlobEl.setAttribute(k, String(v));
|
|
2141
|
+
hoverBlobEl.setAttribute("fill", effectiveFill);
|
|
2142
|
+
g.appendChild(hoverBlobEl);
|
|
2143
|
+
svg.appendChild(g);
|
|
2144
|
+
return { svg, svgRectEl, hoverBlobEl, feBlur };
|
|
2145
|
+
}
|
|
2146
|
+
var HL_PAD = 12;
|
|
2147
|
+
function computeDims(cfg) {
|
|
2148
|
+
const collW = cfg.dotSize, collH = cfg.dotSize;
|
|
2149
|
+
const expW = cfg.contentSize.w + HL_PAD * 2;
|
|
2150
|
+
const expH = Math.max(cfg.contentSize.h + HL_PAD, cfg.dotSize);
|
|
2151
|
+
const rW = Math.max(expW, collW);
|
|
2152
|
+
const rH = Math.max(expH, collH);
|
|
2153
|
+
return { collW, collH, rW, rH };
|
|
2154
|
+
}
|
|
2155
|
+
function computeBlur(roundness) {
|
|
2156
|
+
return Math.min(10, Math.max(6, roundness * 0.45));
|
|
2157
|
+
}
|
|
2158
|
+
function buildNotchDOM(cfg, pill, content, container, springCfg2) {
|
|
2068
2159
|
const measureEl = document.createElement("div");
|
|
2069
2160
|
measureEl.setAttribute("data-fluix-notch-measure", "");
|
|
2070
|
-
measureEl.appendChild(resolveContent(
|
|
2161
|
+
measureEl.appendChild(resolveContent(content).cloneNode(true));
|
|
2071
2162
|
container.appendChild(measureEl);
|
|
2163
|
+
const d = computeDims(cfg);
|
|
2072
2164
|
const rootEl = document.createElement("div");
|
|
2073
|
-
const attrs = getNotchAttrs({ open: snapshot.open, position, theme });
|
|
2074
|
-
|
|
2075
|
-
rootEl.style.width = `${
|
|
2076
|
-
rootEl.style.height = `${
|
|
2165
|
+
const attrs = getNotchAttrs({ open: cfg.snapshot.open, position: cfg.position, theme: cfg.theme });
|
|
2166
|
+
applyAttrs(rootEl, attrs.root);
|
|
2167
|
+
rootEl.style.width = `${d.rW}px`;
|
|
2168
|
+
rootEl.style.height = `${d.rH}px`;
|
|
2077
2169
|
const canvasDiv = document.createElement("div");
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
svg.setAttribute("height", String(rootH()));
|
|
2083
|
-
svg.setAttribute("viewBox", `0 0 ${rootW()} ${rootH()}`);
|
|
2084
|
-
svg.setAttribute("aria-hidden", "true");
|
|
2085
|
-
const defs = document.createElementNS(SVG_NS2, "defs");
|
|
2086
|
-
const filter = document.createElementNS(SVG_NS2, "filter");
|
|
2087
|
-
filter.setAttribute("id", "fluix-notch-goo");
|
|
2088
|
-
filter.setAttribute("x", "-20%");
|
|
2089
|
-
filter.setAttribute("y", "-20%");
|
|
2090
|
-
filter.setAttribute("width", "140%");
|
|
2091
|
-
filter.setAttribute("height", "140%");
|
|
2092
|
-
filter.setAttribute("color-interpolation-filters", "sRGB");
|
|
2093
|
-
const feBlur = document.createElementNS(SVG_NS2, "feGaussianBlur");
|
|
2094
|
-
feBlur.setAttribute("in", "SourceGraphic");
|
|
2095
|
-
feBlur.setAttribute("stdDeviation", String(blur()));
|
|
2096
|
-
feBlur.setAttribute("result", "blur");
|
|
2097
|
-
const feCM = document.createElementNS(SVG_NS2, "feColorMatrix");
|
|
2098
|
-
feCM.setAttribute("in", "blur");
|
|
2099
|
-
feCM.setAttribute("type", "matrix");
|
|
2100
|
-
feCM.setAttribute("values", "1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 20 -10");
|
|
2101
|
-
feCM.setAttribute("result", "goo");
|
|
2102
|
-
const feComp = document.createElementNS(SVG_NS2, "feComposite");
|
|
2103
|
-
feComp.setAttribute("in", "SourceGraphic");
|
|
2104
|
-
feComp.setAttribute("in2", "goo");
|
|
2105
|
-
feComp.setAttribute("operator", "atop");
|
|
2106
|
-
filter.appendChild(feBlur);
|
|
2107
|
-
filter.appendChild(feCM);
|
|
2108
|
-
filter.appendChild(feComp);
|
|
2109
|
-
defs.appendChild(filter);
|
|
2110
|
-
svg.appendChild(defs);
|
|
2111
|
-
const gGroup = document.createElementNS(SVG_NS2, "g");
|
|
2112
|
-
gGroup.setAttribute("filter", "url(#fluix-notch-goo)");
|
|
2113
|
-
const svgRectEl = document.createElementNS(SVG_NS2, "rect");
|
|
2114
|
-
const cw = collapsedW();
|
|
2115
|
-
const ch = collapsedH();
|
|
2116
|
-
svgRectEl.setAttribute("x", String((rootW() - cw) / 2));
|
|
2117
|
-
svgRectEl.setAttribute("y", String((rootH() - ch) / 2));
|
|
2118
|
-
svgRectEl.setAttribute("width", String(cw));
|
|
2119
|
-
svgRectEl.setAttribute("height", String(ch));
|
|
2120
|
-
svgRectEl.setAttribute("rx", String(cw / 2));
|
|
2121
|
-
svgRectEl.setAttribute("ry", String(ch / 2));
|
|
2122
|
-
svgRectEl.setAttribute("fill", fill ?? "var(--fluix-notch-bg)");
|
|
2123
|
-
gGroup.appendChild(svgRectEl);
|
|
2124
|
-
svg.appendChild(gGroup);
|
|
2125
|
-
const hoverBlobEl = document.createElementNS(SVG_NS2, "rect");
|
|
2126
|
-
hoverBlobEl.setAttribute("x", String((rootW() - cw) / 2));
|
|
2127
|
-
hoverBlobEl.setAttribute("y", String((rootH() - ch) / 2));
|
|
2128
|
-
hoverBlobEl.setAttribute("width", "0");
|
|
2129
|
-
hoverBlobEl.setAttribute("height", "0");
|
|
2130
|
-
hoverBlobEl.setAttribute("rx", "0");
|
|
2131
|
-
hoverBlobEl.setAttribute("ry", "0");
|
|
2132
|
-
hoverBlobEl.setAttribute("opacity", "0");
|
|
2133
|
-
hoverBlobEl.setAttribute("fill", fill ?? "var(--fluix-notch-bg)");
|
|
2134
|
-
gGroup.appendChild(hoverBlobEl);
|
|
2135
|
-
canvasDiv.appendChild(svg);
|
|
2170
|
+
applyAttrs(canvasDiv, attrs.canvas);
|
|
2171
|
+
canvasDiv.style.cssText = "position:absolute;inset:0;pointer-events:none;overflow:visible;";
|
|
2172
|
+
const svgRefs = buildNotchSvg(d.rW, d.rH, d.collW, d.collH, computeBlur(cfg.roundness), cfg.fill);
|
|
2173
|
+
canvasDiv.appendChild(svgRefs.svg);
|
|
2136
2174
|
rootEl.appendChild(canvasDiv);
|
|
2175
|
+
const highlight = createHighlightTracker(svgRefs.hoverBlobEl, springCfg2);
|
|
2137
2176
|
const pillDiv = document.createElement("div");
|
|
2138
|
-
|
|
2139
|
-
pillDiv.style.
|
|
2140
|
-
pillDiv.
|
|
2141
|
-
pillDiv.appendChild(resolveContent(options.pill));
|
|
2177
|
+
applyAttrs(pillDiv, attrs.pill);
|
|
2178
|
+
pillDiv.style.cssText = `position:absolute;z-index:10;top:50%;left:50%;transform:translate(-50%,-50%);display:flex;align-items:center;justify-content:center;border-radius:50%;overflow:hidden;pointer-events:none;width:${cfg.dotSize}px;height:${cfg.dotSize}px;color:var(--fluix-notch-color);`;
|
|
2179
|
+
pillDiv.appendChild(resolveContent(pill));
|
|
2142
2180
|
rootEl.appendChild(pillDiv);
|
|
2143
2181
|
const contentDiv = document.createElement("div");
|
|
2144
|
-
|
|
2145
|
-
contentDiv.
|
|
2182
|
+
applyAttrs(contentDiv, attrs.content);
|
|
2183
|
+
contentDiv.style.cssText = "position:absolute;z-index:10;inset:0;display:flex;align-items:center;justify-content:center;pointer-events:none;opacity:0;color:var(--fluix-notch-color);";
|
|
2184
|
+
contentDiv.appendChild(resolveContent(content));
|
|
2146
2185
|
rootEl.appendChild(contentDiv);
|
|
2147
2186
|
container.appendChild(rootEl);
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2187
|
+
rootEl.setAttribute("role", "button");
|
|
2188
|
+
rootEl.setAttribute("tabindex", "0");
|
|
2189
|
+
rootEl.setAttribute("aria-expanded", String(cfg.snapshot.open));
|
|
2190
|
+
return { rootEl, measureEl, pillDiv, contentDiv, highlight, ...svgRefs };
|
|
2191
|
+
}
|
|
2192
|
+
|
|
2193
|
+
// src/notch/index.ts
|
|
2194
|
+
var HL_PAD2 = 12;
|
|
2195
|
+
function dims(ctx) {
|
|
2196
|
+
const collW = ctx.dotSize, collH = ctx.dotSize;
|
|
2197
|
+
const expW = ctx.contentSize.w + HL_PAD2 * 2;
|
|
2198
|
+
const expH = Math.max(ctx.contentSize.h + HL_PAD2, ctx.dotSize);
|
|
2199
|
+
const tW = ctx.snapshot.open ? expW : collW;
|
|
2200
|
+
const tH = ctx.snapshot.open ? expH : collH;
|
|
2201
|
+
const rW = Math.max(expW, collW);
|
|
2202
|
+
const rH = Math.max(expH, collH);
|
|
2203
|
+
return { collW, collH, expW, expH, tW, tH, rW, rH };
|
|
2204
|
+
}
|
|
2205
|
+
function blur(ctx) {
|
|
2206
|
+
return Math.min(10, Math.max(6, ctx.roundness * 0.45));
|
|
2207
|
+
}
|
|
2208
|
+
function springCfg(ctx) {
|
|
2209
|
+
return ctx.spring ?? FLUIX_SPRING;
|
|
2210
|
+
}
|
|
2211
|
+
function animateRect(ctx) {
|
|
2212
|
+
const d = dims(ctx);
|
|
2213
|
+
const toX = (d.rW - d.tW) / 2, toY = (d.rH - d.tH) / 2;
|
|
2214
|
+
if (d.tW === ctx.prev.w && d.tH === ctx.prev.h) {
|
|
2215
|
+
const el3 = ctx.dom.svgRectEl;
|
|
2216
|
+
const rx = d.tW === d.collW && d.tH === d.collH ? d.collW / 2 : ctx.roundness;
|
|
2217
|
+
for (const [k, v] of Object.entries({ x: toX, y: toY, width: d.tW, height: d.tH, rx, ry: rx })) el3.setAttribute(k, String(v));
|
|
2218
|
+
return;
|
|
2219
|
+
}
|
|
2220
|
+
if (ctx.currentAnim) {
|
|
2221
|
+
ctx.currentAnim.cancel();
|
|
2222
|
+
ctx.currentAnim = null;
|
|
2223
|
+
}
|
|
2224
|
+
const fromW = ctx.prev.w, fromH = ctx.prev.h;
|
|
2225
|
+
const fromX = (d.rW - fromW) / 2, fromY = (d.rH - fromH) / 2;
|
|
2226
|
+
ctx.prev.w = d.tW;
|
|
2227
|
+
ctx.prev.h = d.tH;
|
|
2228
|
+
const wasCollapsed = fromW === d.collW && fromH === d.collH;
|
|
2229
|
+
const isCollapsing = d.tW === d.collW && d.tH === d.collH;
|
|
2230
|
+
const fromRx = wasCollapsed ? d.collW / 2 : ctx.roundness;
|
|
2231
|
+
const toRx = isCollapsing ? d.collW / 2 : ctx.roundness;
|
|
2232
|
+
const el2 = ctx.dom.svgRectEl;
|
|
2233
|
+
const a = animateSpring(el2, {
|
|
2234
|
+
width: { from: fromW, to: d.tW, unit: "px" },
|
|
2235
|
+
height: { from: fromH, to: d.tH, unit: "px" },
|
|
2236
|
+
x: { from: fromX, to: toX, unit: "px" },
|
|
2237
|
+
y: { from: fromY, to: toY, unit: "px" },
|
|
2238
|
+
rx: { from: fromRx, to: toRx, unit: "px" },
|
|
2239
|
+
ry: { from: fromRx, to: toRx, unit: "px" }
|
|
2240
|
+
}, springCfg(ctx));
|
|
2241
|
+
const applyFinal = () => {
|
|
2242
|
+
for (const [k, v] of Object.entries({ width: d.tW, height: d.tH, x: toX, y: toY, rx: toRx, ry: toRx })) el2.setAttribute(k, String(v));
|
|
2243
|
+
};
|
|
2244
|
+
if (a) {
|
|
2245
|
+
ctx.currentAnim = a;
|
|
2246
|
+
a.onfinish = () => {
|
|
2247
|
+
ctx.currentAnim = null;
|
|
2248
|
+
applyFinal();
|
|
2249
|
+
};
|
|
2250
|
+
} else applyFinal();
|
|
2251
|
+
}
|
|
2252
|
+
function updateLayout(ctx) {
|
|
2253
|
+
const d = dims(ctx);
|
|
2254
|
+
const isOpen = ctx.snapshot.open;
|
|
2255
|
+
const newAttrs = getNotchAttrs({ open: isOpen, position: ctx.position, theme: ctx.theme });
|
|
2256
|
+
applyAttrs(ctx.dom.rootEl, newAttrs.root);
|
|
2257
|
+
ctx.dom.rootEl.setAttribute("aria-expanded", String(isOpen));
|
|
2258
|
+
ctx.dom.rootEl.style.width = `${d.rW}px`;
|
|
2259
|
+
ctx.dom.rootEl.style.height = `${d.rH}px`;
|
|
2260
|
+
ctx.dom.svg.setAttribute("width", String(d.rW));
|
|
2261
|
+
ctx.dom.svg.setAttribute("height", String(d.rH));
|
|
2262
|
+
ctx.dom.svg.setAttribute("viewBox", `0 0 ${d.rW} ${d.rH}`);
|
|
2263
|
+
ctx.dom.feBlur.setAttribute("stdDeviation", String(blur(ctx)));
|
|
2264
|
+
const effectiveFill = ctx.fill ?? "var(--fluix-notch-bg)";
|
|
2265
|
+
ctx.dom.svgRectEl.setAttribute("fill", effectiveFill);
|
|
2266
|
+
ctx.dom.hoverBlobEl.setAttribute("fill", effectiveFill);
|
|
2267
|
+
applyAttrs(ctx.dom.contentDiv, newAttrs.content);
|
|
2268
|
+
ctx.dom.contentDiv.style.opacity = isOpen ? "1" : "0";
|
|
2269
|
+
ctx.dom.contentDiv.style.pointerEvents = isOpen ? "auto" : "none";
|
|
2270
|
+
ctx.dom.pillDiv.style.opacity = isOpen ? "0" : "1";
|
|
2271
|
+
animateRect(ctx);
|
|
2272
|
+
if (!isOpen) ctx.highlight.reset(d.rW, d.rH);
|
|
2273
|
+
document.documentElement.style.setProperty("--fluix-notch-offset", `${d.rH}px`);
|
|
2274
|
+
}
|
|
2275
|
+
function createListeners(ctx) {
|
|
2276
|
+
const handleOpen = () => {
|
|
2277
|
+
ctx.controlledOpen === void 0 ? ctx.machine.open() : ctx.onOpenChange?.(true);
|
|
2278
|
+
};
|
|
2279
|
+
const handleClose = () => {
|
|
2280
|
+
ctx.controlledOpen === void 0 ? ctx.machine.close() : ctx.onOpenChange?.(false);
|
|
2281
|
+
};
|
|
2282
|
+
const handleToggle = () => {
|
|
2283
|
+
ctx.controlledOpen === void 0 ? ctx.machine.toggle() : ctx.onOpenChange?.(!ctx.snapshot.open);
|
|
2284
|
+
};
|
|
2285
|
+
return {
|
|
2286
|
+
mouseenter: () => {
|
|
2287
|
+
if (ctx.trigger === "hover") handleOpen();
|
|
2288
|
+
},
|
|
2289
|
+
mouseleave: () => {
|
|
2290
|
+
if (ctx.trigger === "hover") {
|
|
2291
|
+
handleClose();
|
|
2292
|
+
ctx.highlight.reset(dims(ctx).rW, dims(ctx).rH);
|
|
2293
|
+
return;
|
|
2294
|
+
}
|
|
2295
|
+
ctx.highlight.onItemLeave();
|
|
2296
|
+
},
|
|
2297
|
+
mouseover: (e) => {
|
|
2298
|
+
ctx.highlight.onItemEnter(e, ctx.dom.rootEl, ctx.snapshot.open, ctx.roundness);
|
|
2299
|
+
},
|
|
2300
|
+
click: () => {
|
|
2301
|
+
if (ctx.trigger === "click") handleToggle();
|
|
2302
|
+
},
|
|
2303
|
+
keydown: (e) => {
|
|
2304
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
2305
|
+
e.preventDefault();
|
|
2306
|
+
handleToggle();
|
|
2307
|
+
} else if (e.key === "Escape" && ctx.snapshot.open) {
|
|
2308
|
+
e.preventDefault();
|
|
2309
|
+
handleClose();
|
|
2310
|
+
}
|
|
2311
|
+
}
|
|
2312
|
+
};
|
|
2313
|
+
}
|
|
2314
|
+
function attachListeners(el2, ls) {
|
|
2315
|
+
el2.addEventListener("mouseenter", ls.mouseenter);
|
|
2316
|
+
el2.addEventListener("mouseleave", ls.mouseleave);
|
|
2317
|
+
el2.addEventListener("mouseover", ls.mouseover);
|
|
2318
|
+
el2.addEventListener("click", ls.click);
|
|
2319
|
+
el2.addEventListener("keydown", ls.keydown);
|
|
2320
|
+
}
|
|
2321
|
+
function detachListeners(el2, ls) {
|
|
2322
|
+
el2.removeEventListener("mouseenter", ls.mouseenter);
|
|
2323
|
+
el2.removeEventListener("mouseleave", ls.mouseleave);
|
|
2324
|
+
el2.removeEventListener("mouseover", ls.mouseover);
|
|
2325
|
+
el2.removeEventListener("click", ls.click);
|
|
2326
|
+
el2.removeEventListener("keydown", ls.keydown);
|
|
2327
|
+
}
|
|
2328
|
+
function notchUpdate(ctx, opts, listeners) {
|
|
2329
|
+
if (opts.trigger !== void 0) ctx.trigger = opts.trigger;
|
|
2330
|
+
if (opts.position !== void 0) ctx.position = opts.position;
|
|
2331
|
+
if (opts.spring !== void 0) ctx.spring = opts.spring;
|
|
2332
|
+
if (opts.dotSize !== void 0) ctx.dotSize = opts.dotSize;
|
|
2333
|
+
if (opts.roundness !== void 0) ctx.roundness = opts.roundness;
|
|
2334
|
+
if (opts.theme !== void 0) ctx.theme = opts.theme;
|
|
2335
|
+
if (opts.fill !== void 0) ctx.fill = opts.fill;
|
|
2336
|
+
if (opts.open !== void 0) ctx.controlledOpen = opts.open;
|
|
2337
|
+
if (opts.onOpenChange !== void 0) ctx.onOpenChange = opts.onOpenChange;
|
|
2338
|
+
if (opts.pill !== void 0) {
|
|
2339
|
+
ctx.dom.pillDiv.textContent = "";
|
|
2340
|
+
ctx.dom.pillDiv.appendChild(resolveContent(opts.pill));
|
|
2341
|
+
}
|
|
2342
|
+
if (opts.content !== void 0) {
|
|
2343
|
+
ctx.dom.contentDiv.textContent = "";
|
|
2344
|
+
ctx.dom.contentDiv.appendChild(resolveContent(opts.content));
|
|
2345
|
+
ctx.dom.measureEl.textContent = "";
|
|
2346
|
+
ctx.dom.measureEl.appendChild(resolveContent(opts.content).cloneNode(true));
|
|
2347
|
+
}
|
|
2348
|
+
ctx.dom.pillDiv.style.width = `${ctx.dotSize}px`;
|
|
2349
|
+
ctx.dom.pillDiv.style.height = `${ctx.dotSize}px`;
|
|
2350
|
+
ctx.machine.configure({ position: ctx.position, trigger: ctx.trigger, roundness: ctx.roundness, fill: ctx.fill, spring: ctx.spring });
|
|
2351
|
+
if (ctx.controlledOpen !== void 0) {
|
|
2352
|
+
if (ctx.controlledOpen && !ctx.snapshot.open) ctx.machine.open();
|
|
2353
|
+
else if (!ctx.controlledOpen && ctx.snapshot.open) ctx.machine.close();
|
|
2354
|
+
}
|
|
2355
|
+
detachListeners(ctx.dom.rootEl, listeners);
|
|
2356
|
+
const newListeners = createListeners(ctx);
|
|
2357
|
+
Object.assign(listeners, newListeners);
|
|
2358
|
+
attachListeners(ctx.dom.rootEl, listeners);
|
|
2359
|
+
updateLayout(ctx);
|
|
2360
|
+
return listeners;
|
|
2361
|
+
}
|
|
2362
|
+
function createNotch(container, options) {
|
|
2363
|
+
const machine2 = createNotchMachine({
|
|
2364
|
+
position: options.position ?? "top-center",
|
|
2365
|
+
trigger: options.trigger ?? "click",
|
|
2366
|
+
roundness: options.roundness ?? NOTCH_DEFAULTS.roundness,
|
|
2367
|
+
fill: options.fill,
|
|
2368
|
+
spring: options.spring
|
|
2369
|
+
});
|
|
2370
|
+
const dotSize = options.dotSize ?? 36;
|
|
2371
|
+
const roundness = options.roundness ?? NOTCH_DEFAULTS.roundness;
|
|
2372
|
+
const spring = options.spring;
|
|
2373
|
+
const domCfg = {
|
|
2374
|
+
snapshot: machine2.store.getSnapshot(),
|
|
2375
|
+
position: options.position ?? "top-center",
|
|
2376
|
+
theme: options.theme ?? "dark",
|
|
2377
|
+
dotSize,
|
|
2378
|
+
fill: options.fill,
|
|
2379
|
+
contentSize: { w: 200, h: 44 },
|
|
2380
|
+
roundness};
|
|
2381
|
+
const dom = buildNotchDOM(domCfg, options.pill, options.content, container, () => springCfg(ctx));
|
|
2382
|
+
const ctx = {
|
|
2383
|
+
trigger: options.trigger ?? "click",
|
|
2384
|
+
position: options.position ?? "top-center",
|
|
2385
|
+
spring,
|
|
2386
|
+
dotSize,
|
|
2387
|
+
roundness,
|
|
2388
|
+
theme: options.theme ?? "dark",
|
|
2389
|
+
fill: options.fill,
|
|
2390
|
+
controlledOpen: options.open,
|
|
2391
|
+
onOpenChange: options.onOpenChange,
|
|
2392
|
+
snapshot: machine2.store.getSnapshot(),
|
|
2393
|
+
prevOpenVal: void 0,
|
|
2394
|
+
contentSize: { w: 200, h: 44 },
|
|
2395
|
+
currentAnim: null,
|
|
2396
|
+
measureRaf: 0,
|
|
2397
|
+
machine: machine2,
|
|
2398
|
+
prev: { w: dotSize, h: dotSize },
|
|
2399
|
+
highlight: dom.highlight,
|
|
2400
|
+
dom
|
|
2401
|
+
};
|
|
2402
|
+
let listeners = createListeners(ctx);
|
|
2403
|
+
attachListeners(ctx.dom.rootEl, listeners);
|
|
2152
2404
|
const measureObs = new ResizeObserver(() => {
|
|
2153
|
-
cancelAnimationFrame(measureRaf);
|
|
2154
|
-
measureRaf = requestAnimationFrame(() => {
|
|
2155
|
-
const r = measureEl.getBoundingClientRect();
|
|
2405
|
+
cancelAnimationFrame(ctx.measureRaf);
|
|
2406
|
+
ctx.measureRaf = requestAnimationFrame(() => {
|
|
2407
|
+
const r = ctx.dom.measureEl.getBoundingClientRect();
|
|
2156
2408
|
if (r.width > 0 && r.height > 0) {
|
|
2157
2409
|
const newSize = { w: Math.ceil(r.width), h: Math.ceil(r.height) };
|
|
2158
|
-
if (newSize.w !== contentSize.w || newSize.h !== contentSize.h) {
|
|
2159
|
-
contentSize = newSize;
|
|
2160
|
-
updateLayout();
|
|
2410
|
+
if (newSize.w !== ctx.contentSize.w || newSize.h !== ctx.contentSize.h) {
|
|
2411
|
+
ctx.contentSize = newSize;
|
|
2412
|
+
updateLayout(ctx);
|
|
2161
2413
|
}
|
|
2162
2414
|
}
|
|
2163
2415
|
});
|
|
2164
2416
|
});
|
|
2165
|
-
measureObs.observe(measureEl);
|
|
2166
|
-
function onItemEnter(e) {
|
|
2167
|
-
const target = e.target.closest("a, button");
|
|
2168
|
-
if (!target || !snapshot.open) return;
|
|
2169
|
-
const rootRect = rootEl.getBoundingClientRect();
|
|
2170
|
-
const itemW = target.offsetWidth;
|
|
2171
|
-
const itemH = target.offsetHeight;
|
|
2172
|
-
const itemRect = target.getBoundingClientRect();
|
|
2173
|
-
const itemCenterX = itemRect.left + itemRect.width / 2;
|
|
2174
|
-
const itemCenterY = itemRect.top + itemRect.height / 2;
|
|
2175
|
-
const padX = 8;
|
|
2176
|
-
const padY = 4;
|
|
2177
|
-
const blobOvershoot = Math.max(6, roundness * 0.35);
|
|
2178
|
-
const toW = itemW + padX * 2;
|
|
2179
|
-
const toH = Math.max(itemH + padY * 2, rootRect.height + blobOvershoot * 2);
|
|
2180
|
-
const toX = itemCenterX - rootRect.left - toW / 2;
|
|
2181
|
-
const toY = itemCenterY - rootRect.top - toH / 2;
|
|
2182
|
-
const toRx = toH / 2;
|
|
2183
|
-
const fromX = hlPrev.visible ? hlPrev.x : toX + toW / 2;
|
|
2184
|
-
const fromY = hlPrev.visible ? hlPrev.y : toY + toH / 2;
|
|
2185
|
-
const fromW = hlPrev.visible ? hlPrev.w : 0;
|
|
2186
|
-
const fromH = hlPrev.visible ? hlPrev.h : 0;
|
|
2187
|
-
const fromR = hlPrev.visible ? hlPrev.h / 2 : 0;
|
|
2188
|
-
if (highlightAnim) {
|
|
2189
|
-
highlightAnim.cancel();
|
|
2190
|
-
highlightAnim = null;
|
|
2191
|
-
}
|
|
2192
|
-
const sc = springConfig();
|
|
2193
|
-
const a = animateSpring(
|
|
2194
|
-
hoverBlobEl,
|
|
2195
|
-
{
|
|
2196
|
-
x: { from: fromX, to: toX, unit: "px" },
|
|
2197
|
-
y: { from: fromY, to: toY, unit: "px" },
|
|
2198
|
-
width: { from: fromW, to: toW, unit: "px" },
|
|
2199
|
-
height: { from: fromH, to: toH, unit: "px" },
|
|
2200
|
-
rx: { from: fromR, to: toRx, unit: "px" },
|
|
2201
|
-
ry: { from: fromR, to: toRx, unit: "px" }
|
|
2202
|
-
},
|
|
2203
|
-
{ ...sc, stiffness: (sc.stiffness ?? 300) * 1.2 }
|
|
2204
|
-
);
|
|
2205
|
-
hlPrev.x = toX;
|
|
2206
|
-
hlPrev.y = toY;
|
|
2207
|
-
hlPrev.w = toW;
|
|
2208
|
-
hlPrev.h = toH;
|
|
2209
|
-
if (a) {
|
|
2210
|
-
highlightAnim = a;
|
|
2211
|
-
a.onfinish = () => {
|
|
2212
|
-
highlightAnim = null;
|
|
2213
|
-
hoverBlobEl.setAttribute("x", String(toX));
|
|
2214
|
-
hoverBlobEl.setAttribute("y", String(toY));
|
|
2215
|
-
hoverBlobEl.setAttribute("width", String(toW));
|
|
2216
|
-
hoverBlobEl.setAttribute("height", String(toH));
|
|
2217
|
-
hoverBlobEl.setAttribute("rx", String(toRx));
|
|
2218
|
-
hoverBlobEl.setAttribute("ry", String(toRx));
|
|
2219
|
-
hoverBlobEl.setAttribute("opacity", "1");
|
|
2220
|
-
};
|
|
2221
|
-
} else {
|
|
2222
|
-
hoverBlobEl.setAttribute("x", String(toX));
|
|
2223
|
-
hoverBlobEl.setAttribute("y", String(toY));
|
|
2224
|
-
hoverBlobEl.setAttribute("width", String(toW));
|
|
2225
|
-
hoverBlobEl.setAttribute("height", String(toH));
|
|
2226
|
-
hoverBlobEl.setAttribute("rx", String(toRx));
|
|
2227
|
-
hoverBlobEl.setAttribute("ry", String(toRx));
|
|
2228
|
-
hoverBlobEl.setAttribute("opacity", "1");
|
|
2229
|
-
}
|
|
2230
|
-
hoverBlobEl.setAttribute("opacity", "1");
|
|
2231
|
-
hlPrev.visible = true;
|
|
2232
|
-
}
|
|
2233
|
-
function resetHoverBlobImmediate() {
|
|
2234
|
-
if (highlightAnim) {
|
|
2235
|
-
highlightAnim.cancel();
|
|
2236
|
-
highlightAnim = null;
|
|
2237
|
-
}
|
|
2238
|
-
hoverBlobEl.setAttribute("x", String(rootW() / 2));
|
|
2239
|
-
hoverBlobEl.setAttribute("y", String(rootH() / 2));
|
|
2240
|
-
hoverBlobEl.setAttribute("width", "0");
|
|
2241
|
-
hoverBlobEl.setAttribute("height", "0");
|
|
2242
|
-
hoverBlobEl.setAttribute("rx", "0");
|
|
2243
|
-
hoverBlobEl.setAttribute("ry", "0");
|
|
2244
|
-
hoverBlobEl.setAttribute("opacity", "0");
|
|
2245
|
-
hlPrev.visible = false;
|
|
2246
|
-
}
|
|
2247
|
-
function onItemLeave() {
|
|
2248
|
-
if (!hlPrev.visible) return;
|
|
2249
|
-
const cx = hlPrev.x + hlPrev.w / 2;
|
|
2250
|
-
const cy = hlPrev.y + hlPrev.h / 2;
|
|
2251
|
-
const sc = springConfig();
|
|
2252
|
-
const a = animateSpring(
|
|
2253
|
-
hoverBlobEl,
|
|
2254
|
-
{
|
|
2255
|
-
x: { from: hlPrev.x, to: cx, unit: "px" },
|
|
2256
|
-
y: { from: hlPrev.y, to: cy, unit: "px" },
|
|
2257
|
-
width: { from: hlPrev.w, to: 0, unit: "px" },
|
|
2258
|
-
height: { from: hlPrev.h, to: 0, unit: "px" },
|
|
2259
|
-
rx: { from: hlPrev.h / 2, to: 0, unit: "px" },
|
|
2260
|
-
ry: { from: hlPrev.h / 2, to: 0, unit: "px" }
|
|
2261
|
-
},
|
|
2262
|
-
{ ...sc, stiffness: (sc.stiffness ?? 300) * 1.2 }
|
|
2263
|
-
);
|
|
2264
|
-
if (a) {
|
|
2265
|
-
highlightAnim = a;
|
|
2266
|
-
a.onfinish = () => {
|
|
2267
|
-
highlightAnim = null;
|
|
2268
|
-
hoverBlobEl.setAttribute("x", String(cx));
|
|
2269
|
-
hoverBlobEl.setAttribute("y", String(cy));
|
|
2270
|
-
hoverBlobEl.setAttribute("width", "0");
|
|
2271
|
-
hoverBlobEl.setAttribute("height", "0");
|
|
2272
|
-
hoverBlobEl.setAttribute("rx", "0");
|
|
2273
|
-
hoverBlobEl.setAttribute("ry", "0");
|
|
2274
|
-
hoverBlobEl.setAttribute("opacity", "0");
|
|
2275
|
-
};
|
|
2276
|
-
} else {
|
|
2277
|
-
hoverBlobEl.setAttribute("x", String(cx));
|
|
2278
|
-
hoverBlobEl.setAttribute("y", String(cy));
|
|
2279
|
-
hoverBlobEl.setAttribute("width", "0");
|
|
2280
|
-
hoverBlobEl.setAttribute("height", "0");
|
|
2281
|
-
hoverBlobEl.setAttribute("rx", "0");
|
|
2282
|
-
hoverBlobEl.setAttribute("ry", "0");
|
|
2283
|
-
hoverBlobEl.setAttribute("opacity", "0");
|
|
2284
|
-
}
|
|
2285
|
-
hlPrev.visible = false;
|
|
2286
|
-
}
|
|
2287
|
-
function handleOpen() {
|
|
2288
|
-
if (controlledOpen === void 0) machine2.open();
|
|
2289
|
-
else onOpenChange?.(true);
|
|
2290
|
-
}
|
|
2291
|
-
function handleClose() {
|
|
2292
|
-
if (controlledOpen === void 0) machine2.close();
|
|
2293
|
-
else onOpenChange?.(false);
|
|
2294
|
-
}
|
|
2295
|
-
function handleToggle() {
|
|
2296
|
-
if (controlledOpen === void 0) machine2.toggle();
|
|
2297
|
-
else onOpenChange?.(!snapshot.open);
|
|
2298
|
-
}
|
|
2299
|
-
function onMouseEnter() {
|
|
2300
|
-
if (trigger === "hover") handleOpen();
|
|
2301
|
-
}
|
|
2302
|
-
function onMouseLeave() {
|
|
2303
|
-
if (trigger === "hover") {
|
|
2304
|
-
handleClose();
|
|
2305
|
-
resetHoverBlobImmediate();
|
|
2306
|
-
return;
|
|
2307
|
-
}
|
|
2308
|
-
onItemLeave();
|
|
2309
|
-
}
|
|
2310
|
-
function onClick() {
|
|
2311
|
-
if (trigger === "click") handleToggle();
|
|
2312
|
-
}
|
|
2313
|
-
rootEl.addEventListener("mouseenter", onMouseEnter);
|
|
2314
|
-
rootEl.addEventListener("mouseleave", onMouseLeave);
|
|
2315
|
-
rootEl.addEventListener("mouseover", onItemEnter);
|
|
2316
|
-
rootEl.addEventListener("click", onClick);
|
|
2317
|
-
function animateRect() {
|
|
2318
|
-
const tw = targetW();
|
|
2319
|
-
const th = targetH();
|
|
2320
|
-
if (tw === prev.w && th === prev.h) return;
|
|
2321
|
-
if (currentAnim) {
|
|
2322
|
-
currentAnim.cancel();
|
|
2323
|
-
currentAnim = null;
|
|
2324
|
-
}
|
|
2325
|
-
const rw = rootW();
|
|
2326
|
-
const rh = rootH();
|
|
2327
|
-
const fromW = prev.w;
|
|
2328
|
-
const fromH = prev.h;
|
|
2329
|
-
const fromX = (rw - fromW) / 2;
|
|
2330
|
-
const fromY = (rh - fromH) / 2;
|
|
2331
|
-
const toX = (rw - tw) / 2;
|
|
2332
|
-
const toY = (rh - th) / 2;
|
|
2333
|
-
prev.w = tw;
|
|
2334
|
-
prev.h = th;
|
|
2335
|
-
const isCollapsing = tw === collapsedW() && th === collapsedH();
|
|
2336
|
-
const wasCollapsed = fromW === collapsedW() && fromH === collapsedH();
|
|
2337
|
-
const fromRx = wasCollapsed ? collapsedW() / 2 : roundness;
|
|
2338
|
-
const toRx = isCollapsing ? collapsedW() / 2 : roundness;
|
|
2339
|
-
const a = animateSpring(
|
|
2340
|
-
svgRectEl,
|
|
2341
|
-
{
|
|
2342
|
-
width: { from: fromW, to: tw, unit: "px" },
|
|
2343
|
-
height: { from: fromH, to: th, unit: "px" },
|
|
2344
|
-
x: { from: fromX, to: toX, unit: "px" },
|
|
2345
|
-
y: { from: fromY, to: toY, unit: "px" },
|
|
2346
|
-
rx: { from: fromRx, to: toRx, unit: "px" },
|
|
2347
|
-
ry: { from: fromRx, to: toRx, unit: "px" }
|
|
2348
|
-
},
|
|
2349
|
-
springConfig()
|
|
2350
|
-
);
|
|
2351
|
-
if (a) {
|
|
2352
|
-
currentAnim = a;
|
|
2353
|
-
a.onfinish = () => {
|
|
2354
|
-
currentAnim = null;
|
|
2355
|
-
svgRectEl.setAttribute("width", String(tw));
|
|
2356
|
-
svgRectEl.setAttribute("height", String(th));
|
|
2357
|
-
svgRectEl.setAttribute("x", String(toX));
|
|
2358
|
-
svgRectEl.setAttribute("y", String(toY));
|
|
2359
|
-
svgRectEl.setAttribute("rx", String(toRx));
|
|
2360
|
-
svgRectEl.setAttribute("ry", String(toRx));
|
|
2361
|
-
};
|
|
2362
|
-
} else {
|
|
2363
|
-
svgRectEl.setAttribute("width", String(tw));
|
|
2364
|
-
svgRectEl.setAttribute("height", String(th));
|
|
2365
|
-
svgRectEl.setAttribute("x", String(toX));
|
|
2366
|
-
svgRectEl.setAttribute("y", String(toY));
|
|
2367
|
-
svgRectEl.setAttribute("rx", String(toRx));
|
|
2368
|
-
svgRectEl.setAttribute("ry", String(toRx));
|
|
2369
|
-
}
|
|
2370
|
-
}
|
|
2371
|
-
function updateLayout() {
|
|
2372
|
-
const isOpen = snapshot.open;
|
|
2373
|
-
const newAttrs = getNotchAttrs({ open: isOpen, position, theme });
|
|
2374
|
-
applyAttrs2(rootEl, newAttrs.root);
|
|
2375
|
-
rootEl.style.width = `${rootW()}px`;
|
|
2376
|
-
rootEl.style.height = `${rootH()}px`;
|
|
2377
|
-
svg.setAttribute("width", String(rootW()));
|
|
2378
|
-
svg.setAttribute("height", String(rootH()));
|
|
2379
|
-
svg.setAttribute("viewBox", `0 0 ${rootW()} ${rootH()}`);
|
|
2380
|
-
feBlur.setAttribute("stdDeviation", String(blur()));
|
|
2381
|
-
svgRectEl.setAttribute("fill", fill ?? "var(--fluix-notch-bg)");
|
|
2382
|
-
hoverBlobEl.setAttribute("fill", fill ?? "var(--fluix-notch-bg)");
|
|
2383
|
-
applyAttrs2(contentDiv, newAttrs.content);
|
|
2384
|
-
animateRect();
|
|
2385
|
-
if (!isOpen) {
|
|
2386
|
-
resetHoverBlobImmediate();
|
|
2387
|
-
}
|
|
2388
|
-
document.documentElement.style.setProperty(
|
|
2389
|
-
"--fluix-notch-offset",
|
|
2390
|
-
`${rootH()}px`
|
|
2391
|
-
);
|
|
2392
|
-
}
|
|
2417
|
+
measureObs.observe(ctx.dom.measureEl);
|
|
2393
2418
|
const unsubscribe = machine2.store.subscribe(() => {
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
if (controlledOpen &&
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
}
|
|
2403
|
-
prevOpenVal = next.open;
|
|
2404
|
-
updateLayout();
|
|
2419
|
+
ctx.snapshot = machine2.store.getSnapshot();
|
|
2420
|
+
if (ctx.controlledOpen !== void 0) {
|
|
2421
|
+
if (ctx.controlledOpen && !ctx.snapshot.open) machine2.open();
|
|
2422
|
+
else if (!ctx.controlledOpen && ctx.snapshot.open) machine2.close();
|
|
2423
|
+
}
|
|
2424
|
+
if (ctx.prevOpenVal !== void 0 && ctx.prevOpenVal !== ctx.snapshot.open) ctx.onOpenChange?.(ctx.snapshot.open);
|
|
2425
|
+
ctx.prevOpenVal = ctx.snapshot.open;
|
|
2426
|
+
updateLayout(ctx);
|
|
2405
2427
|
});
|
|
2406
|
-
updateLayout();
|
|
2407
|
-
document.documentElement.style.setProperty(
|
|
2408
|
-
"--fluix-notch-offset",
|
|
2409
|
-
`${rootH()}px`
|
|
2410
|
-
);
|
|
2428
|
+
updateLayout(ctx);
|
|
2429
|
+
document.documentElement.style.setProperty("--fluix-notch-offset", `${dims(ctx).rH}px`);
|
|
2411
2430
|
return {
|
|
2412
2431
|
open() {
|
|
2413
|
-
|
|
2432
|
+
ctx.controlledOpen === void 0 ? machine2.open() : ctx.onOpenChange?.(true);
|
|
2414
2433
|
},
|
|
2415
2434
|
close() {
|
|
2416
|
-
|
|
2435
|
+
ctx.controlledOpen === void 0 ? machine2.close() : ctx.onOpenChange?.(false);
|
|
2417
2436
|
},
|
|
2418
2437
|
toggle() {
|
|
2419
|
-
|
|
2438
|
+
ctx.controlledOpen === void 0 ? machine2.toggle() : ctx.onOpenChange?.(!ctx.snapshot.open);
|
|
2420
2439
|
},
|
|
2421
2440
|
destroy() {
|
|
2422
2441
|
unsubscribe();
|
|
2423
|
-
cancelAnimationFrame(measureRaf);
|
|
2442
|
+
cancelAnimationFrame(ctx.measureRaf);
|
|
2424
2443
|
measureObs.disconnect();
|
|
2425
|
-
currentAnim?.cancel();
|
|
2426
|
-
|
|
2427
|
-
rootEl
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
rootEl.
|
|
2431
|
-
measureEl.remove();
|
|
2432
|
-
rootEl.remove();
|
|
2444
|
+
ctx.currentAnim?.cancel();
|
|
2445
|
+
ctx.highlight.cancelAnim();
|
|
2446
|
+
detachListeners(ctx.dom.rootEl, listeners);
|
|
2447
|
+
machine2.destroy();
|
|
2448
|
+
ctx.dom.measureEl.remove();
|
|
2449
|
+
ctx.dom.rootEl.remove();
|
|
2433
2450
|
document.documentElement.style.removeProperty("--fluix-notch-offset");
|
|
2434
2451
|
},
|
|
2435
2452
|
update(opts) {
|
|
2436
|
-
|
|
2437
|
-
if (opts.position !== void 0) position = opts.position;
|
|
2438
|
-
if (opts.spring !== void 0) spring = opts.spring;
|
|
2439
|
-
if (opts.dotSize !== void 0) dotSize = opts.dotSize;
|
|
2440
|
-
if (opts.roundness !== void 0) roundness = opts.roundness;
|
|
2441
|
-
if (opts.theme !== void 0) theme = opts.theme;
|
|
2442
|
-
if (opts.fill !== void 0) fill = opts.fill;
|
|
2443
|
-
if (opts.open !== void 0) controlledOpen = opts.open;
|
|
2444
|
-
if (opts.onOpenChange !== void 0) onOpenChange = opts.onOpenChange;
|
|
2445
|
-
if (opts.pill !== void 0) {
|
|
2446
|
-
pillDiv.textContent = "";
|
|
2447
|
-
pillDiv.appendChild(resolveContent(opts.pill));
|
|
2448
|
-
}
|
|
2449
|
-
if (opts.content !== void 0) {
|
|
2450
|
-
contentDiv.textContent = "";
|
|
2451
|
-
contentDiv.appendChild(resolveContent(opts.content));
|
|
2452
|
-
measureEl.textContent = "";
|
|
2453
|
-
measureEl.appendChild(resolveContent(opts.content).cloneNode(true));
|
|
2454
|
-
}
|
|
2455
|
-
pillDiv.style.width = `${dotSize}px`;
|
|
2456
|
-
pillDiv.style.height = `${dotSize}px`;
|
|
2457
|
-
machine2.configure({ position, trigger, roundness, fill, spring });
|
|
2458
|
-
if (controlledOpen !== void 0) {
|
|
2459
|
-
if (controlledOpen && !snapshot.open) machine2.open();
|
|
2460
|
-
else if (!controlledOpen && snapshot.open) machine2.close();
|
|
2461
|
-
}
|
|
2462
|
-
rootEl.removeEventListener("mouseenter", onMouseEnter);
|
|
2463
|
-
rootEl.removeEventListener("mouseleave", onMouseLeave);
|
|
2464
|
-
rootEl.removeEventListener("click", onClick);
|
|
2465
|
-
rootEl.addEventListener("mouseenter", onMouseEnter);
|
|
2466
|
-
rootEl.addEventListener("mouseleave", onMouseLeave);
|
|
2467
|
-
rootEl.addEventListener("click", onClick);
|
|
2468
|
-
updateLayout();
|
|
2453
|
+
listeners = notchUpdate(ctx, opts, listeners);
|
|
2469
2454
|
}
|
|
2470
2455
|
};
|
|
2471
2456
|
}
|
|
2472
2457
|
|
|
2473
|
-
// src/menu.ts
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2458
|
+
// src/menu/index.ts
|
|
2459
|
+
function buildSvgIndicator(svg, isTab, filterId, resolvedBlur, fill, indicatorAttrs) {
|
|
2460
|
+
clearChildren(svg);
|
|
2461
|
+
const effectiveFill = fill ?? "var(--fluix-menu-indicator)";
|
|
2462
|
+
if (isTab) {
|
|
2463
|
+
const indicatorEl2 = document.createElementNS(SVG_NS, "path");
|
|
2464
|
+
applyAttrs(indicatorEl2, indicatorAttrs);
|
|
2465
|
+
indicatorEl2.setAttribute("d", "");
|
|
2466
|
+
indicatorEl2.setAttribute("opacity", "0");
|
|
2467
|
+
indicatorEl2.style.fill = effectiveFill;
|
|
2468
|
+
svg.appendChild(indicatorEl2);
|
|
2469
|
+
return { indicatorEl: indicatorEl2, ghostIndicatorEl: null };
|
|
2470
|
+
}
|
|
2471
|
+
const { g, defs } = createGooeyFilter(filterId, resolvedBlur);
|
|
2472
|
+
svg.appendChild(defs);
|
|
2473
|
+
const ghostIndicatorEl = document.createElementNS(SVG_NS, "rect");
|
|
2474
|
+
zeroRect(ghostIndicatorEl);
|
|
2475
|
+
ghostIndicatorEl.setAttribute("opacity", "0");
|
|
2476
|
+
ghostIndicatorEl.style.fill = effectiveFill;
|
|
2477
|
+
const indicatorEl = document.createElementNS(SVG_NS, "rect");
|
|
2478
|
+
applyAttrs(indicatorEl, indicatorAttrs);
|
|
2479
|
+
zeroRect(indicatorEl);
|
|
2480
|
+
indicatorEl.setAttribute("opacity", "0");
|
|
2481
|
+
indicatorEl.style.fill = effectiveFill;
|
|
2482
|
+
g.appendChild(ghostIndicatorEl);
|
|
2483
|
+
g.appendChild(indicatorEl);
|
|
2484
|
+
svg.appendChild(g);
|
|
2485
|
+
return { indicatorEl, ghostIndicatorEl };
|
|
2486
|
+
}
|
|
2487
|
+
function buildMenuDOM(attrs, filterId, variant, resolvedBlur, fill) {
|
|
2488
|
+
const navEl = document.createElement("nav");
|
|
2489
|
+
applyAttrs(navEl, attrs.root);
|
|
2490
|
+
navEl.setAttribute("aria-label", "Fluix menu");
|
|
2491
|
+
const canvasDiv = document.createElement("div");
|
|
2492
|
+
applyAttrs(canvasDiv, attrs.canvas);
|
|
2493
|
+
const svg = document.createElementNS(SVG_NS, "svg");
|
|
2494
|
+
svg.setAttribute("xmlns", SVG_NS);
|
|
2495
|
+
for (const [k, v] of Object.entries({ width: "1", height: "1", viewBox: "0 0 1 1", "aria-hidden": "true" })) svg.setAttribute(k, v);
|
|
2496
|
+
const { indicatorEl, ghostIndicatorEl } = buildSvgIndicator(svg, variant === "tab", filterId, resolvedBlur, fill, attrs.indicator);
|
|
2497
|
+
canvasDiv.appendChild(svg);
|
|
2498
|
+
navEl.appendChild(canvasDiv);
|
|
2499
|
+
const listDiv = document.createElement("div");
|
|
2500
|
+
applyAttrs(listDiv, attrs.list);
|
|
2501
|
+
navEl.appendChild(listDiv);
|
|
2502
|
+
return { navEl, svg, listDiv, buttonMap: /* @__PURE__ */ new Map(), indicatorEl, ghostIndicatorEl };
|
|
2503
|
+
}
|
|
2504
|
+
function createItemButton(ctx, item) {
|
|
2505
|
+
const btn = document.createElement("button");
|
|
2506
|
+
btn.type = "button";
|
|
2507
|
+
const active = ctx.snapshot.activeId === item.id;
|
|
2508
|
+
applyAttrs(btn, ctx.attrs.item({ id: item.id, active, disabled: item.disabled }));
|
|
2509
|
+
if (item.disabled) btn.disabled = true;
|
|
2510
|
+
btn.textContent = item.label;
|
|
2511
|
+
btn.addEventListener("click", () => {
|
|
2512
|
+
if (item.disabled) return;
|
|
2513
|
+
if (ctx.controlledActiveId === void 0) ctx.machine.setActive(item.id);
|
|
2514
|
+
else ctx.onActiveChange?.(item.id);
|
|
2515
|
+
});
|
|
2516
|
+
ctx.buttonMap.set(item.id, btn);
|
|
2517
|
+
ctx.listDiv.appendChild(btn);
|
|
2518
|
+
}
|
|
2519
|
+
function makeConnection(ctx) {
|
|
2520
|
+
return connectMenu({
|
|
2521
|
+
root: ctx.navEl,
|
|
2522
|
+
indicator: ctx.indicatorEl,
|
|
2523
|
+
ghostIndicator: ctx.ghostIndicatorEl,
|
|
2524
|
+
getActiveId: () => ctx.snapshot.activeId,
|
|
2525
|
+
onSelect(id) {
|
|
2526
|
+
if (ctx.controlledActiveId === void 0) ctx.machine.setActive(id);
|
|
2527
|
+
else ctx.onActiveChange?.(id);
|
|
2528
|
+
},
|
|
2529
|
+
spring: ctx.spring ?? FLUIX_SPRING,
|
|
2530
|
+
variant: ctx.variant,
|
|
2531
|
+
orientation: ctx.orientation
|
|
2532
|
+
});
|
|
2533
|
+
}
|
|
2534
|
+
function measure(ctx) {
|
|
2535
|
+
const rect = ctx.navEl.getBoundingClientRect();
|
|
2536
|
+
const w = Math.ceil(rect.width);
|
|
2537
|
+
const h = Math.ceil(rect.height);
|
|
2538
|
+
if (ctx.size.width !== w || ctx.size.height !== h) {
|
|
2539
|
+
ctx.size = { width: w, height: h };
|
|
2540
|
+
const sw = Math.max(1, w);
|
|
2541
|
+
const sh = Math.max(1, h);
|
|
2542
|
+
ctx.svg.setAttribute("width", String(sw));
|
|
2543
|
+
ctx.svg.setAttribute("height", String(sh));
|
|
2544
|
+
ctx.svg.setAttribute("viewBox", `0 0 ${sw} ${sh}`);
|
|
2545
|
+
ctx.connection?.sync(false);
|
|
2479
2546
|
}
|
|
2480
2547
|
}
|
|
2548
|
+
function menuUpdate(ctx, opts) {
|
|
2549
|
+
const prevVariant = ctx.variant;
|
|
2550
|
+
if (opts.orientation !== void 0) ctx.orientation = opts.orientation;
|
|
2551
|
+
if (opts.variant !== void 0) ctx.variant = opts.variant;
|
|
2552
|
+
if (opts.theme !== void 0) ctx.theme = opts.theme;
|
|
2553
|
+
if (opts.activeId !== void 0) ctx.controlledActiveId = opts.activeId;
|
|
2554
|
+
if (opts.onActiveChange !== void 0) ctx.onActiveChange = opts.onActiveChange;
|
|
2555
|
+
if (opts.spring !== void 0) ctx.spring = opts.spring;
|
|
2556
|
+
if (opts.roundness !== void 0) ctx.roundness = opts.roundness;
|
|
2557
|
+
if (opts.blur !== void 0) ctx.blurProp = opts.blur;
|
|
2558
|
+
if (opts.fill !== void 0) ctx.fill = opts.fill;
|
|
2559
|
+
ctx.machine.configure({ orientation: ctx.orientation, variant: ctx.variant, spring: ctx.spring, roundness: ctx.roundness, blur: ctx.blurProp, fill: ctx.fill });
|
|
2560
|
+
if (ctx.controlledActiveId !== void 0) ctx.machine.setActive(ctx.controlledActiveId ?? null);
|
|
2561
|
+
ctx.attrs = getMenuAttrs({ orientation: ctx.orientation, theme: ctx.theme, variant: ctx.variant });
|
|
2562
|
+
applyAttrs(ctx.navEl, ctx.attrs.root);
|
|
2563
|
+
if (prevVariant !== ctx.variant) {
|
|
2564
|
+
const resolvedBlur = ctx.blurProp ?? Math.min(10, Math.max(6, ctx.roundness * 0.45));
|
|
2565
|
+
const refs = buildSvgIndicator(ctx.svg, ctx.variant === "tab", ctx.filterId, resolvedBlur, ctx.fill, ctx.attrs.indicator);
|
|
2566
|
+
ctx.indicatorEl = refs.indicatorEl;
|
|
2567
|
+
ctx.ghostIndicatorEl = refs.ghostIndicatorEl;
|
|
2568
|
+
}
|
|
2569
|
+
if (opts.items !== void 0) {
|
|
2570
|
+
ctx.items = opts.items;
|
|
2571
|
+
clearChildren(ctx.listDiv);
|
|
2572
|
+
ctx.buttonMap.clear();
|
|
2573
|
+
for (const item of ctx.items) createItemButton(ctx, item);
|
|
2574
|
+
}
|
|
2575
|
+
ctx.connection.destroy();
|
|
2576
|
+
ctx.connection = makeConnection(ctx);
|
|
2577
|
+
requestAnimationFrame(() => {
|
|
2578
|
+
measure(ctx);
|
|
2579
|
+
ctx.connection.sync(false);
|
|
2580
|
+
});
|
|
2581
|
+
}
|
|
2481
2582
|
function createMenu(container, options) {
|
|
2482
|
-
|
|
2583
|
+
const {
|
|
2483
2584
|
orientation = MENU_DEFAULTS.orientation,
|
|
2484
2585
|
variant = "pill",
|
|
2485
2586
|
theme = "dark",
|
|
@@ -2491,8 +2592,6 @@ var Fluix = (function (exports) {
|
|
|
2491
2592
|
fill,
|
|
2492
2593
|
items
|
|
2493
2594
|
} = options;
|
|
2494
|
-
const springConfig = () => spring ?? FLUIX_SPRING;
|
|
2495
|
-
const resolvedBlur = () => blurProp ?? Math.min(10, Math.max(6, roundness * 0.45));
|
|
2496
2595
|
const machine2 = createMenuMachine({
|
|
2497
2596
|
orientation,
|
|
2498
2597
|
variant,
|
|
@@ -2502,216 +2601,69 @@ var Fluix = (function (exports) {
|
|
|
2502
2601
|
fill,
|
|
2503
2602
|
initialActiveId: controlledActiveId ?? null
|
|
2504
2603
|
});
|
|
2505
|
-
let snapshot = machine2.store.getSnapshot();
|
|
2506
|
-
let lastActiveNotified = snapshot.activeId;
|
|
2507
2604
|
const attrs = getMenuAttrs({ orientation, theme, variant });
|
|
2508
2605
|
const filterId = `fluix-menu-goo-${Math.random().toString(36).slice(2, 8)}`;
|
|
2509
|
-
const
|
|
2510
|
-
const
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
const filter = document.createElementNS(SVG_NS3, "filter");
|
|
2532
|
-
filter.setAttribute("id", filterId);
|
|
2533
|
-
filter.setAttribute("x", "-20%");
|
|
2534
|
-
filter.setAttribute("y", "-20%");
|
|
2535
|
-
filter.setAttribute("width", "140%");
|
|
2536
|
-
filter.setAttribute("height", "140%");
|
|
2537
|
-
filter.setAttribute("color-interpolation-filters", "sRGB");
|
|
2538
|
-
const feBlur = document.createElementNS(SVG_NS3, "feGaussianBlur");
|
|
2539
|
-
feBlur.setAttribute("in", "SourceGraphic");
|
|
2540
|
-
feBlur.setAttribute("stdDeviation", String(resolvedBlur()));
|
|
2541
|
-
feBlur.setAttribute("result", "blur");
|
|
2542
|
-
const feCM = document.createElementNS(SVG_NS3, "feColorMatrix");
|
|
2543
|
-
feCM.setAttribute("in", "blur");
|
|
2544
|
-
feCM.setAttribute("type", "matrix");
|
|
2545
|
-
feCM.setAttribute("values", GOO_MATRIX);
|
|
2546
|
-
feCM.setAttribute("result", "goo");
|
|
2547
|
-
const feComp = document.createElementNS(SVG_NS3, "feComposite");
|
|
2548
|
-
feComp.setAttribute("in", "SourceGraphic");
|
|
2549
|
-
feComp.setAttribute("in2", "goo");
|
|
2550
|
-
feComp.setAttribute("operator", "atop");
|
|
2551
|
-
filter.appendChild(feBlur);
|
|
2552
|
-
filter.appendChild(feCM);
|
|
2553
|
-
filter.appendChild(feComp);
|
|
2554
|
-
defs.appendChild(filter);
|
|
2555
|
-
svg.appendChild(defs);
|
|
2556
|
-
const gGroup = document.createElementNS(SVG_NS3, "g");
|
|
2557
|
-
gGroup.setAttribute("filter", `url(#${filterId})`);
|
|
2558
|
-
indicatorEl = document.createElementNS(SVG_NS3, "rect");
|
|
2559
|
-
applyAttrs3(indicatorEl, attrs.indicator);
|
|
2560
|
-
indicatorEl.setAttribute("x", "0");
|
|
2561
|
-
indicatorEl.setAttribute("y", "0");
|
|
2562
|
-
indicatorEl.setAttribute("width", "0");
|
|
2563
|
-
indicatorEl.setAttribute("height", "0");
|
|
2564
|
-
indicatorEl.setAttribute("rx", "0");
|
|
2565
|
-
indicatorEl.setAttribute("ry", "0");
|
|
2566
|
-
indicatorEl.setAttribute("opacity", "0");
|
|
2567
|
-
indicatorEl.style.fill = fill ?? "var(--fluix-menu-indicator)";
|
|
2568
|
-
gGroup.appendChild(indicatorEl);
|
|
2569
|
-
svg.appendChild(gGroup);
|
|
2570
|
-
}
|
|
2571
|
-
canvasDiv.appendChild(svg);
|
|
2572
|
-
navEl.appendChild(canvasDiv);
|
|
2573
|
-
const listDiv = document.createElement("div");
|
|
2574
|
-
applyAttrs3(listDiv, attrs.list);
|
|
2575
|
-
const buttonMap = /* @__PURE__ */ new Map();
|
|
2576
|
-
function createItemButton(item) {
|
|
2577
|
-
const btn = document.createElement("button");
|
|
2578
|
-
btn.type = "button";
|
|
2579
|
-
const active = snapshot.activeId === item.id;
|
|
2580
|
-
const itemAttrs = attrs.item({ id: item.id, active, disabled: item.disabled });
|
|
2581
|
-
applyAttrs3(btn, itemAttrs);
|
|
2582
|
-
if (item.disabled) btn.disabled = true;
|
|
2583
|
-
btn.textContent = item.label;
|
|
2584
|
-
btn.addEventListener("click", () => {
|
|
2585
|
-
if (item.disabled) return;
|
|
2586
|
-
if (controlledActiveId === void 0) {
|
|
2587
|
-
machine2.setActive(item.id);
|
|
2588
|
-
} else {
|
|
2589
|
-
onActiveChange?.(item.id);
|
|
2590
|
-
}
|
|
2591
|
-
});
|
|
2592
|
-
buttonMap.set(item.id, btn);
|
|
2593
|
-
listDiv.appendChild(btn);
|
|
2594
|
-
}
|
|
2595
|
-
for (const item of items) {
|
|
2596
|
-
createItemButton(item);
|
|
2597
|
-
}
|
|
2598
|
-
navEl.appendChild(listDiv);
|
|
2599
|
-
container.appendChild(navEl);
|
|
2600
|
-
let size = { width: 0, height: 0 };
|
|
2601
|
-
let measureRaf = 0;
|
|
2602
|
-
const measure = () => {
|
|
2603
|
-
const rect = navEl.getBoundingClientRect();
|
|
2604
|
-
const w = Math.ceil(rect.width);
|
|
2605
|
-
const h = Math.ceil(rect.height);
|
|
2606
|
-
if (size.width !== w || size.height !== h) {
|
|
2607
|
-
size = { width: w, height: h };
|
|
2608
|
-
updateSvgSize();
|
|
2609
|
-
connection?.sync(false);
|
|
2610
|
-
}
|
|
2606
|
+
const resolvedBlur = blurProp ?? Math.min(10, Math.max(6, roundness * 0.45));
|
|
2607
|
+
const dom = buildMenuDOM(attrs, filterId, variant, resolvedBlur, fill);
|
|
2608
|
+
const ctx = {
|
|
2609
|
+
orientation,
|
|
2610
|
+
variant,
|
|
2611
|
+
theme,
|
|
2612
|
+
controlledActiveId,
|
|
2613
|
+
onActiveChange,
|
|
2614
|
+
spring,
|
|
2615
|
+
roundness,
|
|
2616
|
+
blurProp,
|
|
2617
|
+
fill,
|
|
2618
|
+
items,
|
|
2619
|
+
attrs,
|
|
2620
|
+
filterId,
|
|
2621
|
+
machine: machine2,
|
|
2622
|
+
snapshot: machine2.store.getSnapshot(),
|
|
2623
|
+
lastActiveNotified: machine2.store.getSnapshot().activeId,
|
|
2624
|
+
...dom,
|
|
2625
|
+
connection: null,
|
|
2626
|
+
size: { width: 0, height: 0 },
|
|
2627
|
+
measureRaf: 0
|
|
2611
2628
|
};
|
|
2629
|
+
for (const item of items) createItemButton(ctx, item);
|
|
2630
|
+
container.appendChild(ctx.navEl);
|
|
2612
2631
|
const resizeObs = new ResizeObserver(() => {
|
|
2613
|
-
cancelAnimationFrame(measureRaf);
|
|
2614
|
-
measureRaf = requestAnimationFrame(measure);
|
|
2615
|
-
});
|
|
2616
|
-
resizeObs.observe(navEl);
|
|
2617
|
-
function updateSvgSize() {
|
|
2618
|
-
const w = Math.max(1, size.width);
|
|
2619
|
-
const h = Math.max(1, size.height);
|
|
2620
|
-
svg.setAttribute("width", String(w));
|
|
2621
|
-
svg.setAttribute("height", String(h));
|
|
2622
|
-
svg.setAttribute("viewBox", `0 0 ${w} ${h}`);
|
|
2623
|
-
}
|
|
2624
|
-
let connection = connectMenu({
|
|
2625
|
-
root: navEl,
|
|
2626
|
-
indicator: indicatorEl,
|
|
2627
|
-
getActiveId: () => snapshot.activeId,
|
|
2628
|
-
onSelect(id) {
|
|
2629
|
-
if (controlledActiveId === void 0) {
|
|
2630
|
-
machine2.setActive(id);
|
|
2631
|
-
} else {
|
|
2632
|
-
onActiveChange?.(id);
|
|
2633
|
-
}
|
|
2634
|
-
},
|
|
2635
|
-
spring: springConfig(),
|
|
2636
|
-
variant,
|
|
2637
|
-
orientation
|
|
2632
|
+
cancelAnimationFrame(ctx.measureRaf);
|
|
2633
|
+
ctx.measureRaf = requestAnimationFrame(() => measure(ctx));
|
|
2638
2634
|
});
|
|
2635
|
+
resizeObs.observe(ctx.navEl);
|
|
2636
|
+
ctx.connection = makeConnection(ctx);
|
|
2639
2637
|
requestAnimationFrame(() => {
|
|
2640
|
-
measure();
|
|
2641
|
-
connection.sync(false);
|
|
2638
|
+
measure(ctx);
|
|
2639
|
+
ctx.connection.sync(false);
|
|
2642
2640
|
});
|
|
2643
2641
|
const unsubscribe = machine2.store.subscribe(() => {
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
if (btn) {
|
|
2649
|
-
const active = next.activeId === item.id;
|
|
2650
|
-
const itemAttrs = attrs.item({ id: item.id, active, disabled: item.disabled });
|
|
2651
|
-
applyAttrs3(btn, itemAttrs);
|
|
2652
|
-
}
|
|
2642
|
+
ctx.snapshot = machine2.store.getSnapshot();
|
|
2643
|
+
for (const item of ctx.items) {
|
|
2644
|
+
const btn = ctx.buttonMap.get(item.id);
|
|
2645
|
+
if (btn) applyAttrs(btn, ctx.attrs.item({ id: item.id, active: ctx.snapshot.activeId === item.id, disabled: item.disabled }));
|
|
2653
2646
|
}
|
|
2654
|
-
if (
|
|
2655
|
-
onActiveChange(
|
|
2647
|
+
if (ctx.snapshot.activeId && ctx.lastActiveNotified !== ctx.snapshot.activeId && ctx.onActiveChange) {
|
|
2648
|
+
ctx.onActiveChange(ctx.snapshot.activeId);
|
|
2656
2649
|
}
|
|
2657
|
-
lastActiveNotified =
|
|
2658
|
-
connection.sync(false);
|
|
2650
|
+
ctx.lastActiveNotified = ctx.snapshot.activeId;
|
|
2651
|
+
ctx.connection.sync(false);
|
|
2659
2652
|
});
|
|
2660
2653
|
return {
|
|
2661
2654
|
setActive(id) {
|
|
2662
2655
|
machine2.setActive(id);
|
|
2663
2656
|
},
|
|
2664
2657
|
update(opts) {
|
|
2665
|
-
|
|
2666
|
-
if (opts.variant !== void 0) variant = opts.variant;
|
|
2667
|
-
if (opts.theme !== void 0) theme = opts.theme;
|
|
2668
|
-
if (opts.activeId !== void 0) controlledActiveId = opts.activeId;
|
|
2669
|
-
if (opts.onActiveChange !== void 0) onActiveChange = opts.onActiveChange;
|
|
2670
|
-
if (opts.spring !== void 0) spring = opts.spring;
|
|
2671
|
-
if (opts.roundness !== void 0) roundness = opts.roundness;
|
|
2672
|
-
if (opts.blur !== void 0) blurProp = opts.blur;
|
|
2673
|
-
if (opts.fill !== void 0) fill = opts.fill;
|
|
2674
|
-
machine2.configure({ orientation, variant, spring, roundness, blur: blurProp, fill });
|
|
2675
|
-
if (controlledActiveId !== void 0) {
|
|
2676
|
-
machine2.setActive(controlledActiveId ?? null);
|
|
2677
|
-
}
|
|
2678
|
-
const newAttrs = getMenuAttrs({ orientation, theme, variant });
|
|
2679
|
-
applyAttrs3(navEl, newAttrs.root);
|
|
2680
|
-
if (opts.items !== void 0) {
|
|
2681
|
-
items = opts.items;
|
|
2682
|
-
listDiv.innerHTML = "";
|
|
2683
|
-
buttonMap.clear();
|
|
2684
|
-
for (const item of items) {
|
|
2685
|
-
createItemButton(item);
|
|
2686
|
-
}
|
|
2687
|
-
}
|
|
2688
|
-
connection.destroy();
|
|
2689
|
-
connection = connectMenu({
|
|
2690
|
-
root: navEl,
|
|
2691
|
-
indicator: indicatorEl,
|
|
2692
|
-
getActiveId: () => snapshot.activeId,
|
|
2693
|
-
onSelect(id) {
|
|
2694
|
-
if (controlledActiveId === void 0) {
|
|
2695
|
-
machine2.setActive(id);
|
|
2696
|
-
} else {
|
|
2697
|
-
onActiveChange?.(id);
|
|
2698
|
-
}
|
|
2699
|
-
},
|
|
2700
|
-
spring: springConfig(),
|
|
2701
|
-
variant,
|
|
2702
|
-
orientation
|
|
2703
|
-
});
|
|
2704
|
-
requestAnimationFrame(() => {
|
|
2705
|
-
measure();
|
|
2706
|
-
connection.sync(false);
|
|
2707
|
-
});
|
|
2658
|
+
menuUpdate(ctx, opts);
|
|
2708
2659
|
},
|
|
2709
2660
|
destroy() {
|
|
2710
2661
|
unsubscribe();
|
|
2711
|
-
cancelAnimationFrame(measureRaf);
|
|
2662
|
+
cancelAnimationFrame(ctx.measureRaf);
|
|
2712
2663
|
resizeObs.disconnect();
|
|
2713
|
-
connection.destroy();
|
|
2714
|
-
|
|
2664
|
+
ctx.connection.destroy();
|
|
2665
|
+
machine2.destroy();
|
|
2666
|
+
ctx.navEl.remove();
|
|
2715
2667
|
}
|
|
2716
2668
|
};
|
|
2717
2669
|
}
|