@jschofield/quick-search 0.2.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/README.md ADDED
@@ -0,0 +1,83 @@
1
+ # @jschofield/quick-search
2
+
3
+ A Cmd+K search modal web component built with [Lit](https://lit.dev/) and [Fuse.js](https://www.fusejs.io/). Provides fuzzy search over page content with keyboard navigation.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @jschofield/quick-search
9
+ ```
10
+
11
+ ### Peer dependencies
12
+
13
+ This component requires the following peer dependency:
14
+
15
+ ```bash
16
+ npm install lit
17
+ ```
18
+
19
+ | Peer | Version |
20
+ |---|---|
21
+ | `lit` | `^3.0.0` |
22
+
23
+ ## Usage
24
+
25
+ ```html
26
+ <script type="module">
27
+ import '@jschofield/quick-search';
28
+ </script>
29
+
30
+ <quick-search></quick-search>
31
+ ```
32
+
33
+ ### Without a bundler
34
+
35
+ If you're not using a bundler, provide peer dependencies via an import map:
36
+
37
+ ```html
38
+ <script type="importmap">
39
+ {
40
+ "imports": {
41
+ "lit": "https://esm.run/lit",
42
+ "lit/": "https://esm.run/lit/"
43
+ }
44
+ }
45
+ </script>
46
+ <script type="module" src="https://esm.run/@jschofield/quick-search"></script>
47
+ ```
48
+
49
+ No attributes needed — drop it in and it works.
50
+
51
+ ## How it works
52
+
53
+ 1. Fetches `/search-data.json` on first open
54
+ 2. Fuzzy-searches by title, excerpt, and categories
55
+ 3. Results link directly to matching pages
56
+
57
+ ### Data format
58
+
59
+ The component expects a JSON file at `/search-data.json` with this shape:
60
+
61
+ ```json
62
+ [
63
+ {
64
+ "title": "My Post Title",
65
+ "excerpt": "A brief description...",
66
+ "url": "/posts/my-post/",
67
+ "categories": ["javascript", "web-components"]
68
+ }
69
+ ]
70
+ ```
71
+
72
+ ## Keyboard shortcuts
73
+
74
+ | Key | Action |
75
+ |---|---|
76
+ | `Cmd+K` / `Ctrl+K` | Open search |
77
+ | `Escape` | Close search |
78
+ | `Enter` | Navigate to selected result |
79
+ | Type to search | Fuzzy match across title, excerpt, categories |
80
+
81
+ ## License
82
+
83
+ MIT
@@ -0,0 +1 @@
1
+ *{box-sizing:border-box}body{background:#bcd;min-height:100vh;margin:0;padding:0}
@@ -0,0 +1,266 @@
1
+ import{LitElement as e,css as t,html as n}from"lit";import{customElement as r,state as i}from"lit/decorators.js";import{createRef as a,ref as o}from"lit/directives/ref.js";import{map as s}from"lit/directives/map.js";import{Task as c}from"@lit/task";(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),e.crossOrigin===`use-credentials`?t.credentials=`include`:e.crossOrigin===`anonymous`?t.credentials=`omit`:t.credentials=`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();function l(e){return Array.isArray?Array.isArray(e):b(e)===`[object Array]`}var u=1/0;function d(e){if(typeof e==`string`)return e;let t=e+``;return t==`0`&&1/e==-u?`-0`:t}function f(e){return e==null?``:d(e)}function p(e){return typeof e==`string`}function m(e){return typeof e==`number`}function h(e){return e===!0||e===!1||_(e)&&b(e)==`[object Boolean]`}function g(e){return typeof e==`object`}function _(e){return g(e)&&e!==null}function v(e){return e!=null}function y(e){return!e.trim().length}function b(e){return e==null?e===void 0?`[object Undefined]`:`[object Null]`:Object.prototype.toString.call(e)}var x=`Incorrect 'index' type`,S=e=>`Invalid value for key ${e}`,ee=e=>`Pattern length exceeds max of ${e}.`,C=e=>`Missing ${e} property in key`,w=e=>`Property 'weight' in key '${e}' must be a positive integer`,T=Object.prototype.hasOwnProperty,te=class{constructor(e){this._keys=[],this._keyMap={};let t=0;e.forEach(e=>{let n=E(e);this._keys.push(n),this._keyMap[n.id]=n,t+=n.weight}),this._keys.forEach(e=>{e.weight/=t})}get(e){return this._keyMap[e]}keys(){return this._keys}toJSON(){return JSON.stringify(this._keys)}};function E(e){let t=null,n=null,r=null,i=1,a=null;if(p(e)||l(e))r=e,t=D(e),n=O(e);else{if(!T.call(e,`name`))throw Error(C(`name`));let o=e.name;if(r=o,T.call(e,`weight`)&&(i=e.weight,i<=0))throw Error(w(o));t=D(o),n=O(o),a=e.getFn}return{path:t,id:n,weight:i,src:r,getFn:a}}function D(e){return l(e)?e:e.split(`.`)}function O(e){return l(e)?e.join(`.`):e}function ne(e,t){let n=[],r=!1,i=(e,t,a,o)=>{if(v(e))if(!t[a])n.push(o===void 0?e:{v:e,i:o});else{let s=e[t[a]];if(!v(s))return;if(a===t.length-1&&(p(s)||m(s)||h(s)))n.push(o===void 0?f(s):{v:f(s),i:o});else if(l(s)){r=!0;for(let e=0,n=s.length;e<n;e+=1)i(s[e],t,a+1,e)}else t.length&&i(s,t,a+1,o)}};return i(e,p(t)?t.split(`.`):t,0),r?n:n[0]}var re={includeMatches:!1,findAllMatches:!1,minMatchCharLength:1},ie={isCaseSensitive:!1,ignoreDiacritics:!1,includeScore:!1,keys:[],shouldSort:!0,sortFn:(e,t)=>e.score===t.score?e.idx<t.idx?-1:1:e.score<t.score?-1:1},ae={location:0,threshold:.6,distance:100},oe={useExtendedSearch:!1,getFn:ne,ignoreLocation:!1,ignoreFieldNorm:!1,fieldNormWeight:1},k={...ie,...re,...ae,...oe},se=/[^ ]+/g;function ce(e=1,t=3){let n=new Map,r=10**t;return{get(t){let i=t.match(se).length;if(n.has(i))return n.get(i);let a=1/i**(.5*e),o=parseFloat(Math.round(a*r)/r);return n.set(i,o),o},clear(){n.clear()}}}var A=class{constructor({getFn:e=k.getFn,fieldNormWeight:t=k.fieldNormWeight}={}){this.norm=ce(t,3),this.getFn=e,this.isCreated=!1,this.setIndexRecords()}setSources(e=[]){this.docs=e}setIndexRecords(e=[]){this.records=e}setKeys(e=[]){this.keys=e,this._keysMap={},e.forEach((e,t)=>{this._keysMap[e.id]=t})}create(){this.isCreated||!this.docs.length||(this.isCreated=!0,p(this.docs[0])?this.docs.forEach((e,t)=>{this._addString(e,t)}):this.docs.forEach((e,t)=>{this._addObject(e,t)}),this.norm.clear())}add(e){let t=this.size();p(e)?this._addString(e,t):this._addObject(e,t)}removeAt(e){this.records.splice(e,1);for(let t=e,n=this.size();t<n;t+=1)--this.records[t].i}removeAll(e){for(let t=e.length-1;t>=0;--t)this.records.splice(e[t],1);for(let e=0,t=this.records.length;e<t;e+=1)this.records[e].i=e}getValueForItemAtKeyId(e,t){return e[this._keysMap[t]]}size(){return this.records.length}_addString(e,t){if(!v(e)||y(e))return;let n={v:e,i:t,n:this.norm.get(e)};this.records.push(n)}_addObject(e,t){let n={i:t,$:{}};this.keys.forEach((t,r)=>{let i=t.getFn?t.getFn(e):this.getFn(e,t.path);if(v(i)){if(l(i)){let e=[];for(let t=0,n=i.length;t<n;t+=1){let n=i[t];if(v(n)){if(p(n)){if(!y(n)){let r={v:n,i:t,n:this.norm.get(n)};e.push(r)}}else if(p(n.v)&&!y(n.v)){let t={v:n.v,i:n.i,n:this.norm.get(n.v)};e.push(t)}}}n.$[r]=e}else if(p(i)&&!y(i)){let e={v:i,n:this.norm.get(i)};n.$[r]=e}}}),this.records.push(n)}toJSON(){return{keys:this.keys,records:this.records}}};function j(e,t,{getFn:n=k.getFn,fieldNormWeight:r=k.fieldNormWeight}={}){let i=new A({getFn:n,fieldNormWeight:r});return i.setKeys(e.map(E)),i.setSources(t),i.create(),i}function le(e,{getFn:t=k.getFn,fieldNormWeight:n=k.fieldNormWeight}={}){let{keys:r,records:i}=e,a=new A({getFn:t,fieldNormWeight:n});return a.setKeys(r),a.setIndexRecords(i),a}function ue(e=[],t=k.minMatchCharLength){let n=[],r=-1,i=-1,a=0;for(let o=e.length;a<o;a+=1){let o=e[a];o&&r===-1?r=a:!o&&r!==-1&&(i=a-1,i-r+1>=t&&n.push([r,i]),r=-1)}return e[a-1]&&a-r>=t&&n.push([r,a-1]),n}var M=32;function de(e,t,n,{location:r=k.location,distance:i=k.distance,threshold:a=k.threshold,findAllMatches:o=k.findAllMatches,minMatchCharLength:s=k.minMatchCharLength,includeMatches:c=k.includeMatches,ignoreLocation:l=k.ignoreLocation}={}){if(t.length>M)throw Error(ee(M));let u=t.length,d=e.length,f=Math.max(0,Math.min(r,d)),p=a,m=f,h=(e,t)=>{let n=e/u;if(l)return n;let r=Math.abs(f-t);return i?n+r/i:r?1:n},g=s>1||c,_=g?Array(d):[],v;for(;(v=e.indexOf(t,m))>-1;){let e=h(0,v);if(p=Math.min(e,p),m=v+u,g){let e=0;for(;e<u;)_[v+e]=1,e+=1}}m=-1;let y=[],b=1,x=u+d,S=1<<u-1;for(let t=0;t<u;t+=1){let r=0,i=x;for(;r<i;)h(t,f+i)<=p?r=i:x=i,i=Math.floor((x-r)/2+r);x=i;let a=Math.max(1,f-i+1),s=o?d:Math.min(f+i,d)+u,c=Array(s+2);c[s+1]=(1<<t)-1;for(let r=s;r>=a;--r){let i=r-1,o=n[e[i]];if(g&&(_[i]=+!!o),c[r]=(c[r+1]<<1|1)&o,t&&(c[r]|=(y[r+1]|y[r])<<1|1|y[r+1]),c[r]&S&&(b=h(t,i),b<=p)){if(p=b,m=i,m<=f)break;a=Math.max(1,2*f-m)}}if(h(t+1,f)>p)break;y=c}let C={isMatch:m>=0,score:Math.max(.001,b)};if(g){let e=ue(_,s);e.length?c&&(C.indices=e):C.isMatch=!1}return C}function fe(e){let t={};for(let n=0,r=e.length;n<r;n+=1){let i=e.charAt(n);t[i]=(t[i]||0)|1<<r-n-1}return t}var N=String.prototype.normalize?(e=>e.normalize(`NFD`).replace(/[\u0300-\u036F\u0483-\u0489\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7\u06E8\u06EA-\u06ED\u0711\u0730-\u074A\u07A6-\u07B0\u07EB-\u07F3\u07FD\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u082D\u0859-\u085B\u08D3-\u08E1\u08E3-\u0903\u093A-\u093C\u093E-\u094F\u0951-\u0957\u0962\u0963\u0981-\u0983\u09BC\u09BE-\u09C4\u09C7\u09C8\u09CB-\u09CD\u09D7\u09E2\u09E3\u09FE\u0A01-\u0A03\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A70\u0A71\u0A75\u0A81-\u0A83\u0ABC\u0ABE-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AE2\u0AE3\u0AFA-\u0AFF\u0B01-\u0B03\u0B3C\u0B3E-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B62\u0B63\u0B82\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD7\u0C00-\u0C04\u0C3E-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C62\u0C63\u0C81-\u0C83\u0CBC\u0CBE-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CE2\u0CE3\u0D00-\u0D03\u0D3B\u0D3C\u0D3E-\u0D44\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0D62\u0D63\u0D82\u0D83\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DF2\u0DF3\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0EB1\u0EB4-\u0EB9\u0EBB\u0EBC\u0EC8-\u0ECD\u0F18\u0F19\u0F35\u0F37\u0F39\u0F3E\u0F3F\u0F71-\u0F84\u0F86\u0F87\u0F8D-\u0F97\u0F99-\u0FBC\u0FC6\u102B-\u103E\u1056-\u1059\u105E-\u1060\u1062-\u1064\u1067-\u106D\u1071-\u1074\u1082-\u108D\u108F\u109A-\u109D\u135D-\u135F\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17B4-\u17D3\u17DD\u180B-\u180D\u1885\u1886\u18A9\u1920-\u192B\u1930-\u193B\u1A17-\u1A1B\u1A55-\u1A5E\u1A60-\u1A7C\u1A7F\u1AB0-\u1ABE\u1B00-\u1B04\u1B34-\u1B44\u1B6B-\u1B73\u1B80-\u1B82\u1BA1-\u1BAD\u1BE6-\u1BF3\u1C24-\u1C37\u1CD0-\u1CD2\u1CD4-\u1CE8\u1CED\u1CF2-\u1CF4\u1CF7-\u1CF9\u1DC0-\u1DF9\u1DFB-\u1DFF\u20D0-\u20F0\u2CEF-\u2CF1\u2D7F\u2DE0-\u2DFF\u302A-\u302F\u3099\u309A\uA66F-\uA672\uA674-\uA67D\uA69E\uA69F\uA6F0\uA6F1\uA802\uA806\uA80B\uA823-\uA827\uA880\uA881\uA8B4-\uA8C5\uA8E0-\uA8F1\uA8FF\uA926-\uA92D\uA947-\uA953\uA980-\uA983\uA9B3-\uA9C0\uA9E5\uAA29-\uAA36\uAA43\uAA4C\uAA4D\uAA7B-\uAA7D\uAAB0\uAAB2-\uAAB4\uAAB7\uAAB8\uAABE\uAABF\uAAC1\uAAEB-\uAAEF\uAAF5\uAAF6\uABE3-\uABEA\uABEC\uABED\uFB1E\uFE00-\uFE0F\uFE20-\uFE2F]/g,``)):(e=>e);function pe(e){if(e.length<=1)return e;e.sort((e,t)=>e[0]-t[0]||e[1]-t[1]);let t=[e[0]];for(let n=1,r=e.length;n<r;n+=1){let r=t[t.length-1],i=e[n];i[0]<=r[1]+1?r[1]=Math.max(r[1],i[1]):t.push(i)}return t}var P=class{constructor(e,{location:t=k.location,threshold:n=k.threshold,distance:r=k.distance,includeMatches:i=k.includeMatches,findAllMatches:a=k.findAllMatches,minMatchCharLength:o=k.minMatchCharLength,isCaseSensitive:s=k.isCaseSensitive,ignoreDiacritics:c=k.ignoreDiacritics,ignoreLocation:l=k.ignoreLocation}={}){if(this.options={location:t,threshold:n,distance:r,includeMatches:i,findAllMatches:a,minMatchCharLength:o,isCaseSensitive:s,ignoreDiacritics:c,ignoreLocation:l},e=s?e:e.toLowerCase(),e=c?N(e):e,this.pattern=e,this.chunks=[],!this.pattern.length)return;let u=(e,t)=>{this.chunks.push({pattern:e,alphabet:fe(e),startIndex:t})},d=this.pattern.length;if(d>M){let e=0,t=d%M,n=d-t;for(;e<n;)u(this.pattern.substr(e,M),e),e+=M;if(t){let e=d-M;u(this.pattern.substr(e),e)}}else u(this.pattern,0)}searchIn(e){let{isCaseSensitive:t,ignoreDiacritics:n,includeMatches:r}=this.options;if(e=t?e:e.toLowerCase(),e=n?N(e):e,this.pattern===e){let t={isMatch:!0,score:0};return r&&(t.indices=[[0,e.length-1]]),t}let{location:i,distance:a,threshold:o,findAllMatches:s,minMatchCharLength:c,ignoreLocation:l}=this.options,u=[],d=0,f=!1;this.chunks.forEach(({pattern:t,alphabet:n,startIndex:p})=>{let{isMatch:m,score:h,indices:g}=de(e,t,n,{location:i+p,distance:a,threshold:o,findAllMatches:s,minMatchCharLength:c,includeMatches:r,ignoreLocation:l});m&&(f=!0),d+=h,m&&g&&u.push(...g)});let p={isMatch:f,score:f?d/this.chunks.length:1};return f&&r&&(p.indices=pe(u)),p}},F=class{constructor(e){this.pattern=e}static isMultiMatch(e){return I(e,this.multiRegex)}static isSingleMatch(e){return I(e,this.singleRegex)}search(){}};function I(e,t){let n=e.match(t);return n?n[1]:null}var me=class extends F{constructor(e){super(e)}static get type(){return`exact`}static get multiRegex(){return/^="(.*)"$/}static get singleRegex(){return/^=(.*)$/}search(e){let t=e===this.pattern;return{isMatch:t,score:t?0:1,indices:[0,this.pattern.length-1]}}},he=class extends F{constructor(e){super(e)}static get type(){return`inverse-exact`}static get multiRegex(){return/^!"(.*)"$/}static get singleRegex(){return/^!(.*)$/}search(e){let t=e.indexOf(this.pattern)===-1;return{isMatch:t,score:t?0:1,indices:[0,e.length-1]}}},ge=class extends F{constructor(e){super(e)}static get type(){return`prefix-exact`}static get multiRegex(){return/^\^"(.*)"$/}static get singleRegex(){return/^\^(.*)$/}search(e){let t=e.startsWith(this.pattern);return{isMatch:t,score:t?0:1,indices:[0,this.pattern.length-1]}}},_e=class extends F{constructor(e){super(e)}static get type(){return`inverse-prefix-exact`}static get multiRegex(){return/^!\^"(.*)"$/}static get singleRegex(){return/^!\^(.*)$/}search(e){let t=!e.startsWith(this.pattern);return{isMatch:t,score:t?0:1,indices:[0,e.length-1]}}},ve=class extends F{constructor(e){super(e)}static get type(){return`suffix-exact`}static get multiRegex(){return/^"(.*)"\$$/}static get singleRegex(){return/^(.*)\$$/}search(e){let t=e.endsWith(this.pattern);return{isMatch:t,score:t?0:1,indices:[e.length-this.pattern.length,e.length-1]}}},ye=class extends F{constructor(e){super(e)}static get type(){return`inverse-suffix-exact`}static get multiRegex(){return/^!"(.*)"\$$/}static get singleRegex(){return/^!(.*)\$$/}search(e){let t=!e.endsWith(this.pattern);return{isMatch:t,score:t?0:1,indices:[0,e.length-1]}}},L=class extends F{constructor(e,{location:t=k.location,threshold:n=k.threshold,distance:r=k.distance,includeMatches:i=k.includeMatches,findAllMatches:a=k.findAllMatches,minMatchCharLength:o=k.minMatchCharLength,isCaseSensitive:s=k.isCaseSensitive,ignoreDiacritics:c=k.ignoreDiacritics,ignoreLocation:l=k.ignoreLocation}={}){super(e),this._bitapSearch=new P(e,{location:t,threshold:n,distance:r,includeMatches:i,findAllMatches:a,minMatchCharLength:o,isCaseSensitive:s,ignoreDiacritics:c,ignoreLocation:l})}static get type(){return`fuzzy`}static get multiRegex(){return/^"(.*)"$/}static get singleRegex(){return/^(.*)$/}search(e){return this._bitapSearch.searchIn(e)}},R=class extends F{constructor(e){super(e)}static get type(){return`include`}static get multiRegex(){return/^'"(.*)"$/}static get singleRegex(){return/^'(.*)$/}search(e){let t=0,n,r=[],i=this.pattern.length;for(;(n=e.indexOf(this.pattern,t))>-1;)t=n+i,r.push([n,t-1]);let a=!!r.length;return{isMatch:a,score:a?0:1,indices:r}}},z=[me,R,ge,_e,ye,ve,he,L],B=z.length,be=/ +(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/,xe=`|`;function Se(e,t={}){return e.split(xe).map(e=>{let n=e.trim().split(be).filter(e=>e&&!!e.trim()),r=[];for(let e=0,i=n.length;e<i;e+=1){let i=n[e],a=!1,o=-1;for(;!a&&++o<B;){let e=z[o],n=e.isMultiMatch(i);n&&(r.push(new e(n,t)),a=!0)}if(!a)for(o=-1;++o<B;){let e=z[o],n=e.isSingleMatch(i);if(n){r.push(new e(n,t));break}}}return r})}var Ce=new Set([L.type,R.type]),we=class{constructor(e,{isCaseSensitive:t=k.isCaseSensitive,ignoreDiacritics:n=k.ignoreDiacritics,includeMatches:r=k.includeMatches,minMatchCharLength:i=k.minMatchCharLength,ignoreLocation:a=k.ignoreLocation,findAllMatches:o=k.findAllMatches,location:s=k.location,threshold:c=k.threshold,distance:l=k.distance}={}){this.query=null,this.options={isCaseSensitive:t,ignoreDiacritics:n,includeMatches:r,minMatchCharLength:i,findAllMatches:o,ignoreLocation:a,location:s,threshold:c,distance:l},e=t?e:e.toLowerCase(),e=n?N(e):e,this.pattern=e,this.query=Se(this.pattern,this.options)}static condition(e,t){return t.useExtendedSearch}searchIn(e){let t=this.query;if(!t)return{isMatch:!1,score:1};let{includeMatches:n,isCaseSensitive:r,ignoreDiacritics:i}=this.options;e=r?e:e.toLowerCase(),e=i?N(e):e;let a=0,o=[],s=0;for(let r=0,i=t.length;r<i;r+=1){let i=t[r];o.length=0,a=0;for(let t=0,r=i.length;t<r;t+=1){let r=i[t],{isMatch:c,indices:l,score:u}=r.search(e);if(c){if(a+=1,s+=u,n){let e=r.constructor.type;Ce.has(e)?o.push(...l):o.push(l)}}else{s=0,a=0,o.length=0;break}}if(a){let e={isMatch:!0,score:s/a};return n&&(e.indices=o),e}}return{isMatch:!1,score:1}}},V=[];function H(...e){V.push(...e)}function U(e,t){for(let n=0,r=V.length;n<r;n+=1){let r=V[n];if(r.condition(e,t))return new r(e,t)}return new P(e,t)}var W={AND:`$and`,OR:`$or`},G={PATH:`$path`,PATTERN:`$val`},K=e=>!!(e[W.AND]||e[W.OR]),Te=e=>!!e[G.PATH],q=e=>!l(e)&&g(e)&&!K(e),J=e=>({[W.AND]:Object.keys(e).map(t=>({[t]:e[t]}))});function Y(e,t,{auto:n=!0}={}){let r=e=>{let i=Object.keys(e),a=Te(e);if(!a&&i.length>1&&!K(e))return r(J(e));if(q(e)){let r=a?e[G.PATH]:i[0],o=a?e[G.PATTERN]:e[r];if(!p(o))throw Error(S(r));let s={keyId:O(r),pattern:o};return n&&(s.searcher=U(o,t)),s}let o={children:[],operator:i[0]};return i.forEach(t=>{let n=e[t];l(n)&&n.forEach(e=>{o.children.push(r(e))})}),o};return K(e)||(e=J(e)),r(e)}function X(e,{ignoreFieldNorm:t=k.ignoreFieldNorm}){let n=1;e.matches.forEach(({key:e,norm:r,score:i})=>{let a=e?e.weight:null;n*=(i===0&&a?2**-52:i)**+((a||1)*(t?1:r))}),e.score=n}function Ee(e,{ignoreFieldNorm:t=k.ignoreFieldNorm}){e.forEach(e=>{X(e,{ignoreFieldNorm:t})})}var De=class{constructor(e){this.limit=e,this.heap=[]}get size(){return this.heap.length}shouldInsert(e){return this.size<this.limit||e<this.heap[0].score}insert(e){this.size<this.limit?(this.heap.push(e),this._bubbleUp(this.size-1)):e.score<this.heap[0].score&&(this.heap[0]=e,this._sinkDown(0))}extractSorted(e){return this.heap.sort(e)}_bubbleUp(e){let t=this.heap;for(;e>0;){let n=e-1>>1;if(t[e].score<=t[n].score)break;let r=t[e];t[e]=t[n],t[n]=r,e=n}}_sinkDown(e){let t=this.heap,n=t.length,r=e;do{e=r;let i=2*e+1,a=2*e+2;if(i<n&&t[i].score>t[r].score&&(r=i),a<n&&t[a].score>t[r].score&&(r=a),r!==e){let n=t[e];t[e]=t[r],t[r]=n}}while(r!==e)}};function Oe(e,t){let n=e.matches;t.matches=[],v(n)&&n.forEach(e=>{if(!v(e.indices)||!e.indices.length)return;let{indices:n,value:r}=e,i={indices:n,value:r};e.key&&(i.key=e.key.src),e.idx>-1&&(i.refIndex=e.idx),t.matches.push(i)})}function ke(e,t){t.score=e.score}function Ae(e,t,{includeMatches:n=k.includeMatches,includeScore:r=k.includeScore}={}){let i=[];return n&&i.push(Oe),r&&i.push(ke),e.map(e=>{let{idx:n}=e,r={item:t[n],refIndex:n};return i.length&&i.forEach(t=>{t(e,r)}),r})}var Z=class{constructor(e,t={},n){this.options={...k,...t},this.options.useExtendedSearch,this._keyStore=new te(this.options.keys),this.setCollection(e,n),this._lastQuery=null,this._lastSearcher=null}_getSearcher(e){if(this._lastQuery===e)return this._lastSearcher;let t=U(e,this.options);return this._lastQuery=e,this._lastSearcher=t,t}setCollection(e,t){if(this._docs=e,t&&!(t instanceof A))throw Error(x);this._myIndex=t||j(this.options.keys,this._docs,{getFn:this.options.getFn,fieldNormWeight:this.options.fieldNormWeight})}add(e){v(e)&&(this._docs.push(e),this._myIndex.add(e))}remove(e=()=>!1){let t=[],n=[];for(let r=0,i=this._docs.length;r<i;r+=1)e(this._docs[r],r)&&(t.push(this._docs[r]),n.push(r));if(n.length){for(let e=n.length-1;e>=0;--e)this._docs.splice(n[e],1);this._myIndex.removeAll(n)}return t}removeAt(e){this._docs.splice(e,1),this._myIndex.removeAt(e)}getIndex(){return this._myIndex}search(e,{limit:t=-1}={}){let{includeMatches:n,includeScore:r,shouldSort:i,sortFn:a,ignoreFieldNorm:o}=this.options,s=m(t)&&t>0&&p(e),c;if(s){let n=new De(t);p(this._docs[0])?this._searchStringList(e,{heap:n,ignoreFieldNorm:o}):this._searchObjectList(e,{heap:n,ignoreFieldNorm:o}),c=n.extractSorted(a)}else c=p(e)?p(this._docs[0])?this._searchStringList(e):this._searchObjectList(e):this._searchLogical(e),Ee(c,{ignoreFieldNorm:o}),i&&c.sort(a),m(t)&&t>-1&&(c=c.slice(0,t));return Ae(c,this._docs,{includeMatches:n,includeScore:r})}_searchStringList(e,{heap:t,ignoreFieldNorm:n}={}){let r=this._getSearcher(e),{records:i}=this._myIndex,a=t?null:[];return i.forEach(({v:e,i,n:o})=>{if(!v(e))return;let{isMatch:s,score:c,indices:l}=r.searchIn(e);if(s){let r={item:e,idx:i,matches:[{score:c,value:e,norm:o,indices:l}]};t?(X(r,{ignoreFieldNorm:n}),t.shouldInsert(r.score)&&t.insert(r)):a.push(r)}}),a}_searchLogical(e){let t=Y(e,this.options),n=(e,t,r)=>{if(!e.children){let{keyId:n,searcher:i}=e,a=this._findMatches({key:this._keyStore.get(n),value:this._myIndex.getValueForItemAtKeyId(t,n),searcher:i});return a&&a.length?[{idx:r,item:t,matches:a}]:[]}let i=[];for(let a=0,o=e.children.length;a<o;a+=1){let o=e.children[a],s=n(o,t,r);if(s.length)i.push(...s);else if(e.operator===W.AND)return[]}return i},r=this._myIndex.records,i=new Map,a=[];return r.forEach(({$:e,i:r})=>{if(v(e)){let o=n(t,e,r);o.length&&(i.has(r)||(i.set(r,{idx:r,item:e,matches:[]}),a.push(i.get(r))),o.forEach(({matches:e})=>{i.get(r).matches.push(...e)}))}}),a}_searchObjectList(e,{heap:t,ignoreFieldNorm:n}={}){let r=this._getSearcher(e),{keys:i,records:a}=this._myIndex,o=t?null:[];return a.forEach(({$:e,i:a})=>{if(!v(e))return;let s=[];if(i.forEach((t,n)=>{s.push(...this._findMatches({key:t,value:e[n],searcher:r}))}),s.length){let r={idx:a,item:e,matches:s};t?(X(r,{ignoreFieldNorm:n}),t.shouldInsert(r.score)&&t.insert(r)):o.push(r)}}),o}_findMatches({key:e,value:t,searcher:n}){if(!v(t))return[];let r=[];if(l(t))t.forEach(({v:t,i,n:a})=>{if(!v(t))return;let{isMatch:o,score:s,indices:c}=n.searchIn(t);o&&r.push({score:s,key:e,value:t,idx:i,norm:a,indices:c})});else{let{v:i,n:a}=t,{isMatch:o,score:s,indices:c}=n.searchIn(i);o&&r.push({score:s,key:e,value:i,norm:a,indices:c})}return r}};Z.version=`7.2.0`,Z.createIndex=j,Z.parseIndex=le,Z.config=k,Z.parseQuery=Y,H(we),Z.use=function(...e){e.forEach(e=>H(e))};function Q(e,t,n,r){var i=arguments.length,a=i<3?t:r===null?r=Object.getOwnPropertyDescriptor(t,n):r,o;if(typeof Reflect==`object`&&typeof Reflect.decorate==`function`)a=Reflect.decorate(e,t,n,r);else for(var s=e.length-1;s>=0;s--)(o=e[s])&&(a=(i<3?o(a):i>3?o(t,n,a):o(t,n))||a);return i>3&&a&&Object.defineProperty(t,n,a),a}var $=class extends e{constructor(...e){super(...e),this.searchTerm=``,this.dataTask=new c(this,{task:async()=>{let e=await fetch(`/search-data.json`);if(!e.ok)throw Error(`HTTP ${e.status}`);let t=await e.json();return this.fuse=new Z(t,{keys:[`title`,`categories`,`excerpt`],shouldSort:!0,includeScore:!0}),t},args:()=>[]}),this.open=()=>{this.#e.value?.showModal()},this.close=()=>{this.#e.value?.close()}}#e=a();connectedCallback(){super.connectedCallback(),window.addEventListener(`keydown`,this.#t)}disconnectedCallback(){window.removeEventListener(`keydown`,this.#t)}get results(){return!this.searchTerm||!this.fuse||this.dataTask.status!==2?[]:this.fuse.search(this.searchTerm)}get hasResults(){return this.results.length>0}#t=e=>{let t=e.key===`k`&&e.getModifierState(`Meta`),n=e.key===`k`&&e.getModifierState(`Control`);(t||n)&&this.open()};#n=e=>{this.searchTerm=e.target.value};render(){return n`
2
+ <dialog part="qs-dialog" ${o(this.#e)}>
3
+ <div class="inner">
4
+ <div class="controls">
5
+ <input
6
+ autofocus
7
+ type="text"
8
+ placeholder="Search for a page"
9
+ part="qs-input"
10
+ value=${this.searchTerm}
11
+ @input=${this.#n}
12
+ />
13
+ <button class="close" @click=${this.close}>Close</button>
14
+ </div>
15
+ <hr part="qs-divider" />
16
+ <div part="qs-results" class="results">
17
+ ${this.dataTask.render({pending:()=>n`<div class="message">Loading search data...</div>`,error:e=>n`<div class="message error">
18
+ Search unavailable:
19
+ ${e instanceof Error?e.message:`Unknown error`}
20
+ </div>`,complete:()=>this.hasResults?n`
21
+ <ul>
22
+ ${s(this.results,({item:e})=>n`<li>
23
+ <a part="qs-result" class="result" href=${e.url}>
24
+ <div part="qs-title" class="title">
25
+ ${e.title}
26
+ </div>
27
+ <div part="qs-excerpt" class="excerpt">
28
+ ${e.excerpt}
29
+ </div>
30
+ <div part="qs-categories" class="categories">
31
+ ${e.categories.map(e=>n`<span>${e}</span>`)}
32
+ </div>
33
+ </a>
34
+ </li>`)}
35
+ </ul>
36
+ `:n`<div class="message">
37
+ Enter a search term or select a category. Press escape to
38
+ return.
39
+ </div>`})}
40
+ </div>
41
+ </div>
42
+ </dialog>
43
+ `}static{this.styles=t`
44
+ :host {
45
+ --gunmetal: #1b2f36;
46
+ --seasalt: #fafafa;
47
+ --carrot: #f79103;
48
+ --teal: #376170;
49
+ --raw-umber: #906b56;
50
+ --paynes-gray: #4d5963;
51
+ --shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
52
+ --gradient: linear-gradient(
53
+ 135deg,
54
+ var(--paynes-gray) 0% 20%,
55
+ var(--carrot) 20% 40%,
56
+ var(--teal) 40% 60%,
57
+ var(--raw-umber) 60% 80%,
58
+ var(--gunmetal) 80% 100%
59
+ );
60
+ }
61
+
62
+ * {
63
+ box-sizing: border-box;
64
+ }
65
+
66
+ *:focus-visible {
67
+ outline: 2px solid var(--raw-umber);
68
+ outline-offset: 1px;
69
+ }
70
+
71
+ dialog {
72
+ margin-top: 10vh;
73
+ height: auto;
74
+ width: 90vw;
75
+ max-width: 600px;
76
+ max-height: 80vh;
77
+ padding: 0;
78
+ border: 2px solid var(--gunmetal);
79
+ border-radius: 8px;
80
+ background: var(--seasalt);
81
+ color: var(--gunmetal);
82
+ box-shadow: var(--shadow);
83
+ overflow: hidden;
84
+ font-family: "Atkinson Hyperlegible Next", system-ui, sans-serif;
85
+ }
86
+
87
+ dialog::backdrop {
88
+ backdrop-filter: blur(4px);
89
+ background: rgba(27, 47, 54, 0.1);
90
+ }
91
+
92
+ .inner {
93
+ max-height: 100%;
94
+ padding: 1rem;
95
+ }
96
+
97
+ .controls {
98
+ display: flex;
99
+ align-items: center;
100
+ gap: 0.5rem;
101
+ margin-bottom: 1rem;
102
+ }
103
+
104
+ input {
105
+ flex: 1;
106
+ padding: 0.75rem;
107
+ font: inherit;
108
+ font-size: 1rem;
109
+ border: 2px solid var(--teal);
110
+ border-radius: 8px;
111
+ background: var(--seasalt);
112
+ color: var(--gunmetal);
113
+
114
+ &:focus {
115
+ outline: none;
116
+ border-color: var(--carrot);
117
+ box-shadow: 0 0 0 2px rgba(247, 145, 3, 0.2);
118
+ }
119
+
120
+ &::placeholder {
121
+ color: var(--paynes-gray);
122
+ }
123
+ }
124
+
125
+ .close {
126
+ display: inline-block;
127
+ padding: 0.75rem 1rem;
128
+ background: var(--gunmetal);
129
+ color: var(--seasalt);
130
+ border-radius: 8px;
131
+ box-shadow: var(--shadow);
132
+ border: none;
133
+ font: inherit;
134
+ cursor: pointer;
135
+
136
+ &:hover {
137
+ background: var(--gradient);
138
+ }
139
+
140
+ &:focus-visible {
141
+ outline: 2px solid var(--raw-umber);
142
+ outline-offset: 1px;
143
+ background: var(--gradient);
144
+ }
145
+ }
146
+
147
+ hr {
148
+ width: 100%;
149
+ border: none;
150
+ height: 4px;
151
+ background: var(--gradient);
152
+ border-radius: 2px;
153
+ margin: 0 0 1rem 0;
154
+ }
155
+
156
+ .results {
157
+ max-height: 60vh;
158
+ overflow-y: auto;
159
+ }
160
+
161
+ .message {
162
+ padding: 2rem 1rem;
163
+ text-align: center;
164
+ color: var(--paynes-gray);
165
+ font-style: italic;
166
+ }
167
+
168
+ .message.error {
169
+ color: var(--raw-umber);
170
+ font-weight: bold;
171
+ }
172
+
173
+ ul {
174
+ margin: 0;
175
+ padding: 0;
176
+ padding-top: 0.5rem;
177
+ list-style-type: none;
178
+ display: grid;
179
+ gap: 0.5rem;
180
+ }
181
+
182
+ .result {
183
+ display: block;
184
+ padding: 1rem;
185
+ color: var(--gunmetal);
186
+ text-decoration: none;
187
+ border: 2px solid transparent;
188
+ border-radius: 8px;
189
+ background: var(--seasalt);
190
+ transition: all 0.2s ease;
191
+
192
+ &:hover {
193
+ border-color: var(--teal);
194
+ transform: translateY(-1px);
195
+ }
196
+
197
+ &:focus-visible {
198
+ outline: none;
199
+ border-color: var(--carrot);
200
+ box-shadow: 0 0 0 2px rgba(247, 145, 3, 0.2);
201
+ }
202
+ }
203
+
204
+ .title {
205
+ font-weight: bold;
206
+ font-size: 1.1rem;
207
+ margin-bottom: 0.25rem;
208
+ color: var(--gunmetal);
209
+ line-height: 1.2;
210
+ }
211
+
212
+ .excerpt {
213
+ font-size: 0.9rem;
214
+ color: var(--paynes-gray);
215
+ line-height: 1.4;
216
+ margin-bottom: 0.5rem;
217
+ }
218
+
219
+ .categories {
220
+ display: flex;
221
+ flex-wrap: wrap;
222
+ gap: 0.25rem;
223
+ font-size: 0.8rem;
224
+ text-transform: capitalize;
225
+
226
+ & span {
227
+ padding: 0.125rem 0.5rem;
228
+ background: var(--teal);
229
+ color: var(--seasalt);
230
+ border-radius: 4px;
231
+ font-weight: 500;
232
+ }
233
+
234
+ & span:last-child::after {
235
+ content: none;
236
+ }
237
+ }
238
+
239
+
240
+ /* Responsive adjustments */
241
+ @media (max-width: 600px) {
242
+ dialog {
243
+ width: 95vw;
244
+ margin-top: 5vh;
245
+ max-height: 85vh;
246
+ }
247
+
248
+ .inner {
249
+ padding: 0.75rem;
250
+ }
251
+
252
+ .controls {
253
+ flex-direction: column;
254
+ gap: 0.75rem;
255
+ }
256
+
257
+ .close {
258
+ width: 100%;
259
+ order: -1;
260
+ }
261
+
262
+ input {
263
+ width: 100%;
264
+ }
265
+ }
266
+ `}};Q([i()],$.prototype,`searchTerm`,void 0),$=Q([r(`quick-search`)],$);
@@ -0,0 +1,136 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link rel="icon" type="image/svg+xml" href="/vite.svg" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>Vite + Lit + TS</title>
8
+ <script type="module" crossorigin src="/assets/index.js"></script>
9
+ <link rel="stylesheet" crossorigin href="/assets/index.css">
10
+ </head>
11
+ <body>
12
+ <quick-search>
13
+ <search-option
14
+ value="Web Components and You (part 1): The Shadow Dom"
15
+ excerpt="We look at why web components are a good solution now, and the very basics on how to make one."
16
+ categories="posts,web-components,cats"
17
+ url="/posts/2024/2/web-components-and-you-1/"
18
+ ></search-option
19
+ ><search-option
20
+ value="Web Components and You (part 2): Attributes and Reactivity"
21
+ excerpt="Let's take a look at web component attributes and how you can get your components to react to attribute changes!"
22
+ categories="posts,web-components,dogs"
23
+ url="/posts/2024/3/web-components-and-you-2-attributes/"
24
+ ></search-option
25
+ ><search-option
26
+ value="Web Components and You (part 3): Simplifying with Lit"
27
+ excerpt="It can be tedious to wire up reactivity in a web component ourselves. Let's see how easy it can be with Lit"
28
+ categories="posts,web-components"
29
+ url="/posts/2024/3/web-components-and-you-3/"
30
+ ></search-option
31
+ ><search-option
32
+ value="Web Components and You (part 4): Style"
33
+ excerpt="Let's visit how you would do CSS styles in a web component, and how Lit includes styles."
34
+ categories="posts,web-components"
35
+ url="/posts/2024/3/web-components-and-you-4/"
36
+ ></search-option
37
+ ><search-option
38
+ value="Web Components and You (part 5): Piercing the Shadow DOM"
39
+ excerpt="The Shadow DOM has scoped styles, which means that styles outside the shadow root don\'t affect it. But there are some exceptions! We will discuss the `:part()` psuedo-selector, css variables, declarative shadow DOM, and other ways the shadow DOM can be styled!"
40
+ categories="posts,web-components"
41
+ url="/posts/2024/3/web-components-and-you-5/"
42
+ ></search-option
43
+ ><search-option
44
+ value="Web Components and You (part 6): Slots and how to use them"
45
+ excerpt="Slots are a fantastic new feature that comes along with the Shadow DOM. You don\'t even need to make a custom element to use them. Let's look at how to use slots, name slots, and some of the lifecycles and features that come along with them."
46
+ categories="posts,web-components"
47
+ url="/posts/2024/4/web-components-and-you-6/"
48
+ ></search-option
49
+ ><search-option
50
+ value="Web Components and You (part 7): Let's talk about Shadow DOM mode"
51
+ excerpt="The Shadow DOM allows us a certain level of encapsulation, and there are two options for which mode you\'d like the Shadow DOM to be int: open or closed. We\'ll talk about the differences, the pros and cons, and ultimately whether it\'s worth it to close the Shadow DOM."
52
+ categories="posts,web-components"
53
+ url="/posts/2024/4/web-components-and-you-7/"
54
+ ></search-option
55
+ ><search-option
56
+ value="Web Components and You (part 8): Making a form element web component!"
57
+ excerpt="We can create form elements with our new web components, but we need to do a few new things: attach internals, handle focus delegation, and register the component as a bona fide form element with a value. It\'s pretty simple once you get into it- let's make a special text component as an example."
58
+ categories="posts,web-components"
59
+ url="/posts/2024/4/web-components-and-you-8/"
60
+ ></search-option
61
+ ><search-option
62
+ value="Web Components and You (part 9): Handling empty slots"
63
+ excerpt="Sometimes you want to check the contents of slots in the shadow DOM and conditionally do things based on what\'s in them. Can you do this with slots? Yes! It\'s a little strange though..."
64
+ categories="posts,web-components"
65
+ url="/posts/2024/8/web-components-and-you-9/"
66
+ ></search-option
67
+ ><search-option
68
+ value="Web Components and You (part 10): Provider patterns"
69
+ excerpt="Web components are by default pretty isolated. There are some nice patterns to start sharing state and actions among web components. This article explores the \'provider\' pattern"
70
+ categories="posts,web-components"
71
+ url="/posts/2024/8/web-components-and-you-10/"
72
+ ></search-option>
73
+ </quick-search
74
+ >
75
+ <p>
76
+ Lorem ipsum dolor sit, amet consectetur adipisicing elit. Quaerat dolor
77
+ magnam accusamus porro culpa sit, hic aliquam laborum voluptatum?
78
+ Temporibus molestiae aut quam ratione iste aspernatur quod vero libero
79
+ dolorem.
80
+ </p>
81
+ <p>
82
+ Voluptatibus saepe porro, ex id exercitationem odio fugit asperiores
83
+ dolorum dolor cupiditate aspernatur veritatis illum aperiam culpa sunt
84
+ quam sint ducimus harum quas impedit doloremque ea maxime recusandae modi?
85
+ Unde.
86
+ </p>
87
+ <p>
88
+ Aperiam cum ratione consequatur. Modi nisi rerum nulla debitis, odio
89
+ mollitia repudiandae aspernatur itaque autem impedit deleniti quam
90
+ provident omnis atque blanditiis! Expedita ex at dicta voluptates ut
91
+ delectus neque!
92
+ </p>
93
+ <p>
94
+ Nam, unde libero corporis possimus similique nesciunt labore doloribus
95
+ totam esse architecto quia officia delectus exercitationem ratione nulla
96
+ quos dolorem deserunt voluptatibus deleniti quo quas et repudiandae,
97
+ tempore eligendi. Nihil.
98
+ </p>
99
+ <p>
100
+ Consequuntur expedita ullam, magnam aliquid, natus recusandae hic libero
101
+ voluptatum labore odit velit eius debitis perferendis quia rem voluptatem,
102
+ accusamus autem non maiores. Neque consequuntur, voluptatum saepe minus
103
+ illo ipsa.
104
+ </p>
105
+ <p>
106
+ Lorem ipsum dolor sit, amet consectetur adipisicing elit. Quaerat dolor
107
+ magnam accusamus porro culpa sit, hic aliquam laborum voluptatum?
108
+ Temporibus molestiae aut quam ratione iste aspernatur quod vero libero
109
+ dolorem.
110
+ </p>
111
+ <p>
112
+ Voluptatibus saepe porro, ex id exercitationem odio fugit asperiores
113
+ dolorum dolor cupiditate aspernatur veritatis illum aperiam culpa sunt
114
+ quam sint ducimus harum quas impedit doloremque ea maxime recusandae modi?
115
+ Unde.
116
+ </p>
117
+ <p>
118
+ Aperiam cum ratione consequatur. Modi nisi rerum nulla debitis, odio
119
+ mollitia repudiandae aspernatur itaque autem impedit deleniti quam
120
+ provident omnis atque blanditiis! Expedita ex at dicta voluptates ut
121
+ delectus neque!
122
+ </p>
123
+ <p>
124
+ Nam, unde libero corporis possimus similique nesciunt labore doloribus
125
+ totam esse architecto quia officia delectus exercitationem ratione nulla
126
+ quos dolorem deserunt voluptatibus deleniti quo quas et repudiandae,
127
+ tempore eligendi. Nihil.
128
+ </p>
129
+ <p>
130
+ Consequuntur expedita ullam, magnam aliquid, natus recusandae hic libero
131
+ voluptatum labore odit velit eius debitis perferendis quia rem voluptatem,
132
+ accusamus autem non maiores. Neque consequuntur, voluptatum saepe minus
133
+ illo ipsa.
134
+ </p>
135
+ </body>
136
+ </html>
package/dist/vite.svg ADDED
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@jschofield/quick-search",
3
+ "version": "0.2.0",
4
+ "type": "module",
5
+ "main": "./dist/assets/index.js",
6
+ "exports": {
7
+ ".": "./dist/assets/index.js"
8
+ },
9
+ "files": [
10
+ "dist"
11
+ ],
12
+ "description": "Site-wide search web component built with Lit and Fuse.js",
13
+ "author": "Jim Schofield",
14
+ "license": "MIT",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "https://github.com/JimSchofield/jschof.dev",
18
+ "directory": "component/quick-search"
19
+ },
20
+ "dependencies": {
21
+ "@lit/task": "^1.0.1",
22
+ "fuse.js": "^7.0.0"
23
+ },
24
+ "peerDependencies": {
25
+ "lit": "^3.0.0"
26
+ },
27
+ "devDependencies": {
28
+ "typescript": "^6.0.2",
29
+ "vite": "^8.0.3"
30
+ },
31
+ "scripts": {
32
+ "dev": "vite",
33
+ "build": "tsc && vite build",
34
+ "preview": "vite preview"
35
+ }
36
+ }