@justeattakeaway/pie-webc-core 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.8.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [Changed] - Update RTL mixin to infer dir by default and document ([#745](https://github.com/justeattakeaway/pie/pull/745)) by [@raoufswe](https://github.com/raoufswe)
8
+
3
9
  ## 0.7.0
4
10
 
5
11
  ### Minor Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@justeattakeaway/pie-webc-core",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "PIE design system base classes, mixins and utilities for web components",
5
5
  "type": "module",
6
6
  "main": "index.ts",
@@ -9,7 +9,9 @@
9
9
  "scripts": {
10
10
  "lint:scripts": "run -T eslint .",
11
11
  "lint:scripts:fix": "run -T eslint . --fix",
12
- "test": "run -T vitest run"
12
+ "test": "run -T vitest run",
13
+ "test:ci": "yarn test",
14
+ "test:watch": "run -T vitest"
13
15
  },
14
16
  "volta": {
15
17
  "extends": "../../../package.json"
@@ -12,7 +12,7 @@ type htmlDirAttribute = 'ltr' | 'rtl' | 'auto';
12
12
  * Any component property interface that implements RTL should extend this interface. See the ModalProps interface for an example of this.
13
13
  */
14
14
  export interface RTLComponentProps {
15
- dir: htmlDirAttribute
15
+ dir?: htmlDirAttribute
16
16
  }
17
17
 
18
18
  // This is just used by the dynamically constructed class below and does not need to be imported or referenced anywhere else
@@ -21,11 +21,23 @@ declare class _RTLInterface {
21
21
  isRTL: boolean;
22
22
  }
23
23
 
24
+ /**
25
+ * This RTL mixin is used with Lit Web components to add programmatic Right-to-Left (RTL) support.
26
+ * It is only required if your component either:
27
+ * - Needs RTL awareness in its TypeScript logic.
28
+ * - Its CSS requires a [dir='rtl'] attribute to be present.
29
+ *
30
+ * By default, components will infer the 'dir' property from the document's root 'dir' attribute.
31
+ * If needed, it's possible to override specific components direction by setting the 'dir' property
32
+ * value. The 'dir' property value is reflected in the DOM, making it queryable. The 'isRTL'
33
+ * internal property returns true or false depending on whether or not the 'dir' property is 'rtl' or not.
34
+ */
35
+
24
36
  export const RtlMixin =
25
37
  <T extends Constructor<LitElement>>(superClass: T) => {
26
38
  class RTLElement extends superClass implements _RTLInterface {
27
39
  @property({ type: String, reflect: true })
28
- dir : htmlDirAttribute = 'ltr';
40
+ dir : htmlDirAttribute = document?.documentElement?.dir as htmlDirAttribute ?? 'ltr';
29
41
 
30
42
  /**
31
43
  * Returns true if the element is in Right to Left mode.
@@ -37,15 +49,7 @@ export const RtlMixin =
37
49
  * will not be reactive and is only computed once
38
50
  */
39
51
  get isRTL () : boolean {
40
- if (this.dir === 'ltr') {
41
- return false;
42
- }
43
-
44
- if (this.dir === 'rtl' || window?.getComputedStyle(this)?.direction === 'rtl') {
45
- return true;
46
- }
47
-
48
- return false;
52
+ return this.dir === 'rtl';
49
53
  }
50
54
  }
51
55
 
@@ -0,0 +1,72 @@
1
+ import { LitElement, html, nothing } from 'lit';
2
+ import {
3
+ describe,
4
+ it,
5
+ expect,
6
+ } from 'vitest';
7
+ import { RTLComponentProps, RtlMixin } from '../index';
8
+
9
+ const scenarios = [
10
+ { dir: 'ltr', isRTL: false },
11
+ { dir: 'rtl', isRTL: true },
12
+ { dir: 'auto', isRTL: false }
13
+ ];
14
+
15
+ describe('RtlMixin', () => {
16
+ const componentSelector = 'rtl-mixin-mock';
17
+ class MockComponent extends RtlMixin(LitElement) implements RTLComponentProps {
18
+ render () {
19
+ const { isRTL, dir } = this;
20
+ return html`<div dir="${dir || nothing}">${isRTL ? 'RTL Mode' : 'LTR Mode'}</div>`;
21
+ }
22
+ }
23
+
24
+ customElements.define(componentSelector, MockComponent);
25
+
26
+ function getMockInstance (): MockComponent {
27
+ return document.body.querySelector(componentSelector) as MockComponent;
28
+ }
29
+
30
+ describe('when the dir attribute is set via the component', () => {
31
+ scenarios.forEach(({ dir, isRTL }) => {
32
+ it(`should default to ${dir} if the component dir attribute is set to ${dir}`, () => {
33
+ // Arrange
34
+ document.body.innerHTML = `<rtl-mixin-mock dir="${dir}"></rtl-mixin-mock>`;
35
+ const component = getMockInstance();
36
+
37
+ // Assert
38
+ expect(component.dir).toEqual(dir);
39
+ expect(component.isRTL).toBe(isRTL);
40
+ });
41
+ });
42
+ });
43
+
44
+ describe('when the dir attribute is set via the root document', () => {
45
+ scenarios.forEach(({ dir, isRTL }) => {
46
+ it(`should default to ${dir} if the root document dir attribute is set to ${dir}`, () => {
47
+ // Arrange
48
+ document.documentElement.setAttribute('dir', dir);
49
+ document.body.innerHTML = '<rtl-mixin-mock></rtl-mixin-mock>'; // component doesn't set dir
50
+ const component = getMockInstance();
51
+
52
+ // Assert
53
+ expect(component.dir).toEqual(dir);
54
+ expect(component.isRTL).toBe(isRTL);
55
+ });
56
+ });
57
+ });
58
+
59
+ it('should default to dir value of the component if the root document and component dir attribute are set', () => {
60
+ // Arrange
61
+ const rootDir = 'ltr';
62
+ const componentDir = 'rtl';
63
+ document.documentElement.setAttribute('dir', rootDir);
64
+ document.body.innerHTML = `<rtl-mixin-mock dir="${componentDir}"></rtl-mixin-mock>`;
65
+ const component = getMockInstance();
66
+
67
+ // Assert
68
+ expect(component.dir).toEqual(componentDir);
69
+ expect(component.dir).not.toEqual(rootDir);
70
+ expect(component.isRTL).toBeTruthy();
71
+ });
72
+ });
package/vite.config.js ADDED
@@ -0,0 +1,7 @@
1
+ import { defineConfig } from 'vite';
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ environment: 'jsdom',
6
+ },
7
+ });