@naniteninja/profile-comparison-lib 1.0.3 → 1.0.6

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/index.d.ts CHANGED
@@ -1,10 +1,39 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { InjectionToken, OnInit, AfterViewInit, OnChanges, EventEmitter, ElementRef, Renderer2, ChangeDetectorRef, SimpleChanges } from '@angular/core';
3
3
  import { Observable, BehaviorSubject } from 'rxjs';
4
+ import * as i2 from '@angular/common';
4
5
  import * as i3 from '@angular/common/http';
5
6
  import { HttpClient } from '@angular/common/http';
6
- import * as i2 from '@angular/common';
7
7
  import * as i4 from '@angular/forms';
8
+ import * as i5 from '@naniteninja/ionic-lib';
9
+
10
+ /** Backend mode for the profile comparison component. */
11
+ declare enum BackendMode {
12
+ /** Use the real deployed backend (default). */
13
+ Real = 0,
14
+ /** Use a local mock server at localhost:3000. */
15
+ Mock = 1
16
+ }
17
+ declare const BACKEND_MODE_URLS: Record<BackendMode, string>;
18
+ /** Either a static base URL or a getter that returns the current base URL (for runtime toggle). */
19
+ type ProfileComparisonApiBaseUrl = string | (() => string | null);
20
+ /**
21
+ * Legacy injection token for the backend base URL.
22
+ * Prefer using the [backendMode] or [backendUrl] @Input on the component instead.
23
+ * Kept for backward compatibility — lowest priority when resolving the URL.
24
+ */
25
+ declare const PROFILE_COMPARISON_API_BASE_URL: InjectionToken<ProfileComparisonApiBaseUrl | null>;
26
+ /** Optional getter: when true, lib and backend service log steps to console for diagnosis. */
27
+ declare const PROFILE_COMPARISON_VERBOSE_LOGGING: InjectionToken<() => boolean>;
28
+ /**
29
+ * Resolves the active backend URL from inputs, with fallback to injection token.
30
+ *
31
+ * Priority:
32
+ * 1. Explicit backendUrl (custom URL string)
33
+ * 2. BackendMode enum (Real or Mock)
34
+ * 3. Legacy PROFILE_COMPARISON_API_BASE_URL token
35
+ */
36
+ declare function resolveBackendUrl(backendUrl: string | null | undefined, backendMode: BackendMode, legacyTokenUrl: string | null | undefined): string | null;
8
37
 
