more fixes for pad editor, mainly for mobile

This commit is contained in:
2025-04-06 18:14:59 -04:00
parent 5d55c6de4a
commit bee420feb3
4 changed files with 120 additions and 6 deletions

View File

@@ -21,8 +21,25 @@
let currentWord = $state('');
let selectedIndex = $state(-1);
let cursorPosition = $state({ x: 0, y: 0 });
let isMobile = $state(false);
const debounce = createDebounce();
// Check for mobile on component mount and resize
function checkMobile() {
isMobile = window.innerWidth < 768;
}
$effect(() => {
// Add resize listener for responsive behavior
window.addEventListener('resize', checkMobile);
checkMobile();
// Cleanup on unmount
return () => {
window.removeEventListener('resize', checkMobile);
};
});
$effect(() => {
if (editor?.getHTML()) {
localStorage.setItem('tipex', editor.getHTML());
@@ -49,7 +66,7 @@
currentWord = '';
}
updateCursorPosition();
}, 300);
}, 1000);
const handleSelectionChange = debounce(async () => {
const selection = editor?.view.state.selection;
@@ -63,6 +80,15 @@
}
}, 300);
// Special handler for touch events
function handleTouchEnd(event: TouchEvent) {
// Prevent default only if we have suggestions
if (suggestions.length > 0 || rhymes.length > 0) {
event.preventDefault();
}
handleSelectionChange();
}
function clearSuggestions() {
suggestions = [];
rhymes = [];
@@ -129,7 +155,7 @@
<div
class="container mx-auto my-8 dark relative px-4"
onmouseup={handleSelectionChange}
ontouchend={handleSelectionChange}
ontouchend={handleTouchEnd}
onmousedown={clearSuggestions}
ontouchstart={clearSuggestions}
role="textbox"
@@ -144,7 +170,7 @@
{#if suggestions.length > 0 || rhymes.length > 0}
<div
class="suggestions-container"
class="suggestions-container {isMobile ? 'mobile-suggestions' : ''}"
role="listbox"
aria-label="Suggestions and rhymes"
style:left="{cursorPosition.x}px"
@@ -184,5 +210,30 @@
box-shadow:
0 4px 6px -1px rgb(0 0 0 / 0.1),
0 2px 4px -2px rgb(0 0 0 / 0.1);
touch-action: manipulation;
background-color: white;
border-radius: 0.375rem;
}
/* Mobile-specific styles */
.mobile-suggestions {
max-width: 90vw;
width: 90vw;
max-height: 200px;
left: 50% !important; /* Override inline styles */
bottom: 20px !important;
top: auto !important;
position: fixed;
}
@media (max-width: 768px) {
.suggestions-container {
position: fixed;
bottom: 20px;
left: 50% !important;
transform: translateX(-50%);
top: auto !important;
width: 90vw;
}
}
</style>

View File

@@ -10,6 +10,13 @@
selectedIndex: number;
onSelect: (word: string) => void;
}>();
const isMobile = window.innerWidth < 768;
function handleTouchSelect(event: TouchEvent, word: string) {
event.preventDefault();
onSelect(word);
}
</script>
<div class="bg-white dark:bg-gray-800 shadow-lg rounded-md p-2 mb-2">
@@ -17,13 +24,28 @@
{#each suggestions.slice(0, 10) as { word }, i}
<button
type="button"
class="block w-full text-left px-2 py-1 hover:bg-gray-100 dark:hover:bg-gray-700 rounded
class="block w-full text-left px-2 {isMobile
? 'py-3'
: 'py-1'} hover:bg-gray-100 dark:hover:bg-gray-700 rounded
{selectedIndex === i ? 'bg-gray-100 dark:bg-gray-700' : ''}"
onmousedown={() => onSelect(word)}
ontouchstart={(e) => handleTouchSelect(e, word)}
role="option"
aria-selected={selectedIndex === i}
style:touch-action="manipulation"
>
{word}
</button>
{/each}
</div>
<style>
/* Mobile-specific styles */
@media (max-width: 768px) {
button {
padding: 12px 8px;
margin-bottom: 4px;
font-size: 16px; /* Minimum readable size on mobile */
}
}
</style>