npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@design.estate/dees-catalog

v7.0.0

Published

A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript.

Readme

@design.estate/dees-catalog

A comprehensive web components library built with TypeScript and LitElement, providing 90+ production-ready UI components for building modern web applications with consistent design and behavior. 🚀

TypeScript LitElement

Issue Reporting and Security

For reporting bugs, issues, or security vulnerabilities, please visit community.foss.global/. This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a code.foss.global/ account to submit Pull Requests directly.

✨ Features

  • 🎨 Consistent Design System — Beautiful, cohesive components following modern UI/UX principles
  • 🌙 Dark/Light Theme Support — All components automatically adapt to your theme
  • ⌨️ Keyboard Accessible — Full keyboard navigation and ARIA support
  • 📱 Responsive — Mobile-first design that works across all screen sizes
  • 🔧 TypeScript-First — Fully typed APIs with excellent IDE support
  • 🧩 Modular — Use only what you need, tree-shakeable architecture
  • 🏗️ Full App Shelldees-appui provides a complete application framework with menus, routing, activity log, and bottom bar
  • 🎬 Media Components — Rich thumbnail previews for PDFs, images, audio, video, notes, and folders
  • 💻 IDE Workspace — Full workspace component with Monaco editor, file tree, terminal, and diff viewer

📦 Installation

npm install @design.estate/dees-catalog
# or
pnpm add @design.estate/dees-catalog

🚀 Quick Start

import { html, DeesElement, customElement } from '@design.estate/dees-element';
import '@design.estate/dees-catalog';

@customElement('my-app')
class MyApp extends DeesElement {
  render() {
    return html`
      <dees-button type="accent" @click=${() => alert('Hello!')}>
        Click me!
      </dees-button>
    `;
  }
}

📖 Development Guide

For developers working on this library, please refer to the UI Components Playbook for comprehensive patterns, best practices, and architectural guidelines.

📚 Components Overview

| Category | Components | |----------|------------| | Core UI | DeesButton, DeesButtonExit, DeesButtonGroup, DeesBadge, DeesChips, DeesHeading, DeesHint, DeesIcon, DeesLabel, DeesPanel, DeesSearchbar, DeesSpinner, DeesToast, DeesWindowcontrols, DeesActionbar | | Forms | DeesForm, DeesInputText, DeesInputCheckbox, DeesInputDropdown, DeesInputRadiogroup, DeesInputFileupload, DeesInputIban, DeesInputPhone, DeesInputQuantitySelector, DeesInputMultitoggle, DeesInputToggle, DeesInputTags, DeesInputTypelist, DeesInputList, DeesInputProfilepicture, DeesInputRichtext, DeesInputWysiwyg, DeesInputDatepicker, DeesInputSearchselect, DeesInputCode, DeesFormSubmit | | App Shell (Layout) | DeesMosaic, DeesAppui, DeesAppuiMainmenu, DeesAppuiSecondarymenu, DeesAppuiMaincontent, DeesAppuiAppbar, DeesAppuiActivitylog, DeesAppuiBottombar, DeesAppuiProfiledropdown, DeesAppuiTabs, DeesMobileNavigation, DeesDashboardGrid | | Data Display | DeesTable, DeesDataviewCodebox, DeesDataviewStatusobject, DeesStatsGrid, DeesPagination, DeesStorageBrowser | | Media & Thumbnails | DeesThumbnailPdf, DeesThumbnailImage, DeesThumbnailAudio, DeesThumbnailVideo, DeesThumbnailNote, DeesThumbnailFolder, DeesPreview, DeesPdfViewer, DeesImageViewer, DeesAudioViewer, DeesVideoViewer | | Visualization | DeesChartArea, DeesChartBar, DeesChartDonut, DeesChartGauge, DeesChartRadar, DeesChartLog | | Dialogs & Overlays | DeesModal, DeesContextmenu, DeesSpeechbubble, DeesWindowlayer | | Navigation | DeesStepper, DeesProgressbar | | Workspace / IDE | DeesWorkspace, DeesWorkspaceMonaco, DeesWorkspaceDiffEditor, DeesWorkspaceFiletree, DeesWorkspaceTerminal, DeesWorkspaceTerminalPreview, DeesWorkspaceMarkdown, DeesWorkspaceMarkdownoutlet, DeesWorkspaceBottombar | | Agentic Chat | DeesHarnessChat, DeesHarnessMessageList, DeesHarnessMessage, DeesHarnessReasoning, DeesHarnessToolCard, DeesHarnessOverflowText, DeesHarnessContentBlocks, DeesHarnessPermissionCard, DeesHarnessQuestionCard, DeesHarnessComposer, DeesHarnessStatus, DeesHarnessTodos, DeesHarnessUsage, DeesHarnessSessionSidebar, DeesHarnessSessionList | | Theming | DeesTheme, DeesUpdater | | Pre-built Templates | DeesSimpleAppdash, DeesSimpleLogin | | Shopping | DeesShoppingProductcard |


🎯 Detailed Component Documentation

Core UI Components

DeesButton

A versatile button component supporting multiple styles and states.

// Basic usage
const button = document.createElement('dees-button');
button.text = 'Click me';

// With options
<dees-button
  type="accent"       // Options: default, accent, destructive, outline, secondary, ghost, link (legacy: normal, highlighted, discreet, big)
  size="sm"           // Options: default, sm, lg, icon (square)
  shape="pill"        // Options: squircle (default rounded rect), pill (capsule for standalone actions)
  status="pending"    // Options: normal, pending, success, error
  disabled={false}    // Optional: disables the button
  full-width          // Optional: stretches the button face to the host width
  @click=${handleClick}
>Click me</dees-button>

The button is keyboard operable: its face carries role="button" and tabindex, Enter and Space activate it (dispatching a real click, so both @click and @clicked fire), a disabled button leaves the tab order, and keyboard focus draws a :focus-visible ring.

DeesBadge

Display status indicators or counts with customizable styles.

<dees-badge
  type="success"  // Options: default, primary, success, warning, error
  text="New"      // Text to display
  rounded        // Optional: applies rounded corners
></dees-badge>

DeesChips

Interactive chips/tags with selection capabilities.

<dees-chips
  selectionMode="multiple"  // Options: none, single, multiple
  chipsAreRemovable        // Optional: allows removing chips
  .selectableChips=${[
    { key: 'tag1', value: 'Important' },
    { key: 'tag2', value: 'Urgent' }
  ]}
  @selection-change=${handleSelection}
></dees-chips>

DeesIcon

Display Lucide icons. Legacy fa: and iconFA inputs are unsupported and log an error.

Applications that only need the icon component can use the granular entry point without registering or bundling the complete catalog:

import '@design.estate/dees-catalog/icon';
// Lucide icons — use 'lucide:' prefix
<dees-icon
  icon="lucide:check"   // Lucide icon with lucide: prefix
  iconSize="24"         // Size in pixels
  color="#22c55e"       // Optional: custom color
></dees-icon>

// Unsupported legacy inputs log an error and render no icon:
// <dees-icon icon="fa:check"></dees-icon>
// <dees-icon iconFA="check"></dees-icon>

dees-icon follows normal CSS text-color inheritance, including translucent rgba(...) colors, and composites the complete Lucide shape as one layer. Use native CSS color and opacity; consumers do not need icon-specific opacity variables or stroke-color workarounds.

DeesLabel

Text label component with optional required indicator and info tooltip. Used internally by all input components.

<dees-label
  .label=${'Email Address'}      // Label text
  .required=${true}              // Optional: shows red asterisk
  .infoText=${'We will never share your email'}  // Optional: shows hover info icon with tooltip
></dees-label>

