@digital-ai/dot-illustrations 2.0.22 → 2.0.24

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 CHANGED
@@ -118,3 +118,64 @@ body.dark-mode .dot-illustration img.dark {
118
118
  padding-right: 0.75rem;
119
119
  font-size: 0.85rem;
120
120
  }
121
+
122
+ /* Modal styles */
123
+ #illustration-modal {
124
+ display: none;
125
+ align-items: center;
126
+ justify-content: center;
127
+ background: rgba(0,0,0,0.5);
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;
168
+ }
169
+ #illustration-modal #modal-close:hover {
170
+ color: #333;
171
+ }
172
+ @media (max-width: 600px) {
173
+ #illustration-modal .modal-content {
174
+ padding: 1rem;
175
+ max-width: 98vw;
176
+ }
177
+ #illustration-modal .modal-image img {
178
+ width: 140px;
179
+ height: 140px;
180
+ }
181
+ }
@@ -0,0 +1,67 @@
1
+ {
2
+ "add-new": "This is the add-new illustration.",
3
+ "ai": "This is the ai illustration.",
4
+ "add-new-grid": "This is the add-new-grid illustration.",
5
+ "add-team": "This is the add-team illustration.",
6
+ "add-user": "This is the add-user illustration.",
7
+ "assets": "This is the assets illustration.",
8
+ "analysis-circle": "This is the analysis-circle illustration.",
9
+ "community": "This is the community illustration.",
10
+ "chart": "This is the chart illustration.",
11
+ "custom-dashboards": "This is the custom-dashboards illustration.",
12
+ "dependency-down": "This is the dependency-down illustration.",
13
+ "dependency-up": "This is the dependency-up illustration.",
14
+ "disconnected": "This is the disconnected illustration.",
15
+ "done": "This is the done illustration.",
16
+ "dora-metrics-circle": "This is the dora-metrics-circle illustration.",
17
+ "download": "This is the download illustration.",
18
+ "empty": "This is the empty illustration.",
19
+ "error-fourhundredfour": "This is the error-fourhundredfour illustration.",
20
+ "error-fivehundred": "This is the error-fivehundred illustration.",
21
+ "error-fivehundredthree": "This is the error-fivehundredthree illustration.",
22
+ "error-fourhundredthree": "This is the error-fourhundredthree illustration.",
23
+ "favorite": "This is the favorite illustration.",
24
+ "features": "This is the features illustration.",
25
+ "folder-versioning": "This is the folder-versioning illustration.",
26
+ "forbiden-access": "This is the forbiden-access illustration.",
27
+ "filter-empty": "This is the filter-empty illustration.",
28
+ "launch": "This is the launch illustration.",
29
+ "no-files": "This is the no-files illustration.",
30
+ "no-filters": "This is the no-filters illustration.",
31
+ "nothing-defined": "This is the nothing-defined illustration.",
32
+ "password-token": "This is the password-token illustration.",
33
+ "protection-in-progress": "This is the protection-in-progress illustration.",
34
+ "reports": "This is the reports illustration.",
35
+ "scan-document": "This is the scan-document illustration.",
36
+ "survey": "This is the survey illustration.",
37
+ "user": "This is the user illustration.",
38
+ "ui-ux-improvements": "This is the ui-ux-improvements illustration.",
39
+ "upload": "This is the upload illustration.",
40
+ "work-item": "This is the work-item illustration.",
41
+ "workflows-main": "This is the workflows-main illustration.",
42
+ "research": "This is the research illustration.",
43
+ "commitrepo": "This is the commitrepo illustration.",
44
+ "analysis": "This is the analysis illustration.",
45
+ "automation": "This is the automation illustration.",
46
+ "burn-down": "This is the burn-down illustration.",
47
+ "burn-up": "This is the burn-up illustration.",
48
+ "change-credit-score": "This is the change-credit-score illustration.",
49
+ "change-data-quality": "This is the change-data-quality illustration.",
50
+ "change-executive": "This is the change-executive illustration.",
51
+ "change-impact-detection": "This is the change-impact-detection illustration.",
52
+ "change-impact-hotspots": "This is the change-impact-hotspots illustration.",
53
+ "change-failure-factors": "This is the change-failure-factors illustration.",
54
+ "change-failure-prediction": "This is the change-failure-prediction illustration.",
55
+ "CRP-failure-prediction-monitoring": "This is the CRP-failure-prediction-monitoring illustration.",
56
+ "custom": "This is the custom illustration.",
57
+ "defect": "This is the defect illustration.",
58
+ "dependency": "This is the dependency illustration.",
59
+ "dora": "This is the dora illustration.",
60
+ "executive": "This is the executive illustration.",
61
+ "change-impact": "This is the change-impact illustration.",
62
+ "item": "This is the item illustration.",
63
+ "late-task": "This is the late-task illustration.",
64
+ "onboarding": "This is the onboarding illustration.",
65
+ "data-extraction": "This is the data-extraction illustration.",
66
+ "workflow": "This is the workflow illustration."
67
+ }
package/demo/index.html CHANGED
@@ -59,5 +59,29 @@
59
59
  <!-- Illustrations will be injected here -->
