Skip to content

Commit dff4c1d

Browse files
committed
feat: first implementation in playground
1 parent 9845fac commit dff4c1d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+1594
-0
lines changed

.editorconfig

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
root = true
2+
3+
[*]
4+
indent_size = 2
5+
indent_style = space
6+
end_of_line = lf
7+
charset = utf-8
8+
trim_trailing_whitespace = true
9+
insert_final_newline = true
10+
11+
[*.md]
12+
trim_trailing_whitespace = false

.eslintignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
dist
2+
node_modules

.eslintrc

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"root": true,
3+
"extends": ["@nuxt/eslint-config"]
4+
}

.gitignore

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# Dependencies
2+
node_modules
3+
4+
# Logs
5+
*.log*
6+
7+
# Temp directories
8+
.temp
9+
.tmp
10+
.cache
11+
12+
# Yarn
13+
**/.yarn/cache
14+
**/.yarn/*state*
15+
16+
# Generated dirs
17+
dist
18+
19+
# Nuxt
20+
.nuxt
21+
.output
22+
.data
23+
.vercel_build_output
24+
.build-*
25+
.netlify
26+
27+
# Env
28+
.env
29+
30+
# Testing
31+
reports
32+
coverage
33+
*.lcov
34+
.nyc_output
35+
36+
# VSCode
37+
.vscode/*
38+
!.vscode/settings.json
39+
!.vscode/tasks.json
40+
!.vscode/launch.json
41+
!.vscode/extensions.json
42+
!.vscode/*.code-snippets
43+
44+
# Intellij idea
45+
*.iml
46+
.idea
47+
48+
# OSX
49+
.DS_Store
50+
.AppleDouble
51+
.LSOverride
52+
.AppleDB
53+
.AppleDesktop
54+
Network Trash Folder
55+
Temporary Items
56+
.apdisk

.npmrc

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
shamefully-hoist=true
2+
strict-peer-dependencies=false

bun.lockb

373 KB
Binary file not shown.

package.json

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
{
2+
"name": "nuxt-swiftsearch",
3+
"version": "1.0.0",
4+
"description": "My new Nuxt module",
5+
"repository": "your-org/my-module",
6+
"license": "MIT",
7+
"type": "module",
8+
"exports": {
9+
".": {
10+
"types": "./dist/types.d.ts",
11+
"import": "./dist/module.mjs",
12+
"require": "./dist/module.cjs"
13+
}
14+
},
15+
"main": "./dist/module.cjs",
16+
"types": "./dist/types.d.ts",
17+
"files": [
18+
"dist"
19+
],
20+
"scripts": {
21+
"prepack": "nuxt-module-build build",
22+
"dev": "nuxi dev playground",
23+
"dev:build": "nuxi build playground",
24+
"dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground",
25+
"release": "npm run lint && npm run test && npm run prepack && changelogen --release && npm publish && git push --follow-tags",
26+
"lint": "eslint .",
27+
"test": "vitest run",
28+
"test:watch": "vitest watch"
29+
},
30+
"dependencies": {
31+
"@nuxt/kit": "^3.10.1"
32+
},
33+
"devDependencies": {
34+
"@nuxt/devtools": "latest",
35+
"@nuxt/eslint-config": "^0.2.0",
36+
"@nuxt/module-builder": "^0.5.5",
37+
"@nuxt/schema": "^3.10.1",
38+
"@nuxt/test-utils": "^3.11.0",
39+
"@types/node": "^20.11.16",
40+
"algoliasearch": "^4.22.1",
41+
"changelogen": "^0.5.5",
42+
"eslint": "^8.56.0",
43+
"instantsearch.js": "^4.64.3",
44+
"nuxt": "^3.10.1",
45+
"qs": "^6.11.2",
46+
"typescript": "^5.3.3",
47+
"vitest": "^1.2.2"
48+
}
49+
}

playground/app.vue

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<template>
2+
<div>
3+
<NuxtLayout> <NuxtPage /> </NuxtLayout>
4+
</div>
5+
</template>
6+
7+
<script setup></script>

playground/app/router.options.ts

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import type { RouterConfig } from "@nuxt/schema";
2+
import qs from "qs";
3+
4+
// https://router.vuejs.org/api/interfaces/routeroptions.html
5+
export default <RouterConfig>{
6+
parseQuery: qs.parse,
7+
stringifyQuery: qs.stringify,
8+
};

playground/bun.lockb

297 KB
Binary file not shown.
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<template>
2+
<div :class="suit()">
3+
<slot v-bind="{ searchParameters, refine }"></slot>
4+
</div>
5+
</template>
6+
7+
<script setup lang="ts">
8+
const { state, widgetParams } = useWidget("configure");
9+
10+
const refine = computed(() => state.value?.refine);
11+
12+
const searchParameters = computed(() => {
13+
return widgetParams.value?.searchParameters;
14+
});
15+
16+
const suit = useSuit("Configure");
17+
</script>
18+
19+
<style scoped></style>
+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<template>
2+
<AisHighlighter
3+
:hit="hit"
4+
:attribute="attribute"
5+
:highlighted-tag-name="highlightedTagName"
6+
:suit="suit"
7+
highlight-property="_highlightResult"
8+
pre-tag="<mark>"
9+
post-tag="</mark>"
10+
/>
11+
</template>
12+
13+
<script setup lang="ts">
14+
import type { Hit } from "instantsearch.js";
15+
16+
const suit = useSuit("Highlight");
17+
withDefaults(
18+
defineProps<{
19+
hit: Hit;
20+
attribute: string;
21+
highlightedTagName?: string;
22+
}>(),
23+
{
24+
highlightedTagName: "mark",
25+
},
26+
);
27+
</script>
+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<template>
2+
<span :class="suit()">
3+
<component
4+
v-for="({ value, isHighlighted }, index) in parsedHighlights as {
5+
value: string | undefined;
6+
isHighlighted: boolean;
7+
}[]"
8+
:class="[isHighlighted && suit('highlighted')]"
9+
:key="index"
10+
:is="isHighlighted ? highlightedTagName : 'span'"
11+
>{{ value }}</component
12+
>
13+
</span>
14+
</template>
15+
16+
<script setup lang="ts">
17+
import type { Hit } from "instantsearch.js";
18+
19+
const props = withDefaults(
20+
defineProps<{
21+
hit: Hit;
22+
attribute: string;
23+
highlightedTagName: string;
24+
highlightProperty: string;
25+
preTag: string;
26+
postTag: string;
27+
suit: (n?: string) => string;
28+
}>(),
29+
{
30+
highlightedTagName: "mark",
31+
},
32+
);
33+
const parsedHighlights = computed(() => {
34+
return parseAlgoliaHit({
35+
attribute: props.attribute,
36+
hit: props.hit,
37+
highlightProperty: props.highlightProperty,
38+
preTag: props.preTag,
39+
postTag: props.postTag,
40+
});
41+
});
42+
</script>

playground/components/AisIndex.vue

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<template>
2+
<div>
3+
<slot />
4+
</div>
5+
</template>
6+
7+
<script setup lang="ts">
8+
const props = defineProps<{
9+
index: string;
10+
}>();
11+
12+
provide("index", props.index);
13+
</script>
+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
<template>
2+
<div v-if="state && state.results" :class="suit()">
3+
<slot
4+
v-if="showPrevious"
5+
name="loadPrevious"
6+
:refine-previous="refinePrevious"
7+
:page="state.results.page"
8+
:is-first-page="state.isFirstPage"
9+
>
10+
<button
11+
:class="[
12+
suit('loadPrevious'),
13+
state.isFirstPage && suit('loadPrevious', 'disabled'),
14+
]"
15+
:disabled="state.isFirstPage"
16+
@click="refinePrevious()"
17+
>
18+
Show previous results
19+
</button>
20+
</slot>
21+
22+
<slot
23+
:items="items"
24+
:results="state.results"
25+
:is-last-page="state.isLastPage"
26+
:refine-previous="refinePrevious"
27+
:refine-next="refineNext"
28+
:refine="refineNext"
29+
:send-event="state.sendEvent"
30+
>
31+
<ol :class="suit('list')">
32+
<li
33+
v-for="(item, index) in items"
34+
:class="suit('item')"
35+
:key="item.objectID"
36+
@click="state.sendEvent('click:internal', item, 'Hit Clicked')"
37+
@auxclick="state.sendEvent('click:internal', item, 'Hit Clicked')"
38+
>
39+
<slot
40+
name="item"
41+
:item="item"
42+
:index="index"
43+
:send-event="state.sendEvent"
44+
>
45+
objectID: {{ item.name }}, index: {{ index }}
46+
</slot>
47+
</li>
48+
</ol>
49+
50+
<slot
51+
name="loadMore"
52+
:refine-next="refineNext"
53+
:refine="refineNext"
54+
:page="state.results.page"
55+
:is-last-page="state.isLastPage"
56+
>
57+
<button
58+
:class="[
59+
suit('loadMore'),
60+
state.isLastPage && suit('loadMore', 'disabled'),
61+
]"
62+
:disabled="state.isLastPage"
63+
@click="refineNext()"
64+
>
65+
Show more results
66+
</button>
67+
</slot>
68+
</slot>
69+
</div>
70+
</template>
71+
72+
<script setup lang="ts">
73+
const { state, widgetParams } = useWidget("infiniteHits");
74+
75+
const suit = useSuit("infinite-hits");
76+
77+
const showPrevious = computed(() => {
78+
return widgetParams.value?.showPrevious ?? false;
79+
});
80+
81+
const items = computed(() => {
82+
// Fixes InstantSearch.js connectors API: every list
83+
// of things must be called `items`
84+
return state.value?.hits;
85+
});
86+
function refinePrevious() {
87+
state.value?.showPrevious();
88+
}
89+
function refineNext() {
90+
state.value?.showMore();
91+
}
92+
</script>
+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<template>
2+
<div>
3+
<slot />
4+
</div>
5+
</template>
6+
7+
<script setup lang="ts">
8+
import type {
9+
IndexWidget,
10+
InstantSearchOptions,
11+
Widget,
12+
} from "instantsearch.js";
13+
14+
const props = defineProps<{
15+
configuration: InstantSearchOptions;
16+
widgets: Array<Widget | IndexWidget>;
17+
}>();
18+
const { setup, getInstance } = useInstantSearch();
19+
20+
const search = getInstance(props.configuration);
21+
22+
search.value.addWidgets(props.widgets);
23+
24+
// react to widget change
25+
const { widgets: widgetsRef } = toRefs(props);
26+
27+
watch(widgetsRef, (newWidgets, oldWidgets) => {
28+
search.value.removeWidgets(oldWidgets);
29+
search.value.addWidgets(newWidgets);
30+
});
31+
32+
await setup();
33+
</script>
34+
35+
<style scoped></style>

0 commit comments

Comments
 (0)