@smartnet360/svelte-components 0.0.35 → 0.0.37

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.
@@ -1 +1,2 @@
1
1
  export * from './antenna-pattern/index.js';
2
+ export * from './site-check/index.js';
@@ -4,3 +4,4 @@
4
4
  export * from './antenna-pattern/index.js';
5
5
  // Test app (if needed for demos)
6
6
  // export * from './test/index.js';
7
+ export * from './site-check/index.js';
@@ -5,6 +5,7 @@
5
5
  import { ChartComponent, type Layout } from '../../core/Charts';
6
6
  import { buildTreeNodes, filterChartData, transformChartData, type CellTrafficRecord } from './index';
7
7
  import { expandLayoutForCells } from './helper';
8
+ import { log } from '../../core/logger';
8
9
  import { onMount } from 'svelte';
9
10
  import type { Mode } from '../../index.js';
10
11
 
@@ -20,8 +21,18 @@
20
21
  let treeStore = $state<ReturnType<typeof createTreeStore> | null>(null);
21
22
 
22
23
  onMount(() => {
24
+ log('🚀 SiteCheck Initializing', {
25
+ totalRecords: rawData.length,
26
+ baseMetrics,
27
+ mode
28
+ });
29
+
23
30
  // Build tree nodes from raw data
24
31
  const treeNodes = buildTreeNodes(rawData);
32
+ log('🌲 Tree Nodes Built', {
33
+ nodeCount: treeNodes.length,
34
+ firstNode: treeNodes[0]
35
+ });
25
36
 
26
37
  // Create tree store
27
38
  treeStore = createTreeStore({
@@ -30,6 +41,7 @@
30
41
  persistState: true,
31
42
  defaultExpandAll: false
32
43
  });
44
+ log('✅ Tree Store Created', { namespace: 'site-check' });
33
45
  });
34
46
 
35
47
  // Derive chart data from tree selection
@@ -37,22 +49,55 @@
37
49
  if (!treeStore) return [];
38
50
  const storeValue = $treeStore;
39
51
  if (!storeValue) return [];
40
- return filterChartData(rawData, storeValue.state.checkedPaths);
52
+ const filtered = filterChartData(rawData, storeValue.state.checkedPaths);
53
+ log('🔍 Filtered Data:', {
54
+ totalRaw: rawData.length,
55
+ checkedPaths: Array.from(storeValue.state.checkedPaths),
56
+ filteredCount: filtered.length,
57
+ cells: Array.from(new Set(filtered.map(r => r.cellName)))
58
+ });
59
+ return filtered;
41
60
  });
42
61
 
43
62
  // Transform data using base metrics from layout
44
- let chartData = $derived(transformChartData(filteredData, baseMetrics));
63
+ let chartData = $derived.by(() => {
64
+ const transformed = transformChartData(filteredData, baseMetrics);
65
+ log('📊 Chart Data:', {
66
+ filteredRows: filteredData.length,
67
+ transformedRows: transformed.length,
68
+ baseMetrics,
69
+ sampleRow: transformed[0],
70
+ columns: transformed[0] ? Object.keys(transformed[0]) : []
71
+ });
72
+ return transformed;
73
+ });
45
74
 
46
75
  // Expand layout based on selected cells
47
- let chartLayout = $derived(expandLayoutForCells(baseLayout, filteredData));
48
- console.log('chartLayout', chartLayout);
76
+ let chartLayout = $derived.by(() => {
77
+ const expanded = expandLayoutForCells(baseLayout, filteredData);
78
+ log('📐 Chart Layout:', {
79
+ grid: expanded.grid,
80
+ sectionsCount: expanded.sections.length,
81
+ totalCharts: expanded.sections.reduce((sum, s) => sum + s.charts.length, 0),
82
+ firstSection: expanded.sections[0]
83
+ });
84
+ return expanded;
85
+ });
49
86
 
50
87
  let totalRecords = $derived(rawData.length);
51
88
  let visibleRecords = $derived(filteredData.length);
52
89
 
53
90
  // Compute simple stats
54
- let totalCells = $derived(new Set(filteredData.map((r) => r.cellName)).size);
55
- let totalSites = $derived(new Set(filteredData.map((r) => r.siteName)).size);
91
+ let totalCells = $derived.by(() => {
92
+ const count = new Set(filteredData.map((r) => r.cellName)).size;
93
+ log('📱 Total Cells:', count);
94
+ return count;
95
+ });
96
+ let totalSites = $derived.by(() => {
97
+ const count = new Set(filteredData.map((r) => r.siteName)).size;
98
+ log('📡 Total Sites:', count);
99
+ return count;
100
+ });
56
101
  </script>
