mirror of
https://github.com/seanmorley15/AdventureLog.git
synced 2025-12-23 22:58:17 -05:00
Fix Safari category dropdown and emoji picker event handling
Co-authored-by: seanmorley15 <98704938+seanmorley15@users.noreply.github.com>
This commit is contained in:
52
frontend/package-lock.json
generated
52
frontend/package-lock.json
generated
@@ -1,48 +1,48 @@
|
||||
{
|
||||
"name": "adventurelog-frontend",
|
||||
"version": "0.10.0",
|
||||
"version": "0.11.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "adventurelog-frontend",
|
||||
"version": "0.10.0",
|
||||
"version": "0.11.0",
|
||||
"dependencies": {
|
||||
"@lukulent/svelte-umami": "^0.0.3",
|
||||
"dompurify": "^3.2.4",
|
||||
"emoji-picker-element": "^1.26.0",
|
||||
"dompurify": "^3.2.5",
|
||||
"emoji-picker-element": "^1.26.3",
|
||||
"gsap": "^3.12.7",
|
||||
"luxon": "^3.6.1",
|
||||
"marked": "^15.0.4",
|
||||
"marked": "^15.0.11",
|
||||
"psl": "^1.15.0",
|
||||
"qrcode": "^1.5.4",
|
||||
"svelte-i18n": "^4.0.1",
|
||||
"svelte-maplibre": "^0.9.8"
|
||||
"svelte-maplibre": "^0.9.14"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@event-calendar/core": "^3.7.1",
|
||||
"@event-calendar/day-grid": "^3.7.1",
|
||||
"@event-calendar/core": "^3.12.0",
|
||||
"@event-calendar/day-grid": "^3.12.0",
|
||||
"@event-calendar/interaction": "^3.12.0",
|
||||
"@event-calendar/time-grid": "^3.7.1",
|
||||
"@iconify-json/mdi": "^1.1.67",
|
||||
"@sveltejs/adapter-node": "^5.2.0",
|
||||
"@sveltejs/adapter-vercel": "^5.4.1",
|
||||
"@sveltejs/kit": "^2.8.3",
|
||||
"@sveltejs/vite-plugin-svelte": "^3.1.1",
|
||||
"@tailwindcss/typography": "^0.5.13",
|
||||
"@types/node": "^22.5.4",
|
||||
"@event-calendar/time-grid": "^3.12.0",
|
||||
"@iconify-json/mdi": "^1.2.3",
|
||||
"@sveltejs/adapter-node": "^5.2.12",
|
||||
"@sveltejs/adapter-vercel": "^5.7.0",
|
||||
"@sveltejs/kit": "^2.20.7",
|
||||
"@sveltejs/vite-plugin-svelte": "^3.1.2",
|
||||
"@tailwindcss/typography": "^0.5.16",
|
||||
"@types/node": "^22.15.2",
|
||||
"@types/qrcode": "^1.5.5",
|
||||
"autoprefixer": "^10.4.19",
|
||||
"daisyui": "^4.12.6",
|
||||
"postcss": "^8.4.38",
|
||||
"prettier": "^3.3.2",
|
||||
"prettier-plugin-svelte": "^3.2.5",
|
||||
"autoprefixer": "^10.4.21",
|
||||
"daisyui": "^4.12.24",
|
||||
"postcss": "^8.5.3",
|
||||
"prettier": "^3.5.3",
|
||||
"prettier-plugin-svelte": "^3.3.3",
|
||||
"svelte": "^4.2.19",
|
||||
"svelte-check": "^3.8.1",
|
||||
"tailwindcss": "^3.4.4",
|
||||
"tslib": "^2.6.3",
|
||||
"typescript": "^5.5.2",
|
||||
"unplugin-icons": "^0.19.0",
|
||||
"svelte-check": "^3.8.6",
|
||||
"tailwindcss": "^3.4.17",
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^5.8.3",
|
||||
"unplugin-icons": "^0.19.3",
|
||||
"vite": "^5.4.19"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -23,11 +23,13 @@
|
||||
let isOpen: boolean = false;
|
||||
let isEmojiPickerVisible: boolean = false;
|
||||
|
||||
function toggleEmojiPicker() {
|
||||
function toggleEmojiPicker(event: Event) {
|
||||
event.stopPropagation();
|
||||
isEmojiPickerVisible = !isEmojiPickerVisible;
|
||||
}
|
||||
|
||||
function toggleDropdown() {
|
||||
function toggleDropdown(event: Event) {
|
||||
event.stopPropagation();
|
||||
isOpen = !isOpen;
|
||||
}
|
||||
|
||||
@@ -35,9 +37,12 @@
|
||||
console.log('category', category);
|
||||
selected_category = category;
|
||||
isOpen = false;
|
||||
isEmojiPickerVisible = false;
|
||||
}
|
||||
|
||||
function custom_category() {
|
||||
function custom_category(event: Event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
new_category.name = new_category.display_name.toLowerCase().replace(/ /g, '_');
|
||||
if (!new_category.icon) {
|
||||
new_category.icon = '🌎'; // Default icon if none selected
|
||||
@@ -46,7 +51,16 @@
|
||||
}
|
||||
|
||||
function handleEmojiSelect(event: CustomEvent) {
|
||||
event.stopPropagation();
|
||||
new_category.icon = event.detail.unicode;
|
||||
isEmojiPickerVisible = false;
|
||||
}
|
||||
|
||||
function handleInputKeydown(event: KeyboardEvent) {
|
||||
if (event.key === 'Enter') {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
}
|
||||
|
||||
// Close dropdown when clicking outside
|
||||
@@ -76,9 +90,9 @@
|
||||
|
||||
<div class="dropdown w-full" bind:this={dropdownRef}>
|
||||
<!-- Main dropdown trigger -->
|
||||
<div
|
||||
<button
|
||||
type="button"
|
||||
tabindex="0"
|
||||
role="button"
|
||||
class="btn btn-outline w-full justify-between sm:h-auto h-12"
|
||||
on:click={toggleDropdown}
|
||||
>
|
||||
@@ -98,21 +112,33 @@
|
||||
>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
{#if isOpen}
|
||||
<!-- Mobile Modal Overlay (only on small screens) -->
|
||||
<div class="fixed inset-0 bg-black/50 z-40 sm:hidden" on:click={() => (isOpen = false)}></div>
|
||||
<div
|
||||
class="fixed inset-0 bg-black/50 z-40 sm:hidden"
|
||||
role="presentation"
|
||||
on:click|stopPropagation={() => (isOpen = false)}
|
||||
on:keydown={(e) => e.key === 'Escape' && (isOpen = false)}
|
||||
></div>
|
||||
|
||||
<!-- Mobile Bottom Sheet -->
|
||||
<div
|
||||
class="fixed bottom-0 left-0 right-0 z-50 bg-base-100 rounded-t-2xl shadow-2xl border-t border-base-300 max-h-[90vh] flex flex-col sm:hidden"
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
on:click|stopPropagation
|
||||
>
|
||||
<!-- Mobile Header -->
|
||||
<div class="flex-shrink-0 bg-base-100 border-b border-base-300 p-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<h2 class="text-lg font-semibold">{$t('categories.select_category')}</h2>
|
||||
<button class="btn btn-ghost btn-sm btn-circle" on:click={() => (isOpen = false)}>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-ghost btn-sm btn-circle"
|
||||
on:click|stopPropagation={() => (isOpen = false)}
|
||||
>
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
@@ -147,6 +173,8 @@
|
||||
placeholder={$t('categories.category_name')}
|
||||
class="input input-bordered w-full h-12 text-base"
|
||||
bind:value={new_category.display_name}
|
||||
on:keydown={handleInputKeydown}
|
||||
on:click|stopPropagation
|
||||
/>
|
||||
<div class="join w-full">
|
||||
<input
|
||||
@@ -154,6 +182,8 @@
|
||||
placeholder={$t('categories.icon')}
|
||||
class="input input-bordered join-item flex-1 h-12 text-base"
|
||||
bind:value={new_category.icon}
|
||||
on:keydown={handleInputKeydown}
|
||||
on:click|stopPropagation
|
||||
/>
|
||||
<button
|
||||
on:click={toggleEmojiPicker}
|
||||
@@ -184,7 +214,12 @@
|
||||
</button>
|
||||
|
||||
{#if isEmojiPickerVisible}
|
||||
<div class="p-3 rounded-lg border border-base-300 bg-base-50">
|
||||
<div
|
||||
class="p-3 rounded-lg border border-base-300 bg-base-50"
|
||||
role="dialog"
|
||||
aria-label="Emoji picker"
|
||||
on:click|stopPropagation
|
||||
>
|
||||
<emoji-picker on:emoji-click={handleEmojiSelect}></emoji-picker>
|
||||
</div>
|
||||
{/if}
|
||||
@@ -204,6 +239,8 @@
|
||||
placeholder={$t('navbar.search')}
|
||||
class="input input-bordered w-full h-12 text-base"
|
||||
bind:value={searchTerm}
|
||||
on:keydown={handleInputKeydown}
|
||||
on:click|stopPropagation
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -221,7 +258,7 @@
|
||||
class:text-primary-content={selected_category &&
|
||||
selected_category.id === category.id}
|
||||
class:border-primary={selected_category && selected_category.id === category.id}
|
||||
on:click={() => selectCategory(category)}
|
||||
on:click|stopPropagation={() => selectCategory(category)}
|
||||
>
|
||||
<div class="flex items-center gap-3 w-full">
|
||||
<span class="text-2xl flex-shrink-0">{category.icon}</span>
|
||||
@@ -247,6 +284,7 @@
|
||||
<!-- Desktop Dropdown -->
|
||||
<div
|
||||
class="dropdown-content z-[1] w-full mt-1 bg-base-300 rounded-box shadow-xl border border-base-300 max-h-96 overflow-y-auto hidden sm:block"
|
||||
on:click|stopPropagation
|
||||
>
|
||||
<!-- Desktop Category Creator Section -->
|
||||
<div class="p-4 border-b border-base-300">
|
||||
@@ -270,6 +308,8 @@
|
||||
placeholder={$t('categories.category_name')}
|
||||
class="input input-bordered input-sm w-full"
|
||||
bind:value={new_category.display_name}
|
||||
on:keydown={handleInputKeydown}
|
||||
on:click|stopPropagation
|
||||
/>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
@@ -279,6 +319,8 @@
|
||||
placeholder={$t('categories.icon')}
|
||||
class="input input-bordered input-sm flex-1"
|
||||
bind:value={new_category.icon}
|
||||
on:keydown={handleInputKeydown}
|
||||
on:click|stopPropagation
|
||||
/>
|
||||
<button
|
||||
on:click={toggleEmojiPicker}
|
||||
@@ -312,7 +354,12 @@
|
||||
</div>
|
||||
|
||||
{#if isEmojiPickerVisible}
|
||||
<div class="p-3 rounded-lg border border-base-300">
|
||||
<div
|
||||
class="p-3 rounded-lg border border-base-300"
|
||||
role="dialog"
|
||||
aria-label="Emoji picker"
|
||||
on:click|stopPropagation
|
||||
>
|
||||
<emoji-picker on:emoji-click={handleEmojiSelect}></emoji-picker>
|
||||
</div>
|
||||
{/if}
|
||||
@@ -340,6 +387,8 @@
|
||||
placeholder={$t('navbar.search')}
|
||||
class="input input-bordered input-sm w-full"
|
||||
bind:value={searchTerm}
|
||||
on:keydown={handleInputKeydown}
|
||||
on:click|stopPropagation
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -356,7 +405,7 @@
|
||||
type="button"
|
||||
class="btn btn-ghost btn-sm justify-start h-auto py-2 px-3"
|
||||
class:btn-active={selected_category && selected_category.id === category.id}
|
||||
on:click={() => selectCategory(category)}
|
||||
on:click|stopPropagation={() => selectCategory(category)}
|
||||
role="option"
|
||||
aria-selected={selected_category && selected_category.id === category.id}
|
||||
>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user