@spatika/editor 1.5.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.
Files changed (142) hide show
  1. package/README.md +43 -0
  2. package/dist/composites/AiCommandDock.d.ts +13 -0
  3. package/dist/composites/AiCommandDock.d.ts.map +1 -0
  4. package/dist/composites/AiCommandDock.js +63 -0
  5. package/dist/composites/AiCommandMenu.d.ts +16 -0
  6. package/dist/composites/AiCommandMenu.d.ts.map +1 -0
  7. package/dist/composites/AiCommandMenu.js +51 -0
  8. package/dist/composites/AiCommandPanel.d.ts +12 -0
  9. package/dist/composites/AiCommandPanel.d.ts.map +1 -0
  10. package/dist/composites/AiCommandPanel.js +12 -0
  11. package/dist/composites/AiOverlay.d.ts +7 -0
  12. package/dist/composites/AiOverlay.d.ts.map +1 -0
  13. package/dist/composites/AiOverlay.js +8 -0
  14. package/dist/composites/EditorBubbleMenu.d.ts +10 -0
  15. package/dist/composites/EditorBubbleMenu.d.ts.map +1 -0
  16. package/dist/composites/EditorBubbleMenu.js +16 -0
  17. package/dist/composites/EditorToolbar.d.ts +20 -0
  18. package/dist/composites/EditorToolbar.d.ts.map +1 -0
  19. package/dist/composites/EditorToolbar.js +45 -0
  20. package/dist/composites/ImageBubbleMenu.d.ts +7 -0
  21. package/dist/composites/ImageBubbleMenu.d.ts.map +1 -0
  22. package/dist/composites/ImageBubbleMenu.js +15 -0
  23. package/dist/composites/MentionMenu.d.ts +11 -0
  24. package/dist/composites/MentionMenu.d.ts.map +1 -0
  25. package/dist/composites/MentionMenu.js +10 -0
  26. package/dist/composites/SlashCommandMenu.d.ts +13 -0
  27. package/dist/composites/SlashCommandMenu.d.ts.map +1 -0
  28. package/dist/composites/SlashCommandMenu.js +10 -0
  29. package/dist/composites/SpatikaEditor.d.ts +14 -0
  30. package/dist/composites/SpatikaEditor.d.ts.map +1 -0
  31. package/dist/composites/SpatikaEditor.js +159 -0
  32. package/dist/composites/TableGridPicker.d.ts +9 -0
  33. package/dist/composites/TableGridPicker.d.ts.map +1 -0
  34. package/dist/composites/TableGridPicker.js +54 -0
  35. package/dist/composites/ToolbarButton.d.ts +7 -0
  36. package/dist/composites/ToolbarButton.d.ts.map +1 -0
  37. package/dist/composites/ToolbarButton.js +7 -0
  38. package/dist/composites/ToolbarFormatPanels.d.ts +9 -0
  39. package/dist/composites/ToolbarFormatPanels.d.ts.map +1 -0
  40. package/dist/composites/ToolbarFormatPanels.js +35 -0
  41. package/dist/composites/ToolbarInsertPanels.d.ts +14 -0
  42. package/dist/composites/ToolbarInsertPanels.d.ts.map +1 -0
  43. package/dist/composites/ToolbarInsertPanels.js +96 -0
  44. package/dist/composites/ToolbarPopover.d.ts +14 -0
  45. package/dist/composites/ToolbarPopover.d.ts.map +1 -0
  46. package/dist/composites/ToolbarPopover.js +48 -0
  47. package/dist/extensions/ai-action.d.ts +24 -0
  48. package/dist/extensions/ai-action.d.ts.map +1 -0
  49. package/dist/extensions/ai-action.js +53 -0
  50. package/dist/extensions/mention.d.ts +17 -0
  51. package/dist/extensions/mention.d.ts.map +1 -0
  52. package/dist/extensions/mention.js +129 -0
  53. package/dist/extensions/resizable-image-view.d.ts +18 -0
  54. package/dist/extensions/resizable-image-view.d.ts.map +1 -0
  55. package/dist/extensions/resizable-image-view.js +70 -0
  56. package/dist/extensions/resizable-image.d.ts +4 -0
  57. package/dist/extensions/resizable-image.d.ts.map +1 -0
  58. package/dist/extensions/resizable-image.js +68 -0
  59. package/dist/extensions/slash-command.d.ts +18 -0
  60. package/dist/extensions/slash-command.d.ts.map +1 -0
  61. package/dist/extensions/slash-command.js +178 -0
  62. package/dist/index.d.ts +24 -0
  63. package/dist/index.d.ts.map +1 -0
  64. package/dist/index.js +18 -0
  65. package/dist/lib/ai-command-menu.d.ts +9 -0
  66. package/dist/lib/ai-command-menu.d.ts.map +1 -0
  67. package/dist/lib/ai-command-menu.js +43 -0
  68. package/dist/lib/cn.d.ts +4 -0
  69. package/dist/lib/cn.d.ts.map +1 -0
  70. package/dist/lib/cn.js +6 -0
  71. package/dist/lib/editor-format-colors.d.ts +10 -0
  72. package/dist/lib/editor-format-colors.d.ts.map +1 -0
  73. package/dist/lib/editor-format-colors.js +24 -0
  74. package/dist/lib/image-upload.d.ts +14 -0
  75. package/dist/lib/image-upload.d.ts.map +1 -0
  76. package/dist/lib/image-upload.js +29 -0
  77. package/dist/lib/insert-editor-images.d.ts +5 -0
  78. package/dist/lib/insert-editor-images.d.ts.map +1 -0
  79. package/dist/lib/insert-editor-images.js +32 -0
  80. package/dist/lib/types.d.ts +131 -0
  81. package/dist/lib/types.d.ts.map +1 -0
  82. package/dist/lib/types.js +12 -0
  83. package/dist/lib/use-spatika-editor.d.ts +13 -0
  84. package/dist/lib/use-spatika-editor.d.ts.map +1 -0
  85. package/dist/lib/use-spatika-editor.js +171 -0
  86. package/dist/styles.css +1056 -0
  87. package/package.json +101 -0
  88. package/src/composites/AiCommandDock.test.tsx +48 -0
  89. package/src/composites/AiCommandDock.tsx +137 -0
  90. package/src/composites/AiCommandMenu.test.tsx +67 -0
  91. package/src/composites/AiCommandMenu.tsx +120 -0
  92. package/src/composites/AiCommandPanel.test.tsx +42 -0
  93. package/src/composites/AiCommandPanel.tsx +56 -0
  94. package/src/composites/AiOverlay.test.tsx +18 -0
  95. package/src/composites/AiOverlay.tsx +18 -0
  96. package/src/composites/EditorBubbleMenu.test.tsx +49 -0
  97. package/src/composites/EditorBubbleMenu.tsx +73 -0
  98. package/src/composites/EditorToolbar.test.tsx +146 -0
  99. package/src/composites/EditorToolbar.tsx +362 -0
  100. package/src/composites/ImageBubbleMenu.test.tsx +43 -0
  101. package/src/composites/ImageBubbleMenu.tsx +51 -0
  102. package/src/composites/MentionMenu.test.tsx +25 -0
  103. package/src/composites/MentionMenu.tsx +46 -0
  104. package/src/composites/SlashCommandMenu.test.tsx +33 -0
  105. package/src/composites/SlashCommandMenu.tsx +54 -0
  106. package/src/composites/SpatikaEditor.test.tsx +167 -0
  107. package/src/composites/SpatikaEditor.tsx +302 -0
  108. package/src/composites/TableGridPicker.test.tsx +26 -0
  109. package/src/composites/TableGridPicker.tsx +138 -0
  110. package/src/composites/ToolbarButton.test.tsx +21 -0
  111. package/src/composites/ToolbarButton.tsx +24 -0
  112. package/src/composites/ToolbarFormatPanels.test.tsx +46 -0
  113. package/src/composites/ToolbarFormatPanels.tsx +78 -0
  114. package/src/composites/ToolbarInsertPanels.test.tsx +60 -0
  115. package/src/composites/ToolbarInsertPanels.tsx +200 -0
  116. package/src/composites/ToolbarPopover.test.tsx +24 -0
  117. package/src/composites/ToolbarPopover.tsx +95 -0
  118. package/src/extensions/ai-action.test.ts +26 -0
  119. package/src/extensions/ai-action.ts +73 -0
  120. package/src/extensions/mention.test.ts +31 -0
  121. package/src/extensions/mention.ts +158 -0
  122. package/src/extensions/resizable-image-view.test.ts +26 -0
  123. package/src/extensions/resizable-image-view.ts +96 -0
  124. package/src/extensions/resizable-image.test.ts +28 -0
  125. package/src/extensions/resizable-image.ts +75 -0
  126. package/src/extensions/slash-command.test.ts +45 -0
  127. package/src/extensions/slash-command.ts +197 -0
  128. package/src/index.ts +49 -0
  129. package/src/lib/ai-command-menu.test.ts +48 -0
  130. package/src/lib/ai-command-menu.ts +57 -0
  131. package/src/lib/cn.ts +7 -0
  132. package/src/lib/editor-format-colors.test.ts +15 -0
  133. package/src/lib/editor-format-colors.ts +31 -0
  134. package/src/lib/image-upload.test.ts +19 -0
  135. package/src/lib/image-upload.ts +49 -0
  136. package/src/lib/insert-editor-images.test.ts +76 -0
  137. package/src/lib/insert-editor-images.ts +44 -0
  138. package/src/lib/types.ts +149 -0
  139. package/src/lib/use-spatika-editor.test.tsx +56 -0
  140. package/src/lib/use-spatika-editor.ts +191 -0
  141. package/src/styles/editor.css +1056 -0
  142. package/src/test/setup.ts +46 -0
