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/components/tabs.tsx
CHANGED
|
@@ -1,279 +1,279 @@
|
|
|
1
|
-
import {
|
|
2
|
-
CssProps,
|
|
3
|
-
RefProps,
|
|
4
|
-
VNode,
|
|
5
|
-
bindGlobalStyle,
|
|
6
|
-
domUniqueId,
|
|
7
|
-
getGlobalStylesId,
|
|
8
|
-
mountInnerComponent,
|
|
9
|
-
} from 'lupine.web';
|
|
10
|
-
import { stopPropagation } from '../lib';
|
|
11
|
-
|
|
12
|
-
export type TabsHookProps = {
|
|
13
|
-
updateTitle?: (index: number, title: string) => void;
|
|
14
|
-
updateIndex?: (index: number) => void;
|
|
15
|
-
newPage?: (title: string, page: VNode<any>, index?: number) => Promise<void>;
|
|
16
|
-
removePage?: (index: number) => void;
|
|
17
|
-
// set from outside and called when the active tab index changes
|
|
18
|
-
indexChanged?: (index: number) => void;
|
|
19
|
-
getIndex?: () => number;
|
|
20
|
-
getCount?: () => number;
|
|
21
|
-
findAndActivate?: (title: string) => boolean;
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
export type TabsPageProps = { title: string; page: VNode<any> };
|
|
25
|
-
|
|
26
|
-
export type TabsProps = {
|
|
27
|
-
pages: TabsPageProps[];
|
|
28
|
-
defaultIndex?: number;
|
|
29
|
-
topClassName?: string;
|
|
30
|
-
pagePadding?: string;
|
|
31
|
-
hook?: TabsHookProps;
|
|
32
|
-
};
|
|
33
|
-
// For CSS or query selectors, please pay attention to that Tabs can be nested
|
|
34
|
-
export const Tabs = ({ pages, defaultIndex, topClassName, pagePadding, hook: refUpdate }: TabsProps) => {
|
|
35
|
-
let newIndex = typeof defaultIndex === 'number' ? defaultIndex : 0;
|
|
36
|
-
const clearIndex = () => {
|
|
37
|
-
const header = ref.$(`.&tabs > div > .tab.active`);
|
|
38
|
-
header && header.classList.remove('active');
|
|
39
|
-
const page = ref.$(`.&pages > .page.active`);
|
|
40
|
-
page && page.classList.remove('active');
|
|
41
|
-
};
|
|
42
|
-
const updateIndex = (index: number) => {
|
|
43
|
-
clearIndex();
|
|
44
|
-
const doms = ref.$all(`.&tabs > div > .tab`);
|
|
45
|
-
if (index >= 0 && index < doms.length) {
|
|
46
|
-
doms[index].classList.add('active');
|
|
47
|
-
const pages = ref.$all(`.&pages > .page`);
|
|
48
|
-
pages[index].classList.add('active');
|
|
49
|
-
refUpdate?.indexChanged && refUpdate?.indexChanged(index);
|
|
50
|
-
}
|
|
51
|
-
};
|
|
52
|
-
const removePage = (index: number) => {
|
|
53
|
-
const doms = ref.$all(`.&tabs > div > .tab`);
|
|
54
|
-
if (index >= 0 && index < doms.length) {
|
|
55
|
-
const newIndex = index === doms.length - 1 ? index - 1 : index;
|
|
56
|
-
const isAct = doms[index].classList.contains('active');
|
|
57
|
-
doms[index].parentNode.remove();
|
|
58
|
-
const pages = ref.$all(`.&pages > .page`);
|
|
59
|
-
pages[index].remove();
|
|
60
|
-
|
|
61
|
-
if (isAct) {
|
|
62
|
-
updateIndex(newIndex);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
};
|
|
66
|
-
const removePageFromX = (event: any) => {
|
|
67
|
-
stopPropagation(event);
|
|
68
|
-
|
|
69
|
-
const tab = event.target.parentNode;
|
|
70
|
-
const index = Array.prototype.indexOf.call(tab.parentNode.parentNode.children, tab.parentNode);
|
|
71
|
-
removePage(index);
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
const newPage = async (title: string, page: VNode<any>, index?: number) => {
|
|
75
|
-
const allTabs = ref.$all(`.&tabs > div > .tab`);
|
|
76
|
-
let newPageIndex = allTabs.length;
|
|
77
|
-
if (typeof index === 'number' && index >= 0 && index < allTabs.length) {
|
|
78
|
-
newPageIndex = index;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
clearIndex();
|
|
82
|
-
const newTab2 = createTabHeader(title, ' active');
|
|
83
|
-
const newTab = document.createElement('div');
|
|
84
|
-
|
|
85
|
-
const newPage = document.createElement('div');
|
|
86
|
-
newPage.className = 'page';
|
|
87
|
-
if (newPageIndex === allTabs.length) {
|
|
88
|
-
ref.$(`.&tabs`).appendChild(newTab);
|
|
89
|
-
ref.$(`.&pages`).appendChild(newPage);
|
|
90
|
-
} else {
|
|
91
|
-
ref.$(`.&tabs`).insertBefore(newTab, allTabs[newPageIndex]);
|
|
92
|
-
const pages = ref.$all(`.&pages > .page`);
|
|
93
|
-
ref.$(`.&pages`).insertBefore(newPage, pages[newPageIndex]);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
await mountInnerComponent(newTab, newTab2);
|
|
97
|
-
await mountInnerComponent(newPage, page);
|
|
98
|
-
updateIndex(newPageIndex);
|
|
99
|
-
};
|
|
100
|
-
const createTabHeader = (title: string, className: string) => {
|
|
101
|
-
return (
|
|
102
|
-
<div onClick={onTabClick} class={'tab' + className}>
|
|
103
|
-
{title}
|
|
104
|
-
<span class='modal-close' onClick={removePageFromX}>
|
|
105
|
-
×
|
|
106
|
-
</span>
|
|
107
|
-
</div>
|
|
108
|
-
);
|
|
109
|
-
};
|
|
110
|
-
const onTabClick = (event: any) => {
|
|
111
|
-
stopPropagation(event);
|
|
112
|
-
|
|
113
|
-
const tab = event.target;
|
|
114
|
-
const index = Array.prototype.indexOf.call(tab.parentNode.parentNode.children, tab.parentNode);
|
|
115
|
-
updateIndex(index);
|
|
116
|
-
};
|
|
117
|
-
const flashTitle = (index: number) => {
|
|
118
|
-
const doms = ref.$all(`.&tabs > div > .tab`);
|
|
119
|
-
if (index >= 0 && index < doms.length) {
|
|
120
|
-
doms[index].classList.add('flash');
|
|
121
|
-
setTimeout(() => {
|
|
122
|
-
doms[index].classList.remove('flash');
|
|
123
|
-
}, 1000);
|
|
124
|
-
}
|
|
125
|
-
};
|
|
126
|
-
if (refUpdate) {
|
|
127
|
-
refUpdate.updateTitle = (index: number, title: string) => {
|
|
128
|
-
const doms = ref.$all(`.&tabs > div > .tab`);
|
|
129
|
-
if (index >= 0 && index < doms.length) {
|
|
130
|
-
doms[index].innerHTML = title;
|
|
131
|
-
}
|
|
132
|
-
};
|
|
133
|
-
refUpdate.updateIndex = updateIndex;
|
|
134
|
-
refUpdate.removePage = removePage;
|
|
135
|
-
refUpdate.newPage = newPage;
|
|
136
|
-
refUpdate.getIndex = () => {
|
|
137
|
-
const header = ref.$(`.&tabs > div > .tab.active`);
|
|
138
|
-
return header ? Array.prototype.indexOf.call(header.parentNode.parentNode.children, header.parentNode) : -1;
|
|
139
|
-
};
|
|
140
|
-
refUpdate.getCount = () => {
|
|
141
|
-
const doms = ref.$all(`.&tabs > div > .tab`);
|
|
142
|
-
return doms.length;
|
|
143
|
-
};
|
|
144
|
-
refUpdate.findAndActivate = (title: string) => {
|
|
145
|
-
const doms = ref.$all(`.&tabs > div > .tab`);
|
|
146
|
-
for (let i = 0; i < doms.length; i++) {
|
|
147
|
-
if (doms[i].innerText === title) {
|
|
148
|
-
updateIndex(i);
|
|
149
|
-
flashTitle(i);
|
|
150
|
-
return true;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
return false;
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// pay attention to nest tabs
|
|
158
|
-
const css: CssProps = {
|
|
159
|
-
display: 'flex',
|
|
160
|
-
'flex-direction': 'column',
|
|
161
|
-
width: '100%',
|
|
162
|
-
height: '100%',
|
|
163
|
-
// border: 'solid 1px grey',
|
|
164
|
-
'&:not(:has(.pages .page))': {
|
|
165
|
-
// hide tabs when there is no tabs (not need to show borders)
|
|
166
|
-
display: 'none',
|
|
167
|
-
},
|
|
168
|
-
'> .&tabs': {
|
|
169
|
-
display: 'flex',
|
|
170
|
-
height: 'auto',
|
|
171
|
-
'border-bottom': '1px solid grey',
|
|
172
|
-
'overflow-x': 'auto',
|
|
173
|
-
'overflow-y': 'hidden',
|
|
174
|
-
'scrollbar-width': 'thin',
|
|
175
|
-
'scrollbar-color': '#ababab4d #d5d5d552',
|
|
176
|
-
'> div > .tab': {
|
|
177
|
-
padding: '2px 3px',
|
|
178
|
-
width: 'auto',
|
|
179
|
-
'font-size': 'smaller',
|
|
180
|
-
'text-overflow': 'ellipsis',
|
|
181
|
-
overflow: 'hidden',
|
|
182
|
-
'white-space': 'nowrap',
|
|
183
|
-
margin: '1px 1px 0 1px',
|
|
184
|
-
cursor: 'pointer',
|
|
185
|
-
position: 'relative',
|
|
186
|
-
// transition: 'all 1s',
|
|
187
|
-
'border-top-right-radius': '4px',
|
|
188
|
-
'border-top-left-radius': '4px',
|
|
189
|
-
'border-top': 'solid 1px var(--primary-border-color)',
|
|
190
|
-
'border-left': 'solid 1px var(--primary-border-color)',
|
|
191
|
-
'border-right': 'solid 1px var(--primary-border-color)',
|
|
192
|
-
// 'border-bottom': '2px solid transparent',
|
|
193
|
-
color: 'var(--activatable-color-normal)',
|
|
194
|
-
backgroundColor: 'var(--activatable-bg-color-normal)',
|
|
195
|
-
},
|
|
196
|
-
'> div > .tab:hover': {
|
|
197
|
-
padding: '3px 3px 1px 3px',
|
|
198
|
-
// color: 'var(--activatable-color-hover)',
|
|
199
|
-
// backgroundColor: 'var(--activatable-bg-color-hover)',
|
|
200
|
-
},
|
|
201
|
-
'> div > .tab.flash': {
|
|
202
|
-
backgroundColor: 'red',
|
|
203
|
-
},
|
|
204
|
-
'> div > .active': {
|
|
205
|
-
// 'border-bottom': '2px solid red',
|
|
206
|
-
color: 'var(--activatable-color-selected)',
|
|
207
|
-
backgroundColor: 'var(--activatable-bg-color-selected)',
|
|
208
|
-
marginBottom: '-1px',
|
|
209
|
-
borderBottom: '1px solid #FFFFFF00',
|
|
210
|
-
},
|
|
211
|
-
'> div > .tab > .modal-close': {
|
|
212
|
-
display: 'none',
|
|
213
|
-
float: 'right',
|
|
214
|
-
fontSize: '12px',
|
|
215
|
-
fontWeight: 'bold',
|
|
216
|
-
cursor: 'pointer',
|
|
217
|
-
position: 'absolute',
|
|
218
|
-
top: '-4px',
|
|
219
|
-
right: '1px',
|
|
220
|
-
},
|
|
221
|
-
'> div > .tab:hover > .modal-close': {
|
|
222
|
-
display: 'inline-block',
|
|
223
|
-
color: '#ff0000',
|
|
224
|
-
},
|
|
225
|
-
},
|
|
226
|
-
'> .&pages': {
|
|
227
|
-
display: 'flex',
|
|
228
|
-
flex: '1',
|
|
229
|
-
position: 'relative',
|
|
230
|
-
'> .page': {
|
|
231
|
-
display: 'none',
|
|
232
|
-
position: 'absolute',
|
|
233
|
-
padding: pagePadding || '0px',
|
|
234
|
-
overflow: 'auto',
|
|
235
|
-
width: '100%',
|
|
236
|
-
maxWidth: '100%',
|
|
237
|
-
height: '100%',
|
|
238
|
-
overflowX: 'auto',
|
|
239
|
-
overflowY: 'auto',
|
|
240
|
-
},
|
|
241
|
-
'> .active': {
|
|
242
|
-
display: 'inline-block',
|
|
243
|
-
},
|
|
244
|
-
},
|
|
245
|
-
};
|
|
246
|
-
// we want to put all common styles in the header
|
|
247
|
-
const tabGlobalCssId = getGlobalStylesId(css);
|
|
248
|
-
bindGlobalStyle(tabGlobalCssId, css);
|
|
249
|
-
|
|
250
|
-
const ref: RefProps = {
|
|
251
|
-
globalCssId: tabGlobalCssId,
|
|
252
|
-
};
|
|
253
|
-
|
|
254
|
-
// but we also want to create unique id for the current tab
|
|
255
|
-
const cssTab: CssProps = {
|
|
256
|
-
'&tabs': {
|
|
257
|
-
display: 'flex',
|
|
258
|
-
},
|
|
259
|
-
'&pages': {
|
|
260
|
-
display: 'flex',
|
|
261
|
-
},
|
|
262
|
-
};
|
|
263
|
-
return (
|
|
264
|
-
<div ref={ref} css={cssTab} class={topClassName ? ' ' + topClassName : ''}>
|
|
265
|
-
<div class='&tabs tabs'>
|
|
266
|
-
{pages.map((i, index) => {
|
|
267
|
-
const className = index === newIndex ? ' active' : '';
|
|
268
|
-
return <div>{createTabHeader(i.title, className)}</div>;
|
|
269
|
-
})}
|
|
270
|
-
</div>
|
|
271
|
-
<div class='&pages pages'>
|
|
272
|
-
{pages.map((i, index) => {
|
|
273
|
-
const className = index === newIndex ? ' active' : '';
|
|
274
|
-
return <div class={'page' + className}>{i.page}</div>;
|
|
275
|
-
})}
|
|
276
|
-
</div>
|
|
277
|
-
</div>
|
|
278
|
-
);
|
|
279
|
-
};
|
|
1
|
+
import {
|
|
2
|
+
CssProps,
|
|
3
|
+
RefProps,
|
|
4
|
+
VNode,
|
|
5
|
+
bindGlobalStyle,
|
|
6
|
+
domUniqueId,
|
|
7
|
+
getGlobalStylesId,
|
|
8
|
+
mountInnerComponent,
|
|
9
|
+
} from 'lupine.web';
|
|
10
|
+
import { stopPropagation } from '../lib';
|
|
11
|
+
|
|
12
|
+
export type TabsHookProps = {
|
|
13
|
+
updateTitle?: (index: number, title: string) => void;
|
|
14
|
+
updateIndex?: (index: number) => void;
|
|
15
|
+
newPage?: (title: string, page: VNode<any>, index?: number) => Promise<void>;
|
|
16
|
+
removePage?: (index: number) => void;
|
|
17
|
+
// set from outside and called when the active tab index changes
|
|
18
|
+
indexChanged?: (index: number) => void;
|
|
19
|
+
getIndex?: () => number;
|
|
20
|
+
getCount?: () => number;
|
|
21
|
+
findAndActivate?: (title: string) => boolean;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export type TabsPageProps = { title: string; page: VNode<any> };
|
|
25
|
+
|
|
26
|
+
export type TabsProps = {
|
|
27
|
+
pages: TabsPageProps[];
|
|
28
|
+
defaultIndex?: number;
|
|
29
|
+
topClassName?: string;
|
|
30
|
+
pagePadding?: string;
|
|
31
|
+
hook?: TabsHookProps;
|
|
32
|
+
};
|
|
33
|
+
// For CSS or query selectors, please pay attention to that Tabs can be nested
|
|
34
|
+
export const Tabs = ({ pages, defaultIndex, topClassName, pagePadding, hook: refUpdate }: TabsProps) => {
|
|
35
|
+
let newIndex = typeof defaultIndex === 'number' ? defaultIndex : 0;
|
|
36
|
+
const clearIndex = () => {
|
|
37
|
+
const header = ref.$(`.&tabs > div > .tab.active`);
|
|
38
|
+
header && header.classList.remove('active');
|
|
39
|
+
const page = ref.$(`.&pages > .page.active`);
|
|
40
|
+
page && page.classList.remove('active');
|
|
41
|
+
};
|
|
42
|
+
const updateIndex = (index: number) => {
|
|
43
|
+
clearIndex();
|
|
44
|
+
const doms = ref.$all(`.&tabs > div > .tab`);
|
|
45
|
+
if (index >= 0 && index < doms.length) {
|
|
46
|
+
doms[index].classList.add('active');
|
|
47
|
+
const pages = ref.$all(`.&pages > .page`);
|
|
48
|
+
pages[index].classList.add('active');
|
|
49
|
+
refUpdate?.indexChanged && refUpdate?.indexChanged(index);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
const removePage = (index: number) => {
|
|
53
|
+
const doms = ref.$all(`.&tabs > div > .tab`);
|
|
54
|
+
if (index >= 0 && index < doms.length) {
|
|
55
|
+
const newIndex = index === doms.length - 1 ? index - 1 : index;
|
|
56
|
+
const isAct = doms[index].classList.contains('active');
|
|
57
|
+
doms[index].parentNode.remove();
|
|
58
|
+
const pages = ref.$all(`.&pages > .page`);
|
|
59
|
+
pages[index].remove();
|
|
60
|
+
|
|
61
|
+
if (isAct) {
|
|
62
|
+
updateIndex(newIndex);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
const removePageFromX = (event: any) => {
|
|
67
|
+
stopPropagation(event);
|
|
68
|
+
|
|
69
|
+
const tab = event.target.parentNode;
|
|
70
|
+
const index = Array.prototype.indexOf.call(tab.parentNode.parentNode.children, tab.parentNode);
|
|
71
|
+
removePage(index);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const newPage = async (title: string, page: VNode<any>, index?: number) => {
|
|
75
|
+
const allTabs = ref.$all(`.&tabs > div > .tab`);
|
|
76
|
+
let newPageIndex = allTabs.length;
|
|
77
|
+
if (typeof index === 'number' && index >= 0 && index < allTabs.length) {
|
|
78
|
+
newPageIndex = index;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
clearIndex();
|
|
82
|
+
const newTab2 = createTabHeader(title, ' active');
|
|
83
|
+
const newTab = document.createElement('div');
|
|
84
|
+
|
|
85
|
+
const newPage = document.createElement('div');
|
|
86
|
+
newPage.className = 'page';
|
|
87
|
+
if (newPageIndex === allTabs.length) {
|
|
88
|
+
ref.$(`.&tabs`).appendChild(newTab);
|
|
89
|
+
ref.$(`.&pages`).appendChild(newPage);
|
|
90
|
+
} else {
|
|
91
|
+
ref.$(`.&tabs`).insertBefore(newTab, allTabs[newPageIndex]);
|
|
92
|
+
const pages = ref.$all(`.&pages > .page`);
|
|
93
|
+
ref.$(`.&pages`).insertBefore(newPage, pages[newPageIndex]);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
await mountInnerComponent(newTab, newTab2);
|
|
97
|
+
await mountInnerComponent(newPage, page);
|
|
98
|
+
updateIndex(newPageIndex);
|
|
99
|
+
};
|
|
100
|
+
const createTabHeader = (title: string, className: string) => {
|
|
101
|
+
return (
|
|
102
|
+
<div onClick={onTabClick} class={'tab' + className}>
|
|
103
|
+
{title}
|
|
104
|
+
<span class='modal-close' onClick={removePageFromX}>
|
|
105
|
+
×
|
|
106
|
+
</span>
|
|
107
|
+
</div>
|
|
108
|
+
);
|
|
109
|
+
};
|
|
110
|
+
const onTabClick = (event: any) => {
|
|
111
|
+
stopPropagation(event);
|
|
112
|
+
|
|
113
|
+
const tab = event.target;
|
|
114
|
+
const index = Array.prototype.indexOf.call(tab.parentNode.parentNode.children, tab.parentNode);
|
|
115
|
+
updateIndex(index);
|
|
116
|
+
};
|
|
117
|
+
const flashTitle = (index: number) => {
|
|
118
|
+
const doms = ref.$all(`.&tabs > div > .tab`);
|
|
119
|
+
if (index >= 0 && index < doms.length) {
|
|
120
|
+
doms[index].classList.add('flash');
|
|
121
|
+
setTimeout(() => {
|
|
122
|
+
doms[index].classList.remove('flash');
|
|
123
|
+
}, 1000);
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
if (refUpdate) {
|
|
127
|
+
refUpdate.updateTitle = (index: number, title: string) => {
|
|
128
|
+
const doms = ref.$all(`.&tabs > div > .tab`);
|
|
129
|
+
if (index >= 0 && index < doms.length) {
|
|
130
|
+
doms[index].innerHTML = title;
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
refUpdate.updateIndex = updateIndex;
|
|
134
|
+
refUpdate.removePage = removePage;
|
|
135
|
+
refUpdate.newPage = newPage;
|
|
136
|
+
refUpdate.getIndex = () => {
|
|
137
|
+
const header = ref.$(`.&tabs > div > .tab.active`);
|
|
138
|
+
return header ? Array.prototype.indexOf.call(header.parentNode.parentNode.children, header.parentNode) : -1;
|
|
139
|
+
};
|
|
140
|
+
refUpdate.getCount = () => {
|
|
141
|
+
const doms = ref.$all(`.&tabs > div > .tab`);
|
|
142
|
+
return doms.length;
|
|
143
|
+
};
|
|
144
|
+
refUpdate.findAndActivate = (title: string) => {
|
|
145
|
+
const doms = ref.$all(`.&tabs > div > .tab`);
|
|
146
|
+
for (let i = 0; i < doms.length; i++) {
|
|
147
|
+
if (doms[i].innerText === title) {
|
|
148
|
+
updateIndex(i);
|
|
149
|
+
flashTitle(i);
|
|
150
|
+
return true;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return false;
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// pay attention to nest tabs
|
|
158
|
+
const css: CssProps = {
|
|
159
|
+
display: 'flex',
|
|
160
|
+
'flex-direction': 'column',
|
|
161
|
+
width: '100%',
|
|
162
|
+
height: '100%',
|
|
163
|
+
// border: 'solid 1px grey',
|
|
164
|
+
'&:not(:has(.pages .page))': {
|
|
165
|
+
// hide tabs when there is no tabs (not need to show borders)
|
|
166
|
+
display: 'none',
|
|
167
|
+
},
|
|
168
|
+
'> .&tabs': {
|
|
169
|
+
display: 'flex',
|
|
170
|
+
height: 'auto',
|
|
171
|
+
'border-bottom': '1px solid grey',
|
|
172
|
+
'overflow-x': 'auto',
|
|
173
|
+
'overflow-y': 'hidden',
|
|
174
|
+
'scrollbar-width': 'thin',
|
|
175
|
+
'scrollbar-color': '#ababab4d #d5d5d552',
|
|
176
|
+
'> div > .tab': {
|
|
177
|
+
padding: '2px 3px',
|
|
178
|
+
width: 'auto',
|
|
179
|
+
'font-size': 'smaller',
|
|
180
|
+
'text-overflow': 'ellipsis',
|
|
181
|
+
overflow: 'hidden',
|
|
182
|
+
'white-space': 'nowrap',
|
|
183
|
+
margin: '1px 1px 0 1px',
|
|
184
|
+
cursor: 'pointer',
|
|
185
|
+
position: 'relative',
|
|
186
|
+
// transition: 'all 1s',
|
|
187
|
+
'border-top-right-radius': '4px',
|
|
188
|
+
'border-top-left-radius': '4px',
|
|
189
|
+
'border-top': 'solid 1px var(--primary-border-color)',
|
|
190
|
+
'border-left': 'solid 1px var(--primary-border-color)',
|
|
191
|
+
'border-right': 'solid 1px var(--primary-border-color)',
|
|
192
|
+
// 'border-bottom': '2px solid transparent',
|
|
193
|
+
color: 'var(--activatable-color-normal)',
|
|
194
|
+
backgroundColor: 'var(--activatable-bg-color-normal)',
|
|
195
|
+
},
|
|
196
|
+
'> div > .tab:hover': {
|
|
197
|
+
padding: '3px 3px 1px 3px',
|
|
198
|
+
// color: 'var(--activatable-color-hover)',
|
|
199
|
+
// backgroundColor: 'var(--activatable-bg-color-hover)',
|
|
200
|
+
},
|
|
201
|
+
'> div > .tab.flash': {
|
|
202
|
+
backgroundColor: 'red',
|
|
203
|
+
},
|
|
204
|
+
'> div > .active': {
|
|
205
|
+
// 'border-bottom': '2px solid red',
|
|
206
|
+
color: 'var(--activatable-color-selected)',
|
|
207
|
+
backgroundColor: 'var(--activatable-bg-color-selected)',
|
|
208
|
+
marginBottom: '-1px',
|
|
209
|
+
borderBottom: '1px solid #FFFFFF00',
|
|
210
|
+
},
|
|
211
|
+
'> div > .tab > .modal-close': {
|
|
212
|
+
display: 'none',
|
|
213
|
+
float: 'right',
|
|
214
|
+
fontSize: '12px',
|
|
215
|
+
fontWeight: 'bold',
|
|
216
|
+
cursor: 'pointer',
|
|
217
|
+
position: 'absolute',
|
|
218
|
+
top: '-4px',
|
|
219
|
+
right: '1px',
|
|
220
|
+
},
|
|
221
|
+
'> div > .tab:hover > .modal-close': {
|
|
222
|
+
display: 'inline-block',
|
|
223
|
+
color: '#ff0000',
|
|
224
|
+
},
|
|
225
|
+
},
|
|
226
|
+
'> .&pages': {
|
|
227
|
+
display: 'flex',
|
|
228
|
+
flex: '1',
|
|
229
|
+
position: 'relative',
|
|
230
|
+
'> .page': {
|
|
231
|
+
display: 'none',
|
|
232
|
+
position: 'absolute',
|
|
233
|
+
padding: pagePadding || '0px',
|
|
234
|
+
overflow: 'auto',
|
|
235
|
+
width: '100%',
|
|
236
|
+
maxWidth: '100%',
|
|
237
|
+
height: '100%',
|
|
238
|
+
overflowX: 'auto',
|
|
239
|
+
overflowY: 'auto',
|
|
240
|
+
},
|
|
241
|
+
'> .active': {
|
|
242
|
+
display: 'inline-block',
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
};
|
|
246
|
+
// we want to put all common styles in the header
|
|
247
|
+
const tabGlobalCssId = getGlobalStylesId(css);
|
|
248
|
+
bindGlobalStyle(tabGlobalCssId, css);
|
|
249
|
+
|
|
250
|
+
const ref: RefProps = {
|
|
251
|
+
globalCssId: tabGlobalCssId,
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
// but we also want to create unique id for the current tab
|
|
255
|
+
const cssTab: CssProps = {
|
|
256
|
+
'&tabs': {
|
|
257
|
+
display: 'flex',
|
|
258
|
+
},
|
|
259
|
+
'&pages': {
|
|
260
|
+
display: 'flex',
|
|
261
|
+
},
|
|
262
|
+
};
|
|
263
|
+
return (
|
|
264
|
+
<div ref={ref} css={cssTab} class={topClassName ? ' ' + topClassName : ''}>
|
|
265
|
+
<div class='&tabs tabs'>
|
|
266
|
+
{pages.map((i, index) => {
|
|
267
|
+
const className = index === newIndex ? ' active' : '';
|
|
268
|
+
return <div>{createTabHeader(i.title, className)}</div>;
|
|
269
|
+
})}
|
|
270
|
+
</div>
|
|
271
|
+
<div class='&pages pages'>
|
|
272
|
+
{pages.map((i, index) => {
|
|
273
|
+
const className = index === newIndex ? ' active' : '';
|
|
274
|
+
return <div class={'page' + className}>{i.page}</div>;
|
|
275
|
+
})}
|
|
276
|
+
</div>
|
|
277
|
+
</div>
|
|
278
|
+
);
|
|
279
|
+
};
|
|
@@ -1,37 +1,37 @@
|
|
|
1
|
-
import { bindGlobalStyle, CssProps } from 'lupine.web';
|
|
2
|
-
|
|
3
|
-
export type TextGlowProps = {
|
|
4
|
-
text: string;
|
|
5
|
-
color?: string;
|
|
6
|
-
padding?: string;
|
|
7
|
-
fontSize?: string;
|
|
8
|
-
fontWeight?: string;
|
|
9
|
-
};
|
|
10
|
-
export const TextGlow = (props: TextGlowProps) => {
|
|
11
|
-
const css: CssProps = {
|
|
12
|
-
width: `100%`,
|
|
13
|
-
height: `100%`,
|
|
14
|
-
textAlign: 'center',
|
|
15
|
-
color: props.color || '#22b8ff',
|
|
16
|
-
padding: props.padding || '10px',
|
|
17
|
-
fontSize: props.fontSize || '30px',
|
|
18
|
-
fontWeight: props.fontWeight || '500',
|
|
19
|
-
'.text-glow': {
|
|
20
|
-
animation: 'text-glow-a 1.5s infinite alternate',
|
|
21
|
-
},
|
|
22
|
-
'@keyframes text-glow-a': {
|
|
23
|
-
'0%': {
|
|
24
|
-
textShadow: '0 0 5px #ff005e, 0 0 10px #ff005e, 0 0 20px #ff005e, 0 0 40px #ff005e, 0 0 80px #ff005e',
|
|
25
|
-
},
|
|
26
|
-
'100%': {
|
|
27
|
-
textShadow: '0 0 10px #00d4ff, 0 0 20px #00d4ff, 0 0 40px #00d4ff, 0 0 80px #00d4ff, 0 0 160px #00d4ff',
|
|
28
|
-
},
|
|
29
|
-
},
|
|
30
|
-
};
|
|
31
|
-
bindGlobalStyle('text-glow-top', css);
|
|
32
|
-
return (
|
|
33
|
-
<div class='text-glow-top'>
|
|
34
|
-
<div class='text-glow'>{props.text}</div>
|
|
35
|
-
</div>
|
|
36
|
-
);
|
|
37
|
-
};
|
|
1
|
+
import { bindGlobalStyle, CssProps } from 'lupine.web';
|
|
2
|
+
|
|
3
|
+
export type TextGlowProps = {
|
|
4
|
+
text: string;
|
|
5
|
+
color?: string;
|
|
6
|
+
padding?: string;
|
|
7
|
+
fontSize?: string;
|
|
8
|
+
fontWeight?: string;
|
|
9
|
+
};
|
|
10
|
+
export const TextGlow = (props: TextGlowProps) => {
|
|
11
|
+
const css: CssProps = {
|
|
12
|
+
width: `100%`,
|
|
13
|
+
height: `100%`,
|
|
14
|
+
textAlign: 'center',
|
|
15
|
+
color: props.color || '#22b8ff',
|
|
16
|
+
padding: props.padding || '10px',
|
|
17
|
+
fontSize: props.fontSize || '30px',
|
|
18
|
+
fontWeight: props.fontWeight || '500',
|
|
19
|
+
'.text-glow': {
|
|
20
|
+
animation: 'text-glow-a 1.5s infinite alternate',
|
|
21
|
+
},
|
|
22
|
+
'@keyframes text-glow-a': {
|
|
23
|
+
'0%': {
|
|
24
|
+
textShadow: '0 0 5px #ff005e, 0 0 10px #ff005e, 0 0 20px #ff005e, 0 0 40px #ff005e, 0 0 80px #ff005e',
|
|
25
|
+
},
|
|
26
|
+
'100%': {
|
|
27
|
+
textShadow: '0 0 10px #00d4ff, 0 0 20px #00d4ff, 0 0 40px #00d4ff, 0 0 80px #00d4ff, 0 0 160px #00d4ff',
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
bindGlobalStyle('text-glow-top', css);
|
|
32
|
+
return (
|
|
33
|
+
<div class='text-glow-top'>
|
|
34
|
+
<div class='text-glow'>{props.text}</div>
|
|
35
|
+
</div>
|
|
36
|
+
);
|
|
37
|
+
};
|