Compare commits

...

12 Commits

Author SHA1 Message Date
8d3a1783fd v3.49.1
Some checks failed
Default (tags) / security (push) Failing after 1s
Default (tags) / test (push) Failing after 1s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped
2026-04-01 05:00:21 +00:00
af1f660486 fix(ts_web): resolve TypeScript nullability and event typing issues across web components 2026-04-01 05:00:21 +00:00
b1c8a7446e Update README and codebase with new components and fixes
- Added `DeesStorageBrowser` to the Data Display section in README.
- Included `DeesUpdater` in the Theming section of README.
- Corrected the path to the LICENSE file in the README.
- Updated company information section for clarity in README.
- Modified `getFormElements` and `getSubmitButton` methods in `DeesForm` to use `querySelectorAll` for better input selection.
- Updated `apexcharts` version from `5.10.3` to `5.10.4` in versions service.
2026-04-01 04:30:10 +00:00
7e991396e9 feat(config): rename npmextra.json to .smartconfig.json for project setup and configuration 2026-04-01 04:29:55 +00:00
25cbf9bfdd v3.49.0
Some checks failed
Default (tags) / security (push) Failing after 1s
Default (tags) / test (push) Failing after 0s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped
2026-03-18 15:28:21 +00:00
4d8ba1fefc feat(dataview-statusobject): add last updated footer to status object and refresh demo data 2026-03-18 15:28:21 +00:00
42317459ff v3.48.5
Some checks failed
Default (tags) / security (push) Failing after 1s
Default (tags) / test (push) Failing after 1s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped
2026-03-14 17:39:34 +00:00
932db338c6 fix(repo): no changes to commit 2026-03-14 17:39:34 +00:00
bc4b87b83a v3.48.4
Some checks failed
Default (tags) / security (push) Failing after 1s
Default (tags) / test (push) Failing after 1s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped
2026-03-14 17:10:20 +00:00
eb055e7214 fix(storage-browser): rename S3-specific storage browser interfaces to generic storage types 2026-03-14 17:10:20 +00:00
c55eb948fe v3.48.3
Some checks failed
Default (tags) / security (push) Failing after 1s
Default (tags) / test (push) Failing after 1s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped
2026-03-14 16:29:46 +00:00
35779209ea fix(dataview): rename dees-s3-browser exports and custom elements to dees-storage-browser 2026-03-14 16:29:46 +00:00
95 changed files with 1306 additions and 1072 deletions

View File

