c3-components 0.14.2 → 0.15.1

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.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { input, signal, viewChild, TemplateRef, inject, ChangeDetectorRef, effect, Component, forwardRef, model, HostListener, Directive, NgModule, Inject, Injector, Injectable, Pipe, output, ViewEncapsulation, Optional, computed, InjectionToken, contentChild, contentChildren, ViewContainerRef, HostBinding, ElementRef, DestroyRef } from '@angular/core';
2
+ import { input, signal, viewChild, TemplateRef, inject, ChangeDetectorRef, effect, Component, forwardRef, model, HostListener, Directive, NgModule, Inject, ViewContainerRef, Injector, Injectable, Pipe, output, ViewEncapsulation, Optional, computed, InjectionToken, contentChild, contentChildren, HostBinding, ElementRef, DestroyRef } from '@angular/core';
3
3
  import * as i1 from '@angular/common';
4
4
  import { CommonModule } from '@angular/common';
5
5
  import * as i2 from '@angular/forms';
@@ -380,14 +380,21 @@ class C3DialogEmbedChildComponent {
380
380
  this.dialogRef = dialogRef;
381
381
  this.data = data;
382
382
  this._cdr = _cdr;
383
- this.target = viewChild.required('target');
383
+ this.target = viewChild('target', ...(ngDevMode ? [{ debugName: "target", read: ViewContainerRef }] : [{
384
+ read: ViewContainerRef,
385
+ }]));
384
386
  // On utilise un signal pour stocker la référence du composant créé
385
387
  this.createdComponent = signal(null, ...(ngDevMode ? [{ debugName: "createdComponent" }] : []));
386
388
  }