9
38
  interface IProfileConfig {
10
39
  person1Interests: string[];
@@ -12,6 +41,8 @@ interface IProfileConfig {
12
41
  person3Interests: string[];
13
42
  user1Image: string;
14
43
  user2Image: string;
44
+ edgeShading?: boolean;
45
+ shadingColor?: string;
15
46
  }
16
47
 
17
48
  interface IBoundingBox {
@@ -177,6 +208,7 @@ interface IComparisonPayload {
177
208
  centerItem: string[];
178
209
  matrixData: IMatrixData | null;
179
210
  rawLLMOutput?: string;
211
+ debug?: any;
180
212
  }
181
213
 
182
214
  declare const STORE_NAMES: readonly ["openai-spacer", "openai-alignment", "openai-similarity", "openai-embeddings", "profile-face", "profile-compare"];
@@ -204,53 +236,6 @@ declare class CachePersistenceService {
204
236
  static ɵprov: i0.ɵɵInjectableDeclaration<CachePersistenceService>;
205
237
  }
206
238
 
207
- declare class EmbeddingService {
208
- private model$;
209
- getEmbedding(text: string): Observable<Float32Array>;
210
- /**
211
- * Group-align two lists based on semantic similarity, allowing one-to-many relationships.
212
- *
213
- * Design goals:
214
- * - Semantic relevance takes priority over original order or spacing.
215
- * - Each term in listB is assigned to the single most similar anchor in listA (if above threshold).
216
- * - For an anchor in listA with multiple highly related listB terms, they are emitted as consecutive rows:
217
- * [A, B1], ['-', B2], ['-', B3], ... so they render adjacently and remain visually connected.
218
- * - Low-similarity/unassigned terms from either side are appended at the end and never break groups.
219
- */
220
- groupAlignLists(listA: string[], listB: string[], threshold?: number, preserveLeftOrder?: boolean, exclusivityMargin?: number, leftCohesion?: number): Observable<IAlignmentRow[]>;
221
- cosineSimilarity(a: Float32Array, b: Float32Array): number;
222
- /**
223
- * Align words in listA with their most semantically similar words in listB
224
- *
225
- * Algorithm:
226
- * 1. Generate embeddings for all words in both lists using Universal Sentence Encoder
227
- * 2. For each word in listA, compare its embedding with all words in listB
228
- * 3. Find the word in listB with highest cosine similarity score
229
- * 4. Return alignment results with similarity scores
230
- *
231
- * @param listA - Source list of words to align
232
- * @param listB - Target list of words to find matches in
233
- * @returns Observable of alignment results with word, alignedWith, score, and index
234
- */
235
- alignLists(listA: string[], listB: string[]): Observable<IWordAlignment[]>;
236
- /**
237
- * Find best matching pairs between two lists above a similarity threshold
238
- *
239
- * @param listA - Source list of words
240
- * @param listB - Target list of words to match against
241
- * @param threshold - Minimum similarity score (0-1, default: 0.15)
242
- * @returns Observable of word pairs with similarity scores
243
- */
244
- findBestMatchingPairs(listA: string[], listB: string[], threshold?: number): Observable<IWordPair[]>;
245
- calculateSimilarity(primaryText: string, comparisonText: string): Observable<number>;
246
- testWordSimilarity(word1: string, word2: string): Observable<void>;
247
- private domainCompatibilityCap;
248
- private computeLexicalBoost;
249
- private loadModel;
250
- static ɵfac: i0.ɵɵFactoryDeclaration<EmbeddingService, never>;
251
- static ɵprov: i0.ɵɵInjectableDeclaration<EmbeddingService>;
252
- }
253
-
254
239
  declare class FileConversionService {
255
240
  private static readonly MIME_TYPE_JPEG;
256
241
  private static readonly MIME_TYPE_PNG;
@@ -281,18 +266,6 @@ declare class ImageCompressionService {
281
266
  static ɵprov: i0.ɵɵInjectableDeclaration<ImageCompressionService>;
282
267
  }
283
268
 
284
- /** Either a static base URL or a getter that returns the current base URL (for runtime toggle). */
285
- type ProfileComparisonApiBaseUrl = string | (() => string | null);
286
- /**
287
- * When provided, ProfileService and OpenAIEmbeddingService call this backend base URL
288
- * (e.g. 'http://localhost:3000/api') for all profile/embedding endpoints instead of
289
- * calling external APIs directly with keys. Can be a string or a getter function for runtime toggle.
290
- * When not provided or getter returns null, the lib uses the direct path with keys.
291
- */
292
- declare const PROFILE_COMPARISON_API_BASE_URL: InjectionToken<ProfileComparisonApiBaseUrl | null>;
293
- /** Optional getter: when true, lib and backend service log steps to console for diagnosis. */
294
- declare const PROFILE_COMPARISON_VERBOSE_LOGGING: InjectionToken<() => boolean>;
295
-
296
269
  /**
297
270
  * OpenAI Alignment Service
298
271
  * Uses OpenAI Chat Completions API to align two lists of text in a single request.
@@ -417,12 +390,16 @@ declare class ProfileService {
417
390
  declare class ProfileComparisonBackendService {
418
391
  private http;
419
392
  private apiBaseUrl;
420
- private getVerboseLogging?;
421
- constructor(http: HttpClient, apiBaseUrl: ProfileComparisonApiBaseUrl | null, getVerboseLogging?: (() => boolean) | undefined);
393
+ private getVerboseLogging;
394
+ constructor();
395
+ static extractErrorMessage(err: unknown): string;
422
396
  private log;
397
+ /** Returns the legacy token URL (for backward compat fallback). */
398
+ getLegacyTokenUrl(): string | null;
399
+ /** @deprecated Use getLegacyTokenUrl(). Kept for backward compat. */
423
400
  getBaseUrl(): string | null;
424
- getComparison(config: IProfileConfig): Observable<IComparisonPayload>;
425
- static ɵfac: i0.ɵɵFactoryDeclaration<ProfileComparisonBackendService, [null, { optional: true; }, { optional: true; }]>;
401
+ getComparison(config: IProfileConfig, baseUrl?: string | null): Observable<IComparisonPayload>;
402
+ static ɵfac: i0.ɵɵFactoryDeclaration<ProfileComparisonBackendService, never>;
426
403
  static ɵprov: i0.ɵɵInjectableDeclaration<ProfileComparisonBackendService>;
427
404
  }
428
405
 
@@ -447,6 +424,7 @@ declare class ProfileComparisonLibComponent implements OnInit, AfterViewInit, On
447
424
  private static readonly DEFAULT_MAX_HEIGHT;
448
425
  private static readonly SPACER_SMALL;
449
426
  private static readonly SPACER_LARGE;
427
+ private static readonly PLACEHOLDER;
450
428
  private static readonly CONSOLIDATION_SEPARATOR_X;
451
429
  private static readonly CONSOLIDATION_SEPARATOR_SLASH;
452
430
  private static readonly FACEPP_RATE_LIMIT_DELAY_MS;
@@ -465,6 +443,8 @@ declare class ProfileComparisonLibComponent implements OnInit, AfterViewInit, On
465
443
  private static readonly TRANSFORM_RESET;
466
444
  private static readonly TRANSITION_RESET_DELAY_MS;
467
445
  config: IProfileConfig;
446
+ backendMode: BackendMode;
447
+ backendUrl: string | null;
468
448
  fadeAllEdges: boolean;
469
449
  matrixDataChange: EventEmitter<IMatrixData>;
470
450
  rawLLMOutputChange: EventEmitter<string>;
@@ -505,6 +485,8 @@ declare class ProfileComparisonLibComponent implements OnInit, AfterViewInit, On
505
485
  alignedPerson2Interests: string[];
506
486
  leftProfileClicked: boolean;
507
487
  rightProfileClicked: boolean;
488
+ leftShapeAnimating: boolean;
489
+ rightShapeAnimating: boolean;
508
490
  sortedA: {
509
491
  item: string;
510
492
  score: number;
@@ -522,21 +504,19 @@ declare class ProfileComparisonLibComponent implements OnInit, AfterViewInit, On
522
504
  matrixData: IMatrixData | null;
523
505
  /** When false, backend URL is not provided — show "Configure backend". */
524
506
  backendConfigured: boolean;
507
+ /** The resolved backend URL computed from inputs and legacy token. */
508
+ private resolvedBackendUrl;
525
509
  compressionConfig: IImageCompressionConfig;
526
510
  private computeSub?;
527
511
  /** Incremented on each fetchComparison(); used to ignore stale success/error from an older request. */
528
512
  private fetchRequestId;
529
513
  leftContainer: ElementRef;
530
514
  rightContainer: ElementRef;
531
- profileFlex: ElementRef<HTMLElement>;
532
- profileImgLeft: ElementRef<HTMLElement>;
533
- profileImgRight: ElementRef<HTMLElement>;
515
+ leftFrame: ElementRef<HTMLElement>;
516
+ rightFrame: ElementRef<HTMLElement>;
517
+ leftBgFrame: ElementRef<HTMLElement>;
518
+ rightBgFrame: ElementRef<HTMLElement>;
534
519
  shapeContainer: ElementRef<HTMLElement>;
535
- shapeBg: ElementRef<HTMLElement>;
536
- shapeBg1: ElementRef<SVGElement>;
537
- shapeBg2: ElementRef<SVGElement>;
538
- shapeTextLeft: ElementRef<HTMLElement>;
539
- shapeTextRight: ElementRef<HTMLElement>;
540
520
  shapeTextCenter: ElementRef<HTMLElement>;
541
521
  constructor(backendService: ProfileComparisonBackendService, renderer: Renderer2, fileConversionService: FileConversionService, imageCompressionService: ImageCompressionService, cdr: ChangeDetectorRef, getVerboseLogging?: (() => boolean) | undefined);
542
522
  private log;
@@ -547,6 +527,27 @@ declare class ProfileComparisonLibComponent implements OnInit, AfterViewInit, On
547
527
  ngOnChanges(changes: SimpleChanges): void;
548
528
  /** Use for template: hide left/right item when it's a shared (center) item. Compares case-insensitively. */
549
529
  isInCenter(interest: string): boolean;
530
+ /**
531
+ * Returns true if the value is a placeholder string consisting only of one or more dashes.
532
+ * Handles variations like "-", "---", "----", etc.
533
+ */
534
+ /**
535
+ * Returns true if we should show a dash on the side instead of the text.
536
+ * This happens if:
537
+ * 1. The interest is a placeholder (----).
538
+ * 2. The interest exactly matches the center label at that index (to avoid redundancy).
539
+ */
540
+ shouldShowDash(interest: string, index: number): boolean;
541
+ /**
542
+ * Returns true if the center label at the current index is a repeat of the one above it.
543
+ * This is used to "collapse" repeating categories into dashes.
544
+ */
545
+ isCenterRedundant(index: number): boolean;
546
+ /**
547
+ * Reorders the aligned results so that items with identical center labels follow each other.
548
+ */
549
+ private regroupByCenterLabel;
550
+ isPlaceholder(val: unknown): boolean;
550
551
  private fetchComparison;
551
552
  private updateConfigProperties;
552
553
  private buildConfigWithDefaults;
@@ -558,6 +559,7 @@ declare class ProfileComparisonLibComponent implements OnInit, AfterViewInit, On
558
559
  waitForImagesAndInitDrag(): void;
559
560
  initDrag(): void;
560
561
  onViewProfile(side: 'left' | 'right'): void;
562
+ onShapeClick(side: 'left' | 'right'): void;
561
563
  private compressConfigImagesIfNeeded;
562
564
  private compressImageStringToDataUrl;
563
565
  getEyeCoordinatesFromBBox(bbox: IBoundingBox): {
@@ -582,14 +584,14 @@ declare class ProfileComparisonLibComponent implements OnInit, AfterViewInit, On
582
584
  applyDefaultAlignment(): void;
583
585
  isValidFaceData(face: IBoundingBox): boolean;
584
586
  static ɵfac: i0.ɵɵFactoryDeclaration<ProfileComparisonLibComponent, [null, null, null, null, null, { optional: true; }]>;
585
- static ɵcmp: i0.ɵɵComponentDeclaration<ProfileComparisonLibComponent, "lib-profile-comparison", never, { "config": { "alias": "config"; "required": false; }; "fadeAllEdges": { "alias": "fadeAllEdges"; "required": false; }; }, { "matrixDataChange": "matrixDataChange"; "rawLLMOutputChange": "rawLLMOutputChange"; "viewProfileClick": "viewProfileClick"; }, never, never, false, never>;
587
+ static ɵcmp: i0.ɵɵComponentDeclaration<ProfileComparisonLibComponent, "lib-profile-comparison", never, { "config": { "alias": "config"; "required": false; }; "backendMode": { "alias": "backendMode"; "required": false; }; "backendUrl": { "alias": "backendUrl"; "required": false; }; "fadeAllEdges": { "alias": "fadeAllEdges"; "required": false; }; }, { "matrixDataChange": "matrixDataChange"; "rawLLMOutputChange": "rawLLMOutputChange"; "viewProfileClick": "viewProfileClick"; }, never, never, false, never>;
586
588
  }
587
589
 
588
590
  declare class ProfileComparisonLibModule {
589
591
  static ɵfac: i0.ɵɵFactoryDeclaration<ProfileComparisonLibModule, never>;
590
- static ɵmod: i0.ɵɵNgModuleDeclaration<ProfileComparisonLibModule, [typeof ProfileComparisonLibComponent], [typeof i2.CommonModule, typeof i3.HttpClientModule, typeof i4.FormsModule, typeof i4.ReactiveFormsModule], [typeof ProfileComparisonLibComponent]>;
592
+ static ɵmod: i0.ɵɵNgModuleDeclaration<ProfileComparisonLibModule, [typeof ProfileComparisonLibComponent], [typeof i2.CommonModule, typeof i3.HttpClientModule, typeof i4.FormsModule, typeof i4.ReactiveFormsModule, typeof i5.LibMarqueeModule], [typeof ProfileComparisonLibComponent]>;
591
593
  static ɵinj: i0.ɵɵInjectorDeclaration<ProfileComparisonLibModule>;
592
594
  }
593
595
 
594
- export { CachePersistenceService, EmbeddingService, FileConversionService, ImageCompressionService, OpenAIEmbeddingService, PROFILE_COMPARISON_API_BASE_URL, PROFILE_COMPARISON_VERBOSE_LOGGING, ProfileComparisonBackendService, ProfileComparisonLibComponent, ProfileComparisonLibModule, ProfileComparisonLibService, ProfileService };
596
+ export { BACKEND_MODE_URLS, BackendMode, CachePersistenceService, FileConversionService, ImageCompressionService, OpenAIEmbeddingService, PROFILE_COMPARISON_API_BASE_URL, PROFILE_COMPARISON_VERBOSE_LOGGING, ProfileComparisonBackendService, ProfileComparisonLibComponent, ProfileComparisonLibModule, ProfileComparisonLibService, ProfileService, resolveBackendUrl };
595
597
  export type { CacheStoreName, FaceDetectionData, FaceDetectionResponse, FileInputEvent, IAlignmentRow, IBoundingBox, IComparisonPayload, IComparisonResult, IEnvironment, IFaceBoxWithLandmarks, IFaceDetectionResult, IFaceLandmarks, IFacePlusPlusFace, IFacePlusPlusResponse, IFaceRectangle, IImageCompressionConfig, IMatrixData, IMatrixLegendItem, IMatrixRow, IOpenAIEmbeddingItem, IOpenAIResponse, IPoint, IProfileConfig, ISimilarityResponse, ISimilarityThreshold, IWordAlignment, IWordPair };
package/package.json CHANGED
@@ -1,14 +1,12 @@
1
1
  {
2
2
  "name": "@naniteninja/profile-comparison-lib",
3
- "version": "1.0.3",
3
+ "version": "1.0.6",
4
4
  "peerDependencies": {
5
5
  "@angular/common": "^20.0.0",
6
6
  "@angular/core": "^20.0.0"
7
7
  },
8
8
  "dependencies": {
9
- "tslib": "^2.3.0",
10
- "@tensorflow-models/universal-sentence-encoder": "^1.3.3",
11
- "@tensorflow/tfjs": "^4.22.0"
9
+ "tslib": "^2.3.0"
12
10
  },
13
11
  "module": "fesm2022/naniteninja-profile-comparison-lib.mjs",
14
12
  "typings": "index.d.ts",