* wip

* wip

* wip3

* chore: utils

* feat: add command

* wip

* fix: key duplicate

* fix: move and check

* fix: use react-use instead

* fix: sidebar

* chore: make dynamic

* chore: tablet mode

* chore: fix padding

* chore: link instead of inbox

* fix: use dnd kit

* feat: add select component

* chore: use atom

* refactor: remove dnd provider

* feat: disabled drag when sort is not manual

* search route

* .

* feat: accessibility

* fix: search

* .

* .

* .

* fix: sidebar collapsed

* ai search layout

* .

* .

* .

* .

* ai responsible content

* .

* .

* .

* .

* .

* global topic route

* global topic correct route

* topic buttons

* sidebar search navigation

* ai

* Update jazz

* .

* .

* .

* .

* .

* learning status

* .

* .

* chore: content header

* fix: pointer none when dragging. prevent auto click after drag end

* fix: confirm

* fix: prevent drag when editing

* chore: remove unused fn

* fix: check propagation

* chore: list

* chore: tweak sonner

* chore: update stuff

* feat: add badge

* chore: close edit when create

* chore: escape on manage form

* refactor: remove learn path

* css: responsive item

* chore: separate pages and topic

* reafactor: remove new-schema

* feat(types): extend jazz type so it can be nullable

* chore: use new types

* fix: missing deps

* fix: link

* fix: sidebar in layout

* fix: quotes

* css: use medium instead semi

* Actual streaming and rendering markdown response

* .

* .

* .

* .

* .

* .

* .

* .

* .

* .

* .

* .

* .

* .

* .

* .

* .

* .

* .

* .

* .

* chore: metadata

* feat: la-editor

* .

* fix: editor and page

* .

* .

* .

* .

* .

* .

* fix: remove link

* chore: page sidebar

* fix: remove 'replace with learning status'

* fix: link

* fix: link

* chore: update schema

* chore: use new schema

* fix: instead of showing error, just do unique slug

* feat: create slug

* refactor apply

* update package json

* fix: schema personal page

* chore: editor

* feat: pages

* fix: metadata

* fix: jazz provider

* feat: handling data

* feat: page detail

* chore: server page to id

* chore: use id instead of slug

* chore: update content header

* chore: update link header implementation

* refactor: global.css

* fix: la editor use animation frame

* fix: editor export ref

* refactor: page detail

* chore: tidy up schema

* chore: adapt to new schema

* fix: wrap using settimeout

* fix: wrap using settimeout

* .

* .

---------

Co-authored-by: marshennikovaolga <marshennikova@gmail.com>
Co-authored-by: Nikita <github@nikiv.dev>
Co-authored-by: Anselm <anselm.eickhoff@gmail.com>
Co-authored-by: Damian Tarnawski <gthetarnav@gmail.com>
This commit is contained in:
Aslam
2024-08-08 00:57:22 +07:00
committed by GitHub
parent 228faf226a
commit 36e0e19212
143 changed files with 6967 additions and 101 deletions

View File

@@ -0,0 +1,14 @@
import { Editor } from "@tiptap/core"
import { LAEditorProps } from "../../la-editor"
export function getOutput(editor: Editor, output: LAEditorProps["output"]) {
if (output === "html") return editor.getHTML()
if (output === "json") return editor.getJSON()
if (output === "text") return editor.getText()
return ""
}
export * from "./keyboard"
export * from "./platform"
export * from "./isCustomNodeSelected"
export * from "./isTextSelected"

View File

@@ -0,0 +1,28 @@
import { Editor } from "@tiptap/react"
import { Link } from "@/components/la-editor/extensions/link"
import { HorizontalRule } from "@/components/la-editor/extensions/horizontal-rule"
export const isTableGripSelected = (node: HTMLElement) => {
let container = node
while (container && !["TD", "TH"].includes(container.tagName)) {
container = container.parentElement!
}
const gripColumn = container && container.querySelector && container.querySelector("a.grip-column.selected")
const gripRow = container && container.querySelector && container.querySelector("a.grip-row.selected")
if (gripColumn || gripRow) {
return true
}
return false
}
export const isCustomNodeSelected = (editor: Editor, node: HTMLElement) => {
const customNodes = [HorizontalRule.name, Link.name]
return customNodes.some(type => editor.isActive(type)) || isTableGripSelected(node)
}
export default isCustomNodeSelected

View File

@@ -0,0 +1,25 @@
import { isTextSelection } from "@tiptap/core"
import { Editor } from "@tiptap/react"
export const isTextSelected = ({ editor }: { editor: Editor }) => {
const {
state: {
doc,
selection,
selection: { empty, from, to }
}
} = editor
// Sometime check for `empty` is not enough.
// Doubleclick an empty paragraph returns a node size of 2.
// So we check also for an empty text size.
const isEmptyTextBlock = !doc.textBetween(from, to).length && isTextSelection(selection)
if (empty || isEmptyTextBlock || !editor.isEditable) {
return false
}
return true
}
export default isTextSelected

View File

@@ -0,0 +1,25 @@
import { isMacOS } from "./platform"
export const getShortcutKey = (key: string) => {
const lowercaseKey = key.toLowerCase()
const macOS = isMacOS()
switch (lowercaseKey) {
case "mod":
return macOS ? "⌘" : "Ctrl"
case "alt":
return macOS ? "⌥" : "Alt"
case "shift":
return macOS ? "⇧" : "Shift"
default:
return key
}
}
export const getShortcutKeys = (keys: string | string[], separator: string = "") => {
const keyArray = Array.isArray(keys) ? keys : keys.split(/\s+/)
const shortcutKeys = keyArray.map(getShortcutKey)
return shortcutKeys.join(separator)
}
export default { getShortcutKey, getShortcutKeys }

View File

@@ -0,0 +1,46 @@
export interface NavigatorWithUserAgentData extends Navigator {
userAgentData?: {
brands: { brand: string; version: string }[]
mobile: boolean
platform: string
getHighEntropyValues: (hints: string[]) => Promise<{
platform: string
platformVersion: string
uaFullVersion: string
}>
}
}
let isMac: boolean | undefined
const getPlatform = () => {
const nav = navigator as NavigatorWithUserAgentData
if (nav.userAgentData) {
if (nav.userAgentData.platform) {
return nav.userAgentData.platform
}
nav.userAgentData
.getHighEntropyValues(["platform"])
.then(highEntropyValues => {
if (highEntropyValues.platform) {
return highEntropyValues.platform
}
})
.catch(() => {
return navigator.platform || ""
})
}
return navigator.platform || ""
}
export const isMacOS = () => {
if (isMac === undefined) {
isMac = getPlatform().toLowerCase().includes("mac")
}
return isMac
}
export default isMacOS