Skip to content

Commit

Permalink
Initial commit.
Browse files Browse the repository at this point in the history
  • Loading branch information
Stnaire committed Oct 10, 2022
0 parents commit b4524dd
Show file tree
Hide file tree
Showing 14 changed files with 21,900 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.idea
.vscode
.DS_Store
node_modules
coverage
/dist
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Webpack demo

A very simple todo app bundled with Webpack that uses Banquette.
8 changes: 8 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Banquette demo with Webpack</title>
</head>
<body id="app"></body>
</html>
21,582 changes: 21,582 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

36 changes: 36 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"name": "banquette-demo-webpack",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"devDependencies": {
"@types/node": "^18.8.2",
"@types/webpack": "^5.28.0",
"@webpack-cli/generators": "^2.5.0",
"clean-webpack-plugin": "^4.0.0",
"copy-webpack-plugin": "^11.0.0",
"css-loader": "^6.7.1",
"declaration-bundler-webpack-plugin": "^1.0.3",
"html-webpack-plugin": "^5.5.0",
"style-loader": "^3.3.1",
"ts-loader": "^9.4.1",
"typescript": "^4.8.4",
"vue-loader": "^17.0.0",
"webpack": "^5.74.0",
"webpack-cli": "^4.10.0",
"webpack-dev-server": "^4.11.1",
"wepack-cli": "^0.0.1-security"
},
"description": "My webpack project",
"scripts": {
"build": "webpack --mode=production --node-env=production",
"build:dev": "webpack --mode=development",
"build:prod": "webpack --mode=production --node-env=production",
"watch": "webpack --watch",
"serve": "webpack serve"
},
"dependencies": {
"@banquette/vue-ui": "^0.0.1",
"vue": "^3.2.40"
}
}
26 changes: 26 additions & 0 deletions src/app.component.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<script lang="ts">
import { Component } from "@banquette/vue-typescript";
import TodoComponent from "./todo/todo.component.vue";
@Component({
components: [TodoComponent]
})
export default class App {
}
</script>

<template>
<div class="container">
<h1>What do you want to do today?</h1>
<todo></todo>
</div>
</template>

<style>
.container {
max-width: 750px;
margin: 2rem auto;
padding: 0 2rem;
}
</style>
12 changes: 12 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { createApp } from 'vue';
import App from './app.component.vue';

import './main.css';

/**
* The default theme defines the --bt-* variables used by the components
* as well as some variants.
*/
import '@banquette/vue-ui/themes/default';

createApp(App).mount('#app');
24 changes: 24 additions & 0 deletions src/main.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500&display=swap');

html {
font-size: 14px;
font-family: 'Roboto', sans-serif;
}

h1 {
font-weight: 500;
}

/**
* To animate the popovers.
*/
.v-enter-active,
.v-leave-active {
transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1) 0ms, opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1) 0ms;
}

.v-enter-from,
.v-leave-to {
transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1) 0ms, opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1) 0ms;
opacity: 0;
}
42 changes: 42 additions & 0 deletions src/todo/task.component.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<script lang="ts">
import { Component, Prop, Vue } from "@banquette/vue-typescript";
import { PopoverDirective } from "@banquette/vue-ui/popover";
import { FormCheckboxComponent } from "@banquette/vue-ui/form/checkbox";
import { ButtonComponent } from "@banquette/vue-ui/button";
import { TaskInterface } from "./task.interface";
@Component({
name: 'task',
components: [FormCheckboxComponent, ButtonComponent],
directives: [PopoverDirective],
emits: ['delete']
})
export default class TaskComponent extends Vue {
@Prop({type: Object, required: true}) public entity!: TaskInterface;
}
</script>

<template>
<div class="task" :class="{completed: entity.done}">
<span>{{ entity.description }}</span>
<bt-form-checkbox v-model="entity.done" v-if="!entity.done" v-bt-popover="{content: 'Mark as completed', placement: 'right'}"></bt-form-checkbox>
<bt-button variant="sm link danger" v-else v-bt-popover="{content: 'Delete', placement: 'right'}" @click="$emit('delete', entity)">X</bt-button>
</div>
</template>

<style scoped>
.task {
display: flex;
align-items: center;
justify-content: space-between;
padding: 1rem;
}
.task:hover {
background: #fafafa;
}
.task.completed span {
text-decoration: line-through;
}
</style>
6 changes: 6 additions & 0 deletions src/todo/task.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

