Compare commits

..

No commits in common. "master" and "v1.5.3" have entirely different histories.

17 changed files with 157 additions and 1262 deletions

@ -1,48 +1,5 @@
# Changelog
## 2025-04-25 - 1.8.0 - feat(dees-pagination)
Add new pagination component to the library along with its demo and integration in the main export.
- Introduced dees-pagination component with support for various page range scenarios.
- Created demo file to showcase pagination with both small and large sets of pages.
- Updated the module's index to export the new pagination component.
## 2025-04-22 - 1.7.0 - feat(dees-searchbar)
Add dees-searchbar component with live search and filter demo
- Introduces a new dees-searchbar element with an input field, a search button, and filters
- Wires up events for 'search-changed' and 'search-submit' to provide realtime feedback
- Adds a demo file to showcase usage and logging of search events
## 2025-04-22 - 1.6.0 - feat(documentation/dees-heading)
Add codex documentation overview and dees-heading component demo
- Introduce 'codex.md' to provide a high-level overview of project layout, component patterns, and build workflow
- Add and update dees-heading component with demo to support multiple heading levels and horizontal rule styles
- Update component export index to include dees-heading
## 2025-04-18 - 1.5.6 - fix(dependencies)
Bump dependency versions and update demo code references
- Upgrade @design.estate/dees-element from ^2.0.39 to ^2.0.41
- Upgrade @tsclass/tsclass from ^4.4.0 to ^9.0.0
- Upgrade lucide from ^0.488.0 to ^0.501.0
- Update @types/node from ^22.10.7 to ^22.14.1
- Update dees-icon demo: scope search to demo container and adjust hover scaling
- Replace resolveExec with directives.resolveExec in dees-table for proper rendering
## 2025-04-12 - 1.5.5 - fix(catalog)
No code or documentation changes were detected. This commit records an empty update in commit information and confirms that the current state remains stable.
- Verified that there are no modifications in source, documentation, or demos
- Commit metadata and build configuration remain unchanged
## 2025-04-11 - 1.5.4 - fix(readme)
Update readme with company and trademark guidelines, clarifying legal usage without exposing licensing details.
- Added sections detailing company information and trademark guidelines.
- Outlined legal disclaimers for trademark usage.
## 2025-04-11 - 1.5.3 - fix(readme)
Update readme.md: remove redundant usage section and refine component documentation with improved examples.

@ -1,43 +0,0 @@
# Codex: Project Overview and Codebase Structure
## Project Overview
- Package: `@design.estate/dees-catalog`
- Focus: Web Components library providing UI elements and layouts for modern web apps.
## Directory Layout
- ts_web/: TypeScript source files
- elements/: Individual Web Component definitions
- pages/: Page-level templates for composite layouts
- html/: Demo/app entry point loading the bundled scripts
- dist_bundle/: Bundled browser JS and source maps
- dist_ts_web/: ES module outputs for TypeScript/web consumers
- dist_watch/: Watch-mode development bundle with live reload
- test/: Browser-based tests using `@push.rocks/tapbundle`
## Component Patterns
- Each component in ts_web/elements/:
- Decorated with `@customElement('tag-name')`
- Extends `DeesElement` from `@design.estate/dees-element`
- Uses `@property` for reactive, reflected attributes
- Defines `static styles = [cssManager.defaultStyles, css`...`]`
- Implements `render()` returning a Lit `html` template with slots or markup
- Exposes a demo via `public static demo` linking to `.demo.ts` files
## Build & Development Workflow
- Install dependencies: `npm install` or `pnpm install`
- Build production bundle: `npm run build`
- Start dev watch mode: `npm run watch`
- Run tests: `npm test` (launches browser fixtures)
## Theming & Utilities
- Default global styles via `cssManager.defaultStyles`
- Theme-aware values with `cssManager.bdTheme(light, dark)`
- DOM utilities set up in `html/index.ts` using `@design.estate/dees-domtools`
## Documentation
- `readme.md` provides an overview of all components and basic usage
- Live examples in `.demo.ts` files
accessible via component `demo` static property
## Updates to this file
If you have pattern insisights or general changes to the codebase, please update this file.

