@signalwire/web-components 1.0.0-dev-20260428141127 → 1.0.0-dev-20260428183200
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 +45 -52
- package/dist/_virtual/_commonjsHelpers.js +9 -0
- package/dist/_virtual/_commonjsHelpers.js.map +1 -0
- package/dist/_virtual/prism-python.js +28 -0
- package/dist/_virtual/prism-python.js.map +1 -0
- package/dist/_virtual/prism-python2.js +5 -0
- package/dist/_virtual/prism-python2.js.map +1 -0
- package/dist/_virtual/prism-typescript.js +28 -0
- package/dist/_virtual/prism-typescript.js.map +1 -0
- package/dist/_virtual/prism-typescript2.js +5 -0
- package/dist/_virtual/prism-typescript2.js.map +1 -0
- package/dist/_virtual/prism.js +28 -0
- package/dist/_virtual/prism.js.map +1 -0
- package/dist/_virtual/prism2.js +5 -0
- package/dist/_virtual/prism2.js.map +1 -0
- package/dist/assets/sw_background.webp.js +5 -0
- package/dist/assets/sw_background.webp.js.map +1 -0
- package/dist/components/UI/DEFAULT_BACKGROUND.d.ts +4 -0
- package/dist/components/UI/DEFAULT_BACKGROUND.d.ts.map +1 -0
- package/dist/components/UI/DEFAULT_BACKGROUND.js +5 -0
- package/dist/components/UI/DEFAULT_BACKGROUND.js.map +1 -0
- package/dist/components/UI/controls/sw-ui-control-bar.d.ts +114 -0
- package/dist/components/UI/controls/sw-ui-control-bar.d.ts.map +1 -0
- package/dist/components/UI/controls/sw-ui-control-bar.js +324 -0
- package/dist/components/UI/controls/sw-ui-control-bar.js.map +1 -0
- package/dist/components/UI/controls/sw-ui-dialpad.d.ts +57 -0
- package/dist/components/UI/controls/sw-ui-dialpad.d.ts.map +1 -0
- package/dist/components/UI/controls/sw-ui-dialpad.js +319 -0
- package/dist/components/UI/controls/sw-ui-dialpad.js.map +1 -0
- package/dist/components/UI/controls/sw-ui-dropup.d.ts +42 -0
- package/dist/components/UI/controls/sw-ui-dropup.d.ts.map +1 -0
- package/dist/components/UI/controls/sw-ui-dropup.js +137 -0
- package/dist/components/UI/controls/sw-ui-dropup.js.map +1 -0
- package/dist/components/UI/controls/sw-ui-split-button.d.ts +44 -0
- package/dist/components/UI/controls/sw-ui-split-button.d.ts.map +1 -0
- package/dist/components/UI/controls/sw-ui-split-button.js +177 -0
- package/dist/components/UI/controls/sw-ui-split-button.js.map +1 -0
- package/dist/components/UI/icons/backspace.svg.js +10 -0
- package/dist/components/UI/icons/backspace.svg.js.map +1 -0
- package/dist/components/UI/icons/camera-off.svg.js +8 -0
- package/dist/components/UI/icons/camera-off.svg.js.map +1 -0
- package/dist/components/UI/icons/camera-on.svg.js +8 -0
- package/dist/components/UI/icons/camera-on.svg.js.map +1 -0
- package/dist/components/UI/icons/check-circle.svg.js +6 -0
- package/dist/components/UI/icons/check-circle.svg.js.map +1 -0
- package/dist/components/UI/icons/chevron-up.svg.js +8 -0
- package/dist/components/UI/icons/chevron-up.svg.js.map +1 -0
- package/dist/components/UI/icons/close.svg.js +6 -0
- package/dist/components/UI/icons/close.svg.js.map +1 -0
- package/dist/components/UI/icons/copy.svg.js +6 -0
- package/dist/components/UI/icons/copy.svg.js.map +1 -0
- package/dist/components/UI/icons/download.svg.js +6 -0
- package/dist/components/UI/icons/download.svg.js.map +1 -0
- package/dist/components/UI/icons/fullscreen-exit.svg.js +8 -0
- package/dist/components/UI/icons/fullscreen-exit.svg.js.map +1 -0
- package/dist/components/UI/icons/fullscreen.svg.js +8 -0
- package/dist/components/UI/icons/fullscreen.svg.js.map +1 -0
- package/dist/components/UI/icons/hand-raise.svg.js +6 -0
- package/dist/components/UI/icons/hand-raise.svg.js.map +1 -0
- package/dist/components/UI/icons/icons.d.ts +31 -0
- package/dist/components/UI/icons/icons.d.ts.map +1 -0
- package/dist/components/UI/icons/icons.js +60 -0
- package/dist/components/UI/icons/icons.js.map +1 -0
- package/dist/components/UI/icons/index.d.ts +4 -0
- package/dist/components/UI/icons/index.d.ts.map +1 -0
- package/dist/components/UI/icons/info-circle.svg.js +6 -0
- package/dist/components/UI/icons/info-circle.svg.js.map +1 -0
- package/dist/components/UI/icons/mic-off.svg.js +8 -0
- package/dist/components/UI/icons/mic-off.svg.js.map +1 -0
- package/dist/components/UI/icons/mic-on.svg.js +8 -0
- package/dist/components/UI/icons/mic-on.svg.js.map +1 -0
- package/dist/components/UI/icons/person.svg.js +8 -0
- package/dist/components/UI/icons/person.svg.js.map +1 -0
- package/dist/components/UI/icons/phone-call.svg.js +8 -0
- package/dist/components/UI/icons/phone-call.svg.js.map +1 -0
- package/dist/components/UI/icons/phone-end.svg.js +8 -0
- package/dist/components/UI/icons/phone-end.svg.js.map +1 -0
- package/dist/components/UI/icons/room.svg.js +8 -0
- package/dist/components/UI/icons/room.svg.js.map +1 -0
- package/dist/components/UI/icons/screen-share-off.svg.js +9 -0
- package/dist/components/UI/icons/screen-share-off.svg.js.map +1 -0
- package/dist/components/UI/icons/screen-share.svg.js +9 -0
- package/dist/components/UI/icons/screen-share.svg.js.map +1 -0
- package/dist/components/UI/icons/sendIcon.svg.js +9 -0
- package/dist/components/UI/icons/sendIcon.svg.js.map +1 -0
- package/dist/components/UI/icons/settings.svg.js +8 -0
- package/dist/components/UI/icons/settings.svg.js.map +1 -0
- package/dist/components/UI/icons/speaker-off.svg.js +8 -0
- package/dist/components/UI/icons/speaker-off.svg.js.map +1 -0
- package/dist/components/UI/icons/speaker-on.svg.js +8 -0
- package/dist/components/UI/icons/speaker-on.svg.js.map +1 -0
- package/dist/components/UI/icons/spinner.svg.js +9 -0
- package/dist/components/UI/icons/spinner.svg.js.map +1 -0
- package/dist/components/UI/icons/sw-logo.svg.js +11 -0
- package/dist/components/UI/icons/sw-logo.svg.js.map +1 -0
- package/dist/components/UI/icons/sw-ui-icon.d.ts +28 -0
- package/dist/components/UI/icons/sw-ui-icon.d.ts.map +1 -0
- package/dist/components/UI/icons/sw-ui-icon.js +47 -0
- package/dist/components/UI/icons/sw-ui-icon.js.map +1 -0
- package/dist/components/UI/icons/transcript.svg.js +10 -0
- package/dist/components/UI/icons/transcript.svg.js.map +1 -0
- package/dist/components/UI/index.d.ts +18 -0
- package/dist/components/UI/index.d.ts.map +1 -0
- package/dist/components/UI/layout/sw-ui-background.d.ts +33 -0
- package/dist/components/UI/layout/sw-ui-background.d.ts.map +1 -0
- package/dist/components/UI/layout/sw-ui-background.js +106 -0
- package/dist/components/UI/layout/sw-ui-background.js.map +1 -0
- package/dist/components/UI/layout/sw-ui-call-layout.d.ts +69 -0
- package/dist/components/UI/layout/sw-ui-call-layout.d.ts.map +1 -0
- package/dist/components/UI/layout/sw-ui-call-layout.js +278 -0
- package/dist/components/UI/layout/sw-ui-call-layout.js.map +1 -0
- package/dist/components/UI/layout/sw-ui-content-drawer.d.ts +50 -0
- package/dist/components/UI/layout/sw-ui-content-drawer.d.ts.map +1 -0
- package/dist/components/UI/layout/sw-ui-content-drawer.js +413 -0
- package/dist/components/UI/layout/sw-ui-content-drawer.js.map +1 -0
- package/dist/components/UI/layout/sw-ui-modal.d.ts +31 -0
- package/dist/components/UI/layout/sw-ui-modal.d.ts.map +1 -0
- package/dist/components/UI/layout/sw-ui-modal.js +150 -0
- package/dist/components/UI/layout/sw-ui-modal.js.map +1 -0
- package/dist/components/UI/layout/sw-ui-responsive-container.d.ts +15 -0
- package/dist/components/UI/layout/sw-ui-responsive-container.d.ts.map +1 -0
- package/dist/components/UI/layout/sw-ui-responsive-container.js +78 -0
- package/dist/components/UI/layout/sw-ui-responsive-container.js.map +1 -0
- package/dist/components/UI/sw-ui-alert.d.ts +37 -0
- package/dist/components/UI/sw-ui-alert.d.ts.map +1 -0
- package/dist/components/UI/sw-ui-alert.js +126 -0
- package/dist/components/UI/sw-ui-alert.js.map +1 -0
- package/dist/components/UI/sw-ui-transcript-view.d.ts +56 -0
- package/dist/components/UI/sw-ui-transcript-view.d.ts.map +1 -0
- package/dist/components/UI/sw-ui-transcript-view.js +341 -0
- package/dist/components/UI/sw-ui-transcript-view.js.map +1 -0
- package/dist/components/directory.d.ts +10 -18
- package/dist/components/directory.d.ts.map +1 -1
- package/dist/components/directory.js +129 -198
- package/dist/components/directory.js.map +1 -1
- package/dist/embed/signalwire-web-components-embed.iife.js +2336 -982
- package/dist/embed/signalwire-web-components-embed.iife.js.map +1 -1
- package/dist/embed/signalwire-web-components-embed.umd.cjs +2336 -982
- package/dist/embed/signalwire-web-components-embed.umd.cjs.map +1 -1
- package/dist/embed.d.ts +1 -1
- package/dist/embed.d.ts.map +1 -1
- package/dist/index.d.ts +2 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +54 -33
- package/dist/index.js.map +1 -1
- package/dist/node_modules/dompurify/dist/purify.es.js +597 -0
- package/dist/node_modules/dompurify/dist/purify.es.js.map +1 -0
- package/dist/node_modules/marked/lib/marked.esm.js +1475 -0
- package/dist/node_modules/marked/lib/marked.esm.js.map +1 -0
- package/dist/node_modules/prismjs/components/prism-bash.js +220 -0
- package/dist/node_modules/prismjs/components/prism-bash.js.map +1 -0
- package/dist/node_modules/prismjs/components/prism-css.js +56 -0
- package/dist/node_modules/prismjs/components/prism-css.js.map +1 -0
- package/dist/node_modules/prismjs/components/prism-javascript.js +138 -0
- package/dist/node_modules/prismjs/components/prism-javascript.js.map +1 -0
- package/dist/node_modules/prismjs/components/prism-json.js +26 -0
- package/dist/node_modules/prismjs/components/prism-json.js.map +1 -0
- package/dist/node_modules/prismjs/components/prism-markdown.js +301 -0
- package/dist/node_modules/prismjs/components/prism-markdown.js.map +1 -0
- package/dist/node_modules/prismjs/components/prism-python.js +69 -0
- package/dist/node_modules/prismjs/components/prism-python.js.map +1 -0
- package/dist/node_modules/prismjs/components/prism-sql.js +34 -0
- package/dist/node_modules/prismjs/components/prism-sql.js.map +1 -0
- package/dist/node_modules/prismjs/components/prism-typescript.js +53 -0
- package/dist/node_modules/prismjs/components/prism-typescript.js.map +1 -0
- package/dist/node_modules/prismjs/components/prism-yaml.js +67 -0
- package/dist/node_modules/prismjs/components/prism-yaml.js.map +1 -0
- package/dist/node_modules/prismjs/prism.js +1165 -0
- package/dist/node_modules/prismjs/prism.js.map +1 -0
- package/dist/react.d.ts +3 -3
- package/dist/utils/prism.d.ts +4 -0
- package/dist/utils/prism.d.ts.map +1 -0
- package/dist/utils/prism.js +34 -0
- package/dist/utils/prism.js.map +1 -0
- package/dist/utils/transcriptToMarkdown.d.ts +14 -0
- package/dist/utils/transcriptToMarkdown.d.ts.map +1 -0
- package/dist/utils/transcriptToMarkdown.js +59 -0
- package/dist/utils/transcriptToMarkdown.js.map +1 -0
- package/package.json +53 -9
- package/dist/components/dialpad.d.ts +0 -74
- package/dist/components/dialpad.d.ts.map +0 -1
- package/dist/components/dialpad.js +0 -372
- package/dist/components/dialpad.js.map +0 -1
- package/dist/components/example-button.d.ts +0 -21
- package/dist/components/example-button.d.ts.map +0 -1
- package/dist/components/example-button.js +0 -74
- package/dist/components/example-button.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"directory.js","sources":["../../src/components/directory.ts"],"sourcesContent":["/**\n * Directory Component\n *\n * A searchable list of addresses from the directory service.\n * Supports filtering, selection, and pagination.\n *\n * @example\n * ```html\n * <sw-directory .directory=${directory}></sw-directory>\n * ```\n *\n * @fires sw-address-select - Fired when an address is selected. Detail: `{ address: Address }`\n * @fires sw-dial - Fired when the call button on an address is clicked. Detail: `{ address: Address, channel: string }`\n *\n * @cssprop [--sw-color-primary=#044cf6] - Primary brand color\n * @cssprop [--sw-color-primary-hover=#0339c4] - Primary color on hover\n * @cssprop [--sw-color-success=#10b981] - Success/positive color\n * @cssprop [--sw-color-text=#1f2937] - Primary text color\n * @cssprop [--sw-color-text-muted=#6b7280] - Secondary/muted text color\n * @cssprop [--sw-color-background=#ffffff] - Component background color\n * @cssprop [--sw-color-background-hover=#f3f4f6] - Background color on hover\n * @cssprop [--sw-color-background-active=#e5e7eb] - Background color on active/press\n * @cssprop [--sw-color-border=#e5e7eb] - Border color\n * @cssprop [--sw-font-family=-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif] - Font family\n * @cssprop [--sw-font-size-sm=12px] - Small font size\n * @cssprop [--sw-font-size-base=14px] - Base font size\n * @cssprop [--sw-font-size-lg=16px] - Large font size\n * @cssprop [--sw-space-1=4px] - Smallest spacing unit\n * @cssprop [--sw-space-2=8px] - Small spacing unit\n * @cssprop [--sw-space-3=12px] - Medium spacing unit\n * @cssprop [--sw-space-4=16px] - Large spacing unit\n * @cssprop [--sw-border-radius=8px] - Border radius for containers and inputs\n */\n\nimport { LitElement, html, css } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\nimport { Subscription } from 'rxjs';\nimport type { Observable } from 'rxjs';\n\n/**\n * Address type from SDK\n */\nexport interface Address {\n id: string;\n name: string;\n displayName?: string;\n type?: 'room' | 'person';\n channels?: {\n audio?: boolean;\n video?: boolean;\n messaging?: boolean;\n };\n}\n\n/**\n * Directory interface for component\n */\nexport interface DirectoryService {\n addresses$: Observable<Address[]>;\n loading$?: Observable<boolean>;\n hasMore$?: Observable<boolean>;\n loadMore?(): Promise<void>;\n}\n\n@customElement('sw-directory')\nexport class DirectoryComponent extends LitElement {\n static styles = css`\n :host {\n /* CSS Custom Properties for theming */\n --sw-color-primary: #044cf6;\n --sw-color-primary-hover: #0339c4;\n --sw-color-success: #10b981;\n --sw-color-text: #1f2937;\n --sw-color-text-muted: #6b7280;\n --sw-color-background: #ffffff;\n --sw-color-background-hover: #f3f4f6;\n --sw-color-background-active: #e5e7eb;\n --sw-color-border: #e5e7eb;\n --sw-font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n --sw-font-size-sm: 12px;\n --sw-font-size-base: 14px;\n --sw-font-size-lg: 16px;\n --sw-space-1: 4px;\n --sw-space-2: 8px;\n --sw-space-3: 12px;\n --sw-space-4: 16px;\n --sw-border-radius: 8px;\n\n display: block;\n font-family: var(--sw-font-family);\n }\n\n /* Dark mode support */\n :host([data-theme='dark']) {\n --sw-color-text: #f9fafb;\n --sw-color-text-muted: #9ca3af;\n --sw-color-background: #1f2937;\n --sw-color-background-hover: #374151;\n --sw-color-background-active: #4b5563;\n --sw-color-border: #374151;\n }\n\n @media (prefers-color-scheme: dark) {\n :host(:not([data-theme='light'])) {\n --sw-color-text: #f9fafb;\n --sw-color-text-muted: #9ca3af;\n --sw-color-background: #1f2937;\n --sw-color-background-hover: #374151;\n --sw-color-background-active: #4b5563;\n --sw-color-border: #374151;\n }\n }\n\n .container {\n display: flex;\n flex-direction: column;\n background: var(--sw-color-background);\n border: 1px solid var(--sw-color-border);\n border-radius: var(--sw-border-radius);\n overflow: hidden;\n }\n\n .search {\n display: flex;\n align-items: center;\n gap: var(--sw-space-2);\n padding: var(--sw-space-3);\n border-bottom: 1px solid var(--sw-color-border);\n }\n\n .search-input {\n flex: 1;\n padding: var(--sw-space-2) var(--sw-space-3);\n border: 1px solid var(--sw-color-border);\n border-radius: var(--sw-border-radius);\n background: var(--sw-color-background);\n color: var(--sw-color-text);\n font-family: var(--sw-font-family);\n font-size: var(--sw-font-size-base);\n outline: none;\n transition: border-color 0.15s ease;\n }\n\n .search-input:focus {\n border-color: var(--sw-color-primary);\n }\n\n .search-input::placeholder {\n color: var(--sw-color-text-muted);\n }\n\n .list {\n display: flex;\n flex-direction: column;\n max-height: 400px;\n overflow-y: auto;\n }\n\n .item {\n display: flex;\n align-items: center;\n gap: var(--sw-space-3);\n padding: var(--sw-space-3) var(--sw-space-4);\n border-bottom: 1px solid var(--sw-color-border);\n cursor: pointer;\n transition: background-color 0.15s ease;\n }\n\n .item:last-child {\n border-bottom: none;\n }\n\n .item:hover {\n background: var(--sw-color-background-hover);\n }\n\n .item:active {\n background: var(--sw-color-background-active);\n }\n\n .item.selected {\n background: var(--sw-color-primary);\n color: white;\n }\n\n .item.selected .item-type,\n .item.selected .item-channels {\n color: rgba(255, 255, 255, 0.8);\n }\n\n .item-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 40px;\n height: 40px;\n border-radius: 50%;\n background: var(--sw-color-background-hover);\n color: var(--sw-color-text-muted);\n flex-shrink: 0;\n }\n\n .item.selected .item-icon {\n background: rgba(255, 255, 255, 0.2);\n color: white;\n }\n\n .item-icon svg {\n width: 20px;\n height: 20px;\n }\n\n .item-content {\n flex: 1;\n min-width: 0;\n }\n\n .item-name {\n font-size: var(--sw-font-size-base);\n font-weight: 500;\n color: inherit;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .item-type {\n font-size: var(--sw-font-size-sm);\n color: var(--sw-color-text-muted);\n text-transform: capitalize;\n }\n\n .item-channels {\n display: flex;\n gap: var(--sw-space-1);\n color: var(--sw-color-text-muted);\n }\n\n .item-channels svg {\n width: 16px;\n height: 16px;\n }\n\n .item-channels .active {\n color: var(--sw-color-success);\n }\n\n .loading,\n .empty {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: var(--sw-space-4);\n color: var(--sw-color-text-muted);\n font-size: var(--sw-font-size-base);\n }\n\n .scroll-sentinel {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: var(--sw-space-3);\n min-height: 1px;\n }\n\n .scroll-loading {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: var(--sw-space-2);\n padding: var(--sw-space-3);\n color: var(--sw-color-text-muted);\n font-size: var(--sw-font-size-sm);\n }\n\n .spinner {\n width: 16px;\n height: 16px;\n border: 2px solid var(--sw-color-border);\n border-top-color: var(--sw-color-primary);\n border-radius: 50%;\n animation: spin 0.8s linear infinite;\n }\n\n @keyframes spin {\n to {\n transform: rotate(360deg);\n }\n }\n\n .dial-button {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n background: var(--sw-color-success);\n border: none;\n border-radius: 50%;\n color: white;\n cursor: pointer;\n flex-shrink: 0;\n transition: background-color 0.15s ease;\n }\n\n .dial-button:hover {\n background: #0ea472;\n }\n\n .dial-button svg {\n width: 18px;\n height: 18px;\n }\n `;\n\n /**\n * Directory service with addresses$ observable\n */\n @property({ type: Object })\n directory: DirectoryService | null = null;\n\n /**\n * Currently selected address\n */\n @state()\n private selectedAddress: Address | null = null;\n\n /**\n * Search filter query\n */\n @state()\n private searchQuery: string = '';\n\n /**\n * List of addresses from directory\n */\n @state()\n private addresses: Address[] = [];\n\n /**\n * Loading state\n */\n @state()\n private loading: boolean = false;\n\n /**\n * Has more addresses to load\n */\n @state()\n private hasMore: boolean = false;\n\n /**\n * RxJS subscriptions for cleanup\n */\n private subscriptions: Subscription[] = [];\n\n /**\n * Debounce timer for search\n */\n private searchDebounceTimer: number | null = null;\n\n /**\n * IntersectionObserver for infinite scroll\n */\n private intersectionObserver: IntersectionObserver | null = null;\n\n /**\n * Flag to track if we're auto-loading for search\n */\n @state()\n private isAutoLoadingForSearch: boolean = false;\n\n connectedCallback() {\n super.connectedCallback();\n this.subscribeToDirectory();\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n this.cleanup();\n }\n\n private subscribeToDirectory() {\n if (!this.directory) return;\n\n // Subscribe to addresses\n if (this.directory.addresses$) {\n const addressesSub = this.directory.addresses$.subscribe((addresses) => {\n this.addresses = addresses;\n });\n this.subscriptions.push(addressesSub);\n }\n\n // Subscribe to loading state\n if (this.directory.loading$) {\n const loadingSub = this.directory.loading$.subscribe((loading) => {\n this.loading = loading;\n });\n this.subscriptions.push(loadingSub);\n }\n\n // Subscribe to hasMore\n if (this.directory.hasMore$) {\n const hasMoreSub = this.directory.hasMore$.subscribe((hasMore) => {\n this.hasMore = hasMore;\n });\n this.subscriptions.push(hasMoreSub);\n }\n\n // Load initial data\n if (this.directory.loadMore) {\n this.directory.loadMore();\n }\n }\n\n private cleanup() {\n this.subscriptions.forEach((sub) => sub.unsubscribe());\n this.subscriptions = [];\n if (this.searchDebounceTimer) {\n clearTimeout(this.searchDebounceTimer);\n }\n if (this.intersectionObserver) {\n this.intersectionObserver.disconnect();\n this.intersectionObserver = null;\n }\n }\n\n protected firstUpdated() {\n this.setupInfiniteScroll();\n }\n\n private setupInfiniteScroll() {\n const sentinel = this.shadowRoot?.querySelector('.scroll-sentinel');\n if (!sentinel) return;\n\n this.intersectionObserver = new IntersectionObserver(\n (entries) => {\n const entry = entries[0];\n if (entry?.isIntersecting && this.hasMore && !this.loading) {\n this.handleLoadMore();\n }\n },\n {\n root: this.shadowRoot?.querySelector('.list'),\n rootMargin: '100px',\n threshold: 0\n }\n );\n\n this.intersectionObserver.observe(sentinel);\n }\n\n protected updated(changedProperties: Map<string, unknown>) {\n super.updated(changedProperties);\n\n // Handle directory property changes\n if (changedProperties.has('directory')) {\n this.cleanup();\n this.subscribeToDirectory();\n }\n\n // Re-setup infinite scroll if needed\n if (!this.intersectionObserver) {\n this.setupInfiniteScroll();\n }\n\n // Auto-load more when searching and no results found but more available\n // Also check when loading state changes so we can trigger subsequent loads\n if (\n changedProperties.has('addresses') ||\n changedProperties.has('searchQuery') ||\n changedProperties.has('loading')\n ) {\n this.checkAutoLoadForSearch();\n }\n }\n\n private async checkAutoLoadForSearch() {\n // If we have a search query, no filtered results, but more to load, keep loading\n // Note: !this.loading prevents concurrent loads, isAutoLoadingForSearch is for UI state only\n if (\n this.searchQuery.trim() &&\n this.filteredAddresses.length === 0 &&\n this.hasMore &&\n !this.loading\n ) {\n this.isAutoLoadingForSearch = true;\n await this.handleLoadMore();\n // The updated() will be called again when addresses/loading change, continuing the loop\n } else if (this.filteredAddresses.length > 0 || !this.hasMore) {\n this.isAutoLoadingForSearch = false;\n }\n }\n\n private get filteredAddresses(): Address[] {\n if (!this.searchQuery.trim()) {\n return this.addresses;\n }\n const query = this.searchQuery.toLowerCase();\n return this.addresses.filter(\n (addr) =>\n addr.name.toLowerCase().includes(query) ||\n (addr.displayName && addr.displayName.toLowerCase().includes(query))\n );\n }\n\n private handleSearchInput(e: Event) {\n const input = e.target as HTMLInputElement;\n\n // Debounce search\n if (this.searchDebounceTimer) {\n clearTimeout(this.searchDebounceTimer);\n }\n\n this.searchDebounceTimer = window.setTimeout(() => {\n this.searchQuery = input.value;\n }, 200);\n }\n\n private handleItemClick(address: Address) {\n this.selectedAddress = address;\n\n this.dispatchEvent(\n new CustomEvent('sw-address-select', {\n detail: { address },\n bubbles: true,\n composed: true\n })\n );\n }\n\n private handleItemDoubleClick(address: Address) {\n this.handleDial(address);\n }\n\n private handleDial(address: Address) {\n this.dispatchEvent(\n new CustomEvent('sw-dial', {\n detail: { address },\n bubbles: true,\n composed: true\n })\n );\n }\n\n private async handleLoadMore() {\n if (this.directory?.loadMore) {\n await this.directory.loadMore();\n }\n }\n\n private renderAddressIcon(address: Address) {\n if (address.type === 'room') {\n return html`\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path\n d=\"M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-7 3c1.93 0 3.5 1.57 3.5 3.5S13.93 13 12 13s-3.5-1.57-3.5-3.5S10.07 6 12 6zm7 13H5v-.23c0-.62.28-1.2.76-1.58C7.47 15.82 9.64 15 12 15s4.53.82 6.24 2.19c.48.38.76.97.76 1.58V19z\"\n />\n </svg>\n `;\n }\n return html`\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path\n d=\"M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z\"\n />\n </svg>\n `;\n }\n\n private renderChannelIcons(address: Address) {\n const channels = address.channels || {};\n return html`\n <div class=\"item-channels\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n class=\"${channels.audio ? 'active' : ''}\"\n title=\"Audio\"\n >\n <path\n d=\"M12 14c1.66 0 2.99-1.34 2.99-3L15 5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3 3 3z\"\n />\n </svg>\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n class=\"${channels.video ? 'active' : ''}\"\n title=\"Video\"\n >\n <path\n d=\"M17 10.5V7c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h12c.55 0 1-.45 1-1v-3.5l4 4v-11l-4 4z\"\n />\n </svg>\n </div>\n `;\n }\n\n private renderLoadingIndicator() {\n return html`\n <div class=\"scroll-loading\">\n <div class=\"spinner\"></div>\n <span>${this.isAutoLoadingForSearch ? 'Searching...' : 'Loading more...'}</span>\n </div>\n `;\n }\n\n render() {\n const showInitialLoading = this.loading && this.addresses.length === 0;\n const showEmptyState = !this.loading && this.filteredAddresses.length === 0 && !this.hasMore;\n const showSearchingState = this.isAutoLoadingForSearch && this.filteredAddresses.length === 0;\n\n return html`\n <div class=\"container\" part=\"container\">\n <div class=\"search\" part=\"search\">\n <input\n type=\"text\"\n class=\"search-input\"\n placeholder=\"Search addresses...\"\n @input=${this.handleSearchInput}\n aria-label=\"Search addresses\"\n />\n </div>\n\n <div class=\"list\" part=\"list\" role=\"listbox\">\n ${showInitialLoading\n ? html`<div class=\"loading\">Loading...</div>`\n : showSearchingState\n ? this.renderLoadingIndicator()\n : showEmptyState\n ? html`<div class=\"empty\">No addresses found</div>`\n : html`\n ${this.filteredAddresses.map(\n (address) => html`\n <div\n class=\"item ${this.selectedAddress?.id === address.id ? 'selected' : ''}\"\n part=\"item ${this.selectedAddress?.id === address.id\n ? 'item-selected'\n : ''}\"\n role=\"option\"\n aria-selected=\"${this.selectedAddress?.id === address.id}\"\n @click=${() => this.handleItemClick(address)}\n @dblclick=${() => this.handleItemDoubleClick(address)}\n >\n <div class=\"item-icon\">${this.renderAddressIcon(address)}</div>\n <div class=\"item-content\">\n <div class=\"item-name\" part=\"item-name\">\n ${address.displayName || address.name}\n </div>\n <div class=\"item-type\" part=\"item-type\">\n ${address.type || 'address'}\n </div>\n </div>\n ${this.renderChannelIcons(address)}\n <button\n class=\"dial-button\"\n @click=${(e: Event) => {\n e.stopPropagation();\n this.handleDial(address);\n }}\n aria-label=\"Call ${address.displayName || address.name}\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n >\n <path\n d=\"M6.62 10.79c1.44 2.83 3.76 5.15 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1-9.39 0-17-7.61-17-17 0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.25.2 2.45.57 3.57.11.35.03.74-.25 1.02l-2.2 2.2z\"\n />\n </svg>\n </button>\n </div>\n `\n )}\n <!-- Scroll sentinel for infinite scroll -->\n <div class=\"scroll-sentinel\">\n ${this.loading && !this.isAutoLoadingForSearch\n ? this.renderLoadingIndicator()\n : null}\n </div>\n `}\n </div>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'sw-directory': DirectoryComponent;\n }\n}\n"],"names":["DirectoryComponent","LitElement","addressesSub","addresses","loadingSub","loading","hasMoreSub","hasMore","sub","sentinel","_a","entries","entry","_b","changedProperties","query","addr","input","address","html","channels","showInitialLoading","showEmptyState","showSearchingState","_c","e","css","__decorateClass","property","state","customElement"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"directory.js","sources":["../../src/components/directory.ts"],"sourcesContent":["/**\n * Directory Component\n *\n * A searchable list of addresses from the directory service.\n * Supports filtering, selection, and pagination.\n *\n * @example\n * ```html\n * <sw-directory .directory=${directory}></sw-directory>\n * ```\n *\n * @fires sw-address-select - Fired when an address is selected. Detail: `{ address: Address }`\n * @fires sw-dial - Fired when the call button on an address is clicked. Detail: `{ address: Address, channel: string }`\n *\n * @cssprop [--interactive-button-primary-bg=#044ef4] - Primary brand color\n * @cssprop [--interactive-button-primary-hover=#0342cf] - Primary color on hover\n * @cssprop [--interactive-status-success=#22c55e] - Success/positive color\n * @cssprop [--fg-default=#f0f0f4] - Primary text color\n * @cssprop [--fg-muted=#a0a0aa] - Secondary/muted text color\n * @cssprop [--bg-surface=#181a28] - Component background color\n * @cssprop [--bg-surface-raised=#222436] - Background color on hover\n * @cssprop [--interactive-dropdown-hover=#333338] - Background color on active/press\n * @cssprop [--border-default=rgba(255,255,255,0.12)] - Border color\n */\n\nimport { LitElement, html, css } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\nimport { Subscription } from 'rxjs';\nimport type { Observable } from 'rxjs';\nimport './UI/icons/sw-ui-icon.js';\n\n/**\n * Address type from SDK\n */\nexport interface Address {\n id: string;\n name: string;\n displayName?: string;\n type?: 'room' | 'person';\n channels?: {\n audio?: boolean;\n video?: boolean;\n messaging?: boolean;\n };\n}\n\n/**\n * Directory interface for component\n */\nexport interface DirectoryService {\n addresses$: Observable<Address[]>;\n loading$?: Observable<boolean>;\n hasMore$?: Observable<boolean>;\n loadMore?(): Promise<void>;\n}\n\n@customElement('sw-directory')\nexport class DirectoryComponent extends LitElement {\n static styles = css`\n :host {\n display: block;\n font-family: var(--type-family-body);\n color: var(--fg-default);\n }\n\n .container {\n display: flex;\n flex-direction: column;\n background: var(--bg-surface);\n border: 1px solid var(--border-default);\n border-radius: var(--radius-md);\n overflow: hidden;\n }\n\n .search {\n display: flex;\n align-items: center;\n gap: var(--sp-2);\n padding: var(--sp-3);\n border-bottom: 1px solid var(--border-default);\n }\n\n .search-input {\n flex: 1;\n padding: var(--sp-2) var(--sp-3);\n border: 1px solid var(--border-default);\n border-radius: var(--radius-md);\n background: var(--bg-surface);\n color: var(--fg-default);\n font-family: var(--type-family-body);\n font-size: var(--type-size-small);\n outline: none;\n transition: border-color 0.15s ease;\n }\n\n .search-input:focus {\n border-color: var(--interactive-button-primary-bg);\n }\n\n .search-input::placeholder {\n color: var(--fg-muted);\n }\n\n .list {\n display: flex;\n flex-direction: column;\n max-height: 400px;\n overflow-y: auto;\n }\n\n .item {\n display: flex;\n align-items: center;\n gap: var(--sp-3);\n padding: var(--sp-3) var(--sp-4);\n border-bottom: 1px solid var(--border-default);\n cursor: pointer;\n transition: background-color 0.15s ease;\n }\n\n .item:last-child {\n border-bottom: none;\n }\n\n .item:hover {\n background: var(--bg-surface-raised);\n }\n\n .item:active {\n background: var(--interactive-dropdown-hover);\n }\n\n .item.selected {\n background: var(--interactive-button-primary-bg);\n color: white;\n }\n\n .item.selected .item-type,\n .item.selected .item-channels {\n color: rgba(255, 255, 255, 0.8);\n }\n\n .item-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 40px;\n height: 40px;\n border-radius: 50%;\n background: var(--bg-surface-raised);\n color: var(--fg-muted);\n flex-shrink: 0;\n }\n\n .item.selected .item-icon {\n background: rgba(255, 255, 255, 0.2);\n color: white;\n }\n\n .item-icon svg,\n .item-icon sw-ui-icon {\n width: 20px;\n height: 20px;\n }\n\n .item-content {\n flex: 1;\n min-width: 0;\n }\n\n .item-name {\n font-size: var(--type-size-small);\n font-weight: 500;\n color: inherit;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .item-type {\n font-size: var(--type-size-caption);\n color: var(--fg-muted);\n text-transform: capitalize;\n }\n\n .item-channels {\n display: flex;\n gap: var(--sp-1);\n color: var(--fg-muted);\n }\n\n .item-channels sw-ui-icon {\n width: 16px;\n height: 16px;\n }\n\n .item-channels sw-ui-icon.active {\n color: var(--interactive-status-success);\n }\n\n .loading,\n .empty {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: var(--sp-4);\n color: var(--fg-muted);\n font-size: var(--type-size-small);\n }\n\n .scroll-sentinel {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: var(--sp-3);\n min-height: 1px;\n }\n\n .scroll-loading {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: var(--sp-2);\n padding: var(--sp-3);\n color: var(--fg-muted);\n font-size: var(--type-size-caption);\n }\n\n .spinner {\n width: 16px;\n height: 16px;\n border: 2px solid var(--border-default);\n border-top-color: var(--interactive-button-primary-bg);\n border-radius: 50%;\n animation: spin 0.8s linear infinite;\n }\n\n @keyframes spin {\n to {\n transform: rotate(360deg);\n }\n }\n\n .dial-button {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n background: var(--interactive-status-success);\n border: none;\n border-radius: 50%;\n color: white;\n cursor: pointer;\n flex-shrink: 0;\n transition: background-color 0.15s ease;\n }\n\n .dial-button:hover {\n background: #0ea472;\n }\n\n .dial-button sw-ui-icon {\n pointer-events: none;\n }\n `;\n\n /**\n * Directory service with addresses$ observable\n */\n @property({ type: Object })\n directory: DirectoryService | null = null;\n\n /**\n * Currently selected address\n */\n @state()\n private selectedAddress: Address | null = null;\n\n /**\n * Search filter query\n */\n @state()\n private searchQuery: string = '';\n\n /**\n * List of addresses from directory\n */\n @state()\n private addresses: Address[] = [];\n\n /**\n * Loading state\n */\n @state()\n private loading: boolean = false;\n\n /**\n * Has more addresses to load\n */\n @state()\n private hasMore: boolean = false;\n\n /**\n * RxJS subscriptions for cleanup\n */\n private subscriptions: Subscription[] = [];\n\n /**\n * Debounce timer for search\n */\n private searchDebounceTimer: number | null = null;\n\n /**\n * IntersectionObserver for infinite scroll\n */\n private intersectionObserver: IntersectionObserver | null = null;\n\n /**\n * Flag to track if we're auto-loading for search\n */\n @state()\n private isAutoLoadingForSearch: boolean = false;\n\n connectedCallback() {\n super.connectedCallback();\n this.subscribeToDirectory();\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n this.cleanup();\n }\n\n private subscribeToDirectory() {\n if (!this.directory) return;\n\n // Subscribe to addresses\n if (this.directory.addresses$) {\n const addressesSub = this.directory.addresses$.subscribe((addresses) => {\n this.addresses = addresses;\n });\n this.subscriptions.push(addressesSub);\n }\n\n // Subscribe to loading state\n if (this.directory.loading$) {\n const loadingSub = this.directory.loading$.subscribe((loading) => {\n this.loading = loading;\n });\n this.subscriptions.push(loadingSub);\n }\n\n // Subscribe to hasMore\n if (this.directory.hasMore$) {\n const hasMoreSub = this.directory.hasMore$.subscribe((hasMore) => {\n this.hasMore = hasMore;\n });\n this.subscriptions.push(hasMoreSub);\n }\n\n // Load initial data\n if (this.directory.loadMore) {\n this.directory.loadMore();\n }\n }\n\n private cleanup() {\n this.subscriptions.forEach((sub) => sub.unsubscribe());\n this.subscriptions = [];\n if (this.searchDebounceTimer) {\n clearTimeout(this.searchDebounceTimer);\n }\n if (this.intersectionObserver) {\n this.intersectionObserver.disconnect();\n this.intersectionObserver = null;\n }\n }\n\n protected firstUpdated() {\n this.setupInfiniteScroll();\n }\n\n private setupInfiniteScroll() {\n const sentinel = this.shadowRoot?.querySelector('.scroll-sentinel');\n if (!sentinel) return;\n\n this.intersectionObserver = new IntersectionObserver(\n (entries) => {\n const entry = entries[0];\n if (entry?.isIntersecting && this.hasMore && !this.loading) {\n this.handleLoadMore();\n }\n },\n {\n root: this.shadowRoot?.querySelector('.list'),\n rootMargin: '100px',\n threshold: 0\n }\n );\n\n this.intersectionObserver.observe(sentinel);\n }\n\n protected updated(changedProperties: Map<string, unknown>) {\n super.updated(changedProperties);\n\n // Handle directory property changes\n if (changedProperties.has('directory')) {\n this.cleanup();\n this.subscribeToDirectory();\n }\n\n // Re-setup infinite scroll if needed\n if (!this.intersectionObserver) {\n this.setupInfiniteScroll();\n }\n\n // Auto-load more when searching and no results found but more available\n // Also check when loading state changes so we can trigger subsequent loads\n if (\n changedProperties.has('addresses') ||\n changedProperties.has('searchQuery') ||\n changedProperties.has('loading')\n ) {\n this.checkAutoLoadForSearch();\n }\n }\n\n private async checkAutoLoadForSearch() {\n // If we have a search query, no filtered results, but more to load, keep loading\n // Note: !this.loading prevents concurrent loads, isAutoLoadingForSearch is for UI state only\n if (\n this.searchQuery.trim() &&\n this.filteredAddresses.length === 0 &&\n this.hasMore &&\n !this.loading\n ) {\n this.isAutoLoadingForSearch = true;\n await this.handleLoadMore();\n // The updated() will be called again when addresses/loading change, continuing the loop\n } else if (this.filteredAddresses.length > 0 || !this.hasMore) {\n this.isAutoLoadingForSearch = false;\n }\n }\n\n private get filteredAddresses(): Address[] {\n if (!this.searchQuery.trim()) {\n return this.addresses;\n }\n const query = this.searchQuery.toLowerCase();\n return this.addresses.filter(\n (addr) =>\n addr.name.toLowerCase().includes(query) ||\n (addr.displayName && addr.displayName.toLowerCase().includes(query))\n );\n }\n\n private handleSearchInput(e: Event) {\n const input = e.target as HTMLInputElement;\n\n // Debounce search\n if (this.searchDebounceTimer) {\n clearTimeout(this.searchDebounceTimer);\n }\n\n this.searchDebounceTimer = window.setTimeout(() => {\n this.searchQuery = input.value;\n }, 200);\n }\n\n private handleItemClick(address: Address) {\n this.selectedAddress = address;\n\n this.dispatchEvent(\n new CustomEvent('sw-address-select', {\n detail: { address },\n bubbles: true,\n composed: true\n })\n );\n }\n\n private handleItemDoubleClick(address: Address) {\n this.handleDial(address);\n }\n\n private handleDial(address: Address) {\n this.dispatchEvent(\n new CustomEvent('sw-dial', {\n detail: { address },\n bubbles: true,\n composed: true\n })\n );\n }\n\n private async handleLoadMore() {\n if (this.directory?.loadMore) {\n await this.directory.loadMore();\n }\n }\n\n private renderAddressIcon(address: Address) {\n const name = address.type === 'room' ? 'room' : 'person';\n return html`<sw-ui-icon name=${name} size=\"20\"></sw-ui-icon>`;\n }\n\n private renderChannelIcons(address: Address) {\n const channels = address.channels || {};\n return html`\n <div class=\"item-channels\">\n <sw-ui-icon\n name=\"mic-on\"\n size=\"16\"\n class=\"${channels.audio ? 'active' : ''}\"\n title=\"Audio\"\n ></sw-ui-icon>\n <sw-ui-icon\n name=\"camera-on\"\n size=\"16\"\n class=\"${channels.video ? 'active' : ''}\"\n title=\"Video\"\n ></sw-ui-icon>\n </div>\n `;\n }\n\n private renderLoadingIndicator() {\n return html`\n <div class=\"scroll-loading\">\n <div class=\"spinner\"></div>\n <span>${this.isAutoLoadingForSearch ? 'Searching...' : 'Loading more...'}</span>\n </div>\n `;\n }\n\n render() {\n const showInitialLoading = this.loading && this.addresses.length === 0;\n const showEmptyState = !this.loading && this.filteredAddresses.length === 0 && !this.hasMore;\n const showSearchingState = this.isAutoLoadingForSearch && this.filteredAddresses.length === 0;\n\n return html`\n <div class=\"container\" part=\"container\">\n <div class=\"search\" part=\"search\">\n <input\n type=\"text\"\n class=\"search-input\"\n placeholder=\"Search addresses...\"\n @input=${this.handleSearchInput}\n aria-label=\"Search addresses\"\n />\n </div>\n\n <div class=\"list\" part=\"list\" role=\"listbox\">\n ${showInitialLoading\n ? html`<div class=\"loading\">Loading...</div>`\n : showSearchingState\n ? this.renderLoadingIndicator()\n : showEmptyState\n ? html`<div class=\"empty\">No addresses found</div>`\n : html`\n ${this.filteredAddresses.map(\n (address) => html`\n <div\n class=\"item ${this.selectedAddress?.id === address.id ? 'selected' : ''}\"\n part=\"item ${this.selectedAddress?.id === address.id\n ? 'item-selected'\n : ''}\"\n role=\"option\"\n aria-selected=\"${this.selectedAddress?.id === address.id}\"\n @click=${() => this.handleItemClick(address)}\n @dblclick=${() => this.handleItemDoubleClick(address)}\n >\n <div class=\"item-icon\">${this.renderAddressIcon(address)}</div>\n <div class=\"item-content\">\n <div class=\"item-name\" part=\"item-name\">\n ${address.displayName || address.name}\n </div>\n <div class=\"item-type\" part=\"item-type\">\n ${address.type || 'address'}\n </div>\n </div>\n ${this.renderChannelIcons(address)}\n <button\n class=\"dial-button\"\n @click=${(e: Event) => {\n e.stopPropagation();\n this.handleDial(address);\n }}\n aria-label=\"Call ${address.displayName || address.name}\"\n >\n <sw-ui-icon name=\"phone-call\" size=\"18\"></sw-ui-icon>\n </button>\n </div>\n `\n )}\n <!-- Scroll sentinel for infinite scroll -->\n <div class=\"scroll-sentinel\">\n ${this.loading && !this.isAutoLoadingForSearch\n ? this.renderLoadingIndicator()\n : null}\n </div>\n `}\n </div>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'sw-directory': DirectoryComponent;\n }\n}\n"],"names":["DirectoryComponent","LitElement","addressesSub","addresses","loadingSub","loading","hasMoreSub","hasMore","sub","sentinel","_a","entries","entry","_b","changedProperties","query","addr","input","address","name","html","channels","showInitialLoading","showEmptyState","showSearchingState","_c","e","css","__decorateClass","property","state","customElement"],"mappings":"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"}
|