Files
frontend-svelte/src/shared/lib/helpers/createDebouncedState/createDebouncedState.svelte.ts
T
Ilia Mashkov 06b6274e66 refactor: extract magic constants — wave 5 (single-site thresholds)
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.
2026-05-24 22:07:44 +03:00

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;
},
};
}