@ -1,6 +1,6 @@
{
"name": "@design.estate/dees-catalog",
"version": "1.8.0",
"version": "1.5.3",
"private": false,
"description": "A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript.",
"main": "dist_ts_web/index.js",
@ -16,7 +16,7 @@
"license": "MIT",
"dependencies": {
"@design.estate/dees-domtools": "^2.1.1",
"@design.estate/dees-element": "^2.0.41",
"@design.estate/dees-element": "^2.0.39",
"@design.estate/dees-wcctools": "^1.0.90",
"@fortawesome/fontawesome-svg-core": "^6.7.2",
"@fortawesome/free-brands-svg-icons": "^6.7.2",
@ -25,12 +25,11 @@
"@push.rocks/smarti18n": "^1.0.4",
"@push.rocks/smartpromise": "^4.2.0",
"@push.rocks/smartstring": "^4.0.15",
"@tsclass/tsclass": "^9.0.0",
"@tsclass/tsclass": "^4.4.0",
"@webcontainer/api": "1.2.0",
"apexcharts": "^4.3.0",
"highlight.js": "11.11.1",
"ibantools": "^4.5.1",
"lucide": "^0.501.0",
"monaco-editor": "^0.52.2",
"pdfjs-dist": "^4.10.38",
"xterm": "^5.3.0",
@ -43,7 +42,7 @@
"@git.zone/tswatch": "^2.0.37",
"@push.rocks/projectinfo": "^5.0.2",
"@push.rocks/tapbundle": "^5.5.6",
"@types/node": "^22.14.1"
"@types/node": "^22.10.7"
},
"files": [
"ts/**/*",

223
pnpm-lock.yaml generated

@ -12,8 +12,8 @@ importers:
specifier: ^2.1.1
version: 2.3.2
'@design.estate/dees-element':
specifier: ^2.0.41
version: 2.0.41
specifier: ^2.0.39
version: 2.0.39
'@design.estate/dees-wcctools':
specifier: ^1.0.90
version: 1.0.90
@ -39,8 +39,8 @@ importers:
specifier: ^4.0.15
version: 4.0.15
'@tsclass/tsclass':
specifier: ^9.0.0
version: 9.0.0
specifier: ^4.4.0
version: 4.4.4
'@webcontainer/api':
specifier: 1.2.0
version: 1.2.0
@ -53,9 +53,6 @@ importers:
ibantools:
specifier: ^4.5.1
version: 4.5.1
lucide:
specifier: ^0.501.0
version: 0.501.0
monaco-editor:
specifier: ^0.52.2
version: 0.52.2
@ -88,8 +85,8 @@ importers:
specifier: ^5.5.6
version: 5.6.3(@aws-sdk/credential-providers@3.787.0)(socks@2.8.4)
'@types/node':
specifier: ^22.14.1
version: 22.14.1
specifier: ^22.10.7
version: 22.14.0
packages:
@ -102,8 +99,8 @@ packages:
'@api.global/typedrequest@3.1.10':
resolution: {integrity: sha512-EiCp44XVcMjBvEs4oM1nMUaeY4ySU0Pzt3+mDwVG5DNP6EV87Nwancbr2jKScvaFNel9eeDgGtgEnFBKjOnApA==}
'@api.global/typedserver@3.0.74':
resolution: {integrity: sha512-lrXaCPaVZLihlF9w39pEqTw2kiHFCheRKTZuK07S7gTGyfdXKPmccVR/EK4ox58E1gjh9A2K8yY8ZWGcjuSJkw==}
'@api.global/typedserver@3.0.72':
resolution: {integrity: sha512-GO6SzPEAIlBrW3xUnorYJAzJycktpq5UG6FzGnfk8GkWwAMUFc3anWc7MPXrM79Mbwqtm0D3Lh9fBWPY56z2Jw==}
'@api.global/typedsocket@3.0.1':
resolution: {integrity: sha512-xojiAVNXtHoxkpBo8U2HHJG8FrVXXuLvDNndSHXwx4C9VslUwDn5zSCI+PdBl8iAg+ZuBmKjqkpZZ9sL6DC5yQ==}
@ -283,8 +280,8 @@ packages:
resolution: {integrity: sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==}
engines: {node: '>=6.9.0'}
'@cloudflare/workers-types@4.20250418.0':
resolution: {integrity: sha512-cPnHbEAryOX1FwEjjMXXCLudkxXUlfy7Hf55lqTPpYRSUA76NGLFfkhUF7+KkRrFg2u6pNpXTj24Gv5pMEHlqg==}
'@cloudflare/workers-types@4.20250410.0':
resolution: {integrity: sha512-Yx9VUi6QpmXtUIhOL+em+V02gue12kmVBVL6RGH5mhFh50M0x9JyOmm6wKwKZUny2uQd+22nuouE2q3z1OrsIQ==}
'@colors/colors@1.6.0':
resolution: {integrity: sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==}
@ -302,8 +299,8 @@ packages:
'@design.estate/dees-domtools@2.3.2':
resolution: {integrity: sha512-RfXR2t67M9kaCoF6CBkKJtVdsdp6p1O7S1OaWjrs8V0S3277ch4bSYfO+8f+QYweXKkI6Tr2PKaq3PIlwFSC1g==}
'@design.estate/dees-element@2.0.41':
resolution: {integrity: sha512-Ss3wq4FJZnPn/6Zcl/oPZJARZElrkm1lmIUFdl5NXwSXBdYthk0sK2agPbrOPIEfutx65R6G4XZZ4rLhirHVBQ==}
'@design.estate/dees-element@2.0.39':
resolution: {integrity: sha512-AQdGU/+GmWmU5M5pDf+GWT7GU8UN073WZvtIkfqQZemxd35HYU1vpi629m8/PjKd5dIHAU7QN2mKb6IQ8anPgw==}
'@design.estate/dees-wcctools@1.0.90':
resolution: {integrity: sha512-EHYWHiOe+P261e9fBbOBmkD7lIsOpD+tu4VZQr20oc8vhsFjeUGJqYeBm/Ghwg+Gck/dto+K9zyJNIyQ642cEw==}
@ -688,8 +685,8 @@ packages:
'@lit-labs/ssr-dom-shim@1.3.0':
resolution: {integrity: sha512-nQIWonJ6eFAvUUrSlwyHDm/aE8PBDu5kRpL0vHMg6K8fK3Diq1xdPjTnsJSwxABhaZ+5eBi1btQB5ShUTKo4nQ==}
'@lit/reactive-element@2.1.0':
resolution: {integrity: sha512-L2qyoZSQClcBmq0qajBVbhYEcG6iK0XfLn66ifLe/RfC0/ihpc+pl0Wdn8bJ8o+hj38cG0fGXRgSS20MuXn7qA==}
'@lit/reactive-element@2.0.4':
resolution: {integrity: sha512-GFn91inaUa2oHLak8awSIigYz0cU0Payr1rcFsrkf5OJ5eSPxElyZfKh0f2p9FsTiZWXQdWGJeXZICEfXXYSXQ==}
'@mixmark-io/domino@2.2.0':
resolution: {integrity: sha512-Y28PR25bHXUg88kCV7nivXrP2Nj2RueZ3/l/jdx6J9f8J4nsEGcgX0Qe6lt7Pa+J79+kPiJU3LguR6O/6zrLOw==}
@ -867,8 +864,8 @@ packages:
'@push.rocks/smartbucket@3.3.7':
resolution: {integrity: sha512-RiOuEtwHJ+HFbV1nlZgh5VuMvP6PXElX6rVe7OSQsyNCBybRQa/d1qDic92+2Ejx852DGeHlyREELQCxd/a/7w==}
'@push.rocks/smartbuffer@3.0.5':
resolution: {integrity: sha512-pWYF08Mn8s/KF/9nHRk7pZPzuMjmYVQay2c5gGexdayxn1W4eCSYYhWH73vR2JBfGeGq/izbRNuUuEaIEeTIKA==}
'@push.rocks/smartbuffer@3.0.4':
resolution: {integrity: sha512-TLfhx/JD61YC8XGO9TI6Ux6US38R14HaIM84QT8hZZod8axfXrg+h8xA8tMUBpSV8PXsQy9LzxmOq0Il1fmDXw==}
'@push.rocks/smartcache@1.0.16':
resolution: {integrity: sha512-UAXf74eDuH4/RebJhydIbHlYVR3ACYJjniEY/9ZePblu7bIPgwFZqLBE9g1lcKVogbH9yY62dk3rSpgBzenyfQ==}
@ -882,8 +879,8 @@ packages:
'@push.rocks/smartcrypto@2.0.4':
resolution: {integrity: sha512-1+/5bsjyataf5uUkUNnnVXGRAt+gHVk1KDzozjTqgqJxHvQk1d9fVDohL6CxUhUucTPtu5VR5xNBiV8YCDuGyw==}
'@push.rocks/smartdata@5.9.2':
resolution: {integrity: sha512-w/Yi98B8u6yfZIPrlERmBnkWStJVFkv+dePwptg3oA5nWLdLgwQT/t/aEu+HP0nQy7Hgi9fb55AOY4UCFVD+lg==}
'@push.rocks/smartdata@5.6.0':
resolution: {integrity: sha512-cqGMAGnagmnbuhRIdbS3IY68hYuh1EtdxjgpKx5lXZHnTgYWtJnF0CM/MBsQZUoA+JI9Zti+cZsKNI0y7OvIYw==}
'@push.rocks/smartdelay@3.0.5':
resolution: {integrity: sha512-mUuI7kj2f7ztjpic96FvRIlf2RsKBa5arw81AHNsndbxO6asRcxuWL8dTVxouEIK8YsBUlj0AsrCkHhMbLQdHw==}
@ -1434,11 +1431,8 @@ packages:
'@tsclass/tsclass@4.4.4':
resolution: {integrity: sha512-YZOAF+u+r4u5rCev2uUd1KBTBdfyFdtDmcv4wuN+864lMccbdfRICR3SlJwCfYS1lbeV3QNLYGD30wjRXgvCJA==}
'@tsclass/tsclass@8.2.1':
resolution: {integrity: sha512-bRDCfJTipsTcK6eEokWdsOR1mGCQFeM7zTg6PRHzbxTWQcWQD9AhEr2q3CrPcmAbvIS7fvkO6/pU/mPm1MZxhQ==}
'@tsclass/tsclass@9.0.0':
resolution: {integrity: sha512-QuV2WKzi3p1ONq0UR+hNulG62D6vRPJxOXunWvN9zpWx6Uj70DKntMu8nqEIWUPgL3UKIPe7GN8l6mPCdxdcEg==}
'@tsclass/tsclass@8.2.0':
resolution: {integrity: sha512-qh3hhW5k030n3XVz6hDNrRPYZTTAvy7FZSnKYZXCRYV/JpNZw84daI4G4CgECOX/LAWAiW57MRwsFbShTddYBA==}
'@types/accepts@1.3.7':
resolution: {integrity: sha512-Pay9fq2lM2wXPWbteBsRAGiWH2hig4ZE2asK+mm7kUzlxRTfL961rj89I6zV/E3PcIkDqyuBEcMxFT7rccugeQ==}
@ -1585,8 +1579,8 @@ packages:
'@types/node-forge@1.3.11':
resolution: {integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==}
'@types/node@22.14.1':
resolution: {integrity: sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw==}
'@types/node@22.14.0':
resolution: {integrity: sha512-Kmpl+z84ILoG+3T/zQFyAJsU6EPTmOCj8/2+83fSN6djd6I4o7uOuGIH6vq3PrjY5BGitSbFuMN18j3iknubbA==}
'@types/parse5@6.0.3':
resolution: {integrity: sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==}
@ -3013,14 +3007,14 @@ packages:
lines-and-columns@1.2.4:
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
lit-element@4.2.0:
resolution: {integrity: sha512-MGrXJVAI5x+Bfth/pU9Kst1iWID6GHDLEzFEnyULB/sFiRLgkd8NPK/PeeXxktA3T6EIIaq8U3KcbTU5XFcP2Q==}
lit-element@4.1.1:
resolution: {integrity: sha512-HO9Tkkh34QkTeUmEdNYhMT8hzLid7YlMlATSi1q4q17HE5d9mrrEHJ/o8O2D0cMi182zK1F3v7x0PWFjrhXFew==}
lit-html@3.3.0:
resolution: {integrity: sha512-RHoswrFAxY2d8Cf2mm4OZ1DgzCoBKUKSPvA1fhtSELxUERq2aQQ2h05pO9j81gS1o7RIRJ+CePLogfyahwmynw==}
lit-html@3.2.1:
resolution: {integrity: sha512-qI/3lziaPMSKsrwlxH/xMgikhQ0EGOX2ICU73Bi/YHFvz2j/yMCIrw4+puF2IpQ4+upd3EWbvnHM9+PnJn48YA==}
lit@3.3.0:
resolution: {integrity: sha512-DGVsqsOIHBww2DqnuZzW7QsuCdahp50ojuDaBPC7jUDRpYoH0z7kHBBYZewRzer75FwtrkmkKk7iOAwSaWdBmw==}
lit@3.2.1:
resolution: {integrity: sha512-1BBa1E/z0O9ye5fZprPtdqnc0BFzxIxTTOO/tQFmyC/hj1O3jL4TfmLBw0WEwjAokdLwpclkvGgDJwTIh0/22w==}
locate-path@5.0.0:
resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==}
@ -3098,9 +3092,6 @@ packages:
resolution: {integrity: sha512-MhWWlVnuab1RG5/zMRRcVGXZLCXrZTgfwMikgzCegsPnG62yDQo5JnqKkrK4jO5iKqDAZGItAqN5CtKBCBWRUA==}
engines: {node: '>=16.14'}
lucide@0.501.0:
resolution: {integrity: sha512-ufrFxsi7s5dcuDgR/z21CqP61jyMshh2BghKaEviz3nrFohrJWZtjvHvlamDaNzeJU1tGTxxPMbWqkmTPBijjA==}
make-dir@3.1.0:
resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==}
engines: {node: '>=8'}
@ -4125,8 +4116,8 @@ packages:
resolution: {integrity: sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==}
engines: {node: '>=12'}
tr46@5.1.1:
resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==}
tr46@5.1.0:
resolution: {integrity: sha512-IUWnUK7ADYR5Sl1fZlO1INDUhVhatWl7BtJWsIhwJ0UAK7ilzzIa8uIqOO/aYVWHZPJkKbEL+362wrzoeRF7bw==}
engines: {node: '>=18'}
tree-kill@1.2.2:
@ -4172,8 +4163,8 @@ packages:
resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==}
engines: {node: '>=12.20'}
type-fest@4.40.0:
resolution: {integrity: sha512-ABHZ2/tS2JkvH1PEjxFDTUWC8dB5OsIGZP4IFLhR293GqT5Y5qB1WwL2kMPYhQW9DVgVD8Hd7I8gjwPIf5GFkw==}
type-fest@4.39.1:
resolution: {integrity: sha512-uW9qzd66uyHYxwyVBYiwS4Oi0qZyUqwjU+Oevr6ZogYiXt99EOYtwvzMSLw1c3lYo2HzJsep/NB23iEVEgjG/w==}
engines: {node: '>=16'}
type-is@1.6.18:
@ -4404,8 +4395,8 @@ packages:
resolution: {integrity: sha512-2OQsPNEmBCvXuFlIni/a+Rn+R2pHW9INm0BxXJ4hVDA8TirqMj+J/Rp9ItLatT/5pZqWwefVrTQcHpixsxnVlA==}
engines: {node: '>= 4.0.0'}
zod@3.24.3:
resolution: {integrity: sha512-HhY1oqzWCQWuUqvBFnsyrtZRhyPeR7SUGv+C4+MsisMuVfSPx8HpwWqH8tRahSlt6M3PiFAcoeFhZAqIXTxoSg==}
zod@3.24.2:
resolution: {integrity: sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==}
zwitch@2.0.4:
resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
@ -4421,19 +4412,19 @@ snapshots:
'@api.global/typedrequest-interfaces': 3.0.19
'@push.rocks/isounique': 1.0.5
'@push.rocks/lik': 6.1.0
'@push.rocks/smartbuffer': 3.0.5
'@push.rocks/smartbuffer': 3.0.4
'@push.rocks/smartdelay': 3.0.5
'@push.rocks/smartguard': 3.1.0
'@push.rocks/smartpromise': 4.2.3
'@push.rocks/webrequest': 3.0.37
'@push.rocks/webstream': 1.0.10
'@api.global/typedserver@3.0.74':
'@api.global/typedserver@3.0.72':
dependencies:
'@api.global/typedrequest': 3.1.10
'@api.global/typedrequest-interfaces': 3.0.19
'@api.global/typedsocket': 3.0.1
'@cloudflare/workers-types': 4.20250418.0
'@cloudflare/workers-types': 4.20250410.0
'@design.estate/dees-comms': 1.0.27
'@push.rocks/lik': 6.1.0
'@push.rocks/smartchok': 1.0.34
@ -4460,13 +4451,13 @@ snapshots:
'@push.rocks/taskbuffer': 3.1.7
'@push.rocks/webrequest': 3.0.37
'@push.rocks/webstore': 2.0.20
'@tsclass/tsclass': 8.2.1
'@tsclass/tsclass': 8.2.0
'@types/express': 5.0.1
body-parser: 1.20.3
cors: 2.8.5
express: 4.21.2
express-force-ssl: 0.3.2
lit: 3.3.0
lit: 3.2.1
transitivePeerDependencies:
- '@nuxt/kit'
- bufferutil
@ -5044,7 +5035,7 @@ snapshots:
dependencies:
regenerator-runtime: 0.14.1
'@cloudflare/workers-types@4.20250418.0': {}
'@cloudflare/workers-types@4.20250410.0': {}
'@colors/colors@1.6.0': {}
@ -5083,7 +5074,7 @@ snapshots:
'@push.rocks/websetup': 3.0.19
'@push.rocks/webstore': 2.0.20
lenis: 1.2.3
lit: 3.3.0
lit: 3.2.1
sweet-scroll: 4.0.0
transitivePeerDependencies:
- '@nuxt/kit'
@ -5091,12 +5082,12 @@ snapshots:
- supports-color
- vue
'@design.estate/dees-element@2.0.41':
'@design.estate/dees-element@2.0.39':
dependencies:
'@design.estate/dees-domtools': 2.3.2
'@push.rocks/isounique': 1.0.5
'@push.rocks/smartrx': 3.0.7
lit: 3.3.0
lit: 3.2.1
transitivePeerDependencies:
- '@nuxt/kit'
- react
@ -5106,9 +5097,9 @@ snapshots:
'@design.estate/dees-wcctools@1.0.90':
dependencies:
'@design.estate/dees-domtools': 2.3.2
'@design.estate/dees-element': 2.0.41
'@design.estate/dees-element': 2.0.39
'@push.rocks/smartdelay': 3.0.5
lit: 3.3.0
lit: 3.2.1
transitivePeerDependencies:
- '@nuxt/kit'
- react
@ -5340,7 +5331,7 @@ snapshots:
'@git.zone/tstest@1.0.96(@aws-sdk/credential-providers@3.787.0)(socks@2.8.4)(typescript@5.7.3)':
dependencies:
'@api.global/typedserver': 3.0.74
'@api.global/typedserver': 3.0.72
'@git.zone/tsbundle': 2.2.5
'@git.zone/tsrun': 1.3.3
'@push.rocks/consolecolor': 2.0.2
@ -5374,7 +5365,7 @@ snapshots:
'@git.zone/tswatch@2.1.0':
dependencies:
'@api.global/typedserver': 3.0.74
'@api.global/typedserver': 3.0.72
'@git.zone/tsbundle': 2.2.5
'@git.zone/tsrun': 1.3.3
'@push.rocks/early': 4.0.4
@ -5421,7 +5412,7 @@ snapshots:
'@jest/schemas': 29.6.3
'@types/istanbul-lib-coverage': 2.0.6
'@types/istanbul-reports': 3.0.4
'@types/node': 22.14.1
'@types/node': 22.14.0
'@types/yargs': 17.0.33
chalk: 4.1.2
@ -5439,7 +5430,7 @@ snapshots:
'@lit-labs/ssr-dom-shim@1.3.0': {}
'@lit/reactive-element@2.1.0':
'@lit/reactive-element@2.0.4':
dependencies:
'@lit-labs/ssr-dom-shim': 1.3.0
@ -5527,7 +5518,7 @@ snapshots:
'@open-wc/scoped-elements@3.0.5':
dependencies:
'@open-wc/dedupe-mixin': 1.4.0
lit: 3.3.0
lit: 3.2.1
'@open-wc/semantic-dom-diff@0.20.1':
dependencies:
@ -5541,8 +5532,8 @@ snapshots:
'@open-wc/testing-helpers@3.0.1':
dependencies:
'@open-wc/scoped-elements': 3.0.5
lit: 3.3.0
lit-html: 3.3.0
lit: 3.2.1
lit-html: 3.2.1
'@open-wc/testing@4.0.0':
dependencies:
@ -5707,7 +5698,7 @@ snapshots:
transitivePeerDependencies:
- aws-crt
'@push.rocks/smartbuffer@3.0.5':
'@push.rocks/smartbuffer@3.0.4':
dependencies:
uint8array-extras: 1.4.0
@ -5741,7 +5732,7 @@ snapshots:
'@types/node-forge': 1.3.11
node-forge: 1.3.1
'@push.rocks/smartdata@5.9.2(@aws-sdk/credential-providers@3.787.0)(socks@2.8.4)':
'@push.rocks/smartdata@5.6.0(@aws-sdk/credential-providers@3.787.0)(socks@2.8.4)':
dependencies:
'@push.rocks/lik': 6.1.0
'@push.rocks/smartdelay': 3.0.5
@ -5753,7 +5744,7 @@ snapshots:
'@push.rocks/smarttime': 4.1.1
'@push.rocks/smartunique': 3.0.9
'@push.rocks/taskbuffer': 3.1.7
'@tsclass/tsclass': 8.2.1
'@tsclass/tsclass': 8.2.0
mongodb: 6.15.0(@aws-sdk/credential-providers@3.787.0)(socks@2.8.4)
transitivePeerDependencies:
- '@aws-sdk/credential-providers'
@ -5909,7 +5900,7 @@ snapshots:
'@push.rocks/smartmongo@2.0.12(@aws-sdk/credential-providers@3.787.0)(socks@2.8.4)':
dependencies:
'@push.rocks/mongodump': 1.0.8
'@push.rocks/smartdata': 5.9.2(@aws-sdk/credential-providers@3.787.0)(socks@2.8.4)
'@push.rocks/smartdata': 5.6.0(@aws-sdk/credential-providers@3.787.0)(socks@2.8.4)
'@push.rocks/smartpath': 5.0.18
'@push.rocks/smartpromise': 4.2.3
mongodb-memory-server: 10.1.4(@aws-sdk/credential-providers@3.787.0)(socks@2.8.4)
@ -5951,7 +5942,7 @@ snapshots:
'@push.rocks/smartntml@2.0.8':
dependencies:
'@design.estate/dees-element': 2.0.41
'@design.estate/dees-element': 2.0.39
'@happy-dom/global-registrator': 15.11.7
'@push.rocks/smartpromise': 4.2.3
fake-indexeddb: 6.0.0
@ -5974,7 +5965,7 @@ snapshots:
'@push.rocks/smartpdf@3.2.2(typescript@5.7.3)':
dependencies:
'@push.rocks/smartbuffer': 3.0.5
'@push.rocks/smartbuffer': 3.0.4
'@push.rocks/smartdelay': 3.0.5
'@push.rocks/smartfile': 11.2.0
'@push.rocks/smartnetwork': 3.0.2
@ -6060,7 +6051,7 @@ snapshots:
'@push.rocks/smartsocket@2.1.0':
dependencies:
'@api.global/typedrequest-interfaces': 3.0.19
'@api.global/typedserver': 3.0.74
'@api.global/typedserver': 3.0.72
'@push.rocks/isohash': 2.0.1
'@push.rocks/isounique': 1.0.5
'@push.rocks/lik': 6.1.0
@ -6778,26 +6769,22 @@ snapshots:
'@tsclass/tsclass@4.4.4':
dependencies:
type-fest: 4.40.0
type-fest: 4.39.1
'@tsclass/tsclass@8.2.1':
'@tsclass/tsclass@8.2.0':
dependencies:
type-fest: 4.40.0
'@tsclass/tsclass@9.0.0':
dependencies:
type-fest: 4.40.0
type-fest: 4.39.1
'@types/accepts@1.3.7':
dependencies:
'@types/node': 22.14.1
'@types/node': 22.14.0
'@types/babel__code-frame@7.0.6': {}
'@types/body-parser@1.19.5':
dependencies:
'@types/connect': 3.4.38
'@types/node': 22.14.1
'@types/node': 22.14.0
'@types/buffer-json@2.0.3': {}
@ -6813,17 +6800,17 @@ snapshots:
'@types/clean-css@4.2.11':
dependencies:
'@types/node': 22.14.1
'@types/node': 22.14.0
source-map: 0.6.1
'@types/co-body@6.1.3':
dependencies:
'@types/node': 22.14.1
'@types/node': 22.14.0
'@types/qs': 6.9.18
'@types/connect@3.4.38':
dependencies:
'@types/node': 22.14.1
'@types/node': 22.14.0
'@types/content-disposition@0.5.8': {}
@ -6834,11 +6821,11 @@ snapshots:
'@types/connect': 3.4.38
'@types/express': 5.0.1
'@types/keygrip': 1.0.6
'@types/node': 22.14.1
'@types/node': 22.14.0
'@types/cors@2.8.17':
dependencies:
'@types/node': 22.14.1
'@types/node': 22.14.0
'@types/debounce@1.2.4': {}
@ -6852,7 +6839,7 @@ snapshots:
'@types/express-serve-static-core@5.0.6':
dependencies:
'@types/node': 22.14.1
'@types/node': 22.14.0
'@types/qs': 6.9.18
'@types/range-parser': 1.2.7
'@types/send': 0.17.4
@ -6869,30 +6856,30 @@ snapshots:
'@types/from2@2.3.5':
dependencies:
'@types/node': 22.14.1
'@types/node': 22.14.0
'@types/fs-extra@11.0.4':
dependencies:
'@types/jsonfile': 6.1.4
'@types/node': 22.14.1
'@types/node': 22.14.0
'@types/fs-extra@9.0.13':
dependencies:
'@types/node': 22.14.1
'@types/node': 22.14.0
'@types/glob@7.2.0':
dependencies:
'@types/minimatch': 5.1.2
'@types/node': 22.14.1
'@types/node': 22.14.0
'@types/glob@8.1.0':
dependencies:
'@types/minimatch': 5.1.2
'@types/node': 22.14.1
'@types/node': 22.14.0
'@types/gunzip-maybe@1.4.2':
dependencies:
'@types/node': 22.14.1
'@types/node': 22.14.0
'@types/hast@3.0.4':
dependencies:
@ -6926,7 +6913,7 @@ snapshots:
'@types/jsonfile@6.1.4':
dependencies:
'@types/node': 22.14.1
'@types/node': 22.14.0
'@types/keygrip@1.0.6': {}
@ -6943,7 +6930,7 @@ snapshots:
'@types/http-errors': 2.0.4
'@types/keygrip': 1.0.6
'@types/koa-compose': 3.2.8
'@types/node': 22.14.1
'@types/node': 22.14.0
'@types/mdast@4.0.4':
dependencies:
@ -6961,9 +6948,9 @@ snapshots:
'@types/node-forge@1.3.11':
dependencies:
'@types/node': 22.14.1
'@types/node': 22.14.0
'@types/node@22.14.1':
'@types/node@22.14.0':
dependencies:
undici-types: 6.21.0
@ -6981,19 +6968,19 @@ snapshots:
'@types/s3rver@3.7.4':
dependencies:
'@types/node': 22.14.1
'@types/node': 22.14.0
'@types/semver@7.7.0': {}
'@types/send@0.17.4':
dependencies:
'@types/mime': 1.3.5
'@types/node': 22.14.1
'@types/node': 22.14.0
'@types/serve-static@1.15.7':
dependencies:
'@types/http-errors': 2.0.4
'@types/node': 22.14.1
'@types/node': 22.14.0
'@types/send': 0.17.4
'@types/sinon-chai@3.2.12':
@ -7013,11 +7000,11 @@ snapshots:
'@types/tar-stream@2.2.3':
dependencies:
'@types/node': 22.14.1
'@types/node': 22.14.0
'@types/through2@2.0.41':
dependencies:
'@types/node': 22.14.1
'@types/node': 22.14.0
'@types/triple-beam@1.3.5': {}
@ -7041,18 +7028,18 @@ snapshots:
'@types/whatwg-url@8.2.2':
dependencies:
'@types/node': 22.14.1
'@types/node': 22.14.0
'@types/webidl-conversions': 7.0.3
'@types/which@3.0.4': {}
'@types/ws@7.4.7':
dependencies:
'@types/node': 22.14.1
'@types/node': 22.14.0
'@types/ws@8.18.1':
dependencies:
'@types/node': 22.14.1
'@types/node': 22.14.0
'@types/yargs-parser@21.0.3': {}
@ -7062,7 +7049,7 @@ snapshots:
'@types/yauzl@2.10.3':
dependencies:
'@types/node': 22.14.1
'@types/node': 22.14.0
optional: true
'@ungap/structured-clone@1.3.0': {}
@ -7404,7 +7391,7 @@ snapshots:
dependencies:
devtools-protocol: 0.0.1425554
mitt: 3.0.1
zod: 3.24.3
zod: 3.24.2
ci-info@3.9.0: {}
@ -7685,7 +7672,7 @@ snapshots:
engine.io@6.6.4:
dependencies:
'@types/cors': 2.8.17
'@types/node': 22.14.1
'@types/node': 22.14.0
accepts: 1.3.8
base64id: 2.0.0
cookie: 0.7.2
@ -8450,7 +8437,7 @@ snapshots:
jest-util@29.7.0:
dependencies:
'@jest/types': 29.6.3
'@types/node': 22.14.1
'@types/node': 22.14.0
chalk: 4.1.2
ci-info: 3.9.0
graceful-fs: 4.2.11
@ -8562,21 +8549,21 @@ snapshots:
lines-and-columns@1.2.4: {}
lit-element@4.2.0:
lit-element@4.1.1:
dependencies:
'@lit-labs/ssr-dom-shim': 1.3.0
'@lit/reactive-element': 2.1.0
lit-html: 3.3.0
'@lit/reactive-element': 2.0.4
lit-html: 3.2.1
lit-html@3.3.0:
lit-html@3.2.1:
dependencies:
'@types/trusted-types': 2.0.7
lit@3.3.0:
lit@3.2.1:
dependencies:
'@lit/reactive-element': 2.1.0
lit-element: 4.2.0
lit-html: 3.3.0
'@lit/reactive-element': 2.0.4
lit-element: 4.1.1
lit-html: 3.2.1
locate-path@5.0.0:
dependencies:
@ -8653,8 +8640,6 @@ snapshots:
lru-cache@8.0.5: {}
lucide@0.501.0: {}
make-dir@3.1.0:
dependencies:
semver: 6.3.1
@ -9968,7 +9953,7 @@ snapshots:
dependencies:
punycode: 2.3.1
tr46@5.1.1:
tr46@5.1.0:
dependencies:
punycode: 2.3.1
@ -10003,7 +9988,7 @@ snapshots:
type-fest@2.19.0: {}
type-fest@4.40.0: {}
type-fest@4.39.1: {}
type-is@1.6.18:
dependencies:
@ -10097,7 +10082,7 @@ snapshots:
whatwg-url@14.2.0:
dependencies:
tr46: 5.1.1
tr46: 5.1.0
webidl-conversions: 7.0.0
which@2.0.2:
@ -10210,6 +10195,6 @@ snapshots:
ylru@1.4.0: {}
zod@3.24.3: {}
zod@3.24.2: {}
zwitch@2.0.4: {}

