@flexiui/svelte-rich-text 0.0.33 → 0.0.34
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
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import { TableKit } from "@tiptap/extension-table";
|
|
5
5
|
import { CellSelection } from "prosemirror-tables";
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
import { NodeLineHeight } from "./extensions/NodeLineHeight";
|
|
8
8
|
import { MediaGridExtension } from "./extensions/MediaGrid/MediaGrid";
|
|
9
9
|
import { MediaGridItemExtension } from "./extensions/MediaGrid/MediaGridItem";
|
|
10
10
|
import {
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
docMarginInline?: string;
|
|
65
65
|
docMarginBlock?: string;
|
|
66
66
|
docRadius?: string;
|
|
67
|
-
}
|
|
67
|
+
};
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
let {
|
|
@@ -92,24 +92,24 @@
|
|
|
92
92
|
|
|
93
93
|
let editor = $state() as Readable<Editor>;
|
|
94
94
|
const defaultEditorConfig = {
|
|
95
|
-
editorBgColor:
|
|
96
|
-
editorRadius:
|
|
95
|
+
editorBgColor: "transparent",
|
|
96
|
+
editorRadius: "12px",
|
|
97
97
|
toolbarStickyPosition: 0,
|
|
98
|
-
toolbarBgColor:
|
|
98
|
+
toolbarBgColor: "#242424",
|
|
99
99
|
toolbarZIndex: 10,
|
|
100
|
-
toolbarPadding:
|
|
101
|
-
toolbarGap:
|
|
102
|
-
docMaxWidth:
|
|
103
|
-
docPadding:
|
|
104
|
-
docBg:
|
|
105
|
-
docMarginInline:
|
|
106
|
-
docMarginBlock:
|
|
107
|
-
docRadius:
|
|
100
|
+
toolbarPadding: "8px",
|
|
101
|
+
toolbarGap: "5px",
|
|
102
|
+
docMaxWidth: "1024px",
|
|
103
|
+
docPadding: "2rem",
|
|
104
|
+
docBg: "transparent",
|
|
105
|
+
docMarginInline: "auto",
|
|
106
|
+
docMarginBlock: "2rem",
|
|
107
|
+
docRadius: "0",
|
|
108
108
|
};
|
|
109
109
|
|
|
110
110
|
let editorConfig = $state({
|
|
111
111
|
...defaultEditorConfig,
|
|
112
|
-
...(config ?? {})
|
|
112
|
+
...(config ?? {}),
|
|
113
113
|
});
|
|
114
114
|
|
|
115
115
|
const extensions = [
|
|
@@ -280,61 +280,67 @@
|
|
|
280
280
|
onMount(() => {
|
|
281
281
|
editor = createEditor({
|
|
282
282
|
extensions,
|
|
283
|
-
content
|
|
283
|
+
content:
|
|
284
|
+
'<h2 style="line-height: 1;"><span style="font-size: 22px;">Aquí tens algunes expressions bàsiques en català. Llegeix-les, escolta-les i repeteix-les.</span></h2><table class="fl-table-editable" style="min-width: 75px;"><colgroup><col style="min-width: 25px;"><col style="min-width: 25px;"><col style="min-width: 25px;"></colgroup><tbody><tr><th class="fl-cell-editable" colspan="1" rowspan="1"><p></p></th><th class="fl-cell-editable" colspan="1" rowspan="1"><p></p></th><th class="fl-cell-editable" colspan="1" rowspan="1"><p></p></th></tr><tr><td class="fl-cell-editable" colspan="1" rowspan="1"><p></p></td><td class="fl-cell-editable" colspan="1" rowspan="1"><p></p></td><td class="fl-cell-editable" colspan="1" rowspan="1"><p></p></td></tr><tr><td class="fl-cell-editable" colspan="1" rowspan="1"><p></p></td><td class="fl-cell-editable" colspan="1" rowspan="1"><p></p></td><td class="fl-cell-editable" colspan="1" rowspan="1"><p></p></td></tr></tbody></table><ul><li><p style="line-height: 1.5;">Hola!</p></li><li><p style="line-height: 1.5;">Com estàs?</p></li><li><p style="line-height: 1.5;">Com et dius?</p></li><li><p style="line-height: 1.5;">Com es diu agua en català?</p></li><li><p style="line-height: 1.5;">Què vol dir rentadora?</p></li><li><p style="line-height: 1.5;">Com s\'escriu bolígraf?</p></li><li><p style="line-height: 1.5;">Com es pronuncia aquesta paraula?</p></li><li><p style="line-height: 1.5;">M\'ho pots repetir, si us plau?</p></li><li><p style="line-height: 1.5;">A poc a poc, si us plau.</p></li><li><p style="line-height: 1.5;">Com?</p></li><li><p style="line-height: 1.5;">No t\'entenc.</p></li><li><p style="line-height: 1.5;">Gràcies.</p></li><li><p style="line-height: 1.5;">De res.</p></li><li><p style="line-height: 1.5;">Perdona.</p></li><li><p style="line-height: 1.5;">I tant!</p></li><li><p style="line-height: 1.5;">Edited</p></li></ul><pre><code>const name = "Alex";\nconsole.log(`Hello ${name}`)</code></pre><media-grid-component class="fl-media-grid" data-cols="3" data-gap="1.5rem" data-show-indicator="false" data-indicator-type="numeric"><div data-type="grid-item" class="fl-grid-item"><img src="https://img2.rtve.es/n/16848600?w=1600"></div><div data-type="grid-item" class="fl-grid-item"><img src="https://img2.rtve.es/n/16848600?w=1600"></div><div data-type="grid-item" class="fl-grid-item"><img src="https://img2.rtve.es/n/16848600?w=1600"></div></media-grid-component><audio-player class="audio-player" src="https://pub-503cb197f1134814ac02f257b9cde1c1.r2.dev/uploads/audio-festa-major.mp3" controls="true" data-color-play="#333" data-color-bar="#888" data-max-width="100%" data-id="fl-audio-4i336em9v43"></audio-player><blockquote><p>- Hola! Com estàs?<br>- Molt bé, i tu?</p></blockquote><audio-player class="audio-player" src="https://pub-503cb197f1134814ac02f257b9cde1c1.r2.dev/uploads/dictat-buscar-habitatge.mp3" controls="true" data-color-play="#333" data-color-bar="#888" data-max-width="100%" data-id="fl-audio-4i336em9v43"></audio-player><blockquote><p>- Com et dius?<br>- Em dic Sara, i tu?</p></blockquote><audio-player class="audio-player" src="https://pub-503cb197f1134814ac02f257b9cde1c1.r2.dev/uploads/dictat-buscar-habitatge.mp3" controls="true" data-color-play="#333" data-color-bar="#888" data-max-width="100%" data-id="fl-audio-4i336em9v43"></audio-player><blockquote><p>Com es diu mesa en català?</p></blockquote><audio-player class="audio-player" src="https://pub-503cb197f1134814ac02f257b9cde1c1.r2.dev/uploads/dictat-buscar-habitatge.mp3" controls="true" data-color-play="#333" data-color-bar="#888" data-max-width="100%" data-id="fl-audio-4i336em9v43"></audio-player><blockquote><p>Què vol dir rentadora?</p></blockquote><audio-player class="audio-player" src="https://pub-503cb197f1134814ac02f257b9cde1c1.r2.dev/uploads/dictat-buscar-habitatge.mp3" controls="true" data-color-play="#333" data-color-bar="#888" data-max-width="100%" data-id="fl-audio-4i336em9v43"></audio-player><blockquote><p>Com s\'escriu bolígraf?</p></blockquote><audio-player class="audio-player" src="https://pub-503cb197f1134814ac02f257b9cde1c1.r2.dev/uploads/dictat-buscar-habitatge.mp3" controls="true" data-color-play="#333" data-color-bar="#888" data-max-width="100%" data-id="fl-audio-4i336em9v43"></audio-player><blockquote><p>Com es pronuncia això?</p></blockquote><audio-player class="audio-player" src="https://pub-503cb197f1134814ac02f257b9cde1c1.r2.dev/uploads/dictat-buscar-habitatge.mp3" controls="true" data-color-play="#333" data-color-bar="#888" data-max-width="100%" data-id="fl-audio-4i336em9v43"></audio-player><blockquote><p>- No t\'entenc. A poc a poc, si us plau.<br>- Ostres, perdona.</p></blockquote><audio-player class="audio-player" src="https://pub-503cb197f1134814ac02f257b9cde1c1.r2.dev/uploads/dictat-buscar-habitatge.mp3" controls="true" data-color-play="#333" data-color-bar="#888" data-max-width="100%" data-id="fl-audio-4i336em9v43"></audio-player><blockquote><p>- Com? M\'ho pots repetir, si us plau?<br>- Sí, i tant!</p></blockquote><audio-player class="audio-player" src="https://pub-503cb197f1134814ac02f257b9cde1c1.r2.dev/uploads/dictat-buscar-habitatge.mp3" controls="true" data-color-play="#333" data-color-bar="#888" data-max-width="100%" data-id="fl-audio-4i336em9v43"></audio-player><blockquote><p>- Gràcies.<br>- De res!</p></blockquote>',
|
|
284
285
|
editorProps: {
|
|
285
286
|
attributes: {
|
|
286
|
-
class: "fl-rich-text-content-
|
|
287
|
+
class: "fl-rich-text-content-doc",
|
|
287
288
|
},
|
|
288
289
|
handleKeyDown: (view, event) => {
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
290
|
+
if (event.key === "Enter" && !event.ctrlKey) {
|
|
291
|
+
enterPressed = true;
|
|
292
|
+
|
|
293
|
+
setTimeout(() => {
|
|
294
|
+
enterPressed = false;
|
|
295
|
+
const { from } = view.state.selection;
|
|
296
|
+
|
|
297
|
+
// Obtener el nodo de ProseMirror en la posición actual
|
|
298
|
+
const pos = view.state.doc.resolve(from);
|
|
299
|
+
const nodeBefore = pos.node(pos.depth);
|
|
300
|
+
const parentNode = pos.node(pos.depth - 1);
|
|
301
|
+
|
|
302
|
+
// console.log("Node type:", nodeBefore.type.name);
|
|
303
|
+
// console.log("Parent node type:", parentNode?.type.name);
|
|
304
|
+
|
|
305
|
+
// Solo ejecutar si estamos en un párrafo Y el padre no es una lista
|
|
306
|
+
const isInList =
|
|
307
|
+
parentNode?.type.name === "listItem" ||
|
|
308
|
+
parentNode?.type.name === "bulletList" ||
|
|
309
|
+
parentNode?.type.name === "orderedList";
|
|
310
|
+
|
|
311
|
+
if (nodeBefore.type.name === "paragraph" && !isInList) {
|
|
312
|
+
const domAtPos = view.domAtPos(from);
|
|
313
|
+
let element = domAtPos.node;
|
|
314
|
+
|
|
315
|
+
if (element.nodeType === Node.TEXT_NODE) {
|
|
316
|
+
element = element.parentElement;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
if (element instanceof HTMLElement) {
|
|
320
|
+
const computedSize =
|
|
321
|
+
window.getComputedStyle(element).fontSize;
|
|
322
|
+
const computedLineHeight =
|
|
323
|
+
window.getComputedStyle(element).lineHeight;
|
|
324
|
+
// console.log({ computedSize, computedLineHeight });
|
|
325
|
+
|
|
326
|
+
const lineHeightPx = parseFloat(
|
|
327
|
+
computedLineHeight.replace("px", "")
|
|
328
|
+
);
|
|
329
|
+
const fontSizePx = parseFloat(computedSize.replace("px", ""));
|
|
330
|
+
|
|
331
|
+
const lineHeightUnitless = lineHeightPx / fontSizePx;
|
|
332
|
+
|
|
333
|
+
// console.log(lineHeightUnitless.toFixed(2)); // ej: "x.xx"
|
|
334
|
+
|
|
335
|
+
fontSize = Math.round(Number(computedSize.replace("px", "")));
|
|
336
|
+
$editor.chain().focus().unsetFontSize().run();
|
|
337
|
+
|
|
338
|
+
$editor.chain().focus().unsetNodeLineHeight().run();
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}, 200);
|
|
342
|
+
}
|
|
343
|
+
},
|
|
338
344
|
},
|
|
339
345
|
onTransaction: ({ editor, transaction }) => {
|
|
340
346
|
editorEvents.onTransaction({ editor, transaction });
|
|
@@ -359,11 +365,12 @@
|
|
|
359
365
|
// Obtener el font-size computado
|
|
360
366
|
if (element instanceof HTMLElement) {
|
|
361
367
|
const computedSize = window.getComputedStyle(element).fontSize;
|
|
362
|
-
const computedLineHeight =
|
|
368
|
+
const computedLineHeight =
|
|
369
|
+
window.getComputedStyle(element).lineHeight;
|
|
363
370
|
// console.log("Get element font size:", computedSize);
|
|
364
371
|
// console.log("Get element line height:", computedLineHeight);
|
|
365
|
-
const lineHeightPx = parseFloat(computedLineHeight.replace("px", ""))
|
|
366
|
-
const fontSizePx = parseFloat(computedSize.replace("px", ""))
|
|
372
|
+
const lineHeightPx = parseFloat(computedLineHeight.replace("px", ""));
|
|
373
|
+
const fontSizePx = parseFloat(computedSize.replace("px", ""));
|
|
367
374
|
const lineHeightUnitless = lineHeightPx / fontSizePx;
|
|
368
375
|
|
|
369
376
|
// console.log(lineHeightUnitless.toFixed(2)); // ej: "x.xx"
|
|
@@ -385,8 +392,6 @@
|
|
|
385
392
|
} else {
|
|
386
393
|
lineHeight = Number(lineHeightUnitless.toFixed(2));
|
|
387
394
|
}
|
|
388
|
-
|
|
389
|
-
|
|
390
395
|
}
|
|
391
396
|
},
|
|
392
397
|
|
|
@@ -535,9 +540,7 @@
|
|
|
535
540
|
}
|
|
536
541
|
|
|
537
542
|
function handleRangeInput(e: any) {
|
|
538
|
-
|
|
539
|
-
$editor.commands.setNodeLineHeight(lineHeight.toString())
|
|
540
|
-
|
|
543
|
+
$editor.commands.setNodeLineHeight(lineHeight.toString());
|
|
541
544
|
}
|
|
542
545
|
|
|
543
546
|
function addAudio() {
|
|
@@ -547,38 +550,39 @@
|
|
|
547
550
|
alert("Please enter a valid URL");
|
|
548
551
|
return;
|
|
549
552
|
}
|
|
550
|
-
|
|
551
|
-
$editor.chain().focus().setAudio({ src, controls: true }).run()
|
|
552
|
-
|
|
553
|
+
|
|
554
|
+
$editor.chain().focus().setAudio({ src, controls: true }).run();
|
|
553
555
|
}
|
|
554
556
|
|
|
555
557
|
function addImage() {
|
|
556
|
-
const previousSrc = $editor.getAttributes("image").src;
|
|
558
|
+
const previousSrc = $editor.getAttributes("image").src;
|
|
557
559
|
const src = window.prompt("Enter the URL of the image:", previousSrc);
|
|
558
560
|
|
|
559
561
|
if (!src) {
|
|
560
562
|
alert("Please enter a valid URL");
|
|
561
563
|
return;
|
|
562
564
|
}
|
|
563
|
-
|
|
564
|
-
$editor.chain().focus().setImage({ src }).run()
|
|
565
|
-
|
|
565
|
+
|
|
566
|
+
$editor.chain().focus().setImage({ src }).run();
|
|
566
567
|
}
|
|
567
568
|
|
|
568
569
|
function addMediaGrid() {
|
|
569
|
-
|
|
570
|
-
$editor.chain().focus().insertGrid({ cols: 2 }).run()
|
|
571
|
-
|
|
570
|
+
$editor.chain().focus().insertGrid({ cols: 2 }).run();
|
|
572
571
|
}
|
|
573
572
|
|
|
574
|
-
function addTable(){
|
|
575
|
-
$editor
|
|
573
|
+
function addTable() {
|
|
574
|
+
$editor
|
|
575
|
+
.chain()
|
|
576
|
+
.focus()
|
|
577
|
+
.insertTable({ rows: 3, cols: 3, withHeaderRow: true })
|
|
578
|
+
.run();
|
|
576
579
|
}
|
|
577
580
|
</script>
|
|
578
581
|
|
|
579
|
-
<div
|
|
580
|
-
class="fl-rich-text {className}"
|
|
581
|
-
|
|
582
|
+
<div
|
|
583
|
+
class="fl-rich-text {className}"
|
|
584
|
+
class:editable
|
|
585
|
+
style="
|
|
582
586
|
--fl-editor-radius: {editorConfig.editorRadius};
|
|
583
587
|
--fl-editor-bg: {editorConfig.editorBgColor};
|
|
584
588
|
--fl-toolbar-sticky-position: {editorConfig.toolbarStickyPosition}px;
|
|
@@ -594,7 +598,6 @@ style="
|
|
|
594
598
|
--fl-doc-radius: {editorConfig.docRadius};
|
|
595
599
|
"
|
|
596
600
|
>
|
|
597
|
-
|
|
598
601
|
{#if editor}
|
|
599
602
|
<header class="fl-rich-text-toolbar">
|
|
600
603
|
<!-- Undo/Redo -->
|
|
@@ -924,35 +927,80 @@ style="
|
|
|
924
927
|
<!-- Font size editor -->
|
|
925
928
|
<div role="group" class="fl-rich-text-toolbar-group">
|
|
926
929
|
<div class="fl-font-size-editor">
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
930
|
+
<button
|
|
931
|
+
type="button"
|
|
932
|
+
aria-label="Decrease font size"
|
|
933
|
+
onclick={decrementFontSize}
|
|
934
|
+
class="fl-font-size-editor-button"
|
|
935
|
+
>
|
|
936
|
+
<svg
|
|
937
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
938
|
+
width="24"
|
|
939
|
+
height="24"
|
|
940
|
+
viewBox="0 0 24 24"
|
|
941
|
+
fill="none"
|
|
942
|
+
stroke="currentColor"
|
|
943
|
+
stroke-width="2"
|
|
944
|
+
stroke-linecap="round"
|
|
945
|
+
stroke-linejoin="round"
|
|
946
|
+
class="icon icon-tabler icons-tabler-outline icon-tabler-minus"
|
|
947
|
+
><path stroke="none" d="M0 0h24v24H0z" fill="none" /><path
|
|
948
|
+
d="M5 12l14 0"
|
|
949
|
+
/></svg
|
|
934
950
|
>
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
951
|
+
</button>
|
|
952
|
+
<input type="text" bind:value={fontSize} />
|
|
953
|
+
<button
|
|
954
|
+
type="button"
|
|
955
|
+
aria-label="Increase font size"
|
|
956
|
+
onclick={incrementFontSize}
|
|
957
|
+
class="fl-font-size-editor-button"
|
|
958
|
+
>
|
|
959
|
+
<svg
|
|
960
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
961
|
+
width="24"
|
|
962
|
+
height="24"
|
|
963
|
+
viewBox="0 0 24 24"
|
|
964
|
+
fill="none"
|
|
965
|
+
stroke="currentColor"
|
|
966
|
+
stroke-width="2"
|
|
967
|
+
stroke-linecap="round"
|
|
968
|
+
stroke-linejoin="round"
|
|
969
|
+
class="icon icon-tabler icons-tabler-outline icon-tabler-plus"
|
|
970
|
+
><path stroke="none" d="M0 0h24v24H0z" fill="none" /><path
|
|
971
|
+
d="M12 5l0 14"
|
|
972
|
+
/><path d="M5 12l14 0" /></svg
|
|
943
973
|
>
|
|
974
|
+
</button>
|
|
944
975
|
</div>
|
|
945
976
|
</div>
|
|
946
977
|
|
|
947
978
|
<!-- Line height -->
|
|
948
979
|
<div role="group" class="fl-rich-text-toolbar-group">
|
|
949
|
-
<button
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
980
|
+
<button
|
|
981
|
+
class="fl-font-size-button"
|
|
982
|
+
aria-label="Line height"
|
|
983
|
+
type="button"
|
|
984
|
+
onclick={(e) =>
|
|
985
|
+
toogleDropdown(e.currentTarget, "line-height-dropdown")}
|
|
954
986
|
>
|
|
955
|
-
<svg
|
|
987
|
+
<svg
|
|
988
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
989
|
+
width="16"
|
|
990
|
+
height="16"
|
|
991
|
+
viewBox="0 0 24 24"
|
|
992
|
+
fill="none"
|
|
993
|
+
stroke="currentColor"
|
|
994
|
+
stroke-width="2"
|
|
995
|
+
stroke-linecap="round"
|
|
996
|
+
stroke-linejoin="round"
|
|
997
|
+
class="icon icon-tabler icons-tabler-outline icon-tabler-line-height"
|
|
998
|
+
><path stroke="none" d="M0 0h24v24H0z" fill="none" /><path
|
|
999
|
+
d="M3 8l3 -3l3 3"
|
|
1000
|
+
/><path d="M3 16l3 3l3 -3" /><path d="M6 5l0 14" /><path
|
|
1001
|
+
d="M13 6l7 0"
|
|
1002
|
+
/><path d="M13 12l7 0" /><path d="M13 18l7 0" /></svg
|
|
1003
|
+
>
|
|
956
1004
|
|
|
957
1005
|
<svg
|
|
958
1006
|
class="toogle-dropdown-button-icon"
|
|
@@ -1277,7 +1325,17 @@ style="
|
|
|
1277
1325
|
aria-label="Image"
|
|
1278
1326
|
class:is-active={$editor.isActive("image")}
|
|
1279
1327
|
>
|
|
1280
|
-
<svg
|
|
1328
|
+
<svg
|
|
1329
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
1330
|
+
width="24"
|
|
1331
|
+
height="24"
|
|
1332
|
+
viewBox="0 0 24 24"
|
|
1333
|
+
fill="currentColor"
|
|
1334
|
+
class="icon icon-tabler icons-tabler-filled icon-tabler-photo"
|
|
1335
|
+
><path stroke="none" d="M0 0h24v24H0z" fill="none" /><path
|
|
1336
|
+
d="M8.813 11.612c.457 -.38 .918 -.38 1.386 .011l.108 .098l4.986 4.986l.094 .083a1 1 0 0 0 1.403 -1.403l-.083 -.094l-1.292 -1.293l.292 -.293l.106 -.095c.457 -.38 .918 -.38 1.386 .011l.108 .098l4.674 4.675a4 4 0 0 1 -3.775 3.599l-.206 .005h-12a4 4 0 0 1 -3.98 -3.603l6.687 -6.69l.106 -.095zm9.187 -9.612a4 4 0 0 1 3.995 3.8l.005 .2v9.585l-3.293 -3.292l-.15 -.137c-1.256 -1.095 -2.85 -1.097 -4.096 -.017l-.154 .14l-.307 .306l-2.293 -2.292l-.15 -.137c-1.256 -1.095 -2.85 -1.097 -4.096 -.017l-.154 .14l-5.307 5.306v-9.585a4 4 0 0 1 3.8 -3.995l.2 -.005h12zm-2.99 5l-.127 .007a1 1 0 0 0 0 1.986l.117 .007l.127 -.007a1 1 0 0 0 0 -1.986l-.117 -.007z"
|
|
1337
|
+
/></svg
|
|
1338
|
+
>
|
|
1281
1339
|
</button>
|
|
1282
1340
|
<!-- Audio -->
|
|
1283
1341
|
<button
|
|
@@ -1286,7 +1344,7 @@ style="
|
|
|
1286
1344
|
aria-label="Audio"
|
|
1287
1345
|
class:is-active={$editor.isActive("audio")}
|
|
1288
1346
|
>
|
|
1289
|
-
|
|
1347
|
+
Audio
|
|
1290
1348
|
</button>
|
|
1291
1349
|
</div>
|
|
1292
1350
|
|
|
@@ -1299,7 +1357,23 @@ style="
|
|
|
1299
1357
|
aria-label="Media grid"
|
|
1300
1358
|
class:is-active={$editor.isActive("MediaGridComponent")}
|
|
1301
1359
|
>
|
|
1302
|
-
<svg
|
|
1360
|
+
<svg
|
|
1361
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
1362
|
+
width="24"
|
|
1363
|
+
height="24"
|
|
1364
|
+
viewBox="0 0 24 24"
|
|
1365
|
+
fill="currentColor"
|
|
1366
|
+
class="icon icon-tabler icons-tabler-filled icon-tabler-layout-grid"
|
|
1367
|
+
><path stroke="none" d="M0 0h24v24H0z" fill="none" /><path
|
|
1368
|
+
d="M9 3a2 2 0 0 1 2 2v4a2 2 0 0 1 -2 2h-4a2 2 0 0 1 -2 -2v-4a2 2 0 0 1 2 -2z"
|
|
1369
|
+
/><path
|
|
1370
|
+
d="M19 3a2 2 0 0 1 2 2v4a2 2 0 0 1 -2 2h-4a2 2 0 0 1 -2 -2v-4a2 2 0 0 1 2 -2z"
|
|
1371
|
+
/><path
|
|
1372
|
+
d="M9 13a2 2 0 0 1 2 2v4a2 2 0 0 1 -2 2h-4a2 2 0 0 1 -2 -2v-4a2 2 0 0 1 2 -2z"
|
|
1373
|
+
/><path
|
|
1374
|
+
d="M19 13a2 2 0 0 1 2 2v4a2 2 0 0 1 -2 2h-4a2 2 0 0 1 -2 -2v-4a2 2 0 0 1 2 -2z"
|
|
1375
|
+
/></svg
|
|
1376
|
+
>
|
|
1303
1377
|
</button>
|
|
1304
1378
|
<!-- Table -->
|
|
1305
1379
|
<button
|
|
@@ -1308,7 +1382,21 @@ style="
|
|
|
1308
1382
|
aria-label="Table"
|
|
1309
1383
|
class:is-active={$editor.isActive("table")}
|
|
1310
1384
|
>
|
|
1311
|
-
<svg
|
|
1385
|
+
<svg
|
|
1386
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
1387
|
+
width="24"
|
|
1388
|
+
height="24"
|
|
1389
|
+
viewBox="0 0 24 24"
|
|
1390
|
+
fill="none"
|
|
1391
|
+
stroke="currentColor"
|
|
1392
|
+
stroke-width="2"
|
|
1393
|
+
stroke-linecap="round"
|
|
1394
|
+
stroke-linejoin="round"
|
|
1395
|
+
class="icon icon-tabler icons-tabler-outline icon-tabler-table"
|
|
1396
|
+
><path stroke="none" d="M0 0h24v24H0z" fill="none" /><path
|
|
1397
|
+
d="M3 5a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v14a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2v-14"
|
|
1398
|
+
/><path d="M3 10h18" /><path d="M10 3v18" /></svg
|
|
1399
|
+
>
|
|
1312
1400
|
</button>
|
|
1313
1401
|
</div>
|
|
1314
1402
|
|
|
@@ -1959,12 +2047,18 @@ style="
|
|
|
1959
2047
|
{/if}
|
|
1960
2048
|
</div>
|
|
1961
2049
|
{:else if activeDropdownType === "line-height-dropdown"}
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
2050
|
+
<div class="fl-range-element">
|
|
2051
|
+
<span class="fl-range-element-value">
|
|
2052
|
+
{lineHeight.toFixed(2)}
|
|
2053
|
+
</span>
|
|
2054
|
+
<input
|
|
2055
|
+
oninput={handleRangeInput}
|
|
2056
|
+
type="range"
|
|
2057
|
+
min="0.5"
|
|
2058
|
+
max="4"
|
|
2059
|
+
step="0.05"
|
|
2060
|
+
bind:value={lineHeight}
|
|
2061
|
+
/>
|
|
2062
|
+
</div>
|
|
1969
2063
|
{/if}
|
|
1970
2064
|
</div>
|
|
@@ -1,2 +1,19 @@
|
|
|
1
1
|
import { Node } from '@tiptap/core';
|
|
2
|
+
interface InsertGridOptions {
|
|
3
|
+
cols?: number;
|
|
4
|
+
}
|
|
5
|
+
declare module '@tiptap/core' {
|
|
6
|
+
interface Commands<ReturnType> {
|
|
7
|
+
MediaGridComponent: {
|
|
8
|
+
/**
|
|
9
|
+
* Añade un elemento de audio personalizado
|
|
10
|
+
* @example
|
|
11
|
+
* editor.commands.setAudio({ src: '/audio.mp3', controls: true })
|
|
12
|
+
*/
|
|
13
|
+
insertGrid: (options?: InsertGridOptions) => ReturnType;
|
|
14
|
+
addGridItem: () => ReturnType;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
}
|
|
2
18
|
export declare const MediaGridExtension: Node<any, any>;
|
|
19
|
+
export {};
|
|
@@ -19,43 +19,43 @@ export const MediaGridExtension = Node.create({
|
|
|
19
19
|
},
|
|
20
20
|
cols: {
|
|
21
21
|
default: 2,
|
|
22
|
-
parseHTML: element =>
|
|
22
|
+
parseHTML: element => {
|
|
23
|
+
return element.dataset.cols;
|
|
24
|
+
},
|
|
23
25
|
renderHTML: attrs => ({ 'data-cols': attrs.cols }),
|
|
24
26
|
},
|
|
25
27
|
gap: {
|
|
26
28
|
default: '1rem',
|
|
27
|
-
parseHTML: element => element.
|
|
29
|
+
parseHTML: element => element.dataset.gap,
|
|
28
30
|
renderHTML: attrs => ({ 'data-gap': attrs.gap }),
|
|
29
31
|
},
|
|
30
32
|
showIndicator: {
|
|
31
33
|
default: false,
|
|
32
|
-
parseHTML: element => element.
|
|
34
|
+
parseHTML: element => element.dataset.showIndicator,
|
|
33
35
|
renderHTML: attrs => ({ 'data-show-indicator': attrs.showIndicator }),
|
|
34
36
|
},
|
|
35
37
|
indicatorType: {
|
|
36
38
|
default: 'numeric', // 'numeric' | 'alphabetic'
|
|
37
|
-
parseHTML: element => element.
|
|
39
|
+
parseHTML: element => element.dataset.indicatorType,
|
|
38
40
|
renderHTML: attrs => ({ 'data-indicator-type': attrs.indicatorType }),
|
|
39
41
|
}
|
|
40
42
|
};
|
|
41
43
|
},
|
|
42
44
|
parseHTML() {
|
|
43
|
-
return [
|
|
45
|
+
return [
|
|
46
|
+
{
|
|
47
|
+
tag: 'media-grid-component',
|
|
48
|
+
}
|
|
49
|
+
];
|
|
44
50
|
},
|
|
45
51
|
renderHTML({ HTMLAttributes }) {
|
|
46
|
-
return ['
|
|
52
|
+
return ['media-grid-component', mergeAttributes(HTMLAttributes), 0];
|
|
47
53
|
},
|
|
48
54
|
addCommands() {
|
|
49
55
|
return {
|
|
50
56
|
insertGrid: (options) => ({ tr, state, dispatch }) => {
|
|
51
57
|
const { schema } = state;
|
|
52
58
|
const cols = options?.cols || 2;
|
|
53
|
-
// const items = Array.from({ length: cols }, () =>
|
|
54
|
-
// schema.nodes.gridItem.create(
|
|
55
|
-
// null,
|
|
56
|
-
// schema.nodes.image.create({ src: 'https://placehold.co/800x400' })
|
|
57
|
-
// )
|
|
58
|
-
// )
|
|
59
59
|
const items = Array.from({ length: cols }, () => schema.nodes.gridItem.create() // 👈 sin contenido
|
|
60
60
|
);
|
|
61
61
|
const grid = this.type.create({ cols }, items);
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
const { node, updateAttributes, selected, getPos, editor }: NodeViewProps = $props();
|
|
7
7
|
|
|
8
|
+
console.log(node);
|
|
8
9
|
let cols = $state(node.attrs.cols || 2);
|
|
9
10
|
let gap = $state(node.attrs.gap || 1);
|
|
10
11
|
let showIndicator = $state(node.attrs.showIndicator || false);
|
|
@@ -101,7 +102,7 @@
|
|
|
101
102
|
oninput={handleShowIndicatorChange}
|
|
102
103
|
type="checkbox"
|
|
103
104
|
id="show-indicator"
|
|
104
|
-
|
|
105
|
+
checked={showIndicator}
|
|
105
106
|
/>
|
|
106
107
|
Show indicators
|
|
107
108
|
</label>
|
package/dist/styles.css
CHANGED
|
@@ -264,14 +264,18 @@
|
|
|
264
264
|
flex-direction: column;
|
|
265
265
|
text-align: left;
|
|
266
266
|
min-height: 56px;
|
|
267
|
-
border-radius: var(--fl-doc-radius, 12px);
|
|
268
267
|
box-sizing: border-box;
|
|
269
|
-
|
|
268
|
+
width: 100%;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
.fl-rich-text-content-doc {
|
|
270
272
|
padding: var(--fl-doc-padding, 2rem);
|
|
271
273
|
background: var(--fl-doc-bg, transparent);
|
|
274
|
+
border-radius: var(--fl-doc-radius, 12px);
|
|
275
|
+
width: 100%;
|
|
276
|
+
max-width: var(--fl-doc-max-width, 1024px);
|
|
272
277
|
margin-inline: var(--fl-doc-margin-inline, auto);
|
|
273
278
|
margin-block: var(--fl-doc-margin-block, 2rem);
|
|
274
|
-
|
|
275
279
|
}
|
|
276
280
|
|
|
277
281
|
.fl-toolbar-dropdown-panel {
|
|
@@ -588,8 +592,8 @@
|
|
|
588
592
|
position: absolute;
|
|
589
593
|
left: 10px;
|
|
590
594
|
top: 10px;
|
|
591
|
-
width:
|
|
592
|
-
height:
|
|
595
|
+
width: 26px;
|
|
596
|
+
height: 26px;
|
|
593
597
|
display: flex;
|
|
594
598
|
align-items: center;
|
|
595
599
|
justify-content: center;
|
|
@@ -597,7 +601,10 @@
|
|
|
597
601
|
border-radius: 100%;
|
|
598
602
|
color: #fff;
|
|
599
603
|
font-weight: 600;
|
|
600
|
-
font-size:
|
|
604
|
+
font-size: 16px;
|
|
605
|
+
text-align: center;
|
|
606
|
+
font-family: monospace;
|
|
607
|
+
text-transform: uppercase;
|
|
601
608
|
}
|
|
602
609
|
}
|
|
603
610
|
|