Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 6 additions & 7 deletions apps/registry/app/components/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,12 @@ const STORYBOOK_URL =
process.env.NEXT_PUBLIC_STORYBOOK_URL ?? "http://localhost:6006";

export async function generateStaticParams() {
return registry.items
.filter(
(item): item is RegistryComponent => item.type === "registry:component",
)
.map((item) => ({
slug: item.name,
}));
return registry.items.reduce<{ slug: string }[]>((params, item) => {
if (item.type === "registry:component") {
params.push({ slug: item.name });
}
return params;
}, []);
}

function getNpmUrl(packageName: string): string {
Expand Down
13 changes: 10 additions & 3 deletions apps/registry/app/llms-full.txt/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,15 @@ async function buildLlmsFullTxt(): Promise<string> {
lines.push("```");
lines.push("");

for (const page of DOC_PAGES) {
const body = await readDocPage(page.slug);
const docPages = await Promise.all(
DOC_PAGES.map(async (page) => ({
...page,
body: await readDocPage(page.slug),
})),
);

for (const page of docPages) {
const { body } = page;
if (!body) continue;
lines.push(`## ${page.title}`);
lines.push("");
Expand All @@ -83,7 +90,7 @@ async function buildLlmsFullTxt(): Promise<string> {
);
lines.push("");

for (const item of [...items].sort((a, b) => a.name.localeCompare(b.name))) {
for (const item of items.toSorted((a, b) => a.name.localeCompare(b.name))) {
lines.push(`### ${item.title}`);
lines.push("");
lines.push(`- Slug: \`${item.name}\``);
Expand Down
2 changes: 1 addition & 1 deletion apps/registry/app/llms.txt/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ function buildLlmsTxt(): string {
const label = CATEGORY_LABEL[category] ?? category;
lines.push(`## Components — ${label}`);
lines.push("");
for (const item of [...bucket].sort((a, b) => a.name.localeCompare(b.name))) {
for (const item of bucket.toSorted((a, b) => a.name.localeCompare(b.name))) {
lines.push(
`- [${item.title}](${SITE_URL}/components/${item.name}): ${item.description}`,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1033,10 +1033,10 @@ function StepNavigationPreview() {
canPrev={step > 1}
currentStep={step}
onNext={() => {
setStep(step + 1);
setStep((currentStep) => currentStep + 1);
}}
onPrev={() => {
setStep(step - 1);
setStep((currentStep) => currentStep - 1);
}}
stepLabel="Step"
totalSteps={5}
Expand Down
19 changes: 12 additions & 7 deletions apps/registry/components/header/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,18 @@ export function Header() {
{ href: "/components", title: "Components" },
];

const searchItems = registry.items
.filter((item) => item.type === "registry:component")
.map((item) => ({
description: item.description,
id: item.name,
title: item.title,
}));
const searchItems = registry.items.reduce<
{ description?: string; id: string; title: string }[]
>((items, item) => {
if (item.type === "registry:component") {
items.push({
description: item.description,
id: item.name,
title: item.title,
});
}
return items;
}, []);

return (
<NavbarSaas
Expand Down
9 changes: 4 additions & 5 deletions apps/registry/components/storybook-embed/storybook-embed.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -147,15 +147,14 @@ export function StorybookEmbed({
height = 400,
storyId,
}: StorybookEmbedProps): React.ReactElement {
const [hasManualThemeSelection, setHasManualThemeSelection] =
React.useState(false);
const hasManualThemeSelectionRef = React.useRef(false);
const [previewTheme, setPreviewTheme] = React.useState<null | PreviewTheme>(
null,
);
const resolvedStoryId = storyId ?? toStoryId(componentName);

React.useEffect(() => {
if (hasManualThemeSelection) {
if (hasManualThemeSelectionRef.current) {
return;
}

Expand All @@ -180,7 +179,7 @@ export function StorybookEmbed({
observer.disconnect();
mediaQuery.removeEventListener("change", updateTheme);
};
}, [hasManualThemeSelection]);
}, []);

const iframeSource = React.useMemo(() => {
if (previewTheme === null) {
Expand All @@ -194,7 +193,7 @@ export function StorybookEmbed({
<div className={className}>
<PreviewThemeControls
onValueChange={(value) => {
setHasManualThemeSelection(true);
hasManualThemeSelectionRef.current = true;
setPreviewTheme(value);
}}
value={previewTheme}
Expand Down
40 changes: 28 additions & 12 deletions apps/registry/lib/sidebar-sections.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,19 @@ import type {
const registry = registryData as Registry;

const components = registry.items
.filter(
(item): item is RegistryComponent => item.type === "registry:component",
.reduce<{ category?: ComponentCategory; name: string; title: string }[]>(
(items, item) => {
if (item.type === "registry:component") {
items.push({
category: item.category,
name: item.name,
title: item.title,
});
}
return items;
},
[],
)
.map((item) => ({
category: item.category,
name: item.name,
title: item.title,
}))
.sort((a, b) => a.title.localeCompare(b.title));

const categoryLabels: Record<ComponentCategory, string> = {
Expand Down Expand Up @@ -53,13 +58,24 @@ function groupComponentsByCategory(
return accumulator;
}, new Map<ComponentCategory, { name: string; title: string }[]>());

return categoryOrder
.filter((cat) => grouped.has(cat))
.map((category) => ({
const sections: {
category: ComponentCategory;
items: { name: string; title: string }[];
label: string;
}[] = [];

for (const category of categoryOrder) {
const items = grouped.get(category);
if (items) {
sections.push({
category,
items: grouped.get(category) ?? [],
items,
label: categoryLabels[category],
}));
});
}
}

return sections;
}

const groupedComponents = groupComponentsByCategory(components);
Expand Down
16 changes: 13 additions & 3 deletions apps/registry/lib/stats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,17 @@ export function getFeaturedComponents(): readonly RegistryItem[] {
"timeline",
"globe-3d",
];
return featuredSlugs
.map((slug) => REGISTRY.items.find((item) => item.name === slug))
.filter((item): item is RegistryItem => item !== undefined);
const registryByName = new Map<string, RegistryItem>();
for (const item of REGISTRY.items) {
registryByName.set(item.name, item);
}

const featured: RegistryItem[] = [];
for (const slug of featuredSlugs) {
const item = registryByName.get(slug);
if (item) {
featured.push(item);
}
}
return featured;
}
2 changes: 1 addition & 1 deletion apps/registry/registry/default/auto-reload/auto-reload.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ function getCurrencyFormatter(
const key = `${locale}|${currency}`;
let formatter = CURRENCY_FORMATTER_CACHE.get(key);
if (!formatter) {
formatter = new Intl.NumberFormat(locale, {
formatter = Intl.NumberFormat(locale, {
currency,
style: "currency",
});
Expand Down
22 changes: 16 additions & 6 deletions apps/registry/registry/default/carousel/carousel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
useContext,
useEffect,
useMemo,
useRef,
useState,
} from "react";

Expand Down Expand Up @@ -82,6 +83,11 @@ function useCarouselLogic({
setCanScrollPrevious(api.canScrollPrev());
setCanScrollNext(api.canScrollNext());
}, []);
const onSelectReference = useRef(onSelect);

useEffect(() => {
onSelectReference.current = onSelect;
}, [onSelect]);

const scrollPrevious = useCallback(() => {
api?.scrollPrev();
Expand Down Expand Up @@ -117,19 +123,23 @@ function useCarouselLogic({
return;
}

api.on("reInit", onSelect);
api.on("select", onSelect);
const notifySelection = (selectedApi: CarouselApi) => {
onSelectReference.current(selectedApi);
};

api.on("reInit", notifySelection);
api.on("select", notifySelection);

const rafId = requestAnimationFrame(() => {
onSelect(api);
notifySelection(api);
});

return () => {
api?.off("select", onSelect);
api?.off("reInit", onSelect);
api?.off("select", notifySelection);
api?.off("reInit", notifySelection);
cancelAnimationFrame(rafId);
};
}, [api, onSelect]);
}, [api]);

return {
api,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client";

import { memo, useCallback, useEffect, useRef } from "react";
import { memo, useEffect, useRef } from "react";

import type { ReactNode } from "react";

Expand Down Expand Up @@ -125,8 +125,12 @@ function CompletionDialogImpl({
onConfirm,
title,
}: CompletionDialogProps): React.ReactNode {
const handleKeyDown = useCallback(
(event: KeyboardEvent) => {
const keyDownHandlerRef = useRef<(event: KeyboardEvent) => void>(() => {
return;
});

useEffect(() => {
keyDownHandlerRef.current = (event: KeyboardEvent) => {
if (!isOpen) return;
if (event.key === "Escape") {
event.preventDefault();
Expand All @@ -148,17 +152,20 @@ function CompletionDialogImpl({
event.stopPropagation();
onCancel();
}
},
[isOpen, onClose, onConfirm, onCancel, confirmShortcut, cancelShortcut],
);
};
}, [cancelShortcut, confirmShortcut, isOpen, onCancel, onClose, onConfirm]);

useEffect(() => {
if (!isOpen) return;
document.addEventListener("keydown", handleKeyDown, true);
const onDocumentKeyDown = (event: KeyboardEvent) => {
keyDownHandlerRef.current(event);
};

document.addEventListener("keydown", onDocumentKeyDown, true);
return () => {
document.removeEventListener("keydown", handleKeyDown, true);
document.removeEventListener("keydown", onDocumentKeyDown, true);
};
}, [isOpen, handleKeyDown]);
}, [isOpen]);

if (!isOpen) return null;

Expand Down
24 changes: 13 additions & 11 deletions apps/registry/registry/default/content-intro/content-intro.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client";

import { memo, useCallback, useEffect } from "react";
import { memo, useEffect, useRef } from "react";

import type { ReactNode } from "react";

Expand Down Expand Up @@ -64,23 +64,25 @@ function ContentIntroImpl({
}: ContentIntroProps): React.ReactNode {
const mergedLabels = { ...DEFAULT_LABELS, ...labels };
const hasProgress = completedSections.size > 0;
const onStartRef = useRef(onStart);

const handleKeyDown = useCallback(
(event: KeyboardEvent) => {
useEffect(() => {
onStartRef.current = onStart;
}, [onStart]);

useEffect(() => {
const onDocumentKeyDown = (event: KeyboardEvent) => {
if (event.key === "Enter") {
event.preventDefault();
onStart();
onStartRef.current();
}
},
[onStart],
);
};

useEffect(() => {
document.addEventListener("keydown", handleKeyDown);
document.addEventListener("keydown", onDocumentKeyDown);
return () => {
document.removeEventListener("keydown", handleKeyDown);
document.removeEventListener("keydown", onDocumentKeyDown);
};
}, [handleKeyDown]);
}, []);

return (
<>
Expand Down
12 changes: 6 additions & 6 deletions apps/registry/registry/default/filter-bar/filter-bar.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client";

import { memo, useCallback, useState } from "react";
import { memo, useCallback, useTransition } from "react";

import { cn } from "@vllnt/ui";
import { Badge } from "@vllnt/ui";
Expand Down Expand Up @@ -263,16 +263,16 @@ function FilterBarImpl({
searchQuery,
tags,
}: FilterBarProps): React.ReactNode {
const [isPending, setIsPending] = useState(false);
const [isPending, startTransition] = useTransition();
const mergedLabels = { ...DEFAULT_LABELS, ...labels };

const handleDifficultyChange = useCallback(
(difficulty: string): void => {
setIsPending(true);
onFiltersChange({ difficulty });
setIsPending(false);
startTransition(() => {
onFiltersChange({ difficulty });
});
},
[onFiltersChange],
[onFiltersChange, startTransition],
);

const handleSearchChange = useCallback(
Expand Down
Loading
Loading