
Company News
Socket Partners with Replit to Block Malicious Packages in AI-Powered Development
Replit is integrating Socket Firewall into its AI-powered development experience to help protect builders from malicious open source packages.
@namelessdev/slots
Advanced tools
Эта библиотека для слотов в ReactJS
Для определение слотов в компоненте используется функция
import * as S from "@namelessdev/slots";
const { SlotOne, SlotTwo, Default } = S.retrive(children, "slot_one", {
name: "slot_two", // Название слота
filter: ..., // Фильтр для того какие элементы могут попасть в слот
overreding: ..., // Перезапись props элементов
})
Она принимает первым аргументом children компонента и неограниченное количество аргументов, которые являются настройкой слотов. Возвращает объект с компонентами слотов с теми же названиями, что и в настройках слотов, только в PascalCase slot_name → SlotName и так же слот Default, это элементы, которые не попали ни в один слот. Название слотов должно быть строго в snake_case. Если вы если вы напишете настройки для слота default, то они будут примениться для элементов, которые не попали ни в один слот.
Настройки слотов могут быть двумя типами.
string - название слота
SlotInfo - настройки слота
type SlotInfo<N extends string> = {
name: N;
filter?: FilterSlot;
overreding?: OverredingSlot;
};
type FilterSlot = (children: React.ReactNode) => boolean;
type OverredingSlot = (
props: Record<string, unknown>,
) => Record<string, unknown>;
Фильтр слота принимает элемент ReactNode и возвращает boolean, если значение равно false, то этот элемент не попадёт в слот в компоненте. В этой функции вы можете всё что угодно, даже можно фильтровать по пропсам при помощи zod. Есть некоторые функции которые упростят фильтрацию, к примеру S.filters.type("h1") пропустить только теги h1
Overreding используется для перезаписи props. Эта функция принимает props элемента и возвращает изменённые props. В библиотеке так же присутствуют функции облегчающие это, к примеру S.overreding.assign(), которая принимает либо объект, либо функцию, которая принимает и возвращает объект, помогает правильно объединить старые и новые props. Так же есть функция S.overreding.fun(), которая принимает функцию из старых props, новую функцию и isSecond?: boolean и помогает правильно объединить функции, чтобы одна функция выполнялась после другой
Есть функция create, которая помогает создать настройки слотов, она принимает название слота и объект с настройками
interface ConfigSlot {
filter?: FilterSlot,
overreding?: OverredingSlot,
}
export const create = <const N extends string>(name: N, config?: ConfigSlot): SlotInfo<N> => ({
name,
filter: config && config.filter,
overreding: config && config.overreding
})
const SlotImage = create("image", {
filter: ...
overreding: ...
})
const SlotTitle = create("title")
После того как вы определили слоты, вы можете использовать их в своей разметке
return (
<div>
<SlotOne />
<section>
<SlotTwo>
Этот текст будет отображатся если этот слот был не передан
</SlotTwo>
</section>
<Default />
<div>
)
Передавать слоты в компонент можно тремя способами
Вы можете использовать атрибут slot чтобы написать название слота в который нужно положить этот элемент
<ComponentWithSlot>
<h1 slot="slot_one">Hello</h1>
<p slot="slot_two">World</p>
Element in Default slot
<ComponentWithSlot>
Вы можете обернуть элементы которые хотите делать частью слота тегом <slot>и дать ему нужное имя. Это полезно, когда частью слота является обычный текст.
<ComponentWithSlot>
<slot name="slot_one">
<h1>Hello</h1>
<p>World</p>
</slot>
<slot name="slot_two">This is Primitive</slot>
Element in Default slot
<ComponentWithSlot>
Вы можете создать компоненты которые будут являться слотами. Для этого используются две функции S.slot и S.wrapper
S.slot создаёт простой компонент который говорит, что дочерние элементы являются элементами слота. Она принимает название слота
import type { Slot } from "@namelessdev/slots";
type ComponentWithSlot = FC<{
children: ReactNode;
}> & {
SlotOne: Slot<"slot_one", /* можно указать тип который должен принимать этот слот */>;
};
ComponentWithSlot.SlotOne = S.slot("slot_one")
<ComponentWithSlot>
<ComponentWithSlot.SlotOne>
Hello
<ComponentWithSlot.SlotOne>
<ComponentWithSlot>
S.wrapper создаёт компонент обёртку. Если в слоте вам нужна только картинка, то вы можете создать компонент обёртку которая не только скажет, что это слот, но и будет принимать все props компонента Image или любово другова, который вы ему передадите
import type { Wrapper } from "@namelessdev/slots";
type ComponentWithSlot = FC<{
children: ReactNode;
}> & {
Image: Wrapper<"image", typeof LazyLoadImage, /* можно указать тип который должен принимать этот слот */>;
};
ComponentWithSlot.Image = S.wrapper("image", LazyLoadImage);
<ComponentWithSlot.Image src="link/to/image.png" alt="" />
const element =
(filter: (node: ReactElement) => boolean): FilterSlot =>
(child) =>
isValidElement(child) && filter(child);
const type =
(type: string | FC): FilterSlot =>
(child) =>
// @ts-ignore
isValidElement(child) && (child.type === type | child.type.element === type);
const primitive: FilterSlot = (child) => !isValidElement(child);
const props =
(props: string): FilterSlot =>
(child) =>
isValidElement(child) && child.props.hasOwnProperty(props);
const hasChildren: FilterSlot = (child) =>
isValidElement(child) && Boolean(React.Children.count(child.props.children));
const hasEvent = (eventName: string) => (child: ReactNode) =>
isValidElement(child) && typeof child.props[eventName] === "function";
const and =
(...filters: FilterSlot[]): FilterSlot =>
(child) =>
filters.reduce((result, filter) => {
if (!result) return result;
return result && filter(child);
}, true);
const or =
(...filters: FilterSlot[]): FilterSlot =>
(child) =>
filters.reduce((result, filter) => {
return result || filter(child);
}, true);
const string = (props: unknown, newprops: string) =>
typeof props === "string" ? `${props} ${newprops}` : newprops;
const fun = (props: unknown, newprops: Function, isSecond?: boolean) =>
typeof props === "function"
? () => {
if (isSecond) {
props && props();
newprops();
} else {
newprops();
props && props();
}
}
: newprops;
const assign =
<T extends Record<string, unknown>>(args: (props: T) => T | T) =>
(props: T) =>
Object.assign({}, props, typeof args === "function" ? args(props) : args);
import * as S from "@namelessdev/slots";
import type { Slot, Wrapper } from "@namelessdev/slots";
export const SlotImage = S.create("image", {
filter: F.type(LazyLoadImage),
overreding: O.assign(props => ({
className: O.string(props.className, "bject-cover w-full rounded-t-lg h-96 md:h-auto md:w-48 md:rounded-none md:rounded-s-lg")
})),
})
export const SlotDefault = S.create("default", {
overreding: O.assign(props => ({
className: O.string(props.className, "mb-3 font-normal text-gray-700 dark:text-gray-400")
})),
})
export const SlotTitle = S.create("title")
type ButtonComponent = FC<{
children: ReactNode;
}> & {
Title: Slot<"title">;
Image: Wrapper<"image", typeof LazyLoadImage>;
};
export const Card: ButtonComponent = ({ children }) => {
const { Default, Title, Image } = S.retrive(
children,
SlotTitle,
SlotImage,
SlotDefault,
);
return (
<a
href="#"
className="flex flex-col items-center bg-white border border-gray-200 rounded-lg shadow md:flex-row md:max-w-xl hover:bg-gray-100 dark:border-gray-700 dark:bg-gray-800 dark:hover:bg-gray-700"
>
<Image />
<div className="flex flex-col justify-between p-4 leading-normal">
<h5 className="mb-2 text-2xl font-bold tracking-tight text-gray-900 dark:text-white">
<Title />
</h5>
<Default />
</div>
</a>
);
};
Card.Title = S.slot("title");
Card.Image = S.wrapper("image", LazyLoadImage);
FAQs
This library is for slots in ReactJS
The npm package @namelessdev/slots receives a total of 19 weekly downloads. As such, @namelessdev/slots popularity was classified as not popular.
We found that @namelessdev/slots demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Company News
Replit is integrating Socket Firewall into its AI-powered development experience to help protect builders from malicious open source packages.

Security News
npm confirmed a tooling bug incorrectly marked several one-character packages as security holders and said it was working on a rollback.

Research
/Security News
Newer packages in this compromise use native extensions and .pth loaders to execute JavaScript stealers in developer environments.