@django-bridge/react 0.4.0-rc.7 → 0.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/dist/index.d.ts CHANGED
@@ -1,6 +1,68 @@
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';
1
+ import React, { FunctionComponent, ReactNode, ReactElement, Context } from 'react';
2
+ import Telepath from 'telepath-unpack';
3
+
4
+ declare class Config$1 {
5
+ views: Map<string, FunctionComponent>;
6
+ telepathRegistry: Telepath;
7
+ constructor();
8
+ addView: <P>(name: string, component: FunctionComponent<P>) => Config$1;
9
+ addAdapter: <Cls>(name: string, ctor: {
10
+ new (...args: any[]): Cls;
11
+ }) => Config$1;
12
+ unpack: (data: Record<string, unknown>) => Record<string, unknown>;
13
+ }
14
+
15
+ interface Metadata {
16
+ title: string;
17
+ }
18
+
19
+ type MessageLevel = "info" | "success" | "warning" | "error";
20
+ interface TextMessage {
21
+ level: MessageLevel;
22
+ text: string;
23
+ }
24
+ interface HTMLMessage {
25
+ level: MessageLevel;
26
+ html: string;
27
+ }
28
+ type Message = TextMessage | HTMLMessage;
29
+ interface ReloadResponse {
30
+ action: "reload";
31
+ }
32
+ interface RedirectResponse {
33
+ action: "redirect";
34
+ path: string;
35
+ }
36
+ interface RenderResponse {
37
+ action: "render";
38
+ overlay: boolean;
39
+ metadata: Metadata;
40
+ view: string;
41
+ props: Record<string, unknown>;
42
+ context: Record<string, unknown>;
43
+ messages: Message[];
44
+ }
45
+ interface CloseOverlayResponse {
46
+ action: "close-overlay";
47
+ messages: Message[];
48
+ }
49
+ interface ServerErrorResponse {
50
+ action: "server-error";
51
+ }
52
+ interface NetworkErrorResponse {
53
+ action: "network-error";
54
+ }
55
+ type DjangoBridgeResponse = ReloadResponse | RedirectResponse | RenderResponse | CloseOverlayResponse | ServerErrorResponse | NetworkErrorResponse;
56
+
57
+ interface Frame<Props = Record<string, unknown>> {
58
+ id: number;
59
+ path: string;
60
+ metadata: Metadata;
61
+ view: string;
62
+ props: Props;
63
+ context: Record<string, unknown>;
64
+ shouldReloadCallback?: (newPath: string, newProps: Props) => boolean;
65
+ }
4
66
 
