@jbpark/use-hooks 2.3.0 → 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.
- package/README.ko.md +4 -5
- package/README.md +4 -5
- package/dist/hooks/index.d.mts +1 -0
- package/dist/hooks/index.mjs +1 -0
- package/dist/hooks/use-history-state.d.mts +16 -0
- package/dist/hooks/use-history-state.mjs +79 -0
- package/dist/hooks/use-history-state.mjs.map +1 -0
- package/dist/index.d.mts +2 -1
- package/dist/index.mjs +2 -1
- package/package.json +4 -1
package/README.ko.md
CHANGED
|
@@ -128,12 +128,11 @@ dist/ # 빌드된 라이브러리 (ESM + types)
|
|
|
128
128
|
|
|
129
129
|
## 빌드 및 배포
|
|
130
130
|
|
|
131
|
-
|
|
131
|
+
배포는 [changesets](https://github.com/changesets/changesets)로 완전히 자동화되어 있습니다:
|
|
132
132
|
|
|
133
|
-
-
|
|
134
|
-
- `
|
|
135
|
-
-
|
|
136
|
-
- 이 릴리스 PR을 머지하면 빌드, npm 배포, 태그 생성까지 자동으로 진행됩니다.
|
|
133
|
+
- `main`으로 향하는 PR마다 AI가 변경 내용을 요약한 changeset 파일을 초안으로 작성합니다.
|
|
134
|
+
- `main`에 changeset들이 쌓이면 "Version Packages" PR이 `package.json`의 버전을 승격시키고 `CHANGELOG.md`를 정리합니다.
|
|
135
|
+
- 이 PR을 머지하면 빌드, npm 배포, 태그 생성까지 자동으로 진행됩니다.
|
|
137
136
|
|
|
138
137
|
라이브러리는 다음과 같이 빌드됩니다:
|
|
139
138
|
|
package/README.md
CHANGED
|
@@ -128,12 +128,11 @@ dist/ # Built library (ESM + types)
|
|
|
128
128
|
|
|
129
129
|
## Build & Deployment
|
|
130
130
|
|
|
131
|
-
|
|
131
|
+
Releases are fully automated via [changesets](https://github.com/changesets/changesets):
|
|
132
132
|
|
|
133
|
-
-
|
|
134
|
-
-
|
|
135
|
-
-
|
|
136
|
-
- Merging the release PR builds, publishes to npm, and tags the release.
|
|
133
|
+
- Each PR against `main` gets an AI-drafted changeset file describing its change.
|
|
134
|
+
- Once changesets accumulate on `main`, a "Version Packages" PR bumps `package.json`'s version and consolidates `CHANGELOG.md`.
|
|
135
|
+
- Merging that PR builds, publishes to npm, and tags the release.
|
|
137
136
|
|
|
138
137
|
The library is built as:
|
|
139
138
|
|
package/dist/hooks/index.d.mts
CHANGED
|
@@ -3,6 +3,7 @@ import { useBodyScrollLock } from "./use-body-scroll-lock.mjs";
|
|
|
3
3
|
import { useClickOutside } from "./use-click-outside.mjs";
|
|
4
4
|
import { useElementPosition } from "./use-element-position.mjs";
|
|
5
5
|
import { useElementScroll } from "./use-element-scroll.mjs";
|
|
6
|
+
import { useHistoryState } from "./use-history-state.mjs";
|
|
6
7
|
import { useResponsiveSize } from "./use-responsive-size.mjs";
|
|
7
8
|
import { useImage } from "./use-image.mjs";
|
|
8
9
|
import { useLocalStorage } from "./use-local-storage.mjs";
|
package/dist/hooks/index.mjs
CHANGED
|
@@ -3,6 +3,7 @@ import useBodyScrollLock from "./use-body-scroll-lock.mjs";
|
|
|
3
3
|
import useClickOutside from "./use-click-outside.mjs";
|
|
4
4
|
import useElementPosition from "./use-element-position.mjs";
|
|
5
5
|
import useElementScroll from "./use-element-scroll.mjs";
|
|
6
|
+
import useHistoryState from "./use-history-state.mjs";
|
|
6
7
|
import useResponsiveSize from "./use-responsive-size.mjs";
|
|
7
8
|
import useImage from "./use-image.mjs";
|
|
8
9
|
import useLocalStorage from "./use-local-storage.mjs";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
//#region src/hooks/use-history-state.d.ts
|
|
2
|
+
interface UseHistoryStateOptions {
|
|
3
|
+
limit?: number;
|
|
4
|
+
}
|
|
5
|
+
declare const useHistoryState: <T>(initialValue: T, options?: UseHistoryStateOptions) => {
|
|
6
|
+
readonly value: T;
|
|
7
|
+
readonly setValue: (value: T | ((prev: T) => T)) => void;
|
|
8
|
+
readonly undo: () => void;
|
|
9
|
+
readonly redo: () => void;
|
|
10
|
+
readonly reset: (value: T) => void;
|
|
11
|
+
readonly canUndo: boolean;
|
|
12
|
+
readonly canRedo: boolean;
|
|
13
|
+
};
|
|
14
|
+
//#endregion
|
|
15
|
+
export { useHistoryState };
|
|
16
|
+
//# sourceMappingURL=use-history-state.d.mts.map
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { useCallback, useReducer } from "react";
|
|
2
|
+
|
|
3
|
+
//#region src/hooks/use-history-state.ts
|
|
4
|
+
const createReducer = (limit) => (state, action) => {
|
|
5
|
+
switch (action.type) {
|
|
6
|
+
case "SET": {
|
|
7
|
+
const resolved = action.value instanceof Function ? action.value(state.present) : action.value;
|
|
8
|
+
if (resolved === state.present) return state;
|
|
9
|
+
return {
|
|
10
|
+
past: [...state.past, state.present].slice(-limit),
|
|
11
|
+
present: resolved,
|
|
12
|
+
future: []
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
case "UNDO": {
|
|
16
|
+
if (state.past.length === 0) return state;
|
|
17
|
+
const previous = state.past[state.past.length - 1];
|
|
18
|
+
return {
|
|
19
|
+
past: state.past.slice(0, -1),
|
|
20
|
+
present: previous,
|
|
21
|
+
future: [state.present, ...state.future]
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
case "REDO": {
|
|
25
|
+
if (state.future.length === 0) return state;
|
|
26
|
+
const [next, ...rest] = state.future;
|
|
27
|
+
return {
|
|
28
|
+
past: [...state.past, state.present].slice(-limit),
|
|
29
|
+
present: next,
|
|
30
|
+
future: rest
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
case "RESET": return {
|
|
34
|
+
past: [],
|
|
35
|
+
present: action.value,
|
|
36
|
+
future: []
|
|
37
|
+
};
|
|
38
|
+
default: return state;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
const DEFAULT_LIMIT = 50;
|
|
42
|
+
const useHistoryState = (initialValue, options) => {
|
|
43
|
+
const [state, dispatch] = useReducer(createReducer(options?.limit ?? DEFAULT_LIMIT), {
|
|
44
|
+
past: [],
|
|
45
|
+
present: initialValue,
|
|
46
|
+
future: []
|
|
47
|
+
});
|
|
48
|
+
const setValue = useCallback((value) => {
|
|
49
|
+
dispatch({
|
|
50
|
+
type: "SET",
|
|
51
|
+
value
|
|
52
|
+
});
|
|
53
|
+
}, []);
|
|
54
|
+
const undo = useCallback(() => {
|
|
55
|
+
dispatch({ type: "UNDO" });
|
|
56
|
+
}, []);
|
|
57
|
+
const redo = useCallback(() => {
|
|
58
|
+
dispatch({ type: "REDO" });
|
|
59
|
+
}, []);
|
|
60
|
+
const reset = useCallback((value) => {
|
|
61
|
+
dispatch({
|
|
62
|
+
type: "RESET",
|
|
63
|
+
value
|
|
64
|
+
});
|
|
65
|
+
}, []);
|
|
66
|
+
return {
|
|
67
|
+
value: state.present,
|
|
68
|
+
setValue,
|
|
69
|
+
undo,
|
|
70
|
+
redo,
|
|
71
|
+
reset,
|
|
72
|
+
canUndo: state.past.length > 0,
|
|
73
|
+
canRedo: state.future.length > 0
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
//#endregion
|
|
78
|
+
export { useHistoryState as default };
|
|
79
|
+
//# sourceMappingURL=use-history-state.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-history-state.mjs","names":[],"sources":["../../src/hooks/use-history-state.ts"],"sourcesContent":["import { useCallback, useReducer } from 'react';\n\ninterface HistoryState<T> {\n past: T[];\n present: T;\n future: T[];\n}\n\ntype Action<T> =\n | { type: 'SET'; value: T | ((prev: T) => T) }\n | { type: 'UNDO' }\n | { type: 'REDO' }\n | { type: 'RESET'; value: T };\n\nconst createReducer =\n <T>(limit: number) =>\n (state: HistoryState<T>, action: Action<T>): HistoryState<T> => {\n switch (action.type) {\n case 'SET': {\n const resolved =\n action.value instanceof Function\n ? action.value(state.present)\n : action.value;\n\n if (resolved === state.present) {\n return state;\n }\n\n return {\n past: [...state.past, state.present].slice(-limit),\n present: resolved,\n future: [],\n };\n }\n\n case 'UNDO': {\n if (state.past.length === 0) {\n return state;\n }\n\n const previous = state.past[state.past.length - 1] as T;\n\n return {\n past: state.past.slice(0, -1),\n present: previous,\n future: [state.present, ...state.future],\n };\n }\n\n case 'REDO': {\n if (state.future.length === 0) {\n return state;\n }\n\n const [next, ...rest] = state.future;\n\n return {\n past: [...state.past, state.present].slice(-limit),\n present: next as T,\n future: rest,\n };\n }\n\n case 'RESET': {\n return { past: [], present: action.value, future: [] };\n }\n\n default: {\n return state;\n }\n }\n };\n\ninterface UseHistoryStateOptions {\n limit?: number;\n}\n\nconst DEFAULT_LIMIT = 50;\n\nconst useHistoryState = <T>(\n initialValue: T,\n options?: UseHistoryStateOptions,\n) => {\n const limit = options?.limit ?? DEFAULT_LIMIT;\n\n const [state, dispatch] = useReducer(createReducer<T>(limit), {\n past: [],\n present: initialValue,\n future: [],\n });\n\n const setValue = useCallback((value: T | ((prev: T) => T)) => {\n dispatch({ type: 'SET', value });\n }, []);\n\n const undo = useCallback(() => {\n dispatch({ type: 'UNDO' });\n }, []);\n\n const redo = useCallback(() => {\n dispatch({ type: 'REDO' });\n }, []);\n\n const reset = useCallback((value: T) => {\n dispatch({ type: 'RESET', value });\n }, []);\n\n return {\n value: state.present,\n setValue,\n undo,\n redo,\n reset,\n canUndo: state.past.length > 0,\n canRedo: state.future.length > 0,\n } as const;\n};\n\nexport default useHistoryState;\n"],"mappings":";;;AAcA,MAAM,iBACA,WACH,OAAwB,WAAuC;AAC9D,SAAQ,OAAO,MAAf;EACE,KAAK,OAAO;GACV,MAAM,WACJ,OAAO,iBAAiB,WACpB,OAAO,MAAM,MAAM,QAAQ,GAC3B,OAAO;AAEb,OAAI,aAAa,MAAM,QACrB,QAAO;AAGT,UAAO;IACL,MAAM,CAAC,GAAG,MAAM,MAAM,MAAM,QAAQ,CAAC,MAAM,CAAC,MAAM;IAClD,SAAS;IACT,QAAQ,EAAE;IACX;;EAGH,KAAK,QAAQ;AACX,OAAI,MAAM,KAAK,WAAW,EACxB,QAAO;GAGT,MAAM,WAAW,MAAM,KAAK,MAAM,KAAK,SAAS;AAEhD,UAAO;IACL,MAAM,MAAM,KAAK,MAAM,GAAG,GAAG;IAC7B,SAAS;IACT,QAAQ,CAAC,MAAM,SAAS,GAAG,MAAM,OAAO;IACzC;;EAGH,KAAK,QAAQ;AACX,OAAI,MAAM,OAAO,WAAW,EAC1B,QAAO;GAGT,MAAM,CAAC,MAAM,GAAG,QAAQ,MAAM;AAE9B,UAAO;IACL,MAAM,CAAC,GAAG,MAAM,MAAM,MAAM,QAAQ,CAAC,MAAM,CAAC,MAAM;IAClD,SAAS;IACT,QAAQ;IACT;;EAGH,KAAK,QACH,QAAO;GAAE,MAAM,EAAE;GAAE,SAAS,OAAO;GAAO,QAAQ,EAAE;GAAE;EAGxD,QACE,QAAO;;;AASf,MAAM,gBAAgB;AAEtB,MAAM,mBACJ,cACA,YACG;CAGH,MAAM,CAAC,OAAO,YAAY,WAAW,cAFvB,SAAS,SAAS,cAE4B,EAAE;EAC5D,MAAM,EAAE;EACR,SAAS;EACT,QAAQ,EAAE;EACX,CAAC;CAEF,MAAM,WAAW,aAAa,UAAgC;AAC5D,WAAS;GAAE,MAAM;GAAO;GAAO,CAAC;IAC/B,EAAE,CAAC;CAEN,MAAM,OAAO,kBAAkB;AAC7B,WAAS,EAAE,MAAM,QAAQ,CAAC;IACzB,EAAE,CAAC;CAEN,MAAM,OAAO,kBAAkB;AAC7B,WAAS,EAAE,MAAM,QAAQ,CAAC;IACzB,EAAE,CAAC;CAEN,MAAM,QAAQ,aAAa,UAAa;AACtC,WAAS;GAAE,MAAM;GAAS;GAAO,CAAC;IACjC,EAAE,CAAC;AAEN,QAAO;EACL,OAAO,MAAM;EACb;EACA;EACA;EACA;EACA,SAAS,MAAM,KAAK,SAAS;EAC7B,SAAS,MAAM,OAAO,SAAS;EAChC"}
|
package/dist/index.d.mts
CHANGED
|
@@ -3,6 +3,7 @@ import { useBodyScrollLock } from "./hooks/use-body-scroll-lock.mjs";
|
|
|
3
3
|
import { useClickOutside } from "./hooks/use-click-outside.mjs";
|
|
4
4
|
import { useElementPosition } from "./hooks/use-element-position.mjs";
|
|
5
5
|
import { useElementScroll } from "./hooks/use-element-scroll.mjs";
|
|
6
|
+
import { useHistoryState } from "./hooks/use-history-state.mjs";
|
|
6
7
|
import { useResponsiveSize } from "./hooks/use-responsive-size.mjs";
|
|
7
8
|
import { useImage } from "./hooks/use-image.mjs";
|
|
8
9
|
import { useLocalStorage } from "./hooks/use-local-storage.mjs";
|
|
@@ -13,4 +14,4 @@ import { useTimeline } from "./hooks/use-timeline.mjs";
|
|
|
13
14
|
import { useWindowScroll } from "./hooks/use-window-scroll.mjs";
|
|
14
15
|
import { useViewport } from "./hooks/use-viewport.mjs";
|
|
15
16
|
import "./hooks/index.mjs";
|
|
16
|
-
export { useBodyScrollLock, useClickOutside, useDebounce, useElementPosition, useElementScroll, useImage, useLocalStorage, useRecursiveTimeout, useResponsiveSize, useScrollToElements, useThrottle, useTimeline, useViewport, useWindowScroll };
|
|
17
|
+
export { useBodyScrollLock, useClickOutside, useDebounce, useElementPosition, useElementScroll, useHistoryState, useImage, useLocalStorage, useRecursiveTimeout, useResponsiveSize, useScrollToElements, useThrottle, useTimeline, useViewport, useWindowScroll };
|
package/dist/index.mjs
CHANGED
|
@@ -3,6 +3,7 @@ import useBodyScrollLock from "./hooks/use-body-scroll-lock.mjs";
|
|
|
3
3
|
import useClickOutside from "./hooks/use-click-outside.mjs";
|
|
4
4
|
import useElementPosition from "./hooks/use-element-position.mjs";
|
|
5
5
|
import useElementScroll from "./hooks/use-element-scroll.mjs";
|
|
6
|
+
import useHistoryState from "./hooks/use-history-state.mjs";
|
|
6
7
|
import useResponsiveSize from "./hooks/use-responsive-size.mjs";
|
|
7
8
|
import useImage from "./hooks/use-image.mjs";
|
|
8
9
|
import useLocalStorage from "./hooks/use-local-storage.mjs";
|
|
@@ -14,4 +15,4 @@ import useWindowScroll from "./hooks/use-window-scroll.mjs";
|
|
|
14
15
|
import useViewport from "./hooks/use-viewport.mjs";
|
|
15
16
|
import "./hooks/index.mjs";
|
|
16
17
|
|
|
17
|
-
export { useBodyScrollLock, useClickOutside, useDebounce, useElementPosition, useElementScroll, useImage, useLocalStorage, useRecursiveTimeout, useResponsiveSize, useScrollToElements, useThrottle, useTimeline, useViewport, useWindowScroll };
|
|
18
|
+
export { useBodyScrollLock, useClickOutside, useDebounce, useElementPosition, useElementScroll, useHistoryState, useImage, useLocalStorage, useRecursiveTimeout, useResponsiveSize, useScrollToElements, useThrottle, useTimeline, useViewport, useWindowScroll };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jbpark/use-hooks",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.0",
|
|
4
4
|
"description": "A collection of reusable React 19 hooks for common UI and interaction patterns",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
"scripts": {
|
|
42
42
|
"dev": "vite",
|
|
43
43
|
"build": "tsc -b && tsdown",
|
|
44
|
+
"build:demo": "vite build",
|
|
44
45
|
"lint": "eslint .",
|
|
45
46
|
"preview": "vite preview",
|
|
46
47
|
"prepublishOnly": "pnpm build",
|
|
@@ -51,8 +52,10 @@
|
|
|
51
52
|
"react-dom": "^19.1.1"
|
|
52
53
|
},
|
|
53
54
|
"devDependencies": {
|
|
55
|
+
"@changesets/cli": "^2.31.1",
|
|
54
56
|
"@eslint/js": "^9.33.0",
|
|
55
57
|
"@jbpark/ui-kit": "^2.7.0",
|
|
58
|
+
"@radix-ui/react-icons": "^1.3.2",
|
|
56
59
|
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
|
|
57
60
|
"@types/node": "^24.5.2",
|
|
58
61
|
"@types/react": "^19.1.10",
|