@fluix-ui/vanilla 0.0.5 → 0.0.7

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.js CHANGED
@@ -1,4 +1,4 @@
1
- import { Toaster, TOAST_DEFAULTS, animateSpring, FLUIX_SPRING } from '@fluix-ui/core';
1
+ import { Toaster, NOTCH_DEFAULTS, createNotchMachine, getNotchAttrs, MENU_DEFAULTS, createMenuMachine, getMenuAttrs, connectMenu, FLUIX_SPRING, animateSpring, TOAST_DEFAULTS } from '@fluix-ui/core';
2
2
  export { fluix } from '@fluix-ui/core';
3
3
 
4
4
  // src/index.ts
@@ -781,7 +781,706 @@ function createToaster(config) {
781
781
  }
782
782
  };
783
783
  }
784
+ var SVG_NS2 = "http://www.w3.org/2000/svg";
785
+ function applyAttrs2(el, attrs) {
786
+ for (const [key, value] of Object.entries(attrs)) {
787
+ el.setAttribute(key, value);
788
+ }
789
+ }
790
+ function resolveContent(source) {
791
+ if (source instanceof HTMLElement) return source;
792
+ const span = document.createElement("span");
793
+ span.textContent = source;
794
+ return span;
795
+ }
796
+ function createNotch(container, options) {
797
+ let {
798
+ trigger = "click",
799
+ position = "top-center",
800
+ spring,
801
+ dotSize = 36,
802
+ roundness = NOTCH_DEFAULTS.roundness,
803
+ theme = "dark",
804
+ fill,
805
+ open: controlledOpen,
806
+ onOpenChange
807
+ } = options;
808
+ const springConfig = () => spring ?? FLUIX_SPRING;
809
+ const machine = createNotchMachine({
810
+ position,
811
+ trigger,
812
+ roundness,
813
+ fill,
814
+ spring
815
+ });
816
+ let snapshot = machine.store.getSnapshot();
817
+ let prevOpenVal;
818
+ const blur = () => Math.min(10, Math.max(6, roundness * 0.45));
819
+ const collapsedW = () => dotSize;
820
+ const collapsedH = () => dotSize;
821
+ let contentSize = { w: 200, h: 44 };
822
+ const hlPad = 12;
823
+ const expandedW = () => contentSize.w + hlPad * 2;
824
+ const expandedH = () => Math.max(contentSize.h + hlPad, dotSize);
825
+ const targetW = () => snapshot.open ? expandedW() : collapsedW();
826
+ const targetH = () => snapshot.open ? expandedH() : collapsedH();
827
+ const rootW = () => Math.max(expandedW(), collapsedW());
828
+ const rootH = () => Math.max(expandedH(), collapsedH());
829
+ const prev = { w: 0, h: 0, initialized: false };
830
+ let currentAnim = null;
831
+ let highlightAnim = null;
832
+ const hlPrev = { x: 0, y: 0, w: 0, h: 0, visible: false };
833
+ const measureEl = document.createElement("div");
834
+ measureEl.setAttribute("data-fluix-notch-measure", "");
835
+ measureEl.appendChild(resolveContent(options.content).cloneNode(true));
836
+ container.appendChild(measureEl);
837
+ const rootEl = document.createElement("div");
838
+ const attrs = getNotchAttrs({ open: snapshot.open, position, theme });
839
+ applyAttrs2(rootEl, attrs.root);
840
+ rootEl.style.width = `${rootW()}px`;
841
+ rootEl.style.height = `${rootH()}px`;
842
+ const canvasDiv = document.createElement("div");
843
+ applyAttrs2(canvasDiv, attrs.canvas);
844
+ const svg = document.createElementNS(SVG_NS2, "svg");
845
+ svg.setAttribute("xmlns", "http://www.w3.org/2000/svg");
846
+ svg.setAttribute("width", String(rootW()));
847
+ svg.setAttribute("height", String(rootH()));
848
+ svg.setAttribute("viewBox", `0 0 ${rootW()} ${rootH()}`);
849
+ svg.setAttribute("aria-hidden", "true");
850
+ const defs = document.createElementNS(SVG_NS2, "defs");
851
+ const filter = document.createElementNS(SVG_NS2, "filter");
852
+ filter.setAttribute("id", "fluix-notch-goo");
853
+ filter.setAttribute("x", "-20%");
854
+ filter.setAttribute("y", "-20%");
855
+ filter.setAttribute("width", "140%");
856
+ filter.setAttribute("height", "140%");
857
+ filter.setAttribute("color-interpolation-filters", "sRGB");
858
+ const feBlur = document.createElementNS(SVG_NS2, "feGaussianBlur");
859
+ feBlur.setAttribute("in", "SourceGraphic");
860
+ feBlur.setAttribute("stdDeviation", String(blur()));
861
+ feBlur.setAttribute("result", "blur");
862
+ const feCM = document.createElementNS(SVG_NS2, "feColorMatrix");
863
+ feCM.setAttribute("in", "blur");
864
+ feCM.setAttribute("type", "matrix");
865
+ feCM.setAttribute("values", "1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 20 -10");
866
+ feCM.setAttribute("result", "goo");
867
+ const feComp = document.createElementNS(SVG_NS2, "feComposite");
868
+ feComp.setAttribute("in", "SourceGraphic");
869
+ feComp.setAttribute("in2", "goo");
870
+ feComp.setAttribute("operator", "atop");
871
+ filter.appendChild(feBlur);
872
+ filter.appendChild(feCM);
873
+ filter.appendChild(feComp);
874
+ defs.appendChild(filter);
875
+ svg.appendChild(defs);
876
+ const gGroup = document.createElementNS(SVG_NS2, "g");
877
+ gGroup.setAttribute("filter", "url(#fluix-notch-goo)");
878
+ const svgRectEl = document.createElementNS(SVG_NS2, "rect");
879
+ const cw = collapsedW();
880
+ const ch = collapsedH();
881
+ svgRectEl.setAttribute("x", String((rootW() - cw) / 2));
882
+ svgRectEl.setAttribute("y", String((rootH() - ch) / 2));
883
+ svgRectEl.setAttribute("width", String(cw));
884
+ svgRectEl.setAttribute("height", String(ch));
885
+ svgRectEl.setAttribute("rx", String(cw / 2));
886
+ svgRectEl.setAttribute("ry", String(ch / 2));
887
+ svgRectEl.setAttribute("fill", fill ?? "var(--fluix-notch-bg)");
888
+ gGroup.appendChild(svgRectEl);
889
+ svg.appendChild(gGroup);
890
+ const hoverBlobEl = document.createElementNS(SVG_NS2, "rect");
891
+ hoverBlobEl.setAttribute("x", String((rootW() - cw) / 2));
892
+ hoverBlobEl.setAttribute("y", String((rootH() - ch) / 2));
893
+ hoverBlobEl.setAttribute("width", "0");
894
+ hoverBlobEl.setAttribute("height", "0");
895
+ hoverBlobEl.setAttribute("rx", "0");
896
+ hoverBlobEl.setAttribute("ry", "0");
897
+ hoverBlobEl.setAttribute("opacity", "0");
898
+ hoverBlobEl.setAttribute("fill", fill ?? "var(--fluix-notch-bg)");
899
+ gGroup.appendChild(hoverBlobEl);
900
+ canvasDiv.appendChild(svg);
901
+ rootEl.appendChild(canvasDiv);
902
+ const pillDiv = document.createElement("div");
903
+ applyAttrs2(pillDiv, attrs.pill);
904
+ pillDiv.style.width = `${dotSize}px`;
905
+ pillDiv.style.height = `${dotSize}px`;
906
+ pillDiv.appendChild(resolveContent(options.pill));
907
+ rootEl.appendChild(pillDiv);
908
+ const contentDiv = document.createElement("div");
909
+ applyAttrs2(contentDiv, attrs.content);
910
+ contentDiv.appendChild(resolveContent(options.content));
911
+ rootEl.appendChild(contentDiv);
912
+ container.appendChild(rootEl);
913
+ prev.w = cw;
914
+ prev.h = ch;
915
+ prev.initialized = true;
916
+ let measureRaf = 0;
917
+ const measureObs = new ResizeObserver(() => {
918
+ cancelAnimationFrame(measureRaf);
919
+ measureRaf = requestAnimationFrame(() => {
920
+ const r = measureEl.getBoundingClientRect();
921
+ if (r.width > 0 && r.height > 0) {
922
+ const newSize = { w: Math.ceil(r.width), h: Math.ceil(r.height) };
923
+ if (newSize.w !== contentSize.w || newSize.h !== contentSize.h) {
924
+ contentSize = newSize;
925
+ updateLayout();
926
+ }
927
+ }
928
+ });
929
+ });
930
+ measureObs.observe(measureEl);
931
+ function onItemEnter(e) {
932
+ const target = e.target.closest("a, button");
933
+ if (!target || !snapshot.open) return;
934
+ const rootRect = rootEl.getBoundingClientRect();
935
+ const itemW = target.offsetWidth;
936
+ const itemH = target.offsetHeight;
937
+ const itemRect = target.getBoundingClientRect();
938
+ const itemCenterX = itemRect.left + itemRect.width / 2;
939
+ const itemCenterY = itemRect.top + itemRect.height / 2;
940
+ const padX = 8;
941
+ const padY = 4;
942
+ const blobOvershoot = Math.max(6, roundness * 0.35);
943
+ const toW = itemW + padX * 2;
944
+ const toH = Math.max(itemH + padY * 2, rootRect.height + blobOvershoot * 2);
945
+ const toX = itemCenterX - rootRect.left - toW / 2;
946
+ const toY = itemCenterY - rootRect.top - toH / 2;
947
+ const toRx = toH / 2;
948
+ const fromX = hlPrev.visible ? hlPrev.x : toX + toW / 2;
949
+ const fromY = hlPrev.visible ? hlPrev.y : toY + toH / 2;
950
+ const fromW = hlPrev.visible ? hlPrev.w : 0;
951
+ const fromH = hlPrev.visible ? hlPrev.h : 0;
952
+ const fromR = hlPrev.visible ? hlPrev.h / 2 : 0;
953
+ if (highlightAnim) {
954
+ highlightAnim.cancel();
955
+ highlightAnim = null;
956
+ }
957
+ const sc = springConfig();
958
+ const a = animateSpring(
959
+ hoverBlobEl,
960
+ {
961
+ x: { from: fromX, to: toX, unit: "px" },
962
+ y: { from: fromY, to: toY, unit: "px" },
963
+ width: { from: fromW, to: toW, unit: "px" },
964
+ height: { from: fromH, to: toH, unit: "px" },
965
+ rx: { from: fromR, to: toRx, unit: "px" },
966
+ ry: { from: fromR, to: toRx, unit: "px" }
967
+ },
968
+ { ...sc, stiffness: (sc.stiffness ?? 300) * 1.2 }
969
+ );
970
+ hlPrev.x = toX;
971
+ hlPrev.y = toY;
972
+ hlPrev.w = toW;
973
+ hlPrev.h = toH;
974
+ if (a) {
975
+ highlightAnim = a;
976
+ a.onfinish = () => {
977
+ highlightAnim = null;
978
+ hoverBlobEl.setAttribute("x", String(toX));
979
+ hoverBlobEl.setAttribute("y", String(toY));
980
+ hoverBlobEl.setAttribute("width", String(toW));
981
+ hoverBlobEl.setAttribute("height", String(toH));
982
+ hoverBlobEl.setAttribute("rx", String(toRx));
983
+ hoverBlobEl.setAttribute("ry", String(toRx));
984
+ hoverBlobEl.setAttribute("opacity", "1");
985
+ };
986
+ } else {
987
+ hoverBlobEl.setAttribute("x", String(toX));
988
+ hoverBlobEl.setAttribute("y", String(toY));
989
+ hoverBlobEl.setAttribute("width", String(toW));
990
+ hoverBlobEl.setAttribute("height", String(toH));
991
+ hoverBlobEl.setAttribute("rx", String(toRx));
992
+ hoverBlobEl.setAttribute("ry", String(toRx));
993
+ hoverBlobEl.setAttribute("opacity", "1");
994
+ }
995
+ hoverBlobEl.setAttribute("opacity", "1");
996
+ hlPrev.visible = true;
997
+ }
998
+ function resetHoverBlobImmediate() {
999
+ if (highlightAnim) {
1000
+ highlightAnim.cancel();
1001
+ highlightAnim = null;
1002
+ }
1003
+ hoverBlobEl.setAttribute("x", String(rootW() / 2));
1004
+ hoverBlobEl.setAttribute("y", String(rootH() / 2));
1005
+ hoverBlobEl.setAttribute("width", "0");
1006
+ hoverBlobEl.setAttribute("height", "0");
1007
+ hoverBlobEl.setAttribute("rx", "0");
1008
+ hoverBlobEl.setAttribute("ry", "0");
1009
+ hoverBlobEl.setAttribute("opacity", "0");
1010
+ hlPrev.visible = false;
1011
+ }
1012
+ function onItemLeave() {
1013
+ if (!hlPrev.visible) return;
1014
+ const cx = hlPrev.x + hlPrev.w / 2;
1015
+ const cy = hlPrev.y + hlPrev.h / 2;
1016
+ const sc = springConfig();
1017
+ const a = animateSpring(
1018
+ hoverBlobEl,
1019
+ {
1020
+ x: { from: hlPrev.x, to: cx, unit: "px" },
1021
+ y: { from: hlPrev.y, to: cy, unit: "px" },
1022
+ width: { from: hlPrev.w, to: 0, unit: "px" },
1023
+ height: { from: hlPrev.h, to: 0, unit: "px" },
1024
+ rx: { from: hlPrev.h / 2, to: 0, unit: "px" },
1025
+ ry: { from: hlPrev.h / 2, to: 0, unit: "px" }
1026
+ },
1027
+ { ...sc, stiffness: (sc.stiffness ?? 300) * 1.2 }
1028
+ );
1029
+ if (a) {
1030
+ highlightAnim = a;
1031
+ a.onfinish = () => {
1032
+ highlightAnim = null;
1033
+ hoverBlobEl.setAttribute("x", String(cx));
1034
+ hoverBlobEl.setAttribute("y", String(cy));
1035
+ hoverBlobEl.setAttribute("width", "0");
1036
+ hoverBlobEl.setAttribute("height", "0");
1037
+ hoverBlobEl.setAttribute("rx", "0");
1038
+ hoverBlobEl.setAttribute("ry", "0");
1039
+ hoverBlobEl.setAttribute("opacity", "0");
1040
+ };
1041
+ } else {
1042
+ hoverBlobEl.setAttribute("x", String(cx));
1043
+ hoverBlobEl.setAttribute("y", String(cy));
1044
+ hoverBlobEl.setAttribute("width", "0");
1045
+ hoverBlobEl.setAttribute("height", "0");
1046
+ hoverBlobEl.setAttribute("rx", "0");
1047
+ hoverBlobEl.setAttribute("ry", "0");
1048
+ hoverBlobEl.setAttribute("opacity", "0");
1049
+ }
1050
+ hlPrev.visible = false;
1051
+ }
1052
+ function handleOpen() {
1053
+ if (controlledOpen === void 0) machine.open();
1054
+ else onOpenChange?.(true);
1055
+ }
1056
+ function handleClose() {
1057
+ if (controlledOpen === void 0) machine.close();
1058
+ else onOpenChange?.(false);
1059
+ }
1060
+ function handleToggle() {
1061
+ if (controlledOpen === void 0) machine.toggle();
1062
+ else onOpenChange?.(!snapshot.open);
1063
+ }
1064
+ function onMouseEnter() {
1065
+ if (trigger === "hover") handleOpen();
1066
+ }
1067
+ function onMouseLeave() {
1068
+ if (trigger === "hover") {
1069
+ handleClose();
1070
+ resetHoverBlobImmediate();
1071
+ return;
1072
+ }
1073
+ onItemLeave();
1074
+ }
1075
+ function onClick() {
1076
+ if (trigger === "click") handleToggle();
1077
+ }
1078
+ rootEl.addEventListener("mouseenter", onMouseEnter);
1079
+ rootEl.addEventListener("mouseleave", onMouseLeave);
1080
+ rootEl.addEventListener("mouseover", onItemEnter);
1081
+ rootEl.addEventListener("click", onClick);
1082
+ function animateRect() {
1083
+ const tw = targetW();
1084
+ const th = targetH();
1085
+ if (tw === prev.w && th === prev.h) return;
1086
+ if (currentAnim) {
1087
+ currentAnim.cancel();
1088
+ currentAnim = null;
1089
+ }
1090
+ const rw = rootW();
1091
+ const rh = rootH();
1092
+ const fromW = prev.w;
1093
+ const fromH = prev.h;
1094
+ const fromX = (rw - fromW) / 2;
1095
+ const fromY = (rh - fromH) / 2;
1096
+ const toX = (rw - tw) / 2;
1097
+ const toY = (rh - th) / 2;
1098
+ prev.w = tw;
1099
+ prev.h = th;
1100
+ const isCollapsing = tw === collapsedW() && th === collapsedH();
1101
+ const wasCollapsed = fromW === collapsedW() && fromH === collapsedH();
1102
+ const fromRx = wasCollapsed ? collapsedW() / 2 : roundness;
1103
+ const toRx = isCollapsing ? collapsedW() / 2 : roundness;
1104
+ const a = animateSpring(
1105
+ svgRectEl,
1106
+ {
1107
+ width: { from: fromW, to: tw, unit: "px" },
1108
+ height: { from: fromH, to: th, unit: "px" },
1109
+ x: { from: fromX, to: toX, unit: "px" },
1110
+ y: { from: fromY, to: toY, unit: "px" },
1111
+ rx: { from: fromRx, to: toRx, unit: "px" },
1112
+ ry: { from: fromRx, to: toRx, unit: "px" }
1113
+ },
1114
+ springConfig()
1115
+ );
1116
+ if (a) {
1117
+ currentAnim = a;
1118
+ a.onfinish = () => {
1119
+ currentAnim = null;
1120
+ svgRectEl.setAttribute("width", String(tw));
1121
+ svgRectEl.setAttribute("height", String(th));
1122
+ svgRectEl.setAttribute("x", String(toX));
1123
+ svgRectEl.setAttribute("y", String(toY));
1124
+ svgRectEl.setAttribute("rx", String(toRx));
1125
+ svgRectEl.setAttribute("ry", String(toRx));
1126
+ };
1127
+ } else {
1128
+ svgRectEl.setAttribute("width", String(tw));
1129
+ svgRectEl.setAttribute("height", String(th));
1130
+ svgRectEl.setAttribute("x", String(toX));
1131
+ svgRectEl.setAttribute("y", String(toY));
1132
+ svgRectEl.setAttribute("rx", String(toRx));
1133
+ svgRectEl.setAttribute("ry", String(toRx));
1134
+ }
1135
+ }
1136
+ function updateLayout() {
1137
+ const isOpen = snapshot.open;
1138
+ const newAttrs = getNotchAttrs({ open: isOpen, position, theme });
1139
+ applyAttrs2(rootEl, newAttrs.root);
1140
+ rootEl.style.width = `${rootW()}px`;
1141
+ rootEl.style.height = `${rootH()}px`;
1142
+ svg.setAttribute("width", String(rootW()));
1143
+ svg.setAttribute("height", String(rootH()));
1144
+ svg.setAttribute("viewBox", `0 0 ${rootW()} ${rootH()}`);
1145
+ feBlur.setAttribute("stdDeviation", String(blur()));
1146
+ svgRectEl.setAttribute("fill", fill ?? "var(--fluix-notch-bg)");
1147
+ hoverBlobEl.setAttribute("fill", fill ?? "var(--fluix-notch-bg)");
1148
+ applyAttrs2(contentDiv, newAttrs.content);
1149
+ animateRect();
1150
+ if (!isOpen) {
1151
+ resetHoverBlobImmediate();
1152
+ }
1153
+ document.documentElement.style.setProperty(
1154
+ "--fluix-notch-offset",
1155
+ `${rootH()}px`
1156
+ );
1157
+ }
1158
+ const unsubscribe = machine.store.subscribe(() => {
1159
+ const next = machine.store.getSnapshot();
1160
+ snapshot = next;
1161
+ if (controlledOpen !== void 0) {
1162
+ if (controlledOpen && !next.open) machine.open();
1163
+ else if (!controlledOpen && next.open) machine.close();
1164
+ }
1165
+ if (prevOpenVal !== void 0 && prevOpenVal !== next.open) {
1166
+ onOpenChange?.(next.open);
1167
+ }
1168
+ prevOpenVal = next.open;
1169
+ updateLayout();
1170
+ });
1171
+ updateLayout();
1172
+ document.documentElement.style.setProperty(
1173
+ "--fluix-notch-offset",
1174
+ `${rootH()}px`
1175
+ );
1176
+ return {
1177
+ open() {
1178
+ handleOpen();
1179
+ },
1180
+ close() {
1181
+ handleClose();
1182
+ },
1183
+ toggle() {
1184
+ handleToggle();
1185
+ },
1186
+ destroy() {
1187
+ unsubscribe();
1188
+ cancelAnimationFrame(measureRaf);
1189
+ measureObs.disconnect();
1190
+ currentAnim?.cancel();
1191
+ highlightAnim?.cancel();
1192
+ rootEl.removeEventListener("mouseenter", onMouseEnter);
1193
+ rootEl.removeEventListener("mouseleave", onMouseLeave);
1194
+ rootEl.removeEventListener("mouseover", onItemEnter);
1195
+ rootEl.removeEventListener("click", onClick);
1196
+ machine.destroy();
1197
+ measureEl.remove();
1198
+ rootEl.remove();
1199
+ document.documentElement.style.removeProperty("--fluix-notch-offset");
1200
+ },
1201
+ update(opts) {
1202
+ if (opts.trigger !== void 0) trigger = opts.trigger;
1203
+ if (opts.position !== void 0) position = opts.position;
1204
+ if (opts.spring !== void 0) spring = opts.spring;
1205
+ if (opts.dotSize !== void 0) dotSize = opts.dotSize;
1206
+ if (opts.roundness !== void 0) roundness = opts.roundness;
1207
+ if (opts.theme !== void 0) theme = opts.theme;
1208
+ if (opts.fill !== void 0) fill = opts.fill;
1209
+ if (opts.open !== void 0) controlledOpen = opts.open;
1210
+ if (opts.onOpenChange !== void 0) onOpenChange = opts.onOpenChange;
1211
+ if (opts.pill !== void 0) {
1212
+ pillDiv.textContent = "";
1213
+ pillDiv.appendChild(resolveContent(opts.pill));
1214
+ }
1215
+ if (opts.content !== void 0) {
1216
+ contentDiv.textContent = "";
1217
+ contentDiv.appendChild(resolveContent(opts.content));
1218
+ measureEl.textContent = "";
1219
+ measureEl.appendChild(resolveContent(opts.content).cloneNode(true));
1220
+ }
1221
+ pillDiv.style.width = `${dotSize}px`;
1222
+ pillDiv.style.height = `${dotSize}px`;
1223
+ machine.configure({ position, trigger, roundness, fill, spring });
1224
+ if (controlledOpen !== void 0) {
1225
+ if (controlledOpen && !snapshot.open) machine.open();
1226
+ else if (!controlledOpen && snapshot.open) machine.close();
1227
+ }
1228
+ rootEl.removeEventListener("mouseenter", onMouseEnter);
1229
+ rootEl.removeEventListener("mouseleave", onMouseLeave);
1230
+ rootEl.removeEventListener("click", onClick);
1231
+ rootEl.addEventListener("mouseenter", onMouseEnter);
1232
+ rootEl.addEventListener("mouseleave", onMouseLeave);
1233
+ rootEl.addEventListener("click", onClick);
1234
+ updateLayout();
1235
+ }
1236
+ };
1237
+ }
1238
+ var SVG_NS3 = "http://www.w3.org/2000/svg";
1239
+ var GOO_MATRIX = "1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 20 -10";
1240
+ function applyAttrs3(el, attrs) {
1241
+ for (const [key, value] of Object.entries(attrs)) {
1242
+ el.setAttribute(key, value);
1243
+ }
1244
+ }
1245
+ function createMenu(container, options) {
1246
+ let {
1247
+ orientation = MENU_DEFAULTS.orientation,
1248
+ variant = "pill",
1249
+ theme = "dark",
1250
+ activeId: controlledActiveId,
1251
+ onActiveChange,
1252
+ spring,
1253
+ roundness = MENU_DEFAULTS.roundness,
1254
+ blur: blurProp,
1255
+ fill,
1256
+ items
1257
+ } = options;
1258
+ const springConfig = () => spring ?? FLUIX_SPRING;
1259
+ const resolvedBlur = () => blurProp ?? Math.min(10, Math.max(6, roundness * 0.45));
1260
+ const machine = createMenuMachine({
1261
+ orientation,
1262
+ variant,
1263
+ spring,
1264
+ roundness,
1265
+ blur: blurProp,
1266
+ fill,
1267
+ initialActiveId: controlledActiveId ?? null
1268
+ });
1269
+ let snapshot = machine.store.getSnapshot();
1270
+ let lastActiveNotified = snapshot.activeId;
1271
+ const attrs = getMenuAttrs({ orientation, theme, variant });
1272
+ const filterId = `fluix-menu-goo-${Math.random().toString(36).slice(2, 8)}`;
1273
+ const isTab = variant === "tab";
1274
+ const navEl = document.createElement("nav");
1275
+ applyAttrs3(navEl, attrs.root);
1276
+ navEl.setAttribute("aria-label", "Fluix menu");
1277
+ const canvasDiv = document.createElement("div");
1278
+ applyAttrs3(canvasDiv, attrs.canvas);
1279
+ const svg = document.createElementNS(SVG_NS3, "svg");
1280
+ svg.setAttribute("xmlns", SVG_NS3);
1281
+ svg.setAttribute("width", "1");
1282
+ svg.setAttribute("height", "1");
1283
+ svg.setAttribute("viewBox", "0 0 1 1");
1284
+ svg.setAttribute("aria-hidden", "true");
1285
+ let indicatorEl;
1286
+ if (isTab) {
1287
+ indicatorEl = document.createElementNS(SVG_NS3, "path");
1288
+ applyAttrs3(indicatorEl, attrs.indicator);
1289
+ indicatorEl.setAttribute("d", "");
1290
+ indicatorEl.setAttribute("opacity", "0");
1291
+ indicatorEl.setAttribute("fill", fill ?? "var(--fluix-menu-indicator)");
1292
+ svg.appendChild(indicatorEl);
1293
+ } else {
1294
+ const defs = document.createElementNS(SVG_NS3, "defs");
1295
+ const filter = document.createElementNS(SVG_NS3, "filter");
1296
+ filter.setAttribute("id", filterId);
1297
+ filter.setAttribute("x", "-20%");
1298
+ filter.setAttribute("y", "-20%");
1299
+ filter.setAttribute("width", "140%");
1300
+ filter.setAttribute("height", "140%");
1301
+ filter.setAttribute("color-interpolation-filters", "sRGB");
1302
+ const feBlur = document.createElementNS(SVG_NS3, "feGaussianBlur");
1303
+ feBlur.setAttribute("in", "SourceGraphic");
1304
+ feBlur.setAttribute("stdDeviation", String(resolvedBlur()));
1305
+ feBlur.setAttribute("result", "blur");
1306
+ const feCM = document.createElementNS(SVG_NS3, "feColorMatrix");
1307
+ feCM.setAttribute("in", "blur");
1308
+ feCM.setAttribute("type", "matrix");
1309
+ feCM.setAttribute("values", GOO_MATRIX);
1310
+ feCM.setAttribute("result", "goo");
1311
+ const feComp = document.createElementNS(SVG_NS3, "feComposite");
1312
+ feComp.setAttribute("in", "SourceGraphic");
1313
+ feComp.setAttribute("in2", "goo");
1314
+ feComp.setAttribute("operator", "atop");
1315
+ filter.appendChild(feBlur);
1316
+ filter.appendChild(feCM);
1317
+ filter.appendChild(feComp);
1318
+ defs.appendChild(filter);
1319
+ svg.appendChild(defs);
1320
+ const gGroup = document.createElementNS(SVG_NS3, "g");
1321
+ gGroup.setAttribute("filter", `url(#${filterId})`);
1322
+ indicatorEl = document.createElementNS(SVG_NS3, "rect");
1323
+ applyAttrs3(indicatorEl, attrs.indicator);
1324
+ indicatorEl.setAttribute("x", "0");
1325
+ indicatorEl.setAttribute("y", "0");
1326
+ indicatorEl.setAttribute("width", "0");
1327
+ indicatorEl.setAttribute("height", "0");
1328
+ indicatorEl.setAttribute("rx", "0");
1329
+ indicatorEl.setAttribute("ry", "0");
1330
+ indicatorEl.setAttribute("opacity", "0");
1331
+ indicatorEl.setAttribute("fill", fill ?? "var(--fluix-menu-indicator)");
1332
+ gGroup.appendChild(indicatorEl);
1333
+ svg.appendChild(gGroup);
1334
+ }
1335
+ canvasDiv.appendChild(svg);
1336
+ navEl.appendChild(canvasDiv);
1337
+ const listDiv = document.createElement("div");
1338
+ applyAttrs3(listDiv, attrs.list);
1339
+ const buttonMap = /* @__PURE__ */ new Map();
1340
+ function createItemButton(item) {
1341
+ const btn = document.createElement("button");
1342
+ btn.type = "button";
1343
+ const active = snapshot.activeId === item.id;
1344
+ const itemAttrs = attrs.item({ id: item.id, active, disabled: item.disabled });
1345
+ applyAttrs3(btn, itemAttrs);
1346
+ if (item.disabled) btn.disabled = true;
1347
+ btn.textContent = item.label;
1348
+ btn.addEventListener("click", () => {
1349
+ if (item.disabled) return;
1350
+ if (controlledActiveId === void 0) {
1351
+ machine.setActive(item.id);
1352
+ } else {
1353
+ onActiveChange?.(item.id);
1354
+ }
1355
+ });
1356
+ buttonMap.set(item.id, btn);
1357
+ listDiv.appendChild(btn);
1358
+ }
1359
+ for (const item of items) {
1360
+ createItemButton(item);
1361
+ }
1362
+ navEl.appendChild(listDiv);
1363
+ container.appendChild(navEl);
1364
+ let size = { width: 0, height: 0 };
1365
+ let measureRaf = 0;
1366
+ const measure = () => {
1367
+ const rect = navEl.getBoundingClientRect();
1368
+ const w = Math.ceil(rect.width);
1369
+ const h = Math.ceil(rect.height);
1370
+ if (size.width !== w || size.height !== h) {
1371
+ size = { width: w, height: h };
1372
+ updateSvgSize();
1373
+ connection?.sync(false);
1374
+ }
1375
+ };
1376
+ const resizeObs = new ResizeObserver(() => {
1377
+ cancelAnimationFrame(measureRaf);
1378
+ measureRaf = requestAnimationFrame(measure);
1379
+ });
1380
+ resizeObs.observe(navEl);
1381
+ function updateSvgSize() {
1382
+ const w = Math.max(1, size.width);
1383
+ const h = Math.max(1, size.height);
1384
+ svg.setAttribute("width", String(w));
1385
+ svg.setAttribute("height", String(h));
1386
+ svg.setAttribute("viewBox", `0 0 ${w} ${h}`);
1387
+ }
1388
+ let connection = connectMenu({
1389
+ root: navEl,
1390
+ indicator: indicatorEl,
1391
+ getActiveId: () => snapshot.activeId,
1392
+ onSelect(id) {
1393
+ if (controlledActiveId === void 0) {
1394
+ machine.setActive(id);
1395
+ } else {
1396
+ onActiveChange?.(id);
1397
+ }
1398
+ },
1399
+ spring: springConfig(),
1400
+ variant,
1401
+ orientation
1402
+ });
1403
+ requestAnimationFrame(() => {
1404
+ measure();
1405
+ connection.sync(false);
1406
+ });
1407
+ const unsubscribe = machine.store.subscribe(() => {
1408
+ const next = machine.store.getSnapshot();
1409
+ snapshot = next;
1410
+ for (const item of items) {
1411
+ const btn = buttonMap.get(item.id);
1412
+ if (btn) {
1413
+ const active = next.activeId === item.id;
1414
+ const itemAttrs = attrs.item({ id: item.id, active, disabled: item.disabled });
1415
+ applyAttrs3(btn, itemAttrs);
1416
+ }
1417
+ }
1418
+ if (next.activeId && lastActiveNotified !== next.activeId && onActiveChange) {
1419
+ onActiveChange(next.activeId);
1420
+ }
1421
+ lastActiveNotified = next.activeId;
1422
+ connection.sync(false);
1423
+ });
1424
+ return {
1425
+ setActive(id) {
1426
+ machine.setActive(id);
1427
+ },
1428
+ update(opts) {
1429
+ if (opts.orientation !== void 0) orientation = opts.orientation;
1430
+ if (opts.variant !== void 0) variant = opts.variant;
1431
+ if (opts.theme !== void 0) theme = opts.theme;
1432
+ if (opts.activeId !== void 0) controlledActiveId = opts.activeId;
1433
+ if (opts.onActiveChange !== void 0) onActiveChange = opts.onActiveChange;
1434
+ if (opts.spring !== void 0) spring = opts.spring;
1435
+ if (opts.roundness !== void 0) roundness = opts.roundness;
1436
+ if (opts.blur !== void 0) blurProp = opts.blur;
1437
+ if (opts.fill !== void 0) fill = opts.fill;
1438
+ machine.configure({ orientation, variant, spring, roundness, blur: blurProp, fill });
1439
+ if (controlledActiveId !== void 0) {
1440
+ machine.setActive(controlledActiveId ?? null);
1441
+ }
1442
+ const newAttrs = getMenuAttrs({ orientation, theme, variant });
1443
+ applyAttrs3(navEl, newAttrs.root);
1444
+ if (opts.items !== void 0) {
1445
+ items = opts.items;
1446
+ listDiv.innerHTML = "";
1447
+ buttonMap.clear();
1448
+ for (const item of items) {
1449
+ createItemButton(item);
1450
+ }
1451
+ }
1452
+ connection.destroy();
1453
+ connection = connectMenu({
1454
+ root: navEl,
1455
+ indicator: indicatorEl,
1456
+ getActiveId: () => snapshot.activeId,
1457
+ onSelect(id) {
1458
+ if (controlledActiveId === void 0) {
1459
+ machine.setActive(id);
1460
+ } else {
1461
+ onActiveChange?.(id);
1462
+ }
1463
+ },
1464
+ spring: springConfig(),
1465
+ variant,
1466
+ orientation
1467
+ });
1468
+ requestAnimationFrame(() => {
1469
+ measure();
1470
+ connection.sync(false);
1471
+ });
1472
+ },
1473
+ destroy() {
1474
+ unsubscribe();
1475
+ cancelAnimationFrame(measureRaf);
1476
+ resizeObs.disconnect();
1477
+ connection.destroy();
1478
+ machine.destroy();
1479
+ navEl.remove();
1480
+ }
1481
+ };
1482
+ }
784
1483
 
785
- export { createToaster };
1484
+ export { createMenu, createNotch, createToaster };
786
1485
  //# sourceMappingURL=index.js.map
787
1486
  //# sourceMappingURL=index.js.map