Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b220203c91 | ||
|
|
5ca923984d | ||
|
|
d97626f543 | ||
|
|
835f82dbcc | ||
|
|
051bdda73a |
+3
-2
@@ -13,6 +13,7 @@
|
|||||||
"build:inject-app-deeplinks": "sh scripts/inject-app-deeplinks.sh",
|
"build:inject-app-deeplinks": "sh scripts/inject-app-deeplinks.sh",
|
||||||
"build:inject-amplitude": "node scripts/inject-amplitude.js",
|
"build:inject-amplitude": "node scripts/inject-amplitude.js",
|
||||||
"build:inject-bugsnag": "node scripts/inject-bugsnag.js",
|
"build:inject-bugsnag": "node scripts/inject-bugsnag.js",
|
||||||
|
"build:inject-intercom": "node scripts/inject-intercom.js",
|
||||||
"build:inject-statuspage": "node scripts/inject-statuspage.js",
|
"build:inject-statuspage": "node scripts/inject-statuspage.js",
|
||||||
"deploy:ipfs": "node scripts/upload-ipfs.js --verbose",
|
"deploy:ipfs": "node scripts/upload-ipfs.js --verbose",
|
||||||
"deploy:update-ipns": "node scripts/update-ipns.js",
|
"deploy:update-ipns": "node scripts/update-ipns.js",
|
||||||
@@ -38,9 +39,9 @@
|
|||||||
"@cosmjs/proto-signing": "^0.31.0",
|
"@cosmjs/proto-signing": "^0.31.0",
|
||||||
"@cosmjs/stargate": "^0.31.0",
|
"@cosmjs/stargate": "^0.31.0",
|
||||||
"@cosmjs/tendermint-rpc": "^0.31.0",
|
"@cosmjs/tendermint-rpc": "^0.31.0",
|
||||||
"@dydxprotocol/v4-abacus": "^0.7.2",
|
"@dydxprotocol/v4-abacus": "^0.7.6",
|
||||||
"@dydxprotocol/v4-client-js": "^0.40.3",
|
"@dydxprotocol/v4-client-js": "^0.40.3",
|
||||||
"@dydxprotocol/v4-localization": "^0.1.30",
|
"@dydxprotocol/v4-localization": "^0.1.32",
|
||||||
"@ethersproject/providers": "^5.7.2",
|
"@ethersproject/providers": "^5.7.2",
|
||||||
"@js-joda/core": "^5.5.3",
|
"@js-joda/core": "^5.5.3",
|
||||||
"@radix-ui/react-collapsible": "^1.0.3",
|
"@radix-ui/react-collapsible": "^1.0.3",
|
||||||
|
|||||||
Generated
+8
-8
@@ -27,14 +27,14 @@ dependencies:
|
|||||||
specifier: ^0.31.0
|
specifier: ^0.31.0
|
||||||
version: 0.31.0
|
version: 0.31.0
|
||||||
'@dydxprotocol/v4-abacus':
|
'@dydxprotocol/v4-abacus':
|
||||||
specifier: ^0.7.2
|
specifier: ^0.7.6
|
||||||
version: 0.7.2
|
version: 0.7.6
|
||||||
'@dydxprotocol/v4-client-js':
|
'@dydxprotocol/v4-client-js':
|
||||||
specifier: ^0.40.3
|
specifier: ^0.40.3
|
||||||
version: 0.40.3
|
version: 0.40.3
|
||||||
'@dydxprotocol/v4-localization':
|
'@dydxprotocol/v4-localization':
|
||||||
specifier: ^0.1.30
|
specifier: ^0.1.32
|
||||||
version: 0.1.30
|
version: 0.1.32
|
||||||
'@ethersproject/providers':
|
'@ethersproject/providers':
|
||||||
specifier: ^5.7.2
|
specifier: ^5.7.2
|
||||||
version: 5.7.2
|
version: 5.7.2
|
||||||
@@ -979,8 +979,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-RpfLEtTlyIxeNPGKcokS+p3BZII/Q3bYxryFRglh5H3A3T8q9fsLYm72VYAMEOOIBLEa8o93kFLiBDUWKrwXZA==}
|
resolution: {integrity: sha512-RpfLEtTlyIxeNPGKcokS+p3BZII/Q3bYxryFRglh5H3A3T8q9fsLYm72VYAMEOOIBLEa8o93kFLiBDUWKrwXZA==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@dydxprotocol/v4-abacus@0.7.2:
|
/@dydxprotocol/v4-abacus@0.7.6:
|
||||||
resolution: {integrity: sha512-5foamomN82FH6ko3EuzwFlSoAEY6Sal8fDgvZo2RsB19Ks6SFgFDeeOcEDdfoa3DNwvl8yW0C9cfxeQ+BfU8uA==}
|
resolution: {integrity: sha512-FdDXRaFMfxhyrJJs0dNrb1KG6X95lPHelua1yCn/SVgzwGaAqlJczrzmdh98INntuRAgIxOu69R5mCGyekumyg==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@dydxprotocol/v4-client-js@0.40.3:
|
/@dydxprotocol/v4-client-js@0.40.3:
|
||||||
@@ -1011,8 +1011,8 @@ packages:
|
|||||||
- utf-8-validate
|
- utf-8-validate
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@dydxprotocol/v4-localization@0.1.30:
|
/@dydxprotocol/v4-localization@0.1.32:
|
||||||
resolution: {integrity: sha512-xTlQuQmPz7wfGkjd07giYMAxRrolDbJE3DryJSIMB6R1MBq1wLzAcwp/iR/nELRwilRX9c44Tap0gGt+oAajiQ==}
|
resolution: {integrity: sha512-ZtXScxgFLjUt0Ag52RyFnQe9aEl1Aky5fp+vMGOBduVkFiCEMRMkSsSgg6grMdyw/x0AbnxOTRkhYoX2MsK9Ow==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@dydxprotocol/v4-proto@0.4.1:
|
/@dydxprotocol/v4-proto@0.4.1:
|
||||||
|
|||||||
@@ -56,15 +56,15 @@
|
|||||||
"endpoints": {
|
"endpoints": {
|
||||||
"indexers": [
|
"indexers": [
|
||||||
{
|
{
|
||||||
"api": "http://indexer.v4dev.dydx.exchange",
|
"api": "https://indexer.v4dev.dydx.exchange",
|
||||||
"socket": "wss://indexer.v4dev.dydx.exchange"
|
"socket": "wss://indexer.v4dev.dydx.exchange"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"validators": [
|
"validators": [
|
||||||
"http://validator.v4dev.dydx.exchange"
|
"https://validator.v4dev.dydx.exchange"
|
||||||
],
|
],
|
||||||
"0xsquid": "https://testnet.api.0xsquid.com",
|
"0xsquid": "https://testnet.api.0xsquid.com",
|
||||||
"faucet": "http://faucet.v4dev.dydx.exchange"
|
"faucet": "https://faucet.v4dev.dydx.exchange"
|
||||||
},
|
},
|
||||||
"links": {
|
"links": {
|
||||||
"tos": "https://dydx.exchange/v4-terms",
|
"tos": "https://dydx.exchange/v4-terms",
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
/* eslint-disable no-console */
|
||||||
|
import fs from 'fs/promises';
|
||||||
|
import path from 'path';
|
||||||
|
import { fileURLToPath } from 'url';
|
||||||
|
|
||||||
|
const INTERCOM_APP_ID = process.env.INTERCOM_APP_ID;
|
||||||
|
|
||||||
|
const currentPath = fileURLToPath(import.meta.url);
|
||||||
|
const projectRoot = path.dirname(currentPath);
|
||||||
|
const htmlFilePath = path.resolve(projectRoot, '../dist/index.html');
|
||||||
|
|
||||||
|
if (INTERCOM_APP_ID) {
|
||||||
|
try {
|
||||||
|
const html = await fs.readFile(htmlFilePath, 'utf-8');
|
||||||
|
|
||||||
|
const intercomScripts = `
|
||||||
|
<!-- Intercom -->
|
||||||
|
<script>
|
||||||
|
window.intercomSettings = {
|
||||||
|
api_base: 'https://api-iam.intercom.io',
|
||||||
|
app_id: '${INTERCOM_APP_ID}',
|
||||||
|
custom_launcher_selector: '.custom_intercom',
|
||||||
|
hide_default_launcher: true,
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// We pre-filled your app ID in the widget URL: 'https://widget.intercom.io/widget/${INTERCOM_APP_ID}'
|
||||||
|
(function () {
|
||||||
|
var w = window;
|
||||||
|
var ic = w.Intercom;
|
||||||
|
if (typeof ic === 'function') {
|
||||||
|
ic('reattach_activator');
|
||||||
|
ic('update', w.intercomSettings);
|
||||||
|
} else {
|
||||||
|
var d = document;
|
||||||
|
var i = function () {
|
||||||
|
i.c(arguments);
|
||||||
|
};
|
||||||
|
i.q = [];
|
||||||
|
i.c = function (args) {
|
||||||
|
i.q.push(args);
|
||||||
|
};
|
||||||
|
w.Intercom = i;
|
||||||
|
var l = function () {
|
||||||
|
var s = d.createElement('script');
|
||||||
|
s.type = 'text/javascript';
|
||||||
|
s.async = true;
|
||||||
|
s.src = 'https://widget.intercom.io/widget/${INTERCOM_APP_ID}';
|
||||||
|
var x = d.getElementsByTagName('script')[0];
|
||||||
|
x.parentNode.insertBefore(s, x);
|
||||||
|
};
|
||||||
|
if (document.readyState === 'complete') {
|
||||||
|
l();
|
||||||
|
} else if (w.attachEvent) {
|
||||||
|
w.attachEvent('onload', l);
|
||||||
|
} else {
|
||||||
|
w.addEventListener('load', l, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
`;
|
||||||
|
|
||||||
|
const injectedHtml = html.replace(
|
||||||
|
'<div id="root"></div>',
|
||||||
|
`<div id="root"></div>\n${intercomScripts}\n`
|
||||||
|
);
|
||||||
|
|
||||||
|
await fs.writeFile(htmlFilePath, injectedHtml, 'utf-8');
|
||||||
|
|
||||||
|
console.log('Intercom scripts successfully injected.');
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error injecting Intercom scripts:', err);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,31 +3,43 @@ import styled, { AnyStyledComponent } from 'styled-components';
|
|||||||
|
|
||||||
import { type MenuConfig } from '@/constants/menus';
|
import { type MenuConfig } from '@/constants/menus';
|
||||||
|
|
||||||
import { Dialog, DialogPlacement } from '@/components/Dialog';
|
import { Dialog, DialogPlacement, type DialogProps } from '@/components/Dialog';
|
||||||
import { ComboboxMenu } from '@/components/ComboboxMenu';
|
import { ComboboxMenu, type ComboboxMenuProps } from '@/components/ComboboxMenu';
|
||||||
|
|
||||||
type ElementProps<MenuItemValue extends string | number, MenuGroupValue extends string | number> = {
|
type ElementProps<MenuItemValue extends string | number, MenuGroupValue extends string | number> = {
|
||||||
isOpen?: boolean;
|
|
||||||
setIsOpen?: (open: boolean) => void;
|
|
||||||
title?: React.ReactNode;
|
title?: React.ReactNode;
|
||||||
description?: React.ReactNode;
|
description?: React.ReactNode;
|
||||||
slotTrigger?: React.ReactNode;
|
|
||||||
slotHeaderInner?: React.ReactNode;
|
|
||||||
slotFooter?: React.ReactNode;
|
|
||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
|
|
||||||
items: MenuConfig<MenuItemValue, MenuGroupValue>;
|
items: MenuConfig<MenuItemValue, MenuGroupValue>;
|
||||||
onItemSelected?: () => void;
|
|
||||||
inputPlaceholder?: string;
|
|
||||||
slotEmpty?: React.ReactNode;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
type StyleProps = {
|
type StyleProps = {
|
||||||
placement: DialogPlacement,
|
|
||||||
className?: string;
|
className?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ComboboxDialogMenu = <MenuItemValue extends string | number, MenuGroupValue extends string | number>({
|
type PickComboxMenuProps<
|
||||||
|
MenuItemValue extends string | number,
|
||||||
|
MenuGroupValue extends string | number
|
||||||
|
> = Pick<
|
||||||
|
ComboboxMenuProps<MenuItemValue, MenuGroupValue>,
|
||||||
|
'inputPlaceholder' | 'onItemSelected' | 'slotEmpty' | 'withSearch' | 'withStickyLayout'
|
||||||
|
>;
|
||||||
|
|
||||||
|
type PickDialogProps = Pick<
|
||||||
|
DialogProps,
|
||||||
|
| 'description'
|
||||||
|
| 'isOpen'
|
||||||
|
| 'placement'
|
||||||
|
| 'setIsOpen'
|
||||||
|
| 'slotHeaderInner'
|
||||||
|
| 'slotTrigger'
|
||||||
|
| 'slotFooter'
|
||||||
|
>;
|
||||||
|
|
||||||
|
export const ComboboxDialogMenu = <
|
||||||
|
MenuItemValue extends string | number,
|
||||||
|
MenuGroupValue extends string | number
|
||||||
|
>({
|
||||||
isOpen = false,
|
isOpen = false,
|
||||||
setIsOpen,
|
setIsOpen,
|
||||||
title,
|
title,
|
||||||
@@ -40,11 +52,16 @@ export const ComboboxDialogMenu = <MenuItemValue extends string | number, MenuGr
|
|||||||
onItemSelected,
|
onItemSelected,
|
||||||
inputPlaceholder,
|
inputPlaceholder,
|
||||||
slotEmpty,
|
slotEmpty,
|
||||||
|
withSearch,
|
||||||
|
withStickyLayout = true,
|
||||||
children,
|
children,
|
||||||
|
|
||||||
placement = DialogPlacement.Default,
|
placement = DialogPlacement.Default,
|
||||||
className,
|
className,
|
||||||
}: ElementProps<MenuItemValue, MenuGroupValue> & StyleProps) => (
|
}: ElementProps<MenuItemValue, MenuGroupValue> &
|
||||||
|
PickComboxMenuProps<MenuItemValue, MenuGroupValue> &
|
||||||
|
PickDialogProps &
|
||||||
|
StyleProps) => (
|
||||||
// TODO: sub-menu state management
|
// TODO: sub-menu state management
|
||||||
<Styled.Dialog
|
<Styled.Dialog
|
||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
@@ -54,7 +71,6 @@ export const ComboboxDialogMenu = <MenuItemValue extends string | number, MenuGr
|
|||||||
slotHeaderInner={slotHeaderInner}
|
slotHeaderInner={slotHeaderInner}
|
||||||
slotTrigger={slotTrigger}
|
slotTrigger={slotTrigger}
|
||||||
slotFooter={slotFooter}
|
slotFooter={slotFooter}
|
||||||
|
|
||||||
placement={placement}
|
placement={placement}
|
||||||
className={className}
|
className={className}
|
||||||
>
|
>
|
||||||
@@ -64,7 +80,8 @@ export const ComboboxDialogMenu = <MenuItemValue extends string | number, MenuGr
|
|||||||
title={title}
|
title={title}
|
||||||
inputPlaceholder={inputPlaceholder}
|
inputPlaceholder={inputPlaceholder}
|
||||||
slotEmpty={slotEmpty}
|
slotEmpty={slotEmpty}
|
||||||
withStickyLayout
|
withSearch={withSearch}
|
||||||
|
withStickyLayout={withStickyLayout}
|
||||||
/>
|
/>
|
||||||
{children}
|
{children}
|
||||||
</Styled.Dialog>
|
</Styled.Dialog>
|
||||||
@@ -98,4 +115,5 @@ Styled.Dialog = styled(Dialog)`
|
|||||||
|
|
||||||
Styled.ComboboxMenu = styled(ComboboxMenu)`
|
Styled.ComboboxMenu = styled(ComboboxMenu)`
|
||||||
--comboboxMenu-backgroundColor: var(--comboboxDialogMenu-backgroundColor);
|
--comboboxMenu-backgroundColor: var(--comboboxDialogMenu-backgroundColor);
|
||||||
|
--comboboxMenu-item-gap: var(--comboxDialogMenu-item-gap, 0.5rem);
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { layoutMixins } from '@/styles/layoutMixins';
|
|||||||
|
|
||||||
import { Tag } from '@/components/Tag';
|
import { Tag } from '@/components/Tag';
|
||||||
|
|
||||||
type ElementProps<MenuItemValue extends string, MenuGroupValue extends string> = {
|
type ElementProps<MenuItemValue extends string | number, MenuGroupValue extends string | number> = {
|
||||||
items: MenuConfig<MenuItemValue, MenuGroupValue>;
|
items: MenuConfig<MenuItemValue, MenuGroupValue>;
|
||||||
onItemSelected?: () => void;
|
onItemSelected?: () => void;
|
||||||
|
|
||||||
@@ -23,6 +23,11 @@ type StyleProps = {
|
|||||||
withStickyLayout?: boolean;
|
withStickyLayout?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type ComboboxMenuProps<
|
||||||
|
MenuItemValue extends string | number,
|
||||||
|
MenuGroupValue extends string | number
|
||||||
|
> = ElementProps<MenuItemValue, MenuGroupValue> & StyleProps;
|
||||||
|
|
||||||
export const ComboboxMenu = <MenuItemValue extends string, MenuGroupValue extends string>({
|
export const ComboboxMenu = <MenuItemValue extends string, MenuGroupValue extends string>({
|
||||||
items,
|
items,
|
||||||
onItemSelected,
|
onItemSelected,
|
||||||
@@ -34,7 +39,7 @@ export const ComboboxMenu = <MenuItemValue extends string, MenuGroupValue extend
|
|||||||
|
|
||||||
className,
|
className,
|
||||||
withStickyLayout,
|
withStickyLayout,
|
||||||
}: ElementProps<MenuItemValue, MenuGroupValue> & StyleProps) => {
|
}: ComboboxMenuProps<MenuItemValue, MenuGroupValue>) => {
|
||||||
const [highlightedCommand, setHighlightedCommand] = useState<MenuItemValue>();
|
const [highlightedCommand, setHighlightedCommand] = useState<MenuItemValue>();
|
||||||
const [searchValue, setSearchValue] = useState('');
|
const [searchValue, setSearchValue] = useState('');
|
||||||
// const inputRef = useRef<HTMLInputElement | null>(null);
|
// const inputRef = useRef<HTMLInputElement | null>(null);
|
||||||
@@ -171,6 +176,7 @@ Styled.Command = styled(Command)<{ $withStickyLayout?: boolean }>`
|
|||||||
--comboboxMenu-item-highlighted-backgroundColor: var(--color-layer-3);
|
--comboboxMenu-item-highlighted-backgroundColor: var(--color-layer-3);
|
||||||
--comboboxMenu-item-highlighted-textColor: var(--color-text-1);
|
--comboboxMenu-item-highlighted-textColor: var(--color-text-1);
|
||||||
--comboboxMenu-item-backgroundColor: ;
|
--comboboxMenu-item-backgroundColor: ;
|
||||||
|
--comboboxMenu-item-gap: 0.5rem;
|
||||||
|
|
||||||
display: grid;
|
display: grid;
|
||||||
align-content: start;
|
align-content: start;
|
||||||
@@ -269,18 +275,17 @@ Styled.List = styled(Command.List)<{ $withStickyLayout?: boolean }>`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
Styled.Item = styled(Command.Item)`
|
Styled.Item = styled(Command.Item)`
|
||||||
|
${layoutMixins.scrollSnapItem}
|
||||||
${popoverMixins.item}
|
${popoverMixins.item}
|
||||||
--item-checked-backgroundColor: var(--comboboxMenu-item-checked-backgroundColor);
|
--item-checked-backgroundColor: var(--comboboxMenu-item-checked-backgroundColor);
|
||||||
--item-checked-textColor: var(--comboboxMenu-item-checked-textColor);
|
--item-checked-textColor: var(--comboboxMenu-item-checked-textColor);
|
||||||
--item-highlighted-textColor: var(--comboboxMenu-item-highlighted-textColor);
|
--item-highlighted-textColor: var(--comboboxMenu-item-highlighted-textColor);
|
||||||
|
--item-gap: var(--comboboxMenu-item-gap);
|
||||||
${layoutMixins.scrollSnapItem}
|
|
||||||
|
|
||||||
background-color: var(--comboboxMenu-backgroundColor, inherit);
|
background-color: var(--comboboxMenu-backgroundColor, inherit);
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0.5rem;
|
|
||||||
|
|
||||||
&[aria-disabled='true'] {
|
&[aria-disabled='true'] {
|
||||||
opacity: 0.75;
|
opacity: 0.75;
|
||||||
|
|||||||
@@ -48,6 +48,8 @@ type StyleProps = {
|
|||||||
className?: string;
|
className?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type DialogProps = ElementProps & StyleProps;
|
||||||
|
|
||||||
const DialogPortal = ({
|
const DialogPortal = ({
|
||||||
withPortal,
|
withPortal,
|
||||||
container,
|
container,
|
||||||
@@ -82,7 +84,7 @@ export const Dialog = ({
|
|||||||
hasHeaderBorder = false,
|
hasHeaderBorder = false,
|
||||||
children,
|
children,
|
||||||
className,
|
className,
|
||||||
}: ElementProps & StyleProps) => {
|
}: DialogProps) => {
|
||||||
const closeButtonRef = useRef<HTMLButtonElement>();
|
const closeButtonRef = useRef<HTMLButtonElement>();
|
||||||
|
|
||||||
const showOverlay = ![DialogPlacement.Inline, DialogPlacement.FullScreen].includes(placement);
|
const showOverlay = ![DialogPlacement.Inline, DialogPlacement.FullScreen].includes(placement);
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import {
|
|||||||
CaretIcon,
|
CaretIcon,
|
||||||
CautionCircleStrokeIcon,
|
CautionCircleStrokeIcon,
|
||||||
CautionCircleIcon,
|
CautionCircleIcon,
|
||||||
|
ChatIcon,
|
||||||
CheckIcon,
|
CheckIcon,
|
||||||
ChevronLeftIcon,
|
ChevronLeftIcon,
|
||||||
ChevronRightIcon,
|
ChevronRightIcon,
|
||||||
@@ -80,6 +81,7 @@ export enum IconName {
|
|||||||
Caret = 'Caret',
|
Caret = 'Caret',
|
||||||
CautionCircle = 'CautionCircle',
|
CautionCircle = 'CautionCircle',
|
||||||
CautionCircleStroked = 'CautionCircleStroked',
|
CautionCircleStroked = 'CautionCircleStroked',
|
||||||
|
Chat = 'Chat',
|
||||||
Check = 'Check',
|
Check = 'Check',
|
||||||
ChevronLeft = 'ChevronLeft',
|
ChevronLeft = 'ChevronLeft',
|
||||||
ChevronRight = 'ChevronRight',
|
ChevronRight = 'ChevronRight',
|
||||||
@@ -148,6 +150,7 @@ const icons = {
|
|||||||
[IconName.Caret]: CaretIcon,
|
[IconName.Caret]: CaretIcon,
|
||||||
[IconName.CautionCircle]: CautionCircleIcon,
|
[IconName.CautionCircle]: CautionCircleIcon,
|
||||||
[IconName.CautionCircleStroked]: CautionCircleStrokeIcon,
|
[IconName.CautionCircleStroked]: CautionCircleStrokeIcon,
|
||||||
|
[IconName.Chat]: ChatIcon,
|
||||||
[IconName.Check]: CheckIcon,
|
[IconName.Check]: CheckIcon,
|
||||||
[IconName.ChevronLeft]: ChevronLeftIcon,
|
[IconName.ChevronLeft]: ChevronLeftIcon,
|
||||||
[IconName.ChevronRight]: ChevronRightIcon,
|
[IconName.ChevronRight]: ChevronRightIcon,
|
||||||
|
|||||||
@@ -44,4 +44,4 @@ export type EvmDerivedAddresses = {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const AMOUNT_RESERVED_FOR_GAS_USDC = 100_000;
|
export const AMOUNT_RESERVED_FOR_GAS_USDC = 0.1;
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export type MenuItem<MenuItemValue, MenuItemTypes = string> = {
|
|||||||
value: MenuItemValue;
|
value: MenuItemValue;
|
||||||
|
|
||||||
slotBefore?: React.ReactNode;
|
slotBefore?: React.ReactNode;
|
||||||
label: string;
|
label: React.ReactNode;
|
||||||
labelRight?: React.ReactNode;
|
labelRight?: React.ReactNode;
|
||||||
tag?: React.ReactNode;
|
tag?: React.ReactNode;
|
||||||
slotAfter?: React.ReactNode;
|
slotAfter?: React.ReactNode;
|
||||||
|
|||||||
@@ -74,13 +74,12 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
|
|||||||
() => ({
|
() => ({
|
||||||
depositToSubaccount: async ({
|
depositToSubaccount: async ({
|
||||||
subaccountClient,
|
subaccountClient,
|
||||||
assetId = 0,
|
|
||||||
amount,
|
amount,
|
||||||
}: {
|
}: {
|
||||||
subaccountClient: SubaccountClient;
|
subaccountClient: SubaccountClient;
|
||||||
assetId?: number;
|
assetId?: number;
|
||||||
amount: Long;
|
amount: number;
|
||||||
}) => await compositeClient?.validatorClient.post.deposit(subaccountClient, assetId, amount),
|
}) => await compositeClient?.depositToSubaccount(subaccountClient, amount.toString()),
|
||||||
|
|
||||||
withdrawFromSubaccount: async ({
|
withdrawFromSubaccount: async ({
|
||||||
subaccountClient,
|
subaccountClient,
|
||||||
@@ -201,13 +200,9 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
|
|||||||
async (balance: AccountBalance) => {
|
async (balance: AccountBalance) => {
|
||||||
if (!localDydxWallet) return;
|
if (!localDydxWallet) return;
|
||||||
|
|
||||||
const amountAfterDust = MustBigNumber(balance.amount)
|
const amount = parseFloat(balance.amount) - AMOUNT_RESERVED_FOR_GAS_USDC;
|
||||||
.minus(AMOUNT_RESERVED_FOR_GAS_USDC) // keep 0.1 USDC in user's wallet for gas
|
|
||||||
.toString();
|
|
||||||
|
|
||||||
const amount = Long.fromString(amountAfterDust || '0');
|
if (amount > 0) {
|
||||||
|
|
||||||
if (amount.greaterThan(Long.ZERO)) {
|
|
||||||
const subaccountClient = new SubaccountClient(localDydxWallet, 0);
|
const subaccountClient = new SubaccountClient(localDydxWallet, 0);
|
||||||
await depositToSubaccount({ amount, subaccountClient });
|
await depositToSubaccount({ amount, subaccountClient });
|
||||||
}
|
}
|
||||||
@@ -225,7 +220,7 @@ export const useSubaccountContext = ({ localDydxWallet }: { localDydxWallet?: Lo
|
|||||||
}, [usdcCoinBalance]);
|
}, [usdcCoinBalance]);
|
||||||
|
|
||||||
const deposit = useCallback(
|
const deposit = useCallback(
|
||||||
async (amount: Long) => {
|
async (amount: number) => {
|
||||||
if (!subaccountClient) {
|
if (!subaccountClient) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M5.625 6.1875h6.75m-6.75 2.25H9M1.6875 9.57c0 1.2.84225 2.2455 2.03025 2.4203.84675.1245 1.7025.2197 2.56725.2842.2625.0195.5025.1575.64875.3758L9 15.75l2.0663-3.0997c.0724-.1078.1685-.1977.2809-.2628.1125-.0651.2382-.1038.3678-.113.8589-.0641 1.7152-.1589 2.5672-.2842 1.188-.1748 2.0303-1.2195 2.0303-2.42105v-4.5135c0-1.2015-.8423-2.24625-2.0303-2.421A36.294434 36.294434 0 0 0 9 2.25c-1.794 0-3.558.13125-5.28225.38475-1.188.17475-2.03025 1.22025-2.03025 2.421V9.57Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||||
|
After Width: | Height: | Size: 672 B |
@@ -1 +1 @@
|
|||||||
<svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M15 8C15 9.53527 14.6867 10.8758 14.2269 11.7954C13.77 12.7092 13.3116 12.9664 13.0527 12.9968L12.6636 12.8953C12.4116 12.7511 12.092 12.4331 11.7731 11.7954C11.3133 10.8758 11 9.53527 11 8C11 6.46473 11.3133 5.12424 11.7731 4.20457C12.0924 3.56607 12.4124 3.24815 12.6645 3.10417L13.0519 3.00311C13.3107 3.0331 13.7696 3.28991 14.2269 4.20457C14.6867 5.12424 15 6.46473 15 8ZM12.2928 2.16768L1.41963 5.00415C0.628571 5.08768 0 6.39699 0 7.99992C0 9.60346 0.629045 10.9131 1.42053 10.9958L2.50023 11.2774V12.9998C2.50023 13.8283 3.17181 14.4998 4.00023 14.4998C4.82866 14.4998 5.50023 13.8283 5.50023 12.9998V12.0601L12.2914 13.8317C12.5186 13.9417 12.7559 14 13 14C14.6569 14 16 11.3137 16 8C16 4.68629 14.6569 2 13 2C12.7564 2 12.5196 2.05808 12.2928 2.16768ZM10.9931 3.5402L2.49607 5.75681C2.80523 6.30634 3 7.10764 3 7.99992C3 8.89214 2.80525 9.69339 2.49614 10.2429L10.9929 12.4595C10.3833 11.3612 10 9.77013 10 8C10 6.22968 10.3834 4.63843 10.9931 3.5402ZM2 7.99992C2 8.70677 1.85462 9.29725 1.66623 9.67403C1.59961 9.80728 1.54246 9.88955 1.5 9.93955C1.45754 9.88955 1.40039 9.80728 1.33377 9.67403C1.14538 9.29725 1 8.70677 1 7.99992C1 7.29308 1.14538 6.70259 1.33377 6.32582C1.40039 6.19256 1.45754 6.11029 1.5 6.06029C1.54246 6.11029 1.59961 6.19256 1.66623 6.32582C1.85462 6.70259 2 7.29308 2 7.99992ZM1.41964 10.0124C1.41962 10.0124 1.42071 10.0118 1.42296 10.0109C1.42079 10.0121 1.41966 10.0125 1.41964 10.0124ZM1.57704 10.0109C1.57929 10.0118 1.58038 10.0124 1.58036 10.0124C1.58033 10.0125 1.57921 10.0121 1.57704 10.0109ZM1.58036 5.9874C1.58038 5.98747 1.57929 5.98808 1.57704 5.98899C1.57921 5.98778 1.58034 5.98732 1.58036 5.9874ZM1.42296 5.98899C1.42071 5.98808 1.41962 5.98747 1.41964 5.9874C1.41966 5.98732 1.42079 5.98778 1.42296 5.98899ZM3.50023 12.9998V11.5383L4.50023 11.7992V12.9998C4.50023 13.276 4.27638 13.4998 4.00023 13.4998C3.72409 13.4998 3.50023 13.276 3.50023 12.9998Z" fill="currentColor"/></svg>
|
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M15 8C15 9.53527 14.6867 10.8758 14.2269 11.7954C13.77 12.7092 13.3116 12.9664 13.0527 12.9968L12.6636 12.8953C12.4116 12.7511 12.092 12.4331 11.7731 11.7954C11.3133 10.8758 11 9.53527 11 8C11 6.46473 11.3133 5.12424 11.7731 4.20457C12.0924 3.56607 12.4124 3.24815 12.6645 3.10417L13.0519 3.00311C13.3107 3.0331 13.7696 3.28991 14.2269 4.20457C14.6867 5.12424 15 6.46473 15 8ZM12.2928 2.16768L1.41963 5.00415C0.628571 5.08768 0 6.39699 0 7.99992C0 9.60346 0.629045 10.9131 1.42053 10.9958L2.50023 11.2774V12.9998C2.50023 13.8283 3.17181 14.4998 4.00023 14.4998C4.82866 14.4998 5.50023 13.8283 5.50023 12.9998V12.0601L12.2914 13.8317C12.5186 13.9417 12.7559 14 13 14C14.6569 14 16 11.3137 16 8C16 4.68629 14.6569 2 13 2C12.7564 2 12.5196 2.05808 12.2928 2.16768ZM10.9931 3.5402L2.49607 5.75681C2.80523 6.30634 3 7.10764 3 7.99992C3 8.89214 2.80525 9.69339 2.49614 10.2429L10.9929 12.4595C10.3833 11.3612 10 9.77013 10 8C10 6.22968 10.3834 4.63843 10.9931 3.5402ZM2 7.99992C2 8.70677 1.85462 9.29725 1.66623 9.67403C1.59961 9.80728 1.54246 9.88955 1.5 9.93955C1.45754 9.88955 1.40039 9.80728 1.33377 9.67403C1.14538 9.29725 1 8.70677 1 7.99992C1 7.29308 1.14538 6.70259 1.33377 6.32582C1.40039 6.19256 1.45754 6.11029 1.5 6.06029C1.54246 6.11029 1.59961 6.19256 1.66623 6.32582C1.85462 6.70259 2 7.29308 2 7.99992ZM1.41964 10.0124C1.41962 10.0124 1.42071 10.0118 1.42296 10.0109C1.42079 10.0121 1.41966 10.0125 1.41964 10.0124ZM1.57704 10.0109C1.57929 10.0118 1.58038 10.0124 1.58036 10.0124C1.58033 10.0125 1.57921 10.0121 1.57704 10.0109ZM1.58036 5.9874C1.58038 5.98747 1.57929 5.98808 1.57704 5.98899C1.57921 5.98778 1.58034 5.98732 1.58036 5.9874ZM1.42296 5.98899C1.42071 5.98808 1.41962 5.98747 1.41964 5.9874C1.41966 5.98732 1.42079 5.98778 1.42296 5.98899ZM3.50023 12.9998V11.5383L4.50023 11.7992V12.9998C4.50023 13.276 4.27638 13.4998 4.00023 13.4998C3.72409 13.4998 3.50023 13.276 3.50023 12.9998Z" fill="currentColor"/></svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
@@ -8,6 +8,7 @@ export { default as CalculatorIcon } from './calculator.svg';
|
|||||||
export { default as CaretIcon } from './caret-down.svg';
|
export { default as CaretIcon } from './caret-down.svg';
|
||||||
export { default as CautionCircleIcon } from './caution-circle.svg';
|
export { default as CautionCircleIcon } from './caution-circle.svg';
|
||||||
export { default as CautionCircleStrokeIcon } from './caution-circle-stroke.svg';
|
export { default as CautionCircleStrokeIcon } from './caution-circle-stroke.svg';
|
||||||
|
export { default as ChatIcon } from './chat-bubble.svg';
|
||||||
export { default as CheckIcon } from './check.svg';
|
export { default as CheckIcon } from './check.svg';
|
||||||
export { default as ChevronLeftIcon } from './chevron-left.svg';
|
export { default as ChevronLeftIcon } from './chevron-left.svg';
|
||||||
export { default as ChevronRightIcon } from './chevron-right.svg';
|
export { default as ChevronRightIcon } from './chevron-right.svg';
|
||||||
|
|||||||
@@ -1,12 +1,16 @@
|
|||||||
import styled, { type AnyStyledComponent, css } from 'styled-components';
|
import styled, { type AnyStyledComponent, css } from 'styled-components';
|
||||||
|
|
||||||
import { AbacusApiStatus } from '@/constants/abacus';
|
import { AbacusApiStatus } from '@/constants/abacus';
|
||||||
|
import { ButtonSize } from '@/constants/buttons';
|
||||||
import { STRING_KEYS } from '@/constants/localization';
|
import { STRING_KEYS } from '@/constants/localization';
|
||||||
|
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
|
||||||
|
|
||||||
import { useApiState, useStringGetter } from '@/hooks';
|
import { useApiState, useSelectedNetwork, useStringGetter } from '@/hooks';
|
||||||
|
import { ChatIcon, LinkOutIcon } from '@/icons';
|
||||||
|
|
||||||
import { layoutMixins } from '@/styles/layoutMixins';
|
import { layoutMixins } from '@/styles/layoutMixins';
|
||||||
|
|
||||||
|
import { Button } from '@/components/Button';
|
||||||
import { Details } from '@/components/Details';
|
import { Details } from '@/components/Details';
|
||||||
import { Output, OutputType } from '@/components/Output';
|
import { Output, OutputType } from '@/components/Output';
|
||||||
import { WithTooltip } from '@/components/WithTooltip';
|
import { WithTooltip } from '@/components/WithTooltip';
|
||||||
@@ -24,6 +28,8 @@ enum ExchangeStatus {
|
|||||||
export const FooterDesktop = () => {
|
export const FooterDesktop = () => {
|
||||||
const stringGetter = useStringGetter();
|
const stringGetter = useStringGetter();
|
||||||
const { height, indexerHeight, status, statusErrorMessage } = useApiState();
|
const { height, indexerHeight, status, statusErrorMessage } = useApiState();
|
||||||
|
const { selectedNetwork } = useSelectedNetwork();
|
||||||
|
const { statusPage } = ENVIRONMENT_CONFIG_MAP[selectedNetwork].links;
|
||||||
|
|
||||||
const { exchangeStatus, label } =
|
const { exchangeStatus, label } =
|
||||||
!status || status === AbacusApiStatus.NORMAL
|
!status || status === AbacusApiStatus.NORMAL
|
||||||
@@ -38,6 +44,7 @@ export const FooterDesktop = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Styled.Footer>
|
<Styled.Footer>
|
||||||
|
<Styled.Row>
|
||||||
<WithTooltip
|
<WithTooltip
|
||||||
slotTooltip={
|
slotTooltip={
|
||||||
statusErrorMessage && (
|
statusErrorMessage && (
|
||||||
@@ -47,11 +54,27 @@ export const FooterDesktop = () => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Styled.Row>
|
<Styled.FooterButton
|
||||||
<Styled.StatusDot exchangeStatus={exchangeStatus} />
|
slotLeft={<Styled.StatusDot exchangeStatus={exchangeStatus} />}
|
||||||
<span>{label}</span>
|
slotRight={statusPage && <LinkOutIcon />}
|
||||||
</Styled.Row>
|
size={ButtonSize.XSmall}
|
||||||
|
state={{ isDisabled: !statusPage }}
|
||||||
|
>
|
||||||
|
{label}
|
||||||
|
</Styled.FooterButton>
|
||||||
</WithTooltip>
|
</WithTooltip>
|
||||||
|
|
||||||
|
{globalThis?.Intercom && (
|
||||||
|
<Styled.FooterButton
|
||||||
|
slotLeft={<ChatIcon />}
|
||||||
|
size={ButtonSize.XSmall}
|
||||||
|
onClick={() => globalThis.Intercom('show')}
|
||||||
|
>
|
||||||
|
{stringGetter({ key: STRING_KEYS.HELP_AND_SUPPORT })}
|
||||||
|
</Styled.FooterButton>
|
||||||
|
)}
|
||||||
|
</Styled.Row>
|
||||||
|
|
||||||
{import.meta.env.MODE !== 'production' && (
|
{import.meta.env.MODE !== 'production' && (
|
||||||
<Styled.Details
|
<Styled.Details
|
||||||
withSeparators
|
withSeparators
|
||||||
@@ -82,20 +105,22 @@ Styled.Footer = styled.footer`
|
|||||||
${layoutMixins.stickyFooter}
|
${layoutMixins.stickyFooter}
|
||||||
${layoutMixins.spacedRow}
|
${layoutMixins.spacedRow}
|
||||||
grid-area: Footer;
|
grid-area: Footer;
|
||||||
|
|
||||||
font-size: 0.66em;
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
Styled.Row = styled.div`
|
Styled.Row = styled.div`
|
||||||
${layoutMixins.row}
|
${layoutMixins.row}
|
||||||
padding: 0 1rem;
|
${layoutMixins.spacedRow}
|
||||||
gap: 0.5rem;
|
width: var(--sidebar-width);
|
||||||
|
|
||||||
|
padding: 0 0.5rem;
|
||||||
|
border-right: 1px solid var(--color-border);
|
||||||
`;
|
`;
|
||||||
|
|
||||||
Styled.StatusDot = styled.div<{ exchangeStatus: ExchangeStatus }>`
|
Styled.StatusDot = styled.div<{ exchangeStatus: ExchangeStatus }>`
|
||||||
width: 1em;
|
width: 0.5rem;
|
||||||
height: 1em;
|
height: 0.5rem;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
|
margin-right: 0.25rem;
|
||||||
|
|
||||||
background-color: ${({ exchangeStatus }) =>
|
background-color: ${({ exchangeStatus }) =>
|
||||||
({
|
({
|
||||||
@@ -104,12 +129,28 @@ Styled.StatusDot = styled.div<{ exchangeStatus: ExchangeStatus }>`
|
|||||||
}[exchangeStatus])};
|
}[exchangeStatus])};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
Styled.FooterButton = styled(Button)`
|
||||||
|
--button-height: 1.5rem;
|
||||||
|
--button-radius: 0.25rem;
|
||||||
|
--button-backgroundColor: var(--color-layer-2);
|
||||||
|
--button-border: none;
|
||||||
|
--button-textColor: var(--color-text-0);
|
||||||
|
|
||||||
|
&:hover:not(:disabled) {
|
||||||
|
--button-backgroundColor: var(--color-layer-3);
|
||||||
|
--button-textColor: var(--color-text-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
Styled.WarningOutput = styled(Output)`
|
Styled.WarningOutput = styled(Output)`
|
||||||
color: var(--color-warning);
|
color: var(--color-warning);
|
||||||
`;
|
`;
|
||||||
|
|
||||||
Styled.Details = styled(Details)`
|
Styled.Details = styled(Details)`
|
||||||
${layoutMixins.scrollArea}
|
${layoutMixins.scrollArea}
|
||||||
|
font: var(--font-tiny-book);
|
||||||
padding: 0 0.5em;
|
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -13,4 +13,6 @@ declare global {
|
|||||||
|
|
||||||
'abacus:connectNetwork': CustomEvent;
|
'abacus:connectNetwork': CustomEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var Intercom: any;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,11 +36,10 @@
|
|||||||
--single-unit-height: 9.375rem;
|
--single-unit-height: 9.375rem;
|
||||||
|
|
||||||
/* Modal constants */
|
/* Modal constants */
|
||||||
--sidebar-modal-width: 18.75rem;
|
--dialog-small-width: 18.75rem;
|
||||||
--modal-small-width: 18.75rem;
|
--dialog-medium-width: 20.5rem;
|
||||||
--modal-medium-width: 20.5rem;
|
--dialog-large-width: 26.25rem;
|
||||||
--modal-large-width: 26.25rem;
|
--dialog-header-height: 4rem;
|
||||||
--modal-header-height: 4rem;
|
|
||||||
|
|
||||||
/* Market Selector constants */
|
/* Market Selector constants */
|
||||||
--marketsDropdown-openWidth: 45rem;
|
--marketsDropdown-openWidth: 45rem;
|
||||||
|
|||||||
@@ -188,13 +188,14 @@ export const popoverMixins = {
|
|||||||
--item-highlighted-backgroundColor: var(--color-layer-2);
|
--item-highlighted-backgroundColor: var(--color-layer-2);
|
||||||
--item-highlighted-textColor: var(--color-text-2);
|
--item-highlighted-textColor: var(--color-text-2);
|
||||||
|
|
||||||
|
--item-gap: 0.5em;
|
||||||
--item-radius: 0px;
|
--item-radius: 0px;
|
||||||
--item-padding: 0.5em 1em;
|
--item-padding: 0.5em 1em;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0.5em;
|
gap: var(--item-gap);
|
||||||
|
|
||||||
padding: var(--item-padding);
|
padding: var(--item-padding);
|
||||||
border-radius: var(--item-radius);
|
border-radius: var(--item-radius);
|
||||||
|
|||||||
@@ -1,69 +1,94 @@
|
|||||||
|
import { useMemo } from 'react';
|
||||||
import styled, { AnyStyledComponent } from 'styled-components';
|
import styled, { AnyStyledComponent } from 'styled-components';
|
||||||
import { useDispatch } from 'react-redux';
|
|
||||||
import { Close } from '@radix-ui/react-dialog';
|
|
||||||
|
|
||||||
import { STRING_KEYS } from '@/constants/localization';
|
import { STRING_KEYS } from '@/constants/localization';
|
||||||
import { useStringGetter } from '@/hooks';
|
import { useStringGetter } from '@/hooks';
|
||||||
import { layoutMixins } from '@/styles/layoutMixins';
|
import { ChatIcon, FeedbackIcon, FileIcon, TerminalIcon } from '@/icons';
|
||||||
|
|
||||||
import { Button } from '@/components/Button';
|
import { ComboboxDialogMenu } from '@/components/ComboboxDialogMenu';
|
||||||
import { Dialog } from '@/components/Dialog';
|
|
||||||
import { ButtonAction, ButtonType } from '@/constants/buttons';
|
import { isTruthy } from '@/lib/isTruthy';
|
||||||
import { Icon, IconName } from '@/components/Icon';
|
|
||||||
|
|
||||||
type ElementProps = {
|
type ElementProps = {
|
||||||
setIsOpen: (open: boolean) => void;
|
setIsOpen: (open: boolean) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const HELP_URL = `https://docs.google.com/forms/d/e/1FAIpQLSezLsWCKvAYDEb7L-2O4wOON1T56xxro9A2Azvl6IxXHP_15Q/viewform?usp=sf_link`;
|
const HELP_LINKS = {
|
||||||
|
apiDocumentation: 'https://v4-teacher.vercel.app/',
|
||||||
|
helpCenter: null,
|
||||||
|
feedback: null,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* HelpDialog
|
|
||||||
* - Will temporarily be used as a 'Give Feedback' dialog.
|
|
||||||
* - It will ask users to navigate to a Google Form in order to record feedback.
|
|
||||||
*/
|
|
||||||
export const HelpDialog = ({ setIsOpen }: ElementProps) => {
|
export const HelpDialog = ({ setIsOpen }: ElementProps) => {
|
||||||
const stringGetter = useStringGetter();
|
const stringGetter = useStringGetter();
|
||||||
|
|
||||||
|
const HELP_ITEMS = useMemo(
|
||||||
|
() => [
|
||||||
|
{
|
||||||
|
group: 'help-items',
|
||||||
|
items: [
|
||||||
|
HELP_LINKS.helpCenter && {
|
||||||
|
value: 'help-center',
|
||||||
|
label: stringGetter({ key: STRING_KEYS.HELP_CENTER }),
|
||||||
|
description: stringGetter({ key: STRING_KEYS.HELP_CENTER_DESCRIPTION }),
|
||||||
|
onSelect: () => {
|
||||||
|
HELP_LINKS.helpCenter && globalThis.open(HELP_LINKS.helpCenter, '_blank');
|
||||||
|
setIsOpen(false);
|
||||||
|
},
|
||||||
|
slotBefore: <FileIcon />,
|
||||||
|
},
|
||||||
|
HELP_LINKS.apiDocumentation && {
|
||||||
|
value: 'api-documentation',
|
||||||
|
label: stringGetter({ key: STRING_KEYS.API_DOCUMENTATION }),
|
||||||
|
description: stringGetter({ key: STRING_KEYS.API_DOCUMENTATION_DESCRIPTION }),
|
||||||
|
onSelect: () => {
|
||||||
|
HELP_LINKS.apiDocumentation && globalThis.open(HELP_LINKS.apiDocumentation, '_blank');
|
||||||
|
setIsOpen(false);
|
||||||
|
},
|
||||||
|
slotBefore: <TerminalIcon />,
|
||||||
|
},
|
||||||
|
globalThis?.Intercom && {
|
||||||
|
value: 'live-chat',
|
||||||
|
label: stringGetter({ key: STRING_KEYS.LIVE_CHAT }),
|
||||||
|
description: stringGetter({ key: STRING_KEYS.LIVE_CHAT_DESCRIPTION }),
|
||||||
|
onSelect: () => {
|
||||||
|
globalThis.Intercom('show');
|
||||||
|
setIsOpen(false);
|
||||||
|
},
|
||||||
|
slotBefore: <ChatIcon />,
|
||||||
|
},
|
||||||
|
HELP_LINKS.feedback && {
|
||||||
|
value: 'feedback',
|
||||||
|
label: stringGetter({ key: STRING_KEYS.PROVIDE_FEEDBACK }),
|
||||||
|
description: stringGetter({ key: STRING_KEYS.PROVIDE_FEEDBACK_DESCRIPTION }),
|
||||||
|
onSelect: () => {
|
||||||
|
HELP_LINKS.feedback && globalThis.open(HELP_LINKS.feedback, '_blank');
|
||||||
|
setIsOpen(false);
|
||||||
|
},
|
||||||
|
slotBefore: <FeedbackIcon />,
|
||||||
|
},
|
||||||
|
].filter(isTruthy),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[stringGetter]
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog
|
<Styled.ComboboxDialogMenu
|
||||||
isOpen
|
isOpen
|
||||||
|
withSearch={false}
|
||||||
setIsOpen={setIsOpen}
|
setIsOpen={setIsOpen}
|
||||||
title={stringGetter({ key: STRING_KEYS.PROVIDE_FEEDBACK })}
|
title={stringGetter({ key: STRING_KEYS.HELP })}
|
||||||
description={stringGetter({ key: STRING_KEYS.PROVIDE_FEEDBACK_DESCRIPTION })}
|
items={HELP_ITEMS}
|
||||||
>
|
/>
|
||||||
<Styled.Content>
|
|
||||||
<p>
|
|
||||||
You will be navigated to a Google Form where you will be able to provide feedback. Thank
|
|
||||||
you for your contribution!
|
|
||||||
</p>
|
|
||||||
<Styled.ButtonRow>
|
|
||||||
<Close asChild>
|
|
||||||
<Button
|
|
||||||
action={ButtonAction.Primary}
|
|
||||||
type={ButtonType.Link}
|
|
||||||
href={HELP_URL}
|
|
||||||
slotRight={<Icon iconName={IconName.LinkOut} />}
|
|
||||||
>
|
|
||||||
{stringGetter({ key: STRING_KEYS.CONTINUE })}
|
|
||||||
</Button>
|
|
||||||
</Close>
|
|
||||||
</Styled.ButtonRow>
|
|
||||||
</Styled.Content>
|
|
||||||
</Dialog>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const Styled: Record<string, AnyStyledComponent> = {};
|
const Styled: Record<string, AnyStyledComponent> = {};
|
||||||
|
|
||||||
Styled.ButtonRow = styled.div`
|
Styled.ComboboxDialogMenu = styled(ComboboxDialogMenu)`
|
||||||
${layoutMixins.row}
|
--dialog-width: var(--dialog-small-width);
|
||||||
|
--dialog-content-paddingTop: 1rem;
|
||||||
gap: 0.5rem;
|
--dialog-content-paddingBottom: 1rem;
|
||||||
justify-content: end;
|
--comboxDialogMenu-item-gap: 1rem;
|
||||||
`;
|
|
||||||
|
|
||||||
Styled.Content = styled.div`
|
|
||||||
${layoutMixins.column}
|
|
||||||
gap: 1rem;
|
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ export const OnboardingDialog = ({ setIsOpen }: ElementProps) => {
|
|||||||
const stringGetter = useStringGetter();
|
const stringGetter = useStringGetter();
|
||||||
const { isMobile } = useBreakpoints();
|
const { isMobile } = useBreakpoints();
|
||||||
|
|
||||||
const { walletType } = useAccounts();
|
const { disconnect, walletType } = useAccounts();
|
||||||
|
|
||||||
const currentOnboardingStep = useSelector(calculateOnboardingStep);
|
const currentOnboardingStep = useSelector(calculateOnboardingStep);
|
||||||
|
|
||||||
@@ -45,10 +45,17 @@ export const OnboardingDialog = ({ setIsOpen }: ElementProps) => {
|
|||||||
if (!currentOnboardingStep) setIsOpen?.(false);
|
if (!currentOnboardingStep) setIsOpen?.(false);
|
||||||
}, [currentOnboardingStep]);
|
}, [currentOnboardingStep]);
|
||||||
|
|
||||||
|
const setIsOpenFromDialog = (open: boolean) => {
|
||||||
|
if (!open && currentOnboardingStep === OnboardingSteps.AcknowledgeTerms) {
|
||||||
|
disconnect();
|
||||||
|
}
|
||||||
|
setIsOpen?.(open);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Styled.Dialog
|
<Styled.Dialog
|
||||||
isOpen={Boolean(currentOnboardingStep)}
|
isOpen={Boolean(currentOnboardingStep)}
|
||||||
setIsOpen={setIsOpen}
|
setIsOpen={setIsOpenFromDialog}
|
||||||
{...(currentOnboardingStep &&
|
{...(currentOnboardingStep &&
|
||||||
{
|
{
|
||||||
[OnboardingSteps.ChooseWallet]: {
|
[OnboardingSteps.ChooseWallet]: {
|
||||||
@@ -87,10 +94,10 @@ export const OnboardingDialog = ({ setIsOpen }: ElementProps) => {
|
|||||||
title: stringGetter({ key: STRING_KEYS.ACKNOWLEDGE_TERMS }),
|
title: stringGetter({ key: STRING_KEYS.ACKNOWLEDGE_TERMS }),
|
||||||
children: (
|
children: (
|
||||||
<Styled.Content>
|
<Styled.Content>
|
||||||
<AcknowledgeTerms />
|
<AcknowledgeTerms onClose={() => setIsOpenFromDialog?.(false)} />
|
||||||
</Styled.Content>
|
</Styled.Content>
|
||||||
),
|
),
|
||||||
width: '20rem',
|
width: '30rem',
|
||||||
},
|
},
|
||||||
[OnboardingSteps.DepositFunds]: {
|
[OnboardingSteps.DepositFunds]: {
|
||||||
title: stringGetter({ key: STRING_KEYS.DEPOSIT }),
|
title: stringGetter({ key: STRING_KEYS.DEPOSIT }),
|
||||||
|
|||||||
@@ -6,14 +6,17 @@ import { AppRoute } from '@/constants/routes';
|
|||||||
import { STRING_KEYS } from '@/constants/localization';
|
import { STRING_KEYS } from '@/constants/localization';
|
||||||
import { ButtonAction } from '@/constants/buttons';
|
import { ButtonAction } from '@/constants/buttons';
|
||||||
|
|
||||||
|
import { layoutMixins } from '@/styles/layoutMixins';
|
||||||
|
|
||||||
import { Button } from '@/components/Button';
|
import { Button } from '@/components/Button';
|
||||||
import { Link } from '@/components/Link';
|
import { Link } from '@/components/Link';
|
||||||
|
|
||||||
type ElementProps = {
|
type ElementProps = {
|
||||||
|
onClose?: () => void;
|
||||||
onContinue?: () => void;
|
onContinue?: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const AcknowledgeTerms = ({ onContinue }: ElementProps) => {
|
export const AcknowledgeTerms = ({ onClose, onContinue }: ElementProps) => {
|
||||||
const stringGetter = useStringGetter();
|
const stringGetter = useStringGetter();
|
||||||
|
|
||||||
const { saveHasAcknowledgedTerms } = useAccounts();
|
const { saveHasAcknowledgedTerms } = useAccounts();
|
||||||
@@ -25,26 +28,40 @@ export const AcknowledgeTerms = ({ onContinue }: ElementProps) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<span>
|
<p>
|
||||||
{stringGetter({
|
{stringGetter({
|
||||||
key: STRING_KEYS.LEGAL_UPDATES_DESCRIPTION,
|
key: STRING_KEYS.TOS_TITLE,
|
||||||
params: {
|
params: {
|
||||||
TOU: (
|
TERMS_LINK: (
|
||||||
<Styled.Link href={`/#${AppRoute.Terms}`}>
|
<Styled.Link href={`/#${AppRoute.Terms}`}>
|
||||||
{stringGetter({ key: STRING_KEYS.TERMS_OF_USE })}
|
{stringGetter({ key: STRING_KEYS.TERMS_OF_USE })}
|
||||||
</Styled.Link>
|
</Styled.Link>
|
||||||
),
|
),
|
||||||
PRIVACY_POLICY: (
|
PRIVACY_POLICY_LINK: (
|
||||||
<Styled.Link href={`/#${AppRoute.Privacy}`}>
|
<Styled.Link href={`/#${AppRoute.Privacy}`}>
|
||||||
{stringGetter({ key: STRING_KEYS.PRIVACY_POLICY })}
|
{stringGetter({ key: STRING_KEYS.PRIVACY_POLICY })}
|
||||||
</Styled.Link>
|
</Styled.Link>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
})}
|
})}
|
||||||
</span>
|
</p>
|
||||||
<Button onClick={onAcknowledgement} action={ButtonAction.Primary}>
|
<Styled.TOS>
|
||||||
|
<ul>
|
||||||
|
<li>{stringGetter({ key: STRING_KEYS.TOS_LINE1 })}</li>
|
||||||
|
<li>{stringGetter({ key: STRING_KEYS.TOS_LINE2 })}</li>
|
||||||
|
<li>{stringGetter({ key: STRING_KEYS.TOS_LINE3 })}</li>
|
||||||
|
<li>{stringGetter({ key: STRING_KEYS.TOS_LINE4 })}</li>
|
||||||
|
<li>{stringGetter({ key: STRING_KEYS.TOS_LINE5 })}</li>
|
||||||
|
</ul>
|
||||||
|
</Styled.TOS>
|
||||||
|
<Styled.Row>
|
||||||
|
<Styled.Button onClick={onClose} action={ButtonAction.Base}>
|
||||||
|
{stringGetter({ key: STRING_KEYS.CLOSE })}
|
||||||
|
</Styled.Button>
|
||||||
|
<Styled.Button onClick={onAcknowledgement} action={ButtonAction.Primary}>
|
||||||
{stringGetter({ key: STRING_KEYS.I_AGREE })}
|
{stringGetter({ key: STRING_KEYS.I_AGREE })}
|
||||||
</Button>
|
</Styled.Button>
|
||||||
|
</Styled.Row>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -59,3 +76,23 @@ Styled.Link = styled(Link)`
|
|||||||
color: var(--color-accent);
|
color: var(--color-accent);
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
Styled.TOS = styled.section`
|
||||||
|
background-color: var(--color-layer-4);
|
||||||
|
padding: 1rem 1rem 1rem 2rem;
|
||||||
|
border-radius: 0.875rem;
|
||||||
|
> ul {
|
||||||
|
${layoutMixins.column};
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
Styled.Row = styled.div`
|
||||||
|
${layoutMixins.row};
|
||||||
|
|
||||||
|
gap: 1rem;
|
||||||
|
`;
|
||||||
|
|
||||||
|
Styled.Button = styled(Button)`
|
||||||
|
flex-grow: 1;
|
||||||
|
`;
|
||||||
|
|||||||
Reference in New Issue
Block a user