DeesSpinner

Loading indicator with customizable appearance.

<dees-spinner
  .size=${20}                    // Optional: diameter in pixels (default 20)
  .status=${'normal'}            // Optional: 'normal' | 'pending' | 'success' | 'error'
  .bnw=${true}                   // Optional: black-and-white treatment
></dees-spinner>

The arc colour follows the --dees-spinner-color custom property, falling back to --dees-color-text-primary. Set it on an ancestor when the spinner sits on a coloured surface — an accent button face, for example — so the arc matches that surface's foreground:

dees-button {
  --dees-spinner-color: var(--dees-color-on-accent);
}

DeesToast

Notification toast messages with various styles, positions, and auto-dismiss functionality.

// Programmatic usage
DeesToast.show({
  message: 'Operation successful',
  type: 'success',      // Options: info, success, warning, error
  duration: 3000,       // Time in milliseconds before auto-dismiss
  position: 'top-right' // Options: top-right, top-left, bottom-right, bottom-left, top-center, bottom-center
});

// Convenience methods
DeesToast.info('Information message');
DeesToast.success('Success message');
DeesToast.warning('Warning message');
DeesToast.error('Error message');

// Advanced control
const toast = await DeesToast.show({
  message: 'Processing...',
  type: 'info',
  duration: 0  // No auto-dismiss
});

// Later dismiss programmatically
toast.dismiss();

Key Features:

  • Multiple toast types with distinct icons and colors
  • 6 position options for flexible placement
  • Auto-dismiss with visual progress indicator
  • Manual dismiss by clicking
  • Smooth animations and transitions
  • Automatic stacking of multiple toasts
  • Theme-aware styling
  • Programmatic control

DeesButtonExit

Exit/close button component with consistent styling.

<dees-button-exit
  @click=${handleClose}
></dees-button-exit>

DeesButtonGroup

Container for grouping related buttons together.

<dees-button-group label="Actions" direction="horizontal">
  <dees-button type="accent" @clicked=${handleSave}>Save</dees-button>
  <dees-button @clicked=${handleCancel}>Cancel</dees-button>
</dees-button-group>

DeesHeading

Consistent heading component with level and styling options.

<dees-heading
  level={1}           // 1-6 for H1-H6
  text="Page Title"
  .subheading=${'Optional subtitle'}
  centered           // Optional: center alignment
></dees-heading>

DeesHint

Hint/tooltip component for providing contextual help.

<dees-hint
  text="This field is required"
  type="info"        // Options: info, warning, error, success
  position="top"     // Options: top, bottom, left, right
></dees-hint>

DeesPanel

Container component for grouping related content with optional title and actions.

<dees-panel
  .title=${'Panel Title'}
  .subtitle=${'Optional subtitle'}
  collapsible        // Optional: allow collapse/expand
  collapsed={false}  // Initial collapsed state
  .actions=${[
    { icon: 'settings', action: handleSettings }
  ]}
>
  <!-- Panel content -->
</dees-panel>

DeesSearchbar

Search input component with suggestions and search handling.

<dees-searchbar
  placeholder="Search..."
  .suggestions=${['item1', 'item2', 'item3']}
  showClearButton    // Show clear button when has value
  @search=${handleSearch}
  @suggestion-select=${handleSuggestionSelect}
></dees-searchbar>

DeesWindowcontrols

Window control buttons (minimize, maximize, close) for desktop-like applications.

<dees-windowcontrols
  .controls=${['minimize', 'maximize', 'close']}
  @minimize=${handleMinimize}
  @maximize=${handleMaximize}
  @close=${handleClose}
></dees-windowcontrols>

DeesActionbar

Floating action bar for contextual actions.

<dees-actionbar
  .actions=${[
    { icon: 'lucide:save', label: 'Save', action: () => handleSave() },
    { icon: 'lucide:trash', label: 'Delete', action: () => handleDelete() }
  ]}
></dees-actionbar>

Form Components

DeesForm

Container component for form elements with built-in validation and data handling.

<dees-form
  @formData=${(e) => handleFormData(e.detail)}  // Emitted when form is submitted
  @formValidation=${(e) => handleValidation(e.detail)}  // Emitted during validation
>
  <dees-input-text required></dees-input-text>
  <dees-form-submit>Submit</dees-form-submit>
</dees-form>

DeesInputText

Text input field with validation, info tooltips, description text, and context menu (Cut/Copy/Paste/Select All).

<dees-input-text
  key="email"           // Unique identifier for form data
  label="Email"         // Input label
  value="[email protected]"  // Initial value
  required             // Makes the field required
  disabled            // Disables the input
  .autocomplete=${'username'}   // Autofill hint; unset renders no autocomplete attribute
  .infoText=${'Hover icon tooltip text'}    // Shows ⓘ icon on label with hover tooltip
  .description=${'Permanent help text below the input'}  // Small text below the input
  .validationFunction=${(value) => {        // Auto-validates on every keystroke
    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    if (emailRegex.test(value)) {
      return { valid: true, message: 'Email is valid' };
    }
    return { valid: false, message: 'Please enter a valid email' };
  }}
></dees-input-text>

💡 All input components share these common properties from DeesInputBase: key, label, required, disabled, infoText, description, layoutMode, labelPosition.

DeesInputCheckbox

Checkbox input component for boolean values.

<dees-input-checkbox
  key="terms"
  label="Accept Terms"
  checked             // Initial checked state
  required
  @change=${handleChange}
></dees-input-checkbox>

DeesInputToggle

Toggle switch component for boolean on/off states.

<dees-input-toggle
  key="darkMode"
  label="Enable Dark Mode"
  .value=${true}
  @change=${handleToggle}
></dees-input-toggle>

DeesInputDropdown

Dropdown selection component with search and filtering capabilities.

<dees-input-dropdown
  key="country"
  label="Select Country"
  .options=${[
    { key: 'us', option: 'United States' },
    { key: 'uk', option: 'United Kingdom' }
  ]}
  searchable          // Enables search functionality
  multiple           // Allows multiple selections
></dees-input-dropdown>

DeesInputFileupload

File upload component with drag-and-drop support.

<dees-input-fileupload
  key="documents"
  label="Upload Files"
  multiple            // Allow multiple file selection
  accept=".pdf,.doc"  // Accepted file types
  maxSize="5MB"      // Maximum file size
  @upload=${handleUpload}
></dees-input-fileupload>

DeesInputIban

Specialized input for IBAN (International Bank Account Number) with validation.

<dees-input-iban
  key="bankAccount"
  label="IBAN"
  country="DE"        // Default country format
  required
  @validate=${handleIbanValidation}
></dees-input-iban>

DeesInputPhone

Phone number input with country code selection and formatting.

<dees-input-phone
  key="phone"
  label="Phone Number"
  defaultCountry="US"  // Default country code
  required
  @validate=${handlePhoneValidation}
></dees-input-phone>

DeesInputQuantitySelector

Numeric input with increment/decrement controls.

<dees-input-quantity-selector
  key="quantity"
  label="Quantity"
  min="0"             // Minimum value
  max="100"           // Maximum value
  step="1"            // Increment/decrement step
  value="1"           // Initial value
></dees-input-quantity-selector>

DeesInputMultitoggle

Multi-state toggle button group.

<dees-input-multitoggle
  key="status"
  label="Status"
  .options=${[
    { key: 'active', label: 'Active' },
    { key: 'pending', label: 'Pending' },
    { key: 'inactive', label: 'Inactive' }
  ]}
  value="active"      // Initial selected value
></dees-input-multitoggle>

DeesInputRadiogroup

Radio button group for single-choice selections with internal state management.

