Skip to content

Commit 1bb20ac

Browse files
docs(examples): add Vue 3 example (#576)
1 parent 2b37a56 commit 1bb20ac

File tree

12 files changed

+420
-61
lines changed

12 files changed

+420
-61
lines changed

.codesandbox/ci.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919
"/examples/recently-viewed-items",
2020
"/examples/starter-algolia",
2121
"/examples/starter",
22-
"/examples/voice-search"
22+
"/examples/voice-search",
23+
"/examples/vue"
2324
],
2425
"node": "14"
2526
}

examples/vue/README.md

Whitespace-only changes.

examples/vue/env.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// Parcel picks the `source` field of the monorepo packages and thus doesn't
2+
// apply the Babel config. We therefore need to manually override the constants
3+
// in the app, as well as the React pragmas.
4+
// See https://twitter.com/devongovett/status/1134231234605830144
5+
(global as any).__DEV__ = process.env.NODE_ENV !== 'production';
6+
(global as any).__TEST__ = false;

examples/vue/favicon.png

43.1 KB
Loading

examples/vue/index.html

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<html lang="en">
2+
<head>
3+
<meta charset="UTF-8" />
4+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
5+
6+
<link rel="shortcut icon" href="favicon.png" type="image/x-icon" />
7+
<link rel="stylesheet" href="style.css" />
8+
9+
<title>Vue | Autocomplete</title>
10+
</head>
11+
12+
<body>
13+
<div id="app"></div>
14+
15+
<script src="env.ts"></script>
16+
<script src="src/main.js"></script>
17+
</body>
18+
</html>

examples/vue/package.json

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"name": "@algolia/autocomplete-example-vue",
3+
"description": "Autocomplete with Vue",
4+
"version": "1.0.0",
5+
"private": true,
6+
"license": "MIT",
7+
"scripts": {
8+
"build": "parcel build index.html",
9+
"start": "parcel index.html"
10+
},
11+
"dependencies": {
12+
"@algolia/autocomplete-js": "1.0.0",
13+
"@algolia/autocomplete-theme-classic": "1.0.0",
14+
"algoliasearch": "4.9.1",
15+
"vue": "3.0.11"
16+
},
17+
"devDependencies": {
18+
"@algolia/client-search": "4.9.1",
19+
"@parcel/transformer-vue": "2.0.0-beta.2",
20+
"parcel": "2.0.0-beta.2"
21+
},
22+
"keywords": [
23+
"algolia",
24+
"autocomplete",
25+
"javascript"
26+
]
27+
}

examples/vue/src/App.vue

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<template>
2+
<div class="container">
3+
<div id="autocomplete" />
4+
</div>
5+
</template>
6+
7+
<script>
8+
import { h, Fragment, render, onMounted } from 'vue';
9+
import { autocomplete, getAlgoliaResults } from '@algolia/autocomplete-js';
10+
import algoliasearch from 'algoliasearch/lite';
11+
12+
import '@algolia/autocomplete-theme-classic';
13+
14+
import { createElement } from './adapter';
15+
import ProductItem from './ProductItem.vue';
16+
17+
const appId = 'latency';
18+
const apiKey = '6be0576ff61c053d5f9a3225e2a90f76';
19+
const searchClient = algoliasearch(appId, apiKey);
20+
21+
export default {
22+
name: 'App',
23+
setup() {
24+
onMounted(() => {
25+
autocomplete({
26+
container: '#autocomplete',
27+
placeholder: 'Search',
28+
getSources({ query }) {
29+
return [
30+
{
31+
sourceId: 'products',
32+
getItems() {
33+
return getAlgoliaResults({
34+
searchClient,
35+
queries: [
36+
{
37+
indexName: 'instant_search',
38+
query,
39+
},
40+
],
41+
});
42+
},
43+
templates: {
44+
item({ item, components }) {
45+
return (
46+
<ProductItem item={item} highlight={components.Highlight} />
47+
);
48+
},
49+
},
50+
},
51+
];
52+
},
53+
renderer: {
54+
createElement,
55+
Fragment,
56+
},
57+
render({ children }, root) {
58+
render(children, root);
59+
},
60+
});
61+
});
62+
},
63+
};
64+
</script>
65+
66+
<style>
67+
.container {
68+
margin: 0 auto;
69+
max-width: 640px;
70+
width: 100%;
71+
}
72+
</style>

