cms-block-editor 1.0.12 → 1.0.14

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/README.md CHANGED
@@ -13,10 +13,12 @@ A powerful, feature-rich block editor for CMS applications built with Lexical an
13
13
  📐 **Layouts** - Flexbox and CSS Grid support with visual controls
14
14
  🖼️ **Images** - Upload, resize, drag-and-drop, and advanced editing with filters
15
15
  🎨 **Image Filters** - 7 adjustable filters with 6 professional presets
16
+ 🎬 **Videos** - Native HTML5 video upload with playback controls
16
17
  🎥 **Embeds** - YouTube, Facebook, Instagram, Twitter, TikTok, Vimeo, Spotify, SoundCloud
17
18
  🔗 **Links** - Custom link insertion with labels and options
18
19
  📊 **Tables** - Visual table builder with configurable rows/columns and professional styling
19
20
  🎨 **Styling** - Background colors, images, gradients, opacity controls
21
+ 🌈 **Themes** - 10 preset themes with light/dark mode and custom theme support
20
22
  📱 **Responsive** - Mobile-first design with automatic responsive behavior
21
23
  💾 **Export/Import** - HTML and Markdown support
22
24
  🎯 **Section Editor** - Full control over section layout, spacing, and styling
@@ -31,19 +33,21 @@ npm install cms-block-editor
31
33
  ## Quick Start
32
34
 
33
35
  ```tsx
34
- import { CMSBlockEditor } from 'cms-block-editor';
36
+ import { CMSBlockEditor, ThemeProvider } from 'cms-block-editor';
35
37
  import 'cms-block-editor/dist/index.css';
36
38
 
37
39
  function App() {
38
40
  const [content, setContent] = useState('');
39
41
 
40
42
  return (
41
- <CMSBlockEditor
42
- value={content}
43
- onChange={(editorState) => {
44
- setContent(JSON.stringify(editorState));
45
- }}
46
- />
43
+ <ThemeProvider defaultTheme="light" defaultMode="auto">
44
+ <CMSBlockEditor
45
+ value={content}
46
+ onChange={(editorState) => {
47
+ setContent(JSON.stringify(editorState));
48
+ }}
49
+ />
50
+ </ThemeProvider>
47
51
  );
48
52
  }
49
53
  ```
@@ -73,6 +77,7 @@ Main editor component with full editing capabilities.
73
77
  - `value?: string` - Initial editor state (JSON string)
74
78
  - `onChange?: (state: any) => void` - Callback fired when content changes
75
79
  - `onImageAdded?: (file: File) => Promise<string>` - Custom image upload handler that returns the image URL
80
+ - `onVideoAdded?: (file: File) => Promise<string>` - Custom video upload handler that returns the video URL
76
81
  - `useBase64Url?: boolean` - Use base64 encoding for images (default: `true`)
77
82
 
78
83
  ### CMSRenderer
@@ -97,6 +102,7 @@ Read-only renderer for displaying saved content.
97
102
  ### Media
98
103
  - **Images**: Upload from computer, resize with 8-point handles, drag-and-drop positioning, custom upload handler support, advanced editing with filters
99
104
  - **Image Filters**: Brightness, contrast, saturation, blur, grayscale, sepia, hue rotation with 6 presets
105
+ - **Videos**: Native HTML5 video upload, drag-and-drop, playback controls (autoplay, loop, mute), resize support
100
106
  - **YouTube**: Embed videos with custom sizing
101
107
  - **Embeds**: Support for 8+ platforms with automatic URL detection
102
108
  - **Tables**: Visual builder with configurable dimensions, header rows, and professional styling
@@ -134,6 +140,79 @@ Read-only renderer for displaying saved content.
134
140
 
135
141
  ## Advanced Usage
136
142
 
