docu v 1.11.0
This commit is contained in:
102
components/markdown/KeyboardMdx.tsx
Normal file
102
components/markdown/KeyboardMdx.tsx
Normal file
@@ -0,0 +1,102 @@
|
||||
import React from 'react';
|
||||
|
||||
// Map of special keys to their Mac symbols
|
||||
const macKeyMap: Record<string, string> = {
|
||||
command: '⌘',
|
||||
cmd: '⌘',
|
||||
option: '⌥',
|
||||
alt: '⌥',
|
||||
shift: '⇧',
|
||||
ctrl: '⌃',
|
||||
control: '⌃',
|
||||
tab: '⇥',
|
||||
caps: '⇪',
|
||||
enter: '⏎',
|
||||
return: '⏎',
|
||||
delete: '⌫',
|
||||
escape: '⎋',
|
||||
esc: '⎋',
|
||||
up: '↑',
|
||||
down: '↓',
|
||||
left: '←',
|
||||
right: '→',
|
||||
space: '␣',
|
||||
};
|
||||
|
||||
// Map of special keys to their Windows display text
|
||||
const windowsKeyMap: Record<string, string> = {
|
||||
command: 'Win',
|
||||
cmd: 'Win',
|
||||
option: 'Alt',
|
||||
alt: 'Alt',
|
||||
ctrl: 'Ctrl',
|
||||
control: 'Ctrl',
|
||||
delete: 'Del',
|
||||
escape: 'Esc',
|
||||
esc: 'Esc',
|
||||
enter: 'Enter',
|
||||
return: 'Enter',
|
||||
tab: 'Tab',
|
||||
caps: 'Caps',
|
||||
shift: 'Shift',
|
||||
space: 'Space',
|
||||
up: '↑',
|
||||
down: '↓',
|
||||
left: '←',
|
||||
right: '→',
|
||||
};
|
||||
|
||||
export interface KbdProps extends React.HTMLAttributes<HTMLElement> {
|
||||
/** The key to display (e.g., 'cmd', 'ctrl', 'a') */
|
||||
show?: string;
|
||||
/** Platform style - 'window' or 'mac' */
|
||||
type?: 'window' | 'mac';
|
||||
/** Custom content to display (overrides automatic rendering) */
|
||||
children?: React.ReactNode;
|
||||
}
|
||||
|
||||
const KbdComponent: React.FC<KbdProps> = ({
|
||||
show: keyProp,
|
||||
type = 'window',
|
||||
children,
|
||||
...props
|
||||
}) => {
|
||||
// Get the display text based on the key and type
|
||||
const getKeyDisplay = (): React.ReactNode => {
|
||||
if (!keyProp || typeof keyProp !== 'string') return null;
|
||||
|
||||
const lowerKey = keyProp.toLowerCase();
|
||||
|
||||
// For Mac type, return the symbol if it exists
|
||||
if (type === 'mac') {
|
||||
return macKeyMap[lowerKey] || keyProp;
|
||||
}
|
||||
|
||||
// For Windows, return the formatted key if it exists, otherwise capitalize the first letter
|
||||
return windowsKeyMap[lowerKey] || (keyProp.charAt(0).toUpperCase() + keyProp.slice(1));
|
||||
};
|
||||
|
||||
// Determine what to render
|
||||
const renderContent = () => {
|
||||
// If children are provided, always use them
|
||||
if (children !== undefined && children !== null && children !== '') {
|
||||
return children;
|
||||
}
|
||||
// Otherwise use the generated display
|
||||
return getKeyDisplay() || keyProp || '';
|
||||
};
|
||||
|
||||
return (
|
||||
<kbd
|
||||
className="inline-flex items-center justify-center px-2 py-1 mx-0.5 text-xs font-mono font-medium text-gray-800 bg-gray-100 border border-gray-300 rounded-md dark:bg-gray-700 dark:text-gray-200 dark:border-gray-600"
|
||||
{...props}
|
||||
>
|
||||
{renderContent()}
|
||||
</kbd>
|
||||
);
|
||||
};
|
||||
|
||||
// Export the component
|
||||
export const Kbd = KbdComponent;
|
||||
// Default export for backward compatibility
|
||||
export default KbdComponent;
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ComponentProps } from "react";
|
||||
import Copy from "./copy";
|
||||
import Copy from "./CopyMdx";
|
||||
|
||||
export default function Pre({
|
||||
children,
|
||||
109
components/markdown/ReleaseMdx.tsx
Normal file
109
components/markdown/ReleaseMdx.tsx
Normal file
@@ -0,0 +1,109 @@
|
||||
import React, { PropsWithChildren } from 'react';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { PlusCircle, Wrench, Zap, AlertTriangle, XCircle } from 'lucide-react';
|
||||
|
||||
interface ReleaseProps extends PropsWithChildren {
|
||||
version: string;
|
||||
title: string;
|
||||
date?: string;
|
||||
}
|
||||
|
||||
function Release({ version, title, date, children }: ReleaseProps) {
|
||||
|
||||
return (
|
||||
<div className="mb-16 group">
|
||||
<div className="mb-6">
|
||||
<div className="flex items-center gap-3 mb-2">
|
||||
<div className="bg-primary/10 text-primary border-2 border-primary/20 rounded-full px-4 py-1.5 text-base font-medium">
|
||||
v{version}
|
||||
</div>
|
||||
{date && (
|
||||
<div className="text-muted-foreground text-sm">
|
||||
{new Date(date).toLocaleDateString('en-US', {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric'
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<h2 className="text-2xl font-bold text-foreground/90 mb-3">
|
||||
{title}
|
||||
</h2>
|
||||
</div>
|
||||
<div className="space-y-8">
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
interface ChangesProps extends PropsWithChildren {
|
||||
type: 'added' | 'fixed' | 'improved' | 'deprecated' | 'removed';
|
||||
}
|
||||
|
||||
const typeConfig = {
|
||||
added: {
|
||||
label: 'Added',
|
||||
className: 'bg-green-100 dark:bg-green-900/50 text-green-700 dark:text-green-300',
|
||||
icon: PlusCircle,
|
||||
},
|
||||
fixed: {
|
||||
label: 'Fixed',
|
||||
className: 'bg-yellow-100 dark:bg-yellow-900/50 text-yellow-700 dark:text-yellow-300',
|
||||
icon: Wrench,
|
||||
},
|
||||
improved: {
|
||||
label: 'Improved',
|
||||
className: 'bg-cyan-100 dark:bg-cyan-900/50 text-cyan-700 dark:text-cyan-300',
|
||||
icon: Zap,
|
||||
},
|
||||
deprecated: {
|
||||
label: 'Deprecated',
|
||||
className: 'bg-orange-100 dark:bg-orange-900/50 text-orange-700 dark:text-orange-300',
|
||||
icon: AlertTriangle,
|
||||
},
|
||||
removed: {
|
||||
label: 'Removed',
|
||||
className: 'bg-pink-100 dark:bg-pink-900/50 text-pink-700 dark:text-pink-300',
|
||||
icon: XCircle,
|
||||
},
|
||||
} as const;
|
||||
|
||||
function Changes({ type, children }: ChangesProps) {
|
||||
const config = typeConfig[type] || typeConfig.added;
|
||||
|
||||
return (
|
||||
<div className="space-y-3 mb-8">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className={cn("px-3 py-1 rounded-full text-sm font-medium flex items-center gap-1.5", config.className)}>
|
||||
<config.icon className="h-3.5 w-3.5" />
|
||||
<span>{config.label}</span>
|
||||
</div>
|
||||
</div>
|
||||
<ul className="list-none pl-0 space-y-2 text-foreground/80">
|
||||
{React.Children.map(children, (child, index) => {
|
||||
// Jika teks dimulai dengan - atau *, hapus karakter tersebut
|
||||
const processedChild = typeof child === 'string'
|
||||
? child.trim().replace(/^[-*]\s+/, '')
|
||||
: child;
|
||||
|
||||
return (
|
||||
<li key={index} className="leading-relaxed">
|
||||
{processedChild}
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export { Release, Changes };
|
||||
|
||||
const ReleaseMdx = {
|
||||
Release,
|
||||
Changes
|
||||
};
|
||||
|
||||
export default ReleaseMdx;
|
||||
29
components/markdown/mdx-provider.tsx
Normal file
29
components/markdown/mdx-provider.tsx
Normal file
@@ -0,0 +1,29 @@
|
||||
'use client';
|
||||
|
||||
import { MDXRemote, MDXRemoteProps } from 'next-mdx-remote/rsc';
|
||||
import { Kbd } from './KeyboardMdx';
|
||||
|
||||
// Define components mapping
|
||||
const components = {
|
||||
// Keyboard components
|
||||
Kbd: Kbd as React.ComponentType<React.HTMLAttributes<HTMLElement> & { type?: 'window' | 'mac' }>,
|
||||
kbd: Kbd as React.ComponentType<React.HTMLAttributes<HTMLElement> & { type?: 'window' | 'mac' }>,
|
||||
};
|
||||
|
||||
interface MDXProviderWrapperProps {
|
||||
source: string;
|
||||
}
|
||||
|
||||
export function MDXProviderWrapper({ source }: MDXProviderWrapperProps) {
|
||||
return (
|
||||
<div className="prose dark:prose-invert max-w-none">
|
||||
<MDXRemote
|
||||
source={source}
|
||||
components={components}
|
||||
options={{
|
||||
parseFrontmatter: true,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user