kempo-ui 0.1.6 → 0.2.2
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/.github/skills/highlight-code/SKILL.md +22 -6
- package/.github/skills/new-component/SKILL.md +68 -4
- package/AGENTS.md +11 -0
- package/bin/highlight_code.js +7 -15
- package/dist/components/Aside.js +326 -0
- package/dist/components/Dialog.js +1 -1
- package/dist/components/Dropdown.js +1 -1
- package/dist/components/Main.js +2 -2
- package/dist/components/Nav.js +27 -0
- package/dist/components/PhotoViewer.js +1 -1
- package/dist/components/ShadowComponent.js +1 -1
- package/dist/components/ThemeSwitcher.js +1 -0
- package/dist/components/Toast.js +1 -1
- package/docs/components/accordion.html +4 -3
- package/docs/components/aside-items.html +43 -0
- package/docs/components/aside-menu.html +43 -0
- package/docs/components/aside-push.html +26 -0
- package/docs/components/aside.html +567 -0
- package/docs/components/card.html +4 -3
- package/docs/components/color-picker.html +4 -3
- package/docs/components/content-slider.html +4 -3
- package/docs/components/dialog.html +4 -3
- package/docs/components/dropdown.html +4 -3
- package/docs/components/filter-list.html +4 -3
- package/docs/components/focus-capture.html +6 -5
- package/docs/components/html-editor.html +5 -4
- package/docs/components/hybrid-component.html +5 -4
- package/docs/components/icon.html +4 -3
- package/docs/components/import.html +5 -4
- package/docs/components/light-component.html +4 -3
- package/docs/components/nav.html +117 -0
- package/docs/components/photo-viewer.html +5 -4
- package/docs/components/resize.html +5 -4
- package/docs/components/shadow-component.html +4 -3
- package/docs/components/show-more.html +5 -4
- package/docs/components/sortable.html +4 -3
- package/docs/components/spinner.html +4 -3
- package/docs/components/split.html +5 -4
- package/docs/components/table.html +4 -3
- package/docs/components/tableControls.html +4 -3
- package/docs/components/tableCustomFields.html +4 -3
- package/docs/components/tableFetchRecords.html +5 -4
- package/docs/components/tableFieldSortHide.html +5 -4
- package/docs/components/tablePagination.html +4 -3
- package/docs/components/tableRecordEditing.html +4 -3
- package/docs/components/tableRecordFiltering.html +5 -4
- package/docs/components/tableRecordHiding.html +4 -3
- package/docs/components/tableRecordSearching.html +5 -4
- package/docs/components/tableRecordSelection.html +4 -3
- package/docs/components/tableRowControls.html +4 -3
- package/docs/components/tableServerSync.html +5 -4
- package/docs/components/tableSorting.html +5 -4
- package/docs/components/tabs.html +4 -3
- package/docs/components/tags.html +4 -3
- package/docs/components/theme-select.html +4 -3
- package/docs/components/theme-switcher.html +5 -4
- package/docs/components/timestamp.html +4 -3
- package/docs/components/toast.html +4 -3
- package/docs/components/toggle.html +5 -4
- package/docs/components/tree.html +5 -4
- package/docs/index.html +22 -21
- package/docs/nav-1.inc.html +18 -12
- package/docs/nav.inc.html +20 -13
- package/docs/nav.inc.js +1 -1
- package/docs/src/components/Aside.js +326 -0
- package/docs/src/components/Dialog.js +1 -1
- package/docs/src/components/Dropdown.js +1 -1
- package/docs/src/components/Main.js +2 -2
- package/docs/src/components/Nav.js +27 -0
- package/docs/src/components/PhotoViewer.js +1 -1
- package/docs/src/components/ShadowComponent.js +1 -1
- package/docs/src/components/ThemeSwitcher.js +1 -0
- package/docs/src/components/Toast.js +1 -1
- package/docs/utils/context.html +4 -3
- package/docs/utils/cookie.html +4 -3
- package/docs/utils/debounce.html +4 -3
- package/docs/utils/drag.html +4 -3
- package/docs/utils/elevation.html +156 -0
- package/docs/utils/formatTimestamp.html +4 -3
- package/docs/utils/object.html +4 -3
- package/docs/utils/propConverters.html +4 -3
- package/docs/utils/string.html +4 -3
- package/docs/utils/theme.html +4 -3
- package/docs/utils/toTitleCase.html +4 -3
- package/docs/utils/type.html +4 -3
- package/docs/utils/wait.html +4 -3
- package/llm.txt +247 -0
- package/package.json +3 -4
- package/src/components/Aside.js +726 -0
- package/src/components/Dialog.js +1 -1
- package/src/components/Dropdown.js +1 -1
- package/src/components/Main.js +34 -30
- package/src/components/Nav.js +53 -0
- package/src/components/PhotoViewer.js +1 -1
- package/src/components/ShadowComponent.js +1 -1
- package/src/components/ThemeSwitcher.js +1 -0
- package/src/components/Toast.js +1 -1
- package/tests/bin/get_icon.node-test.js +26 -0
- package/tests/bin/highlight_code.node-test.js +108 -0
- package/tests/bin/list_icons.node-test.js +26 -0
- package/tests/components/Aside.browser-test.js +778 -0
- package/tests/components/Main.browser-test.js +115 -283
- package/dist/components/SideMenu.js +0 -97
- package/dist/components/SidePanel.js +0 -236
- package/docs/components/side-menu.html +0 -189
- package/docs/components/side-panel-basic.html +0 -44
- package/docs/components/side-panel-dual.html +0 -70
- package/docs/components/side-panel-menu.html +0 -50
- package/docs/components/side-panel-persistent.html +0 -90
- package/docs/components/side-panel-scroll.html +0 -176
- package/docs/components/side-panel.html +0 -245
- package/docs/src/components/SideMenu.js +0 -97
- package/docs/src/components/SidePanel.js +0 -236
- package/scripts/update-kempo-css.js +0 -53
- package/src/components/SideMenu.js +0 -178
- package/src/components/SidePanel.js +0 -513
- package/tests/components/SideMenu.browser-test.js +0 -667
- package/tests/components/SidePanel.browser-test.js +0 -520
- package/tools/highlight.js +0 -51
|
@@ -244,7 +244,7 @@ export default class Dropdown extends ShadowComponent {
|
|
|
244
244
|
display: none;
|
|
245
245
|
position: fixed;
|
|
246
246
|
position-anchor: --dropdown-trigger;
|
|
247
|
-
z-index:
|
|
247
|
+
z-index: 70;
|
|
248
248
|
min-width: anchor-size(width);
|
|
249
249
|
background: var(--c_bg);
|
|
250
250
|
border: 1px solid var(--c_border);
|
package/src/components/Main.js
CHANGED
|
@@ -2,16 +2,9 @@ import ShadowComponent from './ShadowComponent.js';
|
|
|
2
2
|
import { html, css } from '../lit-all.min.js';
|
|
3
3
|
|
|
4
4
|
export default class Main extends ShadowComponent {
|
|
5
|
-
static properties = {
|
|
6
|
-
leftPanelWidth: { type: String, state: true },
|
|
7
|
-
rightPanelWidth: { type: String, state: true }
|
|
8
|
-
};
|
|
9
|
-
|
|
10
5
|
constructor() {
|
|
11
6
|
super();
|
|
12
|
-
this.
|
|
13
|
-
this.rightPanelWidth = '0px';
|
|
14
|
-
this.handlePanelChange = this.handlePanelChange.bind(this);
|
|
7
|
+
this.widthMap = new Map();
|
|
15
8
|
}
|
|
16
9
|
|
|
17
10
|
/*
|
|
@@ -19,33 +12,50 @@ export default class Main extends ShadowComponent {
|
|
|
19
12
|
*/
|
|
20
13
|
connectedCallback() {
|
|
21
14
|
super.connectedCallback();
|
|
22
|
-
window.addEventListener('
|
|
23
|
-
|
|
24
|
-
const leftPanel = document.querySelector('k-side-panel:not([side="right"])');
|
|
25
|
-
if(leftPanel){
|
|
26
|
-
this.leftPanelWidth = leftPanel.collapsed ? '3.5rem' : '16rem';
|
|
27
|
-
}
|
|
15
|
+
window.addEventListener('aside_state_change', this.handleAsideChange);
|
|
28
16
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
17
|
+
document.querySelectorAll('k-aside[main="push"]').forEach(aside => {
|
|
18
|
+
if(aside.state !== 'offscreen') {
|
|
19
|
+
const width = aside.getTargetWidth(aside.state);
|
|
20
|
+
if(width > 0) {
|
|
21
|
+
this.widthMap.set(aside, { side: aside.side || 'left', width });
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
this.recalculate();
|
|
33
27
|
}
|
|
34
28
|
|
|
35
29
|
disconnectedCallback() {
|
|
36
30
|
super.disconnectedCallback();
|
|
37
|
-
window.removeEventListener('
|
|
31
|
+
window.removeEventListener('aside_state_change', this.handleAsideChange);
|
|
38
32
|
}
|
|
39
33
|
|
|
40
34
|
/*
|
|
41
35
|
Event Handlers
|
|
42
36
|
*/
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
37
|
+
handleAsideChange = (event) => {
|
|
38
|
+
const { aside, state, main, width } = event.detail;
|
|
39
|
+
if(main === 'overlay' || state === 'offscreen') {
|
|
40
|
+
this.widthMap.delete(aside);
|
|
41
|
+
} else {
|
|
42
|
+
this.widthMap.set(aside, { side: aside.side || 'left', width });
|
|
48
43
|
}
|
|
44
|
+
this.recalculate();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
recalculate = () => {
|
|
48
|
+
let maxLeft = 0;
|
|
49
|
+
let maxRight = 0;
|
|
50
|
+
for(const [, { side, width }] of this.widthMap) {
|
|
51
|
+
if(side === 'right') {
|
|
52
|
+
maxRight = Math.max(maxRight, width);
|
|
53
|
+
} else {
|
|
54
|
+
maxLeft = Math.max(maxLeft, width);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
this.style.setProperty('--left-panel-width', `${maxLeft}px`);
|
|
58
|
+
this.style.setProperty('--right-panel-width', `${maxRight}px`);
|
|
49
59
|
}
|
|
50
60
|
|
|
51
61
|
/*
|
|
@@ -75,12 +85,6 @@ export default class Main extends ShadowComponent {
|
|
|
75
85
|
padding-right: var(--spacer);
|
|
76
86
|
}
|
|
77
87
|
`;
|
|
78
|
-
|
|
79
|
-
updated() {
|
|
80
|
-
super.updated();
|
|
81
|
-
this.style.setProperty('--left-panel-width', this.leftPanelWidth);
|
|
82
|
-
this.style.setProperty('--right-panel-width', this.rightPanelWidth);
|
|
83
|
-
}
|
|
84
88
|
}
|
|
85
89
|
|
|
86
90
|
window.customElements.define('k-main', Main);
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { html, css } from '../lit-all.min.js';
|
|
2
|
+
import ShadowComponent from './ShadowComponent.js';
|
|
3
|
+
|
|
4
|
+
export default class Nav extends ShadowComponent {
|
|
5
|
+
static properties = {
|
|
6
|
+
fixed: { type: Boolean, reflect: true }
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
constructor() {
|
|
10
|
+
super();
|
|
11
|
+
this.fixed = false;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/*
|
|
15
|
+
Rendering
|
|
16
|
+
*/
|
|
17
|
+
render() {
|
|
18
|
+
return html`<nav><slot></slot></nav>`;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/*
|
|
22
|
+
Styles
|
|
23
|
+
*/
|
|
24
|
+
static styles = css`
|
|
25
|
+
:host {
|
|
26
|
+
display: block;
|
|
27
|
+
}
|
|
28
|
+
:host([fixed]) {
|
|
29
|
+
position: fixed;
|
|
30
|
+
top: 0;
|
|
31
|
+
left: 0;
|
|
32
|
+
right: 0;
|
|
33
|
+
z-index: 50;
|
|
34
|
+
}
|
|
35
|
+
nav {
|
|
36
|
+
display: flex;
|
|
37
|
+
align-items: center;
|
|
38
|
+
width: 100%;
|
|
39
|
+
}
|
|
40
|
+
::slotted(a) {
|
|
41
|
+
display: inline-block;
|
|
42
|
+
padding: var(--spacer);
|
|
43
|
+
text-decoration: none !important;
|
|
44
|
+
}
|
|
45
|
+
::slotted(.link) {
|
|
46
|
+
display: inline-block;
|
|
47
|
+
padding: var(--spacer) !important;
|
|
48
|
+
text-decoration: none !important;
|
|
49
|
+
}
|
|
50
|
+
`;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
customElements.define('k-nav', Nav);
|
|
@@ -29,7 +29,7 @@ export default class ShadowComponent extends LitElement {
|
|
|
29
29
|
|
|
30
30
|
const link = document.createElement('link');
|
|
31
31
|
link.rel = 'stylesheet';
|
|
32
|
-
link.href = window.kempo?.pathToStylesheet || 'https://cdn.jsdelivr.net/npm/kempo-css@
|
|
32
|
+
link.href = window.kempo?.pathToStylesheet || 'https://cdn.jsdelivr.net/npm/kempo-css@2/dist/kempo.min.css';
|
|
33
33
|
shadowRoot.appendChild(link);
|
|
34
34
|
|
|
35
35
|
// Inject component styles if they exist
|
package/src/components/Toast.js
CHANGED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { execFile } from 'child_process';
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
Utility Functions
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const run = (args) => new Promise((resolve) => {
|
|
8
|
+
const proc = execFile('node', ['bin/get_icon.js', ...args], (error, stdout, stderr) => {
|
|
9
|
+
resolve({ code: proc.exitCode ?? error?.code, stdout, stderr });
|
|
10
|
+
});
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
/*
|
|
14
|
+
Tests
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
export default {
|
|
18
|
+
'should exit with error when no icon name provided': async ({pass, fail}) => {
|
|
19
|
+
const {code, stderr} = await run([]);
|
|
20
|
+
if(code !== 0 && stderr.includes('Usage')){
|
|
21
|
+
pass('Shows usage and exits with error');
|
|
22
|
+
} else {
|
|
23
|
+
fail(`Expected error exit with usage, got code=${code}, stderr="${stderr}"`);
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
};
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { execFile } from 'child_process';
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
Utility Functions
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const run = (args, stdin) => new Promise((resolve) => {
|
|
8
|
+
const proc = execFile('node', ['bin/highlight_code.js', ...args], (error, stdout, stderr) => {
|
|
9
|
+
resolve({ code: proc.exitCode ?? error?.code, stdout, stderr });
|
|
10
|
+
});
|
|
11
|
+
if(stdin !== undefined){
|
|
12
|
+
proc.stdin.write(stdin);
|
|
13
|
+
proc.stdin.end();
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
/*
|
|
18
|
+
Tests
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
export default {
|
|
22
|
+
'should exit with error when no arguments provided': async ({pass, fail}) => {
|
|
23
|
+
const {code, stderr} = await run([]);
|
|
24
|
+
if(code !== 0 && stderr.includes('Usage')){
|
|
25
|
+
pass('Shows usage and exits with error');
|
|
26
|
+
} else {
|
|
27
|
+
fail(`Expected error exit with usage message, got code=${code}, stderr="${stderr}"`);
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
'should exit with error for unknown language': async ({pass, fail}) => {
|
|
32
|
+
const {code, stderr} = await run(['fakeLang', 'code']);
|
|
33
|
+
if(code !== 0 && stderr.includes('Unknown language')){
|
|
34
|
+
pass('Shows unknown language error');
|
|
35
|
+
} else {
|
|
36
|
+
fail(`Expected unknown language error, got code=${code}, stderr="${stderr}"`);
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
'should highlight JavaScript passed as argument': async ({pass, fail}) => {
|
|
41
|
+
const {stdout} = await run(['js', 'const x = 1;']);
|
|
42
|
+
if(stdout.includes('<pre><code class="hljs javascript">') &&
|
|
43
|
+
stdout.includes('</code></pre>') &&
|
|
44
|
+
stdout.includes('<span class="hljs-keyword">const</span>')){
|
|
45
|
+
pass('JavaScript highlighted correctly with wrapper');
|
|
46
|
+
} else {
|
|
47
|
+
fail(`Unexpected output: ${stdout}`);
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
'should highlight HTML passed as argument': async ({pass, fail}) => {
|
|
52
|
+
const {stdout} = await run(['html', '<div>hello</div>']);
|
|
53
|
+
if(stdout.includes('<pre><code class="hljs html">') &&
|
|
54
|
+
stdout.includes('</code></pre>') &&
|
|
55
|
+
stdout.includes('hljs-name')){
|
|
56
|
+
pass('HTML highlighted correctly with wrapper');
|
|
57
|
+
} else {
|
|
58
|
+
fail(`Unexpected output: ${stdout}`);
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
'should accept language aliases': async ({pass, fail}) => {
|
|
63
|
+
const {stdout} = await run(['js', 'let x = 1;']);
|
|
64
|
+
if(stdout.includes('class="hljs javascript"')){
|
|
65
|
+
pass('Alias "js" resolved to "javascript"');
|
|
66
|
+
} else {
|
|
67
|
+
fail(`Alias not resolved: ${stdout}`);
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
'should read code from stdin': async ({pass, fail}) => {
|
|
72
|
+
const {stdout} = await run(['css'], 'body { color: red; }');
|
|
73
|
+
if(stdout.includes('<pre><code class="hljs css">') &&
|
|
74
|
+
stdout.includes('</code></pre>')){
|
|
75
|
+
pass('stdin input highlighted correctly');
|
|
76
|
+
} else {
|
|
77
|
+
fail(`Unexpected output: ${stdout}`);
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
|
|
81
|
+
'should convert newlines to <br> tags': async ({pass, fail}) => {
|
|
82
|
+
const {stdout} = await run(['js'], 'const x = 1;\nconst y = 2;');
|
|
83
|
+
if(stdout.includes('<br>') && !stdout.includes('\n</code>')){
|
|
84
|
+
pass('Newlines converted to <br>');
|
|
85
|
+
} else {
|
|
86
|
+
fail(`Expected <br> tags: ${stdout}`);
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
|
|
90
|
+
'should output a single line': async ({pass, fail}) => {
|
|
91
|
+
const {stdout} = await run(['html'], '<div>\n <p>hello</p>\n</div>');
|
|
92
|
+
const lines = stdout.trim().split('\n');
|
|
93
|
+
if(lines.length === 1){
|
|
94
|
+
pass('Output is a single line');
|
|
95
|
+
} else {
|
|
96
|
+
fail(`Expected 1 line, got ${lines.length}`);
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
|
|
100
|
+
'should beautify code before highlighting': async ({pass, fail}) => {
|
|
101
|
+
const {stdout} = await run(['html', '<div><p>hello</p></div>']);
|
|
102
|
+
if(stdout.includes('<br>')){
|
|
103
|
+
pass('Beautifier added line breaks (converted to <br>)');
|
|
104
|
+
} else {
|
|
105
|
+
fail(`Expected beautified output with <br>: ${stdout}`);
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { execFile } from 'child_process';
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
Utility Functions
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const run = (args) => new Promise((resolve) => {
|
|
8
|
+
const proc = execFile('node', ['bin/list_icons.js', ...args], (error, stdout, stderr) => {
|
|
9
|
+
resolve({ code: proc.exitCode ?? error?.code, stdout, stderr });
|
|
10
|
+
});
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
/*
|
|
14
|
+
Tests
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
export default {
|
|
18
|
+
'should exit with error when no search term provided': async ({pass, fail}) => {
|
|
19
|
+
const {code, stderr} = await run([]);
|
|
20
|
+
if(code !== 0 && stderr.includes('Usage')){
|
|
21
|
+
pass('Shows usage and exits with error');
|
|
22
|
+
} else {
|
|
23
|
+
fail(`Expected error exit with usage, got code=${code}, stderr="${stderr}"`);
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
};
|