@dodlhuat/basix 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. package/README.md +1 -1
  2. package/css/accordion.scss +31 -22
  3. package/css/alert.scss +79 -27
  4. package/css/button.scss +151 -102
  5. package/css/card.scss +11 -12
  6. package/css/carousel.scss +123 -87
  7. package/css/chart.scss +9 -11
  8. package/css/chat-bubbles.scss +2 -2
  9. package/css/checkbox.scss +72 -55
  10. package/css/chips.scss +52 -52
  11. package/css/code-viewer.scss +73 -98
  12. package/css/datepicker.scss +20 -0
  13. package/css/dropdown.scss +151 -137
  14. package/css/editor.scss +9 -6
  15. package/css/file-uploader.scss +187 -195
  16. package/css/flyout-menu.scss +20 -13
  17. package/css/form.scss +168 -115
  18. package/css/gallery.scss +62 -63
  19. package/css/grid.scss +0 -1
  20. package/css/modal.scss +117 -72
  21. package/css/placeholder.scss +17 -12
  22. package/css/properties.scss +6 -0
  23. package/css/push-menu.scss +70 -23
  24. package/css/radiobutton.scss +86 -64
  25. package/css/range-slider.scss +136 -0
  26. package/css/scrollbar.scss +69 -69
  27. package/css/spinner.scss +41 -66
  28. package/css/style.css +4351 -3735
  29. package/css/style.css.map +1 -1
  30. package/css/style.scss +2 -1
  31. package/css/switch.scss +43 -42
  32. package/css/table.scss +61 -40
  33. package/css/tabs.scss +12 -7
  34. package/css/timeline.scss +72 -69
  35. package/css/timepicker.scss +151 -72
  36. package/css/toast.scss +49 -48
  37. package/css/tooltip.scss +112 -122
  38. package/css/tree.scss +135 -192
  39. package/css/typography.scss +70 -9
  40. package/css/virtual-dropdown.scss +201 -142
  41. package/js/carousel.js +45 -18
  42. package/js/carousel.ts +217 -173
  43. package/js/datepicker.js +505 -497
  44. package/js/datepicker.ts +9 -0
  45. package/js/editor.js +398 -415
  46. package/js/file-uploader.js +142 -128
  47. package/js/file-uploader.ts +364 -350
  48. package/js/gallery.js +22 -15
  49. package/js/gallery.ts +17 -12
  50. package/js/index.js +718 -720
  51. package/js/index.ts +7 -8
  52. package/js/push-menu.js +113 -101
  53. package/js/push-menu.ts +17 -2
  54. package/js/range-slider.js +26 -0
  55. package/js/range-slider.ts +33 -0
  56. package/js/timepicker.js +144 -98
  57. package/js/timepicker.ts +194 -131
  58. package/js/tree.js +56 -28
  59. package/js/tree.ts +239 -218
  60. package/package.json +1 -1
  61. package/css/accordion.css +0 -109
  62. package/css/accordion.css.map +0 -1
  63. package/css/alert.css +0 -57
  64. package/css/alert.css.map +0 -1
  65. package/css/button.css +0 -69
  66. package/css/button.css.map +0 -1
  67. package/css/card.css +0 -144
  68. package/css/card.css.map +0 -1
  69. package/css/carousel.css +0 -118
  70. package/css/carousel.css.map +0 -1
  71. package/css/chart.css +0 -159
  72. package/css/chart.css.map +0 -1
  73. package/css/chat-bubbles.css +0 -97
  74. package/css/chat-bubbles.css.map +0 -1
  75. package/css/checkbox.css +0 -77
  76. package/css/checkbox.css.map +0 -1
  77. package/css/chips.css +0 -72
  78. package/css/chips.css.map +0 -1
  79. package/css/code-viewer.css +0 -97
  80. package/css/code-viewer.css.map +0 -1
  81. package/css/colors.css +0 -63
  82. package/css/colors.css.map +0 -1
  83. package/css/datepicker.css +0 -264
  84. package/css/datepicker.css.map +0 -1
  85. package/css/defaults.css +0 -118
  86. package/css/defaults.css.map +0 -1
  87. package/css/dropdown.css +0 -146
  88. package/css/dropdown.css.map +0 -1
  89. package/css/editor.css +0 -413
  90. package/css/file-uploader.css +0 -194
  91. package/css/file-uploader.css.map +0 -1
  92. package/css/flyout-menu.css +0 -345
  93. package/css/flyout-menu.css.map +0 -1
  94. package/css/form-builder.css +0 -9
  95. package/css/form-builder.css.map +0 -1
  96. package/css/form-builder.scss +0 -11
  97. package/css/form.css +0 -130
  98. package/css/form.css.map +0 -1
  99. package/css/gallery.css +0 -91
  100. package/css/gallery.css.map +0 -1
  101. package/css/grid.css +0 -44
  102. package/css/grid.css.map +0 -1
  103. package/css/icons.css +0 -327
  104. package/css/icons.css.map +0 -1
  105. package/css/modal.css +0 -97
  106. package/css/modal.css.map +0 -1
  107. package/css/parameters.css +0 -1
  108. package/css/parameters.css.map +0 -1
  109. package/css/placeholder.css +0 -50
  110. package/css/placeholder.css.map +0 -1
  111. package/css/progress.css +0 -51
  112. package/css/progress.css.map +0 -1
  113. package/css/properties.css +0 -31
  114. package/css/properties.css.map +0 -1
  115. package/css/push-menu.css +0 -145
  116. package/css/push-menu.css.map +0 -1
  117. package/css/radiobutton.css +0 -91
  118. package/css/radiobutton.css.map +0 -1
  119. package/css/reset.css +0 -46
  120. package/css/reset.css.map +0 -1
  121. package/css/scrollbar.css +0 -91
  122. package/css/scrollbar.css.map +0 -1
  123. package/css/spinner.css +0 -118
  124. package/css/spinner.css.map +0 -1
  125. package/css/switch.css +0 -66
  126. package/css/switch.css.map +0 -1
  127. package/css/table.css +0 -201
  128. package/css/table.css.map +0 -1
  129. package/css/tabs.css +0 -135
  130. package/css/tabs.css.map +0 -1
  131. package/css/timeline.css +0 -69
  132. package/css/timeline.css.map +0 -1
  133. package/css/toast.css +0 -98
  134. package/css/toast.css.map +0 -1
  135. package/css/tooltip.css +0 -151
  136. package/css/tooltip.css.map +0 -1
  137. package/css/tree.css +0 -199
  138. package/css/tree.css.map +0 -1
  139. package/css/typography.css +0 -137
  140. package/css/typography.css.map +0 -1
  141. package/css/virtual-dropdown.css +0 -149
  142. package/css/virtual-dropdown.css.map +0 -1
