algolia-experiences 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/algolia-experiences.development.js +28582 -0
- package/dist/algolia-experiences.development.js.map +1 -0
- package/dist/algolia-experiences.production.min.js +3 -0
- package/dist/algolia-experiences.production.min.js.map +1 -0
- package/package.json +4 -1
- package/rollup.config.js +0 -76
- package/src/fake-configuration.ts +0 -283
- package/src/get-information.ts +0 -29
- package/src/render.tsx +0 -250
- package/src/setup-instantsearch.ts +0 -40
- package/src/types.ts +0 -104
- package/src/util.ts +0 -9
- package/src/widgets.ts +0 -51
package/package.json
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "algolia-experiences",
|
|
3
3
|
"license": "MIT",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.2",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"jsdelivr": "dist/algolia-experiences.production.min.js",
|
|
7
7
|
"unpkg": "dist/algolia-experiences.production.min.js",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
8
11
|
"dependencies": {
|
|
9
12
|
"instantsearch.js": "^4.73.2",
|
|
10
13
|
"algoliasearch": "^4.23.2"
|
package/rollup.config.js
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import babel from 'rollup-plugin-babel';
|
|
2
|
-
import commonjs from 'rollup-plugin-commonjs';
|
|
3
|
-
import filesize from 'rollup-plugin-filesize';
|
|
4
|
-
import resolve from 'rollup-plugin-node-resolve';
|
|
5
|
-
import replace from 'rollup-plugin-replace';
|
|
6
|
-
import { uglify } from 'rollup-plugin-uglify';
|
|
7
|
-
|
|
8
|
-
import packageJson from '../../package.json';
|
|
9
|
-
|
|
10
|
-
const version =
|
|
11
|
-
process.env.NODE_ENV === 'production'
|
|
12
|
-
? packageJson.version
|
|
13
|
-
: `UNRELEASED (${new Date().toUTCString()})`;
|
|
14
|
-
const algolia = '© Algolia, Inc. and contributors; MIT License';
|
|
15
|
-
const link = 'https://github.com/algolia/instantsearch';
|
|
16
|
-
const license = `/*! algolia-experiences ${version} | ${algolia} | ${link} */`;
|
|
17
|
-
|
|
18
|
-
const plugins = [
|
|
19
|
-
resolve({
|
|
20
|
-
browser: true,
|
|
21
|
-
preferBuiltins: false,
|
|
22
|
-
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json'],
|
|
23
|
-
}),
|
|
24
|
-
babel({
|
|
25
|
-
rootMode: 'upward',
|
|
26
|
-
runtimeHelpers: true,
|
|
27
|
-
exclude: /node_modules|algoliasearch-helper/,
|
|
28
|
-
extensions: ['.js', '.ts', '.tsx'],
|
|
29
|
-
}),
|
|
30
|
-
commonjs(),
|
|
31
|
-
filesize({
|
|
32
|
-
showMinifiedSize: false,
|
|
33
|
-
showGzippedSize: true,
|
|
34
|
-
}),
|
|
35
|
-
];
|
|
36
|
-
|
|
37
|
-
const createConfiguration = ({ mode, filename }) => ({
|
|
38
|
-
input: 'src/index.ts',
|
|
39
|
-
output: {
|
|
40
|
-
file: `dist/${filename}`,
|
|
41
|
-
name: 'instantsearch',
|
|
42
|
-
format: 'umd',
|
|
43
|
-
banner: license,
|
|
44
|
-
sourcemap: true,
|
|
45
|
-
},
|
|
46
|
-
onwarn(warning, warn) {
|
|
47
|
-
if (warning.code === 'CIRCULAR_DEPENDENCY')
|
|
48
|
-
throw new Error(warning.message);
|
|
49
|
-
|
|
50
|
-
warn(warning);
|
|
51
|
-
},
|
|
52
|
-
plugins: [
|
|
53
|
-
...plugins,
|
|
54
|
-
replace({
|
|
55
|
-
__DEV__: mode === 'development',
|
|
56
|
-
'process.env.NODE_ENV': JSON.stringify('production'),
|
|
57
|
-
}),
|
|
58
|
-
mode === 'production' &&
|
|
59
|
-
uglify({
|
|
60
|
-
output: {
|
|
61
|
-
preamble: license,
|
|
62
|
-
},
|
|
63
|
-
}),
|
|
64
|
-
].filter(Boolean),
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
export default [
|
|
68
|
-
createConfiguration({
|
|
69
|
-
mode: 'development',
|
|
70
|
-
filename: 'algolia-experiences.development.js',
|
|
71
|
-
}),
|
|
72
|
-
createConfiguration({
|
|
73
|
-
mode: 'production',
|
|
74
|
-
filename: 'algolia-experiences.production.min.js',
|
|
75
|
-
}),
|
|
76
|
-
];
|
|
@@ -1,283 +0,0 @@
|
|
|
1
|
-
import type { Configuration } from './types';
|
|
2
|
-
|
|
3
|
-
const CONFIGURATION_OBJECT: Record<string, Configuration> = {
|
|
4
|
-
qsdfqsdf: {
|
|
5
|
-
id: 'qsdfqsdf',
|
|
6
|
-
indexName: 'instant_search',
|
|
7
|
-
children: [
|
|
8
|
-
{
|
|
9
|
-
type: 'ais.searchBox',
|
|
10
|
-
parameters: {},
|
|
11
|
-
},
|
|
12
|
-
{
|
|
13
|
-
type: 'columns',
|
|
14
|
-
children: [
|
|
15
|
-
[
|
|
16
|
-
{
|
|
17
|
-
type: 'ais.refinementList',
|
|
18
|
-
parameters: {
|
|
19
|
-
attribute: 'brand',
|
|
20
|
-
header: 'Brand',
|
|
21
|
-
},
|
|
22
|
-
},
|
|
23
|
-
],
|
|
24
|
-
[
|
|
25
|
-
{
|
|
26
|
-
type: 'ais.hits',
|
|
27
|
-
parameters: {},
|
|
28
|
-
children: [
|
|
29
|
-
{
|
|
30
|
-
type: 'span',
|
|
31
|
-
parameters: {
|
|
32
|
-
text: [
|
|
33
|
-
{ type: 'string', value: 'cols: ' },
|
|
34
|
-
{ type: 'highlight', path: ['name'] },
|
|
35
|
-
],
|
|
36
|
-
},
|
|
37
|
-
},
|
|
38
|
-
],
|
|
39
|
-
},
|
|
40
|
-
],
|
|
41
|
-
],
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
type: 'ais.configure',
|
|
45
|
-
parameters: {
|
|
46
|
-
hitsPerPage: 2,
|
|
47
|
-
},
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
type: 'ais.hits',
|
|
51
|
-
parameters: {},
|
|
52
|
-
children: [
|
|
53
|
-
{
|
|
54
|
-
type: 'span',
|
|
55
|
-
parameters: {
|
|
56
|
-
text: [
|
|
57
|
-
{ type: 'string', value: 'one: ' },
|
|
58
|
-
{ type: 'highlight', path: ['name'] },
|
|
59
|
-
],
|
|
60
|
-
},
|
|
61
|
-
},
|
|
62
|
-
],
|
|
63
|
-
},
|
|
64
|
-
],
|
|
65
|
-
},
|
|
66
|
-
'other-one': {
|
|
67
|
-
id: 'other-one',
|
|
68
|
-
indexName: 'instant_search',
|
|
69
|
-
children: [
|
|
70
|
-
{
|
|
71
|
-
type: 'ais.configure',
|
|
72
|
-
parameters: {
|
|
73
|
-
hitsPerPage: 3,
|
|
74
|
-
},
|
|
75
|
-
},
|
|
76
|
-
{
|
|
77
|
-
type: 'ais.hits',
|
|
78
|
-
parameters: {},
|
|
79
|
-
children: [
|
|
80
|
-
{
|
|
81
|
-
type: 'span',
|
|
82
|
-
parameters: {
|
|
83
|
-
text: [
|
|
84
|
-
{ type: 'string', value: 'other: ' },
|
|
85
|
-
{ type: 'attribute', path: ['name'] },
|
|
86
|
-
],
|
|
87
|
-
},
|
|
88
|
-
},
|
|
89
|
-
],
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
type: 'ais.pagination',
|
|
93
|
-
parameters: {
|
|
94
|
-
padding: 2,
|
|
95
|
-
},
|
|
96
|
-
},
|
|
97
|
-
{
|
|
98
|
-
type: 'ais.trendingItems',
|
|
99
|
-
parameters: { limit: 4 },
|
|
100
|
-
children: [
|
|
101
|
-
{
|
|
102
|
-
type: 'span',
|
|
103
|
-
parameters: {
|
|
104
|
-
text: [
|
|
105
|
-
{ type: 'string', value: 'trending: ' },
|
|
106
|
-
{ type: 'attribute', path: ['name'] },
|
|
107
|
-
],
|
|
108
|
-
},
|
|
109
|
-
},
|
|
110
|
-
{
|
|
111
|
-
type: 'image',
|
|
112
|
-
parameters: {
|
|
113
|
-
src: [{ type: 'attribute', path: ['image'] }],
|
|
114
|
-
alt: [{ type: 'string', value: '' }],
|
|
115
|
-
},
|
|
116
|
-
},
|
|
117
|
-
],
|
|
118
|
-
},
|
|
119
|
-
],
|
|
120
|
-
},
|
|
121
|
-
'category:audio': {
|
|
122
|
-
id: 'category:audio',
|
|
123
|
-
indexName: 'instant_search',
|
|
124
|
-
children: [
|
|
125
|
-
{
|
|
126
|
-
type: 'ais.configure',
|
|
127
|
-
parameters: {
|
|
128
|
-
hitsPerPage: 9,
|
|
129
|
-
filters: 'categories:"Audio"',
|
|
130
|
-
},
|
|
131
|
-
},
|
|
132
|
-
{
|
|
133
|
-
type: 'columns',
|
|
134
|
-
children: [
|
|
135
|
-
[
|
|
136
|
-
{
|
|
137
|
-
type: 'ais.refinementList',
|
|
138
|
-
parameters: {
|
|
139
|
-
attribute: 'brand',
|
|
140
|
-
header: 'brand',
|
|
141
|
-
collapsed: true,
|
|
142
|
-
searchable: true,
|
|
143
|
-
},
|
|
144
|
-
},
|
|
145
|
-
{
|
|
146
|
-
type: 'ais.refinementList',
|
|
147
|
-
parameters: {
|
|
148
|
-
attribute: 'type',
|
|
149
|
-
header: 'type',
|
|
150
|
-
collapsed: true,
|
|
151
|
-
searchable: true,
|
|
152
|
-
},
|
|
153
|
-
},
|
|
154
|
-
{
|
|
155
|
-
type: 'ais.rangeInput',
|
|
156
|
-
parameters: {
|
|
157
|
-
attribute: 'price',
|
|
158
|
-
header: 'price',
|
|
159
|
-
collapsed: true,
|
|
160
|
-
},
|
|
161
|
-
},
|
|
162
|
-
{
|
|
163
|
-
type: 'ais.toggleRefinement',
|
|
164
|
-
parameters: {
|
|
165
|
-
attribute: 'free_shipping',
|
|
166
|
-
header: 'free shipping',
|
|
167
|
-
collapsed: true,
|
|
168
|
-
},
|
|
169
|
-
},
|
|
170
|
-
],
|
|
171
|
-
[
|
|
172
|
-
{
|
|
173
|
-
type: 'ais.hits',
|
|
174
|
-
parameters: {},
|
|
175
|
-
children: [
|
|
176
|
-
{
|
|
177
|
-
type: 'link',
|
|
178
|
-
parameters: { href: [{ type: 'attribute', path: ['url'] }] },
|
|
179
|
-
children: [
|
|
180
|
-
{
|
|
181
|
-
type: 'image',
|
|
182
|
-
parameters: {
|
|
183
|
-
src: [{ type: 'attribute', path: ['image'] }],
|
|
184
|
-
alt: [{ type: 'string', value: '' }],
|
|
185
|
-
},
|
|
186
|
-
},
|
|
187
|
-
{
|
|
188
|
-
type: 'div',
|
|
189
|
-
parameters: {
|
|
190
|
-
class: [{ type: 'string', value: '__flex' }],
|
|
191
|
-
},
|
|
192
|
-
children: [
|
|
193
|
-
{
|
|
194
|
-
type: 'span',
|
|
195
|
-
parameters: {
|
|
196
|
-
text: [{ type: 'attribute', path: ['name'] }],
|
|
197
|
-
},
|
|
198
|
-
},
|
|
199
|
-
{
|
|
200
|
-
type: 'span',
|
|
201
|
-
parameters: {
|
|
202
|
-
class: [{ type: 'string', value: '__bold' }],
|
|
203
|
-
text: [
|
|
204
|
-
{ type: 'string', value: '$' },
|
|
205
|
-
{ type: 'attribute', path: ['price'] },
|
|
206
|
-
],
|
|
207
|
-
},
|
|
208
|
-
},
|
|
209
|
-
],
|
|
210
|
-
},
|
|
211
|
-
],
|
|
212
|
-
},
|
|
213
|
-
],
|
|
214
|
-
},
|
|
215
|
-
{
|
|
216
|
-
type: 'ais.pagination',
|
|
217
|
-
parameters: {
|
|
218
|
-
padding: 2,
|
|
219
|
-
},
|
|
220
|
-
},
|
|
221
|
-
{
|
|
222
|
-
type: 'ais.trendingItems',
|
|
223
|
-
parameters: {
|
|
224
|
-
limit: 4,
|
|
225
|
-
facetName: 'categories',
|
|
226
|
-
facetValue: 'Audio',
|
|
227
|
-
},
|
|
228
|
-
children: [
|
|
229
|
-
{
|
|
230
|
-
type: 'link',
|
|
231
|
-
parameters: { href: [{ type: 'attribute', path: ['url'] }] },
|
|
232
|
-
children: [
|
|
233
|
-
{
|
|
234
|
-
type: 'image',
|
|
235
|
-
parameters: {
|
|
236
|
-
src: [{ type: 'attribute', path: ['image'] }],
|
|
237
|
-
alt: [{ type: 'string', value: '' }],
|
|
238
|
-
},
|
|
239
|
-
},
|
|
240
|
-
{
|
|
241
|
-
type: 'div',
|
|
242
|
-
parameters: {
|
|
243
|
-
class: [{ type: 'string', value: '__flex' }],
|
|
244
|
-
},
|
|
245
|
-
children: [
|
|
246
|
-
{
|
|
247
|
-
type: 'span',
|
|
248
|
-
parameters: {
|
|
249
|
-
text: [{ type: 'attribute', path: ['name'] }],
|
|
250
|
-
},
|
|
251
|
-
},
|
|
252
|
-
{
|
|
253
|
-
type: 'span',
|
|
254
|
-
parameters: {
|
|
255
|
-
class: [{ type: 'string', value: '__bold' }],
|
|
256
|
-
text: [
|
|
257
|
-
{ type: 'string', value: '$' },
|
|
258
|
-
{ type: 'attribute', path: ['price'] },
|
|
259
|
-
],
|
|
260
|
-
},
|
|
261
|
-
},
|
|
262
|
-
],
|
|
263
|
-
},
|
|
264
|
-
],
|
|
265
|
-
},
|
|
266
|
-
],
|
|
267
|
-
},
|
|
268
|
-
],
|
|
269
|
-
],
|
|
270
|
-
},
|
|
271
|
-
],
|
|
272
|
-
},
|
|
273
|
-
};
|
|
274
|
-
const CONFIGURATION_MAP = new Map<string, Configuration>(
|
|
275
|
-
Object.entries(CONFIGURATION_OBJECT)
|
|
276
|
-
);
|
|
277
|
-
const FAKE_DELAY = 1000;
|
|
278
|
-
|
|
279
|
-
export function fakeFetchConfiguration(ids: string[]) {
|
|
280
|
-
return new Promise((resolve) => setTimeout(resolve, FAKE_DELAY)).then(() =>
|
|
281
|
-
ids.map((id) => CONFIGURATION_MAP.get(id)!).filter(Boolean)
|
|
282
|
-
);
|
|
283
|
-
}
|
package/src/get-information.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
export function getSettings(): { appId: string; apiKey: string } {
|
|
2
|
-
const metaConfiguration = document.querySelector<HTMLMetaElement>(
|
|
3
|
-
'meta[name="instantsearch-configuration"]'
|
|
4
|
-
);
|
|
5
|
-
|
|
6
|
-
if (!metaConfiguration || !metaConfiguration.content) {
|
|
7
|
-
throw new Error('No meta tag found');
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
const { appId, apiKey } = JSON.parse(metaConfiguration.content);
|
|
11
|
-
|
|
12
|
-
if (!appId || !apiKey) {
|
|
13
|
-
throw new Error('Missing appId or apiKey in the meta tag');
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
return { appId, apiKey };
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function getElements() {
|
|
20
|
-
const elements = new Map<string, HTMLElement>();
|
|
21
|
-
document
|
|
22
|
-
.querySelectorAll<HTMLElement>('[data-instantsearch-id]')
|
|
23
|
-
.forEach((element) => {
|
|
24
|
-
const id = element.dataset.instantsearchId!;
|
|
25
|
-
elements.set(id, element);
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
return elements;
|
|
29
|
-
}
|
package/src/render.tsx
DELETED
|
@@ -1,250 +0,0 @@
|
|
|
1
|
-
/** @jsx h */
|
|
2
|
-
import { getPropertyByPath } from 'instantsearch.js/es/lib/utils';
|
|
3
|
-
import { index, panel } from 'instantsearch.js/es/widgets';
|
|
4
|
-
import { h, Fragment } from 'preact';
|
|
5
|
-
|
|
6
|
-
import { error } from './util';
|
|
7
|
-
import { widgets } from './widgets';
|
|
8
|
-
|
|
9
|
-
import type {
|
|
10
|
-
Child,
|
|
11
|
-
Configuration,
|
|
12
|
-
PanelWidget,
|
|
13
|
-
PanelWidgetTypes,
|
|
14
|
-
TemplateAttribute,
|
|
15
|
-
TemplateChild,
|
|
16
|
-
TemplateText,
|
|
17
|
-
TemplateWidgetTypes,
|
|
18
|
-
} from './types';
|
|
19
|
-
import type { Widget } from 'instantsearch.js';
|
|
20
|
-
import type { ComponentChildren, JSX } from 'preact';
|
|
21
|
-
|
|
22
|
-
export function injectStyles() {
|
|
23
|
-
const style = document.createElement('style');
|
|
24
|
-
// @TODO: decide if this should be for all columns or only a specific type
|
|
25
|
-
style.textContent = `
|
|
26
|
-
.ais-Columns {
|
|
27
|
-
display: grid;
|
|
28
|
-
grid-template-columns: minmax(min-content, 200px) 1fr;
|
|
29
|
-
gap: 1em;
|
|
30
|
-
}
|
|
31
|
-
`;
|
|
32
|
-
document.head.appendChild(style);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export function configToIndex(
|
|
36
|
-
config: Configuration,
|
|
37
|
-
elements: Map<string, HTMLElement>
|
|
38
|
-
) {
|
|
39
|
-
const container = elements.get(config.id);
|
|
40
|
-
if (!container) {
|
|
41
|
-
error(`Element with id ${config.id} not found`);
|
|
42
|
-
return [];
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
return [
|
|
46
|
-
index({
|
|
47
|
-
indexName: config.indexName,
|
|
48
|
-
indexId: config.id,
|
|
49
|
-
}).addWidgets(
|
|
50
|
-
config.children.flatMap((child) => childToWidget(child, container))
|
|
51
|
-
),
|
|
52
|
-
];
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const hitWidgets = new Set<TemplateWidgetTypes>([
|
|
56
|
-
'ais.hits',
|
|
57
|
-
'ais.infiniteHits',
|
|
58
|
-
'ais.frequentlyBoughtTogether',
|
|
59
|
-
'ais.lookingSimilar',
|
|
60
|
-
'ais.relatedProducts',
|
|
61
|
-
'ais.trendingItems',
|
|
62
|
-
]);
|
|
63
|
-
function isTemplateWidget(
|
|
64
|
-
child: Child
|
|
65
|
-
): child is Child & { children: TemplateChild[] } {
|
|
66
|
-
return hitWidgets.has(child.type as any);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const panelWidgets = new Set<PanelWidgetTypes>([
|
|
70
|
-
'ais.refinementList',
|
|
71
|
-
'ais.menu',
|
|
72
|
-
'ais.hierarchicalMenu',
|
|
73
|
-
'ais.breadcrumb',
|
|
74
|
-
'ais.numericMenu',
|
|
75
|
-
'ais.rangeInput',
|
|
76
|
-
'ais.rangeSlider',
|
|
77
|
-
'ais.ratingMenu',
|
|
78
|
-
'ais.toggleRefinement',
|
|
79
|
-
]);
|
|
80
|
-
function isPanelWidget(child: Child): child is PanelWidget {
|
|
81
|
-
return panelWidgets.has(child.type as any);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const tagNames = new Map<string, string>(
|
|
85
|
-
Object.entries({
|
|
86
|
-
paragraph: 'p',
|
|
87
|
-
span: 'span',
|
|
88
|
-
h2: 'h2',
|
|
89
|
-
div: 'div',
|
|
90
|
-
link: 'a',
|
|
91
|
-
image: 'img',
|
|
92
|
-
})
|
|
93
|
-
);
|
|
94
|
-
|
|
95
|
-
function renderText(text: TemplateText[number], hit: any, components: any) {
|
|
96
|
-
if (text.type === 'string') {
|
|
97
|
-
return text.value;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
if (text.type === 'attribute') {
|
|
101
|
-
return getPropertyByPath(hit, text.path);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
if (text.type === 'highlight') {
|
|
105
|
-
return components.Highlight({
|
|
106
|
-
hit,
|
|
107
|
-
attribute: text.path,
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
if (text.type === 'snippet') {
|
|
112
|
-
return components.Snippet({
|
|
113
|
-
hit,
|
|
114
|
-
attribute: text.path,
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
return null;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
function renderAttribute(text: TemplateAttribute[number], hit: any) {
|
|
122
|
-
if (text.type === 'string') {
|
|
123
|
-
return text.value;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
if (text.type === 'attribute') {
|
|
127
|
-
return getPropertyByPath(hit, text.path);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
return null;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
function childToWidget(child: Child, container: HTMLElement): Widget[] {
|
|
134
|
-
const widgetContainer = container.appendChild(document.createElement('div'));
|
|
135
|
-
|
|
136
|
-
if (child.type === 'columns') {
|
|
137
|
-
widgetContainer.classList.add('ais-Columns');
|
|
138
|
-
|
|
139
|
-
return child.children
|
|
140
|
-
.map((column) => {
|
|
141
|
-
const columnContainer = widgetContainer.appendChild(
|
|
142
|
-
Object.assign(document.createElement('div'), {
|
|
143
|
-
className: 'ais-Column',
|
|
144
|
-
})
|
|
145
|
-
);
|
|
146
|
-
return column.map((ch) => childToWidget(ch, columnContainer));
|
|
147
|
-
})
|
|
148
|
-
.flat(2);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
if (child.type === 'ais.configure') {
|
|
152
|
-
return [widgets[child.type]({ ...child.parameters })];
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
if (isTemplateWidget(child)) {
|
|
156
|
-
// type cast is needed here because the spread adding `container` and `templates` loses the type discriminant
|
|
157
|
-
const parameters = child.parameters as Parameters<
|
|
158
|
-
typeof widgets['ais.hits']
|
|
159
|
-
>[0];
|
|
160
|
-
const widget = widgets[child.type] as typeof widgets['ais.hits'];
|
|
161
|
-
|
|
162
|
-
return [
|
|
163
|
-
widget({
|
|
164
|
-
...parameters,
|
|
165
|
-
container: widgetContainer,
|
|
166
|
-
templates: {
|
|
167
|
-
item: (hit: any, { components }) => {
|
|
168
|
-
if (!child.children.length) {
|
|
169
|
-
return <code> no item template given</code>;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
function renderChild(ch: TemplateChild) {
|
|
173
|
-
const Tag = tagNames.get(ch.type) as keyof JSX.IntrinsicElements;
|
|
174
|
-
if (!Tag) {
|
|
175
|
-
return <Fragment></Fragment>;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
let children: ComponentChildren = null;
|
|
179
|
-
if ('text' in ch.parameters) {
|
|
180
|
-
children = ch.parameters.text.map((text) =>
|
|
181
|
-
renderText(text, hit, components)
|
|
182
|
-
);
|
|
183
|
-
} else if ('children' in ch) {
|
|
184
|
-
children = ch.children.map(renderChild);
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
const attributes = Object.fromEntries(
|
|
188
|
-
Object.entries(ch.parameters)
|
|
189
|
-
.filter(
|
|
190
|
-
(tuple): tuple is [string, TemplateAttribute] =>
|
|
191
|
-
tuple[0] !== 'text'
|
|
192
|
-
)
|
|
193
|
-
.map(([key, value]) => [
|
|
194
|
-
key,
|
|
195
|
-
value.map((item) => renderAttribute(item, hit)).join(''),
|
|
196
|
-
])
|
|
197
|
-
);
|
|
198
|
-
|
|
199
|
-
return <Tag {...attributes}>{children}</Tag>;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
return child.children.map(renderChild);
|
|
203
|
-
},
|
|
204
|
-
},
|
|
205
|
-
}),
|
|
206
|
-
];
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
if (isPanelWidget(child)) {
|
|
210
|
-
// type cast is needed here because the spread adding `container` loses the type discriminant
|
|
211
|
-
const {
|
|
212
|
-
header,
|
|
213
|
-
collapsed: defaultCollapsed,
|
|
214
|
-
...parameters
|
|
215
|
-
} = child.parameters as Parameters<
|
|
216
|
-
typeof widgets['ais.refinementList']
|
|
217
|
-
>[0] & { header: string; collapsed: boolean };
|
|
218
|
-
const widget = widgets[child.type] as typeof widgets['ais.refinementList'];
|
|
219
|
-
return [
|
|
220
|
-
panel<typeof widgets['ais.refinementList']>({
|
|
221
|
-
templates: {
|
|
222
|
-
header,
|
|
223
|
-
collapseButtonText: ({ collapsed }) => (
|
|
224
|
-
// @TODO: put this style in a stylesheet
|
|
225
|
-
<span style="cursor: pointer">{collapsed ? '+' : '-'}</span>
|
|
226
|
-
),
|
|
227
|
-
},
|
|
228
|
-
collapsed:
|
|
229
|
-
typeof defaultCollapsed === 'undefined'
|
|
230
|
-
? undefined
|
|
231
|
-
: () => defaultCollapsed,
|
|
232
|
-
})(widget)({
|
|
233
|
-
...parameters,
|
|
234
|
-
container: widgetContainer,
|
|
235
|
-
}),
|
|
236
|
-
];
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
// type cast is needed here because the spread adding `container` loses the type discriminant
|
|
240
|
-
const parameters = child.parameters as Parameters<
|
|
241
|
-
typeof widgets['ais.pagination']
|
|
242
|
-
>[0];
|
|
243
|
-
const widget = widgets[child.type] as typeof widgets['ais.pagination'];
|
|
244
|
-
return [
|
|
245
|
-
widget({
|
|
246
|
-
...parameters,
|
|
247
|
-
container: widgetContainer,
|
|
248
|
-
}),
|
|
249
|
-
];
|
|
250
|
-
}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
/** @jsx h */
|
|
2
|
-
import algoliasearch from 'algoliasearch/lite';
|
|
3
|
-
import InstantSearch from 'instantsearch.js/es/lib/InstantSearch';
|
|
4
|
-
|
|
5
|
-
import { fakeFetchConfiguration } from './fake-configuration';
|
|
6
|
-
import { getElements, getSettings } from './get-information';
|
|
7
|
-
import { configToIndex, injectStyles } from './render';
|
|
8
|
-
import { error } from './util';
|
|
9
|
-
|
|
10
|
-
declare global {
|
|
11
|
-
interface Window {
|
|
12
|
-
__search: InstantSearch;
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export function setupInstantSearch() {
|
|
17
|
-
try {
|
|
18
|
-
const settings = getSettings();
|
|
19
|
-
|
|
20
|
-
const searchClient = algoliasearch(settings.appId, settings.apiKey);
|
|
21
|
-
const search = new InstantSearch({
|
|
22
|
-
searchClient,
|
|
23
|
-
});
|
|
24
|
-
window.__search = search;
|
|
25
|
-
|
|
26
|
-
const elements = getElements();
|
|
27
|
-
|
|
28
|
-
injectStyles();
|
|
29
|
-
|
|
30
|
-
fakeFetchConfiguration([...elements.keys()]).then((configuration) => {
|
|
31
|
-
search
|
|
32
|
-
.addWidgets(
|
|
33
|
-
configuration.flatMap((config) => configToIndex(config, elements))
|
|
34
|
-
)
|
|
35
|
-
.start();
|
|
36
|
-
});
|
|
37
|
-
} catch (err) {
|
|
38
|
-
error((err as Error).message);
|
|
39
|
-
}
|
|
40
|
-
}
|