@flexiui/svelte-rich-text 0.0.36 → 0.0.38

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,95 @@ 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
47
  }),
48
48
  },
49
- colorBar: {
50
- default: '#888',
51
- parseHTML: el => el.getAttribute('data-color-bar') || '#888',
49
+ bgColor: {
50
+ default: '#8c8c8c45',
51
+ parseHTML: el => el.getAttribute('data-bg-color'),
52
52
  renderHTML: attrs => ({
53
- 'data-color-bar': attrs.colorBar,
53
+ 'data-bg-color': attrs.bgColor,
54
+ }),
55
+ },
56
+ textColor: {
57
+ default: 'currentColor',
58
+ parseHTML: el => el.getAttribute('data-text-color'),
59
+ renderHTML: attrs => ({
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
+ playBtnBgColor: {
92
+ default: '#8d8d8d26',
93
+ parseHTML: el => el.getAttribute('data-play-btn-bg-color'),
94
+ renderHTML: attrs => ({
95
+ 'data-play-btn-bg-color': attrs.playBtnBgColor,
96
+ }),
97
+ },
98
+ playBtnTextColor: {
99
+ default: 'currentColor',
100
+ parseHTML: el => el.getAttribute('data-play-btn-text-color'),
101
+ renderHTML: attrs => ({
102
+ 'data-play-btn-text-color': attrs.playBtnTextColor,
103
+ }),
104
+ },
105
+ colorPlay: {
106
+ default: '#5d5d5dc9',
107
+ parseHTML: el => el.getAttribute('data-color-play'),
108
+ renderHTML: attrs => ({
109
+ 'data-color-play': attrs.colorPlay,
54
110
  }),
55
111
  },
56
112
  maxWidth: {
57
113
  default: '100%',
58
- parseHTML: el => el.getAttribute('data-max-width') || '100%',
114
+ parseHTML: el => el.getAttribute('data-max-width'),
59
115
  renderHTML: attrs => ({
60
116
  'data-max-width': attrs.maxWidth,
61
117
  }),
62
118
  },
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
119
  };
71
120
  },
72
121
  parseHTML() {
73
122
  return [
74
123
  {
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
- },
124
+ tag: 'fl-audio-player',
89
125
  },
90
126
  ];
91
127
  },
92
128
  renderHTML({ HTMLAttributes }) {
93
129
  return [
94
- 'audio-player',
130
+ 'fl-audio-player',
95
131
  mergeAttributes(this.options.HTMLAttributes, HTMLAttributes),
96
132
  ];
97
133
  },
@@ -7,18 +7,29 @@
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 playBtnBgColor: string;
22
+ export let playBtnTextColor: string;
23
+ export let colorPlay: string;
24
+ export let maxWidth: string;
16
25
 
17
26
  let wavesurfer: WaveSurfer | null = null;
18
27
  let waveformEl: HTMLDivElement | null = null;
19
28
  let wavesurferReady: boolean = false;
20
29
  let loading: boolean = true;
21
- let audio: any = null;
30
+ // let audio: any = null;
31
+ let audio: HTMLAudioElement | null = null;
32
+
22
33
  let playing: boolean = false;
23
34
  let mounted: boolean = false;
24
35
  let seekbarEl: HTMLDivElement | null = null;
@@ -31,6 +42,8 @@
31
42
  let audioDuration: number = 0;
32
43
  let audioCurrentTime: number = 0;
33
44
 
45
+ id = id + "-" + Math.random().toString(36).substring(2, 15);
46
+
34
47
  function formatTime(seconds: number) {
35
48
  if (isNaN(seconds) || seconds < 0) return "0:00";
36
49
 
@@ -152,10 +165,10 @@
152
165
  // wavesurfer?.stop();
153
166
  // });
154
167
 
155
- audio = new Audio(src);
168
+ // audio = new Audio(src);
169
+ // audio.load();
156
170
  audio.volume = volume;
157
171
  audio.preload = "auto";
158
- audio.load();
159
172
 
160
173
  audio.addEventListener("loadedmetadata", () => {
161
174
  audioDuration = audio.duration;
@@ -173,6 +186,19 @@
173
186
  }
174
187
  });
175
188
 
189
+ audio.onended = () => {
190
+ playing = false;
191
+ console.log("Audio playback ended");
192
+ };
193
+
194
+ audio.addEventListener("play", () => {
195
+ playing = true;
196
+ });
197
+
198
+ audio.addEventListener("pause", () => {
199
+ playing = false;
200
+ });
201
+
176
202
  setTimeout(() => {
177
203
  loading = false;
178
204
  }, 500);
@@ -262,7 +288,20 @@
262
288
  }
263
289
  </script>
264
290
 
