@finsweet/webflow-apps-utils 1.0.23 → 1.0.25
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/ui/components/color-picker/ColorPicker.svelte +21 -26
- package/dist/ui/components/color-picker/ColorSelect.svelte +56 -7
- package/dist/ui/components/color-picker/ColorSelect.svelte.d.ts +1 -0
- package/dist/ui/components/tooltip/Tooltip.svelte +10 -0
- package/dist/ui/components/tooltip/Tooltip.svelte.d.ts +1 -0
- package/package.json +1 -1
|
@@ -50,28 +50,6 @@
|
|
|
50
50
|
id
|
|
51
51
|
}: Props = $props();
|
|
52
52
|
|
|
53
|
-
// Remove local inputValue state
|
|
54
|
-
// let inputValue = $state(color);
|
|
55
|
-
|
|
56
|
-
// Helper: normalize hex to 6-digit uppercase
|
|
57
|
-
// function normalizeHex(value: string): string {
|
|
58
|
-
// if (/^#[A-Fa-f0-9]{3}$/.test(value)) {
|
|
59
|
-
// return (
|
|
60
|
-
// '#' +
|
|
61
|
-
// value
|
|
62
|
-
// .slice(1)
|
|
63
|
-
// .split('')
|
|
64
|
-
// .map((c) => c + c)
|
|
65
|
-
// .join('')
|
|
66
|
-
// .toUpperCase()
|
|
67
|
-
// );
|
|
68
|
-
// }
|
|
69
|
-
// if (/^#[A-Fa-f0-9]{6}$/.test(value)) {
|
|
70
|
-
// return value.toUpperCase();
|
|
71
|
-
// }
|
|
72
|
-
// return value;
|
|
73
|
-
// }
|
|
74
|
-
|
|
75
53
|
function isValidColor(value: string): boolean {
|
|
76
54
|
const hexRegex = /^#?([A-Fa-f0-9]{3}|[A-Fa-f0-9]{6}|[A-Fa-f0-9]{8})$/;
|
|
77
55
|
return hexRegex.test(value.startsWith('#') ? value.slice(1) : value);
|
|
@@ -89,8 +67,11 @@
|
|
|
89
67
|
.join('');
|
|
90
68
|
}
|
|
91
69
|
|
|
92
|
-
//
|
|
70
|
+
// Extract alpha channel if present (8-digit hex)
|
|
71
|
+
let alpha = 100;
|
|
93
72
|
if (normalizedHex.length === 8) {
|
|
73
|
+
const alphaHex = normalizedHex.substring(6, 8);
|
|
74
|
+
alpha = Math.round((parseInt(alphaHex, 16) / 255) * 100);
|
|
94
75
|
normalizedHex = normalizedHex.substring(0, 6);
|
|
95
76
|
}
|
|
96
77
|
|
|
@@ -203,15 +184,24 @@
|
|
|
203
184
|
|
|
204
185
|
function handleFullColorChange(fullColor: ColorObject) {
|
|
205
186
|
oncolorchange?.(fullColor);
|
|
206
|
-
|
|
207
|
-
|
|
187
|
+
// Preserve the alpha channel by using the full hex value with alpha
|
|
188
|
+
// The fullColor.hex already includes the alpha channel if alpha < 100
|
|
189
|
+
color = fullColor.hex;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function handleDragEnd() {
|
|
193
|
+
// Signal the tooltip to ignore the next click event
|
|
194
|
+
// This prevents the tooltip from closing when dragging and releasing outside
|
|
195
|
+
tooltipRef?.ignoreNextClickEvent?.();
|
|
208
196
|
}
|
|
209
197
|
|
|
210
198
|
let showColorSelect = $state(defaultShowColorSelect);
|
|
199
|
+
let tooltipRef: { ignoreNextClickEvent?: () => void } | undefined = $state();
|
|
211
200
|
</script>
|
|
212
201
|
|
|
213
202
|
<div class="color-picker">
|
|
214
203
|
<Tooltip
|
|
204
|
+
bind:this={tooltipRef}
|
|
215
205
|
listener="click"
|
|
216
206
|
listenerout="click"
|
|
217
207
|
showArrow={false}
|
|
@@ -231,7 +221,7 @@
|
|
|
231
221
|
{/snippet}
|
|
232
222
|
{#snippet tooltip()}
|
|
233
223
|
{#if showColorSelect}
|
|
234
|
-
<ColorSelect bind:color oncolorchange={handleFullColorChange} />
|
|
224
|
+
<ColorSelect bind:color oncolorchange={handleFullColorChange} ondragend={handleDragEnd} />
|
|
235
225
|
{/if}
|
|
236
226
|
{/snippet}
|
|
237
227
|
</Tooltip>
|
|
@@ -271,6 +261,11 @@
|
|
|
271
261
|
0px 4px 4px -4px rgba(0, 0, 0, 0.17) inset,
|
|
272
262
|
0px 3px 3px -3px rgba(0, 0, 0, 0.17) inset,
|
|
273
263
|
0px 1px 1px -1px rgba(0, 0, 0, 0.13) inset;
|
|
264
|
+
|
|
265
|
+
user-select: none;
|
|
266
|
+
-webkit-user-select: none;
|
|
267
|
+
-moz-user-select: none;
|
|
268
|
+
-ms-user-select: none;
|
|
274
269
|
}
|
|
275
270
|
|
|
276
271
|
.color-picker__swatch {
|
|
@@ -12,9 +12,14 @@
|
|
|
12
12
|
alpha: number;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
let {
|
|
15
|
+
let {
|
|
16
|
+
color = $bindable('#fff'),
|
|
17
|
+
oncolorchange,
|
|
18
|
+
ondragend
|
|
19
|
+
} = $props<{
|
|
16
20
|
color?: string;
|
|
17
21
|
oncolorchange?: (fullColor: ColorObject) => void;
|
|
22
|
+
ondragend?: () => void;
|
|
18
23
|
}>();
|
|
19
24
|
|
|
20
25
|
function setColor(newColor: string) {
|
|
@@ -108,6 +113,26 @@
|
|
|
108
113
|
return normalizeHex(colorInput);
|
|
109
114
|
}
|
|
110
115
|
|
|
116
|
+
// Helper function to extract alpha value from hex color
|
|
117
|
+
function extractAlphaFromHex(hexColor: string): number {
|
|
118
|
+
if (hexColor.startsWith('#') && hexColor.length === 9) {
|
|
119
|
+
// 8-digit hex with alpha channel (#RRGGBBAA)
|
|
120
|
+
const alphaHex = hexColor.slice(7, 9);
|
|
121
|
+
const alphaValue = parseInt(alphaHex, 16);
|
|
122
|
+
return Math.round((alphaValue / 255) * 100);
|
|
123
|
+
}
|
|
124
|
+
return 100; // Default to 100% opacity if no alpha channel
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Helper function to get hex without alpha channel
|
|
128
|
+
function getHexWithoutAlpha(hexColor: string): string {
|
|
129
|
+
if (hexColor.startsWith('#') && hexColor.length === 9) {
|
|
130
|
+
// Remove alpha channel from 8-digit hex
|
|
131
|
+
return hexColor.slice(0, 7);
|
|
132
|
+
}
|
|
133
|
+
return hexColor;
|
|
134
|
+
}
|
|
135
|
+
|
|
111
136
|
// Color conversion utilities
|
|
112
137
|
function hsbToRgb(h: number, s: number, b: number): [number, number, number] {
|
|
113
138
|
h = h / 360;
|
|
@@ -377,6 +402,7 @@
|
|
|
377
402
|
let hexInputValue = $state('');
|
|
378
403
|
let isHexEditing = $state(false);
|
|
379
404
|
let prevHexValue = $state('');
|
|
405
|
+
let isInitialized = $state(false);
|
|
380
406
|
|
|
381
407
|
function handleHexFocus(event: FocusEvent) {
|
|
382
408
|
prevHexValue = hexValue;
|
|
@@ -489,6 +515,8 @@
|
|
|
489
515
|
if (isDragging) {
|
|
490
516
|
isDragging = false;
|
|
491
517
|
dragTarget = null;
|
|
518
|
+
// Signal that a drag operation just ended
|
|
519
|
+
ondragend?.();
|
|
492
520
|
}
|
|
493
521
|
|
|
494
522
|
// Reset drag detection state
|
|
@@ -508,10 +536,18 @@
|
|
|
508
536
|
|
|
509
537
|
// Watch for prop changes - FIXED: Better color normalization
|
|
510
538
|
$effect(() => {
|
|
539
|
+
// Skip effect during initial mount to prevent overriding alpha
|
|
540
|
+
if (!isInitialized) return;
|
|
541
|
+
|
|
511
542
|
const normalized = normalizeColorToHex(color);
|
|
512
|
-
if
|
|
513
|
-
|
|
514
|
-
|
|
543
|
+
// Extract alpha value from the original color if it has an alpha channel
|
|
544
|
+
const alphaFromColor = extractAlphaFromHex(color);
|
|
545
|
+
|
|
546
|
+
// Use hex without alpha for internal processing
|
|
547
|
+
const hexWithoutAlpha = getHexWithoutAlpha(normalized);
|
|
548
|
+
if (hexWithoutAlpha !== hexValue) {
|
|
549
|
+
hexValue = hexWithoutAlpha;
|
|
550
|
+
const [h, s, b] = hexToHsb(hexValue);
|
|
515
551
|
hue = h;
|
|
516
552
|
saturation = s;
|
|
517
553
|
brightness = b;
|
|
@@ -519,6 +555,11 @@
|
|
|
519
555
|
// Force position update after state changes
|
|
520
556
|
setTimeout(() => updateColorPickerPosition(), 0);
|
|
521
557
|
}
|
|
558
|
+
|
|
559
|
+
// Only update alpha if it's different from current alpha
|
|
560
|
+
if (alphaFromColor !== alpha) {
|
|
561
|
+
alpha = alphaFromColor;
|
|
562
|
+
}
|
|
522
563
|
});
|
|
523
564
|
|
|
524
565
|
let currentColor = $derived(
|
|
@@ -527,14 +568,19 @@
|
|
|
527
568
|
|
|
528
569
|
onMount(() => {
|
|
529
570
|
const normalized = normalizeColorToHex(color);
|
|
530
|
-
|
|
531
|
-
const
|
|
571
|
+
// Extract alpha value from the original color if it has an alpha channel
|
|
572
|
+
const alphaFromColor = extractAlphaFromHex(color);
|
|
573
|
+
alpha = alphaFromColor;
|
|
574
|
+
|
|
575
|
+
// Use hex without alpha for internal processing
|
|
576
|
+
hexValue = getHexWithoutAlpha(normalized);
|
|
577
|
+
const [h, s, b] = hexToHsb(hexValue);
|
|
532
578
|
hue = h;
|
|
533
579
|
saturation = s;
|
|
534
580
|
brightness = b;
|
|
535
581
|
[rgbRed, rgbGreen, rgbBlue] = hsbToRgb(hue, saturation, brightness);
|
|
536
582
|
|
|
537
|
-
console.log('ColorSelect mounted', { color });
|
|
583
|
+
console.log('ColorSelect mounted', { color, alpha: alphaFromColor });
|
|
538
584
|
updateColor();
|
|
539
585
|
// Delay position update to ensure DOM is ready
|
|
540
586
|
|
|
@@ -543,6 +589,9 @@
|
|
|
543
589
|
document.addEventListener('mousemove', handleMouseMove);
|
|
544
590
|
document.addEventListener('mouseup', handleMouseUp);
|
|
545
591
|
|
|
592
|
+
// Mark as initialized after setting up the initial state
|
|
593
|
+
isInitialized = true;
|
|
594
|
+
|
|
546
595
|
return () => {
|
|
547
596
|
document.removeEventListener('mousemove', handleMouseMove);
|
|
548
597
|
document.removeEventListener('mouseup', handleMouseUp);
|
|
@@ -24,6 +24,7 @@ interface ColorObject {
|
|
|
24
24
|
type $$ComponentProps = {
|
|
25
25
|
color?: string;
|
|
26
26
|
oncolorchange?: (fullColor: ColorObject) => void;
|
|
27
|
+
ondragend?: () => void;
|
|
27
28
|
};
|
|
28
29
|
declare const ColorSelect: import("svelte").Component<$$ComponentProps, {}, "color">;
|
|
29
30
|
type ColorSelect = ReturnType<typeof ColorSelect>;
|
|
@@ -64,6 +64,7 @@
|
|
|
64
64
|
let arrowElement: HTMLDivElement | undefined = $state();
|
|
65
65
|
let observer: MutationObserver | null = null;
|
|
66
66
|
let documentClickListener: ((event: MouseEvent) => void) | null = null;
|
|
67
|
+
let ignoreNextClick = $state(false);
|
|
67
68
|
const tooltipId = `tooltip-${uuidv4()}`;
|
|
68
69
|
|
|
69
70
|
/**
|
|
@@ -214,6 +215,12 @@
|
|
|
214
215
|
|
|
215
216
|
// Store reference to the click handler for cleanup
|
|
216
217
|
documentClickListener = (event: MouseEvent) => {
|
|
218
|
+
// Ignore clicks that happen immediately after a drag operation
|
|
219
|
+
if (ignoreNextClick) {
|
|
220
|
+
ignoreNextClick = false;
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
|
|
217
224
|
if (
|
|
218
225
|
tooltipElement &&
|
|
219
226
|
toggle &&
|
|
@@ -263,6 +270,9 @@
|
|
|
263
270
|
|
|
264
271
|
export const show = () => tooltipInstance?.showTooltip();
|
|
265
272
|
export const hide = () => tooltipInstance?.hideTooltip();
|
|
273
|
+
export const ignoreNextClickEvent = () => {
|
|
274
|
+
ignoreNextClick = true;
|
|
275
|
+
};
|
|
266
276
|
|
|
267
277
|
// Svelte 5 effect for hidden prop
|
|
268
278
|
$effect(() => {
|
|
@@ -3,6 +3,7 @@ import type { TooltipProps } from './types';
|
|
|
3
3
|
declare const Tooltip: Component<TooltipProps, {
|
|
4
4
|
show: () => void | undefined;
|
|
5
5
|
hide: () => void | undefined;
|
|
6
|
+
ignoreNextClickEvent: () => void;
|
|
6
7
|
}, "hidden" | "isActive">;
|
|
7
8
|
type Tooltip = ReturnType<typeof Tooltip>;
|
|
8
9
|
export default Tooltip;
|