
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\plugins\cordova-plugin-device\types\index.d.ts

// Type definitions for Apache Cordova Device plugin
// Project: https://github.com/apache/cordova-plugin-device
// Definitions by: Microsoft Open Technologies Inc <http://msopentech.com>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// 
// Copyright (c) Microsoft Open Technologies Inc
// Licensed under the MIT license 

/**
 * This plugin defines a global device object, which describes the device's hardware and software.
 * Although the object is in the global scope, it is not available until after the deviceready event.
 */
interface Device {
    /** Get the version of Cordova running on the device. */
    cordova: string;
    /** Indicates that Cordova initialize successfully. */
    available: boolean;
    /**
     * The device.model returns the name of the device's model or product. The value is set
     * by the device manufacturer and may be different across versions of the same product.
     */
    model: string;
    /** Get the device's operating system name. */
    platform: string;
    /** Get the device's Universally Unique Identifier (UUID). */
    uuid: string;
    /** Get the operating system version. */
    version: string;
	/** Get the device's manufacturer. */
	manufacturer: string;
	/** Whether the device is running on a simulator. */
	isVirtual: boolean;
	/** Get the device hardware serial number. */
	serial: string;}

declare var device: Device;

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\plugins\cordova-plugin-splashscreen\src\wp\ResolutionHelper.cs

/*
    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

using Microsoft.Phone.Info;
using System;
using System.Windows;

namespace WPCordovaClassLib.Cordova.Commands
{
    public enum Resolutions { WVGA, WXGA, HD };

    public static class ResolutionHelper
    { 
       public static Resolutions CurrentResolution
        {
            get
            {
                switch (Application.Current.Host.Content.ScaleFactor) 
                {
                    case 100: return Resolutions.WVGA;
                    case 160: return Resolutions.WXGA;
                    case 150: return Resolutions.HD;
                }
                throw new InvalidOperationException("Unknown resolution");
            }
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\plugins\cordova-plugin-splashscreen\src\wp\SplashScreen.cs

/*
    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Info;
using System.Windows.Controls.Primitives;
using System.Diagnostics;
using System.Windows.Media.Imaging;
using System.Windows.Resources;
using System.IO;
using System.Xml.Linq;
using System.Linq;
using System.Windows.Threading;

namespace WPCordovaClassLib.Cordova.Commands
{
    /// <summary>
    /// Listens for changes to the state of the battery on the device.
    /// Currently only the "isPlugged" parameter available via native APIs.
    /// </summary>
    public class SplashScreen : BaseCommand
    {
        private Popup popup;

        // Time until we dismiss the splashscreen
        private int prefDelay = 3000;

        // Whether we hide it by default
        private bool prefAutoHide = true;

        // Path to image to use
        private string prefImagePath = "SplashScreenImage.jpg";

        // static because autodismiss is only ever applied once, at app launch
        // subsequent page loads should not cause the SplashScreen to be shown.
        private static bool WasShown = false;

        public SplashScreen()
        {
            LoadConfigPrefs();

            Image SplashScreen = new Image()
            {
                Height = Application.Current.Host.Content.ActualHeight,
                Width = Application.Current.Host.Content.ActualWidth,
                Stretch = Stretch.Fill
            };

            var imageResource = GetSplashScreenImageResource();
            if (imageResource != null)
            {
                BitmapImage splash_image = new BitmapImage();
                splash_image.SetSource(imageResource.Stream);
                SplashScreen.Source = splash_image;
            }

            // Instansiate the popup and set the Child property of Popup to SplashScreen
            popup = new Popup() { IsOpen = false,
                                  Child = SplashScreen,
                                  HorizontalAlignment = HorizontalAlignment.Stretch,
                                  VerticalAlignment = VerticalAlignment.Center

            };
        }

        public override void OnInit()
        {
            // we only want to autoload on the first page load.
            // but OnInit is called for every page load.
            if (!SplashScreen.WasShown)
            {
                SplashScreen.WasShown = true;
                show();
            }
        }

        private void LoadConfigPrefs()
        {
            StreamResourceInfo streamInfo = Application.GetResourceStream(new Uri("config.xml", UriKind.Relative));
            if (streamInfo != null)
            {
                using (StreamReader sr = new StreamReader(streamInfo.Stream))
                {
                    //This will Read Keys Collection for the xml file
                    XDocument configFile = XDocument.Parse(sr.ReadToEnd());

                    string configAutoHide = configFile.Descendants()
                                        .Where(x => x.Name.LocalName == "preference")
                                        .Where(x => (string)x.Attribute("name") == "AutoHideSplashScreen")
                                        .Select(x => (string)x.Attribute("value"))
                                        .FirstOrDefault();

                    bool bVal;
                    prefAutoHide = bool.TryParse(configAutoHide, out bVal) ? bVal : prefAutoHide;

                    string configDelay = configFile.Descendants()
                                      .Where(x => x.Name.LocalName == "preference")
                                      .Where(x => (string)x.Attribute("name") == "SplashScreenDelay")
                                      .Select(x => (string)x.Attribute("value"))
                                      .FirstOrDefault();
                    int nVal;
                    prefDelay = int.TryParse(configDelay, out nVal) ? nVal : prefDelay;

                    string configImage = configFile.Descendants()
                                        .Where(x => x.Name.LocalName == "preference")
                                        .Where(x => (string)x.Attribute("name") == "SplashScreen")
                                        .Select(x => (string)x.Attribute("value"))
                                        .FirstOrDefault();

                    if (!String.IsNullOrEmpty(configImage))
                    {
                        prefImagePath = configImage;
                    }
                }
            }
        }

        private StreamResourceInfo GetSplashScreenImageResource()
        {
            // Get the base filename for the splash screen images
            string imageName = System.IO.Path.GetFileNameWithoutExtension(prefImagePath);
            Uri imageUri = null;
            StreamResourceInfo imageResource = null;

            // First, try to get a resolution-specific splashscreen
            try
            {
                // Determine the device's resolution
                switch (ResolutionHelper.CurrentResolution)
                {
                    case Resolutions.HD:
                        imageUri = new Uri(imageName + ".screen-720p.jpg", UriKind.Relative);
                        break;

                    case Resolutions.WVGA:
                        imageUri = new Uri(imageName + ".screen-WVGA.jpg", UriKind.Relative);
                        break;

                    case Resolutions.WXGA:
                    default:
                        imageUri = new Uri(imageName + ".screen-WXGA.jpg", UriKind.Relative);
                        break;
                }

                imageResource = Application.GetResourceStream(imageUri);
            }
            catch (Exception)
            {
                // It's OK if we didn't get a resolution-specific image
            }

            // Fallback to the default image name without decoration
            if (imageResource == null)
            {
                imageUri = new Uri(prefImagePath, UriKind.Relative);
                imageResource = Application.GetResourceStream(imageUri);
            }

            if (imageUri != null) Debug.WriteLine("INFO :: SplashScreen: using image {0}", imageUri.OriginalString);

            return imageResource;
        }

        public void show(string options = null)
        {
            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                if (!popup.IsOpen)
                {
                    popup.Child.Opacity = 0;

                    Storyboard story = new Storyboard();
                    DoubleAnimation animation = new DoubleAnimation()
                                                    {
                                                        From = 0.0,
                                                        To = 1.0,
                                                        Duration = new Duration(TimeSpan.FromSeconds(0.2))
                                                    };

                    Storyboard.SetTarget(animation, popup.Child);
                    Storyboard.SetTargetProperty(animation, new PropertyPath("Opacity"));
                    story.Children.Add(animation);

                    story.Begin();

                    popup.IsOpen = true;

                    if (prefAutoHide)
                    {
                        StartAutoHideTimer();
                    }
                }
            });
        }

        public void hide(string options = null)
        {
            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                if (popup.IsOpen)
                {
                    popup.Child.Opacity = 1.0;

                    Storyboard story = new Storyboard();
                    DoubleAnimation animation = new DoubleAnimation()
                                                    {
                                                        From = 1.0,
                                                        To = 0.0,
                                                        Duration = new Duration(TimeSpan.FromSeconds(0.4))
                                                    };

                    Storyboard.SetTarget(animation, popup.Child);
                    Storyboard.SetTargetProperty(animation, new PropertyPath("Opacity"));
                    story.Children.Add(animation);
                    story.Completed += (object sender, EventArgs e) =>
                    {
                        popup.IsOpen = false;
                    };
                    story.Begin();
                }
            });
        }

        private void StartAutoHideTimer()
        {
            var timer = new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(prefDelay) };
            timer.Tick += (object sender, EventArgs e) =>
            {
                hide();
                timer.Stop();
            };
            timer.Start();
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\plugins\cordova-plugin-splashscreen\types\index.d.ts

// Type definitions for Apache Cordova Splashscreen plugin
// Project: https://github.com/apache/cordova-plugin-splashscreen
// Definitions by: Microsoft Open Technologies Inc <http://msopentech.com>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// 
// Copyright (c) Microsoft Open Technologies Inc
// Licensed under the MIT license.

interface Navigator {
    /** This plugin displays and hides a splash screen during application launch. */
    splashscreen: {
        /** Dismiss the splash screen. */
        hide(): void;
        /** Displays the splash screen. */
        show(): void;
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\plugins\cordova-plugin-statusbar\src\wp\StatusBar.cs

/*  
	Licensed under the Apache License, Version 2.0 (the "License");
	you may not use this file except in compliance with the License.
	You may obtain a copy of the License at
	
	http://www.apache.org/licenses/LICENSE-2.0
	
	Unless required by applicable law or agreed to in writing, software
	distributed under the License is distributed on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	See the License for the specific language governing permissions and
	limitations under the License.
*/


using Microsoft.Phone.Shell;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Threading;
using System.Windows;
using System.Windows.Media;
using System.Windows.Threading;


/*
 *   http://www.idev101.com/code/User_Interface/StatusBar.html
 *   https://developer.apple.com/library/ios/documentation/userexperience/conceptual/transitionguide/Bars.html
 *   https://developer.apple.com/library/ios/documentation/uikit/reference/UIApplication_Class/Reference/Reference.html#//apple_ref/c/econst/UIStatusBarStyleDefault
 * */


namespace WPCordovaClassLib.Cordova.Commands
{
    public class StatusBar : BaseCommand
    {

        // returns an argb value, if the hex is only rgb, it will be full opacity
        protected Color ColorFromHex(string hexString)
        {
            string cleanHex = hexString.Replace("#", "").Replace("0x", "");
            // turn #FFF into #FFFFFF
            if (cleanHex.Length == 3)
            {
                cleanHex = "" + cleanHex[0] + cleanHex[0] + cleanHex[1] + cleanHex[1] + cleanHex[2] + cleanHex[2];
            }
            // add an alpha 100% if it is missing
            if (cleanHex.Length == 6)
            {
                cleanHex = "FF" + cleanHex;
            }
            int argb = Int32.Parse(cleanHex, NumberStyles.HexNumber);
            Color clr = Color.FromArgb((byte)((argb & 0xff000000) >> 0x18),
                              (byte)((argb & 0xff0000) >> 0x10),
                              (byte)((argb & 0xff00) >> 8),
                              (byte)(argb & 0xff));
            return clr;
        }

        public void _ready(string options)
        {
            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                bool isVis = SystemTray.IsVisible;
                // TODO: pass this to JS
                //Debug.WriteLine("Result::" + res);
                DispatchCommandResult(new PluginResult(PluginResult.Status.OK, isVis));
            });
        }

        public void overlaysWebView(string options)
        {    //exec(null, null, "StatusBar", "overlaysWebView", [doOverlay]);
             // string arg = JSON.JsonHelper.Deserialize<string[]>(options)[0];
        }

        public void styleDefault(string options)
        {    //exec(null, null, "StatusBar", "styleDefault", []);
            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                SystemTray.ForegroundColor = Colors.Black;
            });
        }

        public void styleLightContent(string options)
        {    //exec(null, null, "StatusBar", "styleLightContent", []);
            
            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                SystemTray.ForegroundColor = Colors.White;
            });
        }

        public void styleBlackTranslucent(string options)
        {    //exec(null, null, "StatusBar", "styleBlackTranslucent", []);
            styleLightContent(options);
        }

        public void styleBlackOpaque(string options)
        {    //exec(null, null, "StatusBar", "styleBlackOpaque", []);
            styleLightContent(options);
        }

        public void backgroundColorByName(string options)
        {    //exec(null, null, "StatusBar", "backgroundColorByName", [colorname]);
             // this should NOT be called, js should now be using/converting color names to hex 
        }

        public void backgroundColorByHexString(string options)
        {    //exec(null, null, "StatusBar", "backgroundColorByHexString", [hexString]);
            string argb = JSON.JsonHelper.Deserialize<string[]>(options)[0];

            Color clr = ColorFromHex(argb);
              
            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                SystemTray.Opacity = clr.A / 255.0d;
                SystemTray.BackgroundColor = clr;
                
            });
        }

        public void hide(string options)
        {    //exec(null, null, "StatusBar", "hide", []);
            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                SystemTray.IsVisible = false;
            });

        }

        public void show(string options)
        {    //exec(null, null, "StatusBar", "show", []);
            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                SystemTray.IsVisible = true;
            });
        }
	}
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\plugins\cordova-plugin-statusbar\types\index.d.ts

// Type definitions for Apache Cordova StatusBar plugin
// Project: https://github.com/apache/cordova-plugin-statusbar
// Definitions by: Xinkai Chen <https://github.com/Xinkai>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped

/**
* Global object StatusBar.
*/
interface Window {
    StatusBar: StatusBar;
}


/**
* The StatusBar object provides some functions to customize the iOS and Android StatusBar.
*/
interface StatusBar {
    /**
    * On iOS 7, make the statusbar overlay or not overlay the WebView.
    * @param isOverlay         On iOS 7, set to false to make the statusbar appear like iOS 6.
    *                              Set the style and background color to suit using the other functions.
    */
    overlaysWebView: (isOverlay: boolean) => void;

    /**
    * Use the default statusbar (dark text, for light backgrounds).
    */
    styleDefault: () => void;

    /**
    * Use the lightContent statusbar (light text, for dark backgrounds).
    */
    styleLightContent: () => void;

    /**
    * Use the blackTranslucent statusbar (light text, for dark backgrounds).
    */
    styleBlackTranslucent: () => void;

    /**
    * Use the blackOpaque statusbar (light text, for dark backgrounds).
    */
    styleBlackOpaque: () => void;

    /**
    * On iOS 7, when you set StatusBar.statusBarOverlaysWebView to false,
    * you can set the background color of the statusbar by color name.
    * @param color             Supported color names are:
    *                              black, darkGray, lightGray, white, gray, red, green, blue, cyan, yellow, magenta, orange, purple, brown
    */
    backgroundColorByName: (color: string) => void;

    /**
    * Sets the background color of the statusbar by a hex string.
    * @param color             CSS shorthand properties are also supported.
    *                              On iOS 7, when you set StatusBar.statusBarOverlaysWebView to false, you can set the background color of the statusbar by a hex string (#RRGGBB).
    *                              On WP7 and WP8 you can also specify values as #AARRGGBB, where AA is an alpha value
    */
    backgroundColorByHexString: (color: string) => void;

    /**
    * Hide the statusbar.
    */
    hide: () => void;

    /**
    * Show the statusbar.
    */
    show: () => void;

    /**
    * Read this property to see if the statusbar is visible or not.
    */
    isVisible: boolean;
}

declare var StatusBar: StatusBar;

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8"/>
    <title>XFramework App</title>

    <base href="/"/>

    <meta name="viewport" content="viewport-fit=cover, width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
    <meta name="format-detection" content="telephone=no"/>
    <meta name="msapplication-tap-highlight" content="no"/>

    <link rel="icon" type="image/png" href="assets/icon/favicon.png"/>

    <!-- add to homescreen for ios -->
    <meta name="apple-mobile-web-app-capable" content="yes"/>
    <meta name="apple-mobile-web-app-status-bar-style" content="black"/>

    <!-- For Clear Electron Insecure Content Error ... -->
    <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';">

    <link rel="manifest" href="manifest.webmanifest">
  <meta name="theme-color" content="#1976d2">
</head>

  <body>
    <app-root></app-root>
    <noscript>Please enable JavaScript to continue using this application.</noscript>
</body>
</html>

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\main.ts

import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { AppModule } from './app/app.module';
import { environment } from './environments/environment';

if (environment.production) {
  enableProdMode();
}

platformBrowserDynamic().bootstrapModule(AppModule)
  .catch(err => console.error(err));

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\polyfills.ts

/**
 * This file includes polyfills needed by Angular and is loaded before the app.
 * You can add your own extra polyfills to this file.
 *
 * This file is divided into 2 sections:
 *   1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
 *   2. Application imports. Files imported after ZoneJS that should be loaded before your main
 *      file.
 *
 * The current setup is for so-called "evergreen" browsers; the last versions of browsers that
 * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
 * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
 *
 * Learn more in https://angular.io/guide/browser-support
 */

/***************************************************************************************************
 * BROWSER POLYFILLS
 */

/**
 * IE11 requires the following for NgClass support on SVG elements
 */
// import 'classlist.js';  // Run `npm install --save classlist.js`.

/**
 * Web Animations `@angular/platform-browser/animations`
 * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
 * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
 */
// import 'web-animations-js';  // Run `npm install --save web-animations-js`.

/**
 * By default, zone.js will patch all possible macroTask and DomEvents
 * user can disable parts of macroTask/DomEvents patch by setting following flags
 * because those flags need to be set before `zone.js` being loaded, and webpack
 * will put import in the top of bundle, so user need to create a separate file
 * in this directory (for example: zone-flags.ts), and put the following flags
 * into that file, and then add the following code before importing zone.js.
 * import './zone-flags';
 *
 * The flags allowed in zone-flags.ts are listed here.
 *
 * The following flags will work for all browsers.
 *
 * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
 * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
 * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
 *
 *  in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
 *  with the following flag, it will bypass `zone.js` patch for IE/Edge
 *
 *  (window as any).__Zone_enable_cross_context_check = true;
 *
 */

/***************************************************************************************************
 * Zone JS is required by default for Angular itself.
 */
import 'zone.js';  // Included with Angular CLI.


/***************************************************************************************************
 * APPLICATION IMPORTS
 */

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\app-routing.module.ts

import { NgModule } from '@angular/core';
import { Pages, BaseRoutes } from './config/page.config';
import { PreloadAllModules, RouterModule, Routes } from '@angular/router';

const routes: Routes = [
  //
  // Default ...
  {
    path: BaseRoutes.Default,
    redirectTo: Pages.Home.baseRoute,
    pathMatch: 'full',
  },
  //
  // Home ...
  {
    path: Pages.Home.baseRoute,
    loadChildren: () =>
      import('./pages/home/home.module').then((m) => m.HomePageModule),
  },
  //
  // Core ...
  {
    path: Pages.Core.baseRoute,
    loadChildren: () =>
      import('./pages/core/core.module').then((m) => m.CorePageModule),
  },
  //
  // Services ...
  {
    path: Pages.Services.baseRoute,
    loadChildren: () =>
      import('./pages/services/services.module').then(
        (m) => m.ServicesPageModule
      ),
  },
  //
  // Components ...
  {
    path: Pages.Components.baseRoute,
    loadChildren: () =>
      import('./pages/components/components.module').then(
        (m) => m.ComponentsPageModule
      ),
  },
  //
  // TabsNavs ...
  {
    path: Pages.TabsNav.baseRoute,
    loadChildren: () =>
      import('./pages/tabs/tabs.module').then((m) => m.TabsPageModule),
  },
  //
  // Themes ...
  {
    path: Pages.Themes.baseRoute,
    loadChildren: () =>
      import('./pages/themes/themes.module').then((m) => m.ThemesPageModule),
  },
];

@NgModule({
  imports: [
    RouterModule.forRoot(routes, {
      preloadingStrategy: PreloadAllModules,
      scrollPositionRestoration: 'enabled',
    }),
  ],
  exports: [RouterModule],
})
export class AppRoutingModule {}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\app.component.html

<ion-app>
  <ion-router-outlet></ion-router-outlet>
</ion-app>

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\app.component.scss


### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\app.component.ts

import { Component } from '@angular/core';
import { Platform } from '@ionic/angular';

@Component({
  selector: 'app-root',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.scss']
})
export class AppComponent {
  constructor(private platform: Platform) {
    this.initializeApp();
  }

  initializeApp() {
    this.platform.ready().then(() => {});
  }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\app.module.ts

import {
  XCanDeactivateGuard,
  XFrameworkCoreModule,
  X_FRAMEWORK_CORE_CONFIG,
} from 'x-framework-core';
import {
  XManagerService,
  XHttpInterceptorService,
  XFrameworkServicesModule,
  X_FRAMEWORK_SERVICES_CONFIG,
} from 'x-framework-services';
import {
  XFrameworkComponentsModule,
  X_FRAMEWORK_COMPONENTS_CONFIG,
} from 'x-framework-components';
import { NgModule } from '@angular/core';
import { IonicModule } from '@ionic/angular';
import { AppComponent } from './app.component';
import { ViewsModule } from './views/views.module';
import { X_CONFIG, XCONFIG } from './config/x-config';
import { AppRoutingModule } from './app-routing.module';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { BrowserModule } from '@angular/platform-browser';
import { environment } from '../environments/environment';
import { ServiceWorkerModule } from '@angular/service-worker';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

@NgModule({
  declarations: [AppComponent],
  imports: [
    ViewsModule,
    BrowserModule,
    AppRoutingModule,
    XFrameworkCoreModule,
    IonicModule.forRoot(),
    BrowserAnimationsModule,
    XFrameworkServicesModule,
    XFrameworkComponentsModule,
    ServiceWorkerModule.register('ngsw-worker.js', {
      enabled: environment.production,
    }),
  ],
  providers: [
    //
    // Manager Service ...
    XManagerService,
    //
    // Provide it ...
    XCanDeactivateGuard,
    {
      provide: X_FRAMEWORK_CORE_CONFIG,
      useValue: XCONFIG,
    },
    {
      provide: X_FRAMEWORK_SERVICES_CONFIG,
      useValue: XCONFIG,
    },
    {
      provide: X_FRAMEWORK_COMPONENTS_CONFIG,
      useValue: XCONFIG,
    },
    {
      provide: X_CONFIG,
      useValue: XCONFIG,
    },
    //
    // Register Http Interceptor ...
    {
      provide: HTTP_INTERCEPTORS,
      useClass: XHttpInterceptorService,
      multi: true,
    },
  ],
  bootstrap: [AppComponent],
})
export class AppModule {}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\config\app-config.ts

import {
  DefaultLocale,
  AvailableTranslationResources,
} from './localization.config';
import { NotificationAudioSources } from './audio.config';
import { XFrameworkCoreConfig, XPage } from 'x-framework-core';
import { XFrameworkServicesConfig } from 'x-framework-services';
import { XFrameworkComponentsConfig } from 'x-framework-components';

// tslint:disable-next-line:no-empty-interface
export interface AppConfig {
  defaultLandingPage?: XPage;
  defaultBlogPage?: XPage;
}

export type XFrameworkCoreSharedConfig = Partial<XFrameworkCoreConfig>;
export type XFrameworkServicesSharedConfig = Partial<XFrameworkServicesConfig>;
export type XFrameworkComponentsSharedConfig =
  Partial<XFrameworkComponentsConfig>;
export type XAppSharedConfig = Partial<AppConfig>;

export type XConfig = XFrameworkCoreConfig &
  XFrameworkServicesConfig &
  XFrameworkComponentsConfig &
  AppConfig;
export type XSharedConfig = Partial<XConfig>;

export const xFrameworkCoreSharedConfig: XFrameworkCoreSharedConfig = {
  //
  // App Info ...
  appInstanceName: 'xFrameworkTestApp',
  appNameResource: 'app_name',
  appCompanyResource: 'company',
  appVersion: 'v1.1',

  //
  // Audio Service Configurations ...
  defaultNotificationDelay: 2000,
  notificationAudioSources: NotificationAudioSources,

  //
  // Language Configuration ...
  availableLanguages: AvailableTranslationResources,
  defaultLanguage: DefaultLocale,

  //
  // Api Configuration ...
  poweredValue: 'SaherElmITCenter',

  //
  // Security Service Configurations ...
  secretKey: 'SaherElm@09121694056@Hadi_Khazaee_Asl@yahoo.com',

  //
  // Logging Configuration ...
  baseLogTag: 'xFrameworkApp',

  //
  // Image Related Configs ...
  minAllowedImageSize: 512,
  maxAllowedImageSize: 5242880,
  minAllowedImageCroppableSize: 512,
  allowedImageExtensions: ['.png', '.jpg', '.jpeg'],

  //
  // Profile Image Configs ...
  maxProfileImageSize: 5242880,
  maxProfileImagesUploadFiles: 10,

  //
  defaultCountryCode: 'IR',

  //
  defaultPageSize: 20,
  pageSizes: [10, 20, 40, 50, 100, 200],

  //
  defaultActionDelay: 500,
};

export const xFrameworkServicesSharedConfig: XFrameworkServicesSharedConfig = {
  geoLocationConfig: {
    enableHighAccuracy: true,
    timeout: 5000,
  },
};

export const xFrameworkComponentsSharedConfig: XFrameworkComponentsSharedConfig =
  {
    //
    // File Config ...
    minAllowedFileSize: 512,
    maxAllowedFileSize: 20971520,
    maxAllowedSize: 966367641,
    maxUploadFiles: 10,

    //
    defaultSearchDebounceTime: 500,
  };

export const xAppSharedConfig: XAppSharedConfig = {};

export const xSharedConfig: XSharedConfig = {
  ...xFrameworkCoreSharedConfig,
  ...xFrameworkServicesSharedConfig,
  ...xFrameworkComponentsSharedConfig,
  ...xAppSharedConfig,
};

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\config\app.localization.config.ts

import { XTranslationItem } from 'x-framework-core';

export enum AppResourceIDs {
  //
  //#region Global ...
  sample = 'sample',
  temp_label = 'temp_label',
  documentation = 'documentation',
  default_loading = 'default_loading',

  //
  english = 'english',
  persian = 'persian',

  //
  maintainer_title = 'maintainer_title',
  maintainer_name = 'maintainer_name',
  //#endregion

  //
  //#region Landing ...
  landing_page_title = 'landing_page_title',
  landing_page_description = 'landing_page_description',
  //#endregion

  //
  //#region Home ...
  home = 'home',
  home_description = 'home_description',

  //
  //#region Intro ...
  home_introduction = 'home_introduction',
  home_introduction_description = 'home_introduction_description',
  //#endregion
  //#endregion

  //
  //#region Core ...
  core = 'core',
  core_description = 'core_description',

  //
  //#region Intro ...
  core_introduction = 'core_introduction',
  core_introduction_description = 'core_introduction_description',
  //#endregion
  //#endregion

  //
  //#region Services ...
  services = 'services',
  services_description = 'services_description',

  //
  //#region Intro ...
  services_introduction = 'services_introduction',
  services_introduction_description = 'services_introduction_description',
  //#endregion

  //
  //#region User Device ...
  user_device = 'user_device',
  user_device_description = 'user_device_description',
  //#endregion
  //#endregion

  //
  //#region Components ...
  components = 'components',
  components_description = 'components_description',

  //
  //#region Intro ...
  components_introduction = 'components_introduction',
  components_introduction_description = 'components_introduction_description',
  //#endregion

  //
  //#region Small Components ...
  small_components = 'small_components',
  small_components_description = 'small_components_description',

  //
  //#region Button ...
  button = 'button',
  button_description = 'button_description',
  //#endregion

  //
  //#region ActionBar ...
  action_bar = 'action_bar',
  action_bar_description = 'action_bar_description',
  //#endregion

  //
  //#region SearchBar ...
  search_bar = 'search_bar',
  search_bar_description = 'search_bar_description',
  //#endregion

  //
  //#region Alert ...
  alert = 'alert',
  alert_description = 'alert_description',
  //#endregion

  //
  //#region Notification ...
  notification = 'notification',
  notification_description = 'notification_description',
  //#endregion

  //
  //#region Spinner ...
  spinner = 'spinner',
  spinner_description = 'spinner_description',
  //#endregion

  //
  //#region Loading ...
  loading = 'loading',
  loading_description = 'loading_description',
  //#endregion

  //
  //#region Thumbnail ...
  thumbnail_component = 'thumbnail_component',
  thumbnail_description = 'thumbnail_description',
  //#endregion

  //
  //#region Prompt ...
  prompt = 'prompt',
  prompt_description = 'prompt_description',
  //#endregion

  //
  //#region Color ...
  color = 'color',
  color_description = 'color_description',
  //#endregion

  //
  //#region Picker ...
  picker = 'picker',
  picker_description = 'picker_description',
  //#endregion

  //
  //#region Slotter ...
  slotter = 'slotter',
  slotter_description = 'slotter_description',

  //
  vertical = 'vertical',
  horizontal = 'horizontal',
  //#endregion

  //
  //#region Empty Component ...
  empty_component = 'empty_component',
  empty_component_description = 'empty_component_description',
  //#endregion
  //#endregion

  //
  //#region Card ...
  card = 'card',
  card_description = 'card_description',

  //
  header = 'header',
  actions = 'actions',
  footer = 'footer',
  //#endregion

  //
  //#region Icon ...
  icon = 'icon',
  icon_description = 'icon_description',

  icon_list = 'icon_list',
  //#endregion

  //
  //#region Counter ...
  counter = 'counter',
  counter_description = 'counter_description',

  //
  pause = 'pause',
  //#endregion

  //
  //#region ColorPicker ...
  color_picker = 'color_picker',
  color_picker_description = 'color_picker_description',
  //#endregion

  //
  //#region Fab ...
  fab = 'fab',
  fab_description = 'fab_description',
  //#endregion

  //
  //#region FileUpload ...
  file_components = 'file_components',
  file_components_description = 'file_components_description',

  //
  image_cropper = 'image_cropper',
  image_cropper_description = 'image_cropper_description',

  //
  file_drop_area = 'file_drop_area',
  file_drop_area_description = 'file_drop_area_description',

  //
  file_upload = 'file_upload',
  file_upload_description = 'file_upload_description',
  //#endregion

  //
  //#region Form ...
  form = 'form',
  form_description = 'form_description',

  //
  first_name = 'first_name',
  last_name = 'last_name',

  //
  content = 'content',
  content_type = 'content_type',
  post = 'post',
  news = 'news',
  visibility = 'visibility',
  visible = 'visible',
  hidden = 'hidden',

  //
  publish = 'publish',
  brithDate = 'brithDate',
  wedding_state = 'wedding_state',
  num_of_childs = 'num_of_childs',
  //#endregion

  //
  //#region Grid ...
  grid = 'grid',
  grid_description = 'grid_description',
  //#endregion

  //
  //#region List ...
  list = 'list',
  list_description = 'list_description',
  //#endregion

  //
  //#region Map ...
  map = 'map',
  map_description = 'map_description',
  //#endregion

  //
  //#region Markdown ...
  markdown = 'markdown',
  markdown_description = 'markdown_description',
  //#endregion

  //
  //#region Tree ...
  tree = 'tree',
  tree_description = 'tree_description',
  //#endregion

  //
  //#region DescriptionList ...
  description_list = 'description_list',
  description_list_description = 'description_list_description',
  //#endregion

  //
  //#region ExpandableList ...
  expandable_list = 'expandable_list',
  expandable_list_description = 'expandable_list_description',
  //#endregion

  //
  //#region ExpandablePanel ...
  expandable_panel = 'expandable_panel',
  expandable_panel_description = 'expandable_panel_description',
  //#endregion

  //
  //#region ModelPresenter ...
  model_presenter = 'model_presenter',
  model_presenter_description = 'model_presenter_description',
  //#endregion

  //
  //#region Slider ...
  slider = 'slider',
  slider_description = 'slider_description',
  //#endregion

  //
  //#region Stepper ...
  stepper = 'stepper',
  stepper_description = 'stepper_description',
  //#endregion

  //
  //#region Tabs ...
  tabs = 'tabs',
  tabs_description = 'tabs_description',
  //#endregion

  //
  //#region Table ...
  table = 'table',
  table_description = 'table_description',
  //#endregion

  //
  //#region Table ...
  page = 'page',
  page_description = 'page_description',
  //#endregion

  //
  //#region TabNavigation ...
  tab_navigator = 'tab_navigator',
  tab_navigator_description = 'tab_navigator_description',
  //#endregion
  //#endregion

  //
  //#region TabsNav ...
  tab_page_1 = 'tab_page_1',
  tab_page_2 = 'tab_page_2',
  tab_page_3 = 'tab_page_3',
  //#endregion

  //
  //#region Theme ...
  themes = 'themes',
  themes_description = 'themes_description',
  theme_manager = 'theme_manager',
  theme_manager_description = 'theme_manager_description',
  //#endregion
}

//
export const FaCustomLocales: XTranslationItem[] = [
  //
  //#region Global ...
  {
    id: 'sample',
    value: 'نمونه',
  },
  {
    id: 'temp_label',
    value: 'برچسب پیش فرض',
  },
  {
    id: 'documentation',
    value: 'مستندات',
  },
  {
    id: 'default_loading',
    value: 'در حال بارگزاری',
  },

  //
  {
    id: 'persian',
    value: 'فارسی',
  },
  {
    id: 'english',
    value: 'انگلیسی',
  },

  //
  {
    id: 'maintainer_title',
    value: 'طراح و توسعه دهنده:',
  },
  {
    id: 'maintainer_name',
    value: 'هادی خزاعی اصل',
  },
  //#endregion

  //
  //#region Landing ...
  //
  {
    id: 'landing_page_title',
    value: 'صفحه نخست',
  },
  {
    id: 'landing_page_description',
    value: 'نخستین صفحه ای که نمایش داده میشود',
  },
  //#endregion

  //
  //#region Home ...
  {
    id: 'home',
    value: 'خانه',
  },
  {
    id: 'home_description',
    value: 'مرور کلیات',
  },

  //
  //#region Intro ...
  {
    id: 'home_introduction',
    value: 'مقدمه',
  },
  {
    id: 'home_introduction_description',
    value: 'آشنایی با چارچوب ایکس',
  },
  //#endregion
  //#endregion

  //
  //#region Core ...
  {
    id: 'core',
    value: 'هسته',
  },
  {
    id: 'core_description',
    value: 'مروری بر واحد هسته از چارچوب ایکس',
  },

  //
  //#region Intro ...
  {
    id: 'core_introduction',
    value: 'مقدمه',
  },
  {
    id: 'core_introduction_description',
    value: 'آشنایی با واحد هسته از چارچوب ایکس',
  },
  //#endregion
  //#endregion

  //
  //#region Services ...
  {
    id: 'services',
    value: 'خدمات',
  },
  {
    id: 'services_description',
    value: 'مروری بر واحد خدمات از چارچوب ایکس',
  },

  //
  //#region Intro ...
  {
    id: 'services_introduction',
    value: 'مقدمه',
  },
  {
    id: 'services_introduction_description',
    value: 'آشنایی با واحد خدمات از چارچوب ایکس',
  },
  //#endregion

  //
  //#region User Device ...
  {
    id: 'user_device',
    value: 'ابزار کاربر',
  },
  {
    id: 'user_device_description',
    value: 'شناسایی ابزار مقصد کاربر',
  },
  //#endregion
  //#endregion

  //
  //#region Components ...
  //
  {
    id: 'components',
    value: 'مولفه ها',
  },
  {
    id: 'components_description',
    value: 'توضیح کامل مجموعه مولفه های ارائه شده توسط فریمورک ایکس',
  },

  //
  //#region Intro ...
  {
    id: 'components_introduction',
    value: 'مقدمه',
  },
  {
    id: 'components_introduction_description',
    value: 'آشنایی با واحد مولفه ها',
  },
  //#endregion

  //
  //#region Small Components ...
  {
    id: 'small_components',
    value: 'مولفه های جزئی',
  },
  {
    id: 'small_components_description',
    value: 'ارائه مستندات مربوط به مولفه های جزئی',
  },

  //
  //#region Button ...
  {
    id: 'button',
    value: 'دکمه',
  },
  {
    id: 'button_description',
    value: 'مستندات مربوط به مولفه دکمه',
  },
  //#endregion

  //
  //#region ActionBar ...
  {
    id: 'action_bar',
    value: 'میله فرمان',
  },
  {
    id: 'action_bar_description',
    value: 'مستندات مربوط به مولفه میله فرمان',
  },
  //#endregion

  //
  //#region SearchBar ...
  {
    id: 'search_bar',
    value: 'میله جستجو',
  },
  {
    id: 'search_bar_description',
    value: 'مستندات مربوط به مولفه میله جستجو',
  },
  //#endregion

  //
  //#region Alert ...
  {
    id: 'alert',
    value: 'هشدار',
  },
  {
    id: 'alert_description',
    value: 'مستندات مربوط به مولفه هشدار',
  },
  //#endregion

  //
  //#region Notification ...
  {
    id: 'notification',
    value: 'اعلان',
  },
  {
    id: 'notification_description',
    value: 'مستندات مربوط به مولفه اعلان',
  },
  //#endregion

  //
  //#region Spinner ...
  {
    id: 'spinner',
    value: 'فرفره',
  },
  {
    id: 'spinner_description',
    value: 'مستندات مربوط به مولفه فرفره',
  },
  //#endregion

  //
  //#region Loading ...
  {
    id: 'loading',
    value: 'بارگزاری',
  },
  {
    id: 'loading_description',
    value: 'مستندات مربوط به مولفه بارگزاری',
  },
  //#endregion

  //
  //#region Thumbnail ...
  {
    id: 'thumbnail_component',
    value: 'تصویر بند انگشتی',
  },
  {
    id: 'thumbnail_description',
    value: 'مستندات مربوط به مولفه بند انگشتی',
  },
  //#endregion

  //
  //#region Prompt ...
  {
    id: 'prompt',
    value: 'سوال',
  },
  {
    id: 'prompt_description',
    value: 'مستندات مربوط به مولفه سوال',
  },
  //#endregion

  //
  //#region Color ...
  {
    id: 'color',
    value: 'رنگ',
  },
  {
    id: 'color_description',
    value: 'مستندات مربوط به مولفه رنگ',
  },
  //#endregion

  //
  //#region Picker ...
  {
    id: 'picker',
    value: 'انتخاب',
  },
  {
    id: 'picker_description',
    value: 'مستندات مربوط به مولفه انتخاب',
  },
  //#endregion

  //
  //#region Slotter ...
  {
    id: 'slotter',
    value: 'جورچین',
  },
  {
    id: 'slotter_description',
    value: 'مستندات مربوط به مولفه جورچین',
  },

  //
  {
    id: 'vertical',
    value: 'عمودی',
  },
  {
    id: 'horizontal',
    value: 'افقی',
  },
  //#endregion

  //
  //#region Empty Component ...
  {
    id: 'empty_component',
    value: 'محتوای خالی',
  },
  {
    id: 'empty_component_description',
    value: 'مستندات مربوط به مولفه محتوای خالی',
  },
  //#endregion
  //#endregion

  //
  //#region Card ...
  {
    id: 'card',
    value: 'کارت',
  },
  {
    id: 'card_description',
    value: 'مستندات مربوط به مولفه کارت',
  },

  //
  {
    id: 'header',
    value: 'ناحیه فوقانی',
  },
  {
    id: 'actions',
    value: 'فعالیت ها و فرمان ها',
  },
  {
    id: 'footer',
    value: 'ناحیه تحتانی',
  },
  //#endregion

  //
  //#region Icon ...
  {
    id: 'icon',
    value: 'شمایل',
  },
  {
    id: 'icon_description',
    value: 'مستندات مربوط به مولفه شمایل',
  },

  //
  {
    id: 'icon_list',
    value: 'فهرست شمایل های موجود',
  },
  //#endregion

  //
  //#region Counter ...
  {
    id: 'counter',
    value: 'شمارنده',
  },
  {
    id: 'counter_description',
    value: 'مستندات مربوط به مولفه شمارنده',
  },

  //
  {
    id: 'pause',
    value: 'توقف',
  },
  //#endregion

  //
  //#region ColorPicker ...
  {
    id: 'color_picker',
    value: 'انتخابگر رنگ',
  },
  {
    id: 'color_picker_description',
    value: 'مستندات مربوط به مولفه انتخابگر رنگ',
  },
  //#endregion

  //
  //#region Fab ...
  {
    id: 'fab',
    value: 'دکمه شناور',
  },
  {
    id: 'fab_description',
    value: 'مستندات مربوط به مولفه دکمه شناور',
  },
  //#endregion

  //
  //#region FileUpload ...
  {
    id: 'file_components',
    value: 'مولفه های مرتبط با فایل',
  },
  {
    id: 'file_components_description',
    value: 'مستندات مربوط به مولفه های مرتبط با فایل',
  },

  //
  {
    id: 'image_cropper',
    value: 'برشگر تصویر',
  },
  {
    id: 'image_cropper_description',
    value: 'مستندات مربوط به برشگر تصویر',
  },

  //
  {
    id: 'file_drop_area',
    value: 'جایگذاری فایل',
  },
  {
    id: 'file_drop_area_description',
    value: 'مستندات مربوط به مولفه جایگذاری فایل',
  },

  //
  {
    id: 'file_upload',
    value: 'بارگزاری فایل',
  },
  {
    id: 'file_upload_description',
    value: 'مستندات مربوط به مولفه بارگزاری فایل',
  },
  //#endregion

  //
  //#region Form ...
  {
    id: 'form',
    value: 'فرم',
  },
  {
    id: 'form_description',
    value: 'مستندات مربوط به مولفه فرم',
  },

  //
  {
    id: 'first_name',
    value: 'نام',
  },
  {
    id: 'last_name',
    value: 'نام خانوادگی',
  },
  //
  {
    id: 'content',
    value: 'محتوا',
  },
  {
    id: 'content_type',
    value: 'نوع محتوا',
  },
  {
    id: 'post',
    value: 'مطلب',
  },
  {
    id: 'news',
    value: 'خبر',
  },
  //
  {
    id: 'visibility',
    value: 'وضعیت نمایش',
  },
  {
    id: 'visible',
    value: 'قابل رویت',
  },
  {
    id: 'hidden',
    value: 'پنهان',
  },
  //
  {
    id: 'publish',
    value: 'منتشر شود',
  },
  {
    id: 'brithDate',
    value: 'تاریخ تولد',
  },
  {
    id: 'wedding_state',
    value: 'وضعیت تاهل',
  },
  {
    id: 'num_of_childs',
    value: 'تعداد فرزندان',
  },
  //#endregion

  //
  //#region Grid ...
  {
    id: 'grid',
    value: 'توری',
  },
  {
    id: 'grid_description',
    value: 'مستندات مربوط به مولفه توری',
  },
  //#endregion

  //
  //#region List ...
  {
    id: 'list',
    value: 'فهرست',
  },
  {
    id: 'list_description',
    value: 'مستندات مربوط به مولفه فهرست',
  },
  //#endregion

  //
  //#region Map ...
  {
    id: 'map',
    value: 'نقشه',
  },
  {
    id: 'map_description',
    value: 'مستندات مربوط به مولفه نقشه',
  },
  //#endregion

  //
  //#region Markdown ...
  {
    id: 'markdown',
    value: 'نشانه گزاری',
  },
  {
    id: 'markdown_description',
    value: 'مستندات مربوط به مولفه نشانه گزاری',
  },
  //#endregion

  //
  //#region Tree ...
  {
    id: 'tree',
    value: 'ساختار درختی',
  },
  {
    id: 'tree_description',
    value: 'مستندات مربوط به مولفه ساختار درختی',
  },
  //#endregion

  //
  //#region DescriptionList ...
  {
    id: 'description_list',
    value: 'لیست توضیحات',
  },
  {
    id: 'description_list_description',
    value: 'مستندات مربوط به مولفه لیست توضیحات',
  },
  //#endregion

  //
  //#region ExpandableList ...
  {
    id: 'expandable_list',
    value: 'فهرست باز شونده',
  },
  {
    id: 'expandable_list_description',
    value: 'مستندات مربوط به مولفه فهرست باز شونده',
  },
  //#endregion

  //
  //#region ExpandablePanel ...
  {
    id: 'expandable_panel',
    value: 'قطعه بازشونده',
  },
  {
    id: 'expandable_panel_description',
    value: 'مستندات مربوط به مولفه قطعه بازشونده',
  },
  //#endregion

  //
  //#region ModelPresenter ...
  {
    id: 'model_presenter',
    value: 'نمایشگر داده',
  },
  {
    id: 'model_presenter_description',
    value: 'مستندات مربوط به نمایشگر داده',
  },
  //#endregion

  //
  //#region Slider ...
  {
    id: 'slider',
    value: 'لغزنده',
  },
  {
    id: 'slider_description',
    value: 'مستندات مربوط به مولفه لغزنده',
  },
  //#endregion

  //
  //#region Stepper ...
  {
    id: 'stepper',
    value: 'پله ساز',
  },
  {
    id: 'stepper_description',
    value: 'مستندات مربوط به مولفه پله ساز',
  },
  //#endregion

  //
  //#region Tabs ...
  {
    id: 'tabs',
    value: 'برگه ها',
  },
  {
    id: 'tabs_description',
    value: 'مستندات مربوط به مولفه برگه ها',
  },
  //#endregion

  //
  //#region Table ...
  {
    id: 'table',
    value: 'جدول',
  },
  {
    id: 'table_description',
    value: 'مستندات مربوط به مولفه جدول',
  },
  //#endregion

  //
  //#region Page ...
  {
    id: 'page',
    value: 'صفحه',
  },
  {
    id: 'page_description',
    value: 'مستندات مربوط به مولفه صفحه',
  },
  //#endregion

  //
  //#region TabNavigation ...
  {
    id: 'tab_navigator',
    value: 'پیمایشگر برگه',
  },
  {
    id: 'tab_navigator_description',
    value: 'مستندات مربوط به مولفه پیمایشگر برگه',
  },
  //#endregion
  //#endregion

  //
  //#region TabsNav ...
  {
    id: 'tab_page_1',
    value: 'برگه ۱',
  },
  {
    id: 'tab_page_2',
    value: 'برگه ۲',
  },
  {
    id: 'tab_page_3',
    value: 'برگه ۳',
  },
  //#endregion

  //
  //#region Theme ...
  {
    id: 'themes',
    value: 'پوسته ها',
  },
  {
    id: 'themes_description',
    value: 'دسترسی به تمام امکانات مدیریت پوسته ها',
  },
  //
  {
    id: 'theme_manager',
    value: 'مدیریت پوسته',
  },
  {
    id: 'theme_manager_description',
    value: 'مدیریت و دستکاری پوسته های نمایشی برنامه',
  },
  //#endregion
];

//
export const EnCustomLocales: XTranslationItem[] = [
  //
  //#region Global ...
  {
    id: 'sample',
    value: 'Sample',
  },
  {
    id: 'temp_label',
    value: 'Default Label',
  },
  {
    id: 'documentation',
    value: 'Documentation',
  },
  {
    id: 'default_loading',
    value: 'Loading',
  },

  //
  {
    id: 'persian',
    value: 'Persian',
  },
  {
    id: 'english',
    value: 'English',
  },

  //
  {
    id: 'maintainer_title',
    value: 'Design and Develop',
  },
  {
    id: 'maintainer_name',
    value: 'Hadi Khazaee Asl',
  },
  //#endregion

  //
  //#region Landing ...
  //
  {
    id: 'landing_page_title',
    value: 'First Page',
  },
  {
    id: 'landing_page_description',
    value: 'First Page was shown',
  },
  //#endregion

  //
  //#region Home ...
  {
    id: 'home',
    value: 'Home',
  },
  {
    id: 'home_description',
    value: 'Overview of xFramework',
  },

  //
  //#region Intro ...
  {
    id: 'home_introduction',
    value: 'Introduction',
  },
  {
    id: 'home_introduction_description',
    value: 'Introduction to xFramework',
  },
  //#endregion
  //#endregion

  //
  //#region Core ...
  {
    id: 'core',
    value: 'Core Module',
  },
  {
    id: 'core_description',
    value: 'Overview of xFramework Core Module',
  },

  //
  //#region Intro ...
  {
    id: 'core_introduction',
    value: 'Introduction',
  },
  {
    id: 'core_introduction_description',
    value: 'Introduction to xFramework Core Module',
  },
  //#endregion
  //#endregion

  //
  //#region Services ...
  {
    id: 'services',
    value: 'Services Module',
  },
  {
    id: 'services_description',
    value: 'Overview of xFramework Services Module',
  },

  //
  //#region Intro ...
  {
    id: 'services_introduction',
    value: 'Introduction',
  },
  {
    id: 'services_introduction_description',
    value: 'Introduction to xFramework Services Module',
  },
  //#endregion

  //
  //#region User Device ...
  {
    id: 'user_device',
    value: 'َUser Device',
  },
  {
    id: 'user_device_description',
    value: 'User Device Detection',
  },
  //#endregion
  //#endregion

  //
  //#region Components ...
  {
    id: 'components',
    value: 'Components',
  },
  {
    id: 'components_description',
    value: 'Describe all provided Components in XFramework',
  },

  //
  //#region Intro ...
  {
    id: 'components_introduction',
    value: 'Introduction',
  },
  {
    id: 'components_introduction_description',
    value: 'Introduction to xFramework Components Module',
  },
  //#endregion

  //
  //#region Small Components ...
  {
    id: 'small_components',
    value: 'Small Components',
  },
  {
    id: 'small_components_description',
    value: 'Provide Small Components Documentation',
  },

  //
  //#region Button ...
  {
    id: 'button',
    value: 'Button',
  },
  {
    id: 'button_description',
    value: 'Button Component Documentation',
  },
  //#endregion

  //
  //#region ActionBar ...
  {
    id: 'action_bar',
    value: 'ActionBar',
  },
  {
    id: 'action_bar_description',
    value: 'ActionBar Component Documentation',
  },
  //#endregion

  //
  //#region SearchBar ...
  {
    id: 'search_bar',
    value: 'SearchBar',
  },
  {
    id: 'search_bar_description',
    value: 'SearchBar Component Documentation',
  },
  //#endregion

  //
  //#region Alert ...
  {
    id: 'alert',
    value: 'Alert',
  },
  {
    id: 'alert_description',
    value: 'Alert Component Documentation',
  },
  //#endregion

  //
  //#region Notification ...
  {
    id: 'notification',
    value: 'Notification',
  },
  {
    id: 'notification_description',
    value: 'Notification Component Documentation',
  },
  //#endregion

  //
  //#region Spinner ...
  {
    id: 'spinner',
    value: 'Spinner',
  },
  {
    id: 'spinner_description',
    value: 'Spinner Component Documentation',
  },
  //#endregion

  //
  //#region Loading ...
  {
    id: 'loading',
    value: 'Loading',
  },
  {
    id: 'loading_description',
    value: 'Loading Component Documentation',
  },
  //#endregion

  //
  //#region Thumbnail ...
  {
    id: 'thumbnail_component',
    value: 'Thumbnail',
  },
  {
    id: 'thumbnail_description',
    value: 'Thumbnail Component Documentation',
  },
  //#endregion

  //
  //#region Prompt ...
  {
    id: 'prompt',
    value: 'Prompt',
  },
  {
    id: 'prompt_description',
    value: 'Prompt Component Documentation',
  },
  //#endregion

  //
  //#region Color ...
  {
    id: 'color',
    value: 'Color',
  },
  {
    id: 'color_description',
    value: 'Color Component Documentation',
  },
  //#endregion

  //
  //#region Picker ...
  {
    id: 'picker',
    value: 'Picker',
  },
  {
    id: 'picker_description',
    value: 'Picker Component Documentation',
  },
  //#endregion

  //
  //#region Slotter ...
  {
    id: 'slotter',
    value: 'Slotter',
  },
  {
    id: 'slotter_description',
    value: 'Slotter Component Documentation',
  },

  //
  {
    id: 'vertical',
    value: 'Vertical',
  },
  {
    id: 'horizontal',
    value: 'Horizontal',
  },
  //#endregion

  //
  //#region Empty Component ...
  {
    id: 'empty_component',
    value: 'Empty',
  },
  {
    id: 'empty_component_description',
    value: 'Empty Component Documentation',
  },
  //#endregion
  //#endregion

  //
  //#region Card ...
  {
    id: 'card',
    value: 'Card',
  },
  {
    id: 'card_description',
    value: 'Card Component Documentation',
  },

  //
  {
    id: 'header',
    value: 'Header',
  },
  {
    id: 'actions',
    value: 'Actions',
  },
  {
    id: 'footer',
    value: 'Footer',
  },
  //#endregion

  //
  //#region Icon ...
  {
    id: 'icon',
    value: 'Icon',
  },
  {
    id: 'icon_description',
    value: 'Icon Component Documentation',
  },

  //
  {
    id: 'icon_list',
    value: 'Icons List',
  },
  //#endregion

  //
  //#region Counter ...
  {
    id: 'counter',
    value: 'Counter',
  },
  {
    id: 'counter_description',
    value: 'Counter Component Documentation',
  },

  //
  {
    id: 'pause',
    value: 'Pause',
  },
  //#endregion

  //
  //#region ColorPicker ...
  {
    id: 'color_picker',
    value: 'ColorPicker',
  },
  {
    id: 'color_picker_description',
    value: 'ColorPicker Component Documentation',
  },
  //#endregion

  //
  //#region Fab ...
  {
    id: 'fab',
    value: 'Floating Action Button',
  },
  {
    id: 'fab_description',
    value: 'FAB Component Documentation',
  },
  //#endregion

  //
  //#region FileUpload ...
  {
    id: 'file_components',
    value: 'Files Related Components',
  },
  {
    id: 'file_components_description',
    value: 'Files Related Components Documentation',
  },

  //
  {
    id: 'image_cropper',
    value: 'Image Cropper',
  },
  {
    id: 'image_cropper_description',
    value: 'Image Cropper Documentation',
  },

  //
  {
    id: 'file_drop_area',
    value: 'File Drop Area',
  },
  {
    id: 'file_drop_area_description',
    value: 'File Drop Area Documentation',
  },

  //
  {
    id: 'file_upload',
    value: 'FileUpload',
  },
  {
    id: 'file_upload_description',
    value: 'FileUpload Component Documentation',
  },
  //#endregion

  //
  //#region Form ...
  {
    id: 'form',
    value: 'Form',
  },
  {
    id: 'form_description',
    value: 'Form Component Documentation',
  },

  //
  {
    id: 'first_name',
    value: 'First Name',
  },
  {
    id: 'last_name',
    value: 'Last Name',
  },
  //
  {
    id: 'content',
    value: 'Content',
  },
  {
    id: 'content_type',
    value: 'Content Type',
  },
  {
    id: 'post',
    value: 'Post',
  },
  {
    id: 'news',
    value: 'News',
  },
  //
  {
    id: 'visibility',
    value: 'Visibility',
  },
  {
    id: 'visible',
    value: 'Visible',
  },
  {
    id: 'hidden',
    value: 'Hidden',
  },
  //
  {
    id: 'publish',
    value: 'Publish',
  },
  {
    id: 'brithDate',
    value: 'BrithDate',
  },
  {
    id: 'wedding_state',
    value: 'Wedding State',
  },
  {
    id: 'num_of_childs',
    value: 'ٔNumber of Childs',
  },
  //#endregion

  //
  //#region Grid ...
  {
    id: 'grid',
    value: 'Grid',
  },
  {
    id: 'grid_description',
    value: 'Grid Component Documentation',
  },
  //#endregion

  //
  //#region List ...
  {
    id: 'list',
    value: 'List',
  },
  {
    id: 'list_description',
    value: 'List Component Documentation',
  },
  //#endregion

  //
  //#region Map ...
  {
    id: 'map',
    value: 'Map',
  },
  {
    id: 'map_description',
    value: 'Map Component Documentation',
  },
  //#endregion

  //
  //#region Markdown ...
  {
    id: 'markdown',
    value: 'Markdown',
  },
  {
    id: 'markdown_description',
    value: 'Markdown Component Documentation',
  },
  //#endregion

  //
  //#region Tree ...
  {
    id: 'tree',
    value: 'Tree',
  },
  {
    id: 'tree_description',
    value: 'Tree Component Documentation',
  },
  //#endregion

  //
  //#region DescriptionList ...
  {
    id: 'description_list',
    value: 'ِDescription List',
  },
  {
    id: 'description_list_description',
    value: 'Description List Component Documentation',
  },
  //#endregion

  //
  //#region ExpandableList ...
  {
    id: 'expandable_list',
    value: 'Expandable List',
  },
  {
    id: 'expandable_list_description',
    value: 'Expandable List Component Documentation',
  },
  //#endregion

  //
  //#region ExpandablePanel ...
  {
    id: 'expandable_panel',
    value: 'Expandable Panel',
  },
  {
    id: 'expandable_panel_description',
    value: 'Expandable Panel Component Documentation',
  },
  //#endregion

  //
  //#region ModelPresenter ...
  {
    id: 'model_presenter',
    value: 'Model Presenter',
  },
  {
    id: 'model_presenter_description',
    value: 'Model Presenter Component Documentation',
  },
  //#endregion

  //
  //#region Slider ...
  {
    id: 'slider',
    value: 'Slider',
  },
  {
    id: 'slider_description',
    value: 'Slider Component Documentation',
  },
  //#endregion

  //
  //#region Stepper ...
  {
    id: 'stepper',
    value: 'Stepper',
  },
  {
    id: 'stepper_description',
    value: 'Stepper Component Documentation',
  },
  //#endregion

  //
  //#region Tabs ...
  {
    id: 'tabs',
    value: 'Tabs',
  },
  {
    id: 'tabs_description',
    value: 'Tabs Component Documentation',
  },
  //#endregion

  //
  //#region Table ...
  {
    id: 'table',
    value: 'Table',
  },
  {
    id: 'table_description',
    value: 'Table Component Documentation',
  },
  //#endregion

  //
  //#region Page ...
  {
    id: 'page',
    value: 'Page',
  },
  {
    id: 'page_description',
    value: 'Page Component Documentation',
  },
  //#endregion

  //
  //#region TabNavigation ...
  {
    id: 'tab_navigator',
    value: 'Tab Navigator',
  },
  {
    id: 'tab_navigator_description',
    value: 'Tab Navigator Component Documentation',
  },
  //#endregion
  //#endregion

  //
  //#region TabsNav ...
  {
    id: 'tab_page_1',
    value: 'Page 1',
  },
  {
    id: 'tab_page_2',
    value: 'Page 2',
  },
  {
    id: 'tab_page_3',
    value: 'Page 3',
  },
  //#endregion

  //
  //#region Theme ...
  {
    id: 'theme',
    value: 'Themes',
  },
  {
    id: 'themes_description',
    value: 'Access All Theme Management tools',
  },
  //
  {
    id: 'theme_manager',
    value: 'Theme Manager',
  },
  {
    id: 'theme_manager_description',
    value: 'add/remove and edit Application Themes',
  },
  //#endregion
];

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\config\audio.config.ts

import { XNotificationSound, XActionType } from 'x-framework-core';

export const NotificationAudioSources: XNotificationSound[] = [
  {
    type: XActionType.User,
    resourcePath: './assets/audio/user_notification.wav',
  },
  {
    type: XActionType.System,
    resourcePath: './assets/audio/system_notification.wav',
  },
  {
    type: XActionType.Capture,
    resourcePath: './assets/audio/capture_notification.wav',
  },
];

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\config\exceptions.config.ts

import { XTranslationItem } from 'x-framework-core';

/**
 * Persian Exception Translations ...
 */
export const XFaIRExceptions: XTranslationItem[] = [
  //
  //#region Invalid Exceptions 1xx ...
  {
    id: 'ex_100',
    value: 'داده نا معتبر',
  },
  {
    id: 'ex_101',
    value: 'تاریخ نامعتبر',
  },
  {
    id: 'ex_102',
    value: 'درخواست اشتباه',
  },
  {
    id: 'ex_103',
    value: 'ورودی نامعتبر',
  },
  {
    id: 'ex_104',
    value: 'پیام نامعتبر',
  },
  {
    id: 'ex_105',
    value: 'نشانه نامعتبر',
  },
  {
    id: 'ex_106',
    value: 'کد اععتبارسنجی نامعتبر',
  },
  {
    id: 'ex_107',
    value: 'پست الکترونیک نامعتبر',
  },
  {
    id: 'ex_108',
    value: 'شماره تلفن همراه نامعتبر',
  },
  {
    id: 'ex_109',
    value: 'کلمه عبور نامعتبر',
  },
  {
    id: 'ex_110',
    value: 'آدرس اینترنتی نامعتبر',
  },
  {
    id: 'ex_111',
    value: 'دستگاه نامعتبر',
  },
  {
    id: 'ex_112',
    value: 'تصویر پروفایل نامعتبر',
  },
  {
    id: 'ex_113',
    value: 'فایل نامعتبر',
  },
  {
    id: 'ex_114',
    value: 'نام کاربری نامعتبر',
  },
  //#endregion

  //
  //#region Not (...) Exceptions 2xx ...
  {
    id: 'ex_200',
    value: 'یافت نشد',
  },
  {
    id: 'ex_201',
    value: 'عدم تایید جواز',
  },
  {
    id: 'ex_202',
    value: 'سطح دسترسی نامعتبر',
  },
  {
    id: 'ex_203',
    value: 'غیر قابل نمایش',
  },
  //#endregion

  //
  //#region User/Registration/Account/Bann Exceptions 3xx ...
  {
    id: 'ex_300',
    value: 'حساب کاربری قفل شده است',
  },
  {
    id: 'ex_301',
    value: 'خطا در ورود',
  },
  {
    id: 'ex_302',
    value: 'کاربر قبلا ثبت نام کرده است',
  },
  {
    id: 'ex_303',
    value: 'کاربر غیرفعال است',
  },
  {
    id: 'ex_304',
    value: 'دستگاه شما قفل شده است تا : (0)',
  },
  {
    id: 'ex_305',
    value: 'امکان درخواست کد اعتبارسنجی وجود ندارد تا : (0)',
  },
  {
    id: 'ex_306',
    value: 'کلمه عبورها یکسان هستند',
  },
  {
    id: 'ex_307',
    value: 'شماره های تلفن یکسان هستند',
  },
  {
    id: 'ex_308',
    value: 'آدرس های پست الکترونیک یکسان هستند',
  },
  {
    id: 'ex_309',
    value: 'شماره تلفن قبلا ثبت شده است',
  },
  {
    id: 'ex_310',
    value: 'پست الکترونیک قبلا ثبت شده است',
  },
  {
    id: 'ex_311',
    value: 'تلفن همراه تایید نشده است',
  },
  {
    id: 'ex_312',
    value: 'پست الکترونیک تایید نشده است',
  },
  {
    id: 'ex_313',
    value: 'مطلب ممنوعه',
  },
  {
    id: 'ex_314',
    value: 'کاربر ممنوعه',
  },
  //#endregion

  //
  //#region General Exceptions 4xx ...
  {
    id: 'ex_400',
    value: 'خطای نا شناخته',
  },
  {
    id: 'ex_401',
    value: 'مورد تکراری',
  },
  {
    id: 'ex_402',
    value: 'شکست عملیات',
  },
  {
    id: 'ex_403',
    value: 'تاریخ مصرف منقضی شده است',
  },
  {
    id: 'ex_404',
    value: 'غیر قابل اسفاده',
  },
  {
    id: 'ex_405',
    value: 'تعداد برچسب ها بیش از جد مجاز است',
  },
  {
    id: 'ex_406',
    value: 'اتمام مهلت زمانی',
  },
  //#endregion

  //
  //#region File Exceptions 5xx ...
  {
    id: 'ex_500',
    value: 'پرونده خالی است',
  },
  {
    id: 'ex_501',
    value: 'اندازه بیش از حد مجاز',
  },
  {
    id: 'ex_502',
    value: 'گونه نامعتبر فایل',
  },
  {
    id: 'ex_503',
    value: 'تعداد رسانه ها بیش از حد مجاز است',
  },
  //#endregion

  //
  //#region Configuration Exceptions 6xx ...
  {
    id: 'ex_600',
    value: 'پیکربندی اشتباه',
  },
  {
    id: 'ex_601',
    value: 'خطا در پیکربندی سامانه ذخیره سازی',
  },
  {
    id: 'ex_602',
    value: 'خطا در پیکربندی سامانه ذخیره سازی',
  },
  //#endregion

  //
  //#region xFramework Exceptions 9xx ...
  {
    id: 'ex_900',
    value: 'تعداد فایل ها بیش از حد مجاز است',
  },
  {
    id: 'ex_901',
    value: 'مجموع اندازه فایل ها کمتر از حد مجاز است',
  },
  {
    id: 'ex_902',
    value: 'مجموع اندازه فایل ها بیش از حد مجاز است',
  },
  {
    id: 'ex_903',
    value: 'شرایط و ضوابط باید پذیرفته شوند',
  },
  {
    id: 'ex_904',
    value: 'عدم پشتیبانی از سیستم موقعیت یاب',
  },
  {
    id: 'ex_905',
    value: 'مجوز دسترسی به موقعیت خود را صادر نکرده اید',
  },
  {
    id: 'ex_906',
    value: 'دسترسی به موقعیت جغرافیایی امکان پذیر نیست',
  },
  {
    id: 'ex_907',
    value: 'عدم پشتیبانی از سیستم ذخیره سازی',
  },
  {
    id: 'ex_908',
    value: 'برای دسترسی به محتوا باید از سامانه خارج شوید',
  },
  {
    id: 'ex_909',
    value: 'زبان انتخاب شده نامعتبر است',
  },
  {
    id: 'ex_910',
    value: 'داده نامعتبر برای انتخاب کاربر',
  },
  //#endregion
];

/**
 * English Exception Translations ...
 */
export const XEnUSExceptions: XTranslationItem[] = [
  //
  //#region Invalid Exceptions 1xx ...
  {
    id: 'ex_100',
    value: 'Invalid Data ...',
  },
  {
    id: 'ex_101',
    value: 'Invalid Date ...',
  },
  {
    id: 'ex_102',
    value: 'Bad Request ...',
  },
  {
    id: 'ex_103',
    value: 'Invalid Args ...',
  },
  {
    id: 'ex_104',
    value: 'Invalid Message ...',
  },
  {
    id: 'ex_105',
    value: 'Invalid Token ...',
  },
  {
    id: 'ex_106',
    value: 'Invalid Verification Code ...',
  },
  {
    id: 'ex_107',
    value: 'Invalid Email Address ...',
  },
  {
    id: 'ex_108',
    value: 'Invalid Mobile Number ...',
  },
  {
    id: 'ex_109',
    value: 'Invalid Password ...',
  },
  {
    id: 'ex_110',
    value: 'Invalid URL ...',
  },
  {
    id: 'ex_111',
    value: 'Invalid Device ...',
  },
  {
    id: 'ex_112',
    value: 'Invalid Profile Image ...',
  },
  {
    id: 'ex_113',
    value: 'Invalid File ...',
  },
  {
    id: 'ex_114',
    value: 'Invalid Username ...',
  },
  //#endregion

  //
  //#region Not (...) Exceptions 2xx ...
  {
    id: 'ex_200',
    value: 'Not Found ...',
  },
  {
    id: 'ex_201',
    value: 'Not Allowed ...',
  },
  {
    id: 'ex_202',
    value: 'Not Authorized ...',
  },
  {
    id: 'ex_203',
    value: 'Not Visible ...',
  },
  //#endregion

  //
  //#region User/Registration/Account/Bann Exceptions 3xx ...
  {
    id: 'ex_300',
    value: 'Account Locked out ...',
  },
  {
    id: 'ex_301',
    value: 'Login Failed ...',
  },
  {
    id: 'ex_302',
    value: 'User Registered Before ...',
  },
  {
    id: 'ex_303',
    value: 'User Disabled ...',
  },
  {
    id: 'ex_304',
    value: 'Device Banned Until:(0)',
  },
  {
    id: 'ex_305',
    value: `You can't Request Verification code Until:(0)`,
  },
  {
    id: 'ex_306',
    value: 'Passwords Same ...',
  },
  {
    id: 'ex_307',
    value: 'Mobiles Same ...',
  },
  {
    id: 'ex_308',
    value: 'Emails Same ...',
  },
  {
    id: 'ex_309',
    value: 'Mobile In Used ...',
  },
  {
    id: 'ex_310',
    value: 'Email In Used ...',
  },
  {
    id: 'ex_311',
    value: 'Mobile Not Confirmed ...',
  },
  {
    id: 'ex_312',
    value: 'Email Not Confirmed ...',
  },
  {
    id: 'ex_313',
    value: 'Post Banned ...',
  },
  {
    id: 'ex_314',
    value: 'User Banned ...',
  },
  //#endregion

  //
  //#region General Exceptions 4xx ...
  {
    id: 'ex_400',
    value: 'Unknown Error ...',
  },
  {
    id: 'ex_401',
    value: 'Duplicate ...',
  },
  {
    id: 'ex_402',
    value: 'Action Failed ...',
  },
  {
    id: 'ex_403',
    value: 'Expired Date ...',
  },
  {
    id: 'ex_404',
    value: 'Unavailable ...',
  },
  {
    id: 'ex_405',
    value: 'Max Allowed Tag Exceeded ...',
  },
  {
    id: 'ex_406',
    value: 'Timeout ...',
  },
  //#endregion

  //
  //#region File Exceptions 5xx ...
  {
    id: 'ex_500',
    value: 'Empty File ...',
  },
  {
    id: 'ex_501',
    value: 'max File size exceeded ...',
  },
  {
    id: 'ex_502',
    value: 'Unsupported File Type ...',
  },
  {
    id: 'ex_503',
    value: 'Max Allowed Media Exceeded ...',
  },
  //#endregion

  //
  //#region Configuration Exceptions 6xx ...
  {
    id: 'ex_600',
    value: 'Invalid Configuration ...',
  },
  {
    id: 'ex_601',
    value: 'Storage Service Initiallization Failed ...',
  },
  {
    id: 'ex_602',
    value: 'Message Service Initialization Failed ...',
  },
  //#endregion

  //
  //#region xFramework Exceptions 9xx ...
  {
    id: 'ex_900',
    value: 'Max Allowed Files Exceeded ...',
  },
  {
    id: 'ex_901',
    value: 'Min Files Size Exceeded ...',
  },
  {
    id: 'ex_902',
    value: 'Max Files Size Exceeded ...',
  },
  {
    id: 'ex_903',
    value: 'Must Accept Terms And Conditions ...',
  },
  {
    id: 'ex_904',
    value: 'Browser does not support Location Services ...',
  },
  {
    id: 'ex_905',
    value: 'You have rejected access to your Location ...',
  },
  {
    id: 'ex_906',
    value: 'Unable to determine your Location ...',
  },
  {
    id: 'ex_907',
    value: 'Browser does not support Storage Services ...',
  },
  {
    id: 'ex_908',
    value: 'Must Logout to access content ...',
  },
  {
    id: 'ex_909',
    value: 'Invalid Locale ...',
  },
  {
    id: 'ex_910',
    value: 'Invalid User Selector ...',
  },
  //#endregion
];

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\config\localization.config.ts

import { XLocale, XLanguageDescriptor } from 'x-framework-core';
import { XFaIRExceptions, XEnUSExceptions } from './exceptions.config';
import { EnCustomLocales, FaCustomLocales } from './app.localization.config';

export const DefaultLocale: XLocale = 'fa-IR';

export const AvailableTranslationResources: XLanguageDescriptor[] = [
  {
    name: 'persian',
    locale: 'fa-IR',
    language: 'fa',
    direction: 'rtl',
    resources: [
      //
      //#region App ...
      // TODO: Customize this ...
      {
        id: 'app_name',
        value: 'چارچوب ایکس',
      },
      //
      // TODO: Customize this ...
      {
        id: 'company',
        value: 'فن آوران ساحر علم',
      },
      //#endregion

      //
      //#region Commons ...
      {
        id: 'id',
        value: 'شناسه',
      },
      {
        id: 'file_name',
        value: 'نام فایل',
      },

      //
      {
        id: 'error',
        value: 'خطا',
      },
      {
        id: 'required',
        value: 'الزامی است.',
      },

      //
      {
        id: 'loading',
        value: 'بارگزاری',
      },

      //
      {
        id: 'username',
        value: 'نام کاربری',
      },
      {
        id: 'password',
        value: 'کلمه عبور',
      },

      //
      {
        id: 'first_name',
        value: 'نام',
      },
      {
        id: 'last_name',
        value: 'نام خانوادگی',
      },

      //
      {
        id: 'verified',
        value: 'تایید شده',
      },
      {
        id: 'unverified',
        value: 'تایید نشده',
      },

      //
      {
        id: 'thumbnail',
        value: 'پیش نمایش',
      },

      //
      {
        id: 'language',
        value: 'زبان',
      },

      //
      {
        id: 'take_screenshot',
        value: 'تصویر برداری ازمحیط',
      },
      {
        id: 'enable_capture_mode',
        value: 'فعالسازی حالت تصویر برداری',
      },
      {
        id: 'disable_capture_mode',
        value: 'غیرفعالسازی حالت تصویر برداری',
      },
      //#endregion

      //
      //#region File Types ...
      {
        id: 'audio',
        value: 'صوت',
      },
      {
        id: 'video',
        value: 'فیلم',
      },
      {
        id: 'document',
        value: 'سند',
      },
      {
        id: 'cover_image',
        value: 'تصویر',
      },
      {
        id: 'image',
        value: 'تصویر',
      },
      {
        id: 'avatar',
        value: 'تصویر پروفایل',
      },
      {
        id: 'unknown',
        value: 'ناشناس',
      },
      {
        id: 'location',
        value: 'موقعیت جغرافیای',
      },
      //#endregion

      //
      //#region Messages ...
      {
        id: 'are_you_sure',
        value: 'اطمینان دارید ؟',
      },
      {
        id: 'success_msg',
        value: 'عملیات با موفقیت انجام شد',
      },
      {
        id: 'locked_msg',
        value:
          'برای ترک این صفحه باید فعالیت جاری را لغو کرده و یا به اتمام برسانید',
      },
      {
        id: 'empty_content',
        value: 'خالی است',
      },
      {
        id: 'no_item',
        value: 'محتوایی ثبت نشده است',
      },
      {
        id: 'drag_drop_here',
        value: 'محل رها کردن فایل',
      },
      //#endregion

      //
      //#region Components ...
      {
        id: 'map_dialog_title',
        value: 'نمایش موقعیت مکانی',
      },
      {
        id: 'map_dialog_select_title',
        value: 'انتخاب موقعیت جغرافیایی',
      },
      {
        id: 'color_picker_dialog_title',
        value: 'انتخاب رنگ',
      },
      //#endregion

      //
      //#region Verbs ...
      {
        id: 'dismiss',
        value: 'رد کردن',
      },
      {
        id: 'accept',
        value: 'می پذیرم',
      },
      {
        id: 'ok',
        value: 'بسیار خب',
      },
      {
        id: 'save',
        value: 'ذخیره',
      },
      {
        id: 'cancel',
        value: 'لغو',
      },
      {
        id: 'retry',
        value: 'سعی مجدد',
      },
      {
        id: 'edit',
        value: 'ویرایش',
      },
      {
        id: 'reset',
        value: 'باز نشاندن',
      },
      {
        id: 'change',
        value: 'تغییر',
      },
      {
        id: 'start',
        value: 'آغاز',
      },
      {
        id: 'yes',
        value: 'بله',
      },
      {
        id: 'no',
        value: 'خیر',
      },
      {
        id: 'verify',
        value: 'تایید کردن',
      },
      {
        id: 'confirm',
        value: 'تاییدیه',
      },
      {
        id: 'crop',
        value: 'برش',
      },
      {
        id: 'clear',
        value: 'پاک کردن',
      },
      //
      {
        id: 'set',
        value: 'تنظیم',
      },
      {
        id: 'select',
        value: 'انتخاب',
      },
      {
        id: 'send',
        value: 'ارسال',
      },
      {
        id: 'show',
        value: 'نمایش دادن',
      },
      {
        id: 'hide',
        value: 'پنهان کردن',
      },
      {
        id: 'search',
        value: 'جستجو',
      },
      {
        id: 'delete',
        value: 'حذف',
      },
      {
        id: 'clone',
        value: 'نمونه گیری',
      },
      {
        id: 'select_all',
        value: 'انتخاب همه',
      },
      {
        id: 'select_file',
        value: 'انتخاب فایل(ها)',
      },
      {
        id: 'select_all_group',
        value: 'انتخاب همه موارد فیلتر شده',
      },
      {
        id: 'deselect_all',
        value: 'لغو همه انتخاب ها',
      },
      {
        id: 'deselect_all_group',
        value: 'لغو انتخاب همه موارد فیلتر شده',
      },
      {
        id: 'inverse_selection',
        value: 'انتخاب معکوس',
      },
      //
      {
        id: 'selected_location',
        value: 'انتخاب محل',
      },
      {
        id: 'preset_colors',
        value: 'رنگ های پیش فرض',
      },
      {
        id: 'copy_to_clipboard',
        value: 'ثبت در حافظه موقت',
      },
      {
        id: 'color',
        value: 'رنگ',
      },
      {
        id: 'colors',
        value: 'رنگها',
      },
      {
        id: 'upload',
        value: 'بارگزاری',
      },
      {
        id: 'import',
        value: 'وارد کردن',
      },
      {
        id: 'continue',
        value: 'ادامه',
      },
      {
        id: 'finish',
        value: 'پایان',
      },
      {
        id: 'enable',
        value: 'فعال',
      },
      {
        id: 'disable',
        value: 'غیر فعال',
      },
      {
        id: 'all',
        value: 'همه',
      },
      {
        id: 'new',
        value: 'جدید',
      },
      {
        id: 'add',
        value: 'افزودن',
      },
      {
        id: 'update',
        value: 'بروز رسانی',
      },
      {
        id: 'details',
        value: 'جزئیات',
      },
      {
        id: 'translation',
        value: 'ترجمه',
      },
      {
        id: 'download',
        value: 'دریافت',
      },
      {
        id: 'list',
        value: 'فهرست',
      },
      {
        id: 'options',
        value: 'انتخاب ها',
      },
      {
        id: 'descriptions',
        value: 'توضیحات',
      },

      //
      {
        id: 'type',
        value: 'نوع',
      },
      //
      {
        id: 'media',
        value: 'رسانه',
      },
      {
        id: 'medias',
        value: 'رسانه ها',
      },

      //
      {
        id: 'go',
        value: 'رفتن',
      },
      {
        id: 'input',
        value: 'ورود',
      },
      {
        id: 'preview',
        value: 'پیش نمایش',
      },
      //#endregion

      //
      //#region Pagination ...
      {
        id: 'first',
        value: 'نخستین',
      },
      {
        id: 'last',
        value: 'آخرین',
      },
      {
        id: 'previous',
        value: 'قبلی',
      },
      {
        id: 'next',
        value: 'بعدی',
      },
      {
        id: 'back',
        value: 'بازگشت',
      },
      //#endregion

      //
      //#region Markdown ...
      {
        id: 'x_markdown_preview',
        value: 'پیش نمایش',
      },
      {
        id: 'x_markdown_image',
        value: 'تصویر',
      },
      {
        id: 'x_markdown_link',
        value: 'پیوند',
      },
      {
        id: 'x_markdown_ol',
        value: 'فهرست ترتیبی',
      },
      {
        id: 'x_markdown_ul',
        value: 'فهرست بدون ترتیب',
      },
      {
        id: 'x_markdown_quote',
        value: 'نقل قول',
      },
      {
        id: 'x_markdown_code',
        value: 'کد منبع',
      },
      {
        id: 'x_markdown_heading',
        value: 'عنوان',
      },
      {
        id: 'x_markdown_italic',
        value: 'ایتالیک',
      },
      {
        id: 'x_markdown_bold',
        value: 'پر رنگ',
      },
      {
        id: 'x_markdown_guide',
        value: 'راهنمای نگارش',
      },
      //#endregion

      //
      //#region Theme Related ...
      //
      {
        id: 'theme',
        value: 'پوسته',
      },
      {
        id: 'theme_mode',
        value: 'حالت نمایشی',
      },
      //
      {
        id: 'theme_dark',
        value: 'تیره',
      },
      {
        id: 'theme_light',
        value: 'روشن',
      },
      //
      {
        id: 'theme_name',
        value: 'نام پوسته',
      },
      {
        id: 'theme_name_description',
        value: 'نام پوسته را وارد کنید',
      },
      //
      {
        id: 'theme_clone_title',
        value: 'نمونه گیری از پوسته',
      },
      //#endregion

      //
      //#region Color Picker Related ...
      {
        id: 'input_color_title',
        value: 'تعیین رنگ',
      },
      {
        id: 'input_color_description',
        value: 'مقدار رنگ را وارد کنید',
      },
      //#endregion

      //
      // Custom Translations ...
      ...FaCustomLocales,

      //
      // Persian Translated Exceptions ...
      ...XFaIRExceptions,
    ],
  },
  {
    name: 'english',
    locale: 'en-US',
    language: 'en',
    direction: 'ltr',
    resources: [
      //
      //#region App ...
      // TODO: Customize this ...
      {
        id: 'app_name',
        value: 'XFramework',
      },
      //
      // TODO: Customize this ...
      {
        id: 'company',
        value: 'SaherElm IT Center',
      },
      //#endregion

      //
      //#region Commons ...
      {
        id: 'id',
        value: 'ID',
      },
      {
        id: 'file_name',
        value: 'File Name',
      },

      //
      {
        id: 'error',
        value: 'Error',
      },
      {
        id: 'required',
        value: 'required',
      },

      //
      {
        id: 'loading',
        value: 'loading',
      },

      //
      {
        id: 'username',
        value: 'Username',
      },
      {
        id: 'password',
        value: 'Password',
      },

      //
      {
        id: 'first_name',
        value: 'Firstname',
      },
      {
        id: 'last_name',
        value: 'Lastname',
      },

      //
      {
        id: 'verified',
        value: 'Verified',
      },
      {
        id: 'unverified',
        value: 'Unverified',
      },

      //
      {
        id: 'thumbnail',
        value: 'Thumbnail',
      },

      //
      {
        id: 'language',
        value: 'Language',
      },

      //
      {
        id: 'take_screenshot',
        value: 'Take Screenshot',
      },
      {
        id: 'enable_capture_mode',
        value: 'Enable Capture Mode',
      },
      {
        id: 'disable_capture_mode',
        value: 'Disable Capture Mode',
      },
      //#endregion

      //
      //#region File Types ...
      {
        id: 'audio',
        value: 'Audio',
      },
      {
        id: 'video',
        value: 'Video',
      },
      {
        id: 'document',
        value: 'Document',
      },
      {
        id: 'cover_image',
        value: 'Cover Image',
      },
      {
        id: 'image',
        value: 'Image',
      },
      {
        id: 'avatar',
        value: 'Avatar',
      },
      {
        id: 'unknown',
        value: 'Unknown',
      },
      {
        id: 'location',
        value: 'Location',
      },
      //#endregion

      //
      //#region Messages ...
      {
        id: 'are_you_sure',
        value: 'Are You Sure ?',
      },
      {
        id: 'success_msg',
        value: 'Operation done Successfully ...',
      },
      {
        id: 'locked_msg',
        value: 'You have to finish/cancel current proccess for leaving',
      },
      {
        id: 'empty_content',
        value: 'Empty',
      },
      {
        id: 'no_item',
        value: 'there is no Content',
      },
      {
        id: 'drag_drop_here',
        value: 'Drop File Here',
      },
      //#endregion

      //
      //#region Components ...
      {
        id: 'map_dialog_title',
        value: 'Show Location',
      },
      {
        id: 'map_dialog_select_title',
        value: 'Select Location',
      },
      {
        id: 'color_picker_dialog_title',
        value: 'Select Color',
      },
      //#endregion

      //
      //#region Verbs ...
      {
        id: 'dismiss',
        value: 'dismiss',
      },
      {
        id: 'accept',
        value: 'Accept',
      },
      {
        id: 'ok',
        value: 'Ok',
      },
      {
        id: 'save',
        value: 'Save',
      },
      {
        id: 'cancel',
        value: 'Cancel',
      },
      {
        id: 'retry',
        value: 'Retry',
      },
      {
        id: 'edit',
        value: 'Edit',
      },
      {
        id: 'reset',
        value: 'Reset',
      },
      {
        id: 'change',
        value: 'Change',
      },
      {
        id: 'start',
        value: 'Start',
      },
      {
        id: 'yes',
        value: 'Yes',
      },
      {
        id: 'no',
        value: 'No',
      },
      {
        id: 'verify',
        value: 'Verify',
      },
      {
        id: 'confirm',
        value: 'Confirm',
      },
      {
        id: 'crop',
        value: 'Crop',
      },
      {
        id: 'clear',
        value: 'Clear',
      },
      //
      {
        id: 'set',
        value: 'Set',
      },
      {
        id: 'select',
        value: 'Select',
      },
      {
        id: 'send',
        value: 'Send',
      },
      {
        id: 'show',
        value: 'Show',
      },
      {
        id: 'hide',
        value: 'Hide',
      },
      {
        id: 'search',
        value: 'Search',
      },
      {
        id: 'delete',
        value: 'Delete',
      },
      {
        id: 'clone',
        value: 'Clone',
      },
      {
        id: 'select_all',
        value: 'Select All',
      },
      {
        id: 'select_file',
        value: 'Select File(s)',
      },
      {
        id: 'select_all_group',
        value: 'Select All Filtered Items',
      },
      {
        id: 'deselect_all',
        value: 'Deselect All',
      },
      {
        id: 'deselect_all_group',
        value: 'Deselect All Filtered Items',
      },
      {
        id: 'inverse_selection',
        value: 'Inverse Selection',
      },
      //
      {
        id: 'selected_location',
        value: 'Selected Location',
      },
      {
        id: 'preset_colors',
        value: 'Preset Colors',
      },
      {
        id: 'copy_to_clipboard',
        value: 'Copy to Clipboard',
      },
      {
        id: 'color',
        value: 'Color',
      },
      {
        id: 'colors',
        value: 'Colors',
      },
      //
      {
        id: 'upload',
        value: 'Upload',
      },
      {
        id: 'import',
        value: 'Import',
      },
      {
        id: 'continue',
        value: 'Continue',
      },
      {
        id: 'finish',
        value: 'Finish',
      },
      {
        id: 'enable',
        value: 'Enable',
      },
      {
        id: 'disable',
        value: 'Disable',
      },
      {
        id: 'all',
        value: 'All',
      },
      {
        id: 'new',
        value: 'New',
      },
      {
        id: 'add',
        value: 'Add',
      },
      {
        id: 'update',
        value: 'Update',
      },
      {
        id: 'details',
        value: 'Details',
      },
      {
        id: 'translation',
        value: 'Translation',
      },
      {
        id: 'download',
        value: 'Download',
      },
      {
        id: 'list',
        value: 'List',
      },
      {
        id: 'options',
        value: 'Options',
      },
      {
        id: 'descriptions',
        value: 'Description',
      },

      //
      {
        id: 'type',
        value: 'Type',
      },
      //
      {
        id: 'media',
        value: 'Media',
      },
      {
        id: 'medias',
        value: 'Medias',
      },

      //
      {
        id: 'go',
        value: 'Go',
      },
      {
        id: 'input',
        value: 'Input',
      },
      {
        id: 'preview',
        value: 'Preview',
      },
      //#endregion

      //
      //#region Pagination ...
      {
        id: 'first',
        value: 'First',
      },
      {
        id: 'last',
        value: 'Last',
      },
      {
        id: 'previous',
        value: 'Previous',
      },
      {
        id: 'next',
        value: 'Next',
      },
      {
        id: 'back',
        value: 'Back',
      },
      //#endregion

      //
      //#region Markdown ...
      {
        id: 'x_markdown_preview',
        value: 'Preview',
      },
      {
        id: 'x_markdown_image',
        value: 'Image',
      },
      {
        id: 'x_markdown_link',
        value: 'Link',
      },
      {
        id: 'x_markdown_ol',
        value: 'Ordered List',
      },
      {
        id: 'x_markdown_ul',
        value: 'Unordered List',
      },
      {
        id: 'x_markdown_quote',
        value: 'Quote',
      },
      {
        id: 'x_markdown_code',
        value: 'Code',
      },
      {
        id: 'x_markdown_heading',
        value: 'Heading',
      },
      {
        id: 'x_markdown_italic',
        value: 'Italic',
      },
      {
        id: 'x_markdown_bold',
        value: 'Bold',
      },
      {
        id: 'x_markdown_guide',
        value: 'Markdown Guide',
      },
      //#endregion

      //
      //#region Theme Related ...
      //
      {
        id: 'theme',
        value: 'Theme',
      },
      {
        id: 'theme_mode',
        value: 'Theme Mode',
      },
      //
      {
        id: 'theme_dark',
        value: 'Dark',
      },
      {
        id: 'theme_light',
        value: 'Light',
      },
      //
      {
        id: 'theme_name',
        value: 'Theme Name',
      },
      {
        id: 'theme_name_description',
        value: 'Enter Theme name',
      },
      //
      {
        id: 'theme_clone_title',
        value: 'Theme Cloning',
      },
      //#endregion

      //
      //#region Color Picker Related ...
      {
        id: 'input_color_title',
        value: 'Color Value',
      },
      {
        id: 'input_color_description',
        value: 'input color value',
      },
      //#endregion

      //
      // Custom Translations ...
      ...EnCustomLocales,

      //
      // Persian Translated Exceptions ...
      ...XEnUSExceptions,
    ],
  },
];

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\config\page.config.ts

import {
  XIconNames,
  XTabNavigatorItem,
  XNavigatorListItem,
  toTabNavigatiorItem,
  toNavigatiorListItem,
} from 'x-framework-components';
import { XPage } from 'x-framework-core';
import { AppResourceIDs } from './app.localization.config';

//
//#region Route Config ...
export enum BaseRoutes {
  Default = '',
  Unknown = '**',
}

export enum HomeRoutes {
  Default = 'home',
  Home = 'home',
  Introduction = 'introduction',
}

export enum CoreRoutes {
  Default = 'core',
  Core = 'core',
  Introduction = 'introduction',
}

export enum ServicesRoutes {
  Default = 'services',
  Services = 'services',
  Introduction = 'introduction',
  UserDevice = 'user_device',
}

export enum ComponentsRoutes {
  Default = 'components',
  Components = 'components',
  Introduction = 'introduction',
  SmallComponents = 'small-components',
  Card = 'card',
  Icon = 'icon',
  Counter = 'counter',
  ColorPicker = 'color-picker',
  Fab = 'fab',
  FileComponents = 'file-components',
  Form = 'form',
  Grid = 'grid',
  List = 'list',
  Map = 'map',
  MarkDown = 'markdown',
  Tree = 'tree',
  DescriptionList = 'description-list',
  ExpandableList = 'expandable-list',
  ExpandablePanel = 'expandable-panel',
  ModelPresenter = 'model-presenter',
  Slider = 'slider',
  Stepper = 'stepper',
  Tabs = 'tabs',
  Table = 'table',
  Page = 'page',
  TabNavigator = 'tab-navigator',
}

export enum TabsRoutes {
  Default = 'tabs',
  Tabs = 'tabs',
  TabPage1 = 'tab-page-1',
  TabPage2 = 'tab-page-2',
  TabPage3 = 'tab-page-3',
}

export enum ThemesRoutes {
  Default = 'themes',
  Themes = 'themes',
  ThemeManager = 'manager',
}

export enum AppRoutes {
  Default = BaseRoutes.Default,
  Home = HomeRoutes.Default,
  Core = CoreRoutes.Default,
  Services = ServicesRoutes.Default,
  Components = ComponentsRoutes.Default,
  TabsNav = TabsRoutes.Default,
  Themes = ThemesRoutes.Default,
  Unknown = BaseRoutes.Unknown,
}
//#endregion

//
//#region Page Configs ...
export enum PageName {
  //
  // Home ...
  Home = AppRoutes.Home,
  HomeIntoduction = HomeRoutes.Introduction,

  //
  // Core ...
  Core = AppRoutes.Core,
  CoreIntoduction = CoreRoutes.Introduction,

  //
  // Services ...
  Services = AppRoutes.Services,
  ServicesIntoduction = ServicesRoutes.Introduction,
  UserDevice = ServicesRoutes.UserDevice,

  //
  // Components ...
  Components = AppRoutes.Components,
  ComponentsIntoduction = ComponentsRoutes.Introduction,
  SmallComponents = ComponentsRoutes.SmallComponents,
  Card = ComponentsRoutes.Card,
  Icon = ComponentsRoutes.Icon,
  Counter = ComponentsRoutes.Counter,
  ColorPicker = ComponentsRoutes.ColorPicker,
  Fab = ComponentsRoutes.Fab,
  FileComponents = ComponentsRoutes.FileComponents,
  Form = ComponentsRoutes.Form,
  Grid = ComponentsRoutes.Grid,
  List = ComponentsRoutes.List,
  Map = ComponentsRoutes.Map,
  MarkDown = ComponentsRoutes.MarkDown,
  Tree = ComponentsRoutes.Tree,
  DescriptionList = ComponentsRoutes.DescriptionList,
  ExpandableList = ComponentsRoutes.ExpandableList,
  ExpandablePanel = ComponentsRoutes.ExpandablePanel,
  ModelPresenter = ComponentsRoutes.ModelPresenter,
  Slider = ComponentsRoutes.Slider,
  Stepper = ComponentsRoutes.Stepper,
  Tabs = ComponentsRoutes.Tabs,
  Table = ComponentsRoutes.Table,
  Page = ComponentsRoutes.Page,
  TabNavigator = ComponentsRoutes.TabNavigator,

  //
  // Tabs Navigation ...
  TabsNav = AppRoutes.TabsNav,
  TabPage1 = TabsRoutes.TabPage1,
  TabPage2 = TabsRoutes.TabPage2,
  TabPage3 = TabsRoutes.TabPage3,

  //
  // Themes ...
  Themes = AppRoutes.Themes,
  ThemeManager = ThemesRoutes.ThemeManager,
}

export type PageNames = keyof typeof PageName;

export type PageNameIdentifier = PageName | PageNames | string;

export type PageIndexType = {
  [key in PageNames]?: XPage;
};

export const PageIndex: PageIndexType = {
  //
  Home: {
    icon: XIconNames.home,
    id: `${PageName.Home}`,
    name: `${PageName.Home}`,
    title: AppResourceIDs.home,
    baseRoute: `${AppRoutes.Home}`,
    route: ['/', `${AppRoutes.Home}`],
    description: AppResourceIDs.home_description,
    childs: [
      //
      // Intoduction ...
      {
        icon: XIconNames.guide,
        id: `${PageName.HomeIntoduction}`,
        name: `${PageName.HomeIntoduction}`,
        title: AppResourceIDs.home_introduction,
        baseRoute: `${HomeRoutes.Introduction}`,
        description: AppResourceIDs.home_introduction_description,
        route: ['/', `${AppRoutes.Home}`, `${HomeRoutes.Introduction}`],
      },
    ],
  },

  //
  Core: {
    icon: XIconNames.event,
    id: `${PageName.Core}`,
    name: `${PageName.Core}`,
    title: AppResourceIDs.core,
    baseRoute: `${AppRoutes.Core}`,
    route: ['/', `${AppRoutes.Core}`],
    description: AppResourceIDs.core_description,
    childs: [
      //
      // Intoduction ...
      {
        icon: XIconNames.guide,
        id: `${PageName.CoreIntoduction}`,
        name: `${PageName.CoreIntoduction}`,
        title: AppResourceIDs.core_introduction,
        baseRoute: `${CoreRoutes.Introduction}`,
        description: AppResourceIDs.core_introduction_description,
        route: ['/', `${AppRoutes.Core}`, `${CoreRoutes.Introduction}`],
      },
    ],
  },

  //
  Services: {
    icon: XIconNames.job,
    id: `${PageName.Services}`,
    name: `${PageName.Services}`,
    title: AppResourceIDs.services,
    baseRoute: `${AppRoutes.Services}`,
    route: ['/', `${AppRoutes.Services}`],
    description: AppResourceIDs.services_description,
    childs: [
      //
      // Intoduction ...
      {
        icon: XIconNames.guide,
        id: `${PageName.ServicesIntoduction}`,
        name: `${PageName.ServicesIntoduction}`,
        title: AppResourceIDs.services_introduction,
        baseRoute: `${ServicesRoutes.Introduction}`,
        description: AppResourceIDs.services_introduction_description,
        route: ['/', `${AppRoutes.Services}`, `${ServicesRoutes.Introduction}`],
      },
      //
      // UserDevice ...
      {
        icon: XIconNames.guide,
        id: `${PageName.UserDevice}`,
        name: `${PageName.UserDevice}`,
        title: AppResourceIDs.user_device,
        baseRoute: `${ServicesRoutes.UserDevice}`,
        description: AppResourceIDs.user_device_description,
        route: ['/', `${AppRoutes.Services}`, `${ServicesRoutes.UserDevice}`],
      },
    ],
  },

  //
  Components: {
    icon: XIconNames.explorer,
    id: `${PageName.Components}`,
    name: `${PageName.Components}`,
    title: AppResourceIDs.components,
    baseRoute: `${AppRoutes.Components}`,
    route: ['/', `${AppRoutes.Components}`],
    description: AppResourceIDs.components_description,
    childs: [
      //
      // Intoduction ...
      {
        icon: XIconNames.guide,
        id: `${PageName.ComponentsIntoduction}`,
        name: `${PageName.ComponentsIntoduction}`,
        title: AppResourceIDs.components_introduction,
        baseRoute: `${ComponentsRoutes.Introduction}`,
        description: AppResourceIDs.components_introduction_description,
        route: [
          '/',
          `${AppRoutes.Components}`,
          `${ComponentsRoutes.Introduction}`,
        ],
      },
      //
      // SmallComponents ...
      {
        icon: XIconNames.list,
        id: `${PageName.SmallComponents}`,
        name: `${PageName.SmallComponents}`,
        title: AppResourceIDs.small_components,
        baseRoute: `${ComponentsRoutes.SmallComponents}`,
        description: AppResourceIDs.small_components_description,
        route: [
          '/',
          `${AppRoutes.Components}`,
          `${ComponentsRoutes.SmallComponents}`,
        ],
      },
      //
      // Card ...
      {
        icon: XIconNames.list,
        id: `${PageName.Card}`,
        name: `${PageName.Card}`,
        title: AppResourceIDs.card,
        baseRoute: `${ComponentsRoutes.Card}`,
        description: AppResourceIDs.card_description,
        route: ['/', `${AppRoutes.Components}`, `${ComponentsRoutes.Card}`],
      },
      //
      // Icon ...
      {
        icon: XIconNames.list,
        id: `${PageName.Icon}`,
        name: `${PageName.Icon}`,
        title: AppResourceIDs.icon,
        baseRoute: `${ComponentsRoutes.Icon}`,
        description: AppResourceIDs.icon_description,
        route: ['/', `${AppRoutes.Components}`, `${ComponentsRoutes.Icon}`],
      },
      //
      // Counter ...
      {
        icon: XIconNames.list,
        id: `${PageName.Counter}`,
        name: `${PageName.Counter}`,
        title: AppResourceIDs.counter,
        baseRoute: `${ComponentsRoutes.Counter}`,
        description: AppResourceIDs.counter_description,
        route: ['/', `${AppRoutes.Components}`, `${ComponentsRoutes.Counter}`],
      },
      //
      // ColorPicker ...
      {
        icon: XIconNames.list,
        id: `${PageName.ColorPicker}`,
        name: `${PageName.ColorPicker}`,
        title: AppResourceIDs.color_picker,
        baseRoute: `${ComponentsRoutes.ColorPicker}`,
        description: AppResourceIDs.color_picker_description,
        route: [
          '/',
          `${AppRoutes.Components}`,
          `${ComponentsRoutes.ColorPicker}`,
        ],
      },
      //
      // Fab ...
      {
        id: `${PageName.Fab}`,
        icon: XIconNames.list,
        name: `${PageName.Fab}`,
        title: AppResourceIDs.fab,
        baseRoute: `${ComponentsRoutes.Fab}`,
        description: AppResourceIDs.fab_description,
        route: ['/', `${AppRoutes.Components}`, `${ComponentsRoutes.Fab}`],
      },
      //
      // FileComponents ...
      {
        icon: XIconNames.list,
        id: `${PageName.FileComponents}`,
        name: `${PageName.FileComponents}`,
        title: AppResourceIDs.file_components,
        baseRoute: `${ComponentsRoutes.FileComponents}`,
        description: AppResourceIDs.file_components_description,
        route: [
          '/',
          `${AppRoutes.Components}`,
          `${ComponentsRoutes.FileComponents}`,
        ],
      },
      //
      // Form ...
      {
        icon: XIconNames.list,
        id: `${PageName.Form}`,
        name: `${PageName.Form}`,
        title: AppResourceIDs.form,
        baseRoute: `${ComponentsRoutes.Form}`,
        description: AppResourceIDs.form_description,
        route: ['/', `${AppRoutes.Components}`, `${ComponentsRoutes.Form}`],
      },
      //
      // Grid ...
      {
        icon: XIconNames.list,
        id: `${PageName.Grid}`,
        name: `${PageName.Grid}`,
        title: AppResourceIDs.grid,
        baseRoute: `${ComponentsRoutes.Grid}`,
        description: AppResourceIDs.grid_description,
        route: ['/', `${AppRoutes.Components}`, `${ComponentsRoutes.Grid}`],
      },
      //
      // List ...
      {
        icon: XIconNames.list,
        id: `${PageName.List}`,
        name: `${PageName.List}`,
        title: AppResourceIDs.list,
        baseRoute: `${ComponentsRoutes.List}`,
        description: AppResourceIDs.list_description,
        route: ['/', `${AppRoutes.Components}`, `${ComponentsRoutes.List}`],
      },
      //
      // Map ...
      {
        icon: XIconNames.list,
        id: `${PageName.Map}`,
        name: `${PageName.Map}`,
        title: AppResourceIDs.map,
        baseRoute: `${ComponentsRoutes.Map}`,
        description: AppResourceIDs.map_description,
        route: ['/', `${AppRoutes.Components}`, `${ComponentsRoutes.Map}`],
      },
      //
      // MarkDown ...
      {
        icon: XIconNames.list,
        id: `${PageName.MarkDown}`,
        name: `${PageName.MarkDown}`,
        title: AppResourceIDs.markdown,
        baseRoute: `${ComponentsRoutes.MarkDown}`,
        description: AppResourceIDs.markdown_description,
        route: ['/', `${AppRoutes.Components}`, `${ComponentsRoutes.MarkDown}`],
      },
      //
      // Tree ...
      // TODO: Complete this ...
      {
        icon: XIconNames.ul,
        id: `${PageName.Tree}`,
        name: `${PageName.Tree}`,
        title: AppResourceIDs.tree,
        baseRoute: `${ComponentsRoutes.Tree}`,
        description: AppResourceIDs.tree_description,
        route: ['/', `${AppRoutes.Components}`, `${ComponentsRoutes.Tree}`],
      },
      //
      // DescriptionList ...
      {
        icon: XIconNames.list,
        id: `${PageName.DescriptionList}`,
        name: `${PageName.DescriptionList}`,
        title: AppResourceIDs.description_list,
        baseRoute: `${ComponentsRoutes.DescriptionList}`,
        description: AppResourceIDs.description_list_description,
        route: [
          '/',
          `${AppRoutes.Components}`,
          `${ComponentsRoutes.DescriptionList}`,
        ],
      },
      //
      // ExpandableList ...
      {
        icon: XIconNames.list,
        id: `${PageName.ExpandableList}`,
        name: `${PageName.ExpandableList}`,
        title: AppResourceIDs.expandable_list,
        baseRoute: `${ComponentsRoutes.ExpandableList}`,
        description: AppResourceIDs.expandable_list_description,
        route: [
          '/',
          `${AppRoutes.Components}`,
          `${ComponentsRoutes.ExpandableList}`,
        ],
      },
      //
      // ExpandablePanel ...
      {
        icon: XIconNames.list,
        id: `${PageName.ExpandablePanel}`,
        name: `${PageName.ExpandablePanel}`,
        title: AppResourceIDs.expandable_panel,
        baseRoute: `${ComponentsRoutes.ExpandablePanel}`,
        description: AppResourceIDs.expandable_panel_description,
        route: [
          '/',
          `${AppRoutes.Components}`,
          `${ComponentsRoutes.ExpandablePanel}`,
        ],
      },
      //
      // ModelPresenter ...
      {
        icon: XIconNames.list,
        id: `${PageName.ModelPresenter}`,
        name: `${PageName.ModelPresenter}`,
        title: AppResourceIDs.model_presenter,
        baseRoute: `${ComponentsRoutes.ModelPresenter}`,
        description: AppResourceIDs.model_presenter_description,
        route: [
          '/',
          `${AppRoutes.Components}`,
          `${ComponentsRoutes.ModelPresenter}`,
        ],
      },
      //
      // Slider ...
      {
        icon: XIconNames.list,
        id: `${PageName.Slider}`,
        name: `${PageName.Slider}`,
        title: AppResourceIDs.slider,
        baseRoute: `${ComponentsRoutes.Slider}`,
        description: AppResourceIDs.slider_description,
        route: ['/', `${AppRoutes.Components}`, `${ComponentsRoutes.Slider}`],
      },
      //
      // Stepper ...
      {
        icon: XIconNames.list,
        id: `${PageName.Stepper}`,
        name: `${PageName.Stepper}`,
        title: AppResourceIDs.stepper,
        baseRoute: `${ComponentsRoutes.Stepper}`,
        description: AppResourceIDs.stepper_description,
        route: ['/', `${AppRoutes.Components}`, `${ComponentsRoutes.Stepper}`],
      },
      //
      // Tabs ...
      {
        icon: XIconNames.list,
        id: `${PageName.Tabs}`,
        name: `${PageName.Tabs}`,
        title: AppResourceIDs.tabs,
        baseRoute: `${ComponentsRoutes.Tabs}`,
        description: AppResourceIDs.tabs_description,
        route: ['/', `${AppRoutes.Components}`, `${ComponentsRoutes.Tabs}`],
      },
      //
      // Table ...
      {
        icon: XIconNames.list,
        id: `${PageName.Table}`,
        name: `${PageName.Table}`,
        title: AppResourceIDs.table,
        baseRoute: `${ComponentsRoutes.Table}`,
        description: AppResourceIDs.tabs_description,
        route: ['/', `${AppRoutes.Components}`, `${ComponentsRoutes.Table}`],
      },
      //
      // Page ...
      {
        icon: XIconNames.list,
        id: `${PageName.Page}`,
        name: `${PageName.Page}`,
        title: AppResourceIDs.page,
        baseRoute: `${ComponentsRoutes.Page}`,
        description: AppResourceIDs.page_description,
        route: ['/', `${AppRoutes.Components}`, `${ComponentsRoutes.Page}`],
      },
      //
      // TabNavigator ...
      {
        icon: XIconNames.list,
        id: `${PageName.TabNavigator}`,
        name: `${PageName.TabNavigator}`,
        title: AppResourceIDs.tab_navigator,
        baseRoute: `${ComponentsRoutes.TabNavigator}`,
        description: AppResourceIDs.tab_navigator_description,
        route: [
          '/',
          `${AppRoutes.Components}`,
          `${ComponentsRoutes.TabNavigator}`,
        ],
      },
    ],
  },

  //
  TabsNav: {
    icon: XIconNames.list,
    id: `${PageName.TabsNav}`,
    name: `${PageName.TabsNav}`,
    title: AppResourceIDs.tab_navigator,
    baseRoute: `${AppRoutes.TabsNav}`,
    route: ['/', `${AppRoutes.TabsNav}`],
    description: AppResourceIDs.tab_navigator_description,
    childs: [
      //
      // TabPage 1 ...
      {
        icon: XIconNames.list,
        id: `${PageName.TabPage1}`,
        name: `${PageName.TabPage1}`,
        title: AppResourceIDs.tab_page_1,
        baseRoute: `${TabsRoutes.TabPage1}`,
        description: AppResourceIDs.tab_navigator_description,
        route: ['/', `${AppRoutes.TabsNav}`, `${TabsRoutes.TabPage1}`],
      },
      //
      // TabPage 2 ...
      {
        icon: XIconNames.list,
        id: `${PageName.TabPage2}`,
        name: `${PageName.TabPage2}`,
        title: AppResourceIDs.tab_page_2,
        baseRoute: `${TabsRoutes.TabPage2}`,
        description: AppResourceIDs.tab_navigator_description,
        route: ['/', `${AppRoutes.TabsNav}`, `${TabsRoutes.TabPage2}`],
      },
      //
      // TabPage 3 ...
      {
        icon: XIconNames.list,
        id: `${PageName.TabPage3}`,
        name: `${PageName.TabPage3}`,
        title: AppResourceIDs.tab_page_3,
        baseRoute: `${TabsRoutes.TabPage3}`,
        description: AppResourceIDs.tab_navigator_description,
        route: ['/', `${AppRoutes.TabsNav}`, `${TabsRoutes.TabPage3}`],
      },
    ],
  },

  //
  Themes: {
    icon: XIconNames.color_palette,
    id: `${PageName.Themes}`,
    name: `${PageName.Themes}`,
    title: AppResourceIDs.themes,
    baseRoute: `${AppRoutes.Themes}`,
    route: ['/', `${AppRoutes.Themes}`],
    description: AppResourceIDs.themes_description,
    childs: [
      //
      // ThemeManager ...
      {
        icon: XIconNames.color_palette,
        id: `${PageName.ThemeManager}`,
        name: `${PageName.ThemeManager}`,
        title: AppResourceIDs.theme_manager,
        baseRoute: `${ThemesRoutes.ThemeManager}`,
        description: AppResourceIDs.theme_manager_description,
        route: ['/', `${AppRoutes.Themes}`, `${ThemesRoutes.ThemeManager}`],
      },
    ],
  },
};

//
// a Const of Available Pages ...
export const Pages = {
  //
  Home: PageIndex.Home,
  HomeIntroduction: PageIndex.Home.childs[0],

  //
  Core: PageIndex.Core,
  CoreIntroduction: PageIndex.Core.childs[0],

  //
  Services: PageIndex.Services,
  ServicesIntroduction: PageIndex.Services.childs[0],

  //
  Components: PageIndex.Components,
  ComponentsIntroduction: PageIndex.Components.childs[0],
  SmallComponents: PageIndex.Components.childs[1],
  Card: PageIndex.Components.childs[2],
  Icon: PageIndex.Components.childs[3],
  Counter: PageIndex.Components.childs[4],
  ColorPicker: PageIndex.Components.childs[5],
  Fab: PageIndex.Components.childs[6],
  FileUpload: PageIndex.Components.childs[7],
  Form: PageIndex.Components.childs[8],
  Grid: PageIndex.Components.childs[9],
  List: PageIndex.Components.childs[10],
  Map: PageIndex.Components.childs[11],
  MarkDown: PageIndex.Components.childs[12],
  Tree: PageIndex.Components.childs[13],
  DescriptionList: PageIndex.Components.childs[14],
  ExpandableList: PageIndex.Components.childs[15],
  ExpandablePanel: PageIndex.Components.childs[16],
  Slider: PageIndex.Components.childs[17],
  Stepper: PageIndex.Components.childs[18],
  Tabs: PageIndex.Components.childs[19],
  Table: PageIndex.Components.childs[20],
  Page: PageIndex.Components.childs[21],
  TabNavigator: PageIndex.Components.childs[22],

  //
  TabsNav: PageIndex.TabsNav,
  TabPage1: PageIndex.TabsNav.childs[0],
  TabPage2: PageIndex.TabsNav.childs[1],
  TabPage3: PageIndex.TabsNav.childs[2],

  //
  Themes: PageIndex.Themes,
  ThemeManager: PageIndex.Themes.childs[0],
};

//
// Admin Navigator Pages ...
export const NavPageItems: XNavigatorListItem[] = [
  //
  //#region Home ...
  {
    ...toNavigatiorListItem(PageIndex.Home),
  },
  //#endregion

  //
  //#region Core ...
  {
    ...toNavigatiorListItem(PageIndex.Core),
  },
  //#endregion

  //
  //#region Services ...
  {
    ...toNavigatiorListItem(PageIndex.Services),
  },
  //#endregion

  //
  //#region Components ...
  {
    ...toNavigatiorListItem(PageIndex.Components),
  },
  //#endregion
];

//
// Tabs Navigators Pages ...
export const TabNavsItems: XTabNavigatorItem[] = [
  {
    ...toTabNavigatiorItem(Pages.TabPage1),
  },
  {
    ...toTabNavigatiorItem(Pages.TabPage2),
  },
  {
    ...toTabNavigatiorItem(Pages.TabPage3),
  },
];
//#endregion

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\config\x-config.ts

import { XConfig } from './app-config';
import { environment } from '../../environments/environment';
import { InjectionToken } from '@angular/core';

export const XCONFIG: XConfig = JSON.parse(
  JSON.stringify(environment.configurations)
);

export const X_CONFIG = new InjectionToken<XConfig>('x_config');

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\components.module.ts

import { NgModule } from '@angular/core';
import { FabPage } from './fab/fab.page';
import { MapPage } from './map/map.page';
import { FormPage } from './form/form.page';
import { GridPage } from './grid/grid.page';
import { ListPage } from './list/list.page';
import { IconPage } from './icon/icon.page';
import { CardPage } from './card/card.page';
import { PagePage } from './page/page.page';
import { TabsPage } from './tabs/tabs.page';
import { RouterModule } from '@angular/router';
import { CommonModule } from '@angular/common';
import { TablePage } from './table/table.page';
import { SliderPage } from './slider/slider.page';
import { CounterPage } from './counter/counter.page';
import { StepperPage } from './stepper/stepper.page';
import { MarkdownPage } from './markdown/markdown.page';
import { ViewsModule } from 'src/app/views/views.module';
import { ColorPickerPage } from './color-picker/color-picker.page';
import { IntroductionPage } from './introduction/introduction.page';
import { TabNavigatorPage } from './tab-navigator/tab-navigator.page';
import { BaseRoutes, ComponentsRoutes } from 'src/app/config/page.config';
import { FileComponentsPage } from './file-components/file-components.page';
import { ExpandableListPage } from './expandable-list/expandable-list.page';
import { ModelPresenterPage } from './model-presenter/model-presenter.page';
import { DescriptionListPage } from './description-list/description-list.page';
import { SmallComponentsPage } from './small-components/small-components.page';
import { ExpandablePanelPage } from './expandable-panel/expandable-panel.page';
import { SampleModalComponent } from './small-components/sample-modal/sample-modal.component';
import { TreePage } from './tree/tree.page';

@NgModule({
  imports: [
    ViewsModule,
    CommonModule,
    RouterModule.forChild([
      {
        path: BaseRoutes.Default,
        redirectTo: ComponentsRoutes.Introduction,
        pathMatch: 'full',
      },
      {
        path: ComponentsRoutes.Introduction,
        component: IntroductionPage,
      },
      {
        path: ComponentsRoutes.SmallComponents,
        component: SmallComponentsPage,
      },
      {
        path: ComponentsRoutes.Card,
        component: CardPage,
      },
      {
        path: ComponentsRoutes.Icon,
        component: IconPage,
      },
      {
        path: ComponentsRoutes.Counter,
        component: CounterPage,
      },
      {
        path: ComponentsRoutes.ColorPicker,
        component: ColorPickerPage,
      },
      {
        path: ComponentsRoutes.Fab,
        component: FabPage,
      },
      {
        path: ComponentsRoutes.FileComponents,
        component: FileComponentsPage,
      },
      {
        path: ComponentsRoutes.Form,
        component: FormPage,
      },
      {
        path: ComponentsRoutes.Grid,
        component: GridPage,
      },
      {
        path: ComponentsRoutes.List,
        component: ListPage,
      },
      {
        path: ComponentsRoutes.Map,
        component: MapPage,
      },
      {
        path: ComponentsRoutes.MarkDown,
        component: MarkdownPage,
      },
      {
        path: ComponentsRoutes.Tree,
        component: TreePage,
      },
      {
        path: ComponentsRoutes.DescriptionList,
        component: DescriptionListPage,
      },
      {
        path: ComponentsRoutes.ExpandableList,
        component: ExpandableListPage,
      },
      {
        path: ComponentsRoutes.ExpandablePanel,
        component: ExpandablePanelPage,
      },
      {
        path: ComponentsRoutes.ModelPresenter,
        component: ModelPresenterPage,
      },
      {
        path: ComponentsRoutes.Slider,
        component: SliderPage,
      },
      {
        path: ComponentsRoutes.Stepper,
        component: StepperPage,
      },
      {
        path: ComponentsRoutes.Tabs,
        component: TabsPage,
      },
      {
        path: ComponentsRoutes.Table,
        component: TablePage,
      },
      {
        path: ComponentsRoutes.Page,
        component: PagePage,
      },
      {
        path: ComponentsRoutes.TabNavigator,
        component: TabNavigatorPage,
      },
    ]),
  ],
  declarations: [
    FabPage,
    MapPage,
    CardPage,
    IconPage,
    FormPage,
    GridPage,
    PagePage,
    ListPage,
    TabsPage,
    TreePage,
    TablePage,
    SliderPage,
    StepperPage,
    CounterPage,
    MarkdownPage,
    ColorPickerPage,
    IntroductionPage,
    TabNavigatorPage,
    ExpandableListPage,
    FileComponentsPage,
    ModelPresenterPage,
    SmallComponentsPage,
    ExpandablePanelPage,
    DescriptionListPage,

    //
    SampleModalComponent,
  ],
  entryComponents: [SampleModalComponent],
})
export class ComponentsPageModule {}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\card\card.page.html

<v-page
  [hasSide]="true"
  [toolbarTitle]="toolbarTitle"
  [toolbarSubTitle]="toolbarSubTitle"
  [toolbarShowSubTitle]="toolbarShowSubTitle"
>
  <!-- Content -->
  <x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
    <!-- Content -->
    <x-markdown
      [mode]="'preview'"
      [hasToolbar]="false"
      [content]="getContent('content')"
    ></x-markdown>

    <!-- Actions -->
    <div actions>
      <a
        target="_blank"
        href="https://docs.x-framework.ir/x-framework-components/components/XCardComponent.html"
        >{{resourceProvider(ResourceIDs.documentation)}}</a
      >
    </div>
  </x-card>

  <!-- Sample -->
  <x-markdown
    [isInPage]="true"
    [mode]="'preview'"
    [content]="sample1"
    [hasToolbar]="false"
    [wrapWithCard]="true"
    [cssClass]="'code-block'"
    [cardTitle]="resourceProvider(ResourceIDs.sample)"
  ></x-markdown>

  <!-- Component -->
  <x-card
    [showHeader]="true"
    [isInPage]="true"
    [showFooter]="true"
    [showContent]="true"
    [showActions]="true"
    [color]="ColorNames.Tertiary"
    [title]="resourceProvider(ResourceIDs.app_name)"
    [subTitle]="resourceProvider(ResourceIDs.company)"
  >
    <div header>
      {{resourceProvider(ResourceIDs.header)}}
    </div>

    <div content>
      {{resourceProvider(ResourceIDs.temp_label)}}
    </div>

    <div actions>
      {{resourceProvider(ResourceIDs.actions)}}
    </div>

    <div footer>
      {{resourceProvider(ResourceIDs.footer)}}
    </div>
  </x-card>

  <x-markdown
    [mode]="'preview'"
    [content]="sample2"
    [hasToolbar]="false"
    [wrapWithCard]="true"
    [isInPage]="true"
    [cssClass]="'code-block'"
    [cardTitle]="resourceProvider(ResourceIDs.sample)"
  ></x-markdown>

  <x-card
    [showHeader]="true"
    [isInPage]="true"
    [showContent]="true"
    [color]="ColorNames.Medium"
    [imageUrl]="'/assets/image/logo.png'"
    [avatarUrl]="'/assets/image/logo.png'"
    [title]="resourceProvider(ResourceIDs.app_name)"
    [subTitle]="resourceProvider(ResourceIDs.company)"
  >
    <div content>
      {{resourceProvider(ResourceIDs.temp_label)}}
    </div>
  </x-card>
</v-page>

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\card\card.page.scss

.content-container {
  margin: 24px;
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\card\card.page.ts

import { Component } from '@angular/core';
import { VPageComponent } from '../../../views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';
import { XResourceIDs, XColor, isNullOrEmptyString } from 'x-framework-core';

@Component({
  selector: 'app-card',
  templateUrl: './card.page.html',
  styleUrls: ['./card.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class CardPage extends VPageComponent {
  //
  //#region Props ...
  //
  //#region Page Props ...
  titleRes = AppResourceIDs.card;
  toolbarTitle = this.resourceProvider(this.titleRes);
  toolbarSubTitle = this.resourceProvider(AppResourceIDs.card_description);
  toolbarShowSubTitle = true;
  //#endregion

  //
  // Prepare All Resource IDs ...
  readonly ResourceIDs = Object.assign(
    Object.assign({}, XResourceIDs),
    AppResourceIDs
  ) as any;
  //#endregion

  //
  // Content ...
  readonly contentFa = `
  # ${this.toolbarTitle}
این مولفه جهت نمایش یک جزء از اجزای تشکیل دهنده یک صفحه بکار میرود.

  این مولفه می تواند بسته به ابعاد مختلف صفحه واکنش نشان دهد و خود را مطابق کند.
  `;
  readonly contentEn = `
  # ${this.toolbarTitle}
this component use to present a part of a page.

  this component can adapt itself based on screen size.
  `;

  //
  readonly sample1 =
    '```html' +
    `
<x-card
  [showHeader]="true"
  [isPageCard]="true"
  [showFooter]="true"
  [showContent]="true"
  [showActions]="true"
  [color]="ColorNames.Tertiary"
  [title]="resourceProvider(
    ResourceIDs.app_name)"
  [subTitle]="resourceProvider(
    ResourceIDs.company)"
>
  <div header>
    {{resourceProvider(
      ResourceIDs.header)}}
  </div>

  <div content>
    {{resourceProvider(
      ResourceIDs.temp_label)}}
  </div>

  <div actions>
    {{resourceProvider(
      ResourceIDs.actions)}}
  </div>

  <div footer>
    {{resourceProvider(
      ResourceIDs.footer)}}
  </div>
</x-card>
` +
    '```';

  readonly sample2 =
    '```html' +
    `
  <x-card
    [showHeader]="true"
    [isPageCard]="true"
    [showContent]="true"
    [color]="ColorNames.Medium"
    [imageUrl]="
      \'/assets/image/logo.png\'"
    [avatarUrl]="
      \'/assets/image/logo.png\'"
    [title]="resourceProvider(
      ResourceIDs.app_name)"
    [subTitle]="resourceProvider(
      ResourceIDs.company)"
  >
    <div content>
      {{resourceProvider(
        ResourceIDs.temp_label)}}
    </div>
  </x-card>
  ` +
    '```';

  //
  // Provide content based on current locale ...
  getContent(title: string) {
    //
    if (isNullOrEmptyString(title)) {
      return '';
    }

    //
    const currentLocale = this.managerService.currentLocale;

    //
    const varName =
      title +
      (currentLocale === 'en-US'
        ? 'En'
        : currentLocale === 'fa-IR'
        ? 'Fa'
        : '');

    const result = this[`${varName}`];

    //
    return result || '';
  }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\color-picker\color-picker.page.html

<v-page
  [hasSide]="true"
  [toolbarTitle]="toolbarTitle"
  [toolbarSubTitle]="toolbarSubTitle"
  [toolbarShowSubTitle]="toolbarShowSubTitle"
>
  <!-- Content -->
  <x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
    <!-- Content -->
    <x-markdown
      [mode]="'preview'"
      [hasToolbar]="false"
      [content]="getContent('content')"
    ></x-markdown>

    <!-- Actions -->
    <div actions>
      <a
        target="_blank"
        href="https://docs.x-framework.ir/x-framework-components/components/XCounterComponent.html"
        >{{resourceProvider(ResourceIDs.documentation)}}</a
      >
    </div>
  </x-card>

  <!-- <x-markdown
    [isInPage]="true"
    [mode]="'preview'"
    [content]="sample1"
    [hasToolbar]="false"
    [wrapWithCard]="true"
    [cssClass]="'code-block'"
    [cardTitle]="resourceProvider(ResourceIDs.sample)"
  ></x-markdown> -->

  <!-- ColorPicker -->
  <x-color-picker
    [isInPage]="true"
    [wrapWithCard]="true"
    [selectedColor]="'#fff500'"
    [showCopyToClipboard]="true"
    [presetColors]="presetColors"
    [outputFormat]="outputFormat"
    [cursorColor]="'tertiary-tint'"
    [presetColorsLable]="presetColorsLable"
    [representColorFormats]="representFormats"
    (colorSelected)="handleColorSelected($event)"
  ></x-color-picker>
</v-page>

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\color-picker\color-picker.page.scss


### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\color-picker\color-picker.page.ts

import {
  XColorPickerOutputFormat,
  XColorPickerOutputFormatIdentifier,
} from 'x-framework-components';
import { Component } from '@angular/core';
import { VPageComponent } from '../../../views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';
import { XColor, XResourceIDs, isNullOrEmptyString } from 'x-framework-core';

@Component({
  selector: 'app-color-picker',
  templateUrl: './color-picker.page.html',
  styleUrls: ['./color-picker.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class ColorPickerPage extends VPageComponent {
  //
  //#region Props ...
  //
  //#region Page Props ...
  titleRes = AppResourceIDs.color_picker;
  toolbarTitle = this.resourceProvider(this.titleRes);
  toolbarSubTitle = this.resourceProvider(
    AppResourceIDs.color_picker_description
  );
  toolbarShowSubTitle = true;
  //#endregion

  //
  // Prepare All Resource IDs ...
  readonly ResourceIDs = Object.assign(
    Object.assign({}, XResourceIDs),
    AppResourceIDs
  ) as any;
  //#endregion

  //
  // Content ...
  readonly contentFa = `
  # ${this.toolbarTitle}
`;

  readonly contentEn = `
  # ${this.toolbarTitle}
`;

  //
  readonly sample1 =
    '```html' +
    `
` +
    '```';

  //
  readonly presetColorsLable = 'PresetColors';

  //
  readonly presetColors = [
    '#fff',
    '#000',
    '#2889e9',
    '#e920e9',
    '#fff500',
    'rgb(236,64,64)',
  ];

  readonly outputFormat = XColorPickerOutputFormat.XHEX;

  readonly representFormats: XColorPickerOutputFormatIdentifier[] = [
    XColorPickerOutputFormat.XHEX,
    XColorPickerOutputFormat.XRGBA,
    // XColorPickerOutputFormat.XHSLA,
  ];

  //
  //#region UI Providers ...
  //
  // Provide content based on current locale ...
  getContent(title: string) {
    //
    if (isNullOrEmptyString(title)) {
      return '';
    }

    //
    const currentLocale = this.managerService.currentLocale;

    //
    const varName =
      title +
      (currentLocale === 'en-US'
        ? 'En'
        : currentLocale === 'fa-IR'
        ? 'Fa'
        : '');

    const result = this[`${varName}`];

    //
    return result || '';
  }
  //#endregion

  handleColorSelected(color: string) {
    console.log('Color Selected From ColorPicker Component: ', color);
  }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\counter\counter.page.html

<v-page
  [hasSide]="true"
  [toolbarTitle]="toolbarTitle"
  [toolbarSubTitle]="toolbarSubTitle"
  [toolbarShowSubTitle]="toolbarShowSubTitle"
>
  <!-- Content -->
  <x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
    <!-- Content -->
    <x-markdown
      [mode]="'preview'"
      [hasToolbar]="false"
      [content]="getContent('content')"
    ></x-markdown>

    <!-- Actions -->
    <div actions>
      <a
        target="_blank"
        href="https://docs.x-framework.ir/x-framework-components/components/XCounterComponent.html"
        >{{resourceProvider(ResourceIDs.documentation)}}</a
      >
    </div>
  </x-card>

  <x-markdown
    [isInPage]="true"
    [mode]="'preview'"
    [content]="sample1"
    [hasToolbar]="false"
    [wrapWithCard]="true"
    [cssClass]="'code-block'"
    [cardTitle]="resourceProvider(ResourceIDs.sample)"
  ></x-markdown>

  <x-markdown
    [isInPage]="true"
    [mode]="'preview'"
    [content]="sample2"
    [hasToolbar]="false"
    [wrapWithCard]="true"
    [cssClass]="'code-block'"
  ></x-markdown>

  <x-markdown
    [isInPage]="true"
    [mode]="'preview'"
    [content]="sample3"
    [hasToolbar]="false"
    [wrapWithCard]="true"
    [cssClass]="'code-block'"
  ></x-markdown>

  <x-markdown
    [isInPage]="true"
    [mode]="'preview'"
    [content]="sample4"
    [hasToolbar]="false"
    [wrapWithCard]="true"
    [cssClass]="'code-block'"
  ></x-markdown>

  <!-- Counter -->
  <x-counter
    #counter
    [stopValue]="0"
    [isInPage]="true"
    [startValue]="180"
    [autoStart]="true"
    [currentValue]="150"
    [wrapWithCard]="true"
    [cardShowActions]="true"
    [cssClass]="'ion-text-center'"
    [type]="CounterTypes.CountDown"
    [displayPattern]="getCounterMessage"
    (counterStop)="handleCounterStop($event)"
    (counterTtick)="handleCounterTick($event)"
    (counterStart)="handleCounterStart($event)"
  >
    <div actions>
      <x-slotter [layout]="SlotLayout.HORIZONTAL">
        <x-slot [name]="SlotNames.START" [cssClass]="'ion-text-start'">
          <x-button
            (clicked)="counter.start()"
            [title]="ResourceIDs.start"
            [color]="ColorNames.Tertiary"
          ></x-button>
        </x-slot>

        <x-slot [name]="SlotNames.CENTER" [cssClass]="'ion-text-center'">
          <x-button
            (clicked)="counter.pause()"
            [title]="ResourceIDs.pause"
            [color]="ColorNames.Warning"
          ></x-button>
        </x-slot>

        <x-slot [name]="SlotNames.END" [cssClass]="'ion-text-end'">
          <x-button
            [title]="ResourceIDs.reset"
            [color]="ColorNames.Danger"
            (clicked)="counter.startValue = 180; counter.stopValue= 0; counter.currentValue = 0; counter.start()"
          ></x-button>
        </x-slot>
      </x-slotter>
    </div>
  </x-counter>
</v-page>

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\counter\counter.page.scss

.content-container {
  margin: 24px;
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\counter\counter.page.ts

import {
  XColor,
  toTimeFormat,
  XResourceIDs,
  toPersianNumbers,
  isNullOrEmptyString,
} from 'x-framework-core';
import {
  XSlotName,
  XSlotLayout,
  XCounterType,
  XCounterTick,
} from 'x-framework-components';
import { Component } from '@angular/core';
import { VPageComponent } from '../../../views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';

@Component({
  selector: 'app-counter',
  templateUrl: './counter.page.html',
  styleUrls: ['./counter.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class CounterPage extends VPageComponent {
  //
  //#region Props ...
  //
  //#region Page Props ...
  titleRes = AppResourceIDs.counter;
  toolbarTitle = this.resourceProvider(this.titleRes);
  toolbarSubTitle = this.resourceProvider(AppResourceIDs.counter_description);
  toolbarShowSubTitle = true;
  //#endregion

  //
  // Prepare All Resource IDs ...
  readonly ResourceIDs = Object.assign(
    Object.assign({}, XResourceIDs),
    AppResourceIDs
  ) as any;

  //
  // Counter Types ...
  readonly CounterTypes = Object.assign({}, XCounterType);

  //
  // Slotter ...
  readonly SlotNames = Object.assign({}, XSlotName);
  readonly SlotLayout = Object.assign({}, XSlotLayout);
  //#endregion

  //
  // Content ...
  readonly contentFa = `
  # ${this.toolbarTitle}

  این مولفه در مواردی که قصد داریم مدت زمان معینی را برای ادامه یا انجام کاری در نظر بگیریم مورد استفاده قرار می گیرد.
  `;
  readonly contentEn = `
  # ${this.toolbarTitle}
  this component used when we need to wait specific time for continue or doing an action.
  `;

  //
  readonly sample1 =
    '```html' +
    `
<x-counter
  #counter
  [stopValue]="0"
  [startValue]="180"
  [currentValue]="150"
  [type]="CounterTypes
    .CountDown"
  [displayPattern]="
    getCounterMessage"
  (counterStop)="
    handleCounterStop($event)"
  (counterTtick)="
    handleCounterTick($event)"
  (counterStart)="
    handleCounterStart($event)"
></x-counter>
` +
    '```';

  //
  readonly sample2 =
    '```html' +
    `
<x-button
  (click)="counter.start()"
  [title]="ResourceIDs.start"
  [color]="ColorNames.Tertiary"
></x-button>
` +
    '```';

  //
  readonly sample3 =
    '```html' +
    `
<x-button
  (click)="counter.pause()"
  [title]="ResourceIDs.pause"
  [color]="ColorNames.Warning"
></x-button>
` +
    '```';

  //
  readonly sample4 =
    '```html' +
    `
<x-button
  [title]="ResourceIDs.reset"
  [color]="ColorNames.Danger"
  (click)="
    counter.startValue = 180;
    counter.stopValue= 0;
    counter.currentValue = 0;
    counter.start()"
></x-button>
` +
    '```';

  //
  //#region UI Providers ...
  //
  // Provide content based on current locale ...
  getContent(title: string) {
    //
    if (isNullOrEmptyString(title)) {
      return '';
    }

    //
    const currentLocale = this.managerService.currentLocale;

    //
    const varName =
      title +
      (currentLocale === 'en-US'
        ? 'En'
        : currentLocale === 'fa-IR'
        ? 'Fa'
        : '');

    const result = this[`${varName}`];

    //
    return result || '';
  }

  getCounterMessage(start: number, stop: number, current: number): string {
    //
    let steps = stop - start;
    if (steps < 0) {
      steps *= -1;
    }

    //
    const ellapsed = steps - current;
    const remained = steps - ellapsed;

    //
    const minutes = Math.trunc(remained / 60);
    const seconds = remained - minutes * 60;

    //
    const message = `${toTimeFormat(minutes)}:${toTimeFormat(seconds)}`;

    //
    const locale = this.managerService.currentLocale;

    //
    if (locale === 'fa-IR') {
      return toPersianNumbers(message);
    } else {
      return message;
    }
  }
  //#endregion

  //
  //#region UI Handlers ...
  handleCounterStop(event: XCounterTick) {}

  handleCounterStart(event: XCounterTick) {}

  handleCounterTick(event: XCounterTick) {}
  //#endregion
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\description-list\description-list.page.html

<v-page
  [hasSide]="true"
  [toolbarTitle]="toolbarTitle"
  [toolbarSubTitle]="toolbarSubTitle"
  [toolbarShowSubTitle]="toolbarShowSubTitle"
>
  <!-- Content -->
  <x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
    <!-- Content -->
    <x-markdown
      [mode]="'preview'"
      [hasToolbar]="false"
      [content]="getContent('content')"
    ></x-markdown>

    <!-- Actions -->
    <div actions>
      <a
        target="_blank"
        href="https://docs.x-framework.ir/x-framework-components/components/XDescriptionListComponent.html"
        >{{resourceProvider(ResourceIDs.documentation)}}</a
      >
    </div>
  </x-card>

  <!-- Sample -->
  <x-markdown
    [isInPage]="true"
    [mode]="'preview'"
    [content]="sample1"
    [hasToolbar]="false"
    [wrapWithCard]="true"
    [cssClass]="'code-block'"
    [cardTitle]="resourceProvider(ResourceIDs.sample)"
  ></x-markdown>

  <!-- Component -->
  <x-description-list
    [model]="item"
    [isInPage]="true"
    [isLegacy]="true"
    [wrapWithCard]="true"
    ></x-description-list>
    <!-- [hiddenModelKeys]="['gender', 'mobile']" -->
</v-page>

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\description-list\description-list.page.scss

.content-container {
  margin: 24px;
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\description-list\description-list.page.ts

import { Component } from '@angular/core';
import { XResourceIDs, isNullOrEmptyString } from 'x-framework-core';
import { VPageComponent } from '../../../views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';

export interface ItemType {
  first_name: string;
  last_name: string;
  gender: string;
  mobile: string;
  email: string;
}

@Component({
  selector: 'app-description-list',
  templateUrl: './description-list.page.html',
  styleUrls: ['./description-list.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class DescriptionListPage extends VPageComponent {
  //
  //#region Props ...
  //
  //#region Page Props ...
  titleRes = AppResourceIDs.description_list;
  toolbarTitle = this.resourceProvider(this.titleRes);
  toolbarSubTitle = this.resourceProvider(
    AppResourceIDs.description_list_description
  );
  toolbarShowSubTitle = true;
  //#endregion

  //
  item: ItemType = {
    first_name: 'Hadi',
    last_name: 'Khazaee Asl',
    gender: 'male',
    mobile: '09121694056',
    email: 'hadi_khazaee_asl@yahoo.com',
  };

  //
  // Prepare All Resource IDs ...
  readonly ResourceIDs = Object.assign(
    Object.assign({}, XResourceIDs),
    AppResourceIDs
  ) as any;
  //#endregion

  //
  // Content ...
  readonly contentFa = `
  # ${this.toolbarTitle}
این مولفه جهت نمایش یک مدل داده ای در غالبی ساختار یافته بکار میرود
  `;
  readonly contentEn = `
  # ${this.toolbarTitle}
this component used to show a data model in an structural template
  `;

  //
  readonly sample1 =
    '```html' +
    `
<x-description-list
  [model]="item"
  [isInPage]="true"
  [wrapWithCard]="true"
  [hiddenModelKeys]="['gender', 'mobile']"
>
</x-description-list>
` +
    '```';

  //
  // Provide content based on current locale ...
  getContent(title: string) {
    //
    if (isNullOrEmptyString(title)) {
      return '';
    }

    //
    const currentLocale = this.managerService.currentLocale;

    //
    const varName =
      title +
      (currentLocale === 'en-US'
        ? 'En'
        : currentLocale === 'fa-IR'
        ? 'Fa'
        : '');

    const result = this[`${varName}`];

    //
    return result || '';
  }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\expandable-list\expandable-list.page.html

<v-page
  [hasSide]="true"
  [toolbarTitle]="toolbarTitle"
  [toolbarSubTitle]="toolbarSubTitle"
  [toolbarShowSubTitle]="toolbarShowSubTitle"
>
  <!-- Content -->
  <x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
    <!-- Content -->
    <x-markdown
      [mode]="'preview'"
      [hasToolbar]="false"
      [content]="getContent('content')"
    ></x-markdown>

    <!-- Actions -->
    <div actions>
      <a
        target="_blank"
        href="https://docs.x-framework.ir/x-framework-components/components/XExpandableListComponent.html"
        >{{resourceProvider(ResourceIDs.documentation)}}</a
      >
    </div>
  </x-card>

  <x-markdown
    [isInPage]="true"
    [mode]="'preview'"
    [content]="sample1"
    [hasToolbar]="false"
    [wrapWithCard]="true"
    [cssClass]="'code-block'"
    [cardTitle]="resourceProvider(ResourceIDs.sample)"
  ></x-markdown>

  <x-markdown
    [isInPage]="true"
    [mode]="'preview'"
    [content]="sample2"
    [hasToolbar]="false"
    [wrapWithCard]="true"
    [cssClass]="'code-block'"
  ></x-markdown>

  <x-expandable-list
    [isInPage]="true"
    [items]="listItems"
    [wrapWithCard]="true"
    [closeSiblings]="true"
    [supportRouting]="false"
    [showChildDetailIcon]="true"
    [showParentDetailIcon]="true"
    [startupState]="'expand-all'"
    [disableParentRouting]="false"
    [dividerColor]="ColorNames.Danger"
    [childColor]="ColorNames.Secondary"
    [parentColor]="ColorNames.Tertiary"
    [highlightColor]="ColorNames.Success"
    [parentActiveColor]="ColorNames.Danger"
    [childActiveColor]="ColorNames.Warning"
    (itemSelected)="handleItemSelected($event)"
  >
  </x-expandable-list>
</v-page>

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\expandable-list\expandable-list.page.scss


### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\expandable-list\expandable-list.page.ts

import {
  XColor,
  random,
  XResourceIDs,
  isNullOrEmptyString,
} from 'x-framework-core';
import { Component } from '@angular/core';
import { AppResourceIDs } from 'src/app/config/app.localization.config';
import { VPageComponent } from '../../../views/v-page/v-page.component';
import { XIconNames, XExpandableListItem } from 'x-framework-components';

@Component({
  selector: 'app-expandable-list',
  templateUrl: './expandable-list.page.html',
  styleUrls: ['./expandable-list.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class ExpandableListPage extends VPageComponent {
  //
  //#region Props ...
  //
  //#region Page Props ...
  titleRes = AppResourceIDs.expandable_list;
  toolbarTitle = this.resourceProvider(this.titleRes);
  toolbarSubTitle = this.resourceProvider(
    AppResourceIDs.expandable_list_description
  );
  toolbarShowSubTitle = true;
  //#endregion

  //
  // Prepare All Resource IDs ...
  readonly ResourceIDs = Object.assign(
    Object.assign({}, XResourceIDs),
    AppResourceIDs
  ) as any;

  //
  readonly IconNames = Object.assign({}, XIconNames);
  //#endregion

  //
  tempList = Array.from(Array(5).keys());
  tempChilds = Array.from(Array(2).keys());
  listItems: XExpandableListItem<string>[] = this.tempList.map((i) => {
    //
    const li: XExpandableListItem<string> = {
      ...this.toListItem(i),
      childs:
        random(0, 1) === 0
          ? undefined
          : this.tempChilds.map((c) => {
              //
              const cLi: XExpandableListItem<string> = {
                ...this.toListItem(c, i.toString()),
              };

              //
              return cLi;
            }),
    };

    //
    return li;
  });

  //
  // Content ...
  readonly contentFa = `
  # ${this.toolbarTitle}
  از این مولفه در مواقعی استفاده می شود که قصد داریم مجموعه هایی از اطلاعات را در گروه های مختلف دسته بندی کرده و نمایش دهیم.
    `;

  readonly contentEn = `
  # ${this.toolbarTitle}
  this component used to show a collection of data sets in a grouped structure.
    `;

  //
  readonly sample1 =
    '```html' +
    `
<x-expandable-list
  [items]="listItems"
  [closeSiblings]="true"
  [supportRouting]="false"
  [showChildDetailIcon]="true"
  [showParentDetailIcon]="true"
  [startupState]="'expand-all'"
  [disableParentRouting]="false"
  [dividerColor]="ColorNames.Danger"
  [childColor]="ColorNames.Secondary"
  [parentColor]="ColorNames.Tertiary"
  [highlightColor]="ColorNames.Success"
  [parentActiveColor]="ColorNames.Danger"
  [childActiveColor]="ColorNames.Warning"
  (itemSelected)="handleItemSelected($event)"
>
</x-expandable-list>
` +
    '```';

  //
  readonly sample2 =
    '```typescript' +
    `
async handleItemSelected(item: XExpandableListItem<any>) {
  //
  if (!item) {
    return;
  }

  //
  await this.managerService.notificationService.presentSuccessNotification({
    message: \`item \${item.id} Selected ...\`,
    dissmissable: true,
  });
}
  ` +
    '```';

  //
  //#region UI Providers ...
  //
  // Provide content based on current locale ...
  getContent(title: string) {
    //
    if (isNullOrEmptyString(title)) {
      return '';
    }

    //
    const currentLocale = this.managerService.currentLocale;

    //
    const varName =
      title +
      (currentLocale === 'en-US'
        ? 'En'
        : currentLocale === 'fa-IR'
        ? 'Fa'
        : '');

    const result = this[`${varName}`];

    //
    return result || '';
  }
  //#endregion

  async handleItemSelected(item: XExpandableListItem<any>) {
    //
    if (!item) {
      return;
    }

    //
    await this.managerService.notificationService.presentSuccessNotification({
      message: `item ${item.id} Selected ...`,
      dissmissable: true,
    });
  }

  private toListItem(data: any, prefix?: string) {
    return {
      id: `${prefix ? prefix + '_' : ''}${data}`,
      data: `Item ${prefix ? prefix + '_' : ''}${data}`,
      opened: random(0, 1) === 0 ? true : false,
      title: `Title ${prefix ? prefix + '_' : ''}${data}`,
      description: `Description ${prefix ? prefix + '_' : ''}${data}`,
    } as XExpandableListItem<any>;
  }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\expandable-panel\expandable-panel.page.html

<v-page
  [hasSide]="true"
  [toolbarTitle]="toolbarTitle"
  [toolbarSubTitle]="toolbarSubTitle"
  [toolbarShowSubTitle]="toolbarShowSubTitle"
>
  <!-- Content -->
  <x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
    <!-- Content -->
    <x-markdown
      [mode]="'preview'"
      [hasToolbar]="false"
      [content]="getContent('content')"
    ></x-markdown>

    <!-- Actions -->
    <div actions>
      <a
        target="_blank"
        href="https://docs.x-framework.ir/x-framework-components/modules/XExpandablePanelModule.html"
        >{{resourceProvider(ResourceIDs.documentation)}}</a
      >
    </div>
  </x-card>

  <!-- Sample -->
  <x-markdown
    [isInPage]="true"
    [mode]="'preview'"
    [content]="sample1"
    [hasToolbar]="false"
    [wrapWithCard]="true"
    [cssClass]="'code-block'"
    [cardTitle]="resourceProvider(ResourceIDs.sample)"
  >
  </x-markdown>

  <!-- Component -->
  <x-expandable-panel
    [isInPage]="true"
    [isAccordion]="true"
    [selected]="'First'"
    [wrapWithCard]="true"
    [headerColor]="ColorNames.Tertiary"
    [hideDescriptionOnSmallScreens]="false"
    [headerHighlightColor]="ColorNames.Warning"
  >
    <x-panel [id]="'First'" [hasNext]="true" [hasCustomActions]="true">
      <div x-panel-title>
        Title 1
      </div>

      <div x-panel-description>
        Description 1
      </div>

      Content 1

      <div actions>
        Custom Actions 1
      </div>
    </x-panel>

    <x-panel
      [id]="'Second'"
      [hasNext]="true"
      [hasPrev]="true"
      [hasReset]="true"
    >
      <div x-panel-title>
        Title 2
      </div>

      <div x-panel-description>
        Description 2
      </div>

      Content 2
    </x-panel>

    <x-panel [id]="'Third'" [hasPrev]="true" [hasReset]="true">
      <div x-panel-title>
        Title 3
      </div>

      <div x-panel-description>
        Description 3
      </div>

      Content 3
    </x-panel>
  </x-expandable-panel>
</v-page>

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\expandable-panel\expandable-panel.page.scss


### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\expandable-panel\expandable-panel.page.ts

import { Component } from '@angular/core';
import { XIconNames } from 'x-framework-components';
import { VPageComponent } from '../../../views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';
import { XResourceIDs, isNullOrEmptyString, XColor } from 'x-framework-core';

@Component({
  selector: 'app-expandable-panel',
  templateUrl: './expandable-panel.page.html',
  styleUrls: ['./expandable-panel.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class ExpandablePanelPage extends VPageComponent {
  //
  //#region Props ...
  //
  //#region Page Props ...
  titleRes = AppResourceIDs.expandable_panel;
  toolbarTitle = this.resourceProvider(this.titleRes);
  toolbarSubTitle = this.resourceProvider(
    AppResourceIDs.expandable_panel_description
  );
  toolbarShowSubTitle = true;
  //#endregion

  //
  // Prepare All Resource IDs ...
  readonly ResourceIDs = Object.assign(
    Object.assign({}, XResourceIDs),
    AppResourceIDs
  ) as any;

  //
  readonly IconNames = Object.assign({}, XIconNames);
  //#endregion

  //
  // Content ...
  readonly contentFa = `
  # ${this.toolbarTitle}
  این مولفه جهت گروه بندی محتوای قابل ارائه در یک نمایه بکار می رود.
  `;

  readonly contentEn = `
  # ${this.toolbarTitle}
  this component used to Grouped representable contents in a View.
  `;

  //
  readonly sample1 =
    '```html' +
    `
<x-expandable-panel
  [isAccordion]="true"
  [selected]="'First'"
  [headerColor]="ColorNames.Tertiary"
  [headerHighlightColor]="ColorNames.Warning"
>
  <x-panel [id]="'First'" [hasNext]="true" [hasCustomActions]="true">
  <div x-panel-title>
    Title 1
  </div>

  <div x-panel-description>
    Description 1
  </div>

  Content 1

  <div actions>
    Custom Actions 1
  </div>
  </x-panel>

  <x-panel [id]="'Second'" [hasNext]="true" [hasPrev]="true" [hasReset]="true">
  <div x-panel-title>
    Title 2
  </div>

  <div x-panel-description>
    Description 2
  </div>

  Content 2
  </x-panel>

  <x-panel [id]="'Third'" [hasPrev]="true" [hasReset]="true">
  <div x-panel-title>
    Title 3
  </div>

  <div x-panel-description>
    Description 3
  </div>

  Content 3
  </x-panel>
</x-expandable-panel>
` +
    '```';

  //
  //#region UI Providers ...
  //
  // Provide content based on current locale ...
  getContent(title: string) {
    //
    if (isNullOrEmptyString(title)) {
      return '';
    }

    //
    const currentLocale = this.managerService.currentLocale;

    //
    const varName =
      title +
      (currentLocale === 'en-US'
        ? 'En'
        : currentLocale === 'fa-IR'
        ? 'Fa'
        : '');

    const result = this[`${varName}`];

    //
    return result || '';
  }
  //#endregion
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\fab\fab.page.html

<v-page
  [actions]="actions"
  [toolbarSubTitle]="toolbarSubTitle"
  [toolbarShowSubTitle]="toolbarShowSubTitle"
>
  <!-- Content -->
  <x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
    <!-- Content -->
    <x-markdown
      [mode]="'preview'"
      [hasToolbar]="false"
      [content]="getContent('content')"
    ></x-markdown>

    <!-- Actions -->
    <div actions>
      <a
        target="_blank"
        href="https://docs.x-framework.ir/x-framework-components/components/XFabComponent.html"
        >{{resourceProvider(ResourceIDs.documentation)}}</a
      >
    </div>
  </x-card>

  <x-card
    [isInPage]="true"
    [showHeader]="true"
    [showActions]="true"
    [color]="ColorNames.Light"
    [title]="resourceProvider(ResourceIDs.sample)"
  >
    <x-markdown
      [mode]="'preview'"
      [content]="sample1"
      [hasToolbar]="false"
      [cssClass]="'code-block'"
    ></x-markdown>

    <x-markdown
      [mode]="'preview'"
      [content]="sample2"
      [hasToolbar]="false"
      [cssClass]="'code-block'"
    ></x-markdown>
  </x-card>

  <x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />

    <x-fab
      [item]="{
      id: 'fab_1',
      fixed: true,
      icon: IconNames.menu_vertical,
      size: FabButtonSizes.REGULAR,
      color: ColorNames.Tertiary,
      vertical: FabVerticalSlots.CENTER,
      horizontal: FabHorizontalSlots.CENTER,
      childs: [
      {
        id: 'fab_child_1',
        index: 0,
        icon: IconNames.phone,
        side: FabButtonSides.TOP,
        size: FabButtonSizes.MINI,
        color: ColorNames.Success,
        tooltip: ResourceIDs.temp_label,
        handler: fabHandler
      },
      {
        id: 'fab_child_2',
        index: 1,
        icon: IconNames.mail,
        side: FabButtonSides.BOTTOM,
        size: FabButtonSizes.MINI,
        color: ColorNames.Primary,
        tooltip: ResourceIDs.temp_label,
        handler: fabHandler
      },
      {
        id: 'fab_child_3',
        index: 2,
        icon: IconNames.share,
        side: FabButtonSides.START,
        size: FabButtonSizes.MINI,
        color: ColorNames.Medium,
        tooltip: ResourceIDs.temp_label,
        handler: fabHandler
      },
      {
        id: 'fab_child_3_1',
        index: 3,
        icon: IconNames.avatars,
        side: FabButtonSides.START,
        size: FabButtonSizes.MINI,
        color: ColorNames.Secondary,
        tooltip: ResourceIDs.temp_label,
        handler: fabHandler
      },
      {
        id: 'fab_child_4',
        index: 4,
        icon: IconNames.web,
        side: FabButtonSides.END,
        size: FabButtonSizes.MINI,
        color: ColorNames.Danger,
        tooltip: ResourceIDs.temp_label,
        handler: fabHandler
      }
      ]
    }"
    ></x-fab>
  </x-card>

  <!-- Descriptions -->
  <x-card
    [isInPage]="true"
    [showActions]="true"
    [showHeader]="true"
    [color]="ColorNames.Light"
    [title]="resourceProvider(ResourceIDs.descriptions)"
  >
    <!-- Descriptions -->
    <x-markdown
      [mode]="'preview'"
      [hasToolbar]="false"
      [content]="getContent('descriptions')"
    ></x-markdown>

    <!-- Actions -->
    <div actions>
      <a
        target="_blank"
        href="./assets/docs/x-framework-components/components/XPageComponent.html"
        >{{resourceProvider(ResourceIDs.documentation)}}</a
      >
    </div>
  </x-card>

  <!-- Cards -->
  <ng-container *ngFor="let id of ids">
    <ng-container
      *ngTemplateOutlet="contentRef; context: {$implicit: id}"
    ></ng-container>
  </ng-container>
</v-page>

<!-- Template Content -->
<ng-template #contentRef let-id>
  <x-card
    [showHeader]="true"
    [isInPage]="true"
    [showActions]="true"
    [title]="'Title ' + id"
    [subTitle]="'SubTitle ' + id"
    class="v-card v-no-marigin-card"
    [avatarUrl]="'/assets/icon/favicon.png'"
  >
    <!-- Content -->
    <p>
      Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quisquam
      inventore, optio obcaecati, harum temporibus accusamus voluptatem,
      sapiente corporis expedita ipsum quos enim odio adipisci! At praesentium
      hic quaerat ad mollitia.
    </p>

    <!-- Actions -->
    <div actions>
      <!-- Like -->
      <x-button [type]="ButtonTypes.Icon">
        <x-icon [name]="IconNames.liked" [color]="ColorNames.Danger"></x-icon>
      </x-button>

      <!-- Share -->
      <x-button [type]="ButtonTypes.Icon">
        <x-icon [name]="IconNames.share" [color]="ColorNames.Tertiary"></x-icon>
      </x-button>
    </div>
  </x-card>
</ng-template>

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\fab\fab.page.scss


### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\fab\fab.page.ts

import {
  XFabItem,
  XIconNames,
  XButtonType,
  XFabButtonSize,
  XFabButtonSide,
  XFabVerticalSlot,
  XFabHorizontalSlot,
} from 'x-framework-components';
import { Component } from '@angular/core';
import { VPageComponent } from '../../../views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';
import { XResourceIDs, XColor, isNullOrEmptyString } from 'x-framework-core';

@Component({
  selector: 'app-fab',
  templateUrl: './fab.page.html',
  styleUrls: ['./fab.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class FabPage extends VPageComponent {
  //
  //#region Props ...
  //
  //#region Page Props ...
  toolbarShowSubTitle = true;
  titleRes = AppResourceIDs.fab;
  toolbarTitle = this.resourceProvider(this.titleRes);
  toolbarSubTitle = this.resourceProvider(AppResourceIDs.fab_description);

  //
  ids = Array.from(Array(25).keys());
  //#endregion

  //
  // Prepare All Resource IDs ...
  readonly ResourceIDs = Object.assign(
    Object.assign({}, XResourceIDs),
    AppResourceIDs
  ) as any;

  //
  readonly IconNames = Object.assign({}, XIconNames);
  readonly ButtonTypes = Object.assign({}, XButtonType);

  //
  readonly FabButtonSizes = Object.assign({}, XFabButtonSize);
  readonly FabButtonSides = Object.assign({}, XFabButtonSide);
  readonly FabVerticalSlots = Object.assign({}, XFabVerticalSlot);
  readonly FabHorizontalSlots = Object.assign({}, XFabHorizontalSlot);
  //#endregion

  //
  // Content ...
  readonly contentFa = `
  # ${this.toolbarTitle}

  این مولفه جهت ارائه مجموعه ای از فعالیت های مرتبط با یکدیگر در موارد لزوم مورد استفاده قرار می گیرد.
  `;
  readonly contentEn = `
  # ${this.toolbarTitle}

  this components usually used for present a group of related actions together in where we want.
  `;

  //
  readonly sample1 =
    '```html' +
    `
<x-fab
  [item]="{
  id: 'fab_1',
  fixed: true,
  icon: IconNames.menu_vertical,
  size: FabButtonSizes.REGULAR,
  color: ColorNames.Tertiary,
  vertical: FabVerticalSlots.CENTER,
  horizontal: FabHorizontalSlots.CENTER,
  childs: [
  {
    id: 'fab_child_1',
    index: 0,
    icon: IconNames.phone,
    side: FabButtonSides.TOP,
    size: FabButtonSizes.MINI,
    color: ColorNames.Success,
    tooltip: ResourceIDs.temp_label,
    handler: fabHandler
  },
  {
    id: 'fab_child_2',
    index: 1,
    icon: IconNames.mail,
    side: FabButtonSides.BOTTOM,
    size: FabButtonSizes.MINI,
    color: ColorNames.Primary,
    tooltip: ResourceIDs.temp_label,
    handler: fabHandler
  },
  {
    id: 'fab_child_3',
    index: 2,
    icon: IconNames.share,
    side: FabButtonSides.START,
    size: FabButtonSizes.MINI,
    color: ColorNames.Medium,
    tooltip: ResourceIDs.temp_label,
    handler: fabHandler
  },
  {
    id: 'fab_child_3_1',
    index: 3,
    icon: IconNames.avatars,
    side: FabButtonSides.START,
    size: FabButtonSizes.MINI,
    color: ColorNames.Secondary,
    tooltip: ResourceIDs.temp_label,
    handler: fabHandler
  },
  {
    id: 'fab_child_4',
    index: 4,
    icon: IconNames.web,
    side: FabButtonSides.END,
    size: FabButtonSizes.MINI,
    color: ColorNames.Danger,
    tooltip: ResourceIDs.temp_label,
    handler: fabHandler
  }
  ]
}"
></x-fab>
` +
    '```';

  //
  readonly sample2 =
    '```typescript' +
    `
fabHandler = async (id?: string) => {
  await this.handleNotifyFab(id);
};
` +
    '```';

  //
  readonly descriptionsFa = `
  در ادامه نمونه ای از بکارگیری دکمه های شناور ارائه می گردد که در مولفه صفحه و بعنوان یکی از اجزاء آن ارائه شده است.
    برای آشنایی بیشتر می توانید به مستندات مولفه صفحه مراجعه کنید.
    `;

  readonly descriptionsEn = `
    in the following example you will see an implementation of Fab component which provides as a part of Page component.
    for more information you can see Page component documentations.
    `;

  //
  actions: XFabItem = {
    //
    id: 'edit_profile',

    //
    fixed: true,

    //
    color: XColor.Warning,

    //
    icon: XIconNames.edit,

    //
    tooltip: AppResourceIDs.temp_label,

    //
    vertical: XFabVerticalSlot.BOTTOM,
    horizontal: XFabHorizontalSlot.END,

    //
    disabled: this.uiDisabled,

    //
    handler: async (id?: string) => {
      await this.handleNotifyFab(id);
    },
  };

  //
  //#region UI Providers ...
  //
  // Provide content based on current locale ...
  getContent(title: string) {
    //
    if (isNullOrEmptyString(title)) {
      return '';
    }

    //
    const currentLocale = this.managerService.currentLocale;

    //
    const varName =
      title +
      (currentLocale === 'en-US'
        ? 'En'
        : currentLocale === 'fa-IR'
        ? 'Fa'
        : '');

    const result = this[`${varName}`];

    //
    return result || '';
  }

  fabHandler = async (id?: string) => {
    await this.handleNotifyFab(id);
  };
  //#endregion

  //
  //#region UI Handlers ...
  async handleNotifyFab(id?: string) {
    await this.managerService.notificationService.presentInfoNotification({
      message: `Clicked Fab Id: ${id}`,
      dissmissable: true,
    });
  }
  //#endregion
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\file-components\file-components.page.html

<v-page
  [hasSide]="true"
  [toolbarTitle]="toolbarTitle"
  [toolbarSubTitle]="toolbarSubTitle"
  [toolbarShowSubTitle]="toolbarShowSubTitle"
>
  <!-- Content -->
  <x-markdown
    [mode]="'preview'"
    [hasToolbar]="false"
    [wrapWithCard]="true"
    [isInPage]="true"
    [content]="getContent('content')"
  ></x-markdown>

  <!-- Expandable Panel -->
  <x-expandable-panel
    [isInPage]="true"
    [isAccordion]="true"
    [wrapWithCard]="true"
    [selected]="'thumbnail'"
    [headerColor]="ColorNames.Tertiary"
    [headerHighlightColor]="ColorNames.Dark"
  >
    <!-- Thumbnail -->
    <x-panel [id]="'thumbnail'" [hasCustomActions]="true">
      <!-- Title and Description -->
      <div x-panel-title>
        {{ resourceProvider(ResourceIDs.thumbnail_component) }}
      </div>
      <!-- <div x-panel-description>
        {{ resourceProvider(ResourceIDs.thumbnail_description) }}
      </div> -->

      <br />

      <!-- Description -->
      <x-markdown
        [mode]="'preview'"
        [hasToolbar]="false"
        [content]="getContent('thumbnailContent')"
      ></x-markdown>

      <x-markdown
        [mode]="'preview'"
        [hasToolbar]="false"
        [cssClass]="'code-block'"
        [content]="thumbnailSample1"
      ></x-markdown>

      <x-thumbnail [identifier]="fileUrl" [type]="ThumbnailTypes.CUSTOM">
      </x-thumbnail>

      <x-markdown
        [mode]="'preview'"
        [hasToolbar]="false"
        [cssClass]="'code-block'"
        [content]="thumbnailSample2"
      ></x-markdown>

      <x-thumbnail [identifier]="fileUrl" [type]="ThumbnailTypes.GENERAL">
      </x-thumbnail>

      <!-- Actions -->
      <div x-panel-actions>
        <a
          target="_blank"
          href="https://docs.x-framework.ir/x-framework-components/components/XThumbnailComponent.html"
          >{{resourceProvider(ResourceIDs.documentation)}}</a
        >
      </div>
    </x-panel>

    <!-- File Drop Area -->
    <x-panel [id]="'file_drop_area'" [hasCustomActions]="true">
      <!-- Title and Description -->
      <div x-panel-title>
        {{ resourceProvider(ResourceIDs.file_drop_area) }}
      </div>
      <!-- <div x-panel-description>
        {{ resourceProvider(ResourceIDs.file_drop_area_description) }}
      </div> -->

      <br />

      <!-- Description -->
      <x-markdown
        [mode]="'preview'"
        [hasToolbar]="false"
        [content]="getContent('fileDropAreaContent')"
      ></x-markdown>

      <x-markdown
        [mode]="'preview'"
        [hasToolbar]="false"
        [cssClass]="'code-block'"
        [content]="fileDropAreaSample1"
      ></x-markdown>

      <!-- File Drop Area -->
      <x-file-drop-area
        [supportsMultipleFiles]="true"
        (filesChangeEmiter)="handleFilesChanged($event)"
      ></x-file-drop-area>

      <!-- Actions -->
      <div x-panel-actions>
        <a
          target="_blank"
          href="https://docs.x-framework.ir/x-framework-components/components/XFileDropAreaComponent.html"
          >{{resourceProvider(ResourceIDs.documentation)}}</a
        >
      </div>
    </x-panel>

    <!-- Image Cropper -->
    <x-panel [id]="'iamge_cropper'" [hasCustomActions]="true">
      <!-- Title and Description -->
      <div x-panel-title>{{ resourceProvider(ResourceIDs.image_cropper) }}</div>
      <!-- <div x-panel-description>
        {{ resourceProvider(ResourceIDs.image_cropper_description) }}
      </div> -->

      <br />

      <!-- Description -->
      <x-markdown
        [mode]="'preview'"
        [hasToolbar]="false"
        [content]="getContent('imageCropperContent')"
      ></x-markdown>

      <!--
      <x-markdown
        [mode]="'preview'"
        [hasToolbar]="false"
        [cssClass]="'code-block'"
        [content]="imageCropperSample1"
      ></x-markdown>
      -->

      <!-- <div class="container"> -->
      <!-- File Upload Input -->
      <!-- <input
          hidden
          #fileInput
          type="file"
          multiple="false"
          (change)="handleFilesSelected()"
          [disabled]="isLoading || uiDisabled"
        />

        <x-button
          (click)="selectFile()"
          [type]="ButtonTypes.Raised"
          [color]="ColorNames.Primary"
          [title]="resourceProvider(ResourceIDs.select) + ' ' + resourceProvider(ResourceIDs.avatar)"
        >
        </x-button> -->

      <!-- Wrapper of Thumbnail -->
      <!-- <div *ngIf="file" class="thumbnail-wrapper">
          <x-slotter
            [hasCenterSlot]="false"
            [layout]="SlotLayout.HORIZONTAL"
            [startTopSlotCssClass]="'ion-text-start'"
            [endBottomSlotCssClass]="['ion-text-center']"
          >
            <x-slot [name]="SlotNames.START">
              <div>
                <x-thumbnail
                  class="x-thumb"
                  [identifier]="file"
                  [loading]="isLoading"
                  [cssClass]="'thumbnail'"
                  [uiDisabled]="uiDisabled"
                  [type]="ThumbnailTypes.CUSTOM"
                >
                </x-thumbnail>
              </div>
            </x-slot>

            <x-slot [name]="SlotNames.END">
              <div class="avatar-actions ion-text-end">
                <div>
                  <x-button
                    *ngIf="croppableImage()"
                    [type]="ButtonTypes.Icon"
                    (click)="handleLoadCropper()"
                    [color]="ColorNames.Secondary"
                    [matTooltip]="resourceProvider(ResourceIDs.crop)"
                  >
                    <x-icon [name]="IconNames.crop"></x-icon>
                  </x-button>

                  <x-button
                    [type]="ButtonTypes.Icon"
                    (click)="handleClearFile()"
                    [color]="ColorNames.Warning"
                    [matTooltip]="resourceProvider(ResourceIDs.clear)"
                  >
                    <x-icon
                      [name]="IconNames.clear"
                      [color]="ColorNames.Light"
                    ></x-icon>
                  </x-button>
                </div>
              </div>
            </x-slot>
          </x-slotter>
        </div> -->
      <!-- </div> -->

      <x-avatar-upload
        [showFileDropArea]="true"
        [color]="ColorNames.Dark"
        [fileDropAreaColor]="ColorNames.Dark"
        placeHolderAvatar="/assets/image/default-user-image.png"
      >
      </x-avatar-upload>

      <!-- Actions -->
      <div x-panel-actions>
        <a
          target="_blank"
          href="https://docs.x-framework.ir/x-framework-components/modules/XImageCropperModule.html"
          >{{resourceProvider(ResourceIDs.documentation)}}</a
        >
      </div>
    </x-panel>

    <!-- File Upload -->
    <x-panel [id]="'file_upload'" [hasCustomActions]="true">
      <!-- Title and Description -->
      <div x-panel-title>{{ resourceProvider(ResourceIDs.file_upload) }}</div>
      <!-- <div x-panel-description>
        {{ resourceProvider(ResourceIDs.file_upload_description) }}
      </div> -->

      <br />

      <!-- Description -->
      <x-markdown
        [mode]="'preview'"
        [hasToolbar]="false"
        [content]="getContent('fileUploadContent')"
      ></x-markdown>

      <x-markdown
        [mode]="'preview'"
        [hasToolbar]="false"
        [cssClass]="'code-block'"
        [content]="fileUploadSample1"
      ></x-markdown>

      <!-- Sample -->
      <x-file-upload
        [showEmpty]="true"
        [color]="'dark-tint'"
        [showActionBar]="true"
        [listShowToolbar]="true"
        [emptyHasRefresh]="false"
        [listEnableReordering]="true"
        [emptyColor]="ColorNames.Dark"
        [fileDropAreaColor]="'dark-tint'"
        [actionBarColor]="ColorNames.Dark"
        [searchBarColor]="ColorNames.Dark"
        [emptyMessageColor]="ColorNames.Dark"
        [emptyForegroundMessageColor]="false"
        (fileChange)="handleFileChanged($event)"
        [maxAllowedSize]="config.maxAllowedSize"
        [maxAllowedFiles]="config.maxUploadFiles"
        [showFileDropArea]="isNotMobileUi$ | async"
        [searchBarSearchInputColor]="ColorNames.Dark"
        [minAllowedFileSize]="config.minAllowedFileSize"
        [maxAllowedFileSize]="config.maxAllowedFileSize"
        (actionBarActionFired)="handleActionFired($event)"
      ></x-file-upload>

      <!-- Actions -->
      <div x-panel-actions>
        <a
          target="_blank"
          href="https://docs.x-framework.ir/x-framework-components/modules/XFileUploadModule.html"
          >{{resourceProvider(ResourceIDs.documentation)}}</a
        >
      </div>
    </x-panel>
  </x-expandable-panel>
</v-page>

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\file-components\file-components.page.scss

//
$size: 32px !important;
$thumbSize: 64px !important;

.thumbnail-wrapper {
  margin-top: 6px;
  height: $thumbSize;
}

x-thumbnail {
  --thumbnail-size: #{$size};
}

// :host ::ng-deep .thumbnail,
// :host ::ng-deep .x-item {
//   width: $size;
//   min-width: $size;
//   max-width: $size;

//   height: $size;
//   min-height: $size;
//   max-height: $size;
// }

:host ::ng-deep .thumbnail {
  img {
    border-radius: 50% !important;
  }
}

.avatar-actions {
  //
  @extend .thumbnail-wrapper;

  //
  display: flex;
  align-items: center;
  flex-direction: row;

  //
  * {
    flex: auto;
    margin: {
      top: auto;
      bottom: auto;
    }

    //
    * {
      margin: {
        left: 3px;
        right: 3px;
      }
    }
  }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\file-components\file-components.page.ts

import {
  Inject,
  NgZone,
  Component,
  ViewChild,
  Renderer2,
  ElementRef,
  ChangeDetectorRef,
} from '@angular/core';
import {
  XColor,
  toArray,
  isArray,
  hasChild,
  getArrayOf,
  XResourceIDs,
  XExceptionIDs,
  isExtensionOk,
  XDialogResult,
  XOneOrManyType,
  getImageDimensions,
  isNullOrEmptyString,
} from 'x-framework-core';
import {
  XSlotName,
  XIconNames,
  XSlotLayout,
  XFileStatus,
  XButtonType,
  XThumbnailType,
  XPageContainer,
  XPopoverService,
  XImageCropperService,
  XActionBarActionFiredModel,
} from 'x-framework-components';
import { MenuController } from '@ionic/angular';
import { X_CONFIG } from 'src/app/config/x-config';
import { XConfig } from 'src/app/config/app-config';
import { ViewportRuler } from '@angular/cdk/overlay';
import { XManagerService } from 'x-framework-services';
import { VPageComponent } from '../../../views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';

@Component({
  selector: 'app-file-components',
  templateUrl: './file-components.page.html',
  styleUrls: ['./file-components.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class FileComponentsPage extends VPageComponent {
  //
  //#region Props ...
  //
  //#region Page Props ...
  titleRes = AppResourceIDs.file_components;
  toolbarTitle = this.resourceProvider(this.titleRes);
  toolbarSubTitle = this.resourceProvider(
    AppResourceIDs.file_components_description
  );
  toolbarShowSubTitle = true;
  //#endregion

  //
  //#region image cropper props ...
  readonly SlotNames = Object.assign({}, XSlotName);
  readonly SlotLayout = Object.assign({}, XSlotLayout);
  readonly ButtonTypes = Object.assign({}, XButtonType);

  //
  @ViewChild('fileInput', { static: false })
  private fileInputRef!: ElementRef;

  //
  //#region Selected File ...
  private SELECTED_FILE: File;

  set file(v: File) {
    //
    this.SELECTED_FILE = v;

    //
    if (!v) {
      return;
    }

    //
    getImageDimensions(v).then((dimension) => {
      if (dimension) {
        //
        this.selectedFileWidth = dimension.width;
        this.selectedFileHeight = dimension.height;

        //
        this.detectChanges();
      }
    });
  }

  get file() {
    return this.SELECTED_FILE;
  }

  //
  selectedFileWidth = 0;
  selectedFileHeight = 0;

  //
  preparedMaxAllowedFileSize = this.config.maxProfileImageSize;
  preparedAllowedExtensions = this.config.allowedImageExtensions;
  //#endregion

  //
  // Prepare All Resource IDs ...
  readonly ResourceIDs = Object.assign(
    Object.assign({}, XResourceIDs),
    AppResourceIDs
  ) as any;

  //
  readonly IconNames = Object.assign({}, XIconNames);
  //#endregion

  //
  // Content ...
  readonly contentFa = `
  # ${this.resourceProvider(this.ResourceIDs.file_components)}
  در این کتابخانه مجموعه ای از مولفه ها جهت سهولت کار با فایل ها ارائه شده است که در ادامه به بررسی هر یک بتفصیل پرداخته خواهد شد:
`;

  readonly contentEn = `
  # ${this.resourceProvider(this.ResourceIDs.file_components)}
  this framework provides several components to make working with files so easy. in the following section they will be documented:
  `;

  //
  // Thumbnail ...
  readonly ThumbnailTypes = Object.assign({}, XThumbnailType);

  readonly thumbnailContentFa = `
  این مولفه جهت نمایش تصاویر بند انگشتی و یا تعیین نوع فایل در حالت عمومی کاربرد دارد.
  `;
  readonly thumbnailContentEn = `
  this component used to show a thumbnail of an image or file general types.
  `;

  readonly fileUrl = this.managerService.getFullUrl('/assets/icon/favicon.png');

  readonly thumbnailSample1 =
    '```html' +
    `
<x-thumbnail
  [identifier]="fileUrl"
  [type]="ThumbnailTypes.CUSTOM"
>
</x-thumbnail>
` +
    '```';

  readonly thumbnailSample2 =
    '```html' +
    `
<x-thumbnail
  [identifier]="fileUrl"
  [type]="ThumbnailTypes.GENERAL"
>
</x-thumbnail>
` +
    '```';

  //
  // File Drop Area ...
  readonly fileDropAreaContentFa = `
  این مولفه جهت فراهم کردن فضایی برای کشیدن فایل ها و رها کردن آن ها در فضای مناسب مورد استفاده قرار می گیرد.
  `;
  readonly fileDropAreaContentEn = `
  this component use to provide an area for dropping file(s)
  `;

  //
  readonly fileDropAreaSample1 =
    '```html' +
    `
<x-file-drop-area
  [wrapWithCard]="true"
  [isPageFileDropArea]="true"
  [supportsMultipleFiles]="true"
  (filesChangeEmiter)="
    handleFilesChanged($event)"
></x-file-drop-area>
` +
    '```';

  readonly imageCropperContentFa = `
  این مولفه جهت فراهم کردن امکانات بریدن تصاویر کاربرد دارد که مهمترین مورد کاربرد آن در تصاویر پروفایل است.
  `;
  readonly imageCropperContentEn = `
  this component use to provide a way to cropping images before upload them, usually used for avatars.
  `;

  //
  readonly imageCropperSample1 =
    '```html' +
    `
<div class="container">
  <input
    hidden
    #fileInput
    type="file"
    multiple="false"
    (change)="
      handleFilesSelected()"
    [disabled]="
      isLoading || uiDisabled"
  />

  <x-button
    (click)="selectFile()"
    [type]="ButtonTypes.Raised"
    [color]="ColorNames.Primary"
    [title]="
    resourceProvider(
        ResourceIDs.select)
      + \' \' +
      resourceProvider(
          ResourceIDs.avatar)"
  >
  </x-button>

  <div
    *ngIf="file"
    class="thumbnail-wrapper"
  >
    <x-slotter
      [hasCenterSlot]="false"
      [layout]="
        SlotLayout.HORIZONTAL"
      [startTopSlotCssClass]="
        \'ion-text-start\'"
      [endBottomSlotCssClass]="
        \'ion-text-center\'"
    >
      <x-slot
        [name]="SlotNames.START">
        <div>
          <x-thumbnail
            class="x-thumb"
            [identifier]="file"
            [loading]="isLoading"
            [cssClass]="\'thumbnail\'"
            [uiDisabled]="uiDisabled"
            [type]="
              ThumbnailTypes.CUSTOM"
          >
          </x-thumbnail>
        </div>
      </x-slot>

      <x-slot [name]="SlotNames.END">
        <div
          class="
            avatar-actions
            ion-text-end">
          <div>
            <x-button
              *ngIf="
                croppableImage()"
              [type]="
                ButtonTypes.Icon"
              (click)="
                handleLoadCropper()"
              [color]="
                ColorNames.Secondary"
              [matTooltip]="
                resourceProvider(
                  ResourceIDs.crop)"
            >
              <x-icon
                [name]="
                  IconNames.crop">
              </x-icon>
            </x-button>

            <x-button
              [type]="
                ButtonTypes.Icon"
              (click)="
                handleClearFile()"
              [color]="
                ColorNames.Warning"
              [matTooltip]="
                resourceProvider(
                  ResourceIDs.clear)"
            >
              <x-icon
                [name]="
                  IconNames.clear"
                [color]="
                  ColorNames.Light"
              ></x-icon>
            </x-button>
          </div>
        </div>
      </x-slot>
    </x-slotter>
  </div>
</div>
` +
    '```';

  //
  // File Upload ...
  readonly fileUploadContentFa = `
  از این مولفه جهت مدیریت بارگزاری فایل ها استفاده می شود
  `;

  readonly fileUploadContentEn = `
  use this component to manage how files uploaded.
  `;

  readonly fileUploadSample1 =
    '```html' +
    `
<x-file-upload
  [canDrop]="
    isNotMobileUi$ | async"
  (fileChange)="
    handleFileChanged($event)"
  [maxAllowedSize]="
    config.maxAllowedSize"
  [maxAllowedFiles]="
    config.maxUploadFiles"
  [minAllowedFileSize]="
    config.minAllowedFileSize"
  [maxAllowedFileSize]="
    config.maxAllowedFileSize"
></x-file-upload>
` +
    '```';

  //
  //#region Constructor ...
  constructor(
    public zone: NgZone,
    public element: ElementRef,
    public renderer: Renderer2,
    public ruler: ViewportRuler,
    public menuController: MenuController,
    public managerService: XManagerService,
    public changeDetector: ChangeDetectorRef,
    @Inject(X_CONFIG) public config: XConfig,
    public imageCropperService: XImageCropperService,
    protected popoverService: XPopoverService, 
    protected propertyProvider: XPageContainer,
  ) {
    super(
      zone,
      config,
      element,
      renderer,
      ruler,
      menuController,
      managerService,
      changeDetector,
      popoverService,
      propertyProvider
    );
  }
  //#endregion

  //
  //#region UI Providers ...
  //
  // Provide content based on current locale ...
  getContent(title: string) {
    //
    if (isNullOrEmptyString(title)) {
      return '';
    }

    //
    const currentLocale = this.managerService.currentLocale;

    //
    const varName =
      title +
      (currentLocale === 'en-US'
        ? 'En'
        : currentLocale === 'fa-IR'
        ? 'Fa'
        : '');

    const result = this[`${varName}`];

    //
    return result || '';
  }

  croppableImage() {
    return (
      this.file &&
      this.selectedFileWidth > 0 &&
      this.selectedFileHeight > 0 &&
      this.selectedFileWidth >= this.config.minAllowedImageSize &&
      this.selectedFileHeight >= this.config.minAllowedImageSize
    );
  }
  //#endregion

  //
  //#region UI Handlers ...
  //
  async handleFilesChanged(files: File | File[]) {
    //
    console.log('files changed: ', files);

    //
    await this.managerService.notificationService.presentInfoNotification({
      message: `Selected File(s): ${toArray(files).length}`,
      dissmissable: true,
    });
  }

  //
  handleFilesSelected() {
    //
    if (!this.fileInputRef) {
      return;
    }

    //
    const fileInput = this.fileInputRef.nativeElement;
    if (!fileInput || !fileInput.files) {
      return;
    }

    //
    const files = getArrayOf<File>(fileInput.files);

    //
    if (!files || files.length === 0) {
      return;
    }

    //
    const file = files[0];
    if (!file) {
      return;
    }

    //
    fileInput.value = null;

    //
    this.handleFileDropped(files);
  }

  //
  async handleFileDropped(files: File | File[]) {
    //
    if (!files) {
      return;
    }

    //
    this.loading = true;

    //
    let file: File;
    if (!isArray(files) && files instanceof File) {
      file = files as File;
    } else {
      //
      const filesArr = files as File[];
      if (hasChild(filesArr)) {
        file = filesArr[0];
      }
    }

    //
    this.loading = false;

    //
    if (!file) {
      return;
    }

    //
    const status = this.getFileStatus(file);
    if (status !== XFileStatus.OK) {
      this.loading = false;
      this.handleFileStatus(status);
      return;
    }

    //
    this.file = file;
  }

  //
  handleLoadCropper() {
    this.imageCropperService.showCropper(this.file);

    //
    const s = this.applyTakeUntilWrapper(
      this.imageCropperService.onResult.asObservable()
    ).subscribe((res) => {
      //
      if (res.result === XDialogResult.Ok && res.file) {
        //
        this.file = null;
        setTimeout(() => {
          this.file = res.file;
        }, 100);
      }

      //
      s.unsubscribe();
    });
  }

  //
  handleClearFile() {
    //
    this.file = null;
    this.selectedFileWidth = 0;
    this.selectedFileHeight = 0;
  }

  selectFile() {
    //
    if (!this.fileInputRef || !this.fileInputRef.nativeElement) {
      return;
    }

    //
    this.fileInputRef.nativeElement.click();
  }

  //
  // File Upload ...
  async handleFileChanged(files: XOneOrManyType<File>) {
    console.log('files: ', files);
  }

  //
  async handleActionFired(event: XActionBarActionFiredModel) {
    //
    const name = event.action;
    await this.managerService.notificationService.presentXNotification({
      message: `Action Fired: ${name}`,
      dissmissable: true,
      opt: {
        color: XColor.Dark,
      },
    });
  }
  //#endregion

  //
  //#region Private ...
  //
  //#region File Selection Policies ...
  private isExtensionOk(file: File) {
    //
    if (!file) {
      return false;
    }

    //
    if (!hasChild(this.preparedAllowedExtensions)) {
      return true;
    }

    //
    const result = isExtensionOk(file, this.preparedAllowedExtensions);
    return result;
  }

  private isMaxAllowedFileSizeOk(file: File) {
    //
    const result =
      this.preparedMaxAllowedFileSize && this.preparedMaxAllowedFileSize > 0
        ? file.size <= this.preparedMaxAllowedFileSize
        : true;

    //
    return result;
  }

  private getFileStatus(file: File) {
    //
    // Check Not Empty File ...
    if (!file || file.size === 0) {
      return XFileStatus.EMPTY;
    }

    //
    // Check File Extension Validation ...
    if (!this.isExtensionOk(file)) {
      return XFileStatus.NOT_ALLOWED_TYPE;
    }

    //
    // Check File Size Ok ...
    if (!this.isMaxAllowedFileSizeOk(file)) {
      return XFileStatus.SIZE_EXCEEDED;
    }

    //
    // Everythings Ok ...
    return XFileStatus.OK;
  }

  private handleFileStatus(status: XFileStatus) {
    //
    let exception: XExceptionIDs = null;
    switch (status) {
      //
      case XFileStatus.EMPTY:
        exception = this.ExceptionIDs.EmptyFile;
        break;

      //
      case XFileStatus.NOT_ALLOWED_TYPE:
        exception = this.ExceptionIDs.InavlidFile;
        break;

      //
      case XFileStatus.SIZE_EXCEEDED:
        exception = this.ExceptionIDs.MaxFileSizeExceeded;
        break;

      //
      case XFileStatus.MAX_ALLOWED_SIZE_REACHED:
        exception = this.ExceptionIDs.MaxFilesSizeExceeded;
        break;

      //
      case XFileStatus.MAX_ALLOWED_FILES_REACHED:
        exception = this.ExceptionIDs.MaxAllowedFilesExceeded;
        break;
    }

    //
    if (exception) {
      this.managerService.notificationService.presentErrorNotification({
        exception,
        dissmissable: true,
      });
    }
  }
  //#endregion
  //#endregion
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\form\form.page.html

<v-page
  [hasSide]="true"
  [toolbarTitle]="toolbarTitle"
  [toolbarSubTitle]="toolbarSubTitle"
  [toolbarShowSubTitle]="toolbarShowSubTitle"
>
  <!-- Content -->
  <x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
    <!-- Content -->
    <x-markdown
      [mode]="'preview'"
      [hasToolbar]="false"
      [content]="getContent('content')"
    ></x-markdown>

    <!-- Actions -->
    <div actions>
      <a
        target="_blank"
        href="https://docs.x-framework.ir/x-framework-components/components/XFormComponent.html"
        >{{resourceProvider(ResourceIDs.documentation)}}</a
      >
    </div>
  </x-card>

  <x-markdown
    [isInPage]="true"
    [mode]="'preview'"
    [content]="sample1"
    [hasToolbar]="false"
    [wrapWithCard]="true"
    [cssClass]="'code-block'"
    [cardTitle]="resourceProvider(ResourceIDs.sample)"
  ></x-markdown>

  <!-- Form Control Center -->
  <x-form
    [isInPage]="true"
    [wrapWithCard]="true"
    *ngIf="showFormControlCenter"
    [cardTitle]="'Form Controller'"
    [formConfig]="xFormControlConfig"
    [actionProvider]="controlFormActionProvider"
    (valueChanged)="handleFormControlCenterValueChanged($event)"
  >
  </x-form>

  <!-- Form Elements Multiple Actions -->
  <x-card [isInPage]="true">
    <x-slotter [layout]="SlotLayouts.HORIZONTAL">
      <!-- Start -->
      <x-slot [name]="SlotNames.START" [cssClass]="'ion-text-center'">
        <x-button
          [type]="ButtonTypes.Raised"
          [color]="ColorNames.Primary"
          [title]="'Show All Form Fileds'"
          (clicked)="handleShowAllFormFileds()"
        ></x-button>
      </x-slot>

      <!-- Center -->
      <x-slot [name]="SlotNames.CENTER"> </x-slot>

      <!-- End -->
      <x-slot [name]="SlotNames.END" [cssClass]="'ion-text-center'">
        <x-button
          [type]="ButtonTypes.Raised"
          [color]="ColorNames.Danger"
          [title]="'Remove All Form Fileds'"
          (clicked)="handleClearAllFormFileds()"
        ></x-button>
      </x-slot>
    </x-slotter>
  </x-card>

  <!-- Form -->
  <x-form
    [isInPage]="true"
    *ngIf="xFormConfig"
    [wrapWithCard]="true"
    [formConfig]="xFormConfig"
    [cardTitle]="'Sample Form'"
    [actionProvider]="formActionProvider"
    [applyStatusOnControls]="applyStatusOnControls"
    (valueChanged)="handleFormValueChanged($event)"
    [regularColor]="formRegularColor"
    [validColor]="formValidColor"
    [hintColor]="formHintColor"
    [invalidColor]="formInvalidColor"
    [activeColor]="formActiveColor"
    [pendingColor]="formPendingColor"
    [disabledColor]="formDisabledColor"
    [accentColor]="formAccentColor"
    [fillColor]="formFillColor"
    [disabledFillColor]="formDisabledFillColor"
  ></x-form>
</v-page>

<ng-template #nameAutoCompleteRef let-item> {{ item.data }} </ng-template>

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\form\form.page.scss


### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\form\form.page.ts

import {
  keys,
  nameof,
  getKeys,
  hasChild,
  nthItems,
  toBoolean,
  XResourceIDs,
  toNormalString,
  XOneOrManyType,
  XColorIdentifier,
  isNullOrEmptyString,
  XColorWithBrightness,
  XBaseDataPagerQueryResult,
} from 'x-framework-core';
import { Subject } from 'rxjs';
import {
  XListItem,
  XSlotName,
  XIconNames,
  XSlotLayout,
  XButtonType,
  XFormConfig,
  XFormUpdateOn,
  XMarkdownMode,
  XFormBaseAction,
  XFormActionModel,
  XFormControlType,
  XFormControlConfig,
  XFormIconDescriptor,
  XFormMapControlConfig,
  XFormControlAppearance,
  XControlIconDescriptor,
  XFormRadioControlConfig,
  XFormSelectControlConfig,
  XFormSelectControlOption,
  XFormSliderControlConfig,
  XFormMarkdownControlConfig,
  XFormMapControlPresentType,
  XFormCheckBoxControlConfig,
  XFormControlIconDescriptor,
  XFormSelectorControlConfig,
  XFormValueChangeEventModel,
  XBaseFormControlActionModel,
  XFormControlEventsDescriptor,
  XFormDatePickerControlConfig,
  XFormColorPickerControlConfig,
  XFormControlAutoCompleteConfig,
  XFormAvatarUploadControlConfig,
  XFormControlActionProviderModel,
  XFormControlAppearanceIdentifier,
  XFormColorPickerControlPresentType,
  XFormDatePickerControlPickerPosition,
} from 'x-framework-components';
import { Validators } from '@angular/forms';
import { Component, TemplateRef, ViewChild } from '@angular/core';
import { VPageComponent } from '../../../views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';

enum ContentType {
  POST = 'post',
  NEWS = 'news',
}

enum ContentVisibility {
  VISIBLE = 'visible',
  HIDDEN = 'hidden',
}

enum Car {
  GMC = 'gmc',
  BMD = 'bmw',
  JAC = 'jac',
  TOYOTA = 'toyota',
  NISSAN = 'nissan',
}

enum XFormFileds {
  FirstName,
  LastName,
  Content,
  ContentType,
  ContentVisibility,
  Publish,
  BrithDate,
  WeddingState,
  NumOfChilds,
  Avatar,
  Map,
  ColorPicker,
  Selector,
}

interface XFormModel {
  firstName: string;
  lastName: string;
  content: string;
  contentType: string[];
  visibility: ContentVisibility;
  publish: boolean;
  brithDate: Date;
  weddingState: boolean;
  numberOfChilds: number;
  avatar: File;
  latLong: string;
  color: string;
  phoneNumber: string;
  medias: XOneOrManyType<File>;
  car: Car;
}

interface XFormControlModel {
  formFields: string[];
  hasIcon: boolean;
  showHint: boolean;
  showTooltip: boolean;
  disabledByDefault: boolean;
  hasRequiredValidator: boolean;
  applyIconsStateColor: boolean;
  applyStatusOnControls: boolean;
  iconsDefaultColor: XColorIdentifier;
  regularColor: XColorIdentifier;
  validColor: XColorIdentifier;
  hintColor: XColorIdentifier;
  invalidColor: XColorIdentifier;
  activeColor: XColorIdentifier;
  pendingColor: XColorIdentifier;
  disabledColor: XColorIdentifier;
  accentColor: XColorIdentifier;
  fillColor: XColorIdentifier;
  disabledFillColor: XColorIdentifier;
  formControlAppearance: XFormControlAppearanceIdentifier;
}

@Component({
  selector: 'app-form',
  templateUrl: './form.page.html',
  styleUrls: ['./form.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class FormPage extends VPageComponent {
  //
  //#region Props ...
  //
  //#region Page Props ...
  titleRes = AppResourceIDs.form;
  toolbarTitle = this.resourceProvider(this.titleRes);
  toolbarSubTitle = this.resourceProvider(AppResourceIDs.form_description);
  toolbarShowSubTitle = true;
  //#endregion

  //
  // Prepare All Resource IDs ...
  readonly ResourceIDs: any = Object.assign(
    Object.assign({}, XResourceIDs),
    AppResourceIDs
  );

  //
  readonly ColorNames = Object.assign({}, XColorWithBrightness);
  readonly IconNames = Object.assign({}, XIconNames);
  //#endregion

  //
  // Content ...
  readonly contentFa = `
  # ${this.toolbarTitle}
  فرم ها بستر دریافت اطلاعات از کاربر هستند.
  این مولفه امکانات لازم برای تسهیل فرایند ایجاد فرم ها را فراهم می کند.
  `;

  readonly contentEn = `
  # ${this.toolbarTitle}
  Forms used to get data from users.
  this Component provides usefull tools to make form creation easy.
  `;

  //
  readonly sample1 =
    '```html' +
    `
<x-form
  [isInPage]="true"
  *ngIf="xFormConfig"
  [wrapWithCard]="true"
  [formConfig]="xFormConfig"
  [fillColor]="ColorNames.Dark"
  [regularColor]="ColorNames.Light"
  [activeColor]="ColorNames.Primary"
  [actionProvider]="formActionProvider"
  [invalidColor]="ColorNames.DangerShade"
></x-form>
  ` +
    '```';

  //
  private NAME_AUTO_CONMPLETE_REF: TemplateRef<any>;

  @ViewChild('nameAutoCompleteRef')
  set nameAutoCompleteRef(v: TemplateRef<any>) {
    //
    if (!v) {
      return;
    }

    //
    this.NAME_AUTO_CONMPLETE_REF = v;
    this.prepareFormConfig();
    this.detectChanges();
  }

  get nameAutoCompleteRef() {
    return this.NAME_AUTO_CONMPLETE_REF;
  }

  //
  readonly SlotNames = Object.assign({}, XSlotName);
  readonly SlotLayouts = Object.assign({}, XSlotLayout);
  readonly ButtonTypes = Object.assign({}, XButtonType);

  //
  readonly Cars = Object.assign({}, Car);
  readonly FormFields = Object.assign({}, XFormFileds);
  readonly ContentTypes = Object.assign({}, ContentType);
  readonly ContentVisibilities = Object.assign({}, ContentVisibility);

  //
  readonly formActionProvider = new Subject<XFormControlActionProviderModel>();

  //
  private firstNameAutoCompleteIsOpened = false;
  private firstNameAutoCompleteQuery = '';
  private firstNameAutoCompleteItems: XListItem<string>[] =
    this.getFirstNameAutoCompleteItems();

  //
  private readonly FormControlAppearances = Object.assign(
    {},
    XFormControlAppearance
  );

  //
  applyStatusOnControls = false;

  //
  // Last Form Value ...
  lastFormValue: Partial<XFormModel>;

  //
  // Available Form Fields ...
  hasFirstName = false;
  hasLastName = false;
  hasContent = false;
  hasContentType = true;
  hasContentVisibility = false;
  hasPublish = false;
  hasBrithDate = false;
  hasWeddingState = false;
  hasNumOfChilds = false;
  hasAvatar = false;
  hasMap = false;
  hasColorPicker = false;
  hasSelector = false;

  //
  // Form Related Color Values ...
  formRegularColor: XColorIdentifier;
  formValidColor: XColorIdentifier;
  formHintColor: XColorIdentifier;
  formInvalidColor: XColorIdentifier;
  formActiveColor: XColorIdentifier;
  formPendingColor: XColorIdentifier;
  formDisabledColor: XColorIdentifier;
  formAccentColor: XColorIdentifier;
  formFillColor: XColorIdentifier;
  formDisabledFillColor: XColorIdentifier;

  //
  private nameStrings: string[] = [
    'Hadi',
    'Hamid',
    'Hesam',
    'Mehdi',
    'Kourosh',
    'Daruosh',
    'Raymond Reed',
    'Willie Ward',
    'Stephen Edwards',
    'Albert Johnson',
    'Scott Long',
    'Samuel Bailey',
    'Louis Ramirez',
    'Philip Henderson',
    'Jacqueline Bennett',
    'Sharon Hernandez',
    'Karen Morris',
    'Theresa Parker',
    'Judith Coleman',
    'Martha White',
    'Jose Mitchell',
    'Carl Powell',
    'Sandra Lopez',
    'Douglas Wright',
    'Helen Young',
    'Kathryn Hughes',
    'Kathy Bell',
    'Jonathan Price',
    'Paul Morgan',
    'Deborah Roberts',
    'Teresa Martinez',
    'Brenda Williams',
    'Todd Phillips',
    'Clarence Collins',
    'Alan Butler',
    'Donna Torres',
    'Mildred Perry',
    'Katherine Walker',
    'William Flores',
    'Marilyn Brooks',
    'Timothy Clark',
    'Ronald Cook',
    'Frank Hall',
    'Pamela Rogers',
    'Harold Sanders',
    'Harry Hill',
    'Evelyn Thompson',
    'Charles Jenkins',
    'Andrew Murphy',
    'Juan Simmons',
    'Patricia Diaz',
    'Doris Smith',
    'Janice Turner',
    'Matthew Rivera',
    'Joyce Adams',
    'Joe Moore',
    'Nancy Kelly',
    'Peter Garcia',
    'Virginia Ross',
    'Rose James',
    'Donald Nelson',
    'Joan Lewis',
    'Julia Perez',
    'Gerald Washington',
    'Irene Allen',
    'Brandon Green',
    'Melissa Cooper',
    'Sara Taylor',
    'Kelly Martin',
    'Daniel Brown',
    'Robert Evans',
    'Susan Carter',
    'James Thomas',
    'Jack Bryant',
    'Eugene Sanchez',
    'Shirley Davis',
    'Carol Wilson',
    'Ryan Robinson',
    'Roy Griffin',
    'Phillip Alexander',
    'Thomas Miller',
    'Keith Russell',
    'Frances Rodriguez',
    'Diana Wood',
    'Brian Jones',
    'Gregory Jackson',
    'Kenneth Patterson',
    'Anne Stewart',
    'Justin King',
    'Benjamin Scott',
    'Judy Watson',
    'Ruth Gonzalez',
    'Walter Anderson',
    'Steven Peterson',
    'Heather Gonzales',
    'Billy Lee',
    'Betty Campbell',
    'Carolyn Richardson',
    'Jesse Gray',
    'Kevin Cox',
    'Denise Foster',
    'Fred Barnes',
    'Nicholas Howard',
    'Christina Baker',
    'Laura Harris',
    'Jennifer',
  ];

  //
  showFormControlCenter = true;
  allAvailableFormFileds = getKeys(this.FormFields);
  controlFormActionProvider = new Subject<XFormActionModel>();
  formConfigModel: XFormControlModel = {
    //
    formFields: ['BrithDate'],
    //
    hasIcon: true,
    showHint: true,
    showTooltip: true,
    disabledByDefault: false,
    hasRequiredValidator: true,
    applyIconsStateColor: true,
    applyStatusOnControls: true,
    //
    iconsDefaultColor: XColorWithBrightness.WarningShade,
    //
    regularColor: XColorWithBrightness.PrimaryTint,
    validColor: XColorWithBrightness.Success,
    hintColor: XColorWithBrightness.Tertiary,
    invalidColor: XColorWithBrightness.Danger,
    activeColor: XColorWithBrightness.Tertiary,
    pendingColor: XColorWithBrightness.Warning,
    disabledColor: XColorWithBrightness.Medium,
    accentColor: XColorWithBrightness.Secondary,
    fillColor: XColorWithBrightness.TertiaryShade,
    disabledFillColor: XColorWithBrightness.LightShade,
    //
    formControlAppearance: XFormControlAppearance.Outline,
  };
  xFormControlConfig: XFormConfig<XFormControlModel> = {
    name: 'FormControlModel',
    model: {
      ...this.formConfigModel,
    },
    controls: [
      //
      // FormFileds ...
      {
        index: 0,
        propName: 'formFields',
        type: {
          type: XFormControlType.Select,
          config: {
            multiple: true,
            options: this.allAvailableFormFileds.map((k) => {
              return {
                value: k,
                viewValue: k,
              } as XFormSelectControlOption<string>;
            }),
          } as XFormSelectControlConfig,
        },
        appearance: {
          label: 'Form Fields',
          appearance: XFormControlAppearance.Outline,
        },
      },
      //
      // Form Regular Color ...
      {
        index: 1,
        propName: 'regularColor',
        type: {
          type: XFormControlType.Select,
          config: {
            options: keys(this.ColorNames).map((k) => {
              return {
                value: this.ColorNames[k],
                viewValue: this.resourceProvider(this.ColorNames[k]),
              } as XFormSelectControlOption<ContentType>;
            }),
          } as XFormSelectControlConfig,
        },
        appearance: {
          label: 'Form Regular Color',
          appearance: XFormControlAppearance.Outline,
        },
      },
      //
      // Form Valid Color ...
      {
        index: 2,
        propName: 'validColor',
        type: {
          type: XFormControlType.Select,
          config: {
            options: keys(this.ColorNames).map((k) => {
              return {
                value: this.ColorNames[k],
                viewValue: this.resourceProvider(this.ColorNames[k]),
              } as XFormSelectControlOption<ContentType>;
            }),
          } as XFormSelectControlConfig,
        },
        appearance: {
          label: 'Form Valid Color',
          appearance: XFormControlAppearance.Outline,
        },
      },
      //
      // Form Hint Color ...
      {
        index: 3,
        propName: 'hintColor',
        type: {
          type: XFormControlType.Select,
          config: {
            options: keys(this.ColorNames).map((k) => {
              return {
                value: this.ColorNames[k],
                viewValue: this.resourceProvider(this.ColorNames[k]),
              } as XFormSelectControlOption<ContentType>;
            }),
          } as XFormSelectControlConfig,
        },
        appearance: {
          label: 'Form Hint Color',
          appearance: XFormControlAppearance.Outline,
        },
      },
      //
      // Form Invalid Color ...
      {
        index: 4,
        propName: 'invalidColor',
        type: {
          type: XFormControlType.Select,
          config: {
            options: keys(this.ColorNames).map((k) => {
              return {
                value: this.ColorNames[k],
                viewValue: this.resourceProvider(this.ColorNames[k]),
              } as XFormSelectControlOption<ContentType>;
            }),
          } as XFormSelectControlConfig,
        },
        appearance: {
          label: 'Form Invalid Color',
          appearance: XFormControlAppearance.Outline,
        },
      },
      //
      // Form Active Color ...
      {
        index: 5,
        propName: 'activeColor',
        type: {
          type: XFormControlType.Select,
          config: {
            options: keys(this.ColorNames).map((k) => {
              return {
                value: this.ColorNames[k],
                viewValue: this.resourceProvider(this.ColorNames[k]),
              } as XFormSelectControlOption<ContentType>;
            }),
          } as XFormSelectControlConfig,
        },
        appearance: {
          label: 'Form Active Color',
          appearance: XFormControlAppearance.Outline,
        },
      },
      //
      // Form Pending Color ...
      {
        index: 6,
        propName: 'pendingColor',
        type: {
          type: XFormControlType.Select,
          config: {
            options: keys(this.ColorNames).map((k) => {
              return {
                value: this.ColorNames[k],
                viewValue: this.resourceProvider(this.ColorNames[k]),
              } as XFormSelectControlOption<ContentType>;
            }),
          } as XFormSelectControlConfig,
        },
        appearance: {
          label: 'Form Pending Color',
          appearance: XFormControlAppearance.Outline,
        },
      },
      //
      // Form Disabled Color ...
      {
        index: 7,
        propName: 'disabledColor',
        type: {
          type: XFormControlType.Select,
          config: {
            options: keys(this.ColorNames).map((k) => {
              return {
                value: this.ColorNames[k],
                viewValue: this.resourceProvider(this.ColorNames[k]),
              } as XFormSelectControlOption<ContentType>;
            }),
          } as XFormSelectControlConfig,
        },
        appearance: {
          label: 'Form Disabled Color',
          appearance: XFormControlAppearance.Outline,
        },
      },
      //
      // Form Accent Color ...
      {
        index: 8,
        propName: 'accentColor',
        type: {
          type: XFormControlType.Select,
          config: {
            options: keys(this.ColorNames).map((k) => {
              return {
                value: this.ColorNames[k],
                viewValue: this.resourceProvider(this.ColorNames[k]),
              } as XFormSelectControlOption<ContentType>;
            }),
          } as XFormSelectControlConfig,
        },
        appearance: {
          label: 'Form Accent Color',
          appearance: XFormControlAppearance.Outline,
        },
      },
      //
      // Form Fill Color ...
      {
        index: 9,
        propName: 'fillColor',
        type: {
          type: XFormControlType.Select,
          config: {
            options: keys(this.ColorNames).map((k) => {
              return {
                value: this.ColorNames[k],
                viewValue: this.resourceProvider(this.ColorNames[k]),
              } as XFormSelectControlOption<ContentType>;
            }),
          } as XFormSelectControlConfig,
        },
        appearance: {
          label: 'Form Fill Color',
          appearance: XFormControlAppearance.Outline,
        },
      },
      //
      // Form Disabled Fill Color ...
      {
        index: 10,
        propName: 'disabledFillColor',
        type: {
          type: XFormControlType.Select,
          config: {
            options: keys(this.ColorNames).map((k) => {
              return {
                value: this.ColorNames[k],
                viewValue: this.resourceProvider(this.ColorNames[k]),
              } as XFormSelectControlOption<ContentType>;
            }),
          } as XFormSelectControlConfig,
        },
        appearance: {
          label: 'Form Disabled Fill Color',
          appearance: XFormControlAppearance.Outline,
        },
      },

      //
      // HasIcon ...
      {
        index: 11,
        propName: 'hasIcon',
        type: {
          type: XFormControlType.CheckBox,
        },
        appearance: {
          label: 'HasIcon',
          appearance: XFormControlAppearance.Outline,
        },
      },
      //
      // ShowHint ...
      {
        index: 12,
        propName: 'showHint',
        type: {
          type: XFormControlType.CheckBox,
        },
        appearance: {
          label: 'ShowHint',
          appearance: XFormControlAppearance.Outline,
        },
      },
      //
      // ShowTooltip ...
      {
        index: 13,
        propName: 'showTooltip',
        type: {
          type: XFormControlType.CheckBox,
        },
        appearance: {
          label: 'ShowTooltip',
          appearance: XFormControlAppearance.Outline,
        },
      },
      //
      // Disabled Controls ...
      {
        index: 14,
        propName: 'disabledByDefault',
        type: {
          type: XFormControlType.CheckBox,
        },
        appearance: {
          label: 'Disabled Controls',
          appearance: XFormControlAppearance.Outline,
        },
      },
      //
      // Has Required Validator ...
      {
        index: 15,
        propName: 'hasRequiredValidator',
        type: {
          type: XFormControlType.CheckBox,
        },
        appearance: {
          label: 'Has Required Validator',
          appearance: XFormControlAppearance.Outline,
        },
      },
      //
      // Apply Icon State Color ...
      {
        index: 16,
        propName: 'applyIconsStateColor',
        type: {
          type: XFormControlType.CheckBox,
        },
        appearance: {
          label: 'Apply Icon State Color',
          appearance: XFormControlAppearance.Outline,
        },
      },
      //
      // Apply Status On Controls ...
      {
        index: 17,
        propName: 'applyStatusOnControls',
        type: {
          type: XFormControlType.CheckBox,
        },
        appearance: {
          label: 'Apply Status On Controls',
          appearance: XFormControlAppearance.Outline,
        },
      },
      //
      // Controls Appearance ...
      {
        index: 18,
        propName: 'formControlAppearance',
        type: {
          type: XFormControlType.Select,
          config: {
            options: keys(this.FormControlAppearances).map((k) => {
              return {
                value: this.FormControlAppearances[k],
                viewValue: this.resourceProvider(
                  this.FormControlAppearances[k]
                ),
              } as XFormSelectControlOption<ContentType>;
            }),
          } as XFormSelectControlConfig,
        },
        appearance: {
          label: 'Controls Appearance',
          appearance: XFormControlAppearance.Outline,
        },
      },
      //
      // Icons Default Color ...
      {
        index: 19,
        propName: 'iconsDefaultColor',
        type: {
          type: XFormControlType.Select,
          config: {
            options: keys(this.ColorNames).map((k) => {
              return {
                value: this.ColorNames[k],
                viewValue: this.resourceProvider(this.ColorNames[k]),
              } as XFormSelectControlOption<ContentType>;
            }),
          } as XFormSelectControlConfig,
        },
        appearance: {
          label: 'Icons Default Color',
          appearance: XFormControlAppearance.Outline,
        },
      },
    ],
  };

  //
  initialFormValue: Partial<XFormModel> = {
    firstName: 'Hadi',
    lastName: 'Khazaee Asl',
    weddingState: true,
    numberOfChilds: 0,
    contentType: ['news'],
    latLong: '51.0025424,35.7866258',
    color: '#9847a6ff',
    car: Car.BMD,
  };
  xFormConfig: XFormConfig<XFormModel>;

  //
  //#region UI Providers ...
  //
  // Provide content based on current locale ...
  getContent(title: string) {
    //
    if (isNullOrEmptyString(title)) {
      return '';
    }

    //
    const currentLocale = this.managerService.currentLocale;

    //
    const varName =
      title +
      (currentLocale === 'en-US'
        ? 'En'
        : currentLocale === 'fa-IR'
        ? 'Fa'
        : '');

    const result = this[`${varName}`];

    //
    return result || '';
  }
  //#endregion

  //
  //#region UI Handlers ...
  public async handleFormValueChanged(value: XFormValueChangeEventModel) {
    //
    console.log('handleFormValueChanged: ', value.value);

    //
    this.lastFormValue = {
      ...value.value,
    };
  }

  public async handleFormControlCenterValueChanged(
    event: XFormValueChangeEventModel
  ) {
    //
    if (event && event.value) {
      //
      this.formConfigModel = {
        ...this.formConfigModel,
        ...event.value,
      };

      //
      await this.clearAndApplyFormModel();
    }

    //
    this.detectChanges();
  }

  public async handleShowAllFormFileds() {
    //
    this.controlFormActionProvider.next({
      action: XFormBaseAction.SetValue,
      name: nameof<XFormControlModel>('formFields'),
      payload: [...this.allAvailableFormFileds],
    });
  }

  public async handleClearAllFormFileds() {
    //
    this.managerService.dialogService.presentAreYouSureYesNoDialog(() => {
      //
      this.controlFormActionProvider.next({
        action: XFormBaseAction.SetValue,
        name: nameof<XFormControlModel>('formFields'),
        payload: [],
      });
    });
  }
  //#endregion

  //
  //#region Private ...
  private prepareFormConfig() {
    //
    this.xFormConfig = {
      name: 'PersonalForm',
      model: {
        //
        ...this.initialFormValue,
        //
        ...this.lastFormValue,
      },
      updateOn: XFormUpdateOn.CHANGE,
      controls: [],
    };

    //
    let cIdx = 0;

    //
    const hasIcon = this.formConfigModel.hasIcon;
    const showHint = this.formConfigModel.showHint;
    const showTooltip = this.formConfigModel.showTooltip;
    const disabledByDefault = this.formConfigModel.disabledByDefault;
    const iconsDefaultColor = this.formConfigModel.iconsDefaultColor;
    const hasRequiredValidator = this.formConfigModel.hasRequiredValidator;
    const applyIconsStateColor = this.formConfigModel.applyIconsStateColor;
    this.applyStatusOnControls = this.formConfigModel.applyStatusOnControls;
    const FormControlAppearance = this.formConfigModel.formControlAppearance;

    //
    //#region Form Colors ...
    this.formRegularColor = this.formConfigModel.regularColor;
    this.formValidColor = this.formConfigModel.validColor;
    this.formHintColor = this.formConfigModel.hintColor;
    this.formInvalidColor = this.formConfigModel.invalidColor;
    this.formActiveColor = this.formConfigModel.activeColor;
    this.formPendingColor = this.formConfigModel.pendingColor;
    this.formDisabledColor = this.formConfigModel.disabledColor;
    this.formAccentColor = this.formConfigModel.accentColor;
    this.formFillColor = this.formConfigModel.fillColor;
    this.formDisabledFillColor = this.formConfigModel.disabledFillColor;
    //#endregion

    //
    //#region Available Form Fields ...
    //
    const formFieldKeys = getKeys(this.FormFields);

    //
    this.hasFirstName = this.formConfigModel.formFields.includes(
      formFieldKeys[this.FormFields.FirstName]
    );
    this.hasLastName = this.formConfigModel.formFields.includes(
      formFieldKeys[this.FormFields.LastName]
    );
    this.hasContent = this.formConfigModel.formFields.includes(
      formFieldKeys[this.FormFields.Content]
    );
    this.hasContentType = this.formConfigModel.formFields.includes(
      formFieldKeys[this.FormFields.ContentType]
    );
    this.hasContentVisibility = this.formConfigModel.formFields.includes(
      formFieldKeys[this.FormFields.ContentVisibility]
    );
    this.hasPublish = this.formConfigModel.formFields.includes(
      formFieldKeys[this.FormFields.Publish]
    );
    this.hasBrithDate = this.formConfigModel.formFields.includes(
      formFieldKeys[this.FormFields.BrithDate]
    );
    this.hasWeddingState = this.formConfigModel.formFields.includes(
      formFieldKeys[this.FormFields.WeddingState]
    );
    this.hasNumOfChilds = this.formConfigModel.formFields.includes(
      formFieldKeys[this.FormFields.NumOfChilds]
    );
    this.hasAvatar = this.formConfigModel.formFields.includes(
      formFieldKeys[this.FormFields.Avatar]
    );
    this.hasMap = this.formConfigModel.formFields.includes(
      formFieldKeys[this.FormFields.Map]
    );
    this.hasColorPicker = this.formConfigModel.formFields.includes(
      formFieldKeys[this.FormFields.ColorPicker]
    );
    this.hasSelector = this.formConfigModel.formFields.includes(
      formFieldKeys[this.FormFields.Selector]
    );
    //#endregion

    //
    const isPrefixIcon = true;
    const defaultIconObject = {
      applyStateColor: applyIconsStateColor || false,
      name: this.IconNames.first_name,
      color: iconsDefaultColor,
    } as XFormIconDescriptor;
    const defaultIcon: XFormControlIconDescriptor = hasIcon
      ? {
          prefix: isPrefixIcon ? defaultIconObject : undefined,
          suffix: !isPrefixIcon ? defaultIconObject : undefined,
        }
      : undefined;
    const clearIcon: XControlIconDescriptor = {
      applyStateColor: false, //applyIconsStateColor || false,
      name: this.IconNames.clear,
      color: this.ColorNames.Danger,
    };
    const selectIcon: XControlIconDescriptor = {
      applyStateColor: false, // applyIconsStateColor || false,
      name: this.IconNames.touch,
      color: this.ColorNames.SuccessShade,
    };
    const eventHandlers: XFormControlEventsDescriptor = {
      onBlured: (model: XBaseFormControlActionModel) =>
        console.log('blured: ', model),
      onFocused: (model: XBaseFormControlActionModel) =>
        console.log('focused: ', model),
      valueChanged: (event) =>
        console.log(event.name.toString(), ' value changed: ', event.value),
      statusChanged: (event) =>
        console.log(
          event.name.toString(),
          ' status changed: ',
          event.status.toString()
        ),
    };

    //
    //#region First Name ...
    if (this.hasFirstName) {
      //
      this.xFormConfig.controls[cIdx] = {
        index: cIdx,
        propName: 'firstName',
        type: {
          type: XFormControlType.Text,
        },
        appearance: {
          disabled: disabledByDefault || false,
          appearance: FormControlAppearance,
          hint: showHint ? this.ResourceIDs.first_name : undefined,
          tooltip: showTooltip ? this.ResourceIDs.first_name : undefined,
          label: this.ResourceIDs.first_name,
          icons: defaultIcon,
        },
        validators: hasRequiredValidator
          ? {
              validators: [Validators.required],
            }
          : undefined,
        errorHandlers: [
          {
            errorName: 'required',
            errorMessage: 'Required Field ...',
          },
        ],
        eventHandlers: {
          ...eventHandlers,
          onBlured: (name) => {
            //
            eventHandlers.onBlured(name);
            this.prepareFirstNameAutoComplete({ opened: false });
          },
          valueChanged: async (event) => {
            //
            eventHandlers.valueChanged(event);
            await this.handleFilterAutoCompleteFirstName(event.value);
          },
        },
      } as XFormControlConfig<XFormModel>;

      //
      cIdx++;

      //
      this.prepareFirstNameAutoComplete();
    }
    //#endregion

    //
    //#region Last Name ...
    if (this.hasLastName) {
      //
      this.xFormConfig.controls[cIdx] = {
        index: cIdx,
        propName: 'lastName',
        type: {
          type: XFormControlType.Text,
        },
        appearance: {
          disabled: disabledByDefault || false,
          label: this.ResourceIDs.last_name,
          appearance: FormControlAppearance,
          hint: showHint ? this.ResourceIDs.last_name : undefined,
          tooltip: showTooltip ? this.ResourceIDs.last_name : undefined,
          icons: defaultIcon,
        },
        validators: hasRequiredValidator
          ? {
              validators: [Validators.required],
            }
          : undefined,
        errorHandlers: [
          {
            errorName: 'required',
            errorMessage: 'Required Field ...',
          },
        ],
        eventHandlers,
      } as XFormControlConfig<XFormModel>;

      //
      cIdx++;
    }
    //#endregion

    //
    //#region Content ...
    if (this.hasContent) {
      //
      this.xFormConfig.controls[cIdx] = {
        index: cIdx,
        propName: 'content',
        type: {
          type: XFormControlType.MarkDown,
          config: {
            hasToolbar: true,
            mode: XMarkdownMode.BOTH,
            toolbarColor: this.ColorNames.Light,
            contentChanged: (content: string) => {
              console.log('markdown new content: ', content);
            },
          } as XFormMarkdownControlConfig,
        },
        appearance: {
          label: AppResourceIDs.content,
          hint: showHint ? AppResourceIDs.content : undefined,
          tooltip: showTooltip ? AppResourceIDs.content : undefined,
          appearance: FormControlAppearance,
          disabled: disabledByDefault || false,
          icons: defaultIcon,
        },
        eventHandlers,
      } as XFormControlConfig<XFormModel>;

      //
      cIdx++;
    }
    //#endregion

    //
    //#region Content Type ...
    if (this.hasContentType) {
      //
      this.xFormConfig.controls[cIdx] = {
        index: cIdx,
        propName: 'contentType',
        type: {
          type: XFormControlType.Select,
          config: {
            multiple: true,
            options: keys(this.ContentTypes).map((k) => {
              return {
                value: this.ContentTypes[k],
                viewValue: this.resourceProvider(this.ContentTypes[k]),
              } as XFormSelectControlOption<ContentType>;
            }),
          } as XFormSelectControlConfig,
        },
        appearance: {
          disabled: disabledByDefault || false,
          label: AppResourceIDs.content_type,
          hint: showHint ? AppResourceIDs.content_type : undefined,
          tooltip: showTooltip ? AppResourceIDs.content_type : undefined,
          placeholder: AppResourceIDs.content_type,
          appearance: FormControlAppearance,
          icons: defaultIcon,
        },
        eventHandlers,
        validators: hasRequiredValidator
          ? {
              validators: [Validators.required],
            }
          : undefined,
        errorHandlers: [
          {
            errorName: 'required',
            errorMessage: 'Required Field ...',
          },
        ],
      } as XFormControlConfig<XFormModel>;

      //
      cIdx++;
    }
    //#endregion

    //
    //#region Content Visibility ...
    if (this.hasContentVisibility) {
      //
      this.xFormConfig.controls[cIdx] = {
        index: cIdx,
        propName: 'visibility',
        type: {
          type: XFormControlType.Radio,
          config: {
            options: keys(this.ContentVisibilities).map((k) => {
              return {
                value: this.ContentVisibilities[k],
                viewValue: this.resourceProvider(this.ContentVisibilities[k]),
              } as XFormSelectControlOption<ContentType>;
            }),
          } as XFormRadioControlConfig,
        },
        appearance: {
          label: AppResourceIDs.visibility,
          hint: showHint ? AppResourceIDs.visibility : undefined,
          tooltip: showTooltip ? AppResourceIDs.visibility : undefined,
          disabled: disabledByDefault || false,
          appearance: FormControlAppearance,
          icons: defaultIcon,
        },
        validators: hasRequiredValidator
          ? {
              validators: [Validators.required],
            }
          : undefined,
        errorHandlers: [
          {
            errorName: 'required',
            errorMessage: 'Required Field ...',
          },
        ],
        eventHandlers,
      } as XFormControlConfig<XFormModel>;

      //
      cIdx++;
    }
    //#endregion

    //
    //#region Publish ...
    if (this.hasPublish) {
      //
      this.xFormConfig.controls[cIdx] = {
        index: cIdx,
        propName: 'publish',
        type: {
          type: XFormControlType.CheckBox,
          config: {
            checkedChanged: (checked: boolean) => {
              console.log('checked change: ', checked);
            },
          } as XFormCheckBoxControlConfig,
        },
        appearance: {
          label: this.ResourceIDs.publish,
          hint: showHint ? this.ResourceIDs.publish : undefined,
          tooltip: showTooltip ? this.ResourceIDs.publish : undefined,
          disabled: disabledByDefault || false,
          appearance: FormControlAppearance,
          icons: defaultIcon,
        },
        validators: hasRequiredValidator
          ? {
              validators: [Validators.requiredTrue],
            }
          : undefined,
        errorHandlers: [
          {
            errorName: 'requiredTrue',
            errorMessage: 'Required Field ...',
          },
        ],
        eventHandlers,
      } as XFormControlConfig<XFormModel>;

      //
      cIdx++;
    }
    //#endregion

    //
    //#region BrithDate ...
    if (this.hasBrithDate) {
      //
      this.xFormConfig.controls[cIdx] = {
        index: cIdx,
        propName: 'brithDate',
        type: {
          type: XFormControlType.Date,
          config: {
            iconColor: iconsDefaultColor,
            toggleIcon: XIconNames.calendar,
            applyStateColor: applyIconsStateColor || false,
            datePickerPosition: XFormDatePickerControlPickerPosition.Prefix,
          } as XFormDatePickerControlConfig,
        },
        appearance: {
          label: this.ResourceIDs.brithDate,
          hint: showHint ? this.ResourceIDs.brithDate : undefined,
          tooltip: showTooltip ? this.ResourceIDs.brithDate : undefined,
          disabled: disabledByDefault || false,
          appearance: FormControlAppearance,
          icons: defaultIcon,
        },
        validators: hasRequiredValidator
          ? {
              validators: [Validators.required],
            }
          : undefined,
        errorHandlers: [
          {
            errorName: 'required',
            errorMessage: 'Required Field ...',
          },
        ],
        eventHandlers,
      } as XFormControlConfig<XFormModel>;

      //
      cIdx++;
    }
    //#endregion

    //
    //#region Wedding State ...
    if (this.hasWeddingState || this.hasNumOfChilds) {
      //
      this.xFormConfig.controls[cIdx] = {
        index: cIdx,
        propName: 'weddingState',
        type: {
          type: XFormControlType.Toggle,
        },
        appearance: {
          label: this.ResourceIDs.wedding_state,
          hint: showHint ? this.ResourceIDs.wedding_state : undefined,
          tooltip: showTooltip ? this.ResourceIDs.wedding_state : undefined,
          disabled: disabledByDefault || false,
          appearance: FormControlAppearance,
          icons: defaultIcon,
        },
        validators: hasRequiredValidator
          ? {
              validators: [Validators.requiredTrue],
            }
          : undefined,
        errorHandlers: [
          {
            errorName: 'requiredTrue',
            errorMessage: 'Required Field ...',
          },
        ],
        eventHandlers: {
          ...eventHandlers,
          valueChanged: (model) => {
            eventHandlers.valueChanged(model);
            this.handleHasNumberOfChild(toBoolean(model.value));
          },
        },
      } as XFormControlConfig<XFormModel>;

      //
      cIdx++;
    }
    //#endregion

    //
    //#region Number Of Childs ...
    if (this.hasNumOfChilds || this.hasWeddingState) {
      //
      this.xFormConfig.controls[cIdx] = {
        index: cIdx,
        propName: 'numberOfChilds',
        type: {
          type: XFormControlType.Hidden,
          config: {
            min: 0,
            max: 15,
            step: 1,
            vertical: false,
            thumbLabel: true,
            formatter: (value) => this.applyLocale(value),
          } as XFormSliderControlConfig,
        },
        appearance: {
          label: this.ResourceIDs.num_of_childs,
          hint: showHint ? this.ResourceIDs.num_of_childs : undefined,
          tooltip: showTooltip ? this.ResourceIDs.num_of_childs : undefined,
          disabled: disabledByDefault || false,
          appearance: FormControlAppearance,
          icons: defaultIcon,
        },
        validators: hasRequiredValidator
          ? {
              validators: [Validators.min(1)],
            }
          : undefined,
        errorHandlers: [
          {
            errorName: 'required',
            errorMessage: 'Required Field ...',
          },
        ],
        eventHandlers,
      } as XFormControlConfig<XFormModel>;

      //
      cIdx++;
    }
    //#endregion

    //
    //#region Avatar ...
    if (this.hasAvatar) {
      //
      this.xFormConfig.controls[cIdx] = {
        index: cIdx,
        propName: 'avatar',
        type: {
          type: XFormControlType.AvatarUpload,
          config: {
            canDrop: true,
            color: this.ColorNames.Light,
            fileDropAreaColor: this.ColorNames.Light,
            placeHolderAvatar: './assets/image/default-user-image.png',
          } as XFormAvatarUploadControlConfig,
        },
        appearance: {
          label: this.ResourceIDs.avatar,
          hint: showHint ? this.ResourceIDs.avatar : undefined,
          tooltip: showTooltip ? this.ResourceIDs.avatar : undefined,
          disabled: disabledByDefault || false,
          appearance: FormControlAppearance,
        },
        validators: hasRequiredValidator
          ? {
              validators: [Validators.required],
            }
          : undefined,
        errorHandlers: [
          {
            errorName: 'required',
            errorMessage: 'Required Field ...',
          },
        ],
        eventHandlers,
      } as XFormControlConfig<XFormModel>;

      //
      cIdx++;
    }
    //#endregion

    //
    //#region Map ...
    if (this.hasMap) {
      //
      this.xFormConfig.controls[cIdx] = {
        index: cIdx,
        propName: 'latLong',
        type: {
          type: XFormControlType.Map,
          config: {
            zoom: 12,
            clearIcon,
            selectIcon,
            showZoom: true,
            canSelect: true,
            showRotate: true,
            showLocate: true,
            disableInput: true,
            showSearchBar: true,
            showClearMarker: true,
            centerAfterInit: false,
            showGoMarkedPlace: true,
            showSelectedPosition: true,
            inputCssClass: 'ion-text-end',
            searchBarColor: XColorWithBrightness.Primary,
            progressBarColor: XColorWithBrightness.Warning,
            presentType: XFormMapControlPresentType.WithoutDialog,
          } as XFormMapControlConfig,
        },
        appearance: {
          label: this.ResourceIDs.location,
          hint: showHint ? this.ResourceIDs.location : undefined,
          tooltip: showTooltip ? this.ResourceIDs.location : undefined,
          disabled: disabledByDefault || false,
          appearance: FormControlAppearance,
          placeholder: this.ResourceIDs.location,
          icons: defaultIcon,
        },
        validators: hasRequiredValidator
          ? {
              validators: [Validators.required],
            }
          : undefined,
        errorHandlers: [
          {
            errorName: 'required',
            errorMessage: 'Required Field ...',
          },
        ],
        eventHandlers,
      } as XFormControlConfig<XFormModel>;

      //
      cIdx++;
    }
    //#endregion

    //
    //#region Color Picker ...
    if (this.hasColorPicker) {
      //
      this.xFormConfig.controls[cIdx] = {
        index: cIdx,
        propName: 'color',
        type: {
          type: XFormControlType.ColorPicker,
          config: {
            clearIcon,
            selectIcon,
            showCopyToClipboard: true,
            inputCssClass: 'ion-text-end',
            presentType: XFormColorPickerControlPresentType.WithoutDialog,
          } as XFormColorPickerControlConfig,
        },
        appearance: {
          label: this.ResourceIDs.color,
          hint: showHint ? this.ResourceIDs.color : undefined,
          tooltip: showTooltip ? this.ResourceIDs.color : undefined,
          disabled: disabledByDefault || false,
          appearance: FormControlAppearance,
          placeholder: this.ResourceIDs.color,
          icons: defaultIcon,
        },
        validators: hasRequiredValidator
          ? {
              validators: [Validators.required],
            }
          : undefined,
        errorHandlers: [
          {
            errorName: 'required',
            errorMessage: 'Required Field ...',
          },
        ],
        eventHandlers,
      } as XFormControlConfig<XFormModel>;

      //
      cIdx++;
    }
    //#endregion

    //
    //#region Selector ...
    if (this.hasSelector) {
      //
      this.xFormConfig.controls[cIdx] = {
        index: cIdx,
        propName: 'car',
        type: {
          type: XFormControlType.Selector,
          config: {
            clearIcon,
            selectIcon,
            title: 'Select Car',
            showPaginator: true,
            taskName: 'load-cars',
            queryFetcher: (query) => {
              //
              const result: XBaseDataPagerQueryResult<Car> = {
                count: keys(this.Cars).length,
                items: keys(this.Cars).map((k) => k as Car),
              };

              //
              return this.getValue(result);
            },
            formatSelectedItem: (item: Car) => this.resourceProvider(item),
            onTaskFinished: (name) => {
              console.log('Task Finished: ', name);
            },
          } as XFormSelectorControlConfig,
        },
        appearance: {
          label: this.ResourceIDs.color,
          hint: showHint ? this.ResourceIDs.color : undefined,
          tooltip: showTooltip ? this.ResourceIDs.color : undefined,
          disabled: disabledByDefault || false,
          appearance: FormControlAppearance,
          placeholder: this.ResourceIDs.color,
          icons: defaultIcon,
        },
        validators: hasRequiredValidator
          ? {
              validators: [Validators.required],
            }
          : undefined,
        errorHandlers: [
          {
            errorName: 'required',
            errorMessage: 'Required Field ...',
          },
        ],
        eventHandlers,
      } as XFormControlConfig<XFormModel>;

      //
      cIdx++;
    }
    //#endregion

    //
    this.detectChanges();
  }

  private prepareFirstNameAutoComplete(
    dataProvider?: Partial<XFormControlAutoCompleteConfig>
  ) {
    //
    if (!this.xFormConfig || !hasChild(this.xFormConfig.controls)) {
      return;
    }

    //
    this.xFormConfig.controls[0].appearance.autoComplete = {
      ...this.xFormConfig.controls[0].appearance.autoComplete,
      //
      opened:
        dataProvider && dataProvider.opened
          ? dataProvider.opened
          : this.firstNameAutoCompleteIsOpened,
      itemTemplate:
        dataProvider && dataProvider.itemTemplate
          ? dataProvider.itemTemplate
          : this.NAME_AUTO_CONMPLETE_REF,
      color:
        dataProvider && dataProvider.color
          ? dataProvider.color
          : XColorWithBrightness.Tertiary,
      items:
        dataProvider && dataProvider.items
          ? dataProvider.items
          : () => {
              return this.firstNameAutoCompleteItems;
            },
      onSelect:
        dataProvider && dataProvider.onSelect
          ? dataProvider.onSelect
          : (item: string) => {
              console.log('auto complete selected: ', item);
            },
      cssClass:
        dataProvider && dataProvider.cssClass
          ? dataProvider.cssClass
          : ['x-auto-complete-margin'],
    };

    //
    this.detectChanges();
  }

  private async handleFilterAutoCompleteFirstName(value: string) {
    //
    if (toNormalString(value) === this.firstNameAutoCompleteQuery) {
      //
      if (hasChild(this.firstNameAutoCompleteItems)) {
        this.firstNameAutoCompleteIsOpened = true;
      } else {
        this.firstNameAutoCompleteIsOpened = false;
      }

      //
      this.prepareFirstNameAutoComplete();
      return;
    }

    //
    this.firstNameAutoCompleteQuery = toNormalString(value);
    this.firstNameAutoCompleteItems = this.getFirstNameAutoCompleteItems();

    //
    this.firstNameAutoCompleteIsOpened = hasChild(
      this.firstNameAutoCompleteItems
    );

    //
    this.prepareFirstNameAutoComplete();
  }

  private getFirstNameAutoCompleteItems(): XListItem<string>[] {
    //
    if (isNullOrEmptyString(this.firstNameAutoCompleteQuery)) {
      return [];
    }

    //
    // Select Top 5 result of filtered Names ...
    const selectedItems = nthItems(
      0,
      5,
      this.nameStrings.filter(
        (n) =>
          toNormalString(n).includes(this.firstNameAutoCompleteQuery) &&
          toNormalString(n) !== this.firstNameAutoCompleteQuery
      )
    );
    if (!hasChild(selectedItems)) {
      return [];
    }

    return selectedItems.map((i) => {
      return {
        data: i,
      } as XListItem<string>;
    });
  }

  private handleHasNumberOfChild(isMarried?: boolean) {
    //
    if (!this.xFormConfig.controls[8]) {
      return;
    }

    //
    const hasChildCount = toBoolean(isMarried);
    if (!hasChildCount) {
      //
      this.xFormConfig.controls[8].type = {
        ...this.xFormConfig.controls[8].type,
        type: XFormControlType.Hidden,
      };
    } else {
      //
      this.xFormConfig.controls[8].type = {
        ...this.xFormConfig.controls[8].type,
        type: XFormControlType.Slider,
      };
    }

    //
    this.detectChanges();
  }

  private async clearAndApplyFormModel() {
    //
    this.xFormConfig = null;

    //
    await this.runTimedOut(() => {
      this.prepareFormConfig();
    });
  }
  //#endregion
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\grid\grid.page.html

<v-page
  [hasSide]="true"
  [toolbarTitle]="toolbarTitle"
  [toolbarSubTitle]="toolbarSubTitle"
  [toolbarShowSubTitle]="toolbarShowSubTitle"
>
  <!-- Content -->
  <x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
    <!-- Content -->
    <x-markdown
      [mode]="'preview'"
      [hasToolbar]="false"
      [content]="getContent('content')"
    ></x-markdown>

    <!-- Actions -->
    <div actions>
      <a
        target="_blank"
        href="https://docs.x-framework.ir/x-framework-components/components/XGridComponent.html"
        >{{resourceProvider(ResourceIDs.documentation)}}</a
      >
    </div>
  </x-card>

  <!-- Samples -->
  <x-markdown
    [mode]="'preview'"
    [content]="sample1"
    [hasToolbar]="false"
    [wrapWithCard]="true"
    [isInPage]="true"
    [cssClass]="'code-block'"
    [cardTitle]="resourceProvider(ResourceIDs.sample)"
  ></x-markdown>

  <x-grid
    [isInPage]="true"
    [wrapWithCard]="true"
    [items]="templGridItems"
    [selectableItems]="true"
    [itemTemplate]="gridItemRef"
    [type]="GridPresentTypes.AsFlex"
    (itemSelected)="handleGridItemSelected($event)"
  >
  </x-grid>

  <x-markdown
    [mode]="'preview'"
    [content]="sample2"
    [hasToolbar]="false"
    [wrapWithCard]="true"
    [isInPage]="true"
    [cssClass]="'code-block'"
    [cardTitle]="resourceProvider(ResourceIDs.sample)"
  ></x-markdown>

  <x-grid
    [cols]="4"
    [isInPage]="true"
    [wrapWithCard]="true"
    [items]="templGridItems"
    [selectableItems]="true"
    [itemTemplate]="gridItemRef"
    [type]="GridPresentTypes.AsGrid"
    (itemSelected)="handleGridItemSelected($event)"
  >
  </x-grid>
</v-page>

<!-- Grid Item Template -->
<ng-template #gridItemRef let-item>
  <div>
    {{ item.data }}
    <!-- <span>{{ item.data }}</span> -->
  </div>
</ng-template>

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\grid\grid.page.scss


### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\grid\grid.page.ts

import {
  XGridItem,
  XIconNames,
  XGridPresentType,
  defaultGridOptions,
  XStaggedGridOptions,
} from 'x-framework-components';
import { Component } from '@angular/core';
import { VPageComponent } from '../../../views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';
import { XResourceIDs, isNullOrEmptyString, XColor } from 'x-framework-core';

@Component({
  selector: 'app-grid',
  templateUrl: './grid.page.html',
  styleUrls: ['./grid.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class GridPage extends VPageComponent {
  //
  //#region Props ...
  //
  //#region Page Props ...
  titleRes = AppResourceIDs.grid;
  toolbarTitle = this.resourceProvider(this.titleRes);
  toolbarSubTitle = this.resourceProvider(AppResourceIDs.grid_description);
  toolbarShowSubTitle = true;
  //#endregion

  //
  // Prepare All Resource IDs ...
  readonly ResourceIDs = Object.assign(
    Object.assign({}, XResourceIDs),
    AppResourceIDs
  ) as any;

  //
  readonly IconNames = Object.assign({}, XIconNames);
  //#endregion

  //
  // Content ...
  readonly contentFa = `
# ${this.toolbarTitle}
این مولفه نمایش مجموعه ای از عناصر مرتبط با هم بکار می رود.
`;

  readonly contentEn = `
# ${this.toolbarTitle}
this component used to show a collection of related items.
`;

  //
  readonly sample0 =
    '```typescript' +
    `
gridOption: XStaggedGridOptions = {
  ...defaultGridOptions,
};
tempList = Array.from(Array(25).keys());
templGridItems: XGridItem<string>[] = this.tempList.map((i) => {
  //
  const li: XGridItem<string> = {
    data: \`Item \${i.toString()}\`,
  };

  //
  return li;
});
` +
    '```';

  //
  readonly sample1 =
    '```html' +
    `
<x-grid
  [isPageGrid]="true"
  [wrapWithCard]="true"
  [items]="templGridItems"
  [selectableItems]="true"
  [itemTemplate]="gridItemRef"
  [type]="GridPresentTypes.AsFlex"
  (itemSelected)="
    handleGridItemSelected($event)"
>
</x-grid>
` +
    '```';

  readonly sample2 =
    '```html' +
    `
<x-grid
  [cols]="4"
  [isPageGrid]="true"
  [wrapWithCard]="true"
  [items]="templGridItems"
  [selectableItems]="true"
  [itemTemplate]="gridItemRef"
  [type]="GridPresentTypes.AsGrid"
  (itemSelected)="
    handleGridItemSelected($event)"
>
</x-grid>
` +
    '```';

  //
  readonly GridPresentTypes = Object.assign({}, XGridPresentType);

  //
  gridOption: XStaggedGridOptions = {
    ...defaultGridOptions,
  };
  tempList = Array.from(Array(25).keys());
  templGridItems: XGridItem<string>[] = this.tempList.map((i) => {
    //
    const li: XGridItem<string> = {
      data: `Item ${i.toString()}`,
    };

    //
    return li;
  });

  //
  //#region UI Providers ...
  //
  // Provide content based on current locale ...
  getContent(title: string) {
    //
    if (isNullOrEmptyString(title)) {
      return '';
    }

    //
    const currentLocale = this.managerService.currentLocale;

    //
    const varName =
      title +
      (currentLocale === 'en-US'
        ? 'En'
        : currentLocale === 'fa-IR'
        ? 'Fa'
        : '');

    const result = this[`${varName}`];

    //
    return result || '';
  }

  //
  handleGridItemSelected(item: XGridItem<string>) {
    console.log('handleGridItemSelected: ', item.data);
  }
  //#endregion
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\icon\icon.page.html

<v-page
  [hasSide]="true"
  [toolbarTitle]="toolbarTitle"
  [toolbarSubTitle]="toolbarSubTitle"
  [toolbarShowSubTitle]="toolbarShowSubTitle"
>
  <!-- Content -->
  <x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
    <!-- Content -->
    <x-markdown
      [mode]="'preview'"
      [hasToolbar]="false"
      [content]="getContent('content')"
    ></x-markdown>

    <!-- Sample -->
    <x-markdown
      [mode]="'preview'"
      [content]="sample1"
      [hasToolbar]="false"
      [cssClass]="'code-block'"
    ></x-markdown>

    <x-icon
      [foregroundColor]="true"
      [name]="IconNames.blockchain"
      [color]="ColorNames.Success"
    >
    </x-icon>

    <!-- Sample -->
    <x-markdown
      [mode]="'preview'"
      [content]="sample2"
      [hasToolbar]="false"
      [cssClass]="'code-block'"
    ></x-markdown>

    <x-icon
      [clickable]="true"
      [name]="IconNames.blockchain"
      [foregroundColor]="false"
      [color]="ColorNames.Dark"
      (clicked)="managerService.notificationService.presentInfoNotification({
        message: 'icon clicked ...',
        dissmissable: true
      })"
    >
    </x-icon>

    <br />
    <br />

    <x-form
      [fillColor]="ColorNames.Dark"
      [formConfig]="iconListFormConfig"
      [regularColor]="ColorNames.Light"
    ></x-form>

    <!-- Actions -->
    <div actions>
      <a
        target="_blank"
        href="https://docs.x-framework.ir/x-framework-components/components/XIconComponent.html"
        >{{resourceProvider(ResourceIDs.documentation)}}</a
      >
    </div>
  </x-card>

  <!-- Icon List -->
  <x-card
    [isInPage]="true"
    *ngIf="showIconList"
    [title]="resourceProvider(ResourceIDs.icon_list)"
  >
    <!-- Icons List -->
    <x-list
      #listPresenter
      [showToolbar]="true"
      [stickyToolbar]="true"
      [showSearchBar]="true"
      [showActionBar]="false"
      [clickableItems]="true"
      [items]="iconListItems"
      [itemTemplate]="iconTemplate"
      [searchBarColor]="ColorNames.Dark"
      (itemSelected)="handleIconSelected($event)"
      [searchBarSearchInputColor]="ColorNames.Dark"
    >
    </x-list>
  </x-card>
</v-page>

<!-- Icon Template Ref -->
<ng-template #iconTemplate let-item>
  <div class="cb-inherit ion-text-center">
    <x-icon [name]="item.data" [color]="ColorNames.Tertiary"></x-icon>
    {{ item.data }}
  </div>
</ng-template>

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\icon\icon.page.scss


### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\icon\icon.page.ts

import {
  XSpinner,
  hasChild,
  XResourceIDs,
  isNullOrEmptyString,
  XColorWithBrightness,
} from 'x-framework-core';
import {
  XIconNames,
  XListItem,
  XFormConfig,
  XFormControlType,
} from 'x-framework-components';
import { Component } from '@angular/core';
import { VPageComponent } from '../../../views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';

interface IconsListPresentation {
  show: boolean;
}

@Component({
  selector: 'app-icon',
  templateUrl: './icon.page.html',
  styleUrls: ['./icon.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class IconPage extends VPageComponent {
  //
  //#region Props ...
  //
  //#region Page Props ...
  titleRes = AppResourceIDs.icon;
  toolbarTitle = this.resourceProvider(this.titleRes);
  toolbarSubTitle = this.resourceProvider(AppResourceIDs.icon_description);
  toolbarShowSubTitle = true;
  //#endregion

  //
  // Prepare All Resource IDs ...
  readonly ResourceIDs = Object.assign(
    Object.assign({}, XResourceIDs),
    AppResourceIDs
  ) as any;

  //
  // Color Names ...
  readonly ColorNames = Object.assign({}, XColorWithBrightness);

  //
  // Spinner Names ...
  readonly SpinnerNames = Object.assign({}, XSpinner);

  //
  IconNames = Object.assign({}, XIconNames);
  iconList = Object.keys(this.IconNames);
  iconListItems: XListItem<string>[] = [];
  //#endregion

  readonly contentFa = `
  # ${this.toolbarTitle}

  این مولفه جهت نمایش شمایل های مختلف بکار میرود.
  `;
  readonly contentEn = `
  # ${this.toolbarTitle}

  this Component used for show an icon.
  `;

  readonly sample1 =
    '```html' +
    `
<x-icon
  [foregroundColor]="true"
  [name]="IconNames.business"
  [color]="ColorNames.Success"
>
</x-icon>
` +
    '```';

  readonly sample2 =
    '```html' +
    `
<x-icon
  [clickable]="true"
  [name]="IconNames.home"
  [foregroundColor]="false"
  [color]="ColorNames.Dark"
  (clicked)="managerService
    .notificationService
      .presentInfoNotification({
    message: 'icon clicked ...',
    dissmissable: true
  })"
>
</x-icon>
` +
    '```';

  //
  showIconList = false;
  iconListFormConfig: XFormConfig<IconsListPresentation> = {
    name: 'IconListForm',
    controls: [
      {
        index: 5,
        propName: 'show',
        type: {
          type: XFormControlType.CheckBox,
          config: {
            checkedChanged: async (checked: boolean) => {
              //
              if (!hasChild(this.iconListItems)) {
                //
                const loading = await this.managerService.dialogService.presentLoading(
                  {
                    message: this.resourceProvider(
                      AppResourceIDs.default_loading
                    ),
                    spinner: this.SpinnerNames.LinesSmall,
                  }
                );

                //
                await this.prepareIconListItems();

                //
                await loading.dismiss();
              }

              //
              this.showIconList = checked;
            },
          },
        },
        appearance: {
          label: `${this.resourceProvider(
            this.ResourceIDs.show
          )} ${this.resourceProvider(this.ResourceIDs.icon_list)}`,
        },
      },
    ],
  };

  //
  //#region LifeCycle ...
  //#endregion

  //
  //#region UI Providers ...
  //
  // Provide content based on current locale ...
  getContent(title: string) {
    //
    if (isNullOrEmptyString(title)) {
      return '';
    }

    //
    const currentLocale = this.managerService.currentLocale;

    //
    const varName =
      title +
      (currentLocale === 'en-US'
        ? 'En'
        : currentLocale === 'fa-IR'
        ? 'Fa'
        : '');

    const result = this[`${varName}`];

    //
    return result || '';
  }

  canShowIconList() {
    return hasChild(this.iconListItems);
  }
  //#endregion

  //
  //#region UI Handlers ...
  async handleIconSelected(item: XListItem<string>) {
    //
    // text: this.resourceProvider(XResourceIDs.dismiss),
    const iconText = `&lt;x-icon name='${item.data}'&gt;&lt;/x-icon&gt;`;
    const iconCode = `<x-icon name='${item.data}'></x-icon>`;
    await this.managerService.notificationService.presentInfoNotification({
      message: iconText,
      dissmissable: true,
      opt: {
        duration: 4000,
        buttons: [
          {
            icon: this.IconNames.clipboard,
            side: 'end',
            role: 'set',
            handler: () => {
              //
              console.log(iconCode);
              const isSaved = this.managerService.saveToClipboard(iconCode);
              if (isSaved) {
                this.managerService.notificationService.presentDefaultSuccessNotification();
              }
            },
          },
          {
            icon: this.IconNames.close,
            side: 'end',
            role: 'cancel',
          },
        ],
      },
    });
  }
  //#endregion

  //
  //#region Private ...
  private async prepareIconListItems() {
    //
    this.iconListItems = this.iconList.map((i) => {
      //
      const li: XListItem<string> = {
        data: i,
      };

      //
      return li;
    });
    this.detectChanges();
  }
  //#endregion
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\introduction\introduction.page.html

<v-page
  [hasSide]="true"
  [toolbarTitle]="toolbarTitle"
  [toolbarSubTitle]="toolbarSubTitle"
  [toolbarShowSubTitle]="toolbarShowSubTitle"
>
  <!-- Content -->
  <x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
    <!-- Content -->
    <x-markdown
      [mode]="'preview'"
      [hasToolbar]="false"
      [content]="getContent('content')"
    ></x-markdown>

    <!-- Actions -->
    <div actions>
      <a
        target="_blank"
        href="https://docs.x-framework.ir/x-framework-components/index.html"
        >{{resourceProvider(ResourceIDs.documentation)}}</a
      >
    </div>
  </x-card>
</v-page>

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\introduction\introduction.page.scss


### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\introduction\introduction.page.ts

import {
  XResourceIDs,
  isNullOrEmptyString,
  XColorWithBrightness,
} from 'x-framework-core';
import { Component } from '@angular/core';
import { VPageComponent } from '../../../views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';

@Component({
  selector: 'app-components-introduction',
  templateUrl: './introduction.page.html',
  styleUrls: ['./introduction.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class IntroductionPage extends VPageComponent {
  //
  //#region Props ...
  //
  //#region Page Props ...
  titleRes = AppResourceIDs.components_introduction;
  toolbarTitle = this.resourceProvider(this.titleRes);
  toolbarSubTitle = this.resourceProvider(
    AppResourceIDs.components_introduction_description
  );
  toolbarShowSubTitle = true;
  //#endregion

  //
  // Prepare All Resource IDs ...
  readonly ResourceIDs = Object.assign(
    Object.assign({}, XResourceIDs),
    AppResourceIDs
  ) as any;

  //
  // Color Names ...
  readonly ColorNames = Object.assign({}, XColorWithBrightness);
  //#endregion

  //
  // Content ...
  readonly contentFa = `
  # ${this.toolbarTitle}

این واحد در زمره اصلی ترین اجزاء چارچوب ایفای نقش می کند و شامل کلیه مولفه های بصری قابل استفاده در طراحی و پیاده سازی برنامه های کاربردی است.

شناخت عمیق کلیه اجزاء این واحد در تسریع فرآیند توسعه بسیار لازم و ضروری است.
  `;

  readonly contentEn = `
  # ${this.toolbarTitle}

this module is one of most important modules of xFramework and contains all provided UI Components which used to design and develop Applications.

getting deep dive into all components of this module is very usefull to make easier the Design and Develop proccess of Applications.
  `;
  //#endregion

  //
  // Provide content based on current locale ...
  getContent(title: string) {
    //
    if (isNullOrEmptyString(title)) {
      return '';
    }

    //
    const currentLocale = this.managerService.currentLocale;

    //
    const varName =
      title +
      (currentLocale === 'en-US'
        ? 'En'
        : currentLocale === 'fa-IR'
        ? 'Fa'
        : '');

    const result = this[`${varName}`];

    //
    return result || '';
  }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\list\list.page.html

<v-page
  [hasSide]="true"
  [toolbarTitle]="toolbarTitle"
  [toolbarSubTitle]="toolbarSubTitle"
  [toolbarShowSubTitle]="toolbarShowSubTitle"
>
  <!-- Content -->
  <x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
    <!-- Content -->
    <x-markdown
      [mode]="'preview'"
      [hasToolbar]="false"
      [content]="getContent('content')"
    ></x-markdown>

    <!-- Samples -->
    <x-markdown
      [mode]="'preview'"
      [content]="sample1"
      [hasToolbar]="false"
      [cssClass]="'code-block'"
    ></x-markdown>
    <x-markdown
      [mode]="'preview'"
      [content]="sample2"
      [hasToolbar]="false"
      [cssClass]="'code-block'"
    ></x-markdown>
    <x-markdown
      [mode]="'preview'"
      [content]="sample3"
      [hasToolbar]="false"
      [cssClass]="'code-block'"
    ></x-markdown>

    <!-- List Presenter -->
    <x-list
      #listPresenter
      [showToolbar]="true"
      [stickyToolbar]="true"
      [showActionBar]="true"
      [showSearchBar]="true"
      [showDivider]="false"
      [clickableItems]="true"
      [selectableItems]="true"
      [items]="templListItems"
      [enableReordering]="true"
      [itemTemplate]="listItemRef"
      [color]="ColorNames.Tertiary"
      (refresh)="handleRefreshList()"
      [actionBarColor]="ColorNames.Dark"
      [searchBarColor]="ColorNames.Dark"
      [actionBarHideActions]="hideActions"
      (removeItems)="handleRemoveItems($event)"
      [searchBarSearchInputColor]="ColorNames.Dark"
    >
    </x-list>

    <!-- Actions -->
    <div actions>
      <a
        target="_blank"
        href="https://docs.x-framework.ir/x-framework-components/modules/XListModule.html"
        >{{resourceProvider(ResourceIDs.documentation)}}</a
      >
    </div>
  </x-card>
</v-page>

<!-- List Item Template -->
<ng-template #listItemRef let-item>
  <span>{{item.data}}</span>
</ng-template>

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\list\list.page.scss


### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\list\list.page.ts

import {
  XColor,
  XResourceIDs,
  isNullOrEmptyString,
  XBaseRangeRequestDto,
  XStandardType,
  XOneOrManyType,
} from 'x-framework-core';
import { Component } from '@angular/core';
import { XListItem, XIconNames } from 'x-framework-components';
import { VPageComponent } from '../../../views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';

@Component({
  selector: 'app-list',
  templateUrl: './list.page.html',
  styleUrls: ['./list.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class ListPage extends VPageComponent {
  //
  //#region Props ...
  //
  //#region Page Props ...
  titleRes = AppResourceIDs.list;
  toolbarTitle = this.resourceProvider(this.titleRes);
  toolbarSubTitle = this.resourceProvider(AppResourceIDs.list_description);
  toolbarShowSubTitle = true;
  //#endregion

  //
  // Prepare All Resource IDs ...
  readonly ResourceIDs = Object.assign(
    Object.assign({}, XResourceIDs),
    AppResourceIDs
  ) as any;

  //
  readonly IconNames = Object.assign({}, XIconNames);
  //#endregion

  //
  // Content ...
  readonly contentFa = `
  # ${this.toolbarTitle}
  این مولفه جهت نمایش فهرستی از موارد و فراهم کردن ابزار مدیریت آن بکار می رود.
  `;

  readonly contentEn = `
  # ${this.toolbarTitle}
  this component used to provide a way to show items in a list and manage items.
  `;

  //
  readonly sample1 =
    '```typescript' +
    `
tempList = Array
  .from(Array(25).keys());

templListItems: XListItem<string>[] =
  this.tempList.map((i) => {
    const li: XListItem<string> = {
      data: \`Item \${i.toString()}\`,
      slideOptions: [
        {
          id: 'remove',
          icon: this.IconNames.remove,
          color: this.ColorNames.Danger,
          onlyIcon: true,
          slot: 'end',
          handler: () => {
            //
            this.managerService
              .notificationService
              .presentDangerNotification({
                message: \`remove: \${i}\`,
                dissmissable: true,
            });
          },
        },
        {
          id: 'edit',
          icon: this.IconNames.edit,
          color: this.ColorNames.Warning,
          onlyIcon: true,
          slot: 'start',
          handler: () => {
            //
            this.managerService
              .notificationService
              .presentInfoNotification({
                message: \`edit: \${i}\`,
                dissmissable: true,
            });
          },
        },
      ],
  };

  return li;
});
` +
    '```';

  //
  readonly sample2 =
    '```html' +
    `
<x-list
  #listPresenter
  [showToolbar]="true"
  [stickyToolbar]="true"
  [showActionBar]="true"
  [showSearchBar]="true"
  [showDivider]="false"
  [clickableItems]="true"
  [selectableItems]="true"
  [items]="templListItems"
  [enableReordering]="true"
  [itemTemplate]="listItemRef"
  [color]="ColorNames.Tertiary"
  (refresh)="handleRefreshList()"
  [actionBarColor]="ColorNames.Dark"
  [searchBarColor]="ColorNames.Dark"
  [searchBarInputColor]="ColorNames.Dark"
  (removeItems)="handleRemoveItems($event)"
>
</x-list>
` +
    '```';

  readonly sample3 =
    '```typescript' +
    `
handleRefreshList() {
  this.prepareListItems();
}

handleRemoveItems(request:
    XBaseRangeRequestDto<string>) {
  //
  this.templListItems = this
    .templListItems.filter(
      (li) => !request.items
        .includes(li.data)
  );
}

private prepareListItems() {
  this.templListItems = this
    .tempList.map((i) => {
    //
    const li: XListItem<string> = {
      data: \`Item $\{i.toString()}\`,
      slideOptions: [
        {
          id: 'remove',
          icon: this.IconNames.remove,
          color: this.ColorNames.Danger,
          onlyIcon: true,
          slot: 'end',
          handler: () => {
            //
            this.managerService
              .notificationService
              .presentDangerNotification({
                message: \`remove: \${i}\`,
                dissmissable: true,
            });
          },
        },
        {
          id: 'edit',
          icon: this.IconNames.edit,
          color: this.ColorNames.Warning,
          onlyIcon: true,
          slot: 'start',
          handler: () => {
            //
            this.managerService
              .notificationService
              .presentInfoNotification({
                message: \`edit: \${i}\`,
                dissmissable: true,
            });
          },
        },
      ],
    };

    //
    return li;
  });
}
` +
    '```';

  //
  tempList = Array.from(Array(25).keys());
  templListItems: XListItem<string>[] = this.tempList.map((i) => {
    //
    const li: XListItem<string> = {
      data: `Item ${i.toString()}`,
      slideOptions: [
        {
          id: 'remove',
          icon: this.IconNames.remove,
          color: this.ColorNames.Danger,
          onlyIcon: true,
          slot: 'end',
          handler: () => {
            //
            this.managerService.dialogService.presentAreYouSureYesNoDialog(
              () => {
                this.handleRemoveItems({ items: [li.data] });
              }
            );
          },
        },
        {
          id: 'edit',
          icon: this.IconNames.edit,
          color: this.ColorNames.Warning,
          onlyIcon: true,
          slot: 'start',
          handler: () => {
            //
            this.managerService.notificationService.presentInfoNotification({
              message: `edit: ${i}`,
              dissmissable: true,
            });
          },
        },
      ],
    };

    //
    return li;
  });

  //
  hideActions: XStandardType<XOneOrManyType<string>> = []; // [DefaultActionBarItemIds.Remove];

  //
  //#region UI Providers ...
  //
  // Provide content based on current locale ...
  getContent(title: string) {
    //
    if (isNullOrEmptyString(title)) {
      return '';
    }

    //
    const currentLocale = this.managerService.currentLocale;

    //
    const varName =
      title +
      (currentLocale === 'en-US'
        ? 'En'
        : currentLocale === 'fa-IR'
        ? 'Fa'
        : '');

    const result = this[`${varName}`];

    //
    return result || '';
  }
  //#endregion

  //
  //#region UI Handlers ...
  //
  handleRefreshList() {
    this.prepareListItems();
  }

  //
  handleRemoveItems(request: XBaseRangeRequestDto<string>) {
    //
    this.templListItems = this.templListItems.filter(
      (li) => !request.items.includes(li.data)
    );

    //
    this.managerService.notificationService.presentSuccessNotification({
      message: `${request.items.length} item(s) removed ...`,
      dissmissable: true,
    });
  }
  //#endregion

  //
  //#region Private ...
  //
  private prepareListItems() {
    this.templListItems = this.tempList.map((i) => {
      //
      const li: XListItem<string> = {
        data: `Item ${i.toString()}`,
        slideOptions: [
          {
            id: 'remove',
            icon: this.IconNames.remove,
            color: this.ColorNames.Danger,
            onlyIcon: true,
            slot: 'end',
            handler: () => {
              //
              this.managerService.notificationService.presentDangerNotification(
                {
                  message: `remove: ${i}`,
                  dissmissable: true,
                }
              );
            },
          },
          {
            id: 'edit',
            icon: this.IconNames.edit,
            color: this.ColorNames.Warning,
            onlyIcon: true,
            slot: 'start',
            handler: () => {
              //
              this.managerService.notificationService.presentInfoNotification({
                message: `edit: ${i}`,
                dissmissable: true,
              });
            },
          },
        ],
      };

      //
      return li;
    });
  }
  //#endregion
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\map\map.page.html

<v-page
  [hasSide]="true"
  [toolbarTitle]="toolbarTitle"
  [toolbarSubTitle]="toolbarSubTitle"
  [toolbarShowSubTitle]="toolbarShowSubTitle"
>
  <!-- Content -->
  <x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
    <!-- Content -->
    <x-markdown
      [mode]="'preview'"
      [hasToolbar]="false"
      [content]="getContent('content')"
    ></x-markdown>

    <!-- <x-markdown
      [mode]="'preview'"
      [content]="sample1"
      [hasToolbar]="false"
      [cssClass]="'code-block'"
    ></x-markdown> -->

    <!-- Map -->
    <x-map
      #xMap
      [zoom]="14"
      [isInPage]="true"
      [canSelect]="false"
      [wrapWithCard]="false"
      [latitude]="35.814738589583044"
      [longitude]="50.97853161365292"
      [actionProvider]="mapActionProvider"
      [searchBarColor]="ColorNames.Primary"
      [searchBarSearchInputColor]="ColorNames.Primary"
    ></x-map>

    <!-- Center -->
    <x-button
      [title]="'Set Center'"
      [type]="ButtonTypes.Icon"
      [icon]="IconNames.map"
      (clicked)="handleSetCenter()"
    ></x-button>

    <!-- Zoom -->
    <x-button
      [title]="'Set Zoom'"
      [type]="ButtonTypes.Icon"
      [icon]="IconNames.search"
      (clicked)="handleSetZoom()"
    ></x-button>

    <!-- AddMarker -->
    <x-button
      [title]="'Add Marker'"
      [type]="ButtonTypes.Icon"
      [icon]="IconNames.add"
      (clicked)="handleAddMarker()"
    ></x-button>

    <!-- ClearMarker -->
    <x-button
      [title]="'Clear Marker'"
      [type]="ButtonTypes.Icon"
      [icon]="IconNames.clear"
      (clicked)="handleClearMarker()"
    ></x-button>

    <!-- GoMarkedPlace -->
    <x-button
      [title]="'Go Marked Place'"
      [type]="ButtonTypes.Icon"
      [icon]="IconNames.refresh"
      (clicked)="handleGoMarkedPlace()"
    ></x-button>

    <!-- Locate -->
    <x-button
      [title]="'Locate'"
      [type]="ButtonTypes.Icon"
      [icon]="IconNames.locate"
      (clicked)="handleLocate()"
    ></x-button>

    <!-- MapDialog -->
    <x-button
      [title]="'Map Dialog'"
      [icon]="IconNames.map"
      [type]="ButtonTypes.Raised"
      (clicked)="handleMapDialog()"
    ></x-button>

    <!-- Actions -->
    <div actions>
      <a
        target="_blank"
        href="https://docs.x-framework.ir/x-framework-components/components/XMapComponent.html"
        >{{resourceProvider(AppResourceIDs.documentation)}}</a
      >
    </div>
  </x-card>
</v-page>

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\map\map.page.scss

x-map {
    --map-height: 500px;
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\map\map.page.ts

import {
  Inject,
  NgZone,
  Component,
  Renderer2,
  ElementRef,
  ChangeDetectorRef,
} from '@angular/core';
import { Subject } from 'rxjs';
import {
  XIconNames,
  XMapAction,
  XButtonType,
  XMapLocation,
  XMapComponent,
  XPageContainer,
  XMapActionModel,
  XPopoverService,
  XMapDialogService,
} from 'x-framework-components';
import { MenuController } from '@ionic/angular';
import { X_CONFIG } from 'src/app/config/x-config';
import { XConfig } from 'src/app/config/app-config';
import { ViewportRuler } from '@angular/cdk/overlay';
import { XManagerService } from 'x-framework-services';
import { XDialogResult, isNullOrEmptyString } from 'x-framework-core';
import { VPageComponent } from '../../../views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';

@Component({
  selector: 'app-map',
  templateUrl: './map.page.html',
  styleUrls: ['./map.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class MapPage extends VPageComponent {
  //
  //#region Props ...
  //
  //#region Page Props ...
  titleRes = AppResourceIDs.map;
  toolbarTitle = this.resourceProvider(this.titleRes);
  toolbarSubTitle = this.resourceProvider(AppResourceIDs.map_description);
  toolbarShowSubTitle = true;
  //#endregion

  //
  readonly IconNames = Object.assign({}, XIconNames);
  readonly ButtonTypes = Object.assign({}, XButtonType);
  readonly mapActionProvider = new Subject<XMapActionModel>();
  //#endregion

  //
  //#region Constructor ...
  public constructor(
    public zone: NgZone,
    @Inject(X_CONFIG)
    public config: XConfig,
    public element: ElementRef,
    public renderer: Renderer2,
    public ruler: ViewportRuler,
    public menuController: MenuController,
    public managerService: XManagerService,
    public changeDetector: ChangeDetectorRef,
    protected popoverService: XPopoverService, 
    protected propertyProvider: XPageContainer,
    public mapDialogService: XMapDialogService
  ) {
    super(
      zone,
      config,
      element,
      renderer,
      ruler,
      menuController,
      managerService,
      changeDetector,
      popoverService,
      propertyProvider
    );
  }
  //#endregion

  //
  // Content ...
  readonly contentFa = `
  # ${this.toolbarTitle}
  این مولفه جهت نمایش نقشه و مکان یابی بکار می رود
  `;

  readonly contentEn = `
  # ${this.toolbarTitle}
  this component used to show map and locating map.
  `;

  //
  readonly sample1 =
    '```html' +
    `
<x-map
  [zoom]="8"
  [showZoom]="true"
  [latitude]="35.84"
  [showRotate]="true"
  [showLocate]="true"
  [longitude]="50.9391"
  [showSearchBar]="true"
  [showZoomSlider]="false"
  [locateAfterInit]="true"
  [showClearMarker]="true"
  [showGoMarkedPlace]="true"
  style="--map-height: 300px;"
  [searchBarColor]="
    ColorNames.Tertiary"
  [searchResultListColor]="
    ColorNames.Primary"
></x-map>
` +
    '```';

  //
  //#region UI Providers ...
  //
  // Provide content based on current locale ...
  getContent(title: string) {
    //
    if (isNullOrEmptyString(title)) {
      return '';
    }

    //
    const currentLocale = this.managerService.currentLocale;

    //
    const varName =
      title +
      (currentLocale === 'en-US'
        ? 'En'
        : currentLocale === 'fa-IR'
        ? 'Fa'
        : '');

    const result = this[`${varName}`];

    //
    return result || '';
  }
  //#endregion

  //
  //#region UI Handlers ...
  async handleSetZoom(map?: XMapComponent) {
    //
    if (map) {
      //
      await map.setZoom(12);
      return;
    }

    //
    this.mapActionProvider.next({
      action: XMapAction.SetZoom,
      payload: 12,
    });
  }

  async handleSetCenter(map?: XMapComponent) {
    //
    if (map) {
      //
      await map.setCenter(35, 35, 6);
      return;
    }

    //
    this.mapActionProvider.next({
      action: XMapAction.SetCenter,
      payload: {
        zoom: '6',
        latitude: '35',
        longitude: '35',
      } as XMapLocation,
    });
  }

  async handleAddMarker(map?: XMapComponent) {
    //
    if (map) {
      //
      await map.addMarker(35, 35);
      return;
    }

    //
    this.mapActionProvider.next({
      action: XMapAction.AddMarker,
      payload: {
        latitude: '35',
        longitude: '35',
      } as XMapLocation,
    });
  }

  async handleClearMarker(map?: XMapComponent) {
    //
    if (map) {
      //
      await map.clearMarker();
      return;
    }

    //
    this.mapActionProvider.next({
      action: XMapAction.ClearMarker,
    });
  }

  async handleGoMarkedPlace(map?: XMapComponent) {
    //
    if (map) {
      //
      await map.goMarkedPlace();
      return;
    }

    //
    this.mapActionProvider.next({
      action: XMapAction.GoMarkedPlace,
    });
  }

  async handleLocate(map?: XMapComponent) {
    //
    if (map) {
      //
      await map.locate();
      return;
    }

    //
    this.mapActionProvider.next({
      action: XMapAction.Locate,
    });
  }

  async handleMapDialog() {
    //
    this.mapDialogService.openDialog({
      latitude: 35.814738589583044,
      longitude: 50.97853161365292,
      zoom: 14,
    });

    //
    const resSubscription = this.mapDialogService.onResult.subscribe(
      (result) => {
        //
        if (!result || result.result !== XDialogResult.Ok) {
          //
          console.log('empty result');
          resSubscription.unsubscribe();
          return;
        }

        //
        console.log('selected Location: ', result.payload);
        resSubscription.unsubscribe();
      }
    );
  }
  //#endregion
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\markdown\markdown.page.html

<v-page
  [hasSide]="true"
  [toolbarTitle]="toolbarTitle"
  [toolbarSubTitle]="toolbarSubTitle"
  [toolbarShowSubTitle]="toolbarShowSubTitle"
>
  <!-- Content -->
  <x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
    <!-- Content -->
    <x-markdown
      [hasToolbar]="false"
      [mode]="MarkdownModes.PREVIEW"
      [content]="getContent('content')"
    ></x-markdown>

    <!-- Actions -->
    <div actions>
      <a
        target="_blank"
        href="https://docs.x-framework.ir/x-framework-components/components/XMarkdownComponent.html"
        >{{resourceProvider(ResourceIDs.documentation)}}</a
      >
    </div>
  </x-card>

  <!-- Samples -->
  <x-markdown
    [isInPage]="true"
    [content]="sample1"
    [hasToolbar]="false"
    [wrapWithCard]="true"
    [cssClass]="'code-block'"
    [mode]="MarkdownModes.PREVIEW"
    [cardTitle]="resourceProvider(ResourceIDs.sample)"
  ></x-markdown>

  <!-- Components -->
  <x-markdown
    [isInPage]="true"
    [wrapWithCard]="true"
    [mode]="MarkdownModes.BOTH"
    [(content)]="sampleContent1"
    [toolbarColor]="ColorNames.Dark"
  ></x-markdown>

  <!-- Samples -->
  <x-markdown
    [isInPage]="true"
    [content]="sample2"
    [hasToolbar]="false"
    [wrapWithCard]="true"
    [cssClass]="'code-block'"
    [mode]="MarkdownModes.PREVIEW"
    [cardTitle]="resourceProvider(ResourceIDs.sample)"
  ></x-markdown>

  <!-- Components -->
  <x-markdown
    [isInPage]="true"
    [hasToolbar]="false"
    [wrapWithCard]="true"
    [content]="sampleContent2"
    [mode]="MarkdownModes.PREVIEW"
  ></x-markdown>
</v-page>

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\markdown\markdown.page.scss


### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\markdown\markdown.page.ts

import { Component } from '@angular/core';
import { XIconNames } from 'x-framework-components';
import { XMarkdownMode } from 'x-framework-components';
import { VPageComponent } from '../../../views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';
import { XResourceIDs, isNullOrEmptyString, XColor } from 'x-framework-core';

@Component({
  selector: 'app-markdown',
  templateUrl: './markdown.page.html',
  styleUrls: ['./markdown.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class MarkdownPage extends VPageComponent {
  //
  //#region Props ...
  //
  //#region Page Props ...
  titleRes = AppResourceIDs.markdown;
  toolbarTitle = this.resourceProvider(this.titleRes);
  toolbarSubTitle = this.resourceProvider(AppResourceIDs.markdown_description);
  toolbarShowSubTitle = true;
  //#endregion

  //
  // Prepare All Resource IDs ...
  readonly ResourceIDs = Object.assign(
    Object.assign({}, XResourceIDs),
    AppResourceIDs
  ) as any;

  //
  readonly IconNames = Object.assign({}, XIconNames);
  //#endregion

  //
  readonly MarkdownModes = Object.assign({}, XMarkdownMode);

  //
  // Content ...
  readonly contentFa = `
  # ${this.toolbarTitle}
  این مولفه جهت دریافت و نمایش اطلاعات مبتنی بر شیوه نشانه گذاری داده ها موسوم به مارک داون (MarkDown) کاربرد دارد.
  `;

  readonly contentEn = `
  # ${this.toolbarTitle}
  this component used to get and show MarkDown based Data's.
  `;

  //
  readonly sample1 =
    '```html' +
    `
<x-markdown
  [mode]="MarkdownModes.BOTH"
  [(content)]="sampleContent1"
  [toolbarColor]="ColorNames.Dark"
></x-markdown>
` +
    '```';
  readonly sample2 =
    '```html' +
    `
<x-markdown
  [hasToolbar]="false"
  [content]="sampleContent2"
  [mode]="MarkdownModes.PREVIEW"
></x-markdown>
` +
    '```';

  //
  sampleContent1 = `
  ## Todo example

  - Variable binding
  - Code refactor
  - Write more unit tests
  - Module configuration for markdown settings
  - Module configuration for prismjs settings
  `;

  readonly sampleContent2 = `
  ## Todo example
  this is only a preview sample of markdown.
  `;

  //
  //#region UI Providers ...
  //
  // Provide content based on current locale ...
  getContent(title: string) {
    //
    if (isNullOrEmptyString(title)) {
      return '';
    }

    //
    const currentLocale = this.managerService.currentLocale;

    //
    const varName =
      title +
      (currentLocale === 'en-US'
        ? 'En'
        : currentLocale === 'fa-IR'
        ? 'Fa'
        : '');

    const result = this[`${varName}`];

    //
    return result || '';
  }
  //#endregion
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\model-presenter\model-presenter.page.html

<v-page
  [hasSide]="true"
  [toolbarTitle]="toolbarTitle"
  [toolbarSubTitle]="toolbarSubTitle"
  [toolbarShowSubTitle]="toolbarShowSubTitle"
>
  <!-- Content -->
  <x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
    <!-- Content -->
    <x-markdown
      [hasToolbar]="false"
      [mode]="MarkdownModes.PREVIEW"
      [content]="getContent('content')"
    ></x-markdown>

    <!-- Actions -->
    <div actions>
      <a
        target="_blank"
        href="https://docs.x-framework.ir/x-framework-components/components/XModelPresenter.html"
        >{{resourceProvider(ResourceIDs.documentation)}}</a
      >
    </div>
  </x-card>

  <!-- Samples -->
  <x-markdown
    [isInPage]="true"
    [content]="sample1"
    [hasToolbar]="false"
    [wrapWithCard]="true"
    [cssClass]="'code-block'"
    [mode]="MarkdownModes.PREVIEW"
    [cardTitle]="resourceProvider(ResourceIDs.sample)"
  ></x-markdown>

  <!-- Samples -->
  <x-markdown
    [isInPage]="true"
    [content]="sample2"
    [hasToolbar]="false"
    [wrapWithCard]="true"
    [cssClass]="'code-block'"
    [mode]="MarkdownModes.PREVIEW"
  ></x-markdown>

  <!-- Samples -->
  <x-markdown
    [isInPage]="true"
    [content]="sample3"
    [hasToolbar]="false"
    [wrapWithCard]="true"
    [cssClass]="'code-block'"
    [mode]="MarkdownModes.PREVIEW"
  ></x-markdown>

  <!-- Samples -->
  <x-markdown
    [isInPage]="true"
    [content]="sample4"
    [hasToolbar]="false"
    [wrapWithCard]="true"
    [cssClass]="'code-block'"
    [mode]="MarkdownModes.PREVIEW"
  ></x-markdown>

  <!-- Samples -->
  <x-markdown
    [isInPage]="true"
    [content]="sample5"
    [hasToolbar]="false"
    [wrapWithCard]="true"
    [cssClass]="'code-block'"
    [mode]="MarkdownModes.PREVIEW"
  ></x-markdown>

  <!-- Components -->
  <x-model-presenter
    class="v-card"
    [isInPage]="true"
    [model]="dataModel"
    [wrapWithCard]="true"
    [color]="ColorNames.Light"
    [cardTitle]="'Object Editor'"
    [cardColor]="ColorNames.Light"
    [valueColor]="ColorNames.Dark"
    [startupState]="'collapse-all'"
    [headerColor]="ColorNames.Light"
    [actionProvider]="actionProvider"
    [hiddenModelKeys]="hiddenModelKeys"
    [modelKeyProvider]="modelKeyProvider"
    [labelColor]="ColorNames.TertiaryShade"
    [availableModelKeys]="availableModelKeys"
    [sortOrderModelKeys]="sortOrederModelKeys"
    [propertyActionTemplate]="propertyActionRef"
    [hiddenLabelModelKeys]="hiddenLabelModelKeys"
    (onModelChanged)="handleModelChanged($event)"
    [headerHighlightColor]="ColorNames.WarningTint"
  ></x-model-presenter>
</v-page>

<!-- Property Action Template -->
<ng-template
  #propertyActionRef
  let-key="key"
  let-prefix="prefix"
  let-value="value"
>
  <!-- is Small Screen -->
  <ng-container *ngIf="isMobileUi$ | async">
    <!-- Property Selector -->
    <x-icon
      [clickable]="true"
      [foregroundColor]="true"
      [color]="ColorNames.Dark"
      [name]="IconNames.menu_vertical"
      (clicked)="handlePropertyActionMenuClicked(key, prefix, value)"
    ></x-icon>
  </ng-container>

  <!-- is Big Screen -->
  <ng-container *ngIf="isNotMobileUi$ | async">
    <!-- Property Selector -->
    <x-icon
      [clickable]="true"
      [foregroundColor]="true"
      [name]="IconNames.edit"
      (clicked)="handlePropertyEdit(key, prefix, value)"
      [color]="(notNullOrUndefinedValue(value) | async) ? ColorNames.Tertiary : ColorNames.Danger"
    ></x-icon>

    <!-- Property Clear -->
    <x-icon
      [clickable]="true"
      [foregroundColor]="true"
      [name]="IconNames.clear"
      [color]="ColorNames.Danger"
      [uiDisabled]="nullOrUndefinedValue(value) | async"
      (clicked)="handlePropertyClear(key, prefix, value)"
    ></x-icon>
  </ng-container>
</ng-template>

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\model-presenter\model-presenter.page.scss


### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\model-presenter\model-presenter.page.ts

import {
  nameof,
  assign,
  XParam,
  isFunction,
  XResourceIDs,
  XModelProperty,
  XModalButtonRole,
  XModelKeyProvider,
  isNullOrUndefined,
  isNullOrEmptyString,
} from 'x-framework-core';
import { Subject } from 'rxjs';
import {
  XListItem,
  XIconNames,
  XPopoverComponent,
  XListItemSlideOption,
  XModelPresenterAction,
  XModelPresenterActionModel,
} from 'x-framework-components';
import { Component } from '@angular/core';
import { XMarkdownMode } from 'x-framework-components';
import { VPageComponent } from '../../../views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';

export interface DataMODEL {
  firstName: string;
  lastName: string;
  email: string;
  contacts: Array<{
    type: 'mobile' | 'phone';
    title: string;
    number: string;
  }>;
  checkList: {
    todo1: boolean;
    todo2: boolean;
    todo3: boolean;
    todo4: Array<{
      action: string;
      dueData: Date;
    }>;
  };
}

@Component({
  selector: 'app-model-presenter',
  templateUrl: './model-presenter.page.html',
  styleUrls: ['./model-presenter.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class ModelPresenterPage extends VPageComponent {
  //
  //#region Props ...
  //
  //#region Page Props ...
  titleRes = AppResourceIDs.model_presenter;
  toolbarTitle = this.resourceProvider(this.titleRes);
  toolbarSubTitle = this.resourceProvider(
    AppResourceIDs.model_presenter_description
  );
  toolbarShowSubTitle = true;
  //#endregion

  //
  // Prepare All Resource IDs ...
  readonly ResourceIDs = Object.assign(
    Object.assign({}, XResourceIDs),
    AppResourceIDs
  ) as any;

  //
  readonly IconNames = Object.assign({}, XIconNames);
  //#endregion

  //
  readonly MarkdownModes = Object.assign({}, XMarkdownMode);

  //
  //#region Model Presenter ...
  dataModel: DataMODEL = {
    firstName: 'Hadi',
    lastName: 'Khazaee Asl',
    email: 'hadi_khazaee_asl@yahoo.com',
    contacts: [
      {
        type: 'mobile',
        title: 'Personal',
        number: '09121694056',
      },
      {
        type: 'phone',
        title: 'saherelm office',
        number: '02632757987',
      },
    ],
    checkList: {
      todo1: true,
      todo2: false,
      todo3: true,
      todo4: [
        {
          action: 'start',
          dueData: new Date(),
        },
        {
          action: 'end',
          dueData: new Date(),
        },
      ],
    },
  };

  actionProvider = new Subject<XModelPresenterActionModel>();

  availableModelKeys: string[] = [
    nameof<DataMODEL>('lastName'),
    nameof<DataMODEL>('firstName'),
    nameof<DataMODEL>('email'),
    nameof<DataMODEL>('contacts'),
    nameof<DataMODEL>('checkList'),

    //
    // Contacts ...
    // `${nameof<DataMODEL>('contacts')}.type`,
    `${nameof<DataMODEL>('contacts')}.title`,
    // `${nameof<DataMODEL>('contacts')}.number`,

    //
    // Checklist ...
    `${nameof<DataMODEL>('checkList')}.todo1`,
    `${nameof<DataMODEL>('checkList')}.todo2`,
    `${nameof<DataMODEL>('checkList')}.todo3`,
    `${nameof<DataMODEL>('checkList')}.todo4`,

    //
    `${nameof<DataMODEL>('checkList')}.todo4.action`,
    `${nameof<DataMODEL>('checkList')}.todo4.dueData`,
  ];

  hiddenModelKeys: string[] = [`${nameof<DataMODEL>('contacts')}.type`];

  hiddenLabelModelKeys: string[] = [`${nameof<DataMODEL>('contacts')}.number`];

  //
  sortOrederModelKeys: string[] = [
    nameof<DataMODEL>('firstName'),
    nameof<DataMODEL>('lastName'),
    nameof<DataMODEL>('email'),
    nameof<DataMODEL>('contacts'),
    nameof<DataMODEL>('checkList'),

    //
    // Contacts ...
    `${nameof<DataMODEL>('contacts')}.number`,
    `${nameof<DataMODEL>('contacts')}.title`,

    //
    // Checklist ...
    `${nameof<DataMODEL>('checkList')}.todo4.dueData`,
    `${nameof<DataMODEL>('checkList')}.todo4.action`,
  ];

  //
  modelKeyProvider: XModelKeyProvider<any> = (key) => {
    //
    let result = key as string;

    //
    switch (key) {
      //
      case nameof<DataMODEL>('firstName'):
        result = this.resourceProvider(this.AppResourceIDs.first_name);
        break;

      //
      case nameof<DataMODEL>('lastName'):
        result = this.resourceProvider(this.AppResourceIDs.last_name);
        break;

      //
      case nameof<DataMODEL>('contacts'):
        result = this.resourceProvider(this.AppResourceIDs.content);
        break;

      //
      default:
        result = key as string;
        break;
    }

    //
    return result;
  };
  //#endregion

  //
  // Content ...
  readonly contentFa = `
  # ${this.toolbarTitle}
  این مولفه جهت نمایش و ویرایش یک شی یا مدل در نمایی ساختار یافته بکار می رود.
  `;

  readonly contentEn = `
  # ${this.toolbarTitle}
  this component used to view and edit data models in an structural view.
  `;

  //
  readonly sample1 =
    '```html' +
    `
<x-model-presenter
    class="v-card"
    [isInPage]="true"
    [model]="dataModel"
    [wrapWithCard]="true"
    [color]="ColorNames.Light"
    [cardTitle]="'Object Editor'"
    [cardColor]="ColorNames.Light"
    [valueColor]="ColorNames.Dark"
    [startupState]="'collapse-all'"
    [headerColor]="ColorNames.Light"
    [actionProvider]="actionProvider"
    [hiddenModelKeys]="hiddenModelKeys"
    [modelKeyProvider]="modelKeyProvider"
    [labelColor]="ColorNames.TertiaryShade"
    [availableModelKeys]="availableModelKeys"
    [sortOrderModelKeys]="sortOrederModelKeys"
    [propertyActionTemplate]="propertyActionRef"
    [hiddenLabelModelKeys]="hiddenLabelModelKeys"
    (onModelChanged)="handleModelChanged($event)"
    [headerHighlightColor]="ColorNames.WarningTint"
></x-model-presenter>
` +
    '```';

  readonly sample2 =
    '```html' +
    `
<!-- Property Action Template -->
<ng-template
    #propertyActionRef
    let-key="key"
    let-prefix="prefix"
    let-value="value"
>
    <!-- is Small Screen -->
    <ng-container *ngIf="isMobileUi$ | async">
    <!-- Property Selector -->
    <x-icon
        [clickable]="true"
        [foregroundColor]="true"
        [color]="ColorNames.Dark"
        [name]="IconNames.menu_vertical"
        (clicked)="handlePropertyActionMenuClicked(key, prefix, value)"
    ></x-icon>
    </ng-container>

    <!-- is Big Screen -->
    <ng-container *ngIf="isNotMobileUi$ | async">
    <!-- Property Selector -->
    <x-icon
        [clickable]="true"
        [foregroundColor]="true"
        [name]="IconNames.edit"
        (clicked)="handlePropertyEdit(key, prefix, value)"
        [color]="(notNullOrUndefinedValue(value) | async) ? ColorNames.Tertiary : ColorNames.Danger"
    ></x-icon>

    <!-- Property Clear -->
    <x-icon
        [clickable]="true"
        [foregroundColor]="true"
        [name]="IconNames.clear"
        [color]="ColorNames.Danger"
        [uiDisabled]="nullOrUndefinedValue(value) | async"
        (clicked)="handlePropertyClear(key, prefix, value)"
    ></x-icon>
    </ng-container>
</ng-template>      
  ` +
    '```';

  readonly sample3 =
    '```javascript' +
    `
export interface DataMODEL {
    firstName: string;
    lastName: string;
    email: string;
    contacts: Array<{
        type: 'mobile' | 'phone';
        title: string;
        number: string;
    }>;
    checkList: {
        todo1: boolean;
        todo2: boolean;
        todo3: boolean;
        todo4: Array<{
        action: string;
        dueData: Date;
        }>;
    };
}    
  ` +
    '```';

  readonly sample4 =
    '```javascript' +
    `
dataModel: DataMODEL = {
    firstName: 'Hadi',
    lastName: 'Khazaee Asl',
    email: 'hadi_khazaee_asl@yahoo.com',
    contacts: [
        {
        type: 'mobile',
        title: 'Personal',
        number: '09121694056',
        },
        {
        type: 'phone',
        title: 'saherelm office',
        number: '02632757987',
        },
    ],
    checkList: {
        todo1: true,
        todo2: false,
        todo3: true,
        todo4: [
        {
            action: 'start',
            dueData: new Date(),
        },
        {
            action: 'end',
            dueData: new Date(),
        },
        ],
    },
};

actionProvider = new Subject<XModelPresenterActionModel>();

availableModelKeys: string[] = [
    nameof<DataMODEL>('lastName'),
    nameof<DataMODEL>('firstName'),
    nameof<DataMODEL>('email'),
    nameof<DataMODEL>('contacts'),
    nameof<DataMODEL>('checkList'),

    //
    // Contacts ...
    \`\${nameof<DataMODEL>('contacts')}.type\`,
    \`\${nameof<DataMODEL>('contacts')}.title\`,
    \`\${nameof<DataMODEL>('contacts')}.number\`,

    //
    // Checklist ...
    \`\${nameof<DataMODEL>('checkList')}.todo1\`,
    \`\${nameof<DataMODEL>('checkList')}.todo2\`,
    \`\${nameof<DataMODEL>('checkList')}.todo3\`,
    \`\${nameof<DataMODEL>('checkList')}.todo4\`,

    //
    \`\${nameof<DataMODEL>('checkList')}.todo4.action\`,
    \`\${nameof<DataMODEL>('checkList')}.todo4.dueData\`,
];

hiddenModelKeys: string[] = [\`\${nameof<DataMODEL>('contacts')}.type\`];

hiddenLabelModelKeys: string[] = [\`\${nameof<DataMODEL>('contacts')}.number\`];

//
sortOrederModelKeys: string[] = [
    nameof<DataMODEL>('firstName'),
    nameof<DataMODEL>('lastName'),
    nameof<DataMODEL>('email'),
    nameof<DataMODEL>('contacts'),
    nameof<DataMODEL>('checkList'),

    //
    // Contacts ...
    \`\${nameof<DataMODEL>('contacts')}.number\`,
    \`\${nameof<DataMODEL>('contacts')}.title\`,

    //
    // Checklist ...
    \`\${nameof<DataMODEL>('checkList')}.todo4.dueData\`,
    \`\${nameof<DataMODEL>('checkList')}.todo4.action\`,
];

//
modelKeyProvider: XModelPresenterModelKeyProvider<any> = (key) => {
    //
    let result = key as string;

    //
    switch (key) {
        //
        case nameof<DataMODEL>('firstName'):
        result = this.resourceProvider(this.AppResourceIDs.first_name);
        break;

        //
        case nameof<DataMODEL>('lastName'):
        result = this.resourceProvider(this.AppResourceIDs.last_name);
        break;

        //
        case nameof<DataMODEL>('contacts'):
        result = this.resourceProvider(this.AppResourceIDs.content);
        break;

        //
        default:
        result = key as string;
        break;
    }

    //
    return result;
};    
  ` +
    '```';

  readonly sample5 =
    '```javascript' +
    `
async handlePropertyActionMenuClicked(
    key: string,
    prefix: string,
    value: any
) {
    //
    if (isNullOrEmptyString(key)) {
        return;
    }

    //
    const onlyIcon = false;
    const slideOptions: XListItemSlideOption[] = [];

    //
    // Edit ...
    slideOptions.push({
        id: 'property_edit',
        icon: this.IconNames.edit,
        title: this.ResourceIDs.edit,
        color: isNullOrUndefined(value)
        ? this.ColorNames.Danger
        : this.ColorNames.Tertiary,
        slot: 'start',
        onlyIcon,
        handler: async () => {
        await this.handlePropertyEdit(key, prefix, value);
        },
    });

    //
    // Clear ...
    slideOptions.push({
        id: 'property_clear',
        icon: this.IconNames.clear,
        title: this.ResourceIDs.clear,
        color: this.ColorNames.Danger,
        slot: 'start',
        disabled: isNullOrUndefined(value),
        onlyIcon,
        handler: async () => {
        await this.handlePropertyClear(key, prefix, value);
        },
    });

    //
    // Menu Items ...
    const item: XListItem<any> = {
        data: '',
        slideOptions,
    };

    //
    const popOver = await this.managerService.dialogService.presentPopover({
        component: XPopoverComponent,
        componentProps: assign({}, { key: XParam.Item, value: item }),
        translucent: true,
        showBackdrop: true,
        event,
    });

    //
    const { data } = await popOver.onWillDismiss();
    if (!data || !data.id || !data.data) {
        return;
    }

    //
    const optionId = data.id.toString() as string;
    const option =
        item && item.slideOptions
        ? item.slideOptions.find((so) => so.id === optionId)
        : null;
    if (!option) {
        return;
    }

    //
    const handler = option.handler;
    if (!handler || !isFunction(handler)) {
        return;
    }

    //
    // Run Handler ...
    await handler();
}
    
async handlePropertyEdit(key: string, prefix: string, value: any) {
    //
    if (isNullOrEmptyString(key)) {
        return;
    }

    //
    await this.managerService.dialogService.presentAlert({
        header: 'Change Value:',
        message: 'Enter new Value:',
        inputs: [
        {
            type: 'text',
            name: 'value',
            label: 'Value',
            placeholder: isNullOrUndefined(value) ? '' : \`\${value.toString()}\`,
        },
        ],
        buttons: [
        {
            text: 'Change',
            role: XModalButtonRole.Selected,
            cssClass: ['btn-selected'],
            handler: async (value) => {
            //
            let newValue = '';
            if (value && value.value) {
                newValue = value.value;
            }

            //
            console.log('new value to set: ', newValue);

            //
            this.actionProvider.next({
                action: XModelPresenterAction.SetProperty,
                payload: {
                key: key,
                value: newValue,
                keyPrefix: prefix,
                } as XModelPresenterProperty,
            });
            },
        },
        {
            text: 'Cancel',
            role: XModalButtonRole.Cancel,
            cssClass: ['btn-cancel'],
        },
        ],
    });
}
    
async handlePropertyClear(key: string, prefix: string, value: any) {
    //
    if (isNullOrEmptyString(key) || isNullOrUndefined(value)) {
        return;
    }

    //
    await this.managerService.dialogService.presentAreYouSureYesNoDialog(() => {
        //
        this.actionProvider.next({
        action: XModelPresenterAction.ClearProperty,
        payload: {
            key,
            keyPrefix: prefix,
        } as XModelPresenterProperty,
        });
    });
}
    
async handleModelChanged(event: any) {
    console.log('handle model changed: ', event);
}    
  ` +
    '```';

  //     readonly sample3 =
  //     '```html' +
  //     `
  //   ` +
  //     '```';

  //
  //#region UI Providers ...
  //
  // Provide content based on current locale ...
  getContent(title: string) {
    //
    if (isNullOrEmptyString(title)) {
      return '';
    }

    //
    const currentLocale = this.managerService.currentLocale;

    //
    const varName =
      title +
      (currentLocale === 'en-US'
        ? 'En'
        : currentLocale === 'fa-IR'
        ? 'Fa'
        : '');

    const result = this[`${varName}`];

    //
    return result || '';
  }
  //#endregion

  //
  //#region UI Handlers ...
  //
  //#region Model Presenter Handlers ...
  async handlePropertyActionMenuClicked(
    key: string,
    prefix: string,
    value: any
  ) {
    //
    if (isNullOrEmptyString(key)) {
      return;
    }

    //
    const onlyIcon = false;
    const slideOptions: XListItemSlideOption[] = [];

    //
    // Edit ...
    slideOptions.push({
      id: 'property_edit',
      icon: this.IconNames.edit,
      title: this.ResourceIDs.edit,
      color: isNullOrUndefined(value)
        ? this.ColorNames.Danger
        : this.ColorNames.Tertiary,
      slot: 'start',
      onlyIcon,
      handler: async () => {
        await this.handlePropertyEdit(key, prefix, value);
      },
    });

    //
    // Clear ...
    slideOptions.push({
      id: 'property_clear',
      icon: this.IconNames.clear,
      title: this.ResourceIDs.clear,
      color: this.ColorNames.Danger,
      slot: 'start',
      disabled: isNullOrUndefined(value),
      onlyIcon,
      handler: async () => {
        await this.handlePropertyClear(key, prefix, value);
      },
    });

    //
    // Menu Items ...
    const item: XListItem<any> = {
      data: '',
      slideOptions,
    };

    //
    const popOver = await this.managerService.dialogService.presentPopover({
      component: XPopoverComponent,
      componentProps: assign({}, { key: XParam.Item, value: item }),
      translucent: true,
      showBackdrop: true,
      event,
    });

    //
    const { data } = await popOver.onWillDismiss();
    if (!data || !data.id || !data.data) {
      return;
    }

    //
    const optionId = data.id.toString() as string;
    const option =
      item && item.slideOptions
        ? item.slideOptions.find((so) => so.id === optionId)
        : null;
    if (!option) {
      return;
    }

    //
    const handler = option.handler;
    if (!handler || !isFunction(handler)) {
      return;
    }

    //
    // Run Handler ...
    await handler();
  }

  async handlePropertyEdit(key: string, prefix: string, value: any) {
    //
    if (isNullOrEmptyString(key)) {
      return;
    }

    //
    await this.managerService.dialogService.presentAlert({
      header: 'Change Value:',
      message: 'Enter new Value:',
      inputs: [
        {
          type: 'text',
          name: 'value',
          label: 'Value',
          placeholder: isNullOrUndefined(value) ? '' : `${value.toString()}`,
        },
      ],
      buttons: [
        {
          text: 'Change',
          role: XModalButtonRole.Selected,
          cssClass: ['btn-selected'],
          handler: async (value) => {
            //
            let newValue = '';
            if (value && value.value) {
              newValue = value.value;
            }

            //
            console.log('new value to set: ', newValue);

            //
            this.actionProvider.next({
              action: XModelPresenterAction.SetProperty,
              payload: {
                prefix,
                key: key,
                value: newValue,
              } as XModelProperty,
            });
          },
        },
        {
          text: 'Cancel',
          role: XModalButtonRole.Cancel,
          cssClass: ['btn-cancel'],
        },
      ],
    });
  }

  async handlePropertyClear(key: string, prefix: string, value: any) {
    //
    if (isNullOrEmptyString(key) || isNullOrUndefined(value)) {
      return;
    }

    //
    await this.managerService.dialogService.presentAreYouSureYesNoDialog(() => {
      //
      this.actionProvider.next({
        action: XModelPresenterAction.ClearProperty,
        payload: {
          key,
          prefix,
        } as XModelProperty,
      });
    });
  }

  async handleModelChanged(event: any) {
    console.log('handle model changed: ', event);
  }
  //#endregion
  //#endregion
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\page\page.page.html

<v-page
  [hasSide]="true"
  [toolbarTitle]="toolbarTitle"
  [toolbarSubTitle]="toolbarSubTitle"
  [toolbarShowSubTitle]="toolbarShowSubTitle"
>
  <!-- Content -->
  <x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
    <!-- Content -->
    <x-markdown
      [mode]="'preview'"
      [hasToolbar]="false"
      [content]="getContent('content')"
    ></x-markdown>

    <!-- Sample -->
    <x-markdown
      [mode]="'preview'"
      [content]="sample1"
      [hasToolbar]="false"
      [cssClass]="'code-block'"
    ></x-markdown>

    <!-- Actions -->
    <div actions>
      <a
        target="_blank"
        href="https://docs.x-framework.ir/x-framework-components/modules/XPageModule.html"
        >{{resourceProvider(ResourceIDs.documentation)}}</a
      >
    </div>
  </x-card>
</v-page>

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\page\page.page.scss


### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\page\page.page.ts

import { Component } from '@angular/core';
import { XIconNames } from 'x-framework-components';
import { VPageComponent } from '../../../views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';
import { XResourceIDs, isNullOrEmptyString, XColor } from 'x-framework-core';

@Component({
  selector: 'app-page',
  templateUrl: './page.page.html',
  styleUrls: ['./page.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class PagePage extends VPageComponent {
  //
  //#region Props ...
  //
  //#region Page Props ...
  titleRes = AppResourceIDs.page;
  toolbarTitle = this.resourceProvider(this.titleRes);
  toolbarSubTitle = this.resourceProvider(AppResourceIDs.page_description);
  toolbarShowSubTitle = true;
  //#endregion

  //
  // Prepare All Resource IDs ...
  readonly ResourceIDs = Object.assign(
    Object.assign({}, XResourceIDs),
    AppResourceIDs
  ) as any;

  //
  readonly IconNames = Object.assign({}, XIconNames);
  //#endregion

  //
  // Content ...
  readonly contentFa = `
  # ${this.toolbarTitle}
  این مولفه یکی از پرکاربرد ترین مولفه های ارائه شده توسط این چارچوب است و برای ارائه یک صفحه مجزا در یک برنامه کاربردی کاربرد دارد.

  یک صفحه از ترکیب چهار مولفه مجزا تشکیل میگردد، که عبارتند از:

  - **XToolbarComponent**:
این مولفه میتواند در ناحیه فوقانی یک صفحه قرار بگیرد و امکانات مختلفی را فراهم کند.

  - **XFooterComponent**:
این مولفه میتواند در ناحیه تحتانی یک صفحه قرار بگیرد.

  - **XNavigatorComponent**:
این مولفه می تواند در ناحیه کناری صفحه قرار گرفته و گزینه های مختلفی را بعنوان نوار پیمایش در صفحات مختلف را ارئه کند.

  - **XPageComponent**:
این مولفه از هر سه مولفه فوق استفاده می کند و امکانات لازم جهت چینش اجزاء مختلف در صفحه و مدیریت نحوه نمایش آن را فراهم می کند.

صفحه حاضر و تمام صفحاتی که در این مستند مرور کرده اید با بهره گیری از این مولفه ایجاد شده اند.
  `;

  readonly contentEn = `
  # ${this.toolbarTitle}
this is a most common component's of this Framework and used to provide an stand alone Page in an Application.

a page presented by combining 4 unique components, which are:

  - **XToolbarComponent**:
this component can show in top area of a page and provide several options.

  - **XFooterComponent**:
this component can show in bottom area of a page.

  - **XNavigatorComponent**:
this component can show in side area of a page and provide several options as a navigation bar.

  - **XPageComponent**:
this component use all of 3 above components and provide options to manage their usage and how to looks like a page.

this page and all pages you explored until now created useing this Component.
  `;

  //
  readonly sample1 =
    '```html' +
    `
<v-page
  [hasSide]="true"
  [toolbarTitle]="toolbarTitle"
  [toolbarSubTitle]="toolbarSubTitle"
  [toolbarShowSubTitle]="toolbarShowSubTitle"
  ...
>
  <!-- Content -->
  ...
</v-page>
` +
    '```';

  //
  //#region UI Providers ...
  //
  // Provide content based on current locale ...
  getContent(title: string) {
    //
    if (isNullOrEmptyString(title)) {
      return '';
    }

    //
    const currentLocale = this.managerService.currentLocale;

    //
    const varName =
      title +
      (currentLocale === 'en-US'
        ? 'En'
        : currentLocale === 'fa-IR'
        ? 'Fa'
        : '');

    const result = this[`${varName}`];

    //
    return result || '';
  }
  //#endregion
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\slider\slider.page.html

<v-page
  [hasSide]="true"
  [toolbarTitle]="toolbarTitle"
  [toolbarSubTitle]="toolbarSubTitle"
  [toolbarShowSubTitle]="toolbarShowSubTitle"
>
  <!-- Content -->
  <x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
    <!-- Content -->
    <x-markdown
      [mode]="'preview'"
      [hasToolbar]="false"
      [content]="getContent('content')"
    ></x-markdown>

    <!-- Actions -->
    <div actions>
      <a
        target="_blank"
        href="https://docs.x-framework.ir/x-framework-components/modules/XSliderModule.html"
        >{{resourceProvider(ResourceIDs.documentation)}}</a
      >
    </div>
  </x-card>

  <!-- Sample -->
  <x-markdown
    [isInPage]="true"
    [mode]="'preview'"
    [content]="sample1"
    [hasToolbar]="false"
    [wrapWithCard]="true"
    [cssClass]="'code-block'"
    [cardTitle]="resourceProvider(ResourceIDs.sample)"
  ></x-markdown>

  <!-- Component -->
  <x-slider
    [isInPage]="true"
    [options]="{
      lazy: true,
      zoom: true,
      autoplay: true,
      initialSlide: 0,
      grabCursor: true,
      autoHeight: true,
      slidesPerView: 1,
      loadPrevNext: true,
      preventClicks: false,
      speed: 400,
      pagination: true
    }"
    [wrapWithCard]="true"
    [animation]="SliderAnimations.Coverflow"
    (onSlideChange)="handleOnSlideChange($event)"
  >
    <x-slide>
      <ng-container *ngTemplateOutlet="slideRef"></ng-container>
    </x-slide>

    <x-slide>
      <ng-container *ngTemplateOutlet="slideRef"></ng-container>
    </x-slide>

    <x-slide>
      <ng-container *ngTemplateOutlet="slideRef"></ng-container>
    </x-slide>

    <x-slide>
      <ng-container *ngTemplateOutlet="slideRef"></ng-container>
    </x-slide>

    <x-slide>
      <ng-container *ngTemplateOutlet="slideRef"></ng-container>
    </x-slide>
  </x-slider>
</v-page>

<ng-template #slideRef>
  <div class="slide-content">
    Lorem ipsum dolor sit, amet consectetur adipisicing elit. Quas eum odit
    labore magnam accusantium assumenda error voluptatem ad cumque velit? Eos
    expedita minus doloremque error iste nam commodi aspernatur repellendus.
  </div>
</ng-template>

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\slider\slider.page.scss

.slide-content {
  direction: ltr;
  text-align: justify;
  padding: {
    top: 24px;
    bottom: 24px;
    left: 16px;
    right: 16px;
  }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\slider\slider.page.ts

import { Component } from '@angular/core';
import { XIconNames } from 'x-framework-components';
import { XSliderAnimation } from 'x-framework-components';
import { XResourceIDs, isNullOrEmptyString } from 'x-framework-core';
import { VPageComponent } from '../../../views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';

@Component({
  selector: 'app-slider',
  templateUrl: './slider.page.html',
  styleUrls: ['./slider.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class SliderPage extends VPageComponent {
  //
  //#region Props ...
  //
  //#region Page Props ...
  titleRes = AppResourceIDs.slider;
  toolbarTitle = this.resourceProvider(this.titleRes);
  toolbarSubTitle = this.resourceProvider(AppResourceIDs.slider_description);
  toolbarShowSubTitle = true;
  //#endregion

  //
  // Prepare All Resource IDs ...
  readonly ResourceIDs = Object.assign(
    Object.assign({}, XResourceIDs),
    AppResourceIDs
  ) as any;

  //
  readonly IconNames = Object.assign({}, XIconNames);
  //#endregion

  //
  readonly SliderAnimations = Object.assign({}, XSliderAnimation);

  //
  // Content ...
  readonly contentFa = `
# ${this.toolbarTitle}
این مولفه جهت نمایش محتوا بصورت کادر های لغزنده بکار می رود.
`;

  readonly contentEn = `
# ${this.toolbarTitle}
this Component used to provide Slideable Content's.
`;

  //
  readonly sample1 =
    '```html' +
    `
<x-slider
  [options]="{
  lazy: true,
  zoom: true,
  autoplay: true,
  initialSlide: 0,
  grabCursor: true,
  autoHeight: true,
  slidesPerView: 1,
  loadPrevNext: true,
  preventClicks: false,
  speed: 400,
  pagination: true
}"
  [animation]="SliderAnimations.Cube"
>
  <x-slide>
    <ng-container
      *ngTemplateOutlet="slideRef">
    </ng-container>
  </x-slide>

  <x-slide>
    <ng-container
      *ngTemplateOutlet="slideRef">
    </ng-container>
  </x-slide>

  <x-slide>
    <ng-container
      *ngTemplateOutlet="slideRef">
    </ng-container>
  </x-slide>

  <x-slide>
    <ng-container
      *ngTemplateOutlet="slideRef">
    </ng-container>
  </x-slide>

  <x-slide>
    <ng-container
      *ngTemplateOutlet="slideRef">
    </ng-container>
  </x-slide>
</x-slider>
` +
    '```';

  //
  //#region UI Providers ...
  //
  // Provide content based on current locale ...
  getContent(title: string) {
    //
    if (isNullOrEmptyString(title)) {
      return '';
    }

    //
    const currentLocale = this.managerService.currentLocale;

    //
    const varName =
      title +
      (currentLocale === 'en-US'
        ? 'En'
        : currentLocale === 'fa-IR'
        ? 'Fa'
        : '');

    const result = this[`${varName}`];

    //
    return result || '';
  }
  //#endregion

  //
  //#region UI Handlers ...
  handleOnSlideChange(index: number) {
    console.log('handleOnSlideChange: ', index);
  }
  //#endregion
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\small-components\small-components.page.html

<v-page
  [hasSide]="true"
  [toolbarTitle]="toolbarTitle"
  [toolbarSubTitle]="toolbarSubTitle"
  [toolbarShowSubTitle]="toolbarShowSubTitle"
>
  <!-- Content -->
  <x-markdown
    [isInPage]="true"
    [mode]="'preview'"
    [hasToolbar]="false"
    [wrapWithCard]="true"
    [content]="getContent('content')"
  ></x-markdown>

  <!-- Expandable Panel -->
  <x-expandable-panel
    [isInPage]="true"
    [isAccordion]="true"
    [wrapWithCard]="true"
    [selected]="'Button'"
    [headerColor]="'tertiary'"
    [headerHighlightColor]="'dark'"
  >
    <!-- Button -->
    <x-panel [id]="'Button'" [hasCustomActions]="true">
      <!-- Title and Description -->
      <div x-panel-title>{{ resourceProvider(ResourceIDs.button) }}</div>

      <br />

      <!-- Description -->
      <x-markdown
        [mode]="'preview'"
        [hasToolbar]="false"
        [content]="getContent('buttonContent')"
      ></x-markdown>

      <!-- Sample1 -->
      <x-markdown
        [mode]="'preview'"
        [hasToolbar]="false"
        [cssClass]="'code-block'"
        [content]="buttonSample1"
      ></x-markdown>

      <x-button
        [type]="ButtonTypes.Raised"
        [color]="ColorNames.Primary"
        class="ion-margin-horizontal"
        (click)="handleButtonClicked()"
        [title]="ResourceIDs.temp_label"
      ></x-button>

      <!-- Sample2 -->
      <x-markdown
        [mode]="'preview'"
        [hasToolbar]="false"
        [cssClass]="'code-block'"
        [content]="buttonSample2"
      ></x-markdown>

      <x-button
        [foregroundColor]="true"
        [type]="ButtonTypes.Raised"
        class="ion-margin-horizontal"
        [color]="ColorNames.Secondary"
        (click)="handleButtonClicked()"
        [title]="ResourceIDs.temp_label"
      ></x-button>

      <!-- Sample3 -->
      <x-markdown
        [mode]="'preview'"
        [hasToolbar]="false"
        [cssClass]="'code-block'"
        [content]="buttonSample3"
      ></x-markdown>

      <x-button
        [type]="ButtonTypes.Icon"
        [color]="ColorNames.Tertiary"
        class="ion-margin-horizontal"
        (click)="handleButtonClicked()"
      >
        <x-icon [name]="'list'" [color]="'light'"></x-icon>
      </x-button>

      <!-- Actions -->
      <div x-panel-actions>
        <a
          target="_blank"
          href="https://docs.x-framework.ir/x-framework-components/components/XButtonComponent.html"
          >{{resourceProvider(ResourceIDs.documentation)}}</a
        >
      </div>
    </x-panel>

    <!-- ActionBar -->
    <x-panel [id]="'ActionBar'" [hasCustomActions]="true">
      <!-- Title and Description -->
      <div x-panel-title>{{ resourceProvider(ResourceIDs.action_bar) }}</div>
      <!-- <div x-panel-description>
        {{ resourceProvider(ResourceIDs.action_bar_description) }}
      </div> -->

      <br />

      <!-- Description -->
      <x-markdown
        [mode]="'preview'"
        [hasToolbar]="false"
        [content]="getContent('actionBarContent')"
      ></x-markdown>

      <x-markdown
        [mode]="'preview'"
        [hasToolbar]="false"
        [cssClass]="'code-block'"
        [content]="actionBarSample1"
      ></x-markdown>

      <x-action-bar
        [color]="ColorNames.Dark"
        [actions]="actionBarItems"
        (actionFired)="handleActionFired($event)"
      ></x-action-bar>

      <!-- Actions -->
      <div x-panel-actions>
        <a
          target="_blank"
          href="https://docs.x-framework.ir/x-framework-components/components/XActionBarComponent.html"
          >{{resourceProvider(ResourceIDs.documentation)}}</a
        >
      </div>
    </x-panel>

    <!-- SearchBar -->
    <x-panel [id]="'SearchBar'" [hasCustomActions]="true">
      <!-- Title and Description -->
      <div x-panel-title>{{ resourceProvider(ResourceIDs.search_bar) }}</div>
      <!-- <div x-panel-description>
        {{ resourceProvider(ResourceIDs.search_bar_description) }}
      </div> -->

      <br />

      <!-- Description -->
      <x-markdown
        [mode]="'preview'"
        [hasToolbar]="false"
        [content]="getContent('searchBarContent')"
      ></x-markdown>

      <x-markdown
        [mode]="'preview'"
        [hasToolbar]="false"
        [cssClass]="'code-block'"
        [content]="searchBarSample1"
      ></x-markdown>

      <x-search-bar
        value="test"
        [color]="ColorNames.Dark"
        [enterKeyHint]="'search'"
        [searchInputColor]="'dark-tint'"
        (queryChange)="handleQueryChanged($event)"
      >
      </x-search-bar>

      <!-- Actions -->
      <div x-panel-actions>
        <a
          target="_blank"
          href="https://docs.x-framework.ir/x-framework-components/components/XSearchBarComponent.html"
          >{{resourceProvider(ResourceIDs.documentation)}}</a
        >
      </div>
    </x-panel>

    <!-- Alert -->
    <x-panel [id]="'Alert'" [hasCustomActions]="true">
      <!-- Title and Description -->
      <div x-panel-title>{{ resourceProvider(ResourceIDs.alert) }}</div>
      <!-- <div x-panel-description>
        {{ resourceProvider(ResourceIDs.alert_description) }}
      </div> -->

      <br />

      <!-- Description -->
      <x-markdown
        [mode]="'preview'"
        [hasToolbar]="false"
        [content]="getContent('alertContent')"
      ></x-markdown>

      <!-- Sample1 -->
      <x-markdown
        [mode]="'preview'"
        [hasToolbar]="false"
        [cssClass]="'code-block'"
        [content]="alertSample1"
      ></x-markdown>

      <x-button
        [type]="ButtonTypes.Raised"
        [title]="ResourceIDs.alert"
        (click)="handleShowAlert()"
        [color]="ColorNames.Primary"
        class="ion-margin-horizontal"
      ></x-button>

      <!-- Sample2 -->
      <x-markdown
        [mode]="'preview'"
        [hasToolbar]="false"
        [cssClass]="'code-block'"
        [content]="alertSample2"
      ></x-markdown>

      <x-button
        [type]="ButtonTypes.Raised"
        [title]="ResourceIDs.alert"
        (click)="handleShowNativeAlert()"
        [color]="ColorNames.Tertiary"
        class="ion-margin-horizontal"
      ></x-button>

      <br />
      <br />

      <!-- Propt Description -->
      <x-markdown
        [mode]="'preview'"
        [hasToolbar]="false"
        [content]="getContent('promptContent')"
      ></x-markdown>

      <x-markdown
        [mode]="'preview'"
        [hasToolbar]="false"
        [cssClass]="'code-block'"
        [content]="promptSample1"
      ></x-markdown>

      <x-button
        [type]="ButtonTypes.Raised"
        [title]="ResourceIDs.prompt"
        (click)="handleShowPrompt()"
        [color]="ColorNames.Tertiary"
        class="ion-margin-horizontal"
      ></x-button>

      <x-markdown
        [mode]="'preview'"
        [hasToolbar]="false"
        [cssClass]="'code-block'"
        [content]="promptSample2"
      ></x-markdown>

      <x-button
        [type]="ButtonTypes.Raised"
        [title]="ResourceIDs.prompt"
        (click)="handleShowNativePrompt()"
        [color]="ColorNames.Primary"
        class="ion-margin-horizontal"
      ></x-button>

      <x-markdown
        [mode]="'preview'"
        [hasToolbar]="false"
        [cssClass]="'code-block'"
        [content]="promptSample3"
      ></x-markdown>

      <x-button
        [type]="ButtonTypes.Raised"
        [title]="ResourceIDs.prompt"
        [color]="ColorNames.Primary"
        class="ion-margin-horizontal"
        (click)="handleShowActionModal()"
      ></x-button>

      <br />
      <br />

      <!-- Modal -->
      <x-markdown
        [mode]="'preview'"
        [hasToolbar]="false"
        [content]="getContent('modalContent')"
      ></x-markdown>

      <x-markdown
        [mode]="'preview'"
        [hasToolbar]="false"
        [cssClass]="'code-block'"
        [content]="modalSample1"
      ></x-markdown>

      <x-button
        [type]="ButtonTypes.Raised"
        [title]="ResourceIDs.alert"
        [color]="ColorNames.Primary"
        class="ion-margin-horizontal"
        (click)="handleShowModal()"
      ></x-button>

      <br />
      <br />

      <!-- PopOver -->
      <x-markdown
        [mode]="'preview'"
        [hasToolbar]="false"
        [content]="getContent('popOverContent')"
      ></x-markdown>

      <x-markdown
        [mode]="'preview'"
        [hasToolbar]="false"
        [cssClass]="'code-block'"
        [content]="popOverSample1"
      ></x-markdown>

      <x-button
        [type]="ButtonTypes.Raised"
        [title]="ResourceIDs.alert"
        [color]="ColorNames.Primary"
        class="ion-margin-horizontal"
        (click)="handleShowPopOver($event)"
      ></x-button>

      <!-- Actions -->
      <div x-panel-actions>
        <a
          target="_blank"
          href="https://docs.x-framework.ir/x-framework-services/injectables/XDialogService.html#presentAlert"
          >{{resourceProvider(ResourceIDs.documentation)}}</a
        >
      </div>
    </x-panel>

    <!-- Notification -->
    <x-panel [id]="'Notification'" [hasCustomActions]="true">
      <!-- Title and Description -->
      <div x-panel-title>{{ resourceProvider(ResourceIDs.notification) }}</div>
      <!-- <div x-panel-description>
        {{ resourceProvider(ResourceIDs.notification_description) }}
      </div> -->

      <br />

      <!-- Description -->
      <x-markdown
        [mode]="'preview'"
        [hasToolbar]="false"
        [content]="getContent('notificationContent')"
      ></x-markdown>

      <x-markdown
        [mode]="'preview'"
        [hasToolbar]="false"
        [cssClass]="'code-block'"
        [content]="notificationSample1"
      ></x-markdown>

      <x-button
        [type]="ButtonTypes.Raised"
        [color]="ColorNames.Danger"
        class="ion-margin-horizontal"
        (click)="handleShowNotification()"
        [title]="ResourceIDs.notification"
      ></x-button>

      <!-- Actions -->
      <div x-panel-actions>
        <a
          target="_blank"
          href="https://docs.x-framework.ir/x-framework-services/injectables/XNotificationService.html"
          >{{resourceProvider(ResourceIDs.documentation)}}</a
        >
      </div>
    </x-panel>

    <!-- Spinner -->
    <x-panel [id]="'Spinner'" [hasCustomActions]="true">
      <!-- Title and Description -->
      <div x-panel-title>{{ resourceProvider(ResourceIDs.spinner) }}</div>
      <!-- <div x-panel-description>
        {{ resourceProvider(ResourceIDs.spinner_description) }}
      </div> -->

      <br />

      <!-- Description -->
      <x-markdown
        [mode]="'preview'"
        [hasToolbar]="false"
        [content]="getContent('spinnerContent')"
      ></x-markdown>

      <x-markdown
        [mode]="'preview'"
        [hasToolbar]="false"
        [cssClass]="'code-block'"
        [content]="spinnerSample1"
      ></x-markdown>

      <!-- Bubbles -->
      <x-spinner
        [color]="ColorNames.Primary"
        [name]="SpinnerNames.Bubbles"
      ></x-spinner>

      <!-- Circles -->
      <x-spinner
        [name]="SpinnerNames.Circles"
        [color]="ColorNames.Secondary"
      ></x-spinner>

      <!-- Tertiary -->
      <x-spinner
        [color]="ColorNames.Tertiary"
        [name]="SpinnerNames.Circular"
      ></x-spinner>

      <!-- Dark -->
      <x-spinner
        [color]="ColorNames.Dark"
        [name]="SpinnerNames.Crescent"
      ></x-spinner>

      <!-- Warning -->
      <x-spinner
        [color]="ColorNames.Warning"
        [name]="SpinnerNames.Dots"
      ></x-spinner>

      <!-- Danger -->
      <x-spinner
        [color]="ColorNames.Danger"
        [name]="SpinnerNames.Lines"
      ></x-spinner>

      <!-- Success -->
      <x-spinner
        [color]="ColorNames.Success"
        [name]="SpinnerNames.LinesSmall"
      ></x-spinner>

      <!-- Actions -->
      <div x-panel-actions>
        <a
          target="_blank"
          href="https://docs.x-framework.ir/x-framework-components/components/XSpinnerComponent.html"
          >{{resourceProvider(ResourceIDs.documentation)}}</a
        >
      </div>
    </x-panel>

    <!-- Loading -->
    <x-panel [id]="'Loading'" [hasCustomActions]="true">
      <!-- Title and Description -->
      <div x-panel-title>{{ resourceProvider(ResourceIDs.loading) }}</div>
      <!-- <div x-panel-description>
        {{ resourceProvider(ResourceIDs.loading_description) }}
      </div> -->

      <br />

      <!-- Description -->
      <x-markdown
        [mode]="'preview'"
        [hasToolbar]="false"
        [content]="getContent('loadingContent')"
      ></x-markdown>

      <x-markdown
        [mode]="'preview'"
        [hasToolbar]="false"
        [cssClass]="'code-block'"
        [content]="loadingSample1"
      ></x-markdown>

      <x-button
        [type]="ButtonTypes.Raised"
        class="ion-margin-horizontal"
        [color]="ColorNames.Secondary"
        (click)="handleShowLoading()"
        [title]="ResourceIDs.loading"
      ></x-button>

      <!-- Actions -->
      <div x-panel-actions>
        <a
          target="_blank"
          href="https://docs.x-framework.ir/x-framework-services/injectables/XDialogService.html#presentLoading"
          >{{resourceProvider(ResourceIDs.documentation)}}</a
        >
      </div>
    </x-panel>

    <!-- Color -->
    <x-panel [id]="'color'" [hasCustomActions]="true">
      <!-- Title and Description -->
      <div x-panel-title>{{ resourceProvider(ResourceIDs.color) }}</div>
      <!-- <div x-panel-description>
        {{ resourceProvider(ResourceIDs.color_description) }}
      </div> -->

      <br />

      <!-- Description -->
      <x-markdown
        [mode]="'preview'"
        [hasToolbar]="false"
        [content]="getContent('colorContent')"
      ></x-markdown>

      <x-markdown
        [mode]="'preview'"
        [hasToolbar]="false"
        [cssClass]="'code-block'"
        [content]="colorSample1"
      ></x-markdown>

      <!-- Component -->
      <x-color [value]="{ key: 'black', value: '#000000' }"></x-color>

      <!-- Actions -->
      <div x-panel-actions>
        <a
          target="_blank"
          href="https://docs.x-framework.ir/x-framework-components/components/XColorComponent.html"
          >{{resourceProvider(ResourceIDs.documentation)}}</a
        >
      </div>
    </x-panel>

    <!-- Picker -->
    <x-panel [id]="'Picker'" [hasCustomActions]="true">
      <!-- Title and Description -->
      <div x-panel-title>{{ resourceProvider(ResourceIDs.picker) }}</div>
      <!-- <div x-panel-description>
        {{ resourceProvider(ResourceIDs.picker_description) }}
      </div> -->

      <br />

      <!-- Description -->
      <x-markdown
        [mode]="'preview'"
        [hasToolbar]="false"
        [content]="getContent('pickerContent')"
      ></x-markdown>

      <x-markdown
        [mode]="'preview'"
        [hasToolbar]="false"
        [cssClass]="'code-block'"
        [content]="pickerSample1"
      ></x-markdown>

      <x-button
        [type]="ButtonTypes.Raised"
        class="ion-margin-horizontal"
        [color]="ColorNames.Primary"
        (click)="handleShowSelect()"
        [title]="ResourceIDs.picker"
      ></x-button>

      <!-- Actions -->
      <div x-panel-actions>
        <a
          target="_blank"
          href="https://docs.x-framework.ir/x-framework-services/injectables/XDialogService.html#presentPicker"
          >{{resourceProvider(ResourceIDs.documentation)}}</a
        >
      </div>
    </x-panel>

    <!-- Slotter -->
    <x-panel [id]="'Slotter'" [hasCustomActions]="true">
      <!-- Title and Description -->
      <div x-panel-title>{{ resourceProvider(ResourceIDs.slotter) }}</div>
      <!-- <div x-panel-description>
        {{ resourceProvider(ResourceIDs.slotter_description) }}
      </div> -->

      <br />

      <!-- Description -->
      <x-markdown
        [mode]="'preview'"
        [hasToolbar]="false"
        [content]="getContent('slotterContent')"
      ></x-markdown>

      <br />
      <br />
      <h4>{{ resourceProvider(ResourceIDs.horizontal) }}</h4>

      <!-- Sample 1 -->
      <x-markdown
        [mode]="'preview'"
        [hasToolbar]="false"
        [cssClass]="'code-block'"
        [content]="slotterSample1"
      ></x-markdown>
      <br />
      <br />
      <x-slotter [layout]="SlotLayout.HORIZONTAL">
        <x-slot [name]="SlotNames.START" [cssClass]="'ion-text-start'">
          Start
        </x-slot>
        <x-slot [name]="SlotNames.CENTER" [cssClass]="'ion-text-center'">
          Center
        </x-slot>
        <x-slot [name]="SlotNames.END" [cssClass]="'ion-text-end'">
          End
        </x-slot>
      </x-slotter>

      <br />
      <br />
      <!-- Vertical -->
      <h4>{{resourceProvider(ResourceIDs.vertical)}}</h4>

      <!-- Sample 1 -->
      <x-markdown
        [mode]="'preview'"
        [hasToolbar]="false"
        [cssClass]="'code-block'"
        [content]="slotterSample2"
      ></x-markdown>
      <br />
      <br />
      <x-slotter [layout]="SlotLayout.VERTICAL">
        <x-slot [name]="SlotNames.TOP" [cssClass]="'ion-text-center'">
          Top
        </x-slot>
        <x-slot [name]="SlotNames.CENTER" [cssClass]="'ion-text-center'">
          Center
        </x-slot>
        <x-slot [name]="SlotNames.BOTTOM" [cssClass]="'ion-text-center'">
          Bottom
        </x-slot>
      </x-slotter>

      <!-- Actions -->
      <div x-panel-actions>
        <a
          target="_blank"
          href="https://docs.x-framework.ir/x-framework-components/modules/XSlotterModule.html"
          >{{resourceProvider(ResourceIDs.documentation)}}</a
        >
      </div>
    </x-panel>

    <!-- Empty -->
    <x-panel [id]="'Empty'" [hasCustomActions]="true">
      <!-- Title and Description -->
      <div x-panel-title>
        {{ resourceProvider(ResourceIDs.empty_component) }}
      </div>
      <!-- <div x-panel-description>
        {{ resourceProvider(ResourceIDs.empty_component_description) }}
      </div> -->

      <br />

      <!-- Description -->
      <x-markdown
        [mode]="'preview'"
        [hasToolbar]="false"
        [content]="getContent('emptyContent')"
      ></x-markdown>

      <!-- Sample -->
      <x-markdown
        [mode]="'preview'"
        [hasToolbar]="false"
        [content]="emptySample1"
        [cssClass]="'code-block'"
      ></x-markdown>

      <x-empty
        [hasRefresh]="true"
        [foregroundColor]="false"
        [color]="ColorNames.Dark"
        (refresh)="handleRefreshEmpty()"
        [foregroundMessageColor]="false"
        [messageColor]="ColorNames.Dark"
        [refreshButtonColor]="ColorNames.Dark"
        [foregroundRefreshButtonColor]="false"
      ></x-empty>

      <!-- Actions -->
      <div x-panel-actions>
        <a
          target="_blank"
          href="https://docs.x-framework.ir/x-framework-components/components/XEmptyComponent.html"
          >{{resourceProvider(ResourceIDs.documentation)}}</a
        >
      </div>
    </x-panel>
  </x-expandable-panel>
</v-page>

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\small-components\small-components.page.scss


### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\small-components\small-components.page.ts

import {
  XColor,
  XSpinner,
  XActionType,
  XResourceIDs,
  XModalButtonRole,
  isNullOrEmptyString,
} from 'x-framework-core';
import {
  XSlotName,
  XButtonType,
  XSlotLayout,
  XActionBarItem,
  XActionBarActionFiredModel,
  defaultActionBarRemoveItem,
  defaultActionBarSelectAllItem,
  defaultActionBarDeSelectAllItem,
  defaultActionBarInverseSelectionItem,
} from 'x-framework-components';
import { Component } from '@angular/core';
import {
  XModalContext,
  SampleModalComponent,
} from './sample-modal/sample-modal.component';
import { VPageComponent } from '../../../views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';

@Component({
  selector: 'app-small-components',
  templateUrl: './small-components.page.html',
  styleUrls: ['./small-components.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class SmallComponentsPage extends VPageComponent {
  //
  //#region Props ...
  //
  //#region Page Props ...
  titleRes = AppResourceIDs.small_components;
  toolbarTitle = this.resourceProvider(this.titleRes);
  toolbarSubTitle = this.resourceProvider(
    AppResourceIDs.small_components_description
  );
  toolbarShowSubTitle = true;
  //#endregion

  //
  //#region Contents Info ...
  //
  // Prepare All Resource IDs ...
  readonly ResourceIDs = Object.assign(
    Object.assign({}, XResourceIDs),
    AppResourceIDs
  ) as any;

  //
  // Content ...
  readonly contentFa = `
  # مولفه های جزئی

  مولفه هایی هستند که بسیار جزئی اما پرکاربرد هستند و شامل پیکربندی های پیچیده نیستند.
  این مولفه ها را بسادگی می توان مورد بهره برداری قرار داد.

  در ادامه فهرستی از این مولفه ها بهمراه مستندات مربوط به هریک به تفکیک ارائه می گردد:
  `;
  readonly contentEn = `
  # Small Components

  a collection of usefull and common Components which not so complicated to use them.
  these Components can be implement easily.

  the following list contains documentation and examples of how to use these Components:
  `;

  //
  // Button Content ...
  readonly ButtonTypes = Object.assign({}, XButtonType);
  readonly buttonContentFa = `
  دکمه ها در زمره پرکاربرد ترین مولفه ها در برنامه های کاربردی هستند.

  در این چارچوب مجموعه ای از دکمه ها قابل بهره برداری هستند که در ادامه به آنها اشاره خواهد شد.
  `;
  readonly buttonContentEn = `
  Buttons are most common Components which used in Applications.

  this Framework provide a collection of Buttons which can be used. following are some examples.
  `;

  //
  // Button Sample 1 ...
  readonly buttonSample1 =
    '```html' +
    `
  <x-button
    [color]="\'primary\'"
    [type]="ButtonTypes.Raised"
    class="ion-margin-horizontal"
    (click)="handleButtonClicked()"
    [title]="ResourceIDs.temp_label">
  </x-button>
  ` +
    '```';

  //
  // Button Sample 1 ...
  readonly buttonSample2 =
    '```html' +
    `
  <x-button
    [color]="\'secondary\'"
    [foregroundColor]="true"
    [type]="ButtonTypes.Raised"
    class="ion-margin-horizontal"
    (click)="handleButtonClicked()"
    [title]="ResourceIDs.temp_label">
  </x-button
  ` +
    '```';

  //
  // Button Sample 1 ...
  readonly buttonSample3 =
    '```html' +
    `
  <x-button
    [color]="\'tertiary\'"
    [type]="ButtonTypes.Icon"
    class="ion-margin-horizontal"
    (click)="handleButtonClicked()"
    [title]="ResourceIDs.temp_label"
  >
    <x-icon
      [name]="\'list\'"
      [color]="\'light\'">
    </x-icon>
  </x-button>
  ` +
    '```';

  //
  // ActionBar Content ...
  actionBarItems: XActionBarItem[] = [
    //
    // Remove ...
    {
      //
      ...defaultActionBarRemoveItem,

      //
      index: 0,
    },
    //
    // Select All ...
    {
      //
      ...defaultActionBarSelectAllItem,

      //
      index: 1,
    },
    //
    // Inverse Selection ...
    {
      //
      ...defaultActionBarInverseSelectionItem,

      //
      index: 2,
    },
    //
    // De Select All ...
    {
      //
      ...defaultActionBarDeSelectAllItem,

      //
      index: 3,
    },
  ];

  readonly actionBarContentFa = `
این مولفه جهت ارائه مجموعه ای از فرمان های عملیاتی در یک واسط کاربری یکپارچه بکار می رود
`;
  readonly actionBarContentEn = `
this Component used to represent a Collection of Action Buttons in an integrated interface.
`;

  readonly actionBarSample1 =
    '```html' +
    `
<x-action-bar
  [color]="ColorNames.Dark"
  [actions]="actionBarItems"
  (actionFired)="
    handleActionFired($event)"
>
</x-action-bar>
` +
    '```';

  //
  // SearchBar Content ...
  readonly searchBarContentFa = `
این مولفه جهت ارائه امکانات جستجو در اطلاعات بکار می رود.
`;
  readonly searchBarContentEn = `
this component provide a Search interface.
`;

  readonly searchBarSample1 =
    '```html' +
    `
<x-search-bar
  value="test"
  [color]="ColorNames.Dark"
  [enterKeyHint]="'search'"
  [searchInputColor]="
    'dark-tint'"
  (queryChange)="
    handleQueryChanged($event)"
>
</x-search-bar>
` +
    '```';

  //
  // Alert Content ...
  readonly alertContentFa = `
  این مولفه زمانی کاربرد دارد که قصد داریم پیام خاصی را به کاربر نمایش دهیم.

  گونه های مختلفی از هشدارهای از پیش تعریف شده جهت سهولت استفاده فراهم شده اند که با مطالعه مستندات می توانید آن ها را مورد بهره برداری قرار دهید.

  برای نمایش اعلان باید بصورت زیر عمل کنیم:

  `;
  readonly alertContentEn = `
  this Component used when we need to show an Special kind of messages to user.

  there are some predefined of this Components, you can read the documentaion for How to use and get more info about them.

  for show an Alert you must act like this:
  `;

  readonly alertSample1 =
    '```typescript' +
    `
//
await this.managerService
.dialogService
.presentAlert({
  header: AppResourceIDs.alert,
  subHeader: 'sub title',
  message: 'message',
  buttons: [
    {
      text: 'OK',
      role: XModalButtonRole
      .Selected,
      handler: () => {},
    },
  ],
});
  ` +
    '```';

  readonly alertSample2 =
    '```typescript' +
    `
this.managerService
  .dialogService
  .nativeAlert(this
    .ResourceIDs.temp_label);
` +
    '```';

  //
  // Prompt Content ...
  readonly promptContentFa = `
  در برخی موارد احتیاج داریم تا اطلاعات خاصی را از کاربر تحت عنوان ورودی دریافت کنیم:
  `;
  readonly promptContentEn = `
  in some used cases we need to give som information from user through an Alert.
  `;

  readonly promptSample1 =
    '```typescript' +
    `
//
await this.managerService
.dialogService
.presentAlert({
  header: 'عنوان',
  subHeader: 'توضیحات',
  message: 'نام شما چیست ؟',
  inputs: [
    {
      type: 'text',
      name: 'name',
      label: 'نام',
      placeholder:
        'نام و نام خانوادگی ...',
    },
  ],
  buttons: [
    {
      text: 'ثبت',
      role: XModalButtonRole
      .Selected,
      cssClass: ['btn-selected'],
      handler: async (value) => {
        //
        console.log(
          'OK Clicked ...', value
          );

        //
        if (value &&
            value.name &&
            !isNullOrEmptyString(
              value.name)) {
          await this.managerService
          .notificationService
          .presentInfoNotification(
            {
              message: value.name,
              dissmissable: true,
            }
          );
        }
      },
    },
    {
      text: 'لغو',
      role: XModalButtonRole.Cancel,
      cssClass: ['btn-cancel'],
      handler: () => {
        console.log(
          'Cancel Clicked ...'
          );
      },
    },
  ],
});
  ` +
    '```';

  readonly promptSample2 =
    '```typescript' +
    `
  this.managerService.dialogService
  .nativeConfirm(
    this.ResourceIDs.temp_label)
  .subscribe((res) => {
    this.managerService
      .notificationService
      .presentInfoNotification({
      message: \`\${res}\`,
      dissmissable: true,
    });
  });
` +
    '```';

  readonly promptSample3 =
    '```typescript' +
    `
//
await this.managerService
  .dialogService
  .presentActionModal({
  type: XActionType.System,
  playSound: true,
  header: XResourceIDs.are_you_sure,
  buttons: [
    {
      text: XResourceIDs.yes,
      role: XModalButtonRole
        .Selected,
      handler: async () => {
        await this.managerService
          .notificationService
          .presentSuccessNotification(
          {
            message:
              'Yes Selected ...',
            dissmissable: true,
          }
        );
      },
    },
    {
      text: XResourceIDs.no,
      role: XModalButtonRole.Cancel,
      handler: async () => {
        await this.managerService
          .notificationService
          .presentDangerNotification(
          {
            message:
              'No Selected ...',
            dissmissable: true,
          }
        );
      },
    },
  ],
});
` +
    '```';

  readonly colorContentFa = 'این مولفه جهت نمایش رنگ بکار می رود';

  readonly colorContentEn = 'this component used to represent a color';

  readonly colorSample1 =
    '```typescript' +
    `
<x-color [value]="{ key: 'black', value: '#000000' }">
</x-color>
` +
    '```';

  readonly modalContentFa = `
برخی اوقات احتیاج داریم که یک مولفه مجزا در انگولار را بعنوان یک کادر محاوره به کاربر نمایش دهیم.
`;

  readonly modalContentEn = `
some times we had to show an angular component as a dialog to user.
`;

  readonly modalSample1 =
    '```typescript' +
    `
const modal = await this
  .managerService
  .dialogService
  .presentModal({
    component:
      SampleModalComponent,
    componentProps: {
      context: 'Show Modal',
    },
});
` +
    '```';

  readonly popOverContentFa = `
برخی اوقات احتیاج داریم که یک مولفه مجزا در انگولار را بعنوان منوی زمینه به کاربر نمایش دهیم.
`;
  readonly popOverContentEn = `
some times we had to show an angular component as a context menu to user.
`;

  readonly popOverSample1 =
    '```typescript' +
    `
const popOver = await this
  .managerService
  .dialogService
  .presentPopover({
    event,
    component:
      SampleModalComponent,
    componentProps: {
      context: 'Show PopOver',
    },
});
` +
    '```';

  //
  // Notification Content ...
  readonly notificationContentFa = `
  اعلان ها اغلب جهت اطلاع از نتیجه انجام یک عملیات به کار می روند.
  `;
  readonly notificationContentEn = `
  Notifications almost used to notify a process/action result to user.
  `;

  readonly notificationSample1 =
    '```typescript' +
    `
//
await this.managerService
.notificationService
.presentDangerNotification({
  message: XResourceIDs.error,
  dissmissable: true,
});
` +
    '```';

  //
  // Spinner Content ...
  readonly SpinnerNames = Object.assign({}, XSpinner);
  readonly spinnerContentFa = `این مولفه اغلب جهت نمایش وضعیت در حال انجام کار در سایر مولفه ها کاربرد دارد.`;
  readonly spinnerContentEn = `this Components used to act as indicator of another Components`;

  readonly spinnerSample1 =
    '```html' +
    ` +
<x-spinner
  [color]="ColorNames.Primary"
  [name]="SpinnerNames.Circular">
</x-spinner>
` +
    '```';

  //
  // Loading Content ...
  readonly loadingContentFa = `
  این مولفه در مواردی کاربرد دارد که قصد داریم روال اجرای برنامه را تا اتمام یک فرآیند خاص متوقف کنیم.
  `;
  readonly loadingContentEn = `this Component used when we have to stop application process until an action finished.`;
  readonly loadingSample1 =
    '```typescript' +
    `
//
const loading = await this
.managerService
.dialogService
.presentLoading({
  message: this
  .resourceProvider(
    AppResourceIDs.temp_label
  ),
  spinner: this
  .SpinnerNames.LinesSmall,
});

//
// TODO: Do Actions ...

//
// This is for Sample tests ...
loading.dismiss();
` +
    '```';

  //
  // Picker Content ...
  readonly pickerContentFa = `
  انتخاب یک یا چند گزینه از میان مجموعه ای از انتخاب ها مهمترین کاربرد این مولفه است.
  `;
  readonly pickerContentEn = `select on or more item from a collection of items is the main used case of this Component.`;

  readonly pickerSample1 =
    '```typescript' +
    `
//
await this
.managerService
.dialogService
.presentPicker({
  buttons: [
    {
      text: 'Ok',
      role: XModalButtonRole
      .Selected,
      cssClass: ['btn-selected'],
      handler: (value) => {
        console.log(
          'OK Clicked ...', value
        );
      },
    },
    {
      text: 'Cancel',
      role: XModalButtonRole
      .Cancel,
      cssClass: ['btn-cancel'],
      handler: () => {
        console.log(
          'Cancel Clicked ...'
        );
      },
    },
  ],
  columns: [
    {
      name: 'Col_1',
      options: [
        {
          text: 'S 1',
          value: 1,
        },
        {
          text: 'S 2',
          value: 2,
        },
        {
          text: 'S 3',
          value: 3,
        },
        {
          text: 'S 4',
          value: 4,
        },
        {
          text: 'S 5',
          value: 5,
        },
        {
          text: 'S 6',
          value: 6,
        },
        {
          text: 'S 7',
          value: 7,
        },
        {
          text: 'S 8',
          value: 8,
        },
        {
          text: 'S 9',
          value: 9,
        },
        {
          text: 'S 10',
          value: 10,
        },
      ],
    },
  ],
});
` +
    '```';

  //
  // Slotter Content ...
  readonly SlotNames = Object.assign({}, XSlotName);
  readonly SlotLayout = Object.assign({}, XSlotLayout);
  readonly slotterContentFa = `
  این مولفه جهت تقسیم فضای در دسترس بکار میرود.

   توسط بکارگری این مولفه می توان چینش محتوا را مدیریت کرد
  `;
  readonly slotterContentEn = `
  this Component used to divide available screen space.

  with help of this Component you can manage how Components appear in available space.
  `;

  readonly slotterSample1 =
    '```html' +
    `
<x-slotter
  [layout]="SlotLayout.HORIZONTAL"
>
  <x-slot
    [name]="SlotNames.START"
    [cssClass]="\'ion-text-start\'"
  >
    Start
  </x-slot>
  <x-slot
    [name]="SlotNames.CENTER"
    [cssClass]="\'ion-text-center\'"
  >
    Center
  </x-slot>
  <x-slot
    [name]="SlotNames.END"
    [cssClass]="\'ion-text-end\'"
  >
    End
  </x-slot>
</x-slotter>
` +
    '```';

  readonly slotterSample2 =
    '```html' +
    `
<x-slotter
  [layout]="SlotLayout.VERTICAL"
>
  <x-slot
    [name]="SlotNames.TOP"
    [cssClass]="\'ion-text-center\'"
  >
    Top
  </x-slot>
  <x-slot
    [name]="SlotNames.CENTER"
    [cssClass]="\'ion-text-center\'"
  >
    Center
  </x-slot>
  <x-slot
    [name]="SlotNames.BOTTOM"
    [cssClass]="\'ion-text-center\'"
  >
    Bottom
  </x-slot>
</x-slotter>
` +
    '```';

  //
  // Empty Component ...
  readonly emptyContentFa = `
از این مولفه جهت اطلاع رسانی در خصوص عدم وجود مورد یا مواردی که کاربر از منابع درخواست کرده است استفاده می گیرد.
`;
  readonly emptyContentEn = `
this component used when user requet item(s) from resources and the result is empty.
`;

  readonly emptySample1 =
    '```html' +
    `
<x-empty
  [hasRefresh]="true"
  [foregroundColor]="false"
  [color]="ColorNames.Dark"
  (refresh)="handleRefreshEmpty()"
  [foregroundMessageColor]="false"
  [messageColor]="ColorNames.Dark"
  [refreshButtonColor]="ColorNames.Dark"
  [foregroundRefreshButtonColor]="false"
></x-empty>
` +
    '```';

  //#endregion
  //#endregion

  //
  //#region UI Providers ...
  //
  // Provide content based on current locale ...
  getContent(title: string) {
    //
    if (isNullOrEmptyString(title)) {
      return '';
    }

    //
    const currentLocale = this.managerService.currentLocale;

    //
    const varName =
      title +
      (currentLocale === 'en-US'
        ? 'En'
        : currentLocale === 'fa-IR'
        ? 'Fa'
        : '');

    const result = this[`${varName}`];

    //
    return result || '';
  }
  //#endregion

  //
  //#region UI Handlers ...
  //
  async handleButtonClicked() {
    await this.managerService.notificationService.presentSuccessNotification({
      message: this.resourceProvider(AppResourceIDs.temp_label),
      dissmissable: true,
    });
  }

  //
  async handleActionFired(event: XActionBarActionFiredModel) {
    //
    const name = event.action;
    await this.managerService.notificationService.presentXNotification({
      message: `Action Fired: ${name}`,
      dissmissable: true,
      opt: {
        color: XColor.Dark,
      },
    });
  }

  //
  async handleShowAlert() {
    //
    await this.managerService.dialogService.presentAlert({
      header: AppResourceIDs.alert,
      subHeader: 'sub title',
      message: 'message',
      buttons: [
        {
          text: 'OK',
          role: XModalButtonRole.Selected,
          handler: () => {},
        },
      ],
    });
  }

  handleShowNativeAlert() {
    this.managerService.dialogService.nativeAlert(this.ResourceIDs.temp_label);
  }

  async handleShowPrompt() {
    //
    await this.managerService.dialogService.presentAlert({
      header: 'عنوان',
      subHeader: 'توضیحات',
      message: 'نام شما چیست ؟',
      inputs: [
        {
          type: 'text',
          name: 'name',
          label: 'نام',
          placeholder: 'نام و نام خانوادگی ...',
        },
      ],
      buttons: [
        {
          text: 'ثبت',
          role: XModalButtonRole.Selected,
          cssClass: ['btn-selected'],
          handler: async (value) => {
            //
            console.log('OK Clicked ...', value);

            //
            if (value && value.name && !isNullOrEmptyString(value.name)) {
              await this.managerService.notificationService.presentInfoNotification(
                {
                  message: value.name,
                  dissmissable: true,
                }
              );
            }
          },
        },
        {
          text: 'لغو',
          role: XModalButtonRole.Cancel,
          cssClass: ['btn-cancel'],
          handler: () => {
            console.log('Cancel Clicked ...');
          },
        },
      ],
    });
  }

  handleShowNativePrompt() {
    //
    this.managerService.dialogService
      .nativeConfirm(this.ResourceIDs.temp_label)
      .subscribe((res) => {
        this.managerService.notificationService.presentInfoNotification({
          message: `${res}`,
          dissmissable: true,
        });
      });
  }

  async handleShowActionModal() {
    //
    await this.managerService.dialogService.presentActionModal({
      type: XActionType.System,
      playSound: true,
      header: XResourceIDs.are_you_sure,
      buttons: [
        {
          text: XResourceIDs.yes,
          role: XModalButtonRole.Selected,
          handler: async () => {
            await this.managerService.notificationService.presentSuccessNotification(
              {
                message: 'Yes Selected ...',
                dissmissable: true,
              }
            );
          },
        },
        {
          text: XResourceIDs.no,
          role: XModalButtonRole.Cancel,
          handler: async () => {
            await this.managerService.notificationService.presentDangerNotification(
              {
                message: 'No Selected ...',
                dissmissable: true,
              }
            );
          },
        },
      ],
    });
  }

  async handleShowModal() {
    //
    const modal = await this.managerService.dialogService.presentModal({
      component: SampleModalComponent,
      componentProps: {
        context: XModalContext.Modal,
      },
    });
  }

  async handleShowPopOver(event: any) {
    //
    const popOver = await this.managerService.dialogService.presentPopover({
      event,
      component: SampleModalComponent,
      componentProps: {
        context: XModalContext.PopOver,
      },
    });
  }

  async handleShowNotification() {
    //
    await this.managerService.notificationService.presentDangerNotification({
      message: XResourceIDs.error,
      dissmissable: true,
    });
  }

  async handleShowLoading() {
    //
    const loading = await this.managerService.dialogService.presentLoading({
      message: this.resourceProvider(AppResourceIDs.default_loading),
      spinner: this.SpinnerNames.LinesSmall,
    });

    //
    // TODO: Do Actions ...

    //
    // This is for Sample tests ...
    setTimeout(() => {
      loading.dismiss();
    }, 2000);
  }

  async handleShowSelect() {
    //
    await this.managerService.dialogService.presentPicker({
      buttons: [
        {
          text: 'Ok',
          role: XModalButtonRole.Selected,
          cssClass: ['btn-selected'],
          handler: (value) => {
            console.log('OK Clicked ...', value);
          },
        },
        {
          text: 'Cancel',
          role: XModalButtonRole.Cancel,
          cssClass: ['btn-cancel'],
          handler: () => {
            console.log('Cancel Clicked ...');
          },
        },
      ],
      columns: [
        {
          name: 'Col_1',
          options: [
            {
              text: 'S 1',
              value: 1,
            },
            {
              text: 'S 2',
              value: 2,
            },
            {
              text: 'S 3',
              value: 3,
            },
            {
              text: 'S 4',
              value: 4,
            },
            {
              text: 'S 5',
              value: 5,
            },
            {
              text: 'S 6',
              value: 6,
            },
            {
              text: 'S 7',
              value: 7,
            },
            {
              text: 'S 8',
              value: 8,
            },
            {
              text: 'S 9',
              value: 9,
            },
            {
              text: 'S 10',
              value: 10,
            },
          ],
        },
      ],
    });
  }

  async handleQueryChanged(query: string) {
    //
    if (isNullOrEmptyString(query)) {
      return;
    }

    //
    await this.managerService.notificationService.presentSuccessNotification({
      message: `Search Query: ${query}`,
      dissmissable: true,
    });
  }

  async handleRefreshEmpty() {
    await this.managerService.notificationService.presentWarningNotification({
      message: 'Refresh in Empty Clicked ...',
      dissmissable: true,
    });
  }
  //#endregion
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\small-components\sample-modal\sample-modal.component.html

<div>
  <h3>Sample Modal Component</h3>
  <p>this is sample modal component content ...</p>

  <span>Binded Context: {{ context }}</span>

  <x-button (click)="handleClosePopup()">CLOSE</x-button>
</div>

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\small-components\sample-modal\sample-modal.component.scss


### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\small-components\sample-modal\sample-modal.component.ts

import { Component, Input } from '@angular/core';
import { ModalController, PopoverController } from '@ionic/angular';

export enum XModalContext {
  Modal = 'modal',
  PopOver = 'pop_over',
}

@Component({
  selector: 'app-sample-modal',
  templateUrl: './sample-modal.component.html',
  styleUrls: ['./sample-modal.component.scss'],
})
export class SampleModalComponent {
  @Input()
  context: XModalContext;

  constructor(
    private modalController: ModalController,
    private popOverController: PopoverController
  ) {}

  handleClosePopup() {
    //
    if (!this.context) {
      return;
    }

    //
    switch (this.context) {
      //
      case XModalContext.Modal:
        this.modalController.dismiss();
        break;

      //
      case XModalContext.PopOver:
        this.popOverController.dismiss();
        break;
    }
  }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\stepper\stepper.page.html

<v-page
  [hasSide]="true"
  [toolbarTitle]="toolbarTitle"
  [toolbarSubTitle]="toolbarSubTitle"
  [toolbarShowSubTitle]="toolbarShowSubTitle"
>
  <!-- Content -->
  <x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
    <!-- Content -->
    <x-markdown
      [mode]="'preview'"
      [hasToolbar]="false"
      [content]="getContent('content')"
    ></x-markdown>

    <!-- Stepper Type -->
    <x-form [formConfig]="stepperPresentationTypeFormConfig"></x-form>

    <!-- Actions -->
    <div actions>
      <a
        target="_blank"
        href="https://docs.x-framework.ir/x-framework-components/modules/XStepperModule.html"
        >{{resourceProvider(ResourceIDs.documentation)}}</a
      >
    </div>
  </x-card>

  <!-- Sample -->
  <x-markdown
    [isInPage]="true"
    [mode]="'preview'"
    [content]="sample1"
    [hasToolbar]="false"
    [wrapWithCard]="true"
    [cssClass]="'code-block'"
    [cardTitle]="resourceProvider(ResourceIDs.sample)"
  ></x-markdown>

  <!-- Stepper -->
  <x-stepper
    class="v-card"
    [isInPage]="true"
    [showLabel]="true"
    [wrapWithCard]="true"
    [cardTitle]="'Stepper'"
    [type]="currentStepperType"
    [iconColor]="ColorNames.Dark"
    [titleColor]="ColorNames.DangerShade"
    (onReset)="handleResetStepper($event)"
  >
    <!-- Step 1 -->
    <x-step [hasNext]="true" [disableNext]="xFormStepOne.status !== 'VALID'">
      <div x-step-label>Step ONe</div>

      <x-form #xFormStepOne [formConfig]="stepOneModelConfig"></x-form>
    </x-step>

    <!-- Step 2 -->
    <x-step
      [hasPrev]="true"
      [hasReset]="true"
      [disableReset]="xFormStepTwo.status !== 'VALID'"
    >
      <div x-step-label>Step TWo</div>

      <x-form #xFormStepTwo [formConfig]="stepTwoModelConfig"></x-form>
    </x-step>
  </x-stepper>
</v-page>

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\stepper\stepper.page.scss


### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\stepper\stepper.page.ts

import {
  XIconNames,
  XFormConfig,
  XStepperType,
  XFormComponent,
  XFormControlType,
  XStepperTypeIdentifier,
  XFormSelectControlOption,
  XFormStatusChangeEventModel,
} from 'x-framework-components';
import { Component } from '@angular/core';
import { Validators } from '@angular/forms';
import { XResourceIDs, isNullOrEmptyString } from 'x-framework-core';
import { VPageComponent } from '../../../views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';

interface StepOne {
  id: number;
  name: string;
  family: string;
}

interface StepTwo {
  id: number;
  userName: string;
  password: string;
}

interface StepperPresentationType {
  type: XStepperTypeIdentifier;
}

@Component({
  selector: 'app-stepper',
  templateUrl: './stepper.page.html',
  styleUrls: ['./stepper.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class StepperPage extends VPageComponent {
  //
  //#region Props ...
  //
  //#region Page Props ...
  titleRes = AppResourceIDs.stepper;
  toolbarTitle = this.resourceProvider(this.titleRes);
  toolbarSubTitle = this.resourceProvider(AppResourceIDs.stepper_description);
  toolbarShowSubTitle = true;
  //#endregion

  //
  // Prepare All Resource IDs ...
  readonly ResourceIDs = Object.assign(
    Object.assign({}, XResourceIDs),
    AppResourceIDs
  ) as any;

  //
  readonly IconNames = Object.assign({}, XIconNames);
  //#endregion

  //
  // Content ...
  readonly contentFa = `
  # ${this.toolbarTitle}
  از این مولفه جهت دریافت یا نمایش اطلاعات در گام های مختلف از کاربر استفاده می گردد.
  `;

  readonly contentEn = `
  # ${this.toolbarTitle}
  this component used to get or show data to user in several steps.
  `;

  //
  readonly sample1 =
    '```html' +
    `
<!-- Stepper -->
<x-stepper
  isInPage="true"
  showLabel="true"
  wrapWithCard="true"
  [type]="currentStepperType"
>
  <!-- Step 1 -->
  <x-step [hasNext]="true" [disableNext]="xFormStepOne.status !== 'VALID'">
    <div x-step-label>
      Step ONe
    </div>

    <x-form #xFormStepOne [formConfig]="stepOneModelConfig"></x-form>
  </x-step>

  <!-- Step 2 -->
  <x-step
    [hasPrev]="true"
    [hasReset]="true"
    [disableReset]="xFormStepTwo.status !== 'VALID'"
  >
    <div x-step-label>
      Step TWo
    </div>

    <x-form #xFormStepTwo [formConfig]="stepTwoModelConfig"></x-form>
  </x-step>
</x-stepper>
` +
    '```';

  //
  currentStepperType: XStepperTypeIdentifier;
  stepperPresentationTypes = [
    `${XStepperType.VERTICAL}`,
    `${XStepperType.HORIZONTAL}`,
  ];
  stepperPresentationTypeFormConfig: XFormConfig<StepperPresentationType> = {
    name: 'Steper_Present_Type',
    model: {
      type: XStepperType.HORIZONTAL,
    },
    controls: [
      //
      // Id ...
      {
        index: 0,
        propName: 'type',
        type: {
          type: XFormControlType.Select,
          config: {
            multiple: false,
            options: this.stepperPresentationTypes.map((k) => {
              return {
                value: k,
                viewValue: this.resourceProvider(k),
              } as XFormSelectControlOption<XStepperTypeIdentifier>;
            }),
          },
        },
        appearance: {
          label: this.ResourceIDs.type,
        },
        eventHandlers: {
          valueChanged: (model) => {
            //
            if (!model || !model.value) {
              return;
            }

            //
            const type = model.value as XStepperTypeIdentifier;
            if (!type) {
              return;
            }

            //
            this.currentStepperType = type;
            this.detectChanges();
          },
        },
      },
    ],
  };

  //
  stepOneModelConfig: XFormConfig<StepOne> = {
    name: 'StepOneForm',
    controls: [
      //
      // Id ...
      {
        index: 0,
        propName: 'id',
        type: {
          type: XFormControlType.Number,
        },
        appearance: {
          label: this.ResourceIDs.id,
        },
        validators: {
          validators: [Validators.required],
        },
      },
      //
      // Name ...
      {
        index: 1,
        propName: 'name',
        type: {
          type: XFormControlType.Text,
        },
        appearance: {
          label: this.ResourceIDs.first_name,
        },
        validators: {
          validators: [Validators.required],
        },
      },
      //
      // Family ...
      {
        index: 2,
        propName: 'family',
        type: {
          type: XFormControlType.Text,
        },
        appearance: {
          label: this.ResourceIDs.last_name,
        },
        validators: {
          validators: [Validators.required],
        },
      },
    ],
  };

  //
  stepTwoModelConfig: XFormConfig<StepTwo> = {
    name: 'StepTwoForm',
    controls: [
      //
      // Id ...
      {
        index: 0,
        propName: 'id',
        type: {
          type: XFormControlType.Number,
        },
        appearance: {
          label: this.ResourceIDs.id,
        },
        validators: {
          validators: [Validators.required],
        },
      },
      //
      // Username ...
      {
        index: 1,
        propName: 'userName',
        type: {
          type: XFormControlType.Text,
        },
        appearance: {
          label: this.ResourceIDs.username,
        },
        validators: {
          validators: [Validators.required],
        },
      },
      //
      // Password ...
      {
        index: 2,
        propName: 'password',
        type: {
          type: XFormControlType.Password,
        },
        appearance: {
          label: this.ResourceIDs.password,
        },
        validators: {
          validators: [Validators.required],
        },
      },
    ],
  };

  //
  //#region UI Providers ...
  //
  // Provide content based on current locale ...
  getContent(title: string) {
    //
    if (isNullOrEmptyString(title)) {
      return '';
    }

    //
    const currentLocale = this.managerService.currentLocale;

    //
    const varName =
      title +
      (currentLocale === 'en-US'
        ? 'En'
        : currentLocale === 'fa-IR'
        ? 'Fa'
        : '');

    const result = this[`${varName}`];

    //
    return result || '';
  }

  handleFormOneStatusChanged(
    event: XFormStatusChangeEventModel,
    form: XFormComponent
  ) {
    console.log('status changed: ', event, form.isStatusValid);
  }

  handleResetStepper(id: string) {
    //
    console.log('stepper resetted at: ', id);

    //
    this.stepOneModelConfig = {
      ...this.stepOneModelConfig,
      model: null,
    };

    //
    this.stepTwoModelConfig = {
      ...this.stepTwoModelConfig,
      model: null,
    };

    //
    this.detectChanges();
  }
  //#endregion
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\tab-navigator\tab-navigator.page.html

<v-page
  [hasSide]="true"
  [toolbarTitle]="toolbarTitle"
  [toolbarSubTitle]="toolbarSubTitle"
  [toolbarShowSubTitle]="toolbarShowSubTitle"
>
  <!-- Content -->
  <x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
    <!-- Content -->
    <x-markdown
      [mode]="'preview'"
      [hasToolbar]="false"
      [content]="getContent('content')"
    ></x-markdown>

    <!-- Sample -->
    <x-markdown
      [mode]="'preview'"
      [content]="sample1"
      [hasToolbar]="false"
      [cssClass]="'code-block'"
    ></x-markdown>

    <!-- Link to ... -->
    <a [href]="tabsHref" target="_blank"
      >{{ resourceProvider(ResourceIDs.preview) }}</a
    >

    <!-- Actions -->
    <div actions>
      <a
        target="_blank"
        href="https://docs.x-framework.ir/x-framework-components/components/XTabNavigatorComponent.html"
        >{{resourceProvider(ResourceIDs.documentation)}}</a
      >
    </div>
  </x-card>
</v-page>

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\tab-navigator\tab-navigator.page.scss


### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\tab-navigator\tab-navigator.page.ts

import { Component } from '@angular/core';
import { Pages } from 'src/app/config/page.config';
import { XIconNames } from 'x-framework-components';
import { VPageComponent } from '../../../views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';
import { XColor, XResourceIDs, isNullOrEmptyString } from 'x-framework-core';

@Component({
  selector: 'app-tab-navigator',
  templateUrl: './tab-navigator.page.html',
  styleUrls: ['./tab-navigator.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class TabNavigatorPage extends VPageComponent {
  //
  //#region Props ...
  //
  //#region Page Props ...
  titleRes = AppResourceIDs.tab_navigator;
  toolbarTitle = this.resourceProvider(this.titleRes);
  toolbarSubTitle = this.resourceProvider(
    AppResourceIDs.tab_navigator_description
  );
  toolbarShowSubTitle = true;
  //#endregion

  //
  // Prepare All Resource IDs ...
  readonly ResourceIDs = Object.assign(
    Object.assign({}, XResourceIDs),
    AppResourceIDs
  ) as any;

  //
  readonly IconNames = Object.assign({}, XIconNames);
  //#endregion

  //
  // Content ...
  readonly contentFa = `
  # ${this.toolbarTitle}
  این مولفه زمانی کاربرد دارد که قصد داریم صفحاتی را در غالب نمایه ای مبتنی بر برگه ها دسته بندی کرده و نمایش دهیم.
  `;

  readonly contentEn = `
  # ${this.toolbarTitle}
  this component used to group Pages in a Tabbed template and show them.
  `;

  //
  readonly sample1 =
    '```html' +
    `
<x-tab-navigator
  [items]="tabItems"
  [color]="ColorNames.Dark"
  [iconColor]="ColorNames.Danger"
  [highlightColor]="ColorNames.Light"
  [selectedColor]="ColorNames.SecondaryShade"
></x-tab-navigator>
` +
    '```';

  //
  tabsHref = Pages.TabsNav.baseRoute;

  //
  //#region UI Providers ...
  //
  // Provide content based on current locale ...
  getContent(title: string) {
    //
    if (isNullOrEmptyString(title)) {
      return '';
    }

    //
    const currentLocale = this.managerService.currentLocale;

    //
    const varName =
      title +
      (currentLocale === 'en-US'
        ? 'En'
        : currentLocale === 'fa-IR'
        ? 'Fa'
        : '');

    const result = this[`${varName}`];

    //
    return result || '';
  }
  //#endregion
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\table\table.page.html

<v-page
  [hasSide]="true"
  [toolbarTitle]="toolbarTitle"
  [toolbarSubTitle]="toolbarSubTitle"
  [toolbarShowSubTitle]="toolbarShowSubTitle"
>
  <!-- Content -->
  <x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
    <!-- Content -->
    <x-markdown
      [mode]="'preview'"
      [hasToolbar]="false"
      [content]="getContent('content')"
    ></x-markdown>

    <!-- Actions -->
    <div actions>
      <a
        target="_blank"
        href="https://docs.x-framework.ir/x-framework-components/components/XTableComponent.html"
        >{{resourceProvider(ResourceIDs.documentation)}}</a
      >
    </div>
  </x-card>

  <!-- Samples -->
  <x-markdown
    [isInPage]="true"
    [mode]="'preview'"
    [content]="sample1"
    [hasToolbar]="false"
    [wrapWithCard]="true"
    [cssClass]="'code-block'"
  ></x-markdown>

  <x-markdown
    [isInPage]="true"
    [mode]="'preview'"
    [content]="sample2"
    [hasToolbar]="false"
    [wrapWithCard]="true"
    [cssClass]="'code-block'"
  ></x-markdown>

  <x-table
    [isInPage]="true"
    [showHeader]="true"
    [wrapWithCard]="true"
    [showSearchBar]="true"
    [showPaginator]="true"
    [showActionBar]="true"
    [selectableRows]="true"
    [color]="ColorNames.Medium"
    [properties]="tempTableProps"
    [headerColor]="ColorNames.Dark"
    [actionBarColor]="ColorNames.DarkShade"
    [searchBarColor]="ColorNames.DarkShade"
    [paginatorColor]="ColorNames.DarkShade"
    (removeItems)="handleRemoveItems($event)"
    (rowSelected)="handleRowSelected($event)"
    [searchBarPosition]="TableItemPositions.TOP"
    [actionBarPosition]="TableItemPositions.TOP"
    [paginatorPosition]="TableItemPositions.BOTTOM"
    (rowSelectionChanged)="handleRowSelectionChanged($event)"
  >
  </x-table>
</v-page>

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\table\table.page.scss


### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\table\table.page.ts

import {
  XResourceIDs,
  isNullOrEmptyString,
  XColorWithBrightness,
} from 'x-framework-core';
import {
  XIconNames,
  XTableConfig,
  XTableItemPosition,
} from 'x-framework-components';
import { Component } from '@angular/core';
import { VPageComponent } from '../../../views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';

interface Temp {
  id?: string;
  name: string;
  family: string;
  phoneNumber: string;
  value: string;
  slided: boolean;
  checked: boolean;
  level: number;
  person: string;
  dob: Date;
}

@Component({
  selector: 'app-table',
  templateUrl: './table.page.html',
  styleUrls: ['./table.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class TablePage extends VPageComponent {
  //
  //#region Props ...
  //
  //#region Page Props ...
  titleRes = AppResourceIDs.table;
  toolbarTitle = this.resourceProvider(this.titleRes);
  toolbarSubTitle = this.resourceProvider(AppResourceIDs.table_description);
  toolbarShowSubTitle = true;
  //#endregion

  //
  // Prepare All Resource IDs ...
  readonly ResourceIDs = Object.assign(
    Object.assign({}, XResourceIDs),
    AppResourceIDs
  ) as any;

  //
  readonly IconNames = Object.assign({}, XIconNames);
  readonly ColorNames = Object.assign({}, XColorWithBrightness);
  //#endregion

  //
  //#region Data Preparation For Table ...
  //
  readonly TableItemPositions = Object.assign({}, XTableItemPosition);

  //
  tempItems: Partial<Temp>[] = [
    {
      id: '71f14439-262f-44bf-8dc8-ee85929c349c',
      name: 'Deidre',
      family: 'Thomas',
      phoneNumber: '+98 (864) 472-3812',
    },
    {
      id: 'caa22853-dd2d-4669-8b63-b1fe4a38ea07',
      name: 'Hubbard',
      family: 'Preston',
      phoneNumber: '+98 (899) 452-3720',
    },
    {
      id: 'ccb62dc4-a06b-412d-800d-02d18f54a0e0',
      name: 'Cooley',
      family: 'Nixon',
      phoneNumber: '+98 (926) 459-2360',
    },
    {
      id: '6a946279-fe01-4e17-bb2c-a1931780ce9d',
      name: 'Becky',
      family: 'Wallace',
      phoneNumber: '+98 (914) 519-3589',
    },
    {
      id: '8601242a-f2ff-465f-8275-5b991b4a8ade',
      name: 'Kidd',
      family: 'Shelton',
      phoneNumber: '+98 (848) 570-3661',
    },
    {
      id: '1f4bd5e8-d7be-460d-9bfb-f0738957bc4b',
      name: 'Caitlin',
      family: 'Camacho',
      phoneNumber: '+98 (959) 453-2722',
    },
    {
      id: '18a874dc-1f3d-4cdc-a3c7-69d2f417e18e',
      name: 'Estes',
      family: 'Rivera',
      phoneNumber: '+98 (917) 436-3237',
    },
    {
      id: '5a5f2a8e-d20e-4fe9-ae6f-84dde7602e9f',
      name: 'Ines',
      family: 'Powell',
      phoneNumber: '+98 (917) 539-3108',
    },
    {
      id: '663c8403-e525-4b51-b262-e876e97d4532',
      name: 'Carrillo',
      family: 'Acevedo',
      phoneNumber: '+98 (828) 556-3742',
    },
    {
      id: '7e6d0bb6-4180-4329-96cc-364a9a534a04',
      name: 'Ina',
      family: 'Wilkinson',
      phoneNumber: '+98 (933) 560-3834',
    },
    {
      id: '19c21deb-f8b7-40c7-a0bb-da203193c114',
      name: 'Mercer',
      family: 'Adkins',
      phoneNumber: '+98 (981) 480-3459',
    },
    {
      id: 'c2e4de31-d406-4611-9dbe-cd7bdefdc5bc',
      name: 'Donaldson',
      family: 'Vega',
      phoneNumber: '+98 (986) 554-2571',
    },
    {
      id: 'cf846f56-b381-447b-96a1-0d7c29736f4f',
      name: 'Natalie',
      family: 'Cantu',
      phoneNumber: '+98 (857) 445-2595',
    },
    {
      id: 'c5252e01-8a26-44f1-846d-28c8810b10b8',
      name: 'Christa',
      family: 'Higgins',
      phoneNumber: '+98 (983) 498-3785',
    },
    {
      id: 'e7e5b97a-67f8-4bff-8c8c-b68cf6a24b2f',
      name: 'Kelley',
      family: 'Pitts',
      phoneNumber: '+98 (948) 588-3437',
    },
    {
      id: '9db9d0ab-a2c4-4edb-8d0b-e664c86c4e55',
      name: 'Shelby',
      family: 'Macdonald',
      phoneNumber: '+98 (882) 401-2642',
    },
    {
      id: '41305b10-aa7a-415d-a819-5e6ab05e0a49',
      name: 'Preston',
      family: 'Patton',
      phoneNumber: '+98 (923) 509-3278',
    },
    {
      id: '35acdcfe-7015-4a27-a5de-0f5c701a9152',
      name: 'Allen',
      family: 'Flores',
      phoneNumber: '+98 (957) 587-3471',
    },
    {
      id: '31f568b8-272a-43c5-bb7a-bf25c2fa6da9',
      name: 'Margaret',
      family: 'Neal',
      phoneNumber: '+98 (870) 480-3528',
    },
    {
      id: '5ef4be35-3d02-45f7-9c25-bf828b4a3845',
      name: 'Kirkland',
      family: 'Hewitt',
      phoneNumber: '+98 (958) 466-2957',
    },
    {
      id: 'e581d671-5d35-4c21-af77-71f881f8d764',
      name: 'Herminia',
      family: 'Silva',
      phoneNumber: '+98 (925) 546-3981',
    },
    {
      id: '4242bc21-945e-4cbe-b73c-bacc0c8b2013',
      name: 'Galloway',
      family: 'Tyler',
      phoneNumber: '+98 (971) 468-2144',
    },
    {
      id: '58f91369-8718-4c01-aff8-8a5d65527948',
      name: 'Hull',
      family: 'Rojas',
      phoneNumber: '+98 (950) 439-3702',
    },
    {
      id: 'e6d25e18-f272-4ac3-b7f6-54c8bae985b5',
      name: 'Sandoval',
      family: 'Norton',
      phoneNumber: '+98 (920) 439-2511',
    },
    {
      id: 'bff9bdad-2947-4fd9-a18a-92388e32aa0b',
      name: 'Alba',
      family: 'Collins',
      phoneNumber: '+98 (957) 445-2714',
    },
    {
      id: '8272763a-6a67-41da-924e-0f417fb259da',
      name: 'Montoya',
      family: 'Stein',
      phoneNumber: '+98 (889) 585-3578',
    },
    {
      id: '29a6ff2c-746e-4214-b28f-073ac201ea96',
      name: 'Grant',
      family: 'Gilliam',
      phoneNumber: '+98 (814) 562-3575',
    },
    {
      id: '416cb3f4-30ae-4874-a7c3-ffd401cf6c3f',
      name: 'Meadows',
      family: 'Mcknight',
      phoneNumber: '+98 (994) 589-2830',
    },
    {
      id: 'd061721e-ca9c-4054-9aa1-1196a51a0256',
      name: 'Harris',
      family: 'Rhodes',
      phoneNumber: '+98 (853) 489-2436',
    },
    {
      id: 'd01323d5-5126-4c8a-ad89-0298acf4d82d',
      name: 'Frieda',
      family: 'Hayden',
      phoneNumber: '+98 (930) 436-2770',
    },
    {
      id: '34225f99-0986-4294-95f2-3c8961b15036',
      name: 'Rasmussen',
      family: 'Ross',
      phoneNumber: '+98 (821) 599-2812',
    },
    {
      id: '6f7a24d4-8b82-45c4-8b5b-a3053c5a7023',
      name: 'Mitzi',
      family: 'Gregory',
      phoneNumber: '+98 (838) 404-3840',
    },
    {
      id: 'acba244a-12b5-4291-beb2-66a64127121d',
      name: 'Washington',
      family: 'Cruz',
      phoneNumber: '+98 (975) 465-2025',
    },
    {
      id: '2c70c776-80dd-4be9-b32f-6af7d6cea5b0',
      name: 'Jewell',
      family: 'Rios',
      phoneNumber: '+98 (909) 453-3851',
    },
    {
      id: '5f98d7a6-c98b-4dc7-bf90-4df04074b57e',
      name: 'Heath',
      family: 'Bush',
      phoneNumber: '+98 (976) 516-3200',
    },
    {
      id: 'bc51bdc5-47f6-45b4-8c51-6d86324b90d2',
      name: 'Laura',
      family: 'Edwards',
      phoneNumber: '+98 (966) 546-3720',
    },
    {
      id: 'f1f47337-cc3f-49e4-acb7-5989f5eb1a30',
      name: 'Harriett',
      family: 'Sanders',
      phoneNumber: '+98 (816) 579-3042',
    },
    {
      id: '2fce8cd5-398c-4d73-8151-3d0fb375ff49',
      name: 'Milagros',
      family: 'Vazquez',
      phoneNumber: '+98 (941) 437-2907',
    },
    {
      id: 'b725ce24-b08d-4c8e-95ec-5926804ccde3',
      name: 'Sheila',
      family: 'Aguilar',
      phoneNumber: '+98 (855) 509-3995',
    },
    {
      id: 'f7d64d31-43d2-416f-ba19-397b407afeba',
      name: 'Eunice',
      family: 'Langley',
      phoneNumber: '+98 (959) 564-2615',
    },
    {
      id: '6f73fd66-2931-4f1f-9cd1-95803724ff38',
      name: 'Valerie',
      family: 'House',
      phoneNumber: '+98 (985) 550-3203',
    },
    {
      id: '17fab0f9-f37d-4ed0-8656-98b9f9c65333',
      name: 'Carmella',
      family: 'Young',
      phoneNumber: '+98 (964) 548-3625',
    },
    {
      id: '7e9e3057-34df-4727-8a7e-750e876a7ca8',
      name: 'Brittany',
      family: 'Pennington',
      phoneNumber: '+98 (840) 499-3543',
    },
    {
      id: '4ca1aebb-8d6f-4c62-9633-353abf1cab06',
      name: 'Polly',
      family: 'Roberts',
      phoneNumber: '+98 (821) 554-2791',
    },
    {
      id: '147c9f63-800a-4600-94dd-7fa39e233cd7',
      name: 'Estrada',
      family: 'Tate',
      phoneNumber: '+98 (844) 586-3191',
    },
    {
      id: 'decca57e-7d69-4152-99f0-3a56262db788',
      name: 'Aimee',
      family: 'Morrow',
      phoneNumber: '+98 (920) 522-2471',
    },
    {
      id: '1b7d57b2-0169-4949-a1e9-42137085dcda',
      name: 'Elinor',
      family: 'Gill',
      phoneNumber: '+98 (981) 525-3212',
    },
    {
      id: 'db3e2d62-d8cf-4809-9226-49a34a4fbea1',
      name: 'Velasquez',
      family: 'Taylor',
      phoneNumber: '+98 (879) 440-2756',
    },
    {
      id: 'a3f6bda0-0975-4e4e-8bcd-1a9be84777ac',
      name: 'Hardin',
      family: 'Rowe',
      phoneNumber: '+98 (945) 564-3793',
    },
    {
      id: '17c0c061-3215-429d-9172-be3d8ca69119',
      name: 'Miranda',
      family: 'Hendrix',
      phoneNumber: '+98 (804) 519-2572',
    },
    {
      id: '634862e6-09bf-41c3-8553-c8807aab2b22',
      name: 'Kristin',
      family: 'Mcgowan',
      phoneNumber: '+98 (974) 533-3607',
    },
    {
      id: '4214933e-a57c-495c-8c32-ddb9960556f6',
      name: 'Ila',
      family: 'Gutierrez',
      phoneNumber: '+98 (814) 546-2444',
    },
    {
      id: '74f62419-a4eb-414f-9a84-d82dfd117917',
      name: 'Sophie',
      family: 'Pena',
      phoneNumber: '+98 (962) 458-3451',
    },
    {
      id: 'c3cc6ff3-d0ef-45fb-b6a7-b499ff13fedf',
      name: 'Sara',
      family: 'Burton',
      phoneNumber: '+98 (937) 516-2702',
    },
    {
      id: '969ca3e7-78ad-4fbe-b413-0e12021d07b9',
      name: 'Valeria',
      family: 'Spence',
      phoneNumber: '+98 (968) 403-2227',
    },
    {
      id: 'e73ba5bb-adb7-423e-a6e9-22be1501987c',
      name: 'Stefanie',
      family: 'Erickson',
      phoneNumber: '+98 (950) 545-2095',
    },
    {
      id: '83ae1198-c533-43dd-ae1a-85bc5f503293',
      name: 'Bean',
      family: 'Newman',
      phoneNumber: '+98 (824) 504-2755',
    },
    {
      id: 'a2f3949a-7d24-4c42-ac6d-573c11c903fd',
      name: 'Tracie',
      family: 'Keith',
      phoneNumber: '+98 (981) 499-3453',
    },
    {
      id: '7f52c00e-4ccb-4458-ad0c-bb7d9ff759a4',
      name: 'Cardenas',
      family: 'Trevino',
      phoneNumber: '+98 (942) 476-2939',
    },
    {
      id: '48f9d38e-9211-420f-968e-098f7a3dfeaf',
      name: 'Yolanda',
      family: 'Hamilton',
      phoneNumber: '+98 (936) 418-3047',
    },
    {
      id: '0f739ca9-1a2a-41f1-b703-9ddc98e7b328',
      name: 'Mendoza',
      family: 'Cunningham',
      phoneNumber: '+98 (980) 547-3912',
    },
    {
      id: '3e3e68cc-053a-4811-9987-7c700fcc32ee',
      name: 'Singleton',
      family: 'Harmon',
      phoneNumber: '+98 (975) 564-3890',
    },
    {
      id: 'd7d6e72b-5a63-440d-bdf0-125bd9d8d4dd',
      name: 'Witt',
      family: 'Huffman',
      phoneNumber: '+98 (867) 475-3332',
    },
    {
      id: '46c951e3-ab31-44ca-b5eb-2f988dd57562',
      name: 'James',
      family: 'Mccullough',
      phoneNumber: '+98 (895) 507-2233',
    },
    {
      id: '9b7b2396-5758-44be-9d5d-4eef04742a53',
      name: 'Stevenson',
      family: 'Robles',
      phoneNumber: '+98 (847) 587-3623',
    },
    {
      id: 'a0db4093-ec6b-41ed-8ca5-a9b43ee302b7',
      name: 'Mcknight',
      family: 'Perry',
      phoneNumber: '+98 (881) 443-2991',
    },
    {
      id: '1ad02420-9ac0-4250-940c-fc0ea24964a8',
      name: 'Flowers',
      family: 'Emerson',
      phoneNumber: '+98 (933) 514-3019',
    },
    {
      id: 'b2ffa8f4-4f95-4b9d-a219-780d5f4dbd69',
      name: 'Karin',
      family: 'James',
      phoneNumber: '+98 (958) 486-2623',
    },
    {
      id: 'd87e51b3-80db-4e7c-b0d0-9f39c633b70a',
      name: 'Marisol',
      family: 'William',
      phoneNumber: '+98 (961) 533-3778',
    },
    {
      id: '1ce985cc-f810-4972-8e9b-59dfb67b161c',
      name: 'Emilia',
      family: 'Black',
      phoneNumber: '+98 (984) 592-2589',
    },
    {
      id: '4b5be713-cb7e-46cb-b72b-e8c4f644693a',
      name: 'Irene',
      family: 'Miles',
      phoneNumber: '+98 (950) 431-2351',
    },
    {
      id: 'c1ff3dfd-21b4-4824-aeef-d3b6a36ba3ab',
      name: 'Tonia',
      family: 'Serrano',
      phoneNumber: '+98 (955) 511-2933',
    },
    {
      id: '97eec6ce-ccb0-4050-b413-96a0a4afce7a',
      name: 'Thelma',
      family: 'Odom',
      phoneNumber: '+98 (844) 524-2142',
    },
    {
      id: 'e9111905-fc22-4e35-a3a6-4a4c0b6bc0c0',
      name: 'Kerry',
      family: 'Rose',
      phoneNumber: '+98 (947) 581-2952',
    },
    {
      id: '9129d569-5acd-43b7-8eac-de7a9f4f7336',
      name: 'Mcgee',
      family: 'Hernandez',
      phoneNumber: '+98 (865) 521-3785',
    },
    {
      id: '221e68ec-0462-4418-88c9-d433f1d60ae1',
      name: 'Shepard',
      family: 'Santiago',
      phoneNumber: '+98 (892) 446-3690',
    },
    {
      id: '429b8bcc-028d-4989-89d9-5519dc6fec0f',
      name: 'Emily',
      family: 'French',
      phoneNumber: '+98 (836) 537-3964',
    },
    {
      id: 'c750ebd9-9aa0-426f-b668-5702500f7178',
      name: 'Clements',
      family: 'Carson',
      phoneNumber: '+98 (916) 460-3168',
    },
    {
      id: '2f75f87c-65f9-479b-bec4-5c83fbbfb96a',
      name: 'Gibbs',
      family: 'Burch',
      phoneNumber: '+98 (950) 543-2339',
    },
    {
      id: '6dbf72ff-5761-4c0b-9781-93cd4606fd4b',
      name: 'Pearson',
      family: 'Petersen',
      phoneNumber: '+98 (889) 591-2938',
    },
    {
      id: '8944a741-1f18-4d30-8536-a306ab1b5b8f',
      name: 'Stout',
      family: 'Castillo',
      phoneNumber: '+98 (938) 578-3360',
    },
    {
      id: 'aca707ac-97fe-4f7f-8665-ab34d863bc3a',
      name: 'Leonard',
      family: 'Finch',
      phoneNumber: '+98 (821) 441-3242',
    },
    {
      id: '43cc621c-17fb-4196-a28e-658f1fc4752e',
      name: 'Nelson',
      family: 'Kirkland',
      phoneNumber: '+98 (869) 431-2288',
    },
    {
      id: '63292aab-ddc3-4dd8-851a-6430c85f3ad3',
      name: 'Olson',
      family: 'Sherman',
      phoneNumber: '+98 (865) 446-3664',
    },
    {
      id: '40f28107-6a4d-4c1c-a506-a8dc4d65c6e4',
      name: 'Bray',
      family: 'Hansen',
      phoneNumber: '+98 (808) 532-3820',
    },
    {
      id: '02ab1c0b-654f-4277-92dd-1a0219bda442',
      name: 'Antonia',
      family: 'Bell',
      phoneNumber: '+98 (802) 572-3045',
    },
    {
      id: '15019624-9683-4977-a2d8-dc47e434f086',
      name: 'Cecile',
      family: 'Maxwell',
      phoneNumber: '+98 (804) 452-2908',
    },
  ];

  //
  tempTableProps: XTableConfig<Partial<Temp>> = {
    items: [...this.tempItems],
    columns: [
      {
        name: 'name',
        title: 'Name',
        sortable: true,
        description: 'Name of Person',
      },
      {
        name: 'family',
        title: 'Family',
        sortable: true,
        description: 'LastName of Person',
        // hidden: this.managerService.isMobileUi$
      },
      {
        name: 'phoneNumber',
        title: 'Phone Number',
        description: 'Phone Number of Person',
        // hidden: this.managerService.isMobileUi$
      },
      {
        customColumn: true,
        name: 'Actions',
        title: 'Actions',
        description: 'row Action',
      },
    ],
  };
  //#endregion

  //
  // Content ...
  readonly contentFa = `
# ${this.toolbarTitle}
این مولفه جهت نمایش داده های مرتبط بصورت جدول بکار می رود.
`;

  readonly contentEn = `
# ${this.toolbarTitle}
this Component used to show a collection of related Data in a Table.
`;

  //
  readonly sample1 =
    '```typescript' +
    `
  //
  interface Temp {
    id?: string;
    name: string;
    family: string;
    phoneNumber: string;
    value: string;
    slided: boolean;
    checked: boolean;
    level: number;
    person: string;
    dob: Date;
  }

  //
  tempTableProps: XTableProps<Partial<Temp>> = {
    items: [
      {
        id: '
          71f14439-262f-44bf-8dc8-ee85929c349c',
        name: 'Deidre',
        family: 'Thomas',
        phoneNumber: '+98 (864) 472-3812'
      },
      {
        id: '
          caa22853-dd2d-4669-8b63-b1fe4a38ea07',
        name: 'Hubbard',
        family: 'Preston',
        phoneNumber: '+98 (899) 452-3720'
      },
      {
        id: '
          ccb62dc4-a06b-412d-800d-02d18f54a0e0',
        name: 'Cooley',
        family: 'Nixon',
        phoneNumber: '+98 (926) 459-2360'
      },
      {
        ...
      },
      ...
    ],
    columns: [
      {
        name: 'name',
        title: 'Name',
        sortable: true,
        description: 'Name of Person'
      },
      {
        name: 'family',
        title: 'Family',
        sortable: true,
        description: 'LastName of Person'
      },
      {
        name: 'phoneNumber',
        title: 'Phone Number',
        description: 'Phone Number of Person'
      },
      {
        customColumn: true,
        name: 'Actions',
        title: 'Actions',
        description: 'row Action'
      }
    ]
  };
` +
    '```';

  //
  readonly sample2 =
    '```html' +
    `
<x-table
    [showHeader]="true"
    [showSearchBar]="true"
    [showPaginator]="true"
    [showActionBar]="true"
    [selectableRows]="true"
    [color]="ColorNames.Medium"
    [properties]="tempTableProps"
    [headerColor]="ColorNames.Dark"
    [actionBarColor]="ColorNames.Primary"
    [searchBarColor]="ColorNames.Primary"
    [paginatorColor]="ColorNames.Primary"
    (rowSelected)="handleRowSelected($event)"
    [searchBarPosition]="
      TableItemPositions.TOP"
    [actionBarPosition]="
      TableItemPositions.TOP"
    [paginatorPosition]="
      TableItemPositions.BOTTOM"
    (rowSelectionChanged)="
      handleRowSelectionChanged($event)"
>
</x-table>
` +
    '```';

  //
  //#region UI Providers ...
  //
  // Provide content based on current locale ...
  getContent(title: string) {
    //
    if (isNullOrEmptyString(title)) {
      return '';
    }

    //
    const currentLocale = this.managerService.currentLocale;

    //
    const varName =
      title +
      (currentLocale === 'en-US'
        ? 'En'
        : currentLocale === 'fa-IR'
        ? 'Fa'
        : '');

    const result = this[`${varName}`];

    //
    return result || '';
  }

  //
  handleRowSelected(row: any) {
    console.log('handleRowSelected: ', row);
  }

  //
  handleRowSelectionChanged(selectedRows: any[]) {
    console.log('handleRowSelectionChanged: ', selectedRows);
  }

  //
  async handleRemoveItems(items: Partial<Temp>[]) {
    //
    console.log('Remove Items: ', items);
    if (!this.hasChild(items)) {
      return;
    }

    //
    const removedItems = this.tempItems.filter((i) => !items.includes(i));
    console.log('num of items before remove: ', this.tempItems.length);
    console.log('num of items after remove: ', removedItems.length);

    //
    const newTableProps = {
      ...this.tempTableProps,
      items: [...removedItems],
    };

    //
    this.tempTableProps = {
      ...newTableProps,
    };

    //
    this.detectChanges();
  }
  //#endregion
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\tabs\tabs.page.html

<v-page
  [hasSide]="true"
  [toolbarTitle]="toolbarTitle"
  [toolbarSubTitle]="toolbarSubTitle"
  [toolbarShowSubTitle]="toolbarShowSubTitle"
>
  <!-- Content -->
  <x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
    <!-- Content -->
    <x-markdown
      [mode]="'preview'"
      [hasToolbar]="false"
      [content]="getContent('content')"
    ></x-markdown>

    <!-- Actions -->
    <div actions>
      <a
        target="_blank"
        href="https://docs.x-framework.ir/x-framework-components/modules/XTabsModule.html"
        >{{resourceProvider(ResourceIDs.documentation)}}</a
      >
    </div>
  </x-card>

  <!-- Samples -->
  <x-markdown
    [isInPage]="true"
    [mode]="'preview'"
    [content]="sample1"
    [hasToolbar]="false"
    [wrapWithCard]="true"
    [cssClass]="'code-block'"
    [cardTitle]="resourceProvider(ResourceIDs.sample)"
  ></x-markdown>

  <!-- Components -->
  <x-tabs
    #xTabs
    [isInPage]="true"
    [swipable]="true"
    [loopTabs]="false"
    [selectedIndex]="1"
    [wrapWithCard]="true"
    [dynamicHeight]="false"
    [color]="ColorNames.Dark"
    [alignTabs]="TabAligns.STRETCH"
    [activeTabColor]="ColorNames.Medium"
    [tabPaginatorColor]="ColorNames.Dark"
    [tabIndicatorColor]="ColorNames.Warning"
    [headerPosition]="TabsHeaderPositions.BELOW"
  >
    <x-tab>
      <div x-tab-label>
        Tab 1
      </div>
      <div class="tab-wrapper" [xColor]="ColorNames.Danger">
        Lorem ipsum dolor sit amet consectetur adipisicing elit. Omnis similique
        reiciendis vero vel. Et, in nemo. Sapiente doloremque provident ex
        dolore, expedita totam ipsam architecto vero mollitia magni. Corporis,
        dolore.
      </div>
    </x-tab>

    <x-tab>
      <div x-tab-label>
        Tab 2
      </div>

      <div class="tab-wrapper" [xColor]="ColorNames.Secondary">
        Lorem ipsum dolor sit amet consectetur adipisicing elit. Omnis similique
        reiciendis vero vel. Et, in nemo. Sapiente doloremque provident ex
        dolore, expedita totam ipsam architecto vero mollitia magni. Corporis,
        dolore.
      </div>
    </x-tab>

    <x-tab>
      <div x-tab-label>
        Tab 3
      </div>

      <div class="tab-wrapper" [xColor]="ColorNames.Warning">
        Lorem ipsum dolor sit amet consectetur adipisicing elit. Omnis similique
        reiciendis vero vel. Et, in nemo. Sapiente doloremque provident ex
        dolore, expedita totam ipsam architecto vero mollitia magni. Corporis,
        dolore.
      </div>
    </x-tab>

    <x-tab>
      <div x-tab-label>
        Tab 4
      </div>

      <div class="tab-wrapper" [xColor]="color">
        Lorem ipsum dolor sit amet consectetur adipisicing elit. Omnis similique
        reiciendis vero vel. Et, in nemo. Sapiente doloremque provident ex
        dolore, expedita totam ipsam architecto vero mollitia magni. Corporis,
        dolore.
      </div>
    </x-tab>
  </x-tabs>
</v-page>

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\tabs\tabs.page.scss

.tab-wrapper {
  padding: {
    top: 24px;
    left: 6px;
    right: 6px;
    bottom: 24px;
  };
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\tabs\tabs.page.ts

import {
  XTabAlign,
  XIconNames,
  XTabsHeaderPosition,
} from 'x-framework-components';
import { Component } from '@angular/core';
import { VPageComponent } from '../../../views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';
import { XResourceIDs, isNullOrEmptyString, XColor } from 'x-framework-core';

@Component({
  selector: 'app-tabs',
  templateUrl: './tabs.page.html',
  styleUrls: ['./tabs.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class TabsPage extends VPageComponent {
  //
  //#region Props ...
  //
  //#region Page Props ...
  titleRes = AppResourceIDs.tabs;
  toolbarTitle = this.resourceProvider(this.titleRes);
  toolbarSubTitle = this.resourceProvider(AppResourceIDs.tabs_description);
  toolbarShowSubTitle = true;
  //#endregion

  //
  // Prepare All Resource IDs ...
  readonly ResourceIDs = Object.assign(
    Object.assign({}, XResourceIDs),
    AppResourceIDs
  ) as any;

  //
  readonly IconNames = Object.assign({}, XIconNames);
  //#endregion

  //
  readonly TabAligns = Object.assign({}, XTabAlign);
  readonly TabsHeaderPositions = Object.assign({}, XTabsHeaderPosition);

  //
  // Content ...
  readonly contentFa = `
  # ${this.toolbarTitle}
  این مولفه جهت نمایش محتواهای مختلف در غالب برگه ها و دسته بندی آن ها بکار می رود
  `;

  readonly contentEn = `
  # ${this.toolbarTitle}
  this component used to group several contents and show them in tabs area.
  `;

  //
  readonly sample1 =
    '```html' +
    `
<x-tabs
  #xTabs
  [startIndex]="1"
  [swipable]="true"
  [loopTabs]="false"
  [dynamicHeight]="false"
  [color]="ColorNames.Dark"
  [alignTabs]="TabAligns.START"
  [headerPosition]="
    TabsHeaderPositions.BELOW"
>
  <x-tab>
    <div x-tab-label>
      Tab 1
    </div>
    <div
      class="tab-wrapper"
      [xColor]="ColorNames.Danger"
    >
      Lorem ipsum dolor sit amet
      consectetur adipisicing elit.
      Omnis similique reiciendis vero
      vel. Et, in nemo. Sapiente
      doloremque provident ex dolore,
      expedita totam ipsam architecto
      vero mollitia magni. Corporis, dolore.
    </div>
  </x-tab>

  <x-tab>
    <div x-tab-label>
      Tab 2
    </div>

    <div
      class="tab-wrapper"
      [xColor]="ColorNames.Secondary"
    >
      Lorem ipsum dolor sit amet
      consectetur adipisicing elit.
      Omnis similique reiciendis vero
      vel. Et, in nemo. Sapiente
      doloremque provident ex dolore,
      expedita totam ipsam architecto
      vero mollitia magni. Corporis, dolore.
    </div>
  </x-tab>

  <x-tab>
    <div x-tab-label>
      Tab 3
    </div>

    <div
      class="tab-wrapper"
      [xColor]="ColorNames.Warning"
    >
      Lorem ipsum dolor sit amet
      consectetur adipisicing elit.
      Omnis similique reiciendis vero
      vel. Et, in nemo. Sapiente
      doloremque provident ex dolore,
      expedita totam ipsam architecto
      vero mollitia magni. Corporis, dolore.
    </div>
  </x-tab>

  <x-tab>
    <div x-tab-label>
      Tab 4
    </div>

    <div
      class="tab-wrapper"
      [xColor]="color"
    >
      Lorem ipsum dolor sit amet
      consectetur adipisicing elit.
      Omnis similique reiciendis vero
      vel. Et, in nemo. Sapiente
      doloremque provident ex dolore,
      expedita totam ipsam architecto
      vero mollitia magni. Corporis, dolore.
    </div>
  </x-tab>
</x-tabs>
` +
    '```';

  //
  //#region UI Providers ...
  //
  // Provide content based on current locale ...
  getContent(title: string) {
    //
    if (isNullOrEmptyString(title)) {
      return '';
    }

    //
    const currentLocale = this.managerService.currentLocale;

    //
    const varName =
      title +
      (currentLocale === 'en-US'
        ? 'En'
        : currentLocale === 'fa-IR'
        ? 'Fa'
        : '');

    const result = this[`${varName}`];

    //
    return result || '';
  }
  //#endregion
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\tree\tree.page.html

<v-page
  [hasSide]="true"
  [toolbarTitle]="toolbarTitle"
  [toolbarSubTitle]="toolbarSubTitle"
  [toolbarShowSubTitle]="toolbarShowSubTitle"
>
  <!-- Content -->
  <x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
    <!-- Actions -->
    <div actions>
      <a
        target="_blank"
        href="https://docs.x-framework.ir/x-framework-components/components/XTreeComponent.html"
        >{{resourceProvider(ResourceIDs.documentation)}}</a
      >
    </div>
  </x-card>

  <!-- TODO: Complete this ... -->
  <x-button
    [type]="ButtonTypes.Raised"
    [title]="'Expand All'"
    (clicked)="handleTreeExpandAll()"
  ></x-button>

  <x-button
    [type]="ButtonTypes.Raised"
    [title]="'Collapse All'"
    (clicked)="handleTreeCollapseAll()"
  ></x-button>

  <x-button
    [type]="ButtonTypes.Raised"
    [title]="'Expand'"
    (clicked)="handleTreeExpand(1)"
  ></x-button>

  <x-button
    [type]="ButtonTypes.Raised"
    [title]="'Collapse'"
    (clicked)="handleTreeCollapse(1)"
  ></x-button>

  <!-- Tree -->
  <x-tree
    [isInPage]="true"
    [nodes]="treeNodes"
    [wrapWithCard]="true"
    [nodeTemplate]="todoItemRef"
    [actionProvider]="treeActionProvider"
    [toggleIconColor]="ColorNames.SuccessShade"
    (onNodeToggle)="handleTreeNodeToggled($event)"
  ></x-tree>
</v-page>

<!-- ToDo Item Template -->
<ng-template #todoItemRef let-data let-nodeId="nodeId">
  <!-- Title -->
  <div class="v-todo-title">{{ nodeId }}</div>

  <!-- Body -->
  <ng-container *ngIf="(data | xAs : XProgrammingTech) as data">
    <div class="v-todo-description">
      <div>Name: {{ data.name }}</div>

      <div>Description: {{ data.description }}</div>
    </div>
  </ng-container>
</ng-template>

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\tree\tree.page.scss

:host(::ng-deep.mat-tree-node) {
    align-items: baseline !important;
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\components\tree\tree.page.ts

import { Subject } from 'rxjs';
import {
  XTreeNode,
  XIconNames,
  XButtonType,
  XTreeAction,
  XTreeNodeToggle,
  XTreeActionModel,
} from 'x-framework-components';
import { Component } from '@angular/core';
import { XResourceIDs } from 'x-framework-core';
import { VPageComponent } from 'src/app/views/v-page/v-page.component';

interface ProgrammingTech {
  name: string;
  description: string;
}

@Component({
  selector: 'app-tree',
  templateUrl: './tree.page.html',
  styleUrls: ['./tree.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class TreePage extends VPageComponent {
  //
  //#region Props ...
  //
  //#region Page Props ...
  titleRes = this.AppResourceIDs.tree;
  toolbarTitle = this.resourceProvider(this.titleRes);
  toolbarSubTitle = this.resourceProvider(this.AppResourceIDs.tree_description);
  toolbarShowSubTitle = true;

  //
  treeActionProvider = new Subject<XTreeActionModel>();
  //#endregion

  //
  // Prepare All Resource IDs ...
  readonly ResourceIDs = Object.assign(
    Object.assign({}, XResourceIDs),
    this.AppResourceIDs
  ) as any;

  //
  readonly IconNames = Object.assign({}, XIconNames);
  readonly ButtonTypes = Object.assign({}, XButtonType);
  //#endregion

  //
  XProgrammingTech: ProgrammingTech;
  treeNodes = this.getTreeNodes();

  //
  // TODO: Complete this ...
  handleTreeNodeToggled(event: XTreeNodeToggle) {
    console.log('handleTreeNodeToggled: ', event);
  }

  handleTreeExpand(id: number) {
    console.log('handleTreeExpand: ', id);

    //
    this.treeActionProvider.next({
      action: XTreeAction.Expand,
      payload: id,
    });
  }

  handleTreeCollapse(id: number) {
    console.log('handleTreeCollapse: ', id);

    //
    this.treeActionProvider.next({
      action: XTreeAction.Collapse,
      payload: id,
    });
  }

  handleTreeExpandAll() {
    console.log('handleTreeExpandAll');

    //
    this.treeActionProvider.next({
      action: XTreeAction.ExpandAll,
    });
  }

  handleTreeCollapseAll() {
    console.log('handleTreeCollapseAll');

    //
    this.treeActionProvider.next({
      action: XTreeAction.CollapseAll,
    });
  }

  //
  //#region XTree ...
  private getTreeNodes() {
    return [
      //
      // Frontend ...
      {
        id: '1',
        tooltip: 'Frontend Development Technologies',
        data: {
          name: 'Frontend',
          description: 'Frontend Development Technologies',
        },
        childs: [
          //
          // Angular ...
          {
            id: '1/1',
            tooltip: 'Angular Framework',
            data: {
              name: 'Angular',
              description: 'Angular Framework',
            },
            childs: [
              //
              // Components ...
              {
                id: '1/1/1',
                data: {
                  name: 'Components',
                  description:
                    "Components is an important part of Angular's building blocks, since it is on top of Component based architecture",
                },
                childs: [],
              } as XTreeNode<ProgrammingTech>,
            ],
          } as XTreeNode<ProgrammingTech>,
          //
          // React ...
          {
            id: '1/2',
            data: {
              name: 'React',
              description:
                'a Collection of Web tools to create Web client apps',
            },
            childs: [],
          } as XTreeNode<ProgrammingTech>,
          //
          // Vue ...
          {
            id: '1/3',
            data: {
              name: 'Vue',
              description: 'a Frontend Development Frameworks',
            },
            childs: [],
          } as XTreeNode<ProgrammingTech>,
        ],
      } as XTreeNode<ProgrammingTech>,
      //
      // Desktop ...
      {
        id: '2',
        data: {
          name: 'Desktop',
          description: 'Desktop Development Technologies',
        },
        childs: [
          //
          // .Net ...
          {
            id: '2/1',
            data: {
              name: '.Net',
              description: 'a collction of languages for creating Desktop Apps',
            },
            childs: [],
          } as XTreeNode<ProgrammingTech>,
          //
          // Electron ...
          {
            id: '2/2',
            data: {
              name: 'Electron',
              description:
                'a collection of tools to Convert a Web app into Desktop Apps',
            },
            childs: [],
          } as XTreeNode<ProgrammingTech>,
        ],
      } as XTreeNode<ProgrammingTech>,
      //
      // Mobile ...
      {
        id: '3',
        data: {
          name: 'Mobile',
          description: 'Mobile Development Technologies',
        },
        childs: [
          //
          // J2ME ...
          {
            id: '3/1',
            data: {
              name: 'J2ME',
              description:
                'Java Mobile edition, using JAVA language to creating java based Mobile Applications',
            },
            childs: [],
          } as XTreeNode<ProgrammingTech>,
          //
          // CBuilder ...
          {
            id: '3/2',
            data: {
              name: 'CBuilder',
              description:
                'using c++ to creating Symbian based Mobile Applications',
            },
            childs: [],
          } as XTreeNode<ProgrammingTech>,
          //
          // Android SDK ...
          {
            id: '3/3',
            data: {
              name: 'Android',
              description:
                'using Android SDK to create Android OS based Mobile Applications by help of Java/Kotlin',
            },
            childs: [],
          } as XTreeNode<ProgrammingTech>,
          //
          // Swift ...
          {
            id: '3/4',
            data: {
              name: 'Swift',
              description: 'create iOs based Mobile Applications',
            },
            childs: [],
          } as XTreeNode<ProgrammingTech>,
        ],
      } as XTreeNode<ProgrammingTech>,
      //
      // Backend ...
      {
        id: '4',
        data: {
          name: 'Backend',
          description: 'Backend Development Technologies',
        },
        childs: [
          //
          // Php ...
          {
            id: '4/1',
            data: {
              name: 'Php',
              description: 'one of most popular backend development languages',
            },
            childs: [],
          } as XTreeNode<ProgrammingTech>,
          //
          // Python ...
          {
            id: '4/2',
            data: {
              name: 'Python',
              description: 'a multi usage language to develop applications',
            },
            childs: [],
          } as XTreeNode<ProgrammingTech>,
          //
          // NodeJS ...
          {
            id: '4/3',
            data: {
              name: 'Node JS',
              description:
                'a chrome engin based tool to create multi purpose applications',
            },
            childs: [],
          } as XTreeNode<ProgrammingTech>,
          //
          // .Net Core ...
          {
            id: '4/4',
            data: {
              name: '.net core',
              description:
                'a lightweigt, fast and cross platform version of .Net which provided by Microsoft to Develop Applications',
            },
            childs: [],
          } as XTreeNode<ProgrammingTech>,
        ],
      } as XTreeNode<ProgrammingTech>,
    ];
  }
  //#endregion
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\core\core.module.ts

import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { CommonModule } from '@angular/common';
import { ViewsModule } from '../../views/views.module';
import { IntroductionPage } from './introduction/introduction.page';
import { BaseRoutes, ServicesRoutes } from 'src/app/config/page.config';

@NgModule({
  imports: [
    ViewsModule,
    CommonModule,
    RouterModule.forChild([
      {
        path: BaseRoutes.Default,
        redirectTo: ServicesRoutes.Introduction,
        pathMatch: 'full',
      },
      {
        path: ServicesRoutes.Introduction,
        component: IntroductionPage,
      },
    ]),
  ],
  declarations: [IntroductionPage],
})
export class CorePageModule {}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\core\introduction\introduction.page.html

<v-page
  [hasSide]="true"
  [toolbarTitle]="toolbarTitle"
  [toolbarSubTitle]="toolbarSubTitle"
  [toolbarShowSubTitle]="toolbarShowSubTitle"
>
  <!-- Content -->
  <x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
    <!-- Content -->
    <x-markdown
      [mode]="'preview'"
      [hasToolbar]="false"
      [content]="getContent('content')"
    ></x-markdown>

    <!-- Actions -->
    <div actions>
      <a target="_blank" href="https://docs.x-framework.ir/x-framework-core/index.html"
        >{{resourceProvider(ResourceIDs.documentation)}}</a
      >
    </div>
  </x-card>
</v-page>

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\core\introduction\introduction.page.scss


### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\core\introduction\introduction.page.ts

import {
  XResourceIDs,
  isNullOrEmptyString,
  XColorWithBrightness,
} from 'x-framework-core';
import { Component } from '@angular/core';
import { VPageComponent } from 'src/app/views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';

@Component({
  selector: 'app-components-introduction',
  templateUrl: './introduction.page.html',
  styleUrls: ['./introduction.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class IntroductionPage extends VPageComponent {
  //
  //#region Props ...
  //
  //#region Page Props ...
  titleRes = AppResourceIDs.core_introduction;
  toolbarTitle = this.resourceProvider(this.titleRes);
  toolbarSubTitle = this.resourceProvider(
    AppResourceIDs.core_introduction_description
  );
  toolbarShowSubTitle = true;
  //#endregion

  //
  // Prepare All Resource IDs ...
  readonly ResourceIDs = Object.assign(
    Object.assign({}, XResourceIDs),
    AppResourceIDs
  ) as any;

  //
  // Color Names ...
  readonly ColorNames = Object.assign({}, XColorWithBrightness);
  //#endregion

  //
  // Content ...
  readonly contentFa = `
  # ${this.toolbarTitle}
این واحد شامل کلیه نیازمندی های پایه چارچوب است.

برای آشنایی با اجزاء این واحد‌‌ مستندات آن را مورد مطالعه قرار دهید.
  `;

  readonly contentEn = `
  # ${this.toolbarTitle}
this module contains all required dependencies for xFramework.

for complete descriptions please read this module documentaions.
  `;
  //#endregion

  //
  // Provide content based on current locale ...
  getContent(title: string) {
    //
    if (isNullOrEmptyString(title)) {
      return '';
    }

    //
    const currentLocale = this.managerService.currentLocale;

    //
    const varName =
      title +
      (currentLocale === 'en-US'
        ? 'En'
        : currentLocale === 'fa-IR'
        ? 'Fa'
        : '');

    const result = this[`${varName}`];

    //
    return result || '';
  }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\home\home.module.ts

import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { CommonModule } from '@angular/common';
import { ViewsModule } from '../../views/views.module';
import { BaseRoutes, HomeRoutes } from 'src/app/config/page.config';
import { IntroductionPage } from './introduction/introduction.page';

@NgModule({
  imports: [
    ViewsModule,
    CommonModule,
    RouterModule.forChild([
      {
        path: BaseRoutes.Default,
        redirectTo: HomeRoutes.Introduction,
        pathMatch: 'full',
      },
      {
        path: HomeRoutes.Introduction,
        component: IntroductionPage,
      },
    ]),
  ],
  declarations: [IntroductionPage],
})
export class HomePageModule {}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\home\introduction\introduction.page.html

<v-page
  [hasSide]="true"
  [toolbarTitle]="toolbarTitle"
  [toolbarSubTitle]="toolbarSubTitle"
  [toolbarShowSubTitle]="toolbarShowSubTitle"
>
  <!-- Content -->
  <x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
    <!-- Content -->
    <x-markdown
      [mode]="'preview'"
      [hasToolbar]="false"
      [content]="getContent('content')"
    ></x-markdown>

    <!-- Maintainer -->
    <v-maintainer></v-maintainer>

    <!-- Actions -->
    <div actions>
      <a target="_blank" href="https://docs.x-framework.ir/index.html"
        >{{resourceProvider(AppResourceIDs.documentation)}}</a
      >
    </div>
  </x-card>
</v-page>

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\home\introduction\introduction.page.scss


### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\home\introduction\introduction.page.ts

import { Component } from '@angular/core';
import { VPageComponent } from 'src/app/views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';
import { isNullOrEmptyString, XColorWithBrightness } from 'x-framework-core';

@Component({
  selector: 'app-components-introduction',
  templateUrl: './introduction.page.html',
  styleUrls: ['./introduction.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class IntroductionPage extends VPageComponent {
  //
  //#region Props ...
  //
  //#region Page Props ...
  titleRes = AppResourceIDs.home_introduction;
  toolbarTitle = this.resourceProvider(this.titleRes);
  toolbarSubTitle = this.resourceProvider(
    AppResourceIDs.home_introduction_description
  );
  toolbarShowSubTitle = true;
  //#endregion

  //
  // Color Names ...
  readonly ColorNames = Object.assign({}, XColorWithBrightness);
  //#endregion

  //
  // Content ...
  readonly contentFa = `
  # ${this.toolbarTitle}
یک چارچوب طراحی و توسعه ظاهر برنامه های کاربردی است که با بهره گیری از توانمندی های انگولار/آیونیک و کوردوا ایجاد شده است تا فرآیند طراحی و توسعه ظاهر برنامه های کاربردی را سهل تر کند.

این چارچوب بر سه واحد مستقل استوار است که عبارتند از:

- **واحد هسته**:
شامل اصلی ترین نیازمندی های پایه است.

- **واحد خدمات**:
شامل مجموعه ای از خدمات پرکاربرد است که چارچوب از آن ها برای فراهم کردن امکانات مختلف استفاده می کند.

- **واحد مولفه ها**:
مجموعه ای مولفه های بصری که بر پایه استاندارد متریال دیزاین طراحی و توسعه یافته اند و امکانات مختلفی را در اختیار کاربر قرار می دهند.
  `;

  readonly contentEn = `
  # ${this.toolbarTitle}

  a Frontend framework which combined and implement several building blocks to provide an easy to use interface for creating Web/Mobile/Desktop Apps by help of Angular/Ionic and Cordova Powers.

  XFramework built on top of 3 main and unique modules:

  - **Core Module**:
  conatins core features and dependencies.

  - **Services Module**:
  contains some sort of usefull services which this framework used them to provide different options.

  - **Components Module**:
  contains a collection of UI Components which designed and develop based on Material Design and provide different options.
  `;
  //#endregion

  //
  async afterViewInit() {
    await super.afterViewInit();

    //
    // console.log('sortOrder: ', this.sortOrederModelKeys);
  }

  //
  // Provide content based on current locale ...
  getContent(title: string) {
    //
    if (isNullOrEmptyString(title)) {
      return '';
    }

    //
    const currentLocale = this.managerService.currentLocale;

    //
    const varName =
      title +
      (currentLocale === 'en-US'
        ? 'En'
        : currentLocale === 'fa-IR'
        ? 'Fa'
        : '');

    const result = this[`${varName}`];

    //
    return result || '';
  }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\services\services.module.ts

import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { CommonModule } from '@angular/common';
import { ViewsModule } from '../../views/views.module';
import { IntroductionPage } from './introduction/introduction.page';
import { BaseRoutes, ServicesRoutes } from 'src/app/config/page.config';
import { UserDevicePage } from './user-device/user-device.page';

@NgModule({
  imports: [
    ViewsModule,
    CommonModule,
    RouterModule.forChild([
      {
        path: BaseRoutes.Default,
        redirectTo: ServicesRoutes.Introduction,
        pathMatch: 'full',
      },
      {
        path: ServicesRoutes.Introduction,
        component: IntroductionPage,
      },
      {
        path: ServicesRoutes.UserDevice,
        component: UserDevicePage,
      },
    ]),
  ],
  declarations: [UserDevicePage, IntroductionPage],
})
export class ServicesPageModule {}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\services\introduction\introduction.page.html

<v-page
  [hasSide]="true"
  [toolbarTitle]="toolbarTitle"
  [toolbarSubTitle]="toolbarSubTitle"
  [toolbarShowSubTitle]="toolbarShowSubTitle"
>
  <!-- Content -->
  <x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
    <!-- Content -->
    <x-markdown
      [mode]="'preview'"
      [hasToolbar]="false"
      [content]="getContent('content')"
    ></x-markdown>

    <!-- Actions -->
    <div actions>
      <a target="_blank" href="https://docs.x-framework.ir/x-framework-services/index.html"
        >{{resourceProvider(ResourceIDs.documentation)}}</a
      >
    </div>
  </x-card>
</v-page>

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\services\introduction\introduction.page.scss


### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\services\introduction\introduction.page.ts

import {
  XResourceIDs,
  isNullOrEmptyString,
  XColorWithBrightness,
} from 'x-framework-core';
import { Component } from '@angular/core';
import { VPageComponent } from 'src/app/views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';

@Component({
  selector: 'app-components-introduction',
  templateUrl: './introduction.page.html',
  styleUrls: ['./introduction.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class IntroductionPage extends VPageComponent {
  //
  //#region Props ...
  //
  //#region Page Props ...
  titleRes = AppResourceIDs.services_introduction;
  toolbarTitle = this.resourceProvider(this.titleRes);
  toolbarSubTitle = this.resourceProvider(
    AppResourceIDs.services_introduction_description
  );
  toolbarShowSubTitle = true;
  //#endregion

  //
  // Prepare All Resource IDs ...
  readonly ResourceIDs = Object.assign(
    Object.assign({}, XResourceIDs),
    AppResourceIDs
  ) as any;

  //
  // Color Names ...
  readonly ColorNames = Object.assign({}, XColorWithBrightness);
  //#endregion

  //
  // Content ...
  readonly contentFa = `
  # ${this.toolbarTitle}

این واحد شامل کلیه خدمات قابل استفاده در چارچوب است که هر یک امکانات خاصی را در اختیار قرار می دهد، که اهم آن ها عبارتند از:

- **XDialogService**:
قابلیت نمایش و استفاده از کادر های مختلف محاوره ای را فراهم می کند.

- **XGeolocationService**:
قابلیت مکان یابی را فراهم می کند.

- **XHistoryService**:
قابلیت مدیریت و دستکاری تاریخچه مرور صفحات در مرورگر را فراهم می کند.

- **XLocalizationService**:
قابلیت استفاده از منابع در ازای محتوای مستقیم را جهت پشتیبانی از زبان های مختلف را فراهم می کند.

- **XNotificationService**:
قابلیت نمایش اعلان های مختلف را فراهم می کند.

- **XStorageService**:
قابلیت استفاده از حافطه را جهت ذخیره و بازیابی موارد مختلف فراهم می کند.

- **XSecureStorageService**:
قابلیت استفاده از حافظه بصورت رمزنگاری شده را فراهم می کند.

- **XSecurityService**:
قابلیت رمزنگاری و رمزگشایی اطلاعات و تولید امضاهای دیجیتال را فراهم می کند.

- **XSettingsService**:
قابلیت مدیریت تنظیمات چارچوب را فراهم می کند.

- **XTaskManagerService**:
قابلیت اجرای وظایف و اولویت بندی آن ها را فراهم می کند.

- **XManagerService**:
جهت سهولت دستری به خدمات موجود این خدمت بعنوان در برگیرنده کلیه خدمات لازم در چارچوب، مورد بهره برداری قرار می گیرد.

برای آشنایی بیشتر لطفا به مستندات مراجعه فرمایید.
  `;

  readonly contentEn = `
  # ${this.toolbarTitle}

this module contains all useable services inside the framework which each one provide some capabilities, such as:

- **XDialogService**:
provide the ability of use several types of Dialogs.

- **XGeolocationService**:
provide Geo Location abilities.

- **XHistoryService**:
provide the ability of managing and manipulating Browser History.

- **XLocalizationService**:
provide ability of Localization and Internationalization.

- **XNotificationService**:
provide ability of using several Notifications.

- **XStorageService**:
provide ability of Storage used to Save and Retrieve data.

- **XSecureStorageService**:
provide a Secure Storage to Save and Retrieve data privately.

- **XSecurityService**:
provide ability of Encrypt/Decrypt data and also Generate Checksub Digest of data.

- **XSettingsService**:
provide ability of Managing xFramework Settings.

- **XTaskManagerService**:
provide ability to Queue Tasks and run them based on their priority.

- **XManagerService**:
for better access all services, this Service acts as a Container of all required important above services.

for more information, please read documentation.
  `;
  //#endregion

  //
  // Provide content based on current locale ...
  getContent(title: string) {
    //
    if (isNullOrEmptyString(title)) {
      return '';
    }

    //
    const currentLocale = this.managerService.currentLocale;

    //
    const varName =
      title +
      (currentLocale === 'en-US'
        ? 'En'
        : currentLocale === 'fa-IR'
        ? 'Fa'
        : '');

    const result = this[`${varName}`];

    //
    return result || '';
  }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\services\user-device\user-device.page.html

<v-page
  [hasSide]="true"
  [toolbarTitle]="toolbarTitle"
  [toolbarSubTitle]="toolbarSubTitle"
  [toolbarShowSubTitle]="toolbarShowSubTitle"
>
  <!-- Content -->
  <x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
    <pre>{{ device | json }}</pre>
  </x-card>
</v-page>

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\services\user-device\user-device.page.scss


### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\services\user-device\user-device.page.ts

import { Component } from '@angular/core';
import { XResourceIDs, XColorWithBrightness } from 'x-framework-core';
import { VPageComponent } from 'src/app/views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';

@Component({
  selector: 'app-services-user-device',
  templateUrl: './user-device.page.html',
  styleUrls: ['./user-device.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class UserDevicePage extends VPageComponent {
  //
  //#region Props ...
  //
  //#region Page Props ...
  titleRes = AppResourceIDs.user_device;
  toolbarTitle = this.resourceProvider(this.titleRes);
  toolbarSubTitle = this.resourceProvider(
    AppResourceIDs.user_device_description
  );
  toolbarShowSubTitle = true;
  //#endregion

  //
  // Prepare All Resource IDs ...
  readonly ResourceIDs = Object.assign(
    Object.assign({}, XResourceIDs),
    AppResourceIDs
  ) as any;

  //
  // Color Names ...
  readonly ColorNames = Object.assign({}, XColorWithBrightness);
  //#endregion

  //
  device = this.managerService.settingsService.device;
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\tabs\tabs.module.ts

import { TabsPage } from './tabs.page';
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { CommonModule } from '@angular/common';
import { ViewsModule } from '../../views/views.module';
import { TabPage1Page } from './tab-page-1/tab-page-1.page';
import { TabPage2Page } from './tab-page-2/tab-page-2.page';
import { TabPage3Page } from './tab-page-3/tab-page-3.page';
import { Pages, BaseRoutes } from 'src/app/config/page.config';

@NgModule({
  imports: [
    ViewsModule,
    CommonModule,
    RouterModule.forChild([
      {
        path: BaseRoutes.Default,
        component: TabsPage,
        children: [
          {
            path: BaseRoutes.Default,
            redirectTo: Pages.TabPage1.baseRoute,
            pathMatch: 'full',
          },
          {
            path: Pages.TabPage1.baseRoute,
            component: TabPage1Page,
          },
          {
            path: Pages.TabPage2.baseRoute,
            component: TabPage2Page,
          },
          {
            path: Pages.TabPage3.baseRoute,
            component: TabPage3Page,
          },
        ],
      },
    ]),
  ],
  declarations: [TabsPage, TabPage1Page, TabPage2Page, TabPage3Page],
})
export class TabsPageModule {}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\tabs\tabs.page.ts

import { Component } from '@angular/core';
import { XColorWithBrightness } from 'x-framework-core';
import { TabNavsItems } from 'src/app/config/page.config';
import { VPageComponent } from 'src/app/views/v-page/v-page.component';

@Component({
  selector: 'app-components-tabs',
  template: `
    <x-tab-navigator
      [items]="tabItems"
      [color]="ColorNames.Dark"
      [iconColor]="ColorNames.Danger"
      [highlightColor]="ColorNames.Light"
      [selectedColor]="ColorNames.SecondaryShade"
    ></x-tab-navigator>
  `,
  styles: [``],
})
// tslint:disable-next-line:component-class-suffix
export class TabsPage extends VPageComponent {
  //
  //#region Props ...
  tabItems = TabNavsItems;

  readonly ColorNames = Object.assign({}, XColorWithBrightness);
  //#endregion
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\tabs\tab-page-1\tab-page-1.page.html

<p>Tab Page 1</p>

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\tabs\tab-page-1\tab-page-1.page.scss


### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\tabs\tab-page-1\tab-page-1.page.ts

import { Component } from '@angular/core';
import { VPageComponent } from 'src/app/views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';
import { XResourceIDs, XColorWithBrightness } from 'x-framework-core';

@Component({
  selector: 'app-tab-page-1',
  templateUrl: './tab-page-1.page.html',
  styleUrls: ['./tab-page-1.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class TabPage1Page extends VPageComponent {
  //
  //#region Props ...
  //
  //#region Page Props ...
  titleRes = AppResourceIDs.tab_page_1;
  //#endregion

  //
  // Prepare All Resource IDs ...
  readonly ResourceIDs = Object.assign(
    Object.assign({}, XResourceIDs),
    AppResourceIDs
  ) as any;

  //
  // Color Names ...
  readonly ColorNames = Object.assign({}, XColorWithBrightness);
  //#endregion
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\tabs\tab-page-2\tab-page-2.page.html

<p>Tab Page 2</p>

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\tabs\tab-page-2\tab-page-2.page.scss


### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\tabs\tab-page-2\tab-page-2.page.ts

import { Component } from '@angular/core';
import { VPageComponent } from 'src/app/views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';
import { XResourceIDs, XColorWithBrightness } from 'x-framework-core';

@Component({
  selector: 'app-tab-page-2',
  templateUrl: './tab-page-2.page.html',
  styleUrls: ['./tab-page-2.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class TabPage2Page extends VPageComponent {
  //
  //#region Props ...
  //
  //#region Page Props ...
  titleRes = AppResourceIDs.tab_page_2;
  //#endregion

  //
  // Prepare All Resource IDs ...
  readonly ResourceIDs = Object.assign(
    Object.assign({}, XResourceIDs),
    AppResourceIDs
  ) as any;

  //
  // Color Names ...
  readonly ColorNames = Object.assign({}, XColorWithBrightness);
  //#endregion
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\tabs\tab-page-3\tab-page-3.page.html

<p>Tab Page 3</p>

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\tabs\tab-page-3\tab-page-3.page.scss


### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\tabs\tab-page-3\tab-page-3.page.ts

import { Component } from '@angular/core';
import { VPageComponent } from 'src/app/views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';
import { XResourceIDs, XColorWithBrightness } from 'x-framework-core';

@Component({
  selector: 'app-tab-page-3',
  templateUrl: './tab-page-3.page.html',
  styleUrls: ['./tab-page-3.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class TabPage3Page extends VPageComponent {
  //
  //#region Props ...
  //
  //#region Page Props ...
  titleRes = AppResourceIDs.tab_page_3;
  //#endregion

  //
  // Prepare All Resource IDs ...
  readonly ResourceIDs = Object.assign(
    Object.assign({}, XResourceIDs),
    AppResourceIDs
  ) as any;

  //
  // Color Names ...
  readonly ColorNames = Object.assign({}, XColorWithBrightness);
  //#endregion
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\themes\themes.module.ts

import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { CommonModule } from '@angular/common';
import { ViewsModule } from '../../views/views.module';
import { XCanDeactivateGuard } from 'x-framework-core';
import { BaseRoutes, ThemesRoutes } from 'src/app/config/page.config';
import { ThemeManagerPage } from './theme-manager/theme-manager.page';

@NgModule({
  imports: [
    ViewsModule,
    CommonModule,
    RouterModule.forChild([
      {
        path: BaseRoutes.Default,
        redirectTo: ThemesRoutes.ThemeManager,
        pathMatch: 'full',
      },
      {
        path: ThemesRoutes.ThemeManager,
        component: ThemeManagerPage,
        canDeactivate: [XCanDeactivateGuard]
      },
    ]),
  ],
  declarations: [ThemeManagerPage],
})
export class ThemesPageModule {}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\themes\theme-manager\theme-manager.page.html

<v-page
  [hasSide]="true"
  [actions]="actions"
  [toolbarShowSubTitle]="true"
  [toolbarHasBack]="toolbarHasBack"
  [toolbarShowBack]="toolbarShowBack"
  [toolbarSubTitle]="toolbarSubTitle"
  [toolbarShowProgressBar]="isLoading"
  [toolbarBackHandler]="toolbarBackHandler"
>
  <!-- Theme Manager -->
  <!-- [minAllowedThemeFileSize]="1" -->
  <x-theme-manager
    [isInPage]="true"
    [wrapWithCard]="true"
    [actionBarColor]="ColorNames.Dark"
    [listEmptyColor]="ColorNames.Light"
    [themeUploadShowFileDropArea]="false"
    [themeUploadColor]="ColorNames.Light"
    (tabChange)="handleTabChange($event)"
    [listSearchBarColor]="ColorNames.Dark"
    (themeChange)="handleThemeChange($event)"
    [listEmptyMessageColor]="ColorNames.Light"
    [actionProvider]="themeManagerActionProvider"
    [themeUploadFileDropAreaColor]="ColorNames.Light"
    [listSearchBarSearchInputColor]="ColorNames.DarkTint"
  ></x-theme-manager>
</v-page>

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\themes\theme-manager\theme-manager.page.scss


### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\pages\themes\theme-manager\theme-manager.page.ts

import {
  XThemePack,
  XThemeType,
  XStandardType,
  XColorWithBrightness,
} from 'x-framework-core';
import { Subject } from 'rxjs';
import {
  XTabsActionModel,
  getEmptyThemePack,
  XThemeManagerTabs,
  XThemeManagerAction,
  XFormStatusIdentifier,
  XThemeManagerActionModel,
} from 'x-framework-components';
import { Component } from '@angular/core';
import { VPageComponent } from 'src/app/views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';

@Component({
  selector: 'app-theme-manager',
  templateUrl: './theme-manager.page.html',
  styleUrls: ['./theme-manager.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class ThemeManagerPage extends VPageComponent {
  //
  //#region Props ...
  //
  //#region Page Props ...
  titleRes = AppResourceIDs.theme_manager;
  toolbarTitle = this.resourceProvider(this.titleRes);
  toolbarSubTitle = this.resourceProvider(
    AppResourceIDs.theme_manager_description
  );
  toolbarShowSubTitle = true;

  //
  toolbarBackHandler: () => XStandardType<void> = async () => {
    await this.backHandler();
  };
  //#endregion

  //
  // Color Names ...
  readonly ColorNames = Object.assign({}, XColorWithBrightness);

  //
  // Tabs ...
  currentTab: number = XThemeManagerTabs.List;
  tabsActionProvider = new Subject<XTabsActionModel>();

  //
  // Theme Types ...
  readonly ThemeTypes = Object.assign({}, XThemeType);

  //
  themes: XThemePack[];
  themeNames: string[];
  selectedTheme: XThemePack;

  //
  formProvidedTheme: XThemePack;
  formStatus: XFormStatusIdentifier;
  emptyThemePack = getEmptyThemePack();

  //
  // Theme Maker Action Provider ...
  themeManagerActionProvider = new Subject<XThemeManagerActionModel>();
  //#endregion

  //
  //#region LifeCycles ...
  async onInit() {
    super.onInit();
  }

  async onBack() {
    super.onBack();

    //
    if (this.currentTab !== XThemeManagerTabs.List) {
      await this.backHandler();
    }
  }
  //#endregion

  //
  //#region UI Providers ...
  //#endregion

  //
  //#region UI Handlers ...
  async handleTabChange(event: XStandardType<number>) {
    //
    const eventTab = (await this.getValueAsync(event)) || 0;

    //
    switch (eventTab) {
      //
      case XThemeManagerTabs.List:
        //
        this.preventBack = false;
        this.toolbarHasBack = false;
        this.toolbarShowBack = false;
        break;

      //
      case XThemeManagerTabs.Edit:
      case XThemeManagerTabs.Import:
      case XThemeManagerTabs.Details:
        //
        this.preventBack = true;
        this.toolbarHasBack = true;
        this.toolbarShowBack = true;
        break;
    }

    //
    this.currentTab = eventTab;
    await this.prepareActions(this.currentTab);

    //
    this.detectChanges();
  }

  async handleThemeChange(event: boolean) {
    //
    if ((!event && !this.isLocked) || (event && this.isLocked)) {
      return;
    }
    //
    this.lock = event;
    this.detectChanges();
  }
  //#endregion

  //
  //#region Actions ...
  //#endregion

  //
  //#region Private ...
  private async prepareActions(tab = XThemeManagerTabs.List) {
    //
    this.actions = null;
    this.detectChanges();
  }

  private async backHandler() {
    //
    if (this.currentTab === XThemeManagerTabs.List) {
      //
      this.lock = false;
      this.managerService.historyService.back();
    } else {
      //
      if (this.isLocked) {
        await this.presentDeactiveGuardDialog(() => {
          this.issueThemeManagerComponentBackAction();
        });
      } else {
        this.issueThemeManagerComponentBackAction();
      }
    }
  }

  private issueThemeManagerComponentBackAction() {
    //
    this.themeManagerActionProvider.next({
      action: XThemeManagerAction.Back,
    });
  }
  //#endregion
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\views\public-api.ts

//
// Tools ...
export * from './tools/task.tools';
export * from './tools/v-base.tools';
export * from './tools/v-data-pager.tools';

//
// Typings ...
export * from './typings/v-base-form.typings';

//
// Classes ...
export * from './classes/v-base.component';
export * from './classes/v-base-tabs.page';
export * from './classes/v-base-form-view';
export * from './classes/v-base-data-pager.page';
export * from './classes/v-base-data-scroller.page';

//
// VMaintainer ...
export * from './v-maintainer/v-maintainer.component';

//
// VPage ...
export * from './v-page/v-page.component';

//
// Module ...
export * from './views.module';

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\views\views.module.ts

import {
  XFrameworkCoreModule,
  XDirectivesModule as XFrameworkCoreDirectivesModule,
} from 'x-framework-core';
import {
  XManagerService,
  XHttpInterceptorService,
  XFrameworkServicesModule,
  XDirectivesModule as XFrameworkServicesDirectivesModule,
} from 'x-framework-services';
import {
  XFabModule,
  XMapModule,
  XTabsModule,
  XPageModule,
  XCardModule,
  XIconModule,
  XListModule,
  XGridModule,
  XFormModule,
  XTreeModule,
  XTableModule,
  XThemeModule,
  XEmptyModule,
  XColorModule,
  XButtonModule,
  XSliderModule,
  XSpinnerModule,
  XSlotterModule,
  XCounterModule,
  XStepperModule,
  XMarkdownModule,
  XSearchBarModule,
  XThumbnailModule,
  XActionBarModule,
  XDataPagerModule,
  XFileUploadModule,
  XColorPickerModule,
  XTabNavigatorModule,
  XFileDropAreaModule,
  XAvatarUploadModule,
  XImageCropperModule,
  XDataScrollerModule,
  XBaseComponentModule,
  XExpandableListModule,
  XModelPresenterModule,
  XExpandablePanelModule,
  XDescriptionListModule,
  XFrameworkComponentsModule,
  XDialogsModule,
} from 'x-framework-components';
import { NgModule } from '@angular/core';
import { IonicModule } from '@ionic/angular';
import { CommonModule } from '@angular/common';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { VPageComponent } from './v-page/v-page.component';
import { VMaintainerComponent } from './v-maintainer/v-maintainer.component';

@NgModule({
  declarations: [VPageComponent, VMaintainerComponent],
  providers: [
    XManagerService,
    //
    // Register Http Interceptor ...
    {
      provide: HTTP_INTERCEPTORS,
      useClass: XHttpInterceptorService,
      multi: true,
    },
  ],
  imports: [
    //
    IonicModule,
    CommonModule,

    //
    XFrameworkCoreModule,
    XFrameworkCoreDirectivesModule,

    //
    XFrameworkServicesModule,
    XFrameworkServicesDirectivesModule,

    //
    XEmptyModule,
    XBaseComponentModule,
    XFrameworkComponentsModule,

    //
    XFabModule,
    XMapModule,
    XPageModule,
    XCardModule,
    XIconModule,
    XFormModule,
    XTabsModule,
    XListModule,
    XGridModule,
    XTreeModule,
    XColorModule,
    XTableModule,
    XThemeModule,
    XButtonModule,
    XSliderModule,
    XSpinnerModule,
    XStepperModule,
    XSlotterModule,
    XCounterModule,
    XMarkdownModule,
    XDataPagerModule,
    XSearchBarModule,
    XThumbnailModule,
    XActionBarModule,
    XFileUploadModule,
    XColorPickerModule,
    XImageCropperModule,
    XFileDropAreaModule,
    XDataScrollerModule,
    XTabNavigatorModule,
    XAvatarUploadModule,
    XExpandableListModule,
    XModelPresenterModule,
    XExpandablePanelModule,
    XDescriptionListModule,
  ],
  exports: [
    //
    IonicModule,
    CommonModule,

    //
    XFrameworkCoreModule,
    XFrameworkCoreDirectivesModule,

    //
    XFrameworkServicesModule,
    XFrameworkServicesDirectivesModule,

    //
    XEmptyModule,
    XDialogsModule,
    XBaseComponentModule,

    //
    XFabModule,
    XMapModule,
    XPageModule,
    XCardModule,
    XIconModule,
    XFormModule,
    XTabsModule,
    XListModule,
    XGridModule,
    XTreeModule,    
    XColorModule,
    XTableModule,
    XThemeModule,
    XButtonModule,
    XSliderModule,
    XSpinnerModule,
    XStepperModule,
    XSlotterModule,
    XCounterModule,
    XMarkdownModule,
    XDataPagerModule,
    XSearchBarModule,
    XThumbnailModule,
    XActionBarModule,
    XFileUploadModule,
    XColorPickerModule,
    XImageCropperModule,
    XFileDropAreaModule,
    XDataScrollerModule,
    XTabNavigatorModule,
    XAvatarUploadModule,
    XExpandableListModule,
    XModelPresenterModule,
    XExpandablePanelModule,
    XDescriptionListModule,

    //
    VPageComponent,
    VMaintainerComponent,
  ],
})
export class ViewsModule {}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\views\classes\v-base-data-pager.page.ts

import {
  isSameObject,
  XModelKeyProvider,
  XModelValueProvider,
  isNullOrEmptyString,
  XBaseDataPagerQuery,
  XPartialModelFieldNames,
  XBaseDataPagerQueryResult,
} from 'x-framework-core';
import {
  XListItem,
  XListItemSlideOption,
  XDataPagerPresentType,
  XDataPagerPaginatorPosition,
} from 'x-framework-components';
import { map } from 'rxjs/operators';
import {
  VBaseFormViewAction,
  VBaseFormViewActionModel,
  VBaseFormViewPresentType,
} from '../typings/v-base-form.typings';
import { Component } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import { getTaskName } from '../tools/task.tools';
import { VBaseTabsPage } from './v-base-tabs.page';
import { XQueryDto, XQueryResultDto } from '../models/x-query.dto';

@Component({
  template: '',
})
// tslint:disable-next-line: component-class-suffix
export abstract class VBaseDataPagerPage<T = any> extends VBaseTabsPage {
  //
  //#region Props ...
  //
  // XQueryDto ...
  filter: string;
  canSearch: boolean;
  isAscending = true;
  enableTracking = false;
  containsDetail = false;
  sortOrder: keyof Partial<T>;

  //
  readonly DataPagerPaginatorPositions = Object.assign(
    {},
    XDataPagerPaginatorPosition
  );
  readonly ModelPresentTypes = Object.assign({}, VBaseFormViewPresentType);
  readonly DataPagerPresentTypes = Object.assign({}, XDataPagerPresentType);

  //
  showDataPagerPaginator: boolean;
  dataPagerQuery: XBaseDataPagerQuery = {
    filter: '',
    pageNumber: 1,
    rowsInPage: this.config.defaultPageSize,
  };
  dataPagerResultListItems: XListItem<T>[];
  dataPagerResult: XBaseDataPagerQueryResult<T>;

  //
  listTabIndex: number;

  //
  selectedModel: T;
  canAddOrUpdate: boolean;
  hiddenModelKeys: XPartialModelFieldNames<T>;
  availableModelKeys: XPartialModelFieldNames<T>;
  sortOrderModelKeys: XPartialModelFieldNames<T>;
  hiddenLabelModelKeys: XPartialModelFieldNames<T>;
  modelActionProvider = new Subject<VBaseFormViewActionModel>();

  //
  //#region Default Slide Options ...
  //
  // Details ...
  readonly defaultDetailsSlideOption = {
    id: 'Details',
    icon: this.IconNames.visible,
    title: this.ResourceIDs.details,
    color: this.ColorNames.Secondary,
    onlyIcon: true,
    slot: 'start',
    disabled: this.isLoading || this.uiDisabled,
  } as XListItemSlideOption;

  //
  // Edit ...
  readonly defaultEditSlideOption = {
    id: 'Edit',
    icon: this.IconNames.edit,
    title: this.ResourceIDs.edit,
    color: this.ColorNames.Tertiary,
    onlyIcon: true,
    slot: 'start',
    disabled: this.isLoading || this.uiDisabled,
  } as XListItemSlideOption;

  //
  // Download ...
  readonly defaultDownloadSlideOption = {
    id: 'Download',
    icon: this.IconNames.download,
    color: this.ColorNames.Success,
    title: this.ResourceIDs.download,
    onlyIcon: true,
    slot: 'start',
    disabled: this.isLoading || this.uiDisabled,
  } as XListItemSlideOption;

  //
  // Remove ...
  readonly defaultRemoveSlideOption = {
    id: 'Remove',
    icon: this.IconNames.remove,
    title: this.ResourceIDs.delete,
    color: this.ColorNames.Danger,
    onlyIcon: true,
    slot: 'end',
    disabled: this.isLoading || this.uiDisabled,
  } as XListItemSlideOption;
  //#endregion
  //#endregion

  //
  //#region Abstract ...
  abstract modelKeyProvider: XModelKeyProvider<T>;

  abstract modelValueProvider: XModelValueProvider<T>;

  abstract getAddOrUpdateAvailableModelKeys(): XPartialModelFieldNames<T>;

  abstract provideSlideOptions(item: T): Promise<XListItemSlideOption[]>;

  abstract isSameAsDefault(item: T): boolean;

  abstract getTaskNames(): string[];

  abstract queryFetcherTask(query: XQueryDto): Observable<XQueryResultDto<T>>;

  abstract issueDataPagerTask(
    task: Observable<XBaseDataPagerQueryResult<T>>
  ): Promise<void>;

  abstract issueAddModelTask(model: T): Promise<void>;

  abstract issueUpdateModelTask(model: T): Promise<void>;

  abstract issueRemoveModelTask(model: T): Promise<void>;

  abstract handlePresentDetails(model: T): Promise<void>;

  abstract handlePresentAddForm(): Promise<void>;

  abstract handlePresentEditForm(model: T): Promise<void>;

  abstract modelFieldPreparer(model: T): T;
  //#endregion

  //
  //#region Constructor ...
  //#endregion

  //
  //#region LifeCycles ...
  //#endregion

  //
  //#region Register Handlers ...
  //#endregion

  //
  //#region Task Handlers ...
  //#endregion

  //
  //#region UI Providers ...
  queryFetcher = (q: XBaseDataPagerQuery) => {
    //
    const apiQuery = this.toXQuery(q);
    return this.applyToDataPagerQueryResult(this.queryFetcherTask(apiQuery));
    // tslint:disable-next-line: semicolon
  };

  isSameAsSelectedModel(item: T) {
    return isSameObject(item as any, this.selectedModel as any);
  }
  //#endregion

  //
  //#region UI Handlers ...
  public async handleDataPagerTaskReady(
    task: Observable<XBaseDataPagerQueryResult<T>>
  ) {
    //
    // XBaseDataPagerQueryResult<any> ...
    if (!task || this.uiDisabled || this.isLoading) {
      return;
    }

    //
    await this.issueDataPagerTask(task);
  }

  public async handleDataPagerTaskFinished(
    result: XBaseDataPagerQueryResult<T>
  ) {
    //
    this.dataPagerResult = null;
    this.dataPagerResultListItems = null;
    this.detectChanges();

    //
    if (!result) {
      return;
    }

    //
    this.dataPagerResult = {
      ...result,
    };

    //
    this.canSearch =
      (this.hasChild(this.dataPagerResult.items) &&
        this.dataPagerResult.items.length > 1) ||
      !isNullOrEmptyString(this.dataPagerQuery.filter);

    //
    this.showDataPagerPaginator =
      this.hasChild(this.dataPagerResult.items) &&
      this.dataPagerResult.items.length > 1;

    //
    this.dataPagerResultListItems = await this.prepareListItems();
    await this.changeTab(this.listTabIndex);

    //
    this.detectChanges();
  }

  public async handleAddOrUpdateModelTaskFinished(model: T) {
    //
    if (!model) {
      return;
    }

    //
    this.lock = false;

    //
    this.handleResetDataPagerQuery();
  }

  public async handleAddOrUpdateFormModelChanged(model: T) {
    //
    if (!model || !this.selectedModel) {
      return;
    }

    //
    const isSameAsDefault = this.isSameAsDefault(model);
    const isSameAsSelectedModel = this.isSameAsSelectedModel(model);

    //
    this.lock = !isSameAsDefault && !isSameAsSelectedModel;
    this.canAddOrUpdate = !isSameAsSelectedModel;

    //
    this.detectChanges();
  }

  public async handleSubmitAddOrUpdateForm(model: T) {
    //
    if (!model || this.isLoading || this.uiDisabled || !this.canAddOrUpdate) {
      return;
    }

    //
    const isAdd = this.isSameAsDefault(this.selectedModel);
    if (isAdd) {
      await this.issueAddModelTask(model);
    } else {
      await this.issueUpdateModelTask(model);
    }
  }

  public async handleResetAddOrUpdateForm(model: T) {
    //
    if (!model) {
      return;
    }

    //
    await this.managerService.dialogService.presentAreYouSureYesNoDialog(() => {
      //
      this.lock = false;
      this.canAddOrUpdate = false;

      //
      this.modelActionProvider.next({
        action: VBaseFormViewAction.ResetForm,
      });
    });
  }

  public async handleCancelAddOrUpdateForm() {
    //
    if (this.canAddOrUpdate || this.isLocked) {
      //
      await this.managerService.dialogService.presentAreYouSureYesNoDialog(
        async () => {
          //
          this.lock = false;
          await this.toolbarBackHandler();
        }
      );

      //
      return;
    }

    //
    this.lock = false;
    await this.toolbarBackHandler();
  }
  //#endregion

  //
  //#region Actions ...
  async prepareListItems() {
    //
    if (!this.dataPagerResult || !this.hasChild(this.dataPagerResult.items)) {
      return;
    }

    //
    const result = await Promise.all(
      this.dataPagerResult.items.map(async (i) => {
        //
        const slideOptions = await this.provideSlideOptions(
          this.modelFieldPreparer(i)
        );

        //
        return {
          data: i,
          slideOptions,
        } as XListItem<T>;
      })
    );

    //
    return result;
  }

  async handleResetDataPagerQuery() {
    //
    this.dataPagerQuery = {
      filter: '',
      pageNumber: 1,
      rowsInPage: this.config.defaultPageSize,
    };

    //
    this.selectedModel = null;
    await this.changeTab(this.listTabIndex);

    //
    this.detectChanges();
  }

  async handleSearchbarQuryChanged(query: string) {
    //
    this.dataPagerQuery = {
      ...this.dataPagerQuery,
      filter: query,
    };

    //
    this.detectChanges();
  }

  async handleDataPagerQueryChanged(query: XBaseDataPagerQuery) {
    //
    this.dataPagerQuery = {
      ...query,
    };
  }

  async handlePerformRemove(model: T) {
    //
    if (!model) {
      return;
    }

    //
    await this.managerService.dialogService.presentAreYouSureYesNoDialog(
      async () => {
        await this.issueRemoveModelTask(model);
      }
    );
  }

  isPageTask(key: string | any) {
    //
    const pageTasks = this.getTaskNames();
    const mTaskKey = getTaskName(key);
    const result = pageTasks.includes(mTaskKey);

    //
    return result;
  }
  //#endregion

  //
  //#region Private ...
  private toXQuery(q: XBaseDataPagerQuery) {
    return {
      filter: q.filter,
      containsDetail: this.containsDetail,
      enableTracking: this.enableTracking,
      sortBy: this.sortOrder,
      isAscending: this.isAscending,
      page: q.pageNumber,
      pageSize: q.rowsInPage,
    } as XQueryDto;
  }

  private applyToDataPagerQueryResult(result: Observable<XQueryResultDto<T>>) {
    return result.pipe(
      // tslint:disable-next-line: no-shadowed-variable
      map((result) => {
        return {
          count: result.totalItems || 0,
          items: result.items || [],
        } as XBaseDataPagerQueryResult<T>;
      })
    );
  }
  //#endregion
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\views\classes\v-base-data-scroller.page.ts

import {
  XTask,
  toBoolean,
  isNullOrUndefined,
  XModelKeyProvider,
  XModelValueProvider,
  isNullOrEmptyString,
  XBaseDataPagerQuery,
  XBaseDataPagerQueryResult,
} from 'x-framework-core';
import {
  XPageLoadingEvent,
  XDataScrollerAction,
  XDataScrollerActionModel,
} from 'x-framework-components';
import { map } from 'rxjs/operators';
import { Component } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import { getTaskName } from '../tools/task.tools';
import { VPageComponent } from '../v-page/v-page.component';
import { XQueryDto, XQueryResultDto } from '../models/x-query.dto';

@Component({
  template: '',
})
// tslint:disable-next-line: component-class-suffix
export abstract class VBaseDataScrollerPage<T> extends VPageComponent {
  //
  //#region Props ...
  private loaderEvent: any;

  //
  canNext: boolean;
  abstract showSearch: boolean;

  //
  showPageRefresher = true;
  showPageInfinityScroller = true;

  //
  // XQueryDto ...
  canSearch: boolean;
  isAscending = true;
  enableTracking = false;
  containsDetail = false;
  sortOrder: keyof Partial<T>;

  //
  dataScrollerQuery: XBaseDataPagerQuery = {
    filter: '',
    pageNumber: 1,
    rowsInPage: this.config.defaultPageSize,
  };
  dataScrollerResult: XBaseDataPagerQueryResult<T>;
  dataScrollerActionProvider = new Subject<XDataScrollerActionModel>();
  //#endregion

  //
  //#region Abstract ...
  //
  abstract DataScrollerTaskName: string;
  abstract hiddenModelKeys: Array<keyof Partial<T>>;
  abstract availableModelKeys: Array<keyof Partial<T>>;
  abstract sortOrderModelKeys: Array<keyof Partial<T>>;

  //
  abstract modelKeyProvider: XModelKeyProvider<T>;
  abstract modelValueProvider: XModelValueProvider<T>;

  //
  abstract getTaskNames(): string[];
  abstract queryFetcherTask(query: XQueryDto): Observable<XQueryResultDto<T>>;
  //#endregion

  //
  //#region Constructor ...
  //#endregion

  //
  //#region Register Handlers ...
  registerViewHandlers() {
    //
    // Register on DataScroller Action provider ...
    this.applyTakeUntilWrapper(
      this.dataScrollerActionProvider.asObservable()
      // tslint:disable-next-line: deprecation
    ).subscribe((model) => {
      //
      if (!model) {
        return;
      }

      //
      if (model.action === XDataScrollerAction.CanNext) {
        //
        this.canNext = toBoolean(model.payload);
        this.detectChanges();
      }
    });
  }
  //#endregion

  //
  //#region Task Handlers ...
  async onTaskStart(name: string, task: XTask<any>) {
    super.onTaskStart(name, task);
    console.log('onTaskStart: ', name, task);

    //
    if (this.isPageTask(name)) {
      await this.setLoadingState(true);
    }
  }

  async onTaskFinished(name: string, task: XTask<any>) {
    super.onTaskFinished(name, task);
    console.log('onTaskFinished: ', name, task);

    //
    if (this.isPageTask(name)) {
      //
      await this.setLoadingState(false);

      //
      if (name !== this.DataScrollerTaskName) {
        this.showSuccess();
      }

      //
      // Load All Models ...
      if (name === this.DataScrollerTaskName) {
        await this.handleDataScrollerTaskFinished(task.result);
      }
    }
  }

  async onTaskFailed(name: string, task: XTask<any>) {
    super.onTaskFailed(name, task);
    console.log('onTaskFailed: ', name, task);

    //
    if (this.isPageTask(name)) {
      //
      await this.setLoadingState(false);
      this.showError(task.error);
    }
  }
  //#endregion

  //
  //#region UI Providers ...
  queryFetcher = (q: XBaseDataPagerQuery) => {
    //
    const apiQuery = this.toXQuery(q);
    return this.applyToDataScrollerQueryResult(this.queryFetcherTask(apiQuery));
    // tslint:disable-next-line: semicolon
  };

  trackByFn(index: number, item: T) {
    return index;
  }
  //#endregion

  //
  //#region UI Handlers ...
  handleLoadMorePage(event: XPageLoadingEvent) {
    //
    if (!this.canNext) {
      //
      this.loaderEvent = null;
      this.cancelLoading(event.event);
      return;
    }

    //
    this.loaderEvent = event.event;
    this.dataScrollerActionProvider.next({
      action: XDataScrollerAction.LoadMore,
    });
  }

  handleResetDataScrollerQuery() {
    //
    this.dataScrollerQuery = {
      filter: '',
      pageNumber: 1,
      rowsInPage: this.config.defaultPageSize,
    };

    //
    this.dataScrollerActionProvider.next({
      action: XDataScrollerAction.ClearItems,
    });

    //
    this.detectChanges();
  }

  handleRefreshPage(event: XPageLoadingEvent) {
    //
    this.loaderEvent = event.event;
    this.handleResetDataScrollerQuery();
  }

  handleDataScrollerQueryChanged(query: XBaseDataPagerQuery) {
    //
    this.dataScrollerQuery = {
      ...query,
    };
  }

  handleSearchbarQuryChanged(query: string) {
    //
    this.dataScrollerQuery = {
      ...this.dataScrollerQuery,
      filter: query,
    };

    //
    this.detectChanges();
  }

  async handleDataScrollerTaskReady(
    task: Observable<XBaseDataPagerQueryResult<T>>
  ) {
    //
    // XBaseDataPagerQueryResult<any> ...
    if (!task || this.uiDisabled || this.isLoading) {
      return;
    }

    //
    await this.issueDataScrollerTask(task);
  }
  //#endregion

  //
  //#region Actions ...
  protected isPageTask(key: string | any) {
    //
    const pageTasks = this.getTaskNames();
    const mTaskKey = getTaskName(key);
    const result = pageTasks.includes(mTaskKey);

    //
    return result;
  }
  //#endregion

  //
  //#region Private ...
  private toXQuery(q: XBaseDataPagerQuery) {
    return {
      filter: q.filter,
      containsDetail: this.containsDetail,
      enableTracking: this.enableTracking,
      sortBy: this.sortOrder,
      isAscending: this.isAscending,
      page: q.pageNumber,
      pageSize: q.rowsInPage,
    } as XQueryDto;
  }

  private applyToDataScrollerQueryResult(
    result: Observable<XQueryResultDto<T>>
  ) {
    return result.pipe(
      // tslint:disable-next-line: no-shadowed-variable
      map((result) => {
        return {
          count: result.totalItems || 0,
          items: result.items || [],
        } as XBaseDataPagerQueryResult<T>;
      })
    );
  }

  private async issueDataScrollerTask(
    task: Observable<XBaseDataPagerQueryResult<T>>
  ): Promise<void> {
    //
    const mTaskName = this.DataScrollerTaskName;
    const mTask = task;

    //
    await this.addOrUpdateTask({
      priority: 0,
      affectLoading: true,
      name: mTaskName,
      task: mTask,
    });

    //
    await this.dispatchTask(mTaskName);

    //
    if (!isNullOrUndefined(this.loaderEvent)) {
      this.cancelLoading(this.loaderEvent);
    }
  }

  private async handleDataScrollerTaskFinished(
    result: XBaseDataPagerQueryResult<T>
  ) {
    //
    this.dataScrollerResult = null;
    this.detectChanges();

    //
    if (!result) {
      return;
    }

    //
    this.dataScrollerResult = {
      ...result,
    };

    //
    this.canSearch =
      (this.hasChild(this.dataScrollerResult.items) &&
        this.dataScrollerResult.items.length > 1) ||
      !isNullOrEmptyString(this.dataScrollerQuery.filter);

    //
    this.detectChanges();
  }
  //#endregion
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\views\classes\v-base-form-view.ts

import {
  nameof,
  toArray,
  isFunction,
  isSameObject,
  XStandardType,
  XOneOrManyType,
  XColorIdentifier,
  isNullOrUndefined,
  XModelKeyProvider,
  XModelValueProvider,
  XResourceIdentifier,
  isNullOrEmptyString,
  XColorWithBrightness,
  XModelFieldTypeIndex,
  XPartialModelFieldNames,
} from 'x-framework-core';
import {
  XFormConfig,
  XFormStatus,
  XFormActionModel,
  XFormStatusIdentifier,
  XFormValueChangeEventModel,
  XFormStatusChangeEventModel,
  XDescriptionListActionModel,
} from 'x-framework-components';
import {
  VBaseFormViewAction,
  VBaseFormViewActionModel,
  VBaseFormViewPresentType,
  VBaseFormViewPresentTypeIdentifier,
} from '../typings/v-base-form.typings';
import { Subject, Subscription } from 'rxjs';
import { concatMap, map } from 'rxjs/operators';
import { VBaseComponent } from './v-base.component';
import { Input, Output, Component, EventEmitter } from '@angular/core';

@Component({
  template: '',
})
export abstract class VBaseFormViewComponent<T> extends VBaseComponent {
  //
  //#region Props ...
  isValid: boolean;
  validationError: string;
  hasValidationError = false;
  isSameAsDefaultModel: boolean;
  status: XFormStatusIdentifier;

  //
  @Input()
  model: T;
  baseModel: T;
  defaultModel: T;

  //
  @Input()
  hideOptionalValues = false;

  @Input()
  availableModelKeys: XPartialModelFieldNames<T>;

  @Input()
  sortOrderModelKeys: XPartialModelFieldNames<T>;

  @Input()
  hiddenModelKeys: XPartialModelFieldNames<T>;

  @Input()
  hiddenLabelModelKeys: XPartialModelFieldNames<T>;

  @Input()
  modelKeyProvider: XModelKeyProvider<T>;

  @Input()
  modelValueProvider: XModelValueProvider<T>;

  //
  readonly PresentTypes = Object.assign({}, VBaseFormViewPresentType);

  //
  @Input()
  presentType: VBaseFormViewPresentTypeIdentifier =
    VBaseFormViewPresentType.AsForm;

  //
  formConfig: XFormConfig<T>;

  //
  //#region Form Props ...
  @Input()
  formRegularColor: XStandardType<XColorIdentifier> = XColorWithBrightness.Dark;

  @Input()
  formActiveColor: XStandardType<XColorIdentifier> =
    XColorWithBrightness.Tertiary;

  @Input()
  formInvalidColor: XStandardType<XColorIdentifier> =
    XColorWithBrightness.Danger;

  @Input()
  formPendingColor: XStandardType<XColorIdentifier> =
    XColorWithBrightness.Warning;

  @Input()
  formFillColor: XStandardType<XColorIdentifier> =
    XColorWithBrightness.TertiaryShade;

  @Input()
  formDisabledColor: XStandardType<XColorIdentifier> =
    XColorWithBrightness.LightTint;

  @Input()
  formDisabledFillColor: XStandardType<XColorIdentifier> =
    XColorWithBrightness.LightShade;
  //#endregion

  //
  //#region Card Props ...
  @Input()
  isInPage: XStandardType<boolean> = false;

  @Input()
  wrapWithCard: XStandardType<boolean> = false;

  @Input()
  showCardFooter: XStandardType<boolean> = false;

  @Input()
  cardColor: XStandardType<XColorIdentifier> = XColorWithBrightness.Light;

  @Input()
  cardForegroundColor: XStandardType<boolean> = false;

  @Input()
  cardSubTitle: XStandardType<XResourceIdentifier>;
  //#endregion

  //
  //#region Description List Props ...
  @Input()
  cssClass: XOneOrManyType<string>;

  @Input()
  showLabels = true;

  @Input()
  color: XColorIdentifier = XColorWithBrightness.Light;

  @Input()
  foregroundColor = false;

  @Input()
  labelColor: XColorIdentifier = XColorWithBrightness.TertiaryShade;

  @Input()
  contentColor: XColorIdentifier = XColorWithBrightness.Dark;
  //#endregion

  //
  //#region ActionProvider ...
  private ACTION_PROVIDER_SUBSCRIPTION: Subscription;

  @Input()
  actionProvider: Subject<VBaseFormViewActionModel>;

  @Input()
  formActionProvider = new Subject<XFormActionModel>();

  @Input()
  descriptionListActionProvider = new Subject<XDescriptionListActionModel>();
  //#endregion

  //
  //#region Events ...
  @Output()
  modelChanged = new EventEmitter<T>();

  @Output()
  statusChanged = new EventEmitter<boolean>();
  //#endregion
  //#endregion

  //
  //#region Abstract ...
  abstract title: string;
  abstract FieldNames: XModelFieldTypeIndex<T>;
  abstract modelFieldPreparer: (model: T) => T;
  abstract prepareFormConfig(): Promise<void>;
  abstract defaultHiddenModelKeys(): XPartialModelFieldNames<T>;
  abstract defaultSortOrderModelKeys(): XPartialModelFieldNames<T>;
  abstract defaultHiddenLabelModelKeys(): XPartialModelFieldNames<T>;
  abstract defaultModelKeyProvider(): XModelKeyProvider<T>;
  abstract defaultModelValueProvider(): XModelValueProvider<T>;
  //#endregion

  //
  //#region Constructor ...
  //#endregion

  //
  //#region LifeCycles ...
  async onInit() {
    super.onInit();

    //
    await this.prepareModelProviders();

    //
    this.checkSameAsDefault();

    //
    if (!isNullOrUndefined(this.model)) {
      //
      this.baseModel = {
        ...this.model,
      };
      await this.configureForm();
    }
  }

  async onChange(changeKeys: string[]) {
    super.onChange(changeKeys);

    //
    //#region Model Changed ...
    const isModelChanged = changeKeys.includes(
      nameof<VBaseFormViewComponent<T>>('model')
    );
    const isDefaultModelChanged = changeKeys.includes(
      nameof<VBaseFormViewComponent<T>>('defaultModel')
    );

    //
    // Hnadle Model Changed ...
    if (isModelChanged) {
      //
      this.baseModel = {
        ...this.model,
      };
      await this.handleModelChaned();
    }

    //
    // Handle Default Model Check ...
    if (isModelChanged || isDefaultModelChanged) {
      this.checkSameAsDefault();
    }
    //#endregion

    //
    //#region Action Providers ...
    const isActionProviderChanged = changeKeys.includes(
      nameof<VBaseFormViewComponent<T>>('actionProvider')
    );
    if (isActionProviderChanged) {
      this.registerActionProvider();
    }

    //
    const isFormActionProviderChanged = changeKeys.includes(
      nameof<VBaseFormViewComponent<T>>('formActionProvider')
    );
    if (isFormActionProviderChanged) {
      if (!this.formActionProvider) {
        this.formActionProvider = new Subject<XFormActionModel>();
      }
    }

    //
    const isDescriptionListActionProviderChanged = changeKeys.includes(
      nameof<VBaseFormViewComponent<T>>('descriptionListActionProvider')
    );
    if (isDescriptionListActionProviderChanged) {
      if (!this.descriptionListActionProvider) {
        this.descriptionListActionProvider =
          new Subject<XDescriptionListActionModel>();
      }
    }

    //
    if (isFormActionProviderChanged || isDescriptionListActionProviderChanged) {
      this.detectChanges();
    }
    //#endregion

    //
    //#region Color Changed ...
    const isColorChanged = changeKeys.includes(
      nameof<VBaseFormViewComponent<T>>('color')
    );
    if (isColorChanged) {
      //
      this.getValueAsync(this.color).then((color) => {
        this.color = !isNullOrEmptyString(color)
          ? color
          : XColorWithBrightness.Light;
      });
    }
    //#endregion

    //
    //#region ShowLabels Changed ...
    const isShowLabelsChanged = changeKeys.includes(
      nameof<VBaseFormViewComponent<T>>('showLabels')
    );
    if (isShowLabelsChanged) {
      if (isNullOrUndefined(this.showLabels)) {
        this.showLabels = true;
      }
    }
    //#endregion

    //
    //#region CardColor Changed ...
    const isCardColorChanged = changeKeys.includes(
      nameof<VBaseFormViewComponent<T>>('cardColor')
    );
    if (isCardColorChanged) {
      if (isNullOrUndefined(this.cardColor)) {
        this.cardColor = this.ColorNames.Light;
      }
    }
    //#endregion

    //
    //#region SortOrderModelKeys Changed ...
    const isSortOrderModelKeysChanged = changeKeys.includes(
      nameof<VBaseFormViewComponent<T>>('sortOrderModelKeys')
    );
    if (isSortOrderModelKeysChanged) {
      this.prepareSortOrderModelKeys();
    }
    //#endregion

    //
    //#region HiddenModelKeys Changed ...
    const isHiddenModelKeysChanged = changeKeys.includes(
      nameof<VBaseFormViewComponent<T>>('hiddenModelKeys')
    );
    if (isHiddenModelKeysChanged) {
      this.prepareHiddenModelKeys();
    }
    //#endregion

    //
    //#region HiddenLabelModelKeys Changed ...
    const isHiddenLabelModelKeysChanged = changeKeys.includes(
      nameof<VBaseFormViewComponent<T>>('hiddenLabelModelKeys')
    );
    if (isHiddenLabelModelKeysChanged) {
      this.prepareHiddenLabelModelKeys();
    }
    //#endregion

    //
    //#region ModelKeyProvider Changed ...
    const isModelKeyProviderChanged = changeKeys.includes(
      nameof<VBaseFormViewComponent<T>>('modelKeyProvider')
    );
    if (isModelKeyProviderChanged) {
      this.prepareModelKeyProvider();
    }
    //#endregion

    //
    //#region ModelValueProvider Changed ...
    const isModelValueProviderChanged = changeKeys.includes(
      nameof<VBaseFormViewComponent<T>>('modelValueProvider')
    );
    if (isModelValueProviderChanged) {
      this.prepareModelValueProvider();
    }
    //#endregion
  }

  onDestroy() {
    super.onDestroy();

    //
    this.unregisterActionProvider();
  }
  //#endregion

  //
  //#region Register Handlers ...
  registerInstanceHandlers() {
    super.registerInstanceHandlers();

    //
    this.registerActionProvider();
  }
  //#endregion

  //
  //#region UI Handlers ...
  handleFormChange(event: XFormValueChangeEventModel) {
    //
    if (isNullOrUndefined(event) || isNullOrUndefined(event.value)) {
      return;
    }

    //
    const eventModel =
      this.modelFieldPreparer && isFunction(this.modelFieldPreparer)
        ? this.modelFieldPreparer(event.value)
        : (event.value as T);

    //
    this.model = {
      ...eventModel,
    };

    //
    this.checkSameAsDefault();
    this.detectChanges();

    //
    this.modelChanged.emit(this.model);
  }

  handleFormStatusChanged(event: XFormStatusChangeEventModel) {
    //
    if (isNullOrUndefined(event) || isNullOrEmptyString(event.status)) {
      return;
    }

    //
    this.status = event.status;
    this.isValid = this.status === XFormStatus.Valid;

    //
    this.detectChanges();
    this.statusChanged.emit(this.isValid);
  }
  //#endregion

  //
  //#region UI Providers ...
  public canShowKey(key: string) {
    return this.getArrayValue(this.availableModelKeys).pipe(
      concatMap((availableModelKeys) =>
        this.getArrayValue(this.hiddenModelKeys).pipe(
          map((hiddenModelKeys) => {
            return {
              availableModelKeys,
              hiddenModelKeys,
            };
          })
        )
      ),
      map((provider) => {
        //
        const hasChildHiddens = this.hasChild(provider.hiddenModelKeys);
        const hasChildAvailables = this.hasChild(provider.availableModelKeys);

        //
        if (!hasChildAvailables && !hasChildHiddens) {
          return true;
        }

        //
        const isInHiddens = provider.hiddenModelKeys.includes(key as any);
        const isInAvailables = provider.availableModelKeys.includes(key as any);

        //
        if (
          (!hasChildAvailables && !isInHiddens) ||
          (isInAvailables && !hasChildHiddens) ||
          (isInAvailables && !isInHiddens)
        ) {
          return true;
        }

        //
        return false;
      })
    );
  }

  public canShowLabelKey(key: string) {
    return this.getArrayValue(this.hiddenLabelModelKeys).pipe(
      map((hiddenLabelsModelKeys) => {
        //
        const hasChildHiddenLabels = this.hasChild(hiddenLabelsModelKeys);

        //
        if (!hasChildHiddenLabels) {
          return true;
        }

        //
        const isInHiddens = hiddenLabelsModelKeys.includes(key as any);
        return hasChildHiddenLabels && !isInHiddens;
      })
    );
  }
  //#endregion

  //
  //#region Actions ...
  public setValidationError(errorMsg: string) {
    //
    if (isNullOrEmptyString(errorMsg)) {
      return;
    }

    //
    this.hasValidationError = true;
    this.validationError = errorMsg;

    //
    this.detectChanges();
  }

  public clearValidationErrors() {
    //
    this.clearError();
    this.hasValidationError = false;
    this.validationError = null;

    //
    this.detectChanges();
  }

  public async clearForm() {
    //
    this.model = {
      ...this.defaultModel,
    };

    //
    this.checkSameAsDefault();
    await this.prepareFormConfig();

    //
    await this.onFormCleared();
    this.detectChanges();
  }

  public async resetForm() {
    //
    this.model = {
      ...this.baseModel,
    };

    //
    this.checkSameAsDefault();
    await this.prepareFormConfig();

    //
    await this.onFormResetted();
    this.detectChanges();
  }

  public async configureForm() {
    //
    await this.getValueAsync(this.prepareFormConfig());
    this.detectChanges();
  }
  //#endregion

  //
  //#region Protected Actions ...
  protected registerActionProvider() {
    //
    this.unregisterActionProvider();

    //
    if (!this.actionProvider) {
      this.actionProvider = new Subject<VBaseFormViewActionModel>();
    }

    //
    this.ACTION_PROVIDER_SUBSCRIPTION = this.actionProvider
      .asObservable()
      // tslint:disable-next-line: deprecation
      .subscribe(async (model) => {
        //
        if (!model) {
          return;
        }

        //
        switch (model.action) {
          //
          case VBaseFormViewAction.Refresh:
            this.detectChanges();
            break;

          //
          case VBaseFormViewAction.SetError:
            if (model.payload) {
              this.setValidationError(model.payload);
            }
            break;

          //
          case VBaseFormViewAction.ClearError:
            this.clearValidationErrors();
            break;

          //
          case VBaseFormViewAction.ClearForm:
            await this.clearForm();
            break;

          //
          case VBaseFormViewAction.ResetForm:
            await this.resetForm();
            break;
        }
      });
  }

  protected unregisterActionProvider() {
    //
    if (!this.ACTION_PROVIDER_SUBSCRIPTION) {
      return;
    }

    //
    this.ACTION_PROVIDER_SUBSCRIPTION.unsubscribe();
    this.ACTION_PROVIDER_SUBSCRIPTION = null;
  }

  protected async handleModelChaned() {
    await this.configureForm();
  }

  protected checkSameAsDefault() {
    //
    this.isSameAsDefaultModel = false;
    if (
      !isNullOrUndefined(this.model) &&
      !isNullOrUndefined(this.defaultModel)
    ) {
      this.isSameAsDefaultModel = isSameObject(
        this.modelFieldPreparer(this.model) as any,
        this.modelFieldPreparer(this.defaultModel) as any
      );
    }

    //
    this.detectChanges();
  }

  protected async onFormCleared(): Promise<void> {}

  protected async onFormResetted(): Promise<void> {}

  protected async onModelProvidersPrepared(): Promise<void> {}

  protected async onSortOrderModelKeysPrepared(): Promise<void> {}

  protected async onHiddenModelKeysPrepared(): Promise<void> {}

  protected async onHiddenLabelModelKeysPrepared(): Promise<void> {}

  protected async onModelKeyProviderPrepared(): Promise<void> {}

  protected async onModelValueProviderPrepared(): Promise<void> {}
  //#endregion

  //
  //#region Private ...
  private async prepareModelProviders() {
    //
    await this.prepareSortOrderModelKeys();
    await this.prepareHiddenModelKeys();
    await this.prepareHiddenLabelModelKeys();
    await this.prepareModelKeyProvider();
    await this.prepareModelValueProvider();

    //
    await this.onModelProvidersPrepared();
  }

  private async prepareSortOrderModelKeys() {
    //
    if (isNullOrUndefined(this.sortOrderModelKeys)) {
      //
      this.sortOrderModelKeys = [...toArray(this.defaultSortOrderModelKeys())];

      //
      await this.onSortOrderModelKeysPrepared();

      //
      this.detectChanges();
    } else {
      await this.onSortOrderModelKeysPrepared();
    }
  }

  private async prepareHiddenModelKeys() {
    //
    if (isNullOrUndefined(this.hiddenModelKeys)) {
      //
      this.hiddenModelKeys = [...toArray(this.defaultHiddenModelKeys())];

      //
      await this.onHiddenModelKeysPrepared();

      //
      this.detectChanges();
    } else {
      await this.onHiddenModelKeysPrepared();
    }
  }

  private async prepareHiddenLabelModelKeys() {
    //
    if (isNullOrUndefined(this.hiddenLabelModelKeys)) {
      //
      this.hiddenLabelModelKeys = this.defaultHiddenLabelModelKeys();

      //
      await this.onHiddenLabelModelKeysPrepared();

      //
      this.detectChanges();
    } else {
      await this.onHiddenLabelModelKeysPrepared();
    }
  }

  private async prepareModelKeyProvider() {
    //
    if (isNullOrUndefined(this.modelKeyProvider)) {
      //
      this.modelKeyProvider = this.defaultModelKeyProvider();

      //
      await this.onModelKeyProviderPrepared();

      //
      this.detectChanges();
    } else {
      await this.onModelKeyProviderPrepared();
    }
  }

  private async prepareModelValueProvider() {
    //
    if (isNullOrUndefined(this.modelValueProvider)) {
      //
      this.modelValueProvider = this.defaultModelValueProvider();

      //
      await this.onModelValueProviderPrepared();

      //
      this.detectChanges();
    } else {
      await this.onModelValueProviderPrepared();
    }
  }
  //#endregion
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\views\classes\v-base-tabs.page.ts

import { Subject } from 'rxjs';
import {
  XSlotName,
  XFabButton,
  XButtonType,
  XTabsAction,
  XSlotLayout,
  XFabButtonSize,
  XFabButtonSide,
  XTabsActionModel,
} from 'x-framework-components';
import { Component } from '@angular/core';
import { VPageComponent } from '../v-page/v-page.component';

@Component({
  template: '',
})
// tslint:disable-next-line: component-class-suffix
export abstract class VBaseTabsPage extends VPageComponent {
  //
  //#region Props ...
  //
  readonly SlotNames = Object.assign({}, XSlotName);
  readonly SlotLayouts = Object.assign({}, XSlotLayout);
  readonly ButtonTypes = Object.assign({}, XButtonType);

  //
  // Tabs Configs ...
  lastTab: number;
  selectedTab: number;
  tabsActionProvider = new Subject<XTabsActionModel>();

  //
  //#region Default Fab Buttons ...
  //
  // Edit ...
  readonly defaultEditFab: XFabButton = {
    id: 'Edit',
    index: 1,
    icon: this.IconNames.edit,
    tooltip: this.ResourceIDs.edit,
    size: XFabButtonSize.MINI,
    side: XFabButtonSide.TOP,
    disabled: this.isLoading || this.uiDisabled,
    color: this.ColorNames.Tertiary,
  };

  //
  // Remove ...
  readonly defaultRemoveFab: XFabButton = {
    id: 'Remove',
    index: 1,
    icon: this.IconNames.remove,
    tooltip: this.ResourceIDs.delete,
    size: XFabButtonSize.MINI,
    side: XFabButtonSide.TOP,
    disabled: this.isLoading || this.uiDisabled,
    color: this.ColorNames.Danger,
  };

  //
  // Add ...
  readonly defaultAddFab: XFabButton = {
    id: 'Add',
    index: 1,
    icon: this.IconNames.add,
    size: XFabButtonSize.REGULAR,
    color: this.ColorNames.Primary,
    tooltip: this.ResourceIDs.add,
    side: XFabButtonSide.TOP,
    disabled: this.isLoading || this.uiDisabled,
  };

  //
  // Upload ...
  readonly defaultUploadFab: XFabButton = {
    id: 'Upload',
    index: 1,
    icon: this.IconNames.upload,
    size: XFabButtonSize.REGULAR,
    color: this.ColorNames.Primary,
    tooltip: this.ResourceIDs.upload,
    side: XFabButtonSide.TOP,
    disabled: this.isLoading || this.uiDisabled,
  };

  //
  // Download ...
  readonly defaultDownloadFab: XFabButton = {
    id: 'Download',
    index: 1,
    icon: this.IconNames.download,
    size: XFabButtonSize.REGULAR,
    color: this.ColorNames.Success,
    tooltip: this.ResourceIDs.download,
    side: XFabButtonSide.TOP,
    disabled: this.isLoading || this.uiDisabled,
  };

  //
  // Select ...
  readonly defaultSelectFilesFab: XFabButton = {
    index: 1,
    id: 'SelectFiles',
    side: XFabButtonSide.TOP,
    icon: this.IconNames.touch,
    size: XFabButtonSize.REGULAR,
    color: this.ColorNames.Primary,
    tooltip: this.ResourceIDs.select,
    disabled: this.isLoading || this.uiDisabled,
  };

  //
  // More ...
  readonly defaultMoreFab: XFabButton = {
    id: 'More',
    index: 1,
    side: XFabButtonSide.TOP,
    size: XFabButtonSize.REGULAR,
    color: this.ColorNames.Primary,
    tooltip: this.ResourceIDs.options,
    icon: this.IconNames.menu_vertical,
    disabled: this.isLoading || this.uiDisabled,
  };
  //#endregion
  //#endregion

  //
  //#region Constructor ...
  //#endregion

  //
  //#region LifeCycles ...
  toolbarBackHandler = async () => {
    //
    if (this.isLoading || this.uiDisabled || this.isLocked) {
      return;
    }

    //
    await this.handleToolbarBackPressed();
  };
  //#endregion

  //
  //#region Register Handlers ...
  //#endregion

  //
  //#region Task Handlers ...
  //#endregion

  //
  //#region UI Providers ...
  //#endregion

  //
  //#region UI Handlers ...
  //#endregion

  //
  //#region Actions ...
  async changeTab(tab: number) {
    //
    if (tab === this.selectedTab || this.isLocked) {
      return;
    }

    //
    this.selectedTab = tab;
    this.tabsActionProvider.next({
      action: XTabsAction.TO,
      payload: tab,
    });

    //
    await this.prepareStates();
  }
  //#endregion

  //
  //#region Abstracted ...
  abstract prepareStates(): Promise<void>;

  abstract handleToolbarBackPressed(): Promise<void>;
  //#endregion

  //
  //#region Private ...
  //#endregion
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\views\classes\v-base.component.ts

import {
  Inject,
  NgZone,
  Renderer2,
  Component,
  ElementRef,
  ChangeDetectorRef,
} from '@angular/core';
import { X_CONFIG } from '../../config/x-config';
import { XConfig } from '../../config/app-config';
import { ViewportRuler } from '@angular/cdk/overlay';
import { XManagerService } from 'x-framework-services';
import { XColorWithBrightness } from 'x-framework-core';
import { XBaseComponent, XIconNames } from 'x-framework-components';
import { AppResourceIDs } from '../../config/app.localization.config';

@Component({
  template: '',
})
export abstract class VBaseComponent extends XBaseComponent {
  //
  //#region Props ...
  //
  readonly IconNames = Object.assign({}, XIconNames);
  readonly AppResourceIDs = Object.assign({}, AppResourceIDs);
  readonly ColorNames = Object.assign({}, XColorWithBrightness);

  //
  isMobileUi$ = this.managerService.isMobileUi$;
  isNotMobileUi$ = this.managerService.isNotMobileUi$;
  //#endregion

  //
  //#region Constructor ...
  public constructor(
    public zone: NgZone,
    @Inject(X_CONFIG)
    public config: XConfig,
    public element: ElementRef,
    public renderer: Renderer2,
    public ruler: ViewportRuler,
    public managerService: XManagerService,
    public changeDetector: ChangeDetectorRef
  ) {
    super(
      config,
      managerService,
      element,
      renderer,
      ruler,
      zone,
      changeDetector
    );
  }
  //#endregion
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\views\models\x-query.dto.ts

export interface XQueryDto {
  filter?: string;
  containsDetail?: boolean;
  enableTracking?: boolean;
  sortBy?: string;
  isAscending?: boolean;
  page?: number;
  pageSize?: number;
}

export interface XQueryResultDto<T = any> {
  items?: Array<T>;
  page?: number;
  pageSize?: number;
  totalPages?: number;
  totalFilteredItems?: number;
  totalItems?: number;
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\views\tools\task.tools.ts

export const taskIdStartKey = '_[';
export const taskIdEndKey = ']';

/**
 * check if task name contains id  ...
 *
 * @param key the task name ...
 */
export function hasTaskId(key: string | any) {
  //
  if (!key) {
    return false;
  }

  //
  const mKey = key.toString() as string;
  return mKey.includes(taskIdStartKey) && mKey.includes(taskIdEndKey);
}

/**
 * retrieve and extract the raw task name from a task name ...
 *
 * @param key the task name ...
 */
export function getTaskName(key: string | any) {
  //
  if (!key) {
    return '';
  }

  //
  const mKey = key.toString() as string;

  //
  if (!hasTaskId(mKey)) {
    return mKey;
  }

  //
  const taskId = getTaskId(mKey);
  const taskIdString = `${taskIdStartKey}${taskId}${taskIdEndKey}`;
  const result = mKey.replace(taskIdString, '');

  //
  return result;
}

/**
 * retrieve and extract the id inside a task name ...
 *
 * @param key the task name ...
 */
export function getTaskId(key: string | any) {
  //
  // Validate Args ...
  if (!key || !hasTaskId(key)) {
    return '';
  }

  //
  // Task Id ...
  let result = key.toString() as string;

  //
  // Validating Info ...
  let index = result.indexOf(taskIdStartKey);

  //
  result = result.substr(index, result.length);
  result = result.replace(taskIdStartKey, '');

  //
  index = result.indexOf(taskIdEndKey);
  result = result.substring(0, index);

  //
  // Return Result ...
  return result;
}

/**
 * prepare a Task With ID and return ...
 *
 * @param key the Task Name ...
 * @param id th ID ...
 */
export function setTaskId(key: string | any, id: string | any) {
  return `${key.toString()}${taskIdStartKey}${id.toString()}${taskIdEndKey}`;
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\views\tools\v-base.tools.ts

import {
    isValidEmail,
    isValidPhoneNumber,
    isNullOrEmptyString,
  } from 'x-framework-core';
  
  /**
   * generate an href string for linking to email addresses ...
   *
   * @param email the propper email address ...
   */
  export function getEmailHref(email: string) {
    //
    if (isNullOrEmptyString(email) || !isValidEmail(email)) {
      return '';
    }
  
    //
    return `mailto:${email}`;
  }
  
  /**
   * generate an href string for linking to phoneNumber ...
   *
   * @param phoneNumber the propper phone number ...
   */
  export function getPhoneNumberHref(phoneNumber: string) {
    //
    if (isNullOrEmptyString(phoneNumber) || !isValidPhoneNumber(phoneNumber)) {
      return '';
    }
  
    //
    return `tel:${phoneNumber}`;
  }
  

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\views\tools\v-data-pager.tools.ts

import {
    XBaseDataPagerQuery,
    XBaseDataPagerQueryResult,
  } from 'x-framework-core';
  import { Observable } from 'rxjs';
  import { map } from 'rxjs/operators';
  import { XQueryDto, XQueryResultDto } from '../models/x-query.dto';
  
  export function toXQuery(
    q: XBaseDataPagerQuery,
    containsDetail = true,
    enableTracking = false,
    sortBy = 'id',
    isAscending = true
  ) {
    return {
      filter: q.filter,
      containsDetail,
      enableTracking,
      sortBy,
      isAscending,
      page: q.pageNumber,
      pageSize: q.rowsInPage,
    } as XQueryDto;
  }
  
  export function applyToDataPagerQueryResult<T>(
    result: Observable<XQueryResultDto<T>>
  ) {
    return result.pipe(
      map((queryResult) => {
        return {
          count: queryResult.totalItems || 0,
          items: queryResult.items || [],
        } as XBaseDataPagerQueryResult<T>;
      })
    );
  }
  

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\views\typings\v-base-form.typings.ts

import { XBaseActionModel } from 'x-framework-components';

export enum VBaseFormViewPresentType {
  AsForm = 'as_form',
  AsDescriptionList = 'as_description_list',
}

export type VBaseFormViewPresentTypeIdentifier =
  | VBaseFormViewPresentType
  | string;

export enum VBaseFormViewAction {
  //
  Refresh = 'refresh',
  SetError = 'set_error',
  ClearError = 'clear_error',
  ClearForm = 'clear_form',
  ResetForm = 'reset_form',
}

export type VBaseFormViewActionIdentifier = VBaseFormViewAction | string;

export interface VBaseFormViewActionModel
  extends XBaseActionModel<VBaseFormViewActionIdentifier> {}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\views\v-maintainer\v-maintainer.component.html

<div class="wrapper">
  <h3 class="title">
    {{ getResourceValue(ResourceIDs.maintainer_title) | async }}
  </h3>
  <h4 xColor="tertiary" [isForeground]="true" class="content">
    {{ getResourceValue(ResourceIDs.maintainer_name) | async }}
  </h4>
  <div class="socials">
    <!-- LinkedIn -->
    <div class="social linkedin">
      <a
        target="_blank"
        class="social-link"
        href="https://www.linkedin.com/in/hadi-khazaee-asl/"
      >
        <x-icon name="logo_linkedin"></x-icon>
      </a>
    </div>

    <!-- Github -->
    <div class="social github">
      <a target="_blank" class="social-link" href="https://github.com/saherelm">
        <x-icon name="logo_github"></x-icon>
      </a>
    </div>

    <!-- Gitlab -->
    <div class="social gitlab">
      <a target="_blank" class="social-link" href="https://gitlab.com/SaherElm">
        <x-icon name="logo_gitlab"></x-icon>
      </a>
    </div>

    <!-- DockerHub -->
    <div class="social dockerhub">
      <a
        target="_blank"
        class="social-link"
        href="https://hub.docker.com/u/saherelm"
      >
        <x-icon name="logo_docker"></x-icon>
      </a>
    </div>

    <!-- Skype -->
    <div class="social skype">
      <a target="_blank" class="social-link" href="skype:hadi_khazaee_asl?call">
        <x-icon name="logo_skype"></x-icon>
      </a>
    </div>

    <!-- Mail -->
    <div class="social mail">
      <a
        target="_blank"
        class="social-link"
        href="mailto:hadi_khazaee_asl@yahoo.com"
      >
        <x-icon name="mail"></x-icon>
      </a>
    </div>

    <!-- Web -->
    <div class="social web">
      <a target="_blank" class="social-link" href="https://www.saherelm.ir">
        <x-icon name="web"></x-icon>
      </a>
    </div>
  </div>
</div>

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\views\v-maintainer\v-maintainer.component.scss

h1,
h2,
h3,
h4,
h5,
h6 {
  margin: 0;
}

.socials {
  margin-top: 6px;
}

.social {
  display: inline-block;
  margin: 0 2px;
}

:host ::ng-deep .x-icon {
  &:hover {
    color: var(--x-color-tertiary) !important;
  }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\views\v-maintainer\v-maintainer.component.ts

import {
  Inject,
  NgZone,
  Renderer2,
  Component,
  ElementRef,
  ChangeDetectorRef,
  ChangeDetectionStrategy,
} from '@angular/core';
import { XResourceIDs } from 'x-framework-core';
import { X_CONFIG } from '../../config/x-config';
import { XConfig } from '../../config/app-config';
import { ViewportRuler } from '@angular/cdk/overlay';
import { XManagerService } from 'x-framework-services';
import { XBaseComponent } from 'x-framework-components';
import { AppResourceIDs } from 'src/app/config/app.localization.config';

@Component({
  // tslint:disable-next-line:component-selector
  selector: 'v-maintainer',
  templateUrl: './v-maintainer.component.html',
  styleUrls: ['./v-maintainer.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class VMaintainerComponent extends XBaseComponent {
  //
  //#region Props ...
  //
  // Prepare All Resource IDs ...
  readonly ResourceIDs = Object.assign(
    Object.assign({}, XResourceIDs),
    AppResourceIDs
  ) as any;
  //#endregion

  //
  //#region Constructor ...
  public constructor(
    @Inject(X_CONFIG) public config: XConfig,
    public managerService: XManagerService,
    public element: ElementRef,
    public renderer: Renderer2,
    public ruler: ViewportRuler,
    public zone: NgZone,
    public changeDetector: ChangeDetectorRef
  ) {
    super(
      config,
      managerService,
      element,
      renderer,
      ruler,
      zone,
      changeDetector
    );
  }
  //#endregion
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\views\v-page\v-page.component.html

<x-page
  [loading]="isLoading"
  [uiDisabled]="uiDisabled"
  [color]="getValue(color) | async"
  (loadMore)="loadMore.emit($event)"
  [sideColor]="sideColor || 'primary'"
  [hasSide]="getValue(hasSide) | async"
  [actions]="getValue(actions) | async"
  [sideSlot]="getValue(sideSlot) | async"
  [sideType]="getValue(sideType) | async"
  [menuState]="getValue(menuState) | async"
  [menuActionProvider]="menuActionProvider"
  [toolbarBackHandler]="toolbarBackHandler"
  [showFooter]="getValue(showFooter) | async"
  (scrolledEvent)="scrolledEvent.emit($event)"
  [cssClass]="getArrayValue(cssClass) | async"
  (imageCaptured)="handleImageCaptured($event)"
  [footerColor]="getValue(footerColor) | async"
  [toolbarTitle]="getValue(toolbarTitle) | async"
  [toolbarColor]="getValue(toolbarColor) | async"
  [actionsActionProvider]="actionsActionProvider"
  (menuStateChange)="menuStateChange.emit($event)"
  [sideMenuWidth]="getValue(sideMenuWidth) | async"
  [toolbarEndSlotButtonsTemplate]="
    getValue(toolbarEndSlotButtonsTemplate) | async
  "
  [toolbarHasBack]="getValue(toolbarHasBack) | async"
  [toolbarHasMenu]="getValue(toolbarHasMenu) | async"
  [toolbarLogoUrl]="getValue(toolbarLogoUrl) | async"
  [toolbarStartSlotButtonsTemplate]="
    getValue(toolbarStartSlotButtonsTemplate) | async
  "
  [toggleMenuWhen]="getValue(toggleMenuWhen) | async"
  [toolbarShowBack]="getValue(toolbarShowBack) | async"
  [toolbarSubTitle]="getValue(toolbarSubTitle) | async"
  [toolbarShowMenu]="getValue(toolbarShowMenu) | async"
  [toolbarBackSlot]="getValue(toolbarBackSlot) | async"
  [toolbarMenuSlot]="getValue(toolbarMenuSlot) | async"
  [toolbarShowLogo]="getValue(toolbarShowLogo) | async"
  [toolbarLogoSlot]="getValue(toolbarLogoSlot) | async"
  [sideMenuMaxWidth]="getValue(sideMenuMaxWidth) | async"
  [sideMenuMinWidth]="getValue(sideMenuMinWidth) | async"
  [toolbarTitleSlot]="getValue(toolbarTitleSlot) | async"
  [scrollEndClasses]="getValue(scrollEndClasses) | async"
  [scrollingClasses]="getValue(scrollingClasses) | async"
  [toolbarShowTitle]="getValue(toolbarShowTitle) | async"
  [captureTopOffset]="getValue(captureTopOffset) | async"
  [scrollEventActionProvider]="scrollEventActionProvider"
  [toolbarContentTemplate]="
    (getValue(showToolbarContent) | async)
      ? toolbarContentTemplate || toolbarContentTemplateRef
      : undefined
  "
  [showPageRefresher]="getValue(showPageRefresher) | async"
  [enableCaptureMode]="getValue(enableCaptureMode) | async"
  (splitterStateChanged)="splitterStateChanged.emit($event)"
  [scrollBehaviour]="getArrayValue(scrollBehaviour) | async"
  [toolbarContentSlot]="getValue(toolbarContentSlot) | async"
  [toolbarDefaultHref]="getValue(toolbarDefaultHref) | async"
  [scrollStartClasses]="getValue(scrollStartClasses) | async"
  [footerContentTemplate]="footerContentTemplate || footerRef"
  [captureBottomOffset]="getValue(captureBottomOffset) | async"
  [provideScrollEvents]="getValue(provideScrollEvents) | async"
  [toolbarShowSubTitle]="getValue(toolbarShowSubTitle) | async"
  [downloadCapturedImage]="getValue(downloadCapturedImage) | async"
  [toolbarEndSlotButtonsTemplate]="toolbarEndSlotButtonsTemplateRef"
  [toolbarShowProgressBar]="getValue(toolbarShowProgressBar) | async"
  [toolbarProgressBarColor]="getValue(toolbarProgressBarColor) | async"
  [showPageInfinityScroller]="getValue(showPageInfinityScroller) | async"
>
  <!-- Side Content -->
  <div class="app-side-content" side>
    <ng-container *ngTemplateOutlet="defaultSideMenuRef"></ng-container>
  </div>

  <!-- Page Content -->
  <div class="app-page-content">
    <ng-content></ng-content>
  </div>
</x-page>

<!-- Page Footer -->
<ng-template #footerRef>
  <h4 class="x-footer-content">{{ resourceProvider(ResourceIDs.company) }}</h4>
</ng-template>

<!-- Page Side Menu -->
<ng-template #defaultSideMenuRef>
  <x-navigator
    [items]="navPages"
    [showChildIcon]="false"
    [closeSiblings]="false"
    [dividerColor]="'primary'"
    [highlightColor]="'warning'"
    [disableParentRouting]="true"
    [childColor]="'primary-shade'"
    [parentColor]="'tertiary-shade'"
    [parentActiveColor]="'warning-shade'"
    (itemSelected)="handleNavigatorItemSelected($event)"
    *ngIf="(getValue(hasSide) | async) && (hasChildValue(navPages) | async)"
  ></x-navigator>
</ng-template>

<!-- Toolbar Menu -->
<ng-template #toolbarEndSlotButtonsTemplateRef>
  <x-button
    [type]="'icon'"
    [color]="'cb-inherit'"
    (click)="handleMoreButtonClicked($event)"
  >
    <x-icon [name]="'menu_vertical'" [color]="'light'"></x-icon>
  </x-button>
</ng-template>

<!-- Toolbar Content -->
<ng-template #toolbarContentTemplateRef> </ng-template>

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\views\v-page\v-page.component.scss

.x-footer-content {
  margin: 0;
  padding: 0;
}

:host::ng-deep {
  .x-toolbar-end-slot {
    flex-shrink: 0 !important;
    justify-content: flex-end;
  }

  .x-toolbar-start-slot {
    flex-shrink: 1 !important;
    flex-grow: 7 !important;
    justify-content: flex-start;
    overflow: hidden;
    text-overflow: ellipsis;
  }
}

x-page {
  // --content-offset-top: -56px !important;
  // --content-offset-bottom: -56px !important;

  // --side-menu-content-offset-top: -54px !important;
  // --side-menu-content-offset-bottom: -44px !important;
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\app\views\v-page\v-page.component.ts

import {
  Input,
  Inject,
  NgZone,
  Renderer2,
  Component,
  ViewChild,
  ElementRef,
  TemplateRef,
  EventEmitter,
  ChangeDetectorRef,
  ChangeDetectionStrategy,
} from '@angular/core';
import {
  XColor,
  nameof,
  XLocale,
  notValue,
  XResourceIDs,
  XPickerColumn,
  XStandardType,
  XOneOrManyType,
  XColorIdentifier,
  XModalButtonRole,
  XPickerColumnOption,
  XColorWithBrightness,
} from 'x-framework-core';
import {
  XMenuSlot,
  XLogoSlot,
  XBackSlot,
  XSideType,
  XSideSlot,
  XTitleSlot,
  XIconNames,
  XMenuState,
  XContentSlot,
  XPageComponent,
  XPageContainer,
  XPopoverOption,
  XPopoverService,
  XNavigatorListItem,
  XBackSlotIdentifier,
  XLogoSlotIdentifier,
  XMenuSlotIdentifier,
  XPageSizeIdentifier,
  XSideSlotIdentifier,
  XSideTypeIdentifier,
  XTitleSlotIdentifier,
  XContentSlotIdentifier,
} from 'x-framework-components';
import { map } from 'rxjs/operators';
import { MenuController } from '@ionic/angular';
import { X_CONFIG } from 'src/app/config/x-config';
import { Pages } from 'src/app/config/page.config';
import { XConfig } from 'src/app/config/app-config';
import { ViewportRuler } from '@angular/cdk/overlay';
import { XManagerService } from 'x-framework-services';
import { NavPageItems } from 'src/app/config/page.config';
import { isNullOrUndefined, hasChild } from 'x-framework-core';
import { AppResourceIDs } from 'src/app/config/app.localization.config';

@Component({
  // tslint:disable-next-line:component-selector
  selector: 'v-page',
  templateUrl: './v-page.component.html',
  styleUrls: ['./v-page.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class VPageComponent extends XPageComponent {
  //
  //#region Props ...
  //
  isMobileUi$ = this.managerService.isMobileUi$;
  isNotMobileUi$ = this.managerService.isNotMobileUi$;

  //
  readonly IconNames = Object.assign({}, XIconNames);
  readonly AppResourceIDs = Object.assign({}, AppResourceIDs);
  readonly ColorNames = Object.assign({}, XColorWithBrightness);

  //
  navPages = NavPageItems;

  //
  //#region CaptureMode ...
  enableCaptureMode: XStandardType<boolean> = false;
  downloadCapturedImage: XStandardType<boolean> = true;
  captureTopOffset: XStandardType<number> = 0;
  captureBottomOffset: XStandardType<number> = 0;
  imageCaptured = new EventEmitter<string | Blob>();
  //#endregion

  //
  //#region Page Props ...
  //
  //#region Toolbar Content ...
  @Input()
  showToolbarContent = true;
  private TOOLBAR_CONTENT_TEMPLATE: TemplateRef<any>;

  /**
   * the toolbar content ...
   */
  @ViewChild('toolbarContentTemplateRef', { static: false })
  set toolbarContentTemplateRef(v: TemplateRef<any>) {
    //
    if (isNullOrUndefined(v)) {
      return;
    }

    //
    this.TOOLBAR_CONTENT_TEMPLATE = v;
  }

  get toolbarContentTemplateRef() {
    return this.TOOLBAR_CONTENT_TEMPLATE;
  }
  //#endregion

  //
  //#region Toolbar End Slot ...
  @Input()
  showToolbarEndSlot = true;
  //#endregion

  //
  color: XStandardType<XColorIdentifier> = 'light-shade';
  cssClass: XStandardType<XOneOrManyType<string>>;
  //#endregion

  //
  //#region Toolbar Props ...
  //
  //#region Toolbar Boundary ...
  //
  showToolbar: XStandardType<boolean> = true;

  //
  toolbarColor: XStandardType<XColor> = XColor.Primary;
  //#endregion

  //
  //#region Toolbar ProgressBar ...
  toolbarProgressBarColor: XStandardType<XColor> = XColor.Warning;
  //#endregion

  //
  //#region Toolbar Title and SubTitle ...
  //
  // Toolbar Title ...
  toolbarTitleSlot: XStandardType<XTitleSlotIdentifier> = XTitleSlot.End;
  toolbarShowTitle: XStandardType<boolean> = true;
  toolbarShowSubTitle: XStandardType<boolean> = false;
  toolbarTitle: XStandardType<string> = super.resourceProvider(
    this.ResourceIDs.app_name
  );
  //#endregion

  //
  //#region Toolbar Logo ...
  toolbarLogoSlot: XStandardType<XLogoSlotIdentifier> = XLogoSlot.End;
  toolbarShowLogo: XStandardType<boolean> = true;
  toolbarLogoUrl: XStandardType<string> = './assets/image/logo.png';
  //#endregion

  //
  //#region Toolbar Back ...
  toolbarBackSlot: XStandardType<XBackSlotIdentifier> = XBackSlot.Start;
  toolbarShowBack: XStandardType<boolean> = false;
  toolbarHasBack: XStandardType<boolean> = true;
  toolbarDefaultHref: string = '';
  //#endregion

  //
  //#region Toolbar Menu ...
  toolbarMenuSlot: XStandardType<XMenuSlotIdentifier> = XMenuSlot.Start;

  //
  menuState: XStandardType<XMenuState> = XMenuState.WillClose;

  //
  toolbarShowMenu: XStandardType<boolean> = true;

  //
  toolbarHasMenu: XStandardType<boolean> = true;
  //#endregion

  //
  //#region Toolbar Templates ...
  toolbarContentSlot: XStandardType<XContentSlotIdentifier> =
    XContentSlot.Start;
  //#endregion
  //#endregion

  //
  //#region Scrolling Handlers ...
  provideScrollEvents: XStandardType<boolean> = true;
  scrollBehaviour: XOneOrManyType<string> = ['x-fab'];
  scrollStartClasses: XOneOrManyType<string> = 'start-scroll';
  scrollEndClasses: XOneOrManyType<string> = 'end-scroll';
  //#endregion

  //
  //#region Footer Props ...
  //
  footerColor: XStandardType<XColorIdentifier> = XColor.Primary;
  //#endregion

  //
  //#region Side Props ...
  //
  toggleMenuWhen: XStandardType<XPageSizeIdentifier> = 'md';
  hasSide: XStandardType<boolean> = true;
  sideSlot: XStandardType<XSideSlotIdentifier> = XSideSlot.Start;
  sideType: XStandardType<XSideTypeIdentifier> = XSideType.Overlay;
  sideColor: XStandardType<XColorIdentifier> = XColor.Primary;
  //#endregion
  //#endregion

  //
  //#region Constructor ...
  public constructor(
    public zone: NgZone,
    @Inject(X_CONFIG)
    public config: XConfig,
    public element: ElementRef,
    public renderer: Renderer2,
    public ruler: ViewportRuler,
    public menuController: MenuController,
    public managerService: XManagerService,
    public changeDetector: ChangeDetectorRef,
    protected popoverService: XPopoverService, 
    protected propertyProvider: XPageContainer
  ) {
    super(
      config,
      managerService,
      element,
      renderer,
      ruler,
      zone,
      changeDetector,
      menuController,
      propertyProvider
    );

    //
    this.isMobileUi$ = this.managerService.isMobileUi$;
    this.isNotMobileUi$ = notValue(this.isMobileUi$);
  }
  //#endregion

  //
  //#region LifeCycle ...
  onInit() {
    super.onInit();

    //
    this.menuState = this.isMobileUi$.pipe(
      map((isMobile) => (isMobile ? XMenuState.WillClose : XMenuState.Opened))
    );
  }

  async afterViewInit() {
    super.afterViewInit();

    //
    const showToolbar = await this.getValueAsync(this.showToolbar);
    if (showToolbar) {
      this.detectChanges();
    }

    //
    this.managerService.dispatchResizeEvent();
  }

  afterViewChecked() {
    super.afterViewChecked();

    //
    this.changeDetector.detectChanges();
  }

  async onChange(changeKeys: string[]) {
    super.onChange(changeKeys);

    //
    const isHasSideChanged = changeKeys.includes(
      nameof<VPageComponent>('hasSide')
    );
    if (isHasSideChanged) {
      await this.handleHasSideEffect();
    }

    //
    const isToolbarHasMenuChanged = changeKeys.includes(
      nameof<VPageComponent>('toolbarHasMenu')
    );
    const isToolbarShowMenuChanged = changeKeys.includes(
      nameof<VPageComponent>('toolbarShowMenu')
    );
    if (isToolbarHasMenuChanged || isToolbarShowMenuChanged) {
      this.detectChanges();
    }
  }
  //#endregion

  //
  //#region Register Handlers ...
  //#endregion

  //
  //#region Handlers ...
  //#endregion

  //
  //#region UI Providers ...
  //#endregion

  //
  //#region UI Handlers ...
  async handleNavigatorItemSelected(event: XNavigatorListItem) {
    //
    if (!event) {
      return;
    }

    //
    // TODO: Complete Special Actions on NavItems ...
  }

  async handleMoreButtonClicked(event: any) {
    //
    const onlyIcon = false;

    //
    const options: XPopoverOption[] = [];

    //
    // Home Page ...
    options.push({
      id: 'go_home',
      icon: XIconNames.home,
      title: AppResourceIDs.home,
      color: XColor.Tertiary,
      slot: 'start',
      onlyIcon,
      handler: async () => {
        await this.managerService.navigateByPageReplace(Pages.Home);
      },
    });

    //
    // Change Language ...
    options.push({
      id: 'change_language',
      icon: XIconNames.language,
      title: XResourceIDs.language,
      color: XColor.Tertiary,
      slot: 'start',
      onlyIcon,
      handler: async () => {
        await this.handleChangeLocale();
      },
    });

    //
    // CaptureMode ...
    const isCaptureModeEnabled = await this.getValueAsync(
      this.enableCaptureMode
    );
    if (isCaptureModeEnabled) {
      //
      // Capture Mode ...
      options.push({
        id: 'disable_capture_mode',
        icon: XIconNames.crop,
        title: XResourceIDs.disable_capture_mode,
        color: XColor.Danger,
        slot: 'start',
        onlyIcon,
        handler: async () => {
          //
          this.enableCaptureMode = false;
          this.detectChanges();
        },
      });
    } else {
      //
      // Capture Mode ...
      options.push({
        id: 'enable_capture_mode',
        icon: XIconNames.crop,
        title: XResourceIDs.enable_capture_mode,
        color: XColor.Tertiary,
        slot: 'start',
        onlyIcon,
        handler: async () => {
          //
          this.enableCaptureMode = true;
          this.detectChanges();
        },
      });
    }

    //
    // Theme Manager ...
    options.push({
      id: 'theme_manager',
      icon: XIconNames.color_palette,
      title: AppResourceIDs.theme_manager,
      color: XColor.Tertiary,
      slot: 'start',
      onlyIcon,
      handler: async () => {
        await this.managerService.navigateByPageReplace(Pages.ThemeManager);
      },
    });

    //
    // Present Context Menu ...
    await this.popoverService.presentContextMenu(options, event);
  }

  async handleImageCaptured(image: string | Blob) {
    //
    if (image) {
      this.imageCaptured.emit(image);
    }

    //
    this.enableCaptureMode = false;
    this.detectChanges();
  }
  //#endregion

  //
  //#region Provided Actions ...
  //#endregion

  //
  //#region Private ...
  private async handleHasSideEffect() {
    //
    const hasSide = await this.getValueAsync(this.hasSide);
    if (!hasSide) {
      //
      this.toolbarHasMenu = false;
      this.toolbarShowMenu = false;
      this.toggleMenuWhen = '';
    }
  }

  private async handleChangeLocale() {
    //
    const currentLocale = this.managerService.currentLocale;
    const availableLanguages = this.config.availableLanguages.map((ai) => {
      return {
        name: ai.name,
        locale: ai.locale,
      };
    });
    if (!hasChild(availableLanguages)) {
      return;
    }

    //
    const localOptions: XPickerColumnOption[] = availableLanguages.map((al) => {
      //
      const op: XPickerColumnOption = {
        text: al.name,
        value: al.locale,
        disabled: al.locale === currentLocale,
      };

      //
      return op;
    });
    const localColumn: XPickerColumn = {
      name: 'locales',
      options: localOptions,
    };

    //
    await this.managerService.dialogService.presentPicker({
      buttons: [
        {
          text: XResourceIDs.ok,
          role: XModalButtonRole.Selected,
          cssClass: ['btn-selected'],
          handler: async (value) => {
            //
            const selectedLocale: XLocale = value?.locales?.value;
            if (!selectedLocale) {
              return;
            }

            //
            await this.managerService.settingsService.changeLocale(
              selectedLocale,
              true
            );
          },
        },
        {
          text: XResourceIDs.cancel,
          role: XModalButtonRole.Cancel,
          cssClass: ['btn-cancel'],
          handler: () => {},
        },
      ],
      columns: [localColumn],
    });
  }
  //#endregion
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\environments\environment.prod.ts

import { XConfig, xSharedConfig } from '../app/config/app-config';

export const environment = {
  production: true,
  configurations: {
    ...xSharedConfig,

    //
    isProd: true
  } as XConfig
};

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\environments\environment.ts

import { XConfig, xSharedConfig } from '../app/config/app-config';

export const environment = {
  production: false,
  configurations: {
    ...xSharedConfig,

    //
    isProd: false
  } as XConfig
};

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\src\theme\theme.scss

//
// XFramework Color Mechanism ...
:root {
  /** Primary **/
  --x-color-primary: #3880ff;
  --x-color-primary-shade: #3171e0;
  --x-color-primary-tint: #4c8dff;

  --x-color-primary-contrast: #ffffff;
  --x-color-primary-shade-contrast: #ffffff;
  --x-color-primary-tint-contrast: #ffffff;

  /** Secondary **/
  --x-color-secondary: #0cd1e8;
  --x-color-secondary-shade: #0bb8cc;
  --x-color-secondary-tint: #24d6ea;

  --x-color-secondary-contrast: #ffffff;
  --x-color-secondary-shade-contrast: #ffffff;
  --x-color-secondary-tint-contrast: #ffffff;

  /** Tertiary **/
  --x-color-tertiary: #7044ff;
  --x-color-tertiary-shade: #633ce0;
  --x-color-tertiary-tint: #7e57ff;

  --x-color-tertiary-contrast: #ffffff;
  --x-color-tertiary-shade-contrast: #ffffff;
  --x-color-tertiary-tint-contrast: #ffffff;

  /** Success **/
  --x-color-success: #10dc60;
  --x-color-success-shade: #0ec254;
  --x-color-success-tint: #28e070;

  --x-color-success-contrast: #ffffff;
  --x-color-success-shade-contrast: #ffffff;
  --x-color-success-tint-contrast: #ffffff;

  /** Warning **/
  --x-color-warning: #ffce00;
  --x-color-warning-shade: #e0b500;
  --x-color-warning-tint: #ffd31a;

  --x-color-warning-contrast: #ffffff;
  --x-color-warning-shade-contrast: #ffffff;
  --x-color-warning-tint-contrast: #ffffff;

  /** Danger **/
  --x-color-danger: #f04141;
  --x-color-danger-shade: #d33939;
  --x-color-danger-tint: #f25454;

  --x-color-danger-contrast: #ffffff;
  --x-color-danger-shade-contrast: #ffffff;
  --x-color-danger-tint-contrast: #ffffff;

  /** Dark **/
  --x-color-dark: #222428;
  --x-color-dark-shade: #1e2023;
  --x-color-dark-tint: #383a3e;

  --x-color-dark-contrast: #ffffff;
  --x-color-dark-shade-contrast: #ffffff;
  --x-color-dark-tint-contrast: #ffffff;

  /** Medium **/
  --x-color-medium: #989aa2;
  --x-color-medium-shade: #86888f;
  --x-color-medium-tint: #a2a4ab;

  --x-color-medium-contrast: #ffffff;
  --x-color-medium-shade-contrast: #ffffff;
  --x-color-medium-tint-contrast: #ffffff;

  /** Light **/
  --x-color-light: #f4f5f8;
  --x-color-light-shade: #d7d8da;
  --x-color-light-tint: #f5f6f9;

  --x-color-light-contrast: #000000;
  --x-color-light-shade-contrast: #000000;
  --x-color-light-tint-contrast: #000000;
}
/* Core CSS required for Ionic components to work properly */
@import '~@ionic/angular/css/core.css';

/* Basic CSS for apps built with Ionic */
@import '~@ionic/angular/css/normalize.css';
@import '~@ionic/angular/css/structure.css';
@import '~@ionic/angular/css/typography.css';
@import '~@ionic/angular/css/display.css';

/* Optional CSS utils that can be commented out */
@import '~@ionic/angular/css/padding.css';
@import '~@ionic/angular/css/float-elements.css';
@import '~@ionic/angular/css/text-alignment.css';
@import '~@ionic/angular/css/text-transformation.css';
@import '~@ionic/angular/css/flex-utils.css';

/* XFramework Theme */
@import '~x-framework-components/theme/theme.scss';

/* Override Default XFramework's Body Background Color */
body {
  background-color: #ffffff;
}

.code-block {
  direction: ltr;
  color: white;
  margin: {
    top: 6px;
    bottom: 8px;
  }
  // white-space: pre;
  word-spacing: normal;
  word-break: normal;
  background-color: black;

  //
  overflow: hidden;

  //
  .x-header {
    direction: var(--ui-direction) !important;
  }
}

//
//#region Card ..
$border-radius: 8px;

x-card.v-card,
.v-card > x-card {
  .x-title {
    margin-bottom: 8px;
    font-size: 16px !important;

    color: var(--x-color-primary-tint-contrast);
  }

  .x-sub-title {
    margin-bottom: 0;
    font-size: 12px !important;

    color: var(--x-color-primary-tint-contrast);
  }

  mat-card {
    border-top-left-radius: $border-radius;
    border-top-right-radius: $border-radius;
  }

  mat-card.mobile {
    .mat-card-header {
      border-top-left-radius: 0;
      border-top-right-radius: 0;
    }
  }

  mat-card-header {
    @include transition-duration();

    //
    background-color: var(--x-color-primary-tint);

    //
    border-top-left-radius: $border-radius;
    border-top-right-radius: $border-radius;
  }

  mat-card-header:hover {
    background-color: var(--x-color-primary-shade);
  }
}

x-card.v-card.v-no-margin-card,
.v-card.v-no-margin-card > x-card {
  mat-card-content {
    padding: 0 !important;
  }
}
//#endregion

.x-auto-complete-margin {
  margin-top: -1.34375em;
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xFrameworkTest\www\index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8"/>
    <title>XFramework App</title>

    <base href="./"/>

    <meta name="viewport" content="viewport-fit=cover, width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
    <meta name="format-detection" content="telephone=no"/>
    <meta name="msapplication-tap-highlight" content="no"/>

    <link rel="icon" type="image/png" href="assets/icon/favicon.png"/>

    <!-- add to homescreen for ios -->
    <meta name="apple-mobile-web-app-capable" content="yes"/>
    <meta name="apple-mobile-web-app-status-bar-style" content="black"/>

    <!-- For Clear Electron Insecure Content Error ... -->
    <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';">

    <link rel="manifest" href="manifest.webmanifest">
  <meta name="theme-color" content="#1976d2">
<link rel="stylesheet" href="styles.css"></head>

  <body>
    <app-root></app-root>
    <noscript>Please enable JavaScript to continue using this application.</noscript>
<script src="runtime.js" defer></script><script src="polyfills.js" defer></script><script src="vendor.js" defer></script><script src="main.js" defer></script></body>
</html>
