@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.
@@ -4,7 +4,7 @@
4
4
  import { TableKit } from "@tiptap/extension-table";
5
5
  import { CellSelection } from "prosemirror-tables";
6
6
 
7
- import { NodeLineHeight } from './extensions/NodeLineHeight';
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: 'transparent',
96
- editorRadius: '12px',
95
+ editorBgColor: "transparent",
96
+ editorRadius: "12px",
97
97
  toolbarStickyPosition: 0,
98
- toolbarBgColor: '#242424',
98
+ toolbarBgColor: "#242424",
99
99
  toolbarZIndex: 10,
100
- toolbarPadding: '8px',
101
- toolbarGap: '5px',
102
- docMaxWidth: '1024px',
103
- docPadding: '2rem',
104
- docBg: 'transparent',
105
- docMarginInline: 'auto',
106
- docMarginBlock: '2rem',
107
- docRadius: '0',
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 &nbsp;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-eee",
287
+ class: "fl-rich-text-content-doc",
287
288
  },
288
289
  handleKeyDown: (view, event) => {
289
- if (event.key === "Enter" && !event.ctrlKey) {
290
- enterPressed = true;
291
-
292
- setTimeout(() => {
293
- enterPressed = false;
294
- const { from } = view.state.selection;
295
-
296
- // Obtener el nodo de ProseMirror en la posición actual
297
- const pos = view.state.doc.resolve(from);
298
- const nodeBefore = pos.node(pos.depth);
299
- const parentNode = pos.node(pos.depth - 1);
300
-
301
- // console.log("Node type:", nodeBefore.type.name);
302
- // console.log("Parent node type:", parentNode?.type.name);
303
-
304
- // Solo ejecutar si estamos en un párrafo Y el padre no es una lista
305
- const isInList = parentNode?.type.name === "listItem" ||
306
- parentNode?.type.name === "bulletList" ||
307
- parentNode?.type.name === "orderedList";
308
-
309
- if (nodeBefore.type.name === "paragraph" && !isInList) {
310
- const domAtPos = view.domAtPos(from);
311
- let element = domAtPos.node;
312
-
313
- if (element.nodeType === Node.TEXT_NODE) {
314
- element = element.parentElement;
315
- }
316
-
317
- if (element instanceof HTMLElement) {
318
- const computedSize = window.getComputedStyle(element).fontSize;
319
- const computedLineHeight = window.getComputedStyle(element).lineHeight;
320
- // console.log({ computedSize, computedLineHeight });
321
-
322
- const lineHeightPx = parseFloat(computedLineHeight.replace("px", ""))
323
- const fontSizePx = parseFloat(computedSize.replace("px", ""))
324
-
325
- const lineHeightUnitless = lineHeightPx / fontSizePx;
326
-
327
- // console.log(lineHeightUnitless.toFixed(2)); // ej: "x.xx"
328
-
329
- fontSize = Math.round(Number(computedSize.replace("px", "")));
330
- $editor.chain().focus().unsetFontSize().run();
331
-
332
- $editor.chain().focus().unsetNodeLineHeight().run();
333
- }
334
- }
335
- }, 200);
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 = window.getComputedStyle(element).lineHeight;
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.chain().focus().insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run()
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}" class:editable
581
- style="
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
- <button
928
- type="button"
929
- aria-label="Decrease font size"
930
- onclick={decrementFontSize}
931
- class="fl-font-size-editor-button">
932
- <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-minus"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M5 12l14 0" /></svg>
933
- </button
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
- <input type="text" bind:value={fontSize} />
936
- <button
937
- type="button"
938
- aria-label="Increase font size"
939
- onclick={incrementFontSize}
940
- class="fl-font-size-editor-button">
941
- <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-plus"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M12 5l0 14" /><path d="M5 12l14 0" /></svg>
942
- </button
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
- class="fl-font-size-button"
951
- aria-label="Line height"
952
- type="button"
953
- onclick={(e) => toogleDropdown(e.currentTarget, "line-height-dropdown")}
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 xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-line-height"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M3 8l3 -3l3 3" /><path d="M3 16l3 3l3 -3" /><path d="M6 5l0 14" /><path d="M13 6l7 0" /><path d="M13 12l7 0" /><path d="M13 18l7 0" /></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 xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor" class="icon icon-tabler icons-tabler-filled icon-tabler-photo"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path 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" /></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
- Audio
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 xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor" class="icon icon-tabler icons-tabler-filled icon-tabler-layout-grid"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path 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" /><path 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" /><path 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" /><path 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" /></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 xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-table"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path 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" /><path d="M3 10h18" /><path d="M10 3v18" /></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
- <div class="fl-range-element">
1963
- <span class="fl-range-element-value">
1964
- {lineHeight.toFixed(2)}
1965
- </span>
1966
- <input oninput={handleRangeInput} type="range" min="0.5" max="4" step="0.05" bind:value={lineHeight}>
1967
- </div>
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 => parseInt(element.getAttribute('data-cols') || '2', 10),
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.getAttribute('data-gap') || '1rem',
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.getAttribute('data-show-indicator') || false,
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.getAttribute('data-indicator-type') || 'numeric',
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 [{ tag: 'media-grid-component' }];
45
+ return [
46
+ {
47
+ tag: 'media-grid-component',
48
+ }
49
+ ];
44
50
  },
45
51
  renderHTML({ HTMLAttributes }) {
46
- return ['div', mergeAttributes(HTMLAttributes), 0];
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
- value={showIndicator}
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
- max-width: var(--fl-doc-max-width, 1024px);
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: 24px;
592
- height: 24px;
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: 14px;
604
+ font-size: 16px;
605
+ text-align: center;
606
+ font-family: monospace;
607
+ text-transform: uppercase;
601
608
  }
602
609
  }
603
610
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flexiui/svelte-rich-text",
3
- "version": "0.0.33",
3
+ "version": "0.0.34",
4
4
  "description": "A lightweight and flexible rich text editor component for Svelte",
5
5
  "keywords": [
6
6
  "svelte",