@wheeparam/library 0.0.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/api/index.cjs +89 -0
- package/dist/api/index.d.cts +124 -0
- package/dist/api/index.d.ts +124 -0
- package/dist/api/index.js +60 -0
- package/dist/client/index.cjs +205 -0
- package/dist/client/index.d.cts +179 -0
- package/dist/client/index.d.ts +179 -0
- package/dist/client/index.js +168 -0
- package/dist/index.cjs +57 -0
- package/dist/index.d.cts +31 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.js +29 -0
- package/dist/react/index.cjs +134 -0
- package/dist/react/index.d.cts +178 -0
- package/dist/react/index.d.ts +178 -0
- package/dist/react/index.js +95 -0
- package/dist/utils/index.cjs +322 -0
- package/dist/utils/index.d.cts +344 -0
- package/dist/utils/index.d.ts +344 -0
- package/dist/utils/index.js +275 -0
- package/package.json +59 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/react/index.ts
|
|
31
|
+
var react_exports = {};
|
|
32
|
+
__export(react_exports, {
|
|
33
|
+
nl2br: () => nl2br,
|
|
34
|
+
useFormLayer: () => useFormLayer,
|
|
35
|
+
useSortLayer: () => useSortLayer
|
|
36
|
+
});
|
|
37
|
+
module.exports = __toCommonJS(react_exports);
|
|
38
|
+
|
|
39
|
+
// src/react/useFormLayer.ts
|
|
40
|
+
var import_react = require("react");
|
|
41
|
+
function useFormLayer() {
|
|
42
|
+
const [opened, setOpened] = (0, import_react.useState)(false);
|
|
43
|
+
const [mode, setMode] = (0, import_react.useState)(null);
|
|
44
|
+
const [id, setId] = (0, import_react.useState)(null);
|
|
45
|
+
const [parentId, setParentId] = (0, import_react.useState)(null);
|
|
46
|
+
const [payload, setPayload] = (0, import_react.useState)(null);
|
|
47
|
+
const open = (0, import_react.useCallback)(
|
|
48
|
+
(args) => {
|
|
49
|
+
setMode(args.mode);
|
|
50
|
+
setId(args.id ?? null);
|
|
51
|
+
setParentId(args.parentId ?? null);
|
|
52
|
+
setPayload(args.payload ?? null);
|
|
53
|
+
setOpened(true);
|
|
54
|
+
},
|
|
55
|
+
[]
|
|
56
|
+
);
|
|
57
|
+
const openCreate = (0, import_react.useCallback)((pId, pl) => {
|
|
58
|
+
open({ mode: "create", parentId: pId ?? null, id: null, payload: pl ?? null });
|
|
59
|
+
}, [open]);
|
|
60
|
+
const openEdit = (0, import_react.useCallback)((editId, pId, pl) => {
|
|
61
|
+
open({ mode: "edit", id: editId, parentId: pId ?? null, payload: pl ?? null });
|
|
62
|
+
}, [open]);
|
|
63
|
+
const close = (0, import_react.useCallback)(() => {
|
|
64
|
+
setOpened(false);
|
|
65
|
+
setMode(null);
|
|
66
|
+
setId(null);
|
|
67
|
+
setParentId(null);
|
|
68
|
+
setPayload(null);
|
|
69
|
+
}, []);
|
|
70
|
+
return {
|
|
71
|
+
opened,
|
|
72
|
+
mode,
|
|
73
|
+
id,
|
|
74
|
+
parentId,
|
|
75
|
+
payload,
|
|
76
|
+
open,
|
|
77
|
+
openCreate,
|
|
78
|
+
openEdit,
|
|
79
|
+
close,
|
|
80
|
+
setOpened,
|
|
81
|
+
setId,
|
|
82
|
+
setParentId,
|
|
83
|
+
setMode,
|
|
84
|
+
setPayload
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// src/react/useSortLayer.ts
|
|
89
|
+
var import_react2 = require("react");
|
|
90
|
+
function useSortLayer(props) {
|
|
91
|
+
const { list, setList, onSave, clone } = props;
|
|
92
|
+
const [enabled, setEnabled] = (0, import_react2.useState)(false);
|
|
93
|
+
const backupRef = (0, import_react2.useRef)(null);
|
|
94
|
+
const cloneFn = (0, import_react2.useMemo)(() => {
|
|
95
|
+
return clone ?? ((items) => items.slice());
|
|
96
|
+
}, [clone]);
|
|
97
|
+
const start = (0, import_react2.useCallback)(() => {
|
|
98
|
+
backupRef.current = cloneFn(list);
|
|
99
|
+
setEnabled(true);
|
|
100
|
+
}, [cloneFn, list]);
|
|
101
|
+
const cancel = (0, import_react2.useCallback)(() => {
|
|
102
|
+
if (backupRef.current) {
|
|
103
|
+
setList(backupRef.current);
|
|
104
|
+
}
|
|
105
|
+
backupRef.current = null;
|
|
106
|
+
setEnabled(false);
|
|
107
|
+
}, [setList]);
|
|
108
|
+
const save = (0, import_react2.useCallback)(() => {
|
|
109
|
+
setEnabled(false);
|
|
110
|
+
backupRef.current = null;
|
|
111
|
+
onSave?.(cloneFn(list));
|
|
112
|
+
}, [cloneFn, list, onSave]);
|
|
113
|
+
return { start, cancel, save, enabled };
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// src/react/nl2br.tsx
|
|
117
|
+
var import_jsx_runtime = __toESM(require("react/jsx-runtime"), 1);
|
|
118
|
+
function nl2br(text) {
|
|
119
|
+
const newlineRegex = /(\r\n|\r|\n)/g;
|
|
120
|
+
if (!text) return "";
|
|
121
|
+
const props = {};
|
|
122
|
+
return text.split(newlineRegex).map(function(line, index) {
|
|
123
|
+
if (line.match(newlineRegex)) {
|
|
124
|
+
return import_jsx_runtime.default.jsx("br", { key: index, ...props });
|
|
125
|
+
}
|
|
126
|
+
return line;
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
130
|
+
0 && (module.exports = {
|
|
131
|
+
nl2br,
|
|
132
|
+
useFormLayer,
|
|
133
|
+
useSortLayer
|
|
134
|
+
});
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { Dispatch, SetStateAction } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @packageDocumentation
|
|
6
|
+
* ๋ชจ๋ฌ/๋ ์ด์ด ์ํ(์ด๋ฆผ ์ฌ๋ถ + ์ปจํ
์คํธ ํ๋ผ๋ฏธํฐ)๋ฅผ ๊ด๋ฆฌํ๋ React Hook
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* ๋ ์ด์ด(๋ชจ๋ฌ)์ ๋์ ๋ชจ๋
|
|
10
|
+
* - create: ์์ฑ ๋ชจ๋
|
|
11
|
+
* - edit: ์์ ๋ชจ๋
|
|
12
|
+
*/
|
|
13
|
+
type FormLayerMode = "create" | "edit";
|
|
14
|
+
/**
|
|
15
|
+
* useFormLayer๊ฐ ๋ฐํํ๋ ์ ์ด ๊ฐ์ฒด ํ์
|
|
16
|
+
*
|
|
17
|
+
* @template T id/parentId์ ํ์
(string | number)
|
|
18
|
+
* @template P payload ํ์
(์ถ๊ฐ ์ปจํ
์คํธ๊ฐ ํ์ํ ๋ ์ฌ์ฉ)
|
|
19
|
+
*/
|
|
20
|
+
type UseFormLayerReturn<T extends string | number, P> = {
|
|
21
|
+
/** ๋ชจ๋ฌ ์ด๋ฆผ ์ฌ๋ถ */
|
|
22
|
+
opened: boolean;
|
|
23
|
+
/** ํ์ฌ ๋ชจ๋ฌ ๋ชจ๋(create/edit). ๋ซํ์์ผ๋ฉด null */
|
|
24
|
+
mode: FormLayerMode | null;
|
|
25
|
+
/** edit ๋ชจ๋์์ ์ฃผ๋ก ์ฐ๋ PK. create ๋ชจ๋์ผ ๋๋ ๋ณดํต null */
|
|
26
|
+
id: T | null;
|
|
27
|
+
/** ๋ถ๋ชจ ์ปจํ
์คํธ๊ฐ ์๋ ๊ฒฝ์ฐ ์ฌ์ฉ (์: ํธ๋ฆฌ์์ ํน์ ๋
ธ๋ ์๋ ์์ฑ) */
|
|
28
|
+
parentId: T | null;
|
|
29
|
+
/** ๋ชจ๋ฌ์ ์ด ๋ ํจ๊ป ๋๊ธฐ๊ณ ์ถ์ ์ถ๊ฐ ์ปจํ
์คํธ (์ ํ) */
|
|
30
|
+
payload: P | null;
|
|
31
|
+
/**
|
|
32
|
+
* ๋ชจ๋ฌ์ ์ฐ๋ค(์ผ๋ฐํ)
|
|
33
|
+
* @example
|
|
34
|
+
* layer.open({ mode: "edit", id: 10 })
|
|
35
|
+
* layer.open({ mode: "create", parentId: 5 })
|
|
36
|
+
*/
|
|
37
|
+
open: (args: {
|
|
38
|
+
mode: FormLayerMode;
|
|
39
|
+
id?: T | null;
|
|
40
|
+
parentId?: T | null;
|
|
41
|
+
payload?: P | null;
|
|
42
|
+
}) => void;
|
|
43
|
+
/** ๋ชจ๋ฌ์ ๋ซ๊ณ ๋ด๋ถ ์ํ(id/parentId/payload ๋ฑ)๋ฅผ ์ด๊ธฐํํ๋ค */
|
|
44
|
+
close: () => void;
|
|
45
|
+
/**
|
|
46
|
+
* ์์ฑ ๋ชจ๋๋ก ๋ชจ๋ฌ์ ์ฐ๋ค(๋จ์ถํ)
|
|
47
|
+
* @example
|
|
48
|
+
* layer.openCreate()
|
|
49
|
+
* layer.openCreate(3) // parentId=3 ์๋ ์์ฑ
|
|
50
|
+
*/
|
|
51
|
+
openCreate: (parentId?: T | null, payload?: P | null) => void;
|
|
52
|
+
/**
|
|
53
|
+
* ์์ ๋ชจ๋๋ก ๋ชจ๋ฌ์ ์ฐ๋ค(๋จ์ถํ)
|
|
54
|
+
* @example
|
|
55
|
+
* layer.openEdit(10)
|
|
56
|
+
* layer.openEdit(10, 3) // id=10 ํธ์ง, parentId=3 ์ปจํ
์คํธ
|
|
57
|
+
*/
|
|
58
|
+
openEdit: (id: T, parentId?: T | null, payload?: P | null) => void;
|
|
59
|
+
/** ํ์ ์ ์๋ ์ ์ด๋ฅผ ์ํ raw setter๋ค */
|
|
60
|
+
setOpened: React.Dispatch<React.SetStateAction<boolean>>;
|
|
61
|
+
setId: React.Dispatch<React.SetStateAction<T | null>>;
|
|
62
|
+
setParentId: React.Dispatch<React.SetStateAction<T | null>>;
|
|
63
|
+
setMode: React.Dispatch<React.SetStateAction<FormLayerMode | null>>;
|
|
64
|
+
setPayload: React.Dispatch<React.SetStateAction<P | null>>;
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* ๋ชจ๋ฌ/๋ ์ด์ด ์ํ๋ฅผ ๊ด๋ฆฌํ๋ React ํ
|
|
68
|
+
*
|
|
69
|
+
* โ๋ชจ๋ฌ open state + ์ ๋ฌ ํ๋ผ๋ฏธํฐ stateโ๋ฅผ ๋งค๋ฒ ๋ง๋ค๊ธฐ ๊ท์ฐฎ์ ๋ ์ฐ๋ ๋ชฉ์ ์ ์ต์ ํ๋์ด ์๋ค.
|
|
70
|
+
* create/edit ๋ชจ๋, id/parentId, payload(์ ํ)๋ฅผ ํ ๋ฒ์ ๊ด๋ฆฌํ๋ค.
|
|
71
|
+
*
|
|
72
|
+
* @returns ๋ ์ด์ด ์ ์ด ๊ฐ์ฒด
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* const layer = useFormLayer<number>()
|
|
76
|
+
* layer.openCreate()
|
|
77
|
+
* layer.openEdit(10)
|
|
78
|
+
*/
|
|
79
|
+
declare function useFormLayer<T extends string | number = string, P = never>(): UseFormLayerReturn<T, P>;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* @packageDocumentation
|
|
83
|
+
* ๋ชฉ๋ก์ โ์ ๋ ฌ ๋ชจ๋โ๋ฅผ ๊ด๋ฆฌํ๋ React Hook
|
|
84
|
+
*
|
|
85
|
+
* - start(): ํ์ฌ list๋ฅผ ๋ฐฑ์
ํ๊ณ ์ ๋ ฌ๋ชจ๋(enabled=true)๋ก ์ง์
|
|
86
|
+
* - cancel(): ๋ฐฑ์
๋ณธ์ผ๋ก list๋ฅผ ๋ณต๊ตฌํ๊ณ ์ ๋ ฌ๋ชจ๋ ์ข
๋ฃ
|
|
87
|
+
* - save(): ์ ๋ ฌ๋ชจ๋๋ฅผ ์ข
๋ฃํ๊ณ onSave(list)๋ฅผ ํธ์ถ
|
|
88
|
+
*/
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* useSortLayer ์
๋ ฅ Props
|
|
92
|
+
*
|
|
93
|
+
* @template T ๋ชฉ๋ก ์์ดํ
ํ์
|
|
94
|
+
*/
|
|
95
|
+
type UseSortLayerProps<T> = {
|
|
96
|
+
/** ํ์ฌ ๋ชฉ๋ก */
|
|
97
|
+
list: T[];
|
|
98
|
+
/** ๋ชฉ๋ก setter */
|
|
99
|
+
setList: Dispatch<SetStateAction<T[]>>;
|
|
100
|
+
/** ์ ์ฅ ์ฝ๋ฐฑ(์ ํ) */
|
|
101
|
+
onSave?: (items: T[]) => void;
|
|
102
|
+
/**
|
|
103
|
+
* ์ค๋
์ท ๋ณต์ฌ ๋ฐฉ์ (๊ธฐ๋ณธ shallow)
|
|
104
|
+
* - shallow: [...list]
|
|
105
|
+
* - deep: structuredClone(list) (๋ธ๋ผ์ฐ์ ์ง์ ํ์)
|
|
106
|
+
* - custom: (items) => ...
|
|
107
|
+
*/
|
|
108
|
+
clone?: (items: T[]) => T[];
|
|
109
|
+
};
|
|
110
|
+
/**
|
|
111
|
+
* useSortLayer ๋ฐํ ํ์
|
|
112
|
+
*/
|
|
113
|
+
type UseSortLayerReturn = {
|
|
114
|
+
/** ์ ๋ ฌ๋ชจ๋ ์์ (ํ์ฌ list ์ค๋
์ท ๋ฐฑ์
) */
|
|
115
|
+
start: () => void;
|
|
116
|
+
/** ์ ๋ ฌ๋ชจ๋ ์ทจ์ (๋ฐฑ์
๋ณธ์ผ๋ก ๋ณต๊ตฌ) */
|
|
117
|
+
cancel: () => void;
|
|
118
|
+
/** ์ ๋ ฌ๋ชจ๋ ์ ์ฅ(์ข
๋ฃ) */
|
|
119
|
+
save: () => void;
|
|
120
|
+
/** ์ ๋ ฌ๋ชจ๋ ์ฌ๋ถ */
|
|
121
|
+
enabled: boolean;
|
|
122
|
+
};
|
|
123
|
+
/**
|
|
124
|
+
* ๋ชฉ๋ก ์ ๋ ฌ ๋ชจ๋๋ฅผ ๊ด๋ฆฌํ๋ ํ
|
|
125
|
+
*
|
|
126
|
+
* start() ํธ์ถ ์ ํ์ฌ ๋ชฉ๋ก์ ๋ฐฑ์
ํ๊ณ ์ ๋ ฌ๋ชจ๋๋ก ์ง์
ํ๋ค.
|
|
127
|
+
* cancel() ํธ์ถ ์ ์๋ ์ํ๋ก ๋ณต๊ตฌ๋๋ค.
|
|
128
|
+
* save() ํธ์ถ ์ onSave๊ฐ ์คํ๋๋ค.
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* const sort = useSortLayer({ list, setList, onSave })
|
|
132
|
+
* sort.start()
|
|
133
|
+
* // ... drag & drop ๋ฑ์ผ๋ก list ์์ ๋ณ๊ฒฝ ...
|
|
134
|
+
* sort.cancel()
|
|
135
|
+
* // ๋๋
|
|
136
|
+
* sort.save()
|
|
137
|
+
*/
|
|
138
|
+
declare function useSortLayer<T>(props: UseSortLayerProps<T>): UseSortLayerReturn;
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* ๋ฌธ์์ด์ ์ค๋ฐ๊ฟ(\n)์ `<br />` ์์๋ก ๋ณํํ๋ค.
|
|
142
|
+
*
|
|
143
|
+
* ์๋ฒ ์ปดํฌ๋ํธ / ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ ๋ชจ๋์์ ์์ ํ๊ฒ ์ฌ์ฉ ๊ฐ๋ฅํ๋ค.
|
|
144
|
+
*
|
|
145
|
+
* @param text ์ค๋ฐ๊ฟ์ ํฌํจํ ์ ์๋ ๋ฌธ์์ด
|
|
146
|
+
* @returns ReactNode ๋ฐฐ์ด (๋ฌธ์์ด + `<br />`)
|
|
147
|
+
*
|
|
148
|
+
* @example ๊ธฐ๋ณธ ์ฌ์ฉ
|
|
149
|
+
* ```tsx
|
|
150
|
+
* import { nl2br } from "@your-scope/toolkit/react";
|
|
151
|
+
*
|
|
152
|
+
* export default function Page() {
|
|
153
|
+
* return (
|
|
154
|
+
* <div>
|
|
155
|
+
* {nl2br("์ฒซ์ค\n๋์งธ์ค\n์
์งธ์ค")}
|
|
156
|
+
* </div>
|
|
157
|
+
* );
|
|
158
|
+
* }
|
|
159
|
+
* ```
|
|
160
|
+
*
|
|
161
|
+
* @example API ์๋ฌ ๋ฉ์์ง ์ถ๋ ฅ
|
|
162
|
+
* ```tsx
|
|
163
|
+
* Swal.fire({
|
|
164
|
+
* title: "์ค๋ฅ ๋ฐ์",
|
|
165
|
+
* html: nl2br(message),
|
|
166
|
+
* });
|
|
167
|
+
* ```
|
|
168
|
+
*
|
|
169
|
+
* @example textarea ๋ฏธ๋ฆฌ๋ณด๊ธฐ
|
|
170
|
+
* ```tsx
|
|
171
|
+
* <div className="preview">
|
|
172
|
+
* {nl2br(form.content)}
|
|
173
|
+
* </div>
|
|
174
|
+
* ```
|
|
175
|
+
*/
|
|
176
|
+
declare function nl2br(text: string | null | undefined): "" | (string | react.ReactElement<unknown, string | react.JSXElementConstructor<any>>)[];
|
|
177
|
+
|
|
178
|
+
export { type FormLayerMode, type UseFormLayerReturn, type UseSortLayerProps, type UseSortLayerReturn, nl2br, useFormLayer, useSortLayer };
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { Dispatch, SetStateAction } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @packageDocumentation
|
|
6
|
+
* ๋ชจ๋ฌ/๋ ์ด์ด ์ํ(์ด๋ฆผ ์ฌ๋ถ + ์ปจํ
์คํธ ํ๋ผ๋ฏธํฐ)๋ฅผ ๊ด๋ฆฌํ๋ React Hook
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* ๋ ์ด์ด(๋ชจ๋ฌ)์ ๋์ ๋ชจ๋
|
|
10
|
+
* - create: ์์ฑ ๋ชจ๋
|
|
11
|
+
* - edit: ์์ ๋ชจ๋
|
|
12
|
+
*/
|
|
13
|
+
type FormLayerMode = "create" | "edit";
|
|
14
|
+
/**
|
|
15
|
+
* useFormLayer๊ฐ ๋ฐํํ๋ ์ ์ด ๊ฐ์ฒด ํ์
|
|
16
|
+
*
|
|
17
|
+
* @template T id/parentId์ ํ์
(string | number)
|
|
18
|
+
* @template P payload ํ์
(์ถ๊ฐ ์ปจํ
์คํธ๊ฐ ํ์ํ ๋ ์ฌ์ฉ)
|
|
19
|
+
*/
|
|
20
|
+
type UseFormLayerReturn<T extends string | number, P> = {
|
|
21
|
+
/** ๋ชจ๋ฌ ์ด๋ฆผ ์ฌ๋ถ */
|
|
22
|
+
opened: boolean;
|
|
23
|
+
/** ํ์ฌ ๋ชจ๋ฌ ๋ชจ๋(create/edit). ๋ซํ์์ผ๋ฉด null */
|
|
24
|
+
mode: FormLayerMode | null;
|
|
25
|
+
/** edit ๋ชจ๋์์ ์ฃผ๋ก ์ฐ๋ PK. create ๋ชจ๋์ผ ๋๋ ๋ณดํต null */
|
|
26
|
+
id: T | null;
|
|
27
|
+
/** ๋ถ๋ชจ ์ปจํ
์คํธ๊ฐ ์๋ ๊ฒฝ์ฐ ์ฌ์ฉ (์: ํธ๋ฆฌ์์ ํน์ ๋
ธ๋ ์๋ ์์ฑ) */
|
|
28
|
+
parentId: T | null;
|
|
29
|
+
/** ๋ชจ๋ฌ์ ์ด ๋ ํจ๊ป ๋๊ธฐ๊ณ ์ถ์ ์ถ๊ฐ ์ปจํ
์คํธ (์ ํ) */
|
|
30
|
+
payload: P | null;
|
|
31
|
+
/**
|
|
32
|
+
* ๋ชจ๋ฌ์ ์ฐ๋ค(์ผ๋ฐํ)
|
|
33
|
+
* @example
|
|
34
|
+
* layer.open({ mode: "edit", id: 10 })
|
|
35
|
+
* layer.open({ mode: "create", parentId: 5 })
|
|
36
|
+
*/
|
|
37
|
+
open: (args: {
|
|
38
|
+
mode: FormLayerMode;
|
|
39
|
+
id?: T | null;
|
|
40
|
+
parentId?: T | null;
|
|
41
|
+
payload?: P | null;
|
|
42
|
+
}) => void;
|
|
43
|
+
/** ๋ชจ๋ฌ์ ๋ซ๊ณ ๋ด๋ถ ์ํ(id/parentId/payload ๋ฑ)๋ฅผ ์ด๊ธฐํํ๋ค */
|
|
44
|
+
close: () => void;
|
|
45
|
+
/**
|
|
46
|
+
* ์์ฑ ๋ชจ๋๋ก ๋ชจ๋ฌ์ ์ฐ๋ค(๋จ์ถํ)
|
|
47
|
+
* @example
|
|
48
|
+
* layer.openCreate()
|
|
49
|
+
* layer.openCreate(3) // parentId=3 ์๋ ์์ฑ
|
|
50
|
+
*/
|
|
51
|
+
openCreate: (parentId?: T | null, payload?: P | null) => void;
|
|
52
|
+
/**
|
|
53
|
+
* ์์ ๋ชจ๋๋ก ๋ชจ๋ฌ์ ์ฐ๋ค(๋จ์ถํ)
|
|
54
|
+
* @example
|
|
55
|
+
* layer.openEdit(10)
|
|
56
|
+
* layer.openEdit(10, 3) // id=10 ํธ์ง, parentId=3 ์ปจํ
์คํธ
|
|
57
|
+
*/
|
|
58
|
+
openEdit: (id: T, parentId?: T | null, payload?: P | null) => void;
|
|
59
|
+
/** ํ์ ์ ์๋ ์ ์ด๋ฅผ ์ํ raw setter๋ค */
|
|
60
|
+
setOpened: React.Dispatch<React.SetStateAction<boolean>>;
|
|
61
|
+
setId: React.Dispatch<React.SetStateAction<T | null>>;
|
|
62
|
+
setParentId: React.Dispatch<React.SetStateAction<T | null>>;
|
|
63
|
+
setMode: React.Dispatch<React.SetStateAction<FormLayerMode | null>>;
|
|
64
|
+
setPayload: React.Dispatch<React.SetStateAction<P | null>>;
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* ๋ชจ๋ฌ/๋ ์ด์ด ์ํ๋ฅผ ๊ด๋ฆฌํ๋ React ํ
|
|
68
|
+
*
|
|
69
|
+
* โ๋ชจ๋ฌ open state + ์ ๋ฌ ํ๋ผ๋ฏธํฐ stateโ๋ฅผ ๋งค๋ฒ ๋ง๋ค๊ธฐ ๊ท์ฐฎ์ ๋ ์ฐ๋ ๋ชฉ์ ์ ์ต์ ํ๋์ด ์๋ค.
|
|
70
|
+
* create/edit ๋ชจ๋, id/parentId, payload(์ ํ)๋ฅผ ํ ๋ฒ์ ๊ด๋ฆฌํ๋ค.
|
|
71
|
+
*
|
|
72
|
+
* @returns ๋ ์ด์ด ์ ์ด ๊ฐ์ฒด
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* const layer = useFormLayer<number>()
|
|
76
|
+
* layer.openCreate()
|
|
77
|
+
* layer.openEdit(10)
|
|
78
|
+
*/
|
|
79
|
+
declare function useFormLayer<T extends string | number = string, P = never>(): UseFormLayerReturn<T, P>;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* @packageDocumentation
|
|
83
|
+
* ๋ชฉ๋ก์ โ์ ๋ ฌ ๋ชจ๋โ๋ฅผ ๊ด๋ฆฌํ๋ React Hook
|
|
84
|
+
*
|
|
85
|
+
* - start(): ํ์ฌ list๋ฅผ ๋ฐฑ์
ํ๊ณ ์ ๋ ฌ๋ชจ๋(enabled=true)๋ก ์ง์
|
|
86
|
+
* - cancel(): ๋ฐฑ์
๋ณธ์ผ๋ก list๋ฅผ ๋ณต๊ตฌํ๊ณ ์ ๋ ฌ๋ชจ๋ ์ข
๋ฃ
|
|
87
|
+
* - save(): ์ ๋ ฌ๋ชจ๋๋ฅผ ์ข
๋ฃํ๊ณ onSave(list)๋ฅผ ํธ์ถ
|
|
88
|
+
*/
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* useSortLayer ์
๋ ฅ Props
|
|
92
|
+
*
|
|
93
|
+
* @template T ๋ชฉ๋ก ์์ดํ
ํ์
|
|
94
|
+
*/
|
|
95
|
+
type UseSortLayerProps<T> = {
|
|
96
|
+
/** ํ์ฌ ๋ชฉ๋ก */
|
|
97
|
+
list: T[];
|
|
98
|
+
/** ๋ชฉ๋ก setter */
|
|
99
|
+
setList: Dispatch<SetStateAction<T[]>>;
|
|
100
|
+
/** ์ ์ฅ ์ฝ๋ฐฑ(์ ํ) */
|
|
101
|
+
onSave?: (items: T[]) => void;
|
|
102
|
+
/**
|
|
103
|
+
* ์ค๋
์ท ๋ณต์ฌ ๋ฐฉ์ (๊ธฐ๋ณธ shallow)
|
|
104
|
+
* - shallow: [...list]
|
|
105
|
+
* - deep: structuredClone(list) (๋ธ๋ผ์ฐ์ ์ง์ ํ์)
|
|
106
|
+
* - custom: (items) => ...
|
|
107
|
+
*/
|
|
108
|
+
clone?: (items: T[]) => T[];
|
|
109
|
+
};
|
|
110
|
+
/**
|
|
111
|
+
* useSortLayer ๋ฐํ ํ์
|
|
112
|
+
*/
|
|
113
|
+
type UseSortLayerReturn = {
|
|
114
|
+
/** ์ ๋ ฌ๋ชจ๋ ์์ (ํ์ฌ list ์ค๋
์ท ๋ฐฑ์
) */
|
|
115
|
+
start: () => void;
|
|
116
|
+
/** ์ ๋ ฌ๋ชจ๋ ์ทจ์ (๋ฐฑ์
๋ณธ์ผ๋ก ๋ณต๊ตฌ) */
|
|
117
|
+
cancel: () => void;
|
|
118
|
+
/** ์ ๋ ฌ๋ชจ๋ ์ ์ฅ(์ข
๋ฃ) */
|
|
119
|
+
save: () => void;
|
|
120
|
+
/** ์ ๋ ฌ๋ชจ๋ ์ฌ๋ถ */
|
|
121
|
+
enabled: boolean;
|
|
122
|
+
};
|
|
123
|
+
/**
|
|
124
|
+
* ๋ชฉ๋ก ์ ๋ ฌ ๋ชจ๋๋ฅผ ๊ด๋ฆฌํ๋ ํ
|
|
125
|
+
*
|
|
126
|
+
* start() ํธ์ถ ์ ํ์ฌ ๋ชฉ๋ก์ ๋ฐฑ์
ํ๊ณ ์ ๋ ฌ๋ชจ๋๋ก ์ง์
ํ๋ค.
|
|
127
|
+
* cancel() ํธ์ถ ์ ์๋ ์ํ๋ก ๋ณต๊ตฌ๋๋ค.
|
|
128
|
+
* save() ํธ์ถ ์ onSave๊ฐ ์คํ๋๋ค.
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* const sort = useSortLayer({ list, setList, onSave })
|
|
132
|
+
* sort.start()
|
|
133
|
+
* // ... drag & drop ๋ฑ์ผ๋ก list ์์ ๋ณ๊ฒฝ ...
|
|
134
|
+
* sort.cancel()
|
|
135
|
+
* // ๋๋
|
|
136
|
+
* sort.save()
|
|
137
|
+
*/
|
|
138
|
+
declare function useSortLayer<T>(props: UseSortLayerProps<T>): UseSortLayerReturn;
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* ๋ฌธ์์ด์ ์ค๋ฐ๊ฟ(\n)์ `<br />` ์์๋ก ๋ณํํ๋ค.
|
|
142
|
+
*
|
|
143
|
+
* ์๋ฒ ์ปดํฌ๋ํธ / ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ ๋ชจ๋์์ ์์ ํ๊ฒ ์ฌ์ฉ ๊ฐ๋ฅํ๋ค.
|
|
144
|
+
*
|
|
145
|
+
* @param text ์ค๋ฐ๊ฟ์ ํฌํจํ ์ ์๋ ๋ฌธ์์ด
|
|
146
|
+
* @returns ReactNode ๋ฐฐ์ด (๋ฌธ์์ด + `<br />`)
|
|
147
|
+
*
|
|
148
|
+
* @example ๊ธฐ๋ณธ ์ฌ์ฉ
|
|
149
|
+
* ```tsx
|
|
150
|
+
* import { nl2br } from "@your-scope/toolkit/react";
|
|
151
|
+
*
|
|
152
|
+
* export default function Page() {
|
|
153
|
+
* return (
|
|
154
|
+
* <div>
|
|
155
|
+
* {nl2br("์ฒซ์ค\n๋์งธ์ค\n์
์งธ์ค")}
|
|
156
|
+
* </div>
|
|
157
|
+
* );
|
|
158
|
+
* }
|
|
159
|
+
* ```
|
|
160
|
+
*
|
|
161
|
+
* @example API ์๋ฌ ๋ฉ์์ง ์ถ๋ ฅ
|
|
162
|
+
* ```tsx
|
|
163
|
+
* Swal.fire({
|
|
164
|
+
* title: "์ค๋ฅ ๋ฐ์",
|
|
165
|
+
* html: nl2br(message),
|
|
166
|
+
* });
|
|
167
|
+
* ```
|
|
168
|
+
*
|
|
169
|
+
* @example textarea ๋ฏธ๋ฆฌ๋ณด๊ธฐ
|
|
170
|
+
* ```tsx
|
|
171
|
+
* <div className="preview">
|
|
172
|
+
* {nl2br(form.content)}
|
|
173
|
+
* </div>
|
|
174
|
+
* ```
|
|
175
|
+
*/
|
|
176
|
+
declare function nl2br(text: string | null | undefined): "" | (string | react.ReactElement<unknown, string | react.JSXElementConstructor<any>>)[];
|
|
177
|
+
|
|
178
|
+
export { type FormLayerMode, type UseFormLayerReturn, type UseSortLayerProps, type UseSortLayerReturn, nl2br, useFormLayer, useSortLayer };
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// src/react/useFormLayer.ts
|
|
2
|
+
import { useCallback, useState } from "react";
|
|
3
|
+
function useFormLayer() {
|
|
4
|
+
const [opened, setOpened] = useState(false);
|
|
5
|
+
const [mode, setMode] = useState(null);
|
|
6
|
+
const [id, setId] = useState(null);
|
|
7
|
+
const [parentId, setParentId] = useState(null);
|
|
8
|
+
const [payload, setPayload] = useState(null);
|
|
9
|
+
const open = useCallback(
|
|
10
|
+
(args) => {
|
|
11
|
+
setMode(args.mode);
|
|
12
|
+
setId(args.id ?? null);
|
|
13
|
+
setParentId(args.parentId ?? null);
|
|
14
|
+
setPayload(args.payload ?? null);
|
|
15
|
+
setOpened(true);
|
|
16
|
+
},
|
|
17
|
+
[]
|
|
18
|
+
);
|
|
19
|
+
const openCreate = useCallback((pId, pl) => {
|
|
20
|
+
open({ mode: "create", parentId: pId ?? null, id: null, payload: pl ?? null });
|
|
21
|
+
}, [open]);
|
|
22
|
+
const openEdit = useCallback((editId, pId, pl) => {
|
|
23
|
+
open({ mode: "edit", id: editId, parentId: pId ?? null, payload: pl ?? null });
|
|
24
|
+
}, [open]);
|
|
25
|
+
const close = useCallback(() => {
|
|
26
|
+
setOpened(false);
|
|
27
|
+
setMode(null);
|
|
28
|
+
setId(null);
|
|
29
|
+
setParentId(null);
|
|
30
|
+
setPayload(null);
|
|
31
|
+
}, []);
|
|
32
|
+
return {
|
|
33
|
+
opened,
|
|
34
|
+
mode,
|
|
35
|
+
id,
|
|
36
|
+
parentId,
|
|
37
|
+
payload,
|
|
38
|
+
open,
|
|
39
|
+
openCreate,
|
|
40
|
+
openEdit,
|
|
41
|
+
close,
|
|
42
|
+
setOpened,
|
|
43
|
+
setId,
|
|
44
|
+
setParentId,
|
|
45
|
+
setMode,
|
|
46
|
+
setPayload
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// src/react/useSortLayer.ts
|
|
51
|
+
import { useCallback as useCallback2, useMemo, useRef, useState as useState2 } from "react";
|
|
52
|
+
function useSortLayer(props) {
|
|
53
|
+
const { list, setList, onSave, clone } = props;
|
|
54
|
+
const [enabled, setEnabled] = useState2(false);
|
|
55
|
+
const backupRef = useRef(null);
|
|
56
|
+
const cloneFn = useMemo(() => {
|
|
57
|
+
return clone ?? ((items) => items.slice());
|
|
58
|
+
}, [clone]);
|
|
59
|
+
const start = useCallback2(() => {
|
|
60
|
+
backupRef.current = cloneFn(list);
|
|
61
|
+
setEnabled(true);
|
|
62
|
+
}, [cloneFn, list]);
|
|
63
|
+
const cancel = useCallback2(() => {
|
|
64
|
+
if (backupRef.current) {
|
|
65
|
+
setList(backupRef.current);
|
|
66
|
+
}
|
|
67
|
+
backupRef.current = null;
|
|
68
|
+
setEnabled(false);
|
|
69
|
+
}, [setList]);
|
|
70
|
+
const save = useCallback2(() => {
|
|
71
|
+
setEnabled(false);
|
|
72
|
+
backupRef.current = null;
|
|
73
|
+
onSave?.(cloneFn(list));
|
|
74
|
+
}, [cloneFn, list, onSave]);
|
|
75
|
+
return { start, cancel, save, enabled };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// src/react/nl2br.tsx
|
|
79
|
+
import jsxRuntime from "react/jsx-runtime";
|
|
80
|
+
function nl2br(text) {
|
|
81
|
+
const newlineRegex = /(\r\n|\r|\n)/g;
|
|
82
|
+
if (!text) return "";
|
|
83
|
+
const props = {};
|
|
84
|
+
return text.split(newlineRegex).map(function(line, index) {
|
|
85
|
+
if (line.match(newlineRegex)) {
|
|
86
|
+
return jsxRuntime.jsx("br", { key: index, ...props });
|
|
87
|
+
}
|
|
88
|
+
return line;
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
export {
|
|
92
|
+
nl2br,
|
|
93
|
+
useFormLayer,
|
|
94
|
+
useSortLayer
|
|
95
|
+
};
|