Merge remote-tracking branch 'origin/v3-single' into v3-single

# Conflicts:
#	yarn.lock
This commit is contained in:
liangping 2023-05-05 07:39:39 +08:00
commit 7a5368cd69
16 changed files with 15646 additions and 389 deletions

14982
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -33,6 +33,7 @@
"axios": "^1.3.2", "axios": "^1.3.2",
"buffer": "^6.0.3", "buffer": "^6.0.3",
"cross-fetch": "^3.1.5", "cross-fetch": "^3.1.5",
"daisyui": "^2.51.6",
"dayjs": "^1.11.7", "dayjs": "^1.11.7",
"long": "^5.2.1", "long": "^5.2.1",
"md-editor-v3": "^2.8.1", "md-editor-v3": "^2.8.1",
@ -42,6 +43,7 @@
"postcss": "^8.4.23", "postcss": "^8.4.23",
"prismjs": "^1.29.0", "prismjs": "^1.29.0",
"tailwindcss": "^3.3.1", "tailwindcss": "^3.3.1",
"theme-change": "^2.5.0",
"vite-plugin-vue-layouts": "^0.7.0", "vite-plugin-vue-layouts": "^0.7.0",
"vite-plugin-vuetify": "^1.0.2", "vite-plugin-vuetify": "^1.0.2",
"vue": "^3.2.45", "vue": "^3.2.45",

View File

@ -2,7 +2,8 @@
import { useTheme } from 'vuetify' import { useTheme } from 'vuetify'
import { useThemeConfig } from '@/plugins/vuetify/@core/composable/useThemeConfig' import { useThemeConfig } from '@/plugins/vuetify/@core/composable/useThemeConfig'
import { hexToRgb } from '@/plugins/vuetify/@layouts/utils' import { hexToRgb } from '@/plugins/vuetify/@layouts/utils'
import { themeChange } from 'theme-change'
import { onMounted } from 'vue'
const { syncInitialLoaderTheme, syncVuetifyThemeWithTheme: syncConfigThemeWithVuetifyTheme, isAppRtl } = useThemeConfig() const { syncInitialLoaderTheme, syncVuetifyThemeWithTheme: syncConfigThemeWithVuetifyTheme, isAppRtl } = useThemeConfig()
const { global } = useTheme() const { global } = useTheme()
@ -10,6 +11,10 @@ const { global } = useTheme()
// Sync current theme with initial loader theme // Sync current theme with initial loader theme
syncInitialLoaderTheme() syncInitialLoaderTheme()
syncConfigThemeWithVuetifyTheme() syncConfigThemeWithVuetifyTheme()
onMounted(()=> {
themeChange(false)
})
</script> </script>
<template> <template>

View File

@ -0,0 +1 @@
<svg width="22" height="22" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50" enable-background="new 0 0 50 50" fill="red"><path d="M25 39.7l-.6-.5C11.5 28.7 8 25 8 19c0-5 4-9 9-9 4.1 0 6.4 2.3 8 4.1 1.6-1.8 3.9-4.1 8-4.1 5 0 9 4 9 9 0 6-3.5 9.7-16.4 20.2l-.6.5zM17 12c-3.9 0-7 3.1-7 7 0 5.1 3.2 8.5 15 18.1 11.8-9.6 15-13 15-18.1 0-3.9-3.1-7-7-7-3.5 0-5.4 2.1-6.9 3.8L25 17.1l-1.1-1.3C22.4 14.1 20.5 12 17 12z"/></svg>

After

Width:  |  Height:  |  Size: 424 B

View File

