Skip to content

Commit dbb3879

Browse files
Copilotlaske185
andauthored
feat(preview): Add TreePreview component
Agent-Logs-Url: https://github.com/public-ui/public-ui.github.io/sessions/5634a45a-b574-4b8a-8d85-b386827b876e Co-authored-by: laske185 <37439758+laske185@users.noreply.github.com>
1 parent 6b5a655 commit dbb3879

7 files changed

Lines changed: 247 additions & 74 deletions

File tree

docs/30-components/tree.mdx

Lines changed: 5 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ tags:
99
---
1010

1111
import Readme from '../../readmes/tree/readme.md';
12+
import TreePreview from '@site/src/components/previews/components/Tree';
1213
import { ExampleLink } from '@site/src/components/ExampleLink';
1314

1415
# Tree
@@ -17,43 +18,10 @@ Synonyme: List, Navigation
1718

1819
Die **Tree**-Komponente stellt eine hierarchische Liste dar, in der jedes Element untergeordnete Einträge enthalten kann. Elemente mit Kindelementen lassen sich ein- oder ausklappen, um die untergeordnete Ebene anzuzeigen oder auszublenden.
1920

20-
### Code
21-
22-
```html
23-
<kol-tree _label="Sitemap">
24-
<kol-tree-item _label="Home" _href="#" _active></kol-tree-item>
25-
<kol-tree-item _label="Page 1" _href="#" _open>
26-
<kol-tree-item _label="Subpage 1" _href="#" _open>
27-
<kol-tree-item _label="Product 1" _href="#"></kol-tree-item>
28-
<kol-tree-item _label="Product 2" _href="#"></kol-tree-item>
29-
<kol-tree-item _label="Product 3" _href="#"></kol-tree-item>
30-
<kol-tree-item _label="Product 4" _href="#"></kol-tree-item>
31-
</kol-tree-item>
32-
<kol-tree-item _label="Subpage 2" _href="#"></kol-tree-item>
33-
<kol-tree-item _label="Subpage 3" _href="#"></kol-tree-item>
34-
<kol-tree-item _label="Subpage 4" _href="#"></kol-tree-item>
35-
</kol-tree-item>
36-
<kol-tree-item _label="Page 2" _href="#"></kol-tree-item>
37-
</kol-tree>
38-
```
39-
40-
### Beispiel
41-
42-
<kol-tree _label="Sitemap">
43-
<kol-tree-item _label="Home" _href="#" _active></kol-tree-item>
44-
<kol-tree-item _label="Page 1" _href="#" _open>
45-
<kol-tree-item _label="Subpage 1" _href="#" _open>
46-
<kol-tree-item _label="Product 1" _href="#"></kol-tree-item>
47-
<kol-tree-item _label="Product 2" _href="#"></kol-tree-item>
48-
<kol-tree-item _label="Product 3" _href="#"></kol-tree-item>
49-
<kol-tree-item _label="Product 4" _href="#"></kol-tree-item>
50-
</kol-tree-item>
51-
<kol-tree-item _label="Subpage 2" _href="#"></kol-tree-item>
52-
<kol-tree-item _label="Subpage 3" _href="#"></kol-tree-item>
53-
<kol-tree-item _label="Subpage 4" _href="#"></kol-tree-item>
54-
</kol-tree-item>
55-
<kol-tree-item _label="Page 2" _href="#"></kol-tree-item>
56-
</kol-tree>
21+
<TreePreview
22+
codeCollapsable
23+
codeCollapsed
24+
/>
5725

5826
## Verwendung
5927

i18n/de/code.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,15 @@
519519
"preview.component.image.label": {
520520
"message": "Beispielbild"
521521
},
522+
"preview.component.tree.label": {
523+
"message": "Sitemap"
524+
},
525+
"preview.component.tree.items.edit": {
526+
"message": "Einträge bearbeiten"
527+
},
528+
"preview.component.tree.items.closeedit": {
529+
"message": "Bearbeitung schließen"
530+
},
522531
"preview.property.remove": {
523532
"message": "Entfernen"
524533
},

