@windwalker-io/unicorn-next 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.editorconfig +18 -0
- package/.gulp.json +7 -0
- package/bin/release.mjs +47 -0
- package/dist/chunks/_arrayPush.js +168 -0
- package/dist/chunks/_arrayPush.js.map +1 -0
- package/dist/chunks/_baseRest.js +73 -0
- package/dist/chunks/_baseRest.js.map +1 -0
- package/dist/chunks/_commonjsHelpers.js +7 -0
- package/dist/chunks/_commonjsHelpers.js.map +1 -0
- package/dist/chunks/_getPrototype.js +130 -0
- package/dist/chunks/_getPrototype.js.map +1 -0
- package/dist/chunks/button-radio.js +147 -0
- package/dist/chunks/button-radio.js.map +1 -0
- package/dist/chunks/checkboxes-multi-select.js +44 -0
- package/dist/chunks/checkboxes-multi-select.js.map +1 -0
- package/dist/chunks/cloneDeep.js +287 -0
- package/dist/chunks/cloneDeep.js.map +1 -0
- package/dist/chunks/cropper.min.js +5 -0
- package/dist/chunks/cropper.min.js.map +1 -0
- package/dist/chunks/field-cascade-select.js +256 -0
- package/dist/chunks/field-cascade-select.js.map +1 -0
- package/dist/chunks/field-file-drag.js +218 -0
- package/dist/chunks/field-file-drag.js.map +1 -0
- package/dist/chunks/field-flatpickr.js +893 -0
- package/dist/chunks/field-flatpickr.js.map +1 -0
- package/dist/chunks/field-modal-select.js +403 -0
- package/dist/chunks/field-modal-select.js.map +1 -0
- package/dist/chunks/field-modal-tree.js +790 -0
- package/dist/chunks/field-modal-tree.js.map +1 -0
- package/dist/chunks/field-multi-uploader.js +256 -0
- package/dist/chunks/field-multi-uploader.js.map +1 -0
- package/dist/chunks/field-repeatable.js +132 -0
- package/dist/chunks/field-repeatable.js.map +1 -0
- package/dist/chunks/field-single-image-drag.js +338 -0
- package/dist/chunks/field-single-image-drag.js.map +1 -0
- package/dist/chunks/form.js +154 -0
- package/dist/chunks/form.js.map +1 -0
- package/dist/chunks/grid.js +345 -0
- package/dist/chunks/grid.js.map +1 -0
- package/dist/chunks/http-client.js +229 -0
- package/dist/chunks/http-client.js.map +1 -0
- package/dist/chunks/iframe-modal.js +124 -0
- package/dist/chunks/iframe-modal.js.map +1 -0
- package/dist/chunks/index.js +309 -0
- package/dist/chunks/index.js.map +1 -0
- package/dist/chunks/isArguments.js +146 -0
- package/dist/chunks/isArguments.js.map +1 -0
- package/dist/chunks/keep-tab.js +101 -0
- package/dist/chunks/keep-tab.js.map +1 -0
- package/dist/chunks/legacy.js +210 -0
- package/dist/chunks/legacy.js.map +1 -0
- package/dist/chunks/list-dependent.js +231 -0
- package/dist/chunks/list-dependent.js.map +1 -0
- package/dist/chunks/s3-multipart-uploader.js +172 -0
- package/dist/chunks/s3-multipart-uploader.js.map +1 -0
- package/dist/chunks/s3-uploader.js +136 -0
- package/dist/chunks/s3-uploader.js.map +1 -0
- package/dist/chunks/show-on.js +237 -0
- package/dist/chunks/show-on.js.map +1 -0
- package/dist/chunks/tinymce.js +196 -0
- package/dist/chunks/tinymce.js.map +1 -0
- package/dist/chunks/ui-bootstrap5.js +71 -0
- package/dist/chunks/ui-bootstrap5.js.map +1 -0
- package/dist/chunks/unicorn.js +2202 -0
- package/dist/chunks/unicorn.js.map +1 -0
- package/dist/chunks/validation.js +854 -0
- package/dist/chunks/validation.js.map +1 -0
- package/dist/editor.css +1 -0
- package/dist/index.d.ts +1427 -0
- package/dist/multi-level-menu.css +1 -0
- package/dist/switcher.css +1 -0
- package/dist/unicorn-next.css +12 -0
- package/dist/unicorn.js +125 -0
- package/dist/unicorn.js.map +1 -0
- package/fusionfile.mjs +155 -0
- package/images/ajax-loader.gif +0 -0
- package/images/placeholder/avatar.png +0 -0
- package/images/placeholder/image-16x10.png +0 -0
- package/images/placeholder/image-16x9.png +0 -0
- package/images/placeholder/image-1x1.png +0 -0
- package/images/placeholder/image-4x3.png +0 -0
- package/package.json +102 -0
- package/scss/bootstrap/multi-level-menu.scss +121 -0
- package/scss/editor.scss +116 -0
- package/scss/field/file-drag.scss +102 -0
- package/scss/field/single-image-drag.scss +88 -0
- package/scss/field/vue-drag-uploader.scss +160 -0
- package/scss/switcher.scss +156 -0
- package/src/app.ts +128 -0
- package/src/bootstrap/button-radio.ts +208 -0
- package/src/bootstrap/keep-tab.ts +155 -0
- package/src/composable/index.ts +21 -0
- package/src/composable/useCheckboxesMultiSelect.ts +22 -0
- package/src/composable/useFieldCascadeSelect.ts +9 -0
- package/src/composable/useFieldFileDrag.ts +9 -0
- package/src/composable/useFieldFlatpickr.ts +3 -0
- package/src/composable/useFieldModalSelect.ts +6 -0
- package/src/composable/useFieldModalTree.ts +3 -0
- package/src/composable/useFieldMultiUploader.ts +3 -0
- package/src/composable/useFieldRepeatable.ts +9 -0
- package/src/composable/useFieldSingleImageDrag.ts +5 -0
- package/src/composable/useForm.ts +43 -0
- package/src/composable/useGrid.ts +57 -0
- package/src/composable/useHttp.ts +8 -0
- package/src/composable/useIframeModal.ts +9 -0
- package/src/composable/useListDependent.ts +26 -0
- package/src/composable/useQueue.ts +13 -0
- package/src/composable/useS3Uploader.ts +32 -0
- package/src/composable/useShowOn.ts +9 -0
- package/src/composable/useStack.ts +13 -0
- package/src/composable/useTinymce.ts +29 -0
- package/src/composable/useTomSelect.ts +72 -0
- package/src/composable/useUIBootstrap5.ts +48 -0
- package/src/composable/useUniDirective.ts +32 -0
- package/src/composable/useValidation.ts +39 -0
- package/src/data.ts +36 -0
- package/src/events.ts +73 -0
- package/src/legacy/legacy.ts +186 -0
- package/src/legacy/loader.ts +125 -0
- package/src/module/checkboxes-multi-select.ts +54 -0
- package/src/module/field-cascade-select.ts +292 -0
- package/src/module/field-file-drag.ts +292 -0
- package/src/module/field-flatpickr.ts +127 -0
- package/src/module/field-modal-select.ts +174 -0
- package/src/module/field-modal-tree.ts +27 -0
- package/src/module/field-multi-uploader.ts +361 -0
- package/src/module/field-repeatable.ts +202 -0
- package/src/module/field-single-image-drag.ts +468 -0
- package/src/module/form.ts +223 -0
- package/src/module/grid.ts +465 -0
- package/src/module/http-client.ts +243 -0
- package/src/module/iframe-modal.ts +167 -0
- package/src/module/list-dependent.ts +321 -0
- package/src/module/s3-multipart-uploader.ts +300 -0
- package/src/module/s3-uploader.ts +234 -0
- package/src/module/show-on.ts +173 -0
- package/src/module/tinymce.ts +263 -0
- package/src/module/ui-bootstrap5.ts +107 -0
- package/src/module/validation.ts +1019 -0
- package/src/plugin/index.ts +1 -0
- package/src/plugin/php-adapter.ts +65 -0
- package/src/polyfill/form-request-submit.ts +31 -0
- package/src/polyfill/index.ts +9 -0
- package/src/service/animate.ts +58 -0
- package/src/service/crypto.ts +27 -0
- package/src/service/dom-watcher.ts +62 -0
- package/src/service/dom.ts +265 -0
- package/src/service/helper.ts +48 -0
- package/src/service/index.ts +10 -0
- package/src/service/lang.ts +122 -0
- package/src/service/loader.ts +152 -0
- package/src/service/router.ts +118 -0
- package/src/service/ui.ts +497 -0
- package/src/service/uri.ts +106 -0
- package/src/types/base.ts +9 -0
- package/src/types/index.ts +4 -0
- package/src/types/modal-tree.ts +12 -0
- package/src/types/plugin.ts +6 -0
- package/src/types/shims.d.ts +18 -0
- package/src/types/ui.ts +6 -0
- package/src/unicorn.ts +63 -0
- package/src/utilities/arr.ts +25 -0
- package/src/utilities/base.ts +9 -0
- package/src/utilities/data.ts +48 -0
- package/src/utilities/index.ts +5 -0
- package/src/utilities/tree.ts +20 -0
- package/src/vue/components/ModalTree/ModalTreeApp.vue +175 -0
- package/src/vue/components/ModalTree/TreeItem.vue +262 -0
- package/src/vue/components/ModalTree/TreeModal.vue +225 -0
- package/tests/test.js +4 -0
- package/tsconfig.js.json +25 -0
- package/tsconfig.json +17 -0
- package/vite.assets.config.ts +61 -0
- package/vite.config.test.ts +36 -0
- package/vite.config.ts +112 -0
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { useUniDirective } from '../composable';
|
|
2
|
+
import { data } from '../data';
|
|
3
|
+
import { getBoundedInstance, h, selectAll, selectOne } from '../service';
|
|
4
|
+
import { mergeDeep } from '../utilities';
|
|
5
|
+
|
|
6
|
+
export interface ButtonRadioOptions {
|
|
7
|
+
selector?: string;
|
|
8
|
+
buttonClass?: string;
|
|
9
|
+
activeClass?: string;
|
|
10
|
+
color?: {
|
|
11
|
+
'default'?: string;
|
|
12
|
+
green?: string;
|
|
13
|
+
red?: string;
|
|
14
|
+
blue?: string;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const defaultOptions = {
|
|
19
|
+
selector: '.btn-group .radio',
|
|
20
|
+
buttonClass: 'btn',
|
|
21
|
+
activeClass: 'active',
|
|
22
|
+
color: {
|
|
23
|
+
'default': 'btn-default btn-outline-secondary',
|
|
24
|
+
green: 'btn-success',
|
|
25
|
+
red: 'btn-danger',
|
|
26
|
+
blue: 'btn-primary'
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export class ButtonRadio {
|
|
31
|
+
wrapper: HTMLElement;
|
|
32
|
+
element: HTMLElement;
|
|
33
|
+
radios: HTMLInputElement[] = [];
|
|
34
|
+
inputs: HTMLInputElement[] = [];
|
|
35
|
+
buttons: HTMLButtonElement[] = [];
|
|
36
|
+
colors: string[] = [];
|
|
37
|
+
options: Required<ButtonRadioOptions>;
|
|
38
|
+
|
|
39
|
+
static handle(el: HTMLElement | string, options: ButtonRadioOptions = {}) {
|
|
40
|
+
return getBoundedInstance(el, 'button-radio', (el: HTMLElement) => {
|
|
41
|
+
return new this(el, options);
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
constructor(selector: HTMLElement | string, options: ButtonRadioOptions = {}) {
|
|
46
|
+
this.element = selectOne<HTMLElement>(selector)!;
|
|
47
|
+
this.options = mergeDeep({}, defaultOptions, options);
|
|
48
|
+
let wrapper: HTMLElement;
|
|
49
|
+
|
|
50
|
+
// Turn radios into btn-group
|
|
51
|
+
|
|
52
|
+
if (this.element.dataset.fieldInput != null) {
|
|
53
|
+
wrapper = this.element;
|
|
54
|
+
} else {
|
|
55
|
+
wrapper = this.element.querySelector('[data-field-input]')!;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
this.wrapper = wrapper;
|
|
59
|
+
let inputGroup = wrapper.querySelector<HTMLElement>('.btn-group')!;
|
|
60
|
+
const exists = inputGroup != null;
|
|
61
|
+
|
|
62
|
+
if (!inputGroup) {
|
|
63
|
+
inputGroup = h('div', { class: 'btn-group' })
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
this.radios = selectAll(wrapper.querySelectorAll<HTMLInputElement>('.radio'));
|
|
67
|
+
|
|
68
|
+
this.radios.forEach(radio => {
|
|
69
|
+
const button = this.prepareButton(radio, exists);
|
|
70
|
+
|
|
71
|
+
if (!exists) {
|
|
72
|
+
inputGroup.appendChild(button);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
this.syncState();
|
|
77
|
+
|
|
78
|
+
wrapper.insertBefore(inputGroup, wrapper.firstChild);
|
|
79
|
+
|
|
80
|
+
wrapper.dispatchEvent(new Event('button-radio.loaded'));
|
|
81
|
+
|
|
82
|
+
// Make color elements unique
|
|
83
|
+
this.colors = [...new Set(this.colors)];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
prepareButton(radio: HTMLInputElement, exists = false) {
|
|
87
|
+
const options = this.options;
|
|
88
|
+
|
|
89
|
+
const input = radio.querySelector('input')!;
|
|
90
|
+
const label = radio.querySelector('label')!;
|
|
91
|
+
|
|
92
|
+
let button: HTMLButtonElement;
|
|
93
|
+
|
|
94
|
+
if (exists) {
|
|
95
|
+
button = this.wrapper.querySelector(`[data-for="${input.id}"]`)!;
|
|
96
|
+
button.classList.add(...this.parseClasses(`${options.buttonClass} ${options.color['default']}`));
|
|
97
|
+
} else {
|
|
98
|
+
button = h(
|
|
99
|
+
'button',
|
|
100
|
+
{
|
|
101
|
+
type: 'button',
|
|
102
|
+
class: `${options.buttonClass} ${options.color['default']}`,
|
|
103
|
+
'data-value': input.value,
|
|
104
|
+
},
|
|
105
|
+
`<span>${label.innerHTML}</span>`
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
data(button, 'input', input);
|
|
110
|
+
this.inputs.push(input);
|
|
111
|
+
this.buttons.push(button);
|
|
112
|
+
|
|
113
|
+
radio.style.display = 'none';
|
|
114
|
+
|
|
115
|
+
// Prepare color schema
|
|
116
|
+
let color = input.dataset.colorClass || '';
|
|
117
|
+
|
|
118
|
+
if (!color) {
|
|
119
|
+
switch (input.value) {
|
|
120
|
+
case '':
|
|
121
|
+
color = options.color.blue || '';
|
|
122
|
+
break;
|
|
123
|
+
|
|
124
|
+
case '0':
|
|
125
|
+
color = options.color.red || '';
|
|
126
|
+
break;
|
|
127
|
+
|
|
128
|
+
default:
|
|
129
|
+
color = options.color.green || '';
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
input.dataset.colorClass = color;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
this.colors.push(color);
|
|
137
|
+
|
|
138
|
+
if (input.disabled || input.getAttribute('readonly') != null) {
|
|
139
|
+
button.classList.add('disabled');
|
|
140
|
+
button.disabled = true;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (input.getAttribute('readonly') != null) {
|
|
144
|
+
button.classList.add('readonly');
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Bind event
|
|
148
|
+
button.addEventListener('click', () => {
|
|
149
|
+
if (input.getAttribute('disabled') || input.getAttribute('readonly')) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const changed = !input.checked;
|
|
154
|
+
|
|
155
|
+
if (changed) {
|
|
156
|
+
this.inputs.forEach((ele) => {
|
|
157
|
+
ele.checked = false;
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
input.checked = true;
|
|
161
|
+
|
|
162
|
+
input.dispatchEvent(new Event('change'));
|
|
163
|
+
input.dispatchEvent(new Event('input'));
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
input.addEventListener('change', () => {
|
|
168
|
+
this.syncState();
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
return button;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
syncState() {
|
|
175
|
+
const options = this.options;
|
|
176
|
+
|
|
177
|
+
this.buttons.forEach((button) => {
|
|
178
|
+
const input: HTMLInputElement = data(button, 'input');
|
|
179
|
+
|
|
180
|
+
button.classList.add(...this.parseClasses(options.color.default || ''));
|
|
181
|
+
button.classList.remove(...this.parseClasses(options.activeClass));
|
|
182
|
+
button.classList.remove(...this.parseClasses(...this.colors));
|
|
183
|
+
|
|
184
|
+
if (input.checked) {
|
|
185
|
+
button.classList.add(...this.parseClasses(options.activeClass));
|
|
186
|
+
button.classList.add(...this.parseClasses(input.dataset.colorClass || ''));
|
|
187
|
+
button.classList.remove(...this.parseClasses(options.color.default || ''));
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
parseClasses(...className: string[]) {
|
|
193
|
+
const classNameStr = className.join(' ');
|
|
194
|
+
return classNameStr.split(' ').filter(t => t !== '');
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export const ready = useUniDirective('button-radio', {
|
|
199
|
+
mounted(el, { value }) {
|
|
200
|
+
const options: ButtonRadioOptions = JSON.parse(value || '{}');
|
|
201
|
+
ButtonRadio.handle(el, value || {});
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
export interface ButtonRadioModule {
|
|
206
|
+
ButtonRadio: typeof ButtonRadio;
|
|
207
|
+
ready: typeof ready;
|
|
208
|
+
}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { useUniDirective } from '../composable';
|
|
2
|
+
import { module, selectAll, selectOne, sleep } from '../service';
|
|
3
|
+
import { Tab } from 'bootstrap';
|
|
4
|
+
import { mergeDeep } from '../utilities';
|
|
5
|
+
|
|
6
|
+
export interface KeepTabOptions {
|
|
7
|
+
uid?: string;
|
|
8
|
+
delay?: number;
|
|
9
|
+
tabItemSelector?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const defaultOptions = {
|
|
13
|
+
tabItemSelector: '[data-toggle=tab],[data-bs-toggle=tab],[data-toggle=pill],[data-bs-toggle=pill]',
|
|
14
|
+
delay: 0,
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export class KeepTab {
|
|
18
|
+
$element: HTMLElement;
|
|
19
|
+
tabButtons!: NodeListOf<HTMLElement>;
|
|
20
|
+
storageKey: string = '';
|
|
21
|
+
options: any;
|
|
22
|
+
|
|
23
|
+
constructor(selector: HTMLElement | string, options: KeepTabOptions = {}) {
|
|
24
|
+
options = mergeDeep({}, defaultOptions, options);
|
|
25
|
+
let uid: string;
|
|
26
|
+
|
|
27
|
+
if (typeof selector === 'object') {
|
|
28
|
+
uid = options.uid || selector.id;
|
|
29
|
+
} else {
|
|
30
|
+
uid = selector;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const $element = this.$element = selectOne<HTMLElement>(selector)!;
|
|
34
|
+
|
|
35
|
+
if (!$element) {
|
|
36
|
+
console.warn(`[KeepTab] Element ${selector} not found.`);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
this.options = options;
|
|
41
|
+
|
|
42
|
+
this.$element = $element;
|
|
43
|
+
this.tabButtons = $element.querySelectorAll(this.options.tabItemSelector);
|
|
44
|
+
|
|
45
|
+
this.init(uid);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
protected async init(uid: string) {
|
|
49
|
+
this.storageKey = 'tab-href-' + await this.hashCode(location.href + ':' + uid);
|
|
50
|
+
|
|
51
|
+
this.bindEvents();
|
|
52
|
+
|
|
53
|
+
await sleep(this.options.delay || 0);
|
|
54
|
+
|
|
55
|
+
this.switchTab();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
bindEvents() {
|
|
59
|
+
[].forEach.call(this.tabButtons, (button: HTMLAnchorElement) => {
|
|
60
|
+
button.addEventListener('click', () => {
|
|
61
|
+
// Store the selected tab href in localstorage
|
|
62
|
+
window.localStorage.setItem(this.storageKey, this.getButtonHref(button));
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
getButtonHref(button: HTMLAnchorElement) {
|
|
68
|
+
return button.dataset.bsTarget || button.dataset.target || button.href;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
findTabButtonByHref(href: string) {
|
|
72
|
+
return selectAll<HTMLAnchorElement>(this.options.tabItemSelector)
|
|
73
|
+
.filter((button: HTMLAnchorElement) => {
|
|
74
|
+
if (button.href === href) {
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (button.dataset.bsTarget === href) {
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return button.dataset.target === href;
|
|
83
|
+
})
|
|
84
|
+
.shift();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
activateTab(href: string) {
|
|
88
|
+
const tabTrigger = this.findTabButtonByHref(href);
|
|
89
|
+
|
|
90
|
+
if (tabTrigger) {
|
|
91
|
+
Tab.getOrCreateInstance(tabTrigger).show();
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
hasTab(href: string) {
|
|
96
|
+
return this.findTabButtonByHref(href) != null;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Switch tab.
|
|
101
|
+
*
|
|
102
|
+
* @returns {boolean}
|
|
103
|
+
*/
|
|
104
|
+
switchTab() {
|
|
105
|
+
if (localStorage.getItem(this.storageKey)) {
|
|
106
|
+
// When moving from tab area to a different view
|
|
107
|
+
if (!this.hasTab(localStorage.getItem(this.storageKey) || '')) {
|
|
108
|
+
localStorage.removeItem(this.storageKey);
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Clean default tabs
|
|
113
|
+
// selectOne(this.$element, '[data-toggle="tab"], [data-bs-toggle=tab]')
|
|
114
|
+
// this.$element.querySelector('a[data-toggle="tab"]').parent().removeClass('active');
|
|
115
|
+
|
|
116
|
+
const tabhref = localStorage.getItem(this.storageKey) || '';
|
|
117
|
+
|
|
118
|
+
// Add active attribute for selected tab indicated by url
|
|
119
|
+
this.activateTab(tabhref);
|
|
120
|
+
|
|
121
|
+
// Check whether internal tab is selected (in format <tabname>-<id>)
|
|
122
|
+
// const seperatorIndex = tabhref.indexOf('-');
|
|
123
|
+
//
|
|
124
|
+
// if (seperatorIndex !== -1) {
|
|
125
|
+
// const singular = tabhref.substring(0, seperatorIndex);
|
|
126
|
+
// const plural = singular + 's';
|
|
127
|
+
//
|
|
128
|
+
// this.activateTab(plural);
|
|
129
|
+
// }
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Hash code.
|
|
135
|
+
*/
|
|
136
|
+
async hashCode(text: string): Promise<string> {
|
|
137
|
+
const msgBuffer = new TextEncoder().encode(text);
|
|
138
|
+
const hashBuffer = await globalThis.crypto.subtle.digest("SHA-256", msgBuffer);
|
|
139
|
+
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
140
|
+
return hashArray.map(b => b.toString(16).padStart(2, "0")).join("");
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export const ready = useUniDirective('keeptab', {
|
|
145
|
+
mounted(el, { value }) {
|
|
146
|
+
const options: KeepTabOptions = JSON.parse(value || '{}');
|
|
147
|
+
|
|
148
|
+
module(el, 'uni.keeptab', () => new KeepTab(el, options));
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
export interface KeepTabModule {
|
|
153
|
+
KeepTab: typeof KeepTab;
|
|
154
|
+
ready: typeof ready;
|
|
155
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export * from './useCheckboxesMultiSelect';
|
|
2
|
+
export * from './useFieldCascadeSelect';
|
|
3
|
+
export * from './useFieldFileDrag';
|
|
4
|
+
export * from './useFieldFlatpickr';
|
|
5
|
+
export * from './useFieldModalSelect';
|
|
6
|
+
export * from './useFieldModalTree';
|
|
7
|
+
export * from './useFieldRepeatable';
|
|
8
|
+
export * from './useFieldSingleImageDrag';
|
|
9
|
+
export * from './useForm';
|
|
10
|
+
export * from './useGrid';
|
|
11
|
+
export * from './useHttp';
|
|
12
|
+
export * from './useIframeModal';
|
|
13
|
+
export * from './useListDependent';
|
|
14
|
+
export * from './useQueue';
|
|
15
|
+
export * from './useS3Uploader';
|
|
16
|
+
export * from './useShowOn';
|
|
17
|
+
export * from './useStack';
|
|
18
|
+
export * from './useTomSelect';
|
|
19
|
+
export * from './useUIBootstrap5';
|
|
20
|
+
export * from './useUniDirective';
|
|
21
|
+
export * from './useValidation';
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { CheckboxesMultiSelect } from '../module/checkboxes-multi-select';
|
|
2
|
+
import type { Nullable } from '../types';
|
|
3
|
+
|
|
4
|
+
export async function useCheckboxesMultiSelect(): Promise<any>;
|
|
5
|
+
|
|
6
|
+
export async function useCheckboxesMultiSelect(
|
|
7
|
+
selector?: Nullable<string | HTMLElement>,
|
|
8
|
+
options?: Record<string, any>
|
|
9
|
+
): Promise<CheckboxesMultiSelect>;
|
|
10
|
+
|
|
11
|
+
export async function useCheckboxesMultiSelect(
|
|
12
|
+
selector?: Nullable<string | HTMLElement>,
|
|
13
|
+
options: Record<string, any> = {}
|
|
14
|
+
): Promise<any> {
|
|
15
|
+
const m = await import('../module/checkboxes-multi-select');
|
|
16
|
+
|
|
17
|
+
if (selector) {
|
|
18
|
+
m.CheckboxesMultiSelect.handle(selector, options);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return m;
|
|
22
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { UnicornFormElement } from '../module/form';
|
|
2
|
+
import { selectOne, module } from '../service';
|
|
3
|
+
|
|
4
|
+
let formElement: typeof UnicornFormElement;
|
|
5
|
+
|
|
6
|
+
export async function useFormAsync(): Promise<UnicornFormElement>;
|
|
7
|
+
export async function useFormAsync(ele?: string | Element, options?: Record<string, any>): Promise<UnicornFormElement | null>;
|
|
8
|
+
export async function useFormAsync(ele?: string | Element, options: Record<string, any> = {}): Promise<UnicornFormElement | null> {
|
|
9
|
+
const { UnicornFormElement } = await import('../module/form');
|
|
10
|
+
|
|
11
|
+
formElement ??= UnicornFormElement;
|
|
12
|
+
|
|
13
|
+
return useForm(ele, options);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function useForm(): UnicornFormElement;
|
|
17
|
+
export function useForm(ele?: string | Element, options?: Record<string, any>): UnicornFormElement | null;
|
|
18
|
+
export function useForm(ele?: string | Element, options: Record<string, any> = {}): UnicornFormElement | null {
|
|
19
|
+
if (ele == null) {
|
|
20
|
+
return new formElement(undefined, undefined, options);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const selector = typeof ele === 'string' ? ele : undefined;
|
|
24
|
+
const el = selectOne<HTMLFormElement>(ele as string);
|
|
25
|
+
|
|
26
|
+
if (!el) {
|
|
27
|
+
throw new Error(`Form element of: ${selector} not found.`);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return module(
|
|
31
|
+
el,
|
|
32
|
+
'unicorn.form',
|
|
33
|
+
() => new formElement(selector, el, options)
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export async function useFormComponent(ele?: string | Element, options: Record<string, any> = {}) {
|
|
38
|
+
const form = await useFormAsync(ele, options);
|
|
39
|
+
|
|
40
|
+
await form?.initComponent();
|
|
41
|
+
|
|
42
|
+
return form;
|
|
43
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { UnicornGridElement } from '../module/grid';
|
|
2
|
+
import { useForm, useFormAsync } from './useForm';
|
|
3
|
+
import { selectOne, module } from '../service';
|
|
4
|
+
|
|
5
|
+
let gridElement: typeof UnicornGridElement;
|
|
6
|
+
|
|
7
|
+
export async function useGridAsync(
|
|
8
|
+
ele?: string | HTMLElement,
|
|
9
|
+
options: Record<string, any> | undefined = {}
|
|
10
|
+
): Promise<UnicornGridElement | null> {
|
|
11
|
+
await useFormAsync();
|
|
12
|
+
|
|
13
|
+
const { UnicornGridElement } = await import('../module/grid');
|
|
14
|
+
|
|
15
|
+
gridElement ??= UnicornGridElement;
|
|
16
|
+
|
|
17
|
+
if (!ele) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return useGrid(ele, options);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function useGrid(
|
|
25
|
+
ele: string | HTMLElement,
|
|
26
|
+
options: Record<string, any> | undefined = {}
|
|
27
|
+
): UnicornGridElement | null {
|
|
28
|
+
const selector = typeof ele === 'string' ? ele : '';
|
|
29
|
+
const element = selectOne(ele);
|
|
30
|
+
|
|
31
|
+
if (!element) {
|
|
32
|
+
throw new Error('Element is empty');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const form = useForm(selector || element);
|
|
36
|
+
|
|
37
|
+
if (!form) {
|
|
38
|
+
throw new Error('UnicornGrid is depends on UnicornForm');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return module(
|
|
42
|
+
element,
|
|
43
|
+
'grid.plugin',
|
|
44
|
+
() => new gridElement(selector, element, form, options)
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export async function useGridComponent(
|
|
49
|
+
ele: string | HTMLElement,
|
|
50
|
+
options: Record<string, any> | undefined = {}
|
|
51
|
+
): Promise<UnicornGridElement | null> {
|
|
52
|
+
const grid = await useGridAsync(ele, options);
|
|
53
|
+
|
|
54
|
+
await grid?.initComponent();
|
|
55
|
+
|
|
56
|
+
return grid;
|
|
57
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { UnicornHttpClient } from '../module/http-client';
|
|
2
|
+
import type { AxiosInstance, CreateAxiosDefaults } from 'axios';
|
|
3
|
+
|
|
4
|
+
export async function useHttpClient(config?: CreateAxiosDefaults | AxiosInstance): Promise<UnicornHttpClient> {
|
|
5
|
+
const { createHttpClient } = await import('../module/http-client');
|
|
6
|
+
|
|
7
|
+
return createHttpClient(config as CreateAxiosDefaults | undefined);
|
|
8
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { ListDependent, ListDependentModule, ListDependentOptions } from '../module/list-dependent';
|
|
2
|
+
import { Nullable } from '../types';
|
|
3
|
+
|
|
4
|
+
export async function useListDependent(): Promise<ListDependentModule>;
|
|
5
|
+
export async function useListDependent(
|
|
6
|
+
element: string | HTMLSelectElement,
|
|
7
|
+
dependent?: Nullable<string | HTMLSelectElement>,
|
|
8
|
+
options?: Partial<ListDependentOptions>
|
|
9
|
+
): Promise<ListDependent>;
|
|
10
|
+
export async function useListDependent(
|
|
11
|
+
element?: Nullable<string | HTMLSelectElement>,
|
|
12
|
+
dependent?: Nullable<string | HTMLSelectElement>,
|
|
13
|
+
options: Partial<ListDependentOptions> = {}
|
|
14
|
+
): Promise<any> {
|
|
15
|
+
const module = await import('../module/list-dependent');
|
|
16
|
+
|
|
17
|
+
await module.ready;
|
|
18
|
+
|
|
19
|
+
if (element) {
|
|
20
|
+
const { ListDependent } = module;
|
|
21
|
+
|
|
22
|
+
return ListDependent.handle(element, dependent ?? undefined, options);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return module;
|
|
26
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Dictionary } from '../types';
|
|
2
|
+
import { TaskQueue, queue } from '@lyrasoft/ts-toolkit/generic';
|
|
3
|
+
|
|
4
|
+
const queues: Dictionary<TaskQueue> = {};
|
|
5
|
+
|
|
6
|
+
export function useQueue(name: string = 'default', maxRunning = 1): TaskQueue {
|
|
7
|
+
return queues[name] ??= createQueue(maxRunning);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function createQueue(maxRunning = 1): TaskQueue {
|
|
11
|
+
return queue(maxRunning);
|
|
12
|
+
}
|
|
13
|
+
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import {
|
|
2
|
+
S3MultipartUploader,
|
|
3
|
+
S3MultipartUploaderModule,
|
|
4
|
+
S3MultipartUploaderOptions
|
|
5
|
+
} from '../module/s3-multipart-uploader';
|
|
6
|
+
import type { S3Uploader, S3UploaderGlobalOptions, S3UploaderModule } from '../module/s3-uploader';
|
|
7
|
+
|
|
8
|
+
export async function useS3Uploader(): Promise<S3UploaderModule>;
|
|
9
|
+
export async function useS3Uploader(name: string, options?: Partial<S3UploaderGlobalOptions>): Promise<S3Uploader>;
|
|
10
|
+
export async function useS3Uploader(name?: string, options: Partial<S3UploaderGlobalOptions> = {}): Promise<any> {
|
|
11
|
+
const module = await import('../module/s3-uploader');
|
|
12
|
+
|
|
13
|
+
if (!name) {
|
|
14
|
+
return module;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const { get } = module;
|
|
18
|
+
|
|
19
|
+
return get(name, options);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export async function useS3MultipartUploader(): Promise<S3MultipartUploaderModule>;
|
|
23
|
+
export async function useS3MultipartUploader(options: Partial<S3MultipartUploaderOptions>): Promise<S3MultipartUploader>;
|
|
24
|
+
export async function useS3MultipartUploader(options?: Partial<S3MultipartUploaderOptions>): Promise<any> {
|
|
25
|
+
const module = await import('../module/s3-multipart-uploader');
|
|
26
|
+
|
|
27
|
+
if (options != null) {
|
|
28
|
+
return new module.S3MultipartUploader(options);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return module;
|
|
32
|
+
}
|