265
- <div class="audio-player" {id} class:playing>
291
+ <div
292
+ class="audio-player"
293
+ {id}
294
+ class:playing
295
+ style={`
296
+ --player-bg-color: ${bgColor};
297
+ --player-play-btn-bg: ${playBtnBgColor};
298
+ --player-play-btn-color: ${playBtnTextColor};
299
+ --player-primary-color: ${accentColor};
300
+ --player-progress-default-bg: ${accentColorPaused};
301
+ --player-text-color: ${textColor};
302
+ --player-border-radius: ${borderRadius};
303
+ `}
304
+ >
266
305
  <button
267
306
  onclick={() => togglePlayPause()}
268
307
  type="button"
@@ -441,11 +480,12 @@
441
480
  </div>
442
481
  </div>
443
482
 
444
- <!-- {#if mounted && !wavesurferReady}
445
- <div class="audio-player-time">
446
- 0:51
447
- </div>
448
- {/if} -->
483
+ <!-- Reproductor de audo nativo -->
484
+ <audio
485
+ bind:this={audio}
486
+ src={src}
487
+ id={'native-audio-' + id}
488
+ ></audio>
449
489
  </div>
450
490
 
451
491
  <style>
@@ -456,13 +496,14 @@
456
496
 
457
497
  .audio-player {
458
498
  --player-primary-color: #5e17eb;
459
- --player-bg-color: #455f7414;
499
+ --player-bg-color: #8c8c8c45;
460
500
  --player-border-radius: 18px;
461
501
  --player-seekbar-bg: #8d8d8d3a;
462
502
  --player-seekbar-height: 6px;
463
503
  --player-progress-default-bg: #f5f5f5;
464
504
  --player-play-btn-bg: #8d8d8d26;
465
505
  --player-play-btn-color: #fff;
506
+ --player-text-color: currentColor;
466
507
 
467
508
  display: flex;
468
509
  align-items: center;
@@ -472,6 +513,7 @@
472
513
  padding: 12px;
473
514
  width: 100%;
474
515
  box-sizing: border-box;
516
+ color: var(--player-text-color);
475
517
 
476
518
  &.playing {
477
519
  .audio-player-wave {
@@ -496,6 +538,16 @@
496
538
  border-radius: 100%;
497
539
  outline-offset: 4px;
498
540
  outline-color: var(--player-play-btn-bg);
541
+ cursor: pointer;
542
+ transition: filter 0.3s ease, transform 0.3s ease, background 0.3s ease;
543
+
544
+ &:hover {
545
+ /* background: var(--player-primary-color); */
546
+ &:not(.playing) {
547
+ filter: brightness(1.2);
548
+ }
549
+ transform: scale(1.06);
550
+ }
499
551
 
500
552
  svg {
501
553
  width: 20px;
@@ -587,7 +639,7 @@
587
639
  margin-right: 4px;
588
640
 
589
641
  &:hover {
590
- background: #0d121612;
642
+ background: #7a7a7a17;
591
643
  }
592
644
 
593
645
  &:hover .audio-player-seekbar,
@@ -621,6 +673,7 @@
621
673
  border: none;
622
674
  padding: 4px;
623
675
  background: #0d121600;
676
+ color: currentColor;
624
677
  border-radius: 100%;
625
678
  height: 36px;
626
679
  width: 36px;
@@ -1,11 +1,21 @@
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
+ playBtnBgColor: string;
16
+ playBtnTextColor: string;
17
+ colorPlay: string;
18
+ maxWidth: string;
9
19
  };
10
20
  events: {
11
21
  [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,20 @@
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
+ playBtnBgColor={attrs.playBtnBgColor}
85
+ playBtnTextColor={attrs.playBtnTextColor}
86
+ colorPlay={attrs.colorPlay}
87
+ maxWidth={attrs.maxWidth}
88
+ ></AudioPlayer>
80
89
 
81
90
  {#if selected}
82
91
  <span
@@ -93,7 +102,7 @@
93
102
  </NodeViewWrapper>
94
103
 
95
104
  <style>
96
- .fl-audio-player {
105
+ .fl-audio-player-container {
97
106
  display: flex;
98
107
  align-items: center;
99
108
  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,43 @@ 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, playBtnBgColor, playBtnTextColor, 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
+ playBtnBgColor="${playBtnBgColor}"
45
+ playBtnTextColor="${playBtnTextColor}"
46
+ maxWidth="${maxWidth}"
47
+ colorPlay="${colorPlay}"
48
+ >
49
+ </fl-audio-player>
50
+ `;
51
+ },
52
+ };
53
+ export function renderHTMLFromJSON({ json, customExtensions = [], customNodeMapping = {} }) {
54
+ const extensions = getRichTextExtensions({ customExtensions });
55
+ const finalNodeMapping = {
56
+ ...nodeMapping,
57
+ ...customNodeMapping,
58
+ };
59
+ const html = renderToHTMLString({
60
+ extensions: extensions, // using your extensions
61
+ content: json,
62
+ options: {
63
+ nodeMapping: finalNodeMapping,
50
64
  }
51
65
  });
52
66
  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.38",
4
4
  "description": "A lightweight and flexible rich text editor component for Svelte",
5
5
  "keywords": [
6
6
  "svelte",