@krizaka/ui 3.9.0 → 3.10.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/README.md +3 -1
- package/dist/chunk-HG65YAV4.js +379 -0
- package/dist/chunk-HG65YAV4.js.map +1 -0
- package/dist/chunk-OT6HX3PN.js +85 -0
- package/dist/chunk-OT6HX3PN.js.map +1 -0
- package/dist/index.js +9 -367
- package/dist/index.js.map +1 -1
- package/dist/native.d.ts +48 -1
- package/dist/native.js +374 -257
- package/dist/native.js.map +1 -1
- package/dist/nav-bar.d.ts +86 -3
- package/dist/nav-bar.js +88 -2
- package/dist/nav-bar.js.map +1 -1
- package/dist/showcase.d.ts +69 -0
- package/dist/showcase.js +218 -0
- package/dist/showcase.js.map +1 -0
- package/dist/site-footer.d.ts +172 -0
- package/dist/site-footer.js +105 -0
- package/dist/site-footer.js.map +1 -0
- package/dist/sites-CgJrxejx.d.ts +32 -0
- package/dist/sites.d.ts +64 -0
- package/dist/sites.js +69 -0
- package/dist/sites.js.map +1 -0
- package/package.json +44 -6
- package/registry/achievement.json +1 -1
- package/registry/action-bar.json +1 -1
- package/registry/activity-feed.json +1 -1
- package/registry/alert.json +1 -1
- package/registry/app-shell.json +1 -1
- package/registry/argument-card.json +1 -1
- package/registry/audio-player.json +1 -1
- package/registry/auth-layout.json +1 -1
- package/registry/avatar.json +1 -1
- package/registry/badge.json +1 -1
- package/registry/button.json +1 -1
- package/registry/card-grid.json +1 -1
- package/registry/card.json +1 -1
- package/registry/catalogue-page.json +1 -1
- package/registry/changelog-page.json +1 -1
- package/registry/chat.json +1 -1
- package/registry/checkbox.json +1 -1
- package/registry/chip-link.json +1 -1
- package/registry/chip.json +1 -1
- package/registry/choice-grid.json +1 -1
- package/registry/code-block.json +1 -1
- package/registry/combobox.json +1 -1
- package/registry/command.json +1 -1
- package/registry/component-page.json +1 -1
- package/registry/confirm-button.json +1 -1
- package/registry/contact-page.json +1 -1
- package/registry/continue-prompt.json +1 -1
- package/registry/countdown.json +1 -1
- package/registry/cta-panel.json +1 -1
- package/registry/dashboard-layout.json +1 -1
- package/registry/data-table.json +1 -1
- package/registry/date-picker.json +1 -1
- package/registry/decision-list.json +1 -1
- package/registry/description-list.json +1 -1
- package/registry/detail-layout.json +1 -1
- package/registry/dialog.json +1 -1
- package/registry/docs-article-page.json +1 -1
- package/registry/docs-hub-page.json +1 -1
- package/registry/docs-layout.json +1 -1
- package/registry/dropdown-menu.json +1 -1
- package/registry/empty-state.json +1 -1
- package/registry/error-page.json +1 -1
- package/registry/examples/nav-bar/family-admin.d.ts +4 -0
- package/registry/examples/nav-bar/family-admin.js +21 -0
- package/registry/examples/nav-bar/family-admin.tsx +20 -0
- package/registry/examples/nav-bar/family-java.d.ts +4 -0
- package/registry/examples/nav-bar/family-java.js +33 -0
- package/registry/examples/nav-bar/family-java.tsx +34 -0
- package/registry/examples/nav-bar/family-product.d.ts +4 -0
- package/registry/examples/nav-bar/family-product.js +35 -0
- package/registry/examples/nav-bar/family-product.tsx +39 -0
- package/registry/examples/nav-bar/family-ui.d.ts +4 -0
- package/registry/examples/nav-bar/family-ui.js +34 -0
- package/registry/examples/nav-bar/family-ui.tsx +35 -0
- package/registry/examples/nav-bar/family-www.d.ts +4 -0
- package/registry/examples/nav-bar/family-www.js +34 -0
- package/registry/examples/nav-bar/family-www.tsx +36 -0
- package/registry/examples/showcase/native/slides.d.ts +4 -0
- package/registry/examples/showcase/native/slides.dark.png +0 -0
- package/registry/examples/showcase/native/slides.js +27 -0
- package/registry/examples/showcase/native/slides.light.png +0 -0
- package/registry/examples/showcase/native/slides.tsx +28 -0
- package/registry/examples/showcase/prompt-image.d.ts +4 -0
- package/registry/examples/showcase/prompt-image.js +29 -0
- package/registry/examples/showcase/prompt-image.tsx +28 -0
- package/registry/examples/showcase/slides.d.ts +4 -0
- package/registry/examples/showcase/slides.js +29 -0
- package/registry/examples/showcase/slides.tsx +24 -0
- package/registry/examples/site-footer/company.d.ts +4 -0
- package/registry/examples/site-footer/company.js +26 -0
- package/registry/examples/site-footer/company.tsx +23 -0
- package/registry/examples/site-footer/open-source-fr.d.ts +4 -0
- package/registry/examples/site-footer/open-source-fr.js +17 -0
- package/registry/examples/site-footer/open-source-fr.tsx +17 -0
- package/registry/examples/site-footer/product.d.ts +4 -0
- package/registry/examples/site-footer/product.js +22 -0
- package/registry/examples/site-footer/product.tsx +19 -0
- package/registry/examples/sites/family.d.ts +4 -0
- package/registry/examples/sites/family.js +20 -0
- package/registry/examples/sites/family.tsx +30 -0
- package/registry/examples/sites/french.d.ts +4 -0
- package/registry/examples/sites/french.js +25 -0
- package/registry/examples/sites/french.tsx +25 -0
- package/registry/field.json +1 -1
- package/registry/file-upload.json +1 -1
- package/registry/filter-bar.json +1 -1
- package/registry/form.json +1 -1
- package/registry/gallery-page.json +1 -1
- package/registry/glow-card.json +1 -1
- package/registry/goal-gauge.json +1 -1
- package/registry/how-it-works-page.json +1 -1
- package/registry/image-cropper.json +1 -1
- package/registry/index.json +64 -6
- package/registry/iso.json +1 -1
- package/registry/kanban.json +1 -1
- package/registry/kbd.json +1 -1
- package/registry/landing-page.json +1 -1
- package/registry/landscape.json +1 -1
- package/registry/legal-page.json +1 -1
- package/registry/link-card.json +1 -1
- package/registry/list.json +1 -1
- package/registry/loader.json +1 -1
- package/registry/longform-page.json +1 -1
- package/registry/map.json +2 -2
- package/registry/markdown.json +1 -1
- package/registry/marketing-layout.json +1 -1
- package/registry/marquee.json +1 -1
- package/registry/mascot-quote.json +1 -1
- package/registry/mascot-state.json +1 -1
- package/registry/mascots.json +1 -1
- package/registry/match-dialog.json +1 -1
- package/registry/media-capture.json +1 -1
- package/registry/meter.json +1 -1
- package/registry/nav-bar.json +257 -13
- package/registry/number-ticker.json +1 -1
- package/registry/page-header.json +1 -1
- package/registry/page-hero.json +1 -1
- package/registry/page.json +1 -1
- package/registry/pagination.json +1 -1
- package/registry/photo-grid.json +1 -1
- package/registry/pointer-light.json +1 -1
- package/registry/popover.json +1 -1
- package/registry/pricing-page.json +1 -1
- package/registry/product-page.json +1 -1
- package/registry/profile-card.json +1 -1
- package/registry/progress.json +1 -1
- package/registry/promise-card.json +1 -1
- package/registry/radio-group.json +1 -1
- package/registry/recipes.json +1 -1
- package/registry/scroll-stage.json +1 -1
- package/registry/search-field.json +1 -1
- package/registry/section-backdrop.json +1 -1
- package/registry/separator.json +1 -1
- package/registry/settings-layout.json +1 -1
- package/registry/showcase.json +421 -0
- package/registry/site-footer.json +389 -0
- package/registry/sites.json +93 -0
- package/registry/skeleton.json +1 -1
- package/registry/skip-link.json +1 -1
- package/registry/slider.json +1 -1
- package/registry/slot.json +1 -1
- package/registry/spinner.json +1 -1
- package/registry/split-view.json +1 -1
- package/registry/stage-banner.json +1 -1
- package/registry/stat.json +1 -1
- package/registry/status-page.json +1 -1
- package/registry/step-progress.json +1 -1
- package/registry/stepper.json +1 -1
- package/registry/swipe-deck.json +1 -1
- package/registry/switch.json +1 -1
- package/registry/tabs.json +1 -1
- package/registry/tag-input.json +1 -1
- package/registry/tag-selector.json +1 -1
- package/registry/terminal-replay.json +1 -1
- package/registry/theme.json +1 -1
- package/registry/toast.json +1 -1
- package/registry/toc.json +1 -1
- package/registry/tooltip.json +1 -1
- package/registry/tree-view.json +1 -1
- package/registry/verified-badge.json +1 -1
- package/registry/vertical-video.json +1 -1
- package/registry/video-player.json +1 -1
- package/registry/video-trimmer.json +1 -1
- package/registry/virtual.json +1 -1
package/dist/nav-bar.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as tailwind_variants from 'tailwind-variants';
|
|
2
2
|
import { NavigationMenu } from 'radix-ui';
|
|
3
3
|
import * as React from 'react';
|
|
4
|
+
import { S as SiteId, F as FamilyLabels } from './sites-CgJrxejx.js';
|
|
4
5
|
|
|
5
6
|
declare const navBar: tailwind_variants.TVReturnType<{
|
|
6
7
|
floating: {
|
|
@@ -28,6 +29,20 @@ declare const navBar: tailwind_variants.TVReturnType<{
|
|
|
28
29
|
toggle: string;
|
|
29
30
|
mobile: string;
|
|
30
31
|
mobileLink: string;
|
|
32
|
+
family: string;
|
|
33
|
+
familyTrigger: string;
|
|
34
|
+
familyViewport: string;
|
|
35
|
+
familyPanel: string;
|
|
36
|
+
familyGroupTitle: string;
|
|
37
|
+
familyLink: string;
|
|
38
|
+
familyMark: string;
|
|
39
|
+
familyName: string;
|
|
40
|
+
familyText: string;
|
|
41
|
+
familyTag: string;
|
|
42
|
+
mobileFamily: string;
|
|
43
|
+
mobileFamilyLink: string;
|
|
44
|
+
badge: string;
|
|
45
|
+
repo: string;
|
|
31
46
|
}, undefined, {
|
|
32
47
|
floating: {
|
|
33
48
|
true: {
|
|
@@ -54,6 +69,20 @@ declare const navBar: tailwind_variants.TVReturnType<{
|
|
|
54
69
|
toggle: string;
|
|
55
70
|
mobile: string;
|
|
56
71
|
mobileLink: string;
|
|
72
|
+
family: string;
|
|
73
|
+
familyTrigger: string;
|
|
74
|
+
familyViewport: string;
|
|
75
|
+
familyPanel: string;
|
|
76
|
+
familyGroupTitle: string;
|
|
77
|
+
familyLink: string;
|
|
78
|
+
familyMark: string;
|
|
79
|
+
familyName: string;
|
|
80
|
+
familyText: string;
|
|
81
|
+
familyTag: string;
|
|
82
|
+
mobileFamily: string;
|
|
83
|
+
mobileFamilyLink: string;
|
|
84
|
+
badge: string;
|
|
85
|
+
repo: string;
|
|
57
86
|
}, tailwind_variants.TVReturnTypeLike<{
|
|
58
87
|
floating: {
|
|
59
88
|
true: {
|
|
@@ -80,6 +109,20 @@ declare const navBar: tailwind_variants.TVReturnType<{
|
|
|
80
109
|
toggle: string;
|
|
81
110
|
mobile: string;
|
|
82
111
|
mobileLink: string;
|
|
112
|
+
family: string;
|
|
113
|
+
familyTrigger: string;
|
|
114
|
+
familyViewport: string;
|
|
115
|
+
familyPanel: string;
|
|
116
|
+
familyGroupTitle: string;
|
|
117
|
+
familyLink: string;
|
|
118
|
+
familyMark: string;
|
|
119
|
+
familyName: string;
|
|
120
|
+
familyText: string;
|
|
121
|
+
familyTag: string;
|
|
122
|
+
mobileFamily: string;
|
|
123
|
+
mobileFamilyLink: string;
|
|
124
|
+
badge: string;
|
|
125
|
+
repo: string;
|
|
83
126
|
}>>;
|
|
84
127
|
type NavBarRootProps = React.ComponentProps<"header"> & {
|
|
85
128
|
/** The accessible name of the navigation (“Main”) — passed translated. */
|
|
@@ -159,20 +202,60 @@ type NavBarMobileLinkProps = React.ComponentProps<"a"> & {
|
|
|
159
202
|
};
|
|
160
203
|
/** A link of the mobile panel. */
|
|
161
204
|
declare function NavBarMobileLink({ active, asChild, className, ...props }: NavBarMobileLinkProps): React.JSX.Element;
|
|
205
|
+
type NavBarFamilyProps = {
|
|
206
|
+
/** The site this bar belongs to (`@krizaka/ui/sites`): marked in the family, `aria-current="true"`. */
|
|
207
|
+
current: SiteId;
|
|
208
|
+
/**
|
|
209
|
+
* The family's words, passed translated: `familyLabels.fr` from `@krizaka/ui/sites`, or your own of the same shape.
|
|
210
|
+
* @default familyLabels.en
|
|
211
|
+
*/
|
|
212
|
+
labels?: FamilyLabels;
|
|
213
|
+
/** Opens the panel at first render (a story, a screenshot). */
|
|
214
|
+
defaultOpen?: boolean;
|
|
215
|
+
/** Classes of the switcher (or, inside `NavBar.Mobile`, of the family's group). */
|
|
216
|
+
className?: string;
|
|
217
|
+
};
|
|
218
|
+
/**
|
|
219
|
+
* The family switcher, attached to the brand (place it right after `NavBar.Brand`): a chevron that opens every site of
|
|
220
|
+
* Krizaka grouped — Krizaka · Products · Open source · GitHub — the current one marked. It opens on click, Enter, Space
|
|
221
|
+
* or ↓ (never on hover); ↑ ↓ walk the sites, Escape closes and returns the focus. Hidden below `md`: place a second
|
|
222
|
+
* `NavBar.Family` as the last child of `NavBar.Mobile`, where it renders as the panel's last group.
|
|
223
|
+
*/
|
|
224
|
+
declare function NavBarFamily({ current, labels, defaultOpen, className }: NavBarFamilyProps): React.JSX.Element;
|
|
225
|
+
type NavBarBadgeProps = React.ComponentProps<"span"> & {
|
|
226
|
+
/** The environment, when it is not production (`DEV`). */
|
|
227
|
+
env?: string;
|
|
228
|
+
/** The version the site runs (`1.2.3`, shown `v1.2.3`). */
|
|
229
|
+
version?: string;
|
|
230
|
+
};
|
|
231
|
+
/** A small mono badge beside the brand: the environment and the version (`DEV · v1.2.3`). Hidden below `sm`. */
|
|
232
|
+
declare function NavBarBadge({ env, version, className, children, ...props }: NavBarBadgeProps): React.JSX.Element;
|
|
233
|
+
type NavBarRepoProps = Omit<React.ComponentProps<"a">, "children"> & {
|
|
234
|
+
/** The repository the site is built from. */
|
|
235
|
+
href: string;
|
|
236
|
+
/** The link's accessible name (“Source on GitHub”) — passed translated. */
|
|
237
|
+
label: string;
|
|
238
|
+
};
|
|
239
|
+
/** The site's repository on GitHub, an icon link of `NavBar.Actions`. */
|
|
240
|
+
declare function NavBarRepo({ label, className, ...props }: NavBarRepoProps): React.JSX.Element;
|
|
162
241
|
/**
|
|
163
|
-
* `NavBar.Root/Brand/Items/Link/Menu/MenuLink/Actions/Mobile/MobileLink` — the Krizaka navigation bar
|
|
164
|
-
* on
|
|
242
|
+
* `NavBar.Root/Brand/Family/Badge/Items/Link/Menu/MenuLink/Actions/Repo/Mobile/MobileLink` — the Krizaka navigation bar,
|
|
243
|
+
* the same on every site of the family: floating, tightening on scroll, the family switcher on the brand, one light
|
|
244
|
+
* gliding between its items, accessible menus, a mobile panel.
|
|
165
245
|
*/
|
|
166
246
|
declare const NavBar: {
|
|
167
247
|
Root: typeof NavBarRoot;
|
|
168
248
|
Brand: typeof NavBarBrand;
|
|
249
|
+
Family: typeof NavBarFamily;
|
|
250
|
+
Badge: typeof NavBarBadge;
|
|
169
251
|
Items: typeof NavBarItems;
|
|
170
252
|
Link: typeof NavBarLink;
|
|
171
253
|
Menu: typeof NavBarMenu;
|
|
172
254
|
MenuLink: typeof NavBarMenuLink;
|
|
173
255
|
Actions: typeof NavBarActions;
|
|
256
|
+
Repo: typeof NavBarRepo;
|
|
174
257
|
Mobile: typeof NavBarMobile;
|
|
175
258
|
MobileLink: typeof NavBarMobileLink;
|
|
176
259
|
};
|
|
177
260
|
|
|
178
|
-
export { NavBar, NavBarActions, NavBarBrand, type NavBarBrandProps, NavBarItems, NavBarLink, type NavBarLinkProps, NavBarMenu, NavBarMenuLink, type NavBarMenuLinkProps, type NavBarMenuProps, NavBarMobile, NavBarMobileLink, type NavBarMobileLinkProps, type NavBarMobileProps, NavBarRoot, type NavBarRootProps, navBar };
|
|
261
|
+
export { NavBar, NavBarActions, NavBarBadge, type NavBarBadgeProps, NavBarBrand, type NavBarBrandProps, NavBarFamily, type NavBarFamilyProps, NavBarItems, NavBarLink, type NavBarLinkProps, NavBarMenu, NavBarMenuLink, type NavBarMenuLinkProps, type NavBarMenuProps, NavBarMobile, NavBarMobileLink, type NavBarMobileLinkProps, type NavBarMobileProps, NavBarRepo, type NavBarRepoProps, NavBarRoot, type NavBarRootProps, navBar };
|
package/dist/nav-bar.js
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
import {
|
|
3
|
+
FamilyMark,
|
|
4
|
+
GitHubGlyph,
|
|
5
|
+
familyLabels,
|
|
6
|
+
sitesByGroup
|
|
7
|
+
} from "./chunk-OT6HX3PN.js";
|
|
2
8
|
import {
|
|
3
9
|
useSlidingIndicator
|
|
4
10
|
} from "./chunk-VDR2EP6K.js";
|
|
11
|
+
import "./chunk-HG65YAV4.js";
|
|
5
12
|
import {
|
|
6
13
|
cn
|
|
7
14
|
} from "./chunk-2FRWNSRO.js";
|
|
@@ -28,7 +35,22 @@ var navBar = tv({
|
|
|
28
35
|
actions: "ml-auto flex items-center gap-2",
|
|
29
36
|
toggle: "inline-flex h-9 w-9 items-center justify-center rounded-full border border-border-subtle bg-surface-2/60 text-fg md:hidden focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring",
|
|
30
37
|
mobile: "kz-pop absolute inset-x-0 top-full mt-2 grid gap-1 rounded-2xl border border-border-default bg-surface-1 p-2 shadow-lg md:hidden",
|
|
31
|
-
mobileLink: "flex items-center justify-between rounded-xl px-3 py-3 text-[15px] font-medium text-fg no-underline hover:bg-surface-2 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring aria-[current=page]:text-fg-accent"
|
|
38
|
+
mobileLink: "flex items-center justify-between rounded-xl px-3 py-3 text-[15px] font-medium text-fg no-underline hover:bg-surface-2 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring aria-[current=page]:text-fg-accent",
|
|
39
|
+
// The family switcher: a chevron attached to the brand, its panel aligned on the bar's left edge.
|
|
40
|
+
family: "hidden md:block",
|
|
41
|
+
familyTrigger: "group/trigger -ml-2 mr-1 inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-full text-fg-secondary transition-colors hover:bg-surface-3 hover:text-fg data-[state=open]:bg-surface-3 data-[state=open]:text-fg focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring",
|
|
42
|
+
familyViewport: "kz-pop absolute left-0 top-full mt-2 h-(--radix-navigation-menu-viewport-height) w-(--radix-navigation-menu-viewport-width) origin-top-left overflow-hidden rounded-2xl border border-border-default bg-surface-1 shadow-lg transition-[width,height] duration-300 motion-reduce:transition-none",
|
|
43
|
+
familyPanel: "grid w-[min(92vw,42rem)] gap-x-2 gap-y-3 p-3 sm:grid-cols-2",
|
|
44
|
+
familyGroupTitle: "px-3 pb-1 pt-1 text-[11px] font-semibold uppercase tracking-wider text-fg-secondary",
|
|
45
|
+
familyLink: "group/link flex items-start gap-3 rounded-xl px-3 py-2.5 text-left no-underline outline-hidden transition-colors hover:bg-surface-2 focus-visible:bg-surface-2 focus-visible:ring-2 focus-visible:ring-ring data-current:bg-accent-soft",
|
|
46
|
+
familyMark: "mt-0.5 flex h-7 w-7 shrink-0 items-center justify-center text-fg",
|
|
47
|
+
familyName: "flex flex-wrap items-center gap-x-2 gap-y-0.5 text-sm font-semibold text-fg",
|
|
48
|
+
familyText: "mt-0.5 block text-xs leading-relaxed text-fg-secondary",
|
|
49
|
+
familyTag: "rounded-full px-1.5 py-px text-[10px] font-semibold uppercase tracking-wider",
|
|
50
|
+
mobileFamily: "mt-1 grid gap-2 border-t border-border-subtle px-1 pb-1 pt-3",
|
|
51
|
+
mobileFamilyLink: "flex min-h-11 items-center gap-3 rounded-xl px-2 py-2 text-[15px] font-medium text-fg no-underline hover:bg-surface-2 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring data-current:bg-accent-soft",
|
|
52
|
+
badge: "hidden h-6 shrink-0 items-center gap-1 rounded-full border border-border-subtle bg-surface-2 px-2 font-mono text-[11px] font-medium text-fg-secondary sm:inline-flex",
|
|
53
|
+
repo: "inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-full text-fg-secondary transition-colors hover:bg-surface-3 hover:text-fg focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring"
|
|
32
54
|
},
|
|
33
55
|
variants: {
|
|
34
56
|
floating: {
|
|
@@ -40,6 +62,7 @@ var navBar = tv({
|
|
|
40
62
|
});
|
|
41
63
|
var s = navBar();
|
|
42
64
|
var Context = React.createContext(null);
|
|
65
|
+
var MobileContext = React.createContext(false);
|
|
43
66
|
var useNavBar = () => {
|
|
44
67
|
const ctx = React.useContext(Context);
|
|
45
68
|
if (!ctx) throw new Error("NavBar parts must be inside <NavBar.Root>.");
|
|
@@ -121,7 +144,7 @@ function NavBarMobile({ openLabel, closeLabel, className, children, ...props })
|
|
|
121
144
|
if (e.target.closest("a")) setOpen(false);
|
|
122
145
|
},
|
|
123
146
|
...props,
|
|
124
|
-
children
|
|
147
|
+
children: /* @__PURE__ */ jsx(MobileContext.Provider, { value: true, children })
|
|
125
148
|
}
|
|
126
149
|
)
|
|
127
150
|
] });
|
|
@@ -130,27 +153,90 @@ function NavBarMobileLink({ active, asChild, className, ...props }) {
|
|
|
130
153
|
const Comp = asChild ? Slot.Root : "a";
|
|
131
154
|
return /* @__PURE__ */ jsx(Comp, { "aria-current": active ? "page" : void 0, className: s.mobileLink({ className }), ...props });
|
|
132
155
|
}
|
|
156
|
+
var tagTone = {
|
|
157
|
+
upcoming: "bg-accent-soft text-fg ring-1 ring-inset ring-accent/40",
|
|
158
|
+
construction: "bg-warning/15 text-fg ring-1 ring-inset ring-warning/40",
|
|
159
|
+
current: "bg-surface-3 text-fg-secondary"
|
|
160
|
+
};
|
|
161
|
+
function FamilyName({ site, current, labels }) {
|
|
162
|
+
return /* @__PURE__ */ jsxs("span", { className: s.familyName(), children: [
|
|
163
|
+
site.name,
|
|
164
|
+
site.status !== "released" && /* @__PURE__ */ jsx("span", { className: cn(s.familyTag(), tagTone[site.status]), children: labels.status[site.status] }),
|
|
165
|
+
current && /* @__PURE__ */ jsx("span", { className: cn(s.familyTag(), tagTone.current), children: labels.current })
|
|
166
|
+
] });
|
|
167
|
+
}
|
|
168
|
+
function NavBarFamily({ current, labels = familyLabels.en, defaultOpen, className }) {
|
|
169
|
+
const inMobile = React.useContext(MobileContext);
|
|
170
|
+
const id = React.useId();
|
|
171
|
+
const groups = sitesByGroup();
|
|
172
|
+
if (inMobile) {
|
|
173
|
+
return /* @__PURE__ */ jsxs("div", { role: "group", "aria-labelledby": `${id}-family`, className: s.mobileFamily({ className }), children: [
|
|
174
|
+
/* @__PURE__ */ jsx("p", { id: `${id}-family`, className: s.familyGroupTitle(), children: labels.family }),
|
|
175
|
+
groups.map(({ group, sites }) => /* @__PURE__ */ jsxs("div", { children: [
|
|
176
|
+
/* @__PURE__ */ jsx("p", { id: `${id}-${group}`, className: s.familyGroupTitle(), children: labels.groups[group] }),
|
|
177
|
+
/* @__PURE__ */ jsx("ul", { "aria-labelledby": `${id}-${group}`, className: "grid gap-0.5", children: sites.map((site) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs("a", { href: site.url, "data-current": site.id === current ? "" : void 0, "aria-current": site.id === current ? "true" : void 0, className: s.mobileFamilyLink(), children: [
|
|
178
|
+
/* @__PURE__ */ jsx("span", { className: s.familyMark(), children: /* @__PURE__ */ jsx(FamilyMark, { mark: site.mark, size: 24 }) }),
|
|
179
|
+
/* @__PURE__ */ jsx(FamilyName, { site, current: site.id === current, labels })
|
|
180
|
+
] }) }, site.id)) })
|
|
181
|
+
] }, group))
|
|
182
|
+
] });
|
|
183
|
+
}
|
|
184
|
+
const noHover = (e) => e.preventDefault();
|
|
185
|
+
const columns = [groups.filter((g) => g.group === "krizaka" || g.group === "products"), groups.filter((g) => g.group === "open-source" || g.group === "github")];
|
|
186
|
+
return /* @__PURE__ */ jsxs(Nav.Root, { "aria-label": labels.family, defaultValue: defaultOpen ? "family" : void 0, className: s.family({ className }), children: [
|
|
187
|
+
/* @__PURE__ */ jsx(Nav.List, { className: "flex", children: /* @__PURE__ */ jsxs(Nav.Item, { value: "family", children: [
|
|
188
|
+
/* @__PURE__ */ jsx(Nav.Trigger, { "aria-label": labels.family, onPointerMove: noHover, onPointerLeave: noHover, className: s.familyTrigger(), children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", className: s.chevron(), fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "m6 9 6 6 6-6" }) }) }),
|
|
189
|
+
/* @__PURE__ */ jsx(Nav.Content, { onPointerLeave: noHover, className: s.familyPanel(), children: columns.map((column, i) => /* @__PURE__ */ jsx("div", { className: "grid content-start gap-3", children: column.map(({ group, sites }) => /* @__PURE__ */ jsxs("div", { children: [
|
|
190
|
+
/* @__PURE__ */ jsx("p", { id: `${id}-${group}`, className: s.familyGroupTitle(), children: labels.groups[group] }),
|
|
191
|
+
/* @__PURE__ */ jsx("ul", { "aria-labelledby": `${id}-${group}`, className: "grid gap-0.5", children: sites.map((site) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(Nav.Link, { href: site.url, "data-current": site.id === current ? "" : void 0, "aria-current": site.id === current ? "true" : void 0, className: s.familyLink(), children: [
|
|
192
|
+
/* @__PURE__ */ jsx("span", { className: s.familyMark(), children: /* @__PURE__ */ jsx(FamilyMark, { mark: site.mark, size: 28 }) }),
|
|
193
|
+
/* @__PURE__ */ jsxs("span", { className: "min-w-0", children: [
|
|
194
|
+
/* @__PURE__ */ jsx(FamilyName, { site, current: site.id === current, labels }),
|
|
195
|
+
/* @__PURE__ */ jsx("span", { className: s.familyText(), children: labels.descriptions[site.id] })
|
|
196
|
+
] })
|
|
197
|
+
] }) }, site.id)) })
|
|
198
|
+
] }, group)) }, i)) })
|
|
199
|
+
] }) }),
|
|
200
|
+
/* @__PURE__ */ jsx(Nav.Viewport, { onPointerLeave: noHover, className: s.familyViewport() })
|
|
201
|
+
] });
|
|
202
|
+
}
|
|
203
|
+
function NavBarBadge({ env, version, className, children, ...props }) {
|
|
204
|
+
const parts = [env, version && `v${version.replace(/^v/, "")}`].filter(Boolean);
|
|
205
|
+
return /* @__PURE__ */ jsxs("span", { className: s.badge({ className }), ...props, children: [
|
|
206
|
+
parts.join(" \xB7 "),
|
|
207
|
+
children
|
|
208
|
+
] });
|
|
209
|
+
}
|
|
210
|
+
function NavBarRepo({ label, className, ...props }) {
|
|
211
|
+
return /* @__PURE__ */ jsx("a", { "aria-label": label, className: s.repo({ className }), ...props, children: /* @__PURE__ */ jsx(GitHubGlyph, { size: 18 }) });
|
|
212
|
+
}
|
|
133
213
|
var NavBar = {
|
|
134
214
|
Root: NavBarRoot,
|
|
135
215
|
Brand: NavBarBrand,
|
|
216
|
+
Family: NavBarFamily,
|
|
217
|
+
Badge: NavBarBadge,
|
|
136
218
|
Items: NavBarItems,
|
|
137
219
|
Link: NavBarLink,
|
|
138
220
|
Menu: NavBarMenu,
|
|
139
221
|
MenuLink: NavBarMenuLink,
|
|
140
222
|
Actions: NavBarActions,
|
|
223
|
+
Repo: NavBarRepo,
|
|
141
224
|
Mobile: NavBarMobile,
|
|
142
225
|
MobileLink: NavBarMobileLink
|
|
143
226
|
};
|
|
144
227
|
export {
|
|
145
228
|
NavBar,
|
|
146
229
|
NavBarActions,
|
|
230
|
+
NavBarBadge,
|
|
147
231
|
NavBarBrand,
|
|
232
|
+
NavBarFamily,
|
|
148
233
|
NavBarItems,
|
|
149
234
|
NavBarLink,
|
|
150
235
|
NavBarMenu,
|
|
151
236
|
NavBarMenuLink,
|
|
152
237
|
NavBarMobile,
|
|
153
238
|
NavBarMobileLink,
|
|
239
|
+
NavBarRepo,
|
|
154
240
|
NavBarRoot,
|
|
155
241
|
navBar
|
|
156
242
|
};
|
package/dist/nav-bar.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/nav-bar/nav-bar.tsx"],"sourcesContent":["// Client (scroll, a sliding indicator, menus). Radix NavigationMenu does the menus' semantics and keyboard (Enter, Space\n// and ↓ open; ↑ ↓ Home End walk; Escape closes and returns the focus; Tab out closes); this file draws the Krizaka bar:\n// a floating pill that tightens once the page scrolls, one light that glides to the item under the pointer or the\n// focus and rests on the current page, and a mobile panel that is a plain disclosure (no focus trap, Escape closes).\nimport { NavigationMenu as Nav, Slot } from \"radix-ui\";\nimport * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nimport { cn } from \"../cn\";\nimport { useSlidingIndicator } from \"../sliding-indicator\";\n\nexport const navBar = tv({\n slots: {\n root:\n \"group/nav relative z-40 mx-auto flex h-14 w-full items-center gap-2 border-border-subtle bg-surface-1/75 backdrop-blur-xl backdrop-saturate-150 \" +\n \"transition-[height,background-color,border-color,box-shadow] duration-300 motion-reduce:transition-none \" +\n \"data-compact:h-12 data-compact:border-border-default data-compact:bg-surface-1/90 data-compact:shadow-lg\",\n brand:\n \"mr-2 inline-flex shrink-0 items-center gap-2 font-display text-[15px] font-bold tracking-tight text-fg no-underline \" +\n \"rounded-md focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring\",\n items: \"relative hidden md:block\",\n list:\n \"group/list relative isolate flex items-center gap-0.5 \" +\n // The light: under the item that is pointed at or focused, resting on the current page.\n \"before:absolute before:left-0 before:top-0 before:-z-10 before:h-(--kz-ind-h) before:w-(--kz-ind-w) before:translate-x-(--kz-ind-x) before:translate-y-(--kz-ind-y) \" +\n \"before:rounded-full before:bg-surface-3 before:opacity-0 before:transition-[translate,width,opacity] before:duration-300 motion-reduce:before:transition-none \" +\n \"data-[indicator=on]:before:opacity-100\",\n item:\n \"inline-flex h-9 select-none items-center gap-1 rounded-full px-3.5 text-sm font-medium text-fg-secondary no-underline transition-colors \" +\n \"hover:text-fg data-active:text-fg data-[state=open]:text-fg focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring \" +\n // Before the light is ready (server render), the current page carries its own tint.\n \"group-not-data-[indicator=on]/list:data-active:bg-surface-3\",\n chevron: \"h-3.5 w-3.5 transition-transform duration-300 group-data-[state=open]/trigger:rotate-180 motion-reduce:transition-none\",\n viewport:\n \"kz-pop absolute left-0 top-full mt-2 h-(--radix-navigation-menu-viewport-height) w-(--radix-navigation-menu-viewport-width) origin-top-left overflow-hidden \" +\n \"rounded-2xl border border-border-default bg-surface-1 shadow-lg transition-[width,height] duration-300 motion-reduce:transition-none\",\n panel: \"grid w-max max-w-[min(92vw,30rem)] gap-1 p-2\",\n menuLink:\n \"group/link flex items-start gap-3 rounded-xl p-3 text-left no-underline outline-hidden transition-colors \" +\n \"hover:bg-surface-2 focus-visible:bg-surface-2 focus-visible:ring-2 focus-visible:ring-ring data-active:bg-accent-soft\",\n menuIcon:\n \"mt-0.5 flex h-9 w-9 shrink-0 items-center justify-center rounded-lg border border-border-default bg-surface-2 text-fg-accent \" +\n \"transition-[transform,border-color] duration-300 group-hover/link:-translate-y-0.5 group-hover/link:border-accent [&>svg]:h-4.5 [&>svg]:w-4.5 motion-reduce:transform-none\",\n menuTitle: \"block text-sm font-semibold text-fg\",\n menuText: \"mt-0.5 block text-xs leading-relaxed text-fg-secondary\",\n actions: \"ml-auto flex items-center gap-2\",\n toggle:\n \"inline-flex h-9 w-9 items-center justify-center rounded-full border border-border-subtle bg-surface-2/60 text-fg md:hidden \" +\n \"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring\",\n mobile: \"kz-pop absolute inset-x-0 top-full mt-2 grid gap-1 rounded-2xl border border-border-default bg-surface-1 p-2 shadow-lg md:hidden\",\n mobileLink:\n \"flex items-center justify-between rounded-xl px-3 py-3 text-[15px] font-medium text-fg no-underline hover:bg-surface-2 \" +\n \"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring aria-[current=page]:text-fg-accent\",\n },\n variants: {\n floating: {\n true: { root: \"max-w-5xl rounded-full border pl-5 pr-2 data-compact:max-w-4xl\" },\n false: { root: \"border-b px-4 md:px-6\" },\n },\n },\n defaultVariants: { floating: true },\n});\nconst s = navBar();\n\ninterface NavBarContext {\n label: string;\n open: boolean;\n setOpen: (open: boolean) => void;\n panelId: string;\n}\nconst Context = React.createContext<NavBarContext | null>(null);\nconst useNavBar = () => {\n const ctx = React.useContext(Context);\n if (!ctx) throw new Error(\"NavBar parts must be inside <NavBar.Root>.\");\n return ctx;\n};\n\nexport type NavBarRootProps = React.ComponentProps<\"header\"> & {\n /** The accessible name of the navigation (“Main”) — passed translated. */\n label: string;\n /**\n * Pixels of scroll after which the bar tightens (denser, lower, lifted). `false`: never.\n * @default 24\n */\n compactAfter?: number | false;\n /**\n * A floating pill (the Krizaka bar) or a full-width bar with a hairline under it.\n * @default true\n */\n floating?: boolean;\n};\n\n/** The bar. Place it in a `sticky top-3` (floating) or `sticky top-0` wrapper — or let it scroll. */\nexport function NavBarRoot({ label, compactAfter = 24, floating = true, className, children, ...props }: NavBarRootProps) {\n const [compact, setCompact] = React.useState(false);\n const [open, setOpen] = React.useState(false);\n const panelId = React.useId();\n React.useEffect(() => {\n if (compactAfter === false) return;\n const onScroll = () => setCompact(window.scrollY > compactAfter);\n onScroll();\n window.addEventListener(\"scroll\", onScroll, { passive: true });\n return () => window.removeEventListener(\"scroll\", onScroll);\n }, [compactAfter]);\n const ctx = React.useMemo(() => ({ label, open, setOpen, panelId }), [label, open, panelId]);\n return (\n <Context.Provider value={ctx}>\n <header data-compact={compact ? \"\" : undefined} data-floating={floating} className={navBar({ floating }).root({ className })} {...props}>\n {children}\n </header>\n </Context.Provider>\n );\n}\n\nexport type NavBarBrandProps = React.ComponentProps<\"a\"> & {\n /** Renders your link (a router `<Link>`) with the brand's look. */\n asChild?: boolean;\n};\n\n/** The brand: a mark and a name, linking home. */\nexport function NavBarBrand({ asChild, className, ...props }: NavBarBrandProps) {\n const Comp = asChild ? Slot.Root : \"a\";\n return <Comp className={s.brand({ className })} {...props} />;\n}\n\n/** The desktop navigation: links and menus, with the light that glides between them. Hidden below `md` (see `NavBar.Mobile`). */\nexport function NavBarItems({ className, children, ...props }: Omit<React.ComponentProps<typeof Nav.Root>, \"orientation\">) {\n const { label } = useNavBar();\n const { ref, handlers } = useSlidingIndicator<HTMLUListElement>({ item: \"[data-nav-item]\", active: \"[data-nav-item][data-active]\", follow: true });\n return (\n <Nav.Root aria-label={label} className={s.items({ className })} delayDuration={80} {...props}>\n <Nav.List ref={ref} className={s.list()} {...handlers}>\n {children}\n </Nav.List>\n <Nav.Viewport className={s.viewport()} />\n </Nav.Root>\n );\n}\n\nexport type NavBarLinkProps = Omit<React.ComponentProps<typeof Nav.Link>, \"active\"> & {\n /** The current page: `aria-current=\"page\"`, and the light rests on it. */\n active?: boolean;\n};\n\n/** A link of the bar. `asChild` renders your router's `<Link>`. */\nexport function NavBarLink({ active, className, ...props }: NavBarLinkProps) {\n return (\n <Nav.Item>\n <Nav.Link data-nav-item=\"\" data-active={active ? \"\" : undefined} active={active} aria-current={active ? \"page\" : undefined} className={s.item({ className })} {...props} />\n </Nav.Item>\n );\n}\n\nexport type NavBarMenuProps = Omit<React.ComponentProps<typeof Nav.Item>, \"children\"> & {\n /** The trigger's words (“Products”) — passed translated. */\n label: string;\n /** The current page is inside this menu: the light rests on its trigger. */\n active?: boolean;\n /** The menu's links (`NavBar.MenuLink`), laid out in a panel; `columns` sets the grid. */\n children: React.ReactNode;\n /**\n * Columns of the panel.\n * @default 1\n */\n columns?: 1 | 2;\n};\n\n/** A menu of the bar: its trigger, and its links in a panel that opens under the bar. */\nexport function NavBarMenu({ label, active, columns = 1, children, className, ...props }: NavBarMenuProps) {\n return (\n <Nav.Item className={className} {...props}>\n <Nav.Trigger data-nav-item=\"\" data-active={active ? \"\" : undefined} className={cn(s.item(), \"group/trigger\")}>\n {label}\n <svg viewBox=\"0 0 24 24\" className={s.chevron()} fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" aria-hidden>\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n </Nav.Trigger>\n <Nav.Content className={cn(s.panel(), columns === 2 && \"md:grid-cols-2\")}>{children}</Nav.Content>\n </Nav.Item>\n );\n}\n\nexport type NavBarMenuLinkProps = Omit<React.ComponentProps<typeof Nav.Link>, \"title\" | \"active\"> & {\n /** The link's name — passed translated. */\n title: string;\n /** One line under it — passed translated. */\n description?: string;\n /** An icon (a signature icon of `@krizaka/icons`: its node lights up on hover). */\n icon?: React.ReactNode;\n /** The current page. */\n active?: boolean;\n};\n\n/** A link inside a menu: an icon, a name and a line of text. */\nexport function NavBarMenuLink({ title, description, icon, active, href, className, asChild, children, ...props }: NavBarMenuLinkProps) {\n const body = (\n <>\n {icon && <span className={s.menuIcon()}>{icon}</span>}\n <span className=\"min-w-0\">\n <span className={s.menuTitle()}>{title}</span>\n {description && <span className={s.menuText()}>{description}</span>}\n </span>\n </>\n );\n return (\n <Nav.Link asChild={asChild} href={asChild ? undefined : href} active={active} aria-current={active ? \"page\" : undefined} data-active={active ? \"\" : undefined} className={s.menuLink({ className })} {...props}>\n {asChild && React.isValidElement<{ children?: React.ReactNode }>(children) ? React.cloneElement(children, undefined, body) : body}\n </Nav.Link>\n );\n}\n\n/** The right side: search, theme, language, the call to action. */\nexport function NavBarActions({ className, ...props }: React.ComponentProps<\"div\">) {\n return <div className={s.actions({ className })} {...props} />;\n}\n\nexport type NavBarMobileProps = React.ComponentProps<\"nav\"> & {\n /** The toggle's name when closed (“Open the menu”) — passed translated. */\n openLabel: string;\n /** The toggle's name when open (“Close the menu”) — passed translated. */\n closeLabel: string;\n};\n\n/**\n * Below `md`: a toggle, and a panel under the bar with its links (`NavBar.MobileLink`). A disclosure: Escape and a click\n * on a link close it, the focus returns to the toggle.\n */\nexport function NavBarMobile({ openLabel, closeLabel, className, children, ...props }: NavBarMobileProps) {\n const { label, open, setOpen, panelId } = useNavBar();\n const toggle = React.useRef<HTMLButtonElement>(null);\n React.useEffect(() => {\n if (!open) return;\n const onKey = (e: KeyboardEvent) => {\n if (e.key !== \"Escape\") return;\n setOpen(false);\n toggle.current?.focus();\n };\n document.addEventListener(\"keydown\", onKey);\n return () => document.removeEventListener(\"keydown\", onKey);\n }, [open, setOpen]);\n return (\n <>\n <button ref={toggle} type=\"button\" aria-expanded={open} aria-controls={panelId} aria-label={open ? closeLabel : openLabel} onClick={() => setOpen(!open)} className={s.toggle()}>\n <svg viewBox=\"0 0 24 24\" className=\"h-4.5 w-4.5\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" aria-hidden>\n {open ? <path d=\"M18 6 6 18M6 6l12 12\" /> : <path d=\"M4 7h16M4 12h16M4 17h10\" />}\n </svg>\n </button>\n {open && (\n <nav\n id={panelId}\n aria-label={label}\n className={s.mobile({ className })}\n onClick={(e) => {\n if ((e.target as Element).closest(\"a\")) setOpen(false);\n }}\n {...props}\n >\n {children}\n </nav>\n )}\n </>\n );\n}\n\nexport type NavBarMobileLinkProps = React.ComponentProps<\"a\"> & {\n /** The current page. */\n active?: boolean;\n /** Renders your router's `<Link>`. */\n asChild?: boolean;\n};\n\n/** A link of the mobile panel. */\nexport function NavBarMobileLink({ active, asChild, className, ...props }: NavBarMobileLinkProps) {\n const Comp = asChild ? Slot.Root : \"a\";\n return <Comp aria-current={active ? \"page\" : undefined} className={s.mobileLink({ className })} {...props} />;\n}\n\n/**\n * `NavBar.Root/Brand/Items/Link/Menu/MenuLink/Actions/Mobile/MobileLink` — the Krizaka navigation bar: floating, tightening\n * on scroll, one light gliding between its items, accessible menus, a mobile panel.\n */\nexport const NavBar = {\n Root: NavBarRoot,\n Brand: NavBarBrand,\n Items: NavBarItems,\n Link: NavBarLink,\n Menu: NavBarMenu,\n MenuLink: NavBarMenuLink,\n Actions: NavBarActions,\n Mobile: NavBarMobile,\n MobileLink: NavBarMobileLink,\n};\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/nav-bar/nav-bar.tsx"],"sourcesContent":["// Client (scroll, a sliding indicator, menus). Radix NavigationMenu does the menus' semantics and keyboard (Enter, Space\n// and ↓ open; ↑ ↓ Home End walk; Escape closes and returns the focus; Tab out closes); this file draws the Krizaka bar:\n// a floating pill that tightens once the page scrolls, one light that glides to the item under the pointer or the\n// focus and rests on the current page, and a mobile panel that is a plain disclosure (no focus trap, Escape closes).\nimport { NavigationMenu as Nav, Slot } from \"radix-ui\";\nimport * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nimport { cn } from \"../cn\";\nimport { FamilyMark, GitHubGlyph } from \"../family-mark\";\nimport { type FamilyLabels, familyLabels, type Site, type SiteId, sitesByGroup } from \"../sites/sites\";\nimport { useSlidingIndicator } from \"../sliding-indicator\";\n\nexport const navBar = tv({\n slots: {\n root:\n \"group/nav relative z-40 mx-auto flex h-14 w-full items-center gap-2 border-border-subtle bg-surface-1/75 backdrop-blur-xl backdrop-saturate-150 \" +\n \"transition-[height,background-color,border-color,box-shadow] duration-300 motion-reduce:transition-none \" +\n \"data-compact:h-12 data-compact:border-border-default data-compact:bg-surface-1/90 data-compact:shadow-lg\",\n brand:\n \"mr-2 inline-flex shrink-0 items-center gap-2 font-display text-[15px] font-bold tracking-tight text-fg no-underline \" +\n \"rounded-md focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring\",\n items: \"relative hidden md:block\",\n list:\n \"group/list relative isolate flex items-center gap-0.5 \" +\n // The light: under the item that is pointed at or focused, resting on the current page.\n \"before:absolute before:left-0 before:top-0 before:-z-10 before:h-(--kz-ind-h) before:w-(--kz-ind-w) before:translate-x-(--kz-ind-x) before:translate-y-(--kz-ind-y) \" +\n \"before:rounded-full before:bg-surface-3 before:opacity-0 before:transition-[translate,width,opacity] before:duration-300 motion-reduce:before:transition-none \" +\n \"data-[indicator=on]:before:opacity-100\",\n item:\n \"inline-flex h-9 select-none items-center gap-1 rounded-full px-3.5 text-sm font-medium text-fg-secondary no-underline transition-colors \" +\n \"hover:text-fg data-active:text-fg data-[state=open]:text-fg focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring \" +\n // Before the light is ready (server render), the current page carries its own tint.\n \"group-not-data-[indicator=on]/list:data-active:bg-surface-3\",\n chevron: \"h-3.5 w-3.5 transition-transform duration-300 group-data-[state=open]/trigger:rotate-180 motion-reduce:transition-none\",\n viewport:\n \"kz-pop absolute left-0 top-full mt-2 h-(--radix-navigation-menu-viewport-height) w-(--radix-navigation-menu-viewport-width) origin-top-left overflow-hidden \" +\n \"rounded-2xl border border-border-default bg-surface-1 shadow-lg transition-[width,height] duration-300 motion-reduce:transition-none\",\n panel: \"grid w-max max-w-[min(92vw,30rem)] gap-1 p-2\",\n menuLink:\n \"group/link flex items-start gap-3 rounded-xl p-3 text-left no-underline outline-hidden transition-colors \" +\n \"hover:bg-surface-2 focus-visible:bg-surface-2 focus-visible:ring-2 focus-visible:ring-ring data-active:bg-accent-soft\",\n menuIcon:\n \"mt-0.5 flex h-9 w-9 shrink-0 items-center justify-center rounded-lg border border-border-default bg-surface-2 text-fg-accent \" +\n \"transition-[transform,border-color] duration-300 group-hover/link:-translate-y-0.5 group-hover/link:border-accent [&>svg]:h-4.5 [&>svg]:w-4.5 motion-reduce:transform-none\",\n menuTitle: \"block text-sm font-semibold text-fg\",\n menuText: \"mt-0.5 block text-xs leading-relaxed text-fg-secondary\",\n actions: \"ml-auto flex items-center gap-2\",\n toggle:\n \"inline-flex h-9 w-9 items-center justify-center rounded-full border border-border-subtle bg-surface-2/60 text-fg md:hidden \" +\n \"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring\",\n mobile: \"kz-pop absolute inset-x-0 top-full mt-2 grid gap-1 rounded-2xl border border-border-default bg-surface-1 p-2 shadow-lg md:hidden\",\n mobileLink:\n \"flex items-center justify-between rounded-xl px-3 py-3 text-[15px] font-medium text-fg no-underline hover:bg-surface-2 \" +\n \"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring aria-[current=page]:text-fg-accent\",\n // The family switcher: a chevron attached to the brand, its panel aligned on the bar's left edge.\n family: \"hidden md:block\",\n familyTrigger:\n \"group/trigger -ml-2 mr-1 inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-full text-fg-secondary transition-colors \" +\n \"hover:bg-surface-3 hover:text-fg data-[state=open]:bg-surface-3 data-[state=open]:text-fg focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring\",\n familyViewport:\n \"kz-pop absolute left-0 top-full mt-2 h-(--radix-navigation-menu-viewport-height) w-(--radix-navigation-menu-viewport-width) origin-top-left overflow-hidden \" +\n \"rounded-2xl border border-border-default bg-surface-1 shadow-lg transition-[width,height] duration-300 motion-reduce:transition-none\",\n familyPanel: \"grid w-[min(92vw,42rem)] gap-x-2 gap-y-3 p-3 sm:grid-cols-2\",\n familyGroupTitle: \"px-3 pb-1 pt-1 text-[11px] font-semibold uppercase tracking-wider text-fg-secondary\",\n familyLink:\n \"group/link flex items-start gap-3 rounded-xl px-3 py-2.5 text-left no-underline outline-hidden transition-colors \" +\n \"hover:bg-surface-2 focus-visible:bg-surface-2 focus-visible:ring-2 focus-visible:ring-ring data-current:bg-accent-soft\",\n familyMark: \"mt-0.5 flex h-7 w-7 shrink-0 items-center justify-center text-fg\",\n familyName: \"flex flex-wrap items-center gap-x-2 gap-y-0.5 text-sm font-semibold text-fg\",\n familyText: \"mt-0.5 block text-xs leading-relaxed text-fg-secondary\",\n familyTag: \"rounded-full px-1.5 py-px text-[10px] font-semibold uppercase tracking-wider\",\n mobileFamily: \"mt-1 grid gap-2 border-t border-border-subtle px-1 pb-1 pt-3\",\n mobileFamilyLink:\n \"flex min-h-11 items-center gap-3 rounded-xl px-2 py-2 text-[15px] font-medium text-fg no-underline hover:bg-surface-2 \" +\n \"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring data-current:bg-accent-soft\",\n badge:\n \"hidden h-6 shrink-0 items-center gap-1 rounded-full border border-border-subtle bg-surface-2 px-2 font-mono text-[11px] font-medium text-fg-secondary sm:inline-flex\",\n repo:\n \"inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-full text-fg-secondary transition-colors hover:bg-surface-3 hover:text-fg \" +\n \"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring\",\n },\n variants: {\n floating: {\n true: { root: \"max-w-5xl rounded-full border pl-5 pr-2 data-compact:max-w-4xl\" },\n false: { root: \"border-b px-4 md:px-6\" },\n },\n },\n defaultVariants: { floating: true },\n});\nconst s = navBar();\n\ninterface NavBarContext {\n label: string;\n open: boolean;\n setOpen: (open: boolean) => void;\n panelId: string;\n}\nconst Context = React.createContext<NavBarContext | null>(null);\n/** True inside `NavBar.Mobile`: the family renders as the panel's last group instead of a switcher. */\nconst MobileContext = React.createContext(false);\nconst useNavBar = () => {\n const ctx = React.useContext(Context);\n if (!ctx) throw new Error(\"NavBar parts must be inside <NavBar.Root>.\");\n return ctx;\n};\n\nexport type NavBarRootProps = React.ComponentProps<\"header\"> & {\n /** The accessible name of the navigation (“Main”) — passed translated. */\n label: string;\n /**\n * Pixels of scroll after which the bar tightens (denser, lower, lifted). `false`: never.\n * @default 24\n */\n compactAfter?: number | false;\n /**\n * A floating pill (the Krizaka bar) or a full-width bar with a hairline under it.\n * @default true\n */\n floating?: boolean;\n};\n\n/** The bar. Place it in a `sticky top-3` (floating) or `sticky top-0` wrapper — or let it scroll. */\nexport function NavBarRoot({ label, compactAfter = 24, floating = true, className, children, ...props }: NavBarRootProps) {\n const [compact, setCompact] = React.useState(false);\n const [open, setOpen] = React.useState(false);\n const panelId = React.useId();\n React.useEffect(() => {\n if (compactAfter === false) return;\n const onScroll = () => setCompact(window.scrollY > compactAfter);\n onScroll();\n window.addEventListener(\"scroll\", onScroll, { passive: true });\n return () => window.removeEventListener(\"scroll\", onScroll);\n }, [compactAfter]);\n const ctx = React.useMemo(() => ({ label, open, setOpen, panelId }), [label, open, panelId]);\n return (\n <Context.Provider value={ctx}>\n <header data-compact={compact ? \"\" : undefined} data-floating={floating} className={navBar({ floating }).root({ className })} {...props}>\n {children}\n </header>\n </Context.Provider>\n );\n}\n\nexport type NavBarBrandProps = React.ComponentProps<\"a\"> & {\n /** Renders your link (a router `<Link>`) with the brand's look. */\n asChild?: boolean;\n};\n\n/** The brand: a mark and a name, linking home. */\nexport function NavBarBrand({ asChild, className, ...props }: NavBarBrandProps) {\n const Comp = asChild ? Slot.Root : \"a\";\n return <Comp className={s.brand({ className })} {...props} />;\n}\n\n/** The desktop navigation: links and menus, with the light that glides between them. Hidden below `md` (see `NavBar.Mobile`). */\nexport function NavBarItems({ className, children, ...props }: Omit<React.ComponentProps<typeof Nav.Root>, \"orientation\">) {\n const { label } = useNavBar();\n const { ref, handlers } = useSlidingIndicator<HTMLUListElement>({ item: \"[data-nav-item]\", active: \"[data-nav-item][data-active]\", follow: true });\n return (\n <Nav.Root aria-label={label} className={s.items({ className })} delayDuration={80} {...props}>\n <Nav.List ref={ref} className={s.list()} {...handlers}>\n {children}\n </Nav.List>\n <Nav.Viewport className={s.viewport()} />\n </Nav.Root>\n );\n}\n\nexport type NavBarLinkProps = Omit<React.ComponentProps<typeof Nav.Link>, \"active\"> & {\n /** The current page: `aria-current=\"page\"`, and the light rests on it. */\n active?: boolean;\n};\n\n/** A link of the bar. `asChild` renders your router's `<Link>`. */\nexport function NavBarLink({ active, className, ...props }: NavBarLinkProps) {\n return (\n <Nav.Item>\n <Nav.Link data-nav-item=\"\" data-active={active ? \"\" : undefined} active={active} aria-current={active ? \"page\" : undefined} className={s.item({ className })} {...props} />\n </Nav.Item>\n );\n}\n\nexport type NavBarMenuProps = Omit<React.ComponentProps<typeof Nav.Item>, \"children\"> & {\n /** The trigger's words (“Products”) — passed translated. */\n label: string;\n /** The current page is inside this menu: the light rests on its trigger. */\n active?: boolean;\n /** The menu's links (`NavBar.MenuLink`), laid out in a panel; `columns` sets the grid. */\n children: React.ReactNode;\n /**\n * Columns of the panel.\n * @default 1\n */\n columns?: 1 | 2;\n};\n\n/** A menu of the bar: its trigger, and its links in a panel that opens under the bar. */\nexport function NavBarMenu({ label, active, columns = 1, children, className, ...props }: NavBarMenuProps) {\n return (\n <Nav.Item className={className} {...props}>\n <Nav.Trigger data-nav-item=\"\" data-active={active ? \"\" : undefined} className={cn(s.item(), \"group/trigger\")}>\n {label}\n <svg viewBox=\"0 0 24 24\" className={s.chevron()} fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" aria-hidden>\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n </Nav.Trigger>\n <Nav.Content className={cn(s.panel(), columns === 2 && \"md:grid-cols-2\")}>{children}</Nav.Content>\n </Nav.Item>\n );\n}\n\nexport type NavBarMenuLinkProps = Omit<React.ComponentProps<typeof Nav.Link>, \"title\" | \"active\"> & {\n /** The link's name — passed translated. */\n title: string;\n /** One line under it — passed translated. */\n description?: string;\n /** An icon (a signature icon of `@krizaka/icons`: its node lights up on hover). */\n icon?: React.ReactNode;\n /** The current page. */\n active?: boolean;\n};\n\n/** A link inside a menu: an icon, a name and a line of text. */\nexport function NavBarMenuLink({ title, description, icon, active, href, className, asChild, children, ...props }: NavBarMenuLinkProps) {\n const body = (\n <>\n {icon && <span className={s.menuIcon()}>{icon}</span>}\n <span className=\"min-w-0\">\n <span className={s.menuTitle()}>{title}</span>\n {description && <span className={s.menuText()}>{description}</span>}\n </span>\n </>\n );\n return (\n <Nav.Link asChild={asChild} href={asChild ? undefined : href} active={active} aria-current={active ? \"page\" : undefined} data-active={active ? \"\" : undefined} className={s.menuLink({ className })} {...props}>\n {asChild && React.isValidElement<{ children?: React.ReactNode }>(children) ? React.cloneElement(children, undefined, body) : body}\n </Nav.Link>\n );\n}\n\n/** The right side: search, theme, language, the call to action. */\nexport function NavBarActions({ className, ...props }: React.ComponentProps<\"div\">) {\n return <div className={s.actions({ className })} {...props} />;\n}\n\nexport type NavBarMobileProps = React.ComponentProps<\"nav\"> & {\n /** The toggle's name when closed (“Open the menu”) — passed translated. */\n openLabel: string;\n /** The toggle's name when open (“Close the menu”) — passed translated. */\n closeLabel: string;\n};\n\n/**\n * Below `md`: a toggle, and a panel under the bar with its links (`NavBar.MobileLink`). A disclosure: Escape and a click\n * on a link close it, the focus returns to the toggle.\n */\nexport function NavBarMobile({ openLabel, closeLabel, className, children, ...props }: NavBarMobileProps) {\n const { label, open, setOpen, panelId } = useNavBar();\n const toggle = React.useRef<HTMLButtonElement>(null);\n React.useEffect(() => {\n if (!open) return;\n const onKey = (e: KeyboardEvent) => {\n if (e.key !== \"Escape\") return;\n setOpen(false);\n toggle.current?.focus();\n };\n document.addEventListener(\"keydown\", onKey);\n return () => document.removeEventListener(\"keydown\", onKey);\n }, [open, setOpen]);\n return (\n <>\n <button ref={toggle} type=\"button\" aria-expanded={open} aria-controls={panelId} aria-label={open ? closeLabel : openLabel} onClick={() => setOpen(!open)} className={s.toggle()}>\n <svg viewBox=\"0 0 24 24\" className=\"h-4.5 w-4.5\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" aria-hidden>\n {open ? <path d=\"M18 6 6 18M6 6l12 12\" /> : <path d=\"M4 7h16M4 12h16M4 17h10\" />}\n </svg>\n </button>\n {open && (\n <nav\n id={panelId}\n aria-label={label}\n className={s.mobile({ className })}\n onClick={(e) => {\n if ((e.target as Element).closest(\"a\")) setOpen(false);\n }}\n {...props}\n >\n <MobileContext.Provider value>{children}</MobileContext.Provider>\n </nav>\n )}\n </>\n );\n}\n\nexport type NavBarMobileLinkProps = React.ComponentProps<\"a\"> & {\n /** The current page. */\n active?: boolean;\n /** Renders your router's `<Link>`. */\n asChild?: boolean;\n};\n\n/** A link of the mobile panel. */\nexport function NavBarMobileLink({ active, asChild, className, ...props }: NavBarMobileLinkProps) {\n const Comp = asChild ? Slot.Root : \"a\";\n return <Comp aria-current={active ? \"page\" : undefined} className={s.mobileLink({ className })} {...props} />;\n}\n\n\nconst tagTone = {\n upcoming: \"bg-accent-soft text-fg ring-1 ring-inset ring-accent/40\",\n construction: \"bg-warning/15 text-fg ring-1 ring-inset ring-warning/40\",\n current: \"bg-surface-3 text-fg-secondary\",\n};\n\n/** A site's name and its tags: status when not released, “You are here” on the current one. */\nfunction FamilyName({ site, current, labels }: { site: Site; current: boolean; labels: FamilyLabels }) {\n return (\n <span className={s.familyName()}>\n {site.name}\n {site.status !== \"released\" && <span className={cn(s.familyTag(), tagTone[site.status])}>{labels.status[site.status]}</span>}\n {current && <span className={cn(s.familyTag(), tagTone.current)}>{labels.current}</span>}\n </span>\n );\n}\n\nexport type NavBarFamilyProps = {\n /** The site this bar belongs to (`@krizaka/ui/sites`): marked in the family, `aria-current=\"true\"`. */\n current: SiteId;\n /**\n * The family's words, passed translated: `familyLabels.fr` from `@krizaka/ui/sites`, or your own of the same shape.\n * @default familyLabels.en\n */\n labels?: FamilyLabels;\n /** Opens the panel at first render (a story, a screenshot). */\n defaultOpen?: boolean;\n /** Classes of the switcher (or, inside `NavBar.Mobile`, of the family's group). */\n className?: string;\n};\n\n/**\n * The family switcher, attached to the brand (place it right after `NavBar.Brand`): a chevron that opens every site of\n * Krizaka grouped — Krizaka · Products · Open source · GitHub — the current one marked. It opens on click, Enter, Space\n * or ↓ (never on hover); ↑ ↓ walk the sites, Escape closes and returns the focus. Hidden below `md`: place a second\n * `NavBar.Family` as the last child of `NavBar.Mobile`, where it renders as the panel's last group.\n */\nexport function NavBarFamily({ current, labels = familyLabels.en, defaultOpen, className }: NavBarFamilyProps) {\n const inMobile = React.useContext(MobileContext);\n const id = React.useId();\n const groups = sitesByGroup();\n if (inMobile) {\n return (\n <div role=\"group\" aria-labelledby={`${id}-family`} className={s.mobileFamily({ className })}>\n <p id={`${id}-family`} className={s.familyGroupTitle()}>\n {labels.family}\n </p>\n {groups.map(({ group, sites }) => (\n <div key={group}>\n <p id={`${id}-${group}`} className={s.familyGroupTitle()}>\n {labels.groups[group]}\n </p>\n <ul aria-labelledby={`${id}-${group}`} className=\"grid gap-0.5\">\n {sites.map((site) => (\n <li key={site.id}>\n <a href={site.url} data-current={site.id === current ? \"\" : undefined} aria-current={site.id === current ? \"true\" : undefined} className={s.mobileFamilyLink()}>\n <span className={s.familyMark()}>\n <FamilyMark mark={site.mark} size={24} />\n </span>\n <FamilyName site={site} current={site.id === current} labels={labels} />\n </a>\n </li>\n ))}\n </ul>\n </div>\n ))}\n </div>\n );\n }\n // Click only: a pointer passing over the brand never opens the family (Radix opens its menus on hover by default).\n const noHover = (e: React.PointerEvent) => e.preventDefault();\n const columns = [groups.filter((g) => g.group === \"krizaka\" || g.group === \"products\"), groups.filter((g) => g.group === \"open-source\" || g.group === \"github\")];\n return (\n <Nav.Root aria-label={labels.family} defaultValue={defaultOpen ? \"family\" : undefined} className={s.family({ className })}>\n <Nav.List className=\"flex\">\n <Nav.Item value=\"family\">\n <Nav.Trigger aria-label={labels.family} onPointerMove={noHover} onPointerLeave={noHover} className={s.familyTrigger()}>\n <svg viewBox=\"0 0 24 24\" className={s.chevron()} fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" aria-hidden>\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n </Nav.Trigger>\n <Nav.Content onPointerLeave={noHover} className={s.familyPanel()}>\n {columns.map((column, i) => (\n <div key={i} className=\"grid content-start gap-3\">\n {column.map(({ group, sites }) => (\n <div key={group}>\n <p id={`${id}-${group}`} className={s.familyGroupTitle()}>\n {labels.groups[group]}\n </p>\n <ul aria-labelledby={`${id}-${group}`} className=\"grid gap-0.5\">\n {sites.map((site) => (\n <li key={site.id}>\n <Nav.Link href={site.url} data-current={site.id === current ? \"\" : undefined} aria-current={site.id === current ? \"true\" : undefined} className={s.familyLink()}>\n <span className={s.familyMark()}>\n <FamilyMark mark={site.mark} size={28} />\n </span>\n <span className=\"min-w-0\">\n <FamilyName site={site} current={site.id === current} labels={labels} />\n <span className={s.familyText()}>{labels.descriptions[site.id]}</span>\n </span>\n </Nav.Link>\n </li>\n ))}\n </ul>\n </div>\n ))}\n </div>\n ))}\n </Nav.Content>\n </Nav.Item>\n </Nav.List>\n <Nav.Viewport onPointerLeave={noHover} className={s.familyViewport()} />\n </Nav.Root>\n );\n}\n\nexport type NavBarBadgeProps = React.ComponentProps<\"span\"> & {\n /** The environment, when it is not production (`DEV`). */\n env?: string;\n /** The version the site runs (`1.2.3`, shown `v1.2.3`). */\n version?: string;\n};\n\n/** A small mono badge beside the brand: the environment and the version (`DEV · v1.2.3`). Hidden below `sm`. */\nexport function NavBarBadge({ env, version, className, children, ...props }: NavBarBadgeProps) {\n const parts = [env, version && `v${version.replace(/^v/, \"\")}`].filter(Boolean);\n return (\n <span className={s.badge({ className })} {...props}>\n {parts.join(\" · \")}\n {children}\n </span>\n );\n}\n\nexport type NavBarRepoProps = Omit<React.ComponentProps<\"a\">, \"children\"> & {\n /** The repository the site is built from. */\n href: string;\n /** The link's accessible name (“Source on GitHub”) — passed translated. */\n label: string;\n};\n\n/** The site's repository on GitHub, an icon link of `NavBar.Actions`. */\nexport function NavBarRepo({ label, className, ...props }: NavBarRepoProps) {\n return (\n <a aria-label={label} className={s.repo({ className })} {...props}>\n <GitHubGlyph size={18} />\n </a>\n );\n}\n\n/**\n * `NavBar.Root/Brand/Family/Badge/Items/Link/Menu/MenuLink/Actions/Repo/Mobile/MobileLink` — the Krizaka navigation bar,\n * the same on every site of the family: floating, tightening on scroll, the family switcher on the brand, one light\n * gliding between its items, accessible menus, a mobile panel.\n */\nexport const NavBar = {\n Root: NavBarRoot,\n Brand: NavBarBrand,\n Family: NavBarFamily,\n Badge: NavBarBadge,\n Items: NavBarItems,\n Link: NavBarLink,\n Menu: NavBarMenu,\n MenuLink: NavBarMenuLink,\n Actions: NavBarActions,\n Repo: NavBarRepo,\n Mobile: NavBarMobile,\n MobileLink: NavBarMobileLink,\n};\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
interface ShowcaseLabels {
|
|
4
|
+
/** The previous button's name. */
|
|
5
|
+
previous: string;
|
|
6
|
+
/** The next button's name. */
|
|
7
|
+
next: string;
|
|
8
|
+
/** The pause button's name while it plays. */
|
|
9
|
+
pause: string;
|
|
10
|
+
/** The same button's name while it is paused. */
|
|
11
|
+
play: string;
|
|
12
|
+
/** A progress segment's name: `(3, 17) => "Go to image 3"`. */
|
|
13
|
+
goTo: (n: number, total: number) => string;
|
|
14
|
+
/** The position in words, beside the title: `(1, 17) => "Image 1 of 17"`. */
|
|
15
|
+
counter: (n: number, total: number) => string;
|
|
16
|
+
/** The slide's accessible name: `(1, 17) => "1 of 17"`. */
|
|
17
|
+
slide: (n: number, total: number) => string;
|
|
18
|
+
}
|
|
19
|
+
/** English defaults — pass your own translated `labels`. */
|
|
20
|
+
declare const showcaseLabels: ShowcaseLabels;
|
|
21
|
+
interface ShowcaseSlideState {
|
|
22
|
+
index: number;
|
|
23
|
+
/** The slide in view. */
|
|
24
|
+
active: boolean;
|
|
25
|
+
}
|
|
26
|
+
interface ShowcaseProps<T> extends Omit<React.ComponentProps<"section">, "children" | "onChange"> {
|
|
27
|
+
/** The slideshow's accessible name (“Prompt to image”), passed translated. */
|
|
28
|
+
label: string;
|
|
29
|
+
/** The slides, in order. */
|
|
30
|
+
items: readonly T[];
|
|
31
|
+
/** A stable key for an item. */
|
|
32
|
+
getId: (item: T) => string;
|
|
33
|
+
/** One slide's content. Only the slide in view and its neighbours are mounted (the rest stay empty): give slides the same size. */
|
|
34
|
+
renderItem: (item: T, state: ShowcaseSlideState) => React.ReactNode;
|
|
35
|
+
/** A slide's title, shown before the counter (“Golden-hour editorial”). */
|
|
36
|
+
getTitle?: (item: T) => string;
|
|
37
|
+
/** Milliseconds a slide stays (the time the segment takes to fill). @default 6000 */
|
|
38
|
+
interval?: number;
|
|
39
|
+
/** Advances by itself. Never under `prefers-reduced-motion`. @default true */
|
|
40
|
+
autoplay?: boolean;
|
|
41
|
+
/** `fade` crossfades; `slide` also moves the slides a few pixels. @default "fade" */
|
|
42
|
+
transition?: "fade" | "slide";
|
|
43
|
+
/** After the last slide, go back to the first. @default true */
|
|
44
|
+
loop?: boolean;
|
|
45
|
+
/** The slide in view (controlled). */
|
|
46
|
+
index?: number;
|
|
47
|
+
/** The slide shown first. @default 0 */
|
|
48
|
+
defaultIndex?: number;
|
|
49
|
+
/** Called when the slide in view changes — `user` is true when the visitor asked for it. */
|
|
50
|
+
onIndexChange?: (index: number, user: boolean) => void;
|
|
51
|
+
/** The words of the controls, translated. */
|
|
52
|
+
labels?: ShowcaseLabels;
|
|
53
|
+
}
|
|
54
|
+
/** An auto-advancing slideshow with a visible, clickable progress bar, a counter, prev / next and a pause button. */
|
|
55
|
+
declare function Showcase<T>({ label, items, getId, renderItem, getTitle, interval, autoplay, transition, loop, index: controlled, defaultIndex, onIndexChange, labels, className, onKeyDown, onFocus, onBlur, onPointerEnter, onPointerLeave, ...props }: ShowcaseProps<T>): React.JSX.Element;
|
|
56
|
+
/**
|
|
57
|
+
* The typed reveal of a text, kept minimal: the visible prefix grows at `speed` characters per second while `active`;
|
|
58
|
+
* under reduced motion (or when not active) it is the whole text at once. Render the full text for assistive technology
|
|
59
|
+
* (`sr-only`) and this one `aria-hidden`.
|
|
60
|
+
*/
|
|
61
|
+
declare function useTypedText(text: string, { active, speed }?: {
|
|
62
|
+
active?: boolean;
|
|
63
|
+
speed?: number;
|
|
64
|
+
}): {
|
|
65
|
+
text: string;
|
|
66
|
+
done: boolean;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export { Showcase, type ShowcaseLabels, type ShowcaseProps, type ShowcaseSlideState, showcaseLabels, useTypedText };
|