@bouko/react 2.3.8 → 2.4.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.
@@ -1,9 +1 @@
1
- import type { SetState } from "./types";
2
- export declare const useForm: <T>(init: Partial<T>) => {
3
- data: Partial<T>;
4
- update: import("react").Dispatch<import("react").SetStateAction<Partial<T>>>;
5
- clear: () => void;
6
- setField: (name: string, value: unknown) => void;
7
- };
8
- export declare const setField: <T>(update: SetState<T>, id: string, value: unknown) => void;
9
- export declare const parseData: <T extends Record<string, unknown>>(data: T) => T;
1
+ export declare const parseData: <T extends Record<string, unknown>>(data: T) => T;
@@ -1,47 +1,28 @@
1
- "use client";
2
- import { useState, useEffect, useMemo } from "react";
3
- export const useForm = (init) => {
4
- const initial = useMemo(() => init, [JSON.stringify(init)]); // deep compare
5
- const [data, setData] = useState(initial);
6
- useEffect(() => {
7
- setData(initial);
8
- }, [initial]);
9
- return {
10
- data,
11
- update: setData,
12
- clear: () => setData(initial),
13
- setField: (name, value) => setField(setData, name, value)
14
- };
15
- };
16
- export const setField = (update, id, value) => update(prev => ({
17
- ...prev,
18
- [id]: value
19
- }));
20
- export const parseData = (data) => {
21
- const copy = JSON.parse(JSON.stringify(data));
22
- for (const [key, value] of Object.entries(data)) {
23
- if (key === "created_at")
24
- copy[key] = new Date(value);
25
- else if (key === "timestamp")
26
- copy[key] = new Date(value.replaceAll("'", ""));
27
- else if (parseAllowedDate(value))
28
- copy[key] = new Date(value);
29
- }
30
- return copy;
31
- };
32
- function parseAllowedDate(input) {
33
- // ISO 8601 strict (YYYY-MM-DD or YYYY-MM-DDTHH:mm:ss+hh:mm)
34
- const isoStrictRegex = /^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}(:\d{2}(\.\d{1,3})?)?(Z|[+-]\d{2}:\d{2}))?$/;
35
- // MySQL/Postgres style with space + offset without colon (YYYY-MM-DD HH:mm:ss+hhmm)
36
- const spaceOffsetRegex = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}[+-]\d{4}$/;
37
- let normalized = input;
38
- if (spaceOffsetRegex.test(input)) {
39
- // Convert to ISO by replacing space with T and adding colon in offset
40
- normalized = input.replace(" ", "T").replace(/([+-]\d{2})(\d{2})$/, "$1:$2");
41
- }
42
- else if (!isoStrictRegex.test(input)) {
43
- return null; // Not allowed format
44
- }
45
- const date = new Date(normalized);
46
- return !isNaN(date.getTime()) ? date : null;
47
- }
1
+ export const parseData = (data) => {
2
+ const copy = JSON.parse(JSON.stringify(data));
3
+ for (const [key, value] of Object.entries(data)) {
4
+ if (key === "created_at")
5
+ copy[key] = new Date(value);
6
+ else if (key === "timestamp")
7
+ copy[key] = new Date(value.replaceAll("'", ""));
8
+ else if (parseAllowedDate(value))
9
+ copy[key] = new Date(value);
10
+ }
11
+ return copy;
12
+ };
13
+ function parseAllowedDate(input) {
14
+ // ISO 8601 strict (YYYY-MM-DD or YYYY-MM-DDTHH:mm:ss+hh:mm)
15
+ const isoStrictRegex = /^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}(:\d{2}(\.\d{1,3})?)?(Z|[+-]\d{2}:\d{2}))?$/;
16
+ // MySQL/Postgres style with space + offset without colon (YYYY-MM-DD HH:mm:ss+hhmm)
17
+ const spaceOffsetRegex = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}[+-]\d{4}$/;
18
+ let normalized = input;
19
+ if (spaceOffsetRegex.test(input)) {
20
+ // Convert to ISO by replacing space with T and adding colon in offset
21
+ normalized = input.replace(" ", "T").replace(/([+-]\d{2})(\d{2})$/, "$1:$2");
22
+ }
23
+ else if (!isoStrictRegex.test(input)) {
24
+ return null; // Not allowed format
25
+ }
26
+ const date = new Date(normalized);
27
+ return !isNaN(date.getTime()) ? date : null;
28
+ }
@@ -1 +1,8 @@
1
- export default function useInterval(action: () => Promise<boolean | void>, delay: number, deps?: unknown[]): void;
1
+ declare type Props = {
2
+ action: () => Promise<boolean | void>;
3
+ duration: number;
4
+ deps: unknown[];
5
+ oops?: (x: string) => void;
6
+ };
7
+ export default function useInterval({ action, duration, deps, oops }: Props): void;
8
+ export {};
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { useEffect, useRef } from "react";
3
- export default function useInterval(action, delay, deps = []) {
3
+ export default function useInterval({ action, duration, deps = [], oops }) {
4
4
  const ref = useRef(async () => false);
5
5
  useEffect(() => {
6
6
  ref.current = action;
@@ -9,12 +9,17 @@ export default function useInterval(action, delay, deps = []) {
9
9
  if (deps.some(v => v === undefined || v === null))
10
10
  return;
11
11
  const tick = async () => {
12
- const stop = await ref.current();
13
- if (stop && id)
14
- clearInterval(id);
12
+ try {
13
+ const stop = await ref.current();
14
+ if (stop && id)
15
+ clearInterval(id);
16
+ }
17
+ catch (err) {
18
+ oops?.(err.message);
19
+ }
15
20
  };
16
- const id = setInterval(tick, delay);
21
+ const id = setInterval(tick, duration);
17
22
  tick();
18
23
  return () => clearInterval(id);
19
- }, [delay, ...deps]);
24
+ }, [duration, ...deps]);
20
25
  }
package/dist/index.d.ts CHANGED
@@ -11,4 +11,5 @@ export * from "./components/search-bar";
11
11
  export * from "./core/types";
12
12
  export * from "./core/functions";
13
13
  export * from "./core/format";
14
+ export * from "./components/form/functions";
14
15
  export * from "./hooks";
package/dist/index.js CHANGED
@@ -11,4 +11,5 @@ export * from "./components/search-bar";
11
11
  export * from "./core/types";
12
12
  export * from "./core/functions";
13
13
  export * from "./core/format";
14
+ export * from "./components/form/functions";
14
15
  export * from "./hooks";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
 
3
3
  "name": "@bouko/react",
4
- "version": "2.3.8",
4
+ "version": "2.4.0",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
7
7
  "license": "MIT",