60
60
  </div>
61
61
  </div>
62
+ <!-- Modal for illustration details -->
63
+ <div id="illustration-modal" class="fixed inset-0 z-50 flex items-center justify-center bg-black/50 dark:bg-black/70 hidden">
64
+ <div class="bg-white dark:bg-gray-900 rounded-xl shadow-2xl max-w-lg w-full p-6 relative flex flex-col items-center">
65
+ <button id="modal-close" class="absolute top-3 right-3 text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 text-2xl font-bold focus:outline-none">&times;</button>
66
+ <h2 class="text-xl font-semibold mb-4 w-full text-center text-gray-900 dark:text-gray-100">Illustration preview</h2>
67
+ <div id="modal-image" class="mb-4"></div>
68
+ <div class="w-full flex flex-col gap-2 mb-2">
69
+ <label class="text-xs font-medium text-gray-500 dark:text-gray-400" for="modal-id-input">Image ID</label>
70
+ <div class="flex flex-row items-center gap-2">
71
+ <input id="modal-id-input" class="flex-1 px-2 py-1 border border-gray-300 dark:border-gray-700 rounded bg-gray-100 dark:bg-gray-800 text-gray-900 dark:text-white text-base font-mono" readonly />
72
+ <button id="modal-copy-id" class="button flex items-center justify-center px-2 py-1 text-xs 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">Copy ID</button>
73
+ </div>
74
+ </div>
75
+ <div id="modal-description" class="w-full text-center text-sm text-gray-700 dark:text-gray-300 mb-4"></div>
76
+ <div class="w-full flex flex-col gap-2 mb-2">
77
+ <label class="text-xs font-medium text-gray-500 dark:text-gray-400" for="modal-code">Code</label>
78
+ <div class="flex flex-row items-center gap-2">
79
+ <textarea id="modal-code" class="flex-1 px-2 py-1 border border-gray-300 dark:border-gray-700 rounded bg-gray-100 dark:bg-gray-800 text-gray-900 dark:text-white text-xs font-mono resize-none" rows="2" readonly></textarea>
80
+ <button id="modal-copy-code" class="button flex items-center justify-center px-2 py-1 text-xs 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">Copy Code</button>
81
+ </div>
82
+ </div>
83
+ <button id="modal-close-bottom" class="mt-4 px-4 py-2 rounded bg-gray-200 dark:bg-gray-700 text-gray-800 dark:text-gray-200 font-medium hover:bg-gray-300 dark:hover:bg-gray-600 transition">Close</button>
84
+ </div>
85
+ </div>
62
86
  </body>
63
87
  </html>
package/demo/script.js CHANGED
@@ -85,72 +85,31 @@ window.copyText = function(button) {
85
85
  });
