hds-web 1.16.1 → 1.16.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hds-web",
3
- "version": "1.16.1",
3
+ "version": "1.16.3",
4
4
  "private": false,
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.es.js",
@@ -1,3 +1,3 @@
1
1
  <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
2
- <path d="M21 21L15.0001 15M17 10C17 13.866 13.866 17 10 17C6.13401 17 3 13.866 3 10C3 6.13401 6.13401 3 10 3C13.866 3 17 6.13401 17 10Z" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
2
+ <path d="M21 21L15.0001 15M17 10C17 13.866 13.866 17 10 17C6.13401 17 3 13.866 3 10C3 6.13401 6.13401 3 10 3C13.866 3 17 6.13401 17 10Z" stroke-linecap="round" stroke-linejoin="round"/>
3
3
  </svg>
@@ -26,7 +26,7 @@ export default function FlyoutA(props) {
26
26
  {label}
27
27
  </Typography>) : (
28
28
  <div className="mb-9">
29
- </div>
29
+ </div>
30
30
  )}
31
31
  <div className={` tb:tb:grid tb:tb:grid-cols-1 tb:gap-x-4 tb:min-w-[182px] `}>
32
32
  {childArray && childArray.map((item) => (
@@ -110,28 +110,28 @@ export default function FlyoutA(props) {
110
110
 
111
111
  (
112
112
  <>
113
-
114
- <div className="hidden tb-l:flex h-full">
115
- <div className="border-r border-neutral-150 shadow rounded-l-2xl">
116
113
 
117
- {cardLayout(props.label, props.childArray.slice(0, Math.ceil(props.childArray.length / 2)))}
118
- </div>
119
- <div className="shadow rounded-r-2xl">
114
+ <div className="hds-hidden tb-l:flex h-full">
115
+ <div className="border-r border-neutral-150 shadow rounded-l-2xl">
120
116
 
121
- {cardLayout( null , props.childArray.slice(Math.ceil(props.childArray.length / 2)))}
122
- </div>
123
- </div>
124
- <div className="tb-l:hidden shadow h-full rounded-2xl">
125
- {cardLayout(props.label, props.childArray)}
126
- </div>
117
+ {cardLayout(props.label, props.childArray.slice(0, Math.ceil(props.childArray.length / 2)))}
118
+ </div>
119
+ <div className="shadow rounded-r-2xl">
120
+
121
+ {cardLayout(null, props.childArray.slice(Math.ceil(props.childArray.length / 2)))}
122
+ </div>
123
+ </div>
124
+ <div className="hds-hidden-tbl shadow h-full rounded-2xl">
125
+ {cardLayout(props.label, props.childArray)}
126
+ </div>
127
127
  </>
128
- )
128
+ )
129
129
 
130
130
  : (
131
131
  <div className=" shadow h-full rounded-2xl">
132
- {cardLayout(props.label, props.childArray)}
132
+ {cardLayout(props.label, props.childArray)}
133
133
  </div>
134
-
134
+
135
135
  )}
136
136
  </>
137
137
 
@@ -1,6 +1,4 @@
1
1
  import React, { useState, useEffect } from 'react';
2
- import { Fragment } from 'react';
3
- import { GithubWidget } from "./githubButton";
4
2
  import { Icon } from '../common-components/Icon';
5
3
  import { Typography } from '../../foundation/Typography';
6
4
  import { HDSButton } from '../Buttons';
@@ -8,6 +6,7 @@ import { V3Dropdown } from '../Cards/Dropdown'
8
6
  import { HDSColor } from '../../foundation/ColorPalette';
9
7
  import { motion } from "framer-motion"
10
8
  import { AnimatePresence } from 'framer-motion';
9
+ import { AlgoliaSearch } from '../../helpers/AlgoliaSearch';
11
10
 
12
11
  const solutions = [
13
12
  {
@@ -45,7 +44,7 @@ export default function V3Header(props) {
45
44
  const dropdownA = (solutions) => (
46
45
  <div>
47
46
  <div>
48
- <div className='w-full h-5 ' />
47
+ <hr className='w-full h-9 border-0 ' />
49
48
  </div>
50
49
 
51
50
  <div className=" p-2 bg-neutral-150 rounded-3xl ">
@@ -134,7 +133,9 @@ export default function V3Header(props) {
134
133
  )
135
134
  const dropdownB = (solutions) => (
136
135
  <div>
137
- <div className='w-full h-5 ' />
136
+ <div>
137
+ <hr className='w-full h-9 border-0 ' />
138
+ </div>
138
139
 
139
140
 
140
141
  <div className=" p-2 bg-neutral-150 rounded-3xl ">
@@ -301,7 +302,7 @@ export default function V3Header(props) {
301
302
  const dropdownC = (solutions) => (
302
303
  <div>
303
304
  <div>
304
- <div className='w-full h-5 ' />
305
+ <hr className='w-full h-9 border-0 ' />
305
306
  </div>
306
307
  <div className=" p-2 bg-neutral-150 rounded-3xl ">
307
308
  <V3Dropdown
@@ -425,7 +426,7 @@ export default function V3Header(props) {
425
426
  initial={{ opacity: 0 }}
426
427
  animate={{ opacity: 1 }}
427
428
  transition={{ ease: "easeInOut", duration: 0.1 }}
428
- className='absolute top-9 -left-[137px] z-[2] transform'>
429
+ className='absolute -left-[137px] z-[2] transform'>
429
430
  {dropdownA(HEADER_LIST[0]['titleDropdown'])}
430
431
  </motion.div>
431
432
  </div>
@@ -465,7 +466,7 @@ export default function V3Header(props) {
465
466
  initial={{ opacity: 0 }}
466
467
  animate={{ opacity: 1 }}
467
468
  transition={{ ease: "easeInOut", duration: 0.1 }}
468
- className='absolute top-9 -left-[218px] z-[2]'>
469
+ className='absolute -left-[218px] z-[2]'>
469
470
  {dropdownB(HEADER_LIST[1]['titleDropdown'])}
470
471
  </motion.div>
471
472
  </div>
@@ -503,7 +504,7 @@ export default function V3Header(props) {
503
504
  initial={{ opacity: 0 }}
504
505
  animate={{ opacity: 1 }}
505
506
  transition={{ ease: "easeInOut", duration: 0.1 }}
506
- className='absolute top-9 -left-[50px] z-[2] transform'>
507
+ className='absolute -left-[50px] z-[2] transform'>
507
508
  {dropdownC(HEADER_LIST[3]['titleDropdown'])}
508
509
  </motion.div>
509
510
  </div>
@@ -931,14 +932,19 @@ export default function V3Header(props) {
931
932
  <Icon height='w-[103px] h-[33px]' variant={'hasuraPrimary'} strokeColor={''} />
932
933
  </a>
933
934
  </div>
934
- <div className={"tb-l:hidden block z-[10] mr-[30px] h-5 mt-5 " + ((mobileNavOpen) ? "" : "")} onClick={() => handleMbDropdownClose()}>
935
- <div aria-hidden="true" className={`${class1} block absolute h-[2px] w-[15px] bg-neutral-800 transform transition duration-500 ease-in-out`}></div>
936
- <div aria-hidden="true" className={`${class3} block absolute h-0.5 w-[15px] bg-neutral-800 transform transition duration-500 ease-in-out`}></div>
935
+ <div className='hds-hidden-tbl flex z-[10] mr-[30px] items-center gap-6'>
936
+ <div className={'h-full ' + ((mobileNavOpen) ? " hds-hidden" : "")}>
937
+ <AlgoliaSearch {...props} />
938
+ </div>
939
+ <div className=' h-5 mt-3 cursor-pointer' onClick={() => handleMbDropdownClose()}>
940
+ <div aria-hidden="true" className={`${class1} block absolute h-[2px] w-[15px] bg-neutral-800 transform transition duration-500 ease-in-out`}></div>
941
+ <div aria-hidden="true" className={`${class3} block absolute h-0.5 w-[15px] bg-neutral-800 transform transition duration-500 ease-in-out`}></div>
942
+ </div>
937
943
  </div>
938
944
  </div>
939
- <div className='hidden tb-l:flex flex-row w-full justify-between items-center'>
945
+ <div className='hds-hidden tb-l:flex flex-row w-full justify-between items-center'>
940
946
 
941
- <nav className="hidden items-center relative tb-l:pl-8 tb-l:flex tb-l:space-x-6"
947
+ <nav className="hds-hidden items-center relative tb-l:pl-8 tb-l:flex tb-l:space-x-6"
942
948
  onMouseEnter={() => setIsArrowActive(true)}
943
949
  onMouseLeave={() => setIsArrowActive(false)}
944
950
 
@@ -963,61 +969,59 @@ export default function V3Header(props) {
963
969
 
964
970
  </nav>
965
971
 
966
- <div className='hidden tb-l:flex flex-row items-center gap-x-4 '>
967
-
968
-
969
- <a href='' className='hidden tb:flex'>
970
- <Typography textStyle='body3c-medium' className='text-neutral-800'>
971
- Contact Sales
972
- </Typography>
973
- </a>
974
- <HDSButton
975
- label="Log In"
976
- type='tonal'
977
- leftIconVariant='none'
978
- rightIconVariant='none'
979
- state='default'
980
- size='sm'
981
- rightAnimatedArrow='true'
982
- rightAnimatedArrowColor='#3970FD'
983
- animatedHoverStroke='group-hover:stroke-neutral-0'
984
- className='hidden tb-l:flex'
985
- />
986
- <HDSButton
987
- label="Get Started"
988
- type='primary'
989
- leftIconVariant='none'
990
- rightIconVariant='none'
991
- state='default'
992
- size='sm'
993
- rightAnimatedArrow='true'
994
- rightAnimatedArrowColor='#ffffff'
995
- animatedHoverStroke='group-hover:stroke-neutral-0'
996
- className='hidden tb:flex'
997
- />
972
+ <div className='hds-hidden tb-l:flex flex-row items-center gap-x-4 '>
973
+
974
+ <AlgoliaSearch {...props} />
975
+
976
+ <a href='' className='hds-hidden db:flex'>
977
+ <Typography textStyle='body3c-medium' className='text-neutral-800'>
978
+ Contact Sales
979
+ </Typography>
980
+ </a>
981
+ <HDSButton
982
+ label="Log In"
983
+ type='tonal'
984
+ leftIconVariant='none'
985
+ rightIconVariant='none'
986
+ state='default'
987
+ size='sm'
988
+ rightAnimatedArrow='true'
989
+ rightAnimatedArrowColor='#3970FD'
990
+ animatedHoverStroke='group-hover:stroke-neutral-0'
991
+ className='hds-hidden tb-l:flex'
992
+ />
993
+ <HDSButton
994
+ label="Get Started"
995
+ type='primary'
996
+ leftIconVariant='none'
997
+ rightIconVariant='none'
998
+ state='default'
999
+ size='sm'
1000
+ rightAnimatedArrow='true'
1001
+ rightAnimatedArrowColor='#ffffff'
1002
+ animatedHoverStroke='group-hover:stroke-neutral-0'
1003
+ className='hds-hidden tb:flex'
1004
+ />
998
1005
  </div>
999
1006
 
1000
1007
  </div>
1001
- <div className="tb-l:hidden overflow-auto flex ">
1008
+
1009
+ <div className="hds-hidden-tbl overflow-auto flex ">
1002
1010
  {/* <Popover.Button className="inline-flex items-center justify-center rounded-md bg-white pl-6 text-gray-400 hover:bg-gray-100 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-500">
1003
1011
  <span className="sr-only">Open menu</span> */}
1004
1012
 
1005
- <div className='bg-neutral-100 tb:hidden flex flex-row '>
1006
1013
 
1007
-
1008
-
1009
- </div>
1010
- <div className={"bg-neutral-100 tb-l:hidden block fixed w-full tb:max-w-[480px] tb:left-auto tb:right-4 mx-auto left-4 top-0 transform transition duration-500 ease-in-out h-[calc(100%-1px)] max-h-screen overflow-y-auto" + ((mobileNavOpen) ? " translate-x-0" : " translate-x-[1240px]")}>
1014
+ <div className={"bg-neutral-100 hds-hidden-tbl block fixed w-full tb:max-w-[480px] tb:left-auto tb:right-4 mx-auto left-4 top-0 transform transition duration-500 ease-in-out h-[calc(100%-1px)] max-h-screen overflow-y-auto" + ((mobileNavOpen) ? " translate-x-0" : " translate-x-[1240px]")}>
1011
1015
 
1012
1016
  <div className="bg-neutral-100 h-[calc(100%-80px)] rounded-2xl overflow-scroll ">
1013
1017
 
1014
- <div className='pt-11 pb-4 mr-[17px] min-h-[36px] flex flex-row justify-between items-center sticky top-0 bg-neutral-100 z-50 '>
1018
+ <div className='pt-9 pb-4 mr-[17px] min-h-[36px] flex flex-row justify-between items-center sticky top-0 bg-neutral-100 z-50 '>
1015
1019
  {(isCompany || isDeveloper || isProduct) && <div
1016
1020
  className=' flex flex-row justify-start z-10'
1017
1021
  onClick={() => handleBackClick()}
1018
1022
 
1019
1023
  >
1020
- <Icon height='w-5 h-5 ml-4' variant={'arrowleft'} strokeClass='stroke-neutral-1000' />
1024
+ <Icon height='w-5 h-5 ml-4 cursor-pointer' variant={'arrowleft'} strokeClass='stroke-neutral-1000' />
1021
1025
  </div>}
1022
1026
  <motion.div
1023
1027
  initial={{ opacity: 0 }}
@@ -1129,8 +1133,8 @@ export default function V3Header(props) {
1129
1133
  <div>
1130
1134
 
1131
1135
 
1132
- <div className="absolute h-[calc(100%-112px)] bg-base-0 z-[1] inset-x-0 top-0 origin-top-right hidden transform transition">
1133
- <div className=" rounded-lg bg-neutral-0 h-[calc(100%-112px)] shadow-lg">
1136
+ <div className="absolute h-[calc(100%-112px)] bg-base-0 z-[1] inset-x-0 top-0 origin-top-right hds-hidden transform transition">
1137
+ <div className=" rounded-lg bg-neutral-0 h-[calc(100%-112px)] shadow-lg">
1134
1138
  <div className="bg-neutral-0">
1135
1139
  {/* <div className="flex items-center justify-end">
1136
1140
  <div className="">
@@ -1139,7 +1143,7 @@ export default function V3Header(props) {
1139
1143
  </div>
1140
1144
  </div>
1141
1145
  </div> */}
1142
- <div className="mt-6 abcdefhgk flex flex-col gap-6">
1146
+ <div className="mt-6 flex flex-col gap-6">
1143
1147
  <div className='flex flex-col items-center'>
1144
1148
  <img
1145
1149
  className="inline-block w-full px-4 "
@@ -1148,7 +1152,7 @@ export default function V3Header(props) {
1148
1152
  />
1149
1153
  </div>
1150
1154
 
1151
- <nav className="grid divide-y divide-neutral-200 border border-neutral-200 rounded-3xl tb-l:hidden ">
1155
+ <nav className="grid divide-y divide-neutral-200 border border-neutral-200 rounded-3xl hds-hidden-tbl ">
1152
1156
  {props.HEADER_LIST.map((item) => (
1153
1157
  <div
1154
1158
  key={item['title']}
@@ -0,0 +1,48 @@
1
+ export const INDEX_TYPES = Object.freeze({
2
+ blog: "blog",
3
+ docs: "docs",
4
+ learn: "learn",
5
+ });
6
+
7
+ export const SEARCH_INDICES = [
8
+ { name: `blog-production`, title: `Hasura Blog`, type: INDEX_TYPES.blog },
9
+ { name: `graphql-docs-prod`, title: `Hasura GraphQL Engine Docs`, type: INDEX_TYPES.docs },
10
+ { name: `learn-intro-graphql`, title: `Learn Intro GraphQL`, type: INDEX_TYPES.learn },
11
+ { name: `learn-intro-graphql-zh`, title: `Learn Intro GraphQL`, type: INDEX_TYPES.learn },
12
+ { name: `learn-elm-graphql`, title: `Learn ELM GraphQl`, type: INDEX_TYPES.learn },
13
+ { name: `learn-flutter-graphql`, title: `Learn Flutter GraphQL`, type: INDEX_TYPES.learn },
14
+ { name: `learn-database-mysql`, title: `Learn Database MySQL`, type: INDEX_TYPES.learn },
15
+ {
16
+ name: `learn-database-postgresql`,
17
+ title: `Learn Database PostgreSQL`,
18
+ type: INDEX_TYPES.learn,
19
+ },
20
+ { name: `learn-hasura-backend`, title: `Learn Hasura Backend`, type: INDEX_TYPES.learn },
21
+ { name: `learn-hasura-backend-ja`, title: `Learn Hasura Backend`, type: INDEX_TYPES.learn },
22
+ { name: `learn-hasura-backend-zh`, title: `Learn Hasura Backend`, type: INDEX_TYPES.learn },
23
+ { name: `learn-hasura-backend-advanced`, title: `Learn Hasura Backend Advanced`, type: INDEX_TYPES.learn },
24
+ { name: `learn-hasura-auth-slack`, title: `Learn Hasura Auth Slack`, type: INDEX_TYPES.learn },
25
+ { name: `learn-react-apollo-hooks`, title: `Learn React Apollo Hooks`, type: INDEX_TYPES.learn },
26
+ { name: `learn-react-apollo`, title: `Learn React Apollo`, type: INDEX_TYPES.learn },
27
+ {
28
+ name: `learn-typescript-react-apollo`,
29
+ title: `Learn TypeScript React Apollo`,
30
+ type: INDEX_TYPES.learn,
31
+ },
32
+ { name: `learn-angular-apollo`, title: `Learn Angular Apollo`, type: INDEX_TYPES.learn },
33
+ { name: `learn-vue-apollo`, title: `Learn Vue Apollo`, type: INDEX_TYPES.learn },
34
+ { name: `learn-ios-apollo`, title: `Learn IOS Apollo`, type: INDEX_TYPES.learn },
35
+ { name: `learn-svelte-apollo`, title: `Learn Svelte Apollo`, type: INDEX_TYPES.learn },
36
+ { name: `learn-android-apollo`, title: `Learn Android Apollo`, type: INDEX_TYPES.learn },
37
+ {
38
+ name: `learn-react-native-apollo`,
39
+ title: `Learn React Native Apollo`,
40
+ type: INDEX_TYPES.learn,
41
+ },
42
+ {
43
+ name: `learn-reason-react-apollo`,
44
+ title: `Learn Reason React Apollo`,
45
+ type: INDEX_TYPES.learn,
46
+ },
47
+ { name: `learn-database-mssql`, title: `Learn MicrosoftSQL`, type: INDEX_TYPES.learn },
48
+ ];
@@ -0,0 +1 @@
1
+ export {default as AlgoliaSearch } from './search';
@@ -0,0 +1,40 @@
1
+ import React from "react";
2
+ import { useEffect, useState } from "react";
3
+ import SearchOverlay from "./searchoverlay";
4
+ import { Icon } from "../../components/common-components";
5
+ export default function Search(props) {
6
+ const [showSearch, setShowSearch] = useState(false);
7
+
8
+ const handleSearchWithKeyboard = e => {
9
+ if (e.key === "/" || e.key === "Escape") {
10
+ e.preventDefault();
11
+ if (e.key === "/") return setShowSearch(true);
12
+ if (e.key === "Escape") return onCloseSearch();
13
+ }
14
+
15
+ return null;
16
+ };
17
+
18
+ useEffect(() => {
19
+ document.addEventListener("keydown", handleSearchWithKeyboard);
20
+
21
+ return () => {
22
+ document.removeEventListener("keydown", handleSearchWithKeyboard);
23
+ };
24
+ }, []);
25
+
26
+ const onCloseSearch = () => setShowSearch(false);
27
+ return (
28
+ <>
29
+ <div className="">
30
+ <div className="max-w-7xl mx-auto">
31
+ <div className="w-full cursor-pointer gap-0.5 flex items-center" onClick={() => {setShowSearch(preShowSearch => !preShowSearch);}}>
32
+ <p className="-mt-1">/ </p>
33
+ <Icon height={'h-4 w-4 stroke-2'} variant={`searchsm`} strokeClass='stroke-neutral-1000' />
34
+ </div>
35
+ </div>
36
+ </div>
37
+ <SearchOverlay showSearch={showSearch} onCloseSearch={onCloseSearch} />
38
+ </>
39
+ );
40
+ }
@@ -0,0 +1,88 @@
1
+ import React, { useEffect, useRef, useState } from "react";
2
+ import { connectSearchBox } from "react-instantsearch-dom";
3
+ import { Icon } from '../../components/common-components/Icon'
4
+ import { Typography } from '../../foundation/Typography'
5
+ const searchSuggestions = [
6
+ "GraphQL",
7
+ "Actions",
8
+ "Authentication",
9
+ "React",
10
+ "Remote Joins",
11
+ "Postgres",
12
+ ];
13
+
14
+ const DebouncedSearchBox = ({
15
+ refine,
16
+ currentRefinement,
17
+ className,
18
+ delay = 500,
19
+ isSearchStalled,
20
+ }) => {
21
+ const [value, setValue] = useState(currentRefinement);
22
+ const timerId = useRef();
23
+ const searchInputRef = useRef();
24
+ useEffect(() => {
25
+ searchInputRef.current?.focus();
26
+ }, []);
27
+
28
+ const trySuggestion = inputValue => {
29
+ refine(inputValue);
30
+ setValue(inputValue);
31
+ };
32
+
33
+ const resetInput = () => {
34
+ refine("");
35
+ setValue("");
36
+ };
37
+
38
+ const onChangeDebounced = event => {
39
+ const value = event.target.value;
40
+
41
+ clearTimeout(timerId.current);
42
+ timerId.current = setTimeout(() => refine(value), delay);
43
+
44
+ setValue(value);
45
+ };
46
+ return (
47
+ <div className=" sticky -top-20 tb-m:-top-20 z-10 py-8 pt-16 tb-m:pt-16 tb-m:py-9 bg-neutral-50">
48
+ <div className="flex relative items-center w-full">
49
+ <div className="absolute left-2">
50
+ {isSearchStalled ? (
51
+ <div className="loader-spin border-[3px] border-neutral-400 border-t-blue-500 w-5 h-5 rounded-full" />
52
+ ) : (
53
+ <Icon height={'w-5 h-5 stroke-[1.5px]'} variant="searchsm" strokeClass="stroke-neutral-800" />
54
+ )}
55
+ </div>
56
+ <form className={`${className} w-full`} onSubmit={e => e.preventDefault()}>
57
+ <input
58
+ id="search-input"
59
+ ref={searchInputRef}
60
+ className="w-full indent-5 rounded-xl border-neutral-400 h-12"
61
+ type="text"
62
+ placeholder="Search for tutorials, articles or docs"
63
+ aria-label="Search"
64
+ onChange={onChangeDebounced}
65
+ value={value}
66
+ />
67
+ </form>
68
+ <div onClick={resetInput} className="absolute right-2 cursor-pointer bg-neutral-200 rounded-md">
69
+ <Icon height={'w-6 h-6 stroke-[1.5px]'} variant="xclose" strokeClass="stroke-neutral-800" />
70
+ </div>
71
+ </div>
72
+ <div className="hidden tb:flex flex-wrap items-center mt-4">
73
+ <Typography textStyle="body2c-bold" className="uppercase text-neutral-500 mr-4">POPULAR</Typography>
74
+ {searchSuggestions.map(suggestion => (
75
+ <button
76
+ key={suggestion}
77
+ className={`px-3 py-1 border rounded-md m-1 ${currentRefinement === suggestion ? "border-neutral-300 hover:bg-neutral-300 bg-neutral-300" : "bg-neutral-150 hover:bg-neutral-200 border-neutral-150"}`}
78
+ onClick={() => trySuggestion(suggestion)}
79
+ >
80
+ {suggestion}
81
+ </button>
82
+ ))}
83
+ </div>
84
+ </div>
85
+ );
86
+ };
87
+
88
+ export default connectSearchBox(DebouncedSearchBox);
@@ -0,0 +1,30 @@
1
+ import React, { Fragment } from "react";
2
+ import { PoweredBy } from "react-instantsearch-dom";
3
+
4
+ const SearchFooter = () => (
5
+ <Fragment>
6
+ <hr className="my-5 border-t-neutral-200" />
7
+ <div className="mt-12 flex flex-wrap justify-between">
8
+ <div className="community-links-wrapper">
9
+ <p>Unable to find what you're looking for?</p>
10
+ <p>
11
+ Reach out to our{" "}
12
+ <a className="text-blue-500 hover:text-blue-700" href="https://discord.com/invite/hasura" target="_blank" rel="noopener noreferrer">
13
+ Discord Community
14
+ </a>{" "}
15
+ or start a{" "}
16
+ <a className="text-blue-500 hover:text-blue-700"
17
+ href="https://github.com/hasura/graphql-engine/discussions"
18
+ target="_blank"
19
+ rel="noopener noreferrer"
20
+ >
21
+ Discussion on GitHub
22
+ </a>
23
+ </p>
24
+ </div>
25
+ <PoweredBy />
26
+ </div>
27
+ </Fragment>
28
+ );
29
+
30
+ export default SearchFooter;
@@ -0,0 +1,36 @@
1
+ import { useEffect, useState } from "react";
2
+ import { Icon } from '../../components/common-components/Icon'
3
+ import SearchWrapper from "./searchwrapper";
4
+ import { SEARCH_INDICES } from "./constants";
5
+
6
+ export default function SearchOverlay({showSearch, onCloseSearch}) {
7
+
8
+ useEffect(() => {
9
+ if (showSearch) {
10
+ document.body.style.overflow = "hidden";
11
+ }
12
+
13
+ return () => {
14
+ document.body.style.overflow = "unset";
15
+ };
16
+ }, [showSearch]);
17
+
18
+ if (!showSearch) return null;
19
+
20
+ return (
21
+ <div className="fixed left-0 top-0 w-full h-full z-[10000] bg-neutral-50">
22
+ <div className="absolute top-4 right-4 cursor-pointer z-[11]" onClick={onCloseSearch}>
23
+ <Icon height={'w-8 h-8 stroke-[1.5px]'} variant="xclose" strokeClass="stroke-neutral-800" />
24
+ </div>
25
+ <div className="py-20 overflow-y-auto h-full w-full">
26
+ <div className="px-4">
27
+ <div className="max-w-7xl mx-auto">
28
+ <div className="w-full">
29
+ <SearchWrapper indices={SEARCH_INDICES} />
30
+ </div>
31
+ </div>
32
+ </div>
33
+ </div>
34
+ </div>
35
+ );
36
+ }
@@ -0,0 +1,98 @@
1
+ import React, { Fragment } from "react";
2
+ import { connectStateResults, Highlight, Hits, Index, Snippet } from "react-instantsearch-dom";
3
+ import { INDEX_TYPES } from "./constants";
4
+ import SearchFooter from "./searchfooter";
5
+ import { Typography } from '../../foundation/Typography'
6
+
7
+ // import SearchFooter from "./SearchFooter";
8
+
9
+ const baseDomain = 'hasura.io';
10
+
11
+
12
+ const HitsHeader = ({ searchResults, indexTitle, showSeparator }) => {
13
+ const hitCount = searchResults && searchResults.nbHits;
14
+ return hitCount > 0 ? (
15
+ <Fragment>
16
+ {showSeparator && <hr className="my-5 border-t-neutral-200" />}
17
+ {/* <div className="HitCount">
18
+ {hitCount} result{hitCount !== 1 ? `s` : ``}
19
+ </div> */}
20
+ <Typography textStyle="body2c-medium" className="pb-4">{indexTitle}</Typography>
21
+ </Fragment>
22
+ ) : null;
23
+ };
24
+
25
+ const CustomHitsHeader = connectStateResults(HitsHeader);
26
+
27
+ const PageHit = ({ hit, indexType }) => (
28
+ <a href={hit.url} className="grid h-full">
29
+ <div className="self-start">
30
+ <Typography textStyle="body3c-medium" className="uppercase text-neutral-500">{indexType}</Typography>
31
+ {indexType === INDEX_TYPES.docs ? (
32
+ <Fragment>
33
+ {!!hit.hierarchy && (
34
+ <Typography textStyle="body1c-bold" className="font-semibold py-3">{`${
35
+ Object.values(hit.hierarchy)
36
+ .filter(h => !!h)
37
+ .reverse()[0]
38
+ }`}</Typography>
39
+ )}
40
+ <Typography textStyle="body2" className="text-neutral-600 break-words">
41
+ <Snippet attribute="content" hit={hit} tagName="mark" />
42
+ </Typography>
43
+
44
+ </Fragment>
45
+ ) : (
46
+ <Fragment>
47
+ <Typography textStyle="body1c-bold" className="font-semibold py-3">
48
+ <Highlight attribute="title" hit={hit} tagName="mark" />
49
+ </Typography>
50
+ <Typography textStyle="body2" className="text-neutral-600 break-words">
51
+ <Snippet attribute="excerpt" hit={hit} tagName="mark" />
52
+ </Typography>
53
+ </Fragment>
54
+ )}
55
+ </div>
56
+ {hit.url ? (
57
+ <Typography textStyle="body3" className="self-end my-2 pt-3 text-neutral-600">
58
+ <span className='hit-slug break-words'>{hit.url.replace(`https://${baseDomain}/`, "/")}</span>
59
+ </Typography>
60
+ ) : null}
61
+ </a>
62
+ );
63
+
64
+ const HitsByIndexType = ({ indexType }) => {
65
+ if (INDEX_TYPES[indexType] === undefined) return null;
66
+
67
+ return (
68
+ <Hits
69
+ className="Hits"
70
+ hitComponent={hitProps => <PageHit {...hitProps} indexType={indexType} />}
71
+ />
72
+ );
73
+ };
74
+
75
+ const HitsInIndex = ({ index, show }) => (
76
+ <Index indexName={index.name}>
77
+ {show && (
78
+ <Fragment>
79
+ <CustomHitsHeader
80
+ indexTitle={index.title}
81
+ showSeparator={index.type !== INDEX_TYPES.blog}
82
+ />
83
+ <HitsByIndexType indexType={index.type} />
84
+ </Fragment>
85
+ )}
86
+ </Index>
87
+ );
88
+
89
+ const SearchResult = ({ indices, className, id, wrapperRef, activeIndexTypes }) => (
90
+ <div id={id} className={`${className} search-results z-[2] clear-both`} ref={wrapperRef}>
91
+ {indices.map(index => (
92
+ <HitsInIndex index={index} key={index.name} show={activeIndexTypes[index.type]} />
93
+ ))}
94
+ <SearchFooter />
95
+ </div>
96
+ );
97
+
98
+ export default SearchResult;