Skip to content

Commit

Permalink
Merge pull request #45 from honuuk/feature/getExampleCodesFromFile
Browse files Browse the repository at this point in the history
fix: �Import example code for the component from file
  • Loading branch information
hasanharman authored Dec 3, 2024
2 parents 5ff894a + 02f3e10 commit 1a9b677
Show file tree
Hide file tree
Showing 7 changed files with 722 additions and 759 deletions.
246 changes: 4 additions & 242 deletions components/components/autocomplete.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,256 +7,18 @@ import Code from '@/components/code'
import Autocomplete from '@/components/ui/autocomplete'
import { AutocompleteForm } from '@/components/components/autocomplete-form'

import installationManual from '@/components/ui/autocomplete?raw'
import formCode from '@/components/components/autocomplete-form?raw'

const code = `<Autocomplete
value={field.value}
onChange={field.onChange}
/>`

const installationCode = `npx shadcn@latest add https://www.shadcn-form.com/registry/autocomplete.json`

const installationManuel = `'use client'
import { useState, useCallback, useEffect } from 'react'
import { useDebounce } from 'use-debounce'
import { Input } from '@/components/ui/input'
import { Button } from '@/components/ui/button'
import { Search } from 'lucide-react'
// Simulated API call
const fetchSuggestions = async (query: string): Promise<string[]> => {
await new Promise((resolve) => setTimeout(resolve, 300)) // Simulate network delay
const allSuggestions = [
'React',
'Redux',
'Next.js',
'TypeScript',
'JavaScript',
'Node.js',
'Express',
'MongoDB',
'PostgreSQL',
'GraphQL',
'Vue.js',
'Angular',
'Svelte',
'Tailwind CSS',
'Sass',
'Webpack',
'Babel',
'ESLint',
'Jest',
'Cypress',
]
return allSuggestions.filter((suggestion) =>
suggestion.toLowerCase().includes(query.toLowerCase()),
)
}
interface AutoCompleteProps {
value?: string
onChange?: (value: string) => void
}
export default function Autocomplete({ value = '', onChange }: AutoCompleteProps) {
const [query, setQuery] = useState(value)
const [debouncedQuery] = useDebounce(query, 300)
const [suggestions, setSuggestions] = useState<string[]>([])
const [selectedIndex, setSelectedIndex] = useState(-1)
const [isLoading, setIsLoading] = useState(false)
const [isFocused, setIsFocused] = useState(false)
const fetchSuggestionsCallback = useCallback(async (q: string) => {
if (q.trim() === '') {
setSuggestions([])
return
}
setIsLoading(true)
const results = await fetchSuggestions(q)
setSuggestions(results)
setIsLoading(false)
}, [])
useEffect(() => {
if (debouncedQuery && isFocused) {
fetchSuggestionsCallback(debouncedQuery)
} else {
setSuggestions([])
}
}, [debouncedQuery, fetchSuggestionsCallback, isFocused])
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const newValue = e.target.value
setQuery(newValue)
onChange?.(newValue)
setSelectedIndex(-1)
}
const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === 'ArrowDown') {
e.preventDefault()
setSelectedIndex((prev) =>
prev < suggestions.length - 1 ? prev + 1 : prev,
)
} else if (e.key === 'ArrowUp') {
e.preventDefault()
setSelectedIndex((prev) => (prev > 0 ? prev - 1 : -1))
} else if (e.key === 'Enter' && selectedIndex >= 0) {
setQuery(suggestions[selectedIndex])
setSuggestions([])
setSelectedIndex(-1)
} else if (e.key === 'Escape') {
setSuggestions([])
setSelectedIndex(-1)
}
}
const handleSuggestionClick = (suggestion: string) => {
setQuery(suggestion)
onChange?.(suggestion)
setSuggestions([])
setSelectedIndex(-1)
}
const handleFocus = () => {
setIsFocused(true)
}
const handleBlur = () => {
// Delay hiding suggestions to allow for click events on suggestions
setTimeout(() => {
setIsFocused(false)
setSuggestions([])
setSelectedIndex(-1)
}, 200)
}
return (
<div className="w-full max-w-md mx-auto p-4">
<div className="relative">
<Input
type="text"
placeholder="Search..."
value={query}
onChange={handleInputChange}
onKeyDown={handleKeyDown}
onFocus={handleFocus}
onBlur={handleBlur}
className="pr-10"
aria-label="Search input"
aria-autocomplete="list"
aria-controls="suggestions-list"
aria-expanded={suggestions.length > 0}
/>
<Button
size="icon"
variant="ghost"
className="absolute right-0 top-0 h-full"
aria-label="Search"
>
<Search className="h-4 w-4" />
</Button>
</div>
{isLoading && isFocused && (
<div
className="mt-2 p-2 bg-background border rounded-md shadow-sm"
aria-live="polite"
>
Loading...
</div>
)}
{suggestions.length > 0 && !isLoading && isFocused && (
<ul
id="suggestions-list"
className="mt-2 bg-background border rounded-md shadow-sm"
role="listbox"
>
{suggestions.map((suggestion, index) => (
<li
key={suggestion}
className={"px-4 py-2 cursor-pointer hover:bg-muted " +
(index === selectedIndex ? 'bg-muted' : '')
}
onClick={() => handleSuggestionClick(suggestion)}
role="option"
aria-selected={index === selectedIndex}
>
{suggestion}
</li>
))}
</ul>
)}
</div>
)
}
`

const usageCode1 = `import Autocomplete from '@/components/ui/autocomplete'`

const formCode = `
'use client'
import { zodResolver } from '@hookform/resolvers/zod'
import { useForm } from 'react-hook-form'
import { z } from 'zod'
import { toast } from 'sonner'
import { Button } from '@/components/ui/button'
import {
Form,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from '@/components/ui/form'
import Autocomplete from '@/components/ui/autocomplete'
const FormSchema = z.object({
framework: z.string().min(1, 'Please select a framework'),
})
type AutocompleteFormData = z.infer<typeof FormSchema>
export function AutocompleteForm() {
const form = useForm<AutocompleteFormData>({
resolver: zodResolver(FormSchema),
})
const onSubmit = (data: AutocompleteFormData) => {
console.log('HEY', data)
toast(
<pre className="mt-2 w-[340px] rounded-md bg-slate-950 p-4">
<code className="text-white">{JSON.stringify(data, null, 2)}</code>
</pre>,
)
}
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
<FormField
control={form.control}
name="framework"
render={({ field }) => (
<FormItem className="flex flex-col">
<div>
<FormLabel>What is your favorite framework?</FormLabel>
</div>
<Autocomplete value={field.value} onChange={field.onChange} />
<FormDescription>
Please type and select your favorite framework?
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit">Submit</Button>
</form>
</Form>
)
}
`

export default function Component() {
return (
<div className="space-y-6">
Expand Down Expand Up @@ -342,7 +104,7 @@ export default function Component() {
Copy and paste the following code into your project.
</div>

<Code code={installationManuel} customStyle="h-[300px]" />
<Code code={installationManual} customStyle="h-[300px]" />
</div>
<div className="grid gap-1 text-sm relative">
<div className="flex justify-center items-center aspect-square w-6 h-6 bg-gray-200 rounded-full absolute left-0 translate-x-[-31.5px] z-10 top-1 dark:bg-gray-50">
Expand Down
Loading

0 comments on commit 1a9b677

Please sign in to comment.