@ramstack/alpinegear-router 1.2.4 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -0
- package/alpinegear-router.esm.js +28 -28
- package/alpinegear-router.esm.min.js +1 -1
- package/alpinegear-router.js +28 -28
- package/alpinegear-router.min.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -372,6 +372,11 @@ of any element, running a callback when the element is removed from the DOM.
|
|
|
372
372
|
**[@ramstack/alpinegear-hotkey](https://www.npmjs.com/package/@ramstack/alpinegear-hotkey)** ([README](https://github.com/rameel/ramstack.alpinegear.js/tree/main/src/plugins/hotkey))<br>
|
|
373
373
|
Provides the `x-hotkey` directive, which allows you to easily handle keyboard shortcuts within your Alpine.js components or application.
|
|
374
374
|
|
|
375
|
+
**[@ramstack/alpinegear-dialog](https://www.npmjs.com/package/@ramstack/alpinegear-dialog)** ([README](https://github.com/rameel/ramstack.alpinegear.js/tree/main/src/plugins/dialog))<br>
|
|
376
|
+
Provides a headless dialog directive for Alpine.js based on the native HTML `<dialog>` element.
|
|
377
|
+
It supports declarative composition, value-based close semantics, and both modal and non-modal dialogs,
|
|
378
|
+
with optional Promise-based imperative control.
|
|
379
|
+
|
|
375
380
|
|
|
376
381
|
## Contributions
|
|
377
382
|
Bug reports and contributions are welcome.
|
package/alpinegear-router.esm.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const warn = (...args) => console.warn("alpinegear.js:", ...args);
|
|
2
2
|
const is_array = Array.isArray;
|
|
3
3
|
const is_nullish = value => value === null || value === undefined;
|
|
4
|
-
const is_template = el => el
|
|
4
|
+
const is_template = el => el.matches("template");
|
|
5
5
|
const is_function = value => typeof value === "function";
|
|
6
6
|
const as_array = value => is_array(value) ? value : [value];
|
|
7
7
|
const has_modifier = (modifiers, modifier) => modifiers.includes(modifier);
|
|
@@ -454,7 +454,7 @@ async function load_template(path) {
|
|
|
454
454
|
result = await fetch(path);
|
|
455
455
|
}
|
|
456
456
|
catch {
|
|
457
|
-
|
|
457
|
+
// skip
|
|
458
458
|
}
|
|
459
459
|
|
|
460
460
|
if (!result?.ok) {
|
|
@@ -476,9 +476,9 @@ function route({ directive, $data }) {
|
|
|
476
476
|
return;
|
|
477
477
|
}
|
|
478
478
|
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
479
|
+
//
|
|
480
|
+
// x-route:view and x-route:handler must be declared on the same element as x-route
|
|
481
|
+
//
|
|
482
482
|
const route = el._r_route;
|
|
483
483
|
|
|
484
484
|
if (!route && (value === "view" || value === "handler")) {
|
|
@@ -661,7 +661,7 @@ function watch(get_value, callback, options = null) {
|
|
|
661
661
|
}
|
|
662
662
|
|
|
663
663
|
if (initialized || (options?.immediate ?? true)) {
|
|
664
|
-
|
|
664
|
+
// Prevent the watcher from detecting its own dependencies.
|
|
665
665
|
setTimeout(() => {
|
|
666
666
|
callback(new_value, old_value);
|
|
667
667
|
old_value = new_value;
|
|
@@ -681,7 +681,7 @@ function router({ $data, addScopeToNode, directive, magic, reactive }) {
|
|
|
681
681
|
const router = $data(el).$router;
|
|
682
682
|
|
|
683
683
|
if (!router && (value === "outlet" || value === "link")) {
|
|
684
|
-
warn(`
|
|
684
|
+
warn(`x-router:${value} is missing a parent x-router`);
|
|
685
685
|
return;
|
|
686
686
|
}
|
|
687
687
|
|
|
@@ -821,15 +821,15 @@ function router({ $data, addScopeToNode, directive, magic, reactive }) {
|
|
|
821
821
|
cleanup(unsubscribe);
|
|
822
822
|
}
|
|
823
823
|
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
824
|
+
//
|
|
825
|
+
// A warning about a non-existing anchor element is printed in the get_anchor_element function.
|
|
826
|
+
// warn("<a> element not found")
|
|
827
|
+
//
|
|
828
828
|
}
|
|
829
829
|
|
|
830
830
|
function process_outlet() {
|
|
831
831
|
if (router.outlet) {
|
|
832
|
-
warn("x-router:outlet already
|
|
832
|
+
warn("x-router:outlet is already present", router.outlet, el);
|
|
833
833
|
}
|
|
834
834
|
else {
|
|
835
835
|
router.outlet = el;
|
|
@@ -845,22 +845,22 @@ function router({ $data, addScopeToNode, directive, magic, reactive }) {
|
|
|
845
845
|
return false;
|
|
846
846
|
}
|
|
847
847
|
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
848
|
+
//
|
|
849
|
+
// Create a dependency on router.values
|
|
850
|
+
//
|
|
851
851
|
JSON.stringify(router.values);
|
|
852
852
|
|
|
853
853
|
const link = is_anchor_element(el) ? el : closest(el, node => node._r_routerlink)?._r_routerlink;
|
|
854
854
|
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
855
|
+
//
|
|
856
|
+
// The issue is that the router:link directive is processed later than x-bind,
|
|
857
|
+
// and if $active is used in x-bind, we won’t find node._r_routerlink.
|
|
858
|
+
// Therefore, we delay execution and try again.
|
|
859
|
+
//
|
|
860
|
+
// <div x-router:link :class="{ active: $active }">
|
|
861
|
+
// ...
|
|
862
|
+
// </div>
|
|
863
|
+
//
|
|
864
864
|
|
|
865
865
|
if (link) {
|
|
866
866
|
return router.history.resolve(link.href) === router.values.path;
|
|
@@ -872,9 +872,9 @@ function router({ $data, addScopeToNode, directive, magic, reactive }) {
|
|
|
872
872
|
else {
|
|
873
873
|
queueMicrotask(() => {
|
|
874
874
|
el._r_routerlink_init = true;
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
875
|
+
//
|
|
876
|
+
// Force an upate
|
|
877
|
+
//
|
|
878
878
|
router.values.path = router.values.path;
|
|
879
879
|
});
|
|
880
880
|
}
|
|
@@ -902,4 +902,4 @@ function plugin(alpine) {
|
|
|
902
902
|
alpine.plugin([router, route]);
|
|
903
903
|
}
|
|
904
904
|
|
|
905
|
-
export { RoutePattern, plugin as router };
|
|
905
|
+
export { RoutePattern, plugin as router };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const e=(...e)=>console.warn("alpinegear.js:",...e),t=Array.isArray,n=e=>null==e,r=e=>e
|
|
1
|
+
const e=(...e)=>console.warn("alpinegear.js:",...e),t=Array.isArray,n=e=>null==e,r=e=>e.matches("template"),a=e=>"function"==typeof e,o=e=>t(e)?e:[e],i=e=>a(e)&&"AsyncFunction"===e.constructor?.name?e:function(...t){const n=e.apply(this,t);return a(n?.then)?n:Promise.resolve(n)},l=(e,t,n,r)=>(e.addEventListener(t,n,r),()=>e.removeEventListener(t,n,r)),s=Object.freeze({regex(e){const t=new RegExp(e);return{test:e=>t.test(e)}},bool(){return{test:e=>/^(?:true|false)$/i.test(e),transform:e=>4===e.length}},int(){return{test:e=>/^-?\d+$/.test(e),transform:e=>+e}},number(){return{test:e=>/^[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?$/.test(e)&&isFinite(parseFloat(e)),transform:e=>parseFloat(e)}},alpha(){return{test:e=>/^[a-z]+$/i.test(e)}},min(e){return{test:t=>t>=+e}},max(e){return{test:t=>+e>=t}},range(e){let[t,n]=e.split(",",2).map(e=>e.trim());return{test:e=>e>=+t&&+n>=e}},length(e){let t=e.split(",").map(e=>e.trim());return{test:2==t.length?e=>e.length>=+t[0]&&+t[1]>=e.length:e=>e.length===+t[0]}},minlength(e){return{test:t=>t.length>=+e}},maxlength(e){return{test:t=>+e>=t.length}}});class u{#e;#t;#n;#r;#a;get template(){return this.#t}get regex(){return this.#e}get constraints(){return this.#a}constructor(e,t=null){this.#t=e,this.#e=function(e,t,r,a){t.push(...function(e,t){return function(e){e.find(e=>e.parts.length>1&&e.parts.every(e=>e.optional))&&u("Using all segment parameters as optional is not permitted");const r=new Map;return e.flatMap(e=>e.parts).forEach((e,a,o)=>{if("literal"!==e.kind||0>e.value.indexOf("?")||u("Literal segments cannot contain the '?' character"),"parameter"===e.kind){e.catch_all&&a!==o.length-1&&u("A catch-all parameter can only appear as the last segment"),r.has(e.name)&&u(`The route parameter name '${e.name}' appears more than one time`),"*"===e.quantifier&&n(e.default)&&(e.default=""),""===e.default&&"*"!==e.quantifier&&(e.default=null),r.set(e.name,!0);for(let r of e.constraints){const e=t?.[r.name]??s[r.name];n(e)&&u(`Unknown constraint '${r.name}'`),Object.assign(r,e(r.argument))}}}),e}(function(){const t=[];for(let n=0;e.length>n;){const e=r(n);e.template&&t.push(e),n+=e.template.length+1}return t}());function r(t){let n=[],r=t;for(;e.length>r&&"/"!==e[r];){const e=o(r)||a(r);n.push(e),r+=e.template.length}return{template:e.slice(t,r),parts:n}}function a(t){if("{"!==e[t])return null;const r=i(t),a=e.slice(t,t+r.length+2),o=function(e){const t=e.match(/^(?<name>[a-z_$][a-z0-9_$-]*?)(?:[:?+*]|$)/i)?.groups?.name;return n(t)&&u("Invalid parameter name"),t}(r),s=/[*+?]/.exec(r[o.length])?.[0]??"",c=function(e,t){const r=[];for(let a=t;e.length>a;){":"!==e[a]&&u();const t=l(e.slice(a+1));a+=t.length+1;const o="("===e[a]?i(a,e):null;n(o)||(a+=o.length+2),t||o||u(),r.push({name:"="===t?"default":t||"regex",argument:o??""})}return r}(r,o.length+s.length);return{name:o,kind:"parameter",template:a,quantifier:s,constraints:c.filter(e=>"default"!==e.name),default:c.find(e=>"default"===e.name)?.argument,required:"+"===s||""===s,optional:"?"===s||"*"===s,catch_all:"+"===s||"*"===s}}function o(t){for(let n=t;;n++)if(n>=e.length||"/"===e[n]||"{"===e[n]){if(n===t)return null;const r=e.slice(t,n);return{kind:"literal",template:r,value:r}}}function i(t,n){n??=e;const r=[];e:for(let e=t;n.length>e;e++){switch(n[e]){case"{":r.push("}");break;case"(":r.push(")");break;case"}":case")":if(r.pop()!==n[e])break e}if(0===r.length)return n.slice(t+1,e)}u()}function l(e){const t=e.match(/^(?<name>=|[a-z0-9_$]*)(?=[/:(]|$)/i)?.groups?.name;return n(t)&&u("Invalid constraint name"),t}function u(t="Invalid pattern"){throw new Error(`${t}: ${e}`)}}(e,a));let o=t.map(e=>e.parts.map((t,n)=>{if("literal"===t.kind)return n?t.value:`/${t.value}`;if(r.set(t.name,t),1===e.parts.length&&"?"===t.quantifier)return`(?:/(?<${t.name}>[^/]+?))?`;if(t.catch_all){let e=`(?<${t.name}>.${t.quantifier})`;return n||(e=`(?:/${e})`),"*"===t.quantifier&&(e+="?"),"*"===t.quantifier?e+"?":e}{const e=`(?<${t.name}>[^/]+?)${t.quantifier}`;return n?e:`/${e}`}}).join("")).join("")||"/";return"/"!==o&&(o+="/?"),new RegExp(`^${o}$`)}(e,this.#n=[],this.#r=new Map,this.#a=t??{})}match(e){let t=this.#e.exec(e);if(n(t))return null;t=t.groups??{};for(let[e,r]of this.#r.entries()){let a=t[e];if(n(a)&&n(r.default))continue;a||n(r.default)||(a=r.default);const o=r.catch_all?a.split("/").filter(e=>e.length):[a];for(let e=0;o.length>e;e++)for(let t of r.constraints){if(t.test&&!t.test(o[e]))return null;t.transform&&(o[e]=t.transform(o[e]))}t[e]=r.catch_all?o:o[0]}return t}resolve(e){e=new Map(Object.entries(e));const t=[];for(let r of this.#n){const a=[];for(let t of r.parts)if("literal"===t.kind)a.push(t.value);else{let r=e.get(t.name);if(e.delete(t.name),(n(r)||""===r)&&(r=this.#r.get(t.name)?.default,t.catch_all&&r&&(r=r.split("/"))),n(r)||""===r){if(t.required)return null;if(t.optional&&t.default===r)continue}t.catch_all?(r=o(r),a.push(...r.map(e=>encodeURIComponent(e)).join("/"))):a.push(encodeURIComponent(r))}a.length&&t.push(a.join(""))}let r=[...e.entries()].map(([e,t])=>encodeURIComponent(e)+"="+encodeURIComponent(t)).join("&");r&&(r="?"+r);const a=t.join("/")+r;return"/"!==a[0]?"/"+a:a}}function c({directive:t,$data:a}){t("route",(t,{expression:o,value:l},{cleanup:s,evaluate:c})=>{if(!r(t))return void e("x-route can only be used on a 'template' tag");const h=t._r_route;if(h||"view"!==l&&"handler"!==l)switch(l){case"view":h.view=()=>async function(t){let n;try{n=await fetch(t)}catch{}if(!n?.ok)return e(`Failed to load template from ${t}`),new DocumentFragment;const r=new DocumentFragment,a=(new DOMParser).parseFromString(await n.text(),"text/html");return r.append(...a.body.childNodes),r}(o),s(()=>{h.view=()=>new Promise(e=>e(new DocumentFragment))});break;case"handler":!function(){o||(o="[]"),o.startsWith("[")||(o=`[${o}]`);const e=c(o).map(i),r=a(t);h.handler=async t=>{for(let a of e){const e=await a.call(r,t);if(!n(e))return e}},s(()=>h.handler=null)}();break;default:!function(){const n=a(t)?.$router;if(n){const e=()=>new Promise(e=>e(t.content));t._r_route=Object.assign(new u(o),{el:t,view:e,handler:()=>Promise.resolve()}),n.routes.push(t._r_route),s(()=>n.routes=n.routes.filter(e=>e!==t._r_route))}else e("no x-router directive found")}()}else e("no x-route directive found")})}let h,f;function p(){for(let e in h)e in location&&(h[e]=location[e])}const m={get path(){return f.hash.slice(1)||"/"},get location(){return f},resolve(e){let t=new URL(e);return t.hash?t.hash.slice(1)||"/":t.pathname},navigate(e,t=!1){0>e.indexOf("#")&&(e="#"+e),g(e,t)}},d={get path(){return f.pathname},get location(){return f},resolve(e){return new URL(e).pathname},navigate(e,t=!1){g(e,t)}};function g(e,t){history[t?"replaceState":"pushState"]({},"",e),f.refresh()}const v={html5:d,hash:m};function w({$data:t,addScopeToNode:n,directive:a,magic:o,reactive:i}){a("router",(a,{modifiers:o,value:s},{cleanup:u})=>{s||(s="html5");const c=t(a).$router;if(c||"outlet"!==s&&"link"!==s)switch(s){case"outlet":c.outlet?e("x-router:outlet is already present",c.outlet,a):(c.outlet=a,u(()=>c.outlet=null));break;case"link":!function(){let t=function(t){if($(t))return t;const n=t.querySelectorAll("a");return 1!==n.length&&e(`Expected exactly one link, but found ${n.length}`),n[0]}(a);if(t){a._r_routerlink=t;const e=(t.getAttribute("target")??"").indexOf("_blank")>=0,n=l(t,"click",n=>{n.metaKey||n.altKey||n.ctrlKey||n.shiftKey||n.defaultPrevented||n.button>0||e||(n.preventDefault(),c.navigate(`${t.pathname}${t.search}${t.hash}`,(e=>e.includes("replace"))(o)))});u(n)}}();break;default:!function(){if(r(a))return void e("x-router cannot be used on a 'template' tag");const t=i({pattern:"",path:"",params:{}}),o=function(t){f??=(h||(h=Alpine.reactive({hash:"",host:"",hostname:"",href:"",origin:"",pathname:"",port:0,protocol:"",search:"",refresh(){p()}}),p(),l(window,"hashchange",p),l(window,"popstate",p)),h),t||="html5";let n=v[t];return n||(e(`Unknown history API: ${t}`),n=d),n}(s),c={routes:[],outlet:null,active:null,history:o,values:t,async match(e){for(let t of this.routes){const n=t.match(e);if(n){const r={router:c,route:t,params:n,path:e};if(!1!==await t.handler(r))return r}}},navigate(e,t=!1){return o.navigate(e,t),!0}};function m(){if(c.active){for(let e of c.active.nodes??[])e.remove();c.active.nodes=null,c.active=null}}n(a,{$route:t,$router:c});const g=function(e,t,n=null){const{effect:r,release:a}=Alpine;let o,i,l=!1;const s=r(()=>{o=e(),l||(n?.deep&&JSON.stringify(o),i=o),(l||(n?.immediate??1))&&setTimeout(()=>{t(o,i),i=o},0),l=!0});return()=>a(s)}(()=>o.path,async e=>{const n=await c.match(e);n?e===o.path&&function(e,n,a){if(e.nodes?.length&&t.path===n)return;m(),t.path=n,t.pattern=e.template,t.params=a??{},c.active=e;const o=c.outlet;o&&e.view().then(i=>{t.path===n&&t.pattern===e.template&&JSON.stringify(t.params)===JSON.stringify(a)&&(e.nodes=[...i.cloneNode(!0).childNodes],r(o)?e.nodes.forEach(e=>o.parentElement.insertBefore(e,o)):e.nodes.forEach(e=>o.append(e)))})}(n.route,n.path,n.params):m()});u(g),u(m)}()}else e(`x-router:${s} is missing a parent x-router`)}),o("active",n=>{const r=t(n).$router;if(!r)return e("No x-router directive found"),!1;JSON.stringify(r.values);const a=$(n)?n:((e,t)=>{for(;e&&!t(e);)e=(e._x_teleportBack??e).parentElement;return e})(n,e=>e._r_routerlink)?._r_routerlink;return a?r.history.resolve(a.href)===r.values.path:(n._r_routerlink_init?e("x-router:link directive not found",n):queueMicrotask(()=>{n._r_routerlink_init=!0,r.values.path=r.values.path}),!1)})}function $(e){return"A"===e.tagName.toUpperCase()}function _(e){window.RoutePattern=u,e.plugin([w,c])}export{u as RoutePattern,_ as router};
|
package/alpinegear-router.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
const warn = (...args) => console.warn("alpinegear.js:", ...args);
|
|
5
5
|
const is_array = Array.isArray;
|
|
6
6
|
const is_nullish = value => value === null || value === undefined;
|
|
7
|
-
const is_template = el => el
|
|
7
|
+
const is_template = el => el.matches("template");
|
|
8
8
|
const is_function = value => typeof value === "function";
|
|
9
9
|
const as_array = value => is_array(value) ? value : [value];
|
|
10
10
|
const has_modifier = (modifiers, modifier) => modifiers.includes(modifier);
|
|
@@ -457,7 +457,7 @@
|
|
|
457
457
|
result = await fetch(path);
|
|
458
458
|
}
|
|
459
459
|
catch {
|
|
460
|
-
|
|
460
|
+
// skip
|
|
461
461
|
}
|
|
462
462
|
|
|
463
463
|
if (!result?.ok) {
|
|
@@ -479,9 +479,9 @@
|
|
|
479
479
|
return;
|
|
480
480
|
}
|
|
481
481
|
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
482
|
+
//
|
|
483
|
+
// x-route:view and x-route:handler must be declared on the same element as x-route
|
|
484
|
+
//
|
|
485
485
|
const route = el._r_route;
|
|
486
486
|
|
|
487
487
|
if (!route && (value === "view" || value === "handler")) {
|
|
@@ -664,7 +664,7 @@
|
|
|
664
664
|
}
|
|
665
665
|
|
|
666
666
|
if (initialized || (options?.immediate ?? true)) {
|
|
667
|
-
|
|
667
|
+
// Prevent the watcher from detecting its own dependencies.
|
|
668
668
|
setTimeout(() => {
|
|
669
669
|
callback(new_value, old_value);
|
|
670
670
|
old_value = new_value;
|
|
@@ -684,7 +684,7 @@
|
|
|
684
684
|
const router = $data(el).$router;
|
|
685
685
|
|
|
686
686
|
if (!router && (value === "outlet" || value === "link")) {
|
|
687
|
-
warn(`
|
|
687
|
+
warn(`x-router:${value} is missing a parent x-router`);
|
|
688
688
|
return;
|
|
689
689
|
}
|
|
690
690
|
|
|
@@ -824,15 +824,15 @@
|
|
|
824
824
|
cleanup(unsubscribe);
|
|
825
825
|
}
|
|
826
826
|
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
827
|
+
//
|
|
828
|
+
// A warning about a non-existing anchor element is printed in the get_anchor_element function.
|
|
829
|
+
// warn("<a> element not found")
|
|
830
|
+
//
|
|
831
831
|
}
|
|
832
832
|
|
|
833
833
|
function process_outlet() {
|
|
834
834
|
if (router.outlet) {
|
|
835
|
-
warn("x-router:outlet already
|
|
835
|
+
warn("x-router:outlet is already present", router.outlet, el);
|
|
836
836
|
}
|
|
837
837
|
else {
|
|
838
838
|
router.outlet = el;
|
|
@@ -848,22 +848,22 @@
|
|
|
848
848
|
return false;
|
|
849
849
|
}
|
|
850
850
|
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
851
|
+
//
|
|
852
|
+
// Create a dependency on router.values
|
|
853
|
+
//
|
|
854
854
|
JSON.stringify(router.values);
|
|
855
855
|
|
|
856
856
|
const link = is_anchor_element(el) ? el : closest(el, node => node._r_routerlink)?._r_routerlink;
|
|
857
857
|
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
858
|
+
//
|
|
859
|
+
// The issue is that the router:link directive is processed later than x-bind,
|
|
860
|
+
// and if $active is used in x-bind, we won’t find node._r_routerlink.
|
|
861
|
+
// Therefore, we delay execution and try again.
|
|
862
|
+
//
|
|
863
|
+
// <div x-router:link :class="{ active: $active }">
|
|
864
|
+
// ...
|
|
865
|
+
// </div>
|
|
866
|
+
//
|
|
867
867
|
|
|
868
868
|
if (link) {
|
|
869
869
|
return router.history.resolve(link.href) === router.values.path;
|
|
@@ -875,9 +875,9 @@
|
|
|
875
875
|
else {
|
|
876
876
|
queueMicrotask(() => {
|
|
877
877
|
el._r_routerlink_init = true;
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
878
|
+
//
|
|
879
|
+
// Force an upate
|
|
880
|
+
//
|
|
881
881
|
router.values.path = router.values.path;
|
|
882
882
|
});
|
|
883
883
|
}
|
|
@@ -907,4 +907,4 @@
|
|
|
907
907
|
|
|
908
908
|
document.addEventListener("alpine:init", () => { Alpine.plugin(plugin); });
|
|
909
909
|
|
|
910
|
-
})();
|
|
910
|
+
})();
|
package/alpinegear-router.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(){"use strict";const e=(...e)=>console.warn("alpinegear.js:",...e),t=Array.isArray,n=e=>null==e,r=e=>e
|
|
1
|
+
!function(){"use strict";const e=(...e)=>console.warn("alpinegear.js:",...e),t=Array.isArray,n=e=>null==e,r=e=>e.matches("template"),a=e=>"function"==typeof e,o=e=>t(e)?e:[e],i=e=>a(e)&&"AsyncFunction"===e.constructor?.name?e:function(...t){const n=e.apply(this,t);return a(n?.then)?n:Promise.resolve(n)},l=(e,t,n,r)=>(e.addEventListener(t,n,r),()=>e.removeEventListener(t,n,r)),s=Object.freeze({regex(e){const t=new RegExp(e);return{test:e=>t.test(e)}},bool(){return{test:e=>/^(?:true|false)$/i.test(e),transform:e=>4===e.length}},int(){return{test:e=>/^-?\d+$/.test(e),transform:e=>+e}},number(){return{test:e=>/^[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?$/.test(e)&&isFinite(parseFloat(e)),transform:e=>parseFloat(e)}},alpha(){return{test:e=>/^[a-z]+$/i.test(e)}},min(e){return{test:t=>t>=+e}},max(e){return{test:t=>+e>=t}},range(e){let[t,n]=e.split(",",2).map(e=>e.trim());return{test:e=>e>=+t&&+n>=e}},length(e){let t=e.split(",").map(e=>e.trim());return{test:2==t.length?e=>e.length>=+t[0]&&+t[1]>=e.length:e=>e.length===+t[0]}},minlength(e){return{test:t=>t.length>=+e}},maxlength(e){return{test:t=>+e>=t.length}}});class u{#e;#t;#n;#r;#a;get template(){return this.#t}get regex(){return this.#e}get constraints(){return this.#a}constructor(e,t=null){this.#t=e,this.#e=function(e,t,r,a){t.push(...function(e,t){return function(e){e.find(e=>e.parts.length>1&&e.parts.every(e=>e.optional))&&u("Using all segment parameters as optional is not permitted");const r=new Map;return e.flatMap(e=>e.parts).forEach((e,a,o)=>{if("literal"!==e.kind||0>e.value.indexOf("?")||u("Literal segments cannot contain the '?' character"),"parameter"===e.kind){e.catch_all&&a!==o.length-1&&u("A catch-all parameter can only appear as the last segment"),r.has(e.name)&&u(`The route parameter name '${e.name}' appears more than one time`),"*"===e.quantifier&&n(e.default)&&(e.default=""),""===e.default&&"*"!==e.quantifier&&(e.default=null),r.set(e.name,!0);for(let r of e.constraints){const e=t?.[r.name]??s[r.name];n(e)&&u(`Unknown constraint '${r.name}'`),Object.assign(r,e(r.argument))}}}),e}(function(){const t=[];for(let n=0;e.length>n;){const e=r(n);e.template&&t.push(e),n+=e.template.length+1}return t}());function r(t){let n=[],r=t;for(;e.length>r&&"/"!==e[r];){const e=o(r)||a(r);n.push(e),r+=e.template.length}return{template:e.slice(t,r),parts:n}}function a(t){if("{"!==e[t])return null;const r=i(t),a=e.slice(t,t+r.length+2),o=function(e){const t=e.match(/^(?<name>[a-z_$][a-z0-9_$-]*?)(?:[:?+*]|$)/i)?.groups?.name;return n(t)&&u("Invalid parameter name"),t}(r),s=/[*+?]/.exec(r[o.length])?.[0]??"",c=function(e,t){const r=[];for(let a=t;e.length>a;){":"!==e[a]&&u();const t=l(e.slice(a+1));a+=t.length+1;const o="("===e[a]?i(a,e):null;n(o)||(a+=o.length+2),t||o||u(),r.push({name:"="===t?"default":t||"regex",argument:o??""})}return r}(r,o.length+s.length);return{name:o,kind:"parameter",template:a,quantifier:s,constraints:c.filter(e=>"default"!==e.name),default:c.find(e=>"default"===e.name)?.argument,required:"+"===s||""===s,optional:"?"===s||"*"===s,catch_all:"+"===s||"*"===s}}function o(t){for(let n=t;;n++)if(n>=e.length||"/"===e[n]||"{"===e[n]){if(n===t)return null;const r=e.slice(t,n);return{kind:"literal",template:r,value:r}}}function i(t,n){n??=e;const r=[];e:for(let e=t;n.length>e;e++){switch(n[e]){case"{":r.push("}");break;case"(":r.push(")");break;case"}":case")":if(r.pop()!==n[e])break e}if(0===r.length)return n.slice(t+1,e)}u()}function l(e){const t=e.match(/^(?<name>=|[a-z0-9_$]*)(?=[/:(]|$)/i)?.groups?.name;return n(t)&&u("Invalid constraint name"),t}function u(t="Invalid pattern"){throw new Error(`${t}: ${e}`)}}(e,a));let o=t.map(e=>e.parts.map((t,n)=>{if("literal"===t.kind)return n?t.value:`/${t.value}`;if(r.set(t.name,t),1===e.parts.length&&"?"===t.quantifier)return`(?:/(?<${t.name}>[^/]+?))?`;if(t.catch_all){let e=`(?<${t.name}>.${t.quantifier})`;return n||(e=`(?:/${e})`),"*"===t.quantifier&&(e+="?"),"*"===t.quantifier?e+"?":e}{const e=`(?<${t.name}>[^/]+?)${t.quantifier}`;return n?e:`/${e}`}}).join("")).join("")||"/";return"/"!==o&&(o+="/?"),new RegExp(`^${o}$`)}(e,this.#n=[],this.#r=new Map,this.#a=t??{})}match(e){let t=this.#e.exec(e);if(n(t))return null;t=t.groups??{};for(let[e,r]of this.#r.entries()){let a=t[e];if(n(a)&&n(r.default))continue;a||n(r.default)||(a=r.default);const o=r.catch_all?a.split("/").filter(e=>e.length):[a];for(let e=0;o.length>e;e++)for(let t of r.constraints){if(t.test&&!t.test(o[e]))return null;t.transform&&(o[e]=t.transform(o[e]))}t[e]=r.catch_all?o:o[0]}return t}resolve(e){e=new Map(Object.entries(e));const t=[];for(let r of this.#n){const a=[];for(let t of r.parts)if("literal"===t.kind)a.push(t.value);else{let r=e.get(t.name);if(e.delete(t.name),(n(r)||""===r)&&(r=this.#r.get(t.name)?.default,t.catch_all&&r&&(r=r.split("/"))),n(r)||""===r){if(t.required)return null;if(t.optional&&t.default===r)continue}t.catch_all?(r=o(r),a.push(...r.map(e=>encodeURIComponent(e)).join("/"))):a.push(encodeURIComponent(r))}a.length&&t.push(a.join(""))}let r=[...e.entries()].map(([e,t])=>encodeURIComponent(e)+"="+encodeURIComponent(t)).join("&");r&&(r="?"+r);const a=t.join("/")+r;return"/"!==a[0]?"/"+a:a}}function c({directive:t,$data:a}){t("route",(t,{expression:o,value:l},{cleanup:s,evaluate:c})=>{if(!r(t))return void e("x-route can only be used on a 'template' tag");const h=t._r_route;if(h||"view"!==l&&"handler"!==l)switch(l){case"view":h.view=()=>async function(t){let n;try{n=await fetch(t)}catch{}if(!n?.ok)return e(`Failed to load template from ${t}`),new DocumentFragment;const r=new DocumentFragment,a=(new DOMParser).parseFromString(await n.text(),"text/html");return r.append(...a.body.childNodes),r}(o),s(()=>{h.view=()=>new Promise(e=>e(new DocumentFragment))});break;case"handler":!function(){o||(o="[]"),o.startsWith("[")||(o=`[${o}]`);const e=c(o).map(i),r=a(t);h.handler=async t=>{for(let a of e){const e=await a.call(r,t);if(!n(e))return e}},s(()=>h.handler=null)}();break;default:!function(){const n=a(t)?.$router;if(n){const e=()=>new Promise(e=>e(t.content));t._r_route=Object.assign(new u(o),{el:t,view:e,handler:()=>Promise.resolve()}),n.routes.push(t._r_route),s(()=>n.routes=n.routes.filter(e=>e!==t._r_route))}else e("no x-router directive found")}()}else e("no x-route directive found")})}let h,f;function p(){for(let e in h)e in location&&(h[e]=location[e])}const m={get path(){return f.hash.slice(1)||"/"},get location(){return f},resolve(e){let t=new URL(e);return t.hash?t.hash.slice(1)||"/":t.pathname},navigate(e,t=!1){0>e.indexOf("#")&&(e="#"+e),g(e,t)}},d={get path(){return f.pathname},get location(){return f},resolve(e){return new URL(e).pathname},navigate(e,t=!1){g(e,t)}};function g(e,t){history[t?"replaceState":"pushState"]({},"",e),f.refresh()}const v={html5:d,hash:m};function w({$data:t,addScopeToNode:n,directive:a,magic:o,reactive:i}){a("router",(a,{modifiers:o,value:s},{cleanup:u})=>{s||(s="html5");const c=t(a).$router;if(c||"outlet"!==s&&"link"!==s)switch(s){case"outlet":c.outlet?e("x-router:outlet is already present",c.outlet,a):(c.outlet=a,u(()=>c.outlet=null));break;case"link":!function(){let t=function(t){if($(t))return t;const n=t.querySelectorAll("a");return 1!==n.length&&e(`Expected exactly one link, but found ${n.length}`),n[0]}(a);if(t){a._r_routerlink=t;const e=(t.getAttribute("target")??"").indexOf("_blank")>=0,n=l(t,"click",n=>{n.metaKey||n.altKey||n.ctrlKey||n.shiftKey||n.defaultPrevented||n.button>0||e||(n.preventDefault(),c.navigate(`${t.pathname}${t.search}${t.hash}`,(e=>e.includes("replace"))(o)))});u(n)}}();break;default:!function(){if(r(a))return void e("x-router cannot be used on a 'template' tag");const t=i({pattern:"",path:"",params:{}}),o=function(t){f??=(h||(h=Alpine.reactive({hash:"",host:"",hostname:"",href:"",origin:"",pathname:"",port:0,protocol:"",search:"",refresh(){p()}}),p(),l(window,"hashchange",p),l(window,"popstate",p)),h),t||="html5";let n=v[t];return n||(e(`Unknown history API: ${t}`),n=d),n}(s),c={routes:[],outlet:null,active:null,history:o,values:t,async match(e){for(let t of this.routes){const n=t.match(e);if(n){const r={router:c,route:t,params:n,path:e};if(!1!==await t.handler(r))return r}}},navigate(e,t=!1){return o.navigate(e,t),!0}};function m(){if(c.active){for(let e of c.active.nodes??[])e.remove();c.active.nodes=null,c.active=null}}n(a,{$route:t,$router:c});const g=function(e,t,n=null){const{effect:r,release:a}=Alpine;let o,i,l=!1;const s=r(()=>{o=e(),l||(n?.deep&&JSON.stringify(o),i=o),(l||(n?.immediate??1))&&setTimeout(()=>{t(o,i),i=o},0),l=!0});return()=>a(s)}(()=>o.path,async e=>{const n=await c.match(e);n?e===o.path&&function(e,n,a){if(e.nodes?.length&&t.path===n)return;m(),t.path=n,t.pattern=e.template,t.params=a??{},c.active=e;const o=c.outlet;o&&e.view().then(i=>{t.path===n&&t.pattern===e.template&&JSON.stringify(t.params)===JSON.stringify(a)&&(e.nodes=[...i.cloneNode(!0).childNodes],r(o)?e.nodes.forEach(e=>o.parentElement.insertBefore(e,o)):e.nodes.forEach(e=>o.append(e)))})}(n.route,n.path,n.params):m()});u(g),u(m)}()}else e(`x-router:${s} is missing a parent x-router`)}),o("active",n=>{const r=t(n).$router;if(!r)return e("No x-router directive found"),!1;JSON.stringify(r.values);const a=$(n)?n:((e,t)=>{for(;e&&!t(e);)e=(e._x_teleportBack??e).parentElement;return e})(n,e=>e._r_routerlink)?._r_routerlink;return a?r.history.resolve(a.href)===r.values.path:(n._r_routerlink_init?e("x-router:link directive not found",n):queueMicrotask(()=>{n._r_routerlink_init=!0,r.values.path=r.values.path}),!1)})}function $(e){return"A"===e.tagName.toUpperCase()}function _(e){window.RoutePattern=u,e.plugin([w,c])}document.addEventListener("alpine:init",()=>{Alpine.plugin(_)})}();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ramstack/alpinegear-router",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "@ramstack/alpinegear-router provides routing-related directives for Alpine.js, enabling client-side navigation and routing functionality.",
|
|
5
5
|
"author": "Rameel Burhan",
|
|
6
6
|
"license": "MIT",
|