leds-spark-lib
Version:
Biblioteca de geração de código
389 lines (324 loc) • 9.15 kB
JavaScript
import fs from "fs";
import { expandToString } from "../../../../util/template-string.js";
import path from "path";
export function generate(project_abstraction, target_folder) {
fs.writeFileSync(path.join(target_folder, 'DataTable.vue'), generateDataTable());
fs.writeFileSync(path.join(target_folder, 'Card.vue'), generateCard());
fs.writeFileSync(path.join(target_folder, 'GenericTextInput.vue'), generateGenericTextInpput());
fs.writeFileSync(path.join(target_folder, 'PButton.vue'), generatePButton());
fs.writeFileSync(path.join(target_folder, 'TextInput.vue'), generateNoGenericTextInpput());
fs.writeFileSync(path.join(target_folder, 'README.md'), generateREADME());
}
function generateDataTable() {
return expandToString `
<script setup lang="ts">
import { computed, reactive, ref } from 'vue'
interface DataTableHeader {
title: string; // titulo da coluna
value: string; // valor da coluna
}
type DataTableItem = Record<string, string | number>
interface DataTableProps {
items: DataTableItem[]
headers?: DataTableHeader[]
}
const { items, headers } = defineProps<DataTableProps>()
const processedHeaders = computed(() => {
if (headers) {
return headers
} else if (items.length > 0) {
return Object.keys(items[0]).map((key) => {
return { title: key, value: key }
})
}
})
/* pode ser exportado como v-model ou defineExpose. deixar sem exportar por enquanto */
const selectedItems = reactive<Record<number, DataTableItem>>({})
/* import { watch } from 'vue'
watch(selectedItems, (newValue) => console.log(newValue)) */
const updateSelected = (index: number, event: Event) => {
const checked = (event.target as HTMLInputElement | null)?.checked
if (checked) {
selectedItems[index] = items[index]
} else {
delete selectedItems[index]
}
}
const selectAll = ref(false)
const toggleSelectAll = (event: Event) => {
selectAll.value = !!(event.target as HTMLInputElement | null)?.checked
if (selectAll.value) {
items.forEach((item, index) => {
selectedItems[index] = item
})
} else {
items.forEach((_, index) => {
delete selectedItems[index]
})
}
}
const emit = defineEmits<{
editar: [id: DataTableItem];
excluir: [ids: DataTableItem[]];
}>()
const editarDesabilitado = computed(() => {
return Object.keys(selectedItems).length !== 1
})
const editar = () => {
emit('editar', Object.values(selectedItems)[0])
}
const excluirDesabilitado = computed(() => {
return Object.keys(selectedItems).length === 0
})
const excluir = () => {
emit('excluir', Object.values(selectedItems))
}
</script>
<template>
<div>
<p-button
class="mr-2"
:disabled="editarDesabilitado"
@click="editar"
>
Editar
</p-button>
<p-button
variant="error"
:disabled="excluirDesabilitado"
@click="excluir"
>
Excluir
</p-button>
<table class="w-full mb-2">
<thead>
<tr class="border-b border-gray-400">
<th class="w-8 py-2">
<input type="checkbox"
:value="selectAll"
@input="toggleSelectAll"
/>
</th>
<th v-for="header in processedHeaders" class="text-left font-medium">{{ header.title }}</th>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) in items" class="border-b border-gray-300 text-gray-600">
<td class="text-center py-2">
<input type="checkbox"
:checked="!!selectedItems[index]"
:value="selectedItems[index]"
@input="(evt: Event) => updateSelected(index, evt)"
/>
</td>
<td v-for="header in processedHeaders">{{ item[header.value] }}</td>
</tr>
</tbody>
</table>
<div class="flex justify-end gap-4">
<div class="flex gap-1">
<span>Itens por página</span>
<select class="border rounded-md py-1 px-3">
<option>5</option>
<option>10</option>
<option>15</option>
</select>
</div>
<div>
1-5 de 20
</div>
<div class="flex gap-2">
<p-button>|<</p-button>
<p-button class="border"><</p-button>
<p-button class="border">></p-button>
<p-button class="border">>|</p-button>
</div>
</div>
</div>
</template>
`;
}
function generateCard() {
return expandToString `
<template>
<div class="p-3 border-2 rounded-md border-zinc-500 shadow-md">
<slot />
</div>
</template>
`;
}
function generateGenericTextInpput() {
return expandToString `
<script setup lang="ts">
import { computed } from 'vue'
export interface GenericTextInputProps {
type?: 'text' | 'password';
placeholder?: string;
variant?: 'error' | 'default';
}
const {
type = 'text',
placeholder,
variant = 'default'
} = defineProps<GenericTextInputProps>()
const value = defineModel()
const baseClass = 'w-full py-2 px-3 border-2 border-gray-600 rounded-sm placeholder:text-gray-400 '
const inputClass = computed(() => {
if (variant === 'error') {
return baseClass + 'border-red-400'
}
return baseClass
})
const emit = defineEmits<{
keyupEnter: []
}>()
const emitEnter = () => {
emit('keyupEnter')
}
</script>
<template>
<input
v-model="value"
:class="inputClass"
:type="type"
:placeholder="placeholder"
@keyup.enter="emitEnter"
/>
</template>
`;
}
function generatePButton() {
return expandToString `
<!-- P de 'pretty', para ser curto e n conflitar com button nativo-->
<script setup lang="ts">
import { computed } from 'vue';
const props = withDefaults(defineProps<{
variant?: 'default' | 'error'
}>(), {
variant: 'default'
})
const className = computed(() => {
if (props.variant === 'default') {
return 'py-1 px-3 rounded-md text-white cursor-pointer disabled:cursor-default bg-blue-800 disabled:bg-blue-800/50'
} else {
return 'py-1 px-3 rounded-md text-white cursor-pointer disabled:cursor-default bg-red-800 disabled:bg-red-800/50'
}
})
</script>
<template>
<button
:class="className"
>
<slot />
</button>
</template>
`;
}
function generateNoGenericTextInpput() {
return expandToString `
<script lang="ts">
import { computed, watch } from 'vue'
import type { GenericTextInputProps } from './GenericTextInput.vue'
import type { ValidationResult, ValidationResultFunction } from '@/utils/regras'
export interface TextInputProps extends Omit<GenericTextInputProps, 'variant'> {
rules?: ValidationResultFunction[];
}
</script>
<script setup lang="ts">
const value = defineModel()
const {
type,
placeholder,
rules,
} = defineProps<TextInputProps>()
const hasRules = computed(() => {
return rules !== undefined && rules.length > 0
})
const validationMessages = computed<ValidationResult[]>(() => {
if (!hasRules.value) {
return []
}
return (rules as ((value: any) => ValidationResult)[]).map((validarRegra) => {
return validarRegra(value.value)
})
})
const validationMessage = computed<string>(() => {
return validationMessages.value.find((message) => {
return typeof message === 'string'
}) || ''
})
const isValid = computed<boolean>(() => {
return validationMessages.value.every((valid) => {
return valid === true
})
})
const variant = computed(() => {
if (isValid.value) {
return 'default'
} else {
return 'error'
}
})
const emit = defineEmits<{
validationUpdate: [valid: boolean];
keyupEnter: [];
}>()
const emitEnter = () => {
emit('keyupEnter')
}
// pode ser feito tbm como v-model, expose
watch(isValid, (newValue) => {
emit('validationUpdate', newValue)
})
</script>
<template>
<div class="w-[280px]">
<div class="h-[19px] mb-[16px]">
<label class="">
<slot />
</label>
</div>
<generic-text-input
class="mb-[8px]"
v-model="value"
:type="type"
:placeholder="placeholder"
:variant="variant"
@keyup-enter="emitEnter"
/>
<div class="h-(--text-2xl) overflow-auto text-red-400">
{{ validationMessage }}
</div>
</div>
</template>
`;
}
function generateREADME() {
return expandToString `
# Components
Vue template files in this folder are automatically imported.
## 🚀 Usage
Importing is handled by [unplugin-vue-components](https://github.com/unplugin/unplugin-vue-components). This plugin automatically imports ".vue" files created in the "src/components" directory, and registers them as global components. This means that you can use any component in your application without having to manually import it.
The following example assumes a component located at "src/components/MyComponent.vue":
vue
<template>
<div>
<MyComponent />
</div>
</template>
<script lang="ts" setup>
//
</script>
When your template is rendered, the component's import will automatically be inlined, which renders to this:
vue
<template>
<div>
<MyComponent />
</div>
</template>
<script lang="ts" setup>
import MyComponent from '@/components/MyComponent.vue'
</script>
`;
}
//# sourceMappingURL=generate.js.map