@railway/inkwell 0.1.4 → 1.0.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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@railway/inkwell",
3
- "version": "0.1.4",
4
- "description": "Inkwell is a Markdown editor and renderer for React with an extensible plugin system and real-time collaboration support.",
3
+ "version": "1.0.0",
4
+ "description": "Inkwell is a Markdown editor and renderer for React with an extensible plugin system.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
7
7
  "module": "./dist/index.js",
@@ -16,7 +16,8 @@
16
16
  "types": "./dist/index.d.cts",
17
17
  "default": "./dist/index.cjs"
18
18
  }
19
- }
19
+ },
20
+ "./styles.css": "./src/styles.css"
20
21
  },
21
22
  "repository": {
22
23
  "type": "git",
@@ -24,7 +25,8 @@
24
25
  "directory": "packages/inkwell"
25
26
  },
26
27
  "files": [
27
- "dist"
28
+ "dist",
29
+ "src/styles.css"
28
30
  ],
29
31
  "scripts": {
30
32
  "build": "tsup",
@@ -39,7 +41,6 @@
39
41
  "react-dom": "^19.0.0"
40
42
  },
41
43
  "dependencies": {
42
- "@slate-yjs/core": "^1.0.2",
43
44
  "highlight.js": "^11.11.1",
44
45
  "mdast-util-to-string": "^4.0.0",
45
46
  "rehype-highlight": "^7.0.2",
@@ -56,9 +57,7 @@
56
57
  "slate-history": "^0.113.1",
57
58
  "slate-react": "^0.124.0",
58
59
  "unified": "^11.0.5",
59
- "unist-util-visit": "^5.1.0",
60
- "y-protocols": "^1.0.7",
61
- "yjs": "^13.6.30"
60
+ "unist-util-visit": "^5.1.0"
62
61
  },
