Improve cursor hover effect
This commit is contained in:
parent
cec8950ccc
commit
865d1f5073
5 changed files with 42 additions and 18 deletions
|
|
@ -28,7 +28,7 @@
|
|||
<div class="scroll-container">
|
||||
<div class="page-wrapper">
|
||||
<header>
|
||||
<h1>Reconcile-text: conflict-free 3-way text merging</h1>
|
||||
<h1><code>reconcile-text</code>: conflict-free 3-way text merging</h1>
|
||||
<p>
|
||||
Think
|
||||
<a
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ const tokenizerRadios = document.querySelectorAll(
|
|||
'input[name="tokenizer"]'
|
||||
) as NodeListOf<HTMLInputElement>;
|
||||
|
||||
const sampleText = `The \`reconcile\` Rust library is embedded on this page as a WASM module and powers these text boxes. Experiment with changing the "Original", "First concurrent edit", and "Second concurrent edit" text boxes to see competing changes get merged in real-time within the "Deconflicted result" box. Here, you will see color-coded tokens marking the origin of each token, including ones that got deleted. The result highly depends on the tokenization strategy, for example, deciding how casing or whitespace is taken into account.`;
|
||||
const sampleText = `The \`reconcile\` Rust library is embedded on this page as a WASM module and powers these text boxes. Experiment with changing the "Original", "First concurrent edit", and "Second concurrent edit" text boxes to see competing changes get merged in real-time within the "Deconflicted result" box. Here, you will see color-coded tokens marking the origin of each token, including ones that got deleted. The result highly depends on the tokenisation strategy, for example, deciding how casing or whitespace is taken into account.`;
|
||||
|
||||
async function main(): Promise<void> {
|
||||
originalTextArea.addEventListener('input', updateMergedText);
|
||||
|
|
@ -76,11 +76,11 @@ function updateMergedText(): void {
|
|||
}
|
||||
|
||||
const selectionSide = leftCursors ? 'left' : 'right';
|
||||
mergedTextArea.innerHTML = '';
|
||||
const fragment = document.createDocumentFragment();
|
||||
|
||||
let currentPosition = 0;
|
||||
if (selectionEnd === 0) {
|
||||
mergedTextArea.appendChild(createCaret(selectionSide === 'left'));
|
||||
fragment.appendChild(createCaret(selectionSide === 'left'));
|
||||
}
|
||||
|
||||
for (const { text, history } of results.history) {
|
||||
|
|
@ -93,10 +93,10 @@ function updateMergedText(): void {
|
|||
span.className += ` selection-${selectionSide}`;
|
||||
}
|
||||
|
||||
mergedTextArea.appendChild(span);
|
||||
fragment.appendChild(span);
|
||||
|
||||
if (currentPosition == selectionEnd - 1) {
|
||||
mergedTextArea.appendChild(createCaret(selectionSide === 'left'));
|
||||
if (currentPosition === selectionEnd - 1) {
|
||||
fragment.appendChild(createCaret(selectionSide === 'left'));
|
||||
}
|
||||
|
||||
if (history !== 'RemovedFromLeft' && history !== 'RemovedFromRight') {
|
||||
|
|
@ -105,6 +105,9 @@ function updateMergedText(): void {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
mergedTextArea.innerHTML = '';
|
||||
mergedTextArea.appendChild(fragment);
|
||||
}
|
||||
|
||||
function getCursorsFromActiveTextArea() {
|
||||
|
|
@ -167,8 +170,8 @@ function autoResize(textarea: HTMLTextAreaElement): void {
|
|||
|
||||
function focusTextArea(textarea: HTMLTextAreaElement): void {
|
||||
textarea.focus();
|
||||
textarea.selectionStart = textarea.value.length;
|
||||
textarea.selectionEnd = textarea.value.length;
|
||||
textarea.selectionStart = 0;
|
||||
textarea.selectionEnd = 0;
|
||||
}
|
||||
|
||||
main();
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
@use 'sass:color';
|
||||
|
||||
// Colour palette
|
||||
$primary-blue: #2451a6;
|
||||
$light-blue: #85bff7;
|
||||
|
|
@ -16,6 +18,10 @@ $gradient-end: #e0e7ef;
|
|||
@return rgba($colour, $opacity);
|
||||
}
|
||||
|
||||
@function caret-colour($colour, $amount: 20%) {
|
||||
@return color.adjust($colour, $lightness: -$amount);
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
|
|
@ -36,6 +42,7 @@ body {
|
|||
height: 100vh;
|
||||
height: 100dvh;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.background {
|
||||
|
|
@ -274,9 +281,13 @@ textarea {
|
|||
#merged {
|
||||
width: 100%;
|
||||
user-select: text;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
> * {
|
||||
position: relative;
|
||||
display: block;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -328,13 +339,14 @@ $DOT_RADIUS: 4;
|
|||
|
||||
.selection-caret {
|
||||
position: relative;
|
||||
z-index: 1000;
|
||||
|
||||
&.selection-caret-left {
|
||||
background: $green;
|
||||
background: caret-colour($green);
|
||||
}
|
||||
|
||||
&.selection-caret-right {
|
||||
background: $light-blue;
|
||||
background: caret-colour($light-blue);
|
||||
}
|
||||
|
||||
> * {
|
||||
|
|
@ -359,13 +371,24 @@ $DOT_RADIUS: 4;
|
|||
height: #{$DOT_RADIUS * 2}px;
|
||||
top: -#{$DOT_RADIUS}px;
|
||||
left: -#{$DOT_RADIUS}px;
|
||||
transition: transform 0.3s ease-in-out;
|
||||
transition: opacity 0.3s ease-in-out;
|
||||
transform-origin: bottom center;
|
||||
box-sizing: border-box;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover > .dot {
|
||||
transform: scale(0);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
> .info {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,5 @@
|
|||
"skipLibCheck": true,
|
||||
"inlineSourceMap": true
|
||||
},
|
||||
"exclude": [
|
||||
"./dist"
|
||||
]
|
||||
"exclude": ["./dist"]
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue