@stubber/ui 1.5.0 → 1.6.1
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.
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script>
|
|
2
|
-
import { createEventDispatcher } from "svelte";
|
|
3
|
-
import * as
|
|
2
|
+
import { createEventDispatcher, tick } from "svelte";
|
|
3
|
+
import * as Popover from "@stubber/ui/popover";
|
|
4
|
+
import * as Command from "@stubber/ui/command";
|
|
4
5
|
import * as Tooltip from "@stubber/ui/tooltip";
|
|
5
6
|
import { Button } from "@stubber/ui/button";
|
|
6
7
|
import { toast } from "svelte-sonner";
|
|
@@ -19,10 +20,27 @@
|
|
|
19
20
|
success: "success-500",
|
|
20
21
|
};
|
|
21
22
|
|
|
23
|
+
// Combobox state
|
|
24
|
+
let open = false;
|
|
25
|
+
let searchValue = "";
|
|
26
|
+
|
|
27
|
+
// Filter orgs based on search
|
|
28
|
+
$: filteredOrgs = orgs.filter((org) =>
|
|
29
|
+
org.label.toLowerCase().includes(searchValue.toLowerCase())
|
|
30
|
+
);
|
|
31
|
+
|
|
22
32
|
function selectOrg(orguuid) {
|
|
23
33
|
dispatch("selectOrg", orguuid);
|
|
24
34
|
}
|
|
25
35
|
|
|
36
|
+
function closeAndFocusTrigger(triggerId) {
|
|
37
|
+
open = false;
|
|
38
|
+
searchValue = "";
|
|
39
|
+
tick().then(() => {
|
|
40
|
+
document.getElementById(triggerId)?.focus();
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
26
44
|
function copyToClipboard(uuid, event) {
|
|
27
45
|
if (event) {
|
|
28
46
|
event.stopPropagation();
|
|
@@ -33,141 +51,163 @@
|
|
|
33
51
|
}
|
|
34
52
|
</script>
|
|
35
53
|
|
|
36
|
-
<
|
|
37
|
-
<
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
<div class="w-full text-left truncate">
|
|
62
|
-
<p class="text-label text-surface-900 truncate">
|
|
63
|
-
{selectedOrg?.label ?? "No Org"}
|
|
64
|
-
</p>
|
|
65
|
-
{#if selectedOrg?.alert}
|
|
66
|
-
<div class="flex items-center space-x-1">
|
|
67
|
-
<span
|
|
68
|
-
class="h-[6px] w-[6px] bg-{alertColorMap[selectedOrg.alert?.type]} rounded-full"
|
|
69
|
-
/>
|
|
70
|
-
<p class="text-small italic text-{alertColorMap[selectedOrg.alert?.type]}">
|
|
71
|
-
{selectedOrg.alert?.message}
|
|
72
|
-
</p>
|
|
73
|
-
</div>
|
|
54
|
+
<Popover.Root bind:open let:ids>
|
|
55
|
+
<Popover.Trigger asChild let:builder>
|
|
56
|
+
<Button
|
|
57
|
+
builders={[builder]}
|
|
58
|
+
id={ids.trigger}
|
|
59
|
+
variant="outline"
|
|
60
|
+
role="combobox"
|
|
61
|
+
aria-expanded={open}
|
|
62
|
+
class="w-full sm:w-[280px] pl-3 pr-3 py-2 h-auto border-surface-100 transition-colors group justify-start"
|
|
63
|
+
>
|
|
64
|
+
<div class="flex items-center w-full">
|
|
65
|
+
<div class="flex items-center justify-center mr-3">
|
|
66
|
+
{#if selectedOrg?.filesrc && !loading}
|
|
67
|
+
<img
|
|
68
|
+
class="h-[25px] w-[25px] object-cover rounded-full"
|
|
69
|
+
src={selectedOrg.filesrc}
|
|
70
|
+
alt={selectedOrg.label}
|
|
71
|
+
/>
|
|
72
|
+
{:else if selectedOrg?.placeholderColor}
|
|
73
|
+
<div
|
|
74
|
+
class="h-[25px] w-[25px] rounded-full"
|
|
75
|
+
style="background-color: {selectedOrg.placeholderColor}"
|
|
76
|
+
/>
|
|
77
|
+
{:else}
|
|
78
|
+
<div class="h-[25px] w-[25px] rounded-full bg-surface-100" />
|
|
74
79
|
{/if}
|
|
75
80
|
</div>
|
|
76
|
-
{/if}
|
|
77
81
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
|
|
82
|
+
{#if loading}
|
|
83
|
+
<span class="h-[25px] w-40 bg-surface-100 rounded-md" />
|
|
84
|
+
{:else}
|
|
85
|
+
<div class="w-full text-left truncate">
|
|
86
|
+
<p class="text-label text-surface-900 truncate">
|
|
87
|
+
{selectedOrg?.label ?? "No Org"}
|
|
88
|
+
</p>
|
|
89
|
+
{#if selectedOrg?.alert}
|
|
90
|
+
<div class="flex items-center space-x-1">
|
|
91
|
+
<span
|
|
92
|
+
class="h-[6px] w-[6px] bg-{alertColorMap[selectedOrg.alert?.type]} rounded-full"
|
|
93
|
+
/>
|
|
94
|
+
<p class="text-small italic text-{alertColorMap[selectedOrg.alert?.type]}">
|
|
95
|
+
{selectedOrg.alert?.message}
|
|
96
|
+
</p>
|
|
97
|
+
</div>
|
|
98
|
+
{/if}
|
|
99
|
+
</div>
|
|
100
|
+
{/if}
|
|
101
|
+
|
|
102
|
+
{#if selectedOrg}
|
|
103
|
+
<Tooltip.Root openDelay={0} disableHoverableContent={true}>
|
|
104
|
+
<Tooltip.Trigger>
|
|
105
|
+
<div
|
|
106
|
+
class="opacity-100 sm:opacity-0 sm:group-hover:opacity-100 transition-opacity ml-2 mr-2"
|
|
107
|
+
>
|
|
108
|
+
<i
|
|
109
|
+
role="button"
|
|
110
|
+
tabindex="0"
|
|
111
|
+
on:click={(e) => {
|
|
93
112
|
e.stopPropagation();
|
|
94
113
|
copyToClipboard(selectedOrg.orguuid, e);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
{/if}
|
|
104
|
-
</div>
|
|
105
|
-
</Select.Trigger>
|
|
106
|
-
|
|
107
|
-
<Select.Content class="w-full sm:w-[280px]">
|
|
108
|
-
{#each orgs as org}
|
|
109
|
-
<div class="relative group">
|
|
110
|
-
<Select.Item value={org.orguuid} class="pr-12">
|
|
111
|
-
<div class="flex items-center w-full">
|
|
112
|
-
<div class="flex items-center justify-center mr-3">
|
|
113
|
-
{#if org.filesrc}
|
|
114
|
-
<img
|
|
115
|
-
class="h-[25px] w-[25px] object-cover rounded-full"
|
|
116
|
-
src={org.filesrc}
|
|
117
|
-
alt={org.label}
|
|
114
|
+
}}
|
|
115
|
+
on:keydown={(e) => {
|
|
116
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
117
|
+
e.stopPropagation();
|
|
118
|
+
copyToClipboard(selectedOrg.orguuid, e);
|
|
119
|
+
}
|
|
120
|
+
}}
|
|
121
|
+
class="far fa-copy text-surface-400 cursor-pointer"
|
|
118
122
|
/>
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
123
|
+
</div>
|
|
124
|
+
</Tooltip.Trigger>
|
|
125
|
+
<Tooltip.Content>Copy UUID</Tooltip.Content>
|
|
126
|
+
</Tooltip.Root>
|
|
127
|
+
{/if}
|
|
128
|
+
</div>
|
|
129
|
+
</Button>
|
|
130
|
+
</Popover.Trigger>
|
|
131
|
+
|
|
132
|
+
<Popover.Content class="w-full sm:w-[280px] p-0">
|
|
133
|
+
<Command.Root shouldFilter={false}>
|
|
134
|
+
<Command.Input placeholder="Search organizations..." bind:value={searchValue} />
|
|
135
|
+
<Command.Empty>No organizations found.</Command.Empty>
|
|
136
|
+
<Command.Group>
|
|
137
|
+
{#each filteredOrgs as org}
|
|
138
|
+
<div class="relative group">
|
|
139
|
+
<Command.Item
|
|
140
|
+
value={org.orguuid}
|
|
141
|
+
onSelect={() => {
|
|
142
|
+
selectOrg(org.orguuid);
|
|
143
|
+
closeAndFocusTrigger(ids.trigger);
|
|
144
|
+
}}
|
|
145
|
+
class="pr-12"
|
|
146
|
+
>
|
|
147
|
+
<div class="flex items-center w-full">
|
|
148
|
+
<div class="flex items-center justify-center mr-3">
|
|
149
|
+
{#if org.filesrc}
|
|
150
|
+
<img
|
|
151
|
+
class="h-[25px] w-[25px] object-cover rounded-full"
|
|
152
|
+
src={org.filesrc}
|
|
153
|
+
alt={org.label}
|
|
154
|
+
/>
|
|
155
|
+
{:else if org.placeholderColor}
|
|
156
|
+
<div
|
|
157
|
+
class="h-[25px] w-[25px] rounded-full"
|
|
158
|
+
style="background-color: {org.placeholderColor}"
|
|
159
|
+
/>
|
|
160
|
+
{:else}
|
|
161
|
+
<div class="h-[25px] w-[25px] rounded-full bg-surface-100" />
|
|
162
|
+
{/if}
|
|
163
|
+
</div>
|
|
128
164
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
</p>
|
|
133
|
-
{#if org.alert}
|
|
134
|
-
<div class="flex items-center space-x-1">
|
|
135
|
-
<span class="h-[6px] w-[6px] bg-{alertColorMap[org.alert.type]} rounded-full" />
|
|
136
|
-
<p class="text-small italic text-{alertColorMap[org.alert.type]}">
|
|
137
|
-
{org.alert?.message}
|
|
165
|
+
<div class="flex-1 text-left">
|
|
166
|
+
<p class="text-label text-surface-900">
|
|
167
|
+
{org.label}
|
|
138
168
|
</p>
|
|
169
|
+
{#if org.alert}
|
|
170
|
+
<div class="flex items-center space-x-1">
|
|
171
|
+
<span
|
|
172
|
+
class="h-[6px] w-[6px] bg-{alertColorMap[org.alert.type]} rounded-full"
|
|
173
|
+
/>
|
|
174
|
+
<p class="text-small italic text-{alertColorMap[org.alert.type]}">
|
|
175
|
+
{org.alert?.message}
|
|
176
|
+
</p>
|
|
177
|
+
</div>
|
|
178
|
+
{/if}
|
|
139
179
|
</div>
|
|
140
|
-
|
|
180
|
+
</div>
|
|
181
|
+
</Command.Item>
|
|
182
|
+
|
|
183
|
+
<!-- Copy button positioned absolutely -->
|
|
184
|
+
<div class="absolute right-2 top-1/2 -translate-y-1/2">
|
|
185
|
+
<Button
|
|
186
|
+
variant="ghost"
|
|
187
|
+
size="icon"
|
|
188
|
+
class="h-8 w-8 opacity-100 sm:opacity-0 sm:group-hover:opacity-100 transition-opacity"
|
|
189
|
+
on:click={(e) => {
|
|
190
|
+
e.stopPropagation();
|
|
191
|
+
copyToClipboard(org.orguuid, e);
|
|
192
|
+
}}
|
|
193
|
+
>
|
|
194
|
+
<i class="far fa-copy text-surface-400" />
|
|
195
|
+
</Button>
|
|
141
196
|
</div>
|
|
142
197
|
</div>
|
|
143
|
-
|
|
198
|
+
{/each}
|
|
199
|
+
</Command.Group>
|
|
144
200
|
|
|
145
|
-
|
|
146
|
-
<
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
</div>
|
|
159
|
-
</div>
|
|
160
|
-
{/each}
|
|
161
|
-
|
|
162
|
-
{#if createOrgLink}
|
|
163
|
-
<Select.Separator />
|
|
164
|
-
<a
|
|
165
|
-
href={createOrgLink}
|
|
166
|
-
class="flex items-center px-8 py-2 text-sm text-primary-500 hover:bg-accent rounded-sm"
|
|
167
|
-
>
|
|
168
|
-
<i class="far fa-plus mr-2" />
|
|
169
|
-
<span>Create org</span>
|
|
170
|
-
</a>
|
|
171
|
-
{/if}
|
|
172
|
-
</Select.Content>
|
|
173
|
-
</Select.Root>
|
|
201
|
+
{#if createOrgLink}
|
|
202
|
+
<Command.Separator />
|
|
203
|
+
<a
|
|
204
|
+
href={createOrgLink}
|
|
205
|
+
class="flex items-center px-8 py-2 text-sm text-primary-500 hover:bg-accent rounded-sm"
|
|
206
|
+
>
|
|
207
|
+
<i class="far fa-plus mr-2" />
|
|
208
|
+
<span>Create org</span>
|
|
209
|
+
</a>
|
|
210
|
+
{/if}
|
|
211
|
+
</Command.Root>
|
|
212
|
+
</Popover.Content>
|
|
213
|
+
</Popover.Root>
|
|
@@ -4,7 +4,7 @@ declare const __propDef: {
|
|
|
4
4
|
[x: string]: any;
|
|
5
5
|
class?: string | undefined;
|
|
6
6
|
href?: string | undefined | undefined;
|
|
7
|
-
variant?: "secondary" | "
|
|
7
|
+
variant?: "secondary" | "outline" | "default" | "destructive" | undefined;
|
|
8
8
|
as?: "span" | "a" | "button" | undefined;
|
|
9
9
|
};
|
|
10
10
|
events: {
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export { default as HorizontalTabs } from "./components/HorizontalTabs.svelte";
|
|
|
2
2
|
export { default as ProfileMenu } from "./components/ProfileMenu.svelte";
|
|
3
3
|
export { default as Breadcrumbs } from "./components/Breadcrumbs.svelte";
|
|
4
4
|
export { default as OrgSwitcher } from "./components/OrgSwitcher.svelte";
|
|
5
|
+
export { default as OrgSwitcherNew } from "./components/OrgSwitcherNew.svelte";
|
|
5
6
|
export { default as Checkbox } from "./components/fields/Checkbox.svelte";
|
|
6
7
|
export { default as Radio } from "./components/fields/Radio.svelte";
|
|
7
8
|
export { default as SideNavItem } from "./components/SideNav/SideNavItem.svelte";
|
package/dist/index.js
CHANGED
|
@@ -7,6 +7,7 @@ export { default as HorizontalTabs } from "./components/HorizontalTabs.svelte";
|
|
|
7
7
|
export { default as ProfileMenu } from "./components/ProfileMenu.svelte";
|
|
8
8
|
export { default as Breadcrumbs } from "./components/Breadcrumbs.svelte";
|
|
9
9
|
export { default as OrgSwitcher } from "./components/OrgSwitcher.svelte";
|
|
10
|
+
export { default as OrgSwitcherNew } from "./components/OrgSwitcherNew.svelte";
|
|
10
11
|
export { default as Checkbox } from "./components/fields/Checkbox.svelte";
|
|
11
12
|
export { default as Radio } from "./components/fields/Radio.svelte";
|
|
12
13
|
export { default as SideNavItem } from "./components/SideNav/SideNavItem.svelte";
|