Compare commits

...

42 Commits

Author SHA1 Message Date
2f7fdc16c7 1.0.279 2024-02-03 12:44:12 +01:00
f4b426bc7f fix(core): update 2024-02-03 12:44:12 +01:00
9577cc9ebf 1.0.278 2024-02-03 11:26:16 +01:00
be5124217a fix(core): update 2024-02-03 11:26:15 +01:00
d029a6c346 1.0.277 2024-01-24 12:18:38 +01:00
69bb03dcdf fix(core): update 2024-01-24 12:18:37 +01:00
5eb2f4cebc 1.0.276 2024-01-24 00:59:11 +01:00
c021a84788 fix(core): update 2024-01-24 00:59:11 +01:00
321ce99338 1.0.275 2024-01-22 22:30:45 +01:00
6cfe89645c fix(core): update 2024-01-22 22:30:44 +01:00
11f900beeb 1.0.274 2024-01-22 20:51:51 +01:00
39ca21e57c fix(core): update 2024-01-22 20:51:50 +01:00
87872191e2 1.0.273 2024-01-22 19:40:09 +01:00
2d3fd74333 fix(core): update 2024-01-22 19:40:08 +01:00
eebe898dcc 1.0.272 2024-01-22 19:27:54 +01:00
ca73d00f68 fix(core): update 2024-01-22 19:27:54 +01:00
14bdc46073 1.0.271 2024-01-22 19:27:31 +01:00
bf04ce6a8f fix(core): update 2024-01-22 19:27:30 +01:00
9dc6dab3a5 1.0.270 2024-01-22 19:23:23 +01:00
a21a3b6918 fix(core): update 2024-01-22 19:23:22 +01:00
6ae21d73aa 1.0.269 2024-01-22 18:39:31 +01:00
941871991f fix(core): update 2024-01-22 18:39:31 +01:00
497c38f426 1.0.268 2024-01-22 18:30:36 +01:00
bfaa1623d9 fix(core): update 2024-01-22 18:30:35 +01:00
5ffa5a2adc 1.0.267 2024-01-22 18:30:01 +01:00
16d1375e47 fix(core): update 2024-01-22 18:30:00 +01:00
30eda34f37 1.0.266 2024-01-22 17:32:58 +01:00
2cc7eb1ead fix(core): update 2024-01-22 17:32:58 +01:00
64f5bee801 1.0.265 2024-01-22 17:29:53 +01:00
9d57f983dd fix(core): update 2024-01-22 17:29:53 +01:00
8ccd21df36 1.0.264 2024-01-22 17:25:55 +01:00
c22c994d12 fix(core): update 2024-01-22 17:25:55 +01:00
01369444b7 1.0.263 2024-01-22 17:22:33 +01:00
4beb15f70c fix(core): update 2024-01-22 17:22:33 +01:00
30170bcd2e 1.0.262 2024-01-22 17:12:59 +01:00
f29a8de504 fix(core): update 2024-01-22 17:12:58 +01:00
965ab02315 1.0.261 2024-01-22 01:29:28 +01:00
991784eae6 fix(core): update 2024-01-22 01:29:27 +01:00
b474b7986c 1.0.260 2024-01-22 01:26:13 +01:00
98542252cb fix(core): update 2024-01-22 01:26:13 +01:00
0d78deadf2 1.0.259 2024-01-22 01:11:29 +01:00
5108f47e56 fix(core): update 2024-01-22 01:11:28 +01:00
25 changed files with 1850 additions and 18 deletions

View File

