@burdenoff/microfe-comradecircle 2026.704.1 → 2026.704.3
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.
- package/dist/comradecircle/components/Avatar.js +52 -17
- package/dist/comradecircle/components/Avatar.js.map +1 -1
- package/dist/comradecircle/components/AvatarUploadField.js +91 -0
- package/dist/comradecircle/components/AvatarUploadField.js.map +1 -0
- package/dist/comradecircle/components/CircleCard.js +55 -52
- package/dist/comradecircle/components/CircleCard.js.map +1 -1
- package/dist/comradecircle/components/CommentThread.js +80 -64
- package/dist/comradecircle/components/CommentThread.js.map +1 -1
- package/dist/comradecircle/components/CreateCircleDialog.js +74 -63
- package/dist/comradecircle/components/CreateCircleDialog.js.map +1 -1
- package/dist/comradecircle/components/EventCard.js +84 -58
- package/dist/comradecircle/components/EventCard.js.map +1 -1
- package/dist/comradecircle/components/FileImage.js +20 -0
- package/dist/comradecircle/components/FileImage.js.map +1 -0
- package/dist/comradecircle/components/ImageAttachments.js +97 -0
- package/dist/comradecircle/components/ImageAttachments.js.map +1 -0
- package/dist/comradecircle/components/MemberIdentity.js +4 -2
- package/dist/comradecircle/components/MemberIdentity.js.map +1 -1
- package/dist/comradecircle/components/PollCard.js +65 -44
- package/dist/comradecircle/components/PollCard.js.map +1 -1
- package/dist/comradecircle/components/PostCard.js +8 -15
- package/dist/comradecircle/components/PostCard.js.map +1 -1
- package/dist/comradecircle/components/PostComposer.js +45 -35
- package/dist/comradecircle/components/PostComposer.js.map +1 -1
- package/dist/comradecircle/components/ReactionBar.js +1 -1
- package/dist/comradecircle/components/ReactionBar.js.map +1 -1
- package/dist/comradecircle/components/StateViews.js +1 -16
- package/dist/comradecircle/components/StateViews.js.map +1 -1
- package/dist/comradecircle/components/StatusBadge.js +1 -1
- package/dist/comradecircle/components/StatusBadge.js.map +1 -1
- package/dist/comradecircle/hooks/index.js +1 -0
- package/dist/comradecircle/hooks/useComradeCircleApi.js +244 -241
- package/dist/comradecircle/hooks/useComradeCircleApi.js.map +1 -1
- package/dist/comradecircle/hooks/useFiles.js +78 -0
- package/dist/comradecircle/hooks/useFiles.js.map +1 -0
- package/dist/comradecircle/lib/graphql-cache.js +9 -0
- package/dist/comradecircle/lib/graphql-cache.js.map +1 -0
- package/dist/comradecircle/pages/FeedPage.js +79 -33
- package/dist/comradecircle/pages/FeedPage.js.map +1 -1
- package/dist/comradecircle/pages/circles/CircleDetailPage.js +354 -242
- package/dist/comradecircle/pages/circles/CircleDetailPage.js.map +1 -1
- package/dist/comradecircle/pages/circles/CirclesPage.js +97 -47
- package/dist/comradecircle/pages/circles/CirclesPage.js.map +1 -1
- package/dist/comradecircle/pages/events/EventDetailPage.js +193 -126
- package/dist/comradecircle/pages/events/EventDetailPage.js.map +1 -1
- package/dist/comradecircle/pages/events/EventsPage.js +74 -34
- package/dist/comradecircle/pages/events/EventsPage.js.map +1 -1
- package/dist/comradecircle/pages/members/MemberProfilePage.js +154 -81
- package/dist/comradecircle/pages/members/MemberProfilePage.js.map +1 -1
- package/dist/comradecircle/pages/members/MembersPage.js +141 -71
- package/dist/comradecircle/pages/members/MembersPage.js.map +1 -1
- package/dist/comradecircle/pages/profile/MyProfilePage.js +298 -191
- package/dist/comradecircle/pages/profile/MyProfilePage.js.map +1 -1
- package/package.json +1 -1
|
@@ -7,146 +7,216 @@ import "../../hooks/index.js";
|
|
|
7
7
|
import { Avatar as s } from "../../components/Avatar.js";
|
|
8
8
|
import { describeError as c, notify as l } from "../../lib/toast.js";
|
|
9
9
|
import { EmptyState as u } from "../../components/EmptyState.js";
|
|
10
|
-
import { ErrorView as d
|
|
11
|
-
import { Pagination as
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import { Button as S, GlassCard as C, Input as w } from "@burdenoff/fe-libs/ui";
|
|
10
|
+
import { ErrorView as d } from "../../components/StateViews.js";
|
|
11
|
+
import { Pagination as f } from "../../components/Pagination.js";
|
|
12
|
+
import { useMemo as p, useState as m } from "react";
|
|
13
|
+
import { Check as h, Loader2 as g, Search as _, UserMinus as v, UserPlus as y } from "lucide-react";
|
|
14
|
+
import { Fragment as b, jsx as x, jsxs as S } from "react/jsx-runtime";
|
|
15
|
+
import { Button as C, GlassCard as w, Input as T, Skeleton as E } from "@burdenoff/fe-libs/ui";
|
|
17
16
|
//#region src/comradecircle/pages/members/MembersPage.tsx
|
|
18
|
-
var
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
var D = 12, O = [
|
|
18
|
+
"s1",
|
|
19
|
+
"s2",
|
|
20
|
+
"s3",
|
|
21
|
+
"s4",
|
|
22
|
+
"s5",
|
|
23
|
+
"s6",
|
|
24
|
+
"s7",
|
|
25
|
+
"s8"
|
|
26
|
+
];
|
|
27
|
+
function k() {
|
|
28
|
+
return /* @__PURE__ */ S(w, {
|
|
29
|
+
treatment: "plain",
|
|
30
|
+
className: "flex flex-col p-5",
|
|
31
|
+
children: [
|
|
32
|
+
/* @__PURE__ */ S("div", {
|
|
33
|
+
className: "flex items-start gap-3",
|
|
34
|
+
children: [/* @__PURE__ */ x(E, { className: "h-14 w-14 rounded-full" }), /* @__PURE__ */ S("div", {
|
|
35
|
+
className: "min-w-0 flex-1 space-y-2 py-1",
|
|
36
|
+
children: [
|
|
37
|
+
/* @__PURE__ */ x(E, { className: "h-4 w-2/3" }),
|
|
38
|
+
/* @__PURE__ */ x(E, { className: "h-3 w-1/2" }),
|
|
39
|
+
/* @__PURE__ */ x(E, { className: "h-3 w-4/5" })
|
|
40
|
+
]
|
|
41
|
+
})]
|
|
42
|
+
}),
|
|
43
|
+
/* @__PURE__ */ S("div", {
|
|
44
|
+
className: "mt-3 flex flex-wrap gap-1.5",
|
|
45
|
+
children: [/* @__PURE__ */ x(E, { className: "h-5 w-16 rounded-full" }), /* @__PURE__ */ x(E, { className: "h-5 w-20 rounded-full" })]
|
|
46
|
+
}),
|
|
47
|
+
/* @__PURE__ */ x("div", {
|
|
48
|
+
className: "mt-4 flex justify-end border-t border-border-seam pt-3",
|
|
49
|
+
children: /* @__PURE__ */ x(E, { className: "h-8 w-28 rounded-button" })
|
|
50
|
+
})
|
|
51
|
+
]
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
function A() {
|
|
55
|
+
let { navigateTo: A, currentUser: j } = e(), M = o(), [N, P] = m(""), [F, I] = m(null), { data: L, isLoading: R, isError: z, refetch: B } = i({
|
|
21
56
|
discoverable: !0,
|
|
22
57
|
pagination: {
|
|
23
|
-
limit:
|
|
24
|
-
cursor:
|
|
58
|
+
limit: D,
|
|
59
|
+
cursor: M.cursor
|
|
25
60
|
}
|
|
26
|
-
}), { data:
|
|
27
|
-
let e =
|
|
28
|
-
return e ?
|
|
61
|
+
}), { data: V } = r("MEMBER"), H = n(), U = a(), W = p(() => new Set((V ?? []).map((e) => e.targetId)), [V]), G = p(() => L?.items ?? [], [L]), K = p(() => {
|
|
62
|
+
let e = N.trim().toLowerCase();
|
|
63
|
+
return e ? G.filter((t) => [
|
|
29
64
|
t.displayName,
|
|
30
65
|
t.headline ?? "",
|
|
31
66
|
...t.skills,
|
|
32
67
|
...t.interests
|
|
33
|
-
].join(" ").toLowerCase().includes(e)) :
|
|
34
|
-
}, [
|
|
35
|
-
let t =
|
|
68
|
+
].join(" ").toLowerCase().includes(e)) : G;
|
|
69
|
+
}, [G, N]), q = async (e) => {
|
|
70
|
+
let t = W.has(e.memberId), n = {
|
|
36
71
|
targetId: e.memberId,
|
|
37
72
|
targetType: "MEMBER"
|
|
38
73
|
};
|
|
39
|
-
|
|
74
|
+
I(e.memberId);
|
|
40
75
|
try {
|
|
41
|
-
t ? (await
|
|
76
|
+
t ? (await U.mutateAsync(n), l.success("Unfollowed", e.displayName)) : (await H.mutateAsync(n), l.success("Following", e.displayName));
|
|
42
77
|
} catch (e) {
|
|
43
78
|
l.error(t ? "Could not unfollow" : "Could not follow", c(e));
|
|
44
79
|
} finally {
|
|
45
|
-
|
|
80
|
+
I(null);
|
|
46
81
|
}
|
|
47
82
|
};
|
|
48
|
-
return /* @__PURE__ */
|
|
83
|
+
return /* @__PURE__ */ x(t, {
|
|
49
84
|
title: "Members",
|
|
50
85
|
description: "Discover and follow people across your circles — search by name, headline, or skills.",
|
|
51
|
-
children:
|
|
86
|
+
children: R ? /* @__PURE__ */ S("div", {
|
|
87
|
+
className: "flex flex-col gap-5",
|
|
88
|
+
children: [/* @__PURE__ */ x(E, { className: "h-9 w-full max-w-sm rounded-button" }), /* @__PURE__ */ x("div", {
|
|
89
|
+
className: "grid gap-4 sm:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4",
|
|
90
|
+
children: O.map((e) => /* @__PURE__ */ x(k, {}, e))
|
|
91
|
+
})]
|
|
92
|
+
}) : z ? /* @__PURE__ */ x(d, {
|
|
52
93
|
message: "We couldn't load the member directory.",
|
|
53
|
-
onRetry: () =>
|
|
54
|
-
}) :
|
|
94
|
+
onRetry: () => B()
|
|
95
|
+
}) : G.length === 0 && M.page === 0 ? /* @__PURE__ */ x(u, {
|
|
55
96
|
illustration: "empty-people",
|
|
56
97
|
title: "No members to discover yet",
|
|
57
98
|
description: "When members make their profiles discoverable, they'll show up here for you to follow."
|
|
58
|
-
}) : /* @__PURE__ */
|
|
99
|
+
}) : /* @__PURE__ */ S("div", {
|
|
59
100
|
className: "flex flex-col gap-5",
|
|
60
101
|
children: [
|
|
61
|
-
/* @__PURE__ */
|
|
102
|
+
/* @__PURE__ */ S("div", {
|
|
62
103
|
className: "relative w-full max-w-sm",
|
|
63
|
-
children: [/* @__PURE__ */
|
|
104
|
+
children: [/* @__PURE__ */ x(_, {
|
|
64
105
|
className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-tertiary",
|
|
65
106
|
"aria-hidden": "true"
|
|
66
|
-
}), /* @__PURE__ */
|
|
67
|
-
value:
|
|
68
|
-
onChange: (e) =>
|
|
107
|
+
}), /* @__PURE__ */ x(T, {
|
|
108
|
+
value: N,
|
|
109
|
+
onChange: (e) => P(e.target.value),
|
|
69
110
|
placeholder: "Search by name, headline, or skills",
|
|
70
111
|
"aria-label": "Search members",
|
|
71
112
|
className: "pl-9"
|
|
72
113
|
})]
|
|
73
114
|
}),
|
|
74
|
-
|
|
75
|
-
icon: /* @__PURE__ */
|
|
115
|
+
K.length === 0 ? /* @__PURE__ */ x(u, {
|
|
116
|
+
icon: /* @__PURE__ */ x(_, { className: "h-9 w-9" }),
|
|
76
117
|
title: "No matches on this page",
|
|
77
118
|
description: "No members on this page match your search. Try a different term or browse another page."
|
|
78
|
-
}) : /* @__PURE__ */ b("
|
|
79
|
-
className: "
|
|
80
|
-
children:
|
|
81
|
-
|
|
82
|
-
|
|
119
|
+
}) : /* @__PURE__ */ S(b, { children: [/* @__PURE__ */ S("p", {
|
|
120
|
+
className: "text-xs font-medium text-text-tertiary",
|
|
121
|
+
children: [
|
|
122
|
+
"Showing ",
|
|
123
|
+
K.length,
|
|
124
|
+
" member",
|
|
125
|
+
K.length === 1 ? "" : "s"
|
|
126
|
+
]
|
|
127
|
+
}), /* @__PURE__ */ x("div", {
|
|
128
|
+
className: "grid gap-4 sm:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4",
|
|
129
|
+
children: K.map((e) => {
|
|
130
|
+
let t = !!(j?.id && e.memberId === j.id), n = W.has(e.memberId), r = F === e.memberId, i = Array.from(new Set([...e.skills, ...e.interests])).slice(0, 4);
|
|
131
|
+
return /* @__PURE__ */ S(w, {
|
|
83
132
|
treatment: "plain",
|
|
84
|
-
className: "flex flex-col p-5",
|
|
133
|
+
className: "flex flex-col p-5 transition-all duration-200 motion-safe:hover:-translate-y-0.5 hover:border-[var(--color-accent-soft)]",
|
|
85
134
|
children: [
|
|
86
|
-
/* @__PURE__ */
|
|
87
|
-
|
|
88
|
-
|
|
135
|
+
/* @__PURE__ */ S("button", {
|
|
136
|
+
type: "button",
|
|
137
|
+
onClick: () => A(`members/${e.memberId}`),
|
|
138
|
+
"aria-label": `View ${e.displayName}'s profile`,
|
|
139
|
+
className: "group/head flex w-full items-start gap-3 rounded-lg text-left outline-none focus-visible:ring-1 focus-visible:ring-[var(--color-focus-ring)]",
|
|
140
|
+
children: [/* @__PURE__ */ x(s, {
|
|
89
141
|
name: e.displayName,
|
|
90
142
|
presence: e.presence,
|
|
91
|
-
size: "lg"
|
|
92
|
-
|
|
143
|
+
size: "lg",
|
|
144
|
+
fileId: e.avatar?.id,
|
|
145
|
+
seed: e.memberId
|
|
146
|
+
}), /* @__PURE__ */ S("div", {
|
|
93
147
|
className: "min-w-0 flex-1",
|
|
94
148
|
children: [
|
|
95
|
-
/* @__PURE__ */
|
|
96
|
-
|
|
97
|
-
onClick: () => E(`members/${e.memberId}`),
|
|
98
|
-
className: "block max-w-full truncate text-left text-base font-semibold text-text-primary hover:underline",
|
|
149
|
+
/* @__PURE__ */ x("span", {
|
|
150
|
+
className: "block max-w-full truncate text-base font-semibold text-text-primary group-hover/head:underline",
|
|
99
151
|
children: e.displayName
|
|
100
152
|
}),
|
|
101
|
-
e.headline && /* @__PURE__ */
|
|
153
|
+
e.headline && /* @__PURE__ */ x("p", {
|
|
102
154
|
className: "truncate text-sm text-text-secondary",
|
|
103
155
|
children: e.headline
|
|
104
156
|
}),
|
|
105
|
-
/* @__PURE__ */
|
|
106
|
-
className: "mt-
|
|
107
|
-
children:
|
|
157
|
+
e.bio && /* @__PURE__ */ x("p", {
|
|
158
|
+
className: "mt-0.5 line-clamp-1 text-xs text-text-tertiary",
|
|
159
|
+
children: e.bio
|
|
108
160
|
})
|
|
109
161
|
]
|
|
110
162
|
})]
|
|
111
163
|
}),
|
|
112
|
-
|
|
164
|
+
i.length > 0 && /* @__PURE__ */ x("div", {
|
|
113
165
|
className: "mt-3 flex flex-wrap gap-1.5",
|
|
114
|
-
children:
|
|
166
|
+
children: i.map((e) => /* @__PURE__ */ x("span", {
|
|
115
167
|
className: "rounded-full bg-bg-sunken px-2 py-0.5 text-xs font-medium text-text-secondary",
|
|
116
168
|
children: e
|
|
117
169
|
}, e))
|
|
118
170
|
}),
|
|
119
|
-
!t && /* @__PURE__ */
|
|
171
|
+
!t && /* @__PURE__ */ x("div", {
|
|
120
172
|
className: "mt-4 flex items-center justify-end border-t border-border-seam pt-3",
|
|
121
|
-
children: n ? /* @__PURE__ */ x(
|
|
173
|
+
children: n ? /* @__PURE__ */ x(C, {
|
|
122
174
|
size: "sm",
|
|
123
175
|
variant: "outline",
|
|
124
|
-
onClick: () =>
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
176
|
+
onClick: (t) => {
|
|
177
|
+
t.stopPropagation(), q(e);
|
|
178
|
+
},
|
|
179
|
+
disabled: r,
|
|
180
|
+
"aria-label": `Following ${e.displayName}. Activate to unfollow.`,
|
|
181
|
+
className: "group/follow min-w-[7.5rem] justify-center hover:border-status-error-border hover:bg-status-error-bg-subtle hover:text-status-error-text",
|
|
182
|
+
children: r ? /* @__PURE__ */ S(b, { children: [/* @__PURE__ */ x(g, { className: "motion-safe:animate-spin" }), /* @__PURE__ */ x("span", { children: "Following" })] }) : /* @__PURE__ */ S(b, { children: [
|
|
183
|
+
/* @__PURE__ */ x(h, { className: "group-hover/follow:hidden" }),
|
|
184
|
+
/* @__PURE__ */ x(v, { className: "hidden group-hover/follow:inline" }),
|
|
185
|
+
/* @__PURE__ */ x("span", {
|
|
186
|
+
className: "group-hover/follow:hidden",
|
|
187
|
+
children: "Following"
|
|
188
|
+
}),
|
|
189
|
+
/* @__PURE__ */ x("span", {
|
|
190
|
+
className: "hidden group-hover/follow:inline",
|
|
191
|
+
children: "Unfollow"
|
|
192
|
+
})
|
|
193
|
+
] })
|
|
194
|
+
}) : /* @__PURE__ */ S(C, {
|
|
128
195
|
size: "sm",
|
|
129
|
-
onClick: () =>
|
|
130
|
-
|
|
131
|
-
|
|
196
|
+
onClick: (t) => {
|
|
197
|
+
t.stopPropagation(), q(e);
|
|
198
|
+
},
|
|
199
|
+
disabled: r,
|
|
200
|
+
className: "min-w-[7.5rem] justify-center",
|
|
201
|
+
children: [r ? /* @__PURE__ */ x(g, { className: "motion-safe:animate-spin" }) : /* @__PURE__ */ x(y, {}), "Follow"]
|
|
132
202
|
})
|
|
133
203
|
})
|
|
134
204
|
]
|
|
135
205
|
}, e.id);
|
|
136
206
|
})
|
|
137
|
-
}),
|
|
138
|
-
/* @__PURE__ */
|
|
139
|
-
page:
|
|
140
|
-
pageSize:
|
|
141
|
-
itemCount:
|
|
142
|
-
hasMore:
|
|
143
|
-
onPageChange: (e) =>
|
|
207
|
+
})] }),
|
|
208
|
+
/* @__PURE__ */ x(f, {
|
|
209
|
+
page: M.page,
|
|
210
|
+
pageSize: D,
|
|
211
|
+
itemCount: G.length,
|
|
212
|
+
hasMore: L?.pageInfo.hasMore ?? !1,
|
|
213
|
+
onPageChange: (e) => M.onPageChange(e, L?.pageInfo.cursor)
|
|
144
214
|
})
|
|
145
215
|
]
|
|
146
216
|
})
|
|
147
217
|
});
|
|
148
218
|
}
|
|
149
219
|
//#endregion
|
|
150
|
-
export {
|
|
220
|
+
export { A as MembersPage };
|
|
151
221
|
|
|
152
222
|
//# sourceMappingURL=MembersPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MembersPage.js","names":[],"sources":["../../../../src/comradecircle/pages/members/MembersPage.tsx"],"sourcesContent":["/**\n * MembersPage — the discoverable member directory.\n * @module comradecircle/pages/members\n *\n * Reads `comListProfiles(discoverable: true)` — every member who has opted into\n * discovery via their {@link ComProfile}. Each card resolves display identity\n * from the social-identity layer (never a raw actor id), links to the member's\n * public profile, and offers a Follow/Following toggle wired to `comFollow` /\n * `comUnfollow` (targetType MEMBER). An optional client-side search narrows the\n * current page by name, headline, skills, or interests.\n */\n\nimport { useMemo, useState } from 'react';\nimport { Search, UserPlus, Check } from 'lucide-react';\nimport { GlassCard, Button, Input } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { Avatar } from '../../components/Avatar';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { EmptyState } from '../../components/EmptyState';\nimport { LoadingView, ErrorView } from '../../components/StateViews';\nimport { Pagination } from '../../components/Pagination';\nimport {\n useComProfiles,\n useComMyFollows,\n useComFollow,\n useComUnfollow,\n useCursorPager,\n} from '../../hooks';\nimport { useComradeCircle } from '../../context';\nimport { notify, describeError } from '../../lib/toast';\nimport type { ComProfile } from '../../types';\n\nconst PAGE_SIZE = 12;\n\nexport function MembersPage() {\n const { navigateTo, currentUser } = useComradeCircle();\n const pager = useCursorPager();\n const [search, setSearch] = useState('');\n const [pendingId, setPendingId] = useState<string | null>(null);\n\n const { data, isLoading, isError, refetch } = useComProfiles({\n discoverable: true,\n pagination: { limit: PAGE_SIZE, cursor: pager.cursor },\n });\n\n const { data: follows } = useComMyFollows('MEMBER');\n const follow = useComFollow();\n const unfollow = useComUnfollow();\n\n const followSet = useMemo(() => new Set((follows ?? []).map((f) => f.targetId)), [follows]);\n\n const profiles = useMemo(() => data?.items ?? [], [data]);\n\n const visible = useMemo(() => {\n const q = search.trim().toLowerCase();\n if (!q) return profiles;\n return profiles.filter((p) => {\n const haystack = [p.displayName, p.headline ?? '', ...p.skills, ...p.interests]\n .join(' ')\n .toLowerCase();\n return haystack.includes(q);\n });\n }, [profiles, search]);\n\n const toggleFollow = async (profile: ComProfile) => {\n const wasFollowing = followSet.has(profile.memberId);\n const input = { targetId: profile.memberId, targetType: 'MEMBER' as const };\n setPendingId(profile.memberId);\n try {\n if (wasFollowing) {\n await unfollow.mutateAsync(input);\n notify.success('Unfollowed', profile.displayName);\n } else {\n await follow.mutateAsync(input);\n notify.success('Following', profile.displayName);\n }\n } catch (err) {\n notify.error(wasFollowing ? 'Could not unfollow' : 'Could not follow', describeError(err));\n } finally {\n setPendingId(null);\n }\n };\n\n return (\n <PageLayout\n title=\"Members\"\n description=\"Discover and follow people across your circles — search by name, headline, or skills.\"\n >\n {isLoading ? (\n <LoadingView label=\"Loading members…\" />\n ) : isError ? (\n <ErrorView message=\"We couldn't load the member directory.\" onRetry={() => refetch()} />\n ) : profiles.length === 0 && pager.page === 0 ? (\n <EmptyState\n illustration=\"empty-people\"\n title=\"No members to discover yet\"\n description=\"When members make their profiles discoverable, they'll show up here for you to follow.\"\n />\n ) : (\n <div className=\"flex flex-col gap-5\">\n <div className=\"relative w-full max-w-sm\">\n <Search\n className=\"pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-tertiary\"\n aria-hidden=\"true\"\n />\n <Input\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n placeholder=\"Search by name, headline, or skills\"\n aria-label=\"Search members\"\n className=\"pl-9\"\n />\n </div>\n\n {visible.length === 0 ? (\n <EmptyState\n icon={<Search className=\"h-9 w-9\" />}\n title=\"No matches on this page\"\n description=\"No members on this page match your search. Try a different term or browse another page.\"\n />\n ) : (\n <div className=\"grid gap-4 sm:grid-cols-2 xl:grid-cols-3\">\n {visible.map((p) => {\n const isSelf = Boolean(currentUser?.id && p.memberId === currentUser.id);\n const isFollowing = followSet.has(p.memberId);\n const chips = Array.from(new Set([...p.skills, ...p.interests])).slice(0, 4);\n\n return (\n <GlassCard key={p.id} treatment=\"plain\" className=\"flex flex-col p-5\">\n <div className=\"flex items-start gap-3\">\n <Avatar name={p.displayName} presence={p.presence} size=\"lg\" />\n <div className=\"min-w-0 flex-1\">\n <button\n type=\"button\"\n onClick={() => navigateTo(`members/${p.memberId}`)}\n className=\"block max-w-full truncate text-left text-base font-semibold text-text-primary hover:underline\"\n >\n {p.displayName}\n </button>\n {p.headline && (\n <p className=\"truncate text-sm text-text-secondary\">{p.headline}</p>\n )}\n <div className=\"mt-1.5\">\n <StatusBadge status={p.presence} />\n </div>\n </div>\n </div>\n\n {chips.length > 0 && (\n <div className=\"mt-3 flex flex-wrap gap-1.5\">\n {chips.map((chip) => (\n <span\n key={chip}\n className=\"rounded-full bg-bg-sunken px-2 py-0.5 text-xs font-medium text-text-secondary\"\n >\n {chip}\n </span>\n ))}\n </div>\n )}\n\n {!isSelf && (\n <div className=\"mt-4 flex items-center justify-end border-t border-border-seam pt-3\">\n {isFollowing ? (\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => toggleFollow(p)}\n disabled={pendingId === p.memberId}\n >\n <Check className=\"mr-1.5 h-4 w-4\" /> Following\n </Button>\n ) : (\n <Button\n size=\"sm\"\n onClick={() => toggleFollow(p)}\n disabled={pendingId === p.memberId}\n >\n <UserPlus className=\"mr-1.5 h-4 w-4\" /> Follow\n </Button>\n )}\n </div>\n )}\n </GlassCard>\n );\n })}\n </div>\n )}\n\n <Pagination\n page={pager.page}\n pageSize={PAGE_SIZE}\n itemCount={profiles.length}\n hasMore={data?.pageInfo.hasMore ?? false}\n onPageChange={(target) => pager.onPageChange(target, data?.pageInfo.cursor)}\n />\n </div>\n )}\n </PageLayout>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAgCA,IAAM,IAAY;AAElB,SAAgB,IAAc;CAC5B,IAAM,EAAE,eAAY,mBAAgB,GAAkB,EAChD,IAAQ,GAAgB,EACxB,CAAC,GAAQ,KAAa,EAAS,GAAG,EAClC,CAAC,GAAW,KAAgB,EAAwB,KAAK,EAEzD,EAAE,SAAM,cAAW,YAAS,eAAY,EAAe;EAC3D,cAAc;EACd,YAAY;GAAE,OAAO;GAAW,QAAQ,EAAM;GAAQ;EACvD,CAAC,EAEI,EAAE,MAAM,MAAY,EAAgB,SAAS,EAC7C,IAAS,GAAc,EACvB,IAAW,GAAgB,EAE3B,IAAY,QAAc,IAAI,KAAK,KAAW,EAAE,EAAE,KAAK,MAAM,EAAE,SAAS,CAAC,EAAE,CAAC,EAAQ,CAAC,EAErF,IAAW,QAAc,GAAM,SAAS,EAAE,EAAE,CAAC,EAAK,CAAC,EAEnD,IAAU,QAAc;EAC5B,IAAM,IAAI,EAAO,MAAM,CAAC,aAAa;AAErC,SADK,IACE,EAAS,QAAQ,MACL;GAAC,EAAE;GAAa,EAAE,YAAY;GAAI,GAAG,EAAE;GAAQ,GAAG,EAAE;GAAU,CAC5E,KAAK,IAAI,CACT,aAAa,CACA,SAAS,EAAE,CAC3B,GANa;IAOd,CAAC,GAAU,EAAO,CAAC,EAEhB,IAAe,OAAO,MAAwB;EAClD,IAAM,IAAe,EAAU,IAAI,EAAQ,SAAS,EAC9C,IAAQ;GAAE,UAAU,EAAQ;GAAU,YAAY;GAAmB;AAC3E,IAAa,EAAQ,SAAS;AAC9B,MAAI;AACF,GAAI,KACF,MAAM,EAAS,YAAY,EAAM,EACjC,EAAO,QAAQ,cAAc,EAAQ,YAAY,KAEjD,MAAM,EAAO,YAAY,EAAM,EAC/B,EAAO,QAAQ,aAAa,EAAQ,YAAY;WAE3C,GAAK;AACZ,KAAO,MAAM,IAAe,uBAAuB,oBAAoB,EAAc,EAAI,CAAC;YAClF;AACR,KAAa,KAAK;;;AAItB,QACE,kBAAC,GAAD;EACE,OAAM;EACN,aAAY;YAEX,IACC,kBAAC,GAAD,EAAa,OAAM,oBAAqB,CAAA,GACtC,IACF,kBAAC,GAAD;GAAW,SAAQ;GAAyC,eAAe,GAAS;GAAI,CAAA,GACtF,EAAS,WAAW,KAAK,EAAM,SAAS,IAC1C,kBAAC,GAAD;GACE,cAAa;GACb,OAAM;GACN,aAAY;GACZ,CAAA,GAEF,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,GAAD;MACE,WAAU;MACV,eAAY;MACZ,CAAA,EACF,kBAAC,GAAD;MACE,OAAO;MACP,WAAW,MAAM,EAAU,EAAE,OAAO,MAAM;MAC1C,aAAY;MACZ,cAAW;MACX,WAAU;MACV,CAAA,CACE;;IAEL,EAAQ,WAAW,IAClB,kBAAC,GAAD;KACE,MAAM,kBAAC,GAAD,EAAQ,WAAU,WAAY,CAAA;KACpC,OAAM;KACN,aAAY;KACZ,CAAA,GAEF,kBAAC,OAAD;KAAK,WAAU;eACZ,EAAQ,KAAK,MAAM;MAClB,IAAM,IAAS,GAAQ,GAAa,MAAM,EAAE,aAAa,EAAY,KAC/D,IAAc,EAAU,IAAI,EAAE,SAAS,EACvC,IAAQ,MAAM,KAAK,IAAI,IAAI,CAAC,GAAG,EAAE,QAAQ,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,MAAM,GAAG,EAAE;AAE5E,aACE,kBAAC,GAAD;OAAsB,WAAU;OAAQ,WAAU;iBAAlD;QACE,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,GAAD;UAAQ,MAAM,EAAE;UAAa,UAAU,EAAE;UAAU,MAAK;UAAO,CAAA,EAC/D,kBAAC,OAAD;UAAK,WAAU;oBAAf;WACE,kBAAC,UAAD;YACE,MAAK;YACL,eAAe,EAAW,WAAW,EAAE,WAAW;YAClD,WAAU;sBAET,EAAE;YACI,CAAA;WACR,EAAE,YACD,kBAAC,KAAD;YAAG,WAAU;sBAAwC,EAAE;YAAa,CAAA;WAEtE,kBAAC,OAAD;YAAK,WAAU;sBACb,kBAAC,GAAD,EAAa,QAAQ,EAAE,UAAY,CAAA;YAC/B,CAAA;WACF;YACF;;QAEL,EAAM,SAAS,KACd,kBAAC,OAAD;SAAK,WAAU;mBACZ,EAAM,KAAK,MACV,kBAAC,QAAD;UAEE,WAAU;oBAET;UACI,EAJA,EAIA,CACP;SACE,CAAA;QAGP,CAAC,KACA,kBAAC,OAAD;SAAK,WAAU;mBACZ,IACC,kBAAC,GAAD;UACE,MAAK;UACL,SAAQ;UACR,eAAe,EAAa,EAAE;UAC9B,UAAU,MAAc,EAAE;oBAJ5B,CAME,kBAAC,GAAD,EAAO,WAAU,kBAAmB,CAAA,EAAA,aAC7B;cAET,kBAAC,GAAD;UACE,MAAK;UACL,eAAe,EAAa,EAAE;UAC9B,UAAU,MAAc,EAAE;oBAH5B,CAKE,kBAAC,GAAD,EAAU,WAAU,kBAAmB,CAAA,EAAA,UAChC;;SAEP,CAAA;QAEE;SAvDI,EAAE,GAuDN;OAEd;KACE,CAAA;IAGR,kBAAC,GAAD;KACE,MAAM,EAAM;KACZ,UAAU;KACV,WAAW,EAAS;KACpB,SAAS,GAAM,SAAS,WAAW;KACnC,eAAe,MAAW,EAAM,aAAa,GAAQ,GAAM,SAAS,OAAO;KAC3E,CAAA;IACE;;EAEG,CAAA"}
|
|
1
|
+
{"version":3,"file":"MembersPage.js","names":[],"sources":["../../../../src/comradecircle/pages/members/MembersPage.tsx"],"sourcesContent":["/**\n * MembersPage — the discoverable member directory.\n * @module comradecircle/pages/members\n *\n * Reads `comListProfiles(discoverable: true)` — every member who has opted into\n * discovery via their {@link ComProfile}. Each card resolves display identity\n * from the social-identity layer (never a raw actor id), links to the member's\n * public profile, and offers a Follow/Following toggle wired to `comFollow` /\n * `comUnfollow` (targetType MEMBER). An optional client-side search narrows the\n * current page by name, headline, skills, or interests.\n */\n\nimport { useMemo, useState } from 'react';\nimport { Search, UserPlus, UserMinus, Check, Loader2 } from 'lucide-react';\nimport { GlassCard, Button, Input, Skeleton } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { Avatar } from '../../components/Avatar';\nimport { EmptyState } from '../../components/EmptyState';\nimport { ErrorView } from '../../components/StateViews';\nimport { Pagination } from '../../components/Pagination';\nimport {\n useComProfiles,\n useComMyFollows,\n useComFollow,\n useComUnfollow,\n useCursorPager,\n} from '../../hooks';\nimport { useComradeCircle } from '../../context';\nimport { notify, describeError } from '../../lib/toast';\nimport type { ComProfile } from '../../types';\n\nconst PAGE_SIZE = 12;\n\nconst SKELETON_KEYS = ['s1', 's2', 's3', 's4', 's5', 's6', 's7', 's8'] as const;\n\n/** Card-shaped placeholder that mirrors the member card while the page loads. */\nfunction MemberCardSkeleton() {\n return (\n <GlassCard treatment=\"plain\" className=\"flex flex-col p-5\">\n <div className=\"flex items-start gap-3\">\n <Skeleton className=\"h-14 w-14 rounded-full\" />\n <div className=\"min-w-0 flex-1 space-y-2 py-1\">\n <Skeleton className=\"h-4 w-2/3\" />\n <Skeleton className=\"h-3 w-1/2\" />\n <Skeleton className=\"h-3 w-4/5\" />\n </div>\n </div>\n <div className=\"mt-3 flex flex-wrap gap-1.5\">\n <Skeleton className=\"h-5 w-16 rounded-full\" />\n <Skeleton className=\"h-5 w-20 rounded-full\" />\n </div>\n <div className=\"mt-4 flex justify-end border-t border-border-seam pt-3\">\n <Skeleton className=\"h-8 w-28 rounded-button\" />\n </div>\n </GlassCard>\n );\n}\n\nexport function MembersPage() {\n const { navigateTo, currentUser } = useComradeCircle();\n const pager = useCursorPager();\n const [search, setSearch] = useState('');\n const [pendingId, setPendingId] = useState<string | null>(null);\n\n const { data, isLoading, isError, refetch } = useComProfiles({\n discoverable: true,\n pagination: { limit: PAGE_SIZE, cursor: pager.cursor },\n });\n\n const { data: follows } = useComMyFollows('MEMBER');\n const follow = useComFollow();\n const unfollow = useComUnfollow();\n\n const followSet = useMemo(() => new Set((follows ?? []).map((f) => f.targetId)), [follows]);\n\n const profiles = useMemo(() => data?.items ?? [], [data]);\n\n const visible = useMemo(() => {\n const q = search.trim().toLowerCase();\n if (!q) return profiles;\n return profiles.filter((p) => {\n const haystack = [p.displayName, p.headline ?? '', ...p.skills, ...p.interests]\n .join(' ')\n .toLowerCase();\n return haystack.includes(q);\n });\n }, [profiles, search]);\n\n const toggleFollow = async (profile: ComProfile) => {\n const wasFollowing = followSet.has(profile.memberId);\n const input = { targetId: profile.memberId, targetType: 'MEMBER' as const };\n setPendingId(profile.memberId);\n try {\n if (wasFollowing) {\n await unfollow.mutateAsync(input);\n notify.success('Unfollowed', profile.displayName);\n } else {\n await follow.mutateAsync(input);\n notify.success('Following', profile.displayName);\n }\n } catch (err) {\n notify.error(wasFollowing ? 'Could not unfollow' : 'Could not follow', describeError(err));\n } finally {\n setPendingId(null);\n }\n };\n\n return (\n <PageLayout\n title=\"Members\"\n description=\"Discover and follow people across your circles — search by name, headline, or skills.\"\n >\n {isLoading ? (\n <div className=\"flex flex-col gap-5\">\n <Skeleton className=\"h-9 w-full max-w-sm rounded-button\" />\n <div className=\"grid gap-4 sm:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4\">\n {SKELETON_KEYS.map((key) => (\n <MemberCardSkeleton key={key} />\n ))}\n </div>\n </div>\n ) : isError ? (\n <ErrorView message=\"We couldn't load the member directory.\" onRetry={() => refetch()} />\n ) : profiles.length === 0 && pager.page === 0 ? (\n <EmptyState\n illustration=\"empty-people\"\n title=\"No members to discover yet\"\n description=\"When members make their profiles discoverable, they'll show up here for you to follow.\"\n />\n ) : (\n <div className=\"flex flex-col gap-5\">\n <div className=\"relative w-full max-w-sm\">\n <Search\n className=\"pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-tertiary\"\n aria-hidden=\"true\"\n />\n <Input\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n placeholder=\"Search by name, headline, or skills\"\n aria-label=\"Search members\"\n className=\"pl-9\"\n />\n </div>\n\n {visible.length === 0 ? (\n <EmptyState\n icon={<Search className=\"h-9 w-9\" />}\n title=\"No matches on this page\"\n description=\"No members on this page match your search. Try a different term or browse another page.\"\n />\n ) : (\n <>\n <p className=\"text-xs font-medium text-text-tertiary\">\n Showing {visible.length} member{visible.length === 1 ? '' : 's'}\n </p>\n\n <div className=\"grid gap-4 sm:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4\">\n {visible.map((p) => {\n const isSelf = Boolean(currentUser?.id && p.memberId === currentUser.id);\n const isFollowing = followSet.has(p.memberId);\n const isPending = pendingId === p.memberId;\n const chips = Array.from(new Set([...p.skills, ...p.interests])).slice(0, 4);\n\n return (\n <GlassCard\n key={p.id}\n treatment=\"plain\"\n className=\"flex flex-col p-5 transition-all duration-200 motion-safe:hover:-translate-y-0.5 hover:border-[var(--color-accent-soft)]\"\n >\n <button\n type=\"button\"\n onClick={() => navigateTo(`members/${p.memberId}`)}\n aria-label={`View ${p.displayName}'s profile`}\n className=\"group/head flex w-full items-start gap-3 rounded-lg text-left outline-none focus-visible:ring-1 focus-visible:ring-[var(--color-focus-ring)]\"\n >\n <Avatar\n name={p.displayName}\n presence={p.presence}\n size=\"lg\"\n fileId={p.avatar?.id}\n seed={p.memberId}\n />\n <div className=\"min-w-0 flex-1\">\n <span className=\"block max-w-full truncate text-base font-semibold text-text-primary group-hover/head:underline\">\n {p.displayName}\n </span>\n {p.headline && (\n <p className=\"truncate text-sm text-text-secondary\">{p.headline}</p>\n )}\n {p.bio && (\n <p className=\"mt-0.5 line-clamp-1 text-xs text-text-tertiary\">\n {p.bio}\n </p>\n )}\n </div>\n </button>\n\n {chips.length > 0 && (\n <div className=\"mt-3 flex flex-wrap gap-1.5\">\n {chips.map((chip) => (\n <span\n key={chip}\n className=\"rounded-full bg-bg-sunken px-2 py-0.5 text-xs font-medium text-text-secondary\"\n >\n {chip}\n </span>\n ))}\n </div>\n )}\n\n {!isSelf && (\n <div className=\"mt-4 flex items-center justify-end border-t border-border-seam pt-3\">\n {isFollowing ? (\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={(e) => {\n e.stopPropagation();\n void toggleFollow(p);\n }}\n disabled={isPending}\n aria-label={`Following ${p.displayName}. Activate to unfollow.`}\n className=\"group/follow min-w-[7.5rem] justify-center hover:border-status-error-border hover:bg-status-error-bg-subtle hover:text-status-error-text\"\n >\n {isPending ? (\n <>\n <Loader2 className=\"motion-safe:animate-spin\" />\n <span>Following</span>\n </>\n ) : (\n <>\n <Check className=\"group-hover/follow:hidden\" />\n <UserMinus className=\"hidden group-hover/follow:inline\" />\n <span className=\"group-hover/follow:hidden\">Following</span>\n <span className=\"hidden group-hover/follow:inline\">Unfollow</span>\n </>\n )}\n </Button>\n ) : (\n <Button\n size=\"sm\"\n onClick={(e) => {\n e.stopPropagation();\n void toggleFollow(p);\n }}\n disabled={isPending}\n className=\"min-w-[7.5rem] justify-center\"\n >\n {isPending ? (\n <Loader2 className=\"motion-safe:animate-spin\" />\n ) : (\n <UserPlus />\n )}\n Follow\n </Button>\n )}\n </div>\n )}\n </GlassCard>\n );\n })}\n </div>\n </>\n )}\n\n <Pagination\n page={pager.page}\n pageSize={PAGE_SIZE}\n itemCount={profiles.length}\n hasMore={data?.pageInfo.hasMore ?? false}\n onPageChange={(target) => pager.onPageChange(target, data?.pageInfo.cursor)}\n />\n </div>\n )}\n </PageLayout>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;AA+BA,IAAM,IAAY,IAEZ,IAAgB;CAAC;CAAM;CAAM;CAAM;CAAM;CAAM;CAAM;CAAM;CAAK;AAGtE,SAAS,IAAqB;AAC5B,QACE,kBAAC,GAAD;EAAW,WAAU;EAAQ,WAAU;YAAvC;GACE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,GAAD,EAAU,WAAU,0BAA2B,CAAA,EAC/C,kBAAC,OAAD;KAAK,WAAU;eAAf;MACE,kBAAC,GAAD,EAAU,WAAU,aAAc,CAAA;MAClC,kBAAC,GAAD,EAAU,WAAU,aAAc,CAAA;MAClC,kBAAC,GAAD,EAAU,WAAU,aAAc,CAAA;MAC9B;OACF;;GACN,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,GAAD,EAAU,WAAU,yBAA0B,CAAA,EAC9C,kBAAC,GAAD,EAAU,WAAU,yBAA0B,CAAA,CAC1C;;GACN,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,GAAD,EAAU,WAAU,2BAA4B,CAAA;IAC5C,CAAA;GACI;;;AAIhB,SAAgB,IAAc;CAC5B,IAAM,EAAE,eAAY,mBAAgB,GAAkB,EAChD,IAAQ,GAAgB,EACxB,CAAC,GAAQ,KAAa,EAAS,GAAG,EAClC,CAAC,GAAW,KAAgB,EAAwB,KAAK,EAEzD,EAAE,SAAM,cAAW,YAAS,eAAY,EAAe;EAC3D,cAAc;EACd,YAAY;GAAE,OAAO;GAAW,QAAQ,EAAM;GAAQ;EACvD,CAAC,EAEI,EAAE,MAAM,MAAY,EAAgB,SAAS,EAC7C,IAAS,GAAc,EACvB,IAAW,GAAgB,EAE3B,IAAY,QAAc,IAAI,KAAK,KAAW,EAAE,EAAE,KAAK,MAAM,EAAE,SAAS,CAAC,EAAE,CAAC,EAAQ,CAAC,EAErF,IAAW,QAAc,GAAM,SAAS,EAAE,EAAE,CAAC,EAAK,CAAC,EAEnD,IAAU,QAAc;EAC5B,IAAM,IAAI,EAAO,MAAM,CAAC,aAAa;AAErC,SADK,IACE,EAAS,QAAQ,MACL;GAAC,EAAE;GAAa,EAAE,YAAY;GAAI,GAAG,EAAE;GAAQ,GAAG,EAAE;GAAU,CAC5E,KAAK,IAAI,CACT,aAAa,CACA,SAAS,EAAE,CAC3B,GANa;IAOd,CAAC,GAAU,EAAO,CAAC,EAEhB,IAAe,OAAO,MAAwB;EAClD,IAAM,IAAe,EAAU,IAAI,EAAQ,SAAS,EAC9C,IAAQ;GAAE,UAAU,EAAQ;GAAU,YAAY;GAAmB;AAC3E,IAAa,EAAQ,SAAS;AAC9B,MAAI;AACF,GAAI,KACF,MAAM,EAAS,YAAY,EAAM,EACjC,EAAO,QAAQ,cAAc,EAAQ,YAAY,KAEjD,MAAM,EAAO,YAAY,EAAM,EAC/B,EAAO,QAAQ,aAAa,EAAQ,YAAY;WAE3C,GAAK;AACZ,KAAO,MAAM,IAAe,uBAAuB,oBAAoB,EAAc,EAAI,CAAC;YAClF;AACR,KAAa,KAAK;;;AAItB,QACE,kBAAC,GAAD;EACE,OAAM;EACN,aAAY;YAEX,IACC,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,GAAD,EAAU,WAAU,sCAAuC,CAAA,EAC3D,kBAAC,OAAD;IAAK,WAAU;cACZ,EAAc,KAAK,MAClB,kBAAC,GAAD,EAAgC,EAAP,EAAO,CAChC;IACE,CAAA,CACF;OACJ,IACF,kBAAC,GAAD;GAAW,SAAQ;GAAyC,eAAe,GAAS;GAAI,CAAA,GACtF,EAAS,WAAW,KAAK,EAAM,SAAS,IAC1C,kBAAC,GAAD;GACE,cAAa;GACb,OAAM;GACN,aAAY;GACZ,CAAA,GAEF,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,GAAD;MACE,WAAU;MACV,eAAY;MACZ,CAAA,EACF,kBAAC,GAAD;MACE,OAAO;MACP,WAAW,MAAM,EAAU,EAAE,OAAO,MAAM;MAC1C,aAAY;MACZ,cAAW;MACX,WAAU;MACV,CAAA,CACE;;IAEL,EAAQ,WAAW,IAClB,kBAAC,GAAD;KACE,MAAM,kBAAC,GAAD,EAAQ,WAAU,WAAY,CAAA;KACpC,OAAM;KACN,aAAY;KACZ,CAAA,GAEF,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,KAAD;KAAG,WAAU;eAAb;MAAsD;MAC3C,EAAQ;MAAO;MAAQ,EAAQ,WAAW,IAAI,KAAK;MAC1D;QAEJ,kBAAC,OAAD;KAAK,WAAU;eACZ,EAAQ,KAAK,MAAM;MAClB,IAAM,IAAS,GAAQ,GAAa,MAAM,EAAE,aAAa,EAAY,KAC/D,IAAc,EAAU,IAAI,EAAE,SAAS,EACvC,IAAY,MAAc,EAAE,UAC5B,IAAQ,MAAM,KAAK,IAAI,IAAI,CAAC,GAAG,EAAE,QAAQ,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,MAAM,GAAG,EAAE;AAE5E,aACE,kBAAC,GAAD;OAEE,WAAU;OACV,WAAU;iBAHZ;QAKE,kBAAC,UAAD;SACE,MAAK;SACL,eAAe,EAAW,WAAW,EAAE,WAAW;SAClD,cAAY,QAAQ,EAAE,YAAY;SAClC,WAAU;mBAJZ,CAME,kBAAC,GAAD;UACE,MAAM,EAAE;UACR,UAAU,EAAE;UACZ,MAAK;UACL,QAAQ,EAAE,QAAQ;UAClB,MAAM,EAAE;UACR,CAAA,EACF,kBAAC,OAAD;UAAK,WAAU;oBAAf;WACE,kBAAC,QAAD;YAAM,WAAU;sBACb,EAAE;YACE,CAAA;WACN,EAAE,YACD,kBAAC,KAAD;YAAG,WAAU;sBAAwC,EAAE;YAAa,CAAA;WAErE,EAAE,OACD,kBAAC,KAAD;YAAG,WAAU;sBACV,EAAE;YACD,CAAA;WAEF;YACC;;QAER,EAAM,SAAS,KACd,kBAAC,OAAD;SAAK,WAAU;mBACZ,EAAM,KAAK,MACV,kBAAC,QAAD;UAEE,WAAU;oBAET;UACI,EAJA,EAIA,CACP;SACE,CAAA;QAGP,CAAC,KACA,kBAAC,OAAD;SAAK,WAAU;mBACZ,IACC,kBAAC,GAAD;UACE,MAAK;UACL,SAAQ;UACR,UAAU,MAAM;AAET,WADL,EAAE,iBAAiB,EACd,EAAa,EAAE;;UAEtB,UAAU;UACV,cAAY,aAAa,EAAE,YAAY;UACvC,WAAU;oBAET,IACC,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD,EAAS,WAAU,4BAA6B,CAAA,EAChD,kBAAC,QAAD,EAAA,UAAM,aAAgB,CAAA,CACrB,EAAA,CAAA,GAEH,kBAAA,GAAA,EAAA,UAAA;WACE,kBAAC,GAAD,EAAO,WAAU,6BAA8B,CAAA;WAC/C,kBAAC,GAAD,EAAW,WAAU,oCAAqC,CAAA;WAC1D,kBAAC,QAAD;YAAM,WAAU;sBAA4B;YAAgB,CAAA;WAC5D,kBAAC,QAAD;YAAM,WAAU;sBAAmC;YAAe,CAAA;WACjE,EAAA,CAAA;UAEE,CAAA,GAET,kBAAC,GAAD;UACE,MAAK;UACL,UAAU,MAAM;AAET,WADL,EAAE,iBAAiB,EACd,EAAa,EAAE;;UAEtB,UAAU;UACV,WAAU;oBAPZ,CASG,IACC,kBAAC,GAAD,EAAS,WAAU,4BAA6B,CAAA,GAEhD,kBAAC,GAAD,EAAY,CAAA,EACZ,SAEK;;SAEP,CAAA;QAEE;SA7FL,EAAE,GA6FG;OAEd;KACE,CAAA,CACL,EAAA,CAAA;IAGL,kBAAC,GAAD;KACE,MAAM,EAAM;KACZ,UAAU;KACV,WAAW,EAAS;KACpB,SAAS,GAAM,SAAS,WAAW;KACnC,eAAe,MAAW,EAAM,aAAa,GAAQ,GAAM,SAAS,OAAO;KAC3E,CAAA;IACE;;EAEG,CAAA"}
|