<dees-input-radiogroup
  key="plan"
  label="Select Plan"
  .options=${['Free', 'Pro', 'Enterprise']}
  selectedOption="Pro"
  required
  @change=${handlePlanChange}
></dees-input-radiogroup>

// With custom option objects
<dees-input-radiogroup
  key="priority"
  label="Priority Level"
  .options=${[
    { key: 'low', label: 'Low Priority' },
    { key: 'medium', label: 'Medium Priority' },
    { key: 'high', label: 'High Priority' }
  ]}
  selectedOption="medium"
></dees-input-radiogroup>

DeesInputTags

Tag input component for managing lists of tags with auto-complete and validation.

<dees-input-tags
  key="skills"
  label="Skills"
  .value=${['JavaScript', 'TypeScript', 'CSS']}
  placeholder="Add a skill..."
  .suggestions=${[
    'JavaScript', 'TypeScript', 'Python', 'Go', 'Rust',
    'React', 'Vue', 'Angular', 'Node.js', 'Docker'
  ]}
  maxTags={10}  // Optional: limit number of tags
  required
  @change=${handleTagsChange}
></dees-input-tags>

Key Features:

  • Add tags by pressing Enter or typing comma/semicolon
  • Remove tags with click or backspace
  • Auto-complete suggestions with keyboard navigation
  • Maximum tag limit support
  • Full theme support
  • Form validation integration

DeesInputTypelist

Dynamic list input for managing arrays of typed values.

<dees-input-typelist
  key="features"
  label="Product Features"
  placeholder="Add a feature..."
  .value=${['Feature 1', 'Feature 2']}
  @change=${handleFeaturesChange}
></dees-input-typelist>

DeesInputList

Advanced list input with drag-and-drop reordering, inline editing, and validation.

<dees-input-list
  key="items"
  label="List Items"
  placeholder="Add new item..."
  .value=${['Item 1', 'Item 2', 'Item 3']}
  maxItems={10}            // Optional: maximum items
  minItems={1}             // Optional: minimum items
  allowDuplicates={false}  // Optional: allow duplicate values
  sortable={true}          // Optional: enable drag-and-drop reordering
  confirmDelete={true}     // Optional: confirm before deletion
  @change=${handleListChange}
></dees-input-list>

Key Features:

  • Add, edit, and remove items inline
  • Drag-and-drop reordering with visual feedback
  • Optional duplicate prevention
  • Min/max item constraints
  • Delete confirmation dialog
  • Full keyboard support
  • Form validation integration

DeesInputProfilepicture

Profile picture input with cropping, zoom, and image processing.

<dees-input-profilepicture
  key="avatar"
  label="Profile Picture"
  shape="round"           // Options: round, square
  size={120}              // Display size in pixels
  .value=${imageBase64}   // Base64 encoded image or URL
  allowUpload={true}      // Enable upload button
  allowDelete={true}      // Enable delete button
  maxFileSize={5242880}   // Max file size in bytes (5MB)
  .acceptedFormats=${['image/jpeg', 'image/png', 'image/webp']}
  outputSize={800}        // Output resolution in pixels
  outputQuality={0.95}    // JPEG quality (0-1)
  @change=${handleAvatarChange}
></dees-input-profilepicture>

Key Features:

  • Interactive cropping modal with zoom and pan
  • Drag-and-drop file upload
  • Round or square output shapes
  • Configurable output size and quality
  • File size and format validation
  • Delete functionality
  • Preview on hover

DeesInputDatepicker

Date and time picker component with calendar interface and manual typing support.

<dees-input-datepicker
  key="eventDate"
  label="Event Date"
  placeholder="YYYY-MM-DD"
  value="2025-01-15T14:30:00Z"  // ISO string format
  dateFormat="YYYY-MM-DD"        // Display format (default: YYYY-MM-DD)
  enableTime={true}              // Enable time selection
  timeFormat="24h"               // Options: 24h, 12h
  minuteIncrement={15}           // Time step in minutes
  minDate="2025-01-01"          // Minimum selectable date
  maxDate="2025-12-31"          // Maximum selectable date
  .disabledDates=${[            // Array of disabled dates
    '2025-01-10',
    '2025-01-11'
  ]}
  weekStartsOn={1}              // 0 = Sunday, 1 = Monday
  required
  @change=${handleDateChange}
></dees-input-datepicker>

Key Features:

  • Interactive calendar popup
  • Manual date typing with multiple formats
  • Optional time selection
  • Configurable date format
  • Min/max date constraints
  • Disable specific dates
  • Keyboard navigation
  • Today button
  • Clear functionality
  • 12/24 hour time formats
  • Theme-aware styling
  • Live parsing and validation

Manual Input Formats:

// Date formats supported
"2023-12-20"     // ISO format (YYYY-MM-DD)
"20.12.2023"     // European format (DD.MM.YYYY)
"12/20/2023"     // US format (MM/DD/YYYY)

// Date with time (add space and time after any date format)
"2023-12-20 14:30"
"20.12.2023 9:45"
"12/20/2023 16:00"

DeesInputSearchselect

Search-enabled dropdown selection component.

<dees-input-searchselect
  key="category"
  label="Select Category"
  placeholder="Search categories..."
  .options=${[
    { key: 'tech', label: 'Technology' },
    { key: 'health', label: 'Healthcare' },
    { key: 'finance', label: 'Finance' }
  ]}
  required
  @change=${handleCategoryChange}
></dees-input-searchselect>

DeesInputRichtext

Rich text editor with formatting toolbar powered by TipTap.

<dees-input-richtext
  key="content"
  label="Article Content"
  .value=${htmlContent}
  placeholder="Start writing..."
  minHeight={300}      // Minimum editor height
  showWordCount={true} // Show word/character count
  @change=${handleContentChange}
></dees-input-richtext>

Key Features:

  • Full formatting toolbar (bold, italic, underline, strike, etc.)
  • Heading levels (H1-H6)
  • Lists (bullet, ordered)
  • Links with URL editing
  • Code blocks and inline code
  • Blockquotes
  • Horizontal rules
  • Undo/redo support
  • Word and character count
  • HTML output

DeesInputWysiwyg

Advanced block-based editor with slash commands and rich content blocks.

<dees-input-wysiwyg
  key="document"
  label="Document Editor"
  .value=${documentContent}
  outputFormat="html"  // Options: html, markdown, json
  @change=${handleDocumentChange}
></dees-input-wysiwyg>

Key Features:

  • Slash commands for quick formatting
  • Block-based editing (paragraphs, headings, lists, etc.)
  • Drag and drop block reordering
  • Multiple output formats
  • Keyboard shortcuts
  • Collaborative editing ready
  • Extensible block types

DeesInputCode

Code input component for editing source code with syntax highlighting.

<dees-input-code
  key="snippet"
  label="Code Snippet"
  .value=${codeString}
  language="typescript"
  @change=${handleCodeChange}
></dees-input-code>

DeesFormSubmit

Submit button component specifically designed for DeesForm.

<dees-form-submit
  disabled            // Optional: disable submit button
  status="normal"     // Options: normal, pending, success, error
  full-width          // Optional: stretches the button face to the host width
>Submit Form</dees-form-submit>

Note that DeesFormSubmit.focus() submits rather than focuses — DeesForm calls it to implement "Enter in the last field submits". Keyboard focus reaches the submit through the inner DeesButton face.


App Shell (Layout) Components

DeesMosaic

Sway-like tiling workspace: a controlled split-tree layout where tiles resize against each other, drag by a slim tilebar (which also closes them), and dock onto any edge of another tile with a live drop preview. Content projects through named slots, so hosts keep light-DOM ownership — Electron <webview> content survives every layout change because slot reassignment never moves the light-DOM node.

