79 lines
2.6 KiB
JavaScript
79 lines
2.6 KiB
JavaScript
const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
|
|
let react = require("react");
|
|
react = require_runtime.__toESM(react);
|
|
let tailwind_merge = require("tailwind-merge");
|
|
|
|
//#region src/lib/slots.tsx
|
|
/**
|
|
* Shallow equality comparison for objects.
|
|
*/
|
|
function shallowEqual(obj1, obj2) {
|
|
const keys1 = Object.keys(obj1);
|
|
const keys2 = Object.keys(obj2);
|
|
if (keys1.length !== keys2.length) return false;
|
|
for (const key of keys1) if (obj1[key] !== obj2[key]) return false;
|
|
return true;
|
|
}
|
|
/**
|
|
* Check if a value is a React component type (function, class, forwardRef, memo, etc.)
|
|
*/
|
|
function isReactComponentType(value) {
|
|
if (typeof value === "function") return true;
|
|
if (value && typeof value === "object" && "$$typeof" in value && !react.default.isValidElement(value)) return true;
|
|
return false;
|
|
}
|
|
/**
|
|
* Internal function to render a slot value as a React element (non-memoized).
|
|
*/
|
|
function renderSlotElement(slot, DefaultComponent, props) {
|
|
if (typeof slot === "string") {
|
|
const existingClassName = props.className;
|
|
return react.default.createElement(DefaultComponent, {
|
|
...props,
|
|
className: (0, tailwind_merge.twMerge)(existingClassName, slot)
|
|
});
|
|
}
|
|
if (isReactComponentType(slot)) return react.default.createElement(slot, props);
|
|
if (slot && typeof slot === "object" && !react.default.isValidElement(slot)) return react.default.createElement(DefaultComponent, {
|
|
...props,
|
|
...slot
|
|
});
|
|
return react.default.createElement(DefaultComponent, props);
|
|
}
|
|
/**
|
|
* Internal memoized wrapper component for renderSlot.
|
|
* Uses forwardRef to support ref forwarding.
|
|
*/
|
|
const MemoizedSlotWrapper = react.default.memo(react.default.forwardRef(function MemoizedSlotWrapper(props, ref) {
|
|
const { $slot, $component, ...rest } = props;
|
|
return renderSlotElement($slot, $component, ref !== null ? {
|
|
...rest,
|
|
ref
|
|
} : rest);
|
|
}), (prev, next) => {
|
|
if (prev.$slot !== next.$slot) return false;
|
|
if (prev.$component !== next.$component) return false;
|
|
const { $slot: _ps, $component: _pc, ...prevRest } = prev;
|
|
const { $slot: _ns, $component: _nc, ...nextRest } = next;
|
|
return shallowEqual(prevRest, nextRest);
|
|
});
|
|
/**
|
|
* Renders a slot value as a memoized React element.
|
|
* Automatically prevents unnecessary re-renders using shallow prop comparison.
|
|
* Supports ref forwarding.
|
|
*
|
|
* @example
|
|
* renderSlot(customInput, CopilotChatInput, { onSubmit: handleSubmit })
|
|
*/
|
|
function renderSlot(slot, DefaultComponent, props) {
|
|
return react.default.createElement(MemoizedSlotWrapper, {
|
|
...props,
|
|
$slot: slot,
|
|
$component: DefaultComponent
|
|
});
|
|
}
|
|
|
|
//#endregion
|
|
exports.isReactComponentType = isReactComponentType;
|
|
exports.renderSlot = renderSlot;
|
|
//# sourceMappingURL=slots.cjs.map
|