@flexiui/svelte-rich-text 0.0.36 → 0.0.37

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.
@@ -39,59 +39,81 @@ export const Audio = Node.create({
39
39
  parseHTML: el => el.hasAttribute('loop'),
40
40
  renderHTML: attrs => (attrs.loop ? { loop: true } : {}),
41
41
  },
42
- colorPlay: {
43
- default: '#333',
44
- parseHTML: el => el.getAttribute('data-color-play') || '#333',
42
+ id: {
43
+ default: `fl-audio-player-${Math.random().toString(36).substring(2, 15)}`,
44
+ parseHTML: el => el.getAttribute('data-id') || null,
45
45
  renderHTML: attrs => ({
46
- 'data-color-play': attrs.colorPlay,
46
+ 'data-id': attrs.id,
47
+ }),
48
+ },
49
+ bgColor: {
50
+ default: '#8c8c8c45',
51
+ parseHTML: el => el.getAttribute('data-bg-color'),
52
+ renderHTML: attrs => ({
53
+ 'data-bg-color': attrs.bgColor,
47
54
  }),
48
55
  },
49
- colorBar: {
50
- default: '#888',
51
- parseHTML: el => el.getAttribute('data-color-bar') || '#888',
56
+ textColor: {
57
+ default: 'currentColor',
58
+ parseHTML: el => el.getAttribute('data-text-color'),
52
59
  renderHTML: attrs => ({
53
- 'data-color-bar': attrs.colorBar,
60
+ 'data-text-color': attrs.textColor,
61
+ }),
62
+ },
63
+ borderRadius: {
64
+ default: '18px',
65
+ parseHTML: el => el.getAttribute('data-border-radius'),
66
+ renderHTML: attrs => ({
67
+ 'data-border-radius': attrs.borderRadius,
68
+ }),
69
+ },
70
+ accentColor: {
71
+ default: '#5e17eb',
72
+ parseHTML: el => el.getAttribute('data-accent-color'),
73
+ renderHTML: attrs => ({
74
+ 'data-accent-color': attrs.accentColor,
75
+ }),
76
+ },
77
+ accentColorPaused: {
78
+ default: '#fff',
79
+ parseHTML: el => el.getAttribute('data-accent-color-paused'),
80
+ renderHTML: attrs => ({
81
+ 'data-accent-color-paused': attrs.accentColorPaused,
82
+ }),
83
+ },
84
+ seekBarBgColor: {
85
+ default: '#8d8d8d3a',
86
+ parseHTML: el => el.getAttribute('data-seek-bar-bg-color'),
87
+ renderHTML: attrs => ({
88
+ 'data-seek-bar-bg-color': attrs.seekBarBgColor,
89
+ }),
90
+ },
91
+ colorPlay: {
92
+ default: '#5d5d5dc9',
93
+ parseHTML: el => el.getAttribute('data-color-play'),
94
+ renderHTML: attrs => ({
95
+ 'data-color-play': attrs.colorPlay,
54
96
  }),
55
97
  },
56
98
  maxWidth: {
57
99
  default: '100%',
58
- parseHTML: el => el.getAttribute('data-max-width') || '100%',
100
+ parseHTML: el => el.getAttribute('data-max-width'),
59
101
  renderHTML: attrs => ({
60
102
  'data-max-width': attrs.maxWidth,
61
103
  }),
62
104
  },
63
- id: {
64
- default: "fl-audio-" + Math.random().toString(36).slice(2),
65
- parseHTML: el => el.getAttribute('data-id') || null,
66
- renderHTML: attrs => ({
67
- 'data-id': attrs.id,
68
- }),
69
- }
70
105
  };
71
106
  },
72
107
  parseHTML() {
73
108
  return [
74
109
  {
75
- tag: 'audio-player',
76
- getAttrs: el => {
77
- if (!(el instanceof HTMLElement))
78
- return false;
79
- return {
80
- src: el.getAttribute('src'),
81
- controls: el.hasAttribute('controls'),
82
- autoplay: el.hasAttribute('autoplay'),
83
- loop: el.hasAttribute('loop'),
84
- colorPlay: el.getAttribute('data-color-play') || '#333',
85
- colorBar: el.getAttribute('data-color-bar') || '#888',
86
- maxWidth: el.getAttribute('data-max-width') || '100%',
87
- };
88
- },
110
+ tag: 'fl-audio-player',
89
111
  },
90
112
  ];
91
113
  },
92
114
  renderHTML({ HTMLAttributes }) {
93
115
  return [
94
- 'audio-player',
116
+ 'fl-audio-player',
95
117
  mergeAttributes(this.options.HTMLAttributes, HTMLAttributes),
96
118
  ];
97
119
  },
@@ -7,18 +7,27 @@
7
7
  import WaveSurfer from "wavesurfer.js";
8
8
  import { activeAudioId } from "./audioStore";
9
9
 
10
- export let id: string = "audio-" + Math.random().toString(36).slice(2);
10
+ export let id: string;
11
11
  export let src: string;
12
+ export let controls: any
12
13
  export let showSeekbar: boolean = true;
13
14
  export let config: any = {};
14
-
15
15
  export let playerType: "waveform" | "seekbar" = "waveform";
16
+ export let bgColor: string;
17
+ export let textColor: string;
18
+ export let borderRadius: string;
19
+ export let accentColor: string;
20
+ export let accentColorPaused: string;
21
+ export let colorPlay: string;
22
+ export let maxWidth: string;
16
23
 
17
24
  let wavesurfer: WaveSurfer | null = null;
18
25
  let waveformEl: HTMLDivElement | null = null;
19
26
  let wavesurferReady: boolean = false;
20
27
  let loading: boolean = true;
21
- let audio: any = null;
28
+ // let audio: any = null;
29
+ let audio: HTMLAudioElement | null = null;
30
+
22
31
  let playing: boolean = false;
23
32
  let mounted: boolean = false;
24
33
  let seekbarEl: HTMLDivElement | null = null;
@@ -31,6 +40,8 @@
31
40
  let audioDuration: number = 0;
32
41
  let audioCurrentTime: number = 0;
33
42
 
43
+ id = id + "-" + Math.random().toString(36).substring(2, 15);
44
+
34
45
  function formatTime(seconds: number) {
35
46
  if (isNaN(seconds) || seconds < 0) return "0:00";
36
47
 
@@ -152,10 +163,10 @@
152
163
  // wavesurfer?.stop();
153
164
  // });
154
165
 
155
- audio = new Audio(src);
166
+ // audio = new Audio(src);
167
+ // audio.load();
156
168
  audio.volume = volume;
157
169
  audio.preload = "auto";
158
- audio.load();
159
170
 
160
171
  audio.addEventListener("loadedmetadata", () => {
161
172
  audioDuration = audio.duration;
@@ -173,6 +184,19 @@
173
184
  }
174
185
  });
175
186
 
187
+ audio.onended = () => {
188
+ playing = false;
189
+ console.log("Audio playback ended");
190
+ };
191
+
192
+ audio.addEventListener("play", () => {
193
+ playing = true;
194
+ });
195
+
196
+ audio.addEventListener("pause", () => {
197
+ playing = false;
198
+ });
199
+
176
200
  setTimeout(() => {
177
201
  loading = false;
178
202
  }, 500);
@@ -262,7 +286,19 @@
262
286
  }