143
+ ### Theme System
144
+
145
+ Use preset themes or create custom ones:
146
+
147
+ ```typescript
148
+ import { CMSBlockEditor, ThemeProvider, ThemeSwitcher } from 'cms-block-editor';
149
+
150
+ function App() {
151
+ return (
152
+ <ThemeProvider defaultTheme="ocean" defaultMode="auto">
153
+ <div>
154
+ <ThemeSwitcher />
155
+ <CMSBlockEditor value={content} onChange={setContent} />
156
+ </div>
157
+ </ThemeProvider>
158
+ );
159
+ }
160
+ ```
161
+
162
+ **Available Themes**: light, dark, ocean, forest, sunset, rose, midnight, dracula, monokai, minimal
163
+
164
+ **Custom Theme**:
165
+ ```typescript
166
+ import { Theme, lightTheme } from 'cms-block-editor';
167
+
168
+ const myTheme: Theme = {
169
+ ...lightTheme,
170
+ name: 'my-theme',
171
+ colors: {
172
+ ...lightTheme.colors,
173
+ primary: '#ff6b6b',
174
+ primaryHover: '#ee5a52',
175
+ },
176
+ };
177
+
178
+ <ThemeProvider defaultTheme={myTheme}>
179
+ <CMSBlockEditor />
180
+ </ThemeProvider>
181
+ ```
182
+
183
+ ### Custom Video Upload
184
+
185
+ Upload videos to your server:
186
+
187
+ ```typescript
188
+ import { CMSBlockEditor } from 'cms-block-editor';
189
+
190
+ function Editor() {
191
+ const [content, setContent] = useState('');
192
+
193
+ const handleVideoUpload = async (file: File): Promise<string> => {
194
+ const formData = new FormData();
195
+ formData.append('video', file);
196
+
197
+ const response = await fetch('/api/upload-video', {
198
+ method: 'POST',
199
+ body: formData,
200
+ });
201
+
202
+ const data = await response.json();
203
+ return data.url;
204
+ };
205
+
206
+ return (
207
+ <CMSBlockEditor
208
+ value={content}
209
+ onChange={(state) => setContent(JSON.stringify(state))}
210
+ onVideoAdded={handleVideoUpload}
211
+ />
212
+ );
213
+ }
214
+ ```
215
+
137
216
  ### Custom Image Upload
138
217
 
139
218
  Upload images to your server instead of using base64 encoding:
@@ -293,6 +372,8 @@ Check out the [example app](./example-app) for a complete implementation with:
293
372
  ## Documentation
294
373
 
295
374
  Comprehensive guides available:
375
+ - [Theme System Guide](./docs/THEME-GUIDE.md) - Complete theming and customization
376
+ - [Video Upload Guide](./docs/VIDEO-GUIDE.md) - Native HTML5 video upload and playback
296
377
  - [Image Editing Guide](./docs/IMAGE-EDITING-GUIDE.md) - Advanced image filters and effects
297
378
  - [Section Creator Guide](./SECTION-CREATOR-GUIDE.md)
298
379
  - [Section Editing Guide](./SECTION-EDITING-GUIDE.md)
package/dist/index.css CHANGED
@@ -2522,6 +2522,39 @@
2522
2522
  grid-template-columns: repeat(2, 1fr);
2523
2523
  }
2524
2524
  }
2525
+ .video-node-wrapper {
2526
+ position: relative;
2527
+ display: inline-block;
2528
+ max-width: 100%;
2529
+ }
2530
+ .video-node-wrapper.selected {
2531
+ outline: 2px solid #667eea;
2532
+ outline-offset: 2px;
2533
+ }
2534
+ .video-node-wrapper video {
2535
+ display: block;
2536
+ width: 100%;
2537
+ height: auto;
2538
+ border-radius: 4px;
2539
+ background: #000;
2540
+ }
2541
+ .video-resize-handle {
2542
+ position: absolute;
2543
+ background: #667eea;
2544
+ border: 2px solid white;
2545
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
2546
+ z-index: 10;
2547
+ transition: all 0.2s;
2548
+ }
2549
+ .video-resize-handle:hover {
2550
+ background: #5568d3;
2551
+ transform: scale(1.2);
2552
+ }
2553
+ @media (max-width: 768px) {
2554
+ .video-node-wrapper {
2555
+ width: 100% !important;
2556
+ }
2557
+ }
2525
2558
 
2526
2559
  /* src/styles/renderer.css */
2527
2560
  .cms-renderer {
@@ -3170,4 +3203,322 @@
3170
3203
  background: #3a3a3a;
3171
3204
  }
3172
3205
  }