export interface TaskInterface {
id: number;
description: string;
done: boolean;
}
84 changes: 84 additions & 0 deletions src/todo/todo.component.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<script lang="ts">
import { FormControl } from "@banquette/form";
import { Component, Computed, Ref, Expose } from "@banquette/vue-typescript";
import { ButtonComponent } from "@banquette/vue-ui/button";
import { DialogComponent } from "@banquette/vue-ui/dialog";
import { FormTextComponent } from "@banquette/vue-ui/form/text";
import ValidateNotEmptyComponent from "@banquette/vue-ui/form/validator/not-empty-validator.component.vue";
import TaskComponent from "./task.component.vue";
import { TaskInterface } from "./task.interface";
@Component({
name: 'todo',
components: [TaskComponent, FormTextComponent, ValidateNotEmptyComponent, ButtonComponent, DialogComponent]
})
export default class TodoComponent {
// The FormControl that holds the description of the new task.
@Expose() public newTaskControl = new FormControl();
// @Ref() is used instead of @Expose() so we don't expose the raw array of tasks to the template.
@Ref() private tasks: TaskInterface[] = [];
// These computed will update as the list of tasks changes.
@Computed() public get tasksCount(): number {
return this.tasks.length;
}
@Computed() public get uncompletedTasks(): TaskInterface[] {
return this.tasks.filter((i) => !i.done);
}
@Computed() public get completedTasks(): TaskInterface[] {
return this.tasks.filter((i) => i.done);
}
@Expose() public addTask = (() => {
let maxId = 0; // Used to uniquely identify each task in the v-for
return () => {
if (this.newTaskControl.validate()) {
this.tasks.push({id: ++maxId, description: String(this.newTaskControl.value), done: false});
this.newTaskControl.reset();
}
}
})();
@Expose() public onDelete(task: TaskInterface): void {
this.tasks = this.tasks.filter((i) => i.id !== task.id);
}
}
</script>

<template>
<bt-form-text :control="newTaskControl">
Task's description
<bt-validate-not-empty>A value is required.</bt-validate-not-empty>
<template #after-raw>
<bt-button @click="addTask()">Add</bt-button>
</template>
</bt-form-text>
<div class="todo-list">
<div class="title">Uncompleted tasks ({{ uncompletedTasks.length }})</div>
<task v-for="task in uncompletedTasks" :entity="task" :key="task.id"></task>

<div class="title">Completed tasks ({{ completedTasks.length }})</div>
<task v-for="task in completedTasks" :entity="task" :key="task.id" @delete="onDelete"></task>
</div>
</template>

<style scoped>
.todo-list {
background: #fff;
border-radius: var(--bt-border-radius-base);
box-shadow: 4px 6px 12px rgb(0 0 0 / 8%);
margin-top: 1rem;
border: 1px solid #ededed;
overflow: hidden;
}
.title {
font-size: 1.1em;
padding: 1rem;
font-weight: 500;
background: #f1f1f1;
}
</style>
10 changes: 10 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"noImplicitAny": true,
"experimentalDecorators": true,
"moduleResolution": "node",
"module": "es6",
"target": "es5"
}
}
6 changes: 6 additions & 0 deletions vue-shim.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
declare module "*.vue" {
import { defineComponent } from 'vue';

const component: ReturnType<typeof defineComponent>;
export default component;
}
55 changes: 55 additions & 0 deletions webpack.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { VueLoaderPlugin } = require('vue-loader');

const isProduction = process.env.NODE_ENV === 'production';
const stylesHandler = 'style-loader';

const config = {
entry: './src/index.ts',
output: {
path: path.resolve(__dirname, 'dist'),
},
devServer: {
open: true,
host: 'localhost'
},
plugins: [
new HtmlWebpackPlugin({
template: 'index.html',
}),
new VueLoaderPlugin()
],
module: {
rules: [
{
test: /\.(ts|tsx)$/i,
loader: 'ts-loader',
exclude: ['/node_modules/'],
options: {
appendTsSuffixTo: [/\.vue$/]
}
},
{
test: /\.vue$/,
loader: 'vue-loader'
},
{
test: /\.css$/i,
use: [stylesHandler, 'css-loader'],
},
{
test: /\.(eot|svg|ttf|woff|woff2|png|jpg|gif)$/i,
type: 'asset',
}
],
},
resolve: {
extensions: ['.tsx', '.ts', '.jsx', '.js', '.vue'],
},
};

module.exports = () => {
config.mode = isProduction ? 'production' : 'development';
return config;
};

0 comments on commit b4524dd

Please sign in to comment.