@flowtomic/ui 0.1.2 → 0.1.4
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/blocks/developer-panel/page.d.ts.map +1 -1
- package/dist/blocks/developer-panel/page.js +2 -2
- package/dist/components/atoms/actions/badge/badge.d.ts +2 -2
- package/dist/components/atoms/actions/button/button.d.ts +2 -2
- package/dist/components/atoms/animation/encrypted-text/encrypted-text.d.ts +57 -0
- package/dist/components/atoms/animation/encrypted-text/encrypted-text.d.ts.map +1 -0
- package/dist/components/atoms/animation/encrypted-text/encrypted-text.js +104 -0
- package/dist/components/atoms/animation/encrypted-text/index.d.ts +3 -0
- package/dist/components/atoms/animation/encrypted-text/index.d.ts.map +1 -0
- package/dist/components/atoms/animation/encrypted-text/index.js +1 -0
- package/dist/components/atoms/animation/index.d.ts +2 -0
- package/dist/components/atoms/animation/index.d.ts.map +1 -1
- package/dist/components/atoms/animation/index.js +1 -0
- package/dist/components/atoms/feedback/alert/alert.d.ts +1 -1
- package/dist/components/atoms/feedback/alert-dialog/alert-dialog.d.ts +2 -2
- package/dist/components/atoms/feedback/tooltip/index.d.ts +1 -1
- package/dist/components/atoms/feedback/tooltip/index.d.ts.map +1 -1
- package/dist/components/atoms/feedback/tooltip/index.js +1 -1
- package/dist/components/atoms/feedback/tooltip/tooltip.d.ts +42 -5
- package/dist/components/atoms/feedback/tooltip/tooltip.d.ts.map +1 -1
- package/dist/components/atoms/feedback/tooltip/tooltip.js +188 -5
- package/dist/components/atoms/forms/autocomplete/autocomplete-context.d.ts +29 -0
- package/dist/components/atoms/forms/autocomplete/autocomplete-context.d.ts.map +1 -0
- package/dist/components/atoms/forms/autocomplete/autocomplete-context.js +10 -0
- package/dist/components/atoms/forms/autocomplete/autocomplete-item.d.ts +16 -0
- package/dist/components/atoms/forms/autocomplete/autocomplete-item.d.ts.map +1 -0
- package/dist/components/atoms/forms/autocomplete/autocomplete-item.js +48 -0
- package/dist/components/atoms/forms/autocomplete/autocomplete-section.d.ts +14 -0
- package/dist/components/atoms/forms/autocomplete/autocomplete-section.d.ts.map +1 -0
- package/dist/components/atoms/forms/autocomplete/autocomplete-section.js +13 -0
- package/dist/components/atoms/forms/autocomplete/autocomplete.d.ts +13 -9
- package/dist/components/atoms/forms/autocomplete/autocomplete.d.ts.map +1 -1
- package/dist/components/atoms/forms/autocomplete/autocomplete.js +295 -87
- package/dist/components/atoms/forms/autocomplete/index.d.ts +6 -0
- package/dist/components/atoms/forms/autocomplete/index.d.ts.map +1 -1
- package/dist/components/atoms/forms/autocomplete/index.js +3 -0
- package/dist/components/atoms/forms/index.d.ts +0 -2
- package/dist/components/atoms/forms/index.d.ts.map +1 -1
- package/dist/components/atoms/forms/index.js +0 -1
- package/dist/components/atoms/forms/input/input.d.ts +2 -2
- package/dist/components/atoms/forms/toggle/toggle.d.ts +2 -2
- package/dist/components/atoms/layout/sidebar/sidebar.d.ts +2 -2
- package/dist/components/atoms/navigation/command/command.d.ts +7 -7
- package/dist/components/atoms/navigation/tabs/tabs.js +2 -2
- package/dist/components/molecules/auth/auth-navigation-link/auth-navigation-link.d.ts +1 -11
- package/dist/components/molecules/auth/auth-navigation-link/auth-navigation-link.d.ts.map +1 -1
- package/dist/components/molecules/auth/auth-navigation-link/auth-navigation-link.js +2 -3
- package/dist/components/molecules/forms/autocomplete/autocomplete-context.d.ts +16 -0
- package/dist/components/molecules/forms/autocomplete/autocomplete-context.d.ts.map +1 -0
- package/dist/components/molecules/forms/autocomplete/autocomplete-context.js +14 -0
- package/dist/components/molecules/forms/autocomplete/autocomplete-item.d.ts +23 -0
- package/dist/components/molecules/forms/autocomplete/autocomplete-item.d.ts.map +1 -0
- package/dist/components/molecules/forms/autocomplete/autocomplete-item.js +29 -0
- package/dist/components/molecules/forms/autocomplete/autocomplete-section.d.ts +19 -0
- package/dist/components/molecules/forms/autocomplete/autocomplete-section.d.ts.map +1 -0
- package/dist/components/molecules/forms/autocomplete/autocomplete-section.js +13 -0
- package/dist/components/molecules/forms/autocomplete/autocomplete.d.ts +33 -0
- package/dist/components/molecules/forms/autocomplete/autocomplete.d.ts.map +1 -0
- package/dist/components/molecules/forms/autocomplete/autocomplete.js +101 -0
- package/dist/components/molecules/forms/autocomplete/index.d.ts +9 -0
- package/dist/components/molecules/forms/autocomplete/index.d.ts.map +1 -0
- package/dist/components/molecules/forms/autocomplete/index.js +4 -0
- package/dist/components/molecules/forms/item/item.d.ts +3 -3
- package/dist/components/molecules/index.d.ts +2 -2
- package/dist/components/molecules/index.d.ts.map +1 -1
- package/dist/components/molecules/index.js +1 -1
- package/dist/components/molecules/navigation/menu-dock/menu-dock.d.ts +5 -0
- package/dist/components/molecules/navigation/menu-dock/menu-dock.d.ts.map +1 -1
- package/dist/components/molecules/navigation/menu-dock/menu-dock.js +103 -10
- package/dist/components/molecules/typography/index.d.ts +0 -2
- package/dist/components/molecules/typography/index.d.ts.map +1 -1
- package/dist/components/molecules/typography/index.js +1 -1
- package/dist/components/organisms/model-selector/model-selector.d.ts +1 -1
- package/dist/index.js +460 -498
- package/package.json +28 -17
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
* MenuDock - Componente Molecule
|
|
3
3
|
*
|
|
4
4
|
* Componente de dock de menu com animação e suporte a múltiplos itens
|
|
5
|
+
* Suporta duas animações: "default" (underline animado) e "floating" (estilo macOS)
|
|
5
6
|
*/
|
|
6
7
|
"use client";
|
|
7
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
8
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
8
9
|
import { useAnimatedIndicator } from "@flowtomic/logic";
|
|
9
|
-
import { motion, useReducedMotion } from "motion/react";
|
|
10
|
+
import { AnimatePresence, motion, useMotionValue, useReducedMotion, useSpring, useTransform, } from "motion/react";
|
|
10
11
|
import { useEffect, useMemo, useRef, useState } from "react";
|
|
12
|
+
import { Menu } from "lucide-react";
|
|
11
13
|
import { cn } from "@/lib/utils";
|
|
12
14
|
const defaultItems = [
|
|
13
15
|
{ label: "home", icon: () => null },
|
|
@@ -16,7 +18,7 @@ const defaultItems = [
|
|
|
16
18
|
{ label: "security", icon: () => null },
|
|
17
19
|
{ label: "settings", icon: () => null },
|
|
18
20
|
];
|
|
19
|
-
export const MenuDock = ({ items, className, variant = "default", orientation = "horizontal", showLabels = true, animated: _animated = true, defaultActiveIndex = 0, activeIndex: controlledActiveIndex, onActiveIndexChange, }) => {
|
|
21
|
+
export const MenuDock = ({ items, className, variant = "default", orientation = "horizontal", showLabels = true, animated: _animated = true, animationType = "default", defaultActiveIndex = 0, activeIndex: controlledActiveIndex, onActiveIndexChange, desktopClassName, mobileClassName, }) => {
|
|
20
22
|
const finalItems = useMemo(() => {
|
|
21
23
|
const isValid = items && Array.isArray(items) && items.length >= 2 && items.length <= 8;
|
|
22
24
|
if (!isValid) {
|
|
@@ -25,6 +27,16 @@ export const MenuDock = ({ items, className, variant = "default", orientation =
|
|
|
25
27
|
}
|
|
26
28
|
return items;
|
|
27
29
|
}, [items]);
|
|
30
|
+
// Se animationType for "floating", renderizar FloatingDock
|
|
31
|
+
if (animationType === "floating") {
|
|
32
|
+
return (_jsx(FloatingDock, { items: finalItems.map((item) => ({
|
|
33
|
+
title: item.label,
|
|
34
|
+
icon: _jsx(item.icon, { className: "h-full w-full" }),
|
|
35
|
+
href: item.href || item.path || "#",
|
|
36
|
+
onClick: item.onClick,
|
|
37
|
+
})), desktopClassName: desktopClassName, mobileClassName: mobileClassName, className: className }));
|
|
38
|
+
}
|
|
39
|
+
// Animação default (comportamento original)
|
|
28
40
|
const [internalActiveIndex, setInternalActiveIndex] = useState(defaultActiveIndex);
|
|
29
41
|
// Usar índice controlado se fornecido, caso contrário usar estado interno
|
|
30
42
|
const isControlled = controlledActiveIndex !== undefined;
|
|
@@ -39,20 +51,38 @@ export const MenuDock = ({ items, className, variant = "default", orientation =
|
|
|
39
51
|
const shouldReduceMotion = useReducedMotion();
|
|
40
52
|
// Para o underline, precisamos rastrear o texto, não o botão
|
|
41
53
|
const textRefs = useRef([]);
|
|
54
|
+
const buttonRefs = useRef([]);
|
|
42
55
|
useEffect(() => {
|
|
43
56
|
if (activeIndex >= finalItems.length && !isControlled) {
|
|
44
57
|
setInternalActiveIndex(0);
|
|
45
58
|
}
|
|
46
59
|
}, [finalItems, activeIndex, isControlled]);
|
|
47
60
|
// Usar o hook apenas quando showLabels e horizontal
|
|
48
|
-
const
|
|
61
|
+
const shouldUseIndicator = showLabels && orientation === "horizontal";
|
|
62
|
+
const { indicatorStyle, registerElement, unregisterElement } = useAnimatedIndicator({
|
|
49
63
|
containerRef: containerRef,
|
|
50
|
-
activeSelector: '[data-active="true"]',
|
|
64
|
+
activeSelector: 'span[data-active="true"]',
|
|
65
|
+
value: activeIndex.toString(),
|
|
51
66
|
getElementValue: (element) => {
|
|
52
67
|
return element.getAttribute("data-index") || "";
|
|
53
68
|
},
|
|
54
|
-
updateOnResize:
|
|
69
|
+
updateOnResize: shouldUseIndicator,
|
|
55
70
|
});
|
|
71
|
+
// Registrar elementos quando shouldUseIndicator mudar ou items mudarem
|
|
72
|
+
useEffect(() => {
|
|
73
|
+
if (shouldUseIndicator) {
|
|
74
|
+
textRefs.current.forEach((el, index) => {
|
|
75
|
+
if (el) {
|
|
76
|
+
registerElement(el, index.toString());
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
return () => {
|
|
80
|
+
textRefs.current.forEach((_, index) => {
|
|
81
|
+
unregisterElement(index.toString());
|
|
82
|
+
});
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
}, [shouldUseIndicator, finalItems.length, registerElement, unregisterElement]);
|
|
56
86
|
const sizeClasses = {
|
|
57
87
|
default: "p-3",
|
|
58
88
|
compact: "p-2",
|
|
@@ -66,16 +96,18 @@ export const MenuDock = ({ items, className, variant = "default", orientation =
|
|
|
66
96
|
return (_jsxs("nav", { ref: containerRef, className: cn("relative flex", orientation === "horizontal" ? "flex-row" : "flex-col", "items-center gap-2", "bg-background border border-border rounded-lg", "p-2", className), "aria-label": "Menu dock", children: [finalItems.map((item, index) => {
|
|
67
97
|
const Icon = item.icon;
|
|
68
98
|
const isActive = activeIndex === index;
|
|
69
|
-
return (_jsxs("button", { type: "button",
|
|
99
|
+
return (_jsxs("button", { type: "button", ref: (el) => {
|
|
100
|
+
buttonRefs.current[index] = el;
|
|
101
|
+
}, "data-active": isActive ? "true" : "false", "data-index": index.toString(), onClick: () => {
|
|
70
102
|
setActiveIndex(index);
|
|
71
103
|
item.onClick?.();
|
|
72
104
|
}, className: cn("relative flex items-center gap-2", "px-3 py-2 rounded-md", "transition-all duration-200", "hover:bg-accent hover:text-accent-foreground", isActive && "bg-accent text-accent-foreground", sizeClasses[variant]), "aria-label": item.label, "aria-current": isActive ? "page" : undefined, children: [_jsx(Icon, { className: cn(iconSizes[variant], isActive && "text-primary") }), showLabels && (_jsx("span", { ref: (el) => {
|
|
73
105
|
textRefs.current[index] = el;
|
|
74
|
-
if (
|
|
106
|
+
if (shouldUseIndicator && el) {
|
|
75
107
|
registerElement(el, index.toString());
|
|
76
108
|
}
|
|
77
|
-
}, "data-active": isActive, "data-index": index.toString(), className: cn("text-sm font-medium", "transition-all duration-200", isActive && "text-primary"), children: item.label }))] }, item.id || `menu-item-${index}`));
|
|
78
|
-
}),
|
|
109
|
+
}, "data-active": isActive, "data-index": index.toString(), className: cn("text-sm font-medium inline-block", "transition-all duration-200", isActive && "text-primary"), children: item.label }))] }, item.id || `menu-item-${index}`));
|
|
110
|
+
}), shouldUseIndicator && (_jsx(motion.div, { className: "absolute bottom-0 bg-primary", initial: false, animate: shouldReduceMotion
|
|
79
111
|
? {
|
|
80
112
|
opacity: indicatorStyle.opacity,
|
|
81
113
|
}
|
|
@@ -90,8 +122,69 @@ export const MenuDock = ({ items, className, variant = "default", orientation =
|
|
|
90
122
|
mass: 0.5,
|
|
91
123
|
}, style: {
|
|
92
124
|
pointerEvents: "none",
|
|
125
|
+
zIndex: 0,
|
|
93
126
|
left: 0,
|
|
94
127
|
bottom: 0,
|
|
95
128
|
height: "2px",
|
|
96
129
|
} }))] }));
|
|
97
130
|
};
|
|
131
|
+
/**
|
|
132
|
+
* FloatingDock - Componente de dock estilo macOS
|
|
133
|
+
*
|
|
134
|
+
* Note: Use position fixed according to your needs
|
|
135
|
+
* Desktop navbar is better positioned at the bottom
|
|
136
|
+
* Mobile navbar is better positioned at bottom right.
|
|
137
|
+
*/
|
|
138
|
+
const FloatingDock = ({ items, desktopClassName, mobileClassName, className, }) => {
|
|
139
|
+
return (_jsxs(_Fragment, { children: [_jsx(FloatingDockDesktop, { items: items, className: desktopClassName || className }), _jsx(FloatingDockMobile, { items: items, className: mobileClassName || className })] }));
|
|
140
|
+
};
|
|
141
|
+
const FloatingDockMobile = ({ items, className }) => {
|
|
142
|
+
const [open, setOpen] = useState(false);
|
|
143
|
+
return (_jsxs("div", { className: cn("relative block md:hidden", className), children: [_jsx(AnimatePresence, { children: open && (_jsx(motion.div, { layoutId: "nav", className: "absolute inset-x-0 bottom-full mb-2 flex flex-col gap-2", children: items.map((item, idx) => (_jsx(motion.div, { initial: { opacity: 0, y: 10 }, animate: {
|
|
144
|
+
opacity: 1,
|
|
145
|
+
y: 0,
|
|
146
|
+
}, exit: {
|
|
147
|
+
opacity: 0,
|
|
148
|
+
y: 10,
|
|
149
|
+
transition: {
|
|
150
|
+
delay: idx * 0.05,
|
|
151
|
+
},
|
|
152
|
+
}, transition: { delay: (items.length - 1 - idx) * 0.05 }, children: _jsx("a", { href: item.href, onClick: item.onClick, className: "flex h-10 w-10 items-center justify-center rounded-full bg-gray-50 dark:bg-neutral-900", children: _jsx("div", { className: "h-4 w-4", children: item.icon }) }) }, item.title))) })) }), _jsx("button", { onClick: () => setOpen(!open), className: "flex h-10 w-10 items-center justify-center rounded-full bg-gray-50 dark:bg-neutral-800", "aria-label": "Toggle menu", children: _jsx(Menu, { className: "h-5 w-5 text-neutral-500 dark:text-neutral-400" }) })] }));
|
|
153
|
+
};
|
|
154
|
+
const FloatingDockDesktop = ({ items, className }) => {
|
|
155
|
+
const mouseX = useMotionValue(Infinity);
|
|
156
|
+
return (_jsx(motion.div, { onMouseMove: (e) => mouseX.set(e.pageX), onMouseLeave: () => mouseX.set(Infinity), className: cn("mx-auto hidden h-16 items-end gap-4 rounded-2xl bg-gray-50 px-4 pb-3 md:flex dark:bg-neutral-900", className), children: items.map((item) => (_jsx(IconContainer, { mouseX: mouseX, ...item }, item.title))) }));
|
|
157
|
+
};
|
|
158
|
+
function IconContainer({ mouseX, title, icon, href, onClick, }) {
|
|
159
|
+
const ref = useRef(null);
|
|
160
|
+
const distance = useTransform(mouseX, (val) => {
|
|
161
|
+
const bounds = ref.current?.getBoundingClientRect() ?? { x: 0, width: 0 };
|
|
162
|
+
return val - bounds.x - bounds.width / 2;
|
|
163
|
+
});
|
|
164
|
+
const widthTransform = useTransform(distance, [-150, 0, 150], [40, 80, 40]);
|
|
165
|
+
const heightTransform = useTransform(distance, [-150, 0, 150], [40, 80, 40]);
|
|
166
|
+
const widthTransformIcon = useTransform(distance, [-150, 0, 150], [20, 40, 20]);
|
|
167
|
+
const heightTransformIcon = useTransform(distance, [-150, 0, 150], [20, 40, 20]);
|
|
168
|
+
const width = useSpring(widthTransform, {
|
|
169
|
+
mass: 0.1,
|
|
170
|
+
stiffness: 150,
|
|
171
|
+
damping: 12,
|
|
172
|
+
});
|
|
173
|
+
const height = useSpring(heightTransform, {
|
|
174
|
+
mass: 0.1,
|
|
175
|
+
stiffness: 150,
|
|
176
|
+
damping: 12,
|
|
177
|
+
});
|
|
178
|
+
const widthIcon = useSpring(widthTransformIcon, {
|
|
179
|
+
mass: 0.1,
|
|
180
|
+
stiffness: 150,
|
|
181
|
+
damping: 12,
|
|
182
|
+
});
|
|
183
|
+
const heightIcon = useSpring(heightTransformIcon, {
|
|
184
|
+
mass: 0.1,
|
|
185
|
+
stiffness: 150,
|
|
186
|
+
damping: 12,
|
|
187
|
+
});
|
|
188
|
+
const [hovered, setHovered] = useState(false);
|
|
189
|
+
return (_jsx("a", { href: href, onClick: onClick, children: _jsxs(motion.div, { ref: ref, style: { width, height }, onMouseEnter: () => setHovered(true), onMouseLeave: () => setHovered(false), className: "relative flex aspect-square items-center justify-center rounded-full bg-gray-200 dark:bg-neutral-800", children: [_jsx(AnimatePresence, { children: hovered && (_jsx(motion.div, { initial: { opacity: 0, y: 10, x: "-50%" }, animate: { opacity: 1, y: 0, x: "-50%" }, exit: { opacity: 0, y: 2, x: "-50%" }, className: "absolute -top-8 left-1/2 w-fit rounded-md border border-gray-200 bg-gray-100 px-2 py-0.5 text-xs whitespace-pre text-neutral-700 dark:border-neutral-900 dark:bg-neutral-800 dark:text-white", children: title })) }), _jsx(motion.div, { style: { width: widthIcon, height: heightIcon }, className: "flex items-center justify-center", children: icon })] }) }));
|
|
190
|
+
}
|
|
@@ -2,6 +2,4 @@
|
|
|
2
2
|
* Typography Molecules - Componentes de Tipografia Compostos
|
|
3
3
|
* Atomic Design: Componentes compostos de tipografia
|
|
4
4
|
*/
|
|
5
|
-
export type { AnimatedShinyTextProps } from "./animated-shiny-text";
|
|
6
|
-
export { AnimatedShinyText } from "./animated-shiny-text";
|
|
7
5
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/molecules/typography/index.ts"],"names":[],"mappings":"AAAA;;;GAGG
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/molecules/typography/index.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
|
@@ -30,7 +30,7 @@ export declare const ModelSelectorInput: React.ForwardRefExoticComponent<Omit<Om
|
|
|
30
30
|
ref?: React.Ref<HTMLInputElement>;
|
|
31
31
|
} & {
|
|
32
32
|
asChild?: boolean;
|
|
33
|
-
}, "
|
|
33
|
+
}, "key" | "asChild" | keyof React.InputHTMLAttributes<HTMLInputElement>>, "onChange" | "type" | "value"> & {
|
|
34
34
|
value?: string;
|
|
35
35
|
onValueChange?: (search: string) => void;
|
|
36
36
|
} & React.RefAttributes<HTMLInputElement>, "ref"> & React.RefAttributes<HTMLInputElement>, "ref"> & React.RefAttributes<HTMLInputElement>>;
|