#   Getting Started

[![npm version](https://img.shields.io/npm/v/ul-lib)](https://www.npmjs.com/package/ul-lib)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
[![Angular 18+](https://img.shields.io/badge/Angular-18%2B-DD0031?logo=angular&logoColor=white)](https://angular.io/)
[![TailwindCSS 4.x](https://img.shields.io/badge/TailwindCSS-4.x-38B2AC?logo=tailwind-css&logoColor=white)](https://tailwindcss.com/)
[![DaisyUI 5.x](https://img.shields.io/badge/DaisyUI-5.x-5A0EF8)](https://daisyui.com/)

## Install

```bash
npm install ul-lib
```
[NPM Package](https://www.npmjs.com/package/ul-lib)

[UL-Lib Sandbox - StackBlitz](https://stackblitz.com/edit/stackblitz-starters-7i4nep?file=src%2Fapp%2Fapp.component.html)


## Build
Use the below script to build the CSS file and to build/pack npm package.
```
npm run buildPack
```

## Configure

### Tailwinds v4
Add this to the root css to load tailwind styles 
[Tailwind CSS Installation](https://tailwindcss.com/docs/installation/framework-guides/angular)
```css
@import "tailwindcss";
```

### Tailwindcss-Motion
Add tailwind motion for animations.
[TailwindCSS-Motion](https://www.npmjs.com/package/tailwindcss-motion/v/0.1.0)
``` css
@plugin "tailwindcss-motion";
```


### DaisyUI v5
Add Daisy UI plug-in
[DaisyUI Installation](https://v5.daisyui.com/docs/install/)
```css
@plugin "daisyui"{
    themes: light --default, dark --prefersdark, dracula; 
}
```


### UL-Lib CSS Import
Add import of css from ul-lib to css of a new app project.
```css
@import '../node_modules/ul-lib/index.css';
```


### Date Selector Config

In your project that was used to install this package update the `angular.json` in the styles property.

`Projects > architect > Build > Styles`

```json
{
            "styles": [
              "node_modules/flatpickr/dist/flatpickr.css"
              ]
}
```

# Modules

| Modules        | Components                                                                                                                                                                                 |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| ULAlertsModule | [UIAlertComponent,UIAlertsComponent]                                                                                                                                                       |
| ULCommonModule | [LocalDatePipe]                                                                                                                                                                            |
| ULInputsModule | [UIBasicInputFieldComponent,<br>    UIFormComponent]                                                                                                                                       |
| ULMenuModule   | [UIMenuComponent,<br>    UIMenuDetailComponent,<br>    UIMenuDropdownComponent,<br>    UIMenuItemComponent]                                                                                |
| ULModalModule  | [UIModalPopUpComponent,<br>    UIModalViewComponent]                                                                                                                                       |
| ULStatsModule  | [UIStatComponent,<br>    UIStatsComponent]                                                                                                                                                 |
| ULTableModule  | [UIBasicTableComponent,<br>    UIBasicTableColumnComponent,<br>    UINestedTableRowComponent, UIAdvancedFilterComponent, UIFilterItemComponent ]                                                                                              |
| ULTabsModule   | [UITabComponent,<br>    UITabViewComponent]                                                                                                                                                |
| ULViewsModule  | [UIAccordionComponent,<br>    UICardViewComponent,<br>    UIDividerComponent,<br>    UIBasicChipComponent,<br>    UINavBarComponent,<br>    UISidebarComponent,<br>    UITooltipComponent,<br>    UICalendarViewComponent,<br>    UICalendarCellComponent,<br>    UICalendarHeaderComponent] |

# Pipes

| Pipes         | Description                                                             | Selector    |
| ------------- | ----------------------------------------------------------------------- | ----------- |
| LocalDatePipe | Uses the native @Angular Date to convert UTC dates into local datetimes | 'localDate' |

# UL Components  

Overview of the functionality that is available in the UL package.
UITable

|Component|Selector|
|---|---|
|UIBasicTableComponent|`ul-table`|

## Parameters

| Parameters     | Data Type                                                   | Type   | Description                                                                                                                                | Optional |
| -------------- | ----------------------------------------------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------ | -------- |
| dataSource     | Function (SearchRequest) => any[] \| Observable<any[]>      | @Input | Source data for table                                                                                                                      |          |
| searchRequest  | SearchRequest                                               | @Input | Object to used when sending request to update source after sort/filtering.                                                                 | ✅        |
| headerClass    | String = 'bg-base-300'                                      | @Input |                                                                                                                                            | ✅        |
| rowClass       | String = 'drop-shadow-none shadow-none'                     | @Input |                                                                                                                                            | ✅        |
| footerClass    | String = ''                                                 | @Input |                                                                                                                                            | ✅        |
| refreshTrigger | `Observable<any>`                                           | @Input | Used to to trigger and return signalR response. This can also be set in the datasource as well.                                            | ✅        |
| triggerHandle  | `(source: any, tableSource:BehaviorSubject<any[]>) => void` | @Input | Used to update the table before the refresh is fully complete to create seamless row updates. You can also include this in the datasource. | ✅        |
| trackBy        | (row:any) => any                                            | @Input | Optionally can be used to indicate a row identity for the table when rendering                                                             | ✅        |

## Concepts

As mentioned you can include the following the in the Datasource row for the datasource of the table. Also I found the best way to include child or nestedRow data is to include the Observables in the datasource row as well.

|Input Name|Row Property Name|
|---|---|
|triggerHandle|$trigger|
|refreshTrigger|$refresh|

### Example

This example will include an Child data and refresh/trigger handling. The example should include filtering and sorting using the searchRequest object.

```typescript
export class ExampleComponent
{
  $exampleSource: (sr: SearchRequest) => Observable<SearchResponse<any>>;

  constructor(private exampleService:ServiceExample  private updateStores: UpdateStoreMap)
  {
    //Example Table Source
    this.$exampleSource = (sr) => this.exampleService.GetA(sr).ToPageObservable().EditResult(x => {
        x.$SubSource1 = this.traceJobService.GetB(x.Id); //Returns on Observable given an individual row
        x.$SubSource2 = this.traceJobService.Getc(x.Id); //Returns on Observable given an individual row
        x.$refresh = this.updateStores.getStores("ATableUpdate", "BTableUpdate"); //This comes from SignalR
        x.$trigger = (updateSource:any, tableSource:BehaviorSubject<any[]>) => {
          var ATable = source?.ATableUpdate;
          var currentData = tableSource.getValue();   
          //Use currentData and updateSource to perform your updates
          tableSource.next(currentData);
        }
        return x;
      });
  }
}

```

> ### Warning
> 
> If you use signalR for the auto-refresh and have a nestedRow then you would need to use the UIColumn @Input Parameter `isRowID` (or use the UITable @Input `trackBy` ) because typically the way a row is indicated as open is from the entire Row dataobject matching the row that is being built upon re-rendering. You can set the unique row ID using the `isRowID` or `trackBy` delegate and instead of checking the whole row it will compare both the Re-Render row and selected row using the delegate.

```json
{
"RowId": 123,
"Column1": "Value 1",
"Column2": "Value 2",
"Column3": "Value 3"
}
```

**Option A**
```typescript
  tableGetId(r:any)
  {
    return r?.RowId;
  }
```
---
**Option B**
```html 
    <ul-table #tbl class="border-collapse" [dataSource]="$exampleSource" >        
    <ul-column isRowId dataKey="RowId" display="Row ID" />
        <!--...-->
        </ul-table>
```
---

```typescript
//This is example of how I decided to store the update observables from SignalR. 
export class UpdateStoreMap
{
  $stores: Map<string, BehaviorSubject< unknown>> = new Map<string, BehaviorSubject< unknown>>();

  updateStore(groupName: string, values: unknown)
  {
    var isIncluded = this.$stores.has(groupName);
    if (!isIncluded) {
      this.$stores.set(groupName, new BehaviorSubject(values));
    } else {

      this.$stores.get(groupName).next(values);
    }
  }

  getStore(groupName:string):BehaviorSubject<unknown> |undefined
  {
    return this.$stores.get(groupName) ?? undefined;
  }

  getStores(...groupNames: string[])
  {
    //Create a selection object of target observables to check if any of the selected changes
    //it then converts the output into a object using the groupName as the key and changed rows as the values
    /*Example:groupdNames = ['SourceA', 'SourceB']
    {
      SourceA: [],
      SourceB: []
    }
    */ 
    var val = groupNames.map(x => this.getStore(x)).filter(x => x != undefined);
    return combineLatest(val).pipe(map((m: any[]) => {
      var newMap: Map<string, any> = new Map<string, any>();
      
      m.forEach((v, i) => {

        newMap.set(groupNames[i], v);

      });

      return Object.fromEntries(newMap);
    }));
  }
}
```
### Observable Pipes
#### Set Refresh/Trigger
``` typescript
//This example uses the SignalR UpdateStoreMap
export class ExampleComponent {

  constructor(private sourceService: SourceService, private updateStores: UpdateStoreMap)
  {
  var source = this.sourceService.get()
  .pipe(setRefresh(this.updateStores.getStores('Update1', 'Update2'))) 
  .pipe(setTrigger<{ Update1: any, Update2: any }, any>
      ((source, table) => source.Update2?.ColumnA == table.ColumnA, 'Update2'));
  }
}
```




## Children Components

### UIColumn

|Component|Selector|
|---|---|
|UIBasicTableColumnComponent|`ul-column`|

#### Parameters

| Parameters | Data Type | Type   | Description                                                                                                                                                   | Optional |
| ---------- | --------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| sortable   | Boolean   | @Input | Is column sortable                                                                                                                                            | ✅        |
| display    | String    | @Input | Sets the column display text                                                                                                                                  | ✅        |
| dataKey    | String    | @Input | Used to get the Property value from the Objects array based on the property key (i.e. dataKey).                                                               |          |
| isFilter   | Boolean   | @Input | Sets if column is filterable                                                                                                                                  | ✅        |
| isRowID    | String    | @Input | Determines if a dataKey designates this row's rowID. The selected row for the table uses this determine if a row is selected even after a datasource refresh. | ✅        |

### UINestedTableRow

|Component|Selector|
|---|---|
|UINestedTableRowComponent|`ul-nestedRow`|

#### Parameters

|Parameters|Data Type|Type|Description|Optional|
|---|---|---|---|---|
|class|String|@Input()|Set class on NestedRow component.|✅|

#### Example

```html
  <ul-nestedRow>
    <ng-template let-row>
      <div class="grid grid-cols-2 gap-2">
        <span>{{row.display}}</span>
        <span>{{row.id}}</span>
      </div>
      </ng-template>
  </ul-nestedRow>
```

## Dependent Entities
### ULRow (Optional)
Used to aide in building/customizing the row element when building table. This is a directive and can be applied to the UIBasicTablecomponent by adding the element to the `ul-table` tag.
- For now this only applies to the dataRow. (No column row, header row and Nested is handled in its own component)
- No Parameters


| Directive           | Selector | Context                | Parent                           |
| ------------------- | -------- | ---------------------- | -------------------------------- |
| UlTableRowDirective | `ul-row` | `TableCacheContext<T>` | UIBasicTableComponent (ul-table) |

#### Model
```typescript
export interface TableCacheContext<T>
{
  $implicit: T;
  $index: number;
  selectedExpandRow?: T;
  rowSelected: boolean;
  rowTriggered:boolean;
  nestedComponent: UINestedTableRowComponent | undefined;
  columns: UIColumnHandler[];
  cell?:UIColumnHandler ;
  isDataRow:boolean;
}

export interface TableRenderCache<T>
{
  dataRow: EmbeddedViewRef<TableCacheContext<T>> | undefined;
  nestedRow: EmbeddedViewRef<TableCacheContext<T>> | undefined;
  context: TableCacheContext<T>;
}
```

#### Example
```html
    <ul-table #tbl class="border-collapse" [dataSource]="countryData" nestedClickEnabled>        

<tr *ul-row="let row;"
class="bg-slate-500"></tr>
        <!--...-->
        </ul-table>
```

> # Information
> This should render in real time anytime there is a change and not conflict with changing data as long as you use the trackBy functionality.

### ULHeaderCell
Used to aide in building the Header cell for each of the columns. This is optional as well and if not set then the default will be used.


| Directive             | Selector                     | Context                                                                                        | Parent                           |
| --------------------- | ---------------------------- | ---------------------------------------------------------------------------------------------- | -------------------------------- |
| ULHeaderCellDirective | `th[ul-header], [ul-header]` | { "$implicit": "Columns from the TableComponent", "Sort": "Saved Sort object for the table"  } | UIBasicTableComponent (ul-table) |

#### Example
```html
<ul-table #tbl [dataSource]="$source" >
<!--...-->
          <th *ul-header="let column;let sort='Sort';"> <!-- Context -->
            <div class="flex container group hover:text-red-400"> 
              <button (click)="tbl.SortClicked(column.DataKey)"> <!-- This is how to trigger the table sort from the header definition -->
                <span> {{column.Display}}  </span> <!-- Output header display name-->
                <!--Up Arrow-->
                <i class="fa fa-long-arrow-up "
                   [class.invisible]="!column.Sortable || (sort?.active != column.DataKey) || (sort?.direction ?? '') == 'desc' || (sort?.direction ?? '') == ''"
                   [class.group-hover:visible]="column.Sortable && ((sort?.direction ?? '') == ''  || (sort?.direction == 'desc' && column.DataKey == sort?.active))"
                   style="padding-right: 1px;" aria-hidden="true"></i>
                <!--Down Arrow-->
                <i class="fa fa-long-arrow-down"
                   [class.invisible]="!column.Sortable || (sort?.active != column.DataKey ) || sort?.direction == 'asc'  || (sort?.direction ?? '') == '' "
                   [class.group-hover:visible]="column.Sortable && (sort?.direction == 'asc' && column.DataKey == sort?.active)"
                   aria-hidden="true"></i>
                   <!-- The conditional for the classes should be universal so feel free to use your own icons or design for sort client-display -->
              </button>
            </div>
          </th>
</ul-table>
```


### UIFilter 

Automatically included in the UITable.

| Component              | Selector          |
| ---------------------- | ----------------- |
| UIBasicFilterComponent | `ul-basic-filter` |

#### Parameters

| Parameters      | Data Type                          | Type      | Description                                                                         | Optional |
| --------------- | ---------------------------------- | --------- | ----------------------------------------------------------------------------------- | -------- |
| SelectedFilters | `EventEmitter<ListItem<string>[]>` | @Output() | Outputs a dataKey and filter pairing determining which data Key should be filtered. | ✅        |

## Example

```html
<ul-table [dataSource]="services.magicWand['CompanyLocationsService'].getAllCompanyLocationTypes()">
  <ul-column  dataKey="id" display="ID">
    <!--You can leave the template empty if the result should be just text -->
    <!--  The logic uses the dataKey value and applies it like so:
    <ng-template #noData let-row let-cell="cell">
    <span>{{row[cell.DataKey]}}</span>
    </ng-template>
      -->
  </ul-column>
  <ul-column dataKey="display" display="Display">
    <ng-template let-row>
      <span>{{row.display}}</span>
    </ng-template>
  </ul-column>  

  <ul-nestedRow>
    <ng-template let-row>
      <div class="grid grid-cols-2 gap-2">
        <span>{{row.display}}</span>
        <span>{{row.id}}</span>
      </div>
      </ng-template>
  </ul-nestedRow>  

</ul-table>

  

```
#  UIModal  
This component comes with a button and is meant for an inline implementation of the UIModal.

| Component            | Selector   |
| -------------------- | ---------- |
| UIModalViewComponent | `ul-modal` |

##  Parameters

| Parameters  | Data Type | Type   | Description                               | Optional |
| ----------- | --------- | ------ | ----------------------------------------- | -------- |
| buttonText  | String    | @Input | Sets the text for the inline button.      |          |
| buttonClass | String    | @Input | Sets class for button in the UIModal      | ✅        |
| modalClass  | String    | @Input | Set the class on the modal dialog element | ✅        |
| contentClass  | String    | @Input | Set the class on the modal-box element | ✅        |
| iconClass  | String    | @Input | Displays and sets icon for button that opens modal. | ✅        |
| Close()  | method    | Property | Displays and sets icon for button that opens modal. |        |

## Content Projection

```html
<!-- ... -->
 <dialog #Modal1 class="modal overflow-y-auto" [ngClass]="modalClass">
    <div class="modal-box max-w-fit" [ngClass]="contentClass">
        <ng-content></ng-content> <!-- no tag acts as default -->
        <div class="modal-action">
            <form method="dialog">
                  <button class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2">✕</button>
                <ng-content select="[actions]"></ng-content> <!-- actions tag -->
            </form>
        </div>
    </div>
</dialog>
```
##  Example  



```html
                <ul-modal buttonText="Open Popup">
                    <div> <!-- no tag acts as default -->
                        <span>TEST Popup</span>
                    </div>
                    <div actions class="grid grid-cols-2 gap-2"> <!-- actions tag -->                        <button class="btn btn-primary">Test button 1</button>
                        <button class="btn btn-primary">Test button 2</button>
                    </div>
                </ul-modal>
```
#  UITabView

| Component          | Selector  |
| ------------------ | --------- |
| UITabViewComponent | `ul-tabs` |

##  Parameters

| Parameters | Data Type | Type   | Description                                                        | Optional |
| ---------- | --------- | ------ | ------------------------------------------------------------------ | -------- |
| name       | String="" | @Input | Sets the tabnameindex inside each tab inside of the tabs component | ✅        |


##  Content Projection
```html
<div role="tablist" class="tabs tabs-boxed" [ngClass]="class">
  <ng-content></ng-content> <!--Nested Content-->
  </div>
```
##  Child Components
##  UITab
| Component      | Selector |
| -------------- | -------- |
| UITabComponent | `ul-tab` |

###  Parameters

| Parameters   | Data Type          | Type   | Description                                                                                          | Optional |
| ------------ | ------------------ | ------ | ---------------------------------------------------------------------------------------------------- | -------- |
| tabLabel     | String=""          | @Input | Sets the text on the button for this tab.                                                            | ✅        |
| tabSelected  | Boolean=False      | @Input | Sets whether or not the tab is pre-selected                                                          | ✅        |
| tabNameIndex | String="my_tabs_1" | @Input | Sets the tab so that only 1 tab that has the same NameIndex can be opened at any given point in time | ✅        |
| tabClass     | String             | @Input | Sets the class for the tab pane                                                                      | ✅        |

### Content Projection

```html
<input #checkbox type="radio" [name]="tabNameIndex" role="tab" class="tab" [attr.aria-label]="tabLabel"  /><div role="tabpanel" class="tab-content p-10"><ng-content></ng-content></div>
```
### Example
```html

        <ul-tabs class="w-full">
            <ul-tab tabLabel="Label 1" tabNameIndex="tab_1" [tabSelected]="true" >
                <div class="grid grid-cols-2">
                    <ul-input contentType="input" label="Input 1" ></ul-input>
                    <button class="btn btn-accent w-24"> Done </button>
                </div>
            </ul-tab>

            <ul-tab tabLabel="Label 2" tabNameIndex="tab_1"  >
                <div class="grid grid-cols-2">
                    <ul-input contentType="input" label="Input 2" defaultValue="Set Default" ></ul-input>
                </div>
            </ul-tab>

        </ul-tabs>
```
#  UIMenu  
| Component       | Selector  |
| --------------- | --------- |
| UIMenuComponent | `ul-menu` |

##  Parameters

| Parameters | Data Type | Type   | Description                 | Optional |
| ---------- | --------- | ------ | --------------------------- | -------- |
| class      | String    | @Input | Sets the class for the Menu | ✅        |

##  Example  

```html
        <ul-menu class="w-48 menu"> <!-- This is set on the component level but angular is kind of stupid -->
            <ul-menuItem  label="test"></ul-menuItem>
            <ul-menuItem  label="test 1" >
                <ul-menuDetail summary="test">
                    <ul-menuItem  label="inner test"></ul-menuItem>
                    <ul-menuItem  label="inner test 1"></ul-menuItem>
                    <ul-menuItem  label="inner test 1"></ul-menuItem>
                  </ul-menuDetail>
            </ul-menuItem>
            <ul-menuItem  label="test 2" (action)="print('Hello World')"></ul-menuItem>            
          </ul-menu>
```

*  *You may need to add the class 'menu' to ul-menu. I had 1 project where it was necessary and another where it was not. The class should be preset but even after that issue might persist and is why I left this note. This is due to multiple style sheets and different rendering in different components depending on how its built. Basically there's difference between setting menu on a package level and target project level. 😓*
##  Children Components
###  UIMenuItem

| Component           | Selector      |
| ------------------- | ------------- |
| UIMenuItemComponent | `ul-menuItem` |

#### Parameters

| Parameters | Data Type           | Type    | Description          | Required |
| ---------- | ------------------- | ------- | -------------------- | -------- |
| label      | String              | @Input  | Menu option text     |          |
| click      | `EventEmitter<any>` | @Output | Handles click action |          |

#### Example
```html
<ul-menuItem label="inner test"></ul-menuItem>
```
#### Children Components
#####  UIMenuDetails
Also the UI MenuItem can be inserted into MenuDetails

| Component             | Selector        |
| --------------------- | --------------- |
| UIMenuDetailComponent | `ul-menuDetail` |

###### Parameters 

| Parameters | Data Type | Type   | Description                 | Required |
| ---------- | --------- | ------ | --------------------------- | -------- |
| summary    | String    | @Input | Name of folder for dropdown |          |

###### Example
```html
                <ul-menuDetail summary="test">
                    <ul-menuItem  label="inner test"></ul-menuItem>
                    <ul-menuItem  label="inner test 1"></ul-menuItem>
                    <ul-menuItem  label="inner test 1"></ul-menuItem>
                  </ul-menuDetail>
```
#  UIMenuDropdown
The main difference between this and UIMenu is that this UI object starts as a button and to open the menu you must click the button. On the other hand UIMenu renders as collapsed but visible.

| Component               | Selector          |
| ----------------------- | ----------------- |
| UIMenuDropdownComponent | `ul-menuDropdown` |

##  Parameters


| Parameters  | Data Type | Type   | Description                                                            | Required |
| ----------- | --------- | ------ | ---------------------------------------------------------------------- | -------- |
| class       | String    | @Input | Class for dropdown                                                     |          |
| buttonText  | String    | @Input | Sets the text for the inline button that is rendered with the dropdown |          |
| buttonClass | String    | @Input | Sets the class for the button that opens this dropdown.                |          |

##  Children Components
Uses the same child components from UIMenu.
*  `UIMenuItem`
*  `UIMenuDetails`  
##  Example
```html
  <ul-menuDropdown class="w-48" buttonText="test">
            <ul-menuItem  label="test"></ul-menuItem>
            <ul-menuItem  label="test 1" >
                <ul-menuDetail summary="test">
                    <ul-menuItem  label="inner test"></ul-menuItem>
                    <ul-menuItem  label="inner test 1"></ul-menuItem>
                    <ul-menuItem  label="inner test 1"></ul-menuItem>
                  </ul-menuDetail>
            </ul-menuItem>
            <ul-menuItem  label="test 2" (click)="print('Hello World')"></ul-menuItem>    
  </ul-menuDropdown>
```
#  UICardView

| Component           | Selector  |
| ------------------- | --------- |
| UICardViewComponent | `ul-card` |

##  Parameters

| Parameters | Data Type | Type   | Description                                  | Required |
| ---------- | --------- | ------ | -------------------------------------------- | -------- |
| header     | String="" | @Input | Sets a title text for the UICard             |          |
| content    | String="" | @Input | Sets the span as content to insert text body |          |
| cardClass  | String="" | @Input | Set the class for the UICard                 |          |

## Content Projection
```html
<div class="card shadow-xl">
    <div class="card-body">
        <h2 class="card-title">{{header}}</h2>
        <p>{{content}}</p>
        <ng-content ></ng-content> <!-- Default content location -->
        <div class="card-actions justify-end flex flex-row">
            <ng-content select="[actions]"></ng-content> <!-- Must include actions tag -->
        </div>
    </div>
</div>
```
##  Example 
```html
  <ul-card header="Header Text" content="Lorem Ipsum">
    <div>
      </div>
      <div actions>
    <button class="btn btn-accent"> Test </button>
      </div>
  </ul-card>
```  

#  UIDetailView

| Component             | Selector    |
| --------------------- | ----------- |
| UIDetailViewComponent | `ul-detail` |

##  Parameters

| Parameters  | Data Type            | Type   | Description                             | Required | Options                                                                        |
| ----------- | -------------------- | ------ | --------------------------------------- | -------- | ------------------------------------------------------------------------------ |
| placement   | String               | @Input | Sets the placement of the grid class    |          | "stretch" \| "evenly" \| "around" \| "between" \| "end" \| "start" \| "center" |
| columnCount | Number               | @Input | Set the grid class column count         |          |                                                                                |
| class       | String               | @Input | Sets other classes to the Grid element  |          |                                                                                |
| gap         | Number               | @Input | Sets gap for grid class                 |          |                                                                                |
| details     | `ListItem<string>[]` | @Input | Sets the data for cells in detail view. |          |                                                                                |

##  InitLogic
[Link to Tailwinds Logic](https://tailwindcss.com/docs/place-content)
```typescript
  var ConcatedClass:string = ' grid-cols-' + this.columnCount + ' gap-'+ this.gap + ' place-content-' + this.placement;
  this.class = this.class + ConcatedClass;
```
##  Example
```typescript
  private exDetails: ListItem<string>[] = [
    new ListItem("Test1", "Value1"),
    new ListItem("Test2", "Value2"),
    new ListItem("Test3", "Value3"),
    new ListItem("Test4", "Value4")
  ];
```

```html
    <ul-detail [details]="exDetails" columnCount="2" gap="4" placement="center">
    </ul-detail>
```
#  UIInputField

| Component                  | Selector   |
| -------------------------- | ---------- |
| UIBasicInputFieldComponent | `ul-input` |

##  Parameters

| Parameters    | Data Type                                                | Type    | Description                                                                                                                                                                                           | Required                       | Options                                                                                                                                |
| ------------- | -------------------------------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------- |
| label         | String                                                   | @Input  | Sets the label for the Input form                                                                                                                                                                     |                                |                                                                                                                                        |
| contentType   | String="input"                                           | @Input  | Sets the content type when loading Input box                                                                                                                                                          | ✅                              | "input" \| "select" \| "textarea" \| "radio" \| "toggle" \| "checkbox" \| "file" \| "autocomplete"                                     |
| inputType     | String="text"                                            | @Input  | Sets the input type for loading the input box. Typically for content type 'input'.                                                                                                                    |                                | "color" \| "email" \| "date" \|  "month" \| "number" \| "password" \| "search" \| "tel" \| "text" \| "url" \| "week" \| "autocomplete" |
| dateMode      | String="single"                                          | @Input  | Sets date input mode                                                                                                                                                                                  |                                | 'multiple' \| 'range'                                                                                                                  |
| dateOptions   | FlatpickrDefaultsInterface=new FlatpickrDefaults()       | @Input  | Sets other date options                                                                                                                                                                               |                                | [Options - flatpickr](https://flatpickr.js.org/options/)                                                                               |
| datasource    | `ListItem<string>[] = []`                                | @Input  | Sets datasource for Select, Autocomplete and Radio                                                                                                                                                    | ✅ (If autoComplete is not set) |                                                                                                                                        |
| dataDefault   | `ListItem<string>`                                       | @Input  | Sets the dataDefault for select                                                                                                                                                                       | ✅                              |                                                                                                                                        |
| defaultValue  | Any=""                                                   | @Input  | Sets the default value for any UIInput                                                                                                                                                                |                                |                                                                                                                                        |
| class         | String                                                   | @Input  | Sets class for Input element or actionable element                                                                                                                                                    |                                |                                                                                                                                        |
| formClass     | String                                                   | @Input  | Sets the class for the parent div of the input element and label element                                                                                                                              |                                |                                                                                                                                        |
| labelClass    | String                                                   | @Input  | Sets label class                                                                                                                                                                                      |                                |                                                                                                                                        |
| iconClass     | String                                                   | @Input  | Sets Icon class                                                                                                                                                                                       |                                |                                                                                                                                        |
| tooltip       | String                                                   | @Input  | When a user hovers over the input it displays a tooltip pop-up                                                                                                                                        |                                |                                                                                                                                        |
| tipClass      | String                                                   | @Input  | Sets class for tooltip (Direction/Color)                                                                                                                                                              |                                |                                                                                                                                        |
| placeholder   | String                                                   | @Input  | Sets placeholder text for input boxes (Limited to text-based inputs)                                                                                                                                  |                                |                                                                                                                                        |
| disabled      | Boolean                                                  | @Input  | Disables user input for the input box                                                                                                                                                                 |                                |                                                                                                                                        |
| required      | Boolean                                                  | @Input  | This is more to save whether or not an input is required no UI changes occur                                                                                                                          |                                |                                                                                                                                        |
| fieldID       | String                                                   | @Input  | Only needed for radio inputs. Sets the name for the radio. Groups with the same name can only have one enabled radio                                                                                  | ✅(Radio)                       |                                                                                                                                        |
| rowIndex      | Number                                                   | @Input  | Can be used to set an index for duplicate inputs and possibly integrate with UINestedRow                                                                                                              |                                |                                                                                                                                        |
| dataKey       | String                                                   | @Input  | Can be used to locate the target input box in UIFormComponent                                                                                                                                         |                                |                                                                                                                                        |
| Change        | `EventEmitter<any>`                                      | @Output | Can extract data from input box from this event for (All Inputs)                                                                                                                                      |                                |                                                                                                                                        |
| alt           | String                                                   | @Input  | Anything that is not undefined for this attribute will trigger an alternate input design.                                                                                                             |                                |                                                                                                                                        |
| dropdownClass | String                                                   | @Input  | Specifically for the Autocomplete dropdown class                                                                                                                                                      |                                |                                                                                                                                        |
| autoComplete  | `(inputValue?:string) => Observable<ListItem<string>[]>` | @Input  | Used to dynamically set the autocomplete selection list based on current autocomplete value. Any input value change triggers this function to return a new list. (The observable should auto destroy) | ✅ (If datasource is not set)   |                                                                                                                                        |
| validators    | ValidatorFn[]?                                           | @Input  | Set validators for the input based on output form value. Use method `Validate()` to trigger validation check.                                                                                         |                                |                                                                                                                                        |
| isReactive    | string?                                                  | @Input  | Sets if the input should auto-resize base on screen size                                                                                                                                              |                                |                                                                                                                                        |
| maxlength     | string                                                   | @Input  | Adds to validation of form. Triggers invalid if value char count is above the maxlength                                                                                                               |                                |                                                                                                                                        |
| minlength     | string                                                   | @Input  | Adds to validation of form. Triggers invalid if value char count is above the minlength                                                                                                               |                                |                                                                                                                                        |
| pattern       | string                                                   | @Input  | Sets regex to verify from the inputs value.                                                                                                                                                           |                                |                                                                                                                                        |
| title         | string                                                   | @Input  | Sets title for input element (Hover hint pops-up)                                                                                                                                                     |                                |                                                                                                                                        |

##  Logic 

###  GetValue
Can be used to get value from component no matter the type just from one function.  

``` typescript
  public GetValue(): string | undefined {
      if (this.contentType == "select") {
      return String(this.SelectElement.nativeElement.value);
    } else if (this.contentType == "input") {
      return String(this.InputElement.nativeElement.value);
    }else if (this.contentType == "radio"){
      var selectedItems = this.RadioElement.filter(x => x.nativeElement.checked == 'checked');
      return selectedItems.length > 0 ? selectedItems[0].nativeElement.value: undefined;
    }else if (this.contentType == "checkbox"){
      var selectedItem:string = this.CheckboxElement.nativeElement.checked;
      return selectedItem;
    }else if(this.contentType == 'multiSelect')
    {
      return JSON.stringify( this.multiItem.filter(x => (x.nativeElement.firstChild?.lastChild as HTMLInputElement).checked ).map(x => x.nativeElement.ariaValueText));
    }
    else{
      return undefined;
    }  
  }
```

```typescript
  public SetValue(value:any|undefined){
    if (this.contentType == "select") {
      this.SelectElement.nativeElement.value = value ?? this.defaultValue;
    } else if (this.contentType == "input") {
       this.InputElement.nativeElement.value = value ?? this.defaultValue;
    }else if (this.contentType == "radio"){
      var selectedItems = this.RadioElement.filter(x => x.nativeElement.checked == 'checked');
      selectedItems.forEach(x => {
        x.nativeElement.checked = value ?? this.defaultValue;
      });
    }else if (this.contentType == "checkbox"){
      this.CheckboxElement.nativeElement.checked = value ?? this.defaultValue;
    }else if (this.contentType == "multiSelect"){
      this.multiItem.forEach(x => {
        var foundDefault = this.multiSelectData?.find(defaults =>  defaults.nativeElement.value == x.nativeElement.ariaValueText);
        var targetCheck = (x.nativeElement.firstChild?.lastChild as HTMLInputElement);
        if (foundDefault != undefined)
        {
        targetCheck.checked = foundDefault?.nativeElement.checked
        }
      });
    }
  }
```

##  Example  
```html
  <div class="m-2 grid grid-cols-2 gap-2">
<!-- Dates -->
    <ul-input label="Start Date" contentType="input" inputType="date" class="w-64"></ul-input>
    <ul-input label="End Date" contentType="input" inputType="date" class="w-64"></ul-input>
<!-- Inputs  -->
    <ul-input label="Color" contentType="input" inputType="color" class="w-48" iconClass="fa fa-eyedropper mr-1"></ul-input>
    <ul-input label="Email" minlength contentType="input" inputType="email" class="w-48" placeholder="Enter Email" iconClass="fa fa-envelope mr-1">
<p hint class="validator-hint hidden"> 
<!-- This is how the hint is defined. I might change this to a directive instead -->
Test Error Hint
</p>

</ul-input>
<!-- Select -->
    <ul-input label="Example Select" contentType="select" [datasource]="exList" class="w-48 text-white" iconClass="fa fa-filter mr-2" labelClass="text-white"></ul-input>
<!-- Radio -->
    <ul-input contentType="radio" [datasource]="exDetails" formClass="grid grid-cols-4 gap-2 w-fit"></ul-input>
<!-- Toggle -->
    <ul-input contentType="toggle" label="Test switch" iconClass="fa fa-moon mr-1"></ul-input>
<!-- Checkbox -->
    <ul-input contentType="checkbox" label="Test checkbox"></ul-input>
<!-- Autocomplete -->
                    <ul-input contentType="autocomplete" label="Search" [autoComplete]="autocompleteList"
                        iconClass="fa fa-search mr-1" 
                        tooltip="Test"  
                        tipClass="tooltip-primary tooltip-top" dropdownRelative alt ></ul-input>  

                        <!-- Multi-Select -->
                        <ul-input  contentType="multiSelect" hint="test" (Change)="print($event)" tooltip="Test" label="Test" formClass="m-2">
    <input #listItem class="checkbox-error" name="Test 1" value="1"  >
    <input #listItem class="checkbox-error"  name="Test 2" value="2" checked >
    <input #listItem class="checkbox-error" name="Test 3" value="3"  >
    <input #listItem class="checkbox-error" name="Test 4" value="4"  >
    <input #listItem class="checkbox-error" name="Test 5" value="5"  >
    <input #listItem class="checkbox-error" name="Test 6" value="6"  >
</ul-input>
  </div>
```
#  UIBasicChip

| Component            | Selector  |
| -------------------- | --------- |
| UIBasicChipComponent | `ul-chip` |

##  Parameters

| Parameters | Data Type              | Type    | Description                    | Required |
| ---------- | ---------------------- | ------- | ------------------------------ | -------- |
| click      | `EventEmitter<string>` | @Output | Gets the label of clicked chip |          |
| class      | String                 | @Input  | Chip class                     |          |
| label      | String                 | @Input  | Chip text                      |          |
| value      | String                 | @Input  | Sets hidden value for chip     |          |

##  Example
So far this is only used in filter component
```html
    <div class="flex flex-row items-center basis-1/2 mt-2 ml-1">
       @if (ChipList.length > 0) { 
       <span class="text-ghost text-sm "> Delete Filters: </span>
       }
        @for (item of ChipList; track $index)
        {
        <ul-chip [label]="item.Key + ': \'' + item.Value! + '\''" [value]="item.Value!" class="badge-sm" (click)="ChipDeleteClick(item.Value!)"></ul-chip>
        }
    </div>
```
#  UIAlerts
I considered making this component something that is built with in a context of a component and therefore can be used in multiple components. The problem is that may cause the pop-ups to overlap. So its better to me to have one HTML Definition that connects to a static source of alerts.

| Component         | Selector    |
| ----------------- | ----------- |
| UIAlertsComponent | `ul-alerts` |

##  Parameters
  

| Parameters | Data Type | Type   | Description                                                                                  | Required |
| ---------- | --------- | ------ | -------------------------------------------------------------------------------------------- | -------- |
| allAlerts  | Any[]     | @Input | Automatically gets the saved alerts from static store but can be overwritten with this input |          |

## Variables

*  static SavedAlerts:any[] `Contains the saved alerts that were created`
##  Logic
**Automatically DESTROYS the alert after 10s**  

```typescript
public static AddAlert(headerString:string,textString:string, classString:string, timeSecs:number = 7, showAlertBool:boolean=true,buttonList:UIButton[] = [] )
```

```typescript
public static ClearAlerts()
```
##  Example
```html
<ul-alerts [allAlerts]="getAlerts()"> <!-- Setting the allalerts parameter should no longer be needed -->
</ul-alerts>
```

```typescript
  AlertEvent(x:any) {
    UIAlertsComponent.AddAlert("Test Header", "test text 3", "alert-error", 20, true, [
      new UIButton("Button1", "", null)
    ]);
  }
```

##  Service
###  AlertService
Automatically adds the AlertsComponent (NOT Alert) if it hasn't been initialized. Once initialized like below then it can be accessed by any child components from the static instance: UIAlertsComponent
###  Example  

```typescript
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrl: './app.component.scss',
  providers:[AlertsService]
})
export class AppComponent {
  title = 'UITools_Test';
  constructor(public vcr:ViewContainerRef, public thisAlerts: AlertsService)  {
  }
}
```
##  Dependent Components
###  UIAlert
####  Parameters
These are the same parameters used in UIAlerts > allAlerts.


| Parameters | Data Type | Type   | Description                       | Required |
| ---------- | --------- | ------ | --------------------------------- | -------- |
| header     | String    | @Input | Sets Header for alert             |          |
| text       | String    | @Input | Set alert body                    |          |
| class      | String    | @Input | Sets alert class                  |          |
| showAlert  | Boolean   | @Input | Determines if alert should render |          |
| buttons    | UIButton  | @Input | Adds buttons to the alert         |          |
| timeSeconds    | number  | @Input | Seconds that the alert shows on screen for         |          |


#  UIAccordion
Ng-Content enabled. Content of inner tags gets passed through to the accordion content.  
  
| Component            | Selector       |
| -------------------- | -------------- |
| UIAccordionComponent | `ul-accordion` |

##  Parameters


| Parameters | Data Type               | Type    | Description                                                           | Required | Options               |
| ---------- | ----------------------- | ------- | --------------------------------------------------------------------- | -------- | --------------------- |
| label      | String                  | @Input  | Sets pre-opened accordion text                                        |          |                       |
| isOpened   | Boolean                 | @Input  | Sets rather or not the accordion renders pre-opened                   |          |                       |
| name       | String                  | @Input  | Sets accordion name                                                   |          |                       |
| type       | String                  | @Input  | Sets rather accordion can be multi-select or single-select (By name). |          | "radio" \| "checkbox" |
| selected   | `EventEmitter<Boolean>` | @Output | Used to acquire if a accordion is selected upon clicking              |          |                       |

##  Example
```html
    <ul-accordion label="Test 1" name="1">
      <span>Content 1</span>
    </ul-accordion>  

    <ul-accordion label="Test 2" name="1">
      <span>Content 2</span>
    </ul-accordion>
```

# UIStats

  
| Component        | Selector   |
| ---------------- | ---------- |
| UIStatsComponent | `ul-stats` |

## Parameters 

| Parameters | Data Type | Type   | Description                       | Required |
| ---------- | --------- | ------ | --------------------------------- | -------- |
| class      | String    | @Input | Sets class for stats panel holder |          |

##  Dependent Components
###  UIStat

| Component       | Selector  |
| --------------- | --------- |
| UIStatComponent | `ul-stat` |

####  Parameters

| Parameters | Data Type | Type   | Description                                      | Required |
| ---------- | --------- | ------ | ------------------------------------------------ | -------- |
| title      | String    | @Input | Sets the text for the title of the stat          |          |
| value      | String    | @Input | Sets value text for stat                         |          |
| desc       | String    | @Input | Sets description text for stat                   |          |
| titleClass | String    | @Input | Sets class of title                              |          |
| valueClass | String    | @Input | Sets class for value text                        |          |
| descClass  | String    | @Input | Sets description class                           |          |
| statClass  | String    | @Input | Sets class for greater form of this stat         |          |
| iconClass  | String    | @Input | Sets a fontawesome icon to display with the stat |          |

####  Example
```html
<ul-stat title="Stat 1" value="20%" desc="↖ Lorem Ipsum" iconClass="fa fa-info-circle" valueClass="text-accent" ></ul-stat>
```
##  Example
```html
  <ul-stats class="">
    <ul-stat title="Stat 1" value="20%" desc="↖ Lorem Ipsum" iconClass="fa fa-info-circle" valueClass="text-accent" ></ul-stat>  

    <ul-stat title="Stat 2" value="40%" desc="↖ Lorem Ipsum" valueClass="text-primary" ></ul-stat>  

    <ul-stat title="Stat 3" value="10%" desc="↘ Lorem Ipsum" valueClass="text-info"></ul-stat>  

  </ul-stats>
```


*Use Win + ';' to get some extra characters to use.*
#  Theme Handling
The theme is determined by the below CommonComponentService. [DaisyUI Theme Documentation](https://daisyui.com/components/theme-controller/)  

```typescript

  

export abstract class CommonComponentService{  

    public currentTheme:string = CommonComponentService.themeString;
    static themeString :string | 'dark' | 'dracula' | 'light' = localStorage.getItem('theme') ?? 'dark' ; 

    constructor(){
        document.documentElement.setAttribute("data-theme", "dark");
    }

    static UpdateTheme(theme: string | 'dark' | 'dracula' | 'light'){
        localStorage.setItem('theme', theme);
        document.documentElement.setAttribute("data-theme", localStorage.getItem('theme')?? theme);
        console.log("Updated theme to: " + theme);
    }
}
```
##  Usage  
```typescript
  ThemeEvent(x: any, newTheme:string) {
    CommonComponentService.UpdateTheme(newTheme);
  }
```

```html
<div class="m-2 grid grid-cols-3 gap-1">
  <button class="btn btn-accent" (click)="ThemeEvent($event, 'dracula')">Dracula</button>
  <button class="btn btn-accent" (click)="ThemeEvent($event, 'light')">Light</button>
  <button class="btn btn-accent" (click)="ThemeEvent($event, 'dark')">Dark</button>
</div>
```


#  UINavBar  
| Component         | Selector |
| ----------------- | -------- |
| UINavBarComponent | `ul-nav` |

##  Parameters

| Parameters | Data Type | Type   | Description                         | Required |
| ---------- | --------- | ------ | ----------------------------------- | -------- |
| titleText  | String    | @Input | Sets the center text for the NavBar |          |
| titleClass | String    | @Input | Sets the class for the center title |          |
| class      | String    | @Input | Sets class for NavBar element       |          |

##  Content Projection
```html
<div class="navbar bg-base-100" [ngClass]="class">
    <div class="navbar-start">
        <ng-content select="[start]" ></ng-content>
    </div>
    <div class="navbar-center">
      <button class="btn text-xl" [ngClass]="titleClass">{{titleText}}</button>
    </div>
    <div class="navbar-end">
        <ng-content select="[end]" ></ng-content>
    </div>
  </div>
```
##  Example

```html
<ul-nav titleText="Daisy UI">
    <div start>
        <ul-menuDropdown class="w-48" buttonText="Menu" buttonClass="btn btn-accent">
            <ul-menuItem label="test"></ul-menuItem>
            <ul-menuItem label="test 1">
                <ul-menuDetail summary="test">
                    <ul-menuItem label="inner test"></ul-menuItem>
                    <ul-menuItem label="inner test 1"></ul-menuItem>
                    <ul-menuItem label="inner test 1"></ul-menuItem>
                </ul-menuDetail>
            </ul-menuItem>
            <ul-menuItem label="test 2" (action)="print('Hello World')"></ul-menuItem>
        </ul-menuDropdown>
    </div>
    <div end> <button class="btn btn-primary"> Activity</button></div>
</ul-nav>
```
#  ModalService
This is a service for handling in code Modal Windows to open whilst also maintaining the abillity to extract updated data.
##  Initialize
*  ViewContainerRef must be injected into the parent component
*  Inject `ModalService<T>` with target component type `<T>`.
##  Functions
*  open(diagComp:`Type<T>`, setInputs:((comp:`ComponentRef<T>`) => void) |undefined = undefined) `Use to init component `
*  close()  `Use to fully close the dialog`
*  afterClosed():Observable<T|undefined> `Allows user to subscribe for when dialog is closed`
##  Usage/Example
```typescript
//...
constructor(public vcr:ViewContainerRef, private mDiag:ModalService<TempComponent>) //Target component
{//...
}
//...
``` 

```typescript
  testModal(x:any)
  {
  this.mDiag.open(TempComponent,(c)=> {
    c.setInput('title','Parent Title Example')
  });
  this.mDiag.afterClosed().subscribe((res) => {
    console.log(res?.GetValues());
    this.mDiag.close();
  });  
  }
```

```html
<button class="btn btn-primary" (click)="testModal($event)">Modal</button>
```
#  UISidebar
| Component          | Selector     |
| ------------------ | ------------ |
| UISidebarComponent | `ul-sideBar` |

##  Parameters

| Parameters    | Data Type               | Type   | Description                                          | Required |
| ------------- | ----------------------- | ------ | ---------------------------------------------------- | -------- |
| actionClass   | String='btn btn-accent' | @Input | Sets class for sidebar trigger button                |          |
| actionText    | String                  | @Input | Sets text for button that triggers the button        |          |
| sidebarClass  | String                  | @Input | Sets the class for the menu options in the sidebar   |          |
| sidebarZIndex | String                  | @Input | Sets the z-axis for the sidebar so no overlaps occur |          |

##  Example
```html
<ul-nav titleText="Daisy UI">
    <div start>
        <ul-sideBar actionText="Menu">
            <li><a href="./testPage">Home</a></li>
            <li><a href="./tablePage">Tables</a></li>
            <li><a href="./menuExample">Menu</a></li>
            <li><a href="./modalExample">Modal</a></li>
            <li><a href="./statsExample">Stats</a></li>
            <li><a href="./alertsExample">Alerts</a></li>
            <li><a href="./inputsExample/">Inputs</a></li>
        </ul-sideBar>
    </div>
    <div end> <button class="btn btn-primary" (click)="NewAlert($event)"> Activity</button></div>
</ul-nav>
```
#  UITooltip
This component is meant to be very simple and just wraps content in a tooltip div. If no string is given for a tooltip then the class would not load.

  
| Component          | Selector |
| ------------------ | -------- |
| UITooltipComponent | `ul-tip` |

##  Parameters

| Parameters | Data Type | Type   | Description            | Required |
| ---------- | --------- | ------ | ---------------------- | -------- |
| tooltip    | String    | @Input | Sets the tooltip text  |          |
| tipClass   | String    | @Input | Sets class for tooltip |          |

##  Content Projection
```html
<div [class.tooltip]="tooltip != undefined" [attr.data-tip]="tooltip"   [ngClass]="tipClass">
    <ng-content/>
</div>
```
##  Example
```html
<ul-input contentType="autocomplete" label="Search" [datasource]="listSource"
                        iconClass="fa fa-search mr-1" tooltip="Test" tipClass="tooltip-accent tooltip-open" ></ul-input>  

```
[Tailwinds info for Options](https://daisyui.com/components/tooltip/)

# UICalendar

| Component               | Selector |
| ----------------------- | -------- |
| UICalendarViewComponent | `ul-cal` |


## Parameters

| Parameter     | Data Type | Type   | Description                                                                                                              | Required |
| ------------- | --------- | ------ | ------------------------------------------------------------------------------------------------------------------------ | -------- |
| year          | number    | @Input | Default Year for the calendar                                                                                            |          |
| month         | number    | @Input | Default month of the calendar                                                                                            |          |
| offset        | number    | @Input | Allow you to page through months and years by just changing the index. (-x is previous months and +x is for next months) |          |
| dayClass      | string    | @Input | Sets the class for each active month day cell                                                                            |          |
| disabledClass | string    | @Input | Sets the class for specifically the disabled dates from the prior month.                                                 |          |
| headerClass   | string    | @Input | Sets the container div class for each header item.                                                                       |          |
| cellClass     | string    | @Input | Sets the class for all calendar day cells. Used for size mostly.                                                         | ✅        |

## Examples 
```html
<div class="block w-fit">
    <div class="flex justify-between my-2">
        <button class="btn btn-primary" (click)="updateIndex(false)" >Previous</button>
        <button class="btn btn-secondary" (click)="updateIndex()" >Next</button>
        
    </div>
    <div>
    <ul-cal #cal cellClass="w-40 h-40" [year]="2024" [month]="5" [offset]="indexCalendar" >
        <ul-day>        
        <ng-template let-day >
            <div class="m-2">        
            <span class="badge badge-secondary">{{day | date :'mediumDate' }}</span>
            </div>
        
        </ng-template>
        
        </ul-day>    
        
        </ul-cal>
    </div>
</div>
```

```typescript
  updateIndex(isNext:boolean = true)
  {
    if (isNext)
    {      
    this.indexCalendar ++;
    }
    else{
      this.indexCalendar --;
    }
  }

```

## Child components 

### UICalendarCell
This meant to just contain the template for the loading of the days in the calendar view.

| Component               | Selector |
| ----------------------- | -------- |
| UICalendarCellComponent | `ul-day` |

#### Variables

| Name       | Description                                                                   |
| ---------- | ----------------------------------------------------------------------------- |
| day        | Gives template access to the date object for the rendered day                 |
| isPrevious | Boolean that lets you know if the day is from previous month or target month. |

```html

<ul-day>
<ng-template let-day let-isPrevious >
    <span>{{day | date :'mediumDate' }}</span>
</ng-template>
</ul-day>   
```

### UICalendarHeader
This meant to just contain the template for the loading of the header cells.

| Component                 | Selector       |
| ------------------------- | -------------- |
| UICalendarHeaderComponent | `ul-calHeader` |

#### Variables

| Name  | Description       |
| ----- | ----------------- |
| value | Give the day name |



```html
<ul-calHeader> 
<ng-template let-value>
<span class="badge badge-primary">{{value}}</span>
</ng-template>
</ul-calHeader>
```

# UIChart
This component depends on the [ChartJS](https://www.npmjs.com/package/chart.js).



| Component        | Selector   |
| ---------------- | ---------- |
| UIChartComponent | `ul-chart` |

## Variables

| Parameter         | Data Type                            | Type             | Description                                                                                                        | Required |
| ----------------- | ------------------------------------ | ---------------- | ------------------------------------------------------------------------------------------------------------------ | -------- |
| chartClass        | String                               | @Input           | Controls the div that holds the chart                                                                              |          |
| plugins           | Plugin[]                             | @Input           | From chartjs and is for chart customization. [Plugins](https://www.chartjs.org/docs/latest/configuration/#options) |          |
| labels            | String[]                             | @Input           | Labels for nodes across the X-Axis or Pie segments                                                                 |          |
| datasetComponents | `QueryList<UIChartDatasetComponent>` | @ContentChildren | Used to define the datasets                                                                                        | ✅        |
| optionsComponents | UIChartOptionsComponent              | @ContentChild    | Used to define chart options. [Options](https://www.chartjs.org/docs/latest/configuration/#options)                |          |

## Example
```html 
<div class="grid grid-cols-2">  

<ul-chart chartClass="w-96 h-96">
    <ul-dataset label="Test label" type="bar" [options]=" optionBar() " ></ul-dataset>  
</ul-chart>  

<ul-chart chartClass="w-96 h-96">
    <ul-dataset label="Test label" type="line" [options]=" optionLine()" ></ul-dataset>
</ul-chart>

<ul-chart chartClass="w-96 h-96">
    <ul-dataset label="Test label" type="bar" [options]=" optionBar() " ></ul-dataset>
    <ul-dataset label="Test label 2" type="line" [options]=" optionLine()" ></ul-dataset>
</ul-chart>  

<ul-chart chartClass="w-96 h-96" [labels]="['January', 'Feburary', 'March']" >
    <ul-dataset label="Test label" type="pie" [data]="[50,25,30]" ></ul-dataset>
</ul-chart> 

</div>

```


```typescript
  public optionBar()
  {
    var options = UIChart.DatasetOptions('bar');
    options.backgroundColor = "#de1d67";
    return options;
  }  

  public optionLine()
  {
    var options = UIChart.DatasetOptions('line');
    options.backgroundColor = "#de1d67";
    return options;
  }
```
## Dependent Components

### UIChartDataset

| Component               | Selector     |
| ----------------------- | ------------ |
| UIChartDatasetComponent | `ul-dataset` |


| Parameter | Data Type                                             | Type   | Description                                             | Required |
| --------- | ----------------------------------------------------- | ------ | ------------------------------------------------------- | -------- |
| data      | Any[]                                                 | @Input | Data to populate the chart                              | ✅        |
| label     | String                                                | @Input | Label that is specific to this data set                 |          |
| options   | `ChartDatasetCustomTypesPerDataset<typeof this.type>` | @Input | Sets other dataset options if set.                      |          |
| type      | ChartType = 'bar'                                     | @Input | Sets the chart type for the dataset that is being built | ✅        |




### UIChartOptions

| Component               | Selector          |
| ----------------------- | ----------------- |
| UIChartOptionsComponent | `ul-chartOptions` |


| Parameter | Data Type                        | Type   | Description                                             | Required |
| --------- | -------------------------------- | ------ | ------------------------------------------------------- | -------- |
| options   | `ChartOptions<typeof this.type>` | @Input | Sets other dataset options if set.                      |          |
| type      | ChartType = 'bar'                | @Input | Sets the chart type for the dataset that is being built | ✅        |


# UIAdvancedFilter

| Component                 | Selector    |
| ------------------------- | ----------- |
| UIAdvancedFilterComponent | `ul-filter` |


## Variables


| Parameter     | Data Type                                 | Type             | Description                                                      | Required |
| ------------- | ----------------------------------------- | ---------------- | ---------------------------------------------------------------- | -------- |
| filterOptions | `QueryList<UIFilterItemComponent>`        | @ContentChildren | Set the inputs for the filter options.                           | ✅        |
| filterInputs  | `QueryList<UIFormComponent> \| undefined` | @ViewChildren    | This is meant for getting the form inputs for the filter options |          |
| filter        | `EventEmitter<IFilterItem[]>`             | @Output          | Returns the filters that were set in the filter search           |          |

## Example

```html

<ul-table #tbl class="w-full" [dataSource]="countryData" nestedClickEnabled>

        <ul-filter search (filter)="tbl.setFilter($event)" >

            <ul-filterItem [config]="{id:'abbreviation', name: 'Abbreviation', type: 'text'}"></ul-filterItem>

            <ul-filterItem [config]="{id:'capital', name: 'Capital', type: 'dropdown', datasource: [{display: 'Test 1', value:'1'},{display: 'Test 2', value:'2'}]}"></ul-filterItem>

            <ul-filterItem [config]="{id:'name', name: 'Name', type: 'autocomplete', $autocomplete:search }" [context]="APIService"></ul-filterItem>

            </ul-filter>
  <!--...-->

    </ul-table>


```
``` typescript
  search(input?: string, context?: APIService): Observable<IFilterValue[]>
  {
    var value = context?.completeSearch(input);
    return value;
  }
```

## Table Integration
- You would need to apply the attribute `search` so that only the filter shows in the modal.
- In order to apply filters to the SearchRequest you can use the method `setFilter`.


```html
<ul-table #tbl class="w-full">

        <ul-filter search (filter)="tbl.setFilter($event)" >
            </ul-filter>
    </ul-table>

```
> # Update
> The @Output() Filter should now automatically be subscribed to by the parent table that it is inserted in and in the subscription then the table method setFilter is then called. 


# UIFilterItem
For each filter item it is an input generator that you continuosly add/remove datapoints from depending on the composition of your filter.


| Component             | Selector        |
| --------------------- | --------------- |
| UIFilterItemComponent | `ul-filterItem` |
## Variables

| Parameters | Data Type   | Type   | Description                              | Required |
| ---------- | ----------- | ------ | ---------------------------------------- | -------- |
| config     | IFilterItem | @Input | Set the control generating filter inputs | ✅        |
| context     | any | @Input | Set the object context to retrieve data from a data provider | ✅ (For accessing the data providing service)        |

## Model
```typescript
export interface IFilterValue {
  id?: number;
  display: string;
  value: string;
  parentFilterId?: number ;
}  

export interface IFilterItem {

  id: string;
  name: string;
  type: string | 'text' | 'dropdown' | 'autocomplete' | 'date' | 'dateRange'
  value?: string;
  datasource?:IFilterValue[]  ;
  defaultValue?: any;
  IsIncluded?:boolean;
  excludeFilter?: boolean;
  allowMultiple?: boolean ;
  validators?: ValidatorFn[];
  dateOptions?: FlatpickrDefaultsInterface;
  customBools?: Map<string, boolean> ;
  $autocomplete?: ((input?: string) => Observable<IFilterValue[]>) ;
  selected?:boolean;
  utcDate?:boolean; //determines if the the date/dateRange value(s) should be converted before sending to webServer. Doesn't affect UI display of date
  index?:number;
}

```

## Build Options

```html

            @switch(item.type)

                    {

                      @case('text')

                      {

                        <ul-input alt dataKey="filterInput" [validators]="item.validators" autoValidate  formClass="w-full"  class="w-full" [label]="item.name"  [defaultValue]="item?.defaultValue ?? ''"  > </ul-input>

                      }

                      @case('dropdown')

                      {

                        <ul-input alt dataKey="filterInput" [validators]="item.validators" autoValidate  contentType="select" [dataDefault]="{Key:'Select ' + item.name, Value:'-1'}" [datasource]="filterValueToListItem(item.datasource)" formClass="w-full"  class="w-full" [label]="item.name"  [defaultValue]="item?.defaultValue ?? '-1'"  > </ul-input>

                      }

                      @case('autocomplete')

                      {

                        <ul-input alt style="position: relative;"  dataKey="filterInput" [validators]="item.validators" autoValidate [style.z-index]="setZIndex($index)"  contentType="autocomplete" [autoComplete]="filterValueToAutocomplete(item.$autocomplete)" placeholder="Type to search for value.." formClass="w-full"  class="w-full" [label]="item.name"  [defaultValue]="item?.defaultValue ?? '-1'"  > </ul-input>

                      }

                      @case('date') <!-- Same as DateRange -->

                      {

                        <ul-input dataKey="filterInput"  [validators]="item.validators" autoValidate inputType="date" formClass="w-full"  class="w-full" [label]="item.name"  [defaultValue]="item?.defaultValue ?? ''"  > </ul-input>

                      }

                      @default{

                        <ul-input alt dataKey="filterInput" [validators]="item.validators" autoValidate  formClass="w-full"  class="w-full" [label]="item.name"  [defaultValue]="item?.defaultValue ?? ''"  > </ul-input>

                      }

                    }
```


# Source Builder

``` typescript
export declare class SourceBuilder<T, TRefresh> {

    data?: T[] | SearchResponse<T>;
    $refresh?: Observable<TRefresh>;
    $trigger?: (source: TRefresh, tblSource: BehaviorSubject<T[]>) => void;
    $nestedSources: {
        Name: string;
        SourceDefinition: (row: T) => Observable<any>;
    }[];

    constructor(inputData: T[] | SearchResponse<T>);
    setRefresh(inputRefresh: Observable<TRefresh>): void;
    setTrigger(inputTrigger: (source: TRefresh, tblSource: BehaviorSubject<T[]>) => void): void;
    addDynamicSource(sourceName: string, sourceDefinition: (row: T) => Observable<any>): void;
    buildPageSource(): SearchResponse<any> | undefined;
    mapSources(resultData?: T[]): any[] | undefined;
    buildSource(): any[] | undefined;
    build(): any[] | SearchResponse<any> | undefined;
}
```

## Features

| Method           | Description                                                                                                                                       |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| setRefresh       | Allows you to append the refresh observable to the rows in the data property                                                                      |
| setTrigger       | Allows you to set trigger to use the `$refresh` data to update the row that corresponds with the updated data from from refresh.                  |
| addDynamicSource | Allows you to nest custom observables that can be used to create nested data sources per row for dropdown sources, nested table sources and more. |
## Table Source Model
### SearchResponse
``` typescript
export class SearchResponse<T>
{
  public count: number = 0;
  public results?: Array<T>;
}
```
 - You can use the `Observable.prototype.ToSearchResponse` to bind the results and the count properties.
	 - You can continue to use the output `Observable<SearchResponse<T>>`, along with any pipes you want to use to append/filter/modify data to build your table.
 - You can also do the same custom count/results binding with the `Observable.prototype.ToPageObservable`. 
	 - The main difference with this class is that contains the `Observable<SearchResponse<T>>` as property `$observable` along with methods that make use of this property to help with building the output observable.
	 - Methods
		 - map(delegate:(singleResult:any) => any): Meant to allow a user to edit the data set per-row.
		 - ToListItems(bindKey:string, bindValue:string): Converts the `results` per row into Listitems given the binding strings that corresponds with the property name.
		 - buildSources: This utilizes the sourceBuilder class to append the `$refresh/$trigger` and other dynamic sources that can be SearchRequest/Row specific.
			 - This Build sources utilizes the observable pipe `configSources`.
```typescript
  public buildSources(buildOptions:(builder: SourceBuilder<T,any>) => void)
  {
   return this.$observable
    .pipe(configSources<T, SearchResponse<any>>(buildOptions));
  }				 
```
---
#### Observable Pipe
This can be used without using the `PageObservable` or the `buildSources()` method.

```typescript
export function configSources<T, R extends any[] | SearchResponse<any>>(buildOptions:(builder: SourceBuilder<T,any>) => void) //T is carried over to SourceBuilder and second type is always Any (since the model is no longer the same with the new props). R in this case refers to the return and should be SearchResponse<any> or Any[]
{
//...
      var builder = new SourceBuilder<T, any>(x);
      buildOptions(builder);
//...
}
```
---
```typescript 
public interface IModel
{
	A:string,
	B:string
}
public test()
{
	this.$example
	.pipe(configSources<IModel,SearchResponse<any>>(x => {
		x.setRefresh(this.$example2); //Set refresh
		//You can set the trigger explicitly or with a default
		x.setTrigger(CommonTableFunctions.defaultTrigger((source, table) => source?.NewA == table.A)); //Default
		x.setTrigger((source:any, tableSource: BehaviorSubject<IModel[]>) => 
		{//Explicit
		var rawTableData = tableSource.getValue();
		var updatedValues = rawTableData.map((tableRow:TtableData) =>
	    {
	      if (source.NewA == tableRow.A)
	      {
	       tableRow.B = source.NewB;
	      }
	      return tableRow;
	    });
	    tableData.next(updatedValues);	
		});	
		addDynamicSource('$innerA', row => this.GetObservableInnerA(row.A));	
	}));
}
```
---
>**Trigger Note**
>
> The 2 definitions for the triggers above are the same, the main difference is ease of use and the Default does auto bind but has options to exclude and acquire nested refresh sources.

>**Until Destroy Note**
>
> You don't need to worry much about including an until destroy when using the nested source in HTML of the component because if you use the async pipe `($innerA | async)` then it will auto destroy when not present in the component

### Array
A lot remains the same for building with this source but the main difference is instead of using the `SearchResponse` as a type argument you would use the `T[]` (Example: `IModel[]`);
```typescript
public test()
{
	this.$example
	.pipe(configSources<IModel,any[]>(x => {	
		//All the customization from previous example can stay the same 
	});
}
```
[Change Log](changelog.md)