@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.
@@ -1 +1 @@
1
- {"version":3,"file":"useAutocomplete.d.ts","sourceRoot":"","sources":["../../../src/hooks/useAutocomplete/useAutocomplete.ts"],"names":[],"mappings":"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"}
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,3 @@
1
+ export type { GridConfig, UseDashboardLayoutProps, UseDashboardLayoutReturn, WidgetLayout, } from "./useDashboardLayout";
2
+ export { useDashboardLayout } from "./useDashboardLayout";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -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
@@ -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;AACvC,cAAc,yBAAyB,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",
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 .",