@rendra-ui/web 2.7.0 → 2.8.0
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/README.md +14 -14
- package/dist/base.css +1 -1
- package/dist/{brand-feedback-icon-BYNcqBel.js → brand-feedback-icon-CVux4pNh.js} +3 -3
- package/dist/{brand-feedback-icon-BYNcqBel.js.map → brand-feedback-icon-CVux4pNh.js.map} +1 -1
- package/dist/{button-DlzWwpZk.js → button-CrSlVIsY.js} +6 -6
- package/dist/{button-DlzWwpZk.js.map → button-CrSlVIsY.js.map} +1 -1
- package/dist/chart.js +7 -7
- package/dist/cli/auditar.js +1 -1
- package/dist/cli/codigos.js +2 -2
- package/dist/cli/executar-auditar.js +1 -1
- package/dist/cli/help.js +1 -1
- package/dist/cli/trocar.js +2 -2
- package/dist/cli/typescript-loader.js +1 -1
- package/dist/{cn-B0N3Pek0.js → cn-BlJHpkDs.js} +2 -2
- package/dist/{cn-B0N3Pek0.js.map → cn-BlJHpkDs.js.map} +1 -1
- package/dist/{components-CpQPMGfT.js → components-6RpoJ2Od.js} +4 -4
- package/dist/components-6RpoJ2Od.js.map +1 -0
- package/dist/components.css +19 -1
- package/dist/document-viewer.js +4 -4
- package/dist/{dropdown-menu-M8vs0byD.js → dropdown-menu-BUGKtR6k.js} +5 -5
- package/dist/{dropdown-menu-M8vs0byD.js.map → dropdown-menu-BUGKtR6k.js.map} +1 -1
- package/dist/{empty-state-a47Kd_Ci.js → empty-state-i4e-LacG.js} +6 -6
- package/dist/{empty-state-a47Kd_Ci.js.map → empty-state-i4e-LacG.js.map} +1 -1
- package/dist/{features-max-ScxV8gb3.js → features-max-BCIy1Ic-.js} +1 -1
- package/dist/flow.js +7 -7
- package/dist/index.js +808 -229
- package/dist/index.js.map +1 -1
- package/dist/{motion-context-BUMPf0e9.js → motion-context-PJPj6X4g.js} +4 -4
- package/dist/{motion-context-BUMPf0e9.js.map → motion-context-PJPj6X4g.js.map} +1 -1
- package/dist/{motion-on-CNN6y8g-.js → motion-on-Bocf4Smc.js} +2 -2
- package/dist/{motion-on-CNN6y8g-.js.map → motion-on-Bocf4Smc.js.map} +1 -1
- package/dist/motion.js +2 -2
- package/dist/{rendra-provider-DEURIIL3.js → rendra-provider-Do_qWjJC.js} +3 -3
- package/dist/{rendra-provider-DEURIIL3.js.map → rendra-provider-Do_qWjJC.js.map} +1 -1
- package/dist/rich-text-editor.js +4 -4
- package/dist/router-bridge.js +2 -2
- package/dist/{timeline-BOh7gUdA.js → timeline-xrMHeV92.js} +10 -10
- package/dist/{timeline-BOh7gUdA.js.map → timeline-xrMHeV92.js.map} +1 -1
- package/dist/tokens.css +9 -1
- package/dist/{tooltip-Ym9S4h9_.js → tooltip-to0h6aPe.js} +5 -5
- package/dist/{tooltip-Ym9S4h9_.js.map → tooltip-to0h6aPe.js.map} +1 -1
- package/dist/types/components/ui/data-toolbar.d.ts +6 -1
- package/dist/types/components/ui/kanban.d.ts +75 -6
- package/dist/{use-breakpoint-En17oXKY.js → use-breakpoint-CM-yeDHJ.js} +2 -2
- package/dist/{use-breakpoint-En17oXKY.js.map → use-breakpoint-CM-yeDHJ.js.map} +1 -1
- package/dist/{use-motion-presets-D3ww1oJX.js → use-motion-presets-I4StrsCi.js} +3 -3
- package/dist/{use-motion-presets-D3ww1oJX.js.map → use-motion-presets-I4StrsCi.js.map} +1 -1
- package/dist/widget-grid.js +2 -2
- package/package.json +2 -1
- package/dist/components-CpQPMGfT.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
/*! Rendra Design System v2.
|
|
2
|
-
import { t as cn } from "./cn-
|
|
3
|
-
import { a as useMotionMode, c as getReducedMotion, i as useMotionLib, l as subscribeReducedMotion, n as useLayoutReady, o as useMotionOn, r as useMotionAdopted, u as usePrefersReducedMotion } from "./motion-context-
|
|
4
|
-
import { t as useMotionPresets } from "./use-motion-presets-
|
|
5
|
-
import { A as lookupCnpj, B as ActionBar, C as toE164, D as controlInput, E as controlFrame, F as CardHeader, H as useShell, I as CardTitle, L as InfoHint, M as CardContent, N as CardDescription, O as useLookup, P as CardFooter, R as Modal, S as toCents, T as controlAdornmentSpace, V as ShellContext, _ as internationalPhoneMask, a as Label, b as percentMask, c as fieldGridClass, d as Drawer, f as PickerPanel, g as formatCurrency, h as formatCents, i as Field, j as Card, k as lookupCep, l as gapClass, m as DEFAULT_DDI, n as useFillHeight, o as useFieldControl, p as Input, r as Select, s as alignClass, t as Timeline, u as justifyClass, v as masks, w as controlAdornmentButton, x as phoneCountries, y as parseLocaleNumber, z as Alert } from "./timeline-
|
|
6
|
-
import { a as catalogByComponent, c as findComponentsWithoutDefault, d as findPresetCollisions, f as getCatalogEntry, i as assertCatalogIntegrity, l as findDuplicateCodes, n as CATALOG_EXCLUDED_FILES, o as filesMissingCatalogEntry, p as resolveCatalogCode, r as COMPONENT_CODE_PATTERN, s as findComponentsWithMultipleDefaults, t as CATALOG, u as findInvalidFormatCodes } from "./components-
|
|
7
|
-
import { n as buttonVariants, r as Spinner, t as Button } from "./button-
|
|
8
|
-
import { a as DropdownMenuItem, c as DropdownMenuRadioItem, d as DropdownMenuSubContent, f as DropdownMenuSubTrigger, i as DropdownMenuGroup, l as DropdownMenuSeparator, n as DropdownMenuCheckboxItem, o as DropdownMenuLabel, p as DropdownMenuTrigger, r as DropdownMenuContent, s as DropdownMenuRadioGroup, t as DropdownMenu, u as DropdownMenuSub } from "./dropdown-menu-
|
|
9
|
-
import { i as BrandContext, n as feedbackLabels, r as useBrand, t as BrandFeedbackIcon } from "./brand-feedback-icon-
|
|
10
|
-
import { a as useRendraNavigate, i as useRendraLink, n as useCurrentPath, r as useRendraBreadcrumbs, t as RendraProvider } from "./rendra-provider-
|
|
11
|
-
import { n as useBreakpoint, t as breakpoints } from "./use-breakpoint-
|
|
12
|
-
import { t as EmptyState } from "./empty-state-
|
|
13
|
-
import { n as TooltipProvider, t as Tooltip } from "./tooltip-
|
|
14
|
-
import { ArrowDown, ArrowDownRight, ArrowLeft, ArrowRight, ArrowRightLeft, ArrowUp, ArrowUpRight, Bell, Bot, CalendarDays, Check, CheckCheck, ChevronDown, ChevronLeft, ChevronRight, ChevronsUpDown, Clock, Columns3, Download, EllipsisVertical, FileText, Film, Filter, Globe, GripVertical, Home, ImageIcon, ImagePlus, LayoutTemplate, LogOut, Mail, MapPin, Menu, MessageCircle, MessagesSquare, Mic, Minus, Monitor, Moon, MoreHorizontal, Palette, PanelLeft, Paperclip, Pause, Pencil, Phone, Play, Plus, Reply, RotateCw, Search, Send, Smartphone, Smile, Star, Sun, Trash2, TriangleAlert, UploadCloud, User, VideoIcon, X, Zap } from "lucide-react";
|
|
1
|
+
/*! Rendra Design System v2.8.0 | MIT | © 2026 Bruno Magalhaes | brunomagalhaes.me */
|
|
2
|
+
import { t as cn } from "./cn-BlJHpkDs.js";
|
|
3
|
+
import { a as useMotionMode, c as getReducedMotion, i as useMotionLib, l as subscribeReducedMotion, n as useLayoutReady, o as useMotionOn, r as useMotionAdopted, u as usePrefersReducedMotion } from "./motion-context-PJPj6X4g.js";
|
|
4
|
+
import { t as useMotionPresets } from "./use-motion-presets-I4StrsCi.js";
|
|
5
|
+
import { A as lookupCnpj, B as ActionBar, C as toE164, D as controlInput, E as controlFrame, F as CardHeader, H as useShell, I as CardTitle, L as InfoHint, M as CardContent, N as CardDescription, O as useLookup, P as CardFooter, R as Modal, S as toCents, T as controlAdornmentSpace, V as ShellContext, _ as internationalPhoneMask, a as Label, b as percentMask, c as fieldGridClass, d as Drawer, f as PickerPanel, g as formatCurrency, h as formatCents, i as Field, j as Card, k as lookupCep, l as gapClass, m as DEFAULT_DDI, n as useFillHeight, o as useFieldControl, p as Input, r as Select, s as alignClass, t as Timeline, u as justifyClass, v as masks, w as controlAdornmentButton, x as phoneCountries, y as parseLocaleNumber, z as Alert } from "./timeline-xrMHeV92.js";
|
|
6
|
+
import { a as catalogByComponent, c as findComponentsWithoutDefault, d as findPresetCollisions, f as getCatalogEntry, i as assertCatalogIntegrity, l as findDuplicateCodes, n as CATALOG_EXCLUDED_FILES, o as filesMissingCatalogEntry, p as resolveCatalogCode, r as COMPONENT_CODE_PATTERN, s as findComponentsWithMultipleDefaults, t as CATALOG, u as findInvalidFormatCodes } from "./components-6RpoJ2Od.js";
|
|
7
|
+
import { n as buttonVariants, r as Spinner, t as Button } from "./button-CrSlVIsY.js";
|
|
8
|
+
import { a as DropdownMenuItem, c as DropdownMenuRadioItem, d as DropdownMenuSubContent, f as DropdownMenuSubTrigger, i as DropdownMenuGroup, l as DropdownMenuSeparator, n as DropdownMenuCheckboxItem, o as DropdownMenuLabel, p as DropdownMenuTrigger, r as DropdownMenuContent, s as DropdownMenuRadioGroup, t as DropdownMenu, u as DropdownMenuSub } from "./dropdown-menu-BUGKtR6k.js";
|
|
9
|
+
import { i as BrandContext, n as feedbackLabels, r as useBrand, t as BrandFeedbackIcon } from "./brand-feedback-icon-CVux4pNh.js";
|
|
10
|
+
import { a as useRendraNavigate, i as useRendraLink, n as useCurrentPath, r as useRendraBreadcrumbs, t as RendraProvider } from "./rendra-provider-Do_qWjJC.js";
|
|
11
|
+
import { n as useBreakpoint, t as breakpoints } from "./use-breakpoint-CM-yeDHJ.js";
|
|
12
|
+
import { t as EmptyState } from "./empty-state-i4e-LacG.js";
|
|
13
|
+
import { n as TooltipProvider, t as Tooltip } from "./tooltip-to0h6aPe.js";
|
|
14
|
+
import { ArrowDown, ArrowDownRight, ArrowLeft, ArrowRight, ArrowRightLeft, ArrowUp, ArrowUpRight, Bell, Bot, CalendarClock, CalendarDays, CalendarX2, Check, CheckCheck, ChevronDown, ChevronLeft, ChevronRight, ChevronsUpDown, Clock, Columns3, Download, EllipsisVertical, FileText, Film, Filter, Globe, GripVertical, Home, ImageIcon, ImagePlus, LayoutTemplate, LogOut, Mail, MapPin, Menu, MessageCircle, MessagesSquare, Mic, Minus, Monitor, Moon, MoreHorizontal, Palette, PanelLeft, Paperclip, Pause, Pencil, Phone, Play, Plus, Reply, RotateCw, Search, Send, Settings2, Smartphone, Smile, Star, Sun, Trash2, TriangleAlert, UploadCloud, User, VideoIcon, X, Zap } from "lucide-react";
|
|
15
15
|
import { Accordion as Accordion$1, Avatar as Avatar$1, Checkbox as Checkbox$1, Collapsible, ContextMenu, Dialog, NavigationMenu, Popover as Popover$1, Progress as Progress$1, RadioGroup as RadioGroup$1, Slider as Slider$1, Slot, Switch as Switch$1, Tabs as Tabs$1, VisuallyHidden } from "radix-ui";
|
|
16
16
|
import { Fragment, createContext, forwardRef, useCallback, useContext, useEffect, useId, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
17
17
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
18
18
|
import { cva } from "class-variance-authority";
|
|
19
|
-
import { addDays, addMonths, addWeeks, differenceInMinutes, endOfMonth, endOfWeek, format, isSameDay, isSameMonth, isToday, isYesterday, startOfDay, startOfMonth, startOfWeek } from "date-fns";
|
|
19
|
+
import { addDays, addMonths, addWeeks, differenceInCalendarDays, differenceInMinutes, endOfMonth, endOfWeek, format, isSameDay, isSameMonth, isToday, isYesterday, startOfDay, startOfMonth, startOfWeek } from "date-fns";
|
|
20
20
|
import { ptBR } from "date-fns/locale";
|
|
21
21
|
import { DayPicker } from "react-day-picker";
|
|
22
22
|
import { ptBR as ptBR$1 } from "react-day-picker/locale";
|
|
@@ -2697,7 +2697,7 @@ function Switch({ checked, defaultChecked, onCheckedChange, label, description,
|
|
|
2697
2697
|
}
|
|
2698
2698
|
//#endregion
|
|
2699
2699
|
//#region src/components/ui/data-toolbar.tsx
|
|
2700
|
-
function DataToolbar({ search, filters, filterCount = 0, onClearFilters, chips = [], sort, columns, actions, primaryAction, selectionBar }) {
|
|
2700
|
+
function DataToolbar({ search, filters, filterCount = 0, onClearFilters, chips = [], sort, columns, actions, summary, primaryAction, selectionBar }) {
|
|
2701
2701
|
const { isMobile } = useBreakpoint();
|
|
2702
2702
|
const [drawer, setDrawer] = useState(false);
|
|
2703
2703
|
const hasPanel = Boolean(filters || sort || columns?.length);
|
|
@@ -2735,49 +2735,57 @@ function DataToolbar({ search, filters, filterCount = 0, onClearFilters, chips =
|
|
|
2735
2735
|
children: selectionBar
|
|
2736
2736
|
}) : /* @__PURE__ */ jsxs("div", {
|
|
2737
2737
|
className: "flex flex-col gap-3 md:flex-row md:items-center",
|
|
2738
|
-
children: [
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
children:
|
|
2775
|
-
})
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2738
|
+
children: [
|
|
2739
|
+
search && /* @__PURE__ */ jsx(Input, {
|
|
2740
|
+
icon: /* @__PURE__ */ jsx(Search, {}),
|
|
2741
|
+
clearable: true,
|
|
2742
|
+
value: search.value,
|
|
2743
|
+
onChange: search.onChange,
|
|
2744
|
+
placeholder: search.placeholder ?? "Buscar",
|
|
2745
|
+
"aria-label": search.placeholder ?? "Buscar",
|
|
2746
|
+
type: "search",
|
|
2747
|
+
className: "md:w-3xs lg:w-sm"
|
|
2748
|
+
}),
|
|
2749
|
+
summary && /* @__PURE__ */ jsx("div", {
|
|
2750
|
+
"data-toolbar-summary": true,
|
|
2751
|
+
className: "flex flex-col gap-1 text-sm",
|
|
2752
|
+
children: summary
|
|
2753
|
+
}),
|
|
2754
|
+
isMobile ? /* @__PURE__ */ jsxs(Fragment$1, { children: [(hasPanel || primaryAction) && /* @__PURE__ */ jsxs("div", {
|
|
2755
|
+
className: cn("grid gap-3", hasPanel && primaryAction ? "grid-actions-2" : "grid-cols-1"),
|
|
2756
|
+
children: [hasPanel && filterButton(() => setDrawer(true)), primaryAction]
|
|
2757
|
+
}), actions && /* @__PURE__ */ jsx("div", {
|
|
2758
|
+
className: "flex flex-wrap gap-3 *:flex-1",
|
|
2759
|
+
children: actions
|
|
2760
|
+
})] }) : /* @__PURE__ */ jsxs("div", {
|
|
2761
|
+
className: "flex flex-wrap items-center gap-2 md:ml-auto",
|
|
2762
|
+
children: [
|
|
2763
|
+
actions,
|
|
2764
|
+
columnsMenu,
|
|
2765
|
+
sort,
|
|
2766
|
+
filters && /* @__PURE__ */ jsxs(Popover, { children: [/* @__PURE__ */ jsx(PopoverTrigger, {
|
|
2767
|
+
asChild: true,
|
|
2768
|
+
children: filterButton()
|
|
2769
|
+
}), /* @__PURE__ */ jsxs(PopoverContent, {
|
|
2770
|
+
align: "end",
|
|
2771
|
+
className: "flex flex-col",
|
|
2772
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
2773
|
+
className: "max-h-command overflow-y-auto p-4",
|
|
2774
|
+
children: filters
|
|
2775
|
+
}), onClearFilters && filterCount > 0 && /* @__PURE__ */ jsx("div", {
|
|
2776
|
+
className: "border-t p-2",
|
|
2777
|
+
children: /* @__PURE__ */ jsx(Button, {
|
|
2778
|
+
variant: "ghost",
|
|
2779
|
+
size: "sm",
|
|
2780
|
+
onClick: onClearFilters,
|
|
2781
|
+
children: "Limpar filtros"
|
|
2782
|
+
})
|
|
2783
|
+
})]
|
|
2784
|
+
})] }),
|
|
2785
|
+
primaryAction
|
|
2786
|
+
]
|
|
2787
|
+
})
|
|
2788
|
+
]
|
|
2781
2789
|
}),
|
|
2782
2790
|
chips.length > 0 && /* @__PURE__ */ jsxs("div", {
|
|
2783
2791
|
className: "flex flex-wrap items-center gap-2",
|
|
@@ -3834,10 +3842,239 @@ var targetIconTone = {
|
|
|
3834
3842
|
info: "text-info",
|
|
3835
3843
|
outline: "text-foreground"
|
|
3836
3844
|
};
|
|
3837
|
-
|
|
3838
|
-
|
|
3845
|
+
/** Fundo claro de cada destino do rodapé flutuante, pela cor da ação. */
|
|
3846
|
+
var targetSoft = {
|
|
3847
|
+
neutral: "bg-muted",
|
|
3848
|
+
primary: "bg-primary-soft",
|
|
3849
|
+
success: "bg-success-soft",
|
|
3850
|
+
warning: "bg-warning-soft",
|
|
3851
|
+
error: "bg-destructive-soft",
|
|
3852
|
+
info: "bg-info-soft",
|
|
3853
|
+
outline: "bg-card"
|
|
3854
|
+
};
|
|
3855
|
+
/** Destino realçado (card por cima): fundo forte com o `-foreground` dele em tudo. */
|
|
3856
|
+
var targetStrong = {
|
|
3857
|
+
neutral: "bg-muted text-foreground",
|
|
3858
|
+
primary: "bg-primary text-primary-foreground",
|
|
3859
|
+
success: "bg-success text-success-foreground",
|
|
3860
|
+
warning: "bg-warning text-warning-foreground",
|
|
3861
|
+
error: "bg-destructive text-destructive-foreground",
|
|
3862
|
+
info: "bg-info text-info-foreground",
|
|
3863
|
+
outline: "bg-muted text-foreground"
|
|
3864
|
+
};
|
|
3865
|
+
/**
|
|
3866
|
+
* Situação do card a partir da próxima atividade e da cadência da etapa. Compara por dia de
|
|
3867
|
+
* calendário; `referenceDate` é o "hoje" (injetável para teste).
|
|
3868
|
+
*/
|
|
3869
|
+
function getKanbanCardStatus(card, column, referenceDate) {
|
|
3870
|
+
const daysInColumn = card.enteredColumnAt ? differenceInCalendarDays(referenceDate, card.enteredColumnAt) : null;
|
|
3871
|
+
const cadenceOverdue = column?.cadenceDays !== void 0 && daysInColumn !== null && daysInColumn > column.cadenceDays;
|
|
3872
|
+
const ahead = card.activity ? differenceInCalendarDays(card.activity.at, referenceDate) : null;
|
|
3873
|
+
const activity = ahead === null ? "none" : ahead < 0 ? "late" : ahead === 0 ? "today" : "onTime";
|
|
3874
|
+
return {
|
|
3875
|
+
background: cadenceOverdue && (activity === "late" || activity === "none") ? "critical" : cadenceOverdue ? "cadenceOverdue" : activity === "none" ? "noActivity" : "normal",
|
|
3876
|
+
activity,
|
|
3877
|
+
daysInColumn,
|
|
3878
|
+
daysLate: ahead !== null && ahead < 0 ? -ahead : 0
|
|
3879
|
+
};
|
|
3880
|
+
}
|
|
3881
|
+
/** Classes literais completas (nada de classe montada por string). */
|
|
3882
|
+
var statusBackground = {
|
|
3883
|
+
critical: "bg-critical-soft",
|
|
3884
|
+
cadenceOverdue: "bg-destructive-soft",
|
|
3885
|
+
noActivity: "bg-warning-soft",
|
|
3886
|
+
normal: "bg-card"
|
|
3887
|
+
};
|
|
3888
|
+
var activityIcon = {
|
|
3889
|
+
onTime: {
|
|
3890
|
+
icon: CalendarDays,
|
|
3891
|
+
circle: "bg-info-soft text-info-soft-foreground"
|
|
3892
|
+
},
|
|
3893
|
+
today: {
|
|
3894
|
+
icon: CalendarClock,
|
|
3895
|
+
circle: "bg-warning-mid text-warning-mid-foreground"
|
|
3896
|
+
},
|
|
3897
|
+
late: {
|
|
3898
|
+
icon: CalendarX2,
|
|
3899
|
+
circle: "bg-destructive text-destructive-foreground"
|
|
3900
|
+
},
|
|
3901
|
+
none: {
|
|
3902
|
+
icon: CalendarDays,
|
|
3903
|
+
circle: "border border-dashed border-muted-foreground text-muted-foreground"
|
|
3904
|
+
}
|
|
3905
|
+
};
|
|
3906
|
+
function plural(n, one, many) {
|
|
3907
|
+
return `${n} ${n === 1 ? one : many}`;
|
|
3908
|
+
}
|
|
3909
|
+
function situationText(status) {
|
|
3910
|
+
if (status.activity === "onTime") return "Em dia";
|
|
3911
|
+
if (status.activity === "today") return "Vence hoje";
|
|
3912
|
+
if (status.activity === "late") return `Atrasada há ${plural(status.daysLate, "dia", "dias")}`;
|
|
3913
|
+
return "Sem atividade agendada";
|
|
3914
|
+
}
|
|
3915
|
+
/** Texto para o leitor de tela: a cor do fundo nunca é a única informação. */
|
|
3916
|
+
function backgroundLabel(status) {
|
|
3917
|
+
if (status.background === "critical") return `Situação: crítico, cadência vencida e ${status.activity === "late" ? "atividade atrasada" : "sem próxima atividade"}`;
|
|
3918
|
+
if (status.background === "cadenceOverdue") return "Situação: cadência vencida";
|
|
3919
|
+
if (status.background === "noActivity") return "Situação: sem atividade";
|
|
3920
|
+
return null;
|
|
3921
|
+
}
|
|
3922
|
+
function whenText(at, status) {
|
|
3923
|
+
return status.activity === "today" ? `Hoje às ${format(at, "HH:mm")}` : `${format(at, "dd/MM/yyyy")} às ${format(at, "HH:mm")}`;
|
|
3924
|
+
}
|
|
3925
|
+
var baseFields = [
|
|
3926
|
+
{
|
|
3927
|
+
id: "tags",
|
|
3928
|
+
label: "Tags"
|
|
3929
|
+
},
|
|
3930
|
+
{
|
|
3931
|
+
id: "document",
|
|
3932
|
+
label: "CNPJ ou CPF"
|
|
3933
|
+
},
|
|
3934
|
+
{
|
|
3935
|
+
id: "description",
|
|
3936
|
+
label: "Descrição"
|
|
3937
|
+
},
|
|
3938
|
+
{
|
|
3939
|
+
id: "contact",
|
|
3940
|
+
label: "Contato"
|
|
3941
|
+
},
|
|
3942
|
+
{
|
|
3943
|
+
id: "phone",
|
|
3944
|
+
label: "Telefone"
|
|
3945
|
+
},
|
|
3946
|
+
{
|
|
3947
|
+
id: "email",
|
|
3948
|
+
label: "E-mail"
|
|
3949
|
+
},
|
|
3950
|
+
{
|
|
3951
|
+
id: "activity",
|
|
3952
|
+
label: "Atividade"
|
|
3953
|
+
},
|
|
3954
|
+
{
|
|
3955
|
+
id: "assignee",
|
|
3956
|
+
label: "Responsável"
|
|
3957
|
+
}
|
|
3958
|
+
];
|
|
3959
|
+
/** Lê os campos escondidos; qualquer falha do armazenamento cai no padrão (tudo visível). */
|
|
3960
|
+
function readHidden(storageKey) {
|
|
3961
|
+
if (!storageKey) return {};
|
|
3962
|
+
try {
|
|
3963
|
+
const raw = localStorage.getItem(storageKey);
|
|
3964
|
+
const list = raw ? JSON.parse(raw) : [];
|
|
3965
|
+
return Array.isArray(list) ? Object.fromEntries(list.filter((f) => typeof f === "string").map((f) => [f, true])) : {};
|
|
3966
|
+
} catch {
|
|
3967
|
+
return {};
|
|
3968
|
+
}
|
|
3969
|
+
}
|
|
3970
|
+
function writeHidden(storageKey, hidden) {
|
|
3971
|
+
if (!storageKey) return;
|
|
3972
|
+
try {
|
|
3973
|
+
localStorage.setItem(storageKey, JSON.stringify(Object.keys(hidden).filter((k) => hidden[k])));
|
|
3974
|
+
} catch {}
|
|
3975
|
+
}
|
|
3976
|
+
var HINT_CLOSE_DELAY = 150;
|
|
3977
|
+
/**
|
|
3978
|
+
* Calendário do card: ícone de situação, data ao lado e hint (tipo, quando, com quem,
|
|
3979
|
+
* responsável e situação). Abre por clique, toque, foco por teclado e mouse; o gatilho é um
|
|
3980
|
+
* botão fora do botão de clique do card.
|
|
3981
|
+
*/
|
|
3982
|
+
function ActivityHint({ card, status }) {
|
|
3983
|
+
const [open, setOpen] = useState(false);
|
|
3984
|
+
const pressed = useRef(false);
|
|
3985
|
+
const holding = useRef(false);
|
|
3986
|
+
const triggerRef = useRef(null);
|
|
3987
|
+
const lastPointer = useRef("");
|
|
3988
|
+
const timer = useRef(void 0);
|
|
3989
|
+
const { icon: Icon, circle } = activityIcon[status.activity];
|
|
3990
|
+
const activity = card.activity;
|
|
3991
|
+
const visible = activity ? status.activity === "today" ? `Hoje ${format(activity.at, "HH:mm")}` : format(activity.at, "dd/MM/yyyy") : "Sem atividade";
|
|
3992
|
+
const cancelClose = () => clearTimeout(timer.current);
|
|
3993
|
+
const scheduleClose = () => {
|
|
3994
|
+
cancelClose();
|
|
3995
|
+
timer.current = setTimeout(() => {
|
|
3996
|
+
if (!holding.current) setOpen(false);
|
|
3997
|
+
}, HINT_CLOSE_DELAY);
|
|
3998
|
+
};
|
|
3999
|
+
useEffect(() => cancelClose, []);
|
|
4000
|
+
return /* @__PURE__ */ jsxs(Popover, {
|
|
4001
|
+
open,
|
|
4002
|
+
onOpenChange: (next) => !next && !holding.current && setOpen(false),
|
|
4003
|
+
children: [/* @__PURE__ */ jsx(PopoverAnchor, {
|
|
4004
|
+
asChild: true,
|
|
4005
|
+
children: /* @__PURE__ */ jsxs("button", {
|
|
4006
|
+
ref: triggerRef,
|
|
4007
|
+
type: "button",
|
|
4008
|
+
"aria-haspopup": "dialog",
|
|
4009
|
+
"aria-expanded": open,
|
|
4010
|
+
"aria-label": `${visible}. ${situationText(status)}`,
|
|
4011
|
+
className: "relative z-10 -ml-1 inline-flex cursor-pointer items-center gap-1 rounded-item px-1 tabular-nums outline-none focus-visible:ring-2 focus-visible:ring-ring max-md:min-h-touch",
|
|
4012
|
+
onPointerDown: (e) => {
|
|
4013
|
+
cancelClose();
|
|
4014
|
+
pressed.current = true;
|
|
4015
|
+
holding.current = true;
|
|
4016
|
+
window.addEventListener("pointerup", () => holding.current = false, { once: true });
|
|
4017
|
+
window.addEventListener("pointercancel", () => holding.current = false, { once: true });
|
|
4018
|
+
lastPointer.current = e.pointerType;
|
|
4019
|
+
},
|
|
4020
|
+
onPointerEnter: (e) => {
|
|
4021
|
+
if (e.pointerType !== "mouse") return;
|
|
4022
|
+
cancelClose();
|
|
4023
|
+
setOpen(true);
|
|
4024
|
+
},
|
|
4025
|
+
onPointerLeave: (e) => e.pointerType === "mouse" && scheduleClose(),
|
|
4026
|
+
onFocus: () => {
|
|
4027
|
+
if (!pressed.current) setOpen(true);
|
|
4028
|
+
},
|
|
4029
|
+
onBlur: () => {
|
|
4030
|
+
pressed.current = false;
|
|
4031
|
+
if (!holding.current) setOpen(false);
|
|
4032
|
+
},
|
|
4033
|
+
onClick: (e) => {
|
|
4034
|
+
e.preventDefault();
|
|
4035
|
+
e.stopPropagation();
|
|
4036
|
+
pressed.current = false;
|
|
4037
|
+
const byMouse = lastPointer.current === "mouse";
|
|
4038
|
+
lastPointer.current = "";
|
|
4039
|
+
setOpen((o) => byMouse || !o);
|
|
4040
|
+
},
|
|
4041
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
4042
|
+
"aria-hidden": true,
|
|
4043
|
+
className: cn("flex size-6 shrink-0 items-center justify-center rounded-full", circle),
|
|
4044
|
+
children: /* @__PURE__ */ jsx(Icon, { className: "size-3" })
|
|
4045
|
+
}), visible]
|
|
4046
|
+
})
|
|
4047
|
+
}), /* @__PURE__ */ jsxs(PopoverContent, {
|
|
4048
|
+
width: "sm",
|
|
4049
|
+
align: "start",
|
|
4050
|
+
className: "flex flex-col gap-1 p-3 text-xs",
|
|
4051
|
+
onOpenAutoFocus: (e) => e.preventDefault(),
|
|
4052
|
+
onInteractOutside: (e) => {
|
|
4053
|
+
if (triggerRef.current?.contains(e.target)) e.preventDefault();
|
|
4054
|
+
},
|
|
4055
|
+
onPointerEnter: cancelClose,
|
|
4056
|
+
onPointerLeave: scheduleClose,
|
|
4057
|
+
children: [
|
|
4058
|
+
activity ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("p", {
|
|
4059
|
+
className: "text-sm font-medium",
|
|
4060
|
+
children: [
|
|
4061
|
+
activity.type,
|
|
4062
|
+
" · ",
|
|
4063
|
+
whenText(activity.at, status)
|
|
4064
|
+
]
|
|
4065
|
+
}), activity.with && /* @__PURE__ */ jsxs("p", { children: ["Com: ", activity.with] })] }) : null,
|
|
4066
|
+
card.assignee && /* @__PURE__ */ jsxs("p", { children: ["Responsável: ", card.assignee] }),
|
|
4067
|
+
/* @__PURE__ */ jsx("p", {
|
|
4068
|
+
className: "font-medium",
|
|
4069
|
+
children: situationText(status)
|
|
4070
|
+
})
|
|
4071
|
+
]
|
|
4072
|
+
})]
|
|
4073
|
+
});
|
|
4074
|
+
}
|
|
4075
|
+
function CardBody({ card, show, withHandle }) {
|
|
3839
4076
|
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
3840
|
-
card.tags && card.tags.length > 0 && /* @__PURE__ */ jsx("span", {
|
|
4077
|
+
show("tags") && card.tags && card.tags.length > 0 && /* @__PURE__ */ jsx("span", {
|
|
3841
4078
|
className: "flex flex-wrap gap-1",
|
|
3842
4079
|
children: card.tags.map((t) => /* @__PURE__ */ jsx(Badge, {
|
|
3843
4080
|
tone: t.tone ?? "neutral",
|
|
@@ -3849,19 +4086,19 @@ function CardBody({ card, valueFields = [], formatValue, withHandle }) {
|
|
|
3849
4086
|
children: [/* @__PURE__ */ jsx("span", {
|
|
3850
4087
|
className: "line-clamp-2 text-sm font-medium",
|
|
3851
4088
|
children: card.title
|
|
3852
|
-
}), card.subtitle && /* @__PURE__ */ jsx("span", {
|
|
4089
|
+
}), show("document") && card.subtitle && /* @__PURE__ */ jsx("span", {
|
|
3853
4090
|
className: "text-xs text-muted-foreground tabular-nums",
|
|
3854
4091
|
children: card.subtitle
|
|
3855
4092
|
})]
|
|
3856
4093
|
}),
|
|
3857
|
-
card.description && /* @__PURE__ */ jsx("span", {
|
|
4094
|
+
show("description") && card.description && /* @__PURE__ */ jsx("span", {
|
|
3858
4095
|
className: "line-clamp-2 text-xs text-muted-foreground",
|
|
3859
4096
|
children: card.description
|
|
3860
4097
|
}),
|
|
3861
4098
|
card.contact && /* @__PURE__ */ jsxs("span", {
|
|
3862
4099
|
className: "flex flex-col gap-1 text-xs text-muted-foreground",
|
|
3863
4100
|
children: [
|
|
3864
|
-
card.contact.name && /* @__PURE__ */ jsxs("span", {
|
|
4101
|
+
show("contact") && card.contact.name && /* @__PURE__ */ jsxs("span", {
|
|
3865
4102
|
className: "flex min-w-0 items-center gap-1 text-foreground",
|
|
3866
4103
|
children: [/* @__PURE__ */ jsx(User, {
|
|
3867
4104
|
className: "size-3 shrink-0",
|
|
@@ -3871,7 +4108,7 @@ function CardBody({ card, valueFields = [], formatValue, withHandle }) {
|
|
|
3871
4108
|
children: card.contact.name
|
|
3872
4109
|
})]
|
|
3873
4110
|
}),
|
|
3874
|
-
card.contact.phone && /* @__PURE__ */ jsxs("span", {
|
|
4111
|
+
show("phone") && card.contact.phone && /* @__PURE__ */ jsxs("span", {
|
|
3875
4112
|
className: "flex min-w-0 items-center gap-1 tabular-nums",
|
|
3876
4113
|
children: [/* @__PURE__ */ jsx(Phone, {
|
|
3877
4114
|
className: "size-3 shrink-0",
|
|
@@ -3881,7 +4118,7 @@ function CardBody({ card, valueFields = [], formatValue, withHandle }) {
|
|
|
3881
4118
|
children: card.contact.phone
|
|
3882
4119
|
})]
|
|
3883
4120
|
}),
|
|
3884
|
-
card.contact.email && /* @__PURE__ */ jsxs("span", {
|
|
4121
|
+
show("email") && card.contact.email && /* @__PURE__ */ jsxs("span", {
|
|
3885
4122
|
className: "flex min-w-0 items-center gap-1",
|
|
3886
4123
|
children: [/* @__PURE__ */ jsx(Mail, {
|
|
3887
4124
|
className: "size-3 shrink-0",
|
|
@@ -3892,50 +4129,96 @@ function CardBody({ card, valueFields = [], formatValue, withHandle }) {
|
|
|
3892
4129
|
})]
|
|
3893
4130
|
})
|
|
3894
4131
|
]
|
|
3895
|
-
}),
|
|
3896
|
-
shown.length > 0 && /* @__PURE__ */ jsx("span", {
|
|
3897
|
-
className: "grid grid-cols-2 divide-x rounded-block bg-muted text-xs",
|
|
3898
|
-
children: shown.map((f) => /* @__PURE__ */ jsxs("span", {
|
|
3899
|
-
className: "flex min-w-0 flex-col px-2 py-1",
|
|
3900
|
-
children: [/* @__PURE__ */ jsxs("span", {
|
|
3901
|
-
className: "text-muted-foreground",
|
|
3902
|
-
children: [f.label, ":"]
|
|
3903
|
-
}), /* @__PURE__ */ jsx("span", {
|
|
3904
|
-
className: "truncate font-semibold text-foreground tabular-nums",
|
|
3905
|
-
children: formatValue(card.values?.[f.key] ?? 0)
|
|
3906
|
-
})]
|
|
3907
|
-
}, f.key))
|
|
3908
|
-
}),
|
|
3909
|
-
(card.assignee || card.dueDate || card.meta) && /* @__PURE__ */ jsxs("span", {
|
|
3910
|
-
className: "flex items-center gap-2 border-t pt-2 text-xs text-muted-foreground",
|
|
3911
|
-
children: [
|
|
3912
|
-
card.dueDate && /* @__PURE__ */ jsxs("span", {
|
|
3913
|
-
className: "inline-flex items-center gap-1 tabular-nums",
|
|
3914
|
-
children: [/* @__PURE__ */ jsx(CalendarDays, {
|
|
3915
|
-
className: "size-3",
|
|
3916
|
-
"aria-hidden": true
|
|
3917
|
-
}), format(card.dueDate, "dd/MM/yyyy")]
|
|
3918
|
-
}),
|
|
3919
|
-
card.meta && /* @__PURE__ */ jsx("span", {
|
|
3920
|
-
className: "font-medium text-foreground tabular-nums",
|
|
3921
|
-
children: card.meta
|
|
3922
|
-
}),
|
|
3923
|
-
card.assignee && /* @__PURE__ */ jsx("span", {
|
|
3924
|
-
className: "ml-auto",
|
|
3925
|
-
title: card.assignee,
|
|
3926
|
-
children: /* @__PURE__ */ jsx(Avatar, {
|
|
3927
|
-
name: card.assignee,
|
|
3928
|
-
size: "sm"
|
|
3929
|
-
})
|
|
3930
|
-
})
|
|
3931
|
-
]
|
|
3932
4132
|
})
|
|
3933
4133
|
] });
|
|
3934
4134
|
}
|
|
4135
|
+
/**
|
|
4136
|
+
* Rodapé do card, fora do botão de clique: linha de calendário, meta e responsável e, depois
|
|
4137
|
+
* de uma divisória, os valores empilhados. Sem `renderCard` apenas.
|
|
4138
|
+
*/
|
|
4139
|
+
function cardFooter({ card, status, show, valueFields, formatValue }) {
|
|
4140
|
+
const calendar = show("activity") ? status ? /* @__PURE__ */ jsx(ActivityHint, {
|
|
4141
|
+
card,
|
|
4142
|
+
status
|
|
4143
|
+
}) : card.dueDate && /* @__PURE__ */ jsxs("span", {
|
|
4144
|
+
className: "inline-flex items-center gap-1 tabular-nums",
|
|
4145
|
+
children: [/* @__PURE__ */ jsx(CalendarDays, {
|
|
4146
|
+
className: "size-3",
|
|
4147
|
+
"aria-hidden": true
|
|
4148
|
+
}), format(card.dueDate, "dd/MM/yyyy")]
|
|
4149
|
+
}) : null;
|
|
4150
|
+
const assignee = show("assignee") ? card.assignee : void 0;
|
|
4151
|
+
const values = valueFields.slice(0, 2).filter((f) => show(`value:${f.key}`));
|
|
4152
|
+
const hasRow = Boolean(calendar || assignee || card.meta);
|
|
4153
|
+
if (!hasRow && values.length === 0) return null;
|
|
4154
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [hasRow && /* @__PURE__ */ jsxs("span", {
|
|
4155
|
+
className: "flex items-center gap-2 border-t pt-2 text-xs text-muted-foreground",
|
|
4156
|
+
children: [
|
|
4157
|
+
calendar,
|
|
4158
|
+
card.meta && /* @__PURE__ */ jsx("span", {
|
|
4159
|
+
className: "font-medium text-foreground tabular-nums",
|
|
4160
|
+
children: card.meta
|
|
4161
|
+
}),
|
|
4162
|
+
assignee && /* @__PURE__ */ jsx("span", {
|
|
4163
|
+
className: "ml-auto",
|
|
4164
|
+
title: assignee,
|
|
4165
|
+
children: /* @__PURE__ */ jsx(Avatar, {
|
|
4166
|
+
name: assignee,
|
|
4167
|
+
size: "sm"
|
|
4168
|
+
})
|
|
4169
|
+
})
|
|
4170
|
+
]
|
|
4171
|
+
}), values.length > 0 && /* @__PURE__ */ jsx("span", {
|
|
4172
|
+
className: "flex flex-col gap-1 border-t pt-2 text-xs",
|
|
4173
|
+
children: values.map((f) => /* @__PURE__ */ jsxs("span", {
|
|
4174
|
+
className: "flex items-baseline justify-between gap-2",
|
|
4175
|
+
children: [/* @__PURE__ */ jsxs("span", {
|
|
4176
|
+
className: "text-muted-foreground",
|
|
4177
|
+
children: [f.label, ":"]
|
|
4178
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
4179
|
+
className: "truncate font-semibold text-foreground tabular-nums",
|
|
4180
|
+
children: formatValue(card.values?.[f.key] ?? 0)
|
|
4181
|
+
})]
|
|
4182
|
+
}, f.key))
|
|
4183
|
+
})] });
|
|
4184
|
+
}
|
|
4185
|
+
/** Sem acento e sem diferença de maiúscula, para a busca. */
|
|
4186
|
+
function normalize(text) {
|
|
4187
|
+
const marks = new RegExp(`[${String.fromCharCode(768)}-${String.fromCharCode(879)}]`, "g");
|
|
4188
|
+
return text.normalize("NFD").replace(marks, "").toLowerCase();
|
|
4189
|
+
}
|
|
4190
|
+
/**
|
|
4191
|
+
* Posição, na lista completa da coluna, de um índice da lista desenhada (que pode ser só uma
|
|
4192
|
+
* parte dela, por busca, filtro ou paginação). Fim da lista desenhada = logo depois do último
|
|
4193
|
+
* card desenhado; sem card desenhado = fim da lista completa.
|
|
4194
|
+
*/
|
|
4195
|
+
function toFullIndex(full, drawn, drawnIndex) {
|
|
4196
|
+
if (drawn.length === 0) return full.length;
|
|
4197
|
+
if (drawnIndex < drawn.length) return full.indexOf(drawn[drawnIndex]);
|
|
4198
|
+
return full.indexOf(drawn[drawn.length - 1]) + 1;
|
|
4199
|
+
}
|
|
4200
|
+
var situationOptions = [
|
|
4201
|
+
{
|
|
4202
|
+
value: "critical",
|
|
4203
|
+
label: "Crítico"
|
|
4204
|
+
},
|
|
4205
|
+
{
|
|
4206
|
+
value: "cadenceOverdue",
|
|
4207
|
+
label: "Cadência vencida"
|
|
4208
|
+
},
|
|
4209
|
+
{
|
|
4210
|
+
value: "noActivity",
|
|
4211
|
+
label: "Sem atividade"
|
|
4212
|
+
},
|
|
4213
|
+
{
|
|
4214
|
+
value: "late",
|
|
4215
|
+
label: "Atividade atrasada"
|
|
4216
|
+
}
|
|
4217
|
+
];
|
|
3935
4218
|
function Kanban({ columns, cards, onCardMove, onCardClick, onAddCard, renderCard, valueFields, formatValue = (n) => n.toLocaleString("pt-BR", {
|
|
3936
4219
|
style: "currency",
|
|
3937
4220
|
currency: "BRL"
|
|
3938
|
-
}), pageSize = 20, visibleColumns = 5, onLoadMore, hasMore, dropTargets, onDropTarget, className, ...aria }) {
|
|
4221
|
+
}), pageSize = 20, visibleColumns = 5, onLoadMore, hasMore, dropTargets, onDropTarget, referenceDate, toolbar, onNewCard, storageKey, className, ...aria }) {
|
|
3939
4222
|
const code = resolveCatalogCode("Kanban", { hasDropTargets: Boolean(dropTargets?.length) });
|
|
3940
4223
|
const { isMobile } = useBreakpoint();
|
|
3941
4224
|
const motion = useMotionMode();
|
|
@@ -3960,18 +4243,66 @@ function Kanban({ columns, cards, onCardMove, onCardClick, onAddCard, renderCard
|
|
|
3960
4243
|
const [active, setActive] = useState(columns[0]?.id ?? "");
|
|
3961
4244
|
const [dragging, setDragging] = useState(null);
|
|
3962
4245
|
const [over, setOver] = useState(null);
|
|
4246
|
+
const [overTarget, setOverTarget] = useState(null);
|
|
3963
4247
|
const [touchDrag, setTouchDrag] = useState(null);
|
|
4248
|
+
const [pendingDrop, setPendingDrop] = useState(null);
|
|
4249
|
+
const [reason, setReason] = useState("");
|
|
4250
|
+
const [query, setQuery] = useState("");
|
|
4251
|
+
const [assigneeFilter, setAssigneeFilter] = useState(null);
|
|
4252
|
+
const [situationFilter, setSituationFilter] = useState(null);
|
|
4253
|
+
const [customizing, setCustomizing] = useState(false);
|
|
4254
|
+
const [hidden, setHidden] = useState(() => readHidden(storageKey));
|
|
4255
|
+
const changeHidden = (next) => {
|
|
4256
|
+
setHidden(next);
|
|
4257
|
+
writeHidden(storageKey, next);
|
|
4258
|
+
};
|
|
4259
|
+
const show = (field) => !hidden[field];
|
|
4260
|
+
const today = referenceDate ?? /* @__PURE__ */ new Date();
|
|
4261
|
+
const statusEnabled = columns.some((c) => c.cadenceDays !== void 0) || cards.some((c) => c.activity);
|
|
4262
|
+
const statusOf = (card) => statusEnabled ? getKanbanCardStatus(card, columns.find((c) => c.id === card.columnId), today) : null;
|
|
4263
|
+
const filtering = toolbar && (query.trim() !== "" || assigneeFilter || situationFilter);
|
|
4264
|
+
const matches = (card) => {
|
|
4265
|
+
const q = normalize(query.trim());
|
|
4266
|
+
if (q && ![
|
|
4267
|
+
card.title,
|
|
4268
|
+
card.subtitle,
|
|
4269
|
+
card.contact?.name
|
|
4270
|
+
].some((t) => t && normalize(t).includes(q))) return false;
|
|
4271
|
+
if (assigneeFilter && card.assignee !== assigneeFilter) return false;
|
|
4272
|
+
if (situationFilter) {
|
|
4273
|
+
const status = statusOf(card);
|
|
4274
|
+
if (!status) return false;
|
|
4275
|
+
if (situationFilter === "late" ? status.activity !== "late" : status.background !== situationFilter) return false;
|
|
4276
|
+
}
|
|
4277
|
+
return true;
|
|
4278
|
+
};
|
|
4279
|
+
const visibleCards = filtering ? cards.filter(matches) : cards;
|
|
4280
|
+
/** Lista completa da coluna: a única fonte do índice que sai em `onCardMove`. */
|
|
3964
4281
|
const inColumn = (id) => cards.filter((c) => c.columnId === id);
|
|
4282
|
+
/** Lista visível (busca e filtros): cards desenhados, contagem, totais, paginação e abas. */
|
|
4283
|
+
const visibleInColumn = (id) => visibleCards.filter((c) => c.columnId === id);
|
|
3965
4284
|
const drop = (columnId, index) => {
|
|
3966
|
-
if (dragging)
|
|
4285
|
+
if (dragging) {
|
|
4286
|
+
const drawn = visibleInColumn(columnId).slice(0, limitOf(columnId));
|
|
4287
|
+
onCardMove?.(dragging, columnId, toFullIndex(inColumn(columnId), drawn, index));
|
|
4288
|
+
}
|
|
3967
4289
|
setDragging(null);
|
|
3968
4290
|
setOver(null);
|
|
4291
|
+
setOverTarget(null);
|
|
3969
4292
|
};
|
|
3970
4293
|
const draggingCardId = dragging ?? touchDrag?.cardId ?? null;
|
|
3971
4294
|
const showTargetBar = Boolean(dropTargets?.length) && draggingCardId !== null;
|
|
3972
4295
|
const dropOnTarget = (cardId, targetId) => {
|
|
3973
4296
|
const target = dropTargets?.find((t) => t.id === targetId);
|
|
3974
4297
|
if (!target || target.disabled) return;
|
|
4298
|
+
if (target.confirm) {
|
|
4299
|
+
setReason(target.confirm.reasons?.[0]?.value ?? "");
|
|
4300
|
+
setPendingDrop({
|
|
4301
|
+
cardId,
|
|
4302
|
+
targetId
|
|
4303
|
+
});
|
|
4304
|
+
return;
|
|
4305
|
+
}
|
|
3975
4306
|
onDropTarget?.(cardId, targetId);
|
|
3976
4307
|
};
|
|
3977
4308
|
const startTouchDrag = (card, e) => {
|
|
@@ -4049,43 +4380,60 @@ function Kanban({ columns, cards, onCardMove, onCardClick, onAddCard, renderCard
|
|
|
4049
4380
|
]
|
|
4050
4381
|
})] });
|
|
4051
4382
|
};
|
|
4052
|
-
/**
|
|
4383
|
+
/** Rodapé flutuante de destinos, mostrado durante o arraste (mouse ou toque). */
|
|
4384
|
+
const highlightedTarget = overTarget ?? touchDrag?.overTargetId ?? null;
|
|
4053
4385
|
const targetBar = showTargetBar && /* @__PURE__ */ jsx("div", {
|
|
4054
4386
|
"aria-label": "Soltar em",
|
|
4055
|
-
className: "fixed inset-x-4 bottom-4 z-30
|
|
4056
|
-
children: dropTargets.map((t) =>
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
|
|
4071
|
-
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
}
|
|
4075
|
-
|
|
4076
|
-
|
|
4077
|
-
|
|
4078
|
-
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
}
|
|
4083
|
-
t.disabled
|
|
4084
|
-
|
|
4085
|
-
|
|
4086
|
-
|
|
4087
|
-
|
|
4088
|
-
|
|
4387
|
+
className: "fixed inset-x-4 bottom-4 z-30 grid grid-cols-2 gap-2 rounded-surface border bg-card p-2 shadow-lg md:flex md:justify-center md:overflow-x-auto",
|
|
4388
|
+
children: dropTargets.map((t) => {
|
|
4389
|
+
const tone = t.tone ?? "neutral";
|
|
4390
|
+
const highlighted = !t.disabled && highlightedTarget === t.id;
|
|
4391
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
4392
|
+
"data-kanban-target": t.id,
|
|
4393
|
+
"data-over": highlighted ? "true" : void 0,
|
|
4394
|
+
onDragEnter: () => {
|
|
4395
|
+
if (dragging && !t.disabled) setOverTarget(t.id);
|
|
4396
|
+
},
|
|
4397
|
+
onDragOver: (e) => {
|
|
4398
|
+
if (dragging && !t.disabled) {
|
|
4399
|
+
e.preventDefault();
|
|
4400
|
+
setOverTarget(t.id);
|
|
4401
|
+
}
|
|
4402
|
+
},
|
|
4403
|
+
onDragLeave: (e) => {
|
|
4404
|
+
if (e.relatedTarget instanceof Node && e.currentTarget.contains(e.relatedTarget)) return;
|
|
4405
|
+
setOverTarget((id) => id === t.id ? null : id);
|
|
4406
|
+
},
|
|
4407
|
+
onDrop: (e) => {
|
|
4408
|
+
e.preventDefault();
|
|
4409
|
+
setOverTarget(null);
|
|
4410
|
+
if (dragging) {
|
|
4411
|
+
dropOnTarget(dragging, t.id);
|
|
4412
|
+
setDragging(null);
|
|
4413
|
+
}
|
|
4414
|
+
},
|
|
4415
|
+
className: cn("flex min-w-24 flex-col items-center gap-1 rounded-block border p-2 text-center text-xs transition-colors", t.disabled ? "cursor-not-allowed bg-muted opacity-50" : highlighted ? cn(targetStrong[tone], "ring-2 ring-ring") : targetSoft[tone]),
|
|
4416
|
+
children: [
|
|
4417
|
+
t.icon && /* @__PURE__ */ jsx("span", {
|
|
4418
|
+
"aria-hidden": true,
|
|
4419
|
+
className: highlighted ? void 0 : targetIconTone[tone],
|
|
4420
|
+
children: t.icon
|
|
4421
|
+
}),
|
|
4422
|
+
/* @__PURE__ */ jsx("span", {
|
|
4423
|
+
className: "font-medium",
|
|
4424
|
+
children: t.label
|
|
4425
|
+
}),
|
|
4426
|
+
t.hint && !t.disabled && /* @__PURE__ */ jsx("span", {
|
|
4427
|
+
className: highlighted ? void 0 : "text-muted-foreground",
|
|
4428
|
+
children: t.hint
|
|
4429
|
+
}),
|
|
4430
|
+
t.disabled && t.disabledReason && /* @__PURE__ */ jsx("span", {
|
|
4431
|
+
className: "text-muted-foreground",
|
|
4432
|
+
children: t.disabledReason
|
|
4433
|
+
})
|
|
4434
|
+
]
|
|
4435
|
+
}, t.id);
|
|
4436
|
+
})
|
|
4089
4437
|
});
|
|
4090
4438
|
const canTouchDrag = Boolean(onCardMove) || Boolean(dropTargets?.length && onDropTarget);
|
|
4091
4439
|
const showHandle = isMobile && canTouchDrag;
|
|
@@ -4099,7 +4447,10 @@ function Kanban({ columns, cards, onCardMove, onCardClick, onAddCard, renderCard
|
|
|
4099
4447
|
const dragEnd = () => {
|
|
4100
4448
|
setDragging(null);
|
|
4101
4449
|
setOver(null);
|
|
4450
|
+
setOverTarget(null);
|
|
4102
4451
|
};
|
|
4452
|
+
const status = statusOf(card);
|
|
4453
|
+
const label = status && backgroundLabel(status);
|
|
4103
4454
|
const common = {
|
|
4104
4455
|
"data-kanban-card": card.id,
|
|
4105
4456
|
draggable: !isMobile && Boolean(onCardMove),
|
|
@@ -4119,27 +4470,37 @@ function Kanban({ columns, cards, onCardMove, onCardClick, onAddCard, renderCard
|
|
|
4119
4470
|
e.stopPropagation();
|
|
4120
4471
|
if (over) drop(over.column, over.index);
|
|
4121
4472
|
},
|
|
4122
|
-
className: cn("relative flex rounded-block border bg-card p-3 shadow-sm transition-[box-shadow,opacity]", !isMobile && onCardMove && "cursor-grab active:cursor-grabbing", (dragging === card.id || touchDrag?.cardId === card.id) && "opacity-50", over?.column === card.columnId && over.index === index && dragging !== card.id && "ring-2 ring-ring ring-offset-2 ring-offset-muted")
|
|
4473
|
+
className: cn("relative flex rounded-block border", status ? statusBackground[status.background] : "bg-card", "p-3 shadow-sm transition-[box-shadow,opacity]", !isMobile && onCardMove && "cursor-grab active:cursor-grabbing", (dragging === card.id || touchDrag?.cardId === card.id) && "opacity-50", over?.column === card.columnId && over.index === index && dragging !== card.id && "ring-2 ring-ring ring-offset-2 ring-offset-muted")
|
|
4123
4474
|
};
|
|
4475
|
+
const content = renderCard ? renderCard(card) : /* @__PURE__ */ jsx(CardBody, {
|
|
4476
|
+
card,
|
|
4477
|
+
show,
|
|
4478
|
+
withHandle: showHandle
|
|
4479
|
+
});
|
|
4480
|
+
const footer = renderCard ? null : cardFooter({
|
|
4481
|
+
card,
|
|
4482
|
+
status,
|
|
4483
|
+
show,
|
|
4484
|
+
valueFields: valueFields ?? [],
|
|
4485
|
+
formatValue
|
|
4486
|
+
});
|
|
4487
|
+
const main = onCardClick ? /* @__PURE__ */ jsx("button", {
|
|
4488
|
+
type: "button",
|
|
4489
|
+
onClick: () => onCardClick(card),
|
|
4490
|
+
className: footer ? "flex min-w-0 cursor-pointer flex-col gap-2 rounded-block text-left outline-none after:absolute after:inset-0 focus-visible:ring-2 focus-visible:ring-ring" : "flex min-w-0 flex-1 cursor-pointer flex-col gap-2 rounded-block text-left outline-none after:absolute after:inset-0 focus-visible:ring-2 focus-visible:ring-ring",
|
|
4491
|
+
children: content
|
|
4492
|
+
}) : /* @__PURE__ */ jsx("div", {
|
|
4493
|
+
className: footer ? "flex min-w-0 flex-col gap-2" : "flex min-w-0 flex-1 flex-col gap-2",
|
|
4494
|
+
children: content
|
|
4495
|
+
});
|
|
4124
4496
|
const body = /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
4125
|
-
|
|
4126
|
-
type: "button",
|
|
4127
|
-
onClick: () => onCardClick(card),
|
|
4128
|
-
className: "flex min-w-0 flex-1 cursor-pointer flex-col gap-2 rounded-block text-left outline-none after:absolute after:inset-0 focus-visible:ring-2 focus-visible:ring-ring",
|
|
4129
|
-
children: renderCard ? renderCard(card) : /* @__PURE__ */ jsx(CardBody, {
|
|
4130
|
-
card,
|
|
4131
|
-
valueFields,
|
|
4132
|
-
formatValue,
|
|
4133
|
-
withHandle: showHandle
|
|
4134
|
-
})
|
|
4135
|
-
}) : /* @__PURE__ */ jsx("div", {
|
|
4497
|
+
footer ? /* @__PURE__ */ jsxs("div", {
|
|
4136
4498
|
className: "flex min-w-0 flex-1 flex-col gap-2",
|
|
4137
|
-
children:
|
|
4138
|
-
|
|
4139
|
-
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
})
|
|
4499
|
+
children: [main, footer]
|
|
4500
|
+
}) : main,
|
|
4501
|
+
label && /* @__PURE__ */ jsx("span", {
|
|
4502
|
+
className: "sr-only",
|
|
4503
|
+
children: label
|
|
4143
4504
|
}),
|
|
4144
4505
|
showHandle && /* @__PURE__ */ jsx("button", {
|
|
4145
4506
|
type: "button",
|
|
@@ -4187,53 +4548,79 @@ function Kanban({ columns, cards, onCardMove, onCardClick, onAddCard, renderCard
|
|
|
4187
4548
|
children: body
|
|
4188
4549
|
}, card.id);
|
|
4189
4550
|
};
|
|
4190
|
-
const
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4551
|
+
const totalFields = (valueFields ?? []).slice(0, 2);
|
|
4552
|
+
const sumOf = (list, key) => list.reduce((sum, c) => sum + (c.values?.[key] ?? 0), 0);
|
|
4553
|
+
const boardCards = visibleCards.filter((c) => columns.some((col) => col.id === c.columnId));
|
|
4554
|
+
const totals = (col) => totalFields.map((f) => {
|
|
4555
|
+
const total = sumOf(visibleInColumn(col.id), f.key);
|
|
4556
|
+
const board = sumOf(boardCards, f.key);
|
|
4557
|
+
return {
|
|
4558
|
+
...f,
|
|
4559
|
+
total,
|
|
4560
|
+
percent: board === 0 ? 0 : Math.round(total / board * 100)
|
|
4561
|
+
};
|
|
4562
|
+
});
|
|
4194
4563
|
const columnHeader = (col, count) => /* @__PURE__ */ jsxs("div", {
|
|
4195
4564
|
className: "flex flex-col gap-2 px-1",
|
|
4196
|
-
children: [
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
"
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
|
|
4211
|
-
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
className: "
|
|
4225
|
-
children: [
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
|
|
4565
|
+
children: [
|
|
4566
|
+
/* @__PURE__ */ jsxs("div", {
|
|
4567
|
+
className: "flex items-center gap-2",
|
|
4568
|
+
children: [
|
|
4569
|
+
/* @__PURE__ */ jsx("span", {
|
|
4570
|
+
"aria-hidden": true,
|
|
4571
|
+
className: cn("size-2 rounded-full", dotTone[col.tone ?? "neutral"])
|
|
4572
|
+
}),
|
|
4573
|
+
/* @__PURE__ */ jsx("h3", {
|
|
4574
|
+
className: "min-w-0 flex-1 truncate text-sm font-semibold",
|
|
4575
|
+
children: col.title
|
|
4576
|
+
}),
|
|
4577
|
+
/* @__PURE__ */ jsx(Badge, {
|
|
4578
|
+
tone: col.limit && count > col.limit ? "warning" : "neutral",
|
|
4579
|
+
children: col.limit ? `${count}/${col.limit}` : count
|
|
4580
|
+
}),
|
|
4581
|
+
onAddCard && /* @__PURE__ */ jsx(Button, {
|
|
4582
|
+
variant: "ghost",
|
|
4583
|
+
size: "sm",
|
|
4584
|
+
iconOnly: true,
|
|
4585
|
+
"aria-label": `Adicionar card em ${col.title}`,
|
|
4586
|
+
onClick: () => onAddCard(col.id),
|
|
4587
|
+
className: "-my-1 -mr-1 rounded-full",
|
|
4588
|
+
children: /* @__PURE__ */ jsx(Plus, {})
|
|
4589
|
+
})
|
|
4590
|
+
]
|
|
4591
|
+
}),
|
|
4592
|
+
col.cadenceDays !== void 0 && /* @__PURE__ */ jsxs("p", {
|
|
4593
|
+
className: "text-xs text-muted-foreground",
|
|
4594
|
+
children: ["Cadência: ", plural(col.cadenceDays, "dia", "dias")]
|
|
4595
|
+
}),
|
|
4596
|
+
valueFields && valueFields.length > 0 && /* @__PURE__ */ jsx("div", {
|
|
4597
|
+
className: "grid grid-cols-2 divide-x rounded-block bg-card text-xs",
|
|
4598
|
+
children: totals(col).map((t) => /* @__PURE__ */ jsxs("span", {
|
|
4599
|
+
className: "flex min-w-0 flex-col px-2 py-1",
|
|
4600
|
+
children: [
|
|
4601
|
+
/* @__PURE__ */ jsxs("span", {
|
|
4602
|
+
className: "text-muted-foreground",
|
|
4603
|
+
children: ["Total ", t.label]
|
|
4604
|
+
}),
|
|
4605
|
+
/* @__PURE__ */ jsx("span", {
|
|
4606
|
+
className: "truncate font-semibold tabular-nums",
|
|
4607
|
+
children: formatValue(t.total)
|
|
4608
|
+
}),
|
|
4609
|
+
/* @__PURE__ */ jsxs("span", {
|
|
4610
|
+
className: "text-muted-foreground tabular-nums",
|
|
4611
|
+
children: [
|
|
4612
|
+
"(",
|
|
4613
|
+
t.percent,
|
|
4614
|
+
"%)"
|
|
4615
|
+
]
|
|
4616
|
+
})
|
|
4617
|
+
]
|
|
4618
|
+
}, t.key))
|
|
4619
|
+
})
|
|
4620
|
+
]
|
|
4234
4621
|
});
|
|
4235
4622
|
const columnList = (col) => {
|
|
4236
|
-
const all =
|
|
4623
|
+
const all = visibleInColumn(col.id);
|
|
4237
4624
|
const list = all.slice(0, limitOf(col.id));
|
|
4238
4625
|
const more = all.length > list.length || Boolean(hasMore?.(col.id));
|
|
4239
4626
|
return /* @__PURE__ */ jsx("div", {
|
|
@@ -4271,32 +4658,213 @@ function Kanban({ columns, cards, onCardMove, onCardClick, onAddCard, renderCard
|
|
|
4271
4658
|
}, String(ready))
|
|
4272
4659
|
});
|
|
4273
4660
|
};
|
|
4274
|
-
|
|
4275
|
-
|
|
4276
|
-
|
|
4277
|
-
|
|
4278
|
-
|
|
4279
|
-
|
|
4280
|
-
|
|
4281
|
-
|
|
4282
|
-
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
|
|
4291
|
-
|
|
4292
|
-
|
|
4293
|
-
|
|
4294
|
-
|
|
4295
|
-
|
|
4296
|
-
|
|
4297
|
-
|
|
4661
|
+
const assignees = [...new Set(cards.map((c) => c.assignee).filter((a) => !!a))].sort((a, b) => a.localeCompare(b, "pt-BR"));
|
|
4662
|
+
const filterCount = (assigneeFilter ? 1 : 0) + (situationFilter ? 1 : 0);
|
|
4663
|
+
const hasFilters = assignees.length > 0 || statusEnabled;
|
|
4664
|
+
const toolbarNode = toolbar && /* @__PURE__ */ jsx(DataToolbar, {
|
|
4665
|
+
search: {
|
|
4666
|
+
value: query,
|
|
4667
|
+
onChange: setQuery,
|
|
4668
|
+
placeholder: "Buscar card"
|
|
4669
|
+
},
|
|
4670
|
+
filters: hasFilters ? /* @__PURE__ */ jsxs("div", {
|
|
4671
|
+
className: "flex flex-col gap-4",
|
|
4672
|
+
children: [assignees.length > 0 && /* @__PURE__ */ jsx(Field, {
|
|
4673
|
+
label: "Responsável",
|
|
4674
|
+
span: "full",
|
|
4675
|
+
children: /* @__PURE__ */ jsx(Select, {
|
|
4676
|
+
placeholder: "Todos",
|
|
4677
|
+
clearable: true,
|
|
4678
|
+
options: assignees.map((a) => ({
|
|
4679
|
+
value: a,
|
|
4680
|
+
label: a
|
|
4681
|
+
})),
|
|
4682
|
+
value: assigneeFilter,
|
|
4683
|
+
onChange: setAssigneeFilter
|
|
4684
|
+
})
|
|
4685
|
+
}), statusEnabled && /* @__PURE__ */ jsx(Field, {
|
|
4686
|
+
label: "Situação",
|
|
4687
|
+
span: "full",
|
|
4688
|
+
children: /* @__PURE__ */ jsx(Select, {
|
|
4689
|
+
placeholder: "Todas",
|
|
4690
|
+
clearable: true,
|
|
4691
|
+
options: situationOptions,
|
|
4692
|
+
value: situationFilter,
|
|
4693
|
+
onChange: setSituationFilter
|
|
4694
|
+
})
|
|
4695
|
+
})]
|
|
4696
|
+
}) : void 0,
|
|
4697
|
+
filterCount,
|
|
4698
|
+
onClearFilters: () => {
|
|
4699
|
+
setAssigneeFilter(null);
|
|
4700
|
+
setSituationFilter(null);
|
|
4701
|
+
},
|
|
4702
|
+
summary: totalFields.length > 0 ? totalFields.map((f) => /* @__PURE__ */ jsxs("span", {
|
|
4703
|
+
className: "flex items-baseline gap-1",
|
|
4704
|
+
children: [/* @__PURE__ */ jsxs("span", {
|
|
4705
|
+
className: "text-muted-foreground",
|
|
4706
|
+
children: [
|
|
4707
|
+
"Total ",
|
|
4708
|
+
f.label,
|
|
4709
|
+
":"
|
|
4710
|
+
]
|
|
4711
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
4712
|
+
className: "font-semibold tabular-nums",
|
|
4713
|
+
children: formatValue(sumOf(boardCards, f.key))
|
|
4714
|
+
})]
|
|
4715
|
+
}, f.key)) : void 0,
|
|
4716
|
+
actions: /* @__PURE__ */ jsx(Button, {
|
|
4717
|
+
variant: "outline",
|
|
4718
|
+
icon: /* @__PURE__ */ jsx(Settings2, {}),
|
|
4719
|
+
onClick: () => setCustomizing(true),
|
|
4720
|
+
children: "Customizar"
|
|
4721
|
+
}),
|
|
4722
|
+
primaryAction: onNewCard ? /* @__PURE__ */ jsx(Button, {
|
|
4723
|
+
icon: /* @__PURE__ */ jsx(Plus, {}),
|
|
4724
|
+
onClick: () => onNewCard(),
|
|
4725
|
+
children: "Novo card"
|
|
4726
|
+
}) : void 0
|
|
4727
|
+
});
|
|
4728
|
+
const customizeFields = [...baseFields.map((f) => ({
|
|
4729
|
+
id: f.id,
|
|
4730
|
+
label: f.label
|
|
4731
|
+
})), ...totalFields.map((f) => ({
|
|
4732
|
+
id: `value:${f.key}`,
|
|
4733
|
+
label: f.label
|
|
4734
|
+
}))];
|
|
4735
|
+
const customizeDrawer = toolbar && /* @__PURE__ */ jsx(Drawer, {
|
|
4736
|
+
open: customizing,
|
|
4737
|
+
onOpenChange: setCustomizing,
|
|
4738
|
+
title: "Customizar",
|
|
4739
|
+
icon: /* @__PURE__ */ jsx(Settings2, {}),
|
|
4740
|
+
footer: /* @__PURE__ */ jsx(ActionBar, {
|
|
4741
|
+
cancel: {
|
|
4742
|
+
label: "Restaurar",
|
|
4743
|
+
onClick: () => changeHidden({})
|
|
4744
|
+
},
|
|
4745
|
+
primary: {
|
|
4746
|
+
label: "Pronto",
|
|
4747
|
+
onClick: () => setCustomizing(false)
|
|
4748
|
+
}
|
|
4749
|
+
}),
|
|
4750
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
4751
|
+
className: "flex flex-col gap-1",
|
|
4752
|
+
children: customizeFields.map((f) => /* @__PURE__ */ jsx(Checkbox, {
|
|
4753
|
+
label: f.label,
|
|
4754
|
+
checked: show(f.id),
|
|
4755
|
+
onCheckedChange: (checked) => changeHidden({
|
|
4756
|
+
...hidden,
|
|
4757
|
+
[f.id]: !checked
|
|
4758
|
+
})
|
|
4759
|
+
}, f.id))
|
|
4760
|
+
})
|
|
4298
4761
|
});
|
|
4299
|
-
|
|
4762
|
+
const pendingTarget = pendingDrop && dropTargets?.find((t) => t.id === pendingDrop.targetId);
|
|
4763
|
+
const pendingCard = pendingDrop && cards.find((c) => c.id === pendingDrop.cardId);
|
|
4764
|
+
useEffect(() => {
|
|
4765
|
+
if (pendingDrop && !pendingCard) setPendingDrop(null);
|
|
4766
|
+
}, [pendingDrop, pendingCard]);
|
|
4767
|
+
const confirmation = pendingDrop && pendingTarget?.confirm && pendingCard ? /* @__PURE__ */ jsxs(Modal, {
|
|
4768
|
+
open: true,
|
|
4769
|
+
onOpenChange: (next) => !next && setPendingDrop(null),
|
|
4770
|
+
type: pendingTarget.confirm.destructive ? "destructive" : "confirm",
|
|
4771
|
+
title: pendingTarget.confirm.title,
|
|
4772
|
+
description: pendingTarget.confirm.description,
|
|
4773
|
+
confirmLabel: pendingTarget.confirm.confirmLabel ?? pendingTarget.label,
|
|
4774
|
+
onConfirm: () => onDropTarget?.(pendingDrop.cardId, pendingDrop.targetId, reason || void 0),
|
|
4775
|
+
children: [/* @__PURE__ */ jsxs("dl", {
|
|
4776
|
+
className: "flex w-full flex-col gap-1 rounded-block bg-muted p-3 text-left text-sm",
|
|
4777
|
+
children: [
|
|
4778
|
+
/* @__PURE__ */ jsxs("div", {
|
|
4779
|
+
className: "flex justify-between gap-2",
|
|
4780
|
+
children: [/* @__PURE__ */ jsx("dt", {
|
|
4781
|
+
className: "text-muted-foreground",
|
|
4782
|
+
children: "Empresa"
|
|
4783
|
+
}), /* @__PURE__ */ jsx("dd", {
|
|
4784
|
+
className: "font-medium",
|
|
4785
|
+
children: pendingCard.title
|
|
4786
|
+
})]
|
|
4787
|
+
}),
|
|
4788
|
+
pendingCard.subtitle && /* @__PURE__ */ jsxs("div", {
|
|
4789
|
+
className: "flex justify-between gap-2",
|
|
4790
|
+
children: [/* @__PURE__ */ jsx("dt", {
|
|
4791
|
+
className: "text-muted-foreground",
|
|
4792
|
+
children: "Documento"
|
|
4793
|
+
}), /* @__PURE__ */ jsx("dd", {
|
|
4794
|
+
className: "tabular-nums",
|
|
4795
|
+
children: pendingCard.subtitle
|
|
4796
|
+
})]
|
|
4797
|
+
}),
|
|
4798
|
+
/* @__PURE__ */ jsxs("div", {
|
|
4799
|
+
className: "flex justify-between gap-2",
|
|
4800
|
+
children: [/* @__PURE__ */ jsx("dt", {
|
|
4801
|
+
className: "text-muted-foreground",
|
|
4802
|
+
children: "Etapa"
|
|
4803
|
+
}), /* @__PURE__ */ jsx("dd", { children: columns.find((c) => c.id === pendingCard.columnId)?.title })]
|
|
4804
|
+
}),
|
|
4805
|
+
totalFields.map((f) => /* @__PURE__ */ jsxs("div", {
|
|
4806
|
+
className: "flex justify-between gap-2",
|
|
4807
|
+
children: [/* @__PURE__ */ jsxs("dt", {
|
|
4808
|
+
className: "text-muted-foreground",
|
|
4809
|
+
children: [f.label, ":"]
|
|
4810
|
+
}), /* @__PURE__ */ jsx("dd", {
|
|
4811
|
+
className: "font-semibold tabular-nums",
|
|
4812
|
+
children: formatValue(pendingCard.values?.[f.key] ?? 0)
|
|
4813
|
+
})]
|
|
4814
|
+
}, f.key))
|
|
4815
|
+
]
|
|
4816
|
+
}), pendingTarget.confirm.reasons && /* @__PURE__ */ jsxs("div", {
|
|
4817
|
+
className: "flex w-full flex-col gap-1 text-left",
|
|
4818
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
4819
|
+
className: "text-sm font-medium",
|
|
4820
|
+
children: "Motivo"
|
|
4821
|
+
}), /* @__PURE__ */ jsx(Select, {
|
|
4822
|
+
label: "Motivo",
|
|
4823
|
+
options: pendingTarget.confirm.reasons,
|
|
4824
|
+
value: reason,
|
|
4825
|
+
onChange: (value) => setReason(value ?? "")
|
|
4826
|
+
})]
|
|
4827
|
+
})]
|
|
4828
|
+
}) : null;
|
|
4829
|
+
if (isMobile) {
|
|
4830
|
+
const board = /* @__PURE__ */ jsxs("div", {
|
|
4831
|
+
ref: boardRef,
|
|
4832
|
+
className: cn("flex h-board min-w-0 flex-col gap-3", className),
|
|
4833
|
+
"aria-label": aria["aria-label"],
|
|
4834
|
+
"data-rendra": code,
|
|
4835
|
+
children: [
|
|
4836
|
+
targetBar,
|
|
4837
|
+
/* @__PURE__ */ jsx(Tabs, {
|
|
4838
|
+
variant: "pill",
|
|
4839
|
+
"aria-label": "Colunas",
|
|
4840
|
+
value: active,
|
|
4841
|
+
onChange: setActive,
|
|
4842
|
+
items: columns.map((col) => ({
|
|
4843
|
+
value: col.id,
|
|
4844
|
+
label: col.title,
|
|
4845
|
+
count: visibleInColumn(col.id).length,
|
|
4846
|
+
content: null
|
|
4847
|
+
}))
|
|
4848
|
+
}),
|
|
4849
|
+
columns.filter((col) => col.id === active).map((col) => /* @__PURE__ */ jsxs("div", {
|
|
4850
|
+
className: "flex min-h-0 flex-1 flex-col gap-2 rounded-surface bg-muted p-2",
|
|
4851
|
+
children: [columnHeader(col, visibleInColumn(col.id).length), columnList(col)]
|
|
4852
|
+
}, col.id))
|
|
4853
|
+
]
|
|
4854
|
+
});
|
|
4855
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
4856
|
+
toolbar ? /* @__PURE__ */ jsxs("div", {
|
|
4857
|
+
className: "flex min-w-0 flex-col gap-3",
|
|
4858
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
4859
|
+
className: "rounded-surface border bg-card",
|
|
4860
|
+
children: toolbarNode
|
|
4861
|
+
}), board]
|
|
4862
|
+
}) : board,
|
|
4863
|
+
customizeDrawer,
|
|
4864
|
+
confirmation
|
|
4865
|
+
] });
|
|
4866
|
+
}
|
|
4867
|
+
const board = /* @__PURE__ */ jsxs("section", {
|
|
4300
4868
|
ref: boardRef,
|
|
4301
4869
|
"aria-label": aria["aria-label"] ?? "Quadro kanban",
|
|
4302
4870
|
"data-rendra": code,
|
|
@@ -4307,10 +4875,21 @@ function Kanban({ columns, cards, onCardMove, onCardClick, onAddCard, renderCard
|
|
|
4307
4875
|
className: "flex min-h-0 w-kanban-col flex-col gap-2 rounded-surface bg-muted p-2",
|
|
4308
4876
|
children: [/* @__PURE__ */ jsx("div", {
|
|
4309
4877
|
className: "pt-1",
|
|
4310
|
-
children: columnHeader(col,
|
|
4878
|
+
children: columnHeader(col, visibleInColumn(col.id).length)
|
|
4311
4879
|
}), columnList(col)]
|
|
4312
4880
|
}, col.id))]
|
|
4313
4881
|
});
|
|
4882
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
4883
|
+
toolbar ? /* @__PURE__ */ jsxs("div", {
|
|
4884
|
+
className: "flex min-w-0 flex-col gap-4",
|
|
4885
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
4886
|
+
className: "rounded-surface border bg-card",
|
|
4887
|
+
children: toolbarNode
|
|
4888
|
+
}), board]
|
|
4889
|
+
}) : board,
|
|
4890
|
+
customizeDrawer,
|
|
4891
|
+
confirmation
|
|
4892
|
+
] });
|
|
4314
4893
|
}
|
|
4315
4894
|
/** Move um card na lista (para usar no onCardMove): devolve a lista nova. */
|
|
4316
4895
|
function moveKanbanCard(cards, cardId, toColumnId, toIndex) {
|
|
@@ -9557,6 +10136,6 @@ function createTheme(input) {
|
|
|
9557
10136
|
};
|
|
9558
10137
|
}
|
|
9559
10138
|
//#endregion
|
|
9560
|
-
export { Accordion, ActionBar, Alert, AppShell, Avatar, AvatarGroup, Badge, BrandFeedbackIcon, BrandLogo, BrandProvider, Breadcrumb, Button, ButtonGroup, CATALOG, CATALOG_EXCLUDED_FILES, COMPONENT_CODE_PATTERN, Calendar, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, ChannelBadge, ChatComposer, ChatThread, Checkbox, CheckboxGroup, Checklist, ColorPicker, Container, ConversationList, DEFAULT_DDI, DataToolbar, DatePicker, Drawer, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, ErrorPage, Field, Form, FormField, FormSection, Grid, ImageCropper, ImageViewer, InfoHint, Inline, Input, Kanban, Label, List, Modal, OtpInput, PageHeader, Pagination, Popover, PopoverAnchor, PopoverClose, PopoverContent, PopoverTrigger, Progress, QR_MAX_VERSION, QrCode, QrEncodingError, RENDRA_CREDIT_HREF, RENDRA_CREDIT_TEXT, RadioGroup, Rating, RendraCredit, RendraProvider, RepeatableField, Section, Select, Separator, Skeleton, Slider, Spinner, Stack, StatCard, Stepper, Switch, TABLE_PAGE_SIZE, TOKEN_KEYS, Table, Tabs, Textarea, Timeline, Toaster, Tooltip, TooltipProvider, Upload, Wizard, applyPalette, applyTheme, assertCatalogIntegrity, bindPointerDrag, breakpoints, buildDataCodewords, buttonVariants, catalogByComponent, chatChannels, cn, computeCropGeometry, computeFormatBits, computeMaskPenalty, computeVersionBits, contrast, contrastRatio, controlAdornmentButton, controlAdornmentSpace, controlFrame, controlInput, createPalette, createTheme, defaultShellLayout, encodeQrMatrix, feedbackLabels, filesMissingCatalogEntry, findComponentsWithMultipleDefaults, findComponentsWithoutDefault, findDragTarget, findDuplicateCodes, findInvalidFormatCodes, findPresetCollisions, formatCents, formatCurrency, getCatalogEntry, getReducedMotion, internationalPhoneMask, isValidCnpj, isValidCpf, isValidDateBR, layoutOptions, lookupCep, lookupCnpj, masks, moveKanbanCard, parseLocaleNumber, percentMask, phoneCountries, qrMatrixToSvgPath, readCodewordsForTest, readVar, reedSolomonComputeDivisor, reedSolomonComputeRemainder, reedSolomonEncode, reedSolomonMultiply, resolveCatalogCode, resolveDropIndex, shapeLabels, subscribeReducedMotion, toCents, toE164, toast, useBrand, useBreakpoint, useCurrentPath, useDebouncedValue, useFieldControl, useFillHeight, useLookup, usePrefersReducedMotion, useRendraBreadcrumbs, useRendraLink, useRendraNavigate, useSortable, zBR };
|
|
10139
|
+
export { Accordion, ActionBar, Alert, AppShell, Avatar, AvatarGroup, Badge, BrandFeedbackIcon, BrandLogo, BrandProvider, Breadcrumb, Button, ButtonGroup, CATALOG, CATALOG_EXCLUDED_FILES, COMPONENT_CODE_PATTERN, Calendar, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, ChannelBadge, ChatComposer, ChatThread, Checkbox, CheckboxGroup, Checklist, ColorPicker, Container, ConversationList, DEFAULT_DDI, DataToolbar, DatePicker, Drawer, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, ErrorPage, Field, Form, FormField, FormSection, Grid, ImageCropper, ImageViewer, InfoHint, Inline, Input, Kanban, Label, List, Modal, OtpInput, PageHeader, Pagination, Popover, PopoverAnchor, PopoverClose, PopoverContent, PopoverTrigger, Progress, QR_MAX_VERSION, QrCode, QrEncodingError, RENDRA_CREDIT_HREF, RENDRA_CREDIT_TEXT, RadioGroup, Rating, RendraCredit, RendraProvider, RepeatableField, Section, Select, Separator, Skeleton, Slider, Spinner, Stack, StatCard, Stepper, Switch, TABLE_PAGE_SIZE, TOKEN_KEYS, Table, Tabs, Textarea, Timeline, Toaster, Tooltip, TooltipProvider, Upload, Wizard, applyPalette, applyTheme, assertCatalogIntegrity, bindPointerDrag, breakpoints, buildDataCodewords, buttonVariants, catalogByComponent, chatChannels, cn, computeCropGeometry, computeFormatBits, computeMaskPenalty, computeVersionBits, contrast, contrastRatio, controlAdornmentButton, controlAdornmentSpace, controlFrame, controlInput, createPalette, createTheme, defaultShellLayout, encodeQrMatrix, feedbackLabels, filesMissingCatalogEntry, findComponentsWithMultipleDefaults, findComponentsWithoutDefault, findDragTarget, findDuplicateCodes, findInvalidFormatCodes, findPresetCollisions, formatCents, formatCurrency, getCatalogEntry, getKanbanCardStatus, getReducedMotion, internationalPhoneMask, isValidCnpj, isValidCpf, isValidDateBR, layoutOptions, lookupCep, lookupCnpj, masks, moveKanbanCard, parseLocaleNumber, percentMask, phoneCountries, qrMatrixToSvgPath, readCodewordsForTest, readVar, reedSolomonComputeDivisor, reedSolomonComputeRemainder, reedSolomonEncode, reedSolomonMultiply, resolveCatalogCode, resolveDropIndex, shapeLabels, subscribeReducedMotion, toCents, toE164, toast, useBrand, useBreakpoint, useCurrentPath, useDebouncedValue, useFieldControl, useFillHeight, useLookup, usePrefersReducedMotion, useRendraBreadcrumbs, useRendraLink, useRendraNavigate, useSortable, zBR };
|
|
9561
10140
|
|
|
9562
10141
|
//# sourceMappingURL=index.js.map
|