@yeongseoksong/framework 1.6.2 → 1.7.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.md +63 -1
- package/dist/platform/index.d.mts +40 -0
- package/dist/platform/index.mjs +30 -0
- package/dist/ui/index.mjs +104 -102
- package/dist/util/index.d.mts +50 -1
- package/dist/util/index.mjs +68 -0
- package/package.json +14 -33
- package/dist/store/index.cjs +0 -393
- package/dist/store/index.d.ts +0 -237
- package/dist/types/index.cjs +0 -18
- package/dist/types/index.d.ts +0 -105
- package/dist/ui/index.cjs +0 -3136
- package/dist/ui/index.d.ts +0 -1347
- package/dist/util/index.cjs +0 -199
- package/dist/util/index.d.ts +0 -114
package/dist/util/index.mjs
CHANGED
|
@@ -26,6 +26,8 @@ var _a2;
|
|
|
26
26
|
var LOGO_SRC = (_a2 = process.env.NEXT_PUBLIC_LOGO_SRC) != null ? _a2 : "/logo.svg";
|
|
27
27
|
var _a3;
|
|
28
28
|
var LOGO_ALT = (_a3 = process.env.NEXT_PUBLIC_LOGO_ALT) != null ? _a3 : "\uB85C\uACE0";
|
|
29
|
+
var _a4;
|
|
30
|
+
var API_BASE_URL = (_a4 = process.env.NEXT_PUBLIC_API_BASE_URL) != null ? _a4 : "";
|
|
29
31
|
|
|
30
32
|
// util/text.util.ts
|
|
31
33
|
var COMPANY_TOKEN = "%c";
|
|
@@ -148,16 +150,82 @@ function fixJosa(text) {
|
|
|
148
150
|
);
|
|
149
151
|
}
|
|
150
152
|
var WITH_FINAL = /* @__PURE__ */ new Set(["\uC740", "\uC774", "\uC744", "\uACFC"]);
|
|
153
|
+
|
|
154
|
+
// util/axios.util.ts
|
|
155
|
+
import axios from "axios";
|
|
156
|
+
var apiClient = axios.create({
|
|
157
|
+
baseURL: API_BASE_URL,
|
|
158
|
+
withCredentials: true,
|
|
159
|
+
timeout: 15e3,
|
|
160
|
+
headers: { Accept: "application/json" }
|
|
161
|
+
});
|
|
162
|
+
var getAccessToken = null;
|
|
163
|
+
function setAccessTokenGetter(getter) {
|
|
164
|
+
getAccessToken = getter;
|
|
165
|
+
}
|
|
166
|
+
apiClient.interceptors.request.use((config) => {
|
|
167
|
+
const token = getAccessToken == null ? void 0 : getAccessToken();
|
|
168
|
+
if (token) config.headers.set("Authorization", `Bearer ${token}`);
|
|
169
|
+
return config;
|
|
170
|
+
});
|
|
171
|
+
var refreshHandler = null;
|
|
172
|
+
function setRefreshHandler(handler) {
|
|
173
|
+
refreshHandler = handler;
|
|
174
|
+
}
|
|
175
|
+
var refreshPromise = null;
|
|
176
|
+
function refreshAccessToken() {
|
|
177
|
+
if (!refreshHandler) return Promise.resolve(false);
|
|
178
|
+
if (!refreshPromise) {
|
|
179
|
+
refreshPromise = refreshHandler().catch(() => false).finally(() => {
|
|
180
|
+
refreshPromise = null;
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
return refreshPromise;
|
|
184
|
+
}
|
|
185
|
+
var ApiError = class extends Error {
|
|
186
|
+
constructor(message, status, code) {
|
|
187
|
+
super(message);
|
|
188
|
+
this.name = "ApiError";
|
|
189
|
+
this.status = status;
|
|
190
|
+
this.code = code;
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
var onUnauthorized = null;
|
|
194
|
+
function setUnauthorizedHandler(handler) {
|
|
195
|
+
onUnauthorized = handler;
|
|
196
|
+
}
|
|
197
|
+
apiClient.interceptors.response.use(
|
|
198
|
+
(response) => response,
|
|
199
|
+
(error) => __async(null, null, function* () {
|
|
200
|
+
var _a5, _b, _c;
|
|
201
|
+
const status = (_a5 = error.response) == null ? void 0 : _a5.status;
|
|
202
|
+
const originalRequest = error.config;
|
|
203
|
+
if (status === 401 && refreshHandler && originalRequest && !originalRequest._retry) {
|
|
204
|
+
originalRequest._retry = true;
|
|
205
|
+
const refreshed = yield refreshAccessToken();
|
|
206
|
+
if (refreshed) return apiClient(originalRequest);
|
|
207
|
+
}
|
|
208
|
+
if (status === 401) onUnauthorized == null ? void 0 : onUnauthorized();
|
|
209
|
+
const body = (_b = error.response) == null ? void 0 : _b.data;
|
|
210
|
+
return Promise.reject(new ApiError((_c = body == null ? void 0 : body.message) != null ? _c : error.message, status, body == null ? void 0 : body.code));
|
|
211
|
+
})
|
|
212
|
+
);
|
|
151
213
|
export {
|
|
214
|
+
API_BASE_URL,
|
|
215
|
+
ApiError,
|
|
152
216
|
COMPANY_NAME,
|
|
153
217
|
LOGO_ALT,
|
|
154
218
|
LOGO_SRC,
|
|
219
|
+
apiClient,
|
|
155
220
|
filterAndSort,
|
|
156
221
|
fixJosa,
|
|
157
222
|
getFinalSound,
|
|
158
223
|
hasFinalConsonant,
|
|
159
224
|
josa,
|
|
160
225
|
runFinalizers,
|
|
226
|
+
setAccessTokenGetter,
|
|
227
|
+
setRefreshHandler,
|
|
228
|
+
setUnauthorizedHandler,
|
|
161
229
|
t,
|
|
162
230
|
withJosa
|
|
163
231
|
};
|
package/package.json
CHANGED
|
@@ -1,49 +1,29 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yeongseoksong/framework",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"files": [
|
|
5
5
|
"dist"
|
|
6
6
|
],
|
|
7
7
|
"exports": {
|
|
8
8
|
"./ui": {
|
|
9
|
-
"
|
|
10
|
-
|
|
11
|
-
"default": "./dist/ui/index.mjs"
|
|
12
|
-
},
|
|
13
|
-
"require": {
|
|
14
|
-
"types": "./dist/ui/index.d.ts",
|
|
15
|
-
"default": "./dist/ui/index.cjs"
|
|
16
|
-
}
|
|
9
|
+
"types": "./dist/ui/index.d.mts",
|
|
10
|
+
"default": "./dist/ui/index.mjs"
|
|
17
11
|
},
|
|
18
12
|
"./store": {
|
|
19
|
-
"
|
|
20
|
-
|
|
21
|
-
"default": "./dist/store/index.mjs"
|
|
22
|
-
},
|
|
23
|
-
"require": {
|
|
24
|
-
"types": "./dist/store/index.d.ts",
|
|
25
|
-
"default": "./dist/store/index.cjs"
|
|
26
|
-
}
|
|
13
|
+
"types": "./dist/store/index.d.mts",
|
|
14
|
+
"default": "./dist/store/index.mjs"
|
|
27
15
|
},
|
|
28
16
|
"./util": {
|
|
29
|
-
"
|
|
30
|
-
|
|
31
|
-
"default": "./dist/util/index.mjs"
|
|
32
|
-
},
|
|
33
|
-
"require": {
|
|
34
|
-
"types": "./dist/util/index.d.ts",
|
|
35
|
-
"default": "./dist/util/index.cjs"
|
|
36
|
-
}
|
|
17
|
+
"types": "./dist/util/index.d.mts",
|
|
18
|
+
"default": "./dist/util/index.mjs"
|
|
37
19
|
},
|
|
38
20
|
"./types": {
|
|
39
|
-
"
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
"
|
|
44
|
-
|
|
45
|
-
"default": "./dist/types/index.cjs"
|
|
46
|
-
}
|
|
21
|
+
"types": "./dist/types/index.d.mts",
|
|
22
|
+
"default": "./dist/types/index.mjs"
|
|
23
|
+
},
|
|
24
|
+
"./platform": {
|
|
25
|
+
"types": "./dist/platform/index.d.mts",
|
|
26
|
+
"default": "./dist/platform/index.mjs"
|
|
47
27
|
}
|
|
48
28
|
},
|
|
49
29
|
"publishConfig": {
|
|
@@ -60,6 +40,7 @@
|
|
|
60
40
|
"react": "19.2.4",
|
|
61
41
|
"react-dom": "19.2.4",
|
|
62
42
|
"@tabler/icons-react": "^3.44.0",
|
|
43
|
+
"axios": "^1.18.1",
|
|
63
44
|
"zustand": "^5.0.14"
|
|
64
45
|
},
|
|
65
46
|
"devDependencies": {
|
package/dist/store/index.cjs
DELETED
|
@@ -1,393 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
"use strict";
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __defProps = Object.defineProperties;
|
|
5
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
-
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
7
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
8
|
-
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
9
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
10
|
-
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
11
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
12
|
-
var __spreadValues = (a, b) => {
|
|
13
|
-
for (var prop in b || (b = {}))
|
|
14
|
-
if (__hasOwnProp.call(b, prop))
|
|
15
|
-
__defNormalProp(a, prop, b[prop]);
|
|
16
|
-
if (__getOwnPropSymbols)
|
|
17
|
-
for (var prop of __getOwnPropSymbols(b)) {
|
|
18
|
-
if (__propIsEnum.call(b, prop))
|
|
19
|
-
__defNormalProp(a, prop, b[prop]);
|
|
20
|
-
}
|
|
21
|
-
return a;
|
|
22
|
-
};
|
|
23
|
-
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
24
|
-
var __restKey = (key) => typeof key === "symbol" ? key : key + "";
|
|
25
|
-
var __objRest = (source, exclude) => {
|
|
26
|
-
var target = {};
|
|
27
|
-
for (var prop in source)
|
|
28
|
-
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
|
|
29
|
-
target[prop] = source[prop];
|
|
30
|
-
if (source != null && __getOwnPropSymbols)
|
|
31
|
-
for (var prop of __getOwnPropSymbols(source)) {
|
|
32
|
-
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
|
|
33
|
-
target[prop] = source[prop];
|
|
34
|
-
}
|
|
35
|
-
return target;
|
|
36
|
-
};
|
|
37
|
-
var __export = (target, all) => {
|
|
38
|
-
for (var name in all)
|
|
39
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
40
|
-
};
|
|
41
|
-
var __copyProps = (to, from, except, desc) => {
|
|
42
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
43
|
-
for (let key of __getOwnPropNames(from))
|
|
44
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
45
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
46
|
-
}
|
|
47
|
-
return to;
|
|
48
|
-
};
|
|
49
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
50
|
-
var __async = (__this, __arguments, generator) => {
|
|
51
|
-
return new Promise((resolve, reject) => {
|
|
52
|
-
var fulfilled = (value) => {
|
|
53
|
-
try {
|
|
54
|
-
step(generator.next(value));
|
|
55
|
-
} catch (e) {
|
|
56
|
-
reject(e);
|
|
57
|
-
}
|
|
58
|
-
};
|
|
59
|
-
var rejected = (value) => {
|
|
60
|
-
try {
|
|
61
|
-
step(generator.throw(value));
|
|
62
|
-
} catch (e) {
|
|
63
|
-
reject(e);
|
|
64
|
-
}
|
|
65
|
-
};
|
|
66
|
-
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
67
|
-
step((generator = generator.apply(__this, __arguments)).next());
|
|
68
|
-
});
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
// store/index.ts
|
|
72
|
-
var store_exports = {};
|
|
73
|
-
__export(store_exports, {
|
|
74
|
-
formRules: () => formRules,
|
|
75
|
-
useAuthHydrated: () => useAuthHydrated,
|
|
76
|
-
useAuthStore: () => useAuthStore,
|
|
77
|
-
useFormStore: () => useFormStore,
|
|
78
|
-
useNavStore: () => useNavStore,
|
|
79
|
-
useSdForm: () => useSdForm,
|
|
80
|
-
useUiStore: () => useUiStore
|
|
81
|
-
});
|
|
82
|
-
module.exports = __toCommonJS(store_exports);
|
|
83
|
-
|
|
84
|
-
// store/auth.store.ts
|
|
85
|
-
var import_react = require("react");
|
|
86
|
-
var import_zustand = require("zustand");
|
|
87
|
-
var import_middleware = require("zustand/middleware");
|
|
88
|
-
var useAuthStore = (0, import_zustand.create)()(
|
|
89
|
-
(0, import_middleware.persist)(
|
|
90
|
-
(set) => ({
|
|
91
|
-
user: null,
|
|
92
|
-
isAuthenticated: false,
|
|
93
|
-
hasHydrated: false,
|
|
94
|
-
login: (user) => set({ user, isAuthenticated: true }),
|
|
95
|
-
logout: () => set({ user: null, isAuthenticated: false }),
|
|
96
|
-
setHasHydrated: (value) => set({ hasHydrated: value })
|
|
97
|
-
}),
|
|
98
|
-
{
|
|
99
|
-
name: "sd-auth",
|
|
100
|
-
storage: (0, import_middleware.createJSONStorage)(() => localStorage),
|
|
101
|
-
partialize: (state) => ({ user: state.user, isAuthenticated: state.isAuthenticated }),
|
|
102
|
-
skipHydration: true,
|
|
103
|
-
onRehydrateStorage: () => (state) => state == null ? void 0 : state.setHasHydrated(true)
|
|
104
|
-
}
|
|
105
|
-
)
|
|
106
|
-
);
|
|
107
|
-
var rehydrateStarted = false;
|
|
108
|
-
function useAuthHydrated() {
|
|
109
|
-
const hasHydrated = useAuthStore((state) => state.hasHydrated);
|
|
110
|
-
(0, import_react.useEffect)(() => {
|
|
111
|
-
if (rehydrateStarted) return;
|
|
112
|
-
rehydrateStarted = true;
|
|
113
|
-
void useAuthStore.persist.rehydrate();
|
|
114
|
-
}, []);
|
|
115
|
-
return hasHydrated;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// store/ui.store.ts
|
|
119
|
-
var import_zustand2 = require("zustand");
|
|
120
|
-
var useUiStore = (0, import_zustand2.create)()((set) => ({
|
|
121
|
-
globalLoading: false,
|
|
122
|
-
setGlobalLoading: (value) => set({ globalLoading: value }),
|
|
123
|
-
sideNavOpened: false,
|
|
124
|
-
openSideNav: () => set({ sideNavOpened: true }),
|
|
125
|
-
closeSideNav: () => set({ sideNavOpened: false }),
|
|
126
|
-
toggleSideNav: () => set((state) => ({ sideNavOpened: !state.sideNavOpened }))
|
|
127
|
-
}));
|
|
128
|
-
|
|
129
|
-
// store/nav.store.ts
|
|
130
|
-
var import_zustand3 = require("zustand");
|
|
131
|
-
var useNavStore = (0, import_zustand3.create)()((set) => ({
|
|
132
|
-
navItems: [],
|
|
133
|
-
setNavItems: (navItems) => set({ navItems })
|
|
134
|
-
}));
|
|
135
|
-
|
|
136
|
-
// store/form.state.ts
|
|
137
|
-
var import_react2 = require("react");
|
|
138
|
-
var import_zustand4 = require("zustand");
|
|
139
|
-
|
|
140
|
-
// ui/atom/Toast.tsx
|
|
141
|
-
var import_notifications = require("@mantine/notifications");
|
|
142
|
-
var import_icons_react = require("@tabler/icons-react");
|
|
143
|
-
var import_jsx_runtime = require("react/jsx-runtime");
|
|
144
|
-
var toastStyles = {
|
|
145
|
-
/** 성공 — 저장·전송 완료 */
|
|
146
|
-
Success: { color: "green", icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons_react.IconCheck, { size: 18 }), title: "\uC644\uB8CC" },
|
|
147
|
-
/** 실패 — 요청 오류·검증 실패 */
|
|
148
|
-
Error: { color: "red", icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons_react.IconX, { size: 18 }), title: "\uC624\uB958" },
|
|
149
|
-
/** 주의 — 되돌릴 수 없는 동작 안내 등 */
|
|
150
|
-
Warning: { color: "amber", icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons_react.IconAlertTriangle, { size: 18 }), title: "\uC8FC\uC758" },
|
|
151
|
-
/** 안내 — 중립 정보 */
|
|
152
|
-
Info: { color: "primary", icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons_react.IconInfoCircle, { size: 18 }), title: "\uC548\uB0B4" },
|
|
153
|
-
/** 진행 중 — 스피너 + 자동 닫힘 없음. Update로 결과 변형으로 바꾼다. */
|
|
154
|
-
Loading: { loading: true, autoClose: false, withCloseButton: false, title: "\uCC98\uB9AC \uC911" }
|
|
155
|
-
};
|
|
156
|
-
function createToast(defaults) {
|
|
157
|
-
return function SdToast2(message, options) {
|
|
158
|
-
return import_notifications.notifications.show(__spreadValues(__spreadProps(__spreadValues({}, defaults), { message }), options));
|
|
159
|
-
};
|
|
160
|
-
}
|
|
161
|
-
var SdToast = {
|
|
162
|
-
Success: createToast(toastStyles.Success),
|
|
163
|
-
Error: createToast(toastStyles.Error),
|
|
164
|
-
Warning: createToast(toastStyles.Warning),
|
|
165
|
-
Info: createToast(toastStyles.Info),
|
|
166
|
-
Loading: createToast(toastStyles.Loading),
|
|
167
|
-
/**
|
|
168
|
-
* 이미 떠 있는 알림을 다른 변형으로 교체한다 — `Loading` → `Success`/`Error` 전환용.
|
|
169
|
-
* `loading: false`·`autoClose`를 먼저 깔아 두므로 스피너가 그대로 남지 않는다.
|
|
170
|
-
*/
|
|
171
|
-
Update: (id, variant, message, options) => import_notifications.notifications.update(__spreadValues(__spreadProps(__spreadValues({
|
|
172
|
-
id,
|
|
173
|
-
loading: false,
|
|
174
|
-
autoClose: 4e3,
|
|
175
|
-
withCloseButton: true
|
|
176
|
-
}, toastStyles[variant]), {
|
|
177
|
-
message
|
|
178
|
-
}), options)),
|
|
179
|
-
/** 특정 알림 닫기 */
|
|
180
|
-
Hide: (id) => import_notifications.notifications.hide(id),
|
|
181
|
-
/** 떠 있는 알림 전부 닫기 */
|
|
182
|
-
Clean: () => import_notifications.notifications.clean()
|
|
183
|
-
};
|
|
184
|
-
var SdToastSuccess = SdToast.Success;
|
|
185
|
-
var SdToastError = SdToast.Error;
|
|
186
|
-
var SdToastWarning = SdToast.Warning;
|
|
187
|
-
var SdToastInfo = SdToast.Info;
|
|
188
|
-
var SdToastLoading = SdToast.Loading;
|
|
189
|
-
var SdToastUpdate = SdToast.Update;
|
|
190
|
-
var SdToastHide = SdToast.Hide;
|
|
191
|
-
var SdToastClean = SdToast.Clean;
|
|
192
|
-
|
|
193
|
-
// util/finalize.util.ts
|
|
194
|
-
function runFinalizers(finalize, label = "finalize") {
|
|
195
|
-
return __async(this, null, function* () {
|
|
196
|
-
if (!finalize) return;
|
|
197
|
-
const list = Array.isArray(finalize) ? finalize : [finalize];
|
|
198
|
-
for (const fn of list) {
|
|
199
|
-
try {
|
|
200
|
-
yield fn();
|
|
201
|
-
} catch (caught) {
|
|
202
|
-
console.error(`[${label}] finalize\uC5D0\uC11C \uC608\uC678\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4.`, caught);
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
});
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
// store/form.state.ts
|
|
209
|
-
var EMPTY_ERRORS = {};
|
|
210
|
-
function readChangePayload(payload) {
|
|
211
|
-
if (payload && typeof payload === "object" && "currentTarget" in payload) {
|
|
212
|
-
const target = payload.currentTarget;
|
|
213
|
-
if (target && typeof target === "object" && "value" in target) {
|
|
214
|
-
return target.type === "checkbox" ? target.checked : target.value;
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
return payload;
|
|
218
|
-
}
|
|
219
|
-
function blankEntry(values) {
|
|
220
|
-
return { values, errors: {}, submitting: false, error: null };
|
|
221
|
-
}
|
|
222
|
-
function patch(state, formId, next) {
|
|
223
|
-
const current = state.forms[formId];
|
|
224
|
-
if (!current) return state;
|
|
225
|
-
return __spreadProps(__spreadValues({}, state), { forms: __spreadProps(__spreadValues({}, state.forms), { [formId]: __spreadValues(__spreadValues({}, current), next) }) });
|
|
226
|
-
}
|
|
227
|
-
var useFormStore = (0, import_zustand4.create)()((set) => ({
|
|
228
|
-
forms: {},
|
|
229
|
-
ensureForm: (formId, initialValues) => set(
|
|
230
|
-
(state) => state.forms[formId] ? state : __spreadProps(__spreadValues({}, state), { forms: __spreadProps(__spreadValues({}, state.forms), { [formId]: blankEntry(initialValues) }) })
|
|
231
|
-
),
|
|
232
|
-
setValue: (formId, name, value) => set((state) => {
|
|
233
|
-
const current = state.forms[formId];
|
|
234
|
-
if (!current) return state;
|
|
235
|
-
const _a = current.errors, { [name]: _removed } = _a, restErrors = __objRest(_a, [__restKey(name)]);
|
|
236
|
-
return patch(state, formId, {
|
|
237
|
-
values: __spreadProps(__spreadValues({}, current.values), { [name]: value }),
|
|
238
|
-
errors: restErrors
|
|
239
|
-
});
|
|
240
|
-
}),
|
|
241
|
-
setValues: (formId, values) => set((state) => {
|
|
242
|
-
const current = state.forms[formId];
|
|
243
|
-
if (!current) return state;
|
|
244
|
-
return patch(state, formId, { values: __spreadValues(__spreadValues({}, current.values), values) });
|
|
245
|
-
}),
|
|
246
|
-
setErrors: (formId, errors) => set((state) => patch(state, formId, { errors })),
|
|
247
|
-
setSubmitting: (formId, submitting) => set((state) => patch(state, formId, { submitting })),
|
|
248
|
-
setError: (formId, error) => set((state) => patch(state, formId, { error })),
|
|
249
|
-
resetForm: (formId, initialValues) => set((state) => __spreadProps(__spreadValues({}, state), { forms: __spreadProps(__spreadValues({}, state.forms), { [formId]: blankEntry(initialValues) }) })),
|
|
250
|
-
removeForm: (formId) => set((state) => {
|
|
251
|
-
const _a = state.forms, { [formId]: _removed } = _a, rest = __objRest(_a, [__restKey(formId)]);
|
|
252
|
-
return __spreadProps(__spreadValues({}, state), { forms: rest });
|
|
253
|
-
})
|
|
254
|
-
}));
|
|
255
|
-
function useSdForm({
|
|
256
|
-
id,
|
|
257
|
-
initialValues,
|
|
258
|
-
rules,
|
|
259
|
-
onSubmit,
|
|
260
|
-
successMessage,
|
|
261
|
-
errorMessage,
|
|
262
|
-
resetOnSuccess,
|
|
263
|
-
onSuccess,
|
|
264
|
-
onError,
|
|
265
|
-
finalize
|
|
266
|
-
}) {
|
|
267
|
-
var _a, _b, _c, _d;
|
|
268
|
-
const entry = useFormStore((state) => state.forms[id]);
|
|
269
|
-
const store = useFormStore;
|
|
270
|
-
(0, import_react2.useEffect)(() => {
|
|
271
|
-
store.getState().ensureForm(id, initialValues);
|
|
272
|
-
}, [id]);
|
|
273
|
-
const values = (_a = entry == null ? void 0 : entry.values) != null ? _a : initialValues;
|
|
274
|
-
const errors = (_b = entry == null ? void 0 : entry.errors) != null ? _b : EMPTY_ERRORS;
|
|
275
|
-
const submitting = (_c = entry == null ? void 0 : entry.submitting) != null ? _c : false;
|
|
276
|
-
const error = (_d = entry == null ? void 0 : entry.error) != null ? _d : null;
|
|
277
|
-
const setValue = (0, import_react2.useCallback)(
|
|
278
|
-
(name, value) => store.getState().setValue(id, String(name), value),
|
|
279
|
-
[id, store]
|
|
280
|
-
);
|
|
281
|
-
const setValues = (0, import_react2.useCallback)(
|
|
282
|
-
(next) => store.getState().setValues(id, next),
|
|
283
|
-
[id, store]
|
|
284
|
-
);
|
|
285
|
-
const reset = (0, import_react2.useCallback)(
|
|
286
|
-
() => store.getState().resetForm(id, initialValues),
|
|
287
|
-
// initialValues 참조가 바뀌어도 reset의 의미는 같다.
|
|
288
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
289
|
-
[id, store]
|
|
290
|
-
);
|
|
291
|
-
const getInputProps = (0, import_react2.useCallback)(
|
|
292
|
-
(name, options) => {
|
|
293
|
-
const key = String(name);
|
|
294
|
-
const fieldError = errors[name];
|
|
295
|
-
const current = values[name];
|
|
296
|
-
const onChange = (payload) => store.getState().setValue(id, key, readChangePayload(payload));
|
|
297
|
-
if ((options == null ? void 0 : options.type) === "checkbox") {
|
|
298
|
-
return { checked: Boolean(current), error: fieldError, onChange };
|
|
299
|
-
}
|
|
300
|
-
return {
|
|
301
|
-
// undefined일 때만 ''로 메운다 — null은 그대로 둬야 Select·Date가 "값 없음"으로 읽는다.
|
|
302
|
-
value: current === void 0 ? "" : current,
|
|
303
|
-
error: fieldError,
|
|
304
|
-
onChange
|
|
305
|
-
};
|
|
306
|
-
},
|
|
307
|
-
[errors, id, store, values]
|
|
308
|
-
);
|
|
309
|
-
const handleSubmit = (0, import_react2.useCallback)(
|
|
310
|
-
(event) => __async(null, null, function* () {
|
|
311
|
-
var _a2, _b2;
|
|
312
|
-
event == null ? void 0 : event.preventDefault();
|
|
313
|
-
const state = store.getState();
|
|
314
|
-
const current = state.forms[id];
|
|
315
|
-
if (current == null ? void 0 : current.submitting) return;
|
|
316
|
-
const currentValues = (_a2 = current == null ? void 0 : current.values) != null ? _a2 : initialValues;
|
|
317
|
-
if (rules) {
|
|
318
|
-
const found = {};
|
|
319
|
-
for (const [name, rule] of Object.entries(rules)) {
|
|
320
|
-
const message = rule == null ? void 0 : rule(currentValues[name], currentValues);
|
|
321
|
-
if (message) found[name] = message;
|
|
322
|
-
}
|
|
323
|
-
if (Object.keys(found).length > 0) {
|
|
324
|
-
state.setErrors(id, found);
|
|
325
|
-
return;
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
state.setErrors(id, {});
|
|
329
|
-
state.setError(id, null);
|
|
330
|
-
state.setSubmitting(id, true);
|
|
331
|
-
try {
|
|
332
|
-
yield onSubmit(currentValues);
|
|
333
|
-
if (successMessage !== false) SdToast.Success(successMessage != null ? successMessage : "\uC800\uC7A5\uD588\uC2B5\uB2C8\uB2E4.");
|
|
334
|
-
if (resetOnSuccess) state.resetForm(id, initialValues);
|
|
335
|
-
onSuccess == null ? void 0 : onSuccess(currentValues);
|
|
336
|
-
} catch (caught) {
|
|
337
|
-
const message = (_b2 = errorMessage == null ? void 0 : errorMessage(caught)) != null ? _b2 : caught instanceof Error ? caught.message : "\uC694\uCCAD\uC744 \uCC98\uB9AC\uD558\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.";
|
|
338
|
-
state.setError(id, message);
|
|
339
|
-
SdToast.Error(message);
|
|
340
|
-
onError == null ? void 0 : onError(caught);
|
|
341
|
-
} finally {
|
|
342
|
-
store.getState().setSubmitting(id, false);
|
|
343
|
-
yield runFinalizers(finalize, "useSdForm");
|
|
344
|
-
}
|
|
345
|
-
}),
|
|
346
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
347
|
-
[
|
|
348
|
-
id,
|
|
349
|
-
store,
|
|
350
|
-
rules,
|
|
351
|
-
onSubmit,
|
|
352
|
-
successMessage,
|
|
353
|
-
errorMessage,
|
|
354
|
-
resetOnSuccess,
|
|
355
|
-
onSuccess,
|
|
356
|
-
onError,
|
|
357
|
-
finalize
|
|
358
|
-
]
|
|
359
|
-
);
|
|
360
|
-
return (0, import_react2.useMemo)(
|
|
361
|
-
() => ({
|
|
362
|
-
values,
|
|
363
|
-
errors,
|
|
364
|
-
submitting,
|
|
365
|
-
error,
|
|
366
|
-
setValue,
|
|
367
|
-
setValues,
|
|
368
|
-
reset,
|
|
369
|
-
getInputProps,
|
|
370
|
-
onSubmit: handleSubmit
|
|
371
|
-
}),
|
|
372
|
-
[values, errors, submitting, error, setValue, setValues, reset, getInputProps, handleSubmit]
|
|
373
|
-
);
|
|
374
|
-
}
|
|
375
|
-
var formRules = {
|
|
376
|
-
required: (message = "\uD544\uC218 \uC785\uB825 \uD56D\uBAA9\uC785\uB2C8\uB2E4.") => (value) => value === void 0 || value === null || String(value).trim() === "" ? message : null,
|
|
377
|
-
email: (message = "\uC774\uBA54\uC77C \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.") => (value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(String(value != null ? value : "")) ? null : message,
|
|
378
|
-
minLength: (length, message) => (value) => String(value != null ? value : "").length >= length ? null : message != null ? message : `${length}\uC790 \uC774\uC0C1 \uC785\uB825\uD558\uC138\uC694.`,
|
|
379
|
-
/** 체크박스 동의 — 반드시 true여야 한다. */
|
|
380
|
-
checked: (message = "\uB3D9\uC758\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.") => (value) => value === true ? null : message,
|
|
381
|
-
/** 다른 필드와 같은 값인지 — 비밀번호 확인 등. */
|
|
382
|
-
sameAs: (other, message = "\uAC12\uC774 \uC77C\uCE58\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.") => (value, values) => value === values[other] ? null : message
|
|
383
|
-
};
|
|
384
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
385
|
-
0 && (module.exports = {
|
|
386
|
-
formRules,
|
|
387
|
-
useAuthHydrated,
|
|
388
|
-
useAuthStore,
|
|
389
|
-
useFormStore,
|
|
390
|
-
useNavStore,
|
|
391
|
-
useSdForm,
|
|
392
|
-
useUiStore
|
|
393
|
-
});
|