Compare commits

...

128 Commits

Author SHA1 Message Date
a736ee9800 1.0.221 2023-10-12 15:43:11 +02:00
bea2047092 fix(core): update 2023-10-12 15:43:10 +02:00
7d98ac8f38 1.0.220 2023-10-11 12:24:13 +02:00
32244bb450 fix(core): update 2023-10-11 12:24:12 +02:00
b154631c77 1.0.219 2023-10-07 20:01:50 +02:00
466a24ac10 fix(core): update 2023-10-07 20:01:49 +02:00
7db91a2fe6 1.0.218 2023-10-07 19:33:05 +02:00
46652dec6f fix(core): update 2023-10-07 19:33:04 +02:00
50e591b80c 1.0.217 2023-10-05 22:42:34 +02:00
6710a163a9 fix(core): update 2023-10-05 22:42:33 +02:00
a39f43f79a 1.0.216 2023-10-05 14:37:00 +02:00
964520a2f9 fix(core): update 2023-10-05 14:36:59 +02:00
6e680085a4 1.0.215 2023-09-22 20:02:49 +02:00
286a843b67 fix(core): update 2023-09-22 20:02:48 +02:00
df7c5ebafc 1.0.214 2023-09-22 19:42:23 +02:00
9927323a9d fix(core): update 2023-09-22 19:42:23 +02:00
66f3e66c8b 1.0.213 2023-09-22 19:04:03 +02:00
c68b0c5090 fix(core): update 2023-09-22 19:04:02 +02:00
53ac03507d 1.0.212 2023-09-22 13:15:34 +02:00
0031b51bcf fix(core): update 2023-09-22 13:15:34 +02:00
67a8c6e591 1.0.211 2023-09-20 18:57:54 +02:00
806390a068 fix(core): update 2023-09-20 18:57:54 +02:00
508b18bc3b 1.0.210 2023-09-18 15:12:58 +02:00
c2499ea507 fix(core): update 2023-09-18 15:12:57 +02:00
c0c91aec94 1.0.209 2023-09-17 21:38:02 +02:00
a27008a295 fix(core): update 2023-09-17 21:38:02 +02:00
7e11627618 1.0.208 2023-09-17 10:29:23 +02:00
968ce63a53 fix(core): update 2023-09-17 10:29:22 +02:00
7c0eb3290f 1.0.207 2023-09-16 14:31:03 +02:00
62403625ba fix(core): update 2023-09-16 14:31:03 +02:00
9a34b03540 1.0.206 2023-09-15 20:51:04 +02:00
8bb63df7e3 fix(core): update 2023-09-15 20:51:03 +02:00
65cd73845a 1.0.205 2023-09-15 20:11:52 +02:00
8534bc254b fix(core): update 2023-09-15 20:11:51 +02:00
2a2fd324a0 1.0.204 2023-09-15 19:07:35 +02:00
58e3de2559 fix(core): update 2023-09-15 19:07:34 +02:00
c30736870d 1.0.203 2023-09-15 19:03:19 +02:00
cfd48de885 fix(core): update 2023-09-15 19:03:18 +02:00
462df2b648 1.0.202 2023-09-15 17:27:36 +02:00
f64da93cf9 fix(core): update 2023-09-15 17:27:35 +02:00
a55db621ef 1.0.201 2023-09-14 19:46:10 +02:00
c033bdfc3b fix(core): update 2023-09-14 19:46:09 +02:00
2610e56ec1 1.0.200 2023-09-14 19:43:27 +02:00
08aa9e3fe4 fix(core): update 2023-09-14 19:43:26 +02:00
411ae7ee07 1.0.199 2023-09-13 21:14:06 +02:00
41700c1eb1 fix(core): update 2023-09-13 21:14:05 +02:00
8d7bac9793 1.0.198 2023-09-13 21:13:48 +02:00
0229eefa4d fix(core): update 2023-09-13 21:13:47 +02:00
61f646743a 1.0.197 2023-09-13 19:15:54 +02:00
e3babde7e8 fix(core): update 2023-09-13 19:15:53 +02:00
c389e43e93 1.0.196 2023-09-13 18:12:02 +02:00
1511db4eea fix(core): update 2023-09-13 18:12:01 +02:00
d713756034 1.0.195 2023-09-13 16:46:01 +02:00
17d224332d fix(core): update 2023-09-13 16:46:00 +02:00
32dd5e769b 1.0.194 2023-09-13 16:25:55 +02:00
12ace00a90 fix(core): update 2023-09-13 16:25:54 +02:00
bbc09330c9 1.0.193 2023-09-13 13:41:57 +02:00
82ead7bd1a fix(core): update 2023-09-13 13:41:56 +02:00
f8f9b150b8 1.0.192 2023-09-13 01:37:03 +02:00
494e8b7e26 fix(core): update 2023-09-13 01:37:02 +02:00
c76d364071 1.0.191 2023-09-12 13:44:07 +02:00
760e0085f7 fix(core): update 2023-09-12 13:44:07 +02:00
6890ca1f1f 1.0.190 2023-09-12 13:42:56 +02:00
9ca000cf06 fix(core): update 2023-09-12 13:42:55 +02:00
1c0f5129a9 1.0.189 2023-09-09 13:34:46 +02:00
69e17949f4 fix(core): update 2023-09-09 13:34:46 +02:00
bcfd3495dd 1.0.188 2023-09-08 11:44:04 +02:00
03a46a72c5 fix(core): update 2023-09-08 11:44:03 +02:00
2465ce5f9b 1.0.187 2023-09-07 18:34:39 +02:00
00ac83f205 fix(core): update 2023-09-07 18:34:38 +02:00
67065b1ffb 1.0.186 2023-09-07 02:57:31 +02:00
783c10479f fix(core): update 2023-09-07 02:57:30 +02:00
d4eae1cd9e 1.0.185 2023-09-04 19:29:39 +02:00
4e674f67c5 fix(core): update 2023-09-04 19:29:39 +02:00
889a543780 1.0.184 2023-09-04 19:28:50 +02:00
fc5f3a9576 fix(core): update 2023-09-04 19:28:50 +02:00
66644364b5 1.0.183 2023-09-02 14:05:34 +02:00
51febdae06 fix(core): update 2023-09-02 14:05:33 +02:00
745ff299dc 1.0.182 2023-09-01 16:44:14 +02:00
3606d60ba6 fix(core): update 2023-09-01 16:44:13 +02:00
8970a79141 1.0.181 2023-09-01 14:21:16 +02:00
566a7ce148 fix(core): update 2023-09-01 14:21:15 +02:00
362bef15e3 1.0.180 2023-08-30 11:27:47 +02:00
446c494863 fix(core): update 2023-08-30 11:27:46 +02:00
dbe2f2f217 1.0.179 2023-08-28 09:59:13 +02:00
02ca92a431 fix(core): update 2023-08-28 09:59:12 +02:00
a9015e787c 1.0.178 2023-08-28 09:49:52 +02:00
9cd28fa819 fix(core): update 2023-08-28 09:49:51 +02:00
7b3793e943 1.0.177 2023-08-26 12:15:49 +02:00
a22c04d98d fix(core): update 2023-08-26 12:15:49 +02:00
5367512292 1.0.176 2023-08-20 17:11:41 +02:00
9c387f8ace fix(core): update 2023-08-20 17:11:41 +02:00
c3ec288d09 1.0.175 2023-08-19 18:56:33 +02:00
9d952afebb fix(core): update 2023-08-19 18:56:32 +02:00
621262fde7 1.0.174 2023-08-19 11:47:45 +02:00
e3e79d9a11 fix(core): update 2023-08-19 11:47:45 +02:00
d08a92814e 1.0.173 2023-08-08 01:10:03 +02:00
a6f277250e fix(core): update 2023-08-08 01:10:02 +02:00
09cb82d587 1.0.172 2023-08-07 20:02:19 +02:00
316e2a0b27 fix(core): update 2023-08-07 20:02:18 +02:00
e0d2679801 1.0.171 2023-08-07 19:13:30 +02:00
107800a057 fix(core): update 2023-08-07 19:13:29 +02:00
4ee8512ee4 1.0.170 2023-04-12 02:47:46 +02:00
f75a3714ae fix(core): update 2023-04-12 02:47:45 +02:00
d6047f2e78 1.0.169 2023-04-12 00:40:40 +02:00
03769c8412 fix(core): update 2023-04-12 00:40:40 +02:00
1a782eb4ee 1.0.168 2023-04-10 00:26:55 +02:00
a27adf25cb fix(core): update 2023-04-10 00:26:55 +02:00
96e237b9af 1.0.167 2023-04-10 00:18:17 +02:00
710e06b2f1 fix(core): update 2023-04-10 00:18:16 +02:00
a3bc25c4ac 1.0.166 2023-04-10 00:17:38 +02:00
ee5b712a37 fix(core): update 2023-04-10 00:17:38 +02:00
879ae5ad91 1.0.165 2023-04-07 23:55:56 +02:00
2bbda416b2 fix(core): update 2023-04-07 23:55:55 +02:00
de88957857 1.0.164 2023-04-07 23:46:09 +02:00
aa0c63d569 fix(core): update 2023-04-07 23:46:08 +02:00
d843f27fd3 1.0.163 2023-04-06 17:41:46 +02:00
a26755b7d3 fix(core): update 2023-04-06 17:41:46 +02:00
345a562a21 1.0.162 2023-04-06 17:32:50 +02:00
3fae99554d fix(core): update 2023-04-06 17:32:49 +02:00
ed30ed3f8f 1.0.161 2023-04-06 17:29:08 +02:00
beef47959b fix(core): update 2023-04-06 17:29:07 +02:00
aec2cf18fd 1.0.160 2023-04-05 18:57:13 +02:00
0f45633666 fix(core): update 2023-04-05 18:57:12 +02:00
8588888ce7 1.0.159 2023-04-05 17:17:02 +02:00
2a62a635cd fix(core): update 2023-04-05 17:17:02 +02:00
0eb2557956 1.0.158 2023-04-05 17:00:44 +02:00
9960bf7018 fix(core): update 2023-04-05 17:00:44 +02:00
54 changed files with 4452 additions and 1389 deletions

View File

@ -0,0 +1,66 @@
name: Default (not tags)
on:
push:
tags-ignore:
- '**'
env:
IMAGE: registry.gitlab.com/hosttoday/ht-docker-node:npmci
NPMCI_COMPUTED_REPOURL: https://${{gitea.repository_owner}}:${{secrets.GITEA_TOKEN}}@gitea.lossless.digital/${{gitea.repository}}.git
NPMCI_TOKEN_NPM: ${{secrets.NPMCI_TOKEN_NPM}}
NPMCI_TOKEN_NPM2: ${{secrets.NPMCI_TOKEN_NPM2}}
NPMCI_GIT_GITHUBTOKEN: ${{secrets.NPMCI_GIT_GITHUBTOKEN}}
NPMCI_URL_CLOUDLY: ${{secrets.NPMCI_URL_CLOUDLY}}
jobs:
security:
runs-on: ubuntu-latest
continue-on-error: true
container:
image: ${{ env.IMAGE }}
steps:
- uses: actions/checkout@v3
- name: Install pnpm and npmci
run: |
pnpm install -g pnpm
pnpm install -g @shipzone/npmci
- name: Run npm prepare
run: npmci npm prepare
- name: Audit production dependencies
run: |
npmci command npm config set registry https://registry.npmjs.org
npmci command pnpm audit --audit-level=high --prod
continue-on-error: true
- name: Audit development dependencies
run: |
npmci command npm config set registry https://registry.npmjs.org
npmci command pnpm audit --audit-level=high --dev
continue-on-error: true
test:
if: ${{ always() }}
needs: security
runs-on: ubuntu-latest
container:
image: ${{ env.IMAGE }}
steps:
- uses: actions/checkout@v3
- name: Test stable
run: |
npmci node install stable
npmci npm install
npmci npm test
- name: Test build
run: |
npmci node install stable
npmci npm install
npmci npm build

View File

@ -0,0 +1,124 @@
name: Default (tags)
on:
push:
tags:
- '*'
env:
IMAGE: registry.gitlab.com/hosttoday/ht-docker-node:npmci
NPMCI_COMPUTED_REPOURL: https://${{gitea.repository_owner}}:${{secrets.GITEA_TOKEN}}@gitea.lossless.digital/${{gitea.repository}}.git
NPMCI_TOKEN_NPM: ${{secrets.NPMCI_TOKEN_NPM}}
NPMCI_TOKEN_NPM2: ${{secrets.NPMCI_TOKEN_NPM2}}
NPMCI_GIT_GITHUBTOKEN: ${{secrets.NPMCI_GIT_GITHUBTOKEN}}
NPMCI_URL_CLOUDLY: ${{secrets.NPMCI_URL_CLOUDLY}}
jobs:
security:
runs-on: ubuntu-latest
continue-on-error: true
container:
image: ${{ env.IMAGE }}
steps:
- uses: actions/checkout@v3
- name: Prepare
run: |
pnpm install -g pnpm
pnpm install -g @shipzone/npmci
npmci npm prepare
- name: Audit production dependencies
run: |
npmci command npm config set registry https://registry.npmjs.org
npmci command pnpm audit --audit-level=high --prod
continue-on-error: true
- name: Audit development dependencies
run: |
npmci command npm config set registry https://registry.npmjs.org
npmci command pnpm audit --audit-level=high --dev
continue-on-error: true
test:
if: ${{ always() }}
needs: security
runs-on: ubuntu-latest
container:
image: ${{ env.IMAGE }}
steps:
- uses: actions/checkout@v3
- name: Prepare
run: |
pnpm install -g pnpm
pnpm install -g @shipzone/npmci
npmci npm prepare
- name: Test stable
run: |
npmci node install stable
npmci npm install
npmci npm test
- name: Test build
run: |
npmci node install stable
npmci npm install
npmci npm build
release:
needs: test
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
container:
image: ${{ env.IMAGE }}
steps:
- uses: actions/checkout@v3
- name: Prepare
run: |
pnpm install -g pnpm
pnpm install -g @shipzone/npmci
npmci npm prepare
- name: Release
run: |
npmci node install stable
npmci npm publish
metadata:
needs: test
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
container:
image: ${{ env.IMAGE }}
continue-on-error: true
steps:
- uses: actions/checkout@v3
- name: Prepare
run: |
pnpm install -g pnpm
pnpm install -g @shipzone/npmci
npmci npm prepare
- name: Code quality
run: |
npmci command npm install -g typescript
npmci npm install
- name: Trigger
run: npmci trigger
- name: Build docs and upload artifacts
run: |
npmci node install stable
npmci npm install
pnpm install -g @gitzone/tsdoc
npmci command tsdoc
continue-on-error: true