@ -1,6 +1,6 @@
{
"name": "@design.estate/dees-catalog",
"version": "1.0.258",
"version": "1.0.279",
"private": false,
"description": "website for lossless.com",
"main": "dist_ts_web/index.js",
@ -26,9 +26,14 @@
"@push.rocks/smartpromise": "^4.0.3",
"@push.rocks/smartstring": "^4.0.13",
"@tsclass/tsclass": "^4.0.46",
"@webcontainer/api": "^1.1.8",
"apexcharts": "^3.45.2",
"highlight.js": "11.9.0",
"ibantools": "^4.3.9",
"pdfjs-dist": "^4.0.379"
"monaco-editor": "^0.45.0",
"pdfjs-dist": "^4.0.379",
"xterm": "^5.3.0",
"xterm-addon-fit": "^0.8.0"
},
"devDependencies": {
"@git.zone/tsbuild": "^2.1.72",

105
pnpm-lock.yaml generated
View File

@ -38,15 +38,30 @@ dependencies:
'@tsclass/tsclass':
specifier: ^4.0.46
version: 4.0.46
'@webcontainer/api':
specifier: ^1.1.8
version: 1.1.8
apexcharts:
specifier: ^3.45.2
version: 3.45.2
highlight.js:
specifier: 11.9.0
version: 11.9.0
ibantools:
specifier: ^4.3.9
version: 4.3.9
monaco-editor:
specifier: ^0.45.0
version: 0.45.0
pdfjs-dist:
specifier: ^4.0.379
version: 4.0.379
xterm:
specifier: ^5.3.0
version: 5.3.0
xterm-addon-fit:
specifier: ^0.8.0
version: 0.8.0(xterm@5.3.0)
devDependencies:
'@git.zone/tsbuild':
@ -2084,11 +2099,19 @@ packages:
- utf-8-validate
dev: true
/@webcontainer/api@1.1.8:
resolution: {integrity: sha512-m9WRj38oCoFPrqZOTeJcncPjnZ00FZUMq9YHEXxdhAoYhhQ69Rz4qK5p444cIPaMy2j8H7HcNLcAIwMGWnpMpw==}
dev: false
/@xmldom/xmldom@0.8.10:
resolution: {integrity: sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==}
engines: {node: '>=10.0.0'}
dev: true
/@yr/monotone-cubic-spline@1.0.3:
resolution: {integrity: sha512-FQXkOta0XBSUPHndIKON2Y9JeQz5ZeMqLYZVVK93FliNBFm7LNMIZmY6FrMEB9XPcDbE2bekMbZD6kzDkxwYjA==}
dev: false
/abbrev@1.1.1:
resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==}
requiresBuild: true
@ -2202,6 +2225,18 @@ packages:
picomatch: 2.3.1
dev: true
/apexcharts@3.45.2:
resolution: {integrity: sha512-PpuM4sJWy70sUh5U1IFn1m1p45MdHSChLUNnqEoUUUHSU2IHZugFrsVNhov1S8Q0cvfdrCRCvdBtHGSs6PSAWQ==}
dependencies:
'@yr/monotone-cubic-spline': 1.0.3
svg.draggable.js: 2.2.2
svg.easing.js: 2.0.0
svg.filter.js: 2.0.2
svg.pathmorphing.js: 0.1.3
svg.resize.js: 1.4.3
svg.select.js: 3.0.1
dev: false
/aproba@2.0.0:
resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==}
requiresBuild: true
@ -5095,6 +5130,10 @@ packages:
yargs-unparser: 1.6.0
dev: true
/monaco-editor@0.45.0:
resolution: {integrity: sha512-mjv1G1ZzfEE3k9HZN0dQ2olMdwIfaeAAjFiwNprLfYNRSz7ctv9XuCT7gPtBGrMUeV1/iZzYKj17Khu1hxoHOA==}
dev: false
/ms@2.0.0:
resolution: {integrity: sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=}
dev: true
@ -6249,6 +6288,60 @@ packages:
has-flag: 4.0.0
dev: true
/svg.draggable.js@2.2.2:
resolution: {integrity: sha512-JzNHBc2fLQMzYCZ90KZHN2ohXL0BQJGQimK1kGk6AvSeibuKcIdDX9Kr0dT9+UJ5O8nYA0RB839Lhvk4CY4MZw==}
engines: {node: '>= 0.8.0'}
dependencies:
svg.js: 2.7.1
dev: false
/svg.easing.js@2.0.0:
resolution: {integrity: sha512-//ctPdJMGy22YoYGV+3HEfHbm6/69LJUTAqI2/5qBvaNHZ9uUFVC82B0Pl299HzgH13rKrBgi4+XyXXyVWWthA==}
engines: {node: '>= 0.8.0'}
dependencies:
svg.js: 2.7.1
dev: false
/svg.filter.js@2.0.2:
resolution: {integrity: sha512-xkGBwU+dKBzqg5PtilaTb0EYPqPfJ9Q6saVldX+5vCRy31P6TlRCP3U9NxH3HEufkKkpNgdTLBJnmhDHeTqAkw==}
engines: {node: '>= 0.8.0'}
dependencies:
svg.js: 2.7.1
dev: false
/svg.js@2.7.1:
resolution: {integrity: sha512-ycbxpizEQktk3FYvn/8BH+6/EuWXg7ZpQREJvgacqn46gIddG24tNNe4Son6omdXCnSOaApnpZw6MPCBA1dODA==}
dev: false
/svg.pathmorphing.js@0.1.3:
resolution: {integrity: sha512-49HWI9X4XQR/JG1qXkSDV8xViuTLIWm/B/7YuQELV5KMOPtXjiwH4XPJvr/ghEDibmLQ9Oc22dpWpG0vUDDNww==}
engines: {node: '>= 0.8.0'}
dependencies:
svg.js: 2.7.1
dev: false
/svg.resize.js@1.4.3:
resolution: {integrity: sha512-9k5sXJuPKp+mVzXNvxz7U0uC9oVMQrrf7cFsETznzUDDm0x8+77dtZkWdMfRlmbkEEYvUn9btKuZ3n41oNA+uw==}
engines: {node: '>= 0.8.0'}
dependencies:
svg.js: 2.7.1
svg.select.js: 2.1.2
dev: false
/svg.select.js@2.1.2:
resolution: {integrity: sha512-tH6ABEyJsAOVAhwcCjF8mw4crjXSI1aa7j2VQR8ZuJ37H2MBUbyeqYr5nEO7sSN3cy9AR9DUwNg0t/962HlDbQ==}
engines: {node: '>= 0.8.0'}
dependencies:
svg.js: 2.7.1
dev: false
/svg.select.js@3.0.1:
resolution: {integrity: sha512-h5IS/hKkuVCbKSieR9uQCj9w+zLHoPh+ce19bBYyqF53g6mnPB8sAtIbe1s9dh2S2fCmYX2xel1Ln3PJBbK4kw==}
engines: {node: '>= 0.8.0'}
dependencies:
svg.js: 2.7.1
dev: false
/sweet-scroll@4.0.0:
resolution: {integrity: sha512-mR6fRsAQANtm3zpzhUE73KAOt2aT4ZsWzNSggiEsSqdO6Zh4gM7ioJG81EngrZEl0XAc3ZvzEfhxggOoEBc8jA==}
dev: false
@ -6871,6 +6964,18 @@ packages:
engines: {node: '>=0.4.0'}
dev: true
/xterm-addon-fit@0.8.0(xterm@5.3.0):
resolution: {integrity: sha512-yj3Np7XlvxxhYF/EJ7p3KHaMt6OdwQ+HDu573Vx1lRXsVxOcnVJs51RgjZOouIZOczTsskaS+CpXspK81/DLqw==}
peerDependencies:
xterm: ^5.0.0
dependencies:
xterm: 5.3.0
dev: false
/xterm@5.3.0:
resolution: {integrity: sha512-8QqjlekLUFTrU6x7xck1MsPzPA571K5zNqWm0M0oroYEWVOptZ0+ubQSkQ3uxIEhcIHRujJy6emDWX4A7qyFzg==}
dev: false
/y18n@4.0.3:
resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==}
dev: true

View File

@ -3,6 +3,6 @@
*/
export const commitinfo = {
name: '@design.estate/dees-catalog',
version: '1.0.258',
version: '1.0.279',
description: 'website for lossless.com'
}

View File

@ -1,11 +1,13 @@
export const dark = {
blue: '#0050b9',
blueActive: '#0069f2',
blueMuted: '#012452',
text: '#ffffff',
}
export const bright = {
blue: '#0050b9',
blueActive: '#0069f2',
blueMuted: '#0069f2',
text: '#333333',
}

View File