package/js/index.js CHANGED
@@ -1,720 +1,718 @@
1
- import { utils } from "./utils.js";
2
- import { Scrollbar } from "./scrollbar.js";
3
- import { Modal } from "./modal.js";
4
- import { PushMenu } from "./push-menu.js";
5
- import { Toast } from "./toast.js";
6
- import { DatePicker } from "./datepicker.js";
7
- import { Theme } from "./theme.js";
8
- import { Table } from "./table.js";
9
- import { FlyoutMenu } from "./flyout-menu.js";
10
- import { Tabs } from "./tabs.js";
11
- import { Carousel } from "./carousel.js";
12
- import { CodeViewer } from "./code-viewer.js";
13
- import { FileUploader } from "./file-uploader.js";
14
- import { TreeComponent, TreeNode } from "./tree.js";
15
- import { MasonryGallery } from "./gallery.js";
16
- import { Tooltip } from "./tooltip.js";
17
- import { Dropdown } from "./dropdown.js";
18
- import { VirtualDropdown } from "./virtual-dropdown.js";
19
- import { TimeSpanPicker } from "./timepicker.js";
20
- // Generate sample table data
21
- const generateData = (count) => {
22
- const data = [];
23
- const firstNames = [
24
- "John",
25
- "Jane",
26
- "Mike",
27
- "Sarah",
28
- "Robert",
29
- "Emily",
30
- "David",
31
- "Emma",
32
- "James",
33
- "Olivia",
34
- ];
35
- const lastNames = [
36
- "Smith",
37
- "Johnson",
38
- "Williams",
39
- "Brown",
40
- "Jones",
41
- "Garcia",
42
- "Miller",
43
- "Davis",
44
- "Rodriguez",
45
- "Martinez",
46
- ];
47
- const roles = ["Admin", "User", "Editor", "Viewer", "Manager", "Developer"];
48
- const statuses = ["Active", "Inactive", "Pending", "Banned"];
49
- for (let i = 1; i <= count; i++) {
50
- const firstName = firstNames[Math.floor(Math.random() * firstNames.length)];
51
- const lastName = lastNames[Math.floor(Math.random() * lastNames.length)];
52
- const role = roles[Math.floor(Math.random() * roles.length)];
53
- const status = statuses[Math.floor(Math.random() * statuses.length)];
54
- const lastLoginDate = new Date(Date.now() - Math.floor(Math.random() * 10000000000));
55
- data.push({
56
- id: i,
57
- name: `${firstName} ${lastName}`,
58
- email: `user${i}@example.com`,
59
- role,
60
- status,
61
- lastLogin: lastLoginDate.toLocaleDateString(),
62
- });
63
- }
64
- return data;
65
- };
66
- // Initialize all components when DOM is ready
67
- utils.ready(() => {
68
- // Initialize scrollbars
69
- Scrollbar.initAll(".scroll-container");
70
- // Initialize theme
71
- Theme.init();
72
- // Initialize horizontal tabs
73
- const horizontalTabs = new Tabs(".horizontal", {
74
- layout: "horizontal",
75
- });
76
- // Initialize vertical tabs
77
- const verticalTabs = new Tabs(".vertical", {
78
- layout: "vertical",
79
- });
80
- // Initialize carousel
81
- const carousel = new Carousel("#carouselIdHere", {
82
- loop: true,
83
- });
84
- // Initialize advanced table with data
85
- const columns = [
86
- { key: "id", label: "ID" },
87
- { key: "name", label: "Name" },
88
- { key: "email", label: "Email" },
89
- { key: "role", label: "Role" },
90
- { key: "status", label: "Status" },
91
- { key: "lastLogin", label: "Last Login" },
92
- ];
93
- const tableData = generateData(50);
94
- new Table("#demo-table-js", {
95
- data: tableData,
96
- columns: columns,
97
- pageSize: 10,
98
- });
99
- // Initialize modal
100
- const modalTrigger = document.querySelector(".show-modal");
101
- if (modalTrigger) {
102
- modalTrigger.addEventListener("click", () => {
103
- const buttons = '<div class="buttons"><button class="button-light">Close</button>&nbsp;<button>Save Changes</button></div>';
104
- const modal = new Modal("bluffi", "<strong>blaffi</strong>", buttons, true, "default");
105
- modal.show();
106
- console.warn("Buttons have no bound listeners");
107
- });
108
- }
109
- // Initialize toast
110
- const toastTrigger = document.querySelector(".show-toast");
111
- if (toastTrigger) {
112
- toastTrigger.addEventListener("click", () => {
113
- const toast = new Toast("some content. maybe even more text in here!", "some header", "success", true);
114
- toast.show(3000);
115
- });
116
- }
117
- // Initialize push menu
118
- PushMenu.init();
119
- // Initialize flyout menu
120
- const menu = new FlyoutMenu({
121
- direction: "right",
122
- triggerSelector: ".trigger-flyout-menu",
123
- });
124
- // Flyout menu controls: Switch direction
125
- const directionBtns = document.querySelectorAll(".flyout-controls > button");
126
- directionBtns.forEach((btn) => {
127
- btn.addEventListener("click", () => {
128
- // Remove active class from all buttons
129
- directionBtns.forEach((b) => b.classList.remove("active"));
130
- // Add active class to clicked button
131
- btn.classList.add("active");
132
- // Update menu direction
133
- const direction = btn.dataset.direction;
134
- if (direction) {
135
- menu.setDirection(direction);
136
- }
137
- });
138
- });
139
- new DatePicker("#datepicker-single", {
140
- mode: "single",
141
- onSelect: (date) => {
142
- console.log("Single selected:", date);
143
- },
144
- });
145
- new DatePicker("#datepicker-time", {
146
- mode: "single",
147
- timePicker: true,
148
- onSelect: (date) => {
149
- console.log("Single selected:", date);
150
- },
151
- });
152
- new DatePicker("#datepicker-range", {
153
- mode: "range",
154
- onSelect: (range) => {
155
- console.log("Range selected:", range);
156
- },
157
- });
158
- new DatePicker("#datepicker-localized", {
159
- mode: "single",
160
- startDay: 1, // Monday
161
- locales: {
162
- days: ["Do", "Lu", "Ma", "Mi", "Ju", "Vi", "Sa"],
163
- months: [
164
- "Enero",
165
- "Febrero",
166
- "Marzo",
167
- "Abril",
168
- "Mayo",
169
- "Junio",
170
- "Julio",
171
- "Agosto",
172
- "Septiembre",
173
- "Octubre",
174
- "Noviembre",
175
- "Diciembre",
176
- ],
177
- },
178
- format: (date) => {
179
- return date.toLocaleDateString("es-ES", {
180
- weekday: "long",
181
- year: "numeric",
182
- month: "long",
183
- day: "numeric",
184
- });
185
- },
186
- onSelect: (date) => {
187
- console.log("Localized selected:", date);
188
- },
189
- });
190
- // Initialize code viewer with usage example
191
- const usageTabs = `new Tabs('.horizontal', {
192
- layout: 'horizontal',
193
- defaultTab: 0
194
- });`;
195
- new CodeViewer("#usage-tabs", usageTabs, "js");
196
- // Initialize file uploader
197
- const uploaderElement = document.querySelector(".uploader-content");
198
- if (uploaderElement) {
199
- new FileUploader(uploaderElement);
200
- }
201
- const sampleData = [
202
- new TreeNode("Documents", "folder", [
203
- new TreeNode("Work", "folder", [
204
- new TreeNode("presentation.pptx", "file"),
205
- new TreeNode("report.docx", "file"),
206
- new TreeNode("budget.xlsx", "file"),
207
- ]),
208
- new TreeNode("Personal", "folder", [
209
- new TreeNode("resume.pdf", "file"),
210
- new TreeNode("vacation-photos", "folder", [
211
- new TreeNode("beach.jpg", "file"),
212
- new TreeNode("mountain.jpg", "file"),
213
- ]),
214
- ]),
215
- ]),
216
- new TreeNode("Projects", "folder", [
217
- new TreeNode("website", "folder", [
218
- new TreeNode("index.html", "file"),
219
- new TreeNode("styles.css", "file"),
220
- new TreeNode("script.js", "file"),
221
- ]),
222
- new TreeNode("app", "folder", [
223
- new TreeNode("src", "folder", [
224
- new TreeNode("main.js", "file"),
225
- new TreeNode("utils.js", "file"),
226
- ]),
227
- new TreeNode("package.json", "file"),
228
- ]),
229
- ]),
230
- new TreeNode("Downloads", "folder", [
231
- new TreeNode("installer.exe", "file"),
232
- new TreeNode("readme.txt", "file"),
233
- ]),
234
- new TreeNode("README.md", "file"),
235
- ];
236
- const tree = new TreeComponent("#tree-root", sampleData);
237
- const batchSize = 12;
238
- let indexNumber = 1;
239
- const gallery = new MasonryGallery("gallery", {
240
- minColumnWidth: 300,
241
- fetchFunction: new Promise((resolve) => {
242
- setTimeout(() => {
243
- const images = [];
244
- for (let i = 0; i < batchSize; i++) {
245
- const width = 400;
246
- const height = Math.floor(Math.random() * 301) + 300; // 300-600
247
- const id = Math.floor(Math.random() * 1000);
248
- const imageIndex = indexNumber * batchSize + i;
249
- images.push({
250
- src: `https://picsum.photos/${width}/${height}?random=${imageIndex}`,
251
- title: `Image ${imageIndex + 1}`,
252
- desc: `A random caption for image ${id}`,
253
- });
254
- }
255
- indexNumber++;
256
- resolve(images);
257
- }, 800);
258
- }),
259
- });
260
- const dropdown = new Dropdown("#myDropdown");
261
- const dropdownElement = document.querySelector("#myDropdown");
262
- dropdownElement?.addEventListener("dropdown-select", ((event) => {
263
- const { text, element } = event.detail;
264
- console.log("User selected:", text);
265
- console.log("Selected element:", element);
266
- }));
267
- const generateItems = (count, prefix) => {
268
- return Array.from({ length: count }, (_, i) => ({
269
- label: `${prefix} Item ${i + 1}`,
270
- value: `${prefix.toLowerCase()}_${i + 1}`,
271
- }));
272
- };
273
- const bigData = generateItems(10000, "Option");
274
- const smallData = generateItems(50, "Choice");
275
- const singleDropdown = new VirtualDropdown({
276
- container: "#dropdown-single",
277
- options: bigData,
278
- searchable: true,
279
- placeholder: "Search 10k items...",
280
- renderLimit: 15,
281
- onSelect: (val) => {
282
- console.log("Single Select:", val);
283
- },
284
- });
285
- const multiDropdown = new VirtualDropdown({
286
- container: "#dropdown-multi",
287
- options: smallData,
288
- searchable: true,
289
- multiSelect: true,
290
- placeholder: "Choose multiple...",
291
- renderLimit: 10,
292
- onSelect: (vals) => {
293
- console.log("Multi Select:", vals);
294
- },
295
- });
296
- Tooltip.initializeAll();
297
- const timeSpanPicker = new TimeSpanPicker('timespan-1', {
298
- onChange: (start, end) => {
299
- console.log(`Start: ${start}, Ende: ${end}`);
300
- }
301
- });
302
- new CodeViewer("#usage-text-input", `<label for="text-input-demo">Text Input</label>
303
- <input type="text" id="text-input-demo"/>`, "html");
304
- new CodeViewer("#usage-textarea", `<label for="textarea-demo">Text Area</label>
305
- <textarea id="textarea-demo"></textarea>`, "html");
306
- new CodeViewer("#usage-checkbox-demo", `<input class="styled-checkbox"
307
- id="checkbox-1"
308
- type="checkbox"
309
- value="1"
310
- />
311
- <label for="checkbox-1">Checkbox</label>`, "html");
312
- });
313
- new CodeViewer("#usage-radiobutton-demo", `<label class="radio-button-container">Three
314
- <input type="radio" name="radio"/>
315
- <span class="checkmark"></span>
316
- </label>`, "html");
317
- new CodeViewer("#usage-switch-demo", `<div class="switch">
318
- <input type="checkbox" id="switch"/><label for="switch">Toggle</label>
319
- </div>`, "html");
320
- new CodeViewer("#usage-slider-demo", `<label for="range-slider" class="hidden">Slider</label>
321
- <input
322
- type="range"
323
- min="1"
324
- max="100"
325
- value="50"
326
- id="range-slider-demo"
327
- />`, "html");
328
- new CodeViewer("#usage-pushmenu-control-demo", `<div class="open-menu">
329
- <div class="navigation-controls">
330
- <input type="checkbox" id="menu-navigation" class="navigation"/>
331
- <label for="menu-navigation">
332
- <span class="icon icon-menu"></span>
333
- </label>
334
- </div>
335
- </div>`, "html");
336
- new CodeViewer("#usage-pushmenu-demo", `<nav class="push-menu">
337
- <ul>
338
- <li>
339
- <a onclick="window.Scroll.to('#grid')">Grid</a>
340
- </li>
341
- <li>
342
- <a onclick="window.Scroll.to('#typography')">Typography</a>
343
- </li>
344
- </ul>
345
- </nav>`, "html");
346
- new CodeViewer("#usage-pushmenu-script-demo", `PushMenu.init();`, "js");
347
- new CodeViewer("#usage-flyout-script-demo", `const menu = new FlyoutMenu({
348
- direction: "right",
349
- triggerSelector: ".trigger-flyout-menu",
350
- });`, "js");
351
- new CodeViewer("#usage-flyout-demo", `<div class="flyout-overlay" id="flyoutOverlay"></div>
352
- <div class="flyout-menu" id="flyoutMenu">
353
- <ul>
354
- <li><a href="#">Home</a></li>
355
- <li>
356
- About
357
- <ul>
358
- <li><a href="#">Our Story</a></li>
359
- <li><a href="#">Team</a></li>
360
- <li><a href="#">Careers</a></li>
361
- </ul>
362
- </li>
363
- <li>
364
- Services
365
- <ul>
366
- <li>
367
- Web Design
368
- <ul>
369
- <li><a href="#">eCommerce</a></li>
370
- <li><a href="#">Landing Pages</a></li>
371
- <li><a href="#">Portfolios</a></li>
372
- </ul>
373
- </li>
374
- <li><a href="#">Development</a></li>
375
- <li><a href="#">SEO</a></li>
376
- </ul>
377
- </li>
378
- <li><a href="#">Portfolio</a></li>
379
- <li><a href="#">Contact</a></li>
380
- </ul>
381
- </div>`, "html");
382
- new CodeViewer("#usage-dropdown-menu-demo", `<div class="dropdown-container" id="myDropdown">
383
- <button class="dropdown-trigger">Select Option</button>
384
- <ul class="dropdown-menu">
385
- <li>
386
- <div class="dropdown-item">Profile</div>
387
- </li>
388
- <li>
389
- <div class="dropdown-item">Settings</div>
390
- <ul>
391
- <li>
392
- <div class="dropdown-item">Account</div>
393
- </li>
394
- <li>
395
- <div class="dropdown-item">Privacy</div>
396
- <ul>
397
- <li>
398
- <div class="dropdown-item">Public</div>
399
- </li>
400
- <li>
401
- <div class="dropdown-item">Private</div>
402
- </li>
403
- <li>
404
- <div class="dropdown-item">Friends Only</div>
405
- </li>
406
- </ul>
407
- </li>
408
- <li>
409
- <div class="dropdown-item">Notifications</div>
410
- </li>
411
- </ul>
412
- </li>
413
- <li>
414
- <div class="dropdown-item">Help</div>
415
- </li>
416
- <li>
417
- <div class="dropdown-item">Logout</div>
418
- </li>
419
- </ul>
420
- </div>`, "html");
421
- new CodeViewer("#usage-dropdown-menu-js-demo", `const dropdown = new Dropdown("#myDropdown");
422
- const dropdownElement = document.querySelector("#myDropdown");
423
- dropdownElement?.addEventListener("dropdown-select", ((
424
- event: CustomEvent<DropdownSelectDetail>,
425
- ) => {
426
- const { text, element } = event.detail;
427
- console.log("User selected:", text);
428
- console.log("Selected element:", element);
429
- }) as EventListener);`, "js");
430
- new CodeViewer("#usage-modal-demo", `const modal = new Modal(
431
- "content",
432
- "<strong>header</strong>",
433
- "controls",
434
- true,
435
- "default",
436
- );
437
- modal.show();`, "js");
438
- new CodeViewer("#usage-toast-demo", `const toast = new Toast(
439
- "some content. maybe even more text in here!",
440
- "some header",
441
- "success",
442
- true,
443
- );
444
- toast.show(3000);`, "js");
445
- new CodeViewer("#usage-tooltip-demo", `<button class="tooltip-trigger" data-tooltip="This is a simple tooltip">
446
- Simple Tooltip
447
- </button>`, "html");
448
- new CodeViewer("#usage-tooltip-js-demo", `Tooltip.initializeAll();`, "js");
449
- new CodeViewer("#usage-spinner-demo", `<div class="spinner"></div>`, "html");
450
- new CodeViewer("#usage-loading-demo", `<div class="loading"></div>`, "html");
451
- new CodeViewer("#usage-alerts-demo", `<div class="alert alert-default">
452
- <strong>Default:</strong> This is a default alert message.
453
- </div>`, "html");
454
- new CodeViewer("#usage-chips-demo", `<div class="chips">
455
- <div class="chip">Example Chip</div>
456
- <div class="chip clickable">Example Chip with hover</div>
457
- <div class="chip closeable">
458
- Example Chip with closure
459
- <button class="close">
460
- <span class="icon icon-close"></span>
461
- </button>
462
- </div>
463
- </div>`, "html");
464
- new CodeViewer("#usage-accordion-demo", `<div class="accordion">
465
- <div class="accordion-item">
466
- <input
467
- type="radio"
468
- name="accordion"
469
- id="acc1"
470
- class="accordion-input"
471
- checked
472
- />
473
- <label for="acc1" class="accordion-label"> What is this? </label>
474
- <div class="accordion-content">
475
- <div class="accordion-body">
476
- <div>
477
- <p>
478
- This is a pure CSS accordion component. It uses the "Radio
479
- Button Hack" to manage state without a single line of
480
- JavaScript.
481
- </p>
482
- </div>
483
- </div>
484
- </div>
485
- </div>
486
- <div class="accordion-item">
487
- <input
488
- type="radio"
489
- name="accordion"
490
- id="acc2"
491
- class="accordion-input"
492
- />
493
- <label for="acc2" class="accordion-label"> How does it work? </label>
494
- <div class="accordion-content">
495
- <div class="accordion-body">
496
- <div>
497
- <p>It links label elements to hidden radio buttons.</p>
498
- </div>
499
- </div>
500
- </div>
501
- </div>
502
- <div class="accordion-item">
503
- <input
504
- type="radio"
505
- name="accordion"
506
- id="acc3"
507
- class="accordion-input"
508
- />
509
- <label for="acc3" class="accordion-label"> Is it accessible? </label>
510
- <div class="accordion-content">
511
- <div class="accordion-body">
512
- <div>
513
- <p>
514
- It's reasonably accessible as it uses semantic form elements.
515
- Users can tab through the headers (radio inputs) and select
516
- them with the keyboard. However, for full ARIA support, a
517
- small amount of JS is usually recommended to manage
518
- aria-expanded attributes.
519
- </p>
520
- </div>
521
- </div>
522
- </div>
523
- </div>
524
- </div>`, "html");
525
- new CodeViewer("#usage-timeline-demo", `<div class="timeline">
526
- <div class="timeline-item active">
527
- <div class="timeline-content">
528
- <span class="timeline-date">October 12, 2023</span>
529
- <h3 class="timeline-title">Project Kickoff</h3>
530
- <p class="timeline-body">
531
- Initial meeting with shareholders to discuss the scope and
532
- requirements of the project. Team roles were assigned and the
533
- roadmap was drafted.
534
- </p>
535
- </div>
536
- </div>
537
- <div class="timeline-item">
538
- <div class="timeline-content">
539
- <span class="timeline-date">January 15, 2024</span>
540
- <h3 class="timeline-title">Beta Launch</h3>
541
- <p class="timeline-body">
542
- Opened the platform to a closed beta group of 500 users. Collected
543
- feedback regarding the onboarding flow and notification settings.
544
- </p>
545
- </div>
546
- </div>
547
- </div>`, "html");
548
- new CodeViewer("#usage-progress-bar-demo", `<div class="progress-bar">
549
- <div class="progress" style="height: 24px; width: 50%"></div>
550
- </div>`, "html");
551
- new CodeViewer("#usage-placeholder-demo", `<span class="placeholder w-6">`, "html");
552
- new CodeViewer("#usage-table-demo", `const columns: TableColumn[] = [
553
- { key: "id", label: "ID" },
554
- { key: "name", label: "Name" },
555
- ];
556
- const tableData: TableRow[] = [
557
- { id: 1, name: "John Doe" },
558
- { id: 2, name: "Jane Smith" },
559
- { id: 3, name: "Mike Johnson" },
560
- ];
561
- new Table("#demo-table-js", {
562
- data: tableData,
563
- columns: columns,
564
- pageSize: 10,
565
- });
566
-
567
- // Initialize basic table from html data
568
- new Table("#demo-table", { pageSize: 5 });`, "js");
569
- new CodeViewer("#usage-datepicker-html-demo", `<label for="datepicker-range">Datepicker Range</label>
570
- <input
571
- type="text"
572
- id="datepicker-range"
573
- class="datepicker-input"
574
- placeholder="Select a date range"
575
- readonly
576
- />`, "html");
577
- new CodeViewer("#usage-datepicker-js-demo", `new DatePicker("#datepicker-single", {
578
- mode: "single",
579
- onSelect: (date) => {
580
- console.log("Single selected:", date);
581
- },
582
- });`, "js");
583
- new CodeViewer("#usage-tree-demo-html", `<ul id="tree-root" class="tree"></ul>`, "html");
584
- new CodeViewer("#usage-tree-demo-js", `const sampleData: TreeNode[] = [
585
- new TreeNode("Documents", "folder", [
586
- new TreeNode("Work", "folder", [
587
- new TreeNode("presentation.pptx", "file"),
588
- new TreeNode("report.docx", "file"),
589
- new TreeNode("budget.xlsx", "file"),
590
- ]),
591
- new TreeNode("Personal", "folder", [
592
- new TreeNode("resume.pdf", "file"),
593
- new TreeNode("vacation-photos", "folder", [
594
- new TreeNode("beach.jpg", "file"),
595
- new TreeNode("mountain.jpg", "file"),
596
- ]),
597
- ]),
598
- ]),
599
- ];
600
- const tree = new TreeComponent("#tree-root", sampleData);`, "js");
601
- new CodeViewer("#usage-file-uploader-demo", `<div class="uploader-content">
602
- <div class="header">
603
- <h2>Upload Files</h2>
604
- <p>Select or drag files to upload</p>
605
- </div>
606
- <div id="drop-zone" class="drop-zone">
607
- <input type="file" id="file-input" multiple hidden/>
608
- <div class="drop-zone-content">
609
- <div class="icon-container">
610
- <svg
611
- xmlns="http://www.w3.org/2000/svg"
612
- width="24"
613
- height="24"
614
- viewBox="0 0 24 24"
615
- fill="none"
616
- stroke="currentColor"
617
- stroke-width="2"
618
- stroke-linecap="round"
619
- stroke-linejoin="round"
620
- class="upload-icon"
621
- >
622
- <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
623
- <polyline points="17 8 12 3 7 8"></polyline>
624
- <line x1="12" y1="3" x2="12" y2="15"></line>
625
- </svg>
626
- </div>
627
- <p class="primary-text">Click to upload or drag and drop</p>
628
- <p class="secondary-text">
629
- SVG, PNG, JPG or GIF (max. 800x400px)
630
- </p>
631
- </div>
632
- </div>
633
-
634
- <div id="file-list" class="file-list"></div>
635
-
636
- <div class="actions">
637
- <button id="upload-btn" disabled>Upload Files</button>
638
- </div>
639
- </div>`, "html");
640
- new CodeViewer("#usage-file-uploader-demo-js", `const uploaderElement =
641
- document.querySelector<HTMLElement>(".uploader-content");
642
- if (uploaderElement) {
643
- new FileUploader(uploaderElement);
644
- }`, "js");
645
- new CodeViewer("#usage-virtual-dropdown-demo-html", `<div class="virtual-dropdown">
646
- <h2>1. Searchable Single Select (10,000 items)</h2>
647
- <p>
648
- This list uses virtual scrolling to handle 10k items efficiently.
649
- </p>
650
- <div id="dropdown-single"></div>
651
- </div>`, "html");
652
- new CodeViewer("#usage-virtual-dropdown-demo-js", `const singleDropdown = new VirtualDropdown({
653
- container: "#dropdown-single",
654
- options: bigData,
655
- searchable: true,
656
- placeholder: "Search 10k items...",
657
- renderLimit: 15,
658
- onSelect: (val) => {
659
- console.log("Single Select:", val);
660
- },
661
- });`, "js");
662
- new CodeViewer("#usage-scrollbar-demo", `Scrollbar.initAll(".scroll-container");`, "js");
663
- new CodeViewer("#usage-theme-demo", `Theme.init();`, "js");
664
- new CodeViewer("#usage-scroll-demo", `window.Scroll.to('#grid')`, "js");
665
- new CodeViewer("#usage-chat-demo-html", `<div class="chat-container">
666
- <div class="message message-incoming">
667
- Hi there! How are you doing today?
668
- <span class="message-meta">10:42 AM</span>
669
- </div>
670
- <div class="message message-outgoing">
671
- I'm doing great, thanks! Just working on some new CSS
672
- components.<br/>And other stuff.
673
- <span class="message-meta">10:43 AM</span>
674
- </div>
675
- <div class="message message-outgoing">
676
- Trying to make a simple chat UI.
677
- <span class="message-meta">10:43 AM</span>
678
- </div>
679
- <div class="message message-incoming">
680
- That sounds cool!
681
- <span class="message-meta">10:45 AM</span>
682
- </div>
683
- </div>`, "html");
684
- new CodeViewer("#usage-carousel-demo-html", `<div class="carousel" id="carouselIdHere">
685
- <div>Slide 1</div>
686
- <div>Slide 2</div>
687
- <div>Slide 3</div>
688
- <div>Slide 4</div>
689
- </div>`, "html");
690
- new CodeViewer("#usage-carousel-demo-js", `const carousel = new Carousel("#carouselIdHere", {
691
- loop: true,
692
- });`, "js");
693
- new CodeViewer("#usage-gallery-demo-html", `<div id="gallery" class="masonry-container"></div>
694
- <div class="loader hidden">
695
- <div class="spinner"></div>
696
- </div>`, "html");
697
- new CodeViewer("#usage-gallery-demo-js", `const gallery = new MasonryGallery("gallery", {
698
- minColumnWidth: 300,
699
- fetchFunction: new Promise((resolve) => {
700
- setTimeout(() => {
701
- const images: ImageData[] = [];
702
-
703
- for (let i = 0; i < batchSize; i++) {
704
- const width = 400;
705
- const height = Math.floor(Math.random() * 301) + 300;
706
- const id = Math.floor(Math.random() * 1000);
707
- const imageIndex = indexNumber * batchSize + i;
708
-
709
- images.push({
710
- src: \`https://picsum.photos/$\{width}/$\{height}?random=$\{imageIndex}\`,
711
- title: \`Image $\{imageIndex + 1}\`,
712
- desc: \`A random caption for image $\{id}\`,
713
- });
714
- }
715
-
716
- indexNumber++;
717
- resolve(images);
718
- }, 800);
719
- }),
720
- });`, "js");
1
+ import { utils } from "./utils.js";
2
+ import { Scrollbar } from "./scrollbar.js";
3
+ import { Modal } from "./modal.js";
4
+ import { PushMenu } from "./push-menu.js";
5
+ import { Toast } from "./toast.js";
6
+ import { DatePicker } from "./datepicker.js";
7
+ import { Theme } from "./theme.js";
8
+ import { Table } from "./table.js";
9
+ import { FlyoutMenu } from "./flyout-menu.js";
10
+ import { Tabs } from "./tabs.js";
11
+ import { Carousel } from "./carousel.js";
12
+ import { CodeViewer } from "./code-viewer.js";
13
+ import { FileUploader } from "./file-uploader.js";
14
+ import { TreeComponent, TreeNode } from "./tree.js";
15
+ import { MasonryGallery } from "./gallery.js";
16
+ import { Tooltip } from "./tooltip.js";
17
+ import { Dropdown } from "./dropdown.js";
18
+ import { VirtualDropdown } from "./virtual-dropdown.js";
19
+ import { TimeSpanPicker } from "./timepicker.js";
20
+ import { RangeSlider } from "./range-slider.js";
21
+ // Generate sample table data
22
+ const generateData = (count) => {
23
+ const data = [];
24
+ const firstNames = [
25
+ "John",
26
+ "Jane",
27
+ "Mike",
28
+ "Sarah",
29
+ "Robert",
30
+ "Emily",
31
+ "David",
32
+ "Emma",
33
+ "James",
34
+ "Olivia",
35
+ ];
36
+ const lastNames = [
37
+ "Smith",
38
+ "Johnson",
39
+ "Williams",
40
+ "Brown",
41
+ "Jones",
42
+ "Garcia",
43
+ "Miller",
44
+ "Davis",
45
+ "Rodriguez",
46
+ "Martinez",
47
+ ];
48
+ const roles = ["Admin", "User", "Editor", "Viewer", "Manager", "Developer"];
49
+ const statuses = ["Active", "Inactive", "Pending", "Banned"];
50
+ for (let i = 1; i <= count; i++) {
51
+ const firstName = firstNames[Math.floor(Math.random() * firstNames.length)];
52
+ const lastName = lastNames[Math.floor(Math.random() * lastNames.length)];
53
+ const role = roles[Math.floor(Math.random() * roles.length)];
54
+ const status = statuses[Math.floor(Math.random() * statuses.length)];
55
+ const lastLoginDate = new Date(Date.now() - Math.floor(Math.random() * 10000000000));
56
+ data.push({
57
+ id: i,
58
+ name: `${firstName} ${lastName}`,
59
+ email: `user${i}@example.com`,
60
+ role,
61
+ status,
62
+ lastLogin: lastLoginDate.toLocaleDateString(),
63
+ });
64
+ }
65
+ return data;
66
+ };
67
+ // Initialize all components when DOM is ready
68
+ utils.ready(() => {
69
+ // Initialize scrollbars
70
+ Scrollbar.initAll(".scroll-container");
71
+ // Initialize theme
72
+ Theme.init();
73
+ // Initialize horizontal tabs
74
+ const horizontalTabs = new Tabs(".horizontal", {
75
+ layout: "horizontal",
76
+ });
77
+ // Initialize vertical tabs
78
+ const verticalTabs = new Tabs(".vertical", {
79
+ layout: "vertical",
80
+ });
81
+ // Initialize carousel
82
+ const carousel = new Carousel("#carouselIdHere", {
83
+ loop: true,
84
+ });
85
+ // Initialize advanced table with data
86
+ const columns = [
87
+ { key: "id", label: "ID" },
88
+ { key: "name", label: "Name" },
89
+ { key: "email", label: "Email" },
90
+ { key: "role", label: "Role" },
91
+ { key: "status", label: "Status" },
92
+ { key: "lastLogin", label: "Last Login" },
93
+ ];
94
+ const tableData = generateData(50);
95
+ new Table("#demo-table-js", {
96
+ data: tableData,
97
+ columns: columns,
98
+ pageSize: 10,
99
+ });
100
+ // Initialize modal
101
+ const modalTrigger = document.querySelector(".show-modal");
102
+ if (modalTrigger) {
103
+ modalTrigger.addEventListener("click", () => {
104
+ const buttons = '<div class="buttons"><button class="button-light">Close</button>&nbsp;<button>Save Changes</button></div>';
105
+ const modal = new Modal("bluffi", "<strong>blaffi</strong>", buttons, true, "default");
106
+ modal.show();
107
+ console.warn("Buttons have no bound listeners");
108
+ });
109
+ }
110
+ // Initialize toast
111
+ const toastTrigger = document.querySelector(".show-toast");
112
+ if (toastTrigger) {
113
+ toastTrigger.addEventListener("click", () => {
114
+ const toast = new Toast("some content. maybe even more text in here!", "some header", "success", true);
115
+ toast.show(3000);
116
+ });
117
+ }
118
+ // Initialize push menu
119
+ PushMenu.init();
120
+ // Initialize flyout menu
121
+ const menu = new FlyoutMenu({
122
+ direction: "right",
123
+ triggerSelector: ".trigger-flyout-menu",
124
+ });
125
+ // Flyout menu controls: Switch direction
126
+ const directionBtns = document.querySelectorAll(".flyout-controls > button");
127
+ directionBtns.forEach((btn) => {
128
+ btn.addEventListener("click", () => {
129
+ // Remove active class from all buttons
130
+ directionBtns.forEach((b) => b.classList.remove("active"));
131
+ // Add active class to clicked button
132
+ btn.classList.add("active");
133
+ // Update menu direction
134
+ const direction = btn.dataset.direction;
135
+ if (direction) {
136
+ menu.setDirection(direction);
137
+ }
138
+ });
139
+ });
140
+ new DatePicker("#datepicker-single", {
141
+ mode: "single",
142
+ onSelect: (date) => {
143
+ console.log("Single selected:", date);
144
+ },
145
+ });
146
+ new DatePicker("#datepicker-time", {
147
+ mode: "single",
148
+ timePicker: true,
149
+ onSelect: (date) => {
150
+ console.log("Single selected:", date);
151
+ },
152
+ });
153
+ new DatePicker("#datepicker-range", {
154
+ mode: "range",
155
+ onSelect: (range) => {
156
+ console.log("Range selected:", range);
157
+ },
158
+ });
159
+ new DatePicker("#datepicker-localized", {
160
+ mode: "single",
161
+ startDay: 1, // Monday
162
+ locales: {
163
+ days: ["Do", "Lu", "Ma", "Mi", "Ju", "Vi", "Sa"],
164
+ months: [
165
+ "Enero",
166
+ "Febrero",
167
+ "Marzo",
168
+ "Abril",
169
+ "Mayo",
170
+ "Junio",
171
+ "Julio",
172
+ "Agosto",
173
+ "Septiembre",
174
+ "Octubre",
175
+ "Noviembre",
176
+ "Diciembre",
177
+ ],
178
+ },
179
+ format: (date) => {
180
+ return date.toLocaleDateString("es-ES", {
181
+ weekday: "long",
182
+ year: "numeric",
183
+ month: "long",
184
+ day: "numeric",
185
+ });
186
+ },
187
+ onSelect: (date) => {
188
+ console.log("Localized selected:", date);
189
+ },
190
+ });
191
+ // Initialize code viewer with usage example
192
+ const usageTabs = `new Tabs('.horizontal', {
193
+ layout: 'horizontal',
194
+ defaultTab: 0
195
+ });`;
196
+ new CodeViewer("#usage-tabs", usageTabs, "js");
197
+ // Initialize file uploader
198
+ const uploaderElement = document.querySelector(".uploader-content");
199
+ if (uploaderElement) {
200
+ new FileUploader(uploaderElement);
201
+ }
202
+ const sampleData = [
203
+ new TreeNode("Documents", "folder", [
204
+ new TreeNode("Work", "folder", [
205
+ new TreeNode("presentation.pptx", "file"),
206
+ new TreeNode("report.docx", "file"),
207
+ new TreeNode("budget.xlsx", "file"),
208
+ ]),
209
+ new TreeNode("Personal", "folder", [
210
+ new TreeNode("resume.pdf", "file"),
211
+ new TreeNode("vacation-photos", "folder", [
212
+ new TreeNode("beach.jpg", "file"),
213
+ new TreeNode("mountain.jpg", "file"),
214
+ ]),
215
+ ]),
216
+ ]),
217
+ new TreeNode("Projects", "folder", [
218
+ new TreeNode("website", "folder", [
219
+ new TreeNode("index.html", "file"),
220
+ new TreeNode("styles.css", "file"),
221
+ new TreeNode("script.js", "file"),
222
+ ]),
223
+ new TreeNode("app", "folder", [
224
+ new TreeNode("src", "folder", [
225
+ new TreeNode("main.js", "file"),
226
+ new TreeNode("utils.js", "file"),
227
+ ]),
228
+ new TreeNode("package.json", "file"),
229
+ ]),
230
+ ]),
231
+ new TreeNode("Downloads", "folder", [
232
+ new TreeNode("installer.exe", "file"),
233
+ new TreeNode("readme.txt", "file"),
234
+ ]),
235
+ new TreeNode("README.md", "file"),
236
+ ];
237
+ const tree = new TreeComponent("#tree-root", sampleData);
238
+ const batchSize = 12;
239
+ let indexNumber = 1;
240
+ const gallery = new MasonryGallery("gallery", {
241
+ minColumnWidth: 300,
242
+ fetchFunction: () => new Promise((resolve) => {
243
+ setTimeout(() => {
244
+ const images = [];
245
+ for (let i = 0; i < batchSize; i++) {
246
+ const width = 400;
247
+ const height = Math.floor(Math.random() * 301) + 300; // 300-600
248
+ const id = Math.floor(Math.random() * 1000);
249
+ const imageIndex = indexNumber * batchSize + i;
250
+ images.push({
251
+ src: `https://picsum.photos/${width}/${height}?random=${imageIndex}`,
252
+ title: `Image ${imageIndex + 1}`,
253
+ desc: `A random caption for image ${id}`,
254
+ });
255
+ }
256
+ indexNumber++;
257
+ resolve(images);
258
+ }, 800);
259
+ }),
260
+ });
261
+ const dropdown = new Dropdown("#myDropdown");
262
+ const dropdownElement = document.querySelector("#myDropdown");
263
+ dropdownElement?.addEventListener("dropdown-select", ((event) => {
264
+ const { text, element } = event.detail;
265
+ console.log("User selected:", text);
266
+ console.log("Selected element:", element);
267
+ }));
268
+ const generateItems = (count, prefix) => {
269
+ return Array.from({ length: count }, (_, i) => ({
270
+ label: `${prefix} Item ${i + 1}`,
271
+ value: `${prefix.toLowerCase()}_${i + 1}`,
272
+ }));
273
+ };
274
+ const bigData = generateItems(10000, "Option");
275
+ const smallData = generateItems(50, "Choice");
276
+ const singleDropdown = new VirtualDropdown({
277
+ container: "#dropdown-single",
278
+ options: bigData,
279
+ searchable: true,
280
+ placeholder: "Search 10k items...",
281
+ renderLimit: 15,
282
+ onSelect: (val) => {
283
+ console.log("Single Select:", val);
284
+ },
285
+ });
286
+ const multiDropdown = new VirtualDropdown({
287
+ container: "#dropdown-multi",
288
+ options: smallData,
289
+ searchable: true,
290
+ multiSelect: true,
291
+ placeholder: "Choose multiple...",
292
+ renderLimit: 10,
293
+ onSelect: (vals) => {
294
+ console.log("Multi Select:", vals);
295
+ },
296
+ });
297
+ // Initialize range sliders
298
+ RangeSlider.initAll();
299
+ Tooltip.initializeAll();
300
+ const timeSpanPicker = new TimeSpanPicker('timespan-1', {
301
+ onChange: (start, end) => {
302
+ console.log(`Start: ${start}, Ende: ${end}`);
303
+ }
304
+ });
305
+ new CodeViewer("#usage-text-input", `<label for="text-input-demo">Text Input</label>
306
+ <input type="text" id="text-input-demo"/>`, "html");
307
+ new CodeViewer("#usage-textarea", `<label for="textarea-demo">Text Area</label>
308
+ <textarea id="textarea-demo"></textarea>`, "html");
309
+ new CodeViewer("#usage-checkbox-demo", `<input class="styled-checkbox"
310
+ id="checkbox-1"
311
+ type="checkbox"
312
+ value="1"
313
+ />
314
+ <label for="checkbox-1">Checkbox</label>`, "html");
315
+ });
316
+ new CodeViewer("#usage-radiobutton-demo", `<label class="radio-button-container">Three
317
+ <input type="radio" name="radio"/>
318
+ <span class="checkmark"></span>
319
+ </label>`, "html");
320
+ new CodeViewer("#usage-switch-demo", `<div class="switch">
321
+ <input type="checkbox" id="switch"/><label for="switch">Toggle</label>
322
+ </div>`, "html");
323
+ new CodeViewer("#usage-slider-demo", `<div class="range-slider">
324
+ <input type="range" min="1" max="100" value="50" />
325
+ </div>`, "html");
326
+ new CodeViewer("#usage-pushmenu-control-demo", `<div class="open-menu">
327
+ <div class="navigation-controls">
328
+ <input type="checkbox" id="menu-navigation" class="navigation"/>
329
+ <label for="menu-navigation">
330
+ <span class="icon icon-menu"></span>
331
+ </label>
332
+ </div>
333
+ </div>`, "html");
334
+ new CodeViewer("#usage-pushmenu-demo", `<nav class="push-menu">
335
+ <ul>
336
+ <li>
337
+ <a onclick="window.Scroll.to('#grid')">Grid</a>
338
+ </li>
339
+ <li>
340
+ <a onclick="window.Scroll.to('#typography')">Typography</a>
341
+ </li>
342
+ </ul>
343
+ </nav>`, "html");
344
+ new CodeViewer("#usage-pushmenu-script-demo", `PushMenu.init();`, "js");
345
+ new CodeViewer("#usage-flyout-script-demo", `const menu = new FlyoutMenu({
346
+ direction: "right",
347
+ triggerSelector: ".trigger-flyout-menu",
348
+ });`, "js");
349
+ new CodeViewer("#usage-flyout-demo", `<div class="flyout-overlay" id="flyoutOverlay"></div>
350
+ <div class="flyout-menu" id="flyoutMenu">
351
+ <ul>
352
+ <li><a href="#">Home</a></li>
353
+ <li>
354
+ About
355
+ <ul>
356
+ <li><a href="#">Our Story</a></li>
357
+ <li><a href="#">Team</a></li>
358
+ <li><a href="#">Careers</a></li>
359
+ </ul>
360
+ </li>
361
+ <li>
362
+ Services
363
+ <ul>
364
+ <li>
365
+ Web Design
366
+ <ul>
367
+ <li><a href="#">eCommerce</a></li>
368
+ <li><a href="#">Landing Pages</a></li>
369
+ <li><a href="#">Portfolios</a></li>
370
+ </ul>
371
+ </li>
372
+ <li><a href="#">Development</a></li>
373
+ <li><a href="#">SEO</a></li>
374
+ </ul>
375
+ </li>
376
+ <li><a href="#">Portfolio</a></li>
377
+ <li><a href="#">Contact</a></li>
378
+ </ul>
379
+ </div>`, "html");
380
+ new CodeViewer("#usage-dropdown-menu-demo", `<div class="dropdown-container" id="myDropdown">
381
+ <button class="dropdown-trigger">Select Option</button>
382
+ <ul class="dropdown-menu">
383
+ <li>
384
+ <div class="dropdown-item">Profile</div>
385
+ </li>
386
+ <li>
387
+ <div class="dropdown-item">Settings</div>
388
+ <ul>
389
+ <li>
390
+ <div class="dropdown-item">Account</div>
391
+ </li>
392
+ <li>
393
+ <div class="dropdown-item">Privacy</div>
394
+ <ul>
395
+ <li>
396
+ <div class="dropdown-item">Public</div>
397
+ </li>
398
+ <li>
399
+ <div class="dropdown-item">Private</div>
400
+ </li>
401
+ <li>
402
+ <div class="dropdown-item">Friends Only</div>
403
+ </li>
404
+ </ul>
405
+ </li>
406
+ <li>
407
+ <div class="dropdown-item">Notifications</div>
408
+ </li>
409
+ </ul>
410
+ </li>
411
+ <li>
412
+ <div class="dropdown-item">Help</div>
413
+ </li>
414
+ <li>
415
+ <div class="dropdown-item">Logout</div>
416
+ </li>
417
+ </ul>
418
+ </div>`, "html");
419
+ new CodeViewer("#usage-dropdown-menu-js-demo", `const dropdown = new Dropdown("#myDropdown");
420
+ const dropdownElement = document.querySelector("#myDropdown");
421
+ dropdownElement?.addEventListener("dropdown-select", ((
422
+ event: CustomEvent<DropdownSelectDetail>,
423
+ ) => {
424
+ const { text, element } = event.detail;
425
+ console.log("User selected:", text);
426
+ console.log("Selected element:", element);
427
+ }) as EventListener);`, "js");
428
+ new CodeViewer("#usage-modal-demo", `const modal = new Modal(
429
+ "content",
430
+ "<strong>header</strong>",
431
+ "controls",
432
+ true,
433
+ "default",
434
+ );
435
+ modal.show();`, "js");
436
+ new CodeViewer("#usage-toast-demo", `const toast = new Toast(
437
+ "some content. maybe even more text in here!",
438
+ "some header",
439
+ "success",
440
+ true,
441
+ );
442
+ toast.show(3000);`, "js");
443
+ new CodeViewer("#usage-tooltip-demo", `<button class="tooltip-trigger" data-tooltip="This is a simple tooltip">
444
+ Simple Tooltip
445
+ </button>`, "html");
446
+ new CodeViewer("#usage-tooltip-js-demo", `Tooltip.initializeAll();`, "js");
447
+ new CodeViewer("#usage-spinner-demo", `<div class="spinner"></div>`, "html");
448
+ new CodeViewer("#usage-loading-demo", `<div class="loading"></div>`, "html");
449
+ new CodeViewer("#usage-alerts-demo", `<div class="alert alert-default">
450
+ <strong>Default:</strong> This is a default alert message.
451
+ </div>`, "html");
452
+ new CodeViewer("#usage-chips-demo", `<div class="chips">
453
+ <div class="chip">Example Chip</div>
454
+ <div class="chip clickable">Example Chip with hover</div>
455
+ <div class="chip closeable">
456
+ Example Chip with closure
457
+ <button class="close">
458
+ <span class="icon icon-close"></span>
459
+ </button>
460
+ </div>
461
+ </div>`, "html");
462
+ new CodeViewer("#usage-accordion-demo", `<div class="accordion">
463
+ <div class="accordion-item">
464
+ <input
465
+ type="radio"
466
+ name="accordion"
467
+ id="acc1"
468
+ class="accordion-input"
469
+ checked
470
+ />
471
+ <label for="acc1" class="accordion-label"> What is this? </label>
472
+ <div class="accordion-content">
473
+ <div class="accordion-body">
474
+ <div>
475
+ <p>
476
+ This is a pure CSS accordion component. It uses the "Radio
477
+ Button Hack" to manage state without a single line of
478
+ JavaScript.
479
+ </p>
480
+ </div>
481
+ </div>
482
+ </div>
483
+ </div>
484
+ <div class="accordion-item">
485
+ <input
486
+ type="radio"
487
+ name="accordion"
488
+ id="acc2"
489
+ class="accordion-input"
490
+ />
491
+ <label for="acc2" class="accordion-label"> How does it work? </label>
492
+ <div class="accordion-content">
493
+ <div class="accordion-body">
494
+ <div>
495
+ <p>It links label elements to hidden radio buttons.</p>
496
+ </div>
497
+ </div>
498
+ </div>
499
+ </div>
500
+ <div class="accordion-item">
501
+ <input
502
+ type="radio"
503
+ name="accordion"
504
+ id="acc3"
505
+ class="accordion-input"
506
+ />
507
+ <label for="acc3" class="accordion-label"> Is it accessible? </label>
508
+ <div class="accordion-content">
509
+ <div class="accordion-body">
510
+ <div>
511
+ <p>
512
+ It's reasonably accessible as it uses semantic form elements.
513
+ Users can tab through the headers (radio inputs) and select
514
+ them with the keyboard. However, for full ARIA support, a
515
+ small amount of JS is usually recommended to manage
516
+ aria-expanded attributes.
517
+ </p>
518
+ </div>
519
+ </div>
520
+ </div>
521
+ </div>
522
+ </div>`, "html");
523
+ new CodeViewer("#usage-timeline-demo", `<div class="timeline">
524
+ <div class="timeline-item active">
525
+ <div class="timeline-content">
526
+ <span class="timeline-date">October 12, 2023</span>
527
+ <h3 class="timeline-title">Project Kickoff</h3>
528
+ <p class="timeline-body">
529
+ Initial meeting with shareholders to discuss the scope and
530
+ requirements of the project. Team roles were assigned and the
531
+ roadmap was drafted.
532
+ </p>
533
+ </div>
534
+ </div>
535
+ <div class="timeline-item">
536
+ <div class="timeline-content">
537
+ <span class="timeline-date">January 15, 2024</span>
538
+ <h3 class="timeline-title">Beta Launch</h3>
539
+ <p class="timeline-body">
540
+ Opened the platform to a closed beta group of 500 users. Collected
541
+ feedback regarding the onboarding flow and notification settings.
542
+ </p>
543
+ </div>
544
+ </div>
545
+ </div>`, "html");
546
+ new CodeViewer("#usage-progress-bar-demo", `<div class="progress-bar">
547
+ <div class="progress" style="height: 24px; width: 50%"></div>
548
+ </div>`, "html");
549
+ new CodeViewer("#usage-placeholder-demo", `<span class="placeholder w-6">`, "html");
550
+ new CodeViewer("#usage-table-demo", `const columns: TableColumn[] = [
551
+ { key: "id", label: "ID" },
552
+ { key: "name", label: "Name" },
553
+ ];
554
+ const tableData: TableRow[] = [
555
+ { id: 1, name: "John Doe" },
556
+ { id: 2, name: "Jane Smith" },
557
+ { id: 3, name: "Mike Johnson" },
558
+ ];
559
+ new Table("#demo-table-js", {
560
+ data: tableData,
561
+ columns: columns,
562
+ pageSize: 10,
563
+ });
564
+
565
+ // Initialize basic table from html data
566
+ new Table("#demo-table", { pageSize: 5 });`, "js");
567
+ new CodeViewer("#usage-datepicker-html-demo", `<label for="datepicker-range">Datepicker Range</label>
568
+ <input
569
+ type="text"
570
+ id="datepicker-range"
571
+ class="datepicker-input"
572
+ placeholder="Select a date range"
573
+ readonly
574
+ />`, "html");
575
+ new CodeViewer("#usage-datepicker-js-demo", `new DatePicker("#datepicker-single", {
576
+ mode: "single",
577
+ onSelect: (date) => {
578
+ console.log("Single selected:", date);
579
+ },
580
+ });`, "js");
581
+ new CodeViewer("#usage-tree-demo-html", `<ul id="tree-root" class="tree"></ul>`, "html");
582
+ new CodeViewer("#usage-tree-demo-js", `const sampleData: TreeNode[] = [
583
+ new TreeNode("Documents", "folder", [
584
+ new TreeNode("Work", "folder", [
585
+ new TreeNode("presentation.pptx", "file"),
586
+ new TreeNode("report.docx", "file"),
587
+ new TreeNode("budget.xlsx", "file"),
588
+ ]),
589
+ new TreeNode("Personal", "folder", [
590
+ new TreeNode("resume.pdf", "file"),
591
+ new TreeNode("vacation-photos", "folder", [
592
+ new TreeNode("beach.jpg", "file"),
593
+ new TreeNode("mountain.jpg", "file"),
594
+ ]),
595
+ ]),
596
+ ]),
597
+ ];
598
+ const tree = new TreeComponent("#tree-root", sampleData);`, "js");
599
+ new CodeViewer("#usage-file-uploader-demo", `<div class="uploader-content">
600
+ <div class="header">
601
+ <h2>Upload Files</h2>
602
+ <p>Select or drag files to upload</p>
603
+ </div>
604
+ <div id="drop-zone" class="drop-zone">
605
+ <input type="file" id="file-input" multiple hidden/>
606
+ <div class="drop-zone-content">
607
+ <div class="icon-container">
608
+ <svg
609
+ xmlns="http://www.w3.org/2000/svg"
610
+ width="24"
611
+ height="24"
612
+ viewBox="0 0 24 24"
613
+ fill="none"
614
+ stroke="currentColor"
615
+ stroke-width="2"
616
+ stroke-linecap="round"
617
+ stroke-linejoin="round"
618
+ class="upload-icon"
619
+ >
620
+ <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
621
+ <polyline points="17 8 12 3 7 8"></polyline>
622
+ <line x1="12" y1="3" x2="12" y2="15"></line>
623
+ </svg>
624
+ </div>
625
+ <p class="primary-text">Click to upload or drag and drop</p>
626
+ <p class="secondary-text">
627
+ SVG, PNG, JPG or GIF (max. 800x400px)
628
+ </p>
629
+ </div>
630
+ </div>
631
+
632
+ <div id="file-list" class="file-list"></div>
633
+
634
+ <div class="actions">
635
+ <button id="upload-btn" disabled>Upload Files</button>
636
+ </div>
637
+ </div>`, "html");
638
+ new CodeViewer("#usage-file-uploader-demo-js", `const uploaderElement =
639
+ document.querySelector<HTMLElement>(".uploader-content");
640
+ if (uploaderElement) {
641
+ new FileUploader(uploaderElement);
642
+ }`, "js");
643
+ new CodeViewer("#usage-virtual-dropdown-demo-html", `<div class="virtual-dropdown">
644
+ <h2>1. Searchable Single Select (10,000 items)</h2>
645
+ <p>
646
+ This list uses virtual scrolling to handle 10k items efficiently.
647
+ </p>
648
+ <div id="dropdown-single"></div>
649
+ </div>`, "html");
650
+ new CodeViewer("#usage-virtual-dropdown-demo-js", `const singleDropdown = new VirtualDropdown({
651
+ container: "#dropdown-single",
652
+ options: bigData,
653
+ searchable: true,
654
+ placeholder: "Search 10k items...",
655
+ renderLimit: 15,
656
+ onSelect: (val) => {
657
+ console.log("Single Select:", val);
658
+ },
659
+ });`, "js");
660
+ new CodeViewer("#usage-scrollbar-demo", `Scrollbar.initAll(".scroll-container");`, "js");
661
+ new CodeViewer("#usage-theme-demo", `Theme.init();`, "js");
662
+ new CodeViewer("#usage-scroll-demo", `window.Scroll.to('#grid')`, "js");
663
+ new CodeViewer("#usage-chat-demo-html", `<div class="chat-container">
664
+ <div class="message message-incoming">
665
+ Hi there! How are you doing today?
666
+ <span class="message-meta">10:42 AM</span>
667
+ </div>
668
+ <div class="message message-outgoing">
669
+ I'm doing great, thanks! Just working on some new CSS
670
+ components.<br/>And other stuff.
671
+ <span class="message-meta">10:43 AM</span>
672
+ </div>
673
+ <div class="message message-outgoing">
674
+ Trying to make a simple chat UI.
675
+ <span class="message-meta">10:43 AM</span>
676
+ </div>
677
+ <div class="message message-incoming">
678
+ That sounds cool!
679
+ <span class="message-meta">10:45 AM</span>
680
+ </div>
681
+ </div>`, "html");
682
+ new CodeViewer("#usage-carousel-demo-html", `<div class="carousel" id="carouselIdHere">
683
+ <div>Slide 1</div>
684
+ <div>Slide 2</div>
685
+ <div>Slide 3</div>
686
+ <div>Slide 4</div>
687
+ </div>`, "html");
688
+ new CodeViewer("#usage-carousel-demo-js", `const carousel = new Carousel("#carouselIdHere", {
689
+ loop: true,
690
+ });`, "js");
691
+ new CodeViewer("#usage-gallery-demo-html", `<div id="gallery" class="masonry-container"></div>
692
+ <div class="loader hidden">
693
+ <div class="spinner"></div>
694
+ </div>`, "html");
695
+ new CodeViewer("#usage-gallery-demo-js", `const gallery = new MasonryGallery("gallery", {
696
+ minColumnWidth: 300,
697
+ fetchFunction: () => new Promise((resolve) => {
698
+ setTimeout(() => {
699
+ const images: ImageData[] = [];
700
+
701
+ for (let i = 0; i < batchSize; i++) {
702
+ const width = 400;
703
+ const height = Math.floor(Math.random() * 301) + 300;
704
+ const id = Math.floor(Math.random() * 1000);
705
+ const imageIndex = indexNumber * batchSize + i;
706
+
707
+ images.push({
708
+ src: \`https://picsum.photos/$\{width}/$\{height}?random=$\{imageIndex}\`,
709
+ title: \`Image $\{imageIndex + 1}\`,
710
+ desc: \`A random caption for image $\{id}\`,
711
+ });
712
+ }
713
+
714
+ indexNumber++;
715
+ resolve(images);
716
+ }, 800);
717
+ }),
718
+ });`, "js");