import { createMosaicLeaf, mosaicInsert, type IMosaicLayout } from '@design.estate/dees-catalog';

let layout: IMosaicLayout = mosaicInsert({ root: null }, null, 'right', createMosaicLeaf('editor', 'l-editor'));
layout = mosaicInsert(layout, 'l-editor', 'right', createMosaicLeaf('chat', 'l-chat'));
layout = mosaicInsert(layout, null, 'bottom', createMosaicLeaf('terminal', 'l-term'));
<dees-mosaic
  .layout=${layout}
  .surfaces=${{ editor: { title: 'Editor', icon: 'lucide:Code' }, chat: { title: 'AI Chat' }, terminal: { title: 'Terminal' } }}
  @mosaic-layout-change=${(e) => { layout = e.detail.layout; /* persist */ }}
>
  <my-editor slot="tile-l-editor"></my-editor>
  <my-chat slot="tile-l-chat"></my-chat>
  <my-terminal slot="tile-l-term"></my-terminal>
  <div slot="empty">Workspace is empty.</div>
</dees-mosaic>

The component is controlled: apply e.detail.layout back (and persist it) on every mosaic-layout-change (reason: 'resize' | 'drop' | 'close' | 'equalize'). Other events: cancelable mosaic-tile-close, mosaic-tile-focus, throttled mosaic-resizing (re-measure embedded content), mosaic-drag-state. Methods: getLeafRects() (viewport rect per leaf content area), equalize(splitId?), focusTile(id). Pure helpers (mosaicInsert/mosaicRemove/mosaicMove/mosaicResize/mosaicEqualize/mosaicNormalize/mosaicLeaves) are exported for host-side layout logic. Splitters are keyboard-accessible (role="separator", arrow keys resize, double-click equalizes); Escape cancels drags.

DeesAppui 🏗️

A comprehensive application shell component providing a complete UI framework with navigation, menus, activity logging, bottom bar, and view management.

Full API Documentation: See ts_web/elements/00group-appui/dees-appui/readme.md for complete documentation including all programmatic APIs, view lifecycle hooks, and TypeScript interfaces.

Quick Start:

import { html, DeesElement, customElement } from '@design.estate/dees-element';
import { DeesAppui } from '@design.estate/dees-catalog';

@customElement('my-app')
class MyApp extends DeesElement {
  private appui: DeesAppui;

  async firstUpdated() {
    this.appui = this.shadowRoot.querySelector('dees-appui');

    this.appui.configure({
      branding: { logoIcon: 'lucide:box', logoText: 'My App' },
      views: [
        { id: 'dashboard', name: 'Dashboard', iconName: 'lucide:home', content: 'my-dashboard' },
        { id: 'settings', name: 'Settings', iconName: 'lucide:settings', content: 'my-settings' },
      ],
      mainMenu: {
        sections: [{ name: 'Main', views: ['dashboard', 'settings'] }]
      },
      defaultView: 'dashboard',
      bottomBar: {
        visible: true,
        widgets: [
          { id: 'status', iconName: 'lucide:activity', label: 'Online', status: 'success' }
        ]
      }
    });
  }

  render() {
    return html`<dees-appui></dees-appui>`;
  }
}

Architecture Overview:

┌─────────────────────────────────────────────────────────────────────┐
│  AppBar (dees-appui-appbar)                                         │
│  ├── Menus (File, Edit, View...)                                    │
│  ├── Breadcrumbs                                                    │
│  ├── User Profile + Dropdown                                        │
│  └── Activity Log Toggle                                            │
├─────────────┬───────────────────────────────────┬───────────────────┤
│ Main Menu   │  Content Area                     │  Activity Log     │
│ (collapsed/ │  ├── Content Tabs                 │  (slide panel)    │
│  expanded)  │  │   (closable, from tables/lists)│                   │
│             │  └── View Container               │                   │
│ ┌─────────┐ │      └── Active View              │                   │
│ │ 🏠 Home │ ├─────────────────────────────────┐ │                   │
│ │ 📁 Files│ │ Secondary Menu                  │ │                   │
│ │ ⚙ Set.. │ │  ├── Collapsible Groups         │ │                   │
│ │         │ │  │   ├── Tabs / Actions          │ │                   │
│ └─────────┘ │  │   ├── Filters / Links         │ │                   │
│             │  │   └── Dividers / Headers       │ │                   │
├─────────────┴──┴───────────────────────────────┴───────────────────┤
│  Bottom Bar (dees-appui-bottombar) — 24px status bar                │
│  ├── Status widgets (left/right)                                    │
│  └── Action buttons (left/right)                                    │
└─────────────────────────────────────────────────────────────────────┘

Configuration (IAppConfig):

interface IAppConfig {
  branding?: { logoIcon?: string; logoText?: string };
  appBar?: IAppBarConfig;
  views: IViewDefinition[];
  mainMenu?: IMainMenuConfig;
  defaultView?: string;
  activityLog?: IActivityLogConfig;
  bottomBar?: IBottomBarConfig;
  onViewChange?: (viewId: string, view: IViewDefinition) => void;
  onSearch?: (query: string) => void;
}

Key Features:

  • 🔧 Configure API — Single configure() method for complete app setup
  • 📄 View Management — Automatic view caching, lazy loading, and lifecycle hooks (onActivate, onDeactivate, canDeactivate)
  • 🧭 Hash-based Routing — Automatic URL synchronization with view navigation and parameterized routes
  • 📊 Activity Log — Slide-out panel with stacked entries, date grouping, search, and filtering
  • 📌 Bottom Status Bar — Configurable widgets and actions with status colors and loading states
  • 🎯 RxJS ObservablesviewChanged$ and viewLifecycle$ for reactive programming
  • 🏷️ TypeScript-first — Typed IViewActivationContext passed to views on activation

Programmatic APIs:

| Area | Methods | |------|---------| | Navigation | navigateToView(viewId, params?), getCurrentView(), getViewRegistry() | | App Bar | setAppBarMenus(), updateAppBarMenu(), setBreadcrumbs(), setUser(), setProfileMenuItems(), setSearchVisible(), onSearch(), setWindowControlsVisible() | | Main Menu | setMainMenu(), updateMainMenuGroup(), addMainMenuItem(), removeMainMenuItem(), setMainMenuSelection(), setMainMenuCollapsed(), setMainMenuVisible(), setMainMenuBadge(), clearMainMenuBadge() | | Secondary Menu | setSecondaryMenu(), updateSecondaryMenuGroup(), addSecondaryMenuItem(), setSecondaryMenuSelection(), setSecondaryMenuCollapsed(), setSecondaryMenuVisible(), clearSecondaryMenu() | | Content Tabs | setContentTabs(), addContentTab(), removeContentTab(), selectContentTab(), getSelectedContentTab(), setContentTabsVisible(), setContentTabsAutoHide() | | Activity Log | activityLog.add(), activityLog.addMany(), activityLog.clear(), activityLog.getEntries(), activityLog.filter(), activityLog.search(), setActivityLogVisible(), toggleActivityLog(), getActivityLogVisible() | | Bottom Bar | bottomBar.addWidget(), bottomBar.updateWidget(), bottomBar.removeWidget(), bottomBar.getWidget(), bottomBar.clearWidgets(), bottomBar.addAction(), bottomBar.removeAction(), bottomBar.clearActions(), setBottomBarVisible(), getBottomBarVisible() | | Observables | viewChanged$, viewLifecycle$ |

View Lifecycle Hooks:

import { DeesElement, customElement } from '@design.estate/dees-element';
import type { IViewActivationContext, IViewLifecycle } from '@design.estate/dees-catalog';