@ -0,0 +1,239 @@
import * as plugins from './00plugins.js';
import {
DeesElement,
type TemplateResult,
property,
customElement,
html,
css,
cssManager,
} from '@design.estate/dees-element';
import * as domtools from '@design.estate/dees-domtools';
import { DeesContextmenu } from './dees-contextmenu.js';
@customElement('dees-appui-activitylog')
export class DeesAppuiActivitylog extends DeesElement {
// STATIC
public static demo = () => html`<dees-appui-activitylog></dees-appui-activitylog>`;
// INSTANCE
public static styles = [
cssManager.defaultStyles,
css`
:host {
color: #fff;
position: relative;
display: block;
width: 100%;
max-width: 300px;
height: 100%;
background: #111c28;
font-family: 'Intel One Mono', sans-serif;
border-left: 1px solid #202020;
cursor: default;
}
.maincontainer {
position: absolute;
top: 0px;
left: 0px;
height: 100%;
width: 100%;
}
.topbar {
position: absolute;
top: 0px;
height: 32px;
width: 100%;
padding: 0px 12px 0px 12px;
background: #0e151f;
}
.topbar .heading {
text-align: left;
line-height: 24px;
padding-top: 8px;
font-weight: 500;
font-size: 14px;
font-family: 'Roboto', 'Inter', sans-serif;
}
.activityContainer {
position: absolute;
top: 32px;
bottom: 40px;
width: 100%;
padding: 8px 0px;
overflow-y: scroll;
}
.streamingIndicator {
font-size: 12px;
text-align: center;
padding-top: 16px;
color: #888
}
.streamingIndicator.bottom {
padding-top: 0px;
padding-bottom: 16px;
}
.activityentry {
min-height: 30px;
font-size: 12px;
padding: 8px 16px;
border-bottom: 1px dotted #ffffff20;
}
.activityentry:last-of-type {
border-bottom: 1px solid #ffffff00;
}
.activityentry:hover {
background: #00000080;
}
.timestamp {
color: #ff8787;
}
.searchbox {
position: absolute;
bottom: 0px;
width: 100%;
height: 40px;
background: #0e151f;
}
.searchbox input {
color: #fff;
background: none;
width: 100%;
height: 40px;
line-height: 32px;
border: none;
padding: 4px 12px;
font-family: 'Intel One Mono', sans-serif;
}
.searchbox input:focus {
outline: none;
}
.bottomShadow {
position: absolute;
width: 100%;
height: 32px;
bottom: 40px;
background: linear-gradient(180deg, #111c2800 0%, #0e151f 100%);
pointer-events: none;
}
.topShadow {
position: absolute;
width: 100%;
height: 32px;
top: 32px;
background: linear-gradient(0deg, #111c2800 0%, #0e151f 100%);
pointer-events: none;
}
`,
];
public render(): TemplateResult {
return html`
${domtools.elementBasic.styles}
<style></style>
<div class="maincontainer">
<div class="topbar">
<div class="heading">Activity Log</div>
</div>
<div class="activityContainer">
<div class="streamingIndicator">streaming...</div>
<div class="activityentry" @contextmenu=${async eventArg => {
DeesContextmenu.openContextMenuWithOptions(eventArg, [
{
name: 'app settings',
action: async () => {},
},
{
name: 'account settings',
action: async () => {},
},
{
name: 'logout',
action: async () => {},
},
]);
}}>
<span class="timestamp">22:01:</span> Max Mustermann logged in
</div>
<div class="activityentry">
<span class="timestamp">22:02:</span> Max Mustermann viewed an invoice
</div>
<div class="activityentry">
<span class="timestamp">22:03:</span> Max Mustermann added a new contact
</div>
<div class="activityentry">
<span class="timestamp">22:04:</span> Max Mustermann updated account settings
</div>
<div class="activityentry">
<span class="timestamp">22:05:</span> Max Mustermann logged out
</div>
<div class="activityentry">
<span class="timestamp">22:06:</span> Max Mustermann logged in
</div>
<div class="activityentry">
<span class="timestamp">22:07:</span> Max Mustermann created a new invoice
</div>
<div class="activityentry">
<span class="timestamp">22:08:</span> Max Mustermann sent an invoice
</div>
<div class="activityentry">
<span class="timestamp">22:09:</span> Max Mustermann viewed reports
</div>
<div class="activityentry">
<span class="timestamp">22:10:</span> Max Mustermann logged out
</div>
<div class="activityentry">
<span class="timestamp">22:11:</span> Max Mustermann logged in
</div>
<div class="activityentry">
<span class="timestamp">22:12:</span> Max Mustermann deleted an invoice
</div>
<div class="activityentry">
<span class="timestamp">22:13:</span> Max Mustermann contacted support
</div>
<div class="activityentry">
<span class="timestamp">22:14:</span> Max Mustermann added a new user
</div>
<div class="activityentry">
<span class="timestamp">22:15:</span> Max Mustermann changed password
</div>
<div class="activityentry">
<span class="timestamp">22:16:</span> Max Mustermann logged out
</div>
<div class="activityentry">
<span class="timestamp">22:17:</span> Max Mustermann logged in
</div>
<div class="activityentry">
<span class="timestamp">22:18:</span> Max Mustermann archived an invoice
</div>
<div class="activityentry">
<span class="timestamp">22:19:</span> Max Mustermann approved a payment
</div>
<div class="activityentry">
<span class="timestamp">22:20:</span> Max Mustermann logged out
</div>
<div class="streamingIndicator bottom">loading more...</div>
</div>
<div class="searchbox">
<input type="text" placeholder="Search" />
</div>
<div class="topShadow"></div>
<div class="bottomShadow"></div>
</div>
`;
}
}

View File

@ -0,0 +1,77 @@
import {
DeesElement,
type TemplateResult,
property,
customElement,
html,
css,
cssManager,
} from '@design.estate/dees-element';
@customElement('dees-appui-appbar')
export class DeesAppuiBar extends DeesElement {
public static demo = () => html`<dees-appui-appbar></dees-appui-appbar>`;
public static styles = [
cssManager.defaultStyles,
css`
:host {
display: block;
position: relative;
height: 100%;
width: 100%;
height: 40px;
border-bottom: 1px solid #202020;
background: #000000;
color: #ffffff80;
font-size: 12px;
display: grid;
grid-template-columns: ${cssManager.cssGridColumns(3, 20)};
-webkit-app-region: drag;
}
.menus {
display: flex;
padding-left: 8px;
cursor: default;
}
.menuItem {
line-height: 24px;
padding: 0px 8px;
margin: 8px 0px;
border-radius: 4px;
-webkit-app-region: no-drag;
}
.menuItem:hover {
background: #ffffff20;
}
.breadcrumbs {
height: 24px;
line-height: 24px;
margin: 8px;
border-radius: 8px;
text-align: center;
}
`,
];
// INSTANCE
public render(): TemplateResult {
return html`
<div class="menus">
<dees-windowcontrols></dees-windowcontrols>
<div class="menuItem">File</div>
<div class="menuItem">View</div>
<div class="menuItem">Help</div>
<div class="menuItem">Terminal</div>
</div>
<div class="breadcrumbs">
tool:social.io > org:design.estate > prop:lossless.com
</div>
<div class="account"></div>
`;
}
}

View File

@ -0,0 +1,47 @@
import {
DeesElement,
type TemplateResult,
property,
customElement,
html,
css,
cssManager,
} from '@design.estate/dees-element';
@customElement('dees-appui-base')
export class DeesAppuiBase extends DeesElement {
public static demo = () => html`<dees-appui-base></dees-appui-base>`;
public static styles = [
cssManager.defaultStyles,
css`
:host {
position: absolute;
height: 100%;
width: 100%;
}
.maingrid {
position: absolute;
top: 40px;
height: calc(100% - 40px);
width: 100%;
display: grid;
grid-template-columns: 60px 240px auto 240px;
}
`,
];
// INSTANCE
public render(): TemplateResult {
return html`
<style></style>
<dees-appui-appbar></dees-appui-appbar>
<div class="maingrid">
<dees-appui-mainmenu></dees-appui-mainmenu>
<dees-appui-mainselector></dees-appui-mainselector>
<dees-appui-maincontent></dees-appui-maincontent>
<dees-appui-activitylog></dees-appui-activitylog>
</div>
`;
}
}

View File

