Skip to content

Commit 6d86ff0

Browse files
authored
docs(core): implement RTL service documentation (#12198)
* closes [#11854](#11854) ## Description Implementing RTl documentation with examples * closes [#11854](#11854) ## Description Added documentation for using RtlService to implement RTL in applications. Included examples and guidance on how and when to use RtlService, and added an RTL section to each control's documentation. * closes [#11854](#11854) ## Description Added documentation for using RtlService to implement RTL in applications. Included examples and guidance on how and when to use RtlService, and added an RTL section to each control's documentation. * closes [#11854](#11854) ## Description Refactored the RTL service basic example to use a button instead of the existing RTL switch. Synchronized the RTL switch ngModel with the isRtl property and ensured it is only synced within the appropriate context. * closes [#11854](#11854) ## Description Refactored the RTL service basic example to use a button instead of the existing RTL switch. Synchronized the RTL switch ngModel with the isRtl property and ensured it is only synced within the appropriate context. * closes [#11854](#11854) ## Description Moved RTl service docs in CDK utilities section * closes [#12198](#12198) ## Description Removed redundant `_updateTextContainerDirection` call on button click. Direction updates are now handled solely by effect triggered by `_dir$` changes. * closes [#12198](#12198) docs(core): implement RTL service documentation ## Description Added documentation for using RtlService to implement RTL in applications. Included examples and guidance on how and when to use RtlService, and added an RTL section to each control's documentation. * docs(core): Implement RTL service documentation closes [#12198](#12198) ## Description Rolled back package json format change
1 parent 7f1d8fb commit 6d86ff0

19 files changed

+316
-32
lines changed

libs/cdk/utils/services/rtl.service.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Inject, Injectable, InjectionToken, Optional, Signal } from '@angular/c
22
import { toSignal } from '@angular/core/rxjs-interop';
33
import { BehaviorSubject } from 'rxjs';
44

5+
/** Default RTL languages */
56
const DefaultRtlLanguages = ['ar', 'arc', 'dv', 'fa', 'ha', 'he', 'khw', 'ks', 'ku', 'ps', 'ur', 'yi'];
67
export const RTL_LANGUAGE = new InjectionToken<string[]>('RtlLanguage');
78

libs/docs/cdk/api-files.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,6 @@ export const API_FILES = {
1919
clicked: ['ClickedDirective'],
2020
focusableList: ['FocusableListDirective', 'FocusableItemDirective'],
2121
dnd: ['DndListDirective', 'DndItemDirective', 'DndKeyboardGroupDirective', 'DndKeyboardItemDirective'],
22-
initialFocus: ['InitialFocusDirective']
22+
initialFocus: ['InitialFocusDirective'],
23+
rtlService: ['RtlService']
2324
} as const;

libs/docs/cdk/docs-data.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@
5555
{
5656
"url": "cdk/tabbable",
5757
"name": "Tabbable element"
58+
},
59+
{
60+
"url": "cdk/rtl-service",
61+
"name": "RTL Service"
5862
}
5963
]
6064
}

libs/docs/cdk/docs-routes.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ const componentRoutes = [
6565
{
6666
path: 'breakpoint',
6767
loadChildren: () => import('@fundamental-ngx/docs/cdk/breakpoint').then(configureLibRoutes)
68+
},
69+
{
70+
path: 'rtl-service',
71+
loadChildren: () => import('libs/docs/cdk/rtl-service').then(configureLibRoutes)
6872
}
6973
];
7074

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
describe('RTL Service', () => {});
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"extends": "../../../../../e2e/tsconfig.json",
3+
"include": ["./**/*.e2e-spec.ts"]
4+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<div id="exampleTextContainer">
2+
<h3>Is <code>RTL</code>: {{ rtl$() }}</h3>
3+
<h3>Whitespaces disabled</h3>
4+
<fd-text [text]="text"></fd-text>
5+
6+
<h3>Whitespaces enabled</h3>
7+
<fd-text id="example-text" [text]="text" [whitespaces]="true"></fd-text>
8+
<br /><br />
9+
<button fd-button (click)="simulateRTL()">Simulate {{ rtl$() ? 'LTR' : 'RTL' }}</button>
10+
</div>
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { Direction } from '@angular/cdk/bidi';
2+
import { ChangeDetectionStrategy, Component, computed, effect, inject } from '@angular/core';
3+
import { FormsModule } from '@angular/forms';
4+
import { ButtonComponent, FormLabelComponent, RtlService, SwitchComponent, TextComponent } from '@fundamental-ngx/core';
5+
6+
@Component({
7+
selector: 'fd-rtl-service-basic-example',
8+
templateUrl: 'rtl-service-basic-example.component.html',
9+
imports: [TextComponent, ButtonComponent, FormLabelComponent, SwitchComponent, FormsModule],
10+
changeDetection: ChangeDetectionStrategy.OnPush,
11+
standalone: true
12+
})
13+
export class RtlServiceBasicExampleComponent {
14+
// Injecting the RtlService
15+
private _rtlService = inject(RtlService);
16+
17+
// Example text
18+
text = `
19+
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et
20+
dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
21+
aliquip ex ea commodo consequat.
22+
23+
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore
24+
eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia
25+
deserunt mollit anim id est laborum.`;
26+
27+
// Signal to track RTL state
28+
rtl$ = computed(() => !!this._rtlService?.rtlSignal());
29+
// Signal to track a direction
30+
_dir$ = computed<Direction>(() => {
31+
return this.rtl$() ? 'rtl' : 'ltr';
32+
});
33+
34+
constructor() {
35+
effect(() => {
36+
this._updateTextContainerDirection();
37+
});
38+
}
39+
40+
// Method to update the direction of the text container
41+
private _updateTextContainerDirection() {
42+
const labelElement = document.getElementById('exampleTextContainer');
43+
labelElement && (labelElement.dir = this._dir$());
44+
}
45+
// Method to handle changes in RTL state
46+
simulateRTL(): void {
47+
this._rtlService.rtl.next(!this._rtlService.rtl.value);
48+
}
49+
}

