@commonpub/layer 0.7.2 → 0.7.4

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 (64) hide show
  1. package/components/CommentSection.vue +4 -4
  2. package/components/ContentAttachments.vue +4 -4
  3. package/components/DiscussionItem.vue +1 -1
  4. package/components/FeedItem.vue +1 -1
  5. package/components/MessageThread.vue +1 -1
  6. package/components/NotificationItem.vue +1 -1
  7. package/components/editors/ArticleEditor.vue +11 -12
  8. package/components/editors/BlogEditor.vue +17 -18
  9. package/components/editors/ExplainerEditor.vue +13 -14
  10. package/components/editors/ProjectEditor.vue +17 -18
  11. package/components/hub/HubHero.vue +2 -2
  12. package/components/hub/HubLayout.vue +1 -1
  13. package/components/hub/HubProducts.vue +2 -2
  14. package/components/hub/HubSidebarCard.vue +2 -2
  15. package/components/views/ArticleView.vue +15 -15
  16. package/components/views/BlogView.vue +14 -14
  17. package/components/views/ExplainerView.vue +11 -11
  18. package/components/views/ProjectView.vue +36 -36
  19. package/composables/useMarkdownImport.ts +1 -1
  20. package/package.json +9 -9
  21. package/pages/admin/theme.vue +1 -1
  22. package/pages/authorize_interaction.vue +1 -1
  23. package/pages/docs/[siteSlug]/edit.vue +4 -4
  24. package/pages/federated-hubs/[id]/index.vue +6 -6
  25. package/pages/federated-hubs/[id]/posts/[postId].vue +5 -5
  26. package/pages/hubs/[slug]/index.vue +6 -6
  27. package/pages/hubs/[slug]/posts/[postId].vue +6 -6
  28. package/pages/hubs/index.vue +2 -2
  29. package/pages/mirror/[id].vue +2 -2
  30. package/pages/u/[username]/[type]/[slug]/edit.vue +2 -1
  31. package/server/api/docs/[siteSlug]/search.get.ts +2 -1
  32. package/theme/components.css +2 -2
  33. package/theme/layouts.css +2 -2
  34. package/theme/prose.css +4 -4
  35. package/components/editors/BlockCanvas.vue +0 -487
  36. package/components/editors/BlockInsertZone.vue +0 -84
  37. package/components/editors/BlockPicker.vue +0 -285
  38. package/components/editors/BlockWrapper.vue +0 -192
  39. package/components/editors/EditorBlocks.vue +0 -248
  40. package/components/editors/EditorSection.vue +0 -81
  41. package/components/editors/EditorShell.vue +0 -196
  42. package/components/editors/EditorTagInput.vue +0 -114
  43. package/components/editors/EditorVisibility.vue +0 -110
  44. package/components/editors/blocks/BuildStepBlock.vue +0 -102
  45. package/components/editors/blocks/CalloutBlock.vue +0 -122
  46. package/components/editors/blocks/CheckpointBlock.vue +0 -27
  47. package/components/editors/blocks/CodeBlock.vue +0 -177
  48. package/components/editors/blocks/DividerBlock.vue +0 -22
  49. package/components/editors/blocks/DownloadsBlock.vue +0 -41
  50. package/components/editors/blocks/EmbedBlock.vue +0 -20
  51. package/components/editors/blocks/GalleryBlock.vue +0 -236
  52. package/components/editors/blocks/HeadingBlock.vue +0 -96
  53. package/components/editors/blocks/ImageBlock.vue +0 -271
  54. package/components/editors/blocks/MarkdownBlock.vue +0 -258
  55. package/components/editors/blocks/MathBlock.vue +0 -37
  56. package/components/editors/blocks/PartsListBlock.vue +0 -358
  57. package/components/editors/blocks/QuizBlock.vue +0 -47
  58. package/components/editors/blocks/QuoteBlock.vue +0 -101
  59. package/components/editors/blocks/SectionHeaderBlock.vue +0 -130
  60. package/components/editors/blocks/SliderBlock.vue +0 -318
  61. package/components/editors/blocks/TextBlock.vue +0 -201
  62. package/components/editors/blocks/ToolListBlock.vue +0 -70
  63. package/components/editors/blocks/VideoBlock.vue +0 -22
  64. package/composables/useBlockEditor.ts +0 -187
@@ -266,7 +266,7 @@ async function deleteComment(id: string): Promise<void> {
266
266
  color: var(--text-faint);
267
267
  background: var(--surface2);
268
268
  padding: 1px 6px;
269
- border: 1px solid var(--border2);
269
+ border: var(--border-width-default) solid var(--border2);
270
270
  }