@customElement('my-settings-view')
class MySettingsView extends DeesElement implements IViewLifecycle {
  // Called when view becomes visible
  async onActivate(context: IViewActivationContext) {
    const { appui, viewId, params } = context;

    // Set view-specific secondary menu
    appui.setSecondaryMenu({
      heading: 'Settings',
      groups: [{ name: 'Options', items: [...] }]
    });

    // Control visibility of other shell parts
    appui.setContentTabsVisible(false);
    appui.setSecondaryMenuVisible(true);
  }

  // Called when navigating away
  onDeactivate() { /* cleanup */ }

  // Return false or a message string to block navigation
  canDeactivate(): boolean | string {
    if (this.hasUnsavedChanges) return 'You have unsaved changes. Leave anyway?';
    return true;
  }
}

Secondary Menu Item Types:

The secondary menu supports 8 distinct item types for building rich contextual sidebars:

| Type | Description | |------|-------------| | Tab (default) | Selectable item that stays highlighted | | Action | Executes on click without staying selected (blue styling) | | Filter | Checkbox toggle for filtering | | MultiFilter | Collapsible multi-select filter box | | Divider | Visual separator line | | Header | Non-interactive section label | | Link | Opens an external URL | | Danger Action | Red-styled action with optional confirmation |

DeesAppuiMainmenu

Main navigation menu component for application-wide navigation. Supports collapsed (icon-only) mode.

<dees-appui-mainmenu
  .menuGroups=${[
    {
      name: 'Main',
      items: [
        { key: 'dashboard', iconName: 'lucide:home', action: () => navigate('dashboard') },
        { key: 'settings', iconName: 'lucide:settings', action: () => navigate('settings') }
      ]
    }
  ]}
  collapsed           // Optional: show collapsed icon-only version
></dees-appui-mainmenu>

DeesAppuiSecondarymenu

Secondary navigation component for sub-section selection with collapsible groups, badges, and 8 item types.

<dees-appui-secondarymenu
  .heading=${'Projects'}
  .groups=${[
    {
      name: 'Active',
      iconName: 'lucide:folder',
      items: [
        { key: 'Frontend App', iconName: 'lucide:code', action: () => select('frontend'), badge: 3, badgeVariant: 'warning' },
        { key: 'API Server', iconName: 'lucide:server', action: () => select('api') }
      ]
    }
  ]}
  @item-select=${handleSectionChange}
></dees-appui-secondarymenu>

DeesAppuiMaincontent

Main content area with tab management support.

<dees-appui-maincontent
  .tabs=${[
    { key: 'Overview', iconName: 'lucide:home', action: () => selectTab('overview') },
    { key: 'Details', iconName: 'lucide:info', action: () => selectTab('details') }
  ]}
  @tab-select=${handleTabChange}
>
  <!-- Content goes here -->
</dees-appui-maincontent>

DeesAppuiAppbar

Professional application bar component with hierarchical menus, breadcrumb navigation, user account management, and activity log toggle.

<dees-appui-appbar
  .menuItems=${[
    {
      name: 'File',
      action: async () => {},
      submenu: [
        { name: 'New File', shortcut: 'Cmd+N', iconName: 'file-plus', action: async () => handleNewFile() },
        { name: 'Open...', shortcut: 'Cmd+O', iconName: 'folder-open', action: async () => handleOpen() },
        { divider: true },
        { name: 'Save', shortcut: 'Cmd+S', iconName: 'save', action: async () => handleSave(), disabled: true }
      ]
    }
  ]}
  .breadcrumbs=${'Project > src > components'}
  .showWindowControls=${true}
  .showSearch=${true}
  .showActivityLogToggle=${true}
  .activityLogCount=${5}
  .activityLogActive=${false}
  .user=${{
    name: 'John Doe',
    avatar: '/path/to/avatar.jpg',
    status: 'online'  // Options: 'online' | 'offline' | 'busy' | 'away'
  }}
  @menu-select=${(e) => handleMenuSelect(e.detail.item)}
  @breadcrumb-navigate=${(e) => handleBreadcrumbClick(e.detail)}
  @activity-toggle=${() => handleActivityToggle()}
></dees-appui-appbar>

Key Features:

  • Hierarchical Menu System — Top-level menus with dropdown submenus, icons, and keyboard shortcuts
  • Keyboard Navigation — Full keyboard support (Tab, Arrow keys, Enter, Escape)
  • Breadcrumb Navigation — Customizable breadcrumb trail with click events
  • User Account Section — Avatar with status indicator and profile dropdown
  • Activity Log Toggle — Button with badge count to show/hide activity panel
  • Accessibility — Full ARIA support with menubar roles

DeesAppuiActivitylog

Real-time activity log panel for displaying user actions and system events.

<dees-appui-activitylog></dees-appui-activitylog>

// Programmatic API
activityLog.add({
  type: 'update',        // Options: login, logout, view, create, update, delete, custom
  user: 'John Doe',
  message: 'Updated project settings',
  iconName: 'lucide:settings'  // Optional: custom icon
});

activityLog.addMany(entries);  // Add multiple entries
activityLog.clear();           // Clear all entries
activityLog.getEntries();      // Get all entries
activityLog.filter({ user: 'John' });  // Filter by user/type
activityLog.search('settings');        // Search by message

Key Features:

  • Stacked entry layout with icon, user, timestamp, and message
  • Date grouping (Today, Yesterday, etc.)
  • Search and filter functionality
  • Context menu for entry actions
  • Live streaming indicator
  • Animated slide-in/out panel
  • Theme-aware styling

DeesAppuiBottombar

A 24px fixed-height status bar at the bottom of the application shell. Supports status widgets and action buttons positioned left or right.

// Configure via DeesAppui
appui.configure({
  bottomBar: {
    visible: true,
    widgets: [
      {
        id: 'status',
        iconName: 'lucide:activity',
        label: 'System Online',
        status: 'success',       // 'idle' | 'active' | 'success' | 'warning' | 'error'
        tooltip: 'All systems operational',
        onClick: () => console.log('Status clicked'),
      },
      {
        id: 'version',
        iconName: 'lucide:gitBranch',
        label: 'v1.2.3',
        position: 'right',
      }
    ],
    actions: [
      {
        id: 'terminal',
        iconName: 'lucide:terminal',
        tooltip: 'Open Terminal',
        position: 'right',
        onClick: () => console.log('Terminal clicked'),
      }
    ]
  }
});

// Programmatic updates
appui.bottomBar.addWidget({ id: 'build', iconName: 'lucide:hammer', label: 'Building...', loading: true, status: 'active' });
appui.bottomBar.updateWidget('build', { label: 'Build complete', loading: false, status: 'success' });
appui.bottomBar.removeWidget('build');

appui.bottomBar.addAction({ id: 'refresh', iconName: 'lucide:refreshCw', onClick: () => location.reload() });
appui.bottomBar.removeAction('refresh');

appui.setBottomBarVisible(false);

Key Features:

  • Configurable status widgets with icons, labels, and colored status indicators
  • Loading spinner state for widgets
  • Contextual actions with icon buttons
  • Left/right positioning for both widgets and actions
  • Tooltips on hover
  • Context menu support per widget

DeesAppuiTabs

Reusable tab component with horizontal/vertical layout support.

<dees-appui-tabs
  .tabs=${[
    { key: 'Home', iconName: 'lucide:home', action: () => console.log('Home') },
    { key: 'Settings', iconName: 'lucide:settings', action: () => console.log('Settings') }
  ]}
  tabStyle="horizontal"  // Options: horizontal, vertical
  showTabIndicator={true}
  @tab-select=${handleTabSelect}
></dees-appui-tabs>