5
67
  interface NavigateOptions {
6
68
  pushState?: boolean;
@@ -94,4 +156,4 @@ interface AppProps {
94
156
  }
95
157
  declare function App({ config, initialResponse }: AppProps): ReactElement;
96
158
 
97
- export { App, type AppProps, BuildLinkElement, Config, type DirtyForm, DirtyFormContext, DirtyFormMarker, Form, FormSubmissionStatus, FormWidgetChangeNotificationContext, Link, MessagesContext, type Navigation, NavigationContext, type NavigationController, OverlayContext, RenderFrame, buildLinkElement };
159
+ 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 };
package/dist/index.js CHANGED
@@ -1 +1 @@
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});
1
+ "use strict";var Re=Object.create;var G=Object.defineProperty;var ye=Object.getOwnPropertyDescriptor;var xe=Object.getOwnPropertyNames;var we=Object.getPrototypeOf,Pe=Object.prototype.hasOwnProperty;var Fe=(e,o)=>{for(var t in o)G(e,t,{get:o[t],enumerable:!0})},pe=(e,o,t,a)=>{if(o&&typeof o=="object"||typeof o=="function")for(let n of xe(o))!Pe.call(e,n)&&n!==t&&G(e,n,{get:()=>o[n],enumerable:!(a=ye(o,n))||a.enumerable});return e};var M=(e,o,t)=>(t=e!=null?Re(we(e)):{},pe(o||!e||!e.__esModule?G(t,"default",{value:e,enumerable:!0}):t,e)),be=e=>pe(G({},"__esModule",{value:!0}),e);var Ne={};Fe(Ne,{App:()=>Ee,BuildLinkElement:()=>ae,Config:()=>W,DirtyFormContext:()=>F,DirtyFormMarker:()=>$,Form:()=>ie,FormSubmissionStatus:()=>K,FormWidgetChangeNotificationContext:()=>z,Link:()=>fe,MessagesContext:()=>B,NavigationContext:()=>D,OverlayContext:()=>J,RenderFrame:()=>Q,buildLinkElement:()=>ne});module.exports=be(Ne);var b=M(require("react"));var ge=M(require("telepath-unpack")),q=class{views;telepathRegistry;constructor(){this.views=new Map,this.telepathRegistry=new ge.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 S(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 ee(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 C=require("react");var V=1;function Y(e,o,t,a,n={}){V+=1;let[i,u]=(0,C.useState)({id:V,path:a,metadata:{title:"Loading"},view:"loading",props:{},context:{}}),p=(0,C.useCallback)((r,v,w,P,k,N,U=!0,Ce=!0)=>{let le=i.id,ce=w!==i.view||Ce;if(ce&&(V+=1,le=V),!e&&(document.title=v.title,U)){let me=0,he=window.scrollY,ue=window.history?.state;ue?.prevPath===r&&(me=ue.prevScrollPosition??0),window.history.pushState({prevPath:window.location.pathname,prevScrollPosition:he},"",r),window.scrollTo(0,me)}let de={id:le,path:r,metadata:v,view:w,props:P,context:k};u(de),n.onNavigation&&n.onNavigation(de,ce,N)},[n,i.id,i.view,e]),[c,g]=(0,C.useState)(null),d=(0,C.useCallback)((r,v,w=!0,P=!1)=>{if(r.action==="reload")if(!e)window.location.href=v;else return e.handleResponse(r,v);else{if(r.action==="redirect")return g(r.path),Promise.resolve();if(r.action==="render"){if(e&&!r.overlay)return e.handleResponse(r,v);let k=o(r.props),N=o(r.context),U=!P;U&&r.view===i.view&&i.shouldReloadCallback&&(U=i.shouldReloadCallback(v,k)),p(v,r.metadata,r.view,k,N,r.messages,w,U)}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,p,o]),h=(0,C.useRef)(1),R=(0,C.useRef)(1),m=(0,C.useCallback)(async(r,v,w,P=!1)=>{h.current+=1;let k=h.current,N=await r();k<R.current||(R.current=k,N!==null&&await d(N,v,w,P))},[d]),l=(0,C.useCallback)((r,v=!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(()=>S(w,!!e),w,v)},[m,e]),x=(0,C.useCallback)((r,v)=>{r===i.id&&(i.path=v,e||history.replaceState({},"",i.path))},[i,e]),s=(0,C.useCallback)((r,v)=>m(()=>ee(r,v,!!e),r,!0),[m,e]),f=(0,C.useCallback)(()=>m(()=>S(i.path,!!e),i.path,!1,!0),[i.path,m,e]);return(0,C.useEffect)(()=>{d(t,a,!1)},[]),(0,C.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:f}}var y=M(require("react")),I=require("react/jsx-runtime"),oe=y.default.createContext(()=>{}),F=y.default.createContext({isDirty:!1,requestUnload:()=>Promise.resolve(),unloadRequested:!1,unloadBlocked:!1,confirmUnload:()=>{},cancelUnload:()=>{},unloadConfirmed:!1});function te({handleBrowserUnload:e=!1,children:o}){let[t,a]=y.default.useState(!1),[n,i]=y.default.useState({cb:()=>{}}),[u,p]=y.default.useState(!1),[c,g]=y.default.useState(!1),d=y.default.useRef(null),h=()=>d.current&&!!d.current.querySelector("div.dirty-form-marker")||!1;y.default.useEffect(()=>{if(e&&c){let x="This page has unsaved changes.",s=f=>h()?(f.returnValue=x,x):"";return window.addEventListener("beforeunload",s),()=>{window.removeEventListener("beforeunload",s)}}return()=>{}},[e,c]);let R=y.default.useContext(oe),m=y.default.useCallback(()=>{g(h()),R()},[R]),l=y.default.useMemo(()=>({isDirty:c,requestUnload:()=>c&&h()?(a(!0),new Promise(x=>{i({cb:x})})):Promise.resolve(),unloadRequested:t,unloadBlocked:c&&t,confirmUnload:()=>{t&&(p(!0),n.cb(),a(!1),i({cb:()=>{}}))},cancelUnload:()=>{t&&(a(!1),i({cb:()=>{}}))},unloadConfirmed:u}),[c,n,u,t]);return(0,I.jsx)("div",{ref:d,children:(0,I.jsx)(oe.Provider,{value:m,children:(0,I.jsx)(F.Provider,{value:l,children:o})})})}function $(){let e=y.default.useContext(oe);return y.default.useEffect(e),(0,I.jsx)("div",{className:"dirty-form-marker",style:{display:"none"}})}var re=M(require("react"));var O=M(require("react")),J=O.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=O.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=O.default.createContext(()=>{}),K=O.default.createContext(!1),B=O.default.createContext({messages:[],pushMessage:()=>{}});var L=require("react/jsx-runtime");function Me({config:e,frame:o}){let t=e.views.get(o.view);if(!t)return(0,L.jsxs)("p",{children:["Unknown view '",o.view,"'"]});let a=(0,L.jsx)(t,{...o.props});return e.contextProviders.forEach((n,i)=>{a=(0,L.jsx)(n.Provider,{value:o.context[i],children:a})}),(0,L.jsx)("div",{children:a},o.id)}var Q=Me;var Z=require("react/jsx-runtime");function De({config:e,navigationController:o,openOverlay:t}){let{currentFrame:a,navigate:n,replacePath:i,submitForm:u,refreshProps:p}=o,{isDirty:c,requestUnload:g,cancelUnload:d}=re.default.useContext(F),h=re.default.useMemo(()=>({frameId:a.id,path:a.path,props:a.props,context:a.context,navigate:(R,m={})=>!c||m.skipDirtyFormCheck===!0?(m.skipDirtyFormCheck===!0&&d(),n(R,m.pushState)):g().then(()=>n(R,m.pushState)),replacePath:i,submitForm:u,openOverlay:t,refreshProps:p}),[a,i,u,t,c,g,d,n,p]);return(0,Z.jsx)(D.Provider,{value:h,children:(0,Z.jsx)("div",{children:(0,Z.jsx)(Q,{config:e,frame:a})},a.id)})}var _=De;var A=M(require("react"));var ve=require("react/jsx-runtime");function ne({children:e,href:o,skipDirtyFormCheck:t=!1,...a},{navigate:n},i){return(0,ve.jsx)("a",{onClick:p=>{o&&(p.preventDefault(),n(o,{skipDirtyFormCheck:t}))},href:o||"#",ref:i,...a,children:e})}var ae=A.default.createContext(ne),ke=A.default.forwardRef((e,o)=>{let t=A.default.useContext(D);return A.default.useContext(ae)(e,t,o)}),fe=ke;var W=class extends q{contextProviders;constructor(){super(),this.contextProviders=new Map}addContextProvider=(o,t)=>(this.contextProviders.set(o,t),this)};var j=M(require("react"));var T=require("react/jsx-runtime");function ie({children:e,onSubmit:o,isDirty:t=!1,disableDirtyCheck:a=!1,...n}){let{submitForm:i,navigate:u}=j.default.useContext(D),[p,c]=j.default.useState(!1),[g,d]=j.default.useState(t),{cancelUnload:h}=j.default.useContext(F),R=l=>{if(g&&h(),!(o&&(o(l),l.defaultPrevented))&&l.target instanceof HTMLFormElement){if(p){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("&"),f=l.target.action+(l.target.action.indexOf("?")===-1?"?":"&")+s;c(!0),u(f).catch(()=>c(!1))}}},m=j.default.useCallback(()=>{d(!0)},[]);return(0,T.jsxs)("form",{onSubmit:R,...n,children:[g&&!a&&(0,T.jsx)($,{}),(0,T.jsx)(K.Provider,{value:p,children:(0,T.jsx)(z.Provider,{value:m,children:e})})]})}var X=M(require("react"));var H=require("react/jsx-runtime");function se({config:e,initialResponse:o,initialPath:t,parentNavigationContoller:a,render:n,requestClose:i,closeRequested:u,onCloseCompleted:p,onServerError:c}){let{pushMessage:g}=X.default.useContext(B),d=Y(a,e.unpack,o,t,{onNavigation:(l,x,s)=>{s.forEach(g)},onOverlayClose:l=>{l.forEach(g),i()},onServerError:c}),h=X.default.useContext(F),R=X.default.useCallback(({skipDirtyFormCheck:l=!1}={})=>{!l&&h.isDirty?h.requestUnload().then(()=>i()):i()},[h,i]),m=X.default.useMemo(()=>({overlay:!0,closeRequested:u,requestClose:R,onCloseCompleted:p}),[u,p,R]);return d.isLoading?(0,H.jsx)(H.Fragment,{}):(0,H.jsx)(J.Provider,{value:m,children:n((0,H.jsx)(_,{config:e,navigationController:d,openOverlay:()=>{}}))})}var E=require("react/jsx-runtime");function Ee({config:e,initialResponse:o}){let[t,a]=b.default.useReducer((s,f)=>{switch(f.action){case"push":return s.concat([f.message]);case"clear":return[];default:return s}},[]),n=b.default.useCallback(s=>{a({action:"push",message:s})},[a]),i=b.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]),[u,p]=b.default.useState(null),[c,g]=b.default.useState(!1),d=b.default.useRef(null),h=(s,f,r)=>{f&&(g(!0),d.current=null),f&&a({action:"clear"}),r.forEach(n)},R=window.location.pathname+window.location.search+window.location.hash,m=Y(null,e.unpack,o,R,{onNavigation:h,onServerError:i});b.default.useEffect(()=>{let s=document.querySelector(".django-bridge-load");s instanceof HTMLElement&&(s.classList.add("django-bridge-load--hidden"),setTimeout(()=>{s.remove()},200));let f=()=>{m.navigate(document.location.pathname,!1)};return window.addEventListener("popstate",f),()=>{window.removeEventListener("popstate",f)}},[]);let l=async(s,f,{onClose:r}={})=>{let v=await S(s,!0);r&&(d.current=r),g(!1),p({render:f,initialResponse:v,initialPath:s})},x=b.default.useMemo(()=>({messages:t,pushMessage:n}),[t,n]);return(0,E.jsx)(te,{handleBrowserUnload:!0,children:(0,E.jsxs)(B.Provider,{value:x,children:[u&&(0,E.jsx)(te,{children:(0,E.jsx)(se,{config:e,initialResponse:u.initialResponse,initialPath:u.initialPath,parentNavigationContoller:m,render:s=>u.render(s),requestClose:()=>g(!0),closeRequested:c,onCloseCompleted:()=>{p(null),g(!1),d.current&&(d.current(),d.current=null)},onServerError:i})}),!m.isLoading&&(0,E.jsx)(_,{config:e,navigationController:m,openOverlay:(s,f,r)=>void l(s,f,r)})]})})}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.7",
3
+ "version": "0.4.0",
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",
@@ -10,7 +10,7 @@
10
10
  "/dist"
11
11
  ],
12
12
  "scripts": {
13
- "build": "tsup src/index.tsx --format cjs --dts --minify --clean --out-dir dist",
13
+ "build": "tsup",
14
14
  "check-types": "tsc --noEmit"
15
15
  },
16
16
  "browserslist": {
@@ -27,8 +27,7 @@
27
27
  },
28
28
  "dependencies": {
29
29
  "react": "^18.2.0",
30
- "telepath-unpack": "^0.0.4",
31
- "@django-bridge/common": "*"
30
+ "telepath-unpack": "^0.0.4"
32
31
  },
33
32
  "devDependencies": {
34
33
  "@types/node": "^12.0.0",