@nuasite/cms 0.39.2 → 0.41.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/editor.js +15910 -15027
- package/package.json +1 -1
- package/src/collection-scanner.ts +127 -13
- package/src/content-config-ast.ts +91 -24
- package/src/editor/components/attribute-editor.tsx +0 -1
- package/src/editor/components/bg-image-overlay.tsx +7 -8
- package/src/editor/components/block-editor.tsx +12 -12
- package/src/editor/components/collections-browser.tsx +10 -10
- package/src/editor/components/create-page-modal.tsx +18 -18
- package/src/editor/components/delete-page-dialog.tsx +4 -3
- package/src/editor/components/field-utils.ts +54 -0
- package/src/editor/components/fields.tsx +516 -73
- package/src/editor/components/frontmatter-fields.tsx +188 -55
- package/src/editor/components/frontmatter-sidebar.tsx +56 -58
- package/src/editor/components/link-edit-popover.tsx +10 -5
- package/src/editor/components/markdown-editor-overlay.tsx +100 -39
- package/src/editor/components/markdown-inline-editor.tsx +58 -26
- package/src/editor/components/mdx-block-view.tsx +4 -4
- package/src/editor/components/mdx-component-picker.tsx +2 -2
- package/src/editor/components/media-library.tsx +19 -18
- package/src/editor/components/modal-shell.tsx +16 -3
- package/src/editor/components/prop-editor.tsx +15 -18
- package/src/editor/components/redirects-manager.tsx +42 -35
- package/src/editor/components/reference-picker.tsx +5 -4
- package/src/editor/components/seo-editor.tsx +36 -27
- package/src/editor/components/toolbar.tsx +50 -33
- package/src/editor/dom.ts +13 -2
- package/src/editor/editor.ts +7 -6
- package/src/editor/hooks/useBlockEditorHandlers.ts +7 -6
- package/src/editor/index.tsx +7 -6
- package/src/editor/signals.ts +44 -13
- package/src/editor/strings.ts +123 -0
- package/src/editor/styles.css +75 -2
- package/src/editor/types.ts +8 -0
- package/src/field-types.ts +15 -0
- package/src/index.ts +6 -0
- package/src/types.ts +7 -0
package/src/editor/styles.css
CHANGED
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
|
|
31
31
|
/* Border & Radius */
|
|
32
32
|
--color-cms-border: rgba(0, 0, 0, 0.08);
|
|
33
|
+
--radius-cms-xs: 5px;
|
|
33
34
|
--radius-cms-sm: 8px;
|
|
34
35
|
--radius-cms-md: 16px;
|
|
35
36
|
--radius-cms-lg: 24px;
|
|
@@ -58,6 +59,10 @@
|
|
|
58
59
|
line-height: 1.5;
|
|
59
60
|
-webkit-font-smoothing: antialiased;
|
|
60
61
|
-moz-osx-font-smoothing: grayscale;
|
|
62
|
+
/* Render all native form chrome (date picker indicator, scrollbars, autofill,
|
|
63
|
+
default controls) in dark-mode colors. Replaces a webkit-only `filter: invert(1)`
|
|
64
|
+
workaround that didn't cover Firefox. */
|
|
65
|
+
color-scheme: dark;
|
|
61
66
|
}
|
|
62
67
|
|
|
63
68
|
.cms-root *,
|
|
@@ -66,6 +71,33 @@
|
|
|
66
71
|
box-sizing: border-box;
|
|
67
72
|
}
|
|
68
73
|
|
|
74
|
+
.cms-root button:not(:disabled) {
|
|
75
|
+
cursor: pointer;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.cms-root select {
|
|
79
|
+
/* -moz-appearance: none dropped — Firefox 70+ honors the standard appearance property. */
|
|
80
|
+
appearance: none;
|
|
81
|
+
-webkit-appearance: none;
|
|
82
|
+
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff66' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='m6 9 6 6 6-6'/></svg>");
|
|
83
|
+
background-repeat: no-repeat;
|
|
84
|
+
background-position: right 0.75rem center;
|
|
85
|
+
background-size: 1rem;
|
|
86
|
+
padding-right: 2rem;
|
|
87
|
+
/* appearance: none strips the native click affordance — restore it explicitly. */
|
|
88
|
+
cursor: pointer;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.cms-root input[type="number"] {
|
|
92
|
+
-moz-appearance: textfield;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.cms-root input[type="number"]::-webkit-inner-spin-button,
|
|
96
|
+
.cms-root input[type="number"]::-webkit-outer-spin-button {
|
|
97
|
+
-webkit-appearance: none;
|
|
98
|
+
margin: 0;
|
|
99
|
+
}
|
|
100
|
+
|
|
69
101
|
/* Custom animations for CMS */
|
|
70
102
|
@keyframes spin {
|
|
71
103
|
from { transform: rotate(0deg); }
|
|
@@ -242,14 +274,55 @@
|
|
|
242
274
|
|
|
243
275
|
.milkdown-dark .ProseMirror h1 {
|
|
244
276
|
font-size: 1.75em;
|
|
245
|
-
border-bottom:
|
|
246
|
-
padding-bottom: 0
|
|
277
|
+
border-bottom: none;
|
|
278
|
+
padding-bottom: 0;
|
|
247
279
|
}
|
|
248
280
|
|
|
249
281
|
.milkdown-dark .ProseMirror h2 {
|
|
250
282
|
font-size: 1.5em;
|
|
251
283
|
}
|
|
252
284
|
|
|
285
|
+
.milkdown-editor .ProseMirror h1,
|
|
286
|
+
.milkdown-editor .ProseMirror h2,
|
|
287
|
+
.milkdown-editor .ProseMirror h3,
|
|
288
|
+
.milkdown-editor .ProseMirror h4,
|
|
289
|
+
.milkdown-editor .ProseMirror h5,
|
|
290
|
+
.milkdown-editor .ProseMirror h6 {
|
|
291
|
+
position: relative;
|
|
292
|
+
padding-right: 3em;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
.milkdown-editor .ProseMirror h1::after,
|
|
296
|
+
.milkdown-editor .ProseMirror h2::after,
|
|
297
|
+
.milkdown-editor .ProseMirror h3::after,
|
|
298
|
+
.milkdown-editor .ProseMirror h4::after,
|
|
299
|
+
.milkdown-editor .ProseMirror h5::after,
|
|
300
|
+
.milkdown-editor .ProseMirror h6::after {
|
|
301
|
+
position: absolute;
|
|
302
|
+
right: 0;
|
|
303
|
+
top: 50%;
|
|
304
|
+
transform: translateY(-50%);
|
|
305
|
+
padding: 0.15em 0.6em;
|
|
306
|
+
font-size: 0.55em;
|
|
307
|
+
font-weight: 600;
|
|
308
|
+
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
309
|
+
color: var(--color-cms-primary);
|
|
310
|
+
background: rgba(223, 255, 64, 0.12);
|
|
311
|
+
border: 1px solid rgba(223, 255, 64, 0.3);
|
|
312
|
+
border-radius: 9999px;
|
|
313
|
+
letter-spacing: 0.05em;
|
|
314
|
+
user-select: none;
|
|
315
|
+
pointer-events: none;
|
|
316
|
+
line-height: 1.3;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
.milkdown-editor .ProseMirror h1::after { content: "H1"; }
|
|
320
|
+
.milkdown-editor .ProseMirror h2::after { content: "H2"; }
|
|
321
|
+
.milkdown-editor .ProseMirror h3::after { content: "H3"; }
|
|
322
|
+
.milkdown-editor .ProseMirror h4::after { content: "H4"; }
|
|
323
|
+
.milkdown-editor .ProseMirror h5::after { content: "H5"; }
|
|
324
|
+
.milkdown-editor .ProseMirror h6::after { content: "H6"; }
|
|
325
|
+
|
|
253
326
|
.milkdown-dark .ProseMirror h3 {
|
|
254
327
|
font-size: 1.25em;
|
|
255
328
|
}
|
package/src/editor/types.ts
CHANGED
|
@@ -54,6 +54,14 @@ export interface CmsConfig {
|
|
|
54
54
|
features?: CmsFeatures
|
|
55
55
|
/** Maximum upload size in bytes for media uploads (injected by the integration). */
|
|
56
56
|
maxUploadSize?: number
|
|
57
|
+
/**
|
|
58
|
+
* Describes the host site's color theme. The CMS draws editor chrome and outlines
|
|
59
|
+
* in a contrasting color so they read clearly against the page being edited.
|
|
60
|
+
* - 'light' — host is light → CMS uses dark outlines
|
|
61
|
+
* - 'dark' — host is dark → CMS uses light outlines
|
|
62
|
+
* - 'auto' (default) — detect from `prefers-color-scheme` and the page background
|
|
63
|
+
*/
|
|
64
|
+
siteTheme?: 'auto' | 'light' | 'dark'
|
|
57
65
|
}
|
|
58
66
|
|
|
59
67
|
export interface ComponentProp {
|
package/src/field-types.ts
CHANGED
|
@@ -55,6 +55,10 @@ export interface ImageHints {
|
|
|
55
55
|
accept?: string
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
export interface FileHints {
|
|
59
|
+
accept?: string
|
|
60
|
+
}
|
|
61
|
+
|
|
58
62
|
// --- Internals ---
|
|
59
63
|
|
|
60
64
|
type OrderByDirection = 'asc' | 'desc'
|
|
@@ -122,6 +126,8 @@ export const n = {
|
|
|
122
126
|
},
|
|
123
127
|
/** Image picker (opens media library). Accepts hints for the scanner; no Zod validation applied. */
|
|
124
128
|
image: (_hints?: ImageHints) => withOrderBy(z.string().describe('cms:image')),
|
|
129
|
+
/** File picker (opens media library for any file type — PDFs, docs, etc.). Accepts hints for the scanner; no Zod validation applied. */
|
|
130
|
+
file: (_hints?: FileHints) => withOrderBy(z.string().describe('cms:file')),
|
|
125
131
|
/** URL input */
|
|
126
132
|
url: (hints?: TextHints) => stringField('url', hints),
|
|
127
133
|
/** Email input */
|
|
@@ -130,6 +136,15 @@ export const n = {
|
|
|
130
136
|
tel: (hints?: TextHints) => stringField('tel', hints),
|
|
131
137
|
/** Color picker */
|
|
132
138
|
color: () => withOrderBy(z.string().describe('cms:color')),
|
|
139
|
+
/** Year picker (integer input). Defaults to 1900–2100 when no min/max given. */
|
|
140
|
+
year: (hints?: NumberHints) => {
|
|
141
|
+
let schema = z.number()
|
|
142
|
+
if (hints?.min != null) schema = schema.min(hints.min)
|
|
143
|
+
if (hints?.max != null) schema = schema.max(hints.max)
|
|
144
|
+
return withOrderBy(schema.describe('cms:year'))
|
|
145
|
+
},
|
|
146
|
+
/** Month picker (YYYY-MM). Accepts hints for the scanner; no Zod validation applied. */
|
|
147
|
+
month: (_hints?: DateHints) => withOrderBy(z.string().describe('cms:month')),
|
|
133
148
|
/** Date picker (handles YAML Date coercion → ISO date string). Accepts hints for the scanner; no Zod validation applied. */
|
|
134
149
|
date: (_hints?: DateHints) => withOrderBy(z.preprocess(toISODate, z.string()).describe('cms:date')),
|
|
135
150
|
/** Date + time picker (handles YAML Date coercion → ISO datetime string). Accepts hints for the scanner; no Zod validation applied. */
|
package/src/index.ts
CHANGED
|
@@ -34,6 +34,12 @@ export interface NuaCmsOptions extends CmsMarkerOptions {
|
|
|
34
34
|
theme?: Record<string, string>
|
|
35
35
|
themePreset?: string
|
|
36
36
|
features?: CmsFeatures
|
|
37
|
+
/**
|
|
38
|
+
* Describes the host site's color theme. The CMS draws editor chrome and outlines
|
|
39
|
+
* in a contrasting color. 'auto' (default) detects via prefers-color-scheme and
|
|
40
|
+
* the page's computed background.
|
|
41
|
+
*/
|
|
42
|
+
siteTheme?: 'auto' | 'light' | 'dark'
|
|
37
43
|
}
|
|
38
44
|
/**
|
|
39
45
|
* Proxy /_nua/cms requests to this target URL during dev.
|
package/src/types.ts
CHANGED
|
@@ -244,9 +244,12 @@ export type FieldType =
|
|
|
244
244
|
| 'date'
|
|
245
245
|
| 'datetime'
|
|
246
246
|
| 'time'
|
|
247
|
+
| 'year'
|
|
248
|
+
| 'month'
|
|
247
249
|
| 'boolean'
|
|
248
250
|
| 'number'
|
|
249
251
|
| 'image'
|
|
252
|
+
| 'file'
|
|
250
253
|
| 'url'
|
|
251
254
|
| 'email'
|
|
252
255
|
| 'tel'
|
|
@@ -300,6 +303,10 @@ export interface FieldDefinition {
|
|
|
300
303
|
hints?: FieldHints
|
|
301
304
|
/** True when the field uses Astro's `image()` schema (entry-relative paths through astro:assets). */
|
|
302
305
|
astroImage?: boolean
|
|
306
|
+
/** Semantic role used by the editor UI to position special fields without name matching.
|
|
307
|
+
* - `publish-toggle`: boolean controlling whether the entry is published (e.g. `draft`, `isDraft`, `published`).
|
|
308
|
+
* - `publish-date`: the publish/release date field (e.g. `date`, `publishDate`, `publishedAt`). */
|
|
309
|
+
role?: 'publish-toggle' | 'publish-date'
|
|
303
310
|
}
|
|
304
311
|
|
|
305
312
|
/** Per-entry metadata for collection browsing */
|