Code Monkey home page Code Monkey logo

ember-style-modifier's Introduction

ember-style-modifier

CI Ember Observer Score npm version

This addon provides a {{style}} element modifier to set element's style. This allows to set custom CSS of an element without requiring a Content Security Policy style-src-attr: "unsafe-inline".

Compatibility

  • Ember.js v3.28 or above
  • Ember CLI v3.28 or above
  • Node.js v18 or above

Installation

ember install ember-style-modifier

Usage

It expects CSS declarations as named arguments or as a hash as positional argument. Property names are supported in dasherized as well as in camelCase spelling. Value must be a string or undefined. You may set a priority by adding an "!important" suffix.

<p
  {{style
    border="1px"
    padding="1em !important"
  }}
>
</p>

<p
  {{style
    (hash border="1px" padding="1em !important")
  }}
>
</p>

You may pass multiple hashes as positional arguments and combine hashes with named arguments. If multiple hashes are passed and contain CSS declarations for the same property, last one wins. If hashes and named arguments declare same property, named argument wins.

Adding styles to pseudo-elements is not supported.

Known limitations

Ember Style Modifier suffers from two known limitations of Modifiers in Ember. Both need to be addressed by extending modifiers capabilities. Doing so, is discussed in a RFC issue.

Server-side rendering is not supported

Modifiers do not run in server-side rendering (SSR). Styles set using ember-style-modifier are therefore not applied if application is run with FastBoot or prerendered using Prember. This may lead to wrong layout before rehydration and layout shifts on rehydration.

Browser may paint the element twice on initial render

Modifiers run after browser has printed the page. If styles are applied to an elements immediately, the browser first renders the element without those styles applied and immediately afterwards with these styles applied.

This may theoretically cause the experience of a flickering user interface. But such a case has not been noticed yet in practice.

Rendering the element twice has a performance impact. But it should not have any noticeable impact in practice.

Contributing

See the Contributing guide for details.

License

This project is licensed under the MIT License.

ember-style-modifier's People

Contributors

andreyfel avatar bertdeblock avatar boris-petrov avatar buschtoens avatar dependabot[bot] avatar drewpereli avatar ember-tomster avatar jelhan avatar mansona avatar mkszepp avatar renovate-bot avatar renovate[bot] avatar sergeastapov avatar techn1x 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

Watchers

 avatar  avatar  avatar

ember-style-modifier's Issues

Better error message for: "Uncaught Error: Assertion Failed: Value must be a string or undefined, number given"

I had this object:

elementStyle = {
    position: 'fixed',
    bottom: 0,
    'margin-bottom': 0,
    width: '100%'
};

Which I passed to the {{style}} modifier <div {{style this.elementStyle}}>. That gave me the error message:

Uncaught Error: Assertion Failed: Value must be a string or undefined, number given

Where my initial thought was: "hey... I passed an object, neither string nor number - what's happening". Actually, it was complaining about 0 in bottom: 0 not beeing a string but a number. Maybe 0 is special ;) however the error message could be way better, should at least say "the value for rule xyz" πŸ‘

Support type-coercion to strings

I got this well known error:

Error: Assertion Failed: Your given value for property '--left' is 0 (number). 
Accepted types are string and undefined. Please change accordingly.

Which is quite explicit in the code, but I am curious why. If there's one thing I can count on JavaScript for, it's turning things into strings.

By not allowing type-coercion, I now have to do this casting in my code, which means introducing a helper for the sole purpose of .toString.

Here's my actual code to illustrate how quickly doing this in JS isn't really an option:

<div
  {{style
    --left=(scale-fn-compute xScale this.activeDatum.startTime)
    --top=(scale-fn-compute yScale this.activeDatum.count)
  }}
>

Which will become this for now

<div
  {{style
    --left=(str (scale-fn-compute xScale this.activeDatum.startTime))
    --top=(str (scale-fn-compute yScale this.activeDatum.count))
  }}
>

peseudoselectors support

It will be great to have :before, :after pseudoselectors support for usecases like

<div {{style ":before" content=this.someText}} />

investigate if value must be escaped

Must the value be escaped before passing it to CSSStyleDeclaration.setProperty()? Or is it enough to limit it's type to strings and undefined?

