Giter Club home page Giter Club logo

rtl-css-js's Introduction

rtl-css-js

RTL conversion for CSS in JS objects

Build Status Code Coverage version downloads MIT License ![All Contributors][all-contributors-badge] PRs Welcome Code of Conduct

The problem

For some locales, it's necessary to change padding-left to padding-right when your text direction is right to left. There are tools like this for CSS (cssjanus for example) which manipulate strings of CSS to do this, but none for CSS in JS where your CSS is represented by an object.

This solution

This is a function which accepts a CSS in JS object and can convert padding-left to padding-right as well as all other properties where it makes sense to do that (at least, that's what it's going to be when it's done... This is a work in progress).

Table of Contentss

Installation

This module is distributed via npm which is bundled with node and should be installed as one of your project's dependencies:

npm install --save rtl-css-js

Usage

This module is exposed via CommonJS as well as UMD with the global as rtlCSSJS

CommonJS:

const rtlCSSJS = require('rtl-css-js')
const styles = rtlCSSJS({paddingLeft: 23})
console.log(styles) // logs {paddingRight: 23}

You can also just include a script tag in your browser and use the rtlCSSJS variable:

<script src="https://unpkg.com/rtl-css-js"></script>
<script>
  const styles = rtlCSSJS({paddingRight: 23})
  console.log(styles) // logs {paddingLeft: 23}
</script>

You can also control which rules you don't want to flip by adding a /* @noflip */ CSS comment to your rule

const rtlCSSJS = require('rtl-css-js')
const styles = rtlCSSJS({paddingLeft: '20px /* @noflip */'})
console.log(styles) // logs {paddingLeft: '20px /* @noflip */' }

kebab-case

This library support kebab-case properties too.

const rtlCSSJS = require('rtl-css-js')
const styles = rtlCSSJS({'padding-right': 23})
console.log(styles) // logs {'padding-left': 23}

core

rtl-css-js also exposes its internal helpers and utilities so you can deal with certain scenarios yourself. To use these you can use the rtlCSSJSCore global with the UMD build, require('rtl-css-js/core'), or use import {propertyValueConverters, arrayToObject} from 'rtl-css-js/core'.

You can import anything that's exported from src/core. Please see the code comments for documentation on how to use these.

Caveats

background

Right now background and backgroundImage just replace all instances of ltr with rtl and right with left. This is so you can have a different image for your LTR and RTL, and in order to flip linear gradients. Note that this is case sensitive! Must be lower case. Note also that it will not change bright to bleft. It's a little smarter than that. But this is definitely something to consider with your URLs.

CSS variables - var()

Since it's impossible to know what the contents of a css variable are until the styles are actually calculated by the browser, any CSS variable contents will not be converted.

Inspiration

CSSJanus was a major inspiration.

Ecosystem

Other Solutions

I'm not aware of any, if you are please make a pull request and add it here!

Contributors

Thanks goes to these people (emoji key):


Kent C. Dodds

๐Ÿ’ป โš ๏ธ ๐Ÿš‡

Ahmed El Gabri

๐Ÿ’ป ๐Ÿ“– โš ๏ธ

Maja Wichrowska

๐Ÿ’ป โš ๏ธ

Yaniv

๐Ÿ’ป โš ๏ธ

Jonathan Pollak

๐Ÿ’ป โš ๏ธ

Ali Taheri Moghaddar

๐Ÿ’ป ๐Ÿ“– โš ๏ธ

garrettberg

๐Ÿ’ป โš ๏ธ

Miles Johnson

๐Ÿ’ป โš ๏ธ

Kevin Weber

๐Ÿ’ป

Justin Dorfman

๐Ÿ”

Royston Shufflebotham

๐Ÿ› ๐Ÿ’ป โš ๏ธ

Oleksandr Fediashov

๐Ÿ’ป

Lingfan Gao

๐Ÿ’ป โš ๏ธ

Miroslav Stastny

๐Ÿ’ป ๐Ÿ“– โš ๏ธ

This project follows the all-contributors specification. Contributions of any kind welcome!

LICENSE

MIT

rtl-css-js's People

Contributors

ahmedelgabri avatar alitaheri avatar allcontributors[bot] avatar andarist avatar andrewmcodes avatar christiango avatar garrettberg avatar jdorfman avatar kentcdodds avatar kevinweber avatar lastw avatar layershifter avatar ling1726 avatar majapw avatar michaeldeboey avatar milesj avatar miroslavstastny avatar palashmon avatar roystons avatar txhawks avatar yzimet avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rtl-css-js's Issues

is this Supported direction property

  • rtl-css-js version:
  • node version:
  • npm (or yarn) version:

Relevant code or config

What you did:

What happened:

Reproduction repository:

Problem description:

Suggested solution:
x change direction property

Support `transition`

  • rtl-css-js version: 1.11.0
  • node version: 10.14.0
  • npm (or yarn) version: 1.15.2

Relevant code or config

{
  toggle: {
    left: 0,
    transition: 'left 300ms, transform: 300ms',
  },

  toggle_checked: {
    left: '100%',
    transform: 'translateX(-100%)',
  },
}

// This converts to
{
  toggle: {
    right: 0,
    transition: 'left 300ms, transform: 300ms',
  },

  toggle_checked: {
    right: '100%',
    transform: 'translateX(100%)',
  },
},

What you did:

^^ Above.

What happened:

Since transition does not convert properties, it causes broken animations.

Reproduction repository:

airbnb/lunar#59

Problem description:

The left in transition does not convert to right, while the left property itself does. This obviously causes broken animations. For the time being I solved it with:

transition: 'left 300ms, right 300ms, transform: 300ms',

Suggested solution:

Convert properties within a transition statement.

Add initial tests

Let's just add a TON of tests here and here to get started. We can get lots of those from relevant tests from: cssjanus.

Once we get that done then we can do #2

No d.ts typescript typings

It would be great to add a d.ts and a typings entry to package.json so that downstream projects with noImplicitAnys can consume the library.

Open to a typescript conversion?

Doesn't handle `null` or `undefined`style values

I have the following code in my app:

import rtlCSSJS from 'rtl-css-js';

const rtlStyles = rtlCSSJS({
  border: null,
  marginLeft: 16px,
  ...
});

The basic idea is that I can't super control the styles that are being passed in and sometimes have a null value for a specific style type. I would expect this to be parsed, but instead it fails pretty dramatically:

Cannot convert undefined or null to object
TypeError: Cannot convert undefined or null to object
    at keys (<anonymous>)
    at Function.keys (webpack:///./~/es5-shim/es5-shim.js?:1103:24)
    at convert (webpack:///./~/rtl-css-js/dist/index.js?:129:17)
    at getValueDoppelganger (webpack:///./~/rtl-css-js/dist/index.js?:176:12)
    at convertProperty (webpack:///./~/rtl-css-js/dist/index.js?:154:42)
    at eval (webpack:///./~/rtl-css-js/dist/index.js?:136:28)
    at Array.reduce (<anonymous>)
    at convert (webpack:///./~/rtl-css-js/dist/index.js?:129:30)

So digging into the source code, what's actually happening is that in order to recurse into the styles object, we check the value type here - https://github.com/kentcdodds/rtl-css-js/blob/master/src/index.js#L259-L261.

Unfortunately, the isObject method (https://github.com/kentcdodds/rtl-css-js/blob/master/src/index.js#L259-L261) just checks for typeof val === 'object', something that's true for null (yay javascript!).

A simple patch would be to change isObject to return val && typeof val === 'object'. I can make a PR for that if you'd like! :)

Doesn't convert margin

I see padding coverted in the tests but not margin. margin: 0 0 0 1px; should autoflip. Seems to be missing.

`object-position` values are not RTL-flipped

  • rtl-css-js version: 1.13.1
  • node version: 10.13.0
  • npm (or yarn) version: npm 6.4.1

Relevant code or config

{ objectPosition: 'left top' }

What you did:

Used a value of left top for the object-position CSS property.

What happened:

rtl-css-js left the value unchanged and did not flip it to right top.

Reproduction repository:
RoystonS@5c0ffa5
(This is a clone of the rtl-css-js repo with some extra unit tests added for this issue.)

Suggested solution:

Update rtl-css-js to support flipping of left and right values in the object-position property.

I'm happy to submit a PR for this. The behaviour seems to be very similar to background-position, including needing to swap a horizontal 10% value to be 90%, etc.

Caveat

object-position accepts horizontal non-percentage length values, e.g. 10px top. These are extremely problematic because there's no facility to flip this to an equivalent RTL value.

Sadly, even in an RTL flow (dir="rtl") environment, this 10px is still interpreted as 'from the left'. Unfortunately there's no way to specify 'n pixels from the right' and a value -10px means 'offset 10px left from the left hand side'. So this value cannot be RTL-flipped at all.

Is it right for rtl-css-js to fail silently on values like this? It's been asked to flip the value, and isn't doing so, and isn't reporting an error or even a warning, even in a non-production build.

Provide an option to pass back resets for styles

Hello @kentcdodds!

For our particular usecase, we don't have access to whether or not we are in the RTL or the LTR context when we call this package. We are instead using rtl-css-js to generate flipped styles and resets that get applied at the same time as the original styles. You can see the code here - https://github.com/airbnb/react-with-styles-interface-aphrodite/blob/master/src/generateRTLStyles.js

The actual generated css down the line is something like:

[dir="rtl"] .inlineStyles_8vmhww {
    margin-right: 16px !important;
    margin-left: initial !important;
}

.inlineStyles_8vmhww {
    margin-left: 16px !important;
}

While we're currently resetting things to initial, we realized that there might be some benefit to having a specific reset value for different styles keys (also initial is bad in general because it doesn't seem to be a thing in IE).

We were thinking this might be a good thing to build into rtl-css-js itself as an option so that you could do something like:

import rtlCSSJS from 'rtl-css-js';

const styles =  { left: 10 };
const flippedStyles = rtlCSSJS(styles, { withResets: true });

and then rtl-css-js could be responsible for choosing the best possible value. I was wondering if this would be something you would be willing to support.

@yzimet @lencioni

Array.Includes is not supported on IE11

  • rtl-css-js version: 1.4.3
  • node version:
  • npm (or yarn) version:

Problem description:

When using rtl-css-js in Internet Explorer 11, line 59 of index.js (https://github.com/kentcdodds/rtl-css-js/blob/master/src/index.js#L59) throws the following exception:

TypeError: Object doesn't support property or method 'includes'

This is because IE doesn't support array.includes (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes)

Suggested solution:

I'm currently working around this by using a polyfill but it could easily be solved using indexOf rather than includes on line 59.

css vars being transformed incorrectly with `textShadow` converter

  • rtl-css-js version: 1.14.1
  • node version: 14
  • npm (or yarn) version: 1.22.x

Relevant code or config

convertProperty('boxShadow', 'var(--shadow16)');

What you did:

Fluent UI's css-in-js engine uses rtl-css-js for its rtl property and value computations. I noticed that css variable names that included numbers were matched by the textShadow property value converter and transformed the name of the css variable

What happened:

var(--shadow16) became var(--shadow-16) which broke all rtl box shadows using Fluent UI.

Reproduction repository:
https://github.com/ling1726/box-shadow-rtl-css-js-repro

Problem description:

See above in What you did

Suggested solution:

This library could consider ignoring rtl doppelganger computations for any value that includes css variables. This is already the case for undefined and boolean values.

I'm also open to push back, if this check should be done by consumers.

Tests for "undefined" values don't seem to run

  • rtl-css-js version: 1.4.0
  • node version: 8.4.0
  • npm (or yarn) version: yarn 1.0.2 and npm 5.4.1

What you did:
yarn test
then t to filter and type undefined

What happened:
No tests are run, despite the fact that several matching the filter exist.

Problem description:
Tests that include an undefined value seem to not be running at all.

Suggested solution:
Not sure, but happy to try and fix if pointed in the right direction

Can't seem to run tests anymore

  • rtl-css-js version: v1.6.0
  • node version: 8.1.4
  • npm (or yarn) version: [email protected]

What you did:

npm run test

What happened:

Running tests gives the following error:

โžœ  rtl-css-js git:(master) โœ— npm run test

> [email protected] test /Users/maja_wichrowska/code/rtl-css-js
> kcd-scripts test

(node:37562) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): TypeError: Path must be a string. Received [ '/Users/maja_wichrowska/code/rtl-css-js' ]
(node:37562) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

This was after a fresh npm install. Any idea what's going on?

Transform of "background: 0" throws

  • rtl-css-js version: 1.14.1
  • node version: N/A
  • npm (or yarn) version: N/A

Relevant code or config

rtlCSSJS({ background: 0 })

What you did:

According to Usage, it's possible to use this package with numeric values, i.e. rtlCSSJS({paddingRight: 23}). However, it does not work with background, it throws an error ๐Ÿ’ฅ

background: 0 is valid CSS rule (https://stackoverflow.com/a/24306798/6488546)

What happened:

image

Reproduction repository:

https://codesandbox.io/s/blissful-http-vgn7s?file=/src/App.js:283-348

Problem description:

I guess that we need an additional handling there:

const backgroundPositionValue = value
.replace(
/(url\(.*?\))|(rgba?\(.*?\))|(hsl\(.*?\))|(#[a-fA-F0-9]+)|((^| )(\D)+( |$))/g,
'',
)
.trim()

Computed properties not working

Expected behavior:

The rtl function should switch the styles.

Describe the bug:

The rtl funcion doesn't switch all the styles.

const useStyles = createUseStyles({
  myButton1: {
    paddingLeft: "16px" โœ…
  },
  myButton2: {
    paddingRight: ({ isMobile }) => (isMobile ? 0 : "26px") โŒ
  },
  myLabel: props => ({
    paddingRight: "8px" โœ…
  })
});

Codesandbox link:

https://codesandbox.io/s/react-jss-playground-37lqs

Building the repo gives `Definition for rule 'no-import-assign' was not found no-import-assign` errors

  • rtl-css-js version: latest code (56d18ab)
  • node version: 10.13.0
  • npm (or yarn) version: 6.4.1

Relevant code or config:

Follow the steps in CONTRIBUTING.md:

  1. Clone repo
  2. npm install
  3. npm run validate

OR

submit a PR and see the Travis build fail.

The error:

/home/travis/build/kentcdodds/rtl-css-js/core.esm.js
[lint]   1:1  error  Definition for rule 'no-import-assign' was not found  no-import-assign

Looks like we have an eslint configuration that doesn't match the version of eslint.

There's neither a yarn nor an npm lock file in this repo so it will float to latest deps on install.

Reproduction repository:
This repo. ;-)

Suggested solution:
Some sort of dependencies update - I can't quite tell which bits are inside kcd-scripts and which bits aren't, at a cursory glance.

๐Ÿ› Support transform translate calc

The result seems to be wrong when I use translateX(calc(...)) and translate(calc(...), ...)

const styles = rtlCSSJS({transform: 'translateX(calc(-50% - 20px))'});
console.log(styles) // logs {transform: "translateX(calc(-50% - 20px))"}

In my opinion, the result should be {transform: "translateX(calc(50% + 20px))"}

I checked transform: translateX(20px) and the result is completely correct as transform: translateX(-20px)

Images I tested with CSS:

image

โœ”๏ธ
image

โŒ
image

usage of rtl-css-js/core throws in ESM packages

  • rtl-css-js version: 1.16.0
  • node version: v16.14.0
  • npm (or yarn) version: N/A

Relevant code or config

// index.js
import * as c from 'rtl-css-js/core';
console.log(c);
{
  "name": "node-starter",
  "version": "0.0.0",
  "type": "module",
  "dependencies": {
    "rtl-css-js": "^1.16.0"
  }
}

What you did: node index.js

What happened:

node:internal/process/esm_loader:94
    internalBinding('errors').triggerUncaughtException(
                              ^

Error [ERR_UNSUPPORTED_DIR_IMPORT]: Directory import '/node_modules/rtl-css-js/core' is not supported resolving ES modules imported from /index.js
Did you mean to import rtl-css-js/dist/cjs/core.js?
    at new NodeError (node:internal/errors:371:5)
    at finalizeResolution (node:internal/modules/esm/resolve:414:17)
    at moduleResolve (node:internal/modules/esm/resolve:981:10)
    at defaultResolve (node:internal/modules/esm/resolve:1078:11)
    at ESMLoader.resolve (node:internal/modules/esm/loader:530:30)
    at ESMLoader.getModuleJob (node:internal/modules/esm/loader:251:18)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:79:40)
    at link (node:internal/modules/esm/module_job:78:36) {
  code: 'ERR_UNSUPPORTED_DIR_IMPORT',
  url: 'file:///node_modules/rtl-css-js/core'
}

Reproduction repository: https://stackblitz.com/edit/node-hlunhf?file=package.json,index.js
tip: You can run node directly there in a terminal

Problem description: ESM in node requires explicit imports, however obviously no one wants to import rtl-css-js/dist/esm/core.js directly.
Suggested solution: Add exports field to define exports.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.