@django-bridge/react 0.4.0-rc.1 → 0.4.0-rc.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +16 -73
- package/dist/index.js +1 -1
- package/package.json +3 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,47 +1,6 @@
|
|
|
1
|
-
import React, { ReactNode, ReactElement,
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
interface Metadata {
|
|
5
|
-
title: string;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
type MessageLevel = "info" | "success" | "warning" | "error";
|
|
9
|
-
interface TextMessage {
|
|
10
|
-
level: MessageLevel;
|
|
11
|
-
text: string;
|
|
12
|
-
}
|
|
13
|
-
interface HTMLMessage {
|
|
14
|
-
level: MessageLevel;
|
|
15
|
-
html: string;
|
|
16
|
-
}
|
|
17
|
-
type Message = TextMessage | HTMLMessage;
|
|
18
|
-
interface ReloadResponse {
|
|
19
|
-
action: "reload";
|
|
20
|
-
}
|
|
21
|
-
interface RedirectResponse {
|
|
22
|
-
action: "redirect";
|
|
23
|
-
path: string;
|
|
24
|
-
}
|
|
25
|
-
interface RenderResponse {
|
|
26
|
-
action: "render";
|
|
27
|
-
overlay: boolean;
|
|
28
|
-
metadata: Metadata;
|
|
29
|
-
view: string;
|
|
30
|
-
props: Record<string, unknown>;
|
|
31
|
-
context: Record<string, unknown>;
|
|
32
|
-
messages: Message[];
|
|
33
|
-
}
|
|
34
|
-
interface CloseOverlayResponse {
|
|
35
|
-
action: "close-overlay";
|
|
36
|
-
messages: Message[];
|
|
37
|
-
}
|
|
38
|
-
interface ServerErrorResponse {
|
|
39
|
-
action: "server-error";
|
|
40
|
-
}
|
|
41
|
-
interface NetworkErrorResponse {
|
|
42
|
-
action: "network-error";
|
|
43
|
-
}
|
|
44
|
-
type DjangoBridgeResponse = ReloadResponse | RedirectResponse | RenderResponse | CloseOverlayResponse | ServerErrorResponse | NetworkErrorResponse;
|
|
1
|
+
import React, { ReactNode, ReactElement, Context } from 'react';
|
|
2
|
+
import { Message, Config as Config$1, Frame, DjangoBridgeResponse } from '@django-bridge/common';
|
|
3
|
+
export { Frame, Message, Metadata, DjangoBridgeResponse as Response } from '@django-bridge/common';
|
|
45
4
|
|
|
46
5
|
interface NavigateOptions {
|
|
47
6
|
pushState?: boolean;
|
|
@@ -88,17 +47,10 @@ declare const Link: React.ForwardRefExoticComponent<React.AnchorHTMLAttributes<H
|
|
|
88
47
|
skipDirtyFormCheck?: boolean;
|
|
89
48
|
} & React.RefAttributes<HTMLAnchorElement>>;
|
|
90
49
|
|
|
91
|
-
declare class Config {
|
|
92
|
-
views: Map<string, FunctionComponent>;
|
|
50
|
+
declare class Config extends Config$1 {
|
|
93
51
|
contextProviders: Map<string, Context<unknown>>;
|
|
94
|
-
telepathRegistry: Telepath;
|
|
95
52
|
constructor();
|
|
96
|
-
addView: <P>(name: string, component: FunctionComponent<P>) => Config;
|
|
97
53
|
addContextProvider: <C>(name: string, context: Context<C>) => Config;
|
|
98
|
-
addAdapter: <Cls>(name: string, ctor: {
|
|
99
|
-
new (...args: any[]): Cls;
|
|
100
|
-
}) => Config;
|
|
101
|
-
unpack: (data: Record<string, unknown>) => Record<string, unknown>;
|
|
102
54
|
}
|
|
103
55
|
|
|
104
56
|
interface FormProps extends React.HTMLProps<HTMLFormElement> {
|
|
@@ -107,26 +59,6 @@ interface FormProps extends React.HTMLProps<HTMLFormElement> {
|
|
|
107
59
|
}
|
|
108
60
|
declare function Form({ children, onSubmit: callerOnSubmit, isDirty: isInitiallyDirty, disableDirtyCheck, ...props }: FormProps): ReactElement;
|
|
109
61
|
|
|
110
|
-
interface Frame<Props = Record<string, unknown>> {
|
|
111
|
-
id: number;
|
|
112
|
-
path: string;
|
|
113
|
-
metadata: Metadata;
|
|
114
|
-
view: string;
|
|
115
|
-
props: Props;
|
|
116
|
-
context: Record<string, unknown>;
|
|
117
|
-
shouldReloadCallback?: (newPath: string, newProps: Props) => boolean;
|
|
118
|
-
}
|
|
119
|
-
interface NavigationController {
|
|
120
|
-
parent: NavigationController | null;
|
|
121
|
-
currentFrame: Frame;
|
|
122
|
-
isLoading: boolean;
|
|
123
|
-
handleResponse: (response: DjangoBridgeResponse, path: string, pushState?: boolean, neverReload?: boolean) => Promise<void>;
|
|
124
|
-
navigate: (url: string, pushState?: boolean) => Promise<void>;
|
|
125
|
-
replacePath: (frameId: number, path: string) => void;
|
|
126
|
-
submitForm: (url: string, data: FormData) => Promise<void>;
|
|
127
|
-
refreshProps: () => Promise<void>;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
62
|
interface RenderFrameProps {
|
|
131
63
|
config: Config;
|
|
132
64
|
frame: Frame;
|
|
@@ -145,10 +77,21 @@ interface DirtyForm {
|
|
|
145
77
|
declare const DirtyFormContext: React.Context<DirtyForm>;
|
|
146
78
|
declare function DirtyFormMarker(): React.ReactElement;
|
|
147
79
|
|
|
80
|
+
interface NavigationController {
|
|
81
|
+
parent: NavigationController | null;
|
|
82
|
+
currentFrame: Frame;
|
|
83
|
+
isLoading: boolean;
|
|
84
|
+
handleResponse: (response: DjangoBridgeResponse, path: string, pushState?: boolean, neverReload?: boolean) => Promise<void>;
|
|
85
|
+
navigate: (url: string, pushState?: boolean) => Promise<void>;
|
|
86
|
+
replacePath: (frameId: number, path: string) => void;
|
|
87
|
+
submitForm: (url: string, data: FormData) => Promise<void>;
|
|
88
|
+
refreshProps: () => Promise<void>;
|
|
89
|
+
}
|
|
90
|
+
|
|
148
91
|
interface AppProps {
|
|
149
92
|
config: Config;
|
|
150
93
|
initialResponse: DjangoBridgeResponse | JSON;
|
|
151
94
|
}
|
|
152
95
|
declare function App({ config, initialResponse }: AppProps): ReactElement;
|
|
153
96
|
|
|
154
|
-
export { App, type AppProps, BuildLinkElement, Config, type DirtyForm, DirtyFormContext, DirtyFormMarker, Form, FormSubmissionStatus, FormWidgetChangeNotificationContext,
|
|
97
|
+
export { App, type AppProps, BuildLinkElement, Config, type DirtyForm, DirtyFormContext, DirtyFormMarker, Form, FormSubmissionStatus, FormWidgetChangeNotificationContext, Link, MessagesContext, type Navigation, NavigationContext, type NavigationController, OverlayContext, RenderFrame, buildLinkElement };
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var he=Object.create;var X=Object.defineProperty;var Re=Object.getOwnPropertyDescriptor;var ye=Object.getOwnPropertyNames;var xe=Object.getPrototypeOf,we=Object.prototype.hasOwnProperty;var Pe=(e,o)=>{for(var t in o)X(e,t,{get:o[t],enumerable:!0})},me=(e,o,t,a)=>{if(o&&typeof o=="object"||typeof o=="function")for(let n of ye(o))!we.call(e,n)&&n!==t&&X(e,n,{get:()=>o[n],enumerable:!(a=Re(o,n))||a.enumerable});return e};var k=(e,o,t)=>(t=e!=null?he(xe(e)):{},me(o||!e||!e.__esModule?X(t,"default",{value:e,enumerable:!0}):t,e)),be=e=>me(X({},"__esModule",{value:!0}),e);var Ee={};Pe(Ee,{App:()=>Me,BuildLinkElement:()=>re,Config:()=>A,DirtyFormContext:()=>b,DirtyFormMarker:()=>V,Form:()=>ne,FormSubmissionStatus:()=>$,FormWidgetChangeNotificationContext:()=>Y,Link:()=>ue,MessagesContext:()=>O,NavigationContext:()=>D,OverlayContext:()=>G,RenderFrame:()=>J,buildLinkElement:()=>te});module.exports=be(Ee);var F=k(require("react"));var oe=k(require("react"));var y=k(require("react")),U=require("react/jsx-runtime"),_=y.default.createContext(()=>{}),b=y.default.createContext({isDirty:!1,requestUnload:()=>Promise.resolve(),unloadRequested:!1,unloadBlocked:!1,confirmUnload:()=>{},cancelUnload:()=>{},unloadConfirmed:!1});function ee({handleBrowserUnload:e=!1,children:o}){let[t,a]=y.default.useState(!1),[n,i]=y.default.useState({cb:()=>{}}),[p,u]=y.default.useState(!1),[c,g]=y.default.useState(!1),d=y.default.useRef(null),C=()=>d.current&&!!d.current.querySelector("div.dirty-form-marker")||!1;y.default.useEffect(()=>{if(e&&c){let x="This page has unsaved changes.",s=R=>C()?(R.returnValue=x,x):"";return window.addEventListener("beforeunload",s),()=>{window.removeEventListener("beforeunload",s)}}return()=>{}},[e,c]);let h=y.default.useContext(_),m=y.default.useCallback(()=>{g(C()),h()},[h]),l=y.default.useMemo(()=>({isDirty:c,requestUnload:()=>c&&C()?(a(!0),new Promise(x=>{i({cb:x})})):Promise.resolve(),unloadRequested:t,unloadBlocked:c&&t,confirmUnload:()=>{t&&(u(!0),n.cb(),a(!1),i({cb:()=>{}}))},cancelUnload:()=>{t&&(a(!1),i({cb:()=>{}}))},unloadConfirmed:p}),[c,n,p,t]);return(0,U.jsx)("div",{ref:d,children:(0,U.jsx)(_.Provider,{value:m,children:(0,U.jsx)(b.Provider,{value:l,children:o})})})}function V(){let e=y.default.useContext(_);return y.default.useEffect(e),(0,U.jsx)("div",{className:"dirty-form-marker",style:{display:"none"}})}var S=k(require("react")),G=S.default.createContext({overlay:!1,closeRequested:!1,requestClose:()=>{console.error("OverlayContext.requestClose() called from outside an overlay")},onCloseCompleted:()=>{console.error("OverlayContext.onCloseCompleted() called from outside an overlay")}}),D=S.default.createContext({frameId:0,path:"/",props:{},context:{},navigate:()=>(console.error("navigate() called from outside a Django Bridge Browser"),Promise.resolve()),replacePath:()=>{console.error("replacePath() called from outside a Django Bridge Browser")},submitForm:()=>(console.error("submitForm() called from outside a Django Bridge Browser"),Promise.resolve()),openOverlay:()=>{throw console.error("openOverlay() called from outside a Django Bridge Browser"),new Error("Modal cannot be opened here")},refreshProps:()=>(console.error("refreshProps() called from outside a Django Bridge Browser"),Promise.resolve())}),Y=S.default.createContext(()=>{}),$=S.default.createContext(!1),O=S.default.createContext({messages:[],pushMessage:()=>{}});var B=require("react/jsx-runtime");function Fe({config:e,frame:o}){let t=e.views.get(o.view);if(!t)return(0,B.jsxs)("p",{children:["Unknown view '",o.view,"'"]});let a=(0,B.jsx)(t,{...o.props});return e.contextProviders.forEach((n,i)=>{a=(0,B.jsx)(n.Provider,{value:o.context[i],children:a})}),(0,B.jsx)("div",{children:a},o.id)}var J=Fe;var z=require("react/jsx-runtime");function ke({config:e,navigationController:o,openOverlay:t}){let{currentFrame:a,navigate:n,replacePath:i,submitForm:p,refreshProps:u}=o,{isDirty:c,requestUnload:g,cancelUnload:d}=oe.default.useContext(b),C=oe.default.useMemo(()=>({frameId:a.id,path:a.path,props:a.props,context:a.context,navigate:(h,m={})=>!c||m.skipDirtyFormCheck===!0?(m.skipDirtyFormCheck===!0&&d(),n(h,m.pushState)):g().then(()=>n(h,m.pushState)),replacePath:i,submitForm:p,openOverlay:t,refreshProps:u}),[a,i,p,t,c,g,d,n,u]);return(0,z.jsx)(D.Provider,{value:C,children:(0,z.jsx)("div",{children:(0,z.jsx)(J,{config:e,frame:a})},a.id)})}var K=ke;async function q(e,o){let t,a={"X-Requested-With":"DjangoBridge"};o&&(a["X-DjangoBridge-Overlay"]="true");try{t=await fetch(e,{headers:a})}catch{return{action:"network-error"}}return t.status===500?{action:"server-error"}:t.headers.get("X-DjangoBridge-Action")?t.json():{action:"reload"}}async function pe(e,o,t){let a,n={"X-Requested-With":"DjangoBridge"};t&&(n["X-DjangoBridge-Overlay"]="true");try{a=await fetch(e,{method:"post",headers:n,body:o})}catch{return{action:"network-error"}}return a.status===500?{action:"server-error"}:a.headers.get("X-DjangoBridge-Action")?a.json():{action:"reload"}}var v=require("react");var Q=1;function Z(e,o,t,a,n={}){Q+=1;let[i,p]=(0,v.useState)({id:Q,path:a,metadata:{title:"Loading"},view:"loading",props:{},context:{}}),u=(0,v.useCallback)((r,f,w,P,M,N,H=!0,ve=!0)=>{let ie=i.id,se=w!==i.view||ve;if(se&&(Q+=1,ie=Q),!e&&(document.title=f.title,H)){let ce=0,Ce=window.scrollY,de=window.history?.state;de?.prevPath===r&&(ce=de.prevScrollPosition??0),window.history.pushState({prevPath:window.location.pathname,prevScrollPosition:Ce},"",r),window.scrollTo(0,ce)}let le={id:ie,path:r,metadata:f,view:w,props:P,context:M};p(le),n.onNavigation&&n.onNavigation(le,se,N)},[n,i.id,i.view,e]),[c,g]=(0,v.useState)(null),d=(0,v.useCallback)((r,f,w=!0,P=!1)=>{if(r.action==="reload")if(!e)window.location.href=f;else return e.handleResponse(r,f);else{if(r.action==="redirect")return g(r.path),Promise.resolve();if(r.action==="render"){if(e&&!r.overlay)return e.handleResponse(r,f);let M=o(r.props),N=o(r.context),H=!P;H&&r.view===i.view&&i.shouldReloadCallback&&(H=i.shouldReloadCallback(f,M)),u(f,r.metadata,r.view,M,N,r.messages,w,H)}else if(r.action==="close-overlay")n.onOverlayClose&&n.onOverlayClose(r.messages);else{if(r.action==="server-error")return n.onServerError&&n.onServerError("server"),Promise.reject();if(r.action==="network-error")return n.onServerError&&n.onServerError("network"),Promise.reject()}}return Promise.resolve()},[n,i,e,u,o]),C=(0,v.useRef)(1),h=(0,v.useRef)(1),m=(0,v.useCallback)(async(r,f,w,P=!1)=>{C.current+=1;let M=C.current,N=await r();M<h.current||(h.current=M,N!==null&&await d(N,f,w,P))},[d]),l=(0,v.useCallback)((r,f=!0)=>{let w=r;if(!r.startsWith("/")){let P=new URL(r);if(P.origin!==window.location.origin)return window.location.href=r,Promise.resolve();w=P.pathname+P.search}return m(()=>q(w,!!e),w,f)},[m,e]),x=(0,v.useCallback)((r,f)=>{r===i.id&&(i.path=f,e||history.replaceState({},"",i.path))},[i,e]),s=(0,v.useCallback)((r,f)=>m(()=>pe(r,f,!!e),r,!0),[m,e]),R=(0,v.useCallback)(()=>m(()=>q(i.path,!!e),i.path,!1,!0),[i.path,m,e]);return(0,v.useEffect)(()=>{d(t,a,!1)},[]),(0,v.useEffect)(()=>{c&&(g(null),l(c))},[l,c]),{parent:e,currentFrame:i,isLoading:i.view==="loading",handleResponse:d,navigate:l,replacePath:x,submitForm:s,refreshProps:R}}var I=k(require("react"));var ge=require("react/jsx-runtime");function te({children:e,href:o,skipDirtyFormCheck:t=!1,...a},{navigate:n},i){return(0,ge.jsx)("a",{onClick:u=>{o&&(u.preventDefault(),n(o,{skipDirtyFormCheck:t}))},href:o||"#",ref:i,...a,children:e})}var re=I.default.createContext(te),De=I.default.forwardRef((e,o)=>{let t=I.default.useContext(D);return I.default.useContext(re)(e,t,o)}),ue=De;var fe=k(require("telepath-unpack")),A=class{views;contextProviders;telepathRegistry;constructor(){this.views=new Map,this.contextProviders=new Map,this.telepathRegistry=new fe.default,this.addAdapter("Date",Date)}addView=(o,t)=>(this.views.set(o,t),this);addContextProvider=(o,t)=>(this.contextProviders.set(o,t),this);addAdapter=(o,t)=>(this.telepathRegistry.register(o,t),this);unpack=o=>this.telepathRegistry.unpack(o)};var L=k(require("react"));var j=require("react/jsx-runtime");function ne({children:e,onSubmit:o,isDirty:t=!1,disableDirtyCheck:a=!1,...n}){let{submitForm:i,navigate:p}=L.default.useContext(D),[u,c]=L.default.useState(!1),[g,d]=L.default.useState(t),{cancelUnload:C}=L.default.useContext(b),h=l=>{if(g&&C(),!(o&&(o(l),l.defaultPrevented))&&l.target instanceof HTMLFormElement){if(u){l.preventDefault();return}let x=new FormData(l.target);if(l.nativeEvent instanceof SubmitEvent&&l.nativeEvent.submitter){let{submitter:s}=l.nativeEvent;(s instanceof HTMLButtonElement||s instanceof HTMLInputElement)&&s.name&&s.value&&x.set(s.name,s.value)}if(l.target.method==="post")l.preventDefault(),c(!0),i(l.target.action,x).catch(()=>c(!1));else if(l.target.method==="get"){l.preventDefault();let s=Array.from(x.entries()).map(r=>`${encodeURIComponent(r[0])}=${encodeURIComponent(r[1])}`).join("&"),R=l.target.action+(l.target.action.indexOf("?")===-1?"?":"&")+s;c(!0),p(R).catch(()=>c(!1))}}},m=L.default.useCallback(()=>{d(!0)},[]);return(0,j.jsxs)("form",{onSubmit:h,...n,children:[g&&!a&&(0,j.jsx)(V,{}),(0,j.jsx)($.Provider,{value:u,children:(0,j.jsx)(Y.Provider,{value:m,children:e})})]})}var W=k(require("react"));var T=require("react/jsx-runtime");function ae({config:e,initialResponse:o,initialPath:t,parentNavigationContoller:a,render:n,requestClose:i,closeRequested:p,onCloseCompleted:u,onServerError:c}){let{pushMessage:g}=W.default.useContext(O),d=Z(a,e.unpack,o,t,{onNavigation:(l,x,s)=>{s.forEach(g)},onOverlayClose:l=>{l.forEach(g),i()},onServerError:c}),C=W.default.useContext(b),h=W.default.useCallback(({skipDirtyFormCheck:l=!1}={})=>{!l&&C.isDirty?C.requestUnload().then(()=>i()):i()},[C,i]),m=W.default.useMemo(()=>({overlay:!0,closeRequested:p,requestClose:h,onCloseCompleted:u}),[p,u,h]);return d.isLoading?(0,T.jsx)(T.Fragment,{}):(0,T.jsx)(G.Provider,{value:m,children:n((0,T.jsx)(K,{config:e,navigationController:d,openOverlay:()=>{}}))})}var E=require("react/jsx-runtime");function Me({config:e,initialResponse:o}){let[t,a]=F.default.useState([]),n=F.default.useCallback(s=>{a(t.concat([s]))},[t]),i=F.default.useCallback(s=>{s==="server"?n({level:"error",text:"A server error occurred. Please try again later."}):s==="network"&&n({level:"error",text:"A network error occurred. Please check your internet connection or try again later."})},[n]),[p,u]=F.default.useState(null),[c,g]=F.default.useState(!1),d=F.default.useRef(null),C=(s,R,r)=>{R&&(g(!0),d.current=null),R?a(r):r.forEach(n)},h=window.location.pathname+window.location.search+window.location.hash,m=Z(null,e.unpack,o,h,{onNavigation:C,onServerError:i});F.default.useEffect(()=>{let s=document.querySelector(".django-bridge-load");s instanceof HTMLElement&&(s.classList.add("django-bridge-load--hidden"),setTimeout(()=>{s.remove()},200));let R=()=>{m.navigate(document.location.pathname,!1)};return window.addEventListener("popstate",R),()=>{window.removeEventListener("popstate",R)}},[]);let l=async(s,R,{onClose:r}={})=>{let f=await q(s,!0);r&&(d.current=r),g(!1),u({render:R,initialResponse:f,initialPath:s})},x=F.default.useMemo(()=>({messages:t,pushMessage:n}),[t,n]);return(0,E.jsx)(ee,{handleBrowserUnload:!0,children:(0,E.jsxs)(O.Provider,{value:x,children:[p&&(0,E.jsx)(ee,{children:(0,E.jsx)(ae,{config:e,initialResponse:p.initialResponse,initialPath:p.initialPath,parentNavigationContoller:m,render:s=>p.render(s),requestClose:()=>g(!0),closeRequested:c,onCloseCompleted:()=>{u(null),g(!1),d.current&&(d.current(),d.current=null)},onServerError:i})}),!m.isLoading&&(0,E.jsx)(K,{config:e,navigationController:m,openOverlay:(s,R,r)=>void l(s,R,r)})]})})}0&&(module.exports={App,BuildLinkElement,Config,DirtyFormContext,DirtyFormMarker,Form,FormSubmissionStatus,FormWidgetChangeNotificationContext,Link,MessagesContext,NavigationContext,OverlayContext,RenderFrame,buildLinkElement});
|
|
1
|
+
"use strict";var xe=Object.create;var V=Object.defineProperty;var ye=Object.getOwnPropertyDescriptor;var he=Object.getOwnPropertyNames;var Re=Object.getPrototypeOf,Pe=Object.prototype.hasOwnProperty;var Fe=(e,t)=>{for(var a in t)V(e,a,{get:t[a],enumerable:!0})},me=(e,t,a,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of he(t))!Pe.call(e,r)&&r!==a&&V(e,r,{get:()=>t[r],enumerable:!(s=ye(t,r))||s.enumerable});return e};var M=(e,t,a)=>(a=e!=null?xe(Re(e)):{},me(t||!e||!e.__esModule?V(a,"default",{value:e,enumerable:!0}):a,e)),be=e=>me(V({},"__esModule",{value:!0}),e);var Ee={};Fe(Ee,{App:()=>Me,BuildLinkElement:()=>re,Config:()=>A,DirtyFormContext:()=>b,DirtyFormMarker:()=>$,Form:()=>ne,FormSubmissionStatus:()=>K,FormWidgetChangeNotificationContext:()=>z,Link:()=>ue,MessagesContext:()=>O,NavigationContext:()=>k,OverlayContext:()=>J,RenderFrame:()=>Q,buildLinkElement:()=>te});module.exports=be(Ee);var w=M(require("react")),pe=require("@django-bridge/common");var g=require("react"),q=require("@django-bridge/common"),G=1;function Y(e,t,a,s,r={}){G+=1;let[n,u]=(0,g.useState)({id:G,path:s,metadata:{title:"Loading"},view:"loading",props:{},context:{}}),f=(0,g.useCallback)((o,p,P,F,D,N,j=!0,ge=!0)=>{let ie=n.id,se=P!==n.view||ge;if(se&&(G+=1,ie=G),!e&&(document.title=p.title,j)){let ce=0,Ce=window.scrollY,de=window.history?.state;de?.prevPath===o&&(ce=de.prevScrollPosition??0),window.history.pushState({prevPath:window.location.pathname,prevScrollPosition:Ce},"",o),window.scrollTo(0,ce)}let le={id:ie,path:o,metadata:p,view:P,props:F,context:D};u(le),r.onNavigation&&r.onNavigation(le,se,N)},[r,n.id,n.view,e]),[c,v]=(0,g.useState)(null),d=(0,g.useCallback)((o,p,P=!0,F=!1)=>{if(o.action==="reload")if(!e)window.location.href=p;else return e.handleResponse(o,p);else{if(o.action==="redirect")return v(o.path),Promise.resolve();if(o.action==="render"){if(e&&!o.overlay)return e.handleResponse(o,p);let D=t(o.props),N=t(o.context),j=!F;j&&o.view===n.view&&n.shouldReloadCallback&&(j=n.shouldReloadCallback(p,D)),f(p,o.metadata,o.view,D,N,o.messages,P,j)}else if(o.action==="close-overlay")r.onOverlayClose&&r.onOverlayClose(o.messages);else{if(o.action==="server-error")return r.onServerError&&r.onServerError("server"),Promise.reject();if(o.action==="network-error")return r.onServerError&&r.onServerError("network"),Promise.reject()}}return Promise.resolve()},[r,n,e,f,t]),C=(0,g.useRef)(1),x=(0,g.useRef)(1),m=(0,g.useCallback)(async(o,p,P,F=!1)=>{C.current+=1;let D=C.current,N=await o();D<x.current||(x.current=D,N!==null&&await d(N,p,P,F))},[d]),l=(0,g.useCallback)((o,p=!0)=>{let P=o;if(!o.startsWith("/")){let F=new URL(o);if(F.origin!==window.location.origin)return window.location.href=o,Promise.resolve();P=F.pathname+F.search}return m(()=>(0,q.djangoGet)(P,!!e),P,p)},[m,e]),R=(0,g.useCallback)((o,p)=>{o===n.id&&(n.path=p,e||history.replaceState({},"",n.path))},[n,e]),i=(0,g.useCallback)((o,p)=>m(()=>(0,q.djangoPost)(o,p,!!e),o,!0),[m,e]),y=(0,g.useCallback)(()=>m(()=>(0,q.djangoGet)(n.path,!!e),n.path,!1,!0),[n.path,m,e]);return(0,g.useEffect)(()=>{d(a,s,!1)},[]),(0,g.useEffect)(()=>{c&&(v(null),l(c))},[l,c]),{parent:e,currentFrame:n,isLoading:n.view==="loading",handleResponse:d,navigate:l,replacePath:R,submitForm:i,refreshProps:y}}var h=M(require("react")),H=require("react/jsx-runtime"),_=h.default.createContext(()=>{}),b=h.default.createContext({isDirty:!1,requestUnload:()=>Promise.resolve(),unloadRequested:!1,unloadBlocked:!1,confirmUnload:()=>{},cancelUnload:()=>{},unloadConfirmed:!1});function ee({handleBrowserUnload:e=!1,children:t}){let[a,s]=h.default.useState(!1),[r,n]=h.default.useState({cb:()=>{}}),[u,f]=h.default.useState(!1),[c,v]=h.default.useState(!1),d=h.default.useRef(null),C=()=>d.current&&!!d.current.querySelector("div.dirty-form-marker")||!1;h.default.useEffect(()=>{if(e&&c){let R="This page has unsaved changes.",i=y=>C()?(y.returnValue=R,R):"";return window.addEventListener("beforeunload",i),()=>{window.removeEventListener("beforeunload",i)}}return()=>{}},[e,c]);let x=h.default.useContext(_),m=h.default.useCallback(()=>{v(C()),x()},[x]),l=h.default.useMemo(()=>({isDirty:c,requestUnload:()=>c&&C()?(s(!0),new Promise(R=>{n({cb:R})})):Promise.resolve(),unloadRequested:a,unloadBlocked:c&&a,confirmUnload:()=>{a&&(f(!0),r.cb(),s(!1),n({cb:()=>{}}))},cancelUnload:()=>{a&&(s(!1),n({cb:()=>{}}))},unloadConfirmed:u}),[c,r,u,a]);return(0,H.jsx)("div",{ref:d,children:(0,H.jsx)(_.Provider,{value:m,children:(0,H.jsx)(b.Provider,{value:l,children:t})})})}function $(){let e=h.default.useContext(_);return h.default.useEffect(e),(0,H.jsx)("div",{className:"dirty-form-marker",style:{display:"none"}})}var oe=M(require("react"));var S=M(require("react")),J=S.default.createContext({overlay:!1,closeRequested:!1,requestClose:()=>{console.error("OverlayContext.requestClose() called from outside an overlay")},onCloseCompleted:()=>{console.error("OverlayContext.onCloseCompleted() called from outside an overlay")}}),k=S.default.createContext({frameId:0,path:"/",props:{},context:{},navigate:()=>(console.error("navigate() called from outside a Django Bridge Browser"),Promise.resolve()),replacePath:()=>{console.error("replacePath() called from outside a Django Bridge Browser")},submitForm:()=>(console.error("submitForm() called from outside a Django Bridge Browser"),Promise.resolve()),openOverlay:()=>{throw console.error("openOverlay() called from outside a Django Bridge Browser"),new Error("Modal cannot be opened here")},refreshProps:()=>(console.error("refreshProps() called from outside a Django Bridge Browser"),Promise.resolve())}),z=S.default.createContext(()=>{}),K=S.default.createContext(!1),O=S.default.createContext({messages:[],pushMessage:()=>{}});var L=require("react/jsx-runtime");function we({config:e,frame:t}){let a=e.views.get(t.view);if(!a)return(0,L.jsxs)("p",{children:["Unknown view '",t.view,"'"]});let s=(0,L.jsx)(a,{...t.props});return e.contextProviders.forEach((r,n)=>{s=(0,L.jsx)(r.Provider,{value:t.context[n],children:s})}),(0,L.jsx)("div",{children:s},t.id)}var Q=we;var X=require("react/jsx-runtime");function ke({config:e,navigationController:t,openOverlay:a}){let{currentFrame:s,navigate:r,replacePath:n,submitForm:u,refreshProps:f}=t,{isDirty:c,requestUnload:v,cancelUnload:d}=oe.default.useContext(b),C=oe.default.useMemo(()=>({frameId:s.id,path:s.path,props:s.props,context:s.context,navigate:(x,m={})=>!c||m.skipDirtyFormCheck===!0?(m.skipDirtyFormCheck===!0&&d(),r(x,m.pushState)):v().then(()=>r(x,m.pushState)),replacePath:n,submitForm:u,openOverlay:a,refreshProps:f}),[s,n,u,a,c,v,d,r,f]);return(0,X.jsx)(k.Provider,{value:C,children:(0,X.jsx)("div",{children:(0,X.jsx)(Q,{config:e,frame:s})},s.id)})}var Z=ke;var I=M(require("react"));var fe=require("react/jsx-runtime");function te({children:e,href:t,skipDirtyFormCheck:a=!1,...s},{navigate:r},n){return(0,fe.jsx)("a",{onClick:f=>{t&&(f.preventDefault(),r(t,{skipDirtyFormCheck:a}))},href:t||"#",ref:n,...s,children:e})}var re=I.default.createContext(te),De=I.default.forwardRef((e,t)=>{let a=I.default.useContext(k);return I.default.useContext(re)(e,a,t)}),ue=De;var ve=require("@django-bridge/common"),A=class extends ve.Config{contextProviders;constructor(){super(),this.contextProviders=new Map}addContextProvider=(t,a)=>(this.contextProviders.set(t,a),this)};var B=M(require("react"));var T=require("react/jsx-runtime");function ne({children:e,onSubmit:t,isDirty:a=!1,disableDirtyCheck:s=!1,...r}){let{submitForm:n,navigate:u}=B.default.useContext(k),[f,c]=B.default.useState(!1),[v,d]=B.default.useState(a),{cancelUnload:C}=B.default.useContext(b),x=l=>{if(v&&C(),!(t&&(t(l),l.defaultPrevented))&&l.target instanceof HTMLFormElement){if(f){l.preventDefault();return}let R=new FormData(l.target);if(l.nativeEvent instanceof SubmitEvent&&l.nativeEvent.submitter){let{submitter:i}=l.nativeEvent;(i instanceof HTMLButtonElement||i instanceof HTMLInputElement)&&i.name&&i.value&&R.set(i.name,i.value)}if(l.target.method==="post")l.preventDefault(),c(!0),n(l.target.action,R).catch(()=>c(!1));else if(l.target.method==="get"){l.preventDefault();let i=Array.from(R.entries()).map(o=>`${encodeURIComponent(o[0])}=${encodeURIComponent(o[1])}`).join("&"),y=l.target.action+(l.target.action.indexOf("?")===-1?"?":"&")+i;c(!0),u(y).catch(()=>c(!1))}}},m=B.default.useCallback(()=>{d(!0)},[]);return(0,T.jsxs)("form",{onSubmit:x,...r,children:[v&&!s&&(0,T.jsx)($,{}),(0,T.jsx)(K.Provider,{value:f,children:(0,T.jsx)(z.Provider,{value:m,children:e})})]})}var W=M(require("react"));var U=require("react/jsx-runtime");function ae({config:e,initialResponse:t,initialPath:a,parentNavigationContoller:s,render:r,requestClose:n,closeRequested:u,onCloseCompleted:f,onServerError:c}){let{pushMessage:v}=W.default.useContext(O),d=Y(s,e.unpack,t,a,{onNavigation:(l,R,i)=>{i.forEach(v)},onOverlayClose:l=>{l.forEach(v),n()},onServerError:c}),C=W.default.useContext(b),x=W.default.useCallback(({skipDirtyFormCheck:l=!1}={})=>{!l&&C.isDirty?C.requestUnload().then(()=>n()):n()},[C,n]),m=W.default.useMemo(()=>({overlay:!0,closeRequested:u,requestClose:x,onCloseCompleted:f}),[u,f,x]);return d.isLoading?(0,U.jsx)(U.Fragment,{}):(0,U.jsx)(J.Provider,{value:m,children:r((0,U.jsx)(Z,{config:e,navigationController:d,openOverlay:()=>{}}))})}var E=require("react/jsx-runtime");function Me({config:e,initialResponse:t}){let[a,s]=w.default.useState([]),r=w.default.useCallback(i=>{s(a.concat([i]))},[a]),n=w.default.useCallback(i=>{i==="server"?r({level:"error",text:"A server error occurred. Please try again later."}):i==="network"&&r({level:"error",text:"A network error occurred. Please check your internet connection or try again later."})},[r]),[u,f]=w.default.useState(null),[c,v]=w.default.useState(!1),d=w.default.useRef(null),C=(i,y,o)=>{y&&(v(!0),d.current=null),y?s(o):o.forEach(r)},x=window.location.pathname+window.location.search+window.location.hash,m=Y(null,e.unpack,t,x,{onNavigation:C,onServerError:n});w.default.useEffect(()=>{let i=document.querySelector(".django-bridge-load");i instanceof HTMLElement&&(i.classList.add("django-bridge-load--hidden"),setTimeout(()=>{i.remove()},200));let y=()=>{m.navigate(document.location.pathname,!1)};return window.addEventListener("popstate",y),()=>{window.removeEventListener("popstate",y)}},[]);let l=async(i,y,{onClose:o}={})=>{let p=await(0,pe.djangoGet)(i,!0);o&&(d.current=o),v(!1),f({render:y,initialResponse:p,initialPath:i})},R=w.default.useMemo(()=>({messages:a,pushMessage:r}),[a,r]);return(0,E.jsx)(ee,{handleBrowserUnload:!0,children:(0,E.jsxs)(O.Provider,{value:R,children:[u&&(0,E.jsx)(ee,{children:(0,E.jsx)(ae,{config:e,initialResponse:u.initialResponse,initialPath:u.initialPath,parentNavigationContoller:m,render:i=>u.render(i),requestClose:()=>v(!0),closeRequested:c,onCloseCompleted:()=>{f(null),v(!1),d.current&&(d.current(),d.current=null)},onServerError:n})}),!m.isLoading&&(0,E.jsx)(Z,{config:e,navigationController:m,openOverlay:(i,y,o)=>void l(i,y,o)})]})})}0&&(module.exports={App,BuildLinkElement,Config,DirtyFormContext,DirtyFormMarker,Form,FormSubmissionStatus,FormWidgetChangeNotificationContext,Link,MessagesContext,NavigationContext,OverlayContext,RenderFrame,buildLinkElement});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@django-bridge/react",
|
|
3
|
-
"version": "0.4.0-rc.
|
|
3
|
+
"version": "0.4.0-rc.7",
|
|
4
4
|
"description": "The simple way to build Django applications with modern React frontends",
|
|
5
5
|
"repository": "https://github.com/django-bridge/django-bridge",
|
|
6
6
|
"license": "BSD-3-Clause",
|
|
@@ -27,7 +27,8 @@
|
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"react": "^18.2.0",
|
|
30
|
-
"telepath-unpack": "^0.0.4"
|
|
30
|
+
"telepath-unpack": "^0.0.4",
|
|
31
|
+
"@django-bridge/common": "*"
|
|
31
32
|
},
|
|
32
33
|
"devDependencies": {
|
|
33
34
|
"@types/node": "^12.0.0",
|