CSS Object Model defines a CSS.escape() method but that one seems to be meant for identifiers only. There is a cssesc library "for escaping text for use in CSS strings or identifiers while generating the shortest possible valid ASCII-only output. Here’s an online demo." But it's not clear to my if this is also needed for CSSStyleDeclaration.setProperty(). All examples are about escaping a string which is inserted in a style sheet.

If I got the spec right, there is no need to escape the string in anyway if passed to setProperty(). But as I'm not an expert on this topic and it might open up security issues, I leave this issue open for further investigations.

Road to v1

The public API hasn't changed for a long time.

Not having a v1 release makes it more challenging for addon authors to rely on ember-style-modifier in their own addon. As every v0.x release could include a breaking change, they must upgrade ember-style-modifier explicitly every time a new v0.x release has been published. For consumers of such addons it may even get worse as different addons may require incompatible SemVer ranges. E.g. one dependency may be upgraded to ~0.8.0 already while another still declares ~0.7.0. Consumer may need to use yarn resolutions or a similar tool to force a predictable version.

This issue lists the work needed to be done before releasing a v1.

  • Upgrade dependencies
  • Verify that CI is green
  • Verify that no deprecations are triggered
  • Review supported versions of Ember and Ember CLI
  • Review supported versions of node.js
  • Drop support for node 12
  • Drop support for Ember < 3.28
  • Document known limitations for server-side rendering / FastBoot #11
  • Document that styles are applied after element is attached to DOM and potential impact (performance, flickering UI, CSS animations)

Update to `ember-modifier` v3

ember-modifier v3 has been released. I tried updating it in my app but then ember serve gave me:

ATTENTION: ember-cli-addon-guard has prevented your application from building!

Please correct the following errors:

Your application is dependent on multiple versions of the following run-time addon:

ember-modifier
----------------------------------------
frontend
β”œβ”€β”€ [email protected] (cacheKey: ab9c44defd35e1aa4d263e37f5cb1db2, runtime: true)
└─┬ ember-style-modifier
  └── [email protected] (cacheKey: 75635b586f7febfc54c7ed2c66531ec4, runtime: true)

It would be nice if ember-style-modifier updates it too so I can use it in my app.

active/focus states support

It will be great to have :active, :focus pseudoselectors support for usecases like

<div {{style ":active" background-color="blue"}} />

breaks ember-basic-dropdown

It seems that installing this component breaks the following other components, which depend on ember-basic-dropdown:

  • ember-power-select
  • ember-power-calendar

This for sure could be an issue of ember-basic-dropdown and I'll leave an issue there too.

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Awaiting Schedule

These updates are awaiting their schedule. Click on a checkbox to get an update now.

  • chore(deps): lock file maintenance

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

github-actions
.github/workflows/ci.yml
  • actions/checkout v4
  • wyvox/action-setup-pnpm v3
  • actions/checkout v4
  • wyvox/action-setup-pnpm v3
  • actions/checkout v4
  • wyvox/action-setup-pnpm v3
