},
"main": "background.js",
"dependencies": {
+ "animejs": "^3.2.0",
"core-js": "^3.6.5",
"vue": "^3.0.0-0",
"vue-router": "^4.0.0-0",
"vuex": "^4.0.0-0"
},
"devDependencies": {
+ "@types/animejs": "^3.1.2",
"@types/jest": "^24.0.19",
"@typescript-eslint/eslint-plugin": "^2.33.0",
"@typescript-eslint/parser": "^2.33.0",
<template>
- <div id="nav">
- <router-link to="/">Home</router-link> |
- <router-link to="/about">About</router-link>
+ <div id="app">
+ <router-view/>
</div>
- <router-view/>
</template>
<style lang="scss">
+html,
+body {
+ margin: 0;
+ padding: 0;
+}
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
-}
-
-#nav {
- padding: 30px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ flex-direction: column;
+ height: 100vh;
+ width: 100vw;
+ }
- a {
- font-weight: bold;
- color: #2c3e50;
-
- &.router-link-exact-active {
- color: #42b983;
- }
- }
-}
</style>
+++ /dev/null
-<template>
- <div class="hello">
- <h1>{{ msg }}</h1>
- <p>
- For a guide and recipes on how to configure / customize this project,<br>
- check out the
- <a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
- </p>
- <h3>Installed CLI Plugins</h3>
- <ul>
- <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
- <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-router" target="_blank" rel="noopener">router</a></li>
- <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-vuex" target="_blank" rel="noopener">vuex</a></li>
- <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
- <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-unit-jest" target="_blank" rel="noopener">unit-jest</a></li>
- <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-typescript" target="_blank" rel="noopener">typescript</a></li>
- </ul>
- <h3>Essential Links</h3>
- <ul>
- <li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
- <li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
- <li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
- <li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
- <li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
- </ul>
- <h3>Ecosystem</h3>
- <ul>
- <li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
- <li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
- <li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
- <li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
- <li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
- </ul>
- </div>
-</template>
-
-<script lang="ts">
-import { defineComponent } from 'vue';
-
-export default defineComponent({
- name: 'HelloWorld',
- props: {
- msg: String,
- },
-});
-</script>
-
-<!-- Add "scoped" attribute to limit CSS to this component only -->
-<style scoped lang="scss">
-h3 {
- margin: 40px 0 0;
-}
-ul {
- list-style-type: none;
- padding: 0;
-}
-li {
- display: inline-block;
- margin: 0 10px;
-}
-a {
- color: #42b983;
-}
-</style>
--- /dev/null
+<template>
+ <g
+ :id="item.id"
+ :class="item.modifier"
+ :transform="startingOffset"
+ >
+ <rect
+ ref="bubble"
+ id="#bubble"
+ x="30"
+ y="10"
+ width="196"
+ height="63"
+ rx="20"
+ :fill="bubbleFill"
+ />
+ <text
+ font-size="14"
+ font-family="SF Pro"
+ id="#message"
+ ref="content"
+ :fill="textFill"
+ >
+ <tspan
+ dy="16"
+ x="0"
+ v-for="(item, index) in textArr"
+ :key="index"
+ >
+ {{ item }}
+ </tspan>
+ </text>
+ <g :transform="signature">
+ <image
+ xlink:href="profile.png"
+ width="29"
+ height="29"
+ fill="#b5b5b5"
+ clip-path="url(#clip)"
+ />
+ <text
+ transform="translate(36, 17)"
+ fill="#888"
+ font-size="10"
+ font-family="SFCompactDisplay-Bold, SF Compact Display"
+ font-weight="700"
+ >
+ <tspan v-if="item.outgoing">You to</tspan>
+ <tspan v-else>From</tspan>
+ <tspan xml:space="preserve" fill="#000"> {{ item.signature }}</tspan>
+ </text>
+ </g>
+ </g>
+</template>
+
+<script lang="ts">
+import { defineComponent } from 'vue';
+ export default defineComponent({
+ name: "MessageItem",
+ props: {
+ item: {
+ type: Object,
+ required: true
+ },
+ },
+ data() {
+ return {
+ textArr: [],
+ signature: ""
+ };
+ },
+ computed: {
+ textFill() {
+ switch (this.item.modifier) {
+ case "ai":
+ return "#fff";
+ default:
+ return "#000";
+ }
+ },
+ bubbleFill() {
+ switch (this.item.modifier) {
+ case "sf":
+ return "#61b4f4";
+ case "ai":
+ return "#585858";
+ default:
+ return "#fff";
+ }
+ },
+ startingOffset() {
+ switch (this.item.modifier) {
+ case "sf":
+ return "translate(10, 600)";
+ case "ai":
+ return "translate(135, 600)";
+ default:
+ return "translate(20, 600)";
+ }
+ }
+ },
+ async mounted() {
+ await this.createTextBox(this.item.content, 32);
+ await this.adjustRect();
+ this.signaturePosition();
+ },
+ methods: {
+ signaturePosition() {
+ const height = Number(this.$refs.bubble.getAttribute("height"));
+ const p = -10;
+ this.signature = `translate(-10 ${height + p})`;
+ },
+ createTextBox(s, w) {
+ // return tspan elements for text with correct size
+ const wrap = (s, w) =>
+ s.replace(
+ new RegExp(`(?![^\\n]{1,${w}}$)([^\\n]{1,${w}})\\s`, "g"),
+ "$1\n"
+ );
+ this.textArr = wrap(s, w).split("\n");
+ },
+ adjustRect() {
+ // must get dimensions of text box to fit bubble around
+ const padding = 20;
+ const bbox = this.$refs.content.getBBox();
+ const bubble = this.$refs.bubble;
+ bubble.setAttribute("x", bbox.x - padding);
+ bubble.setAttribute("y", bbox.y - padding);
+ bubble.setAttribute("width", bbox.width + 2 * padding);
+ bubble.setAttribute("height", bbox.height + 2 * padding);
+ }
+ }
+ });
+</script>
+
+<style></style>
--- /dev/null
+const Messages = [
+ {
+ content:
+ "I can be there at 5 pm tomorrow to greet you at a Chick file with my almond and chive salad.",
+ signature: "Tommy McConville",
+ outgoing: true,
+ modifier: "sf",
+ imgURL: "../assets/logo.png",
+ id: "1"
+ },
+ {
+ content: "Sounds good, see you Thursday.",
+ signature: "Josie Wright",
+ outgoing: false,
+ modifier: "fr",
+ imgURL: "@/assets/logo.png",
+ id: "2"
+ },
+ {
+ content: "Hey Anna, did you get the paper done?",
+ signature: "Tommy McConville",
+ outgoing: false,
+ modifier: "fr",
+ imgURL: "@/assets/logo.png",
+ id: "3"
+ },
+ {
+ content: "Yes posting it online soon.",
+ signature: "Tommy McConville",
+ outgoing: true,
+ modifier: "sf",
+ imgURL: "../../assets/logo.png",
+ id: "4"
+ },
+ {
+ content: "Sweet, thanks!",
+ signature: "Tommy McConville",
+ outgoing: false,
+ modifier: "fr",
+ imgURL: "../../assets/logo.png",
+ id: "5"
+ },
+ {
+ content: "Hey do you know Enrique Hernandez?",
+ signature: "Crimata AI",
+ outgoing: false,
+ modifier: "ai",
+ imgURL: "../../assets/logo.png",
+ id: "6"
+ }
+];
+export default Messages;
--- /dev/null
+<template>
+ <svg
+ id="messenger"
+ version="1.1"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ >
+ <defs>
+ <linearGradient
+ id="linear-gradient"
+ x1="0.5"
+ y1="-1.438"
+ x2="0.5"
+ y2="0.633"
+ gradientUnits="objectBoundingBox"
+ >
+ <stop offset="0" stop-color="#fff33b" stop-opacity="0" />
+ <stop offset="0.152" stop-color="#ffde46" stop-opacity="0.141" />
+ <stop offset="0.467" stop-color="#ffa764" stop-opacity="0.435" />
+ <stop offset="0.581" stop-color="#ff916f" stop-opacity="0.541" />
+ <stop offset="1" stop-color="#ff5782" />
+ </linearGradient>
+ <linearGradient
+ id="linear-gradient-2"
+ x1="0.498"
+ y1="0.728"
+ x2="0.498"
+ y2="-0.433"
+ gradientUnits="objectBoundingBox"
+ >
+ <stop offset="0" stop-color="#f7cf83" />
+ <stop offset="1" stop-color="#fff" />
+ </linearGradient>
+ <rect id="rect" width="29" height="29" rx="10" />
+ <clipPath id="clip">
+ <use xlink:href="#rect" />
+ </clipPath>
+ </defs>
+ <g id="cardsDiv">
+ <g
+ v-for="(item, index) in renderArr"
+ :key="index"
+ id="cards"
+ transform="translate(0, 0)"
+ >
+ <transition
+ appear
+ v-on:before-appear="beforeEnter"
+ v-on:appear="enter"
+ v-on:appear-cancelled="leave"
+ >
+ <MessageItem
+ :v-if="item"
+ :item="item"
+ :key="index"
+ />
+ </transition>
+ </g>
+ </g>
+ <g id="titlebar" transform="translate(0, 0)">
+ <g data-name="Group 73" transform="translate(20 20)">
+ <ellipse
+ id="Oval"
+ cx="8.134"
+ cy="8.134"
+ rx="8.134"
+ ry="8.134"
+ transform="translate(0 0)"
+ fill="url(#linear-gradient)"
+ />
+ <ellipse
+ id="Oval-2"
+ data-name="Oval"
+ cx="8.134"
+ cy="8.134"
+ rx="8.134"
+ ry="8.134"
+ transform="translate(27 0)"
+ fill="url(#linear-gradient-2)"
+ />
+ </g>
+ </g>
+ </svg>
+</template>
+
+<script lang="ts">
+import { defineComponent, inject } from "vue";
+import MessageItem from './UIDetails/messageItem.vue';
+// @ts-ignore
+import {Messages} from "./UIDetails/messages.js";
+ export default defineComponent({
+ name: 'UIindex',
+ components: { MessageItem },
+ setup() {
+ const anime = inject('animejs');
+ let timeline;
+ console.log(Messages);
+ const setTimeLine = () => {
+ timeline = anime.timeline({ loop: true });
+ }
+ setTimeLine();
+ return {
+ timeline
+ }
+ },
+ // data() {
+ // return {
+ // renderArr: [],
+ // messages: [],
+ // timeline: null,
+ // msgOffset: {
+ // x: null,
+ // y: null
+ // },
+ // prevCardH: 0
+ // };
+ // },
+ // mounted() {
+ // this.setTimeLine();
+ // this.runAnim();
+ // },
+ // methods: {
+ // setTimeLine() {
+ // this.timeline = this.anime.timeline({ loop: true });
+ // },
+ // runAnim() {
+ // this.messages = Messages;
+ // for (let i = 0; i < this.messages.length; i++) {
+ // this.renderMsg(i);
+ // }
+ // },
+ // renderMsg(i) {
+ // setTimeout(() => {
+ // this.renderArr.push(this.messages[i]);
+ // }, 2000);
+ // },
+ // async beforeEnter(el) {},
+ // async enter(el, done) {
+ // const winW = document.getElementById("messenger").clientWidth;
+ // const modifier = el.className.baseVal.substring(0, 2);
+ // const msg = await document.getElementById(el.id);
+ // const rect = msg.getBoundingClientRect();
+ // const msgW = rect.width;
+ // const msgH = rect.height;
+ // const paddingLeft = 40;
+ // const cardsDiv = await document.getElementById("cardsDiv");
+ // const cdBox = cardsDiv.getBBox();
+ //
+ // if (this.prevCardH === 0) {
+ // this.msgOffset.y += cdBox.height;
+ // } else if (this.prevCardH > msgH) {
+ // // cardsDiv is offset by 17.5
+ // this.msgOffset.y += this.prevCardH + msgH / 2 + 17.5;
+ // } else {
+ // this.msgOffset.y += cdBox.height - 20;
+ // }
+ // this.prevCardH = msgH;
+ //
+ // switch (modifier) {
+ // case "sf":
+ // this.msgOffset.x = winW - msgW;
+ // break;
+ // case "ai":
+ // this.msgOffset.x = (winW - msgW) / 2;
+ // break;
+ // default:
+ // this.msgOffset.x = paddingLeft;
+ // }
+ //
+ // const translateUp = `translate(${this.msgOffset.x} ${this.msgOffset.y})`;
+ // const translateDown = `translate(${this.msgOffset.x} ${this.msgOffset.y +
+ // 5})`;
+ // this.timeline
+ // .add({
+ // targets: el,
+ // transform: translateUp,
+ // easing: "easeInOutQuad",
+ // duration: 1000
+ // })
+ // .add({
+ // targets: el,
+ // transform: translateDown,
+ // easing: "easeInOutQuad",
+ // duration: 500,
+ // offset: 1000
+ // });
+ // done();
+ // },
+ // leave(el, done) {
+ // console.log("leaving");
+ // }
+ // }
+
+ });
+</script>
+
+<style lang="scss" scoped>
+#messenger {
+ width: 350px;
+ height: 500px;
+ background-color: #E6E6E6;
+ box-shadow: 0px 3px 10px 0px rgba(0, 0, 0, 0.3);
+ border-radius: 20px;
+}
+</style>
-import { createApp } from "vue";
+import { createApp, provide, inject } from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";
+import anime from "animejs/lib/anime.es.js";
+
createApp(App)
.use(store)
.use(router)
+ .provide("animejs", anime)
.mount("#app");
--- /dev/null
+import { provide, inject } from "vue";
+
+const animeSymbol = Symbol();
+
+export function provideAnime(anime: any) {
+ provide(animeSymbol, anime);
+}
+
+export function useAnime() {
+ const anime = inject(animeSymbol);
+ if (!anime) {
+ console.log("Error! Failed to provide AnimeJS");
+ // throw error, no store provided
+ }
+ return anime;
+}
-import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
-import Home from '../views/Home.vue'
+import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";
+import HomeIndex from "../views/home/index.vue";
const routes: Array<RouteRecordRaw> = [
{
- path: '/',
- name: 'Home',
- component: Home
- },
- {
- path: '/about',
- name: 'About',
- // route level code-splitting
- // this generates a separate chunk (about.[hash].js) for this route
- // which is lazy-loaded when the route is visited.
- component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
+ path: "/",
+ name: "Home",
+ component: HomeIndex
}
-]
+];
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes
-})
+});
-export default router
+export default router;
-declare module '*.vue' {
- import { defineComponent } from 'vue'
- const component: ReturnType<typeof defineComponent>
- export default component
+declare module "*.vue" {
+ import { defineComponent } from "vue";
+ const component: ReturnType<typeof defineComponent>;
+ export default component;
}
+
+declare module "animejs/lib/anime.es.js";
+++ /dev/null
-<template>
- <div class="about">
- <h1>This is an about page</h1>
- </div>
-</template>
+++ /dev/null
-<template>
- <div class="home">
- <img alt="Vue logo" src="../assets/logo.png">
- <HelloWorld msg="Welcome to Your Vue.js + TypeScript App"/>
- </div>
-</template>
-
-<script lang="ts">
-import { defineComponent } from 'vue';
-import HelloWorld from '@/components/HelloWorld.vue'; // @ is an alias to /src
-
-export default defineComponent({
- name: 'Home',
- components: {
- HelloWorld,
- },
- async mounted(){
- await import("../../crate/pkg").then(async module => {
- const result = await module.add(1, 2);
- console.log('testing rust', result)
- })
- }
-});
-</script>
--- /dev/null
+<template>
+ Hello from vue home view
+ <!-- <UIindex /> -->
+
+</template>
+
+<script lang="ts">
+ import { defineComponent, onMounted } from 'vue';
+ import UIindex from "@/components/UI/index.vue";
+
+ export default defineComponent({
+ name: "HomeIndex",
+ components: { UIindex },
+ setup() {
+ let result;
+ const getCwasm = async () => {
+ await import('../../../crate/pkg').then(async module => {
+ result = await module.add(1, 2);
+ console.log(result);
+ });
+ }
+ onMounted(() => {
+ getCwasm();
+ })
+ },
+ });
+
+</script>
+
+<style></style>
dependencies:
defer-to-connect "^2.0.0"
+"@types/animejs@^3.1.2":
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/@types/animejs/-/animejs-3.1.2.tgz#93289a902b0b9bfac3020d29413139dcca6acdbc"
+ integrity sha512-GyyuoztWbZMErx9brJQChvvfeMd5vplWU/H6BYVl7JUcLoMaDOVxlqF3d4ypB7TzXnbgnMSykGmjAVVRsvhHhQ==
+
"@types/anymatch@*":
version "1.3.1"
resolved "https://registry.yarnpkg.com/@types/anymatch/-/anymatch-1.3.1.tgz#336badc1beecb9dacc38bea2cf32adf627a8421a"
resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5"
integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=
+animejs@^3.2.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/animejs/-/animejs-3.2.0.tgz#2daea7365983249022cc454fa726acdb4a84345d"
+ integrity sha512-zhtGl5cS0G2f5DfciMO8uwWpnx06nfFnHlXYYXHBazHep1Lyd6kEtBQP+9hpYKE0dBZjIigHp9VpMO95ZfXQJQ==
+
ansi-align@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.0.tgz#b536b371cf687caaef236c18d3e21fe3797467cb"