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.
Files changed (140) hide show
  1. package/README.md +105 -185
  2. package/dist/assets/{base-styles-BSEzBDsk.js → base-styles-DC0ilu4S.js} +3 -3
  3. package/dist/assets/{base-styles-BSEzBDsk.js.map → base-styles-DC0ilu4S.js.map} +1 -1
  4. package/dist/assets/{copy-delegation-B7y2q5Kn.js → copy-delegation-CcagQMIW.js} +5 -5
  5. package/dist/assets/{copy-delegation-B7y2q5Kn.js.map → copy-delegation-CcagQMIW.js.map} +1 -1
  6. package/dist/assets/{dialog-component-Da1ZIYh9.js → dialog-component-Dqg0QU9I.js} +2 -7
  7. package/dist/assets/dialog-component-Dqg0QU9I.js.map +1 -0
  8. package/dist/assets/{dialog-likers-BqDn2P_3.js → dialog-likers-D3c7WIMp.js} +5 -5
  9. package/dist/assets/dialog-likers-D3c7WIMp.js.map +1 -0
  10. package/dist/assets/index.esm-ByUtE_cm.js +2159 -0
  11. package/dist/assets/index.esm-ByUtE_cm.js.map +1 -0
  12. package/dist/assets/nip05-utils-BNBHUmkr.js.map +1 -1
  13. package/dist/assets/nostr-login-service-D2FmscPI.js +2 -0
  14. package/dist/assets/nostr-login-service-D2FmscPI.js.map +1 -0
  15. package/dist/assets/nostr-service-m3Hgc5Xx.js +266 -0
  16. package/dist/assets/nostr-service-m3Hgc5Xx.js.map +1 -0
  17. package/dist/assets/nostr-user-component-XEnanH-d.js +2 -0
  18. package/dist/assets/nostr-user-component-XEnanH-d.js.map +1 -0
  19. package/dist/assets/{pure-DPo-pzxM.js → pure-laCRX9eG.js} +2 -2
  20. package/dist/assets/pure-laCRX9eG.js.map +1 -0
  21. package/dist/assets/{theme-BN1Bvweb.js → theme-C1r1Zw8r.js} +2 -2
  22. package/dist/assets/{theme-BN1Bvweb.js.map → theme-C1r1Zw8r.js.map} +1 -1
  23. package/dist/assets/{user-resolver-CMmbtY9Y.js → user-resolver-DqI5KGh6.js} +2 -2
  24. package/dist/assets/{user-resolver-CMmbtY9Y.js.map → user-resolver-DqI5KGh6.js.map} +1 -1
  25. package/dist/assets/utils--bxLbhGF.js.map +1 -1
  26. package/dist/assets/zap-utils-BZcaCsT_.js +2 -0
  27. package/dist/assets/zap-utils-BZcaCsT_.js.map +1 -0
  28. package/dist/components/nostr-comment.es.js +26 -26
  29. package/dist/components/nostr-comment.es.js.map +1 -1
  30. package/dist/components/nostr-dm.es.js +2 -2
  31. package/dist/components/nostr-dm.es.js.map +1 -1
  32. package/dist/components/nostr-follow-button.es.js +6 -7
  33. package/dist/components/nostr-follow-button.es.js.map +1 -1
  34. package/dist/components/nostr-like.es.js +16 -16
  35. package/dist/components/nostr-like.es.js.map +1 -1
  36. package/dist/components/nostr-live-chat.es.js +3 -3
  37. package/dist/components/nostr-live-chat.es.js.map +1 -1
  38. package/dist/components/nostr-post.es.js +19 -19
  39. package/dist/components/nostr-post.es.js.map +1 -1
  40. package/dist/components/nostr-profile-badge.es.js +3 -3
  41. package/dist/components/nostr-profile-badge.es.js.map +1 -1
  42. package/dist/components/nostr-profile.es.js +2 -2
  43. package/dist/components/nostr-profile.es.js.map +1 -1
  44. package/dist/components/nostr-zap.es.js +24 -24
  45. package/dist/components/nostr-zap.es.js.map +1 -1
  46. package/dist/nostr-components.es.js +1 -1
  47. package/dist/nostr-components.es.js.map +1 -1
  48. package/dist/nostr-components.umd.js +2644 -305
  49. package/dist/nostr-components.umd.js.map +1 -1
  50. package/package.json +5 -2
  51. package/dist/assets/dark-nostrich-running.gif +0 -0
  52. package/dist/assets/default_dp-NQ3TGrtT.png +0 -0
  53. package/dist/assets/default_dp.png +0 -0
  54. package/dist/assets/default_dp_32.png +0 -0
  55. package/dist/assets/dialog-component-Da1ZIYh9.js.map +0 -1
  56. package/dist/assets/dialog-likers-BqDn2P_3.js.map +0 -1
  57. package/dist/assets/light-nostrich-running.gif +0 -0
  58. package/dist/assets/nostr-service-CnaPxjc6.js +0 -78
  59. package/dist/assets/nostr-service-CnaPxjc6.js.map +0 -1
  60. package/dist/assets/nostr-user-component-Cbs97dlK.js +0 -2
  61. package/dist/assets/nostr-user-component-Cbs97dlK.js.map +0 -1
  62. package/dist/assets/pure-DPo-pzxM.js.map +0 -1
  63. package/dist/assets/zap-utils-KFUD_vTU.js +0 -2
  64. package/dist/assets/zap-utils-KFUD_vTU.js.map +0 -1
  65. package/dist/index.d.ts +0 -6
  66. package/dist/nostr-comment.d.ts +0 -4
  67. package/dist/nostr-dm.d.ts +0 -4
  68. package/dist/nostr-follow-button.d.ts +0 -4
  69. package/dist/nostr-like.d.ts +0 -4
  70. package/dist/nostr-live-chat.d.ts +0 -4
  71. package/dist/nostr-post.d.ts +0 -4
  72. package/dist/nostr-profile-badge.d.ts +0 -4
  73. package/dist/nostr-profile.d.ts +0 -4
  74. package/dist/nostr-zap.d.ts +0 -4
  75. package/dist/src/base/base-component/nostr-base-component.d.ts +0 -116
  76. package/dist/src/base/copy-delegation.d.ts +0 -5
  77. package/dist/src/base/dialog-component/dialog-component.d.ts +0 -67
  78. package/dist/src/base/dialog-component/style.d.ts +0 -5
  79. package/dist/src/base/event-component/nostr-event-component.d.ts +0 -53
  80. package/dist/src/base/render-options.d.ts +0 -5
  81. package/dist/src/base/resolvers/event-resolver.d.ts +0 -20
  82. package/dist/src/base/resolvers/user-resolver.d.ts +0 -19
  83. package/dist/src/base/text-row/render-name.d.ts +0 -7
  84. package/dist/src/base/text-row/render-nip05.d.ts +0 -1
  85. package/dist/src/base/text-row/render-npub.d.ts +0 -1
  86. package/dist/src/base/text-row/render-text-row.d.ts +0 -9
  87. package/dist/src/base/user-component/nostr-user-component.d.ts +0 -43
  88. package/dist/src/common/base-styles.d.ts +0 -44
  89. package/dist/src/common/constants.d.ts +0 -4
  90. package/dist/src/common/date-utils.d.ts +0 -9
  91. package/dist/src/common/icons.d.ts +0 -7
  92. package/dist/src/common/nip05-utils.d.ts +0 -13
  93. package/dist/src/common/nostr-service.d.ts +0 -40
  94. package/dist/src/common/theme.d.ts +0 -4
  95. package/dist/src/common/types.d.ts +0 -1
  96. package/dist/src/common/utils.d.ts +0 -34
  97. package/dist/src/index.d.ts +0 -32
  98. package/dist/src/nostr-comment/nostr-comment.d.ts +0 -60
  99. package/dist/src/nostr-comment/render.d.ts +0 -15
  100. package/dist/src/nostr-comment/utils.d.ts +0 -81
  101. package/dist/src/nostr-dm/nostr-dm.d.ts +0 -34
  102. package/dist/src/nostr-dm/render.d.ts +0 -15
  103. package/dist/src/nostr-follow-button/nostr-follow-button.d.ts +0 -24
  104. package/dist/src/nostr-follow-button/render.d.ts +0 -11
  105. package/dist/src/nostr-follow-button/style.d.ts +0 -1
  106. package/dist/src/nostr-like/dialog-help-style.d.ts +0 -1
  107. package/dist/src/nostr-like/dialog-help.d.ts +0 -2
  108. package/dist/src/nostr-like/dialog-likers-style.d.ts +0 -1
  109. package/dist/src/nostr-like/dialog-likers.d.ts +0 -24
  110. package/dist/src/nostr-like/like-utils.d.ts +0 -52
  111. package/dist/src/nostr-like/nostr-like.d.ts +0 -49
  112. package/dist/src/nostr-like/render.d.ts +0 -10
  113. package/dist/src/nostr-like/style.d.ts +0 -1
  114. package/dist/src/nostr-live-chat/nostr-live-chat.d.ts +0 -65
  115. package/dist/src/nostr-live-chat/render.d.ts +0 -31
  116. package/dist/src/nostr-post/nostr-post.d.ts +0 -25
  117. package/dist/src/nostr-post/parse-text.d.ts +0 -8
  118. package/dist/src/nostr-post/render-content.d.ts +0 -5
  119. package/dist/src/nostr-post/render.d.ts +0 -19
  120. package/dist/src/nostr-post/style.d.ts +0 -1
  121. package/dist/src/nostr-profile/nostr-profile.d.ts +0 -24
  122. package/dist/src/nostr-profile/render-stats.d.ts +0 -1
  123. package/dist/src/nostr-profile/render.d.ts +0 -22
  124. package/dist/src/nostr-profile/style.d.ts +0 -1
  125. package/dist/src/nostr-profile-badge/nostr-profile-badge.d.ts +0 -34
  126. package/dist/src/nostr-profile-badge/render.d.ts +0 -11
  127. package/dist/src/nostr-profile-badge/style.d.ts +0 -1
  128. package/dist/src/nostr-zap/dialog-help-style.d.ts +0 -5
  129. package/dist/src/nostr-zap/dialog-help.d.ts +0 -2
  130. package/dist/src/nostr-zap/dialog-zap-style.d.ts +0 -6
  131. package/dist/src/nostr-zap/dialog-zap.d.ts +0 -31
  132. package/dist/src/nostr-zap/dialog-zappers-style.d.ts +0 -1
  133. package/dist/src/nostr-zap/dialog-zappers.d.ts +0 -25
  134. package/dist/src/nostr-zap/nostr-zap.d.ts +0 -45
  135. package/dist/src/nostr-zap/render.d.ts +0 -9
  136. package/dist/src/nostr-zap/style.d.ts +0 -1
  137. package/dist/src/nostr-zap/zap-utils.d.ts +0 -53
  138. package/dist/vite.config.d.ts +0 -2
  139. package/dist/vite.config.esm.d.ts +0 -2
  140. package/dist/vite.config.umd.d.ts +0 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nostr-components",
