web-mojo 2.1.46

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.
Files changed (91) hide show
  1. package/LICENSE +198 -0
  2. package/README.md +510 -0
  3. package/dist/admin.cjs.js +2 -0
  4. package/dist/admin.cjs.js.map +1 -0
  5. package/dist/admin.css +621 -0
  6. package/dist/admin.es.js +7973 -0
  7. package/dist/admin.es.js.map +1 -0
  8. package/dist/auth.cjs.js +2 -0
  9. package/dist/auth.cjs.js.map +1 -0
  10. package/dist/auth.css +804 -0
  11. package/dist/auth.es.js +2168 -0
  12. package/dist/auth.es.js.map +1 -0
  13. package/dist/charts.cjs.js +2 -0
  14. package/dist/charts.cjs.js.map +1 -0
  15. package/dist/charts.css +1002 -0
  16. package/dist/charts.es.js +16 -0
  17. package/dist/charts.es.js.map +1 -0
  18. package/dist/chunks/ContextMenu-BrHqj0fn.js +80 -0
  19. package/dist/chunks/ContextMenu-BrHqj0fn.js.map +1 -0
  20. package/dist/chunks/ContextMenu-gEcpSz56.js +2 -0
  21. package/dist/chunks/ContextMenu-gEcpSz56.js.map +1 -0
  22. package/dist/chunks/DataView-DPryYpEW.js +2 -0
  23. package/dist/chunks/DataView-DPryYpEW.js.map +1 -0
  24. package/dist/chunks/DataView-DjZQrpba.js +843 -0
  25. package/dist/chunks/DataView-DjZQrpba.js.map +1 -0
  26. package/dist/chunks/Dialog-BsRx4eg3.js +2 -0
  27. package/dist/chunks/Dialog-BsRx4eg3.js.map +1 -0
  28. package/dist/chunks/Dialog-DSlctbon.js +1377 -0
  29. package/dist/chunks/Dialog-DSlctbon.js.map +1 -0
  30. package/dist/chunks/FilePreviewView-BmFHzK5K.js +5868 -0
  31. package/dist/chunks/FilePreviewView-BmFHzK5K.js.map +1 -0
  32. package/dist/chunks/FilePreviewView-DcdRl_ta.js +2 -0
  33. package/dist/chunks/FilePreviewView-DcdRl_ta.js.map +1 -0
  34. package/dist/chunks/FormView-CmBuwKGD.js +2 -0
  35. package/dist/chunks/FormView-CmBuwKGD.js.map +1 -0
  36. package/dist/chunks/FormView-DqUBMPJ9.js +5054 -0
  37. package/dist/chunks/FormView-DqUBMPJ9.js.map +1 -0
  38. package/dist/chunks/MetricsChart-CM4CI6eA.js +2095 -0
  39. package/dist/chunks/MetricsChart-CM4CI6eA.js.map +1 -0
  40. package/dist/chunks/MetricsChart-CPidSMaN.js +2 -0
  41. package/dist/chunks/MetricsChart-CPidSMaN.js.map +1 -0
  42. package/dist/chunks/PDFViewer-BNQlnS83.js +2 -0
  43. package/dist/chunks/PDFViewer-BNQlnS83.js.map +1 -0
  44. package/dist/chunks/PDFViewer-Dyo-Oeyd.js +946 -0
  45. package/dist/chunks/PDFViewer-Dyo-Oeyd.js.map +1 -0
  46. package/dist/chunks/Page-B524zSQs.js +351 -0
  47. package/dist/chunks/Page-B524zSQs.js.map +1 -0
  48. package/dist/chunks/Page-BFgj0pAA.js +2 -0
  49. package/dist/chunks/Page-BFgj0pAA.js.map +1 -0
  50. package/dist/chunks/TokenManager-BXNva8Jk.js +287 -0
  51. package/dist/chunks/TokenManager-BXNva8Jk.js.map +1 -0
  52. package/dist/chunks/TokenManager-Bzn4guFm.js +2 -0
  53. package/dist/chunks/TokenManager-Bzn4guFm.js.map +1 -0
  54. package/dist/chunks/TopNav-D3I3_25f.js +371 -0
  55. package/dist/chunks/TopNav-D3I3_25f.js.map +1 -0
  56. package/dist/chunks/TopNav-MDjL4kV0.js +2 -0
  57. package/dist/chunks/TopNav-MDjL4kV0.js.map +1 -0
  58. package/dist/chunks/User-BalfYTEF.js +3 -0
  59. package/dist/chunks/User-BalfYTEF.js.map +1 -0
  60. package/dist/chunks/User-DwIT-CTQ.js +1937 -0
  61. package/dist/chunks/User-DwIT-CTQ.js.map +1 -0
  62. package/dist/chunks/WebApp-B6mgbNn2.js +4767 -0
  63. package/dist/chunks/WebApp-B6mgbNn2.js.map +1 -0
  64. package/dist/chunks/WebApp-DqDowtkl.js +2 -0
  65. package/dist/chunks/WebApp-DqDowtkl.js.map +1 -0
  66. package/dist/chunks/WebSocketClient-D6i85jl2.js +2 -0
  67. package/dist/chunks/WebSocketClient-D6i85jl2.js.map +1 -0
  68. package/dist/chunks/WebSocketClient-Dvl3AYx1.js +297 -0
  69. package/dist/chunks/WebSocketClient-Dvl3AYx1.js.map +1 -0
  70. package/dist/core.css +1181 -0
  71. package/dist/css/web-mojo.css +17 -0
  72. package/dist/css-manifest.json +6 -0
  73. package/dist/docit.cjs.js +2 -0
  74. package/dist/docit.cjs.js.map +1 -0
  75. package/dist/docit.es.js +959 -0
  76. package/dist/docit.es.js.map +1 -0
  77. package/dist/index.cjs.js +2 -0
  78. package/dist/index.cjs.js.map +1 -0
  79. package/dist/index.es.js +2681 -0
  80. package/dist/index.es.js.map +1 -0
  81. package/dist/lightbox.cjs.js +2 -0
  82. package/dist/lightbox.cjs.js.map +1 -0
  83. package/dist/lightbox.css +606 -0
  84. package/dist/lightbox.es.js +3737 -0
  85. package/dist/lightbox.es.js.map +1 -0
  86. package/dist/loader.es.js +115 -0
  87. package/dist/loader.umd.js +85 -0
  88. package/dist/portal.css +2446 -0
  89. package/dist/table.css +639 -0
  90. package/dist/toast.css +181 -0
  91. package/package.json +179 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MetricsChart-CPidSMaN.js","sources":["../../src/extensions/charts/BaseChart.js","../../src/extensions/charts/SeriesChart.js","../../src/extensions/charts/PieChart.js","../../src/extensions/charts/MetricsChart.js"],"sourcesContent":["/**\n * BaseChart - Foundation class for all chart components in MOJO framework\n * Uses Chart.js 4.x with API integration, refresh capabilities, and event system\n */\n\nimport View from '@core/View.js';\nimport WebSocketClient from '@core/services/WebSocketClient.js';\nimport dataFormatter from '@core/utils/DataFormatter.js';\n\nexport default class BaseChart extends View {\n constructor(options = {}) {\n super({\n ...options,\n className: `chart-component ${options.className || ''}`,\n tagName: 'div'\n });\n\n // Chart.js instance\n this.chart = null;\n this.chartType = options.chartType || 'line';\n\n // Data source options\n this.endpoint = options.endpoint || null;\n this.data = options.data || null;\n this.dataTransform = options.dataTransform || null; // Function to transform API data\n\n // Refresh options\n this.refreshInterval = options.refreshInterval || null; // ms\n this.autoRefresh = options.autoRefresh !== false;\n this.refreshTimer = null;\n\n // WebSocket for real-time updates\n this.websocketUrl = options.websocketUrl || null;\n this.websocket = null;\n this.websocketReconnect = options.websocketReconnect !== false;\n\n // Dimensions\n this.width = options.width || null;\n this.height = options.height || null;\n // Precompute inline content style for initial render (Mustache section)\n this.contentStyle = [\n this.width ? `width: ${this.width}px;` : '',\n this.height ? `height: ${this.height}px;` : ''\n ].filter(Boolean).join(' ');\n if (options.maintainAspectRatio === undefined) {\n options.maintainAspectRatio = true;\n }\n\n // Chart configuration\n this.title = options.title || '';\n this.chartTitle = options.chartTitle || '';\n this.chartOptions = {\n responsive: true,\n maintainAspectRatio: options.maintainAspectRatio,\n interaction: {\n intersect: false,\n mode: 'index'\n },\n plugins: {\n legend: {\n display: options.showLegend !== false,\n position: options.legendPosition || 'top'\n },\n title: {\n display: !!this.chartTitle,\n text: this.chartTitle\n },\n tooltip: {\n enabled: options.showTooltips !== false,\n backgroundColor: 'rgba(0,0,0,0.8)',\n titleColor: '#fff',\n bodyColor: '#fff',\n borderColor: 'rgba(255,255,255,0.1)',\n borderWidth: 1\n }\n },\n ...options.chartOptions\n };\n\n // Axis configuration with DataFormatter support\n this.xAxis = options.xAxis || null;\n this.yAxis = options.yAxis || null;\n this.tooltipFormatters = options.tooltip || {};\n\n // Theme and appearance\n this.theme = options.theme || 'light';\n this.colorScheme = options.colorScheme || 'default';\n this.animations = options.animations !== false;\n\n // Export options\n this.exportEnabled = options.exportEnabled === true;\n this.exportFormats = options.exportFormats || ['png', 'jpg', 'csv'];\n\n // State\n this.isLoading = false;\n this.hasError = false;\n this.lastFetch = null;\n this.dataPoints = 0;\n\n // Canvas element\n this.canvas = null;\n\n // Chart.js CDN URL - can be customized\n this.chartJsCdn = options.chartJsCdn || 'https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.js';\n\n // DataFormatter instance (use singleton)\n this.dataFormatter = dataFormatter;\n\n // Template data properties (available to Mustache)\n\n // Store essential listeners for cleanup\n this._essentialListeners = [];\n }\n\n get refreshEnabled() {\n return !!(this.endpoint || this.websocketUrl);\n }\n\n buildDefaultHeaderConfig() {\n return {\n titleHtml: this.title || '',\n chartTitle: this.chartTitle || '',\n showExport: this.exportEnabled === true,\n showRefresh: this.refreshEnabled,\n showTheme: true,\n controls: []\n };\n }\n\n async getTemplate() {\n return `\n <div class=\"chart-container\" data-theme=\"{{theme}}\">\n <div class=\"chart-header mb-3\">\n <div data-container=\"header\"></div>\n <div class=\"chart-header-aux mt-2\">\n <div data-container=\"header-aux\"></div>\n </div>\n </div>\n\n <div class=\"chart-content position-relative\" {{#contentStyle}}style=\"{{contentStyle}}\"{{/contentStyle}}>\n <canvas class=\"chart-canvas\" data-container=\"canvas\"></canvas>\n\n <!-- Loading overlay -->\n <div class=\"chart-overlay d-none\" data-loading>\n <div class=\"d-flex flex-column align-items-center\">\n <div class=\"spinner-border text-primary mb-2\" role=\"status\">\n <span class=\"visually-hidden\">Loading...</span>\n </div>\n <small class=\"text-muted\">Loading chart data...</small>\n </div>\n </div>\n\n <!-- Error overlay -->\n <div class=\"chart-overlay d-none\" data-error>\n <div class=\"alert alert-danger mb-0\" role=\"alert\">\n <div class=\"d-flex align-items-center\">\n <i class=\"bi bi-exclamation-triangle me-2\"></i>\n <div class=\"flex-grow-1\">\n <strong>Error:</strong> <span class=\"error-message\">Failed to load chart data</span>\n </div>\n <button class=\"btn btn-sm btn-outline-danger ms-2\" data-action=\"retry-load\">\n <i class=\"bi bi-arrow-clockwise\"></i> Retry\n </button>\n </div>\n </div>\n </div>\n\n <!-- No data overlay -->\n <div class=\"chart-overlay d-none\" data-no-data>\n <div class=\"text-center text-muted\">\n <i class=\"bi bi-bar-chart display-4 mb-3 opacity-50\"></i>\n <p class=\"mb-0\">No data available</p>\n {{#refreshEnabled}}\n <button class=\"btn btn-sm btn-outline-secondary mt-2\" data-action=\"refresh-chart\">\n <i class=\"bi bi-arrow-clockwise\"></i> Refresh\n </button>\n {{/refreshEnabled}}\n </div>\n </div>\n\n <!-- WebSocket status indicator -->\n <div class=\"position-absolute top-0 end-0 mt-2 me-2\">\n <span class=\"badge bg-success websocket-status\" style=\"display: none;\" data-websocket-status>\n <i class=\"bi bi-wifi\"></i> Live\n </span>\n </div>\n </div>\n\n <div class=\"chart-footer mt-2\" style=\"display: none;\">\n <div class=\"row\">\n <div class=\"col\">\n <small class=\"text-muted\">\n <i class=\"bi bi-graph-up me-1\"></i>\n <span class=\"data-points\">0 data points</span>\n </small>\n </div>\n <div class=\"col text-end\">\n <small class=\"text-muted refresh-info\">\n Auto-refresh: <span class=\"refresh-status\">Off</span>\n </small>\n </div>\n </div>\n </div>\n </div>\n `;\n }\n\n async onInit() {\n // Initialize Chart.js\n await this.initializeChartJS();\n\n // Build and create header view in onInit\n try {\n const headerConfig = this.headerConfig || (this.buildDefaultHeaderConfig ? this.buildDefaultHeaderConfig() : null);\n if (headerConfig) {\n this.headerView = new ChartHeaderView({ ...headerConfig, containerId: 'header' });\n this.addChild(this.headerView);\n }\n } catch (e) {\n // Header is optional; ignore if missing\n console.debug('ChartHeaderView not available:', e?.message);\n }\n }\n\n async onAfterRender() {\n // Cache DOM elements\n this.canvas = this.element.querySelector('.chart-canvas');\n this.titleElement = this.element.querySelector('.chart-title');\n this.contentElement = this.element.querySelector('.chart-content');\n this.footerElement = this.element.querySelector('.chart-footer');\n\n // Overlay elements\n this.loadingOverlay = this.element.querySelector('[data-loading]');\n this.errorOverlay = this.element.querySelector('[data-error]');\n this.noDataOverlay = this.element.querySelector('[data-no-data]');\n this.websocketStatus = this.element.querySelector('[data-websocket-status]');\n\n // Control elements\n this.refreshBtn = this.element.querySelector('.refresh-btn');\n this.themeToggle = this.element.querySelector('.theme-toggle');\n\n // Apply initial theme\n this.applyTheme();\n\n // Header is created in onInit\n\n // First-time data fetch occurs here, before creating the chart\n if (this.endpoint) {\n await this.fetchData(); // fetchData will call updateChart() which creates the chart\n await this.updateChart(this.data, true);\n if (this.height || this.width) {\n this._updateChartDimensions();\n }\n } else if (this.data) {\n await this.updateChart(this.data, true);\n if (this.height || this.width) {\n this._updateChartDimensions();\n }\n } else {\n this.showNoData();\n }\n\n // Set up auto-refresh\n if (this.autoRefresh && this.refreshInterval && this.endpoint) {\n this.startAutoRefresh();\n }\n\n // Set up WebSocket\n if (this.websocketUrl) {\n await this.connectWebSocket();\n }\n\n // Set up resize observer\n this.setupResizeObserver();\n\n // Show footer with stats\n this.showFooter();\n }\n\n async initializeChartJS() {\n try {\n // Load Chart.js if not already loaded\n if (typeof window.Chart === 'undefined') {\n await this.loadChartJS();\n }\n\n return true;\n } catch (error) {\n console.error('Failed to initialize Chart.js:', error);\n this.showError('Failed to initialize charting library');\n return false;\n }\n }\n\n async loadChartJS() {\n return new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.src = this.chartJsCdn;\n script.onload = () => {\n console.log('Chart.js loaded successfully');\n resolve();\n };\n script.onerror = () => {\n reject(new Error('Failed to load Chart.js'));\n };\n document.head.appendChild(script);\n });\n }\n\n // Action Handlers (EventDelegate)\n async handleActionRefreshChart() {\n await this.fetchData();\n }\n\n async handleActionRetryLoad() {\n this.hideError();\n await this.fetchData();\n }\n\n async handleActionExportChart(event, element) {\n const format = element.getAttribute('data-format') || 'png';\n this.exportChart(format);\n }\n\n async handleActionToggleTheme() {\n this.toggleTheme();\n }\n\n async handleActionSetChartType(event, element) {\n const type = element.getAttribute('data-type');\n if (type && this.setChartType) {\n await this.setChartType(type);\n }\n }\n\n // Data Management\n async fetchData() {\n if (!this.endpoint) return;\n\n this.showLoading();\n this.setRefreshButtonState(true);\n\n try {\n const response = await fetch(this.endpoint, {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json',\n 'Accept': 'application/json'\n }\n });\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n let data = await response.json();\n\n // Transform data if transformer provided\n if (this.dataTransform && typeof this.dataTransform === 'function') {\n data = this.dataTransform(data);\n }\n\n this.lastFetch = new Date();\n this.data = data;\n this.updateLastUpdatedTime();\n\n // Emit success event\n const eventBus = this.getApp()?.events;\n if (eventBus) {\n eventBus.emit('chart:data-loaded', {\n chart: this,\n data,\n source: 'http',\n endpoint: this.endpoint\n });\n }\n\n } catch (error) {\n console.error('Failed to fetch chart data:', error);\n this.showError(`Failed to load data: ${error.message}`);\n\n // Emit error event\n this.emit('chart:error', {\n chart: this,\n error,\n source: 'http',\n endpoint: this.endpoint\n });\n } finally {\n this.hideLoading();\n this.setRefreshButtonState(false);\n }\n }\n\n async connectWebSocket() {\n if (!this.websocketUrl) return;\n\n try {\n this.websocket = new WebSocketClient({\n url: this.websocketUrl,\n autoReconnect: this.websocketReconnect,\n dataTransform: this.dataTransform,\n eventBus: this.getApp()?.events,\n debug: false\n });\n\n // Set up WebSocket event handlers\n this.websocket.on('connected', () => {\n this.showWebSocketStatus(true);\n console.log('WebSocket connected for chart data');\n });\n\n this.websocket.on('disconnected', () => {\n this.showWebSocketStatus(false);\n console.log('WebSocket disconnected');\n });\n\n this.websocket.on('data', async (data) => {\n await this.updateChart(data);\n this.updateLastUpdatedTime();\n\n // Emit real-time update event\n this.emit('chart:data-updated', {\n chart: this,\n data,\n source: 'websocket'\n });\n });\n\n this.websocket.on('error', (error) => {\n console.error('WebSocket error:', error);\n this.showWebSocketStatus(false, 'error');\n });\n\n // Connect\n await this.websocket.connect();\n\n } catch (error) {\n console.error('Failed to connect WebSocket:', error);\n this.showWebSocketStatus(false, 'error');\n }\n }\n\n async updateChart(data, recreate=false) {\n if (!data) {\n this.showNoData();\n return;\n }\n\n this.data = data;\n\n // If canvas is not ready yet (called before render), defer chart creation\n if (!this.canvas || typeof window.Chart === 'undefined') {\n return;\n }\n\n this.hideAllOverlays();\n\n // Process data with axis formatters\n const processedData = this.processChartData(data);\n\n if (recreate && this.chart) {\n this.chart.destroy();\n this.chart = null;\n }\n\n if (this.chart) {\n // Update existing chart\n this.chart.data = processedData;\n this.chart.update('none'); // No animation for real-time updates\n } else {\n // Create new chart\n await this.createChart(processedData);\n }\n\n // Update stats\n this.updateDataStats(processedData);\n\n if (this.height || this.width) {\n this._updateChartDimensions();\n }\n\n }\n\n processChartData(data) {\n // This method should be overridden by subclasses\n // Base implementation just applies formatters to labels if configured\n\n let processedData = { ...data };\n\n // Apply formatters to labels if xAxis formatter is configured (normalized)\n const xAxisCfg = this.normalizeAxis(this.xAxis);\n if (xAxisCfg && xAxisCfg.formatter && processedData.labels) {\n processedData.labels = processedData.labels.map(label =>\n this.dataFormatter.pipe(label, xAxisCfg.formatter)\n );\n }\n\n return processedData;\n }\n\n async createChart(data) {\n if (!this.canvas || typeof window.Chart === 'undefined') {\n throw new Error('Chart.js not loaded or canvas not found');\n }\n\n // Chart.js handles canvas dimensions internally\n // Container dimensions are set via CSS in template\n\n // Build chart configuration\n const config = {\n type: this.chartType,\n data: data,\n options: this.buildChartOptions()\n };\n\n try {\n this.chart = new window.Chart(this.canvas, config);\n\n // Set up chart event handlers\n this.setupChartEventHandlers();\n\n } catch (error) {\n console.error('Failed to create chart:', error);\n throw error;\n }\n }\n\n buildChartOptions() {\n const options = { ...this.chartOptions };\n\n // Handle custom dimensions\n if (this.width || this.height) {\n options.responsive = true;\n options.maintainAspectRatio = false;\n }\n\n // Build scales from normalized axis configs\n const xAxisCfg = this.normalizeAxis(this.xAxis);\n const yAxisCfg = this.normalizeAxis(this.yAxis);\n\n options.scales = options.scales || {};\n\n // X-axis\n options.scales.x = {\n type: this._detectAxisType(this.data, xAxisCfg, 'x'),\n display: true,\n title: {\n display: !!xAxisCfg.label,\n text: xAxisCfg.label || ''\n },\n grid: { display: true },\n ticks: {}\n };\n if (xAxisCfg.formatter) {\n options.scales.x.ticks.callback = this._createFormatterCallback(xAxisCfg.formatter);\n }\n\n // Y-axis\n options.scales.y = {\n type: this._detectAxisType(this.data, yAxisCfg, 'y'),\n display: true,\n beginAtZero: yAxisCfg.beginAtZero !== false,\n title: {\n display: !!yAxisCfg.label,\n text: yAxisCfg.label || ''\n },\n grid: { display: true },\n ticks: {}\n };\n if (yAxisCfg.formatter) {\n options.scales.y.ticks.callback = this._createFormatterCallback(yAxisCfg.formatter);\n }\n\n // Apply theme colors\n this.applyThemeToOptions(options);\n\n // Configure tooltips with formatters\n if (this.tooltipFormatters.x || this.tooltipFormatters.y) {\n options.plugins = options.plugins || {};\n options.plugins.tooltip = options.plugins.tooltip || {};\n options.plugins.tooltip.callbacks = options.plugins.tooltip.callbacks || {};\n\n if (this.tooltipFormatters.x) {\n options.plugins.tooltip.callbacks.title = (context) => {\n const value = context[0]?.label;\n return value ? this.dataFormatter.pipe(value, this.tooltipFormatters.x) : value;\n };\n }\n\n if (this.tooltipFormatters.y) {\n options.plugins.tooltip.callbacks.label = (context) => {\n const value = context.raw;\n const formattedValue = this.dataFormatter.pipe(value, this.tooltipFormatters.y);\n return `${context.dataset.label}: ${formattedValue}`;\n };\n }\n }\n\n // Allow subclasses to tweak chart options (e.g., indexAxis, stacking)\n if (typeof this.applySubclassChartOptions === 'function') {\n this.applySubclassChartOptions(options);\n }\n\n return options;\n }\n\n // Helper method to create Chart.js callback from MOJO formatter\n _createFormatterCallback(formatter) {\n if (!formatter) return null;\n\n return (value) => {\n try {\n return this.dataFormatter.pipe(value, formatter);\n } catch (error) {\n console.warn(`Chart formatter error:`, error);\n return value;\n }\n };\n }\n\n // Normalize axis configuration into a consistent object\n normalizeAxis(axisConfig) {\n if (!axisConfig) return {};\n if (typeof axisConfig === 'string') {\n // Simple formatter shorthand\n return { formatter: axisConfig };\n }\n if (typeof axisConfig === 'object') {\n const { formatter, label, type, beginAtZero, ...rest } = axisConfig;\n return { formatter, label, type, beginAtZero, ...rest };\n }\n return {};\n }\n\n // Smart axis type detection from data\n _detectAxisType(data, axisConfig, axisName = 'x') {\n // If user explicitly set the type, use it\n if (axisConfig && axisConfig.type) {\n return axisConfig.type;\n }\n\n // If formatter suggests a type\n if (axisConfig && axisConfig.formatter) {\n const formatter = axisConfig.formatter.toLowerCase();\n if (formatter.includes('date') || formatter.includes('time')) {\n return 'time';\n }\n }\n\n // Auto-detect from data based on axis\n if (data) {\n if (axisName === 'x' && data.labels && data.labels.length > 0) {\n // X-axis: check labels\n const firstLabel = data.labels[0];\n\n // Check if labels are strings (category axis)\n if (typeof firstLabel === 'string') {\n // If it's a string that's not purely numeric, treat as category\n // This handles cases like \"01:00\", \"Jan\", \"Q1 2023\", etc.\n if (!/^\\d+\\.?\\d*$/.test(firstLabel.trim())) {\n return 'category';\n }\n }\n\n // Check if labels are dates\n if (firstLabel instanceof Date ||\n (typeof firstLabel === 'string' && !isNaN(Date.parse(firstLabel)))) {\n return 'time';\n }\n\n // Numeric labels default to linear\n return 'linear';\n } else if (axisName === 'y' && data.datasets && data.datasets.length > 0) {\n // Y-axis: check data values\n const firstDataset = data.datasets[0];\n if (firstDataset.data && firstDataset.data.length > 0) {\n const firstValue = firstDataset.data[0];\n\n // If it's numeric data, use linear\n if (typeof firstValue === 'number' || !isNaN(parseFloat(firstValue))) {\n return 'linear';\n }\n\n // If it's string data, use category\n return 'category';\n }\n }\n }\n\n // Default based on axis\n return axisName === 'x' ? 'category' : 'linear';\n }\n\n setupChartEventHandlers() {\n if (!this.chart) return;\n\n // Click events\n this.chart.options.onClick = (event, elements) => {\n if (elements.length > 0) {\n const element = elements[0];\n const datasetIndex = element.datasetIndex;\n const index = element.index;\n const value = this.chart.data.datasets[datasetIndex].data[index];\n const label = this.chart.data.labels[index];\n\n // Emit click event\n this.emit('chart:point-clicked', {\n chart: this,\n datasetIndex,\n index,\n value,\n label,\n dataset: this.chart.data.datasets[datasetIndex]\n });\n }\n };\n\n // Hover events\n this.chart.options.onHover = (event, elements) => {\n this.canvas.style.cursor = elements.length > 0 ? 'pointer' : 'default';\n };\n }\n\n // Theme Management\n applyTheme() {\n this.element.setAttribute('data-theme', this.theme);\n\n if (this.chart) {\n this.chart.options = this.buildChartOptions();\n this.chart.update('none');\n }\n }\n\n applyThemeToOptions(options) {\n const isDark = this.theme === 'dark';\n\n // Grid and axis colors\n if (options.scales) {\n Object.keys(options.scales).forEach(scaleId => {\n const scale = options.scales[scaleId];\n scale.grid = scale.grid || {};\n scale.ticks = scale.ticks || {};\n\n scale.grid.color = isDark ? 'rgba(255,255,255,0.1)' : 'rgba(0,0,0,0.1)';\n scale.ticks.color = isDark ? '#e9ecef' : '#495057';\n });\n }\n\n // Legend colors\n if (options.plugins?.legend) {\n options.plugins.legend.labels = options.plugins.legend.labels || {};\n options.plugins.legend.labels.color = isDark ? '#e9ecef' : '#495057';\n }\n\n // Title colors\n if (options.plugins?.title) {\n options.plugins.title.color = isDark ? '#ffffff' : '#212529';\n }\n }\n\n toggleTheme() {\n this.theme = this.theme === 'light' ? 'dark' : 'light';\n this.applyTheme();\n\n // Emit theme change event\n this.emit('chart:theme-changed', {\n chart: this,\n theme: this.theme\n });\n }\n\n // Auto-refresh Management\n startAutoRefresh() {\n if (!this.endpoint || !this.refreshInterval) return;\n\n this.stopAutoRefresh();\n\n this.refreshTimer = setInterval(() => {\n this.fetchData();\n }, this.refreshInterval);\n\n this.updateRefreshStatus(true);\n }\n\n stopAutoRefresh() {\n if (this.refreshTimer) {\n clearInterval(this.refreshTimer);\n this.refreshTimer = null;\n }\n this.updateRefreshStatus(false);\n }\n\n // Export Functionality\n exportChart(format = 'png') {\n if (!this.chart) return;\n\n try {\n if (format === 'csv') {\n this.exportCSV();\n } else {\n const url = this.chart.toBase64Image('image/' + format, 1);\n const link = document.createElement('a');\n link.download = `chart-${Date.now()}.${format}`;\n link.href = url;\n link.click();\n\n // Emit export event\n this.emit('chart:exported', {\n chart: this,\n format,\n filename: link.download\n });\n }\n\n } catch (error) {\n console.error('Failed to export chart:', error);\n this.showError('Failed to export chart');\n }\n }\n\n // CSV Export Functionality\n exportCSV() {\n if (!this.chart || !this.chart.data) return;\n\n try {\n const csvData = this.generateCSV();\n const blob = new Blob([csvData], { type: 'text/csv;charset=utf-8;' });\n const url = URL.createObjectURL(blob);\n\n const link = document.createElement('a');\n link.download = `chart-data-${Date.now()}.csv`;\n link.href = url;\n link.click();\n\n // Clean up\n URL.revokeObjectURL(url);\n\n // Emit export event\n this.emit('chart:exported', {\n chart: this,\n format: 'csv',\n filename: link.download\n });\n\n } catch (error) {\n console.error('Failed to export CSV:', error);\n this.showError('Failed to export CSV');\n }\n }\n\n // Generate CSV data from chart\n generateCSV() {\n const data = this.chart.data;\n const labels = data.labels || [];\n const datasets = data.datasets || [];\n\n // Create CSV header\n let csv = 'Label';\n datasets.forEach(dataset => {\n csv += ',' + (dataset.label || 'Data');\n });\n csv += '\\n';\n\n // Add data rows\n labels.forEach((label, index) => {\n csv += `\"${label}\"`;\n datasets.forEach(dataset => {\n const value = dataset.data[index] || '';\n csv += ',' + value;\n });\n csv += '\\n';\n });\n\n return csv;\n }\n\n // UI State Management\n showLoading() {\n this.isLoading = true;\n this.hideAllOverlays();\n this.loadingOverlay?.classList.remove('d-none');\n }\n\n hideLoading() {\n this.isLoading = false;\n this.loadingOverlay?.classList.add('d-none');\n }\n\n showError(message) {\n this.hasError = true;\n this.hideAllOverlays();\n const errorMessageEl = this.errorOverlay?.querySelector('.error-message');\n if (errorMessageEl) {\n errorMessageEl.textContent = message;\n }\n this.errorOverlay?.classList.remove('d-none');\n }\n\n hideError() {\n this.hasError = false;\n this.errorOverlay?.classList.add('d-none');\n }\n\n showNoData() {\n this.hideAllOverlays();\n this.noDataOverlay?.classList.remove('d-none');\n }\n\n hideAllOverlays() {\n this.loadingOverlay?.classList.add('d-none');\n this.errorOverlay?.classList.add('d-none');\n this.noDataOverlay?.classList.add('d-none');\n }\n\n showWebSocketStatus(connected, status = 'connected') {\n if (!this.websocketStatus) return;\n\n if (connected) {\n this.websocketStatus.className = 'badge bg-success';\n this.websocketStatus.innerHTML = '<i class=\"bi bi-wifi\"></i> Live';\n } else {\n this.websocketStatus.className = status === 'error' ? 'badge bg-danger' : 'badge bg-secondary';\n this.websocketStatus.innerHTML = status === 'error' ?\n '<i class=\"bi bi-wifi-off\"></i> Error' :\n '<i class=\"bi bi-wifi-off\"></i> Offline';\n }\n\n this.websocketStatus.style.display = 'inline-block';\n }\n\n setRefreshButtonState(loading) {\n if (!this.refreshBtn) return;\n\n const icon = this.refreshBtn.querySelector('i');\n if (loading) {\n this.refreshBtn.disabled = true;\n icon?.classList.add('spin');\n } else {\n this.refreshBtn.disabled = false;\n icon?.classList.remove('spin');\n }\n }\n\n updateLastUpdatedTime() {\n const lastUpdatedEl = this.element.querySelector('.last-updated');\n const timestampEl = this.element.querySelector('.timestamp');\n\n if (lastUpdatedEl && timestampEl) {\n timestampEl.textContent = new Date().toLocaleTimeString();\n lastUpdatedEl.style.display = 'block';\n }\n }\n\n updateRefreshStatus(active) {\n const statusEl = this.element.querySelector('.refresh-status');\n if (statusEl) {\n statusEl.textContent = active ?\n `Every ${this.refreshInterval / 1000}s` : 'Off';\n }\n }\n\n updateDataStats(data) {\n // Count data points\n let points = 0;\n if (data.datasets) {\n points = data.datasets.reduce((sum, dataset) => {\n return sum + (dataset.data ? dataset.data.length : 0);\n }, 0);\n }\n\n this.dataPoints = points;\n\n const dataPointsEl = this.element.querySelector('.data-points');\n if (dataPointsEl) {\n dataPointsEl.textContent = `${points} data point${points !== 1 ? 's' : ''}`;\n }\n }\n\n showFooter() {\n if (this.footerElement) {\n this.footerElement.style.display = 'block';\n }\n }\n\n setupResizeObserver() {\n if (!window.ResizeObserver || !this.contentElement) return;\n\n const resizeObserver = new ResizeObserver(() => {\n if (this.chart) {\n this.chart.resize();\n }\n });\n\n resizeObserver.observe(this.contentElement);\n this._resizeObserver = resizeObserver;\n }\n\n // Cleanup\n async onBeforeDestroy() {\n // Stop auto-refresh\n this.stopAutoRefresh();\n\n // Disconnect WebSocket\n if (this.websocket) {\n this.websocket.disconnect();\n this.websocket = null;\n }\n\n // Destroy Chart.js instance\n if (this.chart) {\n this.chart.destroy();\n this.chart = null;\n }\n\n // Clean up resize observer\n if (this._resizeObserver) {\n this._resizeObserver.disconnect();\n this._resizeObserver = null;\n }\n\n // Clean up essential listeners\n if (this._essentialListeners) {\n this._essentialListeners.forEach(({ el, type, fn }) => {\n if (el) el.removeEventListener(type, fn);\n });\n this._essentialListeners = [];\n }\n\n // Emit destroy event\n this.emit('chart:destroyed', { chart: this });\n }\n\n // Public API\n setData(data) {\n this.data = data;\n return this.updateChart(data);\n }\n\n setEndpoint(endpoint) {\n this.endpoint = endpoint;\n if (endpoint) {\n return this.fetchData();\n }\n }\n\n setWebSocketUrl(url) {\n if (this.websocket) {\n this.websocket.disconnect();\n }\n this.websocketUrl = url;\n if (url) {\n return this.connectWebSocket();\n }\n }\n\n // Dimension Control Methods\n setWidth(width) {\n this.width = width;\n this.contentStyle = [\n this.width ? `width: ${this.width}px;` : '',\n this.height ? `height: ${this.height}px;` : ''\n ].filter(Boolean).join(' ');\n if (this.contentElement) {\n this._updateChartDimensions();\n }\n }\n\n setHeight(height) {\n this.height = height;\n this.contentStyle = [\n this.width ? `width: ${this.width}px;` : '',\n this.height ? `height: ${this.height}px;` : ''\n ].filter(Boolean).join(' ');\n if (this.contentElement) {\n this._updateChartDimensions();\n }\n }\n\n setDimensions(width, height) {\n this.width = width;\n this.height = height;\n this.contentStyle = [\n this.width ? `width: ${this.width}px;` : '',\n this.height ? `height: ${this.height}px;` : ''\n ].filter(Boolean).join(' ');\n if (this.contentElement) {\n this._updateChartDimensions();\n }\n }\n\n _updateChartDimensions() {\n if (this.chart) {\n // Update chart options for custom dimensions\n if (this.width || this.height) {\n this.chart.options.responsive = true;\n this.chart.options.maintainAspectRatio = false;\n if (this.width && this.contentElement) {\n this.contentElement.style.width = this.width ? this.width + 'px' : '';\n }\n if (this.height && this.contentElement) {\n this.contentElement.style.height = this.height ? this.height + 'px' : '';\n }\n } else {\n this.chart.options.responsive = true;\n this.chart.options.maintainAspectRatio = this.chartOptions.maintainAspectRatio;\n }\n this.chart.resize();\n }\n }\n\n resize() {\n if (this.chart) {\n this.chart.resize();\n }\n }\n\n refresh() {\n return this.fetchData();\n }\n\n export(format = 'png') {\n return this.exportChart(format);\n }\n\n setTheme(theme) {\n this.theme = theme;\n this.applyTheme();\n }\n\n getStats() {\n return {\n isLoading: this.isLoading,\n hasError: this.hasError,\n dataPoints: this.dataPoints,\n lastFetch: this.lastFetch,\n theme: this.theme,\n chartType: this.chartType,\n autoRefresh: !!this.refreshTimer,\n websocketConnected: this.websocket?.isConnected || false\n };\n }\n}\n\nclass ChartHeaderView extends View {\n constructor(options = {}) {\n super({\n ...options,\n className: `mojo-chart-header ${options.className || ''}`,\n tagName: 'div'\n });\n\n // Header configuration\n this.titleHtml = options.titleHtml || '';\n this.chartTitle = options.chartTitle || '';\n this.showExport = options.showExport === true;\n this.showRefresh = !!options.showRefresh;\n this.showTheme = false;\n this.showTheme = options.showTheme === true;\n this.controls = Array.isArray(options.controls) ? options.controls : [];\n\n // Pre-rendered controls HTML\n this.controlsHtml = this._buildControlsHtml(this.controls);\n }\n\n async getTemplate() {\n return `\n <div class=\"d-flex justify-content-between align-items-center\">\n <div class=\"chart-title-section\">\n <h5 class=\"mb-2 chart-title\">{{{titleHtml}}}</h5>\n <small class=\"text-muted last-updated\" style=\"display: none;\">\n Last updated: <span class=\"timestamp\"></span>\n </small>\n </div>\n\n <div class=\"chart-controls\">\n <div class=\"btn-toolbar\" role=\"toolbar\">\n {{{controlsHtml}}}\n\n <div class=\"btn-group btn-group-sm\" role=\"group\">\n\n {{#showTheme}}\n <button type=\"button\" class=\"btn btn-outline-secondary theme-toggle\" data-action=\"toggle-theme\" title=\"Toggle Theme\">\n <i class=\"bi bi-palette\"></i>\n </button>\n {{/showTheme}}\n\n {{#showExport}}\n <div class=\"btn-group btn-group-sm\" role=\"group\">\n <button type=\"button\" class=\"btn btn-outline-secondary dropdown-toggle\" data-bs-toggle=\"dropdown\" title=\"Export Chart\">\n <i class=\"bi bi-download\"></i>\n </button>\n <ul class=\"dropdown-menu\">\n <li><a class=\"dropdown-item\" href=\"#\" data-action=\"export-chart\" data-format=\"png\">\n <i class=\"bi bi-image\"></i> PNG\n </a></li>\n <li><a class=\"dropdown-item\" href=\"#\" data-action=\"export-chart\" data-format=\"jpg\">\n <i class=\"bi bi-image\"></i> JPEG\n </a></li>\n <li><a class=\"dropdown-item\" href=\"#\" data-action=\"export-chart\" data-format=\"csv\">\n <i class=\"bi bi-file-earmark-spreadsheet\"></i> CSV\n </a></li>\n </ul>\n </div>\n {{/showExport}}\n\n {{#showRefresh}}\n <button type=\"button\" class=\"btn btn-outline-secondary refresh-btn\" data-action=\"refresh-chart\" title=\"Refresh Data\">\n <i class=\"bi bi-arrow-clockwise\"></i>\n </button>\n {{/showRefresh}}\n </div>\n </div>\n </div>\n </div>\n `;\n }\n\n // Build custom controls HTML for the toolbar from config\n _buildControlsHtml(controls) {\n if (!Array.isArray(controls) || controls.length === 0) return '';\n\n const parts = [];\n\n controls.forEach((item) => {\n if (!item || !item.type) return;\n\n switch (item.type) {\n case 'select': {\n const sizeCls = item.size === 'md' ? '' : ' form-select-sm';\n const cls = `form-select${sizeCls} ${item.className || ''}`.trim();\n const optionsHtml = (item.options || [])\n .map(opt => `<option value=\"${this._escapeAttr(opt.value)}\"${opt.selected ? ' selected' : ''}>${this._escapeHtml(opt.label)}</option>`)\n .join('');\n parts.push(`\n <div class=\"btn-group btn-group-sm me-2\" role=\"group\">\n <select class=\"${cls}\" data-change-action=\"${this._escapeAttr(item.action || item.name || 'select-changed')}\" style=\"width: auto;\">\n ${optionsHtml}\n </select>\n </div>\n `);\n break;\n }\n\n case 'button': {\n const { variant = 'outline-secondary', size = 'sm' } = item;\n const sizeCls = size === 'md' ? '' : ' btn-sm';\n const btnCls = `btn btn-${variant}${sizeCls} ${item.className || ''}`.trim();\n const titleAttr = item.title ? ` title=\"${this._escapeAttr(item.title)}\"` : '';\n const dataAttrs = this._buildDataAttrs(item.data);\n parts.push(`\n <div class=\"btn-group btn-group-sm me-2\" role=\"group\">\n <button type=\"button\" class=\"${btnCls}\" data-action=\"${this._escapeAttr(item.action || 'button-action')}\"${titleAttr}${dataAttrs}>\n ${item.labelHtml || ''}\n </button>\n </div>\n `);\n break;\n }\n\n case 'buttongroup': {\n const size = item.size || 'sm';\n const groupCls = `btn-group btn-group-${size} me-2 ${item.className || ''}`.trim();\n const buttons = (item.buttons || []).map(btn => {\n const variant = btn.variant || 'outline-secondary';\n const sizeCls = size === 'md' ? '' : ' btn-sm';\n const btnCls = `btn btn-${variant}${sizeCls} ${btn.className || ''}`.trim();\n const titleAttr = btn.title ? ` title=\"${this._escapeAttr(btn.title)}\"` : '';\n const dataAttrs = this._buildDataAttrs(btn.data);\n return `<button type=\"button\" class=\"${btnCls}\" data-action=\"${this._escapeAttr(btn.action || 'button-action')}\"${titleAttr}${dataAttrs}>${btn.labelHtml || ''}</button>`;\n }).join('');\n parts.push(`\n <div class=\"${groupCls}\" role=\"group\">\n ${buttons}\n </div>\n `);\n break;\n }\n\n case 'divider': {\n parts.push(`<div class=\"vr mx-2\"></div>`);\n break;\n }\n\n case 'html': {\n const html = item.html || '';\n parts.push(`<div class=\"me-2 d-inline-block\">${html}</div>`);\n break;\n }\n\n default:\n // Unknown type; ignore silently\n break;\n }\n });\n\n return parts.join('\\n');\n }\n\n _buildDataAttrs(data) {\n if (!data || typeof data !== 'object') return '';\n return Object.entries(data)\n .map(([key, val]) => ` data-${this._kebabCase(String(key))}=\"${this._escapeAttr(String(val))}\"`)\n .join('');\n }\n\n _kebabCase(str) {\n return str\n .replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g, '$1-$2')\n .toLowerCase()\n .replace(/[^a-z0-9\\-]/g, '-')\n .replace(/--+/g, '-')\n .replace(/^-|-$/g, '');\n }\n\n _escapeAttr(value) {\n return String(value)\n .replace(/\"/g, '&quot;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;');\n }\n\n _escapeHtml(value) {\n return String(value)\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;');\n }\n}\n","/**\n * SeriesChart - Combined Line and Bar chart component for MOJO framework\n * Supports switching between line and bar chart types with the same data\n */\n\nimport BaseChart from './BaseChart.js';\nimport Dialog from '@core/views/feedback/Dialog.js';\n\n\nexport default class SeriesChart extends BaseChart {\n constructor(options = {}) {\n super({\n ...options,\n chartType: options.chartType || 'line'\n });\n\n // Series-specific options\n this.showTypeSwitch = true;\n if (options.showTypeSwitch !== undefined) this.showTypeSwitch = options.showTypeSwitch;\n this.orientation = options.orientation || 'vertical'; // 'vertical' or 'horizontal'\n this.stacked = options.stacked || false;\n this.stepped = options.stepped || false; // For line charts\n this.tension = options.tension || 0.4; // Line curve tension\n this.fill = options.fill || false; // Fill area under line\n this.showRefreshButton = options.showRefreshButton !== false;\n\n if (!this.headerConfig) {\n this.headerConfig = {\n titleHtml: this.title || '',\n chartTitle: this.chartTitle || '',\n showExport: this.exportEnabled,\n showRefresh: this.refreshEnabled,\n showTheme: true,\n controls: []\n }\n }\n\n\n // Data series configuration\n this.series = options.series || [];\n this.xField = options.xField || 'x';\n this.yField = options.yField || 'y';\n\n\n\n // Color scheme for multiple datasets\n this.colors = options.colors || [\n 'rgba(54, 162, 235, 0.8)', // Blue\n 'rgba(255, 99, 132, 0.8)', // Red\n 'rgba(75, 192, 192, 0.8)', // Green\n 'rgba(255, 206, 86, 0.8)', // Yellow\n 'rgba(153, 102, 255, 0.8)', // Purple\n 'rgba(255, 159, 64, 0.8)', // Orange\n 'rgba(199, 199, 199, 0.8)', // Grey\n 'rgba(83, 102, 255, 0.8)' // Indigo\n ];\n\n\n\n // Process tooltip formatters\n this.tooltipFormatters = options.tooltip || {};\n }\n\n async getTemplate() {\n return await super.getTemplate();\n }\n\n async onInit() {\n // Provide header controls (type switcher) via BaseChart headerConfig\n if (this.showTypeSwitch) {\n this.headerConfig.controls.push({\n type: 'buttongroup',\n size: 'sm',\n buttons: [\n { action: 'set-chart-type', labelHtml: '<i class=\"bi bi-graph-up\"></i>', title: 'Line', variant: (this.chartType === 'line' ? 'primary' : 'outline-primary'), data: { type: 'line' } },\n { action: 'set-chart-type', labelHtml: '<i class=\"bi bi-bar-chart\"></i>', title: 'Bar', variant: (this.chartType === 'bar' ? 'primary' : 'outline-primary'), data: { type: 'bar' } }\n ]\n });\n }\n\n await super.onInit();\n\n }\n\n // Action Handlers\n async onActionSetChartType(event, element) {\n event.stopPropagation();\n const newType = element.getAttribute('data-type');\n if (newType && newType !== this.chartType) {\n await this.setChartType(newType);\n }\n }\n\n async rebuildChart() {\n if (this.chart && this.data) {\n this.chart.destroy();\n this.chart = null;\n\n const processedData = this.processChartData(this.data);\n await this.createChart(processedData);\n }\n }\n\n async setChartType(newType) {\n if (!['line', 'bar'].includes(newType)) {\n throw new Error(`Unsupported chart type: ${newType}`);\n }\n\n const oldType = this.chartType;\n this.chartType = newType;\n\n // Recreate chart with new type\n if (this.chart && this.data) {\n this.chart.destroy();\n this.chart = null;\n\n const processedData = this.processChartData(this.data);\n await this.createChart(processedData);\n }\n\n // Update type switcher button styles dynamically\n this._updateTypeSwitcherButtons();\n\n // Emit type change event\n const eventBus = this.getApp()?.events;\n if (eventBus) {\n eventBus.emit('chart:type-changed', {\n chart: this,\n oldType,\n newType: this.chartType\n });\n }\n }\n\n processChartData(data) {\n if (!data) return data;\n\n let processedData;\n\n // Handle different data input formats\n if (Array.isArray(data)) {\n // Array of objects: [{x: '2024-01', y: 100}, {x: '2024-02', y: 150}]\n processedData = this.processArrayData(data);\n } else if (data.labels && data.datasets) {\n // Chart.js format: {labels: [...], datasets: [...]}\n processedData = this.processChartJSData(data);\n } else if (data.series) {\n // Custom series format: {series: [{name: 'Sales', data: [...]}]}\n processedData = this.processSeriesData(data);\n } else {\n processedData = data;\n }\n\n // Apply formatters to the processed data\n return this.applyFormattersToData(processedData);\n }\n\n processArrayData(data) {\n const labels = [];\n const values = [];\n\n data.forEach(item => {\n const xValue = item[this.xField];\n const yValue = item[this.yField];\n\n labels.push(xValue);\n values.push(yValue);\n });\n\n return {\n labels,\n datasets: [{\n label: this.title || 'Data',\n data: values,\n backgroundColor: this.colors[0].replace('0.8', '0.6'),\n borderColor: this.colors[0],\n borderWidth: 2,\n tension: this.chartType === 'line' ? this.tension : 0,\n fill: this.chartType === 'line' ? this.fill : false,\n stepped: this.chartType === 'line' ? this.stepped : false\n }]\n };\n }\n\n processChartJSData(data) {\n // Already in Chart.js format, just apply our styling\n const processedData = { ...data };\n\n processedData.datasets = processedData.datasets.map((dataset, index) => ({\n ...dataset,\n backgroundColor: dataset.backgroundColor || this.colors[index % this.colors.length].replace('0.8', '0.6'),\n borderColor: dataset.borderColor || this.colors[index % this.colors.length],\n borderWidth: dataset.borderWidth || 2,\n tension: this.chartType === 'line' ? (dataset.tension ?? this.tension) : 0,\n fill: this.chartType === 'line' ? (dataset.fill ?? this.fill) : false,\n stepped: this.chartType === 'line' ? (dataset.stepped ?? this.stepped) : false\n }));\n\n return processedData;\n }\n\n processSeriesData(data) {\n const labels = data.labels || [];\n const datasets = [];\n\n data.series.forEach((series, index) => {\n datasets.push({\n label: series.name || series.label || `Series ${index + 1}`,\n data: series.data || [],\n backgroundColor: series.backgroundColor || this.colors[index % this.colors.length].replace('0.8', '0.6'),\n borderColor: series.borderColor || this.colors[index % this.colors.length],\n borderWidth: series.borderWidth || 2,\n tension: this.chartType === 'line' ? (series.tension ?? this.tension) : 0,\n fill: this.chartType === 'line' ? (series.fill ?? this.fill) : false,\n stepped: this.chartType === 'line' ? (series.stepped ?? this.stepped) : false\n });\n });\n\n return { labels, datasets };\n }\n\n applyFormattersToData(data) {\n if (!data) return data;\n\n const processedData = { ...data };\n\n // Apply x-axis formatter to labels if configured\n const xAxisCfg = this.normalizeAxis ? this.normalizeAxis(this.xAxis) : {};\n if (xAxisCfg.formatter && processedData.labels) {\n processedData.labels = processedData.labels.map(label =>\n this.dataFormatter.pipe(label, xAxisCfg.formatter)\n );\n }\n\n return processedData;\n }\n\n applySubclassChartOptions(options) {\n // Stacking for bar charts\n if (this.stacked && this.chartType === 'bar' && options.scales) {\n if (options.scales.x) options.scales.x.stacked = true;\n if (options.scales.y) options.scales.y.stacked = true;\n }\n\n // Horizontal bars\n if (this.chartType === 'bar' && this.orientation === 'horizontal') {\n options.indexAxis = 'y';\n }\n\n // Interaction mode tuned to chart type\n options.interaction = options.interaction || {};\n options.interaction.intersect = false;\n options.interaction.mode = this.chartType === 'line' ? 'index' : 'nearest';\n\n // Elements styling\n options.elements = options.elements || {};\n options.elements.line = {\n ...(options.elements.line || {}),\n tension: this.tension,\n borderWidth: 2\n };\n options.elements.point = {\n ...(options.elements.point || {}),\n radius: this.chartType === 'line' ? 4 : 0,\n hoverRadius: 6,\n hitRadius: 8\n };\n options.elements.bar = {\n ...(options.elements.bar || {}),\n borderWidth: 1,\n borderSkipped: false\n };\n }\n\n\n\n // Process simple axis configuration into detailed config\n processAxisConfig(axisConfig) {\n if (!axisConfig) return {};\n\n if (typeof axisConfig === 'string') {\n // Simple string format: just a formatter name\n return { formatter: axisConfig };\n }\n\n if (typeof axisConfig === 'object') {\n // Object format: full configuration\n return {\n formatter: axisConfig.formatter,\n label: axisConfig.label,\n type: axisConfig.type,\n beginAtZero: axisConfig.beginAtZero,\n ...axisConfig\n };\n }\n\n return {};\n }\n\n\n\n\n\n _updateTypeSwitcherButtons() {\n const buttons = this.element?.querySelectorAll('[data-action=\"set-chart-type\"]');\n if (!buttons || buttons.length === 0) return;\n\n buttons.forEach(button => {\n const buttonType = button.getAttribute('data-type');\n const isActive = buttonType === this.chartType;\n\n // Normalize classes for Bootstrap primary/outline-primary variants\n button.classList.toggle('btn-primary', isActive);\n button.classList.toggle('btn-outline-primary', !isActive);\n\n // Optional 'active' state for accessibility/visual feedback\n button.classList.toggle('active', isActive);\n });\n }\n\n // Public API extensions\n setOrientation(orientation) {\n if (!['vertical', 'horizontal'].includes(orientation)) {\n throw new Error(`Invalid orientation: ${orientation}`);\n }\n\n this.orientation = orientation;\n\n if (this.chart) {\n this.chart.destroy();\n this.chart = null;\n\n if (this.data) {\n const processedData = this.processChartData(this.data);\n this.createChart(processedData);\n }\n }\n }\n\n setStacked(stacked) {\n this.stacked = stacked;\n\n if (this.chart) {\n this.chart.options.scales.x.stacked = stacked;\n this.chart.options.scales.y.stacked = stacked;\n this.chart.update();\n }\n }\n\n addSeries(series) {\n if (!this.data || !this.data.datasets) return;\n\n const newDataset = {\n label: series.label || series.name || `Series ${this.data.datasets.length + 1}`,\n data: series.data || [],\n backgroundColor: series.backgroundColor || this.colors[this.data.datasets.length % this.colors.length].replace('0.8', '0.6'),\n borderColor: series.borderColor || this.colors[this.data.datasets.length % this.colors.length],\n borderWidth: series.borderWidth || 2,\n tension: this.chartType === 'line' ? (series.tension ?? this.tension) : 0,\n fill: this.chartType === 'line' ? (series.fill ?? this.fill) : false\n };\n\n this.data.datasets.push(newDataset);\n\n if (this.chart) {\n this.chart.data.datasets.push(newDataset);\n this.chart.update();\n }\n\n // Emit series added event\n const eventBus = this.getApp()?.events;\n if (eventBus) {\n eventBus.emit('chart:series-added', {\n chart: this,\n series: newDataset\n });\n }\n }\n\n removeSeries(index) {\n if (!this.data || !this.data.datasets || index < 0 || index >= this.data.datasets.length) {\n return;\n }\n\n const removedSeries = this.data.datasets.splice(index, 1)[0];\n\n if (this.chart) {\n this.chart.data.datasets.splice(index, 1);\n this.chart.update();\n }\n\n // Emit series removed event\n const eventBus = this.getApp()?.events;\n if (eventBus) {\n eventBus.emit('chart:series-removed', {\n chart: this,\n series: removedSeries,\n index\n });\n }\n }\n\n // Static dialog method\n static async showDialog(options = {}) {\n const {\n title = 'Chart Viewer',\n size = 'xl',\n ...chartOptions\n } = options;\n\n const chart = new SeriesChart({\n ...chartOptions,\n title\n });\n\n\n\n const dialog = new Dialog({\n title,\n body: chart,\n size,\n centered: true,\n backdrop: 'static',\n keyboard: true,\n buttons: [\n {\n text: 'Export PNG',\n action: 'export',\n class: 'btn btn-outline-primary'\n },\n {\n text: 'Close',\n action: 'close',\n class: 'btn btn-secondary',\n dismiss: true\n }\n ]\n });\n\n // Render and mount\n await dialog.render();\n document.body.appendChild(dialog.element);\n await dialog.mount();\n\n // Show the dialog\n dialog.show();\n\n return new Promise((resolve) => {\n dialog.on('hidden', () => {\n dialog.destroy();\n resolve(chart);\n });\n\n dialog.on('action:export', () => {\n chart.exportChart('png');\n });\n\n dialog.on('action:close', () => {\n dialog.hide();\n });\n });\n }\n}\n","/**\n * PieChart - Pie chart component with segment interactions for MOJO framework\n * Supports click interactions, custom colors, and DataFormatter integration\n */\n\nimport BaseChart from './BaseChart.js';\nimport Dialog from '@core/views/feedback/Dialog.js';\n\nexport default class PieChart extends BaseChart {\n constructor(options = {}) {\n super({\n ...options,\n chartType: 'pie'\n });\n\n // Pie-specific options\n this.cutout = options.cutout || 0; // 0 for pie, >0 for doughnut\n this.rotation = options.rotation || 0; // Starting angle\n this.circumference = options.circumference || 360; // Full circle\n \n // Segment configuration\n this.borderWidth = options.borderWidth || 2;\n this.borderColor = options.borderColor || '#ffffff';\n this.hoverBorderWidth = options.hoverBorderWidth || 3;\n \n // Label configuration\n this.showLabels = options.showLabels !== false;\n this.labelPosition = options.labelPosition || 'outside'; // 'inside', 'outside'\n this.labelFormatter = options.labelFormatter || null;\n this.valueFormatter = options.valueFormatter || null;\n \n // Data field configuration\n this.labelField = options.labelField || 'label';\n this.valueField = options.valueField || 'value';\n \n // Color scheme for segments\n this.colors = options.colors || [\n '#FF6384', // Red\n '#36A2EB', // Blue \n '#FFCE56', // Yellow\n '#4BC0C0', // Teal\n '#9966FF', // Purple\n '#FF9F40', // Orange\n '#C9CBCF', // Grey\n '#4BC0C0', // Green\n '#FF6384', // Pink\n '#36A2EB' // Light Blue\n ];\n\n // Animation options\n this.animateRotate = options.animateRotate !== false;\n this.animateScale = options.animateScale || false;\n \n // Interaction options\n this.clickable = options.clickable !== false;\n this.hoverable = options.hoverable !== false;\n \n // Selected segment tracking\n this.selectedSegment = null;\n this.highlightedSegments = new Set();\n\n // Value formatting\n this.valueFormatter = options.valueFormatter || null;\n\n\n }\n\n\n\n processChartData(data) {\n if (!data) return data;\n\n let processedData;\n\n // Handle different data input formats\n if (Array.isArray(data)) {\n // Array of objects: [{label: 'A', value: 100}, {label: 'B', value: 200}]\n processedData = this.processArrayData(data);\n } else if (data.labels && data.datasets) {\n // Chart.js format: {labels: [...], datasets: [...]}\n processedData = this.processChartJSData(data);\n } else if (typeof data === 'object' && !data.labels) {\n // Simple object: {A: 100, B: 200}\n processedData = this.processObjectData(data);\n } else {\n processedData = data;\n }\n\n // Apply formatters to the processed data\n return this.applyFormattersToData(processedData);\n }\n\n processArrayData(data) {\n const labels = [];\n const values = [];\n\n data.forEach(item => {\n const label = item[this.labelField];\n const value = item[this.valueField];\n \n if (label !== undefined && value !== undefined) {\n labels.push(label);\n values.push(value);\n }\n });\n\n return {\n labels,\n datasets: [{\n data: values,\n backgroundColor: this.generateColors(labels.length),\n borderColor: this.borderColor,\n borderWidth: this.borderWidth,\n hoverBorderWidth: this.hoverBorderWidth\n }]\n };\n }\n\n processChartJSData(data) {\n const processedData = { ...data };\n \n // Apply our styling to existing datasets\n processedData.datasets = processedData.datasets.map(dataset => ({\n ...dataset,\n backgroundColor: dataset.backgroundColor || this.generateColors(processedData.labels.length),\n borderColor: dataset.borderColor || this.borderColor,\n borderWidth: dataset.borderWidth || this.borderWidth,\n hoverBorderWidth: dataset.hoverBorderWidth || this.hoverBorderWidth\n }));\n\n return processedData;\n }\n\n processObjectData(data) {\n const labels = Object.keys(data);\n const values = Object.values(data);\n\n return {\n labels,\n datasets: [{\n data: values,\n backgroundColor: this.generateColors(labels.length),\n borderColor: this.borderColor,\n borderWidth: this.borderWidth,\n hoverBorderWidth: this.hoverBorderWidth\n }]\n };\n }\n\n applyFormattersToData(data) {\n if (!data) return data;\n\n const processedData = { ...data };\n\n // Apply label formatter to labels\n if (this.labelFormatter && processedData.labels) {\n processedData.labels = processedData.labels.map(label =>\n this.dataFormatter.pipe(label, this.labelFormatter)\n );\n }\n\n return processedData;\n }\n\n generateColors(count) {\n const colors = [];\n for (let i = 0; i < count; i++) {\n colors.push(this.colors[i % this.colors.length]);\n }\n return colors;\n }\n\n buildChartOptions() {\n const options = super.buildChartOptions();\n\n // Pie chart specific configuration\n options.cutout = this.cutout;\n options.rotation = this.rotation;\n options.circumference = this.circumference;\n\n // Animation configuration\n options.animation = {\n animateRotate: this.animateRotate,\n animateScale: this.animateScale,\n duration: this.animations ? 1000 : 0\n };\n\n // Plugin configuration\n options.plugins = {\n ...options.plugins,\n legend: {\n ...options.plugins.legend,\n position: options.plugins.legend.position || 'right',\n labels: {\n ...options.plugins.legend.labels,\n usePointStyle: true,\n padding: 20,\n generateLabels: (chart) => {\n const data = chart.data;\n if (data.labels.length && data.datasets.length) {\n return data.labels.map((label, i) => {\n const dataset = data.datasets[0];\n const value = dataset.data[i];\n const backgroundColor = dataset.backgroundColor[i];\n \n // Calculate percentage\n const total = dataset.data.reduce((sum, val) => sum + val, 0);\n const percentage = ((value / total) * 100).toFixed(1);\n \n return {\n text: `${label} (${percentage}%)`,\n fillStyle: backgroundColor,\n strokeStyle: backgroundColor,\n lineWidth: 0,\n hidden: false,\n index: i\n };\n });\n }\n return [];\n }\n }\n },\n tooltip: {\n ...options.plugins.tooltip,\n callbacks: {\n ...options.plugins.tooltip.callbacks,\n label: (context) => {\n const label = context.label || '';\n const value = context.raw;\n const dataset = context.dataset;\n \n // Calculate percentage\n const total = dataset.data.reduce((sum, val) => sum + val, 0);\n const percentage = ((value / total) * 100).toFixed(1);\n \n // Apply value formatter if configured\n let formattedValue = value;\n if (this.valueFormatter) {\n formattedValue = this.dataFormatter.pipe(value, this.valueFormatter);\n } else if (this.tooltipFormatters && this.tooltipFormatters.y) {\n formattedValue = this.dataFormatter.pipe(value, this.tooltipFormatters.y);\n }\n \n return `${label}: ${formattedValue} (${percentage}%)`;\n }\n }\n }\n };\n\n // Remove scales (not used in pie charts)\n delete options.scales;\n\n return options;\n }\n\n setupChartEventHandlers() {\n super.setupChartEventHandlers();\n\n if (!this.chart || !this.clickable) return;\n\n // Override click handler for pie chart specific behavior\n this.chart.options.onClick = (event, elements) => {\n if (elements.length > 0) {\n const element = elements[0];\n const index = element.index;\n const dataset = this.chart.data.datasets[0];\n const label = this.chart.data.labels[index];\n const value = dataset.data[index];\n\n // Calculate percentage\n const total = dataset.data.reduce((sum, val) => sum + val, 0);\n const percentage = ((value / total) * 100).toFixed(1);\n\n // Toggle segment selection\n this.toggleSegmentSelection(index);\n\n // Emit click event\n const eventBus = this.getApp()?.events;\n if (eventBus) {\n eventBus.emit('chart:segment-clicked', {\n chart: this,\n index,\n label,\n value,\n percentage: parseFloat(percentage),\n isSelected: this.selectedSegment === index\n });\n }\n }\n };\n\n // Hover handler for visual feedback\n if (this.hoverable) {\n this.chart.options.onHover = (event, elements) => {\n this.canvas.style.cursor = elements.length > 0 ? 'pointer' : 'default';\n \n if (elements.length > 0) {\n const element = elements[0];\n const index = element.index;\n \n // Emit hover event\n const eventBus = this.getApp()?.events;\n if (eventBus) {\n eventBus.emit('chart:segment-hover', {\n chart: this,\n index,\n label: this.chart.data.labels[index],\n value: this.chart.data.datasets[0].data[index]\n });\n }\n }\n };\n }\n }\n\n toggleSegmentSelection(index) {\n if (this.selectedSegment === index) {\n // Deselect current segment\n this.selectedSegment = null;\n this.resetSegmentStyle(index);\n } else {\n // Reset previous selection\n if (this.selectedSegment !== null) {\n this.resetSegmentStyle(this.selectedSegment);\n }\n \n // Select new segment\n this.selectedSegment = index;\n this.highlightSegment(index);\n }\n }\n\n highlightSegment(index) {\n if (!this.chart) return;\n\n const meta = this.chart.getDatasetMeta(0);\n const segment = meta.data[index];\n \n if (segment) {\n // Expand segment slightly\n segment.outerRadius += 10;\n this.chart.update('none');\n }\n }\n\n resetSegmentStyle(index) {\n if (!this.chart) return;\n\n const meta = this.chart.getDatasetMeta(0);\n const segment = meta.data[index];\n \n if (segment) {\n // Reset segment to normal size\n segment.outerRadius -= 10;\n this.chart.update('none');\n }\n }\n\n highlightSegments(indices) {\n if (!Array.isArray(indices)) {\n indices = [indices];\n }\n\n this.highlightedSegments.clear();\n indices.forEach(index => {\n this.highlightedSegments.add(index);\n this.highlightSegment(index);\n });\n }\n\n clearHighlights() {\n this.highlightedSegments.forEach(index => {\n this.resetSegmentStyle(index);\n });\n this.highlightedSegments.clear();\n \n if (this.selectedSegment !== null) {\n this.resetSegmentStyle(this.selectedSegment);\n this.selectedSegment = null;\n }\n }\n\n // Public API extensions\n selectSegment(index) {\n if (index >= 0 && index < this.chart?.data?.labels?.length) {\n this.toggleSegmentSelection(index);\n }\n }\n\n getSegmentData(index) {\n if (!this.chart || !this.chart.data) return null;\n\n const dataset = this.chart.data.datasets[0];\n const label = this.chart.data.labels[index];\n const value = dataset.data[index];\n const total = dataset.data.reduce((sum, val) => sum + val, 0);\n const percentage = ((value / total) * 100).toFixed(1);\n\n return {\n index,\n label,\n value,\n percentage: parseFloat(percentage),\n color: dataset.backgroundColor[index],\n isSelected: this.selectedSegment === index\n };\n }\n\n getAllSegments() {\n if (!this.chart || !this.chart.data) return [];\n\n return this.chart.data.labels.map((_, index) => this.getSegmentData(index));\n }\n\n updateSegmentColor(index, color) {\n if (!this.chart || !this.chart.data.datasets[0]) return;\n\n this.chart.data.datasets[0].backgroundColor[index] = color;\n this.chart.update('none');\n\n // Emit color change event\n const eventBus = this.getApp()?.events;\n if (eventBus) {\n eventBus.emit('chart:segment-color-changed', {\n chart: this,\n index,\n color,\n segment: this.getSegmentData(index)\n });\n }\n }\n\n addSegment(label, value, color = null) {\n if (!this.chart || !this.chart.data) return;\n\n const dataset = this.chart.data.datasets[0];\n const segmentColor = color || this.colors[this.chart.data.labels.length % this.colors.length];\n\n this.chart.data.labels.push(label);\n dataset.data.push(value);\n dataset.backgroundColor.push(segmentColor);\n\n this.chart.update();\n\n // Emit segment added event\n const eventBus = this.getApp()?.events;\n if (eventBus) {\n eventBus.emit('chart:segment-added', {\n chart: this,\n label,\n value,\n color: segmentColor,\n index: this.chart.data.labels.length - 1\n });\n }\n }\n\n removeSegment(index) {\n if (!this.chart || !this.chart.data || index < 0 || index >= this.chart.data.labels.length) {\n return;\n }\n\n const dataset = this.chart.data.datasets[0];\n const label = this.chart.data.labels[index];\n const value = dataset.data[index];\n\n this.chart.data.labels.splice(index, 1);\n dataset.data.splice(index, 1);\n dataset.backgroundColor.splice(index, 1);\n\n // Reset selection if removed segment was selected\n if (this.selectedSegment === index) {\n this.selectedSegment = null;\n } else if (this.selectedSegment > index) {\n this.selectedSegment--;\n }\n\n this.chart.update();\n\n // Emit segment removed event\n const eventBus = this.getApp()?.events;\n if (eventBus) {\n eventBus.emit('chart:segment-removed', {\n chart: this,\n label,\n value,\n index,\n removedSegment: { label, value, index }\n });\n }\n }\n\n // Override applyThemeToOptions for pie chart specific theming\n applyThemeToOptions(options) {\n super.applyThemeToOptions(options);\n\n const isDark = this.theme === 'dark';\n \n // Adjust border colors for theme\n if (isDark) {\n this.borderColor = '#404449';\n } else {\n this.borderColor = '#ffffff';\n }\n }\n\n // Static dialog method\n static async showDialog(options = {}) {\n const {\n title = 'Pie Chart',\n size = 'lg',\n ...chartOptions\n } = options;\n\n const chart = new PieChart({\n ...chartOptions,\n title\n });\n\n // Using static import at top: import Dialog from '@core/views/feedback/Dialog.js';\n\n const dialog = new Dialog({\n title,\n body: chart,\n size,\n centered: true,\n backdrop: 'static',\n keyboard: true,\n buttons: [\n { \n text: 'Export PNG', \n action: 'export', \n class: 'btn btn-outline-primary' \n },\n { \n text: 'Close', \n action: 'close', \n class: 'btn btn-secondary',\n dismiss: true\n }\n ]\n });\n\n // Render and mount\n await dialog.render();\n document.body.appendChild(dialog.element);\n await dialog.mount();\n\n // Show the dialog\n dialog.show();\n\n return new Promise((resolve) => {\n dialog.on('hidden', () => {\n dialog.destroy();\n resolve(chart);\n });\n\n dialog.on('action:export', () => {\n chart.exportChart('png');\n });\n\n dialog.on('action:close', () => {\n dialog.hide();\n });\n });\n }\n}","/**\n * MetricsChart - Specialized metrics chart extending SeriesChart\n * Provides header controls and a REST-based fetch to transform API data into Chart.js format\n */\n\nimport SeriesChart from './SeriesChart.js';\nimport Dialog from '@core/views/feedback/Dialog.js';\n\nexport default class MetricsChart extends SeriesChart {\n constructor(options = {}) {\n super({\n ...options,\n chartType: options.chartType || 'line',\n title: options.title || 'Metrics',\n colors: options.colors || [\n 'rgba(54, 162, 235, 0.8)', // Blue\n 'rgba(255, 99, 132, 0.8)', // Red\n 'rgba(75, 192, 192, 0.8)', // Green\n 'rgba(255, 206, 86, 0.8)', // Yellow\n 'rgba(153, 102, 255, 0.8)', // Purple\n 'rgba(255, 159, 64, 0.8)', // Orange\n 'rgba(199, 199, 199, 0.8)', // Grey\n 'rgba(83, 102, 255, 0.8)' // Indigo\n ],\n yAxis: options.yAxis || { label: 'Count', beginAtZero: true },\n tooltip: options.tooltip || { y: 'number' },\n width: options.width,\n height: options.height\n });\n\n // API configuration\n this.endpoint = options.endpoint || '/api/metrics/fetch';\n this.account = options.account || 'global';\n\n // Initial parameters\n this.granularity = options.granularity || 'hours';\n this.slugs = options.slugs || ['api_calls', 'api_errors'];\n this.dateStart = options.dateStart || null;\n this.dateEnd = options.dateEnd || null;\n this.defaultDateRange = options.defaultDateRange || '24h';\n\n // Control visibility options\n this.showGranularity = options.showGranularity !== false;\n this.showDateRange = options.showDateRange !== false;\n\n // Options for controls\n this.granularityOptions = options.granularityOptions || [\n { value: 'minutes', label: 'Minutes' },\n { value: 'hours', label: 'Hours' },\n { value: 'days', label: 'Days' },\n { value: 'weeks', label: 'Weeks' },\n { value: 'months', label: 'Months' }\n ];\n\n this.quickRanges = options.quickRanges || [\n { value: '1h', label: '1H' },\n { value: '24h', label: '24H' },\n { value: '7d', label: '7D' },\n { value: '30d', label: '30D' }\n ];\n\n this.availableMetrics = options.availableMetrics || [\n { value: 'api_calls', label: 'API Calls' },\n { value: 'api_errors', label: 'API Errors' },\n { value: 'incident_evt', label: 'System Events' },\n { value: 'incidents', label: 'Incidents' }\n ];\n\n // State\n this.isLoading = false;\n this.lastFetch = null;\n\n // Initialize date range if missing\n if (!this.dateStart || !this.dateEnd) {\n this.setQuickRange(this.defaultDateRange);\n }\n }\n\n async onInit() {\n // Build header controls for granularity and date range\n const controls = [];\n\n if (this.showGranularity) {\n controls.push({\n type: 'select',\n name: 'granularity',\n action: 'granularity-changed',\n size: 'sm',\n options: this.granularityOptions.map(opt => ({\n value: opt.value,\n label: opt.label,\n selected: opt.value === this.granularity\n }))\n });\n }\n\n if (this.showDateRange) {\n controls.push({\n type: 'button',\n action: 'show-date-range-dialog',\n labelHtml: `<i class=\"bi bi-calendar-range me-1\"></i>${this.formatDateRangeDisplay()}`,\n title: 'Select Date Range',\n variant: 'outline-secondary',\n size: 'sm'\n });\n }\n\n this.headerConfig = {\n titleHtml: this.title || 'Metrics',\n chartTitle: this.chartTitle || '',\n showExport: this.exportEnabled === true,\n showRefresh: this.refreshEnabled,\n showTheme: false,\n controls\n };\n\n await super.onInit();\n }\n\n // Action Handlers\n async onActionGranularityChanged(event, element) {\n const newGranularity = element.value;\n if (newGranularity && newGranularity !== this.granularity) {\n this.granularity = newGranularity;\n await this.fetchData();\n }\n }\n\n async onActionShowDateRangeDialog() {\n try {\n const result = await Dialog.showForm({\n title: 'Select Date Range',\n size: 'md',\n fields: [\n {\n name: 'dateRange',\n type: 'daterange',\n label: 'Date Range',\n startName: 'dt_start',\n endName: 'dt_end',\n startDate: this.formatDateTimeLocal(this.dateStart),\n endDate: this.formatDateTimeLocal(this.dateEnd),\n required: true\n }\n ],\n formConfig: {\n options: {\n submitButton: false,\n resetButton: false\n }\n }\n });\n\n if (result && result.startDate && result.endDate) {\n this.dateStart = new Date(result.startDate);\n this.dateEnd = new Date(result.endDate);\n\n // Update the header button label\n const btn = this.element?.querySelector('[data-action=\"show-date-range-dialog\"]');\n if (btn) {\n btn.innerHTML = `<i class=\"bi bi-calendar-range me-1\"></i>${this.formatDateRangeDisplay()}`;\n }\n\n await this.fetchData();\n }\n } catch (error) {\n console.error('Date range dialog error:', error);\n }\n }\n\n // Data Management\n buildApiParams() {\n const params = {\n granularity: this.granularity,\n account: this.account,\n with_labels: true\n };\n\n // Add slugs\n this.slugs.forEach(slug => {\n if (!params['slugs[]']) params['slugs[]'] = [];\n params['slugs[]'].push(slug);\n });\n\n // Date range\n if (this.dateStart) {\n params.dr_start = Math.floor(this.dateStart.getTime() / 1000);\n }\n if (this.dateEnd) {\n params.dr_end = Math.floor(this.dateEnd.getTime() / 1000);\n }\n\n // Cache buster\n params._ = Date.now();\n\n return params;\n }\n\n async fetchData() {\n if (!this.endpoint) return;\n\n this.isLoading = true;\n this.showLoading();\n\n try {\n const rest = this.getApp()?.rest;\n if (!rest) {\n throw new Error('No REST client available');\n }\n\n const params = this.buildApiParams();\n const response = await rest.GET(this.endpoint, params);\n\n // Handle Rest standardized response\n if (!response.success) {\n throw new Error(response.message || 'Network error');\n }\n if (!response.data?.status) {\n throw new Error(response.data?.error || 'Server error');\n }\n\n const metricsData = response.data.data;\n const chartData = this.processMetricsData(metricsData);\n await this.setData(chartData);\n this.lastFetch = new Date();\n\n // Emit success event\n this.emit('metrics:data-loaded', {\n chart: this,\n data: metricsData,\n params\n });\n\n } catch (error) {\n console.error('Failed to fetch metrics data:', error);\n this.showError(`Failed to load metrics: ${error.message}`);\n\n // Emit error event\n this.emit('metrics:error', { chart: this, error });\n\n } finally {\n this.isLoading = false;\n this.hideLoading();\n }\n }\n\n processMetricsData(data) {\n // Expecting: { labels: [...], data: { metric_slug: [values...] } }\n const { data: metricsData, labels } = data;\n const datasets = [];\n\n Object.keys(metricsData).forEach((metric, index) => {\n const values = metricsData[metric];\n\n const sanitizedValues = values.map(val => {\n if (val === null || val === undefined || val === '') return 0;\n return typeof val === 'number' ? val : (parseFloat(val) || 0);\n });\n\n datasets.push({\n label: this.formatMetricLabel(metric),\n data: sanitizedValues,\n backgroundColor: this.colors[index % this.colors.length].replace('0.8', '0.6'),\n borderColor: this.colors[index % this.colors.length],\n borderWidth: 2,\n tension: this.chartType === 'line' ? 0.4 : 0,\n fill: false,\n pointRadius: this.chartType === 'line' ? 3 : 0,\n pointHoverRadius: 5\n });\n });\n\n return { labels, datasets };\n }\n\n formatMetricLabel(metric) {\n return metric\n .split('_')\n .map(word => word.charAt(0).toUpperCase() + word.slice(1))\n .join(' ');\n }\n\n // Date utilities\n setQuickRange(range) {\n const now = new Date();\n let startDate;\n\n switch (range) {\n case '1h':\n startDate = new Date(now.getTime() - (60 * 60 * 1000));\n break;\n case '24h':\n startDate = new Date(now.getTime() - (24 * 60 * 60 * 1000));\n break;\n case '7d':\n startDate = new Date(now.getTime() - (7 * 24 * 60 * 60 * 1000));\n break;\n case '30d':\n startDate = new Date(now.getTime() - (30 * 24 * 60 * 60 * 1000));\n break;\n default:\n startDate = new Date(now.getTime() - (24 * 60 * 60 * 1000));\n }\n\n this.dateStart = startDate;\n this.dateEnd = now;\n }\n\n formatDateTimeLocal(date) {\n if (!date) return '';\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, '0');\n const day = String(date.getDate()).padStart(2, '0');\n const hours = String(date.getHours()).padStart(2, '0');\n const minutes = String(date.getMinutes()).padStart(2, '0');\n return `${year}-${month}-${day}T${hours}:${minutes}`;\n }\n\n // Public API\n setGranularity(granularity) {\n this.granularity = granularity;\n return this.fetchData();\n }\n\n setDateRange(startDate, endDate) {\n this.dateStart = new Date(startDate);\n this.dateEnd = new Date(endDate);\n return this.fetchData();\n }\n\n setMetrics(slugs) {\n this.slugs = [...slugs];\n return this.fetchData();\n }\n\n getStats() {\n const base = super.getStats();\n return {\n ...base,\n lastFetch: this.lastFetch,\n granularity: this.granularity,\n slugs: [...this.slugs],\n dateRange: {\n start: this.dateStart,\n end: this.dateEnd\n }\n };\n }\n}\n"],"names":["BaseChart","View","constructor","options","super","className","tagName","this","chart","chartType","endpoint","data","dataTransform","refreshInterval","autoRefresh","refreshTimer","websocketUrl","websocket","websocketReconnect","width","height","contentStyle","filter","Boolean","join","maintainAspectRatio","title","chartTitle","chartOptions","responsive","interaction","intersect","mode","plugins","legend","display","showLegend","position","legendPosition","text","tooltip","enabled","showTooltips","backgroundColor","titleColor","bodyColor","borderColor","borderWidth","xAxis","yAxis","tooltipFormatters","theme","colorScheme","animations","exportEnabled","exportFormats","isLoading","hasError","lastFetch","dataPoints","canvas","chartJsCdn","dataFormatter","_essentialListeners","refreshEnabled","buildDefaultHeaderConfig","titleHtml","showExport","showRefresh","showTheme","controls","getTemplate","onInit","initializeChartJS","headerConfig","headerView","ChartHeaderView","containerId","addChild","e","onAfterRender","element","querySelector","titleElement","contentElement","footerElement","loadingOverlay","errorOverlay","noDataOverlay","websocketStatus","refreshBtn","themeToggle","applyTheme","fetchData","updateChart","_updateChartDimensions","showNoData","startAutoRefresh","connectWebSocket","setupResizeObserver","showFooter","window","Chart","loadChartJS","error","console","showError","Promise","resolve","reject","script","document","createElement","src","onload","log","onerror","Error","head","appendChild","handleActionRefreshChart","handleActionRetryLoad","hideError","handleActionExportChart","event","format","getAttribute","exportChart","handleActionToggleTheme","toggleTheme","handleActionSetChartType","type","setChartType","showLoading","setRefreshButtonState","response","fetch","method","headers","Accept","ok","status","statusText","json","Date","updateLastUpdatedTime","eventBus","getApp","events","emit","source","message","hideLoading","WebSocketClient","url","autoReconnect","debug","on","showWebSocketStatus","async","connect","recreate","hideAllOverlays","processedData","processChartData","destroy","update","createChart","updateDataStats","xAxisCfg","normalizeAxis","formatter","labels","map","pipe","label","config","buildChartOptions","setupChartEventHandlers","yAxisCfg","scales","x","_detectAxisType","grid","ticks","callback","_createFormatterCallback","y","beginAtZero","applyThemeToOptions","callbacks","context","value","raw","formattedValue","dataset","applySubclassChartOptions","warn","axisConfig","rest","axisName","toLowerCase","includes","length","firstLabel","test","trim","isNaN","parse","datasets","firstDataset","firstValue","parseFloat","onClick","elements","datasetIndex","index","onHover","style","cursor","setAttribute","isDark","Object","keys","forEach","scaleId","scale","color","stopAutoRefresh","setInterval","updateRefreshStatus","clearInterval","exportCSV","toBase64Image","link","download","now","href","click","filename","csvData","generateCSV","blob","Blob","URL","createObjectURL","revokeObjectURL","csv","classList","remove","add","errorMessageEl","textContent","connected","innerHTML","loading","icon","disabled","lastUpdatedEl","timestampEl","toLocaleTimeString","active","statusEl","points","reduce","sum","dataPointsEl","ResizeObserver","resizeObserver","resize","observe","_resizeObserver","onBeforeDestroy","disconnect","el","fn","removeEventListener","setData","setEndpoint","setWebSocketUrl","setWidth","setHeight","setDimensions","refresh","setTheme","getStats","websocketConnected","isConnected","Array","isArray","controlsHtml","_buildControlsHtml","parts","item","cls","size","optionsHtml","opt","_escapeAttr","selected","_escapeHtml","push","action","name","variant","btnCls","titleAttr","dataAttrs","_buildDataAttrs","labelHtml","groupCls","buttons","btn","html","entries","key","val","_kebabCase","String","str","replace","SeriesChart","showTypeSwitch","orientation","stacked","stepped","tension","fill","showRefreshButton","series","xField","yField","colors","onActionSetChartType","stopPropagation","newType","rebuildChart","oldType","_updateTypeSwitcherButtons","processArrayData","processChartJSData","processSeriesData","applyFormattersToData","values","xValue","yValue","indexAxis","line","point","radius","hoverRadius","hitRadius","bar","borderSkipped","processAxisConfig","querySelectorAll","button","isActive","toggle","setOrientation","setStacked","addSeries","newDataset","removeSeries","removedSeries","splice","showDialog","dialog","Dialog","body","centered","backdrop","keyboard","class","dismiss","render","mount","show","hide","PieChart","cutout","rotation","circumference","hoverBorderWidth","showLabels","labelPosition","labelFormatter","valueFormatter","labelField","valueField","animateRotate","animateScale","clickable","hoverable","selectedSegment","highlightedSegments","Set","processObjectData","generateColors","count","i","animation","duration","usePointStyle","padding","generateLabels","toFixed","fillStyle","strokeStyle","lineWidth","hidden","percentage","toggleSegmentSelection","isSelected","resetSegmentStyle","highlightSegment","segment","getDatasetMeta","outerRadius","highlightSegments","indices","clear","clearHighlights","selectSegment","getSegmentData","getAllSegments","_","updateSegmentColor","addSegment","segmentColor","removeSegment","removedSegment","account","granularity","slugs","dateStart","dateEnd","defaultDateRange","showGranularity","showDateRange","granularityOptions","quickRanges","availableMetrics","setQuickRange","formatDateRangeDisplay","onActionGranularityChanged","newGranularity","onActionShowDateRangeDialog","result","showForm","fields","startName","endName","startDate","formatDateTimeLocal","endDate","required","formConfig","submitButton","resetButton","buildApiParams","params","with_labels","slug","dr_start","Math","floor","getTime","dr_end","GET","success","metricsData","chartData","processMetricsData","metric","sanitizedValues","formatMetricLabel","pointRadius","pointHoverRadius","split","word","charAt","toUpperCase","slice","range","date","getFullYear","getMonth","padStart","getDate","getHours","getMinutes","setGranularity","setDateRange","setMetrics","dateRange","start","end"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ "use strict";const t=require("./WebApp-DqDowtkl.js"),e=require("./Dialog-BsRx4eg3.js");class LightboxGallery extends t.View{constructor(t={}){super({...t,className:`lightbox-gallery ${t.className||""}`,tagName:"div"});const e=Array.isArray(t.images)?t.images:[t.images||t.src].filter(Boolean);this.images=e.map(t=>"string"==typeof t?{src:t,alt:""}:{src:t.src,alt:t.alt||""}),this.currentIndex=t.startIndex||0,this.showNavigation=!1!==t.showNavigation&&this.images.length>1,this.showCounter=!1!==t.showCounter&&this.images.length>1,this.allowKeyboard=!1!==t.allowKeyboard,this.closeOnBackdrop=!1!==t.closeOnBackdrop,this.fitToScreen=!1!==t.fitToScreen,this._keyboardHandler=this.handleKeyboard.bind(this),this.updateTemplateProperties()}updateTemplateProperties(){this.currentImage=this.images[this.currentIndex]||{src:"",alt:""},this.currentNumber=this.currentIndex+1,this.total=this.images.length,this.isFirst=0===this.currentIndex,this.isLast=this.currentIndex===this.images.length-1,this.imageStyle=this.fitToScreen?"width: 90vw; max-height: 100%; object-fit: contain; user-select: none; cursor: zoom-in;":"max-width: none; max-height: none; user-select: none; cursor: zoom-out;",this.containerStyle=this.fitToScreen?"":"overflow: auto;",this.modeIndicator=this.fitToScreen?"Fit to Screen":"Original Size"}async getTemplate(){return this.images[this.currentIndex],this.images.length,'\n <div class="lightbox-overlay position-fixed top-0 start-0 w-100 h-100 d-flex align-items-center justify-content-center"\n style="background: rgba(0,0,0,0.9); z-index: 9999;"\n data-action="backdrop-click">\n\n \x3c!-- Close button --\x3e\n <button type="button" class="btn-close btn-close-white position-absolute top-0 end-0 m-4"\n data-action="close"\n style="z-index: 10001;"\n title="Close"></button>\n\n \x3c!-- Counter --\x3e\n {{#showCounter}}\n <div class="lightbox-counter position-absolute top-0 start-50 translate-middle-x mt-4 text-white"\n style="z-index: 10001; font-size: 1.1rem;">\n {{currentNumber}} of {{total}}\n </div>\n {{/showCounter}}\n\n \x3c!-- Mode Indicator --\x3e\n <div class="lightbox-mode-indicator position-absolute bottom-0 start-50 translate-middle-x mb-4 text-white bg-dark bg-opacity-75 px-3 py-2 rounded"\n style="z-index: 10001; font-size: 0.9rem;">\n {{modeIndicator}} • Click image to toggle\n </div>\n\n \x3c!-- Navigation --\x3e\n {{#showNavigation}}\n <button type="button" class="btn btn-light btn-lg position-absolute start-0 top-50 translate-middle-y ms-4"\n data-action="prev"\n style="z-index: 10001;"\n title="Previous"\n {{#isFirst}}disabled{{/isFirst}}>\n <i class="bi bi-chevron-left"></i>\n </button>\n\n <button type="button" class="btn btn-light btn-lg position-absolute end-0 top-50 translate-middle-y me-4"\n data-action="next"\n style="z-index: 10001;"\n title="Next"\n {{#isLast}}disabled{{/isLast}}>\n <i class="bi bi-chevron-right"></i>\n </button>\n {{/showNavigation}}\n\n \x3c!-- Image container --\x3e\n <div class="lightbox-image-container w-100 h-100 d-flex align-items-center justify-content-center p-5"\n style="{{containerStyle}}">\n {{#currentImage}}\n <img src="{{src}}"\n alt="{{alt}}"\n class="lightbox-image img-fluid"\n style="{{imageStyle}}"\n data-action="image-click">\n {{/currentImage}}\n </div>\n\n \x3c!-- Loading spinner --\x3e\n <div class="lightbox-loading position-absolute top-50 start-50 translate-middle text-white"\n style="display: none;">\n <div class="spinner-border" role="status">\n <span class="visually-hidden">Loading...</span>\n </div>\n </div>\n </div>\n '}async onAfterRender(){document.body.appendChild(this.element),document.body.style.overflow="hidden",this.allowKeyboard&&document.addEventListener("keydown",this._keyboardHandler),this.preloadAdjacentImages()}async handleActionClose(){this.close()}async handleActionBackdropClick(t){this.closeOnBackdrop&&t.target===t.currentTarget&&this.close()}async handleActionPrev(){this.showPrevious()}async handleActionNext(){this.showNext()}async handleActionImageClick(){this.toggleImageMode()}showPrevious(){this.currentIndex>0&&(this.currentIndex--,this.updateImage(),this.preloadAdjacentImages())}showNext(){this.currentIndex<this.images.length-1&&(this.currentIndex++,this.updateImage(),this.preloadAdjacentImages())}goToImage(t){t>=0&&t<this.images.length&&t!==this.currentIndex&&(this.currentIndex=t,this.updateImage(),this.preloadAdjacentImages())}async updateImage(){const t=this.images[this.currentIndex],e=this.element.querySelector(".lightbox-image"),s=this.element.querySelector(".lightbox-counter"),i=this.element.querySelector('[data-action="prev"]'),n=this.element.querySelector('[data-action="next"]');e&&(this.showLoading(),e.src=t.src,e.alt=t.alt,await this.waitForImageLoad(e),this.hideLoading()),s&&(s.textContent=`${this.currentIndex+1} of ${this.images.length}`),i&&(i.disabled=0===this.currentIndex),n&&(n.disabled=this.currentIndex===this.images.length-1),this.updateTemplateProperties(),this.updateImageDisplay();const a=this.getApp()?.events;a&&a.emit("lightbox:image-changed",{gallery:this,index:this.currentIndex,image:t})}showLoading(){const t=this.element.querySelector(".lightbox-loading");t&&(t.style.display="block")}hideLoading(){const t=this.element.querySelector(".lightbox-loading");t&&(t.style.display="none")}waitForImageLoad(t){return new Promise(e=>{t.complete?e():(t.onload=e,t.onerror=e)})}preloadAdjacentImages(){const t=[];this.currentIndex>0&&t.push(this.currentIndex-1),this.currentIndex<this.images.length-1&&t.push(this.currentIndex+1),t.forEach(t=>{const e=this.images[t];(new Image).src=e.src})}handleKeyboard(t){switch(t.key){case"Escape":t.preventDefault(),this.close();break;case"ArrowLeft":t.preventDefault(),this.showPrevious();break;case"ArrowRight":t.preventDefault(),this.showNext();break;case"Home":t.preventDefault(),this.goToImage(0);break;case"End":t.preventDefault(),this.goToImage(this.images.length-1)}}toggleImageMode(){this.fitToScreen=!this.fitToScreen,this.updateTemplateProperties(),this.updateImageDisplay();const t=this.getApp()?.events;t&&t.emit("lightbox:mode-changed",{gallery:this,fitToScreen:this.fitToScreen})}updateImageDisplay(){const t=this.element.querySelector(".lightbox-image"),e=this.element.querySelector(".lightbox-image-container"),s=this.element.querySelector(".lightbox-mode-indicator");t&&(this.fitToScreen?(t.style.maxWidth="100%",t.style.maxHeight="100%",t.style.objectFit="contain",t.style.cursor="zoom-in"):(t.style.maxWidth="none",t.style.maxHeight="none",t.style.objectFit="none",t.style.cursor="zoom-out"),t.style.userSelect="none"),e&&(e.style.overflow=this.fitToScreen?"":"auto"),s&&(s.textContent=`${this.modeIndicator} • Click image to toggle`)}close(){const t=this.getApp()?.events;t&&t.emit("lightbox:closed",{gallery:this}),this.destroy()}async onBeforeDestroy(){document.body.style.overflow="",this.allowKeyboard&&document.removeEventListener("keydown",this._keyboardHandler),this.element.parentNode===document.body&&document.body.removeChild(this.element)}static show(t,e={}){const s=new LightboxGallery({images:t,...e});return s.render().then(()=>{s.mount()}),s}}window.LightboxGallery=LightboxGallery;class PDFViewer extends t.View{constructor(t={}){super({...t,className:`pdf-viewer ${t.className||""}`,tagName:"div"}),this.pdfUrl=t.pdfUrl||t.src||"",this.title=t.title||"PDF Document",this.pdfDoc=null,this.currentPage=1,this.totalPages=0,this.pageRendering=!1,this.pageNumPending=null,this.scale=1,this.minScale=.25,this.maxScale=5,this.scaleStep=.25,this.fitMode="page",this.canvas=null,this.ctx=null,this.showControls=!1!==t.showControls,this.allowZoom=!1!==t.allowZoom,this.allowNavigation=!1!==t.allowNavigation,this.showPageNumbers=!1!==t.showPageNumbers,this.isLoaded=!1,this.isLoading=!1,this.pdfjsWorkerPath=t.pdfjsWorkerPath||"https://cdnjs.cloudflare.com/ajax/libs/pdf.js/4.0.379/pdf.worker.min.js",this.pdfjsCMapUrl=t.pdfjsCMapUrl||"https://cdnjs.cloudflare.com/ajax/libs/pdf.js/4.0.379/cmaps/",this.canvasContainer=null,this.controlsElement=null,this.statusElement=null,this.pageInput=null}async getTemplate(){return'\n <div class="pdf-viewer-container">\n {{#showControls}}\n <div class="pdf-viewer-toolbar" data-container="toolbar">\n <div class="btn-toolbar" role="toolbar">\n \x3c!-- Navigation Controls --\x3e\n {{#allowNavigation}}\n <div class="btn-group me-2" role="group" aria-label="Navigation">\n <button type="button" class="btn btn-outline-secondary btn-sm" data-action="first-page" title="First Page">\n <i class="bi bi-chevron-double-left"></i>\n </button>\n <button type="button" class="btn btn-outline-secondary btn-sm" data-action="prev-page" title="Previous Page">\n <i class="bi bi-chevron-left"></i>\n </button>\n \n {{#showPageNumbers}}\n <div class="input-group input-group-sm" style="width: 120px;">\n <input type="number" class="form-control text-center page-input" min="1" value="1" data-change-action="page-input">\n <span class="input-group-text page-total">/ 0</span>\n </div>\n {{/showPageNumbers}}\n \n <button type="button" class="btn btn-outline-secondary btn-sm" data-action="next-page" title="Next Page">\n <i class="bi bi-chevron-right"></i>\n </button>\n <button type="button" class="btn btn-outline-secondary btn-sm" data-action="last-page" title="Last Page">\n <i class="bi bi-chevron-double-right"></i>\n </button>\n </div>\n {{/allowNavigation}}\n\n \x3c!-- Zoom Controls --\x3e\n {{#allowZoom}}\n <div class="btn-group me-2" role="group" aria-label="Zoom">\n <button type="button" class="btn btn-outline-secondary btn-sm" data-action="zoom-out" title="Zoom Out">\n <i class="bi bi-zoom-out"></i>\n </button>\n <button type="button" class="btn btn-outline-secondary btn-sm" data-action="zoom-in" title="Zoom In">\n <i class="bi bi-zoom-in"></i>\n </button>\n \n <div class="btn-group" role="group">\n <button type="button" class="btn btn-outline-secondary btn-sm dropdown-toggle" data-bs-toggle="dropdown" title="Fit">\n <i class="bi bi-arrows-fullscreen"></i>\n </button>\n <ul class="dropdown-menu">\n <li><a class="dropdown-item" href="#" data-action="fit-page">Fit Page</a></li>\n <li><a class="dropdown-item" href="#" data-action="fit-width">Fit Width</a></li>\n <li><a class="dropdown-item" href="#" data-action="actual-size">Actual Size</a></li>\n </ul>\n </div>\n </div>\n {{/allowZoom}}\n\n \x3c!-- Utility Controls --\x3e\n <div class="btn-group me-2" role="group" aria-label="Utilities">\n <button type="button" class="btn btn-outline-secondary btn-sm" data-action="download" title="Download">\n <i class="bi bi-download"></i>\n </button>\n <button type="button" class="btn btn-outline-secondary btn-sm" data-action="print" title="Print">\n <i class="bi bi-printer"></i>\n </button>\n </div>\n </div>\n </div>\n {{/showControls}}\n\n \x3c!-- PDF Content Area --\x3e\n <div class="pdf-viewer-content" data-container="content">\n <div class="pdf-canvas-container" data-container="canvasContainer">\n <canvas class="pdf-canvas" data-container="canvas"></canvas>\n </div>\n\n <div class="pdf-viewer-overlay">\n <div class="pdf-viewer-loading">\n <div class="spinner-border text-primary" role="status">\n <span class="visually-hidden">Loading PDF...</span>\n </div>\n <div class="mt-2">Loading PDF...</div>\n </div>\n </div>\n\n <div class="pdf-viewer-error" style="display: none;">\n <div class="alert alert-danger" role="alert">\n <i class="bi bi-exclamation-triangle"></i>\n <strong>Error:</strong> <span class="error-message">Failed to load PDF</span>\n </div>\n </div>\n </div>\n\n \x3c!-- Status Bar --\x3e\n <div class="pdf-viewer-status" data-container="status">\n <small class="text-muted">\n <span class="current-page">0</span> of <span class="total-pages">0</span> pages |\n <span class="zoom-level">100%</span> |\n <span class="document-title">{{title}}</span>\n </small>\n </div>\n </div>\n '}get(){return{pdfUrl:this.pdfUrl,title:this.title,showControls:this.showControls,allowZoom:this.allowZoom,allowNavigation:this.allowNavigation,showPageNumbers:this.showPageNumbers}}async onAfterRender(){this.canvas=this.element.querySelector(".pdf-canvas"),this.canvasContainer=this.element.querySelector(".pdf-canvas-container"),this.controlsElement=this.element.querySelector(".pdf-viewer-toolbar"),this.statusElement=this.element.querySelector(".pdf-viewer-status"),this.pageInput=this.element.querySelector(".page-input"),this.overlayElement=this.element.querySelector(".pdf-viewer-overlay"),this.errorElement=this.element.querySelector(".pdf-viewer-error"),this.canvas&&(this.ctx=this.canvas.getContext("2d")),this.setupEssentialEventListeners(),await this.initializePDFJS(),this.pdfUrl&&await this.loadPDF()}setupEssentialEventListeners(){const t=t=>this.handleKeyDown(t);document.addEventListener("keydown",t);let e=null;this.canvasContainer&&(e=new ResizeObserver(()=>{"auto"!==this.fitMode&&this.applyFitMode()}),e.observe(this.canvasContainer)),this._essentialListeners=[{el:document,type:"keydown",fn:t}],this._resizeObserver=e}async initializePDFJS(){try{return void 0===window.pdfjsLib&&await this.loadPDFJSLibrary(),window.pdfjsLib.GlobalWorkerOptions.workerSrc=this.pdfjsWorkerPath,!0}catch(t){return console.error("Failed to initialize PDF.js:",t),this.showError("Failed to initialize PDF viewer"),!1}}async loadPDFJSLibrary(){return new Promise((t,e)=>{const s=document.createElement("script");s.src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/4.0.379/pdf.min.js",s.onload=t,s.onerror=e,document.head.appendChild(s)})}async handleActionFirstPage(){await this.goToPage(1)}async handleActionPrevPage(){await this.goToPage(this.currentPage-1)}async handleActionNextPage(){await this.goToPage(this.currentPage+1)}async handleActionLastPage(){await this.goToPage(this.totalPages)}async onChangePageInput(t,e){const s=parseInt(e.value,10);s>=1&&s<=this.totalPages?await this.goToPage(s):e.value=this.currentPage}async handleActionZoomIn(){this.setScale(this.scale+this.scaleStep)}async handleActionZoomOut(){this.setScale(this.scale-this.scaleStep)}async handleActionFitPage(){this.setFitMode("page")}async handleActionFitWidth(){this.setFitMode("width")}async handleActionActualSize(){this.setScale(1),this.fitMode="auto"}async handleActionDownload(){this.downloadPDF()}async handleActionPrint(){window.print()}async loadPDF(){if(!this.pdfUrl||!window.pdfjsLib)return this.showError("PDF URL or PDF.js library not available"),!1;this.isLoading=!0,this.showLoading();try{const t=window.pdfjsLib.getDocument({url:this.pdfUrl,cMapUrl:this.pdfjsCMapUrl,cMapPacked:!0});this.pdfDoc=await t.promise,this.totalPages=this.pdfDoc.numPages,this.currentPage=1,this.updatePageControls(),this.updateStatus(),await this.renderPage(1),this.isLoaded=!0,this.isLoading=!1,this.element.classList.add("loaded"),this.hideLoading(),this.applyFitMode();const e=this.getApp()?.events;return e&&e.emit("pdfviewer:loaded",{viewer:this,pdfUrl:this.pdfUrl,totalPages:this.totalPages}),!0}catch(t){console.error("Error loading PDF:",t),this.isLoading=!1,this.showError("Failed to load PDF document");const e=this.getApp()?.events;return e&&e.emit("pdfviewer:error",{viewer:this,pdfUrl:this.pdfUrl,error:t.message}),!1}}async renderPage(t){if(this.pageRendering)this.pageNumPending=t;else if(this.pdfDoc&&this.canvas&&this.ctx){this.pageRendering=!0,this.currentPage=t;try{const e=await this.pdfDoc.getPage(t),s=e.getViewport({scale:this.scale});this.canvas.height=s.height,this.canvas.width=s.width,this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height);const i={canvasContext:this.ctx,viewport:s},n=e.render(i);if(await n.promise,this.pageRendering=!1,null!==this.pageNumPending){const t=this.pageNumPending;this.pageNumPending=null,await this.renderPage(t)}this.updatePageControls(),this.updateStatus();const a=this.getApp()?.events;a&&a.emit("pdfviewer:page-changed",{viewer:this,currentPage:this.currentPage,totalPages:this.totalPages})}catch(e){console.error("Error rendering page:",e),this.pageRendering=!1,this.showError("Failed to render PDF page")}}}async goToPage(t){!this.pdfDoc||t<1||t>this.totalPages||await this.renderPage(t)}setScale(t){const e=this.scale;this.scale=Math.max(this.minScale,Math.min(this.maxScale,t)),this.fitMode="auto",this.isLoaded&&this.renderPage(this.currentPage);const s=this.getApp()?.events;s&&e!==this.scale&&s.emit("pdfviewer:scale-changed",{viewer:this,oldScale:e,newScale:this.scale})}setFitMode(t){const e=this.fitMode;this.fitMode=t,this.applyFitMode();const s=this.getApp()?.events;s&&s.emit("pdfviewer:fit-mode-changed",{viewer:this,oldMode:e,newMode:t})}applyFitMode(){this.isLoaded&&this.pdfDoc&&this.canvasContainer&&this.pdfDoc.getPage(this.currentPage).then(t=>{const e=this.canvasContainer.getBoundingClientRect(),s=t.getViewport({scale:1});let i;if("page"===this.fitMode){const t=(e.width-40)/s.width,n=(e.height-40)/s.height;i=Math.min(t,n)}else{if("width"!==this.fitMode)return;i=(e.width-40)/s.width}this.scale=Math.max(this.minScale,Math.min(this.maxScale,i)),this.renderPage(this.currentPage)})}handleKeyDown(t){if("INPUT"!==t.target.tagName||t.target===this.pageInput)switch(t.key){case"ArrowLeft":case"PageUp":t.preventDefault(),this.goToPage(this.currentPage-1);break;case"ArrowRight":case"PageDown":t.preventDefault(),this.goToPage(this.currentPage+1);break;case"Home":t.preventDefault(),this.goToPage(1);break;case"End":t.preventDefault(),this.goToPage(this.totalPages);break;case"+":case"=":(t.ctrlKey||t.metaKey)&&(t.preventDefault(),this.setScale(this.scale+this.scaleStep));break;case"-":(t.ctrlKey||t.metaKey)&&(t.preventDefault(),this.setScale(this.scale-this.scaleStep));break;case"0":(t.ctrlKey||t.metaKey)&&(t.preventDefault(),this.setFitMode("page"))}}updatePageControls(){this.pageInput&&(this.pageInput.value=this.currentPage);const t=this.element.querySelector(".page-total");t&&(t.textContent=`/ ${this.totalPages}`);const e=this.element.querySelector('[data-action="first-page"]'),s=this.element.querySelector('[data-action="prev-page"]'),i=this.element.querySelector('[data-action="next-page"]'),n=this.element.querySelector('[data-action="last-page"]');e&&(e.disabled=this.currentPage<=1),s&&(s.disabled=this.currentPage<=1),i&&(i.disabled=this.currentPage>=this.totalPages),n&&(n.disabled=this.currentPage>=this.totalPages);const a=this.element.querySelector('[data-action="zoom-in"]'),o=this.element.querySelector('[data-action="zoom-out"]');a&&(a.disabled=this.scale>=this.maxScale),o&&(o.disabled=this.scale<=this.minScale)}updateStatus(){if(!this.statusElement)return;const t=this.statusElement.querySelector(".current-page"),e=this.statusElement.querySelector(".total-pages"),s=this.statusElement.querySelector(".zoom-level");t&&(t.textContent=this.currentPage),e&&(e.textContent=this.totalPages),s&&(s.textContent=`${Math.round(100*this.scale)}%`)}showLoading(){this.overlayElement&&(this.overlayElement.style.display="flex")}hideLoading(){this.overlayElement&&(this.overlayElement.style.display="none")}showError(t){if(this.hideLoading(),this.errorElement){const e=this.errorElement.querySelector(".error-message");e&&(e.textContent=t),this.errorElement.style.display="block"}console.error("PDF Viewer Error:",t)}downloadPDF(){if(!this.pdfUrl)return;const t=document.createElement("a");t.href=this.pdfUrl,t.download=this.title+".pdf",t.target="_blank",t.click()}setPDF(t,e=""){const s=this.pdfUrl;this.pdfUrl=t,this.title=e||"PDF Document",this.isLoaded=!1,this.element.classList.remove("loaded"),this.pdfDoc&&(this.pdfDoc.destroy(),this.pdfDoc=null),this.currentPage=1,this.totalPages=0,this.scale=1,t&&this.loadPDF();const i=this.getApp()?.events;i&&i.emit("pdfviewer:pdf-changed",{viewer:this,oldPdfUrl:s,newPdfUrl:t})}getCurrentPage(){return this.currentPage}getTotalPages(){return this.totalPages}getCurrentScale(){return this.scale}async onBeforeDestroy(){this.pdfDoc&&(this.pdfDoc.destroy(),this.pdfDoc=null),this.pageRendering=!1,this.pageNumPending=null,this._essentialListeners&&(this._essentialListeners.forEach(({el:t,type:e,fn:s})=>{t&&t.removeEventListener(e,s)}),this._essentialListeners=null),this._resizeObserver&&(this._resizeObserver.disconnect(),this._resizeObserver=null);const t=this.getApp()?.events;t&&t.emit("pdfviewer:destroyed",{viewer:this})}static async showDialog(t,s={}){const{title:i="PDF Viewer",size:n="fullscreen",showControls:a=!0,allowZoom:o=!0,allowNavigation:r=!0,showPageNumbers:l=!0,...c}=s,d=new PDFViewer({pdfUrl:t,title:i,showControls:a,allowZoom:o,allowNavigation:r,showPageNumbers:l}),h=new e.default({title:i,body:d,size:n,centered:!0,backdrop:"static",keyboard:!0,buttons:[{text:"Download",action:"download",class:"btn btn-outline-primary"},{text:"Close",action:"close",class:"btn btn-secondary",dismiss:!0}],...c});return await h.render(),document.body.appendChild(h.element),await h.mount(),h.show(),new Promise(t=>{h.on("hidden",()=>{h.destroy(),t(d)}),h.on("action:download",()=>{d.downloadPDF()}),h.on("action:close",()=>{h.hide()})})}}exports.LightboxGallery=LightboxGallery,exports.PDFViewer=PDFViewer;
2
+ //# sourceMappingURL=PDFViewer-BNQlnS83.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PDFViewer-BNQlnS83.js","sources":["../../src/extensions/lightbox/LightboxGallery.js","../../src/extensions/lightbox/PDFViewer.js"],"sourcesContent":["/**\n * LightboxGallery - Simple fullscreen image gallery\n * Clean, minimal lightbox for viewing single images or galleries\n */\n\nimport View from '@core/View.js';\n\nexport default class LightboxGallery extends View {\n constructor(options = {}) {\n super({\n ...options,\n className: `lightbox-gallery ${options.className || ''}`,\n tagName: 'div'\n });\n\n // Handle single image or array of images and normalize to objects\n const rawImages = Array.isArray(options.images) ? options.images : [options.images || options.src].filter(Boolean);\n this.images = rawImages.map(img => {\n if (typeof img === 'string') {\n return { src: img, alt: '' };\n }\n return { src: img.src, alt: img.alt || '' };\n });\n this.currentIndex = options.startIndex || 0;\n this.showNavigation = options.showNavigation !== false && this.images.length > 1;\n this.showCounter = options.showCounter !== false && this.images.length > 1;\n this.allowKeyboard = options.allowKeyboard !== false;\n this.closeOnBackdrop = options.closeOnBackdrop !== false;\n this.fitToScreen = options.fitToScreen !== false; // Start in fit-to-screen mode\n\n // Bind keyboard handler for cleanup\n this._keyboardHandler = this.handleKeyboard.bind(this);\n\n // Set template properties directly on view instance\n this.updateTemplateProperties();\n }\n\n updateTemplateProperties() {\n this.currentImage = this.images[this.currentIndex] || { src: '', alt: '' };\n this.currentNumber = this.currentIndex + 1;\n this.total = this.images.length;\n this.isFirst = this.currentIndex === 0;\n this.isLast = this.currentIndex === this.images.length - 1;\n this.imageStyle = this.fitToScreen\n ? 'width: 90vw; max-height: 100%; object-fit: contain; user-select: none; cursor: zoom-in;'\n : 'max-width: none; max-height: none; user-select: none; cursor: zoom-out;';\n this.containerStyle = this.fitToScreen\n ? ''\n : 'overflow: auto;';\n this.modeIndicator = this.fitToScreen ? 'Fit to Screen' : 'Original Size';\n }\n\n async getTemplate() {\n const currentImage = this.images[this.currentIndex];\n const hasMultiple = this.images.length > 1;\n\n return `\n <div class=\"lightbox-overlay position-fixed top-0 start-0 w-100 h-100 d-flex align-items-center justify-content-center\"\n style=\"background: rgba(0,0,0,0.9); z-index: 9999;\"\n data-action=\"backdrop-click\">\n\n <!-- Close button -->\n <button type=\"button\" class=\"btn-close btn-close-white position-absolute top-0 end-0 m-4\"\n data-action=\"close\"\n style=\"z-index: 10001;\"\n title=\"Close\"></button>\n\n <!-- Counter -->\n {{#showCounter}}\n <div class=\"lightbox-counter position-absolute top-0 start-50 translate-middle-x mt-4 text-white\"\n style=\"z-index: 10001; font-size: 1.1rem;\">\n {{currentNumber}} of {{total}}\n </div>\n {{/showCounter}}\n\n <!-- Mode Indicator -->\n <div class=\"lightbox-mode-indicator position-absolute bottom-0 start-50 translate-middle-x mb-4 text-white bg-dark bg-opacity-75 px-3 py-2 rounded\"\n style=\"z-index: 10001; font-size: 0.9rem;\">\n {{modeIndicator}} • Click image to toggle\n </div>\n\n <!-- Navigation -->\n {{#showNavigation}}\n <button type=\"button\" class=\"btn btn-light btn-lg position-absolute start-0 top-50 translate-middle-y ms-4\"\n data-action=\"prev\"\n style=\"z-index: 10001;\"\n title=\"Previous\"\n {{#isFirst}}disabled{{/isFirst}}>\n <i class=\"bi bi-chevron-left\"></i>\n </button>\n\n <button type=\"button\" class=\"btn btn-light btn-lg position-absolute end-0 top-50 translate-middle-y me-4\"\n data-action=\"next\"\n style=\"z-index: 10001;\"\n title=\"Next\"\n {{#isLast}}disabled{{/isLast}}>\n <i class=\"bi bi-chevron-right\"></i>\n </button>\n {{/showNavigation}}\n\n <!-- Image container -->\n <div class=\"lightbox-image-container w-100 h-100 d-flex align-items-center justify-content-center p-5\"\n style=\"{{containerStyle}}\">\n {{#currentImage}}\n <img src=\"{{src}}\"\n alt=\"{{alt}}\"\n class=\"lightbox-image img-fluid\"\n style=\"{{imageStyle}}\"\n data-action=\"image-click\">\n {{/currentImage}}\n </div>\n\n <!-- Loading spinner -->\n <div class=\"lightbox-loading position-absolute top-50 start-50 translate-middle text-white\"\n style=\"display: none;\">\n <div class=\"spinner-border\" role=\"status\">\n <span class=\"visually-hidden\">Loading...</span>\n </div>\n </div>\n </div>\n `;\n }\n\n\n\n async onAfterRender() {\n // Add to body for fullscreen\n document.body.appendChild(this.element);\n document.body.style.overflow = 'hidden';\n\n // Set up keyboard navigation\n if (this.allowKeyboard) {\n document.addEventListener('keydown', this._keyboardHandler);\n }\n\n // Preload next/previous images\n this.preloadAdjacentImages();\n }\n\n // Action handlers\n async handleActionClose() {\n this.close();\n }\n\n async handleActionBackdropClick(e) {\n // Only close if clicked on backdrop, not image\n if (this.closeOnBackdrop && e.target === e.currentTarget) {\n this.close();\n }\n }\n\n async handleActionPrev() {\n this.showPrevious();\n }\n\n async handleActionNext() {\n this.showNext();\n }\n\n async handleActionImageClick() {\n this.toggleImageMode();\n }\n\n // Navigation methods\n showPrevious() {\n if (this.currentIndex > 0) {\n this.currentIndex--;\n this.updateImage();\n this.preloadAdjacentImages();\n }\n }\n\n showNext() {\n if (this.currentIndex < this.images.length - 1) {\n this.currentIndex++;\n this.updateImage();\n this.preloadAdjacentImages();\n }\n }\n\n goToImage(index) {\n if (index >= 0 && index < this.images.length && index !== this.currentIndex) {\n this.currentIndex = index;\n this.updateImage();\n this.preloadAdjacentImages();\n }\n }\n\n // Update image without full re-render\n async updateImage() {\n const currentImage = this.images[this.currentIndex];\n const imgElement = this.element.querySelector('.lightbox-image');\n const counterElement = this.element.querySelector('.lightbox-counter');\n const prevBtn = this.element.querySelector('[data-action=\"prev\"]');\n const nextBtn = this.element.querySelector('[data-action=\"next\"]');\n\n if (imgElement) {\n // Show loading\n this.showLoading();\n\n // Update image\n imgElement.src = currentImage.src;\n imgElement.alt = currentImage.alt;\n\n // Wait for image to load\n await this.waitForImageLoad(imgElement);\n\n // Hide loading\n this.hideLoading();\n }\n\n // Update counter\n if (counterElement) {\n counterElement.textContent = `${this.currentIndex + 1} of ${this.images.length}`;\n }\n\n // Update navigation buttons\n if (prevBtn) {\n prevBtn.disabled = this.currentIndex === 0;\n }\n if (nextBtn) {\n nextBtn.disabled = this.currentIndex === this.images.length - 1;\n }\n\n // Update template properties\n this.updateTemplateProperties();\n\n // Update image display mode\n this.updateImageDisplay();\n\n // Emit event\n const eventBus = this.getApp()?.events;\n if (eventBus) {\n eventBus.emit('lightbox:image-changed', {\n gallery: this,\n index: this.currentIndex,\n image: currentImage\n });\n }\n }\n\n showLoading() {\n const loading = this.element.querySelector('.lightbox-loading');\n if (loading) {\n loading.style.display = 'block';\n }\n }\n\n hideLoading() {\n const loading = this.element.querySelector('.lightbox-loading');\n if (loading) {\n loading.style.display = 'none';\n }\n }\n\n waitForImageLoad(imgElement) {\n return new Promise((resolve) => {\n if (imgElement.complete) {\n resolve();\n } else {\n imgElement.onload = resolve;\n imgElement.onerror = resolve; // Still resolve on error\n }\n });\n }\n\n // Preload adjacent images for smooth navigation\n preloadAdjacentImages() {\n const preloadIndexes = [];\n\n // Previous image\n if (this.currentIndex > 0) {\n preloadIndexes.push(this.currentIndex - 1);\n }\n\n // Next image\n if (this.currentIndex < this.images.length - 1) {\n preloadIndexes.push(this.currentIndex + 1);\n }\n\n preloadIndexes.forEach(index => {\n const image = this.images[index];\n\n // Create image element to trigger browser caching\n const preloadImg = new Image();\n preloadImg.src = image.src;\n });\n }\n\n // Keyboard navigation\n handleKeyboard(e) {\n switch (e.key) {\n case 'Escape':\n e.preventDefault();\n this.close();\n break;\n case 'ArrowLeft':\n e.preventDefault();\n this.showPrevious();\n break;\n case 'ArrowRight':\n e.preventDefault();\n this.showNext();\n break;\n case 'Home':\n e.preventDefault();\n this.goToImage(0);\n break;\n case 'End':\n e.preventDefault();\n this.goToImage(this.images.length - 1);\n break;\n }\n }\n\n // Toggle between fit-to-screen and original size\n toggleImageMode() {\n this.fitToScreen = !this.fitToScreen;\n this.updateTemplateProperties();\n this.updateImageDisplay();\n\n // Emit mode change event\n const eventBus = this.getApp()?.events;\n if (eventBus) {\n eventBus.emit('lightbox:mode-changed', {\n gallery: this,\n fitToScreen: this.fitToScreen\n });\n }\n }\n\n // Update image display without full re-render\n updateImageDisplay() {\n const imgElement = this.element.querySelector('.lightbox-image');\n const containerElement = this.element.querySelector('.lightbox-image-container');\n const indicatorElement = this.element.querySelector('.lightbox-mode-indicator');\n\n if (imgElement) {\n if (this.fitToScreen) {\n imgElement.style.maxWidth = '100%';\n imgElement.style.maxHeight = '100%';\n imgElement.style.objectFit = 'contain';\n imgElement.style.cursor = 'zoom-in';\n } else {\n imgElement.style.maxWidth = 'none';\n imgElement.style.maxHeight = 'none';\n imgElement.style.objectFit = 'none';\n imgElement.style.cursor = 'zoom-out';\n }\n imgElement.style.userSelect = 'none';\n }\n\n if (containerElement) {\n containerElement.style.overflow = this.fitToScreen ? '' : 'auto';\n }\n\n if (indicatorElement) {\n indicatorElement.textContent = `${this.modeIndicator} • Click image to toggle`;\n }\n }\n\n // Close lightbox\n close() {\n // Emit close event\n const eventBus = this.getApp()?.events;\n if (eventBus) {\n eventBus.emit('lightbox:closed', { gallery: this });\n }\n\n this.destroy();\n }\n\n async onBeforeDestroy() {\n // Restore body overflow\n document.body.style.overflow = '';\n\n // Remove keyboard listener\n if (this.allowKeyboard) {\n document.removeEventListener('keydown', this._keyboardHandler);\n }\n\n // Remove from body\n if (this.element.parentNode === document.body) {\n document.body.removeChild(this.element);\n }\n }\n\n // Static method to show lightbox\n static show(images, options = {}) {\n const lightbox = new LightboxGallery({\n images,\n ...options\n });\n\n lightbox.render().then(() => {\n lightbox.mount();\n });\n\n return lightbox;\n }\n}\n\nwindow.LightboxGallery = LightboxGallery;\n","/**\n * PDFViewer - PDF document viewer component with zoom and navigation\n * Built for the MOJO framework with PDF.js integration\n */\n\nimport View from '@core/View.js';\nimport Dialog from '@core/views/feedback/Dialog.js';\n\nexport default class PDFViewer extends View {\n constructor(options = {}) {\n super({\n ...options,\n className: `pdf-viewer ${options.className || ''}`,\n tagName: 'div'\n });\n\n // PDF properties\n this.pdfUrl = options.pdfUrl || options.src || '';\n this.title = options.title || 'PDF Document';\n\n // PDF.js objects\n this.pdfDoc = null;\n this.currentPage = 1;\n this.totalPages = 0;\n this.pageRendering = false;\n this.pageNumPending = null;\n\n // Zoom and display state\n this.scale = 1.0;\n this.minScale = 0.25;\n this.maxScale = 5.0;\n this.scaleStep = 0.25;\n this.fitMode = 'page'; // 'page', 'width', 'auto'\n\n // Canvas and context\n this.canvas = null;\n this.ctx = null;\n\n // Options\n this.showControls = options.showControls !== false;\n this.allowZoom = options.allowZoom !== false;\n this.allowNavigation = options.allowNavigation !== false;\n this.showPageNumbers = options.showPageNumbers !== false;\n\n // Loading state\n this.isLoaded = false;\n this.isLoading = false;\n\n // PDF.js worker path - can be customized\n this.pdfjsWorkerPath = options.pdfjsWorkerPath || 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/4.0.379/pdf.worker.min.js';\n this.pdfjsCMapUrl = options.pdfjsCMapUrl || 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/4.0.379/cmaps/';\n\n // Elements\n this.canvasContainer = null;\n this.controlsElement = null;\n this.statusElement = null;\n this.pageInput = null;\n }\n\n async getTemplate() {\n return `\n <div class=\"pdf-viewer-container\">\n {{#showControls}}\n <div class=\"pdf-viewer-toolbar\" data-container=\"toolbar\">\n <div class=\"btn-toolbar\" role=\"toolbar\">\n <!-- Navigation Controls -->\n {{#allowNavigation}}\n <div class=\"btn-group me-2\" role=\"group\" aria-label=\"Navigation\">\n <button type=\"button\" class=\"btn btn-outline-secondary btn-sm\" data-action=\"first-page\" title=\"First Page\">\n <i class=\"bi bi-chevron-double-left\"></i>\n </button>\n <button type=\"button\" class=\"btn btn-outline-secondary btn-sm\" data-action=\"prev-page\" title=\"Previous Page\">\n <i class=\"bi bi-chevron-left\"></i>\n </button>\n \n {{#showPageNumbers}}\n <div class=\"input-group input-group-sm\" style=\"width: 120px;\">\n <input type=\"number\" class=\"form-control text-center page-input\" min=\"1\" value=\"1\" data-change-action=\"page-input\">\n <span class=\"input-group-text page-total\">/ 0</span>\n </div>\n {{/showPageNumbers}}\n \n <button type=\"button\" class=\"btn btn-outline-secondary btn-sm\" data-action=\"next-page\" title=\"Next Page\">\n <i class=\"bi bi-chevron-right\"></i>\n </button>\n <button type=\"button\" class=\"btn btn-outline-secondary btn-sm\" data-action=\"last-page\" title=\"Last Page\">\n <i class=\"bi bi-chevron-double-right\"></i>\n </button>\n </div>\n {{/allowNavigation}}\n\n <!-- Zoom Controls -->\n {{#allowZoom}}\n <div class=\"btn-group me-2\" role=\"group\" aria-label=\"Zoom\">\n <button type=\"button\" class=\"btn btn-outline-secondary btn-sm\" data-action=\"zoom-out\" title=\"Zoom Out\">\n <i class=\"bi bi-zoom-out\"></i>\n </button>\n <button type=\"button\" class=\"btn btn-outline-secondary btn-sm\" data-action=\"zoom-in\" title=\"Zoom In\">\n <i class=\"bi bi-zoom-in\"></i>\n </button>\n \n <div class=\"btn-group\" role=\"group\">\n <button type=\"button\" class=\"btn btn-outline-secondary btn-sm dropdown-toggle\" data-bs-toggle=\"dropdown\" title=\"Fit\">\n <i class=\"bi bi-arrows-fullscreen\"></i>\n </button>\n <ul class=\"dropdown-menu\">\n <li><a class=\"dropdown-item\" href=\"#\" data-action=\"fit-page\">Fit Page</a></li>\n <li><a class=\"dropdown-item\" href=\"#\" data-action=\"fit-width\">Fit Width</a></li>\n <li><a class=\"dropdown-item\" href=\"#\" data-action=\"actual-size\">Actual Size</a></li>\n </ul>\n </div>\n </div>\n {{/allowZoom}}\n\n <!-- Utility Controls -->\n <div class=\"btn-group me-2\" role=\"group\" aria-label=\"Utilities\">\n <button type=\"button\" class=\"btn btn-outline-secondary btn-sm\" data-action=\"download\" title=\"Download\">\n <i class=\"bi bi-download\"></i>\n </button>\n <button type=\"button\" class=\"btn btn-outline-secondary btn-sm\" data-action=\"print\" title=\"Print\">\n <i class=\"bi bi-printer\"></i>\n </button>\n </div>\n </div>\n </div>\n {{/showControls}}\n\n <!-- PDF Content Area -->\n <div class=\"pdf-viewer-content\" data-container=\"content\">\n <div class=\"pdf-canvas-container\" data-container=\"canvasContainer\">\n <canvas class=\"pdf-canvas\" data-container=\"canvas\"></canvas>\n </div>\n\n <div class=\"pdf-viewer-overlay\">\n <div class=\"pdf-viewer-loading\">\n <div class=\"spinner-border text-primary\" role=\"status\">\n <span class=\"visually-hidden\">Loading PDF...</span>\n </div>\n <div class=\"mt-2\">Loading PDF...</div>\n </div>\n </div>\n\n <div class=\"pdf-viewer-error\" style=\"display: none;\">\n <div class=\"alert alert-danger\" role=\"alert\">\n <i class=\"bi bi-exclamation-triangle\"></i>\n <strong>Error:</strong> <span class=\"error-message\">Failed to load PDF</span>\n </div>\n </div>\n </div>\n\n <!-- Status Bar -->\n <div class=\"pdf-viewer-status\" data-container=\"status\">\n <small class=\"text-muted\">\n <span class=\"current-page\">0</span> of <span class=\"total-pages\">0</span> pages |\n <span class=\"zoom-level\">100%</span> |\n <span class=\"document-title\">{{title}}</span>\n </small>\n </div>\n </div>\n `;\n }\n\n get() {\n return {\n pdfUrl: this.pdfUrl,\n title: this.title,\n showControls: this.showControls,\n allowZoom: this.allowZoom,\n allowNavigation: this.allowNavigation,\n showPageNumbers: this.showPageNumbers\n };\n }\n\n async onAfterRender() {\n // Cache DOM elements\n this.canvas = this.element.querySelector('.pdf-canvas');\n this.canvasContainer = this.element.querySelector('.pdf-canvas-container');\n this.controlsElement = this.element.querySelector('.pdf-viewer-toolbar');\n this.statusElement = this.element.querySelector('.pdf-viewer-status');\n this.pageInput = this.element.querySelector('.page-input');\n this.overlayElement = this.element.querySelector('.pdf-viewer-overlay');\n this.errorElement = this.element.querySelector('.pdf-viewer-error');\n\n if (this.canvas) {\n this.ctx = this.canvas.getContext('2d');\n }\n// Set up essential event listeners (keyboard, resize)\nthis.setupEssentialEventListeners();\n\n// Initialize PDF.js and load PDF\nawait this.initializePDFJS();\nif (this.pdfUrl) {\n await this.loadPDF();\n}\n}\n\n\n\n setupEssentialEventListeners() {\n // Essential events that can't be handled by EventDelegate\n const keydownHandler = (e) => this.handleKeyDown(e);\n document.addEventListener('keydown', keydownHandler);\n\n // Canvas resize observer for fit mode\n let resizeObserver = null;\n if (this.canvasContainer) {\n resizeObserver = new ResizeObserver(() => {\n if (this.fitMode !== 'auto') {\n this.applyFitMode();\n }\n });\n resizeObserver.observe(this.canvasContainer);\n }\n\n // Store listeners for cleanup\n this._essentialListeners = [\n { el: document, type: 'keydown', fn: keydownHandler }\n ];\n this._resizeObserver = resizeObserver;\n }\n\n async initializePDFJS() {\n try {\n // Load PDF.js if not already loaded\n if (typeof window.pdfjsLib === 'undefined') {\n await this.loadPDFJSLibrary();\n }\n\n // Configure PDF.js\n window.pdfjsLib.GlobalWorkerOptions.workerSrc = this.pdfjsWorkerPath;\n \n return true;\n } catch (error) {\n console.error('Failed to initialize PDF.js:', error);\n this.showError('Failed to initialize PDF viewer');\n return false;\n }\n }\n\n async loadPDFJSLibrary() {\n return new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.src = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/4.0.379/pdf.min.js';\n script.onload = resolve;\n script.onerror = reject;\n document.head.appendChild(script);\n });\n }\n\n // Action Handlers\n async handleActionFirstPage() {\n await this.goToPage(1);\n }\n\n async handleActionPrevPage() {\n await this.goToPage(this.currentPage - 1);\n }\n\n async handleActionNextPage() {\n await this.goToPage(this.currentPage + 1);\n }\n\n async handleActionLastPage() {\n await this.goToPage(this.totalPages);\n }\n\n async onChangePageInput(event, element) {\n const pageNumber = parseInt(element.value, 10);\n if (pageNumber >= 1 && pageNumber <= this.totalPages) {\n await this.goToPage(pageNumber);\n } else {\n element.value = this.currentPage;\n }\n }\n\n async handleActionZoomIn() {\n this.setScale(this.scale + this.scaleStep);\n }\n\n async handleActionZoomOut() {\n this.setScale(this.scale - this.scaleStep);\n }\n\n async handleActionFitPage() {\n this.setFitMode('page');\n }\n\n async handleActionFitWidth() {\n this.setFitMode('width');\n }\n\n async handleActionActualSize() {\n this.setScale(1.0);\n this.fitMode = 'auto';\n }\n\n async handleActionDownload() {\n this.downloadPDF();\n }\n\n async handleActionPrint() {\n window.print();\n }\n\n // PDF Loading\n async loadPDF() {\n if (!this.pdfUrl || !window.pdfjsLib) {\n this.showError('PDF URL or PDF.js library not available');\n return false;\n }\n\n this.isLoading = true;\n this.showLoading();\n\n try {\n const loadingTask = window.pdfjsLib.getDocument({\n url: this.pdfUrl,\n cMapUrl: this.pdfjsCMapUrl,\n cMapPacked: true\n });\n\n this.pdfDoc = await loadingTask.promise;\n this.totalPages = this.pdfDoc.numPages;\n this.currentPage = 1;\n\n // Update UI\n this.updatePageControls();\n this.updateStatus();\n\n // Render first page\n await this.renderPage(1);\n\n this.isLoaded = true;\n this.isLoading = false;\n this.element.classList.add('loaded');\n this.hideLoading();\n\n // Apply initial fit mode\n this.applyFitMode();\n\n // Emit loaded event via EventBus\n const eventBus = this.getApp()?.events;\n if (eventBus) {\n eventBus.emit('pdfviewer:loaded', { \n viewer: this, \n pdfUrl: this.pdfUrl,\n totalPages: this.totalPages\n });\n }\n\n return true;\n\n } catch (error) {\n console.error('Error loading PDF:', error);\n this.isLoading = false;\n this.showError('Failed to load PDF document');\n \n // Emit error event via EventBus\n const eventBus = this.getApp()?.events;\n if (eventBus) {\n eventBus.emit('pdfviewer:error', { \n viewer: this, \n pdfUrl: this.pdfUrl,\n error: error.message\n });\n }\n \n return false;\n }\n }\n\n async renderPage(pageNumber) {\n if (this.pageRendering) {\n this.pageNumPending = pageNumber;\n return;\n }\n\n if (!this.pdfDoc || !this.canvas || !this.ctx) {\n return;\n }\n\n this.pageRendering = true;\n this.currentPage = pageNumber;\n\n try {\n const page = await this.pdfDoc.getPage(pageNumber);\n const viewport = page.getViewport({ scale: this.scale });\n\n // Set canvas dimensions\n this.canvas.height = viewport.height;\n this.canvas.width = viewport.width;\n\n // Clear canvas\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n // Render page\n const renderContext = {\n canvasContext: this.ctx,\n viewport: viewport\n };\n\n const renderTask = page.render(renderContext);\n await renderTask.promise;\n\n this.pageRendering = false;\n\n // If there was a pending page render request\n if (this.pageNumPending !== null) {\n const pendingPage = this.pageNumPending;\n this.pageNumPending = null;\n await this.renderPage(pendingPage);\n }\n\n this.updatePageControls();\n this.updateStatus();\n\n // Emit page changed event\n const eventBus = this.getApp()?.events;\n if (eventBus) {\n eventBus.emit('pdfviewer:page-changed', { \n viewer: this, \n currentPage: this.currentPage,\n totalPages: this.totalPages\n });\n }\n\n } catch (error) {\n console.error('Error rendering page:', error);\n this.pageRendering = false;\n this.showError('Failed to render PDF page');\n }\n }\n\n // Navigation\n async goToPage(pageNumber) {\n if (!this.pdfDoc || pageNumber < 1 || pageNumber > this.totalPages) {\n return;\n }\n\n await this.renderPage(pageNumber);\n }\n\n // Zoom and Fit\n setScale(scale) {\n const oldScale = this.scale;\n this.scale = Math.max(this.minScale, Math.min(this.maxScale, scale));\n this.fitMode = 'auto';\n \n if (this.isLoaded) {\n this.renderPage(this.currentPage);\n }\n\n // Emit scale change event\n const eventBus = this.getApp()?.events;\n if (eventBus && oldScale !== this.scale) {\n eventBus.emit('pdfviewer:scale-changed', { \n viewer: this, \n oldScale, \n newScale: this.scale \n });\n }\n }\n\n setFitMode(mode) {\n const oldMode = this.fitMode;\n this.fitMode = mode;\n this.applyFitMode();\n\n // Emit fit mode change event\n const eventBus = this.getApp()?.events;\n if (eventBus) {\n eventBus.emit('pdfviewer:fit-mode-changed', { \n viewer: this, \n oldMode, \n newMode: mode \n });\n }\n }\n\n applyFitMode() {\n if (!this.isLoaded || !this.pdfDoc || !this.canvasContainer) {\n return;\n }\n\n this.pdfDoc.getPage(this.currentPage).then(page => {\n const containerRect = this.canvasContainer.getBoundingClientRect();\n const viewport = page.getViewport({ scale: 1 });\n\n let newScale;\n if (this.fitMode === 'page') {\n const scaleX = (containerRect.width - 40) / viewport.width;\n const scaleY = (containerRect.height - 40) / viewport.height;\n newScale = Math.min(scaleX, scaleY);\n } else if (this.fitMode === 'width') {\n newScale = (containerRect.width - 40) / viewport.width;\n } else {\n return; // auto mode, don't change scale\n }\n\n this.scale = Math.max(this.minScale, Math.min(this.maxScale, newScale));\n this.renderPage(this.currentPage);\n });\n }\n\n // Event Handlers\n handleKeyDown(e) {\n // Only handle if PDF viewer is focused or no input is focused\n if (e.target.tagName === 'INPUT' && e.target !== this.pageInput) {\n return;\n }\n\n switch (e.key) {\n case 'ArrowLeft':\n case 'PageUp':\n e.preventDefault();\n this.goToPage(this.currentPage - 1);\n break;\n case 'ArrowRight':\n case 'PageDown':\n e.preventDefault();\n this.goToPage(this.currentPage + 1);\n break;\n case 'Home':\n e.preventDefault();\n this.goToPage(1);\n break;\n case 'End':\n e.preventDefault();\n this.goToPage(this.totalPages);\n break;\n case '+':\n case '=':\n if (e.ctrlKey || e.metaKey) {\n e.preventDefault();\n this.setScale(this.scale + this.scaleStep);\n }\n break;\n case '-':\n if (e.ctrlKey || e.metaKey) {\n e.preventDefault();\n this.setScale(this.scale - this.scaleStep);\n }\n break;\n case '0':\n if (e.ctrlKey || e.metaKey) {\n e.preventDefault();\n this.setFitMode('page');\n }\n break;\n }\n }\n\n // UI Updates\n updatePageControls() {\n // Update page input\n if (this.pageInput) {\n this.pageInput.value = this.currentPage;\n }\n\n // Update page total display\n const pageTotalElement = this.element.querySelector('.page-total');\n if (pageTotalElement) {\n pageTotalElement.textContent = `/ ${this.totalPages}`;\n }\n\n // Update navigation buttons\n const firstBtn = this.element.querySelector('[data-action=\"first-page\"]');\n const prevBtn = this.element.querySelector('[data-action=\"prev-page\"]');\n const nextBtn = this.element.querySelector('[data-action=\"next-page\"]');\n const lastBtn = this.element.querySelector('[data-action=\"last-page\"]');\n\n if (firstBtn) firstBtn.disabled = this.currentPage <= 1;\n if (prevBtn) prevBtn.disabled = this.currentPage <= 1;\n if (nextBtn) nextBtn.disabled = this.currentPage >= this.totalPages;\n if (lastBtn) lastBtn.disabled = this.currentPage >= this.totalPages;\n\n // Update zoom buttons\n const zoomInBtn = this.element.querySelector('[data-action=\"zoom-in\"]');\n const zoomOutBtn = this.element.querySelector('[data-action=\"zoom-out\"]');\n\n if (zoomInBtn) zoomInBtn.disabled = this.scale >= this.maxScale;\n if (zoomOutBtn) zoomOutBtn.disabled = this.scale <= this.minScale;\n }\n\n updateStatus() {\n if (!this.statusElement) return;\n\n const currentPageElement = this.statusElement.querySelector('.current-page');\n const totalPagesElement = this.statusElement.querySelector('.total-pages');\n const zoomLevelElement = this.statusElement.querySelector('.zoom-level');\n\n if (currentPageElement) {\n currentPageElement.textContent = this.currentPage;\n }\n if (totalPagesElement) {\n totalPagesElement.textContent = this.totalPages;\n }\n if (zoomLevelElement) {\n zoomLevelElement.textContent = `${Math.round(this.scale * 100)}%`;\n }\n }\n\n // Utility Methods\n showLoading() {\n if (this.overlayElement) {\n this.overlayElement.style.display = 'flex';\n }\n }\n\n hideLoading() {\n if (this.overlayElement) {\n this.overlayElement.style.display = 'none';\n }\n }\n\n showError(message) {\n this.hideLoading();\n \n if (this.errorElement) {\n const errorMessageElement = this.errorElement.querySelector('.error-message');\n if (errorMessageElement) {\n errorMessageElement.textContent = message;\n }\n this.errorElement.style.display = 'block';\n }\n\n console.error('PDF Viewer Error:', message);\n }\n\n downloadPDF() {\n if (!this.pdfUrl) return;\n\n const link = document.createElement('a');\n link.href = this.pdfUrl;\n link.download = this.title + '.pdf';\n link.target = '_blank';\n link.click();\n }\n\n // Public API\n setPDF(pdfUrl, title = '') {\n const oldPdfUrl = this.pdfUrl;\n this.pdfUrl = pdfUrl;\n this.title = title || 'PDF Document';\n this.isLoaded = false;\n this.element.classList.remove('loaded');\n \n if (this.pdfDoc) {\n this.pdfDoc.destroy();\n this.pdfDoc = null;\n }\n \n this.currentPage = 1;\n this.totalPages = 0;\n this.scale = 1.0;\n \n if (pdfUrl) {\n this.loadPDF();\n }\n\n // Emit PDF changed event\n const eventBus = this.getApp()?.events;\n if (eventBus) {\n eventBus.emit('pdfviewer:pdf-changed', { \n viewer: this, \n oldPdfUrl, \n newPdfUrl: pdfUrl \n });\n }\n }\n\n getCurrentPage() {\n return this.currentPage;\n }\n\n getTotalPages() {\n return this.totalPages;\n }\n\n getCurrentScale() {\n return this.scale;\n }\n\n async onBeforeDestroy() {\n // Clean up PDF.js resources\n if (this.pdfDoc) {\n this.pdfDoc.destroy();\n this.pdfDoc = null;\n }\n\n this.pageRendering = false;\n this.pageNumPending = null;\n\n // Clean up essential event listeners\n if (this._essentialListeners) {\n this._essentialListeners.forEach(({ el, type, fn }) => {\n if (el) el.removeEventListener(type, fn);\n });\n this._essentialListeners = null;\n }\n\n // Clean up resize observer\n if (this._resizeObserver) {\n this._resizeObserver.disconnect();\n this._resizeObserver = null;\n }\n\n // Emit destroy event\n const eventBus = this.getApp()?.events;\n if (eventBus) {\n eventBus.emit('pdfviewer:destroyed', { viewer: this });\n }\n }\n\n // Static method to show PDF in a fullscreen dialog\n static async showDialog(pdfUrl, options = {}) {\n const {\n title = 'PDF Viewer',\n size = 'fullscreen',\n showControls = true,\n allowZoom = true,\n allowNavigation = true,\n showPageNumbers = true,\n ...dialogOptions\n } = options;\n\n const viewer = new PDFViewer({\n pdfUrl,\n title,\n showControls,\n allowZoom,\n allowNavigation,\n showPageNumbers\n });\n\n const dialog = new Dialog({\n title,\n body: viewer,\n size,\n centered: true,\n backdrop: 'static',\n keyboard: true,\n buttons: [\n { \n text: 'Download', \n action: 'download', \n class: 'btn btn-outline-primary' \n },\n { \n text: 'Close', \n action: 'close', \n class: 'btn btn-secondary',\n dismiss: true\n }\n ],\n ...dialogOptions\n });\n\n // Render and mount\n await dialog.render();\n document.body.appendChild(dialog.element);\n await dialog.mount();\n\n // Show the dialog\n dialog.show();\n\n return new Promise((resolve) => {\n dialog.on('hidden', () => {\n dialog.destroy();\n resolve(viewer);\n });\n\n dialog.on('action:download', () => {\n viewer.downloadPDF();\n });\n\n dialog.on('action:close', () => {\n dialog.hide();\n });\n });\n }\n}"],"names":["LightboxGallery","View","constructor","options","super","className","tagName","rawImages","Array","isArray","images","src","filter","Boolean","this","map","img","alt","currentIndex","startIndex","showNavigation","length","showCounter","allowKeyboard","closeOnBackdrop","fitToScreen","_keyboardHandler","handleKeyboard","bind","updateTemplateProperties","currentImage","currentNumber","total","isFirst","isLast","imageStyle","containerStyle","modeIndicator","getTemplate","onAfterRender","document","body","appendChild","element","style","overflow","addEventListener","preloadAdjacentImages","handleActionClose","close","handleActionBackdropClick","e","target","currentTarget","handleActionPrev","showPrevious","handleActionNext","showNext","handleActionImageClick","toggleImageMode","updateImage","goToImage","index","imgElement","querySelector","counterElement","prevBtn","nextBtn","showLoading","waitForImageLoad","hideLoading","textContent","disabled","updateImageDisplay","eventBus","getApp","events","emit","gallery","image","loading","display","Promise","resolve","complete","onload","onerror","preloadIndexes","push","forEach","Image","key","preventDefault","containerElement","indicatorElement","maxWidth","maxHeight","objectFit","cursor","userSelect","destroy","onBeforeDestroy","removeEventListener","parentNode","removeChild","show","lightbox","render","then","mount","window","PDFViewer","pdfUrl","title","pdfDoc","currentPage","totalPages","pageRendering","pageNumPending","scale","minScale","maxScale","scaleStep","fitMode","canvas","ctx","showControls","allowZoom","allowNavigation","showPageNumbers","isLoaded","isLoading","pdfjsWorkerPath","pdfjsCMapUrl","canvasContainer","controlsElement","statusElement","pageInput","get","overlayElement","errorElement","getContext","setupEssentialEventListeners","initializePDFJS","loadPDF","keydownHandler","handleKeyDown","resizeObserver","ResizeObserver","applyFitMode","observe","_essentialListeners","el","type","fn","_resizeObserver","pdfjsLib","loadPDFJSLibrary","GlobalWorkerOptions","workerSrc","error","console","showError","reject","script","createElement","head","handleActionFirstPage","goToPage","handleActionPrevPage","handleActionNextPage","handleActionLastPage","onChangePageInput","event","pageNumber","parseInt","value","handleActionZoomIn","setScale","handleActionZoomOut","handleActionFitPage","setFitMode","handleActionFitWidth","handleActionActualSize","handleActionDownload","downloadPDF","handleActionPrint","print","loadingTask","getDocument","url","cMapUrl","cMapPacked","promise","numPages","updatePageControls","updateStatus","renderPage","classList","add","viewer","message","page","getPage","viewport","getViewport","height","width","clearRect","renderContext","canvasContext","renderTask","pendingPage","oldScale","Math","max","min","newScale","mode","oldMode","newMode","containerRect","getBoundingClientRect","scaleX","scaleY","ctrlKey","metaKey","pageTotalElement","firstBtn","lastBtn","zoomInBtn","zoomOutBtn","currentPageElement","totalPagesElement","zoomLevelElement","round","errorMessageElement","link","href","download","click","setPDF","oldPdfUrl","remove","newPdfUrl","getCurrentPage","getTotalPages","getCurrentScale","disconnect","showDialog","size","dialogOptions","dialog","Dialog","centered","backdrop","keyboard","buttons","text","action","class","dismiss","on","hide"],"mappings":"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"}