271
271
 
272
272
  .cpub-comment-form {
@@ -290,7 +290,7 @@ async function deleteComment(id: string): Promise<void> {
290
290
  gap: 8px;
291
291
  padding: 6px 10px;
292
292
  background: var(--surface2);
293
- border: 1px solid var(--border);
293
+ border: var(--border-width-default) solid var(--border);
294
294
  }
295
295
 
296
296
  .cpub-cancel-reply {
@@ -313,7 +313,7 @@ async function deleteComment(id: string): Promise<void> {
313
313
  margin-bottom: 12px;
314
314
  padding: 8px 12px;
315
315
  background: var(--accent-bg);
316
- border: 1px solid var(--accent-border);
316
+ border: var(--border-width-default) solid var(--accent-border);
317
317
  border-radius: 8px;
318
318
  }
319
319
  .cpub-comment-fed-notice i { color: var(--accent); font-size: 11px; }
@@ -461,6 +461,6 @@ async function deleteComment(id: string): Promise<void> {
461
461
  margin-bottom: 12px;
462
462
  padding: 8px 12px;
463
463
  background: var(--green-bg, rgba(34, 197, 94, 0.08));
464
- border: 1px solid var(--green-border, rgba(34, 197, 94, 0.2));
464
+ border: var(--border-width-default) solid var(--green-border, rgba(34, 197, 94, 0.2));
465
465
  }
466
466
  </style>
@@ -57,7 +57,7 @@ const safeAttachments = computed(() =>
57
57
  .cpub-attachments {
58
58
  margin: 28px 0;
59
59
  padding-top: 16px;
60
- border-top: 1px solid var(--border);
60
+ border-top: var(--border-width-default) solid var(--border);
61
61
  }
62
62
  .cpub-attachments-label {
63
63
  font-size: 10px;
@@ -77,7 +77,7 @@ const safeAttachments = computed(() =>
77
77
  align-items: center;
78
78
  gap: 8px;
79
79
  padding: 8px 12px;
80
- border: 1px solid var(--border);
80
+ border: var(--border-width-default) solid var(--border);
81
81
  background: var(--surface);
82
82
  text-decoration: none;
83
83
  color: var(--text-dim);
@@ -92,7 +92,7 @@ const safeAttachments = computed(() =>
92
92
  width: 40px;
93
93
  height: 40px;
94
94
  object-fit: cover;
95
- border: 1px solid var(--border2);
95
+ border: var(--border-width-default) solid var(--border2);
96
96
  }
97
97
  .cpub-attachment-icon {
98
98
  width: 32px;
@@ -101,7 +101,7 @@ const safeAttachments = computed(() =>
101
101
  align-items: center;
102
102
  justify-content: center;
103
103
  background: var(--surface2);
104
- border: 1px solid var(--border2);
104
+ border: var(--border-width-default) solid var(--border2);
105
105
  color: var(--text-faint);
106
106
  font-size: 14px;
107
107
  }
@@ -177,7 +177,7 @@ const lastReplyFormatted = computed((): string | null => {
177
177
  width: 16px;
178
178
  height: 16px;
179
179
  object-fit: cover;
180
- border: 1px solid var(--border);
180
+ border: var(--border-width-default) solid var(--border);
181
181
  flex-shrink: 0;
182
182
  }
183
183
 
@@ -271,7 +271,7 @@ const formattedDate = computed((): string => {
271
271
 
272
272
  .cpub-feed-stat-btn {
273
273
  background: none;
274
- border: 1px solid transparent;
274
+ border: var(--border-width-default) solid transparent;
275
275
  cursor: pointer;
276
276
  padding: 2px 8px;
277
277
  border-radius: 4px;
@@ -116,7 +116,7 @@ function handleSend(): void {
116
116
  width: 20px;
117
117
  height: 20px;
118
118
  object-fit: cover;
119
- border: 1px solid var(--border);
119
+ border: var(--border-width-default) solid var(--border);
120
120
  flex-shrink: 0;
121
121
  }
122
122
 
@@ -103,7 +103,7 @@ const iconMap: Record<string, string> = {
103
103
  align-items: center;
104
104
  justify-content: center;
105
105
  background: var(--surface);
106
- border: 1px solid var(--border);
106
+ border: var(--border-width-default) solid var(--border);
107
107
  border-radius: 50%;
108
108
  font-size: 8px;
109
109
  color: var(--text-dim);
@@ -1,6 +1,5 @@
1
1
  <script setup lang="ts">
2
- import type { BlockEditor } from '../../composables/useBlockEditor';
3
- import type { BlockTypeGroup } from './BlockPicker.vue';
2
+ import { BlockCanvas, EditorBlocks, EditorSection, EditorTagInput, EditorVisibility, type BlockEditor, type BlockTypeGroup } from '@commonpub/editor/vue';
4
3
 
5
4
  const props = defineProps<{
6
5
  blockEditor: BlockEditor;
@@ -201,7 +200,7 @@ const canvasMaxWidth = computed(() => {
201
200
 
202
201
  <!-- Modules tab -->
203
202
  <div v-if="activeLeftTab === 'modules'" class="cpub-ae-left-body">
204
- <EditorsEditorBlocks :groups="blockTypes" :block-editor="blockEditor" />
203
+ <EditorBlocks :groups="blockTypes" :block-editor="blockEditor" />
205
204
  </div>
206
205
 
207
206
  <!-- Structure tab -->
@@ -267,7 +266,7 @@ const canvasMaxWidth = computed(() => {
267
266
  <!-- Scrollable canvas -->
268
267
  <div class="cpub-ae-canvas">
269
268
  <div class="cpub-ae-canvas-inner" :style="{ maxWidth: canvasMaxWidth }">
270
- <EditorsBlockCanvas :block-editor="blockEditor" :block-types="blockTypes" />
269
+ <BlockCanvas :block-editor="blockEditor" :block-types="blockTypes" />
271
270
  </div>
272
271
  </div>
273
272
 
@@ -297,7 +296,7 @@ const canvasMaxWidth = computed(() => {
297
296
  </div>
298
297
  <div class="cpub-ae-right-body">
299
298
  <!-- Content / Metadata -->
300
- <EditorsEditorSection title="Content" icon="fa-pen-nib" :open="openSections.content" @toggle="toggleSection('content')">
299
+ <EditorSection title="Content" icon="fa-pen-nib" :open="openSections.content" @toggle="toggleSection('content')">
301
300
  <div class="cpub-ep-field">
302
301
  <label class="cpub-ep-flabel">Slug</label>
303
302
  <input class="cpub-ep-input" type="text" :value="metadata.slug" placeholder="auto-generated" @input="updateMeta('slug', ($event.target as HTMLInputElement).value)">
@@ -331,22 +330,22 @@ const canvasMaxWidth = computed(() => {
331
330
  </div>
332
331
  </template>
333
332
  </div>
334
- </EditorsEditorSection>
333
+ </EditorSection>
335
334
 
336
335
  <!-- SEO -->
337
- <EditorsEditorSection title="SEO" icon="fa-magnifying-glass" :open="openSections.seo" @toggle="toggleSection('seo')">
336
+ <EditorSection title="SEO" icon="fa-magnifying-glass" :open="openSections.seo" @toggle="toggleSection('seo')">
338
337
  <div class="cpub-ep-field">
339
338
  <label class="cpub-ep-flabel">Meta Description</label>
340
339
  <textarea class="cpub-ep-textarea" rows="3" :value="metadata.seoDescription as string" placeholder="Search engine description..." @input="updateMeta('seoDescription', ($event.target as HTMLTextAreaElement).value)" />
341
340
  <span class="cpub-ep-hint">{{ ((metadata.seoDescription as string) || '').length }}/160</span>
342
341
  </div>
343
- </EditorsEditorSection>
342
+ </EditorSection>
344
343
 
345
344
  <!-- Publishing -->
346
- <EditorsEditorSection title="Publishing" icon="fa-rocket" :open="openSections.publishing" @toggle="toggleSection('publishing')">
345
+ <EditorSection title="Publishing" icon="fa-rocket" :open="openSections.publishing" @toggle="toggleSection('publishing')">
347
346
  <div class="cpub-ep-field">
348
347
  <label class="cpub-ep-flabel">Visibility</label>
349
- <EditorsEditorVisibility :model-value="visibility" @update:model-value="onVisibilityUpdate" />
348
+ <EditorVisibility :model-value="visibility" @update:model-value="onVisibilityUpdate" />
350
349
  </div>
351
350
  <div class="cpub-ep-field">
352
351
  <label class="cpub-ep-flabel">Category</label>
@@ -362,9 +361,9 @@ const canvasMaxWidth = computed(() => {
362
361
  </div>
363
362
  <div class="cpub-ep-field">
364
363
  <label class="cpub-ep-flabel">Tags</label>
365
- <EditorsEditorTagInput :tags="tags" @update:tags="onTagsUpdate" />
364
+ <EditorTagInput :tags="tags" @update:tags="onTagsUpdate" />
366
365
  </div>
367
- </EditorsEditorSection>
366
+ </EditorSection>
368
367
  </div>
369
368
  </aside>
370
369
  </div>
@@ -1,6 +1,5 @@
1
1
  <script setup lang="ts">
2
- import type { BlockEditor } from '../../composables/useBlockEditor';
3
- import type { BlockTypeGroup } from './BlockPicker.vue';
2
+ import { BlockCanvas, EditorBlocks, EditorSection, EditorTagInput, EditorVisibility, type BlockEditor, type BlockTypeGroup } from '@commonpub/editor/vue';
4
3
 
5
4
  const props = defineProps<{
6
5
  blockEditor: BlockEditor;
@@ -149,7 +148,7 @@ const canvasMaxWidth = computed(() => {
149
148
 
150
149
  <!-- LEFT: Block Library -->
151
150
  <aside class="cpub-be-library" :class="{ 'cpub-be-sidebar-open': mobileLeftOpen }" aria-label="Block library">
152
- <EditorsEditorBlocks :groups="blockTypes" :block-editor="blockEditor" />
151
+ <EditorBlocks :groups="blockTypes" :block-editor="blockEditor" />
153
152
  </aside>
154
153
 
155
154
  <!-- CENTER: Canvas with toolbar, cover, title, subtitle, byline, blocks -->
@@ -231,7 +230,7 @@ const canvasMaxWidth = computed(() => {
231
230
  </div>
232
231
 
233
232
  <!-- Block editor canvas -->
234
- <EditorsBlockCanvas :block-editor="blockEditor" :block-types="blockTypes" />
233
+ <BlockCanvas :block-editor="blockEditor" :block-types="blockTypes" />
235
234
  </div>
236
235
 
237
236
  <!-- Word count bar -->
@@ -247,7 +246,7 @@ const canvasMaxWidth = computed(() => {
247
246
  <aside class="cpub-be-right" :class="{ 'cpub-be-sidebar-open': mobileRightOpen }" aria-label="Blog properties">
248
247
  <div class="cpub-be-right-body">
249
248
  <!-- Meta -->
250
- <EditorsEditorSection title="Meta" icon="fa-tag" :open="openSections.meta" @toggle="toggleSection('meta')">
249
+ <EditorSection title="Meta" icon="fa-tag" :open="openSections.meta" @toggle="toggleSection('meta')">
251
250
  <div class="cpub-ep-field">
252
251
  <label class="cpub-ep-flabel">Slug</label>
253
252
  <input class="cpub-ep-input cpub-ep-input-mono" type="text" :value="metadata.slug" placeholder="auto-generated" @input="updateMeta('slug', ($event.target as HTMLInputElement).value)">
@@ -266,21 +265,21 @@ const canvasMaxWidth = computed(() => {
266
265
  </div>
267
266
  <div class="cpub-ep-field">
268
267
  <label class="cpub-ep-flabel">Tags</label>
269
- <EditorsEditorTagInput :tags="tags" @update:tags="onTagsUpdate" />
268
+ <EditorTagInput :tags="tags" @update:tags="onTagsUpdate" />
270
269
  </div>
271
- </EditorsEditorSection>
270
+ </EditorSection>
272
271
 
273
272
  <!-- Excerpt / Description -->
274
- <EditorsEditorSection title="Excerpt" icon="fa-align-left" :open="openSections.excerpt" @toggle="toggleSection('excerpt')">
273
+ <EditorSection title="Excerpt" icon="fa-align-left" :open="openSections.excerpt" @toggle="toggleSection('excerpt')">
275
274
  <div class="cpub-ep-field">
276
275
  <label class="cpub-ep-flabel">Custom Excerpt</label>
277
276
  <textarea class="cpub-ep-textarea" rows="3" :value="(metadata.description as string) || ''" placeholder="Short description shown in feed previews..." @input="updateMeta('description', ($event.target as HTMLTextAreaElement).value)" />
278
277
  <span class="cpub-ep-hint cpub-ep-hint-right">{{ ((metadata.description as string) || '').length }} / 300</span>
279
278
  </div>
280
- </EditorsEditorSection>
279
+ </EditorSection>
281
280
 
282
281
  <!-- SEO Preview -->
283
- <EditorsEditorSection title="SEO Preview" icon="fa-brands fa-google" :open="openSections.seo" @toggle="toggleSection('seo')">
282
+ <EditorSection title="SEO Preview" icon="fa-brands fa-google" :open="openSections.seo" @toggle="toggleSection('seo')">
284
283
  <div class="cpub-be-seo-card">
285
284
  <div class="cpub-be-seo-url">
286
285
  <span class="cpub-be-seo-favicon">C</span>
@@ -294,13 +293,13 @@ const canvasMaxWidth = computed(() => {
294
293
  <textarea class="cpub-ep-textarea" rows="3" :value="(metadata.seoDescription as string) || ''" placeholder="Search engine description..." @input="updateMeta('seoDescription', ($event.target as HTMLTextAreaElement).value)" />
295
294
  <span class="cpub-ep-hint cpub-ep-hint-right">{{ ((metadata.seoDescription as string) || '').length }}/160</span>
296
295
  </div>
297
- </EditorsEditorSection>
296
+ </EditorSection>
298
297
 
299
298
  <!-- Publishing -->
300
- <EditorsEditorSection title="Publishing" icon="fa-globe" :open="openSections.publishing" @toggle="toggleSection('publishing')">
299
+ <EditorSection title="Publishing" icon="fa-globe" :open="openSections.publishing" @toggle="toggleSection('publishing')">
301
300
  <div class="cpub-ep-field">
302
301
  <label class="cpub-ep-flabel">Visibility</label>
303
- <EditorsEditorVisibility :model-value="(metadata.visibility as string) || 'public'" @update:model-value="(v: string) => updateMeta('visibility', v)" />
302
+ <EditorVisibility :model-value="(metadata.visibility as string) || 'public'" @update:model-value="(v: string) => updateMeta('visibility', v)" />
304
303
  </div>
305
304
  <div class="cpub-ep-field">
306
305
  <label class="cpub-be-schedule-row">
@@ -319,10 +318,10 @@ const canvasMaxWidth = computed(() => {
319
318
  <label class="cpub-ep-flabel">Series <span class="cpub-ep-optional">(optional)</span></label>
320
319
  <input class="cpub-ep-input" type="text" :value="metadata.series" placeholder="e.g. Home Lab Chronicles" @input="updateMeta('series', ($event.target as HTMLInputElement).value)">
321
320
  </div>
322
- </EditorsEditorSection>
321
+ </EditorSection>
323
322
 
324
323
  <!-- Author -->
325
- <EditorsEditorSection title="Author" icon="fa-user" :open="openSections.author" @toggle="toggleSection('author')">
324
+ <EditorSection title="Author" icon="fa-user" :open="openSections.author" @toggle="toggleSection('author')">
326
325
  <div class="cpub-be-author-row">
327
326
  <div class="cpub-be-author-av">{{ authorInitials }}</div>
328
327
  <div class="cpub-be-author-info">
@@ -331,10 +330,10 @@ const canvasMaxWidth = computed(() => {
331
330
  </div>
332
331
  <span class="cpub-be-author-badge">You</span>
333
332
  </div>
334
- </EditorsEditorSection>
333
+ </EditorSection>
335
334
 
336
335
  <!-- Social -->
337
- <EditorsEditorSection title="Social" icon="fa-share-nodes" :open="openSections.social" @toggle="toggleSection('social')">
336
+ <EditorSection title="Social" icon="fa-share-nodes" :open="openSections.social" @toggle="toggleSection('social')">
338
337
  <div class="cpub-ep-field">
339
338
  <label class="cpub-ep-flabel">Open Graph Image</label>
340
339
  <div class="cpub-be-og-thumb">
@@ -344,7 +343,7 @@ const canvasMaxWidth = computed(() => {
344
343
  </div>
345
344
  </div>
346
345
  </div>
347
- </EditorsEditorSection>
346
+ </EditorSection>
348
347
  </div>
349
348
  </aside>
350
349
  </div>
@@ -1,6 +1,5 @@
1
1
  <script setup lang="ts">
2
- import type { BlockEditor } from '../../composables/useBlockEditor';
3
- import type { BlockTypeGroup } from './BlockPicker.vue';
2
+ import { BlockCanvas, EditorBlocks, EditorSection, EditorTagInput, EditorVisibility, type BlockEditor, type BlockTypeGroup } from '@commonpub/editor/vue';
4
3
 
5
4
  const props = defineProps<{
6
5
  blockEditor: BlockEditor;
@@ -203,7 +202,7 @@ const blockCount = computed(() => props.blockEditor.blocks.value.length);
203
202
  </div>
204
203
 
205
204
  <div v-if="activeLeftTab === 'modules'" class="cpub-ee-left-body">
206
- <EditorsEditorBlocks :groups="blockTypes" :block-editor="blockEditor" />
205
+ <EditorBlocks :groups="blockTypes" :block-editor="blockEditor" />
207
206
  </div>
208
207
 
209
208
  <div v-else-if="activeLeftTab === 'structure'" class="cpub-ee-left-body" style="padding: 10px;">
@@ -299,7 +298,7 @@ const blockCount = computed(() => props.blockEditor.blocks.value.length);
299
298
 
300
299
  <div class="cpub-ee-canvas">
301
300
  <div class="cpub-ee-canvas-inner" :style="{ maxWidth: canvasMaxWidth }">
302
- <EditorsBlockCanvas :block-editor="blockEditor" :block-types="blockTypes" />
301
+ <BlockCanvas :block-editor="blockEditor" :block-types="blockTypes" />
303
302
  </div>
304
303
  </div>
305
304
 
@@ -318,7 +317,7 @@ const blockCount = computed(() => props.blockEditor.blocks.value.length);
318
317
  <!-- RIGHT: Properties -->
319
318
  <aside class="cpub-ee-right" :class="{ 'cpub-ee-sidebar-open': mobileRightOpen }" aria-label="Explainer properties">
320
319
  <div class="cpub-ee-right-body">
321
- <EditorsEditorSection title="Content" icon="fa-sliders" :open="openSections.section" @toggle="toggleSection('section')">
320
+ <EditorSection title="Content" icon="fa-sliders" :open="openSections.section" @toggle="toggleSection('section')">
322
321
  <div class="cpub-ep-field">
323
322
  <label class="cpub-ep-flabel">Slug</label>
324
323
  <input class="cpub-ep-input" type="text" :value="metadata.slug" placeholder="auto-generated" @input="updateMeta('slug', ($event.target as HTMLInputElement).value)">
@@ -333,27 +332,27 @@ const blockCount = computed(() => props.blockEditor.blocks.value.length);
333
332
  </div>
334
333
  <div class="cpub-ep-field">
335
334
  <label class="cpub-ep-flabel">Tags</label>
336
- <EditorsEditorTagInput :tags="tags" @update:tags="onTagsUpdate" />
335
+ <EditorTagInput :tags="tags" @update:tags="onTagsUpdate" />
337
336
  </div>
338
- </EditorsEditorSection>
337
+ </EditorSection>
339
338
 
340
- <EditorsEditorSection title="Difficulty" icon="fa-gauge-high" :open="openSections.difficulty" @toggle="toggleSection('difficulty')">
339
+ <EditorSection title="Difficulty" icon="fa-gauge-high" :open="openSections.difficulty" @toggle="toggleSection('difficulty')">
341
340
  <select class="cpub-ep-select" :value="metadata.difficulty || 'beginner'" @change="updateMeta('difficulty', ($event.target as HTMLSelectElement).value)">
342
341
  <option value="beginner">Beginner</option>
343
342
  <option value="intermediate">Intermediate</option>
344
343
  <option value="advanced">Advanced</option>
345
344
  </select>
346
- </EditorsEditorSection>
345
+ </EditorSection>
347
346
 
348
- <EditorsEditorSection title="Visibility" icon="fa-eye" :open="openSections.visibility" @toggle="toggleSection('visibility')">
349
- <EditorsEditorVisibility :model-value="visibility" @update:model-value="onVisibilityUpdate" />
350
- </EditorsEditorSection>
347
+ <EditorSection title="Visibility" icon="fa-eye" :open="openSections.visibility" @toggle="toggleSection('visibility')">
348
+ <EditorVisibility :model-value="visibility" @update:model-value="onVisibilityUpdate" />
349
+ </EditorSection>
351
350
 
352
- <EditorsEditorSection title="Cover Image" icon="fa-image" :open="openSections.cover" @toggle="toggleSection('cover')">
351
+ <EditorSection title="Cover Image" icon="fa-image" :open="openSections.cover" @toggle="toggleSection('cover')">
353
352
  <div class="cpub-ep-field">
354
353
  <input class="cpub-ep-input" type="url" :value="metadata.coverImageUrl" placeholder="https://..." @input="updateMeta('coverImageUrl', ($event.target as HTMLInputElement).value)">
355
354
  </div>
356
- </EditorsEditorSection>
355
+ </EditorSection>
357
356
  </div>
358
357
  </aside>
359
358
  </div>
@@ -1,6 +1,5 @@
1
1
  <script setup lang="ts">
2
- import type { BlockEditor } from '../../composables/useBlockEditor';
3
- import type { BlockTypeGroup } from './BlockPicker.vue';
2
+ import { BlockCanvas, EditorBlocks, EditorSection, EditorTagInput, EditorVisibility, type BlockEditor, type BlockTypeGroup } from '@commonpub/editor/vue';
4
3
 
5
4
  const props = defineProps<{
6
5
  blockEditor: BlockEditor;
@@ -151,7 +150,7 @@ const blockCount = computed(() => props.blockEditor.blocks.value.length);
151
150
 
152
151
  <!-- LEFT: Block Library -->
153
152
  <aside class="cpub-pe-library" :class="{ 'cpub-pe-sidebar-open': mobileLeftOpen }" aria-label="Block library">
154
- <EditorsEditorBlocks :groups="blockTypes" :block-editor="blockEditor" />
153
+ <EditorBlocks :groups="blockTypes" :block-editor="blockEditor" />
155
154
  </aside>
156
155
 
157
156
  <!-- CENTER: Canvas with toolbar -->
@@ -202,7 +201,7 @@ const blockCount = computed(() => props.blockEditor.blocks.value.length);
202
201
  placeholder="Project title..."
203
202
  />
204
203
 
205
- <EditorsBlockCanvas :block-editor="blockEditor" :block-types="blockTypes" />
204
+ <BlockCanvas :block-editor="blockEditor" :block-types="blockTypes" />
206
205
  </div>
207
206
  </div>
208
207
 
@@ -217,7 +216,7 @@ const blockCount = computed(() => props.blockEditor.blocks.value.length);
217
216
  <!-- RIGHT: Settings Panel -->
218
217
  <aside class="cpub-pe-settings" :class="{ 'cpub-pe-sidebar-open': mobileRightOpen }" aria-label="Project settings">
219
218
  <div class="cpub-pe-settings-body">
220
- <EditorsEditorSection title="Project Meta" icon="fa-sliders" :open="openSections.meta" @toggle="toggleSection('meta')">
219
+ <EditorSection title="Project Meta" icon="fa-sliders" :open="openSections.meta" @toggle="toggleSection('meta')">
221
220
  <div class="cpub-ep-field">
222
221
  <label class="cpub-ep-flabel">Slug</label>
223
222
  <input class="cpub-ep-input" type="text" :value="metadata.slug" placeholder="project-url-slug" @input="updateMeta('slug', ($event.target as HTMLInputElement).value)">
@@ -246,17 +245,17 @@ const blockCount = computed(() => props.blockEditor.blocks.value.length);
246
245
  <label class="cpub-ep-flabel">Description</label>
247
246
  <textarea class="cpub-ep-textarea" rows="3" :value="metadata.description as string" placeholder="Brief project description..." @input="updateMeta('description', ($event.target as HTMLTextAreaElement).value)" />
248
247
  </div>
249
- </EditorsEditorSection>
248
+ </EditorSection>
250
249
 
251
- <EditorsEditorSection title="Tags" icon="fa-tag" :open="openSections.tags" @toggle="toggleSection('tags')">
252
- <EditorsEditorTagInput :tags="tags" @update:tags="onTagsUpdate" />
253
- </EditorsEditorSection>
250
+ <EditorSection title="Tags" icon="fa-tag" :open="openSections.tags" @toggle="toggleSection('tags')">
251
+ <EditorTagInput :tags="tags" @update:tags="onTagsUpdate" />
252
+ </EditorSection>
254
253
 
255
- <EditorsEditorSection title="Visibility" icon="fa-eye" :open="openSections.visibility" @toggle="toggleSection('visibility')">
256
- <EditorsEditorVisibility :model-value="visibility" @update:model-value="onVisibilityUpdate" />
257
- </EditorsEditorSection>
254
+ <EditorSection title="Visibility" icon="fa-eye" :open="openSections.visibility" @toggle="toggleSection('visibility')">
255
+ <EditorVisibility :model-value="visibility" @update:model-value="onVisibilityUpdate" />
256
+ </EditorSection>
258
257
 
259
- <EditorsEditorSection title="Cover Image" icon="fa-image" :open="openSections.cover" @toggle="toggleSection('cover')">
258
+ <EditorSection title="Cover Image" icon="fa-image" :open="openSections.cover" @toggle="toggleSection('cover')">
260
259
  <div class="cpub-pe-cover" :class="{ 'has-image': !!coverImageUrl }">
261
260
  <template v-if="coverImageUrl">
262
261
  <img :src="coverImageUrl" alt="Cover image" class="cpub-pe-cover-img" />
@@ -282,17 +281,17 @@ const blockCount = computed(() => props.blockEditor.blocks.value.length);
282
281
  </div>
283
282
  </template>
284
283
  </div>
285
- </EditorsEditorSection>
284
+ </EditorSection>
286
285
 
287
- <EditorsEditorSection title="SEO" icon="fa-magnifying-glass" :open="openSections.seo" @toggle="toggleSection('seo')">
286
+ <EditorSection title="SEO" icon="fa-magnifying-glass" :open="openSections.seo" @toggle="toggleSection('seo')">
288
287
  <div class="cpub-pe-field">
289
288
  <label class="cpub-pe-flabel">Meta Description</label>
290
289
  <textarea class="cpub-pe-textarea" rows="3" :value="metadata.seoDescription as string" placeholder="Search engine description (recommended 50-160 chars)" @input="updateMeta('seoDescription', ($event.target as HTMLTextAreaElement).value)" />
291
290
  <span class="cpub-pe-hint">{{ ((metadata.seoDescription as string) || '').length }}/160</span>
292
291
  </div>
293
- </EditorsEditorSection>
292
+ </EditorSection>
294
293
 
295
- <EditorsEditorSection title="Checklist" icon="fa-circle-check" :open="openSections.checklist" @toggle="toggleSection('checklist')">
294
+ <EditorSection title="Checklist" icon="fa-circle-check" :open="openSections.checklist" @toggle="toggleSection('checklist')">
296
295
  <div class="cpub-pe-checklist">
297
296
  <div v-for="item in checklist" :key="item.label" class="cpub-pe-check-item" :class="{ pass: item.pass }">
298
297
  <i :class="item.pass ? 'fa-regular fa-square-check' : 'fa-regular fa-square'" :style="{ color: item.pass ? 'var(--green)' : 'var(--text-faint)' }"></i>
@@ -302,7 +301,7 @@ const blockCount = computed(() => props.blockEditor.blocks.value.length);
302
301
  <div class="cpub-pe-checklist-summary">
303
302
  {{ checklistDone }}/{{ checklist.length }} complete
304
303
  </div>
305
- </EditorsEditorSection>
304
+ </EditorSection>
306
305
  </div>
307
306
  </aside>
308
307
  </div>
@@ -66,7 +66,7 @@ const isCompanyHub = computed(() => hubType.value === 'company');
66
66
  background: linear-gradient(135deg, var(--accent) 0%, #006b6b 50%, var(--accent-border) 100%);
67
67
  position: relative;
68
68
  overflow: hidden;
69
- border-bottom: 1px solid var(--border);
69
+ border-bottom: var(--border-width-default) solid var(--border);
70
70
  }
71
71
 
72
72
  .cpub-hub-banner-pattern {
@@ -87,7 +87,7 @@ const isCompanyHub = computed(() => hubType.value === 'company');
87
87
 
88
88
  .cpub-hub-meta-bar {
89
89
  background: var(--surface);
90
- border-bottom: 1px solid var(--border);
90
+ border-bottom: var(--border-width-default) solid var(--border);
91
91
  padding: 20px 0;
92
92
  }
93
93
 
@@ -45,7 +45,7 @@ const activeTab = defineModel<string>('activeTab', { required: true });
45
45
  <style scoped>
46
46
  .cpub-hub-tabs {
47
47
  background: var(--surface);
48
- border-bottom: 1px solid var(--border);
48
+ border-bottom: var(--border-width-default) solid var(--border);
49
49
  position: sticky;
50
50
  top: 48px;
51
51
  z-index: 90;
@@ -36,7 +36,7 @@ defineProps<{
36
36
 
37
37
  .cpub-product-card {
38
38
  background: var(--surface);
39
- border: 1px solid var(--border);
39
+ border: var(--border-width-default) solid var(--border);
40
40
  border-radius: 12px;
41
41
  padding: 16px;
42
42
  display: flex;
@@ -55,7 +55,7 @@ defineProps<{
55
55
  width: 48px;
56
56
  height: 48px;
57
57
  background: var(--surface2);
58
- border: 1px solid var(--border);
58
+ border: var(--border-width-default) solid var(--border);
59
59
  border-radius: 10px;
60
60
  display: flex;
61
61
  align-items: center;
@@ -14,7 +14,7 @@ defineProps<{
14
14
  <style scoped>
15
15
  .cpub-sb-card {
16
16
  background: var(--surface);
17
- border: 1px solid var(--border);
17
+ border: var(--border-width-default) solid var(--border);
18
18
  padding: 18px;
19
19
  box-shadow: var(--shadow-sm);
20
20
  margin-bottom: 16px;
@@ -30,6 +30,6 @@ defineProps<{
30
30
  color: var(--text-dim);
31
31
  margin-bottom: 14px;
32
32
  padding-bottom: 8px;
33
- border-bottom: 1px solid var(--border);
33
+ border-bottom: var(--border-width-default) solid var(--border);
34
34
  }
35
35
  </style>