@mlw-packages/react-components 1.10.19 → 1.10.20

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
@@ -3858,7 +3858,7 @@ var FileUploader = React32__namespace.forwardRef(
3858
3858
  showPreview = true,
3859
3859
  dropzoneText = "Arraste arquivos aqui ou clique para selecionar",
3860
3860
  dropzoneSubtext,
3861
- animate: animate2 = true,
3861
+ animate: animate3 = true,
3862
3862
  ...props
3863
3863
  }, ref) => {
3864
3864
  const [isDragging, setIsDragging] = React32__namespace.useState(false);
@@ -4011,7 +4011,7 @@ var FileUploader = React32__namespace.forwardRef(
4011
4011
  framerMotion.motion.p,
4012
4012
  {
4013
4013
  className: "mb-2 text-xs font-semibold text-foreground",
4014
- initial: animate2 ? { opacity: 0, y: -10 } : false,
4014
+ initial: animate3 ? { opacity: 0, y: -10 } : false,
4015
4015
  animate: { opacity: 1, y: 0 },
4016
4016
  transition: { delay: 0.1 },
4017
4017
  children: dropzoneText
@@ -4021,7 +4021,7 @@ var FileUploader = React32__namespace.forwardRef(
4021
4021
  framerMotion.motion.p,
4022
4022
  {
4023
4023
  className: "text-xs text-muted-foreground",
4024
- initial: animate2 ? { opacity: 0, y: -10 } : false,
4024
+ initial: animate3 ? { opacity: 0, y: -10 } : false,
4025
4025
  animate: { opacity: 1, y: 0 },
4026
4026
  transition: { delay: 0.2 },
4027
4027
  children: defaultSubtext
@@ -4031,7 +4031,7 @@ var FileUploader = React32__namespace.forwardRef(
4031
4031
  framerMotion.motion.div,
4032
4032
  {
4033
4033
  className: "py-2 w-full",
4034
- initial: animate2 ? { opacity: 0, y: 10 } : false,
4034
+ initial: animate3 ? { opacity: 0, y: 10 } : false,
4035
4035
  animate: { opacity: 1, y: 0 },
4036
4036
  transition: { delay: 0.3 },
4037
4037
  children: [
@@ -4046,7 +4046,7 @@ var FileUploader = React32__namespace.forwardRef(
4046
4046
  framerMotion.motion.div,
4047
4047
  {
4048
4048
  layout: true,
4049
- initial: animate2 ? { opacity: 0, x: -20 } : false,
4049
+ initial: animate3 ? { opacity: 0, x: -20 } : false,
4050
4050
  animate: { opacity: 1, x: 0 },
4051
4051
  exit: {
4052
4052
  opacity: 0,
@@ -4054,7 +4054,7 @@ var FileUploader = React32__namespace.forwardRef(
4054
4054
  transition: { duration: 0.2 }
4055
4055
  },
4056
4056
  transition: {
4057
- delay: animate2 ? index * 0.05 : 0,
4057
+ delay: animate3 ? index * 0.05 : 0,
4058
4058
  layout: { duration: 0.2 }
4059
4059
  },
4060
4060
  className: cn(
@@ -16625,6 +16625,13 @@ var useIsTruncated = (ref) => {
16625
16625
  }, [ref]);
16626
16626
  return truncated;
16627
16627
  };
16628
+ var SNAP_HEIGHTS = {
16629
+ collapsed: "80px",
16630
+ peek: "42dvh",
16631
+ full: "85dvh"
16632
+ };
16633
+ var VELOCITY_THRESHOLD = 500;
16634
+ var CLOSE_THRESHOLD = 50;
16628
16635
  var CopyData = ({ value }) => {
16629
16636
  const [copied, setCopied] = React32.useState(false);
16630
16637
  const handleCopy = React32.useCallback(() => {
@@ -16658,26 +16665,56 @@ var propertyLabels = {
16658
16665
  Destino: "Destino",
16659
16666
  Origem: "Origem"
16660
16667
  };
16661
- var IntegrationCard = ({ title, details }) => {
16668
+ var LongPressTooltip = ({ content, isMobile, children }) => {
16669
+ const [open, setOpen] = React32.useState(false);
16670
+ const timerRef = React32.useRef(null);
16671
+ const handleTouchStart = React32.useCallback(() => {
16672
+ timerRef.current = setTimeout(() => setOpen(true), 1e3);
16673
+ }, []);
16674
+ const handleTouchEnd = React32.useCallback(() => {
16675
+ if (timerRef.current) clearTimeout(timerRef.current);
16676
+ setTimeout(() => setOpen(false), 1500);
16677
+ }, []);
16678
+ React32.useEffect(
16679
+ () => () => {
16680
+ if (timerRef.current) clearTimeout(timerRef.current);
16681
+ },
16682
+ []
16683
+ );
16684
+ return /* @__PURE__ */ jsxRuntime.jsx(TooltipProviderBase, { children: /* @__PURE__ */ jsxRuntime.jsxs(
16685
+ TooltipBase,
16686
+ {
16687
+ open: isMobile ? open : void 0,
16688
+ onOpenChange: isMobile ? setOpen : void 0,
16689
+ children: [
16690
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipTriggerBase, { asChild: true, children: isMobile ? React32__namespace.default.cloneElement(children, {
16691
+ onTouchStart: handleTouchStart,
16692
+ onTouchEnd: handleTouchEnd,
16693
+ onTouchCancel: handleTouchEnd
16694
+ }) : children }),
16695
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipContentBase, { sideOffset: 6, className: "z-[10001]", children: content })
16696
+ ]
16697
+ }
16698
+ ) });
16699
+ };
16700
+ var IntegrationCard = ({ title, details, isMobile }) => {
16662
16701
  const titleRef = React32.useRef(null);
16663
16702
  const isTitleTruncated = useIsTruncated(titleRef);
16664
16703
  const blackList = ["id", "elementId", "identity"];
16665
16704
  const entries = details ? Object.entries(details).filter(
16666
16705
  ([key, value]) => value !== void 0 && value !== null && value !== "" && !blackList.includes(key)
16667
16706
  ) : [];
16707
+ const titleSpan = /* @__PURE__ */ jsxRuntime.jsx(
16708
+ "span",
16709
+ {
16710
+ ref: titleRef,
16711
+ className: "text-sm font-bold text-foreground truncate flex-1 min-w-0 cursor-default",
16712
+ children: title
16713
+ }
16714
+ );
16668
16715
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-border/40 bg-muted/20 overflow-hidden", children: [
16669
16716
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 px-3 py-2 border-b border-border/30", children: [
16670
- /* @__PURE__ */ jsxRuntime.jsx(TooltipProviderBase, { children: /* @__PURE__ */ jsxRuntime.jsxs(TooltipBase, { children: [
16671
- /* @__PURE__ */ jsxRuntime.jsx(TooltipTriggerBase, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
16672
- "span",
16673
- {
16674
- ref: titleRef,
16675
- className: "text-sm font-bold text-foreground truncate flex-1 min-w-0 cursor-default",
16676
- children: title
16677
- }
16678
- ) }),
16679
- isTitleTruncated && /* @__PURE__ */ jsxRuntime.jsx(TooltipContentBase, { sideOffset: 6, className: "z-[10001]", children: title })
16680
- ] }) }),
16717
+ isTitleTruncated ? /* @__PURE__ */ jsxRuntime.jsx(LongPressTooltip, { content: title, isMobile, children: titleSpan }) : titleSpan,
16681
16718
  entries.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
16682
16719
  CopyData,
16683
16720
  {
@@ -16697,69 +16734,59 @@ var IntegrationCard = ({ title, details }) => {
16697
16734
  }) })
16698
16735
  ] });
16699
16736
  };
16700
- var Name = ({
16701
- name,
16702
- description
16703
- }) => {
16737
+ var Name = ({ name, description, isMobile }) => {
16704
16738
  const nameRef = React32.useRef(null);
16705
16739
  const descRef = React32.useRef(null);
16706
16740
  const isNameTruncated = useIsTruncated(nameRef);
16707
16741
  const isDescTruncated = useIsTruncated(descRef);
16708
16742
  const showTooltip = isNameTruncated || isDescTruncated;
16709
- return /* @__PURE__ */ jsxRuntime.jsx(TooltipProviderBase, { children: /* @__PURE__ */ jsxRuntime.jsxs(TooltipBase, { children: [
16710
- /* @__PURE__ */ jsxRuntime.jsx(TooltipTriggerBase, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "cursor-default min-w-0", children: [
16711
- /* @__PURE__ */ jsxRuntime.jsx(
16712
- "h3",
16713
- {
16714
- ref: nameRef,
16715
- className: "text-xl font-bold text-foreground tracking-tight truncate",
16716
- children: name
16717
- }
16718
- ),
16719
- description && /* @__PURE__ */ jsxRuntime.jsx(
16720
- "p",
16721
- {
16722
- ref: descRef,
16723
- className: "text-xs text-foreground/70 truncate mt-0.5",
16724
- children: description
16725
- }
16726
- )
16727
- ] }) }),
16728
- showTooltip && /* @__PURE__ */ jsxRuntime.jsxs(TooltipContentBase, { sideOffset: 8, className: "z-[10001]", children: [
16729
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-semibold", children: name }),
16730
- description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-foreground/70 mt-0.5", children: description })
16731
- ] })
16732
- ] }) });
16743
+ const content = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "cursor-default min-w-0", children: [
16744
+ /* @__PURE__ */ jsxRuntime.jsx(
16745
+ "h3",
16746
+ {
16747
+ ref: nameRef,
16748
+ className: "text-xl font-bold text-foreground tracking-tight truncate",
16749
+ children: name
16750
+ }
16751
+ ),
16752
+ description && /* @__PURE__ */ jsxRuntime.jsx("p", { ref: descRef, className: "text-xs text-foreground/70 truncate mt-0.5", children: description })
16753
+ ] });
16754
+ if (!showTooltip) return content;
16755
+ return /* @__PURE__ */ jsxRuntime.jsx(
16756
+ LongPressTooltip,
16757
+ {
16758
+ content: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
16759
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-semibold", children: name }),
16760
+ description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-foreground/70 mt-0.5", children: description })
16761
+ ] }),
16762
+ isMobile,
16763
+ children: content
16764
+ }
16765
+ );
16733
16766
  };
