@mks2508/mks-ui 0.5.4 → 0.5.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.
Files changed (26) hide show
  1. package/dist/react-ui/primitives/waapi/Gooey/Gooey.types.d.ts +21 -4
  2. package/dist/react-ui/primitives/waapi/Gooey/Gooey.types.d.ts.map +1 -1
  3. package/dist/react-ui/primitives/waapi/Gooey/GooeyCanvas.d.ts +2 -2
  4. package/dist/react-ui/primitives/waapi/Gooey/GooeyCanvas.d.ts.map +1 -1
  5. package/dist/react-ui/primitives/waapi/Gooey/GooeyCanvas.js +163 -32
  6. package/dist/react-ui/primitives/waapi/Gooey/gooey-utils.d.ts +7 -0
  7. package/dist/react-ui/primitives/waapi/Gooey/gooey-utils.d.ts.map +1 -1
  8. package/dist/react-ui/primitives/waapi/Gooey/gooey-utils.js +6 -1
  9. package/dist/react-ui/ui/DynamicToggle/{DynamicToggle-Cm6-VceQ.css → DynamicToggle-DOR3Ld-k.css} +104 -32
  10. package/dist/react-ui/ui/DynamicToggle/DynamicToggle.css +105 -32
  11. package/dist/react-ui/ui/DynamicToggle/DynamicToggle.styles.js +2 -2
  12. package/dist/react-ui/ui/DynamicToggle/DynamicToggle.types.d.ts +6 -0
  13. package/dist/react-ui/ui/DynamicToggle/DynamicToggle.types.d.ts.map +1 -1
  14. package/dist/react-ui/ui/DynamicToggle/index.d.ts.map +1 -1
  15. package/dist/react-ui/ui/DynamicToggle/index.js +23 -5
  16. package/package.json +1 -1
  17. package/src/react-ui/primitives/waapi/Gooey/Gooey.types.ts +21 -3
  18. package/src/react-ui/primitives/waapi/Gooey/GooeyCanvas.tsx +177 -40
  19. package/src/react-ui/primitives/waapi/Gooey/gooey-utils.ts +9 -0
  20. package/src/react-ui/ui/DynamicToggle/DynamicToggle.css +105 -32
  21. package/src/react-ui/ui/DynamicToggle/DynamicToggle.styles.ts +2 -2
  22. package/src/react-ui/ui/DynamicToggle/DynamicToggle.types.ts +6 -0
  23. package/src/react-ui/ui/DynamicToggle/index.tsx +30 -8
  24. package/src/react-ui/ui/DynamicToggle/prototype-v7-ios.html +413 -0
  25. package/src/react-ui/ui/DynamicToggle/prototype-v8-gooey-safari.html +560 -0
  26. package/src/react-ui/ui/DynamicToggle/prototype-v8b-react-structure.html +227 -0
@@ -3,7 +3,6 @@
3
3
  *
4
4
  * @module @mks2508/mks-ui/react/primitives/waapi/Gooey
5
5
  */
6
- import type { ReactNode } from 'react';
7
6
  /**
8
7
  * Props for the GooeyFilter SVG filter definition.
9
8
  *
@@ -39,8 +38,20 @@ export interface IGooeyFilterProps {
39
38
  export interface IGooeyCanvasProps {
40
39
  /** Blur radius override. If omitted, auto-calculated from `height`. */
41
40
  blur?: number;
42
- /** Element height used to auto-calculate blur (default: 32) */
41
+ /** Pill height in px (default: 32) */
43
42
  height?: number;
43
+ /** Pill width in px (default: 260) */
44
+ width?: number;
45
+ /** Border radius in px (default: 9999) */
46
+ radius?: number;
47
+ /** Fill color (default: 'var(--card)') */
48
+ fillColor?: string;
49
+ /** Bubble height in px when expanded (default: 40% of height) */
50
+ bubbleHeight?: number;
51
+ /** Bubble inset from edges as fraction 0-1 (default: 0.2) */
52
+ bubbleInset?: number;
53
+ /** Whether the bubble is expanded */
54
+ expanded?: boolean;
44
55
  /** Drop-shadow outline blur in px (default: 0.5) */
45
56
  outlineBlur?: number;
46
57
  /** Drop-shadow outline color (default: 'var(--border)') */
