@django-bridge/react 0.5.0 → 0.6.0-rc.2
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 +33 -9
- package/dist/index.js +1 -1
- package/package.json +2 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,14 +1,31 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
import Telepath from 'telepath-unpack';
|
|
1
|
+
import React, { ReactNode, ReactElement, FunctionComponent, Context } from 'react';
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
interface PackedValuesById {
|
|
4
|
+
[id: string]: any;
|
|
5
|
+
}
|
|
6
|
+
interface ValuesById {
|
|
7
|
+
[id: string]: any;
|
|
8
|
+
}
|
|
9
|
+
interface ConstructorRegistry {
|
|
10
|
+
[name: string]: new (...args: any[]) => any;
|
|
11
|
+
}
|
|
12
|
+
declare class Telepath {
|
|
13
|
+
constructors: ConstructorRegistry;
|
|
14
|
+
constructor();
|
|
15
|
+
register(name: string, constructor: new (...args: any[]) => any): void;
|
|
16
|
+
unpack(objData: any): any;
|
|
17
|
+
scanForIds(objData: any, packedValuesById: PackedValuesById): void;
|
|
18
|
+
unpackWithRefs(objData: any, packedValuesById: PackedValuesById, valuesById: ValuesById): any;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
declare class Config$1<V> {
|
|
22
|
+
views: Map<string, V>;
|
|
6
23
|
telepathRegistry: Telepath;
|
|
7
24
|
constructor();
|
|
8
|
-
addView: <P>(name: string, component:
|
|
25
|
+
addView: <P>(name: string, component: V) => Config$1<V>;
|
|
9
26
|
addAdapter: <Cls>(name: string, ctor: {
|
|
10
27
|
new (...args: any[]): Cls;
|
|
11
|
-
}) => Config$1
|
|
28
|
+
}) => Config$1<V>;
|
|
12
29
|
unpack: (data: Record<string, unknown>) => Record<string, unknown>;
|
|
13
30
|
}
|
|
14
31
|
|
|
@@ -54,14 +71,16 @@ interface NetworkErrorResponse {
|
|
|
54
71
|
}
|
|
55
72
|
type DjangoBridgeResponse = ReloadResponse | RedirectResponse | RenderResponse | CloseOverlayResponse | ServerErrorResponse | NetworkErrorResponse;
|
|
56
73
|
|
|
74
|
+
type ShouldReloadCallback = (newPath: string, newProps: Record<string, unknown>) => boolean;
|
|
57
75
|
interface Frame<Props = Record<string, unknown>> {
|
|
58
76
|
id: number;
|
|
77
|
+
originalId: number;
|
|
59
78
|
path: string;
|
|
60
79
|
metadata: Metadata;
|
|
61
80
|
view: string;
|
|
62
81
|
props: Props;
|
|
63
82
|
context: Record<string, unknown>;
|
|
64
|
-
shouldReloadCallback?:
|
|
83
|
+
shouldReloadCallback?: ShouldReloadCallback;
|
|
65
84
|
}
|
|
66
85
|
|
|
67
86
|
interface NavigateOptions {
|
|
@@ -82,6 +101,7 @@ interface OverlayContextType {
|
|
|
82
101
|
declare const OverlayContext: React.Context<OverlayContextType>;
|
|
83
102
|
interface Navigation {
|
|
84
103
|
frameId: number;
|
|
104
|
+
originalFrameId: number;
|
|
85
105
|
path: string;
|
|
86
106
|
props: Record<string, unknown>;
|
|
87
107
|
context: Record<string, unknown>;
|
|
@@ -91,6 +111,7 @@ interface Navigation {
|
|
|
91
111
|
openOverlay: (path: string, render: (content: ReactNode) => ReactNode, options?: OpenOverlayOptions) => void;
|
|
92
112
|
refreshProps: () => Promise<void>;
|
|
93
113
|
isNavigating: boolean;
|
|
114
|
+
setShouldReloadCallback: (callback: ShouldReloadCallback) => void;
|
|
94
115
|
}
|
|
95
116
|
declare const NavigationContext: React.Context<Navigation>;
|
|
96
117
|
declare const FormWidgetChangeNotificationContext: React.Context<() => void>;
|
|
@@ -110,7 +131,7 @@ declare const Link: React.ForwardRefExoticComponent<React.AnchorHTMLAttributes<H
|
|
|
110
131
|
skipDirtyFormCheck?: boolean;
|
|
111
132
|
} & React.RefAttributes<HTMLAnchorElement>>;
|
|
112
133
|
|
|
113
|
-
declare class Config extends Config$1 {
|
|
134
|
+
declare class Config extends Config$1<FunctionComponent> {
|
|
114
135
|
contextProviders: Map<string, Context<unknown>>;
|
|
115
136
|
constructor();
|
|
116
137
|
addContextProvider: <C>(name: string, context: Context<C>) => Config;
|
|
@@ -140,6 +161,9 @@ interface DirtyForm {
|
|
|
140
161
|
declare const DirtyFormContext: React.Context<DirtyForm>;
|
|
141
162
|
declare function DirtyFormMarker(): React.ReactElement;
|
|
142
163
|
|
|
164
|
+
declare function useAutoRefresh(enabled: boolean, interval: number): void;
|
|
165
|
+
declare function useShouldReloadCallback(callback: ShouldReloadCallback, deps: React.DependencyList): void;
|
|
166
|
+
|
|
143
167
|
interface NavigationController {
|
|
144
168
|
parent: NavigationController | null;
|
|
145
169
|
currentFrame: Frame;
|
|
@@ -159,4 +183,4 @@ interface AppProps {
|
|
|
159
183
|
}
|
|
160
184
|
declare function App({ config, initialResponse }: AppProps): ReactElement;
|
|
161
185
|
|
|
162
|
-
export { App, type AppProps, BuildLinkElement, Config, type DirtyForm, DirtyFormContext, DirtyFormMarker, Form, FormSubmissionStatus, FormWidgetChangeNotificationContext, type Frame, Link, type Message, MessagesContext, type Metadata, type Navigation, NavigationContext, type NavigationController, OverlayContext, RenderFrame, type DjangoBridgeResponse as Response, buildLinkElement };
|
|
186
|
+
export { App, type AppProps, BuildLinkElement, Config, type DirtyForm, DirtyFormContext, DirtyFormMarker, Form, FormSubmissionStatus, FormWidgetChangeNotificationContext, type Frame, Link, type Message, MessagesContext, type Metadata, type Navigation, NavigationContext, type NavigationController, OverlayContext, RenderFrame, type DjangoBridgeResponse as Response, buildLinkElement, useAutoRefresh, useShouldReloadCallback };
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var we=Object.create;var V=Object.defineProperty;var Pe=Object.getOwnPropertyDescriptor;var be=Object.getOwnPropertyNames;var Fe=Object.getPrototypeOf,Me=Object.prototype.hasOwnProperty;var De=(e,o)=>{for(var t in o)V(e,t,{get:o[t],enumerable:!0})},fe=(e,o,t,n)=>{if(o&&typeof o=="object"||typeof o=="function")for(let r of be(o))!Me.call(e,r)&&r!==t&&V(e,r,{get:()=>o[r],enumerable:!(n=Pe(o,r))||n.enumerable});return e};var D=(e,o,t)=>(t=e!=null?we(Fe(e)):{},fe(o||!e||!e.__esModule?V(t,"default",{value:e,enumerable:!0}):t,e)),ke=e=>fe(V({},"__esModule",{value:!0}),e);var Be={};De(Be,{App:()=>Oe,BuildLinkElement:()=>se,Config:()=>X,DirtyFormContext:()=>F,DirtyFormMarker:()=>J,Form:()=>le,FormSubmissionStatus:()=>Q,FormWidgetChangeNotificationContext:()=>K,Link:()=>Ce,MessagesContext:()=>L,NavigationContext:()=>k,OverlayContext:()=>z,RenderFrame:()=>Z,buildLinkElement:()=>ie});module.exports=ke(Be);var M=D(require("react"));var ve=D(require("telepath-unpack")),q=class{views;telepathRegistry;constructor(){this.views=new Map,this.telepathRegistry=new ve.default,this.addAdapter("Date",Date)}addView=(o,t)=>(this.views.set(o,t),this);addAdapter=(o,t)=>(this.telepathRegistry.register(o,t),this);unpack=o=>this.telepathRegistry.unpack(o)};async function O(e,o){let t,n={"X-Requested-With":"DjangoBridge"};o&&(n["X-DjangoBridge-Overlay"]="true");try{t=await fetch(e,{headers:n})}catch{return{action:"network-error"}}return t.status===500?{action:"server-error"}:t.headers.get("X-DjangoBridge-Action")?t.json():{action:"reload"}}async function te(e,o,t){let n,r={"X-Requested-With":"DjangoBridge"};t&&(r["X-DjangoBridge-Overlay"]="true");try{n=await fetch(e,{method:"post",headers:r,body:o})}catch{return{action:"network-error"}}return n.status===500?{action:"server-error"}:n.headers.get("X-DjangoBridge-Action")?n.json():{action:"reload"}}var u=require("react");var Y=1;function $(e,o,t,n,r={}){Y+=1;let[i,p]=(0,u.useState)({id:Y,path:n,metadata:{title:"Loading"},view:"loading",props:{},context:{}}),[v,c]=(0,u.useState)(!1),g=(0,u.useCallback)((s,R,P,b,N,S,U=!0,ye=!0)=>{let de=i.id,me=P!==i.view||ye;if(me&&(Y+=1,de=Y),!e&&(document.title=R.title,U)){let pe=0,xe=window.scrollY,ge=window.history?.state;ge?.prevPath===s&&(pe=ge.prevScrollPosition??0),window.history.pushState({prevPath:window.location.pathname,prevScrollPosition:xe},"",s),window.scrollTo(0,pe)}let ue={id:de,path:s,metadata:R,view:P,props:b,context:N};p(ue),r.onNavigation&&r.onNavigation(ue,me,S)},[r,i.id,i.view,e]),[d,C]=(0,u.useState)(null),h=(0,u.useCallback)((s,R,P=!0,b=!1)=>{if(s.action==="reload")if(!e)window.location.href=R;else return e.handleResponse(s,R);else{if(s.action==="redirect")return C(s.path),Promise.resolve();if(s.action==="render"){if(e&&!s.overlay)return e.handleResponse(s,R);let N=o(s.props),S=o(s.context),U=!b;U&&s.view===i.view&&i.shouldReloadCallback&&(U=i.shouldReloadCallback(R,N)),g(R,s.metadata,s.view,N,S,s.messages,P,U)}else if(s.action==="close-overlay")r.onOverlayClose&&r.onOverlayClose(s.messages);else{if(s.action==="server-error")return r.onServerError&&r.onServerError("server"),Promise.reject();if(s.action==="network-error")return r.onServerError&&r.onServerError("network"),Promise.reject()}}return Promise.resolve()},[r,i,e,g,o]),f=(0,u.useRef)(1),l=(0,u.useRef)(1),y=(0,u.useRef)(!1),a=(0,u.useCallback)(async(s,R,P,b=!1)=>{f.current+=1;let N=f.current;y.current=!0;let S=await s();N<l.current||(l.current=N,S!==null&&(await h(S,R,P,b),y.current=!1))},[h]),m=(0,u.useCallback)((s,R=!0)=>{let P=s;if(!s.startsWith("/")){let b=new URL(s);if(b.origin!==window.location.origin)return window.location.href=s,Promise.resolve();P=b.pathname+b.search}return c(!0),a(()=>O(P,!!e),P,R).finally(()=>{c(!1)})},[a,e]),w=(0,u.useCallback)((s,R)=>{s===i.id&&(i.path=R,e||history.replaceState({},"",i.path))},[i,e]),oe=(0,u.useCallback)((s,R)=>a(()=>te(s,R,!!e),s,!0),[a,e]),Re=(0,u.useCallback)(()=>y.current?Promise.resolve():a(()=>O(i.path,!!e),i.path,!1,!0),[i.path,a,e]);return(0,u.useEffect)(()=>{h(t,n,!1)},[]),(0,u.useEffect)(()=>{d&&(C(null),m(d))},[m,d]),{parent:e,currentFrame:i,isLoading:i.view==="loading",handleResponse:h,navigate:m,replacePath:w,submitForm:oe,refreshProps:Re,isNavigating:v,setIsNavigating:c}}var x=D(require("react")),A=require("react/jsx-runtime"),re=x.default.createContext(()=>{}),F=x.default.createContext({isDirty:!1,requestUnload:()=>Promise.resolve(),unloadRequested:!1,unloadBlocked:!1,confirmUnload:()=>{},cancelUnload:()=>{},unloadConfirmed:!1});function ne({handleBrowserUnload:e=!1,children:o}){let[t,n]=x.default.useState(!1),[r,i]=x.default.useState({cb:()=>{}}),[p,v]=x.default.useState(!1),[c,g]=x.default.useState(!1),d=x.default.useRef(null),C=()=>d.current&&!!d.current.querySelector("div.dirty-form-marker")||!1;x.default.useEffect(()=>{if(e&&c){let y="This page has unsaved changes.",a=m=>C()?(m.returnValue=y,y):"";return window.addEventListener("beforeunload",a),()=>{window.removeEventListener("beforeunload",a)}}return()=>{}},[e,c]);let h=x.default.useContext(re),f=x.default.useCallback(()=>{g(C()),h()},[h]),l=x.default.useMemo(()=>({isDirty:c,requestUnload:()=>c&&C()?(n(!0),new Promise(y=>{i({cb:y})})):Promise.resolve(),unloadRequested:t,unloadBlocked:c&&t,confirmUnload:()=>{t&&(v(!0),r.cb(),n(!1),i({cb:()=>{}}))},cancelUnload:()=>{t&&(n(!1),i({cb:()=>{}}))},unloadConfirmed:p}),[c,r,p,t]);return(0,A.jsx)("div",{ref:d,children:(0,A.jsx)(re.Provider,{value:f,children:(0,A.jsx)(F.Provider,{value:l,children:o})})})}function J(){let e=x.default.useContext(re);return x.default.useEffect(e),(0,A.jsx)("div",{className:"dirty-form-marker",style:{display:"none"}})}var ae=D(require("react"));var B=D(require("react")),z=B.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=B.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()),isNavigating:!1}),K=B.default.createContext(()=>{}),Q=B.default.createContext(!1),L=B.default.createContext({messages:[],pushMessage:()=>{}});var j=require("react/jsx-runtime");function Ne({config:e,frame:o}){let t=e.views.get(o.view);if(!t)return(0,j.jsxs)("p",{children:["Unknown view '",o.view,"'"]});let n=(0,j.jsx)(t,{...o.props});return e.contextProviders.forEach((r,i)=>{n=(0,j.jsx)(r.Provider,{value:o.context[i],children:n})}),(0,j.jsx)("div",{children:n},o.id)}var Z=Ne;var _=require("react/jsx-runtime");function Ee({config:e,navigationController:o,openOverlay:t}){let{currentFrame:n,navigate:r,replacePath:i,submitForm:p,refreshProps:v,isNavigating:c}=o,{isDirty:g,requestUnload:d,cancelUnload:C}=ae.default.useContext(F),h=ae.default.useMemo(()=>({frameId:n.id,path:n.path,props:n.props,context:n.context,navigate:(f,l={})=>!g||l.skipDirtyFormCheck===!0?(l.skipDirtyFormCheck===!0&&C(),r(f,l.pushState)):d().then(()=>r(f,l.pushState)),replacePath:i,submitForm:p,openOverlay:t,refreshProps:v,isNavigating:c}),[n,i,p,t,g,d,C,r,v,c]);return(0,_.jsx)(k.Provider,{value:h,children:(0,_.jsx)("div",{children:(0,_.jsx)(Z,{config:e,frame:n})},n.id)})}var ee=Ee;var W=D(require("react"));var he=require("react/jsx-runtime");function ie({children:e,href:o,skipDirtyFormCheck:t=!1,...n},{navigate:r},i){return(0,he.jsx)("a",{onClick:v=>{o&&(v.preventDefault(),r(o,{skipDirtyFormCheck:t}))},href:o||"#",ref:i,...n,children:e})}var se=W.default.createContext(ie),Se=W.default.forwardRef((e,o)=>{let t=W.default.useContext(k);return W.default.useContext(se)(e,t,o)}),Ce=Se;var X=class extends q{contextProviders;constructor(){super(),this.contextProviders=new Map}addContextProvider=(o,t)=>(this.contextProviders.set(o,t),this)};var T=D(require("react"));var I=require("react/jsx-runtime");function le({children:e,onSubmit:o,isDirty:t=!1,disableDirtyCheck:n=!1,...r}){let{submitForm:i,navigate:p}=T.default.useContext(k),[v,c]=T.default.useState(!1),[g,d]=T.default.useState(t),{cancelUnload:C}=T.default.useContext(F),h=l=>{if(g&&C(),!(o&&(o(l),l.defaultPrevented))&&l.target instanceof HTMLFormElement){if(v){l.preventDefault();return}let y=new FormData(l.target);if(l.nativeEvent instanceof SubmitEvent&&l.nativeEvent.submitter){let{submitter:a}=l.nativeEvent;(a instanceof HTMLButtonElement||a instanceof HTMLInputElement)&&a.name&&a.value&&y.set(a.name,a.value)}if(l.target.method==="post")l.preventDefault(),c(!0),i(l.target.action,y).catch(()=>c(!1));else if(l.target.method==="get"){l.preventDefault();let a=Array.from(y.entries()).map(w=>`${encodeURIComponent(w[0])}=${encodeURIComponent(w[1])}`).join("&"),m=l.target.action+(l.target.action.indexOf("?")===-1?"?":"&")+a;c(!0),p(m).catch(()=>c(!1))}}},f=T.default.useCallback(()=>{d(!0)},[]);return(0,I.jsxs)("form",{onSubmit:h,...r,children:[g&&!n&&(0,I.jsx)(J,{}),(0,I.jsx)(Q.Provider,{value:v,children:(0,I.jsx)(K.Provider,{value:f,children:e})})]})}var G=D(require("react"));var H=require("react/jsx-runtime");function ce({config:e,initialResponse:o,initialPath:t,parentNavigationContoller:n,render:r,requestClose:i,closeRequested:p,onCloseCompleted:v,onServerError:c}){let{pushMessage:g}=G.default.useContext(L),d=$(n,e.unpack,o,t,{onNavigation:(l,y,a)=>{a.forEach(g)},onOverlayClose:l=>{l.forEach(g),i()},onServerError:c}),C=G.default.useContext(F),h=G.default.useCallback(({skipDirtyFormCheck:l=!1}={})=>{!l&&C.isDirty?C.requestUnload().then(()=>i()):i()},[C,i]),f=G.default.useMemo(()=>({overlay:!0,closeRequested:p,requestClose:h,onCloseCompleted:v}),[p,v,h]);return d.isLoading?(0,H.jsx)(H.Fragment,{}):(0,H.jsx)(z.Provider,{value:f,children:r((0,H.jsx)(ee,{config:e,navigationController:d,openOverlay:()=>{}}))})}var E=require("react/jsx-runtime");function Oe({config:e,initialResponse:o}){let[t,n]=M.default.useReducer((a,m)=>{switch(m.action){case"push":return a.concat([m.message]);case"clear":return[];default:return a}},[]),r=M.default.useCallback(a=>{n({action:"push",message:a})},[n]),i=M.default.useCallback(a=>{a==="server"?r({level:"error",text:"A server error occurred. Please try again later."}):a==="network"&&r({level:"error",text:"A network error occurred. Please check your internet connection or try again later."})},[r]),[p,v]=M.default.useState(null),[c,g]=M.default.useState(!1),d=M.default.useRef(null),C=(a,m,w)=>{m&&(g(!0),d.current=null),m&&n({action:"clear"}),w.forEach(r)},h=window.location.pathname+window.location.search+window.location.hash,f=$(null,e.unpack,o,h,{onNavigation:C,onServerError:i});M.default.useEffect(()=>{let a=document.querySelector(".django-bridge-load");a instanceof HTMLElement&&(a.classList.add("django-bridge-load--hidden"),setTimeout(()=>{a.remove()},200));let m=()=>{f.navigate(document.location.pathname,!1)};return window.addEventListener("popstate",m),()=>{window.removeEventListener("popstate",m)}},[]);let l=async(a,m,{onClose:w}={})=>{f.setIsNavigating(!0);let oe=await O(a,!0);w&&(d.current=w),g(!1),v({render:m,initialResponse:oe,initialPath:a}),f.setIsNavigating(!1)},y=M.default.useMemo(()=>({messages:t,pushMessage:r}),[t,r]);return(0,E.jsx)(ne,{handleBrowserUnload:!0,children:(0,E.jsxs)(L.Provider,{value:y,children:[p&&(0,E.jsx)(ne,{children:(0,E.jsx)(ce,{config:e,initialResponse:p.initialResponse,initialPath:p.initialPath,parentNavigationContoller:f,render:a=>p.render(a),requestClose:()=>g(!0),closeRequested:c,onCloseCompleted:()=>{v(null),g(!1),d.current&&(d.current(),d.current=null)},onServerError:i})}),!f.isLoading&&(0,E.jsx)(ee,{config:e,navigationController:f,openOverlay:(a,m,w)=>void l(a,m,w)})]})})}0&&(module.exports={App,BuildLinkElement,Config,DirtyFormContext,DirtyFormMarker,Form,FormSubmissionStatus,FormWidgetChangeNotificationContext,Link,MessagesContext,NavigationContext,OverlayContext,RenderFrame,buildLinkElement});
|
|
1
|
+
"use strict";var be=Object.create;var Y=Object.defineProperty;var Me=Object.getOwnPropertyDescriptor;var Ee=Object.getOwnPropertyNames;var Ne=Object.getPrototypeOf,Se=Object.prototype.hasOwnProperty;var Oe=(n,e)=>{for(var t in e)Y(n,t,{get:e[t],enumerable:!0})},ye=(n,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of Ee(e))!Se.call(n,o)&&o!==t&&Y(n,o,{get:()=>e[o],enumerable:!(r=Me(e,o))||r.enumerable});return n};var N=(n,e,t)=>(t=n!=null?be(Ne(n)):{},ye(e||!n||!n.__esModule?Y(t,"default",{value:n,enumerable:!0}):t,n)),De=n=>ye(Y({},"__esModule",{value:!0}),n);var _e={};Oe(_e,{App:()=>Ie,BuildLinkElement:()=>ue,Config:()=>X,DirtyFormContext:()=>b,DirtyFormMarker:()=>z,Form:()=>me,FormSubmissionStatus:()=>ee,FormWidgetChangeNotificationContext:()=>Z,Link:()=>Re,MessagesContext:()=>T,NavigationContext:()=>P,OverlayContext:()=>Q,RenderFrame:()=>te,buildLinkElement:()=>de,useAutoRefresh:()=>we,useShouldReloadCallback:()=>Pe});module.exports=De(_e);var E=N(require("react"));var q=class{constructors;constructor(){this.constructors={}}register(e,t){this.constructors[e]=t}unpack(e){let t={};this.scanForIds(e,t);let r={};return this.unpackWithRefs(e,t,r)}scanForIds(e,t){if(e===null||typeof e!="object")return;if(Array.isArray(e)){e.forEach(o=>this.scanForIds(o,t));return}let r=!1;if("_id"in e&&(r=!0,t[e._id]=e),("_type"in e||"_val"in e||"_ref"in e)&&(r=!0),"_list"in e&&(r=!0,e._list.forEach(o=>this.scanForIds(o,t))),"_args"in e&&(r=!0,e._args.forEach(o=>this.scanForIds(o,t))),"_dict"in e){r=!0;for(let[o,i]of Object.entries(e._dict))this.scanForIds(i,t)}if(!r)for(let[o,i]of Object.entries(e))this.scanForIds(i,t)}unpackWithRefs(e,t,r){if(e===null||typeof e!="object")return e;if(Array.isArray(e))return e.map(i=>this.unpackWithRefs(i,t,r));let o;if("_ref"in e)e._ref in r?o=r[e._ref]:o=this.unpackWithRefs(t[e._ref],t,r);else if("_val"in e)o=e._val;else if("_list"in e)o=e._list.map(i=>this.unpackWithRefs(i,t,r));else if("_dict"in e){o={};for(let[i,c]of Object.entries(e._dict))o[i]=this.unpackWithRefs(c,t,r)}else if("_type"in e){let i=e._type,c=this.constructors[i];if(typeof c!="function")throw new Error(`telepath encountered unknown object type ${i}`);let m=e._args.map(d=>this.unpackWithRefs(d,t,r));o=new c(...m)}else{if("_id"in e)throw new Error("telepath encountered object with _id but no type specified");o={};for(let[i,c]of Object.entries(e))o[i]=this.unpackWithRefs(c,t,r);return o}return"_id"in e&&(r[e._id]=o),o}};var W=class{views;telepathRegistry;constructor(){this.views=new Map,this.telepathRegistry=new q,this.addAdapter("Date",Date)}addView=(e,t)=>(this.views.set(e,t),this);addAdapter=(e,t)=>(this.telepathRegistry.register(e,t),this);unpack=e=>this.telepathRegistry.unpack(e)};async function L(n,e){let t,r={"X-Requested-With":"DjangoBridge"};e&&(r["X-DjangoBridge-Overlay"]="true");try{t=await fetch(n,{headers:r})}catch{return{action:"network-error"}}return t.status===500?{action:"server-error"}:t.headers.get("X-DjangoBridge-Action")?t.json():{action:"reload"}}async function ie(n,e,t){let r,o={"X-Requested-With":"DjangoBridge"};t&&(o["X-DjangoBridge-Overlay"]="true");try{r=await fetch(n,{method:"post",headers:o,body:e})}catch{return{action:"network-error"}}return r.status===500?{action:"server-error"}:r.headers.get("X-DjangoBridge-Action")?r.json():{action:"reload"}}var g=require("react");var J=1;function K(n,e,t,r,o={}){let[i,c]=(0,g.useState)({id:J,originalId:J,path:r,metadata:{title:"Loading"},view:"loading",props:{},context:{}}),[m,d]=(0,g.useState)(!1),v=(0,g.useCallback)((a,C,k,F,D,S,ne=!0,H=!0)=>{J+=1;let $=J,pe=i.originalId,ge=k!==i.view||H;if(ge&&(pe=$),!n&&(document.title=C.title,ne)){let he=0,Fe=window.scrollY,Ce=window.history?.state;Ce?.prevPath===a&&(he=Ce.prevScrollPosition??0),window.history.pushState({prevPath:window.location.pathname,prevScrollPosition:Fe},"",a),window.scrollTo(0,he)}let ve={id:$,originalId:pe,path:a,metadata:C,view:k,props:F,context:D};c(ve),o.onNavigation&&o.onNavigation(ve,ge,S)},[o,i.originalId,i.view,n]),[u,h]=(0,g.useState)(null),y=(0,g.useCallback)((a,C,k=!0,F=!1,D=!1)=>{if(a.action==="reload")if(!n)window.location.href=C;else return n.handleResponse(a,C);else{if(a.action==="redirect")return h(a.path),Promise.resolve();if(a.action==="render"){if(n&&!a.overlay){D&&console.warn(`openOverlay('${C}') returned a response that couldn't be rendered in an overlay.`);let $=n.handleResponse(a,C);return o.onEscalate&&o.onEscalate(),$}let S=e(a.props),ne=e(a.context),H=!F;H&&a.view===i.view&&i.shouldReloadCallback&&(H=i.shouldReloadCallback(C,S)),v(C,a.metadata,a.view,S,ne,a.messages,k,H)}else if(a.action==="close-overlay")o.onOverlayClose&&o.onOverlayClose(a.messages);else{if(a.action==="server-error")return o.onServerError&&o.onServerError("server"),Promise.reject();if(a.action==="network-error")return o.onServerError&&o.onServerError("network"),Promise.reject()}}return Promise.resolve()},[o,i,n,v,e]),f=(0,g.useRef)(1),l=(0,g.useRef)(1),R=(0,g.useRef)(!1),s=(0,g.useCallback)(async(a,C,k,F=!1)=>{f.current+=1;let D=f.current;R.current=!0;let S=await a();D<l.current||(l.current=D,S!==null&&(await y(S,C,k,F),R.current=!1))},[y]),p=(0,g.useCallback)((a,C=!0)=>{let k=a;if(!a.startsWith("/")){let F=new URL(a);if(F.origin!==window.location.origin)return window.location.href=a,Promise.resolve();k=F.pathname+F.search}return d(!0),s(()=>L(k,!!n),k,C).finally(()=>{d(!1)})},[s,n]),w=(0,g.useCallback)((a,C)=>{a===i.id&&(i.path=C,n||history.replaceState({},"",i.path))},[i,n]),re=(0,g.useCallback)((a,C)=>s(()=>ie(a,C,!!n),a,!0),[s,n]),ke=(0,g.useCallback)(()=>R.current?Promise.resolve():s(()=>L(i.path,!!n),i.path,!1,!0),[i.path,s,n]);return(0,g.useEffect)(()=>{y(t,r,!1,!1,!0)},[]),(0,g.useEffect)(()=>{u&&(h(null),p(u))},[p,u]),{parent:n,currentFrame:i,isLoading:i.view==="loading",handleResponse:y,navigate:p,replacePath:w,submitForm:re,refreshProps:ke,isNavigating:m,setIsNavigating:d}}var x=N(require("react")),j=require("react/jsx-runtime"),se=x.default.createContext(()=>{}),b=x.default.createContext({isDirty:!1,requestUnload:()=>Promise.resolve(),unloadRequested:!1,unloadBlocked:!1,confirmUnload:()=>{},cancelUnload:()=>{},unloadConfirmed:!1});function ae({handleBrowserUnload:n=!1,children:e}){let[t,r]=x.default.useState(!1),[o,i]=x.default.useState({cb:()=>{}}),[c,m]=x.default.useState(!1),[d,v]=x.default.useState(!1),u=x.default.useRef(null),h=()=>u.current&&!!u.current.querySelector("div.dirty-form-marker")||!1;x.default.useEffect(()=>{if(n&&d){let R="This page has unsaved changes.",s=p=>h()?(p.returnValue=R,R):"";return window.addEventListener("beforeunload",s),()=>{window.removeEventListener("beforeunload",s)}}return()=>{}},[n,d]);let y=x.default.useContext(se),f=x.default.useCallback(()=>{v(h()),y()},[y]),l=x.default.useMemo(()=>({isDirty:d,requestUnload:()=>d&&h()?(r(!0),new Promise(R=>{i({cb:R})})):Promise.resolve(),unloadRequested:t,unloadBlocked:d&&t,confirmUnload:()=>{t&&(m(!0),o.cb(),r(!1),i({cb:()=>{}}))},cancelUnload:()=>{t&&(r(!1),i({cb:()=>{}}))},unloadConfirmed:c}),[d,o,c,t]);return(0,j.jsx)("div",{ref:u,children:(0,j.jsx)(se.Provider,{value:f,children:(0,j.jsx)(b.Provider,{value:l,children:e})})})}function z(){let n=x.default.useContext(se);return x.default.useEffect(n),(0,j.jsx)("div",{className:"dirty-form-marker",style:{display:"none"}})}var le=N(require("react"));var B=N(require("react")),Q=B.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")}}),P=B.default.createContext({frameId:0,originalFrameId: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()),isNavigating:!1,setShouldReloadCallback:()=>{}}),Z=B.default.createContext(()=>{}),ee=B.default.createContext(!1),T=B.default.createContext({messages:[],pushMessage:()=>{}});var I=require("react/jsx-runtime");function Le({config:n,frame:e}){let t=n.views.get(e.view);if(!t)return(0,I.jsxs)("p",{children:["Unknown view '",e.view,"'"]});let r=(0,I.jsx)(t,{...e.props});return n.contextProviders.forEach((o,i)=>{i in e.context&&(r=(0,I.jsx)(o.Provider,{value:e.context[i],children:r}))}),(0,I.jsx)("div",{children:r},e.originalId)}var te=Le;var ce=require("react/jsx-runtime");function Be({config:n,navigationController:e,openOverlay:t}){let{currentFrame:r,navigate:o,replacePath:i,submitForm:c,refreshProps:m,isNavigating:d}=e,{isDirty:v,requestUnload:u,cancelUnload:h}=le.default.useContext(b),y=le.default.useMemo(()=>({originalFrameId:r.originalId,frameId:r.id,path:r.path,props:r.props,context:r.context,navigate:(f,l={})=>!v||l.skipDirtyFormCheck===!0?(l.skipDirtyFormCheck===!0&&h(),o(f,l.pushState)):u().then(()=>o(f,l.pushState)),replacePath:i,submitForm:c,openOverlay:t,refreshProps:m,isNavigating:d,setShouldReloadCallback:f=>{r.shouldReloadCallback=f}}),[r,i,c,t,v,u,h,o,m,d]);return(0,ce.jsx)(P.Provider,{value:y,children:(0,ce.jsx)(te,{config:n,frame:r})})}var oe=Be;var V=N(require("react"));var xe=require("react/jsx-runtime");function de({children:n,href:e,skipDirtyFormCheck:t=!1,...r},{navigate:o},i){return(0,xe.jsx)("a",{onClick:m=>{e&&(m.preventDefault(),o(e,{skipDirtyFormCheck:t}))},href:e||"#",ref:i,...r,children:n})}var ue=V.default.createContext(de),Te=V.default.forwardRef((n,e)=>{let t=V.default.useContext(P);return V.default.useContext(ue)(n,t,e)}),Re=Te;var X=class extends W{contextProviders;constructor(){super(),this.contextProviders=new Map}addContextProvider=(e,t)=>(this.contextProviders.set(e,t),this)};var _=N(require("react"));var A=require("react/jsx-runtime");function me({children:n,onSubmit:e,isDirty:t=!1,disableDirtyCheck:r=!1,...o}){let{submitForm:i,navigate:c}=_.default.useContext(P),[m,d]=_.default.useState(!1),[v,u]=_.default.useState(t),{cancelUnload:h}=_.default.useContext(b),y=l=>{if(v&&h(),!(e&&(e(l),l.defaultPrevented))&&l.target instanceof HTMLFormElement){if(m){l.preventDefault();return}let R=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&&R.set(s.name,s.value)}if(l.target.method==="post")l.preventDefault(),d(!0),i(l.target.action,R).catch(()=>d(!1));else if(l.target.method==="get"){l.preventDefault();let s=Array.from(R.entries()).map(w=>`${encodeURIComponent(w[0])}=${encodeURIComponent(w[1])}`).join("&"),p=l.target.action+(l.target.action.indexOf("?")===-1?"?":"&")+s;d(!0),c(p).catch(()=>d(!1))}}},f=_.default.useCallback(()=>{u(!0)},[]);return(0,A.jsxs)("form",{onSubmit:y,...o,children:[v&&!r&&(0,A.jsx)(z,{}),(0,A.jsx)(ee.Provider,{value:m,children:(0,A.jsx)(Z.Provider,{value:f,children:n})})]})}var G=N(require("react"));var U=require("react/jsx-runtime");function fe({config:n,initialResponse:e,initialPath:t,parentNavigationController:r,render:o,requestClose:i,closeRequested:c,onCloseCompleted:m,onServerError:d}){let{pushMessage:v}=G.default.useContext(T),u=K(r,n.unpack,e,t,{onNavigation:(l,R,s)=>{s.forEach(v)},onEscalate:()=>{m()},onOverlayClose:l=>{l.forEach(v),i()},onServerError:d}),h=G.default.useContext(b),y=G.default.useCallback(({skipDirtyFormCheck:l=!1}={})=>{!l&&h.isDirty?h.requestUnload().then(()=>i()):i()},[h,i]),f=G.default.useMemo(()=>({overlay:!0,closeRequested:c,requestClose:y,onCloseCompleted:m}),[c,m,y]);return u.isLoading?(0,U.jsx)(U.Fragment,{}):(0,U.jsx)(Q.Provider,{value:f,children:o((0,U.jsx)(oe,{config:n,navigationController:u,openOverlay:()=>{}}))})}var M=N(require("react"));function we(n,e){let{refreshProps:t}=M.default.useContext(P);M.default.useEffect(()=>{if(!n)return()=>{};let r=null,o=()=>{r=setTimeout(()=>{t(),o()},e)};return o(),()=>{r&&clearTimeout(r)}},[n,e,t])}function Pe(n,e){let t=(0,M.useCallback)(n,e),{setShouldReloadCallback:r}=(0,M.useContext)(P);(0,M.useEffect)(()=>r(t),[t,r])}var O=require("react/jsx-runtime");function Ie({config:n,initialResponse:e}){let[t,r]=E.default.useReducer((s,p)=>{switch(p.action){case"push":return s.concat([p.message]);case"clear":return[];default:return s}},[]),o=E.default.useCallback(s=>{r({action:"push",message:s})},[r]),i=E.default.useCallback(s=>{s==="server"?o({level:"error",text:"A server error occurred. Please try again later."}):s==="network"&&o({level:"error",text:"A network error occurred. Please check your internet connection or try again later."})},[o]),[c,m]=E.default.useState(null),[d,v]=E.default.useState(!1),u=E.default.useRef(null),h=(s,p,w)=>{p&&(v(!0),u.current=null),p&&r({action:"clear"}),w.forEach(o)},y=window.location.pathname+window.location.search+window.location.hash,f=K(null,n.unpack,e,y,{onNavigation:h,onServerError:i});E.default.useEffect(()=>{let s=document.querySelector(".django-bridge-load");s instanceof HTMLElement&&(s.classList.add("django-bridge-load--hidden"),setTimeout(()=>{s.remove()},200));let p=()=>{f.navigate(document.location.pathname,!1)};return window.addEventListener("popstate",p),()=>{window.removeEventListener("popstate",p)}},[]);let l=async(s,p,{onClose:w}={})=>{if(c){console.error("Unable to open overlay as an overlay is already open.");return}f.setIsNavigating(!0);let re=await L(s,!0);w&&(u.current=w),v(!1),m({render:p,initialResponse:re,initialPath:s}),f.setIsNavigating(!1)},R=E.default.useMemo(()=>({messages:t,pushMessage:o}),[t,o]);return(0,O.jsx)(ae,{handleBrowserUnload:!0,children:(0,O.jsxs)(T.Provider,{value:R,children:[c&&(0,O.jsx)(ae,{children:(0,O.jsx)(fe,{config:n,initialResponse:c.initialResponse,initialPath:c.initialPath,parentNavigationController:f,render:s=>c.render(s),requestClose:()=>v(!0),closeRequested:d,onCloseCompleted:()=>{m(null),v(!1),u.current&&(u.current(),u.current=null)},onServerError:i})}),!f.isLoading&&(0,O.jsx)(oe,{config:n,navigationController:f,openOverlay:(s,p,w)=>{l(s,p,w)}})]})})}0&&(module.exports={App,BuildLinkElement,Config,DirtyFormContext,DirtyFormMarker,Form,FormSubmissionStatus,FormWidgetChangeNotificationContext,Link,MessagesContext,NavigationContext,OverlayContext,RenderFrame,buildLinkElement,useAutoRefresh,useShouldReloadCallback});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@django-bridge/react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0-rc.2",
|
|
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",
|
|
@@ -26,8 +26,7 @@
|
|
|
26
26
|
]
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"react": "^18.2.0"
|
|
30
|
-
"telepath-unpack": "^0.0.4"
|
|
29
|
+
"react": "^18.2.0"
|
|
31
30
|
},
|
|
32
31
|
"devDependencies": {
|
|
33
32
|
"@types/node": "^12.0.0",
|