@flowtomic/logic 0.1.7 → 0.1.8
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/hooks/useDashboardLayout/index.d.ts +2 -2
- package/dist/hooks/useDashboardLayout/index.d.ts.map +1 -1
- package/dist/hooks/useDashboardLayout/useDashboardLayout.d.ts +21 -0
- package/dist/hooks/useDashboardLayout/useDashboardLayout.d.ts.map +1 -1
- package/dist/hooks/useResizable/index.d.ts +1 -1
- package/dist/hooks/useResizable/index.d.ts.map +1 -1
- package/dist/hooks/useResizable/useResizable.d.ts +5 -0
- package/dist/hooks/useResizable/useResizable.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/package.json +3 -3
- package/dist/hooks/useAnimatedIndicator/index.js +0 -1
- package/dist/hooks/useAnimatedIndicator/useAnimatedIndicator.js +0 -242
- package/dist/hooks/useAutocomplete/index.js +0 -1
- package/dist/hooks/useAutocomplete/useAutocomplete.js +0 -380
- package/dist/hooks/useDashboardLayout/index.js +0 -1
- package/dist/hooks/useDashboardLayout/useDashboardLayout.js +0 -175
- package/dist/hooks/useGenealogy/index.js +0 -1
- package/dist/hooks/useGenealogy/useGenealogy.js +0 -341
- package/dist/hooks/useMoblile/index.js +0 -1
- package/dist/hooks/useMoblile/useMobile.js +0 -15
- package/dist/hooks/useProjectProgress/index.js +0 -1
- package/dist/hooks/useProjectProgress/useProjectProgress.js +0 -124
- package/dist/hooks/useProjectStats/index.js +0 -1
- package/dist/hooks/useProjectStats/useProjectStats.js +0 -87
- package/dist/hooks/useReactTableBack/index.js +0 -1
- package/dist/hooks/useReactTableBack/useReactTableBack.js +0 -124
- package/dist/hooks/useReactTableFront/index.js +0 -1
- package/dist/hooks/useReactTableFront/useReactTableFront.js +0 -112
- package/dist/hooks/useResizable/index.js +0 -1
- package/dist/hooks/useResizable/useResizable.js +0 -129
- package/dist/hooks/useScriptEditor/index.js +0 -1
- package/dist/hooks/useScriptEditor/useScriptEditor.js +0 -247
- package/dist/hooks/useStatCard/index.js +0 -1
- package/dist/hooks/useStatCard/useStatCard.js +0 -187
- package/dist/hooks/useThemeTransition/index.js +0 -1
- package/dist/hooks/useThemeTransition/useThemeTransition.js +0 -35
- package/dist/hooks/useTimeTracker/index.js +0 -1
- package/dist/hooks/useTimeTracker/useTimeTracker.js +0 -143
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* useProjectStats - Headless UI Hook
|
|
3
|
-
*
|
|
4
|
-
* Fornece apenas: lógica, estado, processamento e API
|
|
5
|
-
* NÃO fornece: markup, styles ou implementações pré-construídas
|
|
6
|
-
*
|
|
7
|
-
* Padrão Headless UI: você controla o markup e styles
|
|
8
|
-
*
|
|
9
|
-
* @example
|
|
10
|
-
* ```tsx
|
|
11
|
-
* function MyProjectStats() {
|
|
12
|
-
* const { total, ended, running, pending, stats } = useProjectStats({
|
|
13
|
-
* projects: [
|
|
14
|
-
* { id: '1', status: 'running', ... },
|
|
15
|
-
* { id: '2', status: 'ended', ... },
|
|
16
|
-
* ],
|
|
17
|
-
* })
|
|
18
|
-
*
|
|
19
|
-
* return (
|
|
20
|
-
* <div>
|
|
21
|
-
* <div>Total: {total}</div>
|
|
22
|
-
* <div>Running: {running}</div>
|
|
23
|
-
* <div>Ended: {ended}</div>
|
|
24
|
-
* <div>Pending: {pending}</div>
|
|
25
|
-
* </div>
|
|
26
|
-
* )
|
|
27
|
-
* }
|
|
28
|
-
* ```
|
|
29
|
-
*/
|
|
30
|
-
import { useMemo } from "react";
|
|
31
|
-
/**
|
|
32
|
-
* Hook headless para calcular estatísticas de projetos
|
|
33
|
-
*/
|
|
34
|
-
export function useProjectStats(options) {
|
|
35
|
-
const { projects, filter, groupBy } = options;
|
|
36
|
-
const stats = useMemo(() => {
|
|
37
|
-
// Aplicar filtro se fornecido
|
|
38
|
-
const filtered = filter ? projects.filter(filter) : projects;
|
|
39
|
-
// Calcular contagens por status
|
|
40
|
-
const byStatus = {
|
|
41
|
-
running: 0,
|
|
42
|
-
ended: 0,
|
|
43
|
-
pending: 0,
|
|
44
|
-
"on-hold": 0,
|
|
45
|
-
cancelled: 0,
|
|
46
|
-
};
|
|
47
|
-
filtered.forEach((project) => {
|
|
48
|
-
const status = project.status || "pending";
|
|
49
|
-
if (status in byStatus) {
|
|
50
|
-
byStatus[status]++;
|
|
51
|
-
}
|
|
52
|
-
});
|
|
53
|
-
// Agrupar se groupBy foi fornecido
|
|
54
|
-
const grouped = groupBy
|
|
55
|
-
? filtered.reduce((acc, project) => {
|
|
56
|
-
const key = groupBy(project);
|
|
57
|
-
if (!acc[key]) {
|
|
58
|
-
acc[key] = [];
|
|
59
|
-
}
|
|
60
|
-
acc[key].push(project);
|
|
61
|
-
return acc;
|
|
62
|
-
}, {})
|
|
63
|
-
: undefined;
|
|
64
|
-
return {
|
|
65
|
-
total: filtered.length,
|
|
66
|
-
ended: byStatus.ended,
|
|
67
|
-
running: byStatus.running,
|
|
68
|
-
pending: byStatus.pending,
|
|
69
|
-
onHold: byStatus["on-hold"],
|
|
70
|
-
cancelled: byStatus.cancelled,
|
|
71
|
-
byStatus,
|
|
72
|
-
filtered,
|
|
73
|
-
grouped,
|
|
74
|
-
};
|
|
75
|
-
}, [projects, filter, groupBy]);
|
|
76
|
-
return {
|
|
77
|
-
stats,
|
|
78
|
-
total: stats.total,
|
|
79
|
-
ended: stats.ended,
|
|
80
|
-
running: stats.running,
|
|
81
|
-
pending: stats.pending,
|
|
82
|
-
onHold: stats.onHold,
|
|
83
|
-
cancelled: stats.cancelled,
|
|
84
|
-
filtered: stats.filtered,
|
|
85
|
-
grouped: stats.grouped,
|
|
86
|
-
};
|
|
87
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { useReactTableBack } from "./useReactTableBack";
|
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* useReactTableBack - Headless UI Hook
|
|
3
|
-
*
|
|
4
|
-
* Hook headless para TanStack Table com paginação e ordenação no backend (server-side).
|
|
5
|
-
* Fornece apenas: lógica, estado, processamento e API
|
|
6
|
-
* NÃO fornece: markup, styles ou implementações pré-construídas
|
|
7
|
-
*
|
|
8
|
-
* @example
|
|
9
|
-
* ```tsx
|
|
10
|
-
* function MyTable() {
|
|
11
|
-
* const { table, sorting, pagination, setPagination, paginationInfo } = useReactTableBack({
|
|
12
|
-
* data: pageData,
|
|
13
|
-
* columns: columnDefs,
|
|
14
|
-
* totalCount: 1000,
|
|
15
|
-
* onPaginationChange: ({ pageIndex, pageSize }) => {
|
|
16
|
-
* fetchData({ page: pageIndex + 1, pageSize });
|
|
17
|
-
* },
|
|
18
|
-
* onSortingChange: (sorting) => {
|
|
19
|
-
* fetchData({ sorting });
|
|
20
|
-
* },
|
|
21
|
-
* })
|
|
22
|
-
*
|
|
23
|
-
* return (
|
|
24
|
-
* <table>
|
|
25
|
-
* {/* Usar table.getHeaderGroups(), table.getRowModel(), etc. *\/}
|
|
26
|
-
* </table>
|
|
27
|
-
* )
|
|
28
|
-
* }
|
|
29
|
-
* ```
|
|
30
|
-
*/
|
|
31
|
-
import { getCoreRowModel, useReactTable, } from "@tanstack/react-table";
|
|
32
|
-
import { useEffect, useMemo, useState } from "react";
|
|
33
|
-
/**
|
|
34
|
-
* Hook Headless UI para TanStack Table com paginação/ordenação server-side
|
|
35
|
-
*/
|
|
36
|
-
export function useReactTableBack(options) {
|
|
37
|
-
const { data, columns, totalCount, enablePagination = true, pageSize = 10, onPaginationChange, enableSorting = true, initialSorting = [], onSortingChange, initialColumnFilters = [], initialColumnVisibility = {}, enableRowSelection = false, onSelectionChange, } = options;
|
|
38
|
-
const [sorting, setSorting] = useState(initialSorting);
|
|
39
|
-
const [columnFilters, setColumnFilters] = useState(initialColumnFilters);
|
|
40
|
-
const [globalFilter, setGlobalFilter] = useState("");
|
|
41
|
-
const [columnVisibility, setColumnVisibility] = useState(initialColumnVisibility);
|
|
42
|
-
const [rowSelection, setRowSelection] = useState({});
|
|
43
|
-
const [pagination, setPagination] = useState({
|
|
44
|
-
pageIndex: 0,
|
|
45
|
-
pageSize,
|
|
46
|
-
});
|
|
47
|
-
// Notificar mudanças de paginação (server-side)
|
|
48
|
-
useEffect(() => {
|
|
49
|
-
if (enablePagination && onPaginationChange) {
|
|
50
|
-
onPaginationChange({
|
|
51
|
-
pageIndex: pagination.pageIndex,
|
|
52
|
-
pageSize: pagination.pageSize,
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
}, [pagination, enablePagination, onPaginationChange]);
|
|
56
|
-
// Notificar mudanças de ordenação (server-side)
|
|
57
|
-
useEffect(() => {
|
|
58
|
-
if (enableSorting && onSortingChange) {
|
|
59
|
-
onSortingChange(sorting);
|
|
60
|
-
}
|
|
61
|
-
}, [sorting, enableSorting, onSortingChange]);
|
|
62
|
-
const table = useReactTable({
|
|
63
|
-
data,
|
|
64
|
-
columns,
|
|
65
|
-
state: {
|
|
66
|
-
sorting: enableSorting ? sorting : undefined,
|
|
67
|
-
columnFilters,
|
|
68
|
-
columnVisibility,
|
|
69
|
-
rowSelection: enableRowSelection ? rowSelection : undefined,
|
|
70
|
-
pagination: enablePagination ? pagination : undefined,
|
|
71
|
-
},
|
|
72
|
-
onSortingChange: enableSorting ? setSorting : undefined,
|
|
73
|
-
onColumnFiltersChange: setColumnFilters,
|
|
74
|
-
onColumnVisibilityChange: setColumnVisibility,
|
|
75
|
-
onRowSelectionChange: enableRowSelection ? setRowSelection : undefined,
|
|
76
|
-
onPaginationChange: enablePagination ? setPagination : undefined,
|
|
77
|
-
getCoreRowModel: getCoreRowModel(),
|
|
78
|
-
enableSorting,
|
|
79
|
-
enableRowSelection,
|
|
80
|
-
// Server-side: manual pagination e sorting
|
|
81
|
-
manualPagination: enablePagination,
|
|
82
|
-
manualSorting: enableSorting,
|
|
83
|
-
// Total de páginas calculado do totalCount
|
|
84
|
-
pageCount: enablePagination && totalCount !== undefined
|
|
85
|
-
? Math.ceil(totalCount / pagination.pageSize)
|
|
86
|
-
: undefined,
|
|
87
|
-
});
|
|
88
|
-
// Notificar mudanças na seleção
|
|
89
|
-
useEffect(() => {
|
|
90
|
-
if (onSelectionChange && enableRowSelection) {
|
|
91
|
-
const selectedRows = table.getFilteredSelectedRowModel().rows.map((row) => row.original);
|
|
92
|
-
onSelectionChange(selectedRows);
|
|
93
|
-
}
|
|
94
|
-
}, [table, onSelectionChange, enableRowSelection]);
|
|
95
|
-
// Calcular informações de paginação
|
|
96
|
-
const paginationInfo = useMemo(() => {
|
|
97
|
-
const start = pagination.pageIndex * pagination.pageSize + 1;
|
|
98
|
-
const end = Math.min((pagination.pageIndex + 1) * pagination.pageSize, totalCount);
|
|
99
|
-
return {
|
|
100
|
-
start,
|
|
101
|
-
end,
|
|
102
|
-
total: totalCount,
|
|
103
|
-
pageCount: enablePagination && totalCount !== undefined
|
|
104
|
-
? Math.ceil(totalCount / pagination.pageSize)
|
|
105
|
-
: 1,
|
|
106
|
-
};
|
|
107
|
-
}, [pagination, totalCount, enablePagination]);
|
|
108
|
-
return {
|
|
109
|
-
table,
|
|
110
|
-
sorting,
|
|
111
|
-
setSorting,
|
|
112
|
-
pagination,
|
|
113
|
-
setPagination,
|
|
114
|
-
columnFilters,
|
|
115
|
-
setColumnFilters,
|
|
116
|
-
globalFilter,
|
|
117
|
-
setGlobalFilter,
|
|
118
|
-
columnVisibility,
|
|
119
|
-
setColumnVisibility,
|
|
120
|
-
rowSelection,
|
|
121
|
-
setRowSelection,
|
|
122
|
-
paginationInfo,
|
|
123
|
-
};
|
|
124
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { useReactTableFront } from "./useReactTableFront";
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* useReactTableFront - Headless UI Hook
|
|
3
|
-
*
|
|
4
|
-
* Hook headless para TanStack Table com paginação e ordenação no frontend (client-side).
|
|
5
|
-
* Fornece apenas: lógica, estado, processamento e API
|
|
6
|
-
* NÃO fornece: markup, styles ou implementações pré-construídas
|
|
7
|
-
*
|
|
8
|
-
* @example
|
|
9
|
-
* ```tsx
|
|
10
|
-
* function MyTable() {
|
|
11
|
-
* const { table, sorting, pagination, setPagination, paginationInfo } = useReactTableFront({
|
|
12
|
-
* data: allData,
|
|
13
|
-
* columns: columnDefs,
|
|
14
|
-
* enablePagination: true,
|
|
15
|
-
* enableSorting: true,
|
|
16
|
-
* })
|
|
17
|
-
*
|
|
18
|
-
* return (
|
|
19
|
-
* <table>
|
|
20
|
-
* {/* Usar table.getHeaderGroups(), table.getRowModel(), etc. *\/}
|
|
21
|
-
* </table>
|
|
22
|
-
* )
|
|
23
|
-
* }
|
|
24
|
-
* ```
|
|
25
|
-
*/
|
|
26
|
-
import { getCoreRowModel, getFilteredRowModel, getPaginationRowModel, getSortedRowModel, useReactTable, } from "@tanstack/react-table";
|
|
27
|
-
import { useEffect, useMemo, useState } from "react";
|
|
28
|
-
/**
|
|
29
|
-
* Hook Headless UI para TanStack Table com paginação/ordenação client-side
|
|
30
|
-
*/
|
|
31
|
-
export function useReactTableFront(options) {
|
|
32
|
-
const { data, columns, enablePagination = true, pageSize = 10, enableSorting = true, initialSorting = [], enableGlobalFilter = true, initialColumnFilters = [], initialColumnVisibility = {}, enableRowSelection = false, onSelectionChange, } = options;
|
|
33
|
-
const [sorting, setSorting] = useState(initialSorting);
|
|
34
|
-
const [columnFilters, setColumnFilters] = useState(initialColumnFilters);
|
|
35
|
-
const [globalFilter, setGlobalFilter] = useState("");
|
|
36
|
-
const [columnVisibility, setColumnVisibility] = useState(initialColumnVisibility);
|
|
37
|
-
const [rowSelection, setRowSelection] = useState({});
|
|
38
|
-
const [pagination, setPagination] = useState({
|
|
39
|
-
pageIndex: 0,
|
|
40
|
-
pageSize,
|
|
41
|
-
});
|
|
42
|
-
const table = useReactTable({
|
|
43
|
-
data,
|
|
44
|
-
columns,
|
|
45
|
-
state: {
|
|
46
|
-
sorting: enableSorting ? sorting : undefined,
|
|
47
|
-
columnFilters,
|
|
48
|
-
globalFilter: enableGlobalFilter ? globalFilter : undefined,
|
|
49
|
-
columnVisibility,
|
|
50
|
-
rowSelection: enableRowSelection ? rowSelection : undefined,
|
|
51
|
-
pagination: enablePagination ? pagination : undefined,
|
|
52
|
-
},
|
|
53
|
-
onSortingChange: enableSorting ? setSorting : undefined,
|
|
54
|
-
onColumnFiltersChange: setColumnFilters,
|
|
55
|
-
onGlobalFilterChange: enableGlobalFilter ? setGlobalFilter : undefined,
|
|
56
|
-
onColumnVisibilityChange: setColumnVisibility,
|
|
57
|
-
onRowSelectionChange: enableRowSelection ? setRowSelection : undefined,
|
|
58
|
-
onPaginationChange: enablePagination ? setPagination : undefined,
|
|
59
|
-
getCoreRowModel: getCoreRowModel(),
|
|
60
|
-
getFilteredRowModel: getFilteredRowModel(),
|
|
61
|
-
getPaginationRowModel: enablePagination ? getPaginationRowModel() : undefined,
|
|
62
|
-
getSortedRowModel: enableSorting ? getSortedRowModel() : undefined,
|
|
63
|
-
enableSorting,
|
|
64
|
-
enableRowSelection,
|
|
65
|
-
manualPagination: false,
|
|
66
|
-
manualSorting: false,
|
|
67
|
-
});
|
|
68
|
-
// Notificar mudanças na seleção
|
|
69
|
-
useEffect(() => {
|
|
70
|
-
if (onSelectionChange && enableRowSelection) {
|
|
71
|
-
const selectedRows = table.getFilteredSelectedRowModel().rows.map((row) => row.original);
|
|
72
|
-
onSelectionChange(selectedRows);
|
|
73
|
-
}
|
|
74
|
-
}, [table, onSelectionChange, enableRowSelection]);
|
|
75
|
-
// Calcular informações de paginação
|
|
76
|
-
const paginationInfo = useMemo(() => {
|
|
77
|
-
const filteredCount = table.getFilteredRowModel().rows.length;
|
|
78
|
-
// Se a paginação estiver desabilitada, retornar valores padrão
|
|
79
|
-
if (!enablePagination) {
|
|
80
|
-
return {
|
|
81
|
-
start: 1,
|
|
82
|
-
end: filteredCount,
|
|
83
|
-
total: filteredCount,
|
|
84
|
-
pageCount: 1,
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
const start = pagination.pageIndex * pagination.pageSize + 1;
|
|
88
|
-
const end = Math.min((pagination.pageIndex + 1) * pagination.pageSize, filteredCount);
|
|
89
|
-
return {
|
|
90
|
-
start,
|
|
91
|
-
end,
|
|
92
|
-
total: filteredCount,
|
|
93
|
-
pageCount: table.getPageCount(),
|
|
94
|
-
};
|
|
95
|
-
}, [table, pagination, enablePagination]);
|
|
96
|
-
return {
|
|
97
|
-
table,
|
|
98
|
-
sorting,
|
|
99
|
-
setSorting,
|
|
100
|
-
pagination,
|
|
101
|
-
setPagination,
|
|
102
|
-
columnFilters,
|
|
103
|
-
setColumnFilters,
|
|
104
|
-
globalFilter,
|
|
105
|
-
setGlobalFilter,
|
|
106
|
-
columnVisibility,
|
|
107
|
-
setColumnVisibility,
|
|
108
|
-
rowSelection,
|
|
109
|
-
setRowSelection,
|
|
110
|
-
paginationInfo,
|
|
111
|
-
};
|
|
112
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { useResizable } from "./useResizable";
|
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* useResizable - Headless UI Hook
|
|
3
|
-
*
|
|
4
|
-
* Fornece apenas: lógica, estado, processamento e API para componentes resizable
|
|
5
|
-
* NÃO fornece: markup, styles ou implementações pré-construídas
|
|
6
|
-
*
|
|
7
|
-
* Padrão Headless UI: você controla o markup e styles
|
|
8
|
-
*/
|
|
9
|
-
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
10
|
-
const MOBILE_BREAKPOINT = 768;
|
|
11
|
-
export function useResizable({ sidebarOpen, setSidebarOpen, side = "left", persistKey = "default", defaultSidebarPct = 0.28, minPx = 250, maxPct = 0.6, maxPxCap = 500, mobileDrawer = true, tinySizePx, snapThreshold = 50, }) {
|
|
12
|
-
const containerRef = useRef(null);
|
|
13
|
-
const sidebarPanelRef = useRef(null);
|
|
14
|
-
const [isMobile, setIsMobile] = useState(false);
|
|
15
|
-
const [sidebarSize, setSidebarSize] = useState(defaultSidebarPct * 100);
|
|
16
|
-
const [containerWidth, setContainerWidth] = useState(null);
|
|
17
|
-
// Detectar mobile
|
|
18
|
-
useEffect(() => {
|
|
19
|
-
const checkMobile = () => {
|
|
20
|
-
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
|
|
21
|
-
};
|
|
22
|
-
checkMobile();
|
|
23
|
-
window.addEventListener("resize", checkMobile);
|
|
24
|
-
return () => window.removeEventListener("resize", checkMobile);
|
|
25
|
-
}, []);
|
|
26
|
-
// Observar largura do container para recalcular min/max (ref não dispara re-render)
|
|
27
|
-
useEffect(() => {
|
|
28
|
-
const el = containerRef.current;
|
|
29
|
-
if (!el)
|
|
30
|
-
return;
|
|
31
|
-
const update = () => setContainerWidth(el.offsetWidth);
|
|
32
|
-
update();
|
|
33
|
-
const ro = new ResizeObserver(update);
|
|
34
|
-
ro.observe(el);
|
|
35
|
-
return () => ro.disconnect();
|
|
36
|
-
}, []);
|
|
37
|
-
// Carregar tamanho persistido
|
|
38
|
-
useEffect(() => {
|
|
39
|
-
if (typeof window === "undefined")
|
|
40
|
-
return;
|
|
41
|
-
const storageKey = `resizable-sidebar-${persistKey}`;
|
|
42
|
-
const saved = localStorage.getItem(storageKey);
|
|
43
|
-
if (saved) {
|
|
44
|
-
try {
|
|
45
|
-
const parsed = JSON.parse(saved);
|
|
46
|
-
if (typeof parsed.size === "number" && parsed.size >= 5 && parsed.size < 100) {
|
|
47
|
-
setSidebarSize(parsed.size);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
catch {
|
|
51
|
-
// Ignorar erros de parsing
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}, [persistKey]);
|
|
55
|
-
// Salvar tamanho no localStorage
|
|
56
|
-
const saveSize = useCallback((size) => {
|
|
57
|
-
if (typeof window === "undefined")
|
|
58
|
-
return;
|
|
59
|
-
const storageKey = `resizable-sidebar-${persistKey}`;
|
|
60
|
-
localStorage.setItem(storageKey, JSON.stringify({ size, timestamp: Date.now() }));
|
|
61
|
-
}, [persistKey]);
|
|
62
|
-
// Calcular tamanhos (usa containerWidth do ResizeObserver para atualizar quando container monta)
|
|
63
|
-
const minSize = useMemo(() => {
|
|
64
|
-
const w = containerWidth ?? 1920;
|
|
65
|
-
return (minPx / w) * 100;
|
|
66
|
-
}, [minPx, containerWidth]);
|
|
67
|
-
const maxSize = useMemo(() => {
|
|
68
|
-
const w = containerWidth ?? 1920;
|
|
69
|
-
const maxPx = Math.min(maxPxCap, w * maxPct);
|
|
70
|
-
return (maxPx / w) * 100;
|
|
71
|
-
}, [maxPct, maxPxCap, containerWidth]);
|
|
72
|
-
// Handler para toggle do sidebar (double click)
|
|
73
|
-
const handleDoubleClick = useCallback(() => {
|
|
74
|
-
if (sidebarOpen) {
|
|
75
|
-
// Colapsar
|
|
76
|
-
sidebarPanelRef.current?.collapse();
|
|
77
|
-
setSidebarOpen(false);
|
|
78
|
-
}
|
|
79
|
-
else {
|
|
80
|
-
// Expandir: restaurar tamanho padrão (evita library reportar valor bogus em onLayoutChanged)
|
|
81
|
-
const defaultSize = defaultSidebarPct * 100;
|
|
82
|
-
setSidebarSize(defaultSize);
|
|
83
|
-
saveSize(defaultSize);
|
|
84
|
-
sidebarPanelRef.current?.expand();
|
|
85
|
-
// v4 interprets number as px; pass "N%" for percentage (logic uses v3 types but UI uses v4 at runtime)
|
|
86
|
-
sidebarPanelRef.current?.resize(`${defaultSize}%`);
|
|
87
|
-
setSidebarOpen(true);
|
|
88
|
-
}
|
|
89
|
-
}, [sidebarOpen, setSidebarOpen, defaultSidebarPct, saveSize]);
|
|
90
|
-
// Handler para mudanças de layout
|
|
91
|
-
const handleLayout = useCallback((sizes) => {
|
|
92
|
-
if (sizes.length > 0) {
|
|
93
|
-
const newSize = side === "left" ? sizes[0] : sizes[sizes.length - 1];
|
|
94
|
-
setSidebarSize(newSize);
|
|
95
|
-
saveSize(newSize);
|
|
96
|
-
}
|
|
97
|
-
}, [side, saveSize]);
|
|
98
|
-
// Handler para fim do resize (snap automático)
|
|
99
|
-
const handleResizeEnd = useCallback(() => {
|
|
100
|
-
if (!tinySizePx || !containerRef.current)
|
|
101
|
-
return;
|
|
102
|
-
const containerWidth = containerRef.current.offsetWidth;
|
|
103
|
-
const currentSizePx = (sidebarSize / 100) * containerWidth;
|
|
104
|
-
const tinySizePercent = (tinySizePx / containerWidth) * 100;
|
|
105
|
-
// Verificar se está próximo do tamanho tiny
|
|
106
|
-
if (Math.abs(currentSizePx - tinySizePx) <= snapThreshold &&
|
|
107
|
-
currentSizePx < tinySizePx + snapThreshold) {
|
|
108
|
-
// Snap para tiny
|
|
109
|
-
const targetSize = tinySizePercent;
|
|
110
|
-
setSidebarSize(targetSize);
|
|
111
|
-
saveSize(targetSize);
|
|
112
|
-
sidebarPanelRef.current?.resize(`${targetSize}%`);
|
|
113
|
-
}
|
|
114
|
-
}, [sidebarSize, tinySizePx, snapThreshold, saveSize]);
|
|
115
|
-
const shouldUseMobileDrawer = mobileDrawer && isMobile;
|
|
116
|
-
const autoSaveId = `resizable-${persistKey}`;
|
|
117
|
-
return {
|
|
118
|
-
handleDoubleClick,
|
|
119
|
-
shouldUseMobileDrawer,
|
|
120
|
-
containerRef,
|
|
121
|
-
autoSaveId,
|
|
122
|
-
handleLayout,
|
|
123
|
-
sidebarPanelRef: sidebarPanelRef,
|
|
124
|
-
sidebarSize,
|
|
125
|
-
minSize,
|
|
126
|
-
maxSize,
|
|
127
|
-
handleResizeEnd,
|
|
128
|
-
};
|
|
129
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { useScriptEditor } from "./useScriptEditor";
|