63
62
  "devDependencies": {
64
63
  "@testing-library/jest-dom": "^6.9.1",
package/src/styles.css ADDED
@@ -0,0 +1,474 @@
1
+ /* Default Inkwell editor, plugin, and renderer styles.
2
+ *
3
+ * Neutral, theme-aware defaults designed as a sensible baseline that any
4
+ * consumer can drop in and either keep or override. Light by default,
5
+ * dark via `prefers-color-scheme: dark`. No saturated brand colors.
6
+ *
7
+ * Import with: `import "@railway/inkwell/styles.css";`
8
+ */
9
+
10
+ /* ── Tokens ──────────────────────────────────────────────────────── */
11
+
12
+ .inkwell-editor,
13
+ .inkwell-editor-wrapper,
14
+ .inkwell-renderer,
15
+ .inkwell-plugin-bubble-menu-container,
16
+ .inkwell-plugin-picker-popup {
17
+ /* Surfaces */
18
+ --inkwell-bg: hsl(0, 0%, 100%);
19
+ --inkwell-bg-elevated: hsl(0, 0%, 100%);
20
+ --inkwell-bg-subtle: hsl(220, 14%, 96%);
21
+ --inkwell-border: hsl(220, 13%, 88%);
22
+ --inkwell-border-strong: hsl(220, 13%, 76%);
23
+
24
+ /* Foreground */
25
+ --inkwell-text: hsl(220, 15%, 18%);
26
+ --inkwell-text-muted: hsl(220, 10%, 45%);
27
+ --inkwell-text-dim: hsl(220, 10%, 62%);
28
+
29
+ /* Accents (link, focus, selection chip). Restrained blue so the
30
+ defaults read as neutral rather than branded. */
31
+ --inkwell-accent: hsl(217, 91%, 50%);
32
+ --inkwell-accent-soft: hsla(217, 91%, 50%, 0.12);
33
+ --inkwell-danger: hsl(0, 72%, 51%);
34
+
35
+ /* Inline code */
36
+ --inkwell-code-bg: hsl(220, 14%, 94%);
37
+ --inkwell-code-fg: hsl(338, 78%, 42%);
38
+
39
+ /* Type */
40
+ --inkwell-font-mono:
41
+ "JetBrains Mono", "Fira Code", ui-monospace, SFMono-Regular, Menlo,
42
+ Consolas, monospace;
43
+ --inkwell-radius: 6px;
44
+ }
45
+
46
+ @media (prefers-color-scheme: dark) {
47
+ .inkwell-editor,
48
+ .inkwell-editor-wrapper,
49
+ .inkwell-renderer,
50
+ .inkwell-plugin-bubble-menu-container,
51
+ .inkwell-plugin-picker-popup {
52
+ --inkwell-bg: hsl(220, 13%, 10%);
53
+ --inkwell-bg-elevated: hsl(220, 13%, 13%);
54
+ --inkwell-bg-subtle: hsl(220, 13%, 16%);
55
+ --inkwell-border: hsl(220, 13%, 22%);
56
+ --inkwell-border-strong: hsl(220, 13%, 32%);
57
+
58
+ --inkwell-text: hsl(220, 14%, 90%);
59
+ --inkwell-text-muted: hsl(220, 10%, 65%);
60
+ --inkwell-text-dim: hsl(220, 8%, 48%);
61
+
62
+ --inkwell-accent: hsl(217, 91%, 65%);
63
+ --inkwell-accent-soft: hsla(217, 91%, 65%, 0.16);
64
+
65
+ --inkwell-code-bg: hsl(220, 13%, 18%);
66
+ --inkwell-code-fg: hsl(340, 70%, 75%);
67
+ }
68
+ }
69
+
70
+ /* ── Editor surface ──────────────────────────────────────────────── */
71
+
72
+ .inkwell-editor-wrapper {
73
+ position: relative;
74
+ }
75
+ .inkwell-editor {
76
+ min-height: 200px;
77
+ padding: 1rem 1.25rem;
78
+ outline: none;
79
+ border: 1px solid var(--inkwell-border);
80
+ border-radius: var(--inkwell-radius);
81
+ background: var(--inkwell-bg);
82
+ color: var(--inkwell-text);
83
+ line-height: 1.6;
84
+ font-size: 0.95rem;
85
+ transition: border-color 0.15s ease;
86
+ }
87
+ .inkwell-editor:focus-within {
88
+ border-color: var(--inkwell-border-strong);
89
+ }
90
+
91
+ .inkwell-editor p {
92
+ margin: 0;
93
+ position: relative;
94
+ }
95
+ .inkwell-editor strong {
96
+ font-weight: 600;
97
+ color: var(--inkwell-text);
98
+ }
99
+ .inkwell-editor em {
100
+ font-style: italic;
101
+ }
102
+ .inkwell-editor del {
103
+ text-decoration: line-through;
104
+ color: var(--inkwell-text-muted);
105
+ }
106
+ .inkwell-editor code {
107
+ background: var(--inkwell-code-bg);
108
+ color: var(--inkwell-code-fg);
109
+ padding: 0.1em 0.35em;
110
+ border-radius: 4px;
111
+ font-family: var(--inkwell-font-mono);
112
+ font-size: 0.85em;
113
+ }
114
+
115
+ .inkwell-editor-blockquote {
116
+ border-left: 3px solid var(--inkwell-border-strong);
117
+ padding-left: 0.85em;
118
+ margin: 0.5em 0;
119
+ color: var(--inkwell-text-muted);
120
+ }
121
+
122
+ .inkwell-editor-heading {
123
+ font-weight: 600;
124
+ line-height: 1.3;
125
+ color: var(--inkwell-text);
126
+ }
127
+ .inkwell-editor-heading-1 {
128
+ font-size: 1.75em;
129
+ }
130
+ .inkwell-editor-heading-2 {
131
+ font-size: 1.4em;
132
+ }
133
+ .inkwell-editor-heading-3 {
134
+ font-size: 1.2em;
135
+ }
136
+ .inkwell-editor-heading-4 {
137
+ font-size: 1em;
138
+ }
139
+ .inkwell-editor-heading-5 {
140
+ font-size: 0.9em;
141
+ }
142
+ .inkwell-editor-heading-6 {
143
+ font-size: 0.8em;
144
+ }
145
+
146
+ .inkwell-editor-image {
147
+ margin: 0.75em 0;
148
+ border-radius: var(--inkwell-radius);
149
+ overflow: hidden;
150
+ border: 1px solid transparent;
151
+ transition:
152
+ border-color 0.15s ease,
153
+ box-shadow 0.15s ease;
154
+ }
155
+ .inkwell-editor-image[data-selected] {
156
+ border-color: var(--inkwell-accent);
157
+ box-shadow: 0 0 0 3px var(--inkwell-accent-soft);
158
+ }
159
+ .inkwell-editor-image img {
160
+ display: block;
161
+ max-width: 100%;
162
+ height: auto;
163
+ }
164
+
165
+ /* Built-in character count. Anchored to the bottom-right of the editor
166
+ wrapper. `characterLimit` is a soft hint — typing past the limit is
167
+ allowed; the count turns red and the wrapper picks up
168
+ `.inkwell-editor-over-limit`, which paints a red ring on the editor
169
+ surface so it's visually obvious the document is over budget. */
170
+ .inkwell-editor-character-count {
171
+ position: absolute;
172
+ right: 0.7rem;
173
+ bottom: 0.7rem;
174
+ z-index: 10;
175
+ padding: 0.15rem 0.45rem;
176
+ font-size: 0.72rem;
177
+ font-variant-numeric: tabular-nums;
178
+ color: var(--inkwell-text-dim);
179
+ pointer-events: none;
180
+ user-select: none;
181
+ }
182
+ .inkwell-editor-character-count-over {
183
+ color: hsl(0, 75%, 55%);
184
+ font-weight: 500;
185
+ }
186
+ .inkwell-editor-wrapper.inkwell-editor-has-character-limit .inkwell-editor {
187
+ padding-right: 5.25rem;
188
+ padding-bottom: 2.25rem;
189
+ }
190
+ .inkwell-editor-wrapper.inkwell-editor-over-limit .inkwell-editor {
191
+ border-color: hsl(0, 75%, 55%);
192
+ box-shadow: 0 0 0 1px hsl(0, 75%, 55%);
193
+ }
194
+
195
+ .inkwell-editor-backtick,
196
+ .inkwell-editor-marker {
197
+ color: var(--inkwell-text-dim);
198
+ }
199
+ .inkwell-editor .inkwell-editor-code-fence {
200
+ color: var(--inkwell-text-dim);
201
+ }
202
+ .inkwell-editor .inkwell-editor-code-line,
203
+ .inkwell-editor .inkwell-editor-code-fence,
204
+ .inkwell-renderer pre code {
205
+ font-family: var(--inkwell-font-mono);
206
+ font-size: 0.85em;
207
+ line-height: 1.55;
208
+ }
209
+ .inkwell-editor .inkwell-editor-code-line {
210
+ white-space: pre-wrap;
211
+ word-wrap: break-word;
212
+ }
213
+
214
+ /* ── Bubble menu plugin ──────────────────────────────────────────── */
215
+
216
+ @keyframes inkwell-fade-in {
217
+ from {
218
+ opacity: 0;
219
+ transform: translateY(4px);
220
+ }
221
+ to {
222
+ opacity: 1;
223
+ transform: translateY(0);
224
+ }
225
+ }
226
+
227
+ .inkwell-plugin-bubble-menu-container {
228
+ position: absolute;
229
+ z-index: 1100;
230
+ }
231
+ .inkwell-plugin-bubble-menu-inner {
232
+ display: flex;
233
+ gap: 2px;
234
+ background: var(--inkwell-bg-elevated);
235
+ border: 1px solid var(--inkwell-border);
236
+ border-radius: var(--inkwell-radius);
237
+ padding: 3px;
238
+ box-shadow: 0 6px 20px hsla(220, 20%, 10%, 0.12);
239
+ animation: inkwell-fade-in 0.12s ease-out;
240
+ }
241
+ .inkwell-plugin-bubble-menu-btn {
242
+ display: flex;
243
+ align-items: center;
244
+ justify-content: center;
245
+ width: 28px;
246
+ height: 28px;
247
+ border: none;
248
+ background: transparent;
249
+ color: var(--inkwell-text-muted);
250
+ border-radius: 4px;
251
+ cursor: pointer;
252
+ transition:
253
+ background 0.1s ease,
254
+ color 0.1s ease;
255
+ }
256
+ .inkwell-plugin-bubble-menu-btn:hover {
257
+ background: var(--inkwell-bg-subtle);
258
+ color: var(--inkwell-text);
259
+ }
260
+ .inkwell-plugin-bubble-menu-btn-active {
261
+ background: var(--inkwell-bg-subtle);
262
+ color: var(--inkwell-text);
263
+ }
264
+ .inkwell-plugin-bubble-menu-item-bold {
265
+ font-weight: 700;
266
+ font-size: 14px;
267
+ }
268
+ .inkwell-plugin-bubble-menu-item-italic {
269
+ font-style: italic;
270
+ font-size: 14px;
271
+ font-family: Georgia, "Times New Roman", serif;
272
+ }
273
+ .inkwell-plugin-bubble-menu-item-strike {
274
+ text-decoration: line-through;
275
+ font-size: 14px;
276
+ }
277
+
278
+ /* ── Shared plugin picker (snippets, mentions, etc.) ─────────────── */
279
+
280
+ .inkwell-plugin-picker-popup {
281
+ position: absolute;
282
+ z-index: 1001;
283
+ }
284
+ .inkwell-plugin-picker {
285
+ background: var(--inkwell-bg-elevated);
286
+ border: 1px solid var(--inkwell-border);
287
+ border-radius: var(--inkwell-radius);
288
+ overflow: hidden;
289
+ min-width: 260px;
290
+ max-width: 320px;
291
+ box-shadow: 0 6px 24px hsla(220, 20%, 10%, 0.14);
292
+ }
293
+ .inkwell-plugin-picker-search {
294
+ width: 100%;
295
+ padding: 7px 10px;
296
+ background: var(--inkwell-bg);
297
+ border: none;
298
+ border-bottom: 1px solid var(--inkwell-border);
299
+ color: var(--inkwell-text-muted);
300
+ font-size: 0.85rem;
301
+ outline: none;
302
+ }
303
+ .inkwell-plugin-picker-search::placeholder {
304
+ color: var(--inkwell-text-dim);
305
+ }
306
+ .inkwell-plugin-picker-item {
307
+ padding: 7px 10px;
308
+ cursor: pointer;
309
+ transition: background 0.1s ease;
310
+ }
311
+ .inkwell-plugin-picker-item:hover,
312
+ .inkwell-plugin-picker-item-active {
313
+ background: var(--inkwell-bg-subtle);
314
+ }
315
+ .inkwell-plugin-picker-title {
316
+ font-size: 0.85rem;
317
+ font-weight: 500;
318
+ color: var(--inkwell-text);
319
+ margin-right: 0.5rem;
320
+ }
321
+ .inkwell-plugin-picker-subtitle {
322
+ font-size: 0.75rem;
323
+ color: var(--inkwell-text-muted);
324
+ margin-top: 2px;
325
+ }
326
+ .inkwell-plugin-picker-preview {
327
+ font-size: 0.75rem;
328
+ color: var(--inkwell-text-muted);
329
+ margin-top: 2px;
330
+ overflow: hidden;
331
+ text-overflow: ellipsis;
332
+ white-space: nowrap;
333
+ }
334
+ .inkwell-plugin-picker-empty {
335
+ padding: 12px;
336
+ text-align: center;
337
+ color: var(--inkwell-text-dim);
338
+ font-size: 0.85rem;
339
+ }
340
+
341
+ .inkwell-plugin-slash-commands-execute {
342
+ padding: 8px 10px;
343
+ color: var(--inkwell-text);
344
+ font-size: 0.85rem;
345
+ font-weight: 500;
346
+ text-align: center;
347
+ }
348
+
349
+ /* ── Renderer ────────────────────────────────────────────────────── */
350
+
351
+ .inkwell-renderer {
352
+ line-height: 1.65;
353
+ font-size: 0.95rem;
354
+ color: var(--inkwell-text);
355
+ }
356
+ .inkwell-renderer :first-child {
357
+ margin-top: 0;
358
+ }
359
+ .inkwell-renderer h1 {
360
+ font-size: 1.75em;
361
+ font-weight: 600;
362
+ margin: 0.67em 0;
363
+ }
364
+ .inkwell-renderer h2 {
365
+ font-size: 1.4em;
366
+ font-weight: 600;
367
+ margin: 0.75em 0;
368
+ }
369
+ .inkwell-renderer h3 {
370
+ font-size: 1.2em;
371
+ font-weight: 600;
372
+ margin: 0.8em 0;
373
+ }
374
+ .inkwell-renderer p {
375
+ margin: 0.5em 0;
376
+ }
377
+ .inkwell-renderer blockquote {
378
+ border-left: 3px solid var(--inkwell-border-strong);
379
+ padding-left: 0.85em;
380
+ margin: 1em 0;
381
+ color: var(--inkwell-text-muted);
382
+ }
383
+ .inkwell-renderer ul,
384
+ .inkwell-renderer ol {
385
+ padding-left: 1.5em;
386
+ margin: 1em 0;
387
+ }
388
+ .inkwell-renderer ul {
389
+ list-style: disc;
390
+ }
391
+ .inkwell-renderer ol {
392
+ list-style: decimal;
393
+ }
394
+ .inkwell-renderer li {
395
+ margin: 0.25em 0;
396
+ }
397
+ .inkwell-renderer code {
398
+ background: var(--inkwell-code-bg);
399
+ color: var(--inkwell-code-fg);
400
+ padding: 0.1em 0.35em;
401
+ border-radius: 4px;
402
+ font-family: var(--inkwell-font-mono);
403
+ font-size: 0.85em;
404
+ }
405
+ .inkwell-renderer-code-block {
406
+ position: relative;
407
+ }
408
+ .inkwell-renderer-copy-btn {
409
+ position: absolute;
410
+ top: 0.5rem;
411
+ right: 0.5rem;
412
+ display: flex;
413
+ align-items: center;
414
+ justify-content: center;
415
+ width: 26px;
416
+ height: 26px;
417
+ border: 1px solid var(--inkwell-border);
418
+ border-radius: 4px;
419
+ background: var(--inkwell-bg-elevated);
420
+ color: var(--inkwell-text-muted);
421
+ cursor: pointer;
422
+ opacity: 0;
423
+ transition:
424
+ opacity 0.15s ease,
425
+ color 0.15s ease,
426
+ background 0.15s ease;
427
+ z-index: 1;
428
+ }
429
+ .inkwell-renderer-code-block:hover .inkwell-renderer-copy-btn {
430
+ opacity: 1;
431
+ }
432
+ .inkwell-renderer-copy-btn:hover {
433
+ background: var(--inkwell-bg-subtle);
434
+ color: var(--inkwell-text);
435
+ }
436
+ .inkwell-renderer pre {
437
+ margin: 1em 0;
438
+ border-radius: var(--inkwell-radius);
439
+ overflow: auto;
440
+ border: 1px solid var(--inkwell-border);
441
+ background: var(--inkwell-bg-subtle);
442
+ }
443
+ .inkwell-renderer pre code {
444
+ display: block;
445
+ padding: 0.85em 1em;
446
+ background: transparent;
447
+ color: var(--inkwell-text);
448
+ font-size: 0.82em;
449
+ }
450
+ .inkwell-renderer a {
451
+ color: var(--inkwell-accent);
452
+ text-decoration: underline;
453
+ text-underline-offset: 2px;
454
+ }
455
+ .inkwell-renderer hr {
456
+ border: none;
457
+ border-top: 1px solid var(--inkwell-border);
458
+ margin: 2em 0;
459
+ }
460
+ .inkwell-renderer strong {
461
+ font-weight: 600;
462
+ }
463
+ .inkwell-renderer em {
464
+ font-style: italic;
465
+ }
466
+ .inkwell-renderer del {
467
+ text-decoration: line-through;
468
+ }
469
+ .inkwell-renderer img {
470
+ max-width: 100%;
471
+ height: auto;
472
+ border-radius: var(--inkwell-radius);
473
+ margin: 1em 0;
474
+ }