@design.estate/dees-catalog 3.28.1 → 3.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,7 +3,7 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@design.estate/dees-catalog',
6
- version: '3.28.1',
6
+ version: '3.29.0',
7
7
  description: 'A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript.'
8
8
  };
9
9
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHNfd2ViLzAwX2NvbW1pdGluZm9fZGF0YS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7R0FFRztBQUNILE1BQU0sQ0FBQyxNQUFNLFVBQVUsR0FBRztJQUN4QixJQUFJLEVBQUUsNkJBQTZCO0lBQ25DLE9BQU8sRUFBRSxRQUFRO0lBQ2pCLFdBQVcsRUFBRSxzSkFBc0o7Q0FDcEssQ0FBQSJ9
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@design.estate/dees-catalog",
3
- "version": "3.28.1",
3
+ "version": "3.29.0",
4
4
  "private": false,
5
5
  "description": "A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript.",
6
6
  "main": "dist_ts_web/index.js",
package/readme.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @design.estate/dees-catalog
2
2
 
3
- A comprehensive web components library built with TypeScript and LitElement, providing **75+ UI components** for building modern web applications with consistent design and behavior. 🚀
3
+ A comprehensive web components library built with TypeScript and LitElement, providing **80+ production-ready UI components** for building modern web applications with consistent design and behavior. 🚀
4
4
 
