snice 7.2.0 → 7.4.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/.agents/skills/snice/SKILL.md +36 -13
- package/README.md +11 -6
- package/adapters/react/SniceProvider.js +1 -1
- package/adapters/react/SniceRouter.d.ts +2 -0
- package/adapters/react/SniceRouter.js +3 -2
- package/adapters/react/SniceRouter.js.map +1 -1
- package/adapters/react/matchRoute.d.ts +4 -1
- package/adapters/react/matchRoute.js +13 -3
- package/adapters/react/matchRoute.js.map +1 -1
- package/adapters/react/useRequestHandler.js +1 -1
- package/bin/analyzer-contracts.js +4 -1
- package/bin/project-analyzer.js +521 -20
- package/bin/snice.js +77 -13
- package/bin/templates/AI_GUIDANCE.md +6 -1
- package/bin/templates/default/README.md +1 -1
- package/bin/templates/default/src/components/app-header.ts +11 -16
- package/bin/templates/default/src/components/notification-badge.ts +5 -14
- package/bin/templates/default/src/components/search-bar.ts +21 -65
- package/bin/templates/default/src/pages/dashboard.ts +15 -11
- package/bin/templates/default/src/pages/data.ts +10 -13
- package/bin/templates/default/src/pages/notifications.ts +4 -9
- package/bin/templates/default/src/pages/profile.ts +2 -8
- package/bin/templates/default/src/pages/settings.ts +16 -16
- package/dist/app-context.d.ts +10 -10
- package/dist/cdn/accordion/snice-accordion.js +1 -1
- package/dist/cdn/action-bar/snice-action-bar.js +1 -1
- package/dist/cdn/activity-feed/snice-activity-feed.js +1 -1
- package/dist/cdn/alert/snice-alert.js +1 -1
- package/dist/cdn/app-tiles/snice-app-tiles.js +1 -1
- package/dist/cdn/approval-flow/snice-approval-flow.js +1 -1
- package/dist/cdn/audio-recorder/snice-audio-recorder.js +1 -1
- package/dist/cdn/availability/snice-availability.js +1 -1
- package/dist/cdn/avatar/snice-avatar.js +1 -1
- package/dist/cdn/avatar-group/snice-avatar-group.js +1 -1
- package/dist/cdn/badge/snice-badge.js +1 -1
- package/dist/cdn/banner/snice-banner.js +1 -1
- package/dist/cdn/binpack/snice-binpack.js +1 -1
- package/dist/cdn/book/snice-book.js +1 -1
- package/dist/cdn/booking/snice-booking.js +1 -1
- package/dist/cdn/breadcrumbs/snice-breadcrumbs.js +1 -1
- package/dist/cdn/button/snice-button.js +1 -1
- package/dist/cdn/calendar/snice-calendar.js +1 -1
- package/dist/cdn/camera/snice-camera.js +1 -1
- package/dist/cdn/camera-annotate/snice-camera-annotate.js +1 -1
- package/dist/cdn/candlestick/snice-candlestick.js +1 -1
- package/dist/cdn/card/snice-card.js +1 -1
- package/dist/cdn/carousel/snice-carousel.js +1 -1
- package/dist/cdn/cart/snice-cart.js +1 -1
- package/dist/cdn/chart/snice-chart.js +1 -1
- package/dist/cdn/chat/snice-chat.js +1 -1
- package/dist/cdn/checkbox/snice-checkbox.js +1 -1
- package/dist/cdn/chip/snice-chip.js +1 -1
- package/dist/cdn/code-block/snice-code-block.js +1 -1
- package/dist/cdn/color-display/snice-color-display.js +1 -1
- package/dist/cdn/color-picker/snice-color-picker.js +1 -1
- package/dist/cdn/command-palette/snice-command-palette.js +1 -1
- package/dist/cdn/comments/snice-comments.js +1 -1
- package/dist/cdn/countdown/snice-countdown.js +1 -1
- package/dist/cdn/cropper/snice-cropper.js +1 -1
- package/dist/cdn/data-card/snice-data-card.js +1 -1
- package/dist/cdn/date-picker/snice-date-picker.js +1 -1
- package/dist/cdn/date-range-picker/snice-date-range-picker.js +1 -1
- package/dist/cdn/date-time-picker/snice-date-time-picker.js +1 -1
- package/dist/cdn/diff/snice-diff.js +1 -1
- package/dist/cdn/divider/snice-divider.js +1 -1
- package/dist/cdn/doc/snice-doc.js +1 -1
- package/dist/cdn/draw/snice-draw.js +1 -1
- package/dist/cdn/drawer/snice-drawer.js +1 -1
- package/dist/cdn/empty-state/snice-empty-state.js +1 -1
- package/dist/cdn/estimate/snice-estimate.js +1 -1
- package/dist/cdn/file-gallery/snice-file-gallery.js +1 -1
- package/dist/cdn/file-upload/snice-file-upload.js +1 -1
- package/dist/cdn/flip-card/snice-flip-card.js +1 -1
- package/dist/cdn/flow/snice-flow.js +1 -1
- package/dist/cdn/form-layout/snice-form-layout.js +1 -1
- package/dist/cdn/funnel/snice-funnel.js +1 -1
- package/dist/cdn/gantt/snice-gantt.js +1 -1
- package/dist/cdn/gauge/snice-gauge.js +1 -1
- package/dist/cdn/grid/snice-grid.js +1 -1
- package/dist/cdn/heatmap/snice-heatmap.js +1 -1
- package/dist/cdn/image/snice-image.js +1 -1
- package/dist/cdn/input/snice-input.js +1 -1
- package/dist/cdn/invoice/snice-invoice.js +1 -1
- package/dist/cdn/kanban/snice-kanban.js +1 -1
- package/dist/cdn/key-value/snice-key-value.js +1 -1
- package/dist/cdn/kpi/snice-kpi.js +1 -1
- package/dist/cdn/layout/snice-layout.js +1 -1
- package/dist/cdn/leaderboard/snice-leaderboard.js +1 -1
- package/dist/cdn/link/snice-link.js +1 -1
- package/dist/cdn/link-preview/snice-link-preview.js +1 -1
- package/dist/cdn/list/snice-list.js +1 -1
- package/dist/cdn/location/snice-location.js +1 -1
- package/dist/cdn/login/snice-login.js +1 -1
- package/dist/cdn/map/snice-map.js +1 -1
- package/dist/cdn/markdown/snice-markdown.js +1 -1
- package/dist/cdn/masonry/snice-masonry.js +1 -1
- package/dist/cdn/menu/snice-menu.js +1 -1
- package/dist/cdn/message-strip/snice-message-strip.js +1 -1
- package/dist/cdn/modal/snice-modal.js +1 -1
- package/dist/cdn/music-player/snice-music-player.js +1 -1
- package/dist/cdn/nav/snice-nav.js +1 -1
- package/dist/cdn/network-graph/snice-network-graph.js +1 -1
- package/dist/cdn/notification-center/snice-notification-center.js +1 -1
- package/dist/cdn/order-tracker/snice-order-tracker.js +1 -1
- package/dist/cdn/org-chart/snice-org-chart.js +1 -1
- package/dist/cdn/pagination/snice-pagination.js +1 -1
- package/dist/cdn/paint/snice-paint.js +1 -1
- package/dist/cdn/pdf-viewer/snice-pdf-viewer.js +1 -1
- package/dist/cdn/permission-matrix/snice-permission-matrix.js +1 -1
- package/dist/cdn/podcast-player/snice-podcast-player.js +1 -1
- package/dist/cdn/popover/snice-popover.js +1 -1
- package/dist/cdn/pricing-table/snice-pricing-table.js +1 -1
- package/dist/cdn/product-card/snice-product-card.js +1 -1
- package/dist/cdn/progress/snice-progress.js +1 -1
- package/dist/cdn/progress-ring/snice-progress-ring.js +1 -1
- package/dist/cdn/qr-code/snice-qr-code.js +1 -1
- package/dist/cdn/qr-reader/snice-qr-reader.js +1 -1
- package/dist/cdn/radio/snice-radio.js +1 -1
- package/dist/cdn/range-slider/snice-range-slider.js +1 -1
- package/dist/cdn/rating/snice-rating.js +1 -1
- package/dist/cdn/receipt/snice-receipt.js +1 -1
- package/dist/cdn/recipe/snice-recipe.js +1 -1
- package/dist/cdn/runtime/README.md +2 -2
- package/dist/cdn/runtime/snice-runtime.esm.js +333 -192
- package/dist/cdn/runtime/snice-runtime.esm.js.map +1 -1
- package/dist/cdn/runtime/snice-runtime.esm.min.js +1 -1
- package/dist/cdn/runtime/snice-runtime.esm.min.js.map +1 -1
- package/dist/cdn/runtime/snice-runtime.js +333 -191
- package/dist/cdn/runtime/snice-runtime.js.map +1 -1
- package/dist/cdn/runtime/snice-runtime.min.js +1 -1
- package/dist/cdn/runtime/snice-runtime.min.js.map +1 -1
- package/dist/cdn/sankey/snice-sankey.js +1 -1
- package/dist/cdn/segmented-control/snice-segmented-control.js +1 -1
- package/dist/cdn/select/snice-select.js +1 -1
- package/dist/cdn/skeleton/snice-skeleton.js +1 -1
- package/dist/cdn/slider/snice-slider.js +1 -1
- package/dist/cdn/sortable/snice-sortable.js +1 -1
- package/dist/cdn/sparkline/snice-sparkline.js +1 -1
- package/dist/cdn/spinner/snice-spinner.js +1 -1
- package/dist/cdn/split-button/snice-split-button.js +1 -1
- package/dist/cdn/split-pane/snice-split-pane.js +1 -1
- package/dist/cdn/spotlight/snice-spotlight.js +1 -1
- package/dist/cdn/stat-group/snice-stat-group.js +1 -1
- package/dist/cdn/step-input/snice-step-input.js +1 -1
- package/dist/cdn/stepper/snice-stepper.js +1 -1
- package/dist/cdn/switch/snice-switch.js +1 -1
- package/dist/cdn/table/snice-table.esm.js +1 -1
- package/dist/cdn/table/snice-table.js +1 -1
- package/dist/cdn/tabs/snice-tabs.js +1 -1
- package/dist/cdn/tag/snice-tag.js +1 -1
- package/dist/cdn/tag-input/snice-tag-input.js +1 -1
- package/dist/cdn/terminal/snice-terminal.js +1 -1
- package/dist/cdn/testimonial/snice-testimonial.js +1 -1
- package/dist/cdn/textarea/snice-textarea.js +1 -1
- package/dist/cdn/time-picker/snice-time-picker.js +1 -1
- package/dist/cdn/time-range-picker/snice-time-range-picker.js +1 -1
- package/dist/cdn/timeline/snice-timeline.js +1 -1
- package/dist/cdn/timer/snice-timer.js +1 -1
- package/dist/cdn/toast/snice-toast.js +1 -1
- package/dist/cdn/tooltip/snice-tooltip.js +1 -1
- package/dist/cdn/tree/snice-tree.js +1 -1
- package/dist/cdn/treemap/snice-treemap.js +1 -1
- package/dist/cdn/user-card/snice-user-card.js +1 -1
- package/dist/cdn/video-player/snice-video-player.js +1 -1
- package/dist/cdn/virtual-scroller/snice-virtual-scroller.js +1 -1
- package/dist/cdn/waterfall/snice-waterfall.js +1 -1
- package/dist/cdn/weather/snice-weather.js +1 -1
- package/dist/cdn/work-order/snice-work-order.js +1 -1
- package/dist/components/pagination/snice-pagination.types.d.ts +5 -0
- package/dist/context-provider.d.ts +11 -1
- package/dist/context.d.ts +5 -6
- package/dist/index.cjs +330 -188
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.esm.js +330 -189
- package/dist/index.esm.js.map +1 -1
- package/dist/index.iife.js +330 -188
- package/dist/index.iife.js.map +1 -1
- package/dist/react/SniceProvider.js +1 -1
- package/dist/react/SniceRouter.d.ts +2 -0
- package/dist/react/SniceRouter.js +3 -2
- package/dist/react/SniceRouter.js.map +1 -1
- package/dist/react/index.js +1 -1
- package/dist/react/matchRoute.d.ts +4 -1
- package/dist/react/matchRoute.js +13 -3
- package/dist/react/matchRoute.js.map +1 -1
- package/dist/react/useRequestHandler.js +1 -1
- package/dist/symbols.cjs +1 -1
- package/dist/symbols.esm.js +1 -1
- package/dist/testing-dom.cjs +48 -0
- package/dist/testing-dom.cjs.map +1 -0
- package/dist/testing-dom.d.ts +23 -0
- package/dist/testing-dom.esm.js +45 -0
- package/dist/testing-dom.esm.js.map +1 -0
- package/dist/transitions.cjs +1 -1
- package/dist/transitions.esm.js +1 -1
- package/dist/types/context.d.ts +8 -8
- package/dist/types/page-options.d.ts +15 -1
- package/dist/types/router-instance.d.ts +2 -1
- package/dist/utils.d.ts +3 -1
- package/docs/ai/README.md +6 -4
- package/docs/ai/api.md +13 -2
- package/docs/ai/architecture.md +28 -11
- package/docs/ai/bindings.md +1 -1
- package/docs/ai/cli.md +26 -1
- package/docs/ai/components/badge.md +4 -0
- package/docs/ai/components/pagination.md +4 -2
- package/docs/ai/components/segmented-control.md +5 -1
- package/docs/ai/controllers.md +41 -12
- package/docs/ai/decorators.md +3 -3
- package/docs/ai/events.md +8 -2
- package/docs/ai/fetcher.md +32 -1
- package/docs/ai/lifecycle.md +4 -1
- package/docs/ai/patterns.md +9 -4
- package/docs/ai/react-integration.md +1 -0
- package/docs/ai/request-response.md +20 -6
- package/docs/ai/routing.md +33 -4
- package/docs/ai/testing.md +71 -0
- package/docs/bindings.md +1 -1
- package/docs/cli.md +27 -2
- package/docs/components/badge.md +4 -0
- package/docs/components/pagination.md +8 -5
- package/docs/components/segmented-control.md +5 -1
- package/docs/controllers.md +46 -15
- package/docs/events.md +11 -2
- package/docs/fetcher.md +32 -1
- package/docs/lifecycle.md +5 -1
- package/docs/react-integration.md +1 -0
- package/docs/request-response.md +25 -7
- package/docs/routing.md +39 -3
- package/docs/testing.md +71 -0
- package/package.json +6 -1
|
@@ -8,9 +8,21 @@ description: Build, modify, debug, or review applications and components that us
|
|
|
8
8
|
Use the documentation shipped with the exact installed Snice version. Do not
|
|
9
9
|
reconstruct Snice APIs from Lit or generic web-component conventions.
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
## Choose the owner before the API
|
|
12
|
+
|
|
13
|
+
Make this decision before creating files or choosing decorators:
|
|
14
|
+
|
|
15
|
+
- **Element:** visual behavior, rendering, internal DOM, focus, keyboard behavior, visual state, and semantic events.
|
|
16
|
+
- **Controller:** application behavior specific to a set of elements, including API/storage access and business rules.
|
|
17
|
+
- **Page:** element orchestration: composition, properties, events, controller binding, and screen coordination. Routing is only one page concern.
|
|
18
|
+
|
|
19
|
+
Do not attach a controller to a page host, create a “page controller,” or move visual behavior into a controller to shrink an element. Host-free reusable functions may stay plain modules. State plus lifecycle belongs in an explicitly constructed `@daemon`, never a singleton.
|
|
20
|
+
|
|
21
|
+
Examples: focus/internal buttons → element; element-specific API behavior → controller;
|
|
22
|
+
coordinating search, results, and dialog elements → page; state plus lifecycle → daemon.
|
|
23
|
+
|
|
24
|
+
If `.agents/skills/snice/SKILL.md` is absent, run `npx snice init-ai` from the
|
|
25
|
+
project root before writing code; it installs version-matched agent guidance.
|
|
14
26
|
|
|
15
27
|
## Locate the reference
|
|
16
28
|
|
|
@@ -19,18 +31,23 @@ Use the first directory that exists:
|
|
|
19
31
|
1. `docs/ai/` in a Snice source checkout.
|
|
20
32
|
2. `node_modules/snice/docs/ai/` in a consuming application.
|
|
21
33
|
|
|
34
|
+
Every reference below is relative to that AI-doc root. Never substitute the
|
|
35
|
+
parallel human-facing files under `docs/`.
|
|
36
|
+
|
|
22
37
|
If neither exists, install the project dependencies before writing Snice code.
|
|
23
38
|
|
|
24
|
-
##
|
|
39
|
+
## Documentation gate (mandatory)
|
|
25
40
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
3.
|
|
41
|
+
The agent doing the work must complete this gate itself before editing. Do not
|
|
42
|
+
delegate the reading, rely on memory, or substitute another agent's summary.
|
|
43
|
+
|
|
44
|
+
1. Read the AI-doc root's `README.md` for its contract and documentation map.
|
|
45
|
+
2. Before touching code that uses a Snice decorator, or introducing one, read
|
|
46
|
+
`decorators.md` and that decorator's complete topical AI reference. The
|
|
47
|
+
general decorator index alone does not satisfy this gate.
|
|
48
|
+
3. Before touching code that uses a built-in Snice element, or introducing one,
|
|
49
|
+
read that element's complete `components/<name>.md` reference.
|
|
50
|
+
4. Read the applicable template, binding, routing, controller, daemon, React, theme, accessibility, or lifecycle reference before using that feature.
|
|
34
51
|
|
|
35
52
|
Treat those versioned files and the runtime TypeScript declarations as
|
|
36
53
|
authoritative. If they conflict, inspect the installed declarations/source and
|
|
@@ -47,8 +64,12 @@ type-checks with `npx tsc -p references/tsconfig.kitchen-sink.json` after
|
|
|
47
64
|
- Import built-in elements through their documented deep side-effect path.
|
|
48
65
|
- Import React wrappers from `snice/react`; also register each underlying
|
|
49
66
|
custom element through its documented deep side-effect import.
|
|
50
|
-
- Keep application data and orchestration in pages, controllers, or services.
|
|
51
67
|
- Pass objects and arrays through property bindings, not string attributes.
|
|
68
|
+
- In Router-backed controllers, receive `Context` with `@context()` and use
|
|
69
|
+
`ctx.fetch` for middleware-aware transport. Managed decorators activate
|
|
70
|
+
after `attach()`, so context-dependent startup belongs in the `@context()`
|
|
71
|
+
handler. Do not call bare `fetch`, import the Router into the controller, or
|
|
72
|
+
invent another context-injection channel.
|
|
52
73
|
- Preserve native form, keyboard, focus, and accessibility behavior.
|
|
53
74
|
- Use the project compiler configuration for TC39 decorators.
|
|
54
75
|
- Do not edit generated distribution, adapter, metadata, or website output.
|
|
@@ -58,6 +79,8 @@ configuration, import, hallucination, and component-recommendation checks.
|
|
|
58
79
|
Use `npx snice doctor` or `npx snice validate` only when isolating the
|
|
59
80
|
configuration or source half of a failed check.
|
|
60
81
|
|
|
82
|
+
Diagnostics expose stable codes. After reading the referenced AI docs and verifying intentional acceptance, the agent may record the narrowest suppression in project-root `.sniceignore`: `code path:line:column` (one diagnostic), `code path` (one file), or `code` (global). Use global only when the project rejects the rule. Never suppress merely to pass a gate; comment non-obvious reasons.
|
|
83
|
+
|
|
61
84
|
## Verify
|
|
62
85
|
|
|
63
86
|
Run the consuming project's available checks in this order:
|
package/README.md
CHANGED
|
@@ -433,7 +433,11 @@ setValue(val: string) {
|
|
|
433
433
|
|
|
434
434
|
### Global State
|
|
435
435
|
|
|
436
|
-
**`@context(options?)`** - Receive
|
|
436
|
+
**`@context(options?)`** - Receive Router context updates on pages, descendant
|
|
437
|
+
elements, and attached controllers. Controllers can use the same
|
|
438
|
+
middleware-aware `ctx.fetch` as pages; context-dependent controller startup
|
|
439
|
+
belongs in the `@context()` handler because managed decorators activate after
|
|
440
|
+
`attach()`.
|
|
437
441
|
```typescript
|
|
438
442
|
// Method decorator that receives context updates
|
|
439
443
|
@context()
|
|
@@ -591,11 +595,12 @@ elements in `src/components/`, attached behavior in `src/controllers/`, and
|
|
|
591
595
|
app-owned services in `src/daemons/`. `src/router.ts` constructs and exports the
|
|
592
596
|
router pieces; `src/main.ts` imports page modules and calls `initialize()`.
|
|
593
597
|
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
598
|
+
Visual behavior belongs in elements, application behavior specific to a set of
|
|
599
|
+
elements belongs in a controller, and element orchestration belongs in pages.
|
|
600
|
+
Do not attach a controller to the page host. A host-free reusable function may
|
|
601
|
+
stay a plain module in the project's chosen location. `snice check` reports
|
|
602
|
+
page-host controllers, manual URL parsing, and decomposition opportunities while
|
|
603
|
+
treating broken Router construction as an error.
|
|
599
604
|
|
|
600
605
|
## Template Syntax
|
|
601
606
|
|
|
@@ -2,6 +2,8 @@ import { type ReactNode, type ReactElement, type ComponentType } from 'react';
|
|
|
2
2
|
import type { Placard } from './SniceProvider';
|
|
3
3
|
export interface RouteProps {
|
|
4
4
|
path: string;
|
|
5
|
+
/** Lower values win when route specificity ties. Declaration order is the fallback. */
|
|
6
|
+
order?: number;
|
|
5
7
|
/** React component OR Snice element tag name (string) */
|
|
6
8
|
page: ComponentType<any> | string;
|
|
7
9
|
/** Single guard function */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* snice v7.
|
|
2
|
+
* snice v7.3.0
|
|
3
3
|
* A decorator-driven web component library with routing, controllers, daemons, and 130+ UI components. For better coding-agent results, run npx snice init-ai.
|
|
4
4
|
* (c) 2024
|
|
5
5
|
* Released under the MIT License.
|
|
@@ -83,6 +83,7 @@ function SniceRouter({ mode, context = {}, layout: defaultLayout, loading, fallb
|
|
|
83
83
|
guards.push(...props.guards);
|
|
84
84
|
result.push({
|
|
85
85
|
path: props.path,
|
|
86
|
+
order: props.order,
|
|
86
87
|
page: props.page,
|
|
87
88
|
guards,
|
|
88
89
|
guardRedirect: props.guardRedirect,
|
|
@@ -99,7 +100,7 @@ function SniceRouter({ mode, context = {}, layout: defaultLayout, loading, fallb
|
|
|
99
100
|
.map((r) => r.placard);
|
|
100
101
|
}, [parsedRoutes]);
|
|
101
102
|
// Build route configs for matching
|
|
102
|
-
const routeConfigs = useMemo(() => parsedRoutes.map((r, i) => ({ path: r.path, index: i })), [parsedRoutes]);
|
|
103
|
+
const routeConfigs = useMemo(() => parsedRoutes.map((r, i) => ({ path: r.path, index: i, order: r.order })), [parsedRoutes]);
|
|
103
104
|
// Navigate function
|
|
104
105
|
const navigate = useCallback((path) => {
|
|
105
106
|
if (mode === 'hash') {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SniceRouter.js","sources":["../../src/react/SniceRouter.tsx"],"sourcesContent":["import {\n useState,\n useEffect,\n useCallback,\n useMemo,\n useRef,\n type ReactNode,\n type ReactElement,\n type ComponentType,\n Children,\n isValidElement,\n createElement,\n} from 'react';\nimport { SniceProvider } from './SniceProvider';\nimport { matchRoutes, type RouteConfig } from './matchRoute';\nimport type { Placard } from './SniceProvider';\n\n// ─── Route component (declarative config) ───\n\nexport interface RouteProps {\n path: string;\n /** React component OR Snice element tag name (string) */\n page: ComponentType<any> | string;\n /** Single guard function */\n guard?: (context: Record<string, any>, params: Record<string, string>) => boolean | Promise<boolean>;\n /** Multiple guards (AND logic) */\n guards?: Array<(context: Record<string, any>, params: Record<string, string>) => boolean | Promise<boolean>>;\n /** Redirect path if guard rejects */\n guardRedirect?: string;\n /** Layout override. Component, string (Snice tag), or false (no layout) */\n layout?: ComponentType<{ children: ReactNode }> | string | false;\n /** Page metadata for layouts */\n placard?: Placard;\n}\n\n/**\n * Route definition component. Child of <SniceRouter>.\n * Does not render anything — SniceRouter reads its props.\n */\nexport function Route(_props: RouteProps): ReactElement | null {\n return null;\n}\n\n// ─── SniceRouter ───\n\nexport interface SniceRouterProps {\n /** URL strategy */\n mode: 'hash' | 'history';\n /** Application context passed to guards, pages, layouts */\n context?: Record<string, any>;\n /** Default layout component or Snice tag name */\n layout?: ComponentType<{ children: ReactNode }> | string;\n /** Loading component shown during async guards. Component, string (Snice tag), or JSX. */\n loading?: ComponentType | string | ReactNode;\n /** Fallback when no route matches. Component, string (Snice tag), or JSX. */\n fallback?: ComponentType | string | ReactNode;\n children: ReactNode;\n}\n\ninterface ParsedRoute {\n path: string;\n page: ComponentType<any> | string;\n guards: Array<(ctx: Record<string, any>, params: Record<string, string>) => boolean | Promise<boolean>>;\n guardRedirect?: string;\n layout?: ComponentType<{ children: ReactNode }> | string | false;\n placard?: Placard;\n}\n\nfunction getPath(mode: 'hash' | 'history'): string {\n if (mode === 'hash') {\n return window.location.hash.slice(1) || '/';\n }\n return window.location.pathname;\n}\n\nfunction DefaultLoading() {\n return createElement('div', {\n style: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n height: '100%',\n minHeight: '200px',\n },\n },\n createElement('style', null, '@keyframes snice-spin{to{transform:rotate(360deg)}}'),\n createElement('div', {\n style: {\n width: '32px',\n height: '32px',\n border: '3px solid rgba(128,128,128,0.3)',\n borderTopColor: 'rgba(128,128,128,0.8)',\n borderRadius: '50%',\n animation: 'snice-spin 0.6s linear infinite',\n },\n }),\n );\n}\n\n/** Render a page/layout/loading/fallback prop that can be component, string tag, or JSX */\nfunction renderFlexible(\n value: ComponentType<any> | string | ReactNode | undefined,\n props?: Record<string, any>,\n): ReactNode {\n if (value === undefined || value === null) return null;\n\n // String = Snice web component tag name\n if (typeof value === 'string') {\n return createElement(value, props);\n }\n\n // Function = React component\n if (typeof value === 'function') {\n return createElement(value as ComponentType<any>, props);\n }\n\n // Already JSX/ReactNode\n return value;\n}\n\n/**\n * Root provider component. Manages URL state, route matching,\n * guard execution, layout selection, and context propagation.\n */\nexport function SniceRouter({\n mode,\n context = {},\n layout: defaultLayout,\n loading,\n fallback,\n children,\n}: SniceRouterProps) {\n const [currentPath, setCurrentPath] = useState(() => getPath(mode));\n const [guardState, setGuardState] = useState<'idle' | 'checking' | 'passed' | 'failed'>('idle');\n const contextRef = useRef(context);\n contextRef.current = context;\n\n // Parse Route children into config\n const parsedRoutes = useMemo<ParsedRoute[]>(() => {\n const result: ParsedRoute[] = [];\n Children.forEach(children, (child) => {\n if (!isValidElement(child) || child.type !== Route) return;\n const props = child.props as RouteProps;\n const guards: ParsedRoute['guards'] = [];\n if (props.guard) guards.push(props.guard);\n if (props.guards) guards.push(...props.guards);\n result.push({\n path: props.path,\n page: props.page,\n guards,\n guardRedirect: props.guardRedirect,\n layout: props.layout,\n placard: props.placard,\n });\n });\n return result;\n }, [children]);\n\n // Collect placards\n const placards = useMemo<Placard[]>(() => {\n return parsedRoutes\n .filter((r) => r.placard)\n .map((r) => r.placard!);\n }, [parsedRoutes]);\n\n // Build route configs for matching\n const routeConfigs = useMemo<RouteConfig[]>(\n () => parsedRoutes.map((r, i) => ({ path: r.path, index: i })),\n [parsedRoutes],\n );\n\n // Navigate function\n const navigate = useCallback(\n (path: string) => {\n if (mode === 'hash') {\n window.location.hash = path;\n } else {\n window.history.pushState(null, '', path);\n setCurrentPath(path);\n }\n },\n [mode],\n );\n\n // Listen for URL changes\n useEffect(() => {\n const handler = () => setCurrentPath(getPath(mode));\n const event = mode === 'hash' ? 'hashchange' : 'popstate';\n window.addEventListener(event, handler);\n return () => window.removeEventListener(event, handler);\n }, [mode]);\n\n // Match current path\n const match = useMemo(\n () => matchRoutes(routeConfigs, currentPath),\n [routeConfigs, currentPath],\n );\n\n const matchedRoute = match ? parsedRoutes[match.index] : null;\n // Stable params reference across renders so downstream `useMemo` deps\n // (SniceProvider value, guard effect) don't churn on every render when\n // nothing actually changed.\n const params = useMemo(\n () => match?.params ?? {},\n // Re-create only when the param content actually changes\n [JSON.stringify(match?.params ?? {})],\n );\n\n // Run guards\n useEffect(() => {\n if (!matchedRoute) {\n setGuardState('idle');\n return;\n }\n\n if (matchedRoute.guards.length === 0) {\n setGuardState('passed');\n return;\n }\n\n let cancelled = false;\n setGuardState('checking');\n\n (async () => {\n try {\n for (const guard of matchedRoute.guards) {\n const result = await guard(contextRef.current, params);\n if (cancelled) return;\n if (!result) {\n setGuardState('failed');\n if (matchedRoute.guardRedirect) {\n navigate(matchedRoute.guardRedirect);\n }\n return;\n }\n }\n if (!cancelled) setGuardState('passed');\n } catch {\n if (!cancelled) {\n setGuardState('failed');\n if (matchedRoute.guardRedirect) {\n navigate(matchedRoute.guardRedirect);\n }\n }\n }\n })();\n\n return () => { cancelled = true; };\n }, [matchedRoute, currentPath]); // eslint-disable-line react-hooks/exhaustive-deps\n\n // Determine what to render\n let content: ReactNode;\n\n if (!matchedRoute) {\n // No route match → fallback\n content = renderFlexible(fallback) ?? createElement('div', null, '404 — Page not found');\n } else if (guardState === 'checking') {\n // Async guards running → show loading\n content = renderFlexible(loading) ?? createElement(DefaultLoading);\n } else if (guardState === 'failed') {\n // Guard rejected (redirect may have fired) — render nothing\n content = null;\n } else {\n // Guard passed or no guards → render page\n content = renderFlexible(matchedRoute.page, params);\n }\n\n // Apply layout\n const layoutCandidate = matchedRoute?.layout !== undefined ? matchedRoute.layout : defaultLayout;\n const layoutToUse = layoutCandidate === false ? undefined : layoutCandidate;\n if (layoutToUse && content !== null) {\n content = renderFlexible(\n layoutToUse as ComponentType<{ children: ReactNode }> | string,\n { children: content },\n );\n }\n\n return (\n <SniceProvider\n context={context}\n navigate={navigate}\n route={match?.path ?? ''}\n params={params}\n placards={placards}\n >\n {content}\n </SniceProvider>\n );\n}\n"],"names":["_jsx"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SniceRouter.js","sources":["../../src/react/SniceRouter.tsx"],"sourcesContent":["import {\n useState,\n useEffect,\n useCallback,\n useMemo,\n useRef,\n type ReactNode,\n type ReactElement,\n type ComponentType,\n Children,\n isValidElement,\n createElement,\n} from 'react';\nimport { SniceProvider } from './SniceProvider';\nimport { matchRoutes, type RouteConfig } from './matchRoute';\nimport type { Placard } from './SniceProvider';\n\n// ─── Route component (declarative config) ───\n\nexport interface RouteProps {\n path: string;\n /** Lower values win when route specificity ties. Declaration order is the fallback. */\n order?: number;\n /** React component OR Snice element tag name (string) */\n page: ComponentType<any> | string;\n /** Single guard function */\n guard?: (context: Record<string, any>, params: Record<string, string>) => boolean | Promise<boolean>;\n /** Multiple guards (AND logic) */\n guards?: Array<(context: Record<string, any>, params: Record<string, string>) => boolean | Promise<boolean>>;\n /** Redirect path if guard rejects */\n guardRedirect?: string;\n /** Layout override. Component, string (Snice tag), or false (no layout) */\n layout?: ComponentType<{ children: ReactNode }> | string | false;\n /** Page metadata for layouts */\n placard?: Placard;\n}\n\n/**\n * Route definition component. Child of <SniceRouter>.\n * Does not render anything — SniceRouter reads its props.\n */\nexport function Route(_props: RouteProps): ReactElement | null {\n return null;\n}\n\n// ─── SniceRouter ───\n\nexport interface SniceRouterProps {\n /** URL strategy */\n mode: 'hash' | 'history';\n /** Application context passed to guards, pages, layouts */\n context?: Record<string, any>;\n /** Default layout component or Snice tag name */\n layout?: ComponentType<{ children: ReactNode }> | string;\n /** Loading component shown during async guards. Component, string (Snice tag), or JSX. */\n loading?: ComponentType | string | ReactNode;\n /** Fallback when no route matches. Component, string (Snice tag), or JSX. */\n fallback?: ComponentType | string | ReactNode;\n children: ReactNode;\n}\n\ninterface ParsedRoute {\n path: string;\n order?: number;\n page: ComponentType<any> | string;\n guards: Array<(ctx: Record<string, any>, params: Record<string, string>) => boolean | Promise<boolean>>;\n guardRedirect?: string;\n layout?: ComponentType<{ children: ReactNode }> | string | false;\n placard?: Placard;\n}\n\nfunction getPath(mode: 'hash' | 'history'): string {\n if (mode === 'hash') {\n return window.location.hash.slice(1) || '/';\n }\n return window.location.pathname;\n}\n\nfunction DefaultLoading() {\n return createElement('div', {\n style: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n height: '100%',\n minHeight: '200px',\n },\n },\n createElement('style', null, '@keyframes snice-spin{to{transform:rotate(360deg)}}'),\n createElement('div', {\n style: {\n width: '32px',\n height: '32px',\n border: '3px solid rgba(128,128,128,0.3)',\n borderTopColor: 'rgba(128,128,128,0.8)',\n borderRadius: '50%',\n animation: 'snice-spin 0.6s linear infinite',\n },\n }),\n );\n}\n\n/** Render a page/layout/loading/fallback prop that can be component, string tag, or JSX */\nfunction renderFlexible(\n value: ComponentType<any> | string | ReactNode | undefined,\n props?: Record<string, any>,\n): ReactNode {\n if (value === undefined || value === null) return null;\n\n // String = Snice web component tag name\n if (typeof value === 'string') {\n return createElement(value, props);\n }\n\n // Function = React component\n if (typeof value === 'function') {\n return createElement(value as ComponentType<any>, props);\n }\n\n // Already JSX/ReactNode\n return value;\n}\n\n/**\n * Root provider component. Manages URL state, route matching,\n * guard execution, layout selection, and context propagation.\n */\nexport function SniceRouter({\n mode,\n context = {},\n layout: defaultLayout,\n loading,\n fallback,\n children,\n}: SniceRouterProps) {\n const [currentPath, setCurrentPath] = useState(() => getPath(mode));\n const [guardState, setGuardState] = useState<'idle' | 'checking' | 'passed' | 'failed'>('idle');\n const contextRef = useRef(context);\n contextRef.current = context;\n\n // Parse Route children into config\n const parsedRoutes = useMemo<ParsedRoute[]>(() => {\n const result: ParsedRoute[] = [];\n Children.forEach(children, (child) => {\n if (!isValidElement(child) || child.type !== Route) return;\n const props = child.props as RouteProps;\n const guards: ParsedRoute['guards'] = [];\n if (props.guard) guards.push(props.guard);\n if (props.guards) guards.push(...props.guards);\n result.push({\n path: props.path,\n order: props.order,\n page: props.page,\n guards,\n guardRedirect: props.guardRedirect,\n layout: props.layout,\n placard: props.placard,\n });\n });\n return result;\n }, [children]);\n\n // Collect placards\n const placards = useMemo<Placard[]>(() => {\n return parsedRoutes\n .filter((r) => r.placard)\n .map((r) => r.placard!);\n }, [parsedRoutes]);\n\n // Build route configs for matching\n const routeConfigs = useMemo<RouteConfig[]>(\n () => parsedRoutes.map((r, i) => ({ path: r.path, index: i, order: r.order })),\n [parsedRoutes],\n );\n\n // Navigate function\n const navigate = useCallback(\n (path: string) => {\n if (mode === 'hash') {\n window.location.hash = path;\n } else {\n window.history.pushState(null, '', path);\n setCurrentPath(path);\n }\n },\n [mode],\n );\n\n // Listen for URL changes\n useEffect(() => {\n const handler = () => setCurrentPath(getPath(mode));\n const event = mode === 'hash' ? 'hashchange' : 'popstate';\n window.addEventListener(event, handler);\n return () => window.removeEventListener(event, handler);\n }, [mode]);\n\n // Match current path\n const match = useMemo(\n () => matchRoutes(routeConfigs, currentPath),\n [routeConfigs, currentPath],\n );\n\n const matchedRoute = match ? parsedRoutes[match.index] : null;\n // Stable params reference across renders so downstream `useMemo` deps\n // (SniceProvider value, guard effect) don't churn on every render when\n // nothing actually changed.\n const params = useMemo(\n () => match?.params ?? {},\n // Re-create only when the param content actually changes\n [JSON.stringify(match?.params ?? {})],\n );\n\n // Run guards\n useEffect(() => {\n if (!matchedRoute) {\n setGuardState('idle');\n return;\n }\n\n if (matchedRoute.guards.length === 0) {\n setGuardState('passed');\n return;\n }\n\n let cancelled = false;\n setGuardState('checking');\n\n (async () => {\n try {\n for (const guard of matchedRoute.guards) {\n const result = await guard(contextRef.current, params);\n if (cancelled) return;\n if (!result) {\n setGuardState('failed');\n if (matchedRoute.guardRedirect) {\n navigate(matchedRoute.guardRedirect);\n }\n return;\n }\n }\n if (!cancelled) setGuardState('passed');\n } catch {\n if (!cancelled) {\n setGuardState('failed');\n if (matchedRoute.guardRedirect) {\n navigate(matchedRoute.guardRedirect);\n }\n }\n }\n })();\n\n return () => { cancelled = true; };\n }, [matchedRoute, currentPath]); // eslint-disable-line react-hooks/exhaustive-deps\n\n // Determine what to render\n let content: ReactNode;\n\n if (!matchedRoute) {\n // No route match → fallback\n content = renderFlexible(fallback) ?? createElement('div', null, '404 — Page not found');\n } else if (guardState === 'checking') {\n // Async guards running → show loading\n content = renderFlexible(loading) ?? createElement(DefaultLoading);\n } else if (guardState === 'failed') {\n // Guard rejected (redirect may have fired) — render nothing\n content = null;\n } else {\n // Guard passed or no guards → render page\n content = renderFlexible(matchedRoute.page, params);\n }\n\n // Apply layout\n const layoutCandidate = matchedRoute?.layout !== undefined ? matchedRoute.layout : defaultLayout;\n const layoutToUse = layoutCandidate === false ? undefined : layoutCandidate;\n if (layoutToUse && content !== null) {\n content = renderFlexible(\n layoutToUse as ComponentType<{ children: ReactNode }> | string,\n { children: content },\n );\n }\n\n return (\n <SniceProvider\n context={context}\n navigate={navigate}\n route={match?.path ?? ''}\n params={params}\n placards={placards}\n >\n {content}\n </SniceProvider>\n );\n}\n"],"names":["_jsx"],"mappings":";;;;;;;;;;;;;;AAqCA;;;AAGG;AACG,SAAU,KAAK,CAAC,MAAkB,EAAA;AACtC,IAAA,OAAO,IAAI;AACb;AA4BA,SAAS,OAAO,CAAC,IAAwB,EAAA;AACvC,IAAA,IAAI,IAAI,KAAK,MAAM,EAAE;AACnB,QAAA,OAAO,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,GAAG;IAC7C;AACA,IAAA,OAAO,MAAM,CAAC,QAAQ,CAAC,QAAQ;AACjC;AAEA,SAAS,cAAc,GAAA;IACrB,OAAO,aAAa,CAAC,KAAK,EAAE;AAC1B,QAAA,KAAK,EAAE;AACL,YAAA,OAAO,EAAE,MAAM;AACf,YAAA,UAAU,EAAE,QAAQ;AACpB,YAAA,cAAc,EAAE,QAAQ;AACxB,YAAA,MAAM,EAAE,MAAM;AACd,YAAA,SAAS,EAAE,OAAO;AACnB,SAAA;AACF,KAAA,EACC,aAAa,CAAC,OAAO,EAAE,IAAI,EAAE,qDAAqD,CAAC,EACnF,aAAa,CAAC,KAAK,EAAE;AACnB,QAAA,KAAK,EAAE;AACL,YAAA,KAAK,EAAE,MAAM;AACb,YAAA,MAAM,EAAE,MAAM;AACd,YAAA,MAAM,EAAE,iCAAiC;AACzC,YAAA,cAAc,EAAE,uBAAuB;AACvC,YAAA,YAAY,EAAE,KAAK;AACnB,YAAA,SAAS,EAAE,iCAAiC;AAC7C,SAAA;AACF,KAAA,CAAC,CACH;AACH;AAEA;AACA,SAAS,cAAc,CACrB,KAA0D,EAC1D,KAA2B,EAAA;AAE3B,IAAA,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;AAAE,QAAA,OAAO,IAAI;;AAGtD,IAAA,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;AAC7B,QAAA,OAAO,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC;IACpC;;AAGA,IAAA,IAAI,OAAO,KAAK,KAAK,UAAU,EAAE;AAC/B,QAAA,OAAO,aAAa,CAAC,KAA2B,EAAE,KAAK,CAAC;IAC1D;;AAGA,IAAA,OAAO,KAAK;AACd;AAEA;;;AAGG;SACa,WAAW,CAAC,EAC1B,IAAI,EACJ,OAAO,GAAG,EAAE,EACZ,MAAM,EAAE,aAAa,EACrB,OAAO,EACP,QAAQ,EACR,QAAQ,GACS,EAAA;AACjB,IAAA,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACnE,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAA4C,MAAM,CAAC;AAC/F,IAAA,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC;AAClC,IAAA,UAAU,CAAC,OAAO,GAAG,OAAO;;AAG5B,IAAA,MAAM,YAAY,GAAG,OAAO,CAAgB,MAAK;QAC/C,MAAM,MAAM,GAAkB,EAAE;QAChC,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,KAAK,KAAI;YACnC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,KAAK;gBAAE;AACpD,YAAA,MAAM,KAAK,GAAG,KAAK,CAAC,KAAmB;YACvC,MAAM,MAAM,GAA0B,EAAE;YACxC,IAAI,KAAK,CAAC,KAAK;AAAE,gBAAA,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC;YACzC,IAAI,KAAK,CAAC,MAAM;gBAAE,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC;YAC9C,MAAM,CAAC,IAAI,CAAC;gBACV,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,MAAM;gBACN,aAAa,EAAE,KAAK,CAAC,aAAa;gBAClC,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,OAAO,EAAE,KAAK,CAAC,OAAO;AACvB,aAAA,CAAC;AACJ,QAAA,CAAC,CAAC;AACF,QAAA,OAAO,MAAM;AACf,IAAA,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;;AAGd,IAAA,MAAM,QAAQ,GAAG,OAAO,CAAY,MAAK;AACvC,QAAA,OAAO;aACJ,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO;aACvB,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAQ,CAAC;AAC3B,IAAA,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC;;AAGlB,IAAA,MAAM,YAAY,GAAG,OAAO,CAC1B,MAAM,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,EAC9E,CAAC,YAAY,CAAC,CACf;;AAGD,IAAA,MAAM,QAAQ,GAAG,WAAW,CAC1B,CAAC,IAAY,KAAI;AACf,QAAA,IAAI,IAAI,KAAK,MAAM,EAAE;AACnB,YAAA,MAAM,CAAC,QAAQ,CAAC,IAAI,GAAG,IAAI;QAC7B;aAAO;YACL,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,EAAE,IAAI,CAAC;YACxC,cAAc,CAAC,IAAI,CAAC;QACtB;AACF,IAAA,CAAC,EACD,CAAC,IAAI,CAAC,CACP;;IAGD,SAAS,CAAC,MAAK;AACb,QAAA,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AACnD,QAAA,MAAM,KAAK,GAAG,IAAI,KAAK,MAAM,GAAG,YAAY,GAAG,UAAU;AACzD,QAAA,MAAM,CAAC,gBAAgB,CAAC,KAAK,EAAE,OAAO,CAAC;QACvC,OAAO,MAAM,MAAM,CAAC,mBAAmB,CAAC,KAAK,EAAE,OAAO,CAAC;AACzD,IAAA,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;;IAGV,MAAM,KAAK,GAAG,OAAO,CACnB,MAAM,WAAW,CAAC,YAAY,EAAE,WAAW,CAAC,EAC5C,CAAC,YAAY,EAAE,WAAW,CAAC,CAC5B;AAED,IAAA,MAAM,YAAY,GAAG,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,IAAI;;;;IAI7D,MAAM,MAAM,GAAG,OAAO,CACpB,MAAM,KAAK,EAAE,MAAM,IAAI,EAAE;;AAEzB,IAAA,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,MAAM,IAAI,EAAE,CAAC,CAAC,CACtC;;IAGD,SAAS,CAAC,MAAK;QACb,IAAI,CAAC,YAAY,EAAE;YACjB,aAAa,CAAC,MAAM,CAAC;YACrB;QACF;QAEA,IAAI,YAAY,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE;YACpC,aAAa,CAAC,QAAQ,CAAC;YACvB;QACF;QAEA,IAAI,SAAS,GAAG,KAAK;QACrB,aAAa,CAAC,UAAU,CAAC;QAEzB,CAAC,YAAW;AACV,YAAA,IAAI;AACF,gBAAA,KAAK,MAAM,KAAK,IAAI,YAAY,CAAC,MAAM,EAAE;oBACvC,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC;AACtD,oBAAA,IAAI,SAAS;wBAAE;oBACf,IAAI,CAAC,MAAM,EAAE;wBACX,aAAa,CAAC,QAAQ,CAAC;AACvB,wBAAA,IAAI,YAAY,CAAC,aAAa,EAAE;AAC9B,4BAAA,QAAQ,CAAC,YAAY,CAAC,aAAa,CAAC;wBACtC;wBACA;oBACF;gBACF;AACA,gBAAA,IAAI,CAAC,SAAS;oBAAE,aAAa,CAAC,QAAQ,CAAC;YACzC;AAAE,YAAA,MAAM;gBACN,IAAI,CAAC,SAAS,EAAE;oBACd,aAAa,CAAC,QAAQ,CAAC;AACvB,oBAAA,IAAI,YAAY,CAAC,aAAa,EAAE;AAC9B,wBAAA,QAAQ,CAAC,YAAY,CAAC,aAAa,CAAC;oBACtC;gBACF;YACF;QACF,CAAC,GAAG;QAEJ,OAAO,MAAK,EAAG,SAAS,GAAG,IAAI,CAAC,CAAC,CAAC;IACpC,CAAC,EAAE,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC,CAAC;;AAGhC,IAAA,IAAI,OAAkB;IAEtB,IAAI,CAAC,YAAY,EAAE;;AAEjB,QAAA,OAAO,GAAG,cAAc,CAAC,QAAQ,CAAC,IAAI,aAAa,CAAC,KAAK,EAAE,IAAI,EAAE,sBAAsB,CAAC;IAC1F;AAAO,SAAA,IAAI,UAAU,KAAK,UAAU,EAAE;;QAEpC,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,IAAI,aAAa,CAAC,cAAc,CAAC;IACpE;AAAO,SAAA,IAAI,UAAU,KAAK,QAAQ,EAAE;;QAElC,OAAO,GAAG,IAAI;IAChB;SAAO;;QAEL,OAAO,GAAG,cAAc,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC;IACrD;;AAGA,IAAA,MAAM,eAAe,GAAG,YAAY,EAAE,MAAM,KAAK,SAAS,GAAG,YAAY,CAAC,MAAM,GAAG,aAAa;AAChG,IAAA,MAAM,WAAW,GAAG,eAAe,KAAK,KAAK,GAAG,SAAS,GAAG,eAAe;AAC3E,IAAA,IAAI,WAAW,IAAI,OAAO,KAAK,IAAI,EAAE;QACnC,OAAO,GAAG,cAAc,CACtB,WAA8D,EAC9D,EAAE,QAAQ,EAAE,OAAO,EAAE,CACtB;IACH;AAEA,IAAA,QACEA,GAAA,CAAC,aAAa,EAAA,EACZ,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,KAAK,EAAE,IAAI,IAAI,EAAE,EACxB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,QAAQ,EAAA,QAAA,EAEjB,OAAO,EAAA,CACM;AAEpB;;;;"}
|
|
@@ -2,6 +2,8 @@ import { type RouteParams } from 'pica-route';
|
|
|
2
2
|
export interface RouteConfig {
|
|
3
3
|
path: string;
|
|
4
4
|
index: number;
|
|
5
|
+
/** Lower values win when route specificity ties. Defaults to 0. */
|
|
6
|
+
order?: number;
|
|
5
7
|
}
|
|
6
8
|
export interface MatchResult {
|
|
7
9
|
index: number;
|
|
@@ -11,6 +13,7 @@ export interface MatchResult {
|
|
|
11
13
|
/**
|
|
12
14
|
* Match a URL path against an array of route configs.
|
|
13
15
|
* Uses pica-route — same matching as vanilla Snice's Router.
|
|
14
|
-
* Routes are sorted by per-segment specificity (static > dynamic > wildcard)
|
|
16
|
+
* Routes are sorted by per-segment specificity (static > dynamic > wildcard),
|
|
17
|
+
* then optional lower-first order, then declaration order.
|
|
15
18
|
*/
|
|
16
19
|
export declare function matchRoutes(routes: RouteConfig[], pathname: string): MatchResult | null;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* snice v7.
|
|
2
|
+
* snice v7.3.0
|
|
3
3
|
* A decorator-driven web component library with routing, controllers, daemons, and 130+ UI components. For better coding-agent results, run npx snice init-ai.
|
|
4
4
|
* (c) 2024
|
|
5
5
|
* Released under the MIT License.
|
|
@@ -45,11 +45,21 @@ function routeSpecificity(spec) {
|
|
|
45
45
|
/**
|
|
46
46
|
* Match a URL path against an array of route configs.
|
|
47
47
|
* Uses pica-route — same matching as vanilla Snice's Router.
|
|
48
|
-
* Routes are sorted by per-segment specificity (static > dynamic > wildcard)
|
|
48
|
+
* Routes are sorted by per-segment specificity (static > dynamic > wildcard),
|
|
49
|
+
* then optional lower-first order, then declaration order.
|
|
49
50
|
*/
|
|
50
51
|
function matchRoutes(routes, pathname) {
|
|
52
|
+
for (const route of routes) {
|
|
53
|
+
if (route.order !== undefined && !Number.isFinite(route.order)) {
|
|
54
|
+
throw new TypeError(`Route order for "${route.path}" must be a finite number.`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
51
57
|
// Sort by specificity (most specific first), same model as the vanilla Router.
|
|
52
|
-
const sorted =
|
|
58
|
+
const sorted = routes
|
|
59
|
+
.map((route, registrationOrder) => ({ ...route, registrationOrder }))
|
|
60
|
+
.sort((a, b) => routeSpecificity(b.path) - routeSpecificity(a.path)
|
|
61
|
+
|| (a.order ?? 0) - (b.order ?? 0)
|
|
62
|
+
|| a.registrationOrder - b.registrationOrder);
|
|
53
63
|
for (const route of sorted) {
|
|
54
64
|
const matcher = new Route(route.path);
|
|
55
65
|
const params = matcher.match(pathname);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"matchRoute.js","sources":["../../src/react/route-specificity.ts","../../src/react/matchRoute.ts"],"sourcesContent":["/**\n * Route specificity scorer for the React binding.\n *\n * IMPORTANT: keep this in exact sync with `src/route-specificity.ts`. The React\n * integration is bundled in isolation (rootDir: src/react) and cannot import\n * across that boundary, so the scorer is mirrored here. The `matchRoutes`\n * resolution tests exercise this copy, so behavioral drift is caught.\n *\n * Scoring is per-segment by ROLE, not string length: a static segment outweighs\n * a dynamic (`:param`) segment, which outweighs a wildcard (`*` / `*name`). So\n * `/post/new` beats `/post/:id`, and a splat always ranks last. Sort callers\n * descending by this score (highest = most specific = first).\n */\nconst STATIC_SEGMENT = 10;\nconst DYNAMIC_SEGMENT = 3;\nconst WILDCARD_SEGMENT = -2;\n\nexport function routeSpecificity(spec: string): number {\n const segments = spec.split('/').filter(Boolean);\n // Base on segment count so a deeper path outranks a shallower one on ties.\n let score = segments.length;\n\n for (const segment of segments) {\n if (segment.startsWith('*')) {\n score += WILDCARD_SEGMENT;\n } else if (segment.startsWith(':')) {\n score += DYNAMIC_SEGMENT;\n } else {\n score += STATIC_SEGMENT;\n }\n }\n\n return score;\n}\n","import { Route, type RouteParams } from 'pica-route';\nimport { routeSpecificity } from './route-specificity';\n\nexport interface RouteConfig {\n path: string;\n index: number;\n}\n\nexport interface MatchResult {\n index: number;\n params: RouteParams;\n path: string;\n}\n\n/**\n * Match a URL path against an array of route configs.\n * Uses pica-route — same matching as vanilla Snice's Router.\n * Routes are sorted by per-segment specificity (static > dynamic > wildcard).\n */\nexport function matchRoutes(routes: RouteConfig[], pathname: string): MatchResult | null {\n // Sort by specificity (most specific first), same model as the vanilla Router.\n const sorted =
|
|
1
|
+
{"version":3,"file":"matchRoute.js","sources":["../../src/react/route-specificity.ts","../../src/react/matchRoute.ts"],"sourcesContent":["/**\n * Route specificity scorer for the React binding.\n *\n * IMPORTANT: keep this in exact sync with `src/route-specificity.ts`. The React\n * integration is bundled in isolation (rootDir: src/react) and cannot import\n * across that boundary, so the scorer is mirrored here. The `matchRoutes`\n * resolution tests exercise this copy, so behavioral drift is caught.\n *\n * Scoring is per-segment by ROLE, not string length: a static segment outweighs\n * a dynamic (`:param`) segment, which outweighs a wildcard (`*` / `*name`). So\n * `/post/new` beats `/post/:id`, and a splat always ranks last. Sort callers\n * descending by this score (highest = most specific = first).\n */\nconst STATIC_SEGMENT = 10;\nconst DYNAMIC_SEGMENT = 3;\nconst WILDCARD_SEGMENT = -2;\n\nexport function routeSpecificity(spec: string): number {\n const segments = spec.split('/').filter(Boolean);\n // Base on segment count so a deeper path outranks a shallower one on ties.\n let score = segments.length;\n\n for (const segment of segments) {\n if (segment.startsWith('*')) {\n score += WILDCARD_SEGMENT;\n } else if (segment.startsWith(':')) {\n score += DYNAMIC_SEGMENT;\n } else {\n score += STATIC_SEGMENT;\n }\n }\n\n return score;\n}\n","import { Route, type RouteParams } from 'pica-route';\nimport { routeSpecificity } from './route-specificity';\n\nexport interface RouteConfig {\n path: string;\n index: number;\n /** Lower values win when route specificity ties. Defaults to 0. */\n order?: number;\n}\n\nexport interface MatchResult {\n index: number;\n params: RouteParams;\n path: string;\n}\n\n/**\n * Match a URL path against an array of route configs.\n * Uses pica-route — same matching as vanilla Snice's Router.\n * Routes are sorted by per-segment specificity (static > dynamic > wildcard),\n * then optional lower-first order, then declaration order.\n */\nexport function matchRoutes(routes: RouteConfig[], pathname: string): MatchResult | null {\n for (const route of routes) {\n if (route.order !== undefined && !Number.isFinite(route.order)) {\n throw new TypeError(`Route order for \"${route.path}\" must be a finite number.`);\n }\n }\n // Sort by specificity (most specific first), same model as the vanilla Router.\n const sorted = routes\n .map((route, registrationOrder) => ({ ...route, registrationOrder }))\n .sort((a, b) =>\n routeSpecificity(b.path) - routeSpecificity(a.path)\n || (a.order ?? 0) - (b.order ?? 0)\n || a.registrationOrder - b.registrationOrder\n );\n\n for (const route of sorted) {\n const matcher = new Route(route.path);\n const params = matcher.match(pathname);\n if (params !== false) {\n return {\n index: route.index,\n params: params as RouteParams,\n path: route.path,\n };\n }\n }\n\n return null;\n}\n"],"names":[],"mappings":";;;;;;;;;;AAAA;;;;;;;;;;;;AAYG;AACH,MAAM,cAAc,GAAG,EAAE;AACzB,MAAM,eAAe,GAAG,CAAC;AACzB,MAAM,gBAAgB,GAAG,EAAE;AAErB,SAAU,gBAAgB,CAAC,IAAY,EAAA;AAC3C,IAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC;;AAEhD,IAAA,IAAI,KAAK,GAAG,QAAQ,CAAC,MAAM;AAE3B,IAAA,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE;AAC9B,QAAA,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE;YAC3B,KAAK,IAAI,gBAAgB;QAC3B;AAAO,aAAA,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE;YAClC,KAAK,IAAI,eAAe;QAC1B;aAAO;YACL,KAAK,IAAI,cAAc;QACzB;IACF;AAEA,IAAA,OAAO,KAAK;AACd;;ACjBA;;;;;AAKG;AACG,SAAU,WAAW,CAAC,MAAqB,EAAE,QAAgB,EAAA;AACjE,IAAA,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE;AAC1B,QAAA,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE;YAC9D,MAAM,IAAI,SAAS,CAAC,CAAA,iBAAA,EAAoB,KAAK,CAAC,IAAI,CAAA,0BAAA,CAA4B,CAAC;QACjF;IACF;;IAEA,MAAM,MAAM,GAAG;AACZ,SAAA,GAAG,CAAC,CAAC,KAAK,EAAE,iBAAiB,MAAM,EAAE,GAAG,KAAK,EAAE,iBAAiB,EAAE,CAAC;SACnE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,KACT,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,IAAI;AAC/C,WAAA,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,IAAI,CAAC;AAC9B,WAAA,CAAC,CAAC,iBAAiB,GAAG,CAAC,CAAC,iBAAiB,CAC7C;AAEH,IAAA,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE;QAC1B,MAAM,OAAO,GAAG,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC;QACrC,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC;AACtC,QAAA,IAAI,MAAM,KAAK,KAAK,EAAE;YACpB,OAAO;gBACL,KAAK,EAAE,KAAK,CAAC,KAAK;AAClB,gBAAA,MAAM,EAAE,MAAqB;gBAC7B,IAAI,EAAE,KAAK,CAAC,IAAI;aACjB;QACH;IACF;AAEA,IAAA,OAAO,IAAI;AACb;;;;"}
|
|
@@ -21,7 +21,7 @@ export const ANALYZER_CONTRACTS = {
|
|
|
21
21
|
"componentModules": 188,
|
|
22
22
|
"componentUtilityModules": 31,
|
|
23
23
|
"reactWrappers": 193,
|
|
24
|
-
"rootExports":
|
|
24
|
+
"rootExports": 118
|
|
25
25
|
},
|
|
26
26
|
"rootExports": [
|
|
27
27
|
"AdoptedOptions",
|
|
@@ -30,6 +30,7 @@ export const ANALYZER_CONTRACTS = {
|
|
|
30
30
|
"Context",
|
|
31
31
|
"ContextAwareFetcher",
|
|
32
32
|
"ContextOptions",
|
|
33
|
+
"ContextProviderOptions",
|
|
33
34
|
"ControllerClass",
|
|
34
35
|
"CreateRequestHandlerOptions",
|
|
35
36
|
"DaemonMap",
|
|
@@ -48,6 +49,7 @@ export const ANALYZER_CONTRACTS = {
|
|
|
48
49
|
"OnOptions",
|
|
49
50
|
"OnScope",
|
|
50
51
|
"PageOptions",
|
|
52
|
+
"PageRouteOptions",
|
|
51
53
|
"PartOptions",
|
|
52
54
|
"Placard",
|
|
53
55
|
"PropertyConverter",
|
|
@@ -98,6 +100,7 @@ export const ANALYZER_CONTRACTS = {
|
|
|
98
100
|
"escapeHtml",
|
|
99
101
|
"getBodyScrollLockCount",
|
|
100
102
|
"getContext",
|
|
103
|
+
"getContextFetch",
|
|
101
104
|
"getController",
|
|
102
105
|
"getSymbol",
|
|
103
106
|
"html",
|