@foxeltech/angular-ui 0.0.3 → 0.0.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 CHANGED
@@ -1,3 +1,3 @@
1
- # @fxlt/common-ui
1
+ # @foxeltech/angular-ui
2
2
 
3
- Common UI & Service Library
3
+ Common UI & Service Library
@@ -310,9 +310,9 @@ class FxUtils {
310
310
  return 'Session timeout. Please login again.';
311
311
  }
312
312
  if (this.isStringEmpty(_.get(err, 'error.code'))) {
313
- return _.get(err, 'error.message', 'Unknown Error');
313
+ return _.get(err, 'error.errors', 'Unknown Error');
314
314
  }
315
- return `${_.get(err, 'error.code')}: ${_.get(err, 'error.message', 'Unknown Error')}`;
315
+ return `${_.get(err, 'error.code')}: ${_.get(err, 'error.errors', 'Unknown Error')}`;
316
316
  }
317
317
  static convertColorFromVariable(name, alpha = 1) {
318
318
  const value = getComputedStyle(document.body)
@@ -505,7 +505,7 @@ class BaseTableComponent extends BaseComponent {
505
505
  init() { }
506
506
  ngAfterViewInit() {
507
507
  if (this.paginator && this.paginator.page) {
508
- this.paginator.page.subscribe(event => {
508
+ this.paginator.page.subscribe((event) => {
509
509
  this.onPageChange(event);
510
510
  });
511
511
  }
@@ -513,6 +513,9 @@ class BaseTableComponent extends BaseComponent {
513
513
  }
514
514
  async refresh() {
515
515
  this.page = 0;
516
+ if (this.paginator) {
517
+ this.paginator.pageIndex = 0;
518
+ }
516
519
  await this.fetch();
517
520
  }
518
521
  setDataSource(result) {
@@ -692,7 +695,7 @@ class BaseTableComponent extends BaseComponent {
692
695
  return await this.api.remove({ ...model });
693
696
  }
694
697
  catch (err) {
695
- throw err;
698
+ this.toastr.error(FxUtils.parseError(err));
696
699
  }
697
700
  }
698
701
  tagClass(tag) {
@@ -764,7 +767,7 @@ class BaseDialogComponent extends BaseComponent {
764
767
  }
765
768
  ngAfterViewInit() { }
766
769
  ngOnInit() { }
767
- accept(form, params = null) {
770
+ async accept(form, params = null) {
768
771
  if (form.invalid) {
769
772
  FxUtils.checkInvalidField(form);
770
773
  return;
@@ -773,66 +776,66 @@ class BaseDialogComponent extends BaseComponent {
773
776
  if (!this.validate())
774
777
  return;
775
778
  if (this.method === 'create') {
776
- this.create(params);
779
+ await this.create(params);
777
780
  return;
778
781
  }
779
782
  else {
780
- this.update(params);
783
+ await this.update(params);
781
784
  return;
782
785
  }
783
786
  }
784
787
  this.cancel();
785
788
  }
786
- create(params = null) {
789
+ async create(params = null) {
787
790
  if (this.loading) {
788
791
  return;
789
792
  }
790
793
  this.loading = true;
791
- this.api
792
- .create({ ...this.model, ...params })
793
- .then(() => {
794
+ try {
795
+ await this.api.create({ ...this.model, ...params });
794
796
  this.toastr.success(this.message);
795
797
  this.ref.close(true);
796
- }, (error) => {
798
+ }
799
+ catch (error) {
797
800
  this.toastr.error(FxUtils.parseError(error));
798
- })
799
- .then(() => {
801
+ }
802
+ finally {
800
803
  this.loading = false;
801
- });
804
+ }
802
805
  }
803
- update(params = null) {
806
+ async update(params = null) {
804
807
  if (this.loading) {
805
808
  return;
806
809
  }
807
810
  this.loading = true;
808
- this.api
809
- .update({ ...this.model, ...params })
810
- .then(() => {
811
+ try {
812
+ await this.api.update({ ...this.model, ...params });
811
813
  this.toastr.success(this.message);
812
814
  this.ref.close(true);
813
- }, (error) => {
815
+ }
816
+ catch (error) {
814
817
  this.toastr.error(FxUtils.parseError(error));
815
- })
816
- .then(() => {
818
+ }
819
+ finally {
817
820
  this.loading = false;
818
- });
821
+ }
819
822
  }
820
- updateInfo(params = null) {
823
+ async updateInfo(params = null) {
821
824
  if (this.loading) {
822
825
  return;
823
826
  }
824
827
  this.loading = true;
825
- this.api
826
- .updateInfo({ ...this.model, ...params })
827
- .then(() => {
828
+ try {
829
+ await this.api.updateInfo({ ...this.model, ...params });
828
830
  this.toastr.success(this.message);
829
831
  this.ref.close(true);
830
- }, (error) => {
831
- this.toastr.error(error);
832
- })
833
- .then(() => {
832
+ }
833
+ catch (error) {
834
+ this.toastr.error(FxUtils.parseError(error));
835
+ }
836
+ finally {
834
837
  this.loading = false;
835
- });
838
+ }
836
839
  }
837
840
  cancel() {
838
841
  this.ref.close(false);
@@ -890,6 +893,122 @@ class BaseResolver {
890
893
  }
891
894
  }
892
895
 
896
+ class FxValidators {
897
+ /**
898
+ * Name fields: firstName, lastName, groupName, projectName, displayName
899
+ * Allows: letters (Unicode), spaces, hyphens, apostrophes, periods
900
+ */
901
+ static validateName(value) {
902
+ if (!value || value.trim() === '')
903
+ return null;
904
+ const regex = /^[\p{L}\s'\-.]{1,100}$/u;
905
+ return regex.test(value) ? null : { invalidName: 'Only letters, spaces, hyphens, apostrophes, and periods are allowed (max 100 characters)' };
906
+ }
907
+ /**
908
+ * Description fields
909
+ * Allows: letters, digits, spaces, basic punctuation
910
+ */
911
+ static validateDescription(value) {
912
+ if (!value || value.trim() === '')
913
+ return null;
914
+ const regex = /^[\p{L}\d\s.,;:!?'/()"&\-\n\r]{1,500}$/u;
915
+ return regex.test(value) ? null : { invalidDescription: 'Contains disallowed characters (max 500 characters)' };
916
+ }
917
+ /**
918
+ * Email fields
919
+ */
920
+ static validateEmail(value) {
921
+ if (!value || value.trim() === '')
922
+ return null;
923
+ const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
924
+ return regex.test(value) ? null : { invalidEmail: 'Please enter a valid email address' };
925
+ }
926
+ /**
927
+ * Phone fields
928
+ * Allows: digits, optional leading +, spaces, hyphens, parentheses (7-15 digits)
929
+ */
930
+ static validatePhone(value) {
931
+ if (!value || value.trim() === '')
932
+ return null;
933
+ const regex = /^\+?[\d\s\-()]{7,20}$/;
934
+ const digitCount = value.replace(/\D/g, '').length;
935
+ if (!regex.test(value) || digitCount < 7 || digitCount > 15) {
936
+ return { invalidPhone: 'Please enter a valid phone number' };
937
+ }
938
+ return null;
939
+ }
940
+ /**
941
+ * Code/identifier fields: server code, template code, templateId
942
+ * Allows: alphanumeric, hyphens, underscores
943
+ */
944
+ static validateCode(value) {
945
+ if (!value || value.trim() === '')
946
+ return null;
947
+ const regex = /^[a-zA-Z0-9_\-]{1,50}$/;
948
+ return regex.test(value) ? null : { invalidCode: 'Only letters, numbers, hyphens, and underscores are allowed (max 50 characters)' };
949
+ }
950
+ /**
951
+ * Domain fields
952
+ * Standard domain pattern with optional port
953
+ */
954
+ static validateDomain(value) {
955
+ if (!value || value.trim() === '')
956
+ return null;
957
+ const regex = /^([a-zA-Z0-9]([a-zA-Z0-9\-]*[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}(:\d{1,5})?$/;
958
+ return regex.test(value) ? null : { invalidDomain: 'Please enter a valid domain (e.g., mail.example.com)' };
959
+ }
960
+ /**
961
+ * Subject fields (email subject)
962
+ * Allows: letters, digits, spaces, common punctuation, template placeholders {{}}
963
+ */
964
+ static validateSubject(value) {
965
+ if (!value || value.trim() === '')
966
+ return null;
967
+ const regex = /^[\p{L}\d\s.,;:!?'/()"&\-{}]{1,200}$/u;
968
+ return regex.test(value) ? null : { invalidSubject: 'Contains disallowed characters (max 200 characters)' };
969
+ }
970
+ /**
971
+ * Tag fields
972
+ * Allows: alphanumeric, hyphens, underscores, dots, spaces
973
+ */
974
+ static validateTag(value) {
975
+ if (!value || value.trim() === '')
976
+ return null;
977
+ const regex = /^[a-zA-Z0-9_\-.\s]{1,50}$/;
978
+ return regex.test(value) ? null : { invalidTag: 'Only letters, numbers, hyphens, underscores, dots, and spaces are allowed' };
979
+ }
980
+ /**
981
+ * URL fields: proxy, masterUrl
982
+ * Standard URL pattern
983
+ */
984
+ static validateUrl(value) {
985
+ if (!value || value.trim() === '')
986
+ return null;
987
+ const regex = /^https?:\/\/[a-zA-Z0-9\-._~:/?#[\]@!$&'()*+,;=%]{1,2000}$/;
988
+ return regex.test(value) ? null : { invalidUrl: 'Please enter a valid URL (http:// or https://)' };
989
+ }
990
+ /**
991
+ * Numeric string fields: timeout, memoryLimit, cpuCores
992
+ * Allows: digits, optional decimal point
993
+ */
994
+ static validateNumeric(value) {
995
+ if (!value || value.toString().trim() === '')
996
+ return null;
997
+ const regex = /^\d+(\.\d+)?$/;
998
+ return regex.test(value.toString()) ? null : { invalidNumeric: 'Please enter a valid number' };
999
+ }
1000
+ /**
1001
+ * Version fields (semver-like)
1002
+ * Allows: digits, dots, hyphens, plus, letters
1003
+ */
1004
+ static validateVersion(value) {
1005
+ if (!value || value.trim() === '')
1006
+ return null;
1007
+ const regex = /^[a-zA-Z0-9.\-+]{1,50}$/;
1008
+ return regex.test(value) ? null : { invalidVersion: 'Please enter a valid version (e.g., 1.0.0)' };
1009
+ }
1010
+ }
1011
+
893
1012
  function HttpLoaderFactory(http) {
894
1013
  return new TranslateHttpLoader(http, '/assets/i18n/', '.json');
895
1014
  }
@@ -1510,6 +1629,7 @@ class ChartComponent {
1510
1629
  intersectionObserver;
1511
1630
  canInit = false;
1512
1631
  isMobile = false;
1632
+ containerWidth = 0;
1513
1633
  constructor(ref, cdr) {
1514
1634
  this.ref = ref;
1515
1635
  this.cdr = cdr;
@@ -1563,6 +1683,7 @@ class ChartComponent {
1563
1683
  updateResponsiveState() {
1564
1684
  const { width } = this.ref.nativeElement.getBoundingClientRect();
1565
1685
  if (width > 0) {
1686
+ this.containerWidth = width;
1566
1687
  this.isMobile = width < this.mobileWidth;
1567
1688
  }
1568
1689
  }
@@ -1574,7 +1695,7 @@ class ChartComponent {
1574
1695
  requestAnimationFrame(() => this.forceMediaRecalc(retry + 1));
1575
1696
  return;
1576
1697
  }
1577
- this.chartInstance.setOption(this.chartOptions, true);
1698
+ this.rebuildChart();
1578
1699
  this.chartInstance.resize();
1579
1700
  }
1580
1701
  rebuildChart() {
@@ -1646,20 +1767,20 @@ class ChartComponent {
1646
1767
  }),
1647
1768
  pie: (data, colors) => {
1648
1769
  const total = data.reduce((sum, d) => sum + d.value, 0);
1649
- const isMobile = this.isMobile;
1770
+ const layout = this.calcPieLayout(data);
1650
1771
  return {
1651
1772
  color: colors,
1652
1773
  tooltip: { trigger: 'item' },
1653
1774
  legend: {
1654
- orient: isMobile ? 'horizontal' : 'vertical',
1775
+ type: 'scroll',
1776
+ orient: layout.legendOrient,
1655
1777
  icon: 'circle',
1656
1778
  itemGap: 12,
1657
- width: 160,
1658
- // 🔑 layout switch
1659
- right: isMobile ? undefined : this.pieLegendAlign,
1660
- top: isMobile ? undefined : this.pieLegendPosition,
1661
- left: isMobile ? 'center' : undefined,
1662
- bottom: isMobile ? 0 : undefined,
1779
+ right: layout.legendRight,
1780
+ top: layout.legendTop,
1781
+ left: layout.legendLeft,
1782
+ bottom: layout.legendBottom,
1783
+ width: layout.legendWidth,
1663
1784
  formatter: (name) => {
1664
1785
  const item = data.find((d) => d.name === name);
1665
1786
  return item ? `${name}: ${item.value}` : name;
@@ -1676,7 +1797,7 @@ class ChartComponent {
1676
1797
  {
1677
1798
  type: 'pie',
1678
1799
  radius: ['40%', '70%'],
1679
- center: isMobile ? ['50%', '40%'] : ['35%', '50%'],
1800
+ center: layout.pieCenter,
1680
1801
  data,
1681
1802
  label: {
1682
1803
  show: this.showPieLabel,
@@ -1697,8 +1818,8 @@ class ChartComponent {
1697
1818
  ],
1698
1819
  graphic: {
1699
1820
  type: 'group',
1700
- left: isMobile ? '50%' : '35%',
1701
- top: isMobile ? '40%' : '50%',
1821
+ left: layout.graphicLeft,
1822
+ top: layout.graphicTop,
1702
1823
  bounding: 'raw',
1703
1824
  children: [
1704
1825
  {
@@ -1740,6 +1861,46 @@ class ChartComponent {
1740
1861
  ],
1741
1862
  }),
1742
1863
  };
1864
+ /* ================= PIE LAYOUT ================= */
1865
+ calcPieLayout(data) {
1866
+ const cw = this.containerWidth || 400;
1867
+ if (this.isMobile) {
1868
+ return {
1869
+ legendOrient: 'horizontal',
1870
+ legendLeft: 'center',
1871
+ legendRight: undefined,
1872
+ legendTop: undefined,
1873
+ legendBottom: 0,
1874
+ legendWidth: undefined,
1875
+ pieCenter: ['50%', '40%'],
1876
+ graphicLeft: '50%',
1877
+ graphicTop: '40%',
1878
+ };
1879
+ }
1880
+ // Estimate legend pixel width from longest formatted label
1881
+ const CHAR_WIDTH = 7.5; // approx px per char at fontSize 13
1882
+ const ICON_GAP = 30; // legend icon + padding
1883
+ const longestLabel = data.reduce((max, d) => {
1884
+ return Math.max(max, `${d.name}: ${d.value}`.length);
1885
+ }, 0);
1886
+ const rawLegendPx = longestLabel * CHAR_WIDTH + ICON_GAP;
1887
+ // Clamp: min 100px, max 45% of container
1888
+ const legendPx = Math.max(100, Math.min(rawLegendPx, cw * 0.45));
1889
+ const legendPct = (legendPx / cw) * 100;
1890
+ // Pie center: middle of the remaining space after legend
1891
+ const pieCenterX = Math.round((100 - legendPct) / 2);
1892
+ return {
1893
+ legendOrient: 'vertical',
1894
+ legendLeft: undefined,
1895
+ legendRight: '2%',
1896
+ legendTop: 'middle',
1897
+ legendBottom: undefined,
1898
+ legendWidth: Math.round(legendPx),
1899
+ pieCenter: [`${pieCenterX}%`, '50%'],
1900
+ graphicLeft: `${pieCenterX}%`,
1901
+ graphicTop: '50%',
1902
+ };
1903
+ }
1743
1904
  /* ================= BUILD ================= */
1744
1905
  detectType() {
1745
1906
  if (this.type !== 'auto')
@@ -2294,11 +2455,11 @@ class LoadingPanel {
2294
2455
  show = false;
2295
2456
  message = "Loading";
2296
2457
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: LoadingPanel, deps: [], target: i0.ɵɵFactoryTarget.Component });
2297
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.4", type: LoadingPanel, isStandalone: false, selector: "fx-ui-loading-panel", inputs: { show: "show", message: "message" }, ngImport: i0, template: "<!-- Full-screen glass overlay -->\n<div\n *ngIf=\"show\"\n class=\"fixed inset-0 z-50 flex items-center justify-center\"\n aria-hidden=\"false\"\n role=\"alert\"\n aria-busy=\"true\"\n>\n <div class=\"absolute inset-0 bg-bg-primary/30 backdrop-blur-xl\" aria-hidden=\"true\"></div>\n\n <div\n class=\"relative z-10 flex flex-col items-center gap-4 p-6 rounded-2xl shadow-xl bg-bg-primary/70 border border-border-strong backdrop-bg-primary/70\"\n style=\"min-width: 220px; max-width: 90%\"\n >\n <svg fill=\"rgb(var(--primary))\" width=\"50\" height=\"50\" viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"4\" cy=\"12\" r=\"0\">\n <animate begin=\"0;spinner_z0Or.end\" attributeName=\"r\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"0;3\" fill=\"freeze\"/>\n <animate begin=\"spinner_OLMs.end\" attributeName=\"cx\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"4;12\" fill=\"freeze\"/>\n <animate begin=\"spinner_UHR2.end\" attributeName=\"cx\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"12;20\" fill=\"freeze\"/>\n <animate id=\"spinner_lo66\" begin=\"spinner_Aguh.end\" attributeName=\"r\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"3;0\" fill=\"freeze\"/>\n <animate id=\"spinner_z0Or\" begin=\"spinner_lo66.end\" attributeName=\"cx\" dur=\"0.001s\" values=\"20;4\" fill=\"freeze\"/>\n </circle>\n <circle cx=\"4\" cy=\"12\" r=\"3\">\n <animate begin=\"0;spinner_z0Or.end\" attributeName=\"cx\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"4;12\" fill=\"freeze\"/>\n <animate begin=\"spinner_OLMs.end\" attributeName=\"cx\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"12;20\" fill=\"freeze\"/>\n <animate id=\"spinner_JsnR\" begin=\"spinner_UHR2.end\" attributeName=\"r\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"3;0\" fill=\"freeze\"/>\n <animate id=\"spinner_Aguh\" begin=\"spinner_JsnR.end\" attributeName=\"cx\" dur=\"0.001s\" values=\"20;4\" fill=\"freeze\"/>\n <animate begin=\"spinner_Aguh.end\" attributeName=\"r\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"0;3\" fill=\"freeze\"/>\n </circle>\n <circle cx=\"12\" cy=\"12\" r=\"3\">\n <animate begin=\"0;spinner_z0Or.end\" attributeName=\"cx\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"12;20\" fill=\"freeze\"/>\n <animate id=\"spinner_hSjk\" begin=\"spinner_OLMs.end\" attributeName=\"r\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"3;0\" fill=\"freeze\"/>\n <animate id=\"spinner_UHR2\" begin=\"spinner_hSjk.end\" attributeName=\"cx\" dur=\"0.001s\" values=\"20;4\" fill=\"freeze\"/>\n <animate begin=\"spinner_UHR2.end\" attributeName=\"r\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"0;3\" fill=\"freeze\"/>\n <animate begin=\"spinner_Aguh.end\" attributeName=\"cx\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"4;12\" fill=\"freeze\"/>\n </circle>\n <circle cx=\"20\" cy=\"12\" r=\"3\">\n <animate id=\"spinner_4v5M\" begin=\"0;spinner_z0Or.end\" attributeName=\"r\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"3;0\" fill=\"freeze\"/>\n <animate id=\"spinner_OLMs\" begin=\"spinner_4v5M.end\" attributeName=\"cx\" dur=\"0.001s\" values=\"20;4\" fill=\"freeze\"/>\n <animate begin=\"spinner_OLMs.end\" attributeName=\"r\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"0;3\" fill=\"freeze\"/>\n <animate begin=\"spinner_UHR2.end\" attributeName=\"cx\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"4;12\" fill=\"freeze\"/>\n <animate begin=\"spinner_Aguh.end\" attributeName=\"cx\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"12;20\" fill=\"freeze\"/>\n </circle>\n </svg>\n \n\n <div *ngIf=\"message\" class=\"text-sm text-text-primary text-center\">\n {{ message }}\n </div>\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
2458
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.4", type: LoadingPanel, isStandalone: false, selector: "fx-ui-loading-panel", inputs: { show: "show", message: "message" }, ngImport: i0, template: "<!-- Full-screen glass overlay -->\n<div\n *ngIf=\"show\"\n class=\"fixed inset-0 z-50 flex items-center justify-center\"\n aria-hidden=\"false\"\n role=\"alert\"\n aria-busy=\"true\"\n>\n <div class=\"absolute inset-0 bg-bg-primary/30 backdrop-blur-xl\" aria-hidden=\"true\"></div>\n\n <div\n class=\"relative z-10 flex flex-col items-center gap-4 p-6 rounded-2xl shadow-xl bg-bg-primary/70 border border-border-strong backdrop-bg-primary/70\"\n style=\"min-width: 220px; max-width: 90%\"\n >\n <svg fill=\"url(#spinner-gradient)\" width=\"50\" height=\"50\" viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\">\n <defs>\n <linearGradient id=\"spinner-gradient\" x1=\"0%\" y1=\"0%\" x2=\"100%\" y2=\"0%\">\n <stop offset=\"0%\" style=\"stop-color: rgb(var(--gradient-primary-start)); stop-opacity: 1\" />\n <stop offset=\"100%\" style=\"stop-color: rgb(var(--gradient-primary-end)); stop-opacity: 1\" />\n </linearGradient>\n </defs>\n <circle cx=\"4\" cy=\"12\" r=\"0\">\n <animate begin=\"0;spinner_z0Or.end\" attributeName=\"r\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"0;3\" fill=\"freeze\"/>\n <animate begin=\"spinner_OLMs.end\" attributeName=\"cx\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"4;12\" fill=\"freeze\"/>\n <animate begin=\"spinner_UHR2.end\" attributeName=\"cx\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"12;20\" fill=\"freeze\"/>\n <animate id=\"spinner_lo66\" begin=\"spinner_Aguh.end\" attributeName=\"r\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"3;0\" fill=\"freeze\"/>\n <animate id=\"spinner_z0Or\" begin=\"spinner_lo66.end\" attributeName=\"cx\" dur=\"0.001s\" values=\"20;4\" fill=\"freeze\"/>\n </circle>\n <circle cx=\"4\" cy=\"12\" r=\"3\">\n <animate begin=\"0;spinner_z0Or.end\" attributeName=\"cx\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"4;12\" fill=\"freeze\"/>\n <animate begin=\"spinner_OLMs.end\" attributeName=\"cx\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"12;20\" fill=\"freeze\"/>\n <animate id=\"spinner_JsnR\" begin=\"spinner_UHR2.end\" attributeName=\"r\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"3;0\" fill=\"freeze\"/>\n <animate id=\"spinner_Aguh\" begin=\"spinner_JsnR.end\" attributeName=\"cx\" dur=\"0.001s\" values=\"20;4\" fill=\"freeze\"/>\n <animate begin=\"spinner_Aguh.end\" attributeName=\"r\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"0;3\" fill=\"freeze\"/>\n </circle>\n <circle cx=\"12\" cy=\"12\" r=\"3\">\n <animate begin=\"0;spinner_z0Or.end\" attributeName=\"cx\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"12;20\" fill=\"freeze\"/>\n <animate id=\"spinner_hSjk\" begin=\"spinner_OLMs.end\" attributeName=\"r\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"3;0\" fill=\"freeze\"/>\n <animate id=\"spinner_UHR2\" begin=\"spinner_hSjk.end\" attributeName=\"cx\" dur=\"0.001s\" values=\"20;4\" fill=\"freeze\"/>\n <animate begin=\"spinner_UHR2.end\" attributeName=\"r\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"0;3\" fill=\"freeze\"/>\n <animate begin=\"spinner_Aguh.end\" attributeName=\"cx\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"4;12\" fill=\"freeze\"/>\n </circle>\n <circle cx=\"20\" cy=\"12\" r=\"3\">\n <animate id=\"spinner_4v5M\" begin=\"0;spinner_z0Or.end\" attributeName=\"r\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"3;0\" fill=\"freeze\"/>\n <animate id=\"spinner_OLMs\" begin=\"spinner_4v5M.end\" attributeName=\"cx\" dur=\"0.001s\" values=\"20;4\" fill=\"freeze\"/>\n <animate begin=\"spinner_OLMs.end\" attributeName=\"r\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"0;3\" fill=\"freeze\"/>\n <animate begin=\"spinner_UHR2.end\" attributeName=\"cx\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"4;12\" fill=\"freeze\"/>\n <animate begin=\"spinner_Aguh.end\" attributeName=\"cx\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"12;20\" fill=\"freeze\"/>\n </circle>\n </svg>\n \n\n <div *ngIf=\"message\" class=\"text-sm text-text-primary text-center\">\n {{ message }}\n </div>\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
2298
2459
  }
2299
2460
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: LoadingPanel, decorators: [{
2300
2461
  type: Component,
2301
- args: [{ selector: 'fx-ui-loading-panel', standalone: false, template: "<!-- Full-screen glass overlay -->\n<div\n *ngIf=\"show\"\n class=\"fixed inset-0 z-50 flex items-center justify-center\"\n aria-hidden=\"false\"\n role=\"alert\"\n aria-busy=\"true\"\n>\n <div class=\"absolute inset-0 bg-bg-primary/30 backdrop-blur-xl\" aria-hidden=\"true\"></div>\n\n <div\n class=\"relative z-10 flex flex-col items-center gap-4 p-6 rounded-2xl shadow-xl bg-bg-primary/70 border border-border-strong backdrop-bg-primary/70\"\n style=\"min-width: 220px; max-width: 90%\"\n >\n <svg fill=\"rgb(var(--primary))\" width=\"50\" height=\"50\" viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"4\" cy=\"12\" r=\"0\">\n <animate begin=\"0;spinner_z0Or.end\" attributeName=\"r\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"0;3\" fill=\"freeze\"/>\n <animate begin=\"spinner_OLMs.end\" attributeName=\"cx\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"4;12\" fill=\"freeze\"/>\n <animate begin=\"spinner_UHR2.end\" attributeName=\"cx\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"12;20\" fill=\"freeze\"/>\n <animate id=\"spinner_lo66\" begin=\"spinner_Aguh.end\" attributeName=\"r\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"3;0\" fill=\"freeze\"/>\n <animate id=\"spinner_z0Or\" begin=\"spinner_lo66.end\" attributeName=\"cx\" dur=\"0.001s\" values=\"20;4\" fill=\"freeze\"/>\n </circle>\n <circle cx=\"4\" cy=\"12\" r=\"3\">\n <animate begin=\"0;spinner_z0Or.end\" attributeName=\"cx\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"4;12\" fill=\"freeze\"/>\n <animate begin=\"spinner_OLMs.end\" attributeName=\"cx\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"12;20\" fill=\"freeze\"/>\n <animate id=\"spinner_JsnR\" begin=\"spinner_UHR2.end\" attributeName=\"r\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"3;0\" fill=\"freeze\"/>\n <animate id=\"spinner_Aguh\" begin=\"spinner_JsnR.end\" attributeName=\"cx\" dur=\"0.001s\" values=\"20;4\" fill=\"freeze\"/>\n <animate begin=\"spinner_Aguh.end\" attributeName=\"r\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"0;3\" fill=\"freeze\"/>\n </circle>\n <circle cx=\"12\" cy=\"12\" r=\"3\">\n <animate begin=\"0;spinner_z0Or.end\" attributeName=\"cx\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"12;20\" fill=\"freeze\"/>\n <animate id=\"spinner_hSjk\" begin=\"spinner_OLMs.end\" attributeName=\"r\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"3;0\" fill=\"freeze\"/>\n <animate id=\"spinner_UHR2\" begin=\"spinner_hSjk.end\" attributeName=\"cx\" dur=\"0.001s\" values=\"20;4\" fill=\"freeze\"/>\n <animate begin=\"spinner_UHR2.end\" attributeName=\"r\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"0;3\" fill=\"freeze\"/>\n <animate begin=\"spinner_Aguh.end\" attributeName=\"cx\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"4;12\" fill=\"freeze\"/>\n </circle>\n <circle cx=\"20\" cy=\"12\" r=\"3\">\n <animate id=\"spinner_4v5M\" begin=\"0;spinner_z0Or.end\" attributeName=\"r\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"3;0\" fill=\"freeze\"/>\n <animate id=\"spinner_OLMs\" begin=\"spinner_4v5M.end\" attributeName=\"cx\" dur=\"0.001s\" values=\"20;4\" fill=\"freeze\"/>\n <animate begin=\"spinner_OLMs.end\" attributeName=\"r\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"0;3\" fill=\"freeze\"/>\n <animate begin=\"spinner_UHR2.end\" attributeName=\"cx\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"4;12\" fill=\"freeze\"/>\n <animate begin=\"spinner_Aguh.end\" attributeName=\"cx\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"12;20\" fill=\"freeze\"/>\n </circle>\n </svg>\n \n\n <div *ngIf=\"message\" class=\"text-sm text-text-primary text-center\">\n {{ message }}\n </div>\n </div>\n</div>\n" }]
2462
+ args: [{ selector: 'fx-ui-loading-panel', standalone: false, template: "<!-- Full-screen glass overlay -->\n<div\n *ngIf=\"show\"\n class=\"fixed inset-0 z-50 flex items-center justify-center\"\n aria-hidden=\"false\"\n role=\"alert\"\n aria-busy=\"true\"\n>\n <div class=\"absolute inset-0 bg-bg-primary/30 backdrop-blur-xl\" aria-hidden=\"true\"></div>\n\n <div\n class=\"relative z-10 flex flex-col items-center gap-4 p-6 rounded-2xl shadow-xl bg-bg-primary/70 border border-border-strong backdrop-bg-primary/70\"\n style=\"min-width: 220px; max-width: 90%\"\n >\n <svg fill=\"url(#spinner-gradient)\" width=\"50\" height=\"50\" viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\">\n <defs>\n <linearGradient id=\"spinner-gradient\" x1=\"0%\" y1=\"0%\" x2=\"100%\" y2=\"0%\">\n <stop offset=\"0%\" style=\"stop-color: rgb(var(--gradient-primary-start)); stop-opacity: 1\" />\n <stop offset=\"100%\" style=\"stop-color: rgb(var(--gradient-primary-end)); stop-opacity: 1\" />\n </linearGradient>\n </defs>\n <circle cx=\"4\" cy=\"12\" r=\"0\">\n <animate begin=\"0;spinner_z0Or.end\" attributeName=\"r\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"0;3\" fill=\"freeze\"/>\n <animate begin=\"spinner_OLMs.end\" attributeName=\"cx\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"4;12\" fill=\"freeze\"/>\n <animate begin=\"spinner_UHR2.end\" attributeName=\"cx\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"12;20\" fill=\"freeze\"/>\n <animate id=\"spinner_lo66\" begin=\"spinner_Aguh.end\" attributeName=\"r\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"3;0\" fill=\"freeze\"/>\n <animate id=\"spinner_z0Or\" begin=\"spinner_lo66.end\" attributeName=\"cx\" dur=\"0.001s\" values=\"20;4\" fill=\"freeze\"/>\n </circle>\n <circle cx=\"4\" cy=\"12\" r=\"3\">\n <animate begin=\"0;spinner_z0Or.end\" attributeName=\"cx\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"4;12\" fill=\"freeze\"/>\n <animate begin=\"spinner_OLMs.end\" attributeName=\"cx\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"12;20\" fill=\"freeze\"/>\n <animate id=\"spinner_JsnR\" begin=\"spinner_UHR2.end\" attributeName=\"r\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"3;0\" fill=\"freeze\"/>\n <animate id=\"spinner_Aguh\" begin=\"spinner_JsnR.end\" attributeName=\"cx\" dur=\"0.001s\" values=\"20;4\" fill=\"freeze\"/>\n <animate begin=\"spinner_Aguh.end\" attributeName=\"r\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"0;3\" fill=\"freeze\"/>\n </circle>\n <circle cx=\"12\" cy=\"12\" r=\"3\">\n <animate begin=\"0;spinner_z0Or.end\" attributeName=\"cx\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"12;20\" fill=\"freeze\"/>\n <animate id=\"spinner_hSjk\" begin=\"spinner_OLMs.end\" attributeName=\"r\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"3;0\" fill=\"freeze\"/>\n <animate id=\"spinner_UHR2\" begin=\"spinner_hSjk.end\" attributeName=\"cx\" dur=\"0.001s\" values=\"20;4\" fill=\"freeze\"/>\n <animate begin=\"spinner_UHR2.end\" attributeName=\"r\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"0;3\" fill=\"freeze\"/>\n <animate begin=\"spinner_Aguh.end\" attributeName=\"cx\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"4;12\" fill=\"freeze\"/>\n </circle>\n <circle cx=\"20\" cy=\"12\" r=\"3\">\n <animate id=\"spinner_4v5M\" begin=\"0;spinner_z0Or.end\" attributeName=\"r\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"3;0\" fill=\"freeze\"/>\n <animate id=\"spinner_OLMs\" begin=\"spinner_4v5M.end\" attributeName=\"cx\" dur=\"0.001s\" values=\"20;4\" fill=\"freeze\"/>\n <animate begin=\"spinner_OLMs.end\" attributeName=\"r\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"0;3\" fill=\"freeze\"/>\n <animate begin=\"spinner_UHR2.end\" attributeName=\"cx\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"4;12\" fill=\"freeze\"/>\n <animate begin=\"spinner_Aguh.end\" attributeName=\"cx\" calcMode=\"spline\" dur=\"0.5s\" keySplines=\".36,.6,.31,1\" values=\"12;20\" fill=\"freeze\"/>\n </circle>\n </svg>\n \n\n <div *ngIf=\"message\" class=\"text-sm text-text-primary text-center\">\n {{ message }}\n </div>\n </div>\n</div>\n" }]
2302
2463
  }], propDecorators: { show: [{
2303
2464
  type: Input
2304
2465
  }], message: [{
@@ -3449,5 +3610,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImpor
3449
3610
  * Generated bundle index. Do not edit.
3450
3611
  */
3451
3612
 
3452
- export { AuthInterceptor, AuthStateService, BaseComponent, BaseDialogComponent, BaseResolver, BaseTableComponent, BreadcrumbService, ButtonComponent, ChartComponent, CheckboxComponent, CircleProgressBar, ConfirmationDialogComponent, DatetimePicker, DndUploadComponent, DrawerComponent, FlowConnection, FxLoadingService, FxStorageService, FxToastrService, FxUtils, HasPermissionDirective, HeroIconComponent, HttpLoaderFactory, HttpWrapper, InputComponent, KanbanBoardComponent, LoadingPanel, MY_MOMENT_FORMATS, NotificationService, PermissionGuard, PermissionService, QuillStyleLoaderService, RadioButtonComponent, RadioButtonToggleComponent, RichTextAreaComponent, SearchBarComponent, SelectComponent, SkeletonTableLoadingComponent, SliderComponent, SwitchComponent, TabComponent, TabGroupComponent, TableCell, TagComponent, ThemeService, ToastComponent, ToastContainerComponent, TranslationModule, TranslationService, TreeDiagram, TrimOnBlurDirective, UiModule };
3613
+ export { AuthInterceptor, AuthStateService, BaseComponent, BaseDialogComponent, BaseResolver, BaseTableComponent, BreadcrumbService, ButtonComponent, ChartComponent, CheckboxComponent, CircleProgressBar, ConfirmationDialogComponent, DatetimePicker, DndUploadComponent, DrawerComponent, FlowConnection, FxLoadingService, FxStorageService, FxToastrService, FxUtils, FxValidators, HasPermissionDirective, HeroIconComponent, HttpLoaderFactory, HttpWrapper, InputComponent, KanbanBoardComponent, LoadingPanel, MY_MOMENT_FORMATS, NotificationService, PermissionGuard, PermissionService, QuillStyleLoaderService, RadioButtonComponent, RadioButtonToggleComponent, RichTextAreaComponent, SearchBarComponent, SelectComponent, SkeletonTableLoadingComponent, SliderComponent, SwitchComponent, TabComponent, TabGroupComponent, TableCell, TagComponent, ThemeService, ToastComponent, ToastContainerComponent, TranslationModule, TranslationService, TreeDiagram, TrimOnBlurDirective, UiModule };
3453
3614
  //# sourceMappingURL=foxeltech-angular-ui.mjs.map