@refrakt-md/editor 0.7.2 → 0.8.1

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.
Files changed (50) hide show
  1. package/app/dist/assets/{index-4SP4_AaD.js → index-BBinZAiy.js} +1 -1
  2. package/app/dist/assets/index-BD2EBUrQ.css +1 -0
  3. package/app/dist/assets/{index-D77rckeh.js → index-BLuaHLN3.js} +1 -1
  4. package/app/dist/assets/{index-30gAspk8.js → index-BgCNqcSo.js} +1 -1
  5. package/app/dist/assets/index-BlAOhWAQ.js +453 -0
  6. package/app/dist/assets/{index-BZ4adnS0.js → index-BwFn9q4x.js} +1 -1
  7. package/app/dist/assets/{index-DFkteo0w.js → index-C72UC2ga.js} +1 -1
  8. package/app/dist/assets/{index-x67KGOIr.js → index-COIPZ34u.js} +1 -1
  9. package/app/dist/assets/{index-BEFUVB_B.js → index-CW02bulk.js} +1 -1
  10. package/app/dist/assets/{index-CI5PewQM.js → index-CXFMPmtf.js} +1 -1
  11. package/app/dist/assets/{index-ByHhigzw.js → index-CeU_s7BB.js} +1 -1
  12. package/app/dist/assets/{index-DvgOtlru.js → index-CqHjo2YT.js} +1 -1
  13. package/app/dist/assets/{index-DKnhR16N.js → index-D3TQo8gu.js} +1 -1
  14. package/app/dist/assets/{index-Baf7ZSct.js → index-DVM3uoxc.js} +1 -1
  15. package/app/dist/assets/{index-C9w1RpYY.js → index-DW2zI-Ss.js} +1 -1
  16. package/app/dist/assets/{index--rGC9bba.js → index-D_Y6J00B.js} +1 -1
  17. package/app/dist/assets/{index-kPhFxtn-.js → index-DgIg-QAA.js} +2 -2
  18. package/app/dist/assets/{index-DIuFNfTc.js → index-DmY6uqAw.js} +1 -1
  19. package/app/dist/assets/{index-D1WOi3EN.js → index-DzHt8ZRh.js} +1 -1
  20. package/app/dist/assets/{index-BwWzfQVn.js → index-ZLvRNfLb.js} +1 -1
  21. package/app/dist/index.html +2 -2
  22. package/app/src/lib/api/client.ts +49 -0
  23. package/app/src/lib/components/ActionEditPopover.svelte +245 -0
  24. package/app/src/lib/components/BlockCard.svelte +255 -1
  25. package/app/src/lib/components/BlockEditPanel.svelte +697 -138
  26. package/app/src/lib/components/BlockEditor.svelte +467 -389
  27. package/app/src/lib/components/CodeEditPopover.svelte +226 -0
  28. package/app/src/lib/components/ContentModelTree.svelte +562 -0
  29. package/app/src/lib/components/ContentTree.svelte +181 -0
  30. package/app/src/lib/components/EditorLayout.svelte +1 -6
  31. package/app/src/lib/components/FrontmatterEditPanel.svelte +0 -1
  32. package/app/src/lib/components/HeaderBar.svelte +38 -0
  33. package/app/src/lib/components/InlineEditPopover.svelte +593 -0
  34. package/app/src/lib/components/InsertBlockDialog.svelte +429 -0
  35. package/app/src/lib/components/PageCard.svelte +3 -4
  36. package/app/src/lib/components/PreviewPane.svelte +19 -1
  37. package/app/src/lib/components/RuneAttributes.svelte +249 -100
  38. package/app/src/lib/editor/block-parser.ts +463 -0
  39. package/app/src/lib/preview/block-renderer.ts +30 -14
  40. package/dist/community-tags-builder.d.ts.map +1 -1
  41. package/dist/community-tags-builder.js +5 -1
  42. package/dist/community-tags-builder.js.map +1 -1
  43. package/dist/server.d.ts +1 -0
  44. package/dist/server.d.ts.map +1 -1
  45. package/dist/server.js +92 -6
  46. package/dist/server.js.map +1 -1
  47. package/package.json +6 -6
  48. package/preview-runtime/App.svelte +2 -0
  49. package/app/dist/assets/index-DlrXwdpb.css +0 -1
  50. package/app/dist/assets/index-GlUHQ_jL.js +0 -324