Data Display Components

DeesTable

Advanced table component with sorting, filtering, and action support.

<dees-table
  .data=${tableData}
  .displayFunction=${(item) => ({
    name: item.name,
    date: item.date,
    amount: item.amount,
    description: item.description
  })}
  .dataActions=${[
    {
      name: 'Edit',
      icon: 'edit',
      action: (item) => handleEdit(item)
    },
    {
      name: 'Delete',
      icon: 'trash',
      action: (item) => handleDelete(item)
    }
  ]}
  heading1="Transactions"
  heading2="Recent Activity"
  searchable           // Enable search functionality
  dataName="transaction"  // Name for single data item
  @selection-change=${handleSelectionChange}
></dees-table>

Advanced Features:

  • Schema-first columns or displayFunction rendering
  • Sorting via header clicks with aria-sort + sortChange
  • Global search with Lucene-like syntax; modes: table, data, server
  • Per-column quick filters row; showColumnFilters and column.filterable=false
  • Selection: none | single | multi, with select-all and selectionChange
  • Sticky header + internal scroll (stickyHeader, --table-max-height)
  • Rich actions: header/in-row/contextmenu/footer/doubleClick; pinned Actions column
  • Editable cells via editableFields
  • Drag & drop files onto rows

DeesDataviewCodebox

Code display component with syntax highlighting and line numbers.

<dees-dataview-codebox
  progLang="typescript"  // Programming language for syntax highlighting
  .codeToDisplay=${`
    import { html } from '@design.estate/dees-element';

    export const myComponent = () => {
      return html\`<div>Hello World</div>\`;
    };
  `}
></dees-dataview-codebox>

Diff mode — set codeBefore (compared against codeToDisplay as the after state) or a pre-computed unifiedDiff patch; diffView selects 'inline' or 'split' (side-by-side) and can force diff mode on its own:

<dees-dataview-codebox
  progLang="typescript"
  filename="config.ts"
  diffView="split"
  .codeBefore=${previousSource}
  .codeToDisplay=${newSource}
></dees-dataview-codebox>

Diff rendering includes word-level intraline change highlighting, unchanged-context folding with expandable "N unchanged lines" rows, +added −removed stats in the footer, and a "Copy Unified Diff" context-menu action. The app bar switches between inline and split layouts and emits the bubbling, composed diff-view-change event with IDiffViewChangeDetail ({ diffView: TDiffView }). The exported TDiffView type is 'inline' | 'split'. Split mode keeps a fixed center divider and gives each side an independent horizontal scroll position while the containing surface owns their shared vertical movement. Set showDiffLineNumbers to false when snippet inputs do not carry trustworthy source positions. The copy button yields the after-state text. The dependency-free engine (computeLineDiff, parseUnifiedDiff, foldContextRows, buildSplitRows, diffStats, toUnifiedDiff) is exported for programmatic use.

DeesDataviewStatusobject

Status display component for complex objects with nested status indicators.

<dees-dataview-statusobject
  .statusObject=${{
    id: '1',
    name: 'System Status',
    combinedStatus: 'partly_ok',
    combinedStatusText: 'Partially OK',
    details: [
      { name: 'Database', value: 'Connected', status: 'ok', statusText: 'OK' },
      { name: 'API Service', value: 'Degraded', status: 'partly_ok', statusText: 'Partially OK' }
    ]
  }}
></dees-dataview-statusobject>

DeesStatsGrid

A responsive grid component for displaying statistical data with various visualization types.

<dees-statsgrid
  .tiles=${[
    {
      id: 'revenue',
      title: 'Total Revenue',
      value: 125420,
      unit: '$',
      type: 'number',
      icon: 'lucide:dollarSign',
      description: '+12.5% from last month',
      color: '#22c55e'
    },
    {
      id: 'cpu',
      title: 'CPU Usage',
      value: 73,
      type: 'gauge',
      icon: 'lucide:cpu',
      gaugeOptions: {
        min: 0, max: 100,
        thresholds: [
          { value: 0, color: '#22c55e' },
          { value: 60, color: '#f59e0b' },
          { value: 80, color: '#ef4444' }
        ]
      }
    },
    {
      id: 'requests',
      title: 'API Requests',
      value: '1.2k',
      unit: '/min',
      type: 'trend',
      icon: 'lucide:server',
      trendData: [45, 52, 38, 65, 72, 68, 75, 82, 79, 85, 88, 92]
    },
    {
      id: 'cores',
      title: 'CPU Cores',
      value: 0,
      type: 'cpuCores',
      icon: 'lucide:cpu',
      columnSpan: 2,
      coresData: [
        { id: 0, usage: 45, label: '0' },
        { id: 1, usage: 72, label: '1' },
        { id: 2, usage: 30, label: '2' },
        { id: 3, usage: 88, label: '3' }
      ]
    }
  ]}
  .minTileWidth=${250}
  .gap=${16}
></dees-statsgrid>

Tile Types: number, gauge, percentage, trend, text, multiPercentage, cpuCores

DeesPagination

Pagination component for navigating through large datasets.

<dees-pagination
  totalItems={500}
  itemsPerPage={20}
  currentPage={1}
  maxVisiblePages={7}
  @page-change=${handlePageChange}
></dees-pagination>

Media & Thumbnail Components 🎬

A rich collection of thumbnail components for displaying media files in grids. All thumbnails share a consistent base class (DeesThumbnailBase) with lazy loading via IntersectionObserver, hover interactions, click events, and three size variants (small, default, large). DeesThumbnailPdf also supplies PDF-specific context-menu actions.

Thumbnail metadata and labels share one fixed bottom information bar.

DeesThumbnailPdf

PDF document thumbnail with a locally rendered page preview.

<dees-thumbnail-pdf
  .pdfUrl=${'/documents/report.pdf'}
  label="Annual Report"
  .clickable=${true}
  @tile-click=${handleClick}
></dees-thumbnail-pdf>

Key Features:

  • Renders first page as canvas preview
  • Hover to scrub through pages (mouse X position maps to page number)
  • Shows page count, file size, and hover page indicator
  • Detects A4/Letter vs non-standard aspect ratios
  • Bundles the PDF.js worker locally and releases it when the URL changes or the component disconnects

Public properties include pdfUrl, currentPreviewPage, pageCount, rendered, fileSize, clickable, loading, error, size, and label. Loading starts within the thumbnail observer's 200px viewport preload margin. URL replacement, failed loads, and disconnection all release the current PDF document and worker.

DeesThumbnailImage

Image thumbnail with lazy loading and dimension display.

<dees-thumbnail-image
  src="/photos/landscape.jpg"
  alt="Mountain landscape"
  label="landscape.jpg"
  clickable
  @tile-click=${handleClick}
></dees-thumbnail-image>

Key Features:

  • Lazy loads image on scroll into view
  • Shows image dimensions after loading (e.g. "1920 × 1080")
  • Checkerboard background for transparent images

DeesThumbnailAudio

Audio file tile with waveform visualization.

<dees-thumbnail-audio
  src="/music/track.mp3"
  title="Summer Vibes"
  artist="DJ Example"
  clickable
  @tile-click=${handleClick}
></dees-thumbnail-audio>

Key Features:

  • Generates waveform visualization from audio data
  • Shows duration badge (e.g. "3:42")
  • Displays title and artist metadata
  • Play overlay on hover

DeesThumbnailVideo

Video tile with thumbnail capture and hover preview.

<dees-thumbnail-video
  src="/videos/intro.mp4"
  poster="/thumbs/intro.jpg"
  label="Introduction"
  clickable
  @tile-click=${handleClick}
></dees-thumbnail-video>

