@malloydata/render 0.0.354 → 0.0.355

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.
@@ -63,7 +63,7 @@ ${n}}`,r}constructor(t={},n){if(this._read=!1,n!==void 0&&(this._parent=n),t.eq!
63
63
  drill:
64
64
  ${n.map(i=>` ${i}`).join(`,
65
65
  `)}
66
- } +`),r+=" { select: * }",r}class Ws{constructor(t,n,r){this.cell=t,this.field=n,this.parent=r}get literalValue(){}isNull(){return this instanceof x7}isArray(){return this instanceof v7}isRecord(){return this instanceof Y2}isRepeatedRecord(){return this instanceof G2}isRecordOrRepeatedRecord(){return this.isRepeatedRecord()||this.isRecord()}isNest(){return this.isRepeatedRecord()||this.isRecord()||this.isArray()}isNumber(){return this instanceof w7}isDate(){return this instanceof $7}isTime(){return this.isDate()||this.isTimestamp()}isJSON(){return this instanceof _7}isString(){return this instanceof k7}isTimestamp(){return this instanceof S7}isBoolean(){return this instanceof E7}asCell(){if(this instanceof v7||this instanceof G2||this instanceof Y2||this instanceof w7||this instanceof $7||this instanceof _7||this instanceof k7||this instanceof S7||this instanceof E7||this instanceof x7||this instanceof hR)return this;throw new Error("Not a cell")}root(){return this.parent?this.parent.root():this.asCell()}getPathInfo(t){const n=t.split("/"),r=n.filter(s=>s==="..").length+1,i=n.filter(s=>s!==".."&&s!=="");return{levelsUp:r,pathSegments:i}}getParentRecord(t){let n=this.asCell();for(;n&&t>0;){for(n=n.parent;n!=null&&n.isArray();)n=n.parent;t--}if(!(n!=null&&n.isRecord()))throw new Error(`Parent ${t} levels up was not a record`);return n}getRelativeCell(t){try{const{levelsUp:n,pathSegments:r}=this.getPathInfo(t);return this.getParentRecord(n).cellAtPath(r)}catch{return}}cellAt(t){return typeof t=="string"?this.cellAtPath(JSON.parse(t)):this.cellAtPath(t)}cellAtPath(t){if(t.length===0)return this.asCell();throw new Error(`${this.constructor.name} cannot contain columns`)}compareTo(t){return 0}canDrill(){return $fe(this.asCell())}getStableDrillQuery(){return uR(this.asCell())}getStableDrillClauses(){return b7(this.asCell())}getDrillExpressions(){return fR(this.asCell())}getDrillEntries(){return Sfe(this.asCell())}getStableDrillQueryMalloy(){return dR(this.asCell())}getDrillQueryMalloy(){return _fe(this.asCell())}}class v7 extends Ws{constructor(t,n,r){super(t,n,r),this.cell=t,this.field=n,this.parent=r,this.values=[];for(const i of this.cell.array_value)this.values.push(mR.from(i,this.field.elementField,this))}get value(){return this.values}}class G2 extends Ws{constructor(t,n,r){var s;super(t,n,r),this.cell=t,this.field=n,this.parent=r,this.rows=[],this.fieldValueSets=new Map;for(let a=0;a<this.cell.array_value.length;a++){const o=this.cell.array_value[a];if(!("record_value"in o))throw new Error("Expected record cell in RepeatedRecordCell");const l=new Y2(o,this.field.nestedRecordField,this);this.rows.push(l)}for(const a of this.rows)for(const o of a.columns){const l=o.field;let u=this.fieldValueSets.get(l.name);u===void 0&&(u=new Set,this.fieldValueSets.set(l.name,u)),u.add(o.value)}for(const[a,o]of this.fieldValueSets.entries())this.field.registerValueSetSize(a,o.size);const i=this.field.getPlugins();for(const a of i)(s=a.processData)==null||s.call(a,this.field,this)}get value(){return this.rows}get values(){return this.rows}}class kfe extends G2{constructor(t,n){super(t,n,void 0),this.cell=t,this.field=n}}class Y2 extends Ws{constructor(t,n,r){super(t,n,r),this.cell=t,this.field=n,this.parent=r,this.cells={};for(let i=0;i<n.fields.length;i++){const s=n.fields[i],a=mR.from(t.record_value[i],s,this);this.cells[s.name]=a}}get rows(){return[this]}get value(){return this.cells}column(t){return this.cells[t]}get columns(){return this.field.fields.map(t=>this.column(t.name))}allCellValues(){return Object.fromEntries(Object.entries(this.cells).map(([t,n])=>[t,n.value]))}cellAtPath(t){if(t.length===0)return this.asCell();{const[n,...r]=t,i=this.cells[n];if(i===void 0)throw new Error(`No such column ${n} in ${this.field.path}`);return i.cellAtPath(r)}}}class x7 extends Ws{constructor(t,n,r){super(t,n,r),this.cell=t,this.field=n,this.parent=r,this.field.registerNullValue()}get value(){return null}get literalValue(){return{kind:"null_literal"}}}class w7 extends Ws{constructor(t,n,r){super(t,n,r),this.cell=t,this.field=n,this.parent=r,this.field.registerValue(this.value)}get value(){return this.cell.number_value}get stringValue(){return this.cell.string_value}get subtype(){return this.cell.subtype}needsStringPrecision(){return this.subtype==="bigint"}numberValue(){return this.value}bigint(){return this.stringValue!==void 0?BigInt(this.stringValue):BigInt(this.value)}compareTo(t){if(!t.isNumber())return 0;if(this.stringValue!==void 0&&t.stringValue!==void 0){const r=this.bigint(),i=t.bigint();return r>i?1:r<i?-1:0}const n=this.value-t.value;return n>0?1:n===0?0:-1}get literalValue(){return{kind:"number_literal",number_value:this.value,string_value:this.stringValue}}}class $7 extends Ws{constructor(t,n,r){super(t,n,r),this.cell=t,this.field=n,this.parent=r,this.field.registerValue(this.value)}get value(){return new Date(this.cell.date_value)}get timeframe(){return this.field.timeframe}compareTo(t){return t.isTime()?this.value>t.value?1:this.value<t.value?-1:0:0}get literalValue(){return{kind:"date_literal",date_value:this.cell.date_value,granularity:this.timeframe}}}class S7 extends Ws{constructor(t,n,r){super(t,n,r),this.cell=t,this.field=n,this.parent=r,this.field.registerValue(this.value)}get value(){return new Date(this.cell.timestamp_value)}get timeframe(){return this.field.timeframe}compareTo(t){return t.isTime()?this.value>t.value?1:this.value<t.value?-1:0:0}get literalValue(){return{kind:"timestamp_literal",timestamp_value:this.cell.timestamp_value,granularity:this.timeframe}}}class _7 extends Ws{constructor(t,n,r){super(t,n,r),this.cell=t,this.field=n,this.parent=r}get value(){try{return JSON.parse(this.cell.json_value)}catch{return this.cell.json_value}}compareTo(t){const n=this.value.toString(),r=t.toString();return n===r?0:n>r?1:-1}}class hR extends Ws{constructor(t,n,r){super(t,n,r),this.cell=t,this.field=n,this.parent=r}get value(){try{return JSON.parse(this.cell.sql_native_value)}catch{return this.cell.sql_native_value}}compareTo(t){const n=this.value.toString(),r=t.toString();return n===r?0:n>r?1:-1}}class k7 extends Ws{constructor(t,n,r){super(t,n,r),this.cell=t,this.field=n,this.parent=r,this.field.registerValue(this.value)}get value(){return this.cell.string_value}compareTo(t){return t.isString()?this.value.toLocaleLowerCase().localeCompare(t.value.toLocaleLowerCase()):0}get literalValue(){return{kind:"string_literal",string_value:this.cell.string_value}}}class E7 extends Ws{constructor(t,n,r){super(t,n,r),this.cell=t,this.field=n,this.parent=r,this.field.registerValue(this.value)}get value(){return this.cell.boolean_value}compareTo(t){return this.value===t.value?0:this.value?1:-1}get literalValue(){return{kind:"boolean_literal",boolean_value:this.cell.boolean_value}}}const mR={from(e,t,n){switch(e.kind){case"array_cell":{if(t instanceof ou)return new G2(e,t,n);if(t instanceof Ud)return new v7(e,t,n);throw new Error("Expected record data to be associated with record field")}case"record_cell":{if(t instanceof Ho)return new Y2(e,t,n);throw new Error("Expected record data to be associated with record field")}case"null_cell":return new x7(e,t,n);case"number_cell":{if(t instanceof s0)return new w7(e,t,n);throw new Error("Expected number data to be associated with number field")}case"date_cell":{if(t instanceof a0)return new $7(e,t,n);throw new Error("Expected date data to be associated with date field")}case"json_cell":{if(t instanceof u0)return new _7(e,t,n);throw new Error("Expected JSON data to be associated with JSON field")}case"string_cell":{if(t instanceof Bd)return new k7(e,t,n);throw new Error("Expected string data to be associated with string field")}case"timestamp_cell":{if(t instanceof o0)return new S7(e,t,n);throw new Error("Expected timestamp data to be associated with timestamp field")}case"boolean_cell":{if(t instanceof c0)return new E7(e,t,n);throw new Error("Expected boolean data to be associated with boolean field")}case"sql_native_cell":{if(t instanceof l0)return new hR(e,t,n);throw new Error("Expected sql_native data to be associated with sql_native field")}}}},Efe={url:"",range:{start:{line:0,character:0},end:{line:0,character:0}}};function pR(e){return(e==null?void 0:e.location)??Efe}class gR{constructor(){this.logs=[]}reset(){this.logs=[]}warn(t,n){this.add("warn",t,n)}error(t,n){this.add("error",t,n)}add(t,n,r){const{url:i,range:s}=r?pR(r):pR();this.logs.push({url:i,range:s,severity:t,message:n})}collectUnreadTags(t,n){const r=t.getUnreadProperties();for(const i of r){const s=i.join(".");this.warn(`Unknown render tag '${s}' on field '${n}'`,t)}}getLogs(){return[...this.logs]}}function Cfe(e){const n=e.tag.tag("image");if(!n)return{};const r=n.text("width"),i=n.text("height");let s,a;const o=n.tag("alt");return o&&(a=o.text("field"),a||(s=o.text())),{width:r??void 0,height:i??void 0,alt:s,altField:a}}function Afe(e){const n=e.tag.tag("link");return n?{linkField:n.text("field")??void 0,urlTemplate:n.text("url_template")??void 0}:{}}function Mfe(e){return{isListDetail:e.tag.has("list_detail")}}function Ffe(e){const t=e.text("currency"),n=t?Gfe(t):null;if(n)return{symbol:n.symbol,scale:n.scale,decimals:n.decimals,suffixFormat:"lower"};let r="$";switch(t){case"euro":r="€";break;case"pound":r="£";break;case"usd":default:r="$";break}const i=e.text("currency","scale"),s=_R(i),a=e.numeric("currency","decimals")??void 0,o=e.text("currency","suffix");let l="lower";return o?l=o:s&&(l="letter"),{symbol:r,scale:s,decimals:a,suffixFormat:l}}function Tfe(e){const t=e.text("number"),n=t?Hfe(t):null;if(n)return{scale:n.scale,decimals:n.decimals,isId:n.isId,isBig:!1,suffixFormat:"lower"};const r=e.text("number","scale"),i=_R(r);if(i){const s=e.numeric("number","decimals")??2,o=e.text("number","suffix")??"letter";return{scale:i,decimals:s,suffixFormat:o}}return t==="big"?{isBig:!0}:{formatString:t??void 0}}function Dfe(e){const t=e.tag;if(t.has("currency"))return{mode:"currency",currency:Ffe(t)};if(t.has("percent"))return{mode:"percent"};if(t.has("duration")){const n=t.text("duration"),r=t.has("duration","terse");return{mode:"duration",duration:{unit:n??lt.Seconds,terse:r}}}if(t.has("number")){if(e.isTime()){const n=t.text("number");if(n)return{mode:"dateFormat",formatString:n}}return{mode:"number",number:Tfe(t)}}return{mode:"default"}}const yR={xs:28,sm:64,md:128,lg:256,xl:384,"2xl":512};function Ofe(e){const t=e.tag.tag("column");if(!t)return;let n=null;const r=t.text("width"),i=t.numeric("width");r&&yR[r]?n=yR[r]:i&&(n=i);const s=t.numeric("height")??null,a=t.text("word_break")==="break_all";return{width:n,height:s,wordBreak:a}}function Rfe(e){const t=e.tag,n=t.tag("table"),r=n==null?void 0:n.tag("size"),i=(r==null?void 0:r.text())==="fill";let s;t.has("transpose")&&(s=t.numeric("transpose","limit")??void 0);let a;if(t.has("pivot")){const o=t.textArray("pivot","dimensions");a=o&&o.length>0?o:void 0}return{fillSize:i,transposeLimit:s,pivotDimensions:a}}function Nfe(e){const n=e.tag.tag("dashboard");let r=361;const i=n==null?void 0:n.tag("table","max_height");return(i==null?void 0:i.text())==="none"?r=null:i!=null&&i.numeric()&&(r=i.numeric()),{maxTableHeight:r}}function Ife(e){const t=e.renderAs(),n=e.tag,r=n.text("label");r!==void 0&&e.setResolvedLabel(r);const i=Ofe(e);i&&e.setColumnConfig(i),n.tag("tooltip"),n.tag("break");const s=n.tag("size");switch(s&&s.numeric("height"),t){case"image":e.setTagConfig(Cfe(e));break;case"link":e.setTagConfig(Afe(e));break;case"list":e.setTagConfig(Mfe(e));break;case"cell":e.setTagConfig(Dfe(e));break;case"table":e.setTagConfig(Rfe(e));break;case"dashboard":e.setTagConfig(Nfe(e));break}}class bR{constructor(t,n=[],r={},i,s){this.pluginRegistry=n,this.pluginOptions=r,this.onPluginCreateError=i,this.logCollector=s??new gR,this.registry=new Map,this.rootField=new wfe({name:"root",type:{kind:"array_type",element_type:{kind:"record_type",fields:t.schema.fields.filter(a=>a.kind==="dimension"||a.kind==="calculate")}},annotations:t.annotations},{modelTag:M7(t.model_annotations,"## "),queryTimezone:t.query_timezone}),this.registerFields(this.rootField)}instantiatePluginsForField(t){const n=[];for(const r of this.pluginRegistry)try{if(r.matches(t,t.tag,oR(t))){const i=this.pluginOptions[r.name],s=this.rootField.modelTag,a=r.create(t,i,s);n.push(a)}}catch(i){const s=i instanceof Error?i.message:String(i);this.logCollector.error(`Plugin ${r.name} failed for field '${t.key}': ${s}`),this.onPluginCreateError&&this.onPluginCreateError(i,r,t,n)}return t.setPlugins(n),n}registerFields(t){const n=t.key;if(!this.registry.has(n)){const r=this.instantiatePluginsForField(t),i={field:t,renderProperties:{field:t,renderAs:t.renderAs(),sizingStrategy:"fit",properties:{},errors:[]},plugins:r},s=this.populateRenderFieldProperties(t,r);i.renderProperties.properties=s.properties,i.renderProperties.errors=s.errors,this.registry.set(n,i),Ife(t),this.validateFieldTags(t),this.markDeclaredTags(t,r)}if(t.isNest())for(const r of t.fields)this.registerFields(r)}populateRenderFieldProperties(t,n){const r={},i=[];for(const s of n)r[s.name]=s.getMetadata();return{properties:r,errors:i}}getAllFields(){return Array.from(this.registry.values()).map(t=>t.field)}getRootField(){return this.rootField}getPluginsForField(t){const n=this.registry.get(t);return n?n.plugins:[]}getFieldEntry(t){return this.registry.get(t)}validateFieldTags(t){var m;const n=t.tag,r=oR(t),i=this.logCollector,s=["viz","bar_chart","line_chart","list","list_detail","pivot","dashboard","transpose","table"],a=[Gt.RepeatedRecord,Gt.Record];for(const p of s)n.has(p)&&!a.includes(r)&&i.error(`Tag '${p}' on field '${t.name}' requires a nested query, but field is ${r}`,n.tag(p));n.has("link")&&r!==Gt.String&&i.error(`Tag 'link' on field '${t.name}' requires a string field, but field is ${r}`,n.tag("link")),n.has("image")&&r!==Gt.String&&i.error(`Tag 'image' on field '${t.name}' requires a string field, but field is ${r}`,n.tag("image"));const o=["number","currency","percent","duration"];for(const p of o)n.has(p)&&r!==Gt.Number&&r!==Gt.Array&&!(p==="number"&&(r===Gt.Date||r===Gt.Timestamp))&&i.error(`Tag '${p}' on field '${t.name}' requires a numeric field, but field is ${r}`,n.tag(p));const l=n.tag("number");(l==null?void 0:l.scalarType())==="number"&&i.error(`Tag 'number' on field '${t.name}' has a bare numeric value. Use a quoted format string instead, e.g. # number="#,##0.00"`,l);const u=n.text("viz");if(u!==void 0){const p=["bar","line","table","dashboard"];p.includes(u)||i.error(`Invalid viz type '${u}' on field '${t.name}'. Valid types: ${p.join(", ")}`,n.tag("viz"))}const c=n.text("size");if(c!==void 0){const p=["fill","spark","xs","sm","md","lg","xl","2xl"];!p.includes(c)&&!((m=n.tag("size"))!=null&&m.has("width"))&&i.warn(`Unknown size '${c}' on field '${t.name}'. Valid presets: ${p.join(", ")}`,n.tag("size"))}if(n.has("currency")){const p=n.text("currency");if(p!==void 0){const g=["usd","eur","gbp","euro","pound"];p.match(/^(euro|pound|usd|eur|gbp)/i)||i.error(`Unknown currency '${p}' on field '${t.name}'. Valid codes: ${g.join(", ")}`,n.tag("currency"))}}if(n.has("duration")){const p=n.text("duration");if(p!==void 0){const g=["nanoseconds","microseconds","milliseconds","seconds","minutes","hours","days"];g.includes(p)||i.error(`Unknown duration unit '${p}' on field '${t.name}'. Valid units: ${g.join(", ")}`,n.tag("duration"))}}if(t.isNest()){const p=n.tag("viz");if(p){const g=new Set(t.fields.map(y=>y.name));for(const y of["x","y","series"]){const b=p.textArray(y),v=b??[],x=p.text(y);x&&!b&&v.push(x);for(const $ of v)g.has($)||i.error(`Chart field reference '${$}' for '${y}' on '${t.name}' does not match any field. Available fields: ${[...g].join(", ")}`,p.tag(y))}}}const f=n.tag("column");if(f){const p=f.text("width");if(p!==void 0){const y=["xs","sm","md","lg","xl","2xl"];f.numeric("width")===void 0&&!y.includes(p)&&i.warn(`Unknown column width '${p}' on field '${t.name}'. Valid presets: ${y.join(", ")}`,f.tag("width"))}const g=f.text("word_break");g!==void 0&&g!=="break_all"&&i.error(`Unknown column word_break '${g}' on field '${t.name}'. Valid values: break_all`,f.tag("word_break"))}if(t.isNest()){const p=n.tag("viz");if(p){const g=p.text("mode");if(g!==void 0){const y=["normal","yoy"];y.includes(g)||i.error(`Invalid chart mode '${g}' on field '${t.name}'. Valid modes: ${y.join(", ")}`,p.tag("mode"))}}}const d=n.tag("big_value");if(d){const p=d.text("size");if(p!==void 0){const y=["sm","md","lg"];y.includes(p)||i.error(`Invalid big_value size '${p}' on field '${t.name}'. Valid sizes: ${y.join(", ")}`,d.tag("size"))}const g=d.text("comparison_format");if(g!==void 0){const y=["pct","ppt"];y.includes(g)||i.error(`Invalid big_value comparison_format '${g}' on field '${t.name}'. Valid formats: ${y.join(", ")}`,d.tag("comparison_format"))}}if(n.has("big_value")&&t.isNest()){const p=t.fields.filter(g=>g.isBasic()&&g.wasDimension());if(p.length>0){const g=p.map(y=>y.name).join(", ");i.error(`Tag 'big_value' on field '${t.name}' does not support group_by fields. Found dimensions: ${g}`,n.tag("big_value"))}}const h=n.tag("number");if(h){const p=h.text("scale");if(p!==void 0){const y=["k","m","b","t","q","auto"];y.includes(p)||i.error(`Invalid number scale '${p}' on field '${t.name}'. Valid scales: ${y.join(", ")}`,h.tag("scale"))}const g=h.text("suffix");if(g!==void 0){const y=["letter","lower","word","short","finance","scientific","none"];y.includes(g)||i.error(`Invalid number suffix '${g}' on field '${t.name}'. Valid suffixes: ${y.join(", ")}`,h.tag("suffix"))}}}markDeclaredTags(t,n){const r=t.tag;for(const i of n)if(i.getDeclaredTagPaths)for(const s of i.getDeclaredTagPaths())r.find(s)}}function vR(e,t){t||(t=new bR(e));const n=t.getRootField(),r=e.data.kind==="record_cell"?{kind:"array_cell",array_value:[e.data]}:e.data;return new kfe(r,n)}function zfe(e){return["day","week","month","quarter","year"].includes(e)}function xR(e){return zfe(e)||["hour","minute","second"].includes(e)}const jt="∅";function C7(...e){const t={};for(const n of e)if(A7(n))for(const r in n){const i=n[r];if(A7(i)){const s=A7(t[r])?t[r]:{};t[r]=C7(s,i)}else t[r]=n[r]}return t}function A7(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function M7(e,t="# "){var i;const n=((i=e==null?void 0:e.map(s=>s.value))==null?void 0:i.filter(s=>s.startsWith(t)))??[],r=new Td.TagParser;for(const s of n)r.parse(s);return r.finish()}function Pfe(e){var s,a;const t=((s=e==null?void 0:e.map(o=>o.value))==null?void 0:s.filter(o=>o.startsWith("# ")))??[],n=((a=e==null?void 0:e.map(o=>o.value))==null?void 0:a.filter(o=>o.startsWith("#r ")))??[],r=[...t,...n],i=new Td.TagParser;for(const o of r)i.parse(o);return i.finish()}function wR(e,t,n={}){let r=t.toString();return n.terse?r=Lfe.get(t)??r:e===1&&(r=r.substring(0,r.length-1)),`${n.numFormat?Bo.format(n.numFormat,e):e.toLocaleString()}${n.terse?"":" "}${r}`}const Lfe=new Map([[lt.Nanoseconds,"ns"],[lt.Microseconds,"µs"],[lt.Milliseconds,"ms"],[lt.Seconds,"s"],[lt.Minutes,"m"],[lt.Hours,"h"],[lt.Days,"d"]]),Bfe=new Map([[lt.Nanoseconds,1e3],[lt.Microseconds,1e3],[lt.Milliseconds,1e3],[lt.Seconds,60],[lt.Minutes,60],[lt.Hours,24],[lt.Days,Number.MAX_VALUE]]);function Ufe(e,t,n){const r=n.durationUnit&&a7(n.durationUnit)?n.durationUnit:lt.Seconds,i=void 0,s=n.terse??!1;let a=t,o=0,l=[],u=!1;for(const[c,f]of Bfe)if(c===r&&(u=!0),!!u&&(o=a%f,a=Math.floor(a/=f),o>0&&(l=[wR(o,c,{numFormat:i,terse:s}),...l]),a===0))break;return l.length>0?l.slice(0,2).join(" "):wR(0,r,{numFormat:i,terse:s})}function f0(e,t=2){return`${"0".repeat(t-1)}${e}`.slice(-t)}function $R(e,t={}){if(t.timezone){const f=t.timeframe&&xR(t.timeframe)?t.timeframe:"second";return T2(e,f,t.timezone)}if(t.extractFormat)switch(t.extractFormat){case"month-day":return e.toLocaleDateString("en-US",{month:"short",day:"numeric",timeZone:"UTC"});case"month":return e.toLocaleDateString("en-US",{month:"long",timeZone:"UTC"});case"quarter":return`Q${Math.floor(e.getUTCMonth()/3)+1}`;case"week":return e.toLocaleDateString("en-US",{month:"short",day:"numeric",timeZone:"UTC"});case"day":return e.toLocaleDateString("en-US",{day:"numeric",timeZone:"UTC"})}const n=e.getUTCFullYear(),r=f0(e.getUTCMonth()+1),i=f0(e.getUTCDate()),s=f0(e.getUTCHours()),a=f0(e.getUTCMinutes()),o=f0(e.getUTCSeconds()),l=`${s}:${a}:${o}`,u=`${n}-${r}-${i}`,c=t.timeframe;if(c&&xR(c))switch(c){case"second":return`${u} ${l}`;case"minute":return`${u} ${s}:${a}`;case"hour":return`${u} ${s}`;case"day":return`${u}`;case"week":return`${u}-WK`;case"month":return`${n}-${r}`;case"quarter":return`${n}-Q${Math.floor(e.getUTCMonth()/3)+1}`;case"year":return e.getUTCFullYear().toString()}return t.isDate?u:`${u} ${l}`}function qfe(e){return`"${e.replace(/(["\\])/g,"\\$1")}"`}function SR(e){return e.isNull()?"null":e.isString()?qfe(e.value):e.isNumber()||e.isBoolean()?e.value.toString():e.isTime()?"@"+$R(e.value,{isDate:e.isDate(),timeframe:e.field.timeframe}):"invalid_drill_literal()"}function F7(e,t){e.fields.forEach(n=>{t(n),qd.isNestField(n)&&F7(n,t)})}function jfe(e){return e!==void 0}function T7(e){const t=Math.abs(e),n=e<0?"-":"";let r,i="";if(t>=1e15)r=(t/1e15).toFixed(1),i="Q";else if(t>=1e12)r=(t/1e12).toFixed(1),i="T";else if(t>=1e9)r=(t/1e9).toFixed(1),i="B";else if(t>=1e6)r=(t/1e6).toFixed(1),i="M";else if(t>=1e3)r=(t/1e3).toFixed(1),i="K";else return e.toLocaleString("en-US");return r=r.replace(/\.0$/,""),`${n}${r}${i}`}const Hs={k:{divisor:1e3,threshold:1e3},m:{divisor:1e6,threshold:1e6},b:{divisor:1e9,threshold:1e9},t:{divisor:1e12,threshold:1e12},q:{divisor:1e15,threshold:1e15}},Vfe={letter:{k:"K",m:"M",b:"B",t:"T",q:"Q"},lower:{k:"k",m:"m",b:"b",t:"t",q:"q"},word:{k:" Thousand",m:" Million",b:" Billion",t:" Trillion",q:" Quadrillion"},short:{k:"K",m:" Mil",b:" Bil",t:" Tril",q:" Quad"},finance:{k:"M",m:"MM",b:"B",t:"T",q:"Q"},scientific:{k:"×10³",m:"×10⁶",b:"×10⁹",t:"×10¹²",q:"×10¹⁵"},none:{k:"",m:"",b:"",t:"",q:""}};function X2(e,t={}){const{scale:n="auto",decimals:r=2,suffix:i="lower"}=t,s=Math.min(Math.max(0,r),10),a=Math.abs(e),o=e<0?"-":"";let l=null,u=1;if(n==="auto")if(a>=Hs.q.threshold)l="q",u=Hs.q.divisor;else if(a>=Hs.t.threshold)l="t",u=Hs.t.divisor;else if(a>=Hs.b.threshold)l="b",u=Hs.b.divisor;else if(a>=Hs.m.threshold)l="m",u=Hs.m.divisor;else if(a>=Hs.k.threshold)l="k",u=Hs.k.divisor;else return e.toLocaleString("en-US");else l=n,u=Hs[n].divisor;const c=a/u;if(i==="scientific"){const h=Math.floor(Math.log10(a)+1e-10),p=(a/Math.pow(10,h)).toLocaleString("en-US",{minimumFractionDigits:0,maximumFractionDigits:s}),g={0:"⁰",1:"¹",2:"²",3:"³",4:"⁴",5:"⁵",6:"⁶",7:"⁷",8:"⁸",9:"⁹","-":"⁻"},y=String(h).split("").map(b=>g[b]||b).join("");return`${o}${p}×10${y}`}const f=c.toLocaleString("en-US",{minimumFractionDigits:0,maximumFractionDigits:s}),d=Vfe[i][l];return`${o}${f}${d}`}const Wfe={usd:"$",eur:"€",gbp:"£",euro:"€",pound:"£"};function Hfe(e){const t=e.toLowerCase().trim();if(t==="auto")return{scale:"auto",decimals:2};if(t==="id")return{isId:!0};const n=t.match(/^(\d)([kmbtq])$/i);if(n){const i=parseInt(n[1],10),s=n[2].toLowerCase();return{decimals:i,scale:s}}const r=t.match(/^(\d)$/);return r?{decimals:parseInt(r[1],10)}:null}function Gfe(e){const t=e.toLowerCase().trim(),n=t.match(/^(euro|pound|usd|eur|gbp)/i);if(!n)return null;const r=n[1].toLowerCase(),i=Wfe[r];if(!i)return null;const s=t.slice(n[1].length);if(s===".auto")return{currency:r,symbol:i,scale:"auto",decimals:2};const a=s.match(/^(\d)([kmbtq])$/i);if(a)return{currency:r,symbol:i,decimals:parseInt(a[1],10),scale:a[2].toLowerCase()};const o=s.match(/^(\d)$/);return o?{currency:r,symbol:i,decimals:parseInt(o[1],10)}:s===""?{currency:r,symbol:i}:null}function _R(e){if(!e)return;const t=e.toLowerCase().trim();if(["k","m","b","t","q"].includes(t))return t;if(t==="auto")return"auto"}class Z2 extends nu{constructor(t,n){super(t),this.options=n}getText(t){if(!t.isNumber())return null;if(this.options.value_format){if(this.options.value_format==="big")return T7(t.value);try{return Bo.format(this.options.value_format,t.value)}catch{throw new Error(`Invalid value format: ${this.options.value_format}`)}}return t.value.toLocaleString()}}const Ux=class Ux extends Pt{constructor(){super(),this.addExtractor((t,n)=>{t.value_format=n==null?void 0:n.text()},this.rendererName,"format")}activates(t){return t.isNumber()}create(t,n,r,i,s){return new Z2(t,s)}get rendererName(){return"number"}};Ux.instance=new Ux;let D7=Ux;class kR{constructor(t,n,r){this.parentField=t,this.values=n,this.span=r,this.key=JSON.stringify({parentField:this.parentField.name,values:this.values.map(i=>i.field.isBasic()?String(i.value):"")}),this.fieldValueMap=new Map;for(const i of this.values)this.fieldValueMap.set(i.field.name,i)}}class d0{constructor(t,n,r){this.pivotedField=t,this.field=n,this.userDefinedPivotDimensions=r}isPivotedColumnField(){return this instanceof d0}}class h0{constructor(t,n,r){this.flattenedField=t,this.field=n,this.name=r}isFlattenedColumnField(){return this instanceof h0}getChildRenderer(t){const n=t[this.flattenedField.name];if(n instanceof m0)return n.childRenderers[this.field.name];throw Error("Could not render flattened table. `# flatten` only supports nests.")}getValue(t){const n=t.column(this.flattenedField.name);if(n.isRecord())return n.column(this.field.name);throw Error("Cannot find nested record within flattened field. `# flatten` only supports nests with no group_bys.")}}function ER(e){return e.isRecord()&&e.tag.has("flatten")}class m0 extends h2{constructor(){super(...arguments),this.childrenStyleDefaults={size:"medium"}}async render(t){var d,h,m;if(t.isNull())return this.document.createElement("span");if(!t.isRecordOrRepeatedRecord())throw new Error("Invalid type for Table Renderer");const n=this.tagged.has("transpose"),r=t.field.fields;if(n&&r.length>20)throw new Error("Transpose limit of 20 columns exceeded.");let i=0,s=0,a=[];a[i]=[];const o=[];let l=0;for(const p of r){if(p.isHidden())continue;const g=this.childRenderers[p.name];if(g instanceof m0&&g.tagged.has("pivot")){const b=g.tagged.textArray("pivot","dimensions");let v,x=[];const $=new Map;for(const w of t.rows){const k=w.column(p.name);if(!k.isNull()){if(!k.isRecordOrRepeatedRecord())throw new Error(`Can not pivot field ${p.name}.`);if(!v){const _=g.calculatePivotDimensions(k,b);v=_.dimensions,x=_.nonDimensions}for(const _ of k.rows){const E=new kR(k.field,v.map(A=>_.column(A.field.name)),x.length),C=E.key;$.get(C)||$.set(C,E)}}}if(!v)throw new Error(`Could not pivot ${p.name}, no data found.`);const S=Array.from($.values()).sort((w,k)=>{for(const _ of v){const E=w.fieldValueMap.get(_.field.name),C=k.fieldValueMap.get(_.field.name);if(E!=null&&E.field.isBasic()&&(C!=null&&C.field.isBasic())&&typeof E==typeof C){if(E.isNull())return C.isNull()?0:1;if(C.isNull())return-1;const A=E.compareTo(C);if(A!==0)return _.dir!=="desc"?A:-A}}return 0});for(const w of S)for(const k of x)o.push(new d0(w,k.field,b)),a[i][s]=g.createHeaderCell(k.field,n,{name:(d=k.flattenedField)==null?void 0:d.name,childRenderer:(h=k.flattenedField)==null?void 0:h.getChildRenderer(g.childRenderers)}),s++;l=Math.max(l,v.length)}else if(ER(p)){const b=p,x=b.fields.map($=>new h0(b,$,`${b.name} ${$.name}`));for(const $ of x)a[i][s]=this.createHeaderCell($.field,n,{name:$.name,childRenderer:$.getChildRenderer(this.childRenderers)}),o.push($),s++}else a[i][s]=this.createHeaderCell(p,n),o.push(p),s++}if(l>0&&o.length>30)throw new Error("Pivot limit of 30 columns exceeded.");if(!n&&this.options.isDrillingEnabled){const p=this.document.createElement("th");p.style.cssText=`
66
+ } +`),r+=" { select: * }",r}class Ws{constructor(t,n,r){this.cell=t,this.field=n,this.parent=r}get literalValue(){}isNull(){return this instanceof x7}isArray(){return this instanceof v7}isRecord(){return this instanceof Y2}isRepeatedRecord(){return this instanceof G2}isRecordOrRepeatedRecord(){return this.isRepeatedRecord()||this.isRecord()}isNest(){return this.isRepeatedRecord()||this.isRecord()||this.isArray()}isNumber(){return this instanceof w7}isDate(){return this instanceof $7}isTime(){return this.isDate()||this.isTimestamp()}isJSON(){return this instanceof _7}isString(){return this instanceof k7}isTimestamp(){return this instanceof S7}isBoolean(){return this instanceof E7}asCell(){if(this instanceof v7||this instanceof G2||this instanceof Y2||this instanceof w7||this instanceof $7||this instanceof _7||this instanceof k7||this instanceof S7||this instanceof E7||this instanceof x7||this instanceof hR)return this;throw new Error("Not a cell")}root(){return this.parent?this.parent.root():this.asCell()}getPathInfo(t){const n=t.split("/"),r=n.filter(s=>s==="..").length+1,i=n.filter(s=>s!==".."&&s!=="");return{levelsUp:r,pathSegments:i}}getParentRecord(t){let n=this.asCell();for(;n&&t>0;){for(n=n.parent;n!=null&&n.isArray();)n=n.parent;t--}if(!(n!=null&&n.isRecord()))throw new Error(`Parent ${t} levels up was not a record`);return n}getRelativeCell(t){try{const{levelsUp:n,pathSegments:r}=this.getPathInfo(t);return this.getParentRecord(n).cellAtPath(r)}catch{return}}cellAt(t){return typeof t=="string"?this.cellAtPath(JSON.parse(t)):this.cellAtPath(t)}cellAtPath(t){if(t.length===0)return this.asCell();throw new Error(`${this.constructor.name} cannot contain columns`)}compareTo(t){return 0}canDrill(){return $fe(this.asCell())}getStableDrillQuery(){return uR(this.asCell())}getStableDrillClauses(){return b7(this.asCell())}getDrillExpressions(){return fR(this.asCell())}getDrillEntries(){return Sfe(this.asCell())}getStableDrillQueryMalloy(){return dR(this.asCell())}getDrillQueryMalloy(){return _fe(this.asCell())}}class v7 extends Ws{constructor(t,n,r){super(t,n,r),this.cell=t,this.field=n,this.parent=r,this.values=[];for(const i of this.cell.array_value)this.values.push(mR.from(i,this.field.elementField,this))}get value(){return this.values}}class G2 extends Ws{constructor(t,n,r){var s;super(t,n,r),this.cell=t,this.field=n,this.parent=r,this.rows=[],this.fieldValueSets=new Map;for(let a=0;a<this.cell.array_value.length;a++){const o=this.cell.array_value[a];if(!("record_value"in o))throw new Error("Expected record cell in RepeatedRecordCell");const l=new Y2(o,this.field.nestedRecordField,this);this.rows.push(l)}for(const a of this.rows)for(const o of a.columns){const l=o.field;let u=this.fieldValueSets.get(l.name);u===void 0&&(u=new Set,this.fieldValueSets.set(l.name,u)),u.add(o.value)}for(const[a,o]of this.fieldValueSets.entries())this.field.registerValueSetSize(a,o.size);const i=this.field.getPlugins();for(const a of i)(s=a.processData)==null||s.call(a,this.field,this)}get value(){return this.rows}get values(){return this.rows}}class kfe extends G2{constructor(t,n){super(t,n,void 0),this.cell=t,this.field=n}}class Y2 extends Ws{constructor(t,n,r){super(t,n,r),this.cell=t,this.field=n,this.parent=r,this.cells={};for(let i=0;i<n.fields.length;i++){const s=n.fields[i],a=mR.from(t.record_value[i],s,this);this.cells[s.name]=a}}get rows(){return[this]}get value(){return this.cells}column(t){return this.cells[t]}get columns(){return this.field.fields.map(t=>this.column(t.name))}allCellValues(){return Object.fromEntries(Object.entries(this.cells).map(([t,n])=>[t,n.value]))}cellAtPath(t){if(t.length===0)return this.asCell();{const[n,...r]=t,i=this.cells[n];if(i===void 0)throw new Error(`No such column ${n} in ${this.field.path}`);return i.cellAtPath(r)}}}class x7 extends Ws{constructor(t,n,r){super(t,n,r),this.cell=t,this.field=n,this.parent=r,this.field.registerNullValue()}get value(){return null}get literalValue(){return{kind:"null_literal"}}}class w7 extends Ws{constructor(t,n,r){super(t,n,r),this.cell=t,this.field=n,this.parent=r,this.field.registerValue(this.value)}get value(){return this.cell.number_value}get stringValue(){return this.cell.string_value}get subtype(){return this.cell.subtype}needsStringPrecision(){return this.subtype==="bigint"}numberValue(){return this.value}bigint(){return this.stringValue!==void 0?BigInt(this.stringValue):BigInt(this.value)}compareTo(t){if(!t.isNumber())return 0;if(this.stringValue!==void 0&&t.stringValue!==void 0){const r=this.bigint(),i=t.bigint();return r>i?1:r<i?-1:0}const n=this.value-t.value;return n>0?1:n===0?0:-1}get literalValue(){return{kind:"number_literal",number_value:this.value,string_value:this.stringValue}}}class $7 extends Ws{constructor(t,n,r){super(t,n,r),this.cell=t,this.field=n,this.parent=r,this.field.registerValue(this.value)}get value(){return new Date(this.cell.date_value)}get timeframe(){return this.field.timeframe}compareTo(t){return t.isTime()?this.value>t.value?1:this.value<t.value?-1:0:0}get literalValue(){return{kind:"date_literal",date_value:this.cell.date_value,granularity:this.timeframe}}}class S7 extends Ws{constructor(t,n,r){super(t,n,r),this.cell=t,this.field=n,this.parent=r,this.field.registerValue(this.value)}get value(){return new Date(this.cell.timestamp_value)}get timeframe(){return this.field.timeframe}compareTo(t){return t.isTime()?this.value>t.value?1:this.value<t.value?-1:0:0}get literalValue(){return{kind:"timestamp_literal",timestamp_value:this.cell.timestamp_value,granularity:this.timeframe}}}class _7 extends Ws{constructor(t,n,r){super(t,n,r),this.cell=t,this.field=n,this.parent=r}get value(){try{return JSON.parse(this.cell.json_value)}catch{return this.cell.json_value}}compareTo(t){const n=this.value.toString(),r=t.toString();return n===r?0:n>r?1:-1}}class hR extends Ws{constructor(t,n,r){super(t,n,r),this.cell=t,this.field=n,this.parent=r}get value(){try{return JSON.parse(this.cell.sql_native_value)}catch{return this.cell.sql_native_value}}compareTo(t){const n=this.value.toString(),r=t.toString();return n===r?0:n>r?1:-1}}class k7 extends Ws{constructor(t,n,r){super(t,n,r),this.cell=t,this.field=n,this.parent=r,this.field.registerValue(this.value)}get value(){return this.cell.string_value}compareTo(t){return t.isString()?this.value.toLocaleLowerCase().localeCompare(t.value.toLocaleLowerCase()):0}get literalValue(){return{kind:"string_literal",string_value:this.cell.string_value}}}class E7 extends Ws{constructor(t,n,r){super(t,n,r),this.cell=t,this.field=n,this.parent=r,this.field.registerValue(this.value)}get value(){return this.cell.boolean_value}compareTo(t){return this.value===t.value?0:this.value?1:-1}get literalValue(){return{kind:"boolean_literal",boolean_value:this.cell.boolean_value}}}const mR={from(e,t,n){switch(e.kind){case"array_cell":{if(t instanceof ou)return new G2(e,t,n);if(t instanceof Ud)return new v7(e,t,n);throw new Error("Expected record data to be associated with record field")}case"record_cell":{if(t instanceof Ho)return new Y2(e,t,n);throw new Error("Expected record data to be associated with record field")}case"null_cell":return new x7(e,t,n);case"number_cell":{if(t instanceof s0)return new w7(e,t,n);throw new Error("Expected number data to be associated with number field")}case"date_cell":{if(t instanceof a0)return new $7(e,t,n);throw new Error("Expected date data to be associated with date field")}case"json_cell":{if(t instanceof u0)return new _7(e,t,n);throw new Error("Expected JSON data to be associated with JSON field")}case"string_cell":{if(t instanceof Bd)return new k7(e,t,n);throw new Error("Expected string data to be associated with string field")}case"timestamp_cell":{if(t instanceof o0)return new S7(e,t,n);throw new Error("Expected timestamp data to be associated with timestamp field")}case"boolean_cell":{if(t instanceof c0)return new E7(e,t,n);throw new Error("Expected boolean data to be associated with boolean field")}case"sql_native_cell":{if(t instanceof l0)return new hR(e,t,n);throw new Error("Expected sql_native data to be associated with sql_native field")}}}},Efe={url:"",range:{start:{line:0,character:0},end:{line:0,character:0}}};function pR(e){return(e==null?void 0:e.location)??Efe}class gR{constructor(){this.logs=[]}reset(){this.logs=[]}warn(t,n){this.add("warn",t,n)}error(t,n){this.add("error",t,n)}add(t,n,r){const{url:i,range:s}=r?pR(r):pR();this.logs.push({url:i,range:s,severity:t,message:n})}collectUnreadTags(t,n){const r=t.getUnreadProperties();for(const i of r){const s=i.join(".");this.warn(`Unknown render tag '${s}' on field '${n}'`,t)}}getLogs(){return[...this.logs]}}function Cfe(e){const n=e.tag.tag("image");if(!n)return{};const r=n.text("width"),i=n.text("height");let s,a;const o=n.tag("alt");return o&&(a=o.text("field"),a||(s=o.text())),{width:r??void 0,height:i??void 0,alt:s,altField:a}}function Afe(e){const n=e.tag.tag("link");return n?{linkField:n.text("field")??void 0,urlTemplate:n.text("url_template")??void 0}:{}}function Mfe(e){return{isListDetail:e.tag.has("list_detail")}}function Ffe(e){const t=e.text("currency"),n=t?Gfe(t):null;if(n)return{symbol:n.symbol,scale:n.scale,decimals:n.decimals,suffixFormat:"lower"};let r="$";switch(t){case"euro":r="€";break;case"pound":r="£";break;case"usd":default:r="$";break}const i=e.text("currency","scale"),s=_R(i),a=e.numeric("currency","decimals")??void 0,o=e.text("currency","suffix");let l="lower";return o?l=o:s&&(l="letter"),{symbol:r,scale:s,decimals:a,suffixFormat:l}}function Tfe(e){const t=e.text("number"),n=t?Hfe(t):null;if(n)return{scale:n.scale,decimals:n.decimals,isId:n.isId,isBig:!1,suffixFormat:"lower"};const r=e.text("number","scale"),i=_R(r);if(i){const s=e.numeric("number","decimals")??2,o=e.text("number","suffix")??"letter";return{scale:i,decimals:s,suffixFormat:o}}return t==="big"?{isBig:!0}:{formatString:t??void 0}}function Dfe(e){const t=e.tag;if(t.has("currency"))return{mode:"currency",currency:Ffe(t)};if(t.has("percent"))return{mode:"percent"};if(t.has("duration")){const n=t.text("duration"),r=t.has("duration","terse");return{mode:"duration",duration:{unit:n??lt.Seconds,terse:r}}}if(t.has("number")){if(e.isTime()){const n=t.text("number");if(n)return{mode:"dateFormat",formatString:n}}return{mode:"number",number:Tfe(t)}}return{mode:"default"}}const yR={xs:28,sm:64,md:128,lg:256,xl:384,"2xl":512};function Ofe(e){const t=e.tag.tag("column");if(!t)return;let n=null;const r=t.text("width"),i=t.numeric("width");r&&yR[r]?n=yR[r]:i&&(n=i);const s=t.numeric("height")??null,a=t.text("word_break")==="break_all";return{width:n,height:s,wordBreak:a}}function Rfe(e){const t=e.tag,n=t.tag("table"),r=n==null?void 0:n.tag("size"),i=(r==null?void 0:r.text())==="fill";let s;t.has("transpose")&&(s=t.numeric("transpose","limit")??void 0);let a;if(t.has("pivot")){const o=t.textArray("pivot","dimensions");a=o&&o.length>0?o:void 0}return{fillSize:i,transposeLimit:s,pivotDimensions:a}}function Nfe(e){const n=e.tag.tag("dashboard");let r=361;const i=n==null?void 0:n.tag("table","max_height");return(i==null?void 0:i.text())==="none"?r=null:i!=null&&i.numeric()&&(r=i.numeric()),{maxTableHeight:r}}function Ife(e){const t=e.renderAs(),n=e.tag,r=n.text("label");r!==void 0&&e.setResolvedLabel(r);const i=Ofe(e);i&&e.setColumnConfig(i),n.tag("tooltip"),n.tag("break");const s=n.tag("size");switch(s&&s.numeric("height"),t){case"image":e.setTagConfig(Cfe(e));break;case"link":e.setTagConfig(Afe(e));break;case"list":e.setTagConfig(Mfe(e));break;case"cell":e.setTagConfig(Dfe(e));break;case"table":e.setTagConfig(Rfe(e));break;case"dashboard":e.setTagConfig(Nfe(e));break}}class bR{constructor(t,n=[],r={},i,s){this.pluginRegistry=n,this.pluginOptions=r,this.onPluginCreateError=i,this.logCollector=s??new gR,this.registry=new Map,this.rootField=new wfe({name:"root",type:{kind:"array_type",element_type:{kind:"record_type",fields:t.schema.fields.filter(a=>a.kind==="dimension")}},annotations:t.annotations},{modelTag:M7(t.model_annotations,"## "),queryTimezone:t.query_timezone}),this.registerFields(this.rootField)}instantiatePluginsForField(t){const n=[];for(const r of this.pluginRegistry)try{if(r.matches(t,t.tag,oR(t))){const i=this.pluginOptions[r.name],s=this.rootField.modelTag,a=r.create(t,i,s);n.push(a)}}catch(i){const s=i instanceof Error?i.message:String(i);this.logCollector.error(`Plugin ${r.name} failed for field '${t.key}': ${s}`),this.onPluginCreateError&&this.onPluginCreateError(i,r,t,n)}return t.setPlugins(n),n}registerFields(t){const n=t.key;if(!this.registry.has(n)){const r=this.instantiatePluginsForField(t),i={field:t,renderProperties:{field:t,renderAs:t.renderAs(),sizingStrategy:"fit",properties:{},errors:[]},plugins:r},s=this.populateRenderFieldProperties(t,r);i.renderProperties.properties=s.properties,i.renderProperties.errors=s.errors,this.registry.set(n,i),Ife(t),this.validateFieldTags(t),this.markDeclaredTags(t,r)}if(t.isNest())for(const r of t.fields)this.registerFields(r)}populateRenderFieldProperties(t,n){const r={},i=[];for(const s of n)r[s.name]=s.getMetadata();return{properties:r,errors:i}}getAllFields(){return Array.from(this.registry.values()).map(t=>t.field)}getRootField(){return this.rootField}getPluginsForField(t){const n=this.registry.get(t);return n?n.plugins:[]}getFieldEntry(t){return this.registry.get(t)}validateFieldTags(t){var m;const n=t.tag,r=oR(t),i=this.logCollector,s=["viz","bar_chart","line_chart","list","list_detail","pivot","dashboard","transpose","table"],a=[Gt.RepeatedRecord,Gt.Record];for(const p of s)n.has(p)&&!a.includes(r)&&i.error(`Tag '${p}' on field '${t.name}' requires a nested query, but field is ${r}`,n.tag(p));n.has("link")&&r!==Gt.String&&i.error(`Tag 'link' on field '${t.name}' requires a string field, but field is ${r}`,n.tag("link")),n.has("image")&&r!==Gt.String&&i.error(`Tag 'image' on field '${t.name}' requires a string field, but field is ${r}`,n.tag("image"));const o=["number","currency","percent","duration"];for(const p of o)n.has(p)&&r!==Gt.Number&&r!==Gt.Array&&!(p==="number"&&(r===Gt.Date||r===Gt.Timestamp))&&i.error(`Tag '${p}' on field '${t.name}' requires a numeric field, but field is ${r}`,n.tag(p));const l=n.tag("number");(l==null?void 0:l.scalarType())==="number"&&i.error(`Tag 'number' on field '${t.name}' has a bare numeric value. Use a quoted format string instead, e.g. # number="#,##0.00"`,l);const u=n.text("viz");if(u!==void 0){const p=["bar","line","table","dashboard"];p.includes(u)||i.error(`Invalid viz type '${u}' on field '${t.name}'. Valid types: ${p.join(", ")}`,n.tag("viz"))}const c=n.text("size");if(c!==void 0){const p=["fill","spark","xs","sm","md","lg","xl","2xl"];!p.includes(c)&&!((m=n.tag("size"))!=null&&m.has("width"))&&i.warn(`Unknown size '${c}' on field '${t.name}'. Valid presets: ${p.join(", ")}`,n.tag("size"))}if(n.has("currency")){const p=n.text("currency");if(p!==void 0){const g=["usd","eur","gbp","euro","pound"];p.match(/^(euro|pound|usd|eur|gbp)/i)||i.error(`Unknown currency '${p}' on field '${t.name}'. Valid codes: ${g.join(", ")}`,n.tag("currency"))}}if(n.has("duration")){const p=n.text("duration");if(p!==void 0){const g=["nanoseconds","microseconds","milliseconds","seconds","minutes","hours","days"];g.includes(p)||i.error(`Unknown duration unit '${p}' on field '${t.name}'. Valid units: ${g.join(", ")}`,n.tag("duration"))}}if(t.isNest()){const p=n.tag("viz");if(p){const g=new Set(t.fields.map(y=>y.name));for(const y of["x","y","series"]){const b=p.textArray(y),v=b??[],x=p.text(y);x&&!b&&v.push(x);for(const $ of v)g.has($)||i.error(`Chart field reference '${$}' for '${y}' on '${t.name}' does not match any field. Available fields: ${[...g].join(", ")}`,p.tag(y))}}}const f=n.tag("column");if(f){const p=f.text("width");if(p!==void 0){const y=["xs","sm","md","lg","xl","2xl"];f.numeric("width")===void 0&&!y.includes(p)&&i.warn(`Unknown column width '${p}' on field '${t.name}'. Valid presets: ${y.join(", ")}`,f.tag("width"))}const g=f.text("word_break");g!==void 0&&g!=="break_all"&&i.error(`Unknown column word_break '${g}' on field '${t.name}'. Valid values: break_all`,f.tag("word_break"))}if(t.isNest()){const p=n.tag("viz");if(p){const g=p.text("mode");if(g!==void 0){const y=["normal","yoy"];y.includes(g)||i.error(`Invalid chart mode '${g}' on field '${t.name}'. Valid modes: ${y.join(", ")}`,p.tag("mode"))}}}const d=n.tag("big_value");if(d){const p=d.text("size");if(p!==void 0){const y=["sm","md","lg"];y.includes(p)||i.error(`Invalid big_value size '${p}' on field '${t.name}'. Valid sizes: ${y.join(", ")}`,d.tag("size"))}const g=d.text("comparison_format");if(g!==void 0){const y=["pct","ppt"];y.includes(g)||i.error(`Invalid big_value comparison_format '${g}' on field '${t.name}'. Valid formats: ${y.join(", ")}`,d.tag("comparison_format"))}}if(n.has("big_value")&&t.isNest()){const p=t.fields.filter(g=>g.isBasic()&&g.wasDimension());if(p.length>0){const g=p.map(y=>y.name).join(", ");i.error(`Tag 'big_value' on field '${t.name}' does not support group_by fields. Found dimensions: ${g}`,n.tag("big_value"))}}const h=n.tag("number");if(h){const p=h.text("scale");if(p!==void 0){const y=["k","m","b","t","q","auto"];y.includes(p)||i.error(`Invalid number scale '${p}' on field '${t.name}'. Valid scales: ${y.join(", ")}`,h.tag("scale"))}const g=h.text("suffix");if(g!==void 0){const y=["letter","lower","word","short","finance","scientific","none"];y.includes(g)||i.error(`Invalid number suffix '${g}' on field '${t.name}'. Valid suffixes: ${y.join(", ")}`,h.tag("suffix"))}}}markDeclaredTags(t,n){const r=t.tag;for(const i of n)if(i.getDeclaredTagPaths)for(const s of i.getDeclaredTagPaths())r.find(s)}}function vR(e,t){t||(t=new bR(e));const n=t.getRootField(),r=e.data.kind==="record_cell"?{kind:"array_cell",array_value:[e.data]}:e.data;return new kfe(r,n)}function zfe(e){return["day","week","month","quarter","year"].includes(e)}function xR(e){return zfe(e)||["hour","minute","second"].includes(e)}const jt="∅";function C7(...e){const t={};for(const n of e)if(A7(n))for(const r in n){const i=n[r];if(A7(i)){const s=A7(t[r])?t[r]:{};t[r]=C7(s,i)}else t[r]=n[r]}return t}function A7(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function M7(e,t="# "){var i;const n=((i=e==null?void 0:e.map(s=>s.value))==null?void 0:i.filter(s=>s.startsWith(t)))??[],r=new Td.TagParser;for(const s of n)r.parse(s);return r.finish()}function Pfe(e){var s,a;const t=((s=e==null?void 0:e.map(o=>o.value))==null?void 0:s.filter(o=>o.startsWith("# ")))??[],n=((a=e==null?void 0:e.map(o=>o.value))==null?void 0:a.filter(o=>o.startsWith("#r ")))??[],r=[...t,...n],i=new Td.TagParser;for(const o of r)i.parse(o);return i.finish()}function wR(e,t,n={}){let r=t.toString();return n.terse?r=Lfe.get(t)??r:e===1&&(r=r.substring(0,r.length-1)),`${n.numFormat?Bo.format(n.numFormat,e):e.toLocaleString()}${n.terse?"":" "}${r}`}const Lfe=new Map([[lt.Nanoseconds,"ns"],[lt.Microseconds,"µs"],[lt.Milliseconds,"ms"],[lt.Seconds,"s"],[lt.Minutes,"m"],[lt.Hours,"h"],[lt.Days,"d"]]),Bfe=new Map([[lt.Nanoseconds,1e3],[lt.Microseconds,1e3],[lt.Milliseconds,1e3],[lt.Seconds,60],[lt.Minutes,60],[lt.Hours,24],[lt.Days,Number.MAX_VALUE]]);function Ufe(e,t,n){const r=n.durationUnit&&a7(n.durationUnit)?n.durationUnit:lt.Seconds,i=void 0,s=n.terse??!1;let a=t,o=0,l=[],u=!1;for(const[c,f]of Bfe)if(c===r&&(u=!0),!!u&&(o=a%f,a=Math.floor(a/=f),o>0&&(l=[wR(o,c,{numFormat:i,terse:s}),...l]),a===0))break;return l.length>0?l.slice(0,2).join(" "):wR(0,r,{numFormat:i,terse:s})}function f0(e,t=2){return`${"0".repeat(t-1)}${e}`.slice(-t)}function $R(e,t={}){if(t.timezone){const f=t.timeframe&&xR(t.timeframe)?t.timeframe:"second";return T2(e,f,t.timezone)}if(t.extractFormat)switch(t.extractFormat){case"month-day":return e.toLocaleDateString("en-US",{month:"short",day:"numeric",timeZone:"UTC"});case"month":return e.toLocaleDateString("en-US",{month:"long",timeZone:"UTC"});case"quarter":return`Q${Math.floor(e.getUTCMonth()/3)+1}`;case"week":return e.toLocaleDateString("en-US",{month:"short",day:"numeric",timeZone:"UTC"});case"day":return e.toLocaleDateString("en-US",{day:"numeric",timeZone:"UTC"})}const n=e.getUTCFullYear(),r=f0(e.getUTCMonth()+1),i=f0(e.getUTCDate()),s=f0(e.getUTCHours()),a=f0(e.getUTCMinutes()),o=f0(e.getUTCSeconds()),l=`${s}:${a}:${o}`,u=`${n}-${r}-${i}`,c=t.timeframe;if(c&&xR(c))switch(c){case"second":return`${u} ${l}`;case"minute":return`${u} ${s}:${a}`;case"hour":return`${u} ${s}`;case"day":return`${u}`;case"week":return`${u}-WK`;case"month":return`${n}-${r}`;case"quarter":return`${n}-Q${Math.floor(e.getUTCMonth()/3)+1}`;case"year":return e.getUTCFullYear().toString()}return t.isDate?u:`${u} ${l}`}function qfe(e){return`"${e.replace(/(["\\])/g,"\\$1")}"`}function SR(e){return e.isNull()?"null":e.isString()?qfe(e.value):e.isNumber()||e.isBoolean()?e.value.toString():e.isTime()?"@"+$R(e.value,{isDate:e.isDate(),timeframe:e.field.timeframe}):"invalid_drill_literal()"}function F7(e,t){e.fields.forEach(n=>{t(n),qd.isNestField(n)&&F7(n,t)})}function jfe(e){return e!==void 0}function T7(e){const t=Math.abs(e),n=e<0?"-":"";let r,i="";if(t>=1e15)r=(t/1e15).toFixed(1),i="Q";else if(t>=1e12)r=(t/1e12).toFixed(1),i="T";else if(t>=1e9)r=(t/1e9).toFixed(1),i="B";else if(t>=1e6)r=(t/1e6).toFixed(1),i="M";else if(t>=1e3)r=(t/1e3).toFixed(1),i="K";else return e.toLocaleString("en-US");return r=r.replace(/\.0$/,""),`${n}${r}${i}`}const Hs={k:{divisor:1e3,threshold:1e3},m:{divisor:1e6,threshold:1e6},b:{divisor:1e9,threshold:1e9},t:{divisor:1e12,threshold:1e12},q:{divisor:1e15,threshold:1e15}},Vfe={letter:{k:"K",m:"M",b:"B",t:"T",q:"Q"},lower:{k:"k",m:"m",b:"b",t:"t",q:"q"},word:{k:" Thousand",m:" Million",b:" Billion",t:" Trillion",q:" Quadrillion"},short:{k:"K",m:" Mil",b:" Bil",t:" Tril",q:" Quad"},finance:{k:"M",m:"MM",b:"B",t:"T",q:"Q"},scientific:{k:"×10³",m:"×10⁶",b:"×10⁹",t:"×10¹²",q:"×10¹⁵"},none:{k:"",m:"",b:"",t:"",q:""}};function X2(e,t={}){const{scale:n="auto",decimals:r=2,suffix:i="lower"}=t,s=Math.min(Math.max(0,r),10),a=Math.abs(e),o=e<0?"-":"";let l=null,u=1;if(n==="auto")if(a>=Hs.q.threshold)l="q",u=Hs.q.divisor;else if(a>=Hs.t.threshold)l="t",u=Hs.t.divisor;else if(a>=Hs.b.threshold)l="b",u=Hs.b.divisor;else if(a>=Hs.m.threshold)l="m",u=Hs.m.divisor;else if(a>=Hs.k.threshold)l="k",u=Hs.k.divisor;else return e.toLocaleString("en-US");else l=n,u=Hs[n].divisor;const c=a/u;if(i==="scientific"){const h=Math.floor(Math.log10(a)+1e-10),p=(a/Math.pow(10,h)).toLocaleString("en-US",{minimumFractionDigits:0,maximumFractionDigits:s}),g={0:"⁰",1:"¹",2:"²",3:"³",4:"⁴",5:"⁵",6:"⁶",7:"⁷",8:"⁸",9:"⁹","-":"⁻"},y=String(h).split("").map(b=>g[b]||b).join("");return`${o}${p}×10${y}`}const f=c.toLocaleString("en-US",{minimumFractionDigits:0,maximumFractionDigits:s}),d=Vfe[i][l];return`${o}${f}${d}`}const Wfe={usd:"$",eur:"€",gbp:"£",euro:"€",pound:"£"};function Hfe(e){const t=e.toLowerCase().trim();if(t==="auto")return{scale:"auto",decimals:2};if(t==="id")return{isId:!0};const n=t.match(/^(\d)([kmbtq])$/i);if(n){const i=parseInt(n[1],10),s=n[2].toLowerCase();return{decimals:i,scale:s}}const r=t.match(/^(\d)$/);return r?{decimals:parseInt(r[1],10)}:null}function Gfe(e){const t=e.toLowerCase().trim(),n=t.match(/^(euro|pound|usd|eur|gbp)/i);if(!n)return null;const r=n[1].toLowerCase(),i=Wfe[r];if(!i)return null;const s=t.slice(n[1].length);if(s===".auto")return{currency:r,symbol:i,scale:"auto",decimals:2};const a=s.match(/^(\d)([kmbtq])$/i);if(a)return{currency:r,symbol:i,decimals:parseInt(a[1],10),scale:a[2].toLowerCase()};const o=s.match(/^(\d)$/);return o?{currency:r,symbol:i,decimals:parseInt(o[1],10)}:s===""?{currency:r,symbol:i}:null}function _R(e){if(!e)return;const t=e.toLowerCase().trim();if(["k","m","b","t","q"].includes(t))return t;if(t==="auto")return"auto"}class Z2 extends nu{constructor(t,n){super(t),this.options=n}getText(t){if(!t.isNumber())return null;if(this.options.value_format){if(this.options.value_format==="big")return T7(t.value);try{return Bo.format(this.options.value_format,t.value)}catch{throw new Error(`Invalid value format: ${this.options.value_format}`)}}return t.value.toLocaleString()}}const Ux=class Ux extends Pt{constructor(){super(),this.addExtractor((t,n)=>{t.value_format=n==null?void 0:n.text()},this.rendererName,"format")}activates(t){return t.isNumber()}create(t,n,r,i,s){return new Z2(t,s)}get rendererName(){return"number"}};Ux.instance=new Ux;let D7=Ux;class kR{constructor(t,n,r){this.parentField=t,this.values=n,this.span=r,this.key=JSON.stringify({parentField:this.parentField.name,values:this.values.map(i=>i.field.isBasic()?String(i.value):"")}),this.fieldValueMap=new Map;for(const i of this.values)this.fieldValueMap.set(i.field.name,i)}}class d0{constructor(t,n,r){this.pivotedField=t,this.field=n,this.userDefinedPivotDimensions=r}isPivotedColumnField(){return this instanceof d0}}class h0{constructor(t,n,r){this.flattenedField=t,this.field=n,this.name=r}isFlattenedColumnField(){return this instanceof h0}getChildRenderer(t){const n=t[this.flattenedField.name];if(n instanceof m0)return n.childRenderers[this.field.name];throw Error("Could not render flattened table. `# flatten` only supports nests.")}getValue(t){const n=t.column(this.flattenedField.name);if(n.isRecord())return n.column(this.field.name);throw Error("Cannot find nested record within flattened field. `# flatten` only supports nests with no group_bys.")}}function ER(e){return e.isRecord()&&e.tag.has("flatten")}class m0 extends h2{constructor(){super(...arguments),this.childrenStyleDefaults={size:"medium"}}async render(t){var d,h,m;if(t.isNull())return this.document.createElement("span");if(!t.isRecordOrRepeatedRecord())throw new Error("Invalid type for Table Renderer");const n=this.tagged.has("transpose"),r=t.field.fields;if(n&&r.length>20)throw new Error("Transpose limit of 20 columns exceeded.");let i=0,s=0,a=[];a[i]=[];const o=[];let l=0;for(const p of r){if(p.isHidden())continue;const g=this.childRenderers[p.name];if(g instanceof m0&&g.tagged.has("pivot")){const b=g.tagged.textArray("pivot","dimensions");let v,x=[];const $=new Map;for(const w of t.rows){const k=w.column(p.name);if(!k.isNull()){if(!k.isRecordOrRepeatedRecord())throw new Error(`Can not pivot field ${p.name}.`);if(!v){const _=g.calculatePivotDimensions(k,b);v=_.dimensions,x=_.nonDimensions}for(const _ of k.rows){const E=new kR(k.field,v.map(A=>_.column(A.field.name)),x.length),C=E.key;$.get(C)||$.set(C,E)}}}if(!v)throw new Error(`Could not pivot ${p.name}, no data found.`);const S=Array.from($.values()).sort((w,k)=>{for(const _ of v){const E=w.fieldValueMap.get(_.field.name),C=k.fieldValueMap.get(_.field.name);if(E!=null&&E.field.isBasic()&&(C!=null&&C.field.isBasic())&&typeof E==typeof C){if(E.isNull())return C.isNull()?0:1;if(C.isNull())return-1;const A=E.compareTo(C);if(A!==0)return _.dir!=="desc"?A:-A}}return 0});for(const w of S)for(const k of x)o.push(new d0(w,k.field,b)),a[i][s]=g.createHeaderCell(k.field,n,{name:(d=k.flattenedField)==null?void 0:d.name,childRenderer:(h=k.flattenedField)==null?void 0:h.getChildRenderer(g.childRenderers)}),s++;l=Math.max(l,v.length)}else if(ER(p)){const b=p,x=b.fields.map($=>new h0(b,$,`${b.name} ${$.name}`));for(const $ of x)a[i][s]=this.createHeaderCell($.field,n,{name:$.name,childRenderer:$.getChildRenderer(this.childRenderers)}),o.push($),s++}else a[i][s]=this.createHeaderCell(p,n),o.push(p),s++}if(l>0&&o.length>30)throw new Error("Pivot limit of 30 columns exceeded.");if(!n&&this.options.isDrillingEnabled){const p=this.document.createElement("th");p.style.cssText=`
67
67
  padding: 8px;
68
68
  color: var(--malloy-title-color, #505050);
69
69
  border-bottom: 1px solid var(--malloy-border-color, #eaeaea);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@malloydata/render",
3
- "version": "0.0.354",
3
+ "version": "0.0.355",
4
4
  "license": "MIT",
5
5
  "main": "dist/module/index.umd.js",
6
6
  "types": "dist/module/index.d.ts",
@@ -29,8 +29,8 @@
29
29
  "generate-flow": "ts-node ../../scripts/gen-flow.ts"
30
30
  },
31
31
  "dependencies": {
32
- "@malloydata/malloy-interfaces": "0.0.354",
33
- "@malloydata/malloy-tag": "0.0.354",
32
+ "@malloydata/malloy-interfaces": "0.0.355",
33
+ "@malloydata/malloy-tag": "0.0.355",
34
34
  "@tanstack/solid-virtual": "^3.10.4",
35
35
  "lodash": "^4.17.20",
36
36
  "luxon": "^3.5.0",
@@ -42,8 +42,8 @@
42
42
  "vega-lite": "^5.2.0"
43
43
  },
44
44
  "devDependencies": {
45
- "@malloydata/db-duckdb": "0.0.354",
46
- "@malloydata/malloy": "0.0.354",
45
+ "@malloydata/db-duckdb": "0.0.355",
46
+ "@malloydata/malloy": "0.0.355",
47
47
  "@storybook/addon-essentials": "^8.6.15",
48
48
  "@storybook/addon-interactions": "^8.6.15",
49
49
  "@storybook/addon-links": "^8.6.15",