This commit is contained in:
andbi 2025-11-19 20:22:22 -06:00
parent aa7c30950c
commit 72716e1c28
41 changed files with 15461 additions and 0 deletions

View file

@ -0,0 +1,48 @@
<template>
<u-modal
title="Confirmation"
description="Confirmation required for the selected action"
:dismissible="false"
>
<template #body>
<p class="my-3">
Type <strong>{{ message }}</strong> to confirm.
</p>
<div>
<u-field-group class="w-full">
<u-input
v-model="inputMessage"
name="user-input"
autocomplete="false"
type="text"
class="w-full"
/>
<u-button color="error" :disabled="!matched" @click="onSubmit">
Submit
</u-button>
</u-field-group>
</div>
</template>
</u-modal>
</template>
<script lang="ts" setup>
import { UModal, UInput, UButton } from "#components";
interface Props {
message: string;
}
const props = defineProps<Props>();
const emit = defineEmits<{ close: [boolean] }>();
const inputMessage = ref("");
const matched = computed(() => {
return inputMessage.value === props.message;
});
function onSubmit() {
emit("close", true);
}
</script>

View file

@ -0,0 +1,96 @@
<template>
<div class="grid grid-cols-2 gap-5">
<u-card variant="soft">
<u-form-field label="Type Name">
<u-input v-model="type.name" class="w-full" />
</u-form-field>
<table class="w-full">
<thead>
<tr>
<th class="w-0">#</th>
<th>Property Name</th>
<th>Property Type</th>
<th>&nbsp;</th>
</tr>
</thead>
<tbody>
<tr v-for="(property, idx) in type.properties" :key="idx">
<th class="align-top w-0 pt-4">{{ idx + 1 }}</th>
<td>
<u-input v-model="property.name" class="w-full" />
</td>
<td class="align-middle">
<u-radio-group
v-model="property.type"
:items="typeItems"
orientation="vertical"
/>
</td>
<td class="align-middle">
<u-button
icon="i-bi-trash"
size="xs"
color="error"
@click="deleteProperty(idx)"
/>
</td>
</tr>
</tbody>
</table>
<u-button
icon="i-bi-plus"
size="sm"
color="neutral"
variant="outline"
@click="addProperty"
>
New Property
</u-button>
<template #footer>
<p class="text-xs muted">
Add and delete type parameters, change their types, the dynamic form
on the right will be automatically updated.
</p>
</template>
</u-card>
<div v-if="allParametersAreValid">
<h4 style="margin-top: 0">Sample Form</h4>
<simple-form :type="type" />
</div>
</div>
</template>
<script setup lang="ts">
import type { DataType, UiPropertyType } from "~/types";
// Here we define our type as a model, meaning that any changes to this object will be published back to the parent view
const type = defineModel<DataType>({ required: true });
const typeItems = ref<UiPropertyType[]>(["number", "string", "text"]);
// Form won't be shown if there are empty parameters
const allParametersAreValid = computed(() => {
const typeProps = type.value.properties;
if (typeProps.length == 0) {
return false; // No properties at all
}
for (const p of typeProps) {
if (p.name.length === 0) {
return false; // Missing a name
}
}
return true;
});
function deleteProperty(index: number) {
const copy = type.value.properties;
copy.splice(index, 1);
type.value.properties = copy;
}
function addProperty() {
type.value.properties.push({ name: "", type: "string" });
}
</script>

View file

@ -0,0 +1,42 @@
<template>
<UNavigationMenu :items="items" class="w-full justify-start bg-neutral-50">
<template #list-trailing>
<div class="flex flex-1 justify-end mx-2">
<UBadge
icon="i-mdi-clock-outline"
size="md"
color="secondary"
variant="solid"
class="font-mono"
>
{{ currentTime }}
</UBadge>
</div>
</template>
</UNavigationMenu>
</template>
<script setup lang="ts">
import type { NavigationMenuItem } from "@nuxt/ui";
import { appState } from "#imports";
const state = appState();
const currentTime = computed(() => {
return state.value.time.toLocaleTimeString();
});
const items = ref<NavigationMenuItem[]>([
{
icon: "i-mdi-home",
to: "/",
active: false,
},
{
label: "Data Structures",
icon: "i-material-symbols-account-tree-outline-rounded",
to: "/data",
active: false,
},
]);
</script>

View file

@ -0,0 +1,41 @@
<template>
<u-breadcrumb :items="items" class="my-nav mb-3" />
</template>
<script setup lang="ts">
import type { BreadcrumbItem } from "@nuxt/ui";
import { UBreadcrumb } from "#components";
import type { NavRoute } from "~/ui";
interface Props {
previous: NavRoute[];
last: string;
}
const items = computed(() => {
const arr: BreadcrumbItem[] = [];
for (const h of props.previous) {
arr.push({
label: h.title,
to: h.path,
});
}
arr.push({
label: props.last,
disabled: true,
class: "text-muted",
});
return arr;
});
const props = defineProps<Props>();
</script>
<style>
/* Override default high margins for <ol> lists */
.my-nav ol {
margin-top: 0 !important;
margin-bottom: 0 !important;
padding-left: 0 !important;
}
</style>

View file

@ -0,0 +1,66 @@
<template>
<div>
<div class="p-2 bg-neutral-50 rounded-lg shadow-neutral-300 shadow-sm">
<table class="table">
<tbody>
<tr v-for="(prop, idx) in type.properties" :key="idx">
<td class="font-semibold w-0 text-nowrap px-2">
{{ prop.name }}
</td>
<td>
<u-input
v-if="prop.type === 'string'"
v-model="formData[prop.name]"
type="text"
class="w-full"
/>
<u-textarea
v-if="prop.type === 'text'"
v-model="formData[prop.name]"
class="w-full"
/>
<u-input
v-if="prop.type === 'number'"
v-model="formData[prop.name]"
type="number"
/>
</td>
</tr>
</tbody>
</table>
</div>
<div>
<h4 class="mx-0">Form Data</h4>
<pre class="mx-0 my-0">{{ formData }}</pre>
</div>
</div>
</template>
<script setup lang="ts">
import type { DataType } from "~/types";
interface Props {
type: DataType;
}
const props = defineProps<Props>();
const formData = ref<Record<string, string>>({});
watch(
props,
() => {
// Property value changed, resetting the form data
formData.value = {};
},
{ deep: true }
);
</script>
<style>
/* Override default high margins for <ol> lists */
.table {
margin-top: 0 !important;
margin-bottom: 0 !important;
}
</style>