kempo 1.0.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/.gitattributes +2 -0
- package/LICENSE +21 -0
- package/README.md +2 -0
- package/dist/components/Card.js +1 -0
- package/dist/components/CodeEditor.js +1 -0
- package/dist/components/Component.js +1 -0
- package/dist/components/Dialog.js +1 -0
- package/dist/components/FocusCapture.js +1 -0
- package/dist/components/Icon.js +1 -0
- package/dist/components/Import.js +1 -0
- package/dist/components/LazyComponent.js +1 -0
- package/dist/components/ReactiveComponent.js +1 -0
- package/dist/components/ReactiveLazyComponent.js +1 -0
- package/dist/components/Resize.js +1 -0
- package/dist/components/Search.js +1 -0
- package/dist/components/ShowMore.js +1 -0
- package/dist/components/SideMenu.js +1 -0
- package/dist/components/Split.js +1 -0
- package/dist/components/Tabs.js +1 -0
- package/dist/components/ThemeSwitcher.js +1 -0
- package/dist/components/Timestamp.js +1 -0
- package/dist/components/WebSnippetEditor.js +1 -0
- package/dist/index.js +1 -0
- package/dist/kempo-hljs.css +1 -0
- package/dist/kempo-styles.css +1 -0
- package/dist/kempo-vars.css +1 -0
- package/dist/kempo.css +1 -0
- package/dist/kempo.js +1 -0
- package/dist/utils/cli.js +1 -0
- package/dist/utils/cookie.js +1 -0
- package/dist/utils/debounce.js +1 -0
- package/dist/utils/drag.js +1 -0
- package/dist/utils/element.js +1 -0
- package/dist/utils/formatTimestamp.js +1 -0
- package/dist/utils/fuzzyMatch.js +1 -0
- package/dist/utils/getPreferredTheme.js +1 -0
- package/dist/utils/loadCss.js +1 -0
- package/dist/utils/loadScript.js +1 -0
- package/dist/utils/object.js +1 -0
- package/dist/utils/string.js +1 -0
- package/dist/utils/toFunction.js +1 -0
- package/dist/utils/type.js +1 -0
- package/dist/utils/waitFrames.js +1 -0
- package/docs/components/_template.html +22 -0
- package/docs/components/card.html +35 -0
- package/docs/components/codeeditor.html +29 -0
- package/docs/components/component.html +88 -0
- package/docs/components/dialog.html +89 -0
- package/docs/components/icon.html +73 -0
- package/docs/components/import.html +34 -0
- package/docs/components/lazycomponent.html +50 -0
- package/docs/components/resize.html +107 -0
- package/docs/components/show-more.html +92 -0
- package/docs/components/sidemenu.html +97 -0
- package/docs/components/split.html +70 -0
- package/docs/components/tabs.html +33 -0
- package/docs/components/websnippeteditor.html +42 -0
- package/docs/index.html +17 -0
- package/docs/kempo/components/Card.js +1 -0
- package/docs/kempo/components/CodeEditor.js +1 -0
- package/docs/kempo/components/Collapse.js +1 -0
- package/docs/kempo/components/Component.js +1 -0
- package/docs/kempo/components/Dialog.js +1 -0
- package/docs/kempo/components/FocusCapture.js +1 -0
- package/docs/kempo/components/Icon.js +1 -0
- package/docs/kempo/components/Import.js +1 -0
- package/docs/kempo/components/LazyComponent.js +1 -0
- package/docs/kempo/components/ReactiveComponent.js +1 -0
- package/docs/kempo/components/ReactiveLazyComponent.js +1 -0
- package/docs/kempo/components/Resize.js +1 -0
- package/docs/kempo/components/Search.js +1 -0
- package/docs/kempo/components/ShowMore.js +1 -0
- package/docs/kempo/components/SideMenu.js +1 -0
- package/docs/kempo/components/Split.js +1 -0
- package/docs/kempo/components/Tabs.js +1 -0
- package/docs/kempo/components/ThemeSwitcher.js +1 -0
- package/docs/kempo/components/Timestamp.js +1 -0
- package/docs/kempo/components/WebSnippetEditor.js +1 -0
- package/docs/kempo/icons/arrow-down-double.svg +1 -0
- package/docs/kempo/icons/arrow-up-double.svg +1 -0
- package/docs/kempo/icons/close.svg +2 -0
- package/docs/kempo/icons/compare.svg +1 -0
- package/docs/kempo/icons/dark-mode.svg +1 -0
- package/docs/kempo/icons/delete.svg +1 -0
- package/docs/kempo/icons/filter-off.svg +1 -0
- package/docs/kempo/icons/filter.svg +1 -0
- package/docs/kempo/icons/light-mode.svg +1 -0
- package/docs/kempo/icons/menu.svg +1 -0
- package/docs/kempo/icons/pause.svg +1 -0
- package/docs/kempo/icons/play.svg +1 -0
- package/docs/kempo/icons/search.svg +1 -0
- package/docs/kempo/icons/settings.svg +1 -0
- package/docs/kempo/icons/storage.svg +1 -0
- package/docs/kempo/icons/trash-x.svg +1 -0
- package/docs/kempo/index.js +1 -0
- package/docs/kempo/kempo-hljs.css +1 -0
- package/docs/kempo/kempo-styles.css +1 -0
- package/docs/kempo/kempo-vars.css +1 -0
- package/docs/kempo/kempo.css +1 -0
- package/docs/kempo/kempo.js +1 -0
- package/docs/kempo/utils/cli.js +1 -0
- package/docs/kempo/utils/cookie.js +1 -0
- package/docs/kempo/utils/debounce.js +1 -0
- package/docs/kempo/utils/drag.js +1 -0
- package/docs/kempo/utils/element.js +1 -0
- package/docs/kempo/utils/formatTimestamp.js +1 -0
- package/docs/kempo/utils/fuzzyMatch.js +1 -0
- package/docs/kempo/utils/getPreferredTheme.js +1 -0
- package/docs/kempo/utils/loadCss.js +1 -0
- package/docs/kempo/utils/loadScript.js +1 -0
- package/docs/kempo/utils/object.js +1 -0
- package/docs/kempo/utils/string.js +1 -0
- package/docs/kempo/utils/toFunction.js +1 -0
- package/docs/kempo/utils/type.js +1 -0
- package/docs/kempo/utils/waitFrames.js +1 -0
- package/docs/nav-1.inc.html +66 -0
- package/docs/nav.inc.html +66 -0
- package/docs/search.json +94 -0
- package/docs/styles/_template.html +22 -0
- package/docs/styles/borders-spacing.html +193 -0
- package/docs/styles/buttons.html +113 -0
- package/docs/styles/colors.html +65 -0
- package/docs/styles/displays-layouts.html +156 -0
- package/docs/styles/embed-1.html +35 -0
- package/docs/styles/inputs.html +89 -0
- package/docs/styles/tables.html +143 -0
- package/docs/styles/typography.html +116 -0
- package/icons/arrow-down-double.svg +1 -0
- package/icons/arrow-up-double.svg +1 -0
- package/icons/close.svg +2 -0
- package/icons/compare.svg +1 -0
- package/icons/dark-mode.svg +1 -0
- package/icons/delete.svg +1 -0
- package/icons/filter-off.svg +1 -0
- package/icons/filter.svg +1 -0
- package/icons/light-mode.svg +1 -0
- package/icons/menu.svg +1 -0
- package/icons/pause.svg +1 -0
- package/icons/play.svg +1 -0
- package/icons/search.svg +1 -0
- package/icons/settings.svg +1 -0
- package/icons/storage.svg +1 -0
- package/icons/trash-x.svg +1 -0
- package/kempo/components/Card.js +65 -0
- package/kempo/components/CodeEditor.js +141 -0
- package/kempo/components/Component.js +109 -0
- package/kempo/components/Dialog.js +277 -0
- package/kempo/components/FocusCapture.js +30 -0
- package/kempo/components/Icon.js +60 -0
- package/kempo/components/Import.js +40 -0
- package/kempo/components/LazyComponent.js +40 -0
- package/kempo/components/ReactiveComponent.js +11 -0
- package/kempo/components/ReactiveLazyComponent.js +11 -0
- package/kempo/components/Resize.js +168 -0
- package/kempo/components/Search.js +136 -0
- package/kempo/components/ShowMore.js +82 -0
- package/kempo/components/SideMenu.js +156 -0
- package/kempo/components/Split.js +133 -0
- package/kempo/components/Tabs.js +254 -0
- package/kempo/components/ThemeSwitcher.js +77 -0
- package/kempo/components/Timestamp.js +25 -0
- package/kempo/components/WebSnippetEditor.js +159 -0
- package/kempo/kempo-hljs.css +145 -0
- package/kempo/kempo-styles.css +893 -0
- package/kempo/kempo-vars.css +154 -0
- package/kempo/kempo.js +48 -0
- package/kempo/utils/cli.js +54 -0
- package/kempo/utils/cookie.js +16 -0
- package/kempo/utils/debounce.js +9 -0
- package/kempo/utils/drag.js +74 -0
- package/kempo/utils/element.js +69 -0
- package/kempo/utils/formatTimestamp.js +11 -0
- package/kempo/utils/fuzzyMatch.js +55 -0
- package/kempo/utils/getPreferredTheme.js +1 -0
- package/kempo/utils/loadCss.js +10 -0
- package/kempo/utils/loadScript.js +10 -0
- package/kempo/utils/object.js +177 -0
- package/kempo/utils/string.js +54 -0
- package/kempo/utils/toFunction.js +24 -0
- package/kempo/utils/type.js +8 -0
- package/kempo/utils/waitFrames.js +17 -0
- package/package.json +33 -0
- package/scripts/build.js +131 -0
- package/scripts/docs.js +14 -0
- package/test/components/SuiteList.js +26 -0
- package/test/components/Test.js +357 -0
- package/test/index.html +49 -0
- package/test/index.js +25 -0
- package/test/suite.html +45 -0
- package/test/suites.inc.html +4 -0
- package/test/tests/components/Component.test.js +138 -0
- package/test/tests/utils/cli.test.js +113 -0
- package/test/tests/utils/cookie.test.js +87 -0
- package/test/tests/utils/debounce.test.js +71 -0
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
import Component from './Component.js';
|
|
2
|
+
import './FocusCapture.js';
|
|
3
|
+
import './Icon.js';
|
|
4
|
+
import {
|
|
5
|
+
firstFocusable,
|
|
6
|
+
onEvent,
|
|
7
|
+
offEvent,
|
|
8
|
+
dispatchEvent
|
|
9
|
+
} from '../utils/element.js';
|
|
10
|
+
|
|
11
|
+
export default class Dialog extends Component {
|
|
12
|
+
constructor({
|
|
13
|
+
opened = false,
|
|
14
|
+
closeBtn = true,
|
|
15
|
+
overlayClose = true,
|
|
16
|
+
confirmText = '',
|
|
17
|
+
confirmClasses = 'success ml',
|
|
18
|
+
confirmAction = () => {},
|
|
19
|
+
cancelText = '',
|
|
20
|
+
cancelClasses = '',
|
|
21
|
+
cancelAction = () => {},
|
|
22
|
+
closeCallback = () => {}
|
|
23
|
+
} = {}){
|
|
24
|
+
super();
|
|
25
|
+
|
|
26
|
+
this.registerAttributes({
|
|
27
|
+
opened,
|
|
28
|
+
closeBtn,
|
|
29
|
+
overlayClose,
|
|
30
|
+
confirmText,
|
|
31
|
+
confirmClasses,
|
|
32
|
+
cancelText,
|
|
33
|
+
cancelClasses
|
|
34
|
+
});
|
|
35
|
+
this.registerProps({
|
|
36
|
+
confirmAction,
|
|
37
|
+
cancelAction,
|
|
38
|
+
closeCallback,
|
|
39
|
+
previousFocus: null,
|
|
40
|
+
_clickHandler: (event) => {
|
|
41
|
+
const {target: { id }} = event;
|
|
42
|
+
if(
|
|
43
|
+
(id == 'overlay' && this.overlayClose) ||
|
|
44
|
+
id == 'close'
|
|
45
|
+
){
|
|
46
|
+
this.close();
|
|
47
|
+
} else if(id == 'cancel'){
|
|
48
|
+
this.cancelAction(event);
|
|
49
|
+
if(!event.defaultPrevented) this.close();
|
|
50
|
+
} else if(id == 'confirm'){
|
|
51
|
+
this.confirmAction(event);
|
|
52
|
+
if(!event.defaultPrevented) this.close();
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
_keydownHandler: ({ keyCode }) => {
|
|
56
|
+
if(keyCode === 27){
|
|
57
|
+
this.close();
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
_hasTitle: () => !!this.querySelector('[slot="title"]')
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
connectedCallback(){
|
|
64
|
+
super.connectedCallback();
|
|
65
|
+
onEvent(this.shadowRoot, 'click', this._clickHandler);
|
|
66
|
+
}
|
|
67
|
+
disconnectedCallback(){
|
|
68
|
+
super.connectedCallback();
|
|
69
|
+
offEvent(this.shadowRoot, 'click', this._clickHandler);
|
|
70
|
+
offEvent(window, 'keydown', this._keydownHandler); // just in case this was removed without being closed first
|
|
71
|
+
}
|
|
72
|
+
attributeChangedCallback(n, oV, nV){
|
|
73
|
+
super.attributeChangedCallback(n, oV, nV);
|
|
74
|
+
if(name === 'opened'){
|
|
75
|
+
dispatchEvent(this, nV?'opened':'closed');
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
open(){
|
|
79
|
+
this.opened = true;
|
|
80
|
+
const $toFucus = this.shadowRoot.querySelector('[autofocus]') || firstFocusable(this.shadowRoot);
|
|
81
|
+
if($toFucus) $toFucus.focus();
|
|
82
|
+
onEvent(window, 'keydown', this._keydownHandler);
|
|
83
|
+
}
|
|
84
|
+
close(){
|
|
85
|
+
this.opened = false;
|
|
86
|
+
this.blur();
|
|
87
|
+
this.closeCallback();
|
|
88
|
+
offEvent(window, 'keydown', this._keydownHandler);
|
|
89
|
+
}
|
|
90
|
+
toggle(){
|
|
91
|
+
this.opened?this.close():this.open();
|
|
92
|
+
}
|
|
93
|
+
focus(){
|
|
94
|
+
const $firstFocus = firstFocusable(this.shadowRoot);
|
|
95
|
+
if($firstFocus){
|
|
96
|
+
this.previousFocus = document.activeElement;
|
|
97
|
+
$firstFocus.focus();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
blur(){
|
|
101
|
+
if(this.previousFocus){
|
|
102
|
+
this.previousFocus.focus();
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
get shadowTemplate(){
|
|
107
|
+
return /*html*/`
|
|
108
|
+
<k-focus-capture>
|
|
109
|
+
<button id="overlay" aria-label="Close the Dialog"></button>
|
|
110
|
+
<div id="wrapper">
|
|
111
|
+
<div
|
|
112
|
+
id="dialog"
|
|
113
|
+
role="dialog"
|
|
114
|
+
aria-modal="true"
|
|
115
|
+
aria-labelledby="title"
|
|
116
|
+
>
|
|
117
|
+
<div
|
|
118
|
+
id="header"
|
|
119
|
+
class="${this._hasTitle()?'has-title':''}"
|
|
120
|
+
>
|
|
121
|
+
<div
|
|
122
|
+
id="title"
|
|
123
|
+
><slot name="title"></slot></div>
|
|
124
|
+
${this.renderIf(this.closeBtn, /*html*/`
|
|
125
|
+
<button
|
|
126
|
+
id="close"
|
|
127
|
+
>
|
|
128
|
+
<k-icon name="close"></k-icon>
|
|
129
|
+
</button>
|
|
130
|
+
`)}
|
|
131
|
+
</div>
|
|
132
|
+
<div id="body">
|
|
133
|
+
${super.shadowTemplate}
|
|
134
|
+
</div>
|
|
135
|
+
${this.renderIf(this.cancelText || this.confirmText, /*html*/`
|
|
136
|
+
<div id="footer">
|
|
137
|
+
${this.renderIf(this.cancelText, /*html*/`
|
|
138
|
+
<button id="cancel" class="${this.cancelClasses}">
|
|
139
|
+
${this.cancelText}
|
|
140
|
+
</button>
|
|
141
|
+
`)}
|
|
142
|
+
${this.renderIf(this.confirmText, /*html*/`
|
|
143
|
+
<button id="confirm" class="${this.confirmClasses}">
|
|
144
|
+
${this.confirmText}
|
|
145
|
+
</button>
|
|
146
|
+
`)}
|
|
147
|
+
</div>
|
|
148
|
+
`)}
|
|
149
|
+
</div>
|
|
150
|
+
</div>
|
|
151
|
+
</k-focus-capture>
|
|
152
|
+
`;
|
|
153
|
+
}
|
|
154
|
+
get shadowStyles(){
|
|
155
|
+
return /*css*/`
|
|
156
|
+
${super.shadowStyles}
|
|
157
|
+
:host {
|
|
158
|
+
display: inline;
|
|
159
|
+
height: 0;
|
|
160
|
+
width: 0;
|
|
161
|
+
}
|
|
162
|
+
:host(:not([opened])){
|
|
163
|
+
display: none;
|
|
164
|
+
}
|
|
165
|
+
#overlay {
|
|
166
|
+
position: fixed;
|
|
167
|
+
width: 100vw;
|
|
168
|
+
height: 100vh;
|
|
169
|
+
top: 0;
|
|
170
|
+
left: 0;
|
|
171
|
+
background-color: var(--c_overlay);
|
|
172
|
+
z-index: 100;
|
|
173
|
+
border: 0px solid transparent;
|
|
174
|
+
box-shadow: 0 0 0 transparent;
|
|
175
|
+
}
|
|
176
|
+
#wrapper {
|
|
177
|
+
display: flex;
|
|
178
|
+
justify-content: center;
|
|
179
|
+
align-items: center;
|
|
180
|
+
position: fixed;
|
|
181
|
+
width: 100vw;
|
|
182
|
+
height: 100vh;
|
|
183
|
+
top: 0;
|
|
184
|
+
left: 0;
|
|
185
|
+
z-index: 101;
|
|
186
|
+
pointer-events: none;
|
|
187
|
+
}
|
|
188
|
+
#dialog {
|
|
189
|
+
display: flex;
|
|
190
|
+
flex-direction: column;
|
|
191
|
+
min-width: var(--min_width, 20rem);
|
|
192
|
+
width: var(--width, fit-content);
|
|
193
|
+
max-width: var(--max_width, calc(100vw - 2rem));
|
|
194
|
+
min-height: var(--min_height, 12rem);
|
|
195
|
+
height: var(--height, fit-content);
|
|
196
|
+
max-height: var(--max_height, calc(100vh - 2rem));
|
|
197
|
+
background-color: var(--c_bg);
|
|
198
|
+
box-shadow: var(--drop_shadow);
|
|
199
|
+
border-radius: var(--radius);
|
|
200
|
+
pointer-events: all;
|
|
201
|
+
}
|
|
202
|
+
#header {
|
|
203
|
+
display: flex;
|
|
204
|
+
align-items: center;
|
|
205
|
+
}
|
|
206
|
+
#header.has-title {
|
|
207
|
+
border-bottom: 1px solid var(--c_border);
|
|
208
|
+
}
|
|
209
|
+
#title {
|
|
210
|
+
flex: 1 1 auto;
|
|
211
|
+
}
|
|
212
|
+
#close {
|
|
213
|
+
border: 0px;
|
|
214
|
+
background: transparent;
|
|
215
|
+
box-shadow: 0 0 0 transparent;
|
|
216
|
+
color: var(--tc);
|
|
217
|
+
}
|
|
218
|
+
#close k-icon {
|
|
219
|
+
pointer-events: none;
|
|
220
|
+
}
|
|
221
|
+
#body {
|
|
222
|
+
flex: 1 1 auto;
|
|
223
|
+
}
|
|
224
|
+
#footer {
|
|
225
|
+
display: flex;
|
|
226
|
+
justify-content: flex-end;
|
|
227
|
+
padding: var(--spacer_h);
|
|
228
|
+
}
|
|
229
|
+
`;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
static renderOnChange = [
|
|
233
|
+
'opened',
|
|
234
|
+
'closeBtn',
|
|
235
|
+
'overlayClose',
|
|
236
|
+
'title',
|
|
237
|
+
'confirmText',
|
|
238
|
+
'cancelText'
|
|
239
|
+
];
|
|
240
|
+
|
|
241
|
+
static create(contents = '', options = {}){
|
|
242
|
+
const $dialog = new Dialog({
|
|
243
|
+
opened: true,
|
|
244
|
+
...options
|
|
245
|
+
});
|
|
246
|
+
onEvent($dialog, 'close', $dialog.remove);
|
|
247
|
+
if(contents instanceof HTMLElement || contents instanceof DocumentFragment){
|
|
248
|
+
$dialog.appendChild(contents);
|
|
249
|
+
} else if(contents instanceof NodeList){
|
|
250
|
+
contents.forEach( $el => $dialog.appendChild($el));
|
|
251
|
+
} else {
|
|
252
|
+
$dialog.innerHTML = contents;
|
|
253
|
+
}
|
|
254
|
+
document.body.appendChild($dialog);
|
|
255
|
+
}
|
|
256
|
+
static confirm(text, responseCallback, options){
|
|
257
|
+
Dialog.create(`
|
|
258
|
+
<h5 slot="title" class="pyh px m0">Confirm Event Deletion</h5>
|
|
259
|
+
<p class="p">${text}</p>
|
|
260
|
+
`, {
|
|
261
|
+
...options,
|
|
262
|
+
closeBtn: false,
|
|
263
|
+
overlayClose: false,
|
|
264
|
+
confirmText: 'Yes',
|
|
265
|
+
confirmClasses: 'success ml',
|
|
266
|
+
confirmAction: () => {
|
|
267
|
+
return responseCallback(true);
|
|
268
|
+
},
|
|
269
|
+
cancelText: 'No',
|
|
270
|
+
cancelClasses: 'danger',
|
|
271
|
+
cancelAction: () => {
|
|
272
|
+
return responseCallback(false);
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
window.customElements.define('k-dialog', Dialog);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import LazyComponent from './LazyComponent.js';
|
|
2
|
+
|
|
3
|
+
export default class FocusCapture extends LazyComponent {
|
|
4
|
+
constructor(){
|
|
5
|
+
super({
|
|
6
|
+
delegatesFocus: true
|
|
7
|
+
});
|
|
8
|
+
}
|
|
9
|
+
render(){
|
|
10
|
+
super.render();
|
|
11
|
+
this.shadowRoot.getElementById('after').addEventListener('focus', () => {
|
|
12
|
+
this.querySelector('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])').focus();
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
get shadowTemplate(){
|
|
17
|
+
return /*html*/`
|
|
18
|
+
${super.shadowTemplate}
|
|
19
|
+
<div id="after" tabindex="0"></div>
|
|
20
|
+
`;
|
|
21
|
+
}
|
|
22
|
+
get shadowStyles(){
|
|
23
|
+
return /*css*/`
|
|
24
|
+
:host {
|
|
25
|
+
display: inline-block;
|
|
26
|
+
}
|
|
27
|
+
`;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
window.customElements.define('k-focus-capture', FocusCapture);
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import Component from './Component.js';
|
|
2
|
+
|
|
3
|
+
export default class Icon extends Component {
|
|
4
|
+
constructor(){
|
|
5
|
+
super();
|
|
6
|
+
this.registerAttributes({
|
|
7
|
+
src: '',
|
|
8
|
+
name: ''
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
async render(force){
|
|
12
|
+
if(await super.render(force)){
|
|
13
|
+
if(this.src){
|
|
14
|
+
this.innerHTML = await (await fetch(this.src)).text();
|
|
15
|
+
this.fixSVG();
|
|
16
|
+
} else if(this.name){
|
|
17
|
+
this.innerHTML = await (await fetch(`${Icon.pathToIcons}/${this.name}.svg`)).text();
|
|
18
|
+
this.fixSVG();
|
|
19
|
+
} else {
|
|
20
|
+
this.rendered = false;
|
|
21
|
+
this.innerHTML = '';
|
|
22
|
+
}
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
attributeChangedCallback(n, oV, nV){
|
|
28
|
+
if(['src', 'name'].includes(n)){
|
|
29
|
+
this.render(true);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
fixSVG(){
|
|
33
|
+
const $svg = this.querySelector('svg');
|
|
34
|
+
$svg.removeAttribute('width');
|
|
35
|
+
$svg.removeAttribute('height');
|
|
36
|
+
$svg.querySelectorAll('path, rect, circle').forEach( $path => {
|
|
37
|
+
$path.setAttribute('fill', 'currentColor');
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
get shadowStyles(){
|
|
41
|
+
return /*css*/`
|
|
42
|
+
:host {
|
|
43
|
+
display: inline-block;
|
|
44
|
+
vertical-align: bottom;
|
|
45
|
+
}
|
|
46
|
+
::slotted(svg){
|
|
47
|
+
height: 1.35em;
|
|
48
|
+
vertical-align: middle;
|
|
49
|
+
}
|
|
50
|
+
`;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
static observedAttributes = [
|
|
54
|
+
'name',
|
|
55
|
+
'src'
|
|
56
|
+
];
|
|
57
|
+
|
|
58
|
+
static pathToIcons = '/icons';
|
|
59
|
+
}
|
|
60
|
+
window.customElements.define('k-icon', Icon);
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import Component from './Component.js';
|
|
2
|
+
|
|
3
|
+
export default class Import extends Component {
|
|
4
|
+
constructor(){
|
|
5
|
+
super();
|
|
6
|
+
this.registerAttribute('src');
|
|
7
|
+
}
|
|
8
|
+
attributeChangedCallback(n, oV, nV){
|
|
9
|
+
if(n === 'src' && oV !== nV){
|
|
10
|
+
this.render(true);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
async render(force){
|
|
14
|
+
const src = this.src;
|
|
15
|
+
if(src && await super.render(force)){
|
|
16
|
+
this.innerHTML = await (await fetch(src)).text();
|
|
17
|
+
this.querySelectorAll('script').forEach( $badScript => {
|
|
18
|
+
const $goodScript = document.createElement('script');
|
|
19
|
+
if($badScript.getAttribute('type')) $goodScript.type = $badScript.getAttribute('type');
|
|
20
|
+
if($badScript.getAttribute('src')) $goodScript.src = $badScript.getAttribute('src');
|
|
21
|
+
if($badScript.textContent) $goodScript.textContent = $badScript.textContent;
|
|
22
|
+
$badScript.parentElement.replaceChild($goodScript, $badScript);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
get shadowStyles(){
|
|
29
|
+
return /*css*/`
|
|
30
|
+
:host {
|
|
31
|
+
display: inline;
|
|
32
|
+
}
|
|
33
|
+
`;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
static get renderOnAttributes(){
|
|
37
|
+
retur ['src'];
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
window.customElements.define('k-import', Import);
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import Component from './Component.js';
|
|
2
|
+
import { isInView } from '../utils/element.js';
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
export default class LazyComponent extends Component {
|
|
6
|
+
constructor(shadowDetails){
|
|
7
|
+
super(shadowDetails);
|
|
8
|
+
(new IntersectionObserver(([comp]) => {
|
|
9
|
+
if(comp.intersectionRatio > 0 && !this.rendered){
|
|
10
|
+
this.inViewCallback();
|
|
11
|
+
} else {
|
|
12
|
+
this.outOfViewCallback();
|
|
13
|
+
}
|
|
14
|
+
})).observe(this);
|
|
15
|
+
|
|
16
|
+
this.registerAttribute('unrender', false);
|
|
17
|
+
}
|
|
18
|
+
async connectedCallback(){
|
|
19
|
+
// Do not do super.connectedCallback() because it will render the component prematurely
|
|
20
|
+
await this.renderSkelton(); // so that the skeleton height is rendered, which will give it the propert height so potentional LazyComponents below it will get out of the viewport as they normally would, before we then check if it is in View (which is delayed a few frames.
|
|
21
|
+
if(await isInView(this)){
|
|
22
|
+
await this.inViewCallback();
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
async inViewCallback(){
|
|
26
|
+
await this.render();
|
|
27
|
+
}
|
|
28
|
+
async outOfViewCallback(){
|
|
29
|
+
if(this.unrender){
|
|
30
|
+
await this.renderSkelton();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
async renderSkelton(){
|
|
34
|
+
this.shadowRoot.innerHTML = `<link rel="stylesheet" href="../kempo/kempo-vars.css" /><link rel="stylesheet" href="../kempo/kempo-styles.css" />${this.skeletonTemplate}<style>${this.shadowStyles}</style>`;
|
|
35
|
+
this.rendered = false;
|
|
36
|
+
}
|
|
37
|
+
get skeletonTemplate(){
|
|
38
|
+
return /*html*/`<div style="height: var(--skeleton_height, 1rem)"></div>`;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import Component from './Component.js';
|
|
2
|
+
|
|
3
|
+
export default class ReactiveComponent extends Component {
|
|
4
|
+
attributeChangedCallback(n, oV, nV){
|
|
5
|
+
super.attributeChangedCallback(n, oV, nV);
|
|
6
|
+
if(this.constructor.renderOnChange.includes(n)){
|
|
7
|
+
this.render(true);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
static renderOnChange = [];
|
|
11
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import LazyComponent from './LazyComponent.js';
|
|
2
|
+
|
|
3
|
+
export default class ReactiveComponent extends LazyComponent {
|
|
4
|
+
attributeChangedCallback(n, oV, nV){
|
|
5
|
+
super.attributeChangedCallback(n, oV, nV);
|
|
6
|
+
if(this.constructor.renderOnChange.includes(n)){
|
|
7
|
+
this.render(true);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
static renderOnChange = [];
|
|
11
|
+
}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import Component from './Component.js';
|
|
2
|
+
import drag from '../utils/drag.js';
|
|
3
|
+
|
|
4
|
+
const startSize = Symbol('startSize'),
|
|
5
|
+
dragStartHandler = Symbol('dragStartHandler'),
|
|
6
|
+
dragEndHandler = Symbol('dragEndHandler'),
|
|
7
|
+
dragSideHandler = Symbol('dragSideHandler'),
|
|
8
|
+
dragBottomHandler = Symbol('dragBottomHandler'),
|
|
9
|
+
dragCornerHandler = Symbol('dragCornerHandler'),
|
|
10
|
+
cleanupFuncs = Symbol('cleanupFuncs');
|
|
11
|
+
export default class Resize extends Component {
|
|
12
|
+
constructor(){
|
|
13
|
+
super();
|
|
14
|
+
|
|
15
|
+
this[startSize] = {width: 0, height: 0};
|
|
16
|
+
|
|
17
|
+
this[dragStartHandler] = ({element}) => {
|
|
18
|
+
const { width, height } = this.getBoundingClientRect();
|
|
19
|
+
this[startSize].width = width;
|
|
20
|
+
this[startSize].height = height;
|
|
21
|
+
this.resizing = element.id;
|
|
22
|
+
}
|
|
23
|
+
this[dragEndHandler] = () => {
|
|
24
|
+
this.resizing = '';
|
|
25
|
+
}
|
|
26
|
+
this[dragSideHandler] = ({x}) => {
|
|
27
|
+
this.style.width = this[startSize].width + x + 'px';
|
|
28
|
+
}
|
|
29
|
+
this[dragBottomHandler] = ({y}) => {
|
|
30
|
+
this.style.height = this[startSize].height + y + 'px';
|
|
31
|
+
}
|
|
32
|
+
this[dragCornerHandler] = ({x, y}) => {
|
|
33
|
+
this.style.width = this[startSize].width + x + 'px';
|
|
34
|
+
this.style.height = this[startSize].height + y + 'px';
|
|
35
|
+
}
|
|
36
|
+
this[cleanupFuncs] = [];
|
|
37
|
+
|
|
38
|
+
this.registerAttribute('resizing', '');
|
|
39
|
+
}
|
|
40
|
+
async render(force){
|
|
41
|
+
if(await super.render(force)){
|
|
42
|
+
this[cleanupFuncs].push(drag({
|
|
43
|
+
element: this.shadowRoot.getElementById('side'),
|
|
44
|
+
startCallback: this[dragStartHandler],
|
|
45
|
+
endCallback: this[dragEndHandler],
|
|
46
|
+
callback: this[dragSideHandler],
|
|
47
|
+
preventScroll: true
|
|
48
|
+
}));
|
|
49
|
+
this[cleanupFuncs].push(drag({
|
|
50
|
+
element: this.shadowRoot.getElementById('bottom'),
|
|
51
|
+
startCallback: this[dragStartHandler],
|
|
52
|
+
endCallback: this[dragEndHandler],
|
|
53
|
+
callback: this[dragBottomHandler],
|
|
54
|
+
preventScroll: true
|
|
55
|
+
}));
|
|
56
|
+
this[cleanupFuncs].push(drag({
|
|
57
|
+
element: this.shadowRoot.getElementById('corner'),
|
|
58
|
+
startCallback: this[dragStartHandler],
|
|
59
|
+
endCallback: this[dragEndHandler],
|
|
60
|
+
callback: this[dragCornerHandler],
|
|
61
|
+
preventScroll: true
|
|
62
|
+
}));
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
disconnectedCallback(){
|
|
68
|
+
super.disconnectedCallback();
|
|
69
|
+
this[cleanupFuncs].forEach( cleanup => cleanup());
|
|
70
|
+
}
|
|
71
|
+
get shadowTemplate(){
|
|
72
|
+
return /*html*/`
|
|
73
|
+
<div id="main">
|
|
74
|
+
${super.shadowTemplate}
|
|
75
|
+
</div>
|
|
76
|
+
<div id="side" class="handle">
|
|
77
|
+
<svg viewBox="0 0 15 64" xmlns="http://www.w3.org/2000/svg"><path fill="currentColor" d="m 15.000001,3 c 0,-1.661998 -1.115001,-3 -2.5,-3 -1.384999,0 -2.5,1.338002 -2.5,3 v 58 c 0,1.661998 1.115001,3 2.5,3 1.384999,0 2.5,-1.338002 2.5,-3 z M 5.0000008,3 c 0,-1.661998 -1.115001,-3 -2.5,-3 C 1.1150018,0 7.5891117e-7,1.338002 7.5891117e-7,3 v 58 c 0,1.661998 1.11500104108883,3 2.50000004108883,3 1.384999,0 2.5,-1.338002 2.5,-3 z" /></svg>
|
|
78
|
+
</div>
|
|
79
|
+
<div id="bottom" class="handle">
|
|
80
|
+
<svg viewBox="0 0 64 15" xmlns="http://www.w3.org/2000/svg"><path fill="currentColor" d="M 3,0 C 1.3380017,0 0,1.1150014 0,2.5 0,3.8849986 1.3380017,5 3,5 H 61 C 62.661998,5 64,3.8849986 64,2.5 64,1.1150014 62.661998,0 61,0 Z M 3,10 C 1.3380017,10 0,11.115001 0,12.5 0,13.884999 1.3380017,15 3,15 h 58 c 1.661998,0 3,-1.115001 3,-2.5 C 64,11.115001 62.661998,10 61,10 Z" /></svg>
|
|
81
|
+
</div>
|
|
82
|
+
<div id="corner" class="handle">
|
|
83
|
+
<svg version="1.1" viewBox="0 0 15 15" xmlns="http://www.w3.org/2000/svg"><path fill="currentColor" d="m12.735 3.0095e-4c-0.77288 0.011702-1.6098 0.36368-2.2773 1.0313l-9.4258 9.4258c-1.1868 1.1868-1.3772 2.908-0.42773 3.8574 0.94943 0.94943 2.6687 0.7571 3.8555-0.42969l9.4258-9.4258c1.1868-1.1868 1.3772-2.906 0.42774-3.8555-0.41537-0.41537-0.977-0.61262-1.5781-0.60352zm0 8.5684c-0.77288 0.011702-1.6098 0.36564-2.2773 1.0332l-0.85744 0.85546c-1.1868 1.1868-1.3772 2.908-0.42773 3.8574 0.94943 0.94943 2.6687 0.7571 3.8555-0.42969l0.85742-0.85742c1.1868-1.1868 1.3772-2.906 0.42773-3.8555-0.41537-0.41537-0.977-0.61262-1.5781-0.60352z" /></svg>
|
|
84
|
+
</div>
|
|
85
|
+
`;
|
|
86
|
+
}
|
|
87
|
+
get shadowStyles(){
|
|
88
|
+
return /*css*/`
|
|
89
|
+
${super.shadowStyles}
|
|
90
|
+
:host {
|
|
91
|
+
--handle_size: 1rem;
|
|
92
|
+
|
|
93
|
+
display: grid;
|
|
94
|
+
grid-template-columns: 1fr var(--handle_size);
|
|
95
|
+
grid-template-rows: 1fr var(--handle_size);
|
|
96
|
+
border: 1px solid var(--c_border);
|
|
97
|
+
border-radius: var(--radius);
|
|
98
|
+
min-width: 10rem;
|
|
99
|
+
max-width: 100%;
|
|
100
|
+
min-height: 10rem;
|
|
101
|
+
max-height: 100%;
|
|
102
|
+
}
|
|
103
|
+
:host([dimention="height"]){
|
|
104
|
+
grid-template-columns: 1fr;
|
|
105
|
+
}
|
|
106
|
+
:host([dimention="width"]){
|
|
107
|
+
grid-template-rows: 1fr;
|
|
108
|
+
}
|
|
109
|
+
#main {
|
|
110
|
+
grid-row: 1;
|
|
111
|
+
grid-column: 1;
|
|
112
|
+
overflow: auto;
|
|
113
|
+
}
|
|
114
|
+
#side {
|
|
115
|
+
grid-row: 1;
|
|
116
|
+
grid-column: 2;
|
|
117
|
+
cursor: ew-resize;
|
|
118
|
+
}
|
|
119
|
+
#bottom {
|
|
120
|
+
grid-row: 2;
|
|
121
|
+
grid-column: 1;
|
|
122
|
+
text-align: center;
|
|
123
|
+
cursor: ns-resize;
|
|
124
|
+
}
|
|
125
|
+
#corner {
|
|
126
|
+
grid-row: 2;
|
|
127
|
+
grid-column: 2;
|
|
128
|
+
overflow: hidden;
|
|
129
|
+
cursor: nwse-resize;
|
|
130
|
+
}
|
|
131
|
+
.handle {
|
|
132
|
+
display: flex;
|
|
133
|
+
align-items: center;
|
|
134
|
+
justify-content: center;
|
|
135
|
+
}
|
|
136
|
+
.handle svg {
|
|
137
|
+
transform: scale(0.5);
|
|
138
|
+
}
|
|
139
|
+
#bottom svg {
|
|
140
|
+
height: var(--handle_size);
|
|
141
|
+
}
|
|
142
|
+
#side svg {
|
|
143
|
+
width: var(--handle_size);
|
|
144
|
+
}
|
|
145
|
+
#corner svg {
|
|
146
|
+
width: var(--handle_size);
|
|
147
|
+
height: var(--handle_size);
|
|
148
|
+
}
|
|
149
|
+
:host(:not([resizing=""])) #main {
|
|
150
|
+
pointer-events: none;
|
|
151
|
+
}
|
|
152
|
+
:host([resizing="side"]) #side,
|
|
153
|
+
:host([resizing="corner"]) #side,
|
|
154
|
+
:host([resizing="corner"]) #corner,
|
|
155
|
+
:host([resizing="corner"]) #bottom,
|
|
156
|
+
:host([resizing="bottom"]) #bottom {
|
|
157
|
+
background-color: var(--c_highlight);
|
|
158
|
+
}
|
|
159
|
+
:host([dimention="height"]) #side,
|
|
160
|
+
:host([dimention="height"]) #corner,
|
|
161
|
+
:host([dimention="width"]) #bottom,
|
|
162
|
+
:host([dimention="width"]) #corner {
|
|
163
|
+
display: none;
|
|
164
|
+
}
|
|
165
|
+
`;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
window.customElements.define('k-resize', Resize);
|