libs/docs/cdk/rtl-service/index.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { Routes } from '@angular/router';
2+
import { RtlServiceDocsComponent } from './rtl-service-docs.component';
3+
import { RtlServiceHeaderComponent } from './rtl-service-header/rtl-service-header.component';
4+
5+
export const ROUTES: Routes = [
6+
{
7+
path: '',
8+
component: RtlServiceHeaderComponent,
9+
children: [
10+
{
11+
path: '',
12+
component: RtlServiceDocsComponent
13+
}
14+
],
15+
data: {
16+
primary: true
17+
}
18+
}
19+
];
20+
21+
export const LIBRARY_NAME = 'rtl-service';
22+
export const API_FILE_KEY = 'rtlService';
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"name": "docs-rtl-service",
3+
"$schema": "../../../../node_modules/nx/schemas/project-schema.json",
4+
"sourceRoot": "libs/docs/core/rtl-service",
5+
"prefix": "lib",
6+
"projectType": "library",
7+
"tags": ["type:lib", "scope:docs"],
8+
"targets": {
9+
"e2e": {
10+
"executor": "@fundamental-ngx/nx-plugin:e2e-test",
11+
"options": {
12+
"e2eFiles": ["libs/docs/core/truncate/e2e/**/*.e2e-spec.ts"],
13+
"devServerTarget": "docs:serve:e2e"
14+
},
15+
"outputs": ["{workspaceRoot}/allure-results/docs-core-rtl-service"]
16+
}
17+
}
18+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<fd-docs-section-title id="rtl-service-usage" componentName="rtl-service"> RTL Service Usage </fd-docs-section-title>
2+
<description>
3+
The <code>RtlService</code> service can be used to manage the Right-To-Left (RTL) settings in your application.
4+
</description>
5+
6+
<description>
7+
It uses a <code>BehaviorSubject</code> to track the RTL status and provides a <code>Signal</code> wrapper for
8+
reactive programming. The service can be configured with a custom list of RTL languages using the
9+
<code>RTL_LANGUAGE</code> injection token.
10+
<fd-code-snippet language="typescript" [contentBased]="true">{{ injectionTokenExample }}</fd-code-snippet>
11+
</description>
12+
13+
<fd-docs-section-title id="rtl-service-default-langs" componentName="rtl-service-default-langs">
14+
Default RTL Languages
15+
</fd-docs-section-title>
16+
17+
<description> The service comes with a predefined set of RTL languages. These are: </description>
18+
<ul>
19+
<li>Arabic (ar)</li>
20+
<li>Aramaic (arc)</li>
21+
<li>Divehi (dv)</li>
22+
<li>Persian (fa)</li>
23+
<li>Hausa (ha)</li>
24+
<li>Hebrew (he)</li>
25+
<li>Khowar (khw)</li>
26+
<li>Kashmiri (ks)</li>
27+
<li>Kurdish (ku)</li>
28+
<li>Pashto (ps)</li>
29+
<li>Urdu (ur)</li>
30+
<li>Yiddish (yi)</li>
31+
</ul>
32+
<description>
33+
You can override this list by providing a custom list to the <code>RTL_LANGUAGE</code> injection token.
34+
</description>
35+
36+
<component-example>
37+
<fd-rtl-service-basic-example />
38+
</component-example>
39+
<code-example [exampleFiles]="rtlService"></code-example>
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { Component } from '@angular/core';
2+
import {
3+
CodeExampleComponent,
4+
CodeSnippetComponent,
5+
ComponentExampleComponent,
6+
DescriptionComponent,
7+
DocsSectionTitleComponent,
8+
ExampleFile,
9+
getAssetFromModuleAssets
10+
} from '@fundamental-ngx/docs/shared';
11+
import { RtlServiceBasicExampleComponent } from './examples/rtl-service-basic-example/rtl-service-basic-example.component';
12+
13+
const rtlServiceBasicExampleTs = 'rtl-service-basic-example/rtl-service-basic-example.component.ts';
14+
const rtlServiceBasicExampleHtml = 'rtl-service-basic-example/rtl-service-basic-example.component.html';
15+
16+
@Component({
17+
selector: 'fd-rtl-service-docs',
18+
templateUrl: './rtl-service-docs.component.html',
19+
imports: [
20+
DocsSectionTitleComponent,
21+
DescriptionComponent,
22+
ComponentExampleComponent,
23+
RtlServiceBasicExampleComponent,
24+
CodeExampleComponent,
25+
CodeSnippetComponent
26+
],
27+
standalone: true
28+
})
29+
export class RtlServiceDocsComponent {
30+
rtlService: ExampleFile[] = [
31+
{
32+
language: 'html',
33+
code: getAssetFromModuleAssets(rtlServiceBasicExampleHtml),
34+
fileName: 'rtl-service-basic-example'
35+
},
36+
{
37+
language: 'typescript',
38+
code: getAssetFromModuleAssets(rtlServiceBasicExampleTs),
39+
fileName: 'rtl-service-basic-example',
40+
component: 'RtlServiceBasicExampleComponent'
41+
}
42+
];
43+
44+
injectionTokenExample = `
45+
@NgModule({
46+
providers: [
47+
RtlService,
48+
{ provide: RTL_LANGUAGE, useValue: ['ar', 'he', 'fa', 'your-custom-lang'] }
49+
],
50+
...
51+
})
52+
export class AppModule { }
53+
`;
54+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<header>RTL Service</header>
2+
<description>
3+
The <code>RtlService</code> is an Angular service designed to manage Right-To-Left (RTL) settings in your
4+
application. It uses a <code>BehaviorSubject</code> to track the RTL state and provides a signal wrapper for
5+
reactive programming.
6+
</description>
7+
8+
<fd-header-tabs />
9+
<router-outlet></router-outlet>

libs/docs/cdk/rtl-service/rtl-service-header/rtl-service-header.component.scss

Whitespace-only changes.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { Component } from '@angular/core';
2+
import { RouterOutlet } from '@angular/router';
3+
import {
4+
DescriptionComponent,
5+
DocPageComponent,
6+
HeaderComponent,
7+
HeaderTabsComponent,
8+
ImportComponent
9+
} from '@fundamental-ngx/docs/shared';
10+
11+
@Component({
12+
selector: 'fd-rtl-service-header',
13+
templateUrl: './rtl-service-header.component.html',
14+
imports: [
15+
HeaderComponent,
16+
DocPageComponent,
17+
RouterOutlet,
18+
DescriptionComponent,
19+
ImportComponent,
20+
HeaderTabsComponent
21+
],
22+
standalone: true
23+
})
24+
export class RtlServiceHeaderComponent {}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"extends": "../../../../tsconfig.base.json",
3+
"files": [],
4+
"include": ["**/*.ts"],
5+
"compilerOptions": {
6+
"forceConsistentCasingInFileNames": true,
7+
"strict": true,
8+
"noImplicitReturns": false,
9+
"noFallthroughCasesInSwitch": true,
10+
"target": "es2022",
11+
"outDir": "../../../../dist/out-tsc",
12+
"declaration": true,
13+
"declarationMap": true,
14+
"inlineSources": true,
15+
"types": []
16+
},
17+
"exclude": ["**/*.test.ts", "**/*.spec.ts", "**/*.e2e-spec.ts"]
18+
}