387
389
  ngAfterViewInit() {
388
390
  // Si on a un composant, on le crée dynamiquement
389
391
  if (this.data.component && !this.data.templateRef) {
390
- const compRef = this.target().createComponent(this.data.component);
392
+ const targetRef = this.target();
393
+ if (!targetRef) {
394
+ console.error('ViewContainerRef not found');
395
+ return;
396
+ }
397
+ const compRef = targetRef.createComponent(this.data.component);
391
398
  this.createdComponent.set(compRef);
392
399
  // Injecter les inputs dans le composant
393
400
  if (this.data.inputs) {
@@ -432,7 +439,7 @@ class C3DialogEmbedChildComponent {
432
439
  }
433
440
  }
434
441
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: C3DialogEmbedChildComponent, deps: [{ token: i1$2.MatDialogRef }, { token: MAT_DIALOG_DATA }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
435
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.14", type: C3DialogEmbedChildComponent, isStandalone: false, selector: "C3DialogEmbedChildComponent", viewQueries: [{ propertyName: "target", first: true, predicate: ["target"], descendants: true, isSignal: true }], ngImport: i0, template: `
442
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.14", type: C3DialogEmbedChildComponent, isStandalone: false, selector: "C3DialogEmbedChildComponent", viewQueries: [{ propertyName: "target", first: true, predicate: ["target"], descendants: true, read: ViewContainerRef, isSignal: true }], ngImport: i0, template: `
436
443
  <div [class]="'dialog-content-container ' + (data.classContainer || '')">
437
444
  @if (data.toolbar) {
438
445
  <mat-toolbar [color]="data.toolbar.color || 'default'" class="py-1">
@@ -445,17 +452,17 @@ class C3DialogEmbedChildComponent {
445
452
  }
446
453
  </mat-toolbar>
447
454
  }
448
-
455
+
449
456
  <div [class]="'dialog-content ' + (data.classContent || '')">
450
457
  <!-- Si templateRef est présent, on l'affiche directement,
451
458
  sinon on laisse la place au composant dynamique -->
452
459
  @if (data.templateRef) {
453
460
  <ng-container *ngTemplateOutlet="data.templateRef"></ng-container>
454
461
  } @else {
455
- <ng-template #target></ng-template>
462
+ <ng-container #target></ng-container>
456
463
  }
457
464
  </div>
458
-
465
+
459
466
  @if (data.actions && data.actions.length > 0) {
460
467
  <div [class]="'dialog-actions ' + (data.classActions || '')">
461
468
  @for (action of data.actions; track action.label) {
@@ -490,7 +497,7 @@ class C3DialogEmbedChildComponent {
490
497
  </div>
491
498
  }
492
499
  </div>
493
- `, isInline: true, styles: [".dialog-content-container{display:flex;flex-direction:column;height:100%;padding:1rem;overflow:auto}.dialog-content-container .dialog-content{display:flex;flex-direction:column;height:100%;overflow:auto;flex-grow:1}.dialog-content-container .mat-toolbar{display:flex;justify-content:space-between;align-items:center;border-radius:.25rem}.dialog-content-container .mat-toolbar span{color:inherit}.dialog-content-container .spacer{flex:1 1 auto;min-width:16px}.dialog-actions{display:flex;justify-content:flex-end;gap:.5rem}\n"], dependencies: [{ kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i3.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: i1$2.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "component", type: i2$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i5$1.MatToolbar, selector: "mat-toolbar", inputs: ["color"], exportAs: ["matToolbar"] }] }); }
500
+ `, isInline: true, styles: [".dialog-content-container{display:flex;flex-direction:column;height:100%;padding:1rem;overflow:auto}.dialog-content-container .dialog-content{display:flex;flex-direction:column;height:100%;overflow:auto;flex-grow:1}.dialog-content-container .mat-toolbar{display:flex;justify-content:space-between;align-items:center;border-radius:.25rem}.dialog-content-container .mat-toolbar span{color:inherit}.dialog-content-container .spacer{flex:1 1 auto;min-width:16px}.dialog-actions{display:flex;justify-content:flex-end;gap:.5rem}\n"], dependencies: [{ kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i3.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: i1$2.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "component", type: i2$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i5$1.MatToolbar, selector: "mat-toolbar", inputs: ["color"], exportAs: ["matToolbar"] }] }); }
494
501
  }
495
502
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: C3DialogEmbedChildComponent, decorators: [{
496
503
  type: Component,
@@ -507,17 +514,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImpo
507
514
  }
508
515
  </mat-toolbar>
509
516
  }
510
-
517
+
511
518
  <div [class]="'dialog-content ' + (data.classContent || '')">
512
519
  <!-- Si templateRef est présent, on l'affiche directement,
513
520
  sinon on laisse la place au composant dynamique -->
514
521
  @if (data.templateRef) {
515
522
  <ng-container *ngTemplateOutlet="data.templateRef"></ng-container>
516
523
  } @else {
517
- <ng-template #target></ng-template>
524
+ <ng-container #target></ng-container>
518
525
  }
519
526
  </div>
520
-
527
+
521
528
  @if (data.actions && data.actions.length > 0) {
522
529
  <div [class]="'dialog-actions ' + (data.classActions || '')">
523
530
  @for (action of data.actions; track action.label) {
@@ -552,11 +559,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImpo
552
559
  </div>
553
560
  }
554
561
  </div>
555
- `, standalone: false, styles: [".dialog-content-container{display:flex;flex-direction:column;height:100%;padding:1rem;overflow:auto}.dialog-content-container .dialog-content{display:flex;flex-direction:column;height:100%;overflow:auto;flex-grow:1}.dialog-content-container .mat-toolbar{display:flex;justify-content:space-between;align-items:center;border-radius:.25rem}.dialog-content-container .mat-toolbar span{color:inherit}.dialog-content-container .spacer{flex:1 1 auto;min-width:16px}.dialog-actions{display:flex;justify-content:flex-end;gap:.5rem}\n"] }]
562
+ `, standalone: false, styles: [".dialog-content-container{display:flex;flex-direction:column;height:100%;padding:1rem;overflow:auto}.dialog-content-container .dialog-content{display:flex;flex-direction:column;height:100%;overflow:auto;flex-grow:1}.dialog-content-container .mat-toolbar{display:flex;justify-content:space-between;align-items:center;border-radius:.25rem}.dialog-content-container .mat-toolbar span{color:inherit}.dialog-content-container .spacer{flex:1 1 auto;min-width:16px}.dialog-actions{display:flex;justify-content:flex-end;gap:.5rem}\n"] }]
556
563
  }], ctorParameters: () => [{ type: i1$2.MatDialogRef }, { type: undefined, decorators: [{
557
564
  type: Inject,
558
565
  args: [MAT_DIALOG_DATA]
559
- }] }, { type: i0.ChangeDetectorRef }], propDecorators: { target: [{ type: i0.ViewChild, args: ['target', { isSignal: true }] }] } });
566
+ }] }, { type: i0.ChangeDetectorRef }], propDecorators: { target: [{ type: i0.ViewChild, args: ['target', { ...{
567
+ read: ViewContainerRef,
568
+ }, isSignal: true }] }] } });
560
569
 