@@ -1,7 +1,7 @@
{
"json.schemas": [
{
"fileMatch": ["/npmextra.json"],
"fileMatch": ["/.smartconfig.json"],
"schema": {
"type": "object",
"properties": {

View File

@@ -1,5 +1,39 @@
# Changelog
## 2026-04-01 - 3.49.1 - fix(ts_web)
resolve TypeScript nullability and event typing issues across web components
- adds explicit non-null assertions and nullable types to component properties, shadowRoot queries, and modal references
- normalizes demo and component event listeners by casting generic Event objects to CustomEvent where needed
- guards optional form, dropdown, menu, and DOM interactions to prevent invalid access under stricter TypeScript checks
- updates tsconfig to include Node types for the web build environment
## 2026-03-18 - 3.49.0 - feat(dataview-statusobject)
add last updated footer to status object and refresh demo data
- Render a bottom bar that shows the status object's lastUpdated timestamp when available.
- Adjust detail row padding to keep spacing consistent with the new footer layout.
- Update demo status objects to include lastUpdated examples for current, hourly, and daily timestamps.
- Bump @tsclass/tsclass from ^9.3.0 to ^9.5.0.
## 2026-03-14 - 3.48.5 - fix(repo)
no changes to commit
## 2026-03-14 - 3.48.4 - fix(storage-browser)
rename S3-specific storage browser interfaces to generic storage types
- Replaces IS3DataProvider, IS3Object, and IS3ChangeEvent with generic storage interface names across storage browser components
- Updates demo provider naming and user-facing demo text from S3 browser to Storage browser
- Aligns interface and utility comments with storage-agnostic terminology
## 2026-03-14 - 3.48.3 - fix(dataview)
rename dees-s3-browser exports and custom elements to dees-storage-browser
- Replaces the dees-s3-browser module path with dees-storage-browser in dataview exports
- Renames the main custom element from dees-s3-browser to dees-storage-browser
- Renames related columns, keys, preview, demo, interfaces, and utility entry points under the new storage-browser module
## 2026-03-12 - 3.48.2 - fix(repo)
no changes to commit

View File

@@ -1,4 +1,4 @@
Copyright (c) 2020 Lossless GmbH (hello@lossless.com)
Copyright (c) 2020 Task Venture Capital GmbH (hello@task.vc)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -8,10 +8,7 @@ copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. You agree to being mentioned
as reference by Lossless GmbH. This includes the use of your entity logos
or profile picture by Lossless GmbH on websites and readme's, also on third party
pages like gitlab.com or github.com.
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
@@ -19,4 +16,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
SOFTWARE.

View File

@@ -1,6 +1,6 @@
{
"name": "@design.estate/dees-catalog",
"version": "3.48.2",
"version": "3.49.1",
"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,8 +16,8 @@
"author": "Lossless GmbH",
"license": "MIT",
"dependencies": {
"@design.estate/dees-domtools": "^2.5.1",
"@design.estate/dees-element": "^2.2.2",
"@design.estate/dees-domtools": "^2.5.4",
"@design.estate/dees-element": "^2.2.4",
"@design.estate/dees-wcctools": "^3.8.0",
"@fortawesome/fontawesome-svg-core": "^7.2.0",
"@fortawesome/free-brands-svg-icons": "^7.2.0",
@@ -33,8 +33,8 @@
"@tiptap/extension-typography": "^2.23.0",
"@tiptap/extension-underline": "^2.23.0",
"@tiptap/starter-kit": "^2.23.0",
"@tsclass/tsclass": "^9.3.0",
"apexcharts": "^5.10.3",
"@tsclass/tsclass": "^9.5.0",
"apexcharts": "^5.10.4",
"highlight.js": "11.11.1",
"ibantools": "^4.5.1",
"lucide": "^0.577.0",
@@ -44,12 +44,12 @@
"xterm-addon-fit": "^0.8.0"
},
"devDependencies": {
"@git.zone/tsbuild": "^4.3.0",
"@git.zone/tsbundle": "^2.9.1",
"@git.zone/tstest": "^3.3.2",
"@git.zone/tswatch": "^3.3.0",
"@push.rocks/projectinfo": "^5.0.2",
"@types/node": "^25.4.0"
"@git.zone/tsbuild": "^4.4.0",
"@git.zone/tsbundle": "^2.10.0",
"@git.zone/tstest": "^3.6.3",
"@git.zone/tswatch": "^3.3.2",
"@push.rocks/projectinfo": "^5.1.0",
"@types/node": "^25.5.0"
},
"files": [
"ts/**/*",
@@ -60,7 +60,7 @@
"dist_ts_web/**/*",
"assets/**/*",
"cli.js",
"npmextra.json",
".smartconfig.json",
"readme.md"
],
"browserslist": [

1324
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -58,13 +58,13 @@ For developers working on this library, please refer to the [UI Components Playb
| **Core UI** | [`DeesButton`](#deesbutton), [`DeesButtonExit`](#deesbuttonexit), [`DeesButtonGroup`](#deesbuttongroup), [`DeesBadge`](#deesbadge), [`DeesChips`](#deeschips), [`DeesHeading`](#deesheading), [`DeesHint`](#deeshint), [`DeesIcon`](#deesicon), [`DeesLabel`](#deeslabel), [`DeesPanel`](#deespanel), [`DeesSearchbar`](#deessearchbar), [`DeesSpinner`](#deesspinner), [`DeesToast`](#deestoast), [`DeesWindowcontrols`](#deeswindowcontrols), [`DeesActionbar`](#deesactionbar) |
| **Forms** | [`DeesForm`](#deesform), [`DeesInputText`](#deesinputtext), [`DeesInputCheckbox`](#deesinputcheckbox), [`DeesInputDropdown`](#deesinputdropdown), [`DeesInputRadiogroup`](#deesinputradiogroup), [`DeesInputFileupload`](#deesinputfileupload), [`DeesInputIban`](#deesinputiban), [`DeesInputPhone`](#deesinputphone), [`DeesInputQuantitySelector`](#deesinputquantityselector), [`DeesInputMultitoggle`](#deesinputmultitoggle), [`DeesInputToggle`](#deesinputtoggle), [`DeesInputTags`](#deesinputtags), [`DeesInputTypelist`](#deesinputtypelist), [`DeesInputList`](#deesinputlist), [`DeesInputProfilepicture`](#deesinputprofilepicture), [`DeesInputRichtext`](#deesinputrichtext), [`DeesInputWysiwyg`](#deesinputwysiwyg), [`DeesInputDatepicker`](#deesinputdatepicker), [`DeesInputSearchselect`](#deesinputsearchselect), [`DeesInputCode`](#deesinputcode), [`DeesFormSubmit`](#deesformsubmit) |
| **App Shell (Layout)** | [`DeesAppui`](#deesappui-), [`DeesAppuiMainmenu`](#deesappuimainmenu), [`DeesAppuiSecondarymenu`](#deesappuisecondarymenu), [`DeesAppuiMaincontent`](#deesappuimaincontent), [`DeesAppuiAppbar`](#deesappuiappbar), [`DeesAppuiActivitylog`](#deesappuiactivitylog), [`DeesAppuiBottombar`](#deesappuibottombar), [`DeesAppuiProfiledropdown`](#deesappuiprofiledropdown), [`DeesAppuiTabs`](#deesappuitabs), [`DeesMobileNavigation`](#deesmobilenavigation), [`DeesDashboardGrid`](#deesdashboardgrid) |
| **Data Display** | [`DeesTable`](#deestable), [`DeesDataviewCodebox`](#deesdataviewcodebox), [`DeesDataviewStatusobject`](#deesdataviewstatusobject), [`DeesPdf`](#deespdf), [`DeesStatsGrid`](#deesstatsgrid), [`DeesPagination`](#deespagination) |
| **Data Display** | [`DeesTable`](#deestable), [`DeesDataviewCodebox`](#deesdataviewcodebox), [`DeesDataviewStatusobject`](#deesdataviewstatusobject), [`DeesPdf`](#deespdf), [`DeesStatsGrid`](#deesstatsgrid), [`DeesPagination`](#deespagination), [`DeesStorageBrowser`](#deesstorgebrowser) |
| **Media & Tiles** | [`DeesTilePdf`](#deestilepdf), [`DeesTileImage`](#deestileimage), [`DeesTileAudio`](#deestileaudio), [`DeesTileVideo`](#deestilevideo), [`DeesTileNote`](#deestilenote), [`DeesTileFolder`](#deestilefolder), [`DeesPreview`](#deespreview), [`DeesPdfViewer`](#deespdfviewer), [`DeesPdfPreview`](#deespdfpreview), [`DeesImageViewer`](#deesimageviewer), [`DeesAudioViewer`](#deesaudioviewer), [`DeesVideoViewer`](#deesvideoviewer) |
| **Visualization** | [`DeesChartArea`](#deeschartarea), [`DeesChartLog`](#deeschartlog) |
| **Dialogs & Overlays** | [`DeesModal`](#deesmodal), [`DeesContextmenu`](#deescontextmenu), [`DeesSpeechbubble`](#deesspeechbubble), [`DeesWindowlayer`](#deeswindowlayer) |
| **Navigation** | [`DeesStepper`](#deesstepper), [`DeesProgressbar`](#deesprogressbar) |
| **Workspace / IDE** | [`DeesWorkspace`](#deesworkspace), [`DeesWorkspaceMonaco`](#deesworkspacemonaco), [`DeesWorkspaceDiffEditor`](#deesworkspacediffeditor), [`DeesWorkspaceFiletree`](#deesworkspacefiletree), [`DeesWorkspaceTerminal`](#deesworkspaceterminal), [`DeesWorkspaceTerminalPreview`](#deesworkspaceterminalpreview), [`DeesWorkspaceMarkdown`](#deesworkspacemarkdown), [`DeesWorkspaceMarkdownoutlet`](#deesworkspacemarkdownoutlet), [`DeesWorkspaceBottombar`](#deesworkspacebottombar) |
| **Theming** | [`DeesTheme`](#deestheme) |
| **Theming** | [`DeesTheme`](#deestheme), [`DeesUpdater`](#deesupdater) |
| **Pre-built Templates** | [`DeesSimpleAppdash`](#deessimpleappdash), [`DeesSimpleLogin`](#deessimplelogin) |
| **Shopping** | [`DeesShoppingProductcard`](#deesshoppingproductcard) |
@@ -1780,7 +1780,7 @@ interface ITileFolderItem {
## License and Legal Information
This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [LICENSE](./LICENSE) file.
This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [LICENSE](./license) file.
**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.
@@ -1792,9 +1792,11 @@ Use of these trademarks must comply with Task Venture Capital GmbH's Trademark G
### Company Information
Task Venture Capital GmbH
Task Venture Capital GmbH
Registered at District Court Bremen HRB 35230 HB, Germany
For any legal inquiries or 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.
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.

View File

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

View File

@@ -122,7 +122,7 @@ export class DeesAppuiBar extends DeesElement {
>
${menuItem.iconName ? html`<dees-icon .icon="${`lucide:${menuItem.iconName}`}"></dees-icon>` : ''}
${menuItem.name}
${hasSubmenu ? this.renderDropdown(menuItem.submenu, itemId, isActive) : ''}
${hasSubmenu ? this.renderDropdown(menuItem.submenu!, itemId, isActive) : ''}
</div>
`;
}

View File

@@ -75,21 +75,21 @@ export const demoFunc = () => {
// Set up status toggle
const statusButtons = elementArg.querySelectorAll('.status-toggle dees-button');
statusButtons[0].addEventListener('click', () => {
appbar.user = { ...appbar.user, status: 'online' };
appbar.user = { ...appbar.user!, status: 'online' };
});
statusButtons[1].addEventListener('click', () => {
appbar.user = { ...appbar.user, status: 'busy' };
appbar.user = { ...appbar.user!, status: 'busy' };
});
statusButtons[2].addEventListener('click', () => {
appbar.user = { ...appbar.user, status: 'away' };
appbar.user = { ...appbar.user!, status: 'away' };
});
statusButtons[3].addEventListener('click', () => {
appbar.user = { ...appbar.user, status: 'offline' };
appbar.user = { ...appbar.user!, status: 'offline' };
});
// Set up window controls toggle
const windowControlsButton = elementArg.querySelector('.window-controls-toggle dees-button');
windowControlsButton.addEventListener('click', () => {
windowControlsButton!.addEventListener('click', () => {
appbar.showWindowControls = !appbar.showWindowControls;
});

View File

@@ -165,7 +165,7 @@ export class DeesAppuiMaincontent extends DeesElement {
}
// Tab selection is now handled by the dees-appui-tabs component
// But we need to ensure the tabs component is ready
const tabsComponent = this.shadowRoot.querySelector('dees-appui-tabs') as DeesAppuiTabs;
const tabsComponent = this.shadowRoot!.querySelector('dees-appui-tabs') as DeesAppuiTabs;
if (tabsComponent) {
await tabsComponent.updateComplete;
}

View File

@@ -46,7 +46,7 @@ export class DeesAppuiMainmenu extends DeesElement {
accessor tabs: interfaces.IMenuItem[] = [];
@property()
accessor selectedTab: interfaces.IMenuItem;
accessor selectedTab!: interfaces.IMenuItem;
@property({ type: Boolean, reflect: true })
accessor collapsed: boolean = false;

View File

@@ -663,21 +663,21 @@ export class DeesAppuiTabs extends DeesElement {
}
private shouldShowIndicator(): boolean {
return this.selectedTab && this.showTabIndicator && this.tabs.includes(this.selectedTab);
return !!this.selectedTab && this.showTabIndicator && this.tabs.includes(this.selectedTab);
}
private getSelectedTabElement(): HTMLElement | null {
const selectedIndex = this.tabs.indexOf(this.selectedTab);
const selectedIndex = this.tabs.indexOf(this.selectedTab!);
const isHorizontal = this.tabStyle === 'horizontal';
const selector = isHorizontal
const selector = isHorizontal
? `.tabs-wrapper .tabsContainer .tab:nth-child(${selectedIndex + 1})`
: `.vertical-wrapper .tabsContainer .tab:nth-child(${selectedIndex + 1})`;
return this.shadowRoot.querySelector(selector);
return this.shadowRoot!.querySelector(selector);
}
private getIndicatorElement(): HTMLElement | null {
return this.shadowRoot.querySelector('.tabIndicator');
return this.shadowRoot!.querySelector('.tabIndicator');
}
private handleInitialTransition(indicator: HTMLElement): void {
@@ -695,7 +695,7 @@ export class DeesAppuiTabs extends DeesElement {
const tabContent = tabElement.querySelector('.tab-content') as HTMLElement;
if (!tabContent) return;
const wrapperRect = indicator.parentElement.getBoundingClientRect();
const wrapperRect = indicator.parentElement!.getBoundingClientRect();
const contentRect = tabContent.getBoundingClientRect();
const contentLeft = contentRect.left - wrapperRect.left;
@@ -707,7 +707,7 @@ export class DeesAppuiTabs extends DeesElement {
}
private updateVerticalIndicator(indicator: HTMLElement, tabElement: HTMLElement): void {
const tabsContainer = this.shadowRoot.querySelector('.vertical-wrapper .tabsContainer') as HTMLElement;
const tabsContainer = this.shadowRoot!.querySelector('.vertical-wrapper .tabsContainer') as HTMLElement;
if (!tabsContainer) return;
indicator.style.top = `${tabElement.offsetTop + tabsContainer.offsetTop}px`;

View File

@@ -12,7 +12,7 @@ class DemoDashboardView extends DeesElement {
@state()
accessor activated: boolean = false;
private ctx: IViewActivationContext;
private ctx!: IViewActivationContext;
private statsTiles: IStatsTile[] = [
{
@@ -267,7 +267,7 @@ class DemoSettingsView extends DeesElement {
@state()
accessor hasChanges: boolean = false;
private appui: DeesAppui;
private appui!: DeesAppui;
onActivate(context: IViewActivationContext) {
this.appui = context.appui as any;

View File

@@ -1037,7 +1037,7 @@ export class DeesAppui extends DeesElement {
if (!config.mainMenu?.sections) return [];
return config.mainMenu.sections.map((section) => ({
name: section.name,
name: section.name || '',
items: section.views
.map((viewId) => {
const view = this.viewRegistry.get(viewId);

View File

@@ -173,7 +173,7 @@ export class ViewRegistry {
}
// Check for cached instance
let element = shouldCache ? this.instances.get(viewId) : undefined;
let element: HTMLElement | null | undefined = shouldCache ? this.instances.get(viewId) : undefined;
if (element) {
// Reuse cached instance - just show it

View File

@@ -1,5 +1,5 @@
import { html, css } from '@design.estate/dees-element';
import '../00group-button/dees-button/dees-button.js';
import '../../00group-button/dees-button/dees-button.js';
import '../../00group-layout/dees-panel/dees-panel.js';
import '@design.estate/dees-wcctools/demotools';

View File

@@ -301,15 +301,15 @@ export class DeesMobilenavigation extends DeesElement {
`;
}
private windowLayer: DeesWindowLayer;
private windowLayer!: DeesWindowLayer;
/**
* inits the show
*/
public async show() {
const domtools = await this.domtoolsPromise;
const main = this.shadowRoot.querySelector('.main');
const main = this.shadowRoot!.querySelector('.main');
// Create window layer first (it will get its own z-index)
if (!this.windowLayer) {
this.windowLayer = await DeesWindowLayer.createAndShow({
@@ -328,7 +328,7 @@ export class DeesMobilenavigation extends DeesElement {
zIndexRegistry.register(this, this.mobileNavZIndex);
await domtools.convenience.smartdelay.delayFor(10);
main.classList.add('show');
main!.classList.add('show');
}
/**
@@ -336,8 +336,8 @@ export class DeesMobilenavigation extends DeesElement {
*/
public async hide() {
const domtools = await this.domtoolsPromise;
const main = this.shadowRoot.querySelector('.main');
main.classList.remove('show');
const main = this.shadowRoot!.querySelector('.main');
main!.classList.remove('show');
// Unregister from z-index registry
zIndexRegistry.unregister(this);

View File

@@ -288,8 +288,8 @@ export const demoFunc = () => html`
}
if (dataBtn && output) {
dataBtn.addEventListener('clicked', (e: CustomEvent) => {
output.textContent = `Clicked: Secondary button with data: ${e.detail.data}`;
dataBtn.addEventListener('clicked', (e: Event) => {
output.textContent = `Clicked: Secondary button with data: ${(e as CustomEvent).detail.data}`;
});
}
@@ -322,9 +322,9 @@ export const demoFunc = () => html`
const output = elementArg.querySelector('#form-output');
if (form && output) {
form.addEventListener('formData', (e: CustomEvent) => {
output.innerHTML = '<strong>Form submitted with data:</strong><br>' +
JSON.stringify(e.detail.data, null, 2);
form.addEventListener('formData', (e: Event) => {
output.innerHTML = '<strong>Form submitted with data:</strong><br>' +
JSON.stringify((e as CustomEvent).detail.data, null, 2);
});
}

View File

@@ -31,10 +31,10 @@ export class DeesButton extends DeesElement {
return true;
}
})
accessor text: string;
accessor text!: string;
@property()
accessor eventDetailData: string;
accessor eventDetailData!: string;
@property({
type: Boolean,
@@ -69,7 +69,7 @@ export class DeesButton extends DeesElement {
accessor insideForm: boolean = false;
@property({ type: String, reflect: true })
accessor icon: string;
accessor icon!: string;
@property({ type: String, reflect: true })
accessor iconPosition: 'left' | 'right' = 'left';

View File

@@ -37,7 +37,7 @@ export class DeesChartArea extends DeesElement {
// instance
@state()
accessor chart: ApexCharts;
accessor chart!: ApexCharts;
@property()
accessor label: string = 'Untitled Chart';
@@ -68,8 +68,8 @@ export class DeesChartArea extends DeesElement {
@property({ type: Number })
accessor autoScrollInterval: number = 1000; // Auto-scroll interval in milliseconds (0 to disable)
private resizeObserver: ResizeObserver;
private resizeTimeout: number;
private resizeObserver!: ResizeObserver;
private resizeTimeout!: number;
private internalChartData: ApexAxisChartSeries = [];
private autoScrollTimer: number | null = null;
private readonly DEBUG_RESIZE = false; // Set to true to enable resize debugging
@@ -132,7 +132,7 @@ export class DeesChartArea extends DeesElement {
if (this.chart) {
try {
this.chart.destroy();
this.chart = null;
this.chart = null as any;
} catch (error) {
console.error('Error destroying chart:', error);
}
@@ -170,14 +170,14 @@ export class DeesChartArea extends DeesElement {
await new Promise(resolve => requestAnimationFrame(resolve));
// Get actual dimensions of the container
const mainbox: HTMLDivElement = this.shadowRoot.querySelector('.mainbox');
const chartContainer: HTMLDivElement = this.shadowRoot.querySelector('.chartContainer');
const mainbox: HTMLDivElement | null = this.shadowRoot!.querySelector('.mainbox');
const chartContainer: HTMLDivElement | null = this.shadowRoot!.querySelector('.chartContainer');
if (!mainbox || !chartContainer) {
console.error('Chart containers not found');
return;
}
// Calculate initial dimensions
const styleChartContainer = window.getComputedStyle(chartContainer);
const paddingTop = parseInt(styleChartContainer.paddingTop, 10);
@@ -368,7 +368,7 @@ export class DeesChartArea extends DeesElement {
};
try {
this.chart = new ApexChartsLib(this.shadowRoot.querySelector('.chartContainer'), options);
this.chart = new ApexChartsLib(this.shadowRoot!.querySelector('.chartContainer')!, options);
await this.chart.render();
// Give the chart a moment to fully initialize before resizing
@@ -376,7 +376,7 @@ export class DeesChartArea extends DeesElement {
await this.resizeChart();
// Ensure resize observer is watching the mainbox
const mainbox = this.shadowRoot.querySelector('.mainbox');
const mainbox = this.shadowRoot!.querySelector('.mainbox');
if (mainbox && this.resizeObserver) {
// Disconnect any previous observations
this.resizeObserver.disconnect();
@@ -572,9 +572,9 @@ export class DeesChartArea extends DeesElement {
}
try {
const mainbox: HTMLDivElement = this.shadowRoot.querySelector('.mainbox');
const chartContainer: HTMLDivElement = this.shadowRoot.querySelector('.chartContainer');
const mainbox: HTMLDivElement | null = this.shadowRoot!.querySelector('.mainbox');
const chartContainer: HTMLDivElement | null = this.shadowRoot!.querySelector('.chartContainer');
if (!mainbox || !chartContainer) {
return;
}

View File

@@ -44,8 +44,8 @@ export const demoFunc = () => {
// Get the chart elements
const chartElement = elementArg.querySelector('#main-chart') as DeesChartArea;
const connectionsChartElement = elementArg.querySelector('#connections-chart') as DeesChartArea;
let intervalId: number;
let connectionsIntervalId: number;
let intervalId: number | null;
let connectionsIntervalId: number | null;
let currentDataset = 'system';
// Y-axis formatters for different datasets
@@ -71,7 +71,7 @@ export const demoFunc = () => {
// Generate initial data points for time window
const generateInitialData = (baseValue: number, variance: number, interval: number = DATA_POINT_INTERVAL) => {
const data = [];
const data: Array<{ x: string; y: number }> = [];
const now = Date.now();
const pointCount = Math.floor(TIME_WINDOW / interval);
@@ -240,10 +240,10 @@ export const demoFunc = () => {
// Switch dataset
const switchDataset = (name: string) => {
currentDataset = name;
const dataset = datasets[name];
const dataset = (datasets as Record<string, any>)[name];
chartElement.label = dataset.label;
chartElement.series = dataset.series;
chartElement.yAxisFormatter = formatters[name];
chartElement.yAxisFormatter = (formatters as Record<string, any>)[name];
// Set appropriate y-axis scaling
if (name === 'system') {

View File

@@ -8,8 +8,8 @@ export const demoFunc = () => {
// Get the log elements
const structuredLog = elementArg.querySelector('#structured-log') as DeesChartLog;
const rawLog = elementArg.querySelector('#raw-log') as DeesChartLog;
let structuredIntervalId: number;
let rawIntervalId: number;
let structuredIntervalId: number | null;
let rawIntervalId: number | null;
const serverSources = ['Server', 'Database', 'API', 'Auth', 'Cache', 'Queue', 'WebSocket', 'Scheduler'];

View File

@@ -203,7 +203,7 @@ export class DeesDataviewCodebox extends DeesElement {
</style>
<div
class="mainbox"
@contextmenu="${(eventArg) => {
@contextmenu="${(eventArg: MouseEvent) => {
DeesContextmenu.openContextMenuWithOptions(eventArg, [
{
name: 'About',
@@ -241,7 +241,7 @@ export class DeesDataviewCodebox extends DeesElement {
private codeToDisplayStore = '';
private highlightJs: HLJSApi | null = null;
public async updated(_changedProperties) {
public async updated(_changedProperties: Map<string, any>) {
super.updated(_changedProperties);
console.log('highlighting now');
console.log(this.childNodes);
@@ -267,11 +267,11 @@ export class DeesDataviewCodebox extends DeesElement {
this.highlightJs = await DeesServiceLibLoader.getInstance().loadHighlightJs();
}
const localCodeNode = this.shadowRoot.querySelector('code');
const localCodeNode = this.shadowRoot!.querySelector('code');
const highlightedHtml = this.highlightJs.highlight(this.codeToDisplayStore, {
language: this.progLang,
ignoreIllegals: true,
});
localCodeNode.innerHTML = highlightedHtml.value;
localCodeNode!.innerHTML = highlightedHtml.value;
}
}

View File

@@ -50,6 +50,7 @@ export const demoFunc = () => html` <style>
.statusObject=${{
id: '1',
name: 'API Gateway Service',
lastUpdated: Date.now(),
combinedStatus: 'ok',
combinedStatusText: 'All systems operational',
details: [
@@ -89,6 +90,7 @@ export const demoFunc = () => html` <style>
.statusObject=${{
id: '2',
name: 'PostgreSQL Cluster',
lastUpdated: Date.now() - 3600000,
combinedStatus: 'partly_ok',
combinedStatusText: 'Minor issues detected',
details: [
@@ -128,6 +130,7 @@ export const demoFunc = () => html` <style>
.statusObject=${{
id: '3',
name: 'CI/CD Pipeline',
lastUpdated: Date.now() - 86400000,
combinedStatus: 'not_ok',
combinedStatusText: 'Build failure',
details: [

View File

@@ -29,7 +29,7 @@ export class DeesDataviewStatusobject extends DeesElement {
public static demo = demoFunc;
public static demoGroups = ['Data View'];
@property({ type: Object }) accessor statusObject: tsclass.code.IStatusObject;
@property({ type: Object }) accessor statusObject!: tsclass.code.IStatusObject;
public static styles = [
themeDefaultStyles,
@@ -128,7 +128,7 @@ export class DeesDataviewStatusobject extends DeesElement {
grid-template-columns: 48px auto;
border-top: 1px solid ${cssManager.bdTheme('hsl(0 0% 94%)', 'hsl(0 0% 14.9%)')};
transition: background-color 0.15s ease;
padding-right: 16px;
padding: 0 16px;
cursor: context-menu;
}
@@ -148,7 +148,7 @@ export class DeesDataviewStatusobject extends DeesElement {
.detail .detailsText .label {
font-size: 12px;
font-weight: 500;
color: ${cssManager.bdTheme('hsl(0 0% 45.1%)', 'hsl(0 0% 63.9%)')}
color: ${cssManager.bdTheme('hsl(0 0% 45.1%)', 'hsl(0 0% 63.9%)')};
margin-bottom: 2px;
letter-spacing: -0.01em;
}
@@ -159,6 +159,28 @@ export class DeesDataviewStatusobject extends DeesElement {
color: ${cssManager.bdTheme('hsl(0 0% 15%)', 'hsl(0 0% 90%)')};
line-height: 1.5;
}
.bottomBar {
position: relative;
color: ${cssManager.bdTheme('hsl(0 0% 45.1%)', 'hsl(0 0% 63.9%)')};
background: ${cssManager.bdTheme('hsl(0 0% 97%)', 'hsl(0 0% 7%)')};
border-top: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
height: 28px;
font-size: 12px;
line-height: 28px;
display: flex;
justify-content: flex-end;
align-items: stretch;
overflow: hidden;
flex-shrink: 0;
}
.bottomBar .statusLabel {
padding: 0 16px;
display: flex;
align-items: center;
font-weight: 500;
}
`,
];
@@ -209,6 +231,11 @@ export class DeesDataviewStatusobject extends DeesElement {
</div>
`;
})}
<div class="bottomBar">
<div class="statusLabel">${this.statusObject?.lastUpdated
? `Last updated: ${new Date(this.statusObject.lastUpdated).toLocaleString()}`
: ''}</div>
</div>
</div>
`;
}
@@ -232,7 +259,7 @@ export class DeesDataviewStatusobject extends DeesElement {
await navigator.clipboard.writeText(JSON.stringify(this.statusObject, null, 2));
// Show feedback
const button = this.shadowRoot.querySelector('.copyMain') as HTMLElement;
const button = this.shadowRoot!.querySelector('.copyMain') as HTMLElement;
const originalText = button.textContent;
button.textContent = 'Copied!';

View File

@@ -878,7 +878,7 @@ export class DeesStatsGrid extends DeesElement {
private renderTile(tile: IStatsTile): TemplateResult {
const hasActions = tile.actions && tile.actions.length > 0;
const clickable = hasActions && tile.actions.length === 1;
const clickable = hasActions && tile.actions!.length === 1;
const columnSpan = tile.columnSpan && tile.columnSpan > 1 ? tile.columnSpan : undefined;
return html`

View File

@@ -1,16 +1,16 @@
import { html } from '@design.estate/dees-element';
import type { IS3DataProvider, IS3Object } from './interfaces.js';
import './dees-s3-browser.js';
import type { IStorageDataProvider, IStorageObject } from './interfaces.js';
import './dees-storage-browser.js';
// Mock in-memory S3 data provider for demo purposes
class MockS3DataProvider implements IS3DataProvider {
// Mock in-memory storage data provider for demo purposes
class MockStorageDataProvider implements IStorageDataProvider {
private objects: Map<string, { content: string; contentType: string; size: number; lastModified: string }> = new Map();
constructor() {
const now = new Date().toISOString();
// Seed with sample data
this.objects.set('documents/readme.md', {
content: btoa('# Welcome\n\nThis is a demo S3 browser.\n'),
content: btoa('# Welcome\n\nThis is a demo Storage browser.\n'),
contentType: 'text/markdown',
size: 42,
lastModified: now,
@@ -59,9 +59,9 @@ class MockS3DataProvider implements IS3DataProvider {
});
}
async listObjects(bucket: string, prefix?: string, delimiter?: string): Promise<{ objects: IS3Object[]; prefixes: string[] }> {
async listObjects(bucket: string, prefix?: string, delimiter?: string): Promise<{ objects: IStorageObject[]; prefixes: string[] }> {
const pfx = prefix || '';
const objects: IS3Object[] = [];
const objects: IStorageObject[] = [];
const prefixes = new Set<string>();
for (const [key, data] of this.objects) {
@@ -148,9 +148,9 @@ export const demoFunc = () => html`
}
</style>
<div class="demo-container">
<dees-s3-browser
.dataProvider=${new MockS3DataProvider()}
<dees-storage-browser
.dataProvider=${new MockStorageDataProvider()}
.bucketName=${'demo-bucket'}
></dees-s3-browser>
></dees-storage-browser>
</div>
`;

View File

@@ -1,26 +1,26 @@
import { customElement, html, css, cssManager, property, state, DeesElement } from '@design.estate/dees-element';
import { themeDefaultStyles } from '../../00theme.js';
import { demoFunc } from './dees-s3-browser.demo.js';
import type { IS3DataProvider, IS3ChangeEvent } from './interfaces.js';
import './dees-s3-columns.js';
import './dees-s3-keys.js';
import './dees-s3-preview.js';
import { demoFunc } from './dees-storage-browser.demo.js';
import type { IStorageDataProvider, IStorageChangeEvent } from './interfaces.js';
import './dees-storage-columns.js';
import './dees-storage-keys.js';
import './dees-storage-preview.js';
declare global {
interface HTMLElementTagNameMap {
'dees-s3-browser': DeesS3Browser;
'dees-storage-browser': DeesStorageBrowser;
}
}
type TViewType = 'columns' | 'keys';
@customElement('dees-s3-browser')
export class DeesS3Browser extends DeesElement {
@customElement('dees-storage-browser')
export class DeesStorageBrowser extends DeesElement {
public static demo = demoFunc;
public static demoGroups = ['Data View'];
@property({ type: Object })
public accessor dataProvider: IS3DataProvider | null = null;
public accessor dataProvider: IStorageDataProvider | null = null;
@property({ type: String })
public accessor bucketName: string = '';
@@ -30,7 +30,7 @@ export class DeesS3Browser extends DeesElement {
* Pass a function that takes a callback and returns an unsubscribe function.
*/
@property({ type: Object })
public accessor onChangeEvent: ((callback: (event: IS3ChangeEvent) => void) => (() => void)) | null = null;
public accessor onChangeEvent: ((callback: (event: IStorageChangeEvent) => void) => (() => void)) | null = null;
@state()
private accessor viewType: TViewType = 'columns';
@@ -288,12 +288,12 @@ export class DeesS3Browser extends DeesElement {
}
try {
this.changeUnsubscribe = this.onChangeEvent((event: IS3ChangeEvent) => {
this.changeUnsubscribe = this.onChangeEvent((event: IStorageChangeEvent) => {
this.handleChange(event);
});
this.isStreamConnected = true;
} catch (error) {
console.warn('[S3Browser] Failed to subscribe to changes:', error);
console.warn('[StorageBrowser] Failed to subscribe to changes:', error);
this.isStreamConnected = false;
}
}
@@ -306,7 +306,7 @@ export class DeesS3Browser extends DeesElement {
this.isStreamConnected = false;
}
private handleChange(event: IS3ChangeEvent) {
private handleChange(event: IStorageChangeEvent) {
this.recentChangeCount++;
this.refreshKey++;
}
@@ -395,24 +395,24 @@ export class DeesS3Browser extends DeesElement {
<div class="main-view">
${this.viewType === 'columns'
? html`
<dees-s3-columns
<dees-storage-columns
.dataProvider=${this.dataProvider}
.bucketName=${this.bucketName}
.currentPrefix=${this.currentPrefix}
.refreshKey=${this.refreshKey}
@key-selected=${this.handleKeySelected}
@navigate=${this.handleNavigate}
></dees-s3-columns>
></dees-storage-columns>
`
: html`
<dees-s3-keys
<dees-storage-keys
.dataProvider=${this.dataProvider}
.bucketName=${this.bucketName}
.currentPrefix=${this.currentPrefix}
.refreshKey=${this.refreshKey}
@key-selected=${this.handleKeySelected}
@navigate=${this.handleNavigate}
></dees-s3-keys>
></dees-storage-keys>
`}
</div>
@@ -423,12 +423,12 @@ export class DeesS3Browser extends DeesElement {
@mousedown=${this.startPreviewResize}
></div>
<div class="preview-panel">
<dees-s3-preview
<dees-storage-preview
.dataProvider=${this.dataProvider}
.bucketName=${this.bucketName}
.objectKey=${this.selectedKey}
@object-deleted=${this.handleObjectDeleted}
></dees-s3-preview>
></dees-storage-preview>
</div>
`
: ''}

View File

@@ -1,7 +1,7 @@
import { customElement, html, css, cssManager, property, state, DeesElement } from '@design.estate/dees-element';
import { DeesContextmenu } from '../../00group-overlay/dees-contextmenu/dees-contextmenu.js';
import { themeDefaultStyles } from '../../00theme.js';
import type { IS3DataProvider, IS3Object, IColumn } from './interfaces.js';
import type { IStorageDataProvider, IStorageObject, IColumn } from './interfaces.js';
import { getFileName, validateMove, getParentPrefix, getContentType, getDefaultContent, getPathSegments } from './utilities.js';
// FileSystem API types for drag-and-drop folder support
@@ -25,14 +25,14 @@ interface FileSystemDirectoryReader {
declare global {
interface HTMLElementTagNameMap {
'dees-s3-columns': DeesS3Columns;
'dees-storage-columns': DeesStorageColumns;
}
}
@customElement('dees-s3-columns')
export class DeesS3Columns extends DeesElement {
@customElement('dees-storage-columns')
export class DeesStorageColumns extends DeesElement {
@property({ type: Object })
public accessor dataProvider: IS3DataProvider | null = null;
public accessor dataProvider: IStorageDataProvider | null = null;
@property({ type: String })
public accessor bucketName: string = '';

View File

@@ -1,19 +1,19 @@
import { customElement, html, css, cssManager, property, state, DeesElement } from '@design.estate/dees-element';
import { DeesContextmenu } from '../../00group-overlay/dees-contextmenu/dees-contextmenu.js';
import { themeDefaultStyles } from '../../00theme.js';
import type { IS3DataProvider, IS3Object } from './interfaces.js';
import type { IStorageDataProvider, IStorageObject } from './interfaces.js';
import { formatSize, getFileName, validateMove, getParentPrefix, getContentType, getDefaultContent, getPathSegments } from './utilities.js';
declare global {
interface HTMLElementTagNameMap {
'dees-s3-keys': DeesS3Keys;
'dees-storage-keys': DeesStorageKeys;
}
}
@customElement('dees-s3-keys')
export class DeesS3Keys extends DeesElement {
@customElement('dees-storage-keys')
export class DeesStorageKeys extends DeesElement {
@property({ type: Object })
public accessor dataProvider: IS3DataProvider | null = null;
public accessor dataProvider: IStorageDataProvider | null = null;
@property({ type: String })
public accessor bucketName: string = '';
@@ -25,7 +25,7 @@ export class DeesS3Keys extends DeesElement {
public accessor refreshKey: number = 0;
@state()
private accessor allKeys: IS3Object[] = [];
private accessor allKeys: IStorageObject[] = [];
@state()
private accessor prefixes: string[] = [];

View File

@@ -1,18 +1,18 @@
import { customElement, html, css, cssManager, property, state, DeesElement } from '@design.estate/dees-element';
import { themeDefaultStyles } from '../../00theme.js';
import type { IS3DataProvider } from './interfaces.js';
import type { IStorageDataProvider } from './interfaces.js';
import { formatSize, getFileName } from './utilities.js';
declare global {
interface HTMLElementTagNameMap {
'dees-s3-preview': DeesS3Preview;
'dees-storage-preview': DeesStoragePreview;
}
}
@customElement('dees-s3-preview')
export class DeesS3Preview extends DeesElement {
@customElement('dees-storage-preview')
export class DeesStoragePreview extends DeesElement {
@property({ type: Object })
public accessor dataProvider: IS3DataProvider | null = null;
public accessor dataProvider: IStorageDataProvider | null = null;
@property({ type: String })
public accessor bucketName: string = '';

View File

@@ -1,6 +1,6 @@
export * from './dees-s3-browser.js';
export * from './dees-s3-columns.js';
export * from './dees-s3-keys.js';
export * from './dees-s3-preview.js';
export * from './dees-storage-browser.js';
export * from './dees-storage-columns.js';
export * from './dees-storage-keys.js';
export * from './dees-storage-preview.js';
export * from './interfaces.js';
export { formatSize, formatCount, getFileName, validateMove, getParentPrefix, getContentType, getDefaultContent, getPathSegments } from './utilities.js';

View File

@@ -1,15 +1,15 @@
/**
* S3 Data Provider interface - implement this to connect the S3 browser to your backend
* Storage Data Provider interface - implement this to connect the storage browser to your backend
*/
export interface IS3Object {
export interface IStorageObject {
key: string;
size?: number;
lastModified?: string;
isPrefix?: boolean;
}
export interface IS3ChangeEvent {
export interface IStorageChangeEvent {
type: 'add' | 'modify' | 'delete';
key: string;
bucket: string;
@@ -17,8 +17,8 @@ export interface IS3ChangeEvent {
lastModified?: Date;
}
export interface IS3DataProvider {
listObjects(bucket: string, prefix?: string, delimiter?: string): Promise<{ objects: IS3Object[]; prefixes: string[] }>;
export interface IStorageDataProvider {
listObjects(bucket: string, prefix?: string, delimiter?: string): Promise<{ objects: IStorageObject[]; prefixes: string[] }>;
getObject(bucket: string, key: string): Promise<{ content: string; contentType: string; size: number; lastModified: string }>;
putObject(bucket: string, key: string, base64Content: string, contentType: string): Promise<boolean>;
deleteObject(bucket: string, key: string): Promise<boolean>;
@@ -30,7 +30,7 @@ export interface IS3DataProvider {
export interface IColumn {
prefix: string;
objects: IS3Object[];
objects: IStorageObject[];
prefixes: string[];
selectedItem: string | null;
width: number;

View File

@@ -1,5 +1,5 @@
/**
* Shared utilities for S3 browser components
* Shared utilities for Storage browser components
*/
export interface IMoveValidation {

View File

@@ -52,12 +52,12 @@ export class DeesTable<T> extends DeesElement {
@property({
type: String,
})
accessor key: string;
accessor key!: string;
@property({
type: String,
})
accessor label: string;
accessor label!: string;
@property({
type: Boolean,
@@ -83,7 +83,7 @@ export class DeesTable<T> extends DeesElement {
type: String,
reflect: true,
})
accessor dataName: string;
accessor dataName!: string;
@property({
@@ -127,7 +127,7 @@ export class DeesTable<T> extends DeesElement {
@property({
type: Object,
})
accessor selectedDataRow: T;
accessor selectedDataRow!: T;
@property({
type: Array,
@@ -359,7 +359,7 @@ export class DeesTable<T> extends DeesElement {
if (elementArg.tagName === 'TR') {
return elementArg;
} else {
return getTr(elementArg.parentElement);
return getTr(elementArg.parentElement!);
}
};
return html`
@@ -393,8 +393,8 @@ export class DeesTable<T> extends DeesElement {
}}
@drop=${async (eventArg: DragEvent) => {
eventArg.preventDefault();
const newFiles = [];
for (const file of Array.from(eventArg.dataTransfer.files)) {
const newFiles: File[] = [];
for (const file of Array.from(eventArg.dataTransfer!.files)) {
this.files.push(file);
newFiles.push(file);
this.requestUpdate();
@@ -548,8 +548,8 @@ export class DeesTable<T> extends DeesElement {
type: ['header'],
actionFunc: async () => {
console.log('open search');
const searchGrid = this.shadowRoot.querySelector('.searchGrid');
searchGrid.classList.toggle('hidden');
const searchGrid = this.shadowRoot!.querySelector('.searchGrid');
searchGrid!.classList.toggle('hidden');
}
});
console.log(this.dataActions);
@@ -609,7 +609,7 @@ export class DeesTable<T> extends DeesElement {
const domtools = await this.domtoolsPromise;
await domtools.convenience.smartdelay.delayFor(0);
// Get the table element
const table = this.shadowRoot.querySelector('table');
const table = this.shadowRoot!.querySelector('table');
if (!table) return;
// Get the first row's cells to measure the widths
@@ -718,7 +718,7 @@ export class DeesTable<T> extends DeesElement {
if (!this._rowIdMap.has(key)) {
this._rowIdMap.set(key, String(++this._rowIdCounter));
}
return this._rowIdMap.get(key);
return this._rowIdMap.get(key)!;
}
private isRowSelected(row: T): boolean {
@@ -818,7 +818,7 @@ export class DeesTable<T> extends DeesElement {
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)
(itemArg as any)[key] = input.value as any; // Convert string to T (you might need better type casting depending on your data structure)
this.changeSubject.next(this);
}
input.remove();

View File

@@ -3,4 +3,4 @@ export * from './dees-dataview-codebox/index.js';
export * from './dees-dataview-statusobject/index.js';
export * from './dees-table/index.js';
export * from './dees-statsgrid/index.js';
export * from './dees-s3-browser/index.js';
export * from './dees-storage-browser/index.js';

View File

@@ -89,7 +89,7 @@ export class DeesProgressbar extends DeesElement {
}
public async updatePercentage() {
const progressBarFill = this.shadowRoot.querySelector('.progressBarFill') as HTMLElement;
const progressBarFill = this.shadowRoot!.querySelector('.progressBarFill') as HTMLElement;
progressBarFill.style.width = `${this.percentage}%`;
}

View File

@@ -30,7 +30,7 @@ export class DeesFormSubmit extends DeesElement {
accessor disabled = false;
@property({ type: String })
accessor text: string;
accessor text!: string;
@property({ type: String })
accessor status: 'normal' | 'pending' | 'success' | 'error' = 'normal';
@@ -42,7 +42,7 @@ export class DeesFormSubmit extends DeesElement {
accessor size: 'sm' | 'default' | 'lg' | 'icon' | 'small' | 'normal' | 'large' = 'default';
@property({ type: String })
accessor icon: string;
accessor icon!: string;
@property({ type: String })
accessor iconPosition: 'left' | 'right' = 'left';

View File

@@ -57,10 +57,10 @@ export const demoFunc = () => html`
const outputDiv = elementArg.querySelector('.form-output');
if (form && outputDiv) {
form.addEventListener('formData', async (eventArg: CustomEvent) => {
form.addEventListener('formData', (async (eventArg: CustomEvent) => {
const data = eventArg.detail.data;
console.log('Form submitted with data:', data);
// Show processing state
form.setStatus('pending', 'Processing your registration...');
outputDiv.innerHTML = `<strong>Submitted Data:</strong>\n${JSON.stringify(data, null, 2)}`;
@@ -75,7 +75,7 @@ export const demoFunc = () => html`
await domtools.plugins.smartdelay.delayFor(2000);
form.reset();
outputDiv.innerHTML = '<em>Form has been reset</em>';
});
}) as unknown as EventListener);
// Track individual field changes
const inputs = form.querySelectorAll('dees-input-text, dees-input-dropdown, dees-input-checkbox');
@@ -158,14 +158,14 @@ export const demoFunc = () => html`
console.log('Horizontal form layout active');
// Monitor filter changes
form.addEventListener('formData', (event: CustomEvent) => {
form.addEventListener('formData', ((event: CustomEvent) => {
const filters = event.detail.data;
console.log('Filter applied:', filters);
// Simulate search
const resultsCount = Math.floor(Math.random() * 100) + 1;
console.log(`Found ${resultsCount} results with filters:`, filters);
});
}) as unknown as EventListener);
// Setup real-time filter updates
const inputs = form.querySelectorAll('[key]');
@@ -224,7 +224,7 @@ export const demoFunc = () => html`
const statusDiv = elementArg.querySelector('#status-display');
if (form) {
form.addEventListener('formData', async (eventArg: CustomEvent) => {
form.addEventListener('formData', (async (eventArg: CustomEvent) => {
const data = eventArg.detail.data;
console.log('Advanced form data:', data);
@@ -252,7 +252,7 @@ export const demoFunc = () => html`
}
console.log('Form data logged:', data);
});
}) as unknown as EventListener);
// Monitor file uploads
const fileUpload = form.querySelector('dees-input-fileupload');

View File

@@ -135,13 +135,14 @@ export class DeesForm extends DeesElement {
}
public getFormElements(): Array<TFormInputElement> {
return Array.from(this.children).filter((child) =>
// Use querySelectorAll('*') to find form inputs nested inside wrapper elements (e.g. <div>)
return Array.from(this.querySelectorAll('*')).filter((child) =>
FORM_INPUT_TYPES.includes(child.constructor as any)
) as unknown as TFormInputElement[];
}
public getSubmitButton(): DeesFormSubmit | undefined {
return Array.from(this.children).find(
return Array.from(this.querySelectorAll('*')).find(
(child) => child instanceof DeesFormSubmit
) as DeesFormSubmit;
}
@@ -155,8 +156,9 @@ export class DeesForm extends DeesElement {
requiredOK = false;
}
}
if (this.getSubmitButton()) {
this.getSubmitButton().disabled = !requiredOK;
const submitButton = this.getSubmitButton();
if (submitButton) {
submitButton.disabled = !requiredOK;
}
}
@@ -199,6 +201,7 @@ export class DeesForm extends DeesElement {
) {
const inputChildren = this.getFormElements();
const submitButton = this.getSubmitButton();
if (!submitButton) return;
switch (visualStateArg) {
case 'normal':
@@ -239,7 +242,6 @@ export class DeesForm extends DeesElement {
*/
reset() {
const inputChildren = this.getFormElements();
const submitButton = this.getSubmitButton();
for (const inputChild of inputChildren) {
inputChild.value = null;

View File

@@ -31,10 +31,10 @@ export abstract class DeesInputBase<T = any> extends DeesElement {
* Common properties for all inputs
*/
@property({ type: String })
accessor key: string;
accessor key!: string;
@property({ type: String })
accessor label: string;
accessor label!: string;
@property({ type: Boolean })
accessor required: boolean = false;
@@ -43,7 +43,7 @@ export abstract class DeesInputBase<T = any> extends DeesElement {
accessor disabled: boolean = false;
@property({ type: String })
accessor description: string;
accessor description!: string;
/**
* Common styles for all input components

View File

@@ -215,7 +215,7 @@ export class DeesInputCheckbox extends DeesInputBase<DeesInputCheckbox> {
}
public focus(): void {
const checkboxDiv = this.shadowRoot.querySelector('.checkbox');
const checkboxDiv = this.shadowRoot!.querySelector('.checkbox');
if (checkboxDiv) {
(checkboxDiv as any).focus();
}

View File

@@ -610,20 +610,20 @@ export class DeesInputCode extends DeesInputBase<string> {
{
name: 'Cancel',
action: async (modalRef) => {
await modalRef.destroy();
await modalRef!.destroy();
},
},
{
name: 'Save & Close',
action: async (modalRef) => {
// Get the editor content from the modal
modalEditorElement = modalRef.shadowRoot?.querySelector('dees-workspace-monaco') as DeesWorkspaceMonaco;
modalEditorElement = modalRef!.shadowRoot?.querySelector('dees-workspace-monaco') as DeesWorkspaceMonaco;
if (modalEditorElement) {
const editor = await modalEditorElement.editorDeferred.promise;
const newValue = editor.getValue();
this.setValue(newValue);
}
await modalRef.destroy();
await modalRef!.destroy();
},
},
],

View File

@@ -47,9 +47,9 @@ export const demoFunc = () => html`
const datePicker = elementArg.querySelector('dees-input-datepicker');
if (datePicker) {
datePicker.addEventListener('change', (event: CustomEvent) => {
datePicker.addEventListener('change', ((event: CustomEvent) => {
console.log('Basic date selected:', (event.target as DeesInputDatepicker).value);
});
}) as EventListener);
}
}}>
<dees-panel .title=${'Basic Date Picker'} .subtitle=${'Simple date selection without time'}>
@@ -66,17 +66,17 @@ export const demoFunc = () => html`
const appointmentPicker = elementArg.querySelector('dees-input-datepicker[label="Appointment"]');
if (dateTimePicker) {
dateTimePicker.addEventListener('change', (event: CustomEvent) => {
dateTimePicker.addEventListener('change', ((event: CustomEvent) => {
const value = (event.target as DeesInputDatepicker).value;
console.log('24h format datetime:', value);
});
}) as EventListener);
}
if (appointmentPicker) {
appointmentPicker.addEventListener('change', (event: CustomEvent) => {
appointmentPicker.addEventListener('change', ((event: CustomEvent) => {
const value = (event.target as DeesInputDatepicker).value;
console.log('12h format datetime:', value);
});
}) as EventListener);
}
}}>
<dees-panel .title=${'Date and Time Selection'} .subtitle=${'Date pickers with time selection in different formats'}>
@@ -102,14 +102,14 @@ export const demoFunc = () => html`
const timezonePickers = elementArg.querySelectorAll('dees-input-datepicker');
timezonePickers.forEach((picker) => {
picker.addEventListener('change', (event: CustomEvent) => {
picker.addEventListener('change', ((event: CustomEvent) => {
const target = event.target as DeesInputDatepicker;
console.log(`${target.label} value:`, target.value);
const input = target.shadowRoot?.querySelector('.date-input') as HTMLInputElement;
if (input) {
console.log(`${target.label} formatted:`, input.value);
}
});
}) as EventListener);
});
}}>
<dees-panel .title=${'Timezone Support'} .subtitle=${'Date and time selection with timezone awareness'}>
@@ -140,7 +140,7 @@ export const demoFunc = () => html`
if (futureDatePicker) {
// Show the min/max constraints in action
futureDatePicker.addEventListener('change', (event: CustomEvent) => {
futureDatePicker.addEventListener('change', ((event: CustomEvent) => {
const value = (event.target as DeesInputDatepicker).value;
if (value) {
const selectedDate = new Date(value);
@@ -148,7 +148,7 @@ export const demoFunc = () => html`
const daysDiff = Math.floor((selectedDate.getTime() - today.getTime()) / (1000 * 60 * 60 * 24));
console.log(`Selected date is ${daysDiff} days from today`);
}
});
}) as EventListener);
}
}}>
<dees-panel .title=${'Date Range Constraints'} .subtitle=${'Limit selectable dates with min and max values'}>
@@ -171,14 +171,14 @@ export const demoFunc = () => html`
const datePickers = elementArg.querySelectorAll('dees-input-datepicker');
datePickers.forEach((picker) => {
picker.addEventListener('change', (event: CustomEvent) => {
picker.addEventListener('change', ((event: CustomEvent) => {
const target = event.target as DeesInputDatepicker;
// Log the formatted value that's displayed in the input
const input = target.shadowRoot?.querySelector('.date-input') as HTMLInputElement;
if (input) {
console.log(`${target.label} format:`, input.value);
}
});
}) as EventListener);
});
}}>
<dees-panel .title=${'Date Formats'} .subtitle=${'Different date display formats for various regions'}>
@@ -268,7 +268,7 @@ export const demoFunc = () => html`
<dees-demowrapper .runAfterRender=${async (elementArg: HTMLElement) => {
// Generate weekend dates for the current month
const generateWeekends = () => {
const weekends = [];
const weekends: string[] = [];
const now = new Date();
const year = now.getFullYear();
const month = now.getMonth();
@@ -286,7 +286,7 @@ export const demoFunc = () => html`
const picker = elementArg.querySelector('dees-input-datepicker');
if (picker) {
picker.disabledDates = generateWeekends();
(picker as DeesInputDatepicker).disabledDates = generateWeekends();
console.log('Disabled weekend dates for current month');
}
}}>
@@ -344,7 +344,7 @@ export const demoFunc = () => html`
const picker = elementArg.querySelector('dees-input-datepicker');
if (picker) {
picker.events = sampleEvents;
(picker as DeesInputDatepicker).events = sampleEvents;
console.log('Calendar events loaded:', sampleEvents);
}
}}>
@@ -371,7 +371,7 @@ export const demoFunc = () => html`
const output = elementArg.querySelector('#event-output');
if (picker && output) {
picker.addEventListener('change', (event: CustomEvent) => {
picker.addEventListener('change', ((event: CustomEvent) => {
const target = event.target as DeesInputDatepicker;
const value = target.value;
if (value) {
@@ -379,16 +379,16 @@ export const demoFunc = () => html`
// Get the formatted value from the input element
const input = target.shadowRoot?.querySelector('.date-input') as HTMLInputElement;
const formattedValue = input?.value || 'N/A';
output.innerHTML = `
(output as HTMLElement).innerHTML = `
<strong>Event triggered!</strong><br>
ISO Value: ${value}<br>
Formatted: ${formattedValue}<br>
Date object: ${date.toLocaleString()}
`;
} else {
output.innerHTML = '<em>Date cleared</em>';
(output as HTMLElement).innerHTML = '<em>Date cleared</em>';
}
});
}) as EventListener);
picker.addEventListener('blur', () => {
console.log('Datepicker lost focus');

View File

@@ -56,16 +56,16 @@ export const demoFunc = () => html`
// Log when country changes
if (countryDropdown) {
countryDropdown.addEventListener('selectedOption', (event: CustomEvent) => {
countryDropdown.addEventListener('selectedOption', ((event: CustomEvent) => {
console.log('Country selected:', event.detail);
});
}) as EventListener);
}
// Log when role changes
if (roleDropdown) {
roleDropdown.addEventListener('selectedOption', (event: CustomEvent) => {
roleDropdown.addEventListener('selectedOption', ((event: CustomEvent) => {
console.log('Role selected:', event.detail);
});
}) as EventListener);
}
}}>
<dees-panel .title=${'1. Basic Dropdowns'} .subtitle=${'Standard dropdown with search functionality and various options'}>
@@ -103,9 +103,9 @@ export const demoFunc = () => html`
const priorityDropdown = elementArg.querySelector('dees-input-dropdown');
if (priorityDropdown) {
priorityDropdown.addEventListener('selectedOption', (event: CustomEvent) => {
priorityDropdown.addEventListener('selectedOption', ((event: CustomEvent) => {
console.log(`Priority changed to: ${event.detail.option}`);
});
}) as EventListener);
}
}}>
<dees-panel .title=${'2. Without Search'} .subtitle=${'Dropdown with search functionality disabled for simpler selection'}>
@@ -128,10 +128,10 @@ export const demoFunc = () => html`
// Log all changes from horizontal dropdowns
dropdowns.forEach((dropdown) => {
dropdown.addEventListener('selectedOption', (event: CustomEvent) => {
dropdown.addEventListener('selectedOption', ((event: CustomEvent) => {
const label = dropdown.getAttribute('label');
console.log(`${label}: ${event.detail.option}`);
});
}) as EventListener);
});
}}>
<dees-panel .title=${'3. Horizontal Layout'} .subtitle=${'Multiple dropdowns in a horizontal layout for compact forms'}>
@@ -216,9 +216,9 @@ export const demoFunc = () => html`
const dropdown = elementArg.querySelector('dees-input-dropdown');
if (dropdown) {
dropdown.addEventListener('selectedOption', (event: CustomEvent) => {
dropdown.addEventListener('selectedOption', ((event: CustomEvent) => {
console.log('Bottom dropdown selected:', event.detail);
});
}) as EventListener);
// Note: The dropdown automatically detects available space
// and opens upward when near the bottom of the viewport
@@ -248,16 +248,16 @@ export const demoFunc = () => html`
output.innerHTML = '<em>Select a product to see details...</em>';
// Handle dropdown changes
dropdown.addEventListener('change', (event: CustomEvent) => {
dropdown.addEventListener('change', ((event: CustomEvent) => {
if (event.detail.value) {
output.innerHTML = `
(output as HTMLElement).innerHTML = `
<strong>Selected:</strong> ${event.detail.value.option}<br>
<strong>Key:</strong> ${event.detail.value.key}<br>
<strong>Price:</strong> $${event.detail.value.payload?.price || 'N/A'}<br>
<strong>Features:</strong> ${event.detail.value.payload?.features?.join(', ') || 'N/A'}
`;
}
});
}) as EventListener);
}
}}>
<dees-panel .title=${'6. Event Handling & Payload'} .subtitle=${'Dropdown with payload data and change event handling'}>
@@ -281,20 +281,20 @@ export const demoFunc = () => html`
const frameworkDropdown = elementArg.querySelector('dees-input-dropdown[key="framework"]');
if (form) {
form.addEventListener('formData', (event: CustomEvent) => {
form.addEventListener('formData', ((event: CustomEvent) => {
console.log('Form submitted with data:', event.detail.data);
});
}) as EventListener);
}
if (projectTypeDropdown && frameworkDropdown) {
// Filter frameworks based on project type
projectTypeDropdown.addEventListener('selectedOption', (event: CustomEvent) => {
projectTypeDropdown.addEventListener('selectedOption', ((event: CustomEvent) => {
const selectedType = event.detail.key;
console.log(`Project type changed to: ${selectedType}`);
// In a real app, you could filter the framework options based on project type
// For demo purposes, we just log the change
});
}) as EventListener);
}
}}>
<dees-panel .title=${'7. Form Integration'} .subtitle=${'Dropdown working within a form with validation'}>

View File

@@ -30,14 +30,14 @@ export class DeesInputDropdown extends DeesInputBase<DeesInputDropdown> {
accessor options: { option: string; key: string; payload?: any }[] = [];
@property()
accessor selectedOption: { option: string; key: string; payload?: any } = null;
accessor selectedOption: { option: string; key: string; payload?: any } | null = null;
// Add value property for form compatibility
public get value() {
return this.selectedOption;
}
public set value(val: { option: string; key: string; payload?: any }) {
public set value(val: { option: string; key: string; payload?: any } | null) {
this.selectedOption = val;
}
@@ -372,7 +372,7 @@ export class DeesInputDropdown extends DeesInputBase<DeesInputDropdown> {
if (this.isOpened) {
// Check available space and set position
const selectedBox = this.shadowRoot.querySelector('.selectedBox') as HTMLElement;
const selectedBox = this.shadowRoot!.querySelector('.selectedBox') as HTMLElement;
const rect = selectedBox.getBoundingClientRect();
const spaceBelow = window.innerHeight - rect.bottom;
const spaceAbove = rect.top;
@@ -382,7 +382,7 @@ export class DeesInputDropdown extends DeesInputBase<DeesInputDropdown> {
// Focus search input if present
await this.updateComplete;
const searchInput = this.shadowRoot.querySelector('.search input') as HTMLInputElement;
const searchInput = this.shadowRoot!.querySelector('.search input') as HTMLInputElement;
if (searchInput) {
searchInput.focus();
}
@@ -455,7 +455,7 @@ export class DeesInputDropdown extends DeesInputBase<DeesInputDropdown> {
}
}
public getValue(): { option: string; key: string; payload?: any } {
public getValue(): { option: string; key: string; payload?: any } | null {
return this.selectedOption;
}

View File

@@ -48,7 +48,7 @@ export class DeesInputFileupload extends DeesInputBase<DeesInputFileupload> {
accessor maxFiles: number = 0; // 0 means no limit
@property({ type: String, reflect: true })
accessor validationState: 'valid' | 'invalid' | 'warn' | 'pending' = null;
accessor validationState: 'valid' | 'invalid' | 'warn' | 'pending' | null = null;
accessor validationMessage: string = '';
@@ -266,7 +266,7 @@ export class DeesInputFileupload extends DeesInputBase<DeesInputFileupload> {
return;
}
['dragenter', 'dragover', 'dragleave', 'drop'].forEach((eventName) => {
this.dropArea!.addEventListener(eventName, this.handleDragEvent);
this.dropArea!.addEventListener(eventName, this.handleDragEvent as unknown as EventListener);
});
}
@@ -275,7 +275,7 @@ export class DeesInputFileupload extends DeesInputBase<DeesInputFileupload> {
return;
}
['dragenter', 'dragover', 'dragleave', 'drop'].forEach((eventName) => {
this.dropArea!.removeEventListener(eventName, this.handleDragEvent);
this.dropArea!.removeEventListener(eventName, this.handleDragEvent as unknown as EventListener);
});
}

View File

@@ -60,7 +60,7 @@ export class DeesInputIban extends DeesInputBase<DeesInputIban> {
public firstUpdated(_changedProperties: Map<string | number | symbol, unknown>) {
super.firstUpdated(_changedProperties);
const deesInputText = this.shadowRoot.querySelector('dees-input-text') as any;
const deesInputText = this.shadowRoot!.querySelector('dees-input-text') as any;
if (deesInputText && deesInputText.changeSubject) {
deesInputText.changeSubject.subscribe(() => {
this.changeSubject.next(this);
@@ -81,8 +81,10 @@ export class DeesInputIban extends DeesInputBase<DeesInputIban> {
}
}
this.enteredIbanIsValid = ibantools.isValidIBAN(this.enteredString.replace(/ /g, ''));
const deesInputText = this.shadowRoot.querySelector('dees-input-text');
deesInputText.validationText = `IBAN is valid: ${this.enteredIbanIsValid}`;
const deesInputText = this.shadowRoot!.querySelector('dees-input-text') as any;
if (deesInputText) {
deesInputText.validationText = `IBAN is valid: ${this.enteredIbanIsValid}`;
}
}
public getValue(): string {

View File

@@ -211,9 +211,9 @@ export class DeesInputMultitoggle extends DeesInputBase<DeesInputMultitoggle> {
private indicatorInitialized = false;
public async setIndicator() {
const indicator: HTMLDivElement = this.shadowRoot.querySelector('.indicator');
const indicator: HTMLDivElement | null = this.shadowRoot!.querySelector('.indicator');
const selectedIndex = this.options.indexOf(this.selectedOption);
// If no valid selection, hide indicator
if (selectedIndex === -1 || !indicator) {
if (indicator) {
@@ -221,8 +221,8 @@ export class DeesInputMultitoggle extends DeesInputBase<DeesInputMultitoggle> {
}
return;
}
const option: HTMLDivElement = this.shadowRoot.querySelector(
const option: HTMLDivElement | null = this.shadowRoot!.querySelector(
`.option:nth-child(${selectedIndex + 2})`
);

View File

@@ -67,7 +67,7 @@ export class DeesInputPhone extends DeesInputBase<DeesInputPhone> {
}
// Subscribe to the inner input's changes
const innerInput = this.shadowRoot.querySelector('dees-input-text') as any;
const innerInput = this.shadowRoot!.querySelector('dees-input-text') as any;
if (innerInput && innerInput.changeSubject) {
innerInput.changeSubject.subscribe(() => {
this.changeSubject.next(this);

View File

@@ -35,7 +35,7 @@ export class DeesInputRadiogroup extends DeesInputBase<string | object> {
accessor direction: 'vertical' | 'horizontal' = 'vertical';
@property({ type: String, reflect: true })
accessor validationState: 'valid' | 'invalid' | 'warn' | 'pending' = null;
accessor validationState: 'valid' | 'invalid' | 'warn' | 'pending' | null = null;
// Form compatibility
public get value() {
@@ -346,15 +346,15 @@ export class DeesInputRadiogroup extends DeesInputBase<string | object> {
}
private focusNextOption() {
const radioCircles = Array.from(this.shadowRoot.querySelectorAll('.radio-circle'));
const currentIndex = radioCircles.findIndex(el => el === this.shadowRoot.activeElement);
const radioCircles = Array.from(this.shadowRoot!.querySelectorAll('.radio-circle'));
const currentIndex = radioCircles.findIndex(el => el === this.shadowRoot!.activeElement);
const nextIndex = (currentIndex + 1) % radioCircles.length;
(radioCircles[nextIndex] as HTMLElement).focus();
}
private focusPreviousOption() {
const radioCircles = Array.from(this.shadowRoot.querySelectorAll('.radio-circle'));
const currentIndex = radioCircles.findIndex(el => el === this.shadowRoot.activeElement);
const radioCircles = Array.from(this.shadowRoot!.querySelectorAll('.radio-circle'));
const currentIndex = radioCircles.findIndex(el => el === this.shadowRoot!.activeElement);
const prevIndex = currentIndex <= 0 ? radioCircles.length - 1 : currentIndex - 1;
(radioCircles[prevIndex] as HTMLElement).focus();
}

View File

@@ -58,11 +58,11 @@ export class DeesInputRichtext extends DeesInputBase<string> {
@state()
accessor wordCount: number = 0;
private editorElement: HTMLElement;
private linkInputElement: HTMLInputElement;
private editorElement!: HTMLElement;
private linkInputElement!: HTMLInputElement;
private tiptapBundle: ITiptapBundle | null = null;
public editor: Editor;
public editor!: Editor;
public static styles = richtextStyles;
@@ -235,8 +235,8 @@ export class DeesInputRichtext extends DeesInputBase<string> {
// Load Tiptap from CDN
this.tiptapBundle = await DeesServiceLibLoader.getInstance().loadTiptap();
this.editorElement = this.shadowRoot.querySelector('.editor-content');
this.linkInputElement = this.shadowRoot.querySelector('.link-input input');
this.editorElement = this.shadowRoot!.querySelector('.editor-content')!;
this.linkInputElement = this.shadowRoot!.querySelector('.link-input input')!;
this.initializeEditor();
}

View File

@@ -73,9 +73,9 @@ export const demoFunc = () => html`
const inputs = elementArg.querySelectorAll('dees-input-text');
inputs.forEach((input: DeesInputText) => {
input.addEventListener('changeSubject', (event: CustomEvent) => {
input.addEventListener('changeSubject', ((event: CustomEvent) => {
console.log(`Input "${input.label}" changed to:`, input.getValue());
});
}) as EventListener);
input.addEventListener('blur', () => {
console.log(`Input "${input.label}" lost focus`);
@@ -271,7 +271,8 @@ export const demoFunc = () => html`
// Track password visibility toggles
const passwordInputs = elementArg.querySelectorAll('dees-input-text[isPasswordBool]');
passwordInputs.forEach((input: DeesInputText) => {
passwordInputs.forEach((_input) => {
const input = _input as DeesInputText;
// Monitor for toggle button clicks within shadow DOM
const checkToggle = () => {
const inputEl = input.shadowRoot?.querySelector('input');
@@ -316,10 +317,10 @@ export const demoFunc = () => html`
if (dynamicInput && output) {
// Update output on every change
dynamicInput.addEventListener('changeSubject', (event: CustomEvent) => {
dynamicInput.addEventListener('changeSubject', ((event: CustomEvent) => {
const value = (event.detail as DeesInputText).getValue();
output.textContent = `Current value: "${value}"`;
});
}) as EventListener);
// Also track focus/blur events
dynamicInput.addEventListener('focus', () => {

View File

@@ -47,7 +47,7 @@ export class DeesInputText extends DeesInputBase {
type: Boolean,
reflect: true,
})
accessor validationState: 'valid' | 'warn' | 'invalid';
accessor validationState!: 'valid' | 'warn' | 'invalid';
@property({
reflect: true,
@@ -55,7 +55,7 @@ export class DeesInputText extends DeesInputBase {
accessor validationText: string = '';
@property({})
accessor validationFunction: (value: string) => boolean;
accessor validationFunction!: (value: string) => boolean;
public static styles = [
themeDefaultStyles,
@@ -274,12 +274,12 @@ export class DeesInputText extends DeesInputBase {
}
public async focus() {
const textInput = this.shadowRoot.querySelector('input');
textInput.focus();
const textInput = this.shadowRoot!.querySelector('input');
textInput!.focus();
}
public async blur() {
const textInput = this.shadowRoot.querySelector('input');
textInput.blur();
const textInput = this.shadowRoot!.querySelector('input');
textInput!.blur();
}
}

View File

@@ -12,17 +12,19 @@ export const demoFunc = () => html`
if (toggleAllOnBtn && toggleAllOffBtn) {
toggleAllOnBtn.addEventListener('click', () => {
featureToggles.forEach((toggle: DeesInputToggle) => {
if (!toggle.disabled && !toggle.required) {
toggle.value = true;
featureToggles.forEach((toggle) => {
const t = toggle as unknown as DeesInputToggle;
if (!t.disabled && !t.required) {
t.value = true;
}
});
});
toggleAllOffBtn.addEventListener('click', () => {
featureToggles.forEach((toggle: DeesInputToggle) => {
if (!toggle.disabled && !toggle.required) {
toggle.value = false;
featureToggles.forEach((toggle) => {
const t = toggle as unknown as DeesInputToggle;
if (!t.disabled && !t.required) {
t.value = false;
}
});
});
@@ -280,10 +282,10 @@ export const demoFunc = () => html`
<dees-input-toggle
.label=${'Airplane mode'}
.value=${false}
@newValue=${(event: CustomEvent) => {
@newValue=${(event: Event) => {
const output = document.querySelector('#airplane-output');
if (output) {
output.textContent = `Airplane mode: ${event.detail ? 'ON' : 'OFF'}`;
output.textContent = `Airplane mode: ${(event as CustomEvent).detail ? 'ON' : 'OFF'}`;
}
}}
></dees-input-toggle>
@@ -291,10 +293,10 @@ export const demoFunc = () => html`
<dees-input-toggle
.label=${'Do not disturb'}
.value=${false}
@newValue=${(event: CustomEvent) => {
@newValue=${(event: Event) => {
const output = document.querySelector('#dnd-output');
if (output) {
output.textContent = `Do not disturb: ${event.detail ? 'ENABLED' : 'DISABLED'}`;
output.textContent = `Do not disturb: ${(event as CustomEvent).detail ? 'ENABLED' : 'DISABLED'}`;
}
}}
></dees-input-toggle>

View File

@@ -156,7 +156,7 @@ export class DeesInputTypelist extends DeesInputBase<DeesInputTypelist> {
<dees-label .label=${this.label} .description=${this.description}></dees-label>
<div class="mainbox">
<div class="tags" @click=${() => {
this.shadowRoot.querySelector('input').focus();
this.shadowRoot!.querySelector('input')!.focus();
}}>
${this.value.length === 0
? html`<div class="notags">No tags yet</div>`

View File

@@ -200,15 +200,16 @@ export class HeadingBlockHandler extends BaseBlockHandler {
const wysiwygBlock = (headingBlock.getRootNode() as ShadowRoot).host as any;
if (wysiwygBlock) {
const originalDisconnectedCallback = (wysiwygBlock as any).disconnectedCallback;
const self = this;
(wysiwygBlock as any).disconnectedCallback = async function() {
if (this.selectionHandler) {
document.removeEventListener('selectionchange', this.selectionHandler);
this.selectionHandler = null;
if (self.selectionHandler) {
document.removeEventListener('selectionchange', self.selectionHandler);
self.selectionHandler = null;
}
if (originalDisconnectedCallback) {
await originalDisconnectedCallback.call(wysiwygBlock);
}
}.bind(this);
};
}
}

View File

@@ -213,15 +213,16 @@ export class ListBlockHandler extends BaseBlockHandler {
const wysiwygBlock = (listBlock.getRootNode() as ShadowRoot).host as any;
if (wysiwygBlock) {
const originalDisconnectedCallback = (wysiwygBlock as any).disconnectedCallback;
const self = this;
(wysiwygBlock as any).disconnectedCallback = async function() {
if (this.selectionHandler) {
document.removeEventListener('selectionchange', this.selectionHandler);
this.selectionHandler = null;
if (self.selectionHandler) {
document.removeEventListener('selectionchange', self.selectionHandler);
self.selectionHandler = null;
}
if (originalDisconnectedCallback) {
await originalDisconnectedCallback.call(wysiwygBlock);
}
}.bind(this);
};
}
}

View File

@@ -193,15 +193,16 @@ export class ParagraphBlockHandler extends BaseBlockHandler {
const wysiwygBlock = element.closest('dees-wysiwyg-block');
if (wysiwygBlock) {
const originalDisconnectedCallback = (wysiwygBlock as any).disconnectedCallback;
const self = this;
(wysiwygBlock as any).disconnectedCallback = async function() {
if (this.selectionHandler) {
document.removeEventListener('selectionchange', this.selectionHandler);
this.selectionHandler = null;
if (self.selectionHandler) {
document.removeEventListener('selectionchange', self.selectionHandler);
self.selectionHandler = null;
}
if (originalDisconnectedCallback) {
await originalDisconnectedCallback.call(wysiwygBlock);
}
}.bind(this);
};
}
}

View File

@@ -192,15 +192,16 @@ export class QuoteBlockHandler extends BaseBlockHandler {
const wysiwygBlock = (quoteBlock.getRootNode() as ShadowRoot).host as any;
if (wysiwygBlock) {
const originalDisconnectedCallback = (wysiwygBlock as any).disconnectedCallback;
const self = this;
(wysiwygBlock as any).disconnectedCallback = async function() {
if (this.selectionHandler) {
document.removeEventListener('selectionchange', this.selectionHandler);
this.selectionHandler = null;
if (self.selectionHandler) {
document.removeEventListener('selectionchange', self.selectionHandler);
self.selectionHandler = null;
}
if (originalDisconnectedCallback) {
await originalDisconnectedCallback.call(wysiwygBlock);
}
}.bind(this);
};
}
}

View File

@@ -188,36 +188,39 @@ export class DeesFormattingMenu extends DeesElement {
public firstUpdated(): void {
// Set up event delegation for the menu
this.shadowRoot?.addEventListener('mousedown', (e: MouseEvent) => {
this.shadowRoot!.addEventListener('mousedown', (e: Event) => {
const mouseEvent = e as MouseEvent;
const menu = this.shadowRoot?.querySelector('.formatting-menu');
if (menu && menu.contains(e.target as Node)) {
if (menu && menu.contains(mouseEvent.target as Node)) {
// Prevent focus loss
e.preventDefault();
e.stopPropagation();
mouseEvent.preventDefault();
mouseEvent.stopPropagation();
}
});
this.shadowRoot?.addEventListener('click', (e: MouseEvent) => {
const target = e.target as HTMLElement;
this.shadowRoot!.addEventListener('click', (e: Event) => {
const mouseEvent = e as MouseEvent;
const target = mouseEvent.target as HTMLElement;
const button = target.closest('.format-button') as HTMLElement;
if (button) {
e.preventDefault();
e.stopPropagation();
mouseEvent.preventDefault();
mouseEvent.stopPropagation();
const command = button.getAttribute('data-command');
if (command) {
this.applyFormat(command);
}
}
});
this.shadowRoot?.addEventListener('focus', (e: FocusEvent) => {
this.shadowRoot!.addEventListener('focus', (e: Event) => {
const focusEvent = e as FocusEvent;
const menu = this.shadowRoot?.querySelector('.formatting-menu');
if (menu && menu.contains(e.target as Node)) {
if (menu && menu.contains(focusEvent.target as Node)) {
// Prevent menu from taking focus
e.preventDefault();
e.stopPropagation();
focusEvent.preventDefault();
focusEvent.stopPropagation();
}
}, true); // Use capture phase
}

View File

@@ -77,7 +77,7 @@ export class DeesInputWysiwyg extends DeesInputBase<string> {
@state()
accessor selectedText: string = '';
public editorContentRef: HTMLDivElement;
public editorContentRef!: HTMLDivElement;
public isComposing: boolean = false;
// Handler instances
@@ -144,7 +144,7 @@ export class DeesInputWysiwyg extends DeesInputBase<string> {
// No global selection listener needed
// Listen for custom selection events from blocks
this.addEventListener('block-text-selected', (e: CustomEvent) => {
this.addEventListener('block-text-selected', ((e: CustomEvent) => {
if (!this.slashMenu.visible && e.detail.hasSelection && e.detail.text.length > 0) {
this.selectedText = e.detail.text;
@@ -164,8 +164,8 @@ export class DeesInputWysiwyg extends DeesInputBase<string> {
);
}
}
});
}) as EventListener);
// Hide formatting menu when clicking outside
document.addEventListener('mousedown', (e) => {
// Check if click is on the formatting menu itself
@@ -896,14 +896,14 @@ export class DeesInputWysiwyg extends DeesInputBase<string> {
{
name: 'Cancel',
action: async (modal) => {
modal.destroy();
modal!.destroy();
resolve(null);
}
},
{
name: 'Add Link',
action: async (modal) => {
modal.destroy();
modal!.destroy();
resolve(linkUrl);
}
}

View File

@@ -216,46 +216,50 @@ export class DeesSlashMenu extends DeesElement {
public firstUpdated(): void {
// Set up event delegation
this.shadowRoot?.addEventListener('mousedown', (e: MouseEvent) => {
this.shadowRoot!.addEventListener('mousedown', (e: Event) => {
const mouseEvent = e as MouseEvent;
const menu = this.shadowRoot?.querySelector('.slash-menu');
if (menu && menu.contains(e.target as Node)) {
if (menu && menu.contains(mouseEvent.target as Node)) {
// Prevent focus loss
e.preventDefault();
e.stopPropagation();
mouseEvent.preventDefault();
mouseEvent.stopPropagation();
}
});
this.shadowRoot?.addEventListener('click', (e: MouseEvent) => {
const target = e.target as HTMLElement;
this.shadowRoot!.addEventListener('click', (e: Event) => {
const mouseEvent = e as MouseEvent;
const target = mouseEvent.target as HTMLElement;
const menuItem = target.closest('.slash-menu-item') as HTMLElement;
if (menuItem) {
e.preventDefault();
e.stopPropagation();
mouseEvent.preventDefault();
mouseEvent.stopPropagation();
const itemType = menuItem.getAttribute('data-item-type');
if (itemType) {
this.selectItem(itemType);
}
}
});
this.shadowRoot?.addEventListener('mouseenter', (e: MouseEvent) => {
const target = e.target as HTMLElement;
this.shadowRoot!.addEventListener('mouseenter', (e: Event) => {
const mouseEvent = e as MouseEvent;
const target = mouseEvent.target as HTMLElement;
const menuItem = target.closest('.slash-menu-item') as HTMLElement;
if (menuItem) {
const index = parseInt(menuItem.getAttribute('data-item-index') || '0', 10);
this.selectedIndex = index;
}
}, true); // Use capture phase
this.shadowRoot?.addEventListener('focus', (e: FocusEvent) => {
this.shadowRoot!.addEventListener('focus', (e: Event) => {
const focusEvent = e as FocusEvent;
const menu = this.shadowRoot?.querySelector('.slash-menu');
if (menu && menu.contains(e.target as Node)) {
if (menu && menu.contains(focusEvent.target as Node)) {
// Prevent menu from taking focus
e.preventDefault();
e.stopPropagation();
focusEvent.preventDefault();
focusEvent.stopPropagation();
}
}, true); // Use capture phase
}

View File

@@ -33,13 +33,13 @@ export class DeesWysiwygBlock extends DeesElement {
}
}
@property({ type: Object })
accessor block: IBlock;
accessor block!: IBlock;
@property({ type: Boolean })
accessor isSelected: boolean = false;
@property({ type: Object })
accessor handlers: IBlockEventHandlers;
accessor handlers!: IBlockEventHandlers;
@property({ type: Object })
accessor wysiwygComponent: any; // Reference to parent dees-input-wysiwyg

View File

@@ -105,10 +105,10 @@ export class WysiwygDragDropHandler {
handleDragEnd(): void {
// Clean up visual state
const allBlocks = this.component.editorContentRef.querySelectorAll('.block-wrapper');
allBlocks.forEach((block: HTMLElement) => {
block.classList.remove('dragging', 'move-up', 'move-down');
block.style.removeProperty('--drag-offset');
block.style.removeProperty('transform');
allBlocks.forEach((block) => {
(block as HTMLElement).classList.remove('dragging', 'move-up', 'move-down');
(block as HTMLElement).style.removeProperty('--drag-offset');
(block as HTMLElement).style.removeProperty('transform');
});
// Remove dragging class from editor

View File

@@ -704,17 +704,17 @@ export class WysiwygKeyboardHandler {
const rect = range.getBoundingClientRect();
// Get the container element
let container = range.commonAncestorContainer;
let container: Node = range.commonAncestorContainer;
if (container.nodeType === Node.TEXT_NODE) {
container = container.parentElement;
container = container.parentElement!;
}
// Get the top position of the container
const containerRect = (container as Element).getBoundingClientRect();
// Check if we're near the top (within 5px tolerance for line height variations)
const isNearTop = rect.top - containerRect.top < 5;
// For single-line content, also check if we're at the beginning
if (container.textContent && !container.textContent.includes('\n')) {
const cursorPos = WysiwygSelection.getCursorPositionInElement(container as Element, ...shadowRoots);
@@ -740,11 +740,11 @@ export class WysiwygKeyboardHandler {
const rect = range.getBoundingClientRect();
// Get the container element
let container = range.commonAncestorContainer;
let container: Node = range.commonAncestorContainer;
if (container.nodeType === Node.TEXT_NODE) {
container = container.parentElement;
container = container.parentElement!;
}
// Get the bottom position of the container
const containerRect = (container as Element).getBoundingClientRect();

View File

@@ -72,7 +72,7 @@ export class WysiwygModalManager {
{
name: 'Cancel',
action: async (modal) => {
modal.destroy();
modal!.destroy();
resolve(null);
}
}
@@ -158,7 +158,7 @@ export class WysiwygModalManager {
{
name: 'Done',
action: async (modal) => {
modal.destroy();
modal!.destroy();
}
}
]

View File

@@ -56,10 +56,10 @@ export const demoFunc = () => html`
const roundProfile = elementArg.querySelector('dees-input-profilepicture[shape="round"]');
if (roundProfile) {
roundProfile.addEventListener('change', (event: CustomEvent) => {
roundProfile.addEventListener('change', ((event: CustomEvent) => {
const target = event.target as DeesInputProfilePicture;
console.log('Round profile picture changed:', target.value?.substring(0, 50) + '...');
});
}) as EventListener);
}
}}>
<dees-panel .title=${'Profile Picture Input'} .subtitle=${'Basic usage with round and square shapes'}>
@@ -85,10 +85,10 @@ export const demoFunc = () => html`
// Different sizes demo
const profiles = elementArg.querySelectorAll('dees-input-profilepicture');
profiles.forEach((profile) => {
profile.addEventListener('change', (event: CustomEvent) => {
profile.addEventListener('change', ((event: CustomEvent) => {
const target = event.target as DeesInputProfilePicture;
console.log(`Profile (size ${target.size}) changed`);
});
}) as EventListener);
});
}}>
<dees-panel .title=${'Size Variations'} .subtitle=${'Profile pictures in different sizes'}>
@@ -122,15 +122,15 @@ export const demoFunc = () => html`
if (prefilledProfile) {
prefilledProfile.value = sampleImageUrl;
prefilledProfile.addEventListener('change', (event: CustomEvent) => {
prefilledProfile.addEventListener('change', ((event: CustomEvent) => {
const target = event.target as DeesInputProfilePicture;
const output = elementArg.querySelector('#prefilled-output');
if (output) {
output.textContent = target.value ?
`Image data: ${target.value.substring(0, 80)}...` :
output.textContent = target.value ?
`Image data: ${target.value.substring(0, 80)}...` :
'No image selected';
}
});
}) as EventListener);
}
}}>
<dees-panel .title=${'Pre-filled and Value Binding'} .subtitle=${'Profile picture with initial value and change tracking'}>

View File

@@ -436,10 +436,10 @@ export class DeesInputProfilePicture extends DeesInputBase<DeesInputProfilePictu
this.modalInstance.outputSize = this.outputSize;
this.modalInstance.outputQuality = this.outputQuality;
this.modalInstance.addEventListener('save', (event: CustomEvent) => {
this.modalInstance.addEventListener('save', ((event: CustomEvent) => {
this.value = event.detail.croppedImage;
this.changeSubject.next(this);
});
}) as EventListener);
document.body.appendChild(this.modalInstance);
}

View File

@@ -41,7 +41,7 @@ export class DeesChips extends DeesElement {
accessor selectableChips: Tag[] = [];
@property()
accessor selectedChip: Tag = null;
accessor selectedChip: Tag | null = null;
@property({
type: Array,

View File

@@ -1,5 +1,6 @@
import { html, css, cssManager } from '@design.estate/dees-element';
import type { DeesDashboardgrid } from './dees-dashboardgrid.js';
import type { LayoutDirection } from './types.js';
import '@design.estate/dees-wcctools/demotools';
export const demoFunc = () => {
@@ -160,7 +161,7 @@ export const demoFunc = () => {
});
// Enhanced logging for reflow events
let lastPlaceholderPosition = null;
let lastPlaceholderPosition: Record<string, string> | null = null;
let moveEventCounter = 0;
// Helper function to log grid state
@@ -231,25 +232,28 @@ export const demoFunc = () => {
// Log initial state
logGridState('Initial Grid State');
grid.addEventListener('widget-move', (e: CustomEvent) => {
grid.addEventListener('widget-move', (e: Event) => {
const detail = (e as CustomEvent).detail;
logGridState('Widget Move', {
widget: e.detail.widget,
displaced: e.detail.displaced,
swappedWith: e.detail.swappedWith
widget: detail.widget,
displaced: detail.displaced,
swappedWith: detail.swappedWith
});
});
grid.addEventListener('widget-resize', (e: CustomEvent) => {
grid.addEventListener('widget-resize', (e: Event) => {
const detail = (e as CustomEvent).detail;
logGridState('Widget Resize', {
widget: e.detail.widget,
displaced: e.detail.displaced,
swappedWith: e.detail.swappedWith
widget: detail.widget,
displaced: detail.displaced,
swappedWith: detail.swappedWith
});
});
grid.addEventListener('widget-remove', (e: CustomEvent) => {
grid.addEventListener('widget-remove', (e: Event) => {
const detail = (e as CustomEvent).detail;
logGridState('Widget Remove', {
removedWidget: e.detail.widget
removedWidget: detail.widget
});
updateStatus();
});
@@ -312,7 +316,7 @@ export const demoFunc = () => {
// Log compact operations
const originalCompact = grid.compact.bind(grid);
grid.compact = (direction?: string) => {
grid.compact = (direction?: LayoutDirection) => {
console.group('🗜️ Compacting Grid');
console.log('Direction:', direction || 'vertical');
logGridState('Before Compact');

View File

@@ -32,7 +32,7 @@ export class DeesLabel extends DeesElement {
type: String,
reflect: true,
})
accessor description: string;
accessor description!: string;
@property({
type: Boolean,

View File

@@ -45,7 +45,7 @@ export class DeesStepper extends DeesElement {
@property({
type: Object,
})
accessor selectedStep: IStep;
accessor selectedStep!: IStep;
constructor() {
super();
@@ -214,19 +214,19 @@ export class DeesStepper extends DeesElement {
this.setScrollStatus();
// Remove entrance class after initial animation completes
await this.domtools.convenience.smartdelay.delayFor(350);
this.shadowRoot.querySelector('.step.entrance')?.classList.remove('entrance');
this.shadowRoot!.querySelector('.step.entrance')?.classList.remove('entrance');
}
public async updated() {
this.setScrollStatus();
}
public scroller: typeof domtools.plugins.SweetScroll.prototype;
public scroller!: typeof domtools.plugins.SweetScroll.prototype;
public async setScrollStatus() {
const stepperContainer: HTMLElement = this.shadowRoot.querySelector('.stepperContainer');
const firstStepElement: HTMLElement = this.shadowRoot.querySelector('.step');
const selectedStepElement: HTMLElement = this.shadowRoot.querySelector('.selected');
const stepperContainer = this.shadowRoot!.querySelector('.stepperContainer') as HTMLElement;
const firstStepElement = this.shadowRoot!.querySelector('.step') as HTMLElement;
const selectedStepElement = this.shadowRoot!.querySelector('.selected') as HTMLElement;
if (!selectedStepElement) {
return;
}
@@ -278,7 +278,7 @@ export class DeesStepper extends DeesElement {
this.selectedStep = previousStep;
await this.domtoolsPromise;
await this.domtools.convenience.smartdelay.delayFor(100);
this.selectedStep.onReturnToStepFunc?.(this, this.shadowRoot.querySelector('.selected'));
this.selectedStep.onReturnToStepFunc?.(this, this.shadowRoot!.querySelector('.selected') as HTMLElement);
}
public goNext() {

View File

@@ -21,9 +21,9 @@ export function throttle<T extends (...args: any[]) => any>(
): (...args: Parameters<T>) => void {
let inThrottle: boolean;
return function executedFunction(...args: Parameters<T>) {
return (...args: Parameters<T>) => {
if (!inThrottle) {
func.apply(this, args);
func(...args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}

View File

@@ -7,7 +7,7 @@ export const demo = () => {
];
const generateGridItems = (count: number) => {
const items = [];
const items: ReturnType<typeof html>[] = [];
for (let i = 0; i < count; i++) {
const pdfUrl = samplePdfs[i % samplePdfs.length];
items.push(html`

View File

@@ -130,7 +130,7 @@ export class DeesContextmenu extends DeesElement {
type: Array,
})
accessor menuItems: (plugins.tsclass.website.IMenuItem & { shortcut?: string; disabled?: boolean; submenu?: (plugins.tsclass.website.IMenuItem & { shortcut?: string; disabled?: boolean } | { divider: true })[]; divider?: never } | { divider: true })[] = [];
windowLayer: DeesWindowLayer;
windowLayer!: DeesWindowLayer;
private submenu: DeesContextmenu | null = null;
private submenuTimeout: any = null;
@@ -278,7 +278,7 @@ export class DeesContextmenu extends DeesElement {
}
private handleKeydown = (event: KeyboardEvent) => {
const menuItems = Array.from(this.shadowRoot.querySelectorAll('.menuitem:not(.disabled)'));
const menuItems = Array.from(this.shadowRoot!.querySelectorAll('.menuitem:not(.disabled)'));
const currentIndex = menuItems.findIndex(item => item.matches(':hover'));
switch (event.key) {
@@ -352,7 +352,7 @@ export class DeesContextmenu extends DeesElement {
if (!menuItem.submenu || menuItem.submenu.length === 0) return;
// Find the menu item element
const menuItems = Array.from(this.shadowRoot.querySelectorAll('.menuitem'));
const menuItems = Array.from(this.shadowRoot!.querySelectorAll('.menuitem'));
const menuItemElement = menuItems.find(el => el.querySelector('.menuitem-text')?.textContent === menuItem.name) as HTMLElement;
if (!menuItemElement) return;

View File

@@ -49,7 +49,7 @@ export const demoFunc = () => html`
heading: 'With Help Button',
showHelpButton: true,
onHelp: async () => {
const helpModal = await DeesModal.createAndShow({
await DeesModal.createAndShow({
heading: 'Help',
width: 'small',
showCloseButton: true,
@@ -60,7 +60,7 @@ export const demoFunc = () => html`
`,
menuOptions: [{
name: 'Got it',
action: async (modal) => modal.destroy()
action: async (modal) => modal!.destroy()
}],
});
},
@@ -70,7 +70,7 @@ export const demoFunc = () => html`
`,
menuOptions: [{
name: 'OK',
action: async (modal) => modal.destroy()
action: async (modal) => modal!.destroy()
}],
});
}}>With Help Button</dees-button>
@@ -85,7 +85,7 @@ export const demoFunc = () => html`
`,
menuOptions: [{
name: 'Close',
action: async (modal) => modal.destroy()
action: async (modal) => modal!.destroy()
}],
});
}}>No Close Button</dees-button>
@@ -101,7 +101,7 @@ export const demoFunc = () => html`
`,
menuOptions: [{
name: 'Done',
action: async (modal) => modal.destroy()
action: async (modal) => modal!.destroy()
}],
});
}}>Both Buttons</dees-button>
@@ -116,7 +116,7 @@ export const demoFunc = () => html`
`,
menuOptions: [{
name: 'Close',
action: async (modal) => modal.destroy()
action: async (modal) => modal!.destroy()
}],
});
}}>Clean Header</dees-button>
@@ -136,10 +136,10 @@ export const demoFunc = () => html`
`,
menuOptions: [{
name: 'Cancel',
action: async (modal) => modal.destroy()
action: async (modal) => modal!.destroy()
}, {
name: 'OK',
action: async (modal) => modal.destroy()
action: async (modal) => modal!.destroy()
}],
});
}}>Small Modal</dees-button>
@@ -157,10 +157,10 @@ export const demoFunc = () => html`
`,
menuOptions: [{
name: 'Cancel',
action: async (modal) => modal.destroy()
action: async (modal) => modal!.destroy()
}, {
name: 'Sign Up',
action: async (modal) => modal.destroy()
action: async (modal) => modal!.destroy()
}],
});
}}>Medium Modal</dees-button>
@@ -181,10 +181,10 @@ export const demoFunc = () => html`
`,
menuOptions: [{
name: 'Cancel',
action: async (modal) => modal.destroy()
action: async (modal) => modal!.destroy()
}, {
name: 'Save',
action: async (modal) => modal.destroy()
action: async (modal) => modal!.destroy()
}],
});
}}>Large Modal</dees-button>
@@ -207,10 +207,10 @@ export const demoFunc = () => html`
`,
menuOptions: [{
name: 'Save',
action: async (modal) => modal.destroy()
action: async (modal) => modal!.destroy()
}, {
name: 'Cancel',
action: async (modal) => modal.destroy()
action: async (modal) => modal!.destroy()
}],
});
}}>Fullscreen Modal</dees-button>
@@ -230,7 +230,7 @@ export const demoFunc = () => html`
`,
menuOptions: [{
name: 'Close',
action: async (modal) => modal.destroy()
action: async (modal) => modal!.destroy()
}],
});
}}>Custom 700px</dees-button>
@@ -245,7 +245,7 @@ export const demoFunc = () => html`
`,
menuOptions: [{
name: 'Got it',
action: async (modal) => modal.destroy()
action: async (modal) => modal!.destroy()
}],
});
}}>Max Width 600px</dees-button>
@@ -260,7 +260,7 @@ export const demoFunc = () => html`
`,
menuOptions: [{
name: 'OK',
action: async (modal) => modal.destroy()
action: async (modal) => modal!.destroy()
}],
});
}}>Min Width 400px</dees-button>
@@ -279,13 +279,13 @@ export const demoFunc = () => html`
`,
menuOptions: [{
name: 'Delete',
action: async (modal) => modal.destroy()
action: async (modal) => modal!.destroy()
}, {
name: 'Cancel',
action: async (modal) => modal.destroy()
action: async (modal) => modal!.destroy()
}, {
name: 'Save Changes',
action: async (modal) => modal.destroy()
action: async (modal) => modal!.destroy()
}],
});
}}>Three Buttons</dees-button>
@@ -298,7 +298,7 @@ export const demoFunc = () => html`
`,
menuOptions: [{
name: 'Acknowledge',
action: async (modal) => modal.destroy()
action: async (modal) => modal!.destroy()
}],
});
}}>Single Button</dees-button>
@@ -322,10 +322,10 @@ export const demoFunc = () => html`
`,
menuOptions: [{
name: 'Discard All Changes',
action: async (modal) => modal.destroy()
action: async (modal) => modal!.destroy()
}, {
name: 'Save and Continue Editing',
action: async (modal) => modal.destroy()
action: async (modal) => modal!.destroy()
}],
});
}}>Long Labels</dees-button>
@@ -347,7 +347,7 @@ export const demoFunc = () => html`
`,
menuOptions: [{
name: 'Close',
action: async (modal) => modal.destroy()
action: async (modal) => modal!.destroy()
}],
});
}}>Test Responsive</dees-button>

View File

@@ -85,7 +85,7 @@ export class DeesModal extends DeesElement {
accessor heading = '';
@state({})
accessor content: TemplateResult;
accessor content!: TemplateResult;
@state({})
accessor menuOptions: plugins.tsclass.website.IMenuItem<DeesModal>[] = [];
@@ -94,10 +94,10 @@ export class DeesModal extends DeesElement {
accessor width: 'small' | 'medium' | 'large' | 'fullscreen' | number = 'medium';
@property({ type: Number })
accessor maxWidth: number;
accessor maxWidth!: number;
@property({ type: Number })
accessor minWidth: number;
accessor minWidth!: number;
@property({ type: Boolean })
accessor showCloseButton: boolean = true;
@@ -106,7 +106,7 @@ export class DeesModal extends DeesElement {
accessor showHelpButton: boolean = false;
@property({ attribute: false })
accessor onHelp: () => void | Promise<void>;
accessor onHelp!: () => void | Promise<void>;
@property({ type: Boolean })
accessor mobileFullscreen: boolean = false;
@@ -383,18 +383,18 @@ export class DeesModal extends DeesElement {
`;
}
private windowLayer: DeesWindowLayer;
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');
const modal = this.shadowRoot!.querySelector('.modal');
modal!.classList.add('show');
}
public async handleOutsideClick(eventArg: MouseEvent) {
eventArg.stopPropagation();
const modalContainer = this.shadowRoot.querySelector('.modalContainer');
const modalContainer = this.shadowRoot!.querySelector('.modalContainer');
if (eventArg.target === modalContainer) {
await this.destroy();
}
@@ -402,8 +402,8 @@ export class DeesModal extends DeesElement {
public async destroy() {
const domtools = await this.domtoolsPromise;
const modal = this.shadowRoot.querySelector('.modal');
modal.classList.add('predestroy');
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

@@ -42,7 +42,7 @@ export class DeesSpeechbubble extends DeesElement {
speechbubble.manifested = true;
windowLayer.appendChild(speechbubble);
windowLayer.style.pointerEvents = 'none';
(windowLayer.shadowRoot.querySelector('.windowOverlay') as HTMLElement).style.pointerEvents = 'none';
(windowLayer.shadowRoot!.querySelector('.windowOverlay') as HTMLElement).style.pointerEvents = 'none';
return speechbubble;
}
@@ -50,13 +50,13 @@ export class DeesSpeechbubble extends DeesElement {
@property({
type: Object,
})
accessor reffedElement: HTMLElement;
accessor reffedElement!: HTMLElement;
@property({
type: String,
reflect: true,
})
accessor text: string;
accessor text!: string;
@property({
type: Boolean,
@@ -73,7 +73,7 @@ export class DeesSpeechbubble extends DeesElement {
})
accessor status: 'normal' | 'pending' | 'success' | 'error' = 'normal';
public windowLayer: DeesWindowLayer;
public windowLayer!: DeesWindowLayer;
constructor() {
super();
@@ -189,7 +189,7 @@ export class DeesSpeechbubble extends DeesElement {
}
if (this.manifested) {
await this.updatePosition();
(this.shadowRoot.querySelector('.maincontainer') as HTMLElement).style.opacity = '1';
(this.shadowRoot!.querySelector('.maincontainer') as HTMLElement).style.opacity = '1';
} else {
// lets make sure we instrument it
let speechbubble: DeesSpeechbubble;
@@ -227,7 +227,7 @@ export class DeesSpeechbubble extends DeesElement {
public async show() {}
public async destroy() {
(this.shadowRoot.querySelector('.maincontainer') as HTMLElement).style.opacity = '0';
(this.shadowRoot!.querySelector('.maincontainer') as HTMLElement).style.opacity = '0';
this.windowLayer.destroy();
}
}

View File

@@ -132,7 +132,7 @@ export class WebContainerEnvironment implements IExecutionEnvironment {
const watcher = this.container!.fs.watch(
path,
{ recursive: options?.recursive ?? false },
callback
callback as (event: 'rename' | 'change', filename: string | Uint8Array) => void
);
return {
stop: () => watcher.close(),

View File

@@ -109,14 +109,14 @@ export const demoFunc = () => html`
<dees-panel .title=${'Interactive Shopping Cart'} .subtitle=${'Product cards with dynamic cart calculation'} .runAfterRender=${async (elementArg: HTMLElement) => {
const products = [
{ id: 'laptop', element: null, data: { name: 'MacBook Pro 14"', category: 'Computers', description: 'M3 Pro chip with 18GB RAM', price: 1999, originalPrice: 2199, iconName: 'lucide:laptop' }},
{ id: 'ipad', element: null, data: { name: 'iPad Air', category: 'Tablets', description: '10.9" Liquid Retina display', price: 599, iconName: 'lucide:tablet' }},
{ id: 'keyboard', element: null, data: { name: 'Magic Keyboard', category: 'Accessories', description: 'Wireless keyboard with Touch ID', price: 149, iconName: 'lucide:keyboard' }}
{ id: 'laptop', element: null as DeesShoppingProductcard | null, data: { name: 'MacBook Pro 14"', category: 'Computers', description: 'M3 Pro chip with 18GB RAM', price: 1999, originalPrice: 2199, iconName: 'lucide:laptop' }},
{ id: 'ipad', element: null as DeesShoppingProductcard | null, data: { name: 'iPad Air', category: 'Tablets', description: '10.9" Liquid Retina display', price: 599, iconName: 'lucide:tablet' }},
{ id: 'keyboard', element: null as DeesShoppingProductcard | null, data: { name: 'Magic Keyboard', category: 'Accessories', description: 'Wireless keyboard with Touch ID', price: 149, iconName: 'lucide:keyboard' }}
];
const updateCartSummary = () => {
let total = 0;
const items = [];
const items: string[] = [];
products.forEach(product => {
const element = elementArg.querySelector(`#${product.id}`) as DeesShoppingProductcard;
@@ -216,8 +216,8 @@ export const demoFunc = () => html`
const output = document.querySelector('#selection-output');
if (output) {
const selectedCards = document.querySelectorAll('dees-shopping-productcard[selectable]');
const selectedProducts = [];
selectedCards.forEach((card: DeesShoppingProductcard) => {
const selectedProducts: string[] = [];
(selectedCards as NodeListOf<DeesShoppingProductcard>).forEach((card) => {
if (card.selected) {
selectedProducts.push(card.productData.name);
}
@@ -243,8 +243,8 @@ export const demoFunc = () => html`
const output = document.querySelector('#selection-output');
if (output) {
const selectedCards = document.querySelectorAll('dees-shopping-productcard[selectable]');
const selectedProducts = [];
selectedCards.forEach((card: DeesShoppingProductcard) => {
const selectedProducts: string[] = [];
(selectedCards as NodeListOf<DeesShoppingProductcard>).forEach((card) => {
if (card.selected) {
selectedProducts.push(card.productData.name);
}
@@ -271,8 +271,8 @@ export const demoFunc = () => html`
const output = document.querySelector('#selection-output');
if (output) {
const selectedCards = document.querySelectorAll('dees-shopping-productcard[selectable]');
const selectedProducts = [];
selectedCards.forEach((card: DeesShoppingProductcard) => {
const selectedProducts: string[] = [];
(selectedCards as NodeListOf<DeesShoppingProductcard>).forEach((card) => {
if (card.selected) {
selectedProducts.push(card.productData.name);
}

View File

@@ -46,7 +46,7 @@ export class DeesSimpleAppDash extends DeesElement {
accessor terminalSetupCommand: string = `echo "Terminal ready"`;
@state()
accessor selectedView: IView;
accessor selectedView!: IView;
public static styles = [
@@ -386,7 +386,7 @@ export class DeesSimpleAppDash extends DeesElement {
`;
}
public async firstUpdated(_changedProperties): Promise<void> {
public async firstUpdated(_changedProperties: Map<string | number | symbol, unknown>): Promise<void> {
const domtools = await this.domtoolsPromise;
super.firstUpdated(_changedProperties);
if (this.viewTabs && this.viewTabs.length > 0) {
@@ -395,7 +395,7 @@ export class DeesSimpleAppDash extends DeesElement {
}
}
public currentTerminal: DeesWorkspaceTerminal;
public currentTerminal: DeesWorkspaceTerminal | null = null;
public async launchTerminal() {
const domtools = await this.domtoolsPromise;
if (this.currentTerminal) {
@@ -404,7 +404,7 @@ export class DeesSimpleAppDash extends DeesElement {
return;
}
const maincontainer = this.shadowRoot.querySelector('.maincontainer');
const maincontainer = this.shadowRoot!.querySelector('.maincontainer')! as HTMLElement;
const { DeesWorkspaceTerminal } = await import('../../00group-workspace/dees-workspace-terminal/dees-workspace-terminal.js');
const terminal = new DeesWorkspaceTerminal();
terminal.setupCommand = this.terminalSetupCommand;
@@ -444,9 +444,9 @@ export class DeesSimpleAppDash extends DeesElement {
}
private currentView: DeesElement;
private currentView!: DeesElement;
public async loadView(viewArg: IView) {
const appcontent = this.shadowRoot.querySelector('.appcontent');
const appcontent = this.shadowRoot!.querySelector('.appcontent')!;
const view = new viewArg.element();
if (this.currentView) {
this.currentView.remove();

View File

@@ -141,15 +141,15 @@ export class DeesSimpleLogin extends DeesElement {
public async firstUpdated(_changedProperties: Map<string | number | symbol, unknown>): Promise<void> {
super.firstUpdated(_changedProperties);
const form = this.shadowRoot.querySelector('dees-form') as any;
const form = this.shadowRoot!.querySelector('dees-form') as any;
if (form) {
form.addEventListener('formData', (event: CustomEvent) => {
form.addEventListener('formData', ((event: CustomEvent) => {
this.dispatchEvent(new CustomEvent('login', {
detail: event.detail,
bubbles: true,
composed: true
}));
});
}) as EventListener);
}
}
@@ -158,9 +158,9 @@ export class DeesSimpleLogin extends DeesElement {
*/
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');
const loginDiv = this.shadowRoot!.querySelector('.login') as HTMLDivElement;
const loginContainerDiv = this.shadowRoot!.querySelector('.loginContainer') as HTMLDivElement;
const slotContainerDiv = this.shadowRoot!.querySelector('.slotContainer') as HTMLDivElement;
loginDiv.style.opacity = '0';
loginDiv.style.transform = 'translateY(20px)';
loginContainerDiv.style.pointerEvents = 'none';

View File

@@ -15,7 +15,7 @@ export const demoFunc = () => {
.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 isFunction = typeof (lucideIcons as any)[key] === 'function';
const notUtility = !['createElement', 'createIcons', 'default'].includes(key);
return isFunction && isUppercaseFirst && notUtility;
})
@@ -63,7 +63,7 @@ export const demoFunc = () => {
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 demoContainer = (event.target as HTMLElement).closest('.demoContainer')!;
const containers = demoContainer.querySelectorAll('.iconContainer');
containers.forEach(container => {
@@ -79,7 +79,7 @@ export const demoFunc = () => {
});
// Update counts - search within demoContainer
demoContainer.querySelectorAll('.section-container').forEach(section => {
demoContainer!.querySelectorAll('.section-container').forEach(section => {
const visibleIcons = section.querySelectorAll('.iconContainer:not(.hidden)').length;
const countElement = section.querySelector('.icon-count');
if (countElement) {

View File

@@ -208,7 +208,7 @@ export class DeesIcon extends DeesElement {
accessor icon: IconWithPrefix | undefined = undefined;
@property({ type: Number })
accessor iconSize: number;
accessor iconSize!: number;
@property({ type: String })
accessor color: string = 'currentColor';
@@ -292,13 +292,13 @@ export class DeesIcon extends DeesElement {
const pascalCaseName = iconName.charAt(0).toUpperCase() + iconName.slice(1);
// Check if the icon exists in lucideIcons
if (!lucideIcons[pascalCaseName]) {
if (!(lucideIcons as any)[pascalCaseName]) {
console.warn(`Lucide icon '${pascalCaseName}' not found in lucideIcons object`);
return '';
}
// Use the exact pattern from Lucide documentation
const svgElement = createElement(lucideIcons[pascalCaseName], {
const svgElement = createElement((lucideIcons as any)[pascalCaseName], {
color: this.color,
size: this.iconSize,
strokeWidth: this.strokeWidth
@@ -404,9 +404,9 @@ export class DeesIcon extends DeesElement {
// Convert to PascalCase
const pascalCaseName = name.charAt(0).toUpperCase() + name.slice(1);
if (lucideIcons[pascalCaseName]) {
if ((lucideIcons as any)[pascalCaseName]) {
// Use the documented pattern from Lucide docs
const svgElement = createElement(lucideIcons[pascalCaseName], {
const svgElement = createElement((lucideIcons as any)[pascalCaseName], {
color: this.color,
size: this.iconSize,
strokeWidth: this.strokeWidth

View File

@@ -33,12 +33,12 @@ export class DeesUpdater extends DeesElement {
@property({
type: String,
})
accessor currentVersion: string;
accessor currentVersion!: string;
@property({
type: String,
})
accessor updatedVersion: string;
accessor updatedVersion!: string;
constructor() {
super();
@@ -107,7 +107,7 @@ export class DeesUpdater extends DeesElement {
}
public async destroy() {
this.parentElement.removeChild(this);
this.parentElement!.removeChild(this);
}
private windowLayerClicked() {}

View File

@@ -447,7 +447,7 @@ export class DeesWorkspaceFiletree extends DeesElement {
e.preventDefault();
e.stopPropagation();
const menuItems = [];
const menuItems: Array<{ name?: string; iconName?: string; action?: () => Promise<void>; divider?: boolean }> = [];
if (node.type === 'directory') {
// Directory-specific options
@@ -503,7 +503,7 @@ export class DeesWorkspaceFiletree extends DeesElement {
}
);
await DeesContextmenu.openContextMenuWithOptions(e, menuItems);
await DeesContextmenu.openContextMenuWithOptions(e, menuItems as any);
}
private async handleEmptySpaceContextMenu(e: MouseEvent) {
@@ -561,14 +561,14 @@ export class DeesWorkspaceFiletree extends DeesElement {
menuOptions: [
{
name: 'Cancel',
action: async (modalRef) => {
action: async (modalRef: any) => {
await modalRef.destroy();
resolve(null);
},
},
{
name: options.buttonName || 'Create',
action: async (modalRef) => {
action: async (modalRef: any) => {
// Query the input element directly and read its value
const contentEl = modalRef.shadowRoot?.querySelector('.modal .content');
const inputElement = contentEl?.querySelector('dees-input-text') as DeesInputText | null;

View File

@@ -129,8 +129,8 @@ export class DeesWorkspaceMarkdown extends DeesElement {
@state()
accessor isDragging: boolean = false;
private resizeHandleElement: HTMLElement;
private containerElement: HTMLElement;
private resizeHandleElement!: HTMLElement;
private containerElement!: HTMLElement;
public render() {
return html`
@@ -173,26 +173,26 @@ const hello = 'yes'
`;
}
public async firstUpdated(_changedPropertiesArg) {
public async firstUpdated(_changedPropertiesArg: Map<string | number | symbol, unknown>) {
await super.firstUpdated(_changedPropertiesArg);
// Initialize current ratio from property
this.currentSplitRatio = this.splitRatio;
// Cache elements
this.containerElement = this.shadowRoot.querySelector('.splitContainer');
this.resizeHandleElement = this.shadowRoot.querySelector('.resizeHandle');
this.containerElement = this.shadowRoot!.querySelector('.splitContainer')!;
this.resizeHandleElement = this.shadowRoot!.querySelector('.resizeHandle')!;
const editor = this.shadowRoot.querySelector('dees-workspace-monaco') as DeesWorkspaceMonaco;
const editor = this.shadowRoot!.querySelector('dees-workspace-monaco') as DeesWorkspaceMonaco;
// Wire up markdown rendering
const markdownOutlet = this.shadowRoot.querySelector('dees-workspace-markdownoutlet');
const markdownOutlet = this.shadowRoot!.querySelector('dees-workspace-markdownoutlet');
const smartmarkdownInstance = new domtools.plugins.smartmarkdown.SmartMarkdown();
const mdParsedResult = await smartmarkdownInstance.getMdParsedResultFromMarkdown('loading...')
editor.contentSubject.subscribe(async contentArg => {
await mdParsedResult.updateFromMarkdownString(contentArg)
const html = mdParsedResult.html;
markdownOutlet.updateHtmlText(html);
markdownOutlet!.updateHtmlText(html);
});
}
@@ -226,7 +226,7 @@ const hello = 'yes'
document.removeEventListener('mouseup', this.handleMouseUp);
// Trigger resize on monaco editor
const editor = this.shadowRoot.querySelector('dees-workspace-monaco') as DeesWorkspaceMonaco;
const editor = this.shadowRoot!.querySelector('dees-workspace-monaco') as DeesWorkspaceMonaco;
if (editor) {
// Monaco needs to be notified of size changes
window.dispatchEvent(new Event('resize'));

View File

@@ -381,7 +381,7 @@ export class DeesWorkspaceMarkdownoutlet extends DeesElement {
];
// INSTANCE
private outlet: HTMLElement;
private outlet!: HTMLElement;
public render(): TemplateResult {
return html`
@@ -394,13 +394,13 @@ export class DeesWorkspaceMarkdownoutlet extends DeesElement {
public async firstUpdated(_changedProperties: Map<string | number | symbol, unknown>) {
await super.firstUpdated(_changedProperties);
this.outlet = this.shadowRoot.querySelector('.outlet');
this.outlet = this.shadowRoot!.querySelector('.outlet')!;
}
public async updateHtmlText(htmlTextArg: string) {
await this.updateComplete;
if (!this.outlet) {
this.outlet = this.shadowRoot.querySelector('.outlet');
this.outlet = this.shadowRoot!.querySelector('.outlet')!;
}
this.outlet.innerHTML = htmlTextArg;
}

View File

@@ -106,7 +106,7 @@ export class DeesWorkspaceMonaco extends DeesElement {
_changedProperties: Map<string | number | symbol, unknown>
): Promise<void> {
super.firstUpdated(_changedProperties);
const container = this.shadowRoot.getElementById('container');
const container = this.shadowRoot!.getElementById('container')!
const monacoCdnBase = `https://cdn.jsdelivr.net/npm/monaco-editor@${MONACO_VERSION}`;
if (!DeesWorkspaceMonaco.monacoDeferred) {
@@ -174,7 +174,7 @@ export class DeesWorkspaceMonaco extends DeesElement {
).text();
const styleElement = document.createElement('style');
styleElement.textContent = css;
this.shadowRoot.append(styleElement);
this.shadowRoot!.append(styleElement);
// editor is setup let do the rest

View File

@@ -537,15 +537,15 @@ export const zIndexShowcase = () => html`
</p>
`,
menuOptions: [
{ name: 'Cancel', action: async (modal) => modal.destroy() },
{ name: 'Save', action: async (modal) => modal.destroy() }
{ name: 'Cancel', action: async (modal) => modal!.destroy() },
{ name: 'Save', action: async (modal) => modal!.destroy() }
]
});
// Add context menu to modal content
const modalContent = modal.shadowRoot.querySelector('.modal .content');
const modalContent = modal!.shadowRoot!.querySelector('.modal .content');
if (modalContent) {
modalContent.addEventListener('contextmenu', async (e: MouseEvent) => {
(modalContent as HTMLElement).addEventListener('contextmenu', async (e: MouseEvent) => {
DeesContextmenu.openContextMenuWithOptions(e, [
{ name: 'Context menu in modal', iconName: 'check', action: async () => {} },
{ divider: true },
@@ -607,7 +607,7 @@ export const zIndexShowcase = () => html`
></dees-input-dropdown>
`,
menuOptions: [
{ name: 'Close', action: async (modal) => modal.destroy() }
{ name: 'Close', action: async (modal) => modal!.destroy() }
]
});
}}>Show Second Modal</dees-button>
@@ -615,7 +615,7 @@ export const zIndexShowcase = () => html`
`,
menuOptions: [
{ name: 'Close All', action: async (modal) => {
modal.destroy();
modal!.destroy();
// Also show a toast
DeesToast.createAndShow({ message: 'All modals closed!', type: 'info' });
}}
@@ -694,10 +694,10 @@ export const zIndexShowcase = () => html`
</div>
`,
menuOptions: [
{ name: 'Cancel', action: async (modal) => modal.destroy() },
{ name: 'Cancel', action: async (modal) => modal!.destroy() },
{ name: 'Save', action: async (modal) => {
DeesToast.createAndShow({ message: 'Document saved!', type: 'success' });
modal.destroy();
modal!.destroy();
}}
]
});
@@ -735,10 +735,10 @@ export const zIndexShowcase = () => html`
</dees-form>
`,
menuOptions: [
{ name: 'Cancel', action: async (modal) => modal.destroy() },
{ name: 'Cancel', action: async (modal) => modal!.destroy() },
{ name: 'Apply', action: async (modal) => {
DeesToast.createAndShow({ message: 'Tags applied!', type: 'success' });
modal.destroy();
modal!.destroy();
}}
]
});
@@ -766,7 +766,7 @@ export const zIndexShowcase = () => html`
></dees-input-dropdown>
`,
menuOptions: [
{ name: 'Exit Fullscreen', action: async (modal) => modal.destroy() }
{ name: 'Exit Fullscreen', action: async (modal) => modal!.destroy() }
]
});
}}>Open Fullscreen</dees-button>

View File

@@ -228,7 +228,7 @@ body > div[style*="top: -50000px"][style*="width: 50000px"] {
const module = await import(/* @vite-ignore */ url);
this.highlightJsLib = module.default;
return this.highlightJsLib;
return this.highlightJsLib!;
})();
return this.highlightJsLoadingPromise;
@@ -252,7 +252,7 @@ body > div[style*="top: -50000px"][style*="width: 50000px"] {
const module = await import(/* @vite-ignore */ url);
this.apexChartsLib = module.default;
return this.apexChartsLib;
return this.apexChartsLib!;
})();
return this.apexChartsLoadingPromise;

View File

@@ -7,7 +7,7 @@ export const CDN_VERSIONS = {
xtermAddonFit: '0.8.0',
xtermAddonSearch: '0.13.0',
highlightJs: '11.11.1',
apexcharts: '5.10.3',
apexcharts: '5.10.4',
tiptap: '2.27.2',
fontawesome: '7.2.0',
} as const;

View File

@@ -5,7 +5,8 @@
"moduleResolution": "NodeNext",
"esModuleInterop": true,
"verbatimModuleSyntax": true,
"skipLibCheck": false
"skipLibCheck": false,
"types": ["node"]
},
"exclude": [
"dist_*/**/*.d.ts"