@memberjunction/ng-conversations 6.2.0-edge.3 → 6.2.0-edge.5
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 +33 -7
- package/dist/lib/components/collection/collection-view.component.d.ts.map +1 -1
- package/dist/lib/components/collection/collection-view.component.js +1 -0
- package/dist/lib/components/collection/collection-view.component.js.map +1 -1
- package/dist/lib/components/composer/ai-composer.component.d.ts +14 -2
- package/dist/lib/components/composer/ai-composer.component.d.ts.map +1 -1
- package/dist/lib/components/composer/ai-composer.component.js +35 -4
- package/dist/lib/components/composer/ai-composer.component.js.map +1 -1
- package/dist/lib/components/conversation/conversation-agent-picker.component.d.ts +1 -1
- package/dist/lib/components/conversation/conversation-agent-picker.component.js +3 -3
- package/dist/lib/components/conversation/conversation-agent-picker.component.js.map +1 -1
- package/dist/lib/components/conversation/conversation-chat-area.component.d.ts +651 -53
- package/dist/lib/components/conversation/conversation-chat-area.component.d.ts.map +1 -1
- package/dist/lib/components/conversation/conversation-chat-area.component.js +3002 -661
- package/dist/lib/components/conversation/conversation-chat-area.component.js.map +1 -1
- package/dist/lib/components/conversation/forks-popover.component.d.ts +37 -0
- package/dist/lib/components/conversation/forks-popover.component.d.ts.map +1 -0
- package/dist/lib/components/conversation/forks-popover.component.js +164 -0
- package/dist/lib/components/conversation/forks-popover.component.js.map +1 -0
- package/dist/lib/components/export/export-modal.component.d.ts +7 -2
- package/dist/lib/components/export/export-modal.component.d.ts.map +1 -1
- package/dist/lib/components/export/export-modal.component.js +16 -3
- package/dist/lib/components/export/export-modal.component.js.map +1 -1
- package/dist/lib/components/message/conversation-message-rating.component.d.ts.map +1 -1
- package/dist/lib/components/message/conversation-message-rating.component.js +11 -9
- package/dist/lib/components/message/conversation-message-rating.component.js.map +1 -1
- package/dist/lib/components/message/message-input.component.d.ts +96 -11
- package/dist/lib/components/message/message-input.component.d.ts.map +1 -1
- package/dist/lib/components/message/message-input.component.js +253 -112
- package/dist/lib/components/message/message-input.component.js.map +1 -1
- package/dist/lib/components/message/message-item.component.d.ts +304 -16
- package/dist/lib/components/message/message-item.component.d.ts.map +1 -1
- package/dist/lib/components/message/message-item.component.js +2029 -363
- package/dist/lib/components/message/message-item.component.js.map +1 -1
- package/dist/lib/components/message/message-list.component.d.ts +101 -22
- package/dist/lib/components/message/message-list.component.d.ts.map +1 -1
- package/dist/lib/components/message/message-list.component.js +326 -55
- package/dist/lib/components/message/message-list.component.js.map +1 -1
- package/dist/lib/components/realtime/avatar/realtime-avatar-channel.d.ts +34 -0
- package/dist/lib/components/realtime/avatar/realtime-avatar-channel.d.ts.map +1 -0
- package/dist/lib/components/realtime/avatar/realtime-avatar-channel.js +75 -0
- package/dist/lib/components/realtime/avatar/realtime-avatar-channel.js.map +1 -0
- package/dist/lib/components/realtime/avatar/realtime-avatar-surface.component.d.ts +80 -0
- package/dist/lib/components/realtime/avatar/realtime-avatar-surface.component.d.ts.map +1 -0
- package/dist/lib/components/realtime/avatar/realtime-avatar-surface.component.js +202 -0
- package/dist/lib/components/realtime/avatar/realtime-avatar-surface.component.js.map +1 -0
- package/dist/lib/components/realtime/capture/realtime-camera-check-card.component.d.ts +45 -0
- package/dist/lib/components/realtime/capture/realtime-camera-check-card.component.d.ts.map +1 -0
- package/dist/lib/components/realtime/capture/realtime-camera-check-card.component.js +123 -0
- package/dist/lib/components/realtime/capture/realtime-camera-check-card.component.js.map +1 -0
- package/dist/lib/components/realtime/capture/realtime-capture-channel.d.ts +90 -0
- package/dist/lib/components/realtime/capture/realtime-capture-channel.d.ts.map +1 -0
- package/dist/lib/components/realtime/capture/realtime-capture-channel.js +223 -0
- package/dist/lib/components/realtime/capture/realtime-capture-channel.js.map +1 -0
- package/dist/lib/components/realtime/capture/realtime-capture-model.d.ts +98 -0
- package/dist/lib/components/realtime/capture/realtime-capture-model.d.ts.map +1 -0
- package/dist/lib/components/realtime/capture/realtime-capture-model.js +161 -0
- package/dist/lib/components/realtime/capture/realtime-capture-model.js.map +1 -0
- package/dist/lib/components/realtime/capture/realtime-capture-surface.component.d.ts +48 -0
- package/dist/lib/components/realtime/capture/realtime-capture-surface.component.d.ts.map +1 -0
- package/dist/lib/components/realtime/capture/realtime-capture-surface.component.js +205 -0
- package/dist/lib/components/realtime/capture/realtime-capture-surface.component.js.map +1 -0
- package/dist/lib/components/realtime/channels/client-context-channel.d.ts +19 -2
- package/dist/lib/components/realtime/channels/client-context-channel.d.ts.map +1 -1
- package/dist/lib/components/realtime/channels/client-context-channel.js +83 -9
- package/dist/lib/components/realtime/channels/client-context-channel.js.map +1 -1
- package/dist/lib/components/realtime/channels/realtime-channel-pane.component.d.ts +30 -9
- package/dist/lib/components/realtime/channels/realtime-channel-pane.component.d.ts.map +1 -1
- package/dist/lib/components/realtime/channels/realtime-channel-pane.component.js +78 -14
- package/dist/lib/components/realtime/channels/realtime-channel-pane.component.js.map +1 -1
- package/dist/lib/components/realtime/identity-verification/identity-verification-channel.d.ts +71 -0
- package/dist/lib/components/realtime/identity-verification/identity-verification-channel.d.ts.map +1 -0
- package/dist/lib/components/realtime/identity-verification/identity-verification-channel.js +259 -0
- package/dist/lib/components/realtime/identity-verification/identity-verification-channel.js.map +1 -0
- package/dist/lib/components/realtime/identity-verification/identity-verification-model.d.ts +129 -0
- package/dist/lib/components/realtime/identity-verification/identity-verification-model.d.ts.map +1 -0
- package/dist/lib/components/realtime/identity-verification/identity-verification-model.js +373 -0
- package/dist/lib/components/realtime/identity-verification/identity-verification-model.js.map +1 -0
- package/dist/lib/components/realtime/identity-verification/identity-verification-surface.component.d.ts +77 -0
- package/dist/lib/components/realtime/identity-verification/identity-verification-surface.component.d.ts.map +1 -0
- package/dist/lib/components/realtime/identity-verification/identity-verification-surface.component.js +420 -0
- package/dist/lib/components/realtime/identity-verification/identity-verification-surface.component.js.map +1 -0
- package/dist/lib/components/realtime/interactive-component/component-contract.d.ts +83 -0
- package/dist/lib/components/realtime/interactive-component/component-contract.d.ts.map +1 -0
- package/dist/lib/components/realtime/interactive-component/component-contract.js +292 -0
- package/dist/lib/components/realtime/interactive-component/component-contract.js.map +1 -0
- package/dist/lib/components/realtime/interactive-component/component-data-state.d.ts +39 -0
- package/dist/lib/components/realtime/interactive-component/component-data-state.d.ts.map +1 -0
- package/dist/lib/components/realtime/interactive-component/component-data-state.js +152 -0
- package/dist/lib/components/realtime/interactive-component/component-data-state.js.map +1 -0
- package/dist/lib/components/realtime/interactive-component/component-instance-engine.d.ts +109 -0
- package/dist/lib/components/realtime/interactive-component/component-instance-engine.d.ts.map +1 -0
- package/dist/lib/components/realtime/interactive-component/component-instance-engine.js +146 -0
- package/dist/lib/components/realtime/interactive-component/component-instance-engine.js.map +1 -0
- package/dist/lib/components/realtime/interactive-component/component-spec-content.d.ts +19 -0
- package/dist/lib/components/realtime/interactive-component/component-spec-content.d.ts.map +1 -0
- package/dist/lib/components/realtime/interactive-component/component-spec-content.js +39 -0
- package/dist/lib/components/realtime/interactive-component/component-spec-content.js.map +1 -0
- package/dist/lib/components/realtime/interactive-component/interactive-component-channel.d.ts +183 -0
- package/dist/lib/components/realtime/interactive-component/interactive-component-channel.d.ts.map +1 -0
- package/dist/lib/components/realtime/interactive-component/interactive-component-channel.js +761 -0
- package/dist/lib/components/realtime/interactive-component/interactive-component-channel.js.map +1 -0
- package/dist/lib/components/realtime/interactive-component/interactive-component-config.d.ts +25 -0
- package/dist/lib/components/realtime/interactive-component/interactive-component-config.d.ts.map +1 -0
- package/dist/lib/components/realtime/interactive-component/interactive-component-config.js +57 -0
- package/dist/lib/components/realtime/interactive-component/interactive-component-config.js.map +1 -0
- package/dist/lib/components/realtime/interactive-component/interactive-component-host.component.d.ts +40 -0
- package/dist/lib/components/realtime/interactive-component/interactive-component-host.component.d.ts.map +1 -0
- package/dist/lib/components/realtime/interactive-component/interactive-component-host.component.js +97 -0
- package/dist/lib/components/realtime/interactive-component/interactive-component-host.component.js.map +1 -0
- package/dist/lib/components/realtime/interactive-component/interactive-component-types.d.ts +144 -0
- package/dist/lib/components/realtime/interactive-component/interactive-component-types.d.ts.map +1 -0
- package/dist/lib/components/realtime/interactive-component/interactive-component-types.js +57 -0
- package/dist/lib/components/realtime/interactive-component/interactive-component-types.js.map +1 -0
- package/dist/lib/components/realtime/interactive-component/react-component-handle.d.ts +36 -0
- package/dist/lib/components/realtime/interactive-component/react-component-handle.d.ts.map +1 -0
- package/dist/lib/components/realtime/interactive-component/react-component-handle.js +55 -0
- package/dist/lib/components/realtime/interactive-component/react-component-handle.js.map +1 -0
- package/dist/lib/components/realtime/interactive-component/realtime-interactive-component-surface.component.d.ts +55 -0
- package/dist/lib/components/realtime/interactive-component/realtime-interactive-component-surface.component.d.ts.map +1 -0
- package/dist/lib/components/realtime/interactive-component/realtime-interactive-component-surface.component.js +210 -0
- package/dist/lib/components/realtime/interactive-component/realtime-interactive-component-surface.component.js.map +1 -0
- package/dist/lib/components/realtime/interactive-component/run-view-component-artifact-source.d.ts +32 -0
- package/dist/lib/components/realtime/interactive-component/run-view-component-artifact-source.d.ts.map +1 -0
- package/dist/lib/components/realtime/interactive-component/run-view-component-artifact-source.js +90 -0
- package/dist/lib/components/realtime/interactive-component/run-view-component-artifact-source.js.map +1 -0
- package/dist/lib/components/realtime/media/media-channel.d.ts +7 -0
- package/dist/lib/components/realtime/media/media-channel.d.ts.map +1 -1
- package/dist/lib/components/realtime/media/media-channel.js +28 -1
- package/dist/lib/components/realtime/media/media-channel.js.map +1 -1
- package/dist/lib/components/realtime/realtime-agent-banner.component.d.ts +8 -1
- package/dist/lib/components/realtime/realtime-agent-banner.component.d.ts.map +1 -1
- package/dist/lib/components/realtime/realtime-agent-banner.component.js +89 -71
- package/dist/lib/components/realtime/realtime-agent-banner.component.js.map +1 -1
- package/dist/lib/components/realtime/realtime-agent-orb.component.d.ts +21 -0
- package/dist/lib/components/realtime/realtime-agent-orb.component.d.ts.map +1 -0
- package/dist/lib/components/realtime/realtime-agent-orb.component.js +49 -0
- package/dist/lib/components/realtime/realtime-agent-orb.component.js.map +1 -0
- package/dist/lib/components/realtime/realtime-agent-picker.component.d.ts +44 -11
- package/dist/lib/components/realtime/realtime-agent-picker.component.d.ts.map +1 -1
- package/dist/lib/components/realtime/realtime-agent-picker.component.js +162 -50
- package/dist/lib/components/realtime/realtime-agent-picker.component.js.map +1 -1
- package/dist/lib/components/realtime/realtime-audio-visuals.d.ts +8 -2
- package/dist/lib/components/realtime/realtime-audio-visuals.d.ts.map +1 -1
- package/dist/lib/components/realtime/realtime-audio-visuals.js +14 -18
- package/dist/lib/components/realtime/realtime-audio-visuals.js.map +1 -1
- package/dist/lib/components/realtime/realtime-composer.component.d.ts +42 -2
- package/dist/lib/components/realtime/realtime-composer.component.d.ts.map +1 -1
- package/dist/lib/components/realtime/realtime-composer.component.js +137 -102
- package/dist/lib/components/realtime/realtime-composer.component.js.map +1 -1
- package/dist/lib/components/realtime/realtime-perception-chip.component.d.ts +71 -0
- package/dist/lib/components/realtime/realtime-perception-chip.component.d.ts.map +1 -0
- package/dist/lib/components/realtime/realtime-perception-chip.component.js +221 -0
- package/dist/lib/components/realtime/realtime-perception-chip.component.js.map +1 -0
- package/dist/lib/components/realtime/realtime-session-overlay.component.d.ts +264 -22
- package/dist/lib/components/realtime/realtime-session-overlay.component.d.ts.map +1 -1
- package/dist/lib/components/realtime/realtime-session-overlay.component.js +851 -135
- package/dist/lib/components/realtime/realtime-session-overlay.component.js.map +1 -1
- package/dist/lib/components/realtime/realtime-surface-placement-prefs.d.ts +14 -0
- package/dist/lib/components/realtime/realtime-surface-placement-prefs.d.ts.map +1 -0
- package/dist/lib/components/realtime/realtime-surface-placement-prefs.js +14 -0
- package/dist/lib/components/realtime/realtime-surface-placement-prefs.js.map +1 -0
- package/dist/lib/components/realtime/realtime-surface-stage.model.d.ts +74 -0
- package/dist/lib/components/realtime/realtime-surface-stage.model.d.ts.map +1 -0
- package/dist/lib/components/realtime/realtime-surface-stage.model.js +171 -0
- package/dist/lib/components/realtime/realtime-surface-stage.model.js.map +1 -0
- package/dist/lib/components/realtime/realtime-surface-tabs.component.d.ts +71 -13
- package/dist/lib/components/realtime/realtime-surface-tabs.component.d.ts.map +1 -1
- package/dist/lib/components/realtime/realtime-surface-tabs.component.js +232 -73
- package/dist/lib/components/realtime/realtime-surface-tabs.component.js.map +1 -1
- package/dist/lib/components/realtime/realtime-surface-tabs.model.d.ts +5 -0
- package/dist/lib/components/realtime/realtime-surface-tabs.model.d.ts.map +1 -1
- package/dist/lib/components/realtime/realtime-surface-tabs.model.js +8 -0
- package/dist/lib/components/realtime/realtime-surface-tabs.model.js.map +1 -1
- package/dist/lib/components/realtime/realtime-ui-config.d.ts +12 -2
- package/dist/lib/components/realtime/realtime-ui-config.d.ts.map +1 -1
- package/dist/lib/components/realtime/realtime-ui-config.js +5 -1
- package/dist/lib/components/realtime/realtime-ui-config.js.map +1 -1
- package/dist/lib/components/realtime/remote-browser/remote-browser-channel.d.ts +10 -1
- package/dist/lib/components/realtime/remote-browser/remote-browser-channel.d.ts.map +1 -1
- package/dist/lib/components/realtime/remote-browser/remote-browser-channel.js +42 -2
- package/dist/lib/components/realtime/remote-browser/remote-browser-channel.js.map +1 -1
- package/dist/lib/components/realtime/remote-browser/remote-browser-surface.component.d.ts +20 -3
- package/dist/lib/components/realtime/remote-browser/remote-browser-surface.component.d.ts.map +1 -1
- package/dist/lib/components/realtime/remote-browser/remote-browser-surface.component.js +44 -10
- package/dist/lib/components/realtime/remote-browser/remote-browser-surface.component.js.map +1 -1
- package/dist/lib/components/realtime/whiteboard/whiteboard-channel.d.ts +28 -44
- package/dist/lib/components/realtime/whiteboard/whiteboard-channel.d.ts.map +1 -1
- package/dist/lib/components/realtime/whiteboard/whiteboard-channel.js +76 -162
- package/dist/lib/components/realtime/whiteboard/whiteboard-channel.js.map +1 -1
- package/dist/lib/components/search/search-panel.component.d.ts +2 -0
- package/dist/lib/components/search/search-panel.component.d.ts.map +1 -1
- package/dist/lib/components/search/search-panel.component.js +25 -12
- package/dist/lib/components/search/search-panel.component.js.map +1 -1
- package/dist/lib/components/sidebar/routines-section.component.js +1 -1
- package/dist/lib/components/sidebar/routines-section.component.js.map +1 -1
- package/dist/lib/components/task/tasks-full-view.component.d.ts +152 -31
- package/dist/lib/components/task/tasks-full-view.component.d.ts.map +1 -1
- package/dist/lib/components/task/tasks-full-view.component.js +2227 -214
- package/dist/lib/components/task/tasks-full-view.component.js.map +1 -1
- package/dist/lib/components/tasks/tasks-dropdown.component.js +4 -4
- package/dist/lib/components/tasks/tasks-dropdown.component.js.map +1 -1
- package/dist/lib/components/workspace/conversation-workspace.component.d.ts +33 -32
- package/dist/lib/components/workspace/conversation-workspace.component.d.ts.map +1 -1
- package/dist/lib/components/workspace/conversation-workspace.component.js +72 -88
- package/dist/lib/components/workspace/conversation-workspace.component.js.map +1 -1
- package/dist/lib/conversations.module.d.ts +30 -29
- package/dist/lib/conversations.module.d.ts.map +1 -1
- package/dist/lib/conversations.module.js +27 -5
- package/dist/lib/conversations.module.js.map +1 -1
- package/dist/lib/events/chat-events.d.ts +25 -0
- package/dist/lib/events/chat-events.d.ts.map +1 -1
- package/dist/lib/events/chat-events.js +36 -0
- package/dist/lib/events/chat-events.js.map +1 -1
- package/dist/lib/models/agent-turn.model.d.ts +5 -0
- package/dist/lib/models/agent-turn.model.d.ts.map +1 -1
- package/dist/lib/models/agent-turn.model.js.map +1 -1
- package/dist/lib/services/agent-state.service.d.ts +34 -8
- package/dist/lib/services/agent-state.service.d.ts.map +1 -1
- package/dist/lib/services/agent-state.service.js +90 -37
- package/dist/lib/services/agent-state.service.js.map +1 -1
- package/dist/lib/services/artifact-state.service.d.ts +0 -9
- package/dist/lib/services/artifact-state.service.d.ts.map +1 -1
- package/dist/lib/services/artifact-state.service.js +1 -32
- package/dist/lib/services/artifact-state.service.js.map +1 -1
- package/dist/lib/services/browser-realtime-media-host.d.ts +19 -7
- package/dist/lib/services/browser-realtime-media-host.d.ts.map +1 -1
- package/dist/lib/services/browser-realtime-media-host.js +21 -72
- package/dist/lib/services/browser-realtime-media-host.js.map +1 -1
- package/dist/lib/services/conversation-agent.service.d.ts +48 -16
- package/dist/lib/services/conversation-agent.service.d.ts.map +1 -1
- package/dist/lib/services/conversation-agent.service.js +110 -35
- package/dist/lib/services/conversation-agent.service.js.map +1 -1
- package/dist/lib/services/conversation-detail-window.store.d.ts +22 -4
- package/dist/lib/services/conversation-detail-window.store.d.ts.map +1 -1
- package/dist/lib/services/conversation-detail-window.store.js +50 -9
- package/dist/lib/services/conversation-detail-window.store.js.map +1 -1
- package/dist/lib/services/conversation-naming.d.ts +72 -22
- package/dist/lib/services/conversation-naming.d.ts.map +1 -1
- package/dist/lib/services/conversation-naming.js +93 -12
- package/dist/lib/services/conversation-naming.js.map +1 -1
- package/dist/lib/services/conversation-tasks-filter.d.ts +15 -0
- package/dist/lib/services/conversation-tasks-filter.d.ts.map +1 -0
- package/dist/lib/services/conversation-tasks-filter.js +69 -0
- package/dist/lib/services/conversation-tasks-filter.js.map +1 -0
- package/dist/lib/services/data-cache.service.d.ts +13 -5
- package/dist/lib/services/data-cache.service.d.ts.map +1 -1
- package/dist/lib/services/data-cache.service.js +39 -19
- package/dist/lib/services/data-cache.service.js.map +1 -1
- package/dist/lib/services/export.service.d.ts +26 -9
- package/dist/lib/services/export.service.d.ts.map +1 -1
- package/dist/lib/services/export.service.js +61 -18
- package/dist/lib/services/export.service.js.map +1 -1
- package/dist/lib/services/realtime-audio-recorder.d.ts +115 -79
- package/dist/lib/services/realtime-audio-recorder.d.ts.map +1 -1
- package/dist/lib/services/realtime-audio-recorder.js +273 -186
- package/dist/lib/services/realtime-audio-recorder.js.map +1 -1
- package/dist/lib/services/realtime-pairing.d.ts +10 -5
- package/dist/lib/services/realtime-pairing.d.ts.map +1 -1
- package/dist/lib/services/realtime-pairing.js +15 -6
- package/dist/lib/services/realtime-pairing.js.map +1 -1
- package/dist/lib/services/realtime-session.service.d.ts +31 -2
- package/dist/lib/services/realtime-session.service.d.ts.map +1 -1
- package/dist/lib/services/realtime-session.service.js +34 -2
- package/dist/lib/services/realtime-session.service.js.map +1 -1
- package/dist/lib/services/recording/libopus-wasm-binary.d.ts +3 -0
- package/dist/lib/services/recording/libopus-wasm-binary.d.ts.map +1 -0
- package/dist/lib/services/recording/libopus-wasm-binary.js +489 -0
- package/dist/lib/services/recording/libopus-wasm-binary.js.map +1 -0
- package/dist/lib/services/recording/libopus-worker-source.d.ts +48 -0
- package/dist/lib/services/recording/libopus-worker-source.d.ts.map +1 -0
- package/dist/lib/services/recording/libopus-worker-source.js +170 -0
- package/dist/lib/services/recording/libopus-worker-source.js.map +1 -0
- package/dist/lib/services/recording/linear-resampler.d.ts +45 -0
- package/dist/lib/services/recording/linear-resampler.d.ts.map +1 -0
- package/dist/lib/services/recording/linear-resampler.js +85 -0
- package/dist/lib/services/recording/linear-resampler.js.map +1 -0
- package/dist/lib/services/recording/opus-packet-encoder.d.ts +50 -0
- package/dist/lib/services/recording/opus-packet-encoder.d.ts.map +1 -0
- package/dist/lib/services/recording/opus-packet-encoder.js +41 -0
- package/dist/lib/services/recording/opus-packet-encoder.js.map +1 -0
- package/dist/lib/services/recording/wasm-opus-encoder.d.ts +86 -0
- package/dist/lib/services/recording/wasm-opus-encoder.d.ts.map +1 -0
- package/dist/lib/services/recording/wasm-opus-encoder.js +232 -0
- package/dist/lib/services/recording/wasm-opus-encoder.js.map +1 -0
- package/dist/lib/services/recording/webcodecs-opus-encoder.d.ts +39 -0
- package/dist/lib/services/recording/webcodecs-opus-encoder.d.ts.map +1 -0
- package/dist/lib/services/recording/webcodecs-opus-encoder.js +101 -0
- package/dist/lib/services/recording/webcodecs-opus-encoder.js.map +1 -0
- package/dist/lib/services/search.service.d.ts +7 -2
- package/dist/lib/services/search.service.d.ts.map +1 -1
- package/dist/lib/services/search.service.js +16 -20
- package/dist/lib/services/search.service.js.map +1 -1
- package/dist/lib/utils/conversation-branching.d.ts +4 -0
- package/dist/lib/utils/conversation-branching.d.ts.map +1 -0
- package/dist/lib/utils/conversation-branching.js +5 -0
- package/dist/lib/utils/conversation-branching.js.map +1 -0
- package/dist/lib/utils/conversation-forks.d.ts +315 -0
- package/dist/lib/utils/conversation-forks.d.ts.map +1 -0
- package/dist/lib/utils/conversation-forks.js +456 -0
- package/dist/lib/utils/conversation-forks.js.map +1 -0
- package/dist/lib/utils/distinct-artifacts.d.ts +9 -3
- package/dist/lib/utils/distinct-artifacts.d.ts.map +1 -1
- package/dist/lib/utils/distinct-artifacts.js +24 -5
- package/dist/lib/utils/distinct-artifacts.js.map +1 -1
- package/dist/public-api.d.ts +23 -1
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +30 -1
- package/dist/public-api.js.map +1 -1
- package/package.json +37 -33
- package/dist/lib/components/thread/thread-panel.component.d.ts +0 -126
- package/dist/lib/components/thread/thread-panel.component.d.ts.map +0 -1
- package/dist/lib/components/thread/thread-panel.component.js +0 -440
- package/dist/lib/components/thread/thread-panel.component.js.map +0 -1
- package/dist/lib/services/realtime-pcm-wav.d.ts +0 -79
- package/dist/lib/services/realtime-pcm-wav.d.ts.map +0 -1
- package/dist/lib/services/realtime-pcm-wav.js +0 -213
- package/dist/lib/services/realtime-pcm-wav.js.map +0 -1
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { OnDestroy } from '@angular/core';
|
|
2
|
+
import type { JSONObject } from '@memberjunction/ai';
|
|
3
|
+
import type { RealtimeChannelVerbResult } from '@memberjunction/realtime-runtime';
|
|
4
|
+
import { IdentityVerificationModel, type IdentityField, type IdentityVerificationView } from './identity-verification-model';
|
|
5
|
+
import * as i0 from "@angular/core";
|
|
6
|
+
/** Sends one of the user's actions to the channel (which runs it as the `user`). */
|
|
7
|
+
export type IdentityVerificationDispatch = (verb: string, args: JSONObject) => Promise<RealtimeChannelVerbResult>;
|
|
8
|
+
/**
|
|
9
|
+
* The IDENTITY VERIFICATION surface (`mj-identity-verification-surface`) — a small, accessible form that
|
|
10
|
+
* renders the channel's state and sends the user's own actions back through it. It owns no rules: whether
|
|
11
|
+
* a value counts as confirmed, whether a code can be sent, what a failure means are the
|
|
12
|
+
* {@link IdentityVerificationModel}'s decisions; this only shows them.
|
|
13
|
+
*
|
|
14
|
+
* Details the agent filled in are marked "Suggested" and carry a Confirm control until the user approves
|
|
15
|
+
* them; a value the user types is theirs and needs no confirmation. Mobile-first: one column, 44px tap
|
|
16
|
+
* targets, 16px inputs (no iOS zoom), the right keyboard and autofill hints per field. Colour comes only
|
|
17
|
+
* from `--mj-*` design tokens, so it follows the host's theme (including dark mode).
|
|
18
|
+
*/
|
|
19
|
+
export declare class IdentityVerificationSurfaceComponent implements OnDestroy {
|
|
20
|
+
private readonly cdr;
|
|
21
|
+
private modelSub;
|
|
22
|
+
private tick;
|
|
23
|
+
private model;
|
|
24
|
+
/** The current snapshot, or `null` until a model is bound. */
|
|
25
|
+
View: IdentityVerificationView | null;
|
|
26
|
+
/** Name of the agent, for the "Suggested by …" marker. */
|
|
27
|
+
AgentName: string;
|
|
28
|
+
/** Seconds until another send is allowed (0 = now). Recomputed on a 1s tick while a cooldown runs. */
|
|
29
|
+
ResendWaitSeconds: number;
|
|
30
|
+
/** True while an action is in flight from THIS surface (disables double-submits). */
|
|
31
|
+
Busy: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Why the user's last action was refused before it reached the server (a malformed email, a missing
|
|
34
|
+
* detail) — the model's own `Problem` only covers what the SERVER said. Cleared by the next action.
|
|
35
|
+
*/
|
|
36
|
+
ActionProblem: string;
|
|
37
|
+
/** The code the user is typing. Never leaves this component except through {@link SubmitCode}. */
|
|
38
|
+
CodeDraft: string;
|
|
39
|
+
/** The unconfirmed drafts the user is typing, per field. */
|
|
40
|
+
Drafts: Record<IdentityField, string>;
|
|
41
|
+
/** Where the user's actions go — wired by the channel; a no-op until then. */
|
|
42
|
+
Dispatch: IdentityVerificationDispatch;
|
|
43
|
+
private codeInput?;
|
|
44
|
+
/** The state engine this surface renders. */
|
|
45
|
+
set Model(value: IdentityVerificationModel | null);
|
|
46
|
+
get Model(): IdentityVerificationModel | null;
|
|
47
|
+
ngOnDestroy(): void;
|
|
48
|
+
/** What to show in an input: the user's draft, else the stored value. */
|
|
49
|
+
ValueFor(field: IdentityField): string;
|
|
50
|
+
/** The agent or host suggested this value and the user has not approved it yet. */
|
|
51
|
+
IsSuggested(field: IdentityField): boolean;
|
|
52
|
+
/** Who suggested it, for the label. */
|
|
53
|
+
SuggestedBy(field: IdentityField): string;
|
|
54
|
+
get Locked(): boolean;
|
|
55
|
+
get CodeStage(): boolean;
|
|
56
|
+
OnDraft(field: IdentityField, event: Event): void;
|
|
57
|
+
/** Commits what the user typed in a field (blur / Enter) — the user's own value, confirmed by being theirs. */
|
|
58
|
+
CommitField(field: IdentityField): Promise<void>;
|
|
59
|
+
ConfirmField(field: IdentityField): Promise<void>;
|
|
60
|
+
ConfirmAll(): Promise<void>;
|
|
61
|
+
SendCode(): Promise<void>;
|
|
62
|
+
Resend(): Promise<void>;
|
|
63
|
+
OnCodeInput(event: Event): void;
|
|
64
|
+
SubmitCode(): Promise<void>;
|
|
65
|
+
get HasUnconfirmed(): boolean;
|
|
66
|
+
private fieldView;
|
|
67
|
+
/** Commits fields the user typed but did not blur out of, so pressing "Send code" never drops them. */
|
|
68
|
+
private commitPendingDrafts;
|
|
69
|
+
private run;
|
|
70
|
+
private onView;
|
|
71
|
+
private syncCooldown;
|
|
72
|
+
private onTick;
|
|
73
|
+
private stopTick;
|
|
74
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<IdentityVerificationSurfaceComponent, never>;
|
|
75
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<IdentityVerificationSurfaceComponent, "mj-identity-verification-surface", never, { "AgentName": { "alias": "AgentName"; "required": false; }; "Dispatch": { "alias": "Dispatch"; "required": false; }; "Model": { "alias": "Model"; "required": false; }; }, {}, never, never, true, never>;
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=identity-verification-surface.component.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity-verification-surface.component.d.ts","sourceRoot":"","sources":["../../../../../src/lib/components/realtime/identity-verification/identity-verification-surface.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4E,SAAS,EAAqB,MAAM,eAAe,CAAC;AAEvI,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,kCAAkC,CAAC;AAElF,OAAO,EAAE,yBAAyB,EAAE,KAAK,aAAa,EAAE,KAAK,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;;AAE7H,oFAAoF;AACpF,MAAM,MAAM,4BAA4B,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,KAAK,OAAO,CAAC,yBAAyB,CAAC,CAAC;AAElH;;;;;;;;;;GAUG;AACH,qBAQa,oCAAqC,YAAW,SAAS;IACpE,OAAO,CAAC,QAAQ,CAAC,GAAG,CAA6B;IACjD,OAAO,CAAC,QAAQ,CAA6B;IAC7C,OAAO,CAAC,IAAI,CAA+C;IAC3D,OAAO,CAAC,KAAK,CAA0C;IAEvD,8DAA8D;IACvD,IAAI,EAAE,wBAAwB,GAAG,IAAI,CAAQ;IAEpD,0DAA0D;IACjD,SAAS,SAAmB;IAErC,sGAAsG;IAC/F,iBAAiB,SAAK;IAE7B,qFAAqF;IAC9E,IAAI,UAAS;IAEpB;;;OAGG;IACI,aAAa,SAAM;IAE1B,kGAAkG;IAC3F,SAAS,SAAM;IAEtB,4DAA4D;IACrD,MAAM,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAA2B;IAEvE,8EAA8E;IACrE,QAAQ,EAAE,4BAA4B,CAA6D;IAEpF,OAAO,CAAC,SAAS,CAAC,CAA+B;IAEzE,6CAA6C;IAC7C,IACW,KAAK,CAAC,KAAK,EAAE,yBAAyB,GAAG,IAAI,EAOvD;IACD,IAAW,KAAK,IAAI,yBAAyB,GAAG,IAAI,CAEnD;IAEM,WAAW,IAAI,IAAI;IAO1B,yEAAyE;IAClE,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM;IAI7C,mFAAmF;IAC5E,WAAW,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO;IAKjD,uCAAuC;IAChC,WAAW,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM;IAIhD,IAAW,MAAM,IAAI,OAAO,CAE3B;IAED,IAAW,SAAS,IAAI,OAAO,CAE9B;IAIM,OAAO,CAAC,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI;IAIxD,+GAA+G;IAClG,WAAW,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAchD,YAAY,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAIjD,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAKzB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAI7B,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAIzB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAYxC,IAAW,cAAc,IAAI,OAAO,CAEnC;IAID,OAAO,CAAC,SAAS;IAIjB,uGAAuG;YACzF,mBAAmB;YAQnB,GAAG;IAajB,OAAO,CAAC,MAAM;IAWd,OAAO,CAAC,YAAY;IAUpB,OAAO,CAAC,MAAM;IAKd,OAAO,CAAC,QAAQ;yCAhML,oCAAoC;2CAApC,oCAAoC;CAsMhD"}
|
|
@@ -0,0 +1,420 @@
|
|
|
1
|
+
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, ViewChild, inject } from '@angular/core';
|
|
2
|
+
import { MJButtonDirective } from '@memberjunction/ng-ui-components';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
const _c0 = ["codeInput"];
|
|
5
|
+
function IdentityVerificationSurfaceComponent_Conditional_0_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
6
|
+
i0.ɵɵelementStart(0, "div", 3);
|
|
7
|
+
i0.ɵɵelement(1, "i", 4);
|
|
8
|
+
i0.ɵɵelementStart(2, "div")(3, "p", 5);
|
|
9
|
+
i0.ɵɵtext(4, "You're verified");
|
|
10
|
+
i0.ɵɵelementEnd();
|
|
11
|
+
i0.ɵɵelementStart(5, "p", 6);
|
|
12
|
+
i0.ɵɵtext(6);
|
|
13
|
+
i0.ɵɵelementEnd()()();
|
|
14
|
+
} if (rf & 2) {
|
|
15
|
+
const view_r1 = i0.ɵɵnextContext();
|
|
16
|
+
i0.ɵɵadvance(6);
|
|
17
|
+
i0.ɵɵtextInterpolate2("", view_r1.Name.Value, " \u00B7 ", view_r1.Email.Value);
|
|
18
|
+
} }
|
|
19
|
+
function IdentityVerificationSurfaceComponent_Conditional_0_Conditional_4_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
20
|
+
const _r4 = i0.ɵɵgetCurrentView();
|
|
21
|
+
i0.ɵɵelementStart(0, "p", 11);
|
|
22
|
+
i0.ɵɵelement(1, "i", 18);
|
|
23
|
+
i0.ɵɵtext(2);
|
|
24
|
+
i0.ɵɵelementStart(3, "button", 19);
|
|
25
|
+
i0.ɵɵlistener("click", function IdentityVerificationSurfaceComponent_Conditional_0_Conditional_4_Conditional_6_Template_button_click_3_listener() { i0.ɵɵrestoreView(_r4); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.ConfirmField("name")); });
|
|
26
|
+
i0.ɵɵtext(4, "Confirm");
|
|
27
|
+
i0.ɵɵelementEnd()();
|
|
28
|
+
} if (rf & 2) {
|
|
29
|
+
const ctx_r2 = i0.ɵɵnextContext(3);
|
|
30
|
+
i0.ɵɵadvance(2);
|
|
31
|
+
i0.ɵɵtextInterpolate1(" Suggested by ", ctx_r2.SuggestedBy("name"), " \u2014 check it's right. ");
|
|
32
|
+
i0.ɵɵadvance();
|
|
33
|
+
i0.ɵɵproperty("disabled", ctx_r2.Busy);
|
|
34
|
+
} }
|
|
35
|
+
function IdentityVerificationSurfaceComponent_Conditional_0_Conditional_4_Conditional_11_Template(rf, ctx) { if (rf & 1) {
|
|
36
|
+
const _r5 = i0.ɵɵgetCurrentView();
|
|
37
|
+
i0.ɵɵelementStart(0, "p", 14);
|
|
38
|
+
i0.ɵɵelement(1, "i", 18);
|
|
39
|
+
i0.ɵɵtext(2);
|
|
40
|
+
i0.ɵɵelementStart(3, "button", 19);
|
|
41
|
+
i0.ɵɵlistener("click", function IdentityVerificationSurfaceComponent_Conditional_0_Conditional_4_Conditional_11_Template_button_click_3_listener() { i0.ɵɵrestoreView(_r5); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.ConfirmField("email")); });
|
|
42
|
+
i0.ɵɵtext(4, "Confirm");
|
|
43
|
+
i0.ɵɵelementEnd()();
|
|
44
|
+
} if (rf & 2) {
|
|
45
|
+
const ctx_r2 = i0.ɵɵnextContext(3);
|
|
46
|
+
i0.ɵɵadvance(2);
|
|
47
|
+
i0.ɵɵtextInterpolate1(" Suggested by ", ctx_r2.SuggestedBy("email"), " \u2014 check it's right. ");
|
|
48
|
+
i0.ɵɵadvance();
|
|
49
|
+
i0.ɵɵproperty("disabled", ctx_r2.Busy);
|
|
50
|
+
} }
|
|
51
|
+
function IdentityVerificationSurfaceComponent_Conditional_0_Conditional_4_Conditional_12_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
52
|
+
const _r7 = i0.ɵɵgetCurrentView();
|
|
53
|
+
i0.ɵɵelementStart(0, "button", 22);
|
|
54
|
+
i0.ɵɵlistener("click", function IdentityVerificationSurfaceComponent_Conditional_0_Conditional_4_Conditional_12_Conditional_1_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r7); const ctx_r2 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r2.ConfirmAll()); });
|
|
55
|
+
i0.ɵɵtext(1, "Confirm details");
|
|
56
|
+
i0.ɵɵelementEnd();
|
|
57
|
+
} if (rf & 2) {
|
|
58
|
+
const ctx_r2 = i0.ɵɵnextContext(4);
|
|
59
|
+
i0.ɵɵproperty("disabled", ctx_r2.Busy || ctx_r2.Locked);
|
|
60
|
+
} }
|
|
61
|
+
function IdentityVerificationSurfaceComponent_Conditional_0_Conditional_4_Conditional_12_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
62
|
+
i0.ɵɵtext(0, " Sending\u2026 ");
|
|
63
|
+
} }
|
|
64
|
+
function IdentityVerificationSurfaceComponent_Conditional_0_Conditional_4_Conditional_12_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
65
|
+
i0.ɵɵtext(0, " Send code ");
|
|
66
|
+
} }
|
|
67
|
+
function IdentityVerificationSurfaceComponent_Conditional_0_Conditional_4_Conditional_12_Template(rf, ctx) { if (rf & 1) {
|
|
68
|
+
const _r6 = i0.ɵɵgetCurrentView();
|
|
69
|
+
i0.ɵɵelementStart(0, "div", 15);
|
|
70
|
+
i0.ɵɵconditionalCreate(1, IdentityVerificationSurfaceComponent_Conditional_0_Conditional_4_Conditional_12_Conditional_1_Template, 2, 1, "button", 20);
|
|
71
|
+
i0.ɵɵelementStart(2, "button", 21);
|
|
72
|
+
i0.ɵɵlistener("click", function IdentityVerificationSurfaceComponent_Conditional_0_Conditional_4_Conditional_12_Template_button_click_2_listener() { i0.ɵɵrestoreView(_r6); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.SendCode()); });
|
|
73
|
+
i0.ɵɵconditionalCreate(3, IdentityVerificationSurfaceComponent_Conditional_0_Conditional_4_Conditional_12_Conditional_3_Template, 1, 0)(4, IdentityVerificationSurfaceComponent_Conditional_0_Conditional_4_Conditional_12_Conditional_4_Template, 1, 0);
|
|
74
|
+
i0.ɵɵelementEnd()();
|
|
75
|
+
} if (rf & 2) {
|
|
76
|
+
const view_r1 = i0.ɵɵnextContext(2);
|
|
77
|
+
const ctx_r2 = i0.ɵɵnextContext();
|
|
78
|
+
i0.ɵɵadvance();
|
|
79
|
+
i0.ɵɵconditional(ctx_r2.HasUnconfirmed ? 1 : -1);
|
|
80
|
+
i0.ɵɵadvance();
|
|
81
|
+
i0.ɵɵproperty("disabled", ctx_r2.Busy || ctx_r2.Locked || !view_r1.CanSubmit && ctx_r2.Drafts.name === "" && ctx_r2.Drafts.email === "");
|
|
82
|
+
i0.ɵɵadvance();
|
|
83
|
+
i0.ɵɵconditional(view_r1.Status === "sending" ? 3 : 4);
|
|
84
|
+
} }
|
|
85
|
+
function IdentityVerificationSurfaceComponent_Conditional_0_Conditional_4_Conditional_13_Conditional_13_Template(rf, ctx) { if (rf & 1) {
|
|
86
|
+
i0.ɵɵtext(0, " Checking\u2026 ");
|
|
87
|
+
} }
|
|
88
|
+
function IdentityVerificationSurfaceComponent_Conditional_0_Conditional_4_Conditional_13_Conditional_14_Template(rf, ctx) { if (rf & 1) {
|
|
89
|
+
i0.ɵɵtext(0, " Verify ");
|
|
90
|
+
} }
|
|
91
|
+
function IdentityVerificationSurfaceComponent_Conditional_0_Conditional_4_Conditional_13_Conditional_16_Template(rf, ctx) { if (rf & 1) {
|
|
92
|
+
i0.ɵɵtext(0);
|
|
93
|
+
} if (rf & 2) {
|
|
94
|
+
const ctx_r2 = i0.ɵɵnextContext(4);
|
|
95
|
+
i0.ɵɵtextInterpolate1(" Resend in ", ctx_r2.ResendWaitSeconds, "s ");
|
|
96
|
+
} }
|
|
97
|
+
function IdentityVerificationSurfaceComponent_Conditional_0_Conditional_4_Conditional_13_Conditional_17_Template(rf, ctx) { if (rf & 1) {
|
|
98
|
+
i0.ɵɵtext(0, " Resend code ");
|
|
99
|
+
} }
|
|
100
|
+
function IdentityVerificationSurfaceComponent_Conditional_0_Conditional_4_Conditional_13_Conditional_18_Template(rf, ctx) { if (rf & 1) {
|
|
101
|
+
i0.ɵɵelementStart(0, "p", 28);
|
|
102
|
+
i0.ɵɵtext(1);
|
|
103
|
+
i0.ɵɵelementEnd();
|
|
104
|
+
} if (rf & 2) {
|
|
105
|
+
const view_r1 = i0.ɵɵnextContext(3);
|
|
106
|
+
i0.ɵɵadvance();
|
|
107
|
+
i0.ɵɵtextInterpolate2("", view_r1.AttemptsRemaining, " ", view_r1.AttemptsRemaining === 1 ? "try" : "tries", " left.");
|
|
108
|
+
} }
|
|
109
|
+
function IdentityVerificationSurfaceComponent_Conditional_0_Conditional_4_Conditional_13_Template(rf, ctx) { if (rf & 1) {
|
|
110
|
+
const _r8 = i0.ɵɵgetCurrentView();
|
|
111
|
+
i0.ɵɵelementStart(0, "div", 16)(1, "p", 23);
|
|
112
|
+
i0.ɵɵelement(2, "i", 24);
|
|
113
|
+
i0.ɵɵtext(3, " We emailed a code to ");
|
|
114
|
+
i0.ɵɵelementStart(4, "strong");
|
|
115
|
+
i0.ɵɵtext(5);
|
|
116
|
+
i0.ɵɵelementEnd();
|
|
117
|
+
i0.ɵɵtext(6, ". Type it below, or open the link in the email. ");
|
|
118
|
+
i0.ɵɵelementEnd();
|
|
119
|
+
i0.ɵɵelementStart(7, "label", 25);
|
|
120
|
+
i0.ɵɵtext(8, "Code");
|
|
121
|
+
i0.ɵɵelementEnd();
|
|
122
|
+
i0.ɵɵelementStart(9, "input", 26, 0);
|
|
123
|
+
i0.ɵɵlistener("input", function IdentityVerificationSurfaceComponent_Conditional_0_Conditional_4_Conditional_13_Template_input_input_9_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.OnCodeInput($event)); })("keydown.enter", function IdentityVerificationSurfaceComponent_Conditional_0_Conditional_4_Conditional_13_Template_input_keydown_enter_9_listener() { i0.ɵɵrestoreView(_r8); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.SubmitCode()); });
|
|
124
|
+
i0.ɵɵelementEnd();
|
|
125
|
+
i0.ɵɵelementStart(11, "div", 15)(12, "button", 27);
|
|
126
|
+
i0.ɵɵlistener("click", function IdentityVerificationSurfaceComponent_Conditional_0_Conditional_4_Conditional_13_Template_button_click_12_listener() { i0.ɵɵrestoreView(_r8); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.SubmitCode()); });
|
|
127
|
+
i0.ɵɵconditionalCreate(13, IdentityVerificationSurfaceComponent_Conditional_0_Conditional_4_Conditional_13_Conditional_13_Template, 1, 0)(14, IdentityVerificationSurfaceComponent_Conditional_0_Conditional_4_Conditional_13_Conditional_14_Template, 1, 0);
|
|
128
|
+
i0.ɵɵelementEnd();
|
|
129
|
+
i0.ɵɵelementStart(15, "button", 22);
|
|
130
|
+
i0.ɵɵlistener("click", function IdentityVerificationSurfaceComponent_Conditional_0_Conditional_4_Conditional_13_Template_button_click_15_listener() { i0.ɵɵrestoreView(_r8); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.Resend()); });
|
|
131
|
+
i0.ɵɵconditionalCreate(16, IdentityVerificationSurfaceComponent_Conditional_0_Conditional_4_Conditional_13_Conditional_16_Template, 1, 1)(17, IdentityVerificationSurfaceComponent_Conditional_0_Conditional_4_Conditional_13_Conditional_17_Template, 1, 0);
|
|
132
|
+
i0.ɵɵelementEnd()();
|
|
133
|
+
i0.ɵɵconditionalCreate(18, IdentityVerificationSurfaceComponent_Conditional_0_Conditional_4_Conditional_13_Conditional_18_Template, 2, 2, "p", 28);
|
|
134
|
+
i0.ɵɵelementEnd();
|
|
135
|
+
} if (rf & 2) {
|
|
136
|
+
const view_r1 = i0.ɵɵnextContext(2);
|
|
137
|
+
const ctx_r2 = i0.ɵɵnextContext();
|
|
138
|
+
i0.ɵɵadvance(5);
|
|
139
|
+
i0.ɵɵtextInterpolate(view_r1.Destination);
|
|
140
|
+
i0.ɵɵadvance(4);
|
|
141
|
+
i0.ɵɵproperty("value", ctx_r2.CodeDraft)("disabled", view_r1.Status === "verifying");
|
|
142
|
+
i0.ɵɵattribute("aria-invalid", view_r1.ProblemCode === "invalid_code" ? "true" : null);
|
|
143
|
+
i0.ɵɵadvance(3);
|
|
144
|
+
i0.ɵɵproperty("disabled", ctx_r2.Busy || view_r1.Status === "verifying" || ctx_r2.CodeDraft.trim() === "");
|
|
145
|
+
i0.ɵɵadvance();
|
|
146
|
+
i0.ɵɵconditional(view_r1.Status === "verifying" ? 13 : 14);
|
|
147
|
+
i0.ɵɵadvance(2);
|
|
148
|
+
i0.ɵɵproperty("disabled", ctx_r2.Busy || view_r1.Status === "verifying" || ctx_r2.ResendWaitSeconds > 0);
|
|
149
|
+
i0.ɵɵadvance();
|
|
150
|
+
i0.ɵɵconditional(ctx_r2.ResendWaitSeconds > 0 ? 16 : 17);
|
|
151
|
+
i0.ɵɵadvance(2);
|
|
152
|
+
i0.ɵɵconditional(view_r1.AttemptsRemaining !== null ? 18 : -1);
|
|
153
|
+
} }
|
|
154
|
+
function IdentityVerificationSurfaceComponent_Conditional_0_Conditional_4_Conditional_14_Template(rf, ctx) { if (rf & 1) {
|
|
155
|
+
i0.ɵɵelementStart(0, "p", 17);
|
|
156
|
+
i0.ɵɵelement(1, "i", 29);
|
|
157
|
+
i0.ɵɵtext(2);
|
|
158
|
+
i0.ɵɵelementEnd();
|
|
159
|
+
} if (rf & 2) {
|
|
160
|
+
const view_r1 = i0.ɵɵnextContext(2);
|
|
161
|
+
const ctx_r2 = i0.ɵɵnextContext();
|
|
162
|
+
i0.ɵɵadvance(2);
|
|
163
|
+
i0.ɵɵtextInterpolate1(" ", view_r1.Problem || ctx_r2.ActionProblem, " ");
|
|
164
|
+
} }
|
|
165
|
+
function IdentityVerificationSurfaceComponent_Conditional_0_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
166
|
+
const _r2 = i0.ɵɵgetCurrentView();
|
|
167
|
+
i0.ɵɵelementStart(0, "p", 7);
|
|
168
|
+
i0.ɵɵtext(1, " Check your details, then we'll email you a code and a link. Either one confirms it's you. ");
|
|
169
|
+
i0.ɵɵelementEnd();
|
|
170
|
+
i0.ɵɵelementStart(2, "div", 8)(3, "label", 9);
|
|
171
|
+
i0.ɵɵtext(4, "Your name");
|
|
172
|
+
i0.ɵɵelementEnd();
|
|
173
|
+
i0.ɵɵelementStart(5, "input", 10);
|
|
174
|
+
i0.ɵɵlistener("input", function IdentityVerificationSurfaceComponent_Conditional_0_Conditional_4_Template_input_input_5_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.OnDraft("name", $event)); })("blur", function IdentityVerificationSurfaceComponent_Conditional_0_Conditional_4_Template_input_blur_5_listener() { i0.ɵɵrestoreView(_r2); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.CommitField("name")); })("keydown.enter", function IdentityVerificationSurfaceComponent_Conditional_0_Conditional_4_Template_input_keydown_enter_5_listener() { i0.ɵɵrestoreView(_r2); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.CommitField("name")); });
|
|
175
|
+
i0.ɵɵelementEnd();
|
|
176
|
+
i0.ɵɵconditionalCreate(6, IdentityVerificationSurfaceComponent_Conditional_0_Conditional_4_Conditional_6_Template, 5, 2, "p", 11);
|
|
177
|
+
i0.ɵɵelementEnd();
|
|
178
|
+
i0.ɵɵelementStart(7, "div", 8)(8, "label", 12);
|
|
179
|
+
i0.ɵɵtext(9, "Your email");
|
|
180
|
+
i0.ɵɵelementEnd();
|
|
181
|
+
i0.ɵɵelementStart(10, "input", 13);
|
|
182
|
+
i0.ɵɵlistener("input", function IdentityVerificationSurfaceComponent_Conditional_0_Conditional_4_Template_input_input_10_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.OnDraft("email", $event)); })("blur", function IdentityVerificationSurfaceComponent_Conditional_0_Conditional_4_Template_input_blur_10_listener() { i0.ɵɵrestoreView(_r2); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.CommitField("email")); })("keydown.enter", function IdentityVerificationSurfaceComponent_Conditional_0_Conditional_4_Template_input_keydown_enter_10_listener() { i0.ɵɵrestoreView(_r2); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.CommitField("email")); });
|
|
183
|
+
i0.ɵɵelementEnd();
|
|
184
|
+
i0.ɵɵconditionalCreate(11, IdentityVerificationSurfaceComponent_Conditional_0_Conditional_4_Conditional_11_Template, 5, 2, "p", 14);
|
|
185
|
+
i0.ɵɵelementEnd();
|
|
186
|
+
i0.ɵɵconditionalCreate(12, IdentityVerificationSurfaceComponent_Conditional_0_Conditional_4_Conditional_12_Template, 5, 3, "div", 15)(13, IdentityVerificationSurfaceComponent_Conditional_0_Conditional_4_Conditional_13_Template, 19, 9, "div", 16);
|
|
187
|
+
i0.ɵɵconditionalCreate(14, IdentityVerificationSurfaceComponent_Conditional_0_Conditional_4_Conditional_14_Template, 3, 1, "p", 17);
|
|
188
|
+
} if (rf & 2) {
|
|
189
|
+
const view_r1 = i0.ɵɵnextContext();
|
|
190
|
+
const ctx_r2 = i0.ɵɵnextContext();
|
|
191
|
+
i0.ɵɵadvance(5);
|
|
192
|
+
i0.ɵɵproperty("value", ctx_r2.ValueFor("name"))("disabled", ctx_r2.Locked || ctx_r2.CodeStage);
|
|
193
|
+
i0.ɵɵattribute("aria-describedby", ctx_r2.IsSuggested("name") ? "idv-name-hint" : null);
|
|
194
|
+
i0.ɵɵadvance();
|
|
195
|
+
i0.ɵɵconditional(ctx_r2.IsSuggested("name") ? 6 : -1);
|
|
196
|
+
i0.ɵɵadvance(4);
|
|
197
|
+
i0.ɵɵproperty("value", ctx_r2.ValueFor("email"))("disabled", ctx_r2.Locked || ctx_r2.CodeStage);
|
|
198
|
+
i0.ɵɵattribute("aria-describedby", ctx_r2.IsSuggested("email") ? "idv-email-hint" : null)("aria-invalid", view_r1.ProblemCode === "invalid_email" ? "true" : null);
|
|
199
|
+
i0.ɵɵadvance();
|
|
200
|
+
i0.ɵɵconditional(ctx_r2.IsSuggested("email") ? 11 : -1);
|
|
201
|
+
i0.ɵɵadvance();
|
|
202
|
+
i0.ɵɵconditional(!ctx_r2.CodeStage ? 12 : 13);
|
|
203
|
+
i0.ɵɵadvance(2);
|
|
204
|
+
i0.ɵɵconditional(view_r1.Problem || ctx_r2.ActionProblem ? 14 : -1);
|
|
205
|
+
} }
|
|
206
|
+
function IdentityVerificationSurfaceComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
207
|
+
i0.ɵɵelementStart(0, "section", 1)(1, "h3", 2);
|
|
208
|
+
i0.ɵɵtext(2, "Verify your identity");
|
|
209
|
+
i0.ɵɵelementEnd();
|
|
210
|
+
i0.ɵɵconditionalCreate(3, IdentityVerificationSurfaceComponent_Conditional_0_Conditional_3_Template, 7, 2, "div", 3)(4, IdentityVerificationSurfaceComponent_Conditional_0_Conditional_4_Template, 15, 11);
|
|
211
|
+
i0.ɵɵelementEnd();
|
|
212
|
+
} if (rf & 2) {
|
|
213
|
+
const view_r1 = ctx;
|
|
214
|
+
i0.ɵɵattribute("data-status", view_r1.Status);
|
|
215
|
+
i0.ɵɵadvance(3);
|
|
216
|
+
i0.ɵɵconditional(view_r1.Status === "verified" ? 3 : 4);
|
|
217
|
+
} }
|
|
218
|
+
/**
|
|
219
|
+
* The IDENTITY VERIFICATION surface (`mj-identity-verification-surface`) — a small, accessible form that
|
|
220
|
+
* renders the channel's state and sends the user's own actions back through it. It owns no rules: whether
|
|
221
|
+
* a value counts as confirmed, whether a code can be sent, what a failure means are the
|
|
222
|
+
* {@link IdentityVerificationModel}'s decisions; this only shows them.
|
|
223
|
+
*
|
|
224
|
+
* Details the agent filled in are marked "Suggested" and carry a Confirm control until the user approves
|
|
225
|
+
* them; a value the user types is theirs and needs no confirmation. Mobile-first: one column, 44px tap
|
|
226
|
+
* targets, 16px inputs (no iOS zoom), the right keyboard and autofill hints per field. Colour comes only
|
|
227
|
+
* from `--mj-*` design tokens, so it follows the host's theme (including dark mode).
|
|
228
|
+
*/
|
|
229
|
+
export class IdentityVerificationSurfaceComponent {
|
|
230
|
+
cdr = inject(ChangeDetectorRef);
|
|
231
|
+
modelSub = null;
|
|
232
|
+
tick = null;
|
|
233
|
+
model = null;
|
|
234
|
+
/** The current snapshot, or `null` until a model is bound. */
|
|
235
|
+
View = null;
|
|
236
|
+
/** Name of the agent, for the "Suggested by …" marker. */
|
|
237
|
+
AgentName = 'The assistant';
|
|
238
|
+
/** Seconds until another send is allowed (0 = now). Recomputed on a 1s tick while a cooldown runs. */
|
|
239
|
+
ResendWaitSeconds = 0;
|
|
240
|
+
/** True while an action is in flight from THIS surface (disables double-submits). */
|
|
241
|
+
Busy = false;
|
|
242
|
+
/**
|
|
243
|
+
* Why the user's last action was refused before it reached the server (a malformed email, a missing
|
|
244
|
+
* detail) — the model's own `Problem` only covers what the SERVER said. Cleared by the next action.
|
|
245
|
+
*/
|
|
246
|
+
ActionProblem = '';
|
|
247
|
+
/** The code the user is typing. Never leaves this component except through {@link SubmitCode}. */
|
|
248
|
+
CodeDraft = '';
|
|
249
|
+
/** The unconfirmed drafts the user is typing, per field. */
|
|
250
|
+
Drafts = { name: '', email: '' };
|
|
251
|
+
/** Where the user's actions go — wired by the channel; a no-op until then. */
|
|
252
|
+
Dispatch = async () => ({ Success: false, Error: 'Not connected.' });
|
|
253
|
+
codeInput;
|
|
254
|
+
/** The state engine this surface renders. */
|
|
255
|
+
set Model(value) {
|
|
256
|
+
if (value === this.model) {
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
this.modelSub?.unsubscribe();
|
|
260
|
+
this.model = value;
|
|
261
|
+
this.modelSub = value?.View$.subscribe((view) => this.onView(view)) ?? null;
|
|
262
|
+
}
|
|
263
|
+
get Model() {
|
|
264
|
+
return this.model;
|
|
265
|
+
}
|
|
266
|
+
ngOnDestroy() {
|
|
267
|
+
this.modelSub?.unsubscribe();
|
|
268
|
+
this.stopTick();
|
|
269
|
+
}
|
|
270
|
+
// ── Template helpers ───────────────────────────────────────────────────────
|
|
271
|
+
/** What to show in an input: the user's draft, else the stored value. */
|
|
272
|
+
ValueFor(field) {
|
|
273
|
+
return this.Drafts[field] !== '' ? this.Drafts[field] : this.View ? this.fieldView(field).Value : '';
|
|
274
|
+
}
|
|
275
|
+
/** The agent or host suggested this value and the user has not approved it yet. */
|
|
276
|
+
IsSuggested(field) {
|
|
277
|
+
const f = this.View ? this.fieldView(field) : null;
|
|
278
|
+
return !!f && f.Value.length > 0 && !f.Confirmed && this.Drafts[field] === '';
|
|
279
|
+
}
|
|
280
|
+
/** Who suggested it, for the label. */
|
|
281
|
+
SuggestedBy(field) {
|
|
282
|
+
return this.View && this.fieldView(field).Source === 'host' ? 'this page' : this.AgentName;
|
|
283
|
+
}
|
|
284
|
+
get Locked() {
|
|
285
|
+
return !!this.View && (this.View.Status === 'sending' || this.View.Status === 'verifying' || this.View.Status === 'verified');
|
|
286
|
+
}
|
|
287
|
+
get CodeStage() {
|
|
288
|
+
return !!this.View && (this.View.Status === 'code_sent' || this.View.Status === 'verifying');
|
|
289
|
+
}
|
|
290
|
+
// ── Actions ────────────────────────────────────────────────────────────────
|
|
291
|
+
OnDraft(field, event) {
|
|
292
|
+
this.Drafts[field] = event.target.value;
|
|
293
|
+
}
|
|
294
|
+
/** Commits what the user typed in a field (blur / Enter) — the user's own value, confirmed by being theirs. */
|
|
295
|
+
async CommitField(field) {
|
|
296
|
+
const draft = this.Drafts[field].trim();
|
|
297
|
+
if (draft === '') {
|
|
298
|
+
this.Drafts[field] = '';
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
await this.run('fill', { field, value: draft });
|
|
302
|
+
// Keep the draft if the model refused it (e.g. a malformed email) so the user can correct it, not retype it.
|
|
303
|
+
if (this.View && this.fieldView(field).Value === draft) {
|
|
304
|
+
this.Drafts[field] = '';
|
|
305
|
+
}
|
|
306
|
+
this.cdr.markForCheck();
|
|
307
|
+
}
|
|
308
|
+
async ConfirmField(field) {
|
|
309
|
+
await this.run('confirm', { field });
|
|
310
|
+
}
|
|
311
|
+
async ConfirmAll() {
|
|
312
|
+
await this.run('confirm', {});
|
|
313
|
+
}
|
|
314
|
+
async SendCode() {
|
|
315
|
+
await this.commitPendingDrafts();
|
|
316
|
+
await this.run('submit', {});
|
|
317
|
+
}
|
|
318
|
+
async Resend() {
|
|
319
|
+
await this.run('resend', {});
|
|
320
|
+
}
|
|
321
|
+
OnCodeInput(event) {
|
|
322
|
+
this.CodeDraft = event.target.value;
|
|
323
|
+
}
|
|
324
|
+
async SubmitCode() {
|
|
325
|
+
const code = this.CodeDraft;
|
|
326
|
+
if (code.trim() === '') {
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
const outcome = await this.run('enter_code', { code });
|
|
330
|
+
if (outcome.Success) {
|
|
331
|
+
this.CodeDraft = '';
|
|
332
|
+
}
|
|
333
|
+
this.cdr.markForCheck();
|
|
334
|
+
}
|
|
335
|
+
get HasUnconfirmed() {
|
|
336
|
+
return !!this.View && ((this.View.Name.Value !== '' && !this.View.Name.Confirmed) || (this.View.Email.Value !== '' && !this.View.Email.Confirmed));
|
|
337
|
+
}
|
|
338
|
+
// ── Internals ──────────────────────────────────────────────────────────────
|
|
339
|
+
fieldView(field) {
|
|
340
|
+
return field === 'name' ? this.View.Name : this.View.Email;
|
|
341
|
+
}
|
|
342
|
+
/** Commits fields the user typed but did not blur out of, so pressing "Send code" never drops them. */
|
|
343
|
+
async commitPendingDrafts() {
|
|
344
|
+
for (const field of ['name', 'email']) {
|
|
345
|
+
if (this.Drafts[field].trim() !== '') {
|
|
346
|
+
await this.CommitField(field);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
async run(verb, args) {
|
|
351
|
+
this.Busy = true;
|
|
352
|
+
this.cdr.markForCheck();
|
|
353
|
+
try {
|
|
354
|
+
const outcome = await this.Dispatch(verb, args);
|
|
355
|
+
this.ActionProblem = outcome.Success ? '' : (outcome.Error ?? 'That did not work. Please try again.');
|
|
356
|
+
return outcome;
|
|
357
|
+
}
|
|
358
|
+
finally {
|
|
359
|
+
this.Busy = false;
|
|
360
|
+
this.cdr.markForCheck();
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
onView(view) {
|
|
364
|
+
const enteredCodeStage = this.View?.Status !== 'code_sent' && view.Status === 'code_sent';
|
|
365
|
+
this.View = view;
|
|
366
|
+
this.syncCooldown();
|
|
367
|
+
this.cdr.markForCheck();
|
|
368
|
+
if (enteredCodeStage) {
|
|
369
|
+
// The code box did not exist until this render; move focus into it once it does.
|
|
370
|
+
queueMicrotask(() => this.codeInput?.nativeElement.focus());
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
syncCooldown() {
|
|
374
|
+
const remaining = this.View ? Math.max(0, Math.ceil((this.View.ResendAvailableAt - Date.now()) / 1000)) : 0;
|
|
375
|
+
this.ResendWaitSeconds = remaining;
|
|
376
|
+
if (remaining > 0 && this.tick === null) {
|
|
377
|
+
this.tick = setInterval(() => this.onTick(), 1000);
|
|
378
|
+
}
|
|
379
|
+
else if (remaining === 0) {
|
|
380
|
+
this.stopTick();
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
onTick() {
|
|
384
|
+
this.syncCooldown();
|
|
385
|
+
this.cdr.markForCheck();
|
|
386
|
+
}
|
|
387
|
+
stopTick() {
|
|
388
|
+
if (this.tick !== null) {
|
|
389
|
+
clearInterval(this.tick);
|
|
390
|
+
this.tick = null;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
static ɵfac = function IdentityVerificationSurfaceComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || IdentityVerificationSurfaceComponent)(); };
|
|
394
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: IdentityVerificationSurfaceComponent, selectors: [["mj-identity-verification-surface"]], viewQuery: function IdentityVerificationSurfaceComponent_Query(rf, ctx) { if (rf & 1) {
|
|
395
|
+
i0.ɵɵviewQuery(_c0, 5);
|
|
396
|
+
} if (rf & 2) {
|
|
397
|
+
let _t;
|
|
398
|
+
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.codeInput = _t.first);
|
|
399
|
+
} }, inputs: { AgentName: "AgentName", Dispatch: "Dispatch", Model: "Model" }, decls: 1, vars: 1, consts: [["codeInput", ""], ["aria-labelledby", "idv-title", 1, "idv"], ["id", "idv-title", 1, "idv__title"], ["role", "status", 1, "idv__done"], ["aria-hidden", "true", 1, "fa-solid", "fa-circle-check", "idv__done-icon"], [1, "idv__done-heading"], [1, "idv__done-detail"], ["id", "idv-lead", 1, "idv__lead"], [1, "idv__field"], ["for", "idv-name", 1, "idv__label"], ["id", "idv-name", "type", "text", "autocomplete", "name", "autocapitalize", "words", "maxlength", "200", 1, "mj-input", "idv__input", 3, "input", "blur", "keydown.enter", "value", "disabled"], ["id", "idv-name-hint", 1, "idv__suggested"], ["for", "idv-email", 1, "idv__label"], ["id", "idv-email", "type", "email", "inputmode", "email", "autocomplete", "email", "autocapitalize", "none", "spellcheck", "false", "maxlength", "200", 1, "mj-input", "idv__input", 3, "input", "blur", "keydown.enter", "value", "disabled"], ["id", "idv-email-hint", 1, "idv__suggested"], [1, "idv__actions"], ["aria-live", "polite", 1, "idv__code"], ["role", "alert", 1, "idv__problem"], ["aria-hidden", "true", 1, "fa-solid", "fa-wand-magic-sparkles"], ["mjButton", "", "variant", "outline", "size", "sm", "type", "button", 1, "idv__confirm", 3, "click", "disabled"], ["mjButton", "", "variant", "outline", "type", "button", 3, "disabled"], ["mjButton", "", "variant", "primary", "type", "button", 1, "idv__send", 3, "click", "disabled"], ["mjButton", "", "variant", "outline", "type", "button", 3, "click", "disabled"], [1, "idv__sent"], ["aria-hidden", "true", 1, "fa-solid", "fa-envelope-circle-check"], ["for", "idv-code", 1, "idv__label"], ["id", "idv-code", "type", "text", "inputmode", "numeric", "autocomplete", "one-time-code", "maxlength", "16", 1, "mj-input", "idv__input", "idv__code-input", 3, "input", "keydown.enter", "value", "disabled"], ["mjButton", "", "variant", "primary", "type", "button", 3, "click", "disabled"], [1, "idv__hint"], ["aria-hidden", "true", 1, "fa-solid", "fa-triangle-exclamation"]], template: function IdentityVerificationSurfaceComponent_Template(rf, ctx) { if (rf & 1) {
|
|
400
|
+
i0.ɵɵconditionalCreate(0, IdentityVerificationSurfaceComponent_Conditional_0_Template, 5, 2, "section", 1);
|
|
401
|
+
} if (rf & 2) {
|
|
402
|
+
let tmp_0_0;
|
|
403
|
+
i0.ɵɵconditional((tmp_0_0 = ctx.View) ? 0 : -1, tmp_0_0);
|
|
404
|
+
} }, dependencies: [MJButtonDirective], styles: ["[_nghost-%COMP%] {\n display: block;\n box-sizing: border-box;\n height: 100%;\n overflow-y: auto;\n padding: var(--mj-space-4, 16px);\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n}\n\n.idv[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-4, 16px);\n max-width: 28rem;\n margin: 0 auto;\n}\n\n.idv__title[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 1.125rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.idv__lead[_ngcontent-%COMP%], \n.idv__hint[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 0.875rem;\n color: var(--mj-text-secondary);\n}\n\n.idv__field[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-1, 4px);\n}\n\n.idv__label[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n\n.idv__input[_ngcontent-%COMP%] {\n box-sizing: border-box;\n width: 100%;\n min-height: 44px;\n font-size: 1rem;\n}\n\n.idv__input[_ngcontent-%COMP%]:focus-visible {\n outline: 2px solid var(--mj-border-focus);\n outline-offset: 1px;\n}\n\n.idv__code-input[_ngcontent-%COMP%] {\n letter-spacing: 0.2em;\n font-variant-numeric: tabular-nums;\n}\n\n.idv__suggested[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--mj-space-2, 8px);\n margin: 0;\n padding: var(--mj-space-2, 8px) var(--mj-space-3, 12px);\n font-size: 0.8125rem;\n color: var(--mj-text-secondary);\n background: color-mix(in srgb, var(--mj-status-info) 10%, var(--mj-bg-surface));\n border: 1px dashed var(--mj-status-info-border);\n border-radius: var(--mj-radius-md, 8px);\n}\n\n.idv__suggested[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-info);\n}\n\n.idv__confirm[_ngcontent-%COMP%] {\n min-height: 44px;\n}\n\n.idv__actions[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: var(--mj-space-2, 8px);\n}\n\n.idv__actions[_ngcontent-%COMP%] > button[_ngcontent-%COMP%] {\n flex: 1 1 8rem;\n min-height: 44px;\n}\n\n.idv__code[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-3, 12px);\n}\n\n.idv__sent[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 0.875rem;\n color: var(--mj-text-secondary);\n overflow-wrap: anywhere;\n}\n\n.idv__sent[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n margin-right: var(--mj-space-1, 4px);\n color: var(--mj-status-success);\n}\n\n.idv__problem[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: var(--mj-space-2, 8px);\n margin: 0;\n padding: var(--mj-space-2, 8px) var(--mj-space-3, 12px);\n font-size: 0.875rem;\n color: var(--mj-status-error-text);\n background: var(--mj-status-error-bg);\n border: 1px solid var(--mj-status-error-border);\n border-radius: var(--mj-radius-md, 8px);\n}\n\n.idv__done[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: var(--mj-space-3, 12px);\n padding: var(--mj-space-4, 16px);\n background: var(--mj-status-success-bg);\n border: 1px solid var(--mj-status-success-border);\n border-radius: var(--mj-radius-md, 8px);\n}\n\n.idv__done-icon[_ngcontent-%COMP%] {\n font-size: 1.75rem;\n color: var(--mj-status-success);\n}\n\n.idv__done-heading[_ngcontent-%COMP%] {\n margin: 0;\n font-weight: 600;\n color: var(--mj-status-success-text);\n}\n\n.idv__done-detail[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 0.875rem;\n color: var(--mj-text-secondary);\n overflow-wrap: anywhere;\n}\n\n@media (prefers-reduced-motion: no-preference) {\n .idv__done[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_idv-in 180ms ease-out;\n }\n}\n\n@keyframes _ngcontent-%COMP%_idv-in {\n from { opacity: 0; transform: translateY(4px); }\n to { opacity: 1; transform: none; }\n}"], changeDetection: 0 });
|
|
405
|
+
}
|
|
406
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(IdentityVerificationSurfaceComponent, [{
|
|
407
|
+
type: Component,
|
|
408
|
+
args: [{ standalone: true, selector: 'mj-identity-verification-surface', imports: [MJButtonDirective], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (View; as view) {\n <section class=\"idv\" [attr.data-status]=\"view.Status\" aria-labelledby=\"idv-title\">\n <h3 id=\"idv-title\" class=\"idv__title\">Verify your identity</h3>\n\n @if (view.Status === 'verified') {\n <div class=\"idv__done\" role=\"status\">\n <i class=\"fa-solid fa-circle-check idv__done-icon\" aria-hidden=\"true\"></i>\n <div>\n <p class=\"idv__done-heading\">You're verified</p>\n <p class=\"idv__done-detail\">{{ view.Name.Value }} · {{ view.Email.Value }}</p>\n </div>\n </div>\n } @else {\n <p class=\"idv__lead\" id=\"idv-lead\">\n Check your details, then we'll email you a code and a link. Either one confirms it's you.\n </p>\n\n <div class=\"idv__field\">\n <label class=\"idv__label\" for=\"idv-name\">Your name</label>\n <input\n id=\"idv-name\"\n class=\"mj-input idv__input\"\n type=\"text\"\n autocomplete=\"name\"\n autocapitalize=\"words\"\n maxlength=\"200\"\n [value]=\"ValueFor('name')\"\n [disabled]=\"Locked || CodeStage\"\n [attr.aria-describedby]=\"IsSuggested('name') ? 'idv-name-hint' : null\"\n (input)=\"OnDraft('name', $event)\"\n (blur)=\"CommitField('name')\"\n (keydown.enter)=\"CommitField('name')\" />\n @if (IsSuggested('name')) {\n <p class=\"idv__suggested\" id=\"idv-name-hint\">\n <i class=\"fa-solid fa-wand-magic-sparkles\" aria-hidden=\"true\"></i>\n Suggested by {{ SuggestedBy('name') }} — check it's right.\n <button mjButton variant=\"outline\" size=\"sm\" type=\"button\" class=\"idv__confirm\" [disabled]=\"Busy\" (click)=\"ConfirmField('name')\">Confirm</button>\n </p>\n }\n </div>\n\n <div class=\"idv__field\">\n <label class=\"idv__label\" for=\"idv-email\">Your email</label>\n <input\n id=\"idv-email\"\n class=\"mj-input idv__input\"\n type=\"email\"\n inputmode=\"email\"\n autocomplete=\"email\"\n autocapitalize=\"none\"\n spellcheck=\"false\"\n maxlength=\"200\"\n [value]=\"ValueFor('email')\"\n [disabled]=\"Locked || CodeStage\"\n [attr.aria-describedby]=\"IsSuggested('email') ? 'idv-email-hint' : null\"\n [attr.aria-invalid]=\"view.ProblemCode === 'invalid_email' ? 'true' : null\"\n (input)=\"OnDraft('email', $event)\"\n (blur)=\"CommitField('email')\"\n (keydown.enter)=\"CommitField('email')\" />\n @if (IsSuggested('email')) {\n <p class=\"idv__suggested\" id=\"idv-email-hint\">\n <i class=\"fa-solid fa-wand-magic-sparkles\" aria-hidden=\"true\"></i>\n Suggested by {{ SuggestedBy('email') }} — check it's right.\n <button mjButton variant=\"outline\" size=\"sm\" type=\"button\" class=\"idv__confirm\" [disabled]=\"Busy\" (click)=\"ConfirmField('email')\">Confirm</button>\n </p>\n }\n </div>\n\n @if (!CodeStage) {\n <div class=\"idv__actions\">\n @if (HasUnconfirmed) {\n <button mjButton variant=\"outline\" type=\"button\" [disabled]=\"Busy || Locked\" (click)=\"ConfirmAll()\">Confirm details</button>\n }\n <button mjButton variant=\"primary\" type=\"button\" class=\"idv__send\" [disabled]=\"Busy || Locked || (!view.CanSubmit && Drafts.name === '' && Drafts.email === '')\" (click)=\"SendCode()\">\n @if (view.Status === 'sending') { Sending\u2026 } @else { Send code }\n </button>\n </div>\n } @else {\n <div class=\"idv__code\" aria-live=\"polite\">\n <p class=\"idv__sent\">\n <i class=\"fa-solid fa-envelope-circle-check\" aria-hidden=\"true\"></i>\n We emailed a code to <strong>{{ view.Destination }}</strong>. Type it below, or open the link in the email.\n </p>\n <label class=\"idv__label\" for=\"idv-code\">Code</label>\n <input\n #codeInput\n id=\"idv-code\"\n class=\"mj-input idv__input idv__code-input\"\n type=\"text\"\n inputmode=\"numeric\"\n autocomplete=\"one-time-code\"\n maxlength=\"16\"\n [value]=\"CodeDraft\"\n [disabled]=\"view.Status === 'verifying'\"\n [attr.aria-invalid]=\"view.ProblemCode === 'invalid_code' ? 'true' : null\"\n (input)=\"OnCodeInput($event)\"\n (keydown.enter)=\"SubmitCode()\" />\n <div class=\"idv__actions\">\n <button mjButton variant=\"primary\" type=\"button\" [disabled]=\"Busy || view.Status === 'verifying' || CodeDraft.trim() === ''\" (click)=\"SubmitCode()\">\n @if (view.Status === 'verifying') { Checking\u2026 } @else { Verify }\n </button>\n <button mjButton variant=\"outline\" type=\"button\" [disabled]=\"Busy || view.Status === 'verifying' || ResendWaitSeconds > 0\" (click)=\"Resend()\">\n @if (ResendWaitSeconds > 0) { Resend in {{ ResendWaitSeconds }}s } @else { Resend code }\n </button>\n </div>\n @if (view.AttemptsRemaining !== null) {\n <p class=\"idv__hint\">{{ view.AttemptsRemaining }} {{ view.AttemptsRemaining === 1 ? 'try' : 'tries' }} left.</p>\n }\n </div>\n }\n\n @if (view.Problem || ActionProblem) {\n <p class=\"idv__problem\" role=\"alert\">\n <i class=\"fa-solid fa-triangle-exclamation\" aria-hidden=\"true\"></i>\n {{ view.Problem || ActionProblem }}\n </p>\n }\n }\n </section>\n}\n", styles: [":host {\n display: block;\n box-sizing: border-box;\n height: 100%;\n overflow-y: auto;\n padding: var(--mj-space-4, 16px);\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n}\n\n.idv {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-4, 16px);\n max-width: 28rem;\n margin: 0 auto;\n}\n\n.idv__title {\n margin: 0;\n font-size: 1.125rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.idv__lead,\n.idv__hint {\n margin: 0;\n font-size: 0.875rem;\n color: var(--mj-text-secondary);\n}\n\n.idv__field {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-1, 4px);\n}\n\n.idv__label {\n font-size: 0.875rem;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n/* 16px keeps iOS from zooming the page on focus; 44px is the minimum comfortable tap target. */\n.idv__input {\n box-sizing: border-box;\n width: 100%;\n min-height: 44px;\n font-size: 1rem;\n}\n\n.idv__input:focus-visible {\n outline: 2px solid var(--mj-border-focus);\n outline-offset: 1px;\n}\n\n.idv__code-input {\n letter-spacing: 0.2em;\n font-variant-numeric: tabular-nums;\n}\n\n.idv__suggested {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--mj-space-2, 8px);\n margin: 0;\n padding: var(--mj-space-2, 8px) var(--mj-space-3, 12px);\n font-size: 0.8125rem;\n color: var(--mj-text-secondary);\n background: color-mix(in srgb, var(--mj-status-info) 10%, var(--mj-bg-surface));\n border: 1px dashed var(--mj-status-info-border);\n border-radius: var(--mj-radius-md, 8px);\n}\n\n.idv__suggested i {\n color: var(--mj-status-info);\n}\n\n.idv__confirm {\n min-height: 44px;\n}\n\n.idv__actions {\n display: flex;\n flex-wrap: wrap;\n gap: var(--mj-space-2, 8px);\n}\n\n.idv__actions > button {\n flex: 1 1 8rem;\n min-height: 44px;\n}\n\n.idv__code {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-3, 12px);\n}\n\n.idv__sent {\n margin: 0;\n font-size: 0.875rem;\n color: var(--mj-text-secondary);\n overflow-wrap: anywhere;\n}\n\n.idv__sent i {\n margin-right: var(--mj-space-1, 4px);\n color: var(--mj-status-success);\n}\n\n.idv__problem {\n display: flex;\n align-items: flex-start;\n gap: var(--mj-space-2, 8px);\n margin: 0;\n padding: var(--mj-space-2, 8px) var(--mj-space-3, 12px);\n font-size: 0.875rem;\n color: var(--mj-status-error-text);\n background: var(--mj-status-error-bg);\n border: 1px solid var(--mj-status-error-border);\n border-radius: var(--mj-radius-md, 8px);\n}\n\n.idv__done {\n display: flex;\n align-items: center;\n gap: var(--mj-space-3, 12px);\n padding: var(--mj-space-4, 16px);\n background: var(--mj-status-success-bg);\n border: 1px solid var(--mj-status-success-border);\n border-radius: var(--mj-radius-md, 8px);\n}\n\n.idv__done-icon {\n font-size: 1.75rem;\n color: var(--mj-status-success);\n}\n\n.idv__done-heading {\n margin: 0;\n font-weight: 600;\n color: var(--mj-status-success-text);\n}\n\n.idv__done-detail {\n margin: 0;\n font-size: 0.875rem;\n color: var(--mj-text-secondary);\n overflow-wrap: anywhere;\n}\n\n@media (prefers-reduced-motion: no-preference) {\n .idv__done {\n animation: idv-in 180ms ease-out;\n }\n}\n\n@keyframes idv-in {\n from { opacity: 0; transform: translateY(4px); }\n to { opacity: 1; transform: none; }\n}\n"] }]
|
|
409
|
+
}], null, { AgentName: [{
|
|
410
|
+
type: Input
|
|
411
|
+
}], Dispatch: [{
|
|
412
|
+
type: Input
|
|
413
|
+
}], codeInput: [{
|
|
414
|
+
type: ViewChild,
|
|
415
|
+
args: ['codeInput']
|
|
416
|
+
}], Model: [{
|
|
417
|
+
type: Input
|
|
418
|
+
}] }); })();
|
|
419
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(IdentityVerificationSurfaceComponent, { className: "IdentityVerificationSurfaceComponent", filePath: "src/lib/components/realtime/identity-verification/identity-verification-surface.component.ts", lineNumber: 30 }); })();
|
|
420
|
+
//# sourceMappingURL=identity-verification-surface.component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity-verification-surface.component.js","sourceRoot":"","sources":["../../../../../src/lib/components/realtime/identity-verification/identity-verification-surface.component.ts","../../../../../src/lib/components/realtime/identity-verification/identity-verification-surface.component.html"],"names":[],"mappings":"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","sourcesContent":["import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, Input, OnDestroy, ViewChild, inject } from '@angular/core';\nimport { Subscription } from 'rxjs';\nimport type { JSONObject } from '@memberjunction/ai';\nimport type { RealtimeChannelVerbResult } from '@memberjunction/realtime-runtime';\nimport { MJButtonDirective } from '@memberjunction/ng-ui-components';\nimport { IdentityVerificationModel, type IdentityField, type IdentityVerificationView } from './identity-verification-model';\n\n/** Sends one of the user's actions to the channel (which runs it as the `user`). */\nexport type IdentityVerificationDispatch = (verb: string, args: JSONObject) => Promise<RealtimeChannelVerbResult>;\n\n/**\n * The IDENTITY VERIFICATION surface (`mj-identity-verification-surface`) — a small, accessible form that\n * renders the channel's state and sends the user's own actions back through it. It owns no rules: whether\n * a value counts as confirmed, whether a code can be sent, what a failure means are the\n * {@link IdentityVerificationModel}'s decisions; this only shows them.\n *\n * Details the agent filled in are marked \"Suggested\" and carry a Confirm control until the user approves\n * them; a value the user types is theirs and needs no confirmation. Mobile-first: one column, 44px tap\n * targets, 16px inputs (no iOS zoom), the right keyboard and autofill hints per field. Colour comes only\n * from `--mj-*` design tokens, so it follows the host's theme (including dark mode).\n */\n@Component({\n standalone: true,\n selector: 'mj-identity-verification-surface',\n imports: [MJButtonDirective],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './identity-verification-surface.component.html',\n styleUrls: ['./identity-verification-surface.component.css']\n})\nexport class IdentityVerificationSurfaceComponent implements OnDestroy {\n private readonly cdr = inject(ChangeDetectorRef);\n private modelSub: Subscription | null = null;\n private tick: ReturnType<typeof setInterval> | null = null;\n private model: IdentityVerificationModel | null = null;\n\n /** The current snapshot, or `null` until a model is bound. */\n public View: IdentityVerificationView | null = null;\n\n /** Name of the agent, for the \"Suggested by …\" marker. */\n @Input() AgentName = 'The assistant';\n\n /** Seconds until another send is allowed (0 = now). Recomputed on a 1s tick while a cooldown runs. */\n public ResendWaitSeconds = 0;\n\n /** True while an action is in flight from THIS surface (disables double-submits). */\n public Busy = false;\n\n /**\n * Why the user's last action was refused before it reached the server (a malformed email, a missing\n * detail) — the model's own `Problem` only covers what the SERVER said. Cleared by the next action.\n */\n public ActionProblem = '';\n\n /** The code the user is typing. Never leaves this component except through {@link SubmitCode}. */\n public CodeDraft = '';\n\n /** The unconfirmed drafts the user is typing, per field. */\n public Drafts: Record<IdentityField, string> = { name: '', email: '' };\n\n /** Where the user's actions go — wired by the channel; a no-op until then. */\n @Input() Dispatch: IdentityVerificationDispatch = async () => ({ Success: false, Error: 'Not connected.' });\n\n @ViewChild('codeInput') private codeInput?: ElementRef<HTMLInputElement>;\n\n /** The state engine this surface renders. */\n @Input()\n public set Model(value: IdentityVerificationModel | null) {\n if (value === this.model) {\n return;\n }\n this.modelSub?.unsubscribe();\n this.model = value;\n this.modelSub = value?.View$.subscribe((view) => this.onView(view)) ?? null;\n }\n public get Model(): IdentityVerificationModel | null {\n return this.model;\n }\n\n public ngOnDestroy(): void {\n this.modelSub?.unsubscribe();\n this.stopTick();\n }\n\n // ── Template helpers ───────────────────────────────────────────────────────\n\n /** What to show in an input: the user's draft, else the stored value. */\n public ValueFor(field: IdentityField): string {\n return this.Drafts[field] !== '' ? this.Drafts[field] : this.View ? this.fieldView(field).Value : '';\n }\n\n /** The agent or host suggested this value and the user has not approved it yet. */\n public IsSuggested(field: IdentityField): boolean {\n const f = this.View ? this.fieldView(field) : null;\n return !!f && f.Value.length > 0 && !f.Confirmed && this.Drafts[field] === '';\n }\n\n /** Who suggested it, for the label. */\n public SuggestedBy(field: IdentityField): string {\n return this.View && this.fieldView(field).Source === 'host' ? 'this page' : this.AgentName;\n }\n\n public get Locked(): boolean {\n return !!this.View && (this.View.Status === 'sending' || this.View.Status === 'verifying' || this.View.Status === 'verified');\n }\n\n public get CodeStage(): boolean {\n return !!this.View && (this.View.Status === 'code_sent' || this.View.Status === 'verifying');\n }\n\n // ── Actions ────────────────────────────────────────────────────────────────\n\n public OnDraft(field: IdentityField, event: Event): void {\n this.Drafts[field] = (event.target as HTMLInputElement).value;\n }\n\n /** Commits what the user typed in a field (blur / Enter) — the user's own value, confirmed by being theirs. */\n public async CommitField(field: IdentityField): Promise<void> {\n const draft = this.Drafts[field].trim();\n if (draft === '') {\n this.Drafts[field] = '';\n return;\n }\n await this.run('fill', { field, value: draft });\n // Keep the draft if the model refused it (e.g. a malformed email) so the user can correct it, not retype it.\n if (this.View && this.fieldView(field).Value === draft) {\n this.Drafts[field] = '';\n }\n this.cdr.markForCheck();\n }\n\n public async ConfirmField(field: IdentityField): Promise<void> {\n await this.run('confirm', { field });\n }\n\n public async ConfirmAll(): Promise<void> {\n await this.run('confirm', {});\n }\n\n public async SendCode(): Promise<void> {\n await this.commitPendingDrafts();\n await this.run('submit', {});\n }\n\n public async Resend(): Promise<void> {\n await this.run('resend', {});\n }\n\n public OnCodeInput(event: Event): void {\n this.CodeDraft = (event.target as HTMLInputElement).value;\n }\n\n public async SubmitCode(): Promise<void> {\n const code = this.CodeDraft;\n if (code.trim() === '') {\n return;\n }\n const outcome = await this.run('enter_code', { code });\n if (outcome.Success) {\n this.CodeDraft = '';\n }\n this.cdr.markForCheck();\n }\n\n public get HasUnconfirmed(): boolean {\n return !!this.View && ((this.View.Name.Value !== '' && !this.View.Name.Confirmed) || (this.View.Email.Value !== '' && !this.View.Email.Confirmed));\n }\n\n // ── Internals ──────────────────────────────────────────────────────────────\n\n private fieldView(field: IdentityField) {\n return field === 'name' ? this.View!.Name : this.View!.Email;\n }\n\n /** Commits fields the user typed but did not blur out of, so pressing \"Send code\" never drops them. */\n private async commitPendingDrafts(): Promise<void> {\n for (const field of ['name', 'email'] as const) {\n if (this.Drafts[field].trim() !== '') {\n await this.CommitField(field);\n }\n }\n }\n\n private async run(verb: string, args: JSONObject): Promise<RealtimeChannelVerbResult> {\n this.Busy = true;\n this.cdr.markForCheck();\n try {\n const outcome = await this.Dispatch(verb, args);\n this.ActionProblem = outcome.Success ? '' : (outcome.Error ?? 'That did not work. Please try again.');\n return outcome;\n } finally {\n this.Busy = false;\n this.cdr.markForCheck();\n }\n }\n\n private onView(view: IdentityVerificationView): void {\n const enteredCodeStage = this.View?.Status !== 'code_sent' && view.Status === 'code_sent';\n this.View = view;\n this.syncCooldown();\n this.cdr.markForCheck();\n if (enteredCodeStage) {\n // The code box did not exist until this render; move focus into it once it does.\n queueMicrotask(() => this.codeInput?.nativeElement.focus());\n }\n }\n\n private syncCooldown(): void {\n const remaining = this.View ? Math.max(0, Math.ceil((this.View.ResendAvailableAt - Date.now()) / 1000)) : 0;\n this.ResendWaitSeconds = remaining;\n if (remaining > 0 && this.tick === null) {\n this.tick = setInterval(() => this.onTick(), 1000);\n } else if (remaining === 0) {\n this.stopTick();\n }\n }\n\n private onTick(): void {\n this.syncCooldown();\n this.cdr.markForCheck();\n }\n\n private stopTick(): void {\n if (this.tick !== null) {\n clearInterval(this.tick);\n this.tick = null;\n }\n }\n}\n","@if (View; as view) {\n <section class=\"idv\" [attr.data-status]=\"view.Status\" aria-labelledby=\"idv-title\">\n <h3 id=\"idv-title\" class=\"idv__title\">Verify your identity</h3>\n\n @if (view.Status === 'verified') {\n <div class=\"idv__done\" role=\"status\">\n <i class=\"fa-solid fa-circle-check idv__done-icon\" aria-hidden=\"true\"></i>\n <div>\n <p class=\"idv__done-heading\">You're verified</p>\n <p class=\"idv__done-detail\">{{ view.Name.Value }} · {{ view.Email.Value }}</p>\n </div>\n </div>\n } @else {\n <p class=\"idv__lead\" id=\"idv-lead\">\n Check your details, then we'll email you a code and a link. Either one confirms it's you.\n </p>\n\n <div class=\"idv__field\">\n <label class=\"idv__label\" for=\"idv-name\">Your name</label>\n <input\n id=\"idv-name\"\n class=\"mj-input idv__input\"\n type=\"text\"\n autocomplete=\"name\"\n autocapitalize=\"words\"\n maxlength=\"200\"\n [value]=\"ValueFor('name')\"\n [disabled]=\"Locked || CodeStage\"\n [attr.aria-describedby]=\"IsSuggested('name') ? 'idv-name-hint' : null\"\n (input)=\"OnDraft('name', $event)\"\n (blur)=\"CommitField('name')\"\n (keydown.enter)=\"CommitField('name')\" />\n @if (IsSuggested('name')) {\n <p class=\"idv__suggested\" id=\"idv-name-hint\">\n <i class=\"fa-solid fa-wand-magic-sparkles\" aria-hidden=\"true\"></i>\n Suggested by {{ SuggestedBy('name') }} — check it's right.\n <button mjButton variant=\"outline\" size=\"sm\" type=\"button\" class=\"idv__confirm\" [disabled]=\"Busy\" (click)=\"ConfirmField('name')\">Confirm</button>\n </p>\n }\n </div>\n\n <div class=\"idv__field\">\n <label class=\"idv__label\" for=\"idv-email\">Your email</label>\n <input\n id=\"idv-email\"\n class=\"mj-input idv__input\"\n type=\"email\"\n inputmode=\"email\"\n autocomplete=\"email\"\n autocapitalize=\"none\"\n spellcheck=\"false\"\n maxlength=\"200\"\n [value]=\"ValueFor('email')\"\n [disabled]=\"Locked || CodeStage\"\n [attr.aria-describedby]=\"IsSuggested('email') ? 'idv-email-hint' : null\"\n [attr.aria-invalid]=\"view.ProblemCode === 'invalid_email' ? 'true' : null\"\n (input)=\"OnDraft('email', $event)\"\n (blur)=\"CommitField('email')\"\n (keydown.enter)=\"CommitField('email')\" />\n @if (IsSuggested('email')) {\n <p class=\"idv__suggested\" id=\"idv-email-hint\">\n <i class=\"fa-solid fa-wand-magic-sparkles\" aria-hidden=\"true\"></i>\n Suggested by {{ SuggestedBy('email') }} — check it's right.\n <button mjButton variant=\"outline\" size=\"sm\" type=\"button\" class=\"idv__confirm\" [disabled]=\"Busy\" (click)=\"ConfirmField('email')\">Confirm</button>\n </p>\n }\n </div>\n\n @if (!CodeStage) {\n <div class=\"idv__actions\">\n @if (HasUnconfirmed) {\n <button mjButton variant=\"outline\" type=\"button\" [disabled]=\"Busy || Locked\" (click)=\"ConfirmAll()\">Confirm details</button>\n }\n <button mjButton variant=\"primary\" type=\"button\" class=\"idv__send\" [disabled]=\"Busy || Locked || (!view.CanSubmit && Drafts.name === '' && Drafts.email === '')\" (click)=\"SendCode()\">\n @if (view.Status === 'sending') { Sending… } @else { Send code }\n </button>\n </div>\n } @else {\n <div class=\"idv__code\" aria-live=\"polite\">\n <p class=\"idv__sent\">\n <i class=\"fa-solid fa-envelope-circle-check\" aria-hidden=\"true\"></i>\n We emailed a code to <strong>{{ view.Destination }}</strong>. Type it below, or open the link in the email.\n </p>\n <label class=\"idv__label\" for=\"idv-code\">Code</label>\n <input\n #codeInput\n id=\"idv-code\"\n class=\"mj-input idv__input idv__code-input\"\n type=\"text\"\n inputmode=\"numeric\"\n autocomplete=\"one-time-code\"\n maxlength=\"16\"\n [value]=\"CodeDraft\"\n [disabled]=\"view.Status === 'verifying'\"\n [attr.aria-invalid]=\"view.ProblemCode === 'invalid_code' ? 'true' : null\"\n (input)=\"OnCodeInput($event)\"\n (keydown.enter)=\"SubmitCode()\" />\n <div class=\"idv__actions\">\n <button mjButton variant=\"primary\" type=\"button\" [disabled]=\"Busy || view.Status === 'verifying' || CodeDraft.trim() === ''\" (click)=\"SubmitCode()\">\n @if (view.Status === 'verifying') { Checking… } @else { Verify }\n </button>\n <button mjButton variant=\"outline\" type=\"button\" [disabled]=\"Busy || view.Status === 'verifying' || ResendWaitSeconds > 0\" (click)=\"Resend()\">\n @if (ResendWaitSeconds > 0) { Resend in {{ ResendWaitSeconds }}s } @else { Resend code }\n </button>\n </div>\n @if (view.AttemptsRemaining !== null) {\n <p class=\"idv__hint\">{{ view.AttemptsRemaining }} {{ view.AttemptsRemaining === 1 ? 'try' : 'tries' }} left.</p>\n }\n </div>\n }\n\n @if (view.Problem || ActionProblem) {\n <p class=\"idv__problem\" role=\"alert\">\n <i class=\"fa-solid fa-triangle-exclamation\" aria-hidden=\"true\"></i>\n {{ view.Problem || ActionProblem }}\n </p>\n }\n }\n </section>\n}\n"]}
|