�PNG  IHDR����Q�gAMA�� �a cHRMz&�����u0�`:�p��Q<�bKGD�������gmIDATx���w�U���ﹻ�& �^C��X(�����J I@� ���"% (** B�X� �+*�i��"]j(IH�{~�R)��[��~��>h��{�}g�y�)I�$I��j��� ������.I�$I�$�ʊ�y@�}x�.�: �$I�$I��i}��V�Z�����PC)I�$I��F� ����^��0ʐJ�$I�$�Q^���}{�"���r�=��OzI��$gR�ZeC.�IO����vH eK��X� �����$IM�px��sk�.��쒷/��&���r�[޳����<���v|�� ��.I���~�)@������$�up��dY�R�����a�$I �|�M�.�e ��Jaֶ�pS�Y�R��6j��>h�%IR��ز�� �i�f&���u�J)������M�����$I vL���i���=�H;�7UJ�,�]�,X��$I��1��AҒ�J����$ X�Y� XzI��@G����N��ҥR���T)E��@��;��]K*�M�w;#�5_�wO�n~\ DC&�$(A�5 �R�R��FkvIR���}�l��!�RytRl;��~^Ƿ�Jj� �اy�뷦BZ��Jr����&ӥ�8�P�j��w~�vn�����v ���X���^�(I;�4�R=�P[�3]J�,�]ȏ�~��:�3�?��[��� ��a��&e)`�e*����P[�4]�T��=Cq�6�R[ ~ޤ����r�XR Հg(�t�_HZ�-Hg �M�$�ãm�L5�R� �u��k�*`%C-�E6/����%[�t X.{��8�P9Z�������.vk����XŐKj����gKZ��Hg�(����aK9ڦ��mKj��Ѻm�_ \�#�$5�,)- � �61eJ�,��5m|� ��r�'��=��� ��&ڡd���%-]J �on�� X���m|�{ ��R�Ҟ����e $eڧY X��Y�����rԮ-a�7�RK�6h���>n$5A�V�ڴ�i��*�ֆ�K)���mѦ���tm�r�1p| �q:흺,)O�����i��*�ֺ�K)���ܬ�֦����K-5�r�3�>0ԔHj��Jئ�EZ��j�,%��r�e��~�/��z��%j�V��M��ڸ�mr��t)��3]J�,���T ��K֦O�vԒg��i�i��*�����bK�i�NO~�%�P��W���0=�d��i�i�������2�t�J9��J����ݕ�{�7�"I P��9�JK�Tb�u,%��r���"�6�RKU��}�Ij�2����HK�Z�XJ�,妝�� X��Y�����rP��� ެ�2�4�c��%i��^���IK|.H�,%��r�b���:XR�l��1X��4Pe/`����x��&����P��8�Pj��28��M��z���s��x���2���r�\���zR��P�z�4J����}�y���P[g=�L)��� .Q[�6Rj�Wgp ��FI�H�*-`I�����M�RaK9T��X��c�q�����*I� y���[j��E>cw%��gL�R���ԕi�F�Cj�-��ď�a`������#e~���I�� j�,%��r�,)?[gp �FI˨���mn��WX#��>mʔ X�A��� �DZf9,�nKҲz�����I��Z�XJ�,�L#��k�i��P�z�4JZF�����,�I,`���61%�2s �$���,�VO��Ϛ2��/U��FJ�fy��7����K�> X�+�6� S�TX����Ie�����JI���Lz�M�fKm ��L�RaK9�%|��4p9L�w�JI��!`N����sia���zĔ)������%-� X��M���q�>�pk�$-$�Q���2����x#�N� ؎�-�QR��}ᶦHZ�ډ��)�J�,�l#��i@y�n3������L��N`���;�nڔ X�����u����X5��p��F)��m|��^�0(��>B�H���F9(c�զE��er��JI rg��7 ��4I@z�0\�JI��������i�䵙���RR��0�s;�$�s6eJ�,�`n �䂦���0�a�)S)�A������ ���1eJ�,堌#�6�35R��I�gpN��Hu������TH���_S���ԕqV�����e `� ��&S)���>�p;S$魁eKI����uX��`I�����4��춒�o}`m�$1"��:�PI���<[�v9�^�\p��TJj�r�iRŭ ��P{#�{R2,`)e-`mgj�~�1�ϣ�L��Kam�7�&U\j�/�3mJ�,�`F��;M��'�䱀�� .KR#��)y�h�Tq�;p���cK9(���q!w�?����u�RR,n.yw�*UXj#�\�]ɱ���(q�v2=R���q����f����B#i��Jm�m�L����<]�Y����͙�#�$5� ��u�TU�7��Ӧ�X�R+q�,`I}����qL�����'���`��6�K�ͷ�6���r�,�]����0S$-���� ��[RKR3���o��iRE����|�nӦ�X�R.�(i�:�L��D�L��TJj�Y��%o�:����)�����6���r�x���zҒ��q��TJj��h㞦I���.�$Y�R.ʼ�n�GZ�\ֿ��f:%5�5 ��I�˼!�6����dK�x��m��4E�"mG�_�� �s? �.e*��?L�RfK9��%�����q�#�uh$�)�i���3U�����L�RfK9yx��m܌b�j�����8��4���$�i��1U��^@Wbm��4uJ�,�����Ҫ�A�>���_Ij�?1�v�3�2����[�gL�R��D��9�6�o�Ta�R���׿��N7%�����L�2�� NT�,`)7�&�Ɲ��L�*꽙��yp���_$���M�2�#�A�����S�,`)7�$r��k�TA���29�_���Iy�e"�|/0�t)�$�n X�T2���`Y���J���;�6��J�x"�����.e�<�`�����$)� P�I$��5�V4]���29���SRI>�~�=@j�]��l�p�2`K9Jaai�^" Ԋ��29�O�RI%��:X�V5]J��m��N9���]�H;1U���C39���NI%���Xe78�t)a��;���O��i Ҙ�>X�t�"~G>�_mn:%���|~ޅ_�+]�$�o���)�@��ǀ{hgN;�IK�6�G&�rp�)�T2�i�୦K�Ju���v*���T��=�T��O�SV�>(��~D�>d�����m�,I*��Ɛ�:���R�#��ۙNI%��D>G��.n��$�o��;�+#��R�R��!��.e�U��˽���TRI�2��8�t)1L��WϚ>IJ�a3�oF��b��u&���:�tJ*��(F7��y�0�Z�R ^�p���'Ii� ����L�24x�| X��RI%�ۄ>S1]J�y��[z��L�$�adB7��.eh4��%���%�누>W�E���Tf+3�����IR:�I�3Xה)3אO�ۦSR�O'�ٺ�)S�}"��q�O��r[B7�ϙ.edG�)^E���TR"R��t��R�ݜh���0}������<�S����ɧx�.6,)�&���)SI�p��j�'I��?���A�L�"���L����.\TZV�N���!�'I�Y.��pAS����5}� �TRbNL�3��”�d�����b�e��)��4]��Mg/S���Z{ni����,)=k����Д�d��p��ǦO��uLb7�ߛ2%lO�}u�)���K��]le�T�P��j�eS(I�Z���ִ��R�^eJ%%*�/\ Ke�̈́�-O�M�$����|.5eJ��o�s)^]oJ%%,�㚃R� <�p��LS��� �*����`GӦ�tdt<�5���o'��/�6�٧�� _��BIJ�kH��_�6%d ���rQ�b�gZ%%n�ڍ9o1mj�U�g���JR>�L�F�VӦD�B^k_���J�Dj��\����=�L���S(I������v─a���T�eZ%e�U����A�M-�0;�~˃@�i��|l�� �@S���4y���7��2��>���sX-vA�}�ϛBI���!ݎߨ����W�l�*)3{'�Y|�iS�lEڻ(��5�����K��t��SI�$��Uv0��2���,~��ԩ~�x��;�P��4��ց��C�r�O%ty�n4��25:���KM��l�D� ^���4JR������xS��ه�F_}شJ�T�S��6uj�+ﷸk�$e���Z�O%�G�*^�V2�����u3E�Mj�3��k%)ok��I]d�T����)�UR�K���DS� �7�~�m@�TJR�~�荪�f�T"�֛L�� �\���s��M��� �-0��T �K�f�J��z+��n�إK�r� �L�����&j��(��)�[�E&I����� ߴ>e �FW�_�kJR�|!���O�:5�/2跌3��T-�'|�zX�� r�yp0��J����S ~^�F�>-�2�< �`*%�ZFP�)����bS��n"���L�� :)���+pʷf(pO���3��TMW$~����>@~ū:����TA�IsV�1}�S2�<���%��ޟ�M�?@�iT ,E�ū�oz%i�~��g�|`wS(�]�oȤ��8��)�$�� �� ntu`өe�`6y�Pl� Iz�MI{�ʣ�z����ʨ�� �)IZ�2��= ld:5+���請M�$-ї���;�U�>_���g��sY��$Á����N�5��W���z�W�fIZ��)�-��y�u�XI�fp���~S*IZ��dt�;�t�>K�ū��KR�|$���#Lc�Ԁ+2�\�;kJ��`]�Y���ǔ��M1B)��U�bG"IRߊ���<x����ܾ��ӔJ�������0�Z����=��'�Y��嵤����� Le�v�e�g��)�$��z���n����V-º����^�3Ւ�o�f��#0�Tfk�^�Z�s[�*I꯳3{���)�ˬ����W�4Ւ4 �Odp��bZ��R���S��|�*I� �����5��5�#��"�&�-IvT&��/��윚Ye:��i�$ �9��{�Lk�u�R���e�[��I~�_�\��ؠ%�>�GL�$iY�8 �9ܕ��"�S���`kS.I�l���C;Ҏ4���x&�>�u_0J��Lr����<��J�2�(^��$5��L� s�=Mg�V� �~�,Ij�u��>�� 7��r2�)^=G���$�1:��3�G< �`J�3�~�&IR%�� 6���T�x�/�rIj���3�O< �ʔ&#f�_yX��J�i�ގN��Sz;�� T�x�(��i���8%���#���4 �~�AS+Ij��e���r�I�U�rIj�����3�62��v8��8�5�+Ij�A�h�K__5���X��%�n�V%Iͳ-y��|7��XV��2��v4���fzo��_6��8���"�S/I-qbf��;� Lk��F�)K���SM�$���� Ms�>K� W�N���V����}�^`��-�큧3����2Œ�Vؙ�G��d��u�,^�^m�%��6���~��N�n�&�͓��3Œ�V�Z����MsRpfE�W���%I�wd���ǀ�Lm[��7���W&�bIR��L�@Q�|�)*�� ����i ImsI�����MmKm�y��V`�i�$��G+R� 0�t�V'����!���V�)֏���28����v���U�7͒�v���H����ꦼt���x�ꗞ�T ;S���}��7�M�f���+��fIR���H��N��ZUk�U�x5��SA�Jㄌ�9��Mq��μ���AIRi|�j�5��)o����*^���'<$�T����w���I�1��hE�U�^c�_�j�?���Е$%d`z� �c�y�f��,X���O IJ�nTg����A�� �����U�XRD��������� ���}�������{�H�}��^�S,P5��V��2���\����Xx`p�Z����|Y�k:����$e�� ��~ ��@nW�L�.j�+��ϝ���Y��b퇪��bZ� �BV�u�)�u�������/IJ_ �1�[�p.p60�bC�� >|X����9�1P�:��N\�!�5�qUB}5�a5ja `ub��c�VxYt1N�0�Z����z���l4����]7­gKj�]�?�4ϻ� ���*���[��b��g$)+À���*x쳀ogO$~,5� �ز���U��S�����9���� lq3�+5�mgw@��n�p1��sso Ӻ=����|�N6 /�g(�Wv7U��;��zωM=��wk�,0���u��T��g�_��`_�P`�uz?�2�yI��!b��`�k���ĸSo��+Q���x%!\��ο����e����|�އ���ԁK��S-s6��pu���_����(ֿ�$�i+��+�T8=�e�Y;��� �צ��P�+p��h�x��WQ���v���*���|p1��. ��ά. XRk�IQ�Y�P,���d�r�Z�� |����� ��������B�%������w��P|�S5`��~́@�i�޾��� E�;��Չaw{o'�Q��?%�iL{u D��?���������N1��B��D������!�o��w�����PHRe��FZ�*�� ���k�_-~����{����E9�b-��~P�`��f��E{AܶB�J�A�FO��� wx6��R�ox�5 K5����=�W����we�������hS8 (��J���C���l�J���~ p+���F���i�;ŗo+��:�bD�#g(��C��"�wA^�� r.�F�8L;�dzd�IH�U�X��݆�Ϟ�X�g� �)I�F����q��e�m��%I�4�d�j&pp�T�{���'{�HO���x�( Rk���6^C�٫����O.�)�3�:s(��۳(Z�?~ٻ8�9�zmT"�PL�tw䥈��5��&b<8GZ-�Y��&�K�?e8,`I��6���e�����(֍x�b8�3 � `���r�����zX�j��)F�=l($I�j� �2*�(F�?h(/9ik:��I`m#�p3�Mg���L�aKj�c�/U��#�n5����S�# �������m(^)=y=đ�x8Ŭ����I���[U]����~S�цA�4�p���$-F �i(��R�,�7C�x�;X��=�c����I��>���{���Km�\ �o(T��v�2������v�x�2q�i����iDJ�N�,���Ҏ����!1f� �5quB�j��1��!�8 �r���D�Fd(���!���W���Ql��,g�S��k����L��1Bx��g'�'�՞�^���ǘ;�p����Q ���P(c���_ IRu����j�g(�W�z ����b�s�#�P�­rz�>���� k�� c&nB=�q+��ؔX���n#r5����)co���*Ũ�+G��?7��<�� |�P�����Q��ӣ'�G�����`uO�d>%M�ct�z�#�� Ԫ�����ڞ�&�7��CaQ��~N�'��-P�.�W`Oedp0�3C!IZc�I�AMP��U�ۀ5�J�<��\u~+�{�9�(Fb�b���y�A�e�B����hOS���ܳ�1� b��È���T�#��ŠyDžs�����,`5�}��D���C�-�`��̞%r&�ڙa��8�7Q����W����W����p6e7� ��Rϫ/�o����Y� ꇅ N��ܶ�ը��tc��!��L���A ���T�7�V4�J�sū� I-�0����P��x�z7�QN�F���_�i����Z�g�úW�k�G���83� ���0e�Wr9 X����]㾮݁#���Jˢ C�}0��=3�ݱ��tB��i�]�_ ��&�{�{[/�o[�~ \q�鯜�0��0��٩���|��cD��3�=4��B_b� ���RY��b$ó�BR���sf�&������l�L�X#M*��C����_�L܄:gx�)WΘs���GSb���u��L ���rF$9�'�;\4�Ɍ�q�'�n�[%p.�Q`�������u ��h���N�b`eCQyQ|���l�_���C>L���b꟟3h��Sb�� �#��x��N��xS���������s^�� 88�|�Mz�)��}:�](vbۢ�amŖ࿥� ��0)Q����7���@�0���=?^k(*�J�����}�3ib�kF�n H�jB׻���NO���� �z�� �x}�7p 0�t��f����D����X�.lw��gȔ��h�Ծ�Ų� }6�g� E� |�Lk��LZ���t��eu+=���q���\I�v0쮑�)��Q�ٵpH8�/2?Σ�o�>�J�vpp��h�������o~�f>%bM��M���}���\�//��":�PT��c(v���9v���!��g�ո��Q ��)��U�fV��G��+!� ��35{=�x\�2�+��k�i,y$���~A1��iC�6#)v��C�5�^>�+gǵ�@1�Hy٪7����u;p ps�ϰ�u���/S�� <��aʸ����Gu't�D1�ԝI��<��p��g|����6�j��'p:�tպ�h��X�{�o(7v],��*�}��6�a_����<�u`��Ȯ�r.E�;ˑ�q�io�p�R��"������26�2E�8j�� ]����U��鿍ǜ�v���D��,2���վ�8ϫ�:�e/^AQ����T�H{�WgRl���̊���2Yx���"1�Q�> �wX�Rk,O�]�Lܳ���~V<�����F���8��a��_g~�o.�XCD�?S�t���h���梫A�o�%���~K1ݵ��O1�LyZ�bJ�� E��Q���xpq�i�Cpv��a6��_�:�wejT����]����"����<��u`"���� 2>���o4��5rp"N5k��;�m���{���rZ�b������Φ${#)��`(��Ŵ�g�,;j���%�6�j���.�pyYT��?}-��kB������D���c3q����A`��N��WQ���ū2�0�/^A��Z�W%�N�Q��� ��MI�.��X#P��#����,^Eb�c&��?X�R tA�V�|Y���.�1����!�����؅�⨉ccww���>���i��v��l(J��T�~� �u`��ٵDm �q)���+���Ri�� x/�x��8cyFO�!�/���*�!/��&��,7�<.���N���,�������YDŽ�&ܑ�Q�F1�Bz��)F���P�ʛ�?5����d� �6`�����kQձ �λc�؎�%58�2��Y��&nD�_$Je4��>a��?��!� ��ͨ�|�Ȏ�WZ��S�s��v���8� �j����(�I��&��y�j� �Jb5��m��?��H������Wp��=����g}�G��3��#�|I��,5v珿�] H~�R3�@B��������[☉9Ox~��oMy�=J���;�xUVoj�� �b�U�s�l_��35�t-�(Ճɼ�RB7�U!�q��c��+�x�4�H�_�Q�o֮$[���GO<��4`��&č�\GO�c[�.[*�A�f%m��G/� ň�M�/�r ��W�/Nw~B1U3������J�?��P&���Y�� �)`�ѓ����Z�����1���p]�^l“��W#)lWZ�i����l�U�Q�u`��-����m|xĐ,������_�ƪ|9i:�_��{*(3G�ѧ}�Uo�D+�>m_�?V��Pۅ�15���&}2�|���/p�IOʵ�>���� G�Z9�cmíت�mnz��)yߐb���D�������� �>e}:�)� �r|@�R5q�V�S�����A�10�C%�E�_��'^�8c��������R��7O;�6�[���eKeP�������G������ϦX7�j���b}��OT�GO^j��n*媓����7n����GMC�� � ���t,�k31�R�b �(v�yܴ�ʭ�!��iTh8~�ZY�Z�p��(q��s���RL ?�b���}����c�Ũ�ʊGO^���!��rP�JO��1��5�MJ[��c&~������Z`"��ѓޔ����H1���C&����^|��Ш|�rʼ,�A�wĴ?�����b��5)�t��L��U��)F�|�� �&��g٣O]���oqSU����j���y(��x<��Ϳ3 ���.���FS�k���oYg�2� \_#w��j�{u'r�Q������>���o���;���%n�|�F�*�O�_��L�"�e�9um��Dds�����?.��fu�u����Qb��IW�z |4\0� s�b;�O�v��xOS�s�; G%����T4g��FR�u�rj���(֍ڑb �u�ԖK�D���u��1MK{���1^ q;�� �C=�6\8��F��R��艇�!���%\Y�Ô�U| �88�m��)֓��Nc��L�ve�� C�6z;��o&�X x5�9�:q���6�1�Z��(T����7���>C?�g�c�ļ�x�ѐ�� Z� ���o�o-�0�8j�ہ �x�,�`���'��� ��Ҕ���Oc��Rl��f��~���`�����jj�"�.N�v+���sM������_��]������Z�k��� �g( UOP���������y�εx%�pU����h�2�������(���@��il0���ݽ��QXxp�px-�N�S��( W�O+�轾 n��Fߢ����3M��<;z�)��FBZ�j����c�i��u�/�Q�oF�� �7R�¥ Z��F�L�F�~��#����ȣ��ߨ^<쩡�ݛк���v�џ)��)���M��E>ώ�x4�m#!-�m���!L;vv#~Y[��đ��K�����m����x�9.[,��U����FS �����C���VkZ ���+���ߟ�r�Y٧��IZd/�io�i$�%��͝ب_ֶX�3���ܫ��hNU �� Z����Z�g�k�=���]��=������b���b��JS[�w��j�U(��)���*I =ώ:}-蹞�l�Uj�:��1��}����M�W��m�=̛���� _�� ¾,8��{__�����m{_�P��V���K^n3�e����sw5�ӫh�#�$-�q=�A̟> ,^I}P�^�J$�qY~Q[ Xq���9�<�r�d�sߏǜs�#������%/���y����kKZ�������b��?� S�k�tc�񫝶L���&I ���W!�b �>{#�&�T.^����G��Vj�_���_R��K�p����n,b=`�ż����Y@�^՝��;z�{p�aV��Kk����QXj�/�)y� ��TI�c&F�;FB�G�7w����g� ZZD�G��!����x�� �r_�t��Ƣ!�}�i�/�V��=M����/��#��n��B8 Xx�Ы ^�@�CR�<{䤭����Y��CN��)�e���K��OSƟa $��&�g[i3�.C�6x�rOc���8�TI���;�o�� ��hH6�P�&L{�@�q��6�[���� �G��zp�^���71�j��(�l�`�J�}]���e6�X����☉#͕� ���׈$A�B1�Vj��h㭦IRs��qFBj�w�Q_7�Xk��>y"������N=�M�B0� ��,�C #�o6MR��c���0��|�$�)�ف����"1����!i���xY<���B��9mx�� ��`���,��t�A�>)5ػ�Q���?j��Q�?�cn�>Y�Z�e�� �Tis���v���h�#�� �GMމȇ���p�:���ԴVuږ�8ɼH��]C.���5C!UV;F`m�b��Bk��� ��L�TM�vP���ʍϤj�?��ԯ/Q�r1���N�B`9s"����s�� �TYs����z��� ��&�9S%U԰�> �{��<�ؿ���SM���xB��|H�\3�@!U�|�� �k']������$U�+>��� |�HHM����Lޢ�?��V9i�D!-�@��x�� �TI���î�%�6Z��*��9X�@HMW#�?��n�N� ,o�e6�?tQw��ڱ�.�]-����y����'�:mW�0#!�J82qF�jH -`�ѓ�&��M��0����u� Uγmxϵ��^-��_�\�]����)@0R���t.8�/?ٰ�C��Y]�x���}=sD3�o��j�ަ���Ы�N���uS%U��}Ԥw��HH�>ڗ�jܷ_3gN �����q7�[q���2�l���a���*����A�r���Ǔ��Ԗ+p�8���/��R��GM�� ]j�a����c�d(�JhWko�6��ڎb�j�]i���5���Bj�����3+�3�!\j��1�����U�Z���L��s��L�T�v8�HHmup<��U���\��GMމ�3�R+��w4R�����6�j� XW�M�T!��u(�*!��Pz�,����#���Sq���*�8?vww )kO���a��$�[&��?�*�bB�X� �@���%�����8�]�=���R�r)kO��w�0j��i��M�Tq�� ng$�2\�q�8f�:���e�N1�R�xr<��5 ������;��M��p^�@;��7]R��ꎾ�JtER�.�/(5�v3�R[�@=�h�l����?����l�@;���.���[]�Q*�Z\�4��"1P�'Y��w��x��# ���ǀg���{��5�i��_IUR���z�RɞsyS5q�E����=�@�Y���っ �����v�k��6 ��&��5�1E�o0�|�kp�c��#�j=`�D���WRU�����j̟���J'P� �����w2 �S� �v�:��p�g�3Rv�},�#�����8�b��Z~�&��(F�=�i�><�>gK�M���Jj����0�@H%��,����W�΃�7�R) "�>c�,����� x�ix������ј���^ ��aܖ>�H[�i.UI�Hc �U�1=y�W\���=��S*���G���R~�)AF���=�`�&�����2��h`�D�z���T��󑓶�����J+����?�W+}��C�%��P:|�0H���܆��}-�<;O����C[�~o.��$~��i�}��~�HQ�� �Tv�X������Έ�r=b}$��v����i�z�L��4�:�ȰT|4�~����*��!o�X�QR6��L�k+�#������t/g �lԁߖ����[��Jڶ_N$�k���������*"�.� ���x���s��xX���7jRVbA��A�ʯKҎ��U3����)�zS�NN �_�'��s�?f����)��6������X���!%s�s�A���kʱ>���qƷ�b ��h�g� %n���� �~p�1RE��GM���HH�=�������B�Jiy[<�5 ���ǁJҖ�����g�K���R��*�倳��e��~�HUy��)A���g,K)`�V�w6bRR:��q����L#\�r���cl��K��/�$�s�h�*$�� ������6�����덤�� ����KԖc� 3��Z�9��=�Ɣ�=o>�X � �Ώ�"1�� )a��`�S��JJ�6�k<��U�������-]�� b�m`��{r�y;����T���u��_GR5���*�%6�do�#XRg#���-!nl��$u�3��A�� L+Q{��9�x~�a-�|�H� �vbq[\�NJT%�]���rO8,��E�-F�����w)+?(Y{�Lz�n6����׀��?C������R�~�,)m�䎧�R�7���cww����qpW�ڳ=i.��U`Xf�F�b=�V��LJ��H^LI}��%�} ��|��w���� aG�$�,��^�R^�6 k2�^B�{7��t�������V�%@G�q� p�%R�zģN_ ��HHI[7�ֱ�>(��<�c e�{%kϊ����P�+��SL'�T�cM���J����WR���m ���ŏ�"�w)qc e�f�꒵i?��b7�b����(�'�"��2r%��������~�HUS�1���\<��(`�1�W����x��9�=�8HY9��m:X��1�8�b��g�����D1��u ���~|H��;K��-��U�ep�,,� C�1 RV.���M�R�5�άh����,�t��W�O8W���C�$ XRV�sQS]3G�J|�1��2����� [�v�M� ������:��k�#����~tH�3�0Rf-�����HYݺ-`I�9�%l�I��D�T�m\ ����S�{]��9�gO���ڒ�M���NCV\��G��*����2���J�R�Ũ;�R��ҏ^���ڽ�̱�mq�1E�u?�To�3I���)��y^��#�j�J�w���^�Ń�j��^�v����vl����B_��⋌�P�4x>0$�c>���K†A�ļ9s_V���jT��t0l�#������m��>E��-�,�,�x�,��-�W��)������سo&�9�6�R�E XR.6b���Xw�+)G���A�����E�v�L�)�͞K4�$p=�Ũ��i_ѱ�O�j��b�� HY����/���+@�θH9޼]�N�ԥ��%n�{����� �&zjT�?�� �Ty) s^�U��L�����lb�,�P�iTf�^���<À�]������� ��62R^V��7)S!nl�l��S�6~�͝�V�}�-=%*� ʻ>���G�� ���������D��nK��<��y��&>L����Py7'r=Hj���� ���9��V`[c"�*��^�8H��pc�����O�8�b�nU�`4���J��ȪA�Ƌ#��1_\ XϘH��PR���gi�k(�~G�~��0��D���A���A����_2�p�|�J�묭a����2���\N�C�r�]����M���_0 �^T��%e#����vD��^��%��x��y-n���}�-E�\�3�aS%�yN!�r_��{ �)s���A��w ���ڼp1pEAk�~v�<�:`'ӭ^�5 �����A�r���X�������OI驻��T �(��dk�)�_�\<��w���^��W�I��"�RFj3��V# ���M<,o�J��.H��#�\�SK���s]���� )��9> P��u�������A�*�B�Y�]����y�B�"�l�\�ey��� ��hH���*t��b�K)3��� IK�Z��򹞋X�jN�� �n� �*n>k�]��X�_��d�!�ry��BH� � ]��*R�� ��0(#'�7 ������%es9??��ښFC��,ՁQP��������j�����AR��J�\Ρw� �K��#��j���ah�g�w�;�2$�l*�)� ��%���Xq5�!U᢯�6Re] |�0����[�_�����_64�c�h�&�_}��i�L8K��Eg�Ҏ�7 M��/�\`|.p,�~`�a���=�BR?x�ܐrQ���8K� XR���2M�8�f ?�`s�gW�S%�"� ������Ԉ 7R%���$� N������}��?QL1|-э�ټwI�Z��%���pv�L���3Hk>,I����m�g�W���7{��E�� x�PHx�7�3R�����A�� ���@R�S�� CC���� �������!\ȟ���5I��XR^Z���xHл�$Q[��ŝ�40 (�>�+� �_C ���>���BR�t��<,T�r�T �������{���O�����/�H��+˟Pl6 I ���B)/�V���C��<6���a��2����~�����(�XwV4�g�n���XR� ϱ5�ǀHٻ?tw�똤Eyxp���{�#���WK��� �q����G%5���]�,���(�0ӈH����� HZ���])ג=K1j��&��G(FbM�@����)%�I` XR�����g ʔ�� KZ�G(v��P,�<`�[� K���n^ ��SJR���sAʠ�5xՅF`�0&R�b�V� ��t��x�:Ea�UE�/{�f��i�2;.I����A��wW8��/��t�T�x�A��GOo��N�?�G���}�l L�(���n�����`�Zv?���p�B��8K�_g�����I�+ܗ � #��i��?���ޙ�.��) p����$�u�tc �~DžfՈE�o3��l/)I-U�?a�ԅ�^��j�x�A�r����A�� ΧX��������}�DmZ@QLےbTXGd�.^|x�KHR{���|Ε�W_h]�� ���I��J`[�G9�{��)�.y�)�� ��<���D�*��zk�(ּ���Ya����O���8S����?��2-��� ������H13����#pK"���I`]`O� ��h�&=�S���F1Z�/Ie����D1R�W�a�"t'�x?!)Ou:��1 ��|��6��gt\s�����7�=�z_;�ؠ��>�0X Y��A1]q�p?�p�_���k+J*��Y�@HI>�^��?�g�t.06R�n ��,��`�� ��?)�;p pSF9����Z����X���L�����BJP�W���j���gQ|�&)7!�� Hj��Q��t���<| ؅��W�5 x �W��� �� HIz�Y���oV���M�G�P��� Hj��n`+�\�(d��N���W)F+I�rS�[���|��/a�����`K��|�ͻ�0Hj�{�R,���Q=��\� (F�}\�W�������R)A�g��SG`I��s�n���AR�=|�8�$}�G(v��C��$)s���� FBJ�?]�_�u XRv�ύ��6z�� �Ũ�G[��3��6-�T9�H��z��p����W�̞ú������� X�����g�큽�=�7C�u������fzI���$��)�k�i���^q��k��-) � ���0H*�N` �QZ��k�k]/���t���nn���sI�^Gu't=��7$�� Z;�{���8�^��jB��%� ��IItR�QS7�[�ϭ���3 �$�_���O�Q�J`7�!�]���W��"��W,)�����Iy �W��� �AJA�;K���WG��`IY�{8���k$I�$�^��%����9�.�^(`��N|���LJ�%�@�$I�}ֽp���=FB*�xN��=gI?Q{٥�4B)m���w �$I���gc~d��Z@G�9K��� X�?7)a�K�%�݅K�$IZ��-`I���p����C ������U��6�$I��\0��>!��9�k}��� Xa� ����II�S���0H�$I �H ?1R��.�Ч�j���:�4~R�w���@p�$I����r��A*�u��}��W�j�WFPJ����$I�➓/���6#!�� L�Ӿ��+ X36�x�8J �|+L;v���$I���o�4����3���0����1�R2�0��M� I�$-E}��@����,pS�^ޟR[���/����s¹'��0H�$IKyf��Ÿ���f�������VO�π�FT*�����a$I��>��H��e��~����V���Y/3�R�/�)��>d$I��>2��8`Cj���w�,n@�FU*�9tt�f$I��~<;��=�/4RD~����@��� X��-�ѕ�z��ἱI�$��:� ԍ��R �a�@��b X��{��+�Qx��u�q�$I�Л�z�o���� /~3\8����ڒ���4B������N7�$IҀ���j �V]n1�8H�$I��YFBj�3��̚�̵���ja ����p���p��� �$I���s/3R� Ӻ�-�Yj+L;�.0�R�́��I�$�A���v?� #!5�"��aʄ��j}���U���Km�ɽ��H�$Ij��C���Ys?h$I��Dl8�4��3���.��v�}���m���7�UiI=�&�=0L�g0$I��4���: ���emb�e��`���� e�Qbm�0u�? �$I�T!Sƍ'�-���s��v�)s#C��0�:�XB���2���a� w I�$�zbww�{�."p��Pz�O� �=�Ɔ�\����[� �����o($I������aw]�`���E���).K���v�i�:�L�*#gР7[��$I�����yG���PI=@��R� �4�y��R~�̮�´cg I�$I/<�t�P�ͽ ��h�Dg�o� 94����Z^k盇�΄8��I���56��^�W�$I�^�0���̜�N�?4*�H`237}g��+h���x�o��q)��SJ@p|�`�� �$I��%>������-�h���O�0e�O�>��\ԣNߌZ��D6��R�=K ����~n($I�$��y�3��D>o4�b#px�2���$��yڪt���z���W���~a�� �$I��~?�x<��e{W���g��ô�{�x$/�=�{t�G�0�7��e���a���B�$IҀ�yG��^S�卆�"puS��3��*�E=洣��,`9�>��'���Bww�pH�$IZ��ݑ�nC�㧄���Pc�_9��sO gw����J=l1�:mKB�>�����Ab<4L�p���$I�����b �o1Z���Q�@8�5�b�̍ S'�F���,�F��e���,^I�$Ij���E�dù{�l4� �8�Ys_�s� Z8.��x �m"+{~��?q,��Z D�!I�$��ϻ�'|X�h��B�)=��…'�]��M�>��5��� r�g���otԎ 獽�PH�$Ij����IP���hh)n#�cÔq���A'�ug5qw���U�&r�F|1��E%I�$%����]��!'�3�AFD/;C�k_`�9��� �v�!ٴt�PV�;��x`�'��*b�Qa� w I�$I�x�5� �����FC�3D����_��~��A�_�#O݆���Dv��V?<���q�w�+I�$I�{��=�Z�8"�.#RI���Y�yj���Ǫ����=f�D�l�9�%�M�,�����a8$I�$��Yw�i[�7�ݍFe�$�s��1��ՋBV�A?�`�]#!��oz����4zjLJ���o8$I�$%�@3j�A��a4��(�o�� �;�p,,dya�=��F9ً[��LS���PH�$IJ�Y�Љ+3��> 5"���3�9�aZ�<ñh!�{T�pB�G��k��j}��S�p��� �$I��lvF��.���F$I� ��z<� '\���K*qq��.f�<���2�Y�!�S"-\I�$I��Yw�č��jF$ w9��� \ߪB�.�1�v!Ʊ���?+��r�:�^�!I�$�BϹ�B� ����H��"�B�;L��'G[ 4�U�����#5>�੐�)|#�o0��aڱ���$I���>�}��k&�1`U#�V��?��Ys��V x���>�{t���1�[�I~D���&(I�$I/{��H�0fw�"�q"���y�%��4����� I�X�y�E~��M�3 8Xψ��L}q�������E�$I���[�> �nD�?~�s����f��� �����]o�΁� �cT��6"?'�_�Ἣ� �$I��>�~��.f�|'!������N�?�⟩����0��G KkX�Z�E��]�ޡ;�����/����&�?k�� O�ۘH�$IR��������ۀw�XӨ��<�7@��P��nS��04�a����Ӷ�p�.��:��@���\IWQ�J6�s�S%I�$���e��5��ڑ���v`�3:���x'�;��w��q_�vp�gHyX�Z� ��3�gЂ7{{���E�����uԹ�n�±��}�$I�$��������8t;b|��5��91n��ء����Q"�P������6���O�5�i���� }�i�R�̈́���%�Q�̄p!�I䮢�]��������O{�H�$IR�ϻ�9��s֧�� a=`-� aB\X��0"+5"C�1�H�b?߮����3x��3�&�g�ş�g��g����l��_���h�����Z^,`5�?���ߎ��vĸ%�̀M!�OZC2#0x ����LJ��0�� �G�w����$I�$I�}�<�{Eb�+y���;�iI,`����ܚ��F�����:�5��ܛ�A�8���-O�-|�8�K�7��s�|#�Z8�a&�>���<��a&����/V��tb�t��L��ʌI�$I�$I�$I�$I�$I�$IRj���D��D�%tEXtdate:create2022-05-31T04:40:26+00:00�!Î%tEXtdate:modify2022-05-31T04:40:26+00:00�|{2IEND�B`�Mini Shell

HOME


Mini Shell 1.0
DIR:/home/htlwork.com/www/himsaral/node_modules/@remix-run/router/dist/
Upload File :
Current File : /home/htlwork.com/www/himsaral/node_modules/@remix-run/router/dist/router.umd.js
/**
 * @remix-run/router v1.1.0
 *
 * Copyright (c) Remix Software Inc.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE.md file in the root directory of this source tree.
 *
 * @license MIT
 */
(function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
  typeof define === 'function' && define.amd ? define(['exports'], factory) :
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.RemixRouter = {}));
})(this, (function (exports) { 'use strict';

  function _extends() {
    _extends = Object.assign ? Object.assign.bind() : function (target) {
      for (var i = 1; i < arguments.length; i++) {
        var source = arguments[i];

        for (var key in source) {
          if (Object.prototype.hasOwnProperty.call(source, key)) {
            target[key] = source[key];
          }
        }
      }

      return target;
    };
    return _extends.apply(this, arguments);
  }

  ////////////////////////////////////////////////////////////////////////////////
  //#region Types and Constants
  ////////////////////////////////////////////////////////////////////////////////

  /**
   * Actions represent the type of change to a location value.
   */
  exports.Action = void 0;
  /**
   * The pathname, search, and hash values of a URL.
   */

  (function (Action) {
    Action["Pop"] = "POP";
    Action["Push"] = "PUSH";
    Action["Replace"] = "REPLACE";
  })(exports.Action || (exports.Action = {}));

  const PopStateEventType = "popstate"; //#endregion
  ////////////////////////////////////////////////////////////////////////////////
  //#region Memory History
  ////////////////////////////////////////////////////////////////////////////////

  /**
   * A user-supplied object that describes a location. Used when providing
   * entries to `createMemoryHistory` via its `initialEntries` option.
   */

  /**
   * Memory history stores the current location in memory. It is designed for use
   * in stateful non-browser environments like tests and React Native.
   */
  function createMemoryHistory(options) {
    if (options === void 0) {
      options = {};
    }

    let {
      initialEntries = ["/"],
      initialIndex,
      v5Compat = false
    } = options;
    let entries; // Declare so we can access from createMemoryLocation

    entries = initialEntries.map((entry, index) => createMemoryLocation(entry, typeof entry === "string" ? null : entry.state, index === 0 ? "default" : undefined));
    let index = clampIndex(initialIndex == null ? entries.length - 1 : initialIndex);
    let action = exports.Action.Pop;
    let listener = null;

    function clampIndex(n) {
      return Math.min(Math.max(n, 0), entries.length - 1);
    }

    function getCurrentLocation() {
      return entries[index];
    }

    function createMemoryLocation(to, state, key) {
      if (state === void 0) {
        state = null;
      }

      let location = createLocation(entries ? getCurrentLocation().pathname : "/", to, state, key);
      warning$1(location.pathname.charAt(0) === "/", "relative pathnames are not supported in memory history: " + JSON.stringify(to));
      return location;
    }

    let history = {
      get index() {
        return index;
      },

      get action() {
        return action;
      },

      get location() {
        return getCurrentLocation();
      },

      createHref(to) {
        return typeof to === "string" ? to : createPath(to);
      },

      encodeLocation(to) {
        let path = typeof to === "string" ? parsePath(to) : to;
        return {
          pathname: path.pathname || "",
          search: path.search || "",
          hash: path.hash || ""
        };
      },

      push(to, state) {
        action = exports.Action.Push;
        let nextLocation = createMemoryLocation(to, state);
        index += 1;
        entries.splice(index, entries.length, nextLocation);

        if (v5Compat && listener) {
          listener({
            action,
            location: nextLocation
          });
        }
      },

      replace(to, state) {
        action = exports.Action.Replace;
        let nextLocation = createMemoryLocation(to, state);
        entries[index] = nextLocation;

        if (v5Compat && listener) {
          listener({
            action,
            location: nextLocation
          });
        }
      },

      go(delta) {
        action = exports.Action.Pop;
        index = clampIndex(index + delta);

        if (listener) {
          listener({
            action,
            location: getCurrentLocation()
          });
        }
      },

      listen(fn) {
        listener = fn;
        return () => {
          listener = null;
        };
      }

    };
    return history;
  } //#endregion
  ////////////////////////////////////////////////////////////////////////////////
  //#region Browser History
  ////////////////////////////////////////////////////////////////////////////////

  /**
   * A browser history stores the current location in regular URLs in a web
   * browser environment. This is the standard for most web apps and provides the
   * cleanest URLs the browser's address bar.
   *
   * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#browserhistory
   */

  /**
   * Browser history stores the location in regular URLs. This is the standard for
   * most web apps, but it requires some configuration on the server to ensure you
   * serve the same app at multiple URLs.
   *
   * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createbrowserhistory
   */
  function createBrowserHistory(options) {
    if (options === void 0) {
      options = {};
    }

    function createBrowserLocation(window, globalHistory) {
      let {
        pathname,
        search,
        hash
      } = window.location;
      return createLocation("", {
        pathname,
        search,
        hash
      }, // state defaults to `null` because `window.history.state` does
      globalHistory.state && globalHistory.state.usr || null, globalHistory.state && globalHistory.state.key || "default");
    }

    function createBrowserHref(window, to) {
      return typeof to === "string" ? to : createPath(to);
    }

    return getUrlBasedHistory(createBrowserLocation, createBrowserHref, null, options);
  } //#endregion
  ////////////////////////////////////////////////////////////////////////////////
  //#region Hash History
  ////////////////////////////////////////////////////////////////////////////////

  /**
   * A hash history stores the current location in the fragment identifier portion
   * of the URL in a web browser environment.
   *
   * This is ideal for apps that do not control the server for some reason
   * (because the fragment identifier is never sent to the server), including some
   * shared hosting environments that do not provide fine-grained controls over
   * which pages are served at which URLs.
   *
   * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#hashhistory
   */

  /**
   * Hash history stores the location in window.location.hash. This makes it ideal
   * for situations where you don't want to send the location to the server for
   * some reason, either because you do cannot configure it or the URL space is
   * reserved for something else.
   *
   * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createhashhistory
   */
  function createHashHistory(options) {
    if (options === void 0) {
      options = {};
    }

    function createHashLocation(window, globalHistory) {
      let {
        pathname = "/",
        search = "",
        hash = ""
      } = parsePath(window.location.hash.substr(1));
      return createLocation("", {
        pathname,
        search,
        hash
      }, // state defaults to `null` because `window.history.state` does
      globalHistory.state && globalHistory.state.usr || null, globalHistory.state && globalHistory.state.key || "default");
    }

    function createHashHref(window, to) {
      let base = window.document.querySelector("base");
      let href = "";

      if (base && base.getAttribute("href")) {
        let url = window.location.href;
        let hashIndex = url.indexOf("#");
        href = hashIndex === -1 ? url : url.slice(0, hashIndex);
      }

      return href + "#" + (typeof to === "string" ? to : createPath(to));
    }

    function validateHashLocation(location, to) {
      warning$1(location.pathname.charAt(0) === "/", "relative pathnames are not supported in hash history.push(" + JSON.stringify(to) + ")");
    }

    return getUrlBasedHistory(createHashLocation, createHashHref, validateHashLocation, options);
  } //#endregion
  ////////////////////////////////////////////////////////////////////////////////
  //#region UTILS
  ////////////////////////////////////////////////////////////////////////////////

  /**
   * @private
   */

  function invariant(value, message) {
    if (value === false || value === null || typeof value === "undefined") {
      throw new Error(message);
    }
  }

  function warning$1(cond, message) {
    if (!cond) {
      // eslint-disable-next-line no-console
      if (typeof console !== "undefined") console.warn(message);

      try {
        // Welcome to debugging history!
        //
        // This error is thrown as a convenience so you can more easily
        // find the source for a warning that appears in the console by
        // enabling "pause on exceptions" in your JavaScript debugger.
        throw new Error(message); // eslint-disable-next-line no-empty
      } catch (e) {}
    }
  }

  function createKey() {
    return Math.random().toString(36).substr(2, 8);
  }
  /**
   * For browser-based histories, we combine the state and key into an object
   */


  function getHistoryState(location) {
    return {
      usr: location.state,
      key: location.key
    };
  }
  /**
   * Creates a Location object with a unique key from the given Path
   */


  function createLocation(current, to, state, key) {
    if (state === void 0) {
      state = null;
    }

    let location = _extends({
      pathname: typeof current === "string" ? current : current.pathname,
      search: "",
      hash: ""
    }, typeof to === "string" ? parsePath(to) : to, {
      state,
      // TODO: This could be cleaned up.  push/replace should probably just take
      // full Locations now and avoid the need to run through this flow at all
      // But that's a pretty big refactor to the current test suite so going to
      // keep as is for the time being and just let any incoming keys take precedence
      key: to && to.key || key || createKey()
    });

    return location;
  }
  /**
   * Creates a string URL path from the given pathname, search, and hash components.
   */

  function createPath(_ref) {
    let {
      pathname = "/",
      search = "",
      hash = ""
    } = _ref;
    if (search && search !== "?") pathname += search.charAt(0) === "?" ? search : "?" + search;
    if (hash && hash !== "#") pathname += hash.charAt(0) === "#" ? hash : "#" + hash;
    return pathname;
  }
  /**
   * Parses a string URL path into its separate pathname, search, and hash components.
   */

  function parsePath(path) {
    let parsedPath = {};

    if (path) {
      let hashIndex = path.indexOf("#");

      if (hashIndex >= 0) {
        parsedPath.hash = path.substr(hashIndex);
        path = path.substr(0, hashIndex);
      }

      let searchIndex = path.indexOf("?");

      if (searchIndex >= 0) {
        parsedPath.search = path.substr(searchIndex);
        path = path.substr(0, searchIndex);
      }

      if (path) {
        parsedPath.pathname = path;
      }
    }

    return parsedPath;
  }
  function createClientSideURL(location) {
    // window.location.origin is "null" (the literal string value) in Firefox
    // under certain conditions, notably when serving from a local HTML file
    // See https://bugzilla.mozilla.org/show_bug.cgi?id=878297
    let base = typeof window !== "undefined" && typeof window.location !== "undefined" && window.location.origin !== "null" ? window.location.origin : window.location.href;
    let href = typeof location === "string" ? location : createPath(location);
    invariant(base, "No window.location.(origin|href) available to create URL for href: " + href);
    return new URL(href, base);
  }

  function getUrlBasedHistory(getLocation, createHref, validateLocation, options) {
    if (options === void 0) {
      options = {};
    }

    let {
      window = document.defaultView,
      v5Compat = false
    } = options;
    let globalHistory = window.history;
    let action = exports.Action.Pop;
    let listener = null;

    function handlePop() {
      action = exports.Action.Pop;

      if (listener) {
        listener({
          action,
          location: history.location
        });
      }
    }

    function push(to, state) {
      action = exports.Action.Push;
      let location = createLocation(history.location, to, state);
      if (validateLocation) validateLocation(location, to);
      let historyState = getHistoryState(location);
      let url = history.createHref(location); // try...catch because iOS limits us to 100 pushState calls :/

      try {
        globalHistory.pushState(historyState, "", url);
      } catch (error) {
        // They are going to lose state here, but there is no real
        // way to warn them about it since the page will refresh...
        window.location.assign(url);
      }

      if (v5Compat && listener) {
        listener({
          action,
          location: history.location
        });
      }
    }

    function replace(to, state) {
      action = exports.Action.Replace;
      let location = createLocation(history.location, to, state);
      if (validateLocation) validateLocation(location, to);
      let historyState = getHistoryState(location);
      let url = history.createHref(location);
      globalHistory.replaceState(historyState, "", url);

      if (v5Compat && listener) {
        listener({
          action,
          location: history.location
        });
      }
    }

    let history = {
      get action() {
        return action;
      },

      get location() {
        return getLocation(window, globalHistory);
      },

      listen(fn) {
        if (listener) {
          throw new Error("A history only accepts one active listener");
        }

        window.addEventListener(PopStateEventType, handlePop);
        listener = fn;
        return () => {
          window.removeEventListener(PopStateEventType, handlePop);
          listener = null;
        };
      },

      createHref(to) {
        return createHref(window, to);
      },

      encodeLocation(to) {
        // Encode a Location the same way window.location would
        let url = createClientSideURL(typeof to === "string" ? to : createPath(to));
        return {
          pathname: url.pathname,
          search: url.search,
          hash: url.hash
        };
      },

      push,
      replace,

      go(n) {
        return globalHistory.go(n);
      }

    };
    return history;
  } //#endregion

  /**
   * Map of routeId -> data returned from a loader/action/error
   */

  let ResultType;
  /**
   * Successful result from a loader or action
   */

  (function (ResultType) {
    ResultType["data"] = "data";
    ResultType["deferred"] = "deferred";
    ResultType["redirect"] = "redirect";
    ResultType["error"] = "error";
  })(ResultType || (ResultType = {}));

  function isIndexRoute(route) {
    return route.index === true;
  } // Walk the route tree generating unique IDs where necessary so we are working
  // solely with AgnosticDataRouteObject's within the Router


  function convertRoutesToDataRoutes(routes, parentPath, allIds) {
    if (parentPath === void 0) {
      parentPath = [];
    }

    if (allIds === void 0) {
      allIds = new Set();
    }

    return routes.map((route, index) => {
      let treePath = [...parentPath, index];
      let id = typeof route.id === "string" ? route.id : treePath.join("-");
      invariant(route.index !== true || !route.children, "Cannot specify children on an index route");
      invariant(!allIds.has(id), "Found a route id collision on id \"" + id + "\".  Route " + "id's must be globally unique within Data Router usages");
      allIds.add(id);

      if (isIndexRoute(route)) {
        let indexRoute = _extends({}, route, {
          id
        });

        return indexRoute;
      } else {
        let pathOrLayoutRoute = _extends({}, route, {
          id,
          children: route.children ? convertRoutesToDataRoutes(route.children, treePath, allIds) : undefined
        });

        return pathOrLayoutRoute;
      }
    });
  }
  /**
   * Matches the given routes to a location and returns the match data.
   *
   * @see https://reactrouter.com/utils/match-routes
   */

  function matchRoutes(routes, locationArg, basename) {
    if (basename === void 0) {
      basename = "/";
    }

    let location = typeof locationArg === "string" ? parsePath(locationArg) : locationArg;
    let pathname = stripBasename(location.pathname || "/", basename);

    if (pathname == null) {
      return null;
    }

    let branches = flattenRoutes(routes);
    rankRouteBranches(branches);
    let matches = null;

    for (let i = 0; matches == null && i < branches.length; ++i) {
      matches = matchRouteBranch(branches[i], // Incoming pathnames are generally encoded from either window.location
      // or from router.navigate, but we want to match against the unencoded
      // paths in the route definitions.  Memory router locations won't be
      // encoded here but there also shouldn't be anything to decode so this
      // should be a safe operation.  This avoids needing matchRoutes to be
      // history-aware.
      safelyDecodeURI(pathname));
    }

    return matches;
  }

  function flattenRoutes(routes, branches, parentsMeta, parentPath) {
    if (branches === void 0) {
      branches = [];
    }

    if (parentsMeta === void 0) {
      parentsMeta = [];
    }

    if (parentPath === void 0) {
      parentPath = "";
    }

    let flattenRoute = (route, index, relativePath) => {
      let meta = {
        relativePath: relativePath === undefined ? route.path || "" : relativePath,
        caseSensitive: route.caseSensitive === true,
        childrenIndex: index,
        route
      };

      if (meta.relativePath.startsWith("/")) {
        invariant(meta.relativePath.startsWith(parentPath), "Absolute route path \"" + meta.relativePath + "\" nested under path " + ("\"" + parentPath + "\" is not valid. An absolute child route path ") + "must start with the combined path of all its parent routes.");
        meta.relativePath = meta.relativePath.slice(parentPath.length);
      }

      let path = joinPaths([parentPath, meta.relativePath]);
      let routesMeta = parentsMeta.concat(meta); // Add the children before adding this route to the array so we traverse the
      // route tree depth-first and child routes appear before their parents in
      // the "flattened" version.

      if (route.children && route.children.length > 0) {
        invariant( // Our types know better, but runtime JS may not!
        // @ts-expect-error
        route.index !== true, "Index routes must not have child routes. Please remove " + ("all child routes from route path \"" + path + "\"."));
        flattenRoutes(route.children, branches, routesMeta, path);
      } // Routes without a path shouldn't ever match by themselves unless they are
      // index routes, so don't add them to the list of possible branches.


      if (route.path == null && !route.index) {
        return;
      }

      branches.push({
        path,
        score: computeScore(path, route.index),
        routesMeta
      });
    };

    routes.forEach((route, index) => {
      var _route$path;

      // coarse-grain check for optional params
      if (route.path === "" || !((_route$path = route.path) != null && _route$path.includes("?"))) {
        flattenRoute(route, index);
      } else {
        for (let exploded of explodeOptionalSegments(route.path)) {
          flattenRoute(route, index, exploded);
        }
      }
    });
    return branches;
  }
  /**
   * Computes all combinations of optional path segments for a given path,
   * excluding combinations that are ambiguous and of lower priority.
   *
   * For example, `/one/:two?/three/:four?/:five?` explodes to:
   * - `/one/three`
   * - `/one/:two/three`
   * - `/one/three/:four`
   * - `/one/three/:five`
   * - `/one/:two/three/:four`
   * - `/one/:two/three/:five`
   * - `/one/three/:four/:five`
   * - `/one/:two/three/:four/:five`
   */


  function explodeOptionalSegments(path) {
    let segments = path.split("/");
    if (segments.length === 0) return [];
    let [first, ...rest] = segments; // Optional path segments are denoted by a trailing `?`

    let isOptional = first.endsWith("?"); // Compute the corresponding required segment: `foo?` -> `foo`

    let required = first.replace(/\?$/, "");

    if (rest.length === 0) {
      // Intepret empty string as omitting an optional segment
      // `["one", "", "three"]` corresponds to omitting `:two` from `/one/:two?/three` -> `/one/three`
      return isOptional ? [required, ""] : [required];
    }

    let restExploded = explodeOptionalSegments(rest.join("/"));
    let result = []; // All child paths with the prefix.  Do this for all children before the
    // optional version for all children so we get consistent ordering where the
    // parent optional aspect is preferred as required.  Otherwise, we can get
    // child sections interspersed where deeper optional segments are higher than
    // parent optional segments, where for example, /:two would explodes _earlier_
    // then /:one.  By always including the parent as required _for all children_
    // first, we avoid this issue

    result.push(...restExploded.map(subpath => subpath === "" ? required : [required, subpath].join("/"))); // Then if this is an optional value, add all child versions without

    if (isOptional) {
      result.push(...restExploded);
    } // for absolute paths, ensure `/` instead of empty segment


    return result.map(exploded => path.startsWith("/") && exploded === "" ? "/" : exploded);
  }

  function rankRouteBranches(branches) {
    branches.sort((a, b) => a.score !== b.score ? b.score - a.score // Higher score first
    : compareIndexes(a.routesMeta.map(meta => meta.childrenIndex), b.routesMeta.map(meta => meta.childrenIndex)));
  }

  const paramRe = /^:\w+$/;
  const dynamicSegmentValue = 3;
  const indexRouteValue = 2;
  const emptySegmentValue = 1;
  const staticSegmentValue = 10;
  const splatPenalty = -2;

  const isSplat = s => s === "*";

  function computeScore(path, index) {
    let segments = path.split("/");
    let initialScore = segments.length;

    if (segments.some(isSplat)) {
      initialScore += splatPenalty;
    }

    if (index) {
      initialScore += indexRouteValue;
    }

    return segments.filter(s => !isSplat(s)).reduce((score, segment) => score + (paramRe.test(segment) ? dynamicSegmentValue : segment === "" ? emptySegmentValue : staticSegmentValue), initialScore);
  }

  function compareIndexes(a, b) {
    let siblings = a.length === b.length && a.slice(0, -1).every((n, i) => n === b[i]);
    return siblings ? // If two routes are siblings, we should try to match the earlier sibling
    // first. This allows people to have fine-grained control over the matching
    // behavior by simply putting routes with identical paths in the order they
    // want them tried.
    a[a.length - 1] - b[b.length - 1] : // Otherwise, it doesn't really make sense to rank non-siblings by index,
    // so they sort equally.
    0;
  }

  function matchRouteBranch(branch, pathname) {
    let {
      routesMeta
    } = branch;
    let matchedParams = {};
    let matchedPathname = "/";
    let matches = [];

    for (let i = 0; i < routesMeta.length; ++i) {
      let meta = routesMeta[i];
      let end = i === routesMeta.length - 1;
      let remainingPathname = matchedPathname === "/" ? pathname : pathname.slice(matchedPathname.length) || "/";
      let match = matchPath({
        path: meta.relativePath,
        caseSensitive: meta.caseSensitive,
        end
      }, remainingPathname);
      if (!match) return null;
      Object.assign(matchedParams, match.params);
      let route = meta.route;
      matches.push({
        // TODO: Can this as be avoided?
        params: matchedParams,
        pathname: joinPaths([matchedPathname, match.pathname]),
        pathnameBase: normalizePathname(joinPaths([matchedPathname, match.pathnameBase])),
        route
      });

      if (match.pathnameBase !== "/") {
        matchedPathname = joinPaths([matchedPathname, match.pathnameBase]);
      }
    }

    return matches;
  }
  /**
   * Returns a path with params interpolated.
   *
   * @see https://reactrouter.com/utils/generate-path
   */


  function generatePath(originalPath, params) {
    if (params === void 0) {
      params = {};
    }

    let path = originalPath;

    if (path.endsWith("*") && path !== "*" && !path.endsWith("/*")) {
      warning(false, "Route path \"" + path + "\" will be treated as if it were " + ("\"" + path.replace(/\*$/, "/*") + "\" because the `*` character must ") + "always follow a `/` in the pattern. To get rid of this warning, " + ("please change the route path to \"" + path.replace(/\*$/, "/*") + "\"."));
      path = path.replace(/\*$/, "/*");
    }

    return path.replace(/^:(\w+)/g, (_, key) => {
      invariant(params[key] != null, "Missing \":" + key + "\" param");
      return params[key];
    }).replace(/\/:(\w+)/g, (_, key) => {
      invariant(params[key] != null, "Missing \":" + key + "\" param");
      return "/" + params[key];
    }).replace(/(\/?)\*/, (_, prefix, __, str) => {
      const star = "*";

      if (params[star] == null) {
        // If no splat was provided, trim the trailing slash _unless_ it's
        // the entire path
        return str === "/*" ? "/" : "";
      } // Apply the splat


      return "" + prefix + params[star];
    });
  }
  /**
   * A PathPattern is used to match on some portion of a URL pathname.
   */

  /**
   * Performs pattern matching on a URL pathname and returns information about
   * the match.
   *
   * @see https://reactrouter.com/utils/match-path
   */
  function matchPath(pattern, pathname) {
    if (typeof pattern === "string") {
      pattern = {
        path: pattern,
        caseSensitive: false,
        end: true
      };
    }

    let [matcher, paramNames] = compilePath(pattern.path, pattern.caseSensitive, pattern.end);
    let match = pathname.match(matcher);
    if (!match) return null;
    let matchedPathname = match[0];
    let pathnameBase = matchedPathname.replace(/(.)\/+$/, "$1");
    let captureGroups = match.slice(1);
    let params = paramNames.reduce((memo, paramName, index) => {
      // We need to compute the pathnameBase here using the raw splat value
      // instead of using params["*"] later because it will be decoded then
      if (paramName === "*") {
        let splatValue = captureGroups[index] || "";
        pathnameBase = matchedPathname.slice(0, matchedPathname.length - splatValue.length).replace(/(.)\/+$/, "$1");
      }

      memo[paramName] = safelyDecodeURIComponent(captureGroups[index] || "", paramName);
      return memo;
    }, {});
    return {
      params,
      pathname: matchedPathname,
      pathnameBase,
      pattern
    };
  }

  function compilePath(path, caseSensitive, end) {
    if (caseSensitive === void 0) {
      caseSensitive = false;
    }

    if (end === void 0) {
      end = true;
    }

    warning(path === "*" || !path.endsWith("*") || path.endsWith("/*"), "Route path \"" + path + "\" will be treated as if it were " + ("\"" + path.replace(/\*$/, "/*") + "\" because the `*` character must ") + "always follow a `/` in the pattern. To get rid of this warning, " + ("please change the route path to \"" + path.replace(/\*$/, "/*") + "\"."));
    let paramNames = [];
    let regexpSource = "^" + path.replace(/\/*\*?$/, "") // Ignore trailing / and /*, we'll handle it below
    .replace(/^\/*/, "/") // Make sure it has a leading /
    .replace(/[\\.*+^$?{}|()[\]]/g, "\\$&") // Escape special regex chars
    .replace(/\/:(\w+)/g, (_, paramName) => {
      paramNames.push(paramName);
      return "/([^\\/]+)";
    });

    if (path.endsWith("*")) {
      paramNames.push("*");
      regexpSource += path === "*" || path === "/*" ? "(.*)$" // Already matched the initial /, just match the rest
      : "(?:\\/(.+)|\\/*)$"; // Don't include the / in params["*"]
    } else if (end) {
      // When matching to the end, ignore trailing slashes
      regexpSource += "\\/*$";
    } else if (path !== "" && path !== "/") {
      // If our path is non-empty and contains anything beyond an initial slash,
      // then we have _some_ form of path in our regex so we should expect to
      // match only if we find the end of this path segment.  Look for an optional
      // non-captured trailing slash (to match a portion of the URL) or the end
      // of the path (if we've matched to the end).  We used to do this with a
      // word boundary but that gives false positives on routes like
      // /user-preferences since `-` counts as a word boundary.
      regexpSource += "(?:(?=\\/|$))";
    } else ;

    let matcher = new RegExp(regexpSource, caseSensitive ? undefined : "i");
    return [matcher, paramNames];
  }

  function safelyDecodeURI(value) {
    try {
      return decodeURI(value);
    } catch (error) {
      warning(false, "The URL path \"" + value + "\" could not be decoded because it is is a " + "malformed URL segment. This is probably due to a bad percent " + ("encoding (" + error + ")."));
      return value;
    }
  }

  function safelyDecodeURIComponent(value, paramName) {
    try {
      return decodeURIComponent(value);
    } catch (error) {
      warning(false, "The value for the URL param \"" + paramName + "\" will not be decoded because" + (" the string \"" + value + "\" is a malformed URL segment. This is probably") + (" due to a bad percent encoding (" + error + ")."));
      return value;
    }
  }
  /**
   * @private
   */


  function stripBasename(pathname, basename) {
    if (basename === "/") return pathname;

    if (!pathname.toLowerCase().startsWith(basename.toLowerCase())) {
      return null;
    } // We want to leave trailing slash behavior in the user's control, so if they
    // specify a basename with a trailing slash, we should support it


    let startIndex = basename.endsWith("/") ? basename.length - 1 : basename.length;
    let nextChar = pathname.charAt(startIndex);

    if (nextChar && nextChar !== "/") {
      // pathname does not start with basename/
      return null;
    }

    return pathname.slice(startIndex) || "/";
  }
  /**
   * @private
   */

  function warning(cond, message) {
    if (!cond) {
      // eslint-disable-next-line no-console
      if (typeof console !== "undefined") console.warn(message);

      try {
        // Welcome to debugging React Router!
        //
        // This error is thrown as a convenience so you can more easily
        // find the source for a warning that appears in the console by
        // enabling "pause on exceptions" in your JavaScript debugger.
        throw new Error(message); // eslint-disable-next-line no-empty
      } catch (e) {}
    }
  }
  /**
   * Returns a resolved path object relative to the given pathname.
   *
   * @see https://reactrouter.com/utils/resolve-path
   */

  function resolvePath(to, fromPathname) {
    if (fromPathname === void 0) {
      fromPathname = "/";
    }

    let {
      pathname: toPathname,
      search = "",
      hash = ""
    } = typeof to === "string" ? parsePath(to) : to;
    let pathname = toPathname ? toPathname.startsWith("/") ? toPathname : resolvePathname(toPathname, fromPathname) : fromPathname;
    return {
      pathname,
      search: normalizeSearch(search),
      hash: normalizeHash(hash)
    };
  }

  function resolvePathname(relativePath, fromPathname) {
    let segments = fromPathname.replace(/\/+$/, "").split("/");
    let relativeSegments = relativePath.split("/");
    relativeSegments.forEach(segment => {
      if (segment === "..") {
        // Keep the root "" segment so the pathname starts at /
        if (segments.length > 1) segments.pop();
      } else if (segment !== ".") {
        segments.push(segment);
      }
    });
    return segments.length > 1 ? segments.join("/") : "/";
  }

  function getInvalidPathError(char, field, dest, path) {
    return "Cannot include a '" + char + "' character in a manually specified " + ("`to." + field + "` field [" + JSON.stringify(path) + "].  Please separate it out to the ") + ("`to." + dest + "` field. Alternatively you may provide the full path as ") + "a string in <Link to=\"...\"> and the router will parse it for you.";
  }
  /**
   * @private
   *
   * When processing relative navigation we want to ignore ancestor routes that
   * do not contribute to the path, such that index/pathless layout routes don't
   * interfere.
   *
   * For example, when moving a route element into an index route and/or a
   * pathless layout route, relative link behavior contained within should stay
   * the same.  Both of the following examples should link back to the root:
   *
   *   <Route path="/">
   *     <Route path="accounts" element={<Link to=".."}>
   *   </Route>
   *
   *   <Route path="/">
   *     <Route path="accounts">
   *       <Route element={<AccountsLayout />}>       // <-- Does not contribute
   *         <Route index element={<Link to=".."} />  // <-- Does not contribute
   *       </Route
   *     </Route>
   *   </Route>
   */


  function getPathContributingMatches(matches) {
    return matches.filter((match, index) => index === 0 || match.route.path && match.route.path.length > 0);
  }
  /**
   * @private
   */

  function resolveTo(toArg, routePathnames, locationPathname, isPathRelative) {
    if (isPathRelative === void 0) {
      isPathRelative = false;
    }

    let to;

    if (typeof toArg === "string") {
      to = parsePath(toArg);
    } else {
      to = _extends({}, toArg);
      invariant(!to.pathname || !to.pathname.includes("?"), getInvalidPathError("?", "pathname", "search", to));
      invariant(!to.pathname || !to.pathname.includes("#"), getInvalidPathError("#", "pathname", "hash", to));
      invariant(!to.search || !to.search.includes("#"), getInvalidPathError("#", "search", "hash", to));
    }

    let isEmptyPath = toArg === "" || to.pathname === "";
    let toPathname = isEmptyPath ? "/" : to.pathname;
    let from; // Routing is relative to the current pathname if explicitly requested.
    //
    // If a pathname is explicitly provided in `to`, it should be relative to the
    // route context. This is explained in `Note on `<Link to>` values` in our
    // migration guide from v5 as a means of disambiguation between `to` values
    // that begin with `/` and those that do not. However, this is problematic for
    // `to` values that do not provide a pathname. `to` can simply be a search or
    // hash string, in which case we should assume that the navigation is relative
    // to the current location's pathname and *not* the route pathname.

    if (isPathRelative || toPathname == null) {
      from = locationPathname;
    } else {
      let routePathnameIndex = routePathnames.length - 1;

      if (toPathname.startsWith("..")) {
        let toSegments = toPathname.split("/"); // Each leading .. segment means "go up one route" instead of "go up one
        // URL segment".  This is a key difference from how <a href> works and a
        // major reason we call this a "to" value instead of a "href".

        while (toSegments[0] === "..") {
          toSegments.shift();
          routePathnameIndex -= 1;
        }

        to.pathname = toSegments.join("/");
      } // If there are more ".." segments than parent routes, resolve relative to
      // the root / URL.


      from = routePathnameIndex >= 0 ? routePathnames[routePathnameIndex] : "/";
    }

    let path = resolvePath(to, from); // Ensure the pathname has a trailing slash if the original "to" had one

    let hasExplicitTrailingSlash = toPathname && toPathname !== "/" && toPathname.endsWith("/"); // Or if this was a link to the current path which has a trailing slash

    let hasCurrentTrailingSlash = (isEmptyPath || toPathname === ".") && locationPathname.endsWith("/");

    if (!path.pathname.endsWith("/") && (hasExplicitTrailingSlash || hasCurrentTrailingSlash)) {
      path.pathname += "/";
    }

    return path;
  }
  /**
   * @private
   */

  function getToPathname(to) {
    // Empty strings should be treated the same as / paths
    return to === "" || to.pathname === "" ? "/" : typeof to === "string" ? parsePath(to).pathname : to.pathname;
  }
  /**
   * @private
   */

  const joinPaths = paths => paths.join("/").replace(/\/\/+/g, "/");
  /**
   * @private
   */

  const normalizePathname = pathname => pathname.replace(/\/+$/, "").replace(/^\/*/, "/");
  /**
   * @private
   */

  const normalizeSearch = search => !search || search === "?" ? "" : search.startsWith("?") ? search : "?" + search;
  /**
   * @private
   */

  const normalizeHash = hash => !hash || hash === "#" ? "" : hash.startsWith("#") ? hash : "#" + hash;

  /**
   * This is a shortcut for creating `application/json` responses. Converts `data`
   * to JSON and sets the `Content-Type` header.
   */
  const json = function json(data, init) {
    if (init === void 0) {
      init = {};
    }

    let responseInit = typeof init === "number" ? {
      status: init
    } : init;
    let headers = new Headers(responseInit.headers);

    if (!headers.has("Content-Type")) {
      headers.set("Content-Type", "application/json; charset=utf-8");
    }

    return new Response(JSON.stringify(data), _extends({}, responseInit, {
      headers
    }));
  };
  class AbortedDeferredError extends Error {}
  class DeferredData {
    constructor(data) {
      this.pendingKeys = new Set();
      this.subscriber = undefined;
      invariant(data && typeof data === "object" && !Array.isArray(data), "defer() only accepts plain objects"); // Set up an AbortController + Promise we can race against to exit early
      // cancellation

      let reject;
      this.abortPromise = new Promise((_, r) => reject = r);
      this.controller = new AbortController();

      let onAbort = () => reject(new AbortedDeferredError("Deferred data aborted"));

      this.unlistenAbortSignal = () => this.controller.signal.removeEventListener("abort", onAbort);

      this.controller.signal.addEventListener("abort", onAbort);
      this.data = Object.entries(data).reduce((acc, _ref) => {
        let [key, value] = _ref;
        return Object.assign(acc, {
          [key]: this.trackPromise(key, value)
        });
      }, {});
    }

    trackPromise(key, value) {
      if (!(value instanceof Promise)) {
        return value;
      }

      this.pendingKeys.add(key); // We store a little wrapper promise that will be extended with
      // _data/_error props upon resolve/reject

      let promise = Promise.race([value, this.abortPromise]).then(data => this.onSettle(promise, key, null, data), error => this.onSettle(promise, key, error)); // Register rejection listeners to avoid uncaught promise rejections on
      // errors or aborted deferred values

      promise.catch(() => {});
      Object.defineProperty(promise, "_tracked", {
        get: () => true
      });
      return promise;
    }

    onSettle(promise, key, error, data) {
      if (this.controller.signal.aborted && error instanceof AbortedDeferredError) {
        this.unlistenAbortSignal();
        Object.defineProperty(promise, "_error", {
          get: () => error
        });
        return Promise.reject(error);
      }

      this.pendingKeys.delete(key);

      if (this.done) {
        // Nothing left to abort!
        this.unlistenAbortSignal();
      }

      const subscriber = this.subscriber;

      if (error) {
        Object.defineProperty(promise, "_error", {
          get: () => error
        });
        subscriber && subscriber(false);
        return Promise.reject(error);
      }

      Object.defineProperty(promise, "_data", {
        get: () => data
      });
      subscriber && subscriber(false);
      return data;
    }

    subscribe(fn) {
      this.subscriber = fn;
    }

    cancel() {
      this.controller.abort();
      this.pendingKeys.forEach((v, k) => this.pendingKeys.delete(k));
      let subscriber = this.subscriber;
      subscriber && subscriber(true);
    }

    async resolveData(signal) {
      let aborted = false;

      if (!this.done) {
        let onAbort = () => this.cancel();

        signal.addEventListener("abort", onAbort);
        aborted = await new Promise(resolve => {
          this.subscribe(aborted => {
            signal.removeEventListener("abort", onAbort);

            if (aborted || this.done) {
              resolve(aborted);
            }
          });
        });
      }

      return aborted;
    }

    get done() {
      return this.pendingKeys.size === 0;
    }

    get unwrappedData() {
      invariant(this.data !== null && this.done, "Can only unwrap data on initialized and settled deferreds");
      return Object.entries(this.data).reduce((acc, _ref2) => {
        let [key, value] = _ref2;
        return Object.assign(acc, {
          [key]: unwrapTrackedPromise(value)
        });
      }, {});
    }

  }

  function isTrackedPromise(value) {
    return value instanceof Promise && value._tracked === true;
  }

  function unwrapTrackedPromise(value) {
    if (!isTrackedPromise(value)) {
      return value;
    }

    if (value._error) {
      throw value._error;
    }

    return value._data;
  }

  function defer(data) {
    return new DeferredData(data);
  }

  /**
   * A redirect response. Sets the status code and the `Location` header.
   * Defaults to "302 Found".
   */
  const redirect = function redirect(url, init) {
    if (init === void 0) {
      init = 302;
    }

    let responseInit = init;

    if (typeof responseInit === "number") {
      responseInit = {
        status: responseInit
      };
    } else if (typeof responseInit.status === "undefined") {
      responseInit.status = 302;
    }

    let headers = new Headers(responseInit.headers);
    headers.set("Location", url);
    return new Response(null, _extends({}, responseInit, {
      headers
    }));
  };
  /**
   * @private
   * Utility class we use to hold auto-unwrapped 4xx/5xx Response bodies
   */

  class ErrorResponse {
    constructor(status, statusText, data, internal) {
      if (internal === void 0) {
        internal = false;
      }

      this.status = status;
      this.statusText = statusText || "";
      this.internal = internal;

      if (data instanceof Error) {
        this.data = data.toString();
        this.error = data;
      } else {
        this.data = data;
      }
    }

  }
  /**
   * Check if the given error is an ErrorResponse generated from a 4xx/5xx
   * Response throw from an action/loader
   */

  function isRouteErrorResponse(e) {
    return e instanceof ErrorResponse;
  }

  //#region Types and Constants
  ////////////////////////////////////////////////////////////////////////////////

  /**
   * A Router instance manages all navigation and data loading/mutations
   */

  const validMutationMethodsArr = ["post", "put", "patch", "delete"];
  const validMutationMethods = new Set(validMutationMethodsArr);
  const validRequestMethodsArr = ["get", ...validMutationMethodsArr];
  const validRequestMethods = new Set(validRequestMethodsArr);
  const redirectStatusCodes = new Set([301, 302, 303, 307, 308]);
  const redirectPreserveMethodStatusCodes = new Set([307, 308]);
  const IDLE_NAVIGATION = {
    state: "idle",
    location: undefined,
    formMethod: undefined,
    formAction: undefined,
    formEncType: undefined,
    formData: undefined
  };
  const IDLE_FETCHER = {
    state: "idle",
    data: undefined,
    formMethod: undefined,
    formAction: undefined,
    formEncType: undefined,
    formData: undefined
  };
  const isBrowser = typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.document.createElement !== "undefined";
  const isServer = !isBrowser; //#endregion
  ////////////////////////////////////////////////////////////////////////////////
  //#region createRouter
  ////////////////////////////////////////////////////////////////////////////////

  /**
   * Create a router and listen to history POP navigations
   */

  function createRouter(init) {
    invariant(init.routes.length > 0, "You must provide a non-empty routes array to createRouter");
    let dataRoutes = convertRoutesToDataRoutes(init.routes); // Cleanup function for history

    let unlistenHistory = null; // Externally-provided functions to call on all state changes

    let subscribers = new Set(); // Externally-provided object to hold scroll restoration locations during routing

    let savedScrollPositions = null; // Externally-provided function to get scroll restoration keys

    let getScrollRestorationKey = null; // Externally-provided function to get current scroll position

    let getScrollPosition = null; // One-time flag to control the initial hydration scroll restoration.  Because
    // we don't get the saved positions from <ScrollRestoration /> until _after_
    // the initial render, we need to manually trigger a separate updateState to
    // send along the restoreScrollPosition

    let initialScrollRestored = false;
    let initialMatches = matchRoutes(dataRoutes, init.history.location, init.basename);
    let initialErrors = null;

    if (initialMatches == null) {
      // If we do not match a user-provided-route, fall back to the root
      // to allow the error boundary to take over
      let error = getInternalRouterError(404, {
        pathname: init.history.location.pathname
      });
      let {
        matches,
        route
      } = getShortCircuitMatches(dataRoutes);
      initialMatches = matches;
      initialErrors = {
        [route.id]: error
      };
    }

    let initialized = !initialMatches.some(m => m.route.loader) || init.hydrationData != null;
    let router;
    let state = {
      historyAction: init.history.action,
      location: init.history.location,
      matches: initialMatches,
      initialized,
      navigation: IDLE_NAVIGATION,
      restoreScrollPosition: null,
      preventScrollReset: false,
      revalidation: "idle",
      loaderData: init.hydrationData && init.hydrationData.loaderData || {},
      actionData: init.hydrationData && init.hydrationData.actionData || null,
      errors: init.hydrationData && init.hydrationData.errors || initialErrors,
      fetchers: new Map()
    }; // -- Stateful internal variables to manage navigations --
    // Current navigation in progress (to be committed in completeNavigation)

    let pendingAction = exports.Action.Pop; // Should the current navigation prevent the scroll reset if scroll cannot
    // be restored?

    let pendingPreventScrollReset = false; // AbortController for the active navigation

    let pendingNavigationController; // We use this to avoid touching history in completeNavigation if a
    // revalidation is entirely uninterrupted

    let isUninterruptedRevalidation = false; // Use this internal flag to force revalidation of all loaders:
    //  - submissions (completed or interrupted)
    //  - useRevalidate()
    //  - X-Remix-Revalidate (from redirect)

    let isRevalidationRequired = false; // Use this internal array to capture routes that require revalidation due
    // to a cancelled deferred on action submission

    let cancelledDeferredRoutes = []; // Use this internal array to capture fetcher loads that were cancelled by an
    // action navigation and require revalidation

    let cancelledFetcherLoads = []; // AbortControllers for any in-flight fetchers

    let fetchControllers = new Map(); // Track loads based on the order in which they started

    let incrementingLoadId = 0; // Track the outstanding pending navigation data load to be compared against
    // the globally incrementing load when a fetcher load lands after a completed
    // navigation

    let pendingNavigationLoadId = -1; // Fetchers that triggered data reloads as a result of their actions

    let fetchReloadIds = new Map(); // Fetchers that triggered redirect navigations from their actions

    let fetchRedirectIds = new Set(); // Most recent href/match for fetcher.load calls for fetchers

    let fetchLoadMatches = new Map(); // Store DeferredData instances for active route matches.  When a
    // route loader returns defer() we stick one in here.  Then, when a nested
    // promise resolves we update loaderData.  If a new navigation starts we
    // cancel active deferreds for eliminated routes.

    let activeDeferreds = new Map(); // Initialize the router, all side effects should be kicked off from here.
    // Implemented as a Fluent API for ease of:
    //   let router = createRouter(init).initialize();

    function initialize() {
      // If history informs us of a POP navigation, start the navigation but do not update
      // state.  We'll update our own state once the navigation completes
      unlistenHistory = init.history.listen(_ref => {
        let {
          action: historyAction,
          location
        } = _ref;
        return startNavigation(historyAction, location);
      }); // Kick off initial data load if needed.  Use Pop to avoid modifying history

      if (!state.initialized) {
        startNavigation(exports.Action.Pop, state.location);
      }

      return router;
    } // Clean up a router and it's side effects


    function dispose() {
      if (unlistenHistory) {
        unlistenHistory();
      }

      subscribers.clear();
      pendingNavigationController && pendingNavigationController.abort();
      state.fetchers.forEach((_, key) => deleteFetcher(key));
    } // Subscribe to state updates for the router


    function subscribe(fn) {
      subscribers.add(fn);
      return () => subscribers.delete(fn);
    } // Update our state and notify the calling context of the change


    function updateState(newState) {
      state = _extends({}, state, newState);
      subscribers.forEach(subscriber => subscriber(state));
    } // Complete a navigation returning the state.navigation back to the IDLE_NAVIGATION
    // and setting state.[historyAction/location/matches] to the new route.
    // - Location is a required param
    // - Navigation will always be set to IDLE_NAVIGATION
    // - Can pass any other state in newState


    function completeNavigation(location, newState) {
      var _state$navigation$for;

      // Deduce if we're in a loading/actionReload state:
      // - We have committed actionData in the store
      // - The current navigation was a submission
      // - We're past the submitting state and into the loading state
      // - The location we've finished loading is different from the submission
      //   location, indicating we redirected from the action (avoids false
      //   positives for loading/submissionRedirect when actionData returned
      //   on a prior submission)
      let isActionReload = state.actionData != null && state.navigation.formMethod != null && state.navigation.state === "loading" && ((_state$navigation$for = state.navigation.formAction) == null ? void 0 : _state$navigation$for.split("?")[0]) === location.pathname; // Always preserve any existing loaderData from re-used routes

      let newLoaderData = newState.loaderData ? {
        loaderData: mergeLoaderData(state.loaderData, newState.loaderData, newState.matches || [])
      } : {};
      updateState(_extends({}, isActionReload ? {} : {
        actionData: null
      }, newState, newLoaderData, {
        historyAction: pendingAction,
        location,
        initialized: true,
        navigation: IDLE_NAVIGATION,
        revalidation: "idle",
        // Don't restore on submission navigations
        restoreScrollPosition: state.navigation.formData ? false : getSavedScrollPosition(location, newState.matches || state.matches),
        preventScrollReset: pendingPreventScrollReset
      }));

      if (isUninterruptedRevalidation) ; else if (pendingAction === exports.Action.Pop) ; else if (pendingAction === exports.Action.Push) {
        init.history.push(location, location.state);
      } else if (pendingAction === exports.Action.Replace) {
        init.history.replace(location, location.state);
      } // Reset stateful navigation vars


      pendingAction = exports.Action.Pop;
      pendingPreventScrollReset = false;
      isUninterruptedRevalidation = false;
      isRevalidationRequired = false;
      cancelledDeferredRoutes = [];
      cancelledFetcherLoads = [];
    } // Trigger a navigation event, which can either be a numerical POP or a PUSH
    // replace with an optional submission


    async function navigate(to, opts) {
      if (typeof to === "number") {
        init.history.go(to);
        return;
      }

      let {
        path,
        submission,
        error
      } = normalizeNavigateOptions(to, opts);
      let location = createLocation(state.location, path, opts && opts.state); // When using navigate as a PUSH/REPLACE we aren't reading an already-encoded
      // URL from window.location, so we need to encode it here so the behavior
      // remains the same as POP and non-data-router usages.  new URL() does all
      // the same encoding we'd get from a history.pushState/window.location read
      // without having to touch history

      location = _extends({}, location, init.history.encodeLocation(location));
      let historyAction = (opts && opts.replace) === true || submission != null && isMutationMethod(submission.formMethod) ? exports.Action.Replace : exports.Action.Push;
      let preventScrollReset = opts && "preventScrollReset" in opts ? opts.preventScrollReset === true : undefined;
      return await startNavigation(historyAction, location, {
        submission,
        // Send through the formData serialization error if we have one so we can
        // render at the right error boundary after we match routes
        pendingError: error,
        preventScrollReset,
        replace: opts && opts.replace
      });
    } // Revalidate all current loaders.  If a navigation is in progress or if this
    // is interrupted by a navigation, allow this to "succeed" by calling all
    // loaders during the next loader round


    function revalidate() {
      interruptActiveLoads();
      updateState({
        revalidation: "loading"
      }); // If we're currently submitting an action, we don't need to start a new
      // navigation, we'll just let the follow up loader execution call all loaders

      if (state.navigation.state === "submitting") {
        return;
      } // If we're currently in an idle state, start a new navigation for the current
      // action/location and mark it as uninterrupted, which will skip the history
      // update in completeNavigation


      if (state.navigation.state === "idle") {
        startNavigation(state.historyAction, state.location, {
          startUninterruptedRevalidation: true
        });
        return;
      } // Otherwise, if we're currently in a loading state, just start a new
      // navigation to the navigation.location but do not trigger an uninterrupted
      // revalidation so that history correctly updates once the navigation completes


      startNavigation(pendingAction || state.historyAction, state.navigation.location, {
        overrideNavigation: state.navigation
      });
    } // Start a navigation to the given action/location.  Can optionally provide a
    // overrideNavigation which will override the normalLoad in the case of a redirect
    // navigation


    async function startNavigation(historyAction, location, opts) {
      // Abort any in-progress navigations and start a new one. Unset any ongoing
      // uninterrupted revalidations unless told otherwise, since we want this
      // new navigation to update history normally
      pendingNavigationController && pendingNavigationController.abort();
      pendingNavigationController = null;
      pendingAction = historyAction;
      isUninterruptedRevalidation = (opts && opts.startUninterruptedRevalidation) === true; // Save the current scroll position every time we start a new navigation,
      // and track whether we should reset scroll on completion

      saveScrollPosition(state.location, state.matches);
      pendingPreventScrollReset = (opts && opts.preventScrollReset) === true;
      let loadingNavigation = opts && opts.overrideNavigation;
      let matches = matchRoutes(dataRoutes, location, init.basename); // Short circuit with a 404 on the root error boundary if we match nothing

      if (!matches) {
        let error = getInternalRouterError(404, {
          pathname: location.pathname
        });
        let {
          matches: notFoundMatches,
          route
        } = getShortCircuitMatches(dataRoutes); // Cancel all pending deferred on 404s since we don't keep any routes

        cancelActiveDeferreds();
        completeNavigation(location, {
          matches: notFoundMatches,
          loaderData: {},
          errors: {
            [route.id]: error
          }
        });
        return;
      } // Short circuit if it's only a hash change


      if (isHashChangeOnly(state.location, location)) {
        completeNavigation(location, {
          matches
        });
        return;
      } // Create a controller/Request for this navigation


      pendingNavigationController = new AbortController();
      let request = createClientSideRequest(location, pendingNavigationController.signal, opts && opts.submission);
      let pendingActionData;
      let pendingError;

      if (opts && opts.pendingError) {
        // If we have a pendingError, it means the user attempted a GET submission
        // with binary FormData so assign here and skip to handleLoaders.  That
        // way we handle calling loaders above the boundary etc.  It's not really
        // different from an actionError in that sense.
        pendingError = {
          [findNearestBoundary(matches).route.id]: opts.pendingError
        };
      } else if (opts && opts.submission && isMutationMethod(opts.submission.formMethod)) {
        // Call action if we received an action submission
        let actionOutput = await handleAction(request, location, opts.submission, matches, {
          replace: opts.replace
        });

        if (actionOutput.shortCircuited) {
          return;
        }

        pendingActionData = actionOutput.pendingActionData;
        pendingError = actionOutput.pendingActionError;

        let navigation = _extends({
          state: "loading",
          location
        }, opts.submission);

        loadingNavigation = navigation; // Create a GET request for the loaders

        request = new Request(request.url, {
          signal: request.signal
        });
      } // Call loaders


      let {
        shortCircuited,
        loaderData,
        errors
      } = await handleLoaders(request, location, matches, loadingNavigation, opts && opts.submission, opts && opts.replace, pendingActionData, pendingError);

      if (shortCircuited) {
        return;
      } // Clean up now that the action/loaders have completed.  Don't clean up if
      // we short circuited because pendingNavigationController will have already
      // been assigned to a new controller for the next navigation


      pendingNavigationController = null;
      completeNavigation(location, {
        matches,
        loaderData,
        errors
      });
    } // Call the action matched by the leaf route for this navigation and handle
    // redirects/errors


    async function handleAction(request, location, submission, matches, opts) {
      interruptActiveLoads(); // Put us in a submitting state

      let navigation = _extends({
        state: "submitting",
        location
      }, submission);

      updateState({
        navigation
      }); // Call our action and get the result

      let result;
      let actionMatch = getTargetMatch(matches, location);

      if (!actionMatch.route.action) {
        result = {
          type: ResultType.error,
          error: getInternalRouterError(405, {
            method: request.method,
            pathname: location.pathname,
            routeId: actionMatch.route.id
          })
        };
      } else {
        result = await callLoaderOrAction("action", request, actionMatch, matches, router.basename);

        if (request.signal.aborted) {
          return {
            shortCircuited: true
          };
        }
      }

      if (isRedirectResult(result)) {
        await startRedirectNavigation(state, result, opts && opts.replace === true);
        return {
          shortCircuited: true
        };
      }

      if (isErrorResult(result)) {
        // Store off the pending error - we use it to determine which loaders
        // to call and will commit it when we complete the navigation
        let boundaryMatch = findNearestBoundary(matches, actionMatch.route.id); // By default, all submissions are REPLACE navigations, but if the
        // action threw an error that'll be rendered in an errorElement, we fall
        // back to PUSH so that the user can use the back button to get back to
        // the pre-submission form location to try again

        if ((opts && opts.replace) !== true) {
          pendingAction = exports.Action.Push;
        }

        return {
          pendingActionError: {
            [boundaryMatch.route.id]: result.error
          }
        };
      }

      if (isDeferredResult(result)) {
        throw new Error("defer() is not supported in actions");
      }

      return {
        pendingActionData: {
          [actionMatch.route.id]: result.data
        }
      };
    } // Call all applicable loaders for the given matches, handling redirects,
    // errors, etc.


    async function handleLoaders(request, location, matches, overrideNavigation, submission, replace, pendingActionData, pendingError) {
      // Figure out the right navigation we want to use for data loading
      let loadingNavigation = overrideNavigation;

      if (!loadingNavigation) {
        let navigation = _extends({
          state: "loading",
          location,
          formMethod: undefined,
          formAction: undefined,
          formEncType: undefined,
          formData: undefined
        }, submission);

        loadingNavigation = navigation;
      }

      let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(state, matches, submission, location, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, pendingActionData, pendingError, fetchLoadMatches); // Cancel pending deferreds for no-longer-matched routes or routes we're
      // about to reload.  Note that if this is an action reload we would have
      // already cancelled all pending deferreds so this would be a no-op

      cancelActiveDeferreds(routeId => !(matches && matches.some(m => m.route.id === routeId)) || matchesToLoad && matchesToLoad.some(m => m.route.id === routeId)); // Short circuit if we have no loaders to run

      if (matchesToLoad.length === 0 && revalidatingFetchers.length === 0) {
        completeNavigation(location, {
          matches,
          loaderData: mergeLoaderData(state.loaderData, {}, matches),
          // Commit pending error if we're short circuiting
          errors: pendingError || null,
          actionData: pendingActionData || null
        });
        return {
          shortCircuited: true
        };
      } // If this is an uninterrupted revalidation, we remain in our current idle
      // state.  If not, we need to switch to our loading state and load data,
      // preserving any new action data or existing action data (in the case of
      // a revalidation interrupting an actionReload)


      if (!isUninterruptedRevalidation) {
        revalidatingFetchers.forEach(_ref2 => {
          let [key] = _ref2;
          let fetcher = state.fetchers.get(key);
          let revalidatingFetcher = {
            state: "loading",
            data: fetcher && fetcher.data,
            formMethod: undefined,
            formAction: undefined,
            formEncType: undefined,
            formData: undefined
          };
          state.fetchers.set(key, revalidatingFetcher);
        });
        updateState(_extends({
          navigation: loadingNavigation,
          actionData: pendingActionData || state.actionData || null
        }, revalidatingFetchers.length > 0 ? {
          fetchers: new Map(state.fetchers)
        } : {}));
      }

      pendingNavigationLoadId = ++incrementingLoadId;
      revalidatingFetchers.forEach(_ref3 => {
        let [key] = _ref3;
        return fetchControllers.set(key, pendingNavigationController);
      });
      let {
        results,
        loaderResults,
        fetcherResults
      } = await callLoadersAndMaybeResolveData(state.matches, matches, matchesToLoad, revalidatingFetchers, request);

      if (request.signal.aborted) {
        return {
          shortCircuited: true
        };
      } // Clean up _after_ loaders have completed.  Don't clean up if we short
      // circuited because fetchControllers would have been aborted and
      // reassigned to new controllers for the next navigation


      revalidatingFetchers.forEach(_ref4 => {
        let [key] = _ref4;
        return fetchControllers.delete(key);
      }); // If any loaders returned a redirect Response, start a new REPLACE navigation

      let redirect = findRedirect(results);

      if (redirect) {
        await startRedirectNavigation(state, redirect, replace);
        return {
          shortCircuited: true
        };
      } // Process and commit output from loaders


      let {
        loaderData,
        errors
      } = processLoaderData(state, matches, matchesToLoad, loaderResults, pendingError, revalidatingFetchers, fetcherResults, activeDeferreds); // Wire up subscribers to update loaderData as promises settle

      activeDeferreds.forEach((deferredData, routeId) => {
        deferredData.subscribe(aborted => {
          // Note: No need to updateState here since the TrackedPromise on
          // loaderData is stable across resolve/reject
          // Remove this instance if we were aborted or if promises have settled
          if (aborted || deferredData.done) {
            activeDeferreds.delete(routeId);
          }
        });
      });
      markFetchRedirectsDone();
      let didAbortFetchLoads = abortStaleFetchLoads(pendingNavigationLoadId);
      return _extends({
        loaderData,
        errors
      }, didAbortFetchLoads || revalidatingFetchers.length > 0 ? {
        fetchers: new Map(state.fetchers)
      } : {});
    }

    function getFetcher(key) {
      return state.fetchers.get(key) || IDLE_FETCHER;
    } // Trigger a fetcher load/submit for the given fetcher key


    function fetch(key, routeId, href, opts) {
      if (isServer) {
        throw new Error("router.fetch() was called during the server render, but it shouldn't be. " + "You are likely calling a useFetcher() method in the body of your component. " + "Try moving it to a useEffect or a callback.");
      }

      if (fetchControllers.has(key)) abortFetcher(key);
      let matches = matchRoutes(dataRoutes, href, init.basename);

      if (!matches) {
        setFetcherError(key, routeId, getInternalRouterError(404, {
          pathname: href
        }));
        return;
      }

      let {
        path,
        submission
      } = normalizeNavigateOptions(href, opts, true);
      let match = getTargetMatch(matches, path);

      if (submission && isMutationMethod(submission.formMethod)) {
        handleFetcherAction(key, routeId, path, match, matches, submission);
        return;
      } // Store off the match so we can call it's shouldRevalidate on subsequent
      // revalidations


      fetchLoadMatches.set(key, [path, match, matches]);
      handleFetcherLoader(key, routeId, path, match, matches, submission);
    } // Call the action for the matched fetcher.submit(), and then handle redirects,
    // errors, and revalidation


    async function handleFetcherAction(key, routeId, path, match, requestMatches, submission) {
      interruptActiveLoads();
      fetchLoadMatches.delete(key);

      if (!match.route.action) {
        let error = getInternalRouterError(405, {
          method: submission.formMethod,
          pathname: path,
          routeId: routeId
        });
        setFetcherError(key, routeId, error);
        return;
      } // Put this fetcher into it's submitting state


      let existingFetcher = state.fetchers.get(key);

      let fetcher = _extends({
        state: "submitting"
      }, submission, {
        data: existingFetcher && existingFetcher.data
      });

      state.fetchers.set(key, fetcher);
      updateState({
        fetchers: new Map(state.fetchers)
      }); // Call the action for the fetcher

      let abortController = new AbortController();
      let fetchRequest = createClientSideRequest(path, abortController.signal, submission);
      fetchControllers.set(key, abortController);
      let actionResult = await callLoaderOrAction("action", fetchRequest, match, requestMatches, router.basename);

      if (fetchRequest.signal.aborted) {
        // We can delete this so long as we weren't aborted by ou our own fetcher
        // re-submit which would have put _new_ controller is in fetchControllers
        if (fetchControllers.get(key) === abortController) {
          fetchControllers.delete(key);
        }

        return;
      }

      if (isRedirectResult(actionResult)) {
        fetchControllers.delete(key);
        fetchRedirectIds.add(key);

        let loadingFetcher = _extends({
          state: "loading"
        }, submission, {
          data: undefined
        });

        state.fetchers.set(key, loadingFetcher);
        updateState({
          fetchers: new Map(state.fetchers)
        });
        return startRedirectNavigation(state, actionResult);
      } // Process any non-redirect errors thrown


      if (isErrorResult(actionResult)) {
        setFetcherError(key, routeId, actionResult.error);
        return;
      }

      if (isDeferredResult(actionResult)) {
        invariant(false, "defer() is not supported in actions");
      } // Start the data load for current matches, or the next location if we're
      // in the middle of a navigation


      let nextLocation = state.navigation.location || state.location;
      let revalidationRequest = createClientSideRequest(nextLocation, abortController.signal);
      let matches = state.navigation.state !== "idle" ? matchRoutes(dataRoutes, state.navigation.location, init.basename) : state.matches;
      invariant(matches, "Didn't find any matches after fetcher action");
      let loadId = ++incrementingLoadId;
      fetchReloadIds.set(key, loadId);

      let loadFetcher = _extends({
        state: "loading",
        data: actionResult.data
      }, submission);

      state.fetchers.set(key, loadFetcher);
      let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(state, matches, submission, nextLocation, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, {
        [match.route.id]: actionResult.data
      }, undefined, // No need to send through errors since we short circuit above
      fetchLoadMatches); // Put all revalidating fetchers into the loading state, except for the
      // current fetcher which we want to keep in it's current loading state which
      // contains it's action submission info + action data

      revalidatingFetchers.filter(_ref5 => {
        let [staleKey] = _ref5;
        return staleKey !== key;
      }).forEach(_ref6 => {
        let [staleKey] = _ref6;
        let existingFetcher = state.fetchers.get(staleKey);
        let revalidatingFetcher = {
          state: "loading",
          data: existingFetcher && existingFetcher.data,
          formMethod: undefined,
          formAction: undefined,
          formEncType: undefined,
          formData: undefined
        };
        state.fetchers.set(staleKey, revalidatingFetcher);
        fetchControllers.set(staleKey, abortController);
      });
      updateState({
        fetchers: new Map(state.fetchers)
      });
      let {
        results,
        loaderResults,
        fetcherResults
      } = await callLoadersAndMaybeResolveData(state.matches, matches, matchesToLoad, revalidatingFetchers, revalidationRequest);

      if (abortController.signal.aborted) {
        return;
      }

      fetchReloadIds.delete(key);
      fetchControllers.delete(key);
      revalidatingFetchers.forEach(_ref7 => {
        let [staleKey] = _ref7;
        return fetchControllers.delete(staleKey);
      });
      let redirect = findRedirect(results);

      if (redirect) {
        return startRedirectNavigation(state, redirect);
      } // Process and commit output from loaders


      let {
        loaderData,
        errors
      } = processLoaderData(state, state.matches, matchesToLoad, loaderResults, undefined, revalidatingFetchers, fetcherResults, activeDeferreds);
      let doneFetcher = {
        state: "idle",
        data: actionResult.data,
        formMethod: undefined,
        formAction: undefined,
        formEncType: undefined,
        formData: undefined
      };
      state.fetchers.set(key, doneFetcher);
      let didAbortFetchLoads = abortStaleFetchLoads(loadId); // If we are currently in a navigation loading state and this fetcher is
      // more recent than the navigation, we want the newer data so abort the
      // navigation and complete it with the fetcher data

      if (state.navigation.state === "loading" && loadId > pendingNavigationLoadId) {
        invariant(pendingAction, "Expected pending action");
        pendingNavigationController && pendingNavigationController.abort();
        completeNavigation(state.navigation.location, {
          matches,
          loaderData,
          errors,
          fetchers: new Map(state.fetchers)
        });
      } else {
        // otherwise just update with the fetcher data, preserving any existing
        // loaderData for loaders that did not need to reload.  We have to
        // manually merge here since we aren't going through completeNavigation
        updateState(_extends({
          errors,
          loaderData: mergeLoaderData(state.loaderData, loaderData, matches)
        }, didAbortFetchLoads ? {
          fetchers: new Map(state.fetchers)
        } : {}));
        isRevalidationRequired = false;
      }
    } // Call the matched loader for fetcher.load(), handling redirects, errors, etc.


    async function handleFetcherLoader(key, routeId, path, match, matches, submission) {
      let existingFetcher = state.fetchers.get(key); // Put this fetcher into it's loading state

      let loadingFetcher = _extends({
        state: "loading",
        formMethod: undefined,
        formAction: undefined,
        formEncType: undefined,
        formData: undefined
      }, submission, {
        data: existingFetcher && existingFetcher.data
      });

      state.fetchers.set(key, loadingFetcher);
      updateState({
        fetchers: new Map(state.fetchers)
      }); // Call the loader for this fetcher route match

      let abortController = new AbortController();
      let fetchRequest = createClientSideRequest(path, abortController.signal);
      fetchControllers.set(key, abortController);
      let result = await callLoaderOrAction("loader", fetchRequest, match, matches, router.basename); // Deferred isn't supported or fetcher loads, await everything and treat it
      // as a normal load.  resolveDeferredData will return undefined if this
      // fetcher gets aborted, so we just leave result untouched and short circuit
      // below if that happens

      if (isDeferredResult(result)) {
        result = (await resolveDeferredData(result, fetchRequest.signal, true)) || result;
      } // We can delete this so long as we weren't aborted by ou our own fetcher
      // re-load which would have put _new_ controller is in fetchControllers


      if (fetchControllers.get(key) === abortController) {
        fetchControllers.delete(key);
      }

      if (fetchRequest.signal.aborted) {
        return;
      } // If the loader threw a redirect Response, start a new REPLACE navigation


      if (isRedirectResult(result)) {
        await startRedirectNavigation(state, result);
        return;
      } // Process any non-redirect errors thrown


      if (isErrorResult(result)) {
        let boundaryMatch = findNearestBoundary(state.matches, routeId);
        state.fetchers.delete(key); // TODO: In remix, this would reset to IDLE_NAVIGATION if it was a catch -
        // do we need to behave any differently with our non-redirect errors?
        // What if it was a non-redirect Response?

        updateState({
          fetchers: new Map(state.fetchers),
          errors: {
            [boundaryMatch.route.id]: result.error
          }
        });
        return;
      }

      invariant(!isDeferredResult(result), "Unhandled fetcher deferred data"); // Put the fetcher back into an idle state

      let doneFetcher = {
        state: "idle",
        data: result.data,
        formMethod: undefined,
        formAction: undefined,
        formEncType: undefined,
        formData: undefined
      };
      state.fetchers.set(key, doneFetcher);
      updateState({
        fetchers: new Map(state.fetchers)
      });
    }
    /**
     * Utility function to handle redirects returned from an action or loader.
     * Normally, a redirect "replaces" the navigation that triggered it.  So, for
     * example:
     *
     *  - user is on /a
     *  - user clicks a link to /b
     *  - loader for /b redirects to /c
     *
     * In a non-JS app the browser would track the in-flight navigation to /b and
     * then replace it with /c when it encountered the redirect response.  In
     * the end it would only ever update the URL bar with /c.
     *
     * In client-side routing using pushState/replaceState, we aim to emulate
     * this behavior and we also do not update history until the end of the
     * navigation (including processed redirects).  This means that we never
     * actually touch history until we've processed redirects, so we just use
     * the history action from the original navigation (PUSH or REPLACE).
     */


    async function startRedirectNavigation(state, redirect, replace) {
      var _window;

      if (redirect.revalidate) {
        isRevalidationRequired = true;
      }

      let redirectLocation = createLocation(state.location, redirect.location);
      invariant(redirectLocation, "Expected a location on the redirect navigation"); // Check if this an external redirect that goes to a new origin

      if (typeof ((_window = window) == null ? void 0 : _window.location) !== "undefined") {
        let newOrigin = createClientSideURL(redirect.location).origin;

        if (window.location.origin !== newOrigin) {
          if (replace) {
            window.location.replace(redirect.location);
          } else {
            window.location.assign(redirect.location);
          }

          return;
        }
      } // There's no need to abort on redirects, since we don't detect the
      // redirect until the action/loaders have settled


      pendingNavigationController = null;
      let redirectHistoryAction = replace === true ? exports.Action.Replace : exports.Action.Push;
      let {
        formMethod,
        formAction,
        formEncType,
        formData
      } = state.navigation; // If this was a 307/308 submission we want to preserve the HTTP method and
      // re-submit the GET/POST/PUT/PATCH/DELETE as a submission navigation to the
      // redirected location

      if (redirectPreserveMethodStatusCodes.has(redirect.status) && formMethod && isMutationMethod(formMethod) && formEncType && formData) {
        await startNavigation(redirectHistoryAction, redirectLocation, {
          submission: {
            formMethod,
            formAction: redirect.location,
            formEncType,
            formData
          }
        });
      } else {
        // Otherwise, we kick off a new loading navigation, preserving the
        // submission info for the duration of this navigation
        await startNavigation(redirectHistoryAction, redirectLocation, {
          overrideNavigation: {
            state: "loading",
            location: redirectLocation,
            formMethod: formMethod || undefined,
            formAction: formAction || undefined,
            formEncType: formEncType || undefined,
            formData: formData || undefined
          }
        });
      }
    }

    async function callLoadersAndMaybeResolveData(currentMatches, matches, matchesToLoad, fetchersToLoad, request) {
      // Call all navigation loaders and revalidating fetcher loaders in parallel,
      // then slice off the results into separate arrays so we can handle them
      // accordingly
      let results = await Promise.all([...matchesToLoad.map(match => callLoaderOrAction("loader", request, match, matches, router.basename)), ...fetchersToLoad.map(_ref8 => {
        let [, href, match, fetchMatches] = _ref8;
        return callLoaderOrAction("loader", createClientSideRequest(href, request.signal), match, fetchMatches, router.basename);
      })]);
      let loaderResults = results.slice(0, matchesToLoad.length);
      let fetcherResults = results.slice(matchesToLoad.length);
      await Promise.all([resolveDeferredResults(currentMatches, matchesToLoad, loaderResults, request.signal, false, state.loaderData), resolveDeferredResults(currentMatches, fetchersToLoad.map(_ref9 => {
        let [,, match] = _ref9;
        return match;
      }), fetcherResults, request.signal, true)]);
      return {
        results,
        loaderResults,
        fetcherResults
      };
    }

    function interruptActiveLoads() {
      // Every interruption triggers a revalidation
      isRevalidationRequired = true; // Cancel pending route-level deferreds and mark cancelled routes for
      // revalidation

      cancelledDeferredRoutes.push(...cancelActiveDeferreds()); // Abort in-flight fetcher loads

      fetchLoadMatches.forEach((_, key) => {
        if (fetchControllers.has(key)) {
          cancelledFetcherLoads.push(key);
          abortFetcher(key);
        }
      });
    }

    function setFetcherError(key, routeId, error) {
      let boundaryMatch = findNearestBoundary(state.matches, routeId);
      deleteFetcher(key);
      updateState({
        errors: {
          [boundaryMatch.route.id]: error
        },
        fetchers: new Map(state.fetchers)
      });
    }

    function deleteFetcher(key) {
      if (fetchControllers.has(key)) abortFetcher(key);
      fetchLoadMatches.delete(key);
      fetchReloadIds.delete(key);
      fetchRedirectIds.delete(key);
      state.fetchers.delete(key);
    }

    function abortFetcher(key) {
      let controller = fetchControllers.get(key);
      invariant(controller, "Expected fetch controller: " + key);
      controller.abort();
      fetchControllers.delete(key);
    }

    function markFetchersDone(keys) {
      for (let key of keys) {
        let fetcher = getFetcher(key);
        let doneFetcher = {
          state: "idle",
          data: fetcher.data,
          formMethod: undefined,
          formAction: undefined,
          formEncType: undefined,
          formData: undefined
        };
        state.fetchers.set(key, doneFetcher);
      }
    }

    function markFetchRedirectsDone() {
      let doneKeys = [];

      for (let key of fetchRedirectIds) {
        let fetcher = state.fetchers.get(key);
        invariant(fetcher, "Expected fetcher: " + key);

        if (fetcher.state === "loading") {
          fetchRedirectIds.delete(key);
          doneKeys.push(key);
        }
      }

      markFetchersDone(doneKeys);
    }

    function abortStaleFetchLoads(landedId) {
      let yeetedKeys = [];

      for (let [key, id] of fetchReloadIds) {
        if (id < landedId) {
          let fetcher = state.fetchers.get(key);
          invariant(fetcher, "Expected fetcher: " + key);

          if (fetcher.state === "loading") {
            abortFetcher(key);
            fetchReloadIds.delete(key);
            yeetedKeys.push(key);
          }
        }
      }

      markFetchersDone(yeetedKeys);
      return yeetedKeys.length > 0;
    }

    function cancelActiveDeferreds(predicate) {
      let cancelledRouteIds = [];
      activeDeferreds.forEach((dfd, routeId) => {
        if (!predicate || predicate(routeId)) {
          // Cancel the deferred - but do not remove from activeDeferreds here -
          // we rely on the subscribers to do that so our tests can assert proper
          // cleanup via _internalActiveDeferreds
          dfd.cancel();
          cancelledRouteIds.push(routeId);
          activeDeferreds.delete(routeId);
        }
      });
      return cancelledRouteIds;
    } // Opt in to capturing and reporting scroll positions during navigations,
    // used by the <ScrollRestoration> component


    function enableScrollRestoration(positions, getPosition, getKey) {
      savedScrollPositions = positions;
      getScrollPosition = getPosition;

      getScrollRestorationKey = getKey || (location => location.key); // Perform initial hydration scroll restoration, since we miss the boat on
      // the initial updateState() because we've not yet rendered <ScrollRestoration/>
      // and therefore have no savedScrollPositions available


      if (!initialScrollRestored && state.navigation === IDLE_NAVIGATION) {
        initialScrollRestored = true;
        let y = getSavedScrollPosition(state.location, state.matches);

        if (y != null) {
          updateState({
            restoreScrollPosition: y
          });
        }
      }

      return () => {
        savedScrollPositions = null;
        getScrollPosition = null;
        getScrollRestorationKey = null;
      };
    }

    function saveScrollPosition(location, matches) {
      if (savedScrollPositions && getScrollRestorationKey && getScrollPosition) {
        let userMatches = matches.map(m => createUseMatchesMatch(m, state.loaderData));
        let key = getScrollRestorationKey(location, userMatches) || location.key;
        savedScrollPositions[key] = getScrollPosition();
      }
    }

    function getSavedScrollPosition(location, matches) {
      if (savedScrollPositions && getScrollRestorationKey && getScrollPosition) {
        let userMatches = matches.map(m => createUseMatchesMatch(m, state.loaderData));
        let key = getScrollRestorationKey(location, userMatches) || location.key;
        let y = savedScrollPositions[key];

        if (typeof y === "number") {
          return y;
        }
      }

      return null;
    }

    router = {
      get basename() {
        return init.basename;
      },

      get state() {
        return state;
      },

      get routes() {
        return dataRoutes;
      },

      initialize,
      subscribe,
      enableScrollRestoration,
      navigate,
      fetch,
      revalidate,
      // Passthrough to history-aware createHref used by useHref so we get proper
      // hash-aware URLs in DOM paths
      createHref: to => init.history.createHref(to),
      encodeLocation: to => init.history.encodeLocation(to),
      getFetcher,
      deleteFetcher,
      dispose,
      _internalFetchControllers: fetchControllers,
      _internalActiveDeferreds: activeDeferreds
    };
    return router;
  } //#endregion
  ////////////////////////////////////////////////////////////////////////////////
  //#region createStaticHandler
  ////////////////////////////////////////////////////////////////////////////////

  function unstable_createStaticHandler(routes, opts) {
    invariant(routes.length > 0, "You must provide a non-empty routes array to unstable_createStaticHandler");
    let dataRoutes = convertRoutesToDataRoutes(routes);
    let basename = (opts ? opts.basename : null) || "/";
    /**
     * The query() method is intended for document requests, in which we want to
     * call an optional action and potentially multiple loaders for all nested
     * routes.  It returns a StaticHandlerContext object, which is very similar
     * to the router state (location, loaderData, actionData, errors, etc.) and
     * also adds SSR-specific information such as the statusCode and headers
     * from action/loaders Responses.
     *
     * It _should_ never throw and should report all errors through the
     * returned context.errors object, properly associating errors to their error
     * boundary.  Additionally, it tracks _deepestRenderedBoundaryId which can be
     * used to emulate React error boundaries during SSr by performing a second
     * pass only down to the boundaryId.
     *
     * The one exception where we do not return a StaticHandlerContext is when a
     * redirect response is returned or thrown from any action/loader.  We
     * propagate that out and return the raw Response so the HTTP server can
     * return it directly.
     */

    async function query(request, _temp) {
      let {
        requestContext
      } = _temp === void 0 ? {} : _temp;
      let url = new URL(request.url);
      let method = request.method.toLowerCase();
      let location = createLocation("", createPath(url), null, "default");
      let matches = matchRoutes(dataRoutes, location, basename); // SSR supports HEAD requests while SPA doesn't

      if (!isValidMethod(method) && method !== "head") {
        let error = getInternalRouterError(405, {
          method
        });
        let {
          matches: methodNotAllowedMatches,
          route
        } = getShortCircuitMatches(dataRoutes);
        return {
          basename,
          location,
          matches: methodNotAllowedMatches,
          loaderData: {},
          actionData: null,
          errors: {
            [route.id]: error
          },
          statusCode: error.status,
          loaderHeaders: {},
          actionHeaders: {}
        };
      } else if (!matches) {
        let error = getInternalRouterError(404, {
          pathname: location.pathname
        });
        let {
          matches: notFoundMatches,
          route
        } = getShortCircuitMatches(dataRoutes);
        return {
          basename,
          location,
          matches: notFoundMatches,
          loaderData: {},
          actionData: null,
          errors: {
            [route.id]: error
          },
          statusCode: error.status,
          loaderHeaders: {},
          actionHeaders: {}
        };
      }

      let result = await queryImpl(request, location, matches, requestContext);

      if (isResponse(result)) {
        return result;
      } // When returning StaticHandlerContext, we patch back in the location here
      // since we need it for React Context.  But this helps keep our submit and
      // loadRouteData operating on a Request instead of a Location


      return _extends({
        location,
        basename
      }, result);
    }
    /**
     * The queryRoute() method is intended for targeted route requests, either
     * for fetch ?_data requests or resource route requests.  In this case, we
     * are only ever calling a single action or loader, and we are returning the
     * returned value directly.  In most cases, this will be a Response returned
     * from the action/loader, but it may be a primitive or other value as well -
     * and in such cases the calling context should handle that accordingly.
     *
     * We do respect the throw/return differentiation, so if an action/loader
     * throws, then this method will throw the value.  This is important so we
     * can do proper boundary identification in Remix where a thrown Response
     * must go to the Catch Boundary but a returned Response is happy-path.
     *
     * One thing to note is that any Router-initiated Errors that make sense
     * to associate with a status code will be thrown as an ErrorResponse
     * instance which include the raw Error, such that the calling context can
     * serialize the error as they see fit while including the proper response
     * code.  Examples here are 404 and 405 errors that occur prior to reaching
     * any user-defined loaders.
     */


    async function queryRoute(request, _temp2) {
      let {
        routeId,
        requestContext
      } = _temp2 === void 0 ? {} : _temp2;
      let url = new URL(request.url);
      let method = request.method.toLowerCase();
      let location = createLocation("", createPath(url), null, "default");
      let matches = matchRoutes(dataRoutes, location, basename); // SSR supports HEAD requests while SPA doesn't

      if (!isValidMethod(method) && method !== "head") {
        throw getInternalRouterError(405, {
          method
        });
      } else if (!matches) {
        throw getInternalRouterError(404, {
          pathname: location.pathname
        });
      }

      let match = routeId ? matches.find(m => m.route.id === routeId) : getTargetMatch(matches, location);

      if (routeId && !match) {
        throw getInternalRouterError(403, {
          pathname: location.pathname,
          routeId
        });
      } else if (!match) {
        // This should never hit I don't think?
        throw getInternalRouterError(404, {
          pathname: location.pathname
        });
      }

      let result = await queryImpl(request, location, matches, requestContext, match);

      if (isResponse(result)) {
        return result;
      }

      let error = result.errors ? Object.values(result.errors)[0] : undefined;

      if (error !== undefined) {
        // If we got back result.errors, that means the loader/action threw
        // _something_ that wasn't a Response, but it's not guaranteed/required
        // to be an `instanceof Error` either, so we have to use throw here to
        // preserve the "error" state outside of queryImpl.
        throw error;
      } // Pick off the right state value to return


      let routeData = [result.actionData, result.loaderData].find(v => v);
      return Object.values(routeData || {})[0];
    }

    async function queryImpl(request, location, matches, requestContext, routeMatch) {
      invariant(request.signal, "query()/queryRoute() requests must contain an AbortController signal");

      try {
        if (isMutationMethod(request.method.toLowerCase())) {
          let result = await submit(request, matches, routeMatch || getTargetMatch(matches, location), requestContext, routeMatch != null);
          return result;
        }

        let result = await loadRouteData(request, matches, requestContext, routeMatch);
        return isResponse(result) ? result : _extends({}, result, {
          actionData: null,
          actionHeaders: {}
        });
      } catch (e) {
        // If the user threw/returned a Response in callLoaderOrAction, we throw
        // it to bail out and then return or throw here based on whether the user
        // returned or threw
        if (isQueryRouteResponse(e)) {
          if (e.type === ResultType.error && !isRedirectResponse(e.response)) {
            throw e.response;
          }

          return e.response;
        } // Redirects are always returned since they don't propagate to catch
        // boundaries


        if (isRedirectResponse(e)) {
          return e;
        }

        throw e;
      }
    }

    async function submit(request, matches, actionMatch, requestContext, isRouteRequest) {
      let result;

      if (!actionMatch.route.action) {
        let error = getInternalRouterError(405, {
          method: request.method,
          pathname: new URL(request.url).pathname,
          routeId: actionMatch.route.id
        });

        if (isRouteRequest) {
          throw error;
        }

        result = {
          type: ResultType.error,
          error
        };
      } else {
        result = await callLoaderOrAction("action", request, actionMatch, matches, basename, true, isRouteRequest, requestContext);

        if (request.signal.aborted) {
          let method = isRouteRequest ? "queryRoute" : "query";
          throw new Error(method + "() call aborted");
        }
      }

      if (isRedirectResult(result)) {
        // Uhhhh - this should never happen, we should always throw these from
        // callLoaderOrAction, but the type narrowing here keeps TS happy and we
        // can get back on the "throw all redirect responses" train here should
        // this ever happen :/
        throw new Response(null, {
          status: result.status,
          headers: {
            Location: result.location
          }
        });
      }

      if (isDeferredResult(result)) {
        throw new Error("defer() is not supported in actions");
      }

      if (isRouteRequest) {
        // Note: This should only be non-Response values if we get here, since
        // isRouteRequest should throw any Response received in callLoaderOrAction
        if (isErrorResult(result)) {
          throw result.error;
        }

        return {
          matches: [actionMatch],
          loaderData: {},
          actionData: {
            [actionMatch.route.id]: result.data
          },
          errors: null,
          // Note: statusCode + headers are unused here since queryRoute will
          // return the raw Response or value
          statusCode: 200,
          loaderHeaders: {},
          actionHeaders: {}
        };
      }

      if (isErrorResult(result)) {
        // Store off the pending error - we use it to determine which loaders
        // to call and will commit it when we complete the navigation
        let boundaryMatch = findNearestBoundary(matches, actionMatch.route.id);
        let context = await loadRouteData(request, matches, requestContext, undefined, {
          [boundaryMatch.route.id]: result.error
        }); // action status codes take precedence over loader status codes

        return _extends({}, context, {
          statusCode: isRouteErrorResponse(result.error) ? result.error.status : 500,
          actionData: null,
          actionHeaders: _extends({}, result.headers ? {
            [actionMatch.route.id]: result.headers
          } : {})
        });
      } // Create a GET request for the loaders


      let loaderRequest = new Request(request.url, {
        headers: request.headers,
        redirect: request.redirect,
        signal: request.signal
      });
      let context = await loadRouteData(loaderRequest, matches, requestContext);
      return _extends({}, context, result.statusCode ? {
        statusCode: result.statusCode
      } : {}, {
        actionData: {
          [actionMatch.route.id]: result.data
        },
        actionHeaders: _extends({}, result.headers ? {
          [actionMatch.route.id]: result.headers
        } : {})
      });
    }

    async function loadRouteData(request, matches, requestContext, routeMatch, pendingActionError) {
      let isRouteRequest = routeMatch != null; // Short circuit if we have no loaders to run (queryRoute())

      if (isRouteRequest && !(routeMatch != null && routeMatch.route.loader)) {
        throw getInternalRouterError(400, {
          method: request.method,
          pathname: new URL(request.url).pathname,
          routeId: routeMatch == null ? void 0 : routeMatch.route.id
        });
      }

      let requestMatches = routeMatch ? [routeMatch] : getLoaderMatchesUntilBoundary(matches, Object.keys(pendingActionError || {})[0]);
      let matchesToLoad = requestMatches.filter(m => m.route.loader); // Short circuit if we have no loaders to run (query())

      if (matchesToLoad.length === 0) {
        return {
          matches,
          loaderData: {},
          errors: pendingActionError || null,
          statusCode: 200,
          loaderHeaders: {}
        };
      }

      let results = await Promise.all([...matchesToLoad.map(match => callLoaderOrAction("loader", request, match, matches, basename, true, isRouteRequest, requestContext))]);

      if (request.signal.aborted) {
        let method = isRouteRequest ? "queryRoute" : "query";
        throw new Error(method + "() call aborted");
      } // Can't do anything with these without the Remix side of things, so just
      // cancel them for now


      results.forEach(result => {
        if (isDeferredResult(result)) {
          result.deferredData.cancel();
        }
      }); // Process and commit output from loaders

      let context = processRouteLoaderData(matches, matchesToLoad, results, pendingActionError);
      return _extends({}, context, {
        matches
      });
    }

    return {
      dataRoutes,
      query,
      queryRoute
    };
  } //#endregion
  ////////////////////////////////////////////////////////////////////////////////
  //#region Helpers
  ////////////////////////////////////////////////////////////////////////////////

  /**
   * Given an existing StaticHandlerContext and an error thrown at render time,
   * provide an updated StaticHandlerContext suitable for a second SSR render
   */

  function getStaticContextFromError(routes, context, error) {
    let newContext = _extends({}, context, {
      statusCode: 500,
      errors: {
        [context._deepestRenderedBoundaryId || routes[0].id]: error
      }
    });

    return newContext;
  }

  function isSubmissionNavigation(opts) {
    return opts != null && "formData" in opts;
  } // Normalize navigation options by converting formMethod=GET formData objects to
  // URLSearchParams so they behave identically to links with query params


  function normalizeNavigateOptions(to, opts, isFetcher) {
    if (isFetcher === void 0) {
      isFetcher = false;
    }

    let path = typeof to === "string" ? to : createPath(to); // Return location verbatim on non-submission navigations

    if (!opts || !isSubmissionNavigation(opts)) {
      return {
        path
      };
    }

    if (opts.formMethod && !isValidMethod(opts.formMethod)) {
      return {
        path,
        error: getInternalRouterError(405, {
          method: opts.formMethod
        })
      };
    } // Create a Submission on non-GET navigations


    let submission;

    if (opts.formData) {
      submission = {
        formMethod: opts.formMethod || "get",
        formAction: stripHashFromPath(path),
        formEncType: opts && opts.formEncType || "application/x-www-form-urlencoded",
        formData: opts.formData
      };

      if (isMutationMethod(submission.formMethod)) {
        return {
          path,
          submission
        };
      }
    } // Flatten submission onto URLSearchParams for GET submissions


    let parsedPath = parsePath(path);

    try {
      let searchParams = convertFormDataToSearchParams(opts.formData); // Since fetcher GET submissions only run a single loader (as opposed to
      // navigation GET submissions which run all loaders), we need to preserve
      // any incoming ?index params

      if (isFetcher && parsedPath.search && hasNakedIndexQuery(parsedPath.search)) {
        searchParams.append("index", "");
      }

      parsedPath.search = "?" + searchParams;
    } catch (e) {
      return {
        path,
        error: getInternalRouterError(400)
      };
    }

    return {
      path: createPath(parsedPath),
      submission
    };
  } // Filter out all routes below any caught error as they aren't going to
  // render so we don't need to load them


  function getLoaderMatchesUntilBoundary(matches, boundaryId) {
    let boundaryMatches = matches;

    if (boundaryId) {
      let index = matches.findIndex(m => m.route.id === boundaryId);

      if (index >= 0) {
        boundaryMatches = matches.slice(0, index);
      }
    }

    return boundaryMatches;
  }

  function getMatchesToLoad(state, matches, submission, location, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, pendingActionData, pendingError, fetchLoadMatches) {
    let actionResult = pendingError ? Object.values(pendingError)[0] : pendingActionData ? Object.values(pendingActionData)[0] : null; // Pick navigation matches that are net-new or qualify for revalidation

    let boundaryId = pendingError ? Object.keys(pendingError)[0] : undefined;
    let boundaryMatches = getLoaderMatchesUntilBoundary(matches, boundaryId);
    let navigationMatches = boundaryMatches.filter((match, index) => match.route.loader != null && (isNewLoader(state.loaderData, state.matches[index], match) || // If this route had a pending deferred cancelled it must be revalidated
    cancelledDeferredRoutes.some(id => id === match.route.id) || shouldRevalidateLoader(state.location, state.matches[index], submission, location, match, isRevalidationRequired, actionResult))); // Pick fetcher.loads that need to be revalidated

    let revalidatingFetchers = [];
    fetchLoadMatches && fetchLoadMatches.forEach((_ref10, key) => {
      let [href, match, fetchMatches] = _ref10;

      // This fetcher was cancelled from a prior action submission - force reload
      if (cancelledFetcherLoads.includes(key)) {
        revalidatingFetchers.push([key, href, match, fetchMatches]);
      } else if (isRevalidationRequired) {
        let shouldRevalidate = shouldRevalidateLoader(href, match, submission, href, match, isRevalidationRequired, actionResult);

        if (shouldRevalidate) {
          revalidatingFetchers.push([key, href, match, fetchMatches]);
        }
      }
    });
    return [navigationMatches, revalidatingFetchers];
  }

  function isNewLoader(currentLoaderData, currentMatch, match) {
    let isNew = // [a] -> [a, b]
    !currentMatch || // [a, b] -> [a, c]
    match.route.id !== currentMatch.route.id; // Handle the case that we don't have data for a re-used route, potentially
    // from a prior error or from a cancelled pending deferred

    let isMissingData = currentLoaderData[match.route.id] === undefined; // Always load if this is a net-new route or we don't yet have data

    return isNew || isMissingData;
  }

  function isNewRouteInstance(currentMatch, match) {
    let currentPath = currentMatch.route.path;
    return (// param change for this match, /users/123 -> /users/456
      currentMatch.pathname !== match.pathname || // splat param changed, which is not present in match.path
      // e.g. /files/images/avatar.jpg -> files/finances.xls
      currentPath && currentPath.endsWith("*") && currentMatch.params["*"] !== match.params["*"]
    );
  }

  function shouldRevalidateLoader(currentLocation, currentMatch, submission, location, match, isRevalidationRequired, actionResult) {
    let currentUrl = createClientSideURL(currentLocation);
    let currentParams = currentMatch.params;
    let nextUrl = createClientSideURL(location);
    let nextParams = match.params; // This is the default implementation as to when we revalidate.  If the route
    // provides it's own implementation, then we give them full control but
    // provide this value so they can leverage it if needed after they check
    // their own specific use cases
    // Note that fetchers always provide the same current/next locations so the
    // URL-based checks here don't apply to fetcher shouldRevalidate calls

    let defaultShouldRevalidate = isNewRouteInstance(currentMatch, match) || // Clicked the same link, resubmitted a GET form
    currentUrl.toString() === nextUrl.toString() || // Search params affect all loaders
    currentUrl.search !== nextUrl.search || // Forced revalidation due to submission, useRevalidate, or X-Remix-Revalidate
    isRevalidationRequired;

    if (match.route.shouldRevalidate) {
      let routeChoice = match.route.shouldRevalidate(_extends({
        currentUrl,
        currentParams,
        nextUrl,
        nextParams
      }, submission, {
        actionResult,
        defaultShouldRevalidate
      }));

      if (typeof routeChoice === "boolean") {
        return routeChoice;
      }
    }

    return defaultShouldRevalidate;
  }

  async function callLoaderOrAction(type, request, match, matches, basename, isStaticRequest, isRouteRequest, requestContext) {
    if (basename === void 0) {
      basename = "/";
    }

    if (isStaticRequest === void 0) {
      isStaticRequest = false;
    }

    if (isRouteRequest === void 0) {
      isRouteRequest = false;
    }

    let resultType;
    let result; // Setup a promise we can race against so that abort signals short circuit

    let reject;
    let abortPromise = new Promise((_, r) => reject = r);

    let onReject = () => reject();

    request.signal.addEventListener("abort", onReject);

    try {
      let handler = match.route[type];
      invariant(handler, "Could not find the " + type + " to run on the \"" + match.route.id + "\" route");
      result = await Promise.race([handler({
        request,
        params: match.params,
        context: requestContext
      }), abortPromise]);
      invariant(result !== undefined, "You defined " + (type === "action" ? "an action" : "a loader") + " for route " + ("\"" + match.route.id + "\" but didn't return anything from your `" + type + "` ") + "function. Please return a value or `null`.");
    } catch (e) {
      resultType = ResultType.error;
      result = e;
    } finally {
      request.signal.removeEventListener("abort", onReject);
    }

    if (isResponse(result)) {
      let status = result.status; // Process redirects

      if (redirectStatusCodes.has(status)) {
        let location = result.headers.get("Location");
        invariant(location, "Redirects returned/thrown from loaders/actions must have a Location header");
        let isAbsolute = /^[a-z+]+:\/\//i.test(location) || location.startsWith("//"); // Support relative routing in internal redirects

        if (!isAbsolute) {
          let activeMatches = matches.slice(0, matches.indexOf(match) + 1);
          let routePathnames = getPathContributingMatches(activeMatches).map(match => match.pathnameBase);
          let resolvedLocation = resolveTo(location, routePathnames, new URL(request.url).pathname);
          invariant(createPath(resolvedLocation), "Unable to resolve redirect location: " + location); // Prepend the basename to the redirect location if we have one

          if (basename) {
            let path = resolvedLocation.pathname;
            resolvedLocation.pathname = path === "/" ? basename : joinPaths([basename, path]);
          }

          location = createPath(resolvedLocation);
        } // Don't process redirects in the router during static requests requests.
        // Instead, throw the Response and let the server handle it with an HTTP
        // redirect.  We also update the Location header in place in this flow so
        // basename and relative routing is taken into account


        if (isStaticRequest) {
          result.headers.set("Location", location);
          throw result;
        }

        return {
          type: ResultType.redirect,
          status,
          location,
          revalidate: result.headers.get("X-Remix-Revalidate") !== null
        };
      } // For SSR single-route requests, we want to hand Responses back directly
      // without unwrapping.  We do this with the QueryRouteResponse wrapper
      // interface so we can know whether it was returned or thrown


      if (isRouteRequest) {
        // eslint-disable-next-line no-throw-literal
        throw {
          type: resultType || ResultType.data,
          response: result
        };
      }

      let data;
      let contentType = result.headers.get("Content-Type");

      if (contentType && contentType.startsWith("application/json")) {
        data = await result.json();
      } else {
        data = await result.text();
      }

      if (resultType === ResultType.error) {
        return {
          type: resultType,
          error: new ErrorResponse(status, result.statusText, data),
          headers: result.headers
        };
      }

      return {
        type: ResultType.data,
        data,
        statusCode: result.status,
        headers: result.headers
      };
    }

    if (resultType === ResultType.error) {
      return {
        type: resultType,
        error: result
      };
    }

    if (result instanceof DeferredData) {
      return {
        type: ResultType.deferred,
        deferredData: result
      };
    }

    return {
      type: ResultType.data,
      data: result
    };
  } // Utility method for creating the Request instances for loaders/actions during
  // client-side navigations and fetches.  During SSR we will always have a
  // Request instance from the static handler (query/queryRoute)


  function createClientSideRequest(location, signal, submission) {
    let url = createClientSideURL(stripHashFromPath(location)).toString();
    let init = {
      signal
    };

    if (submission && isMutationMethod(submission.formMethod)) {
      let {
        formMethod,
        formEncType,
        formData
      } = submission;
      init.method = formMethod.toUpperCase();
      init.body = formEncType === "application/x-www-form-urlencoded" ? convertFormDataToSearchParams(formData) : formData;
    } // Content-Type is inferred (https://fetch.spec.whatwg.org/#dom-request)


    return new Request(url, init);
  }

  function convertFormDataToSearchParams(formData) {
    let searchParams = new URLSearchParams();

    for (let [key, value] of formData.entries()) {
      invariant(typeof value === "string", 'File inputs are not supported with encType "application/x-www-form-urlencoded", ' + 'please use "multipart/form-data" instead.');
      searchParams.append(key, value);
    }

    return searchParams;
  }

  function processRouteLoaderData(matches, matchesToLoad, results, pendingError, activeDeferreds) {
    // Fill in loaderData/errors from our loaders
    let loaderData = {};
    let errors = null;
    let statusCode;
    let foundError = false;
    let loaderHeaders = {}; // Process loader results into state.loaderData/state.errors

    results.forEach((result, index) => {
      let id = matchesToLoad[index].route.id;
      invariant(!isRedirectResult(result), "Cannot handle redirect results in processLoaderData");

      if (isErrorResult(result)) {
        // Look upwards from the matched route for the closest ancestor
        // error boundary, defaulting to the root match
        let boundaryMatch = findNearestBoundary(matches, id);
        let error = result.error; // If we have a pending action error, we report it at the highest-route
        // that throws a loader error, and then clear it out to indicate that
        // it was consumed

        if (pendingError) {
          error = Object.values(pendingError)[0];
          pendingError = undefined;
        }

        errors = errors || {}; // Prefer higher error values if lower errors bubble to the same boundary

        if (errors[boundaryMatch.route.id] == null) {
          errors[boundaryMatch.route.id] = error;
        } // Once we find our first (highest) error, we set the status code and
        // prevent deeper status codes from overriding


        if (!foundError) {
          foundError = true;
          statusCode = isRouteErrorResponse(result.error) ? result.error.status : 500;
        }

        if (result.headers) {
          loaderHeaders[id] = result.headers;
        }
      } else if (isDeferredResult(result)) {
        activeDeferreds && activeDeferreds.set(id, result.deferredData);
        loaderData[id] = result.deferredData.data; // TODO: Add statusCode/headers once we wire up streaming in Remix
      } else {
        loaderData[id] = result.data; // Error status codes always override success status codes, but if all
        // loaders are successful we take the deepest status code.

        if (result.statusCode != null && result.statusCode !== 200 && !foundError) {
          statusCode = result.statusCode;
        }

        if (result.headers) {
          loaderHeaders[id] = result.headers;
        }
      }
    }); // If we didn't consume the pending action error (i.e., all loaders
    // resolved), then consume it here

    if (pendingError) {
      errors = pendingError;
    }

    return {
      loaderData,
      errors,
      statusCode: statusCode || 200,
      loaderHeaders
    };
  }

  function processLoaderData(state, matches, matchesToLoad, results, pendingError, revalidatingFetchers, fetcherResults, activeDeferreds) {
    let {
      loaderData,
      errors
    } = processRouteLoaderData(matches, matchesToLoad, results, pendingError, activeDeferreds); // Process results from our revalidating fetchers

    for (let index = 0; index < revalidatingFetchers.length; index++) {
      let [key,, match] = revalidatingFetchers[index];
      invariant(fetcherResults !== undefined && fetcherResults[index] !== undefined, "Did not find corresponding fetcher result");
      let result = fetcherResults[index]; // Process fetcher non-redirect errors

      if (isErrorResult(result)) {
        let boundaryMatch = findNearestBoundary(state.matches, match.route.id);

        if (!(errors && errors[boundaryMatch.route.id])) {
          errors = _extends({}, errors, {
            [boundaryMatch.route.id]: result.error
          });
        }

        state.fetchers.delete(key);
      } else if (isRedirectResult(result)) {
        // Should never get here, redirects should get processed above, but we
        // keep this to type narrow to a success result in the else
        throw new Error("Unhandled fetcher revalidation redirect");
      } else if (isDeferredResult(result)) {
        // Should never get here, deferred data should be awaited for fetchers
        // in resolveDeferredResults
        throw new Error("Unhandled fetcher deferred data");
      } else {
        let doneFetcher = {
          state: "idle",
          data: result.data,
          formMethod: undefined,
          formAction: undefined,
          formEncType: undefined,
          formData: undefined
        };
        state.fetchers.set(key, doneFetcher);
      }
    }

    return {
      loaderData,
      errors
    };
  }

  function mergeLoaderData(loaderData, newLoaderData, matches) {
    let mergedLoaderData = _extends({}, newLoaderData);

    matches.forEach(match => {
      let id = match.route.id;

      if (newLoaderData[id] === undefined && loaderData[id] !== undefined) {
        mergedLoaderData[id] = loaderData[id];
      }
    });
    return mergedLoaderData;
  } // Find the nearest error boundary, looking upwards from the leaf route (or the
  // route specified by routeId) for the closest ancestor error boundary,
  // defaulting to the root match


  function findNearestBoundary(matches, routeId) {
    let eligibleMatches = routeId ? matches.slice(0, matches.findIndex(m => m.route.id === routeId) + 1) : [...matches];
    return eligibleMatches.reverse().find(m => m.route.hasErrorBoundary === true) || matches[0];
  }

  function getShortCircuitMatches(routes) {
    // Prefer a root layout route if present, otherwise shim in a route object
    let route = routes.find(r => r.index || !r.path || r.path === "/") || {
      id: "__shim-error-route__"
    };
    return {
      matches: [{
        params: {},
        pathname: "",
        pathnameBase: "",
        route
      }],
      route
    };
  }

  function getInternalRouterError(status, _temp3) {
    let {
      pathname,
      routeId,
      method
    } = _temp3 === void 0 ? {} : _temp3;
    let statusText = "Unknown Server Error";
    let errorMessage = "Unknown @remix-run/router error";

    if (status === 400) {
      statusText = "Bad Request";

      if (method && pathname && routeId) {
        errorMessage = "You made a " + method + " request to \"" + pathname + "\" but " + ("did not provide a `loader` for route \"" + routeId + "\", ") + "so there is no way to handle the request.";
      } else {
        errorMessage = "Cannot submit binary form data using GET";
      }
    } else if (status === 403) {
      statusText = "Forbidden";
      errorMessage = "Route \"" + routeId + "\" does not match URL \"" + pathname + "\"";
    } else if (status === 404) {
      statusText = "Not Found";
      errorMessage = "No route matches URL \"" + pathname + "\"";
    } else if (status === 405) {
      statusText = "Method Not Allowed";

      if (method && pathname && routeId) {
        errorMessage = "You made a " + method.toUpperCase() + " request to \"" + pathname + "\" but " + ("did not provide an `action` for route \"" + routeId + "\", ") + "so there is no way to handle the request.";
      } else if (method) {
        errorMessage = "Invalid request method \"" + method.toUpperCase() + "\"";
      }
    }

    return new ErrorResponse(status || 500, statusText, new Error(errorMessage), true);
  } // Find any returned redirect errors, starting from the lowest match


  function findRedirect(results) {
    for (let i = results.length - 1; i >= 0; i--) {
      let result = results[i];

      if (isRedirectResult(result)) {
        return result;
      }
    }
  }

  function stripHashFromPath(path) {
    let parsedPath = typeof path === "string" ? parsePath(path) : path;
    return createPath(_extends({}, parsedPath, {
      hash: ""
    }));
  }

  function isHashChangeOnly(a, b) {
    return a.pathname === b.pathname && a.search === b.search && a.hash !== b.hash;
  }

  function isDeferredResult(result) {
    return result.type === ResultType.deferred;
  }

  function isErrorResult(result) {
    return result.type === ResultType.error;
  }

  function isRedirectResult(result) {
    return (result && result.type) === ResultType.redirect;
  }

  function isResponse(value) {
    return value != null && typeof value.status === "number" && typeof value.statusText === "string" && typeof value.headers === "object" && typeof value.body !== "undefined";
  }

  function isRedirectResponse(result) {
    if (!isResponse(result)) {
      return false;
    }

    let status = result.status;
    let location = result.headers.get("Location");
    return status >= 300 && status <= 399 && location != null;
  }

  function isQueryRouteResponse(obj) {
    return obj && isResponse(obj.response) && (obj.type === ResultType.data || ResultType.error);
  }

  function isValidMethod(method) {
    return validRequestMethods.has(method);
  }

  function isMutationMethod(method) {
    return validMutationMethods.has(method);
  }

  async function resolveDeferredResults(currentMatches, matchesToLoad, results, signal, isFetcher, currentLoaderData) {
    for (let index = 0; index < results.length; index++) {
      let result = results[index];
      let match = matchesToLoad[index];
      let currentMatch = currentMatches.find(m => m.route.id === match.route.id);
      let isRevalidatingLoader = currentMatch != null && !isNewRouteInstance(currentMatch, match) && (currentLoaderData && currentLoaderData[match.route.id]) !== undefined;

      if (isDeferredResult(result) && (isFetcher || isRevalidatingLoader)) {
        // Note: we do not have to touch activeDeferreds here since we race them
        // against the signal in resolveDeferredData and they'll get aborted
        // there if needed
        await resolveDeferredData(result, signal, isFetcher).then(result => {
          if (result) {
            results[index] = result || results[index];
          }
        });
      }
    }
  }

  async function resolveDeferredData(result, signal, unwrap) {
    if (unwrap === void 0) {
      unwrap = false;
    }

    let aborted = await result.deferredData.resolveData(signal);

    if (aborted) {
      return;
    }

    if (unwrap) {
      try {
        return {
          type: ResultType.data,
          data: result.deferredData.unwrappedData
        };
      } catch (e) {
        // Handle any TrackedPromise._error values encountered while unwrapping
        return {
          type: ResultType.error,
          error: e
        };
      }
    }

    return {
      type: ResultType.data,
      data: result.deferredData.data
    };
  }

  function hasNakedIndexQuery(search) {
    return new URLSearchParams(search).getAll("index").some(v => v === "");
  } // Note: This should match the format exported by useMatches, so if you change
  // this please also change that :)  Eventually we'll DRY this up


  function createUseMatchesMatch(match, loaderData) {
    let {
      route,
      pathname,
      params
    } = match;
    return {
      id: route.id,
      pathname,
      params,
      data: loaderData[route.id],
      handle: route.handle
    };
  }

  function getTargetMatch(matches, location) {
    let search = typeof location === "string" ? parsePath(location).search : location.search;

    if (matches[matches.length - 1].route.index && hasNakedIndexQuery(search || "")) {
      // Return the leaf index route when index is present
      return matches[matches.length - 1];
    } // Otherwise grab the deepest "path contributing" match (ignoring index and
    // pathless layout routes)


    let pathMatches = getPathContributingMatches(matches);
    return pathMatches[pathMatches.length - 1];
  } //#endregion

  exports.AbortedDeferredError = AbortedDeferredError;
  exports.ErrorResponse = ErrorResponse;
  exports.IDLE_FETCHER = IDLE_FETCHER;
  exports.IDLE_NAVIGATION = IDLE_NAVIGATION;
  exports.UNSAFE_convertRoutesToDataRoutes = convertRoutesToDataRoutes;
  exports.UNSAFE_getPathContributingMatches = getPathContributingMatches;
  exports.createBrowserHistory = createBrowserHistory;
  exports.createHashHistory = createHashHistory;
  exports.createMemoryHistory = createMemoryHistory;
  exports.createPath = createPath;
  exports.createRouter = createRouter;
  exports.defer = defer;
  exports.generatePath = generatePath;
  exports.getStaticContextFromError = getStaticContextFromError;
  exports.getToPathname = getToPathname;
  exports.invariant = invariant;
  exports.isRouteErrorResponse = isRouteErrorResponse;
  exports.joinPaths = joinPaths;
  exports.json = json;
  exports.matchPath = matchPath;
  exports.matchRoutes = matchRoutes;
  exports.normalizePathname = normalizePathname;
  exports.parsePath = parsePath;
  exports.redirect = redirect;
  exports.resolvePath = resolvePath;
  exports.resolveTo = resolveTo;
  exports.stripBasename = stripBasename;
  exports.unstable_createStaticHandler = unstable_createStaticHandler;
  exports.warning = warning;

  Object.defineProperty(exports, '__esModule', { value: true });

}));
//# sourceMappingURL=router.umd.js.map