@design.estate/dees-wcctools 3.2.0 → 3.4.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.
@@ -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
 
@@ -34,41 +59,51 @@ export class WccDashboard extends DeesElement {
34
59
  @property()
35
60
  accessor selectedTheme: TTheme = 'dark';
36
61
 
62
+ @property()
63
+ accessor searchQuery: string = '';
64
+
37
65
  // Derived from selectedViewport - no need for separate property
38
66
  public get isNative(): boolean {
39
67
  return this.selectedViewport === 'native';
40
68
  }
41
69
 
42
- @property()
43
- accessor pages: Record<string, TTemplateFactory> = {};
44
-
45
- @property()
46
- accessor elements: { [key: string]: DeesElement } = {};
47
-
48
70
  @property()
49
71
  accessor warning: string = null;
50
-
72
+
51
73
  private frameScrollY: number = 0;
52
74
  private sidebarScrollY: number = 0;
53
75
  private scrollPositionsApplied: boolean = false;
54
-
76
+
55
77
  @queryAsync('wcc-frame')
56
78
  accessor wccFrame: Promise<WccFrame>;
57
79
 
58
- constructor(
59
- elementsArg?: { [key: string]: DeesElement },
60
- pagesArg?: Record<string, TTemplateFactory>
61
- ) {
80
+ constructor(config?: IWccConfig) {
62
81
  super();
63
- if (elementsArg) {
64
- this.elements = elementsArg;
65
- console.log('got elements:');
66
- console.log(this.elements);
82
+ if (config && config.sections) {
83
+ this.sections = config.sections;
84
+ console.log('got sections:', this.sections.map(s => s.name));
67
85
  }
86
+ }
68
87
 
69
- if (pagesArg) {
70
- this.pages = pagesArg;
88
+ /**
89
+ * Find an item by name across all sections, returns the item and its section
90
+ */
91
+ public findItemByName(name: string): { item: any; section: IWccSection } | null {
92
+ for (const section of this.sections) {
93
+ const entries = getSectionItems(section);
94
+ const found = entries.find(([itemName]) => itemName === name);
95
+ if (found) {
96
+ return { item: found[1], section };
97
+ }
71
98
  }
99
+ return null;
100
+ }
101
+
102
+ /**
103
+ * Find a section by name (URL-decoded)
104
+ */
105
+ public findSectionByName(name: string): IWccSection | null {
106
+ return this.sections.find(s => s.name === name) || null;
72
107
  }
73
108
 
74
109
  public render(): TemplateResult {
@@ -86,6 +121,7 @@ export class WccDashboard extends DeesElement {
86
121
  <wcc-sidebar
87
122
  .dashboardRef=${this}
88
123
  .selectedItem=${this.selectedItem}
124
+ .searchQuery=${this.searchQuery}
89
125
  .isNative=${this.isNative}
90
126
  @selectedType=${(eventArg) => {
91
127
  this.selectedType = eventArg.detail;
@@ -96,6 +132,10 @@ export class WccDashboard extends DeesElement {
96
132
  @selectedItem=${(eventArg) => {
97
133
  this.selectedItem = eventArg.detail;
98
134
  }}
135
+ @searchChanged=${(eventArg: CustomEvent) => {
136
+ this.searchQuery = eventArg.detail;
137
+ this.updateUrlWithScrollState();
138
+ }}
99
139
  ></wcc-sidebar>
100
140
  <wcc-properties
101
141
  .dashboardRef=${this}
@@ -159,26 +199,50 @@ export class WccDashboard extends DeesElement {
159
199
  this.setupScrollListeners();
160
200
  }, 500);
161
201
 
162
- // Route with demo index (new format)
202
+ // New route format with section name
163
203
  this.domtools.router.on(
164
- '/wcctools-route/:itemType/:itemName/:demoIndex/:viewport/:theme',
204
+ '/wcctools-route/:sectionName/:itemName/:demoIndex/:viewport/:theme',
165
205
  async (routeInfo) => {
166
- this.selectedType = routeInfo.params.itemType as TElementType;
206
+ const sectionName = decodeURIComponent(routeInfo.params.sectionName);
207
+ this.selectedSection = this.findSectionByName(sectionName);
167
208
  this.selectedItemName = routeInfo.params.itemName;
168
209
  this.selectedDemoIndex = parseInt(routeInfo.params.demoIndex) || 0;
169
210
  this.selectedViewport = routeInfo.params.viewport as breakpoints.TViewport;
170
211
  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];
212
+
213
+ if (this.selectedSection) {
214
+ // Find item within the section
215
+ const entries = getSectionItems(this.selectedSection);
216
+ const found = entries.find(([name]) => name === routeInfo.params.itemName);
217
+ if (found) {
218
+ this.selectedItem = found[1];
219
+ this.selectedType = this.selectedSection.type === 'elements' ? 'element' : 'page';
220
+ }
221
+ } else {
222
+ // Fallback: try legacy format (element/page as section name)
223
+ const legacyType = routeInfo.params.sectionName;
224
+ if (legacyType === 'element' || legacyType === 'page') {
225
+ this.selectedType = legacyType as TElementType;
226
+ // Find item in any matching section
227
+ const result = this.findItemByName(routeInfo.params.itemName);
228
+ if (result) {
229
+ this.selectedItem = result.item;
230
+ this.selectedSection = result.section;
231
+ }
232
+ }
175
233
  }
176
234
 
177
- // Restore scroll positions from query parameters
235
+ // Restore state from query parameters
178
236
  if (routeInfo.queryParams) {
237
+ const search = routeInfo.queryParams.search;
179
238
  const frameScrollY = routeInfo.queryParams.frameScrollY;
180
239
  const sidebarScrollY = routeInfo.queryParams.sidebarScrollY;
181
240
 
241
+ if (search) {
242
+ this.searchQuery = search;
243
+ } else {
244
+ this.searchQuery = '';
245
+ }
182
246
  if (frameScrollY) {
183
247
  this.frameScrollY = parseInt(frameScrollY);
184
248
  }
@@ -190,6 +254,8 @@ export class WccDashboard extends DeesElement {
190
254
  setTimeout(() => {
191
255
  this.applyScrollPositions();
192
256
  }, 100);
257
+ } else {
258
+ this.searchQuery = '';
193
259
  }
194
260
 
195
261
  const domtoolsInstance = await plugins.deesDomtools.elementBasic.setup();
@@ -201,24 +267,46 @@ export class WccDashboard extends DeesElement {
201
267
 
202
268
  // Legacy route without demo index (for backwards compatibility)
203
269
  this.domtools.router.on(
204
- '/wcctools-route/:itemType/:itemName/:viewport/:theme',
270
+ '/wcctools-route/:sectionName/:itemName/:viewport/:theme',
205
271
  async (routeInfo) => {
206
- this.selectedType = routeInfo.params.itemType as TElementType;
272
+ const sectionName = decodeURIComponent(routeInfo.params.sectionName);
273
+ this.selectedSection = this.findSectionByName(sectionName);
207
274
  this.selectedItemName = routeInfo.params.itemName;
208
- this.selectedDemoIndex = 0; // Default to first demo
275
+ this.selectedDemoIndex = 0;
209
276
  this.selectedViewport = routeInfo.params.viewport as breakpoints.TViewport;
210
277
  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];
278
+
279
+ if (this.selectedSection) {
280
+ const entries = getSectionItems(this.selectedSection);
281
+ const found = entries.find(([name]) => name === routeInfo.params.itemName);
282
+ if (found) {
283
+ this.selectedItem = found[1];
284
+ this.selectedType = this.selectedSection.type === 'elements' ? 'element' : 'page';
285
+ }
286
+ } else {
287
+ // Fallback: try legacy format
288
+ const legacyType = routeInfo.params.sectionName;
289
+ if (legacyType === 'element' || legacyType === 'page') {
290
+ this.selectedType = legacyType as TElementType;
291
+ const result = this.findItemByName(routeInfo.params.itemName);
292
+ if (result) {
293
+ this.selectedItem = result.item;
294
+ this.selectedSection = result.section;
295
+ }
296
+ }
215
297
  }
216
298
 
217
- // Restore scroll positions from query parameters
299
+ // Restore state from query parameters
218
300
  if (routeInfo.queryParams) {
301
+ const search = routeInfo.queryParams.search;
219
302
  const frameScrollY = routeInfo.queryParams.frameScrollY;
220
303
  const sidebarScrollY = routeInfo.queryParams.sidebarScrollY;
221
304
 
305
+ if (search) {
306
+ this.searchQuery = search;
307
+ } else {
308
+ this.searchQuery = '';
309
+ }
222
310
  if (frameScrollY) {
223
311
  this.frameScrollY = parseInt(frameScrollY);
224
312
  }
@@ -230,6 +318,8 @@ export class WccDashboard extends DeesElement {
230
318
  setTimeout(() => {
231
319
  this.applyScrollPositions();
232
320
  }, 100);
321
+ } else {
322
+ this.searchQuery = '';
233
323
  }
234
324
 
235
325
  const domtoolsInstance = await plugins.deesDomtools.elementBasic.setup();
@@ -297,9 +387,15 @@ export class WccDashboard extends DeesElement {
297
387
  }
298
388
 
299
389
  public buildUrl() {
300
- const baseUrl = `/wcctools-route/${this.selectedType}/${this.selectedItemName}/${this.selectedDemoIndex}/${this.selectedViewport}/${this.selectedTheme}`;
390
+ const sectionName = this.selectedSection
391
+ ? encodeURIComponent(this.selectedSection.name)
392
+ : this.selectedType; // Fallback for legacy
393
+ const baseUrl = `/wcctools-route/${sectionName}/${this.selectedItemName}/${this.selectedDemoIndex}/${this.selectedViewport}/${this.selectedTheme}`;
301
394
  const queryParams = new URLSearchParams();
302
395
 
396
+ if (this.searchQuery) {
397
+ queryParams.set('search', this.searchQuery);
398
+ }
303
399
  if (this.frameScrollY > 0) {
304
400
  queryParams.set('frameScrollY', this.frameScrollY.toString());
305
401
  }
@@ -351,9 +447,15 @@ export class WccDashboard extends DeesElement {
351
447
  }
352
448
 
353
449
  private updateUrlWithScrollState() {
354
- const baseUrl = `/wcctools-route/${this.selectedType}/${this.selectedItemName}/${this.selectedDemoIndex}/${this.selectedViewport}/${this.selectedTheme}`;
450
+ const sectionName = this.selectedSection
451
+ ? encodeURIComponent(this.selectedSection.name)
452
+ : this.selectedType; // Fallback for legacy
453
+ const baseUrl = `/wcctools-route/${sectionName}/${this.selectedItemName}/${this.selectedDemoIndex}/${this.selectedViewport}/${this.selectedTheme}`;
355
454
  const queryParams = new URLSearchParams();
356
455
 
456
+ if (this.searchQuery) {
457
+ queryParams.set('search', this.searchQuery);
458
+ }
357
459
  if (this.frameScrollY > 0) {
358
460
  queryParams.set('frameScrollY', this.frameScrollY.toString());
359
461
  }