@ -1152,21 +1152,4 @@ Accessibility Features:
- Focus management
- ARIA attributes
## License and Legal Information
This repository contains open-source code that is licensed under the MIT License. A copy of the MIT License can be found in the license file within this repository.
Please note: The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.
### Trademarks
This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH and are not included within the scope of the MIT license granted herein. Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines, and any usage must be approved in writing by Task Venture Capital GmbH.
### Company Information
Task Venture Capital GmbH
Registered at District court Bremen HRB 35230 HB, Germany
For any legal inquiries or if you require further information, please contact us via email at hello@task.vc.
By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.
[End of component documentation]

@ -3,6 +3,6 @@
*/
export const commitinfo = {
name: '@design.estate/dees-catalog',
version: '1.8.0',
version: '1.5.3',
description: 'A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript.'
}

@ -1,14 +0,0 @@
import { html } from '@design.estate/dees-element';
export function demoFunc() {
return html`
<dees-heading level="1">This is a H1 heading</dees-heading>
<dees-heading level="2">This is a H2 heading</dees-heading>
<dees-heading level="3">This is a H3 heading</dees-heading>
<dees-heading level="4">This is a H4 heading</dees-heading>
<dees-heading level="5">This is a H5 heading</dees-heading>
<dees-heading level="6">This is a H6 heading</dees-heading>
<dees-heading level="hr">This is an hr heading</dees-heading>
<dees-heading level="hr-small">This is an hr small heading</dees-heading>
`;
}

