@r2digisolutions/components 0.14.20 → 0.14.22

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 min-w-[140px] max-w-[180px] flex-col items-center gap-1.5 rounded-xl border bg-surface-elevated px-3 py-2.5 text-center shadow-sm transition-all',
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.avatarUrl}
44
- <img src={node.avatarUrl} alt="" class="h-9 w-9 rounded-full object-cover" />
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,42 +61,54 @@
49
61
  {initials(node.name)}
50
62
  </span>
51
63
  {/if}
52
- <span class="truncate text-sm font-medium text-primary">{node.name}</span>
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
77
  {#snippet tree(node: OrgNode)}
60
- <div class="relative flex flex-col items-center">
61
- {@render nodeCard(node)}
62
-
63
- {#if node.children && node.children.length > 0}
64
- <div class="h-5 w-px bg-border" aria-hidden="true"></div>
65
- <div class="relative flex flex-wrap justify-center gap-x-8 gap-y-4">
66
- {#if node.children.length > 1}
78
+ <div class="flex flex-col items-center">
79
+ <div class="shrink-0" style:width="{CARD_W}px">
80
+ {@render nodeCard(node)}
81
+ </div>
82
+ {#if node.children?.length}
83
+ <div class="h-6 w-0.5 shrink-0 bg-border-strong" aria-hidden="true"></div>
84
+ {#if node.children.length === 1}
85
+ {@render tree(node.children[0])}
86
+ {:else}
87
+ <div
88
+ class="relative inline-flex items-start justify-center gap-4"
89
+ style:--siblings={node.children.length}
90
+ >
67
91
  <div
68
- class="pointer-events-none absolute left-[12%] right-[12%] top-0 h-px bg-border"
92
+ class="pointer-events-none absolute top-0 h-0.5 bg-border-strong"
93
+ style:left="calc(50% / var(--siblings))"
94
+ style:right="calc(50% / var(--siblings))"
69
95
  aria-hidden="true"
70
96
  ></div>
71
- {/if}
72
- {#each node.children as child (child.id)}
73
- <div class="relative flex flex-col items-center pt-0">
74
- <div class="absolute left-1/2 top-0 h-3 w-px -translate-x-1/2 bg-border" aria-hidden="true"></div>
75
- <div class="pt-3">
97
+ {#each node.children as child (child.id)}
98
+ <div class="flex shrink-0 flex-col items-center" style:min-width="{CARD_W}px">
99
+ <div class="h-4 w-0.5 shrink-0 bg-border-strong" aria-hidden="true"></div>
76
100
  {@render tree(child)}
77
101
  </div>
78
- </div>
79
- {/each}
80
- </div>
102
+ {/each}
103
+ </div>
104
+ {/if}
81
105
  {/if}
82
106
  </div>
83
107
  {/snippet}
84
108
 
85
- <div class={['overflow-x-auto py-2', className]} role="tree" aria-label="Organization chart">
109
+ <div class={['overflow-x-auto py-4', className]} role="tree" aria-label="Organization chart">
86
110
  {#if root}
87
- <div class="inline-flex min-w-full justify-center px-4">
111
+ <div class="flex min-w-max justify-center px-4 pb-2">
88
112
  {@render tree(root)}
89
113
  </div>
90
114
  {:else}
@@ -3,6 +3,11 @@ export interface OrgNode {
3
3
  name: string;
4
4
  role?: string;
5
5
  avatarUrl?: string;
6
+ assignees?: {
7
+ id: string;
8
+ name: string;
9
+ avatarUrl?: string | null;
10
+ }[];
6
11
  children?: OrgNode[];
7
12
  }
8
13
  interface OrgChartProps {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@r2digisolutions/components",
3
- "version": "0.14.20",
3
+ "version": "0.14.22",
4
4
  "private": false,
5
5
  "description": "R2DigiSolutions Svelte 5 component library — Atomic Design, Tailwind 4, Light/Dark mode",
6
6
  "license": "MIT",