561
570
  class C3DialogTemplateComponent {
562
571
  constructor() {
@@ -1243,12 +1252,63 @@ class C3FileViewer {
1243
1252
  ? of(this.locationBlobMap.get(location))
1244
1253
  : this.getFile(location).pipe(map((response) => URL.createObjectURL(response)), tap((url) => this.locationBlobMap.set(location, url)))), tap(() => this.onLoaded()));
1245
1254
  }
1255
+ /**
1256
+ * Encode une URL de manière sûre pour éviter les problèmes avec les caractères spéciaux
1257
+ * comme +, espaces, etc.
1258
+ * Cette fonction encode correctement les segments du chemin et les paramètres de requête.
1259
+ */
1260
+ encodeUrl(url) {
1261
+ try {
1262
+ // Si l'URL est relative, on doit encoder manuellement
1263
+ if (!url.includes('://')) {
1264
+ // Pour les URLs relatives, on sépare le chemin et les paramètres de requête
1265
+ const [path, query] = url.split('?');
1266
+ // Encoder chaque segment du chemin (sauf les séparateurs /)
1267
+ const encodedPath = path
1268
+ .split('/')
1269
+ .map((segment) => (segment ? encodeURIComponent(segment) : ''))
1270
+ .join('/');
1271
+ if (query) {
1272
+ // Pour les paramètres de requête, encoder chaque clé et valeur
1273
+ const params = query.split('&');
1274
+ const encodedParams = params.map((param) => {
1275
+ const [key, ...valueParts] = param.split('=');
1276
+ const value = valueParts.join('=');
1277
+ return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
1278
+ });
1279
+ return `${encodedPath}?${encodedParams.join('&')}`;
1280
+ }
1281
+ return encodedPath;
1282
+ }
1283
+ // Pour les URLs absolues, utiliser le constructeur URL pour parser
1284
+ const urlObj = new URL(url);
1285
+ // Encoder chaque segment du chemin
1286
+ const encodedPath = urlObj.pathname
1287
+ .split('/')
1288
+ .map((segment) => (segment ? encodeURIComponent(segment) : ''))
1289
+ .join('/');
1290
+ // Les searchParams sont déjà gérés correctement par URLSearchParams
1291
+ // mais on doit s'assurer que les valeurs sont encodées
1292
+ const searchParams = new URLSearchParams();
1293
+ urlObj.searchParams.forEach((value, key) => {
1294
+ searchParams.append(key, value);
1295
+ });
1296
+ const encodedSearch = searchParams.toString() ? `?${searchParams.toString()}` : '';
1297
+ return `${urlObj.protocol}//${urlObj.host}${encodedPath}${encodedSearch}${urlObj.hash}`;
1298
+ }
1299
+ catch (e) {
1300
+ // Si le parsing échoue (URL malformée ou relative sans base),
1301
+ // encoder avec encodeURI qui préserve la structure de l'URL
1302
+ return encodeURI(url);
1303
+ }
1304
+ }
1246
1305
  getFile(location) {
1247
1306
  const client = this.config.customClient || this.client;
1248
1307
  if (!client) {
1249
1308
  throw new Error('No http client provided. Please provide a custom client or import HttpClientModule');
1250
1309
  }
1251
- return client(location, {
1310
+ const encodedLocation = this.encodeUrl(location);
1311
+ return client(encodedLocation, {
1252
1312
  responseType: 'blob',
1253
1313
  });
1254
1314
  }
@@ -1395,7 +1455,8 @@ class C3FileViewer {
1395
1455
  }
1396
1456
  downloadWithClient(file, client, originalName) {
1397
1457
  // Utiliser le client fourni pour récupérer le fichier
1398
- client(file.location, {
1458
+ const encodedLocation = this.encodeUrl(file.location);
1459
+ client(encodedLocation, {
1399
1460
  responseType: 'blob',
1400
1461
  }).subscribe({
1401
1462
  next: (blob) => {