@brandlab-digital/site-next 3.7.0 → 3.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/instrumentation-client.d.ts +23 -4
- package/dist/instrumentation-client.d.ts.map +1 -1
- package/dist/instrumentation-client.js +65 -3
- package/dist/instrumentation-client.js.map +1 -1
- package/dist/navigation/constants.d.ts +25 -0
- package/dist/navigation/constants.d.ts.map +1 -0
- package/dist/navigation/constants.js +30 -0
- package/dist/navigation/constants.js.map +1 -0
- package/dist/navigation/index.d.ts +11 -0
- package/dist/navigation/index.d.ts.map +1 -0
- package/dist/navigation/index.js +11 -0
- package/dist/navigation/index.js.map +1 -0
- package/dist/navigation/use-back-to-top.d.ts +5 -0
- package/dist/navigation/use-back-to-top.d.ts.map +1 -0
- package/dist/navigation/use-back-to-top.js +32 -0
- package/dist/navigation/use-back-to-top.js.map +1 -0
- package/dist/navigation/use-header-metrics.d.ts +17 -0
- package/dist/navigation/use-header-metrics.d.ts.map +1 -0
- package/dist/navigation/use-header-metrics.js +52 -0
- package/dist/navigation/use-header-metrics.js.map +1 -0
- package/dist/navigation/use-navigation-menu.d.ts +39 -0
- package/dist/navigation/use-navigation-menu.d.ts.map +1 -0
- package/dist/navigation/use-navigation-menu.js +206 -0
- package/dist/navigation/use-navigation-menu.js.map +1 -0
- package/dist/navigation/use-sticky-call-bar.d.ts +15 -0
- package/dist/navigation/use-sticky-call-bar.d.ts.map +1 -0
- package/dist/navigation/use-sticky-call-bar.js +110 -0
- package/dist/navigation/use-sticky-call-bar.js.map +1 -0
- package/dist/ui-kit/brandlab-skin.d.ts +27 -0
- package/dist/ui-kit/brandlab-skin.d.ts.map +1 -0
- package/dist/ui-kit/brandlab-skin.js +2 -0
- package/dist/ui-kit/brandlab-skin.js.map +1 -0
- package/dist/ui-kit/icons.d.ts +15 -0
- package/dist/ui-kit/icons.d.ts.map +1 -0
- package/dist/ui-kit/icons.js +72 -0
- package/dist/ui-kit/icons.js.map +1 -0
- package/dist/ui-kit/primitives/index.d.ts +6 -0
- package/dist/ui-kit/primitives/index.d.ts.map +1 -0
- package/dist/ui-kit/primitives/index.js +6 -0
- package/dist/ui-kit/primitives/index.js.map +1 -0
- package/dist/ui-kit/primitives/layout.d.ts +73 -0
- package/dist/ui-kit/primitives/layout.d.ts.map +1 -0
- package/dist/ui-kit/primitives/layout.js +34 -0
- package/dist/ui-kit/primitives/layout.js.map +1 -0
- package/dist/ui-kit/primitives/links.d.ts +48 -0
- package/dist/ui-kit/primitives/links.d.ts.map +1 -0
- package/dist/ui-kit/primitives/links.js +36 -0
- package/dist/ui-kit/primitives/links.js.map +1 -0
- package/dist/ui-kit/primitives/quote-button.d.ts +20 -0
- package/dist/ui-kit/primitives/quote-button.d.ts.map +1 -0
- package/dist/ui-kit/primitives/quote-button.js +15 -0
- package/dist/ui-kit/primitives/quote-button.js.map +1 -0
- package/dist/ui-kit/shell/back-to-top-client.d.ts +9 -0
- package/dist/ui-kit/shell/back-to-top-client.d.ts.map +1 -0
- package/dist/ui-kit/shell/back-to-top-client.js +8 -0
- package/dist/ui-kit/shell/back-to-top-client.js.map +1 -0
- package/dist/ui-kit/shell/back-to-top.d.ts +13 -0
- package/dist/ui-kit/shell/back-to-top.d.ts.map +1 -0
- package/dist/ui-kit/shell/back-to-top.js +14 -0
- package/dist/ui-kit/shell/back-to-top.js.map +1 -0
- package/dist/ui-kit/shell/call-bar-client.d.ts +7 -0
- package/dist/ui-kit/shell/call-bar-client.d.ts.map +1 -0
- package/dist/ui-kit/shell/call-bar-client.js +13 -0
- package/dist/ui-kit/shell/call-bar-client.js.map +1 -0
- package/dist/ui-kit/shell/current-link.d.ts +15 -0
- package/dist/ui-kit/shell/current-link.d.ts.map +1 -0
- package/dist/ui-kit/shell/current-link.js +34 -0
- package/dist/ui-kit/shell/current-link.js.map +1 -0
- package/dist/ui-kit/shell/drawer-client.d.ts +22 -0
- package/dist/ui-kit/shell/drawer-client.d.ts.map +1 -0
- package/dist/ui-kit/shell/drawer-client.js +70 -0
- package/dist/ui-kit/shell/drawer-client.js.map +1 -0
- package/dist/ui-kit/shell/header-client.d.ts +44 -0
- package/dist/ui-kit/shell/header-client.d.ts.map +1 -0
- package/dist/ui-kit/shell/header-client.js +59 -0
- package/dist/ui-kit/shell/header-client.js.map +1 -0
- package/dist/ui-kit/shell/index.d.ts +6 -0
- package/dist/ui-kit/shell/index.d.ts.map +1 -0
- package/dist/ui-kit/shell/index.js +6 -0
- package/dist/ui-kit/shell/index.js.map +1 -0
- package/dist/ui-kit/shell/mobile-call-bar.d.ts +16 -0
- package/dist/ui-kit/shell/mobile-call-bar.d.ts.map +1 -0
- package/dist/ui-kit/shell/mobile-call-bar.js +15 -0
- package/dist/ui-kit/shell/mobile-call-bar.js.map +1 -0
- package/dist/ui-kit/shell/mobile-drawer.d.ts +37 -0
- package/dist/ui-kit/shell/mobile-drawer.d.ts.map +1 -0
- package/dist/ui-kit/shell/mobile-drawer.js +25 -0
- package/dist/ui-kit/shell/mobile-drawer.js.map +1 -0
- package/dist/ui-kit/shell/shell-context.d.ts +3 -0
- package/dist/ui-kit/shell/shell-context.d.ts.map +1 -0
- package/dist/ui-kit/shell/shell-context.js +5 -0
- package/dist/ui-kit/shell/shell-context.js.map +1 -0
- package/dist/ui-kit/shell/site-header.d.ts +52 -0
- package/dist/ui-kit/shell/site-header.d.ts.map +1 -0
- package/dist/ui-kit/shell/site-header.js +36 -0
- package/dist/ui-kit/shell/site-header.js.map +1 -0
- package/dist/ui-kit/shell/social-links.d.ts +8 -0
- package/dist/ui-kit/shell/social-links.d.ts.map +1 -0
- package/dist/ui-kit/shell/social-links.js +9 -0
- package/dist/ui-kit/shell/social-links.js.map +1 -0
- package/dist/ui-kit/shell/utility-bar.d.ts +30 -0
- package/dist/ui-kit/shell/utility-bar.d.ts.map +1 -0
- package/dist/ui-kit/shell/utility-bar.js +15 -0
- package/dist/ui-kit/shell/utility-bar.js.map +1 -0
- package/dist/ui-kit/skin-index.d.ts +3 -0
- package/dist/ui-kit/skin-index.d.ts.map +1 -0
- package/dist/ui-kit/skin-index.js +2 -0
- package/dist/ui-kit/skin-index.js.map +1 -0
- package/dist/ui-kit/skin.d.ts +48 -0
- package/dist/ui-kit/skin.d.ts.map +1 -0
- package/dist/ui-kit/skin.js +47 -0
- package/dist/ui-kit/skin.js.map +1 -0
- package/dist/ui-kit/structure.css +717 -0
- package/dist/ui-kit/types.d.ts +27 -0
- package/dist/ui-kit/types.d.ts.map +1 -0
- package/dist/ui-kit/types.js +6 -0
- package/dist/ui-kit/types.js.map +1 -0
- package/package.json +25 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skin-index.d.ts","sourceRoot":"","sources":["../../src/ui-kit/skin-index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,SAAS,EAAE,KAAK,WAAW,EAAE,KAAK,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAA;AACpH,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skin-index.js","sourceRoot":"","sources":["../../src/ui-kit/skin-index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAyE,MAAM,WAAW,CAAA","sourcesContent":["export { cx, skinned, slot, type SkinEntry, type SkinEntryOf, type SkinnedProps, type SlotClasses } from './skin.js'\nexport type { BrandlabSkin } from './brandlab-skin.js'\n"]}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The skin model of the Brandlab ui-kit. A site gives every shared component its own look through one skin entry per
|
|
3
|
+
* component: a variant from the component's closed list, typed layout options and one class string per named slot.
|
|
4
|
+
* Colours, fonts and shapes come from the site's `--bl-*` tokens and these classes; behaviour, semantics, accessible
|
|
5
|
+
* names and analytics hooks never appear here, so a skin can't change them.
|
|
6
|
+
*/
|
|
7
|
+
import { type ComponentType } from 'react';
|
|
8
|
+
/** One class string per named slot. Tailwind v4 utilities, CSS Module class names or nothing (plain CSS on hooks). */
|
|
9
|
+
export type SlotClasses<Slot extends string> = Readonly<Partial<Record<Slot, string>>>;
|
|
10
|
+
/** A component's skin: its variant, its layout options and its slot classes. Every field is optional. */
|
|
11
|
+
export interface SkinEntry<Slot extends string, Variant extends string = never, Layout extends object = Record<never, never>> {
|
|
12
|
+
readonly variant?: Variant;
|
|
13
|
+
readonly layout?: Readonly<Layout>;
|
|
14
|
+
readonly classes?: SlotClasses<Slot>;
|
|
15
|
+
}
|
|
16
|
+
type SkinKeys = 'variant' | 'layout' | 'classes';
|
|
17
|
+
/** The part of a component's props a skin entry supplies. */
|
|
18
|
+
export type SkinEntryOf<P> = Pick<P, Extract<keyof P, SkinKeys>>;
|
|
19
|
+
/** What a page passes to a skinned component: its data, and at most a `layout` adjustment within the contract. */
|
|
20
|
+
export type SkinnedProps<P> = Omit<P, 'variant' | 'classes'>;
|
|
21
|
+
/**
|
|
22
|
+
* Bind a component to the site's skin entry, so pages pass data only. Returns a plain function component (no
|
|
23
|
+
* context, no client code), so it works in server components and client components alike. The skin's layout merges
|
|
24
|
+
* under the page's `layout`; the variant and classes come from the skin only.
|
|
25
|
+
*
|
|
26
|
+
* ```tsx
|
|
27
|
+
* // src/site/ui.tsx
|
|
28
|
+
* export const ReviewsBand = skinned(UI.ReviewsBand, skin.reviewsBand)
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export declare function skinned<P extends {
|
|
32
|
+
variant?: unknown;
|
|
33
|
+
layout?: object;
|
|
34
|
+
classes?: object;
|
|
35
|
+
}>(Component: ComponentType<P>, entry: SkinEntryOf<P>): ComponentType<SkinnedProps<P>>;
|
|
36
|
+
/** Join class strings, dropping empty parts. Returns `undefined` when nothing is left, so no empty `class` renders. */
|
|
37
|
+
export declare function cx(...parts: readonly (string | false | null | undefined)[]): string | undefined;
|
|
38
|
+
/**
|
|
39
|
+
* The stable hook for one named part: `data-slot` plus the skin's class for it. Spread it onto the element:
|
|
40
|
+
* `<div {...slot(classes, 'inner')}>`. Slot names, nesting and element types are public API (a minor release to
|
|
41
|
+
* change); a skin's class never replaces the hook.
|
|
42
|
+
*/
|
|
43
|
+
export declare function slot<Slot extends string>(classes: SlotClasses<Slot> | undefined, name: Slot, extra?: string): {
|
|
44
|
+
'data-slot': Slot;
|
|
45
|
+
className: string | undefined;
|
|
46
|
+
};
|
|
47
|
+
export {};
|
|
48
|
+
//# sourceMappingURL=skin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skin.d.ts","sourceRoot":"","sources":["../../src/ui-kit/skin.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAiB,KAAK,aAAa,EAAkB,MAAM,OAAO,CAAA;AAEzE,sHAAsH;AACtH,MAAM,MAAM,WAAW,CAAC,IAAI,SAAS,MAAM,IAAI,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAA;AAEtF,yGAAyG;AACzG,MAAM,WAAW,SAAS,CACxB,IAAI,SAAS,MAAM,EACnB,OAAO,SAAS,MAAM,GAAG,KAAK,EAC9B,MAAM,SAAS,MAAM,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC;IAE5C,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAA;IAClC,QAAQ,CAAC,OAAO,CAAC,EAAE,WAAW,CAAC,IAAI,CAAC,CAAA;CACrC;AAED,KAAK,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAA;AAEhD,6DAA6D;AAC7D,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAA;AAEhE,kHAAkH;AAClH,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC,CAAA;AAE5D;;;;;;;;;GASG;AACH,wBAAgB,OAAO,CAAC,CAAC,SAAS;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,EACxF,SAAS,EAAE,aAAa,CAAC,CAAC,CAAC,EAC3B,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,GACpB,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAehC;AAED,uHAAuH;AACvH,wBAAgB,EAAE,CAAC,GAAG,KAAK,EAAE,SAAS,CAAC,MAAM,GAAG,KAAK,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,GAAG,MAAM,GAAG,SAAS,CAG/F;AAED;;;;GAIG;AACH,wBAAgB,IAAI,CAAC,IAAI,SAAS,MAAM,EACtC,OAAO,EAAE,WAAW,CAAC,IAAI,CAAC,GAAG,SAAS,EACtC,IAAI,EAAE,IAAI,EACV,KAAK,CAAC,EAAE,MAAM,GACb;IAAE,WAAW,EAAE,IAAI,CAAC;IAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAEtD"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The skin model of the Brandlab ui-kit. A site gives every shared component its own look through one skin entry per
|
|
3
|
+
* component: a variant from the component's closed list, typed layout options and one class string per named slot.
|
|
4
|
+
* Colours, fonts and shapes come from the site's `--bl-*` tokens and these classes; behaviour, semantics, accessible
|
|
5
|
+
* names and analytics hooks never appear here, so a skin can't change them.
|
|
6
|
+
*/
|
|
7
|
+
import { createElement } from 'react';
|
|
8
|
+
/**
|
|
9
|
+
* Bind a component to the site's skin entry, so pages pass data only. Returns a plain function component (no
|
|
10
|
+
* context, no client code), so it works in server components and client components alike. The skin's layout merges
|
|
11
|
+
* under the page's `layout`; the variant and classes come from the skin only.
|
|
12
|
+
*
|
|
13
|
+
* ```tsx
|
|
14
|
+
* // src/site/ui.tsx
|
|
15
|
+
* export const ReviewsBand = skinned(UI.ReviewsBand, skin.reviewsBand)
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export function skinned(Component, entry) {
|
|
19
|
+
const skin = entry;
|
|
20
|
+
function Skinned(props) {
|
|
21
|
+
const pageLayout = props.layout;
|
|
22
|
+
const layout = skin.layout || pageLayout ? { ...(skin.layout ?? {}), ...(pageLayout ?? {}) } : undefined;
|
|
23
|
+
const merged = {
|
|
24
|
+
...props,
|
|
25
|
+
...(skin.variant !== undefined ? { variant: skin.variant } : {}),
|
|
26
|
+
...(layout ? { layout } : {}),
|
|
27
|
+
...(skin.classes ? { classes: skin.classes } : {}),
|
|
28
|
+
};
|
|
29
|
+
return createElement(Component, merged);
|
|
30
|
+
}
|
|
31
|
+
Skinned.displayName = `Skinned(${Component.displayName ?? Component.name ?? 'Component'})`;
|
|
32
|
+
return Skinned;
|
|
33
|
+
}
|
|
34
|
+
/** Join class strings, dropping empty parts. Returns `undefined` when nothing is left, so no empty `class` renders. */
|
|
35
|
+
export function cx(...parts) {
|
|
36
|
+
const joined = parts.filter(Boolean).join(' ');
|
|
37
|
+
return joined === '' ? undefined : joined;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* The stable hook for one named part: `data-slot` plus the skin's class for it. Spread it onto the element:
|
|
41
|
+
* `<div {...slot(classes, 'inner')}>`. Slot names, nesting and element types are public API (a minor release to
|
|
42
|
+
* change); a skin's class never replaces the hook.
|
|
43
|
+
*/
|
|
44
|
+
export function slot(classes, name, extra) {
|
|
45
|
+
return { 'data-slot': name, className: cx(classes?.[name], extra) };
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=skin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skin.js","sourceRoot":"","sources":["../../src/ui-kit/skin.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,aAAa,EAAsC,MAAM,OAAO,CAAA;AAwBzE;;;;;;;;;GASG;AACH,MAAM,UAAU,OAAO,CACrB,SAA2B,EAC3B,KAAqB;IAErB,MAAM,IAAI,GAAG,KAAiE,CAAA;IAC9E,SAAS,OAAO,CAAC,KAAsB;QACrC,MAAM,UAAU,GAAI,KAA6B,CAAC,MAAM,CAAA;QACxD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,UAAU,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,UAAU,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAA;QACxG,MAAM,MAAM,GAAG;YACb,GAAG,KAAK;YACR,GAAG,CAAC,IAAI,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAChE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC7B,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACnC,CAAA;QACjB,OAAO,aAAa,CAAC,SAAS,EAAE,MAAM,CAAC,CAAA;IACzC,CAAC;IACD,OAAO,CAAC,WAAW,GAAG,WAAW,SAAS,CAAC,WAAW,IAAI,SAAS,CAAC,IAAI,IAAI,WAAW,GAAG,CAAA;IAC1F,OAAO,OAAO,CAAA;AAChB,CAAC;AAED,uHAAuH;AACvH,MAAM,UAAU,EAAE,CAAC,GAAG,KAAqD;IACzE,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAC9C,OAAO,MAAM,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAA;AAC3C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,IAAI,CAClB,OAAsC,EACtC,IAAU,EACV,KAAc;IAEd,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,EAAE,CAAA;AACrE,CAAC","sourcesContent":["/**\n * The skin model of the Brandlab ui-kit. A site gives every shared component its own look through one skin entry per\n * component: a variant from the component's closed list, typed layout options and one class string per named slot.\n * Colours, fonts and shapes come from the site's `--bl-*` tokens and these classes; behaviour, semantics, accessible\n * names and analytics hooks never appear here, so a skin can't change them.\n */\nimport { createElement, type ComponentType, type ReactNode } from 'react'\n\n/** One class string per named slot. Tailwind v4 utilities, CSS Module class names or nothing (plain CSS on hooks). */\nexport type SlotClasses<Slot extends string> = Readonly<Partial<Record<Slot, string>>>\n\n/** A component's skin: its variant, its layout options and its slot classes. Every field is optional. */\nexport interface SkinEntry<\n Slot extends string,\n Variant extends string = never,\n Layout extends object = Record<never, never>,\n> {\n readonly variant?: Variant\n readonly layout?: Readonly<Layout>\n readonly classes?: SlotClasses<Slot>\n}\n\ntype SkinKeys = 'variant' | 'layout' | 'classes'\n\n/** The part of a component's props a skin entry supplies. */\nexport type SkinEntryOf<P> = Pick<P, Extract<keyof P, SkinKeys>>\n\n/** What a page passes to a skinned component: its data, and at most a `layout` adjustment within the contract. */\nexport type SkinnedProps<P> = Omit<P, 'variant' | 'classes'>\n\n/**\n * Bind a component to the site's skin entry, so pages pass data only. Returns a plain function component (no\n * context, no client code), so it works in server components and client components alike. The skin's layout merges\n * under the page's `layout`; the variant and classes come from the skin only.\n *\n * ```tsx\n * // src/site/ui.tsx\n * export const ReviewsBand = skinned(UI.ReviewsBand, skin.reviewsBand)\n * ```\n */\nexport function skinned<P extends { variant?: unknown; layout?: object; classes?: object }>(\n Component: ComponentType<P>,\n entry: SkinEntryOf<P>,\n): ComponentType<SkinnedProps<P>> {\n const skin = entry as { variant?: unknown; layout?: object; classes?: object }\n function Skinned(props: SkinnedProps<P>): ReactNode {\n const pageLayout = (props as { layout?: object }).layout\n const layout = skin.layout || pageLayout ? { ...(skin.layout ?? {}), ...(pageLayout ?? {}) } : undefined\n const merged = {\n ...props,\n ...(skin.variant !== undefined ? { variant: skin.variant } : {}),\n ...(layout ? { layout } : {}),\n ...(skin.classes ? { classes: skin.classes } : {}),\n } as unknown as P\n return createElement(Component, merged)\n }\n Skinned.displayName = `Skinned(${Component.displayName ?? Component.name ?? 'Component'})`\n return Skinned\n}\n\n/** Join class strings, dropping empty parts. Returns `undefined` when nothing is left, so no empty `class` renders. */\nexport function cx(...parts: readonly (string | false | null | undefined)[]): string | undefined {\n const joined = parts.filter(Boolean).join(' ')\n return joined === '' ? undefined : joined\n}\n\n/**\n * The stable hook for one named part: `data-slot` plus the skin's class for it. Spread it onto the element:\n * `<div {...slot(classes, 'inner')}>`. Slot names, nesting and element types are public API (a minor release to\n * change); a skin's class never replaces the hook.\n */\nexport function slot<Slot extends string>(\n classes: SlotClasses<Slot> | undefined,\n name: Slot,\n extra?: string,\n): { 'data-slot': Slot; className: string | undefined } {\n return { 'data-slot': name, className: cx(classes?.[name], extra) }\n}\n"]}
|