1
- <script setup lang="ts">
2
- import { ref , onMounted , onUnmounted , computed } from ' vue' ;
3
- import { Icon } from ' @iconify/vue' ;
4
- import ConnectionLine from ' ./ConnectionLine.vue' ;
5
- import DMNOLogo from ' @dmno/ui-lib/brand-assets/domino-d-gradient-tile.svg' ;
6
-
7
- function shuffleArray(array : any []) {
8
- for (let i = array .length - 1 ; i > 0 ; i -- ) {
9
- const j = Math .floor (Math .random () * (i + 1 ));
10
- [array [i ], array [j ]] = [array [j ], array [i ]];
11
- }
12
- }
13
-
14
- const secretIcons = ref ([
15
- { icon: ' mdi:1password' , label: ' 1Password' , docsHref: ' /docs/plugins/1password/' },
16
- { icon: ' simple-icons:bitwarden' , label: ' Bitwarden' , docsHref: ' /docs/plugins/bitwarden/' },
17
- { icon: ' mdi:lock' , label: ' Encrypted Vault' , docsHref: ' /docs/plugins/encrypted-vault/' },
18
- { icon: ' mdi:infinity' , label: ' Infisical' , docsHref: ' /docs/plugins/infisical/' },
19
- { icon: ' mdi:server-outline' , label: ' your self-hosted secrets manager' , docsHref: ' /docs/plugins/overview/' },
20
- ]);
21
-
22
- const integrationIcons = ref ([
23
- { icon: ' devicon:remix' , label: ' Remix' , docsHref: ' /docs/integrations/remix/' },
24
- { icon: ' devicon:nextjs' , label: ' Next.js' , docsHref: ' /docs/integrations/nextjs/' },
25
- { icon: ' devicon:astro' , label: ' Astro' , docsHref: ' /docs/integrations/astro/' },
26
- { icon: ' logos:vitejs' , label: ' Vite' , docsHref: ' /docs/integrations/vite/' },
27
- { icon: ' devicon:nodejs' , label: ' Node.js' , docsHref: ' /docs/integrations/node/' }
28
- ]);
29
-
30
- const platformIcons = ref ([
31
- { icon: ' devicon:netlify' , label: ' Netlify' , docsHref: ' /docs/platforms/netlify/' },
32
- { icon: ' devicon:vercel' , label: ' Vercel' , docsHref: ' /docs/platforms/vercel/' },
33
- { icon: ' devicon:cloudflare' , label: ' Cloudflare' , docsHref: ' /docs/platforms/cloudflare/' },
34
- { icon: ' devicon:docker' , label: ' Docker' , docsHref: ' /docs/platforms/' },
35
- { icon: ' mdi:server-outline' , label: ' Self-hosted infra' , docsHref: ' /docs/platforms/overview/' },
36
- ]);
37
-
38
- // Selected icon states
39
- const selectedLeftIndex = ref (0 );
40
- const selectedMiddleIndex = ref (0 );
41
- const selectedRightIndex = ref (0 );
42
-
43
- const INTERVAL = 4000 ;
44
-
45
- // Cycle through icons every 2 seconds
46
- onMounted (() => {
47
- shuffleArray (secretIcons .value );
48
- shuffleArray (integrationIcons .value );
49
- shuffleArray (platformIcons .value );
50
-
51
- setInterval (() => {
52
- selectedLeftIndex .value = (selectedLeftIndex .value + 1 ) % secretIcons .value .length ;
53
- }, INTERVAL );
54
-
55
- setInterval (() => {
56
- selectedMiddleIndex .value = (selectedMiddleIndex .value + 1 ) % integrationIcons .value .length ;
57
- }, INTERVAL );
58
-
59
- setInterval (() => {
60
- selectedRightIndex .value = (selectedRightIndex .value + 1 ) % platformIcons .value .length ;
61
- }, INTERVAL );
62
-
63
- setInterval (() => {
64
- shuffleArray (secretIcons .value );
65
- shuffleArray (integrationIcons .value );
66
- shuffleArray (platformIcons .value );
67
- }, INTERVAL * platformIcons .value .length );
68
- });
69
-
70
- // Adjusted coordinates for better connections
71
- const iconSize = 64 // 16 * 4 (w-16)
72
- const centerIconSize = 80 // 20 * 4 (w-20)
73
- const spacing = 100
74
- const maxWidth = window .innerWidth < 1200 ? window .innerWidth : 1200 ;
75
-
76
- // Column spacing, calculated based on the viewport width
77
- const colSpacing = ref (maxWidth / 4 || 260 ); // Use SVG viewBox width divided by 4 columns
78
-
79
- const leftX = computed (() => 0 )
80
- const centerX = computed (() => colSpacing .value )
81
- const middleX = computed (() => colSpacing .value * 2 )
82
- const rightX = computed (() => colSpacing .value * 3 )
83
-
84
- onMounted (() => {
85
- const updateSpacing = () => {
86
- colSpacing .value = maxWidth / 4 || 260 ;
87
- }
88
-
89
- window .addEventListener (' resize' , updateSpacing )
90
-
91
- onUnmounted (() => {
92
- window .removeEventListener (' resize' , updateSpacing )
93
- })
94
- })
95
-
96
- // Calculate vertical positions
97
- const getVerticalPosition = (index : number , total : number ) => {
98
- const totalHeight = (total - 1 ) * spacing
99
- const startY = (600 - totalHeight ) / 2
100
- return startY + (index * spacing )
101
- }
102
-
103
- // Center Y position - align with middle of all icons
104
- const centerY = 300 - centerIconSize / 2
105
-
106
- // Calculate connection points for the right group
107
- const getRightConnectionY = (rightIndex : number , middleTotal : number ) => {
108
- const middleSpacing = (middleTotal - 1 ) * spacing
109
- const middleStartY = (600 - middleSpacing ) / 2
110
- const segmentSize = middleSpacing / (platformIcons .value .length - 1 )
111
- return middleStartY + (rightIndex * segmentSize )
112
- }
113
-
114
- const navigateTo = (href : string ) => {
115
- window .location .href = href ;
116
- }
117
- </script >
118
-
119
1
<template >
120
2
<div class =" container" >
121
3
<div class =" dynamic-text-container" >
122
- <h2 >Use secrets from
4
+ <h2 >Use secrets from
123
5
<span class =" dynamic-text-wrapper" >
124
6
<transition name =" fade" mode =" out-in" >
125
7
<span :key =" secretIcons[selectedLeftIndex].label" class =" dynamic-text active-secret" >
126
8
{{ secretIcons[selectedLeftIndex].label }}
127
9
</span >
128
10
</transition >
129
- </span >
130
- in your
11
+ </span >
12
+ in your
131
13
<span class =" dynamic-text-wrapper" >
132
14
<transition name =" fade" mode =" out-in" >
133
15
<span :key =" integrationIcons[selectedMiddleIndex].label" class =" dynamic-text active-integration" >
134
16
{{ integrationIcons[selectedMiddleIndex].label }}
135
17
</span >
136
18
</transition >
137
- </span >
138
- app and deploy to
19
+ </span >
20
+ app and deploy to
139
21
<span class =" dynamic-text-wrapper" >
140
22
<transition name =" fade" mode =" out-in" >
141
23
<span :key =" platformIcons[selectedRightIndex].label" class =" dynamic-text active-platform" >
@@ -202,7 +84,7 @@ const navigateTo = (href: string) => {
202
84
<!-- Center Node -->
203
85
<div
204
86
class =" center-icon"
205
- :style =" {
87
+ :style =" {
206
88
left: centerX + 'px',
207
89
top: centerY + 'px'
208
90
}"
@@ -250,6 +132,126 @@ const navigateTo = (href: string) => {
250
132
</div >
251
133
</template >
252
134
135
+ <script setup lang="ts">
136
+ import {
137
+ ref , onMounted , onUnmounted , computed ,
138
+ } from ' vue' ;
139
+ import { Icon } from ' @iconify/vue' ;
140
+ import DMNOLogo from ' @dmno/ui-lib/brand-assets/domino-d-gradient-tile.svg' ;
141
+ import ConnectionLine from ' ./ConnectionLine.vue' ;
142
+
143
+ function shuffleArray(array : Array <any >) {
144
+ for (let i = array .length - 1 ; i > 0 ; i -- ) {
145
+ const j = Math .floor (Math .random () * (i + 1 ));
146
+ [array [i ], array [j ]] = [array [j ], array [i ]];
147
+ }
148
+ }
149
+
150
+ const secretIcons = ref ([
151
+ { icon: ' mdi:1password' , label: ' 1Password' , docsHref: ' /docs/plugins/1password/' },
152
+ { icon: ' simple-icons:bitwarden' , label: ' Bitwarden' , docsHref: ' /docs/plugins/bitwarden/' },
153
+ { icon: ' mdi:lock' , label: ' Encrypted Vault' , docsHref: ' /docs/plugins/encrypted-vault/' },
154
+ { icon: ' mdi:infinity' , label: ' Infisical' , docsHref: ' /docs/plugins/infisical/' },
155
+ { icon: ' mdi:server-outline' , label: ' your self-hosted secrets manager' , docsHref: ' /docs/plugins/overview/' },
156
+ ]);
157
+
158
+ const integrationIcons = ref ([
159
+ { icon: ' devicon:remix' , label: ' Remix' , docsHref: ' /docs/integrations/remix/' },
160
+ { icon: ' devicon:nextjs' , label: ' Next.js' , docsHref: ' /docs/integrations/nextjs/' },
161
+ { icon: ' devicon:astro' , label: ' Astro' , docsHref: ' /docs/integrations/astro/' },
162
+ { icon: ' logos:vitejs' , label: ' Vite' , docsHref: ' /docs/integrations/vite/' },
163
+ { icon: ' devicon:nodejs' , label: ' Node.js' , docsHref: ' /docs/integrations/node/' },
164
+ ]);
165
+
166
+ const platformIcons = ref ([
167
+ { icon: ' devicon:netlify' , label: ' Netlify' , docsHref: ' /docs/platforms/netlify/' },
168
+ { icon: ' devicon:vercel' , label: ' Vercel' , docsHref: ' /docs/platforms/vercel/' },
169
+ { icon: ' devicon:cloudflare' , label: ' Cloudflare' , docsHref: ' /docs/platforms/cloudflare/' },
170
+ { icon: ' devicon:docker' , label: ' Docker' , docsHref: ' /docs/platforms/' },
171
+ { icon: ' mdi:server-outline' , label: ' Self-hosted infra' , docsHref: ' /docs/platforms/overview/' },
172
+ ]);
173
+
174
+ // Selected icon states
175
+ const selectedLeftIndex = ref (0 );
176
+ const selectedMiddleIndex = ref (0 );
177
+ const selectedRightIndex = ref (0 );
178
+
179
+ const INTERVAL = 4000 ;
180
+
181
+ // Cycle through icons every 2 seconds
182
+ onMounted (() => {
183
+ shuffleArray (secretIcons .value );
184
+ shuffleArray (integrationIcons .value );
185
+ shuffleArray (platformIcons .value );
186
+
187
+ setInterval (() => {
188
+ selectedLeftIndex .value = (selectedLeftIndex .value + 1 ) % secretIcons .value .length ;
189
+ }, INTERVAL );
190
+
191
+ setInterval (() => {
192
+ selectedMiddleIndex .value = (selectedMiddleIndex .value + 1 ) % integrationIcons .value .length ;
193
+ }, INTERVAL );
194
+
195
+ setInterval (() => {
196
+ selectedRightIndex .value = (selectedRightIndex .value + 1 ) % platformIcons .value .length ;
197
+ }, INTERVAL );
198
+
199
+ setInterval (() => {
200
+ shuffleArray (secretIcons .value );
201
+ shuffleArray (integrationIcons .value );
202
+ shuffleArray (platformIcons .value );
203
+ }, INTERVAL * platformIcons .value .length );
204
+ });
205
+
206
+ // Adjusted coordinates for better connections
207
+ const iconSize = 64 ; // 16 * 4 (w-16)
208
+ const centerIconSize = 80 ; // 20 * 4 (w-20)
209
+ const spacing = 100 ;
210
+ const maxWidth = window .innerWidth < 1200 ? window .innerWidth : 1200 ;
211
+
212
+ // Column spacing, calculated based on the viewport width
213
+ const colSpacing = ref (maxWidth / 4 || 260 ); // Use SVG viewBox width divided by 4 columns
214
+
215
+ const leftX = computed (() => 0 );
216
+ const centerX = computed (() => colSpacing .value );
217
+ const middleX = computed (() => colSpacing .value * 2 );
218
+ const rightX = computed (() => colSpacing .value * 3 );
219
+
220
+ onMounted (() => {
221
+ const updateSpacing = () => {
222
+ colSpacing .value = maxWidth / 4 || 260 ;
223
+ };
224
+
225
+ window .addEventListener (' resize' , updateSpacing );
226
+
227
+ onUnmounted (() => {
228
+ window .removeEventListener (' resize' , updateSpacing );
229
+ });
230
+ });
231
+
232
+ // Calculate vertical positions
233
+ const getVerticalPosition = (index : number , total : number ) => {
234
+ const totalHeight = (total - 1 ) * spacing ;
235
+ const startY = (600 - totalHeight ) / 2 ;
236
+ return startY + (index * spacing );
237
+ };
238
+
239
+ // Center Y position - align with middle of all icons
240
+ const centerY = 300 - centerIconSize / 2 ;
241
+
242
+ // Calculate connection points for the right group
243
+ const getRightConnectionY = (rightIndex : number , middleTotal : number ) => {
244
+ const middleSpacing = (middleTotal - 1 ) * spacing ;
245
+ const middleStartY = (600 - middleSpacing ) / 2 ;
246
+ const segmentSize = middleSpacing / (platformIcons .value .length - 1 );
247
+ return middleStartY + (rightIndex * segmentSize );
248
+ };
249
+
250
+ const navigateTo = (href : string ) => {
251
+ window .location .href = href ;
252
+ };
253
+ </script >
254
+
253
255
<style >
254
256
.container {
255
257
margin-left : 40px ;
@@ -285,14 +287,14 @@ const navigateTo = (href: string) => {
285
287
286
288
.dynamic-text-container {
287
289
margin : 2rem 0 ;
288
- }
290
+ }
289
291
290
292
.dynamic-text-container > .dynamic-text {
291
293
color : rgb (147 51 234 ); /* text-purple-600 */
292
294
&:nth-of-type(1 ) {
293
295
color : rgb (41 , 232 , 232 );
294
296
}
295
-
297
+
296
298
&:nth-of-type (2 ) {
297
299
color : rgb (116 , 240 , 161 );
298
300
}
@@ -323,7 +325,7 @@ const navigateTo = (href: string) => {
323
325
/* todo user brand colors */
324
326
325
327
.icon-left {
326
- border-color : rgb (156 163 175 );
328
+ border-color : rgb (156 163 175 );
327
329
}
328
330
329
331
.icon-left.icon-selected {
@@ -335,7 +337,7 @@ const navigateTo = (href: string) => {
335
337
}
336
338
337
339
.icon-right.icon-selected {
338
- border : 2px solid rgb (243 , 125 , 227 );
340
+ border : 2px solid rgb (243 , 125 , 227 );
339
341
}
340
342
341
343
.center-icon {
@@ -383,7 +385,7 @@ const navigateTo = (href: string) => {
383
385
&:nth-of-type(1 ) {
384
386
color : rgb (41 , 232 , 232 );
385
387
}
386
-
388
+
387
389
&:nth-of-type (2 ) {
388
390
color : rgb (116 , 240 , 161 );
389
391
}
0 commit comments