Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 44 additions & 3 deletions src/lib/components/search/input.svelte
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
<script lang="ts">
import { getContext, type ComponentProps } from 'svelte';
import { getContext, onMount, type ComponentProps } from 'svelte';
import { createDialog, melt, type CreateDialogProps } from '@melt-ui/svelte';
import type TextInput from '../input/text.svelte';
import { preventDefault } from '$lib/utils';
import { goto } from '$app/navigation';
import { fade, scale } from 'svelte/transition';
import { StateHistory } from 'runed';
import * as m from '$lib/paraglide/messages';
import {
SearchRecordType,
Expand Down Expand Up @@ -35,12 +36,25 @@
let { ref = $bindable(), debug = false, class: className }: NameInputProps = $props();

let searchValue: string = $state('');

let selectedIndex: number = $state(0);
let previousIndex: number = $state(0);
let previousHistory = new StateHistory(
() => previousIndex,
(c) => (previousIndex = c)
);

let results: SearchRecord[] = $state(context.history.get());
let parent: SearchRecord | undefined = $state(undefined);
const history = new StateHistory(
() => parent,
(c) => (parent = c)
);

$effect(() => {
if (searchValue) {
if (parent && parent.children) {
results = parent.children;
} else if (searchValue) {
results = search(context, searchValue);
} else {
results = context.history.get();
Expand Down Expand Up @@ -96,6 +110,10 @@
onOpenChange: resetSelectedIndex
});

onMount(() => {
$open = true;
});

function handleKeydown(event: KeyboardEvent) {
// Focus the search input when the user presses '/' outside a text input or 'Cmd+k' anywhere
if (
Expand Down Expand Up @@ -137,6 +155,27 @@
event.preventDefault();
return;
}

if (event.key === 'ArrowLeft') {
if (parent) {
selectedIndex = previousIndex;
previousHistory.undo();
history.undo();
}
event.preventDefault();
return;
}

if (event.key === 'ArrowRight') {
let result = results[selectedIndex];
if (result.children && result.children.length > 0) {
parent = result;
previousIndex = selectedIndex;
selectedIndex = 0;
}
event.preventDefault();
return;
}
}
}

Expand Down Expand Up @@ -332,7 +371,9 @@
data-active={active}
class="hidden size-12 place-items-center text-mineShaft-50 group-hover/row:grid data-[active=true]:grid group-has-[:hover]/list:data-[active=true]:hidden group-has-[:hover]/list:group-hover/row:data-[active=true]:grid"
>
<ArrowRight />
{#if item.children && item.children.length > 0}
<ArrowRight />
{/if}
</div>
</Result>
</li>
Expand Down
13 changes: 12 additions & 1 deletion src/lib/components/search/result.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
<script lang="ts">
import { AppWindow, ArrowLeftRight, Box, Boxes, Key, UserSearch } from 'lucide-svelte';
import {
AppWindow,
ArrowLeftRight,
Box,
Boxes,
Key,
ReceiptText,
UserSearch
} from 'lucide-svelte';
import type { ComponentProps, Snippet } from 'svelte';
import * as m from '$lib/paraglide/messages';

Expand Down Expand Up @@ -33,6 +41,9 @@
{:else if record.type === SearchRecordType.BLOCK}
<Box class="size-4" />
<span>{record.value}</span>
{:else if record.type === SearchRecordType.CONTRACT}
<ReceiptText class="size-4" />
<span>{record.value}</span>
{:else if record.type === SearchRecordType.KEY}
<Key class="size-4" />
<span class="max-w-[12ch] truncate">
Expand Down
131 changes: 103 additions & 28 deletions src/lib/state/search.svelte.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ export enum SearchRecordType {
BLOCK = 'block',
// Clear all search history
CLEAR = 'clear',
// View a contract
CONTRACT = 'contract',
// View a key
KEY = 'key',
// Visit a page
Expand All @@ -31,6 +33,7 @@ export enum SearchRecordType {

export interface SearchRecord {
type: SearchRecordType;
children?: SearchRecord[];
data?: unknown; // arbitrary data field
value: string;
keywords?: string[];
Expand All @@ -43,27 +46,96 @@ export interface SearchRecord {
// export interface Favorite extends Record {}

export const SearchCommands: SearchRecord[] = [
{
value: 'Debug',
type: SearchRecordType.PAGE,
children: [
{
value: 'Debug 2',
type: SearchRecordType.PAGE,
children: [
{
value: 'Debug 3',
type: SearchRecordType.PAGE,
children: [],
keywords: ['debug', 'foo'],
description: '(no children)',
url: '/staking'
},
{
value: 'Debug 3',
type: SearchRecordType.PAGE,
children: [],
keywords: ['debug', 'foo'],
description: '(no children)',
url: '/staking'
},
{
value: 'Debug 3',
type: SearchRecordType.PAGE,
children: [
{
value: 'Debug 4',
type: SearchRecordType.PAGE,
children: [],
keywords: ['debug', 'foo'],
description: '(no children)',
url: '/staking'
},
{
value: 'Debug 4',
type: SearchRecordType.PAGE,
children: [],
keywords: ['debug', 'foo'],
description: '(no children)',
url: '/staking'
}
],
keywords: ['debug', 'foo'],
description: '(has children)',
url: '/staking'
}
],
keywords: ['debug', 'foo'],
description: '(has children)',
url: '/staking'
},
{
value: 'Debug 2',
type: SearchRecordType.PAGE,
children: [],
keywords: ['debug', 'foo'],
description: '(no children)',
url: '/staking'
}
],
keywords: ['debug', 'foo'],
description: '(has children)',
url: '/staking'
},
{
value: 'RAM Market',
type: SearchRecordType.PAGE,
children: [
{
value: 'Buy RAM',
type: SearchRecordType.PAGE,
keywords: ['ram', 'buy'],
description: 'Purchase RAM',
url: '/ram/buy'
},
{
value: 'Sell RAM',
type: SearchRecordType.PAGE,
keywords: ['ram', 'sell'],
description: 'Sell RAM',
url: '/ram/sell'
}
],
keywords: ['ram'],
description: 'Market Overview',
url: '/ram'
},
{
value: 'Buy RAM',
type: SearchRecordType.PAGE,
keywords: ['ram', 'buy'],
description: 'Purchase RAM',
url: '/ram/buy'
},
{
value: 'Sell RAM',
type: SearchRecordType.PAGE,
keywords: ['ram', 'sell'],
description: 'Sell RAM',
url: '/ram/sell'
},
{
value: 'Send',
type: SearchRecordType.PAGE,
Expand All @@ -81,24 +153,26 @@ export const SearchCommands: SearchRecord[] = [
{
value: 'Staking',
type: SearchRecordType.PAGE,
children: [
{
value: 'Stake',
type: SearchRecordType.PAGE,
keywords: ['stake'],
description: 'Stake tokens',
url: '/staking/stake'
},
{
value: 'Unstake',
type: SearchRecordType.PAGE,
keywords: ['unstake'],
description: 'Unstake tokens',
url: '/staking/unstake'
}
],
keywords: ['staking', 'stake'],
description: 'Staking overview',
url: '/staking'
},
{
value: 'Stake',
type: SearchRecordType.PAGE,
keywords: ['stake'],
description: 'Stake tokens',
url: '/staking/stake'
},
{
value: 'Unstake',
type: SearchRecordType.PAGE,
keywords: ['unstake'],
description: 'Unstake tokens',
url: '/staking/unstake'
},
{
value: 'Resources',
type: SearchRecordType.PAGE,
Expand Down Expand Up @@ -181,6 +255,7 @@ export function searchHistory(query: string, recentHistory: SearchRecordStorage)
export function getPossibleSearchTypes(value: string): SearchRecordType[] {
const types: SearchRecordType[] = [];
if (isSearchAccount(value)) types.push(SearchRecordType.ACCOUNT);
if (isSearchAccount(value)) types.push(SearchRecordType.CONTRACT);
if (isSearchBlock(value)) types.push(SearchRecordType.BLOCK);
if (isSearchKey(value)) types.push(SearchRecordType.KEY);
if (isSearchTransaction(value)) types.push(SearchRecordType.TRANSACTION);
Expand Down