plotleaf 0.4.1 → 0.5.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 CHANGED
@@ -20,6 +20,8 @@ Follow https://plotleaf-site.loueed.workers.dev/agent and give me a preview and
20
20
 
21
21
  ## Status
22
22
 
23
+ **0.5.0** adds reusable declarative compositions and agent-prepared, explicitly scoped subtotals that remain with their groups when sorting.
24
+
23
25
  **0.4.1** removes metric-value scrollbars; exceptionally long values wrap rather than clip.
24
26
 
25
27
  **0.4.0** adds scoped interactive explorations: dropdowns, segmented choices, toggles, literal text/number inputs and supported date ranges select complete agent-prepared views. Metrics, charts, funnels, tables and data alternatives update together, including offline HTML. Unsupported selections show an unavailable state; no analytics or arbitrary queries run in reports.
@@ -30,7 +32,7 @@ The initial MVP includes validation, live preview/reload, self-contained HTML ex
30
32
 
31
33
  **0.3.0** adds local PNG/JPEG image cells, static sparklines and a cumulative example report. Donut charts and prepared funnel/progress views are available since 0.2.0. Check your installed CLI version or schema before using newer components.
32
34
 
33
- Implemented components: responsive grids, metrics/comparisons, line/area/bar/donut charts, prepared funnel/progress stages, literal chart targets, sortable/formatted tables and callouts. Reports support light/dark system preference, native chart-data disclosures and responsive layouts. Scoped prepared-view controls are supported. Arbitrary row queries, maps, subtotals and reusable compositions remain planned increments.
35
+ Implemented components: responsive grids, metrics/comparisons, line/area/bar/donut charts, prepared funnel/progress stages, literal chart targets, sortable/formatted tables and callouts. Reports support light/dark system preference, native chart-data disclosures and responsive layouts. Scoped prepared-view controls, reusable compositions and prepared subtotals are supported. Arbitrary row queries and maps remain planned increments.
34
36
 
35
37
  ## Quick start
36
38
 
