diff --git a/apps/documentation/components/packages/design/details/details.tsx b/apps/documentation/components/packages/design/details/details.tsx index ad84dce1..9c249836 100644 --- a/apps/documentation/components/packages/design/details/details.tsx +++ b/apps/documentation/components/packages/design/details/details.tsx @@ -1,10 +1,26 @@ /* cSpell:disable */ import dynamic from 'next/dynamic'; -import { Action, Field } from '@elixir-cloud/design/dist/components/details/details'; import SlSkeleton from '@shoelace-style/shoelace/dist/react/skeleton'; const EccUtilsDesignDetails = dynamic( - () => import('@elixir-cloud/design/dist/react/details/index'), + () => import('@elixir-cloud/design/dist/react/ecc-d-details/index'), + { + ssr: false, + loading: () => ( +
+ + +
+ + +
+
+ ), + }, +); + +const EccUtilsDesignDataItem = dynamic( + () => import('@elixir-cloud/design/dist/react/ecc-d-data-item/index'), { ssr: false, loading: () => ( @@ -21,248 +37,192 @@ const EccUtilsDesignDetails = dynamic( ); export default function Details() { - const data: unknown = { - company: { - name: 'TechCorp', - industry: 'Technology', - employees: [ + const employees = [ + { + id: 101, + name: 'Alice Johnson', + position: 'Software Engineer', + skills: ['Java', 'JavaScript', 'SQL'], + projects: [ { - id: 101, - name: 'Alice Johnson', - position: 'Software Engineer', - skills: ['Java', 'JavaScript', 'SQL'], - projects: [ - { - projectId: 'P123', - projectName: 'SmartApp', - startDate: '2022-05-01', - endDate: '2023-01-15', - status: 'Completed', - team: ['Alice Johnson', 'Bob Smith'], - }, - { - projectId: 'P124', - projectName: 'DataAnalyzer', - startDate: '2023-02-01', - endDate: null, - status: 'In Progress', - team: ['Alice Johnson', 'Charlie Brown'], - }, - ], - address: { - street: '123 Tech Street', - city: 'Techville', - zipCode: 'T12345', - country: 'Techland', - }, + projectId: 'P123', + projectName: 'SmartApp', + startDate: '2022-05-01', + endDate: '2023-01-15', + status: 'Completed', + team: ['Alice Johnson', 'Bob Smith'], }, { - id: 102, - name: 'Bob Smith', - position: 'UI/UX Designer', - skills: ['UI Design', 'CSS', 'Adobe XD'], - projects: [ - { - projectId: 'P123', - projectName: 'SmartApp', - startDate: '2022-05-01', - endDate: '2023-01-15', - status: 'Completed', - team: ['Alice Johnson', 'Bob Smith'], - }, - { - projectId: 'P125', - projectName: 'MobileApp', - startDate: '2023-03-01', - endDate: null, - status: 'In Progress', - team: ['Bob Smith', 'Eve White'], - }, - ], - address: { - street: '456 Design Avenue', - city: 'DesignCity', - zipCode: 'D67890', - country: 'Designland', - }, + copy: true, + projectId: 'P124', + projectName: 'DataAnalyzer', + startDate: '2023-02-01', + endDate: null, + status: 'In Progress', + team: ['Alice Johnson', 'Charlie Brown'], }, ], - }, - clients: [ - { - clientId: 'C001', - clientName: 'GlobalTech Solutions', - contactPerson: 'John Johnson', - email: 'john.johnson@globaltech.com', - projects: ['SmartApp', 'DataAnalyzer'], - }, - { - clientId: 'C002', - clientName: 'DesignMaster Co.', - contactPerson: 'Eva Designer', - email: 'eva.designer@designmaster.com', - projects: ['MobileApp'], - }, - ], - financials: { - revenue: 1500000.5, - expenses: { - operating: 500000.25, - marketing: 200000.75, - research: 100000.5, - }, - profit: 696969, - }, - marketSegments: ['Enterprise', 'Startups', 'Government'], - partners: [ - { - partnerId: 'P001', - partnerName: 'InnoTech Innovations', - contactPerson: 'Mark Innovator', - email: 'mark@innotech.com', - projects: ['SmartApp'], - }, - { - partnerId: 'P002', - partnerName: 'CreatiDesign Solutions', - contactPerson: 'Lisa Designer', - email: 'lisa@creatidesign.com', - projects: ['MobileApp'], - }, - ], - debt: { - partnerId: 'P001', - partnerName: 'InnoTech Innovations', - contactPerson: 'Mark Innovator', - email: 'mark@innotech.com', - projects: ['SmartApp'], - }, - }; - - const fields: Field[] = [ - { - key: 'company.name', - path: 'company.name', - tab: 'Company Info', - }, - { - key: 'company.industry', - path: 'company.industry', - tab: 'Company Info', - }, - { - key: 'company.employees', - path: 'company.employees[*]', - tab: 'Employees', - arrayOptions: { - labelOptions: { - path: '.id', - prefix: 'Employee ', - }, - }, - }, - { - key: 'company.employees.skills', - parentKey: 'company.employees', - path: 'company.employees[*].skills', - copy: true, - arrayOptions: { - type: 'tag', + address: { + street: '123 Tech Street', + city: 'Techville', + zipCode: 'T12345', + country: 'Techland', }, }, { - key: 'company.employees.projects.team', - parentKey: 'company.employees', - path: 'company.employees[*].projects[*].team', - arrayOptions: { - type: 'tag', - }, - }, - { - key: 'company.employees.projects', - parentKey: 'company.employees', - path: 'company.employees[*].projects[*]', - arrayOptions: { - labelOptions: { - path: '.projectName', + id: 102, + name: 'Bob Smith', + position: 'UI/UX Designer', + skills: ['UI Design', 'CSS', 'Adobe XD'], + projects: [ + { + projectId: 'P123', + projectName: 'SmartApp', + startDate: '2022-05-01', + endDate: '2023-01-15', + status: 'Completed', + team: ['Alice Johnson', 'Bob Smith'], }, - }, - }, - { - key: 'company.employees.projects', - parentKey: 'company.employees', - path: 'company.employees[0].projects[1]', - copy: true, - }, - { - key: 'clients', - path: 'clients[*]', - tab: 'Clients', - arrayOptions: { - labelOptions: { - path: '.clientName', + { + projectId: 'P125', + projectName: 'MobileApp', + startDate: '2023-03-01', + endDate: null, + status: 'In Progress', + team: ['Bob Smith', 'Eve White'], }, + ], + address: { + street: '456 Design Avenue', + city: 'DesignCity', + zipCode: 'D67890', + country: 'Designland', }, }, - { - key: 'clients.projects', - parentKey: 'clients', - path: 'clients[*].projects', - arrayOptions: { - type: 'tag', - }, - }, - { - key: 'financials', - path: 'financials.*', - tab: 'Financials', - }, - { - key: 'financials.expenses', - parentKey: 'financials', - path: 'financials.expenses', - tooltip: 'Different fields of expenses', - }, - { - key: 'hypothetical', - path: 'hypothetical', - tab: 'Hypothetical', - }, ]; - const actions: Action[] = [ + const clients = [ { - key: '3', - label: 'View More', - type: 'link', - linkOptions: { - url: 'https://www.google.com', - }, - position: 'left', + clientId: 'C001', + clientName: 'GlobalTech Solutions', + contactPerson: 'John Johnson', + email: 'john.johnson@globaltech.com', + projects: ['SmartApp', 'DataAnalyzer'], }, { - key: '2', - label: 'Cancel', - type: 'button', - buttonOptions: { - variant: 'danger', - }, - }, - { - key: '1', - label: 'Save', - type: 'button', - buttonOptions: { - variant: 'primary', - icon: { - url: 'https://img.icons8.com/ios/50/ffffff/save--v1.png', - }, - }, + clientId: 'C002', + clientName: 'DesignMaster Co.', + contactPerson: 'Eva Designer', + email: 'eva.designer@designmaster.com', + projects: ['MobileApp'], }, ]; + + const financials = { + revenue: 1500000.5, + expenses: { + operating: 500000.25, + marketing: 200000.75, + research: 100000.5, + }, + profit: 696969, + }; + + const saveIcon = ''; + return (
- + + +
+ + +
+ +
+ {employees.map((e) => ( + + {Object.keys(e).map( + (key) => + key !== 'address' && + key !== 'projects' && ( + + ), + )} + + {e.projects.map((p) => ( + + {Object.keys(p).map((pKey) => ( + + ))} + + ))} + + + {Object.keys(e.address).map((aKey) => ( + + ))} + + + ))} +
+ +
+ {clients.map((c) => ( + + {Object.keys(c).map((cKey) => ( + + ))} + + ))} +
+ +
+ {Object.keys(financials).map((fKey) => + fKey === 'expenses' ? ( + + {Object.keys(financials[fKey]).map((k) => ( + + ))} + + ) : ( + + ), + )} +
+
+ + + text + + + + +
); } diff --git a/apps/documentation/pages/_meta.json b/apps/documentation/pages/_meta.json index f0749be0..8ae937f2 100644 --- a/apps/documentation/pages/_meta.json +++ b/apps/documentation/pages/_meta.json @@ -13,17 +13,6 @@ }, "about": { "title": "About", - "type": "menu", - "items": { - "contact": { - "title": "Contact", - "type": "page", - "href": "/about/contact" - }, - "contribute": { - "title": "Contribute", - "type": "page" - } - } + "type": "page" } -} \ No newline at end of file +} diff --git a/apps/documentation/pages/about/_meta.json b/apps/documentation/pages/about/_meta.json index 67e3400d..b12a184e 100644 --- a/apps/documentation/pages/about/_meta.json +++ b/apps/documentation/pages/about/_meta.json @@ -1,10 +1,4 @@ { - "contact": { - "title": "Contact", - "type": "page" - }, - "contribute": { - "title": "Contribute", - "type": "page" - } + "contact": "Contact", + "contribute": "Contribute" } diff --git a/packages/ecc-utils-design/demo/details/index.html b/packages/ecc-utils-design/demo/details/index.html index 3e7549a1..b2b54dd5 100644 --- a/packages/ecc-utils-design/demo/details/index.html +++ b/packages/ecc-utils-design/demo/details/index.html @@ -114,8 +114,6 @@ html` @@ -240,13 +238,15 @@ - text - + text + diff --git a/packages/ecc-utils-design/src/components/details/dataItem.ts b/packages/ecc-utils-design/src/components/details/dataItem.ts index da498b63..9f87f622 100644 --- a/packages/ecc-utils-design/src/components/details/dataItem.ts +++ b/packages/ecc-utils-design/src/components/details/dataItem.ts @@ -1,5 +1,5 @@ import { html, LitElement } from "lit"; -import { property } from "lit/decorators.js"; +import { property, state } from "lit/decorators.js"; import "@shoelace-style/shoelace/dist/components/tooltip/tooltip.js"; import "@shoelace-style/shoelace/dist/components/copy-button/copy-button.js"; import "@shoelace-style/shoelace/dist/components/tab/tab.js"; @@ -21,12 +21,32 @@ export class EccUtilsDesignDataItem extends LitElement { dataItemStyles, ]; - @property({ type: Array, reflect: true }) tabs = []; - @property({ type: Boolean }) copy = false; - @property({ type: String }) type = ""; - @property({ type: String }) value = ""; - @property({ type: String }) label = ""; - @property() tooltip = ""; + @property({ type: Array, reflect: true }) tabs: string[] = []; + @property({ type: Boolean, reflect: true }) copy = false; + @property({ type: String, reflect: true }) type = ""; + @property({ type: String, reflect: true }) value = ""; + @property({ type: String, reflect: true }) label = ""; + @property({ type: String, reflect: true }) tooltip = ""; + @state() forceStateUpdate = 0; + + connectedCallback() { + super.connectedCallback(); + + const observer = new MutationObserver((mutations) => { + mutations.forEach((mutation) => { + if (mutation.type === "childList") { + // React does not handle custom elements very well + // So we have to force a state update whenever the childList changes + // so we can have access to its updated attributes + this.forceStateUpdate += 1; + } + }); + }); + + observer.observe(this.shadowRoot!, { + childList: true, + }); + } render() { const tabs = () => html` diff --git a/packages/ecc-utils-design/src/components/details/details.styles.ts b/packages/ecc-utils-design/src/components/details/details.styles.ts index 4d7ece9c..00775a5d 100644 --- a/packages/ecc-utils-design/src/components/details/details.styles.ts +++ b/packages/ecc-utils-design/src/components/details/details.styles.ts @@ -26,7 +26,7 @@ export const detailsStyles = css` text-decoration: underline; padding: 0; } - .action-button { + .ecc-action-button { display: flex; flex-direction: row; align-items: center; @@ -43,20 +43,20 @@ export const detailsStyles = css` white-space: nowrap; font-size: var(--ecc-input-font-size-medium); } - .action-button:active { + .ecc-action-button:active { scale: 0.98; } - .action-button.primary { + .ecc-action-button.ecc-primary { color: white; background-color: var(--ecc-color-primary-600); border: none; } - .action-button.danger { + .ecc-action-button.ecc-danger { color: white; background-color: var(--sl-color-danger-600); border: none; } - .icon { + .ecc-icon { height: var(--ecc-input-font-size-large); width: var(--ecc-input-font-size-large); } diff --git a/packages/ecc-utils-design/src/components/details/details.ts b/packages/ecc-utils-design/src/components/details/details.ts index 9dabd7e4..ddf1c894 100644 --- a/packages/ecc-utils-design/src/components/details/details.ts +++ b/packages/ecc-utils-design/src/components/details/details.ts @@ -23,11 +23,13 @@ export class EccUtilsDesignDetails extends LitElement { render() { const getLeftActionButtons = () => - Array.from(this.querySelectorAll('[type="action"][position="left"]')); + Array.from( + this.querySelectorAll('[ecc-type="action"][ecc-position="left"]') + ); const getRightActionButtons = () => Array.from( - this.querySelectorAll('[type="action"]:not([position="left"])') + this.querySelectorAll('[ecc-type="action"]:not([ecc-position="left"])') ); return html` diff --git a/packages/ecc-utils-design/src/components/details/utils.ts b/packages/ecc-utils-design/src/components/details/utils.ts index aba8af88..8979b57f 100644 --- a/packages/ecc-utils-design/src/components/details/utils.ts +++ b/packages/ecc-utils-design/src/components/details/utils.ts @@ -4,6 +4,7 @@ import * as _ from "lodash-es"; import "@shoelace-style/shoelace/dist/components/tooltip/tooltip.js"; export const getListData = (input: string) => { + if (typeof input !== "string") return input; if (input.trim().startsWith("[") && input.trim().endsWith("]")) { return JSON.parse(input); } @@ -12,13 +13,14 @@ export const getListData = (input: string) => { export const getNestedCopyValue = (el: Element) => { const dataItems = el.querySelectorAll("ecc-d-data-item"); + const data: Record = {}; dataItems.forEach((e) => { const pathName = e.getAttribute("label") || "label"; if (_.isEqual(el, e.parentElement)) { - if (e.getAttribute("type") === null) { + if (!e.getAttribute("type")?.trim()) { _.set(data, pathName, e.getAttribute("value")); } else if (e.getAttribute("type") === "list") { _.set(data, pathName, getListData(e.getAttribute("value") || "")); @@ -44,14 +46,14 @@ export const formatLabel = (str: string) => { export const formatBtn = (btn: Element) => { const parser = new DOMParser(); const startIcon = parser - .parseFromString(btn.getAttribute("start-icon") || "", "text/html") + .parseFromString(btn.getAttribute("ecc-start-icon") || "", "text/html") .body.querySelector("*"); - startIcon?.classList.add("icon", "start-icon"); + startIcon?.classList.add("ecc-icon", "ecc-start-icon"); const endIcon = parser - .parseFromString(btn.getAttribute("end-icon") || "", "text/html") + .parseFromString(btn.getAttribute("ecc-end-icon") || "", "text/html") .body.querySelector("*"); - endIcon?.classList.add("icon", "end-icon"); + endIcon?.classList.add("ecc-icon", "ecc-end-icon"); btn.setAttribute("rel", btn.getAttribute("rel") || "noopener noreferrer"); btn.setAttribute("target", btn.getAttribute("target") || "_blank");