@widgetic/editor 4.0.6 → 4.0.7
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/components/WidgetPreview.svelte +10 -0
- package/dist/components/WidgetPreview.svelte.d.ts +3 -0
- package/dist/components/editors/EmbedEditor.svelte +101 -530
- package/dist/components/editors/EmbedEditor.svelte.d.ts +7 -17
- package/dist/components/editors/PropsEditor.svelte +187 -85
- package/dist/components/editors/PropsEditor.svelte.d.ts +10 -0
- package/dist/components/ic/ColorPickerInputController.svelte +0 -2
- package/dist/components/ic/ColorPickerInputController.svelte.d.ts +0 -2
- package/dist/components/ic/DropdownInputController.svelte +32 -7
- package/dist/components/ic/FontInputController.svelte +25 -8
- package/dist/components/ic/InputControllerRenderer.svelte +98 -0
- package/dist/components/ic/InputControllerRenderer.svelte.d.ts +40 -0
- package/dist/components/ic/RoundedCornersInputController.svelte +5 -15
- package/dist/components/ic/RoundedCornersInputController.svelte.d.ts +0 -2
- package/dist/components/ic/TextAreaInputController.svelte +26 -13
- package/dist/components/icons/locked.svelte +5 -1
- package/dist/components/icons/locked.svelte.d.ts +11 -24
- package/dist/components/icons/unlocked.svelte +5 -1
- package/dist/components/icons/unlocked.svelte.d.ts +11 -24
- package/dist/utils/FontManager.js +10 -3
- package/package.json +10 -9
|
@@ -1,237 +1,52 @@
|
|
|
1
|
-
<!--
|
|
1
|
+
<!--
|
|
2
2
|
/**
|
|
3
3
|
* EmbedEditor Component
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* - Visual code highlighting for better readability
|
|
8
|
-
* - Integrated property customization via PropsEditor
|
|
9
|
-
* - Responsive design with configurable dimensions
|
|
10
|
-
*
|
|
11
|
-
* Note: Requires a valid embedSchema for property customization
|
|
4
|
+
* Adds a copyable embed code panel to PropsEditor's shared shell.
|
|
5
|
+
* PropsEditor owns the toolbar, Save control, property fields and drag behavior.
|
|
6
|
+
* Persistence remains the parent's responsibility through the save event.
|
|
12
7
|
*/
|
|
13
|
-
|
|
14
|
-
<
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* SVELTE IMPORTS
|
|
18
|
-
*/
|
|
19
|
-
import { onMount, createEventDispatcher, onDestroy } from 'svelte';
|
|
20
|
-
|
|
21
|
-
const dispatch = createEventDispatcher();
|
|
8
|
+
-->
|
|
9
|
+
<svelte:options runes={false} />
|
|
22
10
|
|
|
23
|
-
|
|
24
|
-
import {
|
|
25
|
-
|
|
26
|
-
// Add OK icon import
|
|
11
|
+
<script lang="ts">
|
|
12
|
+
import { onMount } from 'svelte';
|
|
13
|
+
import { toast, CopyableHeader } from '@widgetic/design-system/components';
|
|
27
14
|
import OK from '../icons/ok.svelte';
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* LOCAL SVELTE COMPONENTS IMPORTS
|
|
31
|
-
*/
|
|
32
15
|
import PropsEditor from './PropsEditor.svelte';
|
|
33
16
|
|
|
34
|
-
/**
|
|
35
|
-
* SHADCN COMPONENTS
|
|
36
|
-
*/
|
|
37
|
-
import { Button, ScrollArea } from '@widgetic/design-system/components';
|
|
38
|
-
|
|
39
|
-
// Add DragHandle import
|
|
40
|
-
import DragHandle from '../icons/drag.svelte';
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Component Configuration Props
|
|
44
|
-
* width/height: Control overall component dimensions
|
|
45
|
-
* headerHeight: Space allocated for embed code display section
|
|
46
|
-
* embedSchema: Defines customizable properties for the embedded widget
|
|
47
|
-
*
|
|
48
|
-
* Note: headerHeight affects the vertical space distribution between
|
|
49
|
-
* the embed code display and property editor sections
|
|
50
|
-
*/
|
|
17
|
+
/** Component configuration — existing public props and methods are preserved. */
|
|
51
18
|
let className = '';
|
|
52
19
|
export { className as class };
|
|
53
20
|
export let style = '';
|
|
54
|
-
// header embed props
|
|
55
21
|
export let embedHeaderText = 'Embed code';
|
|
56
22
|
export let embedCode = '';
|
|
57
|
-
// editor props
|
|
58
23
|
export let height = 720;
|
|
59
|
-
// export let headerHeight = 215;
|
|
60
|
-
//
|
|
61
24
|
export let embedSchema: any;
|
|
62
25
|
// Initial values for embed options (overrides schema defaultValue)
|
|
63
26
|
export let initialValues: Record<string, any> = {};
|
|
64
27
|
// When false, skip the outer full-page dark wrapper (for embedding inside another layout)
|
|
65
28
|
export let standalone = true;
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
|
|
70
|
-
*/
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
//
|
|
74
|
-
let
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
let initialMousePos = { x: 0, y: 0 };
|
|
79
|
-
let initialEditorPos = { left: 0, top: 0 };
|
|
80
|
-
let embedEditorElement: HTMLElement | null = null;
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* ON MOUNT
|
|
84
|
-
*/
|
|
85
|
-
onMount(() => {
|
|
86
|
-
// console.log('EMBED EDITOR Mounted!');
|
|
87
|
-
|
|
88
|
-
// show loader while fetching schemas
|
|
89
|
-
// loading = true;
|
|
90
|
-
|
|
91
|
-
// hide loader
|
|
92
|
-
loading = false;
|
|
93
|
-
|
|
94
|
-
// Setup draggable functionality for EmbedEditor after loading
|
|
95
|
-
setTimeout(setupDraggable, 300);
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
// Add cleanup for event listeners
|
|
99
|
-
onDestroy(() => {
|
|
100
|
-
document.removeEventListener('mousemove', handleMouseMove);
|
|
101
|
-
document.removeEventListener('mouseup', handleMouseUp);
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
// Add the draggable setup function
|
|
105
|
-
function setupDraggable() {
|
|
106
|
-
// Find the EmbedEditor element
|
|
107
|
-
embedEditorElement = document.querySelector('.embed-editor-container');
|
|
108
|
-
|
|
109
|
-
if (!embedEditorElement) return;
|
|
110
|
-
|
|
111
|
-
// Find the existing drag handle container
|
|
112
|
-
const dragHandleContainer = embedEditorElement.querySelector('.drag-handle-container') as HTMLElement;
|
|
113
|
-
|
|
114
|
-
if (dragHandleContainer) {
|
|
115
|
-
// Only add the mousedown event to the drag handle container
|
|
116
|
-
dragHandleContainer.addEventListener('mousedown', handleMouseDown as EventListener);
|
|
117
|
-
|
|
118
|
-
// Make the drag handle container always visible
|
|
119
|
-
dragHandleContainer.style.opacity = '0';
|
|
120
|
-
|
|
121
|
-
// Increase opacity on hover
|
|
122
|
-
dragHandleContainer.addEventListener('mouseenter', () => {
|
|
123
|
-
dragHandleContainer.style.opacity = '1';
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
dragHandleContainer.addEventListener('mouseleave', () => {
|
|
127
|
-
dragHandleContainer.style.opacity = '0';
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// Remove the need for mouse enter/leave to show drag handle
|
|
132
|
-
embedEditorElement.removeEventListener('mouseenter', handleHeaderMouseEnter);
|
|
133
|
-
embedEditorElement.removeEventListener('mouseleave', handleHeaderMouseLeave);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// Mouse event handlers for dragging
|
|
137
|
-
function handleMouseDown(e: MouseEvent) {
|
|
138
|
-
e.preventDefault();
|
|
139
|
-
|
|
140
|
-
if (!embedEditorElement) return;
|
|
141
|
-
|
|
142
|
-
isDragging = true;
|
|
143
|
-
|
|
144
|
-
// Get initial mouse position
|
|
145
|
-
initialMousePos = { x: e.clientX, y: e.clientY };
|
|
146
|
-
|
|
147
|
-
// Get the current position of the editor
|
|
148
|
-
const rect = embedEditorElement.getBoundingClientRect();
|
|
149
|
-
|
|
150
|
-
// Get the computed style
|
|
151
|
-
const computedStyle = window.getComputedStyle(embedEditorElement);
|
|
152
|
-
|
|
153
|
-
// Check the current position type
|
|
154
|
-
const currentPosition = computedStyle.position;
|
|
155
|
-
|
|
156
|
-
// Set the editor position to absolute and calculate initial position
|
|
157
|
-
embedEditorElement.style.position = 'absolute';
|
|
158
|
-
|
|
159
|
-
// If it's the first time we're dragging, set up initial position
|
|
160
|
-
if (currentPosition !== 'absolute') {
|
|
161
|
-
// Convert to absolute positioning without changing the visual position
|
|
162
|
-
embedEditorElement.style.margin = '0';
|
|
163
|
-
embedEditorElement.style.width = `${rect.width}px`;
|
|
164
|
-
embedEditorElement.style.height = `${rect.height}px`;
|
|
165
|
-
|
|
166
|
-
// Get the parent element's computed style
|
|
167
|
-
const parentElement = embedEditorElement.parentElement;
|
|
168
|
-
const parentRect = parentElement ? parentElement.getBoundingClientRect() : { left: 0, top: 0 };
|
|
169
|
-
|
|
170
|
-
// Calculate initial absolute position with parent offset
|
|
171
|
-
const initialLeft = rect.left - parentRect.left;
|
|
172
|
-
const initialTop = rect.top - parentRect.top;
|
|
173
|
-
|
|
174
|
-
// Set the initial position
|
|
175
|
-
embedEditorElement.style.left = `${initialLeft}px`;
|
|
176
|
-
embedEditorElement.style.top = `${initialTop}px`;
|
|
177
|
-
|
|
178
|
-
// Store initial values for drag calculation
|
|
179
|
-
initialEditorPos = {
|
|
180
|
-
left: initialLeft,
|
|
181
|
-
top: initialTop
|
|
182
|
-
};
|
|
183
|
-
} else {
|
|
184
|
-
// If already absolute, use current left/top values
|
|
185
|
-
initialEditorPos = {
|
|
186
|
-
left: parseInt(computedStyle.left) || 0,
|
|
187
|
-
top: parseInt(computedStyle.top) || 0
|
|
188
|
-
};
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
// Add the document event listeners
|
|
192
|
-
document.addEventListener('mousemove', handleMouseMove);
|
|
193
|
-
document.addEventListener('mouseup', handleMouseUp);
|
|
194
|
-
|
|
195
|
-
// Change cursor during dragging
|
|
196
|
-
document.body.style.cursor = 'move';
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
function handleMouseMove(e: MouseEvent) {
|
|
200
|
-
if (!isDragging || !embedEditorElement) return;
|
|
201
|
-
|
|
202
|
-
// Calculate the movement delta
|
|
203
|
-
const dx = e.clientX - initialMousePos.x;
|
|
204
|
-
const dy = e.clientY - initialMousePos.y;
|
|
205
|
-
|
|
206
|
-
// Update position based on original position plus delta
|
|
207
|
-
embedEditorElement.style.left = `${initialEditorPos.left + dx}px`;
|
|
208
|
-
embedEditorElement.style.top = `${initialEditorPos.top + dy}px`;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
function handleMouseUp() {
|
|
212
|
-
if (!isDragging) return;
|
|
213
|
-
|
|
214
|
-
isDragging = false;
|
|
215
|
-
|
|
216
|
-
// Remove the document event listeners
|
|
217
|
-
document.removeEventListener('mousemove', handleMouseMove);
|
|
218
|
-
document.removeEventListener('mouseup', handleMouseUp);
|
|
219
|
-
|
|
220
|
-
// Reset cursor
|
|
221
|
-
document.body.style.cursor = '';
|
|
222
|
-
}
|
|
29
|
+
/** Show Save status control in the shared drag bar (composition embed overlay). */
|
|
30
|
+
export let showSaveButton = false;
|
|
31
|
+
/** True when local embed option edits are not yet persisted. */
|
|
32
|
+
export let saveDirty = false;
|
|
33
|
+
/** True while a save request is in flight. */
|
|
34
|
+
export let saveSaving = false;
|
|
35
|
+
|
|
36
|
+
// Loading is currently local initialization; preserve the loading/error presentation.
|
|
37
|
+
let loading = true;
|
|
38
|
+
let wrapperElement = null;
|
|
39
|
+
let internalPropsEditorRef = null;
|
|
40
|
+
onMount(() => { loading = false; });
|
|
223
41
|
|
|
224
42
|
/**
|
|
225
43
|
* Clipboard Interaction Handlers
|
|
226
44
|
* Provides copy functionality via the copy button
|
|
227
45
|
* with visual feedback via toast notifications
|
|
228
46
|
*/
|
|
229
|
-
// Add this helper function at the top of your script
|
|
230
47
|
let isToastVisible = false;
|
|
231
|
-
|
|
232
48
|
function showToast(type: 'success' | 'error', message: string, options = {}) {
|
|
233
49
|
if (isToastVisible) return;
|
|
234
|
-
|
|
235
50
|
isToastVisible = true;
|
|
236
51
|
toast[type](message, {
|
|
237
52
|
...options,
|
|
@@ -244,226 +59,96 @@ function showToast(type: 'success' | 'error', message: string, options = {}) {
|
|
|
244
59
|
description: 'embed-editor-toast-description',
|
|
245
60
|
closeButton: 'embed-editor-toast-close-button'
|
|
246
61
|
},
|
|
247
|
-
onAutoClose: () => {
|
|
248
|
-
|
|
249
|
-
},
|
|
250
|
-
onDismiss: () => {
|
|
251
|
-
isToastVisible = false;
|
|
252
|
-
}
|
|
62
|
+
onAutoClose: () => { isToastVisible = false; },
|
|
63
|
+
onDismiss: () => { isToastVisible = false; }
|
|
253
64
|
});
|
|
254
65
|
}
|
|
255
66
|
|
|
256
|
-
/**
|
|
257
|
-
* Component State Management
|
|
258
|
-
* loading: Prevents premature rendering while initializing
|
|
259
|
-
* embedCodeHeaderRef: References header for DOM measurements
|
|
260
|
-
*
|
|
261
|
-
* Note: Currently loading is simplified as there's no actual data fetching,
|
|
262
|
-
* but the structure supports future async operations
|
|
263
|
-
*/
|
|
264
|
-
|
|
265
|
-
/**
|
|
266
|
-
* Layout Structure
|
|
267
|
-
* The component is organized in layers:
|
|
268
|
-
* 1. Border overlay (z-index: -102)
|
|
269
|
-
* 2. Embed code header (z-index: 100)
|
|
270
|
-
* 3. Props editor (z-index: 10)
|
|
271
|
-
*
|
|
272
|
-
* This layering ensures proper visual hierarchy and interaction handling
|
|
273
|
-
*/
|
|
274
|
-
|
|
275
|
-
// These functions are no longer needed since we're making the drag handle always visible
|
|
276
|
-
// But we'll keep them for compatibility with any code that might call them
|
|
277
|
-
function handleHeaderMouseEnter() {
|
|
278
|
-
isDragHandleVisible = true;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
function handleHeaderMouseLeave() {
|
|
282
|
-
isDragHandleVisible = false;
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
/** Root wrapper element ref for programmatic positioning */
|
|
286
|
-
let wrapperElement: HTMLElement | null = null;
|
|
287
|
-
let internalPropsEditorRef: any = null;
|
|
288
|
-
|
|
289
|
-
/** Public: update a design value in the internal PropsEditor (for external dimension sync) */
|
|
67
|
+
/** Public: update a design value in the internal PropsEditor (external dimension sync). */
|
|
290
68
|
export function updateValue(propertyId: string, value: any) {
|
|
291
69
|
internalPropsEditorRef?.updateDesignValue?.(propertyId, value);
|
|
292
70
|
}
|
|
293
71
|
|
|
294
|
-
/** Public:
|
|
72
|
+
/** Public: position the same element used by PropsEditor's built-in drag. */
|
|
295
73
|
export function setPosition(left: number, top: number) {
|
|
296
|
-
|
|
297
|
-
wrapperElement.style.left = `${left}px`;
|
|
298
|
-
wrapperElement.style.top = `${top}px`;
|
|
74
|
+
internalPropsEditorRef?.setPosition(left, top);
|
|
299
75
|
}
|
|
300
76
|
|
|
301
|
-
/** Public: get current position */
|
|
77
|
+
/** Public: get current position. */
|
|
302
78
|
export function getPosition() {
|
|
303
|
-
|
|
304
|
-
return {
|
|
305
|
-
left: parseFloat(wrapperElement.style.left) || 0,
|
|
306
|
-
top: parseFloat(wrapperElement.style.top) || 0
|
|
307
|
-
};
|
|
79
|
+
return internalPropsEditorRef?.getPosition() || { left: 0, top: 0 };
|
|
308
80
|
}
|
|
309
|
-
|
|
310
81
|
</script>
|
|
311
82
|
|
|
312
|
-
|
|
313
|
-
<!-- HTML -->
|
|
314
|
-
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
|
315
|
-
<div
|
|
83
|
+
<div
|
|
316
84
|
bind:this={wrapperElement}
|
|
317
|
-
class="{standalone ? 'min-h-screen w-full flex items-center justify-center widgetic-colors widgetic-radius bg-dark p-4' : 'embed-editor-inline-wrapper absolute'}"
|
|
85
|
+
class="{standalone ? 'embed-editor-standalone-wrapper min-h-screen w-full flex items-center justify-center widgetic-colors widgetic-radius bg-dark p-4' : 'embed-editor-inline-wrapper absolute h-full w-112.5 max-h-full'}"
|
|
318
86
|
>
|
|
319
|
-
<
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
style="
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
87
|
+
<PropsEditor
|
|
88
|
+
bind:this={internalPropsEditorRef}
|
|
89
|
+
class="embed-editor-container rounded-large bg-white shadow-none {className}"
|
|
90
|
+
style="border: 2px solid hsl(var(--grey2)); max-height: 100%; {style}"
|
|
91
|
+
width="450px"
|
|
92
|
+
height={embedSchema ? (standalone ? `min(${height}px, calc(100dvh - 32px))` : `min(${height}px, 100%)`) : 'auto'}
|
|
93
|
+
positionTarget={standalone ? null : wrapperElement}
|
|
94
|
+
designSchema={embedCode ? embedSchema : null}
|
|
95
|
+
contentSchema={null}
|
|
96
|
+
initialDesignValues={initialValues}
|
|
97
|
+
defaultOpen={true}
|
|
98
|
+
showDragHandle={!loading && !!embedCode}
|
|
99
|
+
{showSaveButton}
|
|
100
|
+
{saveDirty}
|
|
101
|
+
{saveSaving}
|
|
102
|
+
title="Edit Options"
|
|
103
|
+
dragHandleClass="text-forest-green"
|
|
104
|
+
headerClass={!loading && embedCode ? 'bg-grey2' : ''}
|
|
105
|
+
showSchemaError={false}
|
|
106
|
+
on:save
|
|
107
|
+
on:propertyChange
|
|
331
108
|
>
|
|
332
|
-
{#
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
<div class="
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
{:else}
|
|
340
|
-
<!-- Embed Code Header and Text Area Container -->
|
|
341
|
-
<section
|
|
342
|
-
class="header-hover-area bg-grey2"
|
|
343
|
-
class:rounded-b-[var(--radius-large)]={!embedSchema}
|
|
344
|
-
aria-label="Embed code header area"
|
|
345
|
-
>
|
|
346
|
-
<!-- Drag Handle -->
|
|
347
|
-
<div class="absolute top-0 left-0 w-full flex justify-center z-[103]">
|
|
348
|
-
<div class="flex items-center justify-center h-6 cursor-move transition-all duration-200 widgetic-colors drag-handle-container">
|
|
349
|
-
<DragHandle class="w-[66px] h-[24px] text-forest-green hover:text-grey3 transition-colors drag-handle" />
|
|
350
|
-
</div>
|
|
351
|
-
</div>
|
|
352
|
-
|
|
353
|
-
<!-- Use the CopyableHeader component -->
|
|
354
|
-
<CopyableHeader
|
|
355
|
-
headerText={embedHeaderText}
|
|
356
|
-
content={embedCode}
|
|
357
|
-
helpText="Read more about embedding"
|
|
358
|
-
helpUrl="/embed"
|
|
359
|
-
showStandaloneCopyButton={true}
|
|
360
|
-
standaloneCopyButtonText="Copy to clipboard"
|
|
361
|
-
showButtonText={false}
|
|
362
|
-
buttonClass="bg-grey2 text-grey7 hover:bg-white rounded-small"
|
|
363
|
-
style="border-top-left-radius: var(--radius-large); border-top-right-radius: var(--radius-large);"
|
|
364
|
-
on:copy={() => {
|
|
365
|
-
showToast('success', 'Copied to clipboard', {
|
|
366
|
-
description: 'Paste it anywhere on your site.',
|
|
367
|
-
icon: OK,
|
|
368
|
-
});
|
|
369
|
-
}}
|
|
370
|
-
/>
|
|
371
|
-
</section>
|
|
372
|
-
|
|
373
|
-
<!-- Props Editor - Only show if embedSchema exists -->
|
|
374
|
-
{#if embedSchema}
|
|
375
|
-
<div class="w-full flex-1 z-10 bg-white overflow-hidden widgetic-colors">
|
|
376
|
-
<ScrollArea
|
|
377
|
-
class="h-full"
|
|
378
|
-
type="hover"
|
|
379
|
-
scrollHideDelay={0}
|
|
380
|
-
scrollbarYClasses="flex touch-none select-none transition-colors w-[24px] px-2 bg-white pt-4 pb-6 [&>div]:w-[8px] [&>div]:bg-grey1 [&>div]:rounded-pill [&>div]:cursor-pointer [&>div]:transition-colors [&>div]:duration-250 [&>div]:hover:bg-grey2 [&>div]:opacity-100"
|
|
381
|
-
>
|
|
382
|
-
<div class="scroll-viewport h-full" data-radix-scroll-area-viewport>
|
|
383
|
-
<div class="min-h-full scroll-content p-0">
|
|
384
|
-
<PropsEditor
|
|
385
|
-
bind:this={internalPropsEditorRef}
|
|
386
|
-
class="z-10"
|
|
387
|
-
width="450px"
|
|
388
|
-
height="100%"
|
|
389
|
-
designSchema={embedSchema}
|
|
390
|
-
contentSchema={null}
|
|
391
|
-
initialDesignValues={initialValues}
|
|
392
|
-
defaultOpen={true}
|
|
393
|
-
showDragHandle={false}
|
|
394
|
-
on:propertyChange={(event: any) => {
|
|
395
|
-
dispatch('propertyChange', event.detail);
|
|
396
|
-
}}
|
|
397
|
-
/>
|
|
398
|
-
</div>
|
|
399
|
-
</div>
|
|
400
|
-
</ScrollArea>
|
|
109
|
+
{#snippet headerContent()}
|
|
110
|
+
{#if loading}
|
|
111
|
+
<div class="embed-editor-loading subtext text-grey5 flex items-center justify-center h-full">Loading...</div>
|
|
112
|
+
{:else if !embedCode}
|
|
113
|
+
<div class="embed-editor-error flex flex-col items-center justify-center h-full">
|
|
114
|
+
<div class="embed-editor-error-title text-error text-lg font-medium">No embed code available</div>
|
|
115
|
+
<div class="embed-editor-error-code text-grey5 subtext mt-1">Error code: EMBED_CODE_NOT_FOUND</div>
|
|
401
116
|
</div>
|
|
117
|
+
{:else}
|
|
118
|
+
<!-- The only additional panel: code display, help link and clipboard control. -->
|
|
119
|
+
<section class="embed-editor-code-header header-hover-area relative shrink-0 bg-grey2" aria-label="Embed code header area">
|
|
120
|
+
<CopyableHeader
|
|
121
|
+
headerText={embedHeaderText}
|
|
122
|
+
content={embedCode}
|
|
123
|
+
helpText="Read more about embedding"
|
|
124
|
+
helpUrl="/embed"
|
|
125
|
+
showStandaloneCopyButton={true}
|
|
126
|
+
standaloneCopyButtonText="Copy to clipboard"
|
|
127
|
+
showButtonText={false}
|
|
128
|
+
buttonClass="bg-grey2 text-grey7 hover:bg-white rounded-small focus:outline-none focus-visible:outline-none focus:shadow-none focus-visible:shadow-none"
|
|
129
|
+
style="border-top-left-radius: var(--radius-large); border-top-right-radius: var(--radius-large);"
|
|
130
|
+
on:copy={() => {
|
|
131
|
+
showToast('success', 'Copied to clipboard', {
|
|
132
|
+
description: 'Paste it anywhere on your site.',
|
|
133
|
+
icon: OK
|
|
134
|
+
});
|
|
135
|
+
}}
|
|
136
|
+
/>
|
|
137
|
+
</section>
|
|
402
138
|
{/if}
|
|
403
|
-
{/
|
|
404
|
-
</
|
|
139
|
+
{/snippet}
|
|
140
|
+
</PropsEditor>
|
|
405
141
|
</div>
|
|
406
142
|
|
|
407
143
|
<style>
|
|
408
|
-
/*
|
|
409
|
-
.
|
|
410
|
-
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
.drag-handle-container {
|
|
414
|
-
transition: opacity 0.3s ease;
|
|
415
|
-
/* Ensure the drag handle is always visible on top */
|
|
416
|
-
z-index: 103;
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
/* Only apply move cursor to the drag handle */
|
|
420
|
-
.drag-handle-container {
|
|
421
|
-
cursor: move;
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
/* Drag Handle Icon */
|
|
425
|
-
:global(.drag-handle svg) {
|
|
426
|
-
color: hsl(var(--forest-green)) !important;
|
|
427
|
-
transition: color 0.2s ease !important;
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
/* Remove white background on hover for drag handle */
|
|
431
|
-
:global(.drag-handle:hover) {
|
|
432
|
-
background-color: transparent !important;
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
:global(.drag-handle:hover svg) {
|
|
436
|
-
color: hsl(var(--grey3)) !important;
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
/* Remove box shadow */
|
|
440
|
-
.embed-editor-container {
|
|
441
|
-
box-shadow: none;
|
|
442
|
-
transform: translateZ(0); /* Force GPU acceleration */
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
/* Prevent shadow inheritance for PropsEditor */
|
|
446
|
-
:global(.props-editor-container) {
|
|
447
|
-
box-shadow: none !important;
|
|
448
|
-
border: none !important;
|
|
449
|
-
padding: 0 !important;
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
/* Add this to ensure proper border radius inheritance */
|
|
453
|
-
:global(.embed-editor-container .props-editor-container) {
|
|
454
|
-
border-bottom-left-radius: var(--radius-large);
|
|
455
|
-
border-bottom-right-radius: var(--radius-large);
|
|
456
|
-
overflow: visible !important;
|
|
457
|
-
width: 100% !important;
|
|
144
|
+
/* Remove the DS inline top padding only inside this embed header. */
|
|
145
|
+
.embed-editor-code-header :global(.copyable-header) {
|
|
146
|
+
padding-top: 0 !important;
|
|
458
147
|
}
|
|
459
148
|
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
/* Style accordion items to match Design system */
|
|
466
|
-
:global(.embed-editor-container .accordion-item) {
|
|
149
|
+
/* Style accordion items to match Design system — only within this Embed instance. */
|
|
150
|
+
.embed-editor-inline-wrapper :global(.accordion-item),
|
|
151
|
+
.embed-editor-standalone-wrapper :global(.accordion-item) {
|
|
467
152
|
border: 2px solid hsl(var(--grey2)) !important;
|
|
468
153
|
background: white !important;
|
|
469
154
|
overflow: hidden !important;
|
|
@@ -471,22 +156,23 @@ export function getPosition() {
|
|
|
471
156
|
position: relative !important;
|
|
472
157
|
}
|
|
473
158
|
|
|
474
|
-
/*
|
|
475
|
-
:global(.embed-editor-container .accordion-item[data-
|
|
159
|
+
/* Accordion Item: Handle first, last and single items. */
|
|
160
|
+
:global(.embed-editor-container .accordion-item[data-position="only"]) {
|
|
161
|
+
border-radius: var(--radius-medium) !important;
|
|
162
|
+
}
|
|
163
|
+
:global(.embed-editor-container .accordion-item[data-position="first"]) {
|
|
476
164
|
border-top-left-radius: var(--radius-medium) !important;
|
|
477
165
|
border-top-right-radius: var(--radius-medium) !important;
|
|
478
166
|
border-bottom-left-radius: 0 !important;
|
|
479
167
|
border-bottom-right-radius: 0 !important;
|
|
480
168
|
}
|
|
481
|
-
|
|
482
|
-
:global(.embed-editor-container .accordion-item[data-accordion-id="Advanced Settings"]) {
|
|
169
|
+
:global(.embed-editor-container .accordion-item[data-position="last"]) {
|
|
483
170
|
border-top-left-radius: 0 !important;
|
|
484
171
|
border-top-right-radius: 0 !important;
|
|
485
172
|
border-bottom-left-radius: var(--radius-medium) !important;
|
|
486
173
|
border-bottom-right-radius: var(--radius-medium) !important;
|
|
487
174
|
margin-bottom: 0 !important;
|
|
488
175
|
}
|
|
489
|
-
|
|
490
176
|
:global(.embed-editor-container .accordion-trigger) {
|
|
491
177
|
padding: 16px !important;
|
|
492
178
|
width: 100% !important;
|
|
@@ -496,56 +182,25 @@ export function getPosition() {
|
|
|
496
182
|
background: white !important;
|
|
497
183
|
border: none !important;
|
|
498
184
|
}
|
|
499
|
-
|
|
500
185
|
:global(.embed-editor-container .accordion-trigger:hover .body-medium) {
|
|
501
186
|
text-decoration: underline !important;
|
|
502
187
|
}
|
|
503
|
-
|
|
504
188
|
:global(.embed-editor-container .accordion-content) {
|
|
505
189
|
padding: 16px !important;
|
|
506
190
|
border-top: 2px solid hsl(var(--grey2)) !important;
|
|
507
191
|
}
|
|
508
|
-
|
|
509
192
|
:global(.embed-editor-container .accordion-content > div) {
|
|
510
193
|
padding: 0 !important;
|
|
511
194
|
background: white !important;
|
|
512
195
|
}
|
|
513
|
-
|
|
514
|
-
/* Style the chevron icon */
|
|
196
|
+
/* Style the chevron icon. */
|
|
515
197
|
:global(.embed-editor-container .accordion-trigger .chevron) {
|
|
516
198
|
transition: transform 200ms ease-out !important;
|
|
517
199
|
}
|
|
518
|
-
|
|
519
200
|
:global(.embed-editor-container .accordion-trigger[data-state="open"] .chevron) {
|
|
520
201
|
transform: rotate(180deg) !important;
|
|
521
202
|
}
|
|
522
|
-
|
|
523
|
-
/* Style for the embed code text area */
|
|
524
|
-
.embed-code-textarea {
|
|
525
|
-
-webkit-user-select: text !important;
|
|
526
|
-
-moz-user-select: text !important;
|
|
527
|
-
-ms-user-select: text !important;
|
|
528
|
-
user-select: text !important;
|
|
529
|
-
font-family: monospace !important;
|
|
530
|
-
overflow-y: auto !important;
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
.embed-code-textarea::selection {
|
|
534
|
-
background-color: rgba(59, 130, 246, 0.2) !important;
|
|
535
|
-
color: inherit !important;
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
.embed-code-textarea::-moz-selection {
|
|
539
|
-
background-color: rgba(59, 130, 246, 0.2) !important;
|
|
540
|
-
color: inherit !important;
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
.text-wrapper {
|
|
544
|
-
font-family: monospace !important;
|
|
545
|
-
line-height: 1;
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
/* Ensure inputs maintain their container width */
|
|
203
|
+
/* Ensure inputs maintain their container width. */
|
|
549
204
|
:global(.embed-editor-container input),
|
|
550
205
|
:global(.embed-editor-container select),
|
|
551
206
|
:global(.embed-editor-container textarea),
|
|
@@ -556,37 +211,16 @@ export function getPosition() {
|
|
|
556
211
|
min-width: 0;
|
|
557
212
|
box-sizing: border-box;
|
|
558
213
|
}
|
|
559
|
-
|
|
560
|
-
/* Force width constraints on content */
|
|
561
|
-
:global(.embed-editor-container .props-editor-container) {
|
|
562
|
-
width: 100%;
|
|
563
|
-
min-width: 0;
|
|
564
|
-
overflow: visible;
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
/* Ensure popover content stays within bounds */
|
|
214
|
+
/* Ensure popover content stays within bounds. */
|
|
568
215
|
:global(.embed-editor-container .popover-content) {
|
|
569
216
|
max-width: calc(100% - 2rem);
|
|
570
217
|
min-width: 0;
|
|
571
218
|
}
|
|
572
|
-
|
|
573
|
-
/* Add scroll visibility styles */
|
|
574
|
-
:global(.embed-editor-container [data-radix-scroll-area-viewport]) {
|
|
575
|
-
width: 100% !important;
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
:global(.embed-editor-container .scroll-area) {
|
|
579
|
-
width: 100% !important;
|
|
580
|
-
overflow: visible !important;
|
|
581
|
-
}
|
|
582
|
-
|
|
583
219
|
/* Button Press Effect */
|
|
584
|
-
:global(.embed-code-header button) {
|
|
220
|
+
:global(.embed-editor-container .embed-code-header button) {
|
|
585
221
|
transition: background-color 0.1s ease;
|
|
586
222
|
}
|
|
587
|
-
|
|
588
223
|
/** TOASTER STYLES **/
|
|
589
|
-
/* Toaster Positioning */
|
|
590
224
|
:global(.embed-editor-toast) {
|
|
591
225
|
position: fixed !important;
|
|
592
226
|
bottom: 20px !important;
|
|
@@ -600,7 +234,6 @@ export function getPosition() {
|
|
|
600
234
|
border-radius: var(--radius-small) !important;
|
|
601
235
|
box-shadow: 0px 0px 15px 3px rgba(0, 0, 0, 0.1) !important;
|
|
602
236
|
}
|
|
603
|
-
|
|
604
237
|
/* Icon container */
|
|
605
238
|
:global(.embed-editor-toast [data-icon]) {
|
|
606
239
|
order: -1 !important;
|
|
@@ -609,7 +242,6 @@ export function getPosition() {
|
|
|
609
242
|
justify-content: center !important;
|
|
610
243
|
margin: 0 !important;
|
|
611
244
|
}
|
|
612
|
-
|
|
613
245
|
/* Text container */
|
|
614
246
|
:global(.embed-editor-toast [data-content]) {
|
|
615
247
|
display: flex !important;
|
|
@@ -617,84 +249,23 @@ export function getPosition() {
|
|
|
617
249
|
gap: 4px !important;
|
|
618
250
|
margin: 0 !important;
|
|
619
251
|
}
|
|
620
|
-
|
|
621
|
-
/* Toaster title */
|
|
622
|
-
.embed-editor-title {
|
|
623
|
-
font-size: var(--h6) !important;
|
|
624
|
-
color: hsl(var(--forest)) !important;
|
|
625
|
-
font-weight: 600 !important;
|
|
626
|
-
}
|
|
627
|
-
|
|
628
|
-
/* Toaster description */
|
|
629
|
-
.embed-editor-toast-description {
|
|
630
|
-
font-size: var(--caption) !important;
|
|
631
|
-
color: hsl(var(--grey3)) !important;
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
/* Toaster icon */
|
|
635
|
-
.embed-editor-toast-icon {
|
|
636
|
-
width: 40px !important;
|
|
637
|
-
height: 40px !important;
|
|
638
|
-
}
|
|
639
|
-
|
|
640
252
|
/* Toaster close button */
|
|
641
253
|
:global(.embed-editor-toast-close-button) {
|
|
642
254
|
background: hsl(var(--grey7)) !important;
|
|
643
255
|
border: 1px solid hsl(var(--grey5)) !important;
|
|
644
256
|
}
|
|
645
|
-
|
|
646
257
|
:global(.embed-editor-toast-close-button:hover) {
|
|
647
258
|
background: hsl(var(--dark)) !important;
|
|
648
259
|
border: 1px solid hsl(var(--grey5)) !important;
|
|
649
260
|
}
|
|
650
|
-
|
|
651
261
|
:global(.embed-editor-toast-close-button svg) {
|
|
652
262
|
color: white !important;
|
|
653
263
|
}
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
:global(.embed-editor-container .accordion-item[data-position="only"]) {
|
|
657
|
-
border-radius: var(--radius-medium) !important;
|
|
658
|
-
}
|
|
659
|
-
|
|
660
|
-
:global(.embed-editor-container .accordion-item[data-position="first"]) {
|
|
661
|
-
border-top-left-radius: var(--radius-medium) !important;
|
|
662
|
-
border-top-right-radius: var(--radius-medium) !important;
|
|
663
|
-
border-bottom-left-radius: 0 !important;
|
|
664
|
-
border-bottom-right-radius: 0 !important;
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
:global(.embed-editor-container .accordion-item[data-position="last"]) {
|
|
668
|
-
border-top-left-radius: 0 !important;
|
|
669
|
-
border-top-right-radius: 0 !important;
|
|
670
|
-
border-bottom-left-radius: var(--radius-medium) !important;
|
|
671
|
-
border-bottom-right-radius: var(--radius-medium) !important;
|
|
672
|
-
}
|
|
673
|
-
|
|
674
|
-
/* Lucide Copy Icon: Set both default and hover colors */
|
|
675
|
-
:global(.lucide-copy) {
|
|
264
|
+
/* Lucide Copy Icon: Set both default and hover colors. */
|
|
265
|
+
:global(.embed-editor-container .lucide-copy) {
|
|
676
266
|
stroke: hsl(var(--error)) !important;
|
|
677
267
|
}
|
|
678
|
-
|
|
679
|
-
:global(button:hover .lucide-copy) {
|
|
268
|
+
:global(.embed-editor-container button:hover .lucide-copy) {
|
|
680
269
|
stroke: hsl(var(--grey7)) !important;
|
|
681
270
|
}
|
|
682
|
-
|
|
683
|
-
/* Add styles for dots pattern */
|
|
684
|
-
.dots-pattern {
|
|
685
|
-
cursor: move;
|
|
686
|
-
user-select: none;
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
.dots-pattern:active {
|
|
690
|
-
cursor: grabbing;
|
|
691
|
-
}
|
|
692
|
-
|
|
693
|
-
/* Add styles for error message */
|
|
694
|
-
:global(.subtext) {
|
|
695
|
-
font-size: 0.875rem;
|
|
696
|
-
line-height: 1.25rem;
|
|
697
|
-
font-weight: 400;
|
|
698
|
-
}
|
|
699
271
|
</style>
|
|
700
|
-
|