@kupola/kupola 1.2.0 → 1.3.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.
- package/LICENSE +21 -0
- package/README.md +330 -286
- package/adapters/axios.d.ts +34 -0
- package/adapters/axios.js +122 -0
- package/adapters/navios-http.d.ts +110 -0
- package/adapters/navios-http.js +151 -0
- package/dist/css/accessibility.css +119 -0
- package/dist/css/animations.css +224 -0
- package/dist/css/brand-themes.css +300 -0
- package/dist/css/colors_and_type.css +441 -0
- package/dist/css/components-ext.css +4165 -0
- package/dist/css/components.css +1483 -0
- package/dist/css/responsive.css +697 -0
- package/dist/css/scaffold.css +145 -0
- package/dist/css/states.css +316 -0
- package/dist/css/theme-dark.css +296 -0
- package/dist/css/theme-light.css +296 -0
- package/dist/css/utilities.css +171 -0
- package/dist/kupola.cjs.js +219 -161
- package/dist/kupola.cjs.js.map +1 -1
- package/dist/kupola.esm.js +6643 -5709
- package/dist/kupola.esm.js.map +1 -1
- package/dist/kupola.umd.js +219 -161
- package/dist/kupola.umd.js.map +1 -1
- package/dist/plugins/vite-plugin-kupola.js +120 -0
- package/dist/types/kupola.d.ts +421 -323
- package/js/calendar.js +334 -25
- package/js/carousel.js +182 -48
- package/js/collapse.js +148 -34
- package/js/color-picker.js +416 -108
- package/js/component.js +8 -19
- package/js/countdown.js +9 -8
- package/js/data-bind.js +73 -16
- package/js/datepicker.js +488 -110
- package/js/depends.js +710 -0
- package/js/dialog.js +4 -2
- package/js/drawer.js +172 -8
- package/js/dropdown.js +272 -17
- package/js/dynamic-tags.js +156 -40
- package/js/fileupload.js +9 -8
- package/js/form.js +280 -254
- package/js/global-events.js +281 -188
- package/js/heatmap.js +10 -7
- package/js/i18n.js +18 -10
- package/js/icons.js +141 -161
- package/js/image-preview.js +146 -2
- package/js/initializer.js +113 -71
- package/js/kupola-core.js +123 -45
- package/js/kupola-lifecycle.js +13 -11
- package/js/message.js +8 -1
- package/js/modal.js +207 -59
- package/js/notification.js +8 -1
- package/js/numberinput.js +9 -8
- package/js/pagination.js +263 -0
- package/js/registry.js +29 -12
- package/js/select.js +482 -27
- package/js/slide-captcha.js +11 -2
- package/js/slider.js +442 -25
- package/js/statcard.js +9 -7
- package/js/table.js +1210 -0
- package/js/tag.js +268 -14
- package/js/theme.js +14 -43
- package/js/timepicker.js +335 -66
- package/js/tooltip.js +317 -86
- package/js/utils.js +6 -2
- package/js/validation.js +6 -2
- package/js/virtual-list.js +11 -7
- package/js/web-components.js +288 -0
- package/package.json +77 -67
- package/plugins/vite-plugin-kupola.js +120 -0
- package/types/kupola.d.ts +421 -323
- package/CHANGELOG.md +0 -130
- package/INTEGRATION.md +0 -440
- package/PROJECT_SUMMARY.md +0 -312
- package/SKILL.md +0 -572
- package/dist/utils/utils/Kupola.cs +0 -77
- package/dist/utils/utils/Kupola.java +0 -104
- package/dist/utils/utils/kupola.go +0 -120
- package/dist/utils/utils/kupola.js +0 -63
- package/dist/utils/utils/kupola.py +0 -1392
- package/dist/utils/utils/kupola.rb +0 -69
- package/js/composition-api.js +0 -458
- package/js/error-handler.js +0 -181
- package/js/http.js +0 -419
- package/js/kupola-devtools.js +0 -598
- package/js/performance.js +0 -250
- package/js/router.js +0 -396
- package/js/security.js +0 -189
- package/js/test-utils.js +0 -251
- package/templates/base.html +0 -30
- package/templates/base_dashboard.html +0 -99
- package/utils/Kupola.cs +0 -77
- package/utils/Kupola.java +0 -104
- package/utils/kupola.go +0 -120
- package/utils/kupola.js +0 -63
- package/utils/kupola.py +0 -1392
- package/utils/kupola.rb +0 -69
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Kupola Web Components — Custom Elements wrapper for core Kupola components.
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* import { registerWebComponents } from '@kupola/kupola';
|
|
6
|
+
* registerWebComponents();
|
|
7
|
+
*
|
|
8
|
+
* Then in HTML:
|
|
9
|
+
* <k-dropdown>
|
|
10
|
+
* <button slot="trigger">Open</button>
|
|
11
|
+
* <a slot="item">Option A</a>
|
|
12
|
+
* <a slot="item">Option B</a>
|
|
13
|
+
* </k-dropdown>
|
|
14
|
+
*
|
|
15
|
+
* <k-tooltip title="Hello!">
|
|
16
|
+
* <button>Hover me</button>
|
|
17
|
+
* </k-tooltip>
|
|
18
|
+
*
|
|
19
|
+
* <k-collapse>
|
|
20
|
+
* <k-collapse-item title="Section 1">Content 1</k-collapse-item>
|
|
21
|
+
* <k-collapse-item title="Section 2">Content 2</k-collapse-item>
|
|
22
|
+
* </k-collapse>
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
let registered = false;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* <k-dropdown> — Wraps Kupola dropdown
|
|
29
|
+
* Slots: trigger (button), item (menu items)
|
|
30
|
+
*/
|
|
31
|
+
class KupolaDropdownElement extends HTMLElement {
|
|
32
|
+
static get observedAttributes() { return ['open']; }
|
|
33
|
+
|
|
34
|
+
connectedCallback() {
|
|
35
|
+
this._render();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
_render() {
|
|
39
|
+
const trigger = this.querySelector('[slot="trigger"]');
|
|
40
|
+
const items = this.querySelectorAll('[slot="item"]');
|
|
41
|
+
|
|
42
|
+
// Build dropdown DOM structure
|
|
43
|
+
const wrapper = document.createElement('div');
|
|
44
|
+
wrapper.className = 'ds-dropdown';
|
|
45
|
+
wrapper.setAttribute('data-dropdown', '');
|
|
46
|
+
|
|
47
|
+
if (trigger) {
|
|
48
|
+
trigger.setAttribute('class', (trigger.getAttribute('class') || '') + ' ds-dropdown__trigger');
|
|
49
|
+
wrapper.appendChild(trigger);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const menu = document.createElement('div');
|
|
53
|
+
menu.className = 'ds-dropdown__menu';
|
|
54
|
+
items.forEach(item => {
|
|
55
|
+
item.className = 'ds-dropdown__item';
|
|
56
|
+
menu.appendChild(item);
|
|
57
|
+
});
|
|
58
|
+
wrapper.appendChild(menu);
|
|
59
|
+
|
|
60
|
+
this.innerHTML = '';
|
|
61
|
+
this.appendChild(wrapper);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
attributeChangedCallback(name, oldVal, newVal) {
|
|
65
|
+
if (name === 'open') {
|
|
66
|
+
const menu = this.querySelector('.ds-dropdown__menu');
|
|
67
|
+
if (menu) menu.style.display = newVal !== null ? 'block' : '';
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* <k-tooltip title="text"> — Wraps Kupola tooltip
|
|
74
|
+
* Default slot: the trigger element
|
|
75
|
+
*/
|
|
76
|
+
class KupolaTooltipElement extends HTMLElement {
|
|
77
|
+
static get observedAttributes() { return ['title', 'position']; }
|
|
78
|
+
|
|
79
|
+
connectedCallback() {
|
|
80
|
+
const trigger = this.firstElementChild;
|
|
81
|
+
if (trigger) {
|
|
82
|
+
trigger.setAttribute('data-title', this.getAttribute('title') || '');
|
|
83
|
+
if (this.getAttribute('position')) {
|
|
84
|
+
trigger.setAttribute('data-tooltip-position', this.getAttribute('position'));
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
attributeChangedCallback(name, oldVal, newVal) {
|
|
90
|
+
if (name === 'title') {
|
|
91
|
+
const trigger = this.firstElementChild;
|
|
92
|
+
if (trigger) trigger.setAttribute('data-title', newVal || '');
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* <k-collapse> — Wraps Kupola collapse/accordion
|
|
99
|
+
* Children: <k-collapse-item title="...">content</k-collapse-item>
|
|
100
|
+
*/
|
|
101
|
+
class KupolaCollapseElement extends HTMLElement {
|
|
102
|
+
connectedCallback() {
|
|
103
|
+
this._render();
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
_render() {
|
|
107
|
+
const wrapper = document.createElement('div');
|
|
108
|
+
wrapper.className = 'ds-collapse';
|
|
109
|
+
wrapper.setAttribute('data-collapse', '');
|
|
110
|
+
|
|
111
|
+
const items = this.querySelectorAll('k-collapse-item');
|
|
112
|
+
items.forEach(item => {
|
|
113
|
+
const title = item.getAttribute('title') || '';
|
|
114
|
+
const content = item.innerHTML;
|
|
115
|
+
|
|
116
|
+
const collapseItem = document.createElement('div');
|
|
117
|
+
collapseItem.className = 'ds-collapse__item';
|
|
118
|
+
collapseItem.innerHTML = `
|
|
119
|
+
<button class="ds-collapse__header">
|
|
120
|
+
<span>${title}</span>
|
|
121
|
+
<svg class="icon ds-collapse__chevron" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="6 9 12 15 18 9"/></svg>
|
|
122
|
+
</button>
|
|
123
|
+
<div class="ds-collapse__body"><div class="ds-collapse__content">${content}</div></div>
|
|
124
|
+
`;
|
|
125
|
+
wrapper.appendChild(collapseItem);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
this.innerHTML = '';
|
|
129
|
+
this.appendChild(wrapper);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* <k-collapse-item title="..."> — Child of <k-collapse>
|
|
135
|
+
* Not registered as a standalone custom element, just a data container.
|
|
136
|
+
*/
|
|
137
|
+
class KupolaCollapseItemElement extends HTMLElement {
|
|
138
|
+
static get observedAttributes() { return ['title']; }
|
|
139
|
+
// Content is read by parent <k-collapse> during its connectedCallback
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* <k-drawer> — Wraps Kupola drawer
|
|
144
|
+
* Attributes: position (left|right|top|bottom), open
|
|
145
|
+
*/
|
|
146
|
+
class KupolaDrawerElement extends HTMLElement {
|
|
147
|
+
static get observedAttributes() { return ['position', 'open']; }
|
|
148
|
+
|
|
149
|
+
connectedCallback() {
|
|
150
|
+
this._render();
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
_render() {
|
|
154
|
+
const position = this.getAttribute('position') || 'left';
|
|
155
|
+
const wrapper = document.createElement('div');
|
|
156
|
+
wrapper.className = `ds-drawer ds-drawer--${position}`;
|
|
157
|
+
wrapper.setAttribute('data-drawer', '');
|
|
158
|
+
wrapper.innerHTML = this.innerHTML;
|
|
159
|
+
this.innerHTML = '';
|
|
160
|
+
this.appendChild(wrapper);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
attributeChangedCallback(name, oldVal, newVal) {
|
|
164
|
+
if (name === 'open') {
|
|
165
|
+
const drawer = this.querySelector('.ds-drawer');
|
|
166
|
+
if (drawer) {
|
|
167
|
+
drawer.classList.toggle('is-open', newVal !== null);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* <k-modal> — Wraps Kupola modal dialog
|
|
175
|
+
* Attributes: title, open
|
|
176
|
+
*/
|
|
177
|
+
class KupolaModalElement extends HTMLElement {
|
|
178
|
+
static get observedAttributes() { return ['title', 'open']; }
|
|
179
|
+
|
|
180
|
+
connectedCallback() {
|
|
181
|
+
this._render();
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
_render() {
|
|
185
|
+
const title = this.getAttribute('title') || '';
|
|
186
|
+
const wrapper = document.createElement('div');
|
|
187
|
+
wrapper.className = 'ds-backdrop';
|
|
188
|
+
wrapper.style.display = 'none';
|
|
189
|
+
wrapper.innerHTML = `
|
|
190
|
+
<div class="ds-dialog">
|
|
191
|
+
<div class="ds-dialog__head">
|
|
192
|
+
<span class="ds-dialog__title">${title}</span>
|
|
193
|
+
<button class="ds-dialog__close" aria-label="Close">
|
|
194
|
+
<svg class="icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
|
|
195
|
+
</button>
|
|
196
|
+
</div>
|
|
197
|
+
<div class="ds-dialog__body"></div>
|
|
198
|
+
<div class="ds-dialog__foot"></div>
|
|
199
|
+
</div>
|
|
200
|
+
`;
|
|
201
|
+
|
|
202
|
+
// Move slotted content into dialog body
|
|
203
|
+
const body = wrapper.querySelector('.ds-dialog__body');
|
|
204
|
+
const content = this.querySelector('[slot="body"]');
|
|
205
|
+
if (content) {
|
|
206
|
+
body.appendChild(content);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Move footer content
|
|
210
|
+
const foot = wrapper.querySelector('.ds-dialog__foot');
|
|
211
|
+
const footer = this.querySelector('[slot="footer"]');
|
|
212
|
+
if (footer) {
|
|
213
|
+
foot.appendChild(footer);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Close button handler
|
|
217
|
+
const closeBtn = wrapper.querySelector('.ds-dialog__close');
|
|
218
|
+
if (closeBtn) {
|
|
219
|
+
closeBtn.addEventListener('click', () => this.close());
|
|
220
|
+
}
|
|
221
|
+
// Backdrop click handler
|
|
222
|
+
wrapper.addEventListener('click', (e) => {
|
|
223
|
+
if (e.target === wrapper) this.close();
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
this.innerHTML = '';
|
|
227
|
+
this.appendChild(wrapper);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
attributeChangedCallback(name, oldVal, newVal) {
|
|
231
|
+
if (name === 'open') {
|
|
232
|
+
const backdrop = this.querySelector('.ds-backdrop');
|
|
233
|
+
if (backdrop) {
|
|
234
|
+
backdrop.style.display = newVal !== null ? 'flex' : 'none';
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
open() {
|
|
240
|
+
this.setAttribute('open', '');
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
close() {
|
|
244
|
+
this.removeAttribute('open');
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Register all Kupola Web Components.
|
|
250
|
+
* Safe to call multiple times — will only register once.
|
|
251
|
+
*/
|
|
252
|
+
export function registerWebComponents() {
|
|
253
|
+
if (registered || typeof customElements === 'undefined') return;
|
|
254
|
+
registered = true;
|
|
255
|
+
|
|
256
|
+
const components = [
|
|
257
|
+
['k-dropdown', KupolaDropdownElement],
|
|
258
|
+
['k-tooltip', KupolaTooltipElement],
|
|
259
|
+
['k-collapse', KupolaCollapseElement],
|
|
260
|
+
['k-collapse-item', KupolaCollapseItemElement],
|
|
261
|
+
['k-drawer', KupolaDrawerElement],
|
|
262
|
+
['k-modal', KupolaModalElement]
|
|
263
|
+
];
|
|
264
|
+
|
|
265
|
+
for (const [tag, cls] of components) {
|
|
266
|
+
if (!customElements.get(tag)) {
|
|
267
|
+
customElements.define(tag, cls);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
export {
|
|
273
|
+
KupolaDropdownElement,
|
|
274
|
+
KupolaTooltipElement,
|
|
275
|
+
KupolaCollapseElement,
|
|
276
|
+
KupolaCollapseItemElement,
|
|
277
|
+
KupolaDrawerElement,
|
|
278
|
+
KupolaModalElement
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
if (typeof window !== 'undefined') {
|
|
282
|
+
window.registerWebComponents = registerWebComponents;
|
|
283
|
+
window.KupolaDropdownElement = KupolaDropdownElement;
|
|
284
|
+
window.KupolaTooltipElement = KupolaTooltipElement;
|
|
285
|
+
window.KupolaCollapseElement = KupolaCollapseElement;
|
|
286
|
+
window.KupolaDrawerElement = KupolaDrawerElement;
|
|
287
|
+
window.KupolaModalElement = KupolaModalElement;
|
|
288
|
+
}
|
package/package.json
CHANGED
|
@@ -1,105 +1,115 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kupola/kupola",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "
|
|
5
|
-
"type": "module",
|
|
3
|
+
"version": "1.3.1",
|
|
4
|
+
"description": "A lightweight UI toolkit for any web project. No heavy frontend frameworks required.",
|
|
6
5
|
"main": "dist/kupola.cjs.js",
|
|
7
6
|
"module": "dist/kupola.esm.js",
|
|
8
7
|
"types": "dist/types/kupola.d.ts",
|
|
8
|
+
"type": "module",
|
|
9
|
+
"sideEffects": false,
|
|
10
|
+
"engines": {
|
|
11
|
+
"node": ">=16.0.0"
|
|
12
|
+
},
|
|
9
13
|
"exports": {
|
|
10
14
|
".": {
|
|
11
15
|
"import": "./dist/kupola.esm.js",
|
|
12
16
|
"require": "./dist/kupola.cjs.js",
|
|
13
17
|
"types": "./dist/types/kupola.d.ts"
|
|
14
18
|
},
|
|
15
|
-
"./
|
|
16
|
-
"import": "./
|
|
17
|
-
"
|
|
19
|
+
"./depends": {
|
|
20
|
+
"import": "./js/depends.js",
|
|
21
|
+
"types": "./dist/types/kupola.d.ts"
|
|
22
|
+
},
|
|
23
|
+
"./component": {
|
|
24
|
+
"import": "./js/kupola-core.js"
|
|
25
|
+
},
|
|
26
|
+
"./data-bind": {
|
|
27
|
+
"import": "./js/data-bind.js"
|
|
28
|
+
},
|
|
29
|
+
"./theme": {
|
|
30
|
+
"import": "./js/theme.js"
|
|
31
|
+
},
|
|
32
|
+
"./icons": {
|
|
33
|
+
"import": "./js/icons.js"
|
|
34
|
+
},
|
|
35
|
+
"./validation": {
|
|
36
|
+
"import": "./js/validation.js"
|
|
37
|
+
},
|
|
38
|
+
"./vite": {
|
|
39
|
+
"import": "./plugins/vite-plugin-kupola.js"
|
|
40
|
+
},
|
|
41
|
+
"./adapters/axios": {
|
|
42
|
+
"import": "./adapters/axios.js",
|
|
43
|
+
"types": "./adapters/axios.d.ts"
|
|
18
44
|
},
|
|
19
|
-
"./
|
|
20
|
-
|
|
21
|
-
|
|
45
|
+
"./adapters/navios-http": {
|
|
46
|
+
"import": "./adapters/navios-http.js",
|
|
47
|
+
"types": "./adapters/navios-http.d.ts"
|
|
48
|
+
},
|
|
49
|
+
"./dist/css/kupola.css": "./dist/css/kupola.css",
|
|
50
|
+
"./dist/css/*": "./dist/css/*",
|
|
51
|
+
"./dist/icons/*": "./dist/icons/*"
|
|
22
52
|
},
|
|
23
53
|
"scripts": {
|
|
54
|
+
"dev": "vite",
|
|
24
55
|
"build": "vite build",
|
|
25
|
-
"prepublishOnly": "npm run build",
|
|
26
56
|
"build:rollup": "rollup -c",
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"start": "npx http-server -p 8080",
|
|
57
|
+
"lint": "eslint .",
|
|
58
|
+
"lint:fix": "eslint . --fix",
|
|
59
|
+
"format": "prettier --write .",
|
|
31
60
|
"test": "jest",
|
|
32
61
|
"test:watch": "jest --watch",
|
|
33
|
-
"test:coverage": "jest --coverage"
|
|
34
|
-
"lint": "eslint js/ src/",
|
|
35
|
-
"lint:fix": "eslint js/ src/ --fix",
|
|
36
|
-
"format": "prettier --write js/ src/ css/"
|
|
62
|
+
"test:coverage": "jest --coverage"
|
|
37
63
|
},
|
|
38
64
|
"keywords": [
|
|
39
65
|
"ui",
|
|
40
66
|
"components",
|
|
41
|
-
"ui-components",
|
|
42
67
|
"design-system",
|
|
68
|
+
"frontend",
|
|
43
69
|
"vanilla-js",
|
|
44
70
|
"no-framework",
|
|
45
71
|
"lightweight",
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"javascript-ui",
|
|
50
|
-
"form-validation",
|
|
72
|
+
"ssr",
|
|
73
|
+
"server-side-rendering",
|
|
74
|
+
"declarative",
|
|
51
75
|
"data-binding",
|
|
76
|
+
"htmx-alternative",
|
|
77
|
+
"alpinejs-alternative",
|
|
52
78
|
"responsive",
|
|
53
79
|
"dark-theme",
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"python",
|
|
58
|
-
"gin",
|
|
59
|
-
"go",
|
|
60
|
-
"spring-boot",
|
|
61
|
-
"java",
|
|
62
|
-
"aspnetcore",
|
|
63
|
-
"csharp",
|
|
64
|
-
"express",
|
|
65
|
-
"nodejs",
|
|
66
|
-
"rails",
|
|
67
|
-
"ruby",
|
|
68
|
-
"backend-agnostic",
|
|
69
|
-
"html-css-js"
|
|
80
|
+
"http-client",
|
|
81
|
+
"axios-adapter",
|
|
82
|
+
"typescript"
|
|
70
83
|
],
|
|
71
84
|
"author": "kupola-cn",
|
|
72
85
|
"license": "MIT",
|
|
86
|
+
"repository": {
|
|
87
|
+
"type": "git",
|
|
88
|
+
"url": "https://github.com/kupola-cn/kupola"
|
|
89
|
+
},
|
|
90
|
+
"bugs": {
|
|
91
|
+
"url": "https://github.com/kupola-cn/kupola/issues"
|
|
92
|
+
},
|
|
93
|
+
"homepage": "https://github.com/kupola-cn/kupola",
|
|
73
94
|
"files": [
|
|
74
|
-
"dist",
|
|
75
|
-
"js",
|
|
76
|
-
"css",
|
|
77
|
-
"icons",
|
|
78
|
-
"
|
|
79
|
-
"
|
|
80
|
-
"
|
|
81
|
-
"README.md",
|
|
82
|
-
"SKILL.md",
|
|
83
|
-
"INTEGRATION.md",
|
|
84
|
-
"CHANGELOG.md",
|
|
85
|
-
"PROJECT_SUMMARY.md"
|
|
95
|
+
"dist/",
|
|
96
|
+
"js/",
|
|
97
|
+
"css/",
|
|
98
|
+
"icons/",
|
|
99
|
+
"plugins/",
|
|
100
|
+
"adapters/",
|
|
101
|
+
"types/"
|
|
86
102
|
],
|
|
87
103
|
"devDependencies": {
|
|
88
|
-
"@rollup/plugin-commonjs": "^
|
|
89
|
-
"@rollup/plugin-node-resolve": "^
|
|
90
|
-
"@rollup/plugin-terser": "^
|
|
91
|
-
"
|
|
92
|
-
"
|
|
104
|
+
"@rollup/plugin-commonjs": "^25.0.7",
|
|
105
|
+
"@rollup/plugin-node-resolve": "^15.2.3",
|
|
106
|
+
"@rollup/plugin-terser": "^0.4.4",
|
|
107
|
+
"eslint": "^8.57.0",
|
|
108
|
+
"jest": "^29.7.0",
|
|
109
|
+
"prettier": "^3.2.5",
|
|
110
|
+
"rollup": "^4.13.0",
|
|
93
111
|
"rollup-plugin-copy": "^3.5.0",
|
|
94
112
|
"rollup-plugin-postcss": "^4.0.2",
|
|
95
|
-
"
|
|
96
|
-
"vite": "^5.4.1",
|
|
97
|
-
"eslint": "^9.5.0",
|
|
98
|
-
"prettier": "^3.3.2",
|
|
99
|
-
"jest": "^29.7.0",
|
|
100
|
-
"jest-environment-jsdom": "^29.7.0"
|
|
101
|
-
},
|
|
102
|
-
"dependencies": {
|
|
103
|
-
"ws": "^8.21.0"
|
|
113
|
+
"vite": "^5.1.6"
|
|
104
114
|
}
|
|
105
|
-
}
|
|
115
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @kupola/vite-plugin - Vite plugin for Kupola development
|
|
3
|
+
*
|
|
4
|
+
* Features:
|
|
5
|
+
* - Auto-import useDeps/useQuery when detected in code
|
|
6
|
+
* - Auto-inject Kupola CSS
|
|
7
|
+
* - Dev-time dependency graph visualization
|
|
8
|
+
* - Transform helper for @depends-like syntax
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { readFileSync } from 'fs';
|
|
12
|
+
import { resolve } from 'path';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @param {Object} options
|
|
16
|
+
* @param {boolean} [options.autoCSS=true] - Auto inject Kupola CSS
|
|
17
|
+
* @param {boolean} [options.autoImport=true] - Auto import useDeps/useQuery
|
|
18
|
+
* @param {boolean} [options.devTools=true] - Enable dev tools in dev mode
|
|
19
|
+
* @param {string} [options.cssPath] - Custom CSS path
|
|
20
|
+
*/
|
|
21
|
+
export function kupola(options = {}) {
|
|
22
|
+
const {
|
|
23
|
+
autoCSS = true,
|
|
24
|
+
autoImport = true,
|
|
25
|
+
devTools = true,
|
|
26
|
+
cssPath = null
|
|
27
|
+
} = options;
|
|
28
|
+
|
|
29
|
+
let isDev = false;
|
|
30
|
+
let kupolaRoot = null;
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
name: 'kupola',
|
|
34
|
+
enforce: 'pre',
|
|
35
|
+
|
|
36
|
+
configResolved(config) {
|
|
37
|
+
isDev = config.command === 'serve';
|
|
38
|
+
kupolaRoot = config.root;
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
// Auto-import useDeps/useQuery
|
|
42
|
+
transform(code, id) {
|
|
43
|
+
if (!autoImport) return null;
|
|
44
|
+
if (!id.endsWith('.js') && !id.endsWith('.ts') && !id.endsWith('.vue') && !id.endsWith('.jsx') && !id.endsWith('.tsx')) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Skip node_modules
|
|
49
|
+
if (id.includes('node_modules')) return null;
|
|
50
|
+
|
|
51
|
+
let transformed = code;
|
|
52
|
+
let hasChanges = false;
|
|
53
|
+
|
|
54
|
+
// Detect useDeps usage without import
|
|
55
|
+
if (code.includes('useDeps(') && !code.includes("from '@kupola/kupola'") && !code.includes("from 'kupola'") && !code.includes('from "../js/depends.js"') && !code.includes('from "./js/depends.js"')) {
|
|
56
|
+
const importStatement = `import { useDeps } from '@kupola/kupola';\n`;
|
|
57
|
+
transformed = importStatement + transformed;
|
|
58
|
+
hasChanges = true;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Detect useQuery usage without import
|
|
62
|
+
if (code.includes('useQuery(') && !code.includes("from '@kupola/kupola'") && !code.includes("from 'kupola'") && !code.includes('from "../js/depends.js"') && !code.includes('from "./js/depends.js"')) {
|
|
63
|
+
if (!transformed.includes("import { useQuery }")) {
|
|
64
|
+
const importStatement = `import { useQuery } from '@kupola/kupola';\n`;
|
|
65
|
+
transformed = importStatement + transformed;
|
|
66
|
+
hasChanges = true;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (hasChanges) {
|
|
71
|
+
return {
|
|
72
|
+
code: transformed,
|
|
73
|
+
map: null
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return null;
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
// Inject CSS in dev mode
|
|
81
|
+
transformIndexHtml(html) {
|
|
82
|
+
if (!autoCSS) return html;
|
|
83
|
+
|
|
84
|
+
const cssLink = cssPath || '/css/kupola.css';
|
|
85
|
+
if (!html.includes(cssLink)) {
|
|
86
|
+
return html.replace(
|
|
87
|
+
'</head>',
|
|
88
|
+
` <link rel="stylesheet" href="${cssLink}">\n</head>`
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
return html;
|
|
92
|
+
},
|
|
93
|
+
|
|
94
|
+
// Dev tools integration
|
|
95
|
+
configureServer(server) {
|
|
96
|
+
if (!devTools || !isDev) return;
|
|
97
|
+
|
|
98
|
+
// Add middleware for dependency graph API
|
|
99
|
+
server.middlewares.use('/__kupola-deps', (req, res) => {
|
|
100
|
+
res.setHeader('Content-Type', 'application/json');
|
|
101
|
+
res.end(JSON.stringify({
|
|
102
|
+
status: 'ok',
|
|
103
|
+
version: '1.2.1',
|
|
104
|
+
features: ['useDeps', 'useQuery', 'Scheduler', 'CacheManager']
|
|
105
|
+
}));
|
|
106
|
+
});
|
|
107
|
+
},
|
|
108
|
+
|
|
109
|
+
// Handle hot update for depends files
|
|
110
|
+
handleHotUpdate(ctx) {
|
|
111
|
+
const { file, modules } = ctx;
|
|
112
|
+
if (file.includes('depends.js')) {
|
|
113
|
+
// Force full reload when core depends files change
|
|
114
|
+
return [];
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export default kupola;
|