Key Features:

  • Auto-captures first frame as thumbnail (or uses provided poster)
  • Plays video preview on hover
  • Shows duration badge
  • Play button overlay

DeesThumbnailNote

Plain-text note thumbnail with a monospace preview.

<dees-thumbnail-note
  title="config.ts"
  language="TypeScript"
  .content=${codeString}
  clickable
  @tile-click=${handleClick}
></dees-thumbnail-note>

Key Features:

  • Monospace plain-text preview
  • Optional language metadata in the bottom information bar
  • Scrollable content on hover (mouse X position controls scroll)
  • Gradient fade at bottom

DeesThumbnailFolder

Folder tile with 2×2 content preview grid.

<dees-thumbnail-folder
  name="Project Assets"
  .items=${[
    { type: 'image', name: 'logo.png', thumbnailSrc: '/thumbs/logo.png' },
    { type: 'pdf', name: 'spec.pdf' },
    { type: 'audio', name: 'jingle.mp3' },
    { type: 'video', name: 'demo.mp4' },
  ]}
  clickable
  @tile-click=${handleClick}
></dees-thumbnail-folder>

Key Features:

  • 2×2 preview grid showing first 4 items (thumbnails or type icons)
  • Item count badge (e.g. "12 items")
  • Folder icon header with name
  • Supports: pdf, image, audio, video, note, folder, unknown types

DeesPreview

Unified preview component that selects the appropriate media viewer or renderer based on content.

DeesPdfViewer

Full PDF viewer with page navigation, zoom, fit modes, selectable text, downloads, printing, and an optional thumbnail sidebar. PDF.js and its module worker are bundled locally; the component owns and releases each worker as documents are replaced or the viewer disconnects.

<dees-pdf-viewer
  .pdfUrl=${'/documents/report.pdf'}
  .initialPage=${1}
  .initialZoom=${'page-fit'}
  .showSidebar=${true}
></dees-pdf-viewer>

Public properties include pdfUrl, initialPage, initialZoom, showToolbar, showSidebar, sidebarPosition, currentPage, totalPages, currentZoom, loading, and pdfFileSize. URL replacement, failed loads, and disconnection cancel active work, remove observers and listeners, and release the current PDF document and worker.

PdfManager

Use PdfManager when loading a PDF outside the supplied components. Always release the returned document. An abort signal cancels an in-flight load and triggers bounded worker cleanup.

When migrating from 6.x, pass the PDFDocumentProxy returned by loadDocument() to releaseDocument() instead of passing the source URL.

PdfManager.initialize() is retained as an asynchronous no-op for existing callers; static PDF.js imports require no initialization step.

import { PdfManager } from '@design.estate/dees-catalog';

const abortController = new AbortController();
const pdfDocument = await PdfManager.loadDocument(pdfUrl, abortController.signal);

try {
  const firstPage = await pdfDocument.getPage(1);
  // Render or inspect the page.
  firstPage.cleanup();
} finally {
  await PdfManager.releaseDocument(pdfDocument);
}

DeesImageViewer

Full-screen image viewer with zoom and pan.

DeesAudioViewer

Audio playback component with waveform and controls.

DeesVideoViewer

Video playback component with standard controls.


Visualization Components

DeesChartArea

Area chart component built on Lightweight Charts for time-series data. Enable rangeSelectionEnabled to let the user drag across the plot. The composed, bubbling range-change event carries { from, to } as Unix epoch milliseconds. Apply that range back through selectedRange to keep the selection visible; set it to null to clear the overlay.

<dees-chart-area
  label="System Usage"
  .rangeSelectionEnabled=${true}
  .selectedRange=${selectedRange}
  .series=${[
    {
      name: 'CPU',
      data: [
        { x: '2025-01-15T03:00:00', y: 25 },
        { x: '2025-01-15T07:00:00', y: 30 },
        { x: '2025-01-15T11:00:00', y: 20 }
      ]
    }
  ]}
  @range-change=${(event: CustomEvent<{ from: number; to: number }>) => {
    selectedRange = event.detail;
  }}
></dees-chart-area>

DeesChartLog

Specialized chart component for visualizing log data and events.

<dees-chart-log
  label="System Events"
  .data=${[
    { timestamp: '2025-01-15T03:00:00', event: 'Server Start', type: 'info' },
    { timestamp: '2025-01-15T03:15:00', event: 'Error Detected', type: 'error' }
  ]}
  .filters=${['info', 'warning', 'error']}
  @event-click=${handleEventClick}
></dees-chart-log>

Dialogs & Overlays Components

DeesModal

Modal dialog component with customizable content and actions.

// Programmatic usage
DeesModal.createAndShow({
  heading: 'Confirm Action',
  content: html`
    <dees-form>
      <dees-input-text .label=${'Enter reason'}></dees-input-text>
    </dees-form>
  `,
  menuOptions: [
    { name: 'Cancel', action: async (modal) => { modal.destroy(); return null; } },
    { name: 'Confirm', action: async (modal) => { /* handle */ modal.destroy(); return null; } }
  ]
});

DeesContextmenu

Context menu component for right-click actions with nested submenu support.

// Programmatic usage
DeesContextmenu.openContextMenuWithOptions(mouseEvent, [
  {
    name: 'Edit',
    iconName: 'lucide:edit',
    action: async () => handleEdit()
  },
  { divider: true },
  {
    name: 'More Options',
    iconName: 'lucide:moreHorizontal',
    submenu: [
      { name: 'Duplicate', iconName: 'lucide:copy', action: async () => handleDuplicate() },
      { name: 'Archive', iconName: 'lucide:archive', action: async () => handleArchive() },
    ]
  },
  {
    name: 'Delete',
    iconName: 'lucide:trash2',
    action: async () => handleDelete()
  }
]);

// Component-based (implement getContextMenuItems on any element)
class MyComponent extends DeesElement {
  getContextMenuItems() {
    return [
      { name: 'View Details', iconName: 'lucide:eye', action: async () => { ... } },
      { name: 'Edit', iconName: 'lucide:edit', action: async () => { ... } },
    ];
  }
}

DeesSpeechbubble

Tooltip-style speech bubble component for contextual information.

// Programmatic usage
const bubble = await DeesSpeechbubble.createAndShow(
  referenceElement,
  'Helpful information about this feature'
);

DeesWindowlayer

Base overlay component used by modal dialogs and other overlay components.

const layer = await DeesWindowLayer.createAndShow({
  blur: true,
});

Navigation Components

DeesStepper

Multi-step navigation component for guided user flows, including optional auto-advancing progress steps that can render dees-progressbar status output between form steps.

<dees-stepper
  .steps=${[
    {
      title: 'Account Setup',
      content: html`<dees-form>...</dees-form>`,
      menuOptions: [{ name: 'Continue', action: async (stepper) => stepper?.goNext() }]
    },
    {
      title: 'Provision Workspace',
      content: html`<p>Preparing your environment...</p>`,
      progressStep: {
        label: 'Workspace setup',
        indeterminate: true,
        statusRows: 4,
        terminalLines: ['Allocating workspace']
      },
      validationFunc: async (stepper, _element, signal) => {
        stepper.updateProgressStep({ percentage: 35, statusText: 'Installing dependencies...' });
        stepper.appendProgressStepLine('Installing dependencies');
        if (signal?.aborted) return;
        stepper.updateProgressStep({ percentage: 100, indeterminate: false, statusText: 'Workspace ready.' });
      }
    }
  ]}
></dees-stepper>

DeesProgressbar

Progress indicator component for tracking completion status, with optional fixed-height status text or terminal-style recent activity output.

<dees-progressbar
  .percentage=${75}
  label="Uploading"
  statusText="Uploading thumbnails to edge cache..."
  .statusRows=${2}
