✨ Adds playground
This commit is contained in:
parent
180faecddf
commit
39b3d2711c
21
index.html
21
index.html
@ -5,16 +5,21 @@
|
||||
<link rel="icon" type="image/png" href="/binary.png"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<title>Binary</title>
|
||||
<script src="https://unpkg.com/vue@3"></script>
|
||||
<script src="https://unpkg.com/vue-router@4"></script>
|
||||
<style>
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
||||
<div id="app">
|
||||
<router-view></router-view>
|
||||
</div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<style>
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
|
@ -9,7 +9,8 @@
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"vue": "^3.4.19"
|
||||
"vue": "^3.4.19",
|
||||
"vue-router": "4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^5.0.4",
|
||||
|
@ -1,7 +1,6 @@
|
||||
<template>
|
||||
<div v-if="bit === '1'" class="w-2 h-8 bg-emerald-100 rounded-t-full" />
|
||||
<div v-else-if="bit === '0'" class="w-2 h-3 bg-emerald-100 rounded-t-full" />
|
||||
<p v-else class="text-emerald-100 text-3xl">{{ bit }}</p>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
56
src/components/Settings.vue
Normal file
56
src/components/Settings.vue
Normal file
@ -0,0 +1,56 @@
|
||||
<template>
|
||||
<div class="flex w-full items-center justify-between mt-4">
|
||||
<button @click="() => (openSettings = !openSettings)" class="ml-4">
|
||||
<img
|
||||
:data-open="openSettings"
|
||||
src="/chevron.svg"
|
||||
alt="Chevron"
|
||||
class="data-[open=true]:rotate-180"
|
||||
/>
|
||||
</button>
|
||||
|
||||
<slot />
|
||||
</div>
|
||||
|
||||
<div v-if="openSettings" class="flex gap-x-2 mt-4">
|
||||
<label for="spacing" class="text-emerald-100">Spacing:</label>
|
||||
|
||||
<select
|
||||
v-model="spacing"
|
||||
name="spacing"
|
||||
id="spacing"
|
||||
class="text-emerald-100 bg-transparent"
|
||||
>
|
||||
<option value="2">2</option>
|
||||
<option value="3">3</option>
|
||||
<option value="4" selected>4</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div v-if="openSettings" class="flex gap-x-2">
|
||||
<input v-model="fill" type="checkbox" id="fill" name="fill" checked />
|
||||
<label for="fill" class="text-emerald-100">Fill</label>
|
||||
</div>
|
||||
|
||||
<router-link
|
||||
v-if="openSettings && route.fullPath === '/'"
|
||||
to="/playground"
|
||||
class="text-emerald-100 underline"
|
||||
>
|
||||
Open playground
|
||||
</router-link>
|
||||
<router-link
|
||||
v-else-if="openSettings"
|
||||
to="/"
|
||||
class="text-emerald-100 underline"
|
||||
>
|
||||
Open home
|
||||
</router-link>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { fill, openSettings, spacing } from "../composables/options.ts";
|
||||
import { useRoute } from "vue-router";
|
||||
|
||||
const route = useRoute();
|
||||
</script>
|
10
src/composables/options.ts
Normal file
10
src/composables/options.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import { computed, ref } from "vue";
|
||||
|
||||
export const openSettings = ref(false);
|
||||
export const spacing = ref("4");
|
||||
export const fill = ref(true);
|
||||
export const options = computed(() => ({
|
||||
spacing: +spacing.value,
|
||||
fill: fill.value,
|
||||
prefix: undefined,
|
||||
}));
|
20
src/main.ts
20
src/main.ts
@ -1,5 +1,19 @@
|
||||
import { createApp } from "vue";
|
||||
import App from "./App.vue";
|
||||
import { createApp } from "vue/dist/vue.esm-bundler";
|
||||
import Home from "./pages/Home.vue";
|
||||
import * as VueRouter from "vue-router";
|
||||
import Playground from "./pages/Playground.vue";
|
||||
import "./index.css";
|
||||
|
||||
createApp(App).mount("#app");
|
||||
const routes = [
|
||||
{ path: "/", component: Home },
|
||||
{ path: "/playground", component: Playground },
|
||||
];
|
||||
|
||||
const router = VueRouter.createRouter({
|
||||
history: VueRouter.createWebHistory(),
|
||||
routes: routes,
|
||||
});
|
||||
|
||||
const app = createApp({});
|
||||
app.use(router);
|
||||
app.mount("#app");
|
||||
|
@ -38,16 +38,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex w-full items-center justify-between mt-4">
|
||||
<button @click="() => (openSettings = !openSettings)" class="ml-4">
|
||||
<img
|
||||
:data-open="openSettings"
|
||||
src="/chevron.svg"
|
||||
alt="Chevron"
|
||||
class="data-[open=true]:rotate-180"
|
||||
/>
|
||||
</button>
|
||||
|
||||
<Settings>
|
||||
<button
|
||||
v-if="shown"
|
||||
@click="next"
|
||||
@ -62,49 +53,22 @@
|
||||
>
|
||||
Show
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div v-if="openSettings" class="flex gap-x-2 mt-4">
|
||||
<label for="spacing" class="text-emerald-100">Spacing:</label>
|
||||
|
||||
<select
|
||||
v-model="spacing"
|
||||
name="spacing"
|
||||
id="spacing"
|
||||
class="text-emerald-100 bg-transparent"
|
||||
>
|
||||
<option value="2">2</option>
|
||||
<option value="3">3</option>
|
||||
<option value="4" selected>4</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div v-if="openSettings" class="flex gap-x-2">
|
||||
<input v-model="fill" type="checkbox" id="fill" name="fill" checked />
|
||||
<label for="fill" class="text-emerald-100">Fill</label>
|
||||
</div>
|
||||
</Settings>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, ref } from "vue";
|
||||
import { levels, Problem } from "./composables/levels.ts";
|
||||
import Number from "./components/Number.vue";
|
||||
import { onMounted, ref } from "vue";
|
||||
import { levels, Problem } from "../composables/levels.ts";
|
||||
import Number from "../components/Number.vue";
|
||||
import { options } from "../composables/options.ts";
|
||||
import Settings from "../components/Settings.vue";
|
||||
|
||||
const level = ref(0);
|
||||
const problem = ref<Problem | undefined>();
|
||||
const shown = ref(false);
|
||||
|
||||
const openSettings = ref(false);
|
||||
const spacing = ref("4");
|
||||
const fill = ref(true);
|
||||
const options = computed(() => ({
|
||||
spacing: +spacing.value,
|
||||
fill: fill.value,
|
||||
prefix: undefined,
|
||||
}));
|
||||
|
||||
function next() {
|
||||
problem.value = levels[level.value].generate();
|
||||
shown.value = false;
|
64
src/pages/Playground.vue
Normal file
64
src/pages/Playground.vue
Normal file
@ -0,0 +1,64 @@
|
||||
<template>
|
||||
<div class="flex items-center justify-center w-screen h-screen bg-gray-900">
|
||||
<div class="flex items-center justify-center flex-col gap-y-2">
|
||||
<input
|
||||
v-if="forward"
|
||||
v-model="number"
|
||||
type="number"
|
||||
placeholder="Number..."
|
||||
class="rounded-full py-2 px-4 bg-transparent border border-emerald-100 text-emerald-100 focus:outline-none"
|
||||
/>
|
||||
|
||||
<Number v-if="forward" :number="number" :options="options" class="mt-2" />
|
||||
|
||||
<div v-if="!forward" class="flex flex-row-reverse gap-x-2 h-[2.375rem]">
|
||||
<div
|
||||
v-for="i in 24 / +spacing"
|
||||
class="flex flex-row-reverse items-end gap-x-1 border-b-[0.375rem] border-b-emerald-100 border-solid w-fit rounded-md"
|
||||
>
|
||||
<button
|
||||
v-for="j in +spacing"
|
||||
@click="setBit(i, j)"
|
||||
:data-bit="(number & (2 ** (i * 4 + j))).toString()"
|
||||
:class="`w-2 ${getBit(i, j) ? 'h-8' : 'h-3'} bg-emerald-100 rounded-t-full`"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p v-if="!forward" class="text-emerald-100 text-lg font-semibold">
|
||||
{{ number }}
|
||||
</p>
|
||||
|
||||
<Settings>
|
||||
<button
|
||||
@click="swap"
|
||||
class="text-emerald-100 border border-emerald-100 rounded-full px-4 py-2"
|
||||
>
|
||||
Swap
|
||||
</button>
|
||||
</Settings>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import Number from "../components/Number.vue";
|
||||
import { options, spacing } from "../composables/options.ts";
|
||||
import { ref } from "vue";
|
||||
import Settings from "../components/Settings.vue";
|
||||
|
||||
const number = ref(0);
|
||||
const forward = ref(true);
|
||||
|
||||
function getBit(i: number, j: number) {
|
||||
return number.value & (2 ** ((i - 1) * 4 + j - 1));
|
||||
}
|
||||
|
||||
function setBit(i: number, j: number) {
|
||||
number.value ^= 2 ** ((i - 1) * 4 + j - 1);
|
||||
}
|
||||
|
||||
function swap() {
|
||||
forward.value = !forward.value;
|
||||
}
|
||||
</script>
|
Loading…
x
Reference in New Issue
Block a user