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.
- package/README.md +412 -287
- package/dist/cli/deploy-artifact.js +2 -2
- package/dist/mcp/servicenow-deployment-mcp.js +1 -1
- package/dist/mcp/servicenow-mcp-server.js +2 -2
- package/dist/mcp/shared/mcp-logger.js +6 -12
- package/dist/queen/agent-factory.js +134 -52
- package/dist/queen/servicenow-queen.d.ts +127 -2
- package/dist/queen/servicenow-queen.js +978 -618
- package/dist/services/widget-deployment-service.d.ts +1 -1
- package/dist/services/widget-deployment-service.js +1 -1
- package/dist/templates/claude-md-template.d.ts +1 -1
- package/dist/templates/claude-md-template.js +2 -2
- package/dist/types/servicenow.types.d.ts +1 -1
- package/dist/utils/dependency-detector.d.ts +1 -1
- package/dist/utils/dependency-detector.js +1 -1
- package/dist/utils/servicenow-client.d.ts +1 -1
- package/dist/utils/servicenow-client.js +4 -8
- package/package.json +1 -1
- package/website/components/README.md +419 -0
- package/website/components/code-display/CodeDisplay.css +583 -0
- package/website/components/code-display/CodeDisplay.html +200 -0
- package/website/components/code-display/CodeDisplay.js +375 -0
- package/website/components/code-display/CodeDisplay.jsx +268 -0
- package/website/components/demo/ComponentLibraryDemo.html +845 -0
- package/website/components/feature-cards/FeatureCards.css +573 -0
- package/website/components/feature-cards/FeatureCards.html +247 -0
- package/website/components/feature-cards/FeatureCards.js +382 -0
- package/website/components/feature-cards/FeatureCards.jsx +235 -0
- package/website/components/hero/Hero.css +558 -0
- package/website/components/hero/Hero.html +98 -0
- package/website/components/hero/Hero.js +415 -0
- package/website/components/hero/Hero.jsx +214 -0
- package/website/components/interactive/InteractiveElements.css +776 -0
- package/website/components/interactive/InteractiveElements.html +283 -0
- package/website/components/interactive/InteractiveElements.js +489 -0
- package/website/components/interactive/InteractiveElements.jsx +444 -0
- package/website/components/layout/LayoutComponents.css +697 -0
- package/website/components/layout/LayoutComponents.html +374 -0
- package/website/components/layout/LayoutComponents.js +447 -0
- package/website/components/layout/LayoutComponents.jsx +379 -0
- package/website/components/navigation/Navigation.css +383 -0
- package/website/components/navigation/Navigation.html +89 -0
- package/website/components/navigation/Navigation.js +248 -0
- package/website/components/navigation/Navigation.jsx +124 -0
- package/website/css/animations.css +854 -0
- package/website/css/style.css +916 -948
- package/website/index.html +394 -424
- package/website/js/animations.js +707 -0
- package/website/js/main.js +310 -383
- package/website/mcp-servers.html +310 -0
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
import React, { useState, useEffect, useRef } from 'react';
|
|
2
|
+
import './InteractiveElements.css';
|
|
3
|
+
|
|
4
|
+
// Button Component
|
|
5
|
+
const Button = ({
|
|
6
|
+
children,
|
|
7
|
+
variant = 'primary',
|
|
8
|
+
size = 'medium',
|
|
9
|
+
disabled = false,
|
|
10
|
+
loading = false,
|
|
11
|
+
onClick,
|
|
12
|
+
className = '',
|
|
13
|
+
...props
|
|
14
|
+
}) => {
|
|
15
|
+
const [ripples, setRipples] = useState([]);
|
|
16
|
+
|
|
17
|
+
const createRipple = (event) => {
|
|
18
|
+
const button = event.currentTarget;
|
|
19
|
+
const rect = button.getBoundingClientRect();
|
|
20
|
+
const size = Math.max(rect.width, rect.height);
|
|
21
|
+
const x = event.clientX - rect.left - size / 2;
|
|
22
|
+
const y = event.clientY - rect.top - size / 2;
|
|
23
|
+
|
|
24
|
+
const newRipple = {
|
|
25
|
+
x,
|
|
26
|
+
y,
|
|
27
|
+
size,
|
|
28
|
+
id: Date.now()
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
setRipples(prev => [...prev, newRipple]);
|
|
32
|
+
|
|
33
|
+
setTimeout(() => {
|
|
34
|
+
setRipples(prev => prev.filter(ripple => ripple.id !== newRipple.id));
|
|
35
|
+
}, 600);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const handleClick = (event) => {
|
|
39
|
+
if (!disabled && !loading) {
|
|
40
|
+
createRipple(event);
|
|
41
|
+
onClick?.(event);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<button
|
|
47
|
+
className={`sf-button sf-button--${variant} sf-button--${size} ${disabled ? 'sf-button--disabled' : ''} ${loading ? 'sf-button--loading' : ''} ${className}`}
|
|
48
|
+
disabled={disabled || loading}
|
|
49
|
+
onClick={handleClick}
|
|
50
|
+
{...props}
|
|
51
|
+
>
|
|
52
|
+
<span className="sf-button__content">
|
|
53
|
+
{loading && <span className="sf-button__spinner"></span>}
|
|
54
|
+
{children}
|
|
55
|
+
</span>
|
|
56
|
+
|
|
57
|
+
{ripples.map(ripple => (
|
|
58
|
+
<span
|
|
59
|
+
key={ripple.id}
|
|
60
|
+
className="sf-button__ripple"
|
|
61
|
+
style={{
|
|
62
|
+
left: ripple.x,
|
|
63
|
+
top: ripple.y,
|
|
64
|
+
width: ripple.size,
|
|
65
|
+
height: ripple.size
|
|
66
|
+
}}
|
|
67
|
+
/>
|
|
68
|
+
))}
|
|
69
|
+
</button>
|
|
70
|
+
);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
// Input Component
|
|
74
|
+
const Input = ({
|
|
75
|
+
label,
|
|
76
|
+
type = 'text',
|
|
77
|
+
value,
|
|
78
|
+
onChange,
|
|
79
|
+
placeholder,
|
|
80
|
+
error,
|
|
81
|
+
disabled = false,
|
|
82
|
+
required = false,
|
|
83
|
+
className = '',
|
|
84
|
+
...props
|
|
85
|
+
}) => {
|
|
86
|
+
const [focused, setFocused] = useState(false);
|
|
87
|
+
const inputRef = useRef(null);
|
|
88
|
+
|
|
89
|
+
return (
|
|
90
|
+
<div className={`sf-input ${focused ? 'sf-input--focused' : ''} ${error ? 'sf-input--error' : ''} ${disabled ? 'sf-input--disabled' : ''} ${className}`}>
|
|
91
|
+
{label && (
|
|
92
|
+
<label className="sf-input__label">
|
|
93
|
+
{label}
|
|
94
|
+
{required && <span className="sf-input__required">*</span>}
|
|
95
|
+
</label>
|
|
96
|
+
)}
|
|
97
|
+
|
|
98
|
+
<div className="sf-input__wrapper">
|
|
99
|
+
<input
|
|
100
|
+
ref={inputRef}
|
|
101
|
+
type={type}
|
|
102
|
+
value={value}
|
|
103
|
+
onChange={onChange}
|
|
104
|
+
placeholder={placeholder}
|
|
105
|
+
disabled={disabled}
|
|
106
|
+
required={required}
|
|
107
|
+
className="sf-input__field"
|
|
108
|
+
onFocus={() => setFocused(true)}
|
|
109
|
+
onBlur={() => setFocused(false)}
|
|
110
|
+
{...props}
|
|
111
|
+
/>
|
|
112
|
+
<div className="sf-input__border"></div>
|
|
113
|
+
</div>
|
|
114
|
+
|
|
115
|
+
{error && <span className="sf-input__error">{error}</span>}
|
|
116
|
+
</div>
|
|
117
|
+
);
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
// Toggle Switch Component
|
|
121
|
+
const Toggle = ({
|
|
122
|
+
checked = false,
|
|
123
|
+
onChange,
|
|
124
|
+
label,
|
|
125
|
+
disabled = false,
|
|
126
|
+
size = 'medium',
|
|
127
|
+
className = ''
|
|
128
|
+
}) => {
|
|
129
|
+
const handleChange = (event) => {
|
|
130
|
+
if (!disabled) {
|
|
131
|
+
onChange?.(event.target.checked);
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
return (
|
|
136
|
+
<label className={`sf-toggle sf-toggle--${size} ${disabled ? 'sf-toggle--disabled' : ''} ${className}`}>
|
|
137
|
+
<input
|
|
138
|
+
type="checkbox"
|
|
139
|
+
checked={checked}
|
|
140
|
+
onChange={handleChange}
|
|
141
|
+
disabled={disabled}
|
|
142
|
+
className="sf-toggle__input"
|
|
143
|
+
/>
|
|
144
|
+
<span className="sf-toggle__slider">
|
|
145
|
+
<span className="sf-toggle__thumb"></span>
|
|
146
|
+
</span>
|
|
147
|
+
{label && <span className="sf-toggle__label">{label}</span>}
|
|
148
|
+
</label>
|
|
149
|
+
);
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
// Progress Bar Component
|
|
153
|
+
const ProgressBar = ({
|
|
154
|
+
value = 0,
|
|
155
|
+
max = 100,
|
|
156
|
+
label,
|
|
157
|
+
showPercent = true,
|
|
158
|
+
animated = true,
|
|
159
|
+
size = 'medium',
|
|
160
|
+
className = ''
|
|
161
|
+
}) => {
|
|
162
|
+
const percentage = Math.min(100, Math.max(0, (value / max) * 100));
|
|
163
|
+
|
|
164
|
+
return (
|
|
165
|
+
<div className={`sf-progress sf-progress--${size} ${animated ? 'sf-progress--animated' : ''} ${className}`}>
|
|
166
|
+
{label && (
|
|
167
|
+
<div className="sf-progress__header">
|
|
168
|
+
<span className="sf-progress__label">{label}</span>
|
|
169
|
+
{showPercent && <span className="sf-progress__percent">{Math.round(percentage)}%</span>}
|
|
170
|
+
</div>
|
|
171
|
+
)}
|
|
172
|
+
|
|
173
|
+
<div className="sf-progress__track">
|
|
174
|
+
<div
|
|
175
|
+
className="sf-progress__fill"
|
|
176
|
+
style={{ width: `${percentage}%` }}
|
|
177
|
+
>
|
|
178
|
+
<div className="sf-progress__shimmer"></div>
|
|
179
|
+
</div>
|
|
180
|
+
</div>
|
|
181
|
+
</div>
|
|
182
|
+
);
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
// Tooltip Component
|
|
186
|
+
const Tooltip = ({
|
|
187
|
+
children,
|
|
188
|
+
content,
|
|
189
|
+
position = 'top',
|
|
190
|
+
trigger = 'hover',
|
|
191
|
+
disabled = false,
|
|
192
|
+
className = ''
|
|
193
|
+
}) => {
|
|
194
|
+
const [visible, setVisible] = useState(false);
|
|
195
|
+
const [coords, setCoords] = useState({ x: 0, y: 0 });
|
|
196
|
+
const triggerRef = useRef(null);
|
|
197
|
+
const tooltipRef = useRef(null);
|
|
198
|
+
|
|
199
|
+
const showTooltip = (event) => {
|
|
200
|
+
if (disabled) return;
|
|
201
|
+
|
|
202
|
+
const rect = triggerRef.current?.getBoundingClientRect();
|
|
203
|
+
if (rect) {
|
|
204
|
+
setCoords({
|
|
205
|
+
x: rect.left + rect.width / 2,
|
|
206
|
+
y: rect.top
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
setVisible(true);
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
const hideTooltip = () => {
|
|
213
|
+
setVisible(false);
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
const triggerProps = trigger === 'hover'
|
|
217
|
+
? { onMouseEnter: showTooltip, onMouseLeave: hideTooltip }
|
|
218
|
+
: { onClick: () => setVisible(!visible) };
|
|
219
|
+
|
|
220
|
+
useEffect(() => {
|
|
221
|
+
if (trigger === 'click' && visible) {
|
|
222
|
+
const handleClickOutside = (event) => {
|
|
223
|
+
if (tooltipRef.current && !tooltipRef.current.contains(event.target) &&
|
|
224
|
+
triggerRef.current && !triggerRef.current.contains(event.target)) {
|
|
225
|
+
setVisible(false);
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
document.addEventListener('mousedown', handleClickOutside);
|
|
230
|
+
return () => document.removeEventListener('mousedown', handleClickOutside);
|
|
231
|
+
}
|
|
232
|
+
}, [visible, trigger]);
|
|
233
|
+
|
|
234
|
+
return (
|
|
235
|
+
<>
|
|
236
|
+
<div
|
|
237
|
+
ref={triggerRef}
|
|
238
|
+
className={`sf-tooltip-trigger ${className}`}
|
|
239
|
+
{...triggerProps}
|
|
240
|
+
>
|
|
241
|
+
{children}
|
|
242
|
+
</div>
|
|
243
|
+
|
|
244
|
+
{visible && (
|
|
245
|
+
<div
|
|
246
|
+
ref={tooltipRef}
|
|
247
|
+
className={`sf-tooltip sf-tooltip--${position} sf-tooltip--visible`}
|
|
248
|
+
style={{
|
|
249
|
+
left: coords.x,
|
|
250
|
+
top: position === 'top' ? coords.y - 10 : coords.y + 30
|
|
251
|
+
}}
|
|
252
|
+
>
|
|
253
|
+
<div className="sf-tooltip__content">{content}</div>
|
|
254
|
+
<div className="sf-tooltip__arrow"></div>
|
|
255
|
+
</div>
|
|
256
|
+
)}
|
|
257
|
+
</>
|
|
258
|
+
);
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
// Loading Spinner Component
|
|
262
|
+
const Spinner = ({
|
|
263
|
+
size = 'medium',
|
|
264
|
+
color = 'primary',
|
|
265
|
+
className = ''
|
|
266
|
+
}) => (
|
|
267
|
+
<div className={`sf-spinner sf-spinner--${size} sf-spinner--${color} ${className}`}>
|
|
268
|
+
<div className="sf-spinner__circle"></div>
|
|
269
|
+
</div>
|
|
270
|
+
);
|
|
271
|
+
|
|
272
|
+
// Demo Component
|
|
273
|
+
const InteractiveElements = () => {
|
|
274
|
+
const [toggleValue, setToggleValue] = useState(false);
|
|
275
|
+
const [inputValue, setInputValue] = useState('');
|
|
276
|
+
const [progress, setProgress] = useState(65);
|
|
277
|
+
const [loading, setLoading] = useState(false);
|
|
278
|
+
|
|
279
|
+
const handleLoadingDemo = () => {
|
|
280
|
+
setLoading(true);
|
|
281
|
+
setTimeout(() => setLoading(false), 3000);
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
const incrementProgress = () => {
|
|
285
|
+
setProgress(prev => Math.min(100, prev + 10));
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
const decrementProgress = () => {
|
|
289
|
+
setProgress(prev => Math.max(0, prev - 10));
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
return (
|
|
293
|
+
<section className="sf-interactive-demo">
|
|
294
|
+
<div className="sf-interactive-demo__container">
|
|
295
|
+
<h2 className="sf-interactive-demo__title">Interactive Elements</h2>
|
|
296
|
+
<p className="sf-interactive-demo__subtitle">
|
|
297
|
+
A comprehensive collection of interactive UI components with modern black/white design
|
|
298
|
+
</p>
|
|
299
|
+
|
|
300
|
+
{/* Buttons Section */}
|
|
301
|
+
<div className="sf-demo-section">
|
|
302
|
+
<h3 className="sf-demo-section__title">Buttons</h3>
|
|
303
|
+
<div className="sf-demo-grid">
|
|
304
|
+
<Button variant="primary">Primary Button</Button>
|
|
305
|
+
<Button variant="secondary">Secondary Button</Button>
|
|
306
|
+
<Button variant="ghost">Ghost Button</Button>
|
|
307
|
+
<Button variant="danger">Danger Button</Button>
|
|
308
|
+
<Button disabled>Disabled Button</Button>
|
|
309
|
+
<Button loading={loading} onClick={handleLoadingDemo}>
|
|
310
|
+
{loading ? 'Loading...' : 'Click to Load'}
|
|
311
|
+
</Button>
|
|
312
|
+
</div>
|
|
313
|
+
</div>
|
|
314
|
+
|
|
315
|
+
{/* Form Inputs Section */}
|
|
316
|
+
<div className="sf-demo-section">
|
|
317
|
+
<h3 className="sf-demo-section__title">Form Inputs</h3>
|
|
318
|
+
<div className="sf-demo-grid sf-demo-grid--vertical">
|
|
319
|
+
<Input
|
|
320
|
+
label="Username"
|
|
321
|
+
placeholder="Enter your username"
|
|
322
|
+
value={inputValue}
|
|
323
|
+
onChange={(e) => setInputValue(e.target.value)}
|
|
324
|
+
required
|
|
325
|
+
/>
|
|
326
|
+
<Input
|
|
327
|
+
label="Email"
|
|
328
|
+
type="email"
|
|
329
|
+
placeholder="Enter your email"
|
|
330
|
+
/>
|
|
331
|
+
<Input
|
|
332
|
+
label="Password"
|
|
333
|
+
type="password"
|
|
334
|
+
placeholder="Enter your password"
|
|
335
|
+
/>
|
|
336
|
+
<Input
|
|
337
|
+
label="Error Example"
|
|
338
|
+
placeholder="This field has an error"
|
|
339
|
+
error="This field is required"
|
|
340
|
+
/>
|
|
341
|
+
<Input
|
|
342
|
+
label="Disabled Input"
|
|
343
|
+
placeholder="This is disabled"
|
|
344
|
+
disabled
|
|
345
|
+
/>
|
|
346
|
+
</div>
|
|
347
|
+
</div>
|
|
348
|
+
|
|
349
|
+
{/* Toggle Switches Section */}
|
|
350
|
+
<div className="sf-demo-section">
|
|
351
|
+
<h3 className="sf-demo-section__title">Toggle Switches</h3>
|
|
352
|
+
<div className="sf-demo-grid">
|
|
353
|
+
<Toggle
|
|
354
|
+
label="Enable notifications"
|
|
355
|
+
checked={toggleValue}
|
|
356
|
+
onChange={setToggleValue}
|
|
357
|
+
/>
|
|
358
|
+
<Toggle
|
|
359
|
+
label="Dark mode"
|
|
360
|
+
checked={false}
|
|
361
|
+
size="small"
|
|
362
|
+
/>
|
|
363
|
+
<Toggle
|
|
364
|
+
label="Auto-save"
|
|
365
|
+
checked={true}
|
|
366
|
+
size="large"
|
|
367
|
+
/>
|
|
368
|
+
<Toggle
|
|
369
|
+
label="Disabled toggle"
|
|
370
|
+
checked={false}
|
|
371
|
+
disabled
|
|
372
|
+
/>
|
|
373
|
+
</div>
|
|
374
|
+
</div>
|
|
375
|
+
|
|
376
|
+
{/* Progress Bars Section */}
|
|
377
|
+
<div className="sf-demo-section">
|
|
378
|
+
<h3 className="sf-demo-section__title">Progress Indicators</h3>
|
|
379
|
+
<div className="sf-demo-grid sf-demo-grid--vertical">
|
|
380
|
+
<ProgressBar
|
|
381
|
+
label="Upload Progress"
|
|
382
|
+
value={progress}
|
|
383
|
+
max={100}
|
|
384
|
+
/>
|
|
385
|
+
<ProgressBar
|
|
386
|
+
label="Loading"
|
|
387
|
+
value={35}
|
|
388
|
+
max={100}
|
|
389
|
+
size="small"
|
|
390
|
+
/>
|
|
391
|
+
<ProgressBar
|
|
392
|
+
value={80}
|
|
393
|
+
max={100}
|
|
394
|
+
showPercent={false}
|
|
395
|
+
/>
|
|
396
|
+
<div className="sf-demo-controls">
|
|
397
|
+
<Button onClick={decrementProgress} size="small">-10%</Button>
|
|
398
|
+
<Button onClick={incrementProgress} size="small">+10%</Button>
|
|
399
|
+
</div>
|
|
400
|
+
</div>
|
|
401
|
+
</div>
|
|
402
|
+
|
|
403
|
+
{/* Tooltips Section */}
|
|
404
|
+
<div className="sf-demo-section">
|
|
405
|
+
<h3 className="sf-demo-section__title">Tooltips</h3>
|
|
406
|
+
<div className="sf-demo-grid">
|
|
407
|
+
<Tooltip content="This is a top tooltip" position="top">
|
|
408
|
+
<Button variant="ghost">Hover me (Top)</Button>
|
|
409
|
+
</Tooltip>
|
|
410
|
+
<Tooltip content="This is a bottom tooltip" position="bottom">
|
|
411
|
+
<Button variant="ghost">Hover me (Bottom)</Button>
|
|
412
|
+
</Tooltip>
|
|
413
|
+
<Tooltip content="Click tooltip that stays open" trigger="click">
|
|
414
|
+
<Button variant="ghost">Click me</Button>
|
|
415
|
+
</Tooltip>
|
|
416
|
+
</div>
|
|
417
|
+
</div>
|
|
418
|
+
|
|
419
|
+
{/* Loading Spinners Section */}
|
|
420
|
+
<div className="sf-demo-section">
|
|
421
|
+
<h3 className="sf-demo-section__title">Loading Spinners</h3>
|
|
422
|
+
<div className="sf-demo-grid">
|
|
423
|
+
<Spinner size="small" />
|
|
424
|
+
<Spinner size="medium" />
|
|
425
|
+
<Spinner size="large" />
|
|
426
|
+
<Spinner color="secondary" />
|
|
427
|
+
</div>
|
|
428
|
+
</div>
|
|
429
|
+
</div>
|
|
430
|
+
</section>
|
|
431
|
+
);
|
|
432
|
+
};
|
|
433
|
+
|
|
434
|
+
// Export individual components and demo
|
|
435
|
+
export {
|
|
436
|
+
Button,
|
|
437
|
+
Input,
|
|
438
|
+
Toggle,
|
|
439
|
+
ProgressBar,
|
|
440
|
+
Tooltip,
|
|
441
|
+
Spinner
|
|
442
|
+
};
|
|
443
|
+
|
|
444
|
+
export default InteractiveElements;
|