@ -0,0 +1,161 @@
import * as interfaces from './interfaces/index.js';
import {
DeesElement,
type TemplateResult,
property,
customElement,
html,
css,
cssManager,
} from '@design.estate/dees-element';
import * as domtools from '@design.estate/dees-domtools';
@customElement('dees-appui-maincontent')
export class DeesAppuiMaincontent extends DeesElement {
public static demo = () => html`<dees-appui-maincontent></dees-appui-maincontent>`;
// INSTANCE
@property({
type: Array,
})
public tabs: interfaces.ITab[] = [
{ key: 'option 1', action: () => {} },
{ key: 'a very long option', action: () => {} },
{ key: 'reminder: set your tabs', action: () => {} },
{ key: 'option 4', action: () => {} },
];
@property()
public selectedTab = null;
public static styles = [
cssManager.defaultStyles,
css`
:host {
color: #fff;
display: block;
width: 100%;
height: 100%;
position: relative;
background: #161616;
}
.maincontainer {
position: absolute;
height: 100%;
right: 0px;
top: 0px;
width: 100%;
}
.topbar {
position: absolute;
width: 100%;
background: #000000;
user-select: none;
}
.topbar .tabsContainer {
padding-top: 20px;
padding-bottom: 0px;
position: relative;
z-index: 1;
display: grid;
margin-left: 24px;
font-size: 14px;
}
.topbar .tabsContainer .tab {
color: #a0a0a0;
white-space: nowrap;
margin-right: 30px;
padding-top: 4px;
padding-bottom: 12px;
transition: color 0.1s;
}
.topbar .tabsContainer .tab:hover {
color: #ffffff;
}
.topbar .tabsContainer .tab.selectedTab {
color: #e0e0e0;
}
.topbar .tabIndicator {
position: absolute;
z-index: 0;
left: 40px;
bottom: 0px;
height: 40px;
width: 40px;
background: #161616;
transition: all 0.1s;
border-top-left-radius: 8px;
border-top-right-radius: 8px;
border-top: 1px solid #444444;
}
.mainicon {
}
`,
];
public render(): TemplateResult {
return html`
<style>
.topbar .tabsContainer {
grid-template-columns: repeat(${this.tabs.length}, min-content);
}
</style>
<div class="maincontainer">
<div class="topbar">
<div class="tabsContainer">
${this.tabs.map((tabArg) => {
return html`
<div
class="tab ${tabArg === this.selectedTab ? 'selectedTab' : null}"
@click="${() => {
this.selectedTab = tabArg;
this.updateTabIndicator();
tabArg.action();
}}"
>
${tabArg.key}
</div>
`;
})}
</div>
<div class="tabIndicator"></div>
</div>
</div>
`;
}
/**
* updates the indicator
*/
private updateTabIndicator() {
let selectedTab = this.selectedTab;
const tabIndex = this.tabs.indexOf(selectedTab);
const selectedTabElement: HTMLElement = this.shadowRoot.querySelector(
`.tabsContainer .tab:nth-child(${tabIndex + 1})`
);
const tabsContainer: HTMLElement = this.shadowRoot.querySelector('.tabsContainer');
const marginLeft = parseInt(window.getComputedStyle(tabsContainer).getPropertyValue("margin-left"));
const tabIndicator: HTMLElement = this.shadowRoot.querySelector('.tabIndicator');
tabIndicator.style.width = selectedTabElement.clientWidth + 24 + 'px';
tabIndicator.style.left = selectedTabElement.offsetLeft + marginLeft - 12 + 'px';
}
private updateTab(tabArg: interfaces.ITab) {
this.selectedTab = tabArg;
this.updateTabIndicator();
this.selectedTab.action();
}
firstUpdated() {
this.updateTab(this.tabs[0]);
}
}

View File

@ -0,0 +1,142 @@
import * as plugins from './00plugins.js';
import * as interfaces from './interfaces/index.js';
import {
DeesElement,
type TemplateResult,
property,
customElement,
html,
css,
cssManager,
} from '@design.estate/dees-element';
import { DeesContextmenu } from './dees-contextmenu.js';
/**
* the most left menu
* usually used as organization selector
*/
@customElement('dees-appui-mainmenu')
export class DeesAppuiMainmenu extends DeesElement {
public static demo = () => html`<dees-appui-mainmenu></dees-appui-mainmenu>`;
// INSTANCE
// INSTANCE
@property()
public tabs: interfaces.ITab[] = [
{ key: 'option 1', iconName: 'building', action: () => {} },
{ key: 'option 2', iconName: 'building', action: () => {} },
{ key: 'option 3', iconName: 'building', action: () => {} },
{ key: 'option 4', iconName: 'building', action: () => {} },
];
@property()
public selectedTab: interfaces.ITab;
public static styles = [
cssManager.defaultStyles,
css`
.mainContainer {
--menuSize: 60px;
color: #ccc;
z-index: 10;
display: block;
position: relative;
width: var(--menuSize);
height: 100%;
background: #000000;
box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.5);
user-select: none;
border-right: 1px solid #202020;
}
.tabsContainer {
}
.tab {
padding-top: 18px;
font-size: 24px;
width: var(--menuSize);
height: var(--menuSize);
text-align: center;
transition: color 0.1s, background 0.2s;
}
.tab:hover {
background: rgba(255, 255, 255, 0.15);
}
.tab.selectedTab {
color: #fff;
background: rgba(255, 255, 255, 0.1);
}
.tabIndicator {
opacity: 0;
background: #4e729a;
position: absolute;
width: 5px;
height: calc((var(--menuSize) / 3) * 2);
left: 0px;
top: calc(var(--menuSize) - (((var(--menuSize) / 3) * 2) / 2));
border-top-right-radius: 7px;
border-bottom-right-radius: 7px;
transition: all 0.1s;
}
`,
];
public render(): TemplateResult {
return html`
<div class="mainContainer" @contextmenu=${(eventArg) => {
DeesContextmenu.openContextMenuWithOptions(eventArg, [{
name: 'app settings',
action: async () => {},
iconName: 'gear',
}])
}}>
<div class="tabsContainer">
${this.tabs.map((tabArg) => {
return html`
<div
class="tab ${tabArg === this.selectedTab ? 'selectedTab' : null}"
@click="${() => {
this.updateTab(tabArg);
}}"
>
<dees-icon iconFA="${tabArg.iconName as any}"></dees-icon>
</div>
`;
})}
</div>
<div class="tabIndicator"></div>
</div>
`;
}
private async updateTabIndicator() {
let selectedTab = this.selectedTab;
if (!selectedTab) {
selectedTab = this.tabs[0];
}
const tabIndex = this.tabs.indexOf(selectedTab);
const selectedTabElement: HTMLElement = this.shadowRoot.querySelector(
`.tabsContainer .tab:nth-child(${tabIndex + 1})`
);
const tabIndicator: HTMLElement = this.shadowRoot.querySelector('.tabIndicator');
const offsetTop = selectedTabElement.offsetTop;
tabIndicator.style.opacity = `1`;
tabIndicator.style.top = `calc(${offsetTop}px + (var(--menuSize) / 6))`;
}
updateTab(tabArg: interfaces.ITab) {
this.selectedTab = tabArg;
this.updateTabIndicator();
this.selectedTab.action();
}
firstUpdated() {
this.updateTab(this.tabs[0]);
}
}

View File

