Skip to content

Commit ba183aa

Browse files
VMihalkovMKirovaVasil MihalkovChronosSFdkamburov
authored
Action Strip Samples (#1949)
* Adding sample with delete/undo all/redo all transactions via action strip. * chore(*): Add Stackblitz config. * chore(*): Fix lint. * Add 3 samples for action strip * Add config for live-editing for action strip * docs(action-strip): Polish samples for action strip * docs(action-strip): Polish samples for action strip * docs(action-strip): Use all parameters for the demo * docs(action-strip): Add missing imports for stackblitz samples * Use Grid interaction directive * Revert "Use Grid interaction directive" This reverts commit fc940cf. * removing left-over console.log Co-authored-by: MKirova <MKirova@DEV-MKIROVA> Co-authored-by: Vasil Mihalkov <[email protected]> Co-authored-by: Stamen Stoychev <[email protected]> Co-authored-by: Deyan Kamburov <[email protected]> Co-authored-by: Deyan Kamburov <[email protected]> Co-authored-by: Stamen Stoychev <[email protected]>
1 parent 30fe352 commit ba183aa

21 files changed

+577
-7
lines changed
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/* tslint:disable:object-literal-sort-keys */
2+
import { IgxActionStripModule, IgxRippleModule, IgxButtonModule, IgxIconModule, IgxButtonGroupModule } from "igniteui-angular";
3+
import {
4+
ActionStripParagraphMenuComponent
5+
} from "../../src/app/menus/action-strip/action-strip-paragraph-menu/action-strip-paragraph-menu.component";
6+
import {
7+
ActionStripStylingComponent
8+
} from "../../src/app/menus/action-strip/action-strip-paragraph-styling/action-strip-paragraph-styling.component";
9+
import {
10+
ActionStripParagraphComponent
11+
} from "../../src/app/menus/action-strip/action-strip-paragraph/action-strip-paragraph.component";
12+
import { AppModuleConfig } from "./core/AppModuleConfig";
13+
import { Config } from "./core/Config";
14+
import { IConfigGenerator } from "./core/IConfigGenerator";
15+
16+
export class ActionStripConfigGenerator implements IConfigGenerator {
17+
public generateConfigs(): Config[] {
18+
const configs = new Array<Config>();
19+
20+
configs.push(new Config({
21+
component: ActionStripParagraphComponent,
22+
appModuleConfig: new AppModuleConfig({
23+
imports: [IgxActionStripModule, ActionStripParagraphComponent, IgxRippleModule, IgxButtonGroupModule, IgxButtonModule, IgxIconModule],
24+
ngDeclarations: [ActionStripParagraphComponent],
25+
ngImports: [IgxActionStripModule, IgxRippleModule, IgxButtonGroupModule, IgxButtonModule, IgxIconModule]
26+
}),
27+
shortenComponentPathBy: "/menus/action-strip/"
28+
}));
29+
30+
configs.push(new Config({
31+
component: ActionStripParagraphMenuComponent,
32+
appModuleConfig: new AppModuleConfig({
33+
imports: [IgxActionStripModule, ActionStripParagraphMenuComponent, IgxRippleModule, IgxButtonModule, IgxIconModule],
34+
ngDeclarations: [ActionStripParagraphMenuComponent],
35+
ngImports: [IgxActionStripModule, IgxRippleModule, IgxButtonModule, IgxIconModule]
36+
}),
37+
shortenComponentPathBy: "/menus/action-strip/"
38+
}));
39+
40+
configs.push(new Config({
41+
component: ActionStripStylingComponent,
42+
appModuleConfig: new AppModuleConfig({
43+
imports: [IgxActionStripModule, ActionStripStylingComponent, IgxRippleModule, IgxButtonModule, IgxIconModule],
44+
ngDeclarations: [ActionStripStylingComponent],
45+
ngImports: [IgxActionStripModule, IgxRippleModule, IgxButtonModule, IgxIconModule]
46+
}),
47+
shortenComponentPathBy: "/menus/action-strip/"
48+
}));
49+
50+
return configs;
51+
}
52+
}

live-editing/configs/GridConfigGenerator.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { CommonModule } from "@angular/common";
22
import { HttpClientModule } from "@angular/common/http";
33
import { Router, RouterModule } from "@angular/router";
44
// tslint:disable:max-line-length
5-
import { IgxAvatarModule, IgxBadgeModule, IgxButtonGroupModule, IgxButtonModule, IgxCheckboxModule, IgxChipsModule, IgxColumnHidingModule, IgxComboModule, IgxCsvExporterService, IgxDatePickerModule, IgxDialogModule, IgxDividerModule, IgxDragDropModule, IgxExcelExporterService, IgxExpansionPanelModule, IgxFocusModule, IgxGridModule, IgxIconModule, IgxInputGroupModule, IgxListModule, IgxOverlayService, IgxProgressBarModule, IgxRadioModule, IgxRippleModule, IgxSelectModule, IgxSnackbarModule, IgxSwitchModule, IgxTabsModule, IgxToastModule, IgxTooltipModule } from "igniteui-angular";
5+
import { IgxAvatarModule, IgxBadgeModule, IgxButtonGroupModule, IgxButtonModule, IgxCheckboxModule, IgxChipsModule, IgxColumnHidingModule, IgxComboModule, IgxCsvExporterService, IgxDatePickerModule, IgxDialogModule, IgxDividerModule, IgxDragDropModule, IgxExcelExporterService, IgxExpansionPanelModule, IgxFocusModule, IgxGridModule, IgxIconModule, IgxInputGroupModule, IgxListModule, IgxOverlayService, IgxProgressBarModule, IgxRadioModule, IgxRippleModule, IgxSelectModule, IgxSnackbarModule, IgxSwitchModule, IgxTabsModule, IgxToastModule, IgxTooltipModule, IgxActionStripModule } from "igniteui-angular";
66
import { IgxCategoryChartModule, IgxLegendModule, IgxPieChartModule, IgxSparklineCoreModule, IgxSparklineModule } from "igniteui-angular-charts";
77
import { IgxPreventDocumentScrollModule } from "../../src/app/directives/prevent-scroll.directive";
88
import { GridColumnGroupSelectionComponent } from "../../src/app/grid/column-group-selection-sample/column-group-selection-sample.component";
@@ -105,6 +105,7 @@ import { RemoteServiceVirt } from "../../src/app/grid/services/remoteService";
105105
import { AppModuleConfig } from "./core/AppModuleConfig";
106106
import { Config } from "./core/Config";
107107
import { IConfigGenerator } from "./core/IConfigGenerator";
108+
import { GridActionStripSampleComponent } from '../../src/app/grid/grid-action-strip/grid-action-strip-sample';
108109

109110
export class GridConfigGenerator implements IConfigGenerator {
110111
public generateConfigs(): Config[] {
@@ -619,6 +620,20 @@ export class GridConfigGenerator implements IConfigGenerator {
619620
})
620621
}));
621622