16734
- var SystemNode = React32__namespace.default.forwardRef(
16735
- ({ label }, ref) => {
16736
- const innerRef = React32.useRef(null);
16737
- const truncated = label.length > 9 ? label.substring(0, 9) + "\u2026" : label;
16738
- const needsTooltip = label.length > 9;
16739
- const setRefs = React32.useCallback(
16740
- (node) => {
16741
- innerRef.current = node;
16742
- if (typeof ref === "function") ref(node);
16743
- else if (ref)
16744
- ref.current = node;
16745
- },
16746
- [ref]
16747
- );
16748
- const circle = /* @__PURE__ */ jsxRuntime.jsx(
16767
+ function SystemNodeInner({ label, isMobile }, ref) {
16768
+ const truncated = label.length > 9 ? label.substring(0, 9) + "\u2026" : label;
16769
+ const needsTooltip = label.length > 9;
16770
+ if (!needsTooltip) {
16771
+ return /* @__PURE__ */ jsxRuntime.jsx(
16749
16772
  "div",
16750
16773
  {
16751
- ref: setRefs,
16774
+ ref,
16752
16775
  className: "w-[76px] h-[76px] rounded-full bg-primary flex items-center justify-center shrink-0 z-10 cursor-default",
16753
16776
  children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-bold text-primary-foreground text-center px-2 leading-tight select-none", children: truncated })
16754
16777
  }
16755
16778
  );
16756
- if (!needsTooltip) return circle;
16757
- return /* @__PURE__ */ jsxRuntime.jsx(TooltipProviderBase, { children: /* @__PURE__ */ jsxRuntime.jsxs(TooltipBase, { children: [
16758
- /* @__PURE__ */ jsxRuntime.jsx(TooltipTriggerBase, { asChild: true, children: circle }),
16759
- /* @__PURE__ */ jsxRuntime.jsx(TooltipContentBase, { sideOffset: 8, className: "z-[10001]", children: label })
16760
- ] }) });
16761
16779
  }
16762
- );
16780
+ return /* @__PURE__ */ jsxRuntime.jsx(LongPressTooltip, { content: label, isMobile, children: /* @__PURE__ */ jsxRuntime.jsx(
16781
+ "div",
16782
+ {
16783
+ ref,
16784
+ className: "w-[76px] h-[76px] rounded-full bg-primary flex items-center justify-center shrink-0 z-10 cursor-default",
16785
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-bold text-primary-foreground text-center px-2 leading-tight select-none", children: truncated })
16786
+ }
16787
+ ) });
16788
+ }
16789
+ var SystemNode = React32__namespace.default.forwardRef(SystemNodeInner);
16763
16790
  SystemNode.displayName = "SystemNode";
16764
16791
  var Beam = ({ isInput, containerRef, leftRef, rightRef }) => {
16765
16792
  const gradientId = React32.useId();
@@ -16767,6 +16794,7 @@ var Beam = ({ isInput, containerRef, leftRef, rightRef }) => {
16767
16794
  const [svgSize, setSvgSize] = React32.useState({ w: 0, h: 0 });
16768
16795
  React32.useEffect(() => {
16769
16796
  let rafId;
16797
+ let running = true;
16770
16798
  const update = () => {
16771
16799
  const container = containerRef.current;
16772
16800
  const left = leftRef.current;
@@ -16779,39 +16807,31 @@ var Beam = ({ isInput, containerRef, leftRef, rightRef }) => {
16779
16807
  const cy1 = lr.top - cr.top + lr.height / 2;
16780
16808
  const cx2 = rr.left - cr.left + rr.width / 2;
16781
16809
  const cy2 = rr.top - cr.top + rr.height / 2;
16782
- const dx = cx2 - cx1, dy = cy2 - cy1;
16810
+ const dx = cx2 - cx1;
16811
+ const dy = cy2 - cy1;
16783
16812
  const dist = Math.sqrt(dx * dx + dy * dy);
16784
16813
  if (dist === 0) return;
16785
- const ux = dx / dist, uy = dy / dist;
16814
+ const ux = dx / dist;
16815
+ const uy = dy / dist;
16786
16816
  const r1 = lr.width / 2;
16787
16817
  const r2 = rr.width / 2;
16788
- setSvgSize({ w: cr.width, h: cr.height });
16789
- setPathD(
16790
- `M ${cx1 + ux * r1},${cy1 + uy * r1} L ${cx2 - ux * r2},${cy2 - uy * r2}`
16818
+ const newW = cr.width;
16819
+ const newH = cr.height;
16820
+ const newPath = `M ${cx1 + ux * r1},${cy1 + uy * r1} L ${cx2 - ux * r2},${cy2 - uy * r2}`;
16821
+ setSvgSize(
16822
+ (prev) => prev.w !== newW || prev.h !== newH ? { w: newW, h: newH } : prev
16791
16823
  );
16824
+ setPathD((prev) => prev !== newPath ? newPath : prev);
16792
16825
  };
16793
- const schedule = () => {
16794
- cancelAnimationFrame(rafId);
16795
- rafId = requestAnimationFrame(update);
16826
+ const loop = () => {
16827
+ if (!running) return;
16828
+ update();
16829
+ rafId = requestAnimationFrame(loop);
16796
16830
  };
16797
- requestAnimationFrame(() => requestAnimationFrame(update));
16798
- schedule();
16799
- const ro = new ResizeObserver(schedule);
16800
- if (containerRef.current) ro.observe(containerRef.current);
16801
- if (leftRef.current) ro.observe(leftRef.current);
16802
- if (rightRef.current) ro.observe(rightRef.current);
16803
- const mo = new MutationObserver(schedule);
16804
- if (containerRef.current) {
16805
- mo.observe(containerRef.current, {
16806
- attributes: true,
16807
- attributeFilter: ["class", "style"],
16808
- subtree: true
16809
- });
16810
- }
16831
+ rafId = requestAnimationFrame(loop);
16811
16832
  return () => {
16833
+ running = false;
16812
16834
  cancelAnimationFrame(rafId);
16813
- ro.disconnect();
16814
- mo.disconnect();
16815
16835
  };
16816
16836
  }, [containerRef, leftRef, rightRef]);
16817
16837
  const animX1 = isInput ? ["90%", "-10%"] : ["10%", "110%"];
@@ -16877,7 +16897,7 @@ var Beam = ({ isInput, containerRef, leftRef, rightRef }) => {
16877
16897
  }
16878
16898
  );
16879
16899
  };
16880
- var SystemsDiagram = ({ isInput, currentSystem, externalSystem }) => {
16900
+ var SystemsDiagram = ({ isInput, currentSystem, externalSystem, isMobile }) => {
16881
16901
  const containerRef = React32.useRef(null);
16882
16902
  const leftRef = React32.useRef(null);
16883
16903
  const rightRef = React32.useRef(null);
@@ -16891,14 +16911,16 @@ var SystemsDiagram = ({ isInput, currentSystem, externalSystem }) => {
16891
16911
  SystemNode,
16892
16912
  {
16893
16913
  ref: leftRef,
16894
- label: isInput ? externalSystem : currentSystem
16914
+ label: isInput ? externalSystem : currentSystem,
16915
+ isMobile
16895
16916
  }
16896
16917
  ),
16897
16918
  /* @__PURE__ */ jsxRuntime.jsx(
16898
16919
  SystemNode,
16899
16920
  {
16900
16921
  ref: rightRef,
16901
- label: isInput ? currentSystem : externalSystem
16922
+ label: isInput ? currentSystem : externalSystem,
16923
+ isMobile
16902
16924
  }
16903
16925
  ),
16904
16926
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -16914,47 +16936,84 @@ var SystemsDiagram = ({ isInput, currentSystem, externalSystem }) => {
16914
16936
  }
16915
16937
  );
16916
16938
  };
16917
- var BodyComponent = ({ data, isLoading, connections, isInput, externalSystem }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-3 py-3 space-y-3 max-h-[460px] overflow-y-auto [&::-webkit-scrollbar]:w-1 [&::-webkit-scrollbar-track]:bg-transparent [&::-webkit-scrollbar-thumb]:bg-muted-foreground/20 [&::-webkit-scrollbar-thumb]:rounded-full hover:[&::-webkit-scrollbar-thumb]:bg-muted-foreground/40 transition-colors", children: [
16918
- isLoading ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
16919
- /* @__PURE__ */ jsxRuntime.jsx(SkeletonBase, { className: "h-6 w-3/4" }),
16920
- /* @__PURE__ */ jsxRuntime.jsx(SkeletonBase, { className: "h-3.5 w-1/2" })
16921
- ] }) : /* @__PURE__ */ jsxRuntime.jsx(Name, { name: data.name, description: data.description }),
16922
- isLoading ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
16923
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between py-1", children: [
16924
- /* @__PURE__ */ jsxRuntime.jsx(SkeletonBase, { className: "w-[76px] h-[76px] rounded-full" }),
16925
- /* @__PURE__ */ jsxRuntime.jsx(SkeletonBase, { className: "w-[76px] h-[76px] rounded-full" })
16926
- ] }),
16927
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-border/20" }),
16928
- [1, 2].map((i) => /* @__PURE__ */ jsxRuntime.jsxs(
16929
- "div",
16930
- {
16931
- className: "rounded-lg border border-border/20 overflow-hidden",
16932
- children: [
16933
- /* @__PURE__ */ jsxRuntime.jsx(SkeletonBase, { className: "h-8 w-full" }),
16934
- [1, 2, 3].map((j) => /* @__PURE__ */ jsxRuntime.jsx(SkeletonBase, { className: "h-7 w-full mt-px" }, j))
16935
- ]
16939
+ var BodyComponent = ({
16940
+ data,
16941
+ isLoading,
16942
+ connections,
16943
+ isInput,
16944
+ externalSystem,
16945
+ isMobile,
16946
+ scrollable
16947
+ }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative min-h-0 flex-1 overflow-hidden", children: [
16948
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute top-0 left-0 right-0 h-5 bg-gradient-to-b from-card to-transparent z-10 pointer-events-none" }),
16949
+ /* @__PURE__ */ jsxRuntime.jsxs(
16950
+ "div",
16951
+ {
16952
+ className: [
16953
+ "px-3 py-3 space-y-3",
16954
+ scrollable ? "overflow-y-auto overscroll-contain [&::-webkit-scrollbar]:w-1 [&::-webkit-scrollbar-track]:bg-transparent [&::-webkit-scrollbar-thumb]:bg-primary/20 [&::-webkit-scrollbar-thumb]:rounded-full" : "overflow-hidden",
16955
+ isMobile ? "max-h-[calc(85dvh-80px)]" : "max-h [&::-webkit-scrollbar]:hidden"
16956
+ ].join(" "),
16957
+ onPointerDownCapture: (e) => {
16958
+ if (scrollable) e.stopPropagation();
16936
16959
  },
16937
- i
16938
- ))
16939
- ] }) : connections.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground text-center", children: "Nenhuma conex\xE3o encontrada" }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
16940
- /* @__PURE__ */ jsxRuntime.jsx(
16941
- SystemsDiagram,
16942
- {
16943
- isInput,
16944
- currentSystem: data.name,
16945
- externalSystem
16946
- }
16947
- ),
16948
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-bold text-muted-foreground uppercase -mb-2", children: isInput ? "Informa\xE7\xF5es de Entrada" : "Informa\xE7\xF5es de Sa\xEDda" }) }),
16949
- /* @__PURE__ */ jsxRuntime.jsx("div", { children: connections.map((conn) => /* @__PURE__ */ jsxRuntime.jsx(
16950
- IntegrationCard,
16951
- {
16952
- title: conn.name,
16953
- details: conn.integration
16960
+ onTouchStartCapture: (e) => {
16961
+ if (scrollable) e.stopPropagation();
16954
16962
  },
16955
- conn.id
16956
- )) })
16957
- ] })
16963
+ children: [
16964
+ isLoading ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
16965
+ /* @__PURE__ */ jsxRuntime.jsx(SkeletonBase, { className: "h-6 w-3/4" }),
16966
+ /* @__PURE__ */ jsxRuntime.jsx(SkeletonBase, { className: "h-3.5 w-1/2" })
16967
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx(
16968
+ Name,
16969
+ {
16970
+ name: data.name,
16971
+ description: data.description,
16972
+ isMobile
16973
+ }
16974
+ ),
16975
+ isLoading ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
16976
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between py-1", children: [
16977
+ /* @__PURE__ */ jsxRuntime.jsx(SkeletonBase, { className: "w-[76px] h-[76px] rounded-full" }),
16978
+ /* @__PURE__ */ jsxRuntime.jsx(SkeletonBase, { className: "w-[76px] h-[76px] rounded-full" })
16979
+ ] }),
16980
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-border/20" }),
16981
+ [1, 2].map((i) => /* @__PURE__ */ jsxRuntime.jsxs(
16982
+ "div",
16983
+ {
16984
+ className: "rounded-lg border border-border/20 overflow-hidden",
16985
+ children: [
16986
+ /* @__PURE__ */ jsxRuntime.jsx(SkeletonBase, { className: "h-8 w-full" }),
16987
+ [1, 2, 3].map((j) => /* @__PURE__ */ jsxRuntime.jsx(SkeletonBase, { className: "h-7 w-full mt-px" }, j))
16988
+ ]
16989
+ },
16990
+ i
16991
+ ))
16992
+ ] }) : connections.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground text-center", children: "Nenhuma conex\xE3o encontrada" }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
16993
+ /* @__PURE__ */ jsxRuntime.jsx(
16994
+ SystemsDiagram,
16995
+ {
16996
+ isInput,
16997
+ currentSystem: data.name,
16998
+ externalSystem,
16999
+ isMobile
17000
+ }
17001
+ ),
17002
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-bold text-muted-foreground uppercase -mb-2", children: isInput ? "Informa\xE7\xF5es de Entrada" : "Informa\xE7\xF5es de Sa\xEDda" }) }),
17003
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: connections.map((conn) => /* @__PURE__ */ jsxRuntime.jsx(
17004
+ IntegrationCard,
17005
+ {
17006
+ title: conn.name,
17007
+ details: conn.integration,
17008
+ isMobile
17009
+ },
17010
+ conn.id
17011
+ )) })
17012
+ ] })
17013
+ ]
17014
+ }
17015
+ ),
17016
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute bottom-0 left-0 right-0 h-5 bg-gradient-to-t from-card to-transparent z-10 pointer-events-none" })
16958
17017
  ] });
