lupine.components 1.1.13 → 1.1.15
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 +3 -3
- package/package.json +42 -42
- package/src/components/action-sheet.tsx +419 -419
- package/src/components/button-push-animation.tsx +147 -138
- package/src/components/button.tsx +55 -55
- package/src/components/desktop-footer.tsx +17 -17
- package/src/components/desktop-header.tsx +52 -52
- package/src/components/drag-refresh.tsx +129 -129
- package/src/components/editable-label.tsx +83 -83
- package/src/components/float-window.tsx +233 -233
- package/src/components/grid.tsx +18 -18
- package/src/components/html-load.tsx +41 -41
- package/src/components/html-var.tsx +81 -81
- package/src/components/index.ts +43 -44
- package/src/components/input-with-title.tsx +24 -24
- package/src/components/link-item.tsx +13 -13
- package/src/components/link-list.tsx +62 -62
- package/src/components/menu-bar.tsx +219 -219
- package/src/components/menu-item-props.tsx +13 -13
- package/src/components/menu-sidebar.tsx +325 -318
- package/src/components/message-box.tsx +44 -44
- package/src/components/meta-data.tsx +36 -36
- package/src/components/meta-description.tsx +12 -12
- package/src/components/mobile-components/icon-menu-item-props.ts +6 -6
- package/src/components/mobile-components/index.ts +8 -9
- package/src/components/mobile-components/mobile-footer-menu.tsx +95 -95
- package/src/components/mobile-components/mobile-header-component.tsx +101 -101
- package/src/components/mobile-components/mobile-header-title-icon.tsx +109 -101
- package/src/components/mobile-components/mobile-header-with-back.tsx +127 -117
- package/src/components/mobile-components/mobile-side-menu.tsx +154 -154
- package/src/components/mobile-components/mobile-top-sys-icon.tsx +18 -18
- package/src/components/mobile-components/mobile-top-sys-menu.tsx +62 -62
- package/src/components/modal.tsx +33 -33
- package/src/components/notice-message.tsx +118 -118
- package/src/components/page-title.tsx +6 -6
- package/src/components/paging-link.tsx +175 -175
- package/src/components/panel.tsx +21 -21
- package/src/components/popup-menu.tsx +289 -289
- package/src/components/progress.tsx +91 -91
- package/src/components/radio-label-component.tsx +36 -36
- package/src/components/redirect.tsx +19 -19
- package/src/components/resizable-splitter.tsx +128 -128
- package/src/components/select-angle-component.tsx +127 -127
- package/src/components/select-with-title.tsx +37 -37
- package/src/components/slide-tab-component.tsx +144 -149
- package/src/components/spinner.tsx +106 -100
- package/src/components/stars-component.tsx +66 -66
- package/src/components/svg.tsx +24 -24
- package/src/components/tabs.tsx +279 -279
- package/src/components/text-glow.tsx +37 -37
- package/src/components/text-scale.tsx +42 -42
- package/src/components/text-wave.tsx +55 -55
- package/src/components/theme-selector.tsx +28 -28
- package/src/components/toggle-base.tsx +285 -269
- package/src/components/toggle-switch.tsx +160 -160
- package/src/frames/index.ts +3 -3
- package/src/frames/responsive-frame.tsx +83 -83
- package/src/frames/slider-frame.tsx +111 -111
- package/src/frames/top-frame.tsx +30 -30
- package/src/index.ts +5 -5
- package/src/lib/back-action-helper.ts +54 -54
- package/src/lib/base62.ts +23 -23
- package/src/lib/blob-utils.ts +23 -23
- package/src/lib/calculate-text-width.ts +13 -13
- package/src/lib/date-utils.ts +317 -317
- package/src/lib/deep-merge.ts +37 -37
- package/src/lib/document-ready.ts +34 -34
- package/src/lib/dom-utils.ts +32 -32
- package/src/lib/download-file.ts +118 -118
- package/src/lib/download-link.ts +12 -12
- package/src/lib/download-stream.ts +19 -19
- package/src/lib/drag-util.ts +118 -118
- package/src/lib/dynamical-load.ts +134 -134
- package/src/lib/encode-html.ts +27 -27
- package/src/lib/find-parent-tag.ts +8 -8
- package/src/lib/format-bytes.ts +11 -11
- package/src/lib/index.ts +24 -24
- package/src/lib/lite-dom.ts +225 -225
- package/src/lib/message-hub.ts +103 -104
- package/src/lib/observable.ts +188 -188
- package/src/lib/path-utils.ts +42 -42
- package/src/lib/promise-timeout.ts +1 -1
- package/src/lib/simple-storage.ts +40 -40
- package/src/lib/stop-propagation.ts +7 -7
- package/src/lib/upload-file.ts +101 -101
- package/src/styles/base-themes.ts +17 -17
- package/src/styles/dark-themes.ts +99 -99
- package/src/styles/index.ts +5 -5
- package/src/styles/light-themes.ts +106 -106
- package/src/styles/media-query.ts +93 -93
- package/src/styles/shared-themes.ts +57 -57
- package/tsconfig.json +113 -113
package/src/lib/observable.ts
CHANGED
|
@@ -1,188 +1,188 @@
|
|
|
1
|
-
// inspired by rxjs
|
|
2
|
-
|
|
3
|
-
export class Subscription {
|
|
4
|
-
private _unsubscribe;
|
|
5
|
-
constructor(unsubscribe: () => void) {
|
|
6
|
-
this._unsubscribe = unsubscribe;
|
|
7
|
-
}
|
|
8
|
-
unsubscribe(): void {
|
|
9
|
-
if (this._unsubscribe) {
|
|
10
|
-
this._unsubscribe();
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export class Observable<T> {
|
|
16
|
-
constructor() {}
|
|
17
|
-
subscribe(next?: (value: T) => void, error?: (error: any) => void, complete?: () => void): Subscription {
|
|
18
|
-
throw new Error('subscribe is not implemented');
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export class Subject<T> extends Observable<T> {
|
|
23
|
-
private observers: {
|
|
24
|
-
next?: (value: T) => void;
|
|
25
|
-
error?: (error: any) => void;
|
|
26
|
-
complete?: () => void;
|
|
27
|
-
}[] = [];
|
|
28
|
-
private isStopped = false;
|
|
29
|
-
private _hasError = false;
|
|
30
|
-
private passLastMsgWhenSubscribe;
|
|
31
|
-
private lastSaved: { [key: string]: T } = {};
|
|
32
|
-
|
|
33
|
-
constructor(passLastMsgWhenSubscribe = false) {
|
|
34
|
-
super();
|
|
35
|
-
this.passLastMsgWhenSubscribe = passLastMsgWhenSubscribe;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
next(value?: T) {
|
|
39
|
-
if (this.isStopped) {
|
|
40
|
-
throw new Error('Subject is closed');
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const len = this.observers.length;
|
|
44
|
-
const copy = this.observers.slice();
|
|
45
|
-
for (let i = 0; i < len; i++) {
|
|
46
|
-
const item = copy[i].next;
|
|
47
|
-
if (typeof item !== 'undefined' && typeof value !== 'undefined') {
|
|
48
|
-
item(value);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
if (this.passLastMsgWhenSubscribe) {
|
|
52
|
-
if (typeof value !== 'undefined') {
|
|
53
|
-
this.lastSaved['value'] = value;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
error(err: any) {
|
|
59
|
-
if (this.isStopped) {
|
|
60
|
-
throw new Error('Subject is closed');
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
this._hasError = true;
|
|
64
|
-
this.isStopped = true;
|
|
65
|
-
const len = this.observers.length;
|
|
66
|
-
const copy = this.observers.slice();
|
|
67
|
-
for (let i = 0; i < len; i++) {
|
|
68
|
-
const item = copy[i].error;
|
|
69
|
-
if (typeof item !== 'undefined' && typeof err !== 'undefined') {
|
|
70
|
-
item(err);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
this.observers.length = 0;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
complete() {
|
|
77
|
-
if (this.isStopped) {
|
|
78
|
-
throw new Error('Subject is closed');
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
this.isStopped = true;
|
|
82
|
-
const copy = this.observers.slice();
|
|
83
|
-
const len = copy.length;
|
|
84
|
-
for (let i = 0; i < len; i++) {
|
|
85
|
-
const item = copy[i].complete;
|
|
86
|
-
if (typeof item !== 'undefined') {
|
|
87
|
-
item();
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
if (this.observers.length != len) {
|
|
91
|
-
console.warn(`Subscribe count changed from ${len} to ${this.observers.length}`);
|
|
92
|
-
}
|
|
93
|
-
this.observers.length = 0;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
hasError() {
|
|
97
|
-
return this._hasError;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
private unsubscribe(observer: {}) {
|
|
101
|
-
const index = this.observers.findIndex((item) => item === observer);
|
|
102
|
-
if (index > -1) {
|
|
103
|
-
this.observers.splice(index, 1);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
subscribe(next?: (value: T) => void, error?: (error: any) => void, complete?: () => void): Subscription {
|
|
108
|
-
if (this.isStopped) {
|
|
109
|
-
throw new Error('Subject is stopped');
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
const observer = {
|
|
113
|
-
next,
|
|
114
|
-
error,
|
|
115
|
-
complete,
|
|
116
|
-
};
|
|
117
|
-
this.observers.push(observer);
|
|
118
|
-
if (this.passLastMsgWhenSubscribe) {
|
|
119
|
-
if (typeof observer.next !== 'undefined' && typeof this.lastSaved['value'] !== 'undefined') {
|
|
120
|
-
observer.next(this.lastSaved['value']);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
const ret = new Subscription(() => {
|
|
124
|
-
this.unsubscribe(observer);
|
|
125
|
-
});
|
|
126
|
-
return ret;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
asObservable(): Observable<T> {
|
|
130
|
-
return this as Observable<T>;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// /*[TEST-START]*/
|
|
135
|
-
// function TEST_sample() {
|
|
136
|
-
// const flag = new Subject(true);
|
|
137
|
-
// const observable1 = flag.asObservable();
|
|
138
|
-
// const unsubscribeA = observable1.subscribe(
|
|
139
|
-
// (next) => {
|
|
140
|
-
// console.log('A', next);
|
|
141
|
-
// },
|
|
142
|
-
// (error) => {
|
|
143
|
-
// console.log('A error:', error);
|
|
144
|
-
// }
|
|
145
|
-
// );
|
|
146
|
-
// const unsubscribeB = observable1.subscribe(
|
|
147
|
-
// (next) => {
|
|
148
|
-
// console.log('B', next);
|
|
149
|
-
// },
|
|
150
|
-
// (error) => {
|
|
151
|
-
// console.log('B error:', error);
|
|
152
|
-
// }
|
|
153
|
-
// );
|
|
154
|
-
|
|
155
|
-
// flag.next('test 1');
|
|
156
|
-
// unsubscribeA.unsubscribe();
|
|
157
|
-
// flag.next('test 2');
|
|
158
|
-
// flag.error('error 1');
|
|
159
|
-
// }
|
|
160
|
-
// TEST_sample();
|
|
161
|
-
/*[TEST-END]*/
|
|
162
|
-
|
|
163
|
-
// const flag: BehaviorSubject<Date>;
|
|
164
|
-
// getFlag(): Observable<Date> {
|
|
165
|
-
// return this.flag.asObservable();
|
|
166
|
-
// }
|
|
167
|
-
// setFlag(flag) {
|
|
168
|
-
// this.flag.next(flag);
|
|
169
|
-
// }
|
|
170
|
-
|
|
171
|
-
// getAll(): Observable<string[]> {
|
|
172
|
-
// this.labelsSubject = new ReplaySubject(1);
|
|
173
|
-
// this.http.get().subscribe(result => {
|
|
174
|
-
// this.labelsSubject.next(result);
|
|
175
|
-
// });
|
|
176
|
-
|
|
177
|
-
// return new Observable<string[]>(observer => {
|
|
178
|
-
// this.labelsSubject.subscribe(result => {
|
|
179
|
-
// observer.next(result);
|
|
180
|
-
// observer.complete();
|
|
181
|
-
// }, error => {
|
|
182
|
-
// observer.error(error);
|
|
183
|
-
// });
|
|
184
|
-
// });
|
|
185
|
-
// }
|
|
186
|
-
|
|
187
|
-
// getAll().subscribe(labels => labels.push(res));
|
|
188
|
-
// sub.unsubscribe()
|
|
1
|
+
// inspired by rxjs
|
|
2
|
+
|
|
3
|
+
export class Subscription {
|
|
4
|
+
private _unsubscribe;
|
|
5
|
+
constructor(unsubscribe: () => void) {
|
|
6
|
+
this._unsubscribe = unsubscribe;
|
|
7
|
+
}
|
|
8
|
+
unsubscribe(): void {
|
|
9
|
+
if (this._unsubscribe) {
|
|
10
|
+
this._unsubscribe();
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export class Observable<T> {
|
|
16
|
+
constructor() {}
|
|
17
|
+
subscribe(next?: (value: T) => void, error?: (error: any) => void, complete?: () => void): Subscription {
|
|
18
|
+
throw new Error('subscribe is not implemented');
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export class Subject<T> extends Observable<T> {
|
|
23
|
+
private observers: {
|
|
24
|
+
next?: (value: T) => void;
|
|
25
|
+
error?: (error: any) => void;
|
|
26
|
+
complete?: () => void;
|
|
27
|
+
}[] = [];
|
|
28
|
+
private isStopped = false;
|
|
29
|
+
private _hasError = false;
|
|
30
|
+
private passLastMsgWhenSubscribe;
|
|
31
|
+
private lastSaved: { [key: string]: T } = {};
|
|
32
|
+
|
|
33
|
+
constructor(passLastMsgWhenSubscribe = false) {
|
|
34
|
+
super();
|
|
35
|
+
this.passLastMsgWhenSubscribe = passLastMsgWhenSubscribe;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
next(value?: T) {
|
|
39
|
+
if (this.isStopped) {
|
|
40
|
+
throw new Error('Subject is closed');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const len = this.observers.length;
|
|
44
|
+
const copy = this.observers.slice();
|
|
45
|
+
for (let i = 0; i < len; i++) {
|
|
46
|
+
const item = copy[i].next;
|
|
47
|
+
if (typeof item !== 'undefined' && typeof value !== 'undefined') {
|
|
48
|
+
item(value);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (this.passLastMsgWhenSubscribe) {
|
|
52
|
+
if (typeof value !== 'undefined') {
|
|
53
|
+
this.lastSaved['value'] = value;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
error(err: any) {
|
|
59
|
+
if (this.isStopped) {
|
|
60
|
+
throw new Error('Subject is closed');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
this._hasError = true;
|
|
64
|
+
this.isStopped = true;
|
|
65
|
+
const len = this.observers.length;
|
|
66
|
+
const copy = this.observers.slice();
|
|
67
|
+
for (let i = 0; i < len; i++) {
|
|
68
|
+
const item = copy[i].error;
|
|
69
|
+
if (typeof item !== 'undefined' && typeof err !== 'undefined') {
|
|
70
|
+
item(err);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
this.observers.length = 0;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
complete() {
|
|
77
|
+
if (this.isStopped) {
|
|
78
|
+
throw new Error('Subject is closed');
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
this.isStopped = true;
|
|
82
|
+
const copy = this.observers.slice();
|
|
83
|
+
const len = copy.length;
|
|
84
|
+
for (let i = 0; i < len; i++) {
|
|
85
|
+
const item = copy[i].complete;
|
|
86
|
+
if (typeof item !== 'undefined') {
|
|
87
|
+
item();
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (this.observers.length != len) {
|
|
91
|
+
console.warn(`Subscribe count changed from ${len} to ${this.observers.length}`);
|
|
92
|
+
}
|
|
93
|
+
this.observers.length = 0;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
hasError() {
|
|
97
|
+
return this._hasError;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
private unsubscribe(observer: {}) {
|
|
101
|
+
const index = this.observers.findIndex((item) => item === observer);
|
|
102
|
+
if (index > -1) {
|
|
103
|
+
this.observers.splice(index, 1);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
subscribe(next?: (value: T) => void, error?: (error: any) => void, complete?: () => void): Subscription {
|
|
108
|
+
if (this.isStopped) {
|
|
109
|
+
throw new Error('Subject is stopped');
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const observer = {
|
|
113
|
+
next,
|
|
114
|
+
error,
|
|
115
|
+
complete,
|
|
116
|
+
};
|
|
117
|
+
this.observers.push(observer);
|
|
118
|
+
if (this.passLastMsgWhenSubscribe) {
|
|
119
|
+
if (typeof observer.next !== 'undefined' && typeof this.lastSaved['value'] !== 'undefined') {
|
|
120
|
+
observer.next(this.lastSaved['value']);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
const ret = new Subscription(() => {
|
|
124
|
+
this.unsubscribe(observer);
|
|
125
|
+
});
|
|
126
|
+
return ret;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
asObservable(): Observable<T> {
|
|
130
|
+
return this as Observable<T>;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// /*[TEST-START]*/
|
|
135
|
+
// function TEST_sample() {
|
|
136
|
+
// const flag = new Subject(true);
|
|
137
|
+
// const observable1 = flag.asObservable();
|
|
138
|
+
// const unsubscribeA = observable1.subscribe(
|
|
139
|
+
// (next) => {
|
|
140
|
+
// console.log('A', next);
|
|
141
|
+
// },
|
|
142
|
+
// (error) => {
|
|
143
|
+
// console.log('A error:', error);
|
|
144
|
+
// }
|
|
145
|
+
// );
|
|
146
|
+
// const unsubscribeB = observable1.subscribe(
|
|
147
|
+
// (next) => {
|
|
148
|
+
// console.log('B', next);
|
|
149
|
+
// },
|
|
150
|
+
// (error) => {
|
|
151
|
+
// console.log('B error:', error);
|
|
152
|
+
// }
|
|
153
|
+
// );
|
|
154
|
+
|
|
155
|
+
// flag.next('test 1');
|
|
156
|
+
// unsubscribeA.unsubscribe();
|
|
157
|
+
// flag.next('test 2');
|
|
158
|
+
// flag.error('error 1');
|
|
159
|
+
// }
|
|
160
|
+
// TEST_sample();
|
|
161
|
+
/*[TEST-END]*/
|
|
162
|
+
|
|
163
|
+
// const flag: BehaviorSubject<Date>;
|
|
164
|
+
// getFlag(): Observable<Date> {
|
|
165
|
+
// return this.flag.asObservable();
|
|
166
|
+
// }
|
|
167
|
+
// setFlag(flag) {
|
|
168
|
+
// this.flag.next(flag);
|
|
169
|
+
// }
|
|
170
|
+
|
|
171
|
+
// getAll(): Observable<string[]> {
|
|
172
|
+
// this.labelsSubject = new ReplaySubject(1);
|
|
173
|
+
// this.http.get().subscribe(result => {
|
|
174
|
+
// this.labelsSubject.next(result);
|
|
175
|
+
// });
|
|
176
|
+
|
|
177
|
+
// return new Observable<string[]>(observer => {
|
|
178
|
+
// this.labelsSubject.subscribe(result => {
|
|
179
|
+
// observer.next(result);
|
|
180
|
+
// observer.complete();
|
|
181
|
+
// }, error => {
|
|
182
|
+
// observer.error(error);
|
|
183
|
+
// });
|
|
184
|
+
// });
|
|
185
|
+
// }
|
|
186
|
+
|
|
187
|
+
// getAll().subscribe(labels => labels.push(res));
|
|
188
|
+
// sub.unsubscribe()
|
package/src/lib/path-utils.ts
CHANGED
|
@@ -1,42 +1,42 @@
|
|
|
1
|
-
export const pathUtils = {
|
|
2
|
-
join(...parts: string[]): string {
|
|
3
|
-
let joined = parts.filter(Boolean).join('/');
|
|
4
|
-
joined = joined.replace(/\/+/g, '/'); // merge duplicate slashes
|
|
5
|
-
const isAbsolute = parts[0]?.startsWith('/');
|
|
6
|
-
return isAbsolute ? '/' + joined.replace(/^\/+/, '') : joined.replace(/^\/+/, '');
|
|
7
|
-
},
|
|
8
|
-
|
|
9
|
-
dirname(p: string): string {
|
|
10
|
-
if (!p) return '.';
|
|
11
|
-
p = p.replace(/\/+$/, '');
|
|
12
|
-
const idx = p.lastIndexOf('/');
|
|
13
|
-
if (idx === -1) return '.';
|
|
14
|
-
if (idx === 0) return '/';
|
|
15
|
-
return p.slice(0, idx);
|
|
16
|
-
},
|
|
17
|
-
|
|
18
|
-
// get filename, remove ext if exists
|
|
19
|
-
basename(p: string, ext?: string): string {
|
|
20
|
-
if (!p) return '';
|
|
21
|
-
p = p.replace(/\/+$/, '');
|
|
22
|
-
const idx = p.lastIndexOf('/');
|
|
23
|
-
let base = idx === -1 ? p : p.slice(idx + 1);
|
|
24
|
-
if (!ext) {
|
|
25
|
-
const lastPot = p.lastIndexOf('.');
|
|
26
|
-
if (lastPot >= 0) {
|
|
27
|
-
base = base.slice(0, lastPot);
|
|
28
|
-
}
|
|
29
|
-
} else if (ext && base.endsWith(ext)) {
|
|
30
|
-
base = base.slice(0, -ext.length);
|
|
31
|
-
}
|
|
32
|
-
return base;
|
|
33
|
-
},
|
|
34
|
-
|
|
35
|
-
// .hidden's ext is empty (Node.js behavior)
|
|
36
|
-
extname(p: string): string {
|
|
37
|
-
if (!p) return '';
|
|
38
|
-
const base = pathUtils.basename(p);
|
|
39
|
-
const idx = base.lastIndexOf('.');
|
|
40
|
-
return idx > 0 ? base.slice(idx) : '';
|
|
41
|
-
},
|
|
42
|
-
};
|
|
1
|
+
export const pathUtils = {
|
|
2
|
+
join(...parts: string[]): string {
|
|
3
|
+
let joined = parts.filter(Boolean).join('/');
|
|
4
|
+
joined = joined.replace(/\/+/g, '/'); // merge duplicate slashes
|
|
5
|
+
const isAbsolute = parts[0]?.startsWith('/');
|
|
6
|
+
return isAbsolute ? '/' + joined.replace(/^\/+/, '') : joined.replace(/^\/+/, '');
|
|
7
|
+
},
|
|
8
|
+
|
|
9
|
+
dirname(p: string): string {
|
|
10
|
+
if (!p) return '.';
|
|
11
|
+
p = p.replace(/\/+$/, '');
|
|
12
|
+
const idx = p.lastIndexOf('/');
|
|
13
|
+
if (idx === -1) return '.';
|
|
14
|
+
if (idx === 0) return '/';
|
|
15
|
+
return p.slice(0, idx);
|
|
16
|
+
},
|
|
17
|
+
|
|
18
|
+
// get filename, remove ext if exists
|
|
19
|
+
basename(p: string, ext?: string): string {
|
|
20
|
+
if (!p) return '';
|
|
21
|
+
p = p.replace(/\/+$/, '');
|
|
22
|
+
const idx = p.lastIndexOf('/');
|
|
23
|
+
let base = idx === -1 ? p : p.slice(idx + 1);
|
|
24
|
+
if (!ext) {
|
|
25
|
+
const lastPot = p.lastIndexOf('.');
|
|
26
|
+
if (lastPot >= 0) {
|
|
27
|
+
base = base.slice(0, lastPot);
|
|
28
|
+
}
|
|
29
|
+
} else if (ext && base.endsWith(ext)) {
|
|
30
|
+
base = base.slice(0, -ext.length);
|
|
31
|
+
}
|
|
32
|
+
return base;
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
// .hidden's ext is empty (Node.js behavior)
|
|
36
|
+
extname(p: string): string {
|
|
37
|
+
if (!p) return '';
|
|
38
|
+
const base = pathUtils.basename(p);
|
|
39
|
+
const idx = base.lastIndexOf('.');
|
|
40
|
+
return idx > 0 ? base.slice(idx) : '';
|
|
41
|
+
},
|
|
42
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const promiseTimeout = (delayMs: number) => new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
1
|
+
export const promiseTimeout = (delayMs: number) => new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
@@ -1,40 +1,40 @@
|
|
|
1
|
-
// Server side has the exactly same class
|
|
2
|
-
export class SimpleStorage {
|
|
3
|
-
private settings: { [key: string]: string } = {};
|
|
4
|
-
|
|
5
|
-
constructor(settings: { [key: string]: string }) {
|
|
6
|
-
this.settings = settings;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
contains(key: string): boolean {
|
|
10
|
-
return key in this.settings;
|
|
11
|
-
}
|
|
12
|
-
set(key: string, value: string) {
|
|
13
|
-
return (this.settings[key] = value);
|
|
14
|
-
}
|
|
15
|
-
get(key: string, defaultValue: string): string {
|
|
16
|
-
return key in this.settings ? this.settings[key] : defaultValue;
|
|
17
|
-
}
|
|
18
|
-
getInt(key: string, defaultValue: number): number {
|
|
19
|
-
if (key in this.settings) {
|
|
20
|
-
const i = parseInt(this.settings[key]);
|
|
21
|
-
if (!isNaN(i)) {
|
|
22
|
-
return i;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
return defaultValue;
|
|
26
|
-
}
|
|
27
|
-
getBoolean(key: string, defaultValue: boolean): boolean {
|
|
28
|
-
return key in this.settings
|
|
29
|
-
? this.settings[key] === '1' || this.settings[key].toLowerCase() === 'true'
|
|
30
|
-
: defaultValue;
|
|
31
|
-
}
|
|
32
|
-
getJson(key: string, defaultValue: object): object {
|
|
33
|
-
if (key in this.settings) {
|
|
34
|
-
try {
|
|
35
|
-
return JSON.parse(this.settings[key]);
|
|
36
|
-
} catch (error) {}
|
|
37
|
-
}
|
|
38
|
-
return defaultValue;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
1
|
+
// Server side has the exactly same class
|
|
2
|
+
export class SimpleStorage {
|
|
3
|
+
private settings: { [key: string]: string } = {};
|
|
4
|
+
|
|
5
|
+
constructor(settings: { [key: string]: string }) {
|
|
6
|
+
this.settings = settings;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
contains(key: string): boolean {
|
|
10
|
+
return key in this.settings;
|
|
11
|
+
}
|
|
12
|
+
set(key: string, value: string) {
|
|
13
|
+
return (this.settings[key] = value);
|
|
14
|
+
}
|
|
15
|
+
get(key: string, defaultValue: string): string {
|
|
16
|
+
return key in this.settings ? this.settings[key] : defaultValue;
|
|
17
|
+
}
|
|
18
|
+
getInt(key: string, defaultValue: number): number {
|
|
19
|
+
if (key in this.settings) {
|
|
20
|
+
const i = parseInt(this.settings[key]);
|
|
21
|
+
if (!isNaN(i)) {
|
|
22
|
+
return i;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return defaultValue;
|
|
26
|
+
}
|
|
27
|
+
getBoolean(key: string, defaultValue: boolean): boolean {
|
|
28
|
+
return key in this.settings
|
|
29
|
+
? this.settings[key] === '1' || this.settings[key].toLowerCase() === 'true'
|
|
30
|
+
: defaultValue;
|
|
31
|
+
}
|
|
32
|
+
getJson(key: string, defaultValue: object): object {
|
|
33
|
+
if (key in this.settings) {
|
|
34
|
+
try {
|
|
35
|
+
return JSON.parse(this.settings[key]);
|
|
36
|
+
} catch (error) {}
|
|
37
|
+
}
|
|
38
|
+
return defaultValue;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export const stopPropagation = (event: any) => {
|
|
2
|
-
if (!event) return;
|
|
3
|
-
if (event.stopPropagation) event.stopPropagation();
|
|
4
|
-
if (event.preventDefault) event.preventDefault();
|
|
5
|
-
event.cancelBubble = true;
|
|
6
|
-
event.returnValue = false;
|
|
7
|
-
};
|
|
1
|
+
export const stopPropagation = (event: any) => {
|
|
2
|
+
if (!event) return;
|
|
3
|
+
if (event.stopPropagation) event.stopPropagation();
|
|
4
|
+
if (event.preventDefault) event.preventDefault();
|
|
5
|
+
event.cancelBubble = true;
|
|
6
|
+
event.returnValue = false;
|
|
7
|
+
};
|