snow-flow 3.4.36 → 3.5.0

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 (72) hide show
  1. package/README.md +414 -287
  2. package/dist/cli/deploy-artifact.js +2 -2
  3. package/dist/index.d.ts +4 -0
  4. package/dist/index.js +10 -2
  5. package/dist/mcp/enhancements/smart-query-enhancement.d.ts +49 -0
  6. package/dist/mcp/enhancements/smart-query-enhancement.js +233 -0
  7. package/dist/mcp/servicenow-deployment-mcp.js +1 -1
  8. package/dist/mcp/servicenow-local-development-mcp.d.ts +48 -0
  9. package/dist/mcp/servicenow-local-development-mcp.js +570 -0
  10. package/dist/mcp/servicenow-mcp-server.js +2 -2
  11. package/dist/queen/agent-factory.js +134 -52
  12. package/dist/queen/queen-knowledge-base.d.ts +151 -0
  13. package/dist/queen/queen-knowledge-base.js +283 -0
  14. package/dist/queen/servicenow-queen.d.ts +129 -2
  15. package/dist/queen/servicenow-queen.js +1069 -618
  16. package/dist/services/widget-deployment-service.d.ts +1 -1
  17. package/dist/services/widget-deployment-service.js +1 -1
  18. package/dist/templates/claude-md-template.d.ts +1 -1
  19. package/dist/templates/claude-md-template.js +2 -2
  20. package/dist/types/servicenow.types.d.ts +1 -1
  21. package/dist/utils/artifact-local-sync.d.ts +115 -0
  22. package/dist/utils/artifact-local-sync.js +705 -0
  23. package/dist/utils/artifact-sync/artifact-registry.d.ts +66 -0
  24. package/dist/utils/artifact-sync/artifact-registry.js +450 -0
  25. package/dist/utils/artifact-sync/index.d.ts +33 -0
  26. package/dist/utils/artifact-sync/index.js +52 -0
  27. package/dist/utils/dependency-detector.d.ts +1 -1
  28. package/dist/utils/dependency-detector.js +1 -1
  29. package/dist/utils/mcp-tool-registry.js +109 -0
  30. package/dist/utils/servicenow-client.d.ts +1 -1
  31. package/dist/utils/servicenow-client.js +4 -8
  32. package/dist/utils/smart-field-fetcher.d.ts +68 -0
  33. package/dist/utils/smart-field-fetcher.js +395 -0
  34. package/package.json +2 -2
  35. package/website/.dockerignore +64 -0
  36. package/website/Dockerfile +36 -0
  37. package/website/README.md +40 -1
  38. package/website/cloudbuild.yaml +69 -0
  39. package/website/components/README.md +419 -0
  40. package/website/components/code-display/CodeDisplay.css +583 -0
  41. package/website/components/code-display/CodeDisplay.html +200 -0
  42. package/website/components/code-display/CodeDisplay.js +375 -0
  43. package/website/components/code-display/CodeDisplay.jsx +268 -0
  44. package/website/components/demo/ComponentLibraryDemo.html +845 -0
  45. package/website/components/feature-cards/FeatureCards.css +573 -0
  46. package/website/components/feature-cards/FeatureCards.html +247 -0
  47. package/website/components/feature-cards/FeatureCards.js +382 -0
  48. package/website/components/feature-cards/FeatureCards.jsx +235 -0
  49. package/website/components/hero/Hero.css +558 -0
  50. package/website/components/hero/Hero.html +98 -0
  51. package/website/components/hero/Hero.js +415 -0
  52. package/website/components/hero/Hero.jsx +214 -0
  53. package/website/components/interactive/InteractiveElements.css +776 -0
  54. package/website/components/interactive/InteractiveElements.html +283 -0
  55. package/website/components/interactive/InteractiveElements.js +489 -0
  56. package/website/components/interactive/InteractiveElements.jsx +444 -0
  57. package/website/components/layout/LayoutComponents.css +697 -0
  58. package/website/components/layout/LayoutComponents.html +374 -0
  59. package/website/components/layout/LayoutComponents.js +447 -0
  60. package/website/components/layout/LayoutComponents.jsx +379 -0
  61. package/website/components/navigation/Navigation.css +383 -0
  62. package/website/components/navigation/Navigation.html +89 -0
  63. package/website/components/navigation/Navigation.js +248 -0
  64. package/website/components/navigation/Navigation.jsx +124 -0
  65. package/website/css/animations.css +854 -0
  66. package/website/css/style.css +1010 -924
  67. package/website/index.html +728 -412
  68. package/website/js/animations.js +707 -0
  69. package/website/js/main.js +333 -381
  70. package/website/mcp-servers.html +310 -0
  71. package/website/nginx.conf +116 -0
  72. package/website/service.yaml +61 -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,307 @@ 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. DOCUMENTATION 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';
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
+ }
247
+
248
+ // Smooth scroll to docs section if not visible
249
+ const docsSection = document.getElementById('docs');
250
+ if (docsSection) {
251
+ const rect = docsSection.getBoundingClientRect();
252
+ if (rect.top < 0 || rect.bottom > window.innerHeight) {
253
+ docsSection.scrollIntoView({
254
+ behavior: 'smooth',
255
+ block: 'start'
256
+ });
298
257
  }
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';
258
+ }
310
259
  });