3
- "version": "0.2.7",
3
+ "version": "0.3.0",
4
4
  "type": "module",
5
5
  "description": "Embed Nostr anywhere on the internet, a Zap Button for every webpage",
6
6
  "keywords": [
@@ -99,7 +99,9 @@
99
99
  "storybook": "storybook dev -p 6006",
100
100
  "build-storybook": "cross-env STORYBOOK_ENV=production storybook build && npm run build:themes",
101
101
  "wp-build": "npm run build:esm && npm run build:themes && npm run wp-copy",
102
- "wp-copy": "node scripts/wp-copy.js"
102
+ "wp-copy": "node scripts/wp-copy.js",
103
+ "wp-prepare-svn": "node scripts/prepare-svn.js",
104
+ "wp-release": "npm run wp-build && npm run wp-prepare-svn"
103
105
  },
104
106
  "devDependencies": {
105
107
  "@chromatic-com/storybook": "^4.1.1",
@@ -126,6 +128,7 @@
126
128
  "@types/qrcode": "^1.5.5",
127
129
  "dompurify": "^3.2.6",
128
130
  "light-bolt11-decoder": "^3.2.0",
131
+ "nostr-login": "^1.7.12",
129
132
  "nostr-tools": "^2.7.2",
130
133
  "qrcode": "^1.5.4"
131
134
  }