examples/vue/src/ProductItem.vue

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<template>
2+
<div class="aa-ItemWrapper">
3+
<div class="aa-ItemContent">
4+
<div class="aa-ItemIcon aa-ItemIcon--picture aa-ItemIcon--alignTop">
5+
<img :src="item.image" :alt="item.name" width="40" height="40" />
6+
</div>
7+
<div className="aa-ItemContentBody">
8+
<div class="aa-ItemContentTitle">
9+
<component :is="highlight" :hit="item" attribute="name" />
10+
</div>
11+
<div class="aa-ItemContentDescription">
12+
By <strong>{{ item.brand }}</strong> in
13+
<strong>{{ item.categories[0] }}</strong>
14+
</div>
15+
</div>
16+
</div>
17+
<div class="aa-ItemActions">
18+
<button
19+
class="aa-ItemActionButton aa-TouchOnly aa-ActiveOnly"
20+
type="button"
21+
title="Select"
22+
>
23+
<svg fill="currentColor" viewBox="0 0 24 24" width="20" height="20">
24+
<path
25+
d="M18.984 6.984h2.016v6h-15.188l3.609 3.609-1.406 1.406-6-6 6-6 1.406 1.406-3.609 3.609h13.172v-4.031z"
26+
/>
27+
</svg>
28+
</button>
29+
<button
30+
class="aa-ItemActionButton"
31+
type="button"
32+
title="Add to cart"
33+
@click="onAddToCart"
34+
>
35+
<svg viewBox="0 0 24 24" width="18" height="18" fill="currentColor">
36+
<path
37+
d="M19 5h-14l1.5-2h11zM21.794 5.392l-2.994-3.992c-0.196-0.261-0.494-0.399-0.8-0.4h-12c-0.326 0-0.616 0.156-0.8 0.4l-2.994 3.992c-0.043 0.056-0.081 0.117-0.111 0.182-0.065 0.137-0.096 0.283-0.095 0.426v14c0 0.828 0.337 1.58 0.879 2.121s1.293 0.879 2.121 0.879h14c0.828 0 1.58-0.337 2.121-0.879s0.879-1.293 0.879-2.121v-14c0-0.219-0.071-0.422-0.189-0.585-0.004-0.005-0.007-0.010-0.011-0.015zM4 7h16v13c0 0.276-0.111 0.525-0.293 0.707s-0.431 0.293-0.707 0.293h-14c-0.276 0-0.525-0.111-0.707-0.293s-0.293-0.431-0.293-0.707zM15 10c0 0.829-0.335 1.577-0.879 2.121s-1.292 0.879-2.121 0.879-1.577-0.335-2.121-0.879-0.879-1.292-0.879-2.121c0-0.552-0.448-1-1-1s-1 0.448-1 1c0 1.38 0.561 2.632 1.464 3.536s2.156 1.464 3.536 1.464 2.632-0.561 3.536-1.464 1.464-2.156 1.464-3.536c0-0.552-0.448-1-1-1s-1 0.448-1 1z"
38+
/>
39+
</svg>
40+
</button>
41+
</div>
42+
</div>
43+
</template>
44+
45+
<script lang="ts">
46+
export default {
47+
props: {
48+
item: Object,
49+
highlight: Function,
50+
},
51+
setup() {
52+
function onAddToCart(event) {
53+
event.preventDefault();
54+
event.stopPropagation();
55+
56+
console.log('Add to cart');
57+
}
58+
59+
return {
60+
onAddToCart,
61+
};
62+
},
63+
};
64+
</script>

examples/vue/src/adapter.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { h } from 'vue';
2+
3+
export function createElement(type, props, ...children) {
4+
const adaptedProps = Object.entries(props || {}).reduce(
5+
(acc, [key, value]) => {
6+
// Vue 3 accepts lower-case event names so we need to transform props like
7+
// `onMouseMove` to `onMousemove`.
8+
const property =
9+
key[0] === 'o' && key[1] === 'n'
10+
? key.slice(0, 3) + key.slice(3).toLowerCase()
11+
: key;
12+
13+
acc[property] = value;
14+
return acc;
15+
},
16+
{}
17+
);
18+
19+
return h(type, adaptedProps, ...children);
20+
}

examples/vue/src/main.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { createApp } from 'vue';
2+
3+
import App from './App.vue';
4+
5+
createApp(App).mount('#app');

examples/vue/style.css

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
* {
2+
box-sizing: border-box;
3+
}
4+
5+
body {
6+
background-color: rgb(244, 244, 249);
7+
color: rgb(65, 65, 65);
8+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
9+
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
10+
sans-serif;
11+
-webkit-font-smoothing: antialiased;
12+
-moz-osx-font-smoothing: grayscale;
13+
padding: 1rem;
14+
}

0 commit comments

Comments
 (0)