@widgetic/editor 4.0.1 → 4.0.3
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/MockWidget.svelte +1 -1
- package/dist/components/WidgetPreview.svelte +36 -52
- package/dist/components/editors/EmbedEditor.svelte +1 -1
- package/dist/components/editors/PropsEditor.svelte +309 -227
- package/dist/components/ic/BrowserInputController.svelte +26 -19
- package/dist/components/ic/CheckboxInputController.svelte +1 -1
- package/dist/components/ic/ColorPickerInputController.svelte +37 -37
- package/dist/components/ic/DatePickerInputController.svelte +6 -6
- package/dist/components/ic/DropdownInputController.svelte +1 -1
- package/dist/components/ic/FontInputController.svelte +225 -116
- package/dist/components/ic/FontInputController.svelte.d.ts +4 -2
- package/dist/components/ic/NumberInputController.svelte +37 -37
- package/dist/components/ic/RadioGroupInputController.svelte +1 -1
- package/dist/components/ic/SliderRangeInputController.svelte +1 -1
- package/dist/components/ic/SwitchInputController.svelte +1 -1
- package/dist/components/ic/TextAreaInputController.svelte +213 -85
- package/dist/components/ic/TextAreaInputController.svelte.d.ts +1 -0
- package/dist/components/ic/TextAreaPreviewInputController.svelte +81 -79
- package/dist/components/ic/VectorInputController.svelte +34 -34
- package/dist/components/ic/shared/CategoryTabs.svelte +1 -0
- package/dist/components/ic/shared/RecentItemsSection.svelte +21 -6
- package/dist/components/ic/shared/RecentItemsSection.svelte.d.ts +1 -0
- package/dist/config.d.ts +6 -0
- package/dist/config.js +19 -7
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/stores/userSession.d.ts +1 -1
- package/dist/stores/userSession.js +17 -2
- package/dist/utils/FontManager.d.ts +3 -1
- package/dist/utils/FontManager.js +95 -103
- package/dist/utils/VectorManager.d.ts +3 -1
- package/dist/utils/VectorManager.js +30 -70
- package/dist/utils/colorTransparency.js +3 -3
- package/dist/utils/fontUtils.js +1 -1
- package/dist/utils/passiveEvents.d.ts +5 -0
- package/dist/utils/passiveEvents.js +9 -18
- package/dist/utils/recentColors.js +15 -15
- package/dist/utils/vectorUtils.js +1 -1
- package/package.json +1 -1
|
@@ -77,8 +77,11 @@
|
|
|
77
77
|
* @prop {Function} toggleDropdown - Function to toggle dropdown state
|
|
78
78
|
* @prop {Function} onFocus - Optional focus handler
|
|
79
79
|
*/
|
|
80
|
-
export let label: string;
|
|
81
|
-
|
|
80
|
+
export let label: string = '';
|
|
81
|
+
let className = '';
|
|
82
|
+
export { className as class };
|
|
83
|
+
export let style = '';
|
|
84
|
+
export let value: { family: string; weight: string; category: string } | string | null = null;
|
|
82
85
|
export let onChange: ((newValue: { family: string; weight: string; category: string }) => void) | undefined = undefined;
|
|
83
86
|
export let description: string | undefined = undefined;
|
|
84
87
|
export let controllerId: string;
|
|
@@ -91,7 +94,7 @@
|
|
|
91
94
|
|
|
92
95
|
// Font weight state - remove localStorage check on init
|
|
93
96
|
let selectedWeight = `${controllerId}-Regular`;
|
|
94
|
-
let availableWeights: string[] = [];
|
|
97
|
+
let availableWeights: string[] = ['Regular', 'Medium', 'SemiBold', 'Bold'];
|
|
95
98
|
|
|
96
99
|
// Font search and filter state
|
|
97
100
|
let allFonts: FontItem[] = [];
|
|
@@ -103,6 +106,9 @@
|
|
|
103
106
|
|
|
104
107
|
// Font loading optimization
|
|
105
108
|
let fontListContainer: HTMLElement;
|
|
109
|
+
let familyTriggerEl: HTMLDivElement | undefined;
|
|
110
|
+
let familyPopoverStyle = '';
|
|
111
|
+
let familyPopoverSide: 'top' | 'bottom' = 'bottom';
|
|
106
112
|
let fontObserver = new IntersectionObserver(() => {});
|
|
107
113
|
|
|
108
114
|
// Initialize FontManager instance
|
|
@@ -120,6 +126,46 @@
|
|
|
120
126
|
export let hideRecentFromList: boolean = false;
|
|
121
127
|
export let hideTrashIcon: boolean = true;
|
|
122
128
|
|
|
129
|
+
function updateFamilyPopoverBox() {
|
|
130
|
+
if (!familyTriggerEl || typeof window === 'undefined') return;
|
|
131
|
+
const rect = familyTriggerEl.getBoundingClientRect();
|
|
132
|
+
const pad = 12;
|
|
133
|
+
const viewportH = window.visualViewport?.height ?? window.innerHeight;
|
|
134
|
+
const below = viewportH - rect.bottom - pad;
|
|
135
|
+
const above = rect.top - pad;
|
|
136
|
+
const openAbove = above > below;
|
|
137
|
+
familyPopoverSide = openAbove ? 'top' : 'bottom';
|
|
138
|
+
const available = Math.max(0, openAbove ? above : below);
|
|
139
|
+
const height = Math.min(565, available);
|
|
140
|
+
const width = Math.min(374, Math.max(240, window.innerWidth - 16));
|
|
141
|
+
familyPopoverStyle = `width: ${width}px; height: ${height}px; max-width: calc(100vw - 16px); max-height: ${height}px;`;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function handleFamilyPopoverViewportChange() {
|
|
145
|
+
if ($openDropdowns?.has(controllerId)) {
|
|
146
|
+
updateFamilyPopoverBox();
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function coerceFontValue(raw: typeof value): { family: string; weight: string; category: string } | null {
|
|
151
|
+
if (!raw) return null;
|
|
152
|
+
if (typeof raw === 'object' && raw.family) {
|
|
153
|
+
return {
|
|
154
|
+
family: raw.family,
|
|
155
|
+
weight: raw.weight || 'Regular',
|
|
156
|
+
category: raw.category || 'Sans Serif',
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
if (typeof raw === 'string' && raw.trim()) {
|
|
160
|
+
const family = raw.split(',')[0].replace(/['"]/g, '').trim();
|
|
161
|
+
if (!family) return null;
|
|
162
|
+
return { family, weight: 'Regular', category: 'Sans Serif' };
|
|
163
|
+
}
|
|
164
|
+
return null;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
$: resolvedFont = coerceFontValue(value);
|
|
168
|
+
|
|
123
169
|
// Add scroll state tracking
|
|
124
170
|
let isScrolled = false;
|
|
125
171
|
|
|
@@ -188,9 +234,12 @@
|
|
|
188
234
|
onMount(async () => {
|
|
189
235
|
try {
|
|
190
236
|
if (browser) {
|
|
191
|
-
|
|
192
|
-
if (
|
|
193
|
-
selectedWeight = `${controllerId}-${
|
|
237
|
+
const coerced = coerceFontValue(value);
|
|
238
|
+
if (coerced?.weight) {
|
|
239
|
+
selectedWeight = `${controllerId}-${coerced.weight}`;
|
|
240
|
+
}
|
|
241
|
+
if (typeof value === 'string' && coerced && onChange) {
|
|
242
|
+
onChange(coerced);
|
|
194
243
|
}
|
|
195
244
|
|
|
196
245
|
// Load saved filter
|
|
@@ -328,13 +377,13 @@
|
|
|
328
377
|
preloadedFonts = fontManagerInstance.getPreloadedFonts('Mine');
|
|
329
378
|
|
|
330
379
|
if (preloadedFonts.length > 0) {
|
|
331
|
-
console.log(`✅ [FontInput:${controllerId}] Using preloaded custom fonts for Mine category:`, {
|
|
332
|
-
count: preloadedFonts.length,
|
|
333
|
-
fonts: preloadedFonts.slice(0, 3).map(f => f.family)
|
|
334
|
-
});
|
|
380
|
+
// console.log(`✅ [FontInput:${controllerId}] Using preloaded custom fonts for Mine category:`, {
|
|
381
|
+
// count: preloadedFonts.length,
|
|
382
|
+
// fonts: preloadedFonts.slice(0, 3).map(f => f.family)
|
|
383
|
+
// });
|
|
335
384
|
} else {
|
|
336
385
|
// If no preloaded fonts found, load them now
|
|
337
|
-
console.log(`📚 [FontInput:${controllerId}] No preloaded custom fonts found, loading them now...`);
|
|
386
|
+
// console.log(`📚 [FontInput:${controllerId}] No preloaded custom fonts found, loading them now...`);
|
|
338
387
|
preloadedFonts = await fontManagerInstance.loadCustomFonts();
|
|
339
388
|
}
|
|
340
389
|
|
|
@@ -399,13 +448,13 @@
|
|
|
399
448
|
initialFonts = fontManagerInstance.getPreloadedFonts('Mine');
|
|
400
449
|
|
|
401
450
|
if (initialFonts.length > 0) {
|
|
402
|
-
console.log(`📚 [FontInput:${controllerId}] Using preloaded custom fonts:`, {
|
|
403
|
-
count: initialFonts.length,
|
|
404
|
-
fonts: initialFonts.slice(0, 3).map(f => f.family)
|
|
405
|
-
});
|
|
451
|
+
// console.log(`📚 [FontInput:${controllerId}] Using preloaded custom fonts:`, {
|
|
452
|
+
// count: initialFonts.length,
|
|
453
|
+
// fonts: initialFonts.slice(0, 3).map(f => f.family)
|
|
454
|
+
// });
|
|
406
455
|
} else {
|
|
407
456
|
// If no preloaded fonts, load them now
|
|
408
|
-
console.log(`📚 [FontInput:${controllerId}] No preloaded custom fonts found, loading them now...`);
|
|
457
|
+
// console.log(`📚 [FontInput:${controllerId}] No preloaded custom fonts found, loading them now...`);
|
|
409
458
|
initialFonts = await fontManagerInstance.loadCustomFonts();
|
|
410
459
|
}
|
|
411
460
|
} else if (currentFilter === 'All') {
|
|
@@ -515,14 +564,14 @@
|
|
|
515
564
|
const preloadedCustomFonts = fontManagerInstance.getPreloadedFonts('Mine');
|
|
516
565
|
|
|
517
566
|
if (preloadedCustomFonts.length > 0) {
|
|
518
|
-
console.log(`📚 [FontInput:${controllerId}] Using preloaded custom fonts in initializeFonts:`, {
|
|
519
|
-
count: preloadedCustomFonts.length,
|
|
520
|
-
fonts: preloadedCustomFonts.slice(0, 3).map(f => f.family)
|
|
521
|
-
});
|
|
567
|
+
// console.log(`📚 [FontInput:${controllerId}] Using preloaded custom fonts in initializeFonts:`, {
|
|
568
|
+
// count: preloadedCustomFonts.length,
|
|
569
|
+
// fonts: preloadedCustomFonts.slice(0, 3).map(f => f.family)
|
|
570
|
+
// });
|
|
522
571
|
return preloadedCustomFonts;
|
|
523
572
|
} else {
|
|
524
573
|
// If no preloaded fonts, load them now
|
|
525
|
-
console.log(`📚 [FontInput:${controllerId}] No preloaded custom fonts found in initializeFonts, loading them now...`);
|
|
574
|
+
// console.log(`📚 [FontInput:${controllerId}] No preloaded custom fonts found in initializeFonts, loading them now...`);
|
|
526
575
|
const customFonts = await fontManagerInstance.loadCustomFonts();
|
|
527
576
|
return customFonts;
|
|
528
577
|
}
|
|
@@ -892,16 +941,16 @@
|
|
|
892
941
|
|
|
893
942
|
if (preloadedCustomFonts.length > 0) {
|
|
894
943
|
// Use preloaded custom fonts
|
|
895
|
-
console.log(`📚 [FontInput:${controllerId}] Using preloaded custom fonts for empty search:`, {
|
|
896
|
-
count: preloadedCustomFonts.length,
|
|
897
|
-
fonts: preloadedCustomFonts.slice(0, 3).map(f => f.family)
|
|
898
|
-
});
|
|
944
|
+
// console.log(`📚 [FontInput:${controllerId}] Using preloaded custom fonts for empty search:`, {
|
|
945
|
+
// count: preloadedCustomFonts.length,
|
|
946
|
+
// fonts: preloadedCustomFonts.slice(0, 3).map(f => f.family)
|
|
947
|
+
// });
|
|
899
948
|
allFonts = preloadedCustomFonts;
|
|
900
949
|
filteredFonts = [];
|
|
901
950
|
updateFilteredFonts();
|
|
902
951
|
} else {
|
|
903
952
|
// If no preloaded fonts, load them asynchronously
|
|
904
|
-
console.log(`📚 [FontInput:${controllerId}] No preloaded custom fonts found for empty search, loading them now...`);
|
|
953
|
+
// console.log(`📚 [FontInput:${controllerId}] No preloaded custom fonts found for empty search, loading them now...`);
|
|
905
954
|
fontManagerInstance.loadCustomFonts().then(customFonts => {
|
|
906
955
|
allFonts = customFonts || [];
|
|
907
956
|
filteredFonts = [];
|
|
@@ -999,13 +1048,13 @@
|
|
|
999
1048
|
|
|
1000
1049
|
if (fonts.length === 0) {
|
|
1001
1050
|
// If no preloaded custom fonts found, load them
|
|
1002
|
-
console.log(`📚 [FontInput:${controllerId}] No preloaded custom fonts found, loading them now...`);
|
|
1051
|
+
// console.log(`📚 [FontInput:${controllerId}] No preloaded custom fonts found, loading them now...`);
|
|
1003
1052
|
fonts = await fontManagerInstance.loadCustomFonts();
|
|
1004
1053
|
} else {
|
|
1005
|
-
console.log(`📚 [FontInput:${controllerId}] Using preloaded custom fonts:`, {
|
|
1006
|
-
count: fonts.length,
|
|
1007
|
-
fonts: fonts.slice(0, 3).map(f => f.family)
|
|
1008
|
-
});
|
|
1054
|
+
// console.log(`📚 [FontInput:${controllerId}] Using preloaded custom fonts:`, {
|
|
1055
|
+
// count: fonts.length,
|
|
1056
|
+
// fonts: fonts.slice(0, 3).map(f => f.family)
|
|
1057
|
+
// });
|
|
1009
1058
|
}
|
|
1010
1059
|
} else {
|
|
1011
1060
|
// For other categories, first try to get preloaded fonts
|
|
@@ -1368,8 +1417,8 @@
|
|
|
1368
1417
|
}
|
|
1369
1418
|
}
|
|
1370
1419
|
|
|
1371
|
-
$: if (
|
|
1372
|
-
fetchFontWeights(
|
|
1420
|
+
$: if (resolvedFont?.family) {
|
|
1421
|
+
fetchFontWeights(resolvedFont.family);
|
|
1373
1422
|
}
|
|
1374
1423
|
|
|
1375
1424
|
/**
|
|
@@ -1453,6 +1502,8 @@
|
|
|
1453
1502
|
capture: true,
|
|
1454
1503
|
passive: true
|
|
1455
1504
|
});
|
|
1505
|
+
window.addEventListener('resize', handleFamilyPopoverViewportChange);
|
|
1506
|
+
window.visualViewport?.addEventListener('resize', handleFamilyPopoverViewportChange);
|
|
1456
1507
|
|
|
1457
1508
|
// Add touch listeners with passive option
|
|
1458
1509
|
window.addEventListener('touchstart', () => {}, { passive: true });
|
|
@@ -1462,6 +1513,8 @@
|
|
|
1462
1513
|
// Update onDestroy to remove all listeners
|
|
1463
1514
|
onDestroy(() => {
|
|
1464
1515
|
window.removeEventListener('scroll', handleGlobalScroll, true);
|
|
1516
|
+
window.removeEventListener('resize', handleFamilyPopoverViewportChange);
|
|
1517
|
+
window.visualViewport?.removeEventListener('resize', handleFamilyPopoverViewportChange);
|
|
1465
1518
|
window.removeEventListener('touchstart', () => {});
|
|
1466
1519
|
window.removeEventListener('touchmove', () => {});
|
|
1467
1520
|
|
|
@@ -1476,10 +1529,10 @@
|
|
|
1476
1529
|
clearTimeout(initialLoadTimeout);
|
|
1477
1530
|
}
|
|
1478
1531
|
|
|
1479
|
-
console.log('🧹 [FontInput] Cleanup complete:', {
|
|
1480
|
-
controllerId,
|
|
1481
|
-
lastFilter: currentFilter
|
|
1482
|
-
});
|
|
1532
|
+
// console.log('🧹 [FontInput] Cleanup complete:', {
|
|
1533
|
+
// controllerId,
|
|
1534
|
+
// lastFilter: currentFilter
|
|
1535
|
+
// });
|
|
1483
1536
|
});
|
|
1484
1537
|
|
|
1485
1538
|
// Add this function to the script section
|
|
@@ -1530,12 +1583,12 @@
|
|
|
1530
1583
|
// Update filtered fonts
|
|
1531
1584
|
updateFilteredFonts();
|
|
1532
1585
|
|
|
1533
|
-
console.log('✅ [FontInput] Font removed:', {
|
|
1534
|
-
fontFamily,
|
|
1535
|
-
remainingFonts: allFonts.length,
|
|
1536
|
-
filteredFonts: filteredFonts.length,
|
|
1537
|
-
recentFonts: recentFonts.length
|
|
1538
|
-
});
|
|
1586
|
+
// console.log('✅ [FontInput] Font removed:', {
|
|
1587
|
+
// fontFamily,
|
|
1588
|
+
// remainingFonts: allFonts.length,
|
|
1589
|
+
// filteredFonts: filteredFonts.length,
|
|
1590
|
+
// recentFonts: recentFonts.length
|
|
1591
|
+
// });
|
|
1539
1592
|
} catch (error) {
|
|
1540
1593
|
console.error('❌ [FontInput] Error removing font:', error);
|
|
1541
1594
|
}
|
|
@@ -1547,11 +1600,12 @@
|
|
|
1547
1600
|
if (browser) {
|
|
1548
1601
|
localStorage.setItem(FONT_WEIGHT_KEY(controllerId), selectedWeight);
|
|
1549
1602
|
}
|
|
1603
|
+
const current = coerceFontValue(value);
|
|
1550
1604
|
if (onChange) {
|
|
1551
1605
|
onChange({
|
|
1552
|
-
family:
|
|
1606
|
+
family: current?.family || '',
|
|
1553
1607
|
weight: weight,
|
|
1554
|
-
category:
|
|
1608
|
+
category: current?.category || 'Sans Serif'
|
|
1555
1609
|
});
|
|
1556
1610
|
}
|
|
1557
1611
|
}
|
|
@@ -1587,7 +1641,7 @@
|
|
|
1587
1641
|
<div class="flex items-center flex-1 min-w-0">
|
|
1588
1642
|
<span
|
|
1589
1643
|
class="text-[24px] truncate"
|
|
1590
|
-
style="font-family: '${font.family}', sans-serif; font-display: swap;"
|
|
1644
|
+
style="font-family: '${font.family}', sans-serif; font-display: swap; color: inherit; -webkit-text-fill-color: currentColor;"
|
|
1591
1645
|
>
|
|
1592
1646
|
${font.family}
|
|
1593
1647
|
</span>
|
|
@@ -1597,7 +1651,7 @@
|
|
|
1597
1651
|
}
|
|
1598
1652
|
|
|
1599
1653
|
function isFontSelected(font: FontItem) {
|
|
1600
|
-
return
|
|
1654
|
+
return resolvedFont?.family === font.family;
|
|
1601
1655
|
}
|
|
1602
1656
|
|
|
1603
1657
|
function isCustomFont(font: FontItem) {
|
|
@@ -1617,34 +1671,34 @@
|
|
|
1617
1671
|
}
|
|
1618
1672
|
</script>
|
|
1619
1673
|
|
|
1620
|
-
<!--
|
|
1621
|
-
<div class="flex flex-col widgetic-colors">
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
<
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
<div class="absolute right-0">
|
|
1633
|
-
<div class="h-[48px] w-[185px] rounded-large border border-grey2 flex items-center bg-grey1 transition-colors duration-200 hover:border-forest-green">
|
|
1674
|
+
<!-- Dual IC: header zone always on the left (even if label is empty); 185px inputs on the right. -->
|
|
1675
|
+
<div class="font-ic flex flex-col gap-2 w-full min-w-0 widgetic-colors {className}" style={style}>
|
|
1676
|
+
<div class="font-family-row flex items-center justify-between w-full min-w-0 gap-2" style="min-height: 48px;">
|
|
1677
|
+
<div class="font-family-label-ct flex-1 min-w-0">
|
|
1678
|
+
<InputControllerHeader label={label || ''} />
|
|
1679
|
+
</div>
|
|
1680
|
+
<div
|
|
1681
|
+
class="font-family-input-ct h-12 shrink-0 rounded-large border border-grey2 flex items-center bg-grey1 transition-colors duration-200 hover:border-forest-green"
|
|
1682
|
+
style="width: 185px; max-width: 185px; min-width: 185px;"
|
|
1683
|
+
bind:this={familyTriggerEl}
|
|
1684
|
+
>
|
|
1634
1685
|
<!-- Font Family Button -->
|
|
1635
1686
|
<Popover.Root
|
|
1636
1687
|
open={$openDropdowns?.has(controllerId)}
|
|
1637
1688
|
onOpenChange={(isOpen) => {
|
|
1638
1689
|
if (isOpen !== $openDropdowns?.has(controllerId)) {
|
|
1639
|
-
if (!isOpen &&
|
|
1690
|
+
if (!isOpen && resolvedFont?.family && !shouldSkipFont(resolvedFont.family)) {
|
|
1640
1691
|
fontUtils.addRecentFont({
|
|
1641
|
-
family:
|
|
1642
|
-
category: normalizeCategory(
|
|
1643
|
-
isCustom: fontManagerInstance?.isCustomFont(
|
|
1692
|
+
family: resolvedFont.family,
|
|
1693
|
+
category: normalizeCategory(resolvedFont.category) as FontItem['category'],
|
|
1694
|
+
isCustom: fontManagerInstance?.isCustomFont(resolvedFont.family) || false
|
|
1644
1695
|
});
|
|
1645
1696
|
} else if (isOpen) {
|
|
1646
|
-
// Reset active search index when opening the dropdown
|
|
1647
1697
|
activeSearchIndex = -1;
|
|
1698
|
+
void tick().then(() => {
|
|
1699
|
+
updateFamilyPopoverBox();
|
|
1700
|
+
requestAnimationFrame(updateFamilyPopoverBox);
|
|
1701
|
+
});
|
|
1648
1702
|
|
|
1649
1703
|
// When opening, ensure we have fonts ready
|
|
1650
1704
|
if (filteredFonts.length === 0 && allFonts.length > 0) {
|
|
@@ -1665,7 +1719,7 @@
|
|
|
1665
1719
|
}
|
|
1666
1720
|
}}
|
|
1667
1721
|
>
|
|
1668
|
-
<Popover.Trigger class="w-full h-full flex items-center border-0 bg-transparent hover:bg-transparent focus:bg-transparent pl-3 pr-[16px] group"
|
|
1722
|
+
<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"
|
|
1669
1723
|
onmouseenter={() => {
|
|
1670
1724
|
// Preload fonts when hovering over the button
|
|
1671
1725
|
// This reduces the delay when actually clicking to open
|
|
@@ -1676,20 +1730,27 @@
|
|
|
1676
1730
|
>
|
|
1677
1731
|
<span
|
|
1678
1732
|
class="truncate flex-1 text-left subtext text-grey7"
|
|
1679
|
-
style="font-family: '{
|
|
1733
|
+
style="font-family: '{resolvedFont?.family || 'system-ui'}', sans-serif; font-display: swap;"
|
|
1680
1734
|
>
|
|
1681
|
-
{
|
|
1735
|
+
{resolvedFont?.family || "Select font..."}
|
|
1682
1736
|
</span>
|
|
1683
1737
|
<IconCaretDownFilled class="w-5 h-5 shrink-0 text-grey5 group-hover:text-grey7" />
|
|
1684
1738
|
</Popover.Trigger>
|
|
1685
1739
|
|
|
1686
|
-
<Popover.Content
|
|
1687
|
-
|
|
1740
|
+
<Popover.Content
|
|
1741
|
+
collisionPadding={12}
|
|
1742
|
+
side={familyPopoverSide}
|
|
1743
|
+
sideOffset={4}
|
|
1744
|
+
class="font-input-popover !p-0 widgetic-colors widgetic-radius rounded-medium modal-shadow border border-grey2"
|
|
1745
|
+
style={familyPopoverStyle}
|
|
1746
|
+
>
|
|
1747
|
+
<div class="flex flex-col h-full min-h-0 font-popover-content">
|
|
1688
1748
|
<!-- Title and upload icon -->
|
|
1689
|
-
<div class="relative pt-6 pb-[11px] px-5">
|
|
1749
|
+
<div class="font-popover-header shrink-0 relative pt-6 pb-[11px] px-5">
|
|
1690
1750
|
<div class="h5 text-grey7 widgetic-colors">Fonts</div>
|
|
1691
1751
|
<button
|
|
1692
1752
|
type="button"
|
|
1753
|
+
tabindex="-1"
|
|
1693
1754
|
class="absolute right-6 top-[26px] bg-transparent border-0 cursor-pointer p-0 rounded-full hover:bg-grey3 transition-all duration-300"
|
|
1694
1755
|
onclick={() => {
|
|
1695
1756
|
try {
|
|
@@ -1708,7 +1769,7 @@
|
|
|
1708
1769
|
{/if}
|
|
1709
1770
|
|
|
1710
1771
|
<!-- Search input -->
|
|
1711
|
-
<div class="relative px-4">
|
|
1772
|
+
<div class="font-popover-search shrink-0 relative px-4">
|
|
1712
1773
|
<SearchInput
|
|
1713
1774
|
placeholder="Search fonts..."
|
|
1714
1775
|
bind:value={searchTerm}
|
|
@@ -1733,7 +1794,7 @@
|
|
|
1733
1794
|
</div>
|
|
1734
1795
|
<!-- Filter toggle group - sticky header -->
|
|
1735
1796
|
{#if !searchTerm}
|
|
1736
|
-
<div class="sticky top-0 bg-white z-10">
|
|
1797
|
+
<div class="font-popover-tabs shrink-0 sticky top-0 bg-white z-10">
|
|
1737
1798
|
<CategoryTabs
|
|
1738
1799
|
categories={filterOptions}
|
|
1739
1800
|
activeCategory={currentFilter}
|
|
@@ -1772,6 +1833,7 @@
|
|
|
1772
1833
|
displayMode="list"
|
|
1773
1834
|
hideTrashIcon={hideTrashIcon}
|
|
1774
1835
|
itemType="font"
|
|
1836
|
+
selectionToken={resolvedFont?.family || ''}
|
|
1775
1837
|
/>
|
|
1776
1838
|
{/if}
|
|
1777
1839
|
|
|
@@ -1809,22 +1871,23 @@
|
|
|
1809
1871
|
{#each filteredFonts as font, index (`${font.family}-${searchTerm ? 'search' : currentFilter}-${index}`)}
|
|
1810
1872
|
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
|
1811
1873
|
<div
|
|
1812
|
-
class="w-full py-1 px-4 cursor-pointer overflow-hidden relative rounded-small h-[42px] flex items-center
|
|
1813
|
-
{
|
|
1814
|
-
index === activeSearchIndex && searchTerm ? 'bg-light-green
|
|
1874
|
+
class="font-list-row w-full py-1 px-4 cursor-pointer overflow-hidden relative rounded-small h-[42px] flex items-center
|
|
1875
|
+
{isFontSelected(font) ? 'bg-sage-green selected-item' :
|
|
1876
|
+
index === activeSearchIndex && searchTerm ? 'bg-light-green' :
|
|
1815
1877
|
'hover:bg-light-green'}"
|
|
1816
1878
|
data-font={font.family}
|
|
1817
1879
|
use:observeFont
|
|
1818
1880
|
onclick={() => handleFontSelect(font)}
|
|
1819
1881
|
onmouseenter={() => handleMouseEnter(index)}
|
|
1820
1882
|
role="button"
|
|
1821
|
-
tabindex="
|
|
1883
|
+
tabindex="-1"
|
|
1884
|
+
style="color: {isFontSelected(font) ? '#ffffff' : 'hsl(var(--grey7))'};"
|
|
1822
1885
|
>
|
|
1823
1886
|
<div class="flex items-center flex-1 min-w-0 group">
|
|
1824
|
-
<Check class="mr-2 h-6 w-6 flex-shrink-0 {
|
|
1887
|
+
<Check class="mr-2 h-6 w-6 flex-shrink-0 {isFontSelected(font) ? 'text-white' : 'text-sage-green opacity-0'}"/>
|
|
1825
1888
|
<span
|
|
1826
1889
|
class="text-[24px] truncate {index === activeSearchIndex && searchTerm ? 'font-medium' : ''}"
|
|
1827
|
-
style="font-family: '{font.family}', sans-serif; font-display: swap;"
|
|
1890
|
+
style="font-family: '{font.family}', sans-serif; font-display: swap; color: inherit; -webkit-text-fill-color: currentColor;"
|
|
1828
1891
|
>
|
|
1829
1892
|
{@html highlightMatch(font.family, searchTerm)}
|
|
1830
1893
|
</span>
|
|
@@ -1861,15 +1924,13 @@
|
|
|
1861
1924
|
</Popover.Content>
|
|
1862
1925
|
</Popover.Root>
|
|
1863
1926
|
</div>
|
|
1864
|
-
|
|
1865
|
-
</div>
|
|
1927
|
+
</div>
|
|
1866
1928
|
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
<!-- Font Weight Button -->
|
|
1929
|
+
<div class="font-weight-row flex items-center justify-between w-full min-w-0 gap-2" style="min-height: 48px;">
|
|
1930
|
+
<div class="font-weight-label-ct flex-1 min-w-0">
|
|
1931
|
+
<InputControllerHeader label={label ? 'Font Weight' : ''} />
|
|
1932
|
+
</div>
|
|
1933
|
+
<div class="font-weight-input-ct h-12 shrink-0 rounded-large border border-grey2 flex items-center bg-grey1 transition-colors duration-200 hover:border-forest-green" style="width: 185px; max-width: 185px; min-width: 185px;">
|
|
1873
1934
|
<Popover.Root
|
|
1874
1935
|
open={$openDropdowns?.has('weight-' + controllerId)}
|
|
1875
1936
|
onOpenChange={(isOpen) => {
|
|
@@ -1878,35 +1939,35 @@
|
|
|
1878
1939
|
}
|
|
1879
1940
|
}}
|
|
1880
1941
|
>
|
|
1881
|
-
<Popover.Trigger class="w-full h-full flex items-center border-0 bg-transparent hover:bg-transparent focus:bg-transparent pl-3 pr-[16px] group">
|
|
1942
|
+
<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">
|
|
1882
1943
|
<span class="truncate flex-1 text-left subtext text-grey7">
|
|
1883
|
-
{displayWeight}
|
|
1944
|
+
{displayWeight || 'Regular'}
|
|
1884
1945
|
</span>
|
|
1885
1946
|
<IconCaretDownFilled class="w-5 h-5 shrink-0 text-grey5 group-hover:text-grey7" />
|
|
1886
1947
|
</Popover.Trigger>
|
|
1887
1948
|
<Popover.Content class="p-0 w-[150px]">
|
|
1888
1949
|
<Command.Root>
|
|
1889
|
-
<Command.
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1950
|
+
<Command.List>
|
|
1951
|
+
<Command.Group>
|
|
1952
|
+
{#each availableWeights as weight}
|
|
1953
|
+
<Command.Item
|
|
1954
|
+
value={weight}
|
|
1955
|
+
onSelect={() => handleWeightSelect(weight)}
|
|
1956
|
+
class="px-2 py-2"
|
|
1957
|
+
>
|
|
1958
|
+
<Check
|
|
1959
|
+
class="mr-1 h-4 w-4 {displayWeight === weight ? 'opacity-100' : 'opacity-0'}"
|
|
1960
|
+
/>
|
|
1961
|
+
<span class="truncate">{weight}</span>
|
|
1962
|
+
</Command.Item>
|
|
1963
|
+
{/each}
|
|
1964
|
+
</Command.Group>
|
|
1965
|
+
</Command.List>
|
|
1903
1966
|
</Command.Root>
|
|
1904
1967
|
</Popover.Content>
|
|
1905
1968
|
</Popover.Root>
|
|
1906
|
-
</div>
|
|
1907
1969
|
</div>
|
|
1908
1970
|
</div>
|
|
1909
|
-
</div>
|
|
1910
1971
|
|
|
1911
1972
|
{#if description}
|
|
1912
1973
|
<p class="subtext text-grey5">{description}</p>
|
|
@@ -1914,6 +1975,30 @@
|
|
|
1914
1975
|
</div>
|
|
1915
1976
|
|
|
1916
1977
|
<style>
|
|
1978
|
+
.font-family-row,
|
|
1979
|
+
.font-weight-row {
|
|
1980
|
+
display: flex;
|
|
1981
|
+
align-items: center;
|
|
1982
|
+
justify-content: space-between;
|
|
1983
|
+
width: 100%;
|
|
1984
|
+
}
|
|
1985
|
+
|
|
1986
|
+
.font-family-label-ct,
|
|
1987
|
+
.font-weight-label-ct {
|
|
1988
|
+
flex: 1 1 auto;
|
|
1989
|
+
min-width: 0;
|
|
1990
|
+
}
|
|
1991
|
+
|
|
1992
|
+
.font-family-input-ct,
|
|
1993
|
+
.font-weight-input-ct {
|
|
1994
|
+
width: 185px !important;
|
|
1995
|
+
max-width: 185px !important;
|
|
1996
|
+
min-width: 185px !important;
|
|
1997
|
+
margin-left: auto;
|
|
1998
|
+
flex-shrink: 0;
|
|
1999
|
+
position: relative;
|
|
2000
|
+
}
|
|
2001
|
+
|
|
1917
2002
|
/* Update button styles */
|
|
1918
2003
|
:global(button.bg-transparent) {
|
|
1919
2004
|
background: transparent !important;
|
|
@@ -1932,9 +2017,11 @@
|
|
|
1932
2017
|
scrollbar-color: hsl(var(--grey3)) transparent;
|
|
1933
2018
|
}
|
|
1934
2019
|
|
|
1935
|
-
/*
|
|
1936
|
-
:global(.popover-trigger),
|
|
1937
|
-
:global(.popover-trigger button)
|
|
2020
|
+
/* Trigger fills the 185px column only — do not leak width:100% to other ICs */
|
|
2021
|
+
.font-family-input-ct :global(.popover-trigger),
|
|
2022
|
+
.font-family-input-ct :global(.popover-trigger button),
|
|
2023
|
+
.font-weight-input-ct :global(.popover-trigger),
|
|
2024
|
+
.font-weight-input-ct :global(.popover-trigger button) {
|
|
1938
2025
|
width: 100% !important;
|
|
1939
2026
|
height: 100% !important;
|
|
1940
2027
|
}
|
|
@@ -1953,12 +2040,28 @@
|
|
|
1953
2040
|
background-color: hsl(var(--light-green)) !important;
|
|
1954
2041
|
}
|
|
1955
2042
|
|
|
1956
|
-
|
|
2043
|
+
.font-family-input-ct :global(button:focus),
|
|
2044
|
+
.font-family-input-ct :global(button:focus-visible),
|
|
2045
|
+
.font-weight-input-ct :global(button:focus),
|
|
2046
|
+
.font-weight-input-ct :global(button:focus-visible),
|
|
2047
|
+
:global(.font-input-popover button:focus),
|
|
2048
|
+
:global(.font-input-popover button:focus-visible),
|
|
2049
|
+
:global(.font-list-row:focus),
|
|
2050
|
+
:global(.font-list-row:focus-visible),
|
|
2051
|
+
:global(.font-input-popover [data-item]:focus),
|
|
2052
|
+
:global(.font-input-popover [data-item]:focus-visible) {
|
|
2053
|
+
outline: none;
|
|
2054
|
+
box-shadow: none;
|
|
2055
|
+
}
|
|
2056
|
+
|
|
2057
|
+
/* Clamp to the viewport so the Fonts header and list stay on screen */
|
|
1957
2058
|
:global(.font-input-popover) {
|
|
1958
2059
|
z-index: 50;
|
|
1959
2060
|
will-change: transform;
|
|
1960
2061
|
transform: translateZ(0);
|
|
1961
2062
|
backface-visibility: hidden;
|
|
2063
|
+
max-width: calc(100vw - 16px) !important;
|
|
2064
|
+
overflow: hidden;
|
|
1962
2065
|
}
|
|
1963
2066
|
|
|
1964
2067
|
:global(.font-popover-content) {
|
|
@@ -1998,14 +2101,20 @@
|
|
|
1998
2101
|
z-index: 10; /* Ensure it appears above other content */
|
|
1999
2102
|
}
|
|
2000
2103
|
|
|
2001
|
-
/*
|
|
2002
|
-
:global(.selected-item
|
|
2003
|
-
|
|
2104
|
+
/* Selected row only — never leave white text on a white (deselected) row. */
|
|
2105
|
+
:global(.font-list-row.selected-item),
|
|
2106
|
+
:global([data-item].selected-item) {
|
|
2004
2107
|
color: white !important;
|
|
2005
2108
|
}
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2109
|
+
:global(.font-list-row:not(.selected-item)),
|
|
2110
|
+
:global([data-item]:not(.selected-item)) {
|
|
2111
|
+
color: hsl(var(--grey7)) !important;
|
|
2112
|
+
}
|
|
2113
|
+
|
|
2114
|
+
/* Prevent hover from keeping sage+white on a row that is no longer selected. */
|
|
2115
|
+
:global(.font-list-row.selected-item:hover),
|
|
2116
|
+
:global([data-item].selected-item:hover) {
|
|
2117
|
+
background-color: hsl(var(--sage-green)) !important;
|
|
2009
2118
|
color: white !important;
|
|
2010
2119
|
}
|
|
2011
2120
|
|
|
@@ -23,12 +23,14 @@ declare const FontInputController: $$__sveltets_2_IsomorphicComponent<{
|
|
|
23
23
|
* @prop {any} openDropdowns - Store tracking open dropdown states
|
|
24
24
|
* @prop {Function} toggleDropdown - Function to toggle dropdown state
|
|
25
25
|
* @prop {Function} onFocus - Optional focus handler
|
|
26
|
-
*/ label
|
|
26
|
+
*/ label?: string;
|
|
27
|
+
class?: string;
|
|
28
|
+
style?: string;
|
|
27
29
|
value?: {
|
|
28
30
|
family: string;
|
|
29
31
|
weight: string;
|
|
30
32
|
category: string;
|
|
31
|
-
} | null;
|
|
33
|
+
} | string | null;
|
|
32
34
|
onChange?: ((newValue: {
|
|
33
35
|
family: string;
|
|
34
36
|
weight: string;
|