311
- }
312
-
313
- // Add Loading Animation
314
- window.addEventListener('load', function() {
315
- document.body.classList.add('loaded');
316
260
  });
317
261
 
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 = '';
262
+ // Initialize first tab as active
263
+ if (tabBtns.length > 0 && tabContents.length > 0) {
264
+ const firstTab = tabBtns[0];
265
+ const firstContent = document.getElementById(firstTab.getAttribute('data-tab'));
324
266
 
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);
267
+ if (!firstTab.classList.contains('active')) {
268
+ firstTab.classList.add('active');
269
+ }
270
+ if (firstContent && !firstContent.classList.contains('active')) {
271
+ firstContent.classList.add('active');
272
+ }
273
+ }
274
+
275
+ /* =========================================
276
+ 9. SEARCH FUNCTIONALITY
277
+ ========================================= */
278
+ const searchInput = document.querySelector('.search-input');
279
+ const searchResults = document.querySelector('.search-results');
280
+
281
+ if (searchInput) {
282
+ searchInput.addEventListener('input', function() {
283
+ const query = this.value.toLowerCase();
331
284
 
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>
285
+ if (query.length > 2) {
286
+ // Simulate search results
287
+ searchResults.classList.add('active');
288
+ searchResults.innerHTML = `
289
+ <div class="search-result">
290
+ <span class="search-result-title">Getting Started with Snow-Flow</span>
291
+ <span class="search-result-description">Learn how to install and configure Snow-Flow</span>
337
292
  </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('')}
293
+ <div class="search-result">
294
+ <span class="search-result-title">MCP Server Integration</span>
295
+ <span class="search-result-description">Complete guide to MCP server setup</span>
355
296
  </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
- });
297
+ `;
298
+ } else {
299
+ searchResults.classList.remove('active');
300
+ }
394
301
  });
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);
302
+
303
+ // Close search results when clicking outside
304
+ document.addEventListener('click', function(e) {
305
+ if (!searchInput.contains(e.target) && !searchResults.contains(e.target)) {
306
+ searchResults.classList.remove('active');
307
+ }
403
308
  });
404
309
  }
405
310
 
406
- // MCP Filter Functionality
407
- function setupMCPFilter() {
408
- const filterButtons = document.querySelectorAll('.filter-btn');
311
+ /* =========================================
312
+ 10. LOADING ANIMATIONS
313
+ ========================================= */
314
+ // Simulate loading for demo
315
+ const loadingElements = document.querySelectorAll('[data-loading]');
316
+ loadingElements.forEach(el => {
317
+ setTimeout(() => {
318
+ el.classList.remove('skeleton');
319
+ el.classList.add('animate-fade-in-up');
320
+ }, Math.random() * 2000 + 500);
321
+ });
322
+
323
+ /* =========================================
324
+ 11. PARTICLE BACKGROUND (SUBTLE)
325
+ ========================================= */
326
+ function createParticle() {
327
+ const particle = document.createElement('div');
328
+ particle.classList.add('particle');
329
+ particle.style.left = Math.random() * 100 + '%';
330
+ particle.style.animationDuration = Math.random() * 20 + 10 + 's';
331
+ particle.style.opacity = Math.random() * 0.5;
332
+ particle.style.animationDelay = Math.random() * 5 + 's';
409
333
 
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
- });
334
+ document.querySelector('.hero')?.appendChild(particle);
335
+
336
+ setTimeout(() => {
337
+ particle.remove();
338
+ }, 30000);
437
339
  }
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
- });
340
+
341
+ // Create particles periodically
342
+ if (document.querySelector('.hero')) {
343
+ setInterval(createParticle, 3000);
344
+
345
+ // Create initial particles
346
+ for (let i = 0; i < 5; i++) {
347
+ setTimeout(createParticle, i * 500);
456
348
  }
457
349
  }