@ -1,6 +1,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import { getLogo, useDashboard, } from '@/stores/useDashboard'; import { getLogo, useDashboard, } from '@/stores/useDashboard';
import { computed } from 'vue'; import { computed } from 'vue';
import { Icon } from '@iconify/vue'
const props = defineProps({ const props = defineProps({
name: { name: {
@ -10,45 +11,27 @@ const props = defineProps({
}); });
const dashboardStore = useDashboard() const dashboardStore = useDashboard()
const conf = computed(()=> dashboardStore.chains[props.name] || {}) const conf = computed(() => dashboardStore.chains[props.name] || {})
const addFavor = (e: Event) => {
e.stopPropagation();
e.preventDefault();
dashboardStore.favoriteMap[props.name] = !dashboardStore?.favoriteMap?.[props.name];
window.localStorage.setItem('favoriteMap', JSON.stringify(dashboardStore.favoriteMap))
}
</script> </script>
<template> <template>
<VCard outlined class="p-1"> <RouterLink :to="`/${name}`" class="bg-base-100 rounded shadow flex items-center px-3 py-3 cursor-pointer">
<VList class="card-list"> <div class="w-8 h-8 rounded-full overflow-hidden">
<VListItem :to="`/${name}`"> <img :src="conf.logo" />
<template #prepend> </div>
<VAvatar rounded size="45" variant="tonal" class="me-3"> <div class="font-semibold ml-4 text-base flex-1">
<VImg :src="conf.logo" height="22"/> {{ conf?.prettyName || props.name }}
</VAvatar> </div>
</template> <div @click="addFavor" class="pl-4 text-xl"
:class="{ 'text-warning': dashboardStore?.favoriteMap?.[props.name], 'text-gray-300 dark:text-gray-500': !dashboardStore?.favoriteMap?.[props.name] }">
<VListItemTitle class="font-weight-semibold text-sm mb-1"> <Icon icon="mdi-star" />
{{ conf?.prettyName || props.name }} </div>
</VListItemTitle> </RouterLink>
<VListItemSubtitle class="text-xs">
{{conf?.chainId || ''}}
</VListItemSubtitle>
<template #append>
<VListItemAction @click="(e:Event)=>{e.stopPropagation()}">
<VCheckbox
v-model="dashboardStore.favorite"
true-icon="mdi-star"
false-icon="mdi-star"
color="warning"
:value="props.name"
/>
<VTooltip
activator="parent"
location="top"
>
{{ $t('index.add_to_favorite') }}
</VTooltip>
</VListItemAction>
</template>
</VListItem>
</VList>
</VCard>
</template> </template>

View File

@ -0,0 +1,59 @@
<script setup lang="ts">
import { useThemeConfig } from '@core/composable/useThemeConfig';
import type { ThemeSwitcherTheme } from '@layouts/types';
import { onMounted, watch } from 'vue';
const props = defineProps<{
themes: ThemeSwitcherTheme[];
}>();
const { theme } = useThemeConfig();
const {
state: currentThemeName,
next: getNextThemeName,
index: currentThemeIndex,
} = useCycleList(
props.themes.map(t => t.name),
{ initialValue: theme.value }
);
const changeTheme = () => {
theme.value = getNextThemeName();
};
const changeMode = (val: 'dark' | 'light' | 'system') => {
let value = val;
if (theme.value === 'system' && window.matchMedia('(prefers-color-scheme: dark)').matches) {
value = 'dark';
}
if (value === 'dark') {
document.documentElement.classList.add('dark');
document.documentElement.classList.remove('light');
} else {
document.documentElement.classList.add('light');
document.documentElement.classList.remove('dark');
}
document.documentElement.setAttribute("data-theme", value);
};
// Update icon if theme is changed from other sources
watch(theme, (val: 'dark' | 'light' | 'system') => {
currentThemeName.value = val;
changeMode(val);
});
onMounted(() => {
if (currentThemeName.value) {
changeMode(currentThemeName.value);
}
});
</script>
<template>
<IconBtn @click="changeTheme">
<VIcon :icon="props.themes[currentThemeIndex].icon" />
<VTooltip activator="parent" open-delay="1000">
<span class="text-capitalize">{{ currentThemeName }}</span>
</VTooltip>
</IconBtn>
</template>

View File

@ -2,7 +2,8 @@
import { useThemeConfig } from '@/plugins/vuetify/@core/composable/useThemeConfig'; import { useThemeConfig } from '@/plugins/vuetify/@core/composable/useThemeConfig';
// Components // Components
import Footer from '@/layouts/components/Footer.vue'; // import Footer from '@/layouts/components/Footer.vue';
import newFooter from '@/layouts/components/newFooter.vue';
import NavbarThemeSwitcher from '@/layouts/components/NavbarThemeSwitcher.vue'; import NavbarThemeSwitcher from '@/layouts/components/NavbarThemeSwitcher.vue';
import UserProfile from '@/layouts/components/ChainProfile.vue'; import UserProfile from '@/layouts/components/ChainProfile.vue';
@ -79,7 +80,8 @@ blockchain.$subscribe((m, s) => {
<!-- 👉 Footer --> <!-- 👉 Footer -->
<template #footer> <template #footer>
<Footer /> <!-- <Footer /> -->
<newFooter />
</template> </template>
<!-- 👉 Customizer --> <!-- 👉 Customizer -->

View File

@ -1,6 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import type { ThemeSwitcherTheme } from '@layouts/types' import type { ThemeSwitcherTheme } from '@layouts/types'
import NewThemeSwitcher from '@/components/ThemeSwitcher.vue'
const themes: ThemeSwitcherTheme[] = [ const themes: ThemeSwitcherTheme[] = [
{ {
name: 'system', name: 'system',
@ -18,5 +18,8 @@ const themes: ThemeSwitcherTheme[] = [
</script> </script>
<template> <template>
<ThemeSwitcher :themes="themes" /> <div>
<NewThemeSwitcher :themes="themes"/>
<!-- <ThemeSwitcher :themes="themes" /> -->
</div>
</template> </template>

View File

@ -0,0 +1,26 @@
<template>
<footer class="footer items-center p-4 text-base">
<div class="items-center grid-flow-col">
&copy;
{{ new Date().getFullYear() }}
Made With
<img src="../../assets/images/heart.svg"/>
By
<a class="link link-info no-underline"
href="https://ping.pub"
target="_blank"
rel="noopener noreferrer"
>Ping.pub</a>
</div>
<div class="grid-flow-col gap-4 md:place-self-center md:justify-self-end hidden md:grid">
<a class="link link-info no-underline"
href="https://github.com/ping-pub/explorer/blob/master/LICENSE"
target="noopener noreferrer"
>License</a>
<a class="link link-info no-underline"
href="https://github.com/ping-pub/explorer"
target="noopener noreferrer"
>Github</a>
</div>
</footer>
</template>

View File

@ -10,10 +10,10 @@ dashboard.$subscribe((mutation, state) => {
localStorage.setItem('favorite', JSON.stringify(state.favorite)) localStorage.setItem('favorite', JSON.stringify(state.favorite))
}) })
const keywords = ref('') const keywords = ref('')
const chains = computed(()=> { const chains = computed(() => {
if(keywords.value) { if (keywords.value) {
return Object.values(dashboard.chains).filter( (x: ChainConfig)=>x.chainName.indexOf(keywords.value) > -1) return Object.values(dashboard.chains).filter((x: ChainConfig) => x.chainName.indexOf(keywords.value) > -1)
}else{ } else {
return Object.values(dashboard.chains) return Object.values(dashboard.chains)
} }
}) })
@ -21,33 +21,37 @@ const chain = useBlockchain()
</script> </script>
<template> <template>
<div class="d-flex flex-column justify-center"> <div class="">
<div class="d-flex justify-center align-center align-self-center p-1 b1"> <div class="flex items-center justify-center mb-6 mt-10">
<VImg src="/logo.svg" width="85" height="85"/> <div class="w-8 md:w-16 rounded-full mr-3">
<h1 class="text-primary text-h3 font-weight-bold d-none d-md-block ml-1"> <img src="/logo.svg" />
Ping Dashboard<VChip>Beta</VChip> </div>
<h1 class="text-primary text-3xl md:text-6xl font-bold mr-2">
Ping dashboard
</h1> </h1>
<div class="badge badge-info badge-outline mt-1 text-sm md:mt-8">Beta</div>
</div> </div>
<div class="d-flex flex-column align-center"> <div class="text-center text-base">
<p class="mb-1"> <p class="mb-1">
{{ $t('index.slogan') }} {{ $t('index.slogan') }}
</p> </p>
<h2 class="mb-9"> <h2 class="mb-6">
Cosmos Ecosystem Blockchains 🚀 Cosmos Ecosystem Blockchains 🚀
</h2> </h2>
</div> </div>
<VProgressLinear v-if="dashboard.status !== LoadingStatus.Loaded " indeterminate color="primary darken-2"/> <div v-if="dashboard.status !== LoadingStatus.Loaded" class="flex justify-center"><progress
<VTextField v-model="keywords" variant="underlined" :placeholder="$t('index.search_placeholder')" style="max-width: 300px;" app> class="progress progress-info w-80 h-1"></progress></div>
<VTextField v-model="keywords" variant="underlined" :placeholder="$t('index.search_placeholder')"
style="max-width: 300px;" app>
<template #append-inner> <template #append-inner>
{{ chains.length }}/{{ dashboard.length }} {{ chains.length }}/{{ dashboard.length }}
</template> </template>
</VTextField> </VTextField>
<VRow class="my-auto">
<VCol v-for="k in chains" md="3"> <div class="grid grid-cols-2 gap-4 mt-6 md:grid-cols-3 lg:grid-cols-4 2xl:grid-cols-5">
<VLazy min-height="40" min-width="200" transition="fade-transition"> <ChainSummary v-for="(chain, index) in chains" :key="index" :name="chain.chainName" />
<ChainSummary :name="k.chainName" /> </div>
</VLazy>
</VCol>
</VRow>
</div> </div>
</template> </template>

View File

@ -1,56 +1,48 @@
<script setup lang="ts"> <script setup lang="ts">
import type { Anchor } from 'vuetify/lib/components' import { Icon } from '@iconify/vue';
import type { I18nLanguage } from '@layouts/types' import type { Anchor } from 'vuetify/lib/components';
import type { I18nLanguage } from '@layouts/types';
const props = withDefaults(defineProps<Props>(), { const props = withDefaults(defineProps<Props>(), {
location: 'bottom end', location: 'bottom end',
}) });
defineEmits<{ defineEmits<{
(e: 'change', id: string): void (e: 'change', id: string): void;
}>() }>();
interface Props { interface Props {
languages: I18nLanguage[] languages: I18nLanguage[];
location?: Anchor location?: Anchor;
} }
const { locale } = useI18n({ useScope: 'global' }) const { locale } = useI18n({ useScope: 'global' });
watch(locale, val => { watch(locale, (val) => {
document.documentElement.setAttribute('lang', val as string) document.documentElement.setAttribute('lang', val as string);
}) });
const currentLang = ref([localStorage.getItem('lang')|| 'en']) const currentLang = ref([localStorage.getItem('lang') || 'en']);
</script> </script>
<template> <template>
<IconBtn> <div class="dropdown dropdown-end">
<VIcon icon="mdi-translate" /> <label tabindex="0" class="btn btn-ghost btn-circle btn-sm mx-1">
<Icon icon="mdi-translate" style="font-size: 24px" />
<!-- Menu --> </label>
<VMenu <ul
activator="parent" tabindex="0"
:location="props.location" class="dropdown-content menu p-2 shadow bg-base-100 rounded-box w-52"
offset="14px"
> >
<!-- List --> <li v-for="lang in props.languages" :key="lang.i18nLang">
<VList <a
v-model:selected="currentLang" @click="
active-color="primary" locale = lang.i18nLang;
min-width="175px" $emit('change', lang.i18nLang);
> "
<!-- List item --> >{{ lang.label }}</a
<VListItem
v-for="lang in props.languages"
:key="lang.i18nLang"
:value="lang.i18nLang"
@click="locale = lang.i18nLang; $emit('change', lang.i18nLang)"
> >
<!-- Language label --> </li>
<VListItemTitle>{{ lang.label }}</VListItemTitle> </ul>
</VListItem> </div>
</VList>
</VMenu>
</IconBtn>
</template> </template>

View File

@ -1,5 +1,6 @@
<script lang="ts"> <script lang="ts">
import type { PropType } from 'vue' import type { PropType} from 'vue'
import {h} from 'vue'
import { useLayouts } from '@layouts' import { useLayouts } from '@layouts'
import { VerticalNav } from '@layouts/components' import { VerticalNav } from '@layouts/components'
import type { VerticalNavItems } from '@layouts/types' import type { VerticalNavItems } from '@layouts/types'
@ -101,17 +102,20 @@ export default defineComponent({
) )
// 👉 Footer // 👉 Footer
const footer = h( // const footer = h(
'footer', // 'footer',
{ class: 'layout-footer' }, // { class: 'layout-footer' },
[ // [
h( // h(
'div', // 'div',
{ class: 'footer-content-container' }, // { class: 'footer-content-container' },
slots.footer?.(), // slots.footer?.(),
), // ),
], // ],
) // )
const footer = h('footer',{},slots.footer?.())
// 👉 Overlay // 👉 Overlay
const layoutOverlay = h( const layoutOverlay = h(

View File

@ -1,121 +1,133 @@
import { defineStore } from "pinia"; import { defineStore } from 'pinia';
import { useDashboard, type ChainConfig, type Endpoint, EndpointType } from "./useDashboard"; import {
import type { VerticalNavItems } from '@/@layouts/types' useDashboard,
import { useRouter } from "vue-router"; type ChainConfig,
import { CosmosRestClient } from "@/libs/client"; type Endpoint,
import { useBankStore, useBaseStore, useGovStore, useMintStore, useStakingStore } from "."; EndpointType,
import { useBlockModule } from "@/modules/[chain]/block/block"; } from './useDashboard';
import { DEFAULT } from "@/libs"; import type { VerticalNavItems } from '@/@layouts/types';
import { useRouter } from 'vue-router';
import { CosmosRestClient } from '@/libs/client';
import {
useBankStore,
useBaseStore,
useGovStore,
useMintStore,
useStakingStore,
} from '.';
import { useBlockModule } from '@/modules/[chain]/block/block';
import { DEFAULT } from '@/libs';
export const useBlockchain = defineStore("blockchain", { export const useBlockchain = defineStore('blockchain', {
state: () => { state: () => {
return { return {
status: {} as Record<string, string>, status: {} as Record<string, string>,
rest: '', rest: '',
chainName: "", chainName: '',
endpoint: {} as { endpoint: {} as {
type?: EndpointType, type?: EndpointType;
address: string address: string;
provider: string provider: string;
}, },
connErr: "" connErr: '',
} };
}, },
getters: { getters: {
current() : ChainConfig | undefined { current(): ChainConfig | undefined {
return this.dashboard.chains[this.chainName] return this.dashboard.chains[this.chainName];
}, },
logo(): string { logo(): string {
return this.current?.logo || '' return this.current?.logo || '';
}, },
dashboard() { dashboard() {
return useDashboard() return useDashboard();
}, },
computedChainMenu() { computedChainMenu() {
let currNavItem: VerticalNavItems = [];
let currNavItem: VerticalNavItems = [] const router = useRouter();
const routes = router?.getRoutes() || [];
const router = useRouter() if (this.current && routes) {
const routes = router?.getRoutes()||[] currNavItem = [
if(this.current && routes) { {
currNavItem = [{ title: this.current?.prettyName || this.chainName || '',
title: this.current?.prettyName || this.chainName || '', icon: { image: this.current.logo, size: '22' },
icon: {image: this.current.logo, size: '22'}, i18n: false,
i18n: false, children: routes
children: routes .filter((x) => x.meta.i18n)
.filter(x=> x.meta.i18n) .map((x) => ({
.map(x => ({ title: `module.${x.meta.i18n}`,
title: `module.${x.meta.i18n}`, to: { path: x.path.replace(':chain', this.chainName) },
to: {path: x.path.replace(':chain',this.chainName)}, icon: { icon: 'mdi-chevron-right', size: '22' },
icon: { icon: 'mdi-chevron-right', size: '22'}, i18n: true,
i18n: true }))
})) .sort((a, b) => a.to.path.length - b.to.path.length),
.sort((a,b)=>a.to.path.length - b.to.path.length) },
}] ];
} }
// compute favorite menu // compute favorite menu
const favNavItems: VerticalNavItems = [] const favNavItems: VerticalNavItems = [];
this.dashboard.favorite.forEach(name => { Object.keys(this.dashboard.favoriteMap).forEach((name) => {
const ch = this.dashboard.chains[name] const ch = this.dashboard.chains[name];
if(ch) { if (ch && this.dashboard.favoriteMap?.[name]) {
favNavItems.push({ favNavItems.push({
title: ch.prettyName || ch.chainName || name, title: ch.prettyName || ch.chainName || name,
to: { path: `/${ch.chainName || name}`}, to: { path: `/${ch.chainName || name}` },
icon: {image: ch.logo, size: '22'} icon: { image: ch.logo, size: '22' },
} ) });
} }
}) });
// combine all together // combine all together
return [...currNavItem, return [
{ heading: 'Ecosystem' }, ...currNavItem,
{ { heading: 'Ecosystem' },
title: 'Favorite', {
children: favNavItems, title: 'Favorite',
badgeContent: favNavItems.length, children: favNavItems,
badgeClass: 'bg-primary', badgeContent: favNavItems.length,
i18n: true, badgeClass: 'bg-primary',
icon: { icon: 'mdi-star', size: '22'} i18n: true,
}, icon: { icon: 'mdi-star', size: '22' },
{ },
title: 'All Blockchains', {
to: { path : '/'}, title: 'All Blockchains',
badgeContent: this.dashboard.length, to: { path: '/' },
badgeClass: 'bg-primary', badgeContent: this.dashboard.length,
i18n: true, badgeClass: 'bg-primary',
icon: { icon: 'mdi-grid', size: '22'} i18n: true,
} icon: { icon: 'mdi-grid', size: '22' },
] },
];
}, },
}, },
actions: { actions: {
async initial() { async initial() {
await this.randomSetupEndpoint() await this.randomSetupEndpoint();
await useStakingStore().init() await useStakingStore().init();
useBankStore().initial() useBankStore().initial();
useBaseStore().initial() useBaseStore().initial();
useGovStore().initial() useGovStore().initial();
useMintStore().initial() useMintStore().initial();
useBlockModule().initial() useBlockModule().initial();
}, },
async randomSetupEndpoint() { async randomSetupEndpoint() {
const all = this.current?.endpoints?.rest const all = this.current?.endpoints?.rest;
if(all) { if (all) {
const rn = Math.random() const rn = Math.random();
const endpoint = all[Math.floor(rn * all.length)] const endpoint = all[Math.floor(rn * all.length)];
await this.setRestEndpoint(endpoint) await this.setRestEndpoint(endpoint);
} }
},
async setRestEndpoint(endpoint: Endpoint) {
this.connErr = ''
this.endpoint = endpoint
this.rpc = new CosmosRestClient(endpoint.address, DEFAULT)
},
setCurrent(name: string) {
this.chainName = name
}, },
} async setRestEndpoint(endpoint: Endpoint) {
}) this.connErr = '';
this.endpoint = endpoint;
this.rpc = new CosmosRestClient(endpoint.address, DEFAULT);
},
setCurrent(name: string) {
this.chainName = name;
},
},
});

View File

@ -1,8 +1,7 @@
import { defineStore } from 'pinia';
import { defineStore } from "pinia"; import { get } from '../libs/http';
import { get } from '../libs/http' import type { Chain, Asset } from '@ping-pub/chain-registry-client/dist/types';
import type { Chain, Asset } from '@ping-pub/chain-registry-client/dist/types' import { useBlockchain } from './useBlockchain';
import { useBlockchain } from "./useBlockchain";
export enum EndpointType { export enum EndpointType {
rpc, rpc,
@ -12,253 +11,278 @@ export enum EndpointType {
} }
export interface Endpoint { export interface Endpoint {
type?: EndpointType, type?: EndpointType;
address: string, address: string;
provider: string provider: string;
} }
// Chain config structure of cosmos.directory // Chain config structure of cosmos.directory
export interface DirectoryChain { export interface DirectoryChain {
assets: Asset[], assets: Asset[];
bech32_prefix: string, bech32_prefix: string;
best_apis: { best_apis: {
rest: Endpoint[] rest: Endpoint[];
rpc: Endpoint[] rpc: Endpoint[];
}, };
chain_id: string, chain_id: string;
chain_name: string, chain_name: string;
pretty_name: string, pretty_name: string;
coingecko_id: string, coingecko_id: string;
cosmwasm_enabled: boolean, cosmwasm_enabled: boolean;
decimals: number, decimals: number;
denom: string, denom: string;
display: string, display: string;
explorers: { explorers:
name?: string | undefined; | {
kind?: string | undefined; name?: string | undefined;
url?: string | undefined; kind?: string | undefined;
tx_page?: string | undefined; url?: string | undefined;
account_page?: string | undefined; tx_page?: string | undefined;
}[] | undefined, account_page?: string | undefined;
height: number, }[]
image: string, | undefined;
name: string, height: number;
network_type: string, image: string;
symbol: string, name: string;
network_type: string;
symbol: string;
versions?: { versions?: {
application_version: string, application_version: string;
cosmos_sdk_version: string, cosmos_sdk_version: string;
tendermint_version: string, tendermint_version: string;
} };
} }
export interface ChainConfig { export interface ChainConfig {
chainName: string, chainName: string;
prettyName: string, prettyName: string;
bech32Prefix: string, bech32Prefix: string;
chainId: string, chainId: string;
assets: Asset[], assets: Asset[];
themeColor?: string, themeColor?: string;
endpoints: { endpoints: {
rest?: Endpoint[] rest?: Endpoint[];
rpc?: Endpoint[] rpc?: Endpoint[];
grpc?: Endpoint[] grpc?: Endpoint[];
}, };
logo: string, logo: string;
versions: { versions: {
application?: string, application?: string;
cosmosSdk?: string, cosmosSdk?: string;
tendermint?: string, tendermint?: string;
}, };
exponent: string, exponent: string;
excludes?: string, excludes?: string;
} }
export interface LocalConfig { export interface LocalConfig {
addr_prefix: string, addr_prefix: string;
alias: string, alias: string;
api: string[] | Endpoint[], api: string[] | Endpoint[];
assets: {base: string, coingecko_id: string, exponent: string, logo: string, symbol: string}[] assets: {
chain_name: string, base: string;
coin_type: string coingecko_id: string;
logo: string, exponent: string;
min_tx_fee: string, logo: string;
rpc: string[] | Endpoint[], symbol: string;
sdk_version: string, }[];
chain_name: string;
coin_type: string;
logo: string;
min_tx_fee: string;
rpc: string[] | Endpoint[];
sdk_version: string;
} }
function apiConverter(api: any[]){ function apiConverter(api: any[]) {
if(!api) return [] if (!api) return [];
const array = typeof api === 'string'? [api] : api const array = typeof api === 'string' ? [api] : api;
return array.map(x => { return array.map((x) => {
if(typeof x === 'string') { if (typeof x === 'string') {
const parts = String(x).split('.') const parts = String(x).split('.');
return { return {
address: x, address: x,
provider: parts.length >=2 ? parts[parts.length-2] : x provider: parts.length >= 2 ? parts[parts.length - 2] : x,
} };
}else{ } else {
return x as Endpoint return x as Endpoint;
} }
}) });
} }
export function fromLocal(lc: LocalConfig ): ChainConfig { export function fromLocal(lc: LocalConfig): ChainConfig {
const conf = {} as ChainConfig const conf = {} as ChainConfig;
conf.assets = lc.assets.map(x => ({ conf.assets = lc.assets.map((x) => ({
name: x.base, name: x.base,
base: x.base, base: x.base,
display: x.symbol, display: x.symbol,
symbol: x.symbol, symbol: x.symbol,
logo_URIs: { svg: x.logo }, logo_URIs: { svg: x.logo },
coingecko_id: x.coingecko_id, coingecko_id: x.coingecko_id,
exponent: x.exponent, exponent: x.exponent,
denom_units: [{denom: x.base, exponent: 0}, {denom: x.symbol.toLowerCase(), exponent: Number(x.exponent)}] denom_units: [
})) { denom: x.base, exponent: 0 },
conf.bech32Prefix = lc.addr_prefix { denom: x.symbol.toLowerCase(), exponent: Number(x.exponent) },
conf.chainName = lc.chain_name ],
conf.prettyName = lc.chain_name }));
conf.bech32Prefix = lc.addr_prefix;
conf.chainName = lc.chain_name;
conf.prettyName = lc.chain_name;
conf.endpoints = { conf.endpoints = {
rest: apiConverter(lc.api), rest: apiConverter(lc.api),
rpc: apiConverter(lc.rpc), rpc: apiConverter(lc.rpc),
} };
conf.logo = lc.logo conf.logo = lc.logo;
return conf return conf;
} }
export function fromDirectory(source: DirectoryChain): ChainConfig { export function fromDirectory(source: DirectoryChain): ChainConfig {
const conf = {} as ChainConfig const conf = {} as ChainConfig;
conf.assets = source.assets, (conf.assets = source.assets),
conf.bech32Prefix = source.bech32_prefix, (conf.bech32Prefix = source.bech32_prefix),
conf.chainId = source.chain_id, (conf.chainId = source.chain_id),
conf.chainName = source.chain_name, (conf.chainName = source.chain_name),
conf.prettyName = source.pretty_name, (conf.prettyName = source.pretty_name),
conf.versions = { (conf.versions = {
application: source.versions?.application_version || '', application: source.versions?.application_version || '',
cosmosSdk: source.versions?.cosmos_sdk_version || '', cosmosSdk: source.versions?.cosmos_sdk_version || '',
tendermint: source.versions?.tendermint_version || '', tendermint: source.versions?.tendermint_version || '',
}, }),
conf.logo = pathConvert(source.image) (conf.logo = pathConvert(source.image));
conf.endpoints = source.best_apis conf.endpoints = source.best_apis;
return conf return conf;
} }
function pathConvert(path: string | undefined) { function pathConvert(path: string | undefined) {
if(path) { if (path) {
path = path.replace('https://raw.githubusercontent.com/cosmos/chain-registry/master', 'https://registry.ping.pub') path = path.replace(
'https://raw.githubusercontent.com/cosmos/chain-registry/master',
'https://registry.ping.pub'
);
} }
return path || '' return path || '';
} }
export function getLogo(conf: { export function getLogo(
svg?: string, conf:
png?: string, | {
jpeg?: string, svg?: string;
} | undefined) { png?: string;
if(conf) { jpeg?: string;
return pathConvert(conf.svg || conf.png || conf.jpeg) }
| undefined
) {
if (conf) {
return pathConvert(conf.svg || conf.png || conf.jpeg);
} }
return undefined return undefined;
} }
function createChainFromDirectory(source: DirectoryChain) : Chain { function createChainFromDirectory(source: DirectoryChain): Chain {
const conf: Chain = {} as Chain; const conf: Chain = {} as Chain;
conf.apis = source.best_apis conf.apis = source.best_apis;
conf.bech32_prefix = source.bech32_prefix conf.bech32_prefix = source.bech32_prefix;
conf.chain_id = source.chain_id conf.chain_id = source.chain_id;
conf.chain_name = source.chain_name conf.chain_name = source.chain_name;
conf.explorers = source.explorers conf.explorers = source.explorers;
conf.pretty_name = source.pretty_name conf.pretty_name = source.pretty_name;
if(source.versions) { if (source.versions) {
conf.codebase = { conf.codebase = {
recommended_version: source.versions.application_version, recommended_version: source.versions.application_version,
cosmos_sdk_version: source.versions.cosmos_sdk_version, cosmos_sdk_version: source.versions.cosmos_sdk_version,
tendermint_version: source.versions.tendermint_version, tendermint_version: source.versions.tendermint_version,
} };
} }
if(source.image) { if (source.image) {
conf.logo_URIs = { conf.logo_URIs = {
svg: source.image svg: source.image,
} };
} }
return conf return conf;
} }
export enum LoadingStatus { export enum LoadingStatus {
Empty, Empty,
Loading, Loading,
Loaded, Loaded,
} }
export enum NetworkType { export enum NetworkType {
Mainnet, Mainnet,
Testnet, Testnet,
} }
export enum ConfigSource { export enum ConfigSource {
MainnetCosmosDirectory = "https://chains.cosmos.directory", MainnetCosmosDirectory = 'https://chains.cosmos.directory',
TestnetCosmosDirectory = "https://chains.testcosmos.directory", TestnetCosmosDirectory = 'https://chains.testcosmos.directory',
Local = 'local', Local = 'local',
} }
export const useDashboard = defineStore('dashboard', { export const useDashboard = defineStore('dashboard', {
state: () => { state: () => {
const fav = JSON.parse(localStorage.getItem('favorite') || '["cosmoshub", "osmosis"]') const fav = JSON.parse(
return { localStorage.getItem('favorite') || '["cosmoshub", "osmosis"]'
status: LoadingStatus.Empty, );
source: ConfigSource.MainnetCosmosDirectory, const favMap = JSON.parse(
networkType: NetworkType.Mainnet, localStorage.getItem('favoriteMap') ||
favorite: fav as string[], '{"cosmoshub":true, "osmosis":true}'
chains: {} as Record<string, ChainConfig>, );
} return {
status: LoadingStatus.Empty,
source: ConfigSource.MainnetCosmosDirectory,
networkType: NetworkType.Mainnet,
favorite: fav as string[],
favoriteMap: favMap as Record<string, boolean>,
chains: {} as Record<string, ChainConfig>,
};
}, },
getters: { getters: {
length() : number { length(): number {
return Object.keys(this.chains).length return Object.keys(this.chains).length;
} },
}, },
actions: { actions: {
initial() { initial() {
this.loadingFromLocal() this.loadingFromLocal();
// this.loadingFromRegistry() // this.loadingFromRegistry()
}, },
async loadingFromRegistry() { async loadingFromRegistry() {
if(this.status === LoadingStatus.Empty) { if (this.status === LoadingStatus.Empty) {
this.status = LoadingStatus.Loading this.status = LoadingStatus.Loading;
get(this.source).then((res)=> { get(this.source).then((res) => {
res.chains.forEach(( x: DirectoryChain ) => { res.chains.forEach((x: DirectoryChain) => {
this.chains[x.chain_name] = fromDirectory(x) this.chains[x.chain_name] = fromDirectory(x);
}); });
this.status = LoadingStatus.Loaded this.status = LoadingStatus.Loaded;
}) });
} }
}, },
async loadingFromLocal() { async loadingFromLocal() {
const source: Record<string, LocalConfig> = this.networkType === NetworkType.Mainnet const source: Record<string, LocalConfig> =
? import.meta.glob('../../chains/mainnet/*.json', {eager: true}) this.networkType === NetworkType.Mainnet
: import.meta.glob('../../chains/testnet/*.json', {eager: true}) ? import.meta.glob('../../chains/mainnet/*.json', { eager: true })
Object.values<LocalConfig>(source).forEach((x: LocalConfig) => { : import.meta.glob('../../chains/testnet/*.json', { eager: true });
this.chains[x.chain_name] = fromLocal(x) Object.values<LocalConfig>(source).forEach((x: LocalConfig) => {
}) this.chains[x.chain_name] = fromLocal(x);
this.setupDefault() });
this.status = LoadingStatus.Loaded this.setupDefault();
this.status = LoadingStatus.Loaded;
}, },
setupDefault() { setupDefault() {
if(this.length > 0) { if (this.length > 0) {
const blockchain = useBlockchain() const blockchain = useBlockchain();
for(let i=0; i < this.favorite.length; i++) { for (let i = 0; i < this.favorite.length; i++) {
if(!blockchain.chainName && this.chains[this.favorite[i]]) { if (!blockchain.chainName && this.chains[this.favorite[i]]) {
blockchain.setCurrent(this.favorite[i]) blockchain.setCurrent(this.favorite[i]);
} }
} }
if(!blockchain.chainName) { if (!blockchain.chainName) {
const [first] = Object.keys(this.chains) const [first] = Object.keys(this.chains);
blockchain.setCurrent(first) blockchain.setCurrent(first);
} }
} }
}, },
setConfigSource(newSource: ConfigSource) { setConfigSource(newSource: ConfigSource) {
this.source = newSource this.source = newSource;
this.initial() this.initial();
} },
} },
}) });

View File

@ -17,5 +17,28 @@ module.exports = {
}, },
}, },
}, },
plugins: [], plugins: [
require("daisyui")
],
daisyui: {
themes: [
{
myTheme: {
info: "#666CFF",
}
},
{
light: {
...require("daisyui/src/colors/themes")["[data-theme=light]"],
info: "#666CFF",
}
},
{
dark: {
...require("daisyui/src/colors/themes")["[data-theme=dark]"],
info: "#666CFF",
}
},
],
}
}; };

145
yarn.lock
View File

@ -2,6 +2,11 @@
# yarn lockfile v1 # yarn lockfile v1
"@alloc/quick-lru@^5.2.0":
version "5.2.0"
resolved "https://registry.yarnpkg.com/@alloc/quick-lru/-/quick-lru-5.2.0.tgz#7bf68b20c0a350f936915fcae06f58e32007ce30"
integrity sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==
"@ampproject/remapping@^2.1.0": "@ampproject/remapping@^2.1.0":
version "2.2.0" version "2.2.0"
resolved "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz" resolved "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz"
@ -3397,11 +3402,27 @@ color-name@1.1.3:
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz"
integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
color-name@^1.1.4, color-name@~1.1.4: color-name@^1.0.0, color-name@^1.1.4, color-name@~1.1.4:
version "1.1.4" version "1.1.4"
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
color-string@^1.9.0:
version "1.9.1"
resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.1.tgz#4467f9146f036f855b764dfb5bf8582bf342c7a4"
integrity sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==
dependencies:
color-name "^1.0.0"
simple-swizzle "^0.2.2"
color@^4.2:
version "4.2.3"
resolved "https://registry.yarnpkg.com/color/-/color-4.2.3.tgz#d781ecb5e57224ee43ea9627560107c0e0c6463a"
integrity sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==
dependencies:
color-convert "^2.0.1"
color-string "^1.9.0"
colord@^2.9.1: colord@^2.9.1:
version "2.9.3" version "2.9.3"
resolved "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz" resolved "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz"
@ -3527,6 +3548,14 @@ css-select@^4.1.3:
domutils "^2.8.0" domutils "^2.8.0"
nth-check "^2.0.1" nth-check "^2.0.1"
css-selector-tokenizer@^0.8.0:
version "0.8.0"
resolved "https://registry.yarnpkg.com/css-selector-tokenizer/-/css-selector-tokenizer-0.8.0.tgz#88267ef6238e64f2215ea2764b3e2cf498b845dd"
integrity sha512-Jd6Ig3/pe62/qe5SBPTN8h8LeUg/pT4lLgtavPf7updwwHpvFzxvOQBHYj2LZDMjUnBzgvIUSjRcf6oT5HzHFg==
dependencies:
cssesc "^3.0.0"
fastparse "^1.1.2"
css-tree@^1.1.2, css-tree@^1.1.3: css-tree@^1.1.2, css-tree@^1.1.3:
version "1.1.3" version "1.1.3"
resolved "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz" resolved "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz"
@ -3614,6 +3643,16 @@ d@1, d@^1.0.1:
es5-ext "^0.10.50" es5-ext "^0.10.50"
type "^1.0.1" type "^1.0.1"
daisyui@^2.51.6:
version "2.51.6"
resolved "https://registry.yarnpkg.com/daisyui/-/daisyui-2.51.6.tgz#c91f5a782f2e991b973dfe9d17d7e93cd973b372"
integrity sha512-JRqOKayuFCmWe4X4k6Qvx1y7V/VNao8U5eTSOhusOKIzCsYqf56+TCSe4d7zmqGE0V6JiLDYAT8JeoWUeRKFCw==
dependencies:
color "^4.2"
css-selector-tokenizer "^0.8.0"
postcss-js "^4.0.0"
tailwindcss "^3"
dargs@7.0.0: dargs@7.0.0:
version "7.0.0" version "7.0.0"
resolved "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz" resolved "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz"
@ -4277,6 +4316,11 @@ fast-levenshtein@^2.0.6:
resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz" resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz"
integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==
fastparse@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.2.tgz#91728c5a5942eced8531283c79441ee4122c35a9"
integrity sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==
fastq@^1.6.0: fastq@^1.6.0:
version "1.15.0" version "1.15.0"
resolved "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz" resolved "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz"
@ -4869,6 +4913,11 @@ is-arrayish@^0.2.1:
resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz" resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz"
integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==
is-arrayish@^0.3.1:
version "0.3.2"
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03"
integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==
is-bigint@^1.0.1: is-bigint@^1.0.1:
version "1.0.4" version "1.0.4"
resolved "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz" resolved "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz"
@ -4896,6 +4945,13 @@ is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7:
resolved "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz" resolved "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz"
integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==
is-core-module@^2.11.0:
version "2.12.0"
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.0.tgz#36ad62f6f73c8253fd6472517a12483cf03e7ec4"
integrity sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ==
dependencies:
has "^1.0.3"
is-core-module@^2.9.0: is-core-module@^2.9.0:
version "2.11.0" version "2.11.0"
resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz" resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz"
@ -5512,7 +5568,7 @@ jiti@^1.16.0, jiti@^1.16.2:
resolved "https://registry.npmjs.org/jiti/-/jiti-1.16.2.tgz" resolved "https://registry.npmjs.org/jiti/-/jiti-1.16.2.tgz"
integrity sha512-OKBOVWmU3FxDt/UH4zSwiKPuc1nihFZiOD722FuJlngvLz2glX1v2/TJIgoA4+mrpnXxHV6dSAoCvPcYQtoG5A== integrity sha512-OKBOVWmU3FxDt/UH4zSwiKPuc1nihFZiOD722FuJlngvLz2glX1v2/TJIgoA4+mrpnXxHV6dSAoCvPcYQtoG5A==
jiti@^1.17.2: jiti@^1.17.2, jiti@^1.18.2:
version "1.18.2" version "1.18.2"
resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.18.2.tgz#80c3ef3d486ebf2450d9335122b32d121f2a83cd" resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.18.2.tgz#80c3ef3d486ebf2450d9335122b32d121f2a83cd"
integrity sha512-QAdOptna2NYiSSpv0O/BwoHBSmz4YhpzJHyi+fnMRTXFjp7B8i/YG5Z8IfusxB1ufjcD2Sre1F3R+nX3fvy7gg== integrity sha512-QAdOptna2NYiSSpv0O/BwoHBSmz4YhpzJHyi+fnMRTXFjp7B8i/YG5Z8IfusxB1ufjcD2Sre1F3R+nX3fvy7gg==
@ -5633,7 +5689,7 @@ lilconfig@^2.0.3:
resolved "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.6.tgz" resolved "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.6.tgz"
integrity sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg== integrity sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==
lilconfig@^2.0.5, lilconfig@^2.0.6: lilconfig@^2.0.5, lilconfig@^2.0.6, lilconfig@^2.1.0:
version "2.1.0" version "2.1.0"
resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52" resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52"
integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ== integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==
@ -6414,7 +6470,16 @@ postcss-import@^14.1.0:
read-cache "^1.0.0" read-cache "^1.0.0"
resolve "^1.1.7" resolve "^1.1.7"
postcss-js@^4.0.0: postcss-import@^15.1.0:
version "15.1.0"
resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-15.1.0.tgz#41c64ed8cc0e23735a9698b3249ffdbf704adc70"
integrity sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==
dependencies:
postcss-value-parser "^4.0.0"
read-cache "^1.0.0"
resolve "^1.1.7"
postcss-js@^4.0.0, postcss-js@^4.0.1:
version "4.0.1" version "4.0.1"
resolved "https://registry.yarnpkg.com/postcss-js/-/postcss-js-4.0.1.tgz#61598186f3703bab052f1c4f7d805f3991bee9d2" resolved "https://registry.yarnpkg.com/postcss-js/-/postcss-js-4.0.1.tgz#61598186f3703bab052f1c4f7d805f3991bee9d2"
integrity sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw== integrity sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==
@ -6429,6 +6494,14 @@ postcss-load-config@^3.1.4:
lilconfig "^2.0.5" lilconfig "^2.0.5"
yaml "^1.10.2" yaml "^1.10.2"
postcss-load-config@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-4.0.1.tgz#152383f481c2758274404e4962743191d73875bd"
integrity sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==
dependencies:
lilconfig "^2.0.5"
yaml "^2.1.1"
postcss-merge-longhand@^5.1.7: postcss-merge-longhand@^5.1.7:
version "5.1.7" version "5.1.7"
resolved "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz" resolved "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz"
@ -6486,6 +6559,13 @@ postcss-nested@6.0.0:
dependencies: dependencies:
postcss-selector-parser "^6.0.10" postcss-selector-parser "^6.0.10"
postcss-nested@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-6.0.1.tgz#f83dc9846ca16d2f4fa864f16e9d9f7d0961662c"
integrity sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==
dependencies:
postcss-selector-parser "^6.0.11"
postcss-normalize-charset@^5.1.0: postcss-normalize-charset@^5.1.0:
version "5.1.0" version "5.1.0"
resolved "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz" resolved "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz"
@ -6879,6 +6959,15 @@ resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.14.2, resolve@^1.20.
path-parse "^1.0.7" path-parse "^1.0.7"
supports-preserve-symlinks-flag "^1.0.0" supports-preserve-symlinks-flag "^1.0.0"
resolve@^1.22.2:
version "1.22.2"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f"
integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==
dependencies:
is-core-module "^2.11.0"
path-parse "^1.0.7"
supports-preserve-symlinks-flag "^1.0.0"
restore-cursor@^2.0.0: restore-cursor@^2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz" resolved "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz"
@ -7039,6 +7128,13 @@ signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7:
resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz" resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz"
integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
simple-swizzle@^0.2.2:
version "0.2.2"
resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a"
integrity sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==
dependencies:
is-arrayish "^0.3.1"
sisteransi@^1.0.5: sisteransi@^1.0.5:
version "1.0.5" version "1.0.5"
resolved "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz" resolved "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz"
@ -7254,7 +7350,7 @@ stylehacks@^5.1.1:
browserslist "^4.21.4" browserslist "^4.21.4"
postcss-selector-parser "^6.0.4" postcss-selector-parser "^6.0.4"
sucrase@^3.29.0: sucrase@^3.29.0, sucrase@^3.32.0:
version "3.32.0" version "3.32.0"
resolved "https://registry.yarnpkg.com/sucrase/-/sucrase-3.32.0.tgz#c4a95e0f1e18b6847127258a75cf360bc568d4a7" resolved "https://registry.yarnpkg.com/sucrase/-/sucrase-3.32.0.tgz#c4a95e0f1e18b6847127258a75cf360bc568d4a7"
integrity sha512-ydQOU34rpSyj2TGyz4D2p8rbktIOZ8QY9s+DGLvFU1i5pWJE8vkpruCjGCMHsdXwnD7JDcS+noSwM/a7zyNFDQ== integrity sha512-ydQOU34rpSyj2TGyz4D2p8rbktIOZ8QY9s+DGLvFU1i5pWJE8vkpruCjGCMHsdXwnD7JDcS+noSwM/a7zyNFDQ==
@ -7376,6 +7472,35 @@ symbol-observable@^2.0.3:
resolved "https://registry.npmjs.org/symbol-observable/-/symbol-observable-2.0.3.tgz" resolved "https://registry.npmjs.org/symbol-observable/-/symbol-observable-2.0.3.tgz"
integrity sha512-sQV7phh2WCYAn81oAkakC5qjq2Ml0g8ozqz03wOGnx9dDlG1de6yrF+0RAzSJD8fPUow3PTSMf2SAbOGxb93BA== integrity sha512-sQV7phh2WCYAn81oAkakC5qjq2Ml0g8ozqz03wOGnx9dDlG1de6yrF+0RAzSJD8fPUow3PTSMf2SAbOGxb93BA==
tailwindcss@^3:
version "3.3.2"
resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.3.2.tgz#2f9e35d715fdf0bbf674d90147a0684d7054a2d3"
integrity sha512-9jPkMiIBXvPc2KywkraqsUfbfj+dHDb+JPWtSJa9MLFdrPyazI7q6WX2sUrm7R9eVR7qqv3Pas7EvQFzxKnI6w==
dependencies:
"@alloc/quick-lru" "^5.2.0"
arg "^5.0.2"
chokidar "^3.5.3"
didyoumean "^1.2.2"
dlv "^1.1.3"
fast-glob "^3.2.12"
glob-parent "^6.0.2"
is-glob "^4.0.3"
jiti "^1.18.2"
lilconfig "^2.1.0"
micromatch "^4.0.5"
normalize-path "^3.0.0"
object-hash "^3.0.0"
picocolors "^1.0.0"
postcss "^8.4.23"
postcss-import "^15.1.0"
postcss-js "^4.0.1"
postcss-load-config "^4.0.1"
postcss-nested "^6.0.1"
postcss-selector-parser "^6.0.11"
postcss-value-parser "^4.2.0"
resolve "^1.22.2"
sucrase "^3.32.0"
tailwindcss@^3.3.1: tailwindcss@^3.3.1:
version "3.3.1" version "3.3.1"
resolved "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.1.tgz#b6662fab6a9b704779e48d083a9fef5a81d2b81e" resolved "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.1.tgz#b6662fab6a9b704779e48d083a9fef5a81d2b81e"
@ -7437,6 +7562,11 @@ text-table@^0.2.0:
resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz" resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz"
integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==
theme-change@^2.5.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/theme-change/-/theme-change-2.5.0.tgz#d3b064af9c4cd01ab16ce0a4ecb251c827a50e68"
integrity sha512-B/UdsgdHAGhSKHTAQnxg/etN0RaMDpehuJmZIjLMDVJ6DGIliRHGD6pODi1CXLQAN9GV0GSyB3G6yCuK05PkPQ==
thenify-all@^1.0.0: thenify-all@^1.0.0:
version "1.6.0" version "1.6.0"
resolved "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz" resolved "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz"
@ -8046,6 +8176,11 @@ yaml@^1.10.0, yaml@^1.10.2:
resolved "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz" resolved "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz"
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
yaml@^2.1.1:
version "2.2.2"
resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.2.2.tgz#ec551ef37326e6d42872dad1970300f8eb83a073"
integrity sha512-CBKFWExMn46Foo4cldiChEzn7S7SRV+wqiluAb6xmueD/fGyRHIhX8m14vVGgeFWjN540nKCNVj6P21eQjgTuA==
yaml@^2.1.3: yaml@^2.1.3:
version "2.2.1" version "2.2.1"
resolved "https://registry.npmjs.org/yaml/-/yaml-2.2.1.tgz" resolved "https://registry.npmjs.org/yaml/-/yaml-2.2.1.tgz"