@orhancodestudio/ocsm-core 0.1.0-alpha.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/CHANGELOG.md +13 -0
- package/README.md +47 -0
- package/package.json +53 -0
- package/src/admin/admin.module.css +1312 -0
- package/src/admin/admin.types.ts +85 -0
- package/src/admin/components/access-denied.tsx +12 -0
- package/src/admin/components/admin-shell.tsx +168 -0
- package/src/admin/components/content-list-view.tsx +83 -0
- package/src/admin/components/dashboard-view.tsx +113 -0
- package/src/admin/components/data-table.tsx +80 -0
- package/src/admin/components/document-delete-button.tsx +44 -0
- package/src/admin/components/icons.tsx +150 -0
- package/src/admin/components/modal.tsx +78 -0
- package/src/admin/components/page-builder.tsx +1334 -0
- package/src/admin/components/settings-view.tsx +334 -0
- package/src/admin/components/sign-out-button.tsx +22 -0
- package/src/admin/components/system-view.tsx +77 -0
- package/src/admin/components/users-panel.tsx +321 -0
- package/src/admin/index.ts +20 -0
- package/src/admin/ocsm-admin.tsx +259 -0
- package/src/auth/authenticate.ts +76 -0
- package/src/auth/index.ts +9 -0
- package/src/auth/password.ts +22 -0
- package/src/auth/permissions.ts +27 -0
- package/src/auth/session.ts +103 -0
- package/src/blocks/block-renderer.tsx +428 -0
- package/src/blocks/block.types.ts +401 -0
- package/src/blocks/index.ts +15 -0
- package/src/blocks/markdown.tsx +11 -0
- package/src/config/config.schema.ts +28 -0
- package/src/config/config.types.ts +16 -0
- package/src/config/define-config.ts +19 -0
- package/src/config/index.ts +13 -0
- package/src/config/resolve-config.ts +10 -0
- package/src/content/content-repository.ts +66 -0
- package/src/content/content-store.interface.ts +23 -0
- package/src/content/content.types.ts +25 -0
- package/src/content/create-content-store.ts +18 -0
- package/src/content/frontmatter.ts +25 -0
- package/src/content/index.ts +12 -0
- package/src/index.ts +10 -0
- package/src/layout/index.ts +1 -0
- package/src/layout/layout-store.ts +27 -0
- package/src/roles/index.ts +10 -0
- package/src/roles/role-store.ts +95 -0
- package/src/roles/role.types.ts +86 -0
- package/src/server/create-ocsm.ts +67 -0
- package/src/server/documents.ts +28 -0
- package/src/server/index.ts +59 -0
- package/src/server/render-mdx.tsx +14 -0
- package/src/storage/create-file-backend.ts +26 -0
- package/src/storage/file-backend.ts +26 -0
- package/src/storage/fs-file-backend.ts +43 -0
- package/src/storage/github-file-backend.ts +97 -0
- package/src/storage/index.ts +8 -0
- package/src/storage/json-store.ts +23 -0
- package/src/theme/css.ts +28 -0
- package/src/theme/index.ts +8 -0
- package/src/theme/theme-store.ts +19 -0
- package/src/theme/theme.types.ts +53 -0
- package/src/types/css-modules.d.ts +4 -0
- package/src/update/check-for-updates.ts +50 -0
- package/src/update/index.ts +1 -0
- package/src/users/index.ts +6 -0
- package/src/users/user-store.ts +120 -0
- package/src/users/user.types.ts +18 -0
- package/src/version.ts +11 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import type { SVGProps } from "react";
|
|
2
|
+
|
|
3
|
+
type IconProps = SVGProps<SVGSVGElement>;
|
|
4
|
+
|
|
5
|
+
function Base({ children, ...props }: IconProps & { children: React.ReactNode }) {
|
|
6
|
+
return (
|
|
7
|
+
<svg
|
|
8
|
+
width="18"
|
|
9
|
+
height="18"
|
|
10
|
+
viewBox="0 0 24 24"
|
|
11
|
+
fill="none"
|
|
12
|
+
stroke="currentColor"
|
|
13
|
+
strokeWidth="1.8"
|
|
14
|
+
strokeLinecap="round"
|
|
15
|
+
strokeLinejoin="round"
|
|
16
|
+
aria-hidden="true"
|
|
17
|
+
{...props}
|
|
18
|
+
>
|
|
19
|
+
{children}
|
|
20
|
+
</svg>
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const IconDashboard = (props: IconProps) => (
|
|
25
|
+
<Base {...props}>
|
|
26
|
+
<rect x="3" y="3" width="7" height="9" />
|
|
27
|
+
<rect x="14" y="3" width="7" height="5" />
|
|
28
|
+
<rect x="14" y="12" width="7" height="9" />
|
|
29
|
+
<rect x="3" y="16" width="7" height="5" />
|
|
30
|
+
</Base>
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
export const IconDocument = (props: IconProps) => (
|
|
34
|
+
<Base {...props}>
|
|
35
|
+
<path d="M14 3v4a1 1 0 0 0 1 1h4" />
|
|
36
|
+
<path d="M17 21H7a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h7l5 5v11a2 2 0 0 1-2 2z" />
|
|
37
|
+
<path d="M9 9h1M9 13h6M9 17h6" />
|
|
38
|
+
</Base>
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
export const IconUsers = (props: IconProps) => (
|
|
42
|
+
<Base {...props}>
|
|
43
|
+
<path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2" />
|
|
44
|
+
<circle cx="9" cy="7" r="4" />
|
|
45
|
+
<path d="M22 21v-2a4 4 0 0 0-3-3.87M16 3.13a4 4 0 0 1 0 7.75" />
|
|
46
|
+
</Base>
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
export const IconTheme = (props: IconProps) => (
|
|
50
|
+
<Base {...props}>
|
|
51
|
+
<circle cx="13.5" cy="6.5" r="2.5" />
|
|
52
|
+
<circle cx="17.5" cy="10.5" r="2.5" />
|
|
53
|
+
<circle cx="8.5" cy="7.5" r="2.5" />
|
|
54
|
+
<circle cx="6.5" cy="12.5" r="2.5" />
|
|
55
|
+
<path d="M12 2a10 10 0 1 0 0 20 2 2 0 0 0 2-2 2 2 0 0 1 2-2h1a4 4 0 0 0 4-4 8 8 0 0 0-9-10z" />
|
|
56
|
+
</Base>
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
export const IconSystem = (props: IconProps) => (
|
|
60
|
+
<Base {...props}>
|
|
61
|
+
<path d="M12 2a3 3 0 0 0-3 3v1.5a6 6 0 0 0-1.3.76l-1.3-.75a3 3 0 1 0-3 5.2l1.3.75a6 6 0 0 0 0 1.5l-1.3.75a3 3 0 1 0 3 5.2l1.3-.75a6 6 0 0 0 1.3.76V21a3 3 0 0 0 6 0v-1.5a6 6 0 0 0 1.3-.76l1.3.75a3 3 0 1 0 3-5.2l-1.3-.75a6 6 0 0 0 0-1.5l1.3-.75a3 3 0 1 0-3-5.2l-1.3.75a6 6 0 0 0-1.3-.76V5a3 3 0 0 0-3-3z" />
|
|
62
|
+
<circle cx="12" cy="12" r="2.5" />
|
|
63
|
+
</Base>
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
export const IconInfo = (props: IconProps) => (
|
|
67
|
+
<Base {...props}>
|
|
68
|
+
<circle cx="12" cy="12" r="9" />
|
|
69
|
+
<path d="M12 16v-4M12 8h.01" />
|
|
70
|
+
</Base>
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
export const IconSettings = (props: IconProps) => (
|
|
74
|
+
<Base {...props}>
|
|
75
|
+
<circle cx="12" cy="12" r="3" />
|
|
76
|
+
<path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09a1.65 1.65 0 0 0-1-1.51 1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09a1.65 1.65 0 0 0 1.51-1 1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z" />
|
|
77
|
+
</Base>
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
export const IconPencil = (props: IconProps) => (
|
|
81
|
+
<Base {...props}>
|
|
82
|
+
<path d="M12 20h9" />
|
|
83
|
+
<path d="M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4z" />
|
|
84
|
+
</Base>
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
export const IconPlus = (props: IconProps) => (
|
|
88
|
+
<Base {...props}>
|
|
89
|
+
<path d="M12 5v14M5 12h14" />
|
|
90
|
+
</Base>
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
export const IconTrash = (props: IconProps) => (
|
|
94
|
+
<Base {...props}>
|
|
95
|
+
<path d="M3 6h18M8 6V4a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v2M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6" />
|
|
96
|
+
</Base>
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
export const IconLogout = (props: IconProps) => (
|
|
100
|
+
<Base {...props}>
|
|
101
|
+
<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4M16 17l5-5-5-5M21 12H9" />
|
|
102
|
+
</Base>
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
export const IconGrip = (props: IconProps) => (
|
|
106
|
+
<svg
|
|
107
|
+
width="16"
|
|
108
|
+
height="16"
|
|
109
|
+
viewBox="0 0 24 24"
|
|
110
|
+
fill="currentColor"
|
|
111
|
+
aria-hidden="true"
|
|
112
|
+
{...props}
|
|
113
|
+
>
|
|
114
|
+
<circle cx="9" cy="5" r="1.6" />
|
|
115
|
+
<circle cx="15" cy="5" r="1.6" />
|
|
116
|
+
<circle cx="9" cy="12" r="1.6" />
|
|
117
|
+
<circle cx="15" cy="12" r="1.6" />
|
|
118
|
+
<circle cx="9" cy="19" r="1.6" />
|
|
119
|
+
<circle cx="15" cy="19" r="1.6" />
|
|
120
|
+
</svg>
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
export const IconMonitor = (props: IconProps) => (
|
|
124
|
+
<Base {...props}>
|
|
125
|
+
<rect x="2" y="3" width="20" height="14" rx="2" />
|
|
126
|
+
<path d="M8 21h8M12 17v4" />
|
|
127
|
+
</Base>
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
export const IconPhone = (props: IconProps) => (
|
|
131
|
+
<Base {...props}>
|
|
132
|
+
<rect x="7" y="2" width="10" height="20" rx="2" />
|
|
133
|
+
<path d="M11 18h2" />
|
|
134
|
+
</Base>
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
export const IconEye = (props: IconProps) => (
|
|
138
|
+
<Base {...props}>
|
|
139
|
+
<path d="M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7-10-7-10-7z" />
|
|
140
|
+
<circle cx="12" cy="12" r="3" />
|
|
141
|
+
</Base>
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
export const IconEyeOff = (props: IconProps) => (
|
|
145
|
+
<Base {...props}>
|
|
146
|
+
<path d="M9.9 4.2A10.9 10.9 0 0 1 12 4c6.5 0 10 7 10 7a18.5 18.5 0 0 1-3 3.9M6.1 6.1C3.5 7.8 2 11 2 11s3.5 7 10 7a10.9 10.9 0 0 0 4-.8" />
|
|
147
|
+
<path d="M9.5 9.5a3 3 0 0 0 4.2 4.2" />
|
|
148
|
+
<path d="M3 3l18 18" />
|
|
149
|
+
</Base>
|
|
150
|
+
);
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { type ReactNode, useEffect } from "react";
|
|
4
|
+
import styles from "../admin.module.css";
|
|
5
|
+
|
|
6
|
+
export interface ModalProps {
|
|
7
|
+
open: boolean;
|
|
8
|
+
title: ReactNode;
|
|
9
|
+
onClose: () => void;
|
|
10
|
+
children: ReactNode;
|
|
11
|
+
/** Optional footer (e.g. action buttons), pinned to the bottom. */
|
|
12
|
+
footer?: ReactNode;
|
|
13
|
+
/** Max width of the dialog in px. */
|
|
14
|
+
width?: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Reusable modal dialog: dimmed overlay, centered card, ESC + backdrop-click to
|
|
19
|
+
* close, scroll-locked body. Use anywhere the panel needs a dialog.
|
|
20
|
+
*/
|
|
21
|
+
export function Modal({
|
|
22
|
+
open,
|
|
23
|
+
title,
|
|
24
|
+
onClose,
|
|
25
|
+
children,
|
|
26
|
+
footer,
|
|
27
|
+
width = 520,
|
|
28
|
+
}: ModalProps) {
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
if (!open) return;
|
|
31
|
+
function onKey(event: KeyboardEvent) {
|
|
32
|
+
if (event.key === "Escape") onClose();
|
|
33
|
+
}
|
|
34
|
+
document.addEventListener("keydown", onKey);
|
|
35
|
+
const prevOverflow = document.body.style.overflow;
|
|
36
|
+
document.body.style.overflow = "hidden";
|
|
37
|
+
return () => {
|
|
38
|
+
document.removeEventListener("keydown", onKey);
|
|
39
|
+
document.body.style.overflow = prevOverflow;
|
|
40
|
+
};
|
|
41
|
+
}, [open, onClose]);
|
|
42
|
+
|
|
43
|
+
if (!open) return null;
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<div
|
|
47
|
+
className={styles.modalOverlay}
|
|
48
|
+
onClick={onClose}
|
|
49
|
+
onKeyDown={(event) => {
|
|
50
|
+
if (event.key === "Escape") onClose();
|
|
51
|
+
}}
|
|
52
|
+
role="presentation"
|
|
53
|
+
>
|
|
54
|
+
<div
|
|
55
|
+
className={styles.modalCard}
|
|
56
|
+
style={{ maxWidth: width }}
|
|
57
|
+
role="dialog"
|
|
58
|
+
aria-modal="true"
|
|
59
|
+
onClick={(event) => event.stopPropagation()}
|
|
60
|
+
onKeyDown={(event) => event.stopPropagation()}
|
|
61
|
+
>
|
|
62
|
+
<div className={styles.modalHeader}>
|
|
63
|
+
<h2 className={styles.modalTitle}>{title}</h2>
|
|
64
|
+
<button
|
|
65
|
+
type="button"
|
|
66
|
+
className={styles.modalClose}
|
|
67
|
+
onClick={onClose}
|
|
68
|
+
aria-label="Kapat"
|
|
69
|
+
>
|
|
70
|
+
✕
|
|
71
|
+
</button>
|
|
72
|
+
</div>
|
|
73
|
+
<div className={styles.modalBody}>{children}</div>
|
|
74
|
+
{footer ? <div className={styles.modalFooter}>{footer}</div> : null}
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
77
|
+
);
|
|
78
|
+
}
|