@rainlanguage/ui-components 0.0.1-alpha.154 → 0.0.1-alpha.155
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/ListViewOrderbookFilters.svelte +1 -1
- package/dist/components/ListViewOrderbookFilters.svelte.d.ts +11 -9
- package/dist/components/OrderOrVaultHash.svelte.d.ts +1 -1
- package/dist/components/TanstackAppTable.svelte +9 -4
- package/dist/components/TanstackAppTable.svelte.d.ts +8 -7
- package/dist/components/VaultCard.svelte +18 -0
- package/dist/components/VaultCard.svelte.d.ts +19 -0
- package/dist/components/charts/LightweightChart.svelte +1 -1
- package/dist/components/charts/LightweightChart.svelte.d.ts +5 -5
- package/dist/components/charts/VaultBalanceChart.svelte +7 -16
- package/dist/components/charts/VaultBalanceChart.svelte.d.ts +1 -5
- package/dist/components/deployment/DeploymentSteps.svelte +1 -26
- package/dist/components/deployment/DepositInput.svelte +4 -4
- package/dist/components/deployment/SelectToken.svelte +20 -69
- package/dist/components/deployment/SelectToken.svelte.d.ts +1 -3
- package/dist/components/deployment/TokenSelectionModal.svelte +72 -45
- package/dist/components/deployment/TokenSelectionModal.svelte.d.ts +0 -3
- package/dist/components/detail/OrderDetail.svelte +58 -16
- package/dist/components/detail/OrderDetail.svelte.d.ts +4 -1
- package/dist/components/detail/TanstackOrderQuote.svelte +1 -1
- package/dist/components/detail/TanstackOrderQuote.svelte.d.ts +12 -10
- package/dist/components/detail/VaultDetail.svelte +3 -4
- package/dist/components/detail/VaultDetail.svelte.d.ts +0 -3
- package/dist/components/input/InputTokenAmount.svelte +15 -20
- package/dist/components/input/InputTokenAmount.svelte.d.ts +3 -3
- package/dist/components/tables/OrderAPY.svelte +5 -25
- package/dist/components/tables/OrderAPY.svelte.d.ts +1 -4
- package/dist/components/tables/OrderTradesListTable.svelte +3 -2
- package/dist/components/tables/OrderVaultsVolTable.svelte +30 -23
- package/dist/components/tables/OrderVaultsVolTable.svelte.d.ts +1 -4
- package/dist/components/tables/OrdersListTable.svelte +31 -8
- package/dist/components/tables/OrdersListTable.svelte.d.ts +11 -9
- package/dist/components/tables/VaultBalanceChangesTable.svelte +1 -1
- package/dist/components/tables/VaultBalanceChangesTable.svelte.d.ts +11 -9
- package/dist/components/tables/VaultsListTable.svelte +119 -7
- package/dist/components/tables/VaultsListTable.svelte.d.ts +13 -10
- package/dist/providers/transactions/TransactionManager.d.ts +26 -2
- package/dist/providers/transactions/TransactionManager.js +61 -4
- package/dist/types/modal.d.ts +2 -2
- package/dist/types/transaction.d.ts +1 -0
- package/dist/types/transaction.js +1 -0
- package/package.json +2 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<script
|
|
1
|
+
<script>import { useRaindexClient } from "../hooks/useRaindexClient";
|
|
2
2
|
import DropdownActiveNetworks from "./dropdown/DropdownActiveNetworks.svelte";
|
|
3
3
|
import { page } from "$app/stores";
|
|
4
4
|
import { isEmpty } from "lodash";
|
|
@@ -3,8 +3,8 @@ import type { QueryObserverResult } from '@tanstack/svelte-query';
|
|
|
3
3
|
import type { Readable } from 'svelte/store';
|
|
4
4
|
import type { Address, RaindexVaultToken } from '@rainlanguage/orderbook';
|
|
5
5
|
import type { AppStoresInterface } from '../types/appStores';
|
|
6
|
-
declare
|
|
7
|
-
props
|
|
6
|
+
declare const __propDef: {
|
|
7
|
+
props: {
|
|
8
8
|
hideZeroBalanceVaults: AppStoresInterface["hideZeroBalanceVaults"];
|
|
9
9
|
activeAccountsItems: AppStoresInterface["activeAccountsItems"];
|
|
10
10
|
showMyItemsOnly: AppStoresInterface["showMyItemsOnly"];
|
|
@@ -15,14 +15,16 @@ declare class __sveltets_Render<T> {
|
|
|
15
15
|
selectedTokens: Address[];
|
|
16
16
|
tokensQuery: Readable<QueryObserverResult<RaindexVaultToken[], Error>>;
|
|
17
17
|
};
|
|
18
|
-
events
|
|
18
|
+
events: {
|
|
19
19
|
[evt: string]: CustomEvent<any>;
|
|
20
20
|
};
|
|
21
|
-
slots
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
export type
|
|
26
|
-
export
|
|
21
|
+
slots: {};
|
|
22
|
+
exports?: {} | undefined;
|
|
23
|
+
bindings?: string | undefined;
|
|
24
|
+
};
|
|
25
|
+
export type ListViewOrderbookFiltersProps = typeof __propDef.props;
|
|
26
|
+
export type ListViewOrderbookFiltersEvents = typeof __propDef.events;
|
|
27
|
+
export type ListViewOrderbookFiltersSlots = typeof __propDef.slots;
|
|
28
|
+
export default class ListViewOrderbookFilters extends SvelteComponent<ListViewOrderbookFiltersProps, ListViewOrderbookFiltersEvents, ListViewOrderbookFiltersSlots> {
|
|
27
29
|
}
|
|
28
30
|
export {};
|
|
@@ -2,7 +2,7 @@ import { SvelteComponent } from "svelte";
|
|
|
2
2
|
import type { Address, RaindexOrder, RaindexOrderAsIO, RaindexVault } from '@rainlanguage/orderbook';
|
|
3
3
|
declare const __propDef: {
|
|
4
4
|
props: {
|
|
5
|
-
orderOrVault:
|
|
5
|
+
orderOrVault: RaindexVault | RaindexOrder | RaindexOrderAsIO;
|
|
6
6
|
type: "orders" | "vaults";
|
|
7
7
|
chainId: number;
|
|
8
8
|
orderbookAddress: Address;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<script generics="
|
|
1
|
+
<script generics="DataItem, InputData = DataItem[]">import { invalidateTanstackQueries } from "../queries/queryClient";
|
|
2
2
|
import Refresh from "./icon/Refresh.svelte";
|
|
3
3
|
import { Button, Table, TableBody, TableBodyRow, TableHead } from "flowbite-svelte";
|
|
4
4
|
import { createEventDispatcher } from "svelte";
|
|
@@ -9,6 +9,11 @@ export let queryKey;
|
|
|
9
9
|
export let query;
|
|
10
10
|
export let emptyMessage = "None found";
|
|
11
11
|
export let rowHoverable = true;
|
|
12
|
+
export let dataSelector = (pageData) => Array.isArray(pageData) ? pageData : [];
|
|
13
|
+
$: data = $query.data ? {
|
|
14
|
+
...$query.data,
|
|
15
|
+
pages: $query.data.pages.map((page) => dataSelector(page))
|
|
16
|
+
} : void 0;
|
|
12
17
|
</script>
|
|
13
18
|
|
|
14
19
|
<div data-testid="title" class="flex h-16 w-full items-center justify-end">
|
|
@@ -26,11 +31,11 @@ export let rowHoverable = true;
|
|
|
26
31
|
}}
|
|
27
32
|
/>
|
|
28
33
|
</div>
|
|
29
|
-
{#if
|
|
34
|
+
{#if (data?.pages?.[0]?.length ?? 0) === 0}
|
|
30
35
|
<div data-testid="emptyMessage" class="text-center text-gray-900 dark:text-white">
|
|
31
36
|
{emptyMessage}
|
|
32
37
|
</div>
|
|
33
|
-
{:else if
|
|
38
|
+
{:else if data}
|
|
34
39
|
<Table
|
|
35
40
|
divClass="cursor-pointer rounded-lg overflow-auto dark:border-none border"
|
|
36
41
|
hoverable={rowHoverable}
|
|
@@ -39,7 +44,7 @@ export let rowHoverable = true;
|
|
|
39
44
|
<slot name="head" />
|
|
40
45
|
</TableHead>
|
|
41
46
|
<TableBody>
|
|
42
|
-
{#each
|
|
47
|
+
{#each data.pages as page}
|
|
43
48
|
{#each page as item}
|
|
44
49
|
<TableBodyRow
|
|
45
50
|
class="whitespace-nowrap"
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { SvelteComponent } from "svelte";
|
|
2
2
|
import type { CreateInfiniteQueryResult, InfiniteData } from '@tanstack/svelte-query';
|
|
3
|
-
declare class __sveltets_Render<
|
|
3
|
+
declare class __sveltets_Render<DataItem, InputData = DataItem[]> {
|
|
4
4
|
props(): {
|
|
5
5
|
queryKey: string;
|
|
6
|
-
query: CreateInfiniteQueryResult<InfiniteData<
|
|
6
|
+
query: CreateInfiniteQueryResult<InfiniteData<InputData, unknown>, Error>;
|
|
7
7
|
emptyMessage?: string;
|
|
8
8
|
rowHoverable?: boolean;
|
|
9
|
+
dataSelector?: ((pageData: InputData) => DataItem[]) | undefined;
|
|
9
10
|
};
|
|
10
11
|
events(): {
|
|
11
12
|
clickRow: CustomEvent<any>;
|
|
@@ -18,13 +19,13 @@ declare class __sveltets_Render<T> {
|
|
|
18
19
|
title: {};
|
|
19
20
|
head: {};
|
|
20
21
|
bodyRow: {
|
|
21
|
-
item:
|
|
22
|
+
item: DataItem;
|
|
22
23
|
};
|
|
23
24
|
};
|
|
24
25
|
}
|
|
25
|
-
export type TanstackAppTableProps<
|
|
26
|
-
export type TanstackAppTableEvents<
|
|
27
|
-
export type TanstackAppTableSlots<
|
|
28
|
-
export default class TanstackAppTable<
|
|
26
|
+
export type TanstackAppTableProps<DataItem, InputData = DataItem[]> = ReturnType<__sveltets_Render<DataItem, InputData>['props']>;
|
|
27
|
+
export type TanstackAppTableEvents<DataItem, InputData = DataItem[]> = ReturnType<__sveltets_Render<DataItem, InputData>['events']>;
|
|
28
|
+
export type TanstackAppTableSlots<DataItem, InputData = DataItem[]> = ReturnType<__sveltets_Render<DataItem, InputData>['slots']>;
|
|
29
|
+
export default class TanstackAppTable<DataItem, InputData = DataItem[]> extends SvelteComponent<TanstackAppTableProps<DataItem, InputData>, TanstackAppTableEvents<DataItem, InputData>, TanstackAppTableSlots<DataItem, InputData>> {
|
|
29
30
|
}
|
|
30
31
|
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<script>import { goto } from "$app/navigation";
|
|
2
|
+
export let vault;
|
|
3
|
+
const handleClick = (event) => {
|
|
4
|
+
event.stopPropagation();
|
|
5
|
+
event.preventDefault();
|
|
6
|
+
goto(`/vaults/${vault.chainId}-${vault.orderbook}-${vault.id}`);
|
|
7
|
+
};
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
<button
|
|
11
|
+
type="button"
|
|
12
|
+
class="flex w-full flex-col rounded-xl border border-gray-200 bg-gray-50 px-4 py-3 text-left shadow-sm transition-colors hover:bg-gray-100 dark:border-gray-600 dark:bg-gray-700 dark:hover:bg-gray-600"
|
|
13
|
+
on:click={handleClick}
|
|
14
|
+
data-testid="vault-card"
|
|
15
|
+
>
|
|
16
|
+
<span class="font-semibold text-gray-800 dark:text-gray-200">{vault.token.symbol}</span>
|
|
17
|
+
<span class="text-xs text-gray-500 dark:text-gray-400">{vault.formattedBalance}</span>
|
|
18
|
+
</button>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
import type { RaindexVault } from '@rainlanguage/orderbook';
|
|
3
|
+
declare const __propDef: {
|
|
4
|
+
props: {
|
|
5
|
+
vault: RaindexVault;
|
|
6
|
+
};
|
|
7
|
+
events: {
|
|
8
|
+
[evt: string]: CustomEvent<any>;
|
|
9
|
+
};
|
|
10
|
+
slots: {};
|
|
11
|
+
exports?: {} | undefined;
|
|
12
|
+
bindings?: string | undefined;
|
|
13
|
+
};
|
|
14
|
+
export type VaultCardProps = typeof __propDef.props;
|
|
15
|
+
export type VaultCardEvents = typeof __propDef.events;
|
|
16
|
+
export type VaultCardSlots = typeof __propDef.slots;
|
|
17
|
+
export default class VaultCard extends SvelteComponent<VaultCardProps, VaultCardEvents, VaultCardSlots> {
|
|
18
|
+
}
|
|
19
|
+
export {};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { SvelteComponent } from "svelte";
|
|
2
2
|
import type { Readable } from 'svelte/store';
|
|
3
3
|
import { type IChartApi, type UTCTimestamp, type ISeriesApi, type WhitespaceData, type Time, type DeepPartial, type SeriesOptionsCommon, type SeriesOptionsMap } from 'lightweight-charts';
|
|
4
|
-
declare class __sveltets_Render<T extends keyof SeriesOptionsMap,
|
|
4
|
+
declare class __sveltets_Render<T extends keyof SeriesOptionsMap, O> {
|
|
5
5
|
props(): {
|
|
6
6
|
[x: string]: any;
|
|
7
7
|
data?: {
|
|
@@ -21,9 +21,9 @@ declare class __sveltets_Render<T extends keyof SeriesOptionsMap, D, O> {
|
|
|
21
21
|
};
|
|
22
22
|
slots(): {};
|
|
23
23
|
}
|
|
24
|
-
export type LightweightChartProps<T extends keyof SeriesOptionsMap,
|
|
25
|
-
export type LightweightChartEvents<T extends keyof SeriesOptionsMap,
|
|
26
|
-
export type LightweightChartSlots<T extends keyof SeriesOptionsMap,
|
|
27
|
-
export default class LightweightChart<T extends keyof SeriesOptionsMap,
|
|
24
|
+
export type LightweightChartProps<T extends keyof SeriesOptionsMap, O> = ReturnType<__sveltets_Render<T, O>['props']>;
|
|
25
|
+
export type LightweightChartEvents<T extends keyof SeriesOptionsMap, O> = ReturnType<__sveltets_Render<T, O>['events']>;
|
|
26
|
+
export type LightweightChartSlots<T extends keyof SeriesOptionsMap, O> = ReturnType<__sveltets_Render<T, O>['slots']>;
|
|
27
|
+
export default class LightweightChart<T extends keyof SeriesOptionsMap, O> extends SvelteComponent<LightweightChartProps<T, O>, LightweightChartEvents<T, O>, LightweightChartSlots<T, O>> {
|
|
28
28
|
}
|
|
29
29
|
export {};
|
|
@@ -1,20 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import TanstackLightweightChartLine from "../charts/TanstackLightweightChartLine.svelte";
|
|
4
|
-
import { QKEY_VAULT_CHANGES } from "../../queries/keys";
|
|
5
|
-
export let vault;
|
|
6
|
-
export let lightweightChartsTheme;
|
|
7
|
-
$: query = createQuery({
|
|
8
|
-
queryKey: [vault.id, QKEY_VAULT_CHANGES + vault.id, QKEY_VAULT_CHANGES],
|
|
9
|
-
queryFn: async () => {
|
|
10
|
-
const result = await vault.getBalanceChanges(1);
|
|
11
|
-
if (result.error) throw new Error(result.error.msg);
|
|
12
|
-
return result.value;
|
|
13
|
-
}
|
|
14
|
-
});
|
|
15
|
-
const Chart = TanstackLightweightChartLine;
|
|
16
|
-
</script>
|
|
1
|
+
<!-- TODO: Issue #1989 -->
|
|
2
|
+
<script></script>
|
|
17
3
|
|
|
4
|
+
<!--
|
|
18
5
|
{#if vault && $query.data}
|
|
19
6
|
<Chart
|
|
20
7
|
title="Balance history"
|
|
@@ -25,4 +12,8 @@ const Chart = TanstackLightweightChartLine;
|
|
|
25
12
|
emptyMessage="No deposits or withdrawals found"
|
|
26
13
|
{lightweightChartsTheme}
|
|
27
14
|
/>
|
|
15
|
+
{/if} -->
|
|
16
|
+
|
|
17
|
+
{#if false}
|
|
18
|
+
<div>TODO: Issue #1989</div>
|
|
28
19
|
{/if}
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import { SvelteComponent } from "svelte";
|
|
2
|
-
import type { RaindexVault } from '@rainlanguage/orderbook';
|
|
3
2
|
declare const __propDef: {
|
|
4
|
-
props:
|
|
5
|
-
vault: RaindexVault;
|
|
6
|
-
lightweightChartsTheme: any;
|
|
7
|
-
};
|
|
3
|
+
props: Record<string, never>;
|
|
8
4
|
events: {
|
|
9
5
|
[evt: string]: CustomEvent<any>;
|
|
10
6
|
};
|
|
@@ -36,8 +36,6 @@ let showAdvancedOptions = false;
|
|
|
36
36
|
let allTokenInfos = [];
|
|
37
37
|
let selectTokens = void 0;
|
|
38
38
|
let checkingDeployment = false;
|
|
39
|
-
let availableTokens = [];
|
|
40
|
-
let loadingTokens = false;
|
|
41
39
|
let tokenBalances = /* @__PURE__ */ new Map();
|
|
42
40
|
const gui = useGui();
|
|
43
41
|
const registry = useRegistry();
|
|
@@ -50,7 +48,6 @@ onMount(async () => {
|
|
|
50
48
|
}
|
|
51
49
|
selectTokens = selectTokensResult.value;
|
|
52
50
|
await areAllTokensSelected();
|
|
53
|
-
await loadAvailableTokens();
|
|
54
51
|
});
|
|
55
52
|
$: if (selectTokens?.length === 0 || allTokensSelected) {
|
|
56
53
|
updateFields();
|
|
@@ -71,22 +68,6 @@ let unsubscribeAccount = account.subscribe((account2) => {
|
|
|
71
68
|
onDestroy(() => {
|
|
72
69
|
unsubscribeAccount();
|
|
73
70
|
});
|
|
74
|
-
async function loadAvailableTokens() {
|
|
75
|
-
if (loadingTokens) return;
|
|
76
|
-
loadingTokens = true;
|
|
77
|
-
try {
|
|
78
|
-
const result = await gui.getAllTokens();
|
|
79
|
-
if (result.error) {
|
|
80
|
-
throw new Error(result.error.msg);
|
|
81
|
-
}
|
|
82
|
-
availableTokens = result.value;
|
|
83
|
-
} catch (error) {
|
|
84
|
-
DeploymentStepsError.catch(error, DeploymentStepsErrorCode.NO_AVAILABLE_TOKENS);
|
|
85
|
-
availableTokens = [];
|
|
86
|
-
} finally {
|
|
87
|
-
loadingTokens = false;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
71
|
function getAllGuiConfig() {
|
|
91
72
|
try {
|
|
92
73
|
let result = gui.getAllGuiConfig();
|
|
@@ -239,13 +220,7 @@ async function handleDeployButtonClick() {
|
|
|
239
220
|
description="Select the tokens that you want to use in your order."
|
|
240
221
|
/>
|
|
241
222
|
{#each selectTokens as token}
|
|
242
|
-
<SelectToken
|
|
243
|
-
{token}
|
|
244
|
-
{onSelectTokenSelect}
|
|
245
|
-
{availableTokens}
|
|
246
|
-
loading={loadingTokens}
|
|
247
|
-
{tokenBalances}
|
|
248
|
-
/>
|
|
223
|
+
<SelectToken {token} {onSelectTokenSelect} {tokenBalances} />
|
|
249
224
|
{/each}
|
|
250
225
|
</div>
|
|
251
226
|
{/if}
|
|
@@ -43,10 +43,10 @@ const getTokenSymbol = async () => {
|
|
|
43
43
|
error = errorMessage;
|
|
44
44
|
}
|
|
45
45
|
};
|
|
46
|
-
function handlePresetClick(preset) {
|
|
46
|
+
async function handlePresetClick(preset) {
|
|
47
47
|
if (deposit.token?.key) {
|
|
48
48
|
inputValue = preset;
|
|
49
|
-
gui.setDeposit(deposit.token?.key, preset);
|
|
49
|
+
await gui.setDeposit(deposit.token?.key, preset);
|
|
50
50
|
try {
|
|
51
51
|
currentDeposit = getCurrentDeposit();
|
|
52
52
|
} catch (e) {
|
|
@@ -54,11 +54,11 @@ function handlePresetClick(preset) {
|
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
|
-
function handleInput(e) {
|
|
57
|
+
async function handleInput(e) {
|
|
58
58
|
if (deposit.token?.key) {
|
|
59
59
|
if (e.currentTarget instanceof HTMLInputElement) {
|
|
60
60
|
inputValue = e.currentTarget.value;
|
|
61
|
-
gui.setDeposit(deposit.token.key, e.currentTarget.value);
|
|
61
|
+
await gui.setDeposit(deposit.token.key, e.currentTarget.value);
|
|
62
62
|
try {
|
|
63
63
|
currentDeposit = getCurrentDeposit();
|
|
64
64
|
} catch (e2) {
|
|
@@ -8,15 +8,12 @@ import TokenSelectionModal from "./TokenSelectionModal.svelte";
|
|
|
8
8
|
import TokenBalanceComponent from "./TokenBalance.svelte";
|
|
9
9
|
export let token;
|
|
10
10
|
export let onSelectTokenSelect;
|
|
11
|
-
export let availableTokens = [];
|
|
12
|
-
export let loading = false;
|
|
13
11
|
export let tokenBalances = /* @__PURE__ */ new Map();
|
|
14
12
|
let inputValue = null;
|
|
15
13
|
let tokenInfo = null;
|
|
16
14
|
let error = "";
|
|
17
15
|
let checking = false;
|
|
18
16
|
let selectionMode = "dropdown";
|
|
19
|
-
let searchQuery = "";
|
|
20
17
|
let selectedToken = null;
|
|
21
18
|
const gui = useGui();
|
|
22
19
|
onMount(async () => {
|
|
@@ -33,43 +30,13 @@ onMount(async () => {
|
|
|
33
30
|
} catch {
|
|
34
31
|
}
|
|
35
32
|
});
|
|
36
|
-
$: if (tokenInfo?.address &&
|
|
37
|
-
const foundToken = availableTokens.find(
|
|
38
|
-
(t) => t.address.toLowerCase() === tokenInfo?.address.toLowerCase()
|
|
39
|
-
);
|
|
40
|
-
selectedToken = foundToken || null;
|
|
41
|
-
if (inputValue === null) {
|
|
42
|
-
inputValue = tokenInfo.address;
|
|
43
|
-
}
|
|
44
|
-
if (!foundToken && selectionMode === "dropdown") {
|
|
45
|
-
selectionMode = "custom";
|
|
46
|
-
}
|
|
47
|
-
} else if (tokenInfo?.address && inputValue === null) {
|
|
33
|
+
$: if (tokenInfo?.address && inputValue === null) {
|
|
48
34
|
inputValue = tokenInfo.address;
|
|
49
35
|
}
|
|
50
36
|
function setMode(mode) {
|
|
51
37
|
selectionMode = mode;
|
|
52
38
|
error = "";
|
|
53
|
-
if (mode === "
|
|
54
|
-
searchQuery = "";
|
|
55
|
-
if (inputValue && tokenInfo) {
|
|
56
|
-
const foundToken = availableTokens.find(
|
|
57
|
-
(t) => t.address.toLowerCase() === inputValue?.toLowerCase()
|
|
58
|
-
);
|
|
59
|
-
if (foundToken) {
|
|
60
|
-
selectedToken = foundToken;
|
|
61
|
-
} else {
|
|
62
|
-
inputValue = null;
|
|
63
|
-
tokenInfo = null;
|
|
64
|
-
selectedToken = null;
|
|
65
|
-
clearTokenSelection();
|
|
66
|
-
}
|
|
67
|
-
} else {
|
|
68
|
-
inputValue = null;
|
|
69
|
-
tokenInfo = null;
|
|
70
|
-
selectedToken = null;
|
|
71
|
-
}
|
|
72
|
-
} else if (mode === "custom") {
|
|
39
|
+
if (mode === "custom") {
|
|
73
40
|
selectedToken = null;
|
|
74
41
|
tokenInfo = null;
|
|
75
42
|
inputValue = "";
|
|
@@ -82,9 +49,6 @@ function handleTokenSelect(token2) {
|
|
|
82
49
|
inputValue = token2.address;
|
|
83
50
|
saveTokenSelection(token2.address);
|
|
84
51
|
}
|
|
85
|
-
function handleSearch(query) {
|
|
86
|
-
searchQuery = query;
|
|
87
|
-
}
|
|
88
52
|
async function saveTokenSelection(address) {
|
|
89
53
|
checking = true;
|
|
90
54
|
error = "";
|
|
@@ -153,34 +117,26 @@ async function handleInput(event) {
|
|
|
153
117
|
{/if}
|
|
154
118
|
</div>
|
|
155
119
|
|
|
156
|
-
|
|
157
|
-
<
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
dataTestId="dropdown-mode-button"
|
|
163
|
-
/>
|
|
164
|
-
<ButtonSelectOption
|
|
165
|
-
active={selectionMode === 'custom'}
|
|
166
|
-
buttonText="Custom address"
|
|
167
|
-
clickHandler={() => setMode('custom')}
|
|
168
|
-
dataTestId="custom-mode-button"
|
|
169
|
-
/>
|
|
170
|
-
</div>
|
|
171
|
-
{/if}
|
|
172
|
-
|
|
173
|
-
{#if selectionMode === 'dropdown' && availableTokens.length > 0 && !loading}
|
|
174
|
-
<TokenSelectionModal
|
|
175
|
-
tokens={availableTokens}
|
|
176
|
-
{selectedToken}
|
|
177
|
-
onSelect={handleTokenSelect}
|
|
178
|
-
searchValue={searchQuery}
|
|
179
|
-
onSearch={handleSearch}
|
|
120
|
+
<div class="selection-mode flex gap-2">
|
|
121
|
+
<ButtonSelectOption
|
|
122
|
+
active={selectionMode === 'dropdown'}
|
|
123
|
+
buttonText="Select from list"
|
|
124
|
+
clickHandler={() => setMode('dropdown')}
|
|
125
|
+
dataTestId="dropdown-mode-button"
|
|
180
126
|
/>
|
|
127
|
+
<ButtonSelectOption
|
|
128
|
+
active={selectionMode === 'custom'}
|
|
129
|
+
buttonText="Custom address"
|
|
130
|
+
clickHandler={() => setMode('custom')}
|
|
131
|
+
dataTestId="custom-mode-button"
|
|
132
|
+
/>
|
|
133
|
+
</div>
|
|
134
|
+
|
|
135
|
+
{#if selectionMode === 'dropdown'}
|
|
136
|
+
<TokenSelectionModal {selectedToken} onSelect={handleTokenSelect} />
|
|
181
137
|
{/if}
|
|
182
138
|
|
|
183
|
-
{#if selectionMode === 'custom'
|
|
139
|
+
{#if selectionMode === 'custom'}
|
|
184
140
|
<div class="custom-input">
|
|
185
141
|
<Input
|
|
186
142
|
type="text"
|
|
@@ -193,12 +149,7 @@ async function handleInput(event) {
|
|
|
193
149
|
{/if}
|
|
194
150
|
|
|
195
151
|
<div class="token-status">
|
|
196
|
-
{#if
|
|
197
|
-
<div class="flex h-5 flex-row items-center gap-2">
|
|
198
|
-
<Spinner class="h-5 w-5" />
|
|
199
|
-
<span>Loading tokens...</span>
|
|
200
|
-
</div>
|
|
201
|
-
{:else if checking}
|
|
152
|
+
{#if checking}
|
|
202
153
|
<div class="flex h-5 flex-row items-center gap-2">
|
|
203
154
|
<Spinner class="h-5 w-5" />
|
|
204
155
|
<span>Checking...</span>
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import { SvelteComponent } from "svelte";
|
|
2
|
-
import type { GuiSelectTokensCfg
|
|
2
|
+
import type { GuiSelectTokensCfg } from '@rainlanguage/orderbook';
|
|
3
3
|
import type { TokenBalance } from '../../types/tokenBalance';
|
|
4
4
|
declare const __propDef: {
|
|
5
5
|
props: {
|
|
6
6
|
token: GuiSelectTokensCfg;
|
|
7
7
|
onSelectTokenSelect: (key: string) => void;
|
|
8
|
-
availableTokens?: TokenInfo[];
|
|
9
|
-
loading?: boolean;
|
|
10
8
|
tokenBalances?: Map<string, TokenBalance>;
|
|
11
9
|
};
|
|
12
10
|
events: {
|
|
@@ -1,20 +1,30 @@
|
|
|
1
1
|
<script>import { Input, Button, Modal } from "flowbite-svelte";
|
|
2
2
|
import { SearchOutline, CheckCircleSolid, ChevronDownSolid } from "flowbite-svelte-icons";
|
|
3
|
-
|
|
3
|
+
import { useGui } from "../../hooks/useGui";
|
|
4
|
+
import { onMount, tick } from "svelte";
|
|
4
5
|
export let selectedToken = null;
|
|
5
6
|
export let onSelect;
|
|
6
|
-
export let searchValue = "";
|
|
7
|
-
export let onSearch;
|
|
8
7
|
let modalOpen = false;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
let searchQuery = "";
|
|
9
|
+
let tokens = [];
|
|
10
|
+
let isSearching = false;
|
|
11
|
+
const gui = useGui();
|
|
12
|
+
async function loadTokens(search) {
|
|
13
|
+
isSearching = true;
|
|
14
|
+
const result = await gui.getAllTokens(search);
|
|
15
|
+
if (result.error) {
|
|
16
|
+
tokens = [];
|
|
17
|
+
} else {
|
|
18
|
+
tokens = result.value;
|
|
19
|
+
}
|
|
20
|
+
isSearching = false;
|
|
21
|
+
}
|
|
14
22
|
function handleSearch(event) {
|
|
15
23
|
const target = event.target;
|
|
16
|
-
|
|
24
|
+
searchQuery = target.value;
|
|
25
|
+
loadTokens(searchQuery || void 0);
|
|
17
26
|
}
|
|
27
|
+
onMount(() => loadTokens());
|
|
18
28
|
function formatAddress(address) {
|
|
19
29
|
return `${address.slice(0, 6)}...${address.slice(-4)}`;
|
|
20
30
|
}
|
|
@@ -23,6 +33,14 @@ function handleTokenSelect(token) {
|
|
|
23
33
|
modalOpen = false;
|
|
24
34
|
}
|
|
25
35
|
$: displayText = selectedToken ? `${selectedToken.name} (${selectedToken.symbol})` : "Select a token...";
|
|
36
|
+
$: if (modalOpen) {
|
|
37
|
+
tick().then(() => {
|
|
38
|
+
const input = document.querySelector(".token-search-input");
|
|
39
|
+
if (input) {
|
|
40
|
+
input.focus();
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
}
|
|
26
44
|
</script>
|
|
27
45
|
|
|
28
46
|
<div class="token-dropdown">
|
|
@@ -50,50 +68,59 @@ $: displayText = selectedToken ? `${selectedToken.name} (${selectedToken.symbol}
|
|
|
50
68
|
<Input
|
|
51
69
|
type="text"
|
|
52
70
|
placeholder="Search tokens..."
|
|
53
|
-
bind:value={
|
|
71
|
+
bind:value={searchQuery}
|
|
54
72
|
on:input={handleSearch}
|
|
55
|
-
class="pl-10"
|
|
73
|
+
class="token-search-input pl-10"
|
|
56
74
|
/>
|
|
57
75
|
</div>
|
|
58
76
|
|
|
59
77
|
<div class="token-list max-h-80 overflow-y-auto">
|
|
60
|
-
{#
|
|
61
|
-
<div
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
<
|
|
78
|
+
{#if isSearching}
|
|
79
|
+
<div class="p-4 text-center text-gray-500 dark:text-gray-400">
|
|
80
|
+
<p>Searching tokens...</p>
|
|
81
|
+
</div>
|
|
82
|
+
{:else}
|
|
83
|
+
{#each tokens as token (token.address)}
|
|
84
|
+
<div
|
|
85
|
+
class="token-item flex cursor-pointer items-center border-b border-gray-100 p-3 last:border-b-0 hover:bg-gray-50 dark:border-gray-600 dark:hover:bg-gray-700"
|
|
86
|
+
class:bg-blue-50={selectedToken?.address === token.address}
|
|
87
|
+
class:dark:bg-blue-900={selectedToken?.address === token.address}
|
|
88
|
+
class:border-l-4={selectedToken?.address === token.address}
|
|
89
|
+
class:border-l-blue-500={selectedToken?.address === token.address}
|
|
90
|
+
on:click={() => handleTokenSelect(token)}
|
|
91
|
+
on:keydown={(e) => e.key === 'Enter' && handleTokenSelect(token)}
|
|
92
|
+
role="button"
|
|
93
|
+
tabindex="0"
|
|
94
|
+
>
|
|
95
|
+
<div class="token-info flex-grow">
|
|
96
|
+
<div class="token-name font-medium text-gray-900 dark:text-white">
|
|
97
|
+
{token.name}
|
|
98
|
+
</div>
|
|
99
|
+
<div class="token-details flex gap-2 text-sm text-gray-500 dark:text-gray-400">
|
|
100
|
+
<span class="symbol font-medium">{token.symbol}</span>
|
|
101
|
+
<span class="address">{formatAddress(token.address)}</span>
|
|
102
|
+
</div>
|
|
79
103
|
</div>
|
|
104
|
+
{#if selectedToken?.address === token.address}
|
|
105
|
+
<CheckCircleSolid class="selected-icon h-5 w-5 text-green-500" />
|
|
106
|
+
{/if}
|
|
80
107
|
</div>
|
|
81
|
-
|
|
82
|
-
<CheckCircleSolid class="selected-icon h-5 w-5 text-green-500" />
|
|
83
|
-
{/if}
|
|
84
|
-
</div>
|
|
85
|
-
{/each}
|
|
108
|
+
{/each}
|
|
86
109
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
110
|
+
{#if tokens.length === 0}
|
|
111
|
+
<div class="no-results p-4 text-center text-gray-500 dark:text-gray-400">
|
|
112
|
+
<p>No tokens found matching your search.</p>
|
|
113
|
+
<button
|
|
114
|
+
class="mt-2 text-blue-600 underline hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300"
|
|
115
|
+
on:click={() => {
|
|
116
|
+
searchQuery = '';
|
|
117
|
+
loadTokens();
|
|
118
|
+
}}
|
|
119
|
+
>
|
|
120
|
+
Clear search
|
|
121
|
+
</button>
|
|
122
|
+
</div>
|
|
123
|
+
{/if}
|
|
97
124
|
{/if}
|
|
98
125
|
</div>
|
|
99
126
|
</Modal>
|
|
@@ -2,11 +2,8 @@ import { SvelteComponent } from "svelte";
|
|
|
2
2
|
import type { TokenInfo } from '@rainlanguage/orderbook';
|
|
3
3
|
declare const __propDef: {
|
|
4
4
|
props: {
|
|
5
|
-
tokens?: TokenInfo[];
|
|
6
5
|
selectedToken?: TokenInfo | null;
|
|
7
6
|
onSelect: (token: TokenInfo) => void;
|
|
8
|
-
searchValue?: string;
|
|
9
|
-
onSearch: (query: string) => void;
|
|
10
7
|
};
|
|
11
8
|
events: {
|
|
12
9
|
[evt: string]: CustomEvent<any>;
|