@ -1,115 +0,0 @@
import {
customElement,
html,
css,
property,
cssManager,
type TemplateResult,
DeesElement,
type CSSResult,
} from '@design.estate/dees-element';
import { demoFunc } from './dees-heading.demo.js';
declare global {
interface HTMLElementTagNameMap {
'dees-heading': DeesHeading;
}
}
@customElement('dees-heading')
export class DeesHeading extends DeesElement {
// demo
public static demo = demoFunc;
// properties
/**
* Heading level: 1-6 for h1-h6, or 'hr' for horizontal rule style
*/
@property({ type: String, reflect: true })
public level: '1' | '2' | '3' | '4' | '5' | '6' | 'hr' | 'hr-small' = '1';
// STATIC STYLES
public static styles: CSSResult[] = [
cssManager.defaultStyles,
css`
/* Heading styles */
h1, h2, h3, h4, h5, h6 {
margin: 16px 0 8px;
font-weight: 600;
color: ${cssManager.bdTheme('#000', '#fff')};
}
h1 { font-size: 32px; font-family: 'Cal Sans'; letter-spacing: 0.025em;}
h2 { font-size: 28px; }
h3 { font-size: 24px; }
h4 { font-size: 20px; }
h5 { font-size: 16px; }
h6 { font-size: 14px; }
/* Horizontal rule style heading */
.heading-hr {
display: flex;
align-items: center;
text-align: center;
margin: 16px 0;
color: ${cssManager.bdTheme('#000', '#fff')};
}
/* Fade lines toward and away from text for hr style */
.heading-hr::before {
content: '';
flex: 1;
height: 1px;
/* fade in toward center */
background: ${cssManager.bdTheme(
'linear-gradient(to right, transparent, #ccc)',
'linear-gradient(to right, transparent, #333)'
)};
margin: 0 8px;
}
.heading-hr::after {
content: '';
flex: 1;
height: 1px;
/* fade out away from center */
background: ${cssManager.bdTheme(
'linear-gradient(to right, #ccc, transparent)',
'linear-gradient(to right, #333, transparent)'
)};
margin: 0 8px;
}
/* Small hr variant with reduced margins */
.heading-hr.heading-hr-small {
margin: 8px 0;
font-size: 12px;
}
.heading-hr.heading-hr-small::before,
.heading-hr.heading-hr-small::after {
margin: 0 8px;
}
`,
];
// INSTANCE
public render(): TemplateResult {
switch (this.level) {
case '1':
return html`<h1><slot></slot></h1>`;
case '2':
return html`<h2><slot></slot></h2>`;
case '3':
return html`<h3><slot></slot></h3>`;
case '4':
return html`<h4><slot></slot></h4>`;
case '5':
return html`<h5><slot></slot></h5>`;
case '6':
return html`<h6><slot></slot></h6>`;
case 'hr':
return html`<div class="heading-hr"><slot></slot></div>`;
case 'hr-small':
return html`<div class="heading-hr heading-hr-small"><slot></slot></div>`;
default:
return html`<h1><slot></slot></h1>`;
}
}
}

