@marlinjai/clearify 1.11.2 → 1.12.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/dist/config-schema.json +225 -0
- package/dist/node/{chunk-PVTUVUBK.js → chunk-2WLFSQS7.js} +160 -10
- package/dist/node/{chunk-NGWAMBXS.js → chunk-6XHVO5AO.js} +1 -1
- package/dist/node/{chunk-EMM4VLF7.js → chunk-6YAEHWC7.js} +2 -2
- package/dist/node/{chunk-PFX7LHRZ.js → chunk-XYS5SV4M.js} +128 -4
- package/dist/node/core/config.d.ts +78 -2
- package/dist/node/core/config.js +11 -3
- package/dist/node/node/build.js +3 -3
- package/dist/node/node/check.js +2 -2
- package/dist/node/node/index.js +4 -4
- package/dist/node/types/index.d.ts +23 -2
- package/dist/node/vite-plugin/index.js +2 -2
- package/package.json +4 -2
- package/src/client/App.tsx +59 -16
- package/src/theme/Header.tsx +32 -0
- package/src/theme/admin/AdminDashboard.tsx +129 -0
- package/src/theme/admin/AdminLayout.tsx +240 -0
- package/src/theme/admin/ProjectsManager.tsx +546 -0
- package/src/theme/admin/SectionsManager.tsx +782 -0
- package/src/theme/admin/SiteSettings.tsx +414 -0
- package/src/theme/admin/components/ConfigPreview.tsx +166 -0
- package/src/theme/admin/components/ConfirmDialog.tsx +73 -0
- package/src/theme/admin/components/FormField.tsx +39 -0
- package/src/theme/admin/components/Modal.tsx +93 -0
- package/src/theme/admin/components/Toast.tsx +59 -0
- package/src/theme/admin/components/index.ts +4 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import React, { useEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
interface ModalProps {
|
|
4
|
+
open: boolean;
|
|
5
|
+
onClose: () => void;
|
|
6
|
+
title: string;
|
|
7
|
+
children: React.ReactNode;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function Modal({ open, onClose, title, children }: ModalProps) {
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
if (!open) return;
|
|
13
|
+
const handler = (e: KeyboardEvent) => {
|
|
14
|
+
if (e.key === 'Escape') onClose();
|
|
15
|
+
};
|
|
16
|
+
document.addEventListener('keydown', handler);
|
|
17
|
+
return () => document.removeEventListener('keydown', handler);
|
|
18
|
+
}, [open, onClose]);
|
|
19
|
+
|
|
20
|
+
if (!open) return null;
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<div
|
|
24
|
+
style={{
|
|
25
|
+
position: 'fixed',
|
|
26
|
+
inset: 0,
|
|
27
|
+
zIndex: 1000,
|
|
28
|
+
display: 'flex',
|
|
29
|
+
alignItems: 'center',
|
|
30
|
+
justifyContent: 'center',
|
|
31
|
+
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
|
32
|
+
backdropFilter: 'blur(4px)',
|
|
33
|
+
}}
|
|
34
|
+
onClick={(e) => {
|
|
35
|
+
if (e.target === e.currentTarget) onClose();
|
|
36
|
+
}}
|
|
37
|
+
>
|
|
38
|
+
<div
|
|
39
|
+
style={{
|
|
40
|
+
backgroundColor: 'var(--clearify-bg)',
|
|
41
|
+
borderRadius: 'var(--clearify-radius-lg)',
|
|
42
|
+
border: '1px solid var(--clearify-border)',
|
|
43
|
+
boxShadow: 'var(--clearify-shadow-lg)',
|
|
44
|
+
padding: '1.5rem',
|
|
45
|
+
minWidth: '400px',
|
|
46
|
+
maxWidth: '90vw',
|
|
47
|
+
maxHeight: '85vh',
|
|
48
|
+
overflow: 'auto',
|
|
49
|
+
animation: 'clearify-scale-in 0.15s ease-out',
|
|
50
|
+
}}
|
|
51
|
+
>
|
|
52
|
+
<div
|
|
53
|
+
style={{
|
|
54
|
+
display: 'flex',
|
|
55
|
+
alignItems: 'center',
|
|
56
|
+
justifyContent: 'space-between',
|
|
57
|
+
marginBottom: '1rem',
|
|
58
|
+
}}
|
|
59
|
+
>
|
|
60
|
+
<h3
|
|
61
|
+
style={{
|
|
62
|
+
fontSize: '1.125rem',
|
|
63
|
+
fontWeight: 700,
|
|
64
|
+
color: 'var(--clearify-text)',
|
|
65
|
+
}}
|
|
66
|
+
>
|
|
67
|
+
{title}
|
|
68
|
+
</h3>
|
|
69
|
+
<button
|
|
70
|
+
onClick={onClose}
|
|
71
|
+
style={{
|
|
72
|
+
background: 'none',
|
|
73
|
+
border: 'none',
|
|
74
|
+
cursor: 'pointer',
|
|
75
|
+
color: 'var(--clearify-text-tertiary)',
|
|
76
|
+
padding: '0.25rem',
|
|
77
|
+
borderRadius: 'var(--clearify-radius-sm)',
|
|
78
|
+
display: 'flex',
|
|
79
|
+
alignItems: 'center',
|
|
80
|
+
justifyContent: 'center',
|
|
81
|
+
}}
|
|
82
|
+
>
|
|
83
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
84
|
+
<line x1="18" y1="6" x2="6" y2="18" />
|
|
85
|
+
<line x1="6" y1="6" x2="18" y2="18" />
|
|
86
|
+
</svg>
|
|
87
|
+
</button>
|
|
88
|
+
</div>
|
|
89
|
+
{children}
|
|
90
|
+
</div>
|
|
91
|
+
</div>
|
|
92
|
+
);
|
|
93
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import React, { useState, useCallback, useRef } from 'react';
|
|
2
|
+
|
|
3
|
+
interface ToastState {
|
|
4
|
+
message: string;
|
|
5
|
+
type: 'success' | 'error';
|
|
6
|
+
id: number;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function useToast() {
|
|
10
|
+
const [toasts, setToasts] = useState<ToastState[]>([]);
|
|
11
|
+
const nextId = useRef(0);
|
|
12
|
+
|
|
13
|
+
const show = useCallback((message: string, type: 'success' | 'error' = 'success') => {
|
|
14
|
+
const id = nextId.current++;
|
|
15
|
+
setToasts((prev) => [...prev, { message, type, id }]);
|
|
16
|
+
setTimeout(() => {
|
|
17
|
+
setToasts((prev) => prev.filter((t) => t.id !== id));
|
|
18
|
+
}, 3000);
|
|
19
|
+
}, []);
|
|
20
|
+
|
|
21
|
+
return { toasts, show };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function ToastContainer({ toasts }: { toasts: ToastState[] }) {
|
|
25
|
+
if (toasts.length === 0) return null;
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<div
|
|
29
|
+
style={{
|
|
30
|
+
position: 'fixed',
|
|
31
|
+
bottom: '1.5rem',
|
|
32
|
+
right: '1.5rem',
|
|
33
|
+
zIndex: 9999,
|
|
34
|
+
display: 'flex',
|
|
35
|
+
flexDirection: 'column',
|
|
36
|
+
gap: '0.5rem',
|
|
37
|
+
}}
|
|
38
|
+
>
|
|
39
|
+
{toasts.map((toast) => (
|
|
40
|
+
<div
|
|
41
|
+
key={toast.id}
|
|
42
|
+
style={{
|
|
43
|
+
padding: '0.75rem 1.25rem',
|
|
44
|
+
borderRadius: 'var(--clearify-radius)',
|
|
45
|
+
fontSize: '0.875rem',
|
|
46
|
+
fontWeight: 500,
|
|
47
|
+
color: '#fff',
|
|
48
|
+
backgroundColor: toast.type === 'success' ? '#16a34a' : '#dc2626',
|
|
49
|
+
boxShadow: 'var(--clearify-shadow-lg)',
|
|
50
|
+
animation: 'clearify-fade-in 0.2s ease-out',
|
|
51
|
+
maxWidth: '360px',
|
|
52
|
+
}}
|
|
53
|
+
>
|
|
54
|
+
{toast.message}
|
|
55
|
+
</div>
|
|
56
|
+
))}
|
|
57
|
+
</div>
|
|
58
|
+
);
|
|
59
|
+
}
|