@xhub-short/ui 0.1.0-beta.8 → 1.0.0-beta.18

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.
Files changed (75) hide show
  1. package/dist/CommentSheet.css-DuBy01rU.d.ts +219 -0
  2. package/dist/VideoSlotPlayIndicator-DPs8Xt5C.d.ts +51 -0
  3. package/dist/chunk-3OB3OVYR.js +349 -0
  4. package/dist/chunk-4RIMQOBR.js +58 -0
  5. package/dist/chunk-5MKYDI4X.js +1 -0
  6. package/dist/chunk-5Y43HNRG.js +296 -0
  7. package/dist/chunk-7WXAQHJI.js +350 -0
  8. package/dist/chunk-BADA7OLG.js +564 -0
  9. package/dist/chunk-BEJAJFV6.js +191 -0
  10. package/dist/chunk-BNI7CYRI.js +334 -0
  11. package/dist/{chunk-UPCVSGWH.js → chunk-CAWE42LH.js} +5 -2
  12. package/dist/chunk-DGKMO3AE.js +717 -0
  13. package/dist/chunk-DR7KR7OT.js +103 -0
  14. package/dist/chunk-GSNIZ6DF.js +605 -0
  15. package/dist/chunk-HXQPEZRG.js +105 -0
  16. package/dist/chunk-IC2KUU4V.js +1264 -0
  17. package/dist/chunk-IWSBYOSS.js +91 -0
  18. package/dist/chunk-MFJS65C5.js +368 -0
  19. package/dist/{chunk-CXPNPSF7.js → chunk-NJXIYSDZ.js} +12 -1
  20. package/dist/{chunk-NRQXKZO3.js → chunk-OM4L7RE5.js} +12 -2
  21. package/dist/chunk-QCRRF76W.js +75 -0
  22. package/dist/chunk-QUEJHA24.js +508 -0
  23. package/dist/chunk-UYBQTE4M.js +337 -0
  24. package/dist/chunk-VJ744W5N.js +603 -0
  25. package/dist/chunk-VXW7AOGM.js +285 -0
  26. package/dist/{chunk-OQ7P5XC7.js → chunk-YB7AXTX7.js} +1 -1
  27. package/dist/components/ActionBar/index.d.ts +7 -2
  28. package/dist/components/ActionBar/index.js +1 -1
  29. package/dist/components/AdvanceMenu/index.d.ts +80 -0
  30. package/dist/components/AdvanceMenu/index.js +1 -0
  31. package/dist/components/ArticleSlot/index.d.ts +213 -0
  32. package/dist/components/ArticleSlot/index.js +1 -0
  33. package/dist/components/AuthorInfo/index.js +1 -1
  34. package/dist/components/BottomSheet/index.d.ts +87 -0
  35. package/dist/components/BottomSheet/index.js +1 -0
  36. package/dist/components/CleanModeOverlay/index.d.ts +60 -0
  37. package/dist/components/CleanModeOverlay/index.js +1 -0
  38. package/dist/components/CommentSheet/index.d.ts +155 -3
  39. package/dist/components/CommentSheet/index.js +1 -1
  40. package/dist/components/DetailView/index.d.ts +314 -0
  41. package/dist/components/DetailView/index.js +1 -0
  42. package/dist/components/ErrorBoundary/index.js +1 -1
  43. package/dist/components/{VideoFeed → Feed}/index.d.ts +64 -45
  44. package/dist/components/Feed/index.js +1 -0
  45. package/dist/components/ImageCarousel/index.d.ts +50 -0
  46. package/dist/components/ImageCarousel/index.js +1 -0
  47. package/dist/components/Playlist/index.d.ts +117 -0
  48. package/dist/components/Playlist/index.js +1 -0
  49. package/dist/components/ProgressBar/index.js +1 -1
  50. package/dist/components/QualityPicker/index.d.ts +35 -0
  51. package/dist/components/QualityPicker/index.js +1 -0
  52. package/dist/components/ReportSheet/index.d.ts +74 -0
  53. package/dist/components/ReportSheet/index.js +1 -0
  54. package/dist/components/Skeleton/index.js +1 -1
  55. package/dist/components/SpeedPicker/index.d.ts +32 -0
  56. package/dist/components/SpeedPicker/index.js +1 -0
  57. package/dist/components/VideoInfo/index.d.ts +7 -3
  58. package/dist/components/VideoInfo/index.js +1 -1
  59. package/dist/components/VideoPlayer/index.js +1 -1
  60. package/dist/components/VideoSlot/index.d.ts +31 -68
  61. package/dist/components/VideoSlot/index.js +2 -1
  62. package/dist/components/VirtualSlider/index.js +1 -1
  63. package/dist/index.d.ts +74 -11
  64. package/dist/index.js +39 -15
  65. package/package.json +8 -4
  66. package/dist/CommentSheet.css-BD6XbpU2.d.ts +0 -207
  67. package/dist/chunk-EBAMBI3O.js +0 -571
  68. package/dist/chunk-K3CETRCY.js +0 -737
  69. package/dist/chunk-PGHLVKXS.js +0 -148
  70. package/dist/chunk-QF7O26KZ.js +0 -357
  71. package/dist/chunk-RKS7YA7Z.js +0 -562
  72. package/dist/chunk-T4RQWGRY.js +0 -1519
  73. package/dist/chunk-UXNIXHII.js +0 -2040
  74. package/dist/chunk-YWAPI7JO.js +0 -204
  75. package/dist/components/VideoFeed/index.js +0 -1
