@djangocfg/ui-core 2.1.440 → 2.1.442
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@djangocfg/ui-core",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.442",
|
|
4
4
|
"description": "Pure React UI component library without Next.js dependencies - for Electron, Vite, CRA apps",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ui-components",
|
|
@@ -53,6 +53,16 @@
|
|
|
53
53
|
"import": "./src/hooks/router/adapters/nextjs.tsx",
|
|
54
54
|
"require": "./src/hooks/router/adapters/nextjs.tsx"
|
|
55
55
|
},
|
|
56
|
+
"./adapters/react-router": {
|
|
57
|
+
"types": "./src/hooks/router/adapters/react-router.tsx",
|
|
58
|
+
"import": "./src/hooks/router/adapters/react-router.tsx",
|
|
59
|
+
"require": "./src/hooks/router/adapters/react-router.tsx"
|
|
60
|
+
},
|
|
61
|
+
"./chart": {
|
|
62
|
+
"types": "./src/components/data/chart/index.tsx",
|
|
63
|
+
"import": "./src/components/data/chart/index.tsx",
|
|
64
|
+
"require": "./src/components/data/chart/index.tsx"
|
|
65
|
+
},
|
|
56
66
|
"./lib": {
|
|
57
67
|
"types": "./src/lib/index.ts",
|
|
58
68
|
"import": "./src/lib/index.ts",
|
|
@@ -106,7 +116,7 @@
|
|
|
106
116
|
"check": "tsc --noEmit"
|
|
107
117
|
},
|
|
108
118
|
"peerDependencies": {
|
|
109
|
-
"@djangocfg/i18n": "^2.1.
|
|
119
|
+
"@djangocfg/i18n": "^2.1.442",
|
|
110
120
|
"consola": "^3.4.2",
|
|
111
121
|
"lucide-react": "^0.545.0",
|
|
112
122
|
"moment": "^2.30.1",
|
|
@@ -115,6 +125,7 @@
|
|
|
115
125
|
"react-device-detect": "^2.2.3",
|
|
116
126
|
"react-dom": "^19.2.4",
|
|
117
127
|
"react-hook-form": "^7.69.0",
|
|
128
|
+
"react-router": ">=7",
|
|
118
129
|
"tailwindcss": "^4.1.18",
|
|
119
130
|
"zod": "^4.3.6",
|
|
120
131
|
"zustand": "^5.0.0"
|
|
@@ -122,6 +133,9 @@
|
|
|
122
133
|
"peerDependenciesMeta": {
|
|
123
134
|
"next": {
|
|
124
135
|
"optional": true
|
|
136
|
+
},
|
|
137
|
+
"react-router": {
|
|
138
|
+
"optional": true
|
|
125
139
|
}
|
|
126
140
|
},
|
|
127
141
|
"dependencies": {
|
|
@@ -180,8 +194,8 @@
|
|
|
180
194
|
"@chenglou/pretext": "*"
|
|
181
195
|
},
|
|
182
196
|
"devDependencies": {
|
|
183
|
-
"@djangocfg/i18n": "^2.1.
|
|
184
|
-
"@djangocfg/typescript-config": "^2.1.
|
|
197
|
+
"@djangocfg/i18n": "^2.1.442",
|
|
198
|
+
"@djangocfg/typescript-config": "^2.1.442",
|
|
185
199
|
"@types/node": "^25.2.3",
|
|
186
200
|
"@types/react": "^19.2.15",
|
|
187
201
|
"@types/react-dom": "^19.2.3",
|
package/src/components/index.ts
CHANGED
|
@@ -199,7 +199,13 @@ export type { BalancedTextProps, BalancedFont } from './data/BalancedText';
|
|
|
199
199
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
200
200
|
// Chart Components
|
|
201
201
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
202
|
-
|
|
202
|
+
// Charts are NOT re-exported from this main barrel ON PURPOSE: they pull in the
|
|
203
|
+
// heavy `recharts` dependency (which imports CJS `lodash/get`), and dragging
|
|
204
|
+
// that into every `import { Button } from "@djangocfg/ui-core"` both bloats the
|
|
205
|
+
// graph and breaks Vite dev (native-ESM) CJS-interop on consumers that never use
|
|
206
|
+
// charts. Import charts from the dedicated subpath instead — same pay-for-what-
|
|
207
|
+
// you-use pattern as `@djangocfg/ui-core/lib/dialog-service`:
|
|
208
|
+
// import { ChartContainer, ChartTooltip, … } from "@djangocfg/ui-core/chart";
|
|
203
209
|
|
|
204
210
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
205
211
|
// Feedback
|
|
@@ -47,7 +47,30 @@ import { NextRouterAdapter, NextLinkProvider } from '@djangocfg/ui-core/adapters
|
|
|
47
47
|
> Using `@djangocfg/layouts`? `BaseApp` already mounts both adapters — you don't
|
|
48
48
|
> need this manual wiring.
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
For a **React-Router v7** SPA (Vite / CRA) — mount the React-Router adapter once,
|
|
51
|
+
**inside** the router context (e.g. in the layout-route element, not around
|
|
52
|
+
`<RouterProvider>`). It bridges the router hooks to `useNavigate` and `<Link>` to
|
|
53
|
+
React-Router's `<Link>`, so ui-core navigation drives the data router instead of
|
|
54
|
+
the bare-`pushState` fallback (which would desync the router):
|
|
55
|
+
|
|
56
|
+
```tsx
|
|
57
|
+
// the layout-route element (rendered inside <RouterProvider>)
|
|
58
|
+
import { ReactRouterProvider } from '@djangocfg/ui-core/adapters/react-router';
|
|
59
|
+
|
|
60
|
+
<ReactRouterProvider>
|
|
61
|
+
{/* sidebar / top-bar / <Outlet/> */}
|
|
62
|
+
</ReactRouterProvider>
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
`ReactRouterProvider` composes `ReactRouterAdapter` (router hooks) +
|
|
66
|
+
`ReactRouterLinkProvider` (`<Link>`); mount either individually if you only need
|
|
67
|
+
one. RR's `<Link>` has no `prefetch`-boolean / `scroll` prop, so those ui-core
|
|
68
|
+
`<Link>` props are ignored by this adapter (by design).
|
|
69
|
+
|
|
70
|
+
Both `next` and `react-router` are **optional peer dependencies** — the package
|
|
71
|
+
never imports from `next/*` or `react-router` from the main entry. Each adapter
|
|
72
|
+
lives behind its own sub-path (`/adapters/nextjs`, `/adapters/react-router`), so a
|
|
73
|
+
consumer only pulls in the framework it actually mounts.
|
|
51
74
|
|
|
52
75
|
For other routers (TanStack Router, wouter, Remix, custom transports) — write a ~20-line custom adapter:
|
|
53
76
|
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* React-Router (v7) adapter — bridges our framework-agnostic router hooks
|
|
5
|
+
* to `react-router` so SPA navigations flow through the data router
|
|
6
|
+
* (`createBrowserRouter`) instead of the bare History API fallback.
|
|
7
|
+
*
|
|
8
|
+
* USAGE:
|
|
9
|
+
* Mount once INSIDE the router context — i.e. inside an element that
|
|
10
|
+
* `RouterProvider` renders (a layout-route element / `<Outlet/>` parent),
|
|
11
|
+
* NOT around `<RouterProvider>` itself (that subtree has no router context,
|
|
12
|
+
* so `useNavigate` would throw):
|
|
13
|
+
*
|
|
14
|
+
* ```tsx
|
|
15
|
+
* import { ReactRouterProvider } from '@djangocfg/ui-core/adapters/react-router';
|
|
16
|
+
*
|
|
17
|
+
* function Shell() {
|
|
18
|
+
* return (
|
|
19
|
+
* <ReactRouterProvider>
|
|
20
|
+
* <Layout><Outlet /></Layout>
|
|
21
|
+
* </ReactRouterProvider>
|
|
22
|
+
* );
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* Without this provider, our hooks fall back to the History API adapter —
|
|
27
|
+
* which mutates `window.history` directly and bypasses React-Router's
|
|
28
|
+
* `<Outlet/>` swap, so programmatic `useNavigate` / `<Link>` clicks desync
|
|
29
|
+
* from the router. Mount it in any Vite / React-Router SPA.
|
|
30
|
+
*
|
|
31
|
+
* PEER DEPENDENCY:
|
|
32
|
+
* `react-router` is an OPTIONAL peer of @djangocfg/ui-core. The base package
|
|
33
|
+
* never imports from `react-router`. This sub-path entry does — so it only
|
|
34
|
+
* loads when the consumer explicitly imports `/adapters/react-router`.
|
|
35
|
+
* Next.js / non-RR consumers: don't import this file and `react-router` is
|
|
36
|
+
* never resolved.
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
import { forwardRef, useMemo, type ReactNode } from 'react';
|
|
40
|
+
import { Link as RouterLink, useNavigate } from 'react-router';
|
|
41
|
+
|
|
42
|
+
import {
|
|
43
|
+
RouterAdapterProvider,
|
|
44
|
+
type RouterAdapter,
|
|
45
|
+
type RouterLocation,
|
|
46
|
+
} from '../adapter';
|
|
47
|
+
import {
|
|
48
|
+
LinkProvider,
|
|
49
|
+
type LinkComponent,
|
|
50
|
+
type LinkComponentProps,
|
|
51
|
+
} from '../../../components/navigation/link';
|
|
52
|
+
|
|
53
|
+
const SSR_LOCATION: RouterLocation = Object.freeze({
|
|
54
|
+
pathname: '/',
|
|
55
|
+
search: '',
|
|
56
|
+
hash: '',
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
export interface ReactRouterAdapterProps {
|
|
60
|
+
children: ReactNode;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Wraps a subtree so all `@djangocfg/ui-core/hooks` router calls go through
|
|
65
|
+
* React-Router's data router. `back`/`forward` use the numeric-delta overload
|
|
66
|
+
* of `useNavigate`; `getLocation` reads `window.location` (SSR-guarded).
|
|
67
|
+
*
|
|
68
|
+
* Must be rendered inside the router context (under `RouterProvider`), since
|
|
69
|
+
* `useNavigate` requires it.
|
|
70
|
+
*/
|
|
71
|
+
export function ReactRouterAdapter({ children }: ReactRouterAdapterProps) {
|
|
72
|
+
const navigate = useNavigate();
|
|
73
|
+
|
|
74
|
+
const adapter = useMemo<RouterAdapter>(
|
|
75
|
+
() => ({
|
|
76
|
+
push(url) {
|
|
77
|
+
navigate(url);
|
|
78
|
+
},
|
|
79
|
+
replace(url) {
|
|
80
|
+
navigate(url, { replace: true });
|
|
81
|
+
},
|
|
82
|
+
back() {
|
|
83
|
+
navigate(-1);
|
|
84
|
+
},
|
|
85
|
+
forward() {
|
|
86
|
+
navigate(1);
|
|
87
|
+
},
|
|
88
|
+
getLocation() {
|
|
89
|
+
if (typeof window === 'undefined') return SSR_LOCATION;
|
|
90
|
+
return {
|
|
91
|
+
pathname: window.location.pathname,
|
|
92
|
+
search: window.location.search,
|
|
93
|
+
hash: window.location.hash,
|
|
94
|
+
};
|
|
95
|
+
},
|
|
96
|
+
}),
|
|
97
|
+
[navigate]
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
return (
|
|
101
|
+
<RouterAdapterProvider value={adapter}>{children}</RouterAdapterProvider>
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Maps our agnostic Link API → react-router `<Link>` props. Lives at module
|
|
107
|
+
* scope so the component identity is stable (avoids tree remounts on every
|
|
108
|
+
* render). `href` → `to`; `replace` is forwarded; `prefetch` (a Next-shaped
|
|
109
|
+
* boolean) and `scroll` have no `react-router` equivalent and are dropped.
|
|
110
|
+
*/
|
|
111
|
+
const ReactRouterLinkAdapter: LinkComponent = forwardRef<HTMLAnchorElement, LinkComponentProps>(
|
|
112
|
+
function ReactRouterLinkAdapter({ href, replace, scroll: _scroll, prefetch: _prefetch, children, ...rest }, ref) {
|
|
113
|
+
return (
|
|
114
|
+
<RouterLink to={href} replace={replace} ref={ref} {...rest}>
|
|
115
|
+
{children}
|
|
116
|
+
</RouterLink>
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
export interface ReactRouterLinkProviderProps {
|
|
122
|
+
children: ReactNode;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Wires `<Link>` from `@djangocfg/ui-core/components` to react-router's
|
|
127
|
+
* `<Link>`. Mount alongside `ReactRouterAdapter` (inside the router context)
|
|
128
|
+
* so every ui-core `<Link>` drives client-side routing.
|
|
129
|
+
*/
|
|
130
|
+
export function ReactRouterLinkProvider({ children }: ReactRouterLinkProviderProps) {
|
|
131
|
+
return <LinkProvider value={ReactRouterLinkAdapter}>{children}</LinkProvider>;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export interface ReactRouterProviderProps {
|
|
135
|
+
children: ReactNode;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Convenience composition of `ReactRouterAdapter` (navigation backend) and
|
|
140
|
+
* `ReactRouterLinkProvider` (link component) — mount this ONE component inside
|
|
141
|
+
* the router context to wire ui-core's whole navigation seam to React-Router.
|
|
142
|
+
*/
|
|
143
|
+
export function ReactRouterProvider({ children }: ReactRouterProviderProps) {
|
|
144
|
+
return (
|
|
145
|
+
<ReactRouterAdapter>
|
|
146
|
+
<ReactRouterLinkProvider>{children}</ReactRouterLinkProvider>
|
|
147
|
+
</ReactRouterAdapter>
|
|
148
|
+
);
|
|
149
|
+
}
|