chore: Enhancement + New Feature (#185)

* wip

* wip page

* chore: style

* wip pages

* wip pages

* chore: toggle

* chore: link

* feat: topic search

* chore: page section

* refactor: apply tailwind class ordering

* fix: handle loggedIn user for guest route

* feat: folder & image schema

* chore: move utils to shared

* refactor: tailwind class ordering

* feat: img ext for editor

* refactor: remove qa

* fix: tanstack start

* fix: wrong import

* chore: use toast

* chore: schema
This commit is contained in:
Aslam
2024-10-18 21:18:20 +07:00
committed by GitHub
parent c93c634a77
commit a440828f8c
158 changed files with 2808 additions and 1064 deletions

View File

@@ -0,0 +1,68 @@
import * as React from "react"
import { NodeViewContent, Editor, NodeViewWrapper } from "@tiptap/react"
import { Icon } from "../../../components/ui/icon"
import { Node as ProseMirrorNode } from "@tiptap/pm/model"
import { Node } from "@tiptap/core"
interface TaskItemProps {
editor: Editor
node: ProseMirrorNode
updateAttributes: (attrs: Record<string, any>) => void
extension: Node
}
export const TaskItemView: React.FC<TaskItemProps> = ({
node,
updateAttributes,
editor,
extension,
}) => {
const handleChange = React.useCallback(
(event: React.ChangeEvent<HTMLInputElement>) => {
const checked = event.target.checked
if (!editor.isEditable && !extension.options.onReadOnlyChecked) {
return
}
if (editor.isEditable) {
updateAttributes({ checked })
} else if (extension.options.onReadOnlyChecked) {
if (!extension.options.onReadOnlyChecked(node, checked)) {
event.target.checked = !checked
}
}
},
[editor.isEditable, extension.options, node, updateAttributes],
)
return (
<NodeViewWrapper
as="li"
data-type="taskItem"
data-checked={node.attrs.checked}
>
<div className="taskItem-checkbox-container">
<Icon
name="GripVertical"
data-drag-handle
className="taskItem-drag-handle"
/>
<label>
<input
type="checkbox"
checked={node.attrs.checked}
onChange={handleChange}
className="taskItem-checkbox"
/>
</label>
</div>
<div className="taskItem-content">
<NodeViewContent />
</div>
</NodeViewWrapper>
)
}
export default TaskItemView

View File

@@ -0,0 +1 @@
export * from "./task-item"

View File

@@ -0,0 +1,64 @@
import { ReactNodeViewRenderer } from "@tiptap/react"
import { mergeAttributes } from "@tiptap/core"
import { TaskItemView } from "./components/task-item-view"
import { TaskItem as TiptapTaskItem } from "@tiptap/extension-task-item"
export const TaskItem = TiptapTaskItem.extend({
name: "taskItem",
draggable: true,
addOptions() {
return {
...this.parent?.(),
nested: true,
}
},
addAttributes() {
return {
checked: {
default: false,
keepOnSplit: false,
parseHTML: (element) => {
const dataChecked = element.getAttribute("data-checked")
return dataChecked === "" || dataChecked === "true"
},
renderHTML: (attributes) => ({
"data-checked": attributes.checked,
}),
},
}
},
renderHTML({ node, HTMLAttributes }) {
return [
"li",
mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, {
"data-type": this.name,
}),
[
"div",
{ class: "taskItem-checkbox-container" },
[
"label",
[
"input",
{
type: "checkbox",
checked: node.attrs.checked ? "checked" : null,
class: "taskItem-checkbox",
},
],
],
],
["div", { class: "taskItem-content" }, 0],
]
},
addNodeView() {
return ReactNodeViewRenderer(TaskItemView, {
as: "span",
})
},
})