@mlw-packages/react-components 1.10.18 → 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.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import './index.css';
2
2
  import * as React32 from 'react';
3
- import React32__default, { forwardRef, useState, useEffect, createContext, useRef, useCallback, memo, useMemo, useId, useContext, useLayoutEffect } from 'react';
3
+ import React32__default, { forwardRef, useState, useEffect, createContext, memo, useMemo, useRef, useCallback, useId, useContext, useLayoutEffect } from 'react';
4
4
  import { Slot } from '@radix-ui/react-slot';
5
5
  import { cva } from 'class-variance-authority';
6
6
  import { clsx } from 'clsx';
@@ -2548,10 +2548,10 @@ function Badge({
2548
2548
  purple: "bg-purple-50 text-purple-500 border-purple-200"
2549
2549
  };
2550
2550
  const rankClasses = {
2551
- diamond: "bg-cyan-100 text-cyan-600 border-cyan-300",
2552
- gold: "bg-yellow-100 text-yellow-500 border-yellow-300",
2553
- silver: "bg-gray-100 text-gray-500 border-gray-300",
2554
- bronze: "bg-orange-100 text-orange-700 border-orange-300"
2551
+ diamond: "bg-cyan-100 text-cyan-600 border-cyan-300 dark:text-cyan-800 dark:border-cyan-800",
2552
+ gold: "bg-amber-50 text-amber-500 border-amber-300 dark:text-amber-600 dark:border-amber-600 dark:bg-amber-50",
2553
+ silver: "bg-gray-100 text-gray-500 border-gray-300 dark:text-gray-800 dark:border-gray-800",
2554
+ bronze: "bg-orange-100 text-orange-700 border-orange-300 dark:text-orange-800 dark:border-orange-800"
2555
2555
  };
2556
2556
  return /* @__PURE__ */ jsx(
2557
2557
  Comp,
@@ -3816,7 +3816,7 @@ var FileUploader = React32.forwardRef(
3816
3816
  showPreview = true,
3817
3817
  dropzoneText = "Arraste arquivos aqui ou clique para selecionar",
3818
3818
  dropzoneSubtext,
3819
- animate: animate2 = true,
3819
+ animate: animate3 = true,
3820
3820
  ...props
3821
3821
  }, ref) => {
3822
3822
  const [isDragging, setIsDragging] = React32.useState(false);
@@ -3969,7 +3969,7 @@ var FileUploader = React32.forwardRef(
3969
3969
  motion.p,
3970
3970
  {
3971
3971
  className: "mb-2 text-xs font-semibold text-foreground",
3972
- initial: animate2 ? { opacity: 0, y: -10 } : false,
3972
+ initial: animate3 ? { opacity: 0, y: -10 } : false,
3973
3973
  animate: { opacity: 1, y: 0 },
3974
3974
  transition: { delay: 0.1 },
3975
3975
  children: dropzoneText
@@ -3979,7 +3979,7 @@ var FileUploader = React32.forwardRef(
3979
3979
  motion.p,
3980
3980
  {
3981
3981
  className: "text-xs text-muted-foreground",
3982
- initial: animate2 ? { opacity: 0, y: -10 } : false,
3982
+ initial: animate3 ? { opacity: 0, y: -10 } : false,
3983
3983
  animate: { opacity: 1, y: 0 },
3984
3984
  transition: { delay: 0.2 },
3985
3985
  children: defaultSubtext
@@ -3989,7 +3989,7 @@ var FileUploader = React32.forwardRef(
3989
3989
  motion.div,
3990
3990
  {
3991
3991
  className: "py-2 w-full",
3992
- initial: animate2 ? { opacity: 0, y: 10 } : false,
3992
+ initial: animate3 ? { opacity: 0, y: 10 } : false,
3993
3993
  animate: { opacity: 1, y: 0 },
3994
3994
  transition: { delay: 0.3 },
3995
3995
  children: [
@@ -4004,7 +4004,7 @@ var FileUploader = React32.forwardRef(
4004
4004
  motion.div,
4005
4005
  {
4006
4006
  layout: true,
4007
- initial: animate2 ? { opacity: 0, x: -20 } : false,
4007
+ initial: animate3 ? { opacity: 0, x: -20 } : false,
4008
4008
  animate: { opacity: 1, x: 0 },
4009
4009
  exit: {
4010
4010
  opacity: 0,
@@ -4012,7 +4012,7 @@ var FileUploader = React32.forwardRef(
4012
4012
  transition: { duration: 0.2 }
4013
4013
  },
4014
4014
  transition: {
4015
- delay: animate2 ? index * 0.05 : 0,
4015
+ delay: animate3 ? index * 0.05 : 0,
4016
4016
  layout: { duration: 0.2 }
4017
4017
  },
4018
4018
  className: cn(
@@ -10134,28 +10134,37 @@ function EventAgenda({
10134
10134
  initialDate,
10135
10135
  onClick,
10136
10136
  showYearView = false,
10137
- noTime = false
10137
+ noTime = false,
10138
+ onlyDay,
10139
+ onlyMonth,
10140
+ onlyWeek,
10141
+ onlyAgenda,
10142
+ onlyYear
10138
10143
  }) {
10144
+ const lockedView = onlyDay ? "day" : onlyMonth ? "month" : onlyWeek ? "week" : onlyAgenda ? "agenda" : onlyYear ? "year" : void 0;
10139
10145
  const [currentDate, setCurrentDate] = useState(
10140
10146
  initialDate && new Date(initialDate) || /* @__PURE__ */ new Date()
10141
10147
  );
10142
- const [view, setView] = useState(initialView);
10148
+ const [view, setView] = useState(
10149
+ lockedView || initialView
10150
+ );
10143
10151
  const [selectedEvent, setSelectedEvent] = useState(null);
10152
+ const activeView = lockedView || view;
10144
10153
  const goPrevious = () => {
10145
- if (view === "month") setCurrentDate((d) => subMonths(d, 1));
10146
- else if (view === "week") setCurrentDate((d) => subWeeks(d, 1));
10147
- else if (view === "day") setCurrentDate((d) => addDays(d, -1));
10148
- else if (view === "agenda")
10154
+ if (activeView === "month") setCurrentDate((d) => subMonths(d, 1));
10155
+ else if (activeView === "week") setCurrentDate((d) => subWeeks(d, 1));
10156
+ else if (activeView === "day") setCurrentDate((d) => addDays(d, -1));
10157
+ else if (activeView === "agenda")
10149
10158
  setCurrentDate((d) => addDays(d, -AgendaDaysToShowAgenda));
10150
- else if (view === "year") setCurrentDate((d) => subYears(d, 1));
10159
+ else if (activeView === "year") setCurrentDate((d) => subYears(d, 1));
10151
10160
  };
10152
10161
  const goNext = () => {
10153
- if (view === "month") setCurrentDate((d) => addMonths(d, 1));
10154
- else if (view === "week") setCurrentDate((d) => addWeeks(d, 1));
10155
- else if (view === "day") setCurrentDate((d) => addDays(d, 1));
10156
- else if (view === "agenda")
10162
+ if (activeView === "month") setCurrentDate((d) => addMonths(d, 1));
10163
+ else if (activeView === "week") setCurrentDate((d) => addWeeks(d, 1));
10164
+ else if (activeView === "day") setCurrentDate((d) => addDays(d, 1));
10165
+ else if (activeView === "agenda")
10157
10166
  setCurrentDate((d) => addDays(d, AgendaDaysToShowAgenda));
10158
- else if (view === "year") setCurrentDate((d) => addYears(d, 1));
10167
+ else if (activeView === "year") setCurrentDate((d) => addYears(d, 1));
10159
10168
  };
10160
10169
  const handleEventSelect = (event, e) => {
10161
10170
  try {
@@ -10201,9 +10210,9 @@ function EventAgenda({
10201
10210
  };
10202
10211
  const viewTitle = useMemo(() => {
10203
10212
  const capitalize2 = (s) => s ? s.charAt(0).toUpperCase() + s.slice(1) : s;
10204
- if (view === "month")
10213
+ if (activeView === "month")
10205
10214
  return capitalize2(format(currentDate, "MMMM yyyy", { locale: ptBR }));
10206
- if (view === "week") {
10215
+ if (activeView === "week") {
10207
10216
  const start = startOfWeek(currentDate, { weekStartsOn: 1 });
10208
10217
  const end = endOfWeek(currentDate, { weekStartsOn: 1 });
10209
10218
  if (isSameMonth(start, end))
@@ -10212,17 +10221,19 @@ function EventAgenda({
10212
10221
  const s2 = capitalize2(format(end, "MMM yyyy", { locale: ptBR }));
10213
10222
  return `${s1} - ${s2}`;
10214
10223
  }
10215
- if (view === "day")
10216
- return format(currentDate, "d 'de' MMMM 'de' yyyy", { locale: ptBR });
10217
- if (view === "agenda") {
10224
+ if (activeView === "day")
10225
+ return capitalize2(
10226
+ format(currentDate, "EEEE, d 'de' MMMM", { locale: ptBR })
10227
+ );
10228
+ if (activeView === "agenda") {
10218
10229
  const start = currentDate;
10219
10230
  return capitalize2(format(start, "MMMM yyyy", { locale: ptBR }));
10220
10231
  }
10221
- if (view === "year") {
10232
+ if (activeView === "year") {
10222
10233
  return format(currentDate, "yyyy");
10223
10234
  }
10224
10235
  return capitalize2(format(currentDate, "MMMM yyyy", { locale: ptBR }));
10225
- }, [currentDate, view]);
10236
+ }, [currentDate, activeView]);
10226
10237
  const availableViews = showYearView ? ["year", "month", "week", "day", "agenda"] : ["month", "week", "day", "agenda"];
10227
10238
  const selectItems = availableViews.map(
10228
10239
  (v) => ({
@@ -10270,22 +10281,22 @@ function EventAgenda({
10270
10281
  ] }),
10271
10282
  /* @__PURE__ */ jsx("h2", { className: "font-semibold text-sm sm:text-base md:text-lg lg:text-xl xl:text-2xl min-w-0 truncate sm:whitespace-normal", children: viewTitle })
10272
10283
  ] }),
10273
- /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsx(
10284
+ !lockedView && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsx(
10274
10285
  Select,
10275
10286
  {
10276
- selected: view,
10287
+ selected: activeView,
10277
10288
  onChange: (v) => {
10278
10289
  setView(v);
10279
10290
  },
10280
10291
  items: selectItems,
10281
- placeholder: viewLabel(view),
10292
+ placeholder: viewLabel(activeView),
10282
10293
  className: "min-w-24",
10283
10294
  hideClear: true
10284
10295
  }
10285
10296
  ) })
10286
10297
  ] }),
10287
10298
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col transition-all duration-200 ease-in-out", children: [
10288
- view === "month" && /* @__PURE__ */ jsx(
10299
+ activeView === "month" && /* @__PURE__ */ jsx(
10289
10300
  MonthViewAgenda,
10290
10301
  {
10291
10302
  currentDate,
@@ -10294,7 +10305,7 @@ function EventAgenda({
10294
10305
  noTime
10295
10306
  }
10296
10307
  ),
10297
- view === "week" && /* @__PURE__ */ jsx(
10308
+ activeView === "week" && /* @__PURE__ */ jsx(
10298
10309
  WeekViewAgenda,
10299
10310
  {
10300
10311
  currentDate,
@@ -10303,7 +10314,7 @@ function EventAgenda({
10303
10314
  noTime
10304
10315
  }
10305
10316
  ),
10306
- view === "day" && /* @__PURE__ */ jsx(
10317
+ activeView === "day" && /* @__PURE__ */ jsx(
10307
10318
  DayViewAgenda,
10308
10319
  {
10309
10320
  currentDate,
@@ -10312,7 +10323,7 @@ function EventAgenda({
10312
10323
  noTime
10313
10324
  }
10314
10325
  ),
10315
- view === "agenda" && /* @__PURE__ */ jsx(
10326
+ activeView === "agenda" && /* @__PURE__ */ jsx(
10316
10327
  Agenda,
10317
10328
  {
10318
10329
  currentDate,
@@ -10321,14 +10332,16 @@ function EventAgenda({
10321
10332
  noTime
10322
10333
  }
10323
10334
  ),
10324
- view === "year" && /* @__PURE__ */ jsx(
10335
+ activeView === "year" && /* @__PURE__ */ jsx(
10325
10336
  YearViewAgenda,
10326
10337
  {
10327
10338
  currentDate,
10328
10339
  events,
10329
10340
  onMonthSelect: (monthDate) => {
10330
10341
  setCurrentDate(monthDate);
10331
- setView("month");
10342
+ if (!lockedView) {
10343
+ setView("month");
10344
+ }
10332
10345
  }
10333
10346
  }
10334
10347
  )
@@ -16570,6 +16583,13 @@ var useIsTruncated = (ref) => {
16570
16583
  }, [ref]);
16571
16584
  return truncated;
16572
16585
  };
16586
+ var SNAP_HEIGHTS = {
16587
+ collapsed: "80px",
16588
+ peek: "42dvh",
16589
+ full: "85dvh"
16590
+ };
16591
+ var VELOCITY_THRESHOLD = 500;
16592
+ var CLOSE_THRESHOLD = 50;
16573
16593
  var CopyData = ({ value }) => {
16574
16594
  const [copied, setCopied] = useState(false);
16575
16595
  const handleCopy = useCallback(() => {
@@ -16603,26 +16623,56 @@ var propertyLabels = {
16603
16623
  Destino: "Destino",
16604
16624
  Origem: "Origem"
16605
16625
  };
16606
- var IntegrationCard = ({ title, details }) => {
16626
+ var LongPressTooltip = ({ content, isMobile, children }) => {
16627
+ const [open, setOpen] = useState(false);
16628
+ const timerRef = useRef(null);
16629
+ const handleTouchStart = useCallback(() => {
16630
+ timerRef.current = setTimeout(() => setOpen(true), 1e3);
16631
+ }, []);
16632
+ const handleTouchEnd = useCallback(() => {
16633
+ if (timerRef.current) clearTimeout(timerRef.current);
16634
+ setTimeout(() => setOpen(false), 1500);
16635
+ }, []);
16636
+ useEffect(
16637
+ () => () => {
16638
+ if (timerRef.current) clearTimeout(timerRef.current);
16639
+ },
16640
+ []
16641
+ );
16642
+ return /* @__PURE__ */ jsx(TooltipProviderBase, { children: /* @__PURE__ */ jsxs(
16643
+ TooltipBase,
16644
+ {
16645
+ open: isMobile ? open : void 0,
16646
+ onOpenChange: isMobile ? setOpen : void 0,
16647
+ children: [
16648
+ /* @__PURE__ */ jsx(TooltipTriggerBase, { asChild: true, children: isMobile ? React32__default.cloneElement(children, {
16649
+ onTouchStart: handleTouchStart,
16650
+ onTouchEnd: handleTouchEnd,
16651
+ onTouchCancel: handleTouchEnd
16652
+ }) : children }),
16653
+ /* @__PURE__ */ jsx(TooltipContentBase, { sideOffset: 6, className: "z-[10001]", children: content })
16654
+ ]
16655
+ }
16656
+ ) });
16657
+ };
16658
+ var IntegrationCard = ({ title, details, isMobile }) => {
16607
16659
  const titleRef = useRef(null);
16608
16660
  const isTitleTruncated = useIsTruncated(titleRef);
16609
16661
  const blackList = ["id", "elementId", "identity"];
16610
16662
  const entries = details ? Object.entries(details).filter(
16611
16663
  ([key, value]) => value !== void 0 && value !== null && value !== "" && !blackList.includes(key)
16612
16664
  ) : [];
16665
+ const titleSpan = /* @__PURE__ */ jsx(
16666
+ "span",
16667
+ {
16668
+ ref: titleRef,
16669
+ className: "text-sm font-bold text-foreground truncate flex-1 min-w-0 cursor-default",
16670
+ children: title
16671
+ }
16672
+ );
16613
16673
  return /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-border/40 bg-muted/20 overflow-hidden", children: [
16614
16674
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-3 py-2 border-b border-border/30", children: [
16615
- /* @__PURE__ */ jsx(TooltipProviderBase, { children: /* @__PURE__ */ jsxs(TooltipBase, { children: [
16616
- /* @__PURE__ */ jsx(TooltipTriggerBase, { asChild: true, children: /* @__PURE__ */ jsx(
16617
- "span",
16618
- {
16619
- ref: titleRef,
16620
- className: "text-sm font-bold text-foreground truncate flex-1 min-w-0 cursor-default",
16621
- children: title
16622
- }
16623
- ) }),
16624
- isTitleTruncated && /* @__PURE__ */ jsx(TooltipContentBase, { sideOffset: 6, className: "z-[10001]", children: title })
16625
- ] }) }),
16675
+ isTitleTruncated ? /* @__PURE__ */ jsx(LongPressTooltip, { content: title, isMobile, children: titleSpan }) : titleSpan,
16626
16676
  entries.length > 0 && /* @__PURE__ */ jsx(
16627
16677
  CopyData,
16628
16678
  {
@@ -16642,69 +16692,59 @@ var IntegrationCard = ({ title, details }) => {
16642
16692
  }) })
16643
16693
  ] });
16644
16694
  };
16645
- var Name = ({
16646
- name,
16647
- description
16648
- }) => {
16695
+ var Name = ({ name, description, isMobile }) => {
16649
16696
  const nameRef = useRef(null);
16650
16697
  const descRef = useRef(null);
16651
16698
  const isNameTruncated = useIsTruncated(nameRef);
16652
16699
  const isDescTruncated = useIsTruncated(descRef);
16653
16700
  const showTooltip = isNameTruncated || isDescTruncated;
16654
- return /* @__PURE__ */ jsx(TooltipProviderBase, { children: /* @__PURE__ */ jsxs(TooltipBase, { children: [
16655
- /* @__PURE__ */ jsx(TooltipTriggerBase, { asChild: true, children: /* @__PURE__ */ jsxs("div", { className: "cursor-default min-w-0", children: [
16656
- /* @__PURE__ */ jsx(
16657
- "h3",
16658
- {
16659
- ref: nameRef,
16660
- className: "text-xl font-bold text-foreground tracking-tight truncate",
16661
- children: name
16662
- }
16663
- ),
16664
- description && /* @__PURE__ */ jsx(
16665
- "p",
16666
- {
16667
- ref: descRef,
16668
- className: "text-xs text-foreground/70 truncate mt-0.5",
16669
- children: description
16670
- }
16671
- )
16672
- ] }) }),
16673
- showTooltip && /* @__PURE__ */ jsxs(TooltipContentBase, { sideOffset: 8, className: "z-[10001]", children: [
16674
- /* @__PURE__ */ jsx("p", { className: "font-semibold", children: name }),
16675
- description && /* @__PURE__ */ jsx("p", { className: "text-xs text-foreground/70 mt-0.5", children: description })
16676
- ] })
16677
- ] }) });
16701
+ const content = /* @__PURE__ */ jsxs("div", { className: "cursor-default min-w-0", children: [
16702
+ /* @__PURE__ */ jsx(
16703
+ "h3",
16704
+ {
16705
+ ref: nameRef,
16706
+ className: "text-xl font-bold text-foreground tracking-tight truncate",
16707
+ children: name
16708
+ }
16709
+ ),
16710
+ description && /* @__PURE__ */ jsx("p", { ref: descRef, className: "text-xs text-foreground/70 truncate mt-0.5", children: description })
16711
+ ] });
16712
+ if (!showTooltip) return content;
16713
+ return /* @__PURE__ */ jsx(
16714
+ LongPressTooltip,
16715
+ {
16716
+ content: /* @__PURE__ */ jsxs(Fragment, { children: [
16717
+ /* @__PURE__ */ jsx("p", { className: "font-semibold", children: name }),
16718
+ description && /* @__PURE__ */ jsx("p", { className: "text-xs text-foreground/70 mt-0.5", children: description })
16719
+ ] }),
16720
+ isMobile,
16721
+ children: content
16722
+ }
16723
+ );
16678
16724
  };
16679
- var SystemNode = React32__default.forwardRef(
16680
- ({ label }, ref) => {
16681
- const innerRef = useRef(null);
16682
- const truncated = label.length > 9 ? label.substring(0, 9) + "\u2026" : label;
16683
- const needsTooltip = label.length > 9;
16684
- const setRefs = useCallback(
16685
- (node) => {
16686
- innerRef.current = node;
16687
- if (typeof ref === "function") ref(node);
16688
- else if (ref)
16689
- ref.current = node;
16690
- },
16691
- [ref]
16692
- );
16693
- const circle = /* @__PURE__ */ jsx(
16725
+ function SystemNodeInner({ label, isMobile }, ref) {
16726
+ const truncated = label.length > 9 ? label.substring(0, 9) + "\u2026" : label;
16727
+ const needsTooltip = label.length > 9;
16728
+ if (!needsTooltip) {
16729
+ return /* @__PURE__ */ jsx(
16694
16730
  "div",
16695
16731
  {
16696
- ref: setRefs,
16732
+ ref,
16697
16733
  className: "w-[76px] h-[76px] rounded-full bg-primary flex items-center justify-center shrink-0 z-10 cursor-default",
16698
16734
  children: /* @__PURE__ */ jsx("span", { className: "text-[10px] font-bold text-primary-foreground text-center px-2 leading-tight select-none", children: truncated })
16699
16735
  }
16700
16736
  );
16701
- if (!needsTooltip) return circle;
16702
- return /* @__PURE__ */ jsx(TooltipProviderBase, { children: /* @__PURE__ */ jsxs(TooltipBase, { children: [
16703
- /* @__PURE__ */ jsx(TooltipTriggerBase, { asChild: true, children: circle }),
16704
- /* @__PURE__ */ jsx(TooltipContentBase, { sideOffset: 8, className: "z-[10001]", children: label })
16705
- ] }) });
16706
16737
  }
16707
- );
16738
+ return /* @__PURE__ */ jsx(LongPressTooltip, { content: label, isMobile, children: /* @__PURE__ */ jsx(
16739
+ "div",
16740
+ {
16741
+ ref,
16742
+ className: "w-[76px] h-[76px] rounded-full bg-primary flex items-center justify-center shrink-0 z-10 cursor-default",
16743
+ children: /* @__PURE__ */ jsx("span", { className: "text-[10px] font-bold text-primary-foreground text-center px-2 leading-tight select-none", children: truncated })
16744
+ }
16745
+ ) });
16746
+ }
16747
+ var SystemNode = React32__default.forwardRef(SystemNodeInner);
16708
16748
  SystemNode.displayName = "SystemNode";
16709
16749
  var Beam = ({ isInput, containerRef, leftRef, rightRef }) => {
16710
16750
  const gradientId = useId();
@@ -16712,6 +16752,7 @@ var Beam = ({ isInput, containerRef, leftRef, rightRef }) => {
16712
16752
  const [svgSize, setSvgSize] = useState({ w: 0, h: 0 });
16713
16753
  useEffect(() => {
16714
16754
  let rafId;
16755
+ let running = true;
16715
16756
  const update = () => {
16716
16757
  const container = containerRef.current;
16717
16758
  const left = leftRef.current;
@@ -16724,39 +16765,31 @@ var Beam = ({ isInput, containerRef, leftRef, rightRef }) => {
16724
16765
  const cy1 = lr.top - cr.top + lr.height / 2;
16725
16766
  const cx2 = rr.left - cr.left + rr.width / 2;
16726
16767
  const cy2 = rr.top - cr.top + rr.height / 2;
16727
- const dx = cx2 - cx1, dy = cy2 - cy1;
16768
+ const dx = cx2 - cx1;
16769
+ const dy = cy2 - cy1;
16728
16770
  const dist = Math.sqrt(dx * dx + dy * dy);
16729
16771
  if (dist === 0) return;
16730
- const ux = dx / dist, uy = dy / dist;
16772
+ const ux = dx / dist;
16773
+ const uy = dy / dist;
16731
16774
  const r1 = lr.width / 2;
16732
16775
  const r2 = rr.width / 2;
16733
- setSvgSize({ w: cr.width, h: cr.height });
16734
- setPathD(
16735
- `M ${cx1 + ux * r1},${cy1 + uy * r1} L ${cx2 - ux * r2},${cy2 - uy * r2}`
16776
+ const newW = cr.width;
16777
+ const newH = cr.height;
16778
+ const newPath = `M ${cx1 + ux * r1},${cy1 + uy * r1} L ${cx2 - ux * r2},${cy2 - uy * r2}`;
16779
+ setSvgSize(
16780
+ (prev) => prev.w !== newW || prev.h !== newH ? { w: newW, h: newH } : prev
16736
16781
  );
16782
+ setPathD((prev) => prev !== newPath ? newPath : prev);
16737
16783
  };
16738
- const schedule = () => {
16739
- cancelAnimationFrame(rafId);
16740
- rafId = requestAnimationFrame(update);
16784
+ const loop = () => {
16785
+ if (!running) return;
16786
+ update();
16787
+ rafId = requestAnimationFrame(loop);
16741
16788
  };
16742
- requestAnimationFrame(() => requestAnimationFrame(update));
16743
- schedule();
16744
- const ro = new ResizeObserver(schedule);
16745
- if (containerRef.current) ro.observe(containerRef.current);
16746
- if (leftRef.current) ro.observe(leftRef.current);
16747
- if (rightRef.current) ro.observe(rightRef.current);
16748
- const mo = new MutationObserver(schedule);
16749
- if (containerRef.current) {
16750
- mo.observe(containerRef.current, {
16751
- attributes: true,
16752
- attributeFilter: ["class", "style"],
16753
- subtree: true
16754
- });
16755
- }
16789
+ rafId = requestAnimationFrame(loop);
16756
16790
  return () => {
16791
+ running = false;
16757
16792
  cancelAnimationFrame(rafId);
16758
- ro.disconnect();
16759
- mo.disconnect();
16760
16793
  };
16761
16794
  }, [containerRef, leftRef, rightRef]);
16762
16795
  const animX1 = isInput ? ["90%", "-10%"] : ["10%", "110%"];
@@ -16822,7 +16855,7 @@ var Beam = ({ isInput, containerRef, leftRef, rightRef }) => {
16822
16855
  }
16823
16856
  );
16824
16857
  };
16825
- var SystemsDiagram = ({ isInput, currentSystem, externalSystem }) => {
16858
+ var SystemsDiagram = ({ isInput, currentSystem, externalSystem, isMobile }) => {
16826
16859
  const containerRef = useRef(null);
16827
16860
  const leftRef = useRef(null);
16828
16861
  const rightRef = useRef(null);
@@ -16836,14 +16869,16 @@ var SystemsDiagram = ({ isInput, currentSystem, externalSystem }) => {
16836
16869
  SystemNode,
16837
16870
  {
16838
16871
  ref: leftRef,
16839
- label: isInput ? externalSystem : currentSystem
16872
+ label: isInput ? externalSystem : currentSystem,
16873
+ isMobile
16840
16874
  }
16841
16875
  ),
16842
16876
  /* @__PURE__ */ jsx(
16843
16877
  SystemNode,
16844
16878
  {
16845
16879
  ref: rightRef,
16846
- label: isInput ? currentSystem : externalSystem
16880
+ label: isInput ? currentSystem : externalSystem,
16881
+ isMobile
16847
16882
  }
16848
16883
  ),
16849
16884
  /* @__PURE__ */ jsx(
@@ -16859,47 +16894,84 @@ var SystemsDiagram = ({ isInput, currentSystem, externalSystem }) => {
16859
16894
  }
16860
16895
  );
16861
16896
  };
16862
- var BodyComponent = ({ data, isLoading, connections, isInput, externalSystem }) => /* @__PURE__ */ 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: [
16863
- isLoading ? /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
16864
- /* @__PURE__ */ jsx(SkeletonBase, { className: "h-6 w-3/4" }),
16865
- /* @__PURE__ */ jsx(SkeletonBase, { className: "h-3.5 w-1/2" })
16866
- ] }) : /* @__PURE__ */ jsx(Name, { name: data.name, description: data.description }),
16867
- isLoading ? /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
16868
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between py-1", children: [
16869
- /* @__PURE__ */ jsx(SkeletonBase, { className: "w-[76px] h-[76px] rounded-full" }),
16870
- /* @__PURE__ */ jsx(SkeletonBase, { className: "w-[76px] h-[76px] rounded-full" })
16871
- ] }),
16872
- /* @__PURE__ */ jsx("div", { className: "border-t border-border/20" }),
16873
- [1, 2].map((i) => /* @__PURE__ */ jsxs(
16874
- "div",
16875
- {
16876
- className: "rounded-lg border border-border/20 overflow-hidden",
16877
- children: [
16878
- /* @__PURE__ */ jsx(SkeletonBase, { className: "h-8 w-full" }),
16879
- [1, 2, 3].map((j) => /* @__PURE__ */ jsx(SkeletonBase, { className: "h-7 w-full mt-px" }, j))
16880
- ]
16897
+ var BodyComponent = ({
16898
+ data,
16899
+ isLoading,
16900
+ connections,
16901
+ isInput,
16902
+ externalSystem,
16903
+ isMobile,
16904
+ scrollable
16905
+ }) => /* @__PURE__ */ jsxs("div", { className: "relative min-h-0 flex-1 overflow-hidden", children: [
16906
+ /* @__PURE__ */ 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" }),
16907
+ /* @__PURE__ */ jsxs(
16908
+ "div",
16909
+ {
16910
+ className: [
16911
+ "px-3 py-3 space-y-3",
16912
+ 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",
16913
+ isMobile ? "max-h-[calc(85dvh-80px)]" : "max-h [&::-webkit-scrollbar]:hidden"
16914
+ ].join(" "),
16915
+ onPointerDownCapture: (e) => {
16916
+ if (scrollable) e.stopPropagation();
16881
16917
  },
16882
- i
16883
- ))
16884
- ] }) : connections.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground text-center", children: "Nenhuma conex\xE3o encontrada" }) : /* @__PURE__ */ jsxs(Fragment, { children: [
16885
- /* @__PURE__ */ jsx(
16886
- SystemsDiagram,
16887
- {
16888
- isInput,
16889
- currentSystem: data.name,
16890
- externalSystem
16891
- }
16892
- ),
16893
- /* @__PURE__ */ jsx("div", { className: "flex items-center", children: /* @__PURE__ */ 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" }) }),
16894
- /* @__PURE__ */ jsx("div", { children: connections.map((conn) => /* @__PURE__ */ jsx(
16895
- IntegrationCard,
16896
- {
16897
- title: conn.name,
16898
- details: conn.integration
16918
+ onTouchStartCapture: (e) => {
16919
+ if (scrollable) e.stopPropagation();
16899
16920
  },
16900
- conn.id
16901
- )) })
16902
- ] })
16921
+ children: [
16922
+ isLoading ? /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
16923
+ /* @__PURE__ */ jsx(SkeletonBase, { className: "h-6 w-3/4" }),
16924
+ /* @__PURE__ */ jsx(SkeletonBase, { className: "h-3.5 w-1/2" })
16925
+ ] }) : /* @__PURE__ */ jsx(
16926
+ Name,
16927
+ {
16928
+ name: data.name,
16929
+ description: data.description,
16930
+ isMobile
16931
+ }
16932
+ ),
16933
+ isLoading ? /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
16934
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between py-1", children: [
16935
+ /* @__PURE__ */ jsx(SkeletonBase, { className: "w-[76px] h-[76px] rounded-full" }),
16936
+ /* @__PURE__ */ jsx(SkeletonBase, { className: "w-[76px] h-[76px] rounded-full" })
16937
+ ] }),
16938
+ /* @__PURE__ */ jsx("div", { className: "border-t border-border/20" }),
16939
+ [1, 2].map((i) => /* @__PURE__ */ jsxs(
16940
+ "div",
16941
+ {
16942
+ className: "rounded-lg border border-border/20 overflow-hidden",
16943
+ children: [
16944
+ /* @__PURE__ */ jsx(SkeletonBase, { className: "h-8 w-full" }),
16945
+ [1, 2, 3].map((j) => /* @__PURE__ */ jsx(SkeletonBase, { className: "h-7 w-full mt-px" }, j))
16946
+ ]
16947
+ },
16948
+ i
16949
+ ))
16950
+ ] }) : connections.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground text-center", children: "Nenhuma conex\xE3o encontrada" }) : /* @__PURE__ */ jsxs(Fragment, { children: [
16951
+ /* @__PURE__ */ jsx(
16952
+ SystemsDiagram,
16953
+ {
16954
+ isInput,
16955
+ currentSystem: data.name,
16956
+ externalSystem,
16957
+ isMobile
16958
+ }
16959
+ ),
16960
+ /* @__PURE__ */ jsx("div", { className: "flex items-center", children: /* @__PURE__ */ 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" }) }),
16961
+ /* @__PURE__ */ jsx("div", { className: "space-y-2", children: connections.map((conn) => /* @__PURE__ */ jsx(
16962
+ IntegrationCard,
16963
+ {
16964
+ title: conn.name,
16965
+ details: conn.integration,
16966
+ isMobile
16967
+ },
16968
+ conn.id
16969
+ )) })
16970
+ ] })
16971
+ ]
16972
+ }
16973
+ ),
16974
+ /* @__PURE__ */ 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" })
16903
16975
  ] });
16904
16976
  var Body = React32__default.memo(BodyComponent);
16905
16977
  var modalVariants = {
@@ -16919,6 +16991,25 @@ var modalVariants = {
16919
16991
  transition: { type: "spring", stiffness: 400, damping: 28 }
16920
16992
  }
16921
16993
  };
16994
+ function resolveSnapPx(snap) {
16995
+ const vh = typeof window !== "undefined" ? window.innerHeight : 800;
16996
+ if (snap === "collapsed") return 80;
16997
+ if (snap === "peek") return vh * 0.42;
16998
+ return vh * 0.85;
16999
+ }
17000
+ function nearestSnap(heightPx) {
17001
+ const snaps = ["collapsed", "peek", "full"];
17002
+ let best = "peek";
17003
+ let bestDist = Infinity;
17004
+ for (const s of snaps) {
17005
+ const dist = Math.abs(resolveSnapPx(s) - heightPx);
17006
+ if (dist < bestDist) {
17007
+ bestDist = dist;
17008
+ best = s;
17009
+ }
17010
+ }
17011
+ return best;
17012
+ }
16922
17013
  var IntegrationModal = ({
16923
17014
  id,
16924
17015
  data,
@@ -17013,6 +17104,66 @@ var IntegrationModal = ({
17013
17104
  },
17014
17105
  [id, onMouseDown]
17015
17106
  );
17107
+ const [snap, setSnap] = useState("peek");
17108
+ const sheetHeight = useMotionValue(SNAP_HEIGHTS.peek);
17109
+ const snapTo = useCallback(
17110
+ (target) => {
17111
+ setSnap(target);
17112
+ animate(sheetHeight, SNAP_HEIGHTS[target], {
17113
+ type: "spring",
17114
+ stiffness: 320,
17115
+ damping: 36
17116
+ });
17117
+ },
17118
+ [sheetHeight]
17119
+ );
17120
+ useEffect(() => {
17121
+ if (isMobile) {
17122
+ sheetHeight.set("0px");
17123
+ animate(sheetHeight, SNAP_HEIGHTS.peek, {
17124
+ type: "spring",
17125
+ stiffness: 320,
17126
+ damping: 36
17127
+ });
17128
+ }
17129
+ }, [isMobile, sheetHeight]);
17130
+ const handleDragEnd = useCallback(
17131
+ (_, info) => {
17132
+ const vy = info.velocity.y;
17133
+ const dy = info.offset.y;
17134
+ const currentHeightStr = sheetHeight.get();
17135
+ const currentHeightPx = typeof currentHeightStr === "string" && currentHeightStr.endsWith("dvh") ? parseFloat(currentHeightStr) / 100 * window.innerHeight : parseFloat(currentHeightStr);
17136
+ const draggedHeightPx = currentHeightPx - dy;
17137
+ const collapsedPx = resolveSnapPx("collapsed");
17138
+ if (draggedHeightPx < collapsedPx - CLOSE_THRESHOLD || snap === "collapsed" && vy > VELOCITY_THRESHOLD) {
17139
+ onClose(id);
17140
+ return;
17141
+ }
17142
+ if (vy < -VELOCITY_THRESHOLD) {
17143
+ if (snap === "collapsed") {
17144
+ snapTo("peek");
17145
+ return;
17146
+ }
17147
+ if (snap === "peek") {
17148
+ snapTo("full");
17149
+ return;
17150
+ }
17151
+ }
17152
+ if (vy > VELOCITY_THRESHOLD) {
17153
+ if (snap === "full") {
17154
+ snapTo("peek");
17155
+ return;
17156
+ }
17157
+ if (snap === "peek") {
17158
+ snapTo("collapsed");
17159
+ return;
17160
+ }
17161
+ }
17162
+ const nearest = nearestSnap(draggedHeightPx);
17163
+ snapTo(nearest);
17164
+ },
17165
+ [id, onClose, snap, snapTo, sheetHeight]
17166
+ );
17016
17167
  const inputConnections = useMemo(
17017
17168
  () => data.connections.filter((c) => c.type === "entrada"),
17018
17169
  [data.connections]
@@ -17027,19 +17178,19 @@ var IntegrationModal = ({
17027
17178
  const header = /* @__PURE__ */ jsxs(
17028
17179
  "div",
17029
17180
  {
17030
- className: "flex items-center justify-between py-1 border-b border-border shrink-0 max-w-lg",
17031
- onMouseDown: handleMouseDownLocal,
17032
- onTouchStart: handleTouchStartLocal,
17181
+ className: "flex items-center justify-between py-1 border-b border-border shrink-0",
17182
+ onMouseDown: !isMobile ? handleMouseDownLocal : void 0,
17183
+ onTouchStart: !isMobile ? handleTouchStartLocal : void 0,
17033
17184
  style: {
17034
- touchAction: "none",
17035
- cursor: dragging ? "grabbing" : "grab"
17185
+ touchAction: isMobile ? "auto" : "none",
17186
+ cursor: isMobile ? "default" : dragging ? "grabbing" : "grab"
17036
17187
  },
17037
17188
  children: [
17038
17189
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-3", children: [
17039
- /* @__PURE__ */ jsx(DotsSixVerticalIcon, { size: 16, className: "text-primary" }),
17190
+ !isMobile && /* @__PURE__ */ jsx(DotsSixVerticalIcon, { size: 16, className: "text-primary" }),
17040
17191
  /* @__PURE__ */ jsx("span", { className: "text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: title })
17041
17192
  ] }),
17042
- /* @__PURE__ */ jsx(
17193
+ !isMobile && /* @__PURE__ */ jsx(
17043
17194
  ButtonBase,
17044
17195
  {
17045
17196
  variant: "ghost",
@@ -17053,7 +17204,15 @@ var IntegrationModal = ({
17053
17204
  ]
17054
17205
  }
17055
17206
  );
17056
- const bodyProps = { data, isLoading, connections, isInput, externalSystem };
17207
+ const bodyProps = {
17208
+ data,
17209
+ isLoading,
17210
+ connections,
17211
+ isInput,
17212
+ externalSystem,
17213
+ isMobile,
17214
+ scrollable: isMobile ? snap === "full" : true
17215
+ };
17057
17216
  if (isMobile) {
17058
17217
  return /* @__PURE__ */ jsx(AnimatePresence, { children: /* @__PURE__ */ jsxs(Fragment, { children: [
17059
17218
  /* @__PURE__ */ jsx(
@@ -17070,17 +17229,42 @@ var IntegrationModal = ({
17070
17229
  /* @__PURE__ */ jsxs(
17071
17230
  motion.div,
17072
17231
  {
17073
- 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",
17074
- style: { maxHeight: "85dvh" },
17075
- initial: { y: "100%" },
17076
- animate: { y: 0 },
17077
- exit: { y: "100%" },
17078
- transition: { type: "spring", stiffness: 320, damping: 36 },
17232
+ className: [
17233
+ "fixed bottom-0 left-0 right-0 z-[10000] bg-card border-t border-border/50 shadow-2xl flex flex-col",
17234
+ snap === "full" ? "rounded-t-[10px]" : "rounded-t-2xl"
17235
+ ].join(" "),
17236
+ style: {
17237
+ height: sheetHeight,
17238
+ touchAction: "none",
17239
+ overscrollBehavior: "none",
17240
+ boxShadow: snap === "full" ? "0 -8px 40px 0 rgba(0,0,0,0.32), 0 -1px 0 0 hsl(var(--border))" : void 0
17241
+ },
17242
+ drag: "y",
17243
+ dragConstraints: { top: 0, bottom: 0 },
17244
+ dragElastic: { top: 0.05, bottom: 0.25 },
17245
+ dragMomentum: false,
17246
+ onDragEnd: handleDragEnd,
17247
+ exit: { height: 0, opacity: 0, transition: { duration: 0.25 } },
17079
17248
  onClick: (e) => e.stopPropagation(),
17080
17249
  children: [
17081
- /* @__PURE__ */ jsx("div", { className: "flex justify-center pt-2.5 pb-1 shrink-0", children: /* @__PURE__ */ jsx("div", { className: "w-10 h-1 rounded-full bg-border" }) }),
17250
+ snap !== "full" && /* @__PURE__ */ jsx(
17251
+ "div",
17252
+ {
17253
+ className: "flex justify-center pt-3 pb-1 shrink-0 touch-none",
17254
+ style: { touchAction: "none" },
17255
+ children: /* @__PURE__ */ jsx("div", { className: "w-10 h-1 rounded-full bg-muted-foreground/30" })
17256
+ }
17257
+ ),
17258
+ snap === "full" && /* @__PURE__ */ jsx(
17259
+ "div",
17260
+ {
17261
+ className: "flex items-center justify-between px-4 pt-3 pb-2 shrink-0 touch-none",
17262
+ style: { touchAction: "none" },
17263
+ children: /* @__PURE__ */ jsx("div", { className: "w-10 h-1 rounded-full bg-muted-foreground/30 mx-auto" })
17264
+ }
17265
+ ),
17082
17266
  header,
17083
- /* @__PURE__ */ 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__ */ jsx(Body, { ...bodyProps }) })
17267
+ /* @__PURE__ */ jsx(Body, { ...bodyProps })
17084
17268
  ]
17085
17269
  },
17086
17270
  `sheet-${id}`