@ -0,0 +1,160 @@
import * as plugins from './00plugins.js';
import * as interfaces from './interfaces/index.js';
import { DeesContextmenu } from './dees-contextmenu.js';
import {
DeesElement,
type TemplateResult,
property,
customElement,
html,
css,
cssManager,
} from '@design.estate/dees-element';
/**
* the property selector menu
* mainly used to select assets within in an organization
*/
@customElement('dees-appui-mainselector')
export class DeesAppuiMainselector extends DeesElement {
public static demo = () => html`<dees-appui-mainselector></dees-appui-mainselector>`;
// INSTANCE
@property()
public selectionOptions: interfaces.ISelectionOption[] = [
{
key: 'Overview',
action: () => {},
},
{
key: 'option 1',
action: () => {},
},
{ key: 'option 2', action: () => {} },
{ key: 'option 3', action: () => {} },
{ key: 'option 4', action: () => {} },
];
@property()
public selectedOption: interfaces.ISelectionOption = null;
public static styles = [
cssManager.defaultStyles,
css`
:host {
color: #fff;
position: relative;
display: block;
width: 100%;
max-width: 300px;
height: 100%;
background: #000000;
border-right: 1px solid #222222;
}
.maincontainer {
position: absolute;
top: 0px;
left: 0px;
height: 100%;
width: 100%;
}
.topbar {
position: absolute;
height: 32px;
width: 100%;
}
.topbar .heading {
padding-left: 16px;
padding-top: 8px;
line-height: 24px;
font-family: 'Roboto', 'Inter', sans-serif;
font-weight: 600;
font-size: 14px;
}
.selectionOptions {
position: absolute;
top: 32px;
padding-top: 8px;
left: 0px;
width: 100%;
font-family: 'Roboto', 'Inter', sans-serif;
font-size: 14px;
}
.selectionOptions .selectionOption {
cursor: default;
margin-left: 16px;
margin-right: 16px;
padding-top: 8px;
padding-bottom: 8px;
border-top: 1px dotted #303030;
border-left: 0px solid rgba(0, 0, 0, 0);
transition: all 0.1s;
}
.selectionOptions .selectionOption:hover {
border-left: 2px solid #26a69a50;
padding-left: 8px;
}
.selectionOptions .selectionOption:first-child {
border-top: 1px solid rgba(0, 0, 0, 0);
}
.selectionOptions .selectionOption.selectedOption {
border-left: 4px solid #26a69a;
padding-left: 10px;
}
`,
];
public render(): TemplateResult {
return html`
<style></style>
<div class="maincontainer">
<div class="topbar">
<div class="heading">Properties</div>
</div>
<div class="selectionOptions">
${this.selectionOptions.map((selectionOptionArg) => {
return html`
<div
class="selectionOption ${this.selectedOption === selectionOptionArg
? 'selectedOption'
: null}"
@click="${() => {
this.selectOption(selectionOptionArg);
}}"
@contextmenu="${(eventArg: MouseEvent) => {
DeesContextmenu.openContextMenuWithOptions(eventArg, [
{
name: 'property settings',
action: async () => {},
iconName: 'gear',
},
]);
}}"
>
${selectionOptionArg.key}
</div>
`;
})}
</div>
</div>
`;
}
private selectOption(optionArg: interfaces.ISelectionOption) {
this.selectedOption = optionArg;
this.selectedOption.action();
}
firstUpdated() {
this.selectOption(this.selectionOptions[0]);
}
}

View File

@ -0,0 +1,18 @@
import { html } from '@design.estate/dees-element';
export const demoFunc = () => {
return html`
<style>
.demoBox {
position: relative;
background: #000000;
height: 100%;
width: 100%;
padding: 40px;
}
</style>
<div class="demoBox">
<dees-chart-area></dees-chart-area>
</div>
`;
};

View File

@ -0,0 +1,92 @@
import {
DeesElement,
css,
cssManager,
customElement,
html,
property,
type CSSResult,
type TemplateResult,
} from '@design.estate/dees-element';
import * as domtools from '@design.estate/dees-domtools';
import { demoFunc } from './dees-chart-area.demo.js';
import ApexCharts from 'apexcharts';
declare global {
interface HTMLElementTagNameMap {
'dees-chart-area': DeesChartArea;
}
}
@customElement('dees-chart-area')
export class DeesChartArea extends DeesElement {
public static demo = demoFunc;
constructor() {
super();
domtools.elementBasic.setup();
}
public static styles = [cssManager.defaultStyles, css`
.mainbox {
width: 600px;
height: 600px;
background: #222;
border-radius: 3px;
padding: 16px;
padding-top: 32px;
}
`];
public render(): TemplateResult {
return html` <div class="mainbox"></div> `;
}
public async firstUpdated() {
var options = {
series: [
{
name: 'series1',
data: [31, 40, 28, 51, 42, 109, 100],
},
{
name: 'series2',
data: [11, 32, 45, 32, 34, 52, 41],
},
],
chart: {
width: 560,
height: 540,
type: 'area',
},
dataLabels: {
enabled: false,
},
stroke: {
curve: 'smooth',
},
xaxis: {
type: 'datetime',
categories: [
'2018-09-19T00:00:00.000Z',
'2018-09-19T01:30:00.000Z',
'2018-09-19T02:30:00.000Z',
'2018-09-19T03:30:00.000Z',
'2018-09-19T04:30:00.000Z',
'2018-09-19T05:30:00.000Z',
'2018-09-19T06:30:00.000Z',
],
},
tooltip: {
x: {
format: 'dd/MM/yy HH:mm',
},
},
};
var chart = new ApexCharts(this.shadowRoot.querySelector('.mainbox'), options);
chart.render();
}
}

View File

