@flowtomic/logic 0.1.0 → 0.1.1
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/useAnimatedIndicator/index.d.ts +3 -0
- package/dist/hooks/useAnimatedIndicator/index.d.ts.map +1 -0
- package/dist/hooks/useAnimatedIndicator/index.js +1 -0
- package/dist/hooks/useAnimatedIndicator/useAnimatedIndicator.d.ts +94 -0
- package/dist/hooks/useAnimatedIndicator/useAnimatedIndicator.d.ts.map +1 -0
- package/dist/hooks/useAnimatedIndicator/useAnimatedIndicator.js +228 -0
- package/dist/hooks/useGenealogy/index.d.ts +3 -0
- package/dist/hooks/useGenealogy/index.d.ts.map +1 -0
- package/dist/hooks/useGenealogy/index.js +1 -0
- package/dist/hooks/useGenealogy/useGenealogy.d.ts +96 -0
- package/dist/hooks/useGenealogy/useGenealogy.d.ts.map +1 -0
- package/dist/hooks/useGenealogy/useGenealogy.js +335 -0
- package/dist/hooks/useMoblile/index.js +1 -868
- package/dist/hooks/useProjectProgress/index.d.ts +3 -0
- package/dist/hooks/useProjectProgress/index.d.ts.map +1 -0
- package/dist/hooks/useProjectProgress/index.js +1 -0
- package/dist/hooks/useProjectProgress/useProjectProgress.d.ts +103 -0
- package/dist/hooks/useProjectProgress/useProjectProgress.d.ts.map +1 -0
- package/dist/hooks/useProjectProgress/useProjectProgress.js +124 -0
- package/dist/hooks/useProjectStats/index.d.ts +3 -0
- package/dist/hooks/useProjectStats/index.d.ts.map +1 -0
- package/dist/hooks/useProjectStats/index.js +1 -0
- package/dist/hooks/useProjectStats/useProjectStats.d.ts +130 -0
- package/dist/hooks/useProjectStats/useProjectStats.d.ts.map +1 -0
- package/dist/hooks/useProjectStats/useProjectStats.js +87 -0
- package/dist/hooks/useResizable/index.d.ts +1 -1
- package/dist/hooks/useResizable/index.d.ts.map +1 -1
- package/dist/hooks/useStatCard/useStatCard.d.ts +44 -5
- package/dist/hooks/useStatCard/useStatCard.d.ts.map +1 -1
- package/dist/hooks/useStatCard/useStatCard.js +81 -20
- package/dist/hooks/useTimeTracker/index.d.ts +3 -0
- package/dist/hooks/useTimeTracker/index.d.ts.map +1 -0
- package/dist/hooks/useTimeTracker/index.js +1 -0
- package/dist/hooks/useTimeTracker/useTimeTracker.d.ts +106 -0
- package/dist/hooks/useTimeTracker/useTimeTracker.d.ts.map +1 -0
- package/dist/hooks/useTimeTracker/useTimeTracker.js +143 -0
- package/dist/index.d.ts +7 -2
- package/dist/index.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -8,11 +8,11 @@
|
|
|
8
8
|
*
|
|
9
9
|
* @example
|
|
10
10
|
* ```tsx
|
|
11
|
+
* // Cálculo automático do delta a partir de lastMonth
|
|
11
12
|
* function MyCustomStatCard() {
|
|
12
13
|
* const { formattedValue, trend, getCardProps } = useStatCard({
|
|
13
14
|
* value: 122380,
|
|
14
|
-
* delta: 15.
|
|
15
|
-
* lastMonth: 105922,
|
|
15
|
+
* lastMonth: 105922, // delta será calculado automaticamente: +15.5%
|
|
16
16
|
* })
|
|
17
17
|
*
|
|
18
18
|
* return (
|
|
@@ -22,23 +22,48 @@
|
|
|
22
22
|
* </div>
|
|
23
23
|
* )
|
|
24
24
|
* }
|
|
25
|
+
*
|
|
26
|
+
* // Ou forneça delta explicitamente para casos especiais
|
|
27
|
+
* function CustomDeltaCard() {
|
|
28
|
+
* const { formattedValue, trend } = useStatCard({
|
|
29
|
+
* value: 122380,
|
|
30
|
+
* delta: 15.1, // delta explícito tem prioridade
|
|
31
|
+
* lastMonth: 105922,
|
|
32
|
+
* })
|
|
33
|
+
* }
|
|
25
34
|
* ```
|
|
26
35
|
*/
|
|
27
36
|
import { useCallback, useMemo } from "react";
|
|
28
37
|
/**
|
|
29
|
-
* Formata um número seguindo padrões comuns
|
|
30
|
-
* - Valores >= 1.000.000: formata como "X.XM"
|
|
31
|
-
* - Valores >= 1.000: formata com separador de milhares
|
|
32
|
-
* - Valores < 1.000: retorna
|
|
38
|
+
* Formata um número seguindo padrões comuns com suporte a locale
|
|
39
|
+
* - Valores >= 1.000.000: formata como "X.XM" (respeitando locale para decimais)
|
|
40
|
+
* - Valores >= 1.000: formata com separador de milhares conforme locale
|
|
41
|
+
* - Valores < 1.000: retorna formatado conforme locale
|
|
33
42
|
*/
|
|
34
|
-
function formatNumberDefault(n) {
|
|
43
|
+
function formatNumberDefault(n, locale = "pt-BR") {
|
|
35
44
|
if (n >= 1_000_000) {
|
|
36
|
-
|
|
45
|
+
const formatter = new Intl.NumberFormat(locale, {
|
|
46
|
+
minimumFractionDigits: 1,
|
|
47
|
+
maximumFractionDigits: 1,
|
|
48
|
+
});
|
|
49
|
+
return `${formatter.format(n / 1_000_000)}M`;
|
|
37
50
|
}
|
|
38
51
|
if (n >= 1_000) {
|
|
39
|
-
return
|
|
52
|
+
return new Intl.NumberFormat(locale).format(n);
|
|
40
53
|
}
|
|
41
|
-
return
|
|
54
|
+
return new Intl.NumberFormat(locale).format(n);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Formata um número como moeda usando locale
|
|
58
|
+
*/
|
|
59
|
+
function formatCurrency(n, locale = "pt-BR", currency = "BRL", currencyDisplay = "symbol") {
|
|
60
|
+
return new Intl.NumberFormat(locale, {
|
|
61
|
+
style: "currency",
|
|
62
|
+
currency,
|
|
63
|
+
currencyDisplay,
|
|
64
|
+
minimumFractionDigits: 0,
|
|
65
|
+
maximumFractionDigits: 2,
|
|
66
|
+
}).format(n);
|
|
42
67
|
}
|
|
43
68
|
/**
|
|
44
69
|
* Hook Headless UI para StatCard
|
|
@@ -48,11 +73,11 @@ function formatNumberDefault(n) {
|
|
|
48
73
|
*
|
|
49
74
|
* @example
|
|
50
75
|
* ```tsx
|
|
76
|
+
* // Cálculo automático do delta a partir de lastMonth
|
|
51
77
|
* function MyCustomStatCard() {
|
|
52
78
|
* const { formattedValue, trend, getCardProps } = useStatCard({
|
|
53
79
|
* value: 122380,
|
|
54
|
-
* delta: 15.
|
|
55
|
-
* lastMonth: 105922,
|
|
80
|
+
* lastMonth: 105922, // delta será calculado automaticamente: +15.5%
|
|
56
81
|
* })
|
|
57
82
|
*
|
|
58
83
|
* return (
|
|
@@ -62,10 +87,32 @@ function formatNumberDefault(n) {
|
|
|
62
87
|
* </div>
|
|
63
88
|
* )
|
|
64
89
|
* }
|
|
90
|
+
*
|
|
91
|
+
* // Ou forneça delta explicitamente para casos especiais
|
|
92
|
+
* function CustomDeltaCard() {
|
|
93
|
+
* const { formattedValue, trend } = useStatCard({
|
|
94
|
+
* value: 122380,
|
|
95
|
+
* delta: 15.1, // delta explícito tem prioridade
|
|
96
|
+
* lastMonth: 105922,
|
|
97
|
+
* })
|
|
98
|
+
* }
|
|
65
99
|
* ```
|
|
66
100
|
*/
|
|
67
101
|
export function useStatCard(data) {
|
|
68
|
-
const { value, delta
|
|
102
|
+
const { value, delta: explicitDelta, lastMonth, prefix = "", suffix = "", locale = "pt-BR", currency, currencyDisplay = "symbol", format, lastFormat, positive: explicitPositive, } = data;
|
|
103
|
+
// Calcula delta automaticamente se não fornecido mas lastMonth estiver disponível
|
|
104
|
+
const delta = useMemo(() => {
|
|
105
|
+
// Se delta foi fornecido explicitamente, usa ele (prioridade)
|
|
106
|
+
if (explicitDelta !== undefined) {
|
|
107
|
+
return explicitDelta;
|
|
108
|
+
}
|
|
109
|
+
// Se lastMonth foi fornecido, calcula o delta automaticamente
|
|
110
|
+
if (lastMonth !== undefined && lastMonth !== 0) {
|
|
111
|
+
return ((Number(value) - Number(lastMonth)) / Number(lastMonth)) * 100;
|
|
112
|
+
}
|
|
113
|
+
// Caso contrário, retorna 0
|
|
114
|
+
return 0;
|
|
115
|
+
}, [value, lastMonth, explicitDelta]);
|
|
69
116
|
// Calcula se a tendência é positiva
|
|
70
117
|
const isPositive = useMemo(() => {
|
|
71
118
|
if (explicitPositive !== undefined) {
|
|
@@ -89,10 +136,16 @@ export function useStatCard(data) {
|
|
|
89
136
|
// Formata o valor principal
|
|
90
137
|
const formattedValue = useMemo(() => {
|
|
91
138
|
if (format) {
|
|
92
|
-
return format(value);
|
|
139
|
+
return format(Number(value));
|
|
140
|
+
}
|
|
141
|
+
const numValue = Number(value);
|
|
142
|
+
if (currency) {
|
|
143
|
+
// Se currency está definido, usa formatação de moeda (ignora prefix)
|
|
144
|
+
return (formatCurrency(numValue, locale, currency, currencyDisplay) + (suffix ? ` ${suffix}` : ""));
|
|
93
145
|
}
|
|
94
|
-
|
|
95
|
-
|
|
146
|
+
// Caso contrário, usa formatação numérica padrão com prefix/suffix
|
|
147
|
+
return prefix + formatNumberDefault(numValue, locale) + suffix;
|
|
148
|
+
}, [value, prefix, suffix, locale, currency, currencyDisplay, format]);
|
|
96
149
|
// Formata o valor do mês anterior
|
|
97
150
|
const formattedLastMonth = useMemo(() => {
|
|
98
151
|
if (!lastMonth)
|
|
@@ -100,8 +153,13 @@ export function useStatCard(data) {
|
|
|
100
153
|
if (lastFormat) {
|
|
101
154
|
return lastFormat(lastMonth);
|
|
102
155
|
}
|
|
103
|
-
|
|
104
|
-
|
|
156
|
+
if (currency) {
|
|
157
|
+
// Se currency está definido, usa formatação de moeda (ignora prefix)
|
|
158
|
+
return formatCurrency(lastMonth, locale, currency, currencyDisplay);
|
|
159
|
+
}
|
|
160
|
+
// Caso contrário, usa formatação numérica padrão com prefix/suffix
|
|
161
|
+
return prefix + formatNumberDefault(lastMonth, locale) + suffix;
|
|
162
|
+
}, [lastMonth, prefix, suffix, locale, currency, currencyDisplay, lastFormat]);
|
|
105
163
|
// Props helper para o card
|
|
106
164
|
const getCardProps = useCallback((props = {}) => {
|
|
107
165
|
return {
|
|
@@ -113,8 +171,11 @@ export function useStatCard(data) {
|
|
|
113
171
|
}, [formattedValue]);
|
|
114
172
|
// Função utilitária de formatação
|
|
115
173
|
const formatNumber = useCallback((n) => {
|
|
116
|
-
|
|
117
|
-
|
|
174
|
+
if (currency) {
|
|
175
|
+
return formatCurrency(n, locale, currency, currencyDisplay);
|
|
176
|
+
}
|
|
177
|
+
return formatNumberDefault(n, locale);
|
|
178
|
+
}, [locale, currency, currencyDisplay]);
|
|
118
179
|
return {
|
|
119
180
|
formattedValue,
|
|
120
181
|
formattedLastMonth,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/hooks/useTimeTracker/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACpF,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useTimeTracker } from "./useTimeTracker";
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useTimeTracker - 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 MyTimer() {
|
|
12
|
+
* const { time, formattedTime, isRunning, start, pause, stop, reset } = useTimeTracker({
|
|
13
|
+
* initialTime: 0,
|
|
14
|
+
* })
|
|
15
|
+
*
|
|
16
|
+
* return (
|
|
17
|
+
* <div>
|
|
18
|
+
* <span>{formattedTime}</span>
|
|
19
|
+
* <button onClick={start}>Start</button>
|
|
20
|
+
* <button onClick={pause}>Pause</button>
|
|
21
|
+
* <button onClick={stop}>Stop</button>
|
|
22
|
+
* <button onClick={reset}>Reset</button>
|
|
23
|
+
* </div>
|
|
24
|
+
* )
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export interface UseTimeTrackerOptions {
|
|
29
|
+
/**
|
|
30
|
+
* Tempo inicial em segundos
|
|
31
|
+
* @default 0
|
|
32
|
+
*/
|
|
33
|
+
initialTime?: number;
|
|
34
|
+
/**
|
|
35
|
+
* Callback quando o timer é pausado
|
|
36
|
+
*/
|
|
37
|
+
onPause?: (time: number) => void;
|
|
38
|
+
/**
|
|
39
|
+
* Callback quando o timer é parado
|
|
40
|
+
*/
|
|
41
|
+
onStop?: (time: number) => void;
|
|
42
|
+
/**
|
|
43
|
+
* Callback quando o timer é iniciado
|
|
44
|
+
*/
|
|
45
|
+
onStart?: (time: number) => void;
|
|
46
|
+
/**
|
|
47
|
+
* Callback quando o timer é retomado
|
|
48
|
+
*/
|
|
49
|
+
onResume?: (time: number) => void;
|
|
50
|
+
/**
|
|
51
|
+
* Callback quando o timer é resetado
|
|
52
|
+
*/
|
|
53
|
+
onReset?: () => void;
|
|
54
|
+
/**
|
|
55
|
+
* Formato de tempo customizado
|
|
56
|
+
* @default "HH:mm:ss"
|
|
57
|
+
*/
|
|
58
|
+
format?: "HH:mm:ss" | "mm:ss" | "ss" | ((seconds: number) => string);
|
|
59
|
+
}
|
|
60
|
+
export interface UseTimeTrackerReturn {
|
|
61
|
+
/**
|
|
62
|
+
* Tempo atual em segundos
|
|
63
|
+
*/
|
|
64
|
+
time: number;
|
|
65
|
+
/**
|
|
66
|
+
* Tempo formatado como string (HH:mm:ss por padrão)
|
|
67
|
+
*/
|
|
68
|
+
formattedTime: string;
|
|
69
|
+
/**
|
|
70
|
+
* Se o timer está rodando
|
|
71
|
+
*/
|
|
72
|
+
isRunning: boolean;
|
|
73
|
+
/**
|
|
74
|
+
* Se o timer está pausado
|
|
75
|
+
*/
|
|
76
|
+
isPaused: boolean;
|
|
77
|
+
/**
|
|
78
|
+
* Se o timer está parado (não iniciado ou resetado)
|
|
79
|
+
*/
|
|
80
|
+
isStopped: boolean;
|
|
81
|
+
/**
|
|
82
|
+
* Inicia o timer
|
|
83
|
+
*/
|
|
84
|
+
start: () => void;
|
|
85
|
+
/**
|
|
86
|
+
* Pausa o timer
|
|
87
|
+
*/
|
|
88
|
+
pause: () => void;
|
|
89
|
+
/**
|
|
90
|
+
* Para o timer (pausa e mantém o tempo)
|
|
91
|
+
*/
|
|
92
|
+
stop: () => void;
|
|
93
|
+
/**
|
|
94
|
+
* Retoma o timer após pausa
|
|
95
|
+
*/
|
|
96
|
+
resume: () => void;
|
|
97
|
+
/**
|
|
98
|
+
* Reseta o timer para o tempo inicial
|
|
99
|
+
*/
|
|
100
|
+
reset: () => void;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Hook headless para gerenciar timer
|
|
104
|
+
*/
|
|
105
|
+
export declare function useTimeTracker(options?: UseTimeTrackerOptions): UseTimeTrackerReturn;
|
|
106
|
+
//# sourceMappingURL=useTimeTracker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useTimeTracker.d.ts","sourceRoot":"","sources":["../../../src/hooks/useTimeTracker/useTimeTracker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAIH,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAEjC;;OAEG;IACH,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAEhC;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAEjC;;OAEG;IACH,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAElC;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IAErB;;;OAGG;IACH,MAAM,CAAC,EAAE,UAAU,GAAG,OAAO,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC,CAAC;CACtE;AAED,MAAM,WAAW,oBAAoB;IACnC;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,aAAa,EAAE,MAAM,CAAC;IAEtB;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC;IAEnB;;OAEG;IACH,QAAQ,EAAE,OAAO,CAAC;IAElB;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC;IAEnB;;OAEG;IACH,KAAK,EAAE,MAAM,IAAI,CAAC;IAElB;;OAEG;IACH,KAAK,EAAE,MAAM,IAAI,CAAC;IAElB;;OAEG;IACH,IAAI,EAAE,MAAM,IAAI,CAAC;IAEjB;;OAEG;IACH,MAAM,EAAE,MAAM,IAAI,CAAC;IAEnB;;OAEG;IACH,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,GAAE,qBAA0B,GAAG,oBAAoB,CAyIxF"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useTimeTracker - 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 MyTimer() {
|
|
12
|
+
* const { time, formattedTime, isRunning, start, pause, stop, reset } = useTimeTracker({
|
|
13
|
+
* initialTime: 0,
|
|
14
|
+
* })
|
|
15
|
+
*
|
|
16
|
+
* return (
|
|
17
|
+
* <div>
|
|
18
|
+
* <span>{formattedTime}</span>
|
|
19
|
+
* <button onClick={start}>Start</button>
|
|
20
|
+
* <button onClick={pause}>Pause</button>
|
|
21
|
+
* <button onClick={stop}>Stop</button>
|
|
22
|
+
* <button onClick={reset}>Reset</button>
|
|
23
|
+
* </div>
|
|
24
|
+
* )
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
29
|
+
/**
|
|
30
|
+
* Hook headless para gerenciar timer
|
|
31
|
+
*/
|
|
32
|
+
export function useTimeTracker(options = {}) {
|
|
33
|
+
const { initialTime = 0, onPause, onStop, onStart, onResume, onReset, format = "HH:mm:ss", } = options;
|
|
34
|
+
const [time, setTime] = useState(initialTime);
|
|
35
|
+
const [isRunning, setIsRunning] = useState(false);
|
|
36
|
+
const [isPaused, setIsPaused] = useState(false);
|
|
37
|
+
const intervalRef = useRef(null);
|
|
38
|
+
const startTimeRef = useRef(null);
|
|
39
|
+
const pausedTimeRef = useRef(0);
|
|
40
|
+
// Limpar intervalo ao desmontar
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
return () => {
|
|
43
|
+
if (intervalRef.current) {
|
|
44
|
+
clearInterval(intervalRef.current);
|
|
45
|
+
intervalRef.current = null;
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
}, []);
|
|
49
|
+
// Formatar tempo
|
|
50
|
+
const formatTime = useCallback((seconds) => {
|
|
51
|
+
if (typeof format === "function") {
|
|
52
|
+
return format(seconds);
|
|
53
|
+
}
|
|
54
|
+
const hours = Math.floor(seconds / 3600);
|
|
55
|
+
const minutes = Math.floor((seconds % 3600) / 60);
|
|
56
|
+
const secs = seconds % 60;
|
|
57
|
+
switch (format) {
|
|
58
|
+
case "HH:mm:ss":
|
|
59
|
+
return `${String(hours).padStart(2, "0")}:${String(minutes).padStart(2, "0")}:${String(secs).padStart(2, "0")}`;
|
|
60
|
+
case "mm:ss":
|
|
61
|
+
return `${String(minutes).padStart(2, "0")}:${String(secs).padStart(2, "0")}`;
|
|
62
|
+
case "ss":
|
|
63
|
+
return String(seconds);
|
|
64
|
+
default:
|
|
65
|
+
return `${String(hours).padStart(2, "0")}:${String(minutes).padStart(2, "0")}:${String(secs).padStart(2, "0")}`;
|
|
66
|
+
}
|
|
67
|
+
}, [format]);
|
|
68
|
+
const formattedTime = formatTime(time);
|
|
69
|
+
// Limpar intervalo
|
|
70
|
+
const clearTimerInterval = useCallback(() => {
|
|
71
|
+
if (intervalRef.current) {
|
|
72
|
+
clearInterval(intervalRef.current);
|
|
73
|
+
intervalRef.current = null;
|
|
74
|
+
}
|
|
75
|
+
}, []);
|
|
76
|
+
// Iniciar timer
|
|
77
|
+
const start = useCallback(() => {
|
|
78
|
+
if (isRunning)
|
|
79
|
+
return;
|
|
80
|
+
clearTimerInterval();
|
|
81
|
+
// Se estava pausado, continuar de onde parou
|
|
82
|
+
const startFrom = isPaused ? time : initialTime;
|
|
83
|
+
setTime(startFrom);
|
|
84
|
+
setIsRunning(true);
|
|
85
|
+
setIsPaused(false);
|
|
86
|
+
pausedTimeRef.current = startFrom;
|
|
87
|
+
startTimeRef.current = Date.now() - startFrom * 1000;
|
|
88
|
+
intervalRef.current = setInterval(() => {
|
|
89
|
+
const elapsed = Math.floor((Date.now() - (startTimeRef.current || 0)) / 1000);
|
|
90
|
+
setTime(elapsed);
|
|
91
|
+
}, 100);
|
|
92
|
+
if (!isPaused) {
|
|
93
|
+
onStart?.(startFrom);
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
onResume?.(startFrom);
|
|
97
|
+
}
|
|
98
|
+
}, [isRunning, isPaused, time, initialTime, onStart, onResume, clearTimerInterval]);
|
|
99
|
+
// Pausar timer
|
|
100
|
+
const pause = useCallback(() => {
|
|
101
|
+
if (!isRunning)
|
|
102
|
+
return;
|
|
103
|
+
clearTimerInterval();
|
|
104
|
+
setIsRunning(false);
|
|
105
|
+
setIsPaused(true);
|
|
106
|
+
onPause?.(time);
|
|
107
|
+
}, [isRunning, time, onPause, clearTimerInterval]);
|
|
108
|
+
// Parar timer
|
|
109
|
+
const stop = useCallback(() => {
|
|
110
|
+
clearTimerInterval();
|
|
111
|
+
setIsRunning(false);
|
|
112
|
+
setIsPaused(false);
|
|
113
|
+
onStop?.(time);
|
|
114
|
+
}, [time, onStop, clearTimerInterval]);
|
|
115
|
+
// Retomar timer
|
|
116
|
+
const resume = useCallback(() => {
|
|
117
|
+
if (!isPaused)
|
|
118
|
+
return;
|
|
119
|
+
start();
|
|
120
|
+
}, [isPaused, start]);
|
|
121
|
+
// Resetar timer
|
|
122
|
+
const reset = useCallback(() => {
|
|
123
|
+
clearTimerInterval();
|
|
124
|
+
setTime(initialTime);
|
|
125
|
+
setIsRunning(false);
|
|
126
|
+
setIsPaused(false);
|
|
127
|
+
pausedTimeRef.current = 0;
|
|
128
|
+
startTimeRef.current = null;
|
|
129
|
+
onReset?.();
|
|
130
|
+
}, [initialTime, onReset, clearTimerInterval]);
|
|
131
|
+
return {
|
|
132
|
+
time,
|
|
133
|
+
formattedTime,
|
|
134
|
+
isRunning,
|
|
135
|
+
isPaused,
|
|
136
|
+
isStopped: !isRunning && !isPaused,
|
|
137
|
+
start,
|
|
138
|
+
pause,
|
|
139
|
+
stop,
|
|
140
|
+
resume,
|
|
141
|
+
reset,
|
|
142
|
+
};
|
|
143
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -4,9 +4,14 @@
|
|
|
4
4
|
* Biblioteca de hooks headless e lógica reutilizável
|
|
5
5
|
* para projetos React/TypeScript
|
|
6
6
|
*/
|
|
7
|
+
export * from "./hooks/useAnimatedIndicator";
|
|
8
|
+
export * from "./hooks/useGenealogy";
|
|
9
|
+
export * from "./hooks/useMoblile";
|
|
10
|
+
export * from "./hooks/useProjectProgress";
|
|
11
|
+
export * from "./hooks/useProjectStats";
|
|
7
12
|
export * from "./hooks/useReactTableBack";
|
|
8
13
|
export * from "./hooks/useReactTableFront";
|
|
9
|
-
export * from "./hooks/useStatCard/useStatCard";
|
|
10
14
|
export * from "./hooks/useResizable";
|
|
11
|
-
export * from "./hooks/
|
|
15
|
+
export * from "./hooks/useStatCard";
|
|
16
|
+
export * from "./hooks/useTimeTracker";
|
|
12
17
|
//# 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,2BAA2B,CAAC;AAC1C,cAAc,4BAA4B,CAAC;
|
|
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,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flowtomic/logic",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
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": "bun build ./src/index.ts --outdir ./dist --target browser --format esm --minify",
|
|
30
|
+
"build": "tsc --emitDeclarationOnly && bun build ./src/index.ts --outdir ./dist --target browser --format esm --minify",
|
|
31
31
|
"type-check": "tsc --noEmit",
|
|
32
32
|
"clean": "rm -rf dist",
|
|
33
33
|
"lint": "biome check .",
|