dn-react-router-toolkit 0.1.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 +1 -0
- package/dist/cjs/auth-kit/apple_auth.js +60 -0
- package/dist/cjs/auth-kit/auth_service.js +204 -0
- package/dist/cjs/auth-kit/client/google_login_button.js +25 -0
- package/dist/cjs/auth-kit/client/redirect_page.js +21 -0
- package/dist/cjs/auth-kit/google_auth.js +65 -0
- package/dist/cjs/auth-kit/jwt.js +53 -0
- package/dist/cjs/auth-kit/kakao_auth.js +38 -0
- package/dist/cjs/auth-kit/repository.js +2 -0
- package/dist/cjs/auth-kit/with_auth.js +46 -0
- package/dist/cjs/cn.js +6 -0
- package/dist/cjs/components/index.js +18 -0
- package/dist/cjs/components/modal/fullscreen_container.js +64 -0
- package/dist/cjs/components/modal/hooks.js +78 -0
- package/dist/cjs/components/modal/index.js +19 -0
- package/dist/cjs/components/modal/modal.js +91 -0
- package/dist/cjs/components/styles.js +10 -0
- package/dist/cjs/date.js +31 -0
- package/dist/cjs/file-kit/cdn.js +9 -0
- package/dist/cjs/file-kit/client/drop_file_input.js +195 -0
- package/dist/cjs/file-kit/client/file_uploader.js +78 -0
- package/dist/cjs/file-kit/file_service.js +29 -0
- package/dist/cjs/file-kit/object_storage.js +50 -0
- package/dist/cjs/file-kit/repository.js +2 -0
- package/dist/cjs/file-kit/responsive_image.js +78 -0
- package/dist/cjs/http-kit/index.js +17 -0
- package/dist/cjs/http-kit/response.js +34 -0
- package/dist/cjs/index.js +20 -0
- package/dist/cjs/route/api/auth/login/[provider]/route.js +36 -0
- package/dist/cjs/route/api/auth/login/route.js +35 -0
- package/dist/cjs/route/api/auth/logout/route.js +22 -0
- package/dist/cjs/route/api/auth/refresh/route.js +23 -0
- package/dist/cjs/route/api/auth/route.js +12 -0
- package/dist/cjs/route/api/files/[fileId]/route.js +20 -0
- package/dist/cjs/route/api/files/route.js +34 -0
- package/dist/cjs/route/auth/callback/[provider]/route.js +35 -0
- package/dist/cjs/route/index.js +80 -0
- package/dist/cjs/seo-kit/index.js +19 -0
- package/dist/cjs/seo-kit/loader.js +17 -0
- package/dist/cjs/seo-kit/seo.js +286 -0
- package/dist/cjs/seo-kit/seo_loader.js +19 -0
- package/dist/cjs/singleton.js +12 -0
- package/dist/cjs/slug.js +10 -0
- package/dist/esm/auth-kit/apple_auth.d.ts +15 -0
- package/dist/esm/auth-kit/apple_auth.js +56 -0
- package/dist/esm/auth-kit/auth_service.d.ts +67 -0
- package/dist/esm/auth-kit/auth_service.js +197 -0
- package/dist/esm/auth-kit/client/google_login_button.d.ts +6 -0
- package/dist/esm/auth-kit/client/google_login_button.js +19 -0
- package/dist/esm/auth-kit/client/redirect_page.d.ts +2 -0
- package/dist/esm/auth-kit/client/redirect_page.js +15 -0
- package/dist/esm/auth-kit/google_auth.d.ts +18 -0
- package/dist/esm/auth-kit/google_auth.js +61 -0
- package/dist/esm/auth-kit/jwt.d.ts +15 -0
- package/dist/esm/auth-kit/jwt.js +49 -0
- package/dist/esm/auth-kit/kakao_auth.d.ts +15 -0
- package/dist/esm/auth-kit/kakao_auth.js +34 -0
- package/dist/esm/auth-kit/repository.d.ts +40 -0
- package/dist/esm/auth-kit/repository.js +1 -0
- package/dist/esm/auth-kit/with_auth.d.ts +12 -0
- package/dist/esm/auth-kit/with_auth.js +43 -0
- package/dist/esm/cn.d.ts +1 -0
- package/dist/esm/cn.js +3 -0
- package/dist/esm/components/index.d.ts +2 -0
- package/dist/esm/components/index.js +2 -0
- package/dist/esm/components/modal/fullscreen_container.d.ts +5 -0
- package/dist/esm/components/modal/fullscreen_container.js +57 -0
- package/dist/esm/components/modal/hooks.d.ts +15 -0
- package/dist/esm/components/modal/hooks.js +69 -0
- package/dist/esm/components/modal/index.d.ts +3 -0
- package/dist/esm/components/modal/index.js +3 -0
- package/dist/esm/components/modal/modal.d.ts +10 -0
- package/dist/esm/components/modal/modal.js +55 -0
- package/dist/esm/components/styles.d.ts +7 -0
- package/dist/esm/components/styles.js +7 -0
- package/dist/esm/date.d.ts +1 -0
- package/dist/esm/date.js +24 -0
- package/dist/esm/file-kit/cdn.d.ts +3 -0
- package/dist/esm/file-kit/cdn.js +5 -0
- package/dist/esm/file-kit/client/drop_file_input.d.ts +31 -0
- package/dist/esm/file-kit/client/drop_file_input.js +158 -0
- package/dist/esm/file-kit/client/file_uploader.d.ts +11 -0
- package/dist/esm/file-kit/client/file_uploader.js +74 -0
- package/dist/esm/file-kit/file_service.d.ts +23 -0
- package/dist/esm/file-kit/file_service.js +25 -0
- package/dist/esm/file-kit/object_storage.d.ts +13 -0
- package/dist/esm/file-kit/object_storage.js +46 -0
- package/dist/esm/file-kit/repository.d.ts +14 -0
- package/dist/esm/file-kit/repository.js +1 -0
- package/dist/esm/file-kit/responsive_image.d.ts +17 -0
- package/dist/esm/file-kit/responsive_image.js +70 -0
- package/dist/esm/http-kit/index.d.ts +1 -0
- package/dist/esm/http-kit/index.js +1 -0
- package/dist/esm/http-kit/response.d.ts +17 -0
- package/dist/esm/http-kit/response.js +28 -0
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.js +4 -0
- package/dist/esm/route/api/auth/login/[provider]/route.d.ts +10 -0
- package/dist/esm/route/api/auth/login/[provider]/route.js +32 -0
- package/dist/esm/route/api/auth/login/route.d.ts +6 -0
- package/dist/esm/route/api/auth/login/route.js +31 -0
- package/dist/esm/route/api/auth/logout/route.d.ts +6 -0
- package/dist/esm/route/api/auth/logout/route.js +18 -0
- package/dist/esm/route/api/auth/refresh/route.d.ts +4 -0
- package/dist/esm/route/api/auth/refresh/route.js +19 -0
- package/dist/esm/route/api/auth/route.d.ts +4 -0
- package/dist/esm/route/api/auth/route.js +8 -0
- package/dist/esm/route/api/files/[fileId]/route.d.ts +8 -0
- package/dist/esm/route/api/files/[fileId]/route.js +16 -0
- package/dist/esm/route/api/files/route.d.ts +6 -0
- package/dist/esm/route/api/files/route.js +30 -0
- package/dist/esm/route/auth/callback/[provider]/route.d.ts +11 -0
- package/dist/esm/route/auth/callback/[provider]/route.js +31 -0
- package/dist/esm/route/index.d.ts +22 -0
- package/dist/esm/route/index.js +76 -0
- package/dist/esm/seo-kit/index.d.ts +3 -0
- package/dist/esm/seo-kit/index.js +3 -0
- package/dist/esm/seo-kit/loader.d.ts +5 -0
- package/dist/esm/seo-kit/loader.js +14 -0
- package/dist/esm/seo-kit/seo.d.ts +100 -0
- package/dist/esm/seo-kit/seo.js +280 -0
- package/dist/esm/seo-kit/seo_loader.d.ts +12 -0
- package/dist/esm/seo-kit/seo_loader.js +13 -0
- package/dist/esm/singleton.d.ts +1 -0
- package/dist/esm/singleton.js +9 -0
- package/dist/esm/slug.d.ts +1 -0
- package/dist/esm/slug.js +6 -0
- package/package.json +81 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ModalContext = void 0;
|
|
7
|
+
exports.useModalRoot = useModalRoot;
|
|
8
|
+
exports.useModalPortal = useModalPortal;
|
|
9
|
+
exports.useModal = useModal;
|
|
10
|
+
const react_1 = require("react");
|
|
11
|
+
const react_dom_1 = require("react-dom");
|
|
12
|
+
const modal_1 = __importDefault(require("./modal"));
|
|
13
|
+
const react_2 = __importDefault(require("react"));
|
|
14
|
+
function useModalRoot() {
|
|
15
|
+
const [container, setContainer] = (0, react_1.useState)(null);
|
|
16
|
+
(0, react_1.useEffect)(() => {
|
|
17
|
+
const container = document.getElementById("modal-root");
|
|
18
|
+
if (container) {
|
|
19
|
+
setContainer(container);
|
|
20
|
+
}
|
|
21
|
+
return () => {
|
|
22
|
+
setContainer(null);
|
|
23
|
+
};
|
|
24
|
+
}, []);
|
|
25
|
+
return container;
|
|
26
|
+
}
|
|
27
|
+
function useModalPortal() {
|
|
28
|
+
const container = useModalRoot();
|
|
29
|
+
if (!container) {
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
31
|
+
return (children) => null;
|
|
32
|
+
}
|
|
33
|
+
return (children) => {
|
|
34
|
+
return (0, react_dom_1.createPortal)(children, container);
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
38
|
+
exports.ModalContext = (0, react_1.createContext)({});
|
|
39
|
+
function useModal() {
|
|
40
|
+
const ch2 = (0, react_1.useRef)(null);
|
|
41
|
+
const open = () => {
|
|
42
|
+
var _a;
|
|
43
|
+
(_a = ch2.current) === null || _a === void 0 ? void 0 : _a.call(ch2, true);
|
|
44
|
+
};
|
|
45
|
+
const close = () => {
|
|
46
|
+
var _a;
|
|
47
|
+
(_a = ch2.current) === null || _a === void 0 ? void 0 : _a.call(ch2, false);
|
|
48
|
+
};
|
|
49
|
+
const Component = (0, react_1.useCallback)(function Component(props) {
|
|
50
|
+
const [isOpen, setIsOpen] = (0, react_1.useState)(false);
|
|
51
|
+
const createPortal = useModalPortal();
|
|
52
|
+
(0, react_1.useEffect)(() => {
|
|
53
|
+
ch2.current = (v) => {
|
|
54
|
+
setIsOpen(v);
|
|
55
|
+
};
|
|
56
|
+
return () => {
|
|
57
|
+
ch2.current = null;
|
|
58
|
+
};
|
|
59
|
+
}, []);
|
|
60
|
+
(0, react_1.useEffect)(() => {
|
|
61
|
+
if (isOpen) {
|
|
62
|
+
// document.body.style.overflow = "hidden";
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
// document.body.style.overflow = "";
|
|
66
|
+
}
|
|
67
|
+
return () => {
|
|
68
|
+
// document.body.style.overflow = "";
|
|
69
|
+
};
|
|
70
|
+
}, [isOpen]);
|
|
71
|
+
return (react_2.default.createElement(exports.ModalContext.Provider, { value: { open, close, isOpen } }, createPortal(react_2.default.createElement(modal_1.default, Object.assign({}, props, { open: isOpen, onBackgroundClick: close })))));
|
|
72
|
+
}, []);
|
|
73
|
+
return {
|
|
74
|
+
open,
|
|
75
|
+
close,
|
|
76
|
+
Modal: Component,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./fullscreen_container"), exports);
|
|
18
|
+
__exportStar(require("./hooks"), exports);
|
|
19
|
+
__exportStar(require("./modal"), exports);
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
36
|
+
var t = {};
|
|
37
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
38
|
+
t[p] = s[p];
|
|
39
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
40
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
41
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
42
|
+
t[p[i]] = s[p[i]];
|
|
43
|
+
}
|
|
44
|
+
return t;
|
|
45
|
+
};
|
|
46
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
47
|
+
exports.default = Modal;
|
|
48
|
+
const react_1 = __importStar(require("react"));
|
|
49
|
+
const fullscreen_container_1 = require("./fullscreen_container");
|
|
50
|
+
const cn_1 = require("../../cn");
|
|
51
|
+
function Modal(_a) {
|
|
52
|
+
var { open, className, background = "bg-gray-500/25", onBackgroundClick, children } = _a, props = __rest(_a, ["open", "className", "background", "onBackgroundClick", "children"]);
|
|
53
|
+
const containerRef = (0, react_1.useRef)(null);
|
|
54
|
+
const fullscreen = (0, fullscreen_container_1.useFullscreen)(containerRef);
|
|
55
|
+
const [mounted, setMounted] = react_1.default.useState(false);
|
|
56
|
+
(0, react_1.useEffect)(() => {
|
|
57
|
+
if (open) {
|
|
58
|
+
// document.body.style.overflow = "hidden";
|
|
59
|
+
setMounted(true);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
// document.body.style.overflow = "";
|
|
63
|
+
setTimeout(() => {
|
|
64
|
+
setMounted(false);
|
|
65
|
+
}, 200);
|
|
66
|
+
}
|
|
67
|
+
return () => {
|
|
68
|
+
// document.body.style.overflow = "";
|
|
69
|
+
};
|
|
70
|
+
}, [open]);
|
|
71
|
+
const onBackgroundMouseDown = (event) => {
|
|
72
|
+
event.preventDefault();
|
|
73
|
+
onBackgroundClick === null || onBackgroundClick === void 0 ? void 0 : onBackgroundClick();
|
|
74
|
+
};
|
|
75
|
+
const onModalMouseDown = (event) => {
|
|
76
|
+
event.stopPropagation();
|
|
77
|
+
};
|
|
78
|
+
const onBackgroundTouchStart = (event) => {
|
|
79
|
+
event.preventDefault();
|
|
80
|
+
onBackgroundClick === null || onBackgroundClick === void 0 ? void 0 : onBackgroundClick();
|
|
81
|
+
};
|
|
82
|
+
const onModalTouchStart = (event) => {
|
|
83
|
+
event.stopPropagation();
|
|
84
|
+
};
|
|
85
|
+
return (react_1.default.createElement("div", { ref: containerRef, className: (0, cn_1.cn)(fullscreen, "z-[999] flex flex-col justify-center transition-bg duration-200 md:px-6 overflow-hidden print:px-0 print:block print:overflow-auto", open && mounted
|
|
86
|
+
? (0, cn_1.cn)(background, "ease-out")
|
|
87
|
+
: "bg-transparent ease-in pointer-events-none"), onMouseDown: onBackgroundMouseDown, onTouchStart: onBackgroundTouchStart },
|
|
88
|
+
react_1.default.createElement("div", { className: (0, cn_1.cn)("relative flex-1 flex flex-col justify-end md:justify-center items-center transition-[opacity transform] duration-200 print:block", open && mounted
|
|
89
|
+
? "translate-y-[0px] opacity-100 ease-out"
|
|
90
|
+
: "translate-y-[100%] md:translate-y-[50px] opacity-0 ease-in") }, (open || mounted) && (react_1.default.createElement("div", Object.assign({}, props, { className: (0, cn_1.cn)(className, "w-full max-h-[92vh] print:w-[unset] print:max-h-[unset] rounded-tl-lg rounded-tr-lg md:rounded-lg overflow-auto print:rounded-none"), onMouseDown: onModalMouseDown, onTouchStart: onModalTouchStart }), children)))));
|
|
91
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.dangerousButtonStyle = exports.outlineButtonStyle = exports.disabledButtonStyle = exports.primaryButtonStyle = exports.baseButtonStyle = exports.formInputStyle = exports.inputBackgroundStyle = void 0;
|
|
4
|
+
exports.inputBackgroundStyle = "text-[16px] border border-neutral-200 outline-none appearance-none disabled:opacity-50 disabled:cursor-not-allowed placeholder:text-neutral-400";
|
|
5
|
+
exports.formInputStyle = `w-full px-3 ${exports.inputBackgroundStyle} h-[40px]`;
|
|
6
|
+
exports.baseButtonStyle = "transition-colors text-sm font-semibold cursor-pointer flex items-center justify-center rounded-lg whitespace-nowrap text-ellipsis overflow-hidden";
|
|
7
|
+
exports.primaryButtonStyle = `${exports.baseButtonStyle} px-4 h-[40px] bg-gradient-to-br from-primary-400 to-primary-500 text-white transition-colors`;
|
|
8
|
+
exports.disabledButtonStyle = `${exports.baseButtonStyle} h-[40px] px-4 bg-neutral-200 text-neutral-400`;
|
|
9
|
+
exports.outlineButtonStyle = `${exports.baseButtonStyle} h-[40px] px-4 bg-white border border-neutral-300 hover:bg-neutral-50`;
|
|
10
|
+
exports.dangerousButtonStyle = `${exports.baseButtonStyle} h-[40px] px-4 bg-white border hover:bg-red-50 text-red-600`;
|
package/dist/cjs/date.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.formatHumanDateTime = void 0;
|
|
7
|
+
const moment_timezone_1 = __importDefault(require("moment-timezone"));
|
|
8
|
+
const formatHumanDateTime = (value) => {
|
|
9
|
+
const date = (0, moment_timezone_1.default)(value).tz("Asia/Seoul");
|
|
10
|
+
const now = (0, moment_timezone_1.default)().tz("Asia/Seoul");
|
|
11
|
+
if (date.isAfter(now.clone().subtract(1, "minute"))) {
|
|
12
|
+
return "방금 전";
|
|
13
|
+
}
|
|
14
|
+
if (date.isAfter(now.clone().subtract(1, "hour"))) {
|
|
15
|
+
const diff = now.diff(date, "minute");
|
|
16
|
+
return `${diff}분 전`;
|
|
17
|
+
}
|
|
18
|
+
if (date.isAfter(now.clone().subtract(6, "hours"))) {
|
|
19
|
+
const diff = now.diff(date, "hour");
|
|
20
|
+
return `${diff}시간 전`;
|
|
21
|
+
}
|
|
22
|
+
if (date.isAfter(now.clone().subtract(1, "week"))) {
|
|
23
|
+
const diff = now.diff(date, "day");
|
|
24
|
+
return `${diff}일 전`;
|
|
25
|
+
}
|
|
26
|
+
if (date.isSame(now, "year")) {
|
|
27
|
+
return date.format("M월 D일");
|
|
28
|
+
}
|
|
29
|
+
return date.format("YYYY년 M월 D일");
|
|
30
|
+
};
|
|
31
|
+
exports.formatHumanDateTime = formatHumanDateTime;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createCDN = void 0;
|
|
4
|
+
const createCDN = (origin) => {
|
|
5
|
+
return (key, { width } = {}) => {
|
|
6
|
+
return (key ? `${origin}/${key}${width ? `?w=${width}` : ""}` : undefined);
|
|
7
|
+
};
|
|
8
|
+
};
|
|
9
|
+
exports.createCDN = createCDN;
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
36
|
+
var t = {};
|
|
37
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
38
|
+
t[p] = s[p];
|
|
39
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
40
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
41
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
42
|
+
t[p[i]] = s[p[i]];
|
|
43
|
+
}
|
|
44
|
+
return t;
|
|
45
|
+
};
|
|
46
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
47
|
+
exports.useDropFileInput = useDropFileInput;
|
|
48
|
+
exports.DropFileMessageBox = DropFileMessageBox;
|
|
49
|
+
const react_1 = __importStar(require("react"));
|
|
50
|
+
const uuid_1 = require("uuid");
|
|
51
|
+
const cn_1 = require("../../cn");
|
|
52
|
+
function useDropFileInput({ defaultValue, options, uploadFile, onFileInput, onFileUploaded, limit, } = {}) {
|
|
53
|
+
const [files, setFiles] = (0, react_1.useState)(defaultValue
|
|
54
|
+
? (Array.isArray(defaultValue) ? defaultValue : [defaultValue])
|
|
55
|
+
.map((v) => {
|
|
56
|
+
return {
|
|
57
|
+
key: (0, uuid_1.v4)(),
|
|
58
|
+
item: v,
|
|
59
|
+
};
|
|
60
|
+
})
|
|
61
|
+
.slice(0, limit ? limit : Infinity)
|
|
62
|
+
: []);
|
|
63
|
+
const fileRef = (0, react_1.useRef)([]);
|
|
64
|
+
(0, react_1.useEffect)(() => {
|
|
65
|
+
fileRef.current = files;
|
|
66
|
+
}, [files]);
|
|
67
|
+
const Component = (0, react_1.useCallback)(function Component(_a) {
|
|
68
|
+
var { className, container = "border border-dashed border-neutral-300 rounded flex items-center justify-center", draggingClassName, name, hideMessage = false, children } = _a, props = __rest(_a, ["className", "container", "draggingClassName", "name", "hideMessage", "children"]);
|
|
69
|
+
const [isDragging, setIsDragging] = (0, react_1.useState)(false);
|
|
70
|
+
const handleDragEnter = (0, react_1.useCallback)((e) => {
|
|
71
|
+
e.preventDefault();
|
|
72
|
+
e.stopPropagation();
|
|
73
|
+
setIsDragging(true);
|
|
74
|
+
}, []);
|
|
75
|
+
const handleDragLeave = (0, react_1.useCallback)((e) => {
|
|
76
|
+
e.preventDefault();
|
|
77
|
+
e.stopPropagation();
|
|
78
|
+
setIsDragging(false);
|
|
79
|
+
}, []);
|
|
80
|
+
const handleDragOver = (0, react_1.useCallback)((e) => {
|
|
81
|
+
e.preventDefault();
|
|
82
|
+
e.stopPropagation();
|
|
83
|
+
}, []);
|
|
84
|
+
const handleFiles = (0, react_1.useCallback)(async (files) => {
|
|
85
|
+
if (limit && fileRef.current.length >= limit) {
|
|
86
|
+
alert(`파일은 최대 ${limit}개 업로드할 수 있습니다.`);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const filteredFiles = files.filter((file) => {
|
|
90
|
+
// if (!props.accept) {
|
|
91
|
+
// return true;
|
|
92
|
+
// }
|
|
93
|
+
// const accepts = props.accept.split(",");
|
|
94
|
+
// for (const accept of accepts) {
|
|
95
|
+
// if (file.type.startsWith(accept)) {
|
|
96
|
+
// return true;
|
|
97
|
+
// }
|
|
98
|
+
// if (file.name.endsWith(accept)) {
|
|
99
|
+
// return true;
|
|
100
|
+
// }
|
|
101
|
+
// }
|
|
102
|
+
// return false;
|
|
103
|
+
return true;
|
|
104
|
+
});
|
|
105
|
+
if (files.length !== filteredFiles.length) {
|
|
106
|
+
alert(`${props.accept} 형식의 파일만 업로드할 수 있습니다.`);
|
|
107
|
+
}
|
|
108
|
+
const limitedFiles = filteredFiles.slice(0, limit ? limit - fileRef.current.length : Infinity);
|
|
109
|
+
if (limitedFiles.length === 0) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
if (onFileInput) {
|
|
113
|
+
onFileInput(limitedFiles);
|
|
114
|
+
}
|
|
115
|
+
for (const file of limitedFiles) {
|
|
116
|
+
const fileItem = {
|
|
117
|
+
key: (0, uuid_1.v4)(),
|
|
118
|
+
};
|
|
119
|
+
setFiles((prevFiles) => [...prevFiles, fileItem]);
|
|
120
|
+
uploadFile === null || uploadFile === void 0 ? void 0 : uploadFile(file, options).then(async (item) => {
|
|
121
|
+
await (onFileUploaded === null || onFileUploaded === void 0 ? void 0 : onFileUploaded(item));
|
|
122
|
+
setFiles((prevFiles) => prevFiles.map((f) => {
|
|
123
|
+
if (f.key === fileItem.key) {
|
|
124
|
+
return Object.assign(Object.assign({}, f), { item });
|
|
125
|
+
}
|
|
126
|
+
return f;
|
|
127
|
+
}));
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
}, [props.accept]);
|
|
131
|
+
const handleDrop = (0, react_1.useCallback)((e) => {
|
|
132
|
+
e.preventDefault();
|
|
133
|
+
e.stopPropagation();
|
|
134
|
+
setIsDragging(false);
|
|
135
|
+
if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {
|
|
136
|
+
handleFiles(Array.from(e.dataTransfer.files));
|
|
137
|
+
e.dataTransfer.clearData();
|
|
138
|
+
}
|
|
139
|
+
}, [handleFiles]);
|
|
140
|
+
const inputRef = (0, react_1.useRef)(null);
|
|
141
|
+
const handleClick = (0, react_1.useCallback)(() => {
|
|
142
|
+
var _a;
|
|
143
|
+
(_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.click();
|
|
144
|
+
}, []);
|
|
145
|
+
const handleKeyDown = (0, react_1.useCallback)((e) => {
|
|
146
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
147
|
+
handleClick();
|
|
148
|
+
}
|
|
149
|
+
}, [handleClick]);
|
|
150
|
+
const handleChange = (0, react_1.useCallback)((e) => {
|
|
151
|
+
if (e.target.files && e.target.files.length > 0) {
|
|
152
|
+
handleFiles(Array.from(e.target.files));
|
|
153
|
+
e.target.value = "";
|
|
154
|
+
}
|
|
155
|
+
}, [handleFiles]);
|
|
156
|
+
return (react_1.default.createElement("div", { className: (0, cn_1.cn)(className, container, (draggingClassName === null || draggingClassName === void 0 ? void 0 : draggingClassName(isDragging)) ||
|
|
157
|
+
(isDragging ? "bg-neutral-300/25" : "hover:bg-neutral-300/25"), "transition-colors cursor-pointer"), onDragEnter: handleDragEnter, onDragLeave: handleDragLeave, onDragOver: handleDragOver, onDrop: handleDrop, onClick: handleClick, onChange: handleChange, onKeyDown: handleKeyDown, tabIndex: 0, role: "button" },
|
|
158
|
+
react_1.default.createElement("input", Object.assign({}, props, { defaultValue: "", type: "file", hidden: true, ref: inputRef })),
|
|
159
|
+
react_1.default.createElement("input", { name: name, hidden: true, readOnly: true, value: files
|
|
160
|
+
.map((file) => {
|
|
161
|
+
if (file.item &&
|
|
162
|
+
typeof file.item === "object" &&
|
|
163
|
+
"id" in file.item) {
|
|
164
|
+
return file.item.id;
|
|
165
|
+
}
|
|
166
|
+
return null;
|
|
167
|
+
})
|
|
168
|
+
.filter(Boolean)
|
|
169
|
+
.join(",") }),
|
|
170
|
+
children ||
|
|
171
|
+
(!(hideMessage && !isDragging) && react_1.default.createElement(DropFileMessageBox, null))));
|
|
172
|
+
}, [limit, fileRef, files, options, uploadFile, onFileInput, onFileUploaded]);
|
|
173
|
+
const loadedFileIds = files
|
|
174
|
+
.map((file) => {
|
|
175
|
+
if (file.item && typeof file.item === "object" && "id" in file.item) {
|
|
176
|
+
return file.item.id;
|
|
177
|
+
}
|
|
178
|
+
return null;
|
|
179
|
+
})
|
|
180
|
+
.filter(Boolean);
|
|
181
|
+
const loadedFileIdsString = loadedFileIds.join(",");
|
|
182
|
+
const fileIds = (0, react_1.useMemo)(() => loadedFileIdsString.split(",").filter(Boolean), [loadedFileIdsString]);
|
|
183
|
+
return {
|
|
184
|
+
fileIds,
|
|
185
|
+
files,
|
|
186
|
+
setFiles,
|
|
187
|
+
Component,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
function DropFileMessageBox() {
|
|
191
|
+
return (react_1.default.createElement("div", { className: "text-sm pointer-events-none flex justify-center items-center" },
|
|
192
|
+
react_1.default.createElement("div", { className: "flex flex-col items-center" },
|
|
193
|
+
react_1.default.createElement("span", null, "\uD30C\uC77C\uC744 \uC5EC\uAE30\uB85C \uB04C\uC5B4\uB2E4 \uB193\uAC70\uB098 \uD074\uB9AD\uD574\uC11C \uC120\uD0DD\uD574 \uC8FC\uC138\uC694"))));
|
|
194
|
+
}
|
|
195
|
+
exports.default = useDropFileInput;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FileUploader = void 0;
|
|
4
|
+
class FileUploader {
|
|
5
|
+
constructor(endpoint = "/api/files") {
|
|
6
|
+
this.formatSize = (size) => {
|
|
7
|
+
if (size < 1024) {
|
|
8
|
+
return `${size} B`;
|
|
9
|
+
}
|
|
10
|
+
if (size < 1024 * 1024) {
|
|
11
|
+
return `${(size / 1024).toFixed(2)} KB`;
|
|
12
|
+
}
|
|
13
|
+
return `${(size / (1024 * 1024)).toFixed(2)} MB`;
|
|
14
|
+
};
|
|
15
|
+
this.endpoint = endpoint;
|
|
16
|
+
}
|
|
17
|
+
uploadFile(file, options = {}) {
|
|
18
|
+
return this.uploadBlob(file, file.name, options);
|
|
19
|
+
}
|
|
20
|
+
async uploadBlob(blob, name = "blob", options = {}) {
|
|
21
|
+
const { type, size } = blob;
|
|
22
|
+
const metadataForMedia = await new Promise((resolve, reject) => {
|
|
23
|
+
if (blob.type.startsWith("image/")) {
|
|
24
|
+
const img = new Image();
|
|
25
|
+
img.src = URL.createObjectURL(blob);
|
|
26
|
+
img.onload = () => {
|
|
27
|
+
resolve(Object.assign(Object.assign({}, options.metadata), { width: img.width, height: img.height }));
|
|
28
|
+
};
|
|
29
|
+
img.onerror = reject;
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
if (blob.type.startsWith("video/")) {
|
|
33
|
+
const video = document.createElement("video");
|
|
34
|
+
video.src = URL.createObjectURL(blob);
|
|
35
|
+
video.onloadedmetadata = () => {
|
|
36
|
+
resolve(Object.assign(Object.assign({}, options.metadata), { width: video.videoWidth, height: video.videoHeight, duration: video.duration }));
|
|
37
|
+
};
|
|
38
|
+
video.onerror = reject;
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
resolve(options.metadata || {});
|
|
42
|
+
});
|
|
43
|
+
const res1 = await fetch(this.endpoint, {
|
|
44
|
+
method: "POST",
|
|
45
|
+
body: JSON.stringify({
|
|
46
|
+
name: name.replace(/ /g, "_"),
|
|
47
|
+
type,
|
|
48
|
+
size,
|
|
49
|
+
metadata: metadataForMedia,
|
|
50
|
+
}),
|
|
51
|
+
});
|
|
52
|
+
if (!res1.ok) {
|
|
53
|
+
const message = await res1.json();
|
|
54
|
+
throw new Error(message);
|
|
55
|
+
}
|
|
56
|
+
const result = await res1.json();
|
|
57
|
+
const { signedUrl, file } = result;
|
|
58
|
+
const res2 = await fetch(signedUrl, {
|
|
59
|
+
method: "PUT",
|
|
60
|
+
body: blob,
|
|
61
|
+
});
|
|
62
|
+
if (!res2.ok) {
|
|
63
|
+
throw new Error(await res2.text());
|
|
64
|
+
}
|
|
65
|
+
return file;
|
|
66
|
+
}
|
|
67
|
+
async deleteFile(fileId) {
|
|
68
|
+
const res = await fetch(`${this.endpoint}/${fileId}`, {
|
|
69
|
+
method: "DELETE",
|
|
70
|
+
});
|
|
71
|
+
if (!res.ok) {
|
|
72
|
+
const { message } = await res.json();
|
|
73
|
+
throw new Error(message);
|
|
74
|
+
}
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
exports.FileUploader = FileUploader;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FileService = void 0;
|
|
4
|
+
const uuid_1 = require("uuid");
|
|
5
|
+
class FileService {
|
|
6
|
+
constructor(prefix = "user", { repository, OBJECT_STORAGE, }) {
|
|
7
|
+
this.prefix = prefix;
|
|
8
|
+
this.repository = repository;
|
|
9
|
+
this.OBJECT_STORAGE = OBJECT_STORAGE;
|
|
10
|
+
}
|
|
11
|
+
async generateSignedUrl({ userId, name, type, size, metadata = {} }) {
|
|
12
|
+
const id = (0, uuid_1.v4)();
|
|
13
|
+
const key = `${this.prefix}/${id}/${name}`;
|
|
14
|
+
const file = await this.repository.createFile({
|
|
15
|
+
id,
|
|
16
|
+
userId,
|
|
17
|
+
name,
|
|
18
|
+
type,
|
|
19
|
+
size,
|
|
20
|
+
metadata,
|
|
21
|
+
key,
|
|
22
|
+
});
|
|
23
|
+
const signedUrl = await this.OBJECT_STORAGE.generateSignedUrl(key, {
|
|
24
|
+
contentType: type,
|
|
25
|
+
});
|
|
26
|
+
return { file, signedUrl };
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
exports.FileService = FileService;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ObjectStorage = void 0;
|
|
4
|
+
const client_s3_1 = require("@aws-sdk/client-s3");
|
|
5
|
+
const s3_request_presigner_1 = require("@aws-sdk/s3-request-presigner");
|
|
6
|
+
class ObjectStorage {
|
|
7
|
+
constructor(bucketName) {
|
|
8
|
+
this.client = new client_s3_1.S3Client({
|
|
9
|
+
region: "ap-northeast-2",
|
|
10
|
+
});
|
|
11
|
+
this.bucketName = bucketName;
|
|
12
|
+
}
|
|
13
|
+
async generateSignedUrl(key, { contentType, expiresIn = 3600, } = {}) {
|
|
14
|
+
const command = new client_s3_1.PutObjectCommand({
|
|
15
|
+
Bucket: this.bucketName,
|
|
16
|
+
Key: key,
|
|
17
|
+
ContentType: contentType,
|
|
18
|
+
});
|
|
19
|
+
const signedUrl = await (0, s3_request_presigner_1.getSignedUrl)(this.client, command, {
|
|
20
|
+
expiresIn,
|
|
21
|
+
});
|
|
22
|
+
return signedUrl;
|
|
23
|
+
}
|
|
24
|
+
async find(key) {
|
|
25
|
+
try {
|
|
26
|
+
const command = new client_s3_1.GetObjectCommand({
|
|
27
|
+
Bucket: this.bucketName,
|
|
28
|
+
Key: key,
|
|
29
|
+
});
|
|
30
|
+
const { Body } = await this.client.send(command);
|
|
31
|
+
if (!Body) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
return Body.transformToByteArray();
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
async put(key, buffer, { contentType } = {}) {
|
|
41
|
+
const command = new client_s3_1.PutObjectCommand({
|
|
42
|
+
Bucket: this.bucketName,
|
|
43
|
+
Key: key,
|
|
44
|
+
ContentType: contentType,
|
|
45
|
+
Body: buffer,
|
|
46
|
+
});
|
|
47
|
+
return await this.client.send(command);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
exports.ObjectStorage = ObjectStorage;
|