tecitheme 0.15.14 → 1.0.1
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/ArrayUtils.d.ts +2 -0
- package/dist/ArrayUtils.js +15 -0
- package/dist/StyleUtils.d.ts +1 -0
- package/dist/StyleUtils.js +20 -0
- package/dist/components/Header.svelte +12 -33
- package/dist/components/Search/SearchBar.svelte +75 -0
- package/dist/components/Search/SearchBar.svelte.d.ts +37 -0
- package/dist/components/Search/SearchModal.svelte +53 -0
- package/dist/components/Search/SearchModal.svelte.d.ts +25 -0
- package/dist/components/Search/TeciSearchBox.svelte +29 -0
- package/dist/components/Search/TeciSearchBox.svelte.d.ts +27 -0
- package/dist/components/Search/TeciSearchHits.svelte +284 -0
- package/dist/components/Search/TeciSearchHits.svelte.d.ts +25 -0
- package/dist/components/Search/TeciSearchRefinementPanel.svelte +14 -0
- package/dist/components/Search/TeciSearchRefinementPanel.svelte.d.ts +29 -0
- package/dist/components/Search/index.d.ts +5 -0
- package/dist/components/Search/index.js +5 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -0
- package/package.json +11 -2
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
//Function to group an array of objects by a specified Key
|
|
2
|
+
//https://stackoverflow.com/questions/14446511/most-efficient-method-to-groupby-on-an-array-of-objects
|
|
3
|
+
export const groupBy = (xs, key) => {
|
|
4
|
+
return xs.reduce((rv, x) => {
|
|
5
|
+
(rv[x[key]] = rv[x[key]] || []).push(x);
|
|
6
|
+
return rv;
|
|
7
|
+
}, {});
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
// Take an array of objects and a key, then return an Array containing all unique values present for that key across all objects.
|
|
12
|
+
export const getValuesOfKey = (arr, key) => {
|
|
13
|
+
const relevantObjs = arr.filter(obj => Object.keys(obj).includes(key));
|
|
14
|
+
return Array.from(new Set(relevantObjs.map(obj => obj[key])));
|
|
15
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function humanizeProduct(product: any): any;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export function humanizeProduct(product) {
|
|
2
|
+
switch (product) {
|
|
3
|
+
case "pyrosim":
|
|
4
|
+
return "PyroSim";
|
|
5
|
+
case "pathfinder":
|
|
6
|
+
return "Pathfinder";
|
|
7
|
+
case "ventus":
|
|
8
|
+
return "Ventus";
|
|
9
|
+
case "results":
|
|
10
|
+
return "Results";
|
|
11
|
+
case "license-manager":
|
|
12
|
+
return "License Manager";
|
|
13
|
+
case "usage":
|
|
14
|
+
return "Usage (Internal)"
|
|
15
|
+
case "sales-licensing":
|
|
16
|
+
return "Sales & Licensing";
|
|
17
|
+
default:
|
|
18
|
+
return product;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
<script>
|
|
2
|
+
import {PUBLIC_BUILD_MODE} from '$env/static/public';
|
|
2
3
|
import Icon from "./Icon.svelte";
|
|
4
|
+
import SearchBar from './Search/SearchBar.svelte';
|
|
3
5
|
import { fade, slide } from "svelte/transition";
|
|
4
6
|
import { cubicIn, cubicOut } from "svelte/easing";
|
|
5
7
|
|
|
@@ -27,6 +29,9 @@
|
|
|
27
29
|
openMenu = "";
|
|
28
30
|
}
|
|
29
31
|
}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
const searchIndex = PUBLIC_BUILD_MODE === "development" ? "preview" : "production";
|
|
30
35
|
</script>
|
|
31
36
|
|
|
32
37
|
<svelte:window on:keyup={handleEscape} />
|
|
@@ -477,39 +482,13 @@
|
|
|
477
482
|
class="ml-2 flex flex-1 items-center justify-center md:ml-0 md:px-0 lg:justify-end"
|
|
478
483
|
>
|
|
479
484
|
<div class="w-full max-w-lg lg:max-w-xs">
|
|
480
|
-
<
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
<div
|
|
488
|
-
class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3"
|
|
489
|
-
>
|
|
490
|
-
<svg
|
|
491
|
-
class="h-5 w-5 text-gray-400"
|
|
492
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
493
|
-
viewBox="0 0 20 20"
|
|
494
|
-
fill="currentColor"
|
|
495
|
-
aria-hidden="true"
|
|
496
|
-
>
|
|
497
|
-
<path
|
|
498
|
-
fill-rule="evenodd"
|
|
499
|
-
d="M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z"
|
|
500
|
-
clip-rule="evenodd"
|
|
501
|
-
/>
|
|
502
|
-
</svg>
|
|
503
|
-
</div>
|
|
504
|
-
<input
|
|
505
|
-
id="search"
|
|
506
|
-
name="teci-search[query]"
|
|
507
|
-
placeholder="Search"
|
|
508
|
-
type="search"
|
|
509
|
-
class="m-0 block w-full rounded-none border border-gray-300 bg-white py-2 pl-10 pr-3 placeholder-gray-500 focus:border-teci-blue-light focus:placeholder-gray-400 focus:outline-none focus:ring-1 focus:ring-teci-blue-light sm:text-sm"
|
|
510
|
-
/>
|
|
511
|
-
</div>
|
|
512
|
-
</form>
|
|
485
|
+
<SearchBar
|
|
486
|
+
id="GlobalSearch"
|
|
487
|
+
placeholder="Search"
|
|
488
|
+
placeholderShort="Search"
|
|
489
|
+
indices={[searchIndex]}
|
|
490
|
+
title=""
|
|
491
|
+
/>
|
|
513
492
|
</div>
|
|
514
493
|
</div>
|
|
515
494
|
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { getModalStore } from "@skeletonlabs/skeleton";
|
|
3
|
+
|
|
4
|
+
export let id, placeholder, placeholderShort, filters, title, indices;
|
|
5
|
+
export let showRefinements = undefined;
|
|
6
|
+
|
|
7
|
+
const modalStore = getModalStore();
|
|
8
|
+
|
|
9
|
+
const modal = {
|
|
10
|
+
type: 'component',
|
|
11
|
+
component: "search",
|
|
12
|
+
backdropClasses: 'bg-gray-500/50 z-[999] overscroll-none p-0 m-0',
|
|
13
|
+
modalClasses: 'p-0 m-0',
|
|
14
|
+
meta: {
|
|
15
|
+
id,
|
|
16
|
+
placeholder,
|
|
17
|
+
placeholderShort,
|
|
18
|
+
filters,
|
|
19
|
+
title,
|
|
20
|
+
indices,
|
|
21
|
+
//If we explicitly say to show/hide refinements, obey that.
|
|
22
|
+
// Otherwise, derive refinement visibility from pre-applied filters
|
|
23
|
+
showRefinements: showRefinements === undefined ? filters === undefined : showRefinements
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
let isModalOpen = false;
|
|
28
|
+
|
|
29
|
+
modalStore.subscribe(modals => {
|
|
30
|
+
isModalOpen = modals.length > 0 ? true : false;
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
function triggerSearch()
|
|
34
|
+
{
|
|
35
|
+
modalStore.trigger(modal)
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
let isCtrlDown = false;
|
|
39
|
+
let isKDown = false;
|
|
40
|
+
|
|
41
|
+
function onKeyMove(e, value)
|
|
42
|
+
{
|
|
43
|
+
switch(e.key)
|
|
44
|
+
{
|
|
45
|
+
case "Control":
|
|
46
|
+
isCtrlDown = value;
|
|
47
|
+
break;
|
|
48
|
+
case "k":
|
|
49
|
+
isKDown = value;
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (isCtrlDown && isKDown && !isModalOpen)
|
|
54
|
+
{
|
|
55
|
+
triggerSearch()
|
|
56
|
+
e.preventDefault();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
</script>
|
|
61
|
+
|
|
62
|
+
<svelte:window
|
|
63
|
+
on:keydown={(e) => onKeyMove(e, true)}
|
|
64
|
+
on:keyup={(e) => onKeyMove(e, false)}
|
|
65
|
+
/>
|
|
66
|
+
|
|
67
|
+
<button
|
|
68
|
+
class="flex flex-row items-center w-[95%] h-12 border border-gray-300 bg-white focus:border-teci-blue-light focus:outline-none focus:ring-1 focus:ring-teci-blue-light text-sm ml-2 -mr-2 my-2 p-2 align-middle text-start hover:scale-[102%] transition-all delay-50 ease-in-out"
|
|
69
|
+
on:click={triggerSearch}
|
|
70
|
+
>
|
|
71
|
+
<span class="hidden md:flex">{placeholder}</span>
|
|
72
|
+
<span class="flex md:hidden">{placeholderShort}</span>
|
|
73
|
+
<div class="hidden md:flex flex-grow"></div>
|
|
74
|
+
<span class="hidden md:flex">Ctrl+K</span>
|
|
75
|
+
</button>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/** @typedef {typeof __propDef.props} SearchBarProps */
|
|
2
|
+
/** @typedef {typeof __propDef.events} SearchBarEvents */
|
|
3
|
+
/** @typedef {typeof __propDef.slots} SearchBarSlots */
|
|
4
|
+
export default class SearchBar extends SvelteComponent<{
|
|
5
|
+
title: any;
|
|
6
|
+
id: any;
|
|
7
|
+
placeholder: any;
|
|
8
|
+
placeholderShort: any;
|
|
9
|
+
filters: any;
|
|
10
|
+
indices: any;
|
|
11
|
+
showRefinements?: any;
|
|
12
|
+
}, {
|
|
13
|
+
[evt: string]: CustomEvent<any>;
|
|
14
|
+
}, {}> {
|
|
15
|
+
}
|
|
16
|
+
export type SearchBarProps = typeof __propDef.props;
|
|
17
|
+
export type SearchBarEvents = typeof __propDef.events;
|
|
18
|
+
export type SearchBarSlots = typeof __propDef.slots;
|
|
19
|
+
import { SvelteComponent } from "svelte";
|
|
20
|
+
declare const __propDef: {
|
|
21
|
+
props: {
|
|
22
|
+
title: any;
|
|
23
|
+
id: any;
|
|
24
|
+
placeholder: any;
|
|
25
|
+
placeholderShort: any;
|
|
26
|
+
filters: any;
|
|
27
|
+
indices: any;
|
|
28
|
+
showRefinements?: any;
|
|
29
|
+
};
|
|
30
|
+
events: {
|
|
31
|
+
[evt: string]: CustomEvent<any>;
|
|
32
|
+
};
|
|
33
|
+
slots: {};
|
|
34
|
+
exports?: {};
|
|
35
|
+
bindings?: string;
|
|
36
|
+
};
|
|
37
|
+
export {};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { humanizeProduct } from "../../StyleUtils";
|
|
3
|
+
import { instantMeiliSearch } from "@meilisearch/instant-meilisearch";
|
|
4
|
+
import { getModalStore } from "@skeletonlabs/skeleton";
|
|
5
|
+
import { onMount } from "svelte";
|
|
6
|
+
import { Configure, SearchBox, InstantSearch } from "svelte-algolia-instantsearch";
|
|
7
|
+
import TeciSearchHits from "./TeciSearchHits.svelte";
|
|
8
|
+
import TeciSearchBox from "./TeciSearchBox.svelte";
|
|
9
|
+
|
|
10
|
+
const modalStore = getModalStore();
|
|
11
|
+
|
|
12
|
+
export let parent;
|
|
13
|
+
|
|
14
|
+
const { type, component, meta } = $modalStore[0]
|
|
15
|
+
const { id, placeholder, placeholderShort, filters, title, indices, showRefinements } = meta;
|
|
16
|
+
|
|
17
|
+
const { searchClient, setMeiliSearchParams } = instantMeiliSearch (
|
|
18
|
+
"https://ms-6689ffd3d866-29089.nyc.meilisearch.io",
|
|
19
|
+
"d9f20886cbbbe171f3933dc93a1ec38e365d53f072854e5d9f92a9b130fa1f7d"
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
onMount(() => {
|
|
23
|
+
const searchBoxes = document.getElementsByClassName("ais-SearchBox");
|
|
24
|
+
for (let i = 0; i < searchBoxes.length; i++)
|
|
25
|
+
{
|
|
26
|
+
const box = searchBoxes[i]
|
|
27
|
+
if (box.checkVisibility())
|
|
28
|
+
{
|
|
29
|
+
const form = box.firstChild
|
|
30
|
+
const input = form.firstChild
|
|
31
|
+
input.focus()
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
})
|
|
35
|
+
</script>
|
|
36
|
+
|
|
37
|
+
<div id="{id}Modal" class="shadow-xl max-w-[95%] md:max-w-[75%] w-full pt-12">
|
|
38
|
+
<InstantSearch
|
|
39
|
+
indexName={indices[0]}
|
|
40
|
+
{searchClient}
|
|
41
|
+
>
|
|
42
|
+
<Configure filters={filters} />
|
|
43
|
+
|
|
44
|
+
{#if title}
|
|
45
|
+
<h3 class="w-full text-xl font-bold">{title}</h3>
|
|
46
|
+
{/if}
|
|
47
|
+
|
|
48
|
+
<TeciSearchBox placeholder={placeholder} placeholderShort={placeholderShort}/>
|
|
49
|
+
|
|
50
|
+
<TeciSearchHits showRefinements={showRefinements}/>
|
|
51
|
+
|
|
52
|
+
</InstantSearch>
|
|
53
|
+
</div>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** @typedef {typeof __propDef.props} SearchModalProps */
|
|
2
|
+
/** @typedef {typeof __propDef.events} SearchModalEvents */
|
|
3
|
+
/** @typedef {typeof __propDef.slots} SearchModalSlots */
|
|
4
|
+
export default class SearchModal extends SvelteComponent<{
|
|
5
|
+
parent: any;
|
|
6
|
+
}, {
|
|
7
|
+
[evt: string]: CustomEvent<any>;
|
|
8
|
+
}, {}> {
|
|
9
|
+
}
|
|
10
|
+
export type SearchModalProps = typeof __propDef.props;
|
|
11
|
+
export type SearchModalEvents = typeof __propDef.events;
|
|
12
|
+
export type SearchModalSlots = typeof __propDef.slots;
|
|
13
|
+
import { SvelteComponent } from "svelte";
|
|
14
|
+
declare const __propDef: {
|
|
15
|
+
props: {
|
|
16
|
+
parent: any;
|
|
17
|
+
};
|
|
18
|
+
events: {
|
|
19
|
+
[evt: string]: CustomEvent<any>;
|
|
20
|
+
};
|
|
21
|
+
slots: {};
|
|
22
|
+
exports?: {};
|
|
23
|
+
bindings?: string;
|
|
24
|
+
};
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { SearchBox } from "svelte-algolia-instantsearch";
|
|
3
|
+
|
|
4
|
+
export let placeholder;
|
|
5
|
+
export let placeholderShort;
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<SearchBox
|
|
9
|
+
classes={{
|
|
10
|
+
root: "hidden md:flex w-full",
|
|
11
|
+
form: "w-full relative",
|
|
12
|
+
input: "w-full pl-8 text-xl py-4",
|
|
13
|
+
submit: "absolute left-0 top-1/2 w-6 h-6 -translate-y-1/2 translate-x-1/2",
|
|
14
|
+
submitIcon: "w-3 h-3",
|
|
15
|
+
reset: "absolute hidden right-0 top-0 w-0 h-0"
|
|
16
|
+
}}
|
|
17
|
+
placeholder={placeholder}
|
|
18
|
+
/>
|
|
19
|
+
|
|
20
|
+
<SearchBox
|
|
21
|
+
classes={{
|
|
22
|
+
root: "flex md:hidden w-full",
|
|
23
|
+
form: "w-full relative",
|
|
24
|
+
input: "w-full pl-8 py-4 text-xl",
|
|
25
|
+
submit: "absolute left-0 top-1/2 w-6 h-6 -translate-y-1/2 translate-x-1/2",
|
|
26
|
+
reset: "absolute hidden right-0 top-0 w-0 h-0"
|
|
27
|
+
}}
|
|
28
|
+
placeholder={placeholderShort}
|
|
29
|
+
/>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/** @typedef {typeof __propDef.props} TeciSearchBoxProps */
|
|
2
|
+
/** @typedef {typeof __propDef.events} TeciSearchBoxEvents */
|
|
3
|
+
/** @typedef {typeof __propDef.slots} TeciSearchBoxSlots */
|
|
4
|
+
export default class TeciSearchBox extends SvelteComponent<{
|
|
5
|
+
placeholder: any;
|
|
6
|
+
placeholderShort: any;
|
|
7
|
+
}, {
|
|
8
|
+
[evt: string]: CustomEvent<any>;
|
|
9
|
+
}, {}> {
|
|
10
|
+
}
|
|
11
|
+
export type TeciSearchBoxProps = typeof __propDef.props;
|
|
12
|
+
export type TeciSearchBoxEvents = typeof __propDef.events;
|
|
13
|
+
export type TeciSearchBoxSlots = typeof __propDef.slots;
|
|
14
|
+
import { SvelteComponent } from "svelte";
|
|
15
|
+
declare const __propDef: {
|
|
16
|
+
props: {
|
|
17
|
+
placeholder: any;
|
|
18
|
+
placeholderShort: any;
|
|
19
|
+
};
|
|
20
|
+
events: {
|
|
21
|
+
[evt: string]: CustomEvent<any>;
|
|
22
|
+
};
|
|
23
|
+
slots: {};
|
|
24
|
+
exports?: {};
|
|
25
|
+
bindings?: string;
|
|
26
|
+
};
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import connectStats from "instantsearch.js/es/connectors/stats/connectStats";
|
|
3
|
+
import { connect, Hits, Highlight, RefinementList, CurrentRefinements, Menu, ClearRefinements } from "svelte-algolia-instantsearch";
|
|
4
|
+
import { writable } from "svelte/store";
|
|
5
|
+
import Panel from "./TeciSearchRefinementPanel.svelte";
|
|
6
|
+
|
|
7
|
+
export let showRefinements = true;
|
|
8
|
+
|
|
9
|
+
const stats = connect(connectStats)
|
|
10
|
+
|
|
11
|
+
const state = new writable({})
|
|
12
|
+
let previewArea;
|
|
13
|
+
|
|
14
|
+
state.subscribe((hit) =>
|
|
15
|
+
{
|
|
16
|
+
if (hit.href)
|
|
17
|
+
{
|
|
18
|
+
const hitPreview = document.getElementById(`${hit.id}Preview`);
|
|
19
|
+
previewArea.innerHTML = hitPreview.innerHTML
|
|
20
|
+
}
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
function navigateToSelection(hit)
|
|
24
|
+
{
|
|
25
|
+
document.getElementById(`${hit.id}Link`).click();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function handleKeyPress(e)
|
|
29
|
+
{
|
|
30
|
+
const hitsList = document.getElementsByClassName("ais-Hits-list")[0];
|
|
31
|
+
|
|
32
|
+
switch (e.key)
|
|
33
|
+
{
|
|
34
|
+
case "Enter":
|
|
35
|
+
if ($state.href)
|
|
36
|
+
{
|
|
37
|
+
navigateToSelection($state)
|
|
38
|
+
}
|
|
39
|
+
else if (hitsList.children.length > 0)
|
|
40
|
+
{
|
|
41
|
+
const firstResult = hitsList.children[0];
|
|
42
|
+
const firstLink = firstResult.getElementsByClassName("hitLink")[0];
|
|
43
|
+
firstLink.click();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
e.preventDefault();
|
|
47
|
+
break;
|
|
48
|
+
case "ArrowDown":
|
|
49
|
+
if ($state.__position)
|
|
50
|
+
{
|
|
51
|
+
const newTargetPos = $state.__position + 1;
|
|
52
|
+
if (newTargetPos <= hitsList.children.length)
|
|
53
|
+
{
|
|
54
|
+
const newTarget = hitsList.children[newTargetPos - 1];
|
|
55
|
+
const targetButton = newTarget.getElementsByClassName("hitButton")[0];
|
|
56
|
+
targetButton.focus();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
else
|
|
60
|
+
{
|
|
61
|
+
const newTarget = hitsList.children[0];
|
|
62
|
+
const targetButton = newTarget.getElementsByClassName("hitButton")[0];
|
|
63
|
+
targetButton.focus();
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
e.preventDefault();
|
|
67
|
+
break;
|
|
68
|
+
case "ArrowUp":
|
|
69
|
+
if ($state.__position)
|
|
70
|
+
{
|
|
71
|
+
const newTargetPos = $state.__position - 1;
|
|
72
|
+
if (newTargetPos >= 0)
|
|
73
|
+
{
|
|
74
|
+
const newTarget = hitsList.children[newTargetPos - 1];
|
|
75
|
+
const targetButton = newTarget.getElementsByClassName("hitButton")[0];
|
|
76
|
+
targetButton.focus();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
else
|
|
80
|
+
{
|
|
81
|
+
const newTarget = hitsList.children[0];
|
|
82
|
+
const targetButton = newTarget.getElementsByClassName("hitButton")[0];
|
|
83
|
+
targetButton.focus();
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
e.preventDefault();
|
|
87
|
+
break;
|
|
88
|
+
default:
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
</script>
|
|
95
|
+
|
|
96
|
+
<svelte:window on:keydown={(e) => handleKeyPress(e)} />
|
|
97
|
+
|
|
98
|
+
{#if $stats.query}
|
|
99
|
+
<section class="searchHits flex flex-row h-[80vh] bg-white">
|
|
100
|
+
|
|
101
|
+
{#if showRefinements}
|
|
102
|
+
<div class="hidden xl:flex flex-col w-1/5">
|
|
103
|
+
<Panel title="Category">
|
|
104
|
+
<Menu
|
|
105
|
+
attribute="category"
|
|
106
|
+
sortBy={["name"]}
|
|
107
|
+
classes={{
|
|
108
|
+
selectedItem: "font-bold"
|
|
109
|
+
}}
|
|
110
|
+
/>
|
|
111
|
+
</Panel>
|
|
112
|
+
|
|
113
|
+
<Panel title="Products">
|
|
114
|
+
<RefinementList
|
|
115
|
+
attribute="products"
|
|
116
|
+
operator="and"
|
|
117
|
+
sortBy={["name"]}
|
|
118
|
+
classes={{
|
|
119
|
+
noResults: "hidden",
|
|
120
|
+
disabledShowMore: "hidden"
|
|
121
|
+
}}
|
|
122
|
+
transformItems={(items) => {
|
|
123
|
+
let finishedItems = [];
|
|
124
|
+
|
|
125
|
+
items.forEach(item => {
|
|
126
|
+
const label = ["usage", "Usage (Internal)"].includes(item.label) ? undefined : item.label;
|
|
127
|
+
|
|
128
|
+
if (label)
|
|
129
|
+
{
|
|
130
|
+
finishedItems.push({...item, label})
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
return finishedItems;
|
|
135
|
+
}}
|
|
136
|
+
/>
|
|
137
|
+
</Panel>
|
|
138
|
+
|
|
139
|
+
<Panel title="Version">
|
|
140
|
+
<RefinementList
|
|
141
|
+
attribute="version"
|
|
142
|
+
operator="and"
|
|
143
|
+
sortBy={["name:desc"]}
|
|
144
|
+
classes={{
|
|
145
|
+
noResults: "hidden",
|
|
146
|
+
disabledShowMore: "hidden"
|
|
147
|
+
}}
|
|
148
|
+
/>
|
|
149
|
+
</Panel>
|
|
150
|
+
</div>
|
|
151
|
+
{/if}
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
<div class="flex flex-col w-1/2">
|
|
155
|
+
|
|
156
|
+
{#if showRefinements}
|
|
157
|
+
<Panel>
|
|
158
|
+
<CurrentRefinements />
|
|
159
|
+
<ClearRefinements
|
|
160
|
+
classes={{
|
|
161
|
+
disabledButton: "hidden"
|
|
162
|
+
}}
|
|
163
|
+
translations={{resetButtonText: "Clear Filters"}}
|
|
164
|
+
/>
|
|
165
|
+
</Panel>
|
|
166
|
+
{/if}
|
|
167
|
+
|
|
168
|
+
<!-- List of hits -->
|
|
169
|
+
<Hits
|
|
170
|
+
let:hit
|
|
171
|
+
classes={{
|
|
172
|
+
root: "flex-grow border-r md:w-full overflow-y-auto overscroll-contain",
|
|
173
|
+
emptyRoot: "",
|
|
174
|
+
list: "flex flex-col",
|
|
175
|
+
item: "w-full border-b"
|
|
176
|
+
}}
|
|
177
|
+
>
|
|
178
|
+
<!-- Left Rail Buttons -->
|
|
179
|
+
<button
|
|
180
|
+
on:click={() => {navigateToSelection(hit)}}
|
|
181
|
+
on:mouseenter={() => {state.update(_ => hit)}}
|
|
182
|
+
on:focus={() => {state.update(_ => hit)}}
|
|
183
|
+
class="hitButton flex flex-row items-center w-full text-start px-2 py-2 pt-4 {$state.__position == hit.__position ? "bg-teci-blue-light/50" : "bg-white"}"
|
|
184
|
+
>
|
|
185
|
+
<div class="flex flex-col items-start">
|
|
186
|
+
<p class="my-0 text-xs">{hit.breadcrumb}</p>
|
|
187
|
+
<h3 class="text-lg font-bold text-black no-underline"><Highlight {hit} attribute="title" /></h3>
|
|
188
|
+
</div>
|
|
189
|
+
|
|
190
|
+
<div class="flex-grow min-w-[10%]"></div>
|
|
191
|
+
|
|
192
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6 mr-1 p-1 flex-shrink-0 bg-white shadow">
|
|
193
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="m7.49 12-3.75 3.75m0 0 3.75 3.75m-3.75-3.75h16.5V4.499" />
|
|
194
|
+
</svg>
|
|
195
|
+
</button>
|
|
196
|
+
|
|
197
|
+
<!-- Hidden Links to navigate to pages -->
|
|
198
|
+
<a id="{hit.id}Link" rel="external" href="{hit.href}" class="hitLink hidden w-0 h-0">{hit.title}</a>
|
|
199
|
+
|
|
200
|
+
<!-- Pre-rendered hit previews -->
|
|
201
|
+
<div id="{hit.id}Preview" class="hidden">
|
|
202
|
+
<!-- Heading -->
|
|
203
|
+
<div class="flex flex-col">
|
|
204
|
+
<p class="my-0 text-xs text-center pt-4"><Highlight {hit} attribute="breadcrumb" /></p>
|
|
205
|
+
<h2 class="text-2xl font-bold text-black no-underline text-center pt-2"><Highlight {hit} attribute="title" /></h2>
|
|
206
|
+
<p class="mb-4 py-4 border-b text-center"><Highlight {hit} attribute="summary" /></p>
|
|
207
|
+
</div>
|
|
208
|
+
|
|
209
|
+
<!-- Content Preview -->
|
|
210
|
+
<div class="flex flex-col">
|
|
211
|
+
<h4 class="text-lg font-bold text-black uppercase">Preview</h4>
|
|
212
|
+
<p class="line-clamp-4 mb-4"><Highlight {hit} attribute="content" /></p>
|
|
213
|
+
</div>
|
|
214
|
+
|
|
215
|
+
<!-- On This Page headings -->
|
|
216
|
+
{#if hit.toc.length > 0}
|
|
217
|
+
<div class="flex flex-col">
|
|
218
|
+
<h4 class="font-bold text-black uppercase">On This Page</h4>
|
|
219
|
+
|
|
220
|
+
<ol class="flex flex-col space-y-2 pl-2 pt-2">
|
|
221
|
+
{#each hit.toc as heading}
|
|
222
|
+
<li class="
|
|
223
|
+
border-b
|
|
224
|
+
{heading.level == 3 ? "ml-8" : ""}
|
|
225
|
+
{heading.level == 4 ? "ml-12" : ""}
|
|
226
|
+
{heading.level == 5 ? "ml-16" : ""}
|
|
227
|
+
">
|
|
228
|
+
<a
|
|
229
|
+
href="{hit.href}{heading.tagRef}"
|
|
230
|
+
rel="external"
|
|
231
|
+
class="hover:text-teci-blue-light"
|
|
232
|
+
>
|
|
233
|
+
{heading.text}
|
|
234
|
+
</a>
|
|
235
|
+
</li>
|
|
236
|
+
{/each}
|
|
237
|
+
</ol>
|
|
238
|
+
</div>
|
|
239
|
+
|
|
240
|
+
{/if}
|
|
241
|
+
</div>
|
|
242
|
+
|
|
243
|
+
</Hits>
|
|
244
|
+
|
|
245
|
+
<footer class="teciSearchHitsFooter flex flex-row bg-gray-100 p-2">
|
|
246
|
+
<ul class="flex flex-row space-x-2">
|
|
247
|
+
<li class="flex flex-row space-x-1">
|
|
248
|
+
<kbd>
|
|
249
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6 mr-1 p-1 flex-shrink-0 bg-white shadow-lg">
|
|
250
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M4.5 10.5 12 3m0 0 7.5 7.5M12 3v18" />
|
|
251
|
+
</svg>
|
|
252
|
+
</kbd>
|
|
253
|
+
<kbd>
|
|
254
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6 mr-1 p-1 flex-shrink-0 bg-white shadow-lg">
|
|
255
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M19.5 13.5 12 21m0 0-7.5-7.5M12 21V3" />
|
|
256
|
+
</svg>
|
|
257
|
+
</kbd>
|
|
258
|
+
<span>Navigate</span>
|
|
259
|
+
</li>
|
|
260
|
+
<li class="flex flex-row space-x-1">
|
|
261
|
+
<kbd>
|
|
262
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6 mr-1 p-1 flex-shrink-0 bg-white shadow-lg">
|
|
263
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="m7.49 12-3.75 3.75m0 0 3.75 3.75m-3.75-3.75h16.5V4.499" />
|
|
264
|
+
</svg>
|
|
265
|
+
</kbd>
|
|
266
|
+
<span>Select</span>
|
|
267
|
+
</li>
|
|
268
|
+
<li class="flex flex-row space-x-1 items-center text-center">
|
|
269
|
+
<kbd class="h-6 w-8 mr-1 p-1 flex-shrink-0 bg-white shadow-lg items-center text-center text-xs">
|
|
270
|
+
ESC
|
|
271
|
+
</kbd>
|
|
272
|
+
<span>Close</span>
|
|
273
|
+
</li>
|
|
274
|
+
</ul>
|
|
275
|
+
</footer>
|
|
276
|
+
|
|
277
|
+
</div>
|
|
278
|
+
|
|
279
|
+
<!-- Selected Hit Preview -->
|
|
280
|
+
<div bind:this={previewArea} class="hidden md:flex flex-col md:w-1/2 overflow-y-auto overscroll-contain p-4 space-y-4">
|
|
281
|
+
</div>
|
|
282
|
+
|
|
283
|
+
</section>
|
|
284
|
+
{/if}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** @typedef {typeof __propDef.props} TeciSearchHitsProps */
|
|
2
|
+
/** @typedef {typeof __propDef.events} TeciSearchHitsEvents */
|
|
3
|
+
/** @typedef {typeof __propDef.slots} TeciSearchHitsSlots */
|
|
4
|
+
export default class TeciSearchHits extends SvelteComponent<{
|
|
5
|
+
showRefinements?: boolean;
|
|
6
|
+
}, {
|
|
7
|
+
[evt: string]: CustomEvent<any>;
|
|
8
|
+
}, {}> {
|
|
9
|
+
}
|
|
10
|
+
export type TeciSearchHitsProps = typeof __propDef.props;
|
|
11
|
+
export type TeciSearchHitsEvents = typeof __propDef.events;
|
|
12
|
+
export type TeciSearchHitsSlots = typeof __propDef.slots;
|
|
13
|
+
import { SvelteComponent } from "svelte";
|
|
14
|
+
declare const __propDef: {
|
|
15
|
+
props: {
|
|
16
|
+
showRefinements?: boolean;
|
|
17
|
+
};
|
|
18
|
+
events: {
|
|
19
|
+
[evt: string]: CustomEvent<any>;
|
|
20
|
+
};
|
|
21
|
+
slots: {};
|
|
22
|
+
exports?: {};
|
|
23
|
+
bindings?: string;
|
|
24
|
+
};
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/** @typedef {typeof __propDef.props} TeciSearchRefinementPanelProps */
|
|
2
|
+
/** @typedef {typeof __propDef.events} TeciSearchRefinementPanelEvents */
|
|
3
|
+
/** @typedef {typeof __propDef.slots} TeciSearchRefinementPanelSlots */
|
|
4
|
+
export default class TeciSearchRefinementPanel extends SvelteComponent<{
|
|
5
|
+
title?: any;
|
|
6
|
+
}, {
|
|
7
|
+
[evt: string]: CustomEvent<any>;
|
|
8
|
+
}, {
|
|
9
|
+
default: {};
|
|
10
|
+
}> {
|
|
11
|
+
}
|
|
12
|
+
export type TeciSearchRefinementPanelProps = typeof __propDef.props;
|
|
13
|
+
export type TeciSearchRefinementPanelEvents = typeof __propDef.events;
|
|
14
|
+
export type TeciSearchRefinementPanelSlots = typeof __propDef.slots;
|
|
15
|
+
import { SvelteComponent } from "svelte";
|
|
16
|
+
declare const __propDef: {
|
|
17
|
+
props: {
|
|
18
|
+
title?: any;
|
|
19
|
+
};
|
|
20
|
+
events: {
|
|
21
|
+
[evt: string]: CustomEvent<any>;
|
|
22
|
+
};
|
|
23
|
+
slots: {
|
|
24
|
+
default: {};
|
|
25
|
+
};
|
|
26
|
+
exports?: {};
|
|
27
|
+
bindings?: string;
|
|
28
|
+
};
|
|
29
|
+
export {};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { default as SearchBar } from "./SearchBar.svelte";
|
|
2
|
+
export { default as SearchModal } from "./SearchModal.svelte";
|
|
3
|
+
export { default as TeciSearchBox } from "./TeciSearchBox.svelte";
|
|
4
|
+
export { default as TeciSearchHits } from "./TeciSearchHits.svelte";
|
|
5
|
+
export { default as RefinementPanel } from "./TeciSearchRefinementPanel.svelte";
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { default as SearchBar } from './SearchBar.svelte';
|
|
2
|
+
export { default as SearchModal } from './SearchModal.svelte';
|
|
3
|
+
export { default as TeciSearchBox } from './TeciSearchBox.svelte';
|
|
4
|
+
export { default as TeciSearchHits } from './TeciSearchHits.svelte';
|
|
5
|
+
export { default as RefinementPanel } from './TeciSearchRefinementPanel.svelte';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export * from "./utils.js";
|
|
2
|
+
export * from "./ArrayUtils.js";
|
|
3
|
+
export * from "./StyleUtils.js";
|
|
2
4
|
export { default as getContent } from "./get-content.js";
|
|
3
5
|
export { default as Accordion } from "./components/Accordion.svelte";
|
|
4
6
|
export { default as Banner } from "./components/Banner.svelte";
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tecitheme",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"dev": "vite dev",
|
|
@@ -21,6 +21,10 @@
|
|
|
21
21
|
".": {
|
|
22
22
|
"types": "./dist/index.d.ts",
|
|
23
23
|
"svelte": "./dist/index.js"
|
|
24
|
+
},
|
|
25
|
+
"./search": {
|
|
26
|
+
"types": "./dist/components/Search/index.d.ts",
|
|
27
|
+
"svelte": "./dist/components/Search/index.js"
|
|
24
28
|
}
|
|
25
29
|
},
|
|
26
30
|
"files": [
|
|
@@ -67,8 +71,13 @@
|
|
|
67
71
|
},
|
|
68
72
|
"dependencies": {
|
|
69
73
|
"@designbycode/tailwindcss-mask-image": "^2.0.3",
|
|
74
|
+
"@meilisearch/instant-meilisearch": "^0.29.0",
|
|
75
|
+
"@skeletonlabs/skeleton": "^2.11.0",
|
|
76
|
+
"@skeletonlabs/tw-plugin": "^0.4.1",
|
|
77
|
+
"instantsearch.js": "^4.81.0",
|
|
70
78
|
"katex": "^0.16.8",
|
|
71
79
|
"slugify": "^1.6.6",
|
|
72
|
-
"svelte": "^4.0.5"
|
|
80
|
+
"svelte": "^4.0.5",
|
|
81
|
+
"svelte-algolia-instantsearch": "^0.12.1"
|
|
73
82
|
}
|
|
74
83
|
}
|