86
86
  }
87
87
 
88
- // Theme toggle logic
89
- const button = document.getElementById('theme-toggle');
90
- const body = document.body;
91
-
92
- // Default to light mode on page load
93
- body.classList.add('light-mode');
94
-
95
- let isDarkMode = false;
96
-
97
- button.addEventListener('click', () => {
98
- isDarkMode = !isDarkMode;
99
- const imgs = document.querySelectorAll("img");
100
-
101
- if (isDarkMode) {
102
- imgs.forEach(img => {
103
- img.classList.remove("light");
104
- img.classList.add("dark");
105
- })
106
- body.classList.remove('light-mode');
107
- body.classList.add('dark-mode');
108
- button.textContent = 'Switch to light mode';
109
- } else {
110
- imgs.forEach(img => {
111
- img.classList.remove("dark");
112
- img.classList.add("light");
113
- })
114
- body.classList.remove('dark-mode');
115
- body.classList.add('light-mode');
116
- button.textContent = 'Switch to dark mode';
117
- }
118
- });
119
-
120
88
  // --- THEME SWITCHER & TABS ---
121
89
  document.addEventListener('DOMContentLoaded', () => {
122
- // Theme Switcher
123
- const themeToggle = document.getElementById('theme-toggle');
124
- const themeIcon = document.getElementById('theme-icon');
125
- const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
126
-
90
+ // --- THEME HANDLING ---
127
91
  function setTheme(dark) {
128
- const imgs = document.querySelectorAll('img');
92
+ const themeIcon = document.getElementById('theme-icon');
129
93
  if (dark) {
130
94
  root.classList.add('dark');
131
95
  localStorage.setItem('theme', 'dark');
132
- themeIcon.innerHTML = `<svg xmlns='http://www.w3.org/2000/svg' class='h-5 w-5' fill='none' viewBox='0 0 24 24' stroke='currentColor'><path stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M21 12.79A9 9 0 1111.21 3a7 7 0 109.79 9.79z' /></svg>`;
133
- imgs.forEach(img => {
134
- img.classList.remove('light');
135
- img.classList.add('dark');
136
- });
96
+ if (themeIcon) themeIcon.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6"><path stroke-linecap="round" stroke-linejoin="round" d="M21.752 15.002A9.718 9.718 0 0112 21.75c-5.385 0-9.75-4.365-9.75-9.75 0-4.005 2.356-7.45 5.748-9.002a.75.75 0 01.908.325.75.75 0 01-.098.976A7.501 7.501 0 0012 19.5a7.5 7.5 0 006.201-11.501.75.75 0 01-.098-.976.75.75 0 01.908-.325c3.392 1.552 5.748 4.997 5.748 9.002z" /></svg>`;
137
97
  } else {
138
98
  root.classList.remove('dark');
139
99
  localStorage.setItem('theme', 'light');
140
- themeIcon.innerHTML = `<svg xmlns='http://www.w3.org/2000/svg' class='h-5 w-5' fill='none' viewBox='0 0 24 24' stroke='currentColor'><path stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M12 3v1m0 16v1m8.66-13.66l-.71.71M4.05 19.07l-.71.71M21 12h-1M4 12H3m16.66 6.66l-.71-.71M4.05 4.93l-.71-.71M16 12a4 4 0 11-8 0 4 4 0 018 0z' /></svg>`;
141
- imgs.forEach(img => {
142
- img.classList.remove('dark');
143
- img.classList.add('light');
144
- });
100
+ if (themeIcon) themeIcon.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6"><path stroke-linecap="round" stroke-linejoin="round" d="M12 3v1.5M12 19.5V21M4.219 4.219l1.061 1.061M17.657 17.657l1.061 1.061M3 12h1.5M19.5 12H21M4.219 19.781l1.061-1.061M17.657 6.343l1.061-1.061M12 7.5A4.5 4.5 0 1012 16.5 4.5 4.5 0 0012 7.5z" /></svg>`;
145
101
  }
146
102
  }
147
103
 
148
- // Initial theme
149
- const savedTheme = localStorage.getItem('theme');
150
- setTheme(savedTheme === 'dark' || (!savedTheme && prefersDark));
151
-
104
+ // Theme Switcher
105
+ const themeToggle = document.getElementById('theme-toggle');
106
+ const themeIcon = document.getElementById('theme-icon');
107
+ // Force light theme on initial load
108
+ setTheme(false);
109
+ localStorage.setItem('theme', 'light');
152
110
  themeToggle.addEventListener('click', () => {
153
111
  setTheme(!root.classList.contains('dark'));
112
+ renderIllustrations();
154
113
  });
155
114
 
156
115
  // --- TABS ---
@@ -226,6 +185,64 @@ document.addEventListener('DOMContentLoaded', () => {
226
185
  renderIllustrations();
227
186
  };
228
187
 
188
+ // --- MODAL LOGIC ---
189
+ let illustrationDescriptions = {};
190
+ let descriptionsLoaded = false;
191
+ let descriptionsLoadError = false;
192
+ fetch('descriptions.json')
193
+ .then(res => res.json())
194
+ .then(data => { illustrationDescriptions = data; descriptionsLoaded = true; })
195
+ .catch(() => { illustrationDescriptions = {}; descriptionsLoaded = true; descriptionsLoadError = true; });
196
+
197
+ const modal = document.getElementById('illustration-modal');
198
+ const modalImage = document.getElementById('modal-image');
199
+ const modalIdInput = document.getElementById('modal-id-input');
200
+ const modalDescription = document.getElementById('modal-description');
201
+ const modalCode = document.getElementById('modal-code');
202
+ const modalCopyId = document.getElementById('modal-copy-id');
203
+ const modalCopyCode = document.getElementById('modal-copy-code');
204
+ const modalClose = document.getElementById('modal-close');
205
+ const modalCloseBottom = document.getElementById('modal-close-bottom');
206
+
207
+ function openModal(illustration) {
208
+ if (modalDescription) modalDescription.innerHTML = '';
209
+ if (!descriptionsLoaded) return;
210
+ const themeClass = root.classList.contains('dark') ? 'dark' : 'light';
211
+ let categoryClass = "";
212
+ let categoryFolder = "";
213
+ if (globalList.includes(illustration)) {
214
+ categoryClass = "global-illustration";
215
+ categoryFolder = "global";
216
+ } else if (dashboardsList.includes(illustration)) {
217
+ categoryClass = "dashboards-illustration";
218
+ categoryFolder = "dashboards";
219
+ }
220
+ const svgPath = `illustrations/${themeClass}/${categoryFolder}/${illustration}.svg`;
221
+ modalImage.innerHTML = `<span class=\"dot-illustration\"><img src=\"${svgPath}\" class=\"${illustration} ${themeClass} ${categoryClass}\" style=\"width:286px;height:286px;object-fit:contain;\"/></span>`;
222
+ modalIdInput.value = illustration;
223
+ const codeString = `<span class=\"dot-illustration\"><img src=\"${svgPath}\" class=\"${illustration} ${themeClass} ${categoryClass}\"/></span>`;
224
+ modalCode.value = codeString;
225
+ modal.classList.add('active');
226
+ modal.classList.remove('hidden');
227
+ }
228
+ function closeModal() {
229
+ modal.classList.remove('active');
230
+ modal.classList.add('hidden');
231
+ }
232
+ modalClose.addEventListener('click', closeModal);
233
+ modalCloseBottom.addEventListener('click', closeModal);
234
+ modal.addEventListener('click', (e) => { if (e.target === modal) closeModal(); });
235
+ document.addEventListener('keydown', (e) => { if (modal.classList.contains('active') && e.key === 'Escape') closeModal(); });
236
+ modalCopyId.addEventListener('click', () => {
237
+ navigator.clipboard.writeText(modalIdInput.value);
238
+ showToast('Copied ID: ' + modalIdInput.value);
239
+ });
240
+ modalCopyCode.addEventListener('click', () => {
241
+ navigator.clipboard.writeText(modalCode.value);
242
+ showToast('Copied code: ' + modalCode.value);
243
+ });
244
+
245
+ // --- ILLUSTRATION RENDERING ---
229
246
  function renderIllustrations() {
230
247
  const list = document.getElementById("illustration-list");
231
248
  list.innerHTML = "";
@@ -250,8 +267,15 @@ document.addEventListener('DOMContentLoaded', () => {
250
267
  const themeClass = root.classList.contains('dark') ? 'dark' : 'light';
251
268
  toShow.forEach(illustration => {
252
269
  let categoryClass = "";
253
- if (globalList.includes(illustration)) categoryClass = "global-illustration";
254
- else if (dashboardsList.includes(illustration)) categoryClass = "dashboards-illustration";
270
+ let categoryFolder = "";
271
+ if (globalList.includes(illustration)) {
272
+ categoryClass = "global-illustration";
273
+ categoryFolder = "global";
274
+ } else if (dashboardsList.includes(illustration)) {
275
+ categoryClass = "dashboards-illustration";
276
+ categoryFolder = "dashboards";
277
+ }
278
+ const svgPath = `illustrations/${themeClass}/${categoryFolder}/${illustration}.svg`;
255
279
  const isFav = favs.includes(illustration);
256
280
  const div = document.createElement("div");
257
281
  div.setAttribute("class", "copy-container relative group flex flex-col items-center justify-between bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-xl shadow-lg p-2 md:p-3 transition-transform duration-200 hover:scale-105 hover:shadow-2xl h-[302px] w-full justify-center");
@@ -263,7 +287,7 @@ document.addEventListener('DOMContentLoaded', () => {
263
287
  </button>
264
288
  <div class="flex-1 flex flex-col justify-center items-center">
265
289
  <span class="dot-illustration">
266
- <img src="./svgs/${illustration}.svg" class="${illustration} ${themeClass} ${categoryClass}"/>
290
+ <img src="${svgPath}" class="${illustration} ${themeClass} ${categoryClass}"/>
267
291
  </span>
268
292
  <span class="iconID block text-center text-base font-medium text-gray-800 dark:text-gray-200 my-2">${illustration}</span>
269
293
  </div>
@@ -277,10 +301,19 @@ document.addEventListener('DOMContentLoaded', () => {
277
301
  <span class="tooltiptext left-1/2 -translate-x-1/2 bottom-10 shadow-md">Copy Code</span>
278
302
  </button>
279
303
  </div>
280
- <pre class="codeBlock"><code class="codeBlock"><span class="dot-illustration"><img src="./svgs/${illustration}.svg" class="${illustration} ${themeClass} ${categoryClass}"/></span></code></pre>
304
+ <pre class="codeBlock"><code class="codeBlock"><span class="dot-illustration"><img src="${svgPath}" class="${illustration} ${themeClass} ${categoryClass}"/></span></code></pre>
281
305
  `;
282
306
  list.appendChild(div);
283
307
  });
308
+ // Attach modal click handler to each card
309
+ document.querySelectorAll('.copy-container').forEach(card => {
310
+ card.addEventListener('click', function(e) {
311
+ if (e.target.closest('button')) return;
312
+ if (!descriptionsLoaded) return; // Wait for descriptions
313
+ const id = this.querySelector('.iconID')?.textContent;
314
+ if (id) openModal(id);
315
+ });
316
+ });
284
317
  }
285
318
 
286
319
  // Search input
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@digital-ai/dot-illustrations",
3
- "version": "2.0.22",
3
+ "version": "2.0.24",
4
4
  "description": "A central place for the design team to keep illustrations and for dev teams to find them.",
5
5
  "main": "./index.css",
6
6
  "scripts": {