@gjermundgaraba/pixel-paper 0.1.1 → 0.2.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.
@@ -0,0 +1,132 @@
1
+ import { EditorView } from "@codemirror/view";
2
+ // src/markdown-editor/live/theme.ts
3
+ const PIXEL_LABEL = {
4
+ fontFamily: "var(--font-px)",
5
+ fontWeight: "400",
6
+ textTransform: "uppercase",
7
+ letterSpacing: "var(--tracking-label)"
8
+ };
9
+ const CODE = {
10
+ fontFamily: "var(--font-code)",
11
+ fontSize: "var(--type-control)"
12
+ };
13
+ /** The live layer's look, in `tokens.css` values alone, so paper and plum both hold. */
14
+ const liveMarkdownTheme = EditorView.baseTheme({
15
+ "&": {
16
+ color: "var(--ink)",
17
+ background: "var(--paper)"
18
+ },
19
+ "&.cm-focused": { outline: "none" },
20
+ ".cm-scroller": {
21
+ fontFamily: "var(--font-body)",
22
+ fontSize: "var(--type-body)",
23
+ lineHeight: "1.5",
24
+ overflow: "auto"
25
+ },
26
+ ".cm-content": {
27
+ padding: "2px 0",
28
+ caretColor: "var(--ink)"
29
+ },
30
+ ".cm-content ::selection": {
31
+ background: "var(--ink)",
32
+ color: "var(--paper)"
33
+ },
34
+ ".cm-cursor": { borderLeftColor: "var(--ink)" },
35
+ ".cm-line": { padding: "0" },
36
+ ".lmd-h": {
37
+ fontWeight: "var(--read-weight)",
38
+ lineHeight: "1.3"
39
+ },
40
+ ".lmd-h1, .lmd-h2": { fontSize: "var(--read-h2)" },
41
+ ".lmd-h3": { fontSize: "var(--read-h3)" },
42
+ ".lmd-h4": {
43
+ ...PIXEL_LABEL,
44
+ fontSize: "var(--type-control)"
45
+ },
46
+ ".lmd-h5": { fontSize: "var(--type-body)" },
47
+ ".lmd-h6": {
48
+ ...PIXEL_LABEL,
49
+ fontSize: "var(--type-label)",
50
+ color: "var(--muted)"
51
+ },
52
+ ".lmd-strong": { fontWeight: "var(--read-weight)" },
53
+ ".lmd-em": { fontStyle: "italic" },
54
+ ".lmd-strike, .lmd-done": {
55
+ textDecoration: "line-through",
56
+ color: "var(--muted)"
57
+ },
58
+ ".lmd-code": {
59
+ ...CODE,
60
+ background: "var(--head)",
61
+ padding: "1px 5px"
62
+ },
63
+ ".lmd-link": {
64
+ color: "var(--ink)",
65
+ textDecoration: "underline",
66
+ textDecorationThickness: "var(--hair)",
67
+ textUnderlineOffset: "3px"
68
+ },
69
+ ".lmd-codeblock": {
70
+ ...CODE,
71
+ background: "var(--head)",
72
+ padding: "0 var(--space-s) !important"
73
+ },
74
+ ".lmd-table": CODE,
75
+ ".lmd-quote": {
76
+ borderLeft: "var(--hair) solid var(--ink)",
77
+ paddingLeft: "var(--space-m) !important",
78
+ color: "var(--muted)"
79
+ },
80
+ ".lmd-labeled-rule": {
81
+ display: "inline-flex",
82
+ width: "100%",
83
+ alignItems: "center",
84
+ gap: "var(--space-s)",
85
+ color: "var(--muted)",
86
+ verticalAlign: "middle"
87
+ },
88
+ ".lmd-labeled-rule::before, .lmd-labeled-rule::after": {
89
+ content: "\"\"",
90
+ flex: "1",
91
+ minWidth: "var(--space-s)",
92
+ height: "var(--hair)",
93
+ background: "var(--rule)"
94
+ },
95
+ ".lmd-hr": {
96
+ height: "0.8em",
97
+ background: "linear-gradient(var(--rule), var(--rule)) center / 100% var(--hair) no-repeat"
98
+ },
99
+ ".lmd-bullet": {
100
+ color: "var(--muted)",
101
+ display: "inline-block",
102
+ minWidth: "0.7em",
103
+ fontVariantNumeric: "tabular-nums"
104
+ },
105
+ ".lmd-check": {
106
+ margin: "0 var(--space-s) 0 0",
107
+ verticalAlign: "-2px",
108
+ cursor: "pointer",
109
+ accentColor: "var(--ink)"
110
+ },
111
+ ".lmd-img": {
112
+ display: "block",
113
+ maxWidth: "100%",
114
+ maxHeight: "480px",
115
+ margin: "var(--space-s) 0"
116
+ },
117
+ ".lmd-img-note": {
118
+ color: "var(--muted)",
119
+ fontStyle: "italic"
120
+ },
121
+ ".lmd-table-widget": {
122
+ cursor: "text",
123
+ padding: "2px 0"
124
+ },
125
+ ".lmd-table-view": { borderCollapse: "collapse" },
126
+ ".lmd-table-view th, .lmd-table-view td": {
127
+ border: "var(--hair) solid var(--rule)",
128
+ padding: "3px var(--space-s)",
129
+ textAlign: "left"
130
+ }
131
+ });
132
+ export { liveMarkdownTheme };
@@ -0,0 +1,11 @@
1
+ import { ViewConfig as ViewConfig$1 } from "../textarea-field/textarea-field.js";
2
+ import { Schema } from "effect";
3
+ import { Html, HtmlBuilder } from "foldkit/html";
4
+ /** Configuration for rendering a Markdown editor with `view`. */
5
+ export type ViewConfig<Message> = Pick<ViewConfig$1<Message>, "id" | "label" | "value" | "onInput" | "help" | "error" | "isRequired" | "rows">;
6
+ /** A labelled Markdown field, edited in place: its marks show only around the caret, and the
7
+ * text it hands back is the Markdown string, untouched where nobody typed. Without
8
+ * `defineMarkdownEditorElement` it is a plain `TextareaField`, which is also what tests see.
9
+ * With it, the element takes the textarea's place and drives `onInput` itself, because a
10
+ * textarea cannot carry a CRLF document. */
11
+ export declare const view: <Message>(config: ViewConfig<Message>, h: HtmlBuilder<Message>) => Html;
@@ -0,0 +1,22 @@
1
+ import { brandViewResult as __foldkitBrandViewResult } from 'foldkit/brand'
2
+ import { view as view$1 } from "../textarea-field/textarea-field.js";
3
+ import { Schema } from "effect";
4
+ import { define } from "foldkit/customElement";
5
+ // src/markdown-editor/markdown-editor.ts
6
+ /** The binding to `<pp-markdown-editor>`. The property is `source`, not `value`, because
7
+ * Foldkit's props module skips a `value` write when the element's `value` already matches. */
8
+ const spec = define({
9
+ tag: "pp-markdown-editor",
10
+ properties: { source: Schema.String },
11
+ events: { "value-change": Schema.Struct({ value: Schema.String }) }
12
+ });
13
+ /** A labelled Markdown field, edited in place: its marks show only around the caret, and the
14
+ * text it hands back is the Markdown string, untouched where nobody typed. Without
15
+ * `defineMarkdownEditorElement` it is a plain `TextareaField`, which is also what tests see.
16
+ * With it, the element takes the textarea's place and drives `onInput` itself, because a
17
+ * textarea cannot carry a CRLF document. */
18
+ const view = (config, h) => {
19
+ const host = spec.withMessage(h);
20
+ return __foldkitBrandViewResult((host([host.Source(config.value), host.OnValueChange(({ value }) => __foldkitBrandViewResult((config.onInput(value)), "@gjermundgaraba/pixel-paper/markdown-editor/markdown-editor.js#anonymous"))], [view$1(config, h)])), "@gjermundgaraba/pixel-paper/markdown-editor/markdown-editor.js#view");
21
+ };
22
+ export { spec, view };
@@ -0,0 +1,24 @@
1
+ import { brandViewResult as __foldkitBrandViewResult } from 'foldkit/brand'
2
+ // src/markdown-editor/reconcile.ts
3
+ /** CodeMirror's document keeps LF, so a stored CRLF text compares equal to it only after this. */
4
+ const withLfLineEndings = (text) => __foldkitBrandViewResult((text.replaceAll(/\r\n?/gu, "\n")), "@gjermundgaraba/pixel-paper/markdown-editor/reconcile.js#withLfLineEndings");
5
+ /** Remembers a document sent up, so its echo cannot be taken for an outside change. */
6
+ const afterEmission = (pending, doc) => __foldkitBrandViewResult(([...pending, doc]), "@gjermundgaraba/pixel-paper/markdown-editor/reconcile.js#afterEmission");
7
+ /** Sorts a `source` write into an echo of this editor's own typing, which must not rewind a
8
+ * document that has moved on, or an outside change. A render may skip echoes, so a match
9
+ * also retires everything older. Text loss here would be silent, with no history behind it. */
10
+ const afterSource = (pending, source, doc) => {
11
+ const echoIndex = pending.indexOf(source);
12
+ if (echoIndex !== -1) return __foldkitBrandViewResult(({
13
+ pending: pending.slice(echoIndex + 1),
14
+ isExternal: false
15
+ }), "@gjermundgaraba/pixel-paper/markdown-editor/reconcile.js#afterSource");
16
+ return __foldkitBrandViewResult((withLfLineEndings(source) === doc ? {
17
+ pending,
18
+ isExternal: false
19
+ } : {
20
+ pending: [],
21
+ isExternal: true
22
+ }), "@gjermundgaraba/pixel-paper/markdown-editor/reconcile.js#afterSource");
23
+ };
24
+ export { afterEmission, afterSource, withLfLineEndings };
@@ -68,17 +68,17 @@ export declare const update: (model: Model, message: Message) => Readonly<{
68
68
  readonly edge: "First" | "Last";
69
69
  };