libs/docs/shared-pages/library-doc-shell-page.component.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { CdkScrollable } from '@angular/cdk/overlay';
2-
32
import { Component, inject } from '@angular/core';
43
import { ActivatedRoute, RouterOutlet } from '@angular/router';
54
import {

libs/docs/shared/src/lib/core-helpers/directionality/directionality.component.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ChangeDetectionStrategy, Component, Input, OnInit, ViewEncapsulation } from '@angular/core';
1+
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnInit, ViewEncapsulation } from '@angular/core';
22
import { FormsModule } from '@angular/forms';
33
import { RtlService } from '@fundamental-ngx/cdk/utils';
44
import { FormLabelComponent } from '@fundamental-ngx/core/form';
@@ -27,14 +27,21 @@ export class DirectionalityComponent implements OnInit {
2727
id: string;
2828
isChecked = false;
2929

30-
constructor(private rtlService: RtlService) {}
30+
constructor(
31+
private rtlService: RtlService,
32+
private cdr: ChangeDetectorRef
33+
) {}
3134

3235
ngOnInit(): void {
3336
if (this.label) {
3437
this.id = this.label + Date.now() + '-rtl';
3538
} else {
3639
this.id = Date.now() + 6 + '';
3740
}
41+
this.rtlService.rtl.subscribe((rtl) => {
42+
this.isChecked = rtl;
43+
this.cdr.detectChanges();
44+
});
3845
}
3946

4047
onChange(): void {

0 commit comments

Comments
 (0)