@windwalker-io/unicorn-next 0.1.12 → 0.1.14
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/dist/chunks/field-modal-select.js +87 -23
- package/dist/chunks/field-modal-select.js.map +1 -1
- package/dist/chunks/form.js +8 -2
- package/dist/chunks/form.js.map +1 -1
- package/dist/chunks/keep-tab.js +3 -0
- package/dist/chunks/keep-tab.js.map +1 -1
- package/dist/chunks/s3-multipart-uploader.js +29 -10
- package/dist/chunks/s3-multipart-uploader.js.map +1 -1
- package/dist/chunks/s3-uploader.js +1 -0
- package/dist/chunks/s3-uploader.js.map +1 -1
- package/dist/chunks/tinymce.js +13 -3
- package/dist/chunks/tinymce.js.map +1 -1
- package/dist/chunks/unicorn.js +83 -38
- package/dist/chunks/unicorn.js.map +1 -1
- package/dist/chunks/validation.js +32 -15
- package/dist/chunks/validation.js.map +1 -1
- package/dist/index.d.ts +51 -24
- package/dist/unicorn.js +15 -14
- package/package.json +2 -2
- package/src/bootstrap/keep-tab.ts +4 -0
- package/src/composable/useForm.ts +36 -6
- package/src/module/field-modal-select.ts +121 -30
- package/src/module/form.ts +9 -2
- package/src/module/s3-multipart-uploader.ts +46 -14
- package/src/module/s3-uploader.ts +2 -0
- package/src/module/tinymce.ts +20 -5
- package/src/module/validation.ts +42 -17
- package/src/service/dom.ts +32 -14
- package/src/service/loader.ts +37 -17
- package/src/service/ui.ts +1 -0
package/dist/index.d.ts
CHANGED
|
@@ -190,6 +190,10 @@ export declare function createUnicorn(): UnicornApp;
|
|
|
190
190
|
|
|
191
191
|
export declare function createUnicornWithPlugins(): UnicornApp;
|
|
192
192
|
|
|
193
|
+
declare type CssSource = string | (() => Promise<{
|
|
194
|
+
default: string;
|
|
195
|
+
}>);
|
|
196
|
+
|
|
193
197
|
export declare function data(name: string, data?: any): any;
|
|
194
198
|
|
|
195
199
|
export declare function data<T = void, R = [T] extends [void] ? any : T | undefined>(name: string): R;
|
|
@@ -209,7 +213,7 @@ export declare function delegate(wrapper: Element | string, selector: string, ev
|
|
|
209
213
|
|
|
210
214
|
export { deleteConfirm }
|
|
211
215
|
|
|
212
|
-
declare function destroy(selector: string): void;
|
|
216
|
+
declare function destroy(selector: string | HTMLElement): void;
|
|
213
217
|
|
|
214
218
|
declare interface Dictionary<T = any> {
|
|
215
219
|
[key: string]: T;
|
|
@@ -299,15 +303,23 @@ declare interface FileDragOptions {
|
|
|
299
303
|
|
|
300
304
|
export declare function forceArray<T>(item: T | T[]): T[];
|
|
301
305
|
|
|
306
|
+
export declare interface FormSubmitOptions {
|
|
307
|
+
form?: string | Element;
|
|
308
|
+
method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
|
|
309
|
+
url?: string;
|
|
310
|
+
data?: Record<string, any>;
|
|
311
|
+
}
|
|
312
|
+
|
|
302
313
|
export declare interface FormValidationOptions {
|
|
303
314
|
scroll: boolean;
|
|
304
315
|
validatedClass: null;
|
|
305
316
|
fieldSelector: null;
|
|
306
317
|
scrollOffset: number;
|
|
307
318
|
enabled: boolean;
|
|
319
|
+
fieldDefaults?: Partial<Omit<FieldValidationOptions, 'inputOptions' | 'formSelector'>>;
|
|
308
320
|
}
|
|
309
321
|
|
|
310
|
-
declare function get(selector: string, options?: Record<string, any>): Promise<TinymceController>;
|
|
322
|
+
declare function get(selector: string | HTMLElement, options?: Record<string, any>): Promise<TinymceController>;
|
|
311
323
|
|
|
312
324
|
export declare function getBoundedInstance<T = any, E = Element>(selector: E, name: string, callback?: ((el: E) => any)): T;
|
|
313
325
|
|
|
@@ -356,9 +368,9 @@ declare interface IFrameModalOptions {
|
|
|
356
368
|
|
|
357
369
|
export declare function initAlpineComponent(directive: string): Promise<void>;
|
|
358
370
|
|
|
359
|
-
export declare function injectCssToDocument(doc: Document, ...css: (
|
|
371
|
+
export declare function injectCssToDocument(doc: Document, ...css: (CssSource | CSSStyleSheet)[]): Promise<CSSStyleSheet[]>;
|
|
360
372
|
|
|
361
|
-
export declare function injectCssToDocument(...css: (
|
|
373
|
+
export declare function injectCssToDocument(...css: (CssSource | CSSStyleSheet)[]): Promise<CSSStyleSheet[]>;
|
|
362
374
|
|
|
363
375
|
declare type InjectionKey<T = any> = string | symbol | Constructor<T>;
|
|
364
376
|
|
|
@@ -490,7 +502,7 @@ declare interface ModalListenMessagesOptions {
|
|
|
490
502
|
modalSelector: string;
|
|
491
503
|
}
|
|
492
504
|
|
|
493
|
-
declare type ModalSelectCallback = (item: any) => void;
|
|
505
|
+
declare type ModalSelectCallback = (item: any, ...args: any[]) => void;
|
|
494
506
|
|
|
495
507
|
declare interface ModalSelectModule {
|
|
496
508
|
createCallback: typeof createCallback;
|
|
@@ -614,12 +626,13 @@ declare class S3MultipartUploader extends S3MultipartUploader_base {
|
|
|
614
626
|
path: string;
|
|
615
627
|
partNumber: number;
|
|
616
628
|
chunkSize: number;
|
|
629
|
+
abortController?: AbortController;
|
|
617
630
|
onUploadProgress: (e: AxiosProgressEvent) => void;
|
|
618
631
|
}): Promise<{
|
|
619
632
|
blob: Blob;
|
|
620
633
|
etag: string;
|
|
621
634
|
}>;
|
|
622
|
-
protected request<T = Record<string, any>>(action: RouteActions, body: Record<string, any>): Promise<T>;
|
|
635
|
+
protected request<T = Record<string, any>>(action: RouteActions, body: Record<string, any>, config?: Partial<AxiosRequestConfig>): Promise<T>;
|
|
623
636
|
abort(id: string, path: string): Promise<void>;
|
|
624
637
|
updateProgress(loaded: number, total: number, options: S3MultipartUploaderRequestOptions): void;
|
|
625
638
|
resolveRoute(action: RouteActions): Promise<string>;
|
|
@@ -673,6 +686,7 @@ declare interface S3MultipartUploaderRequestOptions {
|
|
|
673
686
|
ContentDisposition?: string;
|
|
674
687
|
ACL?: 'public-read' | 'private' | 'authenticated-read' | 'public-read-write' | string;
|
|
675
688
|
extra?: Record<string, any>;
|
|
689
|
+
abortController?: AbortController;
|
|
676
690
|
}
|
|
677
691
|
|
|
678
692
|
declare class S3Uploader extends S3Uploader_base implements EventAwareInterface {
|
|
@@ -748,6 +762,7 @@ declare interface S3UploaderRequestOptions {
|
|
|
748
762
|
'Content-Type'?: string;
|
|
749
763
|
'Content-Disposition'?: string;
|
|
750
764
|
key?: string;
|
|
765
|
+
signal?: AbortSignal;
|
|
751
766
|
[name: string]: any;
|
|
752
767
|
}
|
|
753
768
|
|
|
@@ -858,6 +873,10 @@ export declare function slideToggle(target: string | HTMLElement, duration?: num
|
|
|
858
873
|
|
|
859
874
|
export declare function slideUp(target: string | HTMLElement, duration?: number): Promise<Animation | void>;
|
|
860
875
|
|
|
876
|
+
declare type Source = string | (() => Promise<{
|
|
877
|
+
default: string;
|
|
878
|
+
}>);
|
|
879
|
+
|
|
861
880
|
declare type StartEventHandler = (fileData: FormData) => void;
|
|
862
881
|
|
|
863
882
|
declare type SuccessEventHandler = (url: string, res: S3UploaderResponse) => void;
|
|
@@ -877,6 +896,7 @@ declare class TinymceController {
|
|
|
877
896
|
getValue(): string;
|
|
878
897
|
setValue(text: string): void;
|
|
879
898
|
imageUploadHandler(blobInfo: UploadHandlerParams[0], progress: UploadHandlerParams[1]): Promise<any>;
|
|
899
|
+
destroy(): void;
|
|
880
900
|
}
|
|
881
901
|
|
|
882
902
|
declare interface TinymceModule {
|
|
@@ -948,10 +968,11 @@ export declare class UnicornAssetUri {
|
|
|
948
968
|
declare class UnicornFieldValidation {
|
|
949
969
|
protected el: HTMLElement;
|
|
950
970
|
$input: InputElements | undefined;
|
|
951
|
-
options: FieldValidationOptions
|
|
971
|
+
options: Partial<FieldValidationOptions>;
|
|
952
972
|
static is: string;
|
|
953
973
|
constructor(el: HTMLElement, options?: Partial<FieldValidationOptions>);
|
|
954
|
-
|
|
974
|
+
setOptions(options: Partial<FieldValidationOptions>): this;
|
|
975
|
+
get mergedOptions(): FieldValidationOptions;
|
|
955
976
|
get $form(): HTMLFormElement;
|
|
956
977
|
get errorSelector(): string;
|
|
957
978
|
get selector(): string;
|
|
@@ -976,6 +997,7 @@ declare class UnicornFieldValidation {
|
|
|
976
997
|
*/
|
|
977
998
|
updateValidClass(valid: Boolean): void;
|
|
978
999
|
getFormValidation(element?: Nullable<HTMLFormElement>): UnicornFormValidation | null;
|
|
1000
|
+
get globalOptions(): Partial<FieldValidationOptions>;
|
|
979
1001
|
getValidator(name: string): [Validator, Record<string, any>] | null;
|
|
980
1002
|
handleCustomResult(result: boolean | string | undefined, validator?: Nullable<Validator>): boolean;
|
|
981
1003
|
handleAsyncCustomResult(result: boolean, validator?: Nullable<Validator>): boolean;
|
|
@@ -1030,6 +1052,7 @@ declare class UnicornFormElement {
|
|
|
1030
1052
|
* Make a DELETE request.
|
|
1031
1053
|
*/
|
|
1032
1054
|
delete(url?: Nullable<string>, data?: Nullable<Record<string, any>>): boolean;
|
|
1055
|
+
destroy(): void;
|
|
1033
1056
|
/**
|
|
1034
1057
|
* @see https://stackoverflow.com/a/53739792
|
|
1035
1058
|
*
|
|
@@ -1058,6 +1081,7 @@ declare class UnicornFormValidation {
|
|
|
1058
1081
|
prepareFields(inputs: HTMLElement[]): Promise<void>;
|
|
1059
1082
|
prepareFieldWrapper(input: HTMLElement): HTMLElement | null;
|
|
1060
1083
|
findFields(containsPresets?: boolean): HTMLElement[];
|
|
1084
|
+
getFieldComponents(containsPresets?: boolean): UnicornFieldValidation[];
|
|
1061
1085
|
getFieldComponent(input: HTMLElement): UnicornFieldValidation | null;
|
|
1062
1086
|
validateAll(fields?: Nullable<HTMLElement[]>): boolean;
|
|
1063
1087
|
validateAllAsync(fields?: Nullable<HTMLElement[]>): Promise<boolean>;
|
|
@@ -1272,9 +1296,9 @@ export declare function useCheckboxesMultiSelect(selector?: Nullable<string | HT
|
|
|
1272
1296
|
*/
|
|
1273
1297
|
export declare function useColorPicker(selector?: Nullable<string | HTMLElement | NodeListOf<HTMLElement>>, options?: Partial<SpectrumOptions>): Promise<any>;
|
|
1274
1298
|
|
|
1275
|
-
export declare function useCssImport(...hrefs:
|
|
1299
|
+
export declare function useCssImport(...hrefs: Source[]): Promise<CSSStyleSheet[]>;
|
|
1276
1300
|
|
|
1277
|
-
export declare function useCssIncludes(...hrefs:
|
|
1301
|
+
export declare function useCssIncludes(...hrefs: Source[]): Promise<void[]>;
|
|
1278
1302
|
|
|
1279
1303
|
export declare function useDisableIfStackNotEmpty(buttonSelector?: string, stackName?: string): void;
|
|
1280
1304
|
|
|
@@ -1308,6 +1332,8 @@ export declare function useFormAsync(ele?: string | Element, options?: Record<st
|
|
|
1308
1332
|
|
|
1309
1333
|
export declare function useFormComponent(ele?: string | Element, options?: Record<string, any>): Promise<UnicornFormElement | null>;
|
|
1310
1334
|
|
|
1335
|
+
export declare function useFormSubmit(options?: FormSubmitOptions): Promise<boolean>;
|
|
1336
|
+
|
|
1311
1337
|
export declare function useFormValidation(): Promise<ValidationModule>;
|
|
1312
1338
|
|
|
1313
1339
|
export declare function useFormValidation(selector: string | Element): Promise<UnicornFormValidation | null>;
|
|
@@ -1367,7 +1393,7 @@ export declare function useS3Uploader(): Promise<S3UploaderModule>;
|
|
|
1367
1393
|
|
|
1368
1394
|
export declare function useS3Uploader(name: string, options?: Partial<S3UploaderGlobalOptions>): Promise<S3Uploader>;
|
|
1369
1395
|
|
|
1370
|
-
export declare function useScriptImport(src:
|
|
1396
|
+
export declare function useScriptImport(src: Source, attrs?: Record<string, string>): Promise<void>;
|
|
1371
1397
|
|
|
1372
1398
|
export declare function useSeriesImport(...src: any[]): Promise<any>;
|
|
1373
1399
|
|
|
@@ -1424,6 +1450,7 @@ export declare function useUnicornPhpAdapter(app?: UnicornApp): {
|
|
|
1424
1450
|
modalTree: typeof useFieldModalTree;
|
|
1425
1451
|
multiUploader: typeof useFieldMultiUploader;
|
|
1426
1452
|
tomSelect: typeof useTomSelect;
|
|
1453
|
+
listDependent: typeof useListDependent;
|
|
1427
1454
|
bootstrap: {
|
|
1428
1455
|
tooltip: typeof useBs5Tooltip;
|
|
1429
1456
|
buttonRadio: {
|
|
@@ -1480,10 +1507,9 @@ export declare function watchAttributes<T extends HTMLElement>(el: T, callback?:
|
|
|
1480
1507
|
export { }
|
|
1481
1508
|
|
|
1482
1509
|
|
|
1483
|
-
declare
|
|
1484
|
-
interface
|
|
1485
|
-
|
|
1486
|
-
$ui: typeof methods;
|
|
1510
|
+
declare global {
|
|
1511
|
+
interface Node {
|
|
1512
|
+
__unicorn?: any;
|
|
1487
1513
|
}
|
|
1488
1514
|
}
|
|
1489
1515
|
|
|
@@ -1496,16 +1522,13 @@ declare global {
|
|
|
1496
1522
|
}
|
|
1497
1523
|
|
|
1498
1524
|
|
|
1499
|
-
declare
|
|
1500
|
-
interface
|
|
1501
|
-
|
|
1525
|
+
declare module '@windwalker-io/unicorn-next' {
|
|
1526
|
+
interface UnicornApp {
|
|
1527
|
+
/** @deprecated Only for code generator use. */
|
|
1528
|
+
$ui: typeof methods;
|
|
1502
1529
|
}
|
|
1503
1530
|
}
|
|
1504
1531
|
|
|
1505
|
-
declare global {
|
|
1506
|
-
var S: any;
|
|
1507
|
-
}
|
|
1508
|
-
|
|
1509
1532
|
|
|
1510
1533
|
declare module 'axios' {
|
|
1511
1534
|
interface AxiosRequestConfig {
|
|
@@ -1517,9 +1540,8 @@ declare module 'axios' {
|
|
|
1517
1540
|
}
|
|
1518
1541
|
}
|
|
1519
1542
|
|
|
1520
|
-
|
|
1521
1543
|
declare global {
|
|
1522
|
-
var
|
|
1544
|
+
var S: any;
|
|
1523
1545
|
}
|
|
1524
1546
|
|
|
1525
1547
|
|
|
@@ -1528,3 +1550,8 @@ declare global {
|
|
|
1528
1550
|
bootstrap: typeof bootstrap;
|
|
1529
1551
|
}
|
|
1530
1552
|
}
|
|
1553
|
+
|
|
1554
|
+
|
|
1555
|
+
declare global {
|
|
1556
|
+
var tinymce: TinyMCE;
|
|
1557
|
+
}
|
package/dist/unicorn.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { ax, ag, aL,
|
|
1
|
+
import { ax, ag, aL, ba, aK, aH, _, h, aO, aM, aJ, b, J, I, aQ, d, e, ah, b4, am, an, ac, D, C, ae, aC, t, T, S, ad, x, y, A, aN, U, B, f, a8, i, aA, l, N, z, ay, aP, p, a6, aq, au, av, aw, at, c, r, w, v, M, G, F, s, al, Q, R, P, E, L, aj, K, aF, q, a0, $, a1, Y, V, ab, aE, X, W, aR, aS, aT, aU, aV, aW, aX, j, a4, a2, aY, aZ, g, k, a5, a3, a_, u, a$, aa, ap, Z, aB, as, b0, ar, n, b2, b1, ai, aD, b3, m, o, b5, b6, O, aG, b7, ak, a, ao, b9, aI, b8, az, a9 } from "./chunks/unicorn.js";
|
|
2
2
|
export {
|
|
3
3
|
ax as AttributeMutationObserver,
|
|
4
4
|
ag as EventMixin,
|
|
5
5
|
aL as UnicornAssetUri,
|
|
6
|
-
|
|
6
|
+
ba as UnicornPhpAdapter,
|
|
7
7
|
aK as UnicornSystemUri,
|
|
8
8
|
aH as UnicornUI,
|
|
9
9
|
_ as __,
|
|
@@ -18,7 +18,7 @@ export {
|
|
|
18
18
|
d as clearMessages,
|
|
19
19
|
e as clearNotifies,
|
|
20
20
|
ah as createQueue,
|
|
21
|
-
|
|
21
|
+
b4 as createStack,
|
|
22
22
|
am as createUnicorn,
|
|
23
23
|
an as createUnicornWithPlugins,
|
|
24
24
|
ac as data,
|
|
@@ -90,39 +90,40 @@ export {
|
|
|
90
90
|
a4 as useForm,
|
|
91
91
|
a2 as useFormAsync,
|
|
92
92
|
aY as useFormComponent,
|
|
93
|
+
aZ as useFormSubmit,
|
|
93
94
|
g as useFormValidation,
|
|
94
95
|
k as useFormValidationInstance,
|
|
95
96
|
a5 as useGrid,
|
|
96
97
|
a3 as useGridAsync,
|
|
97
|
-
|
|
98
|
+
a_ as useGridComponent,
|
|
98
99
|
u as useHttpClient,
|
|
99
|
-
|
|
100
|
+
a$ as useIframeModal,
|
|
100
101
|
aa as useImport,
|
|
101
102
|
ap as useInject,
|
|
102
103
|
Z as useKeepAlive,
|
|
103
104
|
aB as useLang,
|
|
104
105
|
as as useLegacy,
|
|
105
|
-
|
|
106
|
+
b0 as useListDependent,
|
|
106
107
|
ar as useMacro,
|
|
107
108
|
n as useQueue,
|
|
108
|
-
|
|
109
|
-
|
|
109
|
+
b2 as useS3MultipartUploader,
|
|
110
|
+
b1 as useS3Uploader,
|
|
110
111
|
ai as useScriptImport,
|
|
111
112
|
aD as useSeriesImport,
|
|
112
|
-
|
|
113
|
+
b3 as useShowOn,
|
|
113
114
|
m as useStack,
|
|
114
115
|
o as useSystemUri,
|
|
115
|
-
|
|
116
|
-
|
|
116
|
+
b5 as useTinymce,
|
|
117
|
+
b6 as useTinymceHook,
|
|
117
118
|
O as useTomSelect,
|
|
118
119
|
aG as useUI,
|
|
119
|
-
|
|
120
|
+
b7 as useUIBootstrap5,
|
|
120
121
|
ak as useUITheme,
|
|
121
122
|
a as useUniDirective,
|
|
122
123
|
ao as useUnicorn,
|
|
123
|
-
|
|
124
|
+
b9 as useUnicornPhpAdapter,
|
|
124
125
|
aI as useVueComponentField,
|
|
125
|
-
|
|
126
|
+
b8 as useWebDirective,
|
|
126
127
|
az as wait,
|
|
127
128
|
a9 as watchAttributes
|
|
128
129
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@windwalker-io/unicorn-next",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.14",
|
|
4
4
|
"description": "Unicorn framework js library",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"typings": "dist/index.d.ts",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
]
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
|
-
"@lyrasoft/ts-toolkit": "^0.2.
|
|
66
|
+
"@lyrasoft/ts-toolkit": "^0.2.4",
|
|
67
67
|
"@rubenbimmel/alpine-class-component": "^0.0.4",
|
|
68
68
|
"@types/alpinejs": "^3",
|
|
69
69
|
"@types/bootstrap": "^5",
|
|
@@ -88,6 +88,10 @@ export class KeepTab {
|
|
|
88
88
|
const tabTrigger = this.findTabButtonByHref(href);
|
|
89
89
|
|
|
90
90
|
if (tabTrigger) {
|
|
91
|
+
if (tabTrigger?.getAttribute('disabled') != null || tabTrigger.classList.contains('disabled')) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
91
95
|
Tab.getOrCreateInstance(tabTrigger).show();
|
|
92
96
|
}
|
|
93
97
|
}
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import type { UnicornFormElement } from '../module/form';
|
|
2
|
-
import {
|
|
2
|
+
import { module, selectOne } from '../service';
|
|
3
|
+
import { Nullable } from '../types';
|
|
3
4
|
|
|
4
5
|
let formElement: typeof UnicornFormElement;
|
|
5
6
|
|
|
6
7
|
export async function useFormAsync(): Promise<UnicornFormElement>;
|
|
7
|
-
export async function useFormAsync(ele?: string | Element,
|
|
8
|
-
|
|
8
|
+
export async function useFormAsync(ele?: string | Element,
|
|
9
|
+
options?: Record<string, any>): Promise<UnicornFormElement | null>;
|
|
10
|
+
export async function useFormAsync(ele?: string | Element,
|
|
11
|
+
options: Record<string, any> = {}): Promise<UnicornFormElement | null> {
|
|
9
12
|
const { UnicornFormElement } = await import('../module/form');
|
|
10
13
|
|
|
11
14
|
formElement ??= UnicornFormElement;
|
|
@@ -16,15 +19,26 @@ export async function useFormAsync(ele?: string | Element, options: Record<strin
|
|
|
16
19
|
export function useForm(): UnicornFormElement;
|
|
17
20
|
export function useForm(ele?: string | Element, options?: Record<string, any>): UnicornFormElement | null;
|
|
18
21
|
export function useForm(ele?: string | Element, options: Record<string, any> = {}): UnicornFormElement | null {
|
|
22
|
+
if (!formElement) {
|
|
23
|
+
throw new Error('Form module is not loaded. Please use useFormAsync() to load the module before using useForm().');
|
|
24
|
+
}
|
|
25
|
+
|
|
19
26
|
if (ele == null) {
|
|
20
27
|
return new formElement(undefined, undefined, options);
|
|
21
28
|
}
|
|
22
29
|
|
|
23
|
-
|
|
24
|
-
|
|
30
|
+
let selector: string | undefined = undefined;
|
|
31
|
+
let el: HTMLFormElement | undefined = undefined;
|
|
32
|
+
|
|
33
|
+
if (typeof ele === 'string') {
|
|
34
|
+
selector = ele;
|
|
35
|
+
el = selectOne<HTMLFormElement>(ele) ?? undefined;
|
|
36
|
+
} else {
|
|
37
|
+
el = ele as HTMLFormElement;
|
|
38
|
+
}
|
|
25
39
|
|
|
26
40
|
if (!el) {
|
|
27
|
-
|
|
41
|
+
return new formElement(selector, el, options);
|
|
28
42
|
}
|
|
29
43
|
|
|
30
44
|
return module(
|
|
@@ -41,3 +55,19 @@ export async function useFormComponent(ele?: string | Element, options: Record<s
|
|
|
41
55
|
|
|
42
56
|
return form;
|
|
43
57
|
}
|
|
58
|
+
|
|
59
|
+
export interface FormSubmitOptions {
|
|
60
|
+
form?: string | Element;
|
|
61
|
+
method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
|
|
62
|
+
url?: string;
|
|
63
|
+
data?: Record<string, any>;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export async function useFormSubmit(options: FormSubmitOptions = {}) {
|
|
67
|
+
const form = (await useFormAsync(options.form)) as UnicornFormElement;
|
|
68
|
+
|
|
69
|
+
// fun type should be method of form
|
|
70
|
+
const func = (options.method?.toLowerCase() || 'post') as 'get' | 'post' | 'put' | 'delete' | 'patch';
|
|
71
|
+
|
|
72
|
+
return form[func](options.url, options.data);
|
|
73
|
+
}
|
|
@@ -1,26 +1,50 @@
|
|
|
1
|
-
import type { IFrameModalElement } from './iframe-modal';
|
|
2
|
-
import { data } from '../data';
|
|
3
|
-
import { __, highlight, html, selectOne, slideUp } from '../service';
|
|
4
1
|
import { template } from 'lodash-es';
|
|
2
|
+
import { data } from '../data';
|
|
3
|
+
import { __, highlight, html, selectOne, simpleAlert, slideUp } from '../service';
|
|
4
|
+
import type { IFrameModalElement } from './iframe-modal';
|
|
5
5
|
|
|
6
|
-
export type ModalSelectCallback = (item: any) => void;
|
|
6
|
+
export type ModalSelectCallback = (item: any, ...args: any[]) => void;
|
|
7
7
|
|
|
8
|
-
export function createCallback(
|
|
8
|
+
export function createCallback(
|
|
9
|
+
type: 'list' | 'single',
|
|
10
|
+
selector: string,
|
|
11
|
+
modalSelector: string
|
|
12
|
+
): ModalSelectCallback {
|
|
9
13
|
switch (type) {
|
|
10
|
-
// case 'tag':
|
|
11
|
-
// return () => {
|
|
12
|
-
//
|
|
13
|
-
// };
|
|
14
14
|
case 'list':
|
|
15
15
|
return (item: any) => {
|
|
16
16
|
const modalList = document.querySelector(selector) as any as ModalListSelectElement;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
17
|
+
const checked = item.checked;
|
|
18
|
+
|
|
19
|
+
if (checked === undefined) {
|
|
20
|
+
// Single selection mode
|
|
21
|
+
if (!modalList.querySelector(`[data-value="${item.value}"]`)) {
|
|
22
|
+
modalList.appendItem(item, true);
|
|
23
|
+
|
|
24
|
+
selectOne<IFrameModalElement>(modalSelector)?.close();
|
|
25
|
+
} else {
|
|
26
|
+
simpleAlert(__('unicorn.field.modal.already.selected'));
|
|
27
|
+
}
|
|
28
|
+
} else if (checked) {
|
|
29
|
+
// Multiple selection mode - add item
|
|
30
|
+
try {
|
|
31
|
+
modalList.appendIfNotExists(item, true);
|
|
32
|
+
} catch (e) {
|
|
33
|
+
window.postMessage({
|
|
34
|
+
task: 'remove-row',
|
|
35
|
+
value: item,
|
|
36
|
+
id: item.instanceId
|
|
37
|
+
});
|
|
38
|
+
simpleAlert((e as Error).message);
|
|
39
|
+
} finally {
|
|
40
|
+
modalList.updateSelected();
|
|
41
|
+
}
|
|
42
|
+
} else if (!checked) {
|
|
43
|
+
// Multiple selection mode - remove item
|
|
44
|
+
modalList.removeItem(item).then(() => {
|
|
45
|
+
console.log(modalList.items);
|
|
46
|
+
modalList.updateSelected();
|
|
47
|
+
});
|
|
24
48
|
}
|
|
25
49
|
};
|
|
26
50
|
|
|
@@ -55,12 +79,14 @@ interface ModalListOptions {
|
|
|
55
79
|
sortable: boolean;
|
|
56
80
|
dataKey: string;
|
|
57
81
|
max: number;
|
|
82
|
+
multiCheck?: boolean;
|
|
58
83
|
}
|
|
59
84
|
|
|
60
85
|
export interface ReceivedItem {
|
|
61
86
|
value: string | number;
|
|
62
87
|
title?: string;
|
|
63
88
|
image?: string;
|
|
89
|
+
|
|
64
90
|
[key: string]: any;
|
|
65
91
|
}
|
|
66
92
|
|
|
@@ -69,11 +95,16 @@ class ModalListSelectElement extends HTMLElement {
|
|
|
69
95
|
|
|
70
96
|
itemTemplate!: ReturnType<typeof template>;
|
|
71
97
|
options!: ModalListOptions;
|
|
98
|
+
isMultiCheck = false;
|
|
72
99
|
|
|
73
100
|
get listContainer() {
|
|
74
101
|
return this.querySelector<HTMLDivElement>('[data-role=list-container]')!;
|
|
75
102
|
}
|
|
76
103
|
|
|
104
|
+
get selectButton() {
|
|
105
|
+
return this.querySelector<HTMLAnchorElement>('[data-role=select]')!;
|
|
106
|
+
}
|
|
107
|
+
|
|
77
108
|
get modal() {
|
|
78
109
|
return document.querySelector<IFrameModalElement>(this.options.modalSelector);
|
|
79
110
|
}
|
|
@@ -82,6 +113,10 @@ class ModalListSelectElement extends HTMLElement {
|
|
|
82
113
|
return Array.from(this.listContainer.querySelectorAll<HTMLElement>('[data-value]'));
|
|
83
114
|
}
|
|
84
115
|
|
|
116
|
+
get count(): number {
|
|
117
|
+
return this.items.length;
|
|
118
|
+
}
|
|
119
|
+
|
|
85
120
|
connectedCallback() {
|
|
86
121
|
this.options = JSON.parse(this.getAttribute('options') || '{}');
|
|
87
122
|
this.itemTemplate = template(document.querySelector(this.options.itemTemplate)!.innerHTML);
|
|
@@ -98,18 +133,23 @@ class ModalListSelectElement extends HTMLElement {
|
|
|
98
133
|
});
|
|
99
134
|
}
|
|
100
135
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
136
|
+
this.selectButton.addEventListener('click', (e) => {
|
|
137
|
+
try {
|
|
138
|
+
this.open(e);
|
|
139
|
+
} catch (e) {
|
|
140
|
+
simpleAlert((e as Error).message);
|
|
141
|
+
}
|
|
104
142
|
});
|
|
105
143
|
|
|
106
144
|
this.querySelector('[data-role=clear]')?.addEventListener('click', () => {
|
|
107
145
|
this.removeAll();
|
|
108
146
|
});
|
|
109
147
|
|
|
110
|
-
selectButton.style.pointerEvents = '';
|
|
148
|
+
this.selectButton.style.pointerEvents = '';
|
|
111
149
|
|
|
112
150
|
this.render();
|
|
151
|
+
|
|
152
|
+
this.enableMultiCheck(this.options.multiCheck || false);
|
|
113
153
|
}
|
|
114
154
|
|
|
115
155
|
render() {
|
|
@@ -121,6 +161,12 @@ class ModalListSelectElement extends HTMLElement {
|
|
|
121
161
|
}
|
|
122
162
|
|
|
123
163
|
appendItem(item: ReceivedItem, highlights = false) {
|
|
164
|
+
const max = this.options.max;
|
|
165
|
+
|
|
166
|
+
if (max && this.count >= max) {
|
|
167
|
+
throw new Error(__('unicorn.field.modal.max.selected', max));
|
|
168
|
+
}
|
|
169
|
+
|
|
124
170
|
const itemHtml = html(this.itemTemplate({ item }));
|
|
125
171
|
|
|
126
172
|
itemHtml.dataset.value = String(item.value);
|
|
@@ -134,6 +180,10 @@ class ModalListSelectElement extends HTMLElement {
|
|
|
134
180
|
if (highlights) {
|
|
135
181
|
highlight(itemHtml);
|
|
136
182
|
}
|
|
183
|
+
|
|
184
|
+
if (this.isMultiCheck) {
|
|
185
|
+
this.updateSelected();
|
|
186
|
+
}
|
|
137
187
|
}
|
|
138
188
|
|
|
139
189
|
appendIfNotExists(item: ReceivedItem, highlights = false) {
|
|
@@ -162,7 +212,7 @@ class ModalListSelectElement extends HTMLElement {
|
|
|
162
212
|
return this.items.map((item) => item.dataset.value);
|
|
163
213
|
}
|
|
164
214
|
|
|
165
|
-
removeItem(item: ReceivedItem | string | number) {
|
|
215
|
+
async removeItem(item: ReceivedItem | string | number) {
|
|
166
216
|
if (typeof item === 'object') {
|
|
167
217
|
item = item.value;
|
|
168
218
|
}
|
|
@@ -170,9 +220,13 @@ class ModalListSelectElement extends HTMLElement {
|
|
|
170
220
|
const element = this.listContainer.querySelector<HTMLElement>(`[data-value="${item}"]`);
|
|
171
221
|
|
|
172
222
|
if (element) {
|
|
173
|
-
slideUp(element).then(() => {
|
|
223
|
+
return slideUp(element).then(() => {
|
|
174
224
|
element.remove();
|
|
175
225
|
this.toggleRequired();
|
|
226
|
+
|
|
227
|
+
if (this.isMultiCheck) {
|
|
228
|
+
this.updateSelected();
|
|
229
|
+
}
|
|
176
230
|
});
|
|
177
231
|
}
|
|
178
232
|
}
|
|
@@ -187,6 +241,10 @@ class ModalListSelectElement extends HTMLElement {
|
|
|
187
241
|
await Promise.all(promises);
|
|
188
242
|
|
|
189
243
|
this.toggleRequired();
|
|
244
|
+
|
|
245
|
+
if (this.isMultiCheck) {
|
|
246
|
+
this.updateSelected();
|
|
247
|
+
}
|
|
190
248
|
}
|
|
191
249
|
|
|
192
250
|
toggleRequired() {
|
|
@@ -210,16 +268,34 @@ class ModalListSelectElement extends HTMLElement {
|
|
|
210
268
|
return;
|
|
211
269
|
}
|
|
212
270
|
|
|
213
|
-
if (this.
|
|
214
|
-
|
|
215
|
-
__('unicorn.field.modal.max.selected', max)
|
|
216
|
-
);
|
|
217
|
-
|
|
218
|
-
return;
|
|
271
|
+
if (this.count >= max) {
|
|
272
|
+
throw new Error(__('unicorn.field.modal.max.selected', max));
|
|
219
273
|
}
|
|
220
274
|
|
|
221
275
|
this.modal?.open(target.href, { size: 'modal-xl' });
|
|
222
276
|
}
|
|
277
|
+
|
|
278
|
+
enableMultiCheck(enable = true) {
|
|
279
|
+
this.isMultiCheck = enable;
|
|
280
|
+
|
|
281
|
+
if (enable) {
|
|
282
|
+
this.updateSelected();
|
|
283
|
+
} else {
|
|
284
|
+
this.clearSelected();
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
updateSelected() {
|
|
289
|
+
const url = new URL(this.selectButton.href);
|
|
290
|
+
url.searchParams.set('selected', this.items.map((i) => i.dataset.value).join(','));
|
|
291
|
+
this.selectButton.href = url.toString();
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
clearSelected() {
|
|
295
|
+
const url = new URL(this.selectButton.href);
|
|
296
|
+
url.searchParams.delete('selected');
|
|
297
|
+
this.selectButton.href = url.toString();
|
|
298
|
+
}
|
|
223
299
|
}
|
|
224
300
|
|
|
225
301
|
async function init() {
|
|
@@ -238,8 +314,23 @@ export function listenMessages(options: ModalListenMessagesOptions) {
|
|
|
238
314
|
const callback = createCallback(options.type, options.selector, options.modalSelector);
|
|
239
315
|
|
|
240
316
|
window.addEventListener('message', (e) => {
|
|
241
|
-
if (e.origin === options.origin
|
|
242
|
-
|
|
317
|
+
if (e.origin === options.origin) {
|
|
318
|
+
if (Array.isArray(e.data) && e.data[0] === options.instanceId) {
|
|
319
|
+
callback(e.data[1]);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
if (
|
|
323
|
+
typeof e.data === 'object'
|
|
324
|
+
&& e.data !== null
|
|
325
|
+
&& e.data.id === options.instanceId
|
|
326
|
+
&& e.data.task === 'select-row'
|
|
327
|
+
) {
|
|
328
|
+
const item = e.data.value;
|
|
329
|
+
item.checked = e.data.checked;
|
|
330
|
+
item.instanceId = e.data.id;
|
|
331
|
+
|
|
332
|
+
callback(e.data.value);
|
|
333
|
+
}
|
|
243
334
|
}
|
|
244
335
|
});
|
|
245
336
|
|