@@ -51,10 +62,16 @@ export interface IGooeyCanvasProps {
51
62
  alphaGain?: number;
52
63
  /** Alpha offset override */
53
64
  alphaOffset?: number;
65
+ /** Expand animation duration in ms (default: 550) */
66
+ expandDuration?: number;
67
+ /** Collapse animation duration in ms (default: 400) */
68
+ collapseDuration?: number;
69
+ /** Expand easing override (default: SPRING_GENTLE) */
70
+ expandEasing?: string;
71
+ /** Collapse easing override (default: EASE_OUT_CUBIC) */
72
+ collapseEasing?: string;
54
73
  /** Extra className on the filter container */
55
74
  className?: string;
56
- /** Content to merge with the gooey filter */
57
- children: ReactNode;
58
75
  }
59
76
  /**
60
77
  * Props for the MorphPath SVG path component.
@@ -1 +1 @@
1
- {"version":3,"file":"Gooey.types.d.ts","sourceRoot":"","sources":["../../../../../src/react-ui/primitives/waapi/Gooey/Gooey.types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAMvC;;;;;;;GAOG;AACH,MAAM,WAAW,iBAAiB;IAChC,2DAA2D;IAC3D,EAAE,EAAE,MAAM,CAAC;IACX,8CAA8C;IAC9C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAMD;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,iBAAiB;IAChC,uEAAuE;IACvE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oDAAoD;IACpD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2DAA2D;IAC3D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,wEAAwE;IACxE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,0BAA0B;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4BAA4B;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8CAA8C;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6CAA6C;IAC7C,QAAQ,EAAE,SAAS,CAAC;CACrB;AAMD;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,eAAgB,SAAQ,KAAK,CAAC,QAAQ,CAAC,cAAc,CAAC;IACrE,uBAAuB;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,uCAAuC;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,uCAAuC;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,wDAAwD;IACxD,QAAQ,EAAE,MAAM,CAAC;IACjB,gCAAgC;IAChC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAMD;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,uBAAuB;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,uBAAuB;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,yBAAyB;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,yBAAyB;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,gCAAgC;IAChC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qBAAqB;IACrB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B"}
1
+ {"version":3,"file":"Gooey.types.d.ts","sourceRoot":"","sources":["../../../../../src/react-ui/primitives/waapi/Gooey/Gooey.types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAQH;;;;;;;GAOG;AACH,MAAM,WAAW,iBAAiB;IAChC,2DAA2D;IAC3D,EAAE,EAAE,MAAM,CAAC;IACX,8CAA8C;IAC9C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAMD;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,iBAAiB;IAChC,uEAAuE;IACvE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sCAAsC;IACtC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sCAAsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0CAA0C;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iEAAiE;IACjE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,6DAA6D;IAC7D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qCAAqC;IACrC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,oDAAoD;IACpD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2DAA2D;IAC3D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,wEAAwE;IACxE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,0BAA0B;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4BAA4B;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qDAAqD;IACrD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,uDAAuD;IACvD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,sDAAsD;IACtD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yDAAyD;IACzD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,8CAA8C;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAMD;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,eAAgB,SAAQ,KAAK,CAAC,QAAQ,CAAC,cAAc,CAAC;IACrE,uBAAuB;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,uCAAuC;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,uCAAuC;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,wDAAwD;IACxD,QAAQ,EAAE,MAAM,CAAC;IACjB,gCAAgC;IAChC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAMD;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,uBAAuB;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,uBAAuB;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,yBAAyB;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,yBAAyB;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,gCAAgC;IAChC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qBAAqB;IACrB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B"}
@@ -1,8 +1,8 @@
1
1
  import type { IGooeyCanvasProps } from './Gooey.types';
2
2
  /**
3
- * GooeyCanvas — container with gooey SVG filter applied.
3
+ * GooeyCanvas — SVG rects + gooey filter, WAAPI-animated bubble.
4
4
  */
5
- declare function GooeyCanvas({ blur, height, outlineBlur, outlineColor, outlineLayers, alphaGain, alphaOffset, className, children, }: IGooeyCanvasProps): import("react/jsx-runtime").JSX.Element;
5
+ declare function GooeyCanvas({ blur, height, width, radius, fillColor, bubbleHeight: bubbleHeightProp, bubbleInset, expanded, outlineBlur, outlineColor, outlineLayers, alphaGain, alphaOffset, expandDuration, collapseDuration, expandEasing, collapseEasing, className, }: IGooeyCanvasProps): import("react/jsx-runtime").JSX.Element;
6
6
  declare namespace GooeyCanvas {
7
7
  var displayName: string;
8
8
  }
