06b6274e66
Long-tail cleanup: threshold and default-value literals in shared helpers get named module-level constants. - CharacterComparisonEngine: CHAR_PROXIMITY_RANGE_PCT (5), DEFAULT_RENDER_SIZE_PX (16) — kept local instead of importing DEFAULT_FONT_SIZE from \$entities/Font because \$shared/lib cannot legally upward-import from \$entities per FSD (also avoids an init cycle through the mocks barrel). - typographySettingsStore: BASE_SIZE_EPSILON (0.01) — rounding-jitter guard for baseSize reconciliation. - createDebouncedState: DEFAULT_DEBOUNCE_MS (300) — exported so callers can mirror the default. - createVirtualizer: MEASUREMENT_EPSILON_PX (0.5) — minimum height delta before committing a re-measured row. - createPerspectiveManager: PERSPECTIVE_TOGGLE_THRESHOLD (0.5) — the halfway point on the 0-1 spring that flips isBack/isFront. Skipped #19 (PerspectivePlan defaults) per review — marginal gain.
69 lines
2.1 KiB
TypeScript
69 lines
2.1 KiB
TypeScript
import { debounce } from '$shared/lib/utils';
|
|
|
|
/**
|
|
* Default debounce delay used when no wait is provided. Picked to feel
|
|
* snappy for typing while still coalescing API-bound side effects.
|
|
*/
|
|
export const DEFAULT_DEBOUNCE_MS = 300;
|
|
|
|
/**
|
|
* Creates reactive state with immediate and debounced values.
|
|
*
|
|
* Useful for UI inputs that need instant feedback but debounced logic
|
|
* (e.g., search fields with API calls). The immediate value updates on
|
|
* every change for UI binding, while debounced updates after a delay.
|
|
*
|
|
* @param initialValue - Initial value for both immediate and debounced state
|
|
* @param wait - Delay in milliseconds before updating debounced value (default: 300)
|
|
* @returns Object with immediate/debounced getters, immediate setter, and reset method
|
|
*
|
|
* @example
|
|
* ```svelte
|
|
* <script lang="ts">
|
|
* const search = createDebouncedState('', 300);
|
|
* </script>
|
|
*
|
|
* <input bind:value={search.immediate} />
|
|
*
|
|
* <p>Typing: {search.immediate}</p>
|
|
* <p>Searching: {search.debounced}</p>
|
|
* ```
|
|
*/
|
|
export function createDebouncedState<T>(initialValue: T, wait: number = DEFAULT_DEBOUNCE_MS) {
|
|
let immediate = $state(initialValue);
|
|
let debounced = $state(initialValue);
|
|
|
|
const updateDebounced = debounce((value: T) => {
|
|
debounced = value;
|
|
}, wait);
|
|
|
|
return {
|
|
/**
|
|
* Current value with immediate updates (for UI binding)
|
|
*/
|
|
get immediate() {
|
|
return immediate;
|
|
},
|
|
set immediate(value: T) {
|
|
immediate = value;
|
|
// Manually trigger the debounce on write
|
|
updateDebounced(value);
|
|
},
|
|
/**
|
|
* Current value with debounced updates (for logic/operations)
|
|
*/
|
|
get debounced() {
|
|
return debounced;
|
|
},
|
|
/**
|
|
* Resets both values to initial or specified value.
|
|
* @param value - Optional value to reset to (defaults to initialValue)
|
|
*/
|
|
reset(value?: T) {
|
|
const resetValue = value ?? initialValue;
|
|
immediate = resetValue;
|
|
debounced = resetValue;
|
|
},
|
|
};
|
|
}
|