@@ -0,0 +1,181 @@
1
+ <script lang="ts">
2
+ import type { ContentNode } from '../editor/block-parser.js';
3
+
4
+ interface Props {
5
+ nodes: ContentNode[];
6
+ activePath: number[];
7
+ onselect: (path: number[]) => void;
8
+ // Root node (only at top level)
9
+ rootLabel?: string;
10
+ onrootclick?: () => void;
11
+ isRootActive?: boolean;
12
+ // Internal (for recursion)
13
+ depth?: number;
14
+ pathPrefix?: number[];
15
+ }
16
+
17
+ let {
18
+ nodes, activePath, onselect,
19
+ rootLabel, onrootclick, isRootActive = false,
20
+ depth = 0, pathPrefix = [],
21
+ }: Props = $props();
22
+
23
+ function isActivePath(path: number[]): boolean {
24
+ if (path.length !== activePath.length) return false;
25
+ return path.every((v, i) => v === activePath[i]);
26
+ }
27
+
28
+ function isInActivePath(path: number[]): boolean {
29
+ if (path.length > activePath.length) return false;
30
+ return path.every((v, i) => v === activePath[i]);
31
+ }
32
+
33
+ const TYPE_ICONS: Record<string, string> = {
34
+ heading: 'M3 3v10M13 3v10M3 8h10',
35
+ paragraph: 'M2 4h12M2 8h12M2 12h8',
36
+ fence: 'M5 4L2 8l3 4M11 4l3 4-3 4',
37
+ list: 'M4 4h10M4 8h10M4 12h10M2 4h0M2 8h0M2 12h0',
38
+ quote: 'M4 4h8M4 7h6M1 3v8',
39
+ hr: 'M2 8h12',
40
+ image: 'M2 2h12v12H2zM5 5l-3 7h12l-4-5-2 2.5',
41
+ };
42
+ </script>
43
+
44
+ <!-- Root node (only rendered at top level) -->
45
+ {#if rootLabel && onrootclick}
46
+ <div class="tree-node">
47
+ <button
48
+ type="button"
49
+ class="tree-node__btn tree-node__btn--rune"
50
+ class:active={isRootActive}
51
+ onclick={onrootclick}
52
+ >
53
+ <span class="tree-node__indicator">▾</span>
54
+ <span class="tree-node__rune-dot"></span>
55
+ <span class="tree-node__label tree-node__label--rune">{rootLabel}</span>
56
+ </button>
57
+ </div>
58
+ {/if}
59
+
60
+ {#each nodes as node, i}
61
+ {@const nodePath = [...pathPrefix, i]}
62
+ {@const isRune = node.type === 'rune'}
63
+ {@const isActive = isActivePath(nodePath)}
64
+ {@const isAncestor = isInActivePath(nodePath) && !isActive}
65
+ {@const hasChildren = isRune && !node.selfClosing && node.children && node.children.length > 0}
66
+
67
+ <div class="tree-node" style="padding-left: {(depth + (rootLabel ? 1 : 0)) * 16}px">
68
+ {#if isRune}
69
+ <button
70
+ type="button"
71
+ class="tree-node__btn tree-node__btn--rune"
72
+ class:active={isActive}
73
+ class:ancestor={isAncestor}
74
+ onclick={() => onselect(nodePath)}
75
+ >
76
+ <span class="tree-node__indicator">{hasChildren ? '▾' : '▸'}</span>
77
+ <span class="tree-node__rune-dot"></span>
78
+ <span class="tree-node__label tree-node__label--rune">{node.label}</span>
79
+ </button>
80
+ {:else}
81
+ <button
82
+ type="button"
83
+ class="tree-node__btn tree-node__btn--content"
84
+ class:active={isActive}
85
+ onclick={() => onselect(nodePath)}
86
+ >
87
+ <svg class="tree-node__icon" width="12" height="12" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
88
+ <path d={TYPE_ICONS[node.type] ?? 'M2 4h12M2 8h12M2 12h8'} />
89
+ </svg>
90
+ <span class="tree-node__label tree-node__label--content">{node.label}</span>
91
+ </button>
92
+ {/if}
93
+ </div>
94
+
95
+ {#if hasChildren && node.children}
96
+ <svelte:self
97
+ nodes={node.children}
98
+ {activePath}
99
+ {onselect}
100
+ depth={depth + 1}
101
+ pathPrefix={nodePath}
102
+ />
103
+ {/if}
104
+ {/each}
105
+
106
+ <style>
107
+ .tree-node {
108
+ display: flex;
109
+ }
110
+
111
+ .tree-node__btn {
112
+ display: flex;
113
+ align-items: center;
114
+ gap: 0.35rem;
115
+ width: 100%;
116
+ padding: 0.2rem 0.4rem;
117
+ border: none;
118
+ border-radius: calc(var(--ed-radius-sm, 4px) - 1px);
119
+ background: transparent;
120
+ color: var(--ed-text-secondary);
121
+ font-size: var(--ed-text-base);
122
+ cursor: pointer;
123
+ text-align: left;
124
+ transition: background var(--ed-transition-fast);
125
+ }
126
+
127
+ .tree-node__btn:hover {
128
+ background: var(--ed-surface-2);
129
+ }
130
+
131
+ .tree-node__btn.active {
132
+ background: var(--ed-accent-muted);
133
+ color: var(--ed-accent);
134
+ }
135
+
136
+ .tree-node__btn.ancestor {
137
+ color: var(--ed-text-primary);
138
+ }
139
+
140
+ .tree-node__btn--content {
141
+ color: var(--ed-text-muted);
142
+ font-size: var(--ed-text-sm);
143
+ }
144
+
145
+ .tree-node__btn--content.active {
146
+ background: var(--ed-surface-2);
147
+ color: var(--ed-text-secondary);
148
+ }
149
+
150
+ .tree-node__indicator {
151
+ width: 12px;
152
+ font-size: 10px;
153
+ color: var(--ed-text-muted);
154
+ flex-shrink: 0;
155
+ text-align: center;
156
+ }
157
+
158
+ .tree-node__rune-dot {
159
+ width: 5px;
160
+ height: 5px;
161
+ border-radius: 50%;
162
+ background: var(--ed-warning);
163
+ flex-shrink: 0;
164
+ }
165
+
166
+ .tree-node__icon {
167
+ flex-shrink: 0;
168
+ opacity: 0.5;
169
+ }
170
+
171
+ .tree-node__label--rune {
172
+ font-weight: 500;
173
+ }
174
+
175
+ .tree-node__label--content {
176
+ overflow: hidden;
177
+ text-overflow: ellipsis;
178
+ white-space: nowrap;
179
+ min-width: 0;
180
+ }
181
+ </style>
@@ -41,7 +41,7 @@
41
41
  {@render center()}
42
42
  </div>
43
43
  </div>
44
- <div class="layout__panel layout__panel--right" class:panel-editing={editorState.editPanelOpen}>
44
+ <div class="layout__panel layout__panel--right">
45
45
  {@render right()}
46
46
  </div>
47
47
  </div>
@@ -113,10 +113,5 @@
113
113
  .layout__panel--right {
114
114
  background: var(--ed-surface-1);
115
115
  align-items: center;
116
- transition: padding-right var(--ed-transition-slow);
117
- }
118
-
119
- .layout__panel--right.panel-editing {
120
- padding-right: 480px;
121
116
  }
122
117
  </style>
@@ -194,7 +194,6 @@
194
194
  .edit-panel {
195
195
  display: flex;
196
196
  flex-direction: column;
197
- height: 100%;
198
197
  }
199
198
 
200
199
  .edit-panel__header {
@@ -113,6 +113,37 @@
113
113
  </svg>
114
114
  </button>
115
115
  </div>
116
+ <span class="header__divider"></span>
117
+ <div class="header__group">
118
+ <button
119
+ class="header__btn header__btn--icon"
120
+ class:header__btn--active={editorState.previewTheme === 'light'}
121
+ onclick={() => editorState.previewTheme = 'light'}
122
+ title="Light mode"
123
+ >
124
+ <svg width="15" height="15" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
125
+ <circle cx="8" cy="8" r="3" />
126
+ <line x1="8" y1="1.5" x2="8" y2="3" />
127
+ <line x1="8" y1="13" x2="8" y2="14.5" />
128
+ <line x1="2.4" y1="2.4" x2="3.5" y2="3.5" />
129
+ <line x1="12.5" y1="12.5" x2="13.6" y2="13.6" />
130
+ <line x1="1.5" y1="8" x2="3" y2="8" />
131
+ <line x1="13" y1="8" x2="14.5" y2="8" />
132
+ <line x1="2.4" y1="13.6" x2="3.5" y2="12.5" />
133
+ <line x1="12.5" y1="3.5" x2="13.6" y2="2.4" />
134
+ </svg>
135
+ </button>
136
+ <button
137
+ class="header__btn header__btn--icon"
138
+ class:header__btn--active={editorState.previewTheme === 'dark'}
139
+ onclick={() => editorState.previewTheme = 'dark'}
140
+ title="Dark mode"
141
+ >
142
+ <svg width="15" height="15" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
143
+ <path d="M13.5 8.5a5.5 5.5 0 0 1-7-7 5.5 5.5 0 1 0 7 7Z" />
144
+ </svg>
145
+ </button>
146
+ </div>
116
147
  {:else if isEdit}
117
148
  <div class="header__group">
118
149
  <button
@@ -253,6 +284,13 @@
253
284
  gap: var(--ed-space-2);
254
285
  }
255
286
 
287
+ .header__divider {
288
+ width: 1px;
289
+ height: 16px;
290
+ background: var(--ed-border-strong);
291
+ opacity: 0.5;
292
+ }
293
+
256
294
  /* ── Unified button style ─────────────────────────── */
257
295
 
258
296
  .header__btn {