623+
//Grid with Action Strip
624+
configs.push(new Config({
625+
component: GridActionStripSampleComponent,
626+
additionalFiles: ["/src/app/directives/prevent-scroll.directive.ts", "/src/app/data/nwindData.ts", "/src/app/data/utils.ts",
627+
"/src/app/grid/grid-batch-editing/grid-transaction.component.ts"],
628+
appModuleConfig: new AppModuleConfig({
629+
imports: [GridActionStripSampleComponent, IgxGridModule, IgxDialogModule, IgxButtonModule,
630+
IgxFocusModule, GridWithTransactionsComponent, IgxPreventDocumentScrollModule, IgxActionStripModule],
631+
ngDeclarations: [GridActionStripSampleComponent, GridWithTransactionsComponent],
632+
ngImports: [IgxPreventDocumentScrollModule, IgxGridModule, IgxDialogModule, IgxButtonModule, IgxActionStripModule,
633+
IgxFocusModule]
634+
})
635+
}));
636+
622637
// Grid Custom Summaries
623638
configs.push(new Config({
624639
component: GridCustomSummariesSelection,

live-editing/generators/ConfigGenerators.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { ActionStripConfigGenerator } from "../configs/ActionStripConfigGenerator";
12
import { AutocompleteConfigGenerator } from "../configs/AutocompleteConfigGenerator";
23
import { AvatarConfigGenerator } from "../configs/AvatarConfigGenerator";
34
import { BadgeConfigGenerator } from "../configs/BadgeConfigGenerator";
@@ -101,6 +102,7 @@ export const CONFIG_GENERATORS =
101102
TreeGridConfigGenerator,
102103

103104
// other:
105+
ActionStripConfigGenerator,
104106
CircularProgressbarConfigGenerator,
105107
DividerConfigGenerator,
106108
ForConfigGenerator,
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
2+
<div class="grid__wrapper">
3+
<app-grid-with-transactions>
4+
<igx-grid igxPreventDocumentScroll #gridRowEditTransaction [data]="data" [primaryKey]="'ProductID'" width="100%" height="500px"
5+
[rowEditable]="true" [allowFiltering]="true" (mouseleave)="onMouseLeave(actionstrip)" (mouseover)="onMouseOver($event, gridRowEditTransaction, actionstrip)">
6+
<igx-column field="ProductID" header="Product ID" [pinned]="true" [hidden]='true' [filterable]="false"></igx-column>
7+
<igx-column field="ProductName" header="Product Name" [dataType]="'string'" [sortable]="true"></igx-column>
8+
<igx-column field="UnitPrice" header="Unit Price" [dataType]="'string'" [sortable]="true"></igx-column>
9+
<igx-column field="UnitsOnOrder" header="Units On Order" dataType="number" [editable]="false"
10+
[filterable]="false"></igx-column>
11+
<igx-column field="UnitsInStock" header="Units In Stock" dataType="number" [sortable]="true">
12+
<ng-template igxCellEditor let-cell="cell">
13+
<input name="units" [igxFocus]="true" [(ngModel)]="cell.editValue"
14+
style="color: black; width: 30px;" />
15+
</ng-template>
16+
</igx-column>
17+
<igx-column field="QuantityPerUnit" header="Quantity Per Unit" [dataType]="'string'" [filterable]="false"></igx-column>
18+
<igx-column field="ReorderLevel" header="Reorder Level" dataType="number" [filterable]="false"></igx-column>
19+
<igx-column field="Discontinued" header="Discontinued" [dataType]="'boolean'" [filterable]="false"></igx-column>
20+
<igx-action-strip #actionstrip>
21+
<button title="Undo All" igxButton="icon" igxRipple *ngIf='isDirty(actionstrip.context)' (click)='undo(actionstrip.context)'>
22+
<igx-icon>undo</igx-icon>
23+
</button>
24+
<button title="Redo All" igxButton="icon" igxRipple *ngIf='!isDirty(actionstrip.context) && hasDiscardedTransactions(actionstrip.context)' (click)='redo(actionstrip.context)'>
25+
<igx-icon>redo</igx-icon>
26+
</button>
27+
<button title='Save' igxButton="icon" igxRipple *ngIf='isDirty(actionstrip.context)' (click)='commit(actionstrip.context)'>
28+
<igx-icon>save</igx-icon>
29+
</button>
30+
<button title="Delete" igxButton="icon" igxRipple *ngIf='!isDeleted(actionstrip.context)' (click)='actionstrip.context.delete()'>
31+
<igx-icon>delete</igx-icon>
32+
</button>
33+
</igx-action-strip>
34+
</igx-grid>
35+
</app-grid-with-transactions>
36+
</div>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.grid__wrapper {
2+
margin: 15px;
3+
}
4+
5+
h4 {
6+
text-align: center;
7+
padding-top: 2%;
8+
padding-bottom: 2%;
9+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import { Component, OnInit, ViewChild } from "@angular/core";
2+
import { DATA } from "../../data/nwindData";
3+
import { generateRandomInteger } from "../../data/utils";
4+
5+
import { IgxGridComponent, IgxGridRowComponent, Transaction } from "igniteui-angular";
6+
7+
@Component({
8+
selector: "app-grid-row-action-strip",
9+
styleUrls: [`grid-action-strip-sample.scss`],
10+
templateUrl: "grid-action-strip-sample.html"
11+
})
12+
export class GridActionStripSampleComponent {
13+
@ViewChild("gridRowEditTransaction", { read: IgxGridComponent, static: true }) public grid: IgxGridComponent;
14+
15+
public currentActiveGrid: { id: string, transactions: any[] } = { id: "", transactions: [] };
16+
17+
public data: any[];
18+
public discardedTransactionsPerRecord: Map<number, Transaction[]> = new Map<number, Transaction[]>();
19+
20+
constructor() {
21+
this.data = DATA;
22+
}
23+
24+
public stateFormatter(value: string) {
25+
return JSON.stringify(value);
26+
}
27+
28+
public typeFormatter(value: string) {
29+
return value.toUpperCase();
30+
}
31+
32+
public onMouseOver(event, grid, actionStrip) {
33+
if (event.target.nodeName.toLowerCase() === "igx-grid-cell") {
34+
const rowIndex = parseInt(event.target.attributes["data-rowindex"].value, 10);
35+
const row = grid.getRowByIndex(rowIndex);
36+
actionStrip.show(row);
37+
}
38+
}
39+
40+
public onMouseLeave(actionstrip, event?) {
41+
if (!event || event.relatedTarget.nodeName.toLowerCase() !== "igx-drop-down-item") {
42+
actionstrip.hide();
43+
}
44+
}
45+
46+
public isDirty(rowContext: IgxGridRowComponent) {
47+
return rowContext && (rowContext.dirty || rowContext.deleted);
48+
}
49+
50+
public isDeleted(rowContext: IgxGridRowComponent) {
51+
return rowContext && rowContext.deleted;
52+
}
53+
54+
public commit(rowContext: IgxGridRowComponent) {
55+
this.grid.transactions.commit(this.grid.data, rowContext.rowID);
56+
this.discardedTransactionsPerRecord.set(rowContext.rowID, []);
57+
}
58+
59+
public redo(rowContext: IgxGridRowComponent) {
60+
const rowID = rowContext.rowID;
61+
const lastDiscarded = this.discardedTransactionsPerRecord.get(rowID);
62+
lastDiscarded.forEach((transaction) => {
63+
const recRef = this.grid.gridAPI.get_rec_by_id(transaction.id);
64+
this.grid.transactions.add(transaction, recRef);
65+
});
66+
this.discardedTransactionsPerRecord.set(rowID, []);
67+
}
68+
69+
public hasDiscardedTransactions(rowContext: IgxGridRowComponent) {
70+
if (!rowContext) { return false; }
71+
const lastDiscarded = this.discardedTransactionsPerRecord.get(rowContext.rowID);
72+
return lastDiscarded && lastDiscarded.length > 0;
73+
}
74+
75+
public undo(rowContext: IgxGridRowComponent) {
76+
const transactionsToDiscard = this.grid.transactions.getAggregatedChanges(true)
77+
.filter(x => x.id === rowContext.rowID);
78+
this.discardedTransactionsPerRecord.set(rowContext.rowID, transactionsToDiscard);
79+
this.grid.transactions.clear(rowContext.rowID);
80+
}
81+
}

src/app/grid/grid-routes-data.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export const gridsRoutesData = {
1616
"grid-row-drag-to-grid": { displayName: "Row Drag between Grids", parentName: "Grid" },
1717
"grid-row-reorder": { displayName: "Grid Row Reorder", parentName: "Grid" },
1818
"grid-batch-editing": { displayName: "Grid Batch Editing", parentName: "Grid" },
19+
"grid-action-strip": { displayName: "Grid with Action Strip", parentName: "Grid" },
1920
"grid-displayDensity": { displayName: "Grid Display Density", parentName: "Grid" },
2021
"grid-cell-styling": { displayName: "Grid Conditional Cell Classes", parentName: "Grid" },
2122
"grid-cell-cellStyling": { displayName: "Grid Conditional Cell Styling", parentName: "Grid" },

src/app/grid/grids-routing.module.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ import { GridColumnGroupSelectionComponent } from "./column-group-selection-samp
7777
import { GridColumnSelectionComponent } from "./column-selection-sample/column-selection-sample.component";
7878
import { GridColumnSelectionStylesComponent } from "./column-selection-styles/column-selection-styles.component";
7979
import { CustomGridPagingStyleSample } from "./custom-grid-paging-style/custom-grid-paging-style.component";
80+
import { GridActionStripSampleComponent } from "./grid-action-strip/grid-action-strip-sample";
8081
import { GridAdvancedFilteringSampleComponent } from "./grid-advanced-filtering-sample/grid-advanced-filtering-sample.component";
8182
import { GridAdvancedFilteringStyleComponent } from "./grid-advanced-filtering-style/grid-advanced-filtering-style.component";
8283
import { GridAllDataSummaryComponent } from "./grid-allData-summary/grid-allData-summary.component";
@@ -190,6 +191,11 @@ export const gridsRoutes: Routes = [
190191
data: gridsRoutesData["grid-batch-editing"],
191192
path: "grid-batch-editing"
192193
},
194+
{
195+
component: GridActionStripSampleComponent,
196+
data: gridsRoutesData["grid-action-strip"],
197+
path: "grid-action-strip"
198+
},
193199
{
194200
component: GridDisplayDensitySampleComponent,
195201
data: gridsRoutesData["grid-displayDensity"],

src/app/grid/grids.module.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,18 @@ import { HttpClientModule } from "@angular/common/http";
44
import { NgModule } from "@angular/core";
55
import { FormsModule } from "@angular/forms";
66
import {
7-
IgxAvatarModule, IgxBadgeModule, IgxBannerModule, IgxButtonGroupModule, IgxButtonModule, IgxCardModule, IgxCheckboxModule,
8-
IgxChipsModule, IgxColumnHidingModule, IgxComboModule, IgxCsvExporterService, IgxDatePickerModule,
9-
IgxDialogModule, IgxDividerModule, IgxExcelExporterService, IgxExpansionPanelModule, IgxFocusModule, IgxGridModule,
10-
IgxIconModule, IgxInputGroupModule, IgxListModule, IgxProgressBarModule, IgxRadioModule, IgxRippleModule, IgxSelectModule, IgxSliderModule,
7+
IgxActionStripModule, IgxAvatarModule, IgxBadgeModule, IgxBannerModule, IgxButtonGroupModule, IgxButtonModule, IgxCardModule,
8+
IgxCheckboxModule, IgxChipsModule, IgxColumnHidingModule, IgxComboModule, IgxCsvExporterService,
9+
IgxDatePickerModule, IgxDialogModule, IgxDividerModule, IgxExcelExporterService, IgxExpansionPanelModule, IgxFocusModule,
10+
IgxGridModule, IgxIconModule, IgxInputGroupModule, IgxListModule, IgxProgressBarModule, IgxRadioModule, IgxRippleModule, IgxSelectModule, IgxSliderModule,
1111
IgxSnackbarModule, IgxSwitchModule, IgxTabsModule, IgxToastModule, IgxToggleModule, IgxTooltipModule
1212
} from "igniteui-angular";
1313
import { IgxPreventDocumentScrollModule } from "../directives/prevent-scroll.directive";
1414
import { GridColumnGroupSelectionComponent } from "./column-group-selection-sample/column-group-selection-sample.component";
1515
import { GridColumnSelectionComponent } from "./column-selection-sample/column-selection-sample.component";
1616
import { GridColumnSelectionStylesComponent } from "./column-selection-styles/column-selection-styles.component";
1717
import { CustomGridPagingStyleSample } from "./custom-grid-paging-style/custom-grid-paging-style.component";
18+
import { GridActionStripSampleComponent } from "./grid-action-strip/grid-action-strip-sample";
1819
import { GridAdvancedFilteringSampleComponent } from "./grid-advanced-filtering-sample/grid-advanced-filtering-sample.component";
1920
import { GridAdvancedFilteringStyleComponent } from "./grid-advanced-filtering-style/grid-advanced-filtering-style.component";
2021
import { GridAllDataSummaryComponent } from "./grid-allData-summary/grid-allData-summary.component";
@@ -111,6 +112,7 @@ import { GridMultiColumnHeadersComponent } from "./multi-column-headers/multi-co
111112
declarations: [
112113
GridWithTransactionsComponent,
113114
GridBatchEditingSampleComponent,
115+
GridActionStripSampleComponent,
114116
GridColumnHidingSampleComponent,
115117
GridColumnHidingToolbarSampleComponent,
116118
GridConditionalCellStyle2Component,
@@ -239,6 +241,7 @@ import { GridMultiColumnHeadersComponent } from "./multi-column-headers/multi-co
239241
IgxTabsModule,
240242
IgxCardModule,
241243
IgxDividerModule,
244+
IgxActionStripModule,
242245
IgxListModule
243246
],
244247
providers: [
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<div class="parent" (mouseenter)="actionStrip.show()" (mouseleave)="onMouseLeave($event)">
2+
<p #myParagraph>
3+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi non nibh eu libero commodo posuere at id augue.
4+
Morbi nec justo enim. Sed placerat fringilla quam in pharetra. Pellentesque imperdiet lorem quis sem bibendum
5+
molestie. Aliquam fringilla tellus nec convallis sodales. Suspendisse a eros accumsan, mattis mauris id,
6+
malesuada nibh. Maecenas eget augue faucibus, euismod arcu sit amet, tempus nisi. Sed tellus nisl, luctus vitae
7+
vestibulum ac, vehicula non ex. Donec condimentum rhoncus enim, et efficitur tortor faucibus sed. Integer at
8+
mauris facilisis mauris condimentum bibendum. Maecenas eget lacus dolor. Etiam pulvinar, sapien vitae fermentum
9+
interdum, nunc justo facilisis est, eu ullamcorper dolor lectus sit amet nisl. Quisque aliquam urna ut leo
10+
mollis luctus. Morbi lacinia orci augue, sed blandit est ornare placerat. Cras a ante nec mauris euismod aliquam
11+
vel pulvinar urna. Morbi tincidunt fringilla tortor, at ultricies neque rhoncus ac.
12+
</p>
13+
<igx-action-strip [(displayDensity)]="displayDensity" class="my-action-strip" #actionStrip [hidden]="true">
14+
<button *igxActionStripMenuItem igxButton class="menu-button" (click)="alignTextLeft()" [igxRipple]="rippleColor">
15+
<igx-icon>format_align_left</igx-icon>
16+
</button>
17+
<button *igxActionStripMenuItem igxButton class="menu-button" (click)="alignTextCenter()" [igxRipple]="rippleColor">
18+
<igx-icon>format_align_center</igx-icon>
19+
</button>
20+
<button *igxActionStripMenuItem igxButton class="menu-button" (click)="alignTextRight()" [igxRipple]="rippleColor">
21+
<igx-icon>format_align_right</igx-icon>
22+
</button>
23+
</igx-action-strip>
24+
</div>
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
::ng-deep {
2+
.igx-drop-down__item {
3+
padding: 0;
4+
}
5+
.igx-drop-down__list {
6+
min-width: 88px;
7+
}
8+
}
9+
.parent {
10+
display: flex;
11+
align-items: center;
12+
justify-content: center;
13+
padding: 1rem;
14+
margin: auto;
15+
min-width: 700px;
16+
max-width: 1000px;
17+
height: 350px;
18+
position: relative;
19+
}
20+
21+
.my-action-strip {
22+
display: flex;
23+
align-items: flex-start;
24+
justify-content: flex-start;
25+
width: 100%;
26+
height: 100%;
27+
padding-top: 1rem;
28+
}
29+
30+
.text-align-left {
31+
text-align: left;
32+
}
33+
34+
.text-align-center {
35+
text-align: center;
36+
}
37+
38+
.text-align-right {
39+
text-align: right;
40+
}

0 commit comments

Comments
 (0)