@vitus-labs/rocketstyle
Version:
Rocketstyle is ultra powerful and extensible styling system for building React components blazingly fast, easily and make them easily extensible and reusable.
787 lines (764 loc) • 25.8 kB
JavaScript
import { Provider as Provider$1, compose, config, context, get, hoistNonReactStatics, isEmpty, merge, omit, pick, render, set, useStableValue } from "@vitus-labs/core";
import { createContext, useCallback, useContext, useImperativeHandle, useMemo, useRef, useState } from "react";
import { jsx } from "react/jsx-runtime";
//#region src/constants/index.ts
/** Default theme mode used when no mode is provided via context. */
const MODE_DEFAULT = "light";
/** Pseudo-state interaction keys tracked for styling (hover, active, focus, pressed). */
const PSEUDO_KEYS = [
"hover",
"active",
"focus",
"pressed"
];
/** Meta pseudo-state keys representing non-interactive states (disabled, readOnly). */
const PSEUDO_META_KEYS = ["disabled", "readOnly"];
/** Supported theme mode flags. */
const THEME_MODES = {
light: true,
dark: true
};
/** Maps each theme mode to its inverse (light -> dark, dark -> light). */
const THEME_MODES_INVERSED = {
dark: "light",
light: "dark"
};
/** Reserved configuration keys accepted by the `.config()` chaining method. */
const CONFIG_KEYS = [
"provider",
"consumer",
"DEBUG",
"name",
"component",
"inversed",
"passProps",
"styled"
];
/** Keys for theme and styles chaining methods. */
const STYLING_KEYS = ["theme", "styles"];
const STATIC_KEYS = [...STYLING_KEYS, "compose"];
/** Union of all reserved keys that cannot be used as dimension names. */
const ALL_RESERVED_KEYS = [
...Object.keys(THEME_MODES),
...CONFIG_KEYS,
...STATIC_KEYS,
"attrs"
];
//#endregion
//#region src/context/context.tsx
/**
* Top-level theme and mode provider for rocketstyle components.
* Reads the parent context, merges incoming props, and resolves
* the active mode (with optional inversion for nested dark/light switching).
*/
const Provider = ({ provider = Provider$1, inversed, ...props }) => {
const { theme, mode, provider: RocketstyleProvider, children } = {
...useContext(context),
...props,
provider
};
let newMode = MODE_DEFAULT;
if (mode) newMode = inversed ? THEME_MODES_INVERSED[mode] : mode;
return /* @__PURE__ */ jsx(RocketstyleProvider, {
mode: newMode,
isDark: newMode === "dark",
isLight: newMode === "light",
theme,
provider,
children
});
};
//#endregion
//#region src/constants/defaultDimensions.ts
/**
* Default dimension configuration for rocketstyle components.
* Defines four built-in dimensions: `states`, `sizes`, `variants`,
* and `multiple` (a multi-select dimension).
*/
const DEFAULT_DIMENSIONS = {
states: "state",
sizes: "size",
variants: "variant",
multiple: {
propName: "multiple",
multi: true
},
modifiers: {
propName: "modifier",
multi: true,
transform: true
}
};
//#endregion
//#region src/cache/LocalThemeManager.ts
/**
* WeakMap-based multi-tier cache for computed theme objects.
* Maintains separate caches for base themes, dimension themes,
* and their light/dark mode variants to avoid recalculation on re-renders.
*/
var ThemeManager = class {
baseTheme = /* @__PURE__ */ new WeakMap();
dimensionsThemes = /* @__PURE__ */ new WeakMap();
modeBaseTheme = {
light: /* @__PURE__ */ new WeakMap(),
dark: /* @__PURE__ */ new WeakMap()
};
modeDimensionTheme = {
light: /* @__PURE__ */ new WeakMap(),
dark: /* @__PURE__ */ new WeakMap()
};
};
//#endregion
//#region src/hooks/usePseudoState.tsx
/**
* Tracks hover, focus, and pressed pseudo-states via mouse and focus
* event handlers. Returns the current state flags and wrapped event
* callbacks that preserve any user-provided handlers.
*/
const usePseudoState = ({ onBlur, onFocus, onMouseDown, onMouseEnter, onMouseLeave, onMouseUp }) => {
const [hover, setHover] = useState(false);
const [focus, setFocus] = useState(false);
const [pressed, setPressed] = useState(false);
const handleOnMouseEnter = useCallback((e) => {
setHover(true);
if (onMouseEnter) onMouseEnter(e);
}, [onMouseEnter]);
const handleOnMouseLeave = useCallback((e) => {
setHover(false);
setPressed(false);
if (onMouseLeave) onMouseLeave(e);
}, [onMouseLeave]);
const handleOnMouseDown = useCallback((e) => {
setPressed(true);
if (onMouseDown) onMouseDown(e);
}, [onMouseDown]);
const handleOnMouseUp = useCallback((e) => {
setPressed(false);
if (onMouseUp) onMouseUp(e);
}, [onMouseUp]);
const handleOnFocus = useCallback((e) => {
setFocus(true);
if (onFocus) onFocus(e);
}, [onFocus]);
const handleOnBlur = useCallback((e) => {
setFocus(false);
if (onBlur) onBlur(e);
}, [onBlur]);
return {
state: useMemo(() => ({
hover,
focus,
pressed
}), [
hover,
focus,
pressed
]),
events: useMemo(() => ({
onMouseEnter: handleOnMouseEnter,
onMouseLeave: handleOnMouseLeave,
onMouseDown: handleOnMouseDown,
onMouseUp: handleOnMouseUp,
onFocus: handleOnFocus,
onBlur: handleOnBlur
}), [
handleOnMouseEnter,
handleOnMouseLeave,
handleOnMouseDown,
handleOnMouseUp,
handleOnFocus,
handleOnBlur
])
};
};
//#endregion
//#region src/hooks/useRef.ts
/**
* Unifies two forwarded refs (the outer consumer ref and the internal
* rocketstyle HOC ref) into a single internal ref using `useImperativeHandle`,
* so both callers receive the same underlying DOM node.
*/
const useRocketstyleRef = ({ $rocketstyleRef, ref }) => {
const internalRef = useRef(null);
useImperativeHandle($rocketstyleRef, () => internalRef.current);
useImperativeHandle(ref, () => internalRef.current);
return internalRef;
};
//#endregion
//#region src/hooks/useTheme.tsx
/**
* Retrieves the current theme object and resolved mode from context.
* Supports mode inversion so nested components can flip between
* light and dark without a new provider.
*/
const useThemeAttrs = ({ inversed }) => {
const { theme = {}, mode: ctxMode = "light", isDark: ctxDark } = useContext(context) || {};
const mode = inversed ? THEME_MODES_INVERSED[ctxMode] : ctxMode;
const isDark = inversed ? !ctxDark : ctxDark;
const isLight = !isDark;
return useMemo(() => ({
theme,
mode,
isDark,
isLight
}), [
theme,
mode,
isDark,
isLight
]);
};
//#endregion
//#region src/context/localContext.tsx
/**
* Local context for propagating pseudo-state (hover, focus, pressed)
* and additional styling attributes from a parent provider component
* to its rocketstyle children.
*/
const context$1 = createContext({});
const EMPTY_CTX = { pseudo: {} };
const useLocalContext = (consumer) => {
const ctx = useContext(context$1);
return useMemo(() => {
if (!consumer) return EMPTY_CTX;
return {
pseudo: {},
...consumer((callback) => callback(ctx))
};
}, [consumer, ctx]);
};
const LocalProvider = context$1.Provider;
//#endregion
//#region src/context/createLocalProvider.tsx
/**
* Higher-order component that wraps a component with a LocalProvider,
* detecting pseudo-states (hover, focus, pressed) via mouse/focus events
* and broadcasting them through local context to child rocketstyle components.
*/
const RocketStyleProviderComponent = (WrappedComponent) => {
const HOC = ({ onMouseEnter, onMouseLeave, onMouseUp, onMouseDown, onFocus, onBlur, $rocketstate, ref, ...props }) => {
const { state: pseudoState, events: pseudoEvents } = usePseudoState({
onMouseEnter,
onMouseLeave,
onMouseUp,
onMouseDown,
onFocus,
onBlur
});
const updatedState = useStableValue({
...$rocketstate,
pseudo: {
...$rocketstate.pseudo,
...pseudoState
}
});
return /* @__PURE__ */ jsx(LocalProvider, {
value: updatedState,
children: /* @__PURE__ */ jsx(WrappedComponent, {
...props,
...pseudoEvents,
ref,
$rocketstate: updatedState
})
});
};
return HOC;
};
//#endregion
//#region src/utils/attrs.ts
const removeUndefinedProps = (props) => {
const result = {};
for (const key in props) if (props[key] !== void 0) result[key] = props[key];
return result;
};
const pickStyledAttrs = (props, keywords) => Object.keys(props).reduce((acc, key) => {
if (keywords[key] && props[key]) acc[key] = props[key];
return acc;
}, {});
const calculateChainOptions = (options) => (args) => {
const result = {};
if (isEmpty(options)) return result;
return options.reduce((acc, item) => Object.assign(acc, item(...args)), {});
};
const calculateStylingAttrs = ({ useBooleans, multiKeys }) => ({ props, dimensions }) => {
const result = {};
Object.keys(dimensions).forEach((item) => {
const pickedProp = props[item];
const t = typeof pickedProp;
if (multiKeys?.[item] && Array.isArray(pickedProp)) result[item] = pickedProp;
else if (t === "string" || t === "number") result[item] = pickedProp;
else result[item] = void 0;
});
if (useBooleans) {
const propsKeys = Object.keys(props);
Object.entries(result).forEach(([key, value]) => {
const isMultiKey = multiKeys[key];
if (!value) {
let newDimensionValue;
const keywordSet = new Set(Object.keys(dimensions[key]));
if (isMultiKey) newDimensionValue = propsKeys.filter((key) => keywordSet.has(key));
else for (let i = propsKeys.length - 1; i >= 0; i--) {
const k = propsKeys[i];
if (keywordSet.has(k) && props[k]) {
newDimensionValue = k;
break;
}
}
result[key] = newDimensionValue;
}
});
}
return result;
};
//#endregion
//#region src/hoc/rocketstyleAttrsHoc.tsx
/**
* HOC that resolves the `.attrs()` chain before the inner component renders.
* Evaluates both regular and priority attrs callbacks with the current theme
* and mode, then merges the results with explicit props (priority attrs
* are applied first, regular attrs can be overridden by direct props).
*/
const rocketStyleHOC = ({ inversed, attrs, priorityAttrs }) => {
const calculateAttrs = calculateChainOptions(attrs);
const calculatePriorityAttrs = calculateChainOptions(priorityAttrs);
const Enhanced = (WrappedComponent) => {
const HOC = ({ ref, ...props }) => {
const { theme, mode, isDark, isLight } = useThemeAttrs({ inversed });
const callbackParams = [theme, {
render,
mode,
isDark,
isLight
}];
const filteredProps = removeUndefinedProps(props);
const prioritizedAttrs = calculatePriorityAttrs([filteredProps, ...callbackParams]);
const finalAttrs = calculateAttrs([{
...prioritizedAttrs,
...filteredProps
}, ...callbackParams]);
return /* @__PURE__ */ jsx(WrappedComponent, {
$rocketstyleRef: ref,
...prioritizedAttrs,
...finalAttrs,
...filteredProps
});
};
return HOC;
};
return Enhanced;
};
//#endregion
//#region src/utils/chaining.ts
const chainOptions = (opts, defaultOpts = []) => {
const result = [...defaultOpts];
if (typeof opts === "function") result.push(opts);
else if (typeof opts === "object") result.push(() => opts);
return result;
};
const chainOrOptions = (keys, opts, defaultOpts) => keys.reduce((acc, item) => ({
...acc,
[item]: opts[item] || defaultOpts[item]
}), {});
const chainReservedKeyOptions = (keys, opts, defaultOpts) => keys.reduce((acc, item) => ({
...acc,
[item]: chainOptions(opts[item], defaultOpts[item])
}), {});
//#endregion
//#region src/utils/compose.ts
const calculateHocsFuncs = (options = {}) => Object.values(options).filter((item) => typeof item === "function").reverse();
//#endregion
//#region src/utils/dimensions.ts
const isValidKey = (value) => value !== void 0 && value !== null && value !== false;
const isMultiKey = (value) => {
if (typeof value === "object" && value !== null) return [true, get(value, "propName")];
return [false, value];
};
const getDimensionsMap = ({ themes, useBooleans }) => {
const result = {
keysMap: {},
keywords: {}
};
if (isEmpty(themes)) return result;
return Object.entries(themes).reduce((accumulator, [key, value]) => {
const { keysMap, keywords } = accumulator;
keywords[key] = true;
Object.entries(value).forEach(([itemKey, itemValue]) => {
if (!isValidKey(itemValue)) return;
if (useBooleans) keywords[itemKey] = true;
set(keysMap, [key, itemKey], true);
});
return accumulator;
}, result);
};
const getKeys = (obj) => Object.keys(obj);
const getValues = (obj) => Object.values(obj);
const getDimensionsValues = (obj) => getValues(obj).map((item) => {
if (typeof item === "object") return item.propName;
return item;
});
const getMultipleDimensions = (obj) => getValues(obj).reduce((accumulator, value) => {
if (typeof value === "object") {
if (value.multi === true) accumulator[value.propName] = true;
}
return accumulator;
}, {});
const getTransformDimensions = (obj) => getValues(obj).reduce((accumulator, value) => {
if (typeof value === "object") {
if (value.transform === true) accumulator[value.propName] = true;
}
return accumulator;
}, {});
//#endregion
//#region src/utils/statics.ts
const createStaticsChainingEnhancers = ({ context, dimensionKeys, func, options }) => {
[...dimensionKeys, ...STATIC_KEYS].forEach((item) => {
context[item] = (props) => func(options, { [item]: props });
});
};
const createStaticsEnhancers = ({ context, options }) => {
if (!isEmpty(options)) Object.assign(context, options);
};
//#endregion
//#region src/utils/styles.ts
const calculateStyles = (styles) => {
if (!styles) return [];
return styles.map((item) => item(config.css));
};
//#endregion
//#region src/utils/collection.ts
const removeNullableValues = (obj) => Object.entries(obj).filter(([, v]) => v != null && v !== false).reduce((acc, [k, v]) => ({
...acc,
[k]: v
}), {});
//#endregion
//#region src/utils/theme.ts
const MODE_CALLBACK_BRAND = Symbol.for("vl.themeModeCallback");
/** Creates a mode-switching function that returns the light or dark value based on the active mode. */
const themeModeCallback = (light, dark) => {
const fn = (mode) => {
if (!mode || mode === "light") return light;
return dark;
};
fn.__brand = MODE_CALLBACK_BRAND;
return fn;
};
const isModeCallback = (value) => typeof value === "function" && value.__brand === MODE_CALLBACK_BRAND;
const getThemeFromChain = (options, theme) => {
const result = {};
if (!options || isEmpty(options)) return result;
return options.reduce((acc, item) => merge(acc, item(theme, themeModeCallback, config.css)), result);
};
const getDimensionThemes = (theme, options) => {
const result = {};
if (isEmpty(options.dimensions)) return result;
return Object.entries(options.dimensions).reduce((acc, [key, value]) => {
const [, dimension] = isMultiKey(value);
const helper = options[key];
if (Array.isArray(helper) && helper.length > 0) acc[dimension] = removeNullableValues(getThemeFromChain(helper, theme));
return acc;
}, result);
};
const getTheme = ({ rocketstate, themes, baseTheme, transformKeys, appTheme }) => {
const finalTheme = { ...baseTheme };
const deferredTransforms = [];
Object.entries(rocketstate).forEach(([key, value]) => {
const keyTheme = themes[key];
const isTransform = transformKeys?.[key];
const mergeValue = (item) => {
const val = keyTheme[item];
if (val == null) return;
if (isTransform && typeof val === "function") deferredTransforms.push(val);
else merge(finalTheme, val);
};
if (Array.isArray(value)) value.forEach(mergeValue);
else mergeValue(value);
});
for (const transform of deferredTransforms) merge(finalTheme, transform(finalTheme, appTheme ?? {}, themeModeCallback, config.css));
return finalTheme;
};
const getThemeByMode = (object, mode) => Object.keys(object).reduce((acc, key) => {
const value = object[key];
if (typeof value === "object" && value !== null) acc[key] = getThemeByMode(value, mode);
else if (isModeCallback(value)) acc[key] = value(mode);
else acc[key] = value;
return acc;
}, {});
//#endregion
//#region src/rocketstyle.tsx
/**
* Core rocketstyle component factory. Creates a fully-featured React component
* that integrates theme management (with light/dark mode support), multi-tier
* WeakMap caching, dimension-based styling props, pseudo-state detection, and
* chainable static methods (`.attrs()`, `.theme()`, `.styles()`, `.config()`, etc.).
* @module rocketstyle
*/
const arraysEqual = (a, b) => {
if (a.length !== b.length) return false;
for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;
return true;
};
const isShallowEqualRocketstate = (a, b) => {
if (a === b) return true;
if (!a || !b) return false;
const aKeys = Object.keys(a);
if (aKeys.length !== Object.keys(b).length) return false;
for (const k of aKeys) {
const av = a[k];
const bv = b[k];
if (av === bv) continue;
if (Array.isArray(av) && Array.isArray(bv) && arraysEqual(av, bv)) continue;
return false;
}
return true;
};
/**
* Clones the current configuration and merges new options, returning a fresh
* rocketComponent.
*
* Component-swap reset: when `opts.component` is set AND differs from the
* current `defaultOpts.component`, the prior `attrs`, `priorityAttrs`, and
* `compose` chains are dropped — they were tailored to the previous
* component's prop shape, and applying them to a different component
* silently leaks invalid props through to the DOM (e.g. `disabled` on an
* `<a>`). Callers who want to preserve them must re-chain explicitly:
*
* const NewBtn = Button.config({ component: 'a' }).attrs(sharedAttrs)
*/
const cloneAndEnhance = (defaultOpts, opts) => {
const componentChanged = opts.component != null && opts.component !== defaultOpts.component;
return rocketComponent({
...defaultOpts,
attrs: componentChanged ? chainOptions(opts.attrs, []) : chainOptions(opts.attrs, defaultOpts.attrs),
filterAttrs: componentChanged ? [...opts.filterAttrs ?? []] : [...defaultOpts.filterAttrs ?? [], ...opts.filterAttrs ?? []],
priorityAttrs: componentChanged ? chainOptions(opts.priorityAttrs, []) : chainOptions(opts.priorityAttrs, defaultOpts.priorityAttrs),
statics: {
...defaultOpts.statics,
...opts.statics
},
compose: componentChanged ? { ...opts.compose } : {
...defaultOpts.compose,
...opts.compose
},
...chainOrOptions(CONFIG_KEYS, opts, defaultOpts),
...chainReservedKeyOptions([...defaultOpts.dimensionKeys, ...STYLING_KEYS], opts, defaultOpts)
});
};
/**
* Builds the final renderable React component with theme resolution,
* dimension mapping, pseudo-state context, HOC composition, and
* chainable static enhancers attached to the returned component.
*/
const rocketComponent = (options) => {
const { component, styles, transformKeys } = options;
const { styled } = config;
const _calculateStylingAttrs = calculateStylingAttrs({
multiKeys: options.multiKeys,
useBooleans: options.useBooleans
});
const componentName = options.name ?? options.component.displayName ?? options.component.name;
const STYLED_COMPONENT = component.IS_ROCKETSTYLE ?? options.styled !== true ? component : styled(component, { boost: true })`
${calculateStyles(styles)};
`;
const RenderComponent = options.provider ? RocketStyleProviderComponent(STYLED_COMPONENT) : STYLED_COMPONENT;
const ThemeManager$1 = new ThemeManager();
const hocsFuncs = [rocketStyleHOC(options), ...calculateHocsFuncs(options.compose)];
const EnhancedComponent = ({ $rocketstyleRef, ref, ...props }) => {
const internalRef = useRocketstyleRef({
$rocketstyleRef,
ref
});
const localCtx = useLocalContext(options.consumer);
const { theme, mode } = useThemeAttrs(options);
const baseTheme = useMemo(() => {
const helper = ThemeManager$1.baseTheme;
if (!helper.has(theme)) helper.set(theme, getThemeFromChain(options.theme, theme));
return helper.get(theme);
}, [theme]);
const themes = useMemo(() => {
const helper = ThemeManager$1.dimensionsThemes;
if (!helper.has(theme)) helper.set(theme, getDimensionThemes(theme, options));
return helper.get(theme);
}, [theme]);
const currentModeBaseTheme = useMemo(() => {
const helper = ThemeManager$1.modeBaseTheme[mode];
if (!helper.has(baseTheme)) helper.set(baseTheme, getThemeByMode(baseTheme, mode));
return helper.get(baseTheme);
}, [mode, baseTheme]);
const currentModeThemes = useMemo(() => {
const helper = ThemeManager$1.modeDimensionTheme[mode];
if (!helper.has(themes)) helper.set(themes, getThemeByMode(themes, mode));
return helper.get(themes);
}, [mode, themes]);
const { keysMap: dimensions, keywords: reservedPropNames } = useMemo(() => getDimensionsMap({
themes,
useBooleans: options.useBooleans
}), [themes]);
const RESERVED_STYLING_PROPS_KEYS = useMemo(() => Object.keys(reservedPropNames), [reservedPropNames]);
const { pseudo, ...mergeProps } = {
...localCtx,
...props
};
const pseudoRocketstate = {
...pseudo,
...pick(props, [...PSEUDO_KEYS, ...PSEUDO_META_KEYS])
};
const rocketstate = _calculateStylingAttrs({
props: pickStyledAttrs(mergeProps, reservedPropNames),
dimensions
});
const finalRocketstate = {
...rocketstate,
pseudo: pseudoRocketstate
};
const rocketstateRef = useRef(rocketstate);
if (!isShallowEqualRocketstate(rocketstateRef.current, rocketstate)) rocketstateRef.current = rocketstate;
const stableRocketstate = rocketstateRef.current;
const rocketstyle = useMemo(() => getTheme({
rocketstate: stableRocketstate,
themes: currentModeThemes,
baseTheme: currentModeBaseTheme,
transformKeys,
appTheme: theme
}), [
stableRocketstate,
currentModeThemes,
currentModeBaseTheme,
theme
]);
const finalProps = {
...omit(mergeProps, [
...RESERVED_STYLING_PROPS_KEYS,
...PSEUDO_KEYS,
...options.filterAttrs
]),
...options.passProps ? pick(mergeProps, options.passProps) : {},
ref: ref ?? $rocketstyleRef ? internalRef : void 0,
$rocketstyle: rocketstyle,
$rocketstate: finalRocketstate
};
if (process.env.NODE_ENV !== "production") {
finalProps["data-rocketstyle"] = componentName;
if (options.DEBUG) {
const debugPayload = {
component: componentName,
rocketstate: finalRocketstate,
rocketstyle,
dimensions,
mode,
reservedPropNames: RESERVED_STYLING_PROPS_KEYS,
filteredAttrs: options.filterAttrs
};
console.debug(`[rocketstyle] ${componentName} render:`, debugPayload);
}
}
return /* @__PURE__ */ jsx(RenderComponent, { ...finalProps });
};
const RocketComponent = compose(...hocsFuncs)(EnhancedComponent);
RocketComponent.IS_ROCKETSTYLE = true;
RocketComponent.displayName = componentName;
hoistNonReactStatics(RocketComponent, options.component);
createStaticsChainingEnhancers({
context: RocketComponent,
dimensionKeys: options.dimensionKeys,
func: cloneAndEnhance,
options
});
RocketComponent.IS_ROCKETSTYLE = true;
RocketComponent.displayName = componentName;
RocketComponent.meta = {};
createStaticsEnhancers({
context: RocketComponent.meta,
options: options.statics
});
Object.assign(RocketComponent, {
attrs: (attrs, { priority, filter } = {}) => {
const result = {};
if (filter) result.filterAttrs = filter;
if (priority) {
result.priorityAttrs = attrs;
return cloneAndEnhance(options, result);
}
result.attrs = attrs;
return cloneAndEnhance(options, result);
},
config: (opts = {}) => {
return cloneAndEnhance(options, pick(opts, CONFIG_KEYS));
},
statics: (opts) => cloneAndEnhance(options, { statics: opts }),
getStaticDimensions: (theme) => {
const { keysMap, keywords } = getDimensionsMap({
themes: getDimensionThemes(theme, options),
useBooleans: options.useBooleans
});
return {
dimensions: keysMap,
keywords,
useBooleans: options.useBooleans,
multiKeys: options.multiKeys
};
},
getDefaultAttrs: (props, theme, mode) => calculateChainOptions(options.attrs)([
props,
theme,
{
render,
mode,
isDark: mode === "dark",
isLight: mode === "light"
}
])
});
return RocketComponent;
};
//#endregion
//#region src/init.ts
const validateInit = (name, component, dimensions) => {
const errors = {};
if (!component) errors.component = "Parameter `component` is missing in params!";
if (!name) errors.name = "Parameter `name` is missing in params!";
if (isEmpty(dimensions)) errors.dimensions = "Parameter `dimensions` is missing in params!";
else {
const definedDimensions = getKeys(dimensions);
if (ALL_RESERVED_KEYS.some((item) => definedDimensions.some((d) => d === item))) errors.invalidDimensions = `Some of your \`dimensions\` is invalid and uses reserved static keys which are
${DEFAULT_DIMENSIONS.toString()}`;
}
if (!isEmpty(errors)) throw Error(JSON.stringify(errors));
};
/**
* Generic implementation. The `D | DefaultDimensions` runtime fallback is
* narrowed to `D` via a single cast — semantically correct because when no
* user dimensions are supplied, `D` *is* the default (its type-parameter
* default is `DefaultDimensions`). This single boundary cast replaces the
* file-wide `@ts-nocheck` previously used here.
*/
const rocketstyle = (params) => {
const dimensions = params?.dimensions ?? DEFAULT_DIMENSIONS;
const useBooleans = params?.useBooleans ?? true;
return ({ name, component }) => {
if (process.env.NODE_ENV !== "production") validateInit(name, component, dimensions);
return rocketComponent({
name,
component,
useBooleans,
dimensions,
dimensionKeys: getKeys(dimensions),
dimensionValues: getDimensionsValues(dimensions),
multiKeys: getMultipleDimensions(dimensions),
transformKeys: getTransformDimensions(dimensions),
styled: true
});
};
};
const typedRocketstyle = rocketstyle;
//#endregion
//#region src/isRocketComponent.tsx
const isRocketComponent = (component) => {
if (component && (typeof component === "object" || typeof component === "function") && Object.hasOwn(component, "IS_ROCKETSTYLE")) return true;
return false;
};
//#endregion
//#region src/index.ts
var src_default = typedRocketstyle;
//#endregion
export { Provider, context, src_default as default, isRocketComponent, typedRocketstyle as rocketstyle };
//# sourceMappingURL=index.js.map