@ -0,0 +1,98 @@
import {
DeesElement,
property,
html,
customElement,
type TemplateResult,
css,
cssManager,
domtools
} from '@design.estate/dees-element';
const deferred = domtools.plugins.smartpromise.defer();
declare global {
interface HTMLElementTagNameMap {
'dees-editormarkdown': DeesEditorMarkdown;
}
}
@customElement('dees-editormarkdown')
export class DeesEditorMarkdown extends DeesElement {
public static demo = () => html`<dees-editormarkdown></dees-editormarkdown>`;
public static styles = [
cssManager.defaultStyles,
css`
.gridcontainer {
position: absolute;
height: 100%;
width: 100%;
display: grid;
grid-template-columns: 60% 40%;
}
.editorContainer {
position: relative;
}
.outletContainer {
background: #111;
color: #fff;
font-family: 'Roboto Slab';
padding: 20px;
overflow-y: scroll;
}
`,
];
public render() {
return html`
<div class="gridcontainer">
<div class="editorContainer">
<dees-editor
.language=${'markdown'}
.content=${`# a test content
This is test content that is of longer form an hopefully starts to wrap when I need it. And yes, it does perfectly. nice.
Test | Hello
--- | ---
Yeah | So good
This is real asset I think. Why would we want to leave that on the table? Can you tell my that?
Why are we here?
Do you know?
> note:
There is something going on.
\`\`\`typescript
const hello = 'yes'
\`\`\`
`}
wordWrap="bounded"
></dees-editor>
</div>
<div class="outletContainer">
<dees-editormarkdownoutlet></dees-editormarkdownoutlet>
</div>
</div>
`;
}
public async firstUpdated(_changedPropertiesArg) {
await super.firstUpdated(_changedPropertiesArg);
const editor = this.shadowRoot.querySelector('dees-editor');
// lets care about wiring the markdown stuff.
const markdownOutlet = this.shadowRoot.querySelector('dees-editormarkdownoutlet');
const smartmarkdownInstance = new domtools.plugins.smartmarkdown.SmartMarkdown();
const mdParsedResult = await smartmarkdownInstance.getMdParsedResultFromMarkdown('loading...')
editor.contentSubject.subscribe(async contentArg => {
await mdParsedResult.updateFromMarkdownString(contentArg)
const html = mdParsedResult.html;
markdownOutlet.updateHtmlText(html);
})
}
}

View File

@ -0,0 +1,42 @@
import { customElement, DeesElement, html, type TemplateResult } from '@design.estate/dees-element';
declare global {
interface HTMLElementTagNameMap {
'dees-editormarkdownoutlet': DeesEditorMarkdownOutlet;
}
}
@customElement('dees-editormarkdownoutlet')
export class DeesEditorMarkdownOutlet extends DeesElement {
// DEMO
public static demo = () => html`<dees-editormarkdownoutlet></dees-editormarkdownoutlet>`;
// INSTANCE
private outlet: HTMLElement;
public render(): TemplateResult {
return html`
<div class="outlet markdown-body">
<h1>Hi there</h1>
</div>
`;
}
public async firstUpdated(_changedProperties: Map<string | number | symbol, unknown>) {
await super.firstUpdated(_changedProperties);
const styleElement = document.createElement('style');
const cssText = await (
await fetch('https://unpkg.com/github-markdown-css@5.1.0/github-markdown-dark.css')
).text();
styleElement.textContent = cssText;
this.shadowRoot.append(styleElement);
}
public async updateHtmlText(htmlTextArg: string) {
await this.updateComplete;
if (!this.outlet) {
this.outlet = this.shadowRoot.querySelector('.outlet');
}
this.outlet.innerHTML = htmlTextArg;
}
}

View File

@ -0,0 +1,126 @@
import {
DeesElement,
property,
html,
customElement,
type TemplateResult,
css,
cssManager,
} from '@design.estate/dees-element';
import * as domtools from '@design.estate/dees-domtools';
import type * as monaco from 'monaco-editor';
declare global {
interface HTMLElementTagNameMap {
'dees-editor': DeesEditor;
}
}
@customElement('dees-editor')
export class DeesEditor extends DeesElement {
// DEMO
public static demo = () => html` <dees-editor></dees-editor> `;
// STATIC
public static monacoDeferred: ReturnType<typeof domtools.plugins.smartpromise.defer>;
// INSTANCE
public editorDeferred = domtools.plugins.smartpromise.defer<monaco.editor.IStandaloneCodeEditor>();
public language = 'typescript';
@property({
type: String
})
public content = "function hello() {\n\talert('Hello world!');\n}";
@property({
type: Object
})
public contentSubject = new domtools.plugins.smartrx.rxjs.Subject<string>();
@property({
type: Boolean
})
public wordWrap: monaco.editor.IStandaloneEditorConstructionOptions['wordWrap'] = 'off';
constructor() {
super();
domtools.DomTools.setupDomTools();
}
public static styles = [
domtools.elementBasic.staticStyles,
css`
:host {
}
* {
box-sizing: border-box;
}
#container {
position: absolute;
height: 100%;
width: 100%;
}
`,
];
public render(): TemplateResult {
return html`
<div class="mainbox">
<div id="container"></div>
</div>
`;
}
public async firstUpdated(
_changedProperties: Map<string | number | symbol, unknown>
): Promise<void> {
super.firstUpdated(_changedProperties);
const container = this.shadowRoot.getElementById('container');
if (!DeesEditor.monacoDeferred) {
DeesEditor.monacoDeferred = domtools.plugins.smartpromise.defer();
const scriptUrl = `https://cdn.jsdelivr.net/npm/monaco-editor/min/vs/loader.js`;
const script = document.createElement('script');
script.src = scriptUrl;
script.onload = () => {
DeesEditor.monacoDeferred.resolve();
};
document.head.appendChild(script);
}
await DeesEditor.monacoDeferred.promise;
(window as any).require.config({
paths: { vs: 'https://cdn.jsdelivr.net/npm/monaco-editor/min/vs' },
});
(window as any).require(['vs/editor/editor.main'], async () => {
const editor = ((window as any).monaco.editor as typeof monaco.editor).create(container, {
value: this.content,
language: this.language,
theme: 'vs-dark',
useShadowDOM: true,
fontSize: 16,
automaticLayout: true,
wordWrap: this.wordWrap
});
this.editorDeferred.resolve(editor);
});
const css = await (
await fetch('https://cdn.jsdelivr.net/npm/monaco-editor/min/vs/editor/editor.main.css')
).text();
const styleElement = document.createElement('style');
styleElement.textContent = css;
this.shadowRoot.append(styleElement);
// editor is setup let do the rest
const editor = await this.editorDeferred.promise;
editor.onDidChangeModelContent(async eventArg => {
this.contentSubject.next(editor.getValue());
});
this.contentSubject.next(editor.getValue());
}
}

View File

