@vela-studio/ui 1.0.1

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 (68) hide show
  1. package/README.md +152 -0
  2. package/dist/index.d.ts +696 -0
  3. package/dist/index.js +10 -0
  4. package/dist/index.js.map +1 -0
  5. package/dist/index.mjs +11786 -0
  6. package/dist/index.mjs.map +1 -0
  7. package/dist/index.umd.js +10 -0
  8. package/dist/index.umd.js.map +1 -0
  9. package/dist/style.css +1 -0
  10. package/index.ts +150 -0
  11. package/package.json +73 -0
  12. package/src/components/advanced/scripting/Scripting.vue +189 -0
  13. package/src/components/advanced/state/State.vue +231 -0
  14. package/src/components/advanced/trigger/Trigger.vue +256 -0
  15. package/src/components/basic/button/Button.vue +120 -0
  16. package/src/components/basic/container/Container.vue +22 -0
  17. package/src/components/chart/barChart/barChart.vue +176 -0
  18. package/src/components/chart/doughnutChart/doughnutChart.vue +128 -0
  19. package/src/components/chart/funnelChart/funnelChart.vue +128 -0
  20. package/src/components/chart/gaugeChart/gaugeChart.vue +144 -0
  21. package/src/components/chart/lineChart/lineChart.vue +188 -0
  22. package/src/components/chart/pieChart/pieChart.vue +114 -0
  23. package/src/components/chart/radarChart/radarChart.vue +115 -0
  24. package/src/components/chart/sankeyChart/sankeyChart.vue +144 -0
  25. package/src/components/chart/scatterChart/scatterChart.vue +162 -0
  26. package/src/components/chart/stackedBarChart/stackedBarChart.vue +184 -0
  27. package/src/components/content/html/Html.vue +104 -0
  28. package/src/components/content/iframe/Iframe.vue +111 -0
  29. package/src/components/content/markdown/Markdown.vue +174 -0
  30. package/src/components/controls/breadcrumb/Breadcrumb.vue +79 -0
  31. package/src/components/controls/buttonGroup/ButtonGroup.vue +93 -0
  32. package/src/components/controls/checkboxGroup/CheckboxGroup.vue +147 -0
  33. package/src/components/controls/dateRange/DateRange.vue +174 -0
  34. package/src/components/controls/multiSelect/MultiSelect.vue +155 -0
  35. package/src/components/controls/navButton/NavButton.vue +97 -0
  36. package/src/components/controls/pagination/Pagination.vue +94 -0
  37. package/src/components/controls/searchBox/SearchBox.vue +170 -0
  38. package/src/components/controls/select/Select.vue +134 -0
  39. package/src/components/controls/slider/Slider.vue +167 -0
  40. package/src/components/controls/switch/Switch.vue +107 -0
  41. package/src/components/data/cardGrid/CardGrid.vue +318 -0
  42. package/src/components/data/list/List.vue +282 -0
  43. package/src/components/data/pivot/Pivot.vue +270 -0
  44. package/src/components/data/table/Table.vue +150 -0
  45. package/src/components/data/timeline/Timeline.vue +315 -0
  46. package/src/components/group/Group.vue +75 -0
  47. package/src/components/kpi/box/Box.vue +98 -0
  48. package/src/components/kpi/countUp/CountUp.vue +193 -0
  49. package/src/components/kpi/progress/Progress.vue +159 -0
  50. package/src/components/kpi/stat/Stat.vue +205 -0
  51. package/src/components/kpi/text/Text.vue +74 -0
  52. package/src/components/layout/badge/Badge.vue +105 -0
  53. package/src/components/layout/col/Col.vue +114 -0
  54. package/src/components/layout/flex/Flex.vue +105 -0
  55. package/src/components/layout/grid/Grid.vue +89 -0
  56. package/src/components/layout/modal/Modal.vue +118 -0
  57. package/src/components/layout/panel/Panel.vue +162 -0
  58. package/src/components/layout/row/Row.vue +99 -0
  59. package/src/components/layout/tabs/Tabs.vue +117 -0
  60. package/src/components/media/image/Image.vue +132 -0
  61. package/src/components/media/video/Video.vue +115 -0
  62. package/src/components/v2/basic/BaseButton.vue +179 -0
  63. package/src/components/v2/kpi/KpiCard.vue +215 -0
  64. package/src/components/v2/layout/GridBox.vue +55 -0
  65. package/src/hooks/useDataSource.ts +123 -0
  66. package/src/types/gis.ts +251 -0
  67. package/src/utils/chartUtils.ts +349 -0
  68. package/src/utils/dataUtils.ts +403 -0
