refactor(ui): centralize prop resolution in useDefinition
Extract prop-splitting and responsive resolution with default fallbacks from `useDefinition` into a new `resolveDefinitionProps` helper. This makes `propDefs.default` the single authoritative source of truth for default values. Previously, `useBgProvider` had a separate manual default lookup (`props.bg ?? (definition.propDefs as any).bg?.default`) that duplicated the main resolution loop. Signed-off-by: Johan Persson <johanopersson@gmail.com>
This commit is contained in:
@@ -16,7 +16,7 @@
|
||||
|
||||
import { breakpoints } from '../useBreakpoint';
|
||||
import { utilityClassMap } from '../../utils/utilityClassMap';
|
||||
import type { UnwrapResponsive, UtilityStyle } from './types';
|
||||
import type { ComponentConfig, UnwrapResponsive, UtilityStyle } from './types';
|
||||
|
||||
const namedBreakpoints = breakpoints.filter(b => b.id !== 'initial');
|
||||
|
||||
@@ -57,6 +57,42 @@ export function resolveResponsiveValue<T>(
|
||||
return value as UnwrapResponsive<T>;
|
||||
}
|
||||
|
||||
export function resolveDefinitionProps<D extends ComponentConfig<any, any>>(
|
||||
definition: D,
|
||||
props: Record<string, any>,
|
||||
breakpoint: string,
|
||||
): {
|
||||
ownPropsResolved: Record<string, any>;
|
||||
restProps: Record<string, any>;
|
||||
} {
|
||||
const ownPropKeys = new Set(Object.keys(definition.propDefs));
|
||||
const utilityPropKeys = new Set(definition.utilityProps ?? []);
|
||||
|
||||
const ownPropsRaw: Record<string, any> = {};
|
||||
const restProps: Record<string, any> = {};
|
||||
|
||||
for (const [key, value] of Object.entries(props)) {
|
||||
if (ownPropKeys.has(key)) {
|
||||
ownPropsRaw[key] = value;
|
||||
} else if (!(utilityPropKeys as Set<string>).has(key)) {
|
||||
restProps[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
const ownPropsResolved: Record<string, any> = {};
|
||||
|
||||
for (const [key, config] of Object.entries(definition.propDefs)) {
|
||||
const rawValue = ownPropsRaw[key];
|
||||
const resolvedValue = resolveResponsiveValue(rawValue, breakpoint);
|
||||
const finalValue = resolvedValue ?? (config as any).default;
|
||||
if (finalValue !== undefined) {
|
||||
ownPropsResolved[key] = finalValue;
|
||||
}
|
||||
}
|
||||
|
||||
return { ownPropsResolved, restProps };
|
||||
}
|
||||
|
||||
export function processUtilityProps<Keys extends string>(
|
||||
props: Record<string, any>,
|
||||
utilityPropKeys: readonly Keys[],
|
||||
|
||||
@@ -18,7 +18,7 @@ import { ReactNode } from 'react';
|
||||
import clsx from 'clsx';
|
||||
import { useBreakpoint } from '../useBreakpoint';
|
||||
import { useBgProvider, useBgConsumer, BgProvider } from '../useBg';
|
||||
import { resolveResponsiveValue, processUtilityProps } from './helpers';
|
||||
import { resolveDefinitionProps, processUtilityProps } from './helpers';
|
||||
import type {
|
||||
ComponentConfig,
|
||||
UseDefinitionOptions,
|
||||
@@ -36,41 +36,19 @@ export function useDefinition<
|
||||
): UseDefinitionResult<D, P> {
|
||||
const { breakpoint } = useBreakpoint();
|
||||
|
||||
// Provider: resolve bg and provide context for children
|
||||
const providerBg = useBgProvider(
|
||||
definition.bg === 'provider'
|
||||
? props.bg ?? (definition.propDefs as any).bg?.default
|
||||
: undefined,
|
||||
// Resolve all props centrally — applies responsive values and defaults
|
||||
const { ownPropsResolved, restProps } = resolveDefinitionProps(
|
||||
definition,
|
||||
props,
|
||||
breakpoint,
|
||||
);
|
||||
|
||||
// Consumer: read parent context bg
|
||||
const consumerBg = useBgConsumer();
|
||||
|
||||
const ownPropKeys = new Set(Object.keys(definition.propDefs));
|
||||
const utilityPropKeys = new Set(definition.utilityProps ?? []);
|
||||
|
||||
const ownPropsRaw: Record<string, any> = {};
|
||||
const restProps: Record<string, any> = {};
|
||||
|
||||
for (const [key, value] of Object.entries(props)) {
|
||||
if (ownPropKeys.has(key)) {
|
||||
ownPropsRaw[key] = value;
|
||||
} else if (!(utilityPropKeys as Set<string>).has(key)) {
|
||||
restProps[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
const ownPropsResolved: Record<string, any> = {};
|
||||
const dataAttributes: Record<string, string | undefined> = {};
|
||||
|
||||
for (const [key, config] of Object.entries(definition.propDefs)) {
|
||||
const rawValue = ownPropsRaw[key];
|
||||
const resolvedValue = resolveResponsiveValue(rawValue, breakpoint);
|
||||
const finalValue = resolvedValue ?? (config as any).default;
|
||||
const finalValue = ownPropsResolved[key];
|
||||
|
||||
if (finalValue !== undefined) {
|
||||
ownPropsResolved[key] = finalValue;
|
||||
|
||||
// Skip data-bg for bg prop when the provider path handles it
|
||||
if (key === 'bg' && definition.bg === 'provider') continue;
|
||||
|
||||
@@ -81,6 +59,14 @@ export function useDefinition<
|
||||
}
|
||||
}
|
||||
|
||||
// Provider: resolve bg and provide context for children
|
||||
const providerBg = useBgProvider(
|
||||
definition.bg === 'provider' ? ownPropsResolved.bg : undefined,
|
||||
);
|
||||
|
||||
// Consumer: read parent context bg
|
||||
const consumerBg = useBgConsumer();
|
||||
|
||||
// Provider: set data-bg from the resolved provider bg
|
||||
if (definition.bg === 'provider' && providerBg.bg !== undefined) {
|
||||
dataAttributes['data-bg'] = String(providerBg.bg);
|
||||
|
||||
Reference in New Issue
Block a user