2026-07-31 15:07:09 +08:00
|
|
|
import { Button } from "@workspace/ui/components/button"
|
|
|
|
|
import {
|
|
|
|
|
Tooltip,
|
|
|
|
|
TooltipContent,
|
|
|
|
|
TooltipTrigger,
|
|
|
|
|
} from "@workspace/ui/components/tooltip"
|
|
|
|
|
import { useLexicalActionContext } from "./context"
|
|
|
|
|
import { useLexicalMessage } from "./i18n"
|
|
|
|
|
import type { LexicalControlProps } from "./types"
|
|
|
|
|
|
|
|
|
|
export function LexicalControl<Value = string>({
|
|
|
|
|
action,
|
2026-08-08 21:13:49 +08:00
|
|
|
className,
|
2026-07-31 15:07:09 +08:00
|
|
|
label,
|
|
|
|
|
presentation = "control",
|
|
|
|
|
render,
|
|
|
|
|
value,
|
|
|
|
|
}: LexicalControlProps<Value>) {
|
|
|
|
|
const context = useLexicalActionContext()
|
|
|
|
|
const active = action.isActive?.(context) ?? false
|
|
|
|
|
const disabled = action.isDisabled?.(context) ?? false
|
|
|
|
|
const resolvedLabel = useLexicalMessage(label ?? action.label)
|
|
|
|
|
const execute = (nextValue?: Value) =>
|
|
|
|
|
action.execute(context, nextValue ?? value)
|
|
|
|
|
const onClick = () => execute()
|
|
|
|
|
const renderProps = {
|
|
|
|
|
active,
|
2026-08-08 21:13:49 +08:00
|
|
|
className,
|
2026-07-31 15:07:09 +08:00
|
|
|
disabled,
|
|
|
|
|
execute,
|
|
|
|
|
label: resolvedLabel,
|
|
|
|
|
onClick,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (render) return render(renderProps)
|
|
|
|
|
|
|
|
|
|
if (action.control) {
|
|
|
|
|
const ActionControl = action.control
|
|
|
|
|
return (
|
|
|
|
|
<ActionControl
|
|
|
|
|
{...renderProps}
|
|
|
|
|
action={action}
|
|
|
|
|
context={context}
|
|
|
|
|
presentation={presentation}
|
|
|
|
|
value={value}
|
|
|
|
|
/>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const Icon = action.icon
|
|
|
|
|
return (
|
|
|
|
|
<Tooltip>
|
|
|
|
|
<TooltipTrigger
|
|
|
|
|
render={
|
|
|
|
|
<Button
|
|
|
|
|
type="button"
|
|
|
|
|
size="icon-sm"
|
2026-08-08 21:13:49 +08:00
|
|
|
className={className}
|
2026-07-31 15:07:09 +08:00
|
|
|
variant={active ? "secondary" : "ghost"}
|
|
|
|
|
disabled={disabled}
|
|
|
|
|
aria-label={resolvedLabel}
|
|
|
|
|
aria-pressed={active}
|
|
|
|
|
onMouseDown={(event) => event.preventDefault()}
|
|
|
|
|
onClick={onClick}
|
|
|
|
|
/>
|
|
|
|
|
}
|
|
|
|
|
>
|
|
|
|
|
{Icon ? <Icon /> : null}
|
|
|
|
|
</TooltipTrigger>
|
|
|
|
|
<TooltipContent showArrow>{resolvedLabel}</TooltipContent>
|
|
|
|
|
</Tooltip>
|
|
|
|
|
)
|
|
|
|
|
}
|