></dees-progressbar>

<dees-progressbar
  label="Installing dependencies"
  .indeterminate=${true}
  .statusRows=${4}
  .terminalLines=${[
    'Resolving workspace packages',
    'Downloading tarballs',
    'Linking local binaries'
  ]}
></dees-progressbar>

Theming Components

DeesTheme

Theme provider component that wraps children and provides CSS custom properties for consistent theming.

// Basic usage — wrap your app
<dees-theme>
  <my-app></my-app>
</dees-theme>

// With custom overrides
<dees-theme
  .customColors=${{
    primary: '#007bff',
    success: '#28a745'
  }}
  .customSpacing=${{
    lg: '24px',
    xl: '32px'
  }}
>
  <my-section></my-section>
</dees-theme>

Key Features:

  • Provides CSS custom properties for colors, spacing, radius, shadows, and transitions
  • Can be nested for section-specific theming
  • Works with dark/light mode
  • Overrides cascade to all child components

DeesUpdater

Updater controller that opens a non-cancelable dees-stepper flow with a progress step and a ready step.

const updater = await DeesUpdater.createAndShow({
  currentVersion: '3.79.0',
  updatedVersion: '3.80.0',
  moreInfoUrl: 'https://code.foss.global/design.estate/dees-catalog',
  changelogUrl: 'https://code.foss.global/design.estate/dees-catalog/-/blob/main/changelog.md',
  successAction: 'reload',
  successDelayMs: 10000,
});

updater.updateProgress({
  percentage: 35,
  statusText: 'Downloading signed bundle...',
  terminalLines: ['Checking release manifest', 'Downloading signed bundle']
});

updater.appendProgressLine('Verifying checksum');
updater.updateProgress({ percentage: 72, statusText: 'Verifying checksum...' });

await updater.markUpdateReady();

After markUpdateReady(), the updater switches to a second countdown step with a determinate progress bar and runs the configured success action when the timer reaches zero.


Workspace / IDE Components 💻

A full-featured IDE workspace component suite for building browser-based code editors, terminal interfaces, and documentation viewers.

DeesWorkspace

Top-level workspace shell that composes editor, file tree, terminal, and bottom bar into an IDE-like layout.

<dees-workspace></dees-workspace>

DeesWorkspaceMonaco

Monaco Editor integration for code editing with full IntelliSense, syntax highlighting, and language support.

<dees-workspace-monaco
  .value=${code}
  .language=${'typescript'}
  @change=${handleCodeChange}
></dees-workspace-monaco>

DeesWorkspaceDiffEditor

Side-by-side diff editor powered by Monaco for comparing file versions.

<dees-workspace-diff-editor
  .originalValue=${originalCode}
  .modifiedValue=${modifiedCode}
  .language=${'typescript'}
></dees-workspace-diff-editor>

DeesWorkspaceFiletree

File tree navigation component with expand/collapse, file icons, and selection.

<dees-workspace-filetree
  .files=${fileTreeData}
  @file-select=${handleFileSelect}
></dees-workspace-filetree>

DeesWorkspaceTerminal

Terminal emulator component powered by xterm.js.

<dees-workspace-terminal></dees-workspace-terminal>

DeesWorkspaceTerminalPreview

Terminal with integrated preview pane for output visualization.

DeesWorkspaceMarkdown

Markdown editor with live preview.

DeesWorkspaceMarkdownoutlet

Read-only markdown renderer for documentation display.

DeesWorkspaceBottombar

IDE-style bottom status bar for the workspace.


Agentic Chat Components 🤖

The 00group-harness family renders what an agent harness produces — streaming messages, reasoning, tool calls, MCP content, permission prompts — behind one normalized data contract (IHarnessMessage, IHarnessToolCall, IHarnessPermissionRequest, IHarnessSessionMeta, IHarnessStatus). Consumers adapt their wire format to these interfaces and feed the components; all events are harness-* CustomEvents (bubbles + composed).

DeesHarnessChat

The assembled chat: optional toolbar (heading, usage chip, host-supplied actions, and session-details control), streaming message list with inline permission cards, transcript status line, and docked composer.

const chat = document.querySelector('dees-harness-chat');
chat.messages = adaptedMessages;          // IHarnessMessage[]
chat.permissions = pendingPermissions;    // IHarnessPermissionRequest[]
chat.status = { type: 'busy', message: 'Responding…' };
chat.account = 'connection-a';
chat.accountOptions = [
  { label: 'Personal · [email protected]', value: 'connection-a' },
  { label: 'Team · [email protected]', value: 'connection-b' },
];
chat.modelOptions = ['gpt-5.5', 'o4-mini'];
chat.effortOptions = ['high', 'medium', 'low'];
chat.markdownWhileStreaming = false; // optional: plain streams, one final parse at message end
chat.toolbarActions = [
  {
    id: 'refresh',
    label: 'Refresh conversation',
    iconName: 'lucide:RefreshCw',
    tooltip: 'Refresh conversation',
    action: () => refreshConversation(),
  },
];
const commandSuggestions = [
  { label: 'Explain code', value: 'Explain the selected code' },
  { label: 'Review diff', value: 'Review the current diff', description: 'Focus on bugs and regressions.' },
];
chat.suggestions = commandSuggestions;

chat.addEventListener('harness-input', (event) => {
  const value = event.detail.value;
  chat.suggestions = value.startsWith('/')
    ? commandSuggestions.filter((suggestion) => suggestion.label.toLowerCase().includes(value.slice(1).toLowerCase()))
    : [];
});

chat.addEventListener('harness-send', (event) => {
  const { text, attachments, account, model, reasoningEffort } = event.detail;
});
chat.addEventListener('harness-permission-response', (event) => {
  const { requestId, response, remember } = event.detail; // 'once' | 'always' | 'reject'
});

// streaming fast path — mutates the same message object, re-renders only that element
chat.applyDelta({ type: 'text', messageId: 'm1', delta: 'chunk' });
chat.applyDelta({ type: 'message-end', messageId: 'm1', usage: { totalTokens: 1200 } });

// one-level child-session streaming uses the parent tool-message id
chat.applyDelta({
  type: 'text',
  parentMessageId: 'task-message-1',
  messageId: 'child-message-1',
  delta: 'child chunk',
});

// authoritative same-object corrections use IDs
chat.messages.find((message) => message.id === 'm1')!.text = 'corrected text';
chat.refreshMessages(['m1']);

// structural mutations omit IDs; an empty ID list is a no-op
chat.messages.push({ id: 'm2', role: 'assistant', text: 'next message', createdAt: Date.now() });
chat.refreshMessages();
chat.refreshMessages([]);

Key props: messages, permissions, questions, status, transcriptKey, hasEarlierMessages/loadingEarlier, usage, todos/todosAuthoritative/showTodosPanel, sessionMetrics, scratchpad/scratchpadBusy/scratchpadError, sessionIntelligenceEnabled/intelligenceExchanges/intelligenceBusy/intelligenceError/intelligenceAvailabilityStatus/intelligenceUnavailableReason/intelligenceHeading, showSessionSidebar, heading, subheading, toolbarActions, showToolbar, busy, queuedCount, steeringEnabled, disabled, suggestions, account/accountOptions, model/modelOptions, reasoningEffort/effortOptions, mode/modeOptions, markdownWhileStreaming, toolRegistry. toolbarActions accepts IHarnessChatToolbarAction[]; each action has id, human-readable label, iconName, action, and optional tooltip/disabled, and renders immediately before the session-details toggle. disabled: true makes only that toolbar action inert and prevents its callback without changing the chat-level disabled state. `markdownWhile