@ -101,6 +101,10 @@ export class DeesForm extends DeesElement {
}
}
/**
* collects the form data
* @returns
*/
public async collectFormData() {
const children = this.getFormElements();
const valueObject: { [key: string]: string | number | boolean | any[] } = {};

View File

@ -57,6 +57,7 @@ import {
faMoneyCheckDollar as faMoneyCheckDollarSolid,
faMugHot as faMugHotSolid,
faMinus as faMinusSolid,
faNetworkWired as faNetworkWiredSolid,
faPaperclip as faPaperclipSolid,
faPaste as faPasteSolid,
faPenToSquare as faPenToSquareSolid,
@ -66,6 +67,7 @@ import {
faUsers as faUsersSolid,
faShare as faShareSolid,
faSun as faSunSolid,
faTerminal as faTerminalSolid,
faTrash as faTrashSolid,
faTrashCan as faTrashCanSolid,
faWallet as faWalletSolid,
@ -104,6 +106,7 @@ export const faIcons = {
moneyCheckDollar: faMoneyCheckDollarSolid,
mugHot: faMugHotSolid,
minus: faMinusSolid,
networkWired: faNetworkWiredSolid,
paperclip: faPaperclipSolid,
paste: faPasteRegular,
pasteSolid: faPasteSolid,
@ -114,6 +117,7 @@ export const faIcons = {
share: faShareSolid,
sun: faSunRegular,
sunSolid: faSunSolid,
terminal: faTerminalSolid,
trash: faTrashSolid,
trashSolid: faTrashSolid,
trashCan: faTrashCanRegular,

View File

@ -1,5 +1,21 @@
import { html } from '@design.estate/dees-element';
import type { IView } from './dees-simple-appdash.js';
export const demoFunc = () => html`
<dees-simple-appdash>Hello there</dees-simple-appdash>
<dees-simple-appdash
.viewTabs=${[
{
name: 'View 1',
element: null,
},
{
name: 'View 2',
element: null,
},
{
name: 'View 3',
element: null,
}
] as IView[]}
>Hello there</dees-simple-appdash>
`;

View File

@ -1,4 +1,6 @@
import { demoFunc } from './dees-simple-appdash.demo.js';
import * as colors from './00colors.js';
import {
customElement,
html,
@ -10,7 +12,9 @@ import {
unsafeCSS,
type CSSResult,
state,
domtools,
} from '@design.estate/dees-element';
import { DeesTerminal } from './dees-terminal.js';
declare global {
interface HTMLElementTagNameMap {
@ -18,6 +22,11 @@ declare global {
}
}
export interface IView {
name: string;
element: DeesElement['constructor']['prototype'];
}
@customElement('dees-simple-appdash')
export class DeesSimpleAppDash extends DeesElement {
// STATIC
@ -27,44 +36,147 @@ export class DeesSimpleAppDash extends DeesElement {
@property()
public name = 'Dees Simple Login';
@property()
public viewTabs: IView[] = [];
public static styles = [
cssManager.defaultStyles,
css`
:host {
color: ${cssManager.bdTheme('#333', '#fff')};
color: ${cssManager.bdTheme('#333', '#ccc')};
user-select: none;
display: block;
position: relative;
height: 100%;
}
.maincontainer {
position: absolute;
width: 100%;
height: 100%;
top: 0px;
left: 0px;
overflow: hidden;
}
.appbar {
position: fixed;
top: 0;
height: 40px;
height: 32px;
width: 100%;
background: ${cssManager.bdTheme('#eeeeeb', '#000')};
border-bottom: 1px solid ${cssManager.bdTheme('#ccc', '#333')};
background: ${cssManager.bdTheme('#eeeeeb', '#222')};
border-bottom: 1px solid ${cssManager.bdTheme('#ccc', '#ffffff10')};
font-size: 14px;
line-height: 40px;
line-height: 32px;
font-family: 'Roboto', 'Inter', sans-serif;
padding: 0px 16px;
z-index: 2;
box-shadow: 0px 4px 10px 0px rgba(0, 0, 0, 0.8);
display: grid;
grid-template-columns: min-content 1fr auto;
}
.appbar .viewTabs {
padding: 0px 16px;
display: flex;
flex-direction: row;
align-items: center;
}
.viewTab {
padding: 0px 8px;
}
.viewTab:hover {
background: ${cssManager.bdTheme(colors.bright.blue, colors.dark.blue)};
color: ${cssManager.bdTheme('#000', '#fff')};
}
.viewTab:active {
background: ${cssManager.bdTheme(colors.bright.blueActive, colors.dark.blueActive)};
color: ${cssManager.bdTheme('#000', '#fff')};
}
.appName {
white-space: nowrap;
}
.appActions {
display: flex;
}
.appActions .action {
}
.appActions .action:hover {
color: ${cssManager.bdTheme('#000', '#fff')};
}
.appcontent {
z-index: 1;
position: fixed;
top: 40px;
height: calc(100% - 40px);
bottom: 0px;
top: 32px;
height: calc(100vh - 32px - 24px);
bottom: 24px;
width: 100%;
overflow: auto;
background: ${cssManager.bdTheme('#eeeeeb', '#000')};
}
.controlbar {
color: #fff;
position: absolute;
bottom: 0px;
left: 0px;
width: 100%;
height: 24px;
background: ${cssManager.bdTheme(colors.bright.blueMuted, colors.dark.blueMuted)};
z-index: 2;
display: flex;
justify-content: flex-end;
align-items: center;
flex-direction: row;
}
.control {
width: min-content;
margin-right: 16px;
font-size: 12px;
white-space: nowrap;
}
`,
];
public render(): TemplateResult {
return html`
<div class="appbar">
configvault v1.2.3
</div>
<div class="appcontent">
<slot></slot>
<div class="maincontainer">
<div class="appbar">
<div class="appName">${this.name}</div>
<div class="viewTabs">
${this.viewTabs.map(
(view) => html`
<div class="viewTab" @click=${() => {
this.loadView(view);
}}>${view.name}</div>
`
)}
</div>
<div class="appActions">
<div class="action" @click=${() => {
this.dispatchEvent(new CustomEvent('logout'));
}}>Logout</div>
</div>
</div>
<div class="appcontent">
</div>
<div class="controlbar">
<div class="control">
<dees-icon .iconFA=${'networkWired'}></dees-icon>
</div>
<div class="control" @click=${this.launchTerminal}>
<dees-icon .iconFA=${'terminal'}></dees-icon>
</div>
</div>
</div>
`;
}
@ -72,5 +184,35 @@ export class DeesSimpleAppDash extends DeesElement {
public async firstUpdated(_changedProperties): Promise<void> {
const domtools = await this.domtoolsPromise;
super.firstUpdated(_changedProperties);
await this.loadView(this.viewTabs[0]);
}
public async launchTerminal() {
const maincontainer = this.shadowRoot.querySelector('.maincontainer');
const terminal = new DeesTerminal();
maincontainer.appendChild(terminal);
terminal.style.position = 'absolute';
terminal.style.zIndex = '1';
terminal.style.top = '32px';
terminal.style.left = '0px';
terminal.style.right = '0px';
terminal.style.bottom = '24px';
terminal.style.opacity = '0';
terminal.style.transform = 'translateY(20px)';
terminal.style.transition = 'all 0.2s';
await domtools.plugins.smartdelay.delayFor(0);
terminal.style.opacity = '1';
terminal.style.transform = 'translateY(0px)';
}
private currentView: DeesElement;
public async loadView(viewArg: IView) {
const appcontent = this.shadowRoot.querySelector('.appcontent');
const view = new viewArg.element();
if (this.currentView) {
this.currentView.remove();
}
appcontent.appendChild(view);
this.currentView = view;
}
}

View File

@ -42,7 +42,18 @@ export class DeesSimpleLogin extends DeesElement {
align-items: center; /* aligns vertically */
width: 100%;
height: 100%;
top: 0px;
left: 0px;
}
.slotContainer {
position: absolute;
width: 100%;
height: 100%;
top: 0px;
left: 0px;
}
.login {
min-width: 320px;
min-height: 100px;
@ -92,7 +103,6 @@ export class DeesSimpleLogin extends DeesElement {
const submit = this.shadowRoot.querySelector('dees-form-submit');
form.addEventListener('formData', (event: CustomEvent) => {
this.dispatchEvent(new CustomEvent('login', { detail: event.detail }));
// this.switchToSlottedContent();
});
}

View File

@ -0,0 +1,320 @@
import {
DeesElement,
property,
html,
customElement,
type TemplateResult,
css,
cssManager,
} from '@design.estate/dees-element';
import * as domtools from '@design.estate/dees-domtools';
import * as webcontainer from '@webcontainer/api';
import { Terminal } from 'xterm';
import { FitAddon } from 'xterm-addon-fit';
declare global {
interface HTMLElementTagNameMap {
'dees-terminal': DeesTerminal;
}
}
@customElement('dees-terminal')
export class DeesTerminal extends DeesElement {
public static demo = () => html` <dees-terminal></dees-terminal> `;
// INSTANCE
private resizeObserver: ResizeObserver;
@property()
public setupCommand = `pnpm install @git.zone/tsbuild && clear && echo 'welcome'`;
constructor() {
super();
this.resizeObserver = new ResizeObserver((entries) => {
for (const entry of entries) {
// Handle the resize event
console.log(`Terminal Resized`);
this.handleResize();
}
});
}
public static styles = [
domtools.elementBasic.staticStyles,
css`
:host {
padding: 20px;
background: #000;
position: absolute;
height: 100%;
width: 100%;
}
* {
box-sizing: border-box;
}
#container {
position: absolute;
height: calc(100% - 40px);
width: calc(100% - 40px);
}
/**
* Copyright (c) 2014 The xterm.js authors. All rights reserved.
* Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
* https://github.com/chjj/term.js
* @license MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* Originally forked from (with the author's permission):
* Fabrice Bellard's javascript vt100 for jslinux:
* http://bellard.org/jslinux/
* Copyright (c) 2011 Fabrice Bellard
* The original design remains. The terminal itself
* has been extended to include xterm CSI codes, among
* other features.
*/
/**
* Default styles for xterm.js
*/
.xterm {
font-feature-settings: 'liga' 0;
position: relative;
user-select: none;
-ms-user-select: none;
-webkit-user-select: none;
}
.xterm.focus,
.xterm:focus {
outline: none;
}
.xterm .xterm-helpers {
position: absolute;
top: 0;
/**
* The z-index of the helpers must be higher than the canvases in order for
* IMEs to appear on top.
*/
z-index: 5;
}
.xterm .xterm-helper-textarea {
padding: 0;
border: 0;
margin: 0;
/* Move textarea out of the screen to the far left, so that the cursor is not visible */
position: absolute;
opacity: 0;
left: -9999em;
top: 0;
width: 0;
height: 0;
z-index: -5;
/** Prevent wrapping so the IME appears against the textarea at the correct position */
white-space: nowrap;
overflow: hidden;
resize: none;
}
.xterm .composition-view {
/* TODO: Composition position got messed up somewhere */
background: #000;
color: #fff;
display: none;
position: absolute;
white-space: nowrap;
z-index: 1;
}
.xterm .composition-view.active {
display: block;
}
.xterm .xterm-viewport {
/* On OS X this is required in order for the scroll bar to appear fully opaque */
background-color: #000;
overflow-y: scroll;
cursor: default;
position: absolute;
right: 0;
left: 0;
top: 0;
bottom: 0;
}
.xterm .xterm-screen {
position: relative;
}
.xterm .xterm-screen canvas {
position: absolute;
left: 0;
top: 0;
}
.xterm .xterm-scroll-area {
visibility: hidden;
}
.xterm-char-measure-element {
display: inline-block;
visibility: hidden;
position: absolute;
top: 0;
left: -9999em;
line-height: normal;
}
.xterm {
cursor: text;
}
.xterm.enable-mouse-events {
/* When mouse events are enabled (eg. tmux), revert to the standard pointer cursor */
cursor: default;
}
.xterm.xterm-cursor-pointer {
cursor: pointer;
}
.xterm.column-select.focus {
/* Column selection mode */
cursor: crosshair;
}
.xterm .xterm-accessibility,
.xterm .xterm-message {
position: absolute;
left: 0;
top: 0;
bottom: 0;
right: 0;
z-index: 10;
color: transparent;
}
.xterm .live-region {
position: absolute;
left: -9999px;
width: 1px;
height: 1px;
overflow: hidden;
}
.xterm-dim {
opacity: 0.5;
}
.xterm-underline {
text-decoration: underline;
}
`,
];
public render(): TemplateResult {
return html`
<div class="mainbox">
<div id="container"></div>
</div>
`;
}
private fitAddon: FitAddon;
public async firstUpdated(
_changedProperties: Map<string | number | symbol, unknown>
): Promise<void> {
const domtools = await this.domtoolsPromise;
super.firstUpdated(_changedProperties);
const container = this.shadowRoot.getElementById('container');
const term = new Terminal({
convertEol: true,
cursorBlink: true,
});
this.fitAddon = new FitAddon();
term.loadAddon(this.fitAddon);
// Open the terminal in #terminal-container
term.open(container);
// Make the terminal's size and geometry fit the size of #terminal-container
this.fitAddon.fit();
term.write(`dees-terminal custom terminal. \r\n$ `);
// lets start the webcontainer
// Call only once
const webcontainerInstance = await webcontainer.WebContainer.boot();
const shellProcess = await webcontainerInstance.spawn('jsh');
shellProcess.output.pipeTo(
new WritableStream({
write(data) {
term.write(data);
},
})
);
const input = shellProcess.input.getWriter();
term.onData((data) => {
input.write(data);
});
await this.waitForPrompt(term, '~/');
input.write(this.setupCommand);
input.write(`\n`);
}
async connectedCallback(): Promise<void> {
await super.connectedCallback();
this.resizeObserver.observe(this);
}
async disconnectedCallback(): Promise<void> {
this.resizeObserver.unobserve(this);
await super.disconnectedCallback();
}
handleResize() {
this.fitAddon.fit();
}
private async waitForPrompt(term: Terminal, prompt: string): Promise<void> {
return new Promise<void>((resolve) => {
const checkPrompt = () => {
const lines = term.buffer.active;
for (let i = 0; i < lines.length; i++) {
const line = lines.getLine(i);
if (line && line.translateToString().includes(prompt)) {
resolve();
return;
}
}
setTimeout(checkPrompt, 100); // check every 100 ms
};
checkPrompt();
});
}
}

View File

@ -1,9 +1,19 @@
export * from './dees-appui-activitylog.js';
export * from './dees-appui-appbar.js';
export * from './dees-appui-base.js';
export * from './dees-appui-maincontent.js';
export * from './dees-appui-mainmenu.js';
export * from './dees-appui-mainselector.js';
export * from './dees-button-exit.js';
export * from './dees-button.js';
export * from './dees-chart-area.js';
export * from './dees-chips.js';
export * from './dees-contextmenu.js';
export * from './dees-dataview-codebox.js';
export * from './dees-dataview-statusobject.js';
export * from './dees-editor.js';
export * from './dees-editor-markdown.js';
export * from './dees-editor-markdownoutlet.js';
export * from './dees-form-submit.js';
export * from './dees-form.js';
export * from './dees-hint.js';
@ -29,6 +39,7 @@ export * from './dees-speechbubble.js';
export * from './dees-spinner.js';
export * from './dees-stepper.js';
export * from './dees-table.js';
export * from './dees-terminal.js';
export * from './dees-toast.js';
export * from './dees-updater.js';
export * from './dees-windowcontrols.js';

View File

@ -0,0 +1,2 @@
export * from './tab.js';
export * from './selectionoption.js';

View File

@ -0,0 +1,4 @@
export interface ISelectionOption {
key: string;
action: () => void;
}

View File

@ -0,0 +1,5 @@
export interface ITab {
key: string;
iconName?: string;
action: () => void;
}