diff --git a/ts_web/00_commitinfo_data.ts b/ts_web/00_commitinfo_data.ts index 26bf3b8..ad8cf9d 100644 --- a/ts_web/00_commitinfo_data.ts +++ b/ts_web/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@design.estate/dees-catalog', - version: '1.0.276', + version: '1.0.277', description: 'website for lossless.com' } diff --git a/ts_web/elements/dees-appui-activitylog.ts b/ts_web/elements/dees-appui-activitylog.ts new file mode 100644 index 0000000..9798709 --- /dev/null +++ b/ts_web/elements/dees-appui-activitylog.ts @@ -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``; + + // 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} + +
+
+
Activity Log
+
+
+
streaming...
+
{ + DeesContextmenu.openContextMenuWithOptions(eventArg, [ + { + name: 'app settings', + action: async () => {}, + }, + { + name: 'account settings', + action: async () => {}, + }, + { + name: 'logout', + action: async () => {}, + }, + ]); + }}> + 22:01: Max Mustermann logged in +
+
+ 22:02: Max Mustermann viewed an invoice +
+
+ 22:03: Max Mustermann added a new contact +
+
+ 22:04: Max Mustermann updated account settings +
+
+ 22:05: Max Mustermann logged out +
+
+ 22:06: Max Mustermann logged in +
+
+ 22:07: Max Mustermann created a new invoice +
+
+ 22:08: Max Mustermann sent an invoice +
+
+ 22:09: Max Mustermann viewed reports +
+
+ 22:10: Max Mustermann logged out +
+
+ 22:11: Max Mustermann logged in +
+
+ 22:12: Max Mustermann deleted an invoice +
+
+ 22:13: Max Mustermann contacted support +
+
+ 22:14: Max Mustermann added a new user +
+
+ 22:15: Max Mustermann changed password +
+
+ 22:16: Max Mustermann logged out +
+
+ 22:17: Max Mustermann logged in +
+
+ 22:18: Max Mustermann archived an invoice +
+
+ 22:19: Max Mustermann approved a payment +
+
+ 22:20: Max Mustermann logged out +
+
loading more...
+
+ +
+
+
+ `; + } +} diff --git a/ts_web/elements/dees-appui-appbar.ts b/ts_web/elements/dees-appui-appbar.ts new file mode 100644 index 0000000..1a55812 --- /dev/null +++ b/ts_web/elements/dees-appui-appbar.ts @@ -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``; + + 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` + + +
+ `; + } +} diff --git a/ts_web/elements/dees-appui-base.ts b/ts_web/elements/dees-appui-base.ts new file mode 100644 index 0000000..deff60b --- /dev/null +++ b/ts_web/elements/dees-appui-base.ts @@ -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``; + + 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` + + +
+ + + + +
+ `; + } +} diff --git a/ts_web/elements/dees-appui-maincontent.ts b/ts_web/elements/dees-appui-maincontent.ts new file mode 100644 index 0000000..7ffda85 --- /dev/null +++ b/ts_web/elements/dees-appui-maincontent.ts @@ -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``; + + // 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` + +
+
+
+ ${this.tabs.map((tabArg) => { + return html` +
+ ${tabArg.key} +
+ `; + })} +
+
+
+
+ `; + } + + /** + * 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]); + } +} diff --git a/ts_web/elements/dees-appui-mainmenu.ts b/ts_web/elements/dees-appui-mainmenu.ts new file mode 100644 index 0000000..e32ac77 --- /dev/null +++ b/ts_web/elements/dees-appui-mainmenu.ts @@ -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``; + + // 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` +
{ + DeesContextmenu.openContextMenuWithOptions(eventArg, [{ + name: 'app settings', + action: async () => {}, + iconName: 'gear', + }]) + }}> +
+ ${this.tabs.map((tabArg) => { + return html` +
+ +
+ `; + })} +
+
+
+ `; + } + + 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]); + } +} diff --git a/ts_web/elements/dees-appui-mainselector.ts b/ts_web/elements/dees-appui-mainselector.ts new file mode 100644 index 0000000..0acec91 --- /dev/null +++ b/ts_web/elements/dees-appui-mainselector.ts @@ -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``; + + // 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` + +
+
+
Properties
+
+
+ ${this.selectionOptions.map((selectionOptionArg) => { + return html` +
+ ${selectionOptionArg.key} +
+ `; + })} +
+
+ `; + } + + private selectOption(optionArg: interfaces.ISelectionOption) { + this.selectedOption = optionArg; + this.selectedOption.action(); + } + + firstUpdated() { + this.selectOption(this.selectionOptions[0]); + } +} diff --git a/ts_web/elements/index.ts b/ts_web/elements/index.ts index ddb2010..d230036 100644 --- a/ts_web/elements/index.ts +++ b/ts_web/elements/index.ts @@ -1,3 +1,9 @@ +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-chips.js'; diff --git a/ts_web/elements/interfaces/index.ts b/ts_web/elements/interfaces/index.ts new file mode 100644 index 0000000..4cced0a --- /dev/null +++ b/ts_web/elements/interfaces/index.ts @@ -0,0 +1,2 @@ +export * from './tab.js'; +export * from './selectionoption.js'; diff --git a/ts_web/elements/interfaces/selectionoption.ts b/ts_web/elements/interfaces/selectionoption.ts new file mode 100644 index 0000000..32f8c6b --- /dev/null +++ b/ts_web/elements/interfaces/selectionoption.ts @@ -0,0 +1,4 @@ +export interface ISelectionOption { + key: string; + action: () => void; +} \ No newline at end of file diff --git a/ts_web/elements/interfaces/tab.ts b/ts_web/elements/interfaces/tab.ts new file mode 100644 index 0000000..29e91d5 --- /dev/null +++ b/ts_web/elements/interfaces/tab.ts @@ -0,0 +1,5 @@ +export interface ITab { + key: string; + iconName?: string; + action: () => void; +}