Compare commits
No commits in common. "dropdown-menu" and "main" have entirely different histories.
dropdown-m
...
main
19 changed files with 15 additions and 569 deletions
|
@ -15,13 +15,11 @@
|
|||
"typesafe-i18n": "tsx scripts/import_translations.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@floating-ui/core": "^1.6.0",
|
||||
"@fontsource-variable/inter": "^5.0.16",
|
||||
"@mdi/js": "^7.4.47",
|
||||
"@resreq/event-hub": "^1.6.0",
|
||||
"daisyui": "^4.7.2",
|
||||
"fast-average-color": "^9.4.0",
|
||||
"svelte-floating-ui": "^1.5.8",
|
||||
"svelte-inview": "^4.0.2",
|
||||
"svelte-local-storage-store": "^0.6.4",
|
||||
"typesafe-i18n": "^5.26.2"
|
||||
|
|
|
@ -5,9 +5,6 @@ settings:
|
|||
excludeLinksFromLockfile: false
|
||||
|
||||
dependencies:
|
||||
'@floating-ui/core':
|
||||
specifier: ^1.6.0
|
||||
version: 1.6.0
|
||||
'@fontsource-variable/inter':
|
||||
specifier: ^5.0.16
|
||||
version: 5.0.16
|
||||
|
@ -23,9 +20,6 @@ dependencies:
|
|||
fast-average-color:
|
||||
specifier: ^9.4.0
|
||||
version: 9.4.0
|
||||
svelte-floating-ui:
|
||||
specifier: ^1.5.8
|
||||
version: 1.5.8
|
||||
svelte-inview:
|
||||
specifier: ^4.0.2
|
||||
version: 4.0.2(svelte@4.2.11)
|
||||
|
@ -398,15 +392,18 @@ packages:
|
|||
resolution: {integrity: sha512-PcF++MykgmTj3CIyOQbKA/hDzOAiqI3mhuoN44WRCopIs1sgoDoU4oty4Jtqaj/y3oDU6fnVSm4QG0a3t5i0+g==}
|
||||
dependencies:
|
||||
'@floating-ui/utils': 0.2.1
|
||||
dev: true
|
||||
|
||||
/@floating-ui/dom@1.6.3:
|
||||
resolution: {integrity: sha512-RnDthu3mzPlQ31Ss/BTwQ1zjzIhr3lk1gZB1OC56h/1vEtaXkESrOqL5fQVMfXpwGtRwX+YsZBdyHtJMQnkArw==}
|
||||
dependencies:
|
||||
'@floating-ui/core': 1.6.0
|
||||
'@floating-ui/utils': 0.2.1
|
||||
dev: true
|
||||
|
||||
/@floating-ui/utils@0.2.1:
|
||||
resolution: {integrity: sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==}
|
||||
dev: true
|
||||
|
||||
/@fontsource-variable/inter@5.0.16:
|
||||
resolution: {integrity: sha512-k+BUNqksTL+AN+o+OV7ILeiE9B5M5X+/jA7LWvCwjbV9ovXTqZyKRhA/x7uYv/ml8WQ0XNLBM7cRFIx4jW0/hg==}
|
||||
|
@ -2895,13 +2892,6 @@ packages:
|
|||
svelte: 4.2.11
|
||||
dev: true
|
||||
|
||||
/svelte-floating-ui@1.5.8:
|
||||
resolution: {integrity: sha512-dVvJhZ2bT+kQDHlE4Lep8t+sgEc0XD96fXLzAi2DDI2bsaegBbClxXVNMma0C2WsG+n9GJSYx292dTvA8CYRtw==}
|
||||
dependencies:
|
||||
'@floating-ui/core': 1.6.0
|
||||
'@floating-ui/dom': 1.6.3
|
||||
dev: false
|
||||
|
||||
/svelte-hmr@0.15.3(svelte@4.2.11):
|
||||
resolution: {integrity: sha512-41snaPswvSf8TJUhlkoJBekRrABDXDMdpNpT2tfHIv4JuhgvHqLMhEPGtaQn0BmbNSTkuz2Ed20DF2eHw0SmBQ==}
|
||||
engines: {node: ^12.20 || ^14.13.1 || >= 16}
|
||||
|
|
|
@ -1,150 +0,0 @@
|
|||
<script lang="ts">
|
||||
import swipeable from "$lib/util/actions/swipeable";
|
||||
import { type Coords, Direction } from "$lib/util/types";
|
||||
import { mdiCog } from "@mdi/js";
|
||||
import Icon from "$lib/components/ui/Icon.svelte";
|
||||
import { screenHeight } from "$lib/stores/layout";
|
||||
import { clamp } from "$lib/util/functions";
|
||||
|
||||
let offset = 50; // 0: top, 50: half
|
||||
|
||||
// onMount(reset);
|
||||
|
||||
let swiping = false;
|
||||
|
||||
function onSwipeStart() {
|
||||
swiping = true;
|
||||
}
|
||||
|
||||
function onSwipeMove(event: CustomEvent<Coords & { dx: number; dy: number }>) {
|
||||
let dperc = (event.detail.dy / $screenHeight) * 100;
|
||||
offset = clamp(offset + dperc, 0, 95);
|
||||
}
|
||||
|
||||
function onSwipeEnd(event: CustomEvent<{ direction: Direction | null }>) {
|
||||
if (offset > 60) {
|
||||
offset = 100;
|
||||
} else if (offset < 40) {
|
||||
offset = 0;
|
||||
} else {
|
||||
reset();
|
||||
}
|
||||
swiping = false;
|
||||
}
|
||||
|
||||
function reset() {
|
||||
swiping = false;
|
||||
offset = 50;
|
||||
}
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="bottomsheet h-full"
|
||||
class:extended={!swiping && offset === 0}
|
||||
style="top: {offset}%"
|
||||
use:swipeable={{ thresholdProvider: () => $screenHeight * 0.1 }}
|
||||
on:swipeStart={onSwipeStart}
|
||||
on:swipeMove={onSwipeMove}
|
||||
on:swipeEnd={onSwipeEnd}
|
||||
on:swipeFailed={reset}
|
||||
>
|
||||
<div>
|
||||
<div class="handle" />
|
||||
|
||||
<ul class="bottomsheet-menu">
|
||||
<li><Icon path={mdiCog} size={1.4} /><a>Item 1</a></li>
|
||||
<li><Icon path={mdiCog} size={1.4} /><a>Item 2</a></li>
|
||||
<li><Icon path={mdiCog} size={1.4} /><a>Item 3</a></li>
|
||||
<li><Icon path={mdiCog} size={1.4} /><a>Item 4</a></li>
|
||||
<li><Icon path={mdiCog} size={1.4} /><a>Item 5</a></li>
|
||||
<li><Icon path={mdiCog} size={1.4} /><a>Item 6</a></li>
|
||||
<li><Icon path={mdiCog} size={1.4} /><a>Item 7</a></li>
|
||||
<li><Icon path={mdiCog} size={1.4} /><a>Item 8</a></li>
|
||||
<li><Icon path={mdiCog} size={1.4} /><a>Item 9</a></li>
|
||||
<li><Icon path={mdiCog} size={1.4} /><a>Item 10</a></li>
|
||||
<li><Icon path={mdiCog} size={1.4} /><a>Item 11</a></li>
|
||||
<li><Icon path={mdiCog} size={1.4} /><a>Item 12</a></li>
|
||||
<li><Icon path={mdiCog} size={1.4} /><a>Item 13</a></li>
|
||||
<li><Icon path={mdiCog} size={1.4} /><a>Item 14</a></li>
|
||||
<li><Icon path={mdiCog} size={1.4} /><a>Item 15</a></li>
|
||||
<li><Icon path={mdiCog} size={1.4} /><a>Item 16</a></li>
|
||||
<li><Icon path={mdiCog} size={1.4} /><a>Item 17</a></li>
|
||||
<li><Icon path={mdiCog} size={1.4} /><a>Item 18</a></li>
|
||||
<li><Icon path={mdiCog} size={1.4} /><a>Item 19</a></li>
|
||||
<li><Icon path={mdiCog} size={1.4} /><a>Item 20</a></li>
|
||||
<li><Icon path={mdiCog} size={1.4} /><a>Item 21</a></li>
|
||||
<li><Icon path={mdiCog} size={1.4} /><a>Item 22</a></li>
|
||||
<li><Icon path={mdiCog} size={1.4} /><a>Item 23</a></li>
|
||||
<li><Icon path={mdiCog} size={1.4} /><a>Item 24</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="postcss">
|
||||
.bottomsheet {
|
||||
@apply fixed flex left-0 bottom-0 z-50 w-full select-none;
|
||||
|
||||
& > div {
|
||||
@apply bg-base-300 rounded-t-xl m-2 w-full h-full;
|
||||
@apply flex flex-col items-center;
|
||||
}
|
||||
|
||||
&.extended > div {
|
||||
@apply overflow-x-auto;
|
||||
}
|
||||
}
|
||||
|
||||
.handle {
|
||||
@apply w-12 h-1 m-2 flex-shrink-0 rounded-full bg-base-content/50;
|
||||
}
|
||||
|
||||
.bottomsheet-menu {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
|
||||
li {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 40px;
|
||||
@apply p-2 pr-4 gap-2;
|
||||
|
||||
.icon-r {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
& > a {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
@apply bg-base-content/10;
|
||||
}
|
||||
|
||||
&.noicon {
|
||||
grid-template-columns: [txt] 1fr;
|
||||
@apply px-2;
|
||||
}
|
||||
}
|
||||
|
||||
.item-sm {
|
||||
height: 1.75rem;
|
||||
@apply py-1;
|
||||
}
|
||||
}
|
||||
|
||||
.sep::before {
|
||||
border-bottom-width: 1px;
|
||||
border-bottom-style: solid;
|
||||
@apply border-b-neutral-content/50;
|
||||
content: "";
|
||||
left: 0;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
}
|
||||
</style>
|
|
@ -1,134 +0,0 @@
|
|||
<script lang="ts">
|
||||
import { TEST_MENU } from "./menus";
|
||||
import { type ContentAction } from "svelte-floating-ui";
|
||||
import TestCtxMenu2Item from "./TestCtxMenu2Item.svelte";
|
||||
import { kbd } from "@melt-ui/svelte/internal/helpers";
|
||||
import { writable, type Writable } from "svelte/store";
|
||||
import outclick from "$lib/util/actions/outclick";
|
||||
import { LIST_PAGENAV_N } from "$lib/util/constants";
|
||||
import { clamp } from "$lib/util/functions";
|
||||
|
||||
export let menu = TEST_MENU;
|
||||
export let menuOpen = false;
|
||||
export let floatingContent: ContentAction | (() => void) = () => {};
|
||||
export let mainMenuClose: (() => void) | undefined = undefined;
|
||||
export let submenuClose: (() => void) | undefined = undefined;
|
||||
|
||||
let menuElements: TestCtxMenu2Item[] = [];
|
||||
let openSubmenu: Writable<string | null> = writable(null);
|
||||
|
||||
export function open() {
|
||||
menuOpen = true;
|
||||
}
|
||||
|
||||
export function close() {
|
||||
menuOpen = false;
|
||||
}
|
||||
|
||||
export function toggle() {
|
||||
if (menuOpen) close();
|
||||
else open();
|
||||
}
|
||||
|
||||
export function focusFirst() {
|
||||
if (menuElements.length > 0 && getCurrentIndex() === -1) menuElements[0].focus();
|
||||
}
|
||||
|
||||
function getCurrentIndex(): number {
|
||||
return menuElements.findIndex((elm) => elm.getIsActive());
|
||||
}
|
||||
|
||||
function onKeydown(e: KeyboardEvent) {
|
||||
if (handleMenuNavigation(e)) {
|
||||
e.stopPropagation();
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/melt-ui/melt-ui/blob/develop/src/lib/builders/menu/create.ts
|
||||
|
||||
function handleMenuNavigation(e: KeyboardEvent): boolean {
|
||||
e.preventDefault();
|
||||
|
||||
// Index of the currently focused item in the candidate nodes array
|
||||
const currentIndex = getCurrentIndex();
|
||||
if (currentIndex === -1) return false;
|
||||
|
||||
// Calculate the index of the next menu item
|
||||
let nextIndex = currentIndex;
|
||||
switch (e.key) {
|
||||
case kbd.ARROW_DOWN:
|
||||
if (e.ctrlKey) nextIndex = menuElements.length - 1;
|
||||
else nextIndex++;
|
||||
break;
|
||||
case kbd.ARROW_UP:
|
||||
if (e.ctrlKey) nextIndex = 0;
|
||||
else nextIndex--;
|
||||
break;
|
||||
case kbd.HOME:
|
||||
nextIndex = 0;
|
||||
break;
|
||||
case kbd.END:
|
||||
nextIndex = menuElements.length - 1;
|
||||
break;
|
||||
case kbd.PAGE_DOWN:
|
||||
nextIndex += LIST_PAGENAV_N;
|
||||
break;
|
||||
case kbd.PAGE_UP:
|
||||
nextIndex -= LIST_PAGENAV_N;
|
||||
break;
|
||||
case kbd.ARROW_RIGHT:
|
||||
if (menu[currentIndex].submenu) {
|
||||
menuElements[currentIndex].focus(true, true);
|
||||
}
|
||||
return true;
|
||||
case kbd.ARROW_LEFT:
|
||||
if (submenuClose) {
|
||||
submenuClose();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
nextIndex = clamp(nextIndex, 0, menuElements.length - 1);
|
||||
menuElements[nextIndex].focus(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
function onOutclick() {
|
||||
console.log("outclick");
|
||||
menuOpen = false;
|
||||
openSubmenu.set(null);
|
||||
}
|
||||
|
||||
const condOutclick = submenuClose ? () => {} : outclick;
|
||||
</script>
|
||||
|
||||
<svelte:window
|
||||
on:keydown={(e) => {
|
||||
if (e.key === kbd.ESCAPE) {
|
||||
onOutclick();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
{#if menuOpen}
|
||||
<div
|
||||
class="ctxmenu"
|
||||
role="menu"
|
||||
use:floatingContent
|
||||
tabindex={submenuClose ? -1 : 0}
|
||||
on:keydown={onKeydown}
|
||||
use:condOutclick
|
||||
on:outclick={onOutclick}
|
||||
>
|
||||
{#each menu as menuItem, i}
|
||||
<TestCtxMenu2Item
|
||||
{menuItem}
|
||||
{openSubmenu}
|
||||
mainMenuClose={mainMenuClose ?? close}
|
||||
bind:this={menuElements[i]}
|
||||
/>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
|
@ -1,114 +0,0 @@
|
|||
<script lang="ts">
|
||||
import LL from "$i18n/i18n-svelte";
|
||||
import { mdiMenuRight } from "@mdi/js";
|
||||
import { type CtxMenuEntry } from "./menus";
|
||||
import Icon from "$lib/components/ui/Icon.svelte";
|
||||
import { createFloatingActions } from "svelte-floating-ui";
|
||||
import { shift, flip, offset } from "svelte-floating-ui/dom";
|
||||
import TestCtxMenu2 from "./TestCtxMenu2.svelte";
|
||||
import { generateId, kbd, sleep } from "@melt-ui/svelte/internal/helpers";
|
||||
import type { Writable } from "svelte/store";
|
||||
|
||||
export let menuItem: CtxMenuEntry;
|
||||
export let openSubmenu: Writable<string | null>;
|
||||
export let mainMenuClose: (() => void) | undefined = undefined;
|
||||
|
||||
let [floatingRef, floatingContent] = menuItem.submenu
|
||||
? createFloatingActions({
|
||||
strategy: "absolute",
|
||||
placement: "right-start",
|
||||
middleware: [shift(), flip(), offset(4)]
|
||||
})
|
||||
: [() => {}, () => {}];
|
||||
|
||||
let itemElm: HTMLElement;
|
||||
let submenuElm: TestCtxMenu2 | undefined;
|
||||
let active = false;
|
||||
let id = generateId();
|
||||
|
||||
// @ts-expect-error ignore localization arguments
|
||||
$: title = $LL[menuItem.title]();
|
||||
$: submenuOpen = $openSubmenu === id;
|
||||
|
||||
export function getId(): string {
|
||||
return id;
|
||||
}
|
||||
|
||||
export function getElement(): HTMLElement {
|
||||
return itemElm;
|
||||
}
|
||||
|
||||
export function getIsActive(): boolean {
|
||||
return active;
|
||||
}
|
||||
|
||||
export function focus(sm = false, jump = false) {
|
||||
active = true;
|
||||
itemElm.focus();
|
||||
if (sm) {
|
||||
openSubmenu.set(menuItem.submenu ? id : null);
|
||||
if (jump) {
|
||||
sleep(1).then(() => submenuElm?.focusFirst());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function submenuClose() {
|
||||
openSubmenu.set(null);
|
||||
focus();
|
||||
}
|
||||
|
||||
function unfocus() {
|
||||
active = false;
|
||||
itemElm.blur();
|
||||
}
|
||||
|
||||
function onKeyup(e: KeyboardEvent) {
|
||||
if (e.key === kbd.ENTER) {
|
||||
clickAction();
|
||||
e.stopPropagation();
|
||||
}
|
||||
}
|
||||
|
||||
function onClick(e: MouseEvent) {
|
||||
focus(true);
|
||||
clickAction();
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
function clickAction() {
|
||||
if(menuItem.onClick) menuItem.onClick();
|
||||
if (mainMenuClose) mainMenuClose();
|
||||
}
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="item"
|
||||
role="menuitem"
|
||||
use:floatingRef
|
||||
tabindex={active ? 0 : -1}
|
||||
bind:this={itemElm}
|
||||
on:click={onClick}
|
||||
on:keyup={onKeyup}
|
||||
on:mouseenter={() => focus(true)}
|
||||
on:mouseleave={unfocus}
|
||||
on:focus={() => (active = true)}
|
||||
on:blur={() => (active = false)}
|
||||
>
|
||||
{#if menuItem.icon}
|
||||
<Icon path={menuItem.icon} size={1.4} />
|
||||
{/if}
|
||||
<span>{title}</span>
|
||||
{#if menuItem.submenu}
|
||||
<div class="icon-r"><Icon path={mdiMenuRight} /></div>
|
||||
|
||||
<TestCtxMenu2
|
||||
menu={menuItem.submenu}
|
||||
menuOpen={submenuOpen}
|
||||
{floatingContent}
|
||||
{mainMenuClose}
|
||||
{submenuClose}
|
||||
bind:this={submenuElm}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
|
@ -1,66 +0,0 @@
|
|||
import type { TranslationFunctions } from "$i18n/i18n-types";
|
||||
import {
|
||||
mdiContentCopy,
|
||||
mdiDownload,
|
||||
mdiPlaylistPlay,
|
||||
mdiPlaylistPlus,
|
||||
mdiShare,
|
||||
} from "@mdi/js";
|
||||
|
||||
export type CtxMenuEntry = {
|
||||
/** Item text (translation key) */
|
||||
title: keyof TranslationFunctions;
|
||||
/** Item icon */
|
||||
icon?: string;
|
||||
/** Item click action */
|
||||
onClick?: () => void;
|
||||
/** Place a separator before the menu item */
|
||||
separator?: boolean;
|
||||
/** Submenu entries */
|
||||
submenu?: CtxMenuEntry[];
|
||||
key?: string;
|
||||
};
|
||||
|
||||
export const TEST_MENU: CtxMenuEntry[] = [
|
||||
{
|
||||
title: "play_next",
|
||||
icon: mdiPlaylistPlay,
|
||||
onClick: () => console.log("play_next"),
|
||||
key: "n",
|
||||
},
|
||||
{
|
||||
title: "add_to_queue",
|
||||
icon: mdiPlaylistPlus,
|
||||
key: "q",
|
||||
},
|
||||
{
|
||||
title: "share",
|
||||
icon: mdiShare,
|
||||
separator: true,
|
||||
submenu: [
|
||||
{
|
||||
title: "copy_url",
|
||||
icon: mdiContentCopy,
|
||||
},
|
||||
{
|
||||
title: "download_audio_file",
|
||||
icon: mdiDownload,
|
||||
},
|
||||
{
|
||||
title: "share",
|
||||
icon: mdiShare,
|
||||
separator: true,
|
||||
submenu: [
|
||||
{
|
||||
title: "copy_url",
|
||||
icon: mdiContentCopy,
|
||||
},
|
||||
{
|
||||
title: "download_audio_file",
|
||||
icon: mdiDownload,
|
||||
},
|
||||
],
|
||||
}
|
||||
],
|
||||
}
|
||||
];
|
|
@ -10,8 +10,8 @@ The header sticks to the top of the page when scrolling down. -->
|
|||
import type { Color } from "$lib/util/types";
|
||||
import {
|
||||
COLOR_B3,
|
||||
DROPDOWN_CFG,
|
||||
MIN_CONTRAST_TITLE,
|
||||
POSITIONING_DROPDOWN,
|
||||
} from "$lib/util/constants";
|
||||
|
||||
import ImgFrame from "$lib/components/ui/ImgFrame.svelte";
|
||||
|
@ -50,7 +50,7 @@ The header sticks to the top of the page when scrolling down. -->
|
|||
elements: { trigger, menu, item },
|
||||
builders: { createSubmenu },
|
||||
states: { open: ddnOpen },
|
||||
} = createDropdownMenu(DROPDOWN_CFG);
|
||||
} = createDropdownMenu({ positioning: POSITIONING_DROPDOWN });
|
||||
</script>
|
||||
|
||||
<div
|
||||
|
|
|
@ -2,14 +2,14 @@
|
|||
import LL from "$i18n/i18n-svelte";
|
||||
import { melt, createDropdownMenu } from "@melt-ui/svelte";
|
||||
|
||||
import { DROPDOWN_CFG } from "$lib/util/constants";
|
||||
import { POSITIONING_DROPDOWN } from "$lib/util/constants";
|
||||
|
||||
import SettingsMenu from "$lib/components/contextmenu/OptionsMenu.svelte";
|
||||
|
||||
const {
|
||||
elements: { trigger, menu, item },
|
||||
states: { open },
|
||||
} = createDropdownMenu(DROPDOWN_CFG);
|
||||
} = createDropdownMenu({ positioning: POSITIONING_DROPDOWN });
|
||||
</script>
|
||||
|
||||
<button
|
||||
|
|
|
@ -192,12 +192,6 @@
|
|||
return;
|
||||
}
|
||||
return;
|
||||
case kbd.HOME:
|
||||
nextSel = 0;
|
||||
break;
|
||||
case kbd.END:
|
||||
nextSel = tracks.length - 1;
|
||||
break;
|
||||
case kbd.PAGE_UP:
|
||||
nextSel -= LIST_PAGENAV_N;
|
||||
break;
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
formatDuration,
|
||||
} from "$lib/util/functions";
|
||||
import { mainPhone } from "$lib/stores/layout";
|
||||
import { CTXMENU_CFG, DROPDOWN_CFG } from "$lib/util/constants";
|
||||
import { POSITIONING_DROPDOWN } from "$lib/util/constants";
|
||||
import { ListView, type FilteredItem, type Track, Direction } from "$lib/util/types";
|
||||
|
||||
import Icon from "$lib/components/ui/Icon.svelte";
|
||||
|
@ -65,12 +65,12 @@
|
|||
elements: { trigger: ctxTrigger, menu: ctxMenu, item: ctxItem },
|
||||
builders: { createSubmenu: createCtxSubmenu },
|
||||
states: { open: ctxOpen },
|
||||
} = createContextMenu(CTXMENU_CFG);
|
||||
} = createContextMenu();
|
||||
const {
|
||||
elements: { trigger: ddnTrigger, menu: ddnMenu, item: ddnItem },
|
||||
builders: { createSubmenu: createDdnSubmenu },
|
||||
states: { open: ddnOpen },
|
||||
} = createDropdownMenu(DROPDOWN_CFG);
|
||||
} = createDropdownMenu({ positioning: POSITIONING_DROPDOWN });
|
||||
</script>
|
||||
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
import NavbarMobileItem from "./NavbarMobileItem.svelte";
|
||||
</script>
|
||||
|
||||
<div class="btm-nav btm-nav-sm text-xs bg-base-300 z-20">
|
||||
<div class="btm-nav btm-nav-sm text-xs bg-base-300 z-50">
|
||||
<NavbarMobileItem
|
||||
title={$LL.home()}
|
||||
icon={mdiHomeOutline}
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
import { clientState, toggleShowQueue } from "$lib/stores/clientState";
|
||||
import { formatDuration } from "$lib/util/functions";
|
||||
import { testTrack } from "$lib/util/testdata";
|
||||
import { DROPDOWN_CFG } from "$lib/util/constants";
|
||||
import { POSITIONING_DROPDOWN } from "$lib/util/constants";
|
||||
|
||||
let position = 81;
|
||||
let displayPosition = position;
|
||||
|
@ -39,7 +39,7 @@
|
|||
elements: { trigger, menu, item },
|
||||
builders: { createSubmenu },
|
||||
states: { open: ddnOpen },
|
||||
} = createDropdownMenu(DROPDOWN_CFG);
|
||||
} = createDropdownMenu({ positioning: POSITIONING_DROPDOWN });
|
||||
</script>
|
||||
|
||||
<div id="playerbar">
|
||||
|
|
|
@ -69,7 +69,7 @@
|
|||
|
||||
<div
|
||||
id="playerbar-mobile"
|
||||
class="shadow rounded-md z-20"
|
||||
class="shadow rounded-md z-50"
|
||||
class:transition-colors={colorTrans}
|
||||
style={`background-color: ${bgColorHex}`}
|
||||
aria-label={$LL.now_playing({ title: track.name, artist: track.artists[0].name })}
|
||||
|
|
|
@ -5,53 +5,6 @@ import type { Color } from "./types";
|
|||
|
||||
const YELLOW: Color = { r: 255, g: 255, b: 127 };
|
||||
|
||||
describe.each([
|
||||
{
|
||||
hex: "#ffffff",
|
||||
color: { r: 255, g: 255, b: 255 },
|
||||
},
|
||||
{
|
||||
hex: "#000000",
|
||||
color: { r: 0, g: 0, b: 0 },
|
||||
},
|
||||
{
|
||||
hex: "#ff0000",
|
||||
color: { r: 255, g: 0, b: 0 },
|
||||
},
|
||||
{
|
||||
hex: "#00ff00",
|
||||
color: { r: 0, g: 255, b: 0 },
|
||||
},
|
||||
{
|
||||
hex: "#0000ff",
|
||||
color: { r: 0, g: 0, b: 255 },
|
||||
},
|
||||
{
|
||||
hex: "#8ECAE6",
|
||||
color: { r: 142, g: 202, b: 230 },
|
||||
},
|
||||
{
|
||||
hex: "#219EBC",
|
||||
color: { r: 33, g: 158, b: 188 },
|
||||
},
|
||||
{
|
||||
hex: "#023047",
|
||||
color: { r: 2, g: 48, b: 71 },
|
||||
},
|
||||
{
|
||||
hex: "#FFB703",
|
||||
color: { r: 255, g: 183, b: 3 },
|
||||
},
|
||||
{
|
||||
hex: "#FB8500",
|
||||
color: { r: 251, g: 133, b: 0 },
|
||||
},
|
||||
])("color conversion", ({ hex, color }) => {
|
||||
it("colorToHex", () => {
|
||||
expect(colorToHex(color)).toBe(hex.toLowerCase());
|
||||
});
|
||||
});
|
||||
|
||||
describe("correctBgColor", () => {
|
||||
it("yellow", () => {
|
||||
expect(correctBgColor(WHITE, YELLOW, 5)).toEqual({ r: 114, g: 114, b: 57 });
|
||||
|
|
|
@ -26,9 +26,6 @@ export const POSITIONING_SUBMENU: FloatingConfig = {
|
|||
export const POSITIONING_DROPDOWN: FloatingConfig = {
|
||||
placement: "bottom-start",
|
||||
};
|
||||
export const SUBMENU_CFG = { arrowSize: 0, positioning: POSITIONING_SUBMENU };
|
||||
export const CTXMENU_CFG = { positioning: POSITIONING_DROPDOWN, typeahead: false };
|
||||
export const DROPDOWN_CFG = { positioning: POSITIONING_DROPDOWN };
|
||||
|
||||
// Future config options
|
||||
export const DATE_LANG = "de";
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script lang="ts">
|
||||
import "@fontsource-variable/inter";
|
||||
import "../style/app.pcss"; // eslint-disable-line no-relative-import-paths/no-relative-import-paths
|
||||
import "../style/app.css"; // eslint-disable-line no-relative-import-paths/no-relative-import-paths
|
||||
|
||||
import { onMount } from "svelte";
|
||||
import { page } from "$app/stores";
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
import ContentHeader from "$lib/components/header/ContentHeader.svelte";
|
||||
import AvatarBadge from "$lib/components/ui/AvatarBadge.svelte";
|
||||
import SimpleWrapper from "$lib/components/layout/SimpleWrapper.svelte";
|
||||
import BottomSheet from "$lib/components/contextmenu/BottomSheet.svelte";
|
||||
|
||||
export let data: PageData;
|
||||
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
<script lang="ts">
|
||||
import TestCtxMenu2 from "$lib/components/contextmenu/TestCtxMenu2.svelte";
|
||||
import { kbd } from "@melt-ui/svelte/internal/helpers";
|
||||
|
||||
let ctxmenu: TestCtxMenu2;
|
||||
</script>
|
||||
|
||||
<div class="m-4">
|
||||
<button class="btn" data-melt-menu-id="1" on:click={() => ctxmenu.toggle()} on:keydown={(e) => {
|
||||
if (e.key === kbd.ARROW_DOWN) {
|
||||
ctxmenu.open();
|
||||
ctxmenu.focusFirst();
|
||||
}
|
||||
}}>Dropdown</button>
|
||||
|
||||
<TestCtxMenu2 bind:this={ctxmenu} />
|
||||
</div>
|
|
@ -76,7 +76,3 @@ mark {
|
|||
max-width: 300px;
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
.thin-line {
|
||||
@apply border-base-content/20 border-solid border-[1px];
|
||||
}
|
Loading…
Reference in a new issue