@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.
- package/dist/RichText.svelte +82 -4
- package/dist/RichText.svelte.d.ts +2 -0
- package/dist/styles.css +59 -0
- package/package.json +1 -1
package/dist/RichText.svelte
CHANGED
|
@@ -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
|
-
|
|
322
|
-
|
|
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>
|
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%;
|