mirror of
https://github.com/linsa-io/linsa.git
synced 2026-01-12 12:20:23 +01:00
* feat: keyboard nav * fix: link update * feat: reusable learning state * chore: use new learning state * feat: add to my profile * . * . * feat: on enter open the link * fix: lint * fix: use eslint v8 instead of v9 * fix: add to my profile * chore: update personal link schema * chore: update personal page schema * fix: update detail wrapper * fix: update page section * removing option for learning status * removing option for learning status for topic * feat: add createdAt and updatedAt for personal Page * chore: update page section component * chore: remove chevron from sub menu * fix: sidebar * chore: add focus and disable toast * feat: la editor add execption for no command class * fix: la editor style and fix page detail * fix: title * fix: topic learning state * chore: add showSearch for learning state * fix: bunch stuff * chore: link list and item handle learning state * chore: set expand to false * feat: personal link for topic detail * chore: hook use topic data * chore: go to list * fix: link and topic * feat(utils): new keyboard utils * feat(store): add linkOpenPopoverForIdAtom for link * chore: using memo for use topic data * fix: remove duplicate component * chore: performance for topic detail lint item * refactor: remove LinkOptions component * chore: improve performance for list * feat: added LinkRoute copmonent * chore: link manage * feat: bottom bar * fix: link * fix: page wrapper * fix: import thing * chore: added a displayname * refactor: page detail * refactor: page detail * fix: add topic to personal link form link * fix: only show page count if more than zero * fix: sidebar topic section --------- Co-authored-by: Nikita <github@nikiv.dev> Co-authored-by: marshennikovaolga <marshennikova@gmail.com>
108 lines
3.2 KiB
TypeScript
108 lines
3.2 KiB
TypeScript
import React, { useMemo } from "react"
|
|
import { useAtom } from "jotai"
|
|
import { Button } from "@/components/ui/button"
|
|
import { Popover, PopoverTrigger, PopoverContent } from "@/components/ui/popover"
|
|
import { cn } from "@/lib/utils"
|
|
import { LaIcon } from "@/components/custom/la-icon"
|
|
import { LEARNING_STATES, LearningStateValue } from "@/lib/constants"
|
|
import { linkLearningStateSelectorAtom } from "@/store/link"
|
|
import { Command, CommandInput, CommandList, CommandItem, CommandGroup } from "@/components/ui/command"
|
|
import { ScrollArea } from "@/components/ui/scroll-area"
|
|
|
|
interface LearningStateSelectorProps {
|
|
showSearch?: boolean
|
|
defaultLabel?: string
|
|
searchPlaceholder?: string
|
|
value?: string
|
|
onChange: (value: LearningStateValue) => void
|
|
className?: string
|
|
}
|
|
|
|
export const LearningStateSelector: React.FC<LearningStateSelectorProps> = ({
|
|
showSearch = true,
|
|
defaultLabel = "Select state",
|
|
searchPlaceholder = "Search state...",
|
|
value,
|
|
onChange,
|
|
className
|
|
}) => {
|
|
const [isLearningStateSelectorOpen, setIsLearningStateSelectorOpen] = useAtom(linkLearningStateSelectorAtom)
|
|
const selectedLearningState = useMemo(() => LEARNING_STATES.find(ls => ls.value === value), [value])
|
|
|
|
const handleSelect = (selectedValue: string) => {
|
|
onChange(selectedValue as LearningStateValue)
|
|
setIsLearningStateSelectorOpen(false)
|
|
}
|
|
|
|
return (
|
|
<Popover open={isLearningStateSelectorOpen} onOpenChange={setIsLearningStateSelectorOpen}>
|
|
<PopoverTrigger asChild>
|
|
<Button
|
|
size="sm"
|
|
type="button"
|
|
role="combobox"
|
|
variant="secondary"
|
|
className={cn("gap-x-2 text-sm", className)}
|
|
>
|
|
{selectedLearningState?.icon && (
|
|
<LaIcon name={selectedLearningState.icon} className={cn(selectedLearningState.className)} />
|
|
)}
|
|
<span className={cn("truncate", selectedLearningState?.className || "")}>
|
|
{selectedLearningState?.label || defaultLabel}
|
|
</span>
|
|
<LaIcon name="ChevronDown" />
|
|
</Button>
|
|
</PopoverTrigger>
|
|
<PopoverContent
|
|
className="w-52 rounded-lg p-0"
|
|
side="bottom"
|
|
align="end"
|
|
onCloseAutoFocus={e => e.preventDefault()}
|
|
>
|
|
<LearningStateSelectorContent
|
|
showSearch={showSearch}
|
|
searchPlaceholder={searchPlaceholder}
|
|
value={value}
|
|
onSelect={handleSelect}
|
|
/>
|
|
</PopoverContent>
|
|
</Popover>
|
|
)
|
|
}
|
|
|
|
interface LearningStateSelectorContentProps {
|
|
showSearch: boolean
|
|
searchPlaceholder: string
|
|
value?: string
|
|
onSelect: (value: string) => void
|
|
}
|
|
|
|
export const LearningStateSelectorContent: React.FC<LearningStateSelectorContentProps> = ({
|
|
showSearch,
|
|
searchPlaceholder,
|
|
value,
|
|
onSelect
|
|
}) => {
|
|
return (
|
|
<Command>
|
|
{showSearch && <CommandInput placeholder={searchPlaceholder} className="h-9" />}
|
|
<CommandList>
|
|
<ScrollArea>
|
|
<CommandGroup>
|
|
{LEARNING_STATES.map(ls => (
|
|
<CommandItem key={ls.value} value={ls.value} onSelect={onSelect}>
|
|
<LaIcon name={ls.icon} className={cn("mr-2", ls.className)} />
|
|
<span className={ls.className}>{ls.label}</span>
|
|
<LaIcon
|
|
name="Check"
|
|
className={cn("absolute right-3", ls.value === value ? "text-primary" : "text-transparent")}
|
|
/>
|
|
</CommandItem>
|
|
))}
|
|
</CommandGroup>
|
|
</ScrollArea>
|
|
</CommandList>
|
|
</Command>
|
|
)
|
|
}
|