@algolia/wizard 0.43.0-rc.141.298 → 0.43.0

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/main.js CHANGED
@@ -3472,7 +3472,7 @@ async function runAnalysis(mode, extraInstructions = []) {
3472
3472
  // package.json
3473
3473
  var package_default = {
3474
3474
  name: "@algolia/wizard",
3475
- version: "0.43.0-rc.141.298",
3475
+ version: "0.43.0",
3476
3476
  description: "Magically implement Algolia functionality in your codebase",
3477
3477
  type: "module",
3478
3478
  engines: {
@@ -4132,7 +4132,6 @@ function searchInstructions(input) {
4132
4132
  return [
4133
4133
  "Implement an in-app Algolia search experience.",
4134
4134
  `Build the search UI for ${input.searchUiTarget}.`,
4135
- "This step is search UI only \u2014 the index is already populated. Do not create or modify ingestion scripts, rake/manage/CLI tasks, migrations, seeders, or any other data-loading code, even if you notice the data looks incomplete.",
4136
4135
  ...doc ? [
4137
4136
  "Follow the Algolia SDK reference below for client setup, search UI wiring, and Insights instrumentation \u2014 Insights is required, not optional; prefer the reference over prior knowledge:",
4138
4137
  doc
@@ -4140,12 +4139,9 @@ function searchInstructions(input) {
4140
4139
  "No bundled Algolia SDK reference exists for this stack, so rely on the project's own conventions and Algolia's official client for its language. Do not invent APIs \u2014 keep to the documented search endpoint and its parameters."
4141
4140
  ],
4142
4141
  `Create the search experience as its own component in a new file, following the project's existing component conventions (location, naming, styling approach). Do not write it inline into an existing file.`,
4143
- `Import and render that new component from ${input.searchLocation ? `"${input.searchLocation}"` : "the best shared, always-rendered layout location (e.g. a header/nav component)"} so it is reachable across the app \u2014 at least a working search input and results panel against the target index.`,
4142
+ `Import and render that new component from ${input.searchLocation ? `"${input.searchLocation}"` : "the best shared, always-rendered layout location (e.g. a header/nav component)"} so it is reachable across the app \u2014 at least a working search input and results list against the target index.`,
4144
4143
  "If a search box already exists, replace its usage with an import and render of your new component; remove the old implementation.",
4145
4144
  "When rendering results with an existing shared component (e.g. a card), import and reuse that component rather than inlining its markup \u2014 inlining silently drops the styles and behavior its own file provides.",
4146
- "Results appear as a dropdown panel, not a permanently visible list: show it only while the input is focused and has a non-empty query, and close it on Escape, on blur, and on an outside click. If the SDK reference above documents an Autocomplete widget for this stack, it already provides all of that (open/close, arrow-key navigation, combobox ARIA, Insights events) \u2014 use it as-is and do not add your own open/close logic or ARIA roles on top of it. Only build this by hand when the reference has no such widget for this stack, or says it is headless; then also handle Up/Down arrows over the results and Enter to select.",
4147
- "Meet WCAG AA contrast (4.5:1 body text, 3:1 large text/icons) between the panel's text and its own background, and give both the input and the active result a focus indicator that is visible against whatever sits behind it. Style the panel through the widget's own class and CSS-variable overrides (or, if building by hand, the app's existing theme tokens) \u2014 never assume a light surface or reuse the surrounding page's colors unchanged inside the panel.",
4148
- "The panel takes its width from the input by default, so a small input makes it unreadably narrow: give it a minimum width of 320px independent of the input, and keep it anchored to the input edge it opens from so widening it does not push it off-screen.",
4149
4145
  `Define ${SEARCH_CONFIG_APP_ID}, ${SEARCH_CONFIG_SEARCH_KEY}, and ${SEARCH_CONFIG_INDEX_NAME} as exported constants in a module that fits this project's existing conventions for shared client-side config \u2014 reuse an existing one if it already holds config like this, or add a small new one otherwise. These are PUBLIC values, safe to commit and expose client-side: never read them from an environment variable or a .env* file, and never hardcode them anywhere except in that one module (import them wherever the search client needs them).`,
4150
4146
  `Set ${SEARCH_CONFIG_APP_ID} to "${input.appId}" and ${SEARCH_CONFIG_INDEX_NAME} to "${input.targetIndex}".`,
4151
4147
  input.searchKey ? `Set ${SEARCH_CONFIG_SEARCH_KEY} to "${input.searchKey}".` : `A real search-only key could not be provisioned${input.searchKeyError ? ` (${input.searchKeyError})` : ""} \u2014 set ${SEARCH_CONFIG_SEARCH_KEY} to the placeholder "${SEARCH_KEY_PLACEHOLDER}" and add a prominent TODO for the developer to fill in a real one.`,
@@ -5074,7 +5070,7 @@ function Sidebar() {
5074
5070
  return /* @__PURE__ */ jsxs14(Box15, { flexDirection: "row", gap: 1, children: [
5075
5071
  /* @__PURE__ */ jsx13(Text15, { color: COLORS.primary, children: `[${c.keyHint}]` }),
5076
5072
  /* @__PURE__ */ jsx13(Text15, { color: COLORS.muted, children: c.description })
5077
- ] });
5073
+ ] }, c.keyHint);
5078
5074
  }) })
