@mui/internal-docs-infra
Version:
MUI Infra - internal documentation creation tools.
97 lines (91 loc) • 4.13 kB
JavaScript
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
import _typeof from "@babel/runtime/helpers/esm/typeof";
import * as React from 'react';
import { usePreference } from "../usePreference/index.js";
/**
* Hook for managing variant selection and providing variant-related data
* Uses React state as source of truth, with localStorage for persistence
*/
export function useVariantSelection(_ref) {
var effectiveCode = _ref.effectiveCode,
initialVariant = _ref.initialVariant,
variantType = _ref.variantType;
// Get variant keys from effective code
var variantKeys = React.useMemo(function () {
return Object.keys(effectiveCode).filter(function (key) {
var variant = effectiveCode[key];
return variant && _typeof(variant) === 'object' && 'source' in variant;
});
}, [effectiveCode]);
// Use localStorage hook for variant persistence
var _usePreference = usePreference('variant', variantType || variantKeys, function () {
return null;
}),
_usePreference2 = _slicedToArray(_usePreference, 2),
storedValue = _usePreference2[0],
setStoredValue = _usePreference2[1];
// Initialize state from localStorage or initialVariant
var _React$useState = React.useState(function () {
// First priority: use stored value if it exists and is valid
if (storedValue && variantKeys.includes(storedValue)) {
return storedValue;
}
// Second priority: use initial variant if provided and valid
if (initialVariant && variantKeys.includes(initialVariant)) {
return initialVariant;
}
// Final fallback: use first available variant
return variantKeys[0] || '';
}),
_React$useState2 = _slicedToArray(_React$useState, 2),
selectedVariantKey = _React$useState2[0],
setSelectedVariantKeyState = _React$useState2[1];
// Sync with localStorage changes (but don't override programmatic changes)
// Only sync when storedValue changes, not when selectedVariantKey changes
var prevStoredValue = React.useRef(storedValue);
React.useEffect(function () {
if (storedValue !== prevStoredValue.current) {
prevStoredValue.current = storedValue;
if (storedValue && variantKeys.includes(storedValue) && storedValue !== selectedVariantKey) {
setSelectedVariantKeyState(storedValue);
}
}
}, [storedValue, variantKeys, selectedVariantKey]);
var setSelectedVariantKeyProgrammatic = React.useCallback(function (value) {
var resolvedValue = typeof value === 'function' ? value(selectedVariantKey) : value;
if (variantKeys.includes(resolvedValue)) {
// Only update React state, not localStorage
// This prevents conflicts with hash-driven navigation
setSelectedVariantKeyState(resolvedValue);
}
}, [selectedVariantKey, variantKeys]);
var setSelectedVariantKeyAsUser = React.useCallback(function (value) {
var resolvedValue = typeof value === 'function' ? value(selectedVariantKey) : value;
if (variantKeys.includes(resolvedValue)) {
setSelectedVariantKeyState(resolvedValue);
setStoredValue(resolvedValue);
}
}, [setStoredValue, selectedVariantKey, variantKeys]);
var selectedVariant = React.useMemo(function () {
var variant = effectiveCode[selectedVariantKey];
if (variant && _typeof(variant) === 'object' && 'source' in variant) {
return variant;
}
return null;
}, [effectiveCode, selectedVariantKey]);
// Safety check: if selectedVariant doesn't exist, fall back to first variant
React.useEffect(function () {
if (!selectedVariant && variantKeys.length > 0) {
// Don't mark this as a user selection - it's just a fallback
// Use programmatic setter to avoid localStorage save
setSelectedVariantKeyProgrammatic(variantKeys[0]);
}
}, [selectedVariant, variantKeys, setSelectedVariantKeyProgrammatic]);
return {
variantKeys: variantKeys,
selectedVariantKey: selectedVariantKey,
selectedVariant: selectedVariant,
selectVariant: setSelectedVariantKeyAsUser,
selectVariantProgrammatic: setSelectedVariantKeyProgrammatic
};
}