npm
ember-style-modifier/package.json
  • @embroider/addon-shim ^1.8.7
  • decorator-transforms ^2.0.0
  • csstype ^3.1.3
  • ember-modifier ^3.2.7 || ^4.0.0
  • @babel/core ^7.23.6
  • @babel/plugin-transform-typescript ^7.23.6
  • @babel/runtime ^7.17.0
  • @embroider/addon-dev ^5.0.0
  • @glint/core ^1.2.1
  • @glint/environment-ember-loose ^1.2.1
  • @glint/environment-ember-template-imports ^1.2.2
  • @glint/template ^1.2.2
  • @rollup/plugin-babel ^6.0.4
  • @tsconfig/ember ^3.0.2
  • @types/ember ^4.0.10
  • @types/ember__application ^4.0.10
  • @types/ember__array ^4.0.9
  • @types/ember__component ^4.0.21
  • @types/ember__controller ^4.0.11
  • @types/ember__debug ^4.0.7
  • @types/ember__destroyable ^4.0.4
  • @types/ember__engine ^4.0.10
  • @types/ember__error ^4.0.5
  • @types/ember__helper ^4.0.5
  • @types/ember__modifier ^4.0.8
  • @types/ember__object ^4.0.11
  • @types/ember__owner ^4.0.8
  • @types/ember__polyfills ^4.0.5
  • @types/ember__routing ^4.0.19
  • @types/ember__runloop ^4.0.8
  • @types/ember__service ^4.0.8
  • @types/ember__string ^3.16.3
  • @types/ember__template ^4.0.5
  • @types/ember__test ^4.0.5
  • @types/ember__utils ^4.0.6
  • @typescript-eslint/eslint-plugin ^7.0.0
  • @typescript-eslint/parser ^7.0.0
  • babel-plugin-ember-template-compilation ^2.2.1
  • concurrently ^8.2.2
  • ember-template-lint ^6.0.0
  • eslint ^8.56.0
  • eslint-config-prettier ^9.1.0
  • eslint-plugin-ember ^12.0.0
  • eslint-plugin-n ^17.0.0
  • eslint-plugin-prettier ^5.0.1
  • prettier ^3.1.1
  • prettier-plugin-ember-template-tag ^2.0.0
  • rollup ^4.9.1
  • typescript ^5.3.3
  • @ember/string ^3.1.1 || ^4.0.0
  • ember-source ^3.28.0 || ^4.0.0 || >=5.0.0
package.json
  • @release-it-plugins/lerna-changelog ^7.0.0
  • @release-it-plugins/workspaces ^4.0.0
  • concurrently ^8.2.0
  • prettier ^3.0.3
  • prettier-plugin-ember-template-tag ^2.0.0
  • release-it ^17.0.0
  • node 18.* || >= 20
  • @types/eslint ^8.0.0
test-app/package.json
  • @babel/core ^7.23.6
  • @ember/optional-features ^2.0.0
  • @ember/string ^4.0.0
  • @ember/test-helpers ^3.2.1
  • @embroider/test-setup ^4.0.0
  • @glimmer/component ^1.1.2
  • @glimmer/tracking ^1.1.2
  • @glint/core ^1.2.2
  • @glint/environment-ember-loose ^1.2.2
  • @glint/environment-ember-template-imports ^1.2.1
  • @glint/template ^1.2.2
  • @tsconfig/ember ^3.0.2
  • @types/ember ^4.0.10
  • @types/ember__application ^4.0.10
  • @types/ember__array ^4.0.9
  • @types/ember__component ^4.0.21
  • @types/ember__controller ^4.0.11
  • @types/ember__debug ^4.0.7
  • @types/ember__destroyable ^4.0.4
  • @types/ember__engine ^4.0.10
  • @types/ember__error ^4.0.5
  • @types/ember__helper ^4.0.5
  • @types/ember__modifier ^4.0.8
  • @types/ember__object ^4.0.11
  • @types/ember__owner ^4.0.8
  • @types/ember__polyfills ^4.0.5
  • @types/ember__routing ^4.0.19
  • @types/ember__runloop ^4.0.8
  • @types/ember__service ^4.0.8
  • @types/ember__string ^3.16.3
  • @types/ember__template ^4.0.5
  • @types/ember__test ^4.0.5
  • @types/ember__utils ^4.0.6
  • @types/qunit ^2.19.9
  • @types/rsvp ^4.0.8
  • @typescript-eslint/eslint-plugin ^7.0.0
  • @typescript-eslint/parser ^7.0.0
  • broccoli-asset-rev ^3.0.0
  • concurrently ^8.2.2
  • ember-auto-import ^2.7.0
  • ember-cli ~5.10.0
  • ember-cli-app-version ^7.0.0
  • ember-cli-babel ^8.2.0
  • ember-cli-clean-css ^3.0.0
  • ember-cli-dependency-checker ^3.3.2
  • ember-cli-htmlbars ^6.3.0
  • ember-cli-inject-live-reload ^2.1.0
  • ember-cli-sri ^2.1.1
  • ember-cli-terser ^4.0.2
  • ember-eslint-parser ^0.5.0
  • ember-fetch ^8.1.2
  • ember-load-initializers ^2.1.2
  • ember-modifier ^4.1.0
  • ember-page-title ^8.1.0
  • ember-qunit ^8.0.2
  • ember-resolver ^11.0.1
  • ember-source ~5.11.0
  • ember-source-channel-url ^3.0.0
  • ember-template-imports ^4.0.0
  • ember-template-lint ^6.0.0
  • ember-try ^3.0.0
  • eslint ^8.55.0
  • eslint-config-prettier ^9.1.0
  • eslint-plugin-ember ^12.0.0
  • eslint-plugin-n ^17.0.0
  • eslint-plugin-prettier ^5.0.1
  • eslint-plugin-qunit ^8.0.1
  • loader.js ^4.7.0
  • prettier ^3.1.1
  • prettier-plugin-ember-template-tag ^2.0.0
  • qunit ^2.20.0
  • qunit-dom ^3.0.0
  • stylelint ^16.0.0
  • stylelint-config-standard ^36.0.0
  • stylelint-prettier ^5.0.0
  • tracked-built-ins ^3.3.0
  • typescript ^5.3.3
  • webpack ^5.89.0
  • node >= 18

  • Check this box to trigger a request for Renovate to run again on this repository

