import { createEffect, createSignal, onMount, Show, splitProps, type JSX } from "solid-js" import { Button } from "./button" import { Icon } from "./icon" import { installLineCommentStyles } from "./line-comment-styles" import { useI18n } from "../context/i18n" installLineCommentStyles() export type LineCommentVariant = "default" | "editor" | "add" function InlineGlyph(props: { icon: "comment" | "plus" }) { return ( } > ) } export type LineCommentAnchorProps = { id?: string top?: number inline?: boolean hideButton?: boolean open: boolean variant?: LineCommentVariant icon?: "comment" | "plus" buttonLabel?: string onClick?: JSX.EventHandlerUnion onMouseEnter?: JSX.EventHandlerUnion onPopoverFocusOut?: JSX.EventHandlerUnion class?: string popoverClass?: string children?: JSX.Element } export const LineCommentAnchor = (props: LineCommentAnchorProps) => { const hidden = () => !props.inline && props.top === undefined const variant = () => props.variant ?? "default" const icon = () => props.icon ?? "comment" const inlineBody = () => props.inline && props.hideButton return ( e.stopPropagation()} on:mouseup={(e) => e.stopPropagation()} on:click={props.onClick as any} on:mouseenter={props.onMouseEnter as any} > } > e.stopPropagation()} on:focusout={props.onPopoverFocusOut as any} > {props.children} > } > e.stopPropagation()} on:click={props.onClick as any} on:mouseenter={props.onMouseEnter as any} on:focusout={props.onPopoverFocusOut as any} > {props.children} ) } export type LineCommentProps = Omit & { comment: JSX.Element selection: JSX.Element actions?: JSX.Element } export const LineComment = (props: LineCommentProps) => { const i18n = useI18n() const [split, rest] = splitProps(props, ["comment", "selection", "actions"]) return ( {split.comment} {split.actions} {i18n.t("ui.lineComment.label.prefix")} {split.selection} {i18n.t("ui.lineComment.label.suffix")} ) } export type LineCommentAddProps = Omit & { label?: string } export const LineCommentAdd = (props: LineCommentAddProps) => { const [split, rest] = splitProps(props, ["label"]) const i18n = useI18n() return ( ) } export type LineCommentEditorProps = Omit & { value: string selection: JSX.Element onInput: (value: string) => void onCancel: VoidFunction onSubmit: (value: string) => void placeholder?: string rows?: number autofocus?: boolean cancelLabel?: string submitLabel?: string } export const LineCommentEditor = (props: LineCommentEditorProps) => { const i18n = useI18n() const [split, rest] = splitProps(props, [ "value", "selection", "onInput", "onCancel", "onSubmit", "placeholder", "rows", "autofocus", "cancelLabel", "submitLabel", ]) const refs = { textarea: undefined as HTMLTextAreaElement | undefined, } const [text, setText] = createSignal(split.value) const focus = () => refs.textarea?.focus() createEffect(() => { setText(split.value) }) const submit = () => { const value = text().trim() if (!value) return split.onSubmit(value) } onMount(() => { if (split.autofocus === false) return requestAnimationFrame(focus) }) return ( focus()}> { refs.textarea = el }} data-slot="line-comment-textarea" rows={split.rows ?? 3} placeholder={split.placeholder ?? i18n.t("ui.lineComment.placeholder")} value={text()} on:input={(e) => { const value = (e.currentTarget as HTMLTextAreaElement).value setText(value) split.onInput(value) }} on:keydown={(e) => { const event = e as KeyboardEvent if (event.isComposing || event.keyCode === 229) return event.stopPropagation() if (e.key === "Escape") { event.preventDefault() e.currentTarget.blur() split.onCancel() return } if (e.key !== "Enter") return if (e.shiftKey) return event.preventDefault() submit() }} /> {i18n.t("ui.lineComment.editorLabel.prefix")} {split.selection} {i18n.t("ui.lineComment.editorLabel.suffix")} {split.cancelLabel ?? i18n.t("ui.common.cancel")} {split.submitLabel ?? i18n.t("ui.lineComment.submit")} > } > {split.cancelLabel ?? i18n.t("ui.common.cancel")} {split.submitLabel ?? i18n.t("ui.lineComment.submit")} ) }