@@ -1 +1 @@
1
- {"version":3,"file":"GooeyCanvas.d.ts","sourceRoot":"","sources":["../../../../../src/react-ui/primitives/waapi/Gooey/GooeyCanvas.tsx"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAEvD;;GAEG;AACH,iBAAS,WAAW,CAAC,EACnB,IAAI,EACJ,MAAW,EACX,WAAiB,EACjB,YAA8B,EAC9B,aAAiB,EACjB,SAAS,EACT,WAAW,EACX,SAAS,EACT,QAAQ,GACT,EAAE,iBAAiB,2CA+BnB;kBAzCQ,WAAW;;;AA6CpB,OAAO,EAAE,WAAW,EAAE,CAAC"}
1
+ {"version":3,"file":"GooeyCanvas.d.ts","sourceRoot":"","sources":["../../../../../src/react-ui/primitives/waapi/Gooey/GooeyCanvas.tsx"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAEvD;;GAEG;AACH,iBAAS,WAAW,CAAC,EACnB,IAAI,EACJ,MAAW,EACX,KAAW,EACX,MAAa,EACb,SAAyB,EACzB,YAAY,EAAE,gBAAgB,EAC9B,WAAiB,EACjB,QAAgB,EAChB,WAAiB,EACjB,YAA8B,EAC9B,aAAiB,EACjB,SAAS,EACT,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,YAAY,EACZ,cAAc,EACd,SAAS,GACV,EAAE,iBAAiB,2CAuKnB;kBA1LQ,WAAW;;;AA8LpB,OAAO,EAAE,WAAW,EAAE,CAAC"}
@@ -1,57 +1,188 @@
1
1
  'use client';
2
2
 
3
3
  import { cn } from "../../../lib/utils.js";
4
- import { buildFilterString, computeBlur } from "./gooey-utils.js";
5
- import { GooeyFilter } from "./GooeyFilter.js";
4
+ import { EASINGS, getResponsiveDuration } from "../core/animationConstants.js";
5
+ import { GOOEY_TIMING, computeBlur } from "./gooey-utils.js";
6
6
  import * as React$1 from "react";
7
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
7
+ import { jsx, jsxs } from "react/jsx-runtime";
8
8
 
9
9
  //#region src/react-ui/primitives/waapi/Gooey/GooeyCanvas.tsx
10
10
  /**
11
- * GooeyCanvas — container that applies gooey SVG filter to children.
11
+ * GooeyCanvas — SVG-based gooey filter with animated pill + bubble rects.
12
12
  *
13
- * Renders a GooeyFilter + a wrapper div with `filter: url(#id)`.
14
- * All same-colored children inside merge organically. Optional drop-shadow
15
- * outline traces the merged shape's edge.
13
+ * Uses SVG `<rect>` elements inside a filtered container. The bubble rect
14
+ * animates via WAAPI for smooth cross-browser rendering.
16
15
  *
17
- * Blur auto-scales with height: `blur = Math.round(height * 0.15)`.
18
- *
19
- * @example
20
- * ```tsx
21
- * <div style={{ position: 'relative' }}>
22
- * <GooeyCanvas height={40}>
23
- * <div className="absolute inset-0 bg-card rounded-full" />
24
- * <div className="absolute bottom-full bg-card w-32 h-6 rounded-lg" />
25
- * </GooeyCanvas>
26
- * <div className="relative z-10">Content on top (not filtered)</div>
27
- * </div>
28
- * ```
16
+ * Key patterns (derived from Sileo):
17
+ * - Filter applied to canvas div, SVG content inside (not HTML children)
18
+ * - `transform: translateZ(0)` + `contain: layout style` on canvas
19
+ * - No DOM mutation during/after animation — `fill: 'forwards'` only
20
+ * - Readiness gate: 1-frame rAF delay before first animation (Sileo pattern)
29
21
  *
30
22
  * @module @mks2508/mks-ui/react/primitives/waapi/Gooey
31
23
  */
32
24
  /**
33
- * GooeyCanvas — container with gooey SVG filter applied.
25
+ * GooeyCanvas — SVG rects + gooey filter, WAAPI-animated bubble.
34
26
  */
35
- function GooeyCanvas({ blur, height = 32, outlineBlur = .5, outlineColor = "var(--border)", outlineLayers = 2, alphaGain, alphaOffset, className, children }) {
27
+ function GooeyCanvas({ blur, height = 32, width = 260, radius = 9999, fillColor = "var(--card)", bubbleHeight: bubbleHeightProp, bubbleInset = .2, expanded = false, outlineBlur = .5, outlineColor = "var(--border)", outlineLayers = 2, alphaGain, alphaOffset, expandDuration, collapseDuration, expandEasing, collapseEasing, className }) {
36
28
  const filterId = React$1.useId().replace(/:/g, "") + "-goo";
37
29
  const computedBlur = blur ?? computeBlur(height);
38
- const filterStyle = React$1.useMemo(() => ({ filter: buildFilterString(filterId, outlineBlur, outlineColor, outlineLayers) }), [
39
- filterId,
30
+ const bubbleRectRef = React$1.useRef(null);
31
+ const animRef = React$1.useRef(null);
32
+ const [ready, setReady] = React$1.useState(false);
33
+ const lastValues = React$1.useRef({
34
+ y: -1,
35
+ h: -1
36
+ });
37
+ const pad = 2;
38
+ const effectiveR = Math.min(radius, height / 2);
39
+ const bubbleH = bubbleHeightProp ?? Math.round(height * .4);
40
+ const insetPx = width * bubbleInset;
41
+ const bubbleW = width - 2 * insetPx;
42
+ const bubbleR = Math.min(effectiveR * .6, bubbleH * .45, 12);
43
+ const totalH = height + bubbleH;
44
+ const filterUrl = React$1.useMemo(() => `url(#${filterId})`, [filterId]);
45
+ const outlineShadow = React$1.useMemo(() => {
46
+ const shadow = `drop-shadow(0 0 ${outlineBlur}px ${outlineColor})`;
47
+ return Array(outlineLayers).fill(shadow).join(" ");
48
+ }, [
40
49
  outlineBlur,
41
50
  outlineColor,
42
51
  outlineLayers
43
52
  ]);
44
- return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(GooeyFilter, {
45
- id: filterId,
46
- blur: computedBlur,
47
- alphaGain,
48
- alphaOffset
49
- }), /* @__PURE__ */ jsx("div", {
53
+ const canvasStyle = React$1.useMemo(() => ({
54
+ filter: `${filterUrl} ${outlineShadow}`,
55
+ transform: "translateZ(0)",
56
+ contain: "layout style"
57
+ }), [filterUrl, outlineShadow]);
58
+ React$1.useEffect(() => {
59
+ const rect = bubbleRectRef.current;
60
+ if (!rect) return;
61
+ lastValues.current = {
62
+ y: expanded ? 0 : bubbleH,
63
+ h: expanded ? bubbleH : 0
64
+ };
65
+ if (expanded) rect.animate([{
66
+ y: "0px",
67
+ height: `${bubbleH}px`
68
+ }], {
69
+ duration: 0,
70
+ fill: "forwards"
71
+ });
72
+ const raf = requestAnimationFrame(() => setReady(true));
73
+ return () => cancelAnimationFrame(raf);
74
+ }, []);
75
+ React$1.useEffect(() => {
76
+ const rect = bubbleRectRef.current;
77
+ if (!rect || !ready) return;
78
+ const isExpanding = expanded;
79
+ const duration = getResponsiveDuration(isExpanding ? expandDuration ?? GOOEY_TIMING.EXPAND_DURATION : collapseDuration ?? GOOEY_TIMING.COLLAPSE_DURATION);
80
+ const easing = isExpanding ? expandEasing ?? EASINGS.SPRING_GENTLE : collapseEasing ?? EASINGS.EASE_OUT_CUBIC;
81
+ const toY = isExpanding ? 0 : bubbleH;
82
+ const toH = isExpanding ? bubbleH : 0;
83
+ const fromY = lastValues.current.y;
84
+ const fromH = lastValues.current.h;
85
+ lastValues.current = {
86
+ y: toY,
87
+ h: toH
88
+ };
89
+ if (duration === 0) {
90
+ if (animRef.current) animRef.current.cancel();
91
+ rect.animate([{
92
+ y: `${toY}px`,
93
+ height: `${toH}px`
94
+ }], {
95
+ duration: 0,
96
+ fill: "forwards"
97
+ });
98
+ return;
99
+ }
100
+ if (animRef.current) animRef.current.cancel();
101
+ animRef.current = rect.animate([{
102
+ y: `${fromY}px`,
103
+ height: `${fromH}px`
104
+ }, {
105
+ y: `${toY}px`,
106
+ height: `${toH}px`
107
+ }], {
108
+ duration,
109
+ easing,
110
+ fill: "forwards"
111
+ });
112
+ }, [
113
+ ready,
114
+ expanded,
115
+ bubbleH,
116
+ expandDuration,
117
+ collapseDuration,
118
+ expandEasing,
119
+ collapseEasing
120
+ ]);
121
+ return /* @__PURE__ */ jsx("div", {
50
122
  "data-slot": "gooey-canvas",
51
- style: filterStyle,
123
+ style: canvasStyle,
52
124
  className: cn("absolute inset-0 rounded-[inherit] pointer-events-none z-0 overflow-visible", className),
53
- children
54
- })] });
125
+ children: /* @__PURE__ */ jsxs("svg", {
126
+ "data-slot": "gooey-svg",
127
+ width,
128
+ height: totalH,
129
+ viewBox: `0 0 ${width} ${totalH}`,
130
+ style: {
131
+ position: "absolute",
132
+ top: -bubbleH,
133
+ left: 0,
134
+ overflow: "visible"
135
+ },
136
+ "aria-hidden": "true",
137
+ children: [
138
+ /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs("filter", {
139
+ id: filterId,
140
+ x: "-20%",
141
+ y: "-20%",
142
+ width: "140%",
143
+ height: "140%",
144
+ colorInterpolationFilters: "sRGB",
145
+ children: [
146
+ /* @__PURE__ */ jsx("feGaussianBlur", {
147
+ in: "SourceGraphic",
148
+ stdDeviation: computedBlur,
149
+ result: "blur"
150
+ }),
151
+ /* @__PURE__ */ jsx("feColorMatrix", {
152
+ in: "blur",
153
+ mode: "matrix",
154
+ values: `1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 ${alphaGain ?? 20} ${alphaOffset ?? -10}`,
155
+ result: "goo"
156
+ }),
157
+ /* @__PURE__ */ jsx("feComposite", {
158
+ in: "SourceGraphic",
159
+ in2: "goo",
160
+ operator: "atop"
161
+ })
162
+ ]
163
+ }) }),
164
+ /* @__PURE__ */ jsx("rect", {
165
+ x: pad,
166
+ y: bubbleH,
167
+ width: width - pad * 2,
168
+ height: height - pad * 2,
169
+ rx: effectiveR,
170
+ ry: effectiveR,
171
+ fill: fillColor
172
+ }),
173
+ /* @__PURE__ */ jsx("rect", {
174
+ ref: bubbleRectRef,
175
+ x: insetPx,
176
+ y: bubbleH,
177
+ width: bubbleW,
178
+ height: 0,
179
+ rx: bubbleR,
180
+ ry: bubbleR,
181
+ fill: fillColor
182
+ })
183
+ ]
184
+ })
185
+ });
55
186
  }
56
187
  GooeyCanvas.displayName = "GooeyCanvas";
57
188
 
@@ -3,6 +3,13 @@
3
3
  *
4
4
  * @module @mks2508/mks-ui/react/primitives/waapi/Gooey
5
5
  */
6
+ /** Gooey animation timing constants. */
7
+ export declare const GOOEY_TIMING: {
8
+ /** Expand duration in ms — spring-like with room for overshoot */
9
+ readonly EXPAND_DURATION: 550;
10
+ /** Collapse duration in ms — snappier settle, no overshoot */
11
+ readonly COLLAPSE_DURATION: 400;
12
+ };
6
13
  /** Default gooey filter parameters. */
7
14
  export declare const GOOEY_DEFAULTS: {
8
15
  /** Blur = height * BLUR_RATIO */
@@ -1 +1 @@
1
- {"version":3,"file":"gooey-utils.d.ts","sourceRoot":"","sources":["../../../../../src/react-ui/primitives/waapi/Gooey/gooey-utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,uCAAuC;AACvC,eAAO,MAAM,cAAc;IACzB,iCAAiC;;IAEjC,6CAA6C;;IAE7C,yCAAyC;;IAEzC,+BAA+B;;IAE/B,sDAAsD;;IAEtD,kCAAkC;;IAElC,yCAAyC;;IAEzC,wDAAwD;;CAEhD,CAAC;AAMX;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAElD;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,GAAE,MAAkC,EACxC,MAAM,GAAE,MAAoC,GAC3C,MAAM,CAER;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,WAAW,GAAE,MAAY,EACzB,YAAY,GAAE,MAAwB,EACtC,aAAa,GAAE,MAAU,GACxB,MAAM,CAKR;AAMD,KAAK,MAAM,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC;AAEpF;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAW9C;AAMD;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAC3B,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,CAAC,EAAE,MAAM,EACT,EAAE,GAAE,MAAmC,GACtC,MAAM,CAwCR;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CACzB,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,CAAC,EAAE,MAAM,EACT,EAAE,GAAE,MAAmC,GACtC,MAAM,CAsDR;AAED,mDAAmD;AACnD,eAAO,MAAM,iBAAiB,QAA6B,CAAC;AAC5D,eAAO,MAAM,eAAe,QAA2B,CAAC"}
1
+ {"version":3,"file":"gooey-utils.d.ts","sourceRoot":"","sources":["../../../../../src/react-ui/primitives/waapi/Gooey/gooey-utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,wCAAwC;AACxC,eAAO,MAAM,YAAY;IACvB,kEAAkE;;IAElE,8DAA8D;;CAEtD,CAAC;AAEX,uCAAuC;AACvC,eAAO,MAAM,cAAc;IACzB,iCAAiC;;IAEjC,6CAA6C;;IAE7C,yCAAyC;;IAEzC,+BAA+B;;IAE/B,sDAAsD;;IAEtD,kCAAkC;;IAElC,yCAAyC;;IAEzC,wDAAwD;;CAEhD,CAAC;AAMX;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAElD;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,GAAE,MAAkC,EACxC,MAAM,GAAE,MAAoC,GAC3C,MAAM,CAER;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,WAAW,GAAE,MAAY,EACzB,YAAY,GAAE,MAAwB,EACtC,aAAa,GAAE,MAAU,GACxB,MAAM,CAKR;AAMD,KAAK,MAAM,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC;AAEpF;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAW9C;AAMD;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAC3B,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,CAAC,EAAE,MAAM,EACT,EAAE,GAAE,MAAmC,GACtC,MAAM,CAwCR;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CACzB,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,CAAC,EAAE,MAAM,EACT,EAAE,GAAE,MAAmC,GACtC,MAAM,CAsDR;AAED,mDAAmD;AACnD,eAAO,MAAM,iBAAiB,QAA6B,CAAC;AAC5D,eAAO,MAAM,eAAe,QAA2B,CAAC"}
@@ -4,6 +4,11 @@
4
4
  *
5
5
  * @module @mks2508/mks-ui/react/primitives/waapi/Gooey
6
6
  */
7
+ /** Gooey animation timing constants. */
8
+ const GOOEY_TIMING = {
9
+ EXPAND_DURATION: 550,
10
+ COLLAPSE_DURATION: 400
11
+ };
7
12
  /** Default gooey filter parameters. */
8
13
  const GOOEY_DEFAULTS = {
9
14
  BLUR_RATIO: .15,
@@ -174,4 +179,4 @@ const morphPathDownMemo = memoizePath(morphPathDown);
174
179
  const morphPathUpMemo = memoizePath(morphPathUp);
175
180
 
176
181
  //#endregion
177
- export { GOOEY_DEFAULTS, buildColorMatrixValues, buildFilterString, computeBlur, memoizePath, morphPathDown, morphPathUp };
182
+ export { GOOEY_DEFAULTS, GOOEY_TIMING, buildColorMatrixValues, buildFilterString, computeBlur, memoizePath, morphPathDown, morphPathUp };
@@ -12,6 +12,8 @@
12
12
  --dt-dur: 0.22s;
13
13
  --dt-ease: cubic-bezier(0.22, 0.61, 0.36, 1);
14
14
  --dt-fade: 0.45;
15
+ --dt-indicator-dur: 0.3s;
16
+ --dt-indicator-ease: cubic-bezier(0.4, 0, 0.2, 1);
15
17
  }
16
18
 
17
19
  /* ── Track: explicit row prevents h-full items from overflowing container ── */
@@ -24,18 +26,9 @@
24
26
  grid-column: span 2;
25
27
  }
26
28
 
27
- /* ── Main indicator slide ── */
28
- [data-slot="dt-root"] [data-slot="dt-indicator"] {
29
- transition: translate var(--dt-dur) var(--dt-ease);
30
- translate: 100% 0;
31
- }
32
- [data-slot="dt-root"] [data-slot="dt-track"]:has(> input:checked) [data-slot="dt-indicator"] {
33
- translate: 0 0;
34
- }
35
-
36
29
  /* ── Primary option text ── */
37
30
  [data-slot="dt-root"] [data-slot="dt-track"]:has(> input:checked) > label {
38
- color: var(--card);
31
+ color: var(--accent-foreground);
39
32
  z-index: 2;
40
33
  }
41
34
  [data-slot="dt-root"] [data-slot="dt-track"]:not(:has(> input:checked)) > label {
@@ -49,31 +42,109 @@
49
42
  overflow: hidden;
50
43
  }
51
44
 
52
- /* ── Group indicator: clip-path reveal ── */
53
- [data-slot="dt-root"] [data-slot="dt-group-indicator"] {
54
- pointer-events: none;
45
+ /* ══════════════════════════════════════════════════════════
46
+ * INDICATOR POSITIONING
47
+ *
48
+ * Modern: CSS Anchor Positioning — indicator follows active option
49
+ * Fallback: translate-based positioning for older browsers
50
+ * ══════════════════════════════════════════════════════════ */
51
+
52
+ /* ── Anchor-based indicator (requires full anchor API) ── */
53
+ @supports (anchor-scope: all) {
54
+ /* Scope anchors per toggle instance */
55
+ [data-slot="dt-root"]:not([data-indicator="translate"]) {
56
+ anchor-scope: --dt-active;
57
+ }
58
+
59
+ /* Active option becomes the anchor via native :checked */
60
+ [data-slot="dt-root"]:not([data-indicator="translate"]) [data-slot="dt-track"] > label:has(+ input:checked) {
61
+ anchor-name: --dt-active;
62
+ }
63
+ [data-slot="dt-root"]:not([data-indicator="translate"]) [data-slot="dt-group"] > label:has(+ input:checked) {
64
+ anchor-name: --dt-active;
65
+ }
66
+
67
+ /* Single unified indicator: morphs from full-width to half-width */
68
+ [data-slot="dt-root"]:not([data-indicator="translate"]) [data-slot="dt-indicator"] {
69
+ position-anchor: --dt-active;
70
+ top: anchor(top);
71
+ right: anchor(right);
72
+ bottom: anchor(bottom);
73
+ left: anchor(left);
74
+ translate: none;
75
+ width: auto;
76
+ transition:
77
+ top var(--dt-indicator-dur) var(--dt-indicator-ease),
78
+ right var(--dt-indicator-dur) var(--dt-indicator-ease),
79
+ bottom var(--dt-indicator-dur) var(--dt-indicator-ease),
80
+ left var(--dt-indicator-dur) var(--dt-indicator-ease);
81
+ }
82
+
83
+ /* Hide the group indicator — unified indicator handles everything */
84
+ [data-slot="dt-root"]:not([data-indicator="translate"]) [data-slot="dt-group-indicator"] {
85
+ display: none;
86
+ }
87
+ }
88
+
89
+ /* ── Inset-based fallback (older browsers) — same morph as anchor but hardcoded ── */
90
+ @supports not (anchor-scope: all) {
91
+ /* Unified indicator: left/right transition morphs width + position */
92
+ [data-slot="dt-root"] [data-slot="dt-indicator"] {
93
+ left: 50%;
94
+ right: 0;
95
+ width: auto;
96
+ translate: none;
97
+ transition:
98
+ left var(--dt-indicator-dur) var(--dt-indicator-ease),
99
+ right var(--dt-indicator-dur) var(--dt-indicator-ease);
100
+ }
101
+ /* Top-level checked: indicator covers left half */
102
+ [data-slot="dt-root"] [data-slot="dt-track"]:has(> input:checked) [data-slot="dt-indicator"] {
103
+ left: 0;
104
+ right: 50%;
105
+ }
106
+ /* Group option 1 checked: indicator at 3rd quarter */
107
+ [data-slot="dt-root"] [data-slot="dt-group"]:has(input:nth-of-type(1):checked) ~ [data-slot="dt-indicator"],
108
+ [data-slot="dt-root"] [data-slot="dt-track"]:has([data-slot="dt-group"] input:nth-of-type(1):checked) [data-slot="dt-indicator"] {
109
+ left: 50%;
110
+ right: 25%;
111
+ }
112
+ /* Group option 2 checked: indicator at 4th quarter */
113
+ [data-slot="dt-root"] [data-slot="dt-group"]:has(input:nth-of-type(2):checked) ~ [data-slot="dt-indicator"],
114
+ [data-slot="dt-root"] [data-slot="dt-track"]:has([data-slot="dt-group"] input:nth-of-type(2):checked) [data-slot="dt-indicator"] {
115
+ left: 75%;
116
+ right: 0;
117
+ }
118
+ /* Hide group indicator — unified indicator handles everything */
119
+ [data-slot="dt-root"] [data-slot="dt-group-indicator"] {
120
+ display: none;
121
+ }
122
+ }
123
+
124
+ /* ── Force inset mode via data-indicator="translate" (works regardless of @supports) ── */
125
+ [data-slot="dt-root"][data-indicator="translate"] [data-slot="dt-indicator"] {
126
+ left: 50%;
127
+ right: 0;
128
+ width: auto;
129
+ translate: none;
55
130
  transition:
56
- translate var(--dt-dur) var(--dt-ease),
57
- clip-path var(--dt-dur) var(--dt-ease),
58
- background var(--dt-dur) var(--dt-ease);
59
- clip-path: inset(
60
- 73cqh calc(50% + 1px) calc(27cqh - 2px) calc(50% - 3px)
61
- round var(--dt-radius, 9999px)
62
- );
63
- translate: -50% 0;
64
- }
65
- [data-slot="dt-root"] [data-slot="dt-track"]:has(> input:checked) [data-slot="dt-group-indicator"] {
66
- background: transparent;
131
+ left var(--dt-indicator-dur) var(--dt-indicator-ease),
132
+ right var(--dt-indicator-dur) var(--dt-indicator-ease);
67
133
  }
68
- [data-slot="dt-root"] [data-slot="dt-group"]:has(input:checked) [data-slot="dt-group-indicator"] {
69
- background: var(--card);
70
- clip-path: inset(0 0 0 0 round var(--dt-radius, 9999px));
134
+ [data-slot="dt-root"][data-indicator="translate"] [data-slot="dt-track"]:has(> input:checked) [data-slot="dt-indicator"] {
135
+ left: 0;
136
+ right: 50%;
71
137
  }
72
- [data-slot="dt-root"] [data-slot="dt-group"]:has(input:nth-of-type(1):checked) [data-slot="dt-group-indicator"] {
73
- translate: -100% 0;
138
+ [data-slot="dt-root"][data-indicator="translate"] [data-slot="dt-track"]:has([data-slot="dt-group"] input:nth-of-type(1):checked) [data-slot="dt-indicator"] {
139
+ left: 50%;
140
+ right: 25%;
74
141
  }
75
- [data-slot="dt-root"] [data-slot="dt-group"]:has(input:nth-of-type(2):checked) [data-slot="dt-group-indicator"] {
76
- translate: 0 0;
142
+ [data-slot="dt-root"][data-indicator="translate"] [data-slot="dt-track"]:has([data-slot="dt-group"] input:nth-of-type(2):checked) [data-slot="dt-indicator"] {
143
+ left: 75%;
144
+ right: 0;
145
+ }
146
+ [data-slot="dt-root"][data-indicator="translate"] [data-slot="dt-group-indicator"] {
147
+ display: none;
77
148
  }
78
149
 
79
150
  /* ══════════════════════════════════════════════════════════
@@ -233,6 +304,8 @@
233
304
  background: var(--card);
234
305
  border: 1px solid var(--border);
235
306
  z-index: 3;
307
+ transform: translateZ(0);
308
+ -webkit-transform: translateZ(0);
236
309
  }
237
310
  [data-slot="dt-group-label"] > span {
238
311
  overflow: hidden;
@@ -301,4 +374,3 @@
301
374
  position: relative;
302
375
  z-index: 1;
303
376
  }
304
-