@@ -1 +1 @@
1
- (()=>{var u=(l)=>typeof l==="object"?`${l.start}/${l.end}`:`${typeof l}:${String(l)}`;var b=JSON.parse(document.getElementById("plotleaf-data")?.textContent??"{}");for(let l of b.explorations??[]){let s=function(){let t=new Map,e=!0;for(let n of l.inputs){let i=f(n.id),m=i[0],p;if(n.type==="select")p=n.options[Number(m.value)]?.value??"\x00";else if(n.type==="segmented")p=n.options[Number(i.find((r)=>r.checked)?.value??-1)]?.value??"\x00";else if(n.type==="toggle")p=m.checked;else if(n.type==="date-range")p={start:i.find((r)=>r.dataset.rangePart==="start").value,end:i.find((r)=>r.dataset.rangePart==="end").value};else p=n.type==="number"?m.value===""?NaN:Number(m.value):m.value;let y=u(p);t.set(n.id,y);let g=n.type==="toggle"||n.options.some((r)=>u(r.value)===y);for(let r of i)r.setAttribute("aria-invalid",String(!g));e&&=g}let o=e?l.views.find((n)=>l.inputs.every((i)=>t.get(i.id)===u(n.when[i.id]))):void 0;for(let n of a.querySelectorAll("[data-plotleaf-view]"))n.hidden=n.dataset.plotleafView!==o?.id;v.textContent=o?`Showing ${o.label} · Prepared view`:"No prepared view for these selections. Choose supported values or reset.",a.dispatchEvent(new Event("plotleaf:viewchange",{bubbles:!0}))},d=function(){for(let t of l.inputs)for(let e of f(t.id))if(t.type==="toggle")e.checked=t.default;else if(t.type==="date-range")e.value=t.default[e.dataset.rangePart];else if(t.type==="segmented")e.checked=u(t.options[Number(e.value)].value)===u(t.default);else if(t.type==="select")e.value=String(t.options.findIndex((o)=>u(o.value)===u(t.default)));else e.value=String(t.default);s()},a=document.getElementById(`${l.id}-title`)?.parentElement;if(!a)continue;let f=(t)=>[...a.querySelectorAll("[data-plotleaf-input]")].filter((e)=>e.dataset.plotleafInput===t),v=a.querySelector("[data-plotleaf-status]");for(let t of l.inputs)for(let e of f(t.id))e.disabled=!1,e.addEventListener("input",s),e.addEventListener("change",s);let c=a.querySelector("[data-plotleaf-reset]");c.disabled=!1,c.addEventListener("click",d),s()}var E=new Intl.Collator("en-GB",{numeric:!0,sensitivity:"base"});for(let l of document.querySelectorAll("table[data-plotleaf-table]")){let a=l.tBodies[0];if(!a)continue;let f=[...a.rows],v=-1,s=!1;for(let d of l.querySelectorAll("thead button[data-column]"))d.disabled=!1,d.addEventListener("click",()=>{let c=Number(d.dataset.column);s=v===c?!s:!1,v=c;let t=f.map((e,o)=>({row:e,index:o,value:JSON.parse(e.cells[c]?.dataset.raw??"null")}));t.sort((e,o)=>{if(e.value===null||o.value===null)return e.value===o.value?e.index-o.index:e.value===null?1:-1;let n=typeof e.value==="number"&&typeof o.value==="number"?e.value-o.value:E.compare(String(e.value),String(o.value));return(s?-n:n)||e.index-o.index}),a.replaceChildren(...t.map((e)=>e.row)),l.querySelectorAll("thead th[aria-sort]").forEach((e)=>{let o=e.contains(d);e.setAttribute("aria-sort",o?s?"descending":"ascending":"none");let n=e.querySelector(".sort-indicator");if(n)n.textContent=o?s?"↓":"↑":"↕"})})}})();
1
+ (()=>{var p=(l)=>typeof l==="object"?`${l.start}/${l.end}`:`${typeof l}:${String(l)}`;var b=JSON.parse(document.getElementById("plotleaf-data")?.textContent??"{}");for(let l of b.explorations??[]){let s=function(){let t=new Map,n=!0;for(let o of l.inputs){let e=m(o.id),a=e[0],i;if(o.type==="select")i=o.options[Number(a.value)]?.value??"\x00";else if(o.type==="segmented")i=o.options[Number(e.find((u)=>u.checked)?.value??-1)]?.value??"\x00";else if(o.type==="toggle")i=a.checked;else if(o.type==="date-range")i={start:e.find((u)=>u.dataset.rangePart==="start").value,end:e.find((u)=>u.dataset.rangePart==="end").value};else i=o.type==="number"?a.value===""?NaN:Number(a.value):a.value;let g=p(i);t.set(o.id,g);let y=o.type==="toggle"||o.options.some((u)=>p(u.value)===g);for(let u of e)u.setAttribute("aria-invalid",String(!y));n&&=y}let c=n?l.views.find((o)=>l.inputs.every((e)=>t.get(e.id)===p(o.when[e.id]))):void 0;for(let o of r.querySelectorAll("[data-plotleaf-view]"))o.hidden=o.dataset.plotleafView!==c?.id;f.textContent=c?`Showing ${c.label} · Prepared view`:"No prepared view for these selections. Choose supported values or reset.",r.dispatchEvent(new Event("plotleaf:viewchange",{bubbles:!0}))},v=function(){for(let t of l.inputs)for(let n of m(t.id))if(t.type==="toggle")n.checked=t.default;else if(t.type==="date-range")n.value=t.default[n.dataset.rangePart];else if(t.type==="segmented")n.checked=p(t.options[Number(n.value)].value)===p(t.default);else if(t.type==="select")n.value=String(t.options.findIndex((c)=>p(c.value)===p(t.default)));else n.value=String(t.default);s()},r=document.getElementById(`${l.id}-title`)?.parentElement;if(!r)continue;let m=(t)=>[...r.querySelectorAll("[data-plotleaf-input]")].filter((n)=>n.dataset.plotleafInput===t),f=r.querySelector("[data-plotleaf-status]");for(let t of l.inputs)for(let n of m(t.id))n.disabled=!1,n.addEventListener("input",s),n.addEventListener("change",s);let d=r.querySelector("[data-plotleaf-reset]");d.disabled=!1,d.addEventListener("click",v),s()}var h=new Intl.Collator("en-GB",{numeric:!0,sensitivity:"base"});for(let l of document.querySelectorAll("table[data-plotleaf-table]")){let r=[...l.tBodies].map((s)=>({body:s,original:[...s.rows]}));if(!r.length)continue;let m=-1,f=!1;for(let s of l.querySelectorAll("thead button[data-column]"))s.disabled=!1,s.addEventListener("click",()=>{let v=Number(s.dataset.column);f=m===v?!f:!1,m=v;for(let{body:d,original:t}of r){let n=t.filter((e)=>e.hasAttribute("data-plotleaf-group-header")),c=t.filter((e)=>e.hasAttribute("data-plotleaf-subtotal")),o=t.filter((e)=>!n.includes(e)&&!c.includes(e)).map((e,a)=>({row:e,index:a,value:JSON.parse(e.cells[v]?.dataset.raw??"null")}));o.sort((e,a)=>{if(e.value===null||a.value===null)return e.value===a.value?e.index-a.index:e.value===null?1:-1;let i=typeof e.value==="number"&&typeof a.value==="number"?e.value-a.value:h.compare(String(e.value),String(a.value));return(f?-i:i)||e.index-a.index}),d.replaceChildren(...n,...o.map((e)=>e.row),...c)}l.querySelectorAll("thead th[aria-sort]").forEach((d)=>{let t=d.contains(s);d.setAttribute("aria-sort",t?f?"descending":"ascending":"none");let n=d.querySelector(".sort-indicator");if(n)n.textContent=t?f?"↓":"↑":"↕"})})}})();
@@ -1,4 +1,4 @@
1
- (()=>{var rD=Object.defineProperty;var iD=(t)=>t;function nD(t,e){this[t]=iD.bind(null,e)}var aD=(t,e)=>{for(var r in e)rD(t,r,{get:e[r],enumerable:!0,configurable:!0,set:nD.bind(e,r)})};var ft={};aD(ft,{Arc:()=>Eo,BezierCurve:()=>Ao,BoundingRect:()=>ae,Circle:()=>wo,CompoundPath:()=>rl,Ellipse:()=>Cf,Group:()=>we,HOVER_LAYER_FOR_INCREMENTAL:()=>pa,HOVER_LAYER_FROM_THRESHOLD:()=>od,HOVER_LAYER_NO:()=>ad,Image:()=>_t,IncrementalDisplayable:()=>ed,Line:()=>Ht,LinearGradient:()=>Do,OrientedBoundingRect:()=>Nf,Path:()=>ie,Point:()=>fe,Polygon:()=>Mf,Polyline:()=>cn,RadialGradient:()=>Qv,Rect:()=>De,Ring:()=>Ef,Sector:()=>dr,Text:()=>$e,WH:()=>hn,XY:()=>ai,applyTransform:()=>Bf,calcZ2Range:()=>FL,clipPointsByRect:()=>sS,clipRectByRect:()=>lS,createIcon:()=>zf,decomposeTransform:()=>HL,ensureCopyRect:()=>Po,ensureCopyTransform:()=>Vf,expandOrShrinkRect:()=>Lo,extendPath:()=>rS,extendShape:()=>tS,getCurrentCanvasPainter:()=>GL,getShapeClass:()=>iS,getTransform:()=>oS,groupTransition:()=>ld,initProps:()=>Qe,isBoundingRectAxisAligned:()=>Ff,isElementRemoved:()=>ca,lineLineIntersect:()=>uS,linePolygonIntersect:()=>zL,makeImage:()=>kf,makePath:()=>nl,mergePath:()=>aS,payloadDisableAnimation:()=>VL,registerShape:()=>mr,removeElement:()=>Mo,removeElementWithFadeOut:()=>pn,resizePath:()=>sd,retrieveZInfo:()=>al,setTooltipConfig:()=>Uf,subPixelOptimize:()=>RL,subPixelOptimizeLine:()=>ha,subPixelOptimizeRect:()=>NL,transformDirection:()=>kL,traverseElements:()=>Ci,traverseUpdateZ:()=>ol,updateProps:()=>Ve});var zi=(t)=>typeof t==="object"?`${t.start}/${t.end}`:`${typeof t}:${String(t)}`;var oD=JSON.parse(document.getElementById("plotleaf-data")?.textContent??"{}");for(let t of oD.explorations??[]){let n=function(){let s=new Map,l=!0;for(let f of t.inputs){let c=r(f.id),p=c[0],h;if(f.type==="select")h=f.options[Number(p.value)]?.value??"\x00";else if(f.type==="segmented")h=f.options[Number(c.find((m)=>m.checked)?.value??-1)]?.value??"\x00";else if(f.type==="toggle")h=p.checked;else if(f.type==="date-range")h={start:c.find((m)=>m.dataset.rangePart==="start").value,end:c.find((m)=>m.dataset.rangePart==="end").value};else h=f.type==="number"?p.value===""?NaN:Number(p.value):p.value;let v=zi(h);s.set(f.id,v);let d=f.type==="toggle"||f.options.some((m)=>zi(m.value)===v);for(let m of c)m.setAttribute("aria-invalid",String(!d));l&&=d}let u=l?t.views.find((f)=>t.inputs.every((c)=>s.get(c.id)===zi(f.when[c.id]))):void 0;for(let f of e.querySelectorAll("[data-plotleaf-view]"))f.hidden=f.dataset.plotleafView!==u?.id;i.textContent=u?`Showing ${u.label} · Prepared view`:"No prepared view for these selections. Choose supported values or reset.",e.dispatchEvent(new Event("plotleaf:viewchange",{bubbles:!0}))},a=function(){for(let s of t.inputs)for(let l of r(s.id))if(s.type==="toggle")l.checked=s.default;else if(s.type==="date-range")l.value=s.default[l.dataset.rangePart];else if(s.type==="segmented")l.checked=zi(s.options[Number(l.value)].value)===zi(s.default);else if(s.type==="select")l.value=String(s.options.findIndex((u)=>zi(u.value)===zi(s.default)));else l.value=String(s.default);n()},e=document.getElementById(`${t.id}-title`)?.parentElement;if(!e)continue;let r=(s)=>[...e.querySelectorAll("[data-plotleaf-input]")].filter((l)=>l.dataset.plotleafInput===s),i=e.querySelector("[data-plotleaf-status]");for(let s of t.inputs)for(let l of r(s.id))l.disabled=!1,l.addEventListener("input",n),l.addEventListener("change",n);let o=e.querySelector("[data-plotleaf-reset]");o.disabled=!1,o.addEventListener("click",a),n()}var sD=new Intl.Collator("en-GB",{numeric:!0,sensitivity:"base"});for(let t of document.querySelectorAll("table[data-plotleaf-table]")){let e=t.tBodies[0];if(!e)continue;let r=[...e.rows],i=-1,n=!1;for(let a of t.querySelectorAll("thead button[data-column]"))a.disabled=!1,a.addEventListener("click",()=>{let o=Number(a.dataset.column);n=i===o?!n:!1,i=o;let s=r.map((l,u)=>({row:l,index:u,value:JSON.parse(l.cells[o]?.dataset.raw??"null")}));s.sort((l,u)=>{if(l.value===null||u.value===null)return l.value===u.value?l.index-u.index:l.value===null?1:-1;let f=typeof l.value==="number"&&typeof u.value==="number"?l.value-u.value:sD.compare(String(l.value),String(u.value));return(n?-f:f)||l.index-u.index}),e.replaceChildren(...s.map((l)=>l.row)),t.querySelectorAll("thead th[aria-sort]").forEach((l)=>{let u=l.contains(a);l.setAttribute("aria-sort",u?n?"descending":"ascending":"none");let f=l.querySelector(".sort-indicator");if(f)f.textContent=u?n?"↓":"↑":"↕"})})}/*! *****************************************************************************
1
+ (()=>{var rD=Object.defineProperty;var iD=(t)=>t;function nD(t,e){this[t]=iD.bind(null,e)}var aD=(t,e)=>{for(var r in e)rD(t,r,{get:e[r],enumerable:!0,configurable:!0,set:nD.bind(e,r)})};var ft={};aD(ft,{Arc:()=>Eo,BezierCurve:()=>Ao,BoundingRect:()=>ae,Circle:()=>wo,CompoundPath:()=>rl,Ellipse:()=>Cf,Group:()=>we,HOVER_LAYER_FOR_INCREMENTAL:()=>pa,HOVER_LAYER_FROM_THRESHOLD:()=>od,HOVER_LAYER_NO:()=>ad,Image:()=>_t,IncrementalDisplayable:()=>ed,Line:()=>Ht,LinearGradient:()=>Do,OrientedBoundingRect:()=>Nf,Path:()=>ie,Point:()=>fe,Polygon:()=>Mf,Polyline:()=>cn,RadialGradient:()=>Qv,Rect:()=>De,Ring:()=>Ef,Sector:()=>dr,Text:()=>$e,WH:()=>hn,XY:()=>ai,applyTransform:()=>Bf,calcZ2Range:()=>FL,clipPointsByRect:()=>sS,clipRectByRect:()=>lS,createIcon:()=>zf,decomposeTransform:()=>HL,ensureCopyRect:()=>Po,ensureCopyTransform:()=>Vf,expandOrShrinkRect:()=>Lo,extendPath:()=>rS,extendShape:()=>tS,getCurrentCanvasPainter:()=>GL,getShapeClass:()=>iS,getTransform:()=>oS,groupTransition:()=>ld,initProps:()=>Qe,isBoundingRectAxisAligned:()=>Ff,isElementRemoved:()=>ca,lineLineIntersect:()=>uS,linePolygonIntersect:()=>zL,makeImage:()=>kf,makePath:()=>nl,mergePath:()=>aS,payloadDisableAnimation:()=>VL,registerShape:()=>mr,removeElement:()=>Mo,removeElementWithFadeOut:()=>pn,resizePath:()=>sd,retrieveZInfo:()=>al,setTooltipConfig:()=>Uf,subPixelOptimize:()=>RL,subPixelOptimizeLine:()=>ha,subPixelOptimizeRect:()=>NL,transformDirection:()=>kL,traverseElements:()=>Ci,traverseUpdateZ:()=>ol,updateProps:()=>Ve});var zi=(t)=>typeof t==="object"?`${t.start}/${t.end}`:`${typeof t}:${String(t)}`;var oD=JSON.parse(document.getElementById("plotleaf-data")?.textContent??"{}");for(let t of oD.explorations??[]){let n=function(){let s=new Map,l=!0;for(let f of t.inputs){let c=r(f.id),p=c[0],h;if(f.type==="select")h=f.options[Number(p.value)]?.value??"\x00";else if(f.type==="segmented")h=f.options[Number(c.find((m)=>m.checked)?.value??-1)]?.value??"\x00";else if(f.type==="toggle")h=p.checked;else if(f.type==="date-range")h={start:c.find((m)=>m.dataset.rangePart==="start").value,end:c.find((m)=>m.dataset.rangePart==="end").value};else h=f.type==="number"?p.value===""?NaN:Number(p.value):p.value;let v=zi(h);s.set(f.id,v);let d=f.type==="toggle"||f.options.some((m)=>zi(m.value)===v);for(let m of c)m.setAttribute("aria-invalid",String(!d));l&&=d}let u=l?t.views.find((f)=>t.inputs.every((c)=>s.get(c.id)===zi(f.when[c.id]))):void 0;for(let f of e.querySelectorAll("[data-plotleaf-view]"))f.hidden=f.dataset.plotleafView!==u?.id;i.textContent=u?`Showing ${u.label} · Prepared view`:"No prepared view for these selections. Choose supported values or reset.",e.dispatchEvent(new Event("plotleaf:viewchange",{bubbles:!0}))},a=function(){for(let s of t.inputs)for(let l of r(s.id))if(s.type==="toggle")l.checked=s.default;else if(s.type==="date-range")l.value=s.default[l.dataset.rangePart];else if(s.type==="segmented")l.checked=zi(s.options[Number(l.value)].value)===zi(s.default);else if(s.type==="select")l.value=String(s.options.findIndex((u)=>zi(u.value)===zi(s.default)));else l.value=String(s.default);n()},e=document.getElementById(`${t.id}-title`)?.parentElement;if(!e)continue;let r=(s)=>[...e.querySelectorAll("[data-plotleaf-input]")].filter((l)=>l.dataset.plotleafInput===s),i=e.querySelector("[data-plotleaf-status]");for(let s of t.inputs)for(let l of r(s.id))l.disabled=!1,l.addEventListener("input",n),l.addEventListener("change",n);let o=e.querySelector("[data-plotleaf-reset]");o.disabled=!1,o.addEventListener("click",a),n()}var sD=new Intl.Collator("en-GB",{numeric:!0,sensitivity:"base"});for(let t of document.querySelectorAll("table[data-plotleaf-table]")){let e=[...t.tBodies].map((n)=>({body:n,original:[...n.rows]}));if(!e.length)continue;let r=-1,i=!1;for(let n of t.querySelectorAll("thead button[data-column]"))n.disabled=!1,n.addEventListener("click",()=>{let a=Number(n.dataset.column);i=r===a?!i:!1,r=a;for(let{body:o,original:s}of e){let l=s.filter((c)=>c.hasAttribute("data-plotleaf-group-header")),u=s.filter((c)=>c.hasAttribute("data-plotleaf-subtotal")),f=s.filter((c)=>!l.includes(c)&&!u.includes(c)).map((c,p)=>({row:c,index:p,value:JSON.parse(c.cells[a]?.dataset.raw??"null")}));f.sort((c,p)=>{if(c.value===null||p.value===null)return c.value===p.value?c.index-p.index:c.value===null?1:-1;let h=typeof c.value==="number"&&typeof p.value==="number"?c.value-p.value:sD.compare(String(c.value),String(p.value));return(i?-h:h)||c.index-p.index}),o.replaceChildren(...l,...f.map((c)=>c.row),...u)}t.querySelectorAll("thead th[aria-sort]").forEach((o)=>{let s=o.contains(n);o.setAttribute("aria-sort",s?i?"descending":"ascending":"none");let l=o.querySelector(".sort-indicator");if(l)l.textContent=s?i?"↓":"↑":"↕"})})}/*! *****************************************************************************
2
2
  Copyright (c) Microsoft Corporation.
3
3
 
4
4
  Permission to use, copy, modify, and/or distribute this software for any
@@ -443,6 +443,20 @@ caption {
443
443
  text-align: start;
444
444
  padding: 0 0 20px;
445
445
  }
446
+ .table-scope {
447
+ display: block;
448
+ color: var(--muted);
449
+ font-size: 14px;
450
+ font-weight: 400;
451
+ }
452
+ .table-group th {
453
+ color: var(--muted);
454
+ font-size: 14px;
455
+ padding-block: 18px 7px;
456
+ }
457
+ .table-subtotal td {
458
+ font-weight: 550;
459
+ }
446
460
  thead {
447
461
  color: var(--muted);
448
462
  }