263
287
  </script>
264
288
 
265
- <div class="audio-player" {id} class:playing>
289
+ <div
290
+ class="audio-player"
291
+ {id}
292
+ class:playing
293
+ style={`
294
+ --player-bg-color: ${bgColor};
295
+ --player-play-btn-bg: ${colorPlay};
296
+ --player-primary-color: ${accentColor};
297
+ --player-progress-default-bg: ${accentColorPaused};
298
+ --player-text-color: ${textColor};
299
+ --player-border-radius: ${borderRadius};
300
+ `}
301
+ >
266
302
  <button
267
303
  onclick={() => togglePlayPause()}
268
304
  type="button"
@@ -441,11 +477,12 @@
441
477
  </div>
442
478
  </div>
443
479
 
444
- <!-- {#if mounted && !wavesurferReady}
445
- <div class="audio-player-time">
446
- 0:51
447
- </div>
448
- {/if} -->
480
+ <!-- Reproductor de audo nativo -->
481
+ <audio
482
+ bind:this={audio}
483
+ src={src}
484
+ id={'native-audio-' + id}
485
+ ></audio>
449
486
  </div>
450
487
 
451
488
  <style>
@@ -456,13 +493,14 @@
456
493
 
457
494
  .audio-player {
458
495
  --player-primary-color: #5e17eb;
459
- --player-bg-color: #455f7414;
496
+ --player-bg-color: #8c8c8c45;
460
497
  --player-border-radius: 18px;
461
498
  --player-seekbar-bg: #8d8d8d3a;
462
499
  --player-seekbar-height: 6px;
463
500
  --player-progress-default-bg: #f5f5f5;
464
501
  --player-play-btn-bg: #8d8d8d26;
465
502
  --player-play-btn-color: #fff;
503
+ --player-text-color: currentColor;
466
504
 
467
505
  display: flex;
468
506
  align-items: center;
@@ -472,6 +510,7 @@
472
510
  padding: 12px;
473
511
  width: 100%;
474
512
  box-sizing: border-box;
513
+ color: var(--player-text-color);
475
514
 
476
515
  &.playing {
477
516
  .audio-player-wave {
@@ -496,6 +535,16 @@
496
535
  border-radius: 100%;
497
536
  outline-offset: 4px;
498
537
  outline-color: var(--player-play-btn-bg);
538
+ cursor: pointer;
539
+ transition: filter 0.3s ease, transform 0.3s ease, background 0.3s ease;
540
+
541
+ &:hover {
542
+ /* background: var(--player-primary-color); */
543
+ &:not(.playing) {
544
+ filter: brightness(1.2);
545
+ }
546
+ transform: scale(1.06);
547
+ }
499
548
 
500
549
  svg {
501
550
  width: 20px;
@@ -587,7 +636,7 @@
587
636
  margin-right: 4px;
588
637
 
589
638
  &:hover {
590
- background: #0d121612;
639
+ background: #7a7a7a17;
591
640
  }
592
641
 
593
642
  &:hover .audio-player-seekbar,
@@ -621,6 +670,7 @@
621
670
  border: none;
622
671
  padding: 4px;
623
672
  background: #0d121600;
673
+ color: currentColor;
624
674
  border-radius: 100%;
625
675
  height: 36px;
626
676
  width: 36px;
@@ -1,11 +1,19 @@
1
1
  import { SvelteComponentTyped } from "svelte";
2
2
  declare const __propDef: {
3
3
  props: {
4
- id?: string;
4
+ id: string;
5
5
  src: string;
6
+ controls: any;
6
7
  showSeekbar?: boolean;
7
8
  config?: any;
8
9
  playerType?: "waveform" | "seekbar";
10
+ bgColor: string;
11
+ textColor: string;
12
+ borderRadius: string;
13
+ accentColor: string;
14
+ accentColorPaused: string;
15
+ colorPlay: string;
16
+ maxWidth: string;
9
17
  };
10
18
  events: {
11
19
  [evt: string]: CustomEvent<any>;
@@ -62,12 +62,8 @@
62
62
  <NodeViewWrapper class="fl-audio-player-wrapper">
63
63
  <div
64
64
  bind:this={targetElement}
65
- class="fl-audio-player"
65
+ class="fl-audio-player-container"
66
66
  class:selected={selected}
67
- style="
68
- --color-play: {attrs.colorPlay};
69
- --color-bar: {attrs.colorBar};
70
- "
71
67
  >
72
68
  <!-- <audio
73
69
  src={attrs.src}
@@ -76,7 +72,18 @@
76
72
  loop={attrs.loop}
77
73
  ></audio> -->
78
74
 
79
- <AudioPlayer src={attrs.src}></AudioPlayer>
75
+ <AudioPlayer
76
+ id={attrs.id}
77
+ controls={true}
78
+ src={attrs.src}
79
+ bgColor={attrs.bgColor}
80
+ textColor={attrs.textColor}
81
+ borderRadius={attrs.borderRadius}
82
+ accentColor={attrs.accentColor}
83
+ accentColorPaused={attrs.accentColorPaused}
84
+ colorPlay={attrs.colorPlay}
85
+ maxWidth={attrs.maxWidth}
86
+ ></AudioPlayer>
80
87
 
81
88
  {#if selected}
82
89
  <span
@@ -93,7 +100,7 @@
93
100
  </NodeViewWrapper>
94
101
 
95
102
  <style>
96
- .fl-audio-player {
103
+ .fl-audio-player-container {
97
104
  display: flex;
98
105
  align-items: center;
99
106
  position: relative;
@@ -1,6 +1,7 @@
1
1
  interface RenderOptions {
2
2
  json: any;
3
3
  customExtensions?: any[];
4
+ customNodeMapping?: any;
4
5
  }
5
- export declare function renderHTMLFromJSON({ json, customExtensions }: RenderOptions): string;
6
+ export declare function renderHTMLFromJSON({ json, customExtensions, customNodeMapping }: RenderOptions): string;
6
7
  export {};
@@ -1,25 +1,17 @@
1
1
  import { renderToHTMLString, serializeChildrenToHTMLString } from "@tiptap/static-renderer";
2
2
  import katex from "katex";
3
3
  import { getRichTextExtensions } from "./getExtensions";
4
- export function renderHTMLFromJSON({ json, customExtensions = [] }) {
5
- const extensions = getRichTextExtensions({ customExtensions });
6
- const html = renderToHTMLString({
7
- extensions: extensions, // using your extensions
8
- content: json,
9
- options: {
10
- nodeMapping: {
11
- // Aquí le dices cómo renderizar el nodo "mathematics"
12
- inlineMath({ node }) {
13
- const latex = node.attrs.latex || '';
14
- // Devuelve el HTML que quieres que se genere
15
- return `<span class="math-inline">${katex.renderToString(latex, { throwOnError: false })}</span>`;
16
- },
17
- MediaGridComponent({ node, children }) {
18
- const cols = node.attrs.cols || 2;
19
- const gap = node.attrs.gap || '1rem';
20
- const showIndicator = node.attrs.showIndicator || false;
21
- const indicatorType = node.attrs.indicatorType || 'numeric';
22
- return `
4
+ const nodeMapping = {
5
+ inlineMath({ node }) {
6
+ const latex = node.attrs.latex || '';
7
+ return `<span class="math-inline">${katex.renderToString(latex, { throwOnError: false })}</span>`;
8
+ },
9
+ MediaGridComponent({ node, children }) {
10
+ const cols = node.attrs.cols || 2;
11
+ const gap = node.attrs.gap || '1rem';
12
+ const showIndicator = node.attrs.showIndicator || false;
13
+ const indicatorType = node.attrs.indicatorType || 'numeric';
14
+ return `
23
15
  <div
24
16
  class="fl-media-grid"
25
17
  data-cols="${cols}"
@@ -32,21 +24,41 @@ export function renderHTMLFromJSON({ json, customExtensions = [] }) {
32
24
  ">
33
25
  ${serializeChildrenToHTMLString(children)}
34
26
  </div>`;
35
- },
36
- gridItem({ node, children }) {
37
- return `<div class="fl-grid-item">${serializeChildrenToHTMLString(children)}</div>`;
38
- },
39
- audio({ node, children }) {
40
- const src = node.attrs.src;
41
- const controls = node.attrs.controls;
42
- return `
43
- <fl-audio-player
44
- class="fl-audio-player"
45
- id="fl-audio-player-${node.attrs.id}"
46
- src="${src}">
47
- </fl-audio-player>`;
48
- }
49
- }
27
+ },
28
+ gridItem({ node, children }) {
29
+ return `<div class="fl-grid-item">${serializeChildrenToHTMLString(children)}</div>`;
30
+ },
31
+ audio({ node, children }) {
32
+ const { id, src, controls, bgColor, textColor, borderRadius, accentColor, accentColorPaused, maxWidth, colorPlay } = node.attrs;
33
+ return `
34
+ <fl-audio-player
35
+ class="fl-audio-player"
36
+ id="${id}"
37
+ src="${src}"
38
+ controls="${controls}"
39
+ bgColor="${bgColor}"
40
+ textColor="${textColor}"
41
+ borderRadius="${borderRadius}"
42
+ accentColor="${accentColor}"
43
+ accentColorPaused="${accentColorPaused}"
44
+ maxWidth="${maxWidth}"
45
+ colorPlay="${colorPlay}"
46
+ >
47
+ </fl-audio-player>
48
+ `;
49
+ },
50
+ };
51
+ export function renderHTMLFromJSON({ json, customExtensions = [], customNodeMapping = {} }) {
52
+ const extensions = getRichTextExtensions({ customExtensions });
53
+ const finalNodeMapping = {
54
+ ...nodeMapping,
55
+ ...customNodeMapping,
56
+ };
57
+ const html = renderToHTMLString({
58
+ extensions: extensions, // using your extensions
59
+ content: json,
60
+ options: {
61
+ nodeMapping: finalNodeMapping,
50
62
  }
51
63
  });
52
64
  return html;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flexiui/svelte-rich-text",
3
- "version": "0.0.36",
3
+ "version": "0.0.37",
4
4
  "description": "A lightweight and flexible rich text editor component for Svelte",
5
5
  "keywords": [
6
6
  "svelte",