@glw907/cairn-cms 0.52.1 → 0.53.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/CHANGELOG.md +22 -0
- package/dist/components/AdminLayout.svelte +6 -4
- package/dist/components/EditPage.svelte +120 -50
- package/dist/components/EditPage.svelte.d.ts +2 -1
- package/dist/components/EditorToolbar.svelte +3 -43
- package/dist/components/EditorToolbar.svelte.d.ts +3 -11
- package/dist/components/MarkdownEditor.svelte +55 -10
- package/dist/components/MarkdownEditor.svelte.d.ts +3 -0
- package/dist/components/cairn-admin.css +79 -9
- package/dist/components/fonts/{Figtree-OFL.txt → IBMPlexSans-OFL.txt} +2 -2
- package/dist/components/fonts/ibm-plex-sans.woff2 +0 -0
- package/dist/sveltekit/static-admin-page.js +2 -2
- package/package.json +1 -1
- package/src/lib/components/AdminLayout.svelte +6 -4
- package/src/lib/components/EditPage.svelte +120 -50
- package/src/lib/components/EditorToolbar.svelte +3 -43
- package/src/lib/components/MarkdownEditor.svelte +55 -10
- package/src/lib/components/cairn-admin.css +27 -3
- package/src/lib/components/fonts/{Figtree-OFL.txt → IBMPlexSans-OFL.txt} +2 -2
- package/src/lib/components/fonts/ibm-plex-sans.woff2 +0 -0
- package/src/lib/sveltekit/static-admin-page.ts +2 -2
- package/dist/components/fonts/figtree.woff2 +0 -0
- package/src/lib/components/fonts/figtree.woff2 +0 -0
|
@@ -31,6 +31,9 @@ through the adapter's render. Swapping the editor stays a one-file change.
|
|
|
31
31
|
focusMode?: boolean;
|
|
32
32
|
/** Typewriter scroll: hold the cursor line at vertical center while typing. Off by default. */
|
|
33
33
|
typewriter?: boolean;
|
|
34
|
+
/** The surface posture. Prose is the writing instrument (72ch measure, larger type, looser
|
|
35
|
+
* leading); markup is the working surface (fills the card, denser). Prose by default. */
|
|
36
|
+
surface?: 'prose' | 'markup';
|
|
34
37
|
}
|
|
35
38
|
|
|
36
39
|
let {
|
|
@@ -43,6 +46,7 @@ through the adapter's render. Swapping the editor stays a one-file change.
|
|
|
43
46
|
completionSources = [],
|
|
44
47
|
focusMode = false,
|
|
45
48
|
typewriter = false,
|
|
49
|
+
surface = 'prose',
|
|
46
50
|
}: Props = $props();
|
|
47
51
|
|
|
48
52
|
let host = $state<HTMLDivElement | null>(null);
|
|
@@ -57,6 +61,12 @@ through the adapter's render. Swapping the editor stays a one-file change.
|
|
|
57
61
|
let modes: typeof import('./editor-modes.js') | null = null;
|
|
58
62
|
let focusCompartment: import('@codemirror/state').Compartment | null = null;
|
|
59
63
|
let typewriterCompartment: import('@codemirror/state').Compartment | null = null;
|
|
64
|
+
let surfaceCompartment: import('@codemirror/state').Compartment | null = null;
|
|
65
|
+
// The posture themes, swapped through the surface compartment. Each owns its type step and
|
|
66
|
+
// leading (the base theme deliberately sets neither on the content node, so the postures never
|
|
67
|
+
// contest it on adoption order). Built in onMount beside the base theme.
|
|
68
|
+
let proseTheme: import('@codemirror/state').Extension | null = null;
|
|
69
|
+
let markupTheme: import('@codemirror/state').Extension | null = null;
|
|
60
70
|
|
|
61
71
|
onMount(async () => {
|
|
62
72
|
const viewMod = await import('@codemirror/view');
|
|
@@ -121,19 +131,23 @@ through the adapter's render. Swapping the editor stays a one-file change.
|
|
|
121
131
|
const theme = EditorView.theme(
|
|
122
132
|
{
|
|
123
133
|
'&': { backgroundColor: 'var(--color-base-100)', color: 'var(--color-base-content)', fontSize: '1rem' },
|
|
124
|
-
// The
|
|
125
|
-
// contenteditable content area carries the height, a
|
|
126
|
-
// text still lands in the editor and focuses it.
|
|
127
|
-
//
|
|
134
|
+
// The 60vh floor keeps the surface reading as the page's center stage even when the
|
|
135
|
+
// entry is short, and because the contenteditable content area carries the height, a
|
|
136
|
+
// click in the empty space below the text still lands in the editor and focuses it.
|
|
137
|
+
// No inner measure cap: the surface fills the card the way a code editor fills its
|
|
138
|
+
// pane, and the card's own width (the host caps it near 89ch of this face) is the one
|
|
139
|
+
// constraint. The surface carries tables, attributed directives, and long URLs, so the
|
|
140
|
+
// ceiling leans toward the code-editor end of the ergonomic band rather than the
|
|
141
|
+
// long-form ideal; paragraphs wrap comfortably below it.
|
|
128
142
|
'.cm-content': {
|
|
129
143
|
// The theme roots set --font-editor to the self-hosted iA Writer Mono; the inline
|
|
130
144
|
// fallback keeps the surface monospace outside an admin theme wrapper.
|
|
131
145
|
fontFamily: "var(--font-editor, ui-monospace, monospace)",
|
|
132
|
-
padding
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
146
|
+
// Vertical padding holds at least one line-height of the body (1.8 x 1rem), with a
|
|
147
|
+
// touch more below than above (the optical center sits high); the sides then read as
|
|
148
|
+
// gutters rather than letterboxing.
|
|
149
|
+
padding: '2rem 1.25rem 2.5rem',
|
|
150
|
+
minHeight: '60vh',
|
|
137
151
|
},
|
|
138
152
|
'.cm-cursor': { borderLeftColor: 'var(--color-primary)' },
|
|
139
153
|
// A quiet always-on focus hairline. :focus-visible is no escape here: browsers treat a
|
|
@@ -176,13 +190,41 @@ through the adapter's render. Swapping the editor stays a one-file change.
|
|
|
176
190
|
color: 'var(--cairn-focus-dim-ink, oklch(66% 0.01 75))',
|
|
177
191
|
backgroundColor: 'transparent',
|
|
178
192
|
},
|
|
193
|
+
// The rails dim with their text: the rail color-mix reads --cairn-directive-rail-N per
|
|
194
|
+
// element, so overriding the percentages on dimmed lines re-resolves every bar in place.
|
|
195
|
+
// Without this the directive block keeps full-strength bars and becomes the one
|
|
196
|
+
// chromatic object in the dimmed field. The active step needs the override too: focus
|
|
197
|
+
// mode's lit unit is the caret PARAGRAPH while the caret-block class spans the whole
|
|
198
|
+
// container, so a container holding a blank line has dimmed rows that still carry the
|
|
199
|
+
// active rail.
|
|
200
|
+
'.cm-cairn-focus-dim': {
|
|
201
|
+
'--cairn-directive-rail-1': 'var(--cairn-focus-dim-rail-1, 24%)',
|
|
202
|
+
'--cairn-directive-rail-2': 'var(--cairn-focus-dim-rail-2, 28%)',
|
|
203
|
+
'--cairn-directive-rail-3': 'var(--cairn-focus-dim-rail-3, 32%)',
|
|
204
|
+
'--cairn-directive-rail-active': 'var(--cairn-focus-dim-rail-active, 36%)',
|
|
205
|
+
},
|
|
206
|
+
},
|
|
207
|
+
{ dark: isDark },
|
|
208
|
+
);
|
|
209
|
+
|
|
210
|
+
// The prose posture: the writing instrument. A 72ch measure centered in the card, one type
|
|
211
|
+
// step up, looser leading. Markup posture (the base theme) keeps the dense fill for tables,
|
|
212
|
+
// directives, and long URLs. Placed after the base theme in the extension list, so its keys
|
|
213
|
+
// win the spec-order ties.
|
|
214
|
+
proseTheme = EditorView.theme(
|
|
215
|
+
{
|
|
216
|
+
// Scoped to the content node (not the editor root) so the base theme's root font-size
|
|
217
|
+
// never contests it, and so the 72ch measure resolves against the prose type step.
|
|
218
|
+
'.cm-content': { fontSize: '1.0625rem', lineHeight: '1.9', maxWidth: '72ch', margin: '0 auto' },
|
|
179
219
|
},
|
|
180
220
|
{ dark: isDark },
|
|
181
221
|
);
|
|
222
|
+
markupTheme = EditorView.theme({ '.cm-content': { lineHeight: '1.8' } }, { dark: isDark });
|
|
182
223
|
|
|
183
224
|
modes = modesMod;
|
|
184
225
|
focusCompartment = new stateMod.Compartment();
|
|
185
226
|
typewriterCompartment = new stateMod.Compartment();
|
|
227
|
+
surfaceCompartment = new stateMod.Compartment();
|
|
186
228
|
|
|
187
229
|
view = new EditorView({
|
|
188
230
|
parent: host,
|
|
@@ -207,6 +249,7 @@ through the adapter's render. Swapping the editor stays a one-file change.
|
|
|
207
249
|
highlightMod.cairnDirectivePlugin(),
|
|
208
250
|
EditorView.contentAttributes.of({ spellcheck: 'true', autocorrect: 'on', autocapitalize: 'sentences' }),
|
|
209
251
|
theme,
|
|
252
|
+
surfaceCompartment.of(surface === 'prose' ? proseTheme : markupTheme),
|
|
210
253
|
EditorView.updateListener.of((update) => {
|
|
211
254
|
if (update.docChanged) value = update.state.doc.toString();
|
|
212
255
|
}),
|
|
@@ -239,11 +282,13 @@ through the adapter's render. Swapping the editor stays a one-file change.
|
|
|
239
282
|
$effect(() => {
|
|
240
283
|
const focus = focusMode;
|
|
241
284
|
const typing = typewriter;
|
|
242
|
-
|
|
285
|
+
const posture = surface;
|
|
286
|
+
if (!mounted || !view || !modes || !focusCompartment || !typewriterCompartment || !surfaceCompartment) return;
|
|
243
287
|
view.dispatch({
|
|
244
288
|
effects: [
|
|
245
289
|
focusCompartment.reconfigure(focus ? modes.focusMode() : []),
|
|
246
290
|
typewriterCompartment.reconfigure(typing ? modes.typewriterScroll() : []),
|
|
291
|
+
surfaceCompartment.reconfigure((posture === 'prose' ? proseTheme : markupTheme) ?? []),
|
|
247
292
|
],
|
|
248
293
|
});
|
|
249
294
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* Cairn's own typefaces, self-hosted so the admin needs no external font request.
|
|
1
|
+
/* Cairn's own typefaces, self-hosted so the admin needs no external font request. IBM Plex Sans carries
|
|
2
2
|
the body and UI (friendly, highly legible at small sizes); Bricolage Grotesque gives the brand and
|
|
3
3
|
the page headings a distinct voice; iA Writer Mono is the editor writing surface. The first two are
|
|
4
4
|
variable (one file spans the weight range), the editor face ships four static files, and all three
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
of use, so this fully overrides the host's theme with no @plugin and no host build step. */
|
|
11
11
|
[data-theme='cairn-admin'] {
|
|
12
12
|
color-scheme: light;
|
|
13
|
-
--font-body: '
|
|
13
|
+
--font-body: 'IBM Plex Sans Variable', system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
|
|
14
14
|
--font-display: 'Bricolage Grotesque Variable', var(--font-body);
|
|
15
15
|
--font-editor: 'iA Writer Mono', ui-monospace, monospace;
|
|
16
16
|
font-family: var(--font-body);
|
|
@@ -63,6 +63,14 @@
|
|
|
63
63
|
ever sits on; on the chips it measured as low as 2.63:1. Do not lighten without
|
|
64
64
|
re-checking. */
|
|
65
65
|
--cairn-focus-dim-ink: oklch(66% 0.01 75);
|
|
66
|
+
/* Focus mode's rail percentages: the directive bars dim with their text (about a third of the
|
|
67
|
+
quiet 72/82/92 ramp), so a dimmed block keeps its structure without staying the one
|
|
68
|
+
chromatic object in the field. Deliberately sub-3:1, the same transient-state call as the
|
|
69
|
+
dim ink; the quiet ramp is one toggle away. */
|
|
70
|
+
--cairn-focus-dim-rail-1: 24%;
|
|
71
|
+
--cairn-focus-dim-rail-2: 28%;
|
|
72
|
+
--cairn-focus-dim-rail-3: 32%;
|
|
73
|
+
--cairn-focus-dim-rail-active: 36%;
|
|
66
74
|
--color-neutral: oklch(32% 0.012 75);
|
|
67
75
|
--color-neutral-content: oklch(96% 0.004 75);
|
|
68
76
|
|
|
@@ -103,7 +111,7 @@
|
|
|
103
111
|
>= 4.5:1 contrast on the dark bases. The polish pass tunes these values against the reference. */
|
|
104
112
|
[data-theme='cairn-admin-dark'] {
|
|
105
113
|
color-scheme: dark;
|
|
106
|
-
--font-body: '
|
|
114
|
+
--font-body: 'IBM Plex Sans Variable', system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
|
|
107
115
|
--font-display: 'Bricolage Grotesque Variable', var(--font-body);
|
|
108
116
|
--font-editor: 'iA Writer Mono', ui-monospace, monospace;
|
|
109
117
|
font-family: var(--font-body);
|
|
@@ -119,6 +127,9 @@
|
|
|
119
127
|
--color-base-300: oklch(30% 0.014 75);
|
|
120
128
|
--color-base-content: oklch(93% 0.006 75);
|
|
121
129
|
|
|
130
|
+
/* Locked pair: pressed footer-toggle text (text-primary on the bg-primary/10 plate over
|
|
131
|
+
dark base-100) measures 4.66:1, only 0.16 above the AA floor. Do not darken dark
|
|
132
|
+
--color-primary without re-checking that pair. */
|
|
122
133
|
--color-primary: oklch(68% 0.18 293);
|
|
123
134
|
--color-primary-content: oklch(20% 0.04 293);
|
|
124
135
|
--color-secondary: oklch(72% 0.02 75);
|
|
@@ -153,6 +164,12 @@
|
|
|
153
164
|
the proposed 50% measured 2.74:1, under the 3:1 floor, so it sits at 53%. Locked pair on
|
|
154
165
|
base-100: 3.12:1. Do not darken without re-checking. */
|
|
155
166
|
--cairn-focus-dim-ink: oklch(53% 0.01 75);
|
|
167
|
+
/* Focus mode's rail percentages on dark, a third of the quiet 62/74/86 ramp; the same
|
|
168
|
+
deliberate sub-3:1 transient-state call as the dim ink. */
|
|
169
|
+
--cairn-focus-dim-rail-1: 21%;
|
|
170
|
+
--cairn-focus-dim-rail-2: 25%;
|
|
171
|
+
--cairn-focus-dim-rail-3: 29%;
|
|
172
|
+
--cairn-focus-dim-rail-active: 33%;
|
|
156
173
|
--color-neutral: oklch(80% 0.01 75);
|
|
157
174
|
--color-neutral-content: oklch(22% 0.008 75);
|
|
158
175
|
|
|
@@ -260,6 +277,13 @@
|
|
|
260
277
|
outline-offset: -1px;
|
|
261
278
|
}
|
|
262
279
|
|
|
280
|
+
/* Under focus mode the document title eases back with the rest of the context: at 30px bold
|
|
281
|
+
it would otherwise be the strongest ink on the page and pull the eye off the lit
|
|
282
|
+
paragraph. Its own focus restores full ink, so editing the title is never dimmed. */
|
|
283
|
+
:where([data-theme='cairn-admin'], [data-theme='cairn-admin-dark']) .cairn-doc-title-dim:not(:focus) {
|
|
284
|
+
color: var(--cairn-focus-dim-ink);
|
|
285
|
+
}
|
|
286
|
+
|
|
263
287
|
/* Menu items come as anchors or buttons, and the omitted Preflight is what made them match:
|
|
264
288
|
without it a button keeps the UA chrome (outset border, gray fill, centered system-font
|
|
265
289
|
text) while its anchor siblings render flat. This scoped substitute levels the buttons to
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Copyright
|
|
1
|
+
Copyright 2019 IBM Corp. All rights reserved. IBMPlexSans-Italic[wdth,wght].ttf: Copyright 2019 IBM Corp. All rights reserved.
|
|
2
2
|
|
|
3
3
|
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
|
4
4
|
This license is copied below, and is also available with a FAQ at:
|
|
@@ -18,7 +18,7 @@ with others.
|
|
|
18
18
|
|
|
19
19
|
The OFL allows the licensed fonts to be used, studied, modified and
|
|
20
20
|
redistributed freely as long as they are not sold by themselves. The
|
|
21
|
-
fonts, including any derivative works, can be bundled, embedded,
|
|
21
|
+
fonts, including any derivative works, can be bundled, embedded,
|
|
22
22
|
redistributed and/or sold with any software provided that any reserved
|
|
23
23
|
names are not used by derivative works. The fonts and derivatives,
|
|
24
24
|
however, cannot be released under any other type of license. The
|
|
Binary file
|
|
@@ -32,7 +32,7 @@ const SHARED_STYLE = `:root {
|
|
|
32
32
|
--shadow: 0 1px 2px oklch(28% 0.02 75 / 0.05), 0 18px 40px -12px oklch(28% 0.02 75 / 0.16);
|
|
33
33
|
--radius-box: 1rem;
|
|
34
34
|
--radius-field: 0.625rem;
|
|
35
|
-
--font: '
|
|
35
|
+
--font: 'IBM Plex Sans Variable', system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
|
|
36
36
|
}
|
|
37
37
|
@media (prefers-color-scheme: dark) {
|
|
38
38
|
:root {
|
|
@@ -107,7 +107,7 @@ main {
|
|
|
107
107
|
h1 {
|
|
108
108
|
margin: 0 0 0.75rem;
|
|
109
109
|
font-size: 1.6rem;
|
|
110
|
-
font-weight:
|
|
110
|
+
font-weight: 700;
|
|
111
111
|
letter-spacing: -0.02em;
|
|
112
112
|
line-height: 1.15;
|
|
113
113
|
}
|
|
Binary file
|
|
Binary file
|