@flowtomic/logic 0.1.3 → 0.1.5
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/useAutocomplete/useAutocomplete.d.ts.map +1 -1
- package/dist/hooks/useAutocomplete/useAutocomplete.js +4 -3
- package/dist/hooks/useDashboardLayout/index.d.ts +3 -0
- package/dist/hooks/useDashboardLayout/index.d.ts.map +1 -0
- package/dist/hooks/useDashboardLayout/index.js +1 -0
- package/dist/hooks/useDashboardLayout/useDashboardLayout.d.ts +120 -0
- package/dist/hooks/useDashboardLayout/useDashboardLayout.d.ts.map +1 -0
- package/dist/hooks/useDashboardLayout/useDashboardLayout.js +175 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAutocomplete.d.ts","sourceRoot":"","sources":["../../../src/hooks/useAutocomplete/useAutocomplete.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;
|
|
1
|
+
{"version":3,"file":"useAutocomplete.d.ts","sourceRoot":"","sources":["../../../src/hooks/useAutocomplete/useAutocomplete.ts"],"names":[],"mappings":"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"}
|
|
@@ -48,8 +48,8 @@
|
|
|
48
48
|
* }
|
|
49
49
|
* ```
|
|
50
50
|
*/
|
|
51
|
-
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
52
51
|
import * as React from "react";
|
|
52
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
53
53
|
/**
|
|
54
54
|
* Função de filtro padrão (case-insensitive)
|
|
55
55
|
*/
|
|
@@ -137,7 +137,7 @@ function extractItemsFromChildren(children) {
|
|
|
137
137
|
* Você é responsável por criar o visual.
|
|
138
138
|
*/
|
|
139
139
|
export function useAutocomplete(options = {}) {
|
|
140
|
-
const { options: providedOptions = [], value: controlledValue, defaultValue, onValueChange, filterFunction = defaultFilter, allowCustomValue = false, isLoading = false, emptyMessage = "Nenhum resultado encontrado.", children, } = options;
|
|
140
|
+
const { options: providedOptions = [], value: controlledValue, defaultValue, onValueChange, filterFunction = defaultFilter, allowCustomValue = false, isLoading = false, emptyMessage: _emptyMessage = "Nenhum resultado encontrado.", children, } = options;
|
|
141
141
|
// Determinar se está usando composição ou API antiga
|
|
142
142
|
const useComposition = children !== undefined;
|
|
143
143
|
// Estado interno
|
|
@@ -267,7 +267,7 @@ export function useAutocomplete(options = {}) {
|
|
|
267
267
|
if (e.key === "ArrowDown") {
|
|
268
268
|
e.preventDefault();
|
|
269
269
|
if (isOpen) {
|
|
270
|
-
setHighlightedIndex((prev) => prev < filteredItems.length - 1 ? prev + 1 : prev);
|
|
270
|
+
setHighlightedIndex((prev) => (prev < filteredItems.length - 1 ? prev + 1 : prev));
|
|
271
271
|
}
|
|
272
272
|
else {
|
|
273
273
|
open();
|
|
@@ -313,6 +313,7 @@ export function useAutocomplete(options = {}) {
|
|
|
313
313
|
close,
|
|
314
314
|
select,
|
|
315
315
|
allowCustomValue,
|
|
316
|
+
setInputValue,
|
|
316
317
|
]);
|
|
317
318
|
const getPopoverProps = useCallback((props = {}) => {
|
|
318
319
|
return {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/hooks/useDashboardLayout/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,UAAU,EACV,uBAAuB,EACvB,wBAAwB,EACxB,YAAY,GACb,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useDashboardLayout } from "./useDashboardLayout";
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useDashboardLayout - 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 MyDashboard() {
|
|
12
|
+
* const [widgets, setWidgets] = useState<WidgetLayout[]>([]);
|
|
13
|
+
* const gridConfig: GridConfig = { columns: 12, cellSize: 50, gap: 16 };
|
|
14
|
+
*
|
|
15
|
+
* const {
|
|
16
|
+
* getWidgetGridPosition,
|
|
17
|
+
* moveWidget,
|
|
18
|
+
* resizeWidget,
|
|
19
|
+
* findNextAvailablePosition,
|
|
20
|
+
* } = useDashboardLayout({
|
|
21
|
+
* widgetsLayout: widgets,
|
|
22
|
+
* gridConfig,
|
|
23
|
+
* onUpdateLayout: setWidgets,
|
|
24
|
+
* });
|
|
25
|
+
*
|
|
26
|
+
* return (
|
|
27
|
+
* <div>
|
|
28
|
+
* {widgets.map(widget => (
|
|
29
|
+
* <div style={getWidgetGridPosition(widget)}>
|
|
30
|
+
* Widget Content
|
|
31
|
+
* </div>
|
|
32
|
+
* ))}
|
|
33
|
+
* </div>
|
|
34
|
+
* );
|
|
35
|
+
* }
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export interface WidgetLayout {
|
|
39
|
+
id: string;
|
|
40
|
+
type: string;
|
|
41
|
+
x: number;
|
|
42
|
+
y: number;
|
|
43
|
+
w: number;
|
|
44
|
+
h: number;
|
|
45
|
+
config?: Record<string, unknown>;
|
|
46
|
+
minimized?: boolean;
|
|
47
|
+
}
|
|
48
|
+
export interface GridConfig {
|
|
49
|
+
columns: number;
|
|
50
|
+
cellSize?: number;
|
|
51
|
+
gap?: number;
|
|
52
|
+
}
|
|
53
|
+
export interface UseDashboardLayoutProps {
|
|
54
|
+
/**
|
|
55
|
+
* Layout atual de widgets
|
|
56
|
+
*/
|
|
57
|
+
widgetsLayout: WidgetLayout[];
|
|
58
|
+
/**
|
|
59
|
+
* Configuração do grid
|
|
60
|
+
*/
|
|
61
|
+
gridConfig: GridConfig;
|
|
62
|
+
/**
|
|
63
|
+
* Callback para atualizar o layout completo
|
|
64
|
+
*/
|
|
65
|
+
onUpdateLayout: (layout: WidgetLayout[]) => void;
|
|
66
|
+
}
|
|
67
|
+
export interface UseDashboardLayoutReturn {
|
|
68
|
+
/**
|
|
69
|
+
* Configuração do grid (normalizada com defaults)
|
|
70
|
+
*/
|
|
71
|
+
gridConfig: GridConfig;
|
|
72
|
+
/**
|
|
73
|
+
* Calcula posição CSS Grid para um widget
|
|
74
|
+
*/
|
|
75
|
+
getWidgetGridPosition: (widget: WidgetLayout) => {
|
|
76
|
+
gridColumnStart: number;
|
|
77
|
+
gridColumnEnd: number;
|
|
78
|
+
gridRowStart: number;
|
|
79
|
+
gridRowEnd: number;
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* Verifica se uma posição está ocupada
|
|
83
|
+
*/
|
|
84
|
+
isPositionOccupied: (x: number, y: number, w: number, h: number, excludeWidgetId?: string) => boolean;
|
|
85
|
+
/**
|
|
86
|
+
* Encontra próxima posição disponível
|
|
87
|
+
*/
|
|
88
|
+
findNextAvailablePosition: (w: number, h: number) => {
|
|
89
|
+
x: number;
|
|
90
|
+
y: number;
|
|
91
|
+
} | null;
|
|
92
|
+
/**
|
|
93
|
+
* Valida se um widget pode ser movido para uma posição
|
|
94
|
+
*/
|
|
95
|
+
canMoveToPosition: (widgetId: string, x: number, y: number) => boolean;
|
|
96
|
+
/**
|
|
97
|
+
* Valida se um widget pode ser redimensionado
|
|
98
|
+
*/
|
|
99
|
+
canResize: (widgetId: string, newW: number, newH: number) => boolean;
|
|
100
|
+
/**
|
|
101
|
+
* Move widget para nova posição
|
|
102
|
+
*/
|
|
103
|
+
moveWidget: (widgetId: string, x: number, y: number) => void;
|
|
104
|
+
/**
|
|
105
|
+
* Redimensiona widget
|
|
106
|
+
*/
|
|
107
|
+
resizeWidget: (widgetId: string, w: number, h: number) => void;
|
|
108
|
+
/**
|
|
109
|
+
* Atualiza layout completo
|
|
110
|
+
*/
|
|
111
|
+
updateLayout: (layout: WidgetLayout[]) => void;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Hook para gerenciar layout do dashboard
|
|
115
|
+
*
|
|
116
|
+
* Hook headless que fornece apenas lógica de layout, sem UI.
|
|
117
|
+
* Você controla o markup e styles.
|
|
118
|
+
*/
|
|
119
|
+
export declare function useDashboardLayout({ widgetsLayout, gridConfig, onUpdateLayout, }: UseDashboardLayoutProps): UseDashboardLayoutReturn;
|
|
120
|
+
//# sourceMappingURL=useDashboardLayout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDashboardLayout.d.ts","sourceRoot":"","sources":["../../../src/hooks/useDashboardLayout/useDashboardLayout.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAOH,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,uBAAuB;IACtC;;OAEG;IACH,aAAa,EAAE,YAAY,EAAE,CAAC;IAE9B;;OAEG;IACH,UAAU,EAAE,UAAU,CAAC;IAEvB;;OAEG;IACH,cAAc,EAAE,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,IAAI,CAAC;CAClD;AAED,MAAM,WAAW,wBAAwB;IACvC;;OAEG;IACH,UAAU,EAAE,UAAU,CAAC;IAEvB;;OAEG;IACH,qBAAqB,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK;QAC/C,eAAe,EAAE,MAAM,CAAC;QACxB,aAAa,EAAE,MAAM,CAAC;QACtB,YAAY,EAAE,MAAM,CAAC;QACrB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;IAEF;;OAEG;IACH,kBAAkB,EAAE,CAClB,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,eAAe,CAAC,EAAE,MAAM,KACrB,OAAO,CAAC;IAEb;;OAEG;IACH,yBAAyB,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAErF;;OAEG;IACH,iBAAiB,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC;IAEvE;;OAEG;IACH,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;IAErE;;OAEG;IACH,UAAU,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAE7D;;OAEG;IACH,YAAY,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAE/D;;OAEG;IACH,YAAY,EAAE,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,IAAI,CAAC;CAChD;AAQD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,aAAa,EACb,UAAU,EACV,cAAc,GACf,EAAE,uBAAuB,GAAG,wBAAwB,CAsKpD"}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useDashboardLayout - 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 MyDashboard() {
|
|
12
|
+
* const [widgets, setWidgets] = useState<WidgetLayout[]>([]);
|
|
13
|
+
* const gridConfig: GridConfig = { columns: 12, cellSize: 50, gap: 16 };
|
|
14
|
+
*
|
|
15
|
+
* const {
|
|
16
|
+
* getWidgetGridPosition,
|
|
17
|
+
* moveWidget,
|
|
18
|
+
* resizeWidget,
|
|
19
|
+
* findNextAvailablePosition,
|
|
20
|
+
* } = useDashboardLayout({
|
|
21
|
+
* widgetsLayout: widgets,
|
|
22
|
+
* gridConfig,
|
|
23
|
+
* onUpdateLayout: setWidgets,
|
|
24
|
+
* });
|
|
25
|
+
*
|
|
26
|
+
* return (
|
|
27
|
+
* <div>
|
|
28
|
+
* {widgets.map(widget => (
|
|
29
|
+
* <div style={getWidgetGridPosition(widget)}>
|
|
30
|
+
* Widget Content
|
|
31
|
+
* </div>
|
|
32
|
+
* ))}
|
|
33
|
+
* </div>
|
|
34
|
+
* );
|
|
35
|
+
* }
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
import { useCallback, useMemo } from "react";
|
|
39
|
+
const DEFAULT_GRID_CONFIG = {
|
|
40
|
+
columns: 12,
|
|
41
|
+
cellSize: 50,
|
|
42
|
+
gap: 16,
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Hook para gerenciar layout do dashboard
|
|
46
|
+
*
|
|
47
|
+
* Hook headless que fornece apenas lógica de layout, sem UI.
|
|
48
|
+
* Você controla o markup e styles.
|
|
49
|
+
*/
|
|
50
|
+
export function useDashboardLayout({ widgetsLayout, gridConfig, onUpdateLayout, }) {
|
|
51
|
+
// Normaliza gridConfig com defaults
|
|
52
|
+
const normalizedGridConfig = useMemo(() => {
|
|
53
|
+
return {
|
|
54
|
+
...DEFAULT_GRID_CONFIG,
|
|
55
|
+
...gridConfig,
|
|
56
|
+
};
|
|
57
|
+
}, [gridConfig]);
|
|
58
|
+
/**
|
|
59
|
+
* Calcula posição CSS Grid para um widget
|
|
60
|
+
*/
|
|
61
|
+
const getWidgetGridPosition = useCallback((widget) => {
|
|
62
|
+
return {
|
|
63
|
+
gridColumnStart: widget.x + 1, // CSS Grid é 1-indexed
|
|
64
|
+
gridColumnEnd: widget.x + widget.w + 1,
|
|
65
|
+
gridRowStart: widget.y + 1,
|
|
66
|
+
gridRowEnd: widget.y + widget.h + 1,
|
|
67
|
+
};
|
|
68
|
+
}, []);
|
|
69
|
+
/**
|
|
70
|
+
* Verifica se uma posição está ocupada
|
|
71
|
+
*/
|
|
72
|
+
const isPositionOccupied = useCallback((x, y, w, h, excludeWidgetId) => {
|
|
73
|
+
return widgetsLayout.some((widget) => {
|
|
74
|
+
if (excludeWidgetId && widget.id === excludeWidgetId) {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
// Verifica sobreposição
|
|
78
|
+
const widgetRight = widget.x + widget.w;
|
|
79
|
+
const widgetBottom = widget.y + widget.h;
|
|
80
|
+
const newRight = x + w;
|
|
81
|
+
const newBottom = y + h;
|
|
82
|
+
return !(widgetRight <= x ||
|
|
83
|
+
widget.x >= newRight ||
|
|
84
|
+
widgetBottom <= y ||
|
|
85
|
+
widget.y >= newBottom);
|
|
86
|
+
});
|
|
87
|
+
}, [widgetsLayout]);
|
|
88
|
+
/**
|
|
89
|
+
* Encontra próxima posição disponível
|
|
90
|
+
*/
|
|
91
|
+
const findNextAvailablePosition = useCallback((w, h) => {
|
|
92
|
+
const maxColumns = normalizedGridConfig.columns;
|
|
93
|
+
const maxRows = 100; // Limite razoável
|
|
94
|
+
for (let y = 0; y < maxRows; y++) {
|
|
95
|
+
for (let x = 0; x <= maxColumns - w; x++) {
|
|
96
|
+
if (!isPositionOccupied(x, y, w, h)) {
|
|
97
|
+
return { x, y };
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return null;
|
|
102
|
+
}, [normalizedGridConfig.columns, isPositionOccupied]);
|
|
103
|
+
/**
|
|
104
|
+
* Valida se um widget pode ser movido para uma posição
|
|
105
|
+
*/
|
|
106
|
+
const canMoveToPosition = useCallback((widgetId, x, y) => {
|
|
107
|
+
const widget = widgetsLayout.find((w) => w.id === widgetId);
|
|
108
|
+
if (!widget)
|
|
109
|
+
return false;
|
|
110
|
+
// Valida limites do grid
|
|
111
|
+
if (x < 0 || y < 0)
|
|
112
|
+
return false;
|
|
113
|
+
if (x + widget.w > normalizedGridConfig.columns)
|
|
114
|
+
return false;
|
|
115
|
+
// Verifica colisões
|
|
116
|
+
return !isPositionOccupied(x, y, widget.w, widget.h, widgetId);
|
|
117
|
+
}, [widgetsLayout, normalizedGridConfig.columns, isPositionOccupied]);
|
|
118
|
+
/**
|
|
119
|
+
* Valida se um widget pode ser redimensionado
|
|
120
|
+
*/
|
|
121
|
+
const canResize = useCallback((widgetId, newW, newH) => {
|
|
122
|
+
const widget = widgetsLayout.find((w) => w.id === widgetId);
|
|
123
|
+
if (!widget)
|
|
124
|
+
return false;
|
|
125
|
+
// Valida tamanhos mínimos e máximos
|
|
126
|
+
if (newW < 2 || newH < 2)
|
|
127
|
+
return false; // Mínimo 2x2
|
|
128
|
+
if (newW > normalizedGridConfig.columns)
|
|
129
|
+
return false;
|
|
130
|
+
if (newH > 20)
|
|
131
|
+
return false; // Máximo 20 linhas
|
|
132
|
+
// Valida limites do grid
|
|
133
|
+
if (widget.x + newW > normalizedGridConfig.columns)
|
|
134
|
+
return false;
|
|
135
|
+
// Verifica colisões
|
|
136
|
+
return !isPositionOccupied(widget.x, widget.y, newW, newH, widgetId);
|
|
137
|
+
}, [widgetsLayout, normalizedGridConfig.columns, isPositionOccupied]);
|
|
138
|
+
/**
|
|
139
|
+
* Move widget para nova posição
|
|
140
|
+
*/
|
|
141
|
+
const moveWidget = useCallback((widgetId, x, y) => {
|
|
142
|
+
if (!canMoveToPosition(widgetId, x, y)) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
const updatedLayout = widgetsLayout.map((widget) => widget.id === widgetId ? { ...widget, x, y } : widget);
|
|
146
|
+
onUpdateLayout(updatedLayout);
|
|
147
|
+
}, [widgetsLayout, canMoveToPosition, onUpdateLayout]);
|
|
148
|
+
/**
|
|
149
|
+
* Redimensiona widget
|
|
150
|
+
*/
|
|
151
|
+
const resizeWidget = useCallback((widgetId, w, h) => {
|
|
152
|
+
if (!canResize(widgetId, w, h)) {
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
const updatedLayout = widgetsLayout.map((widget) => widget.id === widgetId ? { ...widget, w, h } : widget);
|
|
156
|
+
onUpdateLayout(updatedLayout);
|
|
157
|
+
}, [widgetsLayout, canResize, onUpdateLayout]);
|
|
158
|
+
/**
|
|
159
|
+
* Atualiza layout completo
|
|
160
|
+
*/
|
|
161
|
+
const updateLayout = useCallback((layout) => {
|
|
162
|
+
onUpdateLayout(layout);
|
|
163
|
+
}, [onUpdateLayout]);
|
|
164
|
+
return {
|
|
165
|
+
gridConfig: normalizedGridConfig,
|
|
166
|
+
getWidgetGridPosition,
|
|
167
|
+
isPositionOccupied,
|
|
168
|
+
findNextAvailablePosition,
|
|
169
|
+
canMoveToPosition,
|
|
170
|
+
canResize,
|
|
171
|
+
moveWidget,
|
|
172
|
+
resizeWidget,
|
|
173
|
+
updateLayout,
|
|
174
|
+
};
|
|
175
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
* para projetos React/TypeScript
|
|
6
6
|
*/
|
|
7
7
|
export * from "./hooks/useAnimatedIndicator";
|
|
8
|
+
export * from "./hooks/useAutocomplete";
|
|
9
|
+
export * from "./hooks/useDashboardLayout";
|
|
8
10
|
export * from "./hooks/useGenealogy";
|
|
9
11
|
export * from "./hooks/useMoblile";
|
|
10
12
|
export * from "./hooks/useProjectProgress";
|
|
@@ -15,5 +17,4 @@ export * from "./hooks/useResizable";
|
|
|
15
17
|
export * from "./hooks/useScriptEditor";
|
|
16
18
|
export * from "./hooks/useStatCard";
|
|
17
19
|
export * from "./hooks/useTimeTracker";
|
|
18
|
-
export * from "./hooks/useAutocomplete";
|
|
19
20
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,8BAA8B,CAAC;AAC7C,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,yBAAyB,CAAC;AACxC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,sBAAsB,CAAC;AAErC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,8BAA8B,CAAC;AAC7C,cAAc,yBAAyB,CAAC;AACxC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,yBAAyB,CAAC;AACxC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,sBAAsB,CAAC;AAErC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
* para projetos React/TypeScript
|
|
6
6
|
*/
|
|
7
7
|
export * from "./hooks/useAnimatedIndicator";
|
|
8
|
+
export * from "./hooks/useAutocomplete";
|
|
9
|
+
export * from "./hooks/useDashboardLayout";
|
|
8
10
|
export * from "./hooks/useGenealogy";
|
|
9
11
|
export * from "./hooks/useMoblile";
|
|
10
12
|
export * from "./hooks/useProjectProgress";
|
|
@@ -16,4 +18,3 @@ export * from "./hooks/useResizable";
|
|
|
16
18
|
export * from "./hooks/useScriptEditor";
|
|
17
19
|
export * from "./hooks/useStatCard";
|
|
18
20
|
export * from "./hooks/useTimeTracker";
|
|
19
|
-
export * from "./hooks/useAutocomplete";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flowtomic/logic",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Hooks headless e lógica reutilizável para React",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"license": "MIT",
|
|
28
28
|
"scripts": {
|
|
29
29
|
"dev": "bun run --watch src/index.ts",
|
|
30
|
-
"build": "tsc --emitDeclarationOnly && bun build ./src/index.ts --outdir ./dist --target browser --format esm --minify --external react --external react/jsx-runtime",
|
|
30
|
+
"build": "biome check . && tsc --emitDeclarationOnly && bun build ./src/index.ts --outdir ./dist --target browser --format esm --minify --external react --external react/jsx-runtime",
|
|
31
31
|
"type-check": "tsc --noEmit",
|
|
32
32
|
"clean": "rm -rf dist",
|
|
33
33
|
"lint": "biome check .",
|