@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
|
@@ -12,15 +12,7 @@ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> =
|
|
|
12
12
|
z_$$bindings?: Bindings;
|
|
13
13
|
}
|
|
14
14
|
declare const EmbedEditor: $$__sveltets_2_IsomorphicComponent<{
|
|
15
|
-
/**
|
|
16
|
-
* Component Configuration Props
|
|
17
|
-
* width/height: Control overall component dimensions
|
|
18
|
-
* headerHeight: Space allocated for embed code display section
|
|
19
|
-
* embedSchema: Defines customizable properties for the embedded widget
|
|
20
|
-
*
|
|
21
|
-
* Note: headerHeight affects the vertical space distribution between
|
|
22
|
-
* the embed code display and property editor sections
|
|
23
|
-
*/ class?: string;
|
|
15
|
+
/** Component configuration — existing public props and methods are preserved. */ class?: string;
|
|
24
16
|
style?: string;
|
|
25
17
|
embedHeaderText?: string;
|
|
26
18
|
embedCode?: string;
|
|
@@ -28,23 +20,21 @@ declare const EmbedEditor: $$__sveltets_2_IsomorphicComponent<{
|
|
|
28
20
|
embedSchema: any;
|
|
29
21
|
initialValues?: Record<string, any>;
|
|
30
22
|
standalone?: boolean;
|
|
23
|
+
/** Show Save status control in the shared drag bar (composition embed overlay). */ showSaveButton?: boolean;
|
|
24
|
+
/** True when local embed option edits are not yet persisted. */ saveDirty?: boolean;
|
|
25
|
+
/** True while a save request is in flight. */ saveSaving?: boolean;
|
|
31
26
|
updateValue?: (propertyId: string, value: any) => void;
|
|
32
27
|
setPosition?: (left: number, top: number) => void;
|
|
33
|
-
getPosition?: () =>
|
|
34
|
-
left: number;
|
|
35
|
-
top: number;
|
|
36
|
-
};
|
|
28
|
+
getPosition?: () => any;
|
|
37
29
|
}, {
|
|
30
|
+
save: CustomEvent<any>;
|
|
38
31
|
propertyChange: CustomEvent<any>;
|
|
39
32
|
} & {
|
|
40
33
|
[evt: string]: CustomEvent<any>;
|
|
41
34
|
}, {}, {
|
|
42
35
|
updateValue: (propertyId: string, value: any) => void;
|
|
43
36
|
setPosition: (left: number, top: number) => void;
|
|
44
|
-
getPosition: () =>
|
|
45
|
-
left: number;
|
|
46
|
-
top: number;
|
|
47
|
-
};
|
|
37
|
+
getPosition: () => any;
|
|
48
38
|
}, string>;
|
|
49
39
|
type EmbedEditor = InstanceType<typeof EmbedEditor>;
|
|
50
40
|
export default EmbedEditor;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
<svelte:options runes={false} />
|
|
2
|
+
|
|
1
3
|
<script lang="ts">
|
|
2
4
|
/**
|
|
3
5
|
* PropsEditor Component
|
|
@@ -63,6 +65,7 @@
|
|
|
63
65
|
/**
|
|
64
66
|
* UTILS IMPORTS
|
|
65
67
|
*/
|
|
68
|
+
import InputControllerRenderer, { type ControllerDescriptor } from '../ic/InputControllerRenderer.svelte';
|
|
66
69
|
import MediaManager from '../../utils/MediaManager';
|
|
67
70
|
import FontManager from '../../utils/FontManager';
|
|
68
71
|
import { config as appConfig } from '../../config';
|
|
@@ -135,6 +138,23 @@
|
|
|
135
138
|
// Enable built-in drag (component manages its own absolute positioning)
|
|
136
139
|
export let enableDrag = true;
|
|
137
140
|
|
|
141
|
+
/** Show Save status control in the top drag/header bar (composition page). */
|
|
142
|
+
export let showSaveButton = false;
|
|
143
|
+
/** True when local edits are not yet persisted. */
|
|
144
|
+
export let saveDirty = false;
|
|
145
|
+
/** True while a save request is in flight. */
|
|
146
|
+
export let saveSaving = false;
|
|
147
|
+
|
|
148
|
+
/** Optional content below the shared toolbar, before property fields. */
|
|
149
|
+
export let headerContent = undefined;
|
|
150
|
+
export let headerClass = '';
|
|
151
|
+
export let dragHandleClass = 'text-grey2';
|
|
152
|
+
export let title = 'Edit Properties';
|
|
153
|
+
/** Hide the default missing-schema message for header-only editors. */
|
|
154
|
+
export let showSchemaError = true;
|
|
155
|
+
/** Optional layout wrapper moved by this editor's built-in drag and position API. */
|
|
156
|
+
export let positionTarget = null;
|
|
157
|
+
|
|
138
158
|
// Initial values from saved composition (merged over schema defaults)
|
|
139
159
|
export let initialDesignValues: Record<string, any> = {};
|
|
140
160
|
export let initialContentValues: Record<string, any> = {};
|
|
@@ -144,8 +164,11 @@
|
|
|
144
164
|
*/
|
|
145
165
|
const CONTENT_PADDING = 16; // Outer padding for both tabs
|
|
146
166
|
const CONTENT_INNER_PADDING = 16; // Inner padding for cards in Content tab
|
|
147
|
-
const
|
|
148
|
-
const
|
|
167
|
+
const DRAG_BAR_HEIGHT = 28; // Drag handle / Save row (absolute, overlays the header top)
|
|
168
|
+
const TABS_VERTICAL_PADDING = 14; // Breathing room above and below the tab list
|
|
169
|
+
const TABS_LIST_HEIGHT = 56; // Tabs.List height
|
|
170
|
+
// Drag bar band + gap + tabs + gap + 1px separator
|
|
171
|
+
const HEADER_HEIGHT = DRAG_BAR_HEIGHT + TABS_VERTICAL_PADDING * 2 + TABS_LIST_HEIGHT + 1;
|
|
149
172
|
const EDITOR_STROKE_COLOR = '#e5e7eb'; // Color for editor stroke
|
|
150
173
|
const EDITOR_STROKE_WIDTH = '1px'; // Thickness of editor stroke
|
|
151
174
|
|
|
@@ -928,8 +951,11 @@
|
|
|
928
951
|
*/
|
|
929
952
|
onDestroy(() => {
|
|
930
953
|
// Clean up drag listeners
|
|
931
|
-
|
|
932
|
-
|
|
954
|
+
if (browser) {
|
|
955
|
+
document.removeEventListener('mousemove', handleDragMove);
|
|
956
|
+
document.removeEventListener('mouseup', handleDragEnd);
|
|
957
|
+
if (dragState.active) document.body.style.cursor = '';
|
|
958
|
+
}
|
|
933
959
|
|
|
934
960
|
// Clean up scroll listeners
|
|
935
961
|
if (designScrollViewport) {
|
|
@@ -1475,6 +1501,35 @@
|
|
|
1475
1501
|
}
|
|
1476
1502
|
}
|
|
1477
1503
|
|
|
1504
|
+
/** Preserve the schema factory's props while narrowing each concrete render branch. */
|
|
1505
|
+
function describeInputController(component: ReturnType<typeof getInputControllerComponent> | null, props: ReturnType<typeof renderInputController>['props']): ControllerDescriptor | null {
|
|
1506
|
+
switch (component) {
|
|
1507
|
+
case TextInputController: return { kind: 'textinput', props };
|
|
1508
|
+
case TextAreaPreviewInputController: return { kind: 'textarea', props };
|
|
1509
|
+
case NumberInputController: return { kind: 'number', props };
|
|
1510
|
+
case SliderInputController: return { kind: 'slider', props };
|
|
1511
|
+
case SliderRangeInputController: return { kind: 'sliderrange', props };
|
|
1512
|
+
case DropdownInputController: return { kind: 'dropdown', props };
|
|
1513
|
+
case DatePickerInputController: return { kind: 'datepicker', props };
|
|
1514
|
+
case DateFieldInputController: return { kind: 'datefield', props };
|
|
1515
|
+
case RangeCalendarInputController: return { kind: 'rangecalendar', props };
|
|
1516
|
+
case SwitchInputController: return { kind: 'switch', props };
|
|
1517
|
+
case ColorPickerInputController: return { kind: 'colorpicker', props };
|
|
1518
|
+
case CheckboxInputController: return { kind: 'checkbox', props };
|
|
1519
|
+
case RadioGroupInputController: return { kind: 'radiogroup', props };
|
|
1520
|
+
case FontInputController: return { kind: 'font', props };
|
|
1521
|
+
case PositionInputController: return { kind: 'position', props };
|
|
1522
|
+
case BrowserInputController: return { kind: 'browser', props };
|
|
1523
|
+
case FixedPositionInputController: return { kind: 'fixedposition', props };
|
|
1524
|
+
case VectorInputController: return { kind: 'vector', props };
|
|
1525
|
+
case AngleInputController: return { kind: 'angle', props };
|
|
1526
|
+
case TimeInputController: return { kind: 'time', props };
|
|
1527
|
+
case RoundedCornersInputController: return { kind: 'roundedcorners', props };
|
|
1528
|
+
case TagsInputController: return { kind: 'tags', props };
|
|
1529
|
+
default: return null;
|
|
1530
|
+
}
|
|
1531
|
+
}
|
|
1532
|
+
|
|
1478
1533
|
// Create a store for managing open dropdowns (only one should be open at a time)
|
|
1479
1534
|
const openDropdowns = writable<Set<string>>(new Set());
|
|
1480
1535
|
|
|
@@ -1599,6 +1654,8 @@
|
|
|
1599
1654
|
}
|
|
1600
1655
|
|
|
1601
1656
|
interface ContentItem {
|
|
1657
|
+
// Saved content may carry schema-defined values alongside its metadata.
|
|
1658
|
+
[propertyName: string]: unknown;
|
|
1602
1659
|
id: string;
|
|
1603
1660
|
properties: Array<Property>;
|
|
1604
1661
|
orderNumber?: number;
|
|
@@ -2252,28 +2309,43 @@
|
|
|
2252
2309
|
let dragState = { active: false, startX: 0, startY: 0, initialLeft: 0, initialTop: 0 };
|
|
2253
2310
|
|
|
2254
2311
|
function handleDragStart(e: MouseEvent) {
|
|
2255
|
-
|
|
2312
|
+
const target = positionTarget || rootElement;
|
|
2313
|
+
if (!enableDrag || !target || e.button !== 0) return;
|
|
2256
2314
|
e.preventDefault();
|
|
2257
|
-
|
|
2315
|
+
e.stopPropagation();
|
|
2316
|
+
|
|
2317
|
+
// Wrapped editors keep the measured size, including the parent's height clamp.
|
|
2318
|
+
// Resolve percentage/centered placement before leaving flow, never parse it as pixels.
|
|
2319
|
+
if (positionTarget) {
|
|
2320
|
+
const rectangle = target.getBoundingClientRect();
|
|
2321
|
+
const parent = target.offsetParent;
|
|
2322
|
+
const parentRectangle = parent?.getBoundingClientRect() || { left: 0, top: 0 };
|
|
2323
|
+
const left = rectangle.left - parentRectangle.left - (parent?.clientLeft || 0) + (parent?.scrollLeft || 0);
|
|
2324
|
+
const top = rectangle.top - parentRectangle.top - (parent?.clientTop || 0) + (parent?.scrollTop || 0);
|
|
2325
|
+
Object.assign(target.style, {
|
|
2326
|
+
position: 'absolute', margin: '0', transform: 'none',
|
|
2327
|
+
boxSizing: 'border-box', width: `${rectangle.width}px`, height: `${rectangle.height}px`,
|
|
2328
|
+
left: `${left}px`, top: `${top}px`
|
|
2329
|
+
});
|
|
2330
|
+
}
|
|
2258
2331
|
dragState = {
|
|
2259
2332
|
active: true,
|
|
2260
2333
|
startX: e.clientX,
|
|
2261
2334
|
startY: e.clientY,
|
|
2262
|
-
initialLeft: parseFloat(
|
|
2263
|
-
initialTop: parseFloat(
|
|
2335
|
+
initialLeft: parseFloat(target.style.left) || 0,
|
|
2336
|
+
initialTop: parseFloat(target.style.top) || 0
|
|
2264
2337
|
};
|
|
2265
|
-
|
|
2338
|
+
target.style.zIndex = '50';
|
|
2266
2339
|
document.addEventListener('mousemove', handleDragMove);
|
|
2267
2340
|
document.addEventListener('mouseup', handleDragEnd);
|
|
2268
2341
|
document.body.style.cursor = 'move';
|
|
2269
2342
|
}
|
|
2270
2343
|
|
|
2271
2344
|
function handleDragMove(e: MouseEvent) {
|
|
2272
|
-
if (!dragState.active
|
|
2345
|
+
if (!dragState.active) return;
|
|
2273
2346
|
const left = dragState.initialLeft + (e.clientX - dragState.startX);
|
|
2274
2347
|
const top = dragState.initialTop + (e.clientY - dragState.startY);
|
|
2275
|
-
|
|
2276
|
-
rootElement.style.top = `${top}px`;
|
|
2348
|
+
setPosition(left, top);
|
|
2277
2349
|
dispatch('move', { left, top });
|
|
2278
2350
|
}
|
|
2279
2351
|
|
|
@@ -2283,10 +2355,7 @@
|
|
|
2283
2355
|
document.removeEventListener('mousemove', handleDragMove);
|
|
2284
2356
|
document.removeEventListener('mouseup', handleDragEnd);
|
|
2285
2357
|
document.body.style.cursor = '';
|
|
2286
|
-
dispatch('moveEnd',
|
|
2287
|
-
left: parseFloat(rootElement.style.left) || 0,
|
|
2288
|
-
top: parseFloat(rootElement.style.top) || 0
|
|
2289
|
-
});
|
|
2358
|
+
dispatch('moveEnd', getPosition());
|
|
2290
2359
|
}
|
|
2291
2360
|
|
|
2292
2361
|
/** Public: update a design state value externally (used by EmbedEditor for dimension sync) */
|
|
@@ -2296,17 +2365,19 @@
|
|
|
2296
2365
|
|
|
2297
2366
|
/** Public: set absolute position programmatically (used by parent for layout) */
|
|
2298
2367
|
export function setPosition(left: number, top: number) {
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2368
|
+
const target = positionTarget || rootElement;
|
|
2369
|
+
if (!target) return;
|
|
2370
|
+
target.style.left = `${left}px`;
|
|
2371
|
+
target.style.top = `${top}px`;
|
|
2302
2372
|
}
|
|
2303
2373
|
|
|
2304
2374
|
/** Public: get current position */
|
|
2305
2375
|
export function getPosition() {
|
|
2306
|
-
|
|
2376
|
+
const target = positionTarget || rootElement;
|
|
2377
|
+
if (!target) return { left: 0, top: 0 };
|
|
2307
2378
|
return {
|
|
2308
|
-
left: parseFloat(
|
|
2309
|
-
top: parseFloat(
|
|
2379
|
+
left: parseFloat(target.style.left) || 0,
|
|
2380
|
+
top: parseFloat(target.style.top) || 0
|
|
2310
2381
|
};
|
|
2311
2382
|
}
|
|
2312
2383
|
|
|
@@ -2353,47 +2424,64 @@
|
|
|
2353
2424
|
onValueChange={handleTabChange}
|
|
2354
2425
|
>
|
|
2355
2426
|
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
<div class="text-error text-lg font-medium">No schema configuration available</div>
|
|
2359
|
-
<div class="text-grey5 subtext mt-1">Error code: CONFIG_NOT_FOUND</div>
|
|
2360
|
-
</div>
|
|
2361
|
-
{:else}
|
|
2362
|
-
<!-- Drag Handle - Show outside header when no header exists -->
|
|
2363
|
-
{#if showDragHandle && (!designSchema || !contentSchema)}
|
|
2427
|
+
<!-- A single toolbar owns drag and Save for all editor variants. -->
|
|
2428
|
+
{#if showDragHandle && (designSchema || contentSchema || headerContent)}
|
|
2364
2429
|
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
2365
|
-
<div class="
|
|
2430
|
+
<div class="props-editor-drag-bar top-0 left-0 w-full flex h-7 shrink-0 items-center justify-center z-999 px-3 {headerContent ? 'relative ' + headerClass : 'absolute'}">
|
|
2366
2431
|
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
2367
2432
|
<div
|
|
2368
|
-
class="flex items-center justify-center h-
|
|
2433
|
+
class="flex items-center justify-center h-7 cursor-move transition-all duration-200 widgetic-colors opacity-0 hover:opacity-100 drag-handle-container"
|
|
2369
2434
|
onmousedown={handleDragStart}
|
|
2370
2435
|
>
|
|
2371
|
-
<DragHandle class="w-
|
|
2436
|
+
<DragHandle class="w-16.5 h-6 {dragHandleClass} hover:text-grey3 transition-colors" />
|
|
2372
2437
|
</div>
|
|
2438
|
+
{#if showSaveButton}
|
|
2439
|
+
{#if title}<span class="props-editor-title-label absolute left-6 top-1.75 pointer-events-none select-none text-[13px] font-bold leading-none text-[hsl(var(--grey5))]">{title}</span>{/if}
|
|
2440
|
+
<button
|
|
2441
|
+
type="button"
|
|
2442
|
+
class="props-editor-save-btn absolute right-6 top-1 inline-flex h-5 w-19 items-center justify-center rounded-md text-[10px] font-semibold leading-none transition-colors focus:outline-none focus-visible:outline-none
|
|
2443
|
+
{saveSaving
|
|
2444
|
+
? 'text-[hsl(var(--deep-forest-green))] bg-[hsl(var(--light-green))]'
|
|
2445
|
+
: saveDirty
|
|
2446
|
+
? 'text-white bg-[hsl(var(--deep-forest-green))] hover:bg-[hsl(var(--dark))] hover:text-white'
|
|
2447
|
+
: 'text-[hsl(var(--grey5))] bg-grey2 inset-ring inset-ring-grey3/20 hover:inset-ring-deep-forest-green hover:bg-[hsl(var(--deep-forest-green))] hover:text-white'}"
|
|
2448
|
+
disabled={saveSaving}
|
|
2449
|
+
onclick={(e) => {
|
|
2450
|
+
e.stopPropagation();
|
|
2451
|
+
if (!saveSaving && saveDirty) dispatch('save');
|
|
2452
|
+
}}
|
|
2453
|
+
onmousedown={(e) => e.stopPropagation()}
|
|
2454
|
+
>
|
|
2455
|
+
<svg class="props-editor-save-icon absolute left-2 h-3 w-3 shrink-0" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
2456
|
+
<path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z" />
|
|
2457
|
+
<polyline points="17 21 17 13 7 13 7 21" />
|
|
2458
|
+
<polyline points="7 3 7 8 15 8" />
|
|
2459
|
+
</svg>
|
|
2460
|
+
<span class="props-editor-save-label">{saveSaving ? 'Saving' : 'Save'}</span>
|
|
2461
|
+
</button>
|
|
2462
|
+
{/if}
|
|
2373
2463
|
</div>
|
|
2374
2464
|
{/if}
|
|
2375
2465
|
|
|
2466
|
+
{#if headerContent}
|
|
2467
|
+
<div class="props-editor-header-content shrink-0 {headerClass}">{@render headerContent()}</div>
|
|
2468
|
+
{/if}
|
|
2469
|
+
|
|
2470
|
+
{#if !designSchema && !contentSchema}
|
|
2471
|
+
{#if showSchemaError}
|
|
2472
|
+
<div class="props-editor-schema-error flex flex-col items-center justify-center h-full">
|
|
2473
|
+
<div class="props-editor-error-title text-error text-lg font-medium">No schema configuration available</div>
|
|
2474
|
+
<div class="props-editor-error-code text-grey5 subtext mt-1">Error code: CONFIG_NOT_FOUND</div>
|
|
2475
|
+
</div>
|
|
2476
|
+
{/if}
|
|
2477
|
+
{:else}
|
|
2376
2478
|
<!-- Tabs header with buttons and separator - only show if both schemas exist -->
|
|
2377
2479
|
{#if designSchema && contentSchema}
|
|
2378
2480
|
<div
|
|
2379
|
-
class="tabs-header h-
|
|
2481
|
+
class="tabs-header h-28 shrink-0 flex items-start pt-10.5 px-6 pb-3.5 rounded-t-large header-hover-area relative"
|
|
2380
2482
|
>
|
|
2381
|
-
<!-- Drag Handle - Show inside header when header exists -->
|
|
2382
|
-
{#if showDragHandle}
|
|
2383
|
-
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
2384
|
-
<div class="absolute top-0 left-0 w-full flex justify-center z-[999]">
|
|
2385
|
-
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
2386
|
-
<div
|
|
2387
|
-
class="flex items-center justify-center h-6 cursor-move transition-all duration-200 widgetic-colors opacity-0 hover:opacity-100 drag-handle-container"
|
|
2388
|
-
onmousedown={handleDragStart}
|
|
2389
|
-
>
|
|
2390
|
-
<DragHandle class="w-[66px] h-[24px] text-grey2 hover:text-grey3 transition-colors" />
|
|
2391
|
-
</div>
|
|
2392
|
-
</div>
|
|
2393
|
-
{/if}
|
|
2394
|
-
|
|
2395
2483
|
<Tabs.List
|
|
2396
|
-
class="tabs-list w-full h-
|
|
2484
|
+
class="tabs-list w-full h-14 rounded-large bg-grey2 p-1"
|
|
2397
2485
|
>
|
|
2398
2486
|
<Tabs.Trigger
|
|
2399
2487
|
value="design"
|
|
@@ -2421,7 +2509,7 @@
|
|
|
2421
2509
|
{/if}
|
|
2422
2510
|
|
|
2423
2511
|
<!-- Design Tab Content -->
|
|
2424
|
-
<div class="tab-design-container
|
|
2512
|
+
<div class="tab-design-container grow scroll-area widgetic-colors hidden {headerContent ? 'min-h-0 flex-1 overflow-hidden' : 'overflow-y-auto'}"
|
|
2425
2513
|
class:hidden={currentTab !== 'design'}
|
|
2426
2514
|
style="max-height: {!designSchema || !contentSchema ? '100%' : `calc(100% - ${HEADER_HEIGHT}px)`}"
|
|
2427
2515
|
data-scrollable={$designScrollState.shouldShowScroll}
|
|
@@ -2430,13 +2518,13 @@
|
|
|
2430
2518
|
class="h-full"
|
|
2431
2519
|
type="hover"
|
|
2432
2520
|
scrollHideDelay={0}
|
|
2433
|
-
scrollbarYClasses="flex touch-none select-none transition-colors w-
|
|
2521
|
+
scrollbarYClasses="flex touch-none select-none transition-colors w-6 px-2 {headerContent ? 'bg-transparent' : 'bg-white'} {!designSchema || !contentSchema ? 'pt-7' : 'pt-4'} pb-6 [&>div]:w-2 [&>div]:bg-grey1 [&>div]:rounded-pill [&>div]:cursor-pointer [&>div]:transition-colors [&>div]:duration-250 [&>div]:hover:bg-grey2"
|
|
2434
2522
|
>
|
|
2435
2523
|
<div class="scroll-viewport" data-radix-scroll-area-viewport bind:this={designScrollViewport}>
|
|
2436
|
-
<div class="px-6 {!designSchema || !contentSchema ? '
|
|
2524
|
+
<div class="px-6 {!designSchema || !contentSchema ? 'pt-7 pb-6' : 'pt-4 pb-6'}" bind:this={designContentWrapper}>
|
|
2437
2525
|
<Tabs.Content
|
|
2438
2526
|
value="design"
|
|
2439
|
-
class="design-tab-content
|
|
2527
|
+
class="design-tab-content mt-0! tabs-content-container w-full outline-none {isFirstLoad ? 'initial-load' : !isInitialTabLoad ? 'animate-slide-left' : ''}"
|
|
2440
2528
|
data-tab="design"
|
|
2441
2529
|
style="animation-duration: 300ms; transform: none;"
|
|
2442
2530
|
>
|
|
@@ -2495,12 +2583,13 @@
|
|
|
2495
2583
|
</div>
|
|
2496
2584
|
{/if}
|
|
2497
2585
|
|
|
2498
|
-
<div class="ic-input-ct {isFontIc ? 'w-full' : '
|
|
2499
|
-
<
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2586
|
+
<div class="ic-input-ct {isFontIc ? 'w-full' : 'shrink-0 ml-auto'}" style={isFontIc ? '' : 'width: 185px;'}>
|
|
2587
|
+
<InputControllerRenderer
|
|
2588
|
+
controller={describeInputController(InputComponent, {
|
|
2589
|
+
...props,
|
|
2590
|
+
value: reactiveValue !== undefined ? reactiveValue : props.value,
|
|
2591
|
+
shouldFocus: activeControllerId === props.id
|
|
2592
|
+
})}
|
|
2504
2593
|
/>
|
|
2505
2594
|
</div>
|
|
2506
2595
|
</div>
|
|
@@ -2533,7 +2622,7 @@
|
|
|
2533
2622
|
|
|
2534
2623
|
<!-- Content Tab Content -->
|
|
2535
2624
|
{#if contentSchema}
|
|
2536
|
-
<div class="tab-content-container
|
|
2625
|
+
<div class="tab-content-container grow overflow-y-auto scroll-area widgetic-colors hidden"
|
|
2537
2626
|
class:hidden={currentTab !== 'content'}
|
|
2538
2627
|
style="max-height: {!contentSchema || !designSchema ? '100%' : `calc(100% - ${HEADER_HEIGHT}px)`}"
|
|
2539
2628
|
data-scrollable={$contentScrollState.shouldShowScroll}
|
|
@@ -2542,13 +2631,13 @@
|
|
|
2542
2631
|
class="h-full"
|
|
2543
2632
|
type="hover"
|
|
2544
2633
|
scrollHideDelay={0}
|
|
2545
|
-
scrollbarYClasses="flex touch-none select-none transition-colors w-
|
|
2634
|
+
scrollbarYClasses="flex touch-none select-none transition-colors w-6 px-2 {headerContent ? 'bg-transparent' : 'bg-white'} {!designSchema || !contentSchema ? 'pt-7' : 'pt-4'} pb-6 [&>div]:w-2 [&>div]:bg-grey1 [&>div]:rounded-pill [&>div]:cursor-pointer [&>div]:transition-colors [&>div]:duration-250 [&>div]:hover:bg-grey2"
|
|
2546
2635
|
>
|
|
2547
2636
|
<div class="scroll-viewport" data-radix-scroll-area-viewport bind:this={contentScrollViewport}>
|
|
2548
|
-
<div class="px-6 {!designSchema || !contentSchema ? 'pt-
|
|
2637
|
+
<div class="px-6 {!designSchema || !contentSchema ? 'pt-7 pb-6' : 'pt-4 pb-6'}" bind:this={contentWrapper}>
|
|
2549
2638
|
<Tabs.Content
|
|
2550
2639
|
value="content"
|
|
2551
|
-
class="content-tab-content
|
|
2640
|
+
class="content-tab-content mt-0! tabs-content-container w-full {isFirstLoad ? 'initial-load' : !isInitialTabLoad ? 'animate-slide-right' : ''}"
|
|
2552
2641
|
data-tab="content"
|
|
2553
2642
|
style="transform: none; position: relative; z-index: 1;"
|
|
2554
2643
|
>
|
|
@@ -2561,7 +2650,7 @@
|
|
|
2561
2650
|
onOpenChange={() => isGenericContentOpen = !isGenericContentOpen}
|
|
2562
2651
|
>
|
|
2563
2652
|
<Collapsible.Trigger class="generic-content-trigger w-full">
|
|
2564
|
-
<div class="flex items-center h-
|
|
2653
|
+
<div class="flex items-center h-13" style="padding-left: {CONTENT_INNER_PADDING}px; padding-right: {CONTENT_INNER_PADDING}px;">
|
|
2565
2654
|
<h3 class="body-medium text-grey7 flex-1 content-title">{contentSchema?.genericContent?.title || 'Content'}</h3>
|
|
2566
2655
|
<ChevronDown class="h-6 w-6 text-grey5 transition-transform chevron" />
|
|
2567
2656
|
</div>
|
|
@@ -2574,7 +2663,7 @@
|
|
|
2574
2663
|
<Collapsible.Content>
|
|
2575
2664
|
{#if isGenericContentOpen}
|
|
2576
2665
|
<Card.Content class="p-0 px-4">
|
|
2577
|
-
<div class="pt-
|
|
2666
|
+
<div class="pt-3.5 pb-4">
|
|
2578
2667
|
<div class="properties-list flex flex-col" style="gap: 8px;">
|
|
2579
2668
|
{#each contentSchema?.genericContent?.properties || [] as property, propertyIndex}
|
|
2580
2669
|
{@const result = renderInputController(
|
|
@@ -2607,12 +2696,9 @@
|
|
|
2607
2696
|
</div>
|
|
2608
2697
|
{/if}
|
|
2609
2698
|
|
|
2610
|
-
<div class="ic-input-ct {isFontIc ? 'w-full' : '
|
|
2611
|
-
<
|
|
2612
|
-
|
|
2613
|
-
{...props}
|
|
2614
|
-
{header}
|
|
2615
|
-
shouldFocus={activeControllerId === props.id}
|
|
2699
|
+
<div class="ic-input-ct {isFontIc ? 'w-full' : 'shrink-0'}" style={isFontIc ? '' : 'width: 185px;'}>
|
|
2700
|
+
<InputControllerRenderer
|
|
2701
|
+
controller={describeInputController(InputComponent, { ...props, header, shouldFocus: activeControllerId === props.id })}
|
|
2616
2702
|
/>
|
|
2617
2703
|
</div>
|
|
2618
2704
|
</div>
|
|
@@ -2650,8 +2736,8 @@
|
|
|
2650
2736
|
onOpenChange={() => toggleItem(item.id)}
|
|
2651
2737
|
>
|
|
2652
2738
|
<Collapsible.Trigger class="content-item-trigger w-full">
|
|
2653
|
-
<div class="flex items-center h-
|
|
2654
|
-
<div class="drag-handle flex items-center justify-center w-
|
|
2739
|
+
<div class="flex items-center h-13 cursor-pointer widgetic-colors">
|
|
2740
|
+
<div class="drag-handle flex items-center justify-center w-14 cursor-move hover:text-grey5">
|
|
2655
2741
|
<IconGripVertical class="w-6 h-6 text-grey2 transition-colors duration-200" />
|
|
2656
2742
|
</div>
|
|
2657
2743
|
|
|
@@ -2674,7 +2760,7 @@
|
|
|
2674
2760
|
<Collapsible.Content>
|
|
2675
2761
|
{#if isItemOpen(item.id)}
|
|
2676
2762
|
<Card.Content class="p-0 px-4">
|
|
2677
|
-
<div class="pt-
|
|
2763
|
+
<div class="pt-3.5 pb-4">
|
|
2678
2764
|
<div class="properties-list flex flex-col" style="gap: 8px;">
|
|
2679
2765
|
{#each item.properties as property, propertyIndex}
|
|
2680
2766
|
{@const result = renderInputController(
|
|
@@ -2708,12 +2794,9 @@
|
|
|
2708
2794
|
</div>
|
|
2709
2795
|
{/if}
|
|
2710
2796
|
|
|
2711
|
-
<div class="ic-input-ct {isFontIc ? 'w-full' : '
|
|
2712
|
-
<
|
|
2713
|
-
|
|
2714
|
-
{...props}
|
|
2715
|
-
{header}
|
|
2716
|
-
shouldFocus={activeControllerId === props.id}
|
|
2797
|
+
<div class="ic-input-ct {isFontIc ? 'w-full' : 'shrink-0'}" style={isFontIc ? '' : 'width: 185px;'}>
|
|
2798
|
+
<InputControllerRenderer
|
|
2799
|
+
controller={describeInputController(InputComponent, { ...props, header, shouldFocus: activeControllerId === props.id })}
|
|
2717
2800
|
/>
|
|
2718
2801
|
</div>
|
|
2719
2802
|
</div>
|
|
@@ -2722,11 +2805,11 @@
|
|
|
2722
2805
|
</div>
|
|
2723
2806
|
|
|
2724
2807
|
<!-- Delete Item Button -->
|
|
2725
|
-
<div class="mt-
|
|
2808
|
+
<div class="mt-4 flex flex-col gap-2 relative z-10">
|
|
2726
2809
|
<!-- svelte-ignore a11y_mouse_events_have_key_events -->
|
|
2727
2810
|
<button
|
|
2728
2811
|
type="button"
|
|
2729
|
-
class="widgetic-colors h-
|
|
2812
|
+
class="widgetic-colors h-8.5 w-full flex items-center justify-center relative z-10 group"
|
|
2730
2813
|
style="
|
|
2731
2814
|
background-color: hsl(var(--error)) !important;
|
|
2732
2815
|
border-radius: var(--radius-small) !important;
|
|
@@ -2764,7 +2847,7 @@
|
|
|
2764
2847
|
<div class="content-add-item-ct mt-4">
|
|
2765
2848
|
<Button
|
|
2766
2849
|
variant="ghost"
|
|
2767
|
-
class="group w-full h-
|
|
2850
|
+
class="group w-full h-13 bg-grey1 hover:bg-grey2 active:scale-[0.98] border-2 border-grey2 rounded-medium"
|
|
2768
2851
|
style="transition: background-color 0.2s ease, transform 0.15s ease !important;"
|
|
2769
2852
|
onclick={handleAddNewItem}
|
|
2770
2853
|
>
|
|
@@ -2788,7 +2871,7 @@
|
|
|
2788
2871
|
<div
|
|
2789
2872
|
bind:this={fileBrowserPortalHost}
|
|
2790
2873
|
id="props-editor-file-browser-portal"
|
|
2791
|
-
class="props-editor-file-browser-portal pointer-events-none absolute inset-0 z-
|
|
2874
|
+
class="props-editor-file-browser-portal pointer-events-none absolute inset-0 z-999998"
|
|
2792
2875
|
></div>
|
|
2793
2876
|
</Tabs.Root>
|
|
2794
2877
|
</div>
|
|
@@ -2806,7 +2889,9 @@
|
|
|
2806
2889
|
.props-editor-container:not(:has(.header-hover-area)) {
|
|
2807
2890
|
position: relative;
|
|
2808
2891
|
}
|
|
2809
|
-
.props-editor-container:not(:has(.header-hover-area)):hover :global(.drag-handle-container)
|
|
2892
|
+
.props-editor-container:not(:has(.header-hover-area)):hover :global(.drag-handle-container),
|
|
2893
|
+
.props-editor-container:has(.header-hover-area:hover) :global(.props-editor-drag-bar .drag-handle-container),
|
|
2894
|
+
.props-editor-container :global(.props-editor-drag-bar:hover .drag-handle-container) {
|
|
2810
2895
|
opacity: 1 !important;
|
|
2811
2896
|
}
|
|
2812
2897
|
:global(.drag-handle-container) {
|
|
@@ -2844,6 +2929,23 @@
|
|
|
2844
2929
|
.props-editor-container:has(.tabs-header) {
|
|
2845
2930
|
--has-both-schemas: 1rem;
|
|
2846
2931
|
}
|
|
2932
|
+
|
|
2933
|
+
/* ── Save button (composition drag bar) ── */
|
|
2934
|
+
/* Icon stays put next to the text; label is centered in the remaining space
|
|
2935
|
+
with a small left bias so "Save" and "Saving" never shift the icon. */
|
|
2936
|
+
.props-editor-save-label {
|
|
2937
|
+
padding-left: 14px;
|
|
2938
|
+
line-height: 1;
|
|
2939
|
+
}
|
|
2940
|
+
.props-editor-save-btn .props-editor-save-icon {
|
|
2941
|
+
color: currentColor !important;
|
|
2942
|
+
stroke: currentColor !important;
|
|
2943
|
+
}
|
|
2944
|
+
.props-editor-save-label,
|
|
2945
|
+
:global(.props-editor-save-label) {
|
|
2946
|
+
color: currentColor !important;
|
|
2947
|
+
line-height: 1;
|
|
2948
|
+
}
|
|
2847
2949
|
:global(.content-items-wrapper) {
|
|
2848
2950
|
padding-top: 1rem;
|
|
2849
2951
|
}
|
|
@@ -33,6 +33,15 @@ declare const PropsEditor: $$__sveltets_2_IsomorphicComponent<{
|
|
|
33
33
|
defaultOpen?: boolean;
|
|
34
34
|
showDragHandle?: boolean;
|
|
35
35
|
enableDrag?: boolean;
|
|
36
|
+
/** Show Save status control in the top drag/header bar (composition page). */ showSaveButton?: boolean;
|
|
37
|
+
/** True when local edits are not yet persisted. */ saveDirty?: boolean;
|
|
38
|
+
/** True while a save request is in flight. */ saveSaving?: boolean;
|
|
39
|
+
/** Optional content below the shared toolbar, before property fields. */ headerContent?: any;
|
|
40
|
+
headerClass?: string;
|
|
41
|
+
dragHandleClass?: string;
|
|
42
|
+
title?: string;
|
|
43
|
+
/** Hide the default missing-schema message for header-only editors. */ showSchemaError?: boolean;
|
|
44
|
+
/** Optional layout wrapper moved by this editor's built-in drag and position API. */ positionTarget?: any;
|
|
36
45
|
initialDesignValues?: Record<string, any>;
|
|
37
46
|
initialContentValues?: Record<string, any>;
|
|
38
47
|
updateDesignValue?: (propertyId: string, value: any) => void;
|
|
@@ -42,6 +51,7 @@ declare const PropsEditor: $$__sveltets_2_IsomorphicComponent<{
|
|
|
42
51
|
top: number;
|
|
43
52
|
};
|
|
44
53
|
}, {
|
|
54
|
+
save: CustomEvent<any>;
|
|
45
55
|
updated: CustomEvent<any>;
|
|
46
56
|
propertyChange: CustomEvent<any>;
|
|
47
57
|
goToItem: CustomEvent<any>;
|
|
@@ -67,8 +67,6 @@
|
|
|
67
67
|
export let onChange: (newValue: string) => void; // Value change callback
|
|
68
68
|
export let controllerId: string = '';
|
|
69
69
|
export let id: string = '';
|
|
70
|
-
export let openDropdowns: any;
|
|
71
|
-
export let toggleDropdown: (id: string) => void;
|
|
72
70
|
export let config: InputControllerConfig = {}; // Additional configuration
|
|
73
71
|
export let helpText: string | undefined = undefined; // Help text for the input
|
|
74
72
|
|
|
@@ -21,8 +21,6 @@ declare const ColorPickerInputController: $$__sveltets_2_IsomorphicComponent<{
|
|
|
21
21
|
onChange: (newValue: string) => void;
|
|
22
22
|
controllerId?: string;
|
|
23
23
|
id?: string;
|
|
24
|
-
openDropdowns: any;
|
|
25
|
-
toggleDropdown: (id: string) => void;
|
|
26
24
|
config?: InputControllerConfig;
|
|
27
25
|
helpText?: string | undefined;
|
|
28
26
|
saveRecentColors?: boolean;
|