@ -1,155 +1,31 @@
import { html } from '@design.estate/dees-element';
import { icons, type IconWithPrefix } from './dees-icon.js';
import * as lucideIcons from 'lucide';
export const demoFunc = () => {
// Group FontAwesome icons by type
const faIcons = Object.keys(icons.fa);
// Extract Lucide icons from the lucideIcons object directly
// Log the first few keys to understand the structure
console.log('First few Lucide keys:', Object.keys(lucideIcons).slice(0, 5));
// Get all icon functions from lucideIcons (they have PascalCase names)
const lucideIconsList = Object.keys(lucideIcons)
.filter(key => {
// Skip utility functions and focus on icon components (first letter is uppercase)
const isUppercaseFirst = key[0] === key[0].toUpperCase() && key[0] !== key[0].toLowerCase();
const isFunction = typeof lucideIcons[key] === 'function';
const notUtility = !['createElement', 'createIcons', 'default'].includes(key);
return isFunction && isUppercaseFirst && notUtility;
})
.map(pascalName => {
// Convert PascalCase to camelCase
return pascalName.charAt(0).toLowerCase() + pascalName.slice(1);
});
// Log how many icons we found
console.log(`Found ${lucideIconsList.length} Lucide icons`);
// If we didn't find any, try an alternative approach
if (lucideIconsList.length === 0) {
console.log('Trying alternative approach to find Lucide icons');
// Try to get icon names from a known property if available
if (lucideIcons.icons) {
const iconSource = lucideIcons.icons || {};
lucideIconsList.push(...Object.keys(iconSource));
console.log(`Found ${lucideIconsList.length} icons via alternative method`);
}
}
import { faIcons } from './dees-icon.js';
// Define the functions in TS scope instead of script tags
const searchIcons = (event: InputEvent) => {
const searchTerm = (event.target as HTMLInputElement).value.toLowerCase().trim();
// Get the demo container first, then search within it
const demoContainer = (event.target as HTMLElement).closest('.demoContainer');
const containers = demoContainer.querySelectorAll('.iconContainer');
containers.forEach(container => {
const iconName = container.getAttribute('data-name');
if (searchTerm === '') {
container.classList.remove('hidden');
} else if (iconName && iconName.includes(searchTerm)) {
container.classList.remove('hidden');
} else {
container.classList.add('hidden');
}
});
// Update counts - search within demoContainer
demoContainer.querySelectorAll('.section-container').forEach(section => {
const visibleIcons = section.querySelectorAll('.iconContainer:not(.hidden)').length;
const countElement = section.querySelector('.icon-count');
if (countElement) {
const totalIconsCount = section.classList.contains('fa-section')
? faIcons.length
: lucideIconsList.length;
countElement.textContent = visibleIcons === totalIconsCount
? `${totalIconsCount} icons`
: `${visibleIcons} of ${totalIconsCount} icons`;
}
});
};
const copyIconName = (iconNameToCopy: string, type: 'fa' | 'lucide') => {
// Use the new prefix format
const textToCopy = `${type}:${iconNameToCopy}`;
navigator.clipboard.writeText(textToCopy).then(() => {
// Find the event target
const currentEvent = window.event as MouseEvent;
const currentTarget = currentEvent.currentTarget as HTMLElement;
// Show feedback
const tooltip = currentTarget.querySelector('.copy-tooltip');
if (tooltip) {
tooltip.textContent = 'Copied!';
setTimeout(() => {
tooltip.textContent = 'Click to copy';
}, 2000);
}
});
};
return html`
export const demoFunc = () => html`
<style>
.demoContainer {
width: 100%;
box-sizing: border-box;
display: flex;
flex-wrap: wrap;
background: #111111;
padding: 20px;
font-size: 30px;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
padding: 10px; font-size: 30px;
}
.search-container {
width: 100%;
margin-bottom: 20px;
display: flex;
}
#iconSearch {
flex: 1;
padding: 12px 16px;
font-size: 16px;
border: none;
border-radius: 4px;
background: #222;
color: #fff;
border: 1px solid #333;
}
#iconSearch:focus {
outline: none;
border-color: #e4002b;
}
dees-icon {
transition: all 0.2s ease;
transition: color 0.02s;
color: #ffffff;
}
dees-icon:hover {
color: #e4002b;
}
.iconContainer {
display: flex;
flex-direction: column;
align-items: center;
padding: 20px 16px 0px 16px;
display: block;
padding: 16px 16px 0px 16px;
border: 1px solid #333333;
margin-right: 10px;
margin-bottom: 10px;
border-radius: 4px;
transition: background-color 0.2s;
cursor: pointer;
position: relative;
}
.iconContainer:hover {
background-color: #222;
margin-right: 8px;
margin-bottom: 8px;
}
.iconName {
@ -157,136 +33,23 @@ export const demoFunc = () => {
text-align: center;
color: #ccc;
background: #333333;
padding: 6px 10px;
padding: 4px 8px;
padding-bottom: 4px;
margin-left: -16px;
margin-right: -16px;
margin-top: 20px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 120px;
border-radius: 0 0 4px 4px;
}
.section-title {
width: 100%;
color: #ffffff;
font-size: 24px;
margin: 20px 0;
padding-bottom: 10px;
border-bottom: 1px solid #333333;
display: flex;
justify-content: space-between;
align-items: center;
}
.api-note {
font-size: 14px;
color: #e4002b;
margin-bottom: 20px;
padding: 10px;
border: 1px solid #e4002b;
border-radius: 4px;
background: rgba(228, 0, 43, 0.1);
}
.icon-count {
font-size: 14px;
color: #888;
font-weight: normal;
background: #222;
padding: 5px 10px;
border-radius: 20px;
}
.icons-grid {
display: flex;
flex-wrap: wrap;
width: 100%;
}
.section-container {
width: 100%;
margin-bottom: 30px;
}
.copy-tooltip {
position: absolute;
background: #333;
color: white;
padding: 5px 10px;
border-radius: 4px;
font-size: 12px;
top: -30px;
opacity: 0;
transition: opacity 0.3s;
pointer-events: none;
}
.iconContainer:hover .copy-tooltip {
opacity: 1;
}
.iconContainer:hover dees-icon {
transform: scale(1.1);
}
.hidden {
display: none !important;
margin-top: 16px;
}
</style>
<div class="demoContainer">
<div class="search-container">
<input type="text" id="iconSearch" placeholder="Search icons..." @input=${searchIcons}>
<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>
<div class="api-note">
New API: Use <code>icon="fa:iconName"</code> or <code>icon="lucide:iconName"</code> instead of <code>iconFA</code>.
Click any icon to copy its new format to clipboard.
</div>
<div class="section-container fa-section">
<div class="section-title">
FontAwesome Icons
<span class="icon-count">${faIcons.length} icons</span>
</div>
<div class="icons-grid">
${faIcons.map(
(iconName) => {
const prefixedName = `fa:${iconName}`;
return html`
<div class="iconContainer fa-icon" data-name=${iconName.toLowerCase()} @click=${() => copyIconName(iconName, 'fa')}>
<dees-icon .icon=${prefixedName as IconWithPrefix} iconSize="24"></dees-icon>
<div class="iconName">${iconName}</div>
<span class="copy-tooltip">Click to copy</span>
</div>
`;
}
)}
</div>
</div>
<div class="section-container lucide-section">
<div class="section-title">
Lucide Icons
<span class="icon-count">${lucideIconsList.length} icons</span>
</div>
<div class="icons-grid">
${lucideIconsList.map(
(iconName) => {
const prefixedName = `lucide:${iconName}`;
return html`
<div class="iconContainer lucide-icon" data-name=${iconName.toLowerCase()} @click=${() => copyIconName(iconName, 'lucide')}>
<dees-icon .icon=${prefixedName as IconWithPrefix} iconSize="24"></dees-icon>
<div class="iconName">${iconName}</div>
<span class="copy-tooltip">Click to copy</span>
</div>
`;
}
)}
</div>
</div>
</div>
`;
};
`;

@ -75,12 +75,7 @@ import {
} from '@fortawesome/free-solid-svg-icons';
import { demoFunc } from './dees-icon.demo.js';
// Import Lucide icons and the createElement function
import * as lucideIcons from 'lucide';
import { createElement } from 'lucide';
// Collect FontAwesome icons
const faIcons = {
export const faIcons = {
// normal
arrowRight: faArrowRightSolid,
arrowUpRightFromSquare: faArrowUpRightFromSquareSolid,
@ -141,32 +136,7 @@ const faIcons = {
twitter: faTwitter,
};
// Create a string literal type for all FA icons
type FAIconKey = keyof typeof faIcons;
// Create union types for the icons with prefixes
export type IconWithPrefix = `fa:${FAIconKey}` | `lucide:${string}`;
// Export only FontAwesome icons directly
export const icons = {
fa: faIcons
};
// Legacy type for backward compatibility
export type TIconKey = FAIconKey | `lucide:${string}`;
// Use a global static cache for all icons to reduce rendering
const iconCache = new Map<string, string>();
// Clear cache items occasionally to prevent memory leaks
const MAX_CACHE_SIZE = 500;
function limitCacheSize() {
if (iconCache.size > MAX_CACHE_SIZE) {
// Remove oldest entries (first 20% of items)
const keysToDelete = Array.from(iconCache.keys()).slice(0, MAX_CACHE_SIZE / 5);
keysToDelete.forEach(key => iconCache.delete(key));
}
}
export type TIconKey = keyof typeof faIcons;
declare global {
interface HTMLElementTagNameMap {
@ -178,170 +148,31 @@ declare global {
export class DeesIcon extends DeesElement {
public static demo = demoFunc;
/**
* @deprecated Use the `icon` property instead with format "fa:iconName" or "lucide:iconName"
*/
@property({
type: String,
converter: {
// Convert attribute string to property (for reflected attributes)
fromAttribute: (value: string): TIconKey => value as TIconKey,
// Convert property to attribute (for reflection)
toAttribute: (value: TIconKey): string => value
}
type: String
})
public iconFA?: TIconKey;
public iconFA: keyof typeof faIcons;
/**
* The preferred icon property. Use format "fa:iconName" or "lucide:iconName"
* Examples: "fa:check", "lucide:menu"
*/
@property({
type: String,
converter: {
fromAttribute: (value: string): IconWithPrefix => value as IconWithPrefix,
toAttribute: (value: IconWithPrefix): string => value
}
})
public icon?: IconWithPrefix;
@property({ type: Number })
@property()
public iconSize: number;
@property({ type: String })
public color: string = 'currentColor';
@property({ type: Number })
public strokeWidth: number = 2;
// For tracking when we need to re-render
private lastIcon: IconWithPrefix | TIconKey | null = null;
private lastIconSize: number | null = null;
private lastColor: string | null = null;
private lastStrokeWidth: number | null = null;
constructor() {
super();
domtools.elementBasic.setup();
}
/**
* Gets the effective icon value, supporting both the new `icon` property
* and the legacy `iconFA` property for backward compatibility.
* Prefers `icon` if both are set.
*/
private getEffectiveIcon(): IconWithPrefix | TIconKey | null {
// Prefer the new API
if (this.icon) {
return this.icon;
}
// Fall back to the old API
if (this.iconFA) {
// If iconFA is already in the proper format (lucide:name), use it directly
if (this.iconFA.startsWith('lucide:')) {
return this.iconFA;
}
// For FontAwesome icons with no prefix, add the prefix
return `fa:${this.iconFA}` as IconWithPrefix;
}
return null;
}
/**
* Parses an icon string into its type and name parts
* @param iconStr The icon string in format "type:name"
* @returns Object with type and name properties
*/
private parseIconString(iconStr: string): { type: 'fa' | 'lucide', name: string } {
if (iconStr.startsWith('fa:')) {
return {
type: 'fa',
name: iconStr.substring(3) // Remove 'fa:' prefix
};
} else if (iconStr.startsWith('lucide:')) {
return {
type: 'lucide',
name: iconStr.substring(7) // Remove 'lucide:' prefix
};
} else {
// For backward compatibility, assume FontAwesome if no prefix
return {
type: 'fa',
name: iconStr
};
}
}
private renderLucideIcon(iconName: string): string {
// Create a cache key based on all visual properties
const cacheKey = `lucide:${iconName}:${this.iconSize}:${this.color}:${this.strokeWidth}`;
// Check if we already have this icon in the cache
if (iconCache.has(cacheKey)) {
return iconCache.get(cacheKey) || '';
}
try {
// Get the Pascal case icon name (Menu instead of menu)
const pascalCaseName = iconName.charAt(0).toUpperCase() + iconName.slice(1);
// Check if the icon exists in lucideIcons
if (!lucideIcons[pascalCaseName]) {
console.warn(`Lucide icon '${pascalCaseName}' not found in lucideIcons object`);
return '';
}
// Use the exact pattern from Lucide documentation
const svgElement = createElement(lucideIcons[pascalCaseName], {
color: this.color,
size: this.iconSize,
strokeWidth: this.strokeWidth
});
if (!svgElement) {
console.warn(`createElement returned empty result for ${pascalCaseName}`);
return '';
}
// Get the HTML
const result = svgElement.outerHTML;
// Cache the result for future use
iconCache.set(cacheKey, result);
limitCacheSize();
return result;
} catch (error) {
console.error(`Error rendering Lucide icon ${iconName}:`, error);
// Create a fallback SVG with the icon name
return `<svg xmlns="http://www.w3.org/2000/svg" width="${this.iconSize}" height="${this.iconSize}" viewBox="0 0 24 24" fill="none" stroke="${this.color}" stroke-width="${this.strokeWidth}" stroke-linecap="round" stroke-linejoin="round">
<text x="50%" y="50%" font-size="6" text-anchor="middle" dominant-baseline="middle" fill="${this.color}">${iconName}</text>
</svg>`;
}
}
public static styles = [
cssManager.defaultStyles,
css`
:host {
display: inline-flex;
display: block;
white-space: nowrap;
display: flex;
align-items: center;
justify-content: center;
line-height: 1;
vertical-align: middle;
}
/* Improve rendering performance */
#iconContainer svg {
display: block;
height: 100%;
width: 100%;
will-change: transform; /* Helps with animations */
contain: strict; /* Performance optimization */
* {
transition: inherit !important;
}
`,
];
@ -350,8 +181,8 @@ export class DeesIcon extends DeesElement {
return html`
${domtools.elementBasic.styles}
<style>
#iconContainer {
width: ${this.iconSize}px;
#iconContainer svg {
display: block;
height: ${this.iconSize}px;
}
</style>
@ -359,95 +190,14 @@ export class DeesIcon extends DeesElement {
`;
}
public updated() {
// If size is not specified, use font size as a base
public async updated() {
if (!this.iconSize) {
this.iconSize = parseInt(globalThis.getComputedStyle(this).fontSize.replace(/\D/g,''));
}
// Get the effective icon (either from icon or iconFA property)
const effectiveIcon = this.getEffectiveIcon();
// Check if we actually need to update the icon
// This prevents unnecessary DOM operations when properties haven't changed
if (this.lastIcon === effectiveIcon &&
this.lastIconSize === this.iconSize &&
this.lastColor === this.color &&
this.lastStrokeWidth === this.strokeWidth) {
return; // No visual changes - skip update
}
// Update our "last properties" for future change detection
this.lastIcon = effectiveIcon;
this.lastIconSize = this.iconSize;
this.lastColor = this.color;
this.lastStrokeWidth = this.strokeWidth;
const container = this.shadowRoot?.querySelector('#iconContainer');
if (!container || !effectiveIcon) return;
try {
// Parse the icon string to get type and name
const { type, name } = this.parseIconString(effectiveIcon);
if (type === 'lucide') {
// For Lucide, use direct DOM manipulation as shown in the docs
// This approach avoids HTML string issues
container.innerHTML = ''; // Clear container
try {
// Convert to PascalCase
const pascalCaseName = name.charAt(0).toUpperCase() + name.slice(1);
if (lucideIcons[pascalCaseName]) {
// Use the documented pattern from Lucide docs
const svgElement = createElement(lucideIcons[pascalCaseName], {
color: this.color,
size: this.iconSize,
strokeWidth: this.strokeWidth
});
if (svgElement) {
// Directly append the element
container.appendChild(svgElement);
return; // Exit early since we've added the element
}
}
// If we reach here, something went wrong
throw new Error(`Could not create element for ${pascalCaseName}`);
} catch (error) {
console.error(`Error rendering Lucide icon:`, error);
// Fall back to the string-based approach
const iconHtml = this.renderLucideIcon(name);
if (iconHtml) {
container.innerHTML = iconHtml;
}
}
} else {
// Use FontAwesome rendering via HTML string
const faIcon = icons.fa[name as FAIconKey];
if (faIcon) {
const iconHtml = icon(faIcon).html[0];
container.innerHTML = iconHtml;
} else {
console.warn(`FontAwesome icon not found: ${name}`);
}
}
} catch (error) {
console.error(`Error updating icon ${effectiveIcon}:`, error);
if (this.iconFA) {
this.shadowRoot.querySelector('#iconContainer').innerHTML = this.iconFA
? icon(faIcons[this.iconFA]).html[0]
: 'icon not found';
}
}
// Clean up resources when element is removed
async disconnectedCallback() {
super.disconnectedCallback();
// Clear our references
this.lastIcon = null;
this.lastIconSize = null;
this.lastColor = null;
this.lastStrokeWidth = null;
}
}
}

@ -1,28 +0,0 @@
import { html } from '@design.estate/dees-element';
/**
* Demo for dees-pagination component
*/
export const demoFunc = () => html`
<div style="display: flex; align-items: center; gap: 16px;">
<!-- Small set of pages -->
<div style="display: flex; flex-direction: column; gap: 4px;">
<span>5 pages, starting at 1:</span>
<dees-pagination
.total=${5}
.page=${1}
@page-change=${(e: CustomEvent) => console.log('Page changed to', e.detail.page)}
></dees-pagination>
</div>
<!-- Larger set of pages -->
<div style="display: flex; flex-direction: column; gap: 4px;">
<span>15 pages, starting at 8:</span>
<dees-pagination
.total=${15}
.page=${8}
@page-change=${(e: CustomEvent) => console.log('Page changed to', e.detail.page)}
></dees-pagination>
</div>
</div>
`;

@ -1,133 +0,0 @@
import { customElement, html, DeesElement, property, css, cssManager, type TemplateResult } from '@design.estate/dees-element';
import { demoFunc } from './dees-pagination.demo.js';
declare global {
interface HTMLElementTagNameMap {
'dees-pagination': DeesPagination;
}
}
/**
* A simple pagination component.
* @fires page-change - Emitted when the page is changed. detail: { page: number }
*/
@customElement('dees-pagination')
export class DeesPagination extends DeesElement {
public static demo = demoFunc;
/** Current page (1-based) */
@property({ type: Number, reflect: true })
public page = 1;
/** Total number of pages */
@property({ type: Number, reflect: true })
public total = 1;
public static styles = [
cssManager.defaultStyles,
css`
:host {
display: inline-flex;
align-items: center;
}
button {
background: none;
border: none;
margin: 0 2px;
padding: 6px 10px;
font-size: 14px;
cursor: pointer;
color: ${cssManager.bdTheme('#333', '#ccc')};
border-radius: 3px;
transition: background 0.2s;
}
button:hover:not(:disabled) {
background: ${cssManager.bdTheme('#eee', '#444')};
}
button:disabled {
cursor: default;
color: ${cssManager.bdTheme('#aaa', '#666')};
}
button.current {
background: #0050b9;
color: #fff;
cursor: default;
}
span.ellipsis {
margin: 0 4px;
color: ${cssManager.bdTheme('#333', '#ccc')};
}
`,
];
private get pages(): (number | string)[] {
const pages: (number | string)[] = [];
const total = this.total;
const current = this.page;
if (total <= 7) {
for (let i = 1; i <= total; i++) {
pages.push(i);
}
} else {
pages.push(1);
if (current > 4) {
pages.push('...');
}
const start = Math.max(2, current - 2);
const end = Math.min(total - 1, current + 2);
for (let i = start; i <= end; i++) {
pages.push(i);
}
if (current < total - 3) {
pages.push('...');
}
pages.push(total);
}
return pages;
}
public render(): TemplateResult {
return html`
<button
@click=${() => this.changePage(this.page - 1)}
?disabled=${this.page <= 1}
aria-label="Previous page"
>
</button>
${this.pages.map((p) =>
p === '...'
? html`<span class="ellipsis">…</span>`
: html`
<button
class="${p === this.page ? 'current' : ''}"
@click=${() => this.changePage(p as number)}
?disabled=${p === this.page}
aria-label="Page ${p}"
>
${p}
</button>
`
)}
<button
@click=${() => this.changePage(this.page + 1)}
?disabled=${this.page >= this.total}
aria-label="Next page"
>
</button>
`;
}
private changePage(newPage: number) {
if (newPage < 1 || newPage > this.total || newPage === this.page) {
return;
}
this.page = newPage;
this.dispatchEvent(
new CustomEvent('page-change', {
detail: { page: this.page },
bubbles: true,
})
);
}
}

@ -1,46 +0,0 @@
import { html } from '@design.estate/dees-element';
export const demoFunc = () => {
const onChanged = (e: CustomEvent) => {
// find the demo wrapper and update the 'changed' log inside it
const wrapper = (e.target as HTMLElement).closest('.demoWrapper');
const el = wrapper?.querySelector('#changed');
if (el) el.textContent = `search-changed: ${e.detail.value}`;
};
const onSubmit = (e: CustomEvent) => {
// find the demo wrapper and update the 'submitted' log inside it
const wrapper = (e.target as HTMLElement).closest('.demoWrapper');
const el = wrapper?.querySelector('#submitted');
if (el) el.textContent = `search-submit: ${e.detail.value}`;
};
return html`
<style>
.demoWrapper {
display: block;
flex-direction: column;
align-items: center;
background: #888888;
}
.logs {
padding: 16px;
width: 600px;
color: #fff;
font-family: monospace;
}
.logs div {
margin: 4px 0;
}
</style>
<div class="demoWrapper">
<dees-searchbar
@search-changed=${onChanged}
@search-submit=${onSubmit}
></dees-searchbar>
<div class="logs">
<div id="changed">search-changed:</div>
<div id="submitted">search-submit:</div>
</div>
</div>
`;
};

@ -1,160 +0,0 @@
import {
customElement,
DeesElement,
property,
html,
cssManager,
unsafeCSS,
css,
type TemplateResult,
domtools,
query,
} from '@design.estate/dees-element';
import * as colors from './00colors.js';
import { demoFunc } from './dees-searchbar.demo.js';
declare global {
interface HTMLElementTagNameMap {
'dees-searchbar': DeesSearchbar;
}
}
@customElement('dees-searchbar')
export class DeesSearchbar extends DeesElement {
// DEMO
public static demo = demoFunc;
// STATIC
public static styles = [
cssManager.defaultStyles,
css`
:host {
padding: 40px;
font-family: Dees Sans;
display: block;
background: ${cssManager.bdTheme('#eeeeeb', '#000000')};
}
.searchboxContainer {
position: relative;
margin: auto;
max-width: 800px;
background: ${cssManager.bdTheme('#00000015', '#ffffff15')};
--boxHeight: 60px;
height: var(--boxHeight);
border-radius: var(--boxHeight);
display: grid;
grid-template-columns: 1fr 140px;
justify-content: center;
align-items: center;
border-top: 1px solid ${cssManager.bdTheme('#00000015', '#ffffff20')};
}
input {
height: 100%;
width: 100%;
border: none;
background: none;
color: ${cssManager.bdTheme('#000000', '#eeeeeb')};
padding-left: 25px;
margin-right: -8px;
outline: none;
font-size: 16px;
}
.searchButton {
--buttonPadding: 8px;
background: ${cssManager.bdTheme('#eeeeeb', '#000000')};
color: ${cssManager.bdTheme('#000000', '#eeeeeb')};
line-height: calc(var(--boxHeight) - (var(--buttonPadding) * 2));
border-radius: var(--boxHeight);
transform: scale(1) ;
transform-origin: 50% 50%;
text-align: center;
transition: transform 0.1s, background 0.1s;
margin-right: var(--buttonPadding);
user-select: none;
}
.searchButton:hover {
color: #fff;
background: ${cssManager.bdTheme(colors.bright.blue, colors.dark.blue)};
}
.searchButton:active {
color: #fff;
background: ${cssManager.bdTheme(colors.bright.blueActive, colors.dark.blueActive)};
transform: scale(0.98);
}
.filters {
margin: auto;
max-width: 800px;
}
`,
];
// INSTANCE
@property()
public filters = [];
@query('input')
public searchInput!: HTMLInputElement;
@query('.searchButton')
public searchButton!: HTMLElement;
constructor() {
super();
}
public render(): TemplateResult {
return html`
<div class="searchboxContainer">
<input type="text" placeholder="Your Skills (e.g. TypeScript, Rust, Projectmanagement)" />
<div class="searchButton">Search -></div>
</div>
${this.filters.length > 0 ? html`
<div class="filters">
<dees-heading level="hr-small">Filters</dees-heading>
<dees-input-dropdown .label=${'location'}></dees-input-dropdown>
</div>
` : html``}
`;
}
/**
* Lifecycle: after first render, wire up events for input and submit actions
*/
public firstUpdated(): void {
// dispatch change on each input
this.searchInput.addEventListener('input', () => {
this.dispatchEvent(new CustomEvent('search-changed', {
bubbles: true,
composed: true,
detail: { value: this.searchInput.value }
}));
});
// submit on Enter key
this.searchInput.addEventListener('keydown', (e: KeyboardEvent) => {
if (e.key === 'Enter') {
this._dispatchSubmit();
}
});
// submit on button click
this.searchButton.addEventListener('click', () => this._dispatchSubmit());
}
/**
* Dispatch a submit event with the current search value
*/
private _dispatchSubmit(): void {
this.dispatchEvent(new CustomEvent('search-submit', {
bubbles: true,
composed: true,
detail: { value: this.searchInput.value }
}));
}
}

@ -12,7 +12,7 @@ import {
unsafeCSS,
type CSSResult,
state,
directives,
resolveExec,
} from '@design.estate/dees-element';
import { DeesContextmenu } from './dees-contextmenu.js';
@ -415,7 +415,7 @@ export class DeesTable<T> extends DeesElement {
<div class="heading heading2">${this.heading2}</div>
</div>
<div class="headerActions">
${directives.resolveExec(async () => {
${resolveExec(async () => {
const resultArray: TemplateResult[] = [];
for (const action of this.dataActions) {
if (!action.type.includes('header')) continue;
@ -634,7 +634,7 @@ export class DeesTable<T> extends DeesElement {
selected
</div>
<div class="footerActions">
${directives.resolveExec(async () => {
${resolveExec(async () => {
const resultArray: TemplateResult[] = [];
for (const action of this.dataActions) {
if (!action.type.includes('footer')) continue;

@ -18,7 +18,6 @@ export * from './dees-editor-markdown.js';
export * from './dees-editor-markdownoutlet.js';
export * from './dees-form-submit.js';
export * from './dees-form.js';
export * from './dees-heading.js';
export * from './dees-hint.js';
export * from './dees-icon.js';
export * from './dees-input-checkbox.js';
@ -36,7 +35,6 @@ export * from './dees-mobilenavigation.js';
export * from './dees-modal.js';
export * from './dees-input-multitoggle.js';
export * from './dees-pdf.js';
export * from './dees-searchbar.js';
export * from './dees-simple-appdash.js';
export * from './dees-simple-login.js';
export * from './dees-speechbubble.js';
@ -48,4 +46,3 @@ export * from './dees-toast.js';
export * from './dees-updater.js';
export * from './dees-windowcontrols.js';
export * from './dees-windowlayer.js';
export * from './dees-pagination.js';