@design.estate/dees-wcctools 3.1.2 โ†’ 3.3.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@design.estate/dees-wcctools",
3
- "version": "3.1.2",
3
+ "version": "3.3.0",
4
4
  "private": false,
5
5
  "description": "A set of web component tools for creating element catalogues, enabling the structured development and documentation of custom elements and pages.",
6
6
  "exports": {
package/readme.hints.md CHANGED
@@ -1,5 +1,67 @@
1
1
  # Project Hints and Findings
2
2
 
3
+ ## Section-based Configuration API (2025-12-27)
4
+
5
+ ### Overview
6
+ Refactored `setupWccTools` to accept a section-based configuration object instead of separate elements/pages arguments. This allows multiple custom sections with filtering, sorting, and collapsible headers.
7
+
8
+ ### New API
9
+ ```typescript
10
+ import * as deesWccTools from '@design.estate/dees-wcctools';
11
+
12
+ deesWccTools.setupWccTools({
13
+ sections: [
14
+ {
15
+ name: 'Pages',
16
+ type: 'pages',
17
+ items: pages,
18
+ },
19
+ {
20
+ name: 'Elements',
21
+ type: 'elements',
22
+ items: elements,
23
+ filter: (name, item) => !name.startsWith('internal-'),
24
+ sort: ([a], [b]) => a.localeCompare(b),
25
+ },
26
+ {
27
+ name: 'Views',
28
+ type: 'elements',
29
+ items: elements,
30
+ filter: (name, item) => name.startsWith('view-'),
31
+ icon: 'web',
32
+ collapsed: true, // Start collapsed
33
+ },
34
+ ],
35
+ });
36
+ ```
37
+
38
+ ### Section Properties
39
+ - `name`: Display name for the section header
40
+ - `type`: `'elements'` (shows demos) or `'pages'` (renders directly)
41
+ - `items`: Record of items (element classes or page factories)
42
+ - `filter`: Optional `(name, item) => boolean` to filter items
43
+ - `sort`: Optional `([name, item], [name, item]) => number` for ordering
44
+ - `icon`: Optional Material icon name for section header
45
+ - `collapsed`: Optional boolean to start section collapsed
46
+
47
+ ### Backwards Compatibility
48
+ Legacy format is still supported:
49
+ ```typescript
50
+ deesWccTools.setupWccTools(elements, pages); // Still works
51
+ ```
52
+
53
+ ### URL Routing
54
+ Changed from `/wcctools-route/:itemType/:itemName/...` to `/wcctools-route/:sectionName/:itemName/...`
55
+ Section names are URL-encoded. Legacy routes (`element`/`page` as section name) still work for backwards compatibility.
56
+
57
+ ### Files Changed
58
+ - `ts_web/wcctools.interfaces.ts` - New types: `IWccSection`, `IWccConfig`
59
+ - `ts_web/index.ts` - Updated `setupWccTools` with backwards compat detection
60
+ - `ts_web/elements/wcc-dashboard.ts` - Uses sections, updated routing
61
+ - `ts_web/elements/wcc-sidebar.ts` - Dynamic section rendering
62
+
63
+ ---
64
+
3
65
  ## UI Redesign with Shadcn-like Styles (2025-06-27)
4
66
 
5
67
  ### Changes Made
package/readme.md CHANGED
@@ -6,12 +6,13 @@
6
6
 
7
7
  `@design.estate/dees-wcctools` provides a comprehensive development environment for web components, featuring:
8
8
 
9
- - ๐ŸŽจ **Interactive Component Catalogue** โ€” Live preview with sidebar navigation
9
+ - ๐ŸŽจ **Interactive Component Catalogue** โ€” Live preview with customizable sidebar sections
10
10
  - ๐Ÿ”ง **Real-time Property Editing** โ€” Modify component props on the fly with auto-detected editors
11
11
  - ๐ŸŒ“ **Theme Switching** โ€” Test light/dark modes instantly
12
12
  - ๐Ÿ“ฑ **Responsive Viewport Testing** โ€” Phone, phablet, tablet, and desktop views
13
13
  - ๐ŸŽฌ **Screen Recording** โ€” Record component demos with audio support and video trimming
14
14
  - ๐Ÿงช **Advanced Demo Tools** โ€” Post-render hooks for interactive testing
15
+ - ๐Ÿ“‚ **Section-based Organization** โ€” Group components into custom sections with filtering and sorting
15
16
  - ๐Ÿš€ **Zero-config Setup** โ€” TypeScript and Lit support out of the box
16
17
 
17
18
  ## Issue Reporting and Security
@@ -57,29 +58,22 @@ export class MyButton extends DeesElement {
57
58
  padding: 8px 16px;
58
59
  border-radius: 4px;
59
60
  border: none;
60
- font-size: 14px;
61
61
  cursor: pointer;
62
- transition: all 0.3s;
63
62
  }
64
63
  button.primary {
65
- background: #007bff;
64
+ background: #3b82f6;
66
65
  color: white;
67
66
  }
68
67
  button.secondary {
69
- background: #6c757d;
68
+ background: #6b7280;
70
69
  color: white;
71
70
  }
72
- button:hover {
73
- opacity: 0.9;
74
- }
75
71
  `
76
72
  ];
77
73
 
78
74
  public render() {
79
75
  return html`
80
- <button class="${this.variant}">
81
- ${this.label}
82
- </button>
76
+ <button class="${this.variant}">${this.label}</button>
83
77
  `;
84
78
  }
85
79
  }
@@ -93,33 +87,32 @@ import { setupWccTools } from '@design.estate/dees-wcctools';
93
87
  import { html } from 'lit';
94
88
 
95
89
  // Import your components
96
- import { MyButton } from './components/my-button.js';
97
- import { MyCard } from './components/my-card.js';
98
-
99
- // Define elements for the catalogue
100
- const elements = {
101
- 'my-button': MyButton,
102
- 'my-card': MyCard,
103
- };
104
-
105
- // Optionally define pages
106
- const pages = {
107
- 'home': () => html`
108
- <div style="padding: 20px;">
109
- <h1>Welcome to My Component Library</h1>
110
- <p>Browse components using the sidebar.</p>
111
- </div>
112
- `,
113
- 'getting-started': () => html`
114
- <div style="padding: 20px;">
115
- <h2>Getting Started</h2>
116
- <p>Installation and usage instructions...</p>
117
- </div>
118
- `,
119
- };
120
-
121
- // Initialize the catalogue
122
- setupWccTools(elements, pages);
90
+ import * as elements from './components/index.js';
91
+ import * as views from './views/index.js';
92
+ import * as pages from './pages/index.js';
93
+
94
+ // Initialize with sections-based configuration
95
+ setupWccTools({
96
+ sections: [
97
+ {
98
+ name: 'Pages',
99
+ type: 'pages',
100
+ items: pages,
101
+ },
102
+ {
103
+ name: 'Views',
104
+ type: 'elements',
105
+ items: views,
106
+ icon: 'web',
107
+ },
108
+ {
109
+ name: 'Elements',
110
+ type: 'elements',
111
+ items: elements,
112
+ sort: ([a], [b]) => a.localeCompare(b),
113
+ },
114
+ ],
115
+ });
123
116
  ```
124
117
 
125
118
  ### 3. Create an HTML Entry Point
@@ -137,6 +130,69 @@ setupWccTools(elements, pages);
137
130
  </html>
138
131
  ```
139
132
 
133
+ ## ๐Ÿ“‚ Sections Configuration
134
+
135
+ The sections-based API gives you full control over how components are organized in the sidebar.
136
+
137
+ ### Section Properties
138
+
139
+ | Property | Type | Description |
140
+ |----------|------|-------------|
141
+ | `name` | `string` | Display name for the section header |
142
+ | `type` | `'elements' \| 'pages'` | How items render (`elements` show demos, `pages` render directly) |
143
+ | `items` | `Record<string, any>` | Object containing element classes or page factories |
144
+ | `filter` | `(name, item) => boolean` | Optional filter function to include/exclude items |
145
+ | `sort` | `([a, itemA], [b, itemB]) => number` | Optional sort function for ordering items |
146
+ | `icon` | `string` | Optional Material Symbols icon name |
147
+ | `collapsed` | `boolean` | Start section collapsed (default: `false`) |
148
+
149
+ ### Advanced Example
150
+
151
+ ```typescript
152
+ import { setupWccTools } from '@design.estate/dees-wcctools';
153
+ import * as allElements from './elements/index.js';
154
+ import * as pages from './pages/index.js';
155
+
156
+ setupWccTools({
157
+ sections: [
158
+ {
159
+ name: 'Pages',
160
+ type: 'pages',
161
+ items: pages,
162
+ },
163
+ {
164
+ name: 'Form Controls',
165
+ type: 'elements',
166
+ items: allElements,
167
+ icon: 'edit_note',
168
+ filter: (name) => name.startsWith('form-') || name.includes('input'),
169
+ sort: ([a], [b]) => a.localeCompare(b),
170
+ },
171
+ {
172
+ name: 'Layout',
173
+ type: 'elements',
174
+ items: allElements,
175
+ icon: 'dashboard',
176
+ filter: (name) => name.startsWith('layout-') || name.startsWith('grid-'),
177
+ },
178
+ {
179
+ name: 'Legacy',
180
+ type: 'elements',
181
+ items: allElements,
182
+ filter: (name) => name.startsWith('legacy-'),
183
+ collapsed: true, // Start collapsed
184
+ },
185
+ ],
186
+ });
187
+ ```
188
+
189
+ ### Legacy API (Still Supported)
190
+
191
+ ```typescript
192
+ // The old format still works for simple use cases
193
+ setupWccTools(elements, pages);
194
+ ```
195
+
140
196
  ## Features
141
197
 
142
198
  ### ๐ŸŽฏ Live Property Editing
@@ -162,19 +218,7 @@ Test your components across different screen sizes:
162
218
 
163
219
  ### ๐ŸŒ“ Theme Support
164
220
 
165
- Components automatically adapt to light/dark themes using the `goBright` property:
166
-
167
- ```typescript
168
- public render() {
169
- return html`
170
- <div class="${this.goBright ? 'light-theme' : 'dark-theme'}">
171
- <!-- Your component content -->
172
- </div>
173
- `;
174
- }
175
- ```
176
-
177
- Or use CSS custom properties with the theme manager:
221
+ Components automatically adapt to light/dark themes. Use CSS custom properties with the theme manager:
178
222
 
179
223
  ```typescript
180
224
  import { cssManager } from '@design.estate/dees-element';
@@ -182,8 +226,8 @@ import { cssManager } from '@design.estate/dees-element';
182
226
  public static styles = [
183
227
  css`
184
228
  :host {
185
- color: ${cssManager.bdTheme('#000', '#fff')};
186
- background: ${cssManager.bdTheme('#fff', '#000')};
229
+ color: ${cssManager.bdTheme('#1a1a1a', '#e5e5e5')};
230
+ background: ${cssManager.bdTheme('#ffffff', '#0a0a0a')};
187
231
  }
188
232
  `
189
233
  ];
@@ -191,7 +235,7 @@ public static styles = [
191
235
 
192
236
  ### ๐ŸŽฌ Screen Recording
193
237
 
194
- Record component demos directly from the catalogue! The built-in recorder supports:
238
+ Record component demos directly from the catalogue:
195
239
 
196
240
  - **Viewport Recording** โ€” Record just the component viewport
197
241
  - **Full Screen Recording** โ€” Capture the entire screen
@@ -232,9 +276,26 @@ export class MyComponent extends DeesElement {
232
276
  }
233
277
  ```
234
278
 
279
+ ### ๐ŸŽญ Multiple Demos
280
+
281
+ Components can expose multiple demo variations:
282
+
283
+ ```typescript
284
+ @customElement('my-button')
285
+ export class MyButton extends DeesElement {
286
+ public static demo = [
287
+ () => html`<my-button variant="primary">Primary</my-button>`,
288
+ () => html`<my-button variant="secondary">Secondary</my-button>`,
289
+ () => html`<my-button variant="danger">Danger</my-button>`,
290
+ ];
291
+ }
292
+ ```
293
+
294
+ Each demo appears as a numbered item in an expandable folder in the sidebar.
295
+
235
296
  ### โณ Async Demos
236
297
 
237
- Return a `Promise` from `demo` for async setup. The dashboard waits for resolution:
298
+ Return a `Promise` from `demo` for async setup:
238
299
 
239
300
  ```typescript
240
301
  public static demo = async () => {
@@ -243,7 +304,7 @@ public static demo = async () => {
243
304
  };
244
305
  ```
245
306
 
246
- ### ๐ŸŽญ Container Queries
307
+ ### ๐ŸŽฏ Container Queries
247
308
 
248
309
  Components can respond to their container size using the `wccToolsViewport` container:
249
310
 
@@ -269,7 +330,7 @@ public static styles = [
269
330
 
270
331
  ### Required for Catalogue Display
271
332
 
272
- 1. Components must expose a static `demo` property returning a Lit template
333
+ 1. Components must expose a static `demo` property returning a Lit template (or array of templates)
273
334
  2. Use `@property()` decorators with the `accessor` keyword for editable properties
274
335
  3. Export component classes for proper detection
275
336
 
@@ -278,7 +339,7 @@ public static styles = [
278
339
  ```typescript
279
340
  @customElement('best-practice-component')
280
341
  export class BestPracticeComponent extends DeesElement {
281
- // โœ… Static demo property
342
+ // โœ… Static demo property (single or array)
282
343
  public static demo = () => html`
283
344
  <best-practice-component
284
345
  .complexProp=${{ key: 'value' }}
@@ -305,23 +366,40 @@ export class BestPracticeComponent extends DeesElement {
305
366
  The catalogue uses URL routing for deep linking:
306
367
 
307
368
  ```
308
- /wcctools-route/:type/:name/:viewport/:theme
369
+ /wcctools-route/:sectionName/:itemName/:demoIndex/:viewport/:theme
309
370
 
310
371
  Examples:
311
- /wcctools-route/element/my-button/desktop/dark
312
- /wcctools-route/page/home/tablet/bright
372
+ /wcctools-route/Elements/my-button/0/desktop/dark
373
+ /wcctools-route/Views/view-dashboard/0/tablet/bright
374
+ /wcctools-route/Pages/home/0/desktop/dark
313
375
  ```
314
376
 
315
377
  ## API Reference
316
378
 
317
- ### `setupWccTools(elements, pages?)`
379
+ ### `setupWccTools(config)`
380
+
381
+ Initialize the WCC Tools dashboard with sections configuration.
318
382
 
319
- Initialize the WCC Tools dashboard.
383
+ ```typescript
384
+ interface IWccSection {
385
+ name: string;
386
+ type: 'elements' | 'pages';
387
+ items: Record<string, any>;
388
+ filter?: (name: string, item: any) => boolean;
389
+ sort?: (a: [string, any], b: [string, any]) => number;
390
+ icon?: string;
391
+ collapsed?: boolean;
392
+ }
393
+
394
+ interface IWccConfig {
395
+ sections: IWccSection[];
396
+ }
397
+
398
+ setupWccTools(config: IWccConfig): void;
320
399
 
321
- | Parameter | Type | Description |
322
- |-----------|------|-------------|
323
- | `elements` | `Record<string, typeof LitElement>` | Map of element names to classes |
324
- | `pages` | `Record<string, TTemplateFactory>` | Optional map of page names to template functions |
400
+ // Legacy (still supported)
401
+ setupWccTools(elements: Record<string, any>, pages?: Record<string, TTemplateFactory>): void;
402
+ ```
325
403
 
326
404
  ### `DeesDemoWrapper`
327
405
 
@@ -357,14 +435,21 @@ recorder.stopRecording();
357
435
  ## Project Structure
358
436
 
359
437
  ```
360
- my-components/
438
+ my-component-library/
361
439
  โ”œโ”€โ”€ src/
362
- โ”‚ โ”œโ”€โ”€ components/
440
+ โ”‚ โ”œโ”€โ”€ elements/ # UI components
363
441
  โ”‚ โ”‚ โ”œโ”€โ”€ my-button.ts
364
- โ”‚ โ”‚ โ””โ”€โ”€ my-card.ts
365
- โ”‚ โ””โ”€โ”€ catalogue.ts
366
- โ”œโ”€โ”€ dist/
367
- โ”œโ”€โ”€ index.html
442
+ โ”‚ โ”‚ โ”œโ”€โ”€ my-card.ts
443
+ โ”‚ โ”‚ โ””โ”€โ”€ index.ts
444
+ โ”‚ โ”œโ”€โ”€ views/ # Full-page layouts
445
+ โ”‚ โ”‚ โ”œโ”€โ”€ view-dashboard.ts
446
+ โ”‚ โ”‚ โ””โ”€โ”€ index.ts
447
+ โ”‚ โ”œโ”€โ”€ pages/ # Documentation pages
448
+ โ”‚ โ”‚ โ”œโ”€โ”€ home.ts
449
+ โ”‚ โ”‚ โ””โ”€โ”€ index.ts
450
+ โ”‚ โ””โ”€โ”€ catalogue.ts # WCC Tools setup
451
+ โ”œโ”€โ”€ html/
452
+ โ”‚ โ””โ”€โ”€ index.html
368
453
  โ””โ”€โ”€ package.json
369
454
  ```
370
455
 
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@design.estate/dees-wcctools',
6
- version: '3.1.2',
6
+ version: '3.3.0',
7
7
  description: 'A set of web component tools for creating element catalogues, enabling the structured development and documentation of custom elements and pages.'
8
8
  }
@@ -1,6 +1,7 @@
1
1
  import { DeesElement, property, html, customElement, type TemplateResult, queryAsync, render, domtools } from '@design.estate/dees-element';
2
2
  import { resolveTemplateFactory, getDemoAtIndex, getDemoCount, hasMultipleDemos } from './wcctools.helpers.js';
3
3
  import type { TTemplateFactory } from './wcctools.helpers.js';
4
+ import type { IWccConfig, IWccSection, TElementType } from '../wcctools.interfaces.js';
4
5
 
5
6
  import * as plugins from '../wcctools.plugins.js';
6
7
 
@@ -9,13 +10,37 @@ import './wcc-frame.js';
9
10
  import './wcc-sidebar.js';
10
11
  import './wcc-properties.js';
11
12
  import { type TTheme } from './wcc-properties.js';
12
- import { type TElementType } from './wcc-sidebar.js';
13
13
  import { breakpoints } from '@design.estate/dees-domtools';
14
14
  import { WccFrame } from './wcc-frame.js';
15
15
 
16
+ /**
17
+ * Get filtered and sorted items from a section
18
+ */
19
+ export const getSectionItems = (section: IWccSection): Array<[string, any]> => {
20
+ let entries = Object.entries(section.items);
21
+
22
+ // Apply filter if provided
23
+ if (section.filter) {
24
+ entries = entries.filter(([name, item]) => section.filter(name, item));
25
+ }
26
+
27
+ // Apply sort if provided
28
+ if (section.sort) {
29
+ entries.sort(section.sort);
30
+ }
31
+
32
+ return entries;
33
+ };
34
+
16
35
  @customElement('wcc-dashboard')
17
36
  export class WccDashboard extends DeesElement {
18
37
 
38
+ @property()
39
+ accessor sections: IWccSection[] = [];
40
+
41
+ @property()
42
+ accessor selectedSection: IWccSection | null = null;
43
+
19
44
  @property()
20
45
  accessor selectedType: TElementType;
21
46
 
@@ -39,36 +64,43 @@ export class WccDashboard extends DeesElement {
39
64
  return this.selectedViewport === 'native';
40
65
  }
41
66
 
42
- @property()
43
- accessor pages: Record<string, TTemplateFactory> = {};
44
-
45
- @property()
46
- accessor elements: { [key: string]: DeesElement } = {};
47
-
48
67
  @property()
49
68
  accessor warning: string = null;
50
-
69
+
51
70
  private frameScrollY: number = 0;
52
71
  private sidebarScrollY: number = 0;
53
72
  private scrollPositionsApplied: boolean = false;
54
-
73
+
55
74
  @queryAsync('wcc-frame')
56
75
  accessor wccFrame: Promise<WccFrame>;
57
76
 
58
- constructor(
59
- elementsArg?: { [key: string]: DeesElement },
60
- pagesArg?: Record<string, TTemplateFactory>
61
- ) {
77
+ constructor(config?: IWccConfig) {
62
78
  super();
63
- if (elementsArg) {
64
- this.elements = elementsArg;
65
- console.log('got elements:');
66
- console.log(this.elements);
79
+ if (config && config.sections) {
80
+ this.sections = config.sections;
81
+ console.log('got sections:', this.sections.map(s => s.name));
67
82
  }
83
+ }
68
84
 
69
- if (pagesArg) {
70
- this.pages = pagesArg;
85
+ /**
86
+ * Find an item by name across all sections, returns the item and its section
87
+ */
88
+ public findItemByName(name: string): { item: any; section: IWccSection } | null {
89
+ for (const section of this.sections) {
90
+ const entries = getSectionItems(section);
91
+ const found = entries.find(([itemName]) => itemName === name);
92
+ if (found) {
93
+ return { item: found[1], section };
94
+ }
71
95
  }
96
+ return null;
97
+ }
98
+
99
+ /**
100
+ * Find a section by name (URL-decoded)
101
+ */
102
+ public findSectionByName(name: string): IWccSection | null {
103
+ return this.sections.find(s => s.name === name) || null;
72
104
  }
73
105
 
74
106
  public render(): TemplateResult {
@@ -159,19 +191,37 @@ export class WccDashboard extends DeesElement {
159
191
  this.setupScrollListeners();
160
192
  }, 500);
161
193
 
162
- // Route with demo index (new format)
194
+ // New route format with section name
163
195
  this.domtools.router.on(
164
- '/wcctools-route/:itemType/:itemName/:demoIndex/:viewport/:theme',
196
+ '/wcctools-route/:sectionName/:itemName/:demoIndex/:viewport/:theme',
165
197
  async (routeInfo) => {
166
- this.selectedType = routeInfo.params.itemType as TElementType;
198
+ const sectionName = decodeURIComponent(routeInfo.params.sectionName);
199
+ this.selectedSection = this.findSectionByName(sectionName);
167
200
  this.selectedItemName = routeInfo.params.itemName;
168
201
  this.selectedDemoIndex = parseInt(routeInfo.params.demoIndex) || 0;
169
202
  this.selectedViewport = routeInfo.params.viewport as breakpoints.TViewport;
170
203
  this.selectedTheme = routeInfo.params.theme as TTheme;
171
- if (routeInfo.params.itemType === 'element') {
172
- this.selectedItem = this.elements[routeInfo.params.itemName];
173
- } else if (routeInfo.params.itemType === 'page') {
174
- this.selectedItem = this.pages[routeInfo.params.itemName];
204
+
205
+ if (this.selectedSection) {
206
+ // Find item within the section
207
+ const entries = getSectionItems(this.selectedSection);
208
+ const found = entries.find(([name]) => name === routeInfo.params.itemName);
209
+ if (found) {
210
+ this.selectedItem = found[1];
211
+ this.selectedType = this.selectedSection.type === 'elements' ? 'element' : 'page';
212
+ }
213
+ } else {
214
+ // Fallback: try legacy format (element/page as section name)
215
+ const legacyType = routeInfo.params.sectionName;
216
+ if (legacyType === 'element' || legacyType === 'page') {
217
+ this.selectedType = legacyType as TElementType;
218
+ // Find item in any matching section
219
+ const result = this.findItemByName(routeInfo.params.itemName);
220
+ if (result) {
221
+ this.selectedItem = result.item;
222
+ this.selectedSection = result.section;
223
+ }
224
+ }
175
225
  }
176
226
 
177
227
  // Restore scroll positions from query parameters
@@ -201,17 +251,33 @@ export class WccDashboard extends DeesElement {
201
251
 
202
252
  // Legacy route without demo index (for backwards compatibility)
203
253
  this.domtools.router.on(
204
- '/wcctools-route/:itemType/:itemName/:viewport/:theme',
254
+ '/wcctools-route/:sectionName/:itemName/:viewport/:theme',
205
255
  async (routeInfo) => {
206
- this.selectedType = routeInfo.params.itemType as TElementType;
256
+ const sectionName = decodeURIComponent(routeInfo.params.sectionName);
257
+ this.selectedSection = this.findSectionByName(sectionName);
207
258
  this.selectedItemName = routeInfo.params.itemName;
208
- this.selectedDemoIndex = 0; // Default to first demo
259
+ this.selectedDemoIndex = 0;
209
260
  this.selectedViewport = routeInfo.params.viewport as breakpoints.TViewport;
210
261
  this.selectedTheme = routeInfo.params.theme as TTheme;
211
- if (routeInfo.params.itemType === 'element') {
212
- this.selectedItem = this.elements[routeInfo.params.itemName];
213
- } else if (routeInfo.params.itemType === 'page') {
214
- this.selectedItem = this.pages[routeInfo.params.itemName];
262
+
263
+ if (this.selectedSection) {
264
+ const entries = getSectionItems(this.selectedSection);
265
+ const found = entries.find(([name]) => name === routeInfo.params.itemName);
266
+ if (found) {
267
+ this.selectedItem = found[1];
268
+ this.selectedType = this.selectedSection.type === 'elements' ? 'element' : 'page';
269
+ }
270
+ } else {
271
+ // Fallback: try legacy format
272
+ const legacyType = routeInfo.params.sectionName;
273
+ if (legacyType === 'element' || legacyType === 'page') {
274
+ this.selectedType = legacyType as TElementType;
275
+ const result = this.findItemByName(routeInfo.params.itemName);
276
+ if (result) {
277
+ this.selectedItem = result.item;
278
+ this.selectedSection = result.section;
279
+ }
280
+ }
215
281
  }
216
282
 
217
283
  // Restore scroll positions from query parameters
@@ -297,7 +363,10 @@ export class WccDashboard extends DeesElement {
297
363
  }
298
364
 
299
365
  public buildUrl() {
300
- const baseUrl = `/wcctools-route/${this.selectedType}/${this.selectedItemName}/${this.selectedDemoIndex}/${this.selectedViewport}/${this.selectedTheme}`;
366
+ const sectionName = this.selectedSection
367
+ ? encodeURIComponent(this.selectedSection.name)
368
+ : this.selectedType; // Fallback for legacy
369
+ const baseUrl = `/wcctools-route/${sectionName}/${this.selectedItemName}/${this.selectedDemoIndex}/${this.selectedViewport}/${this.selectedTheme}`;
301
370
  const queryParams = new URLSearchParams();
302
371
 
303
372
  if (this.frameScrollY > 0) {
@@ -351,7 +420,10 @@ export class WccDashboard extends DeesElement {
351
420
  }
352
421
 
353
422
  private updateUrlWithScrollState() {
354
- const baseUrl = `/wcctools-route/${this.selectedType}/${this.selectedItemName}/${this.selectedDemoIndex}/${this.selectedViewport}/${this.selectedTheme}`;
423
+ const sectionName = this.selectedSection
424
+ ? encodeURIComponent(this.selectedSection.name)
425
+ : this.selectedType; // Fallback for legacy
426
+ const baseUrl = `/wcctools-route/${sectionName}/${this.selectedItemName}/${this.selectedDemoIndex}/${this.selectedViewport}/${this.selectedTheme}`;
355
427
  const queryParams = new URLSearchParams();
356
428
 
357
429
  if (this.frameScrollY > 0) {