@@ -0,0 +1,349 @@
1
+ import { PlusIcon } from './chunk-ANCP53F3.js';
2
+ import { injectComponentCSS } from './chunk-CAWE42LH.js';
3
+ import { clsx } from 'clsx';
4
+ import { createContext, useInsertionEffect, useMemo, useState, useEffect, useContext } from 'react';
5
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
6
+
7
+ var AuthorInfoContext = createContext(null);
8
+ AuthorInfoContext.displayName = "AuthorInfoContext";
9
+ function useAuthorInfoContext() {
10
+ const context = useContext(AuthorInfoContext);
11
+ if (!context) {
12
+ throw new Error(
13
+ "[AuthorInfo] useAuthorInfoContext must be used within <AuthorInfoHeadless>. Make sure you wrap your component with <AuthorInfoHeadless>."
14
+ );
15
+ }
16
+ return context;
17
+ }
18
+ function useOptionalAuthorInfoContext() {
19
+ return useContext(AuthorInfoContext);
20
+ }
21
+ function DefaultCheckIcon() {
22
+ return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z" }) });
23
+ }
24
+ function DefaultUserIcon() {
25
+ return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z" }) });
26
+ }
27
+ var SIZE_CLASS_MAP = {
28
+ small: "sv-author-info__avatar--small",
29
+ large: "sv-author-info__avatar--large",
30
+ default: ""
31
+ };
32
+ function AuthorAvatar({
33
+ src,
34
+ alt,
35
+ size = "default",
36
+ showVerified = false,
37
+ verifiedIcon,
38
+ onClick,
39
+ className,
40
+ children
41
+ }) {
42
+ const [imgError, setImgError] = useState(false);
43
+ const context = useOptionalAuthorInfoContext();
44
+ const avatarSrc = src ?? context?.author.avatar;
45
+ const avatarAlt = alt ?? context?.author.name ?? "Author avatar";
46
+ const isVerified = context?.author.isVerified ?? false;
47
+ const handleClick = onClick ?? context?.openProfile;
48
+ useEffect(() => {
49
+ setImgError(false);
50
+ }, [avatarSrc]);
51
+ const handleImgError = () => setImgError(true);
52
+ const sizeClass = SIZE_CLASS_MAP[size];
53
+ const showImage = avatarSrc && !imgError;
54
+ const handleKeyDown = (e) => {
55
+ if ((e.key === "Enter" || e.key === " ") && handleClick) {
56
+ e.preventDefault();
57
+ e.stopPropagation();
58
+ handleClick();
59
+ }
60
+ };
61
+ return /* @__PURE__ */ jsxs(
62
+ "div",
63
+ {
64
+ className: clsx("sv-author-info__avatar", sizeClass, className),
65
+ onClick: (e) => {
66
+ e.stopPropagation();
67
+ handleClick?.();
68
+ },
69
+ onKeyDown: handleKeyDown,
70
+ role: handleClick ? "button" : void 0,
71
+ tabIndex: handleClick ? 0 : void 0,
72
+ "aria-label": handleClick ? `View ${avatarAlt}'s profile` : void 0,
73
+ children: [
74
+ children ?? (showImage && avatarSrc ? /* @__PURE__ */ jsx(
75
+ "img",
76
+ {
77
+ src: avatarSrc,
78
+ alt: avatarAlt,
79
+ className: "sv-author-info__avatar-img",
80
+ loading: "lazy",
81
+ onError: handleImgError
82
+ }
83
+ ) : /* @__PURE__ */ jsx("div", { className: "sv-author-info__avatar-placeholder", children: /* @__PURE__ */ jsx(DefaultUserIcon, {}) })),
84
+ showVerified && isVerified && /* @__PURE__ */ jsx("div", { className: "sv-author-info__verified-badge", "aria-label": "Verified", children: verifiedIcon ?? /* @__PURE__ */ jsx(DefaultCheckIcon, {}) })
85
+ ]
86
+ }
87
+ );
88
+ }
89
+ function AuthorDescription({
90
+ description,
91
+ singleLine = false,
92
+ className,
93
+ children
94
+ }) {
95
+ const context = useOptionalAuthorInfoContext();
96
+ const displayDescription = description ?? context?.author.description;
97
+ if (!children && !displayDescription) {
98
+ return null;
99
+ }
100
+ return /* @__PURE__ */ jsx(
101
+ "p",
102
+ {
103
+ className: clsx(
104
+ "sv-author-info__description",
105
+ singleLine && "sv-author-info__description--single-line",
106
+ className
107
+ ),
108
+ children: children ?? displayDescription
109
+ }
110
+ );
111
+ }
112
+
113
+ // src/components/AuthorInfo/AuthorInfo.css.ts
114
+ var AUTHOR_INFO_CSS = `.sv-author-info{display:flex;align-items:center;gap:var(--sv-author-gap,12px);width:100%}.sv-author-info--vertical{flex-direction:column;align-items:flex-start}.sv-author-info--horizontal{flex-direction:row;align-items:center}.sv-author-info--compact{gap:var(--sv-author-gap-compact,8px)}.sv-author-info__avatar{position:relative;flex-shrink:0;width:var(--sv-author-avatar-size,48px);height:var(--sv-author-avatar-size,48px);border-radius:50%;overflow:hidden;background:var(--sv-author-avatar-bg,rgba(255,255,255,.1));cursor:pointer;transition:transform .15s ease}.sv-author-info__avatar:hover{transform:scale(1.05)}.sv-author-info__avatar:active{transform:scale(.98)}.sv-author-info__avatar-img{width:100%;height:100%;object-fit:cover;border-radius:50%}.sv-author-info__avatar-placeholder{width:100%;height:100%;display:flex;align-items:center;justify-content:center;background:var(--sv-author-avatar-placeholder-bg,linear-gradient(135deg,#667eea 0%,#764ba2 100%));color:var(--sv-author-avatar-placeholder-color,#fff);font-size:calc(var(--sv-author-avatar-size,48px)* .4);font-weight:600;text-transform:uppercase}.sv-author-info__avatar-placeholder svg{width:60%;height:60%;opacity:.9}.sv-author-info__avatar--small{width:var(--sv-author-avatar-size-small,32px);height:var(--sv-author-avatar-size-small,32px)}.sv-author-info__avatar--large{width:var(--sv-author-avatar-size-large,64px);height:var(--sv-author-avatar-size-large,64px)}.sv-author-info__verified-badge{position:absolute;bottom:-2px;right:-2px;width:calc(var(--sv-author-avatar-size,48px)* .35);height:calc(var(--sv-author-avatar-size,48px)* .35);min-width:14px;min-height:14px;border-radius:50%;background:var(--sv-verified-badge-bg,#1DA1F2);display:flex;align-items:center;justify-content:center;border:2px solid var(--sv-verified-badge-border,#000)}.sv-author-info__verified-badge svg{width:60%;height:60%;color:var(--sv-verified-badge-color,#fff)}.sv-author-info__content{display:flex;flex-direction:column;gap:var(--sv-author-content-gap,2px);flex:1;min-width:0}.sv-author-info__name{display:flex;align-items:center;gap:var(--sv-author-name-gap,4px);font-size:var(--sv-author-name-size,16px);font-weight:var(--sv-author-name-weight,600);color:var(--sv-author-name-color,#fff);cursor:pointer;transition:opacity .15s ease}.sv-author-info__name:hover{opacity:.8}.sv-author-info__name-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sv-author-info__name--with-at::before{content:'@';opacity:.8}.sv-author-info__name-verified{flex-shrink:0;width:var(--sv-author-name-verified-size,14px);height:var(--sv-author-name-verified-size,14px);color:var(--sv-verified-badge-bg,#1DA1F2)}.sv-author-info__description{font-size:var(--sv-author-desc-size,13px);color:var(--sv-author-desc-color,rgba(255,255,255,.7));line-height:var(--sv-author-desc-line-height,1.4);overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:var(--sv-author-desc-lines,2);-webkit-box-orient:vertical}.sv-author-info__description--single-line{-webkit-line-clamp:1;white-space:nowrap;display:block}.sv-author-info__follow-btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--sv-follow-btn-gap,6px);padding:var(--sv-follow-btn-padding,8px 16px);min-width:var(--sv-follow-btn-min-width,88px);border:0;border-radius:var(--sv-follow-btn-radius,4px);font-size:var(--sv-follow-btn-size,14px);font-weight:var(--sv-follow-btn-weight,600);cursor:pointer;transition:all .2s ease;outline:none;user-select:none;-webkit-tap-highlight-color:transparent}.sv-author-info__follow-btn--default{background:var(--sv-follow-btn-bg,#fe2c55);color:var(--sv-follow-btn-color,#fff)}.sv-author-info__follow-btn--default:hover:not(:disabled){background:var(--sv-follow-btn-bg-hover,#f46);transform:scale(1.02)}.sv-author-info__follow-btn--default:active:not(:disabled){transform:scale(.98)}.sv-author-info__follow-btn--following{background:var(--sv-follow-btn-following-bg,transparent);color:var(--sv-follow-btn-following-color,rgba(255,255,255,.9));border:1px solid var(--sv-follow-btn-following-border,rgba(255,255,255,.3))}.sv-author-info__follow-btn--following:hover:not(:disabled){background:var(--sv-follow-btn-following-bg-hover,rgba(255,255,255,.1));border-color:var(--sv-follow-btn-following-border-hover,rgba(255,255,255,.5))}.sv-author-info__follow-btn--pending{opacity:.6;pointer-events:none;cursor:wait}.sv-author-info__follow-btn:disabled{opacity:.5;cursor:not-allowed}.sv-author-info__follow-btn-icon{width:var(--sv-follow-btn-icon-size,16px);height:var(--sv-follow-btn-icon-size,16px);flex-shrink:0}.sv-author-info__follow-btn-spinner{width:var(--sv-follow-btn-icon-size,16px);height:var(--sv-follow-btn-icon-size,16px);border:2px solid currentColor;border-top-color:transparent;border-radius:50%;animation:sv-author-info-spin .6s linear infinite}@keyframes sv-author-info-spin{from{transform:rotate(0deg)}to{transform:rotate(360deg)}}.sv-author-info__follow-btn--small{padding:var(--sv-follow-btn-padding-small,6px 12px);font-size:var(--sv-follow-btn-size-small,12px);min-width:var(--sv-follow-btn-min-width-small,72px)}.sv-author-info__follow-btn--large{padding:var(--sv-follow-btn-padding-large,10px 20px);font-size:var(--sv-follow-btn-size-large,16px);min-width:var(--sv-follow-btn-min-width-large,100px)}.sv-author-info__follow-btn--icon-only{min-width:unset;padding:var(--sv-follow-btn-icon-padding,8px);border-radius:50%}.sv-author-info--inline{justify-content:space-between}.sv-author-info--inline .sv-author-info__content{flex:1}.sv-author-info--stacked{flex-direction:column;align-items:center;text-align:center}.sv-author-info--stacked .sv-author-info__content{align-items:center}.sv-author-info--overlay{text-shadow:var(--sv-author-overlay-shadow,0 1px 2px rgba(0,0,0,.5))}.sv-author-info--overlay .sv-author-info__avatar{border:2px solid var(--sv-author-overlay-avatar-border,rgba(255,255,255,.5))}.sv-author-info--avatar-badge{position:relative;display:flex;flex-direction:column;align-items:center;width:auto;gap:0}.sv-author-info--avatar-badge .sv-author-info__avatar{width:var(--sv-avatar-badge-size,48px);height:var(--sv-avatar-badge-size,48px);border:2px solid var(--sv-avatar-badge-border,#fff)}.sv-author-info--avatar-badge .sv-author-info__follow-btn{position:absolute;bottom:var(--sv-avatar-badge-btn-bottom,-10px);left:50%;transform:translateX(-50%);min-width:unset;width:var(--sv-avatar-badge-btn-size,24px);height:var(--sv-avatar-badge-btn-size,24px);padding:0;border-radius:50%;background:var(--sv-color-primary,#fe2c55);border:2px solid var(--sv-bg-primary,#000);z-index:1}.sv-author-info--avatar-badge .sv-author-info__follow-btn:hover:not(:disabled){transform:translateX(-50%)scale(1.1)}.sv-author-info--avatar-badge .sv-author-info__follow-btn:active:not(:disabled){transform:translateX(-50%)scale(.95)}.sv-author-info--avatar-badge .sv-author-info__follow-btn-icon{width:var(--sv-avatar-badge-icon-size,14px);height:var(--sv-avatar-badge-icon-size,14px)}.sv-author-info--avatar-badge .sv-author-info__follow-btn--following{display:none}.sv-author-info--avatar-badge .sv-author-info__content{display:none}.sv-author-info--avatar-badge{margin-bottom:var(--sv-avatar-badge-margin,16px)}`;
115
+ function DefaultVerifiedIcon() {
116
+ return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M22.5 12.5c0-1.58-.875-2.95-2.148-3.6.154-.435.238-.905.238-1.4 0-2.21-1.71-3.998-3.818-3.998-.47 0-.92.084-1.336.25C14.818 2.415 13.51 1.5 12 1.5s-2.816.917-3.437 2.25c-.415-.165-.866-.25-1.336-.25-2.11 0-3.818 1.79-3.818 4 0 .494.083.964.237 1.4-1.272.65-2.147 2.018-2.147 3.6 0 1.495.782 2.798 1.942 3.486-.02.17-.032.34-.032.514 0 2.21 1.708 4 3.818 4 .47 0 .92-.086 1.335-.25.62 1.334 1.926 2.25 3.437 2.25 1.512 0 2.818-.916 3.437-2.25.415.163.865.248 1.336.248 2.11 0 3.818-1.79 3.818-4 0-.174-.012-.344-.033-.513 1.158-.687 1.943-1.99 1.943-3.484zm-6.616-3.334l-4.334 6.5c-.145.217-.382.334-.625.334-.143 0-.288-.04-.416-.126l-.115-.094-2.415-2.415c-.293-.293-.293-.768 0-1.06s.768-.294 1.06 0l1.77 1.767 3.825-5.74c.23-.345.696-.436 1.04-.207.346.23.44.696.21 1.04z" }) });
117
+ }
118
+ function AuthorName({
119
+ name,
120
+ showAtPrefix = false,
121
+ showVerified = false,
122
+ verifiedIcon,
123
+ onClick,
124
+ className,
125
+ children
126
+ }) {
127
+ const context = useOptionalAuthorInfoContext();
128
+ const displayName = name ?? context?.author.name ?? "Unknown";
129
+ const isVerified = context?.author.isVerified ?? false;
130
+ const handleClick = onClick ?? context?.openProfile;
131
+ const handleKeyDown = (e) => {
132
+ if ((e.key === "Enter" || e.key === " ") && handleClick) {
133
+ e.preventDefault();
134
+ e.stopPropagation();
135
+ handleClick();
136
+ }
137
+ };
138
+ return /* @__PURE__ */ jsxs(
139
+ "div",
140
+ {
141
+ className: clsx(
142
+ "sv-author-info__name",
143
+ showAtPrefix && "sv-author-info__name--with-at",
144
+ className
145
+ ),
146
+ onClick: (e) => {
147
+ e.stopPropagation();
148
+ handleClick?.();
149
+ },
150
+ onKeyDown: handleKeyDown,
151
+ role: handleClick ? "button" : void 0,
152
+ tabIndex: handleClick ? 0 : void 0,
153
+ "aria-label": handleClick ? `View ${displayName}'s profile` : void 0,
154
+ children: [
155
+ children ?? /* @__PURE__ */ jsx("span", { className: "sv-author-info__name-text", children: displayName }),
156
+ showVerified && isVerified && /* @__PURE__ */ jsx("span", { className: "sv-author-info__name-verified", "aria-label": "Verified", children: verifiedIcon ?? /* @__PURE__ */ jsx(DefaultVerifiedIcon, {}) })
157
+ ]
158
+ }
159
+ );
160
+ }
161
+ function DefaultFollowIcon() {
162
+ return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", "aria-hidden": "true", children: [
163
+ /* @__PURE__ */ jsx("path", { d: "M16 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" }),
164
+ /* @__PURE__ */ jsx("circle", { cx: "8.5", cy: "7", r: "4" }),
165
+ /* @__PURE__ */ jsx("line", { x1: "20", y1: "8", x2: "20", y2: "14" }),
166
+ /* @__PURE__ */ jsx("line", { x1: "23", y1: "11", x2: "17", y2: "11" })
167
+ ] });
168
+ }
169
+ function DefaultFollowingIcon() {
170
+ return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", "aria-hidden": "true", children: [
171
+ /* @__PURE__ */ jsx("path", { d: "M16 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" }),
172
+ /* @__PURE__ */ jsx("circle", { cx: "8.5", cy: "7", r: "4" }),
173
+ /* @__PURE__ */ jsx("polyline", { points: "17 11 19 13 23 9" })
174
+ ] });
175
+ }
176
+ var SIZE_CLASS_MAP2 = {
177
+ small: "sv-author-info__follow-btn--small",
178
+ default: "",
179
+ large: "sv-author-info__follow-btn--large"
180
+ };
181
+ function ButtonIcon({
182
+ isPending,
183
+ isFollowing,
184
+ followIcon,
185
+ followingIcon
186
+ }) {
187
+ if (isPending) {
188
+ return /* @__PURE__ */ jsx("span", { className: "sv-author-info__follow-btn-spinner" });
189
+ }
190
+ const icon = isFollowing ? followingIcon ?? /* @__PURE__ */ jsx(DefaultFollowingIcon, {}) : followIcon ?? /* @__PURE__ */ jsx(DefaultFollowIcon, {});
191
+ return /* @__PURE__ */ jsx("span", { className: "sv-author-info__follow-btn-icon", children: icon });
192
+ }
193
+ function FollowButton({
194
+ isFollowing: isFollowingProp,
195
+ isPending: isPendingProp,
196
+ onClick,
197
+ size = "default",
198
+ iconOnly = false,
199
+ followIcon,
200
+ followingIcon,
201
+ followText = "Follow",
202
+ followingText = "Following",
203
+ disabled = false,
204
+ className,
205
+ children,
206
+ followAriaLabel = "Follow",
207
+ unfollowAriaLabel = "Unfollow"
208
+ }) {
209
+ const context = useOptionalAuthorInfoContext();
210
+ const isFollowing = isFollowingProp ?? context?.isFollowing ?? false;
211
+ const isPending = isPendingProp ?? context?.isFollowPending ?? false;
212
+ const handleClick = onClick ?? context?.toggleFollow;
213
+ const isDisabled = disabled || isPending;
214
+ const stateClass = isFollowing ? "sv-author-info__follow-btn--following" : "sv-author-info__follow-btn--default";
215
+ const buttonText = isFollowing ? followingText : followText;
216
+ const handleButtonClick = (e) => {
217
+ e.stopPropagation();
218
+ e.preventDefault();
219
+ if (!isDisabled) {
220
+ handleClick?.();
221
+ }
222
+ };
223
+ const handleKeyDown = (e) => {
224
+ if ((e.key === "Enter" || e.key === " ") && !isDisabled) {
225
+ e.preventDefault();
226
+ e.stopPropagation();
227
+ handleClick?.();
228
+ }
229
+ };
230
+ const stopPropagation = (e) => e.stopPropagation();
231
+ return /* @__PURE__ */ jsx(
232
+ "button",
233
+ {
234
+ type: "button",
235
+ className: clsx(
236
+ "sv-author-info__follow-btn",
237
+ stateClass,
238
+ isPending && "sv-author-info__follow-btn--pending",
239
+ iconOnly && "sv-author-info__follow-btn--icon-only",
240
+ SIZE_CLASS_MAP2[size],
241
+ className
242
+ ),
243
+ onClick: handleButtonClick,
244
+ onKeyDown: handleKeyDown,
245
+ onPointerDown: stopPropagation,
246
+ onPointerUp: stopPropagation,
247
+ onTouchStart: stopPropagation,
248
+ onTouchEnd: stopPropagation,
249
+ disabled: isDisabled,
250
+ "aria-pressed": isFollowing,
251
+ "aria-label": isFollowing ? unfollowAriaLabel : followAriaLabel,
252
+ "aria-busy": isPending,
253
+ children: children ?? /* @__PURE__ */ jsxs(Fragment, { children: [
254
+ /* @__PURE__ */ jsx(
255
+ ButtonIcon,
256
+ {
257
+ isPending,
258
+ isFollowing,
259
+ followIcon: followIcon ?? /* @__PURE__ */ jsx(PlusIcon, { size: 14 }),
260
+ followingIcon
261
+ }
262
+ ),
263
+ !iconOnly && /* @__PURE__ */ jsx("span", { children: buttonText })
264
+ ] })
265
+ }
266
+ );
267
+ }
268
+ var CSS_COMPONENT_ID = "author-info";
269
+ function AuthorInfoContent({
270
+ className,
271
+ children
272
+ }) {
273
+ return /* @__PURE__ */ jsx("div", { className: clsx("sv-author-info__content", className), children });
274
+ }
275
+ function AuthorInfoHeadlessRoot({
276
+ authorState,
277
+ authorActions,
278
+ showFollowButton = true,
279
+ variant = "horizontal",
280
+ overlay = false,
281
+ className,
282
+ children
283
+ }) {
284
+ useInsertionEffect(() => {
285
+ return injectComponentCSS(CSS_COMPONENT_ID, AUTHOR_INFO_CSS);
286
+ }, []);
287
+ const contextValue = useMemo(
288
+ () => ({
289
+ author: authorState.author,
290
+ isFollowing: authorState.isFollowing,
291
+ isFollowPending: authorState.isFollowPending,
292
+ toggleFollow: () => {
293
+ authorActions.toggleFollow();
294
+ },
295
+ openProfile: () => {
296
+ authorActions.openProfile();
297
+ }
298
+ }),
299
+ [authorState, authorActions]
300
+ );
301
+ const variantClass = `sv-author-info--${variant}`;
302
+ const stopPropagation = (e) => {
303
+ e.stopPropagation();
304
+ };
305
+ return /* @__PURE__ */ jsx(AuthorInfoContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(
306
+ "div",
307
+ {
308
+ className: clsx(
309
+ "sv-author-info",
310
+ variantClass,
311
+ overlay && "sv-author-info--overlay",
312
+ className
313
+ ),
314
+ onClick: stopPropagation,
315
+ onPointerDown: stopPropagation,
316
+ onPointerUp: stopPropagation,
317
+ onTouchStart: stopPropagation,
318
+ onTouchEnd: stopPropagation,
319
+ children: children ? children : variant === "avatar-badge" ? (
320
+ // Default layout for avatar-badge variant
321
+ /* @__PURE__ */ jsxs(Fragment, { children: [
322
+ /* @__PURE__ */ jsx(AuthorAvatar, {}),
323
+ showFollowButton && /* @__PURE__ */ jsx(FollowButton, { iconOnly: true })
324
+ ] })
325
+ ) : (
326
+ // Default layout when no children provided
327
+ /* @__PURE__ */ jsxs(Fragment, { children: [
328
+ /* @__PURE__ */ jsx(AuthorAvatar, { showVerified: true }),
329
+ /* @__PURE__ */ jsx(AuthorInfoContent, { children: /* @__PURE__ */ jsx(AuthorName, { showAtPrefix: true, showVerified: true }) }),
330
+ showFollowButton && /* @__PURE__ */ jsx(FollowButton, {})
331
+ ] })
332
+ )
333
+ }
334
+ ) });
335
+ }
336
+ var AuthorInfoHeadless = Object.assign(AuthorInfoHeadlessRoot, {
337
+ /** Avatar sub-component */
338
+ Avatar: AuthorAvatar,
339
+ /** Name sub-component */
340
+ Name: AuthorName,
341
+ /** Description/bio sub-component */
342
+ Description: AuthorDescription,
343
+ /** Follow button sub-component */
344
+ FollowButton,
345
+ /** Content wrapper for name + description */
346
+ Content: AuthorInfoContent
347
+ });
348
+
349
+ export { AUTHOR_INFO_CSS, AuthorAvatar, AuthorDescription, AuthorInfoContext, AuthorInfoHeadless, AuthorName, FollowButton, useAuthorInfoContext, useOptionalAuthorInfoContext };
@@ -0,0 +1,58 @@
1
+ import { clsx2 } from './chunk-EDWS2IPH.js';
2
+ import { injectComponentCSS } from './chunk-CAWE42LH.js';
3
+ import { useInsertionEffect } from 'react';
4
+ import { jsx } from 'react/jsx-runtime';
5
+
6
+ // src/components/Skeleton/Skeleton.css.ts
7
+ var SKELETON_CSS = `.sv-skeleton{display:block;background:var(--sv-skeleton-bg,rgba(255,255,255,.1));border-radius:var(--sv-border-radius-sm,4px)}.sv-skeleton--pulse{animation:sv-skeleton-pulse 1.5s ease-in-out infinite}@keyframes sv-skeleton-pulse{0%,100%{opacity:1}50%{opacity:.4}}.sv-skeleton--wave{position:relative;overflow:hidden}.sv-skeleton--wave::after{content:'';position:absolute;top:0;left:0;right:0;bottom:0;background:linear-gradient(90deg,transparent,rgba(255,255,255,.1),transparent);animation:sv-skeleton-wave 1.5s ease-in-out infinite}@keyframes sv-skeleton-wave{0%{transform:translateX(-100%)}100%{transform:translateX(100%)}}.sv-skeleton-video{width:100%;height:100%;background:var(--sv-bg-primary,#000)}:root[data-theme="light"] .sv-skeleton,.light .sv-skeleton{background:var(--sv-skeleton-bg-light,rgba(0,0,0,.1))}:root[data-theme="light"] .sv-skeleton--wave::after,.light .sv-skeleton--wave::after{background:linear-gradient(90deg,transparent,rgba(0,0,0,.05),transparent)}`;
8
+ function Skeleton({
9
+ width,
10
+ height,
11
+ borderRadius,
12
+ animation = "pulse",
13
+ circle = false,
14
+ className
15
+ }) {
16
+ useInsertionEffect(() => {
17
+ return injectComponentCSS("skeleton", SKELETON_CSS);
18
+ }, []);
19
+ const style = {};
20
+ if (width !== void 0) {
21
+ style.width = typeof width === "number" ? `${width}px` : width;
22
+ }
23
+ if (height !== void 0) {
24
+ style.height = typeof height === "number" ? `${height}px` : height;
25
+ }
26
+ if (borderRadius !== void 0) {
27
+ style.borderRadius = typeof borderRadius === "number" ? `${borderRadius}px` : borderRadius;
28
+ } else if (circle) {
29
+ style.borderRadius = "50%";
30
+ }
31
+ return /* @__PURE__ */ jsx(
32
+ "div",
33
+ {
34
+ className: clsx2("sv-skeleton", animation !== "none" && `sv-skeleton--${animation}`, className),
35
+ style,
36
+ "aria-hidden": "true"
37
+ }
38
+ );
39
+ }
40
+ function SkeletonVideo({
41
+ className
42
+ }) {
43
+ return /* @__PURE__ */ jsx("div", { className: clsx2("sv-skeleton-video", className), children: /* @__PURE__ */ jsx(Skeleton, { width: "100%", height: "100%", animation: "wave" }) });
44
+ }
45
+ function SkeletonAvatar({
46
+ size = 40,
47
+ className
48
+ }) {
49
+ return /* @__PURE__ */ jsx(Skeleton, { width: size, height: size, circle: true, className });
50
+ }
51
+ function SkeletonText({
52
+ width = "100%",
53
+ className
54
+ }) {
55
+ return /* @__PURE__ */ jsx(Skeleton, { width, height: 14, borderRadius: 4, className });
56
+ }
57
+
58
+ export { Skeleton, SkeletonAvatar, SkeletonText, SkeletonVideo };
@@ -0,0 +1 @@
1
+