nostr-components 0.2.7 → 0.3.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.
- package/README.md +115 -186
- package/dist/assets/{base-styles-BSEzBDsk.js → base-styles-Dmuzg8I4.js} +2 -2
- package/dist/assets/{base-styles-BSEzBDsk.js.map → base-styles-Dmuzg8I4.js.map} +1 -1
- package/dist/assets/{copy-delegation-B7y2q5Kn.js → copy-delegation-xzt-t_do.js} +2 -2
- package/dist/assets/{copy-delegation-B7y2q5Kn.js.map → copy-delegation-xzt-t_do.js.map} +1 -1
- package/dist/assets/dialog-component-Da1ZIYh9.js.map +1 -1
- package/dist/assets/{dialog-likers-BqDn2P_3.js → dialog-likers-B15m_NxI.js} +5 -5
- package/dist/assets/dialog-likers-B15m_NxI.js.map +1 -0
- package/dist/assets/index.esm-ByUtE_cm.js +2159 -0
- package/dist/assets/index.esm-ByUtE_cm.js.map +1 -0
- package/dist/assets/nip05-utils-BNBHUmkr.js.map +1 -1
- package/dist/assets/nostr-login-service-D2FmscPI.js +2 -0
- package/dist/assets/nostr-login-service-D2FmscPI.js.map +1 -0
- package/dist/assets/nostr-service-CA0Qx4nJ.js +266 -0
- package/dist/assets/nostr-service-CA0Qx4nJ.js.map +1 -0
- package/dist/assets/{nostr-user-component-Cbs97dlK.js → nostr-user-component-r-MUbTL6.js} +2 -2
- package/dist/assets/{nostr-user-component-Cbs97dlK.js.map → nostr-user-component-r-MUbTL6.js.map} +1 -1
- package/dist/assets/{pure-DPo-pzxM.js → pure-DOoUcNQv.js} +2 -2
- package/dist/assets/pure-DOoUcNQv.js.map +1 -0
- package/dist/assets/theme-BN1Bvweb.js.map +1 -1
- package/dist/assets/{user-resolver-CMmbtY9Y.js → user-resolver-ArI0680e.js} +2 -2
- package/dist/assets/{user-resolver-CMmbtY9Y.js.map → user-resolver-ArI0680e.js.map} +1 -1
- package/dist/assets/utils--bxLbhGF.js.map +1 -1
- package/dist/assets/zap-utils-QRxLBOst.js +2 -0
- package/dist/assets/zap-utils-QRxLBOst.js.map +1 -0
- package/dist/components/nostr-comment.es.js +26 -26
- package/dist/components/nostr-comment.es.js.map +1 -1
- package/dist/components/nostr-dm.es.js +2 -2
- package/dist/components/nostr-dm.es.js.map +1 -1
- package/dist/components/nostr-follow-button.es.js +6 -7
- package/dist/components/nostr-follow-button.es.js.map +1 -1
- package/dist/components/nostr-like.es.js +16 -16
- package/dist/components/nostr-like.es.js.map +1 -1
- package/dist/components/nostr-live-chat.es.js +3 -3
- package/dist/components/nostr-live-chat.es.js.map +1 -1
- package/dist/components/nostr-post.es.js +19 -19
- package/dist/components/nostr-post.es.js.map +1 -1
- package/dist/components/nostr-profile-badge.es.js +2 -2
- package/dist/components/nostr-profile-badge.es.js.map +1 -1
- package/dist/components/nostr-profile.es.js +5 -5
- package/dist/components/nostr-profile.es.js.map +1 -1
- package/dist/components/nostr-zap.es.js +24 -24
- package/dist/components/nostr-zap.es.js.map +1 -1
- package/dist/nostr-components.es.js +1 -1
- package/dist/nostr-components.es.js.map +1 -1
- package/dist/nostr-components.umd.js +2669 -301
- package/dist/nostr-components.umd.js.map +1 -1
- package/dist/src/common/constants.d.ts +1 -1
- package/dist/src/common/nostr-login-service.d.ts +26 -0
- package/dist/src/nostr-dm/nostr-dm.d.ts +1 -1
- package/dist/src/nostr-like/like-utils.d.ts +2 -6
- package/dist/src/nostr-live-chat/nostr-live-chat.d.ts +1 -1
- package/dist/src/nostr-zap/zap-utils.d.ts +4 -0
- package/package.json +5 -2
- package/dist/assets/dialog-likers-BqDn2P_3.js.map +0 -1
- package/dist/assets/nostr-service-CnaPxjc6.js +0 -78
- package/dist/assets/nostr-service-CnaPxjc6.js.map +0 -1
- package/dist/assets/pure-DPo-pzxM.js.map +0 -1
- package/dist/assets/zap-utils-KFUD_vTU.js +0 -2
- package/dist/assets/zap-utils-KFUD_vTU.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{m as v,e as s,g as m,N as d,p as b}from"../assets/base-styles-
|
|
1
|
+
import{m as v,e as s,g as m,N as d,p as b}from"../assets/base-styles-Dmuzg8I4.js";import{N as y}from"../assets/nostr-user-component-r-MUbTL6.js";import{D as w}from"../assets/nostr-service-CA0Qx4nJ.js";import{r as x,a as C,b as E,d as N}from"../assets/copy-delegation-xzt-t_do.js";import"../assets/user-resolver-ArI0680e.js";function A({isLoading:n,isError:r,errorMessage:o,userProfile:e,ndkUser:t,showNpub:a,showFollow:c}){if(n)return L();if(r||e==null)return S(o||"");const i=e.displayName||e.name||v((t==null?void 0:t.npub)||""),p=s(i),f=s(e.picture||w),g=(t==null?void 0:t.npub)||"",h=(e==null?void 0:e.nip05)||"",u=s((t==null?void 0:t.pubkey)||"");return l(`<img src='${f}' alt='Nostr profile image of ${p}' loading="lazy" decoding="async"/>`,`${x({name:i})}
|
|
2
2
|
${e.nip05?C(h):""}
|
|
3
3
|
${a===!0?E(g||""):""}
|
|
4
4
|
${c===!0&&(t!=null&&t.pubkey)?`<nostr-follow-button pubkey="${u}"></nostr-follow-button>`:""}`)}function L(){return l('<div class="skeleton img-skeleton"></div>',`<div class="skeleton" style="width: 120px;"></div>
|
|
@@ -96,5 +96,5 @@ import{m as v,e as s,g as m,N as d,p as b}from"../assets/base-styles-BSEzBDsk.js
|
|
|
96
96
|
`)}const D="nc:profile_badge";class I extends y{static get observedAttributes(){return[...super.observedAttributes,"show-npub","show-follow"]}connectedCallback(){var r;(r=super.connectedCallback)==null||r.call(this),this.attachDelegatedListeners(),N({addDelegatedListener:this.addDelegatedListener.bind(this)}),this.render()}attributeChangedCallback(r,o,e){var t;o!==e&&((t=super.attributeChangedCallback)==null||t.call(this,r,o,e),(r==="show-npub"||r==="show-follow")&&this.render())}onStatusChange(r){this.render()}onUserReady(r,o){this.render()}onProfileClick(){var o,e;const r=((o=this.user)==null?void 0:o.npub)||this.getAttribute("npub")||((e=this.profile)==null?void 0:e.nip05)||this.getAttribute("nip05");r&&this.handleNjumpClick(D,this.profile,encodeURIComponent(r))}attachDelegatedListeners(){this.delegateEvent("click",".nostr-profile-badge-container",r=>{r.target.closest(".nc-copy-btn, .nostr-follow-button-container, nostr-follow-button")||this.onProfileClick()})}renderContent(){const r=this.computeOverall(),o=r===d.Loading,e=r===d.Error,t=b(this.getAttribute("show-follow")),a=b(this.getAttribute("show-npub")),c=e?super.renderError(this.errorMessage):"",i={isLoading:o,isError:e,errorMessage:c,userProfile:this.profile,ndkUser:this.user,showNpub:a,showFollow:t};this.shadowRoot.innerHTML=`
|
|
97
97
|
${$()}
|
|
98
98
|
${A(i)}
|
|
99
|
-
`}}customElements.define("nostr-profile-badge",I);export{I as default};
|
|
99
|
+
`}}customElements.get("nostr-profile-badge")||customElements.define("nostr-profile-badge",I);export{I as default};
|
|
100
100
|
//# sourceMappingURL=nostr-profile-badge.es.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nostr-profile-badge.es.js","sources":["../../src/nostr-profile-badge/render.ts","../../src/nostr-profile-badge/style.ts","../../src/nostr-profile-badge/nostr-profile-badge.ts"],"sourcesContent":["// SPDX-License-Identifier: MIT\n\nimport { NDKUser, NDKUserProfile } from '@nostr-dev-kit/ndk';\nimport { escapeHtml, maskNPub } from '../common/utils';\nimport { DEFAULT_PROFILE_IMAGE } from '../common/constants';\nimport { renderNpub } from '../base/text-row/render-npub';\nimport { renderNip05 } from '../base/text-row/render-nip05';\nimport { renderName } from '../base/text-row/render-name';\n\nexport interface RenderProfileBadgeOptions {\n isLoading: boolean;\n isError: boolean;\n errorMessage?: string;\n userProfile: NDKUserProfile | null;\n ndkUser: NDKUser | null;\n showNpub: boolean;\n showFollow: boolean;\n}\n\nexport function renderProfileBadge({\n isLoading,\n isError,\n errorMessage,\n userProfile,\n ndkUser,\n showNpub,\n showFollow\n}: RenderProfileBadgeOptions): string {\n\n if (isLoading) {\n return renderLoading();\n }\n\n if (isError || userProfile == null) {\n return renderError(errorMessage || '');\n }\n\n const rawName = userProfile.displayName ||\n userProfile.name ||\n maskNPub(ndkUser?.npub || '')\n const escapedName = escapeHtml(rawName);\n const profileImage = escapeHtml(userProfile.picture || DEFAULT_PROFILE_IMAGE);\n const npub = ndkUser?.npub || '';\n const nip05 = userProfile?.nip05 || '';\n const pubkey = escapeHtml(ndkUser?.pubkey || '');\n\n return renderContainer(\n `<img src='${profileImage}' alt='Nostr profile image of ${escapedName}' loading=\"lazy\" decoding=\"async\"/>`,\n `${renderName({ name: rawName })}\n ${userProfile.nip05 ? renderNip05(nip05) : ''}\n ${showNpub === true ? renderNpub(npub || '') : ''}\n ${showFollow === true && ndkUser?.pubkey ? `<nostr-follow-button pubkey=\"${pubkey}\"></nostr-follow-button>` : ''}`\n );\n}\n\nfunction renderLoading(): string {\n return renderContainer(\n '<div class=\"skeleton img-skeleton\"></div>',\n `<div class=\"skeleton\" style=\"width: 120px;\"></div>\n <div class=\"skeleton\" style=\"width: 160px;\"></div>`\n );\n}\n\nfunction renderError(errorMessage: string): string {\n return renderContainer(\n '<div class=\"error-icon\">⚠</div>',\n escapeHtml(errorMessage)\n );\n}\n\nfunction renderContainer(leftContent: string, rightContent: string): string {\n return `\n <div class='nostr-profile-badge-container'>\n <div class='nostr-profile-badge-left-container'>\n ${leftContent}\n </div>\n <div class='nostr-profile-badge-right-container'>\n ${rightContent}\n </div>\n </div>\n `;\n}","// SPDX-License-Identifier: MIT\n\nimport { getComponentStyles } from \"../common/base-styles\";\n\nexport function getProfileBadgeStyles(): string {\n const customStyles = `\n /* === PROFILE BADGE SPECIFIC CSS VARIABLES === */\n :host {\n --nostrc-profile-badge-bg: var(--nostrc-theme-bg, #ffffff);\n --nostrc-profile-badge-text-primary: var(--nostrc-theme-text-primary, #333333);\n --nostrc-profile-badge-text-secondary: var(--nostrc-theme-text-secondary, #666666);\n --nostrc-profile-badge-border: var(--nostrc-theme-border, var(--nostrc-color-border));\n --nostrc-profile-badge-font-family: var(--nostrc-font-family-primary);\n --nostrc-profile-badge-font-size: var(--nostrc-font-size-base);\n \n /* Hover state variables */\n --nostrc-profile-badge-hover-bg: var(--nostrc-theme-hover-bg, rgba(0, 0, 0, 0.05));\n --nostrc-profile-badge-hover-color: var(--nostrc-theme-text-primary, #333333);\n --nostrc-profile-badge-hover-border: var(--nostrc-border-width) solid var(--nostrc-theme-border, var(--nostrc-color-border));\n\n /* Make the host the visual profile badge surface */\n display: block;\n background: var(--nostrc-profile-badge-bg);\n border: var(--nostrc-border-width) solid var(--nostrc-profile-badge-border);\n border-radius: var(--nostrc-border-radius-md);\n font-family: var(--nostrc-profile-badge-font-family);\n font-size: var(--nostrc-profile-badge-font-size);\n transition: background-color var(--nostrc-transition-duration) var(--nostrc-transition-timing);\n }\n \n /* === PROFILE BADGE CONTAINER PATTERN === */\n .nostr-profile-badge-container {\n display: flex;\n gap: var(--nostrc-spacing-md);\n padding: var(--nostrc-spacing-md);\n }\n\n /* Hover state */\n :host(.is-clickable:hover) {\n background: var(--nostrc-profile-badge-hover-bg);\n color: var(--nostrc-profile-badge-hover-color);\n border: var(--nostrc-profile-badge-hover-border);\n }\n\n :host(.is-error) .nostr-profile-badge-container {\n justify-content: center;\n align-items: center;\n color: var(--nostrc-color-error-text);\n border: var(--nostrc-border-width) solid var(--nostrc-color-error-text);\n }\n \n .nostr-profile-badge-left-container {\n width: 48px;\n height: 48px;\n }\n \n .nostr-profile-badge-left-container img {\n width: 100%;\n height: 100%;\n border-radius: var(--nostrc-border-radius-full);\n object-fit: cover;\n }\n \n .nostr-profile-badge-right-container {\n display: flex;\n flex-direction: column;\n justify-content: center;\n flex-grow: 1;\n min-width: 0;\n }\n \n /* Profile badge specific styling using component variables */\n .nostr-profile-badge-container .nostr-profile-name {\n color: var(--nostrc-profile-badge-text-primary);\n }\n \n .nostr-profile-badge-container .text-row {\n color: var(--nostrc-profile-badge-text-secondary);\n }\n \n /* Skeleton specific styles */\n .img-skeleton {\n width: 48px;\n height: 48px;\n border-radius: var(--nostrc-border-radius-full);\n }\n \n `;\n \n return getComponentStyles(customStyles);\n}\n","// SPDX-License-Identifier: MIT\n\nimport { NCStatus } from '../base/base-component/nostr-base-component';\nimport { NostrUserComponent } from '../base/user-component/nostr-user-component';\nimport { parseBooleanAttribute } from '../common/utils';\nimport { renderProfileBadge, RenderProfileBadgeOptions } from './render';\nimport { getProfileBadgeStyles } from './style';\nimport { attachCopyDelegation } from '../base/copy-delegation';\nimport { NDKUser, NDKUserProfile } from '@nostr-dev-kit/ndk';\n\nconst EVT_BADGE = 'nc:profile_badge';\n\n/**\n * NostrProfileBadge\n * =================\n * UI component (extends `NostrUserComponent`) that renders a compact user badge\n * with avatar/name/nip05 and optional npub + follow button.\n *\n * Observed attributes\n * - `show-npub` — boolean-like attribute to display the masked npub + copy\n * - `show-follow` — boolean-like attribute to display the follow button\n *\n * Events\n * - `nc:status` — (from base) status changes for connection/user\n * - `nc:user` — emitted when user & profile are ready (from parent)\n * - `nc:profile_badge` — fired on badge click (detail: `NDKUserProfile | null`);\n * default action opens `https://njump.me/<nip05|npub>`\n *\n * Note: Follow button placement to be improved in future versions\n */\nexport default class NostrProfileBadge extends NostrUserComponent {\n\n /** Lifecycle methods */\n static get observedAttributes() {\n return [\n ...super.observedAttributes,\n 'show-npub',\n 'show-follow',\n ];\n }\n\n connectedCallback() {\n super.connectedCallback?.();\n \n this.attachDelegatedListeners();\n attachCopyDelegation({\n addDelegatedListener: this.addDelegatedListener.bind(this),\n });\n this.render();\n }\n\n attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null) {\n if (oldValue === newValue) return;\n super.attributeChangedCallback?.(name, oldValue, newValue);\n\n if (name === 'show-npub' || name === 'show-follow') {\n this.render();\n }\n }\n\n /** Base class functions */\n protected onStatusChange(_status: NCStatus) {\n this.render();\n }\n\n protected onUserReady(_user: NDKUser, _profile: NDKUserProfile | null) {\n this.render();\n }\n\n /** Private functions */\n private onProfileClick() {\n const key =\n this.user?.npub ||\n this.getAttribute('npub') ||\n this.profile?.nip05 ||\n this.getAttribute('nip05');\n\n if (key) {\n this.handleNjumpClick(EVT_BADGE, this.profile, encodeURIComponent(key));\n }\n }\n\n private attachDelegatedListeners() {\n\n // Click anywhere on the profile badge (except follow button, copy buttons)\n this.delegateEvent('click', '.nostr-profile-badge-container', (e: Event) => {\n const target = e.target as HTMLElement;\n if (!target.closest('.nc-copy-btn, .nostr-follow-button-container, nostr-follow-button')) {\n this.onProfileClick();\n }\n });\n\n // Copy is handled via attachCopyDelegation() using `.nc-copy-btn`\n }\n\n protected renderContent() {\n const overall = this.computeOverall();\n const isLoading = overall === NCStatus.Loading;\n const isError = overall === NCStatus.Error;\n\n // Get attribute values\n const showFollow = parseBooleanAttribute(this.getAttribute('show-follow'));\n const showNpub = parseBooleanAttribute(this.getAttribute('show-npub'));\n const errorMessage = isError ? super.renderError(this.errorMessage) : '';\n\n const renderOptions: RenderProfileBadgeOptions = {\n isLoading : isLoading,\n isError : isError,\n errorMessage: errorMessage,\n userProfile : this.profile,\n ndkUser : this.user,\n showNpub : showNpub,\n showFollow : showFollow\n };\n\n this.shadowRoot!.innerHTML = `\n ${getProfileBadgeStyles()}\n ${renderProfileBadge(renderOptions)}\n `;\n }\n}\n\ncustomElements.define('nostr-profile-badge', NostrProfileBadge);\n"],"names":["renderProfileBadge","isLoading","isError","errorMessage","userProfile","ndkUser","showNpub","showFollow","renderLoading","renderError","rawName","maskNPub","escapedName","escapeHtml","profileImage","DEFAULT_PROFILE_IMAGE","npub","nip05","pubkey","renderContainer","renderName","renderNip05","renderNpub","leftContent","rightContent","getProfileBadgeStyles","getComponentStyles","EVT_BADGE","NostrProfileBadge","NostrUserComponent","_a","attachCopyDelegation","name","oldValue","newValue","_status","_user","_profile","key","_b","e","overall","NCStatus","parseBooleanAttribute","renderOptions"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"nostr-profile-badge.es.js","sources":["../../src/nostr-profile-badge/render.ts","../../src/nostr-profile-badge/style.ts","../../src/nostr-profile-badge/nostr-profile-badge.ts"],"sourcesContent":["// SPDX-License-Identifier: MIT\n\nimport { NDKUser, NDKUserProfile } from '@nostr-dev-kit/ndk';\nimport { escapeHtml, maskNPub } from '../common/utils';\nimport { DEFAULT_PROFILE_IMAGE } from '../common/constants';\nimport { renderNpub } from '../base/text-row/render-npub';\nimport { renderNip05 } from '../base/text-row/render-nip05';\nimport { renderName } from '../base/text-row/render-name';\n\nexport interface RenderProfileBadgeOptions {\n isLoading: boolean;\n isError: boolean;\n errorMessage?: string;\n userProfile: NDKUserProfile | null;\n ndkUser: NDKUser | null;\n showNpub: boolean;\n showFollow: boolean;\n}\n\nexport function renderProfileBadge({\n isLoading,\n isError,\n errorMessage,\n userProfile,\n ndkUser,\n showNpub,\n showFollow\n}: RenderProfileBadgeOptions): string {\n\n if (isLoading) {\n return renderLoading();\n }\n\n if (isError || userProfile == null) {\n return renderError(errorMessage || '');\n }\n\n const rawName = userProfile.displayName ||\n userProfile.name ||\n maskNPub(ndkUser?.npub || '')\n const escapedName = escapeHtml(rawName);\n const profileImage = escapeHtml(userProfile.picture || DEFAULT_PROFILE_IMAGE);\n const npub = ndkUser?.npub || '';\n const nip05 = userProfile?.nip05 || '';\n const pubkey = escapeHtml(ndkUser?.pubkey || '');\n\n return renderContainer(\n `<img src='${profileImage}' alt='Nostr profile image of ${escapedName}' loading=\"lazy\" decoding=\"async\"/>`,\n `${renderName({ name: rawName })}\n ${userProfile.nip05 ? renderNip05(nip05) : ''}\n ${showNpub === true ? renderNpub(npub || '') : ''}\n ${showFollow === true && ndkUser?.pubkey ? `<nostr-follow-button pubkey=\"${pubkey}\"></nostr-follow-button>` : ''}`\n );\n}\n\nfunction renderLoading(): string {\n return renderContainer(\n '<div class=\"skeleton img-skeleton\"></div>',\n `<div class=\"skeleton\" style=\"width: 120px;\"></div>\n <div class=\"skeleton\" style=\"width: 160px;\"></div>`\n );\n}\n\nfunction renderError(errorMessage: string): string {\n return renderContainer(\n '<div class=\"error-icon\">⚠</div>',\n escapeHtml(errorMessage)\n );\n}\n\nfunction renderContainer(leftContent: string, rightContent: string): string {\n return `\n <div class='nostr-profile-badge-container'>\n <div class='nostr-profile-badge-left-container'>\n ${leftContent}\n </div>\n <div class='nostr-profile-badge-right-container'>\n ${rightContent}\n </div>\n </div>\n `;\n}","// SPDX-License-Identifier: MIT\n\nimport { getComponentStyles } from \"../common/base-styles\";\n\nexport function getProfileBadgeStyles(): string {\n const customStyles = `\n /* === PROFILE BADGE SPECIFIC CSS VARIABLES === */\n :host {\n --nostrc-profile-badge-bg: var(--nostrc-theme-bg, #ffffff);\n --nostrc-profile-badge-text-primary: var(--nostrc-theme-text-primary, #333333);\n --nostrc-profile-badge-text-secondary: var(--nostrc-theme-text-secondary, #666666);\n --nostrc-profile-badge-border: var(--nostrc-theme-border, var(--nostrc-color-border));\n --nostrc-profile-badge-font-family: var(--nostrc-font-family-primary);\n --nostrc-profile-badge-font-size: var(--nostrc-font-size-base);\n \n /* Hover state variables */\n --nostrc-profile-badge-hover-bg: var(--nostrc-theme-hover-bg, rgba(0, 0, 0, 0.05));\n --nostrc-profile-badge-hover-color: var(--nostrc-theme-text-primary, #333333);\n --nostrc-profile-badge-hover-border: var(--nostrc-border-width) solid var(--nostrc-theme-border, var(--nostrc-color-border));\n\n /* Make the host the visual profile badge surface */\n display: block;\n background: var(--nostrc-profile-badge-bg);\n border: var(--nostrc-border-width) solid var(--nostrc-profile-badge-border);\n border-radius: var(--nostrc-border-radius-md);\n font-family: var(--nostrc-profile-badge-font-family);\n font-size: var(--nostrc-profile-badge-font-size);\n transition: background-color var(--nostrc-transition-duration) var(--nostrc-transition-timing);\n }\n \n /* === PROFILE BADGE CONTAINER PATTERN === */\n .nostr-profile-badge-container {\n display: flex;\n gap: var(--nostrc-spacing-md);\n padding: var(--nostrc-spacing-md);\n }\n\n /* Hover state */\n :host(.is-clickable:hover) {\n background: var(--nostrc-profile-badge-hover-bg);\n color: var(--nostrc-profile-badge-hover-color);\n border: var(--nostrc-profile-badge-hover-border);\n }\n\n :host(.is-error) .nostr-profile-badge-container {\n justify-content: center;\n align-items: center;\n color: var(--nostrc-color-error-text);\n border: var(--nostrc-border-width) solid var(--nostrc-color-error-text);\n }\n \n .nostr-profile-badge-left-container {\n width: 48px;\n height: 48px;\n }\n \n .nostr-profile-badge-left-container img {\n width: 100%;\n height: 100%;\n border-radius: var(--nostrc-border-radius-full);\n object-fit: cover;\n }\n \n .nostr-profile-badge-right-container {\n display: flex;\n flex-direction: column;\n justify-content: center;\n flex-grow: 1;\n min-width: 0;\n }\n \n /* Profile badge specific styling using component variables */\n .nostr-profile-badge-container .nostr-profile-name {\n color: var(--nostrc-profile-badge-text-primary);\n }\n \n .nostr-profile-badge-container .text-row {\n color: var(--nostrc-profile-badge-text-secondary);\n }\n \n /* Skeleton specific styles */\n .img-skeleton {\n width: 48px;\n height: 48px;\n border-radius: var(--nostrc-border-radius-full);\n }\n \n `;\n \n return getComponentStyles(customStyles);\n}\n","// SPDX-License-Identifier: MIT\n\nimport { NCStatus } from '../base/base-component/nostr-base-component';\nimport { NostrUserComponent } from '../base/user-component/nostr-user-component';\nimport { parseBooleanAttribute } from '../common/utils';\nimport { renderProfileBadge, RenderProfileBadgeOptions } from './render';\nimport { getProfileBadgeStyles } from './style';\nimport { attachCopyDelegation } from '../base/copy-delegation';\nimport { NDKUser, NDKUserProfile } from '@nostr-dev-kit/ndk';\n\nconst EVT_BADGE = 'nc:profile_badge';\n\n/**\n * NostrProfileBadge\n * =================\n * UI component (extends `NostrUserComponent`) that renders a compact user badge\n * with avatar/name/nip05 and optional npub + follow button.\n *\n * Observed attributes\n * - `show-npub` — boolean-like attribute to display the masked npub + copy\n * - `show-follow` — boolean-like attribute to display the follow button\n *\n * Events\n * - `nc:status` — (from base) status changes for connection/user\n * - `nc:user` — emitted when user & profile are ready (from parent)\n * - `nc:profile_badge` — fired on badge click (detail: `NDKUserProfile | null`);\n * default action opens `https://njump.me/<nip05|npub>`\n *\n * Note: Follow button placement to be improved in future versions\n */\nexport default class NostrProfileBadge extends NostrUserComponent {\n\n /** Lifecycle methods */\n static get observedAttributes() {\n return [\n ...super.observedAttributes,\n 'show-npub',\n 'show-follow',\n ];\n }\n\n connectedCallback() {\n super.connectedCallback?.();\n \n this.attachDelegatedListeners();\n attachCopyDelegation({\n addDelegatedListener: this.addDelegatedListener.bind(this),\n });\n this.render();\n }\n\n attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null) {\n if (oldValue === newValue) return;\n super.attributeChangedCallback?.(name, oldValue, newValue);\n\n if (name === 'show-npub' || name === 'show-follow') {\n this.render();\n }\n }\n\n /** Base class functions */\n protected onStatusChange(_status: NCStatus) {\n this.render();\n }\n\n protected onUserReady(_user: NDKUser, _profile: NDKUserProfile | null) {\n this.render();\n }\n\n /** Private functions */\n private onProfileClick() {\n const key =\n this.user?.npub ||\n this.getAttribute('npub') ||\n this.profile?.nip05 ||\n this.getAttribute('nip05');\n\n if (key) {\n this.handleNjumpClick(EVT_BADGE, this.profile, encodeURIComponent(key));\n }\n }\n\n private attachDelegatedListeners() {\n\n // Click anywhere on the profile badge (except follow button, copy buttons)\n this.delegateEvent('click', '.nostr-profile-badge-container', (e: Event) => {\n const target = e.target as HTMLElement;\n if (!target.closest('.nc-copy-btn, .nostr-follow-button-container, nostr-follow-button')) {\n this.onProfileClick();\n }\n });\n\n // Copy is handled via attachCopyDelegation() using `.nc-copy-btn`\n }\n\n protected renderContent() {\n const overall = this.computeOverall();\n const isLoading = overall === NCStatus.Loading;\n const isError = overall === NCStatus.Error;\n\n // Get attribute values\n const showFollow = parseBooleanAttribute(this.getAttribute('show-follow'));\n const showNpub = parseBooleanAttribute(this.getAttribute('show-npub'));\n const errorMessage = isError ? super.renderError(this.errorMessage) : '';\n\n const renderOptions: RenderProfileBadgeOptions = {\n isLoading : isLoading,\n isError : isError,\n errorMessage: errorMessage,\n userProfile : this.profile,\n ndkUser : this.user,\n showNpub : showNpub,\n showFollow : showFollow\n };\n\n this.shadowRoot!.innerHTML = `\n ${getProfileBadgeStyles()}\n ${renderProfileBadge(renderOptions)}\n `;\n }\n}\n\nif (!customElements.get('nostr-profile-badge')) {\n customElements.define('nostr-profile-badge', NostrProfileBadge);\n}\n"],"names":["renderProfileBadge","isLoading","isError","errorMessage","userProfile","ndkUser","showNpub","showFollow","renderLoading","renderError","rawName","maskNPub","escapedName","escapeHtml","profileImage","DEFAULT_PROFILE_IMAGE","npub","nip05","pubkey","renderContainer","renderName","renderNip05","renderNpub","leftContent","rightContent","getProfileBadgeStyles","getComponentStyles","EVT_BADGE","NostrProfileBadge","NostrUserComponent","_a","attachCopyDelegation","name","oldValue","newValue","_status","_user","_profile","key","_b","e","overall","NCStatus","parseBooleanAttribute","renderOptions"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var S=Object.defineProperty;var L=(e,o,t)=>o in e?S(e,o,{enumerable:!0,configurable:!0,writable:!0,value:t}):e[o]=t;var n=(e,o,t)=>L(e,typeof o!="symbol"?o+"":o,t);import{e as k,g as $,N as p}from"../assets/base-styles-
|
|
1
|
+
var S=Object.defineProperty;var L=(e,o,t)=>o in e?S(e,o,{enumerable:!0,configurable:!0,writable:!0,value:t}):e[o]=t;var n=(e,o,t)=>L(e,typeof o!="symbol"?o+"":o,t);import{e as k,g as $,N as p}from"../assets/base-styles-Dmuzg8I4.js";import{N as z}from"../assets/nostr-user-component-r-MUbTL6.js";import{r as F,a as C,b as E,c as N,d as A}from"../assets/copy-delegation-xzt-t_do.js";import"../assets/nostr-service-CA0Qx4nJ.js";import"../assets/user-resolver-ArI0680e.js";function l(e,o,t){const s=k(e);return`
|
|
2
2
|
<div class="stat" data-orientation="horizontal" aria-busy="${t}" aria-live="polite">
|
|
3
3
|
<div class="stat-inner">
|
|
4
4
|
<div class="stat-value">
|
|
@@ -7,7 +7,7 @@ var S=Object.defineProperty;var L=(e,o,t)=>o in e?S(e,o,{enumerable:!0,configura
|
|
|
7
7
|
<div class="stat-name">${s}</div>
|
|
8
8
|
</div>
|
|
9
9
|
</div>
|
|
10
|
-
`}function R(e){const{isLoading:o,isError:t,errorMessage:s,npub:i,userProfile:r,isStatsLoading:d,isStatsFollowersLoading:c,isStatsFollowsLoading:b,isZapsLoading:
|
|
10
|
+
`}function R(e){const{isLoading:o,isError:t,errorMessage:s,npub:i,userProfile:r,isStatsLoading:d,isStatsFollowersLoading:c,isStatsFollowsLoading:b,isZapsLoading:m,stats:a,showFollow:v,showNpub:w}=e;if(t)return Z(s||"");const h=(r==null?void 0:r.displayName)||(r==null?void 0:r.name)||"",u=(r==null?void 0:r.nip05)||"",x=(r==null?void 0:r.picture)||"",g=(r==null?void 0:r.about)||"",f=(r==null?void 0:r.website)||"",y=()=>!v||i===""?"":`
|
|
11
11
|
<nostr-follow-button
|
|
12
12
|
npub="${i}">
|
|
13
13
|
</nostr-follow-button>
|
|
@@ -38,7 +38,7 @@ var S=Object.defineProperty;var L=(e,o,t)=>o in e?S(e,o,{enumerable:!0,configura
|
|
|
38
38
|
|
|
39
39
|
${o?'<div style="width: 75px; height: 20px;" class="skeleton"></div>':C(u)}
|
|
40
40
|
|
|
41
|
-
${
|
|
41
|
+
${w?o?'<div style="width: 75px; height: 20px;" class="skeleton"></div>':E(i):""}
|
|
42
42
|
|
|
43
43
|
<div class="margin-bottom-md"> </div>
|
|
44
44
|
|
|
@@ -60,7 +60,7 @@ var S=Object.defineProperty;var L=(e,o,t)=>o in e?S(e,o,{enumerable:!0,configura
|
|
|
60
60
|
|
|
61
61
|
${l("Replies",a.replies,d)}
|
|
62
62
|
|
|
63
|
-
${l("Zaps",a.zaps,
|
|
63
|
+
${l("Zaps",a.zaps,m)}
|
|
64
64
|
|
|
65
65
|
</div>
|
|
66
66
|
</div>
|
|
@@ -283,5 +283,5 @@ var S=Object.defineProperty;var L=(e,o,t)=>o in e?S(e,o,{enumerable:!0,configura
|
|
|
283
283
|
`)}const j="nc:profile";class O extends z{constructor(){super(...arguments);n(this,"profileStatus",this.channel("profile"));n(this,"isStatsLoading",!0);n(this,"isStatsFollowsLoading",!0);n(this,"isStatsFollowersLoading",!0);n(this,"isZapsLoading",!0);n(this,"stats",{follows:0,followers:0,notes:0,replies:0,zaps:0,relays:0});n(this,"getUserStats",async()=>{try{this.isStatsLoading=!0,this.isStatsFollowsLoading=!0,this.isStatsFollowersLoading=!0,this.isZapsLoading=!0,this.nostrService.fetchFollows(this.user).then(t=>{this.stats={...this.stats,follows:t},this.isStatsFollowsLoading=!1,this.render()}).catch(t=>{console.error("Error loading follows:",t),this.isStatsFollowsLoading=!1,this.render()}),this.nostrService.fetchFollowers(this.user).then(t=>{this.stats={...this.stats,followers:t},this.isStatsFollowersLoading=!1,this.render()}).catch(t=>{console.error("Error loading followers:",t),this.isStatsFollowersLoading=!1,this.render()}),this.nostrService.fetchNotesAndReplies(this.user).then(([t,s])=>{this.stats={...this.stats,notes:t,replies:s},this.isStatsLoading=!1,this.render()}).catch(t=>{console.error("Error loading notes and replies",t),this.isStatsLoading=!1,this.render()}),this.nostrService.fetchZaps(this.user).then(t=>{this.stats={...this.stats,zaps:t},this.isZapsLoading=!1,this.render()}).catch(t=>{console.error("Error loading Zaps:",t),this.isZapsLoading=!1,this.render()})}catch(t){this.profileStatus.set(p.Error),console.error("getUserStats failed:",t)}finally{this.render()}})}static get observedAttributes(){return[...super.observedAttributes,"show-npub","show-follow"]}async connectedCallback(){var t;(t=super.connectedCallback)==null||t.call(this),this.attachDelegatedListeners(),A({addDelegatedListener:this.addDelegatedListener.bind(this)}),this.render()}onStatusChange(t){this.render()}onUserReady(t,s){this.getUserStats(),this.render()}attributeChangedCallback(t,s,i){var r;s!==i&&((r=super.attributeChangedCallback)==null||r.call(this,t,s,i),(t==="show-npub"||t==="show-follow")&&this.render())}onProfileClick(){var s,i;if(this.profileStatus.get()===p.Error)return;const t=((s=this.user)==null?void 0:s.npub)||this.getAttribute("npub")||((i=this.profile)==null?void 0:i.nip05)||this.getAttribute("nip05");t&&this.handleNjumpClick(j,this.profile,encodeURIComponent(t))}attachDelegatedListeners(){this.delegateEvent("click",".profile-banner",t=>{t.target.closest(".nc-copy-btn, .nostr-follow-button-container, nostr-follow-button")||this.onProfileClick()})}renderContent(){var c;const t=this.computeOverall()===p.Loading,s=this.computeOverall()===p.Error,i=this.getAttribute("show-npub")==="true",r=this.getAttribute("show-follow")==="true",d={isLoading:t,isError:s,errorMessage:this.errorMessage,npub:((c=this.user)==null?void 0:c.npub)||"",userProfile:this.profile,isStatsLoading:this.isStatsLoading,isStatsFollowersLoading:this.isStatsFollowersLoading,isStatsFollowsLoading:this.isStatsFollowsLoading,isZapsLoading:this.isZapsLoading,stats:{notes:this.stats.notes,replies:this.stats.replies,follows:this.stats.follows,followers:this.stats.followers,zaps:this.stats.zaps,relays:this.stats.relays},showFollow:r,showNpub:i};this.shadowRoot.innerHTML=`
|
|
284
284
|
${_()}
|
|
285
285
|
${R(d)}
|
|
286
|
-
`}}customElements.define("nostr-profile",O);export{O as default};
|
|
286
|
+
`}}customElements.get("nostr-profile")||customElements.define("nostr-profile",O);export{O as default};
|
|
287
287
|
//# sourceMappingURL=nostr-profile.es.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nostr-profile.es.js","sources":["../../src/nostr-profile/render-stats.ts","../../src/nostr-profile/render.ts","../../src/nostr-profile/style.ts","../../src/nostr-profile/nostr-profile.ts"],"sourcesContent":["// SPDX-License-Identifier: MIT\n\nimport { escapeHtml } from \"../common/utils\";\n\nexport function renderStats(\n label: string,\n value: number,\n isLoading: boolean\n): string {\n const safeLabel = escapeHtml(label)\n return `\n <div class=\"stat\" data-orientation=\"horizontal\" aria-busy=\"${isLoading}\" aria-live=\"polite\">\n <div class=\"stat-inner\">\n <div class=\"stat-value\">\n ${\n isLoading\n ? '<div style=\"width: 50px; height: 28px; border-radius: 5px\" class=\"skeleton\"></div>'\n : value.toLocaleString()\n }\n </div>\n <div class=\"stat-name\">${safeLabel}</div>\n </div>\n </div>\n `;\n}\n","// SPDX-License-Identifier: MIT\n\nimport { NDKUserProfile } from '@nostr-dev-kit/ndk';\nimport { IRenderOptions } from '../base/render-options';\nimport { renderNpub } from '../base/text-row/render-npub';\nimport { renderNip05 } from '../base/text-row/render-nip05';\nimport { renderStats } from './render-stats';\nimport { renderName } from '../base/text-row/render-name';\nimport { renderTextRow } from '../base/text-row/render-text-row';\n\nexport interface Stats {\n notes: number;\n replies: number;\n follows: number;\n followers: number;\n zaps: number;\n relays: number;\n}\n\nexport interface RenderProfileOptions extends IRenderOptions {\n npub: string;\n userProfile: NDKUserProfile;\n isStatsLoading: boolean;\n isStatsFollowersLoading: boolean;\n isStatsFollowsLoading: boolean;\n isZapsLoading: boolean;\n stats: Stats;\n showFollow: boolean;\n showNpub: boolean;\n}\n\nexport function renderProfile(options: RenderProfileOptions): string {\n const {\n isLoading,\n isError,\n errorMessage,\n npub,\n userProfile,\n isStatsLoading,\n isStatsFollowersLoading,\n isStatsFollowsLoading,\n isZapsLoading,\n stats,\n showFollow,\n showNpub,\n } = options;\n\n if (isError) {\n return renderError(errorMessage || '');\n }\n\n // Extract profile data with null checks and default values\n const displayName = userProfile?.displayName || userProfile?.name || '';\n const nip05 = userProfile?.nip05 || '';\n const image = userProfile?.picture || '';\n const about = userProfile?.about || '';\n const website = userProfile?.website || '';\n\n const renderFollowButton = () => {\n if (!showFollow || npub === '') return '';\n return `\n <nostr-follow-button\n npub=\"${npub}\">\n </nostr-follow-button>\n `;\n };\n\n return `\n <div class=\"nostr-profile-container\">\n <div class=\"profile-banner\">\n ${isLoading\n ? '<div style=\"width: 100%; height: 100%;\" class=\"skeleton\"></div>'\n : userProfile?.banner\n ? `<img src=\"${userProfile.banner}\" width=\"524px\"/>`\n : '<div class=\"banner-placeholder\"></div>'\n }\n\n <div class=\"dp-container\">\n <div class=\"avatar\" role=\"img\" aria-label=\"${displayName}\">\n ${isLoading\n ? '<div style=\"width: 100%; height: 100%; border-radius: 50%\" class=\"skeleton\"></div>'\n : `<img\n src=\"${image}\"\n alt=\"${displayName}\"\n width=\"142\" height=\"142\"\n loading=\"lazy\" decoding=\"async\"\n onerror=\"this.onerror=null; this.src='data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 142 142%22%3E%3Crect width=%22142%22 height=%22142%22 fill=%22%23ccc%22/%3E%3C/svg%3E'\"\n />`\n }\n </div>\n </div>\n </div>\n\n <div class=\"profile_actions\">\n ${showFollow ?\n isLoading? '<div style=\"width: 100px; height: 36px; border-radius: 18px;\" class=\"skeleton\"></div>'\n : renderFollowButton()\n : ''\n }\n </div>\n \n <div class=\"profile_data\">\n ${isLoading\n ? '<div style=\"width: 100px; height: 24px;\" class=\"skeleton\"></div>'\n : renderName({ name: displayName })\n }\n \n ${isLoading\n ? '<div style=\"width: 75px; height: 20px;\" class=\"skeleton\"></div>'\n : renderNip05(nip05)\n }\n\n ${showNpub ?\n isLoading\n ? '<div style=\"width: 75px; height: 20px;\" class=\"skeleton\"></div>'\n : renderNpub(npub)\n : ''\n }\n\n <div class=\"margin-bottom-md\"> </div>\n \n ${isLoading\n ? `<div style=\"width: 100%; margin-bottom: 12px; height: 18px\" class=\"skeleton\"></div>`\n : renderTextRow({ display: about, value: about })\n }\n\n <div class=\"margin-bottom-md\"> </div>\n \n ${isLoading\n ? '<div style=\"width: 150px\" class=\"skeleton\"></div>'\n : website\n ? `<div class=\"website\">\n <a target=\"_blank\" href=\"${website}\">${website}</a>\n </div>`\n : ''\n }\n \n <div class=\"stats\">\n\n ${renderStats('Following', stats.follows, isStatsFollowsLoading)}\n \n ${renderStats('Followers', stats.followers, isStatsFollowersLoading)}\n\n ${renderStats('Notes', stats.notes, isStatsLoading)}\n \n ${renderStats('Replies', stats.replies, isStatsLoading)}\n \n ${renderStats('Zaps', stats.zaps, isZapsLoading)}\n \n </div>\n </div>\n </div>\n `;\n}\n\nfunction renderError(errorMessage: string): string {\n return `\n <div class='nostr-profile-container'>\n <div class='nostr-profile-top-container'>\n <div class=\"error-icon\">⚠</div>\n </div>\n <div class='nostr-profile-bottom-container'>\n ${errorMessage}\n </div>\n </div>\n `;\n}","// SPDX-License-Identifier: MIT\n\nimport { getComponentStyles } from \"../common/base-styles\";\n\nexport function getProfileStyles(): string {\n const customStyles = `\n /* === PROFILE CSS VARIABLES & CONTAINER PATTERN === */\n :host {\n /* Override follow button styles for profile context */\n --nostrc-follow-btn-padding: 5px 8px !important;\n --nostrc-follow-btn-font-size: 14px !important;\n --nostrc-follow-btn-border-radius: 12px !important;\n --nostrc-follow-btn-border: var(--nostrc-border-width) solid var(--nostrc-color-border) !important;\n --nostrc-follow-btn-horizontal-alignment: end !important;\n --nostrc-follow-btn-min-height: auto !important;\n --nostrc-follow-btn-width: 280px;\n\n /* Component theme variables (fallback to global theme tokens) */\n --nostrc-profile-bg: var(--nostrc-theme-bg, #ffffff);\n --nostrc-profile-text-primary: var(--nostrc-theme-text-primary, #333333);\n --nostrc-profile-text-secondary: var(--nostrc-theme-text-secondary, #666666);\n --nostrc-profile-border: var(--nostrc-theme-border, var(--nostrc-border-width) solid var(--nostrc-color-border));\n --nostrc-profile-banner-placeholder: var(--nostrc-profile-border);\n --nostrc-profile-font-family: var(--nostrc-font-family-primary);\n --nostrc-profile-font-size: var(--nostrc-font-size-base);\n \n /* Hover state variables */\n --nostrc-profile-hover-bg: var(--nostrc-theme-hover-bg, rgba(0, 0, 0, 0.05));\n --nostrc-profile-hover-color: var(--nostrc-theme-text-primary, #333333);\n --nostrc-profile-hover-border: var(--nostrc-theme-hover-border, var(--nostrc-border-width) solid var(--nostrc-color-border));\n\n /* Make the host the visual profile surface */\n display: block;\n background: var(--nostrc-profile-bg);\n color: var(--nostrc-profile-text-primary);\n border: var(--nostrc-profile-border);\n border-radius: var(--nostrc-border-radius-md);\n font-family: var(--nostrc-profile-font-family);\n font-size: var(--nostrc-profile-font-size);\n transition: background-color var(--nostrc-transition-duration) var(--nostrc-transition-timing);\n }\n\n .nostr-profile-container {\n display: flex;\n flex-direction: column;\n align-items: stretch;\n gap: var(--nostrc-spacing-md);\n min-height: 500px;\n padding: 0px;\n }\n\n :host(.is-error) .nostr-profile-container {\n justify-content: center;\n align-items: center;\n color: var(--nostrc-color-error-text);\n border: var(--nostrc-border-width) solid var(--nostrc-color-error-text);\n }\n\n /* Hover state */\n :host(.is-clickable:hover) {\n background: var(--nostrc-profile-hover-bg);\n color: var(--nostrc-profile-hover-color);\n border: var(--nostrc-profile-hover-border);\n }\n\n .nostr-profile-top-container img {\n width: 100%;\n height: 100%;\n border-radius: 50%;\n object-fit: cover;\n }\n\n .nostr-profile-bottom-container {\n min-width: 0;\n text-align: center;\n }\n\n .profile-banner {\n position: relative;\n width: 100%;\n height: 214px;\n cursor: pointer;\n border-radius: var(--nostrc-border-radius-md) var(--nostrc-border-radius-md) 0px 0px;\n }\n\n .banner-placeholder {\n width: 100%;\n height: 100%;\n background-color: var(--nostrc-profile-banner-placeholder);\n border-radius: var(--nostrc-border-radius-md) var(--nostrc-border-radius-md) 0px 0px;\n }\n\n .profile-banner img {\n width: 100%;\n height: 214px;\n object-fit: cover;\n }\n\n .dp-container {\n position: absolute;\n top: 140px;\n left: var(--nostrc-spacing-md);\n }\n\n .avatar {\n --avatar-size: 142px;\n --avatar-ring: 4px;\n\n inline-size: var(--avatar-size);\n block-size: var(--avatar-size);\n border-radius: var(--nostrc-border-radius-full);\n overflow: hidden;\n\n /* ring + backfill in one place */\n background-color: var(--nostrc-profile-bg);\n border: var(--avatar-ring) solid var(--nostrc-profile-bg);\n }\n\n .avatar img {\n inline-size: 100%;\n block-size: 100%;\n border-radius: var(--nostrc-border-radius-full);\n display: block;\n object-fit: cover;\n }\n\n .profile_actions {\n height: 56px;\n align-self: flex-end;\n padding: 0 var(--nostrc-spacing-lg);\n }\n\n .profile_data {\n padding: var(--nostrc-spacing-md);\n }\n\n .website {\n font-weight: 400;\n font-size: var(--nostrc-font-size-base);\n line-height: 20px;\n display: flex;\n align-items: center;\n }\n\n .website a {\n line-height: 20px;\n outline: none;\n color: var(--nostrc-profile-accent);\n max-width: 350px;\n overflow: hidden;\n text-overflow: ellipsis;\n word-wrap: normal;\n }\n\n .stats {\n position: relative;\n display: flex;\n flex-direction: row;\n flex-wrap: wrap;\n justify-content: space-between;\n align-items: center;\n border-radius: 0;\n border-top: none;\n margin-top: var(--nostrc-spacing-md);\n }\n\n .stat {\n position: relative;\n display: inline-block;\n padding-inline: var(--nostrc-spacing-md);\n padding-block: var(--nostrc-spacing-xs);\n border: none;\n background: none;\n width: fit-content;\n height: 40px;\n margin: 0 0 var(--nostrc-spacing-md);\n }\n\n .stat-inner {\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n }\n\n .stat-inner .stat-value {\n font-weight: 100;\n font-size: 1.5em;\n color: var(--nostrc-profile-text-primary);\n }\n\n .stat-inner .stat-name {\n font-weight: 400;\n line-height: 16px;\n text-transform: lowercase;\n color: var(--nostrc-profile-text-secondary);\n }\n\n @media only screen and (max-width: 600px) {\n .stat .stat-value {\n font-size: 18px !important;\n }\n :host {\n --nostrc-follow-btn-padding: 5px 8px !important;\n --nostrc-follow-btn-font-size: 12px !important;\n --nostrc-follow-btn-min-height: auto !important;\n --nostrc-follow-btn-border-radius: 8px !important;\n --nostrc-follow-btn-error-max-width: 150px !important;\n }\n }\n\n `;\n \n // Use component styles - includes design tokens + utilities + custom styles\n return getComponentStyles(customStyles);\n}\n","// SPDX-License-Identifier: MIT\n\nimport { NCStatus } from '../base/base-component/nostr-base-component';\nimport { NostrUserComponent } from '../base/user-component/nostr-user-component';\nimport { renderProfile, RenderProfileOptions } from './render';\nimport { getProfileStyles } from './style';\nimport { attachCopyDelegation } from '../base/copy-delegation';\n\nconst EVT_PROFILE = 'nc:profile';\n\nexport default class NostrProfile extends NostrUserComponent {\n\n protected profileStatus = this.channel('profile');\n\n // Stats loading states\n private isStatsLoading: boolean = true;\n private isStatsFollowsLoading: boolean = true;\n private isStatsFollowersLoading: boolean = true;\n private isZapsLoading: boolean = true;\n\n private stats = {\n follows: 0,\n followers: 0,\n notes: 0,\n replies: 0,\n zaps: 0,\n relays: 0,\n };\n\n static get observedAttributes() {\n return [\n ...super.observedAttributes,\n 'show-npub',\n 'show-follow',\n ];\n }\n\n async connectedCallback() {\n super.connectedCallback?.();\n this.attachDelegatedListeners();\n attachCopyDelegation({\n addDelegatedListener: this.addDelegatedListener.bind(this),\n });\n this.render();\n }\n\n /** Base class functions */\n protected onStatusChange(_status: NCStatus) {\n this.render();\n }\n\n protected onUserReady(_user: any, _profile: any) {\n this.getUserStats();\n this.render();\n }\n\n getUserStats = async () => {\n try {\n this.isStatsLoading = true;\n this.isStatsFollowsLoading = true;\n this.isStatsFollowersLoading = true;\n this.isZapsLoading = true;\n\n // Fetch follows\n this.nostrService\n .fetchFollows(this.user!)\n .then((follows) => {\n this.stats = { ...this.stats, follows };\n this.isStatsFollowsLoading = false;\n this.render();\n })\n .catch(err => {\n console.error('Error loading follows:', err);\n this.isStatsFollowsLoading = false;\n this.render();\n });\n\n // Fetch followers\n this.nostrService\n .fetchFollowers(this.user!)\n .then((followers) => {\n this.stats = { ...this.stats, followers };\n this.isStatsFollowersLoading = false;\n this.render();\n })\n .catch(err => {\n console.error('Error loading followers:', err);\n this.isStatsFollowersLoading = false;\n this.render();\n });\n\n // Fetch notes and replies\n this.nostrService\n .fetchNotesAndReplies(this.user!)\n .then(([ notes, replies ]) => {\n this.stats = { ...this.stats, notes, replies };\n this.isStatsLoading = false;\n this.render();\n })\n .catch(err => {\n console.error('Error loading notes and replies', err);\n this.isStatsLoading = false;\n this.render();\n });\n\n // Fetch zaps\n this.nostrService\n .fetchZaps(this.user!)\n .then((zaps) => {\n this.stats = { ...this.stats, zaps };\n this.isZapsLoading = false;\n this.render();\n })\n .catch(err => {\n console.error('Error loading Zaps:', err);\n this.isZapsLoading = false;\n this.render();\n });\n\n\n } catch (err) {\n this.profileStatus.set(NCStatus.Error);\n console.error('getUserStats failed:', err);\n } finally {\n this.render();\n }\n };\n\n attributeChangedCallback(\n name: string,\n oldValue: string | null,\n newValue: string | null\n ) {\n if (oldValue === newValue) return;\n super.attributeChangedCallback?.(name, oldValue, newValue);\n\n if (name === 'show-npub' || name === 'show-follow') {\n this.render();\n }\n }\n\n /** Private functions */\n private onProfileClick() {\n if (this.profileStatus.get() === NCStatus.Error) return;\n\n const key =\n this.user?.npub ||\n this.getAttribute('npub') ||\n this.profile?.nip05 ||\n this.getAttribute('nip05');\n\n if (key) {\n this.handleNjumpClick(EVT_PROFILE, this.profile, encodeURIComponent(key));\n }\n }\n\n private attachDelegatedListeners() {\n\n // Click anywhere on the profile badge (except follow button, copy buttons)\n this.delegateEvent('click', '.profile-banner', (e: Event) => {\n const target = e.target as HTMLElement;\n if (!target.closest('.nc-copy-btn, .nostr-follow-button-container, nostr-follow-button')) {\n this.onProfileClick();\n }\n });\n\n }\n\n protected renderContent() {\n const isLoading = this.computeOverall() === NCStatus.Loading;\n const isError = this.computeOverall() === NCStatus.Error;\n const showNpub = this.getAttribute('show-npub') === 'true';\n const showFollow = this.getAttribute('show-follow') === 'true';\n\n const renderOptions: RenderProfileOptions = {\n isLoading: isLoading,\n isError: isError,\n errorMessage: this.errorMessage,\n npub: this.user?.npub || '',\n userProfile: this.profile!,\n isStatsLoading: this.isStatsLoading,\n isStatsFollowersLoading: this.isStatsFollowersLoading,\n isStatsFollowsLoading: this.isStatsFollowsLoading,\n isZapsLoading: this.isZapsLoading,\n stats: {\n notes: this.stats.notes,\n replies: this.stats.replies,\n follows: this.stats.follows,\n followers: this.stats.followers,\n zaps: this.stats.zaps,\n relays: this.stats.relays,\n },\n showFollow: showFollow,\n showNpub: showNpub,\n };\n\n this.shadowRoot!.innerHTML = `\n ${getProfileStyles()}\n ${renderProfile(renderOptions)}\n `;\n\n }\n}\n\ncustomElements.define('nostr-profile', NostrProfile);\n"],"names":["renderStats","label","value","isLoading","safeLabel","escapeHtml","renderProfile","options","isError","errorMessage","npub","userProfile","isStatsLoading","isStatsFollowersLoading","isStatsFollowsLoading","isZapsLoading","stats","showFollow","showNpub","renderError","displayName","nip05","image","about","website","renderFollowButton","renderName","renderNip05","renderNpub","renderTextRow","getProfileStyles","getComponentStyles","EVT_PROFILE","NostrProfile","NostrUserComponent","__publicField","follows","err","followers","notes","replies","zaps","NCStatus","_a","attachCopyDelegation","_status","_user","_profile","name","oldValue","newValue","key","_b","e","renderOptions"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"nostr-profile.es.js","sources":["../../src/nostr-profile/render-stats.ts","../../src/nostr-profile/render.ts","../../src/nostr-profile/style.ts","../../src/nostr-profile/nostr-profile.ts"],"sourcesContent":["// SPDX-License-Identifier: MIT\n\nimport { escapeHtml } from \"../common/utils\";\n\nexport function renderStats(\n label: string,\n value: number,\n isLoading: boolean\n): string {\n const safeLabel = escapeHtml(label)\n return `\n <div class=\"stat\" data-orientation=\"horizontal\" aria-busy=\"${isLoading}\" aria-live=\"polite\">\n <div class=\"stat-inner\">\n <div class=\"stat-value\">\n ${\n isLoading\n ? '<div style=\"width: 50px; height: 28px; border-radius: 5px\" class=\"skeleton\"></div>'\n : value.toLocaleString()\n }\n </div>\n <div class=\"stat-name\">${safeLabel}</div>\n </div>\n </div>\n `;\n}\n","// SPDX-License-Identifier: MIT\n\nimport { NDKUserProfile } from '@nostr-dev-kit/ndk';\nimport { IRenderOptions } from '../base/render-options';\nimport { renderNpub } from '../base/text-row/render-npub';\nimport { renderNip05 } from '../base/text-row/render-nip05';\nimport { renderStats } from './render-stats';\nimport { renderName } from '../base/text-row/render-name';\nimport { renderTextRow } from '../base/text-row/render-text-row';\n\nexport interface Stats {\n notes: number;\n replies: number;\n follows: number;\n followers: number;\n zaps: number;\n relays: number;\n}\n\nexport interface RenderProfileOptions extends IRenderOptions {\n npub: string;\n userProfile: NDKUserProfile;\n isStatsLoading: boolean;\n isStatsFollowersLoading: boolean;\n isStatsFollowsLoading: boolean;\n isZapsLoading: boolean;\n stats: Stats;\n showFollow: boolean;\n showNpub: boolean;\n}\n\nexport function renderProfile(options: RenderProfileOptions): string {\n const {\n isLoading,\n isError,\n errorMessage,\n npub,\n userProfile,\n isStatsLoading,\n isStatsFollowersLoading,\n isStatsFollowsLoading,\n isZapsLoading,\n stats,\n showFollow,\n showNpub,\n } = options;\n\n if (isError) {\n return renderError(errorMessage || '');\n }\n\n // Extract profile data with null checks and default values\n const displayName = userProfile?.displayName || userProfile?.name || '';\n const nip05 = userProfile?.nip05 || '';\n const image = userProfile?.picture || '';\n const about = userProfile?.about || '';\n const website = userProfile?.website || '';\n\n const renderFollowButton = () => {\n if (!showFollow || npub === '') return '';\n return `\n <nostr-follow-button\n npub=\"${npub}\">\n </nostr-follow-button>\n `;\n };\n\n return `\n <div class=\"nostr-profile-container\">\n <div class=\"profile-banner\">\n ${isLoading\n ? '<div style=\"width: 100%; height: 100%;\" class=\"skeleton\"></div>'\n : userProfile?.banner\n ? `<img src=\"${userProfile.banner}\" width=\"524px\"/>`\n : '<div class=\"banner-placeholder\"></div>'\n }\n\n <div class=\"dp-container\">\n <div class=\"avatar\" role=\"img\" aria-label=\"${displayName}\">\n ${isLoading\n ? '<div style=\"width: 100%; height: 100%; border-radius: 50%\" class=\"skeleton\"></div>'\n : `<img\n src=\"${image}\"\n alt=\"${displayName}\"\n width=\"142\" height=\"142\"\n loading=\"lazy\" decoding=\"async\"\n onerror=\"this.onerror=null; this.src='data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 142 142%22%3E%3Crect width=%22142%22 height=%22142%22 fill=%22%23ccc%22/%3E%3C/svg%3E'\"\n />`\n }\n </div>\n </div>\n </div>\n\n <div class=\"profile_actions\">\n ${showFollow ?\n isLoading? '<div style=\"width: 100px; height: 36px; border-radius: 18px;\" class=\"skeleton\"></div>'\n : renderFollowButton()\n : ''\n }\n </div>\n \n <div class=\"profile_data\">\n ${isLoading\n ? '<div style=\"width: 100px; height: 24px;\" class=\"skeleton\"></div>'\n : renderName({ name: displayName })\n }\n \n ${isLoading\n ? '<div style=\"width: 75px; height: 20px;\" class=\"skeleton\"></div>'\n : renderNip05(nip05)\n }\n\n ${showNpub ?\n isLoading\n ? '<div style=\"width: 75px; height: 20px;\" class=\"skeleton\"></div>'\n : renderNpub(npub)\n : ''\n }\n\n <div class=\"margin-bottom-md\"> </div>\n \n ${isLoading\n ? `<div style=\"width: 100%; margin-bottom: 12px; height: 18px\" class=\"skeleton\"></div>`\n : renderTextRow({ display: about, value: about })\n }\n\n <div class=\"margin-bottom-md\"> </div>\n \n ${isLoading\n ? '<div style=\"width: 150px\" class=\"skeleton\"></div>'\n : website\n ? `<div class=\"website\">\n <a target=\"_blank\" href=\"${website}\">${website}</a>\n </div>`\n : ''\n }\n \n <div class=\"stats\">\n\n ${renderStats('Following', stats.follows, isStatsFollowsLoading)}\n \n ${renderStats('Followers', stats.followers, isStatsFollowersLoading)}\n\n ${renderStats('Notes', stats.notes, isStatsLoading)}\n \n ${renderStats('Replies', stats.replies, isStatsLoading)}\n \n ${renderStats('Zaps', stats.zaps, isZapsLoading)}\n \n </div>\n </div>\n </div>\n `;\n}\n\nfunction renderError(errorMessage: string): string {\n return `\n <div class='nostr-profile-container'>\n <div class='nostr-profile-top-container'>\n <div class=\"error-icon\">⚠</div>\n </div>\n <div class='nostr-profile-bottom-container'>\n ${errorMessage}\n </div>\n </div>\n `;\n}","// SPDX-License-Identifier: MIT\n\nimport { getComponentStyles } from \"../common/base-styles\";\n\nexport function getProfileStyles(): string {\n const customStyles = `\n /* === PROFILE CSS VARIABLES & CONTAINER PATTERN === */\n :host {\n /* Override follow button styles for profile context */\n --nostrc-follow-btn-padding: 5px 8px !important;\n --nostrc-follow-btn-font-size: 14px !important;\n --nostrc-follow-btn-border-radius: 12px !important;\n --nostrc-follow-btn-border: var(--nostrc-border-width) solid var(--nostrc-color-border) !important;\n --nostrc-follow-btn-horizontal-alignment: end !important;\n --nostrc-follow-btn-min-height: auto !important;\n --nostrc-follow-btn-width: 280px;\n\n /* Component theme variables (fallback to global theme tokens) */\n --nostrc-profile-bg: var(--nostrc-theme-bg, #ffffff);\n --nostrc-profile-text-primary: var(--nostrc-theme-text-primary, #333333);\n --nostrc-profile-text-secondary: var(--nostrc-theme-text-secondary, #666666);\n --nostrc-profile-border: var(--nostrc-theme-border, var(--nostrc-border-width) solid var(--nostrc-color-border));\n --nostrc-profile-banner-placeholder: var(--nostrc-profile-border);\n --nostrc-profile-font-family: var(--nostrc-font-family-primary);\n --nostrc-profile-font-size: var(--nostrc-font-size-base);\n \n /* Hover state variables */\n --nostrc-profile-hover-bg: var(--nostrc-theme-hover-bg, rgba(0, 0, 0, 0.05));\n --nostrc-profile-hover-color: var(--nostrc-theme-text-primary, #333333);\n --nostrc-profile-hover-border: var(--nostrc-theme-hover-border, var(--nostrc-border-width) solid var(--nostrc-color-border));\n\n /* Make the host the visual profile surface */\n display: block;\n background: var(--nostrc-profile-bg);\n color: var(--nostrc-profile-text-primary);\n border: var(--nostrc-profile-border);\n border-radius: var(--nostrc-border-radius-md);\n font-family: var(--nostrc-profile-font-family);\n font-size: var(--nostrc-profile-font-size);\n transition: background-color var(--nostrc-transition-duration) var(--nostrc-transition-timing);\n }\n\n .nostr-profile-container {\n display: flex;\n flex-direction: column;\n align-items: stretch;\n gap: var(--nostrc-spacing-md);\n min-height: 500px;\n padding: 0px;\n }\n\n :host(.is-error) .nostr-profile-container {\n justify-content: center;\n align-items: center;\n color: var(--nostrc-color-error-text);\n border: var(--nostrc-border-width) solid var(--nostrc-color-error-text);\n }\n\n /* Hover state */\n :host(.is-clickable:hover) {\n background: var(--nostrc-profile-hover-bg);\n color: var(--nostrc-profile-hover-color);\n border: var(--nostrc-profile-hover-border);\n }\n\n .nostr-profile-top-container img {\n width: 100%;\n height: 100%;\n border-radius: 50%;\n object-fit: cover;\n }\n\n .nostr-profile-bottom-container {\n min-width: 0;\n text-align: center;\n }\n\n .profile-banner {\n position: relative;\n width: 100%;\n height: 214px;\n cursor: pointer;\n border-radius: var(--nostrc-border-radius-md) var(--nostrc-border-radius-md) 0px 0px;\n }\n\n .banner-placeholder {\n width: 100%;\n height: 100%;\n background-color: var(--nostrc-profile-banner-placeholder);\n border-radius: var(--nostrc-border-radius-md) var(--nostrc-border-radius-md) 0px 0px;\n }\n\n .profile-banner img {\n width: 100%;\n height: 214px;\n object-fit: cover;\n }\n\n .dp-container {\n position: absolute;\n top: 140px;\n left: var(--nostrc-spacing-md);\n }\n\n .avatar {\n --avatar-size: 142px;\n --avatar-ring: 4px;\n\n inline-size: var(--avatar-size);\n block-size: var(--avatar-size);\n border-radius: var(--nostrc-border-radius-full);\n overflow: hidden;\n\n /* ring + backfill in one place */\n background-color: var(--nostrc-profile-bg);\n border: var(--avatar-ring) solid var(--nostrc-profile-bg);\n }\n\n .avatar img {\n inline-size: 100%;\n block-size: 100%;\n border-radius: var(--nostrc-border-radius-full);\n display: block;\n object-fit: cover;\n }\n\n .profile_actions {\n height: 56px;\n align-self: flex-end;\n padding: 0 var(--nostrc-spacing-lg);\n }\n\n .profile_data {\n padding: var(--nostrc-spacing-md);\n }\n\n .website {\n font-weight: 400;\n font-size: var(--nostrc-font-size-base);\n line-height: 20px;\n display: flex;\n align-items: center;\n }\n\n .website a {\n line-height: 20px;\n outline: none;\n color: var(--nostrc-profile-accent);\n max-width: 350px;\n overflow: hidden;\n text-overflow: ellipsis;\n word-wrap: normal;\n }\n\n .stats {\n position: relative;\n display: flex;\n flex-direction: row;\n flex-wrap: wrap;\n justify-content: space-between;\n align-items: center;\n border-radius: 0;\n border-top: none;\n margin-top: var(--nostrc-spacing-md);\n }\n\n .stat {\n position: relative;\n display: inline-block;\n padding-inline: var(--nostrc-spacing-md);\n padding-block: var(--nostrc-spacing-xs);\n border: none;\n background: none;\n width: fit-content;\n height: 40px;\n margin: 0 0 var(--nostrc-spacing-md);\n }\n\n .stat-inner {\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n }\n\n .stat-inner .stat-value {\n font-weight: 100;\n font-size: 1.5em;\n color: var(--nostrc-profile-text-primary);\n }\n\n .stat-inner .stat-name {\n font-weight: 400;\n line-height: 16px;\n text-transform: lowercase;\n color: var(--nostrc-profile-text-secondary);\n }\n\n @media only screen and (max-width: 600px) {\n .stat .stat-value {\n font-size: 18px !important;\n }\n :host {\n --nostrc-follow-btn-padding: 5px 8px !important;\n --nostrc-follow-btn-font-size: 12px !important;\n --nostrc-follow-btn-min-height: auto !important;\n --nostrc-follow-btn-border-radius: 8px !important;\n --nostrc-follow-btn-error-max-width: 150px !important;\n }\n }\n\n `;\n \n // Use component styles - includes design tokens + utilities + custom styles\n return getComponentStyles(customStyles);\n}\n","// SPDX-License-Identifier: MIT\n\nimport { NCStatus } from '../base/base-component/nostr-base-component';\nimport { NostrUserComponent } from '../base/user-component/nostr-user-component';\nimport { renderProfile, RenderProfileOptions } from './render';\nimport { getProfileStyles } from './style';\nimport { attachCopyDelegation } from '../base/copy-delegation';\n\nconst EVT_PROFILE = 'nc:profile';\n\nexport default class NostrProfile extends NostrUserComponent {\n\n protected profileStatus = this.channel('profile');\n\n // Stats loading states\n private isStatsLoading: boolean = true;\n private isStatsFollowsLoading: boolean = true;\n private isStatsFollowersLoading: boolean = true;\n private isZapsLoading: boolean = true;\n\n private stats = {\n follows: 0,\n followers: 0,\n notes: 0,\n replies: 0,\n zaps: 0,\n relays: 0,\n };\n\n static get observedAttributes() {\n return [\n ...super.observedAttributes,\n 'show-npub',\n 'show-follow',\n ];\n }\n\n async connectedCallback() {\n super.connectedCallback?.();\n this.attachDelegatedListeners();\n attachCopyDelegation({\n addDelegatedListener: this.addDelegatedListener.bind(this),\n });\n this.render();\n }\n\n /** Base class functions */\n protected onStatusChange(_status: NCStatus) {\n this.render();\n }\n\n protected onUserReady(_user: any, _profile: any) {\n this.getUserStats();\n this.render();\n }\n\n getUserStats = async () => {\n try {\n this.isStatsLoading = true;\n this.isStatsFollowsLoading = true;\n this.isStatsFollowersLoading = true;\n this.isZapsLoading = true;\n\n // Fetch follows\n this.nostrService\n .fetchFollows(this.user!)\n .then((follows) => {\n this.stats = { ...this.stats, follows };\n this.isStatsFollowsLoading = false;\n this.render();\n })\n .catch(err => {\n console.error('Error loading follows:', err);\n this.isStatsFollowsLoading = false;\n this.render();\n });\n\n // Fetch followers\n this.nostrService\n .fetchFollowers(this.user!)\n .then((followers) => {\n this.stats = { ...this.stats, followers };\n this.isStatsFollowersLoading = false;\n this.render();\n })\n .catch(err => {\n console.error('Error loading followers:', err);\n this.isStatsFollowersLoading = false;\n this.render();\n });\n\n // Fetch notes and replies\n this.nostrService\n .fetchNotesAndReplies(this.user!)\n .then(([ notes, replies ]) => {\n this.stats = { ...this.stats, notes, replies };\n this.isStatsLoading = false;\n this.render();\n })\n .catch(err => {\n console.error('Error loading notes and replies', err);\n this.isStatsLoading = false;\n this.render();\n });\n\n // Fetch zaps\n this.nostrService\n .fetchZaps(this.user!)\n .then((zaps) => {\n this.stats = { ...this.stats, zaps };\n this.isZapsLoading = false;\n this.render();\n })\n .catch(err => {\n console.error('Error loading Zaps:', err);\n this.isZapsLoading = false;\n this.render();\n });\n\n\n } catch (err) {\n this.profileStatus.set(NCStatus.Error);\n console.error('getUserStats failed:', err);\n } finally {\n this.render();\n }\n };\n\n attributeChangedCallback(\n name: string,\n oldValue: string | null,\n newValue: string | null\n ) {\n if (oldValue === newValue) return;\n super.attributeChangedCallback?.(name, oldValue, newValue);\n\n if (name === 'show-npub' || name === 'show-follow') {\n this.render();\n }\n }\n\n /** Private functions */\n private onProfileClick() {\n if (this.profileStatus.get() === NCStatus.Error) return;\n\n const key =\n this.user?.npub ||\n this.getAttribute('npub') ||\n this.profile?.nip05 ||\n this.getAttribute('nip05');\n\n if (key) {\n this.handleNjumpClick(EVT_PROFILE, this.profile, encodeURIComponent(key));\n }\n }\n\n private attachDelegatedListeners() {\n\n // Click anywhere on the profile badge (except follow button, copy buttons)\n this.delegateEvent('click', '.profile-banner', (e: Event) => {\n const target = e.target as HTMLElement;\n if (!target.closest('.nc-copy-btn, .nostr-follow-button-container, nostr-follow-button')) {\n this.onProfileClick();\n }\n });\n\n }\n\n protected renderContent() {\n const isLoading = this.computeOverall() === NCStatus.Loading;\n const isError = this.computeOverall() === NCStatus.Error;\n const showNpub = this.getAttribute('show-npub') === 'true';\n const showFollow = this.getAttribute('show-follow') === 'true';\n\n const renderOptions: RenderProfileOptions = {\n isLoading: isLoading,\n isError: isError,\n errorMessage: this.errorMessage,\n npub: this.user?.npub || '',\n userProfile: this.profile!,\n isStatsLoading: this.isStatsLoading,\n isStatsFollowersLoading: this.isStatsFollowersLoading,\n isStatsFollowsLoading: this.isStatsFollowsLoading,\n isZapsLoading: this.isZapsLoading,\n stats: {\n notes: this.stats.notes,\n replies: this.stats.replies,\n follows: this.stats.follows,\n followers: this.stats.followers,\n zaps: this.stats.zaps,\n relays: this.stats.relays,\n },\n showFollow: showFollow,\n showNpub: showNpub,\n };\n\n this.shadowRoot!.innerHTML = `\n ${getProfileStyles()}\n ${renderProfile(renderOptions)}\n `;\n\n }\n}\n\nif (!customElements.get('nostr-profile')) {\n customElements.define('nostr-profile', NostrProfile);\n}\n"],"names":["renderStats","label","value","isLoading","safeLabel","escapeHtml","renderProfile","options","isError","errorMessage","npub","userProfile","isStatsLoading","isStatsFollowersLoading","isStatsFollowsLoading","isZapsLoading","stats","showFollow","showNpub","renderError","displayName","nip05","image","about","website","renderFollowButton","renderName","renderNip05","renderNpub","renderTextRow","getProfileStyles","getComponentStyles","EVT_PROFILE","NostrProfile","NostrUserComponent","__publicField","follows","err","followers","notes","replies","zaps","NCStatus","_a","attachCopyDelegation","_status","_user","_profile","name","oldValue","newValue","key","_b","e","renderOptions"],"mappings":"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"}
|