imba/note-search/src/main.imba
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
import search from './assets/img/search.svg' import menu from './assets/img/menu.svg' def fetchNote slug let res = await window.fetch("./{slug}/index.json") try return await res.json! catch return null tag note-content css h2 mb:4 c:$text-primary css c:$text def routed params, state emit("noteChanged") note = state.note ||= await fetchNote params.slug p = document.createElement('p') p.classList.add "post-text" p.innerHTML = note ? note.content : "" <self [o@suspended:0.4 tween: all 75ms ease]> (<h2> note.title <p[c:$text my:3]> note.date <div.post-labels> if note.tags for t in note.tags <p.post-label> t p) if note tag note-item prop note css pl:4 pr:4 my:10px css a@hover text-decoration: underline a c: $text fw.active: 600 c.active: $text-primary <self> <a route-to="/notes/{note.url.split('/').slice(-2,-1)}"> note.title tag app target notes = [] introBox searchQuery navOpen? = false css d:grid grid-template-columns: repeat(28, 1fr) m: 0px auto w: auto w:1344px w@!1368: 95% w@!768: 90% css .left o: 0.3 @hover: 1 d:vflex ai:left jc:start grid-column: 1 / 7 max-height:calc(100vh - 96px - 112px) min-height:80 pos:sticky top: 96px gap: 2 tween: all 200ms ease min-width: 240px @!768 zin: 150 height: 100vh max-height: 100vh o: 1 x: -100vw grid-row: 1 / -1 bgc: $bg p: 5 w: 80vw box-shadow: 0 3px 12px rgba(0,0,0,0.1) css .note-list ofy:scroll overscroll-behavior: none css .center max-width: 672px grid-column: 8 / 22 grid-column@!1368: 8 / 28 @!768 grid-column: 1 / -1 grid-row: 1 / -1 css input bgc:transparent outline:none bd:none c:$text p:0 w:100% .searchbar bgc:$card-bg d:hflex px:4 py:1 rd:3 gap:2 mb:2 olc:$imba-searchbar-outline-color olw:$imba-searchbar-outline-width ols:$imba-searchbar-outline-style .center h2 mb:4 def escapeRegExp(str) str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); def fuzzyMatch(query, string) pattern = query.trim().split(' ').map(do(l) "{escapeRegExp(l)}").join("|"); const re = new RegExp(pattern, "i") return re.test(string) def setup for c in target.children if c.id == 'notes-list' for n in c.children anchor = n.children[0] let note = {} note.title = anchor.innerHTML note.url = anchor.href notes.push note elif c.className == 'intro-text' introBox = c imba.unmount target nav = document.querySelector("nav") nav.id = "notes-nav" const div = <div [ d:hflex jc:space-between grid-column: 8 / 22 grid-column@!1368: 8 / 28 max-width: 672px @!768 grid-column: 2 / -1 ]> const divl = <div [ grid-column: 1 / 7 min-width: 240px @!768 d: none ]> while nav.firstChild div.appendChild(nav.firstChild) menuSvg = <svg src=menu width=24px [fill:$text d:none d@!768: block mr:4] @click=(navOpen? = !navOpen?)> nav.appendChild divl nav.appendChild menuSvg nav.appendChild div <self> <div.left [x@!768:-5vw]=navOpen?> <div.searchbar> <svg src=search width=18px [fill:$text]> <input bind=searchQuery> <div.note-list.vert-scroller> for note in notes if !searchQuery <note-item note=note> else // <note-item note=note> if note.title.toLowerCase!.indexOf(searchQuery) >= 0 <note-item note=note> if fuzzyMatch(searchQuery, note.title) <div.center @click=(navOpen? = false) @touch=(navOpen? = false)> <div route="/notes/"> <h2[c:$text-primary]> "Notes" introBox <note-content @noteChanged=(navOpen? = false) route="/notes/:slug"> var root = document.getElementById '_search_app_target' var placeholder = document.getElementById '_search_app_placeholder' let appc = <app target=root> if root imba.mount appc, placeholder else console.log("no element with _search_app id found")