grok-digest 0.1.1 → 0.3.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.
@@ -0,0 +1,529 @@
1
+ @theme inline {
2
+ @keyframes accordion-down {
3
+ from {
4
+ height: 0;
5
+ }
6
+ to {
7
+ height: var(--radix-accordion-content-height, var(--accordion-panel-height, auto));
8
+ }
9
+ }
10
+
11
+ @keyframes accordion-up {
12
+ from {
13
+ height: var(--radix-accordion-content-height, var(--accordion-panel-height, auto));
14
+ }
15
+ to {
16
+ height: 0;
17
+ }
18
+ }
19
+ }
20
+
21
+ @custom-variant data-open {
22
+ &:where([data-state="open"]),
23
+ &:where([data-open]:not([data-open="false"])) {
24
+ @slot;
25
+ }
26
+ }
27
+
28
+ @custom-variant data-closed {
29
+ &:where([data-state="closed"]),
30
+ &:where([data-closed]:not([data-closed="false"])) {
31
+ @slot;
32
+ }
33
+ }
34
+
35
+ @custom-variant data-checked {
36
+ &:where([data-state="checked"]),
37
+ &:where([data-checked]:not([data-checked="false"])) {
38
+ @slot;
39
+ }
40
+ }
41
+
42
+ @custom-variant data-unchecked {
43
+ &:where([data-state="unchecked"]),
44
+ &:where([data-unchecked]:not([data-unchecked="false"])) {
45
+ @slot;
46
+ }
47
+ }
48
+
49
+ @custom-variant data-selected {
50
+ &:where([data-selected="true"]) {
51
+ @slot;
52
+ }
53
+ }
54
+
55
+ @custom-variant data-disabled {
56
+ &:where([data-disabled="true"]),
57
+ &:where([data-disabled]:not([data-disabled="false"])) {
58
+ @slot;
59
+ }
60
+ }
61
+
62
+ @custom-variant data-active {
63
+ &:where([data-state="active"]),
64
+ &:where([data-active]:not([data-active="false"])) {
65
+ @slot;
66
+ }
67
+ }
68
+
69
+ @custom-variant data-horizontal {
70
+ &:where([data-orientation="horizontal"]) {
71
+ @slot;
72
+ }
73
+ }
74
+
75
+ @custom-variant data-vertical {
76
+ &:where([data-orientation="vertical"]) {
77
+ @slot;
78
+ }
79
+ }
80
+
81
+ @utility no-scrollbar {
82
+ -ms-overflow-style: none;
83
+ scrollbar-width: none;
84
+
85
+ &::-webkit-scrollbar {
86
+ display: none;
87
+ }
88
+ }
89
+
90
+ @property --scroll-fade-t {
91
+ syntax: "<length-percentage>";
92
+ inherits: false;
93
+ initial-value: 0px;
94
+ }
95
+ @property --scroll-fade-b {
96
+ syntax: "<length-percentage>";
97
+ inherits: false;
98
+ initial-value: 0px;
99
+ }
100
+ @property --scroll-fade-s {
101
+ syntax: "<length-percentage>";
102
+ inherits: false;
103
+ initial-value: 0px;
104
+ }
105
+ @property --scroll-fade-e {
106
+ syntax: "<length-percentage>";
107
+ inherits: false;
108
+ initial-value: 0px;
109
+ }
110
+ @property --scroll-fade-mask {
111
+ syntax: "*";
112
+ inherits: false;
113
+ }
114
+
115
+ @theme inline {
116
+ @keyframes scroll-fade-reveal-t {
117
+ from {
118
+ --scroll-fade-t: 0px;
119
+ }
120
+ to {
121
+ --scroll-fade-t: var(--_scroll-fade-size-t, var(--scroll-fade-size, min(12%, calc(var(--spacing) * 10))));
122
+ }
123
+ }
124
+ @keyframes scroll-fade-reveal-b {
125
+ from {
126
+ --scroll-fade-b: var(--_scroll-fade-size-b, var(--scroll-fade-size, min(12%, calc(var(--spacing) * 10))));
127
+ }
128
+ to {
129
+ --scroll-fade-b: 0px;
130
+ }
131
+ }
132
+ @keyframes scroll-fade-reveal-s {
133
+ from {
134
+ --scroll-fade-s: 0px;
135
+ }
136
+ to {
137
+ --scroll-fade-s: var(--_scroll-fade-size-s, var(--scroll-fade-size, min(12%, calc(var(--spacing) * 10))));
138
+ }
139
+ }
140
+ @keyframes scroll-fade-reveal-e {
141
+ from {
142
+ --scroll-fade-e: var(--_scroll-fade-size-e, var(--scroll-fade-size, min(12%, calc(var(--spacing) * 10))));
143
+ }
144
+ to {
145
+ --scroll-fade-e: 0px;
146
+ }
147
+ }
148
+ }
149
+
150
+ @utility scroll-fade {
151
+ --_scroll-fade-size-t: var(--scroll-fade-t-size, var(--scroll-fade-size, min(12%, calc(var(--spacing) * 10))));
152
+ --_scroll-fade-size-b: var(--scroll-fade-b-size, var(--scroll-fade-size, min(12%, calc(var(--spacing) * 10))));
153
+ --scroll-fade-block: linear-gradient(
154
+ to bottom,
155
+ transparent 0,
156
+ #000 var(--scroll-fade-t, 0px),
157
+ #000 calc(100% - var(--scroll-fade-b, 0px)),
158
+ transparent 100%
159
+ );
160
+ -webkit-mask-image: var(--scroll-fade-mask, var(--scroll-fade-block));
161
+ mask-image: var(--scroll-fade-mask, var(--scroll-fade-block));
162
+ -webkit-mask-composite: source-in;
163
+ mask-composite: intersect;
164
+ -webkit-mask-repeat: no-repeat;
165
+ mask-repeat: no-repeat;
166
+
167
+ @supports (animation-timeline: scroll()) {
168
+ animation:
169
+ scroll-fade-reveal-t 1ms ease-in-out,
170
+ scroll-fade-reveal-b 1ms ease-in-out;
171
+ animation-timeline: scroll(self y), scroll(self y);
172
+ animation-range:
173
+ 0 var(--scroll-fade-reveal, calc(var(--spacing) * 24)),
174
+ calc(100% - var(--scroll-fade-reveal, calc(var(--spacing) * 24))) 100%;
175
+ animation-fill-mode: both;
176
+ }
177
+
178
+ @supports not (animation-timeline: scroll()) {
179
+ --scroll-fade-t: var(--_scroll-fade-size-t);
180
+ --scroll-fade-b: var(--_scroll-fade-size-b);
181
+ }
182
+ }
183
+
184
+ @utility scroll-fade-y {
185
+ --_scroll-fade-size-t: var(--scroll-fade-t-size, var(--scroll-fade-size, min(12%, calc(var(--spacing) * 10))));
186
+ --_scroll-fade-size-b: var(--scroll-fade-b-size, var(--scroll-fade-size, min(12%, calc(var(--spacing) * 10))));
187
+ --scroll-fade-block: linear-gradient(
188
+ to bottom,
189
+ transparent 0,
190
+ #000 var(--scroll-fade-t, 0px),
191
+ #000 calc(100% - var(--scroll-fade-b, 0px)),
192
+ transparent 100%
193
+ );
194
+ -webkit-mask-image: var(--scroll-fade-mask, var(--scroll-fade-block));
195
+ mask-image: var(--scroll-fade-mask, var(--scroll-fade-block));
196
+ -webkit-mask-composite: source-in;
197
+ mask-composite: intersect;
198
+ -webkit-mask-repeat: no-repeat;
199
+ mask-repeat: no-repeat;
200
+
201
+ @supports (animation-timeline: scroll()) {
202
+ animation:
203
+ scroll-fade-reveal-t 1ms ease-in-out,
204
+ scroll-fade-reveal-b 1ms ease-in-out;
205
+ animation-timeline: scroll(self y), scroll(self y);
206
+ animation-range:
207
+ 0 var(--scroll-fade-reveal, calc(var(--spacing) * 24)),
208
+ calc(100% - var(--scroll-fade-reveal, calc(var(--spacing) * 24))) 100%;
209
+ animation-fill-mode: both;
210
+ }
211
+
212
+ @supports not (animation-timeline: scroll()) {
213
+ --scroll-fade-t: var(--_scroll-fade-size-t);
214
+ --scroll-fade-b: var(--_scroll-fade-size-b);
215
+ }
216
+ }
217
+
218
+ @utility scroll-fade-x {
219
+ --_scroll-fade-size-s: var(--scroll-fade-s-size, var(--scroll-fade-size, min(12%, calc(var(--spacing) * 10))));
220
+ --_scroll-fade-size-e: var(--scroll-fade-e-size, var(--scroll-fade-size, min(12%, calc(var(--spacing) * 10))));
221
+ --scroll-fade-inline: linear-gradient(
222
+ to right,
223
+ transparent 0,
224
+ #000 var(--scroll-fade-s, 0px),
225
+ #000 calc(100% - var(--scroll-fade-e, 0px)),
226
+ transparent 100%
227
+ );
228
+ &:where([dir="rtl"], [dir="rtl"] *) {
229
+ --scroll-fade-inline: linear-gradient(
230
+ to left,
231
+ transparent 0,
232
+ #000 var(--scroll-fade-s, 0px),
233
+ #000 calc(100% - var(--scroll-fade-e, 0px)),
234
+ transparent 100%
235
+ );
236
+ }
237
+ -webkit-mask-image: var(--scroll-fade-mask, var(--scroll-fade-inline));
238
+ mask-image: var(--scroll-fade-mask, var(--scroll-fade-inline));
239
+ -webkit-mask-composite: source-in;
240
+ mask-composite: intersect;
241
+ -webkit-mask-repeat: no-repeat;
242
+ mask-repeat: no-repeat;
243
+
244
+ @supports (animation-timeline: scroll()) {
245
+ animation:
246
+ scroll-fade-reveal-s 1ms ease-in-out,
247
+ scroll-fade-reveal-e 1ms ease-in-out;
248
+ animation-timeline: scroll(self inline), scroll(self inline);
249
+ animation-range:
250
+ 0 var(--scroll-fade-reveal, calc(var(--spacing) * 24)),
251
+ calc(100% - var(--scroll-fade-reveal, calc(var(--spacing) * 24))) 100%;
252
+ animation-fill-mode: both;
253
+ }
254
+
255
+ @supports not (animation-timeline: scroll()) {
256
+ --scroll-fade-s: var(--_scroll-fade-size-s);
257
+ --scroll-fade-e: var(--_scroll-fade-size-e);
258
+ }
259
+ }
260
+
261
+ @utility scroll-fade-t {
262
+ --_scroll-fade-size-t: var(--scroll-fade-t-size, var(--scroll-fade-size, min(12%, calc(var(--spacing) * 10))));
263
+ --scroll-fade-mask: linear-gradient(to bottom, transparent 0, #000 var(--scroll-fade-t, 0px), #000 100%);
264
+ -webkit-mask-image: var(--scroll-fade-mask);
265
+ mask-image: var(--scroll-fade-mask);
266
+ -webkit-mask-composite: source-in;
267
+ mask-composite: intersect;
268
+ -webkit-mask-repeat: no-repeat;
269
+ mask-repeat: no-repeat;
270
+
271
+ @supports (animation-timeline: scroll()) {
272
+ animation: scroll-fade-reveal-t 1ms ease-in-out;
273
+ animation-timeline: scroll(self y);
274
+ animation-range: 0 var(--scroll-fade-reveal, calc(var(--spacing) * 24));
275
+ animation-fill-mode: both;
276
+ }
277
+
278
+ @supports not (animation-timeline: scroll()) {
279
+ --scroll-fade-t: var(--_scroll-fade-size-t);
280
+ }
281
+ }
282
+
283
+ @utility scroll-fade-b {
284
+ --_scroll-fade-size-b: var(--scroll-fade-b-size, var(--scroll-fade-size, min(12%, calc(var(--spacing) * 10))));
285
+ --scroll-fade-mask: linear-gradient(to bottom, #000 0, #000 calc(100% - var(--scroll-fade-b, 0px)), transparent 100%);
286
+ -webkit-mask-image: var(--scroll-fade-mask);
287
+ mask-image: var(--scroll-fade-mask);
288
+ -webkit-mask-composite: source-in;
289
+ mask-composite: intersect;
290
+ -webkit-mask-repeat: no-repeat;
291
+ mask-repeat: no-repeat;
292
+
293
+ @supports (animation-timeline: scroll()) {
294
+ animation: scroll-fade-reveal-b 1ms ease-in-out;
295
+ animation-timeline: scroll(self y);
296
+ animation-range: calc(100% - var(--scroll-fade-reveal, calc(var(--spacing) * 24))) 100%;
297
+ animation-fill-mode: both;
298
+ }
299
+
300
+ @supports not (animation-timeline: scroll()) {
301
+ --scroll-fade-b: var(--_scroll-fade-size-b);
302
+ }
303
+ }
304
+
305
+ @utility scroll-fade-l {
306
+ --_scroll-fade-size-s: var(--scroll-fade-s-size, var(--scroll-fade-size, min(12%, calc(var(--spacing) * 10))));
307
+ --scroll-fade-mask: linear-gradient(to right, transparent 0, #000 var(--scroll-fade-s, 0px), #000 100%);
308
+ -webkit-mask-image: var(--scroll-fade-mask);
309
+ mask-image: var(--scroll-fade-mask);
310
+ -webkit-mask-composite: source-in;
311
+ mask-composite: intersect;
312
+ -webkit-mask-repeat: no-repeat;
313
+ mask-repeat: no-repeat;
314
+
315
+ @supports (animation-timeline: scroll()) {
316
+ animation: scroll-fade-reveal-s 1ms ease-in-out;
317
+ animation-timeline: scroll(self x);
318
+ animation-range: 0 var(--scroll-fade-reveal, calc(var(--spacing) * 24));
319
+ animation-fill-mode: both;
320
+ }
321
+
322
+ @supports not (animation-timeline: scroll()) {
323
+ --scroll-fade-s: var(--_scroll-fade-size-s);
324
+ }
325
+ }
326
+
327
+ @utility scroll-fade-r {
328
+ --_scroll-fade-size-e: var(--scroll-fade-e-size, var(--scroll-fade-size, min(12%, calc(var(--spacing) * 10))));
329
+ --scroll-fade-mask: linear-gradient(to right, #000 0, #000 calc(100% - var(--scroll-fade-e, 0px)), transparent 100%);
330
+ -webkit-mask-image: var(--scroll-fade-mask);
331
+ mask-image: var(--scroll-fade-mask);
332
+ -webkit-mask-composite: source-in;
333
+ mask-composite: intersect;
334
+ -webkit-mask-repeat: no-repeat;
335
+ mask-repeat: no-repeat;
336
+
337
+ @supports (animation-timeline: scroll()) {
338
+ animation: scroll-fade-reveal-e 1ms ease-in-out;
339
+ animation-timeline: scroll(self x);
340
+ animation-range: calc(100% - var(--scroll-fade-reveal, calc(var(--spacing) * 24))) 100%;
341
+ animation-fill-mode: both;
342
+ }
343
+
344
+ @supports not (animation-timeline: scroll()) {
345
+ --scroll-fade-e: var(--_scroll-fade-size-e);
346
+ }
347
+ }
348
+
349
+ @utility scroll-fade-s {
350
+ --_scroll-fade-size-s: var(--scroll-fade-s-size, var(--scroll-fade-size, min(12%, calc(var(--spacing) * 10))));
351
+ --scroll-fade-mask: linear-gradient(to right, transparent 0, #000 var(--scroll-fade-s, 0px), #000 100%);
352
+ &:where([dir="rtl"], [dir="rtl"] *) {
353
+ --scroll-fade-mask: linear-gradient(to left, transparent 0, #000 var(--scroll-fade-s, 0px), #000 100%);
354
+ }
355
+ -webkit-mask-image: var(--scroll-fade-mask);
356
+ mask-image: var(--scroll-fade-mask);
357
+ -webkit-mask-composite: source-in;
358
+ mask-composite: intersect;
359
+ -webkit-mask-repeat: no-repeat;
360
+ mask-repeat: no-repeat;
361
+
362
+ @supports (animation-timeline: scroll()) {
363
+ animation: scroll-fade-reveal-s 1ms ease-in-out;
364
+ animation-timeline: scroll(self inline);
365
+ animation-range: 0 var(--scroll-fade-reveal, calc(var(--spacing) * 24));
366
+ animation-fill-mode: both;
367
+ }
368
+
369
+ @supports not (animation-timeline: scroll()) {
370
+ --scroll-fade-s: var(--_scroll-fade-size-s);
371
+ }
372
+ }
373
+
374
+ @utility scroll-fade-e {
375
+ --_scroll-fade-size-e: var(--scroll-fade-e-size, var(--scroll-fade-size, min(12%, calc(var(--spacing) * 10))));
376
+ --scroll-fade-mask: linear-gradient(to right, #000 0, #000 calc(100% - var(--scroll-fade-e, 0px)), transparent 100%);
377
+ &:where([dir="rtl"], [dir="rtl"] *) {
378
+ --scroll-fade-mask: linear-gradient(to left, #000 0, #000 calc(100% - var(--scroll-fade-e, 0px)), transparent 100%);
379
+ }
380
+ -webkit-mask-image: var(--scroll-fade-mask);
381
+ mask-image: var(--scroll-fade-mask);
382
+ -webkit-mask-composite: source-in;
383
+ mask-composite: intersect;
384
+ -webkit-mask-repeat: no-repeat;
385
+ mask-repeat: no-repeat;
386
+
387
+ @supports (animation-timeline: scroll()) {
388
+ animation: scroll-fade-reveal-e 1ms ease-in-out;
389
+ animation-timeline: scroll(self inline);
390
+ animation-range: calc(100% - var(--scroll-fade-reveal, calc(var(--spacing) * 24))) 100%;
391
+ animation-fill-mode: both;
392
+ }
393
+
394
+ @supports not (animation-timeline: scroll()) {
395
+ --scroll-fade-e: var(--_scroll-fade-size-e);
396
+ }
397
+ }
398
+
399
+ @utility scroll-fade-* {
400
+ --scroll-fade-size: calc(var(--spacing) * --value(integer));
401
+ --scroll-fade-size: --value([length], [percentage]);
402
+ }
403
+
404
+ @utility scroll-fade-t-* {
405
+ --scroll-fade-t-size: calc(var(--spacing) * --value(integer));
406
+ --scroll-fade-t-size: --value([length], [percentage]);
407
+ }
408
+
409
+ @utility scroll-fade-b-* {
410
+ --scroll-fade-b-size: calc(var(--spacing) * --value(integer));
411
+ --scroll-fade-b-size: --value([length], [percentage]);
412
+ }
413
+
414
+ @utility scroll-fade-s-* {
415
+ --scroll-fade-s-size: calc(var(--spacing) * --value(integer));
416
+ --scroll-fade-s-size: --value([length], [percentage]);
417
+ }
418
+
419
+ @utility scroll-fade-e-* {
420
+ --scroll-fade-e-size: calc(var(--spacing) * --value(integer));
421
+ --scroll-fade-e-size: --value([length], [percentage]);
422
+ }
423
+
424
+ @utility scroll-fade-none {
425
+ --scroll-fade-mask: none;
426
+ }
427
+
428
+ @property --shimmer-angle {
429
+ syntax: "<angle>";
430
+ inherits: true;
431
+ initial-value: 20deg;
432
+ }
433
+ @property --shimmer-image {
434
+ syntax: "*";
435
+ inherits: false;
436
+ }
437
+ @property --shimmer-text-fill {
438
+ syntax: "*";
439
+ inherits: false;
440
+ }
441
+
442
+ @theme inline {
443
+ @keyframes tw-shimmer {
444
+ from {
445
+ background-position: 100% 0;
446
+ }
447
+ to {
448
+ background-position: 0 0;
449
+ }
450
+ }
451
+ }
452
+
453
+ @utility shimmer {
454
+ --_spread: var(--shimmer-spread, calc(3ch + 40px));
455
+ --_base: currentColor;
456
+ --_highlight: var(--shimmer-color, oklch(from currentColor l c h / calc(alpha* 0.2)));
457
+
458
+ background-image: var(
459
+ --shimmer-image,
460
+ linear-gradient(
461
+ calc(90deg + var(--shimmer-angle)),
462
+ var(--_base) calc(50% - var(--_spread)),
463
+ color-mix(in oklch, var(--_highlight), var(--_base) 50%) calc(50% - var(--_spread) * 0.5),
464
+ var(--_highlight) 50%,
465
+ color-mix(in oklch, var(--_highlight), var(--_base) 50%) calc(50% + var(--_spread) * 0.5),
466
+ var(--_base) calc(50% + var(--_spread))
467
+ )
468
+ );
469
+ background-repeat: no-repeat;
470
+ background-size: calc(200% + var(--_spread) * 2) 100%;
471
+ background-position: 0 0;
472
+ background-clip: text;
473
+ -webkit-background-clip: text;
474
+ -webkit-text-fill-color: var(--shimmer-text-fill, transparent);
475
+ animation: tw-shimmer var(--shimmer-duration, 2s) linear infinite;
476
+
477
+ @variant dark {
478
+ --_highlight: var(--shimmer-color, oklch(from currentColor max(0.8, calc(l + 0.4)) c h / calc(alpha + 0.4)));
479
+ }
480
+
481
+ &:where([dir="rtl"], [dir="rtl"] *) {
482
+ animation-direction: reverse;
483
+ }
484
+
485
+ @media (prefers-reduced-motion: reduce) {
486
+ animation: none;
487
+ background-image: none;
488
+ -webkit-text-fill-color: currentColor;
489
+ }
490
+ }
491
+
492
+ @utility shimmer-once {
493
+ animation-iteration-count: 1;
494
+ }
495
+
496
+ @utility shimmer-reverse {
497
+ animation-direction: reverse;
498
+ }
499
+
500
+ @utility shimmer-none {
501
+ --shimmer-image: none;
502
+ --shimmer-text-fill: currentColor;
503
+ }
504
+
505
+ @utility shimmer-color-* {
506
+ --shimmer-color: --value(--color, [color]);
507
+ --shimmer-color: color-mix(in oklch, --value(--color, [color]) calc(--modifier(integer) * 1%), transparent);
508
+ }
509
+
510
+ @utility shimmer-duration-* {
511
+ --shimmer-duration: calc(--value(integer) * 1ms);
512
+ }
513
+
514
+ @utility shimmer-spread-* {
515
+ --shimmer-spread: calc(var(--spacing) * --value(integer));
516
+ --shimmer-spread: --value([length], [percentage]);
517
+ }
518
+
519
+ @utility shimmer-angle-* {
520
+ --shimmer-angle: calc(--value(integer) * 1deg);
521
+ }
522
+
523
+ @media (prefers-reduced-motion: reduce) {
524
+ .shimmer {
525
+ animation: none;
526
+ background-image: none;
527
+ -webkit-text-fill-color: currentColor;
528
+ }
529
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "grok-digest",
3
- "version": "0.1.1",
3
+ "version": "0.3.0",
4
4
  "description": "Astro integration that renders a Grok Digest site: X bookmarks summarized by Grok, searchable, sorted by topic, with RSS feeds.",
5
5
  "keywords": [
6
6
  "astro",
@@ -19,7 +19,9 @@
19
19
  "grok-digest": "dist/cli.js"
20
20
  },
21
21
  "files": [
22
- "dist"
22
+ "dist",
23
+ "BOT.md",
24
+ "LICENSE-THIRD-PARTY"
23
25
  ],
24
26
  "type": "module",
25
27
  "exports": {
@@ -47,7 +49,7 @@
47
49
  "lint": "oxlint",
48
50
  "lint:fix": "oxlint --fix",
49
51
  "lint:comments": "node scripts/lint-comments.mjs",
50
- "lint:dup": "jscpd --threshold 0 --exit-code 1 --no-tips --reporters ai --ignore '**/bun.lock,**/data/*.json,**/test/fixtures/**,**/dist/**,**/.github/workflows/**' .",
52
+ "lint:dup": "jscpd --threshold 0 --exit-code 1 --no-tips --reporters ai --ignore '**/bun.lock,**/src/styles/shadcn-tailwind.css,**/data/*.json,**/test/fixtures/**,**/dist/**,**/.github/workflows/**' .",
51
53
  "knip": "knip",
52
54
  "format": "oxfmt",
53
55
  "format:check": "oxfmt --check",
@@ -66,7 +68,6 @@
66
68
  "radix-ui": "^1.8.1",
67
69
  "react": "^19.3.0",
68
70
  "react-dom": "^19.3.0",
69
- "shadcn": "^4.21.5",
70
71
  "tailwindcss": "^4.3.3",
71
72
  "tw-animate-css": "^1.4.0",
72
73
  "zod": "^4.6.7"
@@ -1,32 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { SearchIcon } from "lucide-react";
3
- import { useEffect, useMemo, useState } from "react";
4
- import { Button } from "./ui/button.js";
5
- import { Input } from "./ui/input.js";
6
- import { filterSearch, parseFilter } from "../lib/filter.js";
7
- import { matchingIds } from "../lib/search.js";
8
- import { TOPIC_LABELS, TOPICS } from "../lib/topics.js";
9
- export function BookmarkFilters({ entries }) {
10
- const initial = parseFilter(window.location.search);
11
- const [query, setQuery] = useState(initial.query);
12
- const [topic, setTopic] = useState(initial.topic);
13
- const visible = useMemo(() => matchingIds({ entries, query, topic }), [entries, query, topic]);
14
- const topicsInUse = useMemo(() => TOPICS.filter((t) => entries.some((entry) => entry.topic === t)), [entries]);
15
- useEffect(() => {
16
- for (const card of document.querySelectorAll("[data-bookmark-id]")) {
17
- card.hidden = !visible.has(card.dataset["bookmarkId"] ?? "");
18
- }
19
- }, [visible]);
20
- useEffect(() => {
21
- const next = `${window.location.pathname}${filterSearch({ query, topic })}${window.location.hash}`;
22
- const current = `${window.location.pathname}${window.location.search}${window.location.hash}`;
23
- if (current !== next)
24
- window.history.replaceState(null, "", next);
25
- }, [query, topic]);
26
- return (_jsxs("div", { className: "flex flex-col gap-4", children: [_jsxs("div", { className: "relative", children: [_jsx(SearchIcon, { className: "pointer-events-none absolute top-1/2 left-3 size-4 -translate-y-1/2 text-muted-foreground" }), _jsx(Input, { type: "search", value: query, onChange: (event) => setQuery(event.target.value), placeholder: "Search authors, posts, summaries, key points", "aria-label": "Search bookmarks", className: "h-10 rounded-full bg-card pl-9 dark:bg-card" })] }), _jsxs("fieldset", { "aria-label": "Filter by topic", className: "flex min-w-0 flex-wrap gap-2", children: [_jsx(TopicChip, { label: "All", pressed: topic === null, onClick: () => setTopic(null) }), topicsInUse.map((t) => (_jsx(TopicChip, { label: TOPIC_LABELS[t], pressed: topic === t, onClick: () => setTopic(topic === t ? null : t) }, t)))] }), _jsxs("p", { "aria-live": "polite", className: "text-sm text-muted-foreground", children: [visible.size === entries.length
27
- ? `${entries.length} ${entries.length === 1 ? "bookmark" : "bookmarks"}`
28
- : `Showing ${visible.size} of ${entries.length}`, visible.size === 0 && entries.length > 0 ? ". No bookmarks match your search." : ""] })] }));
29
- }
30
- function TopicChip({ label, pressed, onClick }) {
31
- return (_jsx(Button, { type: "button", size: "sm", variant: pressed ? "default" : "outline", "aria-pressed": pressed, onClick: onClick, className: "rounded-full px-3", children: label }));
32
- }