@raf-query/react 0.11.1 → 0.13.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.
Files changed (46) hide show
  1. package/CHANGELOG.md +39 -1
  2. package/README.md +32 -59
  3. package/dist/bind.d.mts +21 -0
  4. package/dist/bind.mjs +23 -0
  5. package/dist/browser-render.mjs +46 -0
  6. package/dist/devtools.d.mts +42 -2
  7. package/dist/devtools.mjs +244 -1
  8. package/dist/hydration-boundary/hydrate.mjs +10 -13
  9. package/dist/hydration-boundary/hydration-boundary-react-server.d.mts +6 -0
  10. package/dist/hydration-boundary/hydration-boundary-react-server.mjs +20 -9
  11. package/dist/hydration-boundary/hydration-boundary.d.mts +15 -28
  12. package/dist/hydration-boundary/hydration-boundary.mjs +7 -26
  13. package/dist/index-react-server.d.mts +7 -6
  14. package/dist/index-react-server.mjs +4 -6
  15. package/dist/index-shared.d.mts +5 -6
  16. package/dist/index-shared.mjs +3 -6
  17. package/dist/index.d.mts +7 -6
  18. package/dist/index.mjs +5 -4
  19. package/dist/provider.d.mts +11 -5
  20. package/dist/provider.mjs +12 -9
  21. package/dist/react-server-hooks.d.mts +43 -0
  22. package/dist/react-server-hooks.mjs +45 -0
  23. package/dist/tanstack-router-browser.d.mts +2 -0
  24. package/dist/tanstack-router-browser.mjs +2 -0
  25. package/dist/tanstack-router-shared.d.mts +9 -7
  26. package/dist/tanstack-router-shared.mjs +12 -22
  27. package/dist/tanstack-router.d.mts +4 -2
  28. package/dist/tanstack-router.mjs +12 -14
  29. package/dist/tracked.d.mts +1 -0
  30. package/dist/tracked.mjs +65 -0
  31. package/dist/use-infinite-query.d.mts +23 -0
  32. package/dist/use-infinite-query.mjs +30 -0
  33. package/dist/use-is-fetching.d.mts +7 -15
  34. package/dist/use-is-fetching.mjs +12 -30
  35. package/dist/use-query.d.mts +52 -50
  36. package/dist/use-query.mjs +112 -47
  37. package/package.json +10 -9
  38. package/dist/devtools-panel.d.mts +0 -38
  39. package/dist/devtools-panel.mjs +0 -896
  40. package/dist/devtools-store.mjs +0 -104
  41. package/dist/hydration-boundary/sent.mjs +0 -16
  42. package/dist/query-provider/browser-requests.mjs +0 -38
  43. package/dist/query-provider/query-provider.d.mts +0 -21
  44. package/dist/query-provider/query-provider.mjs +0 -33
  45. package/dist/use-waterfall.d.mts +0 -18
  46. package/dist/use-waterfall.mjs +0 -41