70
70
  commands?: Update.Commands<{
71
- readonly _tag: "ClickedToggle";
72
- } | {
73
- readonly _tag: "PressedEscape";
71
+ readonly _tag: "CompletedFocus";
74
72
  } | {
75
73
  readonly _tag: "CompletedFocusEdge";
76
74
  } | {
77
- readonly _tag: "CompletedFocus";
75
+ readonly _tag: "ClickedToggle";
78
76
  } | {
79
77
  readonly _tag: "CompletedPlaceSlip";
80
78
  } | {
81
79
  readonly _tag: "LeftSlip";
80
+ } | {
81
+ readonly _tag: "PressedEscape";
82
82
  } | {
83
83
  readonly _tag: "PressedTab";
84
84
  } | {
@@ -114,11 +114,11 @@ export declare const BindSlip: Mount.MountDefinitionWithArgs<"BindSlip", {
114
114
  isEnd: Schema.Boolean;
115
115
  edge: Schema.Literals<readonly ["First", "Last"]>;
116
116
  }, {
117
- readonly _tag: "PressedEscape";
118
- } | {
119
117
  readonly _tag: "CompletedPlaceSlip";
120
118
  } | {
121
119
  readonly _tag: "LeftSlip";
120
+ } | {
121
+ readonly _tag: "PressedEscape";
122
122
  } | {
123
123
  readonly _tag: "PressedTab";
124
124
  }>;
@@ -163,17 +163,17 @@ export declare const view: import("foldkit/submodel").View<{
163
163
  readonly isOpen: boolean;
164
164
  readonly edge: "First" | "Last";
165
165
  }, {
166
- readonly _tag: "ClickedToggle";
167
- } | {
168
- readonly _tag: "PressedEscape";
166
+ readonly _tag: "CompletedFocus";
169
167
  } | {
170
168
  readonly _tag: "CompletedFocusEdge";
171
169
  } | {
172
- readonly _tag: "CompletedFocus";
170
+ readonly _tag: "ClickedToggle";
173
171
  } | {
174
172
  readonly _tag: "CompletedPlaceSlip";
175
173
  } | {
176
174
  readonly _tag: "LeftSlip";
175
+ } | {
176
+ readonly _tag: "PressedEscape";
177
177
  } | {
178
178
  readonly _tag: "PressedTab";
179
179
  } | {
@@ -119,6 +119,10 @@ export declare const update: (model: Model, message: Message) => Readonly<{
119
119
  }>;
120
120
  };
121
121
  commands?: Update.Commands<{
122
+ readonly _tag: "ClickedToggle";
123
+ } | {
124
+ readonly _tag: "PressedEscape";
125
+ } | {
122
126
  readonly _tag: "CompletedShowRailDrawer";
123
127
  } | {
124
128
  readonly _tag: "CompletedHideRailDrawer";
@@ -132,15 +136,11 @@ export declare const update: (model: Model, message: Message) => Readonly<{
132
136
  readonly _tag: "ClickedClose";
133
137
  } | {
134
138
  readonly _tag: "ClickedOpen";
135
- } | {
136
- readonly _tag: "ClickedToggle";
137
139
  } | {
138
140
  readonly _tag: "ClosedDrawer";
139
141
  } | {
140
142
  readonly _tag: "MovedSplitter";
141
143
  readonly clientX: number;
142
- } | {
143
- readonly _tag: "PressedEscape";
144
144
  } | {
145
145
  readonly _tag: "PressedSplitter";
146
146
  readonly pointerId: number;
@@ -187,6 +187,10 @@ export declare const subscriptions: <Prefix extends string>(keyPrefix: Prefix) =
187
187
  readonly width: number;
188
188
  }>;
189
189
  }, {
190
+ readonly _tag: "ClickedToggle";
191
+ } | {
192
+ readonly _tag: "PressedEscape";
193
+ } | {
190
194
  readonly _tag: "CompletedShowRailDrawer";
191
195
  } | {
192
196
  readonly _tag: "CompletedHideRailDrawer";
@@ -200,15 +204,11 @@ export declare const subscriptions: <Prefix extends string>(keyPrefix: Prefix) =
200
204
  readonly _tag: "ClickedClose";
201
205
  } | {
202
206
  readonly _tag: "ClickedOpen";
203
- } | {
204
- readonly _tag: "ClickedToggle";
205
207
  } | {
206
208
  readonly _tag: "ClosedDrawer";
207
209
  } | {
208
210
  readonly _tag: "MovedSplitter";
209
211
  readonly clientX: number;
210
- } | {
211
- readonly _tag: "PressedEscape";
212
212
  } | {
213
213
  readonly _tag: "PressedSplitter";
214
214
  readonly pointerId: number;
@@ -237,6 +237,10 @@ export declare const subscriptions: <Prefix extends string>(keyPrefix: Prefix) =
237
237
  readonly width: number;
238
238
  }>;
239
239
  }, {
240
+ readonly _tag: "ClickedToggle";
241
+ } | {
242
+ readonly _tag: "PressedEscape";
243
+ } | {
240
244
  readonly _tag: "CompletedShowRailDrawer";
241
245
  } | {
242
246
  readonly _tag: "CompletedHideRailDrawer";
@@ -250,15 +254,11 @@ export declare const subscriptions: <Prefix extends string>(keyPrefix: Prefix) =
250
254
  readonly _tag: "ClickedClose";
251
255
  } | {
252
256
  readonly _tag: "ClickedOpen";
253
- } | {
254
- readonly _tag: "ClickedToggle";
255
257
  } | {
256
258
  readonly _tag: "ClosedDrawer";
257
259
  } | {
258
260
  readonly _tag: "MovedSplitter";
259
261
  readonly clientX: number;
260
- } | {
261
- readonly _tag: "PressedEscape";
262
262
  } | {
263
263
  readonly _tag: "PressedSplitter";
264
264
  readonly pointerId: number;
@@ -341,6 +341,10 @@ export declare const view: import("foldkit/submodel").View<{
341
341
  readonly width: number;
342
342
  }>;
343
343
  }, {
344
+ readonly _tag: "ClickedToggle";
345
+ } | {
346
+ readonly _tag: "PressedEscape";
347
+ } | {
344
348
  readonly _tag: "CompletedShowRailDrawer";
345
349
  } | {
346
350
  readonly _tag: "CompletedHideRailDrawer";
@@ -354,15 +358,11 @@ export declare const view: import("foldkit/submodel").View<{
354
358
  readonly _tag: "ClickedClose";
355
359
  } | {
356
360
  readonly _tag: "ClickedOpen";
357
- } | {
358
- readonly _tag: "ClickedToggle";
359
361
  } | {
360
362
  readonly _tag: "ClosedDrawer";
361
363
  } | {
362
364
  readonly _tag: "MovedSplitter";
363
365
  readonly clientX: number;
364
- } | {
365
- readonly _tag: "PressedEscape";
366
366
  } | {
367
367
  readonly _tag: "PressedSplitter";
368
368
  readonly pointerId: number;
@@ -187,8 +187,6 @@ export declare const update: (model: Model, message: Message) => Readonly<{
187
187
  readonly orientation: "Horizontal" | "Vertical";
188
188
  readonly activationThreshold: number;
189
189
  readonly dragState: {
190
- readonly _tag: "Idle";
191
- } | {
192
190
  readonly _tag: "Dragging";
193
191
  readonly itemId: string;
194
192
  readonly sourceContainerId: string;
@@ -205,6 +203,8 @@ export declare const update: (model: Model, message: Message) => Readonly<{
205
203
  readonly containerId: string;
206
204
  readonly index: number;
207
205
  }>;
206
+ } | {
207
+ readonly _tag: "Idle";
208
208
  } | {
209
209
  readonly _tag: "KeyboardDragging";
210
210
  readonly itemId: string;
@@ -344,8 +344,6 @@ export declare const subscriptions: <Prefix extends string>(keyPrefix: Prefix) =
344
344
  readonly orientation: "Horizontal" | "Vertical";
345
345
  readonly activationThreshold: number;
346
346
  readonly dragState: {
347
- readonly _tag: "Idle";
348
- } | {
349
347
  readonly _tag: "Dragging";
350
348
  readonly itemId: string;
351
349
  readonly sourceContainerId: string;
@@ -362,6 +360,8 @@ export declare const subscriptions: <Prefix extends string>(keyPrefix: Prefix) =
362
360
  readonly containerId: string;
363
361
  readonly index: number;
364
362
  }>;
363
+ } | {
364
+ readonly _tag: "Idle";
365
365
  } | {
366
366
  readonly _tag: "KeyboardDragging";
367
367
  readonly itemId: string;
@@ -494,8 +494,6 @@ export declare const subscriptions: <Prefix extends string>(keyPrefix: Prefix) =
494
494
  readonly orientation: "Horizontal" | "Vertical";
495
495
  readonly activationThreshold: number;
496
496
  readonly dragState: {
497
- readonly _tag: "Idle";
498
- } | {
499
497
  readonly _tag: "Dragging";
500
498
  readonly itemId: string;
501
499
  readonly sourceContainerId: string;
@@ -512,6 +510,8 @@ export declare const subscriptions: <Prefix extends string>(keyPrefix: Prefix) =
512
510
  readonly containerId: string;
513
511
  readonly index: number;
514
512
  }>;
513
+ } | {
514
+ readonly _tag: "Idle";
515
515
  } | {
516
516
  readonly _tag: "KeyboardDragging";
517
517
  readonly itemId: string;
@@ -640,8 +640,6 @@ export declare const subscriptions: <Prefix extends string>(keyPrefix: Prefix) =
640
640
  readonly orientation: "Horizontal" | "Vertical";
641
641
  readonly activationThreshold: number;
642
642
  readonly dragState: {
643
- readonly _tag: "Idle";
644
- } | {
645
643
  readonly _tag: "Dragging";
646
644
  readonly itemId: string;
647
645
  readonly sourceContainerId: string;
@@ -658,6 +656,8 @@ export declare const subscriptions: <Prefix extends string>(keyPrefix: Prefix) =
658
656
  readonly containerId: string;
659
657
  readonly index: number;
660
658
  }>;
659
+ } | {
660
+ readonly _tag: "Idle";
661
661
  } | {
662
662
  readonly _tag: "KeyboardDragging";
663
663
  readonly itemId: string;
@@ -786,8 +786,6 @@ export declare const subscriptions: <Prefix extends string>(keyPrefix: Prefix) =
786
786
  readonly orientation: "Horizontal" | "Vertical";
787
787
  readonly activationThreshold: number;
788
788
  readonly dragState: {
789
- readonly _tag: "Idle";
790
- } | {
791
789
  readonly _tag: "Dragging";
792
790
  readonly itemId: string;
793
791
  readonly sourceContainerId: string;
@@ -804,6 +802,8 @@ export declare const subscriptions: <Prefix extends string>(keyPrefix: Prefix) =
804
802
  readonly containerId: string;
805
803
  readonly index: number;
806
804
  }>;
805
+ } | {
806
+ readonly _tag: "Idle";
807
807
  } | {
808
808
  readonly _tag: "KeyboardDragging";
809
809
  readonly itemId: string;
@@ -974,8 +974,6 @@ export declare const view: import("foldkit/submodel").View<{
974
974
  readonly orientation: "Horizontal" | "Vertical";
975
975
  readonly activationThreshold: number;
976
976
  readonly dragState: {
977
- readonly _tag: "Idle";
978
- } | {
979
977
  readonly _tag: "Dragging";
980
978
  readonly itemId: string;
981
979
  readonly sourceContainerId: string;
@@ -992,6 +990,8 @@ export declare const view: import("foldkit/submodel").View<{
992
990
  readonly containerId: string;
993
991
  readonly index: number;
994
992
  }>;
993
+ } | {
994
+ readonly _tag: "Idle";
995
995
  } | {
996
996
  readonly _tag: "KeyboardDragging";
997
997
  readonly itemId: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gjermundgaraba/pixel-paper",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "Printed-paper Foldkit components, tokens and stylesheet.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -12,7 +12,8 @@
12
12
  "dist",
13
13
  "fonts",
14
14
  "src/pixel-paper.css",
15
- "src/tokens.css"
15
+ "src/tokens.css",
16
+ "THIRD_PARTY_NOTICES.md"
16
17
  ],
17
18
  "type": "module",
18
19
  "sideEffects": [
@@ -27,16 +28,29 @@
27
28
  "types": "./dist/scheme/script.d.ts",
28
29
  "default": "./dist/scheme/script.js"
29
30
  },
31
+ "./markdown-editor/element": {
32
+ "types": "./dist/markdown-editor/element.d.ts",
33
+ "default": "./dist/markdown-editor/element.js"
34
+ },
30
35
  "./pixel-paper.css": "./src/pixel-paper.css"
31
36
  },
32
37
  "publishConfig": {
33
38
  "access": "public"
34
39
  },
35
40
  "dependencies": {
41
+ "@codemirror/commands": "6.11.1",
42
+ "@codemirror/lang-markdown": "6.5.2",
43
+ "@codemirror/language": "6.13.1",
44
+ "@codemirror/merge": "6.12.3",
45
+ "@codemirror/state": "6.7.6",
46
+ "@codemirror/view": "6.43.15",
47
+ "@lezer/common": "1.5.4",
48
+ "@lezer/markdown": "1.8.1",
36
49
  "diff": "^9.0.0"
37
50
  },
38
51
  "devDependencies": {
39
52
  "@effect/platform-browser": "4.0.6",
53
+ "@effect/vitest": "4.0.6",
40
54
  "@foldkit/ui": "0.169.0",
41
55
  "@foldkit/vite-plugin": "0.28.0",
42
56
  "@types/node": "26.6.5",
@@ -1673,6 +1673,52 @@ button.choice {
1673
1673
  font: var(--type-body)/1.5 var(--font-body);
1674
1674
  }
1675
1675
 
1676
+ pp-markdown-editor {
1677
+ display: block;
1678
+ position: relative;
1679
+ }
1680
+
1681
+ pp-markdown-editor:defined textarea {
1682
+ position: absolute;
1683
+ width: 1px;
1684
+ height: 1px;
1685
+ min-height: 0;
1686
+ padding: 0;
1687
+ border: 0;
1688
+ opacity: 0;
1689
+ pointer-events: none;
1690
+ overflow: hidden;
1691
+ clip-path: inset(50%);
1692
+ resize: none;
1693
+ }
1694
+
1695
+ .markdown-surface {
1696
+ border-bottom: 1px dotted var(--muted);
1697
+ padding-bottom: 1px;
1698
+ }
1699
+
1700
+ .markdown-surface .cm-scroller {
1701
+ min-height: max(96px, calc(var(--rows) * 1lh));
1702
+ }
1703
+
1704
+ .markdown-surface:focus-within,
1705
+ .field:has([aria-invalid="true"]) .markdown-surface {
1706
+ border-bottom: var(--line) solid var(--ink);
1707
+ padding-bottom: 0;
1708
+ }
1709
+
1710
+ .field:has([aria-invalid="true"]) .markdown-surface {
1711
+ border-bottom-color: var(--red);
1712
+ }
1713
+
1714
+ pp-markdown-editor:disabled .markdown-surface {
1715
+ border-bottom-color: transparent;
1716
+ }
1717
+
1718
+ pp-markdown-editor:disabled .cm-content {
1719
+ color: var(--muted);
1720
+ }
1721
+
1676
1722
  textarea::-webkit-resizer {
1677
1723
  background: linear-gradient(135deg, transparent 0 50%, var(--ink) 50% 100%);
1678
1724
  }