Discuss issues in SSR in README (investigate mitigation)

Since element modifiers do not run at all in SSR / FastBoot mode, we should discuss in the README the caveats an app may have when using this addon. Specifically, if you use {{style}} those styles will not be present when the app is ran via SSR/FastBoot.

There are a few plausible ways to mitigate this, I'd love to have a discussion to help make a path forward...

Types allow numbers to be passed but at runtime it doesn't work

<div {{style scale=1}}></div>

This compiles fine (as PropertiesHyphen from csstype allows it) but at runtime it breaks. Not that big of an issue but would be nice to somehow fix. Not sure how though. Perhaps the best way would be to make the style modifier work with other values not just string. Not sure why it was done so. Otherwise the types from csstype should somehow be augmented which probably won't be simple and will be brittle.

Convert addon to v2 & allow older ember-source versions than 4.12

While updating ember-basic-dropdown to a V2 addon, i have seen that this addon is atm a V1 addon.
I would like that ember-basic-dropdown brings early / later all dependencies as addon V2 (better earlier πŸ˜…).

Is there planned to port this addon to V2? I think that its very easy for this addon, because the addon is very lite.
The requirement for V2 addon is ember-auto-import v2 or embroider (see Addon V2 RFCS)

The other idea is to allow also older ember-source (atm v4.12+ is required). This means that only latest 2 LTS versions are supported. I don't understand why this is necessary... Is there any reason?
All dependency packages are allowing at least v3.28+... so would be great that we can also support this addon for older ember apps.

If you need any help to convert to V2 please let me know.

Support conditionally usage of modifier

The modifier does not have cleanup logic. In most cases that's okay. The element is destroyed anyways when modifier is removed. But it likely breaks when the modifier is applied conditionally.

Adding cleanup logic in a destructor may have negative impact on performance. See emberjs/rfcs#1007 (comment) on that topic. We should investigate the trade-off before shipping.

Conditionally applying this modifier does not seem to be a common case. At least no one reported a bug regarding missing cleanup. We should make sure to not harm everyone for a theoretical bug affecting no actual use case.

can not install v0.6.0 with npm or yarn

It's very strange that I can't install [email protected] with npm or yarn, but I can see this version appears on the npmjs.com website, how is this possible?

This is what I saw when it failed:

npm ERR! code ETARGET
npm ERR! notarget No matching version found for ember-style-modifier@^0.6.0.
npm ERR! notarget In most cases you or one of your dependencies are requesting
npm ERR! notarget a package version that doesn't exist.

BTW I've tried yarn cache clean or npm cache clean --force, doesn't work either.

Refactor away from ember-functional-modifiers

// Store holds information which properties were set
// for an element (key) in last run. This allows us
// to clean up properties that were set but aren't
// present in options hash anymore.
const STORE = new WeakMap();

This is a clear indicator that this modifier is in fact not functional / a pure function. πŸ˜„

I would suggest to refactor this to not use ember-functional-modifiers (even though it's great!) and instead interact with the manager and state bucket directly. I'm doing this in ember-on-modifier for instance.

I'd be happy to submit a PR as well, if you like.

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.