Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
C
canifa_note
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Vũ Hoàng Anh
canifa_note
Commits
6d10251c
Commit
6d10251c
authored
Apr 08, 2024
by
Steven
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: impl list syntax auto complete to editor
parent
436a6cb0
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
135 additions
and
87 deletions
+135
-87
index.tsx
web/src/components/MemoEditor/Editor/index.tsx
+92
-87
handlers.ts
web/src/components/MemoEditor/handlers.ts
+0
-0
index.ts
web/src/components/MemoEditor/hooks/index.ts
+3
-0
useAutoComplete.ts
web/src/components/MemoEditor/hooks/useAutoComplete.ts
+40
-0
No files found.
web/src/components/MemoEditor/Editor/index.tsx
View file @
6d10251c
import
classNames
from
"classnames"
;
import
{
forwardRef
,
ReactNode
,
useCallback
,
useEffect
,
useImperativeHandle
,
useRef
}
from
"react"
;
import
{
useAutoComplete
}
from
"../hooks"
;
import
TagSuggestions
from
"./TagSuggestions"
;
export
interface
EditorRefActions
{
getEditor
:
()
=>
HTMLTextAreaElement
|
null
;
focus
:
FunctionType
;
scrollToCursor
:
FunctionType
;
insertText
:
(
text
:
string
,
prefix
?:
string
,
suffix
?:
string
)
=>
void
;
...
...
@@ -43,101 +45,104 @@ const Editor = forwardRef(function Editor(props: Props, ref: React.ForwardedRef<
}
},
[
editorRef
.
current
?.
value
]);
const
updateEditorHeight
=
()
=>
{
if
(
editorRef
.
current
)
{
editorRef
.
current
.
style
.
height
=
"auto"
;
editorRef
.
current
.
style
.
height
=
(
editorRef
.
current
.
scrollHeight
??
0
)
+
"px"
;
}
};
const
editorActions
=
{
getEditor
:
()
=>
{
return
editorRef
.
current
;
},
focus
:
()
=>
{
editorRef
.
current
?.
focus
();
},
scrollToCursor
:
()
=>
{
if
(
editorRef
.
current
)
{
editorRef
.
current
.
scrollTop
=
editorRef
.
current
.
scrollHeight
;
}
},
insertText
:
(
content
=
""
,
prefix
=
""
,
suffix
=
""
)
=>
{
if
(
!
editorRef
.
current
)
{
return
;
}
useImperativeHandle
(
ref
,
()
=>
({
focus
:
()
=>
{
editorRef
.
current
?.
focus
();
},
scrollToCursor
:
()
=>
{
if
(
editorRef
.
current
)
{
editorRef
.
current
.
scrollTop
=
editorRef
.
current
.
scrollHeight
;
}
},
insertText
:
(
content
=
""
,
prefix
=
""
,
suffix
=
""
)
=>
{
if
(
!
editorRef
.
current
)
{
return
;
}
const
cursorPosition
=
editorRef
.
current
.
selectionStart
;
const
endPosition
=
editorRef
.
current
.
selectionEnd
;
const
prevValue
=
editorRef
.
current
.
value
;
const
value
=
prevValue
.
slice
(
0
,
cursorPosition
)
+
prefix
+
(
content
||
prevValue
.
slice
(
cursorPosition
,
endPosition
))
+
suffix
+
prevValue
.
slice
(
endPosition
);
const
cursorPosition
=
editorRef
.
current
.
selectionStart
;
const
endPosition
=
editorRef
.
current
.
selectionEnd
;
const
prevValue
=
editorRef
.
current
.
value
;
const
value
=
prevValue
.
slice
(
0
,
cursorPosition
)
+
prefix
+
(
content
||
prevValue
.
slice
(
cursorPosition
,
endPosition
))
+
suffix
+
prevValue
.
slice
(
endPosition
);
editorRef
.
current
.
value
=
value
;
editorRef
.
current
.
focus
();
editorRef
.
current
.
selectionEnd
=
endPosition
+
prefix
.
length
+
content
.
length
;
handleContentChangeCallback
(
editorRef
.
current
.
value
);
updateEditorHeight
();
},
removeText
:
(
start
:
number
,
length
:
number
)
=>
{
if
(
!
editorRef
.
current
)
{
return
;
}
editorRef
.
current
.
value
=
value
;
editorRef
.
current
.
focus
();
editorRef
.
current
.
selectionEnd
=
endPosition
+
prefix
.
length
+
content
.
length
;
const
prevValue
=
editorRef
.
current
.
value
;
const
value
=
prevValue
.
slice
(
0
,
start
)
+
prevValue
.
slice
(
start
+
length
);
editorRef
.
current
.
value
=
value
;
editorRef
.
current
.
focus
();
editorRef
.
current
.
selectionEnd
=
start
;
handleContentChangeCallback
(
editorRef
.
current
.
value
);
updateEditorHeight
();
},
setContent
:
(
text
:
string
)
=>
{
if
(
editorRef
.
current
)
{
editorRef
.
current
.
value
=
text
;
handleContentChangeCallback
(
editorRef
.
current
.
value
);
updateEditorHeight
();
},
removeText
:
(
start
:
number
,
length
:
number
)
=>
{
if
(
!
editorRef
.
current
)
{
return
;
}
const
prevValue
=
editorRef
.
current
.
value
;
const
value
=
prevValue
.
slice
(
0
,
start
)
+
prevValue
.
slice
(
start
+
length
);
editorRef
.
current
.
value
=
value
;
}
},
getContent
:
():
string
=>
{
return
editorRef
.
current
?.
value
??
""
;
},
getCursorPosition
:
():
number
=>
{
return
editorRef
.
current
?.
selectionStart
??
0
;
},
getSelectedContent
:
()
=>
{
const
start
=
editorRef
.
current
?.
selectionStart
;
const
end
=
editorRef
.
current
?.
selectionEnd
;
return
editorRef
.
current
?.
value
.
slice
(
start
,
end
)
??
""
;
},
setCursorPosition
:
(
startPos
:
number
,
endPos
?:
number
)
=>
{
const
_endPos
=
isNaN
(
endPos
as
number
)
?
startPos
:
(
endPos
as
number
);
editorRef
.
current
?.
setSelectionRange
(
startPos
,
_endPos
);
},
getCursorLineNumber
:
()
=>
{
const
cursorPosition
=
editorRef
.
current
?.
selectionStart
??
0
;
const
lines
=
editorRef
.
current
?.
value
.
slice
(
0
,
cursorPosition
).
split
(
"
\n
"
)
??
[];
return
lines
.
length
-
1
;
},
getLine
:
(
lineNumber
:
number
)
=>
{
return
editorRef
.
current
?.
value
.
split
(
"
\n
"
)[
lineNumber
]
??
""
;
},
setLine
:
(
lineNumber
:
number
,
text
:
string
)
=>
{
const
lines
=
editorRef
.
current
?.
value
.
split
(
"
\n
"
)
??
[];
lines
[
lineNumber
]
=
text
;
if
(
editorRef
.
current
)
{
editorRef
.
current
.
value
=
lines
.
join
(
"
\n
"
);
editorRef
.
current
.
focus
();
editorRef
.
current
.
selectionEnd
=
start
;
handleContentChangeCallback
(
editorRef
.
current
.
value
);
updateEditorHeight
();
},
setContent
:
(
text
:
string
)
=>
{
if
(
editorRef
.
current
)
{
editorRef
.
current
.
value
=
text
;
handleContentChangeCallback
(
editorRef
.
current
.
value
);
updateEditorHeight
();
}
},
getContent
:
():
string
=>
{
return
editorRef
.
current
?.
value
??
""
;
},
getCursorPosition
:
():
number
=>
{
return
editorRef
.
current
?.
selectionStart
??
0
;
},
getSelectedContent
:
()
=>
{
const
start
=
editorRef
.
current
?.
selectionStart
;
const
end
=
editorRef
.
current
?.
selectionEnd
;
return
editorRef
.
current
?.
value
.
slice
(
start
,
end
)
??
""
;
},
setCursorPosition
:
(
startPos
:
number
,
endPos
?:
number
)
=>
{
const
_endPos
=
isNaN
(
endPos
as
number
)
?
startPos
:
(
endPos
as
number
);
editorRef
.
current
?.
setSelectionRange
(
startPos
,
_endPos
);
},
getCursorLineNumber
:
()
=>
{
const
cursorPosition
=
editorRef
.
current
?.
selectionStart
??
0
;
const
lines
=
editorRef
.
current
?.
value
.
slice
(
0
,
cursorPosition
).
split
(
"
\n
"
)
??
[];
return
lines
.
length
-
1
;
},
getLine
:
(
lineNumber
:
number
)
=>
{
return
editorRef
.
current
?.
value
.
split
(
"
\n
"
)[
lineNumber
]
??
""
;
},
setLine
:
(
lineNumber
:
number
,
text
:
string
)
=>
{
const
lines
=
editorRef
.
current
?.
value
.
split
(
"
\n
"
)
??
[];
lines
[
lineNumber
]
=
text
;
if
(
editorRef
.
current
)
{
editorRef
.
current
.
value
=
lines
.
join
(
"
\n
"
);
editorRef
.
current
.
focus
();
handleContentChangeCallback
(
editorRef
.
current
.
value
);
updateEditorHeight
();
}
},
}),
[],
);
}
},
};
useAutoComplete
(
editorActions
);
useImperativeHandle
(
ref
,
()
=>
editorActions
,
[]);
const
updateEditorHeight
=
()
=>
{
if
(
editorRef
.
current
)
{
editorRef
.
current
.
style
.
height
=
"auto"
;
editorRef
.
current
.
style
.
height
=
(
editorRef
.
current
.
scrollHeight
??
0
)
+
"px"
;
}
};
const
handleEditorInput
=
useCallback
(()
=>
{
handleContentChangeCallback
(
editorRef
.
current
?.
value
??
""
);
...
...
web/src/components/MemoEditor/handlers.ts
x
→
web/src/components/MemoEditor/handlers.ts
View file @
6d10251c
File moved
web/src/components/MemoEditor/hooks/index.ts
0 → 100644
View file @
6d10251c
import
useAutoComplete
from
"./useAutoComplete"
;
export
{
useAutoComplete
};
web/src/components/MemoEditor/hooks/useAutoComplete.ts
0 → 100644
View file @
6d10251c
import
{
last
}
from
"lodash-es"
;
import
{
useEffect
}
from
"react"
;
import
{
NodeType
,
OrderedListNode
,
TaskListNode
,
UnorderedListNode
}
from
"@/types/node"
;
import
{
EditorRefActions
}
from
"../Editor"
;
const
useAutoComplete
=
(
actions
:
EditorRefActions
)
=>
{
useEffect
(()
=>
{
const
editor
=
actions
.
getEditor
();
if
(
!
editor
)
return
;
editor
.
addEventListener
(
"keydown"
,
(
event
)
=>
{
if
(
event
.
key
===
"Enter"
)
{
const
cursorPosition
=
actions
.
getCursorPosition
();
const
prevContent
=
actions
.
getContent
().
substring
(
0
,
cursorPosition
);
const
lastNode
=
last
(
window
.
parse
(
prevContent
));
if
(
!
lastNode
)
{
return
;
}
let
insertText
=
""
;
if
(
lastNode
.
type
===
NodeType
.
TASK_LIST
)
{
const
{
complete
}
=
lastNode
.
value
as
TaskListNode
;
insertText
=
complete
?
"- [x] "
:
"- [ ] "
;
}
else
if
(
lastNode
.
type
===
NodeType
.
UNORDERED_LIST
)
{
const
{
symbol
}
=
lastNode
.
value
as
UnorderedListNode
;
insertText
=
`
${
symbol
}
`
;
}
else
if
(
lastNode
.
type
===
NodeType
.
ORDERED_LIST
)
{
const
{
number
}
=
lastNode
.
value
as
OrderedListNode
;
insertText
=
`
${
Number
(
number
)
+
1
}
. `
;
}
if
(
insertText
)
{
actions
.
insertText
(
`\n
${
insertText
}
`
);
event
.
preventDefault
();
}
}
});
},
[]);
};
export
default
useAutoComplete
;
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment