Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Bring in the aloglia netlify package
- Loading branch information
1 parent
2229c1b
commit 019f19b
Showing
16 changed files
with
1,247 additions
and
36 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,171 @@ | ||
@import '~@algolia/autocomplete-theme-classic'; | ||
|
||
$color-bg: white; | ||
$color-muted: #969FAF; | ||
$color-light: #797979; | ||
$color-text: #23263B; | ||
$color-mark: rgb(84 104 255); | ||
$color-bg-selected: #F5F5FA; | ||
$color-input-icon: #777777; | ||
$color-source-icon: rgb(80 80 80 / 32%); | ||
$font-size-xs: 12px; | ||
$font-size-s: 14px; | ||
$font-size-m: 16px; | ||
$size-xs: 2px; | ||
$size-s: 4px; | ||
$size-m: 8px; | ||
$size-l: 16px; | ||
$size-xl: 32px; | ||
$height: $size-xl; | ||
$height-icon: $size-l; | ||
$font-size: $font-size-m; | ||
.aa-Autocomplete, .aa-Panel, .aa-DetachedContainer { | ||
--color-mark: #{$color-mark}; | ||
--color-background: #{$color-bg}; | ||
--color-selected: #{$color-bg-selected}; | ||
--color-text: #{$color-text}; | ||
--color-input-icon: #{$color-input-icon}; | ||
--color-source-icon: #{$color-source-icon}; | ||
--height: #{$height}; | ||
--height-icon: #{$height-icon}; | ||
--font-size: #{$font-size} | ||
} | ||
|
||
//// ---- Overridden definitions of classic theme | ||
.aa-Panel { | ||
z-index: 1100; | ||
min-width: 350px; | ||
margin-top: $size-xs; | ||
.aa-PanelLayout { | ||
padding-top: 0; | ||
padding-bottom: 0; | ||
background-color: var(--color-background); | ||
.aa-PanelLayoutPreview { | ||
border-left: solid 1px var(--color-selected) | ||
} | ||
} | ||
.aa-GradientBottom { | ||
background-image: none | ||
} | ||
} | ||
.aa-Autocomplete, .aa-DetachedFormContainer { | ||
.aa-Form { | ||
height: var(--height); | ||
padding: 0; | ||
font-size: var(--font-size); | ||
background-color: var(--color-background); | ||
&:focus-within { | ||
box-shadow: none | ||
} | ||
.aa-InputWrapperPrefix { | ||
padding: 0; | ||
.aa-Label { | ||
padding: 0; | ||
svg { | ||
left: 0; | ||
width: var(--height-icon); | ||
color: var(--color-input-icon); | ||
vertical-align: middle | ||
} | ||
} | ||
} | ||
.aa-InputWrapper { | ||
.aa-Input { | ||
height: var(--height); | ||
color: var(--color-text) | ||
} | ||
} | ||
.aa-InputWrapperSuffix { | ||
height: var(--height); | ||
.aa-ClearButton { | ||
padding: 0; | ||
&:hover, | ||
&:focus { | ||
color: var(--color-text) | ||
} | ||
} | ||
} | ||
} | ||
} | ||
.aa-Item { | ||
padding: $size-xs 0; | ||
color: var(--color-text); | ||
a { | ||
color: inherit; | ||
text-decoration: none | ||
} | ||
&[aria-selected='true'] { | ||
background-color: var(--color-selected) | ||
} | ||
.aa-ItemContent { | ||
display: flex; | ||
color: var(--color-text); | ||
mark { | ||
color: var(--color-mark); | ||
background-color: transparent | ||
} | ||
} | ||
.aa-ItemIcon { | ||
align-items: baseline; | ||
margin: 0 var(--aa-spacing-half) 0 2px; | ||
color: var(--color-source-icon); | ||
background: none; | ||
box-shadow: none | ||
} | ||
.aa-ItemTitle { | ||
font-weight: bold; | ||
font-size: $font-size-s; | ||
line-height: 18px | ||
} | ||
.aa-ItemHierarchy { | ||
padding: 1px 0; | ||
font-size: $font-size-xs; | ||
font-style: italic; | ||
line-height: 18px; | ||
opacity: .8 | ||
} | ||
.aa-ItemDescription { | ||
color: $color-light; | ||
font-size: $font-size-xs; | ||
line-height: 16px | ||
} | ||
} | ||
.aa-DetachedContainer { | ||
background: var(--color-background); | ||
.aa-DetachedFormContainer { | ||
.aa-DetachedCancelButton { | ||
color: var(--color-text) | ||
} | ||
} | ||
} | ||
.aa-DetachedOverlay { | ||
z-index: 10 | ||
} | ||
.aa-DetachedSearchButton { | ||
background-color: var(--color-background); | ||
.aa-DetachedSearchButtonIcon { | ||
color: var(--color-input-icon) | ||
} | ||
} | ||
|
||
/* Search by */ | ||
.aa-powered-by-link { | ||
display: inline-block; | ||
width: 64px; | ||
height: 18px; | ||
margin-left: $size-s; | ||
overflow: hidden; | ||
white-space: nowrap; | ||
text-indent: 101%; | ||
vertical-align: middle; | ||
background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0ODUgMTIwIj48ZyBmaWxsPSJub25lIj48cGF0aCBmaWxsPSIjNTQ2OEZGIiBkPSJNMTYuOC0xLjAwMWg4OC40YzguNyAwIDE1LjggNy4wNjUgMTUuOCAxNS44djg4LjQwNWMwIDguNy03LjA2NSAxNS43OTUtMTUuOCAxNS43OTVIMTYuOGMtOC43IDAtMTUuOC03LjA2LTE1LjgtMTUuNzk1VjE0Ljc1OWMwLTguNjk1IDcuMDYtMTUuNzYgMTUuOC0xNS43NiIvPjxwYXRoIGZpbGw9IiNGRkYiIGQ9Ik03My41MDUgMjUuNzg4di00LjExNWE1LjIwOSA1LjIwOSAwIDAwLTUuMjEtNS4yMDVINTYuMTVhNS4yMDkgNS4yMDkgMCAwMC01LjIxIDUuMjA1djQuMjI1YzAgLjQ3LjQzNS44LjkxLjY5YTM3Ljk2NiAzNy45NjYgMCAwMTEwLjU3LTEuNDljMy40NjUgMCA2Ljg5NS40NyAxMC4yMSAxLjM4LjQ0LjExLjg3NS0uMjE1Ljg3NS0uNjlNNDAuMjIgMzEuMTczbC0yLjA3NS0yLjA3NWE1LjIwNiA1LjIwNiAwIDAwLTcuMzY1IDBsLTIuNDggMi40NzVhNS4xODUgNS4xODUgMCAwMDAgNy4zNTVsMi4wNCAyLjA0Yy4zMy4zMjUuODA1LjI1IDEuMDk1LS4wNzVhMzkuODc2IDM5Ljg3NiAwIDAxMy45NzUtNC42NiAzNy42OCAzNy42OCAwIDAxNC43LTRjLjM2NC0uMjIuNC0uNzMuMTEtMS4wNm0yMi4xNjQgMTMuMDY1djE3LjhjMCAuNTEuNTUuODc1IDEuMDIuNjJsMTUuODI1LTguMTljLjM2LS4xOC40Ny0uNjIuMjktLjk4LTMuMjgtNS43NTUtOS4zNy05LjY4NS0xNi40MDUtOS45NC0uMzY1IDAtLjczLjI5LS43My42OW0wIDQyLjg4Yy0xMy4xOTUgMC0yMy45MTUtMTAuNzA1LTIzLjkxNS0yMy44OCAwLTEzLjE3NSAxMC43Mi0yMy44NzUgMjMuOTE1LTIzLjg3NSAxMy4yIDAgMjMuOTE2IDEwLjcgMjMuOTE2IDIzLjg3NXMtMTAuNjggMjMuODgtMjMuOTE2IDIzLjg4bTAtNTcuOGMtMTguNzQgMC0zMy45NCAxNS4xOC0zMy45NCAzMy45MiAwIDE4Ljc0NSAxNS4yIDMzLjg5IDMzLjk0IDMzLjg5czMzLjk0LTE1LjE4IDMzLjk0LTMzLjkyNWMwLTE4Ljc0NS0xNS4xNjUtMzMuODg1LTMzLjk0LTMzLjg4NSIvPjxwYXRoIGZpbGw9IiM1NDY4RkYiIGQ9Ik0yNDAuMjE0IDk0LjE3N2MtMjMuMzY1LjExLTIzLjM2NS0xOC44NTUtMjMuMzY1LTIxLjg3NWwtLjA0LTcxLjA0NSAxNC4yNTQtMi4yNnY3MC42MWMwIDEuNzE1IDAgMTIuNTYgOS4xNSAxMi41OTV2MTEuOTc1aC4wMDF6bS01Ny43OC0xMS42MWM0LjM3NCAwIDcuNjItLjI1NSA5Ljg4LS42OVY2Ny4zOTJhMjkuMTk2IDI5LjE5NiAwIDAwLTMuNDMtLjY5NSAzMy43NDIgMzMuNzQyIDAgMDAtNC45NTYtLjM2NWMtMS41NyAwLTMuMTc1LjExLTQuNzc1LjM2NS0xLjYwNS4yMi0zLjA2NS42NTUtNC4zNCAxLjI3NS0xLjI3NS42Mi0yLjMzNSAxLjQ5NS0zLjEgMi42Mi0uOCAxLjEzLTEuMTY1IDEuNzg1LTEuMTY1IDMuNDk1IDAgMy4zNDUgMS4xNjUgNS4yOCAzLjI4IDYuNTUgMi4xMTUgMS4yNzUgNC45OTUgMS45MyA4LjYwNiAxLjkzem0tMS4yNC01MS42ODVjNC43IDAgOC42NzQuNTg1IDExLjg4NCAxLjc1IDMuMjA2IDEuMTY1IDUuNzk2IDIuOCA3LjY5IDQuODc1IDEuOTM1IDIuMTEgMy4yNDUgNC45MTUgNC4wNDYgNy45Ljg0IDIuOTg1IDEuMjQgNi4yNiAxLjI0IDkuODZ2MzYuNjJjLTIuMTg1LjQ3LTUuNTA2IDEuMDE1LTkuOTUgMS42Ny00LjQ0Ni42NTUtOS40NC45ODUtMTQuOTg2Ljk4NS0zLjY4IDAtNy4wNy0uMzY1LTEwLjA5NS0xLjA1NS0zLjA2NS0uNjktNS42NS0xLjgyLTcuODQtMy4zODUtMi4xNS0xLjU2NS0zLjgyNS0zLjU3LTUuMDY1LTYuMDQtMS4yMDUtMi40OC0xLjgyNS01Ljk3LTEuODI1LTkuNjEgMC0zLjQ5NS42OS01LjcxNSAyLjA0NS04LjEyIDEuMzgtMi40IDMuMjQtNC4zNjUgNS41NzUtNS44OTUgMi4zNy0xLjUzIDUuMDY1LTIuNjIgOC4xNjUtMy4yNzUgMy4xLS42NTUgNi4zNDUtLjk4NSA5LjY5NS0uOTg1IDEuNTcgMCAzLjIxLjExIDQuOTYuMjkgMS43MTUuMTg1IDMuNTc1LjUxNSA1LjU0NS45ODV2LTIuMzNjMC0xLjYzNS0uMTg1LTMuMi0uNTg1LTQuNjU1YTEwLjAxMiAxMC4wMTIgMCAwMC0yLjA0NS0zLjg5NWMtLjk4NS0xLjEzLTIuMjU1LTIuMDA1LTMuODYtMi42Mi0xLjYwNS0uNjItMy42NS0xLjA5NS02LjA5LTEuMDk1LTMuMjggMC02LjI3LjQtOS4wMDUuODc1LTIuNzM1LjQ3LTQuOTk1IDEuMDItNi43MSAxLjYzNWwtMS43MS0xMS42OGMxLjc4NS0uNjIgNC40NDUtMS4yNCA3Ljg3NS0xLjg1NSAzLjQyNS0uNjYgNy4xMS0uOTUgMTEuMDQ1LS45NWguMDAxem0yODEuNTEgNTEuMjg1YzQuMzc1IDAgNy42MTUtLjI1NSA5Ljg3NS0uNjk1di0xNC40OGMtLjgtLjIyLTEuOTMtLjQ3NS0zLjQyNS0uNjk1YTMzLjgxMyAzMy44MTMgMCAwMC00Ljk2LS4zNjVjLTEuNTY1IDAtMy4xNy4xMS00Ljc3NS4zNjUtMS42LjIyLTMuMDYuNjU1LTQuMzM1IDEuMjc1LTEuMjguNjItMi4zMzUgMS40OTUtMy4xIDIuNjItLjgwNSAxLjEzLTEuMTY1IDEuNzg1LTEuMTY1IDMuNDk1IDAgMy4zNDUgMS4xNjUgNS4yOCAzLjI4IDYuNTUgMi4xNSAxLjMxIDQuOTk1IDEuOTMgOC42MDUgMS45M3ptLTEuMjA1LTUxLjY0NWM0LjcgMCA4LjY3NC41OCAxMS44ODQgMS43NDUgMy4yMDUgMS4xNjUgNS43OTUgMi44IDcuNjkgNC44NzUgMS44OTUgMi4wNzUgMy4yNDUgNC45MTUgNC4wNDUgNy45Ljg0IDIuOTg1IDEuMjQgNi4yNiAxLjI0IDkuODY1djM2LjYxNWMtMi4xODUuNDctNS41MDUgMS4wMTUtOS45NSAxLjY3NS00LjQ0NS42NTUtOS40NC45OC0xNC45ODUuOTgtMy42OCAwLTcuMDctLjM2NS0xMC4wOTQtMS4wNTUtMy4wNjUtLjY5LTUuNjUtMS44Mi03Ljg0LTMuMzg1LTIuMTUtMS41NjUtMy44MjUtMy41Ny01LjA2NS02LjA0LTEuMjA1LTIuNDc1LTEuODI1LTUuOTctMS44MjUtOS42MSAwLTMuNDk1LjY5NS01LjcxNSAyLjA0NS04LjEyIDEuMzgtMi40IDMuMjQtNC4zNjUgNS41NzUtNS44OTUgMi4zNy0xLjUyNSA1LjA2NS0yLjYyIDguMTY1LTMuMjc1IDMuMS0uNjU1IDYuMzQ1LS45OCA5LjctLjk4IDEuNTY1IDAgMy4yMDUuMTEgNC45NTUuMjlzMy41NzUuNTEgNS41NC45ODV2LTIuMzNjMC0xLjY0LS4xOC0zLjIwNS0uNTgtNC42NmE5Ljk3NyA5Ljk3NyAwIDAwLTIuMDQ1LTMuODk1Yy0uOTg1LTEuMTMtMi4yNTUtMi4wMDUtMy44Ni0yLjYyLTEuNjA2LS42Mi0zLjY1LTEuMDktNi4wOS0xLjA5LTMuMjggMC02LjI3LjQtOS4wMDUuODctMi43MzUuNDc1LTQuOTk1IDEuMDItNi43MSAxLjY0bC0xLjcxLTExLjY4NWMxLjc4NS0uNjIgNC40NDUtMS4yMzUgNy44NzUtMS44NTUgMy40MjUtLjYyIDcuMTA1LS45NDUgMTEuMDQ1LS45NDV6bS00Mi44LTYuNzdjNC43NzQgMCA4LjY4LTMuODYgOC42OC04LjYzIDAtNC43NjUtMy44NjYtOC42MjUtOC42OC04LjYyNS00LjgxIDAtOC42NzUgMy44Ni04LjY3NSA4LjYyNSAwIDQuNzcgMy45IDguNjMgOC42NzUgOC42M3ptNy4xOCA3MC40MjVoLTE0LjMyNnYtNjEuNDRsMTQuMzI1LTIuMjU1djYzLjY5NWguMDAxem0tMjUuMTE2IDBjLTIzLjM2NS4xMS0yMy4zNjUtMTguODU1LTIzLjM2NS0yMS44NzVsLS4wNC03MS4wNDUgMTQuMjU1LTIuMjZ2NzAuNjFjMCAxLjcxNSAwIDEyLjU2IDkuMTUgMTIuNTk1djExLjk3NXptLTQ2LjMzNS0zMS40NDVjMC02LjE1NS0xLjM1LTExLjI4NS0zLjk3NC0xNC44NS0yLjYyNS0zLjYwNS02LjMwNS01LjM4NS0xMS4wMS01LjM4NS00LjcgMC04LjM4NiAxLjc4LTExLjAwNiA1LjM4NS0yLjYyNSAzLjYtMy45MDQgOC42OTUtMy45MDQgMTQuODUgMCA2LjIyNSAxLjMxNSAxMC40MDUgMy45NCAxNC4wMSAyLjYyNSAzLjY0IDYuMzA1IDUuNDI1IDExLjAxIDUuNDI1IDQuNyAwIDguMzg1LTEuODIgMTEuMDEtNS40MjUgMi42MjQtMy42NCAzLjkzNC03Ljc4NSAzLjkzNC0xNC4wMXptMTQuNTgtLjAzNWMwIDQuODA1LS42OSA4LjQ0LTIuMTE0IDEyLjQxLTEuNDIgMy45NjUtMy40MjUgNy4zNS02LjAxIDEwLjE1NS0yLjU5IDIuOC01LjY5IDQuOTg1LTkuMzM2IDYuNTE1LTMuNjQ0IDEuNTI1LTkuMjYgMi40LTEyLjA2NSAyLjQtMi44MS0uMDM1LTguMzg1LS44MzUtMTEuOTk1LTIuNC0zLjYxLTEuNTY1LTYuNzEtMy43MTUtOS4yOTUtNi41MTUtMi41OS0yLjgwNS00LjU5NC02LjE5LTYuMDU0LTEwLjE1NS0xLjQ1Ni0zLjk3LTIuMTg1LTcuNjA1LTIuMTg1LTEyLjQxcy42NTQtOS40MyAyLjExNC0xMy4zNmMxLjQ2LTMuOTMgMy41LTcuMjggNi4xMjUtMTAuMDggMi42MjUtMi44MDUgNS43Ni00Ljk1NSA5LjMzLTYuNDggMy42MS0xLjUzIDcuNTg1LTIuMjU1IDExLjg4NS0yLjI1NSA0LjMwNSAwIDguMjc1Ljc2IDExLjkyIDIuMjU1IDMuNjUgMS41MjUgNi43ODYgMy42NzUgOS4zMzYgNi40OCAyLjU4NCAyLjggNC41OSA2LjE1IDYuMDUgMTAuMDggMS41MyAzLjkzIDIuMjk1IDguNTU1IDIuMjk1IDEzLjM2aC0uMDAxem0tMTA3LjI4NCAwYzAgNS45NjUgMS4zMSAxMi41OSAzLjkzNSAxNS4zNTUgMi42MjUgMi43NyA2LjAxNCA0LjE1IDEwLjE3NSA0LjE1IDIuMjYgMCA0LjQxLS4zMjUgNi40MTQtLjk0NSAyLjAwNS0uNjIgMy42MDYtMS4zNSA0Ljg4Ni0yLjIydi0zNS4zNGMtMS4wMi0uMjItNS4yODYtMS4wOTUtOS40MS0xLjItNS4xNzUtLjE1LTkuMTEgMS45NjUtMTEuODggNS4zNDUtMi43MzYgMy4zOS00LjEyIDkuMzItNC4xMiAxNC44NTV6bTM5LjYyNSAyOC4wOTVjMCA5LjcyLTIuNDggMTYuODE1LTcuNDc2IDIxLjMzLTQuOTkgNC41MS0xMi42MSA2Ljc3LTIyLjg5IDYuNzctMy43NTUgMC0xMS41NTUtLjczLTE3Ljc5LTIuMTFsMi4yOTUtMTEuMjg1YzUuMjE1IDEuMDkgMTIuMTA1IDEuMzg1IDE1LjcxNSAxLjM4NSA1LjcyIDAgOS44MDUtMS4xNjUgMTIuMjQ1LTMuNDk1IDIuNDQ1LTIuMzMgMy42NDUtNS43ODUgMy42NDUtMTAuMzc1di0yLjMzYy0xLjQyLjY5LTMuMjggMS4zODUtNS41NzUgMi4xMTUtMi4yOTUuNjktNC45NTUgMS4wNTUtNy45NSAxLjA1NS0zLjkzNSAwLTcuNTEtLjYyLTEwLjc1LTEuODYtMy4yNDUtMS4yMzUtNi4wNTUtMy4wNTUtOC4zNS01LjQ2LTIuMjk1LTIuNC00LjEyLTUuNDItNS4zOTUtOS4wMjUtMS4yNzUtMy42MDUtMS45MzUtMTAuMDQ1LTEuOTM1LTE0Ljc3NSAwLTQuNDQuNjk1LTEwLjAxIDIuMDQ2LTEzLjcyNSAxLjM4NC0zLjcxIDMuMzUtNi45MTUgNi4wMTQtOS41NyAyLjYyNi0yLjY1NSA1LjgzNS00LjY5NSA5LjU5LTYuMTkgMy43NTUtMS40OSA4LjE2LTIuNDM1IDEyLjkzNS0yLjQzNSA0LjYzNSAwIDguOS41OCAxMy4wNTUgMS4yNzUgNC4xNTUuNjkgNy42OSAxLjQxNSAxMC41NyAyLjIxNXY1Ni40OWguMDAxeiIvPjwvZz48L3N2Zz4='); | ||
background-repeat: no-repeat; | ||
background-size: contain | ||
} | ||
.aa-powered-by { | ||
padding: $size-m $size-m $size-s 0; | ||
color: $color-muted; | ||
font-weight: normal; | ||
font-size: $font-size-xs; | ||
text-align: right | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import { AutocompleteWrapper } from './AutocompleteWrapper' | ||
import type { Options } from './types' | ||
|
||
const defaultOptions: Omit< | ||
Options, | ||
'apiKey' | 'appId' | 'branch' | 'selector' | 'siteId' | ||
> = { | ||
analytics: true, | ||
hitsPerPage: 5, | ||
debug: false, | ||
poweredBy: true, | ||
placeholder: 'Search...', | ||
openOnFocus: false | ||
} | ||
|
||
const mandatory: Array<keyof Options> = [ | ||
'appId', | ||
'apiKey', | ||
'selector', | ||
'siteId', | ||
'branch' | ||
] | ||
|
||
const instances: AutocompleteWrapper[] = [] | ||
|
||
export default function algoliasearchNetlify (_options: Options): void { | ||
const options = { | ||
...defaultOptions, | ||
..._options | ||
} | ||
for (const key of mandatory) { | ||
if (options[key]) { continue } | ||
|
||
throw new Error(`[algoliasearch-netlify] Missing mandatory key: ${key}`) | ||
} | ||
|
||
const autocomplete = new AutocompleteWrapper(options) | ||
instances.push(autocomplete) | ||
|
||
// Wait for DOM initialization, then render | ||
const render = (): void => { | ||
autocomplete.render() | ||
} | ||
if (['complete', 'interactive'].includes(document.readyState)) { | ||
render() | ||
} else { | ||
document.addEventListener('DOMContentLoaded', render) | ||
} | ||
} |
164 changes: 164 additions & 0 deletions
164
components/algolia-search-netlify/AutocompleteWrapper.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
import { autocomplete, getAlgoliaResults } from '@algolia/autocomplete-js' | ||
import type { | ||
// eslint-disable-next-line no-unused-vars | ||
AutocompleteApi, | ||
AutocompleteSource, | ||
SourceTemplates | ||
} from '@algolia/autocomplete-js' | ||
import type { HighlightedHit } from '@algolia/autocomplete-preset-algolia' | ||
import algoliasearch from 'algoliasearch/lite' | ||
import type { SearchClient } from 'algoliasearch/lite' | ||
|
||
import { templates } from './templates' | ||
import type { Options, AlgoliaRecord } from './types' | ||
|
||
class AutocompleteWrapper { | ||
private options; | ||
private indexName; | ||
private client; | ||
private $themeNode: HTMLStyleElement | null = null; | ||
private autocomplete: AutocompleteApi<AlgoliaRecord> | undefined; | ||
|
||
constructor (options: Options) { | ||
this.options = options | ||
this.client = this.createClient() | ||
this.indexName = this.computeIndexName() | ||
} | ||
|
||
render (): void { | ||
const $input = document.querySelector(this.options.selector) as HTMLElement | ||
if (!$input) { | ||
// eslint-disable-next-line no-console | ||
console.error( | ||
`[algoliasearch-netlify] no element ${this.options.selector} found` | ||
) | ||
return | ||
} | ||
|
||
let detachedMediaQuery | ||
if (this.options.detached !== undefined) { | ||
if (this.options.detached === true) { | ||
detachedMediaQuery = '' | ||
} else if (this.options.detached === false) { | ||
detachedMediaQuery = 'none' | ||
} else { | ||
detachedMediaQuery = this.options.detached.mediaQuery | ||
} | ||
} | ||
const instance = autocomplete<AlgoliaRecord>({ | ||
container: $input, | ||
autoFocus: false, | ||
placeholder: this.options.placeholder, | ||
debug: this.options.debug, | ||
openOnFocus: this.options.openOnFocus, | ||
panelPlacement: 'input-wrapper-width', | ||
detachedMediaQuery, | ||
getSources: () => { | ||
return [this.getSources()] | ||
} | ||
}) | ||
this.applyTheme($input.firstElementChild as HTMLElement) | ||
|
||
this.autocomplete = instance | ||
} | ||
|
||
private computeIndexName (): string { | ||
const { siteId, branch } = this.options | ||
|
||
// Keep in sync with crawler code in /netlify/crawl | ||
const cleanBranch = branch | ||
.trim() | ||
.replace(/[^\p{L}\p{N}_.-]+/gu, '-') | ||
.replace(/-{2,}/g, '-') | ||
.toLocaleLowerCase() | ||
return `netlify_${siteId}_${cleanBranch}_all` | ||
} | ||
|
||
private createClient (): SearchClient { | ||
const client = algoliasearch(this.options.appId, this.options.apiKey) | ||
client.addAlgoliaAgent('Netlify integration 1.0.15') | ||
return client | ||
} | ||
|
||
private getSources (): AutocompleteSource<HighlightedHit<AlgoliaRecord>> { | ||
const poweredBy = this.options.poweredBy | ||
const tpls: SourceTemplates<HighlightedHit<AlgoliaRecord>> = { | ||
header () { | ||
return '' | ||
}, | ||
item ({ item, components }) { | ||
return templates.item(item, components) | ||
}, | ||
footer () { | ||
if (poweredBy) { | ||
return templates.poweredBy({ | ||
hostname: window.location.host | ||
}) | ||
} | ||
return '' | ||
} | ||
} | ||
const res: AutocompleteSource<HighlightedHit<AlgoliaRecord>> = { | ||
sourceId: 'algoliaHits', | ||
getItems: ({ query }) => { | ||
return getAlgoliaResults({ | ||
searchClient: this.client, | ||
queries: [ | ||
{ | ||
indexName: this.indexName, | ||
query, | ||
params: { | ||
analytics: this.options.analytics, | ||
hitsPerPage: this.options.hitsPerPage | ||
} | ||
} | ||
] | ||
}) | ||
}, | ||
getItemUrl ({ item }) { | ||
return item.url | ||
}, | ||
templates: tpls | ||
} | ||
return res | ||
} | ||
|
||
private applyTheme (el: HTMLElement | null): void { | ||
if (!el || !this.options.theme) { | ||
return | ||
} | ||
|
||
const theme = this.options.theme | ||
this.$themeNode = addCss( | ||
`.aa-Autocomplete, .aa-Panel, .aa-DetachedContainer { | ||
${theme.mark && `--color-mark: ${theme.mark};`} | ||
${theme.mark && `--color-background: ${theme.background};`} | ||
${theme.mark && `--color-selected: ${theme.selected};`} | ||
${theme.mark && `--color-text: ${theme.text};`} | ||
${theme.mark && `--color-source-icon: ${theme.colorSourceIcon};`} | ||
}`, | ||
this.$themeNode | ||
) | ||
} | ||
} | ||
|
||
function addCss ( | ||
css: string, | ||
$mainStyle: HTMLElement | null = null | ||
): HTMLStyleElement { | ||
const $usedSibling = | ||
$mainStyle ?? | ||
document.querySelector( | ||
'link[rel=stylesheet][href*="algoliasearchNetlify"]' | ||
) ?? | ||
document.getElementsByTagName('head')[0].lastChild! | ||
const $styleTag = document.createElement('style') | ||
$styleTag.setAttribute('type', 'text/css') | ||
$styleTag.appendChild(document.createTextNode(css)) | ||
return $usedSibling.parentNode!.insertBefore( | ||
$styleTag, | ||
$usedSibling.nextSibling | ||
) | ||
} | ||
|
||
export { AutocompleteWrapper } |
Oops, something went wrong.