@gjermundgaraba/pixel-paper 0.1.0 → 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: "CompletedFocus";
72
+ } | {
71
73
  readonly _tag: "CompletedFocusEdge";
72
74
  } | {
73
75
  readonly _tag: "ClickedToggle";
74
- } | {
75
- readonly _tag: "PressedEscape";
76
- } | {
77
- readonly _tag: "CompletedFocus";
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: "CompletedFocus";
167
+ } | {
166
168
  readonly _tag: "CompletedFocusEdge";
167
169
  } | {
168
170
  readonly _tag: "ClickedToggle";
169
- } | {
170
- readonly _tag: "PressedEscape";
171
- } | {
172
- readonly _tag: "CompletedFocus";
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;
@@ -291,12 +291,10 @@ export declare const subscriptions: <Prefix extends string>(keyPrefix: Prefix) =
291
291
  readonly _tag: "CompletedFocusTab";
292
292
  } | {
293
293
  readonly _tag: "CompletedRestoreFocus";
294
- } | {
295
- readonly _tag: "CancelledPointer";
296
- } | {
297
- readonly _tag: "PressedEscape";
298
294
  } | {
299
295
  readonly _tag: "CompletedScrollIntoView";
296
+ } | {
297
+ readonly _tag: "CancelledPointer";
300
298
  } | {
301
299
  readonly _tag: "CancelledSplitter";
302
300
  } | {
@@ -323,6 +321,8 @@ export declare const subscriptions: <Prefix extends string>(keyPrefix: Prefix) =
323
321
  } | {
324
322
  readonly _tag: "MovedSplitter";
325
323
  readonly share: number;
324
+ } | {
325
+ readonly _tag: "PressedEscape";
326
326
  } | {
327
327
  readonly _tag: "PressedGrip";
328
328
  readonly paneId: string;
@@ -447,12 +447,10 @@ export declare const subscriptions: <Prefix extends string>(keyPrefix: Prefix) =
447
447
  readonly _tag: "CompletedFocusTab";
448
448
  } | {
449
449
  readonly _tag: "CompletedRestoreFocus";
450
- } | {
451
- readonly _tag: "CancelledPointer";
452
- } | {
453
- readonly _tag: "PressedEscape";
454
450
  } | {
455
451
  readonly _tag: "CompletedScrollIntoView";
452
+ } | {
453
+ readonly _tag: "CancelledPointer";
456
454
  } | {
457
455
  readonly _tag: "CancelledSplitter";
458
456
  } | {
@@ -479,6 +477,8 @@ export declare const subscriptions: <Prefix extends string>(keyPrefix: Prefix) =
479
477
  } | {
480
478
  readonly _tag: "MovedSplitter";
481
479
  readonly share: number;
480
+ } | {
481
+ readonly _tag: "PressedEscape";
482
482
  } | {
483
483
  readonly _tag: "PressedGrip";
484
484
  readonly paneId: string;
@@ -603,12 +603,10 @@ export declare const subscriptions: <Prefix extends string>(keyPrefix: Prefix) =
603
603
  readonly _tag: "CompletedFocusTab";
604
604
  } | {
605
605
  readonly _tag: "CompletedRestoreFocus";
606
- } | {
607
- readonly _tag: "CancelledPointer";
608
- } | {
609
- readonly _tag: "PressedEscape";
610
606
  } | {
611
607
  readonly _tag: "CompletedScrollIntoView";
608
+ } | {
609
+ readonly _tag: "CancelledPointer";
612
610
  } | {
613
611
  readonly _tag: "CancelledSplitter";
614
612
  } | {
@@ -635,6 +633,8 @@ export declare const subscriptions: <Prefix extends string>(keyPrefix: Prefix) =
635
633
  } | {
636
634
  readonly _tag: "MovedSplitter";
637
635
  readonly share: number;
636
+ } | {
637
+ readonly _tag: "PressedEscape";
638
638
  } | {
639
639
  readonly _tag: "PressedGrip";
640
640
  readonly paneId: string;
@@ -767,12 +767,10 @@ export declare const subscriptions: <Prefix extends string>(keyPrefix: Prefix) =
767
767
  readonly _tag: "CompletedFocusTab";
768
768
  } | {
769
769
  readonly _tag: "CompletedRestoreFocus";
770
- } | {
771
- readonly _tag: "CancelledPointer";
772
- } | {
773
- readonly _tag: "PressedEscape";
774
770
  } | {
775
771
  readonly _tag: "CompletedScrollIntoView";
772
+ } | {
773
+ readonly _tag: "CancelledPointer";
776
774
  } | {
777
775
  readonly _tag: "CancelledSplitter";
778
776
  } | {
@@ -799,6 +797,8 @@ export declare const subscriptions: <Prefix extends string>(keyPrefix: Prefix) =
799
797
  } | {
800
798
  readonly _tag: "MovedSplitter";
801
799
  readonly share: number;
800
+ } | {
801
+ readonly _tag: "PressedEscape";
802
802
  } | {
803
803
  readonly _tag: "PressedGrip";
804
804
  readonly paneId: string;
@@ -965,12 +965,10 @@ export declare const view: import("foldkit/submodel").View<{
965
965
  readonly _tag: "CompletedFocusTab";
966
966
  } | {
967
967
  readonly _tag: "CompletedRestoreFocus";
968
- } | {
969
- readonly _tag: "CancelledPointer";
970
- } | {
971
- readonly _tag: "PressedEscape";
972
968
  } | {
973
969
  readonly _tag: "CompletedScrollIntoView";
970
+ } | {
971
+ readonly _tag: "CancelledPointer";
974
972
  } | {
975
973
  readonly _tag: "CancelledSplitter";
976
974
  } | {
@@ -997,6 +995,8 @@ export declare const view: import("foldkit/submodel").View<{
997
995
  } | {
998
996
  readonly _tag: "MovedSplitter";
999
997
  readonly share: number;
998
+ } | {
999
+ readonly _tag: "PressedEscape";
1000
1000
  } | {
1001
1001
  readonly _tag: "PressedGrip";
1002
1002
  readonly paneId: string;