@flexiui/svelte-rich-text 0.0.24 → 0.0.26
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/AudioPlayerSimple.svelte +7 -0
- package/dist/AudioPlayerSimple.svelte.d.ts +25 -0
- package/dist/RichText.svelte +110 -5
- package/dist/extensions/Audio.d.ts +29 -0
- package/dist/extensions/Audio.js +123 -0
- package/dist/extensions/AudioPlayer.svelte +622 -0
- package/dist/extensions/AudioPlayer.svelte.d.ts +20 -0
- package/dist/extensions/AudioPlayerWrapper.svelte +123 -0
- package/dist/extensions/AudioPlayerWrapper.svelte.d.ts +21 -0
- package/dist/extensions/MediaGrid/MediaGrid.d.ts +2 -0
- package/dist/extensions/MediaGrid/MediaGrid.js +90 -0
- package/dist/extensions/MediaGrid/MediaGrid.svelte +265 -0
- package/dist/extensions/MediaGrid/MediaGrid.svelte.d.ts +14 -0
- package/dist/extensions/MediaGrid/MediaGridItem.d.ts +2 -0
- package/dist/extensions/MediaGrid/MediaGridItem.js +24 -0
- package/dist/extensions/MediaGrid/MediaGridItem.svelte +484 -0
- package/dist/extensions/MediaGrid/MediaGridItem.svelte.d.ts +14 -0
- package/dist/extensions/MediaGrid/auth-service.d.ts +1 -0
- package/dist/extensions/MediaGrid/auth-service.js +11 -0
- package/dist/extensions/Table/CustomTableCell.d.ts +19 -0
- package/dist/extensions/Table/CustomTableCell.js +86 -0
- package/dist/extensions/Table/CustomTableHeader.d.ts +1 -0
- package/dist/extensions/Table/CustomTableHeader.js +33 -0
- package/dist/extensions/Table/TableCellControls.d.ts +0 -0
- package/dist/extensions/Table/TableCellControls.js +0 -0
- package/dist/extensions/Table/TableCellNodeView.svelte +576 -0
- package/dist/extensions/Table/TableCellNodeView.svelte.d.ts +14 -0
- package/dist/extensions/Table/TableCellSelection.d.ts +12 -0
- package/dist/extensions/Table/TableCellSelection.js +35 -0
- package/dist/extensions/audioStore.d.ts +1 -0
- package/dist/extensions/audioStore.js +2 -0
- package/dist/extensions/extensions.d.ts +7 -0
- package/dist/extensions/extensions.js +86 -0
- package/dist/styles.css +182 -0
- package/package.json +2 -1
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { NodeViewWrapper } from 'svelte-tiptap'
|
|
3
|
+
import type { NodeViewProps } from '@tiptap/core'
|
|
4
|
+
import AudioPlayer from './AudioPlayer.svelte';
|
|
5
|
+
import { onDestroy } from 'svelte';
|
|
6
|
+
|
|
7
|
+
export let node: NodeViewProps['node']
|
|
8
|
+
export let selected: NodeViewProps['selected'] // 👈 aquÃ
|
|
9
|
+
export let getPos: NodeViewProps['getPos']
|
|
10
|
+
export let editor: NodeViewProps['editor']
|
|
11
|
+
|
|
12
|
+
const attrs = node.attrs
|
|
13
|
+
|
|
14
|
+
export let targetElement: any = null;
|
|
15
|
+
|
|
16
|
+
let minWidth = 316;
|
|
17
|
+
let maxWidth = "100%";
|
|
18
|
+
|
|
19
|
+
let startX = 0;
|
|
20
|
+
let startWidth = 0;
|
|
21
|
+
|
|
22
|
+
function onMouseDown(e: MouseEvent) {
|
|
23
|
+
e.preventDefault();
|
|
24
|
+
|
|
25
|
+
if (!targetElement) return;
|
|
26
|
+
|
|
27
|
+
startX = e.clientX;
|
|
28
|
+
startWidth = targetElement.offsetWidth;
|
|
29
|
+
|
|
30
|
+
window.addEventListener("mousemove", onMouseMove);
|
|
31
|
+
window.addEventListener("mouseup", onMouseUp);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function onMouseMove(e: MouseEvent) {
|
|
35
|
+
if (!targetElement) return;
|
|
36
|
+
|
|
37
|
+
// 🔥 Obtenemos el DOM node de ProseMirror
|
|
38
|
+
const domNode = editor.view.nodeDOM(getPos()) as HTMLElement
|
|
39
|
+
|
|
40
|
+
const deltaX = (e.clientX - startX);
|
|
41
|
+
let newWidth = startWidth + deltaX;
|
|
42
|
+
|
|
43
|
+
if (newWidth < minWidth) {
|
|
44
|
+
newWidth = minWidth;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
domNode.style.maxWidth = `${newWidth}px`;
|
|
48
|
+
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function onMouseUp() {
|
|
52
|
+
window.removeEventListener("mousemove", onMouseMove);
|
|
53
|
+
window.removeEventListener("mouseup", onMouseUp);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
onDestroy(() => {
|
|
57
|
+
window.removeEventListener("mousemove", onMouseMove);
|
|
58
|
+
window.removeEventListener("mouseup", onMouseUp);
|
|
59
|
+
});
|
|
60
|
+
</script>
|
|
61
|
+
|
|
62
|
+
<NodeViewWrapper class="fl-audio-player-wrapper">
|
|
63
|
+
<div
|
|
64
|
+
bind:this={targetElement}
|
|
65
|
+
class="fl-audio-player"
|
|
66
|
+
class:selected={selected}
|
|
67
|
+
style="
|
|
68
|
+
--color-play: {attrs.colorPlay};
|
|
69
|
+
--color-bar: {attrs.colorBar};
|
|
70
|
+
"
|
|
71
|
+
>
|
|
72
|
+
<!-- <audio
|
|
73
|
+
src={attrs.src}
|
|
74
|
+
controls={attrs.controls}
|
|
75
|
+
autoplay={attrs.autoplay}
|
|
76
|
+
loop={attrs.loop}
|
|
77
|
+
></audio> -->
|
|
78
|
+
|
|
79
|
+
<AudioPlayer src={attrs.src}></AudioPlayer>
|
|
80
|
+
|
|
81
|
+
{#if selected}
|
|
82
|
+
<span
|
|
83
|
+
class="resize-grab"
|
|
84
|
+
role="button"
|
|
85
|
+
tabindex="0"
|
|
86
|
+
aria-label="Arrastra para cambiar el tamaño"
|
|
87
|
+
contenteditable="false"
|
|
88
|
+
on:mousedown={onMouseDown}
|
|
89
|
+
>
|
|
90
|
+
</span>
|
|
91
|
+
{/if}
|
|
92
|
+
</div>
|
|
93
|
+
</NodeViewWrapper>
|
|
94
|
+
|
|
95
|
+
<style>
|
|
96
|
+
.fl-audio-player {
|
|
97
|
+
display: flex;
|
|
98
|
+
align-items: center;
|
|
99
|
+
position: relative;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.resize-grab {
|
|
103
|
+
position: absolute;
|
|
104
|
+
right: -4px;
|
|
105
|
+
width: 6px;
|
|
106
|
+
background: #535bf2;
|
|
107
|
+
height: 50%;
|
|
108
|
+
border-radius: 13px;
|
|
109
|
+
cursor: col-resize;
|
|
110
|
+
display: flex;
|
|
111
|
+
align-items: center;
|
|
112
|
+
|
|
113
|
+
&::after {
|
|
114
|
+
content: "";
|
|
115
|
+
position: absolute;
|
|
116
|
+
width: 14px;
|
|
117
|
+
height: 14px;
|
|
118
|
+
left: -4px;
|
|
119
|
+
background: inherit;
|
|
120
|
+
border-radius: 100%;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
</style>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
import type { NodeViewProps } from '@tiptap/core';
|
|
3
|
+
declare const __propDef: {
|
|
4
|
+
props: {
|
|
5
|
+
node: NodeViewProps["node"];
|
|
6
|
+
selected: NodeViewProps["selected"];
|
|
7
|
+
getPos: NodeViewProps["getPos"];
|
|
8
|
+
editor: NodeViewProps["editor"];
|
|
9
|
+
targetElement?: any;
|
|
10
|
+
};
|
|
11
|
+
events: {
|
|
12
|
+
[evt: string]: CustomEvent<any>;
|
|
13
|
+
};
|
|
14
|
+
slots: {};
|
|
15
|
+
};
|
|
16
|
+
export type AudioPlayerWrapperProps = typeof __propDef.props;
|
|
17
|
+
export type AudioPlayerWrapperEvents = typeof __propDef.events;
|
|
18
|
+
export type AudioPlayerWrapperSlots = typeof __propDef.slots;
|
|
19
|
+
export default class AudioPlayerWrapper extends SvelteComponentTyped<AudioPlayerWrapperProps, AudioPlayerWrapperEvents, AudioPlayerWrapperSlots> {
|
|
20
|
+
}
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { Node, mergeAttributes } from '@tiptap/core';
|
|
2
|
+
import { SvelteNodeViewRenderer } from 'svelte-tiptap';
|
|
3
|
+
import MediaGridComponent from './MediaGrid.svelte';
|
|
4
|
+
export const MediaGridExtension = Node.create({
|
|
5
|
+
name: 'MediaGridComponent',
|
|
6
|
+
group: 'block',
|
|
7
|
+
content: 'gridItem+',
|
|
8
|
+
defining: true,
|
|
9
|
+
addAttributes() {
|
|
10
|
+
return {
|
|
11
|
+
class: {
|
|
12
|
+
default: "fl-media-grid",
|
|
13
|
+
parseHTML: element => element.getAttribute('class') || null,
|
|
14
|
+
renderHTML: attributes => {
|
|
15
|
+
if (!attributes.class)
|
|
16
|
+
return {};
|
|
17
|
+
return { class: attributes.class };
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
cols: {
|
|
21
|
+
default: 2,
|
|
22
|
+
parseHTML: element => parseInt(element.getAttribute('data-cols') || '2', 10),
|
|
23
|
+
renderHTML: attrs => ({ 'data-cols': attrs.cols }),
|
|
24
|
+
},
|
|
25
|
+
gap: {
|
|
26
|
+
default: '1rem',
|
|
27
|
+
parseHTML: element => element.getAttribute('data-gap') || '1rem',
|
|
28
|
+
renderHTML: attrs => ({ 'data-gap': attrs.gap }),
|
|
29
|
+
},
|
|
30
|
+
showIndicator: {
|
|
31
|
+
default: false,
|
|
32
|
+
parseHTML: element => element.getAttribute('data-show-indicator') || false,
|
|
33
|
+
renderHTML: attrs => ({ 'data-show-indicator': attrs.showIndicator }),
|
|
34
|
+
},
|
|
35
|
+
indicatorType: {
|
|
36
|
+
default: 'numeric', // 'numeric' | 'alphabetic'
|
|
37
|
+
parseHTML: element => element.getAttribute('data-indicator-type') || 'numeric',
|
|
38
|
+
renderHTML: attrs => ({ 'data-indicator-type': attrs.indicatorType }),
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
},
|
|
42
|
+
parseHTML() {
|
|
43
|
+
return [{ tag: 'media-grid-component' }];
|
|
44
|
+
},
|
|
45
|
+
renderHTML({ HTMLAttributes }) {
|
|
46
|
+
return ['div', mergeAttributes(HTMLAttributes), 0];
|
|
47
|
+
},
|
|
48
|
+
addCommands() {
|
|
49
|
+
return {
|
|
50
|
+
insertGrid: (options) => ({ tr, state, dispatch }) => {
|
|
51
|
+
const { schema } = state;
|
|
52
|
+
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
|
+
const items = Array.from({ length: cols }, () => schema.nodes.gridItem.create() // 👈 sin contenido
|
|
60
|
+
);
|
|
61
|
+
const grid = this.type.create({ cols }, items);
|
|
62
|
+
if (dispatch) {
|
|
63
|
+
tr.replaceSelectionWith(grid).scrollIntoView();
|
|
64
|
+
dispatch(tr);
|
|
65
|
+
}
|
|
66
|
+
return true;
|
|
67
|
+
},
|
|
68
|
+
addGridItem: () => ({ tr, state, dispatch }) => {
|
|
69
|
+
const { schema, selection } = state;
|
|
70
|
+
const { $from } = selection;
|
|
71
|
+
for (let depth = $from.depth; depth > 0; depth--) {
|
|
72
|
+
const node = $from.node(depth);
|
|
73
|
+
if (node.type.name === this.name) {
|
|
74
|
+
if (dispatch) {
|
|
75
|
+
const pos = $from.end(depth) - 1;
|
|
76
|
+
const gridItem = schema.nodes.gridItem.create();
|
|
77
|
+
tr.insert(pos, gridItem).scrollIntoView();
|
|
78
|
+
dispatch(tr);
|
|
79
|
+
}
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return false;
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
},
|
|
87
|
+
addNodeView() {
|
|
88
|
+
return SvelteNodeViewRenderer(MediaGridComponent);
|
|
89
|
+
},
|
|
90
|
+
});
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { NodeViewProps } from "@tiptap/core";
|
|
3
|
+
import cx from "clsx";
|
|
4
|
+
import { NodeViewContent, NodeViewWrapper } from "svelte-tiptap";
|
|
5
|
+
|
|
6
|
+
const { node, updateAttributes, selected, getPos, editor }: NodeViewProps = $props();
|
|
7
|
+
|
|
8
|
+
let cols = $state(node.attrs.cols || 2);
|
|
9
|
+
let gap = $state(node.attrs.gap || 1);
|
|
10
|
+
let showIndicator = $state(node.attrs.showIndicator || false);
|
|
11
|
+
let indicatorType = $state(node.attrs.indicatorType || 'numeric');
|
|
12
|
+
|
|
13
|
+
function handleColsChange(e) {
|
|
14
|
+
cols = e.target.value;
|
|
15
|
+
updateAttributes({ cols });
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function handleGapChange(e) {
|
|
19
|
+
gap = e.target.value;
|
|
20
|
+
updateAttributes({ gap });
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function handleShowIndicatorChange(e) {
|
|
24
|
+
showIndicator = e.target.checked;
|
|
25
|
+
updateAttributes({ showIndicator });
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function handleIndicatorTypeChange(e) {
|
|
29
|
+
indicatorType = e.target.value;
|
|
30
|
+
updateAttributes({ indicatorType });
|
|
31
|
+
}
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
<NodeViewWrapper
|
|
35
|
+
id="svelte-component"
|
|
36
|
+
data-selected={selected}
|
|
37
|
+
class={cx("fl-editor-custom-component svelte-component")}
|
|
38
|
+
data-drag-handle=""
|
|
39
|
+
>
|
|
40
|
+
<div class="flex fl-editor-component-header" contentEditable={false}>
|
|
41
|
+
|
|
42
|
+
<button
|
|
43
|
+
class="fl-add-grid-item-btn"
|
|
44
|
+
onclick={() => {
|
|
45
|
+
const pos = getPos();
|
|
46
|
+
if (typeof pos === "number") {
|
|
47
|
+
// Coloca el cursor dentro del grid (contentDOM)
|
|
48
|
+
editor
|
|
49
|
+
.chain()
|
|
50
|
+
.focus()
|
|
51
|
+
.setTextSelection(pos + 1) // 👈 entra dentro del content
|
|
52
|
+
.addGridItem()
|
|
53
|
+
.run();
|
|
54
|
+
} else {
|
|
55
|
+
editor.chain().focus().addGridItem().run();
|
|
56
|
+
}
|
|
57
|
+
}}
|
|
58
|
+
>
|
|
59
|
+
Add grid item
|
|
60
|
+
</button>
|
|
61
|
+
|
|
62
|
+
<div class="fl-editor-component-options">
|
|
63
|
+
<div class="fl-editor-component-option">
|
|
64
|
+
<label>
|
|
65
|
+
<span class="fl-editor-component-option-icon">
|
|
66
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" 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-columns"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M4 6l5.5 0"></path><path d="M4 10l5.5 0"></path><path d="M4 14l5.5 0"></path><path d="M4 18l5.5 0"></path><path d="M14.5 6l5.5 0"></path><path d="M14.5 10l5.5 0"></path><path d="M14.5 14l5.5 0"></path><path d="M14.5 18l5.5 0"></path></svg>
|
|
67
|
+
</span>
|
|
68
|
+
<input
|
|
69
|
+
class="fl-editor-option-input input-number option--cols"
|
|
70
|
+
oninput={handleColsChange}
|
|
71
|
+
type="number"
|
|
72
|
+
id="cols"
|
|
73
|
+
value={cols}
|
|
74
|
+
min="1"
|
|
75
|
+
max="10"
|
|
76
|
+
step="1"
|
|
77
|
+
/>
|
|
78
|
+
</label>
|
|
79
|
+
</div>
|
|
80
|
+
|
|
81
|
+
<div class="fl-editor-component-option">
|
|
82
|
+
<label>
|
|
83
|
+
<span class="fl-editor-component-option-icon">
|
|
84
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="19" height="19" 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-spacing-horizontal"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M20 20h-2a2 2 0 0 1 -2 -2v-12a2 2 0 0 1 2 -2h2" /><path d="M4 20h2a2 2 0 0 0 2 -2v-12a2 2 0 0 0 -2 -2h-2" /><path d="M12 8v8" /></svg>
|
|
85
|
+
</span>
|
|
86
|
+
<input
|
|
87
|
+
class="fl-editor-option-input input-text option--gap"
|
|
88
|
+
oninput={handleGapChange}
|
|
89
|
+
type="text"
|
|
90
|
+
id="gap"
|
|
91
|
+
value={gap}
|
|
92
|
+
/>
|
|
93
|
+
</label>
|
|
94
|
+
</div>
|
|
95
|
+
|
|
96
|
+
<div class="fl-editor-component-option m-l-small">
|
|
97
|
+
<label>
|
|
98
|
+
<input
|
|
99
|
+
class="fl-editor-option-input input-checkbox option--show-indicator"
|
|
100
|
+
oninput={handleShowIndicatorChange}
|
|
101
|
+
type="checkbox"
|
|
102
|
+
id="show-indicator"
|
|
103
|
+
value={showIndicator}
|
|
104
|
+
/>
|
|
105
|
+
Show indicators
|
|
106
|
+
</label>
|
|
107
|
+
</div>
|
|
108
|
+
|
|
109
|
+
{#if showIndicator}
|
|
110
|
+
<div class="fl-editor-component-option">
|
|
111
|
+
<label>
|
|
112
|
+
<select id="indicator-type" value={indicatorType} onchange={handleIndicatorTypeChange}>
|
|
113
|
+
<option value="numeric">Numeric</option>
|
|
114
|
+
<option value="alphabetic">Alphabetic</option>
|
|
115
|
+
</select>
|
|
116
|
+
</label>
|
|
117
|
+
</div>
|
|
118
|
+
{/if}
|
|
119
|
+
</div>
|
|
120
|
+
</div>
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
<!-- <div class="fl-grid" >
|
|
124
|
+
{#each Array(node.childCount) as _, i}
|
|
125
|
+
<div class="fl-grid-item">
|
|
126
|
+
<span class="fl-grid-item-badge">
|
|
127
|
+
{i + 1}
|
|
128
|
+
</span>
|
|
129
|
+
<img src="https://template.tiptap.dev/images/tiptap-ui-placeholder-image.jpg" alt="Imagen de ejemplo" />
|
|
130
|
+
<div class="fl-grid-item-actions">
|
|
131
|
+
<button type="button" onclick={() => {
|
|
132
|
+
editor.commands.addGridItem();
|
|
133
|
+
}}>
|
|
134
|
+
Add
|
|
135
|
+
</button>
|
|
136
|
+
</div>
|
|
137
|
+
</div>
|
|
138
|
+
{/each}
|
|
139
|
+
|
|
140
|
+
</div> -->
|
|
141
|
+
|
|
142
|
+
<NodeViewContent
|
|
143
|
+
class="media-grid-view-content"
|
|
144
|
+
style="
|
|
145
|
+
--fl-grid-cols: {cols};
|
|
146
|
+
--fl-grid-gap: {gap};
|
|
147
|
+
"
|
|
148
|
+
/>
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
<!-- <div class="fl-editor-component-option">
|
|
153
|
+
<button type="button" onclick={addItem}> Add item </button>
|
|
154
|
+
</div> -->
|
|
155
|
+
|
|
156
|
+
</NodeViewWrapper>
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
<style>
|
|
161
|
+
.placeholder {
|
|
162
|
+
opacity: 0.4;
|
|
163
|
+
border: 1px dashed #aaa;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.fl-editor-component-header {
|
|
167
|
+
display: flex;
|
|
168
|
+
gap: 10px;
|
|
169
|
+
margin-bottom: 1rem;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
.fl-add-grid-item-btn {
|
|
173
|
+
padding: 6px 15px;
|
|
174
|
+
border-radius: 12px;
|
|
175
|
+
border: none;
|
|
176
|
+
background: #6b6b6b;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.fl-editor-component-options {
|
|
180
|
+
display: flex;
|
|
181
|
+
align-items: center;
|
|
182
|
+
gap: 8px;
|
|
183
|
+
font-size: 14px;
|
|
184
|
+
color: #ffffffc2;
|
|
185
|
+
background-color: #2a2a2a00;
|
|
186
|
+
backdrop-filter: blur(10px);
|
|
187
|
+
padding: 6px 8px;
|
|
188
|
+
border-radius: 12px;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
.fl-editor-component-option {
|
|
192
|
+
& label {
|
|
193
|
+
display: flex;
|
|
194
|
+
align-items: center;
|
|
195
|
+
gap: 8px;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
& .fl-editor-component-option-icon {
|
|
199
|
+
display: flex;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
&.m-l-small {
|
|
203
|
+
margin-left: 4px;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
select {
|
|
207
|
+
background-color: #131313;
|
|
208
|
+
border: none;
|
|
209
|
+
padding: 3px 2px;
|
|
210
|
+
outline: none;
|
|
211
|
+
|
|
212
|
+
&:focus {
|
|
213
|
+
text-decoration: underline;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.fl-editor-option-input {
|
|
219
|
+
|
|
220
|
+
&.input-number, &.input-text {
|
|
221
|
+
border: none;
|
|
222
|
+
background: #7e7e7e80;
|
|
223
|
+
padding: 6px 7px;
|
|
224
|
+
border-radius: 8px;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
&.option--cols {
|
|
228
|
+
width: 32px;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
&.option--gap {
|
|
232
|
+
width: 74px;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
&.input-checkbox {
|
|
236
|
+
width: 15px;
|
|
237
|
+
margin: 0;
|
|
238
|
+
height: 15px;
|
|
239
|
+
accent-color: #535bf2;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
.fl-grid-item-badge {
|
|
245
|
+
position: absolute;
|
|
246
|
+
left: 10px;
|
|
247
|
+
top: 10px;
|
|
248
|
+
background: #535bf2;
|
|
249
|
+
width: 30px;
|
|
250
|
+
height: 30px;
|
|
251
|
+
display: flex;
|
|
252
|
+
align-items: center;
|
|
253
|
+
justify-content: center;
|
|
254
|
+
font-weight: 600;
|
|
255
|
+
border-radius: 100%;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
.fl-grid-item-actions {
|
|
259
|
+
display: flex;
|
|
260
|
+
gap: 10px;
|
|
261
|
+
position: absolute;
|
|
262
|
+
top: 10px;
|
|
263
|
+
right: 10px;
|
|
264
|
+
}
|
|
265
|
+
</style>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: Record<string, never>;
|
|
4
|
+
events: {
|
|
5
|
+
[evt: string]: CustomEvent<any>;
|
|
6
|
+
};
|
|
7
|
+
slots: {};
|
|
8
|
+
};
|
|
9
|
+
export type MediaGridProps = typeof __propDef.props;
|
|
10
|
+
export type MediaGridEvents = typeof __propDef.events;
|
|
11
|
+
export type MediaGridSlots = typeof __propDef.slots;
|
|
12
|
+
export default class MediaGrid extends SvelteComponentTyped<MediaGridProps, MediaGridEvents, MediaGridSlots> {
|
|
13
|
+
}
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Node, mergeAttributes } from '@tiptap/core';
|
|
2
|
+
import { SvelteNodeViewRenderer } from 'svelte-tiptap';
|
|
3
|
+
import MediaGridItemComponent from './MediaGridItem.svelte';
|
|
4
|
+
export const MediaGridItemExtension = Node.create({
|
|
5
|
+
name: 'gridItem',
|
|
6
|
+
content: 'image?', // 👈 solo permite un nodo image
|
|
7
|
+
selectable: true,
|
|
8
|
+
parseHTML() {
|
|
9
|
+
return [{ tag: 'div[data-type="grid-item"]' }];
|
|
10
|
+
},
|
|
11
|
+
renderHTML({ HTMLAttributes }) {
|
|
12
|
+
return [
|
|
13
|
+
'div',
|
|
14
|
+
mergeAttributes(HTMLAttributes, {
|
|
15
|
+
'data-type': 'grid-item',
|
|
16
|
+
class: 'fl-grid-item',
|
|
17
|
+
}),
|
|
18
|
+
0,
|
|
19
|
+
];
|
|
20
|
+
},
|
|
21
|
+
addNodeView() {
|
|
22
|
+
return SvelteNodeViewRenderer(MediaGridItemComponent);
|
|
23
|
+
},
|
|
24
|
+
});
|