@chartbuddy.io/embed 1.7.52

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.
@@ -0,0 +1,135 @@
1
+ /**
2
+ * @chartbuddy.io/embed — ChartBuddy Insights (NOT Chart.js / Recharts).
3
+ * This file is the multi-file loader (needs sibling engine assets).
4
+ * Default is view-only (hover ChartBuddy ball: Download / Drag to slide /
5
+ * Export / Edit). Pass editable: true for the full editor. Ball → Done exits.
6
+ *
7
+ * Exports:
8
+ * new Insight(target, options?) → Insight
9
+ * getInsights() / snapshotInsights({ png? })
10
+ * clearPersistedChart(instanceId?)
11
+ * version: string
12
+ * Agent hook: window.__CHARTBUDDY_INSIGHTS__ (keyed by instanceId)
13
+ *
14
+ * Minimal example (view mode, data-in, no account / chart ID):
15
+ * import { Insight } from 'https://unpkg.com/@chartbuddy.io/embed';
16
+ * const insight = new Insight('#chart', {
17
+ * instanceId: 'revenue',
18
+ * chartData: {
19
+ * chartType: 'clusteredBar',
20
+ * isDataTransposed: true,
21
+ * seriesData: [['','Q1','Q2'],['Revenue',100,112],['Costs',60,66]],
22
+ * },
23
+ * });
24
+ * await insight.ready;
25
+ * // Agent observe: await insight.toPngBase64() // default bg #ffffff
26
+ * // or toPngBase64({ background: '#0f172a' }) / getChartData()
27
+ * // Full editor: new Insight('#chart', { editable: true, chartData: … })
28
+ * // Leave edit: insight.exitEditMode() or ball → Done
29
+ *
30
+ * Docs (fetch next if needed):
31
+ * https://unpkg.com/@chartbuddy.io/embed/llms.txt
32
+ * https://cb-acc.xyz/llms.txt
33
+ * https://cb-acc.xyz/embed/api
34
+ * https://unpkg.com/@chartbuddy.io/embed/README.md
35
+ */
36
+
37
+ var ChartBuddyEmbed=(()=>{var H=Object.defineProperty;var ge=Object.getOwnPropertyDescriptor;var ye=Object.getOwnPropertyNames;var be=Object.prototype.hasOwnProperty;var fe=(e,t)=>{for(var r in t)H(e,r,{get:t[r],enumerable:!0})},xe=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of ye(t))!be.call(e,i)&&i!==r&&H(e,i,{get:()=>t[i],enumerable:!(n=ge(t,i))||n.enumerable});return e};var ve=e=>xe(H({},"__esModule",{value:!0}),e);var ut={};fe(ut,{CHARTBUDDY_INSIGHTS_GLOBAL:()=>z,ChartDataValidationError:()=>y,Insight:()=>he,assertValidChartData:()=>E,clearPersistedChart:()=>q,default:()=>ct,formatValidationIssues:()=>C,getInsights:()=>I,snapshotInsights:()=>Y,validateChartData:()=>b,version:()=>S});var Ce=`<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 96 96" aria-hidden="true">
38
+ <circle cx="48" cy="48" r="46" fill="#f8fafc"/>
39
+ <rect x="60" y="22" width="12" height="53" fill="#5ce1e6" rx="6"/>
40
+ <rect x="42" y="48" width="12" height="27" fill="#ff5757" rx="6"/>
41
+ <rect x="23" y="30" width="12" height="45" fill="#ffbd59" rx="6"/>
42
+ </svg>`,K="cb-embed-chrome-styles";function Ee(){if(typeof document>"u"||document.getElementById(K))return;let e=document.createElement("style");e.id=K,e.textContent=`
43
+ .cb-embed-chrome-root {
44
+ position: absolute;
45
+ inset: 0;
46
+ pointer-events: none;
47
+ z-index: 20;
48
+ }
49
+ .cb-embed-ball {
50
+ position: absolute;
51
+ top: 10px;
52
+ left: 10px;
53
+ display: none;
54
+ align-items: center;
55
+ justify-content: center;
56
+ width: 40px;
57
+ height: 40px;
58
+ padding: 1px;
59
+ border: 1px solid rgba(255, 255, 255, 0.45);
60
+ border-radius: 50%;
61
+ background-color: rgba(15, 23, 42, 0.55);
62
+ box-shadow: 0 6px 18px rgba(0, 0, 0, 0.40);
63
+ backdrop-filter: blur(12px) saturate(1.15);
64
+ -webkit-backdrop-filter: blur(12px) saturate(1.15);
65
+ cursor: pointer;
66
+ pointer-events: auto;
67
+ transition: background-color 0.15s ease, box-shadow 0.15s ease;
68
+ box-sizing: border-box;
69
+ }
70
+ .cb-embed-chrome-root.is-visible .cb-embed-ball,
71
+ .cb-embed-chrome-root.is-menu-open .cb-embed-ball {
72
+ display: flex;
73
+ }
74
+ .cb-embed-ball:hover,
75
+ .cb-embed-ball:focus-visible {
76
+ background-color: rgba(15, 23, 42, 0.74);
77
+ outline: none;
78
+ }
79
+ .cb-embed-ball svg {
80
+ display: block;
81
+ width: 32px;
82
+ height: 32px;
83
+ }
84
+ .cb-embed-menu {
85
+ position: absolute;
86
+ top: 56px;
87
+ left: 10px;
88
+ min-width: 168px;
89
+ padding: 6px;
90
+ border-radius: 12px;
91
+ border: 1px solid rgba(255, 255, 255, 0.14);
92
+ background: rgba(15, 23, 42, 0.92);
93
+ box-shadow: 0 12px 32px rgba(0, 0, 0, 0.45);
94
+ backdrop-filter: blur(16px) saturate(1.2);
95
+ -webkit-backdrop-filter: blur(16px) saturate(1.2);
96
+ display: none;
97
+ flex-direction: column;
98
+ gap: 2px;
99
+ pointer-events: auto;
100
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
101
+ }
102
+ .cb-embed-chrome-root.is-menu-open .cb-embed-menu {
103
+ display: flex;
104
+ }
105
+ .cb-embed-menu-item {
106
+ appearance: none;
107
+ border: 0;
108
+ background: transparent;
109
+ color: #f8fafc;
110
+ text-align: left;
111
+ font-size: 13px;
112
+ font-weight: 560;
113
+ line-height: 1.2;
114
+ padding: 10px 12px;
115
+ border-radius: 8px;
116
+ cursor: pointer;
117
+ }
118
+ .cb-embed-menu-item:hover,
119
+ .cb-embed-menu-item:focus-visible {
120
+ background: rgba(255, 255, 255, 0.10);
121
+ outline: none;
122
+ }
123
+ `,document.head.appendChild(e)}function we(e){let t=`
124
+ <button type="button" class="cb-embed-menu-item" data-action="download" role="menuitem">Download</button>
125
+ <button type="button" class="cb-embed-menu-item" data-action="dragExport" role="menuitem">Drag to slide</button>
126
+ `;return e==="edit"?`${t}
127
+ <button type="button" class="cb-embed-menu-item" data-action="done" role="menuitem">Done</button>`:`${t}
128
+ <button type="button" class="cb-embed-menu-item" data-action="edit" role="menuitem">Edit</button>`}var A=class{constructor(t,r,n="view"){this.hideTimer=null;this.destroyed=!1;Ee(),this.host=t,getComputedStyle(t).position==="static"&&(t.style.position="relative"),this.root=document.createElement("div"),this.root.className="cb-embed-chrome-root",this.root.setAttribute("data-cb-embed-chrome","1"),this.root.setAttribute("data-cb-embed-chrome-mode",n),this.ball=document.createElement("button"),this.ball.type="button",this.ball.className="cb-embed-ball",this.ball.setAttribute("aria-label","ChartBuddy actions"),this.ball.setAttribute("aria-haspopup","menu"),this.ball.setAttribute("aria-expanded","false"),this.ball.innerHTML=Ce,this.menu=document.createElement("div"),this.menu.className="cb-embed-menu",this.menu.setAttribute("role","menu"),this.menu.innerHTML=we(n),this.root.appendChild(this.ball),this.root.appendChild(this.menu),t.appendChild(this.root),this.ball.addEventListener("click",i=>{i.stopPropagation(),this.toggleMenu()}),this.menu.addEventListener("click",i=>{let a=i.target?.closest?.("[data-action]");if(!a)return;i.stopPropagation();let s=a.getAttribute("data-action");this.closeMenu(),this.dispatch(s,r)}),this.onHostEnter=()=>{this.destroyed||(this.clearHideTimer(),this.root.classList.add("is-visible"))},this.onHostLeave=()=>{this.destroyed||this.scheduleHide()},this.onDocPointer=i=>{if(this.destroyed||!this.root.classList.contains("is-menu-open"))return;let a=i.target;a&&this.root.contains(a)||this.closeMenu()},this.onKeyDown=i=>{i.key==="Escape"&&this.closeMenu()},t.addEventListener("pointerenter",this.onHostEnter),t.addEventListener("pointerleave",this.onHostLeave),document.addEventListener("pointerdown",this.onDocPointer,!0),document.addEventListener("keydown",this.onKeyDown)}async dispatch(t,r){try{t==="download"?await r.onDownload():t==="dragExport"?await r.onDragExport():t==="edit"?await r.onEdit?.():t==="done"&&await r.onDone?.()}catch(n){console.error("[chartbuddy/embed] chrome action failed:",n)}}toggleMenu(){this.root.classList.contains("is-menu-open")?this.closeMenu():this.openMenu()}openMenu(){this.clearHideTimer(),this.root.classList.add("is-visible","is-menu-open"),this.ball.setAttribute("aria-expanded","true")}closeMenu(){this.root.classList.remove("is-menu-open"),this.ball.setAttribute("aria-expanded","false")}scheduleHide(){this.clearHideTimer(),this.hideTimer=setTimeout(()=>{this.root.classList.contains("is-menu-open")||this.root.classList.remove("is-visible")},80)}clearHideTimer(){this.hideTimer&&(clearTimeout(this.hideTimer),this.hideTimer=null)}destroy(){this.destroyed||(this.destroyed=!0,this.clearHideTimer(),this.host.removeEventListener("pointerenter",this.onHostEnter),this.host.removeEventListener("pointerleave",this.onHostLeave),document.removeEventListener("pointerdown",this.onDocPointer,!0),document.removeEventListener("keydown",this.onKeyDown),this.root.remove())}};var x={vertical:{domain:"bottom",primaryRange:"left",secondaryRange:"right"},horizontal:{domain:"left",primaryRange:"bottom",secondaryRange:"top"}};function ke(e,t="vertical"){if(!e||typeof e!="object")return!1;let r=x[t]||x.vertical;return e[r.domain]?.id==="domain"&&e[r.primaryRange]?.id==="primaryRange"}function Ie(e,t="vertical"){let r=x[t]||x.vertical,n=o=>o==="left"?-90:o==="right"?90:0,i={},a=null;for(let o of["left","right","top","bottom"]){let l=e?.[o];if(!l)continue;let m=JSON.parse(JSON.stringify(l));l.id==="domain"||l.id==="primaryRange"||l.id==="secondaryRange"?i[l.id]=m:a=m}let s={},d=(o,l)=>{if(o){if(o.position=l,o.axisTitle){if(o.axisTitle.id){let m=String(o.axisTitle.id).split("-");m.length>=2&&(m[m.length-2]=l,o.axisTitle.id=m.join("-"))}o.axisTitle.rotation=n(l)}o.id==="domain"&&o.labels&&typeof o.labels=="object"&&(o.labels.position=l),s[l]=o}};d(i.domain,r.domain),d(i.primaryRange,r.primaryRange),d(i.secondaryRange,r.secondaryRange);for(let o of["left","right","top","bottom"])if(!s[o]){let l=a?JSON.parse(JSON.stringify(a)):{id:"unused",enabled:!1,visible:!1,scaleType:"band",labels:{visible:!1},axisTitle:{id:`multiline-${o}-title`,text:"",visible:!1}};d(l,o)}return s}function W(e){if(!e||typeof e!="object")return e;let t=e.orientation==="horizontal"?"horizontal":"vertical";return e.orientation=t,!e.axes||ke(e.axes,t)||(e.axes=Ie(e.axes,t)),e}var S="1.7.52";var h={clusteredBar:{label:"Clustered Bar",description:"Side-by-side bars comparing series within each category.",optionBag:"bar",family:"bar",seriesLayout:"seriesRows",minRows:2,minCols:2,status:"stable",docsSlug:"clustered-bar"},stackedBar:{label:"Stacked Bar",description:"Bars stacked to show composition and category totals.",optionBag:"bar",family:"bar",seriesLayout:"seriesRows",minRows:2,minCols:2,status:"stable",docsSlug:"stacked-bar"},stackedBar100:{label:"100% Stacked Bar",description:"Stacked bars normalized to 100% to compare mix, not size.",optionBag:"bar",family:"bar",seriesLayout:"seriesRows",minRows:2,minCols:2,status:"stable",docsSlug:"stacked-bar"},line:{label:"Line Chart",description:"Trends over an ordered domain, one line per series.",optionBag:"line",family:"line",seriesLayout:"seriesRows",minRows:2,minCols:2,status:"stable",docsSlug:"line"},area:{label:"Area Chart",description:"Filled lines showing magnitude over an ordered domain.",optionBag:"area",family:"area",seriesLayout:"seriesRows",minRows:2,minCols:2,status:"stable",docsSlug:"area"},area100:{label:"100% Area Chart",description:"Area chart normalized to 100% to show changing mix.",optionBag:"area",family:"area",seriesLayout:"seriesRows",minRows:2,minCols:2,status:"stable",docsSlug:"area"},pie:{label:"Pie Chart",description:"Share of a single total across categories.",optionBag:"pie",family:"pie",seriesLayout:"categoryValue",minRows:2,minCols:2,status:"stable",docsSlug:"pie"},scatter:{label:"Scatter Plot",description:"Points positioned by two metrics, optionally sized and grouped.",optionBag:"scatter",family:"scatter",seriesLayout:"pointRows",minRows:2,minCols:3,status:"stable",docsSlug:"scatter"},waterfall:{label:"Waterfall",description:"Running total showing how contributions bridge two values.",optionBag:"waterfall",family:"waterfall",seriesLayout:"seriesRows",minRows:2,minCols:2,status:"stable",docsSlug:"waterfall"},mekko:{label:"Marimekko",description:"Variable-width stacked bars where both axes are percentages.",optionBag:"mekko",family:"mekko",seriesLayout:"seriesRows",minRows:2,minCols:2,status:"stable",docsSlug:"mekko"},barMekko:{label:"Bar Mekko",description:"Bars whose width encodes one metric and height another; first data row sets widths.",optionBag:"barMekko",family:"mekko",seriesLayout:"widthRowThenHeightRows",minRows:3,minCols:2,status:"beta",docsSlug:"mekko"},combo:{label:"Combo Chart",description:"Mixed bar and line series on shared or dual axes.",optionBag:"combo",family:"combo",seriesLayout:"seriesRows",minRows:2,minCols:2,status:"stable",docsSlug:"combo"}},T={bubble:"scatter",donut:"pie"},Ae=[];var V=Object.keys(h).sort(),X=Object.keys(T).sort(),R=[...V,...X].sort(),Se=X.filter(e=>!Ae.includes(e)),xt=[...V,...Se].sort();var p={kind:"string",description:"CSS color."},Q={kind:"string",nullable:!0,description:"CSS color; null derives it from the series color."},v={kind:"number",min:0,max:1},u={kind:"object",values:{kind:"unknown"},description:"Per-index overrides; keys are indices, values are style patches."},D={kind:"array",items:Q},O={kind:"array",items:{kind:"number",min:0,nullable:!0}},$={kind:"array",items:{kind:"string",nullable:!0}},Te={id:{kind:"string"},visible:{kind:"boolean"},text:{kind:"string"},fontFamily:{kind:"string"},fontSize:{kind:"number",min:0},fontColor:{kind:"string"},backgroundColor:{kind:"string"},textAlign:{kind:"string"},width:{kind:"number",min:0},height:{kind:"number",min:0},x:{kind:"number"},y:{kind:"number"},movable:{kind:"boolean"},deletable:{kind:"boolean"}},P={kind:"object",fields:Te},Re={shape:{kind:"string",enum:["circle","square","diamond","triangle"]},radius:{kind:"number",min:0,description:"Radius in px."},fill:Q,stroke:p,strokeWidth:{kind:"number",min:0},strokeDashArray:{kind:"string"},series:u,overrides:u},J={kind:"object",fields:Re},Z={kind:"string",enum:["linear","cardinal","step","basis","monotone"]},De={kind:"object",fields:{visible:{kind:"boolean"},color:p,width:{kind:"number",min:0},dashArray:{kind:"string"},opacity:v,overrides:u}},ee={id:{kind:"string"},version:{kind:"string",description:"App version the config was last migrated to. Drives the migrators."},title:P,subtitle:P,footnote:P,isDataTransposed:{kind:"boolean",description:"When true (default), seriesData rows are series."},seriesDataSource:{kind:"unknown"},orientation:{kind:"string",enum:["vertical","horizontal"]},backgroundColor:p,canvas:{kind:"object",fields:{width:{kind:"number",min:0},height:{kind:"number",min:0}}},chartPositionPercentages:{kind:"object",fields:{left:{kind:"number"},right:{kind:"number"},top:{kind:"number"},bottom:{kind:"number"}}},legend:{kind:"object",fields:{visible:{kind:"boolean"},colors:{kind:"array",items:p},position:{kind:"string"}}},axes:{kind:"object",description:"Axes keyed by physical side (left/right/top/bottom).",values:{kind:"object",fields:{id:{kind:"string"},axisTitle:P,gridlines:De}}},annotations:{kind:"object",fields:{cagrs:u,differenceArrows:u,levelArrows:u,levelLines:u}},seriesLabels:{kind:"object",fields:{visible:{kind:"boolean"},fontSize:{kind:"number",min:0},fontColor:p,fontFamily:{kind:"string"},overrides:u}},multilines:{kind:"array",items:{kind:"object",fields:{id:{kind:"string"},deletable:{kind:"boolean"},type:{kind:"string"},text:{kind:"string"},x:{kind:"number"},y:{kind:"number"}}}},origin:{kind:"object"}},N={bar:{padding:{kind:"number",min:0,max:1,description:"Gap between bars, 0\u20131."},cornerRadius:{kind:"number",min:0},reverseStackOrder:{kind:"boolean"},seriesStrokes:D,seriesStrokeWidths:O,seriesStrokeDashArrays:$,series:{kind:"array",items:{kind:"object"}},overrides:u},line:{width:{kind:"number",min:0,description:"Stroke width in px."},strokeDashArray:{kind:"string"},drawPoints:{kind:"boolean"},curveType:Z,curveParameter:{kind:"number"},shadowIntensity:{kind:"number",min:0},padding:{kind:"number",min:0,max:1},pointMarker:J,overrides:u},area:{width:{kind:"number",min:0},strokeDashArray:{kind:"string"},drawPoints:{kind:"boolean"},curveType:Z,curveParameter:{kind:"number"},shadowIntensity:{kind:"number",min:0},fillOpacity:v,fillType:{kind:"string",enum:["solid","gradient"]},fillOpacityTop:v,fillOpacityBottom:v,gradientTarget:{kind:"string"},strokeOpacity:v,pointMarker:J,dataLabels:{kind:"object",fields:{overrides:u}},overrides:u},scatter:{diameter:{kind:"number",min:0,description:"Marker diameter in px. The bubble alias seeds a larger default."},shape:{kind:"string"},shapes:{kind:"array",items:{kind:"string"}},seriesStrokes:D,seriesStrokeWidths:O,seriesStrokeDashArrays:$,overrides:u},pie:{innerRadiusRatio:{kind:"number",min:0,max:1,description:"0 is a full pie; the donut alias seeds 0.5."},scaleFactor:{kind:"number",min:0},labelVisibilityThreshold:{kind:"number",min:0},explode:{kind:"array",items:{kind:"number"},description:"Per-slice explode offsets."},line:{kind:"object",fields:{color:p,width:{kind:"number",min:0},dashArray:{kind:"string"}}},seriesStrokes:D,seriesStrokeWidths:O,seriesStrokeDashArrays:$,overrides:u},waterfall:{totalBarColor:p,totalLegendLabel:{kind:"string"},seriesStrokes:D,seriesStrokeWidths:O,connectorOverrides:u,columns:{kind:"object",description:"Per-column structural metadata, keyed by column index.",values:{kind:"object",fields:{isTotal:{kind:"boolean"},startBar:{kind:"boolean"},showSegments:{kind:"boolean"}}}},overrides:u},mekko:{showTotals:{kind:"boolean",description:"Legacy fallback for charts predating annotations.totals.visible."},overrides:u},barMekko:{sort:{kind:"string",enum:["heightDesc","heightAsc","widthDesc","widthAsc","dataOrder","desc","asc"],description:"Column order along the width axis."},overrides:u},combo:{seriesTypes:{kind:"object",description:"Per-series render type, keyed by series index.",values:{kind:"string",enum:["bar","line","area"]}},baseChartType:{kind:"string",enum:["clusteredBar","stackedBar"],nullable:!0}}},j=Object.keys(N).sort();function Oe(e){return typeof e=="string"&&Object.prototype.hasOwnProperty.call(h,e)}function te(e){return typeof e=="string"&&Object.prototype.hasOwnProperty.call(T,e)}function G(e){return Oe(e)||te(e)}function ne(e){return te(e)?T[e]:e}function U(e,t){let r=new Array(t.length+1),n=new Array(t.length+1);for(let i=0;i<=t.length;i++)r[i]=i;for(let i=1;i<=e.length;i++){n[0]=i;for(let a=1;a<=t.length;a++){let s=e[i-1]===t[a-1]?0:1;n[a]=Math.min(r[a]+1,n[a-1]+1,r[a-1]+s)}for(let a=0;a<=t.length;a++)r[a]=n[a]}return r[t.length]}function re(e){let t=e.toLowerCase(),r=null,n=1/0;for(let a of R){let s=U(t,a.toLowerCase());s<n&&(n=s,r=a)}let i=Math.max(2,Math.floor(t.length/3));return n<=i?r:null}var Pe=2e4,Me=20;function c(e){return e===null?"null":Array.isArray(e)?"array":typeof e}function M(e){return typeof e=="string"?`"${e}"`:typeof e=="bigint"||typeof e=="symbol"||e==null||typeof e!="object"?String(e):c(e)}function _e(e,t){let r=e.toLowerCase(),n,i=1/0;for(let s of t){let d=U(r,s.toLowerCase());d<i&&(i=d,n=s)}let a=Math.max(2,Math.floor(r.length/3));return i<=a?n:void 0}var _=class{constructor(t){this.max=t;this.issues=[]}get full(){return this.issues.length>=this.max}add(t,r,n,i={}){if(this.full)return;let{severity:a="error",...s}=i,d={path:t,code:r,message:n,severity:a};this.issues.push(Object.fromEntries(Object.entries({...d,...s}).filter(([,o])=>o!==void 0)))}};function g(e,t,r,n){if(!(e===void 0||n.full)){if(e===null){if(t.kind==="unknown"||"nullable"in t&&t.nullable)return;n.add(r,"wrong-type",`expected ${t.kind}, received null`,{expected:t.kind,received:"null"});return}switch(t.kind){case"unknown":return;case"union":{if(!t.anyOf.some(a=>{let s=new _(1);return g(e,a,r,s),s.issues.length===0})){let a=t.anyOf.map(s=>s.kind).join(" | ");n.add(r,"wrong-type",`expected ${a}, received ${c(e)}`,{expected:a,received:c(e)})}return}case"string":{if(typeof e!="string"){n.add(r,"wrong-type",`expected string, received ${c(e)}`,{expected:"string",received:c(e)});return}t.enum&&!t.enum.includes(e)&&n.add(r,"not-in-enum",`${M(e)} is not valid; expected one of ${t.enum.map(i=>`"${i}"`).join(", ")}`,{expected:t.enum.map(i=>`"${i}"`).join(" | "),received:M(e),allowed:t.enum,suggestion:_e(e,t.enum)});return}case"number":{if(typeof e!="number"){n.add(r,"wrong-type",`expected number, received ${c(e)}`,{expected:"number",received:c(e)});return}if(!Number.isFinite(e)){n.add(r,"wrong-type",`expected a finite number, received ${e}`,{expected:"finite number",received:String(e)});return}if(t.integer&&!Number.isInteger(e)){n.add(r,"wrong-type",`expected an integer, received ${e}`,{expected:"integer",received:String(e)});return}if(t.min!==void 0&&e<t.min){n.add(r,"out-of-range",`${e} is below the minimum of ${t.min}`,{expected:`>= ${t.min}`,received:String(e)});return}t.max!==void 0&&e>t.max&&n.add(r,"out-of-range",`${e} is above the maximum of ${t.max}`,{expected:`<= ${t.max}`,received:String(e)});return}case"boolean":{typeof e!="boolean"&&n.add(r,"wrong-type",`expected boolean, received ${c(e)}`,{expected:"boolean",received:c(e)});return}case"array":{if(!Array.isArray(e)){n.add(r,"wrong-type",`expected array, received ${c(e)}`,{expected:"array",received:c(e)});return}if(t.minItems!==void 0&&e.length<t.minItems){n.add(r,"out-of-range",`expected at least ${t.minItems} item(s), received ${e.length}`,{expected:`array with >= ${t.minItems} item(s)`,received:`array of ${e.length}`});return}if(!t.items)return;for(let i=0;i<e.length&&!n.full;i++)g(e[i],t.items,`${r}[${i}]`,n);return}case"object":{if(typeof e!="object"||Array.isArray(e)){n.add(r,"wrong-type",`expected object, received ${c(e)}`,{expected:"object",received:c(e)});return}let i=e;if(t.fields)for(let[a,s]of Object.entries(t.fields)){if(n.full)return;g(i[a],s,`${r}.${a}`,n)}if(t.values)for(let[a,s]of Object.entries(i)){if(n.full)return;g(s,t.values,`${r}.${a}`,n)}return}}}}var ie={seriesRows:"row 0 is the category header; each later row is one series",categoryValue:"each row is [Category, Value]",pointRows:"row 0 names the metrics; each later row is one point",widthRowThenHeightRows:"row 1 sizes the bars (never drawn); rows 2+ are stacked height segments"};function Le(e,t,r){if(e===void 0)return;if(!Array.isArray(e)){r.add("seriesData","series-data-shape",`expected a 2D array, received ${c(e)}`,{expected:"2D array",received:c(e)});return}let n=t?h[t]:void 0;n&&e.length<n.minRows&&r.add("seriesData","series-data-shape",`${n.label} needs at least ${n.minRows} rows (${ie[n.seriesLayout]}), received ${e.length}`,{expected:`>= ${n.minRows} rows (${ie[n.seriesLayout]})`,received:`${e.length} rows`});let i=0,a=[];for(let s=0;s<e.length&&!r.full;s++){let d=e[s];if(!Array.isArray(d)){r.add(`seriesData[${s}]`,"series-data-shape",`expected a row array, received ${c(d)}`,{expected:"array",received:c(d)});continue}a.push(d.length),n&&d.length<n.minCols&&r.add(`seriesData[${s}]`,"series-data-shape",`${n.label} needs at least ${n.minCols} columns per row, received ${d.length}`,{expected:`>= ${n.minCols} columns`,received:`${d.length} columns`});for(let o=0;o<d.length;o++){if(r.full||i>=Pe)return;i++;let l=d[o];if(l===null)continue;let m=typeof l;m!=="string"&&m!=="number"&&m!=="boolean"?r.add(`seriesData[${s}][${o}]`,"series-data-shape",`cells must be string, number, boolean, or null; received ${c(l)}`,{expected:"string | number | boolean | null",received:c(l)}):m==="number"&&!Number.isFinite(l)&&r.add(`seriesData[${s}][${o}]`,"series-data-shape",`cells must be finite numbers; received ${l}`,{expected:"finite number",received:String(l)})}}if(a.length>=2){let s=Math.min(...a),d=Math.max(...a);s!==d&&r.add("seriesData","ragged-series-data",`rows have unequal lengths (shortest ${s}, longest ${d}); charts expect a rectangular grid`,{severity:"warning",expected:`every row ${d} cells`,received:`rows of ${s}\u2013${d} cells`})}}function b(e,t={}){let r=new _(t.maxIssues??Me);if(!e||typeof e!="object"||Array.isArray(e))return r.add("","not-an-object",`expected a chart-data object, received ${c(e)}`,{expected:"object",received:c(e)}),ae(r.issues);let n=e,i=null;if(n.chartType!==void 0)if(typeof n.chartType!="string"||!G(n.chartType)){let d=typeof n.chartType=="string"?re(n.chartType):null;r.add("chartType","unknown-chart-type",`${M(n.chartType)} is not a known chart type.${d?` Did you mean "${d}"?`:""}`,{expected:"a ChartType or alias",received:M(n.chartType),allowed:R,suggestion:d??void 0})}else i=ne(n.chartType);(t.requireSomething??!0)&&n.chartType===void 0&&n.seriesData===void 0&&r.add("","empty-patch","expected at least one of chartType or seriesData; a patch with neither cannot change the chart",{expected:"chartType and/or seriesData",received:"neither"}),Le(n.seriesData,i,r);let a=j.filter(d=>n[d]!==void 0);if(!(t.form==="resolved"||t.form!=="patch"&&a.length===j.length)&&i){let d=h[i]?.optionBag;for(let o of a){if(r.full)break;o!==d&&r.add(o,"foreign-option-bag",`${o} options do not apply to a ${i} chart, which reads "${d}"`,{expected:d?`"${d}"`:void 0,received:`"${o}"`,suggestion:d})}}for(let d of a){if(r.full)break;g(n[d],{kind:"object",fields:N[d]},d,r)}for(let[d,o]of Object.entries(ee)){if(r.full)break;g(n[d],o,d,r)}return ae(r.issues)}function ae(e){let t=e.filter(n=>n.severity==="error"),r=e.filter(n=>n.severity==="warning");return{valid:t.length===0,issues:e,errors:t,warnings:r}}function C(e,t="[chartbuddy]"){let r=e.map(i=>` \u2022 ${i.path?`${i.path}: `:""}${i.message}`+(i.severity==="warning"?" (warning)":"")),n=e.length===1?"problem":"problems";return`${t} invalid chart data \u2014 ${e.length} ${n}:
129
+ ${r.join(`
130
+ `)}`}var y=class e extends Error{constructor(r,n){super(r);this.name="ChartDataValidationError";this.issues=n,this.errors=n.filter(i=>i.severity==="error"),this.warnings=n.filter(i=>i.severity==="warning"),Object.setPrototypeOf(this,e.prototype)}toJSON(){return{name:this.name,message:this.message,issues:this.issues}}};function E(e,t="[chartbuddy]",r={}){let{issues:n,errors:i,warnings:a}=b(e,r);if(a.length>0&&console.warn(C(a,t)),i.length>0)throw new y(C(i,t),n)}var f=class e{static{this.globalInstance=null}constructor(t){this.listeners=new Map,this.debugMode=t?.debug??!1}static global(){return e.globalInstance||(e.globalInstance=new e({debug:!1})),e.globalInstance}static resetGlobal(){e.globalInstance=null}on(t,r){return this.listeners.has(t)||this.listeners.set(t,new Set),this.listeners.get(t).add(r),()=>{this.off(t,r)}}once(t,r){let n=i=>{this.off(t,n),r(i)};return this.on(t,n)}emit(t,r){let n=this.listeners.get(t);if(this.debugMode&&console.log(`[EventBus] Emitting "${t}"`,r),!n)return;Array.from(n).forEach(a=>{try{a(r)}catch(s){console.error(`[EventBus] Error in listener for "${t}":`,s)}})}off(t,r){let n=this.listeners.get(t);n&&(r?(n.delete(r),n.size===0&&this.listeners.delete(t)):this.listeners.delete(t))}clear(){this.listeners.clear()}listenerCount(t){let r=this.listeners.get(t);return r?r.size:0}eventNames(){return Array.from(this.listeners.keys())}removeListeners(t){t.forEach(r=>{this.listeners.delete(r)})}};var L={CREATED:"chart.created",TYPE_CHANGED:"chart.type_changed",DELETED:"chart.deleted",SAVED:"chart.saved",DOWNLOADED:"chart.downloaded",OPENED:"chart.opened",CD_CHANGED:"chart.cd_changed"};var Be="chartbuddy-webapp-shell-chart-config",Fe="#ffffff";function He(){try{if(typeof crypto<"u"&&typeof crypto.randomUUID=="function")return crypto.randomUUID()}catch{}return`i${Date.now().toString(36)}${Math.random().toString(36).slice(2,10)}`}function Ve(e){let t=String(e??"").trim();if(!t)throw new Error("[chartbuddy/embed] instanceId must be a non-empty string");if(!/^[A-Za-z0-9_.:-]+$/.test(t))throw new Error('[chartbuddy/embed] instanceId may only contain letters, digits, "_", ".", ":", "-"');return t}function $e(e){let t=e?Ve(e):He(),r=`cb-${t}`;return{instanceId:t,app:`${r}-app`,chart:`${r}-chart`,status:`${r}-status`,logs:`${r}-logs`,toggle:`${r}-toggle`,reset:`${r}-reset`,importBtn:`${r}-import`,importFile:`${r}-import-file`,overlay:`${r}-edit-overlay`}}function B(e){return`chartbuddy-embed-chart-config:${e}`}function de(e){return`chartbuddy-embed-chart-size:${e}`}function Ne(e){try{let t=window.localStorage.getItem(B(e));if(!t)return null;let r=JSON.parse(t);return ce(r)?r:null}catch{return null}}function je(e,t){try{window.localStorage.setItem(B(e),JSON.stringify(t))}catch{}}function Ge(e,t){if(e.persist===!0){let r=Ne(t);if(r)return r}return e.chartData}var z="__CHARTBUDDY_INSIGHTS__",k=new Map;function le(){if(!(typeof window>"u"))try{window[z]=I()}catch{}}function Ue(e){if(k.has(e.instanceId))throw new Error(`[chartbuddy/embed] duplicate instanceId "${e.instanceId}" \u2014 each Insight on the page must have a unique id. Reusing one silently overwrote the registry entry and could cross-contaminate persisted state.`);k.set(e.instanceId,e),le()}function ze(e){k.get(e.instanceId)===e&&(k.delete(e.instanceId),le())}function I(){let e={};return k.forEach((t,r)=>{e[r]=t}),e}async function Y(e={}){let t={},r=I();for(let[n,i]of Object.entries(r)){let a={chartData:i.getChartData()};e.png&&(a.pngBase64=await i.toPngBase64({scale:e.scale,background:e.background})),t[n]=a}return{schemaVersion:1,version:S,charts:t}}function Ye(e){let t=typeof e=="string"?document.querySelector(e):e;if(!t)throw new Error(`[chartbuddy/embed] mount target not found: ${String(e)}`);return t}function ce(e){return!!e&&typeof e=="object"&&typeof e.chartType=="string"&&Array.isArray(e.seriesData)}function se(e,t){E(e,`[chartbuddy/embed] ${t}:`)}function qe(e,t,r){if(e.innerHTML="",e.setAttribute("data-cb-instance",r.instanceId),e.style.position=e.style.position||"relative",e.style.minHeight||(e.style.minHeight="240px"),t){let d=document.createElement("div");d.className="webapp-toolbar",d.innerHTML=`
131
+ <button id="${r.reset}" type="button">Reset All</button>
132
+ <button id="${r.importBtn}" type="button">Import Config</button>
133
+ <input type="file" id="${r.importFile}" style="display:none" accept=".json" />
134
+ `,e.appendChild(d)}let n=document.createElement("div");n.id=r.app,n.className="cb-app-container",n.style.cssText="width:100%;height:100%;min-height:240px;position:relative;box-sizing:border-box;";let i=document.createElement("div");i.id=r.chart,i.className="cb-chart-container",i.style.cssText="width:100%;height:100%;min-height:240px;position:relative;box-sizing:border-box;",n.appendChild(i),e.appendChild(n);let a=document.createElement("div");a.id=r.status,a.className="cb-status",a.style.cssText="display:none;margin-top:8px;font-size:12px;color:#5b616e;",a.textContent="Loading ChartBuddy\u2026",e.appendChild(a);let s=document.createElement("div");s.id=r.logs,s.className="cb-logs",s.style.display="none",e.appendChild(s)}function Ke(e,t){e.innerHTML="",e.setAttribute("data-cb-instance",t.instanceId),e.style.position=e.style.position||"relative";let r=document.createElement("div");return r.id=t.chart,r.className="cb-chart-container cb-chart-container--view",r.style.cssText="width:100%;height:100%;min-height:240px;position:relative;box-sizing:border-box;",e.appendChild(r),r}function We(e,t){let r=document.getElementById(e);r||(r=document.createElement("div"),r.id=e,r.className="cb-edit-overlay",r.style.cssText="position:fixed;inset:0;pointer-events:none;z-index:1000;",document.body.appendChild(r)),r.setAttribute("data-cb-instance",t)}async function Xe(e,t,r){let n=window.ChartBuddyInitEditor;if(typeof n!="function")throw new Error("[chartbuddy/embed] ChartBuddyInitEditor not found after loading the engine. Is the ChartBuddy engine bundle present?");We(t.overlay,t.instanceId);let i=r.persist===!0,a=await n({root:e,chartContainerId:t.chart,statusId:t.status,logsId:t.logs,toggleSpreadsheetBtnId:t.toggle,editOverlaySelector:`#${t.overlay}`,hostOverrides:r.host,chartData:r.chartData??null,persist:i,persistKey:i?B(t.instanceId):void 0,persistSizeKey:i?de(t.instanceId):void 0,enableSpreadsheet:!1});if(!a||!a.chart)throw new Error("[chartbuddy/embed] editor boot returned null");return a}function ue(e,t){let r=Math.max(1,Math.round(t.clientWidth||t.offsetWidth||640)),n=Math.max(1,Math.round(t.clientHeight||t.offsetHeight||360));e.cd.canvas||(e.cd.canvas={}),e.cd.canvas.width=r,e.cd.canvas.height=n}function Je(e,t,r){let n=window.ChartBuddyCreateHeadlessChart;if(typeof n!="function")throw new Error("[chartbuddy/embed] ChartBuddyCreateHeadlessChart not found after loading the engine.");let i=Math.max(1,Math.round(r.clientWidth||r.offsetWidth||640)),a=Math.max(1,Math.round(r.clientHeight||r.offsetHeight||360)),s=n(e,t??null,{width:i,height:a});return ue(s,r),typeof s.drawChart=="function"&&s.drawChart(),s}function Ze(e,t){if(!e||!t)return;let r=t,n=["canvas","title","subtitle","legend","footnote"];for(let[i,a]of Object.entries(r))if(a!=null)if(n.includes(i)&&typeof a=="object"&&!Array.isArray(a))e.cd[i]={...e.cd[i]||{},...a};else if(i==="axes"&&typeof a=="object"&&!Array.isArray(a)){let s={...e.cd.axes||{}};for(let[d,o]of Object.entries(a)){if(o==null||typeof o!="object"){s[d]=o;continue}let l=s[d]||{};s[d]={...l,...o,labels:o.labels?{...l.labels||{},...o.labels,format:{...l.labels?.format||{},...o.labels.format||{}}}:l.labels,axisTitle:o.axisTitle?{...l.axisTitle||{},...o.axisTitle}:l.axisTitle,gridlines:o.gridlines?{...l.gridlines||{},...o.gridlines}:l.gridlines,tickMarks:o.tickMarks?{...l.tickMarks||{},...o.tickMarks}:l.tickMarks}}e.cd.axes=s}else if(i==="annotations"&&typeof a=="object"&&!Array.isArray(a)){let s=e.cd.annotations||{},d={...s,...a};for(let o of["dataLabels","totals","levelLines","levelArrows","cagrArrows"])a[o]&&typeof a[o]=="object"&&!Array.isArray(a[o])&&(d[o]={...s[o]||{},...a[o],...a[o].format||s[o]?.format?{format:{...s[o]?.format||{},...a[o].format||{}}}:{}});e.cd.annotations=d}else i!=="seriesData"&&i!=="seriesDataFormatted"&&i!=="seriesDataColors"&&(e.cd[i]=a);W(e.cd),Array.isArray(r.seriesData)?e.updateData(r.seriesData,r.seriesDataFormatted??null,r.seriesDataColors??null):typeof e.drawChart=="function"&&e.drawChart()}function w(e){let t=e?.cdOriginal??e?.cd;if(!t)return null;try{return JSON.parse(JSON.stringify(t))}catch{return{...t}}}function Qe(e,t,r){let n=new Blob([t],{type:r}),i=URL.createObjectURL(n),a=document.createElement("a");a.href=i,a.download=e,a.rel="noopener",document.body.appendChild(a),a.click(),a.remove(),setTimeout(()=>URL.revokeObjectURL(i),1e3)}async function me(e,t={},r={}){if(!e?.exporter)throw new Error("[chartbuddy/embed] chart exporter unavailable");let n=t.scale??4,i=t.background!==void 0?t.background:r.background;return typeof e.exporter.prepareChartForExport=="function"&&await e.exporter.prepareChartForExport(),e.exporter.generateImageBlob(!1,"export",n,{background:i})}function et(e){return new Promise((t,r)=>{let n=new FileReader;n.onload=()=>{let i=String(n.result||""),a=i.indexOf(",");t(a>=0?i.slice(a+1):i)},n.onerror=()=>r(n.error||new Error("[chartbuddy/embed] FileReader failed")),n.readAsDataURL(e)})}async function tt(e,t={}){let r=await me(e,t,{background:null});await e.exporter.downloadBlob(r,"chart.png")}async function nt(e,t){if(!e?.exporter?.bootDragExportWidgetGoogleSlides)throw new Error("[chartbuddy/embed] drag export unavailable");let r=t?.getBoundingClientRect?.(),n=r?{x:Math.max(12,r.left+56),y:Math.max(12,r.top+12)}:{x:24,y:24};await e.exporter.bootDragExportWidgetGoogleSlides(void 0,n,{skipTrialGate:!0})}function pe(e){let t=e.resolveAssetBase||(r=>"");return class{#a;#d=null;#n=null;#h=null;#u=null;#r=!1;#f;#l;#g;#e;#c=new Map;#m=0;#x=0;#s=null;#i=0;#o=!1;constructor(n,i={}){if(typeof document>"u")throw new Error("[chartbuddy/embed] Insight requires a browser environment");this.container=Ye(n),this.assetBase=t(i.assetBase),this.#l=i,this.#g=i.toolbar===!0,this.#e=$e(i.instanceId),this.instanceId=this.#e.instanceId,this.chartContainerId=this.#e.chart;let a=i.editable===!0;this.#a=a?"edit":"view",i.chartData!==void 0&&se(i.chartData,"chartData"),Ue(this);let s=Ge(i,this.instanceId);this.#f=e.ensureEngineReady(this.assetBase).then(async()=>{this.#r||(a?await this.#A(s):await this.#I(s),!this.#r&&(this.#v(),this.#p("ready")))}).catch(d=>{let o=document.getElementById(this.#e.status);throw o||(o=document.createElement("div"),o.id=this.#e.status,o.className="cb-status",this.container.appendChild(o)),o.style.display="",o.style.marginTop="8px",o.style.fontSize="12px",o.textContent="\u274C "+(d&&d.message?d.message:String(d)),o.style.color="#b42318",console.error(d),d})}get mode(){return this.#a}get ready(){return this.#f}get chart(){return this.#t()}#t(){return(this.#a==="view"?this.#n:this.#d?.chart)??null}#p(n,...i){let a=this.#c.get(n);if(!(!a||a.size===0))for(let s of[...a])try{s(...i)}catch(d){console.error(`[chartbuddy/embed] ${n} handler threw:`,d)}}on(n,i){if(typeof i!="function")throw new Error(`[chartbuddy/embed] on('${n}') requires a function handler`);let a=this.#c.get(n);return a||(a=new Set,this.#c.set(n,a)),a.add(i),()=>this.off(n,i)}off(n,i){this.#c.get(n)?.delete(i)}isDirty(){return this.#m!==this.#x}getRevision(){return this.#m}#v(){this.#x=this.#m}#y(){this.#m+=1,this.#p("change",this.getChartData())}#T(){if(!(this.#o||this.#r)){if(typeof window>"u"){this.#y();return}window.clearTimeout(this.#i),this.#i=window.setTimeout(()=>{this.#i=0,this.#r||this.#y()},50)}}#C(){this.#E(),this.#s=n=>{let i=this.#t(),a=i?.cd?.id??i?.cdOriginal?.id;!a||n?.chartId!==a||this.#T()};try{f.global().on(L.CD_CHANGED,this.#s)}catch{this.#s=null}}#E(){if(this.#s){try{f.global().off(L.CD_CHANGED,this.#s)}catch{}this.#s=null}}#w(n){this.#a!==n&&(this.#a=n,this.#p("mode",n))}#b(){this.#E(),typeof window<"u"&&this.#i&&(window.clearTimeout(this.#i),this.#i=0);try{this.#h?.destroy()}catch{}this.#h=null;try{this.#u?.disconnect()}catch{}this.#u=null;try{this.#n&&this.#n.remove?.()}catch(n){console.warn("[chartbuddy/embed] view chart remove failed:",n)}this.#n=null;try{this.#d?.destroyRuntime?.()}catch(n){console.warn("[chartbuddy/embed] destroyRuntime failed:",n)}this.#d=null,document.getElementById(this.#e.overlay)?.remove()}#k(n,i){this.#h=new A(n,{onDownload:()=>this.downloadPng(),onDragExport:()=>this.dragExport(),onEdit:()=>this.enterEditMode(),onDone:()=>this.exitEditMode()},i)}async#I(n){this.#b(),this.#w("view");let i=Ke(this.container,this.#e);this.#o=!0;try{let a=Je(this.#e.chart,n,i);this.#n=a}finally{this.#o=!1}if(this.#C(),typeof ResizeObserver<"u"){let a=0;this.#u=new ResizeObserver(()=>{cancelAnimationFrame(a),a=requestAnimationFrame(()=>{!this.#n||this.#r||(ue(this.#n,i),this.#n.drawChart?.())})}),this.#u.observe(i)}this.#k(i,"view")}async#A(n){this.#b(),this.#w("edit"),qe(this.container,this.#g,this.#e),this.#o=!0;try{let s=await Xe(this.container,this.#e,{...this.#l,editable:!0,chartData:n,toolbar:this.#g});this.#d=s}finally{this.#o=!1}this.#C();let i=document.getElementById(this.#e.status);i&&(i.textContent="",i.style.display="none");let a=document.getElementById(this.#e.chart);a&&this.#k(a,"edit")}focus(){let n=this.#t();if(!n||this.#a!=="edit")return;let i=window.ChartBuddyFocusEditor;if(typeof i=="function"){i(n);return}try{document.getElementById(this.#e.chart)?.dispatchEvent(new PointerEvent("pointerdown",{bubbles:!0}))}catch{}}setChartData(n){se(n,"setChartData");let i=this.#t();if(!i)throw new Error("[chartbuddy/embed] setChartData called before ready");this.#o=!0;try{Ze(i,n)}finally{typeof window<"u"&&this.#i&&(window.clearTimeout(this.#i),this.#i=0),this.#o=!1}this.#y()}setData(n){if(!Array.isArray(n))throw new Error("[chartbuddy/embed] setData requires a 2D seriesData array");this.setChartData({seriesData:n})}update(n){if(n===void 0){let i=this.#t();if(!i)throw new Error("[chartbuddy/embed] update called before ready");typeof i.drawChart=="function"&&i.drawChart();return}this.setChartData(n)}getChartData(){return w(this.#t())}async toPngBlob(n={}){let i=this.#t();if(!i)throw new Error("[chartbuddy/embed] toPngBlob called before ready");return me(i,n,{background:Fe})}async toPngBase64(n={}){let i=await this.toPngBlob(n);return et(i)}async downloadPng(n={}){let i=this.#t();if(!i)throw new Error("[chartbuddy/embed] downloadPng called before ready");await tt(i,n)}async dragExport(){let n=this.#t();if(!n)throw new Error("[chartbuddy/embed] dragExport called before ready");let i=document.getElementById(this.#e.chart);await nt(n,i)}exportConfig(){let n=w(this.#t());if(!n)throw new Error("[chartbuddy/embed] exportConfig called before ready");Qe("chartbuddy-chart.json",JSON.stringify(n,null,2),"application/json")}#S(n){this.#l.persist!==!0||!n||!ce(n)||je(this.instanceId,n)}async enterEditMode(){if(this.#r||this.#a==="edit")return;let n=w(this.#n)??this.#l.chartData;await e.ensureEngineReady(this.assetBase),await this.#A(n)}async exitEditMode(){if(this.#r||this.#a==="view")return;let n=w(this.#d?.chart),i=n??this.#l.chartData;this.#S(i),await e.ensureEngineReady(this.assetBase),await this.#I(i),this.#v(),n&&this.#p("change",n)}destroy(){this.#r||(this.#r=!0,this.#S(w(this.#t())),this.#b(),this.#c.clear(),this.container.innerHTML="",this.container.removeAttribute("data-cb-instance"),ze(this))}}}function q(e){try{e?(window.localStorage.removeItem(B(e)),window.localStorage.removeItem(de(e))):window.localStorage.removeItem(Be)}catch{}}var mt={};var rt=(()=>{let e="";try{let t=mt?.url;t&&(e=new URL("./",t).href)}catch{}if(!e)try{let t=typeof document<"u"&&document.currentScript?document.currentScript.src:"";t&&(e=new URL("./",t).href)}catch{}return e.replace(/\/api\/embed\/$/,"/embed/")})(),it=["ts/shared/libraries/d3.min.js","ts/shared/libraries/DOMPurify.min.js","webapp-entry.js"],at=["webapp-entry.css"],F=null;function ot(e){let t=e||globalThis.CHARTBUDDY_EDITOR_BASE||rt;if(!t)throw new Error('[chartbuddy/embed] could not determine the engine asset base. Pass { assetBase } pointing at the directory that holds webapp-entry.js (must end with "/").');return t.endsWith("/")?t:t+"/"}function st(e){at.forEach(t=>{let r=e+t;if(document.querySelector(`link[data-cb-embed="${t}"]`))return;let n=document.createElement("link");n.rel="stylesheet",n.href=r,n.setAttribute("data-cb-embed",t),document.head.appendChild(n)})}function dt(e){return new Promise((t,r)=>{let n=document.querySelector(`script[data-cb-embed="${e}"]`);if(n){n.getAttribute("data-cb-loaded")==="true"?t():(n.addEventListener("load",()=>t()),n.addEventListener("error",()=>r(new Error(`[chartbuddy/embed] failed to load ${e}`))));return}let i=document.createElement("script");i.src=e,i.async=!1,i.setAttribute("data-cb-embed",e),i.addEventListener("load",()=>{i.setAttribute("data-cb-loaded","true"),t()}),i.addEventListener("error",()=>r(new Error(`[chartbuddy/embed] failed to load ${e}`))),document.head.appendChild(i)})}function lt(e){return F||(window.__CHARTBUDDY_NO_AUTOBOOT__=!0,window.__WEBAPP_ASSET_BASE__=e,st(e),F=it.reduce((t,r)=>t.then(()=>dt(e+r)),Promise.resolve()),F)}var he=pe({resolveAssetBase:ot,ensureEngineReady:e=>lt(e)}),ct={Insight:he,clearPersistedChart:q,getInsights:I,snapshotInsights:Y,validateChartData:b};return ve(ut);})();
135
+ //# sourceMappingURL=chartbuddy-embed.global.js.map
@@ -0,0 +1,135 @@
1
+ /**
2
+ * @chartbuddy.io/embed — ChartBuddy Insights (NOT Chart.js / Recharts).
3
+ * This file is the multi-file loader (needs sibling engine assets).
4
+ * Default is view-only (hover ChartBuddy ball: Download / Drag to slide /
5
+ * Export / Edit). Pass editable: true for the full editor. Ball → Done exits.
6
+ *
7
+ * Exports:
8
+ * new Insight(target, options?) → Insight
9
+ * getInsights() / snapshotInsights({ png? })
10
+ * clearPersistedChart(instanceId?)
11
+ * version: string
12
+ * Agent hook: window.__CHARTBUDDY_INSIGHTS__ (keyed by instanceId)
13
+ *
14
+ * Minimal example (view mode, data-in, no account / chart ID):
15
+ * import { Insight } from 'https://unpkg.com/@chartbuddy.io/embed';
16
+ * const insight = new Insight('#chart', {
17
+ * instanceId: 'revenue',
18
+ * chartData: {
19
+ * chartType: 'clusteredBar',
20
+ * isDataTransposed: true,
21
+ * seriesData: [['','Q1','Q2'],['Revenue',100,112],['Costs',60,66]],
22
+ * },
23
+ * });
24
+ * await insight.ready;
25
+ * // Agent observe: await insight.toPngBase64() // default bg #ffffff
26
+ * // or toPngBase64({ background: '#0f172a' }) / getChartData()
27
+ * // Full editor: new Insight('#chart', { editable: true, chartData: … })
28
+ * // Leave edit: insight.exitEditMode() or ball → Done
29
+ *
30
+ * Docs (fetch next if needed):
31
+ * https://unpkg.com/@chartbuddy.io/embed/llms.txt
32
+ * https://cb-acc.xyz/llms.txt
33
+ * https://cb-acc.xyz/embed/api
34
+ * https://unpkg.com/@chartbuddy.io/embed/README.md
35
+ */
36
+
37
+ var pe=`<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 96 96" aria-hidden="true">
38
+ <circle cx="48" cy="48" r="46" fill="#f8fafc"/>
39
+ <rect x="60" y="22" width="12" height="53" fill="#5ce1e6" rx="6"/>
40
+ <rect x="42" y="48" width="12" height="27" fill="#ff5757" rx="6"/>
41
+ <rect x="23" y="30" width="12" height="45" fill="#ffbd59" rx="6"/>
42
+ </svg>`,U="cb-embed-chrome-styles";function he(){if(typeof document>"u"||document.getElementById(U))return;let e=document.createElement("style");e.id=U,e.textContent=`
43
+ .cb-embed-chrome-root {
44
+ position: absolute;
45
+ inset: 0;
46
+ pointer-events: none;
47
+ z-index: 20;
48
+ }
49
+ .cb-embed-ball {
50
+ position: absolute;
51
+ top: 10px;
52
+ left: 10px;
53
+ display: none;
54
+ align-items: center;
55
+ justify-content: center;
56
+ width: 40px;
57
+ height: 40px;
58
+ padding: 1px;
59
+ border: 1px solid rgba(255, 255, 255, 0.45);
60
+ border-radius: 50%;
61
+ background-color: rgba(15, 23, 42, 0.55);
62
+ box-shadow: 0 6px 18px rgba(0, 0, 0, 0.40);
63
+ backdrop-filter: blur(12px) saturate(1.15);
64
+ -webkit-backdrop-filter: blur(12px) saturate(1.15);
65
+ cursor: pointer;
66
+ pointer-events: auto;
67
+ transition: background-color 0.15s ease, box-shadow 0.15s ease;
68
+ box-sizing: border-box;
69
+ }
70
+ .cb-embed-chrome-root.is-visible .cb-embed-ball,
71
+ .cb-embed-chrome-root.is-menu-open .cb-embed-ball {
72
+ display: flex;
73
+ }
74
+ .cb-embed-ball:hover,
75
+ .cb-embed-ball:focus-visible {
76
+ background-color: rgba(15, 23, 42, 0.74);
77
+ outline: none;
78
+ }
79
+ .cb-embed-ball svg {
80
+ display: block;
81
+ width: 32px;
82
+ height: 32px;
83
+ }
84
+ .cb-embed-menu {
85
+ position: absolute;
86
+ top: 56px;
87
+ left: 10px;
88
+ min-width: 168px;
89
+ padding: 6px;
90
+ border-radius: 12px;
91
+ border: 1px solid rgba(255, 255, 255, 0.14);
92
+ background: rgba(15, 23, 42, 0.92);
93
+ box-shadow: 0 12px 32px rgba(0, 0, 0, 0.45);
94
+ backdrop-filter: blur(16px) saturate(1.2);
95
+ -webkit-backdrop-filter: blur(16px) saturate(1.2);
96
+ display: none;
97
+ flex-direction: column;
98
+ gap: 2px;
99
+ pointer-events: auto;
100
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
101
+ }
102
+ .cb-embed-chrome-root.is-menu-open .cb-embed-menu {
103
+ display: flex;
104
+ }
105
+ .cb-embed-menu-item {
106
+ appearance: none;
107
+ border: 0;
108
+ background: transparent;
109
+ color: #f8fafc;
110
+ text-align: left;
111
+ font-size: 13px;
112
+ font-weight: 560;
113
+ line-height: 1.2;
114
+ padding: 10px 12px;
115
+ border-radius: 8px;
116
+ cursor: pointer;
117
+ }
118
+ .cb-embed-menu-item:hover,
119
+ .cb-embed-menu-item:focus-visible {
120
+ background: rgba(255, 255, 255, 0.10);
121
+ outline: none;
122
+ }
123
+ `,document.head.appendChild(e)}function ge(e){let t=`
124
+ <button type="button" class="cb-embed-menu-item" data-action="download" role="menuitem">Download</button>
125
+ <button type="button" class="cb-embed-menu-item" data-action="dragExport" role="menuitem">Drag to slide</button>
126
+ `;return e==="edit"?`${t}
127
+ <button type="button" class="cb-embed-menu-item" data-action="done" role="menuitem">Done</button>`:`${t}
128
+ <button type="button" class="cb-embed-menu-item" data-action="edit" role="menuitem">Edit</button>`}var w=class{constructor(t,r,n="view"){this.hideTimer=null;this.destroyed=!1;he(),this.host=t,getComputedStyle(t).position==="static"&&(t.style.position="relative"),this.root=document.createElement("div"),this.root.className="cb-embed-chrome-root",this.root.setAttribute("data-cb-embed-chrome","1"),this.root.setAttribute("data-cb-embed-chrome-mode",n),this.ball=document.createElement("button"),this.ball.type="button",this.ball.className="cb-embed-ball",this.ball.setAttribute("aria-label","ChartBuddy actions"),this.ball.setAttribute("aria-haspopup","menu"),this.ball.setAttribute("aria-expanded","false"),this.ball.innerHTML=pe,this.menu=document.createElement("div"),this.menu.className="cb-embed-menu",this.menu.setAttribute("role","menu"),this.menu.innerHTML=ge(n),this.root.appendChild(this.ball),this.root.appendChild(this.menu),t.appendChild(this.root),this.ball.addEventListener("click",i=>{i.stopPropagation(),this.toggleMenu()}),this.menu.addEventListener("click",i=>{let a=i.target?.closest?.("[data-action]");if(!a)return;i.stopPropagation();let s=a.getAttribute("data-action");this.closeMenu(),this.dispatch(s,r)}),this.onHostEnter=()=>{this.destroyed||(this.clearHideTimer(),this.root.classList.add("is-visible"))},this.onHostLeave=()=>{this.destroyed||this.scheduleHide()},this.onDocPointer=i=>{if(this.destroyed||!this.root.classList.contains("is-menu-open"))return;let a=i.target;a&&this.root.contains(a)||this.closeMenu()},this.onKeyDown=i=>{i.key==="Escape"&&this.closeMenu()},t.addEventListener("pointerenter",this.onHostEnter),t.addEventListener("pointerleave",this.onHostLeave),document.addEventListener("pointerdown",this.onDocPointer,!0),document.addEventListener("keydown",this.onKeyDown)}async dispatch(t,r){try{t==="download"?await r.onDownload():t==="dragExport"?await r.onDragExport():t==="edit"?await r.onEdit?.():t==="done"&&await r.onDone?.()}catch(n){console.error("[chartbuddy/embed] chrome action failed:",n)}}toggleMenu(){this.root.classList.contains("is-menu-open")?this.closeMenu():this.openMenu()}openMenu(){this.clearHideTimer(),this.root.classList.add("is-visible","is-menu-open"),this.ball.setAttribute("aria-expanded","true")}closeMenu(){this.root.classList.remove("is-menu-open"),this.ball.setAttribute("aria-expanded","false")}scheduleHide(){this.clearHideTimer(),this.hideTimer=setTimeout(()=>{this.root.classList.contains("is-menu-open")||this.root.classList.remove("is-visible")},80)}clearHideTimer(){this.hideTimer&&(clearTimeout(this.hideTimer),this.hideTimer=null)}destroy(){this.destroyed||(this.destroyed=!0,this.clearHideTimer(),this.host.removeEventListener("pointerenter",this.onHostEnter),this.host.removeEventListener("pointerleave",this.onHostLeave),document.removeEventListener("pointerdown",this.onDocPointer,!0),document.removeEventListener("keydown",this.onKeyDown),this.root.remove())}};var b={vertical:{domain:"bottom",primaryRange:"left",secondaryRange:"right"},horizontal:{domain:"left",primaryRange:"bottom",secondaryRange:"top"}};function ye(e,t="vertical"){if(!e||typeof e!="object")return!1;let r=b[t]||b.vertical;return e[r.domain]?.id==="domain"&&e[r.primaryRange]?.id==="primaryRange"}function be(e,t="vertical"){let r=b[t]||b.vertical,n=o=>o==="left"?-90:o==="right"?90:0,i={},a=null;for(let o of["left","right","top","bottom"]){let l=e?.[o];if(!l)continue;let m=JSON.parse(JSON.stringify(l));l.id==="domain"||l.id==="primaryRange"||l.id==="secondaryRange"?i[l.id]=m:a=m}let s={},d=(o,l)=>{if(o){if(o.position=l,o.axisTitle){if(o.axisTitle.id){let m=String(o.axisTitle.id).split("-");m.length>=2&&(m[m.length-2]=l,o.axisTitle.id=m.join("-"))}o.axisTitle.rotation=n(l)}o.id==="domain"&&o.labels&&typeof o.labels=="object"&&(o.labels.position=l),s[l]=o}};d(i.domain,r.domain),d(i.primaryRange,r.primaryRange),d(i.secondaryRange,r.secondaryRange);for(let o of["left","right","top","bottom"])if(!s[o]){let l=a?JSON.parse(JSON.stringify(a)):{id:"unused",enabled:!1,visible:!1,scaleType:"band",labels:{visible:!1},axisTitle:{id:`multiline-${o}-title`,text:"",visible:!1}};d(l,o)}return s}function z(e){if(!e||typeof e!="object")return e;let t=e.orientation==="horizontal"?"horizontal":"vertical";return e.orientation=t,!e.axes||ye(e.axes,t)||(e.axes=be(e.axes,t)),e}var F="1.7.52";var h={clusteredBar:{label:"Clustered Bar",description:"Side-by-side bars comparing series within each category.",optionBag:"bar",family:"bar",seriesLayout:"seriesRows",minRows:2,minCols:2,status:"stable",docsSlug:"clustered-bar"},stackedBar:{label:"Stacked Bar",description:"Bars stacked to show composition and category totals.",optionBag:"bar",family:"bar",seriesLayout:"seriesRows",minRows:2,minCols:2,status:"stable",docsSlug:"stacked-bar"},stackedBar100:{label:"100% Stacked Bar",description:"Stacked bars normalized to 100% to compare mix, not size.",optionBag:"bar",family:"bar",seriesLayout:"seriesRows",minRows:2,minCols:2,status:"stable",docsSlug:"stacked-bar"},line:{label:"Line Chart",description:"Trends over an ordered domain, one line per series.",optionBag:"line",family:"line",seriesLayout:"seriesRows",minRows:2,minCols:2,status:"stable",docsSlug:"line"},area:{label:"Area Chart",description:"Filled lines showing magnitude over an ordered domain.",optionBag:"area",family:"area",seriesLayout:"seriesRows",minRows:2,minCols:2,status:"stable",docsSlug:"area"},area100:{label:"100% Area Chart",description:"Area chart normalized to 100% to show changing mix.",optionBag:"area",family:"area",seriesLayout:"seriesRows",minRows:2,minCols:2,status:"stable",docsSlug:"area"},pie:{label:"Pie Chart",description:"Share of a single total across categories.",optionBag:"pie",family:"pie",seriesLayout:"categoryValue",minRows:2,minCols:2,status:"stable",docsSlug:"pie"},scatter:{label:"Scatter Plot",description:"Points positioned by two metrics, optionally sized and grouped.",optionBag:"scatter",family:"scatter",seriesLayout:"pointRows",minRows:2,minCols:3,status:"stable",docsSlug:"scatter"},waterfall:{label:"Waterfall",description:"Running total showing how contributions bridge two values.",optionBag:"waterfall",family:"waterfall",seriesLayout:"seriesRows",minRows:2,minCols:2,status:"stable",docsSlug:"waterfall"},mekko:{label:"Marimekko",description:"Variable-width stacked bars where both axes are percentages.",optionBag:"mekko",family:"mekko",seriesLayout:"seriesRows",minRows:2,minCols:2,status:"stable",docsSlug:"mekko"},barMekko:{label:"Bar Mekko",description:"Bars whose width encodes one metric and height another; first data row sets widths.",optionBag:"barMekko",family:"mekko",seriesLayout:"widthRowThenHeightRows",minRows:3,minCols:2,status:"beta",docsSlug:"mekko"},combo:{label:"Combo Chart",description:"Mixed bar and line series on shared or dual axes.",optionBag:"combo",family:"combo",seriesLayout:"seriesRows",minRows:2,minCols:2,status:"stable",docsSlug:"combo"}},k={bubble:"scatter",donut:"pie"},fe=[];var H=Object.keys(h).sort(),Y=Object.keys(k).sort(),I=[...H,...Y].sort(),xe=Y.filter(e=>!fe.includes(e)),dt=[...H,...xe].sort();var p={kind:"string",description:"CSS color."},W={kind:"string",nullable:!0,description:"CSS color; null derives it from the series color."},f={kind:"number",min:0,max:1},u={kind:"object",values:{kind:"unknown"},description:"Per-index overrides; keys are indices, values are style patches."},A={kind:"array",items:W},S={kind:"array",items:{kind:"number",min:0,nullable:!0}},V={kind:"array",items:{kind:"string",nullable:!0}},ve={id:{kind:"string"},visible:{kind:"boolean"},text:{kind:"string"},fontFamily:{kind:"string"},fontSize:{kind:"number",min:0},fontColor:{kind:"string"},backgroundColor:{kind:"string"},textAlign:{kind:"string"},width:{kind:"number",min:0},height:{kind:"number",min:0},x:{kind:"number"},y:{kind:"number"},movable:{kind:"boolean"},deletable:{kind:"boolean"}},T={kind:"object",fields:ve},Ce={shape:{kind:"string",enum:["circle","square","diamond","triangle"]},radius:{kind:"number",min:0,description:"Radius in px."},fill:W,stroke:p,strokeWidth:{kind:"number",min:0},strokeDashArray:{kind:"string"},series:u,overrides:u},q={kind:"object",fields:Ce},K={kind:"string",enum:["linear","cardinal","step","basis","monotone"]},Ee={kind:"object",fields:{visible:{kind:"boolean"},color:p,width:{kind:"number",min:0},dashArray:{kind:"string"},opacity:f,overrides:u}},X={id:{kind:"string"},version:{kind:"string",description:"App version the config was last migrated to. Drives the migrators."},title:T,subtitle:T,footnote:T,isDataTransposed:{kind:"boolean",description:"When true (default), seriesData rows are series."},seriesDataSource:{kind:"unknown"},orientation:{kind:"string",enum:["vertical","horizontal"]},backgroundColor:p,canvas:{kind:"object",fields:{width:{kind:"number",min:0},height:{kind:"number",min:0}}},chartPositionPercentages:{kind:"object",fields:{left:{kind:"number"},right:{kind:"number"},top:{kind:"number"},bottom:{kind:"number"}}},legend:{kind:"object",fields:{visible:{kind:"boolean"},colors:{kind:"array",items:p},position:{kind:"string"}}},axes:{kind:"object",description:"Axes keyed by physical side (left/right/top/bottom).",values:{kind:"object",fields:{id:{kind:"string"},axisTitle:T,gridlines:Ee}}},annotations:{kind:"object",fields:{cagrs:u,differenceArrows:u,levelArrows:u,levelLines:u}},seriesLabels:{kind:"object",fields:{visible:{kind:"boolean"},fontSize:{kind:"number",min:0},fontColor:p,fontFamily:{kind:"string"},overrides:u}},multilines:{kind:"array",items:{kind:"object",fields:{id:{kind:"string"},deletable:{kind:"boolean"},type:{kind:"string"},text:{kind:"string"},x:{kind:"number"},y:{kind:"number"}}}},origin:{kind:"object"}},$={bar:{padding:{kind:"number",min:0,max:1,description:"Gap between bars, 0\u20131."},cornerRadius:{kind:"number",min:0},reverseStackOrder:{kind:"boolean"},seriesStrokes:A,seriesStrokeWidths:S,seriesStrokeDashArrays:V,series:{kind:"array",items:{kind:"object"}},overrides:u},line:{width:{kind:"number",min:0,description:"Stroke width in px."},strokeDashArray:{kind:"string"},drawPoints:{kind:"boolean"},curveType:K,curveParameter:{kind:"number"},shadowIntensity:{kind:"number",min:0},padding:{kind:"number",min:0,max:1},pointMarker:q,overrides:u},area:{width:{kind:"number",min:0},strokeDashArray:{kind:"string"},drawPoints:{kind:"boolean"},curveType:K,curveParameter:{kind:"number"},shadowIntensity:{kind:"number",min:0},fillOpacity:f,fillType:{kind:"string",enum:["solid","gradient"]},fillOpacityTop:f,fillOpacityBottom:f,gradientTarget:{kind:"string"},strokeOpacity:f,pointMarker:q,dataLabels:{kind:"object",fields:{overrides:u}},overrides:u},scatter:{diameter:{kind:"number",min:0,description:"Marker diameter in px. The bubble alias seeds a larger default."},shape:{kind:"string"},shapes:{kind:"array",items:{kind:"string"}},seriesStrokes:A,seriesStrokeWidths:S,seriesStrokeDashArrays:V,overrides:u},pie:{innerRadiusRatio:{kind:"number",min:0,max:1,description:"0 is a full pie; the donut alias seeds 0.5."},scaleFactor:{kind:"number",min:0},labelVisibilityThreshold:{kind:"number",min:0},explode:{kind:"array",items:{kind:"number"},description:"Per-slice explode offsets."},line:{kind:"object",fields:{color:p,width:{kind:"number",min:0},dashArray:{kind:"string"}}},seriesStrokes:A,seriesStrokeWidths:S,seriesStrokeDashArrays:V,overrides:u},waterfall:{totalBarColor:p,totalLegendLabel:{kind:"string"},seriesStrokes:A,seriesStrokeWidths:S,connectorOverrides:u,columns:{kind:"object",description:"Per-column structural metadata, keyed by column index.",values:{kind:"object",fields:{isTotal:{kind:"boolean"},startBar:{kind:"boolean"},showSegments:{kind:"boolean"}}}},overrides:u},mekko:{showTotals:{kind:"boolean",description:"Legacy fallback for charts predating annotations.totals.visible."},overrides:u},barMekko:{sort:{kind:"string",enum:["heightDesc","heightAsc","widthDesc","widthAsc","dataOrder","desc","asc"],description:"Column order along the width axis."},overrides:u},combo:{seriesTypes:{kind:"object",description:"Per-series render type, keyed by series index.",values:{kind:"string",enum:["bar","line","area"]}},baseChartType:{kind:"string",enum:["clusteredBar","stackedBar"],nullable:!0}}},N=Object.keys($).sort();function we(e){return typeof e=="string"&&Object.prototype.hasOwnProperty.call(h,e)}function J(e){return typeof e=="string"&&Object.prototype.hasOwnProperty.call(k,e)}function j(e){return we(e)||J(e)}function Z(e){return J(e)?k[e]:e}function G(e,t){let r=new Array(t.length+1),n=new Array(t.length+1);for(let i=0;i<=t.length;i++)r[i]=i;for(let i=1;i<=e.length;i++){n[0]=i;for(let a=1;a<=t.length;a++){let s=e[i-1]===t[a-1]?0:1;n[a]=Math.min(r[a]+1,n[a-1]+1,r[a-1]+s)}for(let a=0;a<=t.length;a++)r[a]=n[a]}return r[t.length]}function Q(e){let t=e.toLowerCase(),r=null,n=1/0;for(let a of I){let s=G(t,a.toLowerCase());s<n&&(n=s,r=a)}let i=Math.max(2,Math.floor(t.length/3));return n<=i?r:null}var ke=2e4,Ie=20;function c(e){return e===null?"null":Array.isArray(e)?"array":typeof e}function R(e){return typeof e=="string"?`"${e}"`:typeof e=="bigint"||typeof e=="symbol"||e==null||typeof e!="object"?String(e):c(e)}function Ae(e,t){let r=e.toLowerCase(),n,i=1/0;for(let s of t){let d=G(r,s.toLowerCase());d<i&&(i=d,n=s)}let a=Math.max(2,Math.floor(r.length/3));return i<=a?n:void 0}var D=class{constructor(t){this.max=t;this.issues=[]}get full(){return this.issues.length>=this.max}add(t,r,n,i={}){if(this.full)return;let{severity:a="error",...s}=i,d={path:t,code:r,message:n,severity:a};this.issues.push(Object.fromEntries(Object.entries({...d,...s}).filter(([,o])=>o!==void 0)))}};function g(e,t,r,n){if(!(e===void 0||n.full)){if(e===null){if(t.kind==="unknown"||"nullable"in t&&t.nullable)return;n.add(r,"wrong-type",`expected ${t.kind}, received null`,{expected:t.kind,received:"null"});return}switch(t.kind){case"unknown":return;case"union":{if(!t.anyOf.some(a=>{let s=new D(1);return g(e,a,r,s),s.issues.length===0})){let a=t.anyOf.map(s=>s.kind).join(" | ");n.add(r,"wrong-type",`expected ${a}, received ${c(e)}`,{expected:a,received:c(e)})}return}case"string":{if(typeof e!="string"){n.add(r,"wrong-type",`expected string, received ${c(e)}`,{expected:"string",received:c(e)});return}t.enum&&!t.enum.includes(e)&&n.add(r,"not-in-enum",`${R(e)} is not valid; expected one of ${t.enum.map(i=>`"${i}"`).join(", ")}`,{expected:t.enum.map(i=>`"${i}"`).join(" | "),received:R(e),allowed:t.enum,suggestion:Ae(e,t.enum)});return}case"number":{if(typeof e!="number"){n.add(r,"wrong-type",`expected number, received ${c(e)}`,{expected:"number",received:c(e)});return}if(!Number.isFinite(e)){n.add(r,"wrong-type",`expected a finite number, received ${e}`,{expected:"finite number",received:String(e)});return}if(t.integer&&!Number.isInteger(e)){n.add(r,"wrong-type",`expected an integer, received ${e}`,{expected:"integer",received:String(e)});return}if(t.min!==void 0&&e<t.min){n.add(r,"out-of-range",`${e} is below the minimum of ${t.min}`,{expected:`>= ${t.min}`,received:String(e)});return}t.max!==void 0&&e>t.max&&n.add(r,"out-of-range",`${e} is above the maximum of ${t.max}`,{expected:`<= ${t.max}`,received:String(e)});return}case"boolean":{typeof e!="boolean"&&n.add(r,"wrong-type",`expected boolean, received ${c(e)}`,{expected:"boolean",received:c(e)});return}case"array":{if(!Array.isArray(e)){n.add(r,"wrong-type",`expected array, received ${c(e)}`,{expected:"array",received:c(e)});return}if(t.minItems!==void 0&&e.length<t.minItems){n.add(r,"out-of-range",`expected at least ${t.minItems} item(s), received ${e.length}`,{expected:`array with >= ${t.minItems} item(s)`,received:`array of ${e.length}`});return}if(!t.items)return;for(let i=0;i<e.length&&!n.full;i++)g(e[i],t.items,`${r}[${i}]`,n);return}case"object":{if(typeof e!="object"||Array.isArray(e)){n.add(r,"wrong-type",`expected object, received ${c(e)}`,{expected:"object",received:c(e)});return}let i=e;if(t.fields)for(let[a,s]of Object.entries(t.fields)){if(n.full)return;g(i[a],s,`${r}.${a}`,n)}if(t.values)for(let[a,s]of Object.entries(i)){if(n.full)return;g(s,t.values,`${r}.${a}`,n)}return}}}}var ee={seriesRows:"row 0 is the category header; each later row is one series",categoryValue:"each row is [Category, Value]",pointRows:"row 0 names the metrics; each later row is one point",widthRowThenHeightRows:"row 1 sizes the bars (never drawn); rows 2+ are stacked height segments"};function Se(e,t,r){if(e===void 0)return;if(!Array.isArray(e)){r.add("seriesData","series-data-shape",`expected a 2D array, received ${c(e)}`,{expected:"2D array",received:c(e)});return}let n=t?h[t]:void 0;n&&e.length<n.minRows&&r.add("seriesData","series-data-shape",`${n.label} needs at least ${n.minRows} rows (${ee[n.seriesLayout]}), received ${e.length}`,{expected:`>= ${n.minRows} rows (${ee[n.seriesLayout]})`,received:`${e.length} rows`});let i=0,a=[];for(let s=0;s<e.length&&!r.full;s++){let d=e[s];if(!Array.isArray(d)){r.add(`seriesData[${s}]`,"series-data-shape",`expected a row array, received ${c(d)}`,{expected:"array",received:c(d)});continue}a.push(d.length),n&&d.length<n.minCols&&r.add(`seriesData[${s}]`,"series-data-shape",`${n.label} needs at least ${n.minCols} columns per row, received ${d.length}`,{expected:`>= ${n.minCols} columns`,received:`${d.length} columns`});for(let o=0;o<d.length;o++){if(r.full||i>=ke)return;i++;let l=d[o];if(l===null)continue;let m=typeof l;m!=="string"&&m!=="number"&&m!=="boolean"?r.add(`seriesData[${s}][${o}]`,"series-data-shape",`cells must be string, number, boolean, or null; received ${c(l)}`,{expected:"string | number | boolean | null",received:c(l)}):m==="number"&&!Number.isFinite(l)&&r.add(`seriesData[${s}][${o}]`,"series-data-shape",`cells must be finite numbers; received ${l}`,{expected:"finite number",received:String(l)})}}if(a.length>=2){let s=Math.min(...a),d=Math.max(...a);s!==d&&r.add("seriesData","ragged-series-data",`rows have unequal lengths (shortest ${s}, longest ${d}); charts expect a rectangular grid`,{severity:"warning",expected:`every row ${d} cells`,received:`rows of ${s}\u2013${d} cells`})}}function v(e,t={}){let r=new D(t.maxIssues??Ie);if(!e||typeof e!="object"||Array.isArray(e))return r.add("","not-an-object",`expected a chart-data object, received ${c(e)}`,{expected:"object",received:c(e)}),te(r.issues);let n=e,i=null;if(n.chartType!==void 0)if(typeof n.chartType!="string"||!j(n.chartType)){let d=typeof n.chartType=="string"?Q(n.chartType):null;r.add("chartType","unknown-chart-type",`${R(n.chartType)} is not a known chart type.${d?` Did you mean "${d}"?`:""}`,{expected:"a ChartType or alias",received:R(n.chartType),allowed:I,suggestion:d??void 0})}else i=Z(n.chartType);(t.requireSomething??!0)&&n.chartType===void 0&&n.seriesData===void 0&&r.add("","empty-patch","expected at least one of chartType or seriesData; a patch with neither cannot change the chart",{expected:"chartType and/or seriesData",received:"neither"}),Se(n.seriesData,i,r);let a=N.filter(d=>n[d]!==void 0);if(!(t.form==="resolved"||t.form!=="patch"&&a.length===N.length)&&i){let d=h[i]?.optionBag;for(let o of a){if(r.full)break;o!==d&&r.add(o,"foreign-option-bag",`${o} options do not apply to a ${i} chart, which reads "${d}"`,{expected:d?`"${d}"`:void 0,received:`"${o}"`,suggestion:d})}}for(let d of a){if(r.full)break;g(n[d],{kind:"object",fields:$[d]},d,r)}for(let[d,o]of Object.entries(X)){if(r.full)break;g(n[d],o,d,r)}return te(r.issues)}function te(e){let t=e.filter(n=>n.severity==="error"),r=e.filter(n=>n.severity==="warning");return{valid:t.length===0,issues:e,errors:t,warnings:r}}function O(e,t="[chartbuddy]"){let r=e.map(i=>` \u2022 ${i.path?`${i.path}: `:""}${i.message}`+(i.severity==="warning"?" (warning)":"")),n=e.length===1?"problem":"problems";return`${t} invalid chart data \u2014 ${e.length} ${n}:
129
+ ${r.join(`
130
+ `)}`}var x=class e extends Error{constructor(r,n){super(r);this.name="ChartDataValidationError";this.issues=n,this.errors=n.filter(i=>i.severity==="error"),this.warnings=n.filter(i=>i.severity==="warning"),Object.setPrototypeOf(this,e.prototype)}toJSON(){return{name:this.name,message:this.message,issues:this.issues}}};function P(e,t="[chartbuddy]",r={}){let{issues:n,errors:i,warnings:a}=v(e,r);if(a.length>0&&console.warn(O(a,t)),i.length>0)throw new x(O(i,t),n)}var y=class e{static{this.globalInstance=null}constructor(t){this.listeners=new Map,this.debugMode=t?.debug??!1}static global(){return e.globalInstance||(e.globalInstance=new e({debug:!1})),e.globalInstance}static resetGlobal(){e.globalInstance=null}on(t,r){return this.listeners.has(t)||this.listeners.set(t,new Set),this.listeners.get(t).add(r),()=>{this.off(t,r)}}once(t,r){let n=i=>{this.off(t,n),r(i)};return this.on(t,n)}emit(t,r){let n=this.listeners.get(t);if(this.debugMode&&console.log(`[EventBus] Emitting "${t}"`,r),!n)return;Array.from(n).forEach(a=>{try{a(r)}catch(s){console.error(`[EventBus] Error in listener for "${t}":`,s)}})}off(t,r){let n=this.listeners.get(t);n&&(r?(n.delete(r),n.size===0&&this.listeners.delete(t)):this.listeners.delete(t))}clear(){this.listeners.clear()}listenerCount(t){let r=this.listeners.get(t);return r?r.size:0}eventNames(){return Array.from(this.listeners.keys())}removeListeners(t){t.forEach(r=>{this.listeners.delete(r)})}};var M={CREATED:"chart.created",TYPE_CHANGED:"chart.type_changed",DELETED:"chart.deleted",SAVED:"chart.saved",DOWNLOADED:"chart.downloaded",OPENED:"chart.opened",CD_CHANGED:"chart.cd_changed"};var Te="chartbuddy-webapp-shell-chart-config",Re="#ffffff";function De(){try{if(typeof crypto<"u"&&typeof crypto.randomUUID=="function")return crypto.randomUUID()}catch{}return`i${Date.now().toString(36)}${Math.random().toString(36).slice(2,10)}`}function Oe(e){let t=String(e??"").trim();if(!t)throw new Error("[chartbuddy/embed] instanceId must be a non-empty string");if(!/^[A-Za-z0-9_.:-]+$/.test(t))throw new Error('[chartbuddy/embed] instanceId may only contain letters, digits, "_", ".", ":", "-"');return t}function Pe(e){let t=e?Oe(e):De(),r=`cb-${t}`;return{instanceId:t,app:`${r}-app`,chart:`${r}-chart`,status:`${r}-status`,logs:`${r}-logs`,toggle:`${r}-toggle`,reset:`${r}-reset`,importBtn:`${r}-import`,importFile:`${r}-import-file`,overlay:`${r}-edit-overlay`}}function _(e){return`chartbuddy-embed-chart-config:${e}`}function ie(e){return`chartbuddy-embed-chart-size:${e}`}function Me(e){try{let t=window.localStorage.getItem(_(e));if(!t)return null;let r=JSON.parse(t);return de(r)?r:null}catch{return null}}function _e(e,t){try{window.localStorage.setItem(_(e),JSON.stringify(t))}catch{}}function Le(e,t){if(e.persist===!0){let r=Me(t);if(r)return r}return e.chartData}var ae="__CHARTBUDDY_INSIGHTS__",E=new Map;function oe(){if(!(typeof window>"u"))try{window[ae]=L()}catch{}}function Be(e){if(E.has(e.instanceId))throw new Error(`[chartbuddy/embed] duplicate instanceId "${e.instanceId}" \u2014 each Insight on the page must have a unique id. Reusing one silently overwrote the registry entry and could cross-contaminate persisted state.`);E.set(e.instanceId,e),oe()}function Fe(e){E.get(e.instanceId)===e&&(E.delete(e.instanceId),oe())}function L(){let e={};return E.forEach((t,r)=>{e[r]=t}),e}async function se(e={}){let t={},r=L();for(let[n,i]of Object.entries(r)){let a={chartData:i.getChartData()};e.png&&(a.pngBase64=await i.toPngBase64({scale:e.scale,background:e.background})),t[n]=a}return{schemaVersion:1,version:F,charts:t}}function He(e){let t=typeof e=="string"?document.querySelector(e):e;if(!t)throw new Error(`[chartbuddy/embed] mount target not found: ${String(e)}`);return t}function de(e){return!!e&&typeof e=="object"&&typeof e.chartType=="string"&&Array.isArray(e.seriesData)}function re(e,t){P(e,`[chartbuddy/embed] ${t}:`)}function Ve(e,t,r){if(e.innerHTML="",e.setAttribute("data-cb-instance",r.instanceId),e.style.position=e.style.position||"relative",e.style.minHeight||(e.style.minHeight="240px"),t){let d=document.createElement("div");d.className="webapp-toolbar",d.innerHTML=`
131
+ <button id="${r.reset}" type="button">Reset All</button>
132
+ <button id="${r.importBtn}" type="button">Import Config</button>
133
+ <input type="file" id="${r.importFile}" style="display:none" accept=".json" />
134
+ `,e.appendChild(d)}let n=document.createElement("div");n.id=r.app,n.className="cb-app-container",n.style.cssText="width:100%;height:100%;min-height:240px;position:relative;box-sizing:border-box;";let i=document.createElement("div");i.id=r.chart,i.className="cb-chart-container",i.style.cssText="width:100%;height:100%;min-height:240px;position:relative;box-sizing:border-box;",n.appendChild(i),e.appendChild(n);let a=document.createElement("div");a.id=r.status,a.className="cb-status",a.style.cssText="display:none;margin-top:8px;font-size:12px;color:#5b616e;",a.textContent="Loading ChartBuddy\u2026",e.appendChild(a);let s=document.createElement("div");s.id=r.logs,s.className="cb-logs",s.style.display="none",e.appendChild(s)}function $e(e,t){e.innerHTML="",e.setAttribute("data-cb-instance",t.instanceId),e.style.position=e.style.position||"relative";let r=document.createElement("div");return r.id=t.chart,r.className="cb-chart-container cb-chart-container--view",r.style.cssText="width:100%;height:100%;min-height:240px;position:relative;box-sizing:border-box;",e.appendChild(r),r}function Ne(e,t){let r=document.getElementById(e);r||(r=document.createElement("div"),r.id=e,r.className="cb-edit-overlay",r.style.cssText="position:fixed;inset:0;pointer-events:none;z-index:1000;",document.body.appendChild(r)),r.setAttribute("data-cb-instance",t)}async function je(e,t,r){let n=window.ChartBuddyInitEditor;if(typeof n!="function")throw new Error("[chartbuddy/embed] ChartBuddyInitEditor not found after loading the engine. Is the ChartBuddy engine bundle present?");Ne(t.overlay,t.instanceId);let i=r.persist===!0,a=await n({root:e,chartContainerId:t.chart,statusId:t.status,logsId:t.logs,toggleSpreadsheetBtnId:t.toggle,editOverlaySelector:`#${t.overlay}`,hostOverrides:r.host,chartData:r.chartData??null,persist:i,persistKey:i?_(t.instanceId):void 0,persistSizeKey:i?ie(t.instanceId):void 0,enableSpreadsheet:!1});if(!a||!a.chart)throw new Error("[chartbuddy/embed] editor boot returned null");return a}function le(e,t){let r=Math.max(1,Math.round(t.clientWidth||t.offsetWidth||640)),n=Math.max(1,Math.round(t.clientHeight||t.offsetHeight||360));e.cd.canvas||(e.cd.canvas={}),e.cd.canvas.width=r,e.cd.canvas.height=n}function Ge(e,t,r){let n=window.ChartBuddyCreateHeadlessChart;if(typeof n!="function")throw new Error("[chartbuddy/embed] ChartBuddyCreateHeadlessChart not found after loading the engine.");let i=Math.max(1,Math.round(r.clientWidth||r.offsetWidth||640)),a=Math.max(1,Math.round(r.clientHeight||r.offsetHeight||360)),s=n(e,t??null,{width:i,height:a});return le(s,r),typeof s.drawChart=="function"&&s.drawChart(),s}function Ue(e,t){if(!e||!t)return;let r=t,n=["canvas","title","subtitle","legend","footnote"];for(let[i,a]of Object.entries(r))if(a!=null)if(n.includes(i)&&typeof a=="object"&&!Array.isArray(a))e.cd[i]={...e.cd[i]||{},...a};else if(i==="axes"&&typeof a=="object"&&!Array.isArray(a)){let s={...e.cd.axes||{}};for(let[d,o]of Object.entries(a)){if(o==null||typeof o!="object"){s[d]=o;continue}let l=s[d]||{};s[d]={...l,...o,labels:o.labels?{...l.labels||{},...o.labels,format:{...l.labels?.format||{},...o.labels.format||{}}}:l.labels,axisTitle:o.axisTitle?{...l.axisTitle||{},...o.axisTitle}:l.axisTitle,gridlines:o.gridlines?{...l.gridlines||{},...o.gridlines}:l.gridlines,tickMarks:o.tickMarks?{...l.tickMarks||{},...o.tickMarks}:l.tickMarks}}e.cd.axes=s}else if(i==="annotations"&&typeof a=="object"&&!Array.isArray(a)){let s=e.cd.annotations||{},d={...s,...a};for(let o of["dataLabels","totals","levelLines","levelArrows","cagrArrows"])a[o]&&typeof a[o]=="object"&&!Array.isArray(a[o])&&(d[o]={...s[o]||{},...a[o],...a[o].format||s[o]?.format?{format:{...s[o]?.format||{},...a[o].format||{}}}:{}});e.cd.annotations=d}else i!=="seriesData"&&i!=="seriesDataFormatted"&&i!=="seriesDataColors"&&(e.cd[i]=a);z(e.cd),Array.isArray(r.seriesData)?e.updateData(r.seriesData,r.seriesDataFormatted??null,r.seriesDataColors??null):typeof e.drawChart=="function"&&e.drawChart()}function C(e){let t=e?.cdOriginal??e?.cd;if(!t)return null;try{return JSON.parse(JSON.stringify(t))}catch{return{...t}}}function ze(e,t,r){let n=new Blob([t],{type:r}),i=URL.createObjectURL(n),a=document.createElement("a");a.href=i,a.download=e,a.rel="noopener",document.body.appendChild(a),a.click(),a.remove(),setTimeout(()=>URL.revokeObjectURL(i),1e3)}async function ce(e,t={},r={}){if(!e?.exporter)throw new Error("[chartbuddy/embed] chart exporter unavailable");let n=t.scale??4,i=t.background!==void 0?t.background:r.background;return typeof e.exporter.prepareChartForExport=="function"&&await e.exporter.prepareChartForExport(),e.exporter.generateImageBlob(!1,"export",n,{background:i})}function Ye(e){return new Promise((t,r)=>{let n=new FileReader;n.onload=()=>{let i=String(n.result||""),a=i.indexOf(",");t(a>=0?i.slice(a+1):i)},n.onerror=()=>r(n.error||new Error("[chartbuddy/embed] FileReader failed")),n.readAsDataURL(e)})}async function qe(e,t={}){let r=await ce(e,t,{background:null});await e.exporter.downloadBlob(r,"chart.png")}async function Ke(e,t){if(!e?.exporter?.bootDragExportWidgetGoogleSlides)throw new Error("[chartbuddy/embed] drag export unavailable");let r=t?.getBoundingClientRect?.(),n=r?{x:Math.max(12,r.left+56),y:Math.max(12,r.top+12)}:{x:24,y:24};await e.exporter.bootDragExportWidgetGoogleSlides(void 0,n,{skipTrialGate:!0})}function ue(e){let t=e.resolveAssetBase||(r=>"");return class{#a;#d=null;#n=null;#h=null;#u=null;#r=!1;#f;#l;#g;#e;#c=new Map;#m=0;#x=0;#s=null;#i=0;#o=!1;constructor(n,i={}){if(typeof document>"u")throw new Error("[chartbuddy/embed] Insight requires a browser environment");this.container=He(n),this.assetBase=t(i.assetBase),this.#l=i,this.#g=i.toolbar===!0,this.#e=Pe(i.instanceId),this.instanceId=this.#e.instanceId,this.chartContainerId=this.#e.chart;let a=i.editable===!0;this.#a=a?"edit":"view",i.chartData!==void 0&&re(i.chartData,"chartData"),Be(this);let s=Le(i,this.instanceId);this.#f=e.ensureEngineReady(this.assetBase).then(async()=>{this.#r||(a?await this.#A(s):await this.#I(s),!this.#r&&(this.#v(),this.#p("ready")))}).catch(d=>{let o=document.getElementById(this.#e.status);throw o||(o=document.createElement("div"),o.id=this.#e.status,o.className="cb-status",this.container.appendChild(o)),o.style.display="",o.style.marginTop="8px",o.style.fontSize="12px",o.textContent="\u274C "+(d&&d.message?d.message:String(d)),o.style.color="#b42318",console.error(d),d})}get mode(){return this.#a}get ready(){return this.#f}get chart(){return this.#t()}#t(){return(this.#a==="view"?this.#n:this.#d?.chart)??null}#p(n,...i){let a=this.#c.get(n);if(!(!a||a.size===0))for(let s of[...a])try{s(...i)}catch(d){console.error(`[chartbuddy/embed] ${n} handler threw:`,d)}}on(n,i){if(typeof i!="function")throw new Error(`[chartbuddy/embed] on('${n}') requires a function handler`);let a=this.#c.get(n);return a||(a=new Set,this.#c.set(n,a)),a.add(i),()=>this.off(n,i)}off(n,i){this.#c.get(n)?.delete(i)}isDirty(){return this.#m!==this.#x}getRevision(){return this.#m}#v(){this.#x=this.#m}#y(){this.#m+=1,this.#p("change",this.getChartData())}#T(){if(!(this.#o||this.#r)){if(typeof window>"u"){this.#y();return}window.clearTimeout(this.#i),this.#i=window.setTimeout(()=>{this.#i=0,this.#r||this.#y()},50)}}#C(){this.#E(),this.#s=n=>{let i=this.#t(),a=i?.cd?.id??i?.cdOriginal?.id;!a||n?.chartId!==a||this.#T()};try{y.global().on(M.CD_CHANGED,this.#s)}catch{this.#s=null}}#E(){if(this.#s){try{y.global().off(M.CD_CHANGED,this.#s)}catch{}this.#s=null}}#w(n){this.#a!==n&&(this.#a=n,this.#p("mode",n))}#b(){this.#E(),typeof window<"u"&&this.#i&&(window.clearTimeout(this.#i),this.#i=0);try{this.#h?.destroy()}catch{}this.#h=null;try{this.#u?.disconnect()}catch{}this.#u=null;try{this.#n&&this.#n.remove?.()}catch(n){console.warn("[chartbuddy/embed] view chart remove failed:",n)}this.#n=null;try{this.#d?.destroyRuntime?.()}catch(n){console.warn("[chartbuddy/embed] destroyRuntime failed:",n)}this.#d=null,document.getElementById(this.#e.overlay)?.remove()}#k(n,i){this.#h=new w(n,{onDownload:()=>this.downloadPng(),onDragExport:()=>this.dragExport(),onEdit:()=>this.enterEditMode(),onDone:()=>this.exitEditMode()},i)}async#I(n){this.#b(),this.#w("view");let i=$e(this.container,this.#e);this.#o=!0;try{let a=Ge(this.#e.chart,n,i);this.#n=a}finally{this.#o=!1}if(this.#C(),typeof ResizeObserver<"u"){let a=0;this.#u=new ResizeObserver(()=>{cancelAnimationFrame(a),a=requestAnimationFrame(()=>{!this.#n||this.#r||(le(this.#n,i),this.#n.drawChart?.())})}),this.#u.observe(i)}this.#k(i,"view")}async#A(n){this.#b(),this.#w("edit"),Ve(this.container,this.#g,this.#e),this.#o=!0;try{let s=await je(this.container,this.#e,{...this.#l,editable:!0,chartData:n,toolbar:this.#g});this.#d=s}finally{this.#o=!1}this.#C();let i=document.getElementById(this.#e.status);i&&(i.textContent="",i.style.display="none");let a=document.getElementById(this.#e.chart);a&&this.#k(a,"edit")}focus(){let n=this.#t();if(!n||this.#a!=="edit")return;let i=window.ChartBuddyFocusEditor;if(typeof i=="function"){i(n);return}try{document.getElementById(this.#e.chart)?.dispatchEvent(new PointerEvent("pointerdown",{bubbles:!0}))}catch{}}setChartData(n){re(n,"setChartData");let i=this.#t();if(!i)throw new Error("[chartbuddy/embed] setChartData called before ready");this.#o=!0;try{Ue(i,n)}finally{typeof window<"u"&&this.#i&&(window.clearTimeout(this.#i),this.#i=0),this.#o=!1}this.#y()}setData(n){if(!Array.isArray(n))throw new Error("[chartbuddy/embed] setData requires a 2D seriesData array");this.setChartData({seriesData:n})}update(n){if(n===void 0){let i=this.#t();if(!i)throw new Error("[chartbuddy/embed] update called before ready");typeof i.drawChart=="function"&&i.drawChart();return}this.setChartData(n)}getChartData(){return C(this.#t())}async toPngBlob(n={}){let i=this.#t();if(!i)throw new Error("[chartbuddy/embed] toPngBlob called before ready");return ce(i,n,{background:Re})}async toPngBase64(n={}){let i=await this.toPngBlob(n);return Ye(i)}async downloadPng(n={}){let i=this.#t();if(!i)throw new Error("[chartbuddy/embed] downloadPng called before ready");await qe(i,n)}async dragExport(){let n=this.#t();if(!n)throw new Error("[chartbuddy/embed] dragExport called before ready");let i=document.getElementById(this.#e.chart);await Ke(n,i)}exportConfig(){let n=C(this.#t());if(!n)throw new Error("[chartbuddy/embed] exportConfig called before ready");ze("chartbuddy-chart.json",JSON.stringify(n,null,2),"application/json")}#S(n){this.#l.persist!==!0||!n||!de(n)||_e(this.instanceId,n)}async enterEditMode(){if(this.#r||this.#a==="edit")return;let n=C(this.#n)??this.#l.chartData;await e.ensureEngineReady(this.assetBase),await this.#A(n)}async exitEditMode(){if(this.#r||this.#a==="view")return;let n=C(this.#d?.chart),i=n??this.#l.chartData;this.#S(i),await e.ensureEngineReady(this.assetBase),await this.#I(i),this.#v(),n&&this.#p("change",n)}destroy(){this.#r||(this.#r=!0,this.#S(C(this.#t())),this.#b(),this.#c.clear(),this.container.innerHTML="",this.container.removeAttribute("data-cb-instance"),Fe(this))}}}function me(e){try{e?(window.localStorage.removeItem(_(e)),window.localStorage.removeItem(ie(e))):window.localStorage.removeItem(Te)}catch{}}var We=(()=>{let e="";try{let t=import.meta?.url;t&&(e=new URL("./",t).href)}catch{}if(!e)try{let t=typeof document<"u"&&document.currentScript?document.currentScript.src:"";t&&(e=new URL("./",t).href)}catch{}return e.replace(/\/api\/embed\/$/,"/embed/")})(),Xe=["ts/shared/libraries/d3.min.js","ts/shared/libraries/DOMPurify.min.js","webapp-entry.js"],Je=["webapp-entry.css"],B=null;function Ze(e){let t=e||globalThis.CHARTBUDDY_EDITOR_BASE||We;if(!t)throw new Error('[chartbuddy/embed] could not determine the engine asset base. Pass { assetBase } pointing at the directory that holds webapp-entry.js (must end with "/").');return t.endsWith("/")?t:t+"/"}function Qe(e){Je.forEach(t=>{let r=e+t;if(document.querySelector(`link[data-cb-embed="${t}"]`))return;let n=document.createElement("link");n.rel="stylesheet",n.href=r,n.setAttribute("data-cb-embed",t),document.head.appendChild(n)})}function et(e){return new Promise((t,r)=>{let n=document.querySelector(`script[data-cb-embed="${e}"]`);if(n){n.getAttribute("data-cb-loaded")==="true"?t():(n.addEventListener("load",()=>t()),n.addEventListener("error",()=>r(new Error(`[chartbuddy/embed] failed to load ${e}`))));return}let i=document.createElement("script");i.src=e,i.async=!1,i.setAttribute("data-cb-embed",e),i.addEventListener("load",()=>{i.setAttribute("data-cb-loaded","true"),t()}),i.addEventListener("error",()=>r(new Error(`[chartbuddy/embed] failed to load ${e}`))),document.head.appendChild(i)})}function tt(e){return B||(window.__CHARTBUDDY_NO_AUTOBOOT__=!0,window.__WEBAPP_ASSET_BASE__=e,Qe(e),B=Xe.reduce((t,r)=>t.then(()=>et(e+r)),Promise.resolve()),B)}var nt=ue({resolveAssetBase:Ze,ensureEngineReady:e=>tt(e)}),nn={Insight:nt,clearPersistedChart:me,getInsights:L,snapshotInsights:se,validateChartData:v};export{ae as CHARTBUDDY_INSIGHTS_GLOBAL,x as ChartDataValidationError,nt as Insight,P as assertValidChartData,me as clearPersistedChart,nn as default,O as formatValidationIssues,L as getInsights,se as snapshotInsights,v as validateChartData,F as version};
135
+ //# sourceMappingURL=chartbuddy-embed.mjs.map