@flexiui/svelte-rich-text 0.0.58 → 0.0.60

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.
@@ -27,6 +27,8 @@
27
27
  className?: string;
28
28
  editable?: boolean;
29
29
  content?: string | {type: string, content: any[]} | null;
30
+ nodesLimit?: number;
31
+ limitWarningMessage?: string;
30
32
  customExtensions?: any[];
31
33
  editorEvents?: {
32
34
  onTransaction?: (params: any) => void;
@@ -70,6 +72,8 @@
70
72
  className,
71
73
  editable,
72
74
  content,
75
+ nodesLimit,
76
+ limitWarningMessage,
73
77
  customExtensions = [],
74
78
  editorEvents = {
75
79
  onTransaction: () => {},
@@ -172,6 +176,8 @@
172
176
  let enterPressed = $state(false);
173
177
  let fontSize = $state(16) as number;
174
178
  let lineHeight = $state(null) as number;
179
+ let currentNodeCount = $state(0);
180
+ let showLimitWarning = $state(false);
175
181
 
176
182
  const TEXT_COLOR_PALETTE = [
177
183
  editorConfig.editorAccentColor,
@@ -253,6 +259,25 @@
253
259
  const isCellSelection = () =>
254
260
  $editor && $editor.state.selection instanceof CellSelection;
255
261
 
262
+ // función para contar nodos en el documento
263
+ function countNodes(doc: any): number {
264
+ // Solo contar los nodos de primer nivel (hijos directos del doc)
265
+ console.log(doc);
266
+ if (doc.type === 'doc' && doc.content) {
267
+ return doc.content.length;
268
+ }
269
+ return 0;
270
+ }
271
+
272
+ // función para actualizar el contador de nodos
273
+ function updateNodeCount() {
274
+ if ($editor) {
275
+
276
+ currentNodeCount = countNodes($editor.getJSON());
277
+
278
+ }
279
+ }
280
+
256
281
  onMount(() => {
257
282
  editor = createEditor({
258
283
  extensions,
@@ -263,8 +288,27 @@
263
288
  },
264
289
  handleKeyDown: (view, event) => {
265
290
  if (event.key === "Enter" && !event.ctrlKey) {
291
+ // Verificar si hay límite de nodos y si se ha alcanzado
266
292
  enterPressed = true;
267
293
 
294
+ if (nodesLimit) {
295
+ const currentCount = currentNodeCount;
296
+ if (currentCount >= nodesLimit) {
297
+
298
+ if(!showLimitWarning){
299
+ showLimitWarning = true;
300
+ setTimeout(() => {
301
+ showLimitWarning = false;
302
+ }, 3000);
303
+ }
304
+
305
+ event.preventDefault();
306
+ event.stopPropagation();
307
+ return true;
308
+
309
+ }
310
+ }
311
+
268
312
  setTimeout(() => {
269
313
  enterPressed = false;
270
314
  const { from } = view.state.selection;
@@ -318,14 +362,18 @@
318
362
  },
319
363
  },
320
364
  onTransaction: ({ editor, transaction }) => {
321
- editorEvents.onTransaction({ editor, transaction });
322
- editor = editor;
365
+
366
+ // Actualizar contador de nodos
367
+
368
+ updateNodeCount();
323
369
 
324
370
  if (enterPressed) {
325
- // console.log("Enter pressed");
326
371
  return;
327
372
  }
328
373
 
374
+ editorEvents.onTransaction({ editor, transaction });
375
+ editor = editor;
376
+
329
377
  const { from } = editor.state.selection;
330
378
 
331
379
  // Obtener el elemento DOM
@@ -377,6 +425,8 @@
377
425
  onCreate: ({ editor }) => {
378
426
  editorEvents.onCreate({ editor });
379
427
  migrateMathStrings(editor);
428
+
429
+ updateNodeCount();
380
430
  },
381
431
 
382
432
  onUpdate: ({ editor }) => {
@@ -1510,6 +1560,29 @@
1510
1560
  {/if}
1511
1561
 
1512
1562
  <EditorContent editor={$editor} class="fl-rich-text-content" />
1563
+
1564
+ <!-- Warning message for node limit -->
1565
+ {#if showLimitWarning && nodesLimit}
1566
+ <div class="fl-node-limit-warning">
1567
+ {limitWarningMessage || ` No se pueden añadir más elementos a este editor. Max: ${nodesLimit} elementos.`}
1568
+ </div>
1569
+ {/if}
1570
+
1571
+ <!-- Bottom bar showing node count -->
1572
+ {#if nodesLimit}
1573
+ <div class="fl-node-count-bar">
1574
+ <span class="fl-node-count-text">
1575
+ {currentNodeCount} de {nodesLimit} elementos
1576
+ </span>
1577
+ <div class="fl-node-count-progress">
1578
+ <div
1579
+ class="fl-node-count-progress-bar"
1580
+ style="width: {Math.min((currentNodeCount / nodesLimit) * 100, 100)}%"
1581
+ ></div>
1582
+ </div>
1583
+ </div>
1584
+ {/if}
1585
+
1513
1586
  </div>
1514
1587
 
1515
1588
  <div
@@ -2793,9 +2866,14 @@
2793
2866
  </div>
2794
2867
  {/if}
2795
2868
 
2796
-
2797
2869
  <style>
2798
2870
  .hidden {
2799
2871
  display: none;
2800
2872
  }
2873
+
2874
+ .fl-node-count-text {
2875
+ strong {
2876
+ margin-right: 4px;
2877
+ }
2878
+ }
2801
2879
  </style>
@@ -9,6 +9,8 @@ export interface Props {
9
9
  type: string;
10
10
  content: any[];
11
11
  } | null;
12
+ nodesLimit?: number;
13
+ limitWarningMessage?: string;
12
14
  customExtensions?: any[];
13
15
  editorEvents?: {
14
16
  onTransaction?: (params: any) => void;
package/dist/styles.css CHANGED
@@ -92,6 +92,7 @@
92
92
  background-color: var(--fl-editor-bg, #242424);
93
93
  box-sizing: border-box;
94
94
  border-radius: var(--fl-editor-radius);
95
+ position: relative;
95
96
 
96
97
  .fl-editor-image-url-input {
97
98
  white-space: nowrap;
@@ -490,6 +491,64 @@ button {
490
491
  }
491
492
  }
492
493
 
494
+ /* Node limit styles */
495
+ .fl-node-limit-warning {
496
+ position: absolute;
497
+ bottom: 48px;
498
+ left: 50%;
499
+ transform: translateX(-50%);
500
+ background: #ff4444;
501
+ color: white;
502
+ padding: 4px 12px;
503
+ border-radius: 8px;
504
+ font-size: 14px;
505
+ font-weight: 500;
506
+ animation: slideInTop 0.3s ease-out;
507
+ }
508
+
509
+ @keyframes slideInTop {
510
+ from {
511
+ transform: translateX(-50%) translateY(15px);
512
+ opacity: 0;
513
+ }
514
+ to {
515
+ transform: translateX(-50%) translateY(0);
516
+ opacity: 1;
517
+ }
518
+ }
519
+
520
+ .fl-node-count-bar {
521
+ background: var(--fl-toolbar-bg, #242424);
522
+ border-top: 1px solid #333;
523
+ padding: 8px 16px;
524
+ display: flex;
525
+ align-items: center;
526
+ gap: 12px;
527
+ font-size: 12px;
528
+ color: var(--fl-toolbar-text-color, currentColor);
529
+ }
530
+
531
+ .fl-node-count-text {
532
+ font-weight: 500;
533
+ min-width: fit-content;
534
+ }
535
+
536
+ .fl-node-count-progress {
537
+ flex: 1;
538
+ height: 4px;
539
+ background: rgba(255, 255, 255, 0.1);
540
+ border-radius: 2px;
541
+ overflow: hidden;
542
+ }
543
+
544
+ .fl-node-count-progress-bar {
545
+ height: 100%;
546
+ background: var(--fl-editor-accent-color, #535bf2);
547
+ transition: width 0.2s ease;
548
+ border-radius: 2px;
549
+ }
550
+
551
+
493
552
  .media-grid-item-view-content > div {
494
553
  display: flex;
495
554
  height: 100%;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flexiui/svelte-rich-text",
3
- "version": "0.0.58",
3
+ "version": "0.0.60",
4
4
  "description": "A lightweight and flexible rich text editor component for Svelte",
5
5
  "keywords": [
6
6
  "svelte",