Binary file
Binary file
Binary file
@@ -1 +0,0 @@
1
- {"version":3,"file":"dialog-component-Da1ZIYh9.js","sources":["../../src/base/dialog-component/style.ts","../../src/base/dialog-component/dialog-component.ts"],"sourcesContent":["// SPDX-License-Identifier: MIT\n\n/**\n * Base dialog component styles\n * Provides common styling for all dialog components\n */\nexport const getDialogComponentStyles = (): string => {\n return `\n /* Base Dialog Styles */\n .nostr-base-dialog {\n width: 400px;\n max-width: 90vw;\n border: none;\n border-radius: var(--nostrc-border-radius-lg, 10px);\n padding: var(--nostrc-spacing-xl, 20px);\n background: var(--nostrc-theme-bg, #ffffff);\n color: var(--nostrc-theme-text-primary, #000000);\n margin: auto;\n font-family: var(--nostrc-font-family-primary, ui-sans-serif, system-ui, sans-serif);\n /* Ensure dialog is centered when opened */\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n }\n\n .nostr-base-dialog[open] {\n display: block;\n }\n\n .nostr-base-dialog::backdrop {\n background: rgba(0, 0, 0, 0.5);\n }\n\n .dialog-header {\n position: relative;\n margin-bottom: var(--nostrc-spacing-lg, 16px);\n display: flex;\n align-items: center;\n justify-content: space-between;\n }\n\n .dialog-header h2 {\n font-size: var(--nostrc-font-size-large, 1.25rem);\n font-weight: var(--nostrc-font-weight-bold, 700);\n margin: 0;\n flex: 1;\n text-align: left;\n padding-top: 2px;\n color: var(--nostrc-theme-text-primary, #000000);\n }\n\n .dialog-close-btn {\n border: none;\n background: var(--nostrc-theme-hover-bg, #f7fafc);\n border-radius: var(--nostrc-border-radius-full, 50%);\n width: 32px;\n height: 32px;\n min-width: 32px;\n font-size: var(--nostrc-font-size-base, 16px);\n cursor: pointer;\n color: var(--nostrc-theme-text-secondary, #666666);\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .dialog-close-btn:hover {\n background: var(--nostrc-theme-border, rgba(0, 0, 0, 0.05));\n color: var(--nostrc-theme-text-primary, #000000);\n }\n\n .dialog-content {\n line-height: 1.6;\n color: var(--nostrc-theme-text-primary, #000000);\n }\n `;\n};\n\n","// SPDX-License-Identifier: MIT\n\nimport { getDialogComponentStyles } from './style';\n\n/**\n * Base dialog component that extends HTMLElement\n * Provides common dialog functionality with header, close button, and content area\n * \n * Usage:\n * ```typescript\n * const dialog = document.createElement('dialog-component');\n * dialog.setAttribute('header', 'Dialog Title');\n * dialog.innerHTML = '<p>Your content goes here</p>';\n * dialog.showModal(); // Don't append to body, just call showModal()\n * ```\n * \n * Features:\n * - Header with customizable text\n * - Close button\n * - Click outside to close\n * - ESC key to close\n * - Automatic cleanup on close\n * \n * Important: Only one instance of this component should be added to the DOM at any time.\n * Multiple instances may cause conflicts with event listeners and cleanup behavior.\n */\nexport class DialogComponent extends HTMLElement {\n private dialog: HTMLDialogElement | null = null;\n\n constructor() {\n super();\n }\n\n /**\n * Observed attributes for the component\n */\n static get observedAttributes() {\n return ['header', 'data-theme'];\n }\n\n /**\n * Inject dialog styles into document head\n * Prevents duplicate injection by checking for existing styles\n */\n private injectStyles(): void {\n if (document.querySelector('style[data-dialog-component-styles]')) return;\n \n const style = document.createElement('style');\n style.setAttribute('data-dialog-component-styles', 'true');\n style.textContent = getDialogComponentStyles();\n document.head.appendChild(style);\n }\n\n /**\n * Render the dialog\n */\n private render(): void {\n this.injectStyles();\n\n const headerText = this.getAttribute('header') || 'Dialog';\n const theme = this.getAttribute('data-theme');\n\n this.dialog = document.createElement('dialog');\n this.dialog.className = 'nostr-base-dialog';\n if (theme) {\n this.dialog.setAttribute('data-theme', theme);\n }\n\n const headerDiv = document.createElement('div');\n headerDiv.className = 'dialog-header';\n \n const headerH2 = document.createElement('h2');\n headerH2.textContent = headerText;\n \n const closeBtn = document.createElement('button');\n closeBtn.className = 'dialog-close-btn';\n closeBtn.setAttribute('aria-label', 'Close dialog');\n closeBtn.textContent = '✕';\n \n headerDiv.appendChild(headerH2);\n headerDiv.appendChild(closeBtn);\n\n const contentDiv = document.createElement('div');\n contentDiv.className = 'dialog-content';\n \n // Safely move child nodes from component to dialog content\n // This preserves any existing DOM nodes without using innerHTML\n while (this.firstChild) {\n contentDiv.appendChild(this.firstChild);\n }\n\n this.dialog.appendChild(headerDiv);\n this.dialog.appendChild(contentDiv);\n\n document.body.appendChild(this.dialog);\n\n this.setupEventListeners();\n }\n\n /**\n * Setup event listeners for closing the dialog\n */\n private setupEventListeners(): void {\n if (!this.dialog) return;\n\n // Close button click\n const closeBtn = this.dialog.querySelector('.dialog-close-btn');\n closeBtn?.addEventListener('click', () => {\n this.close();\n });\n\n // Click outside dialog (on backdrop)\n this.dialog.addEventListener('click', (e) => {\n if (e.target === this.dialog) {\n this.close();\n }\n });\n\n // ESC key handler\n this.dialog.addEventListener('cancel', (e) => {\n e.preventDefault();\n this.close();\n });\n\n // Cleanup on close\n this.dialog.addEventListener('close', () => {\n this.cleanup();\n });\n }\n\n /**\n * Show the dialog (alias for showModal)\n */\n public show(): void {\n this.showModal();\n }\n\n /**\n * Show the dialog as modal\n */\n public showModal(): void {\n if (!this.dialog) {\n this.render();\n }\n this.dialog?.showModal();\n }\n\n /**\n * Close the dialog\n */\n public close(): void {\n this.dialog?.close();\n }\n\n /**\n * Cleanup when dialog is closed\n */\n private cleanup(): void {\n if (this.dialog && this.dialog.isConnected) {\n this.dialog.remove();\n }\n if (this.isConnected) {\n this.remove();\n }\n this.dialog = null;\n }\n\n /**\n * Called when component is removed from DOM\n */\n disconnectedCallback(): void {\n this.cleanup();\n }\n\n /**\n * Called when observed attributes change\n */\n attributeChangedCallback(name: string, _oldValue: string, newValue: string): void {\n if (name === 'header' && this.dialog) {\n const heading = this.dialog.querySelector('.dialog-header h2');\n if (heading) {\n heading.textContent = newValue || 'Dialog';\n }\n } else if (name === 'data-theme' && this.dialog) {\n if (newValue) {\n this.dialog.setAttribute('data-theme', newValue);\n } else {\n this.dialog.removeAttribute('data-theme');\n }\n }\n }\n}\n\n// Define custom element\nif (!customElements.get('dialog-component')) {\n customElements.define('dialog-component', DialogComponent);\n}\n\n"],"names":["getDialogComponentStyles","DialogComponent","__publicField","style","headerText","theme","headerDiv","headerH2","closeBtn","contentDiv","e","_a","name","_oldValue","newValue","heading"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"mappings":"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","names":["getLikersDialogStyles","theme","isDark","injectLikersDialogStyles","style","renderLikeEntry","like","index","authorNameSafe","escapeHtml","njumpUrl","hexToNpub","profilePictureSafe","isValidUrl","profilePicture","isDislike","statusText","statusClass","formatRelativeTime","renderSkeletonLikeEntry","npub","openLikersDialog","params","likeDetails","dialogComponent","initialContent","renderInitialContent","dialogElement","_a","dialog","enhanceLikeDetailsProgressively","npubs","likersList","uniqueAuthorIds","profileResults","getBatchedProfileMetadata","profileMap","result","npubMap","pubkey","profile","enhanced","profileContent","extractProfileMetadataContent","skeletonEntry","enhancedEntry","error","enhanceLikeDetailsIndividually","profileCache","profilePromises","cachedProfile","getProfileMetadata","__vitePreload","profileMetadata","promise"],"ignoreList":[],"sources":["../../src/nostr-like/dialog-likers-style.ts","../../src/nostr-like/dialog-likers.ts"],"sourcesContent":["// SPDX-License-Identifier: MIT\n\nexport function getLikersDialogStyles(theme: 'light' | 'dark' = 'light'): string {\n const isDark = theme === 'dark';\n \n return `\n .likers-dialog-content {\n padding: 0;\n max-height: 60vh;\n overflow-y: auto;\n }\n\n .likers-list {\n display: flex;\n flex-direction: column;\n gap: 12px;\n }\n\n .like-entry {\n display: flex;\n align-items: center;\n padding: 12px;\n border-radius: 8px;\n background: ${isDark ? '#2a2a2a' : '#f8f9fa'};\n border: 1px solid ${isDark ? '#3a3a3a' : '#e9ecef'};\n transition: background-color 0.2s ease;\n }\n\n .like-entry:hover {\n background: ${isDark ? '#3a3a3a' : '#e9ecef'};\n }\n\n .like-author-info {\n display: flex;\n align-items: center;\n gap: 12px;\n width: 100%;\n }\n\n .like-author-picture {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n object-fit: cover;\n flex-shrink: 0;\n }\n\n .like-author-picture-default {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n background: ${isDark ? '#3a3a3a' : '#e9ecef'};\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 18px;\n flex-shrink: 0;\n }\n\n .like-author-details {\n display: flex;\n flex-direction: column;\n gap: 4px;\n flex: 1;\n min-width: 0;\n }\n\n .like-author-link {\n color: ${isDark ? '#ffffff' : '#000000'};\n text-decoration: none;\n font-weight: 500;\n font-size: 14px;\n transition: color 0.2s ease;\n }\n\n .like-author-link:hover {\n color: ${isDark ? '#4a9eff' : '#1877f2'};\n text-decoration: underline;\n }\n\n .like-date {\n color: ${isDark ? '#b0b0b0' : '#65676b'};\n font-size: 12px;\n font-weight: 400;\n display: flex;\n align-items: center;\n gap: 8px;\n }\n\n .like-status {\n font-weight: 500;\n font-size: 11px;\n padding: 2px 6px;\n border-radius: 4px;\n }\n\n .like-status.liked {\n color: ${isDark ? '#4a9eff' : '#1877f2'};\n background: ${isDark ? 'rgba(74, 158, 255, 0.1)' : 'rgba(24, 119, 242, 0.1)'};\n }\n\n .like-status.disliked {\n color: #d32f2f;\n background: rgba(211, 47, 47, 0.1);\n }\n\n .no-likes {\n text-align: center;\n color: ${isDark ? '#b0b0b0' : '#65676b'};\n font-size: 14px;\n padding: 40px 20px;\n }\n\n /* Skeleton loading states */\n .skeleton-entry {\n opacity: 0.7;\n }\n\n .skeleton-picture {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n background: linear-gradient(90deg, \n ${isDark ? '#3a3a3a' : '#f0f0f0'} 25%, \n ${isDark ? '#4a4a4a' : '#e0e0e0'} 50%, \n ${isDark ? '#3a3a3a' : '#f0f0f0'} 75%\n );\n background-size: 200% 100%;\n animation: skeleton-loading 1.5s infinite;\n flex-shrink: 0;\n }\n\n .skeleton-name {\n width: 120px;\n height: 14px;\n background: linear-gradient(90deg, \n ${isDark ? '#3a3a3a' : '#f0f0f0'} 25%, \n ${isDark ? '#4a4a4a' : '#e0e0e0'} 50%, \n ${isDark ? '#3a3a3a' : '#f0f0f0'} 75%\n );\n background-size: 200% 100%;\n animation: skeleton-loading 1.5s infinite;\n border-radius: 2px;\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 /* Responsive */\n @media (max-width: 480px) {\n .likers-dialog-content {\n max-height: 70vh;\n }\n\n .like-entry {\n padding: 10px;\n }\n\n .like-author-picture,\n .like-author-picture-default,\n .skeleton-picture {\n width: 36px;\n height: 36px;\n }\n\n .like-author-link {\n font-size: 13px;\n }\n\n .like-date {\n font-size: 11px;\n }\n }\n\n /* Scrollbar styling */\n .likers-dialog-content::-webkit-scrollbar {\n width: 6px;\n }\n\n .likers-dialog-content::-webkit-scrollbar-track {\n background: ${isDark ? '#2a2a2a' : '#f1f1f1'};\n border-radius: 3px;\n }\n\n .likers-dialog-content::-webkit-scrollbar-thumb {\n background: ${isDark ? '#555' : '#c1c1c1'};\n border-radius: 3px;\n }\n\n .likers-dialog-content::-webkit-scrollbar-thumb:hover {\n background: ${isDark ? '#777' : '#a8a8a8'};\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 { getLikersDialogStyles } from './dialog-likers-style';\nimport { getBatchedProfileMetadata, extractProfileMetadataContent } from '../nostr-zap/zap-utils';\nimport { escapeHtml, formatRelativeTime, hexToNpub, isValidUrl } from '../common/utils';\nimport { LikeDetails } from './like-utils';\n\n/**\n * Modal dialog for displaying individual like details (likers).\n * \n * Shows a list of all users who liked a URL with:\n * - User's name\n * - User's profile picture\n * - Time of like (relative time)\n * - Clickable links to user profiles via njump.me\n */\n\nexport interface OpenLikersModalParams {\n likeDetails: LikeDetails[];\n theme?: 'light' | 'dark';\n}\n\n/**\n * Inject likers dialog content styles into document head\n * Prevents duplicate injection by checking for existing styles\n */\nexport const injectLikersDialogStyles = (theme: 'light' | 'dark' = 'light') => {\n // Remove existing likers dialog styles\n const existingStyles = document.querySelectorAll('style[data-likers-dialog-styles]');\n existingStyles.forEach(style => style.remove());\n \n const style = document.createElement('style');\n style.setAttribute('data-likers-dialog-styles', 'true');\n style.textContent = getLikersDialogStyles(theme);\n document.head.appendChild(style);\n}\n\ninterface EnhancedLikeDetails extends LikeDetails {\n authorName?: string;\n authorPicture?: string;\n authorNpub?: string;\n}\n\n/**\n * Render individual like entry HTML (with profile data)\n */\nfunction renderLikeEntry(like: EnhancedLikeDetails, index: number): string {\n const authorNameSafe = escapeHtml(like.authorName || 'Unknown liker');\n const npubSafe = like.authorNpub || hexToNpub(like.authorPubkey);\n const njumpUrl = `https://njump.me/${npubSafe}`;\n const profilePictureSafe = isValidUrl(like.authorPicture || '') ? like.authorPicture || '' : '';\n \n const profilePicture = profilePictureSafe \n ? `<img src=\"${profilePictureSafe}\" alt=\"${authorNameSafe}\" class=\"like-author-picture\" />`\n : `<div class=\"like-author-picture-default\">👤</div>`;\n \n const isDislike = like.content === '-';\n const statusText = isDislike ? 'Disliked' : 'Liked';\n const statusClass = isDislike ? 'disliked' : 'liked';\n \n return `\n <div class=\"like-entry\" data-like-index=\"${index}\" data-author-pubkey=\"${like.authorPubkey}\">\n <div class=\"like-author-info\">\n ${profilePicture}\n <div class=\"like-author-details\">\n <a href=\"${njumpUrl}\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"like-author-link\">\n ${authorNameSafe}\n </a>\n <div class=\"like-date\">\n ${formatRelativeTime(Math.floor(like.date.getTime() / 1000))}\n <span class=\"like-status ${statusClass}\">${statusText}</span>\n </div>\n </div>\n </div>\n </div>\n `;\n}\n\n/**\n * Render skeleton like entry HTML (with npub)\n */\nfunction renderSkeletonLikeEntry(like: LikeDetails, npub: string, index: number): string {\n const isDislike = like.content === '-';\n const statusText = isDislike ? 'Disliked' : 'Liked';\n const statusClass = isDislike ? 'disliked' : 'liked';\n \n return `\n <div class=\"like-entry skeleton-entry\" data-like-index=\"${index}\" data-author-pubkey=\"${like.authorPubkey}\">\n <div class=\"like-author-info\">\n <div class=\"skeleton-picture\"></div>\n <div class=\"like-author-details\">\n <div class=\"like-author-link skeleton-name\">\n ${escapeHtml(npub)}\n </div>\n <div class=\"like-date\">\n ${formatRelativeTime(Math.floor(like.date.getTime() / 1000))}\n <span class=\"like-status ${statusClass}\">${statusText}</span>\n </div>\n </div>\n </div>\n </div>\n `;\n}\n\n/**\n * Opens the likers dialog showing individual like details\n */\nexport async function openLikersDialog(params: OpenLikersModalParams): Promise<DialogComponent> {\n const { likeDetails, theme = 'light' } = params;\n \n // Inject styles\n injectLikersDialogStyles(theme);\n \n // Ensure custom element is defined\n if (!customElements.get('dialog-component')) {\n await customElements.whenDefined('dialog-component');\n }\n \n // Create dialog component (not added to DOM)\n const dialogComponent = document.createElement('dialog-component') as DialogComponent;\n dialogComponent.setAttribute('header', 'Likers');\n if (params.theme) {\n dialogComponent.setAttribute('data-theme', params.theme);\n }\n \n // Initial content with skeleton loaders showing npubs\n const initialContent = await renderInitialContent(likeDetails);\n dialogComponent.innerHTML = initialContent;\n \n // Show the dialog (this will create and append the actual dialog element)\n dialogComponent.showModal();\n \n // Get the actual dialog element for progressive enhancement\n const dialogElement: HTMLDialogElement | null = \n dialogComponent.querySelector('.nostr-base-dialog') ||\n dialogComponent.shadowRoot?.querySelector('.nostr-base-dialog') ||\n document.body.querySelector('.nostr-base-dialog');\n \n if (!dialogElement) {\n console.error('[openLikersDialog] Failed to find dialog element after showModal()');\n throw new Error('Dialog element not found. The dialog may not have been created properly.');\n }\n \n // Type assertion: dialog is guaranteed to be non-null after the check above\n const dialog = dialogElement as HTMLDialogElement;\n \n // Start progressive enhancement\n if (dialog && likeDetails.length > 0) {\n enhanceLikeDetailsProgressively(dialog, likeDetails);\n }\n\n return dialogComponent;\n}\n\n/**\n * Render initial dialog content with skeleton loaders showing npubs\n */\nasync function renderInitialContent(likeDetails: LikeDetails[]): Promise<string> {\n if (likeDetails.length === 0) {\n return `\n <div class=\"likers-dialog-content\">\n <div class=\"likers-list\">\n <div class=\"no-likes\">No likes yet</div>\n </div>\n </div>\n `;\n }\n\n // Convert all pubkeys to npubs for immediate display\n const npubs = likeDetails.map(like => hexToNpub(like.authorPubkey));\n\n const skeletonEntries = likeDetails.map((like, index) => \n renderSkeletonLikeEntry(like, npubs[index], index)\n ).join('');\n\n return `\n <div class=\"likers-dialog-content\">\n <div class=\"likers-list\">\n ${skeletonEntries}\n </div>\n </div>\n `;\n}\n\n/**\n * Progressively enhance like details with profile information (batched approach)\n */\nasync function enhanceLikeDetailsProgressively(dialog: HTMLDialogElement, likeDetails: LikeDetails[]): Promise<void> {\n const likersList = dialog.querySelector('.likers-list') as HTMLElement;\n if (!likersList) return;\n\n // Get unique author IDs\n const uniqueAuthorIds = [...new Set(likeDetails.map(like => like.authorPubkey))];\n console.log(\"Nostr-Components: Likers dialog: Fetching profiles for\", uniqueAuthorIds.length, \"unique authors\");\n\n try {\n // Fetch all profiles in a single batched call\n const profileResults = await getBatchedProfileMetadata(uniqueAuthorIds);\n \n // Create a map for quick lookup\n const profileMap = new Map<string, any>();\n profileResults.forEach(result => {\n profileMap.set(result.id, result.profile);\n });\n\n // Convert all pubkeys to npubs for display\n const npubMap = new Map<string, string>();\n uniqueAuthorIds.forEach(pubkey => {\n npubMap.set(pubkey, hexToNpub(pubkey));\n });\n\n // Process each like entry\n for (let index = 0; index < likeDetails.length; index++) {\n const like = likeDetails[index];\n const profile = profileMap.get(like.authorPubkey);\n const npub = npubMap.get(like.authorPubkey) || like.authorPubkey;\n \n let enhanced: EnhancedLikeDetails;\n \n if (profile) {\n const profileContent = extractProfileMetadataContent(profile);\n enhanced = {\n ...like,\n authorName: profileContent.display_name || profileContent.name || npub,\n authorPicture: profileContent.picture,\n authorNpub: npub,\n };\n } else {\n // Fallback if profile not found\n enhanced = {\n ...like,\n authorName: npub,\n authorNpub: npub,\n };\n }\n\n // Find the corresponding skeleton entry by index and replace it\n const skeletonEntry = likersList.querySelector(`[data-like-index=\"${index}\"]`);\n if (skeletonEntry) {\n const enhancedEntry = renderLikeEntry(enhanced, index);\n skeletonEntry.outerHTML = enhancedEntry;\n }\n }\n\n console.log(\"Nostr-Components: Likers dialog: Progressive enhancement completed for\", likeDetails.length, \"like entries\");\n } catch (error) {\n console.error(\"Nostr-Components: Likers dialog: Error in batched profile enhancement\", error);\n \n // Fallback to individual processing if batched approach fails\n console.log(\"Nostr-Components: Likers dialog: Falling back to individual profile fetching\");\n await enhanceLikeDetailsIndividually(dialog, likeDetails);\n }\n}\n\n/**\n * Fallback: Enhance like details individually (original approach)\n */\nasync function enhanceLikeDetailsIndividually(dialog: HTMLDialogElement, likeDetails: LikeDetails[]): Promise<void> {\n const likersList = dialog.querySelector('.likers-list') as HTMLElement;\n if (!likersList) return;\n\n // Create a map to track which profiles we've already fetched\n const profileCache = new Map<string, EnhancedLikeDetails>();\n \n // Fetch all profile metadata in parallel\n const profilePromises = likeDetails.map(async (like, index) => {\n // Check if we already have this profile cached\n if (profileCache.has(like.authorPubkey)) {\n const cachedProfile = profileCache.get(like.authorPubkey)!;\n return {\n index,\n enhanced: {\n ...like,\n authorName: cachedProfile.authorName,\n authorPicture: cachedProfile.authorPicture,\n authorNpub: cachedProfile.authorNpub,\n }\n };\n }\n\n try {\n const { getProfileMetadata } = await import('../nostr-zap/zap-utils');\n const profileMetadata = await getProfileMetadata(like.authorPubkey);\n const profileContent = extractProfileMetadataContent(profileMetadata);\n const npub = hexToNpub(like.authorPubkey);\n \n const enhanced = {\n ...like,\n authorName: profileContent.display_name || profileContent.name || npub,\n authorPicture: profileContent.picture,\n authorNpub: npub,\n };\n\n // Cache the profile for other entries from the same author\n profileCache.set(like.authorPubkey, enhanced);\n \n return {\n index,\n enhanced\n };\n } catch (error) {\n console.error(\"Nostr-Components: Likers dialog: Error fetching profile for\", like.authorPubkey, error);\n // Fallback with just pubkey converted to npub\n const npub = hexToNpub(like.authorPubkey);\n const enhanced = {\n ...like,\n authorName: npub,\n authorNpub: npub,\n };\n \n // Cache the fallback profile\n profileCache.set(like.authorPubkey, enhanced);\n \n return {\n index,\n enhanced\n };\n }\n });\n\n // Process each profile as it becomes available\n for (const promise of profilePromises) {\n try {\n const { index, enhanced } = await promise;\n \n // Find the corresponding skeleton entry by index and replace it\n const skeletonEntry = likersList.querySelector(`[data-like-index=\"${index}\"]`);\n if (skeletonEntry) {\n const enhancedEntry = renderLikeEntry(enhanced, index);\n skeletonEntry.outerHTML = enhancedEntry;\n }\n } catch (error) {\n console.error(\"Nostr-Components: Likers dialog: Error processing profile enhancement\", error);\n }\n }\n}\n"],"file":"assets/dialog-likers-BqDn2P_3.js"}