taon-ui 19.0.30 → 19.0.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/browser/fesm2022/taon-ui.mjs +180 -2
  2. package/browser/fesm2022/taon-ui.mjs.map +1 -1
  3. package/browser/lib/ui/index.d.ts +2 -1
  4. package/browser/lib/ui/taon-iframe-sync/taon-iframe-sync.component.d.ts +31 -0
  5. package/browser/package.json +1 -1
  6. package/lib/build-info._auto-generated_.d.ts +1 -1
  7. package/lib/build-info._auto-generated_.js +1 -1
  8. package/lib/env/env.angular-node-app.d.ts +1 -0
  9. package/lib/env/env.angular-node-app.js +3 -2
  10. package/lib/env/env.angular-node-app.js.map +1 -1
  11. package/lib/env/env.docs-webapp.d.ts +1 -0
  12. package/lib/env/env.docs-webapp.js +3 -2
  13. package/lib/env/env.docs-webapp.js.map +1 -1
  14. package/lib/env/env.electron-app.d.ts +1 -0
  15. package/lib/env/env.electron-app.js +3 -2
  16. package/lib/env/env.electron-app.js.map +1 -1
  17. package/lib/env/env.mobile-app.d.ts +1 -0
  18. package/lib/env/env.mobile-app.js +3 -2
  19. package/lib/env/env.mobile-app.js.map +1 -1
  20. package/lib/env/env.npm-lib-and-cli-tool.d.ts +1 -0
  21. package/lib/env/env.npm-lib-and-cli-tool.js +3 -2
  22. package/lib/env/env.npm-lib-and-cli-tool.js.map +1 -1
  23. package/lib/env/env.vscode-plugin.d.ts +1 -0
  24. package/lib/env/env.vscode-plugin.js +3 -2
  25. package/lib/env/env.vscode-plugin.js.map +1 -1
  26. package/lib/index.js +2 -2
  27. package/lib/layouts/taon-bootstrap-navbar/index.js +2 -2
  28. package/lib/ui/directives/index.js +2 -2
  29. package/lib/ui/index.d.ts +2 -1
  30. package/lib/ui/index.js +2 -2
  31. package/lib/ui/taon-github-fork-me-corner/index.js +2 -2
  32. package/lib/ui/taon-github-fork-me-ribbon/index.js +2 -2
  33. package/lib/ui/taon-iframe-sync/index.d.ts +1 -0
  34. package/lib/ui/taon-iframe-sync/index.js +5 -0
  35. package/lib/ui/taon-iframe-sync/index.js.map +1 -0
  36. package/lib/ui/taon-iframe-sync/taon-iframe-sync.component.d.ts +27 -0
  37. package/lib/ui/taon-iframe-sync/taon-iframe-sync.d.ts +24 -0
  38. package/lib/ui/taon-iframe-sync/taon-iframe-sync.js +118 -0
  39. package/lib/ui/taon-iframe-sync/taon-iframe-sync.js.map +1 -0
  40. package/lib/ui/taon-notifications/taon-notifications.models.js +2 -2
  41. package/lib/ui/taon-progress-bar/index.js +2 -2
  42. package/lib/ui/taon-session-passcode/index.js +2 -2
  43. package/lib/ui/taon-table/index.js +2 -2
  44. package/package.json +1 -1
  45. package/websql/fesm2022/taon-ui.mjs +180 -2
  46. package/websql/fesm2022/taon-ui.mjs.map +1 -1
  47. package/websql/lib/ui/index.d.ts +2 -1
  48. package/websql/lib/ui/taon-iframe-sync/taon-iframe-sync.component.d.ts +31 -0
  49. package/websql/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.dummy1765050646064 = dummy1765050646064;