57
102
 
58
103
  <div class="container-fluid vh-100 d-flex flex-column">
@@ -2,10 +2,12 @@
2
2
  * Data Transforms for Site Check Component
3
3
  * Converts raw CSV data to TreeView nodes and Chart configurations
4
4
  */
5
+ import { log } from '../../core/logger';
5
6
  /**
6
7
  * Build hierarchical tree structure: Site → Sector (Azimuth) → Cell (Band)
7
8
  */
8
9
  export function buildTreeNodes(data) {
10
+ log('🔄 Building tree nodes', { recordCount: data.length });
9
11
  // Group by site → azimuth → cell
10
12
  const siteMap = new Map();
11
13
  data.forEach((record) => {
@@ -33,6 +35,7 @@ export function buildTreeNodes(data) {
33
35
  // icon: '📡',
34
36
  metadata: { type: 'site', siteName },
35
37
  defaultExpanded: false,
38
+ defaultChecked: false, // Don't check parent nodes
36
39
  children: []
37
40
  };
38
41
  Array.from(azimuthMap.entries())
@@ -44,6 +47,7 @@ export function buildTreeNodes(data) {
44
47
  // icon: '📍',
45
48
  metadata: { type: 'sector', azimuth, siteName },
46
49
  defaultExpanded: false,
50
+ defaultChecked: false, // Don't check parent nodes
47
51
  children: []
48
52
  };
49
53
  Array.from(cellMap.entries())
@@ -69,6 +73,11 @@ export function buildTreeNodes(data) {
69
73
  });
70
74
  treeNodes.push(siteNode);
71
75
  });
76
+ log('✅ Tree nodes built', {
77
+ totalNodes: treeNodes.length,
78
+ totalSites: siteMap.size,
79
+ sampleSite: treeNodes[0]?.label
80
+ });
72
81
  return treeNodes;
73
82
  }
74
83
  /**
@@ -87,6 +96,11 @@ function getBandIcon(band) {
87
96
  * Only include cells that are checked in the tree
88
97
  */
89
98
  export function filterChartData(data, checkedPaths) {
99
+ log('🔄 Filtering chart data', {
100
+ totalRecords: data.length,
101
+ checkedPathsCount: checkedPaths.size,
102
+ paths: Array.from(checkedPaths)
103
+ });
90
104
  // Extract cell names from checked leaf paths (format: "site:azimuth:cellName")
91
105
  const selectedCells = new Set();
92
106
  checkedPaths.forEach((path) => {
@@ -97,7 +111,13 @@ export function filterChartData(data, checkedPaths) {
97
111
  }
98
112
  });
99
113
  // Filter data to only include selected cells
100
- return data.filter((record) => selectedCells.has(record.cellName));
114
+ const filtered = data.filter((record) => selectedCells.has(record.cellName));
115
+ log('✅ Data filtered', {
116
+ selectedCells: Array.from(selectedCells),
117
+ filteredRecords: filtered.length,
118
+ uniqueCells: new Set(filtered.map(r => r.cellName)).size
119
+ });
120
+ return filtered;
101
121
  }
102
122
  /**
103
123
  * Transform data for chart component consumption
@@ -108,6 +128,11 @@ export function filterChartData(data, checkedPaths) {
108
128
  * @param baseMetrics - Array of metric names to pivot (e.g., ['dlGBytes', 'ulGBytes'])
109
129
  */
