snow-flow 3.4.35 → 3.4.39

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 (50) hide show
  1. package/README.md +412 -287
  2. package/dist/cli/deploy-artifact.js +2 -2
  3. package/dist/mcp/servicenow-deployment-mcp.js +1 -1
  4. package/dist/mcp/servicenow-mcp-server.js +2 -2
  5. package/dist/mcp/shared/mcp-logger.js +6 -12
  6. package/dist/queen/agent-factory.js +134 -52
  7. package/dist/queen/servicenow-queen.d.ts +127 -2
  8. package/dist/queen/servicenow-queen.js +978 -618
  9. package/dist/services/widget-deployment-service.d.ts +1 -1
  10. package/dist/services/widget-deployment-service.js +1 -1
  11. package/dist/templates/claude-md-template.d.ts +1 -1
  12. package/dist/templates/claude-md-template.js +2 -2
  13. package/dist/types/servicenow.types.d.ts +1 -1
  14. package/dist/utils/dependency-detector.d.ts +1 -1
  15. package/dist/utils/dependency-detector.js +1 -1
  16. package/dist/utils/servicenow-client.d.ts +1 -1
  17. package/dist/utils/servicenow-client.js +4 -8
  18. package/package.json +1 -1
  19. package/website/components/README.md +419 -0
  20. package/website/components/code-display/CodeDisplay.css +583 -0
  21. package/website/components/code-display/CodeDisplay.html +200 -0
  22. package/website/components/code-display/CodeDisplay.js +375 -0
  23. package/website/components/code-display/CodeDisplay.jsx +268 -0
  24. package/website/components/demo/ComponentLibraryDemo.html +845 -0
  25. package/website/components/feature-cards/FeatureCards.css +573 -0
  26. package/website/components/feature-cards/FeatureCards.html +247 -0
  27. package/website/components/feature-cards/FeatureCards.js +382 -0
  28. package/website/components/feature-cards/FeatureCards.jsx +235 -0
  29. package/website/components/hero/Hero.css +558 -0
  30. package/website/components/hero/Hero.html +98 -0
  31. package/website/components/hero/Hero.js +415 -0
  32. package/website/components/hero/Hero.jsx +214 -0
  33. package/website/components/interactive/InteractiveElements.css +776 -0
  34. package/website/components/interactive/InteractiveElements.html +283 -0
  35. package/website/components/interactive/InteractiveElements.js +489 -0
  36. package/website/components/interactive/InteractiveElements.jsx +444 -0
  37. package/website/components/layout/LayoutComponents.css +697 -0
  38. package/website/components/layout/LayoutComponents.html +374 -0
  39. package/website/components/layout/LayoutComponents.js +447 -0
  40. package/website/components/layout/LayoutComponents.jsx +379 -0
  41. package/website/components/navigation/Navigation.css +383 -0
  42. package/website/components/navigation/Navigation.html +89 -0
  43. package/website/components/navigation/Navigation.js +248 -0
  44. package/website/components/navigation/Navigation.jsx +124 -0
  45. package/website/css/animations.css +854 -0
  46. package/website/css/style.css +916 -948
  47. package/website/index.html +394 -424
  48. package/website/js/animations.js +707 -0
  49. package/website/js/main.js +310 -383
  50. package/website/mcp-servers.html +310 -0
@@ -1,15 +1,27 @@
1
- // Snow-Flow Website JavaScript
1
+ /* =========================================
2
+ SNOW-FLOW MODERN BLACK/WHITE JAVASCRIPT
3
+ =========================================
4
+ Version: 3.0.0
5
+ Theme: Minimalist Black/White with Animations
6
+ ========================================= */
2
7
 
