@digital-ai/dot-illustrations 2.0.37 → 2.0.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/demo/demo.css +37 -183
- package/demo/index.html +156 -116
- package/demo/script.js +125 -81
- package/package.json +1 -1
package/demo/demo.css
CHANGED
|
@@ -1,95 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
body {
|
|
6
|
-
font-family: 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif;
|
|
7
|
-
margin: 0 auto;
|
|
8
|
-
height: 100%;
|
|
9
|
-
text-align: center;
|
|
10
|
-
}
|
|
1
|
+
/* dot-illustrations demo — custom styles
|
|
2
|
+
Tailwind handles layout; this file fills the gaps. */
|
|
11
3
|
|
|
12
|
-
|
|
13
|
-
align-items: center;
|
|
14
|
-
height: 160px;
|
|
15
|
-
width: 160px;
|
|
16
|
-
max-width: 160px;
|
|
17
|
-
max-height: 160px;
|
|
18
|
-
min-width: 92px;
|
|
19
|
-
min-height: 92px;
|
|
20
|
-
margin: auto;
|
|
21
|
-
}
|
|
4
|
+
*, *::before, *::after { box-sizing: border-box; }
|
|
22
5
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
flex-wrap: wrap;
|
|
27
|
-
font-family: 'Lato', sans-serif;
|
|
28
|
-
font-size: 14px;
|
|
29
|
-
margin-top: 8px;
|
|
30
|
-
text-align: center;
|
|
31
|
-
color: #667385;
|
|
32
|
-
z-index: 0;
|
|
33
|
-
}
|
|
6
|
+
/* ── Prevent legacy img rule from overriding card images ─────────────────── */
|
|
7
|
+
/* Only illustration img elements inside .dot-illustration get size treatment */
|
|
8
|
+
.dot-illustration img { display: block; }
|
|
34
9
|
|
|
35
|
-
|
|
10
|
+
/* ── Hidden clipboard source ────────────────────────────────────────────── */
|
|
11
|
+
.codeBlock { display: none !important; }
|
|
36
12
|
|
|
37
|
-
/* Tooltip for
|
|
38
|
-
.tooltiptext {
|
|
39
|
-
visibility: hidden;
|
|
40
|
-
background-color: black;
|
|
41
|
-
color: #fff;
|
|
42
|
-
text-align: center;
|
|
43
|
-
border-radius: 5px;
|
|
44
|
-
padding: 5px;
|
|
45
|
-
position: absolute;
|
|
46
|
-
z-index: 1;
|
|
47
|
-
bottom: 125%;
|
|
48
|
-
left: 50%;
|
|
49
|
-
transform: translateX(-50%);
|
|
50
|
-
opacity: 0;
|
|
51
|
-
transition: opacity 0.3s;
|
|
52
|
-
white-space: nowrap;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
.button:hover .tooltiptext {
|
|
56
|
-
visibility: visible;
|
|
57
|
-
opacity: 1;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
.codeBlock {
|
|
61
|
-
visibility: hidden;
|
|
62
|
-
white-space: pre-wrap;
|
|
63
|
-
background-color: #f4f4f4;
|
|
64
|
-
padding: 10px;
|
|
65
|
-
border: 1px solid #ddd;
|
|
66
|
-
border-radius: 5px;
|
|
67
|
-
max-width: 300px;
|
|
68
|
-
overflow: auto;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
.codeInclude {
|
|
72
|
-
color: rgb(43, 50, 55);
|
|
73
|
-
white-space: pre-wrap;
|
|
74
|
-
background-color: #f4f4f4;
|
|
75
|
-
padding: 10px;
|
|
76
|
-
border: 1px solid #ddd;
|
|
77
|
-
border-radius: 5px;
|
|
78
|
-
max-width: 300px;
|
|
79
|
-
overflow: auto;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/* When dark mode is active */
|
|
83
|
-
body.dark-mode .dot-illustration img.light {
|
|
84
|
-
display: none;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
body.dark-mode .dot-illustration img.dark {
|
|
88
|
-
display: block;
|
|
89
|
-
background-color: #232E40;
|
|
90
|
-
border-radius: 8px;
|
|
91
|
-
}
|
|
13
|
+
/* ── Tooltip (legacy compat — kept for copyText/copyCode) ───────────────── */
|
|
14
|
+
.tooltiptext { display: none; }
|
|
92
15
|
|
|
16
|
+
/* ── Floating bar — hidden off-screen, slides in on scroll ─────────────── */
|
|
93
17
|
#floating-bar {
|
|
94
18
|
pointer-events: none;
|
|
95
19
|
opacity: 0;
|
|
@@ -99,110 +23,40 @@ body.dark-mode .dot-illustration img.dark {
|
|
|
99
23
|
pointer-events: auto;
|
|
100
24
|
opacity: 1;
|
|
101
25
|
transform: translateY(0);
|
|
102
|
-
transition: transform 0.
|
|
103
|
-
|
|
104
|
-
.floating-search {
|
|
105
|
-
min-width: 0;
|
|
106
|
-
width: 120px;
|
|
107
|
-
max-width: 200px;
|
|
108
|
-
}
|
|
109
|
-
@media (min-width: 640px) {
|
|
110
|
-
.floating-search {
|
|
111
|
-
width: 200px;
|
|
112
|
-
max-width: 320px;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
.floating-tab {
|
|
116
|
-
min-width: 60px;
|
|
117
|
-
padding-left: 0.75rem;
|
|
118
|
-
padding-right: 0.75rem;
|
|
119
|
-
font-size: 0.85rem;
|
|
26
|
+
transition: transform 0.28s cubic-bezier(0.4, 0, 0.2, 1),
|
|
27
|
+
opacity 0.28s cubic-bezier(0.4, 0, 0.2, 1);
|
|
120
28
|
}
|
|
121
29
|
|
|
122
|
-
/*
|
|
123
|
-
#
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
}
|
|
129
|
-
#illustration-modal.active {
|
|
130
|
-
display: flex;
|
|
131
|
-
}
|
|
132
|
-
#illustration-modal .modal-content {
|
|
133
|
-
background: white;
|
|
134
|
-
border-radius: 1rem;
|
|
135
|
-
box-shadow: 0 10px 40px rgba(0,0,0,0.2);
|
|
136
|
-
max-width: 90vw;
|
|
137
|
-
max-height: 90vh;
|
|
138
|
-
overflow-y: auto;
|
|
139
|
-
padding: 2rem;
|
|
140
|
-
position: relative;
|
|
141
|
-
}
|
|
142
|
-
#illustration-modal .modal-image img {
|
|
143
|
-
width: 220px;
|
|
144
|
-
height: 220px;
|
|
145
|
-
object-fit: contain;
|
|
146
|
-
border-radius: 0.75rem;
|
|
147
|
-
background: #f3f4f6;
|
|
148
|
-
margin-bottom: 1rem;
|
|
149
|
-
}
|
|
150
|
-
#illustration-modal .iconID {
|
|
151
|
-
font-size: 1.2rem;
|
|
152
|
-
font-weight: 600;
|
|
153
|
-
}
|
|
154
|
-
#illustration-modal .button-group {
|
|
155
|
-
margin-bottom: 1rem;
|
|
156
|
-
}
|
|
157
|
-
#illustration-modal #modal-close {
|
|
158
|
-
position: absolute;
|
|
159
|
-
top: 1rem;
|
|
160
|
-
right: 1rem;
|
|
161
|
-
background: none;
|
|
162
|
-
border: none;
|
|
163
|
-
font-size: 2rem;
|
|
164
|
-
color: #aaa;
|
|
165
|
-
cursor: pointer;
|
|
166
|
-
z-index: 10;
|
|
167
|
-
transition: color 0.2s;
|
|
30
|
+
/* ── Scrollable navs (no scrollbar) ─────────────────────────────────────── */
|
|
31
|
+
#illus-sub-tabs,
|
|
32
|
+
#floating-tabs,
|
|
33
|
+
#section-switcher {
|
|
34
|
+
overflow-x: auto;
|
|
35
|
+
scrollbar-width: none;
|
|
168
36
|
}
|
|
169
|
-
#
|
|
170
|
-
|
|
37
|
+
#illus-sub-tabs::-webkit-scrollbar,
|
|
38
|
+
#floating-tabs::-webkit-scrollbar,
|
|
39
|
+
#section-switcher::-webkit-scrollbar { display: none; }
|
|
40
|
+
|
|
41
|
+
/* ── GitHub user badge ──────────────────────────────────────────────────── */
|
|
42
|
+
#gh-user-badge { display: none; }
|
|
43
|
+
#gh-user-badge.connected { display: flex; }
|
|
44
|
+
|
|
45
|
+
/* ── Card grid items — slide-up action bar ──────────────────────────────── */
|
|
46
|
+
.copy-container { position: relative; }
|
|
47
|
+
.copy-container .action-bar {
|
|
48
|
+
transform: translateY(100%);
|
|
49
|
+
transition: transform 0.15s ease-out;
|
|
171
50
|
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
padding: 1rem;
|
|
175
|
-
max-width: 98vw;
|
|
176
|
-
}
|
|
177
|
-
#illustration-modal .modal-image img {
|
|
178
|
-
width: 140px;
|
|
179
|
-
height: 140px;
|
|
180
|
-
}
|
|
51
|
+
.copy-container:hover .action-bar {
|
|
52
|
+
transform: translateY(0);
|
|
181
53
|
}
|
|
182
54
|
|
|
183
55
|
/* ── Alphabet strip ─────────────────────────────────────────────────────── */
|
|
184
56
|
#alphabet-strip {
|
|
185
57
|
display: flex;
|
|
186
58
|
flex-wrap: wrap;
|
|
187
|
-
|
|
188
|
-
gap: 0.
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
/* ── Tab nav horizontal scroll ──────────────────────────────────────────── */
|
|
192
|
-
#main-tabs {
|
|
193
|
-
overflow-x: auto;
|
|
194
|
-
scrollbar-width: none;
|
|
195
|
-
}
|
|
196
|
-
#main-tabs::-webkit-scrollbar { display: none; }
|
|
197
|
-
#floating-tabs { scrollbar-width: none; }
|
|
198
|
-
#floating-tabs::-webkit-scrollbar { display: none; }
|
|
199
|
-
|
|
200
|
-
/* ── GitHub user badge flex ─────────────────────────────────────────────── */
|
|
201
|
-
#gh-user-badge[style*="flex"] { display: flex !important; }
|
|
202
|
-
|
|
203
|
-
/* ── Integration card image sizing ─────────────────────────────────────── */
|
|
204
|
-
.dot-integration img {
|
|
205
|
-
width: 100%;
|
|
206
|
-
height: 100%;
|
|
207
|
-
object-fit: contain;
|
|
59
|
+
align-items: center;
|
|
60
|
+
gap: 0.125rem;
|
|
61
|
+
row-gap: 0.25rem;
|
|
208
62
|
}
|
package/demo/index.html
CHANGED
|
@@ -78,134 +78,160 @@
|
|
|
78
78
|
<!-- ── Page body ──────────────────────────────────────────────────────── -->
|
|
79
79
|
<main class="max-w-7xl mx-auto px-4 py-6">
|
|
80
80
|
|
|
81
|
-
<!-- Search -->
|
|
82
|
-
<div class="
|
|
83
|
-
<
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
81
|
+
<!-- Row 1: Search + Section switcher -->
|
|
82
|
+
<div class="flex items-center gap-3 mb-4">
|
|
83
|
+
<div class="relative flex-1">
|
|
84
|
+
<svg class="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400 pointer-events-none" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607z"/></svg>
|
|
85
|
+
<input id="myInput" type="text" autocomplete="off" placeholder="Search…"
|
|
86
|
+
class="w-full pl-10 pr-4 py-2.5 bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 rounded-xl text-sm text-gray-900 dark:text-white outline-none focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 transition">
|
|
87
|
+
<div id="search-suggestions" class="absolute top-full left-0 right-0 z-50 mt-1 bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 rounded-xl shadow-lg hidden max-h-64 overflow-y-auto"></div>
|
|
88
|
+
</div>
|
|
89
|
+
<!-- Section switcher inline with search -->
|
|
90
|
+
<div class="flex items-center bg-gray-100 dark:bg-gray-800 rounded-xl p-1 shrink-0" id="section-switcher">
|
|
91
|
+
<button id="section-illustrations" data-section="illustrations"
|
|
92
|
+
class="section-btn px-4 py-1.5 text-sm font-semibold rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white shadow-sm focus:outline-none transition whitespace-nowrap">
|
|
93
|
+
Illustrations
|
|
94
|
+
</button>
|
|
95
|
+
<button id="section-integrations" data-section="integrations"
|
|
96
|
+
class="section-btn px-4 py-1.5 text-sm font-semibold rounded-lg text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white focus:outline-none transition whitespace-nowrap">
|
|
97
|
+
Integrations
|
|
98
|
+
</button>
|
|
99
|
+
</div>
|
|
99
100
|
</div>
|
|
100
101
|
|
|
101
|
-
<!--
|
|
102
|
-
<div
|
|
103
|
-
<
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
102
|
+
<!-- Row 2: Sub-tabs (illustrations) + Alphabet strip -->
|
|
103
|
+
<div class="flex items-center justify-between gap-4 mb-4 flex-wrap">
|
|
104
|
+
<div id="illus-sub-tabs" class="flex items-center gap-1 bg-gray-100 dark:bg-gray-800 rounded-xl p-1 w-fit" role="tablist">
|
|
105
|
+
<button class="tab-btn px-3 py-1.5 text-sm font-medium rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white shadow-sm focus:outline-none transition" data-tab="all" role="tab">All</button>
|
|
106
|
+
<button class="tab-btn px-3 py-1.5 text-sm font-medium rounded-lg text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white focus:outline-none transition" data-tab="global" role="tab">Global</button>
|
|
107
|
+
<button class="tab-btn px-3 py-1.5 text-sm font-medium rounded-lg text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white focus:outline-none transition" data-tab="dashboards" role="tab">Dashboards</button>
|
|
108
|
+
<button class="tab-btn px-3 py-1.5 text-sm font-medium rounded-lg text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white focus:outline-none transition" data-tab="favourites" role="tab">Favourites</button>
|
|
109
|
+
</div>
|
|
110
|
+
<div id="alphabet-strip" class="hidden items-center flex-wrap gap-0.5"></div>
|
|
107
111
|
</div>
|
|
108
112
|
|
|
109
|
-
<!-- Alphabet filter -->
|
|
110
|
-
<div id="alphabet-strip" class="hidden flex flex-wrap gap-1 mb-4"></div>
|
|
111
|
-
|
|
112
113
|
<!-- Result count -->
|
|
113
114
|
<p id="result-count" class="text-xs text-gray-400 dark:text-gray-500 mb-3"></p>
|
|
114
115
|
|
|
115
116
|
<!-- Grid -->
|
|
116
117
|
<div id="illustration-list"
|
|
117
|
-
class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-
|
|
118
|
+
class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 xl:grid-cols-6 gap-3 max-h-[calc(100vh-280px)] overflow-y-auto pr-1">
|
|
118
119
|
</div>
|
|
119
120
|
|
|
120
|
-
<!-- Upload
|
|
121
|
-
<div id="upload-panel" class="hidden
|
|
122
|
-
<div class="bg-white dark:bg-gray-900 rounded-2xl border border-gray-200 dark:border-gray-700 shadow-lg p-6 max-w-2xl">
|
|
123
|
-
<h2 class="text-lg font-semibold text-gray-900 dark:text-white mb-5">Upload new asset → Create PR</h2>
|
|
124
|
-
<div class="grid md:grid-cols-2 gap-6">
|
|
121
|
+
<!-- Upload modal — rendered as fixed overlay, NOT inline -->
|
|
122
|
+
<div id="upload-panel" class="hidden fixed inset-0 z-50 flex items-center justify-center bg-black/40 dark:bg-black/60 backdrop-blur-sm p-4">
|
|
125
123
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
124
|
+
<!-- Modal inner container -->
|
|
125
|
+
<div class="relative bg-white dark:bg-gray-900 rounded-2xl shadow-2xl border border-gray-200 dark:border-gray-700 w-full max-w-md max-h-[90vh] overflow-y-auto">
|
|
126
|
+
<button id="upload-modal-close" class="absolute top-4 right-4 z-10 p-1.5 rounded-lg text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-800 transition">
|
|
127
|
+
<svg class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/></svg>
|
|
128
|
+
</button>
|
|
129
|
+
|
|
130
|
+
<!-- Step 1: choose type -->
|
|
131
|
+
<div id="upload-type-picker" class="p-6">
|
|
132
|
+
<h2 class="text-base font-semibold text-gray-900 dark:text-white mb-1">What do you want to upload?</h2>
|
|
133
|
+
<p class="text-xs text-gray-400 dark:text-gray-500 mb-5">A PR will be created automatically once you fill in the details.</p>
|
|
134
|
+
<div class="grid grid-cols-2 gap-3">
|
|
135
|
+
<button id="pick-illustration"
|
|
136
|
+
class="flex flex-col items-center gap-3 p-5 rounded-xl border-2 border-gray-200 dark:border-gray-700 hover:border-blue-500 dark:hover:border-blue-400 hover:bg-blue-50 dark:hover:bg-blue-900/20 transition group focus:outline-none focus:border-blue-500">
|
|
137
|
+
<span class="text-4xl">🖼</span>
|
|
138
|
+
<div class="text-center">
|
|
139
|
+
<p class="text-sm font-semibold text-gray-900 dark:text-white group-hover:text-blue-700 dark:group-hover:text-blue-300 transition">Illustration</p>
|
|
140
|
+
<p class="text-xs text-gray-400 dark:text-gray-500 mt-0.5">Light + dark SVG variants</p>
|
|
135
141
|
</div>
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
</select>
|
|
144
|
-
<div class="grid grid-cols-2 gap-2">
|
|
145
|
-
<label class="flex flex-col gap-1">
|
|
146
|
-
<span class="text-xs text-gray-500 dark:text-gray-400">☀️ Light SVG</span>
|
|
147
|
-
<div id="illus-light-drop" class="border-2 border-dashed border-gray-200 dark:border-gray-700 rounded-lg p-3 text-center text-xs text-gray-400 cursor-pointer hover:border-blue-400 transition">
|
|
148
|
-
Drop or click<input id="illus-light-input" type="file" accept=".svg" class="hidden">
|
|
149
|
-
</div>
|
|
150
|
-
<p id="illus-light-name" class="hidden text-xs text-green-600 dark:text-green-400 truncate"></p>
|
|
151
|
-
</label>
|
|
152
|
-
<label class="flex flex-col gap-1">
|
|
153
|
-
<span class="text-xs text-gray-500 dark:text-gray-400">🌙 Dark SVG</span>
|
|
154
|
-
<div id="illus-dark-drop" class="border-2 border-dashed border-gray-200 dark:border-gray-700 rounded-lg p-3 text-center text-xs text-gray-400 cursor-pointer hover:border-blue-400 transition">
|
|
155
|
-
Drop or click<input id="illus-dark-input" type="file" accept=".svg" class="hidden">
|
|
156
|
-
</div>
|
|
157
|
-
<p id="illus-dark-name" class="hidden text-xs text-green-600 dark:text-green-400 truncate"></p>
|
|
158
|
-
</label>
|
|
159
|
-
</div>
|
|
160
|
-
<button id="upload-illus-btn"
|
|
161
|
-
class="w-full px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white text-sm font-medium rounded-lg transition disabled:opacity-50">
|
|
162
|
-
Create Pull Request
|
|
163
|
-
</button>
|
|
164
|
-
<div id="upload-illus-status" class="hidden text-xs text-center"></div>
|
|
165
|
-
<div id="upload-illus-pr-link" class="hidden">
|
|
166
|
-
<a id="upload-illus-pr-anchor" href="#" target="_blank"
|
|
167
|
-
class="flex items-center justify-center gap-2 px-4 py-2 bg-green-600 hover:bg-green-700 text-white text-sm font-medium rounded-lg transition">
|
|
168
|
-
View Pull Request ↗
|
|
169
|
-
</a>
|
|
170
|
-
</div>
|
|
142
|
+
</button>
|
|
143
|
+
<button id="pick-integration"
|
|
144
|
+
class="flex flex-col items-center gap-3 p-5 rounded-xl border-2 border-gray-200 dark:border-gray-700 hover:border-blue-500 dark:hover:border-blue-400 hover:bg-blue-50 dark:hover:bg-blue-900/20 transition group focus:outline-none focus:border-blue-500">
|
|
145
|
+
<span class="text-4xl">🔌</span>
|
|
146
|
+
<div class="text-center">
|
|
147
|
+
<p class="text-sm font-semibold text-gray-900 dark:text-white group-hover:text-blue-700 dark:group-hover:text-blue-300 transition">Integration</p>
|
|
148
|
+
<p class="text-xs text-gray-400 dark:text-gray-500 mt-0.5">Single SVG, no dark variant</p>
|
|
171
149
|
</div>
|
|
150
|
+
</button>
|
|
151
|
+
</div>
|
|
152
|
+
</div>
|
|
153
|
+
|
|
154
|
+
<!-- Step 2a: Illustration form -->
|
|
155
|
+
<div id="upload-illus-panel" class="hidden p-6 flex flex-col gap-4">
|
|
156
|
+
<div class="flex items-center gap-3 mb-1">
|
|
157
|
+
<button id="back-from-illus" class="text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 transition">
|
|
158
|
+
<svg class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M10.5 19.5L3 12m0 0l7.5-7.5M3 12h18"/></svg>
|
|
159
|
+
</button>
|
|
160
|
+
<div>
|
|
161
|
+
<h2 class="text-base font-semibold text-gray-900 dark:text-white">🖼 Upload Illustration</h2>
|
|
162
|
+
<p class="text-xs text-gray-400 dark:text-gray-500">Requires light and dark SVG variants</p>
|
|
172
163
|
</div>
|
|
164
|
+
</div>
|
|
173
165
|
|
|
174
|
-
|
|
175
|
-
<
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
</
|
|
184
|
-
<
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
166
|
+
<div id="upload-illus-auth-gate" class="flex items-center gap-2 p-3 bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800 rounded-lg text-xs text-amber-700 dark:text-amber-300">
|
|
167
|
+
<svg class="w-4 h-4 shrink-0" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z"/></svg>
|
|
168
|
+
Connect GitHub to enable uploads
|
|
169
|
+
</div>
|
|
170
|
+
<div id="upload-illus-form" class="hidden flex flex-col gap-3">
|
|
171
|
+
<input id="upload-illus-id" type="text" placeholder="Illustration ID (e.g. my-illustration)"
|
|
172
|
+
class="w-full px-3 py-2 text-sm bg-gray-50 dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg text-gray-900 dark:text-white outline-none focus:border-blue-500 transition">
|
|
173
|
+
<select id="upload-illus-category"
|
|
174
|
+
class="w-full px-3 py-2 text-sm bg-gray-50 dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg text-gray-900 dark:text-white outline-none focus:border-blue-500 transition">
|
|
175
|
+
<option value="global">Global</option>
|
|
176
|
+
<option value="dashboards">Dashboards</option>
|
|
177
|
+
</select>
|
|
178
|
+
<div class="grid grid-cols-2 gap-3">
|
|
179
|
+
<div>
|
|
180
|
+
<p class="text-xs text-gray-500 dark:text-gray-400 mb-1">☀️ Light SVG <span class="text-red-400">*</span></p>
|
|
181
|
+
<div id="illus-light-drop" class="border-2 border-dashed border-gray-200 dark:border-gray-700 rounded-lg p-4 text-center text-xs text-gray-400 cursor-pointer hover:border-blue-400 transition">
|
|
182
|
+
Drop or click<input id="illus-light-input" type="file" accept=".svg" class="hidden">
|
|
189
183
|
</div>
|
|
190
|
-
<p id="
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
<div id="upload-integ-status" class="hidden text-xs text-center"></div>
|
|
197
|
-
<div id="upload-integ-pr-link" class="hidden">
|
|
198
|
-
<a id="upload-integ-pr-anchor" href="#" target="_blank"
|
|
199
|
-
class="flex items-center justify-center gap-2 px-4 py-2 bg-green-600 hover:bg-green-700 text-white text-sm font-medium rounded-lg transition">
|
|
200
|
-
View Pull Request ↗
|
|
201
|
-
</a>
|
|
184
|
+
<p id="illus-light-name" class="hidden text-xs text-green-600 dark:text-green-400 mt-1 truncate"></p>
|
|
185
|
+
</div>
|
|
186
|
+
<div>
|
|
187
|
+
<p class="text-xs text-gray-500 dark:text-gray-400 mb-1">🌙 Dark SVG <span class="text-red-400">*</span></p>
|
|
188
|
+
<div id="illus-dark-drop" class="border-2 border-dashed border-gray-200 dark:border-gray-700 rounded-lg p-4 text-center text-xs text-gray-400 cursor-pointer hover:border-blue-400 transition">
|
|
189
|
+
Drop or click<input id="illus-dark-input" type="file" accept=".svg" class="hidden">
|
|
202
190
|
</div>
|
|
191
|
+
<p id="illus-dark-name" class="hidden text-xs text-green-600 dark:text-green-400 mt-1 truncate"></p>
|
|
203
192
|
</div>
|
|
204
193
|
</div>
|
|
194
|
+
<button id="upload-illus-btn" class="w-full px-4 py-2.5 bg-blue-600 hover:bg-blue-700 text-white text-sm font-medium rounded-lg transition disabled:opacity-50">Create Pull Request</button>
|
|
195
|
+
<div id="upload-illus-status" class="hidden text-xs text-center"></div>
|
|
196
|
+
<div id="upload-illus-pr-link" class="hidden">
|
|
197
|
+
<a id="upload-illus-pr-anchor" href="#" target="_blank" class="flex items-center justify-center gap-2 px-4 py-2 bg-green-600 hover:bg-green-700 text-white text-sm font-medium rounded-lg transition">View Pull Request ↗</a>
|
|
198
|
+
</div>
|
|
199
|
+
</div>
|
|
200
|
+
</div>
|
|
201
|
+
|
|
202
|
+
<!-- Step 2b: Integration form -->
|
|
203
|
+
<div id="upload-integ-panel" class="hidden p-6 flex flex-col gap-4">
|
|
204
|
+
<div class="flex items-center gap-3 mb-1">
|
|
205
|
+
<button id="back-from-integ" class="text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 transition">
|
|
206
|
+
<svg class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M10.5 19.5L3 12m0 0l7.5-7.5M3 12h18"/></svg>
|
|
207
|
+
</button>
|
|
208
|
+
<div>
|
|
209
|
+
<h2 class="text-base font-semibold text-gray-900 dark:text-white">🔌 Upload Integration</h2>
|
|
210
|
+
<p class="text-xs text-gray-400 dark:text-gray-500">Single SVG — no dark variant required</p>
|
|
211
|
+
</div>
|
|
212
|
+
</div>
|
|
205
213
|
|
|
214
|
+
<div id="upload-integ-auth-gate" class="flex items-center gap-2 p-3 bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800 rounded-lg text-xs text-amber-700 dark:text-amber-300">
|
|
215
|
+
<svg class="w-4 h-4 shrink-0" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z"/></svg>
|
|
216
|
+
Connect GitHub to enable uploads
|
|
217
|
+
</div>
|
|
218
|
+
<div id="upload-integ-form" class="hidden flex flex-col gap-3">
|
|
219
|
+
<input id="upload-integ-id" type="text" placeholder="Integration ID (e.g. my-tool)"
|
|
220
|
+
class="w-full px-3 py-2 text-sm bg-gray-50 dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg text-gray-900 dark:text-white outline-none focus:border-blue-500 transition">
|
|
221
|
+
<div id="integ-svg-drop" class="border-2 border-dashed border-gray-200 dark:border-gray-700 rounded-xl p-6 text-center text-sm text-gray-400 cursor-pointer hover:border-blue-400 transition">
|
|
222
|
+
Drop SVG here or click to browse<input id="integ-svg-input" type="file" accept=".svg" class="hidden">
|
|
223
|
+
</div>
|
|
224
|
+
<p id="integ-svg-name" class="hidden text-xs text-green-600 dark:text-green-400 truncate"></p>
|
|
225
|
+
<button id="upload-integ-btn" class="w-full px-4 py-2.5 bg-blue-600 hover:bg-blue-700 text-white text-sm font-medium rounded-lg transition disabled:opacity-50">Create Pull Request</button>
|
|
226
|
+
<div id="upload-integ-status" class="hidden text-xs text-center"></div>
|
|
227
|
+
<div id="upload-integ-pr-link" class="hidden">
|
|
228
|
+
<a id="upload-integ-pr-anchor" href="#" target="_blank" class="flex items-center justify-center gap-2 px-4 py-2 bg-green-600 hover:bg-green-700 text-white text-sm font-medium rounded-lg transition">View Pull Request ↗</a>
|
|
229
|
+
</div>
|
|
206
230
|
</div>
|
|
207
231
|
</div>
|
|
208
|
-
|
|
232
|
+
|
|
233
|
+
</div><!-- /modal inner container -->
|
|
234
|
+
</div><!-- /upload-panel modal overlay -->
|
|
209
235
|
|
|
210
236
|
</main>
|
|
211
237
|
|
|
@@ -218,23 +244,37 @@
|
|
|
218
244
|
<div id="modal-image" class="mb-4 p-4 bg-gray-50 dark:bg-gray-800 rounded-xl"></div>
|
|
219
245
|
<p class="text-base font-semibold text-gray-900 dark:text-white mb-4" id="modal-illustration-name"></p>
|
|
220
246
|
<div class="w-full space-y-3 mb-4">
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
<div class="
|
|
224
|
-
<
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
247
|
+
<!-- Illustration fields (shown for illustrations) -->
|
|
248
|
+
<div id="modal-illus-fields">
|
|
249
|
+
<div class="mb-3">
|
|
250
|
+
<label class="text-xs font-medium text-gray-500 dark:text-gray-400 mb-1 block">Dot Code</label>
|
|
251
|
+
<div class="flex gap-2">
|
|
252
|
+
<textarea id="modal-dot-code" readonly rows="2"
|
|
253
|
+
class="flex-1 px-3 py-2 text-xs font-mono bg-gray-50 dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg text-gray-900 dark:text-white resize-none outline-none"></textarea>
|
|
254
|
+
<button id="modal-copy-dot-code"
|
|
255
|
+
class="px-3 py-1 text-xs bg-gray-100 dark:bg-gray-800 border border-gray-200 dark:border-gray-700 text-gray-700 dark:text-gray-300 rounded-lg hover:bg-blue-50 dark:hover:bg-blue-900/30 transition">Copy</button>
|
|
256
|
+
</div>
|
|
257
|
+
</div>
|
|
258
|
+
<div>
|
|
259
|
+
<label class="text-xs font-medium text-gray-500 dark:text-gray-400 mb-1 block">HTML Code</label>
|
|
260
|
+
<div class="flex gap-2">
|
|
261
|
+
<textarea id="modal-code" readonly rows="2"
|
|
262
|
+
class="flex-1 px-3 py-2 text-xs font-mono bg-gray-50 dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg text-gray-900 dark:text-white resize-none outline-none"></textarea>
|
|
263
|
+
<button id="modal-copy-code"
|
|
264
|
+
class="px-3 py-1 text-xs bg-gray-100 dark:bg-gray-800 border border-gray-200 dark:border-gray-700 text-gray-700 dark:text-gray-300 rounded-lg hover:bg-blue-50 dark:hover:bg-blue-900/30 transition">Copy</button>
|
|
265
|
+
</div>
|
|
228
266
|
</div>
|
|
229
267
|
</div>
|
|
230
|
-
|
|
231
|
-
|
|
268
|
+
<!-- Integration field — single usage snippet (no React component equivalent) -->
|
|
269
|
+
<div id="modal-integ-fields" class="hidden">
|
|
270
|
+
<label class="text-xs font-medium text-gray-500 dark:text-gray-400 mb-1 block">Usage</label>
|
|
232
271
|
<div class="flex gap-2">
|
|
233
|
-
<textarea id="modal-code" readonly rows="2"
|
|
272
|
+
<textarea id="modal-integ-code" readonly rows="2"
|
|
234
273
|
class="flex-1 px-3 py-2 text-xs font-mono bg-gray-50 dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg text-gray-900 dark:text-white resize-none outline-none"></textarea>
|
|
235
|
-
<button id="modal-copy-code"
|
|
274
|
+
<button id="modal-copy-integ-code"
|
|
236
275
|
class="px-3 py-1 text-xs bg-gray-100 dark:bg-gray-800 border border-gray-200 dark:border-gray-700 text-gray-700 dark:text-gray-300 rounded-lg hover:bg-blue-50 dark:hover:bg-blue-900/30 transition">Copy</button>
|
|
237
276
|
</div>
|
|
277
|
+
<p class="text-[10px] text-gray-400 dark:text-gray-500 mt-1.5">Requires <code class="font-mono">index.css</code> — no React component equivalent.</p>
|
|
238
278
|
</div>
|
|
239
279
|
</div>
|
|
240
280
|
<button id="modal-close-bottom"
|
package/demo/script.js
CHANGED
|
@@ -118,21 +118,43 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
118
118
|
const floatingTabs = document.querySelectorAll('.floating-tab');
|
|
119
119
|
|
|
120
120
|
// ── Upload New button (in header) ────────────────────────────────────────
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
121
|
+
// ── Upload New: type picker → form ──────────────────────────────────────
|
|
122
|
+
function showUploadStep(step) {
|
|
123
|
+
// step: 'picker' | 'illustration' | 'integration'
|
|
124
|
+
document.getElementById('upload-type-picker').classList.toggle('hidden', step !== 'picker');
|
|
125
|
+
document.getElementById('upload-illus-panel').classList.toggle('hidden', step !== 'illustration');
|
|
126
|
+
document.getElementById('upload-integ-panel').classList.toggle('hidden', step !== 'integration');
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function openUploadModal() {
|
|
124
130
|
const panel = document.getElementById('upload-panel');
|
|
125
|
-
panel.classList.
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
btn.classList.
|
|
133
|
-
|
|
131
|
+
panel.classList.remove('hidden');
|
|
132
|
+
showUploadStep('picker');
|
|
133
|
+
updateUploadAuthUI();
|
|
134
|
+
document.getElementById('upload-new-btn').classList.add('ring-2','ring-blue-400','bg-blue-700');
|
|
135
|
+
}
|
|
136
|
+
function closeUploadModal() {
|
|
137
|
+
document.getElementById('upload-panel').classList.add('hidden');
|
|
138
|
+
document.getElementById('upload-new-btn').classList.remove('ring-2','ring-blue-400','bg-blue-700');
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
document.getElementById('upload-new-btn')?.addEventListener('click', openUploadModal);
|
|
142
|
+
|
|
143
|
+
// Backdrop click does NOT close — use X button or Escape
|
|
144
|
+
|
|
145
|
+
// Close on X button
|
|
146
|
+
document.getElementById('upload-modal-close')?.addEventListener('click', closeUploadModal);
|
|
147
|
+
|
|
148
|
+
// Close on Escape
|
|
149
|
+
document.addEventListener('keydown', e => {
|
|
150
|
+
if (e.key === 'Escape' && !document.getElementById('upload-panel').classList.contains('hidden')) closeUploadModal();
|
|
134
151
|
});
|
|
135
152
|
|
|
153
|
+
document.getElementById('pick-illustration')?.addEventListener('click', () => { showUploadStep('illustration'); updateUploadAuthUI(); });
|
|
154
|
+
document.getElementById('pick-integration')?.addEventListener('click', () => { showUploadStep('integration'); updateUploadAuthUI(); });
|
|
155
|
+
document.getElementById('back-from-illus')?.addEventListener('click', () => showUploadStep('picker'));
|
|
156
|
+
document.getElementById('back-from-integ')?.addEventListener('click', () => showUploadStep('picker'));
|
|
157
|
+
|
|
136
158
|
// ── Section switcher (Illustrations | Integrations) — pill style ──────────
|
|
137
159
|
function updateSectionUI(section) {
|
|
138
160
|
document.querySelectorAll('.section-btn, .floating-section-btn').forEach(btn => {
|
|
@@ -162,15 +184,19 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
162
184
|
|
|
163
185
|
if (section === 'integrations') {
|
|
164
186
|
grid.classList.remove('hidden');
|
|
165
|
-
alphaStrip.classList.add('hidden');
|
|
166
187
|
illusSubTabs.classList.add('hidden');
|
|
167
188
|
if (floatingTabs) floatingTabs.classList.add('hidden');
|
|
189
|
+
// Alphabet strip — show as flex for integrations (110 items benefit from A–Z jump)
|
|
190
|
+
alphaStrip.style.display = 'flex';
|
|
191
|
+
renderAlphabetStrip();
|
|
168
192
|
renderIllustrations();
|
|
169
193
|
} else {
|
|
194
|
+
// Illustrations — search is sufficient for 72 items; hide alphabet strip
|
|
170
195
|
grid.classList.remove('hidden');
|
|
171
196
|
illusSubTabs.classList.remove('hidden');
|
|
172
197
|
if (floatingTabs) floatingTabs.classList.remove('hidden');
|
|
173
|
-
|
|
198
|
+
alphaStrip.style.display = 'none';
|
|
199
|
+
alphabetFilter = '';
|
|
174
200
|
renderIllustrations();
|
|
175
201
|
}
|
|
176
202
|
}
|
|
@@ -351,43 +377,58 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
351
377
|
if (!descriptionsLoaded) return;
|
|
352
378
|
|
|
353
379
|
const themeClass = root.classList.contains('dark') ? 'dark' : 'light';
|
|
354
|
-
const isInteg = type === 'integration' || integrationsList.includes(item) && !illustrations.includes(item);
|
|
380
|
+
const isInteg = type === 'integration' || (integrationsList.includes(item) && !illustrations.includes(item));
|
|
381
|
+
|
|
382
|
+
// Toggle field visibility
|
|
383
|
+
const illusFields = document.getElementById('modal-illus-fields');
|
|
384
|
+
const integFields = document.getElementById('modal-integ-fields');
|
|
385
|
+
if (illusFields) illusFields.classList.toggle('hidden', isInteg);
|
|
386
|
+
if (integFields) integFields.classList.toggle('hidden', !isInteg);
|
|
355
387
|
|
|
356
|
-
let imgHtml, dotCodeString, codeString;
|
|
357
388
|
if (isInteg) {
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
389
|
+
// Integration modal — single usage field
|
|
390
|
+
modalImage.innerHTML = `<img src="../integrations/${item}.svg" alt="${item}" style="width:140px;height:140px;object-fit:contain;" />`;
|
|
391
|
+
const usageCode = `<span class="dot-integration"><img class="${item}"/></span>`;
|
|
392
|
+
const integCodeEl = document.getElementById('modal-integ-code');
|
|
393
|
+
if (integCodeEl) integCodeEl.value = usageCode;
|
|
394
|
+
const copyInteg = document.getElementById('modal-copy-integ-code');
|
|
395
|
+
if (copyInteg) {
|
|
396
|
+
copyInteg.onclick = () => {
|
|
397
|
+
navigator.clipboard.writeText(usageCode).then(() => {
|
|
398
|
+
copyInteg.textContent = 'Copied!';
|
|
399
|
+
showToast('Copied: ' + usageCode);
|
|
400
|
+
setTimeout(() => { copyInteg.textContent = 'Copy'; }, 2000);
|
|
401
|
+
});
|
|
402
|
+
};
|
|
403
|
+
}
|
|
361
404
|
} else {
|
|
405
|
+
// Illustration modal — Dot Code + HTML Code
|
|
362
406
|
const cat = globalList.includes(item) ? 'global' : 'dashboards';
|
|
363
407
|
const svgPath = `illustrations/${themeClass}/${cat}/${item}.svg`;
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
408
|
+
modalImage.innerHTML = `<span class="dot-illustration"><img src="${svgPath}" class="${item} ${themeClass}" style="width:220px;height:220px;object-fit:contain;"/></span>`;
|
|
409
|
+
|
|
410
|
+
const dotCode = `<DotIllustration illustrationId="${item}" />`;
|
|
411
|
+
const htmlCode = `<span class="dot-illustration"><img src="${svgPath}" class="${item} ${themeClass}"/></span>`;
|
|
412
|
+
const modalDotCode = document.getElementById('modal-dot-code');
|
|
413
|
+
if (modalDotCode) modalDotCode.value = dotCode;
|
|
414
|
+
modalCode.value = htmlCode;
|
|
415
|
+
|
|
416
|
+
const modalCopyDotCode = document.getElementById('modal-copy-dot-code');
|
|
417
|
+
if (modalCopyDotCode) {
|
|
418
|
+
modalCopyDotCode.onclick = () => {
|
|
419
|
+
navigator.clipboard.writeText(dotCode).then(() => {
|
|
420
|
+
modalCopyDotCode.textContent = 'Copied!';
|
|
421
|
+
showToast('Copied: ' + dotCode);
|
|
422
|
+
setTimeout(() => { modalCopyDotCode.textContent = 'Copy'; }, 2000);
|
|
423
|
+
});
|
|
424
|
+
};
|
|
425
|
+
}
|
|
367
426
|
}
|
|
368
427
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
if (modalIllustrationName) modalIllustrationName.textContent = item;
|
|
372
|
-
const modalDotCode = document.getElementById('modal-dot-code');
|
|
373
|
-
if (modalDotCode) modalDotCode.value = dotCodeString;
|
|
374
|
-
modalCode.value = codeString;
|
|
375
|
-
|
|
428
|
+
const nameEl = document.getElementById('modal-illustration-name');
|
|
429
|
+
if (nameEl) nameEl.textContent = item;
|
|
376
430
|
modal.classList.add('active');
|
|
377
431
|
modal.classList.remove('hidden');
|
|
378
|
-
|
|
379
|
-
const modalCopyDotCode = document.getElementById('modal-copy-dot-code');
|
|
380
|
-
if (modalCopyDotCode) {
|
|
381
|
-
modalCopyDotCode.onclick = () => {
|
|
382
|
-
if (modalDotCode) {
|
|
383
|
-
navigator.clipboard.writeText(modalDotCode.value).then(() => {
|
|
384
|
-
modalCopyDotCode.textContent = 'Copied!';
|
|
385
|
-
showToast('Copied Dot Code: ' + modalDotCode.value);
|
|
386
|
-
setTimeout(() => { modalCopyDotCode.textContent = 'Copy Dot Code'; }, 2000);
|
|
387
|
-
});
|
|
388
|
-
}
|
|
389
|
-
};
|
|
390
|
-
}
|
|
391
432
|
}
|
|
392
433
|
function closeModal() {
|
|
393
434
|
modal.classList.remove('active');
|
|
@@ -412,14 +453,19 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
412
453
|
const letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
|
|
413
454
|
|
|
414
455
|
strip.innerHTML = `
|
|
415
|
-
<button class="alpha-btn
|
|
456
|
+
<button class="alpha-btn text-xs font-medium px-1.5 py-0.5 rounded-md transition-all ${
|
|
457
|
+
alphabetFilter === ''
|
|
458
|
+
? 'text-blue-600 dark:text-blue-400 font-semibold'
|
|
459
|
+
: 'text-gray-400 dark:text-gray-500 hover:text-gray-700 dark:hover:text-gray-300'
|
|
460
|
+
}" data-letter="">All</button>
|
|
461
|
+
<span class="text-gray-200 dark:text-gray-700 text-xs select-none">|</span>
|
|
416
462
|
${letters.map(l => `
|
|
417
|
-
<button class="alpha-btn
|
|
463
|
+
<button class="alpha-btn text-xs font-medium px-1.5 py-0.5 rounded-md transition-all ${
|
|
418
464
|
available.has(l)
|
|
419
465
|
? alphabetFilter === l
|
|
420
|
-
? '
|
|
421
|
-
: '
|
|
422
|
-
: '
|
|
466
|
+
? 'text-blue-600 dark:text-blue-400 font-semibold bg-blue-50 dark:bg-blue-900/30'
|
|
467
|
+
: 'text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 hover:bg-gray-100 dark:hover:bg-gray-800'
|
|
468
|
+
: 'text-gray-200 dark:text-gray-700 cursor-default'
|
|
423
469
|
}" data-letter="${l}" ${available.has(l) ? '' : 'disabled'}>${l}</button>
|
|
424
470
|
`).join('')}
|
|
425
471
|
`;
|
|
@@ -475,56 +521,53 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
475
521
|
|
|
476
522
|
if (isInteg) {
|
|
477
523
|
// Integration card — use direct <img src> so the image always loads
|
|
524
|
+
// ── Integration card ─────────────────────────────────────────────
|
|
478
525
|
const htmlCode = `<span class="dot-integration"><img class="${item}"/></span>`;
|
|
479
526
|
const div = document.createElement('div');
|
|
480
|
-
div.
|
|
481
|
-
div.dataset.itemId
|
|
527
|
+
div.className = 'copy-container group relative bg-white dark:bg-gray-900 rounded-2xl overflow-hidden cursor-pointer shadow-sm transition-all duration-200 hover:shadow-md hover:ring-2 hover:ring-blue-400/30 dark:hover:ring-blue-500/30';
|
|
528
|
+
div.dataset.itemId = item;
|
|
482
529
|
div.dataset.itemType = 'integration';
|
|
483
530
|
div.innerHTML = `
|
|
484
|
-
<button class="absolute top-2 right-2 z-
|
|
485
|
-
<svg class="
|
|
531
|
+
<button class="fav-btn absolute top-2.5 right-2.5 z-20 opacity-0 group-hover:opacity-100 transition-opacity p-1 rounded-lg bg-white/80 dark:bg-gray-800/80 backdrop-blur-sm shadow-sm" onclick="event.stopPropagation();window.toggleFavourite('${item}')">
|
|
532
|
+
<svg class="w-3.5 h-3.5" fill="${isFav ? '#FBBF24' : 'none'}" viewBox="0 0 24 24" stroke="${isFav ? '#FBBF24' : '#9CA3AF'}" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M11.049 2.927c.3-.921 1.603-.921 1.902 0l2.036 6.29a1 1 0 00.95.69h6.631c.969 0 1.371 1.24.588 1.81l-5.37 3.905a1 1 0 00-.364 1.118l2.036 6.29c.3.921-.755 1.688-1.54 1.118l-5.37-3.905a1 1 0 00-1.176 0l-5.37 3.905c-.784.57-1.838-.197-1.54-1.118l2.036-6.29a1 1 0 00-.364-1.118L2.342 11.717c-.783-.57-.38-1.81.588-1.81h6.631a1 1 0 00.95-.69l2.036-6.29z"/></svg>
|
|
486
533
|
</button>
|
|
487
|
-
<div class="flex
|
|
488
|
-
<img src="../integrations/${item}.svg" alt="${item}" class="w-
|
|
489
|
-
|
|
534
|
+
<div class="flex items-center justify-center h-36 px-4">
|
|
535
|
+
<img src="../integrations/${item}.svg" alt="${item}" class="w-[80px] h-[80px] object-contain" loading="lazy" />
|
|
536
|
+
</div>
|
|
537
|
+
<div class="px-3 py-3">
|
|
538
|
+
<p class="iconID text-[11px] text-center text-gray-500 dark:text-gray-400 font-medium leading-tight truncate">${item}</p>
|
|
490
539
|
</div>
|
|
491
|
-
<div class="
|
|
492
|
-
<button class="button flex
|
|
493
|
-
|
|
494
|
-
</button>
|
|
495
|
-
<button class="button flex items-center justify-center min-w-[80px] px-1.5 py-0.5 text-[11px] text-gray-400 border border-gray-300 dark:border-gray-700 rounded bg-white dark:bg-gray-800 font-normal hover:bg-blue-100 dark:hover:bg-blue-900 transition relative text-center" onmouseover="showTooltip(this)" onmouseout="hideTooltip(this)" onclick="copyCode(this)">
|
|
496
|
-
Copy Code<span class="tooltiptext left-1/2 -translate-x-1/2 bottom-10 shadow-md">Copy Code</span>
|
|
497
|
-
</button>
|
|
540
|
+
<div class="action-bar absolute bottom-0 inset-x-0 bg-white/97 dark:bg-gray-900/97 backdrop-blur-sm border-t border-gray-100 dark:border-gray-800 p-2 flex gap-1.5 translate-y-full group-hover:translate-y-0 transition-transform duration-150 ease-out">
|
|
541
|
+
<button class="button flex-1 py-1.5 text-[10px] font-semibold text-blue-600 dark:text-blue-400 bg-blue-50 dark:bg-blue-900/30 rounded-lg hover:bg-blue-100 dark:hover:bg-blue-900/60 transition" onclick="event.stopPropagation();copyText(this)">Dot Code</button>
|
|
542
|
+
<button class="button flex-1 py-1.5 text-[10px] font-semibold text-gray-500 dark:text-gray-400 bg-gray-100 dark:bg-gray-800 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-700 transition" onclick="event.stopPropagation();copyCode(this)">HTML</button>
|
|
498
543
|
</div>
|
|
499
|
-
<pre class="codeBlock"><code class="codeBlock">${htmlCode}</code></pre>
|
|
544
|
+
<pre class="codeBlock hidden"><code class="codeBlock">${htmlCode}</code></pre>
|
|
500
545
|
`;
|
|
501
546
|
list.appendChild(div);
|
|
502
547
|
} else {
|
|
503
|
-
// Illustration card
|
|
548
|
+
// ── Illustration card ─────────────────────────────────────────────
|
|
504
549
|
let categoryFolder = globalList.includes(item) ? 'global' : 'dashboards';
|
|
505
|
-
const svgPath
|
|
550
|
+
const svgPath = `illustrations/${themeClass}/${categoryFolder}/${item}.svg`;
|
|
506
551
|
const codeString = `<span class="dot-illustration"><img src="${svgPath}" class="${item} ${themeClass}"/></span>`;
|
|
507
552
|
const div = document.createElement('div');
|
|
508
|
-
div.
|
|
509
|
-
div.dataset.itemId
|
|
553
|
+
div.className = 'copy-container group relative bg-white dark:bg-gray-900 rounded-2xl overflow-hidden cursor-pointer shadow-sm transition-all duration-200 hover:shadow-md hover:ring-2 hover:ring-blue-400/30 dark:hover:ring-blue-500/30';
|
|
554
|
+
div.dataset.itemId = item;
|
|
510
555
|
div.dataset.itemType = 'illustration';
|
|
511
556
|
div.innerHTML = `
|
|
512
|
-
<button class="absolute top-2 right-2 z-
|
|
513
|
-
<svg class="
|
|
557
|
+
<button class="fav-btn absolute top-2.5 right-2.5 z-20 opacity-0 group-hover:opacity-100 transition-opacity p-1 rounded-lg bg-white/80 dark:bg-gray-800/80 backdrop-blur-sm shadow-sm" onclick="event.stopPropagation();window.toggleFavourite('${item}')">
|
|
558
|
+
<svg class="w-3.5 h-3.5" fill="${isFav ? '#FBBF24' : 'none'}" viewBox="0 0 24 24" stroke="${isFav ? '#FBBF24' : '#9CA3AF'}" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M11.049 2.927c.3-.921 1.603-.921 1.902 0l2.036 6.29a1 1 0 00.95.69h6.631c.969 0 1.371 1.24.588 1.81l-5.37 3.905a1 1 0 00-.364 1.118l2.036 6.29c.3.921-.755 1.688-1.54 1.118l-5.37-3.905a1 1 0 00-1.176 0l-5.37 3.905c-.784.57-1.838-.197-1.54-1.118l2.036-6.29a1 1 0 00-.364-1.118L2.342 11.717c-.783-.57-.38-1.81.588-1.81h6.631a1 1 0 00.95-.69l2.036-6.29z"/></svg>
|
|
514
559
|
</button>
|
|
515
|
-
<div class="flex
|
|
516
|
-
<
|
|
517
|
-
|
|
560
|
+
<div class="flex items-center justify-center h-36 px-4 dot-illustration">
|
|
561
|
+
<img src="${svgPath}" class="${item} ${themeClass}" style="width:120px;height:120px;object-fit:contain;display:block;" />
|
|
562
|
+
</div>
|
|
563
|
+
<div class="px-3 py-3">
|
|
564
|
+
<p class="iconID text-[11px] text-center text-gray-500 dark:text-gray-400 font-medium leading-tight break-words">${item}</p>
|
|
518
565
|
</div>
|
|
519
|
-
<div class="
|
|
520
|
-
<button
|
|
521
|
-
|
|
522
|
-
</button>
|
|
523
|
-
<button class="button flex items-center justify-center min-w-[80px] px-1.5 py-0.5 text-[11px] text-gray-400 border border-gray-300 dark:border-gray-700 rounded bg-white dark:bg-gray-800 font-normal hover:bg-blue-100 dark:hover:bg-blue-900 transition relative text-center" onmouseover="showTooltip(this)" onmouseout="hideTooltip(this)" onclick="copyCode(this)">
|
|
524
|
-
Copy Code<span class="tooltiptext left-1/2 -translate-x-1/2 bottom-10 shadow-md">Copy Code</span>
|
|
525
|
-
</button>
|
|
566
|
+
<div class="action-bar absolute bottom-0 inset-x-0 bg-white/97 dark:bg-gray-900/97 backdrop-blur-sm border-t border-gray-100 dark:border-gray-800 p-2 flex gap-1.5 translate-y-full group-hover:translate-y-0 transition-transform duration-150 ease-out">
|
|
567
|
+
<button class="button flex-1 py-1.5 text-[10px] font-semibold text-blue-600 dark:text-blue-400 bg-blue-50 dark:bg-blue-900/30 rounded-lg hover:bg-blue-100 dark:hover:bg-blue-900/60 transition" onclick="event.stopPropagation();copyText(this)">Dot Code</button>
|
|
568
|
+
<button class="button flex-1 py-1.5 text-[10px] font-semibold text-gray-500 dark:text-gray-400 bg-gray-100 dark:bg-gray-800 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-700 transition" onclick="event.stopPropagation();copyCode(this)">HTML</button>
|
|
526
569
|
</div>
|
|
527
|
-
<pre class="codeBlock"><code class="codeBlock">${codeString}</code></pre>
|
|
570
|
+
<pre class="codeBlock hidden"><code class="codeBlock">${codeString}</code></pre>
|
|
528
571
|
`;
|
|
529
572
|
list.appendChild(div);
|
|
530
573
|
}
|
|
@@ -728,10 +771,11 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
728
771
|
document.getElementById('upload-illus-btn')?.addEventListener('click', handleIllusUpload);
|
|
729
772
|
document.getElementById('upload-integ-btn')?.addEventListener('click', handleIntegUpload);
|
|
730
773
|
|
|
731
|
-
// Initial render
|
|
774
|
+
// Initial render — start on illustrations, alphabet hidden
|
|
775
|
+
const strip = document.getElementById('alphabet-strip');
|
|
776
|
+
if (strip) strip.style.display = 'none';
|
|
732
777
|
updateSectionUI('illustrations');
|
|
733
778
|
updateTabUI('all');
|
|
734
|
-
renderAlphabetStrip();
|
|
735
779
|
renderIllustrations();
|
|
736
780
|
|
|
737
781
|
// --- FLOATING BAR LOGIC ---
|
package/package.json
CHANGED