5079
5075
  ] })
5080
5076
  ]
@@ -20,10 +20,8 @@ Always install the **latest stable** within the major (use a caret range like `^
20
20
 
21
21
  - Use a **search-only API key** in any browser/client code. It is safe to expose.
22
22
  NEVER ship an admin or any write-capable key to the client.
23
- - Import the Application ID and search-only key from the project's shared client-side
24
- config module, where they are plain exported constants. They are public values, safe to
25
- commit — do not read them from an env var or `.env*` file, and never hardcode them
26
- inline anywhere else.
23
+ - Read the Application ID and search-only key from **public env vars**, never hardcode
24
+ them inline.
27
25
  - Instantiate the search client **once, outside your components**, and pass a stable
28
26
  reference. Do not inline `algoliasearch(...)` as a prop value — it breaks the
29
27
  client cache and causes re-renders.
@@ -20,19 +20,10 @@ const searchClient = algoliasearch(ALGOLIA_APP_ID, ALGOLIA_SEARCH_API_KEY)
20
20
 
21
21
  ## Vanilla (`instantsearch.js` v4)
22
22
 
23
- Use the `autocomplete` widget for the results panel. It already manages focus, blur,
24
- outside-click dismissal, Up/Down arrow navigation with wrap-around, Enter/Escape/Tab, and
25
- the combobox ARIA (`combobox`, `aria-expanded`, `aria-activedescendant`), so do not add
26
- your own open/close logic or ARIA roles around it.
27
-
28
- The `autocomplete` export needs `instantsearch.js` **4.110.0 or newer**. If the project
29
- pins an older 4.x, upgrade within the major (`^4`) rather than reaching for a different
30
- widget.
31
-
32
23
  ```js
33
24
  import { liteClient as algoliasearch } from 'algoliasearch/lite'
34
25
  import instantsearch from 'instantsearch.js'
35
- import { autocomplete } from 'instantsearch.js/es/widgets'
26
+ import { searchBox, hits } from 'instantsearch.js/es/widgets'
36
27
  import {
37
28
  ALGOLIA_APP_ID,
38
29
  ALGOLIA_SEARCH_API_KEY,
@@ -48,74 +39,13 @@ const search = instantsearch({
48
39
  })
49
40
 
50
41
  search.addWidgets([
51
- autocomplete({
52
- container: '#autocomplete',
53
- placeholder: 'Search...',
54
- indices: [
55
- {
56
- indexName: ALGOLIA_INDEX_NAME,
57
- templates: {
58
- item({ item, onSelect }, { html, components }) {
59
- return html`<div onClick=${onSelect}>
60
- ${components.Highlight({ hit: item, attribute: 'name' })}
61
- </div>`
62
- },
63
- },
64
- },
65
- ],
66
- }),
42
+ searchBox({ container: '#searchbox' }),
43
+ hits({ container: '#hits' }),
67
44
  ])
68
45
 
69
46
  search.start()
70
47
  ```
71
48
 
72
- `indices[].getURL` and `.getQuery` are optional — only pass `getURL` if the app has a real
73
- per-item page to link to; don't invent one. Leave `showQuerySuggestions`,
74
- `showPromptSuggestions`, `showRecent`, and `aiMode` unset — each depends on an index or
75
- feature (query suggestions, recent-search storage, AI chat) this project doesn't have.
76
-
77
- ### Styling the panel
78
-
79
- The widget ships no CSS of its own. Install `instantsearch.css` and import a theme once,
80
- then layer the app's own look on top:
81
-
82
- ```js
83
- import 'instantsearch.css/themes/satellite.css'
84
- ```
85
-
86
- The theme defines its palette as `--ais-*` custom properties on `:root`, and the colors
87
- are **RGB triplets consumed through `rgba()`**, not CSS colors — override them with
88
- triplets or every widget color breaks:
89
-
90
- ```css
91
- :root {
92
- --ais-background-color-rgb: 24, 24, 27; /* not #18181b */
93
- --ais-text-color-rgb: 244, 244, 245;
94
- --ais-primary-color-rgb: 129, 140, 248;
95
- }
96
- ```
97
-
98
- Everything else is plain CSS against the widget's own classes (`.ais-Autocomplete`,
99
- `.ais-AutocompletePanel`, `.ais-AutocompleteInput`, `.ais-AutocompleteIndexList`,
100
- `.ais-AutocompleteIndexItem`), or `cssClasses` / `indices[].cssClasses` to add your own
101
- class names to those elements.
102
-
103
- The theme's panel is `position: absolute; width: 100%`, so it inherits the width of the
104
- input container — a small input yields an unreadably narrow panel. Give it a minimum
105
- width and anchor it to the edge it opens from, or it grows off-screen:
106
-
107
- ```css
108
- .ais-AutocompletePanel {
109
- min-width: 320px;
110
- left: 0; /* right: 0; left: auto for an input aligned to the right */
111
- }
112
- ```
113
-
114
- Below `(max-width: 680px)` the widget switches to detached (fullscreen) mode and renders
115
- no panel, so panel width rules only apply above that breakpoint. Change the breakpoint
116
- with `detachedMediaQuery` or `--ais-autocomplete-detached-media-query`; pass `''` to
117
- disable detached mode.
118
-
119
49
  ## Insights (click analytics) — always enable it
120
50
 
121
51
  The `insights` option turns on the Insights middleware (`instantsearch.js` v4.55+),
@@ -160,19 +90,27 @@ insights: {
160
90
 
161
91
  ### Click and conversion events
162
92
 
163
- With `insights: true`, the `autocomplete` widget sends `view` and `click` events itself:
164
- `view` when results render, `click` from the result element's own click handler. Its item
165
- template receives `{ item, onSelect }` and **no `sendEvent`** — there is nothing to wire,
166
- and nothing to send events from. Call `onSelect` for the widget's own selection behavior
167
- (closing the panel, recording a recent search); the click event fires either way.
93
+ The `hits` and `infiniteHits` widgets send `view` and `click` events on their own. A
94
+ custom `item` template whose click target is your own element gets `sendEvent` as the
95
+ second argument:
168
96
 
169
- The `hits` and `infiniteHits` widgets behave the same way. Only a custom `item` template
170
- there needs explicit wiring, and only when its click target is your own element — that
171
- template gets `sendEvent` as the second argument.
97
+ ```js
98
+ hits({
99
+ container: '#hits',
100
+ templates: {
101
+ item(hit, { html, sendEvent }) {
102
+ return html`<a
103
+ href="${hit.url}"
104
+ onClick="${() => sendEvent('click', hit, 'Hit Clicked')}"
105
+ >${hit.name}</a
106
+ >`
107
+ },
108
+ },
109
+ })
110
+ ```
172
111
 
173
- Conversions are business actions (add to cart, signup, booking) that happen away from the
174
- results panel, so wire them at the real action, in a component that has a `sendEvent` of
175
- its own:
112
+ Conversions are business actions (add to cart, signup, booking), so wire them at the
113
+ real action, not at render:
176
114
 
177
115
  ```js
178
116
  sendEvent('conversion', hit, 'Product Added To Cart', {
@@ -20,18 +20,9 @@ const searchClient = algoliasearch(ALGOLIA_APP_ID, ALGOLIA_SEARCH_API_KEY)
20
20
 
21
21
  ## React (`react-instantsearch` v7)
22
22
 
23
- Use the `Autocomplete` widget for the results panel. It already manages focus, blur,
24
- outside-click dismissal, Up/Down arrow navigation with wrap-around, Enter/Escape/Tab, and
25
- the combobox ARIA (`combobox` on the input, `aria-expanded`, `aria-activedescendant`), so
26
- do not add your own open/close logic or ARIA roles around it.
27
-
28
- The `Autocomplete` export needs `react-instantsearch` **7.18.0 or newer**. If the project
29
- pins an older 7.x, upgrade within the major (`^7`) rather than reaching for a different
30
- widget.
31
-
32
23
  ```tsx
33
24
  import { liteClient as algoliasearch } from 'algoliasearch/lite'
34
- import { InstantSearch, Autocomplete } from 'react-instantsearch'
25
+ import { InstantSearch, SearchBox, Hits } from 'react-instantsearch'
35
26
  import {
36
27
  ALGOLIA_APP_ID,
37
28
  ALGOLIA_SEARCH_API_KEY,
@@ -47,69 +38,13 @@ export function Search() {
47
38
  indexName={ALGOLIA_INDEX_NAME}
48
39
  insights={true}
49
40
  >
50
- <Autocomplete
51
- placeholder="Search..."
52
- indices={[
53
- {
54
- indexName: ALGOLIA_INDEX_NAME,
55
- itemComponent: ({ item, onSelect }) => (
56
- <div onClick={onSelect}>{item.name}</div>
57
- ),
58
- },
59
- ]}
60
- />
41
+ <SearchBox />
42
+ <Hits />
61
43
  </InstantSearch>
62
44
  )
63
45
  }
64
46
  ```
65
47
 
66
- `indices[].getURL` and `.getQuery` are optional — only pass `getURL` if the app has a real
67
- per-item page to link to; don't invent one. Leave `showQuerySuggestions`,
68
- `showPromptSuggestions`, `showRecent`, and `aiMode` unset — each depends on an index or
69
- feature (query suggestions, recent-search storage, AI chat) this project doesn't have.
70
-
71
- ### Styling the panel
72
-
73
- The widget ships no CSS of its own. Install `instantsearch.css` and import a theme once,
74
- then layer the app's own look on top:
75
-
76
- ```tsx
77
- import 'instantsearch.css/themes/satellite.css'
78
- ```
79
-
80
- The theme defines its palette as `--ais-*` custom properties on `:root`, and the colors
81
- are **RGB triplets consumed through `rgba()`**, not CSS colors — override them with
82
- triplets or every widget color breaks:
83
-
84
- ```css
85
- :root {
86
- --ais-background-color-rgb: 24, 24, 27; /* not #18181b */
87
- --ais-text-color-rgb: 244, 244, 245;
88
- --ais-primary-color-rgb: 129, 140, 248;
89
- }
90
- ```
91
-
92
- Everything else is plain CSS against the widget's own classes (`.ais-Autocomplete`,
93
- `.ais-AutocompletePanel`, `.ais-AutocompleteInput`, `.ais-AutocompleteIndexList`,
94
- `.ais-AutocompleteIndexItem`), or the `classNames` / `indices[].classNames` props to add
95
- your own class names to those elements.
96
-
97
- The theme's panel is `position: absolute; width: 100%`, so it inherits the width of the
98
- input container — a small input yields an unreadably narrow panel. Give it a minimum
99
- width and anchor it to the edge it opens from, or it grows off-screen:
100
-
101
- ```css
102
- .ais-AutocompletePanel {
103
- min-width: 320px;
104
- left: 0; /* right: 0; left: auto for an input aligned to the right */
105
- }
106
- ```
107
-
108
- Below `(max-width: 680px)` the widget switches to detached (fullscreen) mode and renders
109
- no panel, so panel width rules only apply above that breakpoint. Change the breakpoint
110
- with `detachedMediaQuery` or `--ais-autocomplete-detached-media-query`; pass `''` to
111
- disable detached mode.
112
-
113
48
  Do not inline `searchClient={algoliasearch(...)}` — keep the stable reference above.
114
49
 
115
50
  ## Insights (click analytics) — always enable it
@@ -128,13 +63,7 @@ case, install `search-insights` from npm and pass its default export as
128
63
  ```tsx
129
64
  import aa from 'search-insights'
130
65
 
131
- export function Search() {
132
- return (
133
- <InstantSearch insights={{ insightsClient: aa }}>
134
- {/* widgets */}
135
- </InstantSearch>
136
- )
137
- }
66
+ <InstantSearch insights={{ insightsClient: aa }} />
138
67
  ```
139
68
 
140
69
  The middleware calls `aa('init', ...)` itself with the app ID and search key, so no
@@ -154,14 +83,8 @@ policy allows it:
154
83
 
155
84
  ### Click and conversion events
156
85
 
157
- With `insights={true}`, `<Autocomplete>` sends `view` and `click` events itself: `view`
158
- when results render, `click` from the result element's own click handler. Its
159
- `itemComponent` receives `{ item, onSelect, onApply }` and **no `sendEvent`** — there is
160
- nothing to wire, and nothing to send events from. Call `onSelect` for the widget's own
161
- selection behavior (closing the panel, recording a recent search); the click event fires
162
- either way.
163
-
164
- `<Hits>` and `<InfiniteHits>` behave the same way. Two cases there need explicit wiring:
86
+ `<Hits>` and `<InfiniteHits>` send `view` and `click` events on their own. Two cases
87
+ need explicit wiring:
165
88
 
166
89
  - A custom `hitComponent` whose click target is your own element — it receives a
167
90
  `sendEvent` prop.
@@ -20,68 +20,19 @@ const searchClient = algoliasearch(ALGOLIA_APP_ID, ALGOLIA_SEARCH_API_KEY)
20
20
 
21
21
  ## Vue (`vue-instantsearch` v4)
22
22
 
23
- Use `ais-autocomplete` for the query and results state. `ais-autocomplete` is headless: its default
24
- slot only provides `currentRefinement`, `indices`, and `refine` — it renders nothing and
25
- handles no focus, blur, keyboard, or ARIA itself. You must build all of it: keep the panel
26
- closed until the input is focused and has a query, close it on Escape, blur, or an outside
27
- click, move an active-option highlight with the Up/Down arrows and select it with Enter,
28
- carry the combobox ARIA on the input, and send click events via each index's `sendEvent`.
29
-
30
23
  ```vue
31
24
  <template>
32
- <div ref="containerRef" class="search" @focusout="onFocusOut">
33
- <ais-instant-search
34
- :search-client="searchClient"
35
- :index-name="ALGOLIA_INDEX_NAME"
36
- :insights="true"
37
- >
38
- <ais-autocomplete>
39
- <template v-slot="{ currentRefinement, indices, refine }">
40
- <input
41
- type="search"
42
- role="combobox"
43
- aria-autocomplete="list"
44
- aria-controls="search-panel"
45
- :aria-expanded="isOpen(currentRefinement)"
46
- :aria-activedescendant="
47
- active >= 0 ? `search-option-${active}` : undefined
48
- "
49
- :value="currentRefinement"
50
- @focus="open = true"
51
- @input="onInput(refine, $event)"
52
- @keydown.down.prevent="move(1, indices)"
53
- @keydown.up.prevent="move(-1, indices)"
54
- @keydown.enter.prevent="select(indices, active)"
55
- @keydown.esc="close"
56
- />
57
- <ul
58
- v-show="isOpen(currentRefinement)"
59
- id="search-panel"
60
- class="search-panel"
61
- role="listbox"
62
- aria-label="Search results"
63
- >
64
- <li
65
- v-for="(hit, i) in indices[0]?.hits ?? []"
66
- :id="`search-option-${i}`"
67
- :key="hit.objectID"
68
- role="option"
69
- :aria-selected="i === active"
70
- :class="{ 'is-active': i === active }"
71
- @mousedown.prevent="select(indices, i)"
72
- @mousemove="active = i"
73
- >
74
- <ais-highlight attribute="name" :hit="hit" />
75
- </li>
76
- </ul>
77
- </template>
78
- </ais-autocomplete>
79
- </ais-instant-search>
80
- </div>
25
+ <ais-instant-search
26
+ :search-client="searchClient"
27
+ :index-name="ALGOLIA_INDEX_NAME"
28
+ :insights="true"
29
+ >
30
+ <ais-search-box />
31
+ <ais-hits />
32
+ </ais-instant-search>
81
33
  </template>
82
34
 
83
35
  <script setup>
84
- import { ref } from 'vue'
85
36
  import { liteClient as algoliasearch } from 'algoliasearch/lite'
86
37
  import {
87
38
  ALGOLIA_APP_ID,
@@ -90,73 +41,9 @@ import {
90
41
  } from '<the project's shared config module>'
91
42
 
92
43
  const searchClient = algoliasearch(ALGOLIA_APP_ID, ALGOLIA_SEARCH_API_KEY)
93
- const open = ref(false)
94
- const active = ref(-1)
95
- const containerRef = ref(null)
96
-
97
- function isOpen(currentRefinement) {
98
- return open.value && Boolean(currentRefinement)
99
- }
100
-
101
- function onInput(refine, event) {
102
- open.value = true
103
- active.value = -1
104
- refine(event.currentTarget.value)
105
- }
106
-
107
- function move(delta, indices) {
108
- const hits = indices[0]?.hits ?? []
109
- if (!hits.length) return
110
- open.value = true
111
- const next = active.value + delta
112
- active.value = next < 0 ? hits.length - 1 : next % hits.length
113
- }
114
-
115
- function select(indices, index) {
116
- const hit = indices[0]?.hits?.[index]
117
- if (!hit) return
118
- indices[0].sendEvent('click', hit, 'Hit Clicked')
119
- close()
120
- // TODO: navigate to this hit's page, where the app has one
121
- }
122
-
123
- function close() {
124
- open.value = false
125
- active.value = -1
126
- }
127
-
128
- function onFocusOut(event) {
129
- if (!containerRef.value?.contains(event.relatedTarget)) close()
130
- }
131
44
  </script>
132
45
  ```
133
46
 
134
- Details that break accessibility if changed:
135
-
136
- - `role="combobox"` belongs on the `input`, not on a wrapper — with `aria-controls`
137
- pointing at the popup's `id` and `aria-activedescendant` at the active option's `id`.
138
- Keep focus on the input while the arrows move the highlight.
139
- - The element carrying `role="listbox"` must be the direct parent of the
140
- `role="option"` elements. A `ul` nested inside a `listbox` div, or options nested one
141
- level deeper, breaks the accessibility tree.
142
- - `v-show`, not `v-if`, so the `aria-activedescendant` target stays in the DOM.
143
- - `@mousedown.prevent` on an option, not `@click` — selection has to land before
144
- `focusout` closes the panel.
145
- - `focusout` on the wrapper is the outside-click dismissal: `event.relatedTarget` is
146
- `null` for a click on non-focusable page chrome, so the panel closes. Don't add a
147
- `document` click listener on top — it fights `@mousedown.prevent` on the options.
148
- - `.is-active` needs a visible style, not just `aria-selected`: the panel is the only
149
- focus feedback a keyboard user gets, since focus never leaves the input.
150
-
151
- The panel is your own markup here, so it has no widget theme to inherit from: give
152
- `.search-panel` its own background from the app's theme tokens (never transparent over
153
- page content), text that clears 4.5:1 against that background, `position: absolute` with
154
- `min-width: 320px` anchored to the input edge it opens from, and a `max-height` with
155
- `overflow-y: auto`.
156
-
157
- `ais-autocomplete`'s `indices` slot prop supports federated search across multiple
158
- indices; this project has only one, so `indices[0]` is always the one to read.
159
-
160
47
  Register the widgets via the InstantSearch Vue plugin in your app entry:
161
48
 
162
49
  ```js
@@ -198,18 +85,19 @@ const insights = { insightsInitParams: { useCookie: true } } // then :insights="
198
85
 
199
86
  ### Click and conversion events
200
87
 
201
- `ais-autocomplete` wraps the same connector as the other flavors, so `view` events fire
202
- on their own when results render. `click` does not, because the option markup is yours:
203
- call the index's `sendEvent` from your own option handler, as in the setup example above.
88
+ `ais-hits` sends `view` and `click` events on its own. A custom `item` slot whose
89
+ click target is your own element needs the slot's `sendEvent`:
204
90
 
205
91
  ```vue
206
- <li @mousedown.prevent="indices[0].sendEvent('click', hit, 'Hit Clicked')">
92
+ <ais-hits>
93
+ <template v-slot:item="{ item, sendEvent }">
94
+ <a :href="item.url" @click="sendEvent('click', item, 'Hit Clicked')">
95
+ {{ item.name }}
96
+ </a>
97
+ </template>
98
+ </ais-hits>
207
99
  ```
208
100
 
209
- `ais-hits`, if the app also has a full results page, does send `view` and `click` itself.
210
- Only a custom `item` slot there needs wiring, and only when its click target is your own
211
- element — that slot provides `sendEvent`.
212
-
213
101
  Conversions are business actions (add to cart, signup, booking), so wire them at the
214
102
  real action, not at render:
215
103
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@algolia/wizard",
3
- "version": "0.43.0-rc.141.298",
3
+ "version": "0.43.0",
4
4
  "description": "Magically implement Algolia functionality in your codebase",
5
5
  "type": "module",
6
6
  "engines": {