4
- function dummy1765050646064() { }
3
+ exports.dummy1765313656635 = dummy1765313656635;
4
+ function dummy1765313656635() { }
5
5
  //# sourceMappingURL=index.js.map
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.dummy1765050646085 = dummy1765050646085;
4
- function dummy1765050646085() { }
3
+ exports.dummy1765313656686 = dummy1765313656686;
4
+ function dummy1765313656686() { }
5
5
  //# sourceMappingURL=index.js.map
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.dummy1765050646099 = dummy1765050646099;
4
- function dummy1765050646099() { }
3
+ exports.dummy1765313656743 = dummy1765313656743;
4
+ function dummy1765313656743() { }
5
5
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "taon-ui",
3
- "version": "19.0.30",
3
+ "version": "19.0.32",
4
4
  "scripts": {
5
5
  "taon init": "taon init",
6
6
  "taon start": "taon start",
@@ -3,6 +3,7 @@ import { EventEmitter, HostListener, HostBinding, Output, Input, Directive, Pipe
3
3
  import { _, json5, Helpers } from 'tnp-core/websql';
4
4
  import { Log, Level } from 'ng2-logger/websql';
5
5
  import * as i1 from '@angular/platform-browser';
6
+ import { DomSanitizer } from '@angular/platform-browser';
6
7
  import { A11yModule } from '@angular/cdk/a11y';
7
8
  import * as i5$1 from '@angular/cdk/drag-drop';
8
9
  import { DragDropModule } from '@angular/cdk/drag-drop';
@@ -52,7 +53,7 @@ import { MatToolbarModule } from '@angular/material/toolbar';
52
53
  import { MatTooltipModule } from '@angular/material/tooltip';
53
54
  import { MatTreeModule } from '@angular/material/tree';
54
55
  import * as i2$1 from '@angular/common';
55
- import { CommonModule } from '@angular/common';
56
+ import { CommonModule, NgIf } from '@angular/common';
56
57
  import { Resource } from 'ng2-rest/websql';
57
58
  import * as i1$1 from '@ngneat/hot-toast';
58
59
  import { __decorate, __metadata } from 'tslib';
@@ -72,6 +73,8 @@ import { StaticColumnsModule } from 'static-columns/websql';
72
73
  import { MatFormFieldModule } from '@angular/material/form-field';
73
74
  import * as i4 from 'ngx-scrollbar';
74
75
  import { NgScrollbarModule } from 'ngx-scrollbar';
76
+ import { Router, ActivatedRoute, NavigationEnd } from '@angular/router';
77
+ import { distinctUntilChanged as distinctUntilChanged$1, takeUntil as takeUntil$1, filter } from 'rxjs/operators';
75
78
  import * as i2$3 from '@ng-bootstrap/ng-bootstrap';
76
79
  import { NgbCollapseModule } from '@ng-bootstrap/ng-bootstrap';
77
80
  import { ModalModule } from 'ngx-bootstrap/modal';
@@ -1225,6 +1228,181 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImpo
1225
1228
  args: ['window:resize', ['$event']]
1226
1229
  }] } });
1227
1230
 