View File

@ -10,11 +10,9 @@
/>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="preconnect" href="https://rsms.me/">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://rsms.me/inter/inter.css">
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200&family=Courier+Prime:ital,wght@0,400;0,700;1,400;1,700&display=swap" rel="stylesheet">
<!--Lets load standard fonts-->
<link rel="preconnect" href="https://assetbroker.lossless.one/" crossorigin>
<link rel="stylesheet" href="https://assetbroker.lossless.one/fonts/fonts.css">
<style>
body {

View File

@ -1,6 +1,6 @@
// dees tools
import * as deesWccTools from '@designestate/dees-wcctools';
import * as deesDomTools from '@designestate/dees-domtools';
import * as deesWccTools from '@design.estate/dees-wcctools';
import * as deesDomTools from '@design.estate/dees-domtools';
// elements and pages
import * as elements from '../ts_web/elements/index.js';

View File

@ -3,10 +3,10 @@
"projectType": "wcc",
"module": {
"githost": "gitlab.com",
"gitscope": "designestate",
"gitscope": "design.estate",
"gitrepo": "dees-catalog",
"description": "a webcomponents catalog for handling daily stuff on the web",
"npmPackagename": "@designestate/dees-catalog",
"npmPackagename": "@design.estate/dees-catalog",
"license": "MIT",
"projectDomain": "design.estate"
}

View File

@ -1,6 +1,6 @@
{
"name": "@designestate/dees-catalog",
"version": "1.0.157",
"name": "@design.estate/dees-catalog",
"version": "1.0.221",
"private": false,
"description": "website for lossless.com",
"main": "dist_ts_web/index.js",
@ -15,27 +15,27 @@
"author": "Lossless GmbH",
"license": "MIT",
"dependencies": {
"@designestate/dees-domtools": "^2.0.30",
"@designestate/dees-element": "^2.0.20",
"@designestate/dees-wcctools": "^1.0.76",
"@fortawesome/fontawesome-svg-core": "^6.4.0",
"@fortawesome/free-brands-svg-icons": "^6.4.0",
"@fortawesome/free-regular-svg-icons": "^6.4.0",
"@fortawesome/free-solid-svg-icons": "^6.4.0",
"@pushrocks/smartpromise": "^4.0.0",
"@pushrocks/smartstring": "^4.0.5",
"@tsclass/tsclass": "^4.0.36",
"highlight.js": "11.7.0",
"pdfjs-dist": "^2.15.349"
"@design.estate/dees-domtools": "^2.0.51",
"@design.estate/dees-element": "^2.0.29",
"@design.estate/dees-wcctools": "^1.0.81",
"@fortawesome/fontawesome-svg-core": "^6.4.2",
"@fortawesome/free-brands-svg-icons": "^6.4.2",
"@fortawesome/free-regular-svg-icons": "^6.4.2",
"@fortawesome/free-solid-svg-icons": "^6.4.2",
"@push.rocks/smartpromise": "^4.0.3",
"@push.rocks/smartstring": "^4.0.9",
"@tsclass/tsclass": "^4.0.43",
"highlight.js": "11.8.0",
"pdfjs-dist": "^3.11.174"
},
"devDependencies": {
"@gitzone/tsbuild": "^2.1.65",
"@gitzone/tsbundle": "^2.0.7",
"@gitzone/tstest": "^1.0.74",
"@gitzone/tsbuild": "^2.1.66",
"@gitzone/tsbundle": "^2.0.8",
"@gitzone/tstest": "^1.0.77",
"@gitzone/tswatch": "^2.0.7",
"@pushrocks/projectinfo": "^5.0.1",
"@pushrocks/tapbundle": "^5.0.4",
"@types/node": "^18.15.11"
"@push.rocks/projectinfo": "^5.0.2",
"@push.rocks/tapbundle": "^5.0.15",
"@types/node": "^20.8.3"
},
"files": [
"ts/**/*",

3401
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -1,26 +1,26 @@
# @designestate/dees-catalog
# @design.estate/dees-catalog
a webcomponents catalog for handling daily stuff on the web
## Availabililty and Links
* [npmjs.org (npm package)](https://www.npmjs.com/package/@designestate/dees-catalog)
* [gitlab.com (source)](https://gitlab.com/designestate/dees-catalog)
* [github.com (source mirror)](https://github.com/designestate/dees-catalog)
* [docs (typedoc)](https://designestate.gitlab.io/dees-catalog/)
* [npmjs.org (npm package)](https://www.npmjs.com/package/@design.estate/dees-catalog)
* [gitlab.com (source)](https://gitlab.com/design.estate/dees-catalog)
* [github.com (source mirror)](https://github.com/design.estate/dees-catalog)
* [docs (typedoc)](https://design.estate.gitlab.io/dees-catalog/)
## Status for master
Status Category | Status Badge
-- | --
GitLab Pipelines | [![pipeline status](https://gitlab.com/designestate/dees-catalog/badges/master/pipeline.svg)](https://lossless.cloud)
GitLab Pipline Test Coverage | [![coverage report](https://gitlab.com/designestate/dees-catalog/badges/master/coverage.svg)](https://lossless.cloud)
npm | [![npm downloads per month](https://badgen.net/npm/dy/@designestate/dees-catalog)](https://lossless.cloud)
Snyk | [![Known Vulnerabilities](https://badgen.net/snyk/designestate/dees-catalog)](https://lossless.cloud)
GitLab Pipelines | [![pipeline status](https://gitlab.com/design.estate/dees-catalog/badges/master/pipeline.svg)](https://lossless.cloud)
GitLab Pipline Test Coverage | [![coverage report](https://gitlab.com/design.estate/dees-catalog/badges/master/coverage.svg)](https://lossless.cloud)
npm | [![npm downloads per month](https://badgen.net/npm/dy/@design.estate/dees-catalog)](https://lossless.cloud)
Snyk | [![Known Vulnerabilities](https://badgen.net/snyk/design.estate/dees-catalog)](https://lossless.cloud)
TypeScript Support | [![TypeScript](https://badgen.net/badge/TypeScript/>=%203.x/blue?icon=typescript)](https://lossless.cloud)
node Support | [![node](https://img.shields.io/badge/node->=%2010.x.x-blue.svg)](https://nodejs.org/dist/latest-v10.x/docs/api/)
Code Style | [![Code Style](https://badgen.net/badge/style/prettier/purple)](https://lossless.cloud)
PackagePhobia (total standalone install weight) | [![PackagePhobia](https://badgen.net/packagephobia/install/@designestate/dees-catalog)](https://lossless.cloud)
PackagePhobia (package size on registry) | [![PackagePhobia](https://badgen.net/packagephobia/publish/@designestate/dees-catalog)](https://lossless.cloud)
BundlePhobia (total size when bundled) | [![BundlePhobia](https://badgen.net/bundlephobia/minzip/@designestate/dees-catalog)](https://lossless.cloud)
PackagePhobia (total standalone install weight) | [![PackagePhobia](https://badgen.net/packagephobia/install/@design.estate/dees-catalog)](https://lossless.cloud)
PackagePhobia (package size on registry) | [![PackagePhobia](https://badgen.net/packagephobia/publish/@design.estate/dees-catalog)](https://lossless.cloud)
BundlePhobia (total size when bundled) | [![BundlePhobia](https://badgen.net/bundlephobia/minzip/@design.estate/dees-catalog)](https://lossless.cloud)
## Usage

View File

@ -1,4 +1,4 @@
import { tap, expect, webhelpers } from '@pushrocks/tapbundle';
import { tap, expect, webhelpers } from '@push.rocks/tapbundle';
import * as deesCatalog from '../ts_web';

View File

@ -2,7 +2,7 @@
* autocreated commitinfo by @pushrocks/commitinfo
*/
export const commitinfo = {
name: '@designestate/dees-catalog',
version: '1.0.157',
name: '@design.estate/dees-catalog',
version: '1.0.221',
description: 'website for lossless.com'
}

View File

@ -3,11 +3,12 @@ import {
customElement,
DeesElement,
html,
TemplateResult,
type TemplateResult,
css,
type CSSResult,
state,
property
} from '@designestate/dees-element';
} from '@design.estate/dees-element';
@customElement('dees-button-exit')
export class DeesButtonExit extends DeesElement {

View File

@ -0,0 +1,15 @@
import { html } from '@design.estate/dees-element';
export const demoFunc = () => html`
<dees-button>This is a slotted Text</dees-button>
<p>
<dees-button text="Highlighted: This text shows" type="highlighted">Highlighted</dees-button>
</p>
<p><dees-button type="discreet">This is discreete button</dees-button></p>
<p><dees-button disabled>This is a disabled button</dees-button></p>
<p><dees-button type="big">This is a slotted Text</dees-button></p>
<p><dees-button status="normal">Normal Status</dees-button></p>
<p><dees-button disabled status="pending">Pending Status</dees-button></p>
<p><dees-button disabled status="success">Success Status</dees-button></p>
<p><dees-button disabled status="error">Error Status</dees-button></p>
`;

View File

@ -1,15 +1,17 @@
import { demoFunc } from './dees-button.demo.js';
import {
customElement,
html,
DeesElement,
property,
TemplateResult,
type TemplateResult,
cssManager,
css,
type CSSResult,
unsafeCSS,
} from '@designestate/dees-element';
} from '@design.estate/dees-element';
import * as domtools from '@designestate/dees-domtools';
import * as domtools from '@design.estate/dees-domtools';
declare global {
interface HTMLElementTagNameMap {
@ -19,17 +21,7 @@ declare global {
@customElement('dees-button')
export class DeesButton extends DeesElement {
public static demo = () => html`
<dees-button>This is a slotted Text</dees-button>
<p><dees-button text="Highlighted: This text shows" type="highlighted">Highlighted</dees-button></p>
<p><dees-button type="discreet">This is discreete button</dees-button></p>
<p><dees-button disabled>This is a disabled button</dees-button></p>
<p><dees-button type="big">This is a slotted Text</dees-button></p>
<p><dees-button status="normal">Normal Status</dees-button></p>
<p><dees-button disabled status="pending">Pending Status</dees-button></p>
<p><dees-button disabled status="success">Success Status</dees-button></p>
<p><dees-button disabled status="error">Error Status</dees-button></p>
`;
public static demo = demoFunc;
@property({
reflect: true,
@ -73,6 +65,7 @@ export class DeesButton extends DeesElement {
:host {
display: block;
box-sizing: border-box;
font-family: 'Roboto', 'monospace';
}
:host([hidden]) {
display: none;
@ -87,7 +80,7 @@ export class DeesButton extends DeesElement {
justify-content: center;
align-items: center;
background: ${cssManager.bdTheme('#fff', '#333')};
box-shadow: ${cssManager.bdTheme('0px 1px 4px rgba(0,0,0,0.3)', 'none')};
box-shadow: ${cssManager.bdTheme('0px 1px 3px rgba(0,0,0,0.3)', 'none')};
border: 1px solid ${cssManager.bdTheme('#eee', '#333')};
border-top: ${cssManager.bdTheme('1px solid #eee', '1px solid #444')};
border-radius: 4px;

View File

@ -3,13 +3,14 @@ import {
html,
DeesElement,
property,
TemplateResult,
type TemplateResult,
cssManager,
css,
type CSSResult,
unsafeCSS,
} from '@designestate/dees-element';
} from '@design.estate/dees-element';
import * as domtools from '@designestate/dees-domtools';
import * as domtools from '@design.estate/dees-domtools';
declare global {
interface HTMLElementTagNameMap {

View File

@ -0,0 +1,57 @@
import { html } from '@design.estate/dees-element';
import * as plugins from './plugins.js';
import { DeesContextmenu } from './dees-contextmenu.js';
export const demoFunc = () => html`
<style>
.withMargin {
display: block;
margin: 20px;
}
</style>
<dees-button @contextmenu=${(eventArg) => {
DeesContextmenu.openContextMenuWithOptions(eventArg, [
{
name: 'copy',
iconName: 'copySolid',
action: async () => {
return null;
},
},
{
name: 'edit',
iconName: 'penToSquare',
action: async () => {
return null;
},
},{
name: 'paste',
iconName: 'pasteSolid',
action: async () => {
return null;
},
},
]);
}}>Right-Click for contextmenu</dees-button>
<dees-contextmenu class="withMargin"></dees-contextmenu>
<dees-contextmenu
class="withMargin"
.menuItems=${[
{
name: 'copy',
iconName: 'copySolid',
action: async () => {},
},
{
name: 'edit',
iconName: 'penToSquare',
action: async () => {},
},{
name: 'paste',
iconName: 'pasteSolid',
action: async () => {},
},
] as plugins.tsclass.website.IMenuItem[]}
></dees-contextmenu>
`;

View File

@ -1,16 +1,18 @@
import { demoFunc } from './dees-contextmenu.demo.js';
import * as plugins from './plugins.js';
import {
customElement,
html,
DeesElement,
property,
TemplateResult,
type TemplateResult,
cssManager,
css,
type CSSResult,
unsafeCSS,
} from '@designestate/dees-element';
} from '@design.estate/dees-element';
import * as domtools from '@designestate/dees-domtools';
import * as domtools from '@design.estate/dees-domtools';
import { DeesWindowLayer } from './dees-windowlayer.js';
declare global {
@ -22,70 +24,25 @@ declare global {
@customElement('dees-contextmenu')
export class DeesContextmenu extends DeesElement {
// DEMO
public static demo = () => html`
<style>
.withMargin {
display: block;
margin: 20px;
}
</style>
<dees-button @contextmenu=${(eventArg) => {
DeesContextmenu.openContextMenuWithOptions(eventArg, [
{
name: 'copy',
iconName: 'copySolid',
action: async () => {
return null;
},
},
{
name: 'edit',
iconName: 'penToSquare',
action: async () => {
return null;
},
},{
name: 'paste',
iconName: 'pasteSolid',
action: async () => {
return null;
},
},
]);
}}>Hello</dees-button>
<dees-contextmenu class="withMargin"></dees-contextmenu>
<dees-contextmenu
class="withMargin"
.menuItems=${[
{
name: 'copy',
iconName: 'copySolid',
action: async () => {},
},
{
name: 'edit',
iconName: 'penToSquare',
action: async () => {},
},{
name: 'paste',
iconName: 'pasteSolid',
action: async () => {},
},
] as plugins.tsclass.website.IMenuItem[]}
></dees-contextmenu>
`;
public static demo = demoFunc
// STATIC
public static async openContextMenuWithOptions(eventArg: MouseEvent, menuItemsArg: plugins.tsclass.website.IMenuItem[]) {
eventArg.preventDefault();
eventArg.stopPropagation();
const contextMenu = new DeesContextmenu();
contextMenu.style.position = 'absolute';
contextMenu.style.position = 'fixed';
contextMenu.style.zIndex = '2000';
contextMenu.style.top = `${eventArg.clientY.toString()}px`;
contextMenu.style.left = `${eventArg.clientX.toString()}px`;
contextMenu.style.opacity = '0';
contextMenu.style.transform = 'scale(0.95,0.95)';
contextMenu.style.transformOrigin = 'top left';
contextMenu.menuItems = menuItemsArg;
contextMenu.windowLayer = await DeesWindowLayer.createAndShow();
contextMenu.windowLayer.addEventListener('click', async () => {
await contextMenu.destroy();
})
document.body.append(contextMenu);
await domtools.plugins.smartdelay.delayFor(0);
contextMenu.style.opacity = '1';
@ -96,6 +53,7 @@ export class DeesContextmenu extends DeesElement {
type: Array,
})
public menuItems: plugins.tsclass.website.IMenuItem[] = [];
windowLayer: DeesWindowLayer;
constructor() {
super();
@ -113,11 +71,11 @@ export class DeesContextmenu extends DeesElement {
color: ${cssManager.bdTheme('#222', '#ccc')};
font-size: 14px;
width: 200px;
border: 1px solid #444;
min-height: 40px;
border: 1px solid ${cssManager.bdTheme('#fff', '#444')};
min-height: 34px;
border-radius: 3px;
background: #222;
box-shadow: 0px 1px 4px #000;
background: ${cssManager.bdTheme('#fff', '#222')};
box-shadow: 0px 1px 4px ${cssManager.bdTheme('#00000020', '#000000')};
user-select: none;
}
@ -134,7 +92,7 @@ export class DeesContextmenu extends DeesElement {
.mainbox .menuitem:hover {
cursor: pointer;
background: #ffffff10;
background: ${cssManager.bdTheme('#00000010', '#ffffff10')};
}
.mainbox .menuitem:active {
@ -155,15 +113,20 @@ export class DeesContextmenu extends DeesElement {
</div>
`;
})}
${this.menuItems.length === 0 ? html`
<div class="menuitem" @click=${() => {
alert('No menu items...')
}}>
<dees-icon .iconFA=${'xmark'}></dees-icon
>No menu item present...
</div>
` : html``}
</div>
`;
}
public async firstUpdated() {
if (!this.menuItems || this.menuItems.length === 0) {
const mainbox = this.shadowRoot.querySelector('.mainbox');
mainbox.textContent = 'no menu items present';
}
}
public async handleClick(menuItem: plugins.tsclass.website.IMenuItem) {
@ -172,6 +135,9 @@ export class DeesContextmenu extends DeesElement {
}
public async destroy() {
if (this.windowLayer) {
this.windowLayer.destroy();
}
this.style.opacity = '0';
this.style.transform = 'scale(0.95,0,95)';
await domtools.plugins.smartdelay.delayFor(100);

View File

@ -0,0 +1,18 @@
import { html } from '@design.estate/dees-element';
export const demoFunc = () => html` <style>
.demoWrapper {
box-sizing: border-box;
position: absolute;
width: 100%;
height: 100%;
padding: 20px;
background: none;
}
</style>
<div class="demoWrapper">
<dees-dataview-codebox proglang="typescript">
import * as text from './hello'; const hiThere = 'nice'; const myFunction = async () => {
console.log('nice one'); }
</dees-dataview-codebox>
</div>`

View File

@ -1,17 +1,20 @@
import { demoFunc } from './dees-dataview-codebox.demo.js';
import {
DeesElement,
html,
customElement,
TemplateResult,
type TemplateResult,
property,
state,
} from '@designestate/dees-element';
cssManager,
} from '@design.estate/dees-element';
import hlight from 'highlight.js';
import * as smartstring from '@pushrocks/smartstring';
import * as smartstring from '@push.rocks/smartstring';
import * as domtools from '@designestate/dees-domtools';
import * as domtools from '@design.estate/dees-domtools';
import { DeesContextmenu } from './dees-contextmenu.js';
declare global {
interface HTMLElementTagNameMap {
@ -21,18 +24,16 @@ declare global {
@customElement('dees-dataview-codebox')
export class DeesDataviewCodebox extends DeesElement {
public static demo = () => html`<dees-dataview-codebox proglang="typescript">
import * as text from './hello'; const hiThere = 'nice'; const myFunction = async () => {
console.log('nice one'); }
</dees-dataview-codebox>`;
public static demo = demoFunc;
@property()
public progLang: string = 'typescript';
@property({
type: String
type: String,
reflect: true,
})
public codeToDisplay: string = '// no code set';
public codeToDisplay: string = '';
constructor() {
super();
@ -47,23 +48,89 @@ export class DeesDataviewCodebox extends DeesElement {
display: block;
text-align: left;
font-size: 16px;
font-family: 'Roboto', 'Inter', sans-serif;
}
.mainbox {
position: relative;
color: ${this.goBright ? '#333333' : '#ffffff'};
border-top: 1px solid ${this.goBright ? '#ffffff' : '#333333'};
box-shadow: 0px 0px 5px ${this.goBright ? 'rgba(0,0,0,0.1)' : 'rgba(0,0,0,0.5)'};
background: ${this.goBright ? '#ffffff' : '#191919'};
border-radius: 16px;
overflow: hidden;
}
.appbar {
color: ${cssManager.bdTheme('#333', '#ccc')};
background: ${cssManager.bdTheme('#ffffff', '#161616')};
border-bottom: 1px solid ${cssManager.bdTheme('#eeeeeb', '#222222')};
height: 24px;
font-size: 12px;
line-height: 24px;
}
.appbar .macControls {
position: absolute;
top: 6px;
left: 20px;
width: 200px;
display: grid;
grid-template-columns: 24px 24px 24px;
}
.appbar .macControls div {
width: 12px;
height: 12px;
display: inline-block;
border-radius: 50%;
margin: 0px;
padding: 0px;
cursor: pointer;
background: #222222;
}
.appbar .macControls div.close {
background: #ff5f57;
}
.appbar .macControls div.toDock {
background: #ffbd2e;
}
.appbar .macControls div.minMax {
background: #27c93f;
}
.appbar .macControls div:hover {
background: #333333;
}
.appbar .fileName {
text-align: center;
}
.bottomBar {
color: ${cssManager.bdTheme('#333', '#ccc')};
background: ${cssManager.bdTheme('#ffffff', '#161616')};
border-top: 1px solid ${cssManager.bdTheme('#eeeeeb', '#222222')};
height: 24px;
font-size: 12px;
line-height: 24px;
text-align: right;
padding-right: 100px;
}
.languageLabel {
color: #fff;
color: ${cssManager.bdTheme('#333', '#ccc')};
font-size: 12px;
line-height: 24px;
z-index: 10;
background: #6596ff;
background: #6596ff20;
display: inline-block;
position: absolute;
right: 32px;
padding: 4px;
border-bottom-left-radius: 3px;
border-bottom-right-radius: 3px;
bottom: 0px;
right: 0px;
padding: 0px 16px 0px 8px;
}
.hljs-keyword {
@ -73,18 +140,14 @@ export class DeesDataviewCodebox extends DeesElement {
.codegrid {
display: grid;
grid-template-columns: 50px auto;
background: ${this.goBright ? '#ffffff' : '#191919'};
border-top: 1px solid ${this.goBright ? '#ffffff' : '#333333'};
box-shadow: 0px 0px 5px ${this.goBright ? 'rgba(0,0,0,0.1)' : 'rgba(0,0,0,0.5)'};
border-radius: 3px;
overflow: hidden;
}
.lineNumbers {
background: ${this.goBright ? '#fafafa' : '#151515'};
color: ${this.goBright ? '#acacac' : '#666666'};
padding: 30px 16px 0px 0px;
text-align: right;
border-right: 1px solid ${this.goBright ? '#eaeaea' : '#222222'};
}
.lineCounter:last-child {
@ -108,7 +171,7 @@ export class DeesDataviewCodebox extends DeesElement {
.lineNumbers {
line-height: 1.4em;
font-weight: 200;
font-family: monospace;
font-family: 'Intel One Mono', 'monospace';
}
.hljs-string {
@ -120,35 +183,62 @@ export class DeesDataviewCodebox extends DeesElement {
}
.hljs-function {
color: ${this.goBright ? '#2765DF': '#6596ff' };
color: ${this.goBright ? '#2765DF' : '#6596ff'};
}
.hljs-params {
color: ${this.goBright ? '#3DB420' : '#65d5ff' };
color: ${this.goBright ? '#3DB420' : '#65d5ff'};
}
.hljs-comment {
color: ${this.goBright ? '#EF9300' : '#ffd765' };
color: ${this.goBright ? '#EF9300' : '#ffd765'};
}
</style>
<div class="mainbox">
<div class="languageLabel">${this.progLang}</div>
<div
class="mainbox"
@contextmenu="${(eventArg) => {
DeesContextmenu.openContextMenuWithOptions(eventArg, [
{
name: 'About',
iconName: 'circleInfo',
action: async () => {
return null;
},
},
]);
}}"
>
<div class="appbar">
<div class="macControls">
<div class="close"></div>
<div class="toDock"></div>
<div class="minMax"></div>
</div>
<div class="fileName">index.ts</div>
</div>
<div class="codegrid">
<div class="lineNumbers">
${(() => {
let lineCounter = 0;
return this.codeToDisplay.split('\n').map(lineArg => {
return this.codeToDisplay.split('\n').map((lineArg) => {
lineCounter++;
return html`<div class="lineCounter">${lineCounter}</div>`;
})
});
})()}
</div>
<pre><code class="${this.progLang}">${this.codeToDisplay}</code></pre>
<pre><code></code></pre>
</div>
<div class="bottomBar">
Spaces: 2
<div class="languageLabel">${this.progLang}</div>
</div>
</div>
`;
}
@state()
private codeToDisplayStore = '';
public async updated(_changedProperties) {
super.updated(_changedProperties);
console.log('highlighting now');
@ -159,11 +249,21 @@ export class DeesDataviewCodebox extends DeesElement {
slottedCodeNodes.push(childNode as Text);
}
});
if (slottedCodeNodes[0] && slottedCodeNodes[0].wholeText) {
this.codeToDisplay = smartstring.indent.normalize(slottedCodeNodes[0].wholeText);
if (this.codeToDisplay && this.codeToDisplay !== this.codeToDisplayStore) {
this.codeToDisplayStore = smartstring.indent.normalize(this.codeToDisplay).trimStart();
}
if (slottedCodeNodes[0] && slottedCodeNodes[0].wholeText && !this.codeToDisplay) {
this.codeToDisplayStore = smartstring.indent
.normalize(slottedCodeNodes[0].wholeText)
.trimStart();
this.codeToDisplay = this.codeToDisplayStore;
}
await domtools.plugins.smartdelay.delayFor(0);
const localCodeNode = this.shadowRoot.querySelector('code');
hlight.highlightBlock(localCodeNode);
const html = hlight.highlight(this.codeToDisplayStore, {
language: this.progLang,
ignoreIllegals: true,
});
localCodeNode.innerHTML = html.value;
}
}

View File

@ -0,0 +1,39 @@
import { html } from '@design.estate/dees-element';
import * as tsclass from '@tsclass/tsclass';
export const demoFunc = () => html`<dees-dataview-statusobject
.statusObject=${{
id: '1',
name: 'Demo Item',
combinedStatus: 'partly_ok',
combinedStatusText: 'partly_ok',
details: [
{
name: 'Detail 1',
value: 'Value 1',
status: 'ok',
statusText: 'OK',
},
{
name: 'Detail 2',
value: 'Value 2',
status: 'partly_ok',
statusText: 'partly_ok',
},
{
name: 'Detail 3',
value: 'Value 3',
status: 'not_ok',
statusText: 'not_ok',
},
{
name: 'Detail 4',
value:
'Value 4 jhdkfjhalskdfjhfdjskalsdkfjhfdjskalskdjfhjdkslaksjdhfjdkslaskdfjhfjdkslaskdjfhjdskalskdjhfdjskalskdjfhdjskl',
status: 'ok',
statusText: 'OK',
},
],
} as tsclass.code.IStatusObject}
>
</dees-dataview-statusobject>`;

View File

@ -1,22 +1,18 @@
import { demoFunc } from './dees-dataview-statusobject.demo.js';
import {
DeesElement,
html,
customElement,
TemplateResult,
type TemplateResult,
property,
state,
cssManager,
css,
} from '@designestate/dees-element';
type CSSResult,
} from '@design.estate/dees-element';
import * as tsclass from '@tsclass/tsclass';
import hlight from 'highlight.js';
import * as smartstring from '@pushrocks/smartstring';
import * as domtools from '@designestate/dees-domtools';
declare global {
interface HTMLElementTagNameMap {
'dees-dataview-statusobject': DeesDataviewStatusobject;
@ -25,41 +21,7 @@ declare global {
@customElement('dees-dataview-statusobject')
export class DeesDataviewStatusobject extends DeesElement {
public static demo = () => html`<dees-dataview-statusobject
.statusObject=${{
id: '1',
name: 'Demo Item',
combinedStatus: 'partly_ok',
combinedStatusText: 'partly_ok',
details: [
{
name: 'Detail 1',
value: 'Value 1',
status: 'ok',
statusText: 'OK',
},
{
name: 'Detail 2',
value: 'Value 2',
status: 'partly_ok',
statusText: 'partly_ok',
},
{
name: 'Detail 3',
value: 'Value 3',
status: 'not_ok',
statusText: 'not_ok',
},
{
name: 'Detail 4',
value: 'Value 4',
status: 'ok',
statusText: 'OK',
},
],
}}
>
</dees-dataview-statusobject>`;
public static demo = demoFunc;
@property({ type: Object }) statusObject: tsclass.code.IStatusObject;
@ -67,9 +29,9 @@ export class DeesDataviewStatusobject extends DeesElement {
cssManager.defaultStyles,
css`
.mainbox {
max-width: 600px;
border-radius: 3px;
background: #1b1b1b;
border-radius: 8px;
background: ${cssManager.bdTheme('#fff', '#1b1b1b')};
box-shadow: 0px 1px 3px #00000030;
min-height: 48px;
color: ${cssManager.bdTheme('#000', '#fff')};
}
@ -100,7 +62,7 @@ export class DeesDataviewStatusobject extends DeesElement {
.copyMain {
cursor: pointer;
font-size: 8px;
font-size: 10px;
font-weight: 600;
text-transform: uppercase;
border: 1px solid ${cssManager.bdTheme('#999', '#444')};
@ -108,6 +70,7 @@ export class DeesDataviewStatusobject extends DeesElement {
padding: 4px;
border-radius: 3px;
margin-right: 16px;
color: #ffffff80
}
.statusdot.ok {
@ -123,20 +86,28 @@ export class DeesDataviewStatusobject extends DeesElement {
}
.detail {
height: 60px;
minheight: 60px;
align-items: center;
display: grid;
grid-template-columns: 40px auto;
border-top: 1px dotted ${cssManager.bdTheme('#999', '#444')};
border-top: 1px dotted ${cssManager.bdTheme('#999', '#282828')};
}
.detail .detailsText {
padding-top: 8px;
padding-bottom: 8px;
padding-right: 8px;
word-break: break-all;
}
.detail .detailsText .label {
font-size: 12px;
color: #ffffff80
}
.detail .detailsText .value {
font-size: 16px;
font-family: Roboto Mono;
font-size: 14px;
font-family: 'Intel One Mono';
}
`,
];
@ -145,11 +116,11 @@ export class DeesDataviewStatusobject extends DeesElement {
return html`
<div class="mainbox">
<div class="heading">
<div class="statusdot ${this.statusObject.combinedStatus}"></div>
<div class="statusdot ${this.statusObject?.combinedStatus}"></div>
<h1>${this.statusObject?.name || 'no status object assigned'}</h1>
<div class="copyMain">Copy as JSON</div>
</div>
${this.statusObject.details.map((detailArg) => {
${this.statusObject?.details?.map((detailArg) => {
return html`
<div class="detail">
<div class="statusdot ${detailArg.status}"></div>

View File

@ -5,7 +5,8 @@ import {
css,
cssManager,
property,
} from '@designestate/dees-element';
type CSSResult,
} from '@design.estate/dees-element';
import { DeesForm } from './dees-form.js';
declare global {
@ -20,6 +21,7 @@ export class DeesFormSubmit extends DeesElement {
@property({
type: Boolean,
reflect: true,
})
public disabled = false;
@ -29,7 +31,7 @@ export class DeesFormSubmit extends DeesElement {
public text: string;
@property({
type: String
type: String,
})
public status: 'normal' | 'pending' | 'success' | 'error' = 'normal';
@ -41,7 +43,12 @@ export class DeesFormSubmit extends DeesElement {
public render() {
return html`
<dees-button status=${this.status} @click=${this.submit} .disabled=${this.disabled} .text=${this.text ? this.text : this.textContent}>
<dees-button
status=${this.status}
@click=${this.submit}
.disabled=${this.disabled}
.text=${this.text ? this.text : this.textContent}
>
</dees-button>
`;
}
@ -53,4 +60,12 @@ export class DeesFormSubmit extends DeesElement {
const parentElement: DeesForm = this.parentElement as DeesForm;
parentElement.gatherAndDispatch();
}
public async focus() {
const domtools = await this.domtoolsPromise;
if (!this.disabled) {
domtools.convenience.smartdelay.delayFor(0);
this.submit();
}
}
}

View File

@ -1,5 +1,5 @@
import { customElement, html, TemplateResult, DeesElement } from '@designestate/dees-element';
import * as domtools from '@designestate/dees-domtools';
import { customElement, html, type TemplateResult, DeesElement, type CSSResult, } from '@design.estate/dees-element';
import * as domtools from '@design.estate/dees-domtools';
import { DeesInputCheckbox } from './dees-input-checkbox.js';
import { DeesInputText } from './dees-input-text.js';
@ -7,9 +7,15 @@ import { DeesInputQuantitySelector } from './dees-input-quantityselector.js';
import { DeesInputRadio } from './dees-input-radio.js';
import { DeesFormSubmit } from './dees-form-submit.js';
export type TFormElement = Array<
DeesInputCheckbox | DeesInputText | DeesInputQuantitySelector | DeesInputRadio
>;
// Unified set for form input types
const FORM_INPUT_TYPES = [
DeesInputCheckbox,
DeesInputText,
DeesInputQuantitySelector,
DeesInputRadio
];
export type TFormInputElement = DeesInputCheckbox | DeesInputText | DeesInputQuantitySelector | DeesInputRadio;
declare global {
interface HTMLElementTagNameMap {
@ -19,6 +25,7 @@ declare global {
@customElement('dees-form')
export class DeesForm extends DeesElement {
public static demo = () => html`
<dees-form
style="display: block; margin:auto; max-width: 500px; padding: 20px"
@ -31,17 +38,14 @@ export class DeesForm extends DeesElement {
>
<dees-input-text .required="${true}" key="hello1" label="a text"></dees-input-text>
<dees-input-text .required="${true}" key="hello2" label="also a text"></dees-input-text>
<dees-input-checkbox
.required="${true}"
key="hello3"
label="another text"
></dees-input-checkbox>
<dees-input-checkbox .required="${true}" key="hello3" label="another text"></dees-input-checkbox>
<dees-form-submit>Submit</dees-form-submit>
</dees-form>
`;
public name: string = 'myform';
public changeSubject = new domtools.rxjs.Subject();
public readyDeferred = domtools.plugins.smartpromise.defer();
public render(): TemplateResult {
return html`
@ -54,51 +58,39 @@ export class DeesForm extends DeesElement {
`;
}
public firstUpdated() {
const formChildren = this.getFormChildren();
this.checkRequiredStatus();
public async firstUpdated() {
const formChildren = this.getFormElements();
this.updateRequiredStatus();
for (const child of formChildren) {
child.changeSubject.subscribe(async (elementArg: TFormElement) => {
const valueObject = await this.gatherData();
child.changeSubject.subscribe(async () => {
const valueObject = await this.collectFormData();
this.changeSubject.next(valueObject);
console.log(valueObject);
this.checkRequiredStatus();
this.updateRequiredStatus();
});
}
await this.addBehaviours();
this.readyDeferred.resolve();
}
public getFormChildren() {
const children: Array<DeesElement> = this.children as any;
const formChildren: TFormElement = [];
for (const child of children) {
if (
child instanceof DeesInputCheckbox ||
child instanceof DeesInputText ||
child instanceof DeesInputQuantitySelector
) {
formChildren.push(child);
}
}
return formChildren;
public getFormElements(): Array<TFormInputElement> {
return (Array.from(this.children)).filter(child =>
FORM_INPUT_TYPES.includes(child.constructor as any)
) as unknown as TFormInputElement[];
}
public getSubmitButton() {
const children: Array<DeesElement> = this.children as any;
let submitButton: DeesFormSubmit;
for (const childArg of children) {
if (childArg instanceof DeesFormSubmit) {
submitButton = childArg;
}
}
return submitButton;
public getSubmitButton(): DeesFormSubmit | undefined {
return Array.from(this.children).find(child =>
child instanceof DeesFormSubmit
) as DeesFormSubmit;
}
public async checkRequiredStatus() {
public async updateRequiredStatus() {
console.log('checking the required status.');
let requiredOK = true;
for (const childArg of this.getFormChildren()) {
for (const childArg of this.getFormElements()) {
if (childArg.required && !childArg.value) {
requiredOK = false;
}
@ -108,17 +100,20 @@ export class DeesForm extends DeesElement {
}
}
public async gatherData() {
const children = this.getFormChildren();
public async collectFormData() {
const children = this.getFormElements();
const valueObject: { [key: string]: string | number | boolean } = {};
for (const child of children) {
if (!child.key) {
console.log(`form element with label "${child.label}" has no key. skipping.`);
}
valueObject[child.key] = child.value;
}
return valueObject;
}
public async gatherAndDispatch() {
const valueObject = await this.gatherData();
const valueObject = await this.collectFormData();
const formDataEvent = new CustomEvent('formData', {
detail: {
data: valueObject,
@ -134,7 +129,7 @@ export class DeesForm extends DeesElement {
visualStateArg: 'normal' | 'pending' | 'error' | 'success',
textStateArg: string
) {
const inputChildren = this.getFormChildren();
const inputChildren = this.getFormElements();
const submitButton = this.getSubmitButton();
switch (visualStateArg) {
@ -170,4 +165,36 @@ export class DeesForm extends DeesElement {
submitButton.text = textStateArg;
}
/**
* resets the form
*/
reset() {
const inputChildren = this.getFormElements();
const submitButton = this.getSubmitButton();
for (const inputChild of inputChildren) {
inputChild.value = null;
}
this.setStatus('normal', 'Submit');
}
public async addBehaviours() {
// Use event delegation
this.addEventListener('keydown', (event: KeyboardEvent) => {
const target = event.target as DeesElement;
if (!FORM_INPUT_TYPES.includes(target.constructor as any)) return;
if (event.key === 'Enter') {
const children = this.getFormElements();
const currentIndex = children.indexOf(target as any);
if (currentIndex < children.length - 1) {
children[currentIndex + 1].focus();
} else {
target.blur();
this.getSubmitButton()?.focus();
}
}
});
}
}

View File

@ -0,0 +1,5 @@
import { html } from '@design.estate/dees-element';
export const demoFunc = () => html`
<dees-hint></dees-hint>
`;

View File

@ -0,0 +1,38 @@
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-hint.demo.js';
declare global {
interface HTMLElementTagNameMap {
'dees-hint': DeesHint;
}
}
@customElement('dees-hint')
export class DeesHint extends DeesElement {
public static demo = demoFunc;
@property({ type: String })
public type: 'info' | 'warn' | 'error' | 'critical' = 'info';
constructor() {
super();
domtools.elementBasic.setup();
}
public static styles = [cssManager.defaultStyles, css``];
public render(): TemplateResult {
return html` <div class="mainbox"></div> `;
}
}

View File

@ -0,0 +1,55 @@
import { html } from '@design.estate/dees-element';
import { faIcons } from './dees-icon.js';
export const demoFunc = () => html`
<style>
.demoContainer {
width: 100%;
display: flex;
flex-wrap: wrap;
background: #111111;
padding: 10px; font-size: 30px;
}
dees-icon {
transition: color 0.02s;
color: #ffffff;
}
dees-icon:hover {
color: #e4002b;
}
.iconContainer {
display: block;
padding: 16px 16px 0px 16px;
border: 1px solid #333333;
margin-right: 8px;
margin-bottom: 8px;
}
.iconName {
font-size: 12px;
text-align: center;
color: #ccc;
background: #333333;
padding: 4px 8px;
padding-bottom: 4px;
margin-left: -16px;
margin-right: -16px;
margin-top: 16px;
}
</style>
<div class="demoContainer">
${Object.keys(faIcons).map(
(iconName) => html`
<div class="iconContainer">
<dees-icon .iconFA=${iconName as any}></dees-icon>
<div class="iconName">${iconName}</div>
</div>
`
)}
</div>
`;

View File

@ -5,11 +5,12 @@ import {
customElement,
cssManager,
css,
} from '@designestate/dees-element';
type CSSResult,
} from '@design.estate/dees-element';
import * as domtools from '@designestate/dees-domtools';
import * as domtools from '@design.estate/dees-domtools';
import { icon, IconDefinition } from '@fortawesome/fontawesome-svg-core';
import { icon, type IconDefinition } from '@fortawesome/fontawesome-svg-core';
import {
faFacebook,
faGoogle,
@ -28,6 +29,7 @@ import {
faMessage as faMessageRegular,
faPaste as faPasteRegular,
faSun as faSunRegular,
faTrashCan as faTrashCanRegular,
} from '@fortawesome/free-regular-svg-icons';
import {
faArrowRight as faArrowRightSolid,
@ -41,74 +43,78 @@ import {
faCircleInfo as faCircleInfoSolid,
faCircleCheck as faCircleCheckSolid,
faCircleXmark as faCircleXmarkSolid,
faClockRotateLeft as faClockRotateLeftSolid,
faCopy as faCopySolid,
faDesktop as faDesktopSolid,
faEye as faEyeSolid,
faEyeSlash as faEyeSlashSolid,
faFileInvoice as faFileInvoiceSolid,
faFileInvoiceDollar as faFileInvoiceDollarSolid,
faGrip as faGripSolid,
faMessage as faMessageSolid,
faMoneyCheckDollar as faMoneyCheckDollarSolid,
faMugHot as faMugHotSolid,
faMinus as faMinusSolid,
faPaste as faPasteSolid,
faPenToSquare as faPenToSquareSolid,
faPlus as faPlusSolid,
faReceipt as faReceiptSolid,
faRss as faRssSolid,
faUsers as faUsersSolid,
faShare as faShareSolid,
faSun as faSunSolid,
faTrash as faTrashSolid,
faTrashCan as faTrashCanSolid,
faWallet as faWalletSolid,
faXmark as faXmarkSolid,
} from '@fortawesome/free-solid-svg-icons';
import { demoFunc } from './dees-icon.demo.js';
export const faIcons = {
// normal
arrowRight: faArrowRightSolid,
arrowUpRightFromSquare: faArrowUpRightFromSquareSolid,
arrowUpRightFromSquareSolid: faArrowUpRightFromSquareSolid,
bell: faBellSolid,
bellSolid: faBellSolid,
bug: faBugSolid,
bugSolid: faBugSolid,
building: faBuildingSolid,
buildingSolid: faBuildingSolid,
caretLeft: faCaretLeftSolid,
caretLeftSolid: faCaretLeftSolid,
caretRight: faCaretRightSolid,
caretRightSolid: faCaretRightSolid,
check: faCheckSolid,
checkSolid: faCheckSolid,
circleInfo: faCircleInfoSolid,
circleInfoSolid: faCircleInfoSolid,
circleCheck: faCircleCheckRegular,
circleCheckSolid: faCircleCheckSolid,
circleXmark: faCircleXmarkRegular,
circleXmarkSolid: faCircleXmarkSolid,
clockRotateLeft: faClockRotateLeftSolid,
copy: faCopyRegular,
copySolid: faCopySolid,
desktop: faDesktopSolid,
desktopSolid: faDesktopSolid,
eye: faEyeSolid,
eyeSolid: faEyeSolid,
eyeSlash: faEyeSlashSolid,
eyeSlashSolid: faEyeSlashSolid,
fileInvoice: faFileInvoiceSolid,
fileInvoiceDoller: faFileInvoiceDollarSolid,
grip: faGripSolid,
gripSolid: faGripSolid,
message: faMessageRegular,
messageSolid: faMessageSolid,
moneyCheckDollar: faMoneyCheckDollarSolid,
mugHot: faMugHotSolid,
faMugHotSolid: faMugHotSolid,
minus: faMinusSolid,
minusSolid: faMinusSolid,
paste: faPasteRegular,
pasteSolid: faPasteSolid,
penToSquare: faPenToSquareSolid,
penToSquareSolid: faPenToSquareSolid,
plus: faPlusSolid,
receipt: faReceiptSolid,
rss: faRssSolid,
rssSolid: faRssSolid,
share: faShareSolid,
shareSolid: faShareSolid,
sun: faSunRegular,
sunSolid: faSunSolid,
trash: faTrashSolid,
trashSolid: faTrashSolid,
trashCan: faTrashCanRegular,
trashCanSolid: faTrashCanSolid,
users: faUsersSolid,
wallet: faWalletSolid,
xmark: faXmarkSolid,
xmarkSolid: faXmarkSolid,
// brands
facebook: faFacebook,
google: faGoogle,
@ -118,9 +124,10 @@ export const faIcons = {
slack: faSlackHash,
tiktok: faTiktok,
twitter: faTwitter,
users: faUsersSolid,
};
export type TIconKey = keyof typeof faIcons;
declare global {
interface HTMLElementTagNameMap {
'dees-icon': DeesIcon;
@ -129,24 +136,7 @@ declare global {
@customElement('dees-icon')
export class DeesIcon extends DeesElement {
public static demo = () => html`
<dees-icon iconName="visibility"></dees-icon>
<div style="background: #fff; padding: 10px; font-size: 30px">
<style>
dees-icon {
transition: color 0.05s;
}
dees-icon:hover {
color: #e4002b;
}
</style>
<dees-icon .iconFA=${'messageSolid'}></dees-icon>
<dees-icon .iconFA=${'sun'}></dees-icon>
<dees-icon .iconFA=${'sunSolid'}></dees-icon>
<dees-icon .iconFA=${'facebook'}></dees-icon>
<dees-icon .iconFA=${'arrowUpRightFromSquare'}></dees-icon>
</div>
`;
public static demo = demoFunc;
@property({
type: String

View File

@ -1,13 +1,14 @@
import {
customElement,
DeesElement,
TemplateResult,
type TemplateResult,
property,
html,
css,
cssManager
} from '@designestate/dees-element';
import * as domtools from '@designestate/dees-domtools';
cssManager,
type CSSResult,
} from '@design.estate/dees-element';
import * as domtools from '@design.estate/dees-domtools';
declare global {
interface HTMLElementTagNameMap {
@ -25,6 +26,7 @@ export class DeesInputCheckbox extends DeesElement {
@property({
type: String,
reflect: true,
})
public key: string;
@ -143,7 +145,7 @@ export class DeesInputCheckbox extends DeesElement {
}
</style>
<div class="maincontainer" @click="${this.toggleSelected}">
<div class="checkbox ${this.value ? 'selected' : ''} ${this.disabled ? 'disabled' : ''}">
<div class="checkbox ${this.value ? 'selected' : ''} ${this.disabled ? 'disabled' : ''}" tabindex="0">
${this.value
? html`
<span class="checkmark">
@ -171,4 +173,11 @@ export class DeesInputCheckbox extends DeesElement {
);
this.changeSubject.next(this);
}
public focus(): void {
const checkboxDiv = this.shadowRoot.querySelector('.checkbox');
if (checkboxDiv) {
(checkboxDiv as any).focus();
}
}
}

View File

@ -1,5 +1,5 @@
import { customElement, DeesElement, TemplateResult, property, html, css, cssManager } from '@designestate/dees-element';
import * as domtools from '@designestate/dees-domtools';
import { customElement, DeesElement, type TemplateResult, property, html, css, cssManager, type CSSResult, } from '@design.estate/dees-element';
import * as domtools from '@design.estate/dees-domtools';
declare global {
interface HTMLElementTagNameMap {
@ -22,7 +22,10 @@ export class DeesInputDropdown extends DeesElement {
// INSTANCE
public changeSubject = new domtools.rxjs.Subject();
@property()
@property({
type: String,
reflect: true,
})
public label: string = 'Label';
@property()

View File

@ -1,15 +1,16 @@
import {
customElement,
DeesElement,
TemplateResult,
type TemplateResult,
property,
html,
css,
unsafeCSS,
cssManager,
} from '@designestate/dees-element';
type CSSResult,
} from '@design.estate/dees-element';
import * as domtools from '@designestate/dees-domtools';
import * as domtools from '@design.estate/dees-domtools';
declare global {
interface HTMLElementTagNameMap {
@ -31,6 +32,7 @@ export class DeesInputFileupload extends DeesElement {
@property({
type: String,
reflect: true,
})
public key: string;
@ -122,7 +124,7 @@ export class DeesInputFileupload extends DeesElement {
border-bottom: 1px dashed #444;
color: ${cssManager.bdTheme('#666', '#ccc')};
padding: 8px;
font-family: 'Inter';
font-family: 'Roboto', 'Inter', sans-serif;
}
.uploadButton:hover .uploadCandidate {
@ -154,7 +156,10 @@ export class DeesInputFileupload extends DeesElement {
public async openFileSelector() {
const inputFile: HTMLInputElement = this.shadowRoot.querySelector('input[type="file"]');
inputFile.click();
this.state = 'idle';
this.buttonText = 'Upload more files...';
}
public async updateValue(eventArg: Event) {
const target: any = eventArg.target;
@ -163,6 +168,20 @@ export class DeesInputFileupload extends DeesElement {
}
public firstUpdated() {
const inputFile: HTMLInputElement = this.shadowRoot.querySelector('input[type="file"]');
inputFile.addEventListener('change', (event: Event) => {
const target = event.target as HTMLInputElement;
for (const file of Array.from(target.files)) {
this.value.push(file);
}
this.requestUpdate();
console.log(`Got ${this.value.length} files!`);
// Reset the input value to allow selecting the same file again if needed
target.value = '';
});
// lets handle drag and drop
const dropArea = this.shadowRoot.querySelector('.uploadButton');
const handlerFunction = (eventArg: DragEvent) => {
eventArg.preventDefault();

View File

@ -1,5 +1,5 @@
import { customElement, property, html, TemplateResult, DeesElement } from '@designestate/dees-element';
import * as domtools from '@designestate/dees-domtools';
import { customElement, property, html, type TemplateResult, DeesElement, type CSSResult, } from '@design.estate/dees-element';
import * as domtools from '@design.estate/dees-domtools';
declare global {
interface HTMLElementTagNameMap {
@ -15,6 +15,12 @@ export class DeesInputQuantitySelector extends DeesElement {
public changeSubject = new domtools.rxjs.Subject();
@property()
public label: string = 'Label';
@property({
type: String,
reflect: true,
})
public key: string;
@property({

View File

@ -1,5 +1,5 @@
import {customElement, DeesElement, TemplateResult, property, html} from '@designestate/dees-element';
import * as domtools from '@designestate/dees-domtools';
import {customElement, DeesElement, type TemplateResult, property, html, type CSSResult,} from '@design.estate/dees-element';
import * as domtools from '@design.estate/dees-domtools';
declare global {
interface HTMLElementTagNameMap {
@ -14,7 +14,10 @@ export class DeesInputRadio extends DeesElement {
// INSTANCE
public changeSubject = new domtools.rxjs.Subject();
@property()
@property({
type: String,
reflect: true,
})
public key: string;
@property()

View File

@ -1,5 +1,5 @@
import {customElement, DeesElement, TemplateResult, property, html, cssManager} from '@designestate/dees-element';
import * as domtools from '@designestate/dees-domtools';
import {customElement, DeesElement, type TemplateResult, property, html, cssManager, type CSSResult,} from '@design.estate/dees-element';
import * as domtools from '@design.estate/dees-domtools';
declare global {
interface HTMLElementTagNameMap {
@ -10,7 +10,7 @@ declare global {
@customElement('dees-input-text')
export class DeesInputText extends DeesElement {
public static demo = () => html`
<dees-input-text .label=${'this is a label'}></dees-input-text>
<dees-input-text .label=${'this is a label'} .value=${'test'}></dees-input-text>
<dees-input-text .isPasswordBool=${true}></dees-input-text>
`;
@ -24,12 +24,14 @@ export class DeesInputText extends DeesElement {
public label: string;
@property({
type: String
type: String,
reflect: true,
})
public key: string;
@property({
type: String
type: String,
reflect: true,
})
public value: string = '';
@ -122,12 +124,12 @@ export class DeesInputText extends DeesElement {
.showPassword:hover {
cursor: pointer;
background: #333;
background: ${cssManager.bdTheme('#00000010', '#ffffff10')};
}
</style>
<div class="maincontainer">
${this.label ? html`<div class="label">${this.label}</div>` : html``}
<input type="${this.isPasswordBool && !this.showPasswordBool ? 'password' : 'text'}" value=${this.value} @input="${this.updateValue}" .disabled=${this.disabled} />
<input type="${this.isPasswordBool && !this.showPasswordBool ? 'password' : 'text'}" .value=${this.value} @input="${this.updateValue}" .disabled=${this.disabled} />
${this.isPasswordBool ? html`
<div class="showPassword" @click=${this.togglePasswordView}>
<dees-icon .iconFA=${this.showPasswordBool ? 'eye' : 'eyeSlash'}></dees-icon>
@ -162,4 +164,9 @@ export class DeesInputText extends DeesElement {
const textInput = this.shadowRoot.querySelector('input');
textInput.focus();
}
public async blur() {
const textInput = this.shadowRoot.querySelector('input');
textInput.blur();
}
}

View File

@ -2,38 +2,34 @@ import * as plugins from './plugins.js';
import {
cssManager,
css,
type CSSResult,
customElement,
DeesElement,
domtools,
html,
property,
} from '@designestate/dees-element';
} from '@design.estate/dees-element';
import { DeesWindowLayer } from './dees-windowlayer.js';
@customElement('dees-mobilenavigation')
export class DeesMobilenavigation extends DeesElement {
// STATIC
public static demo = () => html`
<dees-mobilenavigation
.menuItems="${[
<dees-button @click=${() => {
DeesMobilenavigation.createAndShow([
{
name: 'hello1',
action: async () => {},
name: 'Test',
action: async (deesMobileNav) => {
alert('test');
return null;
},
},
{
name: 'hello2',
action: async () => {},
},
{
name: 'hello3',
action: async () => {},
},
]}"
></dees-mobilenavigation>
]);
}}></dees-button>
`;
private static singletonRef: DeesMobilenavigation;
public static async createAndInit(menuItemsArg: plugins.tsclass.website.IMenuItem[]) {
public static async createAndShow(menuItemsArg: plugins.tsclass.website.IMenuItem<DeesMobilenavigation>[]) {
if (!this.singletonRef) {
this.singletonRef = new DeesMobilenavigation();
document.body.append(this.singletonRef);
@ -56,7 +52,7 @@ export class DeesMobilenavigation extends DeesElement {
})
public menuItems: plugins.tsclass.website.IMenuItem[] = [];
readyDeferred = domtools.plugins.smartpromise.defer();
readyDeferred: plugins.smartpromise.Deferred<any> = domtools.plugins.smartpromise.defer();
constructor() {
super();
@ -93,8 +89,8 @@ export class DeesMobilenavigation extends DeesElement {
right: 0px;
top: 0px;
bottom: 0px;
background: ${cssManager.bdTheme('#eeeeeb', '#000')};;
border-left: 1px dashed #444;
background: ${cssManager.bdTheme('#eeeeeb', '#000')};
border-left: 1px solid ${cssManager.bdTheme('#eeeeeb', '#222')};
pointer-events: none;
}
@ -120,7 +116,7 @@ export class DeesMobilenavigation extends DeesElement {
text-align: left;
font-size: 24px;
padding: 8px 0px;
font-family: Inter;
font-family: 'Roboto', 'Inter', sans-serif;
font-weight: 300;
border-bottom: 1px dashed #444;
margin-top: 16px;
@ -139,7 +135,7 @@ export class DeesMobilenavigation extends DeesElement {
class="menuItem"
@click="${() => {
this.hide();
menuItem.action();
menuItem.action(this);
}}"
>
${menuItem.name}
@ -160,6 +156,7 @@ export class DeesMobilenavigation extends DeesElement {
const main = this.shadowRoot.querySelector('.main');
if (!this.windowLayer) {
this.windowLayer = new DeesWindowLayer();
this.windowLayer.options.blur = true;
this.windowLayer.addEventListener('click', () => {
this.hide();
});

View File

@ -0,0 +1,37 @@
import { html } from '@design.estate/dees-element';
import { DeesModal } from './dees-modal.js';
export const demoFunc = () => html`
<dees-button @click=${() => {
DeesModal.createAndShow({
heading: 'This is a heading',
content: html`
<dees-form>
<dees-input-text
.label=${'Username'}
>
</dees-input-text>
<dees-input-text
.label=${'Password'}
>
</dees-input-text>
</dees-form>
`,
menuOptions: [{
name: 'Cancel',
iconName: null,
action: async (deesModalArg) => {
deesModalArg.destroy();
return null;
}
}, {
name: 'Ok',
iconName: null,
action: async (deesModalArg) => {
deesModalArg.destroy();
return null;
}
}],
});
}}>open modal</dees-button>
`

View File

@ -0,0 +1,196 @@
import * as plugins from './plugins.js';
import { demoFunc } from './dees-modal.demo.js';
import {
customElement,
html,
DeesElement,
property,
type TemplateResult,
cssManager,
css,
type CSSResult,
unsafeCSS,
unsafeHTML,
state,
} from '@design.estate/dees-element';
import * as domtools from '@design.estate/dees-domtools';
import { DeesWindowLayer } from './dees-windowlayer.js';
declare global {
interface HTMLElementTagNameMap {
'dees-modal': DeesModal;
}
}
@customElement('dees-modal')
export class DeesModal extends DeesElement {
// STATIC
public static demo = demoFunc;
public static async createAndShow(optionsArg: {
heading: string;
content: TemplateResult;
menuOptions: plugins.tsclass.website.IMenuItem<DeesModal>[];
}) {
const body = document.body;
const modal = new DeesModal();
modal.heading = optionsArg.heading;
modal.content = optionsArg.content;
modal.menuOptions = optionsArg.menuOptions;
modal.windowLayer = await DeesWindowLayer.createAndShow({
blur: true,
});
modal.windowLayer.addEventListener('click', async () => {
await modal.destroy();
});
body.append(modal.windowLayer);
body.append(modal);
}
// INSTANCE
@property({
type: String,
})
public heading = '';
@state({})
public content: TemplateResult;
@state({})
public menuOptions: plugins.tsclass.website.IMenuItem<DeesModal>[] = [];
constructor() {
super();
}
public static styles = [
cssManager.defaultStyles,
css`
:host {
font-family: 'Roboto', 'Inter', sans-serif;
color: ${cssManager.bdTheme('#333', '#fff')};
}
.modalContainer {
display: flex;
position: fixed;
top: 0px;
left: 0px;
width: 100vw;
height: 100vh;
box-sizing: border-box;
align-items: center;
justify-content: center;
z-index: 2000;
}
.modal {
will-change: transform;
transform: translateY(0px) scale(0.95);
opacity: 0;
width: 480px;
min-height: 120px;
background: #111;
border-radius: 8px;
border: 1px solid #222;
transition: all 0.2s;
overflow: hidden;
box-shadow: 0px 2px 5px #00000080;
}
.modal.show {
opacity: 1;
transform: translateY(0px) scale(1);
}
.modal.show.predestroy {
opacity: 0;
transform: translateY(10px) scale(1);
}
.modal .heading {
height: 32px;
font-family: 'Roboto', 'Inter', sans-serif;
line-height: 32px;
text-align: center;
font-weight: 600;
font-size: 12px;
border-bottom: 1px solid #222;
}
.modal .content {
padding: 16px;
}
.modal .bottomButtons {
display: grid;
border-top: 1px solid #222;
}
.modal .bottomButtons .bottomButton {
height: 40px;
line-height: 40px;
text-align: center;
font-size: 14px;
border-right: 1px solid #222;
cursor: pointer;
}
.modal .bottomButtons .bottomButton:hover {
background: #222;
}
.modal .bottomButtons .bottomButton:last-child {
border-right: none;
}
`,
];
public render(): TemplateResult {
return html`
<style>
.modal .bottomButtons {
grid-template-columns: ${cssManager.cssGridColumns(this.menuOptions.length, 0)};
}
</style>
<div class="modalContainer" @click=${this.handleOutsideClick}>
<div class="modal">
<div class="heading">${this.heading}</div>
<div class="content">${this.content}</div>
<div class="bottomButtons">
${this.menuOptions.map(
(actionArg) => html`
<div class="bottomButton" @click=${() => {
actionArg.action(this);
}}>${actionArg.name}</div>
`
)}
</div>
</div>
</div>
`;
}
private windowLayer: DeesWindowLayer;
public async firstUpdated(_changedProperties: Map<string | number | symbol, unknown>) {
super.firstUpdated(_changedProperties);
const domtools = await this.domtoolsPromise;
await domtools.convenience.smartdelay.delayFor(30);
const modal = this.shadowRoot.querySelector('.modal');
modal.classList.add('show');
}
public async handleOutsideClick(eventArg: MouseEvent) {
eventArg.stopPropagation();
const modalContainer = this.shadowRoot.querySelector('.modalContainer');
if (eventArg.target === modalContainer) {
await this.destroy();
}
}
public async destroy() {
const domtools = await this.domtoolsPromise;
const modal = this.shadowRoot.querySelector('.modal');
modal.classList.add('predestroy');
await domtools.convenience.smartdelay.delayFor(200);
document.body.removeChild(this);
await this.windowLayer.destroy();
}
}

View File

@ -1,8 +1,8 @@
import { DeesElement, property, html, customElement, domtools, TemplateResult } from '@designestate/dees-element';
import { DeesElement, property, html, customElement, domtools, type TemplateResult, type CSSResult, } from '@design.estate/dees-element';
import { Deferred } from '@pushrocks/smartpromise';
import { Deferred } from '@push.rocks/smartpromise';
import type pdfjsTypes from 'pdfjs-dist';
// import type pdfjsTypes from 'pdfjs-dist';
declare global {
interface HTMLElementTagNameMap {
@ -32,7 +32,7 @@ export class DeesPdf extends DeesElement {
return html`
<style>
:host {
font-family: 'Inter', sans-serif;
font-family: 'Roboto', 'Inter', sans-serif;
display: block;
box-sizing: border-box;
max-width: 800px;
@ -51,7 +51,7 @@ export class DeesPdf extends DeesElement {
}
public static pdfJsReady: Promise<any>;
public static pdfjsLib: typeof pdfjsTypes;
public static pdfjsLib: any // typeof pdfjsTypes;
public async connectedCallback() {
super.connectedCallback();
if (!DeesPdf.pdfJsReady) {

View File

@ -0,0 +1,5 @@
import { html } from '@design.estate/dees-element';
export const demoFunc = () => html`
<dees-simple-appdash>Hello there</dees-simple-appdash>
`;

View File

@ -0,0 +1,74 @@
import { demoFunc } from './dees-simple-appdash.demo.js';
import {
customElement,
html,
DeesElement,
property,
type TemplateResult,
cssManager,
css,
unsafeCSS,
type CSSResult,
state,
} from '@design.estate/dees-element';
declare global {
interface HTMLElementTagNameMap {
'dees-simple-appdash': DeesSimpleAppDash;
}
}
@customElement('dees-simple-appdash')
export class DeesSimpleAppDash extends DeesElement {
// STATIC
public static demo = demoFunc;
// INSTANCE
@property()
public name = 'Dees Simple Login';
public static styles = [
cssManager.defaultStyles,
css`
:host {
color: ${cssManager.bdTheme('#333', '#fff')};
user-select: none;
}
.appbar {
position: absolute;
top: 0;
height: 40px;
width: 100%;
background: ${cssManager.bdTheme('#eeeeeb', '#000')};
border-bottom: 1px solid ${cssManager.bdTheme('#ccc', '#333')};
font-size: 14px;
line-height: 40px;
font-family: 'Roboto', 'Inter', sans-serif;
padding: 0px 16px;
}
.appcontent {
position: absolute;
top: 40px;
bottom: 0;
width: 100%;
background: ${cssManager.bdTheme('#eeeeeb', '#000')};
}
`,
];
public render(): TemplateResult {
return html`
<div class="appbar">
configvault v1.2.3
</div>
<div class="appcontent">
<slot></slot>
</div>
`;
}
public async firstUpdated(_changedProperties): Promise<void> {
const domtools = await this.domtoolsPromise;
super.firstUpdated(_changedProperties);
}
}

View File

@ -0,0 +1,3 @@
import { html } from '@design.estate/dees-element';
export const demoFunc = () => html` <dees-simple-login name="someapp"> Hello there </dees-simple-login> `;

View File

@ -0,0 +1,120 @@
import { demoFunc } from './dees-simple-login.demo.js';
import {
customElement,
html,
DeesElement,
property,
type TemplateResult,
cssManager,
css,
unsafeCSS,
type CSSResult,
state,
} from '@design.estate/dees-element';
declare global {
interface HTMLElementTagNameMap {
'dees-simple-login': DeesSimpleLogin;
}
}
@customElement('dees-simple-login')
export class DeesSimpleLogin extends DeesElement {
// STATIC
public static demo = demoFunc
// INSTANCE
@property()
public name = 'Dees Simple Login';
public static styles = [
cssManager.defaultStyles,
css`
:host {
color: ${cssManager.bdTheme('#333', '#fff')};
user-select: none;
}
.loginContainer {
position: absolute;
display: flex;
justify-content: center; /* aligns horizontally */
align-items: center; /* aligns vertically */
width: 100%;
height: 100%;
}
.login {
min-width: 320px;
min-height: 100px;
background: ${cssManager.bdTheme('#eeeeeb', '#111')};
box-shadow: ${cssManager.bdTheme('0px 1px 4px rgba(0,0,0,0.3)', 'none')};
border-radius: 3px;
padding: 24px;
transition: opacity 0.3s, transform 0.3s;
}
.header {
text-align: center;
}
.slotContainer {
opacity:0;
transition: opacity 0.3s, transform 0.3s;
pointer-events: none;
}
`,
];
public render(): TemplateResult {
return html`
<div class="loginContainer">
<div class="login">
<dees-form>
<div class="header">Login to ${this.name}</div>
<dees-input-text key="username" label="username" required></dees-input-text>
<dees-input-text key="password" label="password" isPasswordBool required></dees-input-text>
<dees-form-submit disabled>login</dees-form-submit>
</dees-form>
</div>
</div>
<div class="slotContainer">
<slot></slot>
</div>
`;
}
public async firstUpdated(_changedProperties): Promise<void> {
const domtools = await this.domtoolsPromise;
super.firstUpdated(_changedProperties);
const form = this.shadowRoot.querySelector('dees-form');
await form.readyDeferred.promise;
const username = this.shadowRoot.querySelector('dees-input-text[label="username"]');
const password = this.shadowRoot.querySelector('dees-input-text[label="password"]');
const submit = this.shadowRoot.querySelector('dees-form-submit');
form.addEventListener('formData', (event: CustomEvent) => {
this.dispatchEvent(new CustomEvent('login', { detail: event.detail }));
// this.switchToSlottedContent();
});
}
/**
* allows switching to slotted content
*/
public async switchToSlottedContent() {
const domtools = await this.domtoolsPromise;
const loginDiv: HTMLDivElement = this.shadowRoot.querySelector('.login');
const loginContainerDiv: HTMLDivElement = this.shadowRoot.querySelector('.loginContainer');
const slotContainerDiv: HTMLDivElement = this.shadowRoot.querySelector('.slotContainer');
loginDiv.style.opacity = '0';
loginDiv.style.transform = 'translateY(20px)';
loginContainerDiv.style.pointerEvents = 'none';
slotContainerDiv.style.transform = 'translateY(20px)';
await domtools.convenience.smartdelay.delayFor(300);
slotContainerDiv.style.opacity = '1';
slotContainerDiv.style.transform = 'translateY(0px)';
await domtools.convenience.smartdelay.delayFor(300);
slotContainerDiv.style.pointerEvents = 'all';
}
}

View File

@ -3,13 +3,14 @@ import {
html,
DeesElement,
property,
TemplateResult,
type TemplateResult,
cssManager,
css,
type CSSResult,
unsafeCSS,
} from '@designestate/dees-element';
} from '@design.estate/dees-element';
import * as domtools from '@designestate/dees-domtools';
import * as domtools from '@design.estate/dees-domtools';
declare global {
interface HTMLElementTagNameMap {

View File

@ -3,13 +3,14 @@ import {
html,
DeesElement,
property,
TemplateResult,
type TemplateResult,
cssManager,
css,
type CSSResult,
unsafeCSS,
} from '@designestate/dees-element';
} from '@design.estate/dees-element';
import * as domtools from '@designestate/dees-domtools';
import * as domtools from '@design.estate/dees-domtools';
declare global {
interface HTMLElementTagNameMap {

View File

@ -4,12 +4,13 @@ import {
html,
css,
unsafeCSS,
type CSSResult,
cssManager,
property,
TemplateResult,
} from '@designestate/dees-element';
type TemplateResult,
} from '@design.estate/dees-element';
import * as domtools from '@designestate/dees-domtools';
import * as domtools from '@design.estate/dees-domtools';
export interface IStep {
title: string;
@ -48,15 +49,15 @@ export class DeesStepper extends DeesElement {
`,
validationFunc: async (stepperArg, elementArg) => {
const deesForm = elementArg.querySelector('dees-form');
deesForm.addEventListener('formData', eventArg => {
deesForm.addEventListener('formData', (eventArg) => {
stepperArg.goNext();
})
}
});
},
},
{
title: 'Whats your mobile number?',
content: html``,
}
},
] as IStep[]}
></dees-stepper>
`;
@ -153,7 +154,7 @@ export class DeesStepper extends DeesElement {
.step .title {
text-align: center;
padding-top: 50px;
font-family: Inter;
font-family: 'Roboto', 'Inter', sans-serif;
font-size: 25px;
font-weight: 300;
}
@ -195,22 +196,26 @@ export class DeesStepper extends DeesElement {
return this.steps.findIndex((stepArg2) => stepArg === stepArg2);
};
public firstUpdated() {
public async firstUpdated() {
await this.domtoolsPromise;
await this.domtools.convenience.smartdelay.delayFor(0);
this.selectedStep = this.steps[0];
this.setScrollStatus();
}
public updated() {
public async updated() {
this.setScrollStatus();
}
public scroller: typeof domtools.plugins.SweetScroll.prototype;
public async setScrollStatus() {
await domtools.plugins.smartdelay.delayFor(50);
const stepperContainer: HTMLElement = this.shadowRoot.querySelector('.stepperContainer');
const firstStepElement: HTMLElement = this.shadowRoot.querySelector('.step');
const selectedStepElement: HTMLElement = this.shadowRoot.querySelector('.selected');
if (!selectedStepElement) {
return;
}
if (!stepperContainer.style.paddingTop) {
stepperContainer.style.paddingTop = `${
stepperContainer.offsetHeight / 2 - selectedStepElement.offsetHeight / 2

View File

@ -0,0 +1,129 @@
import { type ITableAction } from './dees-table.js';
import * as plugins from './plugins.js';
import { html } from '@design.estate/dees-element';
interface ITableDemoData {
date: string;
amount: string;
description: string;
}
export const demoFunc = () => html`
<style>
.demoWrapper {
box-sizing: border-box;
position: absolute;
width: 100%;
height: 100%;
padding: 20px;
background: #000000;
}
</style>
<div class="demoWrapper">
<dees-table
heading1="Current Account Statement"
heading2="Bunq - Payment Account 2 - April 2021"
.editableFields="${['description']}"
.data=${[
{
date: '2021-04-01',
amount: '2464.65 €',
description: 'Printing Paper (Office Supplies) - STAPLES BREMEN',
},
{
date: '2021-04-02',
amount: '165.65 €',
description: 'Logitech Mouse (Hardware) - logi.com OnlineShop',
},
{
date: '2021-04-03',
amount: '2999,00 €',
description: 'Macbook Pro 16inch (Hardware) - Apple.de OnlineShop',
},
{
date: '2021-04-01',
amount: '2464.65 €',
description: 'Office-Supplies - STAPLES BREMEN',
},
{
date: '2021-04-01',
amount: '2464.65 €',
description: 'Office-Supplies - STAPLES BREMEN',
},
]}
dataName="transactions"
.dataActions="${[
{
name: 'upload',
iconName: 'bell',
useTableBehaviour: 'upload',
type: ['inRow'],
actionFunc: async (optionsArg) => {
alert(optionsArg.item.amount);
},
},
{
name: 'visibility',
iconName: 'copy',
type: ['inRow'],
useTableBehaviour: 'preview',
actionFunc: async (itemArg: any) => {},
},
{
name: 'create new',
iconName: 'instagram',
type: ['header'],
useTableBehaviour: 'preview',
actionFunc: async (itemArg: any) => {},
},
{
name: 'to gallery',
iconName: 'message',
type: ['footer'],
useTableBehaviour: 'preview',
actionFunc: async (itemArg: any) => {},
},
{
name: 'copy',
iconName: 'copySolid',
type: ['contextmenu', 'inRow'],
action: async () => {
return null;
},
},
{
name: 'edit (from demo)',
iconName: 'penToSquare',
type: ['contextmenu'],
action: async () => {
return null;
},
},
{
name: 'paste',
iconName: 'pasteSolid',
type: ['contextmenu'],
action: async () => {
return null;
},
},
{
name: 'preview',
type: ['doubleClick', 'contextmenu'],
iconName: 'eye',
actionFunc: async (itemArg) => {
alert(itemArg.item.amount);
return null;
},
}
] as (ITableAction<ITableDemoData>)[] as any}"
.displayFunction=${(itemArg) => {
return {
...itemArg,
onlyDisplayProp: 'onlyDisplay',
};
}}
>This is a slotted Text</dees-table
>
</div>
`;

View File

@ -1,16 +1,23 @@
import * as plugins from './plugins.js';
import { demoFunc } from './dees-table.demo.js';
import {
customElement,
html,
DeesElement,
property,
TemplateResult,
type TemplateResult,
cssManager,
css,
unsafeCSS,
type CSSResult,
state,
} from '@designestate/dees-element';
resolveExec,
} from '@design.estate/dees-element';
import * as domtools from '@designestate/dees-domtools';
import { DeesContextmenu } from './dees-contextmenu.js';
import * as domtools from '@design.estate/dees-domtools';
import { type TIconKey } from './dees-icon.js';
declare global {
interface HTMLElementTagNameMap {
@ -18,75 +25,52 @@ declare global {
}
}
export interface IDataAction<T = any> {
// interfaces
export interface ITableAction<T = any> {
name: string;
iconName: string;
iconName: TIconKey;
/**
* the table behaviour to use for this action
* e.g. upload: allows to upload files to the table
*/
useTableBehaviour?: 'upload' | 'cancelUpload' | 'none';
actionFunc: (itemArg: T) => Promise<any>;
/**
* the type of the action
*/
type: (
| 'inRow'
| 'contextmenu'
| 'doubleClick'
| 'footer'
| 'header'
| 'preview'
| 'keyCombination'
)[];
/**
* allows to check if the action is relevant for the given item
* @param itemArg
* @returns
*/
actionRelevancyCheckFunc?: (itemArg: T) => boolean;
/**
* the actual action function implementation
* @param itemArg
* @returns
*/
actionFunc: (actionDataArg: ITableActionDataArg<T>) => Promise<any>;
}
export interface ITableActionDataArg<T> {
item: T,
table: DeesTable<T>,
}
export type TDisplayFunction<T = any> = (itemArg: T) => object;
// the table implementation
@customElement('dees-table')
export class DeesTable<T> extends DeesElement {
public static demo = () => html`
<style>
.demoWrapper {
box-sizing: border-box;
position: absolute;
width: 100%;
height: 100%;
padding: 60px;
background: #000000;
}
</style>
<div class="demoWrapper">
<dees-table
heading1="Current Account Statement"
heading2="Bunq - Payment Account 2 - April 2021"
.data=${[
{
date: '2021-04-01',
amount: '2464.65 €',
description: 'Printing Paper (Office Supplies) - STAPLES BREMEN',
},
{
date: '2021-04-02',
amount: '165.65 €',
description: 'Logitech Mouse (Hardware) - logi.com OnlineShop',
},
{
date: '2021-04-03',
amount: '2999,00 €',
description: 'Macbook Pro 16inch (Hardware) - Apple.de OnlineShop',
},
{
date: '2021-04-01',
amount: '2464.65 €',
description: 'Office-Supplies - STAPLES BREMEN',
},
{
date: '2021-04-01',
amount: '2464.65 €',
description: 'Office-Supplies - STAPLES BREMEN',
},
]}
.dataActions="${[{
name: 'upload',
iconName: 'upload',
useTableBehaviour: 'upload',
actionFunc: async (itemArg: any) => {
},
},{
name: 'visibility',
iconName: 'visibility',
useTableBehaviour: 'preview',
actionFunc: async (itemArg: any) => {
},
}] as IDataAction[]}"
>This is a slotted Text</dees-table>
</div>
`;
public static demo = demoFunc;
// INSTANCE
@property({
@ -104,10 +88,26 @@ export class DeesTable<T> extends DeesElement {
})
public data: T[] = [];
@property({
type: String,
reflect: true,
})
public dataName: string;
@property({
type: Array,
})
public dataActions: IDataAction[] = [];
public dataActions: ITableAction<T>[] = [];
@property({
attribute: false,
})
public displayFunction: TDisplayFunction = (itemArg: T) => itemArg as any;
@property({
attribute: false,
})
public reverseDisplayFunction: (itemArg: any) => T = (itemArg: any) => itemArg as T;
@property({
type: Object,
@ -115,18 +115,15 @@ export class DeesTable<T> extends DeesElement {
public selectedDataRow: T;
@property({
type: String,
type: Array,
})
public type: 'normal' | 'highlighted' | 'discreet' | 'big' = 'normal';
@property({
type: String,
})
public status: 'normal' | 'pending' | 'success' | 'error' = 'normal';
public editableFields: string[] = [];
public files: File[] = [];
public fileWeakMap = new WeakMap();
public dataChangeSubject = new domtools.plugins.smartrx.rxjs.Subject();
constructor() {
super();
}
@ -136,9 +133,9 @@ export class DeesTable<T> extends DeesElement {
css`
.mainbox {
color: ${cssManager.bdTheme('#333', '#fff')};
font-family: 'Inter';
font-family: 'Roboto', 'Inter', sans-serif;
font-weight: 400;
font-size: 16px;
font-size: 14px;
padding: 16px;
display: block;
width: 100%;
@ -149,11 +146,49 @@ export class DeesTable<T> extends DeesElement {
box-shadow: 0px 1px 4px rgba(0, 0, 0, 0.3);
overflow-x: auto;
}
.header {
display: flex;
justify-content: flex-end;
align-items: center;
font-family: 'Roboto', 'Inter', sans-serif;
}
.headingContainer {
}
.heading {
}
.heading1 {
font-weight: 600;
}
.heading2 {
opacity: 0.6;
}
.headingSeparation {
margin-top: 7px;
border-bottom: 1px solid ${cssManager.bdTheme('#bcbcbc', '#bcbcbc')};
}
.headerActions {
margin-left: auto;
cursor: pointer;
}
.headerAction {
display: flex;
color: ${cssManager.bdTheme('#333', '#ccc')};
}
.headerAction:hover {
color: ${cssManager.bdTheme('#555', '#fff')};
}
.headerAction dees-icon {
margin-right: 8px;
}
table,
.noDataSet {
margin-top: 16px;
@ -175,8 +210,8 @@ export class DeesTable<T> extends DeesElement {
tr:hover {
cursor: pointer;
}
tr:hover .innerCellContainer {
background: ${cssManager.bdTheme('#22222210', '#ffffff20')};
tr:hover td {
background: ${cssManager.bdTheme('#22222210', '#ffffff10')};
}
tr:first-child:hover {
cursor: auto;
@ -184,19 +219,32 @@ export class DeesTable<T> extends DeesElement {
tr:first-child:hover .innerCellContainer {
background: none;
}
tr.selected .innerCellContainer {
tr.selected td {
background: ${cssManager.bdTheme('#22222220', '#ffffff20')};
}
tr.hasAttachment td {
background: ${cssManager.bdTheme('#0098847c', '#0098847c')};
}
th {
text-transform: uppercase;
text-transform: none;
font-family: 'Roboto', 'Inter', sans-serif;
font-weight: 500;
}
th,
td {
padding: 3px 0px;
position: relative;
padding: 0px;
border-right: 1px dashed ${cssManager.bdTheme('#999', '#808080')};
}
.innerCellContainer {
min-height: 36px;
position: relative;
height: 100%;
width: 100%;
padding: 6px 8px;
line-height: 24px;
}
th:first-child .innerCellContainer,
td:first-child .innerCellContainer {
@ -210,11 +258,29 @@ export class DeesTable<T> extends DeesElement {
td:last-child {
border-right: none;
}
td input {
width: 100%;
height: 100%;
outline: none;
border: 2px solid #fa6101;
top: 0px;
bottom: 0px;
right: 0px;
left: 0px;
position: absolute;
background: #fa610140;
color: ${cssManager.bdTheme('#333', '#fff')};
font-family: inherit;
font-size: inherit;
font-weight: inherit;
padding: 0px 6px;
}
.action {
margin: -8px 0px;
padding: 8px;
line-height: 16px;
margin: -6px 0px;
padding: 10px;
line-height: 36px;
height: 36px;
display: inline-block;
}
@ -224,17 +290,41 @@ export class DeesTable<T> extends DeesElement {
}
.action:hover {
background: ${cssManager.bdTheme('#CCC', '#111')};
background: ${cssManager.bdTheme('#CCC', '#00000030')};
}
.tableStatistics {
padding: 4px 16px;
font-size: 12px;
.footer {
font-family: 'Roboto', 'Inter', sans-serif;
font-size: 14px;
color: ${cssManager.bdTheme('#111', '#ffffff90')};
background: ${cssManager.bdTheme('#eeeeeb', '#00000050')};
margin: 16px -16px -16px -16px;
border-bottom-left-radius: 3px;
border-bottom-right-radius: 3px;
display: flex;
}
.tableStatistics {
padding: 8px 16px;
}
.footerActions {
margin-left: auto;
}
.footerActions .footerAction {
cursor: pointer;
padding: 8px 16px;
display: flex;
}
.footerActions .footerAction:hover {
background: ${cssManager.bdTheme('#CCC', '#111')};
}
.footerActions dees-icon {
display: flex;
margin-right: 8px;
}
`,
];
@ -243,15 +333,47 @@ export class DeesTable<T> extends DeesElement {
return html`
<div class="mainbox">
<!-- the heading part -->
<div>${this.heading1}</div>
<div>${this.heading2}</div>
<div class="header">
<div class="headingContainer">
<div class="heading heading1">${this.heading1}</div>
<div class="heading heading2">${this.heading2}</div>
</div>
<div class="headerActions">
${resolveExec(async () => {
const resultArray: TemplateResult[] = [];
for (const action of this.dataActions) {
if (!action.type.includes('header')) continue;
resultArray.push(
html`<div
class="headerAction"
@click=${() => {
action.actionFunc({
item: this.selectedDataRow,
table: this,
});
}}
>
${action.iconName
? html`<dees-icon .iconSize=${14} .iconFA=${action.iconName}></dees-icon>
${action.name}`
: action.name}
</div>`
);
}
return resultArray;
})}
</div>
</div>
<div class="headingSeparation"></div>
<!-- the actual table -->
<style></style>
${this.data.length > 0
? (() => {
const headings: string[] = Object.keys(this.data[0]);
// Only pick up the keys from the first transformed data object
// as all data objects are assumed to have the same structure
const firstTransformedItem = this.displayFunction(this.data[0]);
const headings: string[] = Object.keys(firstTransformedItem);
return html`
<table>
<tr>
@ -272,32 +394,42 @@ export class DeesTable<T> extends DeesElement {
}
})()}
</tr>
${this.data.map(
(itemArg) => html`
${this.data.map((itemArg) => {
const transformedItem = this.displayFunction(itemArg);
const getTr = (elementArg: HTMLElement): HTMLElement => {
if (elementArg.tagName === 'TR') {
return elementArg;
} else {
return getTr(elementArg.parentElement);
}
};
return html`
<tr
@click=${() => {
this.selectedDataRow = itemArg;
}}
@dragenter=${async (eventArg: DragEvent) => {
console.log((eventArg.target as HTMLElement).tagName)
console.log('dragenter');
eventArg.preventDefault();
eventArg.stopPropagation();
(eventArg.target as HTMLElement).parentElement.style.background = '#800000';
const realTarget = getTr(eventArg.target as HTMLElement);
console.log('dragenter');
console.log(realTarget);
setTimeout(() => {
realTarget.classList.add('hasAttachment');
}, 0);
}}
@dragleave=${async (eventArg: DragEvent) => {
console.log((eventArg.target as HTMLElement).tagName)
console.log('dragleave');
eventArg.preventDefault();
eventArg.stopPropagation();
(eventArg.target as HTMLElement).parentElement.style.background = 'none';
const realTarget = getTr(eventArg.target as HTMLElement);
realTarget.classList.remove('hasAttachment');
}}
@dragover=${async (eventArg: DragEvent) => {
eventArg.preventDefault();
}}
@drop=${async (eventArg: DragEvent) => {
eventArg.preventDefault();
const newFiles = []
const newFiles = [];
for (const file of Array.from(eventArg.dataTransfer.files)) {
this.files.push(file);
newFiles.push(file);
@ -305,17 +437,52 @@ export class DeesTable<T> extends DeesElement {
}
const result: File[] = this.fileWeakMap.get(itemArg as object);
if (!result) {
this.fileWeakMap.set(itemArg as object, newFiles)
this.fileWeakMap.set(itemArg as object, newFiles);
} else {
result.push(...newFiles);
}
}}
@contextmenu=${async (eventArg: MouseEvent) => {
DeesContextmenu.openContextMenuWithOptions(
eventArg,
this.getActionsForType('contextmenu').map((action) => {
const menuItem: plugins.tsclass.website.IMenuItem = {
name: action.name,
iconName: action.iconName as any,
action: async () => {
await action.actionFunc({
item: itemArg,
table: this,
});
return null;
},
};
return menuItem;
})
);
}}
class="${itemArg === this.selectedDataRow ? 'selected' : ''}"
>
${headings.map(
(headingArg) => html`
<td>
<div class="innerCellContainer">${itemArg[headingArg]}</div>
<td
@dblclick=${(e: Event) => {
if (this.editableFields.includes(headingArg)) {
this.handleCellEditing(e, itemArg, headingArg);
} else {
const wantedAction = this.dataActions.find((actionArg) =>
actionArg.type.includes('doubleClick')
);
if (wantedAction) {
wantedAction.actionFunc({
item: itemArg,
table: this,
});
}
}
}}
>
<div class="innerCellContainer">${transformedItem[headingArg]}</div>
</td>
`
)}
@ -324,36 +491,154 @@ export class DeesTable<T> extends DeesElement {
return html`
<td>
<div class="innerCellContainer">
${(() => {
const actions: TemplateResult[] = [];
for (const action of this.dataActions) {
actions.push(html`<div class="action">${action.iconName ? html`
<dees-icon .iconName=${'upload_file'}></dees-icon>
` : action.name}</div>`)
}
return actions;
})()}
${this.getActionsForType('inRow').map(
(actionArg) => html`<div
class="action"
@click=${() => actionArg.actionFunc({
item: itemArg,
table: this,
})}
>
${actionArg.iconName
? html`
<dees-icon .iconFA=${actionArg.iconName}></dees-icon>
`
: actionArg.name}
</div>`
)}
</div>
</td>
`;
}
})()}
</tr>
`
)}
`;
})}
</table>
`;
})()
: html` <div class="noDataSet">No data set!</div> `}
<div class="tableStatistics">
${this.data.length} data rows (total) |
${this.selectedDataRow
? html`Row ${this.data.indexOf(this.selectedDataRow) + 1} selected`
: html`No row selected`}
<div class="footer">
<div class="tableStatistics">
${this.data.length} ${this.dataName || 'data rows'} (total) |
${this.selectedDataRow ? '# ' + `${this.data.indexOf(this.selectedDataRow) + 1}` : `No`}
selected
</div>
<div class="footerActions">
${resolveExec(async () => {
const resultArray: TemplateResult[] = [];
for (const action of this.dataActions) {
if (!action.type.includes('footer')) continue;
resultArray.push(
html`<div
class="footerAction"
@click=${() => {
action.actionFunc({
item: this.selectedDataRow,
table: this,
});
}}
>
${action.iconName
? html`<dees-icon .iconSize=${14} .iconFA=${action.iconName}></dees-icon>
${action.name}`
: action.name}
</div>`
);
}
return resultArray;
})}
</div>
</div>
</div>
`;
}
public async firstUpdated() {}
public async updated(changedProperties: Map<string | number | symbol, unknown>): Promise<void> {
super.updated(changedProperties);
this.freezeColumnWidths();
}
freezeColumnWidths() {
// Get the table element
const table = this.shadowRoot.querySelector('table');
if (!table) return;
// Create a colgroup if it doesn't exist
let colgroup = table.querySelector('colgroup');
if (!colgroup) {
colgroup = document.createElement('colgroup');
table.insertBefore(colgroup, table.firstChild);
}
// Get the first row's cells to measure the widths
const cells = table.rows[0].cells;
for (let i = 0; i < cells.length; i++) {
const cell = cells[i];
// Get computed width
const width = window.getComputedStyle(cell).width;
// Check if there's already a <col> for this cell
let col = colgroup.children[i] as HTMLElement;
if (!col) {
col = document.createElement('col');
colgroup.appendChild(col);
}
// Set the width
col.style.width = width;
}
}
getActionsForType(typeArg: ITableAction['type'][0]) {
const actions: ITableAction[] = [];
for (const action of this.dataActions) {
if (!action.type.includes(typeArg)) continue;
actions.push(action);
}
return actions;
}
async handleCellEditing(event: Event, itemArg: T, key: string) {
const domtools = await this.domtoolsPromise;
const target = event.target as HTMLElement;
const originalColor = target.style.color;
target.style.color = 'transparent';
const transformedItem = this.displayFunction(itemArg);
const initialValue = (transformedItem[key] as unknown as string) || '';
// Create an input element
const input = document.createElement('input');
input.type = 'text';
input.value = initialValue;
const blurInput = async (blurArg = true, saveArg = false) => {
if (blurArg) {
input.blur();
}
if (saveArg) {
itemArg[key] = input.value as any; // Convert string to T (you might need better type casting depending on your data structure)
}
input.remove();
target.style.color = originalColor;
this.requestUpdate();
};
// When the input loses focus or the Enter key is pressed, update the data
input.addEventListener('blur', () => {
blurInput(false, false);
});
input.addEventListener('keydown', (e: KeyboardEvent) => {
if (e.key === 'Enter') {
blurInput(true, true); // This will trigger the blur event handler above
}
});
// Replace the cell's content with the input
target.appendChild(input);
input.focus();
}
}

View File

@ -0,0 +1,5 @@
import { html } from '@design.estate/dees-element';
export const demoFunc = async () => {
return html`<dees-toast></dees-toast>`;
}

View File

@ -1,6 +1,7 @@
import { customElement, DeesElement, TemplateResult, html } from '@designestate/dees-element';
import { customElement, DeesElement, type TemplateResult, html, type CSSResult, } from '@design.estate/dees-element';
import * as domtools from '@designestate/dees-domtools';
import * as domtools from '@design.estate/dees-domtools';
import { demoFunc } from './dees-toast.demo.js';
declare global {
interface HTMLElementTagNameMap {
@ -10,6 +11,7 @@ declare global {
@customElement('dees-toast')
export class DeesToast extends DeesElement {
public static demo = demoFunc;
constructor() {
super();

View File

@ -1 +1 @@
import {} from '@designestate/dees-element';
import {} from '@design.estate/dees-element';

View File

@ -1,10 +1,10 @@
import { customElement, DeesElement, TemplateResult, html, property } from '@designestate/dees-element';
import { customElement, DeesElement, type TemplateResult, html, property, type CSSResult, } from '@design.estate/dees-element';
import * as domtools from '@designestate/dees-domtools';
import * as domtools from '@design.estate/dees-domtools';
import './dees-windowlayer';
import { css, cssManager } from '@designestate/dees-element';
import { css, cssManager } from '@design.estate/dees-element';
declare global {
interface HTMLElementTagNameMap {

View File

@ -1,6 +1,6 @@
import { customElement, DeesElement, TemplateResult, html, property } from '@designestate/dees-element';
import { customElement, DeesElement, type TemplateResult, html, property, type CSSResult, state, } from '@design.estate/dees-element';
import * as domtools from '@designestate/dees-domtools';
import * as domtools from '@design.estate/dees-domtools';
declare global {
interface HTMLElementTagNameMap {
@ -8,11 +8,33 @@ declare global {
}
}
export interface IOptions_DeesWindowLayer {
blur: boolean;
}
@customElement('dees-windowlayer')
export class DeesWindowLayer extends DeesElement {
// STATIC
public static demo = () => html`<dees-windowlayer></dees-windowlayer>`;
public static async createAndShow(optionsArg?: IOptions_DeesWindowLayer) {
const domtoolsInstance = domtools.DomTools.getGlobalDomToolsSync();
const windowLayer = new DeesWindowLayer();
windowLayer.options = {
...windowLayer.options,
...optionsArg,
}
document.body.append(windowLayer);
await domtoolsInstance.convenience.smartdelay.delayFor(0);
windowLayer.show();
return windowLayer;
}
@state()
public options: IOptions_DeesWindowLayer = {
blur: false
};
// INSTANCE
@property({
type: Boolean
@ -29,7 +51,7 @@ export class DeesWindowLayer extends DeesElement {
${domtools.elementBasic.styles}
<style>
.windowOverlay {
transition: all 0.3s;
transition: all 0.2s;
will-change: transform;
position: fixed;
top: 0px;
@ -40,14 +62,14 @@ export class DeesWindowLayer extends DeesElement {
justify-content: center;
align-items: center;
background: rgba(0, 0, 0, 0.0);
backdrop-filter: brightness(1);
backdrop-filter: brightness(1) ${this.options.blur ? 'blur(0px)' : ''};
pointer-events: none;
z-index: 200;
}
.visible {
background: rgba(0, 0, 0, 0.2);
backdrop-filter: brightness(0.3);
backdrop-filter: brightness(0.9) ${this.options.blur ? 'blur(2px)' : ''};
pointer-events: all;
}
</style>
@ -82,4 +104,11 @@ export class DeesWindowLayer extends DeesElement {
await domtools.convenience.smartdelay.delayFor(0);
this.visible = false;
}
public async destroy() {
const domtools = await this.domtoolsPromise;
await this.hide();
await domtools.convenience.smartdelay.delayFor(300);
this.remove();
}
}

View File

@ -0,0 +1,3 @@
export class FormController {
}

View File

@ -4,8 +4,9 @@ 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-form.js';
export * from './dees-form-submit.js';
export * from './dees-form.js';
export * from './dees-hint.js';
export * from './dees-icon.js';
export * from './dees-input-checkbox.js';
export * from './dees-input-dropdown.js';
@ -14,7 +15,10 @@ export * from './dees-input-quantityselector.js';
export * from './dees-input-radio.js';
export * from './dees-input-text.js';
export * from './dees-mobilenavigation.js';
export * from './dees-modal.js';
export * from './dees-pdf.js';
export * from './dees-simple-appdash.js';
export * from './dees-simple-login.js';
export * from './dees-speechbubble.js';
export * from './dees-spinner.js';
export * from './dees-stepper.js';

View File

@ -1,3 +1,11 @@
// @push.rocks scope
import * as smartpromise from '@push.rocks/smartpromise';
export {
smartpromise,
}
// @tsclass scope
import * as tsclass from '@tsclass/tsclass';
export {

View File

@ -5,6 +5,10 @@
"target": "ES2022",
"module": "ES2022",
"moduleResolution": "nodenext",
"esModuleInterop": true
}
"esModuleInterop": true,
"verbatimModuleSyntax": true
},
"exclude": [
"dist_*/**/*.d.ts"
]
}