surf-core 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/surf.min.js +2 -2
- package/package.json +1 -1
- package/src/signal.js +11 -0
package/dist/surf.min.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
var SurfModule=(()=>{var
|
|
1
|
+
var SurfModule=(()=>{var it=Object.defineProperty;var _t=Object.getOwnPropertyDescriptor;var kt=Object.getOwnPropertyNames;var Bt=Object.prototype.hasOwnProperty;var Dt=(t,e)=>()=>(t&&(e=t(t=0)),e);var y=(t,e)=>{for(var r in e)it(t,r,{get:e[r],enumerable:!0})},Ht=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of kt(e))!Bt.call(t,s)&&s!==r&&it(t,s,{get:()=>e[s],enumerable:!(n=_t(e,s))||n.enumerable});return t};var Ft=t=>Ht(it({},"__esModule",{value:!0}),t);var E={};y(E,{clearPreserved:()=>At,default:()=>Vt,findAll:()=>N,getCellId:()=>I,getState:()=>h,init:()=>z,initAll:()=>A,restore:()=>O,setProperty:()=>xt,setState:()=>x,snapshot:()=>J});function Ut(t){if(!t)return{};let e=t.trim();try{let r=e.startsWith("{")?`return ${e}`:`return { ${e} }`;return new Function(r)()}catch(r){return console.warn(`[Surf] Invalid seed expression: "${e}"`,r),{}}}function I(t){return t.getAttribute(jt)||t.id||null}function N(t=document){return t.querySelectorAll(`[${ut}]`)}function z(t){if(!t.hasAttribute(ut))return console.warn("[Surf] Element is not a cell:",t),{};let e=I(t);if(e&&P.has(e)){let s=P.get(e);return W.set(t,s),s}let r=t.getAttribute(ut),n=Ut(r||"{}");return W.set(t,n),e&&P.set(e,n),n}function h(t){return W.has(t)?W.get(t):z(t)}function x(t,e){let n={...h(t),...e};W.set(t,n);let s=I(t);return s&&P.set(s,n),n}function xt(t,e,r){return x(t,{[e]:r})}function J(t=document){let e=N(t),r=new Map;return e.forEach(n=>{let s=I(n);s&&r.set(s,{...h(n)})}),r}function O(t){t.forEach((e,r)=>{P.set(r,e)})}function A(t=document){N(t).forEach(r=>z(r))}function At(t){P.delete(t)}var ut,jt,W,P,Vt,_=Dt(()=>{ut="d-cell",jt="d-cell-id",W=new WeakMap,P=new Map;Vt={findAll:N,getCellId:I,init:z,getState:h,setState:x,setProperty:xt,snapshot:J,restore:O,initAll:A,clearPreserved:At}});var ne={};y(ne,{Cell:()=>E,Echo:()=>F,Patch:()=>H,Pulse:()=>j,Signal:()=>D,Surface:()=>R,default:()=>re});var R={};y(R,{append:()=>U,default:()=>Gt,findAll:()=>at,getById:()=>yt,getBySelector:()=>p,init:()=>X,prepend:()=>V,replace:()=>b});var ct="d-surface";function at(){return document.querySelectorAll(`[${ct}]`)}function yt(t){let e=t.startsWith("#")?t.slice(1):t,r=document.getElementById(e);return r&&r.hasAttribute(ct)?r:null}function p(t){let e=document.querySelector(t);return e&&e.hasAttribute(ct)?e:null}function b(t,e){let r;if(typeof t=="string"?r=p(t)||document.querySelector(t):r=t,!r)return console.warn(`[Surf] Surface not found: ${t}`),null;let n=document.createElement("template");for(n.innerHTML=e.trim(),r.innerHTML="";n.content.firstChild;)r.appendChild(n.content.firstChild);return r}function U(t,e){return bt(t,e,"beforeend")}function V(t,e){return bt(t,e,"afterbegin")}function bt(t,e,r){let n;if(typeof t=="string"?n=p(t)||document.querySelector(t):n=t,!n)return console.warn(`[Surf] Surface not found: ${t}`),null;let s=document.createElement("template");s.innerHTML=e.trim();let o=document.createDocumentFragment();for(;s.content.firstChild;)o.appendChild(s.content.firstChild);return r==="beforeend"?n.appendChild(o):n.insertBefore(o,n.firstChild),n}function X(){at().forEach(e=>{e.setAttribute("data-surf-ready","true")})}var Gt={findAll:at,getById:yt,getBySelector:p,replace:b,append:U,prepend:V,init:X};_();var D={};y(D,{cleanup:()=>Y,default:()=>Jt,initAll:()=>T,register:()=>B,updateBindings:()=>L});_();var ft="d-signal",Et="d-text",Tt="d-show",$t="d-attr",Pt={};function B(t,e){Pt[t]=e}var Q=new WeakMap;function K(t){return t.closest("[d-cell]")}function k(t,e){if(!t||!e)return;let r=t.trim();if(r in e)return e[r];if(r.startsWith("!")){let i=r.slice(1).trim();return!e[i]}let n=r.match(/^(\w+)\s*={2,3}\s*(.+)$/);if(n){let[,i,u]=n,c=e[i],l=u==="true"?!0:u==="false"?!1:u.startsWith('"')||u.startsWith("'")?u.slice(1,-1):Number(u);return c===l}let s=r.match(/^(\w+)\s*!=\s*(.+)$/);if(s){let[,i,u]=s,c=e[i],l=u==="true"?!0:u==="false"?!1:u.startsWith('"')||u.startsWith("'")?u.slice(1,-1):Number(u);return c!==l}let o=r.match(/^(\w+)\s*>\s*(\d+)$/);if(o)return e[o[1]]>Number(o[2]);let a=r.match(/^(\w+)\s*<\s*(\d+)$/);if(a)return e[a[1]]<Number(a[2])}function Nt(t,e,r,n){let s=t.trim(),o=s.match(/^(\w+)\.(\w+)\((.*)\)$/);if(o){let[,f,d,C]=o;if(f==="this")if(typeof n[d]=="function"){let wt=vt(C,e,r,n);return d==="reset"?setTimeout(()=>n[d](...wt),0):n[d](...wt),{}}else return console.warn(`[Surf] Element does not have method: ${d}`,n),{};let w=Pt[f];if(!w||typeof w[d]!="function")return console.warn(`[Surf] Unknown module method: ${f}.${d}`),{};let It=vt(C,e,r,n),St=w[d](...It);return typeof St=="object"?St:{}}if(s==="submit"){let f=n.tagName==="FORM"?n:n.closest("form");return f?f.requestSubmit?f.requestSubmit():f.submit():console.warn("[Surf] No form found to submit for element:",n),{}}if(s==="reset"){let f=n.tagName==="FORM"?n:n.closest("form");return f?setTimeout(()=>f.reset(),0):console.warn("[Surf] No form found to reset for element:",n),{}}let a=s.match(/^(\w+)\s*=\s*(.+)$/);if(!a)return{};let[,i,u]=a,c=u.trim();if(c===`!${i}`)return{[i]:!e[i]};if(c==="true")return{[i]:!0};if(c==="false")return{[i]:!1};let l=c.match(/^(\w+)\s*\+\s*(\d+)$/);if(l){let[,f,d]=l;return{[i]:(e[f]||0)+Number(d)}}let m=c.match(/^(\w+)\s*-\s*(\d+)$/);if(m){let[,f,d]=m;return{[i]:(e[f]||0)-Number(d)}}let g=c.match(/^Math\.max\((\w+)\s*-\s*(\d+),\s*(\d+)\)$/);if(g){let[,f,d,C]=g,w=(e[f]||0)-Number(d);return{[i]:Math.max(w,Number(C))}}let S=c.match(/^Math\.min\((\w+)\s*\+\s*(\d+),\s*(\d+)\)$/);if(S){let[,f,d,C]=S,w=(e[f]||0)+Number(d);return{[i]:Math.min(w,Number(C))}}return c.startsWith('"')||c.startsWith("'")?{[i]:c.slice(1,-1)}:/^\d+$/.test(c)?{[i]:Number(c)}:c in e?{[i]:e[c]}:{}}function vt(t,e,r,n){return t.trim()===""?[]:t.split(",").map(s=>{let o=s.trim();if(o!=="")return o==="true"?!0:o==="false"?!1:o==="event"?r:o==="this"?n:o.startsWith("'")||o.startsWith('"')?o.slice(1,-1):!isNaN(o)&&o!==""?Number(o):o.startsWith("this.")?Ct(n,o.slice(5)):Ct(e,o)}).filter(s=>s!==void 0&&s!=="")}function Ct(t,e){let r=e.split("."),n=t;for(let s of r){if(n==null)return;n=n[s]}return n}function L(t){let e=h(t);t.querySelectorAll(`[${Et}]`).forEach(o=>{if(K(o)!==t)return;let a=o.getAttribute(Et),i=k(a,e);i!==void 0&&(o.textContent=String(i))}),t.querySelectorAll(`[${Tt}]`).forEach(o=>{if(K(o)!==t)return;let a=o.getAttribute(Tt),i=k(a,e);o.style.display=i?"":"none"}),t.querySelectorAll(`[${$t}]`).forEach(o=>{if(K(o)!==t)return;let a=o.getAttribute($t),i=a.match(/^class\.([\w-]+):\s*(.+)$/);if(i){let[,g,S]=i;k(S.trim(),e)?o.classList.add(g):o.classList.remove(g);return}let u=a.match(/^(\w+):(.+)$/);if(!u)return;let[,c,l]=u,m=k(l.trim(),e);if(m!==void 0){if(typeof m!="boolean"){o.setAttribute(c,String(m));return}m?o.setAttribute(c,""):o.removeAttribute(c)}})}function Xt(t){let e=[],r="",n=0;for(let s=0;s<t.length;s++){let o=t[s];o==="{"?n++:o==="}"&&n--,o===";"&&n===0?(r.trim()&&e.push(r.trim()),r=""):r+=o}return r.trim()&&e.push(r.trim()),e}function zt(t){let e=t.getAttribute(ft);if(!e)return;let r=Xt(e),n=Q.get(t);n&&(Array.isArray(n)?n.forEach(({event:o,handler:a})=>{t.removeEventListener(o,a)}):t.removeEventListener(n.event,n.handler));let s=[];r.forEach(o=>{let a=o.match(/^([\w:-]+):\s*(.+)$/s);if(!a){console.warn(`[Surf] Invalid signal expression: ${o}`);return}let[,i,u]=a,c=K(t);if(!c){console.warn("[Surf] Signal element has no parent cell:",t);return}let l=m=>{let g=h(c),S=Nt(u,g,m,t);Object.keys(S).length>0&&(x(c,S),L(c))};t.addEventListener(i,l),s.push({event:i,handler:l})}),Q.set(t,s)}function T(t=document){t.querySelectorAll(`[${ft}]`).forEach(n=>zt(n)),N(t).forEach(n=>L(n))}function Y(t){t.querySelectorAll(`[${ft}]`).forEach(r=>{let n=Q.get(r);n&&(Array.isArray(n)?n.forEach(({event:s,handler:o})=>{r.removeEventListener(s,o)}):r.removeEventListener(n.event,n.handler),Q.delete(r))})}var Jt={updateBindings:L,initAll:T,cleanup:Y,evaluate:k,executeAssignment:Nt,register:B};var j={};y(j,{action:()=>ht,commit:()=>mt,default:()=>ee,go:()=>st,init:()=>ot,navigate:()=>nt,off:()=>rt,on:()=>et,refresh:()=>G,submit:()=>Rt});var H={};y(H,{create:()=>Lt,default:()=>Ot,isPatch:()=>Z,parse:()=>M});function M(t){let e=[],s=new DOMParser().parseFromString(t,"text/html").querySelector("d-patch");return s?(s.querySelectorAll("surface").forEach(a=>{let i=a.getAttribute("target");if(!i){console.warn("[Surf] Surface element missing target attribute");return}let u=a.querySelector("template");e.push({target:i,content:u?u.innerHTML:a.innerHTML})}),e):(console.warn("[Surf] No <d-patch> element found in response"),e)}function Z(t){return t.includes("<d-patch>")||t.includes("<d-patch ")}function Lt(t){return`<d-patch>
|
|
2
2
|
${t.map(r=>` <surface target="${r.target}">${r.content}</surface>`).join(`
|
|
3
3
|
`)}
|
|
4
|
-
</d-patch>`}var Ot={parse:M,isPatch:
|
|
4
|
+
</d-patch>`}var Ot={parse:M,isPatch:Z,create:Lt};var F={};y(F,{after:()=>dt,before:()=>lt,default:()=>Kt,withPreservation:()=>$});_();function lt(t){return Y(t),J(t)}function dt(t,e){O(e),A(t),T(t)}function $(t,e,r){let n=lt(t);r(),dt(t,n)}var Kt={before:lt,after:dt,withPreservation:$};var tt="d-pulse",qt="d-target",Qt="d-action",v={"before:pulse":[],"after:patch":[],"error:network":[]};function pt(t,e){v[t]&&v[t].forEach(r=>{try{r(e)}catch(n){console.error(`[Surf] Error in ${t} listener:`,n)}})}function et(t,e){v[t]&&v[t].push(e)}function rt(t,e){if(v[t]){let r=v[t].indexOf(e);r>-1&&v[t].splice(r,1)}}function Yt(t){t.forEach(({target:e,content:r})=>{let n=p(e)||document.querySelector(e);if(!n){console.warn(`[Surf] Target not found for patch: ${e}`);return}$(n,r,()=>{b(e,r)})})}async function q(t,e,r){pt("before:pulse",{url:t,options:e,target:r});try{let n=await fetch(t,{...e,headers:{Accept:"text/html","X-Surf-Request":"true",...e.headers}});if(!n.ok)throw new Error(`HTTP ${n.status}: ${n.statusText}`);let s=await n.text();if(Z(s)){let o=M(s);Yt(o)}else if(r){let o=p(r)||document.querySelector(r);if(o){let a=e.swap||o.getAttribute("d-swap")||"inner";$(o,s,()=>{a==="append"?U(o,s):a==="prepend"?V(o,s):b(o,s)})}}pt("after:patch",{url:t,target:r})}catch(n){console.error("[Surf] Pulse error:",n),pt("error:network",{url:t,error:n})}}async function nt(t,e,r={}){let n=e||"body";await q(t,{method:"GET",...r},n),n&&history.pushState({surf:!0,url:t,target:n},"",t)}async function mt(t,e){let r=t.method?.toUpperCase()||"POST",n=t.action||window.location.href,s=new FormData(t),o=t.getAttribute("d-swap"),a=o?{swap:o}:{},i=e||"body",u=new URLSearchParams;if(s.forEach((c,l)=>u.append(l,c)),r==="GET"){let c=n.includes("?")?"&":"?";n=n+c+u.toString(),await q(n,{method:"GET",...a},i)}else await q(n,{method:r,headers:{"Content-Type":"application/x-www-form-urlencoded"},body:u.toString(),...a},i)}async function G(t){let e=window.location.href,r=t||"body",s=(p(r)||document.querySelector(r))?.getAttribute("d-swap");await q(e,{method:"GET",swap:s},r)}async function ht(t,e={},r,n={}){let s=r||"body";await q(t,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e),...n},s)}async function Zt(t){let e=t.target.closest(`[${tt}]`);if(!e)return;let r=e.getAttribute(tt),n=e.getAttribute(qt),s=e.getAttribute(Qt),o=e.getAttribute("d-swap"),a=o?{swap:o}:{};if(e.tagName==="A"&&r==="navigate"){t.preventDefault();let i=e.href;nt(i,n,a);return}if(r==="refresh"){t.preventDefault(),G(n);return}if(r==="action"&&s){t.preventDefault();let i={};for(let c of e.attributes)if(c.name.startsWith("data-")&&c.name!=="data-surf-ready"){let l=c.name.slice(5);i[l]=c.value}let u=e.closest("[d-cell]");if(u){let c=await Promise.resolve().then(()=>(_(),E)),l=c.default?c.default.getState(u):c.getState(u);l&&Object.assign(i,l)}ht(s,i,n,a);return}}function te(t){let e=t.target;if(!e.hasAttribute(tt))return;let r=e.getAttribute(tt),n=e.getAttribute(qt);r==="commit"&&(t.preventDefault(),mt(e,n))}function Mt(t){t.state?.surf&&q(t.state.url,{method:"GET"},t.state.target)}function ot(){document.addEventListener("click",Zt),document.addEventListener("submit",te),window.addEventListener("popstate",Mt),window.addEventListener("popstate",Mt)}async function st(t,e={}){let r=e.target||"body";await nt(t,r,e)}function Rt(t){let e=t.tagName==="FORM"?t:t.closest("form");e?e.requestSubmit?e.requestSubmit():e.submit():console.warn("[Surf] No form found to submit for element:",t)}var ee={on:et,off:rt,navigate:nt,commit:mt,refresh:G,action:ht,go:st,submit:Rt,init:ot};var gt={version:"0.1.0",go(t,e={}){return st(t,e)},refresh(t){return G(t)},on(t,e){et(t,e)},off(t,e){rt(t,e)},getState(t){let e=typeof t=="string"?document.querySelector(t):t;return h(e)},setState(t,e){let r=typeof t=="string"?document.querySelector(t):t;x(r,e),L(r)},applyPatch(t){M(t).forEach(({target:r,content:n})=>{let s=p(r)||document.querySelector(r);s&&$(s,n,()=>{b(r,n),A(s),T(s)})})},register(t,e){B(t,e)},use(t,e={}){return t&&typeof t.install=="function"&&t.install(this,e),this},_modules:{Surface:R,Cell:E,Signal:D,Pulse:j,Patch:H,Echo:F}};function Wt(){X(),A(),T(),ot(),B("Pulse",j),console.log(`[Surf] Initialized v${gt.version}`)}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",Wt):Wt();var re=gt;typeof window<"u"&&(window.Surf=gt);return Ft(ne);})();
|
|
5
5
|
window.Surf=SurfModule.default
|
package/package.json
CHANGED
package/src/signal.js
CHANGED
|
@@ -303,12 +303,16 @@ function resolvePath(obj, path) {
|
|
|
303
303
|
* Update all reactive bindings in a cell
|
|
304
304
|
* @param {Element} cellElement
|
|
305
305
|
*/
|
|
306
|
+
|
|
306
307
|
export function updateBindings(cellElement) {
|
|
307
308
|
const state = Cell.getState(cellElement);
|
|
308
309
|
|
|
309
310
|
// Update d-text bindings
|
|
310
311
|
const textElements = cellElement.querySelectorAll(`[${TEXT_ATTR}]`);
|
|
311
312
|
textElements.forEach(el => {
|
|
313
|
+
// Only update if this element belongs to the current cell (not a nested cell)
|
|
314
|
+
if (findParentCell(el) !== cellElement) return;
|
|
315
|
+
|
|
312
316
|
const prop = el.getAttribute(TEXT_ATTR);
|
|
313
317
|
const value = evaluate(prop, state);
|
|
314
318
|
if (value !== undefined) {
|
|
@@ -319,6 +323,9 @@ export function updateBindings(cellElement) {
|
|
|
319
323
|
// Update d-show bindings
|
|
320
324
|
const showElements = cellElement.querySelectorAll(`[${SHOW_ATTR}]`);
|
|
321
325
|
showElements.forEach(el => {
|
|
326
|
+
// Only update if this element belongs to the current cell
|
|
327
|
+
if (findParentCell(el) !== cellElement) return;
|
|
328
|
+
|
|
322
329
|
const expr = el.getAttribute(SHOW_ATTR);
|
|
323
330
|
const visible = evaluate(expr, state);
|
|
324
331
|
el.style.display = visible ? '' : 'none';
|
|
@@ -328,6 +335,9 @@ export function updateBindings(cellElement) {
|
|
|
328
335
|
// Format: attr:expression or class.className:expression
|
|
329
336
|
const attrElements = cellElement.querySelectorAll(`[${ATTR_ATTR}]`);
|
|
330
337
|
attrElements.forEach(el => {
|
|
338
|
+
// Only update if this element belongs to the current cell
|
|
339
|
+
if (findParentCell(el) !== cellElement) return;
|
|
340
|
+
|
|
331
341
|
const attrExpr = el.getAttribute(ATTR_ATTR);
|
|
332
342
|
|
|
333
343
|
// Check for class.className: expression format
|
|
@@ -366,6 +376,7 @@ export function updateBindings(cellElement) {
|
|
|
366
376
|
});
|
|
367
377
|
}
|
|
368
378
|
|
|
379
|
+
|
|
369
380
|
/**
|
|
370
381
|
* Split signal expression string into individual signals,
|
|
371
382
|
* respecting code blocks { ... } where semicolons might appear.
|