@r2digisolutions/components 0.14.20 → 0.14.21
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.
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
name: string;
|
|
5
5
|
role?: string;
|
|
6
6
|
avatarUrl?: string;
|
|
7
|
+
assignees?: { id: string; name: string; avatarUrl?: string | null }[];
|
|
7
8
|
children?: OrgNode[];
|
|
8
9
|
}
|
|
9
10
|
|
|
@@ -17,6 +18,8 @@
|
|
|
17
18
|
|
|
18
19
|
let selected = $state<string | null>(null);
|
|
19
20
|
|
|
21
|
+
const CARD_W = 176;
|
|
22
|
+
|
|
20
23
|
function initials(name: string) {
|
|
21
24
|
return name
|
|
22
25
|
.split(/\s+/)
|
|
@@ -24,13 +27,22 @@
|
|
|
24
27
|
.map((p) => p[0]?.toUpperCase() ?? '')
|
|
25
28
|
.join('');
|
|
26
29
|
}
|
|
30
|
+
|
|
31
|
+
function primaryAvatar(node: OrgNode) {
|
|
32
|
+
return node.avatarUrl ?? node.assignees?.[0]?.avatarUrl ?? null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function primaryLabel(node: OrgNode) {
|
|
36
|
+
if (node.assignees?.length === 1) return node.assignees[0].name;
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
27
39
|
</script>
|
|
28
40
|
|
|
29
41
|
{#snippet nodeCard(node: OrgNode)}
|
|
30
42
|
<button
|
|
31
43
|
type="button"
|
|
32
44
|
class={[
|
|
33
|
-
'flex
|
|
45
|
+
'flex w-full flex-col items-center gap-1.5 rounded-xl border bg-surface-elevated px-3 py-2.5 text-center shadow-sm transition-all',
|
|
34
46
|
selected === node.id
|
|
35
47
|
? 'border-brand-500 ring-2 ring-brand-500/30'
|
|
36
48
|
: 'border-border hover:border-brand-400'
|
|
@@ -40,8 +52,8 @@
|
|
|
40
52
|
onselect?.(node);
|
|
41
53
|
}}
|
|
42
54
|
>
|
|
43
|
-
{#if node
|
|
44
|
-
<img src={node
|
|
55
|
+
{#if primaryAvatar(node)}
|
|
56
|
+
<img src={primaryAvatar(node)!} alt="" class="h-9 w-9 rounded-full object-cover" />
|
|
45
57
|
{:else}
|
|
46
58
|
<span
|
|
47
59
|
class="flex h-9 w-9 items-center justify-center rounded-full bg-brand-500/15 text-xs font-semibold text-brand-600 dark:text-brand-300"
|
|
@@ -49,43 +61,78 @@
|
|
|
49
61
|
{initials(node.name)}
|
|
50
62
|
</span>
|
|
51
63
|
{/if}
|
|
52
|
-
<span class="
|
|
64
|
+
<span class="line-clamp-2 text-sm leading-snug font-semibold text-primary">{node.name}</span>
|
|
65
|
+
{#if primaryLabel(node)}
|
|
66
|
+
<span class="truncate text-xs text-secondary">{primaryLabel(node)}</span>
|
|
67
|
+
{/if}
|
|
53
68
|
{#if node.role}
|
|
54
69
|
<span class="truncate text-[11px] text-muted">{node.role}</span>
|
|
55
70
|
{/if}
|
|
71
|
+
{#if node.assignees && node.assignees.length > 1}
|
|
72
|
+
<span class="text-[10px] text-muted">+{node.assignees.length - 1} más</span>
|
|
73
|
+
{/if}
|
|
56
74
|
</button>
|
|
57
75
|
{/snippet}
|
|
58
76
|
|
|
59
|
-
{#snippet
|
|
60
|
-
|
|
61
|
-
{
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
77
|
+
{#snippet childForest(node: OrgNode)}
|
|
78
|
+
{#if node.children?.length}
|
|
79
|
+
{#if node.children.length === 1}
|
|
80
|
+
<div class="flex flex-col items-center">
|
|
81
|
+
<div class="h-6 w-px shrink-0 bg-border" aria-hidden="true"></div>
|
|
82
|
+
{@render branch(node.children[0])}
|
|
83
|
+
</div>
|
|
84
|
+
{:else}
|
|
85
|
+
<div class="flex flex-col items-center">
|
|
86
|
+
<div class="h-6 w-px shrink-0 bg-border" aria-hidden="true"></div>
|
|
87
|
+
<div
|
|
88
|
+
class="relative inline-flex items-start justify-center gap-4 pt-4"
|
|
89
|
+
style:--siblings={node.children.length}
|
|
90
|
+
>
|
|
67
91
|
<div
|
|
68
|
-
class="pointer-events-none absolute
|
|
92
|
+
class="pointer-events-none absolute top-0 h-px bg-border"
|
|
93
|
+
style:left="calc(50% / var(--siblings))"
|
|
94
|
+
style:right="calc(50% / var(--siblings))"
|
|
69
95
|
aria-hidden="true"
|
|
70
96
|
></div>
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
97
|
+
{#each node.children as child (child.id)}
|
|
98
|
+
<div class="flex shrink-0 flex-col items-center" style:width="{CARD_W}px">
|
|
99
|
+
<div class="h-4 w-px shrink-0 bg-border" aria-hidden="true"></div>
|
|
100
|
+
<div class="w-full">
|
|
101
|
+
{@render nodeCard(child)}
|
|
102
|
+
</div>
|
|
77
103
|
</div>
|
|
78
|
-
|
|
79
|
-
|
|
104
|
+
{/each}
|
|
105
|
+
</div>
|
|
106
|
+
<div class="inline-flex items-start justify-center gap-4">
|
|
107
|
+
{#each node.children as child (child.id)}
|
|
108
|
+
<div
|
|
109
|
+
class="flex flex-col items-center pt-2"
|
|
110
|
+
style:min-width="{CARD_W}px"
|
|
111
|
+
>
|
|
112
|
+
{#if child.children?.length}
|
|
113
|
+
{@render childForest(child)}
|
|
114
|
+
{/if}
|
|
115
|
+
</div>
|
|
116
|
+
{/each}
|
|
117
|
+
</div>
|
|
80
118
|
</div>
|
|
81
119
|
{/if}
|
|
120
|
+
{/if}
|
|
121
|
+
{/snippet}
|
|
122
|
+
|
|
123
|
+
{#snippet branch(node: OrgNode)}
|
|
124
|
+
<div class="flex flex-col items-center">
|
|
125
|
+
<div class="w-full" style:width="{CARD_W}px">
|
|
126
|
+
{@render nodeCard(node)}
|
|
127
|
+
</div>
|
|
128
|
+
{@render childForest(node)}
|
|
82
129
|
</div>
|
|
83
130
|
{/snippet}
|
|
84
131
|
|
|
85
|
-
<div class={['overflow-x-auto py-
|
|
132
|
+
<div class={['overflow-x-auto py-4', className]} role="tree" aria-label="Organization chart">
|
|
86
133
|
{#if root}
|
|
87
|
-
<div class="
|
|
88
|
-
{@render
|
|
134
|
+
<div class="flex justify-center px-4 pb-2">
|
|
135
|
+
{@render branch(root)}
|
|
89
136
|
</div>
|
|
90
137
|
{:else}
|
|
91
138
|
<p class="py-8 text-center text-sm text-muted">No organization data</p>
|