@kupola/kupola 1.2.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.
- package/CHANGELOG.md +130 -0
- package/INTEGRATION.md +440 -0
- package/PROJECT_SUMMARY.md +312 -0
- package/README.md +286 -0
- package/SKILL.md +572 -0
- package/css/accessibility.css +119 -0
- package/css/animations.css +224 -0
- package/css/brand-themes.css +300 -0
- package/css/colors_and_type.css +441 -0
- package/css/components-ext.css +4165 -0
- package/css/components.css +1483 -0
- package/css/kupola.css +12 -0
- package/css/responsive.css +697 -0
- package/css/scaffold.css +145 -0
- package/css/states.css +316 -0
- package/css/theme-dark.css +296 -0
- package/css/theme-light.css +296 -0
- package/css/utilities.css +171 -0
- package/dist/css/kupola.css +12 -0
- package/dist/icons/icons/activity.svg +3 -0
- package/dist/icons/icons/alert-circle.svg +1 -0
- package/dist/icons/icons/alert-triangle.svg +1 -0
- package/dist/icons/icons/alert.d27e24.svg +1 -0
- package/dist/icons/icons/alert.svg +1 -0
- package/dist/icons/icons/apple.svg +1 -0
- package/dist/icons/icons/arrow-down.svg +1 -0
- package/dist/icons/icons/arrow-expand.svg +1 -0
- package/dist/icons/icons/arrow-left.svg +1 -0
- package/dist/icons/icons/arrow-minimize.svg +1 -0
- package/dist/icons/icons/arrow-right-to-line.svg +1 -0
- package/dist/icons/icons/arrow-right.svg +1 -0
- package/dist/icons/icons/arrow-up-right.svg +1 -0
- package/dist/icons/icons/arrow-up.0c0c0d.svg +1 -0
- package/dist/icons/icons/arrow-up.svg +1 -0
- package/dist/icons/icons/at.svg +1 -0
- package/dist/icons/icons/atom.0c0c0d.svg +1 -0
- package/dist/icons/icons/atom.svg +1 -0
- package/dist/icons/icons/bar-chart-2.svg +1 -0
- package/dist/icons/icons/bar.svg +1 -0
- package/dist/icons/icons/bell.svg +1 -0
- package/dist/icons/icons/box.svg +1 -0
- package/dist/icons/icons/bug.svg +1 -0
- package/dist/icons/icons/button.svg +1 -0
- package/dist/icons/icons/calendar.svg +1 -0
- package/dist/icons/icons/check-circle.33c192.svg +1 -0
- package/dist/icons/icons/check-circle.svg +1 -0
- package/dist/icons/icons/check-square.svg +4 -0
- package/dist/icons/icons/check.d1d3db.svg +1 -0
- package/dist/icons/icons/check.svg +1 -0
- package/dist/icons/icons/chevron-down.svg +1 -0
- package/dist/icons/icons/chevron-left.svg +1 -0
- package/dist/icons/icons/chevron-right.svg +1 -0
- package/dist/icons/icons/chevron-up.svg +1 -0
- package/dist/icons/icons/circle.svg +1 -0
- package/dist/icons/icons/clock.svg +1 -0
- package/dist/icons/icons/cmd.svg +1 -0
- package/dist/icons/icons/code.svg +1 -0
- package/dist/icons/icons/columns.svg +1 -0
- package/dist/icons/icons/copy.svg +1 -0
- package/dist/icons/icons/cpu.svg +1 -0
- package/dist/icons/icons/dashboard.0c0c0d.svg +1 -0
- package/dist/icons/icons/dashboard.svg +1 -0
- package/dist/icons/icons/dollar.svg +1 -0
- package/dist/icons/icons/download.svg +1 -0
- package/dist/icons/icons/edit.svg +1 -0
- package/dist/icons/icons/extensions.svg +1 -0
- package/dist/icons/icons/external.svg +1 -0
- package/dist/icons/icons/eye.svg +1 -0
- package/dist/icons/icons/file-text.svg +1 -0
- package/dist/icons/icons/file.svg +1 -0
- package/dist/icons/icons/files.svg +1 -0
- package/dist/icons/icons/filter.svg +1 -0
- package/dist/icons/icons/folder-open.svg +4 -0
- package/dist/icons/icons/folder.svg +1 -0
- package/dist/icons/icons/gear.svg +1 -0
- package/dist/icons/icons/git.svg +1 -0
- package/dist/icons/icons/github.svg +1 -0
- package/dist/icons/icons/globe.svg +1 -0
- package/dist/icons/icons/grid-2x2.svg +1 -0
- package/dist/icons/icons/hash.svg +1 -0
- package/dist/icons/icons/heart.svg +1 -0
- package/dist/icons/icons/help-circle.svg +5 -0
- package/dist/icons/icons/help.svg +1 -0
- package/dist/icons/icons/home.svg +1 -0
- package/dist/icons/icons/icons.svg +153 -0
- package/dist/icons/icons/image.svg +1 -0
- package/dist/icons/icons/info-circle.svg +1 -0
- package/dist/icons/icons/info-square.svg +1 -0
- package/dist/icons/icons/info.387bff.svg +1 -0
- package/dist/icons/icons/info.svg +1 -0
- package/dist/icons/icons/input.svg +1 -0
- package/dist/icons/icons/key.svg +1 -0
- package/dist/icons/icons/layers.svg +1 -0
- package/dist/icons/icons/layout-grid.svg +6 -0
- package/dist/icons/icons/layout.svg +1 -0
- package/dist/icons/icons/link.svg +1 -0
- package/dist/icons/icons/list.svg +1 -0
- package/dist/icons/icons/lock.svg +1 -0
- package/dist/icons/icons/log-out.svg +1 -0
- package/dist/icons/icons/logo.svg +1 -0
- package/dist/icons/icons/mail.svg +1 -0
- package/dist/icons/icons/menu.svg +1 -0
- package/dist/icons/icons/message-circle.svg +1 -0
- package/dist/icons/icons/message-plus.svg +1 -0
- package/dist/icons/icons/message-square.svg +1 -0
- package/dist/icons/icons/mic.svg +1 -0
- package/dist/icons/icons/minus.svg +1 -0
- package/dist/icons/icons/moon.svg +1 -0
- package/dist/icons/icons/more-h.svg +1 -0
- package/dist/icons/icons/mouse.svg +1 -0
- package/dist/icons/icons/palette.svg +1 -0
- package/dist/icons/icons/panel-bottom.svg +1 -0
- package/dist/icons/icons/pause.svg +1 -0
- package/dist/icons/icons/play.svg +1 -0
- package/dist/icons/icons/plug.svg +1 -0
- package/dist/icons/icons/plus.0c0c0d.svg +1 -0
- package/dist/icons/icons/plus.svg +1 -0
- package/dist/icons/icons/refresh.svg +1 -0
- package/dist/icons/icons/ruler.svg +1 -0
- package/dist/icons/icons/scroll-text.svg +1 -0
- package/dist/icons/icons/search-menu.svg +1 -0
- package/dist/icons/icons/search.svg +1 -0
- package/dist/icons/icons/send.0c0c0d.svg +1 -0
- package/dist/icons/icons/send.svg +1 -0
- package/dist/icons/icons/settings.0c0c0d.svg +1 -0
- package/dist/icons/icons/settings.svg +1 -0
- package/dist/icons/icons/shield.svg +1 -0
- package/dist/icons/icons/sidebar-left.svg +1 -0
- package/dist/icons/icons/sidebar-right.svg +1 -0
- package/dist/icons/icons/sliders.svg +1 -0
- package/dist/icons/icons/sparkles.32f08c.svg +1 -0
- package/dist/icons/icons/sparkles.svg +1 -0
- package/dist/icons/icons/square.svg +1 -0
- package/dist/icons/icons/star.svg +1 -0
- package/dist/icons/icons/sun.svg +1 -0
- package/dist/icons/icons/table.svg +1 -0
- package/dist/icons/icons/terminal.svg +1 -0
- package/dist/icons/icons/trash.svg +1 -0
- package/dist/icons/icons/trending-down.svg +1 -0
- package/dist/icons/icons/trending-up.svg +1 -0
- package/dist/icons/icons/type.svg +1 -0
- package/dist/icons/icons/upload.svg +1 -0
- package/dist/icons/icons/user-circle.svg +1 -0
- package/dist/icons/icons/user-plus.svg +6 -0
- package/dist/icons/icons/user.svg +1 -0
- package/dist/icons/icons/users.svg +1 -0
- package/dist/icons/icons/warning.svg +1 -0
- package/dist/icons/icons/wrench.svg +1 -0
- package/dist/icons/icons/x-circle.svg +1 -0
- package/dist/icons/icons/x.svg +1 -0
- package/dist/icons/icons/zap.0c0c0d.svg +1 -0
- package/dist/icons/icons/zap.svg +1 -0
- package/dist/kupola.cjs.js +258 -0
- package/dist/kupola.cjs.js.map +1 -0
- package/dist/kupola.esm.js +7640 -0
- package/dist/kupola.esm.js.map +1 -0
- package/dist/kupola.umd.js +258 -0
- package/dist/kupola.umd.js.map +1 -0
- package/dist/types/kupola.d.ts +1359 -0
- package/dist/utils/utils/Kupola.cs +77 -0
- package/dist/utils/utils/Kupola.java +104 -0
- package/dist/utils/utils/kupola.go +120 -0
- package/dist/utils/utils/kupola.js +63 -0
- package/dist/utils/utils/kupola.py +1392 -0
- package/dist/utils/utils/kupola.rb +69 -0
- package/icons/activity.svg +3 -0
- package/icons/alert-circle.svg +1 -0
- package/icons/alert-triangle.svg +1 -0
- package/icons/alert.d27e24.svg +1 -0
- package/icons/alert.svg +1 -0
- package/icons/apple.svg +1 -0
- package/icons/arrow-down.svg +1 -0
- package/icons/arrow-expand.svg +1 -0
- package/icons/arrow-left.svg +1 -0
- package/icons/arrow-minimize.svg +1 -0
- package/icons/arrow-right-to-line.svg +1 -0
- package/icons/arrow-right.svg +1 -0
- package/icons/arrow-up-right.svg +1 -0
- package/icons/arrow-up.0c0c0d.svg +1 -0
- package/icons/arrow-up.svg +1 -0
- package/icons/at.svg +1 -0
- package/icons/atom.0c0c0d.svg +1 -0
- package/icons/atom.svg +1 -0
- package/icons/bar-chart-2.svg +1 -0
- package/icons/bar.svg +1 -0
- package/icons/bell.svg +1 -0
- package/icons/box.svg +1 -0
- package/icons/bug.svg +1 -0
- package/icons/button.svg +1 -0
- package/icons/calendar.svg +1 -0
- package/icons/check-circle.33c192.svg +1 -0
- package/icons/check-circle.svg +1 -0
- package/icons/check-square.svg +4 -0
- package/icons/check.d1d3db.svg +1 -0
- package/icons/check.svg +1 -0
- package/icons/chevron-down.svg +1 -0
- package/icons/chevron-left.svg +1 -0
- package/icons/chevron-right.svg +1 -0
- package/icons/chevron-up.svg +1 -0
- package/icons/circle.svg +1 -0
- package/icons/clock.svg +1 -0
- package/icons/cmd.svg +1 -0
- package/icons/code.svg +1 -0
- package/icons/columns.svg +1 -0
- package/icons/copy.svg +1 -0
- package/icons/cpu.svg +1 -0
- package/icons/dashboard.0c0c0d.svg +1 -0
- package/icons/dashboard.svg +1 -0
- package/icons/dollar.svg +1 -0
- package/icons/download.svg +1 -0
- package/icons/edit.svg +1 -0
- package/icons/extensions.svg +1 -0
- package/icons/external.svg +1 -0
- package/icons/eye.svg +1 -0
- package/icons/file-text.svg +1 -0
- package/icons/file.svg +1 -0
- package/icons/files.svg +1 -0
- package/icons/filter.svg +1 -0
- package/icons/folder-open.svg +4 -0
- package/icons/folder.svg +1 -0
- package/icons/gear.svg +1 -0
- package/icons/git.svg +1 -0
- package/icons/github.svg +1 -0
- package/icons/globe.svg +1 -0
- package/icons/grid-2x2.svg +1 -0
- package/icons/hash.svg +1 -0
- package/icons/heart.svg +1 -0
- package/icons/help-circle.svg +5 -0
- package/icons/help.svg +1 -0
- package/icons/home.svg +1 -0
- package/icons/icons.svg +153 -0
- package/icons/image.svg +1 -0
- package/icons/info-circle.svg +1 -0
- package/icons/info-square.svg +1 -0
- package/icons/info.387bff.svg +1 -0
- package/icons/info.svg +1 -0
- package/icons/input.svg +1 -0
- package/icons/key.svg +1 -0
- package/icons/layers.svg +1 -0
- package/icons/layout-grid.svg +6 -0
- package/icons/layout.svg +1 -0
- package/icons/link.svg +1 -0
- package/icons/list.svg +1 -0
- package/icons/lock.svg +1 -0
- package/icons/log-out.svg +1 -0
- package/icons/logo.svg +1 -0
- package/icons/mail.svg +1 -0
- package/icons/menu.svg +1 -0
- package/icons/message-circle.svg +1 -0
- package/icons/message-plus.svg +1 -0
- package/icons/message-square.svg +1 -0
- package/icons/mic.svg +1 -0
- package/icons/minus.svg +1 -0
- package/icons/moon.svg +1 -0
- package/icons/more-h.svg +1 -0
- package/icons/mouse.svg +1 -0
- package/icons/palette.svg +1 -0
- package/icons/panel-bottom.svg +1 -0
- package/icons/pause.svg +1 -0
- package/icons/play.svg +1 -0
- package/icons/plug.svg +1 -0
- package/icons/plus.0c0c0d.svg +1 -0
- package/icons/plus.svg +1 -0
- package/icons/refresh.svg +1 -0
- package/icons/ruler.svg +1 -0
- package/icons/scroll-text.svg +1 -0
- package/icons/search-menu.svg +1 -0
- package/icons/search.svg +1 -0
- package/icons/send.0c0c0d.svg +1 -0
- package/icons/send.svg +1 -0
- package/icons/settings.0c0c0d.svg +1 -0
- package/icons/settings.svg +1 -0
- package/icons/shield.svg +1 -0
- package/icons/sidebar-left.svg +1 -0
- package/icons/sidebar-right.svg +1 -0
- package/icons/sliders.svg +1 -0
- package/icons/sparkles.32f08c.svg +1 -0
- package/icons/sparkles.svg +1 -0
- package/icons/square.svg +1 -0
- package/icons/star.svg +1 -0
- package/icons/sun.svg +1 -0
- package/icons/table.svg +1 -0
- package/icons/terminal.svg +1 -0
- package/icons/trash.svg +1 -0
- package/icons/trending-down.svg +1 -0
- package/icons/trending-up.svg +1 -0
- package/icons/type.svg +1 -0
- package/icons/upload.svg +1 -0
- package/icons/user-circle.svg +1 -0
- package/icons/user-plus.svg +6 -0
- package/icons/user.svg +1 -0
- package/icons/users.svg +1 -0
- package/icons/warning.svg +1 -0
- package/icons/wrench.svg +1 -0
- package/icons/x-circle.svg +1 -0
- package/icons/x.svg +1 -0
- package/icons/zap.0c0c0d.svg +1 -0
- package/icons/zap.svg +1 -0
- package/js/calendar.js +184 -0
- package/js/carousel.js +173 -0
- package/js/collapse.js +127 -0
- package/js/color-picker.js +144 -0
- package/js/component.js +276 -0
- package/js/composition-api.js +458 -0
- package/js/countdown.js +144 -0
- package/js/data-bind.js +1286 -0
- package/js/datepicker.js +270 -0
- package/js/dialog.js +131 -0
- package/js/drawer.js +118 -0
- package/js/dropdown.js +122 -0
- package/js/dynamic-tags.js +156 -0
- package/js/error-handler.js +181 -0
- package/js/fileupload.js +392 -0
- package/js/form.js +291 -0
- package/js/global-events.js +203 -0
- package/js/heatmap.js +405 -0
- package/js/http.js +419 -0
- package/js/i18n.js +228 -0
- package/js/icons.js +165 -0
- package/js/image-preview.js +218 -0
- package/js/initializer.js +162 -0
- package/js/kupola-core.js +66 -0
- package/js/kupola-devtools.js +598 -0
- package/js/kupola-lifecycle.js +510 -0
- package/js/message.js +60 -0
- package/js/modal.js +191 -0
- package/js/notification.js +73 -0
- package/js/numberinput.js +146 -0
- package/js/performance.js +250 -0
- package/js/registry.js +205 -0
- package/js/router.js +396 -0
- package/js/security.js +189 -0
- package/js/select.js +143 -0
- package/js/slide-captcha.js +504 -0
- package/js/slider.js +94 -0
- package/js/statcard.js +219 -0
- package/js/tag.js +83 -0
- package/js/test-utils.js +251 -0
- package/js/theme.js +363 -0
- package/js/timepicker.js +238 -0
- package/js/tooltip.js +122 -0
- package/js/utils.js +1458 -0
- package/js/validation.js +553 -0
- package/js/virtual-list.js +593 -0
- package/package.json +105 -0
- package/templates/base.html +30 -0
- package/templates/base_dashboard.html +99 -0
- package/types/kupola.d.ts +1359 -0
- package/utils/Kupola.cs +77 -0
- package/utils/Kupola.java +104 -0
- package/utils/kupola.go +120 -0
- package/utils/kupola.js +63 -0
- package/utils/kupola.py +1392 -0
- package/utils/kupola.rb +69 -0
package/js/icons.js
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lightweight icon set inspired by Lucide / shadcn — square, 2px stroke,
|
|
3
|
+
* butt caps, miter joins. Use <i data-icon="name"></i> and call Icons.render().
|
|
4
|
+
*/
|
|
5
|
+
(function (global) {
|
|
6
|
+
const ATTRS = 'xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"';
|
|
7
|
+
|
|
8
|
+
const PATHS = {
|
|
9
|
+
// navigation
|
|
10
|
+
'globe': '<circle cx="12" cy="12" r="10"/><path d="M2 12h20"/><path d="M12 2a15.3 15.3 0 0 1 0 20"/><path d="M12 2a15.3 15.3 0 0 0 0 20"/>',
|
|
11
|
+
'dashboard': '<rect x="3" y="3" width="7" height="9"/><rect x="14" y="3" width="7" height="5"/><rect x="14" y="12" width="7" height="9"/><rect x="3" y="16" width="7" height="5"/>',
|
|
12
|
+
'mouse': '<rect x="6" y="2" width="12" height="20" rx="6"/><line x1="12" y1="6" x2="12" y2="11"/>',
|
|
13
|
+
'search': '<circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/>',
|
|
14
|
+
'square': '<rect x="3" y="3" width="18" height="18"/>',
|
|
15
|
+
'circle': '<circle cx="12" cy="12" r="9"/>',
|
|
16
|
+
'list': '<line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/>',
|
|
17
|
+
'palette': '<rect x="3" y="3" width="8" height="8"/><rect x="13" y="3" width="8" height="8"/><rect x="3" y="13" width="8" height="8"/><rect x="13" y="13" width="8" height="8"/>',
|
|
18
|
+
'type': '<polyline points="4 7 4 4 20 4 20 7"/><line x1="9" y1="20" x2="15" y2="20"/><line x1="12" y1="4" x2="12" y2="20"/>',
|
|
19
|
+
'ruler': '<rect x="3" y="9" width="18" height="6" transform="rotate(-45 12 12)"/><line x1="7.5" y1="12.5" x2="9" y2="14"/><line x1="11" y1="9" x2="12.5" y2="10.5"/><line x1="14.5" y1="5.5" x2="16" y2="7"/>',
|
|
20
|
+
'sparkles': '<path d="M12 3l1.8 4.2L18 9l-4.2 1.8L12 15l-1.8-4.2L6 9l4.2-1.8L12 3z"/><path d="M19 14l1 2.2 2.2 1-2.2 1L19 20.4l-1-2.2-2.2-1 2.2-1L19 14z"/>',
|
|
21
|
+
// actions
|
|
22
|
+
'copy': '<rect x="8" y="8" width="13" height="13"/><path d="M16 8V4H4v13h4"/>',
|
|
23
|
+
'download': '<path d="M12 3v12"/><polyline points="7 10 12 15 17 10"/><line x1="3" y1="21" x2="21" y2="21"/>',
|
|
24
|
+
'refresh': '<polyline points="21 4 21 10 15 10"/><polyline points="3 20 3 14 9 14"/><path d="M20.5 9A9 9 0 0 0 5 5.5L3 7M3.5 15A9 9 0 0 0 19 18.5L21 17"/>',
|
|
25
|
+
'external': '<polyline points="14 4 20 4 20 10"/><line x1="20" y1="4" x2="11" y2="13"/><path d="M20 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h5"/>',
|
|
26
|
+
'settings': '<circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.7 1.7 0 0 0 .3 1.8l.1.1a2 2 0 1 1-2.8 2.8l-.1-.1a1.7 1.7 0 0 0-1.8-.3 1.7 1.7 0 0 0-1 1.5V21a2 2 0 1 1-4 0v-.1a1.7 1.7 0 0 0-1-1.5 1.7 1.7 0 0 0-1.8.3l-.1.1a2 2 0 1 1-2.8-2.8l.1-.1a1.7 1.7 0 0 0 .3-1.8 1.7 1.7 0 0 0-1.5-1H3a2 2 0 1 1 0-4h.1a1.7 1.7 0 0 0 1.5-1 1.7 1.7 0 0 0-.3-1.8l-.1-.1a2 2 0 1 1 2.8-2.8l.1.1a1.7 1.7 0 0 0 1.8.3H9a1.7 1.7 0 0 0 1-1.5V3a2 2 0 1 1 4 0v.1a1.7 1.7 0 0 0 1 1.5 1.7 1.7 0 0 0 1.8-.3l.1-.1a2 2 0 1 1 2.8 2.8l-.1.1a1.7 1.7 0 0 0-.3 1.8V9a1.7 1.7 0 0 0 1.5 1H21a2 2 0 1 1 0 4h-.1a1.7 1.7 0 0 0-1.5 1z"/>',
|
|
27
|
+
'sliders': '<line x1="4" y1="21" x2="4" y2="14"/><line x1="4" y1="10" x2="4" y2="3"/><line x1="12" y1="21" x2="12" y2="12"/><line x1="12" y1="8" x2="12" y2="3"/><line x1="20" y1="21" x2="20" y2="16"/><line x1="20" y1="12" x2="20" y2="3"/><line x1="1" y1="14" x2="7" y2="14"/><line x1="9" y1="8" x2="15" y2="8"/><line x1="17" y1="16" x2="23" y2="16"/>',
|
|
28
|
+
'plus': '<line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/>',
|
|
29
|
+
'minus': '<line x1="5" y1="12" x2="19" y2="12"/>',
|
|
30
|
+
'x': '<line x1="6" y1="6" x2="18" y2="18"/><line x1="18" y1="6" x2="6" y2="18"/>',
|
|
31
|
+
'github': '<path d="M9 19c-4.3 1.4-4.3-2.5-6-3m12 5v-3.5c0-1 .1-1.4-.5-2 2.8-.3 5.5-1.4 5.5-6a4.6 4.6 0 0 0-1.3-3.2 4.2 4.2 0 0 0-.1-3.2s-1.1-.3-3.5 1.3a12 12 0 0 0-6.2 0C6.5 2.8 5.4 3.1 5.4 3.1a4.2 4.2 0 0 0-.1 3.2A4.6 4.6 0 0 0 4 9.5c0 4.6 2.7 5.7 5.5 6-.6.6-.6 1.2-.5 2V21"/>',
|
|
32
|
+
'message-circle':'<path d="M21 12a9 9 0 0 1-13.5 7.8L3 21l1.2-4.5A9 9 0 1 1 21 12z"/>',
|
|
33
|
+
// SOLO chat title-bar glyphs (Figma 2510_18334) — round bubble + plus,
|
|
34
|
+
// 4-tooth gear with center circle, and person-in-circle account avatar.
|
|
35
|
+
'message-plus':'<path d="M21 12a9 9 0 0 1-13.5 7.8L3 21l1.2-4.5A9 9 0 1 1 21 12z"/><line x1="12" y1="9" x2="12" y2="15"/><line x1="9" y1="12" x2="15" y2="12"/>',
|
|
36
|
+
'gear': '<path d="M9.3 5.7 6.375 5.025 5.025 6.375 5.7 9.3 3 11.1 3 12.9 5.7 14.7 5.025 17.625 6.375 18.975 9.3 18.3 11.1 21 12.9 21 14.7 18.3 17.625 18.975 18.975 17.625 18.3 14.7 21 12.9 21 11.1 18.3 9.3 18.975 6.375 17.625 5.025 14.7 5.7 12.9 3 11.1 3 9.3 5.7Z"/><circle cx="12" cy="12" r="3"/>',
|
|
37
|
+
'user-circle': '<circle cx="12" cy="12" r="9"/><circle cx="12" cy="10" r="2.5"/><path d="M7 17.5a5 5 0 0 1 10 0"/>',
|
|
38
|
+
'shield': '<path d="M12 3 4 6v6c0 5 3.5 8 8 9 4.5-1 8-4 8-9V6z"/>',
|
|
39
|
+
'check': '<polyline points="4 12 10 18 20 6"/>',
|
|
40
|
+
'arrow-right': '<line x1="4" y1="12" x2="20" y2="12"/><polyline points="14 6 20 12 14 18"/>',
|
|
41
|
+
'arrow-up-right': '<line x1="6" y1="18" x2="18" y2="6"/><polyline points="9 6 18 6 18 15"/>',
|
|
42
|
+
'chevron-right':'<polyline points="9 6 15 12 9 18"/>',
|
|
43
|
+
'chevron-down':'<polyline points="6 9 12 15 18 9"/>',
|
|
44
|
+
// status — strict outline, 24x24, 2px stroke (no filled bowls)
|
|
45
|
+
'check-circle':'<circle cx="12" cy="12" r="9"/><polyline points="8 12 11 15 16 9"/>',
|
|
46
|
+
'alert-circle':'<circle cx="12" cy="12" r="9"/><line x1="12" y1="8" x2="12" y2="13"/><line x1="12" y1="16" x2="12" y2="16.01"/>',
|
|
47
|
+
'alert-triangle':'<path d="M12 3 22 20 2 20 Z"/><line x1="12" y1="10" x2="12" y2="15"/><line x1="12" y1="18" x2="12" y2="18.01"/>',
|
|
48
|
+
'info-circle': '<circle cx="12" cy="12" r="9"/><line x1="12" y1="11" x2="12" y2="16"/><line x1="12" y1="8" x2="12" y2="8.01"/>',
|
|
49
|
+
'x-circle': '<circle cx="12" cy="12" r="9"/><line x1="9" y1="9" x2="15" y2="15"/><line x1="15" y1="9" x2="9" y2="15"/>',
|
|
50
|
+
// legacy aliases — kept outline, square frame
|
|
51
|
+
'alert': '<path d="M12 3 22 20 2 20 Z"/><line x1="12" y1="10" x2="12" y2="15"/><line x1="12" y1="18" x2="12" y2="18.01"/>',
|
|
52
|
+
'info': '<circle cx="12" cy="12" r="9"/><line x1="12" y1="11" x2="12" y2="16"/><line x1="12" y1="8" x2="12" y2="8.01"/>',
|
|
53
|
+
// misc
|
|
54
|
+
'mail': '<rect x="3" y="5" width="18" height="14"/><polyline points="3 6 12 13 21 6"/>',
|
|
55
|
+
'user': '<path d="M4 21v-1a6 6 0 0 1 6-6h4a6 6 0 0 1 6 6v1"/><circle cx="12" cy="8" r="4"/>',
|
|
56
|
+
'users': '<path d="M2 21v-1a5 5 0 0 1 5-5h3a5 5 0 0 1 5 5v1"/><circle cx="8.5" cy="8" r="3.5"/><path d="M22 21v-1a5 5 0 0 0-4-4.9"/><path d="M16 3.1A4 4 0 0 1 16 11"/>',
|
|
57
|
+
'box': '<polyline points="3 7 12 2 21 7 21 17 12 22 3 17 3 7"/><line x1="3" y1="7" x2="12" y2="12"/><line x1="21" y1="7" x2="12" y2="12"/><line x1="12" y1="22" x2="12" y2="12"/>',
|
|
58
|
+
'zap': '<polygon points="13 2 4 14 12 14 11 22 20 10 12 10 13 2"/>',
|
|
59
|
+
'moon': '<path d="M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8z"/>',
|
|
60
|
+
'sun': '<circle cx="12" cy="12" r="4"/><line x1="12" y1="2" x2="12" y2="5"/><line x1="12" y1="19" x2="12" y2="22"/><line x1="2" y1="12" x2="5" y2="12"/><line x1="19" y1="12" x2="22" y2="12"/><line x1="4.6" y1="4.6" x2="6.7" y2="6.7"/><line x1="17.3" y1="17.3" x2="19.4" y2="19.4"/><line x1="4.6" y1="19.4" x2="6.7" y2="17.3"/><line x1="17.3" y1="6.7" x2="19.4" y2="4.6"/>',
|
|
61
|
+
'cmd': '<path d="M9 6h6v12H9z"/><rect x="3" y="3" width="6" height="6"/><rect x="15" y="3" width="6" height="6"/><rect x="3" y="15" width="6" height="6"/><rect x="15" y="15" width="6" height="6"/>',
|
|
62
|
+
'key': '<circle cx="7.5" cy="14.5" r="3.5"/><line x1="10" y1="12" x2="22" y2="12"/><line x1="22" y1="12" x2="22" y2="16"/><line x1="18" y1="12" x2="18" y2="15"/>',
|
|
63
|
+
'bell': '<path d="M6 8a6 6 0 0 1 12 0c0 7 3 8 3 8H3s3-1 3-8z"/><path d="M10 21a2 2 0 0 0 4 0"/>',
|
|
64
|
+
'arrow-up': '<line x1="12" y1="20" x2="12" y2="4"/><polyline points="6 10 12 4 18 10"/>',
|
|
65
|
+
'chevron-up': '<polyline points="6 15 12 9 18 15"/>',
|
|
66
|
+
'arrow-left': '<line x1="20" y1="12" x2="4" y2="12"/><polyline points="10 6 4 12 10 18"/>',
|
|
67
|
+
'mic': '<rect x="9" y="3" width="6" height="12" rx="3"/><path d="M5 11a7 7 0 0 0 14 0"/><line x1="12" y1="18" x2="12" y2="22"/>',
|
|
68
|
+
'at': '<circle cx="12" cy="12" r="4"/><path d="M16 8v5a3 3 0 0 0 6 0v-1a10 10 0 1 0-4 8"/>',
|
|
69
|
+
'hash': '<line x1="4" y1="9" x2="20" y2="9"/><line x1="4" y1="15" x2="20" y2="15"/><line x1="10" y1="3" x2="8" y2="21"/><line x1="16" y1="3" x2="14" y2="21"/>',
|
|
70
|
+
'sidebar-left': '<rect x="3" y="3" width="18" height="18"/><line x1="9" y1="3" x2="9" y2="21"/>',
|
|
71
|
+
'sidebar-right': '<rect x="3" y="3" width="18" height="18"/><line x1="15" y1="3" x2="15" y2="21"/>',
|
|
72
|
+
'panel-bottom': '<rect x="3" y="3" width="18" height="18"/><line x1="3" y1="15" x2="21" y2="15"/>',
|
|
73
|
+
/* ===== Activity-bar icon set =====================================
|
|
74
|
+
* Lucide / shadcn-ui (MIT) — squared outline, 2px stroke. Every glyph
|
|
75
|
+
* draws into the same standard 24-grid bbox (≈3..21) so they read at
|
|
76
|
+
* identical optical size when sized via `data-size` alone, just like
|
|
77
|
+
* every other glyph in this file. See skill.md §13.4. */
|
|
78
|
+
'git': '<circle cx="6" cy="5" r="3"/><circle cx="6" cy="19" r="3"/><circle cx="18" cy="5" r="3"/><line x1="6" y1="8" x2="6" y2="16"/><path d="M18 8v3a4 4 0 0 1-4 4h-4"/>',
|
|
79
|
+
'bug': '<rect x="8" y="6" width="8" height="14" rx="4"/><line x1="12" y1="11" x2="12" y2="20"/><line x1="3" y1="9" x2="8" y2="9"/><line x1="3" y1="14" x2="8" y2="14"/><line x1="3" y1="19" x2="8" y2="19"/><line x1="16" y1="9" x2="21" y2="9"/><line x1="16" y1="14" x2="21" y2="14"/><line x1="16" y1="19" x2="21" y2="19"/><line x1="9" y1="6" x2="9" y2="3"/><line x1="15" y1="6" x2="15" y2="3"/>',
|
|
80
|
+
'search-menu': '<circle cx="11" cy="11" r="6"/><line x1="20" y1="20" x2="16" y2="16"/><line x1="3" y1="20" x2="13" y2="20"/>',
|
|
81
|
+
'extensions': '<rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/><path d="M17.5 14v3.5H21a2 2 0 0 1 0 4h-3.5V21a2 2 0 0 1-4 0v-3.5H14a2 2 0 0 1 0-4h3.5z"/>',
|
|
82
|
+
// settings sidebar — squared, hard-edged outline (Lucide-ish), 2px stroke
|
|
83
|
+
'wrench': '<path d="M14.7 6.3a4 4 0 0 0 5 5L21 12.5l-7.5 7.5a3 3 0 0 1-4.2-4.2L16.7 8 14.7 6.3z"/><path d="M14.7 6.3 12 9l-3-3 2.7-2.7a4 4 0 0 1 3 3z"/>',
|
|
84
|
+
'message-square': '<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/>',
|
|
85
|
+
'file-text': '<path d="M14 3H6v18h12V8z"/><polyline points="14 3 14 8 18 8"/><line x1="9" y1="13" x2="15" y2="13"/><line x1="9" y1="17" x2="15" y2="17"/>',
|
|
86
|
+
'scroll-text': '<path d="M5 4h11a3 3 0 0 1 3 3v10H8v3a1 1 0 0 1-1 1 3 3 0 0 1-3-3V7a3 3 0 0 1 1-3z"/><line x1="9" y1="9" x2="15" y2="9"/><line x1="9" y1="13" x2="15" y2="13"/>',
|
|
87
|
+
'atom': '<circle cx="12" cy="12" r="2"/><ellipse cx="12" cy="12" rx="10" ry="4"/><ellipse cx="12" cy="12" rx="10" ry="4" transform="rotate(60 12 12)"/><ellipse cx="12" cy="12" rx="10" ry="4" transform="rotate(120 12 12)"/>',
|
|
88
|
+
'arrow-right-to-line': '<line x1="20" y1="4" x2="20" y2="20"/><line x1="3" y1="12" x2="17" y2="12"/><polyline points="11 6 17 12 11 18"/>',
|
|
89
|
+
'info-square': '<rect x="3" y="3" width="18" height="18"/><line x1="12" y1="11" x2="12" y2="16"/><line x1="12" y1="8" x2="12" y2="8.01"/>',
|
|
90
|
+
/* Window-control glyphs for SOLO top bar (Figma 2510_20754):
|
|
91
|
+
* .arrow-minimize → diagonal-in arrows (collapse to corners)
|
|
92
|
+
* .icon-expand → diagonal-out arrows (expand to corners) */
|
|
93
|
+
'arrow-minimize': '<polyline points="20 4 14 10 20 10"/><line x1="14" y1="10" x2="14" y2="4"/><polyline points="4 20 10 14 4 14"/><line x1="10" y1="14" x2="10" y2="20"/>',
|
|
94
|
+
'arrow-expand': '<polyline points="14 4 20 4 20 10"/><line x1="14" y1="10" x2="20" y2="4"/><polyline points="10 20 4 20 4 14"/><line x1="10" y1="14" x2="4" y2="20"/>',
|
|
95
|
+
'arrow-down': '<line x1="12" y1="4" x2="12" y2="20"/><polyline points="6 14 12 20 18 14"/>',
|
|
96
|
+
'logo': '<rect x="3" y="3" width="18" height="18"/><line x1="3" y1="9" x2="21" y2="9"/><line x1="9" y1="21" x2="9" y2="9"/>',
|
|
97
|
+
// additional UI
|
|
98
|
+
'more-h': '<circle cx="5" cy="12" r="1.5" fill="currentColor"/><circle cx="12" cy="12" r="1.5" fill="currentColor"/><circle cx="19" cy="12" r="1.5" fill="currentColor"/>',
|
|
99
|
+
'edit': '<path d="M4 20h4l10-10-4-4L4 16v4z"/><path d="M14 6l4 4"/>',
|
|
100
|
+
'trash': '<polyline points="4 6 20 6"/><path d="M6 6v14h12V6"/><path d="M9 6V4h6v2"/><line x1="10" y1="10" x2="10" y2="17"/><line x1="14" y1="10" x2="14" y2="17"/>',
|
|
101
|
+
'file': '<path d="M14 3H6v18h12V7z"/><polyline points="14 3 14 7 18 7"/>',
|
|
102
|
+
// Stacked documents — Lucide "files" (3..21).
|
|
103
|
+
'files': '<path d="M21 8v13H8V3h8z"/><polyline points="16 3 16 8 21 8"/><path d="M8 7H3v14h13v-3"/>',
|
|
104
|
+
// Pure 2×2 grid — Lucide "layout-grid" (3..21).
|
|
105
|
+
'grid-2x2': '<rect x="3" y="3" width="8" height="8"/><rect x="13" y="3" width="8" height="8"/><rect x="3" y="13" width="8" height="8"/><rect x="13" y="13" width="8" height="8"/>',
|
|
106
|
+
'folder': '<path d="M3 6h6l2 3h10v10H3z"/>',
|
|
107
|
+
'layers': '<polygon points="12 3 22 8 12 13 2 8 12 3"/><polyline points="2 13 12 18 22 13"/>',
|
|
108
|
+
'layout': '<rect x="3" y="3" width="18" height="18"/><line x1="3" y1="9" x2="21" y2="9"/><line x1="9" y1="21" x2="9" y2="9"/>',
|
|
109
|
+
'terminal': '<polyline points="4 7 9 12 4 17"/><line x1="12" y1="17" x2="20" y2="17"/>',
|
|
110
|
+
'image': '<rect x="3" y="3" width="18" height="18"/><circle cx="9" cy="9" r="1.5" fill="currentColor"/><polyline points="3 18 9 12 13 16 17 12 21 16"/>',
|
|
111
|
+
'play': '<polygon points="6 4 20 12 6 20 6 4"/>',
|
|
112
|
+
'pause': '<rect x="6" y="4" width="4" height="16"/><rect x="14" y="4" width="4" height="16"/>',
|
|
113
|
+
'help': '<rect x="3" y="3" width="18" height="18"/><path d="M9 9a3 3 0 0 1 6 0c0 2-3 2-3 4"/><line x1="12" y1="17" x2="12" y2="17.01"/>',
|
|
114
|
+
'lock': '<rect x="4" y="11" width="16" height="10"/><path d="M8 11V8a4 4 0 0 1 8 0v3"/>',
|
|
115
|
+
// Lucide "eye" (2..22 horizontal, naturally short — eye shape).
|
|
116
|
+
'eye': '<path d="M2 12s4-7 10-7 10 7 10 7-4 7-10 7-10-7-10-7z"/><circle cx="12" cy="12" r="3"/>',
|
|
117
|
+
'star': '<polygon points="12 3 15 9 22 10 17 14 18 21 12 18 6 21 7 14 2 10 9 9 12 3"/>',
|
|
118
|
+
'heart': '<path d="M12 21s-7-5-7-11a4 4 0 0 1 7-2 4 4 0 0 1 7 2c0 6-7 11-7 11z"/>',
|
|
119
|
+
'home': '<polygon points="3 11 12 3 21 11 21 21 14 21 14 14 10 14 10 21 3 21 3 11"/>',
|
|
120
|
+
'calendar': '<rect x="3" y="5" width="18" height="16"/><line x1="3" y1="10" x2="21" y2="10"/><line x1="8" y1="3" x2="8" y2="7"/><line x1="16" y1="3" x2="16" y2="7"/>',
|
|
121
|
+
'clock': '<circle cx="12" cy="12" r="9"/><polyline points="12 7 12 12 16 14"/>',
|
|
122
|
+
'filter': '<polygon points="3 4 21 4 14 12 14 20 10 18 10 12 3 4"/>',
|
|
123
|
+
'send': '<polygon points="3 12 21 4 17 21 12 13 3 12"/>',
|
|
124
|
+
'link': '<path d="M10 14a4 4 0 0 1 0-6l3-3a4 4 0 0 1 6 6l-1.5 1.5"/><path d="M14 10a4 4 0 0 1 0 6l-3 3a4 4 0 0 1-6-6l1.5-1.5"/>',
|
|
125
|
+
'upload': '<path d="M12 21V9"/><polyline points="7 14 12 9 17 14"/><line x1="3" y1="3" x2="21" y2="3"/>',
|
|
126
|
+
'log-out': '<path d="M14 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h9"/><polyline points="16 16 21 12 16 8"/><line x1="9" y1="12" x2="21" y2="12"/>',
|
|
127
|
+
'menu': '<line x1="4" y1="6" x2="20" y2="6"/><line x1="4" y1="12" x2="20" y2="12"/><line x1="4" y1="18" x2="20" y2="18"/>',
|
|
128
|
+
// data / charts
|
|
129
|
+
'dollar': '<line x1="12" y1="2" x2="12" y2="22"/><path d="M17 6H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"/>',
|
|
130
|
+
'bar': '<line x1="3" y1="21" x2="21" y2="21"/><rect x="5" y="11" width="3" height="8"/><rect x="10.5" y="6" width="3" height="13"/><rect x="16" y="14" width="3" height="5"/>',
|
|
131
|
+
'trending-up': '<polyline points="3 17 9 11 13 15 21 7"/><polyline points="15 7 21 7 21 13"/>',
|
|
132
|
+
'trending-down': '<polyline points="3 7 9 13 13 9 21 17"/><polyline points="15 17 21 17 21 11"/>',
|
|
133
|
+
'columns': '<rect x="3" y="3" width="18" height="18"/><line x1="9" y1="3" x2="9" y2="21"/><line x1="15" y1="3" x2="15" y2="21"/>',
|
|
134
|
+
// settings — framework rules
|
|
135
|
+
'plug': '<path d="M9 2v6"/><path d="M15 2v6"/><path d="M7 8h10v4a5 5 0 0 1-10 0V8z"/><path d="M12 17v5"/>',
|
|
136
|
+
'cpu': '<rect x="6" y="6" width="12" height="12"/><rect x="9" y="9" width="6" height="6"/><line x1="9" y1="2" x2="9" y2="6"/><line x1="15" y1="2" x2="15" y2="6"/><line x1="9" y1="18" x2="9" y2="22"/><line x1="15" y1="18" x2="15" y2="22"/><line x1="2" y1="9" x2="6" y2="9"/><line x1="2" y1="15" x2="6" y2="15"/><line x1="18" y1="9" x2="22" y2="9"/><line x1="18" y1="15" x2="22" y2="15"/>',
|
|
137
|
+
'code': '<polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/>',
|
|
138
|
+
// brand — filled Apple glyph for download CTA
|
|
139
|
+
'apple': '<path fill="currentColor" stroke="none" d="M17.05 12.04c-.03-3.04 2.49-4.5 2.6-4.57-1.42-2.07-3.62-2.36-4.4-2.39-1.87-.19-3.65 1.1-4.6 1.1-.96 0-2.42-1.08-3.98-1.05-2.05.03-3.94 1.19-4.99 3.02-2.13 3.69-.54 9.13 1.53 12.12 1.01 1.46 2.21 3.1 3.78 3.04 1.52-.06 2.09-.98 3.93-.98 1.83 0 2.36.98 3.97.95 1.64-.03 2.68-1.49 3.68-2.96 1.16-1.7 1.64-3.35 1.66-3.43-.04-.02-3.18-1.22-3.21-4.85zM14.06 4.34c.83-1.01 1.39-2.41 1.24-3.81-1.2.05-2.65.8-3.51 1.8-.77.89-1.45 2.31-1.27 3.68 1.34.1 2.71-.68 3.54-1.67z"/>',
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
function svg(name, size = 16, viewBox = '0 0 24 24') {
|
|
143
|
+
const path = PATHS[name];
|
|
144
|
+
if (!path) return '';
|
|
145
|
+
const attrs = ATTRS
|
|
146
|
+
.replace('width="16"', `width="${size}"`)
|
|
147
|
+
.replace('height="16"', `height="${size}"`)
|
|
148
|
+
.replace('viewBox="0 0 24 24"', `viewBox="${viewBox}"`);
|
|
149
|
+
return `<svg ${attrs}>${path}</svg>`;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function render(root = document) {
|
|
153
|
+
root.querySelectorAll('[data-icon]').forEach(el => {
|
|
154
|
+
const name = el.getAttribute('data-icon');
|
|
155
|
+
const size = +el.getAttribute('data-size') || 16;
|
|
156
|
+
const vb = el.getAttribute('data-viewbox') || '0 0 24 24';
|
|
157
|
+
el.innerHTML = svg(name, size, vb);
|
|
158
|
+
el.classList.add('icon');
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
global.Icons = { svg, render, PATHS };
|
|
163
|
+
if (document.readyState !== 'loading') render();
|
|
164
|
+
else document.addEventListener('DOMContentLoaded', () => render());
|
|
165
|
+
})(typeof window !== 'undefined' ? window : globalThis);
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
class ImagePreview {
|
|
2
|
+
constructor(options = {}) {
|
|
3
|
+
this.images = options.images || [];
|
|
4
|
+
this.currentIndex = options.currentIndex || 0;
|
|
5
|
+
this.overlay = null;
|
|
6
|
+
this.closeHandler = this.close.bind(this);
|
|
7
|
+
this.keyHandler = this.handleKeydown.bind(this);
|
|
8
|
+
this.clickHandler = this.handleOverlayClick.bind(this);
|
|
9
|
+
|
|
10
|
+
this.init();
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
init() {
|
|
14
|
+
this.createOverlay();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
createOverlay() {
|
|
18
|
+
this.overlay = document.createElement('div');
|
|
19
|
+
this.overlay.className = 'ds-image-preview-overlay';
|
|
20
|
+
this.overlay.innerHTML = `
|
|
21
|
+
<button class="ds-image-preview__close" type="button" aria-label="Close preview">
|
|
22
|
+
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
23
|
+
<path d="M18 6L6 18"/>
|
|
24
|
+
<path d="M6 6l12 12"/>
|
|
25
|
+
</svg>
|
|
26
|
+
</button>
|
|
27
|
+
<div class="ds-image-preview__nav">
|
|
28
|
+
<button class="ds-image-preview__nav-btn ds-image-preview__nav-btn--prev" type="button" aria-label="Previous image">
|
|
29
|
+
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
30
|
+
<polyline points="15 18 9 12 15 6"/>
|
|
31
|
+
</svg>
|
|
32
|
+
</button>
|
|
33
|
+
<button class="ds-image-preview__nav-btn ds-image-preview__nav-btn--next" type="button" aria-label="Next image">
|
|
34
|
+
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
35
|
+
<polyline points="9 18 15 12 9 6"/>
|
|
36
|
+
</svg>
|
|
37
|
+
</button>
|
|
38
|
+
</div>
|
|
39
|
+
<div class="ds-image-preview__content">
|
|
40
|
+
<img src="" alt="" />
|
|
41
|
+
</div>
|
|
42
|
+
<div class="ds-image-preview__info">
|
|
43
|
+
<div class="ds-image-preview__title"></div>
|
|
44
|
+
<div class="ds-image-preview__meta"></div>
|
|
45
|
+
</div>
|
|
46
|
+
<div class="ds-image-preview__indicators"></div>
|
|
47
|
+
`;
|
|
48
|
+
|
|
49
|
+
document.body.appendChild(this.overlay);
|
|
50
|
+
|
|
51
|
+
this.bindEvents();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
bindEvents() {
|
|
55
|
+
const closeBtn = this.overlay.querySelector('.ds-image-preview__close');
|
|
56
|
+
const prevBtn = this.overlay.querySelector('.ds-image-preview__nav-btn--prev');
|
|
57
|
+
const nextBtn = this.overlay.querySelector('.ds-image-preview__nav-btn--next');
|
|
58
|
+
|
|
59
|
+
this._prevHandler = () => this.prev();
|
|
60
|
+
this._nextHandler = () => this.next();
|
|
61
|
+
|
|
62
|
+
closeBtn.addEventListener('click', this.closeHandler);
|
|
63
|
+
prevBtn.addEventListener('click', this._prevHandler);
|
|
64
|
+
nextBtn.addEventListener('click', this._nextHandler);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
handleKeydown(e) {
|
|
68
|
+
if (!this.overlay.classList.contains('is-visible')) return;
|
|
69
|
+
|
|
70
|
+
switch (e.key) {
|
|
71
|
+
case 'Escape':
|
|
72
|
+
this.close();
|
|
73
|
+
break;
|
|
74
|
+
case 'ArrowLeft':
|
|
75
|
+
this.prev();
|
|
76
|
+
break;
|
|
77
|
+
case 'ArrowRight':
|
|
78
|
+
this.next();
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
handleOverlayClick(e) {
|
|
84
|
+
if (e.target === this.overlay) {
|
|
85
|
+
this.close();
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
show(images, index = 0) {
|
|
90
|
+
this.images = images;
|
|
91
|
+
this.currentIndex = Math.min(Math.max(index, 0), images.length - 1);
|
|
92
|
+
|
|
93
|
+
this.render();
|
|
94
|
+
this.overlay.classList.add('is-visible');
|
|
95
|
+
|
|
96
|
+
document.addEventListener('keydown', this.keyHandler);
|
|
97
|
+
this.overlay.addEventListener('click', this.clickHandler);
|
|
98
|
+
document.body.style.overflow = 'hidden';
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
close() {
|
|
102
|
+
this.overlay.classList.remove('is-visible');
|
|
103
|
+
|
|
104
|
+
document.removeEventListener('keydown', this.keyHandler);
|
|
105
|
+
this.overlay.removeEventListener('click', this.clickHandler);
|
|
106
|
+
document.body.style.overflow = '';
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
prev() {
|
|
110
|
+
if (this.currentIndex > 0) {
|
|
111
|
+
this.currentIndex--;
|
|
112
|
+
this.render();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
next() {
|
|
117
|
+
if (this.currentIndex < this.images.length - 1) {
|
|
118
|
+
this.currentIndex++;
|
|
119
|
+
this.render();
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
goTo(index) {
|
|
124
|
+
if (index >= 0 && index < this.images.length) {
|
|
125
|
+
this.currentIndex = index;
|
|
126
|
+
this.render();
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
render() {
|
|
131
|
+
const img = this.overlay.querySelector('.ds-image-preview__content img');
|
|
132
|
+
const title = this.overlay.querySelector('.ds-image-preview__title');
|
|
133
|
+
const meta = this.overlay.querySelector('.ds-image-preview__meta');
|
|
134
|
+
const indicators = this.overlay.querySelector('.ds-image-preview__indicators');
|
|
135
|
+
const prevBtn = this.overlay.querySelector('.ds-image-preview__nav-btn--prev');
|
|
136
|
+
const nextBtn = this.overlay.querySelector('.ds-image-preview__nav-btn--next');
|
|
137
|
+
|
|
138
|
+
const currentImage = this.images[this.currentIndex];
|
|
139
|
+
|
|
140
|
+
img.src = currentImage.src;
|
|
141
|
+
img.alt = currentImage.alt || '';
|
|
142
|
+
title.textContent = currentImage.title || '';
|
|
143
|
+
meta.textContent = currentImage.meta || `${this.currentIndex + 1} / ${this.images.length}`;
|
|
144
|
+
|
|
145
|
+
prevBtn.disabled = this.currentIndex === 0;
|
|
146
|
+
nextBtn.disabled = this.currentIndex === this.images.length - 1;
|
|
147
|
+
|
|
148
|
+
indicators.innerHTML = this.images.map((_, i) => `
|
|
149
|
+
<button class="ds-image-preview__indicator${i === this.currentIndex ? ' is-active' : ''}" type="button" data-index="${i}" aria-label="Go to image ${i + 1}"></button>
|
|
150
|
+
`).join('');
|
|
151
|
+
|
|
152
|
+
indicators.querySelectorAll('.ds-image-preview__indicator').forEach(indicator => {
|
|
153
|
+
const clickHandler = () => {
|
|
154
|
+
this.goTo(parseInt(indicator.dataset.index));
|
|
155
|
+
};
|
|
156
|
+
indicator.addEventListener('click', clickHandler);
|
|
157
|
+
indicator._clickHandler = clickHandler;
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
destroy() {
|
|
162
|
+
this.close();
|
|
163
|
+
|
|
164
|
+
const indicators = this.overlay?.querySelector('.ds-image-preview__indicators');
|
|
165
|
+
if (indicators) {
|
|
166
|
+
indicators.querySelectorAll('.ds-image-preview__indicator').forEach(indicator => {
|
|
167
|
+
if (indicator._clickHandler) {
|
|
168
|
+
indicator.removeEventListener('click', indicator._clickHandler);
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const closeBtn = this.overlay?.querySelector('.ds-image-preview__close');
|
|
174
|
+
const prevBtn = this.overlay?.querySelector('.ds-image-preview__nav-btn--prev');
|
|
175
|
+
const nextBtn = this.overlay?.querySelector('.ds-image-preview__nav-btn--next');
|
|
176
|
+
|
|
177
|
+
if (closeBtn) {
|
|
178
|
+
closeBtn.removeEventListener('click', this.closeHandler);
|
|
179
|
+
}
|
|
180
|
+
if (prevBtn && this._prevHandler) {
|
|
181
|
+
prevBtn.removeEventListener('click', this._prevHandler);
|
|
182
|
+
}
|
|
183
|
+
if (nextBtn && this._nextHandler) {
|
|
184
|
+
nextBtn.removeEventListener('click', this._nextHandler);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (this.overlay && this.overlay.parentNode) {
|
|
188
|
+
this.overlay.parentNode.removeChild(this.overlay);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
let imagePreviewInstance = null;
|
|
194
|
+
|
|
195
|
+
function initImagePreview() {
|
|
196
|
+
if (!imagePreviewInstance) {
|
|
197
|
+
imagePreviewInstance = new ImagePreview();
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
document.querySelectorAll('[data-image-preview]').forEach(trigger => {
|
|
201
|
+
trigger.addEventListener('click', () => {
|
|
202
|
+
const images = JSON.parse(trigger.getAttribute('data-image-preview'));
|
|
203
|
+
const index = parseInt(trigger.getAttribute('data-image-index')) || 0;
|
|
204
|
+
imagePreviewInstance.show(images, index);
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function showImagePreview(images, index = 0) {
|
|
210
|
+
if (!imagePreviewInstance) {
|
|
211
|
+
imagePreviewInstance = new ImagePreview();
|
|
212
|
+
}
|
|
213
|
+
imagePreviewInstance.show(images, index);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (typeof module !== 'undefined' && module.exports) {
|
|
217
|
+
module.exports = { ImagePreview, initImagePreview, showImagePreview };
|
|
218
|
+
}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
class ComponentInitializerRegistry {
|
|
2
|
+
constructor() {
|
|
3
|
+
this.initializers = new Map();
|
|
4
|
+
this.cleanupFunctions = new Map();
|
|
5
|
+
this.processedElements = new WeakSet();
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
register(name, initFn, cleanupFn = null) {
|
|
9
|
+
this.initializers.set(name, initFn);
|
|
10
|
+
if (cleanupFn) {
|
|
11
|
+
this.cleanupFunctions.set(name, cleanupFn);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
unregister(name) {
|
|
16
|
+
this.initializers.delete(name);
|
|
17
|
+
this.cleanupFunctions.delete(name);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
has(name) {
|
|
21
|
+
return this.initializers.has(name);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
get(name) {
|
|
25
|
+
return this.initializers.get(name);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async initialize(element) {
|
|
29
|
+
if (this.processedElements.has(element)) return;
|
|
30
|
+
|
|
31
|
+
const dataAttrs = ['data-component', 'data-dropdown', 'data-select', 'data-datepicker',
|
|
32
|
+
'data-timepicker', 'data-slider', 'data-carousel', 'data-drawer',
|
|
33
|
+
'data-modal', 'data-dialog', 'data-color-picker', 'data-calendar',
|
|
34
|
+
'data-slide-captcha', 'data-heatmap'];
|
|
35
|
+
|
|
36
|
+
for (const attr of dataAttrs) {
|
|
37
|
+
const value = element.getAttribute(attr);
|
|
38
|
+
if (value) {
|
|
39
|
+
const name = value || attr.replace('data-', '');
|
|
40
|
+
const initFn = this.initializers.get(name) || this.initializers.get(attr.replace('data-', ''));
|
|
41
|
+
|
|
42
|
+
if (initFn) {
|
|
43
|
+
try {
|
|
44
|
+
await initFn(element);
|
|
45
|
+
this.processedElements.add(element);
|
|
46
|
+
} catch (error) {
|
|
47
|
+
console.error(`[ComponentInitializerRegistry] Error initializing "${name}":`, error);
|
|
48
|
+
}
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const className = element.className;
|
|
55
|
+
const classSelectors = [
|
|
56
|
+
'.ds-dropdown', '.ds-select', '.ds-datepicker', '.ds-timepicker',
|
|
57
|
+
'.ds-slider', '.ds-carousel', '.ds-drawer', '.ds-modal', '.ds-dialog',
|
|
58
|
+
'.ds-color-picker', '.ds-calendar', '.ds-slider-captcha', '.ds-heatmap',
|
|
59
|
+
'.ds-tooltip', '.ds-tag', '.ds-statcard', '.ds-collapse', '.ds-fileupload',
|
|
60
|
+
'.ds-notification', '.ds-message'
|
|
61
|
+
];
|
|
62
|
+
|
|
63
|
+
for (const selector of classSelectors) {
|
|
64
|
+
const classNamePart = selector.replace('.', '');
|
|
65
|
+
if (className.includes(classNamePart)) {
|
|
66
|
+
const name = classNamePart.replace('ds-', '');
|
|
67
|
+
const initFn = this.initializers.get(name) || this.initializers.get(classNamePart);
|
|
68
|
+
|
|
69
|
+
if (initFn) {
|
|
70
|
+
try {
|
|
71
|
+
await initFn(element);
|
|
72
|
+
this.processedElements.add(element);
|
|
73
|
+
} catch (error) {
|
|
74
|
+
console.error(`[ComponentInitializerRegistry] Error initializing "${name}":`, error);
|
|
75
|
+
}
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
cleanup(element) {
|
|
83
|
+
const dataAttrs = ['data-component', 'data-dropdown', 'data-select', 'data-datepicker',
|
|
84
|
+
'data-timepicker', 'data-slider', 'data-carousel', 'data-drawer',
|
|
85
|
+
'data-modal', 'data-dialog', 'data-color-picker', 'data-calendar',
|
|
86
|
+
'data-slide-captcha', 'data-heatmap'];
|
|
87
|
+
|
|
88
|
+
for (const attr of dataAttrs) {
|
|
89
|
+
const value = element.getAttribute(attr);
|
|
90
|
+
if (value) {
|
|
91
|
+
const name = value || attr.replace('data-', '');
|
|
92
|
+
const cleanupFn = this.cleanupFunctions.get(name) || this.cleanupFunctions.get(attr.replace('data-', ''));
|
|
93
|
+
|
|
94
|
+
if (cleanupFn) {
|
|
95
|
+
try {
|
|
96
|
+
cleanupFn(element);
|
|
97
|
+
} catch (error) {
|
|
98
|
+
console.error(`[ComponentInitializerRegistry] Error cleaning up "${name}":`, error);
|
|
99
|
+
}
|
|
100
|
+
this.processedElements.delete(element);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const className = element.className;
|
|
107
|
+
const classSelectors = [
|
|
108
|
+
'.ds-dropdown', '.ds-select', '.ds-datepicker', '.ds-timepicker',
|
|
109
|
+
'.ds-slider', '.ds-carousel', '.ds-drawer', '.ds-modal', '.ds-dialog',
|
|
110
|
+
'.ds-color-picker', '.ds-calendar', '.ds-slider-captcha', '.ds-heatmap',
|
|
111
|
+
'.ds-tooltip', '.ds-tag', '.ds-statcard', '.ds-collapse', '.ds-fileupload',
|
|
112
|
+
'.ds-notification', '.ds-message'
|
|
113
|
+
];
|
|
114
|
+
|
|
115
|
+
for (const selector of classSelectors) {
|
|
116
|
+
const classNamePart = selector.replace('.', '');
|
|
117
|
+
if (className.includes(classNamePart)) {
|
|
118
|
+
const name = classNamePart.replace('ds-', '');
|
|
119
|
+
const cleanupFn = this.cleanupFunctions.get(name) || this.cleanupFunctions.get(classNamePart);
|
|
120
|
+
|
|
121
|
+
if (cleanupFn) {
|
|
122
|
+
try {
|
|
123
|
+
cleanupFn(element);
|
|
124
|
+
} catch (error) {
|
|
125
|
+
console.error(`[ComponentInitializerRegistry] Error cleaning up "${name}":`, error);
|
|
126
|
+
}
|
|
127
|
+
this.processedElements.delete(element);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
async initializeAll(root = document) {
|
|
135
|
+
const elements = root.querySelectorAll('[data-component], [data-dropdown], [data-select], ' +
|
|
136
|
+
'[data-datepicker], [data-timepicker], [data-slider], [data-carousel], ' +
|
|
137
|
+
'[data-drawer], [data-modal], [data-dialog], [data-color-picker], ' +
|
|
138
|
+
'[data-calendar], [data-slide-captcha], [data-heatmap], ' +
|
|
139
|
+
'.ds-dropdown, .ds-select, .ds-datepicker, .ds-timepicker, ' +
|
|
140
|
+
'.ds-slider, .ds-carousel, .ds-drawer, .ds-modal, .ds-dialog, ' +
|
|
141
|
+
'.ds-color-picker, .ds-calendar, .ds-slider-captcha, .ds-heatmap, ' +
|
|
142
|
+
'.ds-tooltip, .ds-tag, .ds-statcard, .ds-collapse, .ds-fileupload, ' +
|
|
143
|
+
'.ds-notification, .ds-message');
|
|
144
|
+
|
|
145
|
+
const promises = [];
|
|
146
|
+
elements.forEach(element => {
|
|
147
|
+
if (!this.processedElements.has(element)) {
|
|
148
|
+
promises.push(this.initialize(element));
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
await Promise.all(promises);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const kupolaInitializer = new ComponentInitializerRegistry();
|
|
156
|
+
|
|
157
|
+
if (typeof module !== 'undefined' && module.exports) {
|
|
158
|
+
module.exports = { ComponentInitializerRegistry, kupolaInitializer };
|
|
159
|
+
} else {
|
|
160
|
+
window.ComponentInitializerRegistry = ComponentInitializerRegistry;
|
|
161
|
+
window.kupolaInitializer = kupolaInitializer;
|
|
162
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
if (typeof window === 'undefined') {
|
|
2
|
+
const { KupolaComponent, applyMixin } = require('./component.js');
|
|
3
|
+
const { KupolaComponentRegistry } = require('./registry.js');
|
|
4
|
+
const { KupolaRouter, createRouter } = require('./router.js');
|
|
5
|
+
const { KupolaHttp, createHttp } = require('./http.js');
|
|
6
|
+
|
|
7
|
+
module.exports = {
|
|
8
|
+
KupolaComponent,
|
|
9
|
+
applyMixin,
|
|
10
|
+
KupolaComponentRegistry,
|
|
11
|
+
KupolaRouter,
|
|
12
|
+
KupolaHttp,
|
|
13
|
+
createRouter,
|
|
14
|
+
createHttp
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (window.KupolaComponentRegistry) {
|
|
19
|
+
window.kupolaRegistry = new window.KupolaComponentRegistry();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async function kupolaBootstrap() {
|
|
23
|
+
if (window.kupolaData) {
|
|
24
|
+
window.kupolaData.loadPersisted();
|
|
25
|
+
}
|
|
26
|
+
if (window.kupolaRegistry) {
|
|
27
|
+
await window.kupolaRegistry.bootstrap();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (document.readyState === 'loading') {
|
|
32
|
+
document.addEventListener('DOMContentLoaded', kupolaBootstrap);
|
|
33
|
+
} else {
|
|
34
|
+
setTimeout(kupolaBootstrap, 0);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
window.registerComponent = function(name, componentClass) {
|
|
38
|
+
if (window.kupolaRegistry) {
|
|
39
|
+
window.kupolaRegistry.register(name, componentClass);
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
window.registerLazyComponent = function(name, loader) {
|
|
44
|
+
if (window.kupolaRegistry) {
|
|
45
|
+
window.kupolaRegistry.registerLazy(name, loader);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
window.bootstrapComponents = function(root) {
|
|
50
|
+
if (window.kupolaRegistry) {
|
|
51
|
+
return window.kupolaRegistry.bootstrap(root);
|
|
52
|
+
}
|
|
53
|
+
return Promise.resolve();
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
window.defineMixin = function(name, mixin) {
|
|
57
|
+
if (window.kupolaRegistry) {
|
|
58
|
+
window.kupolaRegistry.defineMixin(name, mixin);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
window.useMixin = function(componentClass, ...mixinNames) {
|
|
63
|
+
if (window.kupolaRegistry) {
|
|
64
|
+
window.kupolaRegistry.useMixin(componentClass, ...mixinNames);
|
|
65
|
+
}
|
|
66
|
+
};
|