@@ -1,896 +0,0 @@
1
- "use client";
2
- import { useOptionalQueryClient } from "./provider.mjs";
3
- import { countByStatus, sortOrders, statuses, useQueryRows, visibleRows } from "./devtools-store.mjs";
4
- import { Query } from "@raf-query/core";
5
- import { useState, useSyncExternalStore } from "react";
6
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
7
- import { Effect, Predicate } from "effect";
8
- //#region src/devtools-panel.tsx
9
- const palettes = {
10
- dark: {
11
- accent: "#978bff",
12
- background: "#0f172a",
13
- boolean: "#f472b6",
14
- border: "#334155",
15
- muted: "#94a3b8",
16
- number: "#fbbf24",
17
- raised: "#1e293b",
18
- selected: "#2b2653",
19
- string: "#4ade80",
20
- text: "#e2e8f0"
21
- },
22
- light: {
23
- accent: "#6c48ea",
24
- background: "#ffffff",
25
- boolean: "#be185d",
26
- border: "#cbd5e1",
27
- muted: "#64748b",
28
- number: "#b45309",
29
- raised: "#f1f5f9",
30
- selected: "#e9e8ff",
31
- string: "#15803d",
32
- text: "#0f172a"
33
- }
34
- };
35
- /** The logo's gradient: blue through violet to coral. */
36
- const brandGradient = "linear-gradient(135deg, #3b8eea, #7b5cff, #ff4d6d)";
37
- const statusColors = {
38
- error: "#dc2626",
39
- fetching: "#2563eb",
40
- fresh: "#16a34a",
41
- inactive: "#64748b",
42
- stale: "#ca8a04"
43
- };
44
- const sortLabels = {
45
- hash: "Key",
46
- status: "Status",
47
- updated: "Last updated"
48
- };
49
- const fontFamily = "ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", Roboto, sans-serif";
50
- const monoFamily = "ui-monospace, SFMono-Regular, Menlo, Consolas, \"Liberation Mono\", monospace";
51
- /** Entries an expanded object, array, map, or set lists before "… more". */
52
- const maxChildren = 100;
53
- const minSize = 120;
54
- const defaultSize = 320;
55
- const storageKeys = {
56
- open: "raf-query-devtools:open",
57
- size: "raf-query-devtools:size"
58
- };
59
- const noop = () => {};
60
- const subscribeNever = () => noop;
61
- /** `false` on the server and while hydrating, then `true`. */
62
- function useIsClient() {
63
- return useSyncExternalStore(subscribeNever, () => true, () => false);
64
- }
65
- function subscribeColorScheme(onChange) {
66
- const media = window.matchMedia("(prefers-color-scheme: dark)");
67
- media.addEventListener("change", onChange);
68
- return () => media.removeEventListener("change", onChange);
69
- }
70
- function prefersDark() {
71
- return window.matchMedia("(prefers-color-scheme: dark)").matches;
72
- }
73
- function usePalette(theme = "system") {
74
- const systemDark = useSyncExternalStore(subscribeColorScheme, prefersDark, () => true);
75
- if (theme === "system") return systemDark ? palettes.dark : palettes.light;
76
- return palettes[theme];
77
- }
78
- function useDevtoolsClient(client) {
79
- const contextClient = useOptionalQueryClient();
80
- const resolved = client ?? contextClient;
81
- if (!resolved) throw new Error("raf-query devtools: pass `client` or render inside a QueryClientProvider");
82
- return resolved;
83
- }
84
- function readStored(key) {
85
- try {
86
- return window.localStorage.getItem(key);
87
- } catch {
88
- return null;
89
- }
90
- }
91
- function writeStored(key, value) {
92
- try {
93
- window.localStorage.setItem(key, value);
94
- } catch {}
95
- }
96
- function formatTime(updatedAt) {
97
- return updatedAt === 0 ? "never" : new Date(updatedAt).toLocaleTimeString();
98
- }
99
- /** One-line form of a value, for leaves and collapsed nodes. */
100
- function preview(value) {
101
- if (Predicate.isString(value)) return JSON.stringify(value);
102
- if (Predicate.isBigInt(value)) return `${value}n`;
103
- if (Predicate.isSymbol(value)) return value.toString();
104
- if (Predicate.isFunction(value)) return `ƒ ${value.name || "anonymous"}()`;
105
- if (Predicate.isDate(value)) return Number.isNaN(value.getTime()) ? "Invalid Date" : value.toISOString();
106
- if (Predicate.isError(value)) return `${value.name}: ${value.message}`;
107
- if (Predicate.isRegExp(value)) return String(value);
108
- if (Predicate.isPromiseLike(value)) return "Promise";
109
- if (Array.isArray(value)) return `Array(${value.length})`;
110
- if (Predicate.isMap(value)) return `Map(${value.size})`;
111
- if (Predicate.isSet(value)) return `Set(${value.size})`;
112
- if (Predicate.isObject(value)) {
113
- const size = Object.keys(value).length;
114
- return size === 1 ? "{1 key}" : `{${size} keys}`;
115
- }
116
- return String(value);
117
- }
118
- /** Labelled children of a value the explorer can expand, else `undefined`. */
119
- function childrenOf(value) {
120
- if (Array.isArray(value)) return value.map((item, index) => [String(index), item]);
121
- if (Predicate.isMap(value)) return [...value].map(([key, item]) => [preview(key), item]);
122
- if (Predicate.isSet(value)) return [...value].map((item, index) => [String(index), item]);
123
- if (!Predicate.isObject(value) || Predicate.isDate(value) || Predicate.isError(value) || Predicate.isRegExp(value) || Predicate.isPromiseLike(value)) return;
124
- return Object.entries(value);
125
- }
126
- function colorOf(value, palette) {
127
- if (Predicate.isString(value)) return palette.string;
128
- if (Predicate.isNumber(value) || Predicate.isBigInt(value)) return palette.number;
129
- if (Predicate.isBoolean(value)) return palette.boolean;
130
- if (Predicate.isNullish(value)) return palette.muted;
131
- return palette.text;
132
- }
133
- function copyText(value) {
134
- try {
135
- return JSON.stringify(value, null, 2) ?? String(value);
136
- } catch {
137
- return preview(value);
138
- }
139
- }
140
- function Explorer(props) {
141
- const [expanded, setExpanded] = useState(props.depth < 1);
142
- const children = childrenOf(props.value);
143
- const palette = props.palette;
144
- const label = props.label === void 0 ? null : /* @__PURE__ */ jsx("span", {
145
- style: { color: palette.accent },
146
- children: `${props.label}: `
147
- });
148
- if (children === void 0) return /* @__PURE__ */ jsxs("div", {
149
- style: { paddingLeft: 14 },
150
- children: [label, /* @__PURE__ */ jsx("span", {
151
- style: { color: colorOf(props.value, palette) },
152
- children: preview(props.value)
153
- })]
154
- });
155
- return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs("button", {
156
- "aria-expanded": expanded,
157
- onClick: () => setExpanded(!expanded),
158
- style: {
159
- background: "none",
160
- border: "none",
161
- color: palette.text,
162
- cursor: "pointer",
163
- font: "inherit",
164
- padding: 0,
165
- textAlign: "left"
166
- },
167
- type: "button",
168
- children: [
169
- /* @__PURE__ */ jsx("span", {
170
- "aria-hidden": true,
171
- style: {
172
- display: "inline-block",
173
- width: 14
174
- },
175
- children: expanded ? "▾" : "▸"
176
- }),
177
- label,
178
- /* @__PURE__ */ jsx("span", {
179
- style: { color: palette.muted },
180
- children: preview(props.value)
181
- })
182
- ]
183
- }), expanded ? /* @__PURE__ */ jsxs("div", {
184
- style: { paddingLeft: 14 },
185
- children: [children.slice(0, maxChildren).map(([key, item]) => /* @__PURE__ */ jsx(Explorer, {
186
- depth: props.depth + 1,
187
- label: key,
188
- palette,
189
- value: item
190
- }, key)), children.length > maxChildren ? /* @__PURE__ */ jsx("div", {
191
- style: {
192
- color: palette.muted,
193
- paddingLeft: 14
194
- },
195
- children: `… ${children.length - maxChildren} more`
196
- }) : null]
197
- }) : null] });
198
- }
199
- function StatusChip(props) {
200
- return /* @__PURE__ */ jsxs("span", {
201
- "data-status": props.status,
202
- style: {
203
- alignItems: "center",
204
- background: props.palette.raised,
205
- border: `1px solid ${props.palette.border}`,
206
- borderRadius: 999,
207
- display: "inline-flex",
208
- gap: 6,
209
- padding: "2px 8px"
210
- },
211
- children: [/* @__PURE__ */ jsx("span", {
212
- "aria-hidden": true,
213
- style: {
214
- background: statusColors[props.status],
215
- borderRadius: 999,
216
- height: 8,
217
- width: 8
218
- }
219
- }), `${props.status} ${props.count}`]
220
- });
221
- }
222
- function ActionButton(props) {
223
- return /* @__PURE__ */ jsx("button", {
224
- disabled: props.disabled,
225
- onClick: props.onClick,
226
- style: {
227
- background: props.color,
228
- border: "none",
229
- borderRadius: 4,
230
- color: "#ffffff",
231
- cursor: props.disabled ? "not-allowed" : "pointer",
232
- font: "inherit",
233
- opacity: props.disabled ? .5 : 1,
234
- padding: "4px 10px"
235
- },
236
- type: "button",
237
- children: props.label
238
- });
239
- }
240
- function Heading(props) {
241
- return /* @__PURE__ */ jsx("h3", {
242
- style: {
243
- background: props.palette.raised,
244
- borderBottom: `1px solid ${props.palette.border}`,
245
- borderTop: `1px solid ${props.palette.border}`,
246
- fontSize: 12,
247
- fontWeight: 600,
248
- margin: 0,
249
- padding: "4px 8px"
250
- },
251
- children: props.title
252
- });
253
- }
254
- function Field(props) {
255
- return /* @__PURE__ */ jsxs("div", {
256
- style: {
257
- display: "flex",
258
- gap: 8,
259
- justifyContent: "space-between"
260
- },
261
- children: [/* @__PURE__ */ jsx("dt", {
262
- style: { color: props.palette.muted },
263
- children: props.label
264
- }), /* @__PURE__ */ jsx("dd", {
265
- style: {
266
- margin: 0,
267
- textAlign: "right"
268
- },
269
- children: props.children
270
- })]
271
- });
272
- }
273
- function QueryDetails(props) {
274
- const palette = props.palette;
275
- const query = props.row.query;
276
- const state = props.row.state;
277
- const options = query.options;
278
- const meta = Query.metaUnsafe(query);
279
- const section = { padding: 8 };
280
- return /* @__PURE__ */ jsxs("section", {
281
- "aria-label": "Query details",
282
- style: {
283
- flex: 1,
284
- minWidth: 0,
285
- overflow: "auto"
286
- },
287
- children: [
288
- /* @__PURE__ */ jsx(Heading, {
289
- palette,
290
- title: "Query details"
291
- }),
292
- /* @__PURE__ */ jsxs("div", {
293
- style: section,
294
- children: [/* @__PURE__ */ jsx("pre", {
295
- style: {
296
- fontFamily: monoFamily,
297
- margin: "0 0 8px",
298
- whiteSpace: "pre-wrap",
299
- wordBreak: "break-all"
300
- },
301
- children: JSON.stringify(query.key, null, 2)
302
- }), /* @__PURE__ */ jsxs("dl", {
303
- style: {
304
- display: "grid",
305
- gap: 4,
306
- margin: 0
307
- },
308
- children: [
309
- /* @__PURE__ */ jsx(Field, {
310
- label: "Status",
311
- palette,
312
- children: props.row.status
313
- }),
314
- /* @__PURE__ */ jsx(Field, {
315
- label: "Observers",
316
- palette,
317
- children: String(props.row.observers)
318
- }),
319
- /* @__PURE__ */ jsx(Field, {
320
- label: "Last updated",
321
- palette,
322
- children: formatTime(state.updatedAt)
323
- }),
324
- /* @__PURE__ */ jsx(Field, {
325
- label: "Kind",
326
- palette,
327
- children: options === void 0 ? "hydrated" : options.kind
328
- }),
329
- /* @__PURE__ */ jsx(Field, {
330
- label: "Failures",
331
- palette,
332
- children: String(state.failureCount)
333
- })
334
- ]
335
- })]
336
- }),
337
- /* @__PURE__ */ jsx(Heading, {
338
- palette,
339
- title: "Actions"
340
- }),
341
- /* @__PURE__ */ jsxs("div", {
342
- style: {
343
- ...section,
344
- display: "flex",
345
- flexWrap: "wrap",
346
- gap: 6
347
- },
348
- children: [
349
- /* @__PURE__ */ jsx(ActionButton, {
350
- color: statusColors.fetching,
351
- disabled: options === void 0 || state.isFetching,
352
- label: "Refetch",
353
- onClick: () => void Effect.runPromise(Query.refetch(query))
354
- }),
355
- /* @__PURE__ */ jsx(ActionButton, {
356
- color: statusColors.stale,
357
- label: "Invalidate",
358
- onClick: () => void Effect.runPromise(Query.invalidate(query))
359
- }),
360
- /* @__PURE__ */ jsx(ActionButton, {
361
- color: statusColors.inactive,
362
- label: "Reset",
363
- onClick: () => void Effect.runPromise(Query.reset(query))
364
- }),
365
- /* @__PURE__ */ jsx(ActionButton, {
366
- color: statusColors.error,
367
- label: "Remove",
368
- onClick: () => props.client.remove({
369
- exact: true,
370
- queryKey: query.key
371
- })
372
- })
373
- ]
374
- }),
375
- state.error == null ? null : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Heading, {
376
- palette,
377
- title: "Error"
378
- }), /* @__PURE__ */ jsxs("div", {
379
- style: {
380
- ...section,
381
- color: statusColors.error
382
- },
383
- children: [/* @__PURE__ */ jsx("div", { children: preview(state.error) }), Predicate.isError(state.error) && state.error.stack ? /* @__PURE__ */ jsx("pre", {
384
- style: {
385
- fontFamily: monoFamily,
386
- fontSize: 11,
387
- margin: "6px 0 0",
388
- whiteSpace: "pre-wrap"
389
- },
390
- children: state.error.stack
391
- }) : null]
392
- })] }),
393
- /* @__PURE__ */ jsx(Heading, {
394
- palette,
395
- title: "Data"
396
- }),
397
- /* @__PURE__ */ jsxs("div", {
398
- style: {
399
- ...section,
400
- fontFamily: monoFamily
401
- },
402
- children: [/* @__PURE__ */ jsx("button", {
403
- onClick: () => void navigator.clipboard?.writeText(copyText(state.data)),
404
- style: {
405
- background: "none",
406
- border: `1px solid ${palette.border}`,
407
- borderRadius: 4,
408
- color: palette.text,
409
- cursor: "pointer",
410
- float: "right",
411
- font: "inherit",
412
- fontFamily,
413
- padding: "2px 8px"
414
- },
415
- type: "button",
416
- children: "Copy"
417
- }), /* @__PURE__ */ jsx(Explorer, {
418
- depth: 0,
419
- palette,
420
- value: state.data
421
- })]
422
- }),
423
- /* @__PURE__ */ jsx(Heading, {
424
- palette,
425
- title: "Input"
426
- }),
427
- /* @__PURE__ */ jsx("div", {
428
- style: {
429
- ...section,
430
- fontFamily: monoFamily
431
- },
432
- children: /* @__PURE__ */ jsx(Explorer, {
433
- depth: 0,
434
- palette,
435
- value: query.handle.input
436
- })
437
- }),
438
- meta === void 0 ? null : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Heading, {
439
- palette,
440
- title: "Meta"
441
- }), /* @__PURE__ */ jsx("div", {
442
- style: {
443
- ...section,
444
- fontFamily: monoFamily
445
- },
446
- children: /* @__PURE__ */ jsx(Explorer, {
447
- depth: 0,
448
- palette,
449
- value: meta
450
- })
451
- })] })
452
- ]
453
- });
454
- }
455
- function QueryList(props) {
456
- const palette = props.palette;
457
- if (props.rows.length === 0) return /* @__PURE__ */ jsx("p", {
458
- style: {
459
- color: palette.muted,
460
- margin: 0,
461
- padding: 12
462
- },
463
- children: "No queries"
464
- });
465
- return /* @__PURE__ */ jsx("ul", {
466
- style: {
467
- listStyle: "none",
468
- margin: 0,
469
- padding: 0
470
- },
471
- children: props.rows.map((row) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs("button", {
472
- "aria-pressed": row.hash === props.selectedHash,
473
- "data-status": row.status,
474
- onClick: () => props.onSelect(row.hash),
475
- style: {
476
- alignItems: "center",
477
- background: row.hash === props.selectedHash ? palette.selected : "transparent",
478
- border: "none",
479
- borderBottom: `1px solid ${palette.border}`,
480
- color: palette.text,
481
- cursor: "pointer",
482
- display: "flex",
483
- font: "inherit",
484
- gap: 8,
485
- padding: "4px 8px",
486
- textAlign: "left",
487
- width: "100%"
488
- },
489
- title: row.status,
490
- type: "button",
491
- children: [/* @__PURE__ */ jsx("span", {
492
- "aria-label": `${row.observers} observers`,
493
- style: {
494
- background: statusColors[row.status],
495
- borderRadius: 4,
496
- color: "#ffffff",
497
- flexShrink: 0,
498
- fontWeight: 600,
499
- minWidth: 22,
500
- padding: "1px 4px",
501
- textAlign: "center"
502
- },
503
- children: row.observers
504
- }), /* @__PURE__ */ jsx("code", {
505
- style: {
506
- fontFamily: monoFamily,
507
- overflow: "hidden",
508
- textOverflow: "ellipsis",
509
- whiteSpace: "nowrap"
510
- },
511
- children: row.hash
512
- })]
513
- }) }, row.hash))
514
- });
515
- }
516
- function isSortBy(value) {
517
- return sortOrders.some((order) => order === value);
518
- }
519
- function Panel(props) {
520
- const client = useDevtoolsClient(props.client);
521
- const palette = usePalette(props.theme);
522
- const rows = useQueryRows(client);
523
- const [filter, setFilter] = useState("");
524
- const [sortBy, setSortBy] = useState("status");
525
- const [selectedHash, setSelectedHash] = useState(void 0);
526
- const counts = countByStatus(rows);
527
- const shown = visibleRows(rows, filter, sortBy);
528
- const selected = rows.find((row) => row.hash === selectedHash);
529
- const control = {
530
- background: palette.raised,
531
- border: `1px solid ${palette.border}`,
532
- borderRadius: 4,
533
- color: palette.text,
534
- font: "inherit",
535
- padding: "3px 6px"
536
- };
537
- const onClose = props.onClose;
538
- return /* @__PURE__ */ jsxs("div", {
539
- "data-raf-query-devtools": "",
540
- style: {
541
- background: palette.background,
542
- boxSizing: "border-box",
543
- color: palette.text,
544
- colorScheme: palette === palettes.dark ? "dark" : "light",
545
- display: "flex",
546
- flexDirection: "column",
547
- fontFamily,
548
- fontSize: 12,
549
- lineHeight: 1.4,
550
- minHeight: 0,
551
- overflow: "hidden",
552
- ...props.style
553
- },
554
- children: [/* @__PURE__ */ jsxs("header", {
555
- style: {
556
- alignItems: "center",
557
- borderBottom: `1px solid ${palette.border}`,
558
- display: "flex",
559
- flexWrap: "wrap",
560
- gap: 8,
561
- padding: 8
562
- },
563
- children: [
564
- /* @__PURE__ */ jsxs("strong", {
565
- style: { fontSize: 13 },
566
- children: ["raf-query ", /* @__PURE__ */ jsx("span", {
567
- style: { color: palette.accent },
568
- children: "devtools"
569
- })]
570
- }),
571
- /* @__PURE__ */ jsx("div", {
572
- style: {
573
- display: "flex",
574
- flexWrap: "wrap",
575
- gap: 4
576
- },
577
- children: statuses.map((status) => /* @__PURE__ */ jsx(StatusChip, {
578
- count: counts[status],
579
- palette,
580
- status
581
- }, status))
582
- }),
583
- /* @__PURE__ */ jsxs("div", {
584
- style: {
585
- display: "flex",
586
- gap: 6,
587
- marginLeft: "auto"
588
- },
589
- children: [
590
- /* @__PURE__ */ jsx("input", {
591
- "aria-label": "Filter queries",
592
- onChange: (event) => setFilter(event.target.value),
593
- placeholder: "Filter",
594
- style: control,
595
- type: "search",
596
- value: filter
597
- }),
598
- /* @__PURE__ */ jsx("select", {
599
- "aria-label": "Sort queries",
600
- onChange: (event) => {
601
- const value = event.target.value;
602
- if (isSortBy(value)) setSortBy(value);
603
- },
604
- style: control,
605
- value: sortBy,
606
- children: sortOrders.map((order) => /* @__PURE__ */ jsx("option", {
607
- value: order,
608
- children: sortLabels[order]
609
- }, order))
610
- }),
611
- /* @__PURE__ */ jsx("button", {
612
- onClick: () => void client.invalidate({}),
613
- style: {
614
- ...control,
615
- cursor: "pointer"
616
- },
617
- type: "button",
618
- children: "Invalidate all"
619
- }),
620
- /* @__PURE__ */ jsx("button", {
621
- onClick: () => client.clear(),
622
- style: {
623
- ...control,
624
- cursor: "pointer"
625
- },
626
- type: "button",
627
- children: "Clear cache"
628
- }),
629
- onClose ? /* @__PURE__ */ jsx("button", {
630
- "aria-label": "Close raf-query devtools",
631
- onClick: () => onClose(),
632
- style: {
633
- ...control,
634
- cursor: "pointer"
635
- },
636
- type: "button",
637
- children: "✕"
638
- }) : null
639
- ]
640
- })
641
- ]
642
- }), /* @__PURE__ */ jsxs("div", {
643
- style: {
644
- display: "flex",
645
- flex: 1,
646
- minHeight: 0
647
- },
648
- children: [/* @__PURE__ */ jsx("nav", {
649
- "aria-label": "Queries",
650
- style: {
651
- borderRight: `1px solid ${palette.border}`,
652
- flex: 1,
653
- minWidth: 0,
654
- overflow: "auto"
655
- },
656
- children: /* @__PURE__ */ jsx(QueryList, {
657
- onSelect: setSelectedHash,
658
- palette,
659
- rows: shown,
660
- selectedHash
661
- })
662
- }), selected ? /* @__PURE__ */ jsx(QueryDetails, {
663
- client,
664
- palette,
665
- row: selected
666
- }) : /* @__PURE__ */ jsx("p", {
667
- style: {
668
- color: palette.muted,
669
- flex: 1,
670
- margin: 0,
671
- padding: 12
672
- },
673
- children: "Select a query to inspect it"
674
- })]
675
- })]
676
- });
677
- }
678
- /**
679
- * The devtools panel on its own, to place anywhere in the page. Renders
680
- * nothing on the server, since the server's cache isn't the browser's.
681
- */
682
- function QueryDevtoolsPanel(props) {
683
- return useIsClient() ? /* @__PURE__ */ jsx(Panel, {
684
- client: props.client,
685
- onClose: props.onClose,
686
- style: props.style,
687
- theme: props.theme
688
- }) : null;
689
- }
690
- const corners = {
691
- "bottom-left": {
692
- bottom: 12,
693
- left: 12
694
- },
695
- "bottom-right": {
696
- bottom: 12,
697
- right: 12
698
- },
699
- "top-left": {
700
- left: 12,
701
- top: 12
702
- },
703
- "top-right": {
704
- right: 12,
705
- top: 12
706
- }
707
- };
708
- function clampSize(size, max) {
709
- return Math.min(Math.max(size, minSize), Math.max(max - 40, minSize));
710
- }
711
- function DockedDevtools(props) {
712
- const position = props.position ?? "bottom";
713
- const buttonPosition = props.buttonPosition ?? "bottom-right";
714
- const horizontal = position === "left" || position === "right";
715
- const [isOpen, setIsOpen] = useState(() => {
716
- const stored = readStored(storageKeys.open);
717
- return stored === null ? props.initialIsOpen ?? false : stored === "true";
718
- });
719
- const [size, setSize] = useState(() => Number(readStored(storageKeys.size)) || defaultSize);
720
- const palette = usePalette(props.theme);
721
- const setOpen = (open) => {
722
- setIsOpen(open);
723
- writeStored(storageKeys.open, String(open));
724
- };
725
- const startResize = (event) => {
726
- event.preventDefault();
727
- let latest = size;
728
- const onMove = (move) => {
729
- const next = {
730
- bottom: window.innerHeight - move.clientY,
731
- left: move.clientX,
732
- right: window.innerWidth - move.clientX,
733
- top: move.clientY
734
- }[position];
735
- latest = clampSize(next, horizontal ? window.innerWidth : window.innerHeight);
736
- setSize(latest);
737
- };
738
- const onUp = () => {
739
- window.removeEventListener("pointermove", onMove);
740
- window.removeEventListener("pointerup", onUp);
741
- writeStored(storageKeys.size, String(latest));
742
- };
743
- window.addEventListener("pointermove", onMove);
744
- window.addEventListener("pointerup", onUp);
745
- };
746
- if (!isOpen) return /* @__PURE__ */ jsxs("button", {
747
- "aria-label": "Open raf-query devtools",
748
- onClick: () => setOpen(true),
749
- style: {
750
- ...corners[buttonPosition],
751
- alignItems: "center",
752
- background: palette.background,
753
- border: `1px solid ${palette.border}`,
754
- borderRadius: 999,
755
- boxShadow: "0 2px 8px rgb(0 0 0 / 0.25)",
756
- color: palette.text,
757
- cursor: "pointer",
758
- display: "flex",
759
- fontFamily,
760
- fontSize: 12,
761
- fontWeight: 600,
762
- gap: 6,
763
- padding: "6px 12px",
764
- position: "fixed",
765
- zIndex: 99999
766
- },
767
- type: "button",
768
- children: [/* @__PURE__ */ jsx("span", {
769
- "aria-hidden": true,
770
- style: {
771
- background: brandGradient,
772
- borderRadius: 999,
773
- height: 8,
774
- width: 8
775
- }
776
- }), "raf-query"]
777
- });
778
- const edge = {
779
- bottom: {
780
- bottom: 0,
781
- height: size,
782
- left: 0,
783
- right: 0
784
- },
785
- left: {
786
- bottom: 0,
787
- left: 0,
788
- top: 0,
789
- width: size
790
- },
791
- right: {
792
- bottom: 0,
793
- right: 0,
794
- top: 0,
795
- width: size
796
- },
797
- top: {
798
- height: size,
799
- left: 0,
800
- right: 0,
801
- top: 0
802
- }
803
- }[position];
804
- const handleEdge = {
805
- bottom: {
806
- height: 10,
807
- left: 0,
808
- right: 0,
809
- top: -5
810
- },
811
- left: {
812
- bottom: 0,
813
- right: -5,
814
- top: 0,
815
- width: 10
816
- },
817
- right: {
818
- bottom: 0,
819
- left: -5,
820
- top: 0,
821
- width: 10
822
- },
823
- top: {
824
- bottom: -5,
825
- height: 10,
826
- left: 0,
827
- right: 0
828
- }
829
- }[position];
830
- return /* @__PURE__ */ jsxs("aside", {
831
- "aria-label": "raf-query devtools",
832
- style: {
833
- ...edge,
834
- borderColor: palette.border,
835
- borderStyle: "solid",
836
- borderWidth: {
837
- bottom: "1px 0 0",
838
- left: "0 1px 0 0",
839
- right: "0 0 0 1px",
840
- top: "0 0 1px"
841
- }[position],
842
- boxShadow: "0 0 16px rgb(0 0 0 / 0.3)",
843
- position: "fixed",
844
- zIndex: 99999
845
- },
846
- children: [/* @__PURE__ */ jsx("div", {
847
- "aria-label": "Resize raf-query devtools",
848
- "aria-orientation": horizontal ? "vertical" : "horizontal",
849
- onPointerDown: startResize,
850
- role: "separator",
851
- style: {
852
- ...handleEdge,
853
- alignItems: "center",
854
- cursor: horizontal ? "ew-resize" : "ns-resize",
855
- display: "flex",
856
- justifyContent: "center",
857
- position: "absolute",
858
- touchAction: "none",
859
- zIndex: 1
860
- },
861
- children: /* @__PURE__ */ jsx("span", {
862
- "aria-hidden": true,
863
- style: {
864
- background: palette.border,
865
- borderRadius: 999,
866
- height: horizontal ? 32 : 4,
867
- width: horizontal ? 4 : 32
868
- }
869
- })
870
- }), /* @__PURE__ */ jsx(QueryDevtoolsPanel, {
871
- client: props.client,
872
- onClose: () => setOpen(false),
873
- style: {
874
- height: "100%",
875
- width: "100%"
876
- },
877
- theme: props.theme
878
- })]
879
- });
880
- }
881
- /**
882
- * A toggle button that opens the devtools panel docked to an edge of the
883
- * viewport. Renders nothing on the server. Open state and size are kept in
884
- * `localStorage`.
885
- */
886
- function QueryDevtools(props) {
887
- return useIsClient() ? /* @__PURE__ */ jsx(DockedDevtools, {
888
- buttonPosition: props.buttonPosition,
889
- client: props.client,
890
- initialIsOpen: props.initialIsOpen,
891
- position: props.position,
892
- theme: props.theme
893
- }) : null;
894
- }
895
- //#endregion
896
- export { QueryDevtools, QueryDevtoolsPanel, preview };