3206
+ .cms-renderer video {
3207
+ max-width: 100%;
3208
+ height: auto;
3209
+ border-radius: 4px;
3210
+ margin: 16px 0;
3211
+ }
3212
+ .cms-renderer .video-node-wrapper {
3213
+ display: block;
3214
+ max-width: 100%;
3215
+ margin: 16px 0;
3216
+ }
3217
+
3218
+ /* src/styles/themes.css */
3219
+ :root {
3220
+ --cms-color-primary: #667eea;
3221
+ --cms-color-primary-hover: #5568d3;
3222
+ --cms-color-primary-light: #e0e7ff;
3223
+ --cms-color-primary-dark: #4c51bf;
3224
+ --cms-color-secondary: #764ba2;
3225
+ --cms-color-secondary-hover: #6a3f8f;
3226
+ --cms-color-background: #ffffff;
3227
+ --cms-color-surface: #f9fafb;
3228
+ --cms-color-border: #e5e7eb;
3229
+ --cms-color-divider: #d1d5db;
3230
+ --cms-color-text-primary: #1f2937;
3231
+ --cms-color-text-secondary: #6b7280;
3232
+ --cms-color-text-disabled: #9ca3af;
3233
+ --cms-color-success: #10b981;
3234
+ --cms-color-warning: #f59e0b;
3235
+ --cms-color-error: #ef4444;
3236
+ --cms-color-info: #3b82f6;
3237
+ --cms-color-editor-background: #ffffff;
3238
+ --cms-color-editor-text: #1f2937;
3239
+ --cms-color-editor-placeholder: #9ca3af;
3240
+ --cms-color-toolbar-background: #f9fafb;
3241
+ --cms-color-toolbar-text: #374151;
3242
+ --cms-color-toolbar-border: #e5e7eb;
3243
+ --cms-color-selection: #dbeafe;
3244
+ --cms-color-highlight: #fef3c7;
3245
+ --cms-color-focus: #667eea;
3246
+ --cms-typography-font-family:
3247
+ -apple-system,
3248
+ BlinkMacSystemFont,
3249
+ "Segoe UI",
3250
+ Roboto,
3251
+ "Helvetica Neue",
3252
+ Arial,
3253
+ sans-serif;
3254
+ --cms-typography-font-family-mono:
3255
+ ui-monospace,
3256
+ SFMono-Regular,
3257
+ "SF Mono",
3258
+ Menlo,
3259
+ Consolas,
3260
+ "Liberation Mono",
3261
+ monospace;
3262
+ --cms-typography-font-size-xs: 0.75rem;
3263
+ --cms-typography-font-size-sm: 0.875rem;
3264
+ --cms-typography-font-size-md: 1rem;
3265
+ --cms-typography-font-size-lg: 1.125rem;
3266
+ --cms-typography-font-size-xl: 1.25rem;
3267
+ --cms-typography-font-weight-normal: 400;
3268
+ --cms-typography-font-weight-medium: 500;
3269
+ --cms-typography-font-weight-bold: 600;
3270
+ --cms-typography-line-height-tight: 1.25;
3271
+ --cms-typography-line-height-normal: 1.5;
3272
+ --cms-typography-line-height-relaxed: 1.75;
3273
+ --cms-spacing-xs: 0.25rem;
3274
+ --cms-spacing-sm: 0.5rem;
3275
+ --cms-spacing-md: 1rem;
3276
+ --cms-spacing-lg: 1.5rem;
3277
+ --cms-spacing-xl: 2rem;
3278
+ --cms-spacing-xxl: 3rem;
3279
+ --cms-radius-none: 0;
3280
+ --cms-radius-sm: 0.25rem;
3281
+ --cms-radius-md: 0.5rem;
3282
+ --cms-radius-lg: 0.75rem;
3283
+ --cms-radius-full: 9999px;
3284
+ --cms-shadow-none: none;
3285
+ --cms-shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
3286
+ --cms-shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
3287
+ --cms-shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
3288
+ --cms-shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
3289
+ }
3290
+ .cms-editor-shell {
3291
+ background: var(--cms-color-editor-background);
3292
+ color: var(--cms-color-editor-text);
3293
+ font-family: var(--cms-typography-font-family);
3294
+ border-radius: var(--cms-radius-md);
3295
+ box-shadow: var(--cms-shadow-md);
3296
+ }
3297
+ .cms-toolbar {
3298
+ background: var(--cms-color-toolbar-background);
3299
+ color: var(--cms-color-toolbar-text);
3300
+ border-bottom: 1px solid var(--cms-color-toolbar-border);
3301
+ }
3302
+ .cms-toolbar button {
3303
+ color: var(--cms-color-toolbar-text);
3304
+ border-radius: var(--cms-radius-sm);
3305
+ }
3306
+ .cms-toolbar button:hover {
3307
+ background: var(--cms-color-surface);
3308
+ }
3309
+ .cms-toolbar button.active {
3310
+ background: var(--cms-color-primary);
3311
+ color: white;
3312
+ }
3313
+ .cms-editor-content {
3314
+ color: var(--cms-color-editor-text);
3315
+ font-size: var(--cms-typography-font-size-md);
3316
+ line-height: var(--cms-typography-line-height-normal);
3317
+ }
3318
+ .cms-editor-placeholder {
3319
+ color: var(--cms-color-editor-placeholder);
3320
+ }
3321
+ .cms-btn-primary {
3322
+ background: var(--cms-color-primary);
3323
+ color: white;
3324
+ border-radius: var(--cms-radius-md);
3325
+ box-shadow: var(--cms-shadow-sm);
3326
+ }
3327
+ .cms-btn-primary:hover {
3328
+ background: var(--cms-color-primary-hover);
3329
+ }
3330
+ .cms-btn-secondary {
3331
+ background: var(--cms-color-surface);
3332
+ color: var(--cms-color-text-primary);
3333
+ border: 1px solid var(--cms-color-border);
3334
+ border-radius: var(--cms-radius-md);
3335
+ }
3336
+ .cms-btn-secondary:hover {
3337
+ background: var(--cms-color-background);
3338
+ }
3339
+ .cms-modal-overlay {
3340
+ background: rgba(0, 0, 0, 0.5);
3341
+ }
3342
+ .cms-modal-content {
3343
+ background: var(--cms-color-background);
3344
+ color: var(--cms-color-text-primary);
3345
+ border-radius: var(--cms-radius-lg);
3346
+ box-shadow: var(--cms-shadow-xl);
3347
+ }
3348
+ .cms-theme-switcher {
3349
+ display: flex;
3350
+ align-items: center;
3351
+ gap: var(--cms-spacing-sm);
3352
+ }
3353
+ .cms-theme-mode-toggle {
3354
+ padding: var(--cms-spacing-sm) var(--cms-spacing-md);
3355
+ background: var(--cms-color-surface);
3356
+ border: 1px solid var(--cms-color-border);
3357
+ border-radius: var(--cms-radius-md);
3358
+ cursor: pointer;
3359
+ font-size: var(--cms-typography-font-size-lg);
3360
+ transition: all 0.2s;
3361
+ }
3362
+ .cms-theme-mode-toggle:hover {
3363
+ background: var(--cms-color-background);
3364
+ transform: scale(1.05);
3365
+ }
3366
+ .cms-theme-selector {
3367
+ position: relative;
3368
+ }
3369
+ .cms-theme-selector-button {
3370
+ padding: var(--cms-spacing-sm) var(--cms-spacing-md);
3371
+ background: var(--cms-color-surface);
3372
+ border: 1px solid var(--cms-color-border);
3373
+ border-radius: var(--cms-radius-md);
3374
+ cursor: pointer;
3375
+ font-size: var(--cms-typography-font-size-sm);
3376
+ font-weight: var(--cms-typography-font-weight-medium);
3377
+ color: var(--cms-color-text-primary);
3378
+ transition: all 0.2s;
3379
+ display: flex;
3380
+ align-items: center;
3381
+ gap: var(--cms-spacing-sm);
3382
+ }
3383
+ .cms-theme-selector-button:hover {
3384
+ background: var(--cms-color-background);
3385
+ border-color: var(--cms-color-primary);
3386
+ }
3387
+ .cms-theme-selector-overlay {
3388
+ position: fixed;
3389
+ top: 0;
3390
+ left: 0;
3391
+ right: 0;
3392
+ bottom: 0;
3393
+ z-index: 999;
3394
+ }
3395
+ .cms-theme-selector-dropdown {
3396
+ position: absolute;
3397
+ top: calc(100% + var(--cms-spacing-sm));
3398
+ right: 0;
3399
+ background: var(--cms-color-background);
3400
+ border: 1px solid var(--cms-color-border);
3401
+ border-radius: var(--cms-radius-lg);
3402
+ box-shadow: var(--cms-shadow-xl);
3403
+ padding: var(--cms-spacing-md);
3404
+ min-width: 320px;
3405
+ max-width: 400px;
3406
+ z-index: 1000;
3407
+ }
3408
+ .cms-theme-selector-header {
3409
+ display: flex;
3410
+ justify-content: space-between;
3411
+ align-items: center;
3412
+ margin-bottom: var(--cms-spacing-md);
3413
+ padding-bottom: var(--cms-spacing-sm);
3414
+ border-bottom: 1px solid var(--cms-color-border);
3415
+ }
3416
+ .cms-theme-selector-header h3 {
3417
+ margin: 0;
3418
+ font-size: var(--cms-typography-font-size-md);
3419
+ font-weight: var(--cms-typography-font-weight-bold);
3420
+ color: var(--cms-color-text-primary);
3421
+ }
3422
+ .cms-theme-selector-header button {
3423
+ background: none;
3424
+ border: none;
3425
+ font-size: 24px;
3426
+ color: var(--cms-color-text-secondary);
3427
+ cursor: pointer;
3428
+ padding: 0;
3429
+ width: 24px;
3430
+ height: 24px;
3431
+ display: flex;
3432
+ align-items: center;
3433
+ justify-content: center;
3434
+ border-radius: var(--cms-radius-sm);
3435
+ }
3436
+ .cms-theme-selector-header button:hover {
3437
+ background: var(--cms-color-surface);
3438
+ color: var(--cms-color-text-primary);
3439
+ }
3440
+ .cms-theme-selector-grid {
3441
+ display: grid;
3442
+ grid-template-columns: repeat(2, 1fr);
3443
+ gap: var(--cms-spacing-sm);
3444
+ margin-bottom: var(--cms-spacing-md);
3445
+ }
3446
+ .cms-theme-option {
3447
+ display: flex;
3448
+ flex-direction: column;
3449
+ align-items: center;
3450
+ gap: var(--cms-spacing-sm);
3451
+ padding: var(--cms-spacing-md);
3452
+ background: var(--cms-color-surface);
3453
+ border: 2px solid var(--cms-color-border);
3454
+ border-radius: var(--cms-radius-md);
3455
+ cursor: pointer;
3456
+ transition: all 0.2s;
3457
+ position: relative;
3458
+ }
3459
+ .cms-theme-option:hover {
3460
+ border-color: var(--cms-color-primary);
3461
+ transform: translateY(-2px);
3462
+ box-shadow: var(--cms-shadow-md);
3463
+ }
3464
+ .cms-theme-option.active {
3465
+ border-color: var(--cms-color-primary);
3466
+ background: var(--cms-color-primary-light);
3467
+ }
3468
+ .cms-theme-preview {
3469
+ width: 100%;
3470
+ height: 40px;
3471
+ border-radius: var(--cms-radius-sm);
3472
+ border: 1px solid;
3473
+ position: relative;
3474
+ overflow: hidden;
3475
+ }
3476
+ .cms-theme-preview-accent {
3477
+ position: absolute;
3478
+ bottom: 0;
3479
+ left: 0;
3480
+ right: 0;
3481
+ height: 8px;
3482
+ }
3483
+ .cms-theme-name {
3484
+ font-size: var(--cms-typography-font-size-sm);
3485
+ font-weight: var(--cms-typography-font-weight-medium);
3486
+ color: var(--cms-color-text-primary);
3487
+ text-transform: capitalize;
3488
+ }
3489
+ .cms-theme-check {
3490
+ position: absolute;
3491
+ top: var(--cms-spacing-xs);
3492
+ right: var(--cms-spacing-xs);
3493
+ color: var(--cms-color-primary);
3494
+ font-weight: var(--cms-typography-font-weight-bold);
3495
+ }
3496
+ .cms-theme-selector-modes {
3497
+ display: flex;
3498
+ gap: var(--cms-spacing-md);
3499
+ padding-top: var(--cms-spacing-md);
3500
+ border-top: 1px solid var(--cms-color-border);
3501
+ }
3502
+ .cms-theme-selector-modes label {
3503
+ display: flex;
3504
+ align-items: center;
3505
+ gap: var(--cms-spacing-xs);
3506
+ font-size: var(--cms-typography-font-size-sm);
3507
+ color: var(--cms-color-text-primary);
3508
+ cursor: pointer;
3509
+ }
3510
+ .cms-theme-selector-modes input[type=radio] {
3511
+ cursor: pointer;
3512
+ accent-color: var(--cms-color-primary);
3513
+ }
3514
+ @media (max-width: 768px) {
3515
+ .cms-theme-selector-dropdown {
3516
+ right: auto;
3517
+ left: 0;
3518
+ min-width: 280px;
3519
+ }
3520
+ .cms-theme-selector-grid {
3521
+ grid-template-columns: 1fr;
3522
+ }
3523
+ }
3173
3524
  /*# sourceMappingURL=index.css.map */