458
350
 
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);
351
+ /* =========================================
352
+ 12. CONSOLE EASTER EGG
353
+ ========================================= */
354
+ 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;');
355
+ console.log('%cWelcome to Snow-Flow - The ServiceNow Development Revolution', 'font-size: 14px; color: #666;');
356
+ console.log('%c17 MCP Servers | 200+ Tools | Unlimited Possibilities', 'font-size: 12px; color: #999;');
357
+ console.log('%cJoin us: https://github.com/groeimetai/snow-flow', 'font-size: 12px; color: #666; text-decoration: underline;');
358
+
359
+ /* =========================================
360
+ 13. PERFORMANCE OPTIMIZATION
361
+ ========================================= */
362
+ // Throttle scroll events
363
+ let scrollTimeout;
364
+ window.addEventListener('scroll', function() {
365
+ if (scrollTimeout) {
366
+ window.cancelAnimationFrame(scrollTimeout);
468
367
  }
469
- }
470
-
471
- // Initialize MCP functionality
472
- initializeMCP();
368
+ scrollTimeout = window.requestAnimationFrame(function() {
369
+ // Handle scroll events
370
+ });
371
+ }, { passive: true });
372
+
373
+ /* =========================================
374
+ 14. ACCESSIBILITY ENHANCEMENTS
375
+ ========================================= */
376
+ // Add keyboard navigation for interactive elements
377
+ const interactiveElements = document.querySelectorAll('.btn, .card, .tab-btn, .navbar-link');
378
+ interactiveElements.forEach(el => {
379
+ el.setAttribute('tabindex', '0');
380
+ el.addEventListener('keypress', function(e) {
381
+ if (e.key === 'Enter' || e.key === ' ') {
382
+ e.preventDefault();
383
+ this.click();
384
+ }
385
+ });
386
+ });
473
387
 
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
- });
388
+ // Skip to content link
389
+ const skipLink = document.createElement('a');
390
+ skipLink.href = '#main-content';
391
+ skipLink.className = 'skip-to-content';
392
+ skipLink.textContent = 'Skip to content';
393
+ document.body.insertBefore(skipLink, document.body.firstChild);
394
+
395
+ /* =========================================
396
+ 15. INITIALIZATION COMPLETE
397
+ ========================================= */
398
+ document.body.classList.add('loaded');
399
+ console.log('✨ Snow-Flow initialized successfully');
400
+ });
401
+
402
+ /* =========================================
403
+ 16. UTILITY FUNCTIONS
404
+ ========================================= */
405
+ // Debounce function for performance
406
+ function debounce(func, wait) {
407
+ let timeout;
408
+ return function executedFunction(...args) {
409
+ const later = () => {
410
+ clearTimeout(timeout);
411
+ func(...args);
412
+ };
413
+ clearTimeout(timeout);
414
+ timeout = setTimeout(later, wait);
415
+ };
416
+ }
417
+
418
+ // Check if element is in viewport
419
+ function isInViewport(element) {
420
+ const rect = element.getBoundingClientRect();
421
+ return (
422
+ rect.top >= 0 &&
423
+ rect.left >= 0 &&
424
+ rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
425
+ rect.right <= (window.innerWidth || document.documentElement.clientWidth)
426
+ );
427
+ }
428
+
429
+ /* =========================================
430
+ END OF SNOW-FLOW JAVASCRIPT
431
+ ========================================= */