@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
|
@@ -51,6 +51,10 @@
|
|
|
51
51
|
*/
|
|
52
52
|
$: open = $openDropdowns?.has(controllerId) || false;
|
|
53
53
|
|
|
54
|
+
/** Timestamp of the last open — used to ignore bits-ui's own opening scrolls. */
|
|
55
|
+
let lastOpenTimestamp = 0;
|
|
56
|
+
$: if (open) lastOpenTimestamp = performance.now();
|
|
57
|
+
|
|
54
58
|
/**
|
|
55
59
|
* Closes the dropdown if it's currently open
|
|
56
60
|
* Used for cleanup and external close triggers
|
|
@@ -63,9 +67,25 @@
|
|
|
63
67
|
|
|
64
68
|
/**
|
|
65
69
|
* Scroll Event Handler
|
|
66
|
-
* Closes dropdown when scrolling occurs to prevent floating UI issues
|
|
70
|
+
* Closes dropdown when scrolling occurs to prevent floating UI issues.
|
|
71
|
+
* Guarded: bits-ui may scroll the viewport/list right after opening, and the
|
|
72
|
+
* capture-phase listener would otherwise close the dropdown in the same frame
|
|
73
|
+
* (which looked like "the dropdown never opens" in the Embed overlay).
|
|
67
74
|
*/
|
|
68
|
-
function handleScroll() {
|
|
75
|
+
function handleScroll(event?: Event) {
|
|
76
|
+
if (!open) return;
|
|
77
|
+
// Grace period after opening — ignore self-inflicted scrolls from bits-ui.
|
|
78
|
+
if (performance.now() - lastOpenTimestamp < 300) return;
|
|
79
|
+
// Never close on scrolls that happen inside the dropdown itself or its portal.
|
|
80
|
+
const target = event?.target as Node | null;
|
|
81
|
+
if (
|
|
82
|
+
target instanceof Element &&
|
|
83
|
+
(target.closest('[data-bits-floating-content-wrapper]') ||
|
|
84
|
+
target.closest('[role="listbox"]') ||
|
|
85
|
+
target.closest('.dropdown-ic-content'))
|
|
86
|
+
) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
69
89
|
closeDropdown();
|
|
70
90
|
}
|
|
71
91
|
|
|
@@ -104,7 +124,8 @@
|
|
|
104
124
|
}
|
|
105
125
|
}
|
|
106
126
|
|
|
107
|
-
$:
|
|
127
|
+
$: selectedValue = typeof value === 'string' ? value : value?.value ?? '';
|
|
128
|
+
$: triggerContent = options.find((option) => option.value === selectedValue)?.label ?? defaultSelectedLabel;
|
|
108
129
|
</script>
|
|
109
130
|
|
|
110
131
|
<!-- Dropdown Container -->
|
|
@@ -122,7 +143,7 @@
|
|
|
122
143
|
>
|
|
123
144
|
<Select.Root
|
|
124
145
|
type="single"
|
|
125
|
-
value={
|
|
146
|
+
value={selectedValue}
|
|
126
147
|
onValueChange={handleValueChange}
|
|
127
148
|
open={open}
|
|
128
149
|
onOpenChange={handleOpenChange}
|
|
@@ -218,9 +239,13 @@
|
|
|
218
239
|
display: none;
|
|
219
240
|
}
|
|
220
241
|
|
|
221
|
-
/*
|
|
222
|
-
|
|
242
|
+
/* bits-ui portals the Select content to <body> and wraps it in
|
|
243
|
+
[data-bits-floating-content-wrapper]. The floating layer's default z-index
|
|
244
|
+
(50) sat below page overlays — in the composition Embed overlay
|
|
245
|
+
(z-index 100000) the dropdown opened but was painted behind the dark
|
|
246
|
+
backdrop, so it looked like it never opened. Lift the wrapper above any
|
|
247
|
+
app overlay. */
|
|
223
248
|
:global([data-bits-floating-content-wrapper]) {
|
|
224
|
-
z-index:
|
|
249
|
+
z-index: 1000001 !important;
|
|
225
250
|
}
|
|
226
251
|
</style>
|
|
@@ -95,6 +95,7 @@
|
|
|
95
95
|
// Font weight state - remove localStorage check on init
|
|
96
96
|
let selectedWeight = `${controllerId}-Regular`;
|
|
97
97
|
let availableWeights: string[] = ['Regular', 'Medium', 'SemiBold', 'Bold'];
|
|
98
|
+
let fontCatalogFallbackWarned = false;
|
|
98
99
|
|
|
99
100
|
// Font search and filter state
|
|
100
101
|
let allFonts: FontItem[] = [];
|
|
@@ -625,7 +626,7 @@
|
|
|
625
626
|
|
|
626
627
|
// try {
|
|
627
628
|
// // Get the current font's ID if it exists in our custom fonts
|
|
628
|
-
// const selectedId =
|
|
629
|
+
// const selectedId = resolvedFont?.family ?
|
|
629
630
|
// fontManagerInstance?.getCachedFontList()
|
|
630
631
|
// .find(f => f.family === value.family && f.category === 'Mine')?.id
|
|
631
632
|
// : undefined;
|
|
@@ -1360,6 +1361,9 @@
|
|
|
1360
1361
|
*/
|
|
1361
1362
|
async function fetchFontWeights(fontFamily: string) {
|
|
1362
1363
|
try {
|
|
1364
|
+
// Wait for FontManager init — reactive weight fetch can race ahead of onMount.
|
|
1365
|
+
fontManagerInstance = await FontManager.getInstance(appConfig.GOOGLE_FONTS_API_KEY);
|
|
1366
|
+
|
|
1363
1367
|
// First check if it's a custom font using FontManager
|
|
1364
1368
|
if (fontManagerInstance?.isCustomFont(fontFamily)) {
|
|
1365
1369
|
// Get custom font data
|
|
@@ -1397,7 +1401,16 @@
|
|
|
1397
1401
|
}
|
|
1398
1402
|
|
|
1399
1403
|
// Google font: use catalog cached by FontManager (no extra API call per font)
|
|
1400
|
-
|
|
1404
|
+
let variantIds = fontManagerInstance?.getGoogleFontVariantIds(fontFamily);
|
|
1405
|
+
if (!variantIds?.length) {
|
|
1406
|
+
// Catalog may still be empty right after init edge cases — force list load once.
|
|
1407
|
+
try {
|
|
1408
|
+
await fontManagerInstance.getInitialFontList();
|
|
1409
|
+
} catch (catalogError) {
|
|
1410
|
+
console.warn('[FontInput] Catalog refresh failed before weight lookup:', catalogError);
|
|
1411
|
+
}
|
|
1412
|
+
variantIds = fontManagerInstance?.getGoogleFontVariantIds(fontFamily);
|
|
1413
|
+
}
|
|
1401
1414
|
if (variantIds?.length) {
|
|
1402
1415
|
availableWeights = mapGoogleVariantIdsToWeightNames(variantIds);
|
|
1403
1416
|
if (!availableWeights.includes(selectedWeight.replace(`${controllerId}-`, ''))) {
|
|
@@ -1407,7 +1420,11 @@
|
|
|
1407
1420
|
}
|
|
1408
1421
|
|
|
1409
1422
|
// API unavailable (403 / no catalog): sensible defaults, still loads via fonts.googleapis.com CSS
|
|
1410
|
-
|
|
1423
|
+
// Warn once — not on every reactive re-run during catalog race.
|
|
1424
|
+
if (!fontCatalogFallbackWarned) {
|
|
1425
|
+
fontCatalogFallbackWarned = true;
|
|
1426
|
+
console.warn('[FontInput] Using default weights (Google catalog not loaded). Later fonts will use the same fallback silently.');
|
|
1427
|
+
}
|
|
1411
1428
|
availableWeights = ['Regular', 'Bold'];
|
|
1412
1429
|
selectedWeight = `${controllerId}-Regular`;
|
|
1413
1430
|
} catch (error) {
|
|
@@ -1431,7 +1448,7 @@
|
|
|
1431
1448
|
*/
|
|
1432
1449
|
function highlightMatch(name: string, term: string) {
|
|
1433
1450
|
// Check if this font is the selected one
|
|
1434
|
-
const isSelected =
|
|
1451
|
+
const isSelected = resolvedFont?.family === name;
|
|
1435
1452
|
|
|
1436
1453
|
if (!term) {
|
|
1437
1454
|
// If no search term, just return the name with appropriate color
|
|
@@ -1558,7 +1575,7 @@
|
|
|
1558
1575
|
await fontManagerInstance?.removeCustomFont(fontFamily);
|
|
1559
1576
|
|
|
1560
1577
|
// If the removed font was selected, clear the selection
|
|
1561
|
-
if (
|
|
1578
|
+
if (resolvedFont?.family === fontFamily && onChange) {
|
|
1562
1579
|
onChange({
|
|
1563
1580
|
family: '',
|
|
1564
1581
|
weight: 'Regular',
|
|
@@ -1719,7 +1736,7 @@
|
|
|
1719
1736
|
}
|
|
1720
1737
|
}}
|
|
1721
1738
|
>
|
|
1722
|
-
<Popover.Trigger tabindex=
|
|
1739
|
+
<Popover.Trigger tabindex={-1} class="w-full h-full flex items-center border-0 bg-transparent hover:bg-transparent focus:bg-transparent pl-3 pr-[16px] group"
|
|
1723
1740
|
onmouseenter={() => {
|
|
1724
1741
|
// Preload fonts when hovering over the button
|
|
1725
1742
|
// This reduces the delay when actually clicking to open
|
|
@@ -1896,7 +1913,7 @@
|
|
|
1896
1913
|
<div
|
|
1897
1914
|
role="button"
|
|
1898
1915
|
tabindex="-1"
|
|
1899
|
-
class="ml-auto transition-opacity {
|
|
1916
|
+
class="ml-auto transition-opacity {resolvedFont?.family === font.family ? 'opacity-0 pointer-events-none' : 'opacity-0 group-hover:opacity-100'}"
|
|
1900
1917
|
onclick={(e) => {
|
|
1901
1918
|
e.stopPropagation();
|
|
1902
1919
|
e.preventDefault();
|
|
@@ -1939,7 +1956,7 @@
|
|
|
1939
1956
|
}
|
|
1940
1957
|
}}
|
|
1941
1958
|
>
|
|
1942
|
-
<Popover.Trigger tabindex=
|
|
1959
|
+
<Popover.Trigger tabindex={-1} class="w-full h-full flex items-center border-0 bg-transparent hover:bg-transparent focus:bg-transparent pl-3 pr-[16px] group">
|
|
1943
1960
|
<span class="truncate flex-1 text-left subtext text-grey7">
|
|
1944
1961
|
{displayWeight || 'Regular'}
|
|
1945
1962
|
</span>
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
<script module lang="ts">
|
|
2
|
+
import type { ComponentProps } from 'svelte';
|
|
3
|
+
import {
|
|
4
|
+
TextInputController, TextAreaPreviewInputController, NumberInputController,
|
|
5
|
+
SliderInputController, SliderRangeInputController, DropdownInputController,
|
|
6
|
+
DatePickerInputController, DateFieldInputController, RangeCalendarInputController,
|
|
7
|
+
SwitchInputController, ColorPickerInputController, CheckboxInputController,
|
|
8
|
+
RadioGroupInputController, FontInputController, PositionInputController,
|
|
9
|
+
BrowserInputController, FixedPositionInputController, VectorInputController,
|
|
10
|
+
AngleInputController, TimeInputController, RoundedCornersInputController, TagsInputController
|
|
11
|
+
} from './index';
|
|
12
|
+
|
|
13
|
+
type ControllerComponents = {
|
|
14
|
+
textinput: typeof TextInputController;
|
|
15
|
+
textarea: typeof TextAreaPreviewInputController;
|
|
16
|
+
number: typeof NumberInputController;
|
|
17
|
+
slider: typeof SliderInputController;
|
|
18
|
+
sliderrange: typeof SliderRangeInputController;
|
|
19
|
+
dropdown: typeof DropdownInputController;
|
|
20
|
+
datepicker: typeof DatePickerInputController;
|
|
21
|
+
datefield: typeof DateFieldInputController;
|
|
22
|
+
rangecalendar: typeof RangeCalendarInputController;
|
|
23
|
+
switch: typeof SwitchInputController;
|
|
24
|
+
colorpicker: typeof ColorPickerInputController;
|
|
25
|
+
checkbox: typeof CheckboxInputController;
|
|
26
|
+
radiogroup: typeof RadioGroupInputController;
|
|
27
|
+
font: typeof FontInputController;
|
|
28
|
+
position: typeof PositionInputController;
|
|
29
|
+
browser: typeof BrowserInputController;
|
|
30
|
+
fixedposition: typeof FixedPositionInputController;
|
|
31
|
+
vector: typeof VectorInputController;
|
|
32
|
+
angle: typeof AngleInputController;
|
|
33
|
+
time: typeof TimeInputController;
|
|
34
|
+
roundedcorners: typeof RoundedCornersInputController;
|
|
35
|
+
tags: typeof TagsInputController;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// Each branch preserves the relationship between a controller and its props.
|
|
39
|
+
export type ControllerDescriptor = {
|
|
40
|
+
[Kind in keyof ControllerComponents]: { kind: Kind; props: ComponentProps<ControllerComponents[Kind]> }
|
|
41
|
+
}[keyof ControllerComponents];
|
|
42
|
+
</script>
|
|
43
|
+
|
|
44
|
+
<script lang="ts">
|
|
45
|
+
let { controller, class: className = '', style = '' }: {
|
|
46
|
+
controller: ControllerDescriptor | null;
|
|
47
|
+
class?: string;
|
|
48
|
+
style?: string;
|
|
49
|
+
} = $props();
|
|
50
|
+
</script>
|
|
51
|
+
|
|
52
|
+
<div class="input-controller-renderer contents {className}" {style}>
|
|
53
|
+
{#if controller?.kind === 'textinput'}
|
|
54
|
+
<TextInputController {...controller.props} />
|
|
55
|
+
{:else if controller?.kind === 'textarea'}
|
|
56
|
+
<TextAreaPreviewInputController {...controller.props} />
|
|
57
|
+
{:else if controller?.kind === 'number'}
|
|
58
|
+
<NumberInputController {...controller.props} />
|
|
59
|
+
{:else if controller?.kind === 'slider'}
|
|
60
|
+
<SliderInputController {...controller.props} />
|
|
61
|
+
{:else if controller?.kind === 'sliderrange'}
|
|
62
|
+
<SliderRangeInputController {...controller.props} />
|
|
63
|
+
{:else if controller?.kind === 'dropdown'}
|
|
64
|
+
<DropdownInputController {...controller.props} />
|
|
65
|
+
{:else if controller?.kind === 'datepicker'}
|
|
66
|
+
<DatePickerInputController {...controller.props} />
|
|
67
|
+
{:else if controller?.kind === 'datefield'}
|
|
68
|
+
<DateFieldInputController {...controller.props} />
|
|
69
|
+
{:else if controller?.kind === 'rangecalendar'}
|
|
70
|
+
<RangeCalendarInputController {...controller.props} />
|
|
71
|
+
{:else if controller?.kind === 'switch'}
|
|
72
|
+
<SwitchInputController {...controller.props} />
|
|
73
|
+
{:else if controller?.kind === 'colorpicker'}
|
|
74
|
+
<ColorPickerInputController {...controller.props} />
|
|
75
|
+
{:else if controller?.kind === 'checkbox'}
|
|
76
|
+
<CheckboxInputController {...controller.props} />
|
|
77
|
+
{:else if controller?.kind === 'radiogroup'}
|
|
78
|
+
<RadioGroupInputController {...controller.props} />
|
|
79
|
+
{:else if controller?.kind === 'font'}
|
|
80
|
+
<FontInputController {...controller.props} />
|
|
81
|
+
{:else if controller?.kind === 'position'}
|
|
82
|
+
<PositionInputController {...controller.props} />
|
|
83
|
+
{:else if controller?.kind === 'browser'}
|
|
84
|
+
<BrowserInputController {...controller.props} />
|
|
85
|
+
{:else if controller?.kind === 'fixedposition'}
|
|
86
|
+
<FixedPositionInputController {...controller.props} />
|
|
87
|
+
{:else if controller?.kind === 'vector'}
|
|
88
|
+
<VectorInputController {...controller.props} />
|
|
89
|
+
{:else if controller?.kind === 'angle'}
|
|
90
|
+
<AngleInputController {...controller.props} />
|
|
91
|
+
{:else if controller?.kind === 'time'}
|
|
92
|
+
<TimeInputController {...controller.props} />
|
|
93
|
+
{:else if controller?.kind === 'roundedcorners'}
|
|
94
|
+
<RoundedCornersInputController {...controller.props} />
|
|
95
|
+
{:else if controller?.kind === 'tags'}
|
|
96
|
+
<TagsInputController {...controller.props} />
|
|
97
|
+
{/if}
|
|
98
|
+
</div>
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { ComponentProps } from 'svelte';
|
|
2
|
+
import { TextInputController, TextAreaPreviewInputController, NumberInputController, SliderInputController, SliderRangeInputController, DropdownInputController, DatePickerInputController, DateFieldInputController, RangeCalendarInputController, SwitchInputController, ColorPickerInputController, CheckboxInputController, RadioGroupInputController, FontInputController, PositionInputController, BrowserInputController, FixedPositionInputController, VectorInputController, AngleInputController, TimeInputController, RoundedCornersInputController, TagsInputController } from './index';
|
|
3
|
+
type ControllerComponents = {
|
|
4
|
+
textinput: typeof TextInputController;
|
|
5
|
+
textarea: typeof TextAreaPreviewInputController;
|
|
6
|
+
number: typeof NumberInputController;
|
|
7
|
+
slider: typeof SliderInputController;
|
|
8
|
+
sliderrange: typeof SliderRangeInputController;
|
|
9
|
+
dropdown: typeof DropdownInputController;
|
|
10
|
+
datepicker: typeof DatePickerInputController;
|
|
11
|
+
datefield: typeof DateFieldInputController;
|
|
12
|
+
rangecalendar: typeof RangeCalendarInputController;
|
|
13
|
+
switch: typeof SwitchInputController;
|
|
14
|
+
colorpicker: typeof ColorPickerInputController;
|
|
15
|
+
checkbox: typeof CheckboxInputController;
|
|
16
|
+
radiogroup: typeof RadioGroupInputController;
|
|
17
|
+
font: typeof FontInputController;
|
|
18
|
+
position: typeof PositionInputController;
|
|
19
|
+
browser: typeof BrowserInputController;
|
|
20
|
+
fixedposition: typeof FixedPositionInputController;
|
|
21
|
+
vector: typeof VectorInputController;
|
|
22
|
+
angle: typeof AngleInputController;
|
|
23
|
+
time: typeof TimeInputController;
|
|
24
|
+
roundedcorners: typeof RoundedCornersInputController;
|
|
25
|
+
tags: typeof TagsInputController;
|
|
26
|
+
};
|
|
27
|
+
export type ControllerDescriptor = {
|
|
28
|
+
[Kind in keyof ControllerComponents]: {
|
|
29
|
+
kind: Kind;
|
|
30
|
+
props: ComponentProps<ControllerComponents[Kind]>;
|
|
31
|
+
};
|
|
32
|
+
}[keyof ControllerComponents];
|
|
33
|
+
type $$ComponentProps = {
|
|
34
|
+
controller: ControllerDescriptor | null;
|
|
35
|
+
class?: string;
|
|
36
|
+
style?: string;
|
|
37
|
+
};
|
|
38
|
+
declare const InputControllerRenderer: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
39
|
+
type InputControllerRenderer = ReturnType<typeof InputControllerRenderer>;
|
|
40
|
+
export default InputControllerRenderer;
|
|
@@ -26,7 +26,6 @@
|
|
|
26
26
|
export let label: string;
|
|
27
27
|
export let value: { topLeft: number; topRight: number; bottomRight: number; bottomLeft: number };
|
|
28
28
|
export let onChange: (newValue: { topLeft: number; topRight: number; bottomRight: number; bottomLeft: number }) => void;
|
|
29
|
-
export let config: InputControllerConfig = {};
|
|
30
29
|
export let helpText: string | undefined = undefined;
|
|
31
30
|
export let onFocus: () => void = () => {};
|
|
32
31
|
|
|
@@ -269,7 +268,7 @@
|
|
|
269
268
|
</script>
|
|
270
269
|
|
|
271
270
|
<!-- Main corner radius grid component -->
|
|
272
|
-
<div class="corners-container {className}"
|
|
271
|
+
<div class="corners-container {className}" role="group" aria-label={label || 'Corner radius'} title={helpText}
|
|
273
272
|
on:mouseenter={handleMouseEnter}
|
|
274
273
|
on:mouseleave={handleMouseLeave}
|
|
275
274
|
on:focusin={onFocus}>
|
|
@@ -360,9 +359,9 @@
|
|
|
360
359
|
aria-pressed={isLocked}
|
|
361
360
|
>
|
|
362
361
|
<div class="flex items-center justify-center w-full h-full {isLocked ? 'text-sage-green' : 'text-grey7'}">
|
|
363
|
-
<svelte:component
|
|
364
|
-
this={isLocked ? Lock : Unlock}
|
|
365
|
-
class="w-5 h-5"
|
|
362
|
+
<svelte:component
|
|
363
|
+
this={isLocked ? Lock : Unlock}
|
|
364
|
+
class="w-5 h-5"
|
|
366
365
|
/>
|
|
367
366
|
</div>
|
|
368
367
|
</button>
|
|
@@ -372,19 +371,10 @@
|
|
|
372
371
|
<div
|
|
373
372
|
class="border-overlay {isHovering ? 'hovered' : ''}"
|
|
374
373
|
aria-hidden="true"
|
|
375
|
-
|
|
374
|
+
></div>
|
|
376
375
|
</div>
|
|
377
376
|
|
|
378
377
|
<style>
|
|
379
|
-
/* Hide number input spinners */
|
|
380
|
-
/* svelte-ignore css_unused_selector */
|
|
381
|
-
input[type="number"]::-webkit-inner-spin-button,
|
|
382
|
-
/* svelte-ignore css_unused_selector */
|
|
383
|
-
input[type="number"]::-webkit-outer-spin-button {
|
|
384
|
-
-webkit-appearance: none;
|
|
385
|
-
margin: 0;
|
|
386
|
-
}
|
|
387
|
-
|
|
388
378
|
input {
|
|
389
379
|
-moz-appearance: textfield;
|
|
390
380
|
appearance: textfield;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { InputControllerConfig } from './index';
|
|
2
1
|
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
3
2
|
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
4
3
|
$$bindings?: Bindings;
|
|
@@ -26,7 +25,6 @@ declare const RoundedCornersInputController: $$__sveltets_2_IsomorphicComponent<
|
|
|
26
25
|
bottomRight: number;
|
|
27
26
|
bottomLeft: number;
|
|
28
27
|
}) => void;
|
|
29
|
-
config?: InputControllerConfig;
|
|
30
28
|
helpText?: string | undefined;
|
|
31
29
|
onFocus?: () => void;
|
|
32
30
|
class?: string;
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
}>();
|
|
84
84
|
|
|
85
85
|
// Use config values with fallbacks
|
|
86
|
-
const textColor = config.textColor || '#1a1a1a';
|
|
86
|
+
const textColor = $derived(config.textColor || '#1a1a1a');
|
|
87
87
|
|
|
88
88
|
/**
|
|
89
89
|
* State Variables
|
|
@@ -121,7 +121,7 @@
|
|
|
121
121
|
let currentTextStyle = $state('text'); // Track current text style
|
|
122
122
|
|
|
123
123
|
let showColorPicker = $state(false);
|
|
124
|
-
let currentColor = $
|
|
124
|
+
let currentColor = $derived(textColor);
|
|
125
125
|
let selectedTextRange: { from: number, to: number } | null = $state(null);
|
|
126
126
|
|
|
127
127
|
const textOptions = [
|
|
@@ -159,16 +159,16 @@
|
|
|
159
159
|
|
|
160
160
|
|
|
161
161
|
|
|
162
|
-
//
|
|
163
|
-
const editorStyle =
|
|
162
|
+
// Static styles — avoid $derived so teardown does not leave inert derived reads.
|
|
163
|
+
const editorStyle = `
|
|
164
164
|
--editor-min-height: auto;
|
|
165
165
|
--editor-max-height: none;
|
|
166
166
|
--transition-duration: 0ms;
|
|
167
167
|
--transition-timing: ease-out;
|
|
168
|
-
|
|
168
|
+
`;
|
|
169
169
|
|
|
170
170
|
// Add this with other state declarations
|
|
171
|
-
let editorClass =
|
|
171
|
+
let editorClass = 'border-none overflow-auto editor-height';
|
|
172
172
|
|
|
173
173
|
// Add state to track if any dropdown is open
|
|
174
174
|
let isDropdownOpen = $state(false);
|
|
@@ -191,6 +191,7 @@
|
|
|
191
191
|
// Add these new state variables after the other state declarations
|
|
192
192
|
let lastKnownContent = $state('');
|
|
193
193
|
let wasVisible = $state(true);
|
|
194
|
+
let isDestroyed = false;
|
|
194
195
|
|
|
195
196
|
function handleEditorMount(e: any) {
|
|
196
197
|
editorInstance = e.detail.editor;
|
|
@@ -361,6 +362,7 @@
|
|
|
361
362
|
// Only update if there's a change to prevent unnecessary rerenders
|
|
362
363
|
if (JSON.stringify(newFormats) !== JSON.stringify($state.snapshot(activeFormats))) {
|
|
363
364
|
activeFormats = newFormats;
|
|
365
|
+
syncToggleValues();
|
|
364
366
|
// console.log('Active formats updated:', $state.snapshot(activeFormats));
|
|
365
367
|
}
|
|
366
368
|
}
|
|
@@ -440,11 +442,20 @@
|
|
|
440
442
|
}
|
|
441
443
|
}
|
|
442
444
|
|
|
443
|
-
//
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
445
|
+
// Compute toggle values without $derived — TipTap callbacks can run after unmount
|
|
446
|
+
// and reading an inert derived triggers Svelte's derived_inert warning.
|
|
447
|
+
function getToggleValues(): string[] {
|
|
448
|
+
if (isDestroyed) return [];
|
|
449
|
+
return Object.entries(activeFormats)
|
|
450
|
+
.filter(([_, isActive]) => isActive)
|
|
451
|
+
.map(([format]) => formatMapping[format as FormatType].value);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
let toggleValues = $state<string[]>([]);
|
|
455
|
+
function syncToggleValues() {
|
|
456
|
+
if (isDestroyed) return;
|
|
457
|
+
toggleValues = getToggleValues();
|
|
458
|
+
}
|
|
448
459
|
|
|
449
460
|
// Restore handleTextStyleChange for other style changes
|
|
450
461
|
function handleTextStyleChange(value: string) {
|
|
@@ -823,7 +834,9 @@
|
|
|
823
834
|
|
|
824
835
|
// Add effect to handle clicks outside Color Select
|
|
825
836
|
$effect(() => {
|
|
837
|
+
if (isDestroyed) return;
|
|
826
838
|
const handleClickOutside = (event: MouseEvent) => {
|
|
839
|
+
if (isDestroyed) return;
|
|
827
840
|
const colorSelectModal = document.querySelector('[data-radix-popper-content-wrapper]');
|
|
828
841
|
const isClickingColorSelect = colorSelectModal?.contains(event.target as Node);
|
|
829
842
|
|
|
@@ -896,6 +909,7 @@
|
|
|
896
909
|
|
|
897
910
|
// Update the effect that maintains selection during color picker interactions
|
|
898
911
|
$effect(() => {
|
|
912
|
+
if (isDestroyed) return;
|
|
899
913
|
if (showColorPicker && selectedTextRange && editorInstance) {
|
|
900
914
|
const { from, to } = selectedTextRange;
|
|
901
915
|
editorInstance.chain()
|
|
@@ -1020,6 +1034,7 @@
|
|
|
1020
1034
|
|
|
1021
1035
|
// Add cleanup function
|
|
1022
1036
|
onDestroy(() => {
|
|
1037
|
+
isDestroyed = true;
|
|
1023
1038
|
if (editorInstance) {
|
|
1024
1039
|
// Store the current content before unmounting
|
|
1025
1040
|
lastKnownContent = editorInstance.getHTML();
|
|
@@ -1336,8 +1351,6 @@
|
|
|
1336
1351
|
handleColorChange(color);
|
|
1337
1352
|
}}
|
|
1338
1353
|
controllerId="text-color-picker"
|
|
1339
|
-
{openDropdowns}
|
|
1340
|
-
{toggleDropdown}
|
|
1341
1354
|
saveRecentColors={true}
|
|
1342
1355
|
showOpacityControls={false}
|
|
1343
1356
|
showRing={false}
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
<
|
|
1
|
+
<script>
|
|
2
|
+
let { class: className = '', style = '' } = $props();
|
|
3
|
+
</script>
|
|
4
|
+
|
|
5
|
+
<svg class="locked-icon {className}" {style} width="12" height="22" viewBox="0 0 12 22" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
6
|
<path d="M1 6C1 4.67392 1.52678 3.40215 2.46447 2.46447C3.40215 1.52678 4.67392 1 6 1C7.32608 1 8.59785 1.52678 9.53553 2.46447C10.4732 3.40215 11 4.67392 11 6V16C11 17.3261 10.4732 18.5979 9.53553 19.5355C8.59785 20.4732 7.32608 21 6 21C4.67392 21 3.40215 20.4732 2.46447 19.5355C1.52678 18.5979 1 17.3261 1 16V6Z" stroke="#7BA668" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
3
7
|
<rect x="5" y="6" width="2" height="10" fill="#7BA668"/>
|
|
4
8
|
</svg>
|
|
@@ -1,26 +1,13 @@
|
|
|
1
1
|
export default Locked;
|
|
2
|
-
type Locked =
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
type Locked = {
|
|
3
|
+
$on?(type: string, callback: (e: any) => void): () => void;
|
|
4
|
+
$set?(props: Partial<$$ComponentProps>): void;
|
|
5
|
+
};
|
|
6
|
+
declare const Locked: import("svelte").Component<{
|
|
7
|
+
class?: string;
|
|
8
|
+
style?: string;
|
|
9
|
+
}, {}, "">;
|
|
10
|
+
type $$ComponentProps = {
|
|
11
|
+
class?: string;
|
|
12
|
+
style?: string;
|
|
8
13
|
};
|
|
9
|
-
declare const Locked: $$__sveltets_2_IsomorphicComponent<{
|
|
10
|
-
[x: string]: never;
|
|
11
|
-
}, {
|
|
12
|
-
[evt: string]: CustomEvent<any>;
|
|
13
|
-
}, {}, {}, string>;
|
|
14
|
-
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
15
|
-
new (options: import("svelte").ComponentConstructorOptions<Props>): import("svelte").SvelteComponent<Props, Events, Slots> & {
|
|
16
|
-
$$bindings?: Bindings;
|
|
17
|
-
} & Exports;
|
|
18
|
-
(internal: unknown, props: {
|
|
19
|
-
$$events?: Events;
|
|
20
|
-
$$slots?: Slots;
|
|
21
|
-
}): Exports & {
|
|
22
|
-
$set?: any;
|
|
23
|
-
$on?: any;
|
|
24
|
-
};
|
|
25
|
-
z_$$bindings?: Bindings;
|
|
26
|
-
}
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
<
|
|
1
|
+
<script>
|
|
2
|
+
let { class: className = '', style = '' } = $props();
|
|
3
|
+
</script>
|
|
4
|
+
|
|
5
|
+
<svg class="unlocked-icon {className}" {style} width="12" height="22" viewBox="0 0 12 22" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
6
|
<path d="M3.17157 3.17157C3.92172 2.42143 4.93913 2 6 2C7.06087 2 8.07828 2.42143 8.82843 3.17157C9.57857 3.92172 10 4.93913 10 6V10H12V6C12 4.4087 11.3679 2.88258 10.2426 1.75736C9.11742 0.632141 7.5913 0 6 0C4.4087 0 2.88258 0.632141 1.75736 1.75736C0.632141 2.88258 0 4.4087 0 6V10H2V6C2 4.93913 2.42143 3.92172 3.17157 3.17157Z" fill="#666666"/>
|
|
3
7
|
<path d="M2 12H0V16C0 17.5913 0.632141 19.1174 1.75736 20.2426C2.88258 21.3679 4.4087 22 6 22C7.5913 22 9.11742 21.3679 10.2426 20.2426C11.3679 19.1174 12 17.5913 12 16V12H10V16C10 17.0609 9.57857 18.0783 8.82843 18.8284C8.07828 19.5786 7.06087 20 6 20C4.93913 20 3.92172 19.5786 3.17157 18.8284C2.42143 18.0783 2 17.0609 2 16V12Z" fill="#666666"/>
|
|
4
8
|
</svg>
|
|
@@ -1,26 +1,13 @@
|
|
|
1
1
|
export default Unlocked;
|
|
2
|
-
type Unlocked =
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
type Unlocked = {
|
|
3
|
+
$on?(type: string, callback: (e: any) => void): () => void;
|
|
4
|
+
$set?(props: Partial<$$ComponentProps>): void;
|
|
5
|
+
};
|
|
6
|
+
declare const Unlocked: import("svelte").Component<{
|
|
7
|
+
class?: string;
|
|
8
|
+
style?: string;
|
|
9
|
+
}, {}, "">;
|
|
10
|
+
type $$ComponentProps = {
|
|
11
|
+
class?: string;
|
|
12
|
+
style?: string;
|
|
8
13
|
};
|
|
9
|
-
declare const Unlocked: $$__sveltets_2_IsomorphicComponent<{
|
|
10
|
-
[x: string]: never;
|
|
11
|
-
}, {
|
|
12
|
-
[evt: string]: CustomEvent<any>;
|
|
13
|
-
}, {}, {}, string>;
|
|
14
|
-
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
15
|
-
new (options: import("svelte").ComponentConstructorOptions<Props>): import("svelte").SvelteComponent<Props, Events, Slots> & {
|
|
16
|
-
$$bindings?: Bindings;
|
|
17
|
-
} & Exports;
|
|
18
|
-
(internal: unknown, props: {
|
|
19
|
-
$$events?: Events;
|
|
20
|
-
$$slots?: Slots;
|
|
21
|
-
}): Exports & {
|
|
22
|
-
$set?: any;
|
|
23
|
-
$on?: any;
|
|
24
|
-
};
|
|
25
|
-
z_$$bindings?: Bindings;
|
|
26
|
-
}
|
|
@@ -245,13 +245,20 @@ class FontManager {
|
|
|
245
245
|
* Gets or creates the singleton instance and initializes it
|
|
246
246
|
*/
|
|
247
247
|
static async getInstance(apiKey) {
|
|
248
|
+
const trimmedKey = String(apiKey || '').trim();
|
|
248
249
|
if (!FontManager.instance) {
|
|
249
|
-
FontManager.instance = new FontManager(
|
|
250
|
-
// Initialize only once
|
|
250
|
+
FontManager.instance = new FontManager(trimmedKey);
|
|
251
251
|
if (!FontManager.initializationPromise) {
|
|
252
252
|
FontManager.initializationPromise = FontManager.instance.initialize();
|
|
253
253
|
}
|
|
254
|
-
|
|
254
|
+
}
|
|
255
|
+
else if (trimmedKey && !FontManager.instance.apiKey?.trim()) {
|
|
256
|
+
// Key arrived after a premature empty-key construction (race with setGoogleFontsApiKey).
|
|
257
|
+
FontManager.instance.apiKey = trimmedKey;
|
|
258
|
+
FontManager.instance.catalogFetchPromise = null;
|
|
259
|
+
}
|
|
260
|
+
// Always await in-flight init — concurrent callers used to return mid-initialize.
|
|
261
|
+
if (FontManager.initializationPromise) {
|
|
255
262
|
await FontManager.initializationPromise;
|
|
256
263
|
}
|
|
257
264
|
return FontManager.instance;
|