|
46 | 46 | import ShadeGrid from './ShadeGrid.svelte'; |
47 | 47 | import ChannelSlider from './ChannelSlider.svelte'; |
48 | 48 | import LockIcon from '$lib/components/shared/LockIcon.svelte'; |
| 49 | + import {clamp} from '$lib/utils/math'; |
49 | 50 |
|
50 | 51 | const ROLE_LABELS: Record<string, string> = { |
51 | 52 | background: 'Background', |
|
205 | 206 | }; |
206 | 207 | let activeModel = $derived(getColorPickerModel()); |
207 | 208 |
|
| 209 | + function parseEditedNumber(raw: string): number | null { |
| 210 | + const n = parseFloat(raw.replace(/[°%]/g, '').trim()); |
| 211 | + return Number.isFinite(n) ? n : null; |
| 212 | + } |
| 213 | +
|
| 214 | + // Builds an `oncommit` handler for a ChannelSlider: parse → clamp → dispatch. |
| 215 | + // `transform` lets OKLCH C map its 0..0.4 display value onto the 0..40 slider. |
| 216 | + function makeCommitHandler<C extends string>( |
| 217 | + channel: C, |
| 218 | + handle: (c: C, value: number) => void, |
| 219 | + max: number, |
| 220 | + transform: (n: number) => number = n => n |
| 221 | + ): (raw: string) => void { |
| 222 | + return raw => { |
| 223 | + const n = parseEditedNumber(raw); |
| 224 | + if (n === null) return; |
| 225 | + handle(channel, clamp(transform(n), 0, max)); |
| 226 | + }; |
| 227 | + } |
| 228 | +
|
208 | 229 | let harmonyColors = $derived( |
209 | 230 | HARMONY.map(h => ({ |
210 | 231 | ...h, |
|
567 | 588 | gradient={channelGradient(channel)} |
568 | 589 | disabled={locked} |
569 | 590 | onchange={v => handleRgbChange(channel, Math.round(v))} |
| 591 | + oncommit={makeCommitHandler( |
| 592 | + channel, |
| 593 | + handleRgbChange, |
| 594 | + 255, |
| 595 | + Math.round |
| 596 | + )} |
570 | 597 | /> |
571 | 598 | {/each} |
572 | 599 | {:else if activeModel === 'hsl'} |
|
579 | 606 | gradient={hslChannelGradient(channel)} |
580 | 607 | disabled={locked} |
581 | 608 | onchange={v => handleHslChange(channel, v)} |
| 609 | + oncommit={makeCommitHandler( |
| 610 | + channel, |
| 611 | + handleHslChange, |
| 612 | + HSL_MAX[channel] |
| 613 | + )} |
582 | 614 | /> |
583 | 615 | {/each} |
584 | 616 | {:else} |
|
591 | 623 | gradient={oklchChannelGradient(channel)} |
592 | 624 | disabled={locked} |
593 | 625 | onchange={v => handleOklchChange(channel, v)} |
| 626 | + oncommit={makeCommitHandler( |
| 627 | + channel, |
| 628 | + handleOklchChange, |
| 629 | + OKLCH_MAX[channel], |
| 630 | + // C displays 0..0.4 but slider is 0..40. |
| 631 | + channel === 'c' ? n => n * 100 : undefined |
| 632 | + )} |
594 | 633 | /> |
595 | 634 | {/each} |
596 | 635 | {/if} |
|
0 commit comments