feat(wcctools): Add section-based configuration API for setupWccTools, new Views, and section-aware routing/sidebar
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { DeesElement, property, html, customElement, type TemplateResult, queryAsync, render, domtools } from '@design.estate/dees-element';
|
||||
import { resolveTemplateFactory, getDemoAtIndex, getDemoCount, hasMultipleDemos } from './wcctools.helpers.js';
|
||||
import type { TTemplateFactory } from './wcctools.helpers.js';
|
||||
import type { IWccConfig, IWccSection, TElementType } from '../wcctools.interfaces.js';
|
||||
|
||||
import * as plugins from '../wcctools.plugins.js';
|
||||
|
||||
@@ -9,13 +10,37 @@ import './wcc-frame.js';
|
||||
import './wcc-sidebar.js';
|
||||
import './wcc-properties.js';
|
||||
import { type TTheme } from './wcc-properties.js';
|
||||
import { type TElementType } from './wcc-sidebar.js';
|
||||
import { breakpoints } from '@design.estate/dees-domtools';
|
||||
import { WccFrame } from './wcc-frame.js';
|
||||
|
||||
/**
|
||||
* Get filtered and sorted items from a section
|
||||
*/
|
||||
export const getSectionItems = (section: IWccSection): Array<[string, any]> => {
|
||||
let entries = Object.entries(section.items);
|
||||
|
||||
// Apply filter if provided
|
||||
if (section.filter) {
|
||||
entries = entries.filter(([name, item]) => section.filter(name, item));
|
||||
}
|
||||
|
||||
// Apply sort if provided
|
||||
if (section.sort) {
|
||||
entries.sort(section.sort);
|
||||
}
|
||||
|
||||
return entries;
|
||||
};
|
||||
|
||||
@customElement('wcc-dashboard')
|
||||
export class WccDashboard extends DeesElement {
|
||||
|
||||
@property()
|
||||
accessor sections: IWccSection[] = [];
|
||||
|
||||
@property()
|
||||
accessor selectedSection: IWccSection | null = null;
|
||||
|
||||
@property()
|
||||
accessor selectedType: TElementType;
|
||||
|
||||
@@ -39,36 +64,43 @@ export class WccDashboard extends DeesElement {
|
||||
return this.selectedViewport === 'native';
|
||||
}
|
||||
|
||||
@property()
|
||||
accessor pages: Record<string, TTemplateFactory> = {};
|
||||
|
||||
@property()
|
||||
accessor elements: { [key: string]: DeesElement } = {};
|
||||
|
||||
@property()
|
||||
accessor warning: string = null;
|
||||
|
||||
|
||||
private frameScrollY: number = 0;
|
||||
private sidebarScrollY: number = 0;
|
||||
private scrollPositionsApplied: boolean = false;
|
||||
|
||||
|
||||
@queryAsync('wcc-frame')
|
||||
accessor wccFrame: Promise<WccFrame>;
|
||||
|
||||
constructor(
|
||||
elementsArg?: { [key: string]: DeesElement },
|
||||
pagesArg?: Record<string, TTemplateFactory>
|
||||
) {
|
||||
constructor(config?: IWccConfig) {
|
||||
super();
|
||||
if (elementsArg) {
|
||||
this.elements = elementsArg;
|
||||
console.log('got elements:');
|
||||
console.log(this.elements);
|
||||
if (config && config.sections) {
|
||||
this.sections = config.sections;
|
||||
console.log('got sections:', this.sections.map(s => s.name));
|
||||
}
|
||||
}
|
||||
|
||||
if (pagesArg) {
|
||||
this.pages = pagesArg;
|
||||
/**
|
||||
* Find an item by name across all sections, returns the item and its section
|
||||
*/
|
||||
public findItemByName(name: string): { item: any; section: IWccSection } | null {
|
||||
for (const section of this.sections) {
|
||||
const entries = getSectionItems(section);
|
||||
const found = entries.find(([itemName]) => itemName === name);
|
||||
if (found) {
|
||||
return { item: found[1], section };
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a section by name (URL-decoded)
|
||||
*/
|
||||
public findSectionByName(name: string): IWccSection | null {
|
||||
return this.sections.find(s => s.name === name) || null;
|
||||
}
|
||||
|
||||
public render(): TemplateResult {
|
||||
@@ -159,19 +191,37 @@ export class WccDashboard extends DeesElement {
|
||||
this.setupScrollListeners();
|
||||
}, 500);
|
||||
|
||||
// Route with demo index (new format)
|
||||
// New route format with section name
|
||||
this.domtools.router.on(
|
||||
'/wcctools-route/:itemType/:itemName/:demoIndex/:viewport/:theme',
|
||||
'/wcctools-route/:sectionName/:itemName/:demoIndex/:viewport/:theme',
|
||||
async (routeInfo) => {
|
||||
this.selectedType = routeInfo.params.itemType as TElementType;
|
||||
const sectionName = decodeURIComponent(routeInfo.params.sectionName);
|
||||
this.selectedSection = this.findSectionByName(sectionName);
|
||||
this.selectedItemName = routeInfo.params.itemName;
|
||||
this.selectedDemoIndex = parseInt(routeInfo.params.demoIndex) || 0;
|
||||
this.selectedViewport = routeInfo.params.viewport as breakpoints.TViewport;
|
||||
this.selectedTheme = routeInfo.params.theme as TTheme;
|
||||
if (routeInfo.params.itemType === 'element') {
|
||||
this.selectedItem = this.elements[routeInfo.params.itemName];
|
||||
} else if (routeInfo.params.itemType === 'page') {
|
||||
this.selectedItem = this.pages[routeInfo.params.itemName];
|
||||
|
||||
if (this.selectedSection) {
|
||||
// Find item within the section
|
||||
const entries = getSectionItems(this.selectedSection);
|
||||
const found = entries.find(([name]) => name === routeInfo.params.itemName);
|
||||
if (found) {
|
||||
this.selectedItem = found[1];
|
||||
this.selectedType = this.selectedSection.type === 'elements' ? 'element' : 'page';
|
||||
}
|
||||
} else {
|
||||
// Fallback: try legacy format (element/page as section name)
|
||||
const legacyType = routeInfo.params.sectionName;
|
||||
if (legacyType === 'element' || legacyType === 'page') {
|
||||
this.selectedType = legacyType as TElementType;
|
||||
// Find item in any matching section
|
||||
const result = this.findItemByName(routeInfo.params.itemName);
|
||||
if (result) {
|
||||
this.selectedItem = result.item;
|
||||
this.selectedSection = result.section;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Restore scroll positions from query parameters
|
||||
@@ -201,17 +251,33 @@ export class WccDashboard extends DeesElement {
|
||||
|
||||
// Legacy route without demo index (for backwards compatibility)
|
||||
this.domtools.router.on(
|
||||
'/wcctools-route/:itemType/:itemName/:viewport/:theme',
|
||||
'/wcctools-route/:sectionName/:itemName/:viewport/:theme',
|
||||
async (routeInfo) => {
|
||||
this.selectedType = routeInfo.params.itemType as TElementType;
|
||||
const sectionName = decodeURIComponent(routeInfo.params.sectionName);
|
||||
this.selectedSection = this.findSectionByName(sectionName);
|
||||
this.selectedItemName = routeInfo.params.itemName;
|
||||
this.selectedDemoIndex = 0; // Default to first demo
|
||||
this.selectedDemoIndex = 0;
|
||||
this.selectedViewport = routeInfo.params.viewport as breakpoints.TViewport;
|
||||
this.selectedTheme = routeInfo.params.theme as TTheme;
|
||||
if (routeInfo.params.itemType === 'element') {
|
||||
this.selectedItem = this.elements[routeInfo.params.itemName];
|
||||
} else if (routeInfo.params.itemType === 'page') {
|
||||
this.selectedItem = this.pages[routeInfo.params.itemName];
|
||||
|
||||
if (this.selectedSection) {
|
||||
const entries = getSectionItems(this.selectedSection);
|
||||
const found = entries.find(([name]) => name === routeInfo.params.itemName);
|
||||
if (found) {
|
||||
this.selectedItem = found[1];
|
||||
this.selectedType = this.selectedSection.type === 'elements' ? 'element' : 'page';
|
||||
}
|
||||
} else {
|
||||
// Fallback: try legacy format
|
||||
const legacyType = routeInfo.params.sectionName;
|
||||
if (legacyType === 'element' || legacyType === 'page') {
|
||||
this.selectedType = legacyType as TElementType;
|
||||
const result = this.findItemByName(routeInfo.params.itemName);
|
||||
if (result) {
|
||||
this.selectedItem = result.item;
|
||||
this.selectedSection = result.section;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Restore scroll positions from query parameters
|
||||
@@ -297,7 +363,10 @@ export class WccDashboard extends DeesElement {
|
||||
}
|
||||
|
||||
public buildUrl() {
|
||||
const baseUrl = `/wcctools-route/${this.selectedType}/${this.selectedItemName}/${this.selectedDemoIndex}/${this.selectedViewport}/${this.selectedTheme}`;
|
||||
const sectionName = this.selectedSection
|
||||
? encodeURIComponent(this.selectedSection.name)
|
||||
: this.selectedType; // Fallback for legacy
|
||||
const baseUrl = `/wcctools-route/${sectionName}/${this.selectedItemName}/${this.selectedDemoIndex}/${this.selectedViewport}/${this.selectedTheme}`;
|
||||
const queryParams = new URLSearchParams();
|
||||
|
||||
if (this.frameScrollY > 0) {
|
||||
@@ -351,7 +420,10 @@ export class WccDashboard extends DeesElement {
|
||||
}
|
||||
|
||||
private updateUrlWithScrollState() {
|
||||
const baseUrl = `/wcctools-route/${this.selectedType}/${this.selectedItemName}/${this.selectedDemoIndex}/${this.selectedViewport}/${this.selectedTheme}`;
|
||||
const sectionName = this.selectedSection
|
||||
? encodeURIComponent(this.selectedSection.name)
|
||||
: this.selectedType; // Fallback for legacy
|
||||
const baseUrl = `/wcctools-route/${sectionName}/${this.selectedItemName}/${this.selectedDemoIndex}/${this.selectedViewport}/${this.selectedTheme}`;
|
||||
const queryParams = new URLSearchParams();
|
||||
|
||||
if (this.frameScrollY > 0) {
|
||||
|
||||
Reference in New Issue
Block a user