package/dist/style.css ADDED
@@ -0,0 +1 @@
1
+ .scripting-container[data-v-a842ba5d]{display:flex;flex-direction:column;gap:12px;height:100%}.header[data-v-a842ba5d]{display:flex;justify-content:space-between;align-items:center;padding-bottom:8px;border-bottom:1px solid #3c3c3c}.title[data-v-a842ba5d]{display:flex;align-items:center;gap:6px;font-weight:600;font-size:16px}.section-title[data-v-a842ba5d]{font-size:12px;opacity:.7;margin-bottom:6px;text-transform:uppercase}.code-section[data-v-a842ba5d]{flex-shrink:0}.code-block[data-v-a842ba5d]{margin:0;padding:12px;background:#0000004d;border-radius:4px;overflow-x:auto;white-space:pre-wrap;word-wrap:break-word}.output-section[data-v-a842ba5d]{flex:1;min-height:0;display:flex;flex-direction:column}.output-block[data-v-a842ba5d]{flex:1;margin:0;padding:12px;background:#0003;border-radius:4px;overflow:auto;white-space:pre-wrap;word-wrap:break-word;color:#4ec9b0}.error-output[data-v-a842ba5d]{flex:1;padding:12px;background:#dc26261a;border:1px solid rgba(220,38,38,.3);border-radius:4px;color:#f87171;overflow:auto}.placeholder[data-v-a842ba5d]{display:flex;flex-direction:column;justify-content:center;align-items:center;flex:1;gap:8px;opacity:.5}.placeholder .el-icon[data-v-a842ba5d]{font-size:32px}.state-container[data-v-d334f558]{display:flex;flex-direction:column;gap:12px;height:100%}.header[data-v-d334f558]{display:flex;justify-content:space-between;align-items:center;padding-bottom:8px;border-bottom:1px solid #3c3c3c}.title[data-v-d334f558]{display:flex;align-items:center;gap:6px;font-weight:600;font-size:16px}.state-list[data-v-d334f558]{flex:1;overflow-y:auto;display:flex;flex-direction:column;gap:8px}.state-item[data-v-d334f558]{padding:12px;background:#0003;border-radius:4px;border:1px solid rgba(255,255,255,.1)}.state-key[data-v-d334f558]{display:flex;align-items:center;gap:6px;font-weight:600;margin-bottom:6px;color:#4fc3f7}.state-value[data-v-d334f558]{display:flex;align-items:center;gap:8px;padding-left:24px}.value-text[data-v-d334f558]{flex:1;word-break:break-all}.json-view[data-v-d334f558]{flex:1;overflow:auto}.json-block[data-v-d334f558]{margin:0;padding:12px;background:#0000004d;border-radius:4px;white-space:pre;overflow-x:auto;color:#9cdcfe}.table-view[data-v-d334f558]{flex:1;overflow:auto}.placeholder[data-v-d334f558]{display:flex;flex-direction:column;justify-content:center;align-items:center;flex:1;gap:8px;opacity:.5}.placeholder .el-icon[data-v-d334f558]{font-size:32px}.trigger-container[data-v-8a732abe]{display:flex;flex-direction:column;gap:12px;height:100%}.header[data-v-8a732abe]{display:flex;justify-content:space-between;align-items:center;padding-bottom:8px;border-bottom:1px solid #3c3c3c}.title[data-v-8a732abe]{display:flex;align-items:center;gap:6px;font-weight:600;font-size:16px}.controls[data-v-8a732abe]{display:flex;gap:8px;align-items:center}.info-section[data-v-8a732abe]{display:flex;gap:16px;flex-wrap:wrap;padding:8px 0}.info-item[data-v-8a732abe]{display:flex;align-items:center;gap:6px}.label[data-v-8a732abe]{opacity:.7;font-size:12px}.section-title[data-v-8a732abe]{font-size:12px;opacity:.7;margin-bottom:8px;text-transform:uppercase}.logs-section[data-v-8a732abe]{flex:1;min-height:0;display:flex;flex-direction:column}.logs-container[data-v-8a732abe]{flex:1;overflow-y:auto;background:#0000004d;border-radius:4px;padding:8px}.log-item[data-v-8a732abe]{display:flex;gap:12px;padding:6px 8px;margin-bottom:4px;border-radius:3px;font-size:12px;border-left:3px solid transparent}.log-info[data-v-8a732abe]{background:#3b82f61a;border-left-color:#3b82f6}.log-success[data-v-8a732abe]{background:#22c55e1a;border-left-color:#22c55e}.log-warning[data-v-8a732abe]{background:#fbbf241a;border-left-color:#fbbf24}.log-error[data-v-8a732abe]{background:#ef44441a;border-left-color:#ef4444}.log-time[data-v-8a732abe]{opacity:.6;flex-shrink:0;width:80px}.log-message[data-v-8a732abe]{flex:1;word-break:break-all}.placeholder[data-v-8a732abe]{display:flex;flex-direction:column;justify-content:center;align-items:center;height:100%;gap:8px;opacity:.5}.placeholder .el-icon[data-v-8a732abe]{font-size:32px}.v-container[data-v-b420dc1d]{box-sizing:border-box;position:relative;min-height:50px}.v-bar-chart[data-v-63999390],.echart[data-v-63999390],.v-doughnut-chart[data-v-1651b0b6],.echart[data-v-1651b0b6],.v-funnel-chart[data-v-0beabf00],.echart[data-v-0beabf00],.v-gauge-chart[data-v-f996aeef],.echart[data-v-f996aeef],.v-line-chart[data-v-da6535a9],.echart[data-v-da6535a9],.v-pie-chart[data-v-721c1618],.echart[data-v-721c1618],.v-radar-chart[data-v-a6f641d1],.echart[data-v-a6f641d1],.v-sankey-chart[data-v-b5838036],.echart[data-v-b5838036],.v-scatter-chart[data-v-312d4826],.echart[data-v-312d4826],.v-stacked-bar-chart[data-v-6ed5b757],.echart[data-v-6ed5b757]{width:100%;height:100%}.html-container[data-v-6e6f6510],.html-container[data-v-6e6f6510] *{box-sizing:border-box}.html-container[data-v-6e6f6510] img{max-width:100%;height:auto}.html-container[data-v-6e6f6510] table{border-collapse:collapse;width:100%}.html-container[data-v-6e6f6510] table th,.html-container[data-v-6e6f6510] table td{padding:8px;border:1px solid #ddd}.html-container[data-v-6e6f6510] a{color:#409eff;text-decoration:none}.html-container[data-v-6e6f6510] a:hover{text-decoration:underline}.iframe-container[data-v-7d8f952d]{position:relative}.iframe-mask[data-v-7d8f952d]{position:absolute;top:0;left:0;width:100%;height:100%;background:transparent;z-index:1;pointer-events:auto}.runtime-mode{display:none}.iframe-placeholder[data-v-7d8f952d]{display:flex;flex-direction:column;justify-content:center;align-items:center;width:100%;height:100%;color:#909399;font-size:14px;gap:8px;background-color:#f5f7fa}.iframe-placeholder .el-icon[data-v-7d8f952d]{font-size:48px;color:#c0c4cc}.markdown-body[data-v-73416739]{box-sizing:border-box}.markdown-body[data-v-73416739] h1,.markdown-body[data-v-73416739] h2,.markdown-body[data-v-73416739] h3,.markdown-body[data-v-73416739] h4,.markdown-body[data-v-73416739] h5,.markdown-body[data-v-73416739] h6{margin-top:24px;margin-bottom:16px;font-weight:600;line-height:1.25}.markdown-body[data-v-73416739] h1{font-size:2em;border-bottom:1px solid #eaecef;padding-bottom:.3em}.markdown-body[data-v-73416739] h2{font-size:1.5em;border-bottom:1px solid #eaecef;padding-bottom:.3em}.markdown-body[data-v-73416739] h3{font-size:1.25em}.markdown-body[data-v-73416739] p{margin-top:0;margin-bottom:16px}.markdown-body[data-v-73416739] ul,.markdown-body[data-v-73416739] ol{padding-left:2em;margin-top:0;margin-bottom:16px}.markdown-body[data-v-73416739] li{margin-bottom:4px}.markdown-body[data-v-73416739] code{padding:.2em .4em;margin:0;font-size:85%;background-color:#afb8c133;border-radius:6px;font-family:monospace}.markdown-body[data-v-73416739] pre{padding:16px;overflow:auto;font-size:85%;line-height:1.45;background-color:#f6f8fa;border-radius:6px;margin-bottom:16px}.markdown-body[data-v-73416739] pre code{background-color:transparent;padding:0}.markdown-body[data-v-73416739] blockquote{padding:0 1em;color:#6a737d;border-left:.25em solid #dfe2e5;margin:0 0 16px}.markdown-body[data-v-73416739] table{border-collapse:collapse;width:100%;margin-bottom:16px}.markdown-body[data-v-73416739] table th,.markdown-body[data-v-73416739] table td{padding:6px 13px;border:1px solid #dfe2e5}.markdown-body[data-v-73416739] table th{font-weight:600;background-color:#f6f8fa}.markdown-body[data-v-73416739] img{max-width:100%;box-sizing:content-box}.markdown-body[data-v-73416739] a{color:#0366d6;text-decoration:none}.markdown-body[data-v-73416739] a:hover{text-decoration:underline}.custom-breadcrumb[data-v-a480654b]{padding:8px 16px}.link[data-v-a480654b]{cursor:pointer;color:var(--breadcrumb-link-color, #409eff)}.link[data-v-a480654b]:hover{text-decoration:underline}.current[data-v-a480654b]{color:var(--breadcrumb-active-color, #909399)}[data-v-812ca27f] .el-button-group{display:flex}[data-v-baa6f88d] .el-checkbox-group{display:flex;flex-direction:var(--v0c48ab70);gap:var(--v02d3b180)}[data-v-baa6f88d] .el-checkbox{--el-checkbox-checked-bg-color: var(--v531127bf);--el-checkbox-checked-input-border-color: var(--v53533c6e);--el-checkbox-input-border-color: var(--v69bc1e63);--el-checkbox-text-color: var(--v29640901)}[data-v-baa6f88d] .el-checkbox-button{--el-checkbox-button-checked-bg-color: var(--v531127bf);--el-checkbox-button-checked-border-color: var(--v53533c6e)}.date-range-container[data-v-4992eb7f],.multi-select-container[data-v-b009a2c2]{box-sizing:border-box}.nav-button[data-v-4f78f794]{-webkit-user-select:none;user-select:none;font-weight:500}.nav-button[data-v-4f78f794]:hover{filter:brightness(1.1);transform:translateY(-1px)}.nav-button[data-v-4f78f794]:active{transform:translateY(0);filter:brightness(.95)}.nav-icon[data-v-4f78f794]{flex-shrink:0}.nav-label[data-v-4f78f794]{white-space:nowrap}.pagination-container[data-v-36bfc009]{display:flex;justify-content:center;padding:8px}[data-v-36bfc009] .el-pagination{justify-content:center}.el-input[data-v-75e631db]{width:var(--v548c0e80);font-size:var(--v05978894)}[data-v-75e631db] .el-input__wrapper{--el-input-border-color: var(--fc02e812);--el-input-focus-border-color: var(--v78a9160c);--el-input-hover-border-color: var(--v1ade65b0)}[data-v-75e631db] .el-input__inner{color:var(--v7b9fe278)}[data-v-75e631db] .el-input__inner::placeholder{color:var(--v74d660ec)}.select-container[data-v-34a8e7c2]{box-sizing:border-box}.slider-value[data-v-19b2dde7]{margin-top:8px}[data-v-19b2dde7] .el-slider{--el-slider-main-bg-color: var(--v106b612d);--el-slider-runway-bg-color: var(--v2f9594c2);--el-slider-button-size: var(--v6b7e6a0c)}[data-v-6666ea8d] .el-switch{--el-switch-on-color: var(--f73eaa90);--el-switch-off-color: var(--v094fa838);--el-switch-border-color: var(--v69c07005)}.card-grid-container[data-v-76760ba3]{box-sizing:border-box}.empty-state[data-v-76760ba3]{display:flex;align-items:center;justify-content:center;min-height:200px}.grid-wrapper[data-v-76760ba3]{width:100%}.grid-card[data-v-76760ba3]:hover{transform:translateY(-4px);box-shadow:0 4px 12px #00000026}.card-image img[data-v-76760ba3]{width:100%;height:100%;object-fit:cover}.card-content[data-v-76760ba3]{display:flex;flex-direction:column}.card-tags[data-v-76760ba3]{display:flex;flex-wrap:wrap;margin-top:4px;margin-right:-6px}.list-container[data-v-48008813]{box-sizing:border-box}.empty-state[data-v-48008813]{display:flex;align-items:center;justify-content:center;min-height:200px}.list-wrapper[data-v-48008813]{width:100%}.list-item[data-v-48008813]{display:flex;align-items:center;gap:12px;box-sizing:border-box}.list-item[data-v-48008813]:hover{background-color:#f5f7fa!important}.item-icon[data-v-48008813]{flex-shrink:0;display:flex;align-items:center;justify-content:center}.item-content[data-v-48008813]{flex:1;min-width:0}.item-title[data-v-48008813]{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.item-description[data-v-48008813]{overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical}.item-extra[data-v-48008813]{margin-top:4px}.item-action[data-v-48008813]{flex-shrink:0;color:#c0c4cc;display:flex;align-items:center}.pivot-container[data-v-0b1303d7]{box-sizing:border-box}.empty-state[data-v-0b1303d7]{display:flex;align-items:center;justify-content:center;min-height:200px}.table-container[data-v-a1dc5b93]{box-sizing:border-box;padding:0}[data-v-a1dc5b93] .el-table{width:100%;height:100%}.timeline-container[data-v-6ae929c9]{box-sizing:border-box}.empty-state[data-v-6ae929c9]{display:flex;align-items:center;justify-content:center;min-height:200px}.card-header[data-v-6ae929c9]{display:flex;justify-content:space-between;align-items:center}.card-title[data-v-6ae929c9]{flex:1}.card-time[data-v-6ae929c9]{font-size:13px;color:#909399;font-weight:400;margin-left:12px}.card-content[data-v-6ae929c9]{margin:0}.card-extra[data-v-6ae929c9]{padding-top:8px;border-top:1px solid #ebeef5}.timeline-content[data-v-6ae929c9]{padding:8px 0}.content-title[data-v-6ae929c9]{margin-bottom:4px}.content-text[data-v-6ae929c9]{margin:0}.content-extra[data-v-6ae929c9]{padding-top:6px}.group-container[data-v-3fa8648d]{position:relative;width:100%;height:100%}.group-placeholder[data-v-3fa8648d]{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);color:#909399;font-size:12px;opacity:.5;pointer-events:none}.v-box-container[data-v-96ba1c0c]{box-sizing:border-box}.v-box-content[data-v-96ba1c0c]{word-break:break-word;white-space:pre-wrap}.v-countup-container[data-v-44399741]{box-sizing:border-box}[data-v-44399741] .el-statistic{text-align:center;display:flex;align-items:center;justify-content:center;box-sizing:border-box}.v-progress-container[data-v-02d37fd3]{box-sizing:border-box}[data-v-02d37fd3] .el-progress{width:100%}[data-v-02d37fd3] .el-progress__text{font-size:inherit!important;color:var(--v13e3249a)}.v-stat-card[data-v-c0db472f]{box-sizing:border-box}.v-stat-header[data-v-c0db472f]{margin-bottom:8px}.v-stat-title[data-v-c0db472f]{font-size:14px;color:#909399;margin:0}.v-stat-body[data-v-c0db472f]{display:flex;align-items:center;gap:12px;flex:1}.v-stat-icon[data-v-c0db472f]{display:flex;align-items:center}.v-stat-value[data-v-c0db472f]{line-height:1}.v-stat-footer[data-v-c0db472f]{margin-top:8px}.v-stat-change[data-v-c0db472f]{font-weight:500}.v-text[data-v-0045cea2]{word-break:break-word;white-space:pre-wrap}.v-badge-container[data-v-97776e64]{display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box}[data-v-97776e64] .el-badge{display:inline-flex;align-items:center;justify-content:center}[data-v-97776e64] .el-badge__content{font-size:inherit!important}.v-col[data-v-082964dd]{box-sizing:border-box}.v-col-placeholder[data-v-082964dd]{width:100%}.v-flex-container[data-v-162d144a]{box-sizing:border-box}.v-flex-placeholder[data-v-162d144a]{width:100%}.v-grid-container[data-v-8229882e]{box-sizing:border-box;width:100%}.v-grid-placeholder-item[data-v-8229882e]{padding:12px;background-color:#f3f4f6;border-radius:4px;text-align:center}.v-modal-footer[data-v-a28442e3]{display:flex;justify-content:flex-end;gap:8px}.v-modal-body[data-v-a28442e3]{box-sizing:border-box}.v-panel[data-v-e72601fb]{box-sizing:border-box;width:100%}.v-panel-header[data-v-e72601fb]{-webkit-user-select:none;user-select:none}.v-panel-collapse-icon[data-v-e72601fb]{font-size:12px}.v-panel-body[data-v-e72601fb],.v-panel-footer[data-v-e72601fb]{box-sizing:border-box}.v-row[data-v-c97c26e7]{width:100%;box-sizing:border-box}.v-row-placeholder[data-v-c97c26e7]{width:100%}.v-tabs-container[data-v-97eccaf6]{box-sizing:border-box;width:100%}.image-error[data-v-07b84e1b],.image-loading[data-v-07b84e1b],.image-placeholder[data-v-07b84e1b]{display:flex;flex-direction:column;justify-content:center;align-items:center;width:100%;height:100%;color:#909399;font-size:14px;gap:8px;background-color:#f5f7fa}.image-error .el-icon[data-v-07b84e1b],.image-loading .el-icon[data-v-07b84e1b],.image-placeholder .el-icon[data-v-07b84e1b]{font-size:48px;color:#c0c4cc}.is-loading[data-v-07b84e1b]{animation:rotating-07b84e1b 2s linear infinite}@keyframes rotating-07b84e1b{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.video-placeholder[data-v-ef4cae83]{display:flex;flex-direction:column;justify-content:center;align-items:center;width:100%;height:100%;color:#909399;font-size:14px;gap:8px;background-color:#000}.video-placeholder .el-icon[data-v-ef4cae83]{font-size:64px;color:#606266}.v-button[data-v-14cbbdfe]{display:inline-flex;justify-content:center;align-items:center;line-height:1;height:32px;white-space:nowrap;cursor:pointer;color:#606266;text-align:center;box-sizing:border-box;outline:none;margin:0;transition:.1s;font-weight:500;-webkit-user-select:none;user-select:none;vertical-align:middle;background-color:#fff;border:1px solid #dcdfe6;padding:8px 15px;font-size:14px;border-radius:4px}.v-button[data-v-14cbbdfe]:hover,.v-button[data-v-14cbbdfe]:focus{color:#409eff;border-color:#c6e2ff;background-color:#ecf5ff}.v-button[data-v-14cbbdfe]:active{color:#3a8ee6;border-color:#3a8ee6;outline:none}.v-button.is-disabled[data-v-14cbbdfe]{color:#c0c4cc;cursor:not-allowed;background-image:none;background-color:#fff;border-color:#ebeef5}.v-button--large[data-v-14cbbdfe]{height:40px;padding:12px 19px;font-size:14px}.v-button--small[data-v-14cbbdfe]{height:24px;padding:5px 11px;font-size:12px}.v-button--primary[data-v-14cbbdfe]{color:#fff;background-color:#409eff;border-color:#409eff}.v-button--primary[data-v-14cbbdfe]:not(.is-disabled):hover{background-color:#66b1ff;border-color:#66b1ff}.v-button.is-round[data-v-14cbbdfe]{border-radius:20px}.v-button.is-circle[data-v-14cbbdfe]{border-radius:50%;padding:8px;min-width:32px}.v-stat-card__header[data-v-cfba101d]{display:flex;align-items:center;margin-bottom:8px}.v-stat-card__tooltip-icon[data-v-cfba101d]{margin-left:4px;cursor:help;font-size:12px;color:#909399}.v-stat-card__content[data-v-cfba101d]{flex:1;display:flex;align-items:center}.v-stat-card__value-wrapper[data-v-cfba101d]{display:flex;align-items:baseline}.v-stat-card__prefix[data-v-cfba101d],.v-stat-card__suffix[data-v-cfba101d]{font-size:14px;color:#606266;margin:0 4px}.v-stat-card__footer[data-v-cfba101d]{margin-top:12px;padding-top:12px;border-top:1px solid #ebeef5}.v-stat-card__trend[data-v-cfba101d]{display:flex;align-items:center;font-size:12px}.v-stat-card__trend.is-up[data-v-cfba101d]{color:#f56c6c}.v-stat-card__trend.is-down[data-v-cfba101d]{color:#67c23a}.v-stat-card__trend.is-normal[data-v-cfba101d]{color:#909399}.trend-label[data-v-cfba101d]{margin-right:8px}.trend-icon[data-v-cfba101d]{margin-left:4px;font-weight:700}.v-grid[data-v-db3ad218]{margin:0;padding:0}
package/index.ts ADDED
@@ -0,0 +1,150 @@
1
+ import type { App, Component } from 'vue'
2
+ // @vela/ui/index.ts
3
+
4
+ /**
5
+ * 使用 Vite 的 import.meta.glob 动态导入所有组件
6
+ * 这样新增组件只需在对应目录创建 .vue 文件,无需手动注册
7
+ */
8
+ const componentModules = import.meta.glob<{ default: Component }>('./src/components/**/*.vue', {
9
+ eager: true,
10
+ })
11
+
12
+ /**
13
+ * 从文件路径提取组件名称
14
+ * 例如:'./src/components/chart/lineChart/lineChart.vue' -> 'lineChart'
15
+ * './src/components/kpi/text/Text.vue' -> 'vText'
16
+ */
17
+ function extractComponentName(path: string): string {
18
+ const match = path.match(/\/([^/]+)\.vue$/)
19
+ if (!match || !match[1]) return ''
20
+
21
+ const fileName = match[1]
22
+
23
+ // 对于非图表组件,如果文件名首字母是大写,添加 'v' 前缀
24
+ // 图表组件保持原名(如 lineChart, barChart)
25
+ if (path.includes('/chart/')) {
26
+ return fileName
27
+ }
28
+
29
+ // 其他组件:如果首字母大写,加 'v' 前缀
30
+ const firstChar = fileName.charAt(0)
31
+ if (firstChar && firstChar === firstChar.toUpperCase()) {
32
+ return `v${fileName}`
33
+ }
34
+
35
+ return fileName
36
+ }
37
+
38
+ // 动态构建组件注册表
39
+ const componentRegistry: Record<string, Component> = {}
40
+
41
+ for (const path in componentModules) {
42
+ const mod = componentModules[path]
43
+ const componentName = extractComponentName(path)
44
+ if (componentName && mod?.default) {
45
+ componentRegistry[componentName] = mod.default
46
+ }
47
+ }
48
+
49
+ // 图表组件
50
+ export const lineChart = componentRegistry.lineChart
51
+ export const barChart = componentRegistry.barChart
52
+ export const pieChart = componentRegistry.pieChart
53
+ export const doughnutChart = componentRegistry.doughnutChart
54
+ export const radarChart = componentRegistry.radarChart
55
+ export const gaugeChart = componentRegistry.gaugeChart
56
+ export const funnelChart = componentRegistry.funnelChart
57
+ export const scatterChart = componentRegistry.scatterChart
58
+ export const sankeyChart = componentRegistry.sankeyChart
59
+ export const stackedBarChart = componentRegistry.stackedBarChart
60
+
61
+ // KPI 组件
62
+ export const vText = componentRegistry.vText
63
+ export const vBox = componentRegistry.vBox
64
+ export const vStat = componentRegistry.vStat
65
+ export const vProgress = componentRegistry.vProgress
66
+ export const vCountUp = componentRegistry.vCountUp
67
+
68
+ // 基础组件
69
+ export const vContainer = componentRegistry.vContainer
70
+ export const vButton = componentRegistry.vButton
71
+
72
+ // 布局组件
73
+ export const vBadge = componentRegistry.vBadge
74
+ export const vPanel = componentRegistry.vPanel
75
+ export const vFlex = componentRegistry.vFlex
76
+ export const vGrid = componentRegistry.vGrid
77
+ export const vTabs = componentRegistry.vTabs
78
+ export const vModal = componentRegistry.vModal
79
+ export const vRow = componentRegistry.vRow
80
+ export const vCol = componentRegistry.vCol
81
+
82
+ // 数据组件
83
+ export const vTimeline = componentRegistry.vTimeline
84
+ export const vTable = componentRegistry.vTable
85
+ export const vList = componentRegistry.vList
86
+ export const vCardGrid = componentRegistry.vCardGrid
87
+ export const vPivot = componentRegistry.vPivot
88
+
89
+ // 控件组件
90
+ export const vButtonGroup = componentRegistry.vButtonGroup
91
+ export const vCheckboxGroup = componentRegistry.vCheckboxGroup
92
+ export const vDateRange = componentRegistry.vDateRange
93
+ export const vMultiSelect = componentRegistry.vMultiSelect
94
+ export const vSearchBox = componentRegistry.vSearchBox
95
+ export const vSelect = componentRegistry.vSelect
96
+ export const vSlider = componentRegistry.vSlider
97
+ export const vSwitch = componentRegistry.vSwitch
98
+ export const vNavButton = componentRegistry.vNavButton
99
+ export const vBreadcrumb = componentRegistry.vBreadcrumb
100
+ export const vPagination = componentRegistry.vPagination
101
+
102
+ // 内容组件
103
+ export const vHtml = componentRegistry.vHtml
104
+ export const vIframe = componentRegistry.vIframe
105
+ export const vMarkdown = componentRegistry.vMarkdown
106
+
107
+ // 媒体组件
108
+ export const vImage = componentRegistry.vImage
109
+ export const vVideo = componentRegistry.vVideo
110
+
111
+ // 高级组件
112
+ export const vScripting = componentRegistry.vScripting
113
+ export const vState = componentRegistry.vState
114
+ export const vTrigger = componentRegistry.vTrigger
115
+
116
+ // Group 组件
117
+ export const vGroup = componentRegistry.vGroup
118
+
119
+ // Standard Components (New Architecture) - Static Imports for reliability
120
+ import vBaseButton from './src/components/v2/basic/BaseButton.vue'
121
+ import vKpiCard from './src/components/v2/kpi/KpiCard.vue'
122
+ import vGridBox from './src/components/v2/layout/GridBox.vue'
123
+
124
+ export { vBaseButton, vKpiCard, vGridBox }
125
+
126
+ // 导出组件注册表,供外部使用
127
+ export { componentRegistry }
128
+
129
+ // 导出 Hooks
130
+ export * from './src/hooks/useDataSource'
131
+
132
+ // 导出工具函数
133
+ export * from './src/utils/dataUtils'
134
+
135
+ // 导出类型
136
+ export type { TriggerLog } from './src/components/advanced/trigger/Trigger.vue'
137
+ export type { GroupProps } from './src/components/group/Group.vue'
138
+
139
+ // 导出 GIS 类型
140
+ export * from './src/types/gis'
141
+
142
+ // 提供 Vue 插件式的安装方法
143
+ export default {
144
+ install(app: App) {
145
+ // 自动注册所有组件
146
+ for (const [name, component] of Object.entries(componentRegistry)) {
147
+ app.component(name, component)
148
+ }
149
+ },
150
+ }
package/package.json ADDED
@@ -0,0 +1,73 @@
1
+ {
2
+ "name": "@vela-studio/ui",
3
+ "version": "1.0.1",
4
+ "description": "Vela LowCode UI Component Library - Data visualization components for Vue 3",
5
+ "keywords": [
6
+ "vue3",
7
+ "ui",
8
+ "components",
9
+ "lowcode",
10
+ "echarts",
11
+ "data-visualization",
12
+ "dashboard"
13
+ ],
14
+ "author": "twi1i9ht",
15
+ "license": "MIT",
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "https://github.com/TWILIGHT-wyf/vela-lowcode-editor.git",
19
+ "directory": "packages/ui"
20
+ },
21
+ "bugs": {
22
+ "url": "https://github.com/TWILIGHT-wyf/vela-lowcode-editor/issues"
23
+ },
24
+ "homepage": "https://github.com/TWILIGHT-wyf/vela-lowcode-editor#readme",
25
+ "publishConfig": {
26
+ "access": "public",
27
+ "registry": "https://registry.npmjs.org/"
28
+ },
29
+ "files": [
30
+ "dist",
31
+ "index.ts",
32
+ "src"
33
+ ],
34
+ "main": "./dist/index.js",
35
+ "module": "./dist/index.mjs",
36
+ "types": "./dist/index.d.ts",
37
+ "exports": {
38
+ ".": {
39
+ "types": "./dist/index.d.ts",
40
+ "import": "./dist/index.mjs",
41
+ "require": "./dist/index.js"
42
+ },
43
+ "./dist/style.css": "./dist/style.css",
44
+ "./*": {
45
+ "types": "./dist/*.d.ts",
46
+ "import": "./dist/*.mjs",
47
+ "require": "./dist/*.js"
48
+ }
49
+ },
50
+ "scripts": {
51
+ "build": "vite build",
52
+ "build:lib": "vite build --config vite.lib.config.ts",
53
+ "prepublishOnly": "pnpm build:lib"
54
+ },
55
+ "peerDependencies": {
56
+ "element-plus": "^2.0.0",
57
+ "vue": "^3.0.0"
58
+ },
59
+ "dependencies": {
60
+ "dompurify": "^3.3.1",
61
+ "echarts": "^6.0.0",
62
+ "highlight.js": "^11.11.1",
63
+ "marked": "^17.0.1",
64
+ "vue-echarts": "^8.0.1"
65
+ },
66
+ "devDependencies": {
67
+ "@types/dompurify": "^3.2.0",
68
+ "@vitejs/plugin-vue": "^5.0.0",
69
+ "vite": "^5.0.0",
70
+ "vite-plugin-dts": "^4.5.4",
71
+ "vue": "^3.5.22"
72
+ }
73
+ }
@@ -0,0 +1,189 @@
1
+ <template>
2
+ <div :style="containerStyle">
3
+ <div class="scripting-container">
4
+ <div class="header">
5
+ <span class="title">
6
+ <el-icon><Document /></el-icon>
7
+ {{ title }}
8
+ </span>
9
+ <el-button
10
+ v-if="!autoRun && showControls"
11
+ type="primary"
12
+ size="small"
13
+ @click="$emit('execute')"
14
+ >
15
+ 执行
16
+ </el-button>
17
+ </div>
18
+
19
+ <div v-if="showCode" class="code-section">
20
+ <div class="section-title">代码:</div>
21
+ <pre class="code-block">{{ scriptCode }}</pre>
22
+ </div>
23
+
24
+ <div v-if="output || error" class="output-section">
25
+ <div class="section-title">输出:</div>
26
+ <div v-if="error" class="error-output">{{ error }}</div>
27
+ <pre v-else class="output-block">{{ output }}</pre>
28
+ </div>
29
+
30
+ <div v-if="!output && !error && showPlaceholder" class="placeholder">
31
+ <el-icon><VideoPlay /></el-icon>
32
+ <span>{{ placeholder }}</span>
33
+ </div>
34
+ </div>
35
+ </div>
36
+ </template>
37
+
38
+ <script setup lang="ts">
39
+ import { computed, type CSSProperties } from 'vue'
40
+ import { Document, VideoPlay } from '@element-plus/icons-vue'
41
+
42
+ export interface ScriptingProps {
43
+ title?: string
44
+ scriptCode?: string
45
+ output?: string
46
+ error?: string
47
+ autoRun?: boolean
48
+ showCode?: boolean
49
+ showControls?: boolean
50
+ showPlaceholder?: boolean
51
+ placeholder?: string
52
+ // 样式
53
+ padding?: number
54
+ backgroundColor?: string
55
+ textColor?: string
56
+ fontSize?: number
57
+ lineHeight?: number
58
+ borderRadius?: number
59
+ border?: string
60
+ fontFamily?: string
61
+ }
62
+
63
+ const props = withDefaults(defineProps<ScriptingProps>(), {
64
+ title: '脚本执行器',
65
+ scriptCode: '// 请输入 JavaScript 代码\nconsole.log("Hello World");',
66
+ output: '',
67
+ error: '',
68
+ autoRun: false,
69
+ showCode: true,
70
+ showControls: true,
71
+ showPlaceholder: true,
72
+ placeholder: '点击执行按钮运行脚本',
73
+ padding: 16,
74
+ backgroundColor: '#1e1e1e',
75
+ textColor: '#d4d4d4',
76
+ fontSize: 14,
77
+ lineHeight: 1.6,
78
+ borderRadius: 4,
79
+ border: '1px solid #3c3c3c',
80
+ fontFamily: 'Consolas, Monaco, "Courier New", monospace',
81
+ })
82
+
83
+ defineEmits<{
84
+ execute: []
85
+ }>()
86
+
87
+ const containerStyle = computed<CSSProperties>(() => ({
88
+ width: '100%',
89
+ height: '100%',
90
+ padding: `${props.padding}px`,
91
+ backgroundColor: props.backgroundColor,
92
+ color: props.textColor,
93
+ fontSize: `${props.fontSize}px`,
94
+ lineHeight: props.lineHeight,
95
+ borderRadius: `${props.borderRadius}px`,
96
+ border: props.border,
97
+ overflow: 'auto',
98
+ fontFamily: props.fontFamily,
99
+ }))
100
+ </script>
101
+
102
+ <style scoped>
103
+ .scripting-container {
104
+ display: flex;
105
+ flex-direction: column;
106
+ gap: 12px;
107
+ height: 100%;
108
+ }
109
+
110
+ .header {
111
+ display: flex;
112
+ justify-content: space-between;
113
+ align-items: center;
114
+ padding-bottom: 8px;
115
+ border-bottom: 1px solid #3c3c3c;
116
+ }
117
+
118
+ .title {
119
+ display: flex;
120
+ align-items: center;
121
+ gap: 6px;
122
+ font-weight: 600;
123
+ font-size: 16px;
124
+ }
125
+
126
+ .section-title {
127
+ font-size: 12px;
128
+ opacity: 0.7;
129
+ margin-bottom: 6px;
130
+ text-transform: uppercase;
131
+ }
132
+
133
+ .code-section {
134
+ flex-shrink: 0;
135
+ }
136
+
137
+ .code-block {
138
+ margin: 0;
139
+ padding: 12px;
140
+ background: rgba(0, 0, 0, 0.3);
141
+ border-radius: 4px;
142
+ overflow-x: auto;
143
+ white-space: pre-wrap;
144
+ word-wrap: break-word;
145
+ }
146
+
147
+ .output-section {
148
+ flex: 1;
149
+ min-height: 0;
150
+ display: flex;
151
+ flex-direction: column;
152
+ }
153
+
154
+ .output-block {
155
+ flex: 1;
156
+ margin: 0;
157
+ padding: 12px;
158
+ background: rgba(0, 0, 0, 0.2);
159
+ border-radius: 4px;
160
+ overflow: auto;
161
+ white-space: pre-wrap;
162
+ word-wrap: break-word;
163
+ color: #4ec9b0;
164
+ }
165
+
166
+ .error-output {
167
+ flex: 1;
168
+ padding: 12px;
169
+ background: rgba(220, 38, 38, 0.1);
170
+ border: 1px solid rgba(220, 38, 38, 0.3);
171
+ border-radius: 4px;
172
+ color: #f87171;
173
+ overflow: auto;
174
+ }
175
+
176
+ .placeholder {
177
+ display: flex;
178
+ flex-direction: column;
179
+ justify-content: center;
180
+ align-items: center;
181
+ flex: 1;
182
+ gap: 8px;
183
+ opacity: 0.5;
184
+ }
185
+
186
+ .placeholder .el-icon {
187
+ font-size: 32px;
188
+ }
189
+ </style>
@@ -0,0 +1,231 @@
1
+ <template>
2
+ <div :style="containerStyle">
3
+ <div class="state-container">
4
+ <div class="header">
5
+ <span class="title">
6
+ <el-icon><DataLine /></el-icon>
7
+ {{ title }}
8
+ </span>
9
+ <el-tag size="small" type="info"> {{ stateItems.length }} 项 </el-tag>
10
+ </div>
11
+
12
+ <div v-if="viewMode === 'list'" class="state-list">
13
+ <div v-for="item in stateItems" :key="item.key" class="state-item">
14
+ <div class="state-key">
15
+ <el-icon><Key /></el-icon>
16
+ {{ item.key }}
17
+ </div>
18
+ <div class="state-value">
19
+ <el-tag :type="getTagType(item.type)" size="small">{{ item.type }}</el-tag>
20
+ <span class="value-text">{{ formatValue(item.value) }}</span>
21
+ </div>
22
+ </div>
23
+ </div>
24
+
25
+ <div v-else-if="viewMode === 'json'" class="json-view">
26
+ <pre class="json-block">{{ jsonValue }}</pre>
27
+ </div>
28
+
29
+ <div v-else-if="viewMode === 'table'" class="table-view">
30
+ <el-table :data="stateItems" size="small" :border="true">
31
+ <el-table-column prop="key" label="键" width="120" />
32
+ <el-table-column prop="type" label="类型" width="80">
33
+ <template #default="{ row }">
34
+ <el-tag :type="getTagType(row.type)" size="small">{{ row.type }}</el-tag>
35
+ </template>
36
+ </el-table-column>
37
+ <el-table-column prop="value" label="值">
38
+ <template #default="{ row }">
39
+ {{ formatValue(row.value) }}
40
+ </template>
41
+ </el-table-column>
42
+ </el-table>
43
+ </div>
44
+
45
+ <div v-if="stateItems.length === 0" class="placeholder">
46
+ <el-icon><FolderOpened /></el-icon>
47
+ <span>{{ placeholder }}</span>
48
+ </div>
49
+ </div>
50
+ </div>
51
+ </template>
52
+
53
+ <script setup lang="ts">
54
+ import { computed, type CSSProperties } from 'vue'
55
+ import { DataLine, Key, FolderOpened } from '@element-plus/icons-vue'
56
+
57
+ export interface StateItem {
58
+ key: string
59
+ value: unknown
60
+ type: string
61
+ }
62
+
63
+ export interface StateProps {
64
+ title?: string
65
+ stateData?: Record<string, unknown>
66
+ viewMode?: 'list' | 'json' | 'table'
67
+ placeholder?: string
68
+ // 样式
69
+ padding?: number
70
+ backgroundColor?: string
71
+ textColor?: string
72
+ fontSize?: number
73
+ lineHeight?: number
74
+ borderRadius?: number
75
+ border?: string
76
+ fontFamily?: string
77
+ }
78
+
79
+ const props = withDefaults(defineProps<StateProps>(), {
80
+ title: '状态管理器',
81
+ stateData: () => ({}),
82
+ viewMode: 'list',
83
+ placeholder: '暂无状态数据',
84
+ padding: 16,
85
+ backgroundColor: '#2d2d2d',
86
+ textColor: '#cccccc',
87
+ fontSize: 14,
88
+ lineHeight: 1.6,
89
+ borderRadius: 4,
90
+ border: '1px solid #3c3c3c',
91
+ fontFamily: 'Consolas, Monaco, "Courier New", monospace',
92
+ })
93
+
94
+ const containerStyle = computed<CSSProperties>(() => ({
95
+ width: '100%',
96
+ height: '100%',
97
+ padding: `${props.padding}px`,
98
+ backgroundColor: props.backgroundColor,
99
+ color: props.textColor,
100
+ fontSize: `${props.fontSize}px`,
101
+ lineHeight: props.lineHeight,
102
+ borderRadius: `${props.borderRadius}px`,
103
+ border: props.border,
104
+ overflow: 'auto',
105
+ fontFamily: props.fontFamily,
106
+ }))
107
+
108
+ const stateItems = computed<StateItem[]>(() => {
109
+ return Object.entries(props.stateData).map(([key, value]) => ({
110
+ key,
111
+ value,
112
+ type: typeof value,
113
+ }))
114
+ })
115
+
116
+ const jsonValue = computed(() => {
117
+ return JSON.stringify(props.stateData, null, 2)
118
+ })
119
+
120
+ function getTagType(type: string): 'success' | 'info' | 'warning' | 'danger' | '' {
121
+ const typeMap: Record<string, 'success' | 'info' | 'warning' | 'danger'> = {
122
+ string: 'success',
123
+ number: 'info',
124
+ boolean: 'warning',
125
+ object: 'danger',
126
+ }
127
+ return typeMap[type] || ''
128
+ }
129
+
130
+ function formatValue(value: unknown): string {
131
+ if (value === null) return 'null'
132
+ if (value === undefined) return 'undefined'
133
+ if (typeof value === 'object') return JSON.stringify(value)
134
+ return String(value)
135
+ }
136
+ </script>
137
+
138
+ <style scoped>
139
+ .state-container {
140
+ display: flex;
141
+ flex-direction: column;
142
+ gap: 12px;
143
+ height: 100%;
144
+ }
145
+
146
+ .header {
147
+ display: flex;
148
+ justify-content: space-between;
149
+ align-items: center;
150
+ padding-bottom: 8px;
151
+ border-bottom: 1px solid #3c3c3c;
152
+ }
153
+
154
+ .title {
155
+ display: flex;
156
+ align-items: center;
157
+ gap: 6px;
158
+ font-weight: 600;
159
+ font-size: 16px;
160
+ }
161
+
162
+ .state-list {
163
+ flex: 1;
164
+ overflow-y: auto;
165
+ display: flex;
166
+ flex-direction: column;
167
+ gap: 8px;
168
+ }
169
+
170
+ .state-item {
171
+ padding: 12px;
172
+ background: rgba(0, 0, 0, 0.2);
173
+ border-radius: 4px;
174
+ border: 1px solid rgba(255, 255, 255, 0.1);
175
+ }
176
+
177
+ .state-key {
178
+ display: flex;
179
+ align-items: center;
180
+ gap: 6px;
181
+ font-weight: 600;
182
+ margin-bottom: 6px;
183
+ color: #4fc3f7;
184
+ }
185
+
186
+ .state-value {
187
+ display: flex;
188
+ align-items: center;
189
+ gap: 8px;
190
+ padding-left: 24px;
191
+ }
192
+
193
+ .value-text {
194
+ flex: 1;
195
+ word-break: break-all;
196
+ }
197
+
198
+ .json-view {
199
+ flex: 1;
200
+ overflow: auto;
201
+ }
202
+
203
+ .json-block {
204
+ margin: 0;
205
+ padding: 12px;
206
+ background: rgba(0, 0, 0, 0.3);
207
+ border-radius: 4px;
208
+ white-space: pre;
209
+ overflow-x: auto;
210
+ color: #9cdcfe;
211
+ }
212
+
213
+ .table-view {
214
+ flex: 1;
215
+ overflow: auto;
216
+ }
217
+
218
+ .placeholder {
219
+ display: flex;
220
+ flex-direction: column;
221
+ justify-content: center;
222
+ align-items: center;
223
+ flex: 1;
224
+ gap: 8px;
225
+ opacity: 0.5;
226
+ }
227
+
228
+ .placeholder .el-icon {
229
+ font-size: 32px;
230
+ }
231
+ </style>