3
8
  document.addEventListener('DOMContentLoaded', function() {
4
- // Mobile Navigation Toggle
9
+
10
+ /* =========================================
11
+ 1. GLASS MORPHISM NAVBAR
12
+ ========================================= */
13
+ const navbar = document.querySelector('.navbar');
5
14
  const hamburger = document.querySelector('.hamburger');
6
- const navMenu = document.querySelector('.nav-menu');
15
+ const navMenu = document.querySelector('.navbar-menu');
16
+ let lastScroll = 0;
7
17
 
18
+ // Mobile Navigation Toggle
8
19
  if (hamburger) {
9
20
  hamburger.addEventListener('click', function() {
10
21
  navMenu.classList.toggle('active');
22
+ hamburger.classList.toggle('active');
11
23
 
12
- // Animate hamburger
24
+ // Animate hamburger lines
13
25
  const spans = hamburger.querySelectorAll('span');
14
26
  if (navMenu.classList.contains('active')) {
15
27
  spans[0].style.transform = 'rotate(45deg) translate(5px, 5px)';
@@ -23,12 +35,34 @@ document.addEventListener('DOMContentLoaded', function() {
23
35
  });
24
36
  }
25
37
 
26
- // Smooth Scrolling for Navigation Links
27
- const navLinks = document.querySelectorAll('.nav-link');
38
+ // Glass Morphism on Scroll
39
+ window.addEventListener('scroll', function() {
40
+ const currentScroll = window.pageYOffset;
41
+
42
+ if (currentScroll > 50) {
43
+ navbar.classList.add('scrolled');
44
+ } else {
45
+ navbar.classList.remove('scrolled');
46
+ }
47
+
48
+ // Hide/Show navbar on scroll
49
+ if (currentScroll > lastScroll && currentScroll > 500) {
50
+ navbar.style.transform = 'translateY(-100%)';
51
+ } else {
52
+ navbar.style.transform = 'translateY(0)';
53
+ }
54
+
55
+ lastScroll = currentScroll;
56
+ });
57
+
58
+ /* =========================================
59
+ 2. SMOOTH SCROLLING
60
+ ========================================= */
61
+ const navLinks = document.querySelectorAll('.navbar-link, .nav-link');
28
62
  navLinks.forEach(link => {
29
63
  link.addEventListener('click', function(e) {
30
64
  const href = this.getAttribute('href');
31
- if (href.startsWith('#')) {
65
+ if (href && href.startsWith('#')) {
32
66
  e.preventDefault();
33
67
  const target = document.querySelector(href);
34
68
  if (target) {
@@ -41,60 +75,48 @@ document.addEventListener('DOMContentLoaded', function() {
41
75
 
42
76
  // Close mobile menu if open
43
77
  navMenu.classList.remove('active');
78
+ hamburger?.classList.remove('active');
44
79
  }
45
80
  }
46
81
  });
47
82
  });
48
83
 
49
- // Tab Functionality for Installation Section
50
- const tabBtns = document.querySelectorAll('.tab-btn');
51
- const tabContents = document.querySelectorAll('.tab-content');
52
-
53
- tabBtns.forEach(btn => {
54
- btn.addEventListener('click', function() {
55
- const tabName = this.getAttribute('data-tab');
56
-
57
- // Remove active class from all tabs and contents
58
- tabBtns.forEach(b => b.classList.remove('active'));
59
- tabContents.forEach(c => c.classList.remove('active'));
60
-
61
- // Add active class to clicked tab and corresponding content
62
- this.classList.add('active');
63
- const activeContent = document.getElementById(tabName);
64
- if (activeContent) {
65
- activeContent.classList.add('active');
66
- }
84
+ /* =========================================
85
+ 3. HERO SECTION ANIMATIONS
86
+ ========================================= */
87
+ const hero = document.querySelector('.hero');
88
+ const heroTitle = document.querySelector('.hero-title');
89
+ const heroSubtitle = document.querySelector('.hero-subtitle');
90
+
91
+ // Parallax effect on scroll
92
+ if (hero) {
93
+ window.addEventListener('scroll', function() {
94
+ const scrolled = window.pageYOffset;
95
+ const parallaxSpeed = 0.5;
96
+ hero.style.transform = `translateY(${scrolled * parallaxSpeed}px)`;
67
97
  });
68
- });
69
-
70
- // Navbar Background on Scroll
71
- const navbar = document.querySelector('.navbar');
72
- let lastScroll = 0;
98
+ }
73
99
 
74
- window.addEventListener('scroll', function() {
75
- const currentScroll = window.pageYOffset;
100
+ // Typewriter effect for hero subtitle
101
+ if (heroSubtitle) {
102
+ const text = heroSubtitle.textContent;
103
+ heroSubtitle.textContent = '';
104
+ let i = 0;
76
105
 
77
- if (currentScroll > 100) {
78
- navbar.style.background = 'rgba(255, 255, 255, 0.98)';
79
- navbar.style.backdropFilter = 'blur(10px)';
80
- navbar.style.boxShadow = '0 4px 20px rgba(0,0,0,0.1)';
81
- } else {
82
- navbar.style.background = 'white';
83
- navbar.style.backdropFilter = 'none';
84
- navbar.style.boxShadow = '0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24)';
85
- }
86
-
87
- // Hide/Show navbar on scroll
88
- if (currentScroll > lastScroll && currentScroll > 500) {
89
- navbar.style.transform = 'translateY(-100%)';
90
- } else {
91
- navbar.style.transform = 'translateY(0)';
106
+ function typeWriter() {
107
+ if (i < text.length) {
108
+ heroSubtitle.textContent += text.charAt(i);
109
+ i++;
110
+ setTimeout(typeWriter, 50);
111
+ }
92
112
  }
93
113
 
94
- lastScroll = currentScroll;
95
- });
114
+ setTimeout(typeWriter, 1000);
115
+ }
96
116
 
97
- // Animate Elements on Scroll
117
+ /* =========================================
118
+ 4. INTERSECTION OBSERVER ANIMATIONS
119
+ ========================================= */
98
120
  const observerOptions = {
99
121
  threshold: 0.1,
100
122
  rootMargin: '0px 0px -100px 0px'
@@ -103,377 +125,282 @@ document.addEventListener('DOMContentLoaded', function() {
103
125
  const observer = new IntersectionObserver(function(entries) {
104
126
  entries.forEach(entry => {
105
127
  if (entry.isIntersecting) {
106
- entry.target.style.opacity = '1';
107
- entry.target.style.transform = 'translateY(0)';
128
+ entry.target.classList.add('visible');
108
129
 
109
- // Add stagger effect for grid items
110
- if (entry.target.classList.contains('feature') ||
111
- entry.target.classList.contains('mcp-card') ||
112
- entry.target.classList.contains('what-is-card')) {
113
- const siblings = entry.target.parentElement.children;
114
- Array.from(siblings).forEach((sibling, index) => {
115
- setTimeout(() => {
116
- sibling.style.opacity = '1';
117
- sibling.style.transform = 'translateY(0)';
118
- }, index * 100);
119
- });
120
- }
130
+ // Add stagger effect for children
131
+ const children = entry.target.querySelectorAll('.stagger-item');
132
+ children.forEach((child, index) => {
133
+ setTimeout(() => {
134
+ child.classList.add('visible');
135
+ }, index * 100);
136
+ });
121
137
  }
122
138
  });
123
139
  }, observerOptions);
124
140
 
125
- // Observe elements for animation
126
- const animateElements = document.querySelectorAll('.feature, .mcp-card, .what-is-card, .workflow-step, .example-card, .practice');
127
- animateElements.forEach(el => {
128
- el.style.opacity = '0';
129
- el.style.transform = 'translateY(20px)';
130
- el.style.transition = 'opacity 0.6s ease, transform 0.6s ease';
141
+ // Observe all animated elements
142
+ const animatedElements = document.querySelectorAll('.animate-fade-in-up, .animate-fade-in-down, .animate-scale-in, .animate-slide-in-left, .animate-slide-in-right, .card, .feature, .section');
143
+ animatedElements.forEach(el => {
131
144
  observer.observe(el);
132
145
  });
133
146
 
134
- // Copy Code Functionality
135
- const codeBlocks = document.querySelectorAll('pre code');
136
- codeBlocks.forEach(block => {
137
- const wrapper = block.parentElement;
138
-
139
- // Create copy button
140
- const copyBtn = document.createElement('button');
141
- copyBtn.className = 'copy-btn';
142
- copyBtn.textContent = 'Copy';
143
- copyBtn.style.cssText = `
144
- position: absolute;
145
- top: 10px;
146
- right: 10px;
147
- background: rgba(255,255,255,0.1);
148
- color: white;
149
- border: 1px solid rgba(255,255,255,0.2);
150
- padding: 5px 15px;
151
- border-radius: 5px;
152
- cursor: pointer;
153
- font-size: 0.9rem;
154
- transition: all 0.3s ease;
155
- `;
156
-
157
- wrapper.style.position = 'relative';
158
- wrapper.appendChild(copyBtn);
159
-
160
- copyBtn.addEventListener('click', function() {
161
- const text = block.textContent;
162
- navigator.clipboard.writeText(text).then(() => {
163
- copyBtn.textContent = 'Copied!';
164
- copyBtn.style.background = '#48bb78';
165
- copyBtn.style.borderColor = '#48bb78';
147
+ /* =========================================
148
+ 5. CARD HOVER EFFECTS
149
+ ========================================= */
150
+ const cards = document.querySelectorAll('.card');
151
+ cards.forEach(card => {
152
+ card.addEventListener('mouseenter', function(e) {
153
+ const rect = this.getBoundingClientRect();
154
+ const x = e.clientX - rect.left;
155
+ const y = e.clientY - rect.top;
156
+
157
+ this.style.setProperty('--mouse-x', `${x}px`);
158
+ this.style.setProperty('--mouse-y', `${y}px`);
159
+ });
160
+ });
161
+
162
+ /* =========================================
163
+ 6. BUTTON CLICK HANDLERS & SMOOTH SCROLL
164
+ ========================================= */
165
+ const buttons = document.querySelectorAll('.btn');
166
+ buttons.forEach(btn => {
167
+ // Only add click handler for buttons with href starting with #
168
+ const href = btn.getAttribute('href');
169
+ if (href && href.startsWith('#')) {
170
+ btn.addEventListener('click', function(e) {
171
+ e.preventDefault();
172
+
173
+ const targetId = href.substring(1);
174
+ const targetElement = document.getElementById(targetId);
175
+
176
+ if (targetElement) {
177
+ const offset = 80; // Navbar height
178
+ const targetPosition = targetElement.offsetTop - offset;
179
+
180
+ window.scrollTo({
181
+ top: targetPosition,
182
+ behavior: 'smooth'
183
+ });
184
+ }
166
185
 
186
+ // Add subtle click feedback
187
+ this.style.transform = 'scale(0.98)';
167
188
  setTimeout(() => {
168
- copyBtn.textContent = 'Copy';
169
- copyBtn.style.background = 'rgba(255,255,255,0.1)';
170
- copyBtn.style.borderColor = 'rgba(255,255,255,0.2)';
171
- }, 2000);
189
+ this.style.transform = '';
190
+ }, 150);
172
191
  });
173
- });
192
+ }
174
193
 
175
- // Show copy button on hover
176
- wrapper.addEventListener('mouseenter', () => {
177
- copyBtn.style.opacity = '1';
194
+ // Prevent the shimmer effect from getting too big
195
+ btn.addEventListener('mouseenter', function() {
196
+ this.style.transition = 'all 200ms ease';
178
197
  });
179
198
 
180
- wrapper.addEventListener('mouseleave', () => {
181
- if (copyBtn.textContent === 'Copy') {
182
- copyBtn.style.opacity = '0.7';
183
- }
199
+ btn.addEventListener('mouseleave', function() {
200
+ this.style.transition = '';
184
201
  });
185
202
  });
186
203
 
187
- // Active Section Highlighting in Navigation
188
- const sections = document.querySelectorAll('section[id]');
189
-
190
- function highlightNavigation() {
191
- const scrollPosition = window.scrollY + 100;
192
-
193
- sections.forEach(section => {
194
- const sectionTop = section.offsetTop;
195
- const sectionHeight = section.offsetHeight;
196
- const sectionId = section.getAttribute('id');
204
+ /* =========================================
205
+ 7. COPY TO CLIPBOARD
206
+ ========================================= */
207
+ const copyButtons = document.querySelectorAll('.copy-btn');
208
+ copyButtons.forEach(btn => {
209
+ btn.addEventListener('click', function() {
210
+ const codeBlock = this.parentElement.querySelector('code');
211
+ const text = codeBlock.textContent;
197
212
 
198
- if (scrollPosition >= sectionTop && scrollPosition < sectionTop + sectionHeight) {
199
- navLinks.forEach(link => {
200
- link.classList.remove('active');
201
- if (link.getAttribute('href') === `#${sectionId}`) {
202
- link.classList.add('active');
203
- }
204
- });
205
- }
206
- });
207
- }
208
-
209
- window.addEventListener('scroll', highlightNavigation);
210
-
211
- // Typing Effect for Hero Title
212
- const heroTitle = document.querySelector('.hero-title');
213
- if (heroTitle) {
214
- const text = heroTitle.textContent;
215
- heroTitle.textContent = '';
216
- let index = 0;
217
-
218
- function typeText() {
219
- if (index < text.length) {
220
- heroTitle.textContent += text.charAt(index);
221
- index++;
222
- setTimeout(typeText, 100);
223
- }
224
- }
225
-
226
- // Start typing after a short delay
227
- setTimeout(typeText, 500);
228
- }
229
-
230
- // Counter Animation for Stats
231
- const stats = document.querySelectorAll('.stat-number');
232
- const statsObserver = new IntersectionObserver(function(entries) {
233
- entries.forEach(entry => {
234
- if (entry.isIntersecting && !entry.target.classList.contains('counted')) {
235
- entry.target.classList.add('counted');
236
- const target = entry.target;
237
- const value = target.textContent;
238
-
239
- // Extract number from string (e.g., "16+" -> 16)
240
- const number = parseInt(value.replace(/\D/g, ''));
241
- const suffix = value.replace(/\d/g, '');
242
- const duration = 2000; // 2 seconds
243
- const increment = number / (duration / 16); // 60fps
244
- let current = 0;
213
+ navigator.clipboard.writeText(text).then(() => {
214
+ const originalText = this.textContent;
215
+ this.textContent = '✓ Copied!';
216
+ this.style.color = 'var(--white)';
245
217
 
246
- const counter = setInterval(() => {
247
- current += increment;
248
- if (current >= number) {
249
- target.textContent = number + suffix;
250
- clearInterval(counter);
251
- } else {
252
- target.textContent = Math.floor(current) + suffix;
253
- }
254
- }, 16);
255
- }
218
+ setTimeout(() => {
219
+ this.textContent = originalText;
220
+ this.style.color = '';
221
+ }, 2000);
222
+ });
256
223
  });
257
- }, { threshold: 0.5 });
258
-
259
- stats.forEach(stat => {
260
- statsObserver.observe(stat);
261
224
  });
262
225
 
263
- // Search Functionality for MCP Tools
264
- const searchInput = document.createElement('input');
265
- searchInput.type = 'text';
266
- searchInput.placeholder = 'Search MCP tools...';
267
- searchInput.className = 'mcp-search';
268
- searchInput.style.cssText = `
269
- width: 100%;
270
- max-width: 400px;
271
- margin: 0 auto 2rem;
272
- display: block;
273
- padding: 12px 20px;
274
- border: 2px solid #e2e8f0;
275
- border-radius: 25px;
276
- font-size: 1rem;
277
- transition: all 0.3s ease;
278
- `;
279
-
280
- const mcpSection = document.querySelector('#mcp-servers .container');
281
- if (mcpSection) {
282
- const subtitle = mcpSection.querySelector('.section-subtitle');
283
- if (subtitle) {
284
- subtitle.insertAdjacentElement('afterend', searchInput);
285
- }
226
+ /* =========================================
227
+ 8. TAB FUNCTIONALITY
228
+ ========================================= */
229
+ const tabBtns = document.querySelectorAll('.tab-btn');
230
+ const tabContents = document.querySelectorAll('.tab-content');
286
231
 
287
- searchInput.addEventListener('input', function(e) {
288
- const searchTerm = e.target.value.toLowerCase();
289
- const mcpCards = document.querySelectorAll('.mcp-card');
232
+ tabBtns.forEach(btn => {
233
+ btn.addEventListener('click', function() {
234
+ const tabName = this.getAttribute('data-tab');
290
235
 
291
- mcpCards.forEach(card => {
292
- const text = card.textContent.toLowerCase();
293
- if (text.includes(searchTerm)) {
294
- card.style.display = 'block';
295
- card.style.animation = 'fadeIn 0.3s ease';
296
- } else {
297
- card.style.display = 'none';
298
- }
299
- });
300
- });
301
-
302
- searchInput.addEventListener('focus', function() {
303
- this.style.borderColor = '#0066cc';
304
- this.style.boxShadow = '0 0 0 3px rgba(0,102,204,0.1)';
305
- });
306
-
307
- searchInput.addEventListener('blur', function() {
308
- this.style.borderColor = '#e2e8f0';
309
- this.style.boxShadow = 'none';
236
+ // Remove active class from all tabs and contents
237
+ tabBtns.forEach(b => b.classList.remove('active'));
238
+ tabContents.forEach(c => c.classList.remove('active'));
239
+
240
+ // Add active class to clicked tab and corresponding content
241
+ this.classList.add('active');
242
+ const activeContent = document.getElementById(tabName);
243
+ if (activeContent) {
244
+ activeContent.classList.add('active');
245
+ activeContent.classList.add('animate-fade-in-up');
246
+ }
310
247
  });
311
- }
312
-
313
- // Add Loading Animation
314
- window.addEventListener('load', function() {
315
- document.body.classList.add('loaded');
316
248
  });
317
249
 
318
- // Dynamic MCP Server Generation
319
- function generateMCPCards() {
320
- const mcpGrid = document.getElementById('mcp-grid');
321
- if (!mcpGrid || !window.snowFlowTools) return;
322
-
323
- mcpGrid.innerHTML = '';
324
-
325
- Object.keys(window.snowFlowTools).forEach(serverId => {
326
- const server = window.snowFlowTools[serverId];
327
-
328
- const mcpCard = document.createElement('div');
329
- mcpCard.className = 'mcp-card-dynamic';
330
- mcpCard.setAttribute('data-server', serverId);
250
+ /* =========================================
251
+ 9. SEARCH FUNCTIONALITY
252
+ ========================================= */
253
+ const searchInput = document.querySelector('.search-input');
254
+ const searchResults = document.querySelector('.search-results');
255
+
256
+ if (searchInput) {
257
+ searchInput.addEventListener('input', function() {
258
+ const query = this.value.toLowerCase();
331
259
 
332
- mcpCard.innerHTML = `
333
- <div class="mcp-card-header">
334
- <div class="mcp-title">
335
- <h3>${server.name}</h3>
336
- <span class="mcp-badge">${server.badge}</span>
260
+ if (query.length > 2) {
261
+ // Simulate search results
262
+ searchResults.classList.add('active');
263
+ searchResults.innerHTML = `
264
+ <div class="search-result">
265
+ <span class="search-result-title">Getting Started with Snow-Flow</span>
266
+ <span class="search-result-description">Learn how to install and configure Snow-Flow</span>
337
267
  </div>
338
- <button class="mcp-expand-btn" aria-label="Toggle tools">
339
- <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
340
- <polyline points="6,9 12,15 18,9"></polyline>
341
- </svg>
342
- </button>
343
- </div>
344
- <p class="mcp-description">${server.description}</p>
345
- <div class="mcp-tools-container" style="display: none;">
346
- <div class="mcp-tools-grid">
347
- ${server.tools.map(tool => `
348
- <div class="tool-item">
349
- <div class="tool-header">
350
- <code class="tool-name">${tool.name}</code>
351
- </div>
352
- <p class="tool-description">${tool.description}</p>
353
- </div>
354
- `).join('')}
268
+ <div class="search-result">
269
+ <span class="search-result-title">MCP Server Integration</span>
270
+ <span class="search-result-description">Complete guide to MCP server setup</span>
355
271
  </div>
356
- </div>
357
- `;
358
-
359
- mcpGrid.appendChild(mcpCard);
360
- });
361
-
362
- // Add click handlers for expand/collapse
363
- const expandButtons = document.querySelectorAll('.mcp-expand-btn');
364
- expandButtons.forEach(btn => {
365
- btn.addEventListener('click', function() {
366
- const card = this.closest('.mcp-card-dynamic');
367
- const toolsContainer = card.querySelector('.mcp-tools-container');
368
- const isExpanded = toolsContainer.style.display !== 'none';
369
-
370
- if (isExpanded) {
371
- toolsContainer.style.display = 'none';
372
- this.classList.remove('expanded');
373
- card.classList.remove('expanded');
374
- } else {
375
- toolsContainer.style.display = 'block';
376
- this.classList.add('expanded');
377
- card.classList.add('expanded');
378
-
379
- // Smooth animation
380
- toolsContainer.style.maxHeight = '0px';
381
- toolsContainer.style.overflow = 'hidden';
382
- toolsContainer.style.transition = 'max-height 0.4s ease-in-out';
383
-
384
- setTimeout(() => {
385
- toolsContainer.style.maxHeight = toolsContainer.scrollHeight + 'px';
386
- }, 10);
387
-
388
- setTimeout(() => {
389
- toolsContainer.style.maxHeight = 'none';
390
- toolsContainer.style.overflow = 'visible';
391
- }, 450);
392
- }
393
- });
272
+ `;
273
+ } else {
274
+ searchResults.classList.remove('active');
275
+ }
394
276
  });
395
-
396
- // Add observer for new cards
397
- const newCards = document.querySelectorAll('.mcp-card-dynamic');
398
- newCards.forEach(el => {
399
- el.style.opacity = '0';
400
- el.style.transform = 'translateY(20px)';
401
- el.style.transition = 'opacity 0.6s ease, transform 0.6s ease';
402
- observer.observe(el);
277
+
278
+ // Close search results when clicking outside
279
+ document.addEventListener('click', function(e) {
280
+ if (!searchInput.contains(e.target) && !searchResults.contains(e.target)) {
281
+ searchResults.classList.remove('active');
282
+ }
403
283
  });
404
284
  }
405
285
 
406
- // MCP Filter Functionality
407
- function setupMCPFilter() {
408
- const filterButtons = document.querySelectorAll('.filter-btn');
286
+ /* =========================================
287
+ 10. LOADING ANIMATIONS
288
+ ========================================= */
289
+ // Simulate loading for demo
290
+ const loadingElements = document.querySelectorAll('[data-loading]');
291
+ loadingElements.forEach(el => {
292
+ setTimeout(() => {
293
+ el.classList.remove('skeleton');
294
+ el.classList.add('animate-fade-in-up');
295
+ }, Math.random() * 2000 + 500);
296
+ });
297
+
298
+ /* =========================================
299
+ 11. PARTICLE BACKGROUND (SUBTLE)
300
+ ========================================= */
301
+ function createParticle() {
302
+ const particle = document.createElement('div');
303
+ particle.classList.add('particle');
304
+ particle.style.left = Math.random() * 100 + '%';
305
+ particle.style.animationDuration = Math.random() * 20 + 10 + 's';
306
+ particle.style.opacity = Math.random() * 0.5;
307
+ particle.style.animationDelay = Math.random() * 5 + 's';
409
308
 
410
- filterButtons.forEach(btn => {
411
- btn.addEventListener('click', function() {
412
- const filter = this.getAttribute('data-filter');
413
-
414
- // Update active button
415
- filterButtons.forEach(b => b.classList.remove('active'));
416
- this.classList.add('active');
417
-
418
- // Filter cards
419
- const cards = document.querySelectorAll('.mcp-card-dynamic');
420
- cards.forEach(card => {
421
- const serverId = card.getAttribute('data-server');
422
- const shouldShow = filter === 'all' ||
423
- (filter === 'deployment' && serverId.includes('deployment')) ||
424
- (filter === 'automation' && (serverId.includes('automation') || serverId.includes('flow'))) ||
425
- (filter === 'ml' && serverId.includes('machine-learning')) ||
426
- (filter === 'security' && serverId.includes('security'));
427
-
428
- if (shouldShow) {
429
- card.style.display = 'block';
430
- card.style.animation = 'fadeIn 0.3s ease';
431
- } else {
432
- card.style.display = 'none';
433
- }
434
- });
435
- });
436
- });
309
+ document.querySelector('.hero')?.appendChild(particle);
310
+
311
+ setTimeout(() => {
312
+ particle.remove();
313
+ }, 30000);
437
314
  }
438
-
439
- // Enhanced Search for Dynamic Cards
440
- function updateSearchForDynamicCards() {
441
- if (searchInput) {
442
- searchInput.addEventListener('input', function(e) {
443
- const searchTerm = e.target.value.toLowerCase();
444
- const mcpCards = document.querySelectorAll('.mcp-card-dynamic');
445
-
446
- mcpCards.forEach(card => {
447
- const text = card.textContent.toLowerCase();
448
- if (text.includes(searchTerm)) {
449
- card.style.display = 'block';
450
- card.style.animation = 'fadeIn 0.3s ease';
451
- } else {
452
- card.style.display = 'none';
453
- }
454
- });
455
- });
315
+
316
+ // Create particles periodically
317
+ if (document.querySelector('.hero')) {
318
+ setInterval(createParticle, 3000);
319
+
320
+ // Create initial particles
321
+ for (let i = 0; i < 5; i++) {
322
+ setTimeout(createParticle, i * 500);
456
323
  }
457
324
  }
458
325
 
459
- // Initialize MCP functionality when tools are loaded
460
- function initializeMCP() {
461
- if (window.snowFlowTools) {
462
- generateMCPCards();
463
- setupMCPFilter();
464
- updateSearchForDynamicCards();
465
- } else {
466
- // Retry after a short delay if tools aren't loaded yet
467
- setTimeout(initializeMCP, 100);
326
+ /* =========================================
327
+ 12. CONSOLE EASTER EGG
328
+ ========================================= */
329
+ console.log('%c🏔️ Snow-Flow', 'font-size: 50px; font-weight: bold; background: linear-gradient(135deg, #000 0%, #fff 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent;');
330
+ console.log('%cWelcome to Snow-Flow - The ServiceNow Development Revolution', 'font-size: 14px; color: #666;');
331
+ console.log('%c17 MCP Servers | 200+ Tools | Unlimited Possibilities', 'font-size: 12px; color: #999;');
332
+ console.log('%cJoin us: https://github.com/groeimetai/snow-flow', 'font-size: 12px; color: #666; text-decoration: underline;');
333
+
334
+ /* =========================================
335
+ 13. PERFORMANCE OPTIMIZATION
336
+ ========================================= */
337
+ // Throttle scroll events
338
+ let scrollTimeout;
339
+ window.addEventListener('scroll', function() {
340
+ if (scrollTimeout) {
341
+ window.cancelAnimationFrame(scrollTimeout);
468
342
  }
469
- }
470
-
471
- // Initialize MCP functionality
472
- initializeMCP();
343
+ scrollTimeout = window.requestAnimationFrame(function() {
344
+ // Handle scroll events
345
+ });
346
+ }, { passive: true });
347
+
348
+ /* =========================================
349
+ 14. ACCESSIBILITY ENHANCEMENTS
350
+ ========================================= */
351
+ // Add keyboard navigation for interactive elements
352
+ const interactiveElements = document.querySelectorAll('.btn, .card, .tab-btn, .navbar-link');
353
+ interactiveElements.forEach(el => {
354
+ el.setAttribute('tabindex', '0');
355
+ el.addEventListener('keypress', function(e) {
356
+ if (e.key === 'Enter' || e.key === ' ') {
357
+ e.preventDefault();
358
+ this.click();
359
+ }
360
+ });
361
+ });
473
362
 
474
- // Console Easter Egg
475
- console.log('%c🏔️ Snow-Flow', 'font-size: 30px; font-weight: bold; background: linear-gradient(135deg, #0066cc 0%, #00d4ff 100%); color: white; padding: 10px 20px; border-radius: 10px;');
476
- console.log('%cAdvanced ServiceNow Development Framework', 'font-size: 14px; color: #666;');
477
- console.log('%cVersion 3.4.16 | MIT License', 'font-size: 12px; color: #999;');
478
- console.log('%cInterested in contributing? Visit: https://github.com/groeimetai/snow-flow', 'font-size: 12px; color: #0066cc;');
479
- });
363
+ // Skip to content link
364
+ const skipLink = document.createElement('a');
365
+ skipLink.href = '#main-content';
366
+ skipLink.className = 'skip-to-content';
367
+ skipLink.textContent = 'Skip to content';
368
+ document.body.insertBefore(skipLink, document.body.firstChild);
369
+
370
+ /* =========================================
371
+ 15. INITIALIZATION COMPLETE
372
+ ========================================= */
373
+ document.body.classList.add('loaded');
374
+ console.log('✨ Snow-Flow initialized successfully');
375
+ });
376
+
377
+ /* =========================================
378
+ 16. UTILITY FUNCTIONS
379
+ ========================================= */
380
+ // Debounce function for performance
381
+ function debounce(func, wait) {
382
+ let timeout;
383
+ return function executedFunction(...args) {
384
+ const later = () => {
385
+ clearTimeout(timeout);
386
+ func(...args);
387
+ };
388
+ clearTimeout(timeout);
389
+ timeout = setTimeout(later, wait);
390
+ };
391
+ }
392
+
393
+ // Check if element is in viewport
394
+ function isInViewport(element) {
395
+ const rect = element.getBoundingClientRect();
396
+ return (
397
+ rect.top >= 0 &&
398
+ rect.left >= 0 &&
399
+ rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
400
+ rect.right <= (window.innerWidth || document.documentElement.clientWidth)
401
+ );
402
+ }
403
+
404
+ /* =========================================
405
+ END OF SNOW-FLOW JAVASCRIPT
406
+ ========================================= */