vuerl 1.0.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/dist/index.cjs ADDED
@@ -0,0 +1,738 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var src_exports = {};
22
+ __export(src_exports, {
23
+ parseAsArrayOf: () => parseAsArrayOf,
24
+ parseAsBoolean: () => parseAsBoolean,
25
+ parseAsFloat: () => parseAsFloat,
26
+ parseAsHex: () => parseAsHex,
27
+ parseAsInteger: () => parseAsInteger,
28
+ parseAsIsoDate: () => parseAsIsoDate,
29
+ parseAsIsoDateTime: () => parseAsIsoDateTime,
30
+ parseAsJson: () => parseAsJson,
31
+ parseAsNativeArrayOf: () => parseAsNativeArrayOf,
32
+ parseAsNumberLiteral: () => parseAsNumberLiteral,
33
+ parseAsString: () => parseAsString,
34
+ parseAsStringEnum: () => parseAsStringEnum,
35
+ parseAsStringLiteral: () => parseAsStringLiteral,
36
+ useQueryState: () => useQueryState,
37
+ useQueryStates: () => useQueryStates,
38
+ withDefault: () => withDefault
39
+ });
40
+ module.exports = __toCommonJS(src_exports);
41
+
42
+ // src/useQueryState.ts
43
+ var import_vue = require("vue");
44
+ var import_vue_router = require("vue-router");
45
+
46
+ // src/internal/rate-limiter.ts
47
+ var cachedDelay = null;
48
+ function detectBrowserDelay() {
49
+ if (typeof window === "undefined") {
50
+ return 50;
51
+ }
52
+ const userAgent = navigator.userAgent.toLowerCase();
53
+ const isSafari = /safari/i.test(userAgent) && !/chrome/i.test(userAgent) && !/chromium/i.test(userAgent) && !/firefox/i.test(userAgent);
54
+ return isSafari ? 120 : 50;
55
+ }
56
+ function getSafeBrowserDelay() {
57
+ if (cachedDelay === null) {
58
+ cachedDelay = detectBrowserDelay();
59
+ }
60
+ return cachedDelay;
61
+ }
62
+
63
+ // src/internal/utils.ts
64
+ function normalizeQueryValue(value) {
65
+ if (value === void 0 || value === null) {
66
+ return null;
67
+ }
68
+ if (Array.isArray(value)) {
69
+ return value.filter((item) => typeof item === "string");
70
+ }
71
+ return typeof value === "string" ? value : null;
72
+ }
73
+ function buildQueryString(query) {
74
+ const params = new URLSearchParams();
75
+ for (const [key, value] of Object.entries(query)) {
76
+ if (typeof value === "string") {
77
+ params.append(key, value);
78
+ continue;
79
+ }
80
+ if (Array.isArray(value)) {
81
+ for (const entry of value) {
82
+ if (typeof entry === "string") {
83
+ params.append(key, entry);
84
+ }
85
+ }
86
+ }
87
+ }
88
+ return params.toString();
89
+ }
90
+ function cloneValue(value) {
91
+ if (Array.isArray(value)) {
92
+ return value.slice();
93
+ }
94
+ if (value instanceof Date) {
95
+ return new Date(value);
96
+ }
97
+ if (value && typeof value === "object") {
98
+ return { ...value };
99
+ }
100
+ return value;
101
+ }
102
+
103
+ // src/useQueryState.ts
104
+ function useQueryState(key, parser, options = {}) {
105
+ const route = (0, import_vue_router.useRoute)();
106
+ const router = (0, import_vue_router.useRouter)();
107
+ const parserOptions = parser.options ?? {};
108
+ const historyMode = options.history ?? parserOptions.history ?? "replace";
109
+ const clearOnDefault = options.clearOnDefault ?? parserOptions.clearOnDefault ?? true;
110
+ const shallowRouting = options.shallow ?? parserOptions.shallow ?? true;
111
+ const shouldScroll = options.scroll ?? parserOptions.scroll ?? false;
112
+ const browserSafeDelay = getSafeBrowserDelay();
113
+ const customDebounce = options.debounce ?? parserOptions.debounce ?? null;
114
+ const customThrottle = options.throttle ?? parserOptions.throttle ?? null;
115
+ const resolvedDebounce = customDebounce !== null ? Math.max(customDebounce, browserSafeDelay) : null;
116
+ const resolvedThrottle = resolvedDebounce === null && customThrottle !== null ? Math.max(customThrottle, browserSafeDelay) : null;
117
+ const fallbackDebounce = resolvedDebounce ?? browserSafeDelay;
118
+ const state = (0, import_vue.ref)(getStateFromQueryValue(route.query[key]));
119
+ let updateTimeout = null;
120
+ let isNavigating = false;
121
+ let lastThrottleTimestamp = 0;
122
+ function resolveDefaultValue() {
123
+ if (parser.default !== void 0) {
124
+ return cloneValue(parser.default);
125
+ }
126
+ return null;
127
+ }
128
+ function normalizeValue(value) {
129
+ if (value === void 0 || value === null) {
130
+ return resolveDefaultValue();
131
+ }
132
+ return value;
133
+ }
134
+ function getStateFromQueryValue(rawValue) {
135
+ const normalized = normalizeQueryValue(rawValue);
136
+ const parsed = parser.parse(normalized);
137
+ return normalizeValue(parsed ?? null);
138
+ }
139
+ function equalsDefault(value) {
140
+ if (parser.default === void 0) {
141
+ return value === null;
142
+ }
143
+ if (parser.eq) {
144
+ return parser.eq(value, parser.default);
145
+ }
146
+ return value === parser.default;
147
+ }
148
+ async function updateUrl() {
149
+ updateTimeout = null;
150
+ if (isNavigating) {
151
+ return;
152
+ }
153
+ const serialized = parser.serialize(state.value === null ? null : state.value);
154
+ const newQuery = {};
155
+ for (const [queryKey, queryValue] of Object.entries(route.query)) {
156
+ if (queryValue === null) {
157
+ continue;
158
+ }
159
+ newQuery[queryKey] = queryValue;
160
+ }
161
+ if (serialized === null || clearOnDefault && equalsDefault(state.value)) {
162
+ delete newQuery[key];
163
+ } else {
164
+ newQuery[key] = serialized;
165
+ }
166
+ const urlString = buildQueryString(newQuery);
167
+ if (urlString.length > 2e3) {
168
+ console.warn(
169
+ `URL length (${urlString.length}) exceeds recommended 2000 characters. Consider simplifying or moving state to session storage.`
170
+ );
171
+ }
172
+ const navigationTarget = shallowRouting ? { query: newQuery } : { path: route.path, hash: route.hash, query: newQuery };
173
+ await router[historyMode](navigationTarget);
174
+ if (shouldScroll && typeof window !== "undefined" && typeof window.scrollTo === "function") {
175
+ window.scrollTo({ top: 0, left: 0, behavior: "auto" });
176
+ }
177
+ }
178
+ function queueUrlUpdate() {
179
+ if (resolvedThrottle !== null) {
180
+ const now = Date.now();
181
+ const remaining = resolvedThrottle - (now - lastThrottleTimestamp);
182
+ if (remaining <= 0) {
183
+ if (updateTimeout) {
184
+ clearTimeout(updateTimeout);
185
+ updateTimeout = null;
186
+ }
187
+ lastThrottleTimestamp = now;
188
+ void updateUrl();
189
+ return;
190
+ }
191
+ if (updateTimeout) {
192
+ clearTimeout(updateTimeout);
193
+ }
194
+ updateTimeout = setTimeout(() => {
195
+ lastThrottleTimestamp = Date.now();
196
+ updateTimeout = null;
197
+ void updateUrl();
198
+ }, remaining);
199
+ return;
200
+ }
201
+ const delay = resolvedDebounce ?? fallbackDebounce;
202
+ if (updateTimeout) {
203
+ clearTimeout(updateTimeout);
204
+ }
205
+ updateTimeout = setTimeout(() => {
206
+ updateTimeout = null;
207
+ void updateUrl();
208
+ }, delay);
209
+ }
210
+ function setState(value) {
211
+ const computedValue = typeof value === "function" ? value(state.value) : value;
212
+ const newValue = normalizeValue(computedValue);
213
+ const hasChanged = parser.eq ? !parser.eq(newValue, state.value) : newValue !== state.value;
214
+ if (hasChanged) {
215
+ state.value = newValue;
216
+ queueUrlUpdate();
217
+ }
218
+ }
219
+ const urlWatcher = (0, import_vue.watch)(
220
+ () => route.query[key],
221
+ (newValue) => {
222
+ isNavigating = true;
223
+ if (updateTimeout) {
224
+ clearTimeout(updateTimeout);
225
+ updateTimeout = null;
226
+ }
227
+ state.value = getStateFromQueryValue(newValue);
228
+ setTimeout(() => {
229
+ isNavigating = false;
230
+ }, 0);
231
+ }
232
+ );
233
+ (0, import_vue.onBeforeUnmount)(() => {
234
+ urlWatcher();
235
+ if (updateTimeout) {
236
+ clearTimeout(updateTimeout);
237
+ }
238
+ });
239
+ return [state, setState];
240
+ }
241
+
242
+ // src/useQueryStates.ts
243
+ var import_vue2 = require("vue");
244
+ var import_vue_router2 = require("vue-router");
245
+ function useQueryStates(parsers, options = {}) {
246
+ const route = (0, import_vue_router2.useRoute)();
247
+ const router = (0, import_vue_router2.useRouter)();
248
+ const keys = Object.keys(parsers);
249
+ function findParserOption(option) {
250
+ for (const key of keys) {
251
+ const parserOption = parsers[key].options?.[option];
252
+ if (parserOption !== void 0) {
253
+ return parserOption;
254
+ }
255
+ }
256
+ return void 0;
257
+ }
258
+ const historyMode = options.history ?? findParserOption("history") ?? "replace";
259
+ const shallowRouting = options.shallow ?? findParserOption("shallow") ?? true;
260
+ const shouldScroll = options.scroll ?? findParserOption("scroll") ?? false;
261
+ const globalClearOnDefault = options.clearOnDefault ?? true;
262
+ const browserSafeDelay = getSafeBrowserDelay();
263
+ const parserDebounce = findParserOption("debounce");
264
+ const parserThrottle = findParserOption("throttle");
265
+ const customDebounce = options.debounce ?? (parserDebounce ?? null);
266
+ const customThrottle = options.throttle ?? (parserThrottle ?? null);
267
+ const resolvedDebounce = customDebounce !== null ? Math.max(customDebounce, browserSafeDelay) : null;
268
+ const resolvedThrottle = resolvedDebounce === null && customThrottle !== null ? Math.max(customThrottle, browserSafeDelay) : null;
269
+ const fallbackDebounce = resolvedDebounce ?? browserSafeDelay;
270
+ const state = (0, import_vue2.reactive)({});
271
+ for (const key of keys) {
272
+ state[key] = getStateFromQueryValue(key, route.query[key]);
273
+ }
274
+ let updateTimeout = null;
275
+ let batchMicrotaskId = null;
276
+ let isNavigating = false;
277
+ let lastThrottleTimestamp = 0;
278
+ function shouldClearKey(key) {
279
+ const parserOption = parsers[key].options?.clearOnDefault;
280
+ return parserOption ?? globalClearOnDefault;
281
+ }
282
+ function resolveDefaultValue(key) {
283
+ const parser = parsers[key];
284
+ if (parser.default !== void 0) {
285
+ return cloneValue(parser.default);
286
+ }
287
+ return null;
288
+ }
289
+ function normalizeValue(key, value) {
290
+ if (value === void 0 || value === null) {
291
+ return resolveDefaultValue(key);
292
+ }
293
+ return value;
294
+ }
295
+ function getStateFromQueryValue(key, rawValue) {
296
+ const normalized = normalizeQueryValue(rawValue);
297
+ const parser = parsers[key];
298
+ const parsed = parser.parse(normalized);
299
+ return normalizeValue(key, parsed ?? null);
300
+ }
301
+ function equalsDefault(key, value) {
302
+ const parser = parsers[key];
303
+ if (parser.default === void 0) {
304
+ return value === null;
305
+ }
306
+ if (parser.eq) {
307
+ return parser.eq(value, parser.default);
308
+ }
309
+ return value === parser.default;
310
+ }
311
+ async function updateUrl() {
312
+ updateTimeout = null;
313
+ if (isNavigating) {
314
+ return;
315
+ }
316
+ const newQuery = {};
317
+ for (const [queryKey, queryValue] of Object.entries(route.query)) {
318
+ if (queryValue === null) {
319
+ continue;
320
+ }
321
+ newQuery[queryKey] = queryValue;
322
+ }
323
+ for (const key of keys) {
324
+ const parser = parsers[key];
325
+ const serialized = parser.serialize(state[key] === null ? null : state[key]);
326
+ if (serialized === null || shouldClearKey(key) && equalsDefault(key, state[key])) {
327
+ delete newQuery[key];
328
+ } else {
329
+ newQuery[key] = serialized;
330
+ }
331
+ }
332
+ const urlString = buildQueryString(newQuery);
333
+ if (urlString.length > 2e3) {
334
+ console.warn(
335
+ `URL length (${urlString.length}) exceeds recommended 2000 characters. Consider simplifying or moving state to session storage.`
336
+ );
337
+ }
338
+ const navigationTarget = shallowRouting ? { query: newQuery } : { path: route.path, hash: route.hash, query: newQuery };
339
+ await router[historyMode](navigationTarget);
340
+ if (shouldScroll && typeof window !== "undefined" && typeof window.scrollTo === "function") {
341
+ window.scrollTo({ top: 0, left: 0, behavior: "auto" });
342
+ }
343
+ }
344
+ function queueUrlUpdate() {
345
+ if (resolvedThrottle !== null) {
346
+ const now = Date.now();
347
+ const remaining = resolvedThrottle - (now - lastThrottleTimestamp);
348
+ if (remaining <= 0) {
349
+ if (updateTimeout) {
350
+ clearTimeout(updateTimeout);
351
+ updateTimeout = null;
352
+ }
353
+ lastThrottleTimestamp = now;
354
+ void updateUrl();
355
+ return;
356
+ }
357
+ if (updateTimeout) {
358
+ clearTimeout(updateTimeout);
359
+ }
360
+ updateTimeout = setTimeout(() => {
361
+ lastThrottleTimestamp = Date.now();
362
+ updateTimeout = null;
363
+ void updateUrl();
364
+ }, remaining);
365
+ return;
366
+ }
367
+ const delay = resolvedDebounce ?? fallbackDebounce;
368
+ if (updateTimeout) {
369
+ clearTimeout(updateTimeout);
370
+ }
371
+ updateTimeout = setTimeout(() => {
372
+ updateTimeout = null;
373
+ void updateUrl();
374
+ }, delay);
375
+ }
376
+ function queueBatchUrlUpdate() {
377
+ if (batchMicrotaskId !== null) {
378
+ return;
379
+ }
380
+ batchMicrotaskId = queueMicrotask(() => {
381
+ batchMicrotaskId = null;
382
+ queueUrlUpdate();
383
+ });
384
+ }
385
+ function setState(values) {
386
+ let hasChanges = false;
387
+ if (values === null) {
388
+ for (const key of keys) {
389
+ const parser = parsers[key];
390
+ const newValue = resolveDefaultValue(key);
391
+ const hasChanged = parser.eq ? !parser.eq(newValue, state[key]) : newValue !== state[key];
392
+ if (hasChanged) {
393
+ state[key] = newValue;
394
+ hasChanges = true;
395
+ }
396
+ }
397
+ } else {
398
+ for (const key of Object.keys(values)) {
399
+ const providedValue = values[key];
400
+ if (providedValue === void 0) {
401
+ continue;
402
+ }
403
+ const parser = parsers[key];
404
+ const newValue = normalizeValue(key, providedValue);
405
+ const hasChanged = parser.eq ? !parser.eq(newValue, state[key]) : newValue !== state[key];
406
+ if (hasChanged) {
407
+ state[key] = newValue;
408
+ hasChanges = true;
409
+ }
410
+ }
411
+ }
412
+ if (hasChanges) {
413
+ queueBatchUrlUpdate();
414
+ }
415
+ }
416
+ const watchers = keys.map((key) => {
417
+ return (0, import_vue2.watch)(
418
+ () => route.query[key],
419
+ (newValue) => {
420
+ isNavigating = true;
421
+ if (updateTimeout) {
422
+ clearTimeout(updateTimeout);
423
+ updateTimeout = null;
424
+ }
425
+ state[key] = getStateFromQueryValue(key, newValue);
426
+ setTimeout(() => {
427
+ isNavigating = false;
428
+ }, 0);
429
+ }
430
+ );
431
+ });
432
+ (0, import_vue2.onBeforeUnmount)(() => {
433
+ watchers.forEach((unwatch) => unwatch());
434
+ if (updateTimeout) {
435
+ clearTimeout(updateTimeout);
436
+ }
437
+ });
438
+ return [state, setState];
439
+ }
440
+
441
+ // src/parsers.ts
442
+ function getSingleValue(value) {
443
+ if (value === null) {
444
+ return null;
445
+ }
446
+ if (Array.isArray(value)) {
447
+ return value[0] ?? null;
448
+ }
449
+ return value;
450
+ }
451
+ function getArrayValues(value) {
452
+ if (value === null) {
453
+ return [];
454
+ }
455
+ if (Array.isArray(value)) {
456
+ return value.filter((item) => typeof item === "string");
457
+ }
458
+ return value.length === 0 ? [] : [value];
459
+ }
460
+ function createBuildable(base) {
461
+ const buildable = {
462
+ ...base,
463
+ withDefault(defaultValue) {
464
+ return createBuildable({
465
+ ...base,
466
+ default: defaultValue
467
+ });
468
+ },
469
+ withOptions(options) {
470
+ return createBuildable({
471
+ ...base,
472
+ options: {
473
+ ...base.options ?? {},
474
+ ...options
475
+ }
476
+ });
477
+ }
478
+ };
479
+ return buildable;
480
+ }
481
+ var parseAsString = createBuildable({
482
+ parse: (value) => getSingleValue(value),
483
+ serialize: (value) => value ?? null
484
+ });
485
+ var parseAsInteger = createBuildable({
486
+ parse: (value) => {
487
+ const rawValue = getSingleValue(value);
488
+ if (!rawValue) return null;
489
+ const normalized = rawValue.trim();
490
+ if (!/^-?\d+$/.test(normalized)) {
491
+ return null;
492
+ }
493
+ const num = parseInt(normalized, 10);
494
+ return Number.isNaN(num) ? null : num;
495
+ },
496
+ serialize: (value) => {
497
+ if (value === null || value === void 0) return null;
498
+ return String(Math.floor(value));
499
+ }
500
+ });
501
+ var parseAsFloat = createBuildable({
502
+ parse: (value) => {
503
+ const rawValue = getSingleValue(value);
504
+ if (!rawValue) return null;
505
+ const normalized = rawValue.trim();
506
+ if (!/^[-+]?(?:\d+(?:\.\d*)?|\.\d+)$/.test(normalized)) {
507
+ return null;
508
+ }
509
+ const num = parseFloat(normalized);
510
+ return Number.isFinite(num) ? num : null;
511
+ },
512
+ serialize: (value) => {
513
+ if (value === null || value === void 0) return null;
514
+ return String(value);
515
+ }
516
+ });
517
+ var parseAsBoolean = createBuildable({
518
+ parse: (value) => {
519
+ const rawValue = getSingleValue(value);
520
+ if (!rawValue) return null;
521
+ const lower = rawValue.toLowerCase();
522
+ if (lower === "true") return true;
523
+ if (lower === "false") return false;
524
+ return null;
525
+ },
526
+ serialize: (value) => {
527
+ if (value === null || value === void 0) return null;
528
+ return String(value);
529
+ }
530
+ });
531
+ function parseAsStringLiteral(values) {
532
+ const valueSet = new Set(values);
533
+ return createBuildable({
534
+ parse: (value) => {
535
+ const rawValue = getSingleValue(value);
536
+ if (!rawValue) return null;
537
+ return valueSet.has(rawValue) ? rawValue : null;
538
+ },
539
+ serialize: (value) => {
540
+ if (value === null || value === void 0) return null;
541
+ return String(value);
542
+ }
543
+ });
544
+ }
545
+ function parseAsNumberLiteral(values) {
546
+ const valueSet = new Set(values);
547
+ return createBuildable({
548
+ parse: (value) => {
549
+ const rawValue = getSingleValue(value);
550
+ if (!rawValue) return null;
551
+ const num = parseInt(rawValue, 10);
552
+ return !isNaN(num) && valueSet.has(num) ? num : null;
553
+ },
554
+ serialize: (value) => {
555
+ if (value === null || value === void 0) return null;
556
+ return String(Math.floor(value));
557
+ }
558
+ });
559
+ }
560
+ function parseAsStringEnum(enumObject) {
561
+ const enumValues = new Set(
562
+ Object.values(enumObject).filter((entry) => typeof entry === "string")
563
+ );
564
+ return createBuildable({
565
+ parse: (value) => {
566
+ const rawValue = getSingleValue(value);
567
+ if (!rawValue) return null;
568
+ return enumValues.has(rawValue) ? rawValue : null;
569
+ },
570
+ serialize: (value) => {
571
+ if (value === null || value === void 0) return null;
572
+ return String(value);
573
+ }
574
+ });
575
+ }
576
+ function parseAsArrayOf(itemParser, separator = ",") {
577
+ return createBuildable({
578
+ parse: (value) => {
579
+ const rawValue = getSingleValue(value);
580
+ if (!rawValue) return [];
581
+ return rawValue.split(separator).map((item) => itemParser.parse(item.trim())).filter((item) => item !== null);
582
+ },
583
+ serialize: (value) => {
584
+ if (!value || value.length === 0) return null;
585
+ const serialized = value.map((item) => itemParser.serialize(item)).flatMap((result) => {
586
+ if (result === null) {
587
+ return [];
588
+ }
589
+ return Array.isArray(result) ? result : [result];
590
+ }).filter((s) => typeof s === "string");
591
+ return serialized.length > 0 ? serialized.join(separator) : null;
592
+ },
593
+ eq: (a, b) => {
594
+ if (!a && !b) return true;
595
+ if (!a || !b) return false;
596
+ if (a.length !== b.length) return false;
597
+ return a.every((v, i) => {
598
+ const itemEq = itemParser.eq;
599
+ return itemEq ? itemEq(v, b[i]) : v === b[i];
600
+ });
601
+ },
602
+ default: []
603
+ });
604
+ }
605
+ function parseAsNativeArrayOf(itemParser) {
606
+ return createBuildable({
607
+ parse: (value) => {
608
+ const inputs = getArrayValues(value);
609
+ if (inputs.length === 0) return [];
610
+ return inputs.map((entry) => itemParser.parse(entry)).filter((item) => item !== null);
611
+ },
612
+ serialize: (value) => {
613
+ if (!value || value.length === 0) return null;
614
+ const serialized = value.map((item) => itemParser.serialize(item)).flatMap((result) => {
615
+ if (result === null) {
616
+ return [];
617
+ }
618
+ return Array.isArray(result) ? result : [result];
619
+ }).filter((entry) => typeof entry === "string");
620
+ return serialized.length > 0 ? serialized : null;
621
+ },
622
+ eq: (a, b) => {
623
+ if (!a && !b) return true;
624
+ if (!a || !b) return false;
625
+ if (a.length !== b.length) return false;
626
+ return a.every((v, i) => {
627
+ const itemEq = itemParser.eq;
628
+ return itemEq ? itemEq(v, b[i]) : v === b[i];
629
+ });
630
+ },
631
+ default: []
632
+ });
633
+ }
634
+ var parseAsIsoDate = createBuildable({
635
+ parse: (value) => {
636
+ const rawValue = getSingleValue(value);
637
+ if (!rawValue) return null;
638
+ const dateMatch = /^(\d{4})-(\d{2})-(\d{2})$/.test(rawValue);
639
+ if (!dateMatch) return null;
640
+ const date = /* @__PURE__ */ new Date(rawValue + "T00:00:00Z");
641
+ return isNaN(date.getTime()) ? null : date;
642
+ },
643
+ serialize: (value) => {
644
+ if (!value) return null;
645
+ const iso = value.toISOString();
646
+ return iso.split("T")[0];
647
+ },
648
+ eq: (a, b) => {
649
+ if (!a && !b) return true;
650
+ if (!a || !b) return false;
651
+ return a.getTime() === b.getTime();
652
+ }
653
+ });
654
+ var parseAsIsoDateTime = createBuildable({
655
+ parse: (value) => {
656
+ const rawValue = getSingleValue(value);
657
+ if (!rawValue) return null;
658
+ const dateTimeMatch = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})$/.test(rawValue);
659
+ if (!dateTimeMatch) return null;
660
+ const date = new Date(rawValue);
661
+ return isNaN(date.getTime()) ? null : date;
662
+ },
663
+ serialize: (value) => {
664
+ if (!value) return null;
665
+ return value.toISOString();
666
+ },
667
+ eq: (a, b) => {
668
+ if (!a && !b) return true;
669
+ if (!a || !b) return false;
670
+ return a.getTime() === b.getTime();
671
+ }
672
+ });
673
+ function parseAsJson(schema) {
674
+ return createBuildable({
675
+ parse: (value) => {
676
+ const rawValue = getSingleValue(value);
677
+ if (!rawValue) return null;
678
+ try {
679
+ const parsed = JSON.parse(rawValue);
680
+ if (schema) {
681
+ const result = schema.safeParse ? schema.safeParse(parsed) : schema.parse?.(parsed);
682
+ if (result && !result.success) return null;
683
+ return result?.data ?? parsed;
684
+ }
685
+ return parsed;
686
+ } catch {
687
+ return null;
688
+ }
689
+ },
690
+ serialize: (value) => {
691
+ if (value === null || value === void 0) return null;
692
+ try {
693
+ return JSON.stringify(value);
694
+ } catch {
695
+ return null;
696
+ }
697
+ }
698
+ });
699
+ }
700
+ var parseAsHex = createBuildable({
701
+ parse: (value) => {
702
+ const rawValue = getSingleValue(value);
703
+ if (!rawValue) return null;
704
+ const hex = rawValue.startsWith("#") ? rawValue.slice(1) : rawValue;
705
+ if (!/^[0-9a-fA-F]{6}$/.test(hex)) return null;
706
+ return hex.toLowerCase();
707
+ },
708
+ serialize: (value) => {
709
+ if (!value) return null;
710
+ return value;
711
+ }
712
+ });
713
+ function withDefault(parser, defaultValue) {
714
+ return createBuildable({
715
+ ...parser,
716
+ default: defaultValue
717
+ });
718
+ }
719
+ // Annotate the CommonJS export names for ESM import in node:
720
+ 0 && (module.exports = {
721
+ parseAsArrayOf,
722
+ parseAsBoolean,
723
+ parseAsFloat,
724
+ parseAsHex,
725
+ parseAsInteger,
726
+ parseAsIsoDate,
727
+ parseAsIsoDateTime,
728
+ parseAsJson,
729
+ parseAsNativeArrayOf,
730
+ parseAsNumberLiteral,
731
+ parseAsString,
732
+ parseAsStringEnum,
733
+ parseAsStringLiteral,
734
+ useQueryState,
735
+ useQueryStates,
736
+ withDefault
737
+ });
738
+ //# sourceMappingURL=index.cjs.map