@plumile/router 0.1.14 → 0.1.17
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 +43 -422
- package/lib/esm/builder.d.ts +5 -5
- package/lib/esm/builder.d.ts.map +1 -1
- package/lib/esm/builder.js +1 -1
- package/lib/esm/index.d.ts +0 -4
- package/lib/esm/index.d.ts.map +1 -1
- package/lib/esm/index.js +1 -5
- package/lib/esm/routing/Link.d.ts +3 -3
- package/lib/esm/routing/Link.d.ts.map +1 -1
- package/lib/esm/routing/Link.js +3 -8
- package/lib/esm/routing/RouteComponentWrapper.d.ts +6 -5
- package/lib/esm/routing/RouteComponentWrapper.d.ts.map +1 -1
- package/lib/esm/routing/RouteComponentWrapper.js +1 -1
- package/lib/esm/routing/RouterRenderer.d.ts.map +1 -1
- package/lib/esm/routing/RouterRenderer.js +1 -1
- package/lib/esm/routing/createRouter.d.ts +0 -1
- package/lib/esm/routing/createRouter.d.ts.map +1 -1
- package/lib/esm/routing/createRouter.js +435 -447
- package/lib/esm/routing/index.d.ts +2 -6
- package/lib/esm/routing/index.d.ts.map +1 -1
- package/lib/esm/routing/index.js +3 -7
- package/lib/esm/routing/useAllQuery.d.ts +7 -0
- package/lib/esm/routing/useAllQuery.d.ts.map +1 -0
- package/lib/esm/routing/useAllQuery.js +31 -0
- package/lib/esm/routing/useFilterDiagnostics.d.ts +2 -0
- package/lib/esm/routing/useFilterDiagnostics.d.ts.map +1 -0
- package/lib/esm/routing/useFilterDiagnostics.js +11 -0
- package/lib/esm/routing/useFilters.d.ts +16 -0
- package/lib/esm/routing/useFilters.d.ts.map +1 -0
- package/lib/esm/routing/useFilters.js +83 -0
- package/lib/esm/routing/useNavigate.d.ts +2 -9
- package/lib/esm/routing/useNavigate.d.ts.map +1 -1
- package/lib/esm/routing/useNavigate.js +1 -1
- package/lib/esm/routing/useQueryState.d.ts +1 -1
- package/lib/esm/routing/useQueryState.d.ts.map +1 -1
- package/lib/esm/routing/useQueryState.js +2 -2
- package/lib/esm/routing/useTypedQuery.js +1 -1
- package/lib/esm/tools/buildCombinedSearch.d.ts +11 -0
- package/lib/esm/tools/buildCombinedSearch.d.ts.map +1 -0
- package/lib/esm/tools/buildCombinedSearch.js +28 -0
- package/lib/esm/tools/buildSearch.d.ts +2 -8
- package/lib/esm/tools/buildSearch.d.ts.map +1 -1
- package/lib/esm/tools/buildSearch.js +12 -216
- package/lib/esm/tools.d.ts +1 -1
- package/lib/esm/tools.d.ts.map +1 -1
- package/lib/esm/tools.js +1 -1
- package/lib/esm/types.d.ts +25 -37
- package/lib/esm/types.d.ts.map +1 -1
- package/lib/esm/types.js +1 -1
- package/lib/tsconfig.esm.tsbuildinfo +1 -1
- package/lib/types/builder.d.ts +5 -5
- package/lib/types/builder.d.ts.map +1 -1
- package/lib/types/index.d.ts +0 -4
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/routing/Link.d.ts +3 -3
- package/lib/types/routing/Link.d.ts.map +1 -1
- package/lib/types/routing/RouteComponentWrapper.d.ts +6 -5
- package/lib/types/routing/RouteComponentWrapper.d.ts.map +1 -1
- package/lib/types/routing/RouterRenderer.d.ts.map +1 -1
- package/lib/types/routing/createRouter.d.ts +0 -1
- package/lib/types/routing/createRouter.d.ts.map +1 -1
- package/lib/types/routing/index.d.ts +2 -6
- package/lib/types/routing/index.d.ts.map +1 -1
- package/lib/types/routing/useAllQuery.d.ts +7 -0
- package/lib/types/routing/useAllQuery.d.ts.map +1 -0
- package/lib/types/routing/useFilterDiagnostics.d.ts +2 -0
- package/lib/types/routing/useFilterDiagnostics.d.ts.map +1 -0
- package/lib/types/routing/useFilters.d.ts +16 -0
- package/lib/types/routing/useFilters.d.ts.map +1 -0
- package/lib/types/routing/useNavigate.d.ts +2 -9
- package/lib/types/routing/useNavigate.d.ts.map +1 -1
- package/lib/types/routing/useQueryState.d.ts +1 -1
- package/lib/types/routing/useQueryState.d.ts.map +1 -1
- package/lib/types/tools/buildCombinedSearch.d.ts +11 -0
- package/lib/types/tools/buildCombinedSearch.d.ts.map +1 -0
- package/lib/types/tools/buildSearch.d.ts +2 -8
- package/lib/types/tools/buildSearch.d.ts.map +1 -1
- package/lib/types/tools.d.ts +1 -1
- package/lib/types/tools.d.ts.map +1 -1
- package/lib/types/types.d.ts +25 -37
- package/lib/types/types.d.ts.map +1 -1
- package/package.json +6 -5
- package/lib/esm/routing/devtools.d.ts +0 -21
- package/lib/esm/routing/devtools.d.ts.map +0 -1
- package/lib/esm/routing/devtools.js +0 -690
- package/lib/esm/routing/filters.d.ts +0 -97
- package/lib/esm/routing/filters.d.ts.map +0 -1
- package/lib/esm/routing/filters.js +0 -557
- package/lib/esm/routing/useActiveFilters.d.ts +0 -9
- package/lib/esm/routing/useActiveFilters.d.ts.map +0 -1
- package/lib/esm/routing/useActiveFilters.js +0 -38
- package/lib/esm/routing/useFilterState.d.ts +0 -10
- package/lib/esm/routing/useFilterState.d.ts.map +0 -1
- package/lib/esm/routing/useFilterState.js +0 -14
- package/lib/esm/routing/useNavigateWithQuery.d.ts +0 -15
- package/lib/esm/routing/useNavigateWithQuery.d.ts.map +0 -1
- package/lib/esm/routing/useNavigateWithQuery.js +0 -95
- package/lib/esm/routing/useQueryObject.d.ts +0 -18
- package/lib/esm/routing/useQueryObject.d.ts.map +0 -1
- package/lib/esm/routing/useQueryObject.js +0 -107
- package/lib/esm/routing/useStableRefEquality.d.ts +0 -5
- package/lib/esm/routing/useStableRefEquality.d.ts.map +0 -1
- package/lib/esm/routing/useStableRefEquality.js +0 -47
- package/lib/types/routing/devtools.d.ts +0 -21
- package/lib/types/routing/devtools.d.ts.map +0 -1
- package/lib/types/routing/filters.d.ts +0 -97
- package/lib/types/routing/filters.d.ts.map +0 -1
- package/lib/types/routing/useActiveFilters.d.ts +0 -9
- package/lib/types/routing/useActiveFilters.d.ts.map +0 -1
- package/lib/types/routing/useFilterState.d.ts +0 -10
- package/lib/types/routing/useFilterState.d.ts.map +0 -1
- package/lib/types/routing/useNavigateWithQuery.d.ts +0 -15
- package/lib/types/routing/useNavigateWithQuery.d.ts.map +0 -1
- package/lib/types/routing/useQueryObject.d.ts +0 -18
- package/lib/types/routing/useQueryObject.d.ts.map +0 -1
- package/lib/types/routing/useStableRefEquality.d.ts +0 -5
- package/lib/types/routing/useStableRefEquality.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -37,9 +37,6 @@ import { Route, getResourcePage } from '@plumile/router';
|
|
|
37
37
|
const routes: Route<any, any>[] = [
|
|
38
38
|
{
|
|
39
39
|
path: '/',
|
|
40
|
-
|
|
41
|
-
## Advanced Hooks Deep Dive & Combined Examples
|
|
42
|
-
|
|
43
40
|
resourcePage: getResourcePage('Home', () => import('./pages/Home')),
|
|
44
41
|
},
|
|
45
42
|
{
|
|
@@ -147,9 +144,6 @@ Navigation component that handles client-side routing.
|
|
|
147
144
|
|
|
148
145
|
- `to`: string - Destination path
|
|
149
146
|
- `exact?`: boolean - Exact path matching for active state
|
|
150
|
-
|
|
151
|
-
### Combined Example: Products Listing Page
|
|
152
|
-
|
|
153
147
|
- `activeClassName?`: string - CSS class when link is active
|
|
154
148
|
- `className?`: string - Base CSS class
|
|
155
149
|
- `preload?`: boolean - Preload route on hover
|
|
@@ -482,118 +476,64 @@ Extending: if you need more (e.g. trigger navigations) you can wrap `createRoute
|
|
|
482
476
|
|
|
483
477
|
Production: the symbol is not defined; accessing it will yield `undefined`. Never ship logic depending on it; keep usage inside `if (process.env.NODE_ENV !== 'production')` blocks or guarded optional checks.
|
|
484
478
|
|
|
485
|
-
###
|
|
486
|
-
|
|
487
|
-
To encourage consistent usage of the query hooks, a custom rule is provided inside the router package to flag raw `window.location.search` access.
|
|
488
|
-
|
|
489
|
-
Add to your flat ESLint config:
|
|
490
|
-
|
|
491
|
-
````js
|
|
492
|
-
import noDirectWindowLocationSearch from '@plumile/router/lib/eslint-rules/no-direct-window-location-search.js';
|
|
493
|
-
|
|
494
|
-
export default [
|
|
495
|
-
{
|
|
479
|
+
### Filter Schema & useFilters (Integration with @plumile/filter-query)
|
|
496
480
|
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
The router supports two batching modes:
|
|
500
|
-
|
|
501
|
-
- Manual batching: pass `batch: true` in successive `navigate` calls within the same microtask.
|
|
502
|
-
- Auto batching: enable `createRouter(routes, { autoBatch: true })` and omit `immediate: true` to coalesce navigations scheduled in the same microtask.
|
|
503
|
-
|
|
504
|
-
During a batched sequence, the final history update (a single `push`/`set`) is deferred to a queued microtask. Some code (tests, imperative flows) may need to synchronously observe the merged query state before the flush occurs. To support this, the router performs a provisional in‑memory update of the current route entry on each batched `navigate`:
|
|
505
|
-
|
|
506
|
-
Guarantees (provisional phase):
|
|
507
|
-
|
|
508
|
-
1. `context.get()` returns an entry whose `location.search`, `rawSearch`, `query` (raw parsed) and `typedQuery` reflect the merged state of all batched calls so far.
|
|
509
|
-
2. Each additional batched call merges query keys (last write wins) and overwrites the entire filters object (they are considered atomic state) before recomputing `typedQuery`.
|
|
510
|
-
3. The provisional `typedQuery` uses the deepest route schema of the eventual target pathname (if a batched navigation changes pathname, subsequent calls resolve the schema for that new path).
|
|
511
|
-
4. Normalization (e.g. clamping `page < 1`) is only applied at the final flush listener step; the provisional `typedQuery` may briefly contain unnormalized values until flush.
|
|
512
|
-
5. Subscribers (`context.subscribe`) are **not** notified until the actual history update fires (asynchronously). Reading inside the same tick requires using `context.get()` directly, not relying on subscription callbacks.
|
|
513
|
-
|
|
514
|
-
Non‑guarantees / caveats:
|
|
515
|
-
|
|
516
|
-
- If you read `window.location.search` directly (discouraged) during a batch it will still show the pre‑batch URL; use the entry returned by `context.get()`.
|
|
517
|
-
- If later batched calls change the pathname, earlier provisional `typedQuery` objects become stale; always re‑read after your final batched mutation if you need the merged result.
|
|
518
|
-
- Filters batching (from `useFilters` helpers) coalesces multiple `set/patch/clear` calls in the same microtask via an internal microtask queue. These feed into the outer navigation batching so a burst of filter helper calls plus other `navigate` calls still produce a single history entry.
|
|
519
|
-
|
|
520
|
-
Edge cases:
|
|
521
|
-
|
|
522
|
-
- Calling `navigate({ immediate: true })` inside an active batch forces an immediate flush, bypassing batching for that specific call.
|
|
523
|
-
- Interleaving manual `batch: true` and autoBatch calls: if autoBatch is enabled and you explicitly pass `batch: false`, that call flushes immediately; otherwise the presence of any manual `batch: true` call within the tick keeps coalescing active until flush.
|
|
524
|
-
|
|
525
|
-
Recommended usage pattern inside effects or event handlers:
|
|
481
|
+
The router can parse and serialize structured filter expressions using the `@plumile/filter-query` package. Define a `filterSchema` on the deepest route (same precedence rule as `query`). Each filter key is encoded as `field.operator=value`.
|
|
526
482
|
|
|
527
483
|
```ts
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
context.navigate({ filters: { status: { in: ['active'] } }, filterSchema, batch: true });
|
|
531
|
-
context.navigate({ query: { tag: 'green' }, batch: true });
|
|
532
|
-
// Synchronous inspection (provisional)
|
|
533
|
-
const merged = context.get().typedQuery; // already includes page=1, tag=green, status filter
|
|
534
|
-
````
|
|
535
|
-
|
|
536
|
-
Testing note: tests asserting final URL should poll or await a microtask / tick rather than expecting synchronous `window.location.search` updates when batching is involved.
|
|
537
|
-
|
|
538
|
-
Future evolution: if normalization or additional query transformations grow more complex, the provisional recompute will remain a best‑effort mirror; code relying on _final_ normalized values should subscribe or await the flush boundary.
|
|
539
|
-
|
|
540
|
-
Summary: Provisional batching gives synchronous, allocation‑minimal read access to the in‑flight merged query & typedQuery without sacrificing a single history entry – use `context.get()` for immediate reads, and rely on subscriptions or hooks for React render updates.
|
|
484
|
+
import { r, q, useFilters } from '@plumile/router';
|
|
485
|
+
import { defineSchema, numberField, stringField } from '@plumile/filter-query';
|
|
541
486
|
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
Example:
|
|
547
|
-
|
|
548
|
-
```ts
|
|
549
|
-
import { r, defineFilters, numberFilter, stringFilter } from '@plumile/router';
|
|
487
|
+
const filterSchema = defineSchema({
|
|
488
|
+
price: numberField(), // operators: gt,gte,lt,lte,eq,neq,between,in,nin
|
|
489
|
+
name: stringField(), // operators: contains,sw,ew,eq,neq,in,nin
|
|
490
|
+
});
|
|
550
491
|
|
|
551
|
-
|
|
492
|
+
const routes = [
|
|
552
493
|
r({
|
|
553
|
-
path: '/
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
children: [
|
|
558
|
-
r({
|
|
559
|
-
path: '/:id',
|
|
560
|
-
filterSchema: defineFilters({
|
|
561
|
-
name: stringFilter({ operators: ['contains'] }),
|
|
562
|
-
}),
|
|
563
|
-
}),
|
|
564
|
-
],
|
|
494
|
+
path: '/items',
|
|
495
|
+
query: { page: q.default(q.number(), 1) },
|
|
496
|
+
filterSchema,
|
|
497
|
+
render: () => null,
|
|
565
498
|
}),
|
|
566
499
|
];
|
|
500
|
+
|
|
501
|
+
// Inside a component rendered under /items
|
|
502
|
+
const [filters, actions] = useFilters();
|
|
503
|
+
actions.set('price', 'gt', 10); // ?page=1&price.gt=10
|
|
504
|
+
actions.set('price', 'eq', 15); // ?page=1&price.gt=10&price.eq=15
|
|
505
|
+
actions.remove('price', 'gt'); // remove only that operator
|
|
506
|
+
actions.clear(); // remove all filter segments
|
|
567
507
|
```
|
|
568
508
|
|
|
569
|
-
|
|
509
|
+
`navigate({ filters })` is also available for programmatic changes alongside query updates. Serialization keeps query parameters first, then filter segments, both deterministically ordered.
|
|
570
510
|
|
|
571
|
-
|
|
511
|
+
Diagnostics (unknown field/operator, invalid values, etc.) are accessible via `useFilterDiagnostics()` for debugging tooling or UI feedback.
|
|
572
512
|
|
|
573
|
-
|
|
574
|
-
- No deep merge inside a field definition.
|
|
575
|
-
- Omitted routes: ignored.
|
|
513
|
+
### ESLint Rule: no-direct-window-location-search
|
|
576
514
|
|
|
577
|
-
|
|
515
|
+
To encourage consistent usage of the query hooks, a custom rule is provided inside the router package to flag raw `window.location.search` access.
|
|
578
516
|
|
|
579
|
-
|
|
580
|
-
- Empty filters object with route-level schema is treated as “no change” (no extra keys added).
|
|
517
|
+
Add to your flat ESLint config:
|
|
581
518
|
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
'@plumile-router/dx': {
|
|
585
|
-
rules: {
|
|
586
|
-
'no-direct-window-location-search': noDirectWindowLocationSearch,
|
|
587
|
-
},
|
|
588
|
-
},
|
|
589
|
-
},
|
|
590
|
-
rules: {
|
|
591
|
-
'@plumile-router/dx/no-direct-window-location-search': 'warn',
|
|
592
|
-
},
|
|
593
|
-
},
|
|
594
|
-
];
|
|
519
|
+
```js
|
|
520
|
+
import noDirectWindowLocationSearch from '@plumile/router/lib/eslint-rules/no-direct-window-location-search.js';
|
|
595
521
|
|
|
596
|
-
|
|
522
|
+
export default [
|
|
523
|
+
{
|
|
524
|
+
plugins: {
|
|
525
|
+
'@plumile-router/dx': {
|
|
526
|
+
rules: {
|
|
527
|
+
'no-direct-window-location-search': noDirectWindowLocationSearch,
|
|
528
|
+
},
|
|
529
|
+
},
|
|
530
|
+
},
|
|
531
|
+
rules: {
|
|
532
|
+
'@plumile-router/dx/no-direct-window-location-search': 'warn',
|
|
533
|
+
},
|
|
534
|
+
},
|
|
535
|
+
];
|
|
536
|
+
```
|
|
597
537
|
|
|
598
538
|
Optional configuration:
|
|
599
539
|
|
|
@@ -605,7 +545,7 @@ rules: {
|
|
|
605
545
|
{ allowInFiles: ['legacy-entry.ts'] },
|
|
606
546
|
],
|
|
607
547
|
},
|
|
608
|
-
|
|
548
|
+
```
|
|
609
549
|
|
|
610
550
|
When triggered, replace patterns like:
|
|
611
551
|
|
|
@@ -663,242 +603,6 @@ Behavior:
|
|
|
663
603
|
Options:
|
|
664
604
|
`{ defaultValue?, omitIfDefault?: boolean = true, replace?: boolean, raw?: boolean }`
|
|
665
605
|
|
|
666
|
-
### Filters DSL (Experimental Advanced Filtering)
|
|
667
|
-
|
|
668
|
-
Structured multi‑operator filtering can be expressed via query keys using the pattern `field.operator`.
|
|
669
|
-
|
|
670
|
-
1. Define a schema
|
|
671
|
-
|
|
672
|
-
```ts
|
|
673
|
-
import { defineFilters, numberFilter, stringFilter } from '@plumile/router';
|
|
674
|
-
|
|
675
|
-
export const filters = defineFilters({
|
|
676
|
-
price: numberFilter(), // numeric: eq, neq, gt, gte, lt, lte, in, nin, between, exists
|
|
677
|
-
status: stringFilter({ operators: ['eq', 'in', 'nin'] }),
|
|
678
|
-
name: stringFilter({ operators: ['contains', 'starts', 'ends'] }),
|
|
679
|
-
// Provide default operator values to omit them from serialization when matched
|
|
680
|
-
availability: numberFilter({
|
|
681
|
-
operators: ['exists'],
|
|
682
|
-
defaults: { exists: true },
|
|
683
|
-
}),
|
|
684
|
-
priceRange: numberFilter({
|
|
685
|
-
operators: ['between'],
|
|
686
|
-
defaults: { between: [[0, 100]] },
|
|
687
|
-
}),
|
|
688
|
-
});
|
|
689
|
-
```
|
|
690
|
-
|
|
691
|
-
2. Read & update filters
|
|
692
|
-
|
|
693
|
-
```tsx
|
|
694
|
-
import { useFilters } from '@plumile/router';
|
|
695
|
-
|
|
696
|
-
function Products() {
|
|
697
|
-
const [f, { patch, clear }] = useFilters(filters);
|
|
698
|
-
// f.price.gt => number[] | undefined
|
|
699
|
-
// f.status.in => string[] | undefined
|
|
700
|
-
return (
|
|
701
|
-
<button
|
|
702
|
-
onClick={() => {
|
|
703
|
-
patch({ price: { gt: [10] } });
|
|
704
|
-
}}
|
|
705
|
-
>
|
|
706
|
-
Price > 10
|
|
707
|
-
</button>
|
|
708
|
-
);
|
|
709
|
-
}
|
|
710
|
-
```
|
|
711
|
-
|
|
712
|
-
3. Narrow to a single operator
|
|
713
|
-
|
|
714
|
-
```tsx
|
|
715
|
-
import { useFilterState } from '@plumile/router';
|
|
716
|
-
|
|
717
|
-
function PriceGt() {
|
|
718
|
-
const [gt, setGt] = useFilterState(filters, 'price', 'gt');
|
|
719
|
-
return (
|
|
720
|
-
<input
|
|
721
|
-
value={gt?.[0] ?? ''}
|
|
722
|
-
onChange={(e) => setGt([Number(e.target.value)])}
|
|
723
|
-
/>
|
|
724
|
-
);
|
|
725
|
-
}
|
|
726
|
-
```
|
|
727
|
-
|
|
728
|
-
4. Supported operators
|
|
729
|
-
|
|
730
|
-
| Kind | Operators |
|
|
731
|
-
| ------ | ------------------------------------------------------------------------------------ |
|
|
732
|
-
| number | eq, neq, gt, gte, lt, lte, in, nin, between (tuples), exists |
|
|
733
|
-
| string | eq, neq, in, nin, between (tuples of strings), exists, contains, starts, ends, regex |
|
|
734
|
-
|
|
735
|
-
`exists` expects a boolean; presence of key defaults to `true` if value unrecognized.
|
|
736
|
-
|
|
737
|
-
5. Query string format
|
|
738
|
-
|
|
739
|
-
```
|
|
740
|
-
?price.gt=10&price.between=10&price.between=20&price.between=30&price.between=40&status.in=active&status.in=pending
|
|
741
|
-
```
|
|
742
|
-
|
|
743
|
-
6. Between operator
|
|
744
|
-
|
|
745
|
-
Pairs of values create ranges: four values → two ranges. Odd final value is ignored.
|
|
746
|
-
|
|
747
|
-
7. Clearing
|
|
748
|
-
|
|
749
|
-
`clear()` → remove all filters. `clear(['price'])` → remove only price.\* keys.
|
|
750
|
-
|
|
751
|
-
8. Patching
|
|
752
|
-
|
|
753
|
-
`patch({ price: { gt: [20], between: [[10,20]] } })` merges at field level, replacing individual operator arrays.
|
|
754
|
-
|
|
755
|
-
9. Serialization rules
|
|
756
|
-
|
|
757
|
-
- Previous filter keys (`field.op`) are dropped before adding new ones.
|
|
758
|
-
- Multiple values produce repeated keys (same as existing query arrays).
|
|
759
|
-
- Boolean `exists` serialized as `1` / `0`.
|
|
760
|
-
- Optional omission of default operator values: if a filter definition supplies a `defaults` object
|
|
761
|
-
(e.g. `{ defaults: { gt: [10] } }` or `{ defaults: { exists: true } }`), and the current operator
|
|
762
|
-
value is shallow‑equal to that default, the `field.operator` key is skipped during serialization.
|
|
763
|
-
Applies to array operators (exact ordered match) and `exists` boolean. `between` defaults compare
|
|
764
|
-
tuple pairs (`[[a,b]]`) element-wise.
|
|
765
|
-
|
|
766
|
-
10. Type inference
|
|
767
|
-
|
|
768
|
-
`InferFilters<typeof filters.schema>` gives `{ price: { gt?: number[]; between?: [number, number][]; ... } }`.
|
|
769
|
-
|
|
770
|
-
11. Opt‑in / Backward Compatible
|
|
771
|
-
|
|
772
|
-
No change to existing query parameter behavior. Filter keys are just additional query entries; legacy code reading raw `useQuery()` continues to function.
|
|
773
|
-
|
|
774
|
-
12. Limitations / Future
|
|
775
|
-
|
|
776
|
-
- Sorting deliberately excluded (would be separate DSL).
|
|
777
|
-
- No date operator specialization yet.
|
|
778
|
-
- Regex values are passed through verbatim (URL decoding handled upstream).
|
|
779
|
-
- Default omission currently uses shallow equality (ordered array match). For number arrays
|
|
780
|
-
canonicalization (sorting + optional dedupe) happens prior to comparison, ensuring stable omission.
|
|
781
|
-
|
|
782
|
-
Tests cover parsing (including multiple ranges) and building; extend as needed for your domain.
|
|
783
|
-
|
|
784
|
-
### New Hooks (Phase 4)
|
|
785
|
-
|
|
786
|
-
#### `useQueryObject(opts?)`
|
|
787
|
-
|
|
788
|
-
High-level accessor returning the entire current query object (typed when the matched deepest route declares a `query` schema). It also returns a stable setter that merges partial updates.
|
|
789
|
-
|
|
790
|
-
```tsx
|
|
791
|
-
import { useQueryObject } from '@plumile/router';
|
|
792
|
-
|
|
793
|
-
function Panel() {
|
|
794
|
-
const [query, setQuery] = useQueryObject({ omitDefaults: true });
|
|
795
|
-
// query: typed (if schema) else raw record
|
|
796
|
-
return (
|
|
797
|
-
<button
|
|
798
|
-
onClick={() => {
|
|
799
|
-
setQuery({ page: (query.page ?? 1) + 1 });
|
|
800
|
-
}}
|
|
801
|
-
>
|
|
802
|
-
Next page
|
|
803
|
-
</button>
|
|
804
|
-
);
|
|
805
|
-
}
|
|
806
|
-
```
|
|
807
|
-
|
|
808
|
-
Options:
|
|
809
|
-
|
|
810
|
-
- `raw?: boolean` Use aggregated raw query even if a schema exists.
|
|
811
|
-
- `replace?: boolean` Default navigation mode for all subsequent `setQuery` calls.
|
|
812
|
-
- `omitDefaults?: boolean` When true, schema keys whose value equals their declared default are omitted from the URL.
|
|
813
|
-
|
|
814
|
-
Setter semantics:
|
|
815
|
-
|
|
816
|
-
- Accepts an object or function `(prev) => next`.
|
|
817
|
-
- Keys set to `undefined` are removed from the URL.
|
|
818
|
-
- Partial objects are shallow‑merged with previous query state (post-merge omission rules are applied if `omitDefaults` is enabled).
|
|
819
|
-
|
|
820
|
-
#### `useActiveFilters(filterSchema)`
|
|
821
|
-
|
|
822
|
-
Returns a flat array of currently active filter operator entries derived from the structured filters state returned by `useFilters`.
|
|
823
|
-
|
|
824
|
-
```tsx
|
|
825
|
-
import { useActiveFilters } from '@plumile/router';
|
|
826
|
-
import { filters } from './filters-schema';
|
|
827
|
-
|
|
828
|
-
function ActiveChips() {
|
|
829
|
-
const active = useActiveFilters(filters);
|
|
830
|
-
return (
|
|
831
|
-
<ul>
|
|
832
|
-
{active.map((f) => (
|
|
833
|
-
<li key={f.field + f.operator}>
|
|
834
|
-
{f.field}.{f.operator}: {f.values.join(', ')}
|
|
835
|
-
</li>
|
|
836
|
-
))}
|
|
837
|
-
</ul>
|
|
838
|
-
);
|
|
839
|
-
}
|
|
840
|
-
```
|
|
841
|
-
|
|
842
|
-
Each entry: `{ field: string; operator: string; values: any[] }` where `values` is the already normalized array (for non‑array primitives a singleton array is produced). Empty arrays / undefined operators are skipped.
|
|
843
|
-
|
|
844
|
-
#### `useNavigateWithQuery(opts?)`
|
|
845
|
-
|
|
846
|
-
Convenience wrapper combining current query (typed if possible) with partial updates before invoking `navigate`.
|
|
847
|
-
|
|
848
|
-
```tsx
|
|
849
|
-
import { useNavigateWithQuery } from '@plumile/router';
|
|
850
|
-
|
|
851
|
-
function Incrementer() {
|
|
852
|
-
const update = useNavigateWithQuery({ omitDefaults: true });
|
|
853
|
-
return (
|
|
854
|
-
<button
|
|
855
|
-
onClick={() => {
|
|
856
|
-
update((prev) => ({ page: (prev.page ?? 1) + 1 }));
|
|
857
|
-
}}
|
|
858
|
-
>
|
|
859
|
-
Next
|
|
860
|
-
</button>
|
|
861
|
-
);
|
|
862
|
-
}
|
|
863
|
-
```
|
|
864
|
-
|
|
865
|
-
Behavior:
|
|
866
|
-
|
|
867
|
-
- Reads existing (typed or raw) query as base.
|
|
868
|
-
- Accepts object or functional update.
|
|
869
|
-
- Keys set to `undefined` are removed.
|
|
870
|
-
- `omitDefaults` removes schema-default valued keys.
|
|
871
|
-
- `raw` forces ignoring the schema (raw aggregation base).
|
|
872
|
-
- `replace` option (global or per call) controls history mode.
|
|
873
|
-
|
|
874
|
-
#### `useStableRefEquality(value, areEqual?)`
|
|
875
|
-
|
|
876
|
-
Utility hook that preserves the reference of the latest value (object or array) as long as shallow equality holds. When a new value is passed whose own enumerable keys (and their primitive or reference-equal values) match the previous one, the previous stable reference is returned. If they differ, the new value becomes the stored reference.
|
|
877
|
-
|
|
878
|
-
Designed for niche interop cases (e.g. passing derived objects to dependency arrays of third-party hooks) where you can't or don't want the upstream producer to handle memoization. Most consumers of the router do NOT need this because `useQuery`, `useTypedQuery`, `useFilters` already return stable references.
|
|
879
|
-
|
|
880
|
-
```ts
|
|
881
|
-
import { useStableRefEquality } from '@plumile/router';
|
|
882
|
-
|
|
883
|
-
function Chart({ data }) {
|
|
884
|
-
// Avoid re-renders in a heavy child when parent recreates equivalent arrays
|
|
885
|
-
const stableData = useStableRefEquality(data);
|
|
886
|
-
return <ExpensiveChart data={stableData} />;
|
|
887
|
-
}
|
|
888
|
-
```
|
|
889
|
-
|
|
890
|
-
Custom comparator:
|
|
891
|
-
|
|
892
|
-
```ts
|
|
893
|
-
const value = useStableRefEquality(complex, (a, b) => deepCustomCompare(a, b));
|
|
894
|
-
```
|
|
895
|
-
|
|
896
|
-
Notes:
|
|
897
|
-
|
|
898
|
-
- Only shallow by default (no deep traversal) for perf.
|
|
899
|
-
- Non-object/array inputs are returned as-is (no caching layer needed).
|
|
900
|
-
- Avoid overuse; prefer structuring code so sources themselves are stable.
|
|
901
|
-
|
|
902
606
|
### Data Preloading
|
|
903
607
|
|
|
904
608
|
```typescript
|
|
@@ -946,89 +650,6 @@ function MyComponent() {
|
|
|
946
650
|
}
|
|
947
651
|
```
|
|
948
652
|
|
|
949
|
-
### Navigation With Filters & Batching (Phase 5)
|
|
950
|
-
|
|
951
|
-
You can atomically update query parameters and structured filters via the extended `navigate` API and related hooks.
|
|
952
|
-
|
|
953
|
-
```tsx
|
|
954
|
-
import {
|
|
955
|
-
useNavigate,
|
|
956
|
-
useFilters,
|
|
957
|
-
defineFilters,
|
|
958
|
-
numberFilter,
|
|
959
|
-
} from '@plumile/router';
|
|
960
|
-
|
|
961
|
-
const filterSchema = defineFilters({ price: numberFilter() });
|
|
962
|
-
|
|
963
|
-
function PriceBump() {
|
|
964
|
-
const navigate = useNavigate();
|
|
965
|
-
const [filters, { patch }] = useFilters(filterSchema);
|
|
966
|
-
return (
|
|
967
|
-
<button
|
|
968
|
-
onClick={() => {
|
|
969
|
-
// Update both query & filters in a single URL change
|
|
970
|
-
navigate({
|
|
971
|
-
query: { page: 1 },
|
|
972
|
-
filters: { price: { gt: [10] } },
|
|
973
|
-
filterSchema,
|
|
974
|
-
});
|
|
975
|
-
}}
|
|
976
|
-
>
|
|
977
|
-
Apply
|
|
978
|
-
</button>
|
|
979
|
-
);
|
|
980
|
-
}
|
|
981
|
-
```
|
|
982
|
-
|
|
983
|
-
Batch multiple navigations issued during the same micro‑task into _one_ history update by passing `batch: true`:
|
|
984
|
-
|
|
985
|
-
```tsx
|
|
986
|
-
function ComplexMutation() {
|
|
987
|
-
const navigate = useNavigate();
|
|
988
|
-
return (
|
|
989
|
-
<button
|
|
990
|
-
onClick={() => {
|
|
991
|
-
navigate({ query: { page: 1 }, batch: true });
|
|
992
|
-
navigate({
|
|
993
|
-
filters: { price: { gt: [20] } },
|
|
994
|
-
filterSchema,
|
|
995
|
-
batch: true,
|
|
996
|
-
});
|
|
997
|
-
navigate({
|
|
998
|
-
filters: { price: {} /* clear price */ },
|
|
999
|
-
filterSchema,
|
|
1000
|
-
batch: true,
|
|
1001
|
-
});
|
|
1002
|
-
// All three coalesce into one push
|
|
1003
|
-
}}
|
|
1004
|
-
>
|
|
1005
|
-
Run sequence
|
|
1006
|
-
</button>
|
|
1007
|
-
);
|
|
1008
|
-
}
|
|
1009
|
-
```
|
|
1010
|
-
|
|
1011
|
-
Hooks `useQueryObject` and `useFilters` also accept a `batch` flag in their nav options:
|
|
1012
|
-
|
|
1013
|
-
```tsx
|
|
1014
|
-
const [query, setQuery] = useQueryObject();
|
|
1015
|
-
const [f, { patch, clear }] = useFilters(filterSchema);
|
|
1016
|
-
|
|
1017
|
-
// Coalesce three operations
|
|
1018
|
-
setQuery({ page: 2 }, { batch: true });
|
|
1019
|
-
patch({ price: { gt: [30] } }, { batch: true });
|
|
1020
|
-
clear(['price'], { batch: true });
|
|
1021
|
-
```
|
|
1022
|
-
|
|
1023
|
-
Notes:
|
|
1024
|
-
|
|
1025
|
-
- Batching is opt‑in: default behavior is immediate navigation (backward compatible).
|
|
1026
|
-
- The last non‑undefined `replace` flag wins inside a batch group.
|
|
1027
|
-
- The last provided `query` object and `filters` snapshot in the batch are used for serialization.
|
|
1028
|
-
- Provide `filterSchema` whenever you include `filters`.
|
|
1029
|
-
|
|
1030
|
-
`buildSearch(query, schema, { filters, filterSchema })` merges filters deterministically with query keys (schema‑ordered keys first, then extras).
|
|
1031
|
-
|
|
1032
653
|
### Route Preloading
|
|
1033
654
|
|
|
1034
655
|
```tsx
|
package/lib/esm/builder.d.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { type MatchFunction, type ParamData } from 'path-to-regexp';
|
|
2
|
-
import type { FlatRouteInput, Redirect, Route } from './types.js';
|
|
2
|
+
import type { FlatRouteInput, Redirect, Route, PrepareResult } from './types.js';
|
|
3
3
|
export declare class FlatRoute<TParams extends ParamData> {
|
|
4
4
|
path: string;
|
|
5
|
-
routes: Route<
|
|
5
|
+
routes: Route<PrepareResult>[];
|
|
6
6
|
matchFunction: MatchFunction<TParams>;
|
|
7
7
|
redirectTo?: string;
|
|
8
8
|
constructor(input: FlatRouteInput<TParams>);
|
|
9
9
|
}
|
|
10
|
-
export declare function isRedirect(route: Route<
|
|
11
|
-
export declare function buildRoute(routeConfig: (Route<
|
|
12
|
-
export declare function buildRoutes(routeConfig: Route<
|
|
10
|
+
export declare function isRedirect(route: Route<PrepareResult> | Redirect): route is Redirect;
|
|
11
|
+
export declare function buildRoute(routeConfig: (Route<PrepareResult> | Redirect)[], parentRoutes?: Route<PrepareResult>[], prefix?: string): FlatRoute<ParamData>[];
|
|
12
|
+
export declare function buildRoutes(routeConfig: Route<PrepareResult>[]): FlatRoute<ParamData>[];
|
|
13
13
|
//# sourceMappingURL=builder.d.ts.map
|
package/lib/esm/builder.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../src/builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3E,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../src/builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3E,OAAO,KAAK,EACV,cAAc,EACd,QAAQ,EACR,KAAK,EACL,aAAa,EACd,MAAM,YAAY,CAAC;AAQpB,qBAAa,SAAS,CAAC,OAAO,SAAS,SAAS;IAEvC,IAAI,EAAE,MAAM,CAAC;IAGb,MAAM,EAAE,KAAK,CAAC,aAAa,CAAC,EAAE,CAAC;IAG/B,aAAa,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;IAGtC,UAAU,CAAC,EAAE,MAAM,CAAC;gBAOR,KAAK,EAAE,cAAc,CAAC,OAAO,CAAC;CAOlD;AAQD,wBAAgB,UAAU,CACxB,KAAK,EAAE,KAAK,CAAC,aAAa,CAAC,GAAG,QAAQ,GACrC,KAAK,IAAI,QAAQ,CAGnB;AAYD,wBAAgB,UAAU,CACxB,WAAW,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,GAAG,QAAQ,CAAC,EAAE,EAChD,YAAY,GAAE,KAAK,CAAC,aAAa,CAAC,EAAO,EACzC,MAAM,SAAK,GACV,SAAS,CAAC,SAAS,CAAC,EAAE,CA8DxB;AASD,wBAAgB,WAAW,CACzB,WAAW,EAAE,KAAK,CAAC,aAAa,CAAC,EAAE,GAClC,SAAS,CAAC,SAAS,CAAC,EAAE,CAExB"}
|
package/lib/esm/builder.js
CHANGED
|
@@ -68,4 +68,4 @@ export function buildRoute(routeConfig, parentRoutes = [], prefix = '') {
|
|
|
68
68
|
export function buildRoutes(routeConfig) {
|
|
69
69
|
return buildRoute(routeConfig);
|
|
70
70
|
}
|
|
71
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
71
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVpbGRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9idWlsZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxLQUFLLEVBQXNDLE1BQU0sZ0JBQWdCLENBQUM7QUFlM0UsTUFBTSxPQUFPLFNBQVM7SUFFYixJQUFJLENBQVM7SUFHYixNQUFNLENBQXlCO0lBRy9CLGFBQWEsQ0FBeUI7SUFHdEMsVUFBVSxDQUFVO0lBTzNCLFlBQW1CLEtBQThCO1FBQy9DLE1BQU0sRUFBRSxhQUFhLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsR0FBRyxLQUFLLENBQUM7UUFDMUQsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7UUFDakIsSUFBSSxDQUFDLFVBQVUsR0FBRyxVQUFVLENBQUM7UUFDN0IsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7UUFDckIsSUFBSSxDQUFDLGFBQWEsR0FBRyxhQUFhLENBQUM7SUFDckMsQ0FBQztDQUNGO0FBUUQsTUFBTSxVQUFVLFVBQVUsQ0FDeEIsS0FBc0M7SUFHdEMsT0FBUSxLQUFrQixDQUFDLEVBQUUsSUFBSSxJQUFJLENBQUM7QUFDeEMsQ0FBQztBQVlELE1BQU0sVUFBVSxVQUFVLENBQ3hCLFdBQWdELEVBQ2hELGVBQXVDLEVBQUUsRUFDekMsTUFBTSxHQUFHLEVBQUU7SUFFWCxNQUFNLFVBQVUsR0FBMkIsRUFBRSxDQUFDO0lBRTlDLEtBQUssTUFBTSxLQUFLLElBQUksV0FBVyxFQUFFLENBQUM7UUFDaEMsTUFBTSxLQUFLLEdBQUcsRUFBRSxDQUFDO1FBQ2pCLElBQUksTUFBTSxLQUFLLEVBQUUsRUFBRSxDQUFDO1lBQ2xCLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDckIsQ0FBQztRQUNELElBQUksS0FBSyxDQUFDLElBQUksSUFBSSxJQUFJLElBQUksS0FBSyxDQUFDLElBQUksS0FBSyxFQUFFLElBQUksS0FBSyxDQUFDLElBQUksS0FBSyxHQUFHLEVBQUUsQ0FBQztZQUNsRSxJQUFJLFVBQVUsR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDO1lBQzVCLElBQUksVUFBVSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO2dCQUMvQixVQUFVLEdBQUcsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNuQyxDQUFDO1lBQ0QsS0FBSyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUN6QixDQUFDO1FBRUQsTUFBTSxPQUFPLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUVoQyxNQUFNLEVBQUUsUUFBUSxFQUFFLEdBQUcsS0FBNkIsQ0FBQztRQUVuRCxJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxJQUFJLFFBQVEsSUFBSSxJQUFJLEVBQUUsQ0FBQztZQUMzQyxNQUFNLE1BQU0sR0FBRyxVQUFVLENBQUMsUUFBUSxFQUFFLENBQUMsR0FBRyxZQUFZLEVBQUUsS0FBSyxDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUM7WUFDdkUsVUFBVSxDQUFDLElBQUksQ0FBQyxHQUFHLE1BQU0sQ0FBQyxDQUFDO1lBRTNCLFNBQVM7UUFDWCxDQUFDO1FBRUQsTUFBTSxhQUFhLEdBQUcsS0FBSyxDQUFDLElBQUksT0FBTyxFQUFFLEVBQUU7WUFDekMsUUFBUSxFQUFFLEtBQUs7U0FDaEIsQ0FBQyxDQUFDO1FBRUgsSUFBSSxJQUFJLEdBQUcsT0FBTyxDQUFDO1FBQ25CLElBQUksQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDN0IsSUFBSSxHQUFHLElBQUksT0FBTyxFQUFFLENBQUM7UUFDdkIsQ0FBQztRQUVELElBQUksVUFBVSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDdEIsSUFBSSxVQUFVLEdBQUcsS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUUxQixJQUFJLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO2dCQUNoQyxVQUFVLEdBQUcsR0FBRyxJQUFJLElBQUksVUFBVSxFQUFFLENBQUM7WUFDdkMsQ0FBQztZQUNELFVBQVUsQ0FBQyxJQUFJLENBQ2IsSUFBSSxTQUFTLENBQUM7Z0JBQ1osSUFBSTtnQkFDSixVQUFVO2dCQUNWLGFBQWE7Z0JBQ2IsTUFBTSxFQUFFLENBQUMsR0FBRyxZQUFZLENBQUM7YUFDMUIsQ0FBQyxDQUNILENBQUM7UUFDSixDQUFDO2FBQU0sQ0FBQztZQUNOLFVBQVUsQ0FBQyxJQUFJLENBQ2IsSUFBSSxTQUFTLENBQUM7Z0JBQ1osSUFBSTtnQkFDSixhQUFhO2dCQUNiLE1BQU0sRUFBRSxDQUFDLEdBQUcsWUFBWSxFQUFFLEtBQUssQ0FBQzthQUNqQyxDQUFDLENBQ0gsQ0FBQztRQUNKLENBQUM7SUFDSCxDQUFDO0lBRUQsT0FBTyxVQUFVLENBQUM7QUFDcEIsQ0FBQztBQVNELE1BQU0sVUFBVSxXQUFXLENBQ3pCLFdBQW1DO0lBRW5DLE9BQU8sVUFBVSxDQUFDLFdBQVcsQ0FBQyxDQUFDO0FBQ2pDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBtYXRjaCwgdHlwZSBNYXRjaEZ1bmN0aW9uLCB0eXBlIFBhcmFtRGF0YSB9IGZyb20gJ3BhdGgtdG8tcmVnZXhwJztcblxuaW1wb3J0IHR5cGUge1xuICBGbGF0Um91dGVJbnB1dCxcbiAgUmVkaXJlY3QsXG4gIFJvdXRlLFxuICBQcmVwYXJlUmVzdWx0LFxufSBmcm9tICcuL3R5cGVzLmpzJztcblxuLyoqXG4gKiBSZXByZXNlbnRzIGEgZmxhdHRlbmVkIHJvdXRlIHdpdGggYSBjb21waWxlZCBtYXRjaCBmdW5jdGlvbi5cbiAqIFRoaXMgaXMgYW4gaW50ZXJuYWwgcmVwcmVzZW50YXRpb24gdXNlZCBieSB0aGUgcm91dGVyIHRvIGVmZmljaWVudGx5IG1hdGNoIFVSTHMuXG4gKlxuICogQHRlbXBsYXRlIFRQYXJhbXMgLSBSb3V0ZSBwYXJhbWV0ZXIgdHlwZXMgZXh0cmFjdGVkIGZyb20gdGhlIFVSTCBwYXRoXG4gKi9cbmV4cG9ydCBjbGFzcyBGbGF0Um91dGU8VFBhcmFtcyBleHRlbmRzIFBhcmFtRGF0YT4ge1xuICAvKiogVGhlIFVSTCBwYXRoIHBhdHRlcm4gZm9yIHRoaXMgcm91dGUgKi9cbiAgcHVibGljIHBhdGg6IHN0cmluZztcblxuICAvKiogTmVzdGVkIHJvdXRlcyB0aGF0IHNob3VsZCBiZSByZW5kZXJlZCB3aXRoaW4gdGhpcyByb3V0ZSAqL1xuICBwdWJsaWMgcm91dGVzOiBSb3V0ZTxQcmVwYXJlUmVzdWx0PltdO1xuXG4gIC8qKiBDb21waWxlZCBmdW5jdGlvbiB0byBtYXRjaCBVUkwgcGF0aHMgYWdhaW5zdCB0aGlzIHJvdXRlIHBhdHRlcm4gKi9cbiAgcHVibGljIG1hdGNoRnVuY3Rpb246IE1hdGNoRnVuY3Rpb248VFBhcmFtcz47XG5cbiAgLyoqIE9wdGlvbmFsIHJlZGlyZWN0IGRlc3RpbmF0aW9uIGlmIHRoaXMgcm91dGUgc2hvdWxkIHJlZGlyZWN0ICovXG4gIHB1YmxpYyByZWRpcmVjdFRvPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgbmV3IEZsYXRSb3V0ZSBpbnN0YW5jZS5cbiAgICpcbiAgICogQHBhcmFtIGlucHV0IC0gQ29uZmlndXJhdGlvbiBmb3IgdGhlIGZsYXQgcm91dGVcbiAgICovXG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihpbnB1dDogRmxhdFJvdXRlSW5wdXQ8VFBhcmFtcz4pIHtcbiAgICBjb25zdCB7IG1hdGNoRnVuY3Rpb24sIHBhdGgsIHJlZGlyZWN0VG8sIHJvdXRlcyB9ID0gaW5wdXQ7XG4gICAgdGhpcy5wYXRoID0gcGF0aDtcbiAgICB0aGlzLnJlZGlyZWN0VG8gPSByZWRpcmVjdFRvO1xuICAgIHRoaXMucm91dGVzID0gcm91dGVzO1xuICAgIHRoaXMubWF0Y2hGdW5jdGlvbiA9IG1hdGNoRnVuY3Rpb247XG4gIH1cbn1cblxuLyoqXG4gKiBUeXBlIGd1YXJkIHRvIGNoZWNrIGlmIGEgcm91dGUgY29uZmlndXJhdGlvbiBpcyBhIHJlZGlyZWN0LlxuICpcbiAqIEBwYXJhbSByb3V0ZSAtIFJvdXRlIG9yIHJlZGlyZWN0IGNvbmZpZ3VyYXRpb24gdG8gY2hlY2tcbiAqIEByZXR1cm5zIFRydWUgaWYgdGhlIHJvdXRlIGlzIGEgcmVkaXJlY3QgY29uZmlndXJhdGlvblxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNSZWRpcmVjdChcbiAgcm91dGU6IFJvdXRlPFByZXBhcmVSZXN1bHQ+IHwgUmVkaXJlY3QsXG4pOiByb3V0ZSBpcyBSZWRpcmVjdCB7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW5uZWNlc3NhcnktY29uZGl0aW9uXG4gIHJldHVybiAocm91dGUgYXMgUmVkaXJlY3QpLnRvICE9IG51bGw7XG59XG5cbi8qKlxuICogUmVjdXJzaXZlbHkgYnVpbGRzIGEgZmxhdCBsaXN0IG9mIHJvdXRlcyBmcm9tIGEgbmVzdGVkIHJvdXRlIGNvbmZpZ3VyYXRpb24uXG4gKiBUaGlzIGZ1bmN0aW9uIHByb2Nlc3NlcyB0aGUgcm91dGUgdHJlZSBhbmQgY3JlYXRlcyBGbGF0Um91dGUgaW5zdGFuY2VzIHdpdGhcbiAqIGNvbXBpbGVkIHBhdGggbWF0Y2hlcnMgZm9yIGVmZmljaWVudCBVUkwgbWF0Y2hpbmcuXG4gKlxuICogQHBhcmFtIHJvdXRlQ29uZmlnIC0gQXJyYXkgb2Ygcm91dGUgb3IgcmVkaXJlY3QgY29uZmlndXJhdGlvbnNcbiAqIEBwYXJhbSBwYXJlbnRSb3V0ZXMgLSBQYXJlbnQgcm91dGVzIGluIHRoZSBjdXJyZW50IHBhdGggKGZvciBuZXN0ZWQgcm91dGVzKVxuICogQHBhcmFtIHByZWZpeCAtIFVSTCBwcmVmaXggZnJvbSBwYXJlbnQgcm91dGVzXG4gKiBAcmV0dXJucyBBcnJheSBvZiBmbGF0dGVuZWQgcm91dGVzIHJlYWR5IGZvciBtYXRjaGluZ1xuICovXG5leHBvcnQgZnVuY3Rpb24gYnVpbGRSb3V0ZShcbiAgcm91dGVDb25maWc6IChSb3V0ZTxQcmVwYXJlUmVzdWx0PiB8IFJlZGlyZWN0KVtdLFxuICBwYXJlbnRSb3V0ZXM6IFJvdXRlPFByZXBhcmVSZXN1bHQ+W10gPSBbXSxcbiAgcHJlZml4ID0gJycsXG4pOiBGbGF0Um91dGU8UGFyYW1EYXRhPltdIHtcbiAgY29uc3QgZmxhdFJvdXRlczogRmxhdFJvdXRlPFBhcmFtRGF0YT5bXSA9IFtdO1xuXG4gIGZvciAoY29uc3Qgcm91dGUgb2Ygcm91dGVDb25maWcpIHtcbiAgICBjb25zdCBwYXJ0cyA9IFtdO1xuICAgIGlmIChwcmVmaXggIT09ICcnKSB7XG4gICAgICBwYXJ0cy5wdXNoKHByZWZpeCk7XG4gICAgfVxuICAgIGlmIChyb3V0ZS5wYXRoICE9IG51bGwgJiYgcm91dGUucGF0aCAhPT0gJycgJiYgcm91dGUucGF0aCAhPT0gJy8nKSB7XG4gICAgICBsZXQgbm9ybWFsaXplZCA9IHJvdXRlLnBhdGg7XG4gICAgICBpZiAobm9ybWFsaXplZC5zdGFydHNXaXRoKCcvJykpIHtcbiAgICAgICAgbm9ybWFsaXplZCA9IG5vcm1hbGl6ZWQuc2xpY2UoMSk7XG4gICAgICB9XG4gICAgICBwYXJ0cy5wdXNoKG5vcm1hbGl6ZWQpO1xuICAgIH1cblxuICAgIGNvbnN0IG5ld1BhdGggPSBwYXJ0cy5qb2luKCcvJyk7XG5cbiAgICBjb25zdCB7IGNoaWxkcmVuIH0gPSByb3V0ZSBhcyBSb3V0ZTxQcmVwYXJlUmVzdWx0PjtcblxuICAgIGlmICghaXNSZWRpcmVjdChyb3V0ZSkgJiYgY2hpbGRyZW4gIT0gbnVsbCkge1xuICAgICAgY29uc3Qgcm91dGVzID0gYnVpbGRSb3V0ZShjaGlsZHJlbiwgWy4uLnBhcmVudFJvdXRlcywgcm91dGVdLCBuZXdQYXRoKTtcbiAgICAgIGZsYXRSb3V0ZXMucHVzaCguLi5yb3V0ZXMpO1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnRpbnVlXG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICBjb25zdCBtYXRjaEZ1bmN0aW9uID0gbWF0Y2goYC8ke25ld1BhdGh9YCwge1xuICAgICAgdHJhaWxpbmc6IGZhbHNlLFxuICAgIH0pO1xuXG4gICAgbGV0IHBhdGggPSBuZXdQYXRoO1xuICAgIGlmICghbmV3UGF0aC5zdGFydHNXaXRoKCcvJykpIHtcbiAgICAgIHBhdGggPSBgLyR7bmV3UGF0aH1gO1xuICAgIH1cblxuICAgIGlmIChpc1JlZGlyZWN0KHJvdXRlKSkge1xuICAgICAgbGV0IHJlZGlyZWN0VG8gPSByb3V0ZS50bztcblxuICAgICAgaWYgKCFyZWRpcmVjdFRvLnN0YXJ0c1dpdGgoJy8nKSkge1xuICAgICAgICByZWRpcmVjdFRvID0gYCR7cGF0aH0vJHtyZWRpcmVjdFRvfWA7XG4gICAgICB9XG4gICAgICBmbGF0Um91dGVzLnB1c2goXG4gICAgICAgIG5ldyBGbGF0Um91dGUoe1xuICAgICAgICAgIHBhdGgsXG4gICAgICAgICAgcmVkaXJlY3RUbyxcbiAgICAgICAgICBtYXRjaEZ1bmN0aW9uLFxuICAgICAgICAgIHJvdXRlczogWy4uLnBhcmVudFJvdXRlc10sXG4gICAgICAgIH0pLFxuICAgICAgKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZmxhdFJvdXRlcy5wdXNoKFxuICAgICAgICBuZXcgRmxhdFJvdXRlKHtcbiAgICAgICAgICBwYXRoLFxuICAgICAgICAgIG1hdGNoRnVuY3Rpb24sXG4gICAgICAgICAgcm91dGVzOiBbLi4ucGFyZW50Um91dGVzLCByb3V0ZV0sXG4gICAgICAgIH0pLFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmxhdFJvdXRlcztcbn1cblxuLyoqXG4gKiBCdWlsZHMgYSBmbGF0IHJvdXRlIGxpc3QgZnJvbSB0aGUgZ2l2ZW4gcm91dGUgY29uZmlndXJhdGlvbi5cbiAqIFRoaXMgaXMgdGhlIG1haW4gZW50cnkgcG9pbnQgZm9yIHJvdXRlIGJ1aWxkaW5nLlxuICpcbiAqIEBwYXJhbSByb3V0ZUNvbmZpZyAtIEFycmF5IG9mIHJvdXRlIGNvbmZpZ3VyYXRpb25zIHRvIGZsYXR0ZW5cbiAqIEByZXR1cm5zIEFycmF5IG9mIGZsYXR0ZW5lZCByb3V0ZXMgcmVhZHkgZm9yIG1hdGNoaW5nXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBidWlsZFJvdXRlcyhcbiAgcm91dGVDb25maWc6IFJvdXRlPFByZXBhcmVSZXN1bHQ+W10sXG4pOiBGbGF0Um91dGU8UGFyYW1EYXRhPltdIHtcbiAgcmV0dXJuIGJ1aWxkUm91dGUocm91dGVDb25maWcpO1xufVxuIl19
|
package/lib/esm/index.d.ts
CHANGED
|
@@ -5,9 +5,5 @@ export * from './builder.js';
|
|
|
5
5
|
export * from './ResourcePage.js';
|
|
6
6
|
export * from './tools.js';
|
|
7
7
|
export { q, parseTypedQuery } from './tools/query-dsl.js';
|
|
8
|
-
export { defineFilters, numberFilter, stringFilter, useFilters, useQueryFilters, } from './routing/filters.js';
|
|
9
|
-
export { default as useFilterState } from './routing/useFilterState.js';
|
|
10
|
-
export { default as useActiveFilters } from './routing/useActiveFilters.js';
|
|
11
|
-
export { default as useQueryObject } from './routing/useQueryObject.js';
|
|
12
8
|
export type * from './types.js';
|
|
13
9
|
//# sourceMappingURL=index.d.ts.map
|
package/lib/esm/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,cAAc,mBAAmB,CAAC;AAGlC,cAAc,oBAAoB,CAAC;AAGnC,cAAc,oBAAoB,CAAC;AAGnC,cAAc,cAAc,CAAC;AAG7B,cAAc,mBAAmB,CAAC;AAGlC,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,CAAC,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,cAAc,mBAAmB,CAAC;AAGlC,cAAc,oBAAoB,CAAC;AAGnC,cAAc,oBAAoB,CAAC;AAGnC,cAAc,cAAc,CAAC;AAG7B,cAAc,mBAAmB,CAAC;AAGlC,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,CAAC,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAG1D,mBAAmB,YAAY,CAAC"}
|
package/lib/esm/index.js
CHANGED
|
@@ -5,8 +5,4 @@ export * from './builder.js';
|
|
|
5
5
|
export * from './ResourcePage.js';
|
|
6
6
|
export * from './tools.js';
|
|
7
7
|
export { q, parseTypedQuery } from './tools/query-dsl.js';
|
|
8
|
-
|
|
9
|
-
export { default as useFilterState } from './routing/useFilterState.js';
|
|
10
|
-
export { default as useActiveFilters } from './routing/useActiveFilters.js';
|
|
11
|
-
export { default as useQueryObject } from './routing/useQueryObject.js';
|
|
12
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsY0FBYyxtQkFBbUIsQ0FBQztBQUdsQyxjQUFjLG9CQUFvQixDQUFDO0FBR25DLGNBQWMsb0JBQW9CLENBQUM7QUFHbkMsY0FBYyxjQUFjLENBQUM7QUFHN0IsY0FBYyxtQkFBbUIsQ0FBQztBQUdsQyxjQUFjLFlBQVksQ0FBQztBQUMzQixPQUFPLEVBQUUsQ0FBQyxFQUFFLGVBQWUsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQzFELE9BQU8sRUFDTCxhQUFhLEVBQ2IsWUFBWSxFQUNaLFlBQVksRUFDWixVQUFVLEVBQ1YsZUFBZSxHQUNoQixNQUFNLHNCQUFzQixDQUFDO0FBQzlCLE9BQU8sRUFBRSxPQUFPLElBQUksY0FBYyxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDeEUsT0FBTyxFQUFFLE9BQU8sSUFBSSxnQkFBZ0IsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQzVFLE9BQU8sRUFBRSxPQUFPLElBQUksY0FBYyxFQUFFLE1BQU0sNkJBQTZCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBFeHBvcnQgZXJyb3IgaGFuZGxpbmcgdXRpbGl0aWVzXG5leHBvcnQgKiBmcm9tICcuL2Vycm9ycy9pbmRleC5qcyc7XG5cbi8vIEV4cG9ydCBicm93c2VyIGhpc3RvcnkgbWFuYWdlbWVudFxuZXhwb3J0ICogZnJvbSAnLi9oaXN0b3J5L2luZGV4LmpzJztcblxuLy8gRXhwb3J0IHJvdXRpbmcgY29tcG9uZW50cyBhbmQgdXRpbGl0aWVzXG5leHBvcnQgKiBmcm9tICcuL3JvdXRpbmcvaW5kZXguanMnO1xuXG4vLyBFeHBvcnQgcm91dGUgYnVpbGRpbmcgdXRpbGl0aWVzXG5leHBvcnQgKiBmcm9tICcuL2J1aWxkZXIuanMnO1xuXG4vLyBFeHBvcnQgcmVzb3VyY2UgcGFnZSBtYW5hZ2VtZW50IGZvciBsYXp5IGxvYWRpbmdcbmV4cG9ydCAqIGZyb20gJy4vUmVzb3VyY2VQYWdlLmpzJztcblxuLy8gRXhwb3J0IHV0aWxpdHkgZnVuY3Rpb25zXG5leHBvcnQgKiBmcm9tICcuL3Rvb2xzLmpzJztcbmV4cG9ydCB7IHEsIHBhcnNlVHlwZWRRdWVyeSB9IGZyb20gJy4vdG9vbHMvcXVlcnktZHNsLmpzJztcbmV4cG9ydCB7XG4gIGRlZmluZUZpbHRlcnMsXG4gIG51bWJlckZpbHRlcixcbiAgc3RyaW5nRmlsdGVyLFxuICB1c2VGaWx0ZXJzLFxuICB1c2VRdWVyeUZpbHRlcnMsXG59IGZyb20gJy4vcm91dGluZy9maWx0ZXJzLmpzJztcbmV4cG9ydCB7IGRlZmF1bHQgYXMgdXNlRmlsdGVyU3RhdGUgfSBmcm9tICcuL3JvdXRpbmcvdXNlRmlsdGVyU3RhdGUuanMnO1xuZXhwb3J0IHsgZGVmYXVsdCBhcyB1c2VBY3RpdmVGaWx0ZXJzIH0gZnJvbSAnLi9yb3V0aW5nL3VzZUFjdGl2ZUZpbHRlcnMuanMnO1xuZXhwb3J0IHsgZGVmYXVsdCBhcyB1c2VRdWVyeU9iamVjdCB9IGZyb20gJy4vcm91dGluZy91c2VRdWVyeU9iamVjdC5qcyc7XG5cbi8vIEV4cG9ydCBhbGwgVHlwZVNjcmlwdCB0eXBlc1xuZXhwb3J0IHR5cGUgKiBmcm9tICcuL3R5cGVzLmpzJztcbiJdfQ==
|
|
8
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsY0FBYyxtQkFBbUIsQ0FBQztBQUdsQyxjQUFjLG9CQUFvQixDQUFDO0FBR25DLGNBQWMsb0JBQW9CLENBQUM7QUFHbkMsY0FBYyxjQUFjLENBQUM7QUFHN0IsY0FBYyxtQkFBbUIsQ0FBQztBQUdsQyxjQUFjLFlBQVksQ0FBQztBQUMzQixPQUFPLEVBQUUsQ0FBQyxFQUFFLGVBQWUsRUFBRSxNQUFNLHNCQUFzQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gRXhwb3J0IGVycm9yIGhhbmRsaW5nIHV0aWxpdGllc1xuZXhwb3J0ICogZnJvbSAnLi9lcnJvcnMvaW5kZXguanMnO1xuXG4vLyBFeHBvcnQgYnJvd3NlciBoaXN0b3J5IG1hbmFnZW1lbnRcbmV4cG9ydCAqIGZyb20gJy4vaGlzdG9yeS9pbmRleC5qcyc7XG5cbi8vIEV4cG9ydCByb3V0aW5nIGNvbXBvbmVudHMgYW5kIHV0aWxpdGllc1xuZXhwb3J0ICogZnJvbSAnLi9yb3V0aW5nL2luZGV4LmpzJztcblxuLy8gRXhwb3J0IHJvdXRlIGJ1aWxkaW5nIHV0aWxpdGllc1xuZXhwb3J0ICogZnJvbSAnLi9idWlsZGVyLmpzJztcblxuLy8gRXhwb3J0IHJlc291cmNlIHBhZ2UgbWFuYWdlbWVudCBmb3IgbGF6eSBsb2FkaW5nXG5leHBvcnQgKiBmcm9tICcuL1Jlc291cmNlUGFnZS5qcyc7XG5cbi8vIEV4cG9ydCB1dGlsaXR5IGZ1bmN0aW9uc1xuZXhwb3J0ICogZnJvbSAnLi90b29scy5qcyc7XG5leHBvcnQgeyBxLCBwYXJzZVR5cGVkUXVlcnkgfSBmcm9tICcuL3Rvb2xzL3F1ZXJ5LWRzbC5qcyc7XG5cbi8vIEV4cG9ydCBhbGwgVHlwZVNjcmlwdCB0eXBlc1xuZXhwb3J0IHR5cGUgKiBmcm9tICcuL3R5cGVzLmpzJztcbiJdfQ==
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { type HTMLAttributeAnchorTarget, type ReactNode } from 'react';
|
|
2
2
|
import type { BrowserHistory, HistoryLocation } from '../history/index.js';
|
|
3
3
|
export declare function isCurrentPathname(exact: boolean, history: BrowserHistory | undefined, pathname: string): boolean;
|
|
4
|
-
type Props = {
|
|
4
|
+
type Props<TQuery extends Record<string, unknown> = Record<string, unknown>> = {
|
|
5
5
|
activeClassName?: string;
|
|
6
6
|
children: ReactNode;
|
|
7
7
|
className?: string;
|
|
@@ -15,8 +15,8 @@ type Props = {
|
|
|
15
15
|
onMouseOver?: React.MouseEventHandler<HTMLAnchorElement>;
|
|
16
16
|
target?: HTMLAttributeAnchorTarget;
|
|
17
17
|
to?: HistoryLocation | string;
|
|
18
|
-
query?:
|
|
18
|
+
query?: TQuery;
|
|
19
19
|
};
|
|
20
|
-
declare const Link: React.ForwardRefExoticComponent<Props & React.RefAttributes<HTMLAnchorElement>>;
|
|
20
|
+
declare const Link: React.ForwardRefExoticComponent<Props<Record<string, unknown>> & React.RefAttributes<HTMLAnchorElement>>;
|
|
21
21
|
export default Link;
|
|
22
22
|
//# sourceMappingURL=Link.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Link.d.ts","sourceRoot":"","sources":["../../../src/routing/Link.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EACZ,KAAK,yBAAyB,EAE9B,KAAK,SAAS,EAIf,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"Link.d.ts","sourceRoot":"","sources":["../../../src/routing/Link.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EACZ,KAAK,yBAAyB,EAE9B,KAAK,SAAS,EAIf,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAa3E,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,cAAc,GAAG,SAAS,EACnC,QAAQ,EAAE,MAAM,GACf,OAAO,CAmBT;AAKD,KAAK,KAAK,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI;IAE7E,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,QAAQ,EAAE,SAAS,CAAC;IAEpB,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAE9B,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAE7B,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB,OAAO,CAAC,EAAE,KAAK,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,CAAC;IAErD,OAAO,CAAC,EAAE,KAAK,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,CAAC;IAErD,WAAW,CAAC,EAAE,KAAK,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,CAAC;IAEzD,MAAM,CAAC,EAAE,yBAAyB,CAAC;IAEnC,EAAE,CAAC,EAAE,eAAe,GAAG,MAAM,CAAC;IAE9B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAyBF,QAAA,MAAM,IAAI,0GAyKR,CAAC;AAEH,eAAe,IAAI,CAAC"}
|