5
5
  [![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-blue.svg)](https://www.typescriptlang.org/)
6
6
  [![LitElement](https://img.shields.io/badge/LitElement-4.0+-orange.svg)](https://lit.dev/)
@@ -53,13 +53,14 @@ For developers working on this library, please refer to the [UI Components Playb
53
53
  | Category | Components |
54
54
  |----------|------------|
55
55
  | **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) |
56
- | **Forms** | [`DeesForm`](#deesform), [`DeesInputText`](#deesinputtext), [`DeesInputCheckbox`](#deesinputcheckbox), [`DeesInputDropdown`](#deesinputdropdown), [`DeesInputRadiogroup`](#deesinputradiogroup), [`DeesInputFileupload`](#deesinputfileupload), [`DeesInputIban`](#deesinputiban), [`DeesInputPhone`](#deesinputphone), [`DeesInputQuantitySelector`](#deesinputquantityselector), [`DeesInputMultitoggle`](#deesinputmultitoggle), [`DeesInputTags`](#deesinputtags), [`DeesInputTypelist`](#deesinputtypelist), [`DeesInputRichtext`](#deesinputrichtext), [`DeesInputWysiwyg`](#deesinputwysiwyg), [`DeesInputDatepicker`](#deesinputdatepicker), [`DeesInputSearchselect`](#deesinputsearchselect), [`DeesFormSubmit`](#deesformsubmit) |
56
+ | **Forms** | [`DeesForm`](#deesform), [`DeesInputText`](#deesinputtext), [`DeesInputCheckbox`](#deesinputcheckbox), [`DeesInputDropdown`](#deesinputdropdown), [`DeesInputRadiogroup`](#deesinputradiogroup), [`DeesInputFileupload`](#deesinputfileupload), [`DeesInputIban`](#deesinputiban), [`DeesInputPhone`](#deesinputphone), [`DeesInputQuantitySelector`](#deesinputquantityselector), [`DeesInputMultitoggle`](#deesinputmultitoggle), [`DeesInputTags`](#deesinputtags), [`DeesInputTypelist`](#deesinputtypelist), [`DeesInputList`](#deesinputlist), [`DeesInputProfilepicture`](#deesinputprofilepicture), [`DeesInputRichtext`](#deesinputrichtext), [`DeesInputWysiwyg`](#deesinputwysiwyg), [`DeesInputDatepicker`](#deesinputdatepicker), [`DeesInputSearchselect`](#deesinputsearchselect), [`DeesFormSubmit`](#deesformsubmit) |
57
57
  | **Layout** | [`DeesAppui`](#deesappui), [`DeesAppuiMainmenu`](#deesappuimainmenu), [`DeesAppuiSecondarymenu`](#deesappuisecondarymenu), [`DeesAppuiMaincontent`](#deesappuimaincontent), [`DeesAppuiAppbar`](#deesappuiappbar), [`DeesAppuiActivitylog`](#deesappuiactivitylog), [`DeesAppuiProfiledropdown`](#deesappuiprofiledropdown), [`DeesAppuiTabs`](#deesappuitabs), [`DeesMobileNavigation`](#deesmobilenavigation), [`DeesDashboardGrid`](#deesdashboardgrid) |
58
58
  | **Data Display** | [`DeesTable`](#deestable), [`DeesDataviewCodebox`](#deesdataviewcodebox), [`DeesDataviewStatusobject`](#deesdataviewstatusobject), [`DeesPdf`](#deespdf), [`DeesStatsGrid`](#deesstatsgrid), [`DeesPagination`](#deespagination) |
59
59
  | **Visualization** | [`DeesChartArea`](#deeschartarea), [`DeesChartLog`](#deeschartlog) |
60
60
  | **Dialogs & Overlays** | [`DeesModal`](#deesmodal), [`DeesContextmenu`](#deescontextmenu), [`DeesSpeechbubble`](#deesspeechbubble), [`DeesWindowlayer`](#deeswindowlayer) |
61
61
  | **Navigation** | [`DeesStepper`](#deesstepper), [`DeesProgressbar`](#deesprogressbar) |
62
62
  | **Development** | [`DeesEditor`](#deeseditor), [`DeesEditorMarkdown`](#deeseditormarkdown), [`DeesEditorMarkdownoutlet`](#deeseditormarkdownoutlet), [`DeesTerminal`](#deesterminal), [`DeesUpdater`](#deesupdater) |
63
+ | **Theming** | [`DeesTheme`](#deestheme) |
63
64
  | **Auth & Utilities** | [`DeesSimpleAppdash`](#deessimpleappdash), [`DeesSimpleLogin`](#deessimplelogin) |
64
65
  | **Shopping** | [`DeesShoppingProductcard`](#deesshoppingproductcard) |
65
66
 
@@ -482,6 +483,62 @@ Dynamic list input for managing arrays of typed values.
482
483
  ></dees-input-typelist>
483
484
  ```
484
485
 
486
+ #### `DeesInputList`
487
+ Advanced list input with drag-and-drop reordering, inline editing, and validation.
488
+
489
+ ```typescript
490
+ <dees-input-list
491
+ key="items"
492
+ label="List Items"
493
+ placeholder="Add new item..."
494
+ .value=${['Item 1', 'Item 2', 'Item 3']}
495
+ maxItems={10} // Optional: maximum items
496
+ minItems={1} // Optional: minimum items
497
+ allowDuplicates={false} // Optional: allow duplicate values
498
+ sortable={true} // Optional: enable drag-and-drop reordering
499
+ confirmDelete={true} // Optional: confirm before deletion
500
+ @change=${handleListChange}
501
+ ></dees-input-list>
502
+ ```
503
+
504
+ **Key Features:**
505
+ - Add, edit, and remove items inline
506
+ - Drag-and-drop reordering with visual feedback
507
+ - Optional duplicate prevention
508
+ - Min/max item constraints
509
+ - Delete confirmation dialog
510
+ - Full keyboard support
511
+ - Form validation integration
512
+
513
+ #### `DeesInputProfilepicture`
514
+ Profile picture input with cropping, zoom, and image processing.
515
+
516
+ ```typescript
517
+ <dees-input-profilepicture
518
+ key="avatar"
519
+ label="Profile Picture"
520
+ shape="round" // Options: round, square
521
+ size={120} // Display size in pixels
522
+ .value=${imageBase64} // Base64 encoded image or URL
523
+ allowUpload={true} // Enable upload button
524
+ allowDelete={true} // Enable delete button
525
+ maxFileSize={5242880} // Max file size in bytes (5MB)
526
+ .acceptedFormats=${['image/jpeg', 'image/png', 'image/webp']}
527
+ outputSize={800} // Output resolution in pixels
528
+ outputQuality={0.95} // JPEG quality (0-1)
529
+ @change=${handleAvatarChange}
530
+ ></dees-input-profilepicture>
531
+ ```
532
+
533
+ **Key Features:**
534
+ - Interactive cropping modal with zoom and pan
535
+ - Drag-and-drop file upload
536
+ - Round or square output shapes
537
+ - Configurable output size and quality
538
+ - File size and format validation
539
+ - Delete functionality
540
+ - Preview on hover
541
+
485
542
  #### `DeesInputDatepicker`
486
543
  Date and time picker component with calendar interface and manual typing support.
487
544
 
@@ -661,6 +718,7 @@ class MyApp extends DeesElement {
661
718
  - **Hash-based Routing**: Automatic URL synchronization with view navigation
662
719
  - **RxJS Observables**: `viewChanged$` and `viewLifecycle$` for reactive programming
663
720
  - **TypeScript-first**: Typed `IViewActivationContext` passed to views on activation
721
+ - **Activity Log Toggle**: Built-in appbar button to show/hide activity panel with entry count badge
664
722
 
665
723
  **Programmatic APIs include:**
666
724
  - `navigateToView(viewId, params?)` - Navigate between views
@@ -670,6 +728,7 @@ class MyApp extends DeesElement {
670
728
  - `setSecondaryMenu()`, `setSecondaryMenuCollapsed()`, `setSecondaryMenuVisible()` - Control secondary menu
671
729
  - `setContentTabs()`, `setContentTabsVisible()` - Control view-specific UI
672
730
  - `activityLog.add()`, `activityLog.addMany()`, `activityLog.clear()` - Manage activity entries
731
+ - `setActivityLogVisible()`, `toggleActivityLog()`, `getActivityLogVisible()` - Control activity panel
673
732
 
674
733
  **View Visibility Control:**
675
734
  ```typescript
@@ -740,7 +799,7 @@ Main content area with tab management support.
740
799
  ```
741
800
 
742
801
  #### `DeesAppuiAppbar`
743
- Professional application bar component with hierarchical menus, breadcrumb navigation, and user account management.
802
+ Professional application bar component with hierarchical menus, breadcrumb navigation, user account management, and activity log toggle.
744
803
 
745
804
  ```typescript
746
805
  <dees-appui-appbar
@@ -775,6 +834,9 @@ Professional application bar component with hierarchical menus, breadcrumb navig
775
834
  .breadcrumbs=${'Project > src > components'}
776
835
  .showWindowControls=${true}
777
836
  .showSearch=${true}
837
+ .showActivityLogToggle=${true}
838
+ .activityLogCount=${5}
839
+ .activityLogActive=${false}
778
840
  .user=${{
779
841
  name: 'John Doe',
780
842
  avatar: '/path/to/avatar.jpg',
@@ -782,6 +844,7 @@ Professional application bar component with hierarchical menus, breadcrumb navig
782
844
  }}
783
845
  @menu-select=${(e) => handleMenuSelect(e.detail.item)}
784
846
  @breadcrumb-navigate=${(e) => handleBreadcrumbClick(e.detail)}
847
+ @activity-toggle=${() => handleActivityToggle()}
785
848
  ></dees-appui-appbar>
786
849
  ```
787
850
 
@@ -789,9 +852,40 @@ Professional application bar component with hierarchical menus, breadcrumb navig
789
852
  - **Hierarchical Menu System** - Top-level menus with dropdown submenus, icons, and keyboard shortcuts
790
853
  - **Keyboard Navigation** - Full keyboard support (Tab, Arrow keys, Enter, Escape)
791
854
  - **Breadcrumb Navigation** - Customizable breadcrumb trail with click events
792
- - **User Account Section** - Avatar with status indicator
855
+ - **User Account Section** - Avatar with status indicator and profile dropdown
856
+ - **Activity Log Toggle** - Button with badge count to show/hide activity panel
793
857
  - **Accessibility** - Full ARIA support with menubar roles
794
858
 
859
+ #### `DeesAppuiActivitylog`
860
+ Real-time activity log panel for displaying user actions and system events.
861
+
862
+ ```typescript
863
+ <dees-appui-activitylog></dees-appui-activitylog>
864
+
865
+ // Programmatic API
866
+ activityLog.add({
867
+ type: 'update', // Options: login, logout, view, create, update, delete, custom
868
+ user: 'John Doe',
869
+ message: 'Updated project settings',
870
+ iconName: 'lucide:settings' // Optional: custom icon
871
+ });
872
+
873
+ activityLog.addMany(entries); // Add multiple entries
874
+ activityLog.clear(); // Clear all entries
875
+ activityLog.getEntries(); // Get all entries
876
+ activityLog.filter({ user: 'John' }); // Filter by user/type
877
+ activityLog.search('settings'); // Search by message
878
+ ```
879
+
880
+ **Key Features:**
881
+ - Stacked entry layout with icon, user, timestamp, and message
882
+ - Date grouping (Today, Yesterday, etc.)
883
+ - Search and filter functionality
884
+ - Context menu for entry actions
885
+ - Live streaming indicator
886
+ - Animated slide-in/out panel
887
+ - Theme-aware styling
888
+
795
889
  #### `DeesAppuiTabs`
796
890
  Reusable tab component with horizontal/vertical layout support.
797
891
 
@@ -1089,6 +1183,40 @@ Progress indicator component for tracking completion status.
1089
1183
 
1090
1184
  ---
1091
1185
 
1186
+ ### Theming Components
1187
+
1188
+ #### `DeesTheme`
1189
+ Theme provider component that wraps children and provides CSS custom properties for consistent theming.
1190
+
1191
+ ```typescript
1192
+ // Basic usage - wrap your app
1193
+ <dees-theme>
1194
+ <my-app></my-app>
1195
+ </dees-theme>
1196
+
1197
+ // With custom overrides
1198
+ <dees-theme
1199
+ .customColors=${{
1200
+ primary: '#007bff',
1201
+ success: '#28a745'
1202
+ }}
1203
+ .customSpacing=${{
1204
+ lg: '24px',
1205
+ xl: '32px'
1206
+ }}
1207
+ >
1208
+ <my-section></my-section>
1209
+ </dees-theme>
1210
+ ```
1211
+
1212
+ **Key Features:**
1213
+ - Provides CSS custom properties for colors, spacing, radius, shadows, and transitions
1214
+ - Can be nested for section-specific theming
1215
+ - Works with dark/light mode
1216
+ - Overrides cascade to all child components
1217
+
1218
+ ---
1219
+
1092
1220
  ### Development Components
1093
1221
 
1094
1222
  #### `DeesEditor`
@@ -1241,6 +1369,29 @@ interface IMenuGroup {
1241
1369
  collapsed?: boolean;
1242
1370
  iconName?: string;
1243
1371
  }
1372
+
1373
+ // View definition for app navigation
1374
+ interface IViewDefinition {
1375
+ id: string;
1376
+ name: string;
1377
+ iconName?: string;
1378
+ content: string | HTMLElement | (() => TemplateResult);
1379
+ secondaryMenu?: ISecondaryMenuGroup[];
1380
+ contentTabs?: IMenuItem[];
1381
+ route?: string;
1382
+ badge?: string | number;
1383
+ }
1384
+
1385
+ // Activity log entry
1386
+ interface IActivityEntry {
1387
+ id?: string;
1388
+ timestamp?: Date;
1389
+ type: 'login' | 'logout' | 'view' | 'create' | 'update' | 'delete' | 'custom';
1390
+ user: string;
1391
+ message: string;
1392
+ iconName?: string;
1393
+ data?: Record<string, unknown>;
1394
+ }
1244
1395
  ```
1245
1396
 
1246
1397
  ---
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@design.estate/dees-catalog',
6
- version: '3.28.1',
6
+ version: '3.29.0',
7
7
  description: 'A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript.'
8
8
  }
@@ -1,6 +1,6 @@
1
1
  # DeesAppui
2
2
 
3
- A comprehensive application shell component providing a complete UI framework with navigation, menus, activity logging, and view management.
3
+ A comprehensive application shell component providing a complete UI framework with navigation, menus, activity logging, and view management. 🚀
4
4
 
5
5
  ## Quick Start
6
6
 
@@ -35,6 +35,34 @@ class MyApp extends DeesElement {
35
35
  }
36
36
  ```
37
37
 
38
+ ## Architecture Overview
39
+
40
+ The DeesAppui shell consists of several interconnected components:
41
+
42
+ ```
43
+ ┌─────────────────────────────────────────────────────────────────────┐
44
+ │ AppBar (dees-appui-appbar) │
45
+ │ ├── Menus (File, Edit, View...) │
46
+ │ ├── Breadcrumbs │
47
+ │ ├── User Profile + Dropdown │
48
+ │ └── Activity Log Toggle │
49
+ ├─────────────┬───────────────────────────────────┬───────────────────┤
50
+ │ Main Menu │ Content Area │ Activity Log │
51
+ │ (collapsed/ │ ├── Content Tabs │ (slide panel) │
52
+ │ expanded) │ │ (closable, from tables/lists)│ │
53
+ │ │ └── View Container │ │
54
+ │ ┌─────────┐ │ └── Active View │ │
55
+ │ │ 🏠 Home │ ├─────────────────────────────────┐ │ │
56
+ │ │ 📁 Files│ │ Secondary Menu │ │ │
57
+ │ │ ⚙ Settings ├── Collapsible Groups │ │ │
58
+ │ │ │ │ ├── Item 1 │ │ │
59
+ │ └─────────┘ │ ├── Item 2 (with badge) │ │ │
60
+ │ │ └── Item 3 │ │ │
61
+ └─────────────┴─────────────────────────────────┴───────────────────────┘
62
+ ```
63
+
64
+ ---
65
+
38
66
  ## Configuration API
39
67
 
40
68
  ### `configure(config: IAppConfig)`
@@ -155,74 +183,289 @@ appui.removeMainMenuItem('Main', 'tasks');
155
183
 
156
184
  // Selection
157
185
  appui.setMainMenuSelection('dashboard');
158
- appui.setMainMenuCollapsed(true);
186
+
187
+ // Visibility control
188
+ appui.setMainMenuCollapsed(true); // Collapse to icon-only sidebar
189
+ appui.setMainMenuVisible(false); // Hide completely
159
190
 
160
191
  // Badges
161
192
  appui.setMainMenuBadge('inbox', 12);
162
193
  appui.clearMainMenuBadge('inbox');
163
194
  ```
164
195
 
165
- ### Secondary Menu API
196
+ ---
197
+
198
+ ## Secondary Menu API 📋
199
+
200
+ The secondary menu is a contextual sidebar that appears next to the main content area. It supports **collapsible groups** with icons and badges, making it perfect for:
166
201
 
167
- Views can control the secondary (contextual) menu.
202
+ - **Settings pages** (grouped settings categories)
203
+ - **File browsers** (folder trees)
204
+ - **Project navigation** (grouped by category)
205
+ - **Documentation** (chapters/sections)
206
+
207
+ ### Collapsible Groups
208
+
209
+ Groups can be collapsed/expanded by clicking the group header. The state is visually indicated with an icon rotation.
168
210
 
169
211
  ```typescript
170
- // Set menu
212
+ // Set secondary menu with collapsible groups
171
213
  appui.setSecondaryMenu({
172
214
  heading: 'Settings',
173
215
  groups: [
174
216
  {
175
217
  name: 'Account',
218
+ iconName: 'lucide:user', // Group icon
219
+ collapsed: false, // Initial state (default: false)
176
220
  items: [
177
- { key: 'profile', iconName: 'lucide:user', action: () => {} },
178
- { key: 'security', iconName: 'lucide:shield', action: () => {} },
221
+ { key: 'profile', iconName: 'lucide:user', action: () => showProfile() },
222
+ { key: 'security', iconName: 'lucide:shield', badge: '!', badgeVariant: 'warning', action: () => showSecurity() },
223
+ { key: 'billing', iconName: 'lucide:credit-card', action: () => showBilling() }
224
+ ]
225
+ },
226
+ {
227
+ name: 'Preferences',
228
+ iconName: 'lucide:settings',
229
+ collapsed: true, // Start collapsed
230
+ items: [
231
+ { key: 'notifications', iconName: 'lucide:bell', action: () => {} },
232
+ { key: 'appearance', iconName: 'lucide:palette', action: () => {} },
233
+ { key: 'language', iconName: 'lucide:globe', action: () => {} }
179
234
  ]
180
235
  }
181
236
  ]
182
237
  });
238
+ ```
239
+
240
+ ### Secondary Menu Item Properties
241
+
242
+ ```typescript
243
+ interface ISecondaryMenuItem {
244
+ key: string; // Unique identifier
245
+ iconName?: string; // Icon (e.g., 'lucide:user')
246
+ action: () => void; // Click handler
247
+ badge?: string | number; // Badge text/count
248
+ badgeVariant?: 'default' | 'success' | 'warning' | 'error';
249
+ }
183
250
 
184
- // Update group
185
- appui.updateSecondaryMenuGroup('Account', { items: newItems });
251
+ interface ISecondaryMenuGroup {
252
+ name: string; // Group name (shown in header)
253
+ iconName?: string; // Group icon
254
+ collapsed?: boolean; // Initial collapsed state
255
+ items: ISecondaryMenuItem[]; // Items in this group
256
+ }
257
+ ```
258
+
259
+ ### Updating Secondary Menu
260
+
261
+ ```typescript
262
+ // Update a specific group
263
+ appui.updateSecondaryMenuGroup('Account', {
264
+ items: [...newItems]
265
+ });
186
266
 
187
- // Add item
267
+ // Add item to a group
188
268
  appui.addSecondaryMenuItem('Account', {
189
- key: 'notifications',
190
- iconName: 'lucide:bell',
191
- action: () => {}
269
+ key: 'api-keys',
270
+ iconName: 'lucide:key',
271
+ action: () => showApiKeys()
192
272
  });
193
273
 
194
- // Selection
274
+ // Selection (highlights the item)
195
275
  appui.setSecondaryMenuSelection('profile');
196
276
 
277
+ // Visibility control
278
+ appui.setSecondaryMenuCollapsed(true); // Collapse panel
279
+ appui.setSecondaryMenuVisible(false); // Hide completely
280
+
197
281
  // Clear
198
282
  appui.clearSecondaryMenu();
199
283
  ```
200
284
 
201
- ### Content Tabs API
285
+ ### View-Specific Secondary Menus
286
+
287
+ Each view can define its own secondary menu that appears when the view is activated:
288
+
289
+ ```typescript
290
+ // In view definition
291
+ {
292
+ id: 'settings',
293
+ name: 'Settings',
294
+ content: 'my-settings-view',
295
+ secondaryMenu: [
296
+ {
297
+ name: 'General',
298
+ items: [
299
+ { key: 'account', iconName: 'lucide:user', action: () => {} },
300
+ { key: 'security', iconName: 'lucide:shield', action: () => {} }
301
+ ]
302
+ }
303
+ ]
304
+ }
305
+
306
+ // Or set dynamically in view's onActivate hook
307
+ onActivate(context: IViewActivationContext) {
308
+ context.appui.setSecondaryMenu({
309
+ heading: 'Project Files',
310
+ groups: [...]
311
+ });
312
+ }
313
+ ```
314
+
315
+ ---
316
+
317
+ ## Content Tabs API 📑
318
+
319
+ Content tabs appear above the main view content. They're designed for **opening multiple items** from tables, lists, or other data sources—similar to browser tabs or IDE editor tabs.
202
320
 
203
- Control tabs in the main content area.
321
+ ### Common Use Cases
322
+
323
+ - **Table row details** - Click a row to open it as a tab
324
+ - **Document editing** - Open multiple documents
325
+ - **Entity inspection** - View customer, order, product details
326
+ - **Multi-file editing** - Edit multiple configuration files
327
+
328
+ ### Closable Tabs
329
+
330
+ Tabs can be closable, allowing users to open items, work with them, and close when done:
204
331
 
205
332
  ```typescript
206
- // Set tabs
333
+ // Set initial tabs
207
334
  appui.setContentTabs([
208
- { key: 'code', iconName: 'lucide:code', action: () => {} },
209
- { key: 'preview', iconName: 'lucide:eye', action: () => {} }
335
+ { key: 'overview', iconName: 'lucide:home', action: () => showOverview() },
336
+ { key: 'activity', iconName: 'lucide:activity', action: () => showActivity() }
210
337
  ]);
211
338
 
212
- // Add/remove
213
- appui.addContentTab({ key: 'debug', iconName: 'lucide:bug', action: () => {} });
339
+ // Add a closable tab when user clicks a table row
340
+ table.addEventListener('row-click', (e) => {
341
+ const item = e.detail.item;
342
+
343
+ appui.addContentTab({
344
+ key: `item-${item.id}`,
345
+ label: item.name, // Display label
346
+ iconName: 'lucide:file',
347
+ closable: true, // Allow closing
348
+ action: () => showItemDetails(item)
349
+ });
350
+
351
+ // Select the new tab
352
+ appui.selectContentTab(`item-${item.id}`);
353
+ });
354
+
355
+ // Handle tab close
356
+ appui.addEventListener('tab-close', (e) => {
357
+ const tabKey = e.detail.key;
358
+ // Cleanup resources if needed
359
+ console.log(`Tab ${tabKey} closed`);
360
+ });
361
+ ```
362
+
363
+ ### Tab Management
364
+
365
+ ```typescript
366
+ // Add/remove tabs
367
+ appui.addContentTab({
368
+ key: 'debug',
369
+ iconName: 'lucide:bug',
370
+ closable: true,
371
+ action: () => {}
372
+ });
214
373
  appui.removeContentTab('debug');
215
374
 
216
- // Select
375
+ // Select tab
217
376
  appui.selectContentTab('preview');
218
377
 
219
- // Get current
378
+ // Get current tab
220
379
  const current = appui.getSelectedContentTab();
380
+
381
+ // Visibility control
382
+ appui.setContentTabsVisible(false); // Hide tab bar
383
+
384
+ // Auto-hide when only one tab
385
+ appui.setContentTabsAutoHide(true, 1); // Hide when ≤ 1 tab
386
+ ```
387
+
388
+ ### Opening Items from Tables/Lists
389
+
390
+ A common pattern is opening table rows as closable tabs:
391
+
392
+ ```typescript
393
+ @customElement('my-customers-view')
394
+ class MyCustomersView extends DeesElement {
395
+ private appui: DeesAppui;
396
+
397
+ onActivate(context: IViewActivationContext) {
398
+ this.appui = context.appui;
399
+
400
+ // Set base tabs
401
+ this.appui.setContentTabs([
402
+ { key: 'list', label: 'All Customers', iconName: 'lucide:users', action: () => this.showList() }
403
+ ]);
404
+ }
405
+
406
+ render() {
407
+ return html`
408
+ <dees-table
409
+ .data=${this.customers}
410
+ @row-dblclick=${this.openCustomerTab}
411
+ ></dees-table>
412
+ `;
413
+ }
414
+
415
+ openCustomerTab(e: CustomEvent) {
416
+ const customer = e.detail.item;
417
+ const tabKey = `customer-${customer.id}`;
418
+
419
+ // Check if tab already exists
420
+ const existingTab = this.appui.getSelectedContentTab();
421
+ if (existingTab?.key === tabKey) {
422
+ return; // Already viewing this customer
423
+ }
424
+
425
+ // Add new closable tab
426
+ this.appui.addContentTab({
427
+ key: tabKey,
428
+ label: customer.name,
429
+ iconName: 'lucide:user',
430
+ closable: true,
431
+ action: () => this.showCustomerDetails(customer)
432
+ });
433
+
434
+ this.appui.selectContentTab(tabKey);
435
+ }
436
+
437
+ showCustomerDetails(customer: Customer) {
438
+ // Render customer details
439
+ this.currentView = html`<customer-details .customer=${customer}></customer-details>`;
440
+ }
441
+
442
+ showList() {
443
+ this.currentView = html`<dees-table ...></dees-table>`;
444
+ }
445
+ }
221
446
  ```
222
447
 
223
- ### Activity Log API
448
+ ---
449
+
450
+ ## Activity Log API 📊
451
+
452
+ The activity log is a slide-out panel on the right side showing user actions and system events.
224
453
 
225
- Add activity entries to the right-side activity log.
454
+ ### Activity Log Toggle
455
+
456
+ The appbar includes a toggle button with a badge showing the entry count:
457
+
458
+ ```typescript
459
+ // Control visibility
460
+ appui.setActivityLogVisible(true); // Show panel
461
+ appui.toggleActivityLog(); // Toggle state
462
+ const isVisible = appui.getActivityLogVisible();
463
+
464
+ // The toggle button automatically shows entry count
465
+ // Add entries and the badge updates automatically
466
+ ```
467
+
468
+ ### Adding Entries
226
469
 
227
470
  ```typescript
228
471
  // Add single entry
@@ -234,19 +477,35 @@ appui.activityLog.add({
234
477
  data: { invoiceId: '123' } // Optional metadata
235
478
  });
236
479
 
237
- // Add multiple
480
+ // Add multiple entries (e.g., from backend)
238
481
  appui.activityLog.addMany([...entries]);
239
482
 
240
- // Clear
483
+ // Clear all entries
241
484
  appui.activityLog.clear();
242
485
 
243
- // Query
486
+ // Query entries
244
487
  const entries = appui.activityLog.getEntries();
245
488
  const filtered = appui.activityLog.filter({ user: 'John', type: 'create' });
246
489
  const searched = appui.activityLog.search('invoice');
247
490
  ```
248
491
 
249
- ### Navigation API
492
+ ### Activity Entry Types
493
+
494
+ Each type has a default icon that can be overridden:
495
+
496
+ | Type | Default Icon | Use Case |
497
+ |------|--------------|----------|
498
+ | `login` | `lucide:log-in` | User sign-in |
499
+ | `logout` | `lucide:log-out` | User sign-out |
500
+ | `view` | `lucide:eye` | Page/item viewed |
501
+ | `create` | `lucide:plus` | New item created |
502
+ | `update` | `lucide:pencil` | Item modified |
503
+ | `delete` | `lucide:trash` | Item deleted |
504
+ | `custom` | `lucide:activity` | Custom events |
505
+
506
+ ---
507
+
508
+ ## Navigation API
250
509
 
251
510
  Navigate between views programmatically.
252
511
 
@@ -512,6 +771,7 @@ class CrmSettings extends DeesElement {
512
771
  groups: [
513
772
  {
514
773
  name: 'Account',
774
+ iconName: 'lucide:user',
515
775
  items: [
516
776
  { key: 'profile', iconName: 'lucide:user', action: () => this.showSection('profile') },
517
777
  { key: 'security', iconName: 'lucide:shield', action: () => this.showSection('security') }
@@ -519,6 +779,8 @@ class CrmSettings extends DeesElement {
519
779
  },
520
780
  {
521
781
  name: 'Preferences',
782
+ iconName: 'lucide:settings',
783
+ collapsed: true,
522
784
  items: [
523
785
  { key: 'notifications', iconName: 'lucide:bell', action: () => this.showSection('notifications') }
524
786
  ]
@@ -557,4 +819,5 @@ All interfaces are exported from `@design.estate/dees-catalog`:
557
819
  - `IAppBarMenuItem` - App bar menu item
558
820
  - `IMainMenuConfig` - Main menu configuration
559
821
  - `ISecondaryMenuGroup` - Secondary menu group
560
- - `ITab` - Tab definition
822
+ - `ISecondaryMenuItem` - Secondary menu item
823
+ - `IMenuItem` - Tab/menu item definition