vgapp 1.2.5 → 1.3.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/README.md +131 -20
- package/app/modules/base-module.js +111 -17
- package/app/modules/vgalert/js/vgalert.js +3 -3
- package/app/modules/vgdynamictable/index.js +5 -0
- package/app/modules/vgdynamictable/js/editable.js +438 -0
- package/app/modules/vgdynamictable/js/expandable.js +248 -0
- package/app/modules/vgdynamictable/js/filters.js +450 -0
- package/app/modules/vgdynamictable/js/fixed.js +566 -0
- package/app/modules/vgdynamictable/js/options.js +646 -0
- package/app/modules/vgdynamictable/js/pagination.js +623 -0
- package/app/modules/vgdynamictable/js/search.js +82 -0
- package/app/modules/vgdynamictable/js/skeleton.js +136 -0
- package/app/modules/vgdynamictable/js/sortable.js +442 -0
- package/app/modules/vgdynamictable/js/summary-footer.js +284 -0
- package/app/modules/vgdynamictable/js/table-remote.js +821 -0
- package/app/modules/vgdynamictable/js/table-state.js +243 -0
- package/app/modules/vgdynamictable/js/table-url-state.js +444 -0
- package/app/modules/vgdynamictable/js/utils/common.js +48 -0
- package/app/modules/vgdynamictable/js/vgdynamictable.js +3829 -0
- package/app/modules/vgdynamictable/js/viewport.js +322 -0
- package/app/modules/vgdynamictable/readme.md +251 -0
- package/app/modules/vgdynamictable/scss/_actions.scss +193 -0
- package/app/modules/vgdynamictable/scss/_pagination.scss +183 -0
- package/app/modules/vgdynamictable/scss/_skeleton.scss +60 -0
- package/app/modules/vgdynamictable/scss/_sortable.scss +63 -0
- package/app/modules/vgdynamictable/scss/_table.scss +157 -0
- package/app/modules/vgdynamictable/scss/_variables.scss +130 -0
- package/app/modules/vgdynamictable/scss/vgdynamictable.scss +267 -0
- package/app/modules/vgrangeslider/index.js +3 -0
- package/app/modules/vgrangeslider/js/skins.js +222 -0
- package/app/modules/vgrangeslider/js/vgrangeslider.js +704 -0
- package/app/modules/vgrangeslider/readme.md +523 -0
- package/app/modules/vgrangeslider/scss/_variables.scss +53 -0
- package/app/modules/vgrangeslider/scss/vgrangeslider.scss +240 -0
- package/app/utils/js/components/ajax.js +116 -7
- package/app/vgapp.js +107 -0
- package/build/vgapp.css +2 -3246
- package/build/vgapp.css.map +1 -1
- package/build/vgapp.js +3 -30
- package/build/vgapp.js.LICENSE.txt +1 -0
- package/build/vgapp.js.map +1 -1
- package/index.js +15 -8
- package/index.scss +6 -0
- package/package.json +21 -1
- package/.gitattributes +0 -1
- package/CHANGELOG.md +0 -369
- package/agents.md +0 -14
- package/webpack.config.js +0 -63
package/README.md
CHANGED
|
@@ -6,10 +6,119 @@ VGApp — набор фронтенд‑модулей (UI‑компонент
|
|
|
6
6
|
|
|
7
7
|
[](https://www.npmjs.com/package/vgapp) []()
|
|
8
8
|
|
|
9
|
-
## Install
|
|
10
|
-
```
|
|
11
|
-
npm i vgapp
|
|
12
|
-
```
|
|
9
|
+
## Install
|
|
10
|
+
```
|
|
11
|
+
npm i vgapp
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Локально из соседнего репозитория:
|
|
15
|
+
```json
|
|
16
|
+
{
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"vgapp": "file:../vegas-app"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## API
|
|
24
|
+
```js
|
|
25
|
+
import vgapp from 'vgapp';
|
|
26
|
+
|
|
27
|
+
vgapp.boot();
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
- `vgapp` экспортируется как singleton app.
|
|
31
|
+
- `vgapp.register()` регистрирует модули по их статическому `NAME`.
|
|
32
|
+
- `vgapp.boot()` вызывает общий boot-контракт модуля.
|
|
33
|
+
- У модулей со своим `initAll()` boot использует его автоматически.
|
|
34
|
+
|
|
35
|
+
Для выборочного набора модулей создавайте отдельный экземпляр:
|
|
36
|
+
```js
|
|
37
|
+
import { VGApp, VGModal, VGTooltip } from 'vgapp';
|
|
38
|
+
|
|
39
|
+
const app = new VGApp();
|
|
40
|
+
|
|
41
|
+
app
|
|
42
|
+
.register(VGModal, VGTooltip)
|
|
43
|
+
.boot();
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Подключение
|
|
47
|
+
|
|
48
|
+
### Laravel + Vite
|
|
49
|
+
`resources/js/app.js`
|
|
50
|
+
```js
|
|
51
|
+
import vgapp from 'vgapp';
|
|
52
|
+
import 'vgapp/build/vgapp.css';
|
|
53
|
+
|
|
54
|
+
vgapp.boot();
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
`vite.config.js`
|
|
58
|
+
```js
|
|
59
|
+
import { defineConfig } from 'vite';
|
|
60
|
+
import laravel from 'laravel-vite-plugin';
|
|
61
|
+
|
|
62
|
+
export default defineConfig({
|
|
63
|
+
plugins: [
|
|
64
|
+
laravel([
|
|
65
|
+
'resources/css/app.css',
|
|
66
|
+
'resources/js/app.js',
|
|
67
|
+
]),
|
|
68
|
+
],
|
|
69
|
+
});
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
В Blade:
|
|
73
|
+
```php
|
|
74
|
+
@vite(['resources/css/app.css', 'resources/js/app.js'])
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Vite
|
|
78
|
+
`src/main.js`
|
|
79
|
+
```js
|
|
80
|
+
import vgapp from 'vgapp';
|
|
81
|
+
import 'vgapp/build/vgapp.css';
|
|
82
|
+
|
|
83
|
+
vgapp.boot();
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Webpack
|
|
87
|
+
`src/app.js`
|
|
88
|
+
```js
|
|
89
|
+
import vgapp from 'vgapp';
|
|
90
|
+
import 'vgapp/build/vgapp.css';
|
|
91
|
+
|
|
92
|
+
vgapp.boot();
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Минимально в `webpack.config.js`:
|
|
96
|
+
```js
|
|
97
|
+
module.exports = {
|
|
98
|
+
entry: './src/app.js',
|
|
99
|
+
module: {
|
|
100
|
+
rules: [
|
|
101
|
+
{
|
|
102
|
+
test: /\.css$/i,
|
|
103
|
+
use: ['style-loader', 'css-loader'],
|
|
104
|
+
},
|
|
105
|
+
],
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Частичный boot
|
|
111
|
+
Если не нужно поднимать весь реестр singleton-приложения:
|
|
112
|
+
```js
|
|
113
|
+
import { VGApp, VGModal, VGTooltip } from 'vgapp';
|
|
114
|
+
import 'vgapp/build/vgapp.css';
|
|
115
|
+
|
|
116
|
+
const app = new VGApp();
|
|
117
|
+
|
|
118
|
+
app
|
|
119
|
+
.register(VGModal, VGTooltip)
|
|
120
|
+
.boot();
|
|
121
|
+
```
|
|
13
122
|
|
|
14
123
|
## Что умеет
|
|
15
124
|
|
|
@@ -21,22 +130,24 @@ npm i vgapp
|
|
|
21
130
|
- Локализация интерфейсных текстов.
|
|
22
131
|
- Расширяемая архитектура модулей и рендереров.
|
|
23
132
|
|
|
24
|
-
### Основные модули
|
|
25
|
-
- `VGAlert` — диалоги подтверждения и уведомления с поддержкой AJAX‑сценариев.
|
|
26
|
-
- `VGCollapse` — сворачиваемые секции и аккордеоны с анимацией.
|
|
27
|
-
- `VGDropdown` — выпадающие меню с гибким открытием и позиционированием.
|
|
28
|
-
- `
|
|
29
|
-
- `
|
|
30
|
-
- `
|
|
31
|
-
- `
|
|
32
|
-
- `
|
|
33
|
-
- `
|
|
34
|
-
- `
|
|
35
|
-
- `
|
|
36
|
-
- `
|
|
37
|
-
- `
|
|
38
|
-
- `
|
|
39
|
-
- `
|
|
133
|
+
### Основные модули
|
|
134
|
+
- `VGAlert` — диалоги подтверждения и уведомления с поддержкой AJAX‑сценариев.
|
|
135
|
+
- `VGCollapse` — сворачиваемые секции и аккордеоны с анимацией.
|
|
136
|
+
- `VGDropdown` — выпадающие меню с гибким открытием и позиционированием.
|
|
137
|
+
- `VGDynamicTable` — интерактивные таблицы с сортировкой, фильтрацией, remote-режимом и состоянием.
|
|
138
|
+
- `VGFiles` — загрузка и управление файлами (dropzone, валидация, AJAX, сортировка).
|
|
139
|
+
- `VGFilePreview` — предпросмотр файлов разных типов и действия по файлу (preview/download).
|
|
140
|
+
- `VGFormSender` — отправка форм (AJAX/нативно), обработка состояний и ответов.
|
|
141
|
+
- `VGLawCookie` — баннер cookies с сохранением выбора пользователя.
|
|
142
|
+
- `VGLoadMore` — подгрузка контента кнопкой или при прокрутке.
|
|
143
|
+
- `VGModal` — базовый модуль модальных окон.
|
|
144
|
+
- `VGNav` — навигация и мобильное меню.
|
|
145
|
+
- `VGNestable` — drag‑and‑drop вложенных списков с обновлением структуры.
|
|
146
|
+
- `VGRangeSlider` — одиночные и диапазонные слайдеры со значениями, лимитами и синхронизацией полей.
|
|
147
|
+
- `VGRollup` — ограничение контента по высоте/элементам с кнопкой разворота.
|
|
148
|
+
- `VGSelect` — кастомный select с поиском, мультивыбором и i18n.
|
|
149
|
+
- `VGSidebar` — боковые панели с управлением открытием/закрытием.
|
|
150
|
+
- `VGSpy` — scroll‑spy для подсветки активных ссылок по секциям.
|
|
40
151
|
- `VGTabs` — вкладки с переключением контента и поддержкой URL/hash.
|
|
41
152
|
- `VGToast` — всплывающие уведомления со стеком и автозакрытием.
|
|
42
153
|
- `VGTooltip` — tooltip/popover подсказки с Data API, автопозиционированием и закрытием по `Esc`/клику вне элемента.
|
|
@@ -15,8 +15,8 @@ import Animation from "../utils/js/components/animation";
|
|
|
15
15
|
import Ajax from "../utils/js/components/ajax";
|
|
16
16
|
import Html from "../utils/js/components/templater";
|
|
17
17
|
|
|
18
|
-
class BaseModule {
|
|
19
|
-
constructor(element) {
|
|
18
|
+
class BaseModule {
|
|
19
|
+
constructor(element) {
|
|
20
20
|
if (!element) return
|
|
21
21
|
|
|
22
22
|
this._element = Selectors.find(element);
|
|
@@ -54,9 +54,13 @@ class BaseModule {
|
|
|
54
54
|
* - timeout = задержка перед отправкой, по умолчанию 0
|
|
55
55
|
* @param callback
|
|
56
56
|
*/
|
|
57
|
-
_route(callback) {
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
_route(callback) {
|
|
58
|
+
if (typeof callback !== 'function') {
|
|
59
|
+
return this._requestRoute(callback);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
let $content = null,
|
|
63
|
+
timeout = this._params.ajax.timeout || 0;
|
|
60
64
|
|
|
61
65
|
if (this._isLoaded) return;
|
|
62
66
|
|
|
@@ -133,10 +137,83 @@ class BaseModule {
|
|
|
133
137
|
if (this._params.ajax.method.toLowerCase() === 'delete') {
|
|
134
138
|
ajax.delete(this._params.ajax.route, ajaxData);
|
|
135
139
|
}
|
|
136
|
-
}, timeout);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
+
}, timeout);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
_requestRoute(options = {}) {
|
|
144
|
+
const config = this._normalizeRouteRequestOptions(options);
|
|
145
|
+
return Ajax.requestRoute(config);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
_buildRouteUrl(params = {}, endpoint = '', options = {}) {
|
|
149
|
+
const config = this._normalizeRouteRequestOptions(Object.assign({}, options, {
|
|
150
|
+
params,
|
|
151
|
+
route: endpoint || options.route || '',
|
|
152
|
+
}));
|
|
153
|
+
return Ajax.buildRouteUrl(config.route, {
|
|
154
|
+
params: config.params,
|
|
155
|
+
baseParams: config.baseParams,
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
_normalizeRouteRequestOptions(options = {}) {
|
|
160
|
+
const requestOptions = this._params && isObject(this._params.request)
|
|
161
|
+
? this._params.request
|
|
162
|
+
: {};
|
|
163
|
+
const ajaxOptions = this._params && isObject(this._params.ajax)
|
|
164
|
+
? this._params.ajax
|
|
165
|
+
: {};
|
|
166
|
+
const source = isObject(options) ? options : {};
|
|
167
|
+
const route = String(
|
|
168
|
+
source.route
|
|
169
|
+
|| source.endpoint
|
|
170
|
+
|| requestOptions.route
|
|
171
|
+
|| ajaxOptions.route
|
|
172
|
+
|| ''
|
|
173
|
+
).trim();
|
|
174
|
+
const method = String(
|
|
175
|
+
source.method
|
|
176
|
+
|| requestOptions.method
|
|
177
|
+
|| ajaxOptions.method
|
|
178
|
+
|| 'GET'
|
|
179
|
+
).toUpperCase().trim() || 'GET';
|
|
180
|
+
const credentials = String(
|
|
181
|
+
source.credentials
|
|
182
|
+
|| requestOptions.credentials
|
|
183
|
+
|| 'same-origin'
|
|
184
|
+
).trim() || 'same-origin';
|
|
185
|
+
const headers = mergeDeepObject(
|
|
186
|
+
{
|
|
187
|
+
'Accept': 'application/json',
|
|
188
|
+
'X-Requested-With': 'XMLHttpRequest',
|
|
189
|
+
},
|
|
190
|
+
isObject(requestOptions.headers) ? requestOptions.headers : {},
|
|
191
|
+
isObject(source.headers) ? source.headers : {}
|
|
192
|
+
);
|
|
193
|
+
const baseParams = mergeDeepObject(
|
|
194
|
+
{},
|
|
195
|
+
isObject(requestOptions.params) ? requestOptions.params : {},
|
|
196
|
+
isObject(source.baseParams) ? source.baseParams : {},
|
|
197
|
+
isObject(source.paramsBase) ? source.paramsBase : {}
|
|
198
|
+
);
|
|
199
|
+
const params = isObject(source.params) ? source.params : {};
|
|
200
|
+
const body = source.body !== undefined
|
|
201
|
+
? source.body
|
|
202
|
+
: (source.data !== undefined ? source.data : null);
|
|
203
|
+
return {
|
|
204
|
+
route,
|
|
205
|
+
method,
|
|
206
|
+
credentials,
|
|
207
|
+
headers,
|
|
208
|
+
baseParams,
|
|
209
|
+
params,
|
|
210
|
+
body,
|
|
211
|
+
signal: source.signal || null,
|
|
212
|
+
responseType: String(source.responseType || source.parse || 'auto').toLowerCase().trim() || 'auto',
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
_dismissElement() {
|
|
140
217
|
let cross = getSVG('cross'),
|
|
141
218
|
button = this._element.querySelector('.vg-btn-close');
|
|
142
219
|
|
|
@@ -158,17 +235,34 @@ class BaseModule {
|
|
|
158
235
|
return Data.get(Selectors.find(element), this.NAME_KEY)
|
|
159
236
|
}
|
|
160
237
|
|
|
161
|
-
static getOrCreateInstance(element, params = {}) {
|
|
162
|
-
return this.getInstance(element) || new this(element, !isEmptyObj(params) ? params : {})
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
static
|
|
166
|
-
|
|
167
|
-
|
|
238
|
+
static getOrCreateInstance(element, params = {}) {
|
|
239
|
+
return this.getInstance(element) || new this(element, !isEmptyObj(params) ? params : {})
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
static boot(params = {}) {
|
|
243
|
+
if (typeof this.initAll === 'function') {
|
|
244
|
+
return this.initAll(params);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
if (typeof this.init !== 'function') {
|
|
248
|
+
return null;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
if (params && Object.prototype.hasOwnProperty.call(params, 'element')) {
|
|
252
|
+
const { element, ...options } = params;
|
|
253
|
+
return this.init(element, options);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
return null;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
static get DATA_KEY() {
|
|
260
|
+
return `vg.${this.NAME}`
|
|
261
|
+
}
|
|
168
262
|
|
|
169
263
|
static get EVENT_KEY() {
|
|
170
264
|
return `.${this.DATA_KEY}`
|
|
171
265
|
}
|
|
172
266
|
}
|
|
173
267
|
|
|
174
|
-
export default BaseModule;
|
|
268
|
+
export default BaseModule;
|
|
@@ -127,7 +127,7 @@ class VGAlert {
|
|
|
127
127
|
const cancelBtn = Selectors.find(`[${DATA_CANCEL}]`, container);
|
|
128
128
|
|
|
129
129
|
return new Promise((resolve, reject) => {
|
|
130
|
-
const closeAlert = () => {
|
|
130
|
+
const closeAlert = (isHide = true) => {
|
|
131
131
|
if (type === 'modal') {
|
|
132
132
|
render.hide();
|
|
133
133
|
return;
|
|
@@ -136,7 +136,7 @@ class VGAlert {
|
|
|
136
136
|
if (type === 'overlay') {
|
|
137
137
|
container.remove();
|
|
138
138
|
|
|
139
|
-
if (context._params.render.dismiss) {
|
|
139
|
+
if (context._params.render.dismiss && isHide) {
|
|
140
140
|
render.hide();
|
|
141
141
|
}
|
|
142
142
|
}
|
|
@@ -159,7 +159,7 @@ class VGAlert {
|
|
|
159
159
|
accepted: false,
|
|
160
160
|
timestamp: new Date(),
|
|
161
161
|
});
|
|
162
|
-
closeAlert();
|
|
162
|
+
closeAlert(false);
|
|
163
163
|
};
|
|
164
164
|
|
|
165
165
|
const handleKeydown = (e) => {
|