nostr-components 0.2.7 → 0.3.0
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 +105 -185
- package/dist/assets/{base-styles-BSEzBDsk.js → base-styles-DC0ilu4S.js} +3 -3
- package/dist/assets/{base-styles-BSEzBDsk.js.map → base-styles-DC0ilu4S.js.map} +1 -1
- package/dist/assets/{copy-delegation-B7y2q5Kn.js → copy-delegation-CcagQMIW.js} +5 -5
- package/dist/assets/{copy-delegation-B7y2q5Kn.js.map → copy-delegation-CcagQMIW.js.map} +1 -1
- package/dist/assets/{dialog-component-Da1ZIYh9.js → dialog-component-Dqg0QU9I.js} +2 -7
- package/dist/assets/dialog-component-Dqg0QU9I.js.map +1 -0
- package/dist/assets/{dialog-likers-BqDn2P_3.js → dialog-likers-D3c7WIMp.js} +5 -5
- package/dist/assets/dialog-likers-D3c7WIMp.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-m3Hgc5Xx.js +266 -0
- package/dist/assets/nostr-service-m3Hgc5Xx.js.map +1 -0
- package/dist/assets/nostr-user-component-XEnanH-d.js +2 -0
- package/dist/assets/nostr-user-component-XEnanH-d.js.map +1 -0
- package/dist/assets/{pure-DPo-pzxM.js → pure-laCRX9eG.js} +2 -2
- package/dist/assets/pure-laCRX9eG.js.map +1 -0
- package/dist/assets/{theme-BN1Bvweb.js → theme-C1r1Zw8r.js} +2 -2
- package/dist/assets/{theme-BN1Bvweb.js.map → theme-C1r1Zw8r.js.map} +1 -1
- package/dist/assets/{user-resolver-CMmbtY9Y.js → user-resolver-DqI5KGh6.js} +2 -2
- package/dist/assets/{user-resolver-CMmbtY9Y.js.map → user-resolver-DqI5KGh6.js.map} +1 -1
- package/dist/assets/utils--bxLbhGF.js.map +1 -1
- package/dist/assets/zap-utils-BZcaCsT_.js +2 -0
- package/dist/assets/zap-utils-BZcaCsT_.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 +3 -3
- package/dist/components/nostr-profile-badge.es.js.map +1 -1
- package/dist/components/nostr-profile.es.js +2 -2
- 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 +2644 -305
- package/dist/nostr-components.umd.js.map +1 -1
- package/package.json +5 -2
- package/dist/assets/dark-nostrich-running.gif +0 -0
- package/dist/assets/default_dp-NQ3TGrtT.png +0 -0
- package/dist/assets/default_dp.png +0 -0
- package/dist/assets/default_dp_32.png +0 -0
- package/dist/assets/dialog-component-Da1ZIYh9.js.map +0 -1
- package/dist/assets/dialog-likers-BqDn2P_3.js.map +0 -1
- package/dist/assets/light-nostrich-running.gif +0 -0
- package/dist/assets/nostr-service-CnaPxjc6.js +0 -78
- package/dist/assets/nostr-service-CnaPxjc6.js.map +0 -1
- package/dist/assets/nostr-user-component-Cbs97dlK.js +0 -2
- package/dist/assets/nostr-user-component-Cbs97dlK.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
- package/dist/index.d.ts +0 -6
- package/dist/nostr-comment.d.ts +0 -4
- package/dist/nostr-dm.d.ts +0 -4
- package/dist/nostr-follow-button.d.ts +0 -4
- package/dist/nostr-like.d.ts +0 -4
- package/dist/nostr-live-chat.d.ts +0 -4
- package/dist/nostr-post.d.ts +0 -4
- package/dist/nostr-profile-badge.d.ts +0 -4
- package/dist/nostr-profile.d.ts +0 -4
- package/dist/nostr-zap.d.ts +0 -4
- package/dist/src/base/base-component/nostr-base-component.d.ts +0 -116
- package/dist/src/base/copy-delegation.d.ts +0 -5
- package/dist/src/base/dialog-component/dialog-component.d.ts +0 -67
- package/dist/src/base/dialog-component/style.d.ts +0 -5
- package/dist/src/base/event-component/nostr-event-component.d.ts +0 -53
- package/dist/src/base/render-options.d.ts +0 -5
- package/dist/src/base/resolvers/event-resolver.d.ts +0 -20
- package/dist/src/base/resolvers/user-resolver.d.ts +0 -19
- package/dist/src/base/text-row/render-name.d.ts +0 -7
- package/dist/src/base/text-row/render-nip05.d.ts +0 -1
- package/dist/src/base/text-row/render-npub.d.ts +0 -1
- package/dist/src/base/text-row/render-text-row.d.ts +0 -9
- package/dist/src/base/user-component/nostr-user-component.d.ts +0 -43
- package/dist/src/common/base-styles.d.ts +0 -44
- package/dist/src/common/constants.d.ts +0 -4
- package/dist/src/common/date-utils.d.ts +0 -9
- package/dist/src/common/icons.d.ts +0 -7
- package/dist/src/common/nip05-utils.d.ts +0 -13
- package/dist/src/common/nostr-service.d.ts +0 -40
- package/dist/src/common/theme.d.ts +0 -4
- package/dist/src/common/types.d.ts +0 -1
- package/dist/src/common/utils.d.ts +0 -34
- package/dist/src/index.d.ts +0 -32
- package/dist/src/nostr-comment/nostr-comment.d.ts +0 -60
- package/dist/src/nostr-comment/render.d.ts +0 -15
- package/dist/src/nostr-comment/utils.d.ts +0 -81
- package/dist/src/nostr-dm/nostr-dm.d.ts +0 -34
- package/dist/src/nostr-dm/render.d.ts +0 -15
- package/dist/src/nostr-follow-button/nostr-follow-button.d.ts +0 -24
- package/dist/src/nostr-follow-button/render.d.ts +0 -11
- package/dist/src/nostr-follow-button/style.d.ts +0 -1
- package/dist/src/nostr-like/dialog-help-style.d.ts +0 -1
- package/dist/src/nostr-like/dialog-help.d.ts +0 -2
- package/dist/src/nostr-like/dialog-likers-style.d.ts +0 -1
- package/dist/src/nostr-like/dialog-likers.d.ts +0 -24
- package/dist/src/nostr-like/like-utils.d.ts +0 -52
- package/dist/src/nostr-like/nostr-like.d.ts +0 -49
- package/dist/src/nostr-like/render.d.ts +0 -10
- package/dist/src/nostr-like/style.d.ts +0 -1
- package/dist/src/nostr-live-chat/nostr-live-chat.d.ts +0 -65
- package/dist/src/nostr-live-chat/render.d.ts +0 -31
- package/dist/src/nostr-post/nostr-post.d.ts +0 -25
- package/dist/src/nostr-post/parse-text.d.ts +0 -8
- package/dist/src/nostr-post/render-content.d.ts +0 -5
- package/dist/src/nostr-post/render.d.ts +0 -19
- package/dist/src/nostr-post/style.d.ts +0 -1
- package/dist/src/nostr-profile/nostr-profile.d.ts +0 -24
- package/dist/src/nostr-profile/render-stats.d.ts +0 -1
- package/dist/src/nostr-profile/render.d.ts +0 -22
- package/dist/src/nostr-profile/style.d.ts +0 -1
- package/dist/src/nostr-profile-badge/nostr-profile-badge.d.ts +0 -34
- package/dist/src/nostr-profile-badge/render.d.ts +0 -11
- package/dist/src/nostr-profile-badge/style.d.ts +0 -1
- package/dist/src/nostr-zap/dialog-help-style.d.ts +0 -5
- package/dist/src/nostr-zap/dialog-help.d.ts +0 -2
- package/dist/src/nostr-zap/dialog-zap-style.d.ts +0 -6
- package/dist/src/nostr-zap/dialog-zap.d.ts +0 -31
- package/dist/src/nostr-zap/dialog-zappers-style.d.ts +0 -1
- package/dist/src/nostr-zap/dialog-zappers.d.ts +0 -25
- package/dist/src/nostr-zap/nostr-zap.d.ts +0 -45
- package/dist/src/nostr-zap/render.d.ts +0 -9
- package/dist/src/nostr-zap/style.d.ts +0 -1
- package/dist/src/nostr-zap/zap-utils.d.ts +0 -53
- package/dist/vite.config.d.ts +0 -2
- package/dist/vite.config.esm.d.ts +0 -2
- package/dist/vite.config.umd.d.ts +0 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"mappings":";6ZAcO,SAASA,EAAiB,CAC/B,UAAAC,EACA,QAAAC,EACA,aAAAC,EACA,WAAAC,EACA,QAAAC,EACA,UAAAC,EACA,SAAAC,EAAW,GACX,eAAAC,EAAiB,GACjB,MAAAC,EAAQ,OACV,EAAoC,CAElC,GAAIP,EACK,OAAAQ,EAAYP,GAAgB,EAAE,EAGjC,MAAAQ,EAAcC,EAAgBP,EAASI,CAAK,EAC5CI,EAAcR,EAChB,qBACA,SAASS,EAAWV,CAAU,CAAC,UAEnC,OAAOW,EAAgBJ,EAAaE,EAAaP,EAAWC,EAAUF,EAASJ,EAAWO,CAAc,CAC1G,CAEA,SAASE,EAAYP,EAA8B,CAC1C,OAAAa,EACL,wCACAF,EAAWX,CAAY,CACzB,CACF,CAEA,SAASa,EAAqBC,EAAqBC,EAA8B,CACxE;AAAA;AAAA;AAAA,UAGCD,CAAW;AAAA;AAAA;AAAA,UAGXC,CAAY;AAAA;AAAA;AAAA,GAItB,CAEA,SAASH,EACPJ,EACAE,EACAP,EACAC,EAAoB,GACpBF,EAAmB,GACnBJ,EAAqB,GACrBO,EAA0B,GAClB,CACR,IAAIW,EAAY,GAChB,OAAIX,EACUW,EAAA,4CACHb,EAAY,IAErBa,EAAY,0BAA0BZ,EAAW,aAAe,EAAE,KAAKD,CAAS,IADlEA,IAAc,EAAI,OAAS,OACgD,WAMpF;AAAA;AAAA,uBAHaD,EAAU,0BAA4B,mBAK1B;AAAA,UACxBM,CAAW;AAAA,UACXV,EAAY,6CAA+CY,CAAW;AAAA;AAAA,QAExEM,CAAS;AAAA;AAAA,GAGjB,CAEA,SAASP,EAAgBP,EAAkBI,EAA0B,QAAiB,CAE9E,MAAAW,EAAaX,IAAU,OAAS,UAAY,UAC5CY,EAAeZ,IAAU,OAAS,UAAY,UAEpD,OAAIJ,EAEK;AAAA,sdAC2ce,CAAU;AAAA,gPAChPA,CAAU;AAAA,YAI/O;AAAA,oeACydC,CAAY;AAAA,8PAClPA,CAAY;AAAA,WAG1Q,CCvGO,SAASC,GAA8B,CA0N5C,OAAOC,EAzNc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAyNiB,CACxC,CC7NO,SAASC,GAA8B,CACrC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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","names":["renderLikeButton","isLoading","isError","errorMessage","buttonText","isLiked","likeCount","hasLikes","isCountLoading","theme","renderError","iconContent","getThumbsUpIcon","textContent","escapeHtml","renderContainer","renderErrorContainer","leftContent","rightContent","countHtml","likedColor","outlineColor","getLikeButtonStyles","getComponentStyles","getHelpDialogStyles","injectHelpDialogStyles","style","showHelpDialog","dialogComponent","normalizeURL","url","p","fetchLikesForUrl","relays","normalizedUrl","pool","SimplePool","events","likes","likedCount","dislikedCount","event","a","b","error","createReactionEvent","content","createLikeEvent","createUnlikeEvent","hasUserLiked","userPubkey","latest","getUserPubkey","signEvent","isNip07Available","NostrLike","NostrBaseComponent","__publicField","_a","NCStatus","name","oldValue","newValue","urlAttr","textAttr","tagName","isValidUrl","_status","seq","result","signedEvent","NDKEvent","openLikersDialog","__vitePreload","e","_b","renderOptions"],"ignoreList":[4],"sources":["../../src/nostr-like/render.ts","../../src/nostr-like/style.ts","../../src/nostr-like/dialog-help-style.ts","../../src/nostr-like/dialog-help.ts","../../node_modules/nostr-tools/lib/esm/utils.js","../../src/nostr-like/like-utils.ts","../../src/nostr-like/nostr-like.ts"],"sourcesContent":["// SPDX-License-Identifier: MIT\n\nimport { escapeHtml } from '../common/utils';\nimport { IRenderOptions } from '../base/render-options';\n\nexport interface RenderLikeButtonOptions extends IRenderOptions {\n buttonText: string;\n isLiked: boolean;\n likeCount: number;\n hasLikes?: boolean;\n isCountLoading?: boolean;\n theme?: 'light' | 'dark';\n}\n\nexport function renderLikeButton({\n isLoading,\n isError,\n errorMessage,\n buttonText,\n isLiked,\n likeCount,\n hasLikes = false,\n isCountLoading = false,\n theme = 'light',\n}: RenderLikeButtonOptions): string {\n\n if (isError) {\n return renderError(errorMessage || '');\n }\n\n const iconContent = getThumbsUpIcon(isLiked, theme);\n const textContent = isLiked \n ? `<span>Liked</span>`\n : `<span>${escapeHtml(buttonText)}</span>`;\n\n return renderContainer(iconContent, textContent, likeCount, hasLikes, isLiked, isLoading, isCountLoading);\n}\n\nfunction renderError(errorMessage: string): string {\n return renderErrorContainer(\n '<div class=\"error-icon\">⚠</div>',\n escapeHtml(errorMessage)\n );\n}\n\nfunction renderErrorContainer(leftContent: string, rightContent: string): string {\n return `\n <div class=\"nostr-like-button-container\">\n <div class=\"nostr-like-button-left-container\">\n ${leftContent}\n </div>\n <div class=\"nostr-like-button-right-container\">\n ${rightContent}\n </div>\n </div>\n `;\n}\n\nfunction renderContainer(\n iconContent: string, \n textContent: string, \n likeCount: number, \n hasLikes: boolean = false,\n isLiked: boolean = false,\n isLoading: boolean = false,\n isCountLoading: boolean = false\n): string {\n let countHtml = '';\n if (isCountLoading) {\n countHtml = '<span class=\"like-count skeleton\"></span>';\n } else if (likeCount > 0) {\n const label = likeCount === 1 ? 'like' : 'likes';\n countHtml = `<span class=\"like-count${hasLikes ? ' clickable' : ''}\">${likeCount} ${label}</span>`;\n }\n \n const buttonClass = isLiked ? 'nostr-like-button liked' : 'nostr-like-button';\n const helpIconHtml = `<button class=\"help-icon\" title=\"What is a like?\">?</button>`;\n \n return `\n <div class=\"nostr-like-button-container\">\n <button class=\"${buttonClass}\">\n ${iconContent}\n ${isLoading ? '<span class=\"button-text-skeleton\"></span>' : textContent}\n </button>\n ${countHtml} ${helpIconHtml}\n </div>\n `;\n}\n\nfunction getThumbsUpIcon(isLiked: boolean, theme: 'light' | 'dark' = 'light'): string {\n // Determine colors based on theme\n const likedColor = theme === 'dark' ? '#8ab4f8' : '#1877f2'; // Light blue for dark theme, blue for light theme\n const outlineColor = theme === 'dark' ? '#e0e7ff' : '#0d46a1'; // Light color for dark theme, dark blue for light theme\n\n if (isLiked) {\n // Filled thumbs up\n return `<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" viewBox=\"0 0 100 100\" width=\"24\" height=\"24\">\n <path d=\"M93.6,53.1c2.6-1.5,4.2-4.4,3.8-7.6c-0.5-4-4.2-6.8-8.2-6.8l-25,0c0.2-0.5,0.5-1.2,0.7-1.8c1.5-3.8,4.3-10.8,4.3-18 c0-8.1-5.7-13-9.6-13.3C57.2,5.5,55.4,7,55,9.7c-0.7,5.1-4.1,12.6-5.5,15.5c-0.4,0.9-0.9,1.7-1.6,2.4c-2.3,2.6-8.1,9-13.6,12.8 c0,0.2,0.1,0.5,0.1,0.7v47.9c0,0.4-0.1,0.8-0.1,1.2c9.4,2.7,17.9,4,27.2,4l21.3,0c3.7,0,7.2-2.5,7.9-6.1c0.6-3-0.5-5.7-2.5-7.5 c3.4-0.8,6-3.9,6-7.5c0-2.3-1-4.4-2.7-5.8c3.4-0.8,6-3.9,6-7.5C97.5,57,96,54.5,93.6,53.1z\" fill=\"${likedColor}\"/>\n <path d=\"M23.4,36.9H6.7c-2.3,0-4.2,1.9-4.2,4.2v47.9c0,2.3,1.9,4.2,4.2,4.2h16.7c2.3,0,4.2-1.9,4.2-4.2V41.2 C27.6,38.8,25.8,36.9,23.4,36.9z M15.1,85.9c-2.4,0-4.4-2-4.4-4.4s2-4.4,4.4-4.4c2.4,0,4.4,2,4.4,4.4S17.5,85.9,15.1,85.9z\" fill=\"${likedColor}\"/>\n </svg>`;\n } else {\n // Outline thumbs up\n return `<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" viewBox=\"0 0 100 100\" width=\"24\" height=\"24\">\n <path d=\"M93.6,53.1c2.6-1.5,4.2-4.4,3.8-7.6c-0.5-4-4.2-6.8-8.2-6.8l-25,0c0.2-0.5,0.5-1.2,0.7-1.8c1.5-3.8,4.3-10.8,4.3-18 c0-8.1-5.7-13-9.6-13.3C57.2,5.5,55.4,7,55,9.7c-0.7,5.1-4.1,12.6-5.5,15.5c-0.4,0.9-0.9,1.7-1.6,2.4c-2.3,2.6-8.1,9-13.6,12.8 c0,0.2,0.1,0.5,0.1,0.7v47.9c0,0.4-0.1,0.8-0.1,1.2c9.4,2.7,17.9,4,27.2,4l21.3,0c3.7,0,7.2-2.5,7.9-6.1c0.6-3-0.5-5.7-2.5-7.5 c3.4-0.8,6-3.9,6-7.5c0-2.3-1-4.4-2.7-5.8c3.4-0.8,6-3.9,6-7.5C97.5,57,96,54.5,93.6,53.1z\" fill=\"none\" stroke=\"${outlineColor}\" stroke-width=\"2\"/>\n <path d=\"M23.4,36.9H6.7c-2.3,0-4.2,1.9-4.2,4.2v47.9c0,2.3,1.9,4.2,4.2,4.2h16.7c2.3,0,4.2-1.9,4.2-4.2V41.2 C27.6,38.8,25.8,36.9,23.4,36.9z M15.1,85.9c-2.4,0-4.4-2-4.4-4.4s2-4.4,4.4-4.4c2.4,0,4.4,2,4.4,4.4S17.5,85.9,15.1,85.9z\" fill=\"none\" stroke=\"${outlineColor}\" stroke-width=\"2\"/>\n </svg>`;\n }\n}\n","// SPDX-License-Identifier: MIT\n\nimport { getComponentStyles } from '../common/base-styles';\n\nexport function getLikeButtonStyles(): string {\n const customStyles = `\n /* === LIKE BUTTON CONTAINER PATTERN === */\n :host {\n /* Icon sizing (overridable via CSS variables) */\n --nostrc-icon-height: 25px;\n --nostrc-icon-width: 25px;\n\n /* Like button CSS variables (overridable by parent components) */\n --nostrc-like-btn-padding: var(--nostrc-spacing-sm) var(--nostrc-spacing-md);\n --nostrc-like-btn-border-radius: var(--nostrc-border-radius-md);\n --nostrc-like-btn-border: var(--nostrc-border-width) solid var(--nostrc-color-border);\n --nostrc-like-btn-min-height: 47px;\n --nostrc-like-btn-width: auto;\n --nostrc-like-btn-horizontal-alignment: left;\n --nostrc-like-btn-bg: var(--nostrc-theme-bg, #ffffff);\n --nostrc-like-btn-color: var(--nostrc-theme-text-primary, #333333);\n --nostrc-like-btn-font-family: var(--nostrc-font-family-primary);\n --nostrc-like-btn-font-size: var(--nostrc-font-size-base);\n \n /* Hover state variables */\n --nostrc-like-btn-hover-bg: var(--nostrc-theme-hover-bg, rgba(0, 0, 0, 0.05));\n --nostrc-like-btn-hover-color: var(--nostrc-theme-text-primary, #333333);\n --nostrc-like-btn-hover-border: var(--nostrc-border-width) solid var(--nostrc-theme-border, var(--nostrc-color-border));\n\n /* Liked state variables */\n --nostrc-like-btn-liked-bg: #e7f3ff;\n --nostrc-like-btn-liked-color: #1877f2;\n --nostrc-like-btn-liked-border: #1877f2;\n --nostrc-like-btn-liked-hover-bg: #d1e7ff;\n\n /* Make the host a flex container for button + count */\n display: inline-flex;\n flex-direction: row;\n align-items: center;\n gap: var(--nostrc-spacing-md);\n font-family: var(--nostrc-like-btn-font-family);\n font-size: var(--nostrc-like-btn-font-size);\n }\n\n /* Focus state for accessibility */\n :host(:focus-visible) {\n outline: 2px solid var(--nostrc-color-primary, #007bff);\n outline-offset: 2px;\n }\n\n :host(.is-error) .nostr-like-button-container {\n border: var(--nostrc-border-width) solid var(--nostrc-color-error-text);\n border-radius: var(--nostrc-border-radius-md);\n padding: var(--nostrc-spacing-sm);\n color: var(--nostrc-color-error-text);\n }\n\n .nostr-like-button-container {\n display: flex;\n align-items: center;\n gap: var(--nostrc-spacing-md);\n width: fit-content;\n }\n\n .nostr-like-button-left-container {\n display: flex;\n align-items: center;\n }\n\n .nostr-like-button-right-container {\n display: flex;\n align-items: center;\n }\n\n .nostr-like-button {\n display: flex;\n align-items: center;\n justify-content: var(--nostrc-like-btn-horizontal-alignment);\n gap: var(--nostrc-spacing-sm);\n background: var(--nostrc-like-btn-bg);\n color: var(--nostrc-like-btn-color);\n border: var(--nostrc-like-btn-border);\n border-radius: var(--nostrc-like-btn-border-radius);\n padding: var(--nostrc-like-btn-padding);\n min-height: var(--nostrc-like-btn-min-height);\n width: var(--nostrc-like-btn-width);\n cursor: pointer;\n transition: background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease;\n font-family: inherit;\n font-size: inherit;\n }\n\n /* Hover state on the button */\n .nostr-like-button:hover {\n background: var(--nostrc-like-btn-hover-bg);\n color: var(--nostrc-like-btn-hover-color);\n border: var(--nostrc-like-btn-hover-border);\n }\n\n /* Liked state */\n .nostr-like-button.liked {\n background: var(--nostrc-like-btn-liked-bg);\n color: var(--nostrc-like-btn-liked-color);\n border: var(--nostrc-border-width) solid var(--nostrc-like-btn-liked-border);\n }\n\n .nostr-like-button.liked:hover {\n background: var(--nostrc-like-btn-liked-hover-bg);\n }\n\n .nostr-like-button:disabled {\n pointer-events: none;\n user-select: none;\n opacity: 0.6;\n }\n\n :host:not([status=\"ready\"]) .nostr-like-button {\n cursor: not-allowed;\n }\n\n /* SVG Icon Styles */\n .nostr-like-button svg {\n display: inline-block;\n vertical-align: middle;\n width: var(--nostrc-icon-width);\n height: var(--nostrc-icon-height);\n }\n\n /* Like count display */\n .like-count {\n font-size: var(--nostrc-font-size-sm);\n color: var(--nostrc-theme-text-secondary, #666666);\n white-space: nowrap;\n text-decoration: underline;\n text-decoration-color: transparent;\n transition: text-decoration-color 0.2s ease, color 0.2s ease;\n }\n\n /* Clickable like count */\n .like-count.clickable {\n cursor: pointer;\n text-decoration-color: currentColor;\n }\n\n .like-count.clickable:hover {\n color: var(--nostrc-color-primary, #7f00ff);\n text-decoration-color: var(--nostrc-color-primary, #7f00ff);\n }\n\n /* Help icon */\n .help-icon {\n background: none;\n border: 1px solid var(--nostrc-color-border, #e0e0e0);\n border-radius: var(--nostrc-border-radius-full, 50%);\n width: var(--nostrc-help-icon-size, 16px);\n height: var(--nostrc-help-icon-size, 16px);\n font-size: calc(var(--nostrc-help-icon-size, 16px) * 0.7);\n font-weight: bold;\n color: var(--nostrc-theme-text-secondary, #666666);\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n margin-left: var(--nostrc-spacing-xs, 4px);\n transition: all 0.2s ease;\n }\n\n .help-icon:hover {\n background: var(--nostrc-color-hover-background, rgba(0, 0, 0, 0.05));\n border-color: var(--nostrc-color-primary, #7f00ff);\n color: var(--nostrc-color-primary, #7f00ff);\n }\n\n /* Skeleton loader for like count */\n .like-count.skeleton {\n background: linear-gradient(90deg, \n var(--nostrc-skeleton-color-min) 25%, \n var(--nostrc-skeleton-color-max) 50%, \n var(--nostrc-skeleton-color-min) 75%\n );\n background-size: 200% 100%;\n animation: skeleton-loading var(--nostrc-skeleton-duration) var(--nostrc-skeleton-timing-function) var(--nostrc-skeleton-iteration-count);\n border-radius: var(--nostrc-border-radius-sm);\n width: 80px;\n height: 1.2em;\n display: inline-block;\n }\n\n /* Skeleton loader for button text */\n .button-text-skeleton {\n background: linear-gradient(90deg, \n var(--nostrc-skeleton-color-min) 25%, \n var(--nostrc-skeleton-color-max) 50%, \n var(--nostrc-skeleton-color-min) 75%\n );\n background-size: 200% 100%;\n animation: skeleton-loading var(--nostrc-skeleton-duration) var(--nostrc-skeleton-timing-function) var(--nostrc-skeleton-iteration-count);\n border-radius: var(--nostrc-border-radius-sm);\n width: 60px;\n height: 1em;\n display: inline-block;\n }\n\n @keyframes skeleton-loading {\n 0% {\n background-position: 200% 0;\n }\n 100% {\n background-position: -200% 0;\n }\n }\n\n /* Error message styling */\n .nostr-like-button-error small {\n color: var(--nostrc-color-error-text);\n font-size: var(--nostrc-font-size-sm);\n line-height: 1em;\n max-width: 250px;\n white-space: pre-line;\n }\n `;\n \n return getComponentStyles(customStyles);\n}\n","// SPDX-License-Identifier: MIT\n\nexport function getHelpDialogStyles(): string {\n return `\n .help-content {\n padding: var(--nostrc-spacing-md, 12px);\n }\n\n .help-content p {\n margin: 0 0 var(--nostrc-spacing-md, 12px) 0;\n color: var(--nostrc-theme-text-primary, #333333);\n line-height: 1.5;\n }\n\n .help-content p:last-child {\n margin-bottom: 0;\n }\n\n .help-content ul {\n margin: 0 0 var(--nostrc-spacing-md, 12px) 0;\n padding-left: var(--nostrc-spacing-lg, 16px);\n color: var(--nostrc-theme-text-primary, #333333);\n }\n\n .help-content li {\n margin-bottom: var(--nostrc-spacing-xs, 4px);\n line-height: 1.5;\n }\n\n .help-content li:last-child {\n margin-bottom: 0;\n }\n\n .help-content strong {\n font-weight: 600;\n color: var(--nostrc-theme-text-primary, #333333);\n }\n\n .help-content a {\n color: var(--nostrc-theme-primary, #0066cc);\n text-decoration: underline;\n }\n\n .help-content a:hover {\n color: var(--nostrc-theme-primary-hover, #0052a3);\n }\n `;\n}\n\n","// SPDX-License-Identifier: MIT\n\n// Import for side effects to register the custom element\nimport '../base/dialog-component/dialog-component';\nimport type { DialogComponent } from '../base/dialog-component/dialog-component';\nimport { getHelpDialogStyles } from './dialog-help-style';\n\nexport const injectHelpDialogStyles = (): void => {\n // Check if styles are already injected\n if (document.querySelector('style[data-help-dialog-styles]')) return;\n \n const style = document.createElement('style');\n style.setAttribute('data-help-dialog-styles', 'true');\n style.textContent = getHelpDialogStyles();\n document.head.appendChild(style);\n};\n\nexport const showHelpDialog = async (theme?: 'light' | 'dark'): Promise<void> => {\n injectHelpDialogStyles();\n \n if (!customElements.get('dialog-component')) {\n await customElements.whenDefined('dialog-component');\n }\n \n const dialogComponent = document.createElement('dialog-component') as DialogComponent;\n dialogComponent.setAttribute('header', 'What is a Like?');\n if (theme) {\n dialogComponent.setAttribute('data-theme', theme);\n }\n \n // Set dialog content\n dialogComponent.innerHTML = `\n <div class=\"help-content\">\n <p>Like any webpage to show your appreciation! Your likes are stored on Nostr, a decentralized network you control—no accounts needed.</p>\n <ul>\n <li>Like any webpage or article</li>\n <li>See who liked the content</li>\n <li>Works with a browser extension like <a href=\"https://getalby.com\" target=\"_blank\" rel=\"noopener noreferrer\">Alby</a> or nos2x</li>\n </ul>\n </div>\n `;\n \n dialogComponent.showModal();\n};\n\n","// utils.ts\nvar utf8Decoder = new TextDecoder(\"utf-8\");\nvar utf8Encoder = new TextEncoder();\nfunction normalizeURL(url) {\n if (url.indexOf(\"://\") === -1)\n url = \"wss://\" + url;\n let p = new URL(url);\n p.pathname = p.pathname.replace(/\\/+/g, \"/\");\n if (p.pathname.endsWith(\"/\"))\n p.pathname = p.pathname.slice(0, -1);\n if (p.port === \"80\" && p.protocol === \"ws:\" || p.port === \"443\" && p.protocol === \"wss:\")\n p.port = \"\";\n p.searchParams.sort();\n p.hash = \"\";\n return p.toString();\n}\nfunction insertEventIntoDescendingList(sortedArray, event) {\n const [idx, found] = binarySearch(sortedArray, (b) => {\n if (event.id === b.id)\n return 0;\n if (event.created_at === b.created_at)\n return -1;\n return b.created_at - event.created_at;\n });\n if (!found) {\n sortedArray.splice(idx, 0, event);\n }\n return sortedArray;\n}\nfunction insertEventIntoAscendingList(sortedArray, event) {\n const [idx, found] = binarySearch(sortedArray, (b) => {\n if (event.id === b.id)\n return 0;\n if (event.created_at === b.created_at)\n return -1;\n return event.created_at - b.created_at;\n });\n if (!found) {\n sortedArray.splice(idx, 0, event);\n }\n return sortedArray;\n}\nfunction binarySearch(arr, compare) {\n let start = 0;\n let end = arr.length - 1;\n while (start <= end) {\n const mid = Math.floor((start + end) / 2);\n const cmp = compare(arr[mid]);\n if (cmp === 0) {\n return [mid, true];\n }\n if (cmp < 0) {\n end = mid - 1;\n } else {\n start = mid + 1;\n }\n }\n return [start, false];\n}\nvar QueueNode = class {\n value;\n next = null;\n prev = null;\n constructor(message) {\n this.value = message;\n }\n};\nvar Queue = class {\n first;\n last;\n constructor() {\n this.first = null;\n this.last = null;\n }\n enqueue(value) {\n const newNode = new QueueNode(value);\n if (!this.last) {\n this.first = newNode;\n this.last = newNode;\n } else if (this.last === this.first) {\n this.last = newNode;\n this.last.prev = this.first;\n this.first.next = newNode;\n } else {\n newNode.prev = this.last;\n this.last.next = newNode;\n this.last = newNode;\n }\n return true;\n }\n dequeue() {\n if (!this.first)\n return null;\n if (this.first === this.last) {\n const target2 = this.first;\n this.first = null;\n this.last = null;\n return target2.value;\n }\n const target = this.first;\n this.first = target.next;\n return target.value;\n }\n};\nexport {\n Queue,\n QueueNode,\n binarySearch,\n insertEventIntoAscendingList,\n insertEventIntoDescendingList,\n normalizeURL,\n utf8Decoder,\n utf8Encoder\n};\n","// SPDX-License-Identifier: MIT\n\nimport { SimplePool } from 'nostr-tools';\nimport { normalizeURL } from 'nostr-tools/utils';\n\n/**\n * Helper utilities for Nostr like operations using NIP-25 External Content Reactions.\n * These are deliberately kept self-contained so `nostr-like` Web Component can import\n * everything from a single module without polluting the rest of the codebase.\n */\n\nexport interface LikeDetails {\n authorPubkey: string;\n date: Date;\n content: string;\n}\n\nexport interface LikeCountResult {\n totalCount: number;\n likeDetails: LikeDetails[];\n likedCount: number;\n dislikedCount: number;\n}\n\n/**\n * Fetch all likes for a URL using NIP-25 kind 17 events\n */\nexport async function fetchLikesForUrl(\n url: string, \n relays: string[]\n): Promise<LikeCountResult> {\n // Normalize URL at the beginning for consistent comparison with tags\n const normalizedUrl = normalizeURL(url);\n \n const pool = new SimplePool();\n \n try {\n // Query kind 17 events (both likes and unlikes)\n const events = await pool.querySync(relays, {\n kinds: [17],\n '#k': ['web'],\n '#i': [normalizedUrl],\n limit: 1000\n });\n \n const likes: LikeDetails[] = [];\n let likedCount = 0;\n let dislikedCount = 0;\n \n for (const event of events) {\n likes.push({\n authorPubkey: event.pubkey,\n date: new Date(event.created_at * 1000),\n content: event.content\n });\n \n if (event.content === '-') {\n dislikedCount++;\n } else {\n likedCount++;\n }\n }\n \n likes.sort((a, b) => b.date.getTime() - a.date.getTime());\n \n const totalCount = likedCount - dislikedCount;\n \n return {\n totalCount: totalCount,\n likeDetails: likes,\n likedCount: likedCount,\n dislikedCount: dislikedCount\n };\n } catch (error) {\n // Rethrow error so callers can handle relay/network failures appropriately\n throw error instanceof Error ? error : new Error(String(error));\n } finally {\n pool.close(relays);\n }\n}\n\n/**\n * Create reaction event (kind 17)\n * @param url - URL to react to\n * @param content - '+' for like, '-' for unlike\n */\nexport function createReactionEvent(url: string, content: '+' | '-'): any {\n return {\n kind: 17,\n content,\n tags: [\n ['k', 'web'],\n ['i', url]\n ],\n created_at: Math.floor(Date.now() / 1000)\n };\n}\n\n/**\n * Create like event (kind 17)\n * @deprecated Use createReactionEvent(url, '+') instead\n */\nexport function createLikeEvent(url: string): any {\n return createReactionEvent(url, '+');\n}\n\n/**\n * Create unlike event (kind 17 with '-' content)\n * @deprecated Use createReactionEvent(url, '-') instead\n */\nexport function createUnlikeEvent(url: string): any {\n return createReactionEvent(url, '-');\n}\n\n/**\n * Check if user has liked a URL\n */\nexport async function hasUserLiked(\n url: string,\n userPubkey: string,\n relays: string[]\n): Promise<boolean> {\n const pool = new SimplePool();\n const normalizedUrl = url;\n \n try {\n // Get user's latest reaction for this URL\n const events = await pool.querySync(relays, {\n kinds: [17],\n authors: [userPubkey],\n '#k': ['web'],\n '#i': [normalizedUrl],\n limit: 1\n });\n \n if (events.length === 0) return false;\n \n // Check if latest reaction is a like (not an unlike)\n const latest = events[0];\n return latest.content === '+' || latest.content === '';\n } catch (error) {\n console.error(\"Nostr-Components: Like button: Error checking user like status\", error);\n return false;\n } finally {\n pool.close(relays);\n }\n}\n\n/**\n * Get user's pubkey from NIP-07 signer\n */\nexport async function getUserPubkey(): Promise<string | null> {\n try {\n if (typeof window !== 'undefined' && (window as any).nostr) {\n const nip07signer = (window as any).nostr;\n const user = await nip07signer.getPublicKey();\n return user;\n }\n } catch (error) {\n console.error(\"Nostr-Components: Like button: Error getting user pubkey\", error);\n }\n return null;\n}\n\n/**\n * Sign event with NIP-07\n */\nexport async function signEvent(event: any): Promise<any> {\n try {\n if (typeof window !== 'undefined' && (window as any).nostr) {\n const nip07signer = (window as any).nostr;\n const signedEvent = await nip07signer.signEvent(event);\n return signedEvent;\n }\n throw new Error('NIP-07 extension not available');\n } catch (error) {\n console.error(\"Nostr-Components: Like button: Error signing event\", error);\n throw error;\n }\n}\n\n/**\n * Check if NIP-07 extension is available\n */\nexport function isNip07Available(): boolean {\n return typeof window !== 'undefined' && !!(window as any).nostr;\n}\n","// SPDX-License-Identifier: MIT\n\nimport { NostrBaseComponent } from '../base/base-component/nostr-base-component';\nimport { NCStatus } from '../base/base-component/nostr-base-component';\nimport { NDKEvent } from '@nostr-dev-kit/ndk';\nimport { renderLikeButton, RenderLikeButtonOptions } from './render';\nimport { getLikeButtonStyles } from './style';\nimport { showHelpDialog } from './dialog-help';\nimport { isValidUrl } from '../common/utils';\nimport { \n fetchLikesForUrl, \n createLikeEvent,\n createUnlikeEvent,\n hasUserLiked, \n getUserPubkey, \n signEvent, \n isNip07Available,\n LikeCountResult \n} from './like-utils';\nimport { normalizeURL } from 'nostr-tools/utils';\n\n/**\n * <nostr-like>\n * Attributes:\n * - url (optional) : URL to like (default: current page URL)\n * - text (optional) : custom text (default \"Like\") (Max 32 characters)\n * - relays (optional) : comma-separated relay URLs\n * - data-theme (optional) : \"light\" | \"dark\" (default light)\n * \n * Features:\n * - URL-based likes using NIP-25 kind 17 events\n * - Click count to view likers\n */\nexport default class NostrLike extends NostrBaseComponent {\n protected likeActionStatus = this.channel('likeAction');\n protected likeListStatus = this.channel('likeList');\n \n private currentUrl: string = '';\n private isLiked: boolean = false;\n private likeCount: number = 0;\n private cachedLikeDetails: LikeCountResult | null = null;\n private loadSeq = 0;\n\n constructor() {\n super();\n }\n\n connectedCallback() {\n super.connectedCallback?.();\n if (this.likeListStatus.get() === NCStatus.Idle) {\n this.initChannelStatus('likeList', NCStatus.Loading, { reflectOverall: false });\n }\n this.attachDelegatedListeners();\n this.render();\n }\n\n static get observedAttributes() {\n return [\n ...super.observedAttributes,\n 'url',\n 'text'\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 === 'url' || name === 'text') {\n this.likeActionStatus.set(NCStatus.Ready);\n this.likeListStatus.set(NCStatus.Loading);\n this.isLiked = false;\n this.errorMessage = '';\n this.updateLikeCount();\n this.render();\n }\n }\n\n /** Base class functions */\n protected validateInputs(): boolean {\n if (!super.validateInputs()) {\n this.likeActionStatus.set(NCStatus.Idle);\n this.likeListStatus.set(NCStatus.Idle);\n return false;\n }\n\n const urlAttr = this.getAttribute('url');\n const textAttr = this.getAttribute('text');\n const tagName = this.tagName.toLowerCase();\n\n let errorMessage: string | null = null;\n\n if (urlAttr) {\n if (!isValidUrl(urlAttr)) {\n errorMessage = 'Invalid URL format';\n }\n }\n\n if (textAttr && textAttr.length > 32) {\n errorMessage = 'Max text length: 32 characters';\n }\n\n if (errorMessage) {\n this.likeActionStatus.set(NCStatus.Error, errorMessage);\n this.likeListStatus.set(NCStatus.Error, errorMessage);\n console.error(`Nostr-Components: ${tagName}: ${errorMessage}`);\n return false;\n }\n\n return true;\n }\n\n protected onStatusChange(_status: NCStatus) {\n this.render();\n }\n\n protected onNostrRelaysConnected() {\n this.updateLikeCount();\n this.render();\n }\n\n /** Private functions */\n /**\n * Lazy initializer for currentUrl - ensures it's set before like/unlike operations\n */\n private ensureCurrentUrl(): void {\n if (!this.currentUrl) {\n this.currentUrl = normalizeURL(this.getAttribute('url') || window.location.href);\n }\n }\n\n private async updateLikeCount() {\n const seq = ++this.loadSeq;\n try {\n await this.ensureNostrConnected();\n this.currentUrl = normalizeURL(this.getAttribute('url') || window.location.href);\n this.likeListStatus.set(NCStatus.Loading);\n this.render();\n \n const result = await fetchLikesForUrl(this.currentUrl, this.getRelays());\n if (seq !== this.loadSeq) return; // stale\n this.likeCount = result.totalCount;\n this.cachedLikeDetails = result;\n this.likeListStatus.set(NCStatus.Ready);\n } catch (error) {\n console.error('[NostrLike] Failed to fetch like count:', error);\n this.likeListStatus.set(NCStatus.Error, 'Failed to load likes');\n } finally {\n this.render();\n }\n }\n\n // TODO: Do onboarding logic here\n private async handleLikeClick() {\n // Ensure currentUrl is set before proceeding\n this.ensureCurrentUrl();\n \n if (!this.currentUrl) {\n this.likeActionStatus.set(NCStatus.Error, 'Invalid URL');\n this.render();\n return;\n }\n\n this.likeActionStatus.set(NCStatus.Loading);\n if (!isNip07Available()) {\n this.likeActionStatus.set(NCStatus.Error, \n 'Please install a Nostr browser extension (Alby, nos2x, etc.)'\n );\n this.render();\n return;\n }\n\n // Check user like status\n try {\n const userPubkey = await getUserPubkey();\n if (userPubkey) {\n this.isLiked = await hasUserLiked(this.currentUrl, userPubkey, this.getRelays());\n }\n } catch (error) {\n console.error('[NostrLike] Failed to check user like status:', error);\n this.likeActionStatus.set(NCStatus.Error, 'Failed to check user like status');\n } finally {\n this.render();\n }\n\n // If already liked, show confirmation dialog\n if (this.isLiked) {\n const confirmed = window.confirm('You have already liked this. Do you want to unlike it?');\n if (!confirmed) {\n this.likeActionStatus.set(NCStatus.Ready);\n this.render();\n return;\n }\n \n // Proceed with unlike\n await this.handleUnlike();\n } else {\n // Proceed with like\n await this.handleLike();\n }\n }\n\n private async handleLike() {\n // Ensure currentUrl is set before proceeding\n this.ensureCurrentUrl();\n \n if (!this.currentUrl) {\n this.likeActionStatus.set(NCStatus.Error, 'Invalid URL');\n this.render();\n return;\n }\n\n this.likeActionStatus.set(NCStatus.Loading);\n this.render();\n\n try {\n // Create like event\n const event = createLikeEvent(this.currentUrl);\n \n // Sign with NIP-07\n const signedEvent = await signEvent(event);\n \n // Create NDKEvent and publish\n const ndkEvent = new NDKEvent(this.nostrService.getNDK(), signedEvent);\n await ndkEvent.publish();\n \n // Update state optimistically\n this.isLiked = true;\n this.likeCount++;\n this.likeActionStatus.set(NCStatus.Ready);\n \n // Refresh like count to get accurate data\n await this.updateLikeCount();\n } catch (error) {\n console.error('[NostrLike] Failed to like:', error);\n \n // Rollback optimistic update\n this.isLiked = false;\n this.likeCount--;\n \n const errorMessage = error instanceof Error ? error.message : 'Failed to like';\n this.likeActionStatus.set(NCStatus.Error, errorMessage);\n } finally {\n this.render();\n }\n }\n\n private async handleUnlike() {\n // Ensure currentUrl is set before proceeding\n this.ensureCurrentUrl();\n \n if (!this.currentUrl) {\n this.likeActionStatus.set(NCStatus.Error, 'Invalid URL');\n this.render();\n return;\n }\n\n this.likeActionStatus.set(NCStatus.Loading);\n this.render();\n \n try {\n // Create unlike event\n const event = createUnlikeEvent(this.currentUrl);\n \n // Sign with NIP-07\n const signedEvent = await signEvent(event);\n \n // Create NDKEvent and publish\n const ndkEvent = new NDKEvent(this.nostrService.getNDK(), signedEvent);\n await ndkEvent.publish();\n \n // Update state optimistically\n this.isLiked = false;\n if (this.likeCount > 0) {\n this.likeCount--;\n }\n this.likeActionStatus.set(NCStatus.Ready);\n \n // Refresh like count to get accurate data\n await this.updateLikeCount();\n } catch (error) {\n console.error('[NostrLike] Failed to unlike:', error);\n \n // Rollback optimistic update\n this.isLiked = true;\n this.likeCount++;\n \n const errorMessage = error instanceof Error ? error.message : 'Failed to unlike';\n this.likeActionStatus.set(NCStatus.Error, errorMessage);\n } finally {\n this.render();\n }\n }\n\n private async handleCountClick() {\n if (this.likeCount === 0 || !this.cachedLikeDetails) {\n return;\n }\n\n try {\n // Import dialog dynamically to avoid circular dependencies\n const { openLikersDialog } = await import('./dialog-likers');\n await openLikersDialog({\n likeDetails: this.cachedLikeDetails.likeDetails,\n theme: this.theme === 'dark' ? 'dark' : 'light',\n });\n } catch (error) {\n console.error('[NostrLike] Error opening likers dialog:', error);\n }\n }\n\n private async handleHelpClick() {\n try {\n await showHelpDialog(this.theme === 'dark' ? 'dark' : 'light');\n } catch (error) {\n console.error('[NostrLike] Error showing help dialog:', error);\n }\n }\n\n private attachDelegatedListeners() {\n this.delegateEvent('click', '.nostr-like-button', (e) => {\n e.preventDefault?.();\n e.stopPropagation?.();\n void this.handleLikeClick();\n });\n\n this.delegateEvent('click', '.like-count', (e) => {\n e.preventDefault?.();\n e.stopPropagation?.();\n void this.handleCountClick();\n });\n\n this.delegateEvent('click', '.help-icon', (e) => {\n e.preventDefault?.();\n e.stopPropagation?.();\n this.handleHelpClick();\n });\n }\n\n protected renderContent() {\n // console.log(`Like: Render: conn: ${this.conn.get()}, likeActionStatus: ${this.likeActionStatus.get()}, likeListStatus: ${this.likeListStatus.get()}`);\n const isLoading = this.likeActionStatus.get() === NCStatus.Loading || this.conn.get() === NCStatus.Loading;\n const isCountLoading = this.likeListStatus.get() === NCStatus.Loading;\n const isError = this.computeOverall() === NCStatus.Error;\n const errorMessage = this.errorMessage;\n const buttonText = this.getAttribute('text') || 'Like';\n\n const renderOptions: RenderLikeButtonOptions = {\n isLoading,\n isError,\n errorMessage,\n buttonText,\n isLiked: this.isLiked,\n likeCount: this.likeCount,\n hasLikes: this.likeCount > 0,\n isCountLoading,\n theme: this.theme as 'light' | 'dark',\n };\n\n this.shadowRoot!.innerHTML = `\n ${getLikeButtonStyles()}\n ${renderLikeButton(renderOptions)}\n `;\n }\n}\n\ncustomElements.define('nostr-like', NostrLike);\n"],"file":"components/nostr-like.es.js"}
|
|
1
|
+
{"version":3,"mappings":";yeAcO,SAASA,EAAiB,CAC/B,UAAAC,EACA,QAAAC,EACA,aAAAC,EACA,WAAAC,EACA,QAAAC,EACA,UAAAC,EACA,SAAAC,EAAW,GACX,eAAAC,EAAiB,GACjB,MAAAC,EAAQ,OACV,EAAoC,CAElC,GAAIP,EACF,OAAOQ,EAAYP,GAAgB,EAAE,EAGvC,MAAMQ,EAAcC,EAAgBP,EAASI,CAAK,EAC5CI,EAAcR,EAChB,qBACA,SAASS,EAAWV,CAAU,CAAC,UAEnC,OAAOW,EAAgBJ,EAAaE,EAAaP,EAAWC,EAAUF,EAASJ,EAAWO,CAAc,CAC1G,CAEA,SAASE,EAAYP,EAA8B,CACjD,OAAOa,EACL,wCACAF,EAAWX,CAAY,EAE3B,CAEA,SAASa,EAAqBC,EAAqBC,EAA8B,CAC/E,MAAO;AAAA;AAAA;AAAA,UAGCD,CAAW;AAAA;AAAA;AAAA,UAGXC,CAAY;AAAA;AAAA;AAAA,GAItB,CAEA,SAASH,EACPJ,EACAE,EACAP,EACAC,EAAoB,GACpBF,EAAmB,GACnBJ,EAAqB,GACrBO,EAA0B,GAClB,CACR,IAAIW,EAAY,GAChB,OAAIX,EACFW,EAAY,4CACHb,EAAY,IAErBa,EAAY,0BAA0BZ,EAAW,aAAe,EAAE,KAAKD,CAAS,IADlEA,IAAc,EAAI,OAAS,OACgD,WAMpF;AAAA;AAAA,uBAHaD,EAAU,0BAA4B,mBAK1B;AAAA,UACxBM,CAAW;AAAA,UACXV,EAAY,6CAA+CY,CAAW;AAAA;AAAA,QAExEM,CAAS;AAAA;AAAA,GAGjB,CAEA,SAASP,EAAgBP,EAAkBI,EAA0B,QAAiB,CAEpF,MAAMW,EAAaX,IAAU,OAAS,UAAY,UAC5CY,EAAeZ,IAAU,OAAS,UAAY,UAEpD,OAAIJ,EAEK;AAAA,sdAC2ce,CAAU;AAAA,gPAChPA,CAAU;AAAA,YAI/O;AAAA,oeACydC,CAAY;AAAA,8PAClPA,CAAY;AAAA,WAG1Q,CCvGO,SAASC,GAA8B,CA0N5C,OAAOC,EAzNc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAyNiB,CACxC,CC7NO,SAASC,GAA8B,CAC5C,MAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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","names":["renderLikeButton","isLoading","isError","errorMessage","buttonText","isLiked","likeCount","hasLikes","isCountLoading","theme","renderError","iconContent","getThumbsUpIcon","textContent","escapeHtml","renderContainer","renderErrorContainer","leftContent","rightContent","countHtml","likedColor","outlineColor","getLikeButtonStyles","getComponentStyles","getHelpDialogStyles","injectHelpDialogStyles","style","showHelpDialog","dialogComponent","normalizeURL","url","p","fetchLikesForUrl","relays","normalizedUrl","pool","SimplePool","events","likes","likedCount","dislikedCount","event","a","b","error","createReactionEvent","content","createLikeEvent","createUnlikeEvent","hasUserLiked","userPubkey","latest","getUserPubkey","ensureInitialized","getPublicKey","signEvent","signEventWithNostrLogin","NostrLike","NostrBaseComponent","__publicField","NCStatus","_a","name","oldValue","newValue","urlAttr","textAttr","tagName","isValidUrl","_status","seq","result","signedEvent","NDKEvent","openLikersDialog","__vitePreload","e","_b","renderOptions"],"ignoreList":[4],"sources":["../../src/nostr-like/render.ts","../../src/nostr-like/style.ts","../../src/nostr-like/dialog-help-style.ts","../../src/nostr-like/dialog-help.ts","../../node_modules/nostr-tools/lib/esm/utils.js","../../src/nostr-like/like-utils.ts","../../src/nostr-like/nostr-like.ts"],"sourcesContent":["// SPDX-License-Identifier: MIT\n\nimport { escapeHtml } from '../common/utils';\nimport { IRenderOptions } from '../base/render-options';\n\nexport interface RenderLikeButtonOptions extends IRenderOptions {\n buttonText: string;\n isLiked: boolean;\n likeCount: number;\n hasLikes?: boolean;\n isCountLoading?: boolean;\n theme?: 'light' | 'dark';\n}\n\nexport function renderLikeButton({\n isLoading,\n isError,\n errorMessage,\n buttonText,\n isLiked,\n likeCount,\n hasLikes = false,\n isCountLoading = false,\n theme = 'light',\n}: RenderLikeButtonOptions): string {\n\n if (isError) {\n return renderError(errorMessage || '');\n }\n\n const iconContent = getThumbsUpIcon(isLiked, theme);\n const textContent = isLiked \n ? `<span>Liked</span>`\n : `<span>${escapeHtml(buttonText)}</span>`;\n\n return renderContainer(iconContent, textContent, likeCount, hasLikes, isLiked, isLoading, isCountLoading);\n}\n\nfunction renderError(errorMessage: string): string {\n return renderErrorContainer(\n '<div class=\"error-icon\">⚠</div>',\n escapeHtml(errorMessage)\n );\n}\n\nfunction renderErrorContainer(leftContent: string, rightContent: string): string {\n return `\n <div class=\"nostr-like-button-container\">\n <div class=\"nostr-like-button-left-container\">\n ${leftContent}\n </div>\n <div class=\"nostr-like-button-right-container\">\n ${rightContent}\n </div>\n </div>\n `;\n}\n\nfunction renderContainer(\n iconContent: string, \n textContent: string, \n likeCount: number, \n hasLikes: boolean = false,\n isLiked: boolean = false,\n isLoading: boolean = false,\n isCountLoading: boolean = false\n): string {\n let countHtml = '';\n if (isCountLoading) {\n countHtml = '<span class=\"like-count skeleton\"></span>';\n } else if (likeCount > 0) {\n const label = likeCount === 1 ? 'like' : 'likes';\n countHtml = `<span class=\"like-count${hasLikes ? ' clickable' : ''}\">${likeCount} ${label}</span>`;\n }\n \n const buttonClass = isLiked ? 'nostr-like-button liked' : 'nostr-like-button';\n const helpIconHtml = `<button class=\"help-icon\" title=\"What is a like?\">?</button>`;\n \n return `\n <div class=\"nostr-like-button-container\">\n <button class=\"${buttonClass}\">\n ${iconContent}\n ${isLoading ? '<span class=\"button-text-skeleton\"></span>' : textContent}\n </button>\n ${countHtml} ${helpIconHtml}\n </div>\n `;\n}\n\nfunction getThumbsUpIcon(isLiked: boolean, theme: 'light' | 'dark' = 'light'): string {\n // Determine colors based on theme\n const likedColor = theme === 'dark' ? '#8ab4f8' : '#1877f2'; // Light blue for dark theme, blue for light theme\n const outlineColor = theme === 'dark' ? '#e0e7ff' : '#0d46a1'; // Light color for dark theme, dark blue for light theme\n\n if (isLiked) {\n // Filled thumbs up\n return `<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" viewBox=\"0 0 100 100\" width=\"24\" height=\"24\">\n <path d=\"M93.6,53.1c2.6-1.5,4.2-4.4,3.8-7.6c-0.5-4-4.2-6.8-8.2-6.8l-25,0c0.2-0.5,0.5-1.2,0.7-1.8c1.5-3.8,4.3-10.8,4.3-18 c0-8.1-5.7-13-9.6-13.3C57.2,5.5,55.4,7,55,9.7c-0.7,5.1-4.1,12.6-5.5,15.5c-0.4,0.9-0.9,1.7-1.6,2.4c-2.3,2.6-8.1,9-13.6,12.8 c0,0.2,0.1,0.5,0.1,0.7v47.9c0,0.4-0.1,0.8-0.1,1.2c9.4,2.7,17.9,4,27.2,4l21.3,0c3.7,0,7.2-2.5,7.9-6.1c0.6-3-0.5-5.7-2.5-7.5 c3.4-0.8,6-3.9,6-7.5c0-2.3-1-4.4-2.7-5.8c3.4-0.8,6-3.9,6-7.5C97.5,57,96,54.5,93.6,53.1z\" fill=\"${likedColor}\"/>\n <path d=\"M23.4,36.9H6.7c-2.3,0-4.2,1.9-4.2,4.2v47.9c0,2.3,1.9,4.2,4.2,4.2h16.7c2.3,0,4.2-1.9,4.2-4.2V41.2 C27.6,38.8,25.8,36.9,23.4,36.9z M15.1,85.9c-2.4,0-4.4-2-4.4-4.4s2-4.4,4.4-4.4c2.4,0,4.4,2,4.4,4.4S17.5,85.9,15.1,85.9z\" fill=\"${likedColor}\"/>\n </svg>`;\n } else {\n // Outline thumbs up\n return `<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" viewBox=\"0 0 100 100\" width=\"24\" height=\"24\">\n <path d=\"M93.6,53.1c2.6-1.5,4.2-4.4,3.8-7.6c-0.5-4-4.2-6.8-8.2-6.8l-25,0c0.2-0.5,0.5-1.2,0.7-1.8c1.5-3.8,4.3-10.8,4.3-18 c0-8.1-5.7-13-9.6-13.3C57.2,5.5,55.4,7,55,9.7c-0.7,5.1-4.1,12.6-5.5,15.5c-0.4,0.9-0.9,1.7-1.6,2.4c-2.3,2.6-8.1,9-13.6,12.8 c0,0.2,0.1,0.5,0.1,0.7v47.9c0,0.4-0.1,0.8-0.1,1.2c9.4,2.7,17.9,4,27.2,4l21.3,0c3.7,0,7.2-2.5,7.9-6.1c0.6-3-0.5-5.7-2.5-7.5 c3.4-0.8,6-3.9,6-7.5c0-2.3-1-4.4-2.7-5.8c3.4-0.8,6-3.9,6-7.5C97.5,57,96,54.5,93.6,53.1z\" fill=\"none\" stroke=\"${outlineColor}\" stroke-width=\"2\"/>\n <path d=\"M23.4,36.9H6.7c-2.3,0-4.2,1.9-4.2,4.2v47.9c0,2.3,1.9,4.2,4.2,4.2h16.7c2.3,0,4.2-1.9,4.2-4.2V41.2 C27.6,38.8,25.8,36.9,23.4,36.9z M15.1,85.9c-2.4,0-4.4-2-4.4-4.4s2-4.4,4.4-4.4c2.4,0,4.4,2,4.4,4.4S17.5,85.9,15.1,85.9z\" fill=\"none\" stroke=\"${outlineColor}\" stroke-width=\"2\"/>\n </svg>`;\n }\n}\n","// SPDX-License-Identifier: MIT\n\nimport { getComponentStyles } from '../common/base-styles';\n\nexport function getLikeButtonStyles(): string {\n const customStyles = `\n /* === LIKE BUTTON CONTAINER PATTERN === */\n :host {\n /* Icon sizing (overridable via CSS variables) */\n --nostrc-icon-height: 25px;\n --nostrc-icon-width: 25px;\n\n /* Like button CSS variables (overridable by parent components) */\n --nostrc-like-btn-padding: var(--nostrc-spacing-sm) var(--nostrc-spacing-md);\n --nostrc-like-btn-border-radius: var(--nostrc-border-radius-md);\n --nostrc-like-btn-border: var(--nostrc-border-width) solid var(--nostrc-color-border);\n --nostrc-like-btn-min-height: 47px;\n --nostrc-like-btn-width: auto;\n --nostrc-like-btn-horizontal-alignment: left;\n --nostrc-like-btn-bg: var(--nostrc-theme-bg, #ffffff);\n --nostrc-like-btn-color: var(--nostrc-theme-text-primary, #333333);\n --nostrc-like-btn-font-family: var(--nostrc-font-family-primary);\n --nostrc-like-btn-font-size: var(--nostrc-font-size-base);\n \n /* Hover state variables */\n --nostrc-like-btn-hover-bg: var(--nostrc-theme-hover-bg, rgba(0, 0, 0, 0.05));\n --nostrc-like-btn-hover-color: var(--nostrc-theme-text-primary, #333333);\n --nostrc-like-btn-hover-border: var(--nostrc-border-width) solid var(--nostrc-theme-border, var(--nostrc-color-border));\n\n /* Liked state variables */\n --nostrc-like-btn-liked-bg: #e7f3ff;\n --nostrc-like-btn-liked-color: #1877f2;\n --nostrc-like-btn-liked-border: #1877f2;\n --nostrc-like-btn-liked-hover-bg: #d1e7ff;\n\n /* Make the host a flex container for button + count */\n display: inline-flex;\n flex-direction: row;\n align-items: center;\n gap: var(--nostrc-spacing-md);\n font-family: var(--nostrc-like-btn-font-family);\n font-size: var(--nostrc-like-btn-font-size);\n }\n\n /* Focus state for accessibility */\n :host(:focus-visible) {\n outline: 2px solid var(--nostrc-color-primary, #007bff);\n outline-offset: 2px;\n }\n\n :host(.is-error) .nostr-like-button-container {\n border: var(--nostrc-border-width) solid var(--nostrc-color-error-text);\n border-radius: var(--nostrc-border-radius-md);\n padding: var(--nostrc-spacing-sm);\n color: var(--nostrc-color-error-text);\n }\n\n .nostr-like-button-container {\n display: flex;\n align-items: center;\n gap: var(--nostrc-spacing-md);\n width: fit-content;\n }\n\n .nostr-like-button-left-container {\n display: flex;\n align-items: center;\n }\n\n .nostr-like-button-right-container {\n display: flex;\n align-items: center;\n }\n\n .nostr-like-button {\n display: flex;\n align-items: center;\n justify-content: var(--nostrc-like-btn-horizontal-alignment);\n gap: var(--nostrc-spacing-sm);\n background: var(--nostrc-like-btn-bg);\n color: var(--nostrc-like-btn-color);\n border: var(--nostrc-like-btn-border);\n border-radius: var(--nostrc-like-btn-border-radius);\n padding: var(--nostrc-like-btn-padding);\n min-height: var(--nostrc-like-btn-min-height);\n width: var(--nostrc-like-btn-width);\n cursor: pointer;\n transition: background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease;\n font-family: inherit;\n font-size: inherit;\n }\n\n /* Hover state on the button */\n .nostr-like-button:hover {\n background: var(--nostrc-like-btn-hover-bg);\n color: var(--nostrc-like-btn-hover-color);\n border: var(--nostrc-like-btn-hover-border);\n }\n\n /* Liked state */\n .nostr-like-button.liked {\n background: var(--nostrc-like-btn-liked-bg);\n color: var(--nostrc-like-btn-liked-color);\n border: var(--nostrc-border-width) solid var(--nostrc-like-btn-liked-border);\n }\n\n .nostr-like-button.liked:hover {\n background: var(--nostrc-like-btn-liked-hover-bg);\n }\n\n .nostr-like-button:disabled {\n pointer-events: none;\n user-select: none;\n opacity: 0.6;\n }\n\n :host:not([status=\"ready\"]) .nostr-like-button {\n cursor: not-allowed;\n }\n\n /* SVG Icon Styles */\n .nostr-like-button svg {\n display: inline-block;\n vertical-align: middle;\n width: var(--nostrc-icon-width);\n height: var(--nostrc-icon-height);\n }\n\n /* Like count display */\n .like-count {\n font-size: var(--nostrc-font-size-sm);\n color: var(--nostrc-theme-text-secondary, #666666);\n white-space: nowrap;\n text-decoration: underline;\n text-decoration-color: transparent;\n transition: text-decoration-color 0.2s ease, color 0.2s ease;\n }\n\n /* Clickable like count */\n .like-count.clickable {\n cursor: pointer;\n text-decoration-color: currentColor;\n }\n\n .like-count.clickable:hover {\n color: var(--nostrc-color-primary, #7f00ff);\n text-decoration-color: var(--nostrc-color-primary, #7f00ff);\n }\n\n /* Help icon */\n .help-icon {\n background: none;\n border: 1px solid var(--nostrc-color-border, #e0e0e0);\n border-radius: var(--nostrc-border-radius-full, 50%);\n width: var(--nostrc-help-icon-size, 16px);\n height: var(--nostrc-help-icon-size, 16px);\n font-size: calc(var(--nostrc-help-icon-size, 16px) * 0.7);\n font-weight: bold;\n color: var(--nostrc-theme-text-secondary, #666666);\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n margin-left: var(--nostrc-spacing-xs, 4px);\n transition: all 0.2s ease;\n }\n\n .help-icon:hover {\n background: var(--nostrc-color-hover-background, rgba(0, 0, 0, 0.05));\n border-color: var(--nostrc-color-primary, #7f00ff);\n color: var(--nostrc-color-primary, #7f00ff);\n }\n\n /* Skeleton loader for like count */\n .like-count.skeleton {\n background: linear-gradient(90deg, \n var(--nostrc-skeleton-color-min) 25%, \n var(--nostrc-skeleton-color-max) 50%, \n var(--nostrc-skeleton-color-min) 75%\n );\n background-size: 200% 100%;\n animation: skeleton-loading var(--nostrc-skeleton-duration) var(--nostrc-skeleton-timing-function) var(--nostrc-skeleton-iteration-count);\n border-radius: var(--nostrc-border-radius-sm);\n width: 80px;\n height: 1.2em;\n display: inline-block;\n }\n\n /* Skeleton loader for button text */\n .button-text-skeleton {\n background: linear-gradient(90deg, \n var(--nostrc-skeleton-color-min) 25%, \n var(--nostrc-skeleton-color-max) 50%, \n var(--nostrc-skeleton-color-min) 75%\n );\n background-size: 200% 100%;\n animation: skeleton-loading var(--nostrc-skeleton-duration) var(--nostrc-skeleton-timing-function) var(--nostrc-skeleton-iteration-count);\n border-radius: var(--nostrc-border-radius-sm);\n width: 60px;\n height: 1em;\n display: inline-block;\n }\n\n @keyframes skeleton-loading {\n 0% {\n background-position: 200% 0;\n }\n 100% {\n background-position: -200% 0;\n }\n }\n\n /* Error message styling */\n .nostr-like-button-error small {\n color: var(--nostrc-color-error-text);\n font-size: var(--nostrc-font-size-sm);\n line-height: 1em;\n max-width: 250px;\n white-space: pre-line;\n }\n `;\n \n return getComponentStyles(customStyles);\n}\n","// SPDX-License-Identifier: MIT\n\nexport function getHelpDialogStyles(): string {\n return `\n .help-content {\n padding: var(--nostrc-spacing-md, 12px);\n }\n\n .help-content p {\n margin: 0 0 var(--nostrc-spacing-md, 12px) 0;\n color: var(--nostrc-theme-text-primary, #333333);\n line-height: 1.5;\n }\n\n .help-content p:last-child {\n margin-bottom: 0;\n }\n\n .help-content ul {\n margin: 0 0 var(--nostrc-spacing-md, 12px) 0;\n padding-left: var(--nostrc-spacing-lg, 16px);\n color: var(--nostrc-theme-text-primary, #333333);\n }\n\n .help-content li {\n margin-bottom: var(--nostrc-spacing-xs, 4px);\n line-height: 1.5;\n }\n\n .help-content li:last-child {\n margin-bottom: 0;\n }\n\n .help-content strong {\n font-weight: 600;\n color: var(--nostrc-theme-text-primary, #333333);\n }\n\n .help-content a {\n color: var(--nostrc-theme-primary, #0066cc);\n text-decoration: underline;\n }\n\n .help-content a:hover {\n color: var(--nostrc-theme-primary-hover, #0052a3);\n }\n `;\n}\n\n","// SPDX-License-Identifier: MIT\n\n// Import for side effects to register the custom element\nimport '../base/dialog-component/dialog-component';\nimport type { DialogComponent } from '../base/dialog-component/dialog-component';\nimport { getHelpDialogStyles } from './dialog-help-style';\n\nexport const injectHelpDialogStyles = (): void => {\n // Check if styles are already injected\n if (document.querySelector('style[data-help-dialog-styles]')) return;\n \n const style = document.createElement('style');\n style.setAttribute('data-help-dialog-styles', 'true');\n style.textContent = getHelpDialogStyles();\n document.head.appendChild(style);\n};\n\nexport const showHelpDialog = async (theme?: 'light' | 'dark'): Promise<void> => {\n injectHelpDialogStyles();\n \n if (!customElements.get('dialog-component')) {\n await customElements.whenDefined('dialog-component');\n }\n \n const dialogComponent = document.createElement('dialog-component') as DialogComponent;\n dialogComponent.setAttribute('header', 'What is a Like?');\n if (theme) {\n dialogComponent.setAttribute('data-theme', theme);\n }\n \n // Set dialog content\n dialogComponent.innerHTML = `\n <div class=\"help-content\">\n <p>Like any webpage to show your appreciation! Your likes are stored on Nostr, a decentralized network you control—no accounts needed.</p>\n <ul>\n <li>Like any webpage or article</li>\n <li>See who liked the content</li>\n <li>Works with a browser extension like <a href=\"https://getalby.com\" target=\"_blank\" rel=\"noopener noreferrer\">Alby</a> or nos2x</li>\n </ul>\n </div>\n `;\n \n dialogComponent.showModal();\n};\n\n","// utils.ts\nimport { bytesToHex, hexToBytes } from \"@noble/hashes/utils\";\nvar utf8Decoder = new TextDecoder(\"utf-8\");\nvar utf8Encoder = new TextEncoder();\nfunction normalizeURL(url) {\n try {\n if (url.indexOf(\"://\") === -1)\n url = \"wss://\" + url;\n let p = new URL(url);\n if (p.protocol === \"http:\")\n p.protocol = \"ws:\";\n else if (p.protocol === \"https:\")\n p.protocol = \"wss:\";\n p.pathname = p.pathname.replace(/\\/+/g, \"/\");\n if (p.pathname.endsWith(\"/\"))\n p.pathname = p.pathname.slice(0, -1);\n if (p.port === \"80\" && p.protocol === \"ws:\" || p.port === \"443\" && p.protocol === \"wss:\")\n p.port = \"\";\n p.searchParams.sort();\n p.hash = \"\";\n return p.toString();\n } catch (e) {\n throw new Error(`Invalid URL: ${url}`);\n }\n}\nfunction insertEventIntoDescendingList(sortedArray, event) {\n const [idx, found] = binarySearch(sortedArray, (b) => {\n if (event.id === b.id)\n return 0;\n if (event.created_at === b.created_at)\n return -1;\n return b.created_at - event.created_at;\n });\n if (!found) {\n sortedArray.splice(idx, 0, event);\n }\n return sortedArray;\n}\nfunction insertEventIntoAscendingList(sortedArray, event) {\n const [idx, found] = binarySearch(sortedArray, (b) => {\n if (event.id === b.id)\n return 0;\n if (event.created_at === b.created_at)\n return -1;\n return event.created_at - b.created_at;\n });\n if (!found) {\n sortedArray.splice(idx, 0, event);\n }\n return sortedArray;\n}\nfunction binarySearch(arr, compare) {\n let start = 0;\n let end = arr.length - 1;\n while (start <= end) {\n const mid = Math.floor((start + end) / 2);\n const cmp = compare(arr[mid]);\n if (cmp === 0) {\n return [mid, true];\n }\n if (cmp < 0) {\n end = mid - 1;\n } else {\n start = mid + 1;\n }\n }\n return [start, false];\n}\nvar QueueNode = class {\n value;\n next = null;\n prev = null;\n constructor(message) {\n this.value = message;\n }\n};\nvar Queue = class {\n first;\n last;\n constructor() {\n this.first = null;\n this.last = null;\n }\n enqueue(value) {\n const newNode = new QueueNode(value);\n if (!this.last) {\n this.first = newNode;\n this.last = newNode;\n } else if (this.last === this.first) {\n this.last = newNode;\n this.last.prev = this.first;\n this.first.next = newNode;\n } else {\n newNode.prev = this.last;\n this.last.next = newNode;\n this.last = newNode;\n }\n return true;\n }\n dequeue() {\n if (!this.first)\n return null;\n if (this.first === this.last) {\n const target2 = this.first;\n this.first = null;\n this.last = null;\n return target2.value;\n }\n const target = this.first;\n this.first = target.next;\n if (this.first) {\n this.first.prev = null;\n }\n return target.value;\n }\n};\nexport {\n Queue,\n QueueNode,\n binarySearch,\n bytesToHex,\n hexToBytes,\n insertEventIntoAscendingList,\n insertEventIntoDescendingList,\n normalizeURL,\n utf8Decoder,\n utf8Encoder\n};\n","// SPDX-License-Identifier: MIT\n\nimport { SimplePool } from 'nostr-tools';\nimport { normalizeURL } from 'nostr-tools/utils';\nimport { ensureInitialized, getPublicKey, signEvent as signEventWithNostrLogin } from '../common/nostr-login-service';\n\n/**\n * Helper utilities for Nostr like operations using NIP-25 External Content Reactions.\n * These are deliberately kept self-contained so `nostr-like` Web Component can import\n * everything from a single module without polluting the rest of the codebase.\n */\n\nexport interface LikeDetails {\n authorPubkey: string;\n date: Date;\n content: string;\n}\n\nexport interface LikeCountResult {\n totalCount: number;\n likeDetails: LikeDetails[];\n likedCount: number;\n dislikedCount: number;\n}\n\n/**\n * Fetch all likes for a URL using NIP-25 kind 17 events\n */\nexport async function fetchLikesForUrl(\n url: string, \n relays: string[]\n): Promise<LikeCountResult> {\n // Normalize URL at the beginning for consistent comparison with tags\n const normalizedUrl = normalizeURL(url);\n \n const pool = new SimplePool();\n \n try {\n // Query kind 17 events (both likes and unlikes)\n const events = await pool.querySync(relays, {\n kinds: [17],\n '#k': ['web'],\n '#i': [normalizedUrl],\n limit: 1000\n });\n \n const likes: LikeDetails[] = [];\n let likedCount = 0;\n let dislikedCount = 0;\n \n for (const event of events) {\n likes.push({\n authorPubkey: event.pubkey,\n date: new Date(event.created_at * 1000),\n content: event.content\n });\n \n if (event.content === '-') {\n dislikedCount++;\n } else {\n likedCount++;\n }\n }\n \n likes.sort((a, b) => b.date.getTime() - a.date.getTime());\n \n const totalCount = likedCount - dislikedCount;\n \n return {\n totalCount: totalCount,\n likeDetails: likes,\n likedCount: likedCount,\n dislikedCount: dislikedCount\n };\n } catch (error) {\n // Rethrow error so callers can handle relay/network failures appropriately\n throw error instanceof Error ? error : new Error(String(error));\n } finally {\n pool.close(relays);\n }\n}\n\n/**\n * Create reaction event (kind 17)\n * @param url - URL to react to\n * @param content - '+' for like, '-' for unlike\n */\nexport function createReactionEvent(url: string, content: '+' | '-'): any {\n return {\n kind: 17,\n content,\n tags: [\n ['k', 'web'],\n ['i', url]\n ],\n created_at: Math.floor(Date.now() / 1000)\n };\n}\n\n/**\n * Create like event (kind 17)\n * @deprecated Use createReactionEvent(url, '+') instead\n */\nexport function createLikeEvent(url: string): any {\n return createReactionEvent(url, '+');\n}\n\n/**\n * Create unlike event (kind 17 with '-' content)\n * @deprecated Use createReactionEvent(url, '-') instead\n */\nexport function createUnlikeEvent(url: string): any {\n return createReactionEvent(url, '-');\n}\n\n/**\n * Check if user has liked a URL\n */\nexport async function hasUserLiked(\n url: string,\n userPubkey: string,\n relays: string[]\n): Promise<boolean> {\n const pool = new SimplePool();\n const normalizedUrl = url;\n \n try {\n // Get user's latest reaction for this URL\n const events = await pool.querySync(relays, {\n kinds: [17],\n authors: [userPubkey],\n '#k': ['web'],\n '#i': [normalizedUrl],\n limit: 1\n });\n \n if (events.length === 0) return false;\n \n // Check if latest reaction is a like (not an unlike)\n const latest = events[0];\n return latest.content === '+' || latest.content === '';\n } catch (error) {\n console.error(\"Nostr-Components: Like button: Error checking user like status\", error);\n return false;\n } finally {\n pool.close(relays);\n }\n}\n\n/**\n * Get user's pubkey from NostrLogin\n */\nexport async function getUserPubkey(): Promise<string | null> {\n try {\n await ensureInitialized();\n return await getPublicKey();\n } catch (error) {\n console.error(\"Nostr-Components: Like button: Error getting user pubkey\", error);\n return null;\n }\n}\n\n/**\n * Sign event with NostrLogin\n */\nexport async function signEvent(event: any): Promise<any> {\n try {\n await ensureInitialized();\n return await signEventWithNostrLogin(event);\n } catch (error) {\n console.error(\"Nostr-Components: Like button: Error signing event\", error);\n throw error;\n }\n}","// SPDX-License-Identifier: MIT\n\nimport { NostrBaseComponent } from '../base/base-component/nostr-base-component';\nimport { NCStatus } from '../base/base-component/nostr-base-component';\nimport { NDKEvent } from '@nostr-dev-kit/ndk';\nimport { renderLikeButton, RenderLikeButtonOptions } from './render';\nimport { getLikeButtonStyles } from './style';\nimport { showHelpDialog } from './dialog-help';\nimport { isValidUrl } from '../common/utils';\nimport { \n fetchLikesForUrl, \n createLikeEvent,\n createUnlikeEvent,\n hasUserLiked, \n getUserPubkey, \n signEvent, \n LikeCountResult \n} from './like-utils';\nimport { ensureInitialized } from '../common/nostr-login-service';\nimport { normalizeURL } from 'nostr-tools/utils';\n\n/**\n * <nostr-like>\n * Attributes:\n * - url (optional) : URL to like (default: current page URL)\n * - text (optional) : custom text (default \"Like\") (Max 32 characters)\n * - relays (optional) : comma-separated relay URLs\n * - data-theme (optional) : \"light\" | \"dark\" (default light)\n * \n * Features:\n * - URL-based likes using NIP-25 kind 17 events\n * - Click count to view likers\n */\nexport default class NostrLike extends NostrBaseComponent {\n protected likeActionStatus = this.channel('likeAction');\n protected likeListStatus = this.channel('likeList');\n \n private currentUrl: string = '';\n private isLiked: boolean = false;\n private likeCount: number = 0;\n private cachedLikeDetails: LikeCountResult | null = null;\n private loadSeq = 0;\n\n constructor() {\n super();\n this.likeListStatus.set(NCStatus.Loading);\n }\n\n connectedCallback() {\n super.connectedCallback?.();\n this.attachDelegatedListeners();\n this.render();\n }\n\n static get observedAttributes() {\n return [\n ...super.observedAttributes,\n 'url',\n 'text'\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 === 'url' || name === 'text') {\n this.likeActionStatus.set(NCStatus.Ready);\n this.likeListStatus.set(NCStatus.Loading);\n this.isLiked = false;\n this.errorMessage = '';\n this.updateLikeCount();\n this.render();\n }\n }\n\n /** Base class functions */\n protected validateInputs(): boolean {\n if (!super.validateInputs()) {\n this.likeActionStatus.set(NCStatus.Idle);\n this.likeListStatus.set(NCStatus.Idle);\n return false;\n }\n\n const urlAttr = this.getAttribute('url');\n const textAttr = this.getAttribute('text');\n const tagName = this.tagName.toLowerCase();\n\n let errorMessage: string | null = null;\n\n if (urlAttr) {\n if (!isValidUrl(urlAttr)) {\n errorMessage = 'Invalid URL format';\n }\n }\n\n if (textAttr && textAttr.length > 32) {\n errorMessage = 'Max text length: 32 characters';\n }\n\n if (errorMessage) {\n this.likeActionStatus.set(NCStatus.Error, errorMessage);\n this.likeListStatus.set(NCStatus.Error, errorMessage);\n console.error(`Nostr-Components: ${tagName}: ${errorMessage}`);\n return false;\n }\n\n return true;\n }\n\n protected onStatusChange(_status: NCStatus) {\n this.render();\n }\n\n protected onNostrRelaysConnected() {\n this.updateLikeCount();\n this.render();\n }\n\n /** Private functions */\n /**\n * Lazy initializer for currentUrl - ensures it's set before like/unlike operations\n */\n private ensureCurrentUrl(): void {\n if (!this.currentUrl) {\n this.currentUrl = normalizeURL(this.getAttribute('url') || window.location.href);\n }\n }\n\n private async updateLikeCount() {\n const seq = ++this.loadSeq;\n try {\n await this.ensureNostrConnected();\n this.currentUrl = normalizeURL(this.getAttribute('url') || window.location.href);\n this.likeListStatus.set(NCStatus.Loading);\n this.render();\n \n const result = await fetchLikesForUrl(this.currentUrl, this.getRelays());\n if (seq !== this.loadSeq) return; // stale\n this.likeCount = result.totalCount;\n this.cachedLikeDetails = result;\n this.likeListStatus.set(NCStatus.Ready);\n } catch (error) {\n console.error('[NostrLike] Failed to fetch like count:', error);\n this.likeListStatus.set(NCStatus.Error, 'Failed to load likes');\n } finally {\n this.render();\n }\n }\n\n private async handleLikeClick() {\n // Ensure currentUrl is set before proceeding\n this.ensureCurrentUrl();\n \n if (!this.currentUrl) {\n this.likeActionStatus.set(NCStatus.Error, 'Invalid URL');\n this.render();\n return;\n }\n\n this.likeActionStatus.set(NCStatus.Loading);\n this.render();\n\n try {\n // Ensure NostrLogin is initialized (sets up window.nostr)\n await ensureInitialized();\n\n // Check user like status\n const userPubkey = await getUserPubkey();\n if (userPubkey) {\n this.isLiked = await hasUserLiked(this.currentUrl, userPubkey, this.getRelays());\n }\n\n // If already liked, show confirmation dialog\n if (this.isLiked) {\n const confirmed = window.confirm('You have already liked this. Do you want to unlike it?');\n if (!confirmed) {\n this.likeActionStatus.set(NCStatus.Ready);\n this.render();\n return;\n }\n \n // Proceed with unlike\n await this.handleUnlike();\n } else {\n // Proceed with like\n await this.handleLike();\n }\n } catch (error) {\n console.error('[NostrLike] Failed to check user like status:', error);\n const errorMessage = error instanceof Error ? error.message : 'Failed to check user like status';\n this.likeActionStatus.set(NCStatus.Error, errorMessage);\n this.render();\n }\n }\n\n private async handleLike() {\n // Ensure currentUrl is set before proceeding\n this.ensureCurrentUrl();\n \n if (!this.currentUrl) {\n this.likeActionStatus.set(NCStatus.Error, 'Invalid URL');\n this.render();\n return;\n }\n\n this.likeActionStatus.set(NCStatus.Loading);\n this.render();\n\n try {\n // Create like event\n const event = createLikeEvent(this.currentUrl);\n \n // Sign with NIP-07\n const signedEvent = await signEvent(event);\n \n // Create NDKEvent and publish\n const ndkEvent = new NDKEvent(this.nostrService.getNDK(), signedEvent);\n await ndkEvent.publish();\n \n // Update state optimistically\n this.isLiked = true;\n this.likeCount++;\n this.likeActionStatus.set(NCStatus.Ready);\n \n // Refresh like count to get accurate data\n await this.updateLikeCount();\n } catch (error) {\n console.error('[NostrLike] Failed to like:', error);\n \n // Rollback optimistic update\n this.isLiked = false;\n this.likeCount--;\n \n const errorMessage = error instanceof Error ? error.message : 'Failed to like';\n this.likeActionStatus.set(NCStatus.Error, errorMessage);\n } finally {\n this.render();\n }\n }\n\n private async handleUnlike() {\n // Ensure currentUrl is set before proceeding\n this.ensureCurrentUrl();\n \n if (!this.currentUrl) {\n this.likeActionStatus.set(NCStatus.Error, 'Invalid URL');\n this.render();\n return;\n }\n\n this.likeActionStatus.set(NCStatus.Loading);\n this.render();\n \n try {\n // Create unlike event\n const event = createUnlikeEvent(this.currentUrl);\n \n // Sign with NIP-07\n const signedEvent = await signEvent(event);\n \n // Create NDKEvent and publish\n const ndkEvent = new NDKEvent(this.nostrService.getNDK(), signedEvent);\n await ndkEvent.publish();\n \n // Update state optimistically\n this.isLiked = false;\n if (this.likeCount > 0) {\n this.likeCount--;\n }\n this.likeActionStatus.set(NCStatus.Ready);\n \n // Refresh like count to get accurate data\n await this.updateLikeCount();\n } catch (error) {\n console.error('[NostrLike] Failed to unlike:', error);\n \n // Rollback optimistic update\n this.isLiked = true;\n this.likeCount++;\n \n const errorMessage = error instanceof Error ? error.message : 'Failed to unlike';\n this.likeActionStatus.set(NCStatus.Error, errorMessage);\n } finally {\n this.render();\n }\n }\n\n private async handleCountClick() {\n if (this.likeCount === 0 || !this.cachedLikeDetails) {\n return;\n }\n\n try {\n // Import dialog dynamically to avoid circular dependencies\n const { openLikersDialog } = await import('./dialog-likers');\n await openLikersDialog({\n likeDetails: this.cachedLikeDetails.likeDetails,\n theme: this.theme === 'dark' ? 'dark' : 'light',\n });\n } catch (error) {\n console.error('[NostrLike] Error opening likers dialog:', error);\n }\n }\n\n private async handleHelpClick() {\n try {\n await showHelpDialog(this.theme === 'dark' ? 'dark' : 'light');\n } catch (error) {\n console.error('[NostrLike] Error showing help dialog:', error);\n }\n }\n\n private attachDelegatedListeners() {\n this.delegateEvent('click', '.nostr-like-button', (e) => {\n e.preventDefault?.();\n e.stopPropagation?.();\n void this.handleLikeClick();\n });\n\n this.delegateEvent('click', '.like-count', (e) => {\n e.preventDefault?.();\n e.stopPropagation?.();\n void this.handleCountClick();\n });\n\n this.delegateEvent('click', '.help-icon', (e) => {\n e.preventDefault?.();\n e.stopPropagation?.();\n this.handleHelpClick();\n });\n }\n\n protected renderContent() {\n // console.log(`Like: Render: conn: ${this.conn.get()}, likeActionStatus: ${this.likeActionStatus.get()}, likeListStatus: ${this.likeListStatus.get()}`);\n const isLoading = this.likeActionStatus.get() === NCStatus.Loading || this.conn.get() === NCStatus.Loading;\n const isCountLoading = this.likeListStatus.get() === NCStatus.Loading;\n const isError = this.computeOverall() === NCStatus.Error;\n const errorMessage = this.errorMessage;\n const buttonText = this.getAttribute('text') || 'Like';\n\n const renderOptions: RenderLikeButtonOptions = {\n isLoading,\n isError,\n errorMessage,\n buttonText,\n isLiked: this.isLiked,\n likeCount: this.likeCount,\n hasLikes: this.likeCount > 0,\n isCountLoading,\n theme: this.theme as 'light' | 'dark',\n };\n\n this.shadowRoot!.innerHTML = `\n ${getLikeButtonStyles()}\n ${renderLikeButton(renderOptions)}\n `;\n }\n}\n\ncustomElements.define('nostr-like', NostrLike);\n"],"file":"components/nostr-like.es.js"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var P=Object.defineProperty;var H=(h,f,t)=>f in h?P(h,f,{enumerable:!0,configurable:!0,writable:!0,value:t}):h[f]=t;var a=(h,f,t)=>H(h,typeof f!="symbol"?f+"":f,t);import{_ as L}from"../assets/preload-helper-D7HrI6pR.js";import{
|
|
1
|
+
var P=Object.defineProperty;var H=(h,f,t)=>f in h?P(h,f,{enumerable:!0,configurable:!0,writable:!0,value:t}):h[f]=t;var a=(h,f,t)=>H(h,typeof f!="symbol"?f+"":f,t);import{_ as L}from"../assets/preload-helper-D7HrI6pR.js";import{N as A,D,c as v,d as $,e as M,g as S}from"../assets/nostr-service-m3Hgc5Xx.js";import{g as R,a as C}from"../assets/theme-C1r1Zw8r.js";import{r as U}from"../assets/nip05-utils-BNBHUmkr.js";import"../assets/icons-Dr_d9MII.js";function K(h){try{return new Date(h*1e3).toLocaleString()}catch{return""}}function _(h){try{const f=Date.now(),t=h*1e3,r=f-t,e=Math.floor(r/1e3);if(e<60)return"just now";if(e<3600){const s=Math.floor(e/60);return`${s} ${s===1?"min":"mins"} ago`}if(e<86400){const s=Math.floor(e/3600);return`${s} ${s===1?"hour":"hours"} ago`}if(e<2592e3){const s=Math.floor(e/86400);return`${s} ${s===1?"day":"days"} ago`}if(e<31536e3){const s=Math.floor(e/2592e3);return`${s} ${s===1?"month":"months"} ago`}const o=Math.floor(e/31536e3);return`${o} ${o===1?"year":"years"} ago`}catch{return""}}function I(h){return h==="me"||h==="them"?h:"them"}function y(h){return h==null?"":String(h).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function O({theme:h,recipientNpub:f,recipientName:t,recipientPicture:r,message:e,messages:o,isLoading:s,isFinding:l,isError:p,errorMessage:i,currentUserName:d,currentUserPicture:b,showWelcome:k,welcomeText:u,startChatText:n,maxMessageLength:g}){const m=typeof g=="number"?g:1e3,N=(e||"").length,E=Math.max(0,m-N),T=E<=10?"nostr-chat-char-counter warn":"nostr-chat-char-counter";return`
|
|
2
2
|
<div class="nostr-chat-container ${p?"nostr-chat-error":""}">
|
|
3
3
|
<div class="nostr-chat-header">
|
|
4
4
|
<div class="nostr-chat-header-left">
|
|
@@ -495,7 +495,7 @@ var P=Object.defineProperty;var H=(h,f,t)=>f in h?P(h,f,{enumerable:!0,configura
|
|
|
495
495
|
text-align: center;
|
|
496
496
|
}
|
|
497
497
|
</style>
|
|
498
|
-
`}const x=class x extends HTMLElement{constructor(){super();a(this,"rendered",!1);a(this,"nostrService",A.getInstance());a(this,"dmSubscription",null);a(this,"theme","light");a(this,"recipientNpub",null);a(this,"recipientNip05",null);a(this,"recipientName",null);a(this,"recipientPicture",null);a(this,"recipientPubkey",null);a(this,"message","");a(this,"messages",[]);a(this,"currentUserPubkey",null);a(this,"currentUserNpub",null);a(this,"currentUserName",null);a(this,"currentUserPicture",null);a(this,"displayType","embed");a(this,"isOpen",!1);a(this,"showWelcome",!1);a(this,"welcomeText",x.DEFAULT_WELCOME_TEXT);a(this,"startChatText",x.DEFAULT_START_CHAT_TEXT);a(this,"onlineText",x.DEFAULT_ONLINE_TEXT);a(this,"helpText",x.DEFAULT_HELP_TEXT);a(this,"MESSAGE_MAX_LENGTH",1e3);a(this,"isLoading",!1);a(this,"isFinding",!1);a(this,"isError",!1);a(this,"errorMessage","");a(this,"keySupplier",null);a(this,"boundHandleFind",null);a(this,"boundHandleSend",null);a(this,"boundHandleTextareaChange",null);a(this,"boundHandleLauncherClick",null);a(this,"boundHandleCloseClick",null);a(this,"boundHandleStartChat",null);a(this,"boundHandleNpubKeydown",null);a(this,"resubscribeTimer",null);a(this,"getRelays",()=>{const t=this.getAttribute("relays");return t?t.split(",").map(r=>r.trim()).filter(r=>r.length>0).filter((r,e,o)=>o.indexOf(r)===e):D});a(this,"getTheme",()=>{const t=this.getAttribute("theme"),r=(t||"").toLowerCase();r==="light"||r==="dark"?this.theme=r:(t&&console.warn(`Invalid theme '${t}'. Accepted values are 'light', 'dark'. Falling back to 'light'.`),this.theme="light")});a(this,"getRecipient",()=>{const t=this.getAttribute("pubkey");if(t)try{this.recipientPubkey=t,this.recipientNpub=v.npubEncode(t),this.lookupRecipient(this.recipientNpub);return}catch(o){const s=`Invalid recipient pubkey "${t}": ${o instanceof Error?o.message:String(o)}`;this.isError=!0,this.errorMessage=s,console.error("nostr-live-chat:",s,o),this.render();return}const r=this.getAttribute("nip05");if(r){this.recipientNip05=r,this.lookupRecipientByNip05();return}const e=this.getAttribute("npub");e&&(this.recipientNpub=e,this.lookupRecipient())});this.attachShadow({mode:"open"})}async getCurrentUserInfo(){var t,r,e,o,s,l,p,i,d,b;try{const k=this.nostrService.getNDK();let u=null;if(typeof window<"u"&&window.nostr){const n=window.nostr;console.log("Nostr extension found, checking for public key...");try{const g=!!(n.enable&&typeof n.enable=="function"&&n.getPublicKey&&typeof n.getPublicKey=="function");if(console.log("Is this nos2x extension?",g),g){console.log("Using nos2x specific flow");try{await n.enable(),console.log("nos2x extension enabled"),await new Promise(m=>setTimeout(m,100));const c=await n.getPublicKey();console.log("nos2x returned pubkey:",c),c&&typeof c=="string"&&c.length===64&&(u=c,console.log("Successfully got pubkey from nos2x:",u))}catch(c){console.error("Error with nos2x extension:",c)}}else{if(typeof n.enable=="function"){console.log("Attempting to enable generic extension...");try{await n.enable(),console.log("Extension enabled successfully")}catch(c){console.warn("Extension enable failed, continuing anyway:",c)}}if(typeof n.getPublicKey=="function"){console.log("Calling getPublicKey()...");try{u=await n.getPublicKey(),console.log("Got pubkey from extension:",u)}catch(c){console.error("Error getting public key:",c)}}else if(n.getPublicKey){console.log("Found getPublicKey property, resolving...");try{u=await Promise.resolve(n.getPublicKey),console.log("Got pubkey from extension (property):",u)}catch(c){console.error("Error resolving public key:",c)}}}}catch(g){console.error("Error in extension interaction:",g)}}if(!u){let n=null;if(this.keySupplier)try{n=await this.keySupplier()}catch{}if(n)try{const{NDKPrivateKeySigner:g}=await L(async()=>{const{NDKPrivateKeySigner:E}=await import("../assets/nostr-service-CnaPxjc6.js").then(T=>T.k);return{NDKPrivateKeySigner:E}},[]);let c=n;n.startsWith("nsec")&&(c=v.decode(n).data),u=(await new g(c).user()).pubkey}catch{}}if(u){this.currentUserPubkey=u,this.currentUserNpub=v.npubEncode(u),console.log("Got pubkey from extension and will use it:",u);try{const n=k.getUser({pubkey:u});console.log("Fetching profile for user:",u),await n.fetchProfile(),console.log("Fetched profile:",n.profile),this.currentUserName=((t=n.profile)==null?void 0:t.displayName)||((r=n.profile)==null?void 0:r.name)||((e=this.currentUserNpub)==null?void 0:e.substring(0,10))||null,this.currentUserPicture=((o=n.profile)==null?void 0:o.image)||null,this.currentUserName||console.warn("No username found in profile"),this.currentUserPicture||console.warn("No profile picture found"),console.log("Profile info set:",{name:this.currentUserName,picture:this.currentUserPicture,npub:this.currentUserNpub})}catch(n){console.error("Error fetching profile:",n),this.currentUserName=((s=this.currentUserNpub)==null?void 0:s.substring(0,10))||null}this.render()}else{console.log("Checking for direct nos2x logs in console...");try{if(await new Promise(n=>setTimeout(n,500)),typeof window<"u"&&window.nostr){console.log("Trying direct call to extension again...");try{const n=await window.nostr.getPublicKey();if(n&&typeof n=="string"){console.log("Got pubkey on second try:",n),this.currentUserPubkey=n,this.currentUserNpub=v.npubEncode(n);try{const g=k.getUser({pubkey:n});console.log("Fetching profile for user on second try:",n),await g.fetchProfile(),console.log("Fetched profile on second try:",g.profile),this.currentUserName=((l=g.profile)==null?void 0:l.displayName)||((p=g.profile)==null?void 0:p.name)||((i=this.currentUserNpub)==null?void 0:i.substring(0,10))||null,this.currentUserPicture=((d=g.profile)==null?void 0:d.image)||null,this.render();return}catch(g){console.error("Error fetching profile on second try:",g),this.currentUserName=((b=this.currentUserNpub)==null?void 0:b.substring(0,10))||null,this.render();return}}}catch(n){console.error("Error getting pubkey on direct second try:",n)}}}catch(n){console.error("Error in fallback pubkey detection:",n)}console.warn("No pubkey available from extension - trying fallback method")}}catch{}}getDisplayType(){const t=this.getAttribute("display-type"),r=["fab","bottom-bar","full","embed"],o=(t?String(t):"").toLowerCase(),s=r.includes(o)?o:"embed";this.displayType=s,this.displayType==="full"?this.isOpen=!0:this.displayType==="fab"||this.displayType==="bottom-bar"?(this.isOpen===void 0||this.isOpen===null)&&(this.isOpen=!1):this.isOpen=!1,this.getAttribute("display-type")!==s&&this.setAttribute("display-type",s)}connectedCallback(){if(!this.rendered){this.getTheme(),this.getDisplayType();const t=this.getAttribute("welcome-text");t&&(this.welcomeText=t);const r=this.getAttribute("start-chat-text");r&&(this.startChatText=r);const e=this.getAttribute("online-text");e&&(this.onlineText=e);const o=this.getAttribute("help-text");o&&(this.helpText=o),this.getRecipient(),this.nostrService.connectToNostr(this.getRelays()),this.getCurrentUserInfo(),this.render(),this.rendered=!0}}static get observedAttributes(){return["npub","pubkey","nip05","relays","theme","display-type","welcome-text","start-chat-text","online-text","help-text","history-days"]}unsubscribeFromDms(){if(this.dmSubscription){try{this.dmSubscription.stop()}catch{}this.dmSubscription=null}this.resubscribeTimer&&(clearTimeout(this.resubscribeTimer),this.resubscribeTimer=null)}clearRecipientAndChatState(){this.recipientPubkey=null,this.recipientNpub=null,this.recipientNip05=null,this.recipientName=null,this.recipientPicture=null,this.messages=[],this.message="",this.showWelcome=!1,this.isLoading=!1,this.isFinding=!1,this.isError=!1,this.errorMessage=""}attributeChangedCallback(t,r,e){if(this.rendered)if(t==="npub"){if(e===null){this.unsubscribeFromDms(),this.clearRecipientAndChatState(),this.render();return}e!==r&&(this.unsubscribeFromDms(),this.clearRecipientAndChatState(),this.recipientNpub=e,this.lookupRecipient());return}else if(t==="pubkey"){if(e===null){this.unsubscribeFromDms(),this.clearRecipientAndChatState(),this.render();return}if(e!==r){this.unsubscribeFromDms(),this.clearRecipientAndChatState();try{this.recipientPubkey=e,this.recipientNpub=v.npubEncode(e),this.lookupRecipient(this.recipientNpub)}catch{}}return}else if(t==="nip05"){if(e===null){this.unsubscribeFromDms(),this.clearRecipientAndChatState(),this.render();return}e!==r&&(this.unsubscribeFromDms(),this.clearRecipientAndChatState(),this.recipientNip05=e,this.lookupRecipientByNip05());return}else if(t==="relays"){if(e!==r){const o=this.getRelays();this.recipientPubkey&&!this.showWelcome?(this.resubscribeTimer&&clearTimeout(this.resubscribeTimer),this.resubscribeTimer=window.setTimeout(()=>{this.unsubscribeFromDms(),this.nostrService.connectToNostr(o),this.subscribeToDms()},300)):this.nostrService.connectToNostr(o)}}else t==="theme"?(this.getTheme(),this.render()):t==="display-type"?(this.getDisplayType(),this.render()):t==="welcome-text"?(this.welcomeText=e!==null?e:x.DEFAULT_WELCOME_TEXT,this.render()):t==="start-chat-text"?(this.startChatText=e!==null?e:x.DEFAULT_START_CHAT_TEXT,this.render()):t==="online-text"?(this.onlineText=e!==null?e:x.DEFAULT_ONLINE_TEXT,this.render()):t==="help-text"?(this.helpText=e!==null?e:x.DEFAULT_HELP_TEXT,this.render()):t==="history-days"&&e!==r&&this.recipientPubkey&&!this.showWelcome&&(this.resubscribeTimer&&clearTimeout(this.resubscribeTimer),this.resubscribeTimer=window.setTimeout(()=>{this.subscribeToDms()},250))}async lookupRecipient(t){var r,e,o;this.unsubscribeFromDms(),this.messages=[],this.showWelcome=!1,this.isFinding=!0,this.render();try{const s=t||this.recipientNpub;if(!s)return;const{type:l,data:p}=v.decode(s);if(l!=="npub")throw new Error("Invalid npub");this.recipientPubkey=p;const i=this.nostrService.getNDK().getUser({pubkey:this.recipientPubkey});await i.fetchProfile(),this.recipientName=((r=i.profile)==null?void 0:r.displayName)||((e=i.profile)==null?void 0:e.name)||s.substring(0,10),this.recipientPicture=((o=i.profile)==null?void 0:o.image)||null,this.showWelcome=!0,this.messages=[],this.isError=!1,this.errorMessage="",this.render()}catch(s){this.isError=!0,this.errorMessage=s.message}finally{this.isFinding=!1,this.render()}}async lookupRecipientByNip05(t){this.isFinding=!0,this.render();try{const r=t||this.recipientNip05;if(!r)return;const e=await U(r),o=v.npubEncode(e);this.recipientNpub=o,this.isError=!1,this.errorMessage="",await this.lookupRecipient(o)}catch(r){this.isError=!0,this.errorMessage=r.message}finally{this.isFinding=!1,this.render()}}handleFindClick(){const r=this.shadowRoot.querySelector(".nostr-chat-npub-input").value.trim();this.isError=!1,this.errorMessage="",this.render(),r&&(r.startsWith("npub")?(this.recipientNpub=r,this.lookupRecipient()):r.includes("@")?(this.recipientNip05=r,this.lookupRecipientByNip05()):(this.isError=!0,this.errorMessage="Invalid input. Please provide an npub or nip05 address.",this.render()))}async handleSendClick(){var r,e;if(!this.message.trim()||!this.recipientPubkey)return;if(this.message.length>this.MESSAGE_MAX_LENGTH){this.isError=!0,this.errorMessage=`Message is too long (max ${this.MESSAGE_MAX_LENGTH} characters).`,this.render();return}this.isLoading=!0,this.render();let t=null;try{const o=this.nostrService.getNDK();let s;if(typeof window<"u"&&window.nostr&&window.nostr.getPublicKey&&window.nostr.signEvent)try{s=new $}catch(d){console.error("Error creating NIP-07 signer:",d),this.isError=!0,this.errorMessage=`Error connecting to Nostr extension: ${d.message}`,this.isLoading=!1,this.render();return}if(!s)throw new Error("No signer available. Please install a NIP-07 extension or set a private key.");o.signer=s;const l=new M(o,{kind:S.EncryptedDirectMessage,tags:[["p",this.recipientPubkey]],created_at:Math.floor(Date.now()/1e3)});let p=!1;if(typeof((e=(r=window.nostr)==null?void 0:r.nip04)==null?void 0:e.encrypt)=="function")try{l.content=await window.nostr.nip04.encrypt(this.recipientPubkey,this.message.trim()),p=!0}catch(d){console.error("NIP-07 encryption failed, falling back to local encryption:",d)}if(!p)throw new Error("No private key available for encryption. Please use a NIP-07 extension.");t=`temp_${Date.now()}`,this.messages.push({id:t,text:this.message,sender:"me",timestamp:l.created_at,status:"sending"}),this.message="",this.render(),await l.publish();const i=this.messages.find(d=>d.id===t);i&&(this.messages.find(b=>b.id===l.id&&b.id!==t)?this.messages=this.messages.filter(b=>b.id!==t):(i.id=l.id,i.status="sent"),this.render())}catch(o){if(this.isError=!0,this.errorMessage=o.message,t){const s=this.messages.find(l=>l.id===t);s&&(s.status="failed"),this.render()}}finally{this.isLoading=!1,this.render()}}handleTextareaChange(t){var s;const r=t.target;this.message=r.value;const e=Math.max(0,this.MESSAGE_MAX_LENGTH-this.message.length),o=(s=this.shadowRoot)==null?void 0:s.querySelector(".nostr-chat-char-counter");o&&(o.textContent=`${e} chars left`,o.classList.toggle("warn",e<=10))}handleStartChat(){this.showWelcome=!1,this.subscribeToDms(),this.render()}async subscribeToDms(){if(this.dmSubscription&&this.dmSubscription.stop(),!this.recipientPubkey)return;let t=null;try{if(typeof window<"u"&&window.nostr&&window.nostr.getPublicKey)t={pubkey:await window.nostr.getPublicKey()};else{let i=null;if(this.keySupplier)try{i=await this.keySupplier()}catch{}if(i){const{NDKPrivateKeySigner:d}=await L(async()=>{const{NDKPrivateKeySigner:u}=await import("../assets/nostr-service-CnaPxjc6.js").then(n=>n.k);return{NDKPrivateKeySigner:u}},[]);let b=i;i.startsWith("nsec")&&(b=v.decode(i).data),t=await new d(b).user()}}}catch(i){console.error("Failed to determine current user for subscription",i)}if(!t){this.isError=!0,this.errorMessage="No signer available. Please install a NIP-07 extension or set a private key to start the chat.",this.render();return}this.messages=[];const r=this.getAttribute("history-days");let e;if(!r)e=void 0;else if(r.toLowerCase()==="all"||parseInt(r,10)<=0)e=void 0;else{const i=Math.max(1,parseInt(r,10)||30);e=Math.floor((Date.now()-i*24*60*60*1e3)/1e3)}const o={kinds:[S.EncryptedDirectMessage],"#p":[t.pubkey],authors:[this.recipientPubkey]},s={kinds:[S.EncryptedDirectMessage],"#p":[this.recipientPubkey],authors:[t.pubkey]},l=e!==void 0?{...o,since:e}:o,p=e!==void 0?{...s,since:e}:s;this.dmSubscription=this.nostrService.getNDK().subscribe([l,p],{closeOnEose:!1,groupable:!1}),this.dmSubscription.on("event",async i=>{var d;try{!this.currentUserPubkey&&t&&(this.currentUserPubkey=t.pubkey,this.currentUserNpub=v.npubEncode(t.pubkey));const b=i.pubkey===t.pubkey,k=b?(d=i.tags.find(c=>c[0]==="p"))==null?void 0:d[1]:i.pubkey;if(!k){try{console.debug("nostr-live-chat: skipping event with missing peer",i.id)}catch{}return}if(k!==this.recipientPubkey)return;if(b){const c=this.messages.find(m=>m.id===i.id);if(c){c.status==="sending"&&(c.status="sent",this.render());return}}let u="";if(!k){try{console.debug("nostr-live-chat: missing peer prior to decrypt, skipping",i.id)}catch{}return}if(!i.content||i.content.trim()===""){try{console.debug("nostr-live-chat: missing or empty content prior to decrypt, skipping",i.id)}catch{}return}if(window.nostr&&window.nostr.nip04&&typeof window.nostr.nip04.decrypt=="function")try{u=await window.nostr.nip04.decrypt(k,i.content)}catch(c){console.error("Failed to decrypt DM content:",c);return}else throw new Error("No private key available for decryption. Please use a NIP-07 extension.");if(b){const c=this.messages.find(m=>m.status==="sending"&&m.sender==="me"&&m.text===u&&Math.abs(m.timestamp-i.created_at)<2);if(c){c.id=i.id,c.status="sent",this.render();return}}const n={id:i.id,text:u,sender:b?"me":"them",timestamp:i.created_at,status:"sent"};this.messages.find(c=>c.id===n.id)||(this.messages.push(n),this.messages.sort((c,m)=>c.timestamp-m.timestamp),this.render())}catch(b){console.error("Failed to decrypt DM content:",b)}})}attachEventListeners(){const t=this.shadowRoot.querySelector(".nostr-chat-launcher");t&&(this.boundHandleLauncherClick&&t.removeEventListener("click",this.boundHandleLauncherClick),this.boundHandleLauncherClick=()=>{this.isOpen=!0,this.render()},t.addEventListener("click",this.boundHandleLauncherClick));const r=this.shadowRoot.querySelector(".nostr-chat-close-btn");r&&(this.boundHandleCloseClick&&r.removeEventListener("click",this.boundHandleCloseClick),this.boundHandleCloseClick=i=>{i==null||i.stopPropagation(),(this.displayType==="fab"||this.displayType==="bottom-bar")&&(this.isOpen=!1),this.render()},r.addEventListener("click",this.boundHandleCloseClick));const e=this.shadowRoot.querySelector(".nostr-chat-find-btn");e&&(this.boundHandleFind&&e.removeEventListener("click",this.boundHandleFind),this.boundHandleFind=this.handleFindClick.bind(this),e.addEventListener("click",this.boundHandleFind));const o=this.shadowRoot.querySelector(".nostr-chat-send-btn");o&&(this.boundHandleSend&&o.removeEventListener("click",this.boundHandleSend),this.boundHandleSend=this.handleSendClick.bind(this),o.addEventListener("click",this.boundHandleSend));const s=this.shadowRoot.querySelector(".nostr-chat-start-btn");s&&(this.boundHandleStartChat&&s.removeEventListener("click",this.boundHandleStartChat),this.boundHandleStartChat=this.handleStartChat.bind(this),s.addEventListener("click",this.boundHandleStartChat));const l=this.shadowRoot.querySelector(".nostr-chat-textarea");l&&(this.boundHandleTextareaChange&&l.removeEventListener("input",this.boundHandleTextareaChange),this.boundHandleTextareaChange=this.handleTextareaChange.bind(this),l.addEventListener("input",this.boundHandleTextareaChange));const p=this.shadowRoot.querySelector(".nostr-chat-npub-input");p&&(this.boundHandleNpubKeydown&&p.removeEventListener("keydown",this.boundHandleNpubKeydown),this.boundHandleNpubKeydown=i=>{i.key==="Enter"&&this.handleFindClick()},p.addEventListener("keydown",this.boundHandleNpubKeydown))}disconnectedCallback(){var i,d,b,k,u,n,g;this.dmSubscription&&this.dmSubscription.stop();const t=(i=this.shadowRoot)==null?void 0:i.querySelector(".nostr-chat-launcher");t&&this.boundHandleLauncherClick&&t.removeEventListener("click",this.boundHandleLauncherClick);const r=(d=this.shadowRoot)==null?void 0:d.querySelector(".nostr-chat-close-btn");r&&this.boundHandleCloseClick&&r.removeEventListener("click",this.boundHandleCloseClick);const e=(b=this.shadowRoot)==null?void 0:b.querySelector(".nostr-chat-find-btn");e&&this.boundHandleFind&&e.removeEventListener("click",this.boundHandleFind);const o=(k=this.shadowRoot)==null?void 0:k.querySelector(".nostr-chat-send-btn");o&&this.boundHandleSend&&o.removeEventListener("click",this.boundHandleSend);const s=(u=this.shadowRoot)==null?void 0:u.querySelector(".nostr-chat-start-btn");s&&this.boundHandleStartChat&&s.removeEventListener("click",this.boundHandleStartChat);const l=(n=this.shadowRoot)==null?void 0:n.querySelector(".nostr-chat-textarea");l&&this.boundHandleTextareaChange&&l.removeEventListener("input",this.boundHandleTextareaChange);const p=(g=this.shadowRoot)==null?void 0:g.querySelector(".nostr-chat-npub-input");p&&this.boundHandleNpubKeydown&&p.removeEventListener("keydown",this.boundHandleNpubKeydown),this.resubscribeTimer&&(clearTimeout(this.resubscribeTimer),this.resubscribeTimer=null)}setKeySupplier(t){this.keySupplier=t}escapeHtml(t){return t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}render(){const t={theme:this.theme,recipientNpub:this.recipientNpub,recipientName:this.recipientName,recipientPicture:this.recipientPicture,message:this.message,messages:this.messages,isLoading:this.isLoading,isFinding:this.isFinding,isError:this.isError,errorMessage:this.errorMessage,currentUserName:this.currentUserName,currentUserPicture:this.currentUserPicture,showWelcome:this.showWelcome,welcomeText:this.welcomeText,startChatText:this.startChatText,onlineText:this.onlineText,helpText:this.helpText,maxMessageLength:this.MESSAGE_MAX_LENGTH},r=z(this.theme),{onlineText:e,helpText:o,...s}=t,l=O(s);let p=r;this.displayType==="embed"?p+=l:this.displayType==="full"?p+=`
|
|
498
|
+
`}const x=class x extends HTMLElement{constructor(){super();a(this,"rendered",!1);a(this,"nostrService",A.getInstance());a(this,"dmSubscription",null);a(this,"theme","light");a(this,"recipientNpub",null);a(this,"recipientNip05",null);a(this,"recipientName",null);a(this,"recipientPicture",null);a(this,"recipientPubkey",null);a(this,"message","");a(this,"messages",[]);a(this,"currentUserPubkey",null);a(this,"currentUserNpub",null);a(this,"currentUserName",null);a(this,"currentUserPicture",null);a(this,"displayType","embed");a(this,"isOpen",!1);a(this,"showWelcome",!1);a(this,"welcomeText",x.DEFAULT_WELCOME_TEXT);a(this,"startChatText",x.DEFAULT_START_CHAT_TEXT);a(this,"onlineText",x.DEFAULT_ONLINE_TEXT);a(this,"helpText",x.DEFAULT_HELP_TEXT);a(this,"MESSAGE_MAX_LENGTH",1e3);a(this,"isLoading",!1);a(this,"isFinding",!1);a(this,"isError",!1);a(this,"errorMessage","");a(this,"keySupplier",null);a(this,"boundHandleFind",null);a(this,"boundHandleSend",null);a(this,"boundHandleTextareaChange",null);a(this,"boundHandleLauncherClick",null);a(this,"boundHandleCloseClick",null);a(this,"boundHandleStartChat",null);a(this,"boundHandleNpubKeydown",null);a(this,"resubscribeTimer",null);a(this,"getRelays",()=>{const t=this.getAttribute("relays");return t?t.split(",").map(r=>r.trim()).filter(r=>r.length>0).filter((r,e,o)=>o.indexOf(r)===e):D});a(this,"getTheme",()=>{const t=this.getAttribute("theme"),r=(t||"").toLowerCase();r==="light"||r==="dark"?this.theme=r:(t&&console.warn(`Invalid theme '${t}'. Accepted values are 'light', 'dark'. Falling back to 'light'.`),this.theme="light")});a(this,"getRecipient",()=>{const t=this.getAttribute("pubkey");if(t)try{this.recipientPubkey=t,this.recipientNpub=v.npubEncode(t),this.lookupRecipient(this.recipientNpub);return}catch(o){const s=`Invalid recipient pubkey "${t}": ${o instanceof Error?o.message:String(o)}`;this.isError=!0,this.errorMessage=s,console.error("nostr-live-chat:",s,o),this.render();return}const r=this.getAttribute("nip05");if(r){this.recipientNip05=r,this.lookupRecipientByNip05();return}const e=this.getAttribute("npub");e&&(this.recipientNpub=e,this.lookupRecipient())});this.attachShadow({mode:"open"})}async getCurrentUserInfo(){var t,r,e,o,s,l,p,i,d,b;try{const k=this.nostrService.getNDK();let u=null;if(typeof window<"u"&&window.nostr){const n=window.nostr;console.log("Nostr extension found, checking for public key...");try{const g=!!(n.enable&&typeof n.enable=="function"&&n.getPublicKey&&typeof n.getPublicKey=="function");if(console.log("Is this nos2x extension?",g),g){console.log("Using nos2x specific flow");try{await n.enable(),console.log("nos2x extension enabled"),await new Promise(m=>setTimeout(m,100));const c=await n.getPublicKey();console.log("nos2x returned pubkey:",c),c&&typeof c=="string"&&c.length===64&&(u=c,console.log("Successfully got pubkey from nos2x:",u))}catch(c){console.error("Error with nos2x extension:",c)}}else{if(typeof n.enable=="function"){console.log("Attempting to enable generic extension...");try{await n.enable(),console.log("Extension enabled successfully")}catch(c){console.warn("Extension enable failed, continuing anyway:",c)}}if(typeof n.getPublicKey=="function"){console.log("Calling getPublicKey()...");try{u=await n.getPublicKey(),console.log("Got pubkey from extension:",u)}catch(c){console.error("Error getting public key:",c)}}else if(n.getPublicKey){console.log("Found getPublicKey property, resolving...");try{u=await Promise.resolve(n.getPublicKey),console.log("Got pubkey from extension (property):",u)}catch(c){console.error("Error resolving public key:",c)}}}}catch(g){console.error("Error in extension interaction:",g)}}if(!u){let n=null;if(this.keySupplier)try{n=await this.keySupplier()}catch{}if(n)try{const{NDKPrivateKeySigner:g}=await L(async()=>{const{NDKPrivateKeySigner:E}=await import("../assets/nostr-service-m3Hgc5Xx.js").then(T=>T.k);return{NDKPrivateKeySigner:E}},[]);let c=n;n.startsWith("nsec")&&(c=v.decode(n).data),u=(await new g(c).user()).pubkey}catch{}}if(u){this.currentUserPubkey=u,this.currentUserNpub=v.npubEncode(u),console.log("Got pubkey from extension and will use it:",u);try{const n=k.getUser({pubkey:u});console.log("Fetching profile for user:",u),await n.fetchProfile(),console.log("Fetched profile:",n.profile),this.currentUserName=((t=n.profile)==null?void 0:t.displayName)||((r=n.profile)==null?void 0:r.name)||((e=this.currentUserNpub)==null?void 0:e.substring(0,10))||null,this.currentUserPicture=((o=n.profile)==null?void 0:o.image)||null,this.currentUserName||console.warn("No username found in profile"),this.currentUserPicture||console.warn("No profile picture found"),console.log("Profile info set:",{name:this.currentUserName,picture:this.currentUserPicture,npub:this.currentUserNpub})}catch(n){console.error("Error fetching profile:",n),this.currentUserName=((s=this.currentUserNpub)==null?void 0:s.substring(0,10))||null}this.render()}else{console.log("Checking for direct nos2x logs in console...");try{if(await new Promise(n=>setTimeout(n,500)),typeof window<"u"&&window.nostr){console.log("Trying direct call to extension again...");try{const n=await window.nostr.getPublicKey();if(n&&typeof n=="string"){console.log("Got pubkey on second try:",n),this.currentUserPubkey=n,this.currentUserNpub=v.npubEncode(n);try{const g=k.getUser({pubkey:n});console.log("Fetching profile for user on second try:",n),await g.fetchProfile(),console.log("Fetched profile on second try:",g.profile),this.currentUserName=((l=g.profile)==null?void 0:l.displayName)||((p=g.profile)==null?void 0:p.name)||((i=this.currentUserNpub)==null?void 0:i.substring(0,10))||null,this.currentUserPicture=((d=g.profile)==null?void 0:d.image)||null,this.render();return}catch(g){console.error("Error fetching profile on second try:",g),this.currentUserName=((b=this.currentUserNpub)==null?void 0:b.substring(0,10))||null,this.render();return}}}catch(n){console.error("Error getting pubkey on direct second try:",n)}}}catch(n){console.error("Error in fallback pubkey detection:",n)}console.warn("No pubkey available from extension - trying fallback method")}}catch{}}getDisplayType(){const t=this.getAttribute("display-type"),r=["fab","bottom-bar","full","embed"],o=(t?String(t):"").toLowerCase(),s=r.includes(o)?o:"embed";this.displayType=s,this.displayType==="full"?this.isOpen=!0:this.displayType==="fab"||this.displayType==="bottom-bar"?(this.isOpen===void 0||this.isOpen===null)&&(this.isOpen=!1):this.isOpen=!1,this.getAttribute("display-type")!==s&&this.setAttribute("display-type",s)}connectedCallback(){if(!this.rendered){this.getTheme(),this.getDisplayType();const t=this.getAttribute("welcome-text");t&&(this.welcomeText=t);const r=this.getAttribute("start-chat-text");r&&(this.startChatText=r);const e=this.getAttribute("online-text");e&&(this.onlineText=e);const o=this.getAttribute("help-text");o&&(this.helpText=o),this.getRecipient(),this.nostrService.connectToNostr(this.getRelays()),this.getCurrentUserInfo(),this.render(),this.rendered=!0}}static get observedAttributes(){return["npub","pubkey","nip05","relays","theme","display-type","welcome-text","start-chat-text","online-text","help-text","history-days"]}unsubscribeFromDms(){if(this.dmSubscription){try{this.dmSubscription.stop()}catch{}this.dmSubscription=null}this.resubscribeTimer&&(clearTimeout(this.resubscribeTimer),this.resubscribeTimer=null)}clearRecipientAndChatState(){this.recipientPubkey=null,this.recipientNpub=null,this.recipientNip05=null,this.recipientName=null,this.recipientPicture=null,this.messages=[],this.message="",this.showWelcome=!1,this.isLoading=!1,this.isFinding=!1,this.isError=!1,this.errorMessage=""}attributeChangedCallback(t,r,e){if(this.rendered)if(t==="npub"){if(e===null){this.unsubscribeFromDms(),this.clearRecipientAndChatState(),this.render();return}e!==r&&(this.unsubscribeFromDms(),this.clearRecipientAndChatState(),this.recipientNpub=e,this.lookupRecipient());return}else if(t==="pubkey"){if(e===null){this.unsubscribeFromDms(),this.clearRecipientAndChatState(),this.render();return}if(e!==r){this.unsubscribeFromDms(),this.clearRecipientAndChatState();try{this.recipientPubkey=e,this.recipientNpub=v.npubEncode(e),this.lookupRecipient(this.recipientNpub)}catch{}}return}else if(t==="nip05"){if(e===null){this.unsubscribeFromDms(),this.clearRecipientAndChatState(),this.render();return}e!==r&&(this.unsubscribeFromDms(),this.clearRecipientAndChatState(),this.recipientNip05=e,this.lookupRecipientByNip05());return}else if(t==="relays"){if(e!==r){const o=this.getRelays();this.recipientPubkey&&!this.showWelcome?(this.resubscribeTimer&&clearTimeout(this.resubscribeTimer),this.resubscribeTimer=window.setTimeout(()=>{this.unsubscribeFromDms(),this.nostrService.connectToNostr(o),this.subscribeToDms()},300)):this.nostrService.connectToNostr(o)}}else t==="theme"?(this.getTheme(),this.render()):t==="display-type"?(this.getDisplayType(),this.render()):t==="welcome-text"?(this.welcomeText=e!==null?e:x.DEFAULT_WELCOME_TEXT,this.render()):t==="start-chat-text"?(this.startChatText=e!==null?e:x.DEFAULT_START_CHAT_TEXT,this.render()):t==="online-text"?(this.onlineText=e!==null?e:x.DEFAULT_ONLINE_TEXT,this.render()):t==="help-text"?(this.helpText=e!==null?e:x.DEFAULT_HELP_TEXT,this.render()):t==="history-days"&&e!==r&&this.recipientPubkey&&!this.showWelcome&&(this.resubscribeTimer&&clearTimeout(this.resubscribeTimer),this.resubscribeTimer=window.setTimeout(()=>{this.subscribeToDms()},250))}async lookupRecipient(t){var r,e,o;this.unsubscribeFromDms(),this.messages=[],this.showWelcome=!1,this.isFinding=!0,this.render();try{const s=t||this.recipientNpub;if(!s)return;const{type:l,data:p}=v.decode(s);if(l!=="npub")throw new Error("Invalid npub");this.recipientPubkey=p;const i=this.nostrService.getNDK().getUser({pubkey:this.recipientPubkey});await i.fetchProfile(),this.recipientName=((r=i.profile)==null?void 0:r.displayName)||((e=i.profile)==null?void 0:e.name)||s.substring(0,10),this.recipientPicture=((o=i.profile)==null?void 0:o.image)||null,this.showWelcome=!0,this.messages=[],this.isError=!1,this.errorMessage="",this.render()}catch(s){this.isError=!0,this.errorMessage=s.message}finally{this.isFinding=!1,this.render()}}async lookupRecipientByNip05(t){this.isFinding=!0,this.render();try{const r=t||this.recipientNip05;if(!r)return;const e=await U(r),o=v.npubEncode(e);this.recipientNpub=o,this.isError=!1,this.errorMessage="",await this.lookupRecipient(o)}catch(r){this.isError=!0,this.errorMessage=r.message}finally{this.isFinding=!1,this.render()}}handleFindClick(){const r=this.shadowRoot.querySelector(".nostr-chat-npub-input").value.trim();this.isError=!1,this.errorMessage="",this.render(),r&&(r.startsWith("npub")?(this.recipientNpub=r,this.lookupRecipient()):r.includes("@")?(this.recipientNip05=r,this.lookupRecipientByNip05()):(this.isError=!0,this.errorMessage="Invalid input. Please provide an npub or nip05 address.",this.render()))}async handleSendClick(){var r,e;if(!this.message.trim()||!this.recipientPubkey)return;if(this.message.length>this.MESSAGE_MAX_LENGTH){this.isError=!0,this.errorMessage=`Message is too long (max ${this.MESSAGE_MAX_LENGTH} characters).`,this.render();return}this.isLoading=!0,this.render();let t=null;try{const o=this.nostrService.getNDK();let s;if(typeof window<"u"&&window.nostr&&window.nostr.getPublicKey&&window.nostr.signEvent)try{s=new $}catch(d){console.error("Error creating NIP-07 signer:",d),this.isError=!0,this.errorMessage=`Error connecting to Nostr extension: ${d.message}`,this.isLoading=!1,this.render();return}if(!s)throw new Error("No signer available. Please install a NIP-07 extension or set a private key.");o.signer=s;const l=new M(o,{kind:S.EncryptedDirectMessage,tags:[["p",this.recipientPubkey]],created_at:Math.floor(Date.now()/1e3)});let p=!1;if(typeof((e=(r=window.nostr)==null?void 0:r.nip04)==null?void 0:e.encrypt)=="function")try{l.content=await window.nostr.nip04.encrypt(this.recipientPubkey,this.message.trim()),p=!0}catch(d){console.error("NIP-07 encryption failed, falling back to local encryption:",d)}if(!p)throw new Error("No private key available for encryption. Please use a NIP-07 extension.");t=`temp_${Date.now()}`,this.messages.push({id:t,text:this.message,sender:"me",timestamp:l.created_at,status:"sending"}),this.message="",this.render(),await l.publish();const i=this.messages.find(d=>d.id===t);i&&(this.messages.find(b=>b.id===l.id&&b.id!==t)?this.messages=this.messages.filter(b=>b.id!==t):(i.id=l.id,i.status="sent"),this.render())}catch(o){if(this.isError=!0,this.errorMessage=o.message,t){const s=this.messages.find(l=>l.id===t);s&&(s.status="failed"),this.render()}}finally{this.isLoading=!1,this.render()}}handleTextareaChange(t){var s;const r=t.target;this.message=r.value;const e=Math.max(0,this.MESSAGE_MAX_LENGTH-this.message.length),o=(s=this.shadowRoot)==null?void 0:s.querySelector(".nostr-chat-char-counter");o&&(o.textContent=`${e} chars left`,o.classList.toggle("warn",e<=10))}handleStartChat(){this.showWelcome=!1,this.subscribeToDms(),this.render()}async subscribeToDms(){if(this.dmSubscription&&this.dmSubscription.stop(),!this.recipientPubkey)return;let t=null;try{if(typeof window<"u"&&window.nostr&&window.nostr.getPublicKey)t={pubkey:await window.nostr.getPublicKey()};else{let i=null;if(this.keySupplier)try{i=await this.keySupplier()}catch{}if(i){const{NDKPrivateKeySigner:d}=await L(async()=>{const{NDKPrivateKeySigner:u}=await import("../assets/nostr-service-m3Hgc5Xx.js").then(n=>n.k);return{NDKPrivateKeySigner:u}},[]);let b=i;i.startsWith("nsec")&&(b=v.decode(i).data),t=await new d(b).user()}}}catch(i){console.error("Failed to determine current user for subscription",i)}if(!t){this.isError=!0,this.errorMessage="No signer available. Please install a NIP-07 extension or set a private key to start the chat.",this.render();return}this.messages=[];const r=this.getAttribute("history-days");let e;if(!r)e=void 0;else if(r.toLowerCase()==="all"||parseInt(r,10)<=0)e=void 0;else{const i=Math.max(1,parseInt(r,10)||30);e=Math.floor((Date.now()-i*24*60*60*1e3)/1e3)}const o={kinds:[S.EncryptedDirectMessage],"#p":[t.pubkey],authors:[this.recipientPubkey]},s={kinds:[S.EncryptedDirectMessage],"#p":[this.recipientPubkey],authors:[t.pubkey]},l=e!==void 0?{...o,since:e}:o,p=e!==void 0?{...s,since:e}:s;this.dmSubscription=this.nostrService.getNDK().subscribe([l,p],{closeOnEose:!1,groupable:!1}),this.dmSubscription.on("event",async i=>{var d;try{!this.currentUserPubkey&&t&&(this.currentUserPubkey=t.pubkey,this.currentUserNpub=v.npubEncode(t.pubkey));const b=i.pubkey===t.pubkey,k=b?(d=i.tags.find(c=>c[0]==="p"))==null?void 0:d[1]:i.pubkey;if(!k){try{console.debug("nostr-live-chat: skipping event with missing peer",i.id)}catch{}return}if(k!==this.recipientPubkey)return;if(b){const c=this.messages.find(m=>m.id===i.id);if(c){c.status==="sending"&&(c.status="sent",this.render());return}}let u="";if(!k){try{console.debug("nostr-live-chat: missing peer prior to decrypt, skipping",i.id)}catch{}return}if(!i.content||i.content.trim()===""){try{console.debug("nostr-live-chat: missing or empty content prior to decrypt, skipping",i.id)}catch{}return}if(window.nostr&&window.nostr.nip04&&typeof window.nostr.nip04.decrypt=="function")try{u=await window.nostr.nip04.decrypt(k,i.content)}catch(c){console.error("Failed to decrypt DM content:",c);return}else throw new Error("No private key available for decryption. Please use a NIP-07 extension.");if(b){const c=this.messages.find(m=>m.status==="sending"&&m.sender==="me"&&m.text===u&&Math.abs(m.timestamp-i.created_at)<2);if(c){c.id=i.id,c.status="sent",this.render();return}}const n={id:i.id,text:u,sender:b?"me":"them",timestamp:i.created_at,status:"sent"};this.messages.find(c=>c.id===n.id)||(this.messages.push(n),this.messages.sort((c,m)=>c.timestamp-m.timestamp),this.render())}catch(b){console.error("Failed to decrypt DM content:",b)}})}attachEventListeners(){const t=this.shadowRoot.querySelector(".nostr-chat-launcher");t&&(this.boundHandleLauncherClick&&t.removeEventListener("click",this.boundHandleLauncherClick),this.boundHandleLauncherClick=()=>{this.isOpen=!0,this.render()},t.addEventListener("click",this.boundHandleLauncherClick));const r=this.shadowRoot.querySelector(".nostr-chat-close-btn");r&&(this.boundHandleCloseClick&&r.removeEventListener("click",this.boundHandleCloseClick),this.boundHandleCloseClick=i=>{i==null||i.stopPropagation(),(this.displayType==="fab"||this.displayType==="bottom-bar")&&(this.isOpen=!1),this.render()},r.addEventListener("click",this.boundHandleCloseClick));const e=this.shadowRoot.querySelector(".nostr-chat-find-btn");e&&(this.boundHandleFind&&e.removeEventListener("click",this.boundHandleFind),this.boundHandleFind=this.handleFindClick.bind(this),e.addEventListener("click",this.boundHandleFind));const o=this.shadowRoot.querySelector(".nostr-chat-send-btn");o&&(this.boundHandleSend&&o.removeEventListener("click",this.boundHandleSend),this.boundHandleSend=this.handleSendClick.bind(this),o.addEventListener("click",this.boundHandleSend));const s=this.shadowRoot.querySelector(".nostr-chat-start-btn");s&&(this.boundHandleStartChat&&s.removeEventListener("click",this.boundHandleStartChat),this.boundHandleStartChat=this.handleStartChat.bind(this),s.addEventListener("click",this.boundHandleStartChat));const l=this.shadowRoot.querySelector(".nostr-chat-textarea");l&&(this.boundHandleTextareaChange&&l.removeEventListener("input",this.boundHandleTextareaChange),this.boundHandleTextareaChange=this.handleTextareaChange.bind(this),l.addEventListener("input",this.boundHandleTextareaChange));const p=this.shadowRoot.querySelector(".nostr-chat-npub-input");p&&(this.boundHandleNpubKeydown&&p.removeEventListener("keydown",this.boundHandleNpubKeydown),this.boundHandleNpubKeydown=i=>{i.key==="Enter"&&this.handleFindClick()},p.addEventListener("keydown",this.boundHandleNpubKeydown))}disconnectedCallback(){var i,d,b,k,u,n,g;this.dmSubscription&&this.dmSubscription.stop();const t=(i=this.shadowRoot)==null?void 0:i.querySelector(".nostr-chat-launcher");t&&this.boundHandleLauncherClick&&t.removeEventListener("click",this.boundHandleLauncherClick);const r=(d=this.shadowRoot)==null?void 0:d.querySelector(".nostr-chat-close-btn");r&&this.boundHandleCloseClick&&r.removeEventListener("click",this.boundHandleCloseClick);const e=(b=this.shadowRoot)==null?void 0:b.querySelector(".nostr-chat-find-btn");e&&this.boundHandleFind&&e.removeEventListener("click",this.boundHandleFind);const o=(k=this.shadowRoot)==null?void 0:k.querySelector(".nostr-chat-send-btn");o&&this.boundHandleSend&&o.removeEventListener("click",this.boundHandleSend);const s=(u=this.shadowRoot)==null?void 0:u.querySelector(".nostr-chat-start-btn");s&&this.boundHandleStartChat&&s.removeEventListener("click",this.boundHandleStartChat);const l=(n=this.shadowRoot)==null?void 0:n.querySelector(".nostr-chat-textarea");l&&this.boundHandleTextareaChange&&l.removeEventListener("input",this.boundHandleTextareaChange);const p=(g=this.shadowRoot)==null?void 0:g.querySelector(".nostr-chat-npub-input");p&&this.boundHandleNpubKeydown&&p.removeEventListener("keydown",this.boundHandleNpubKeydown),this.resubscribeTimer&&(clearTimeout(this.resubscribeTimer),this.resubscribeTimer=null)}setKeySupplier(t){this.keySupplier=t}escapeHtml(t){return t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}render(){const t={theme:this.theme,recipientNpub:this.recipientNpub,recipientName:this.recipientName,recipientPicture:this.recipientPicture,message:this.message,messages:this.messages,isLoading:this.isLoading,isFinding:this.isFinding,isError:this.isError,errorMessage:this.errorMessage,currentUserName:this.currentUserName,currentUserPicture:this.currentUserPicture,showWelcome:this.showWelcome,welcomeText:this.welcomeText,startChatText:this.startChatText,onlineText:this.onlineText,helpText:this.helpText,maxMessageLength:this.MESSAGE_MAX_LENGTH},r=z(this.theme),{onlineText:e,helpText:o,...s}=t,l=O(s);let p=r;this.displayType==="embed"?p+=l:this.displayType==="full"?p+=`
|
|
499
499
|
<div class="nostr-chat-float-panel open">${l}</div>
|
|
500
500
|
`:this.displayType==="fab"?p+=`
|
|
501
501
|
${this.isOpen?"":`
|
|
@@ -519,5 +519,5 @@ var P=Object.defineProperty;var H=(h,f,t)=>f in h?P(h,f,{enumerable:!0,configura
|
|
|
519
519
|
<div class="nostr-chat-float-panel ${this.isOpen?"open":""}">
|
|
520
520
|
${l}
|
|
521
521
|
</div>
|
|
522
|
-
`),this.shadowRoot.innerHTML=p,this.attachEventListeners(),setTimeout(()=>{var d;const i=(d=this.shadowRoot)==null?void 0:d.querySelector(".nostr-chat-history");i&&(i.scrollTop=i.scrollHeight)},0)}};a(x,"DEFAULT_WELCOME_TEXT","Welcome! How can we help you today?"),a(x,"DEFAULT_START_CHAT_TEXT","Start chat"),a(x,"DEFAULT_ONLINE_TEXT","We're Online!"),a(x,"DEFAULT_HELP_TEXT","How may I help you today?");let F=x;customElements.define("nostr-live-chat",F);
|
|
522
|
+
`),this.shadowRoot.innerHTML=p,this.attachEventListeners(),setTimeout(()=>{var d;const i=(d=this.shadowRoot)==null?void 0:d.querySelector(".nostr-chat-history");i&&(i.scrollTop=i.scrollHeight)},0)}};a(x,"DEFAULT_WELCOME_TEXT","Welcome! How can we help you today?"),a(x,"DEFAULT_START_CHAT_TEXT","Start chat"),a(x,"DEFAULT_ONLINE_TEXT","We're Online!"),a(x,"DEFAULT_HELP_TEXT","How may I help you today?");let F=x;customElements.define("nostr-live-chat",F);
|
|
523
523
|
//# sourceMappingURL=nostr-live-chat.es.js.map
|