110
130
  export function transformChartData(data, baseMetrics) {
131
+ log('🔄 Transforming chart data', {
132
+ inputRecords: data.length,
133
+ baseMetrics,
134
+ uniqueCells: new Set(data.map(r => r.cellName)).size
135
+ });
111
136
  // Group data by date
112
137
  const dateMap = new Map();
113
138
  data.forEach((record) => {
@@ -138,5 +163,13 @@ export function transformChartData(data, baseMetrics) {
138
163
  });
139
164
  // Sort by date
140
165
  pivotedData.sort((a, b) => a.TIMESTAMP.localeCompare(b.TIMESTAMP));
166
+ log('✅ Data transformed', {
167
+ outputRows: pivotedData.length,
168
+ dateRange: pivotedData.length > 0 ?
169
+ `${pivotedData[0].TIMESTAMP} to ${pivotedData[pivotedData.length - 1].TIMESTAMP}` :
170
+ 'none',
171
+ columnsPerRow: pivotedData[0] ? Object.keys(pivotedData[0]).length : 0,
172
+ sampleRow: pivotedData[0]
173
+ });
141
174
  return pivotedData;
142
175
  }
@@ -7,6 +7,7 @@
7
7
  import { createTimeSeriesTraceWithMA, getYAxisTitle, createDefaultPlotlyLayout } from './data-utils.js';
8
8
  import { adaptPlotlyLayout, addMarkersToLayout, type ContainerSize } from './adapt.js';
9
9
  import { getKPIValues, type ProcessedChartData } from './data-processor.js';
10
+ import { log } from '../logger';
10
11
 
11
12
  const dispatch = createEventDispatcher<{
12
13
  chartcontextmenu: {
@@ -235,9 +236,16 @@
235
236
  // Use Plotly.react() for updates (preserves zoom/pan) or newPlot for initial render
236
237
  if (chartInitialized) {
237
238
  // Update existing chart - much faster, preserves user interactions
239
+ log('🔄 Updating chart with Plotly.react', { chartTitle: chart.title });
238
240
  Plotly.react(chartDiv, traces, finalLayout, config);
239
241
  } else {
240
242
  // Initial chart creation
243
+ log('📊 Creating new chart with Plotly.newPlot', {
244
+ chartTitle: chart.title,
245
+ traces: traces.length,
246
+ leftKPIs: chart.yLeft.length,
247
+ rightKPIs: chart.yRight.length
248
+ });
241
249
  Plotly.newPlot(chartDiv, traces, finalLayout, config);
242
250
  chartInitialized = true;
243
251
  }
@@ -251,11 +259,23 @@
251
259
  }
252
260
 
253
261
  onMount(() => {
262
+ log('📈 ChartCard mounted', {
263
+ chartTitle: chart.title,
264
+ leftKPIs: chart.yLeft.length,
265
+ rightKPIs: chart.yRight.length
266
+ });
267
+
254
268
  // Initial container size measurement
255
269
  if (chartDiv) {
256
270
  const rect = chartDiv.getBoundingClientRect();
257
271
  containerSize.width = rect.width;
258
272
  containerSize.height = rect.height;
273
+
274
+ log('📐 Initial container size', {
275
+ chartTitle: chart.title,
276
+ width: rect.width,
277
+ height: rect.height
278
+ });
259
279
  }
260
280
 
261
281
  renderChart();
@@ -6,6 +6,7 @@
6
6
  import ChartCard from './ChartCard.svelte';
7
7
  import GlobalControls from './GlobalControls.svelte';
8
8
  import { getPreprocessedData, type ProcessedChartData } from './data-processor.js';
9
+ import { log } from '../logger';
9
10
 
10
11
  interface Props {
11
12
  layout: Layout;
@@ -55,6 +56,18 @@
55
56
 
56
57
  let { layout, data, mode, markers, plotlyLayout, enableAdaptation = true, showGlobalControls = true }: Props = $props();
57
58
 
59
+ // Log component initialization
60
+ $effect(() => {
61
+ log('📊 ChartComponent initialized', {
62
+ mode,
63
+ dataRows: data.length,
64
+ sections: layout.sections.length,
65
+ totalCharts: layout.sections.reduce((sum, s) => sum + s.charts.length, 0),
66
+ enableAdaptation,
67
+ showGlobalControls
68
+ });
69
+ });
70
+
58
71
  // Preprocess raw data once - automatically memoized by Svelte's $derived
59
72
  // This extracts all KPI values and timestamps, cached until data or layout changes
60
73
  let processedData = $derived(getPreprocessedData(data, layout));
@@ -76,6 +89,12 @@
76
89
 
77
90
  // Handler for global controls updates
78
91
  function handleControlsUpdate(updatedControls: GlobalChartControls) {
92
+ log('🎛️ Global controls updated', {
93
+ movingAverageEnabled: updatedControls.movingAverage?.enabled,
94
+ windowOverride: updatedControls.movingAverage?.windowOverride,
95
+ markersEnabled: updatedControls.markers?.enabled,
96
+ legendEnabled: updatedControls.legend?.enabled
97
+ });
79
98
  globalControls = updatedControls;
80
99
  }
81
100
 
@@ -166,12 +185,17 @@
166
185
 
167
186
  function zoomSelectedChart() {
168
187
  if (contextMenu.chart && contextMenu.section) {
188
+ log('🔍 Zooming chart', {
189
+ chartTitle: contextMenu.chart.title,
190
+ sectionId: contextMenu.section.id
191
+ });
169
192
  zoomedChart = { chart: contextMenu.chart, section: contextMenu.section };
170
193
  }
171
194
  closeContextMenu();
172
195
  }
173
196
 
174
197
  function exitZoom() {
198
+ log('🔍 Exiting zoom mode');
175
199
  zoomedChart = null;
176
200
  closeContextMenu();
177
201
  }
@@ -1,3 +1,4 @@
1
+ import { log } from '../logger';
1
2
  /**
2
3
  * Extract all unique KPI rawNames from a layout configuration
3
4
  * This determines which columns we need to extract from raw data
@@ -16,6 +17,10 @@ export function extractKPINames(layout) {
16
17
  }
17
18
  }
18
19
  }
20
+ log('📋 KPI names extracted', {
21
+ totalKPIs: kpiNames.size,
22
+ kpiNames: Array.from(kpiNames)
23
+ });
19
24
  return kpiNames;
20
25
  }
21
26
  /**
@@ -28,6 +33,11 @@ export function extractKPINames(layout) {
28
33
  * @returns Preprocessed data ready for chart rendering
29
34
  */
30
35
  export function preprocessChartData(data, layout, timestampField = 'TIMESTAMP') {
36
+ log('🔄 Preprocessing chart data', {
37
+ rawDataRows: data.length,
38
+ sections: layout.sections.length,
39
+ timestampField
40
+ });
31
41
  // Extract all unique KPI names we need to process
32
42
  const kpiNames = extractKPINames(layout);
33
43
  // Initialize the result map
@@ -42,9 +52,18 @@ export function preprocessChartData(data, layout, timestampField = 'TIMESTAMP')
42
52
  })
43
53
  .filter(val => !isNaN(val)); // Remove invalid values
44
54
  kpiValues.set(kpiName, values);
55
+ if (values.length === 0) {
56
+ log('⚠️ No valid values found for KPI', { kpiName });
57
+ }
45
58
  }
46
59
  // Extract timestamps once
47
60
  const timestamps = data.map(row => row[timestampField]);
61
+ log('✅ Data preprocessing complete', {
62
+ processedKPIs: kpiValues.size,
63
+ timestampCount: timestamps.length,
64
+ sampleKPI: kpiValues.keys().next().value,
65
+ sampleValues: kpiValues.values().next().value?.slice(0, 3)
66
+ });
48
67
  return {
49
68
  kpiValues,
50
69
  timestamps,
@@ -72,9 +91,11 @@ export function getPreprocessedData(data, layout, timestampField = 'TIMESTAMP')
72
91
  if (cached) {
73
92
  // Verify cache is still valid (data reference matches)
74
93
  if (cached._rawDataRef === data) {
94
+ log('💾 Using cached preprocessed data');
75
95
  return cached;
76
96
  }
77
97
  }
98
+ log('🔄 Cache miss - preprocessing data');
78
99
  // Cache miss or invalid - compute and cache
79
100
  const processed = preprocessChartData(data, layout, timestampField);
80
101
  preprocessCache.set(data, processed);
@@ -2,6 +2,7 @@
2
2
  * Tree utility functions
3
3
  * Helper functions for path manipulation, tree flattening, and state management
4
4
  */
5
+ import { log } from '../logger';
5
6
  /**
6
7
  * Get parent path from a node path
7
8
  * @example getParentPath("site-a:sector-1:700", ":") => "site-a:sector-1"
@@ -144,10 +145,18 @@ export function saveStateToStorage(namespace, state) {
144
145
  if (!namespace)
145
146
  return;
146
147
  try {
147
- localStorage.setItem(getStorageKey(namespace, 'checked'), JSON.stringify(Array.from(state.checkedPaths)));
148
- localStorage.setItem(getStorageKey(namespace, 'expanded'), JSON.stringify(Array.from(state.expandedPaths)));
148
+ const checkedArray = Array.from(state.checkedPaths);
149
+ const expandedArray = Array.from(state.expandedPaths);
150
+ localStorage.setItem(getStorageKey(namespace, 'checked'), JSON.stringify(checkedArray));
151
+ localStorage.setItem(getStorageKey(namespace, 'expanded'), JSON.stringify(expandedArray));
152
+ log('💾 State saved to localStorage', {
153
+ namespace,
154
+ checkedCount: checkedArray.length,
155
+ expandedCount: expandedArray.length
156
+ });
149
157
  }
150
158
  catch (error) {
159
+ log('❌ Failed to save tree state', { namespace, error });
151
160
  console.warn('Failed to save tree state to localStorage:', error);
152
161
  }
153
162
  }
@@ -166,14 +175,23 @@ export function loadStateFromStorage(namespace, state) {
166
175
  updates.checkedPaths = new Set(checkedArray);
167
176
  // Recalculate indeterminate states
168
177
  updates.indeterminatePaths = calculateIndeterminateStates(state.nodes, updates.checkedPaths);
178
+ log('📂 Loaded checked paths from localStorage', {
179
+ namespace,
180
+ checkedCount: checkedArray.length
181
+ });
169
182
  }
170
183
  if (expandedJson) {
171
184
  const expandedArray = JSON.parse(expandedJson);
172
185
  updates.expandedPaths = new Set(expandedArray);
186
+ log('📂 Loaded expanded paths from localStorage', {
187
+ namespace,
188
+ expandedCount: expandedArray.length
189
+ });
173
190
  }
174
191
  return updates;
175
192
  }
176
193
  catch (error) {
194
+ log('❌ Failed to load tree state', { namespace, error });
177
195
  console.warn('Failed to load tree state from localStorage:', error);
178
196
  return {};
179
197
  }
@@ -187,8 +205,10 @@ export function clearStorageForNamespace(namespace) {
187
205
  try {
188
206
  localStorage.removeItem(getStorageKey(namespace, 'checked'));
189
207
  localStorage.removeItem(getStorageKey(namespace, 'expanded'));
208
+ log('🗑️ Cleared tree state from localStorage', { namespace });
190
209
  }
191
210
  catch (error) {
211
+ log('❌ Failed to clear tree state', { namespace, error });
192
212
  console.warn('Failed to clear tree state from localStorage:', error);
193
213
  }
194
214
  }
@@ -4,19 +4,39 @@
4
4
  */
5
5
  import { writable } from 'svelte/store';
6
6
  import { flattenTree, buildInitialState, calculateIndeterminateStates, getDescendantPaths, getParentPath, saveStateToStorage, loadStateFromStorage, clearStorageForNamespace } from './tree-utils';
7
+ import { log } from '../logger';
7
8
  /**
8
9
  * Create a tree store with state management and persistence
9
10
  */
10
11
  export function createTreeStore(config) {
12
+ log('🌲 Creating TreeStore', {
13
+ namespace: config.namespace,
14
+ nodeCount: config.nodes.length,
15
+ persistState: config.persistState,
16
+ defaultExpandAll: config.defaultExpandAll
17
+ });
11
18
  const separator = config.pathSeparator || ':';
12
19
  // Flatten tree structure
13
20
  const nodesMap = flattenTree(config.nodes, config);
21
+ log('📊 Tree flattened', {
22
+ totalNodes: nodesMap.size,
23
+ separator
24
+ });
14
25
  // Build initial state
15
26
  let state = buildInitialState(nodesMap, config);
27
+ log('🔧 Initial state built', {
28
+ checkedPaths: state.checkedPaths.size,
29
+ expandedPaths: state.expandedPaths.size
30
+ });
16
31
  // Load persisted state if enabled
17
32
  if (config.persistState && config.namespace) {
18
33
  const persistedState = loadStateFromStorage(config.namespace, state);
19
34
  state = { ...state, ...persistedState };
35
+ log('💾 Loaded persisted state', {
36
+ namespace: config.namespace,
37
+ checkedPaths: state.checkedPaths.size,
38
+ expandedPaths: state.expandedPaths.size
39
+ });
20
40
  }
21
41
  // Create writable store
22
42
  const store = writable({
@@ -52,10 +72,13 @@ export function createTreeStore(config) {
52
72
  * Toggle a node's checked state (with cascading)
53
73
  */
54
74
  function toggle(path) {
75
+ log('🔄 Toggling node', { path });
55
76
  updateState(state => {
56
77
  const nodeState = state.nodes.get(path);
57
- if (!nodeState)
78
+ if (!nodeState) {
79
+ log('⚠️ Node not found', { path });
58
80
  return state;
81
+ }
59
82
  const newChecked = !state.checkedPaths.has(path);
60
83
  const newCheckedPaths = new Set(state.checkedPaths);
61
84
  // Update this node
@@ -67,6 +90,11 @@ export function createTreeStore(config) {
67
90
  }
68
91
  // Cascade to all descendants
69
92
  const descendants = getDescendantPaths(path, state.nodes, separator);
93
+ log('📦 Cascading to descendants', {
94
+ path,
95
+ descendantCount: descendants.length,
96
+ newChecked
97
+ });
70
98
  descendants.forEach(descendantPath => {
71
99
  if (newChecked) {
72
100
  newCheckedPaths.add(descendantPath);
@@ -99,6 +127,12 @@ export function createTreeStore(config) {
99
127
  }
100
128
  // Recalculate indeterminate states
101
129
  const newIndeterminatePaths = calculateIndeterminateStates(state.nodes, newCheckedPaths);
130
+ log('✅ Toggle complete', {
131
+ path,
132
+ newChecked,
133
+ totalChecked: newCheckedPaths.size,
134
+ indeterminate: newIndeterminatePaths.size
135
+ });
102
136
  return {
103
137
  ...state,
104
138
  checkedPaths: newCheckedPaths,
@@ -155,11 +189,13 @@ export function createTreeStore(config) {
155
189
  * Check all nodes
156
190
  */
157
191
  function checkAll() {
192
+ log('✅ Check all nodes');
158
193
  updateState(state => {
159
194
  const newCheckedPaths = new Set();
160
195
  state.nodes.forEach((_, path) => {
161
196
  newCheckedPaths.add(path);
162
197
  });
198
+ log('✅ All nodes checked', { totalChecked: newCheckedPaths.size });
163
199
  return {
164
200
  ...state,
165
201
  checkedPaths: newCheckedPaths,
@@ -171,6 +207,7 @@ export function createTreeStore(config) {
171
207
  * Uncheck all nodes
172
208
  */
173
209
  function uncheckAll() {
210
+ log('❌ Uncheck all nodes');
174
211
  updateState(state => ({
175
212
  ...state,
176
213
  checkedPaths: new Set(),
@@ -1,3 +1,4 @@
1
1
  export * from './Desktop/index.js';
2
2
  export * from './Charts/index.js';
3
3
  export * from './TreeView/index.js';
4
+ export * from './logger/index.js';
@@ -6,3 +6,5 @@ export * from './Desktop/index.js';
6
6
  export * from './Charts/index.js';
7
7
  // TreeView generic hierarchical component
8
8
  export * from './TreeView/index.js';
9
+ // Logger utility for debugging and monitoring
10
+ export * from './logger/index.js';
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Simple debug logger utility
3
+ *
4
+ * @example
5
+ * ```typescript
6
+ * import { log } from './';
7
+ *
8
+ * log('User clicked button', { userId: 123 });
9
+ * log('Data loaded', data);
10
+ *
11
+ * // Disable logging globally
12
+ * log.disable();
13
+ *
14
+ * // Enable logging globally
15
+ * log.enable();
16
+ * ```
17
+ */
18
+ /**
19
+ * Simple log function - logs to console when enabled
20
+ */
21
+ export declare function log(message: string, ...args: any[]): void;
22
+ export declare namespace log {
23
+ var disable: () => void;
24
+ var enable: () => void;
25
+ var isEnabled: () => boolean;
26
+ }
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Simple debug logger utility
3
+ *
4
+ * @example
5
+ * ```typescript
6
+ * import { log } from './';
7
+ *
8
+ * log('User clicked button', { userId: 123 });
9
+ * log('Data loaded', data);
10
+ *
11
+ * // Disable logging globally
12
+ * log.disable();
13
+ *
14
+ * // Enable logging globally
15
+ * log.enable();
16
+ * ```
17
+ */
18
+ let enabled = true;
19
+ /**
20
+ * Simple log function - logs to console when enabled
21
+ */
22
+ export function log(message, ...args) {
23
+ if (enabled) {
24
+ console.log(`[DEBUG]`, message, ...args);
25
+ }
26
+ }
27
+ /**
28
+ * Disable logging globally
29
+ */
30
+ log.disable = () => {
31
+ enabled = false;
32
+ };
33
+ /**
34
+ * Enable logging globally
35
+ */
36
+ log.enable = () => {
37
+ enabled = true;
38
+ };
39
+ /**
40
+ * Check if logging is enabled
41
+ */
42
+ log.isEnabled = () => enabled;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smartnet360/svelte-components",
3
- "version": "0.0.35",
3
+ "version": "0.0.37",
4
4
  "scripts": {
5
5
  "dev": "vite dev",
6
6
  "build": "vite build && npm run prepack",