@hypoth-ui/docs-renderer-next 0.1.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/LICENSE +21 -0
- package/README.md +44 -0
- package/app/accessibility/CategoryFilter.tsx +123 -0
- package/app/accessibility/ConformanceTable.tsx +109 -0
- package/app/accessibility/StatusBadge.tsx +47 -0
- package/app/accessibility/[component]/page.tsx +166 -0
- package/app/accessibility/page.tsx +207 -0
- package/app/api/search/route.ts +241 -0
- package/app/components/[id]/page.tsx +316 -0
- package/app/edition-upgrade/page.tsx +76 -0
- package/app/guides/[id]/page.tsx +67 -0
- package/app/layout.tsx +93 -0
- package/app/page.tsx +29 -0
- package/components/branding/header.tsx +82 -0
- package/components/branding/logo.tsx +54 -0
- package/components/feedback/feedback-widget.tsx +263 -0
- package/components/live-example.tsx +477 -0
- package/components/mdx/edition.tsx +149 -0
- package/components/mdx-renderer.tsx +90 -0
- package/components/nav-sidebar.tsx +269 -0
- package/components/search/search-input.tsx +508 -0
- package/components/theme-init-script.tsx +35 -0
- package/components/theme-switcher.tsx +166 -0
- package/components/tokens-used.tsx +135 -0
- package/components/upgrade/upgrade-prompt.tsx +141 -0
- package/dist/index.d.ts +60 -0
- package/dist/index.js +751 -0
- package/package.json +66 -0
- package/styles/globals.css +613 -0
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import Link from "next/link";
|
|
4
|
+
|
|
5
|
+
interface TokensUsedProps {
|
|
6
|
+
tokens: string[];
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Display tokens used by a component
|
|
11
|
+
* Links each token to its documentation page
|
|
12
|
+
*/
|
|
13
|
+
export function TokensUsed({ tokens }: TokensUsedProps) {
|
|
14
|
+
if (!tokens || tokens.length === 0) {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Group tokens by category
|
|
19
|
+
const tokensByCategory = new Map<string, string[]>();
|
|
20
|
+
|
|
21
|
+
for (const token of tokens) {
|
|
22
|
+
const parts = token.split(".");
|
|
23
|
+
const category = parts[0];
|
|
24
|
+
if (!category) continue;
|
|
25
|
+
if (!tokensByCategory.has(category)) {
|
|
26
|
+
tokensByCategory.set(category, []);
|
|
27
|
+
}
|
|
28
|
+
tokensByCategory.get(category)?.push(token);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const categories = Array.from(tokensByCategory.keys()).sort();
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<section className="tokens-used">
|
|
35
|
+
<h2>Design Tokens</h2>
|
|
36
|
+
<p className="tokens-used-intro">
|
|
37
|
+
This component uses the following design tokens for theming:
|
|
38
|
+
</p>
|
|
39
|
+
|
|
40
|
+
<div className="tokens-used-categories">
|
|
41
|
+
{categories.map((category) => (
|
|
42
|
+
<div key={category} className="tokens-used-category">
|
|
43
|
+
<h3>
|
|
44
|
+
<Link href={`/tokens/${category}`}>{formatCategoryName(category)}</Link>
|
|
45
|
+
</h3>
|
|
46
|
+
<ul className="tokens-used-list">
|
|
47
|
+
{(tokensByCategory.get(category) ?? []).map((token) => (
|
|
48
|
+
<li key={token}>
|
|
49
|
+
<code className="token-path">{token}</code>
|
|
50
|
+
<code className="token-css-var">var(--{token.replace(/\./g, "-")})</code>
|
|
51
|
+
</li>
|
|
52
|
+
))}
|
|
53
|
+
</ul>
|
|
54
|
+
</div>
|
|
55
|
+
))}
|
|
56
|
+
</div>
|
|
57
|
+
|
|
58
|
+
<style jsx>{`
|
|
59
|
+
.tokens-used {
|
|
60
|
+
margin-top: 2rem;
|
|
61
|
+
padding: 1.5rem;
|
|
62
|
+
background: var(--color-background-subtle, #f9fafb);
|
|
63
|
+
border-radius: var(--radius-md, 6px);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.tokens-used h2 {
|
|
67
|
+
margin: 0 0 0.5rem;
|
|
68
|
+
font-size: 1.25rem;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.tokens-used-intro {
|
|
72
|
+
margin: 0 0 1rem;
|
|
73
|
+
color: var(--color-text-secondary, #6b7280);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.tokens-used-categories {
|
|
77
|
+
display: grid;
|
|
78
|
+
gap: 1rem;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.tokens-used-category h3 {
|
|
82
|
+
margin: 0 0 0.5rem;
|
|
83
|
+
font-size: 1rem;
|
|
84
|
+
text-transform: capitalize;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.tokens-used-category h3 a {
|
|
88
|
+
color: var(--color-primary, #0066cc);
|
|
89
|
+
text-decoration: none;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.tokens-used-category h3 a:hover {
|
|
93
|
+
text-decoration: underline;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.tokens-used-list {
|
|
97
|
+
margin: 0;
|
|
98
|
+
padding: 0;
|
|
99
|
+
list-style: none;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.tokens-used-list li {
|
|
103
|
+
display: flex;
|
|
104
|
+
gap: 1rem;
|
|
105
|
+
padding: 0.5rem 0;
|
|
106
|
+
border-bottom: 1px solid var(--color-border-default, #e5e7eb);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.tokens-used-list li:last-child {
|
|
110
|
+
border-bottom: none;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.token-path {
|
|
114
|
+
font-family: monospace;
|
|
115
|
+
font-size: 0.875rem;
|
|
116
|
+
color: var(--color-text-primary, #111827);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.token-css-var {
|
|
120
|
+
font-family: monospace;
|
|
121
|
+
font-size: 0.875rem;
|
|
122
|
+
color: var(--color-text-secondary, #6b7280);
|
|
123
|
+
}
|
|
124
|
+
`}</style>
|
|
125
|
+
</section>
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Format category name for display
|
|
131
|
+
*/
|
|
132
|
+
function formatCategoryName(category: string): string {
|
|
133
|
+
if (category === "z-index") return "Z-Index";
|
|
134
|
+
return category.charAt(0).toUpperCase() + category.slice(1);
|
|
135
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Upgrade Prompt Component
|
|
3
|
+
*
|
|
4
|
+
* Displays a call-to-action for users to upgrade their edition tier
|
|
5
|
+
* to access premium content and features.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { Edition, UpgradeConfig } from "@hypoth-ui/docs-core";
|
|
9
|
+
|
|
10
|
+
export interface UpgradePromptProps {
|
|
11
|
+
/** Current user edition */
|
|
12
|
+
currentEdition: Edition;
|
|
13
|
+
/** Required edition for access */
|
|
14
|
+
requiredEdition: Edition;
|
|
15
|
+
/** Upgrade configuration from edition config */
|
|
16
|
+
upgradeConfig?: UpgradeConfig;
|
|
17
|
+
/** Component or feature name being blocked */
|
|
18
|
+
itemName?: string;
|
|
19
|
+
/** Component ID (for URL params) */
|
|
20
|
+
componentId?: string;
|
|
21
|
+
/** Visual variant */
|
|
22
|
+
variant?: "inline" | "full-page" | "card";
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Default upgrade configuration
|
|
27
|
+
*/
|
|
28
|
+
const DEFAULT_UPGRADE_CONFIG: UpgradeConfig = {
|
|
29
|
+
url: "/upgrade",
|
|
30
|
+
ctaText: "Upgrade Now",
|
|
31
|
+
message: "Upgrade your plan to access this content.",
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Edition display names
|
|
36
|
+
*/
|
|
37
|
+
const EDITION_NAMES: Record<Edition, string> = {
|
|
38
|
+
core: "Core",
|
|
39
|
+
pro: "Pro",
|
|
40
|
+
enterprise: "Enterprise",
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Edition tier descriptions
|
|
45
|
+
*/
|
|
46
|
+
const EDITION_DESCRIPTIONS: Record<Edition, string> = {
|
|
47
|
+
core: "Basic components for getting started",
|
|
48
|
+
pro: "Advanced features and additional components",
|
|
49
|
+
enterprise: "Full access to all components and features",
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export function UpgradePrompt({
|
|
53
|
+
currentEdition,
|
|
54
|
+
requiredEdition,
|
|
55
|
+
upgradeConfig = DEFAULT_UPGRADE_CONFIG,
|
|
56
|
+
itemName,
|
|
57
|
+
componentId,
|
|
58
|
+
variant = "card",
|
|
59
|
+
}: UpgradePromptProps) {
|
|
60
|
+
const config = { ...DEFAULT_UPGRADE_CONFIG, ...upgradeConfig };
|
|
61
|
+
|
|
62
|
+
// Build upgrade URL with optional component parameter
|
|
63
|
+
const upgradeUrl = componentId
|
|
64
|
+
? `${config.url}?component=${componentId}&from=${currentEdition}&to=${requiredEdition}`
|
|
65
|
+
: `${config.url}?from=${currentEdition}&to=${requiredEdition}`;
|
|
66
|
+
|
|
67
|
+
const message = config.message || DEFAULT_UPGRADE_CONFIG.message;
|
|
68
|
+
|
|
69
|
+
if (variant === "inline") {
|
|
70
|
+
return (
|
|
71
|
+
<span className="upgrade-prompt upgrade-prompt--inline">
|
|
72
|
+
<span className="upgrade-prompt__icon" aria-hidden="true">
|
|
73
|
+
🔒
|
|
74
|
+
</span>
|
|
75
|
+
<span className="upgrade-prompt__text">
|
|
76
|
+
{itemName ? `${itemName} requires ` : "Requires "}
|
|
77
|
+
<strong>{EDITION_NAMES[requiredEdition]}</strong> edition.{" "}
|
|
78
|
+
<a href={upgradeUrl} className="upgrade-prompt__link">
|
|
79
|
+
{config.ctaText}
|
|
80
|
+
</a>
|
|
81
|
+
</span>
|
|
82
|
+
</span>
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (variant === "full-page") {
|
|
87
|
+
return (
|
|
88
|
+
<div className="upgrade-prompt upgrade-prompt--full-page">
|
|
89
|
+
<div className="upgrade-prompt__container">
|
|
90
|
+
<div className="upgrade-prompt__icon" aria-hidden="true">
|
|
91
|
+
🔒
|
|
92
|
+
</div>
|
|
93
|
+
<h1 className="upgrade-prompt__title">
|
|
94
|
+
{itemName ? `${itemName} requires an upgrade` : "Upgrade Required"}
|
|
95
|
+
</h1>
|
|
96
|
+
<p className="upgrade-prompt__message">{message}</p>
|
|
97
|
+
<div className="upgrade-prompt__tiers">
|
|
98
|
+
<div className="upgrade-prompt__tier upgrade-prompt__tier--current">
|
|
99
|
+
<h2>Current: {EDITION_NAMES[currentEdition]}</h2>
|
|
100
|
+
<p>{EDITION_DESCRIPTIONS[currentEdition]}</p>
|
|
101
|
+
</div>
|
|
102
|
+
<div className="upgrade-prompt__arrow" aria-hidden="true">
|
|
103
|
+
→
|
|
104
|
+
</div>
|
|
105
|
+
<div className="upgrade-prompt__tier upgrade-prompt__tier--required">
|
|
106
|
+
<h2>Required: {EDITION_NAMES[requiredEdition]}</h2>
|
|
107
|
+
<p>{EDITION_DESCRIPTIONS[requiredEdition]}</p>
|
|
108
|
+
</div>
|
|
109
|
+
</div>
|
|
110
|
+
<a href={upgradeUrl} className="upgrade-prompt__cta">
|
|
111
|
+
{config.ctaText}
|
|
112
|
+
</a>
|
|
113
|
+
</div>
|
|
114
|
+
</div>
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Default: card variant
|
|
119
|
+
return (
|
|
120
|
+
<div className="upgrade-prompt upgrade-prompt--card">
|
|
121
|
+
<div className="upgrade-prompt__header">
|
|
122
|
+
<span className="upgrade-prompt__icon" aria-hidden="true">
|
|
123
|
+
🔒
|
|
124
|
+
</span>
|
|
125
|
+
<span className="upgrade-prompt__badge">{EDITION_NAMES[requiredEdition]} Edition</span>
|
|
126
|
+
</div>
|
|
127
|
+
<div className="upgrade-prompt__body">
|
|
128
|
+
<h3 className="upgrade-prompt__title">
|
|
129
|
+
{itemName ? `${itemName} requires an upgrade` : "Premium Content"}
|
|
130
|
+
</h3>
|
|
131
|
+
<p className="upgrade-prompt__message">{message}</p>
|
|
132
|
+
</div>
|
|
133
|
+
<div className="upgrade-prompt__footer">
|
|
134
|
+
<span className="upgrade-prompt__current">Your plan: {EDITION_NAMES[currentEdition]}</span>
|
|
135
|
+
<a href={upgradeUrl} className="upgrade-prompt__cta">
|
|
136
|
+
{config.ctaText}
|
|
137
|
+
</a>
|
|
138
|
+
</div>
|
|
139
|
+
</div>
|
|
140
|
+
);
|
|
141
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export * from '@hypoth-ui/docs-core';
|
|
2
|
+
import * as react from 'react';
|
|
3
|
+
import { ReactNode } from 'react';
|
|
4
|
+
|
|
5
|
+
interface SearchInputProps {
|
|
6
|
+
/** Placeholder text */
|
|
7
|
+
placeholder?: string;
|
|
8
|
+
/** Custom class name */
|
|
9
|
+
className?: string;
|
|
10
|
+
/** Whether search is enabled */
|
|
11
|
+
enabled?: boolean;
|
|
12
|
+
}
|
|
13
|
+
declare function SearchInput({ placeholder, className, enabled, }: SearchInputProps): react.JSX.Element | null;
|
|
14
|
+
|
|
15
|
+
interface LiveExampleProps {
|
|
16
|
+
/** The live preview content */
|
|
17
|
+
children: ReactNode;
|
|
18
|
+
/** Source code to display */
|
|
19
|
+
code: string;
|
|
20
|
+
/** Language for syntax highlighting */
|
|
21
|
+
language?: string;
|
|
22
|
+
/** Title for the example */
|
|
23
|
+
title?: string;
|
|
24
|
+
/** Description of what the example demonstrates */
|
|
25
|
+
description?: string;
|
|
26
|
+
/** Whether to show code by default */
|
|
27
|
+
defaultShowCode?: boolean;
|
|
28
|
+
/** Available variants/tabs */
|
|
29
|
+
variants?: Array<{
|
|
30
|
+
name: string;
|
|
31
|
+
code: string;
|
|
32
|
+
preview: ReactNode;
|
|
33
|
+
}>;
|
|
34
|
+
/** Custom class name */
|
|
35
|
+
className?: string;
|
|
36
|
+
}
|
|
37
|
+
declare function LiveExample({ children, code, language, title, description, defaultShowCode, variants, className, }: LiveExampleProps): react.JSX.Element;
|
|
38
|
+
/**
|
|
39
|
+
* Simple code block without live preview
|
|
40
|
+
*/
|
|
41
|
+
interface CodeBlockProps {
|
|
42
|
+
/** Source code to display */
|
|
43
|
+
code: string;
|
|
44
|
+
/** Language for syntax highlighting */
|
|
45
|
+
language?: string;
|
|
46
|
+
/** Filename to display */
|
|
47
|
+
filename?: string;
|
|
48
|
+
/** Whether to show line numbers */
|
|
49
|
+
showLineNumbers?: boolean;
|
|
50
|
+
/** Lines to highlight */
|
|
51
|
+
highlightLines?: number[];
|
|
52
|
+
/** Custom class name */
|
|
53
|
+
className?: string;
|
|
54
|
+
}
|
|
55
|
+
declare function CodeBlock({ code, language, filename, showLineNumbers, highlightLines, className, }: CodeBlockProps): react.JSX.Element;
|
|
56
|
+
|
|
57
|
+
declare const COMPONENTS_PATH = "./components";
|
|
58
|
+
declare const STYLES_PATH = "./styles";
|
|
59
|
+
|
|
60
|
+
export { COMPONENTS_PATH, CodeBlock, type CodeBlockProps, LiveExample, type LiveExampleProps, STYLES_PATH, SearchInput, type SearchInputProps };
|