Resolve "WIP: UTXO Selection and Storage"
This commit is contained in:
@@ -0,0 +1,215 @@
|
||||
import { defineConfig } from 'vitepress';
|
||||
import typedocSidebar from '../api/typedoc-sidebar.json';
|
||||
|
||||
// Special cases map for acronyms and exceptions
|
||||
const SPECIAL_CASES = {
|
||||
hd: 'HD',
|
||||
indexeddb: 'IndexedDB',
|
||||
inmemory: 'InMemory',
|
||||
json: 'JSON',
|
||||
p2p: 'P2P',
|
||||
p2pkh: 'P2PKH',
|
||||
p2sh: 'P2SH',
|
||||
p2sh20: 'P2SH20',
|
||||
p2sh32: 'P2SH32',
|
||||
sse: 'SSE',
|
||||
utxo: 'UTXO',
|
||||
};
|
||||
|
||||
function toPascalCase(str: string) {
|
||||
// Handle special cases first
|
||||
const lowerStr = str.toLowerCase();
|
||||
|
||||
if (lowerStr.startsWith('@')) {
|
||||
return str;
|
||||
}
|
||||
|
||||
// Split by common delimiters (hyphen, space, underscore)
|
||||
return str
|
||||
.split(/[-\s_]/)
|
||||
.map((word) => {
|
||||
if (word.length === 0) return '';
|
||||
|
||||
if (SPECIAL_CASES[word]) {
|
||||
return SPECIAL_CASES[word];
|
||||
}
|
||||
|
||||
// Capitalize first letter, lowercase rest
|
||||
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
|
||||
})
|
||||
.join('');
|
||||
}
|
||||
|
||||
function convertNavToPascalCase(nav: Array<any>) {
|
||||
return nav.map((item) => {
|
||||
const result = { ...item };
|
||||
|
||||
// Convert the text field
|
||||
if (result.text) {
|
||||
// If there was a @ prefix, preserve it
|
||||
result.text = item.text.startsWith('@')
|
||||
? result.text
|
||||
: toPascalCase(result.text);
|
||||
}
|
||||
|
||||
// Recursively process nested items
|
||||
if (result.items && Array.isArray(result.items)) {
|
||||
result.items = convertNavToPascalCase(result.items);
|
||||
}
|
||||
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
// https://vitepress.dev/reference/site-config
|
||||
export default defineConfig({
|
||||
outDir: '../dist',
|
||||
title: 'Stack',
|
||||
description:
|
||||
'XO Stack: Building smart applications on the Bitcoin Cash Network',
|
||||
themeConfig: {
|
||||
// Set the logo
|
||||
logo: {
|
||||
light: '/logo-light.svg',
|
||||
dark: '/logo-dark.svg',
|
||||
},
|
||||
|
||||
// Enable search functionality.
|
||||
// TODO: Re-enable once we release documentation.
|
||||
/*
|
||||
search: {
|
||||
provider: 'local',
|
||||
},
|
||||
*/
|
||||
|
||||
// https://vitepress.dev/reference/default-theme-config
|
||||
nav: [
|
||||
{ text: 'Home', link: '/' },
|
||||
// TODO: Re-enable once we release documentation
|
||||
// { text: 'Documentation', link: '/quick-start' },
|
||||
{ text: 'Tools', link: '/tools/primitives' },
|
||||
],
|
||||
|
||||
sidebar: {
|
||||
// Default Side Menu.
|
||||
'/': [
|
||||
{
|
||||
text: 'Guide',
|
||||
items: [
|
||||
{ text: 'Quick Start', link: '/quick-start' },
|
||||
{ text: 'Best Practices', link: '/api-examples' },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'Frameworks',
|
||||
items: [
|
||||
{ text: 'Vue', link: '/frameworks/vue' },
|
||||
{ text: 'React', link: '/frameworks/react' },
|
||||
{ text: 'Svelte', link: '/frameworks/svelte' },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'API',
|
||||
items: convertNavToPascalCase(typedocSidebar),
|
||||
},
|
||||
],
|
||||
// Side-menu for all routes under /tools/
|
||||
'/tools/': [
|
||||
{
|
||||
text: 'XO Tools',
|
||||
items: [
|
||||
{
|
||||
text: 'Primitives',
|
||||
link: '/tools/primitives',
|
||||
collapsed: false,
|
||||
items: [
|
||||
{ text: 'Address', link: '/tools/primitives#address' },
|
||||
{
|
||||
text: 'Block Header',
|
||||
link: '/tools/primitives#block-header',
|
||||
},
|
||||
{ text: 'Bytes', link: '/tools/primitives#bytes' },
|
||||
{ text: 'Hasher', link: '/tools/primitives#hasher' },
|
||||
{
|
||||
text: 'HD Private Node',
|
||||
link: '/tools/primitives#hd-private-node',
|
||||
},
|
||||
{
|
||||
text: 'HD Public Node',
|
||||
link: '/tools/primitives#hd-public-node',
|
||||
},
|
||||
{
|
||||
text: 'Mnemonic',
|
||||
link: '/tools/primitives#mnemonic',
|
||||
},
|
||||
{
|
||||
text: 'Private Key',
|
||||
link: '/tools/primitives#private-key',
|
||||
},
|
||||
{
|
||||
text: 'Public Key',
|
||||
link: '/tools/primitives#public-key',
|
||||
},
|
||||
{
|
||||
text: 'Satoshis',
|
||||
link: '/tools/primitives#satoshis',
|
||||
},
|
||||
{
|
||||
text: 'Script',
|
||||
link: '/tools/primitives#script',
|
||||
},
|
||||
{
|
||||
text: 'Transaction',
|
||||
link: '/tools/primitives#transaction',
|
||||
},
|
||||
],
|
||||
},
|
||||
/*
|
||||
{
|
||||
text: 'Stack',
|
||||
collapsed: false,
|
||||
items: [
|
||||
{
|
||||
text: 'Blockchain',
|
||||
items: [{ text: 'Blockchain Electrum' }],
|
||||
},
|
||||
],
|
||||
},
|
||||
*/
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
/*
|
||||
|
||||
*/
|
||||
|
||||
socialLinks: [
|
||||
{ icon: 'github', link: 'https://gitlab.com/GeneralProtocols/xo/stack' },
|
||||
],
|
||||
|
||||
// This is the outline on the right-hand side of the page.
|
||||
outline: {
|
||||
level: [2, 4],
|
||||
label: 'On this page',
|
||||
},
|
||||
},
|
||||
|
||||
head: [['link', { rel: 'icon', href: '/favicon.png' }]],
|
||||
|
||||
// Set the dev and build targets to "esnext"
|
||||
// NOTE: We do this so that we can support top-level-await.
|
||||
vite: {
|
||||
esbuild: {
|
||||
target: 'esnext',
|
||||
},
|
||||
build: {
|
||||
target: 'esnext',
|
||||
},
|
||||
optimizeDeps: {
|
||||
esbuildOptions: {
|
||||
target: 'esnext',
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,54 @@
|
||||
<!-- .vitepress/theme/MyLayout.vue -->
|
||||
<script setup>
|
||||
import DefaultTheme from 'vitepress/theme'
|
||||
|
||||
const { Layout } = DefaultTheme
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Layout>
|
||||
<!-- Override the home-hero-image slot with the Stack, BCH, and Apps icons along with gradient arrows -->
|
||||
<template #home-hero-image>
|
||||
<div class="icon-container">
|
||||
|
||||
<!-- Stack Icon -->
|
||||
<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" class="stack-icon">
|
||||
<path d="m2.394 15.759s7.554 4.246 9.09 5.109c.165.093.333.132.492.132.178 0 .344-.049.484-.127 1.546-.863 9.155-5.113 9.155-5.113.246-.138.385-.393.385-.656 0-.566-.614-.934-1.116-.654 0 0-7.052 3.958-8.539 4.77-.211.115-.444.161-.722.006-1.649-.928-8.494-4.775-8.494-4.775-.502-.282-1.117.085-1.117.653 0 .262.137.517.382.655zm0-3.113s7.554 4.246 9.09 5.109c.165.093.333.132.492.132.178 0 .344-.049.484-.127 1.546-.863 9.155-5.113 9.155-5.113.246-.138.385-.393.385-.656 0-.566-.614-.934-1.116-.654 0 0-7.052 3.958-8.539 4.77-.211.115-.444.161-.722.006-1.649-.928-8.494-4.775-8.494-4.775-.502-.282-1.117.085-1.117.653 0 .262.137.517.382.655zm10.271-9.455c-.246-.128-.471-.191-.692-.191-.223 0-.443.065-.675.191l-8.884 5.005c-.276.183-.414.444-.414.698 0 .256.139.505.414.664l8.884 5.006c.221.133.447.203.678.203.223 0 .452-.065.689-.203l8.884-5.006c.295-.166.451-.421.451-.68 0-.25-.145-.503-.451-.682z" fill-rule="nonzero"/>
|
||||
</svg>
|
||||
|
||||
|
||||
<!-- Right Arrow with gradient -->
|
||||
<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" fill="url(#gradient)" fill-rule="evenodd" clip-rule="evenodd" class="right-arrow" stroke="url(#gradient)" stroke-width="2">
|
||||
<defs>
|
||||
<linearGradient id="gradient" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#5271ff;stop-opacity:1" />
|
||||
<stop offset="100%" style="stop-color:#38b6ff;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<path d="M4 .755l14.374 11.245-14.374 11.219.619.781 15.381-12-15.391-12-.609.755z"/>
|
||||
</svg>
|
||||
|
||||
<!-- BCH Icon -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 24 24" fill="currentColor" class="bch-icon">
|
||||
<path d="M12 2c5.514 0 10 4.486 10 10s-4.486 10-10 10-10-4.486-10-10 4.486-10 10-10zm0-2c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm-.5 12.497v2.503c1.984 0 3.344-.188 3.344-1.258 0-1.148-1.469-1.245-3.344-1.245zm2.789-2.247c0-1-1.039-1.25-2.789-1.25v2.5c1.105 0 2.789-.078 2.789-1.25zm-2.289-7.25c-4.971 0-9 4.029-9 9s4.029 9 9 9 9-4.029 9-9-4.029-9-9-9zm1 13.5v1.5h-1v-1.511h-.5v1.511h-1v-1.511h-2.484l.25-1.489h.539c.442 0 .695-.425.695-.854v-4.444c0-.416-.242-.702-.683-.702h-.817v-1.5h2.5v-1.5h1v1.5h.5v-1.5h1v1.526c2.158.073 3.012.891 3.257 1.812.29 1.09-.429 2.005-1.046 2.228.75.192 1.789.746 1.789 2.026 0 1.741-1.344 2.908-4 2.908z"/>
|
||||
</svg>
|
||||
|
||||
<!-- Left Arrow with gradient -->
|
||||
<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" fill="url(#gradient)" fill-rule="evenodd" clip-rule="evenodd" class="left-arrow" stroke="url(#gradient)" stroke-width="2">
|
||||
<defs>
|
||||
<linearGradient id="gradient" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#5271ff;stop-opacity:1" />
|
||||
<stop offset="100%" style="stop-color:#38b6ff;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<path d="M20 .755l-14.374 11.245 14.374 11.219-.619.781-15.381-12 15.391-12 .609.755z"/>
|
||||
</svg>
|
||||
|
||||
<!-- Apps Icon -->
|
||||
<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" class="apps-icon">
|
||||
<path d="m21 4c0-.478-.379-1-1-1h-16c-.62 0-1 .519-1 1v16c0 .621.52 1 1 1h16c.478 0 1-.379 1-1zm-16.5.5h15v15h-15zm6.75 9.25v3.25c0 .53-.47 1-1 1h-3.25c-.53 0-1-.47-1-1v-3.25c0-.53.47-1 1-1h3.25c.53 0 1 .47 1 1zm0-6.75v3.25c0 .53-.47 1-1 1h-3.25c-.53 0-1-.47-1-1v-3.25c0-.53.47-1 1-1h3.25c.53 0 1 .47 1 1zm6.75 0v3.25c0 .53-.47 1-1 1h-3.25c-.53 0-1-.47-1-1v-3.25c0-.53.47-1 1-1h3.25c.53 0 1 .47 1 1z" fill-rule="nonzero"/>
|
||||
</svg>
|
||||
</div>
|
||||
</template>
|
||||
</Layout>
|
||||
</template>
|
||||
@@ -0,0 +1,107 @@
|
||||
<template>
|
||||
<Tooltip :show="showTooltip && !isCopied">
|
||||
<button
|
||||
class="copy-button"
|
||||
:class="{ 'copied': isCopied }"
|
||||
@click="handleCopy"
|
||||
@mouseenter="showTooltip = true"
|
||||
@mouseleave="showTooltip = false"
|
||||
>
|
||||
<Transition mode="out-in">
|
||||
<img v-if="!isCopied" key="icon" src="../icons/copy.svg" alt="Copy" class="copy-icon" />
|
||||
<span v-else key="text" class="copied-text">Copied!</span>
|
||||
</Transition>
|
||||
</button>
|
||||
<template #content>Copy</template>
|
||||
</Tooltip>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import Tooltip from './Tooltip.vue';
|
||||
|
||||
type Props = {
|
||||
content: string;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
content: ''
|
||||
});
|
||||
|
||||
const isCopied = ref(false);
|
||||
const showTooltip = ref(false);
|
||||
|
||||
const handleCopy = async () => {
|
||||
try {
|
||||
await navigator.clipboard.writeText(props.content);
|
||||
isCopied.value = true;
|
||||
showTooltip.value = false;
|
||||
setTimeout(() => {
|
||||
isCopied.value = false;
|
||||
}, 2000);
|
||||
} catch (err) {
|
||||
console.error('Failed to copy text: ', err);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.tooltip-container {
|
||||
position: absolute !important;
|
||||
top: 5px;
|
||||
right: 5px;
|
||||
}
|
||||
|
||||
.copy-button {
|
||||
position: relative;
|
||||
padding: 5px 10px;
|
||||
font-size: 1rem;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
background: var(--vp-home-hero-name-background);
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
text-transform: uppercase;
|
||||
box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.1);
|
||||
opacity: 0.9;
|
||||
width: 2.2em;
|
||||
height: 2.2em;
|
||||
overflow: hidden;
|
||||
transition: width 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.copy-button:hover {
|
||||
opacity: 1;
|
||||
background: var(--primary);
|
||||
}
|
||||
|
||||
.copy-button.copied {
|
||||
width: 70px;
|
||||
}
|
||||
|
||||
.copy-icon {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
filter: invert(1);
|
||||
}
|
||||
|
||||
.copied-text {
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.v-enter-active,
|
||||
.v-leave-active {
|
||||
transition: opacity 0.2s ease;
|
||||
}
|
||||
|
||||
.v-enter-from,
|
||||
.v-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,74 @@
|
||||
<template>
|
||||
<div class="labelled-section-container">
|
||||
<div class="labelled-section">
|
||||
{{ content || ' ' }}
|
||||
</div>
|
||||
<label class="section-label" :class="{ 'is-floating': hasContent }">
|
||||
{{ label }}
|
||||
</label>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
|
||||
export interface Props {
|
||||
content?: string
|
||||
label?: string
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
content: '',
|
||||
label: ''
|
||||
})
|
||||
|
||||
const hasContent = computed(() => props.content.length > 0)
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.labelled-section-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.labelled-section {
|
||||
box-sizing: content-box;
|
||||
padding: 10px 8px;
|
||||
font-size: 1rem;
|
||||
border: 1px dashed #ccc;
|
||||
border-radius: 4px;
|
||||
background: var(--vp-c-bg);
|
||||
line-height: 1.5;
|
||||
min-height: calc(1.5em);
|
||||
font-family: monospace;
|
||||
max-width: 100%;
|
||||
text-wrap: wrap;
|
||||
overflow-wrap: anywhere;
|
||||
white-space: pre-wrap;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.section-label {
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
background: var(--vp-c-bg);
|
||||
padding: 0 4px;
|
||||
font-size: 1em;
|
||||
font-family: monospace;
|
||||
transition: all 0.2s ease;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.section-label.is-floating {
|
||||
top: 0;
|
||||
font-size: 0.8em;
|
||||
transform: translateY(-50%);
|
||||
font-style: normal;
|
||||
color: var(--vp-c-text-2);
|
||||
opacity: 1.0;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,238 @@
|
||||
<template>
|
||||
<div class="input-wrapper">
|
||||
<h2>Input</h2>
|
||||
|
||||
<div class="form-group-row" :class="{ 'extended': state.selectedFromFunction?.extendedInput }">
|
||||
<div class="form-group select-group">
|
||||
<label for="functionSelect">Select Function</label>
|
||||
<select v-model="state.selectedFromFunction">
|
||||
<option v-for="fromFunction of props.fromFunctions" :key="fromFunction.label" :value="fromFunction">{{ fromFunction.label }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group input-group" :class="{ 'extended': state.selectedFromFunction?.extendedInput }">
|
||||
<template v-for="(_input, i) of state.selectedFromFunction.inputs" :key="i">
|
||||
<label for="field">{{ state.selectedFromFunction.inputs[i] }}</label>
|
||||
<div>
|
||||
<textarea
|
||||
v-if="state.selectedFromFunction?.extendedInput"
|
||||
v-model="state.selectedFromFunction.models[i]"
|
||||
class="extended-input"
|
||||
@input="autoGrow($event.target)"
|
||||
></textarea>
|
||||
<input
|
||||
v-else
|
||||
type="text"
|
||||
v-model="state.selectedFromFunction.models[i]"
|
||||
/>
|
||||
<div v-if="state.error" class="text-error">{{ state.error }}</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<button type="submit" class="gradient-button" @click="() => setPrimitive(() => state.selectedFromFunction.callback(state.selectedFromFunction.models))">Create Output</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section output-section">
|
||||
<h2>Output</h2>
|
||||
|
||||
<template v-for="(toFunction, i) of toFunctions" :key="i">
|
||||
<div>
|
||||
<div class="output-box-container">
|
||||
<LabelledSection :label="toFunction.label" :content="getPrimitive(() => toFunction.callback(state.primitive))" />
|
||||
<CopyButton :content="getPrimitive(() => toFunction.callback(state.primitive))" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-if="state.methods.length && state.primitive">
|
||||
<h2>Methods</h2>
|
||||
|
||||
<div class="form-group-row" :class="{ 'extended': state.selectedMethod?.extendedInput }">
|
||||
<div class="form-group select-group">
|
||||
<label for="functionSelect">Select Function</label>
|
||||
<select v-model="state.selectedMethod">
|
||||
<option v-for="method of props.methods" :key="method.label" :value="method">{{ method.label }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group input-group" :class="{ 'extended': state.selectedMethod?.extendedInput }">
|
||||
<template v-for="(_input, i) of state.selectedMethod.inputs" :key="i">
|
||||
<label for="field">{{ state.selectedMethod.inputs[i] }}</label>
|
||||
<div>
|
||||
<textarea
|
||||
v-if="state.selectedMethod?.extendedInput"
|
||||
v-model="state.selectedMethod.models[i]"
|
||||
class="extended-input"
|
||||
@input="autoGrow($event.target)"
|
||||
></textarea>
|
||||
<input
|
||||
v-else
|
||||
type="text"
|
||||
v-model="state.selectedMethod.models[i]"
|
||||
/>
|
||||
<div v-if="state.error" class="text-error">{{ state.error }}</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<button type="submit" class="gradient-button" @click="() => executeMethod(state.selectedMethod.callback(state.primitive, state.selectedMethod.models))">Execute Method</button>
|
||||
</div>
|
||||
<!-- Result -->
|
||||
<div>
|
||||
<div class="output-box-container">
|
||||
<LabelledSection label="Result" :content="state.selectedMethod.result" />
|
||||
<CopyButton :content="state.selectedMethod.result" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup generic="Primitive" lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import type { Ref } from 'vue';
|
||||
|
||||
import LabelledSection from './LabelledSection.vue';
|
||||
import CopyButton from './CopyButton.vue';
|
||||
|
||||
export interface FromFunction<Primitive> {
|
||||
// The label of the function
|
||||
label: string,
|
||||
|
||||
// Array of inputs that the function takes
|
||||
inputs: Array<string>,
|
||||
|
||||
// Array of models that the input stores its value in
|
||||
models: Array<any>,
|
||||
|
||||
// Function that takes the models and returns the primitive
|
||||
callback: (value: Array<any>) => Primitive,
|
||||
|
||||
// Whether the input is extended onto a new line
|
||||
extendedInput?: boolean
|
||||
}
|
||||
|
||||
export interface ToFunction<Primitive> {
|
||||
label: string;
|
||||
callback: (primitive: Primitive) => string;
|
||||
result?: string;
|
||||
}
|
||||
|
||||
export interface Method<Primitive> {
|
||||
// The label of the function
|
||||
label: string;
|
||||
|
||||
// Array of inputs that the function takes
|
||||
inputs: Array<string>,
|
||||
|
||||
// Array of models that the input stores its value in
|
||||
models: Array<any>,
|
||||
|
||||
// Result of method execution,
|
||||
result?: string;
|
||||
|
||||
// Function that takes the models and returns the primitive
|
||||
callback: (primitive: Primitive, value: Array<any>) => string;
|
||||
|
||||
// Whether the input is extended onto a new line
|
||||
extendedInput?: boolean
|
||||
}
|
||||
|
||||
export interface Props<Primitive> {
|
||||
fromFunctions: Array<FromFunction<Primitive>>,
|
||||
toFunctions: Array<ToFunction<Primitive>>,
|
||||
methods?: Array<Method<Primitive>>,
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props<Primitive>>(), {
|
||||
fromFunctions: () => [],
|
||||
toFunctions: () => [],
|
||||
methods: () => [],
|
||||
});
|
||||
|
||||
const state: Ref<{
|
||||
fromFunctions: Array<FromFunction<Primitive>>,
|
||||
toFunctions: Array<ToFunction<Primitive>>,
|
||||
methods: Array<Method<Primitive>>,
|
||||
|
||||
// Selected In Function
|
||||
selectedFromFunction: FromFunction<Primitive>,
|
||||
|
||||
// Selected Method
|
||||
selectedMethod?: Method<Primitive>,
|
||||
|
||||
// The Primitive.
|
||||
primitive?: Primitive,
|
||||
|
||||
// Error to display if an invalid input was given.
|
||||
error?: string;
|
||||
}> = ref({
|
||||
// From functions, to functions and methods.
|
||||
fromFunctions: [ ...props.fromFunctions ],
|
||||
toFunctions: [ ...props.toFunctions ],
|
||||
methods: [ ...props.methods ],
|
||||
|
||||
// The selected function.
|
||||
selectedFromFunction: props.fromFunctions[0],
|
||||
|
||||
// The selected method.
|
||||
selectedMethod: props.methods[0] || undefined,
|
||||
|
||||
// The Primitive.
|
||||
primitive: undefined,
|
||||
})
|
||||
|
||||
async function setPrimitive(functionToExecute: () => Primitive | Promise<Primitive>): void {
|
||||
try {
|
||||
state.value.primitive = await functionToExecute();
|
||||
state.value.error = undefined;
|
||||
|
||||
state.value.toFunctions.forEach((wrappedMethod, i) => {
|
||||
state.value.toFunctions[i].result = wrappedMethod.callback(state.value.primitive)
|
||||
});
|
||||
} catch(error: any) {
|
||||
state.value.error = `${error}`;
|
||||
}
|
||||
}
|
||||
|
||||
function getPrimitive(functionToExecute: () => string): string {
|
||||
try {
|
||||
if(!state.value.primitive) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return functionToExecute();
|
||||
} catch(error: any) {
|
||||
return error.message;
|
||||
}
|
||||
}
|
||||
|
||||
async function executeMethod(wrappedMethod: () => string | Promise<string>): string {
|
||||
try {
|
||||
if(!state.value.primitive) {
|
||||
return '';
|
||||
}
|
||||
|
||||
state.value.selectedMethod.result = await wrappedMethod;
|
||||
} catch(error: any) {
|
||||
return error.message;
|
||||
}
|
||||
};
|
||||
|
||||
// Select the first "from" function.
|
||||
state.value.selectedFromFunction = state.value.fromFunctions[0];
|
||||
|
||||
const autoGrow = (element: HTMLTextAreaElement) => {
|
||||
element.style.height = 'auto'
|
||||
element.style.height = `${Math.min(element.scrollHeight, 300)}px`
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.text-error {
|
||||
color: #f46666;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,76 @@
|
||||
<template>
|
||||
<div class="tooltip-container">
|
||||
<slot></slot>
|
||||
<Transition>
|
||||
<div v-if="show" class="tooltip" :class="position">
|
||||
<slot name="content"></slot>
|
||||
</div>
|
||||
</Transition>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
type Props = {
|
||||
show: boolean;
|
||||
position?: 'top' | 'bottom' | 'left' | 'right';
|
||||
}
|
||||
|
||||
withDefaults(defineProps<Props>(), {
|
||||
position: 'top',
|
||||
show: false
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.tooltip-container {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.tooltip {
|
||||
position: absolute;
|
||||
background: var(--vp-c-text-1);
|
||||
color: var(--vp-c-bg);
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
font-size: 0.8rem;
|
||||
white-space: nowrap;
|
||||
pointer-events: none;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.tooltip.top {
|
||||
bottom: 100%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%) translateY(-6px);
|
||||
}
|
||||
|
||||
.tooltip.bottom {
|
||||
top: 100%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%) translateY(6px);
|
||||
}
|
||||
|
||||
.tooltip.left {
|
||||
right: 100%;
|
||||
top: 50%;
|
||||
transform: translateY(-50%) translateX(-6px);
|
||||
}
|
||||
|
||||
.tooltip.right {
|
||||
left: 100%;
|
||||
top: 50%;
|
||||
transform: translateY(-50%) translateX(6px);
|
||||
}
|
||||
|
||||
.v-enter-active,
|
||||
.v-leave-active {
|
||||
transition: opacity 0.2s ease, transform 0.2s ease;
|
||||
}
|
||||
|
||||
.v-enter-from,
|
||||
.v-leave-to {
|
||||
opacity: 0;
|
||||
transform: translateX(-50%) translateY(0);
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,164 @@
|
||||
:root {
|
||||
--primary: #5271ff;
|
||||
--vp-nav-logo-height: 48px;
|
||||
}
|
||||
|
||||
html.dark {
|
||||
--primary: #38b6ff;
|
||||
}
|
||||
|
||||
body {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.vp-nav .title {
|
||||
font-size: 24px !important;
|
||||
}
|
||||
|
||||
.vp-doc h1 {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.vp-doc h2 {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.vp-doc h3 {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.vp-doc h4 {
|
||||
font-size: 14px;
|
||||
opacity: 0.75;
|
||||
}
|
||||
|
||||
.VPSidebarItem .text {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
ul.VPDocOutlineItem.root {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.VPSidebarItem.level-2.is-active > .item > .indicator,
|
||||
.VPSidebarItem.level-3.is-active > .item > .indicator,
|
||||
.VPSidebarItem.level-4.is-active > .item > .indicator,
|
||||
.VPSidebarItem.level-5.is-active > .item > .indicator {
|
||||
background-color: var(--primary) !important;
|
||||
}
|
||||
|
||||
.VPSidebarItem.level-0.is-active > .item .link > .text,
|
||||
.VPSidebarItem.level-1.is-active > .item .link > .text,
|
||||
.VPSidebarItem.level-2.is-active > .item .link > .text,
|
||||
.VPSidebarItem.level-3.is-active > .item .link > .text,
|
||||
.VPSidebarItem.level-4.is-active > .item .link > .text,
|
||||
.VPSidebarItem.level-5.is-active > .item .link > .text {
|
||||
color: var(--primary) !important;
|
||||
}
|
||||
|
||||
.VPSidebarItem.level-0.is-link > .item > .link:hover .text,
|
||||
.VPSidebarItem.level-1.is-link > .item > .link:hover .text,
|
||||
.VPSidebarItem.level-2.is-link > .item > .link:hover .text,
|
||||
.VPSidebarItem.level-3.is-link > .item > .link:hover .text,
|
||||
.VPSidebarItem.level-4.is-link > .item > .link:hover .text,
|
||||
.VPSidebarItem.level-5.is-link > .item > .link:hover .text {
|
||||
color: var(--primary) !important;
|
||||
}
|
||||
|
||||
.outline-title {
|
||||
font-size: 12px !important;
|
||||
}
|
||||
|
||||
.outline-link {
|
||||
font-size: 12px !important;
|
||||
}
|
||||
|
||||
/* Customization of VitePress CSS */
|
||||
|
||||
:root {
|
||||
--vp-home-hero-name-color: transparent;
|
||||
--vp-home-hero-name-background: -webkit-linear-gradient(
|
||||
120deg,
|
||||
#5271ff,
|
||||
#38b6ff
|
||||
);
|
||||
}
|
||||
|
||||
.VPButton.brand {
|
||||
background: linear-gradient(-45deg, #5271ff, #38b6ff) !important;
|
||||
}
|
||||
|
||||
.VPButton.brand:hover {
|
||||
background: linear-gradient(45deg, #5271ff, #5271ff) !important;
|
||||
}
|
||||
|
||||
/* .vitepress/theme/custom.css */
|
||||
|
||||
.image-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100%; /* Ensure it takes up the full height of the parent */
|
||||
width: 100%; /* Ensure it takes up the full width of the parent */
|
||||
}
|
||||
|
||||
/* .vitepress/theme/custom.css */
|
||||
|
||||
/* Container for all icons and arrows */
|
||||
.icon-container {
|
||||
display: flex;
|
||||
align-items: center; /* Align the icons and arrows vertically */
|
||||
justify-content: center; /* Center the icons and arrows horizontally */
|
||||
gap: 20px; /* Space between the icons and arrows */
|
||||
}
|
||||
|
||||
/* BCH icon styling */
|
||||
.bch-icon {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
transform: rotate(-15deg); /* Rotate the BCH icon by 15 degrees to the left */
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
/* Stack icon styling */
|
||||
.stack-icon {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
/* Apps icon styling */
|
||||
.apps-icon {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
/* Arrow between Stack and BCH */
|
||||
.right-arrow {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
/* Arrow between BCH and Apps */
|
||||
.left-arrow {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
/* Light / dark mode logos */
|
||||
|
||||
:root:not(.dark) .dark-only {
|
||||
display: none;
|
||||
}
|
||||
|
||||
:root:is(.dark) .light-only {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Text colors */
|
||||
|
||||
.text-error {
|
||||
color: #f46666;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg fill="#000000" height="800px" width="800px" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve">
|
||||
<g id="Text-files" stroke="#000000" stroke-width="2" stroke-linejoin="round">
|
||||
<path fill-rule="evenodd" d="M53.9791489,9.1429005H50.010849c-0.0826988,0-0.1562004,0.0283995-0.2331009,0.0469999V5.0228
|
||||
C49.7777481,2.253,47.4731483,0,44.6398468,0h-34.422596C7.3839517,0,5.0793519,2.253,5.0793519,5.0228v46.8432999
|
||||
c0,2.7697983,2.3045998,5.0228004,5.1378999,5.0228004h6.0367002v2.2678986C16.253952,61.8274002,18.4702511,64,21.1954517,64
|
||||
h32.783699c2.7252007,0,4.9414978-2.1725998,4.9414978-4.8432007V13.9861002
|
||||
C58.9206467,11.3155003,56.7043495,9.1429005,53.9791489,9.1429005z M7.1110516,51.8661003V5.0228
|
||||
c0-1.6487999,1.3938999-2.9909999,3.1062002-2.9909999h34.422596c1.7123032,0,3.1062012,1.3422,3.1062012,2.9909999v46.8432999
|
||||
c0,1.6487999-1.393898,2.9911003-3.1062012,2.9911003h-34.422596C8.5049515,54.8572006,7.1110516,53.5149002,7.1110516,51.8661003z
|
||||
M56.8888474,59.1567993c0,1.550602-1.3055,2.8115005-2.9096985,2.8115005h-32.783699
|
||||
c-1.6042004,0-2.9097996-1.2608986-2.9097996-2.8115005v-2.2678986h26.3541946
|
||||
c2.8333015,0,5.1379013-2.2530022,5.1379013-5.0228004V11.1275997c0.0769005,0.0186005,0.1504021,0.0469999,0.2331009,0.0469999
|
||||
h3.9682999c1.6041985,0,2.9096985,1.2609005,2.9096985,2.8115005V59.1567993z"/>
|
||||
<path fill-rule="evenodd" d="M38.6031494,13.2063999H16.253952c-0.5615005,0-1.0159006,0.4542999-1.0159006,1.0158005
|
||||
c0,0.5615997,0.4544001,1.0158997,1.0159006,1.0158997h22.3491974c0.5615005,0,1.0158997-0.4542999,1.0158997-1.0158997
|
||||
C39.6190491,13.6606998,39.16465,13.2063999,38.6031494,13.2063999z"/>
|
||||
<path fill-rule="evenodd" d="M38.6031494,21.3334007H16.253952c-0.5615005,0-1.0159006,0.4542999-1.0159006,1.0157986
|
||||
c0,0.5615005,0.4544001,1.0159016,1.0159006,1.0159016h22.3491974c0.5615005,0,1.0158997-0.454401,1.0158997-1.0159016
|
||||
C39.6190491,21.7877007,39.16465,21.3334007,38.6031494,21.3334007z"/>
|
||||
<path fill-rule="evenodd" d="M38.6031494,29.4603004H16.253952c-0.5615005,0-1.0159006,0.4543991-1.0159006,1.0158997
|
||||
s0.4544001,1.0158997,1.0159006,1.0158997h22.3491974c0.5615005,0,1.0158997-0.4543991,1.0158997-1.0158997
|
||||
S39.16465,29.4603004,38.6031494,29.4603004z"/>
|
||||
<path fill-rule="evenodd" d="M28.4444485,37.5872993H16.253952c-0.5615005,0-1.0159006,0.4543991-1.0159006,1.0158997
|
||||
s0.4544001,1.0158997,1.0159006,1.0158997h12.1904964c0.5615025,0,1.0158005-0.4543991,1.0158005-1.0158997
|
||||
S29.0059509,37.5872993,28.4444485,37.5872993z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.7 KiB |
@@ -0,0 +1,15 @@
|
||||
// https://vitepress.dev/guide/custom-theme
|
||||
import type { Theme } from 'vitepress';
|
||||
import DefaultTheme from 'vitepress/theme';
|
||||
import Layout from './Layout.vue';
|
||||
import './style.css';
|
||||
import './custom.css';
|
||||
import './tools.css';
|
||||
|
||||
export default {
|
||||
extends: DefaultTheme,
|
||||
Layout,
|
||||
enhanceApp({ app, router, siteData }) {
|
||||
// ...
|
||||
},
|
||||
} satisfies Theme;
|
||||
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 80 KiB |
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 80 KiB |
@@ -0,0 +1,560 @@
|
||||
/**
|
||||
* Customize default theme styling by overriding CSS variables:
|
||||
* https://github.com/vuejs/vitepress/blob/main/src/client/theme-default/styles/vars.css
|
||||
*/
|
||||
|
||||
/**
|
||||
* Colors
|
||||
*
|
||||
* Each colors have exact same color scale system with 3 levels of solid
|
||||
* colors with different brightness, and 1 soft color.
|
||||
*
|
||||
* - `XXX-1`: The most solid color used mainly for colored text. It must
|
||||
* satisfy the contrast ratio against when used on top of `XXX-soft`.
|
||||
*
|
||||
* - `XXX-2`: The color used mainly for hover state of the button.
|
||||
*
|
||||
* - `XXX-3`: The color for solid background, such as bg color of the button.
|
||||
* It must satisfy the contrast ratio with pure white (#ffffff) text on
|
||||
* top of it.
|
||||
*
|
||||
* - `XXX-soft`: The color used for subtle background such as custom container
|
||||
* or badges. It must satisfy the contrast ratio when putting `XXX-1` colors
|
||||
* on top of it.
|
||||
*
|
||||
* The soft color must be semi transparent alpha channel. This is crucial
|
||||
* because it allows adding multiple "soft" colors on top of each other
|
||||
* to create a accent, such as when having inline code block inside
|
||||
* custom containers.
|
||||
*
|
||||
* - `default`: The color used purely for subtle indication without any
|
||||
* special meanings attched to it such as bg color for menu hover state.
|
||||
*
|
||||
* - `brand`: Used for primary brand colors, such as link text, button with
|
||||
* brand theme, etc.
|
||||
*
|
||||
* - `tip`: Used to indicate useful information. The default theme uses the
|
||||
* brand color for this by default.
|
||||
*
|
||||
* - `warning`: Used to indicate warning to the users. Used in custom
|
||||
* container, badges, etc.
|
||||
*
|
||||
* - `danger`: Used to show error, or dangerous message to the users. Used
|
||||
* in custom container, badges, etc.
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
:root {
|
||||
--vp-c-default-1: var(--vp-c-gray-1);
|
||||
--vp-c-default-2: var(--vp-c-gray-2);
|
||||
--vp-c-default-3: var(--vp-c-gray-3);
|
||||
--vp-c-default-soft: var(--vp-c-gray-soft);
|
||||
|
||||
--vp-c-brand-1: var(--vp-c-indigo-1);
|
||||
--vp-c-brand-2: var(--vp-c-indigo-2);
|
||||
--vp-c-brand-3: var(--vp-c-indigo-3);
|
||||
--vp-c-brand-soft: var(--vp-c-indigo-soft);
|
||||
|
||||
--vp-c-tip-1: var(--vp-c-brand-1);
|
||||
--vp-c-tip-2: var(--vp-c-brand-2);
|
||||
--vp-c-tip-3: var(--vp-c-brand-3);
|
||||
--vp-c-tip-soft: var(--vp-c-brand-soft);
|
||||
|
||||
--vp-c-warning-1: var(--vp-c-yellow-1);
|
||||
--vp-c-warning-2: var(--vp-c-yellow-2);
|
||||
--vp-c-warning-3: var(--vp-c-yellow-3);
|
||||
--vp-c-warning-soft: var(--vp-c-yellow-soft);
|
||||
|
||||
--vp-c-danger-1: var(--vp-c-red-1);
|
||||
--vp-c-danger-2: var(--vp-c-red-2);
|
||||
--vp-c-danger-3: var(--vp-c-red-3);
|
||||
--vp-c-danger-soft: var(--vp-c-red-soft);
|
||||
}
|
||||
|
||||
/**
|
||||
* Component: Button
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
:root {
|
||||
--vp-button-brand-border: transparent;
|
||||
--vp-button-brand-text: var(--vp-c-white);
|
||||
--vp-button-brand-bg: var(--vp-c-brand-3);
|
||||
--vp-button-brand-hover-border: transparent;
|
||||
--vp-button-brand-hover-text: var(--vp-c-white);
|
||||
--vp-button-brand-hover-bg: var(--vp-c-brand-2);
|
||||
--vp-button-brand-active-border: transparent;
|
||||
--vp-button-brand-active-text: var(--vp-c-white);
|
||||
--vp-button-brand-active-bg: var(--vp-c-brand-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Component: Home
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
:root {
|
||||
--vp-home-hero-name-color: transparent;
|
||||
--vp-home-hero-name-background: -webkit-linear-gradient(
|
||||
120deg,
|
||||
#38b6ff 30%,
|
||||
#5271ff
|
||||
);
|
||||
|
||||
/*
|
||||
|
||||
--vp-home-hero-image-background-image: linear-gradient(
|
||||
-45deg,
|
||||
#5271ff 50%,
|
||||
#38b6ff 50%
|
||||
|
||||
);
|
||||
|
||||
--vp-home-hero-image-filter: blur(44px);
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
:root {
|
||||
--vp-home-hero-image-filter: blur(56px);
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 960px) {
|
||||
:root {
|
||||
--vp-home-hero-image-filter: blur(68px);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Component: Custom Block
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
:root {
|
||||
--vp-custom-block-tip-border: transparent;
|
||||
--vp-custom-block-tip-text: var(--vp-c-text-1);
|
||||
--vp-custom-block-tip-bg: var(--vp-c-brand-soft);
|
||||
--vp-custom-block-tip-code-bg: var(--vp-c-brand-soft);
|
||||
}
|
||||
|
||||
/**
|
||||
* Component: Algolia
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
.DocSearch {
|
||||
--docsearch-primary-color: var(--vp-c-brand-1) !important;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides
|
||||
*/
|
||||
|
||||
:root {
|
||||
--primary: #5271ff;
|
||||
--vp-nav-logo-height: 48px;
|
||||
}
|
||||
|
||||
html.dark {
|
||||
--primary: #38b6ff;
|
||||
}
|
||||
|
||||
body {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.vp-nav .title {
|
||||
font-size: 24px !important;
|
||||
}
|
||||
|
||||
.vp-doc h1 {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.vp-doc h2 {
|
||||
font-size: 22px;
|
||||
color: var(--primary);
|
||||
font-weight: bold;
|
||||
margin-top: 15px;
|
||||
margin-bottom: 5px;
|
||||
border: none !important;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.vp-doc h3 {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.vp-doc h4 {
|
||||
font-size: 14px;
|
||||
opacity: 0.75;
|
||||
}
|
||||
|
||||
.VPSidebarItem .text {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.VPSidebarItem.level-2.is-active > .item > .indicator,
|
||||
.VPSidebarItem.level-3.is-active > .item > .indicator,
|
||||
.VPSidebarItem.level-4.is-active > .item > .indicator,
|
||||
.VPSidebarItem.level-5.is-active > .item > .indicator {
|
||||
background-color: var(--primary) !important;
|
||||
}
|
||||
|
||||
.VPSidebarItem.level-0.is-active > .item .link > .text,
|
||||
.VPSidebarItem.level-1.is-active > .item .link > .text,
|
||||
.VPSidebarItem.level-2.is-active > .item .link > .text,
|
||||
.VPSidebarItem.level-3.is-active > .item .link > .text,
|
||||
.VPSidebarItem.level-4.is-active > .item .link > .text,
|
||||
.VPSidebarItem.level-5.is-active > .item .link > .text {
|
||||
color: var(--primary) !important;
|
||||
}
|
||||
|
||||
.VPSidebarItem.level-0.is-link > .item > .link:hover .text,
|
||||
.VPSidebarItem.level-1.is-link > .item > .link:hover .text,
|
||||
.VPSidebarItem.level-2.is-link > .item > .link:hover .text,
|
||||
.VPSidebarItem.level-3.is-link > .item > .link:hover .text,
|
||||
.VPSidebarItem.level-4.is-link > .item > .link:hover .text,
|
||||
.VPSidebarItem.level-5.is-link > .item > .link:hover .text {
|
||||
color: var(--primary) !important;
|
||||
}
|
||||
|
||||
.outline-title {
|
||||
font-size: 12px !important;
|
||||
}
|
||||
|
||||
.outline-link {
|
||||
font-size: 12px !important;
|
||||
}
|
||||
|
||||
/* Customization of VitePress CSS */
|
||||
|
||||
:root {
|
||||
--vp-home-hero-name-color: transparent;
|
||||
--vp-home-hero-name-background: -webkit-linear-gradient(
|
||||
120deg,
|
||||
#5271ff,
|
||||
#38b6ff
|
||||
);
|
||||
}
|
||||
|
||||
.VPButton.brand {
|
||||
background: linear-gradient(-45deg, #5271ff, #38b6ff) !important;
|
||||
}
|
||||
|
||||
.VPButton.brand:hover {
|
||||
background: linear-gradient(45deg, #5271ff, #5271ff) !important;
|
||||
}
|
||||
|
||||
/* .vitepress/theme/custom.css */
|
||||
|
||||
.image-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100%; /* Ensure it takes up the full height of the parent */
|
||||
width: 100%; /* Ensure it takes up the full width of the parent */
|
||||
}
|
||||
|
||||
/* .vitepress/theme/custom.css */
|
||||
|
||||
/* Container for all icons and arrows */
|
||||
.icon-container {
|
||||
display: flex;
|
||||
align-items: center; /* Align the icons and arrows vertically */
|
||||
justify-content: center; /* Center the icons and arrows horizontally */
|
||||
gap: 20px; /* Space between the icons and arrows */
|
||||
}
|
||||
|
||||
/* BCH icon styling */
|
||||
.bch-icon {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
transform: rotate(-15deg); /* Rotate the BCH icon by 15 degrees to the left */
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
/* Stack icon styling */
|
||||
.stack-icon {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
/* Apps icon styling */
|
||||
.apps-icon {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
/* Arrow between Stack and BCH */
|
||||
.right-arrow {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
/* Arrow between BCH and Apps */
|
||||
.left-arrow {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
/* Light / dark mode logos */
|
||||
|
||||
:root:not(.dark) .dark-only {
|
||||
display: none;
|
||||
}
|
||||
|
||||
:root:is(.dark) .light-only {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Feature box override */
|
||||
|
||||
.feature-box-or {
|
||||
flex-direction: row !important;
|
||||
text-align: center !important;
|
||||
}
|
||||
|
||||
.feature-box-or h2 {
|
||||
border: none !important;
|
||||
padding-top: 10px !important;
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
.feature-box-or img {
|
||||
margin: auto !important;
|
||||
}
|
||||
|
||||
/* Promo on front page */
|
||||
|
||||
.promo {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.promo-text {
|
||||
flex: 2; /* Adjusted flex value for more text space */
|
||||
min-width: 250px; /* Ensures text is responsive */
|
||||
}
|
||||
|
||||
.promo-text h1 {
|
||||
font-size: 2rem; /* Adjust font size as needed */
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.promo-text p {
|
||||
font-size: 1.1rem; /* Slightly larger text for better readability */
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.promo-text .clip {
|
||||
background: var(--vp-home-hero-name-background);
|
||||
-webkit-background-clip: text;
|
||||
background-clip: text;
|
||||
color: var(
|
||||
--vp-home-hero-name-color
|
||||
); /* Make the text color transparent to reveal background */
|
||||
font-weight: bold;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
.promo-image {
|
||||
position: relative; /* To position the animated elements inside */
|
||||
flex: 1; /* Reduce the image's width */
|
||||
min-width: 150px; /* Ensures the image is smaller */
|
||||
max-width: 250px; /* Set a max width for the image */
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.promo-image img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
position: relative; /* Image is above the animated icons */
|
||||
z-index: 1; /* Ensure image is in front of the icons */
|
||||
}
|
||||
|
||||
/* X and O animation styles behind promo-image */
|
||||
.animated-bg {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
pointer-events: none; /* Ignore background interactions */
|
||||
z-index: 0; /* Ensure the animated elements are behind the image */
|
||||
}
|
||||
|
||||
.xo {
|
||||
position: absolute;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.xo-1,
|
||||
.xo-3 {
|
||||
color: var(--primary); /* X elements using --primary color */
|
||||
}
|
||||
|
||||
.xo-2,
|
||||
.xo-4 {
|
||||
color: var(--vp-c-text-1); /* O elements using --vp-c-text-1 color */
|
||||
}
|
||||
|
||||
/* Unique positions and animations for each XO element */
|
||||
.xo-1 {
|
||||
top: 10%;
|
||||
left: 15%;
|
||||
animation:
|
||||
rotate-small 6s infinite linear,
|
||||
move-elliptical 10s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.xo-2 {
|
||||
top: 40%;
|
||||
left: 60%;
|
||||
animation:
|
||||
rotate-large 8s infinite linear,
|
||||
move-circular 12s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.xo-3 {
|
||||
top: 70%;
|
||||
left: 30%;
|
||||
animation:
|
||||
rotate-reverse 5s infinite linear,
|
||||
move-diagonal 14s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.xo-4 {
|
||||
top: 20%;
|
||||
left: 80%;
|
||||
animation:
|
||||
rotate-small-reverse 7s infinite linear,
|
||||
move-random 16s infinite ease-in-out;
|
||||
}
|
||||
|
||||
/* Keyframe for self-rotation: Small */
|
||||
@keyframes rotate-small {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
/* Keyframe for self-rotation: Large */
|
||||
@keyframes rotate-large {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(720deg);
|
||||
}
|
||||
}
|
||||
|
||||
/* Keyframe for reverse self-rotation */
|
||||
@keyframes rotate-reverse {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(-360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes rotate-small-reverse {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(-720deg);
|
||||
}
|
||||
}
|
||||
|
||||
/* Keyframe for elliptical movement */
|
||||
@keyframes move-elliptical {
|
||||
0% {
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
25% {
|
||||
transform: translate(60px, 40px);
|
||||
}
|
||||
50% {
|
||||
transform: translate(120px, 0);
|
||||
}
|
||||
75% {
|
||||
transform: translate(60px, -40px);
|
||||
}
|
||||
100% {
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Keyframe for circular movement */
|
||||
@keyframes move-circular {
|
||||
0% {
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
25% {
|
||||
transform: translate(50px, 50px);
|
||||
}
|
||||
50% {
|
||||
transform: translate(100px, 0);
|
||||
}
|
||||
75% {
|
||||
transform: translate(50px, -50px);
|
||||
}
|
||||
100% {
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Keyframe for diagonal movement */
|
||||
@keyframes move-diagonal {
|
||||
0% {
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
50% {
|
||||
transform: translate(100px, 100px);
|
||||
}
|
||||
100% {
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Keyframe for random, unpredictable movement */
|
||||
@keyframes move-random {
|
||||
0% {
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
20% {
|
||||
transform: translate(40px, -30px);
|
||||
}
|
||||
40% {
|
||||
transform: translate(80px, 50px);
|
||||
}
|
||||
60% {
|
||||
transform: translate(-50px, -40px);
|
||||
}
|
||||
80% {
|
||||
transform: translate(30px, 70px);
|
||||
}
|
||||
100% {
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.promo {
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.promo-image {
|
||||
margin-top: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
.tool h2 {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
/* Wrapper for input section */
|
||||
.input-wrapper {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
/* Flex container for dropdown and input */
|
||||
.form-group-row {
|
||||
display: flex;
|
||||
flex-wrap: wrap; /* Ensure responsiveness */
|
||||
gap: 15px; /* Space between dropdown and input */
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.form-group-row.extended {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* Form group styling */
|
||||
.form-group {
|
||||
flex: 1;
|
||||
min-width: 200px;
|
||||
}
|
||||
|
||||
.select-group {
|
||||
flex: 1;
|
||||
min-width: 200px;
|
||||
max-width: 50%;
|
||||
}
|
||||
|
||||
.input-group {
|
||||
flex: 1;
|
||||
min-width: 200px;
|
||||
}
|
||||
|
||||
.input-group.extended {
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.form-group label {
|
||||
display: block;
|
||||
font-weight: bold;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.form-group select,
|
||||
.form-group input,
|
||||
.form-group button {
|
||||
width: 100%; /* Makes fields responsive */
|
||||
padding: 10px;
|
||||
font-size: 1rem;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
/* Extended input styling */
|
||||
.extended-input {
|
||||
width: 100%;
|
||||
min-height: 2.5rem;
|
||||
max-height: 300px;
|
||||
resize: none;
|
||||
padding: 0.5rem;
|
||||
line-height: 1.5;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 4px;
|
||||
background: var(--vp-c-bg-alt);
|
||||
}
|
||||
|
||||
.form-group button {
|
||||
background-color: #333;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.form-group button:hover {
|
||||
background-color: #555;
|
||||
}
|
||||
|
||||
/* Output section */
|
||||
.output-section {
|
||||
margin-top: 20px;
|
||||
margin-bottom: 50px;
|
||||
}
|
||||
|
||||
.output-box-container {
|
||||
position: relative;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.output-box-label {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
.output-box {
|
||||
box-sizing: content-box;
|
||||
border: 1px dashed #ccc;
|
||||
padding: 10px;
|
||||
min-height: 24px;
|
||||
overflow-wrap: break-word;
|
||||
white-space: pre-wrap;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
.placeholder {
|
||||
text-align: center;
|
||||
color: #888;
|
||||
font-style: italic;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
/* Gradient Button Styling */
|
||||
.gradient-button {
|
||||
padding: 10px 20px;
|
||||
font-size: 1rem;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
background: var(--vp-home-hero-name-background);
|
||||
border: none;
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
border-radius: 10px; /* Full-rounded button */
|
||||
cursor: pointer;
|
||||
text-transform: uppercase;
|
||||
box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1); /* Soft shadow */
|
||||
}
|
||||
|
||||
.gradient-button:hover {
|
||||
background: var(--primary);
|
||||
}
|
||||
|
||||
/* Mobile responsiveness */
|
||||
@media (max-width: 768px) {
|
||||
.select-group {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.input-group {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user