i18n/en/code.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,15 @@
519519
"preview.component.image.label": {
520520
"message": "Sample image"
521521
},
522+
"preview.component.tree.label": {
523+
"message": "Sitemap"
524+
},
525+
"preview.component.tree.items.edit": {
526+
"message": "Edit Items"
527+
},
528+
"preview.component.tree.items.closeedit": {
529+
"message": "Close Editor"
530+
},
522531
"preview.property.remove": {
523532
"message": "Remove"
524533
},

i18n/en/docusaurus-plugin-content-docs/current/30-components/tree.mdx

Lines changed: 5 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ description: Description, specification and examples for the Tree component.
44
---
55

66
import Readme from '/readmes/tree/readme.md';
7+
import TreePreview from '@site/src/components/previews/components/Tree';
78
import { ExampleLink } from '@site/src/components/ExampleLink';
89

910
#Tree
@@ -12,43 +13,10 @@ Synonyms: cunning, navigation
1213

1314
The **Tree** component represents a hierarchical list in which each element can contain child entries. Elements with child elements can be collapsed or expanded to show or hide the child level.
1415

15-
### Code
16-
17-
```html
18-
<kol-tree _label="Sitemap">
19-
<kol-tree-item _label="Home" _href="#" _active></kol-tree-item>
20-
<kol-tree-item _label="Page 1" _href="#" _open>
21-
<kol-tree-item _label="Subpage 1" _href="#" _open>
22-
<kol-tree-item _label="Product 1" _href="#"></kol-tree-item>
23-
<kol-tree-item _label="Product 2" _href="#"></kol-tree-item>
24-
<kol-tree-item _label="Product 3" _href="#"></kol-tree-item>
25-
<kol-tree-item _label="Product 4" _href="#"></kol-tree-item>
26-
</kol-tree-item>
27-
<kol-tree-item _label="Subpage 2" _href="#"></kol-tree-item>
28-
<kol-tree-item _label="Subpage 3" _href="#"></kol-tree-item>
29-
<kol-tree-item _label="Subpage 4" _href="#"></kol-tree-item>
30-
</kol-tree-item>
31-
<kol-tree-item _label="Page 2" _href="#"></kol-tree-item>
32-
</kol-tree>
33-
```
34-
35-
### Example
36-
37-
<kol-tree _label="Sitemap">
38-
<kol-tree-item _label="Home" _href="#" _active></kol-tree-item>
39-
<kol-tree-item _label="Page 1" _href="#" _open>
40-
<kol-tree-item _label="Subpage 1" _href="#" _open>
41-
<kol-tree-item _label="Product 1" _href="#"></kol-tree-item>
42-
<kol-tree-item _label="Product 2" _href="#"></kol-tree-item>
43-
<kol-tree-item _label="Product 3" _href="#"></kol-tree-item>
44-
<kol-tree-item _label="Product 4" _href="#"></kol-tree-item>
45-
</kol-tree-item>
46-
<kol-tree-item _label="Subpage 2" _href="#"></kol-tree-item>
47-
<kol-tree-item _label="Subpage 3" _href="#"></kol-tree-item>
48-
<kol-tree-item _label="Subpage 4" _href="#"></kol-tree-item>
49-
</kol-tree-item>
50-
<kol-tree-item _label="Page 2" _href="#"></kol-tree-item>
51-
</kol-tree>
16+
<TreePreview
17+
codeCollapsable
18+
codeCollapsed
19+
/>
5220