1231
+ // iframe-sync.component.ts
1232
+ // taon-iframe-sync.component.ts
1233
+ class TaonIframeSyncComponent {
1234
+ constructor() {
1235
+ this.destroy$ = new Subject();
1236
+ this.iframeWin = null;
1237
+ // This is the key: iframe stays hidden until first correct page is confirmed loaded
1238
+ this.isReady = false;
1239
+ this.hasInitialSync = false;
1240
+ this.queryParamKey = 'internalIframePath';
1241
+ this.initialPath = null;
1242
+ this.router = inject(Router);
1243
+ this.route = inject(ActivatedRoute);
1244
+ this.sanitizer = inject(DomSanitizer);
1245
+ // This is called when iframe confirms: "Yes, I loaded the correct page!"
1246
+ this.handleIframeMessage = (event) => {
1247
+ const expected = this.targetOrigin ?? this.getSafeOrigin(this.iframeSrc);
1248
+ if (event.origin !== expected)
1249
+ return;
1250
+ // NEW: iframe tells us when it's truly ready
1251
+ if (event.data?.type === 'IFRAME_READY') {
1252
+ this.isReady = true; // NOW show the iframe!
1253
+ return;
1254
+ }
1255
+ if (event.data?.type === 'IFRAME_PATH_UPDATE') {
1256
+ const path = event.data.path || '/';
1257
+ this.router.navigate([], {
1258
+ queryParams: { [this.queryParamKey]: path === '/' ? null : path },
1259
+ queryParamsHandling: 'merge',
1260
+ replaceUrl: true,
1261
+ });
1262
+ }
1263
+ };
1264
+ }
1265
+ // ... same inputs as before
1266
+ #src;
1267
+ set iframeSrc(v) {
1268
+ this.#src = v.trim();
1269
+ this.safeSrc = this.sanitizer.bypassSecurityTrustResourceUrl(this.#src);
1270
+ }
1271
+ get iframeSrc() {
1272
+ return this.#src;
1273
+ }
1274
+ ngAfterViewInit() {
1275
+ this.setupSync();
1276
+ window.addEventListener('message', this.handleIframeMessage);
1277
+ }
1278
+ setupSync() {
1279
+ this.route.queryParamMap
1280
+ .pipe(distinctUntilChanged$1((a, b) => a.get(this.queryParamKey) === b.get(this.queryParamKey)), takeUntil$1(this.destroy$))
1281
+ .subscribe(() => this.sendNavigateIfReady());
1282
+ this.router.events
1283
+ .pipe(filter((e) => e instanceof NavigationEnd), takeUntil$1(this.destroy$))
1284
+ .subscribe(() => this.sendNavigateIfReady());
1285
+ }
1286
+ onIframeLoad() {
1287
+ this.iframeWin = this.iframeRef?.nativeElement?.contentWindow;
1288
+ // Send the correct path — iframe will load it
1289
+ this.sendNavigateIfReady();
1290
+ // The real magic: wait for iframe to confirm it loaded the right page
1291
+ // (we'll enhance the iframe script to send a "READY" message)
1292
+ }
1293
+ sendNavigateIfReady() {
1294
+ if (!this.iframeWin ||
1295
+ !this.isValidUrl(this.iframeSrc) ||
1296
+ this.hasInitialSync)
1297
+ return;
1298
+ const path = this.route.snapshot.queryParamMap.get(this.queryParamKey) ??
1299
+ this.initialPath ??
1300
+ '/';
1301
+ const origin = this.targetOrigin ?? this.getSafeOrigin(this.iframeSrc);
1302
+ this.iframeWin.postMessage({ type: 'NAVIGATE', path }, origin);
1303
+ this.hasInitialSync = true;
1304
+ }
1305
+ // ────── Safe URL helpers ──────
1306
+ isValidUrl(string) {
1307
+ if (!string)
1308
+ return false;
1309
+ try {
1310
+ new URL(string, window.location.origin);
1311
+ return true;
1312
+ }
1313
+ catch {
1314
+ return false;
1315
+ }
1316
+ }
1317
+ getSafeOrigin(src) {
1318
+ if (!src)
1319
+ return window.location.origin;
1320
+ try {
1321
+ // Full URL
1322
+ if (src.startsWith('http')) {
1323
+ return new URL(src).origin;
1324
+ }
1325
+ // Relative path
1326
+ if (src.startsWith('/')) {
1327
+ return window.location.origin;
1328
+ }
1329
+ // Protocol-relative
1330
+ if (src.startsWith('//')) {
1331
+ return new URL(src, window.location.origin).origin;
1332
+ }
1333
+ // Just return current origin for anything else
1334
+ return window.location.origin;
1335
+ }
1336
+ catch {
1337
+ return window.location.origin;
1338
+ }
1339
+ }
1340
+ // ... rest of helpers (isValidUrl, getSafeOrigin) same as before
1341
+ ngOnDestroy() {
1342
+ this.destroy$.next();
1343
+ this.destroy$.complete();
1344
+ window.removeEventListener('message', this.handleIframeMessage);
1345
+ }
1346
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: TaonIframeSyncComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1347
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.15", type: TaonIframeSyncComponent, isStandalone: true, selector: "taon-iframe-sync", inputs: { iframeSrc: "iframeSrc", queryParamKey: "queryParamKey", initialPath: "initialPath", targetOrigin: "targetOrigin" }, viewQueries: [{ propertyName: "iframeRef", first: true, predicate: ["iframe"], descendants: true }], ngImport: i0, template: `
1348
+ <!-- Hidden by default, shown only when ready -->
1349
+ <iframe
1350
+ #iframe
1351
+ [src]="safeSrc"
1352
+ [style.display]="isReady ? 'block' : 'none'"
1353
+ [style.visibility]="isReady ? 'visible' : 'hidden'"
1354
+ [style.opacity]="isReady ? '1' : '0'"
1355
+ frameborder="0"
1356
+ style="width:100%; height:100%; border:none; transition: opacity 0.2s ease;"
1357
+ (load)="onIframeLoad()"
1358
+ allow="clipboard-write"></iframe>
1359
+
1360
+ <!-- Optional: nice loading placeholder -->
1361
+ <div
1362
+ *ngIf="!isReady"
1363
+ class="iframe-loading-placeholder">
1364
+ <div class="spinner"></div>
1365
+ <p>Loading documentation...</p>
1366
+ </div>
1367
+ `, isInline: true, styles: [":host{display:block;width:100%;height:100%;position:relative}.iframe-loading-placeholder{position:absolute;inset:0;background:var(--md-primary-fg-color--light);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:16px;color:var(--text-color, #666);font-family:system-ui,sans-serif}.spinner{width:40px;height:40px;border:4px solid #f3f3f3;border-top:4px solid #3498db;border-radius:50%;animation:spin 1s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}\n"], dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1368
+ }
1369
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: TaonIframeSyncComponent, decorators: [{
1370
+ type: Component,
1371
+ args: [{ selector: 'taon-iframe-sync', template: `
1372
+ <!-- Hidden by default, shown only when ready -->
1373
+ <iframe
1374
+ #iframe
1375
+ [src]="safeSrc"
1376
+ [style.display]="isReady ? 'block' : 'none'"
1377
+ [style.visibility]="isReady ? 'visible' : 'hidden'"
1378
+ [style.opacity]="isReady ? '1' : '0'"
1379
+ frameborder="0"
1380
+ style="width:100%; height:100%; border:none; transition: opacity 0.2s ease;"
1381
+ (load)="onIframeLoad()"
1382
+ allow="clipboard-write"></iframe>
1383
+
1384
+ <!-- Optional: nice loading placeholder -->
1385
+ <div
1386
+ *ngIf="!isReady"
1387
+ class="iframe-loading-placeholder">
1388
+ <div class="spinner"></div>
1389
+ <p>Loading documentation...</p>
1390
+ </div>
1391
+ `, standalone: true, imports: [NgIf], changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block;width:100%;height:100%;position:relative}.iframe-loading-placeholder{position:absolute;inset:0;background:var(--md-primary-fg-color--light);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:16px;color:var(--text-color, #666);font-family:system-ui,sans-serif}.spinner{width:40px;height:40px;border:4px solid #f3f3f3;border-top:4px solid #3498db;border-radius:50%;animation:spin 1s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}\n"] }]
1392
+ }], propDecorators: { iframeRef: [{
1393
+ type: ViewChild,
1394
+ args: ['iframe']
1395
+ }], iframeSrc: [{
1396
+ type: Input,
1397
+ args: [{ required: true }]
1398
+ }], queryParamKey: [{
1399
+ type: Input
1400
+ }], initialPath: [{
1401
+ type: Input
1402
+ }], targetOrigin: [{
1403
+ type: Input
1404
+ }] } });
1405
+
1228
1406
  //#region @browser
1229
1407
  //#endregion
1230
1408
 
@@ -1256,5 +1434,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImpo
1256
1434
  * Generated bundle index. Do not edit.
1257
1435
  */
1258
1436
 
1259
- export { SafePipe, TaonAdminModeConfigurationComponent, TaonBootstrapNavbarComponent, TaonFullMaterialModule, TaonGithubForkMeCornerComponent, TaonGithubForkMeCornerModule, TaonGithubForkMeRibbonComponent, TaonGithubForkMeRibbonModule, TaonInjectHTMLDirective, TaonLongPress, TaonNotificationOptions, TaonNotificationsComponent, TaonNotificationsModule, TaonNotificationsService, TaonProgressBarComponent, TaonProgressBarModule, TaonSessionPasscodeComponent, TaonTableComponent, TaonTableModule };
1437
+ export { SafePipe, TaonAdminModeConfigurationComponent, TaonBootstrapNavbarComponent, TaonFullMaterialModule, TaonGithubForkMeCornerComponent, TaonGithubForkMeCornerModule, TaonGithubForkMeRibbonComponent, TaonGithubForkMeRibbonModule, TaonIframeSyncComponent, TaonInjectHTMLDirective, TaonLongPress, TaonNotificationOptions, TaonNotificationsComponent, TaonNotificationsModule, TaonNotificationsService, TaonProgressBarComponent, TaonProgressBarModule, TaonSessionPasscodeComponent, TaonTableComponent, TaonTableModule };
1260
1438
  //# sourceMappingURL=taon-ui.mjs.map