diff --git a/components/charts.templ b/components/charts.templ
new file mode 100644
index 0000000..7c0a0fe
--- /dev/null
+++ b/components/charts.templ
@@ -0,0 +1,703 @@
+package components
+
+import "encoding/json"
+
+// OHLCData represents a single candlestick data point
+type OHLCData struct {
+ Date string `json:"date"`
+ Open float64 `json:"open"`
+ High float64 `json:"high"`
+ Low float64 `json:"low"`
+ Close float64 `json:"close"`
+}
+
+// AreaSeriesData represents time series data for stacked area chart
+type AreaSeriesData struct {
+ Date string `json:"date"`
+ Industry string `json:"industry"`
+ Value float64 `json:"value"`
+}
+
+// BubbleData represents data for bubble/circle packing chart
+type BubbleData struct {
+ Name string `json:"name"`
+ Sector string `json:"sector"`
+ Value float64 `json:"value"`
+}
+
+// TimeSeriesData represents simple time series data
+type TimeSeriesData struct {
+ Date string `json:"date"`
+ Value float64 `json:"value"`
+}
+
+// Helper to convert data to JSON string for JS
+func toJSON(v interface{}) string {
+ b, _ := json.Marshal(v)
+ return string(b)
+}
+
+// RosenCharts global utilities and chart classes
+script initRosenCharts() {
+ window.RosenCharts = {
+ colors: {
+ success: 'var(--wa-color-success)',
+ danger: 'var(--wa-color-danger)',
+ primary: 'var(--wa-color-primary)',
+ neutral400: 'var(--wa-color-neutral-400)',
+ neutral500: 'var(--wa-color-neutral-500)',
+ neutral600: 'var(--wa-color-neutral-600)',
+ surfaceAlt: 'var(--wa-color-surface-alt)',
+ surface: 'var(--wa-color-surface)',
+ fuchsia: { from: '#f0abfc', to: '#e879f9' },
+ purple: { from: '#c4b5fd', to: '#a855f7' },
+ blue: { from: '#93c5fd', to: '#3b82f6' },
+ sky: { from: '#bae6fd', to: '#38bdf8' },
+ orange: { from: '#fed7aa', to: '#fb923c' },
+ yellow: { from: '#fef08a', to: '#facc15' },
+ emerald: { from: '#6ee7b7', to: '#10b981' },
+ red: { from: '#fca5a5', to: '#ef4444' }
+ },
+ formatNumber(value, decimals = 2) {
+ return new Intl.NumberFormat('en-US', {
+ minimumFractionDigits: decimals,
+ maximumFractionDigits: decimals
+ }).format(value);
+ },
+ formatCurrency(value) {
+ return new Intl.NumberFormat('en-US', {
+ style: 'currency',
+ currency: 'USD'
+ }).format(value);
+ },
+ isDesktop() {
+ return window.innerWidth > 1024;
+ },
+ createSVG(tag, attrs = {}) {
+ const el = document.createElementNS('http://www.w3.org/2000/svg', tag);
+ Object.entries(attrs).forEach(([key, value]) => {
+ el.setAttribute(key, value);
+ });
+ return el;
+ },
+ createElement(tag, attrs = {}, children = []) {
+ const el = document.createElement(tag);
+ Object.entries(attrs).forEach(([key, value]) => {
+ if (key === 'style' && typeof value === 'object') {
+ Object.assign(el.style, value);
+ } else if (key === 'className') {
+ el.className = value;
+ } else {
+ el.setAttribute(key, value);
+ }
+ });
+ children.forEach(child => {
+ if (typeof child === 'string') {
+ el.appendChild(document.createTextNode(child));
+ } else if (child) {
+ el.appendChild(child);
+ }
+ });
+ return el;
+ }
+ };
+}
+
+// CandleChart initialization script
+script initCandleChart(containerId string, dataJSON string) {
+ const container = document.getElementById(containerId);
+ if (!container || !window.d3) return;
+
+ const data = JSON.parse(dataJSON);
+ const RC = window.RosenCharts;
+
+ const options = {
+ marginTop: 10,
+ marginRight: 60,
+ marginBottom: 56,
+ marginLeft: 30,
+ height: 288
+ };
+
+ let zoomLevel = 1;
+ let visibleRange = { start: 0, end: data.length - 1 };
+ let mousePosition = null;
+ let hoverData = null;
+
+ function getVisibleData() {
+ return data.slice(visibleRange.start, visibleRange.end + 1);
+ }
+
+ function render() {
+ container.innerHTML = '';
+ container.style.position = 'relative';
+
+ const visibleData = getVisibleData();
+
+ // Create scales
+ const xScale = d3.scaleBand()
+ .domain(visibleData.map(d => d.date))
+ .range([0, 100])
+ .padding(0.3);
+
+ const yMin = d3.min(visibleData, d => d.low) * 0.995;
+ const yMax = d3.max(visibleData, d => d.high) * 1.005;
+ const yScale = d3.scaleLinear()
+ .domain([yMin, yMax])
+ .range([100, 0]);
+
+ // Legend
+ const legend = RC.createElement('div', {
+ style: {
+ display: 'flex',
+ justifyContent: 'space-between',
+ alignItems: 'center',
+ marginBottom: '8px',
+ padding: '4px 32px',
+ background: 'var(--wa-color-surface-alt)',
+ borderRadius: 'var(--wa-radius-s)',
+ fontSize: 'var(--wa-font-size-xs)'
+ }
+ });
+ legend.innerHTML = `
Hover over chart to see OHLC data
`;
+
+ // Chart area
+ const chartArea = RC.createElement('div', {
+ style: {
+ position: 'relative',
+ height: options.height + 'px',
+ width: '100%'
+ }
+ });
+
+ // Y-axis
+ const yAxisContainer = RC.createElement('div', {
+ style: {
+ position: 'absolute',
+ height: 'calc(100% - ' + options.marginTop + 'px - ' + options.marginBottom + 'px)',
+ transform: 'translateY(' + options.marginTop + 'px)',
+ right: 'calc(' + options.marginRight + 'px - 1rem)',
+ overflow: 'visible'
+ }
+ });
+
+ const yTicks = yScale.ticks(6);
+ yTicks.forEach(value => {
+ const label = RC.createElement('div', {
+ style: {
+ position: 'absolute',
+ right: '0%',
+ top: yScale(value) + '%',
+ transform: 'translateY(-50%)',
+ fontSize: 'var(--wa-font-size-xs)',
+ fontVariantNumeric: 'tabular-nums',
+ color: 'var(--wa-color-neutral-400)',
+ width: '100%',
+ textAlign: 'right'
+ }
+ }, [value.toFixed(2)]);
+ yAxisContainer.appendChild(label);
+ });
+
+ // Chart inner
+ const chartInner = RC.createElement('div', {
+ style: {
+ position: 'absolute',
+ inset: 0,
+ height: 'calc(100% - ' + options.marginTop + 'px - ' + options.marginBottom + 'px)',
+ width: 'calc(100% - ' + options.marginLeft + 'px - ' + options.marginRight + 'px)',
+ transform: 'translate(' + options.marginLeft + 'px, ' + options.marginTop + 'px)',
+ overflow: 'visible'
+ }
+ });
+
+ // SVG for grid and wicks
+ const svg = RC.createSVG('svg', {
+ viewBox: '0 0 100 100',
+ preserveAspectRatio: 'none',
+ style: 'overflow: visible; width: 100%; height: 100%;'
+ });
+
+ // Grid lines
+ yTicks.forEach(value => {
+ const line = RC.createSVG('line', {
+ x1: 0, x2: 100,
+ y1: yScale(value), y2: yScale(value),
+ stroke: 'var(--wa-color-neutral-200)',
+ 'stroke-dasharray': '6,5',
+ 'stroke-width': 0.5,
+ 'vector-effect': 'non-scaling-stroke'
+ });
+ svg.appendChild(line);
+ });
+
+ // Wicks
+ visibleData.forEach(d => {
+ const barX = xScale(d.date) + xScale.bandwidth() / 2;
+ const line = RC.createSVG('line', {
+ x1: barX, y1: yScale(d.high),
+ x2: barX, y2: yScale(d.low),
+ stroke: 'var(--wa-color-neutral-300)',
+ 'stroke-width': 1,
+ 'vector-effect': 'non-scaling-stroke'
+ });
+ svg.appendChild(line);
+ });
+
+ chartInner.appendChild(svg);
+
+ // Candle bodies
+ visibleData.forEach(d => {
+ const barWidth = xScale.bandwidth();
+ const barHeight = Math.abs(yScale(d.open) - yScale(d.close));
+ const barX = xScale(d.date);
+ const barY = yScale(Math.max(d.open, d.close));
+ const isUp = d.close > d.open;
+
+ const bar = RC.createElement('div', {
+ style: {
+ position: 'absolute',
+ width: barWidth + '%',
+ height: barHeight + '%',
+ left: barX + '%',
+ top: barY + '%',
+ background: isUp
+ ? 'linear-gradient(to bottom, #6ee7b7, #10b981)'
+ : 'linear-gradient(to bottom, #fca5a5, #ef4444)',
+ borderRadius: '1px'
+ }
+ });
+ chartInner.appendChild(bar);
+ });
+
+ chartArea.appendChild(yAxisContainer);
+ chartArea.appendChild(chartInner);
+
+ container.appendChild(legend);
+ container.appendChild(chartArea);
+
+ // Wheel zoom
+ chartArea.addEventListener('wheel', (e) => {
+ e.preventDefault();
+ const zoomIn = e.deltaY < 0;
+ const zoomFactor = 1.04;
+ const newZoomLevel = zoomIn
+ ? Math.min(zoomLevel * zoomFactor, 20)
+ : Math.max(zoomLevel / zoomFactor, 1);
+
+ const visibleCount = Math.max(5, Math.floor(data.length / newZoomLevel));
+ const newEnd = data.length - 1;
+ const newStart = Math.max(0, newEnd - visibleCount + 1);
+
+ zoomLevel = newZoomLevel;
+ visibleRange = { start: newStart, end: newEnd };
+ render();
+ }, { passive: false });
+ }
+
+ render();
+}
+
+// StackedAreaChart initialization script
+script initStackedAreaChart(containerId string, dataJSON string) {
+ const container = document.getElementById(containerId);
+ if (!container || !window.d3) return;
+
+ const data = JSON.parse(dataJSON);
+ const RC = window.RosenCharts;
+
+ const colors = [
+ { from: '#f5d0fe', to: '#e879f9', bg: '#e879f9' },
+ { from: '#c4b5fd', to: '#a855f7', bg: '#a855f7' },
+ { from: '#bfdbfe', to: '#3b82f6', bg: '#3b82f6' },
+ { from: '#bae6fd', to: '#38bdf8', bg: '#38bdf8' },
+ { from: '#fed7aa', to: '#fb923c', bg: '#fb923c' }
+ ];
+
+ container.innerHTML = '';
+ container.style.position = 'relative';
+
+ const parseDate = d3.utcParse('%Y-%m-%d');
+ const industries = Array.from(new Set(data.map(d => d.industry)));
+
+ const groupedData = Array.from(
+ d3.group(data, d => d.date),
+ ([date, values]) => {
+ const obj = { date: parseDate(date.split('T')[0]) };
+ values.forEach(val => {
+ obj[val.industry] = val.value || 0;
+ });
+ return obj;
+ }
+ );
+
+ const series = d3.stack().keys(industries)(groupedData);
+
+ // Legend
+ const legendContainer = RC.createElement('div', {
+ style: {
+ display: 'flex',
+ textAlign: 'center',
+ gap: '16px',
+ fontSize: 'var(--wa-font-size-xs)',
+ overflowX: 'auto',
+ padding: '0 40px',
+ marginBottom: '32px'
+ }
+ });
+
+ industries.slice().reverse().forEach((industry, i) => {
+ const colorIndex = industries.length - 1 - i;
+ const color = colors[colorIndex % colors.length];
+
+ const item = RC.createElement('div', {
+ style: { display: 'flex', gap: '6px', alignItems: 'center' }
+ });
+
+ const dot = RC.createElement('div', {
+ style: {
+ width: '4px',
+ height: '16px',
+ borderRadius: '9999px',
+ background: color.bg
+ }
+ });
+
+ item.appendChild(dot);
+ item.appendChild(document.createTextNode(industry));
+ legendContainer.appendChild(item);
+ });
+
+ // Chart container
+ const chartContainer = RC.createElement('div', {
+ style: {
+ position: 'relative',
+ height: '256px',
+ width: '100%'
+ }
+ });
+
+ // Scales
+ const xScale = d3.scaleUtc()
+ .domain(d3.extent(groupedData, d => d.date))
+ .range([0, 100]);
+
+ const yScale = d3.scaleLinear()
+ .domain([0, d3.max(series, d => d3.max(d, d => d[1])) || 0])
+ .rangeRound([100, 0]);
+
+ // Area generator
+ const area = d3.area()
+ .x(d => xScale(d.data.date))
+ .y0(d => yScale(d[0]))
+ .y1(d => yScale(d[1]))
+ .curve(d3.curveMonotoneX);
+
+ // SVG
+ const svg = RC.createSVG('svg', {
+ style: 'position: absolute; inset: 0; z-index: 10; height: 100%; width: 100%; overflow: visible;'
+ });
+
+ const innerSvg = RC.createSVG('svg', {
+ viewBox: '0 0 100 100',
+ preserveAspectRatio: 'none',
+ style: 'overflow: visible;'
+ });
+
+ // Gradients
+ const defs = RC.createSVG('defs');
+ series.forEach((_, i) => {
+ const color = colors[i % colors.length];
+ const gradient = RC.createSVG('linearGradient', {
+ id: 'stacked-area-gradient-' + containerId + '-' + i,
+ x1: 0, x2: 0.5, y1: 0.25, y2: 1
+ });
+
+ const stop1 = RC.createSVG('stop', { offset: '0%', 'stop-color': color.from });
+ const stop2 = RC.createSVG('stop', { offset: '80%', 'stop-color': color.to });
+
+ gradient.appendChild(stop1);
+ gradient.appendChild(stop2);
+ defs.appendChild(gradient);
+ });
+ innerSvg.appendChild(defs);
+
+ // Areas
+ series.forEach((layer, layerIndex) => {
+ const path = RC.createSVG('path', {
+ fill: 'url(#stacked-area-gradient-' + containerId + '-' + layerIndex + ')',
+ d: area(layer),
+ stroke: '#ccc',
+ 'stroke-width': '0.05'
+ });
+ innerSvg.appendChild(path);
+ });
+
+ svg.appendChild(innerSvg);
+ chartContainer.appendChild(svg);
+
+ container.appendChild(legendContainer);
+ container.appendChild(chartContainer);
+}
+
+// BubbleChart initialization script
+script initBubbleChart(containerId string, dataJSON string) {
+ const container = document.getElementById(containerId);
+ if (!container || !window.d3) return;
+
+ const data = JSON.parse(dataJSON);
+ const RC = window.RosenCharts;
+
+ const colors = ['#f472b6', '#8b5cf6', '#84cc16', '#38bdf8', '#fb923c'];
+
+ container.innerHTML = '';
+ container.style.position = 'relative';
+ container.style.width = '100%';
+ container.style.aspectRatio = '1';
+ container.style.maxWidth = '18rem';
+ container.style.margin = '0 auto';
+
+ const sectors = Array.from(new Set(data.map(d => d.sector)));
+ const color = d3.scaleOrdinal().domain(sectors).range(colors);
+
+ const pack = d3.pack().size([1000, 1000]).padding(12);
+
+ const root = pack(
+ d3.hierarchy({ children: data }).sum(d => d.value)
+ );
+
+ root.leaves().forEach(d => {
+ const x = d.x;
+ const y = d.y;
+ const r = d.r;
+ const fillColor = color(d.data.sector);
+ const name = d.data.name;
+ const value = d.data.value;
+
+ const bubble = RC.createElement('div', {
+ style: {
+ position: 'absolute',
+ transform: 'translate(-50%, -50%)',
+ display: 'flex',
+ flexDirection: 'column',
+ alignItems: 'center',
+ justifyContent: 'center',
+ left: (x / 1000 * 100) + '%',
+ top: (y / 1000 * 100) + '%',
+ width: (r * 2 / 1000 * 100) + '%',
+ height: (r * 2 / 1000 * 100) + '%',
+ borderRadius: '50%',
+ backgroundColor: fillColor,
+ border: '1px solid rgba(255,255,255,0.2)',
+ cursor: 'default'
+ },
+ title: name + '\n' + d3.format(',d')(value)
+ });
+
+ if (value > 1000) {
+ const nameEl = RC.createElement('div', {
+ style: {
+ color: 'white',
+ textAlign: 'center',
+ whiteSpace: 'nowrap',
+ fontSize: (r / 9) + 'px',
+ lineHeight: (r / 7) + 'px'
+ }
+ }, [name]);
+
+ const valueEl = RC.createElement('div', {
+ style: {
+ color: 'white',
+ textAlign: 'center',
+ whiteSpace: 'nowrap',
+ opacity: 0.7,
+ fontSize: (r / 10) + 'px',
+ lineHeight: (r / 8) + 'px'
+ }
+ }, [d3.format(',d')(value)]);
+
+ bubble.appendChild(nameEl);
+ bubble.appendChild(valueEl);
+ }
+
+ container.appendChild(bubble);
+ });
+}
+
+// SemiFilledAreaChart initialization script
+script initSemiFilledAreaChart(containerId string, dataJSON string, lineColor string, areaFromColor string, areaToColor string) {
+ const container = document.getElementById(containerId);
+ if (!container || !window.d3) return;
+
+ const data = JSON.parse(dataJSON).map(d => ({
+ ...d,
+ date: new Date(d.date)
+ }));
+ const RC = window.RosenCharts;
+
+ container.innerHTML = '';
+ container.style.position = 'relative';
+ container.style.height = '288px';
+ container.style.width = '100%';
+
+ // Scales
+ const xScale = d3.scaleTime()
+ .domain([data[0].date, data[data.length - 1].date])
+ .range([0, 100]);
+
+ const yScale = d3.scaleLinear()
+ .domain([0, d3.max(data, d => d.value) || 0])
+ .range([100, 0]);
+
+ // Line generator
+ const line = d3.line()
+ .x(d => xScale(d.date))
+ .y(d => yScale(d.value))
+ .curve(d3.curveMonotoneX);
+
+ // Area generator
+ const area = d3.area()
+ .x(d => xScale(d.date))
+ .y0(yScale(0))
+ .y1(d => yScale(d.value))
+ .curve(d3.curveMonotoneX);
+
+ // Chart inner
+ const chartInner = RC.createElement('div', {
+ style: {
+ position: 'absolute',
+ inset: 0,
+ height: '100%',
+ width: '100%',
+ overflow: 'visible'
+ }
+ });
+
+ // SVG
+ const svg = RC.createSVG('svg', {
+ viewBox: '0 0 100 100',
+ preserveAspectRatio: 'none',
+ style: 'width: 100%; height: 100%; overflow: visible;'
+ });
+
+ // Gradient
+ const defs = RC.createSVG('defs');
+ const gradient = RC.createSVG('linearGradient', {
+ id: 'semi-filled-gradient-' + containerId,
+ x1: 0, x2: 0, y1: 0, y2: 1
+ });
+
+ const stop1 = RC.createSVG('stop', { offset: '0%', 'stop-color': areaFromColor });
+ const stop2 = RC.createSVG('stop', { offset: '100%', 'stop-color': areaToColor });
+
+ gradient.appendChild(stop1);
+ gradient.appendChild(stop2);
+ defs.appendChild(gradient);
+ svg.appendChild(defs);
+
+ // Area path
+ const areaPath = RC.createSVG('path', {
+ d: area(data),
+ fill: 'url(#semi-filled-gradient-' + containerId + ')'
+ });
+ svg.appendChild(areaPath);
+
+ // Line path
+ const linePath = RC.createSVG('path', {
+ d: line(data),
+ fill: 'none',
+ stroke: lineColor,
+ 'stroke-width': '1.5',
+ 'vector-effect': 'non-scaling-stroke'
+ });
+ svg.appendChild(linePath);
+
+ chartInner.appendChild(svg);
+
+ // X-axis labels
+ data.forEach((day, i) => {
+ if (i % 6 !== 0 || i === 0 || i >= data.length - 3) return;
+
+ const label = RC.createElement('div', {
+ style: {
+ position: 'absolute',
+ left: xScale(day.date) + '%',
+ top: '90%',
+ fontSize: 'var(--wa-font-size-xs)',
+ color: 'var(--wa-color-neutral-500)',
+ transform: 'translateX(-50%)'
+ }
+ }, [day.date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' })]);
+
+ chartInner.appendChild(label);
+ });
+
+ container.appendChild(chartInner);
+
+ // Y-axis labels
+ yScale.ticks(8).forEach((value, i) => {
+ if (i < 1) return;
+
+ const label = RC.createElement('div', {
+ style: {
+ position: 'absolute',
+ top: yScale(value) + '%',
+ right: '3%',
+ fontSize: 'var(--wa-font-size-xs)',
+ fontVariantNumeric: 'tabular-nums',
+ color: 'var(--wa-color-neutral-400)',
+ transform: 'translateY(-50%)'
+ }
+ }, [value.toString()]);
+
+ container.appendChild(label);
+ });
+}
+
+// CandleChart component
+templ CandleChart(id string, data []OHLCData) {
+
+ @initRosenCharts()
+ @initCandleChart(id, toJSON(data))
+}
+
+// StackedAreaChart component
+templ StackedAreaChart(id string, data []AreaSeriesData) {
+
+ @initRosenCharts()
+ @initStackedAreaChart(id, toJSON(data))
+}
+
+// BubbleChart component
+templ BubbleChart(id string, data []BubbleData) {
+
+ @initRosenCharts()
+ @initBubbleChart(id, toJSON(data))
+}
+
+// SemiFilledAreaChart component with customizable colors
+templ SemiFilledAreaChart(id string, data []TimeSeriesData) {
+ @SemiFilledAreaChartWithColors(id, data, "#facc15", "rgba(234, 179, 8, 0.2)", "rgba(234, 179, 8, 0.05)")
+}
+
+// SemiFilledAreaChart with custom colors
+templ SemiFilledAreaChartWithColors(id string, data []TimeSeriesData, lineColor string, areaFromColor string, areaToColor string) {
+
+ @initRosenCharts()
+ @initSemiFilledAreaChart(id, toJSON(data), lineColor, areaFromColor, areaToColor)
+}
+
+// Chart card wrapper for consistent styling
+templ ChartCard(title string, subtitle string) {
+
+
+
+ { title }
+ if subtitle != "" {
+ { subtitle }
+ }
+
+
+ { children... }
+
+}
diff --git a/components/charts_templ.go b/components/charts_templ.go
new file mode 100644
index 0000000..fea1412
--- /dev/null
+++ b/components/charts_templ.go
@@ -0,0 +1,1003 @@
+// Code generated by templ - DO NOT EDIT.
+
+// templ: version: v0.3.977
+package components
+
+//lint:file-ignore SA4006 This context is only used if a nested component is present.
+
+import "github.com/a-h/templ"
+import templruntime "github.com/a-h/templ/runtime"
+
+import "encoding/json"
+
+// OHLCData represents a single candlestick data point
+type OHLCData struct {
+ Date string `json:"date"`
+ Open float64 `json:"open"`
+ High float64 `json:"high"`
+ Low float64 `json:"low"`
+ Close float64 `json:"close"`
+}
+
+// AreaSeriesData represents time series data for stacked area chart
+type AreaSeriesData struct {
+ Date string `json:"date"`
+ Industry string `json:"industry"`
+ Value float64 `json:"value"`
+}
+
+// BubbleData represents data for bubble/circle packing chart
+type BubbleData struct {
+ Name string `json:"name"`
+ Sector string `json:"sector"`
+ Value float64 `json:"value"`
+}
+
+// TimeSeriesData represents simple time series data
+type TimeSeriesData struct {
+ Date string `json:"date"`
+ Value float64 `json:"value"`
+}
+
+// Helper to convert data to JSON string for JS
+func toJSON(v interface{}) string {
+ b, _ := json.Marshal(v)
+ return string(b)
+}
+
+// RosenCharts global utilities and chart classes
+func initRosenCharts() templ.ComponentScript {
+ return templ.ComponentScript{
+ Name: `__templ_initRosenCharts_9c0e`,
+ Function: `function __templ_initRosenCharts_9c0e(){window.RosenCharts = {
+ colors: {
+ success: 'var(--wa-color-success)',
+ danger: 'var(--wa-color-danger)',
+ primary: 'var(--wa-color-primary)',
+ neutral400: 'var(--wa-color-neutral-400)',
+ neutral500: 'var(--wa-color-neutral-500)',
+ neutral600: 'var(--wa-color-neutral-600)',
+ surfaceAlt: 'var(--wa-color-surface-alt)',
+ surface: 'var(--wa-color-surface)',
+ fuchsia: { from: '#f0abfc', to: '#e879f9' },
+ purple: { from: '#c4b5fd', to: '#a855f7' },
+ blue: { from: '#93c5fd', to: '#3b82f6' },
+ sky: { from: '#bae6fd', to: '#38bdf8' },
+ orange: { from: '#fed7aa', to: '#fb923c' },
+ yellow: { from: '#fef08a', to: '#facc15' },
+ emerald: { from: '#6ee7b7', to: '#10b981' },
+ red: { from: '#fca5a5', to: '#ef4444' }
+ },
+ formatNumber(value, decimals = 2) {
+ return new Intl.NumberFormat('en-US', {
+ minimumFractionDigits: decimals,
+ maximumFractionDigits: decimals
+ }).format(value);
+ },
+ formatCurrency(value) {
+ return new Intl.NumberFormat('en-US', {
+ style: 'currency',
+ currency: 'USD'
+ }).format(value);
+ },
+ isDesktop() {
+ return window.innerWidth > 1024;
+ },
+ createSVG(tag, attrs = {}) {
+ const el = document.createElementNS('http://www.w3.org/2000/svg', tag);
+ Object.entries(attrs).forEach(([key, value]) => {
+ el.setAttribute(key, value);
+ });
+ return el;
+ },
+ createElement(tag, attrs = {}, children = []) {
+ const el = document.createElement(tag);
+ Object.entries(attrs).forEach(([key, value]) => {
+ if (key === 'style' && typeof value === 'object') {
+ Object.assign(el.style, value);
+ } else if (key === 'className') {
+ el.className = value;
+ } else {
+ el.setAttribute(key, value);
+ }
+ });
+ children.forEach(child => {
+ if (typeof child === 'string') {
+ el.appendChild(document.createTextNode(child));
+ } else if (child) {
+ el.appendChild(child);
+ }
+ });
+ return el;
+ }
+ };
+}`,
+ Call: templ.SafeScript(`__templ_initRosenCharts_9c0e`),
+ CallInline: templ.SafeScriptInline(`__templ_initRosenCharts_9c0e`),
+ }
+}
+
+// CandleChart initialization script
+func initCandleChart(containerId string, dataJSON string) templ.ComponentScript {
+ return templ.ComponentScript{
+ Name: `__templ_initCandleChart_55d6`,
+ Function: `function __templ_initCandleChart_55d6(containerId, dataJSON){const container = document.getElementById(containerId);
+ if (!container || !window.d3) return;
+
+ const data = JSON.parse(dataJSON);
+ const RC = window.RosenCharts;
+
+ const options = {
+ marginTop: 10,
+ marginRight: 60,
+ marginBottom: 56,
+ marginLeft: 30,
+ height: 288
+ };
+
+ let zoomLevel = 1;
+ let visibleRange = { start: 0, end: data.length - 1 };
+ let mousePosition = null;
+ let hoverData = null;
+
+ function getVisibleData() {
+ return data.slice(visibleRange.start, visibleRange.end + 1);
+ }
+
+ function render() {
+ container.innerHTML = '';
+ container.style.position = 'relative';
+
+ const visibleData = getVisibleData();
+
+ // Create scales
+ const xScale = d3.scaleBand()
+ .domain(visibleData.map(d => d.date))
+ .range([0, 100])
+ .padding(0.3);
+
+ const yMin = d3.min(visibleData, d => d.low) * 0.995;
+ const yMax = d3.max(visibleData, d => d.high) * 1.005;
+ const yScale = d3.scaleLinear()
+ .domain([yMin, yMax])
+ .range([100, 0]);
+
+ // Legend
+ const legend = RC.createElement('div', {
+ style: {
+ display: 'flex',
+ justifyContent: 'space-between',
+ alignItems: 'center',
+ marginBottom: '8px',
+ padding: '4px 32px',
+ background: 'var(--wa-color-surface-alt)',
+ borderRadius: 'var(--wa-radius-s)',
+ fontSize: 'var(--wa-font-size-xs)'
+ }
+ });
+ legend.innerHTML = ` + "`" + `Hover over chart to see OHLC data
` + "`" + `;
+
+ // Chart area
+ const chartArea = RC.createElement('div', {
+ style: {
+ position: 'relative',
+ height: options.height + 'px',
+ width: '100%'
+ }
+ });
+
+ // Y-axis
+ const yAxisContainer = RC.createElement('div', {
+ style: {
+ position: 'absolute',
+ height: 'calc(100% - ' + options.marginTop + 'px - ' + options.marginBottom + 'px)',
+ transform: 'translateY(' + options.marginTop + 'px)',
+ right: 'calc(' + options.marginRight + 'px - 1rem)',
+ overflow: 'visible'
+ }
+ });
+
+ const yTicks = yScale.ticks(6);
+ yTicks.forEach(value => {
+ const label = RC.createElement('div', {
+ style: {
+ position: 'absolute',
+ right: '0%',
+ top: yScale(value) + '%',
+ transform: 'translateY(-50%)',
+ fontSize: 'var(--wa-font-size-xs)',
+ fontVariantNumeric: 'tabular-nums',
+ color: 'var(--wa-color-neutral-400)',
+ width: '100%',
+ textAlign: 'right'
+ }
+ }, [value.toFixed(2)]);
+ yAxisContainer.appendChild(label);
+ });
+
+ // Chart inner
+ const chartInner = RC.createElement('div', {
+ style: {
+ position: 'absolute',
+ inset: 0,
+ height: 'calc(100% - ' + options.marginTop + 'px - ' + options.marginBottom + 'px)',
+ width: 'calc(100% - ' + options.marginLeft + 'px - ' + options.marginRight + 'px)',
+ transform: 'translate(' + options.marginLeft + 'px, ' + options.marginTop + 'px)',
+ overflow: 'visible'
+ }
+ });
+
+ // SVG for grid and wicks
+ const svg = RC.createSVG('svg', {
+ viewBox: '0 0 100 100',
+ preserveAspectRatio: 'none',
+ style: 'overflow: visible; width: 100%; height: 100%;'
+ });
+
+ // Grid lines
+ yTicks.forEach(value => {
+ const line = RC.createSVG('line', {
+ x1: 0, x2: 100,
+ y1: yScale(value), y2: yScale(value),
+ stroke: 'var(--wa-color-neutral-200)',
+ 'stroke-dasharray': '6,5',
+ 'stroke-width': 0.5,
+ 'vector-effect': 'non-scaling-stroke'
+ });
+ svg.appendChild(line);
+ });
+
+ // Wicks
+ visibleData.forEach(d => {
+ const barX = xScale(d.date) + xScale.bandwidth() / 2;
+ const line = RC.createSVG('line', {
+ x1: barX, y1: yScale(d.high),
+ x2: barX, y2: yScale(d.low),
+ stroke: 'var(--wa-color-neutral-300)',
+ 'stroke-width': 1,
+ 'vector-effect': 'non-scaling-stroke'
+ });
+ svg.appendChild(line);
+ });
+
+ chartInner.appendChild(svg);
+
+ // Candle bodies
+ visibleData.forEach(d => {
+ const barWidth = xScale.bandwidth();
+ const barHeight = Math.abs(yScale(d.open) - yScale(d.close));
+ const barX = xScale(d.date);
+ const barY = yScale(Math.max(d.open, d.close));
+ const isUp = d.close > d.open;
+
+ const bar = RC.createElement('div', {
+ style: {
+ position: 'absolute',
+ width: barWidth + '%',
+ height: barHeight + '%',
+ left: barX + '%',
+ top: barY + '%',
+ background: isUp
+ ? 'linear-gradient(to bottom, #6ee7b7, #10b981)'
+ : 'linear-gradient(to bottom, #fca5a5, #ef4444)',
+ borderRadius: '1px'
+ }
+ });
+ chartInner.appendChild(bar);
+ });
+
+ chartArea.appendChild(yAxisContainer);
+ chartArea.appendChild(chartInner);
+
+ container.appendChild(legend);
+ container.appendChild(chartArea);
+
+ // Wheel zoom
+ chartArea.addEventListener('wheel', (e) => {
+ e.preventDefault();
+ const zoomIn = e.deltaY < 0;
+ const zoomFactor = 1.04;
+ const newZoomLevel = zoomIn
+ ? Math.min(zoomLevel * zoomFactor, 20)
+ : Math.max(zoomLevel / zoomFactor, 1);
+
+ const visibleCount = Math.max(5, Math.floor(data.length / newZoomLevel));
+ const newEnd = data.length - 1;
+ const newStart = Math.max(0, newEnd - visibleCount + 1);
+
+ zoomLevel = newZoomLevel;
+ visibleRange = { start: newStart, end: newEnd };
+ render();
+ }, { passive: false });
+ }
+
+ render();
+}`,
+ Call: templ.SafeScript(`__templ_initCandleChart_55d6`, containerId, dataJSON),
+ CallInline: templ.SafeScriptInline(`__templ_initCandleChart_55d6`, containerId, dataJSON),
+ }
+}
+
+// StackedAreaChart initialization script
+func initStackedAreaChart(containerId string, dataJSON string) templ.ComponentScript {
+ return templ.ComponentScript{
+ Name: `__templ_initStackedAreaChart_1646`,
+ Function: `function __templ_initStackedAreaChart_1646(containerId, dataJSON){const container = document.getElementById(containerId);
+ if (!container || !window.d3) return;
+
+ const data = JSON.parse(dataJSON);
+ const RC = window.RosenCharts;
+
+ const colors = [
+ { from: '#f5d0fe', to: '#e879f9', bg: '#e879f9' },
+ { from: '#c4b5fd', to: '#a855f7', bg: '#a855f7' },
+ { from: '#bfdbfe', to: '#3b82f6', bg: '#3b82f6' },
+ { from: '#bae6fd', to: '#38bdf8', bg: '#38bdf8' },
+ { from: '#fed7aa', to: '#fb923c', bg: '#fb923c' }
+ ];
+
+ container.innerHTML = '';
+ container.style.position = 'relative';
+
+ const parseDate = d3.utcParse('%Y-%m-%d');
+ const industries = Array.from(new Set(data.map(d => d.industry)));
+
+ const groupedData = Array.from(
+ d3.group(data, d => d.date),
+ ([date, values]) => {
+ const obj = { date: parseDate(date.split('T')[0]) };
+ values.forEach(val => {
+ obj[val.industry] = val.value || 0;
+ });
+ return obj;
+ }
+ );
+
+ const series = d3.stack().keys(industries)(groupedData);
+
+ // Legend
+ const legendContainer = RC.createElement('div', {
+ style: {
+ display: 'flex',
+ textAlign: 'center',
+ gap: '16px',
+ fontSize: 'var(--wa-font-size-xs)',
+ overflowX: 'auto',
+ padding: '0 40px',
+ marginBottom: '32px'
+ }
+ });
+
+ industries.slice().reverse().forEach((industry, i) => {
+ const colorIndex = industries.length - 1 - i;
+ const color = colors[colorIndex % colors.length];
+
+ const item = RC.createElement('div', {
+ style: { display: 'flex', gap: '6px', alignItems: 'center' }
+ });
+
+ const dot = RC.createElement('div', {
+ style: {
+ width: '4px',
+ height: '16px',
+ borderRadius: '9999px',
+ background: color.bg
+ }
+ });
+
+ item.appendChild(dot);
+ item.appendChild(document.createTextNode(industry));
+ legendContainer.appendChild(item);
+ });
+
+ // Chart container
+ const chartContainer = RC.createElement('div', {
+ style: {
+ position: 'relative',
+ height: '256px',
+ width: '100%'
+ }
+ });
+
+ // Scales
+ const xScale = d3.scaleUtc()
+ .domain(d3.extent(groupedData, d => d.date))
+ .range([0, 100]);
+
+ const yScale = d3.scaleLinear()
+ .domain([0, d3.max(series, d => d3.max(d, d => d[1])) || 0])
+ .rangeRound([100, 0]);
+
+ // Area generator
+ const area = d3.area()
+ .x(d => xScale(d.data.date))
+ .y0(d => yScale(d[0]))
+ .y1(d => yScale(d[1]))
+ .curve(d3.curveMonotoneX);
+
+ // SVG
+ const svg = RC.createSVG('svg', {
+ style: 'position: absolute; inset: 0; z-index: 10; height: 100%; width: 100%; overflow: visible;'
+ });
+
+ const innerSvg = RC.createSVG('svg', {
+ viewBox: '0 0 100 100',
+ preserveAspectRatio: 'none',
+ style: 'overflow: visible;'
+ });
+
+ // Gradients
+ const defs = RC.createSVG('defs');
+ series.forEach((_, i) => {
+ const color = colors[i % colors.length];
+ const gradient = RC.createSVG('linearGradient', {
+ id: 'stacked-area-gradient-' + containerId + '-' + i,
+ x1: 0, x2: 0.5, y1: 0.25, y2: 1
+ });
+
+ const stop1 = RC.createSVG('stop', { offset: '0%', 'stop-color': color.from });
+ const stop2 = RC.createSVG('stop', { offset: '80%', 'stop-color': color.to });
+
+ gradient.appendChild(stop1);
+ gradient.appendChild(stop2);
+ defs.appendChild(gradient);
+ });
+ innerSvg.appendChild(defs);
+
+ // Areas
+ series.forEach((layer, layerIndex) => {
+ const path = RC.createSVG('path', {
+ fill: 'url(#stacked-area-gradient-' + containerId + '-' + layerIndex + ')',
+ d: area(layer),
+ stroke: '#ccc',
+ 'stroke-width': '0.05'
+ });
+ innerSvg.appendChild(path);
+ });
+
+ svg.appendChild(innerSvg);
+ chartContainer.appendChild(svg);
+
+ container.appendChild(legendContainer);
+ container.appendChild(chartContainer);
+}`,
+ Call: templ.SafeScript(`__templ_initStackedAreaChart_1646`, containerId, dataJSON),
+ CallInline: templ.SafeScriptInline(`__templ_initStackedAreaChart_1646`, containerId, dataJSON),
+ }
+}
+
+// BubbleChart initialization script
+func initBubbleChart(containerId string, dataJSON string) templ.ComponentScript {
+ return templ.ComponentScript{
+ Name: `__templ_initBubbleChart_9cee`,
+ Function: `function __templ_initBubbleChart_9cee(containerId, dataJSON){const container = document.getElementById(containerId);
+ if (!container || !window.d3) return;
+
+ const data = JSON.parse(dataJSON);
+ const RC = window.RosenCharts;
+
+ const colors = ['#f472b6', '#8b5cf6', '#84cc16', '#38bdf8', '#fb923c'];
+
+ container.innerHTML = '';
+ container.style.position = 'relative';
+ container.style.width = '100%';
+ container.style.aspectRatio = '1';
+ container.style.maxWidth = '18rem';
+ container.style.margin = '0 auto';
+
+ const sectors = Array.from(new Set(data.map(d => d.sector)));
+ const color = d3.scaleOrdinal().domain(sectors).range(colors);
+
+ const pack = d3.pack().size([1000, 1000]).padding(12);
+
+ const root = pack(
+ d3.hierarchy({ children: data }).sum(d => d.value)
+ );
+
+ root.leaves().forEach(d => {
+ const x = d.x;
+ const y = d.y;
+ const r = d.r;
+ const fillColor = color(d.data.sector);
+ const name = d.data.name;
+ const value = d.data.value;
+
+ const bubble = RC.createElement('div', {
+ style: {
+ position: 'absolute',
+ transform: 'translate(-50%, -50%)',
+ display: 'flex',
+ flexDirection: 'column',
+ alignItems: 'center',
+ justifyContent: 'center',
+ left: (x / 1000 * 100) + '%',
+ top: (y / 1000 * 100) + '%',
+ width: (r * 2 / 1000 * 100) + '%',
+ height: (r * 2 / 1000 * 100) + '%',
+ borderRadius: '50%',
+ backgroundColor: fillColor,
+ border: '1px solid rgba(255,255,255,0.2)',
+ cursor: 'default'
+ },
+ title: name + '\n' + d3.format(',d')(value)
+ });
+
+ if (value > 1000) {
+ const nameEl = RC.createElement('div', {
+ style: {
+ color: 'white',
+ textAlign: 'center',
+ whiteSpace: 'nowrap',
+ fontSize: (r / 9) + 'px',
+ lineHeight: (r / 7) + 'px'
+ }
+ }, [name]);
+
+ const valueEl = RC.createElement('div', {
+ style: {
+ color: 'white',
+ textAlign: 'center',
+ whiteSpace: 'nowrap',
+ opacity: 0.7,
+ fontSize: (r / 10) + 'px',
+ lineHeight: (r / 8) + 'px'
+ }
+ }, [d3.format(',d')(value)]);
+
+ bubble.appendChild(nameEl);
+ bubble.appendChild(valueEl);
+ }
+
+ container.appendChild(bubble);
+ });
+}`,
+ Call: templ.SafeScript(`__templ_initBubbleChart_9cee`, containerId, dataJSON),
+ CallInline: templ.SafeScriptInline(`__templ_initBubbleChart_9cee`, containerId, dataJSON),
+ }
+}
+
+// SemiFilledAreaChart initialization script
+func initSemiFilledAreaChart(containerId string, dataJSON string, lineColor string, areaFromColor string, areaToColor string) templ.ComponentScript {
+ return templ.ComponentScript{
+ Name: `__templ_initSemiFilledAreaChart_71b8`,
+ Function: `function __templ_initSemiFilledAreaChart_71b8(containerId, dataJSON, lineColor, areaFromColor, areaToColor){const container = document.getElementById(containerId);
+ if (!container || !window.d3) return;
+
+ const data = JSON.parse(dataJSON).map(d => ({
+ ...d,
+ date: new Date(d.date)
+ }));
+ const RC = window.RosenCharts;
+
+ container.innerHTML = '';
+ container.style.position = 'relative';
+ container.style.height = '288px';
+ container.style.width = '100%';
+
+ // Scales
+ const xScale = d3.scaleTime()
+ .domain([data[0].date, data[data.length - 1].date])
+ .range([0, 100]);
+
+ const yScale = d3.scaleLinear()
+ .domain([0, d3.max(data, d => d.value) || 0])
+ .range([100, 0]);
+
+ // Line generator
+ const line = d3.line()
+ .x(d => xScale(d.date))
+ .y(d => yScale(d.value))
+ .curve(d3.curveMonotoneX);
+
+ // Area generator
+ const area = d3.area()
+ .x(d => xScale(d.date))
+ .y0(yScale(0))
+ .y1(d => yScale(d.value))
+ .curve(d3.curveMonotoneX);
+
+ // Chart inner
+ const chartInner = RC.createElement('div', {
+ style: {
+ position: 'absolute',
+ inset: 0,
+ height: '100%',
+ width: '100%',
+ overflow: 'visible'
+ }
+ });
+
+ // SVG
+ const svg = RC.createSVG('svg', {
+ viewBox: '0 0 100 100',
+ preserveAspectRatio: 'none',
+ style: 'width: 100%; height: 100%; overflow: visible;'
+ });
+
+ // Gradient
+ const defs = RC.createSVG('defs');
+ const gradient = RC.createSVG('linearGradient', {
+ id: 'semi-filled-gradient-' + containerId,
+ x1: 0, x2: 0, y1: 0, y2: 1
+ });
+
+ const stop1 = RC.createSVG('stop', { offset: '0%', 'stop-color': areaFromColor });
+ const stop2 = RC.createSVG('stop', { offset: '100%', 'stop-color': areaToColor });
+
+ gradient.appendChild(stop1);
+ gradient.appendChild(stop2);
+ defs.appendChild(gradient);
+ svg.appendChild(defs);
+
+ // Area path
+ const areaPath = RC.createSVG('path', {
+ d: area(data),
+ fill: 'url(#semi-filled-gradient-' + containerId + ')'
+ });
+ svg.appendChild(areaPath);
+
+ // Line path
+ const linePath = RC.createSVG('path', {
+ d: line(data),
+ fill: 'none',
+ stroke: lineColor,
+ 'stroke-width': '1.5',
+ 'vector-effect': 'non-scaling-stroke'
+ });
+ svg.appendChild(linePath);
+
+ chartInner.appendChild(svg);
+
+ // X-axis labels
+ data.forEach((day, i) => {
+ if (i % 6 !== 0 || i === 0 || i >= data.length - 3) return;
+
+ const label = RC.createElement('div', {
+ style: {
+ position: 'absolute',
+ left: xScale(day.date) + '%',
+ top: '90%',
+ fontSize: 'var(--wa-font-size-xs)',
+ color: 'var(--wa-color-neutral-500)',
+ transform: 'translateX(-50%)'
+ }
+ }, [day.date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' })]);
+
+ chartInner.appendChild(label);
+ });
+
+ container.appendChild(chartInner);
+
+ // Y-axis labels
+ yScale.ticks(8).forEach((value, i) => {
+ if (i < 1) return;
+
+ const label = RC.createElement('div', {
+ style: {
+ position: 'absolute',
+ top: yScale(value) + '%',
+ right: '3%',
+ fontSize: 'var(--wa-font-size-xs)',
+ fontVariantNumeric: 'tabular-nums',
+ color: 'var(--wa-color-neutral-400)',
+ transform: 'translateY(-50%)'
+ }
+ }, [value.toString()]);
+
+ container.appendChild(label);
+ });
+}`,
+ Call: templ.SafeScript(`__templ_initSemiFilledAreaChart_71b8`, containerId, dataJSON, lineColor, areaFromColor, areaToColor),
+ CallInline: templ.SafeScriptInline(`__templ_initSemiFilledAreaChart_71b8`, containerId, dataJSON, lineColor, areaFromColor, areaToColor),
+ }
+}
+
+// CandleChart component
+func CandleChart(id string, data []OHLCData) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var1 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var1 == nil {
+ templ_7745c5c3_Var1 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = initRosenCharts().Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = initCandleChart(id, toJSON(data)).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+// StackedAreaChart component
+func StackedAreaChart(id string, data []AreaSeriesData) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var3 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var3 == nil {
+ templ_7745c5c3_Var3 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = initRosenCharts().Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = initStackedAreaChart(id, toJSON(data)).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+// BubbleChart component
+func BubbleChart(id string, data []BubbleData) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var5 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var5 == nil {
+ templ_7745c5c3_Var5 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = initRosenCharts().Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = initBubbleChart(id, toJSON(data)).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+// SemiFilledAreaChart component with customizable colors
+func SemiFilledAreaChart(id string, data []TimeSeriesData) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var7 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var7 == nil {
+ templ_7745c5c3_Var7 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = SemiFilledAreaChartWithColors(id, data, "#facc15", "rgba(234, 179, 8, 0.2)", "rgba(234, 179, 8, 0.05)").Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+// SemiFilledAreaChart with custom colors
+func SemiFilledAreaChartWithColors(id string, data []TimeSeriesData, lineColor string, areaFromColor string, areaToColor string) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var8 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var8 == nil {
+ templ_7745c5c3_Var8 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = initRosenCharts().Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = initSemiFilledAreaChart(id, toJSON(data), lineColor, areaFromColor, areaToColor).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+// Chart card wrapper for consistent styling
+func ChartCard(title string, subtitle string) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var10 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var10 == nil {
+ templ_7745c5c3_Var10 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var11 string
+ templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(title)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/charts.templ`, Line: 695, Col: 38}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, " ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ if subtitle != "" {
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var12 string
+ templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(subtitle)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/charts.templ`, Line: 697, Col: 87}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templ_7745c5c3_Var10.Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+var _ = templruntime.GeneratedTemplate
diff --git a/components/drawers.templ b/components/drawers.templ
new file mode 100644
index 0000000..c6de425
--- /dev/null
+++ b/components/drawers.templ
@@ -0,0 +1,374 @@
+package components
+
+// TokenOption represents a token choice in dropdowns
+type TokenOption struct {
+ Symbol string
+ Name string
+ Balance string
+ Color string
+ Initials string
+}
+
+// DefaultTokenOptions returns the standard token options for drawers
+func DefaultTokenOptions() []TokenOption {
+ return []TokenOption{
+ {Symbol: "SNR", Name: "Sonr", Balance: "8,432.50", Color: "linear-gradient(135deg, #17c2ff, #0090ff)", Initials: "S"},
+ {Symbol: "ETH", Name: "Ethereum", Balance: "2.847", Color: "#627eea", Initials: "E"},
+ {Symbol: "USDC", Name: "USD Coin", Balance: "1,250.00", Color: "#2775ca", Initials: "U"},
+ {Symbol: "AVAX", Name: "Avalanche", Balance: "24.83", Color: "#e84142", Initials: "A"},
+ }
+}
+
+// ReceiveDrawer component for receiving tokens
+templ ReceiveDrawer(tokens []TokenOption, walletAddress string) {
+
+
+
+ @drawerStyles()
+}
+
+// SendDrawer component for sending tokens
+templ SendDrawer(tokens []TokenOption) {
+
+
+
+ @drawerStyles()
+}
+
+// SwapDrawer component for swapping tokens
+templ SwapDrawer(tokens []TokenOption) {
+
+
+
+ @drawerStyles()
+ @swapDirectionScript()
+}
+
+// Script to handle swap direction button
+script swapDirectionScript() {
+ document.getElementById('swap-direction-btn')?.addEventListener('click', function() {
+ this.style.transform = this.style.transform === 'rotate(180deg)' ? '' : 'rotate(180deg)';
+ });
+}
+
+// Drawer-specific styles
+templ drawerStyles() {
+
+}
+
+// AllDrawers renders all three drawers together for convenience
+templ AllDrawers(tokens []TokenOption, walletAddress string) {
+ @ReceiveDrawer(tokens, walletAddress)
+ @SendDrawer(tokens)
+ @SwapDrawer(tokens)
+}
+
+// DrawerTriggerScript provides the JavaScript to wire up drawer triggers
+script drawerTriggerScript() {
+ // Open receive drawer
+ document.querySelectorAll('[data-drawer-open="receive"]').forEach(el => {
+ el.addEventListener('click', () => {
+ document.getElementById('receive-drawer').open = true;
+ });
+ });
+
+ // Open send drawer
+ document.querySelectorAll('[data-drawer-open="send"]').forEach(el => {
+ el.addEventListener('click', () => {
+ document.getElementById('send-drawer').open = true;
+ });
+ });
+
+ // Open swap drawer
+ document.querySelectorAll('[data-drawer-open="swap"]').forEach(el => {
+ el.addEventListener('click', () => {
+ document.getElementById('swap-drawer').open = true;
+ });
+ });
+}
+
+// DrawerTriggers component to initialize drawer triggers
+templ DrawerTriggers() {
+ @drawerTriggerScript()
+}
diff --git a/components/drawers_templ.go b/components/drawers_templ.go
new file mode 100644
index 0000000..530db65
--- /dev/null
+++ b/components/drawers_templ.go
@@ -0,0 +1,564 @@
+// Code generated by templ - DO NOT EDIT.
+
+// templ: version: v0.3.977
+package components
+
+//lint:file-ignore SA4006 This context is only used if a nested component is present.
+
+import "github.com/a-h/templ"
+import templruntime "github.com/a-h/templ/runtime"
+
+// TokenOption represents a token choice in dropdowns
+type TokenOption struct {
+ Symbol string
+ Name string
+ Balance string
+ Color string
+ Initials string
+}
+
+// DefaultTokenOptions returns the standard token options for drawers
+func DefaultTokenOptions() []TokenOption {
+ return []TokenOption{
+ {Symbol: "SNR", Name: "Sonr", Balance: "8,432.50", Color: "linear-gradient(135deg, #17c2ff, #0090ff)", Initials: "S"},
+ {Symbol: "ETH", Name: "Ethereum", Balance: "2.847", Color: "#627eea", Initials: "E"},
+ {Symbol: "USDC", Name: "USD Coin", Balance: "1,250.00", Color: "#2775ca", Initials: "U"},
+ {Symbol: "AVAX", Name: "Avalanche", Balance: "24.83", Color: "#e84142", Initials: "A"},
+ }
+}
+
+// ReceiveDrawer component for receiving tokens
+func ReceiveDrawer(tokens []TokenOption, walletAddress string) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var1 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var1 == nil {
+ templ_7745c5c3_Var1 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = drawerStyles().Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+// SendDrawer component for sending tokens
+func SendDrawer(tokens []TokenOption) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var10 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var10 == nil {
+ templ_7745c5c3_Var10 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = drawerStyles().Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+// SwapDrawer component for swapping tokens
+func SwapDrawer(tokens []TokenOption) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var16 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var16 == nil {
+ templ_7745c5c3_Var16 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = drawerStyles().Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = swapDirectionScript().Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+// Script to handle swap direction button
+func swapDirectionScript() templ.ComponentScript {
+ return templ.ComponentScript{
+ Name: `__templ_swapDirectionScript_d885`,
+ Function: `function __templ_swapDirectionScript_d885(){document.getElementById('swap-direction-btn')?.addEventListener('click', function() {
+ this.style.transform = this.style.transform === 'rotate(180deg)' ? '' : 'rotate(180deg)';
+ });
+}`,
+ Call: templ.SafeScript(`__templ_swapDirectionScript_d885`),
+ CallInline: templ.SafeScriptInline(`__templ_swapDirectionScript_d885`),
+ }
+}
+
+// Drawer-specific styles
+func drawerStyles() templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var23 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var23 == nil {
+ templ_7745c5c3_Var23 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+// AllDrawers renders all three drawers together for convenience
+func AllDrawers(tokens []TokenOption, walletAddress string) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var24 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var24 == nil {
+ templ_7745c5c3_Var24 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = ReceiveDrawer(tokens, walletAddress).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = SendDrawer(tokens).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = SwapDrawer(tokens).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+// DrawerTriggerScript provides the JavaScript to wire up drawer triggers
+func drawerTriggerScript() templ.ComponentScript {
+ return templ.ComponentScript{
+ Name: `__templ_drawerTriggerScript_084e`,
+ Function: `function __templ_drawerTriggerScript_084e(){// Open receive drawer
+ document.querySelectorAll('[data-drawer-open="receive"]').forEach(el => {
+ el.addEventListener('click', () => {
+ document.getElementById('receive-drawer').open = true;
+ });
+ });
+
+ // Open send drawer
+ document.querySelectorAll('[data-drawer-open="send"]').forEach(el => {
+ el.addEventListener('click', () => {
+ document.getElementById('send-drawer').open = true;
+ });
+ });
+
+ // Open swap drawer
+ document.querySelectorAll('[data-drawer-open="swap"]').forEach(el => {
+ el.addEventListener('click', () => {
+ document.getElementById('swap-drawer').open = true;
+ });
+ });
+}`,
+ Call: templ.SafeScript(`__templ_drawerTriggerScript_084e`),
+ CallInline: templ.SafeScriptInline(`__templ_drawerTriggerScript_084e`),
+ }
+}
+
+// DrawerTriggers component to initialize drawer triggers
+func DrawerTriggers() templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var25 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var25 == nil {
+ templ_7745c5c3_Var25 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = drawerTriggerScript().Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+var _ = templruntime.GeneratedTemplate