16959
17018
  var Body = React32__namespace.default.memo(BodyComponent);
16960
17019
  var modalVariants = {
@@ -16974,6 +17033,25 @@ var modalVariants = {
16974
17033
  transition: { type: "spring", stiffness: 400, damping: 28 }
16975
17034
  }
16976
17035
  };
17036
+ function resolveSnapPx(snap) {
17037
+ const vh = typeof window !== "undefined" ? window.innerHeight : 800;
17038
+ if (snap === "collapsed") return 80;
17039
+ if (snap === "peek") return vh * 0.42;
17040
+ return vh * 0.85;
17041
+ }
17042
+ function nearestSnap(heightPx) {
17043
+ const snaps = ["collapsed", "peek", "full"];
17044
+ let best = "peek";
17045
+ let bestDist = Infinity;
17046
+ for (const s of snaps) {
17047
+ const dist = Math.abs(resolveSnapPx(s) - heightPx);
17048
+ if (dist < bestDist) {
17049
+ bestDist = dist;
17050
+ best = s;
17051
+ }
17052
+ }
17053
+ return best;
17054
+ }
16977
17055
  var IntegrationModal = ({
16978
17056
  id,
16979
17057
  data,
@@ -17068,6 +17146,66 @@ var IntegrationModal = ({
17068
17146
  },
17069
17147
  [id, onMouseDown]
17070
17148
  );
17149
+ const [snap, setSnap] = React32.useState("peek");
17150
+ const sheetHeight = framerMotion.useMotionValue(SNAP_HEIGHTS.peek);
17151
+ const snapTo = React32.useCallback(
17152
+ (target) => {
17153
+ setSnap(target);
17154
+ framerMotion.animate(sheetHeight, SNAP_HEIGHTS[target], {
17155
+ type: "spring",
17156
+ stiffness: 320,
17157
+ damping: 36
17158
+ });
17159
+ },
17160
+ [sheetHeight]
17161
+ );
17162
+ React32.useEffect(() => {
17163
+ if (isMobile) {
17164
+ sheetHeight.set("0px");
17165
+ framerMotion.animate(sheetHeight, SNAP_HEIGHTS.peek, {
17166
+ type: "spring",
17167
+ stiffness: 320,
17168
+ damping: 36
17169
+ });
17170
+ }
17171
+ }, [isMobile, sheetHeight]);
17172
+ const handleDragEnd = React32.useCallback(
17173
+ (_, info) => {
17174
+ const vy = info.velocity.y;
17175
+ const dy = info.offset.y;
17176
+ const currentHeightStr = sheetHeight.get();
17177
+ const currentHeightPx = typeof currentHeightStr === "string" && currentHeightStr.endsWith("dvh") ? parseFloat(currentHeightStr) / 100 * window.innerHeight : parseFloat(currentHeightStr);
17178
+ const draggedHeightPx = currentHeightPx - dy;
17179
+ const collapsedPx = resolveSnapPx("collapsed");
17180
+ if (draggedHeightPx < collapsedPx - CLOSE_THRESHOLD || snap === "collapsed" && vy > VELOCITY_THRESHOLD) {
17181
+ onClose(id);
17182
+ return;
17183
+ }
17184
+ if (vy < -VELOCITY_THRESHOLD) {
17185
+ if (snap === "collapsed") {
17186
+ snapTo("peek");
17187
+ return;
17188
+ }
17189
+ if (snap === "peek") {
17190
+ snapTo("full");
17191
+ return;
17192
+ }
17193
+ }
17194
+ if (vy > VELOCITY_THRESHOLD) {
17195
+ if (snap === "full") {
17196
+ snapTo("peek");
17197
+ return;
17198
+ }
17199
+ if (snap === "peek") {
17200
+ snapTo("collapsed");
17201
+ return;
17202
+ }
17203
+ }
17204
+ const nearest = nearestSnap(draggedHeightPx);
17205
+ snapTo(nearest);
17206
+ },
17207
+ [id, onClose, snap, snapTo, sheetHeight]
17208
+ );
17071
17209
  const inputConnections = React32.useMemo(
17072
17210
  () => data.connections.filter((c) => c.type === "entrada"),
17073
17211
  [data.connections]
@@ -17082,19 +17220,19 @@ var IntegrationModal = ({
17082
17220
  const header = /* @__PURE__ */ jsxRuntime.jsxs(
17083
17221
  "div",
17084
17222
  {
17085
- className: "flex items-center justify-between py-1 border-b border-border shrink-0 max-w-lg",
17086
- onMouseDown: handleMouseDownLocal,
17087
- onTouchStart: handleTouchStartLocal,
17223
+ className: "flex items-center justify-between py-1 border-b border-border shrink-0",
17224
+ onMouseDown: !isMobile ? handleMouseDownLocal : void 0,
17225
+ onTouchStart: !isMobile ? handleTouchStartLocal : void 0,
17088
17226
  style: {
17089
- touchAction: "none",
17090
- cursor: dragging ? "grabbing" : "grab"
17227
+ touchAction: isMobile ? "auto" : "none",
17228
+ cursor: isMobile ? "default" : dragging ? "grabbing" : "grab"
17091
17229
  },
17092
17230
  children: [
17093
17231
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 px-3", children: [
17094
- /* @__PURE__ */ jsxRuntime.jsx(react.DotsSixVerticalIcon, { size: 16, className: "text-primary" }),
17232
+ !isMobile && /* @__PURE__ */ jsxRuntime.jsx(react.DotsSixVerticalIcon, { size: 16, className: "text-primary" }),
17095
17233
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: title })
17096
17234
  ] }),
17097
- /* @__PURE__ */ jsxRuntime.jsx(
17235
+ !isMobile && /* @__PURE__ */ jsxRuntime.jsx(
17098
17236
  ButtonBase,
17099
17237
  {
17100
17238
  variant: "ghost",
@@ -17108,7 +17246,15 @@ var IntegrationModal = ({
17108
17246
  ]
17109
17247
  }
17110
17248
  );
17111
- const bodyProps = { data, isLoading, connections, isInput, externalSystem };
17249
+ const bodyProps = {
17250
+ data,
17251
+ isLoading,
17252
+ connections,
17253
+ isInput,
17254
+ externalSystem,
17255
+ isMobile,
17256
+ scrollable: isMobile ? snap === "full" : true
17257
+ };
17112
17258
  if (isMobile) {
17113
17259
  return /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
17114
17260
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -17125,17 +17271,42 @@ var IntegrationModal = ({
17125
17271
  /* @__PURE__ */ jsxRuntime.jsxs(
17126
17272
  framerMotion.motion.div,
17127
17273
  {
17128
- className: "fixed bottom-0 left-0 right-0 z-[10000] bg-card border-t border-border/50 rounded-t-2xl shadow-2xl flex flex-col min-h-0",
17129
- style: { maxHeight: "85dvh" },
17130
- initial: { y: "100%" },
17131
- animate: { y: 0 },
17132
- exit: { y: "100%" },
17133
- transition: { type: "spring", stiffness: 320, damping: 36 },
17274
+ className: [
17275
+ "fixed bottom-0 left-0 right-0 z-[10000] bg-card border-t border-border/50 shadow-2xl flex flex-col",
17276
+ snap === "full" ? "rounded-t-[10px]" : "rounded-t-2xl"
17277
+ ].join(" "),
17278
+ style: {
17279
+ height: sheetHeight,
17280
+ touchAction: "none",
17281
+ overscrollBehavior: "none",
17282
+ boxShadow: snap === "full" ? "0 -8px 40px 0 rgba(0,0,0,0.32), 0 -1px 0 0 hsl(var(--border))" : void 0
17283
+ },
17284
+ drag: "y",
17285
+ dragConstraints: { top: 0, bottom: 0 },
17286
+ dragElastic: { top: 0.05, bottom: 0.25 },
17287
+ dragMomentum: false,
17288
+ onDragEnd: handleDragEnd,
17289
+ exit: { height: 0, opacity: 0, transition: { duration: 0.25 } },
17134
17290
  onClick: (e) => e.stopPropagation(),
17135
17291
  children: [
17136
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center pt-2.5 pb-1 shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-10 h-1 rounded-full bg-border" }) }),
17292
+ snap !== "full" && /* @__PURE__ */ jsxRuntime.jsx(
17293
+ "div",
17294
+ {
17295
+ className: "flex justify-center pt-3 pb-1 shrink-0 touch-none",
17296
+ style: { touchAction: "none" },
17297
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-10 h-1 rounded-full bg-muted-foreground/30" })
17298
+ }
17299
+ ),
17300
+ snap === "full" && /* @__PURE__ */ jsxRuntime.jsx(
17301
+ "div",
17302
+ {
17303
+ className: "flex items-center justify-between px-4 pt-3 pb-2 shrink-0 touch-none",
17304
+ style: { touchAction: "none" },
17305
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-10 h-1 rounded-full bg-muted-foreground/30 mx-auto" })
17306
+ }
17307
+ ),
17137
17308
  header,
17138
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-h-0 overflow-y-auto [&::-webkit-scrollbar]:w-1 [&::-webkit-scrollbar-track]:bg-transparent [&::-webkit-scrollbar-thumb]:bg-muted-foreground/20 [&::-webkit-scrollbar-thumb]:rounded-full hover:[&::-webkit-scrollbar-thumb]:bg-muted-foreground/40 transition-colors", children: /* @__PURE__ */ jsxRuntime.jsx(Body, { ...bodyProps }) })
17309
+ /* @__PURE__ */ jsxRuntime.jsx(Body, { ...bodyProps })
17139
17310
  ]
17140
17311
  },
17141
17312
  `sheet-${id}`