@@ -0,0 +1,1056 @@
1
+ /**
2
+ * Spatika glass editor styles — import `@spatika/editor/styles.css` alongside `@spatika/tokens/styles.css`.
3
+ */
4
+
5
+ .spk-editor-shell {
6
+ /* Opaque surfaces for menus/popovers that float over document text. */
7
+ --spk-editor-overlay-bg: color-mix(in srgb, var(--background) 97%, var(--glass-panel-bg) 3%);
8
+ border-radius: var(--radius-card);
9
+ border: 1px solid var(--glass-border, var(--border));
10
+ background: var(--glass-panel-bg, var(--card));
11
+ backdrop-filter: blur(var(--glass-blur, 12px)) saturate(var(--glass-saturate, 1.2));
12
+ box-shadow: var(--glass-shadow, var(--shadow-sm));
13
+ overflow: hidden;
14
+ display: flex;
15
+ flex-direction: column;
16
+ min-width: 0;
17
+ }
18
+
19
+ .spk-editor-shell--disabled {
20
+ opacity: 0.65;
21
+ pointer-events: none;
22
+ }
23
+
24
+ .spk-editor-shell--loading {
25
+ padding: 1rem;
26
+ color: var(--muted-foreground);
27
+ font-size: 0.875rem;
28
+ }
29
+
30
+ .spk-editor-shell--fullscreen {
31
+ position: fixed;
32
+ inset: 0;
33
+ z-index: var(--z-modal, 50);
34
+ border-radius: 0;
35
+ max-height: none;
36
+ }
37
+
38
+ .spk-editor-toolbar {
39
+ position: relative;
40
+ z-index: 2;
41
+ overflow: visible;
42
+ background: var(--glass-header-bg, var(--muted));
43
+ backdrop-filter: blur(var(--glass-header-blur, 8px));
44
+ border-bottom: 1px solid var(--glass-border, var(--border));
45
+ display: flex;
46
+ flex-wrap: wrap;
47
+ align-items: center;
48
+ gap: 0.35rem;
49
+ padding: 0.35rem 0.5rem;
50
+ }
51
+
52
+ .spk-editor-toolbar--compact .spk-editor-toolbar-row {
53
+ flex-wrap: nowrap;
54
+ overflow-x: auto;
55
+ }
56
+
57
+ .spk-editor-toolbar-row {
58
+ display: flex;
59
+ flex-wrap: wrap;
60
+ gap: 0.35rem;
61
+ align-items: center;
62
+ }
63
+
64
+ .spk-editor-toolbar-group {
65
+ display: inline-flex;
66
+ gap: 0.15rem;
67
+ padding-right: 0.35rem;
68
+ border-right: 1px solid var(--border);
69
+ }
70
+
71
+ .spk-editor-toolbar-group:last-child {
72
+ border-right: 0;
73
+ }
74
+
75
+ .spk-editor-toolbar-actions {
76
+ margin-left: auto;
77
+ display: inline-flex;
78
+ gap: 0.25rem;
79
+ }
80
+
81
+ .spk-editor-toolbar-btn {
82
+ display: inline-flex;
83
+ align-items: center;
84
+ justify-content: center;
85
+ width: 2rem;
86
+ height: 2rem;
87
+ border-radius: var(--radius-sm, 0.375rem);
88
+ border: 0;
89
+ background: transparent;
90
+ color: var(--foreground);
91
+ cursor: pointer;
92
+ }
93
+
94
+ .spk-editor-toolbar-btn:hover {
95
+ background: color-mix(in oklab, var(--foreground) 8%, transparent);
96
+ }
97
+
98
+ .spk-editor-toolbar-btn--active,
99
+ .spk-editor-toolbar-btn[data-active="true"] {
100
+ background: color-mix(in oklab, var(--primary) 16%, transparent);
101
+ color: var(--primary);
102
+ }
103
+
104
+ .spk-editor-body {
105
+ position: relative;
106
+ flex: 1 1 auto;
107
+ min-height: 0;
108
+ }
109
+
110
+ .spk-editor-shell--with-ai-dock {
111
+ min-height: inherit;
112
+ }
113
+
114
+ .spk-editor-shell--with-ai-dock .spk-editor-body {
115
+ overflow-y: auto;
116
+ }
117
+
118
+ .spk-editor-ai-dock-footer {
119
+ position: relative;
120
+ flex-shrink: 0;
121
+ z-index: 3;
122
+ padding: 0.65rem 0.85rem 0.75rem;
123
+ border-top: 1px solid var(--glass-border, var(--border));
124
+ background: color-mix(in oklab, var(--background) 92%, var(--glass-panel-bg));
125
+ }
126
+
127
+ .spk-editor-shell--playground {
128
+ min-height: 32rem;
129
+ overflow: visible;
130
+ }
131
+
132
+ .spk-editor-shell--playground .spk-editor-body {
133
+ overflow: visible;
134
+ }
135
+
136
+ .spk-editor-surface {
137
+ padding: 0.85rem 1rem;
138
+ }
139
+
140
+ .spk-editor-shell .ProseMirror {
141
+ outline: none;
142
+ min-height: inherit;
143
+ font-family: var(--font-body, inherit);
144
+ color: var(--foreground);
145
+ line-height: 1.65;
146
+ }
147
+
148
+ .spk-editor-shell .ProseMirror h1 {
149
+ font-size: 1.75rem;
150
+ font-weight: 700;
151
+ margin: 0.75rem 0 0.35rem;
152
+ }
153
+
154
+ .spk-editor-shell .ProseMirror h2 {
155
+ font-size: 1.35rem;
156
+ font-weight: 650;
157
+ margin: 0.65rem 0 0.3rem;
158
+ }
159
+
160
+ .spk-editor-shell .ProseMirror h3 {
161
+ font-size: 1.1rem;
162
+ font-weight: 600;
163
+ margin: 0.55rem 0 0.25rem;
164
+ }
165
+
166
+ .spk-editor-shell .ProseMirror p {
167
+ margin: 0.35rem 0;
168
+ }
169
+
170
+ .spk-editor-shell .ProseMirror blockquote {
171
+ border-left: 3px solid var(--primary);
172
+ margin: 0.5rem 0;
173
+ padding-left: 0.85rem;
174
+ color: var(--muted-foreground);
175
+ }
176
+
177
+ .spk-editor-shell .ProseMirror ul,
178
+ .spk-editor-shell .ProseMirror ol {
179
+ margin: 0.35rem 0;
180
+ padding-left: 1.25rem;
181
+ }
182
+
183
+ .spk-editor-shell .ProseMirror ul[data-type="taskList"] {
184
+ list-style: none;
185
+ padding-left: 0;
186
+ }
187
+
188
+ .spk-editor-shell .ProseMirror ul[data-type="taskList"] li {
189
+ display: flex;
190
+ align-items: flex-start;
191
+ gap: 0.45rem;
192
+ }
193
+
194
+ .spk-editor-shell .ProseMirror ul[data-type="taskList"] li > label {
195
+ flex: 0 0 auto;
196
+ margin-top: 0.2rem;
197
+ user-select: none;
198
+ }
199
+
200
+ .spk-editor-shell .ProseMirror ul[data-type="taskList"] li > div {
201
+ flex: 1 1 auto;
202
+ }
203
+
204
+ .spk-editor-shell .ProseMirror ul[data-type="taskList"] input[type="checkbox"] {
205
+ accent-color: var(--primary);
206
+ width: 0.95rem;
207
+ height: 0.95rem;
208
+ cursor: pointer;
209
+ }
210
+
211
+ .spk-editor-shell .ProseMirror code {
212
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New",
213
+ monospace;
214
+ font-size: 0.875em;
215
+ border-radius: 0.25rem;
216
+ background: color-mix(in oklab, var(--muted) 75%, transparent);
217
+ padding: 0.08rem 0.3rem;
218
+ }
219
+
220
+ .spk-editor-shell .ProseMirror pre {
221
+ margin: 0.5rem 0;
222
+ border-radius: var(--radius-sm, 0.375rem);
223
+ border: 1px solid var(--border);
224
+ background: color-mix(in oklab, var(--muted) 55%, var(--background));
225
+ padding: 0.65rem 0.75rem;
226
+ overflow-x: auto;
227
+ }
228
+
229
+ .spk-editor-shell .ProseMirror pre code {
230
+ display: block;
231
+ background: transparent;
232
+ padding: 0;
233
+ font-size: 0.8125rem;
234
+ line-height: 1.55;
235
+ }
236
+
237
+ .spk-editor-shell .ProseMirror mark {
238
+ border-radius: 0.15rem;
239
+ padding: 0.05rem 0.1rem;
240
+ }
241
+
242
+ .spk-editor-color-grid {
243
+ display: grid;
244
+ grid-template-columns: repeat(5, minmax(0, 1fr));
245
+ gap: 0.4rem;
246
+ }
247
+
248
+ .spk-editor-color-swatch {
249
+ width: 1.65rem;
250
+ height: 1.65rem;
251
+ border-radius: 999px;
252
+ border: 1px solid var(--border);
253
+ background: var(--swatch-color, var(--foreground));
254
+ cursor: pointer;
255
+ padding: 0;
256
+ }
257
+
258
+ .spk-editor-color-swatch--default {
259
+ background:
260
+ linear-gradient(135deg, transparent 46%, var(--destructive, #dc2626) 46%, var(--destructive, #dc2626) 54%, transparent 54%),
261
+ var(--background);
262
+ }
263
+
264
+ .spk-editor-color-swatch--active {
265
+ box-shadow: 0 0 0 2px var(--background), 0 0 0 3px var(--primary);
266
+ }
267
+
268
+ .spk-editor-shell .ProseMirror hr {
269
+ border: 0;
270
+ border-top: 1px solid var(--border);
271
+ margin: 0.85rem 0;
272
+ }
273
+
274
+ .spk-editor-shell .ProseMirror table {
275
+ border-collapse: collapse;
276
+ width: 100%;
277
+ margin: 0.5rem 0;
278
+ }
279
+
280
+ .spk-editor-shell .ProseMirror th,
281
+ .spk-editor-shell .ProseMirror td {
282
+ border: 1px solid var(--border);
283
+ padding: 0.35rem 0.5rem;
284
+ vertical-align: top;
285
+ }
286
+
287
+ .spk-editor-shell .ProseMirror th {
288
+ background: color-mix(in oklab, var(--muted) 70%, transparent);
289
+ font-weight: 600;
290
+ }
291
+
292
+ .spk-editor-shell .ProseMirror img,
293
+ .spk-editor-image {
294
+ max-width: 100%;
295
+ height: auto;
296
+ border-radius: var(--radius-sm, 0.375rem);
297
+ display: block;
298
+ margin: 0.5rem auto;
299
+ }
300
+
301
+ .spk-editor-image--left {
302
+ margin-left: 0;
303
+ margin-right: auto;
304
+ }
305
+
306
+ .spk-editor-image--right {
307
+ margin-left: auto;
308
+ margin-right: 0;
309
+ }
310
+
311
+ .spk-editor-link {
312
+ color: var(--primary);
313
+ text-decoration: underline;
314
+ text-underline-offset: 2px;
315
+ }
316
+
317
+ .spk-editor-mention {
318
+ display: inline-flex;
319
+ align-items: center;
320
+ border-radius: var(--radius-pill, 999px);
321
+ background: color-mix(in oklab, var(--primary) 14%, transparent);
322
+ color: var(--primary);
323
+ padding: 0.05rem 0.45rem;
324
+ font-weight: 500;
325
+ }
326
+
327
+ .spk-editor-shell .ProseMirror p.is-editor-empty:first-child::before {
328
+ color: var(--muted-foreground);
329
+ content: attr(data-placeholder);
330
+ pointer-events: none;
331
+ float: left;
332
+ height: 0;
333
+ }
334
+
335
+ .spk-editor-bubble-menu {
336
+ display: inline-flex;
337
+ align-items: center;
338
+ gap: 0.15rem;
339
+ padding: 0.2rem;
340
+ background: var(--spk-editor-overlay-bg, var(--background));
341
+ backdrop-filter: blur(var(--glass-menu-blur, var(--glass-blur, 12px)))
342
+ saturate(var(--glass-saturate, 190%));
343
+ border: 1px solid var(--glass-border, var(--border));
344
+ border-radius: var(--radius-pill, 999px);
345
+ box-shadow: var(--shadow-raised, var(--shadow-md));
346
+ }
347
+
348
+ .spk-editor-suggestion {
349
+ position: absolute;
350
+ z-index: 20;
351
+ left: 1rem;
352
+ top: 3.5rem;
353
+ min-width: 14rem;
354
+ max-width: min(20rem, calc(100% - 2rem));
355
+ background: var(--spk-editor-overlay-bg, var(--background));
356
+ backdrop-filter: blur(var(--glass-menu-blur, var(--glass-blur, 12px)))
357
+ saturate(var(--glass-saturate, 190%));
358
+ border: 1px solid var(--glass-border, var(--border));
359
+ border-radius: var(--radius-card);
360
+ box-shadow: var(--shadow-raised, var(--shadow-md));
361
+ overflow: hidden;
362
+ }
363
+
364
+ .spk-editor-suggestion-header {
365
+ padding: 0.45rem 0.65rem;
366
+ font-size: 0.72rem;
367
+ text-transform: uppercase;
368
+ letter-spacing: 0.04em;
369
+ color: var(--muted-foreground);
370
+ border-bottom: 1px solid var(--border);
371
+ }
372
+
373
+ .spk-editor-suggestion-list {
374
+ list-style: none;
375
+ margin: 0;
376
+ padding: 0.25rem;
377
+ max-height: 14rem;
378
+ overflow-y: auto;
379
+ }
380
+
381
+ .spk-editor-suggestion-item {
382
+ width: 100%;
383
+ text-align: left;
384
+ border: 0;
385
+ background: transparent;
386
+ border-radius: var(--radius-sm, 0.375rem);
387
+ padding: 0.45rem 0.55rem;
388
+ cursor: pointer;
389
+ display: flex;
390
+ flex-direction: column;
391
+ gap: 0.1rem;
392
+ }
393
+
394
+ .spk-editor-suggestion-item:hover,
395
+ .spk-editor-suggestion-item--active {
396
+ background: color-mix(in oklab, var(--primary) 10%, transparent);
397
+ }
398
+
399
+ .spk-editor-suggestion-title {
400
+ font-size: 0.875rem;
401
+ font-weight: 600;
402
+ color: var(--foreground);
403
+ }
404
+
405
+ .spk-editor-suggestion-desc {
406
+ font-size: 0.75rem;
407
+ color: var(--muted-foreground);
408
+ }
409
+
410
+ .spk-editor-ai-overlay {
411
+ position: absolute;
412
+ inset: 0;
413
+ display: flex;
414
+ align-items: center;
415
+ justify-content: center;
416
+ gap: 0.5rem;
417
+ background: color-mix(in oklab, var(--background) 55%, transparent);
418
+ color: var(--primary);
419
+ font-size: 0.875rem;
420
+ font-weight: 500;
421
+ pointer-events: none;
422
+ }
423
+
424
+ .spk-editor-ai-overlay-icon {
425
+ animation: spk-editor-sparkle 1.2s ease-in-out infinite;
426
+ }
427
+
428
+ .spk-editor-ai-selection {
429
+ background: color-mix(in oklab, var(--primary) 18%, transparent);
430
+ border-radius: 0.15rem;
431
+ }
432
+
433
+ .spk-editor-fullscreen-bar {
434
+ display: flex;
435
+ justify-content: flex-end;
436
+ padding: 0.5rem 0.75rem;
437
+ padding-top: max(0.5rem, env(safe-area-inset-top));
438
+ border-top: 1px solid var(--border);
439
+ background: var(--glass-header-bg, var(--muted));
440
+ }
441
+
442
+ .spk-editor-fullscreen-close {
443
+ border: 0;
444
+ border-radius: var(--radius-pill, 999px);
445
+ min-height: 2.75rem;
446
+ padding: 0.35rem 0.85rem;
447
+ background: var(--primary);
448
+ color: var(--primary-foreground);
449
+ font-weight: 600;
450
+ cursor: pointer;
451
+ }
452
+
453
+ @media (max-width: 767px) {
454
+ .spk-editor-toolbar-row {
455
+ flex-wrap: nowrap;
456
+ overflow-x: auto;
457
+ overscroll-behavior-x: contain;
458
+ -webkit-overflow-scrolling: touch;
459
+ scrollbar-width: none;
460
+ max-width: 100%;
461
+ }
462
+
463
+ .spk-editor-toolbar-row::-webkit-scrollbar {
464
+ display: none;
465
+ }
466
+
467
+ .spk-editor-toolbar-group {
468
+ flex-shrink: 0;
469
+ }
470
+
471
+ .spk-editor-toolbar-btn {
472
+ width: 2.75rem;
473
+ height: 2.75rem;
474
+ flex-shrink: 0;
475
+ }
476
+
477
+ .spk-editor-surface {
478
+ padding: 0.65rem 0.75rem;
479
+ }
480
+
481
+ .spk-editor-shell--playground {
482
+ min-height: min(32rem, 72vh);
483
+ }
484
+
485
+ .spk-editor-shell--playground .spk-editor-surface {
486
+ min-height: min(28rem, 58vh) !important;
487
+ }
488
+
489
+ .spk-editor-ai-dock-footer {
490
+ padding-left: max(0.65rem, env(safe-area-inset-left));
491
+ padding-right: max(0.65rem, env(safe-area-inset-right));
492
+ padding-bottom: max(0.75rem, env(safe-area-inset-bottom));
493
+ }
494
+
495
+ .spk-editor-ai-dock-panel {
496
+ left: 0;
497
+ right: auto;
498
+ width: min(24rem, calc(100vw - 1.7rem));
499
+ max-width: none;
500
+ }
501
+
502
+ .spk-editor-ai-dock-input {
503
+ font-size: 1rem;
504
+ }
505
+
506
+ .spk-editor-toolbar-popover-panel--portal {
507
+ max-width: min(18rem, calc(100vw - 1.5rem));
508
+ }
509
+
510
+ .spk-editor-suggestion {
511
+ left: 0.65rem;
512
+ right: 0.65rem;
513
+ max-width: none;
514
+ width: auto;
515
+ }
516
+
517
+ .spk-editor-shell--fullscreen {
518
+ padding-top: env(safe-area-inset-top);
519
+ padding-bottom: env(safe-area-inset-bottom);
520
+ }
521
+ }
522
+
523
+ @keyframes spk-editor-sparkle {
524
+ 0%,
525
+ 100% {
526
+ opacity: 0.55;
527
+ transform: scale(0.95);
528
+ }
529
+ 50% {
530
+ opacity: 1;
531
+ transform: scale(1.05);
532
+ }
533
+ }
534
+
535
+ .spk-editor-toolbar-popover {
536
+ position: relative;
537
+ display: inline-flex;
538
+ overflow: visible;
539
+ }
540
+
541
+ .spk-editor-toolbar-popover-panel {
542
+ position: absolute;
543
+ top: calc(100% + 0.35rem);
544
+ left: 0;
545
+ z-index: 40;
546
+ min-width: 15rem;
547
+ padding: 0.65rem;
548
+ border-radius: var(--radius-card);
549
+ border: 1px solid var(--glass-border, var(--border));
550
+ background: var(--spk-editor-overlay-bg, var(--background));
551
+ backdrop-filter: blur(var(--glass-menu-blur, var(--glass-blur, 12px)))
552
+ saturate(var(--glass-saturate, 190%));
553
+ box-shadow: var(--shadow-raised, var(--shadow-md));
554
+ overflow: visible;
555
+ }
556
+
557
+ .spk-editor-toolbar-popover-title {
558
+ margin-bottom: 0.55rem;
559
+ font-size: 0.78rem;
560
+ font-weight: 600;
561
+ letter-spacing: 0.03em;
562
+ text-transform: uppercase;
563
+ color: var(--muted-foreground);
564
+ }
565
+
566
+ .spk-editor-toolbar-popover-form {
567
+ display: flex;
568
+ flex-direction: column;
569
+ gap: 0.55rem;
570
+ }
571
+
572
+ .spk-editor-toolbar-popover-grid {
573
+ display: grid;
574
+ grid-template-columns: 1fr 1fr;
575
+ gap: 0.5rem;
576
+ }
577
+
578
+ .spk-editor-toolbar-popover-field {
579
+ display: flex;
580
+ flex-direction: column;
581
+ gap: 0.25rem;
582
+ font-size: 0.78rem;
583
+ color: var(--muted-foreground);
584
+ }
585
+
586
+ .spk-editor-toolbar-popover-input {
587
+ width: 100%;
588
+ border: 1px solid var(--border);
589
+ border-radius: var(--radius-sm, 0.375rem);
590
+ background: var(--input-background, var(--background));
591
+ color: var(--foreground);
592
+ padding: 0.4rem 0.55rem;
593
+ font: inherit;
594
+ font-size: 0.875rem;
595
+ }
596
+
597
+ .spk-editor-toolbar-popover-input:focus {
598
+ outline: 2px solid color-mix(in oklab, var(--primary) 35%, transparent);
599
+ outline-offset: 1px;
600
+ }
601
+
602
+ .spk-editor-toolbar-popover-check {
603
+ display: inline-flex;
604
+ align-items: center;
605
+ gap: 0.45rem;
606
+ font-size: 0.8125rem;
607
+ color: var(--foreground);
608
+ }
609
+
610
+ .spk-editor-toolbar-popover-actions {
611
+ display: flex;
612
+ justify-content: flex-end;
613
+ gap: 0.35rem;
614
+ flex-wrap: wrap;
615
+ }
616
+
617
+ .spk-editor-toolbar-popover-btn {
618
+ border: 0;
619
+ border-radius: var(--radius-pill, 999px);
620
+ padding: 0.35rem 0.75rem;
621
+ font: inherit;
622
+ font-size: 0.8125rem;
623
+ font-weight: 600;
624
+ cursor: pointer;
625
+ }
626
+
627
+ .spk-editor-toolbar-popover-btn--ghost {
628
+ background: transparent;
629
+ color: var(--foreground);
630
+ }
631
+
632
+ .spk-editor-toolbar-popover-btn--ghost:hover {
633
+ background: color-mix(in oklab, var(--foreground) 8%, transparent);
634
+ }
635
+
636
+ .spk-editor-toolbar-popover-btn--primary {
637
+ background: var(--primary);
638
+ color: var(--primary-foreground);
639
+ }
640
+
641
+ .spk-editor-toolbar-popover-btn--primary:disabled {
642
+ opacity: 0.45;
643
+ cursor: not-allowed;
644
+ }
645
+
646
+ .spk-editor-toolbar-btn:disabled {
647
+ opacity: 0.4;
648
+ cursor: not-allowed;
649
+ }
650
+
651
+ .spk-editor-table-picker {
652
+ display: flex;
653
+ flex-direction: column;
654
+ gap: 0.65rem;
655
+ padding: 0.35rem;
656
+ }
657
+
658
+ .spk-editor-table-picker-label {
659
+ font-size: 0.8125rem;
660
+ font-weight: 600;
661
+ color: var(--foreground);
662
+ text-align: center;
663
+ }
664
+
665
+ .spk-editor-table-picker-grid {
666
+ display: grid;
667
+ grid-template-columns: repeat(10, 1.125rem);
668
+ gap: 0.25rem;
669
+ justify-content: center;
670
+ touch-action: none;
671
+ user-select: none;
672
+ }
673
+
674
+ .spk-editor-table-picker-cell {
675
+ width: 1.125rem;
676
+ height: 1.125rem;
677
+ border: 0;
678
+ border-radius: 0.25rem;
679
+ background: color-mix(in oklab, var(--muted-foreground) 18%, transparent);
680
+ cursor: pointer;
681
+ padding: 0;
682
+ }
683
+
684
+ .spk-editor-table-picker-cell--active {
685
+ background: color-mix(in oklab, var(--primary) 55%, transparent);
686
+ }
687
+
688
+ .spk-editor-table-picker-size {
689
+ display: flex;
690
+ align-items: center;
691
+ justify-content: center;
692
+ gap: 0.45rem;
693
+ }
694
+
695
+ .spk-editor-table-picker-size-field {
696
+ display: inline-flex;
697
+ align-items: center;
698
+ gap: 0.35rem;
699
+ color: var(--muted-foreground);
700
+ }
701
+
702
+ .spk-editor-table-picker-size-input {
703
+ width: 3rem;
704
+ border: 1px solid var(--border);
705
+ border-radius: var(--radius-sm, 0.375rem);
706
+ background: var(--background);
707
+ color: var(--foreground);
708
+ padding: 0.25rem 0.35rem;
709
+ text-align: center;
710
+ }
711
+
712
+ .spk-editor-table-picker-size-sep {
713
+ color: var(--muted-foreground);
714
+ }
715
+
716
+ .spk-editor-table-picker-insert {
717
+ width: 100%;
718
+ }
719
+
720
+ .spk-editor-image-insert {
721
+ min-width: 16rem;
722
+ }
723
+
724
+ .spk-editor-image-dropzone {
725
+ display: flex;
726
+ flex-direction: column;
727
+ align-items: center;
728
+ gap: 0.35rem;
729
+ width: 100%;
730
+ border: 1px dashed color-mix(in oklab, var(--primary) 35%, var(--border));
731
+ border-radius: var(--radius-card);
732
+ background: color-mix(in oklab, var(--primary) 4%, transparent);
733
+ padding: 1rem 0.75rem;
734
+ cursor: pointer;
735
+ text-align: center;
736
+ }
737
+
738
+ .spk-editor-image-dropzone--active,
739
+ .spk-editor-image-dropzone:hover {
740
+ border-color: var(--primary);
741
+ background: color-mix(in oklab, var(--primary) 10%, transparent);
742
+ }
743
+
744
+ .spk-editor-image-dropzone-icon {
745
+ display: inline-flex;
746
+ align-items: center;
747
+ justify-content: center;
748
+ width: 2.2rem;
749
+ height: 2.2rem;
750
+ border-radius: var(--radius-pill, 999px);
751
+ background: color-mix(in oklab, var(--primary) 16%, transparent);
752
+ color: var(--primary);
753
+ }
754
+
755
+ .spk-editor-image-dropzone-title {
756
+ font-size: 0.875rem;
757
+ font-weight: 600;
758
+ color: var(--foreground);
759
+ }
760
+
761
+ .spk-editor-image-dropzone-hint,
762
+ .spk-editor-image-insert-error {
763
+ font-size: 0.75rem;
764
+ color: var(--muted-foreground);
765
+ }
766
+
767
+ .spk-editor-image-insert-error {
768
+ color: var(--destructive, #dc2626);
769
+ margin: 0;
770
+ }
771
+
772
+ .spk-editor-image-insert-divider {
773
+ display: flex;
774
+ align-items: center;
775
+ gap: 0.5rem;
776
+ color: var(--muted-foreground);
777
+ font-size: 0.75rem;
778
+ }
779
+
780
+ .spk-editor-image-insert-divider::before,
781
+ .spk-editor-image-insert-divider::after {
782
+ content: "";
783
+ flex: 1;
784
+ height: 1px;
785
+ background: var(--border);
786
+ }
787
+
788
+ .spk-editor-image-wrap {
789
+ position: relative;
790
+ display: block;
791
+ width: fit-content;
792
+ max-width: 100%;
793
+ margin: 0.5rem auto;
794
+ }
795
+
796
+ .spk-editor-image-wrap--left {
797
+ margin-left: 0;
798
+ margin-right: auto;
799
+ }
800
+
801
+ .spk-editor-image-wrap--right {
802
+ margin-left: auto;
803
+ margin-right: 0;
804
+ }
805
+
806
+ .spk-editor-image-wrap--selected {
807
+ outline: 2px solid color-mix(in oklab, var(--primary) 55%, transparent);
808
+ outline-offset: 2px;
809
+ border-radius: var(--radius-sm, 0.375rem);
810
+ }
811
+
812
+ .spk-editor-image-wrap .spk-editor-image {
813
+ margin: 0;
814
+ display: block;
815
+ }
816
+
817
+ .spk-editor-image-resize-handle {
818
+ position: absolute;
819
+ right: 0.15rem;
820
+ bottom: 0.15rem;
821
+ width: 0.85rem;
822
+ height: 0.85rem;
823
+ border-radius: 0.15rem;
824
+ background: var(--primary);
825
+ border: 2px solid var(--background);
826
+ cursor: nwse-resize;
827
+ touch-action: none;
828
+ }
829
+
830
+ .spk-editor-toolbar-popover-panel--portal {
831
+ position: fixed;
832
+ z-index: 60;
833
+ }
834
+
835
+ .spk-editor-ai-panel {
836
+ background: var(--spk-editor-overlay-bg, var(--background));
837
+ backdrop-filter: blur(var(--glass-menu-blur, var(--glass-blur, 12px)))
838
+ saturate(var(--glass-saturate, 190%));
839
+ border: 1px solid var(--glass-border, var(--border));
840
+ border-radius: 1rem;
841
+ box-shadow: var(--shadow-raised, var(--shadow-md));
842
+ overflow: hidden;
843
+ }
844
+
845
+ .spk-editor-ai-panel-title {
846
+ padding: 0.7rem 0.85rem 0.35rem;
847
+ font-size: 0.78rem;
848
+ font-weight: 600;
849
+ color: var(--muted-foreground);
850
+ }
851
+
852
+ .spk-editor-ai-panel-list {
853
+ list-style: none;
854
+ margin: 0;
855
+ padding: 0.35rem;
856
+ max-height: 18rem;
857
+ overflow-y: auto;
858
+ }
859
+
860
+ .spk-editor-ai-panel-item {
861
+ width: 100%;
862
+ display: flex;
863
+ align-items: center;
864
+ gap: 0.65rem;
865
+ border: 0;
866
+ background: transparent;
867
+ border-radius: 0.65rem;
868
+ padding: 0.55rem 0.65rem;
869
+ cursor: pointer;
870
+ text-align: left;
871
+ }
872
+
873
+ .spk-editor-ai-panel-item:hover:not(:disabled) {
874
+ background: color-mix(in oklab, var(--primary) 8%, transparent);
875
+ }
876
+
877
+ .spk-editor-ai-panel-item:disabled {
878
+ opacity: 0.45;
879
+ cursor: not-allowed;
880
+ }
881
+
882
+ .spk-editor-ai-panel-item-icon {
883
+ display: inline-flex;
884
+ color: var(--muted-foreground);
885
+ }
886
+
887
+ .spk-editor-ai-panel-item-label {
888
+ font-size: 0.875rem;
889
+ font-weight: 500;
890
+ color: var(--foreground);
891
+ }
892
+
893
+ .spk-editor-ai-panel-item-desc {
894
+ font-size: 0.75rem;
895
+ color: var(--muted-foreground);
896
+ }
897
+
898
+ .spk-editor-ai-dock {
899
+ position: relative;
900
+ width: 100%;
901
+ max-width: none;
902
+ }
903
+
904
+ .spk-editor-ai-dock-panel {
905
+ position: absolute;
906
+ left: 0;
907
+ right: 0;
908
+ bottom: calc(100% + 0.55rem);
909
+ max-width: 24rem;
910
+ }
911
+
912
+ .spk-editor-ai-dock-bar {
913
+ display: flex;
914
+ align-items: center;
915
+ gap: 0.45rem;
916
+ padding: 0.35rem 0.45rem;
917
+ border: 1px solid color-mix(in oklab, var(--primary) 28%, var(--border));
918
+ border-radius: var(--radius-pill, 999px);
919
+ background: var(--spk-editor-overlay-bg, var(--background));
920
+ backdrop-filter: blur(var(--glass-menu-blur, var(--glass-blur, 12px)))
921
+ saturate(var(--glass-saturate, 190%));
922
+ box-shadow: var(--shadow-raised, var(--shadow-md));
923
+ }
924
+
925
+ .spk-editor-ai-dock-trigger {
926
+ display: inline-flex;
927
+ align-items: center;
928
+ justify-content: center;
929
+ width: 2rem;
930
+ height: 2rem;
931
+ border: 0;
932
+ border-radius: var(--radius-pill, 999px);
933
+ background: color-mix(in oklab, var(--primary) 12%, transparent);
934
+ color: var(--primary);
935
+ cursor: pointer;
936
+ }
937
+
938
+ .spk-editor-ai-dock-trigger--active {
939
+ background: color-mix(in oklab, var(--primary) 22%, transparent);
940
+ }
941
+
942
+ .spk-editor-ai-dock-field {
943
+ flex: 1;
944
+ min-width: 0;
945
+ }
946
+
947
+ .spk-editor-ai-dock-input {
948
+ width: 100%;
949
+ border: 0;
950
+ background: transparent;
951
+ color: var(--foreground);
952
+ font-size: 0.875rem;
953
+ padding: 0.35rem 0;
954
+ }
955
+
956
+ .spk-editor-ai-dock-input:focus {
957
+ outline: none;
958
+ }
959
+
960
+ .spk-editor-ai-dock-input::placeholder {
961
+ color: var(--muted-foreground);
962
+ }
963
+
964
+ .spk-editor-ai-dock-submit {
965
+ display: inline-flex;
966
+ align-items: center;
967
+ justify-content: center;
968
+ width: 2rem;
969
+ height: 2rem;
970
+ border: 0;
971
+ border-radius: var(--radius-pill, 999px);
972
+ background: var(--primary);
973
+ color: var(--primary-foreground);
974
+ cursor: pointer;
975
+ }
976
+
977
+ .spk-editor-ai-dock-submit:disabled {
978
+ opacity: 0.45;
979
+ cursor: not-allowed;
980
+ }
981
+
982
+ .spk-editor-ai-menu {
983
+ position: relative;
984
+ display: inline-flex;
985
+ }
986
+
987
+ .spk-editor-ai-menu-shell {
988
+ position: absolute;
989
+ z-index: 30;
990
+ top: calc(100% + 0.35rem);
991
+ left: 0;
992
+ min-width: 18rem;
993
+ max-width: min(24rem, calc(100vw - 2rem));
994
+ border-radius: 1rem;
995
+ overflow: hidden;
996
+ box-shadow: var(--shadow-raised, var(--shadow-md));
997
+ }
998
+
999
+ .spk-editor-ai-menu-prompt {
1000
+ display: flex;
1001
+ align-items: center;
1002
+ gap: 0.35rem;
1003
+ padding: 0.55rem 0.65rem;
1004
+ border-top: 1px solid var(--border);
1005
+ background: color-mix(in oklab, var(--primary) 4%, transparent);
1006
+ }
1007
+
1008
+ .spk-editor-ai-menu-prompt-field {
1009
+ flex: 1;
1010
+ min-width: 0;
1011
+ }
1012
+
1013
+ .spk-editor-ai-menu-prompt-input {
1014
+ width: 100%;
1015
+ border: 1px solid color-mix(in oklab, var(--primary) 35%, var(--border));
1016
+ border-radius: var(--radius-pill, 999px);
1017
+ background: var(--background);
1018
+ color: var(--foreground);
1019
+ padding: 0.45rem 0.75rem;
1020
+ font-size: 0.875rem;
1021
+ }
1022
+
1023
+ .spk-editor-ai-menu-prompt-input:focus {
1024
+ outline: 2px solid color-mix(in oklab, var(--primary) 35%, transparent);
1025
+ outline-offset: 1px;
1026
+ }
1027
+
1028
+ .spk-editor-ai-menu-prompt-submit {
1029
+ display: inline-flex;
1030
+ align-items: center;
1031
+ justify-content: center;
1032
+ width: 2rem;
1033
+ height: 2rem;
1034
+ border: 0;
1035
+ border-radius: var(--radius-pill, 999px);
1036
+ background: var(--primary);
1037
+ color: var(--primary-foreground);
1038
+ cursor: pointer;
1039
+ }
1040
+
1041
+ .spk-editor-ai-menu-prompt-submit:disabled {
1042
+ opacity: 0.45;
1043
+ cursor: not-allowed;
1044
+ }
1045
+
1046
+ .spk-editor-shell .sr-only {
1047
+ position: absolute;
1048
+ width: 1px;
1049
+ height: 1px;
1050
+ padding: 0;
1051
+ margin: -1px;
1052
+ overflow: hidden;
1053
+ clip: rect(0, 0, 0, 0);
1054
+ white-space: nowrap;
1055
+ border: 0;
1056
+ }