5321
## Usage
5422

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import React from 'react';
2+
import Preview, { PreviewLayout } from '../Preview';
3+
import type { JSX } from '@public-ui/components';
4+
import { KolInputText, KolTree, KolTreeItem } from '@public-ui/react-v19';
5+
import TreeItemsProperty from '../properties/TreeItemsProperty';
6+
import type { TreeItemData } from '../properties/TreeItemsProperty';
7+
import { translate } from '@docusaurus/Translate';
8+
9+
type TreePreviewProps = JSX.KolTree & { _items?: TreeItemData[] };
10+
11+
interface TreePreviewComponentProps {
12+
initialProps?: TreePreviewProps;
13+
visibleProperties?: (keyof JSX.KolTree | '_items')[];
14+
codeCollapsable?: boolean;
15+
codeCollapsed?: boolean;
16+
}
17+
18+
const TreePreview: React.FC<TreePreviewComponentProps> = (props) => {
19+
const defaultProps = React.useMemo<TreePreviewProps>(
20+
() => ({
21+
_label: translate({ id: 'preview.component.tree.label' }),
22+
_items: [],
23+
}),
24+
[],
25+
);
26+
27+
const formatSource = (currentProps: TreePreviewProps): string => {
28+
const { _items, ...treeProps } = currentProps;
29+
const items = _items ?? [];
30+
31+
const propsString = Object.entries(treeProps as Record<string, unknown>)
32+
.filter(([, value]) => value !== undefined && value !== null && value !== '')
33+
.map(([key, value]) => {
34+
if (typeof value === 'string') return `\n ${key}="${value}"`;
35+
if (typeof value === 'boolean') return value ? `\n ${key}` : '';
36+
if (typeof value === 'number') return `\n ${key}={${value}}`;
37+
return `\n ${key}={${JSON.stringify(value)}}`;
38+
})
39+
.sort()
40+
.join('');
41+
42+
const itemsString = items
43+
.map((item) => {
44+
const itemProps = Object.entries(item as Record<string, unknown>)
45+
.filter(([, value]) => value !== undefined && value !== null && value !== '')
46+
.map(([key, value]) => {
47+
if (typeof value === 'string') return ` ${key}="${value}"`;
48+
if (typeof value === 'boolean') return value ? ` ${key}` : '';
49+
if (typeof value === 'number') return ` ${key}={${value}}`;
50+
return ` ${key}={${JSON.stringify(value)}}`;
51+
})
52+
.join('');
53+
return ` <KolTreeItem${itemProps} />`;
54+
})
55+
.join('\n');
56+
57+
return `<KolTree${propsString}\n>\n${itemsString}\n</KolTree>`;
58+
};
59+
60+
return (
61+
<Preview<TreePreviewProps>
62+
propertyComponents={{
63+
_label: <KolInputText _label="Label" />,
64+
_items: <TreeItemsProperty label="Items" />,
65+
}}
66+
initialProps={{ ...defaultProps, ...props.initialProps }}
67+
componentName="KolTree"
68+
visibleProperties={props.visibleProperties}
69+
codeCollapsable={props.codeCollapsable}
70+
codeCollapsed={props.codeCollapsed}
71+
layout={PreviewLayout.DEFAULT}
72+
sourceFormatter={formatSource}
73+
>
74+
{(componentProps) => {
75+
const { _items, ...treeProps } = componentProps;
76+
const items = _items ?? [];
77+
return (
78+
<div className="min-h-44">
79+
<KolTree {...treeProps}>
80+
{items.map((item, index) => (
81+
<KolTreeItem key={index} {...item} />
82+
))}
83+
</KolTree>
84+
</div>
85+
);
86+
}}
87+
</Preview>
88+
);
89+
};
90+
91+
export default TreePreview;
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
import { KolInputNumber, KolInputText, KolButton, KolInputCheckbox, KolDrawer, KolCard } from '@public-ui/react-v19';
2+
import React, { useEffect, useState } from 'react';
3+
import { translate } from '@docusaurus/Translate';
4+
5+
export type TreeItemData = {
6+
_label: string;
7+
_href?: string;
8+
_active?: boolean;
9+
};
10+
11+
const TREE_ITEMS_POOL: TreeItemData[] = [
12+
{ _label: 'Home', _href: '#/', _active: true },
13+
{ _label: 'Page 1', _href: '#/page-1' },
14+
{ _label: 'Page 2', _href: '#/page-2' },
15+
{ _label: 'Page 3', _href: '#/page-3' },
16+
{ _label: 'Page 4', _href: '#/page-4' },
17+
{ _label: 'Page 5', _href: '#/page-5' },
18+
];
19+
20+
const TreeItemsProperty = (props: {
21+
label: string;
22+
_on?: {
23+
onInput?: (event: Event, value: unknown) => void;
24+
};
25+
}) => {
26+
const [isEditing, setIsEditing] = useState(false);
27+
const [itemCount, setItemCount] = useState(3);
28+
const [items, setItems] = useState<TreeItemData[]>(TREE_ITEMS_POOL);
29+
const currentItems = items.slice(0, itemCount);
30+
31+
useEffect(() => {
32+
props._on?.onInput?.(new Event('input'), currentItems);
33+
}, [items, itemCount]);
34+
35+
const handleCountChange = (_event: Event, value: unknown) => {
36+
const count = Math.min(Math.max(Number(value) || 1, 1), items.length);
37+
setItemCount(count);
38+
};
39+
40+
const handleItemChange = (index: number, field: keyof TreeItemData, value: unknown) => {
41+
const newItems = [...items];
42+
if (field === '_active') {
43+
newItems[index] = { ...newItems[index], [field]: value as boolean };
44+
} else {
45+
newItems[index] = { ...newItems[index], [field]: value as string };
46+
}
47+
setItems(newItems);
48+
};
49+
50+
return (
51+
<div style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>
52+
<KolInputNumber
53+
_label={props.label}
54+
_min={1}
55+
_max={items.length}
56+
_value={itemCount}
57+
_on={{ onInput: handleCountChange }}
58+
/>
59+
60+
{currentItems.length > 0 && (
61+
<KolButton
62+
_label={translate({ id: 'preview.component.tree.items.edit' })}
63+
_variant="secondary"
64+
_on={{ onClick: () => setIsEditing(!isEditing) }}
65+
/>
66+
)}
67+
68+
<KolDrawer
69+
_label={translate({ id: 'preview.component.tree.items.edit' })}
70+
_open={isEditing}
71+
_align="right"
72+
_hasCloser
73+
_on={{ onClose: () => setIsEditing(false) }}
74+
>
75+
<div className="flex flex-col gap-4 py-4">
76+
{currentItems.map((item, index) => (
77+
<KolCard key={index} _label={`Item ${index + 1}`}>
78+
<div className="flex flex-col gap-2">
79+
<KolInputText
80+
_label="Label"
81+
_value={item._label}
82+
_on={{
83+
onInput: (e: Event) => {
84+
const target = e.target as HTMLInputElement;
85+
handleItemChange(index, '_label', target.value);
86+
},
87+
}}
88+
/>
89+
90+
<KolInputText
91+
_label="URL/Href"
92+
_value={item._href}
93+
_on={{
94+
onInput: (e: Event) => {
95+
const target = e.target as HTMLInputElement;
96+
handleItemChange(index, '_href', target.value);
97+
},
98+
}}
99+
/>
100+
101+
<KolInputCheckbox
102+
_label="Active"
103+
_checked={item._active ?? false}
104+
_variant="switch"
105+
_on={{
106+
onInput: (_e: Event, checked: unknown) => {
107+
handleItemChange(index, '_active', !!checked);
108+
},
109+
}}
110+
/>
111+
</div>
112+
</KolCard>
113+
))}
114+
115+
<KolButton
116+
_label={translate({ id: 'preview.component.tree.items.closeedit' })}
117+
_variant="primary"
118+
_on={{ onClick: () => setIsEditing(false) }}
119+
/>
120+
</div>
121+
</KolDrawer>
122+
</div>
123+
);
124+
};
125+
126+
export default TreeItemsProperty;

src/components/previews/properties/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,5 @@ export { default as QuoteVariantProperty } from './QuoteVariantProperty';
1717
export { default as RadioOptionsProperty } from './RadioOptionsProperty';
1818
export { default as ResizeProperty } from './ResizeProperty';
1919
export { default as SmartButtonProperty } from './SmartButtonProperty';
20+
export { default as TreeItemsProperty } from './TreeItemsProperty';
21+
export type { TreeItemData } from './TreeItemsProperty';

0 commit comments

Comments
 (0)