npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

ember-sidenotes

v1.3.1

Published

Ember addon inspired by curvenote/sidenotes which position vertically cards next to targetted text

Downloads

99

Readme

ember-sidenotes

An easy way to place side notes with a vertical reference position for EmberJS (inspired by https://github.com/curvenote/sidenotes)

Compatibility

  • Ember.js v3.20 or above
  • Ember CLI v3.20 or above
  • Node.js v12 or above

Installation

ember install ember-sidenotes

Usage

This is a basic example of what this addon allow you to do.

<SidenotesWrapper @items={{this.items}} as |Sidenote item|>
  <Sidenote @id={{item.id}} @offsetY={{item.y}} @data={{item.data}} as |s|>
    <p>
      {{item.data.content}}
    </p>
    {{#if s.isActive}}
      <button type='button' {{on 'click' s.unselect}}>Unselect</button>
    {{else}}
      <button type='button' {{on 'click' s.select}}>Select</button>
    {{/if}}
  </Sidenote>
</SidenotesWrapper>

There are two ways of using this addon, controlled and non-controlled mode.

Controlled & Non-controlled modes

Controlled mode

The controlled mode makes it possible to managed which side note is selected with an argument named selectedSidenoteId. This has to match the argument id passed to a component <Sidenote @id={{...}} />.

As two actions select and unselect are exposed in each sidenote component, calling them will raise an action on the wrapper (respectively onSelect and onUnselect) with all the data necessary to be aware of which sidenote has been selected ({ element, id, offsetY, data }).

Then, this is your job to mutate your argument selectedSidenoteId to make the new sidenote selected.

MyComponent.hbs

<SidenotesWrapper
  @items={{this.items}}
  @onSelect={{this.onSelect}}
  @onUnselect={{this.onUnselect}}
  @selectedSidenoteId={{this.selectedSidenoteId}}
  as |Sidenote item|
>
  <Sidenote @id={{item.id}} @offsetY={{item.y}} @data={{item.data}} as |s|>
    {{#if s.isActive}}
      <button type='button' {{on 'click' s.unselect}}>Unselect</button>
    {{else}}
      <button type='button' {{on 'click' s.select}}>Select</button>
    {{/if}}
  </Sidenote>
</SidenotesWrapper>

MyComponent.js

export default class MyComponent extends Component {
  @tracked items = [
    { id: 1, offsetY: 104, data: null },
    // ...
  ];

  @action
  onSelect({ id }) {
    this.selectedSidenoteId = id;
  }

  @action
  onUnselect() {
    this.selectedSidenoteId = null;
  }
}

Non-controlled mode

The non-controlled mode is the way to use this addon in a simpler way. The selected sidenote will be handled internally by the components.

Both select and unselect actions will raised the matching action on the wrapper (respectively onSelect and onUnselect) but only for notify purpose.

You can also specify a defaultSidenoteId argument to the wrapper to choose the sidenote selected on component load. If it's not specified or the one specified does not match any sidenote, this will default to the first sidenote.

MyComponent.hbs

<SidenotesWrapper
  @defaultSidenoteId={{6}}
  @items={{this.items}}
  as |Sidenote item|
>
  <Sidenote @id={{item.id}} @offsetY={{item.y}} @data={{item.data}} as |s|>
    {{#if s.isActive}}
      <button type='button' {{on 'click' s.unselect}}>Unselect</button>
    {{else}}
      <button type='button' {{on 'click' s.select}}>Select</button>
    {{/if}}
  </Sidenote>
</SidenotesWrapper>

MyComponent.js

export default class MyComponent extends Component {
  @tracked items = [
    { id: 1, offsetY: 104, data: null },
    // ...
    { id: 6, offsetY: 495, data: null },
  ];
}

Components details

SidenotesWrapper

| Argument | Type | Default | Mode | Description | | ----------------- | ------ | ------- | -------------- | ------------------------------------------------------------------------------------------------------------------ | | activeSidenoteId | Number | null | Controlled | Selected sidenote id (presence of this property will enable controlled mode) | | defaultSidenoteId | Number | null | Non-controlled | Default selected sidenote id on wrapper load | | gutter | Number | 0 | Both | Vertical spacing added between every sidenotes | | key | String | '@identity' | Both | Key passed to #each helper when iterating over @items. It will be used to determine if render is needed on change (See #each doc cf. 'Specifying keys') | | items | Array | - | Both | List of items corresponding to wanted sidenotes | | onSelect | Action | - | Both | Action raised when using select exposed action on Sidenote component | | onSidenotesMoved | Action | - | Both | Action raised after sidenotes finished moving (called after load, selection, unselection, or sidenote size change) | | onUnselect | Action | - | Both | Action raised when using unselect exposed action on Sidenote component |

This component expose two variables.

  • [0] is a Sidenote component instance
  • [1] is the current item to process (as SidenotesWrapper iterate over @items)

Sidenote

| Argument | Type | Default | Description | | -------- | ------ | ------- | --------------------------------------------------------------------------------------------------- | | id | Number | - | Sidenote id used as the unique identifier of this sidenote (should be unique) | | offsetY | Number | - | Preferred vertical position of the sidenote (the sidenote will position at this offset if possible) | | data | Any | - | Custom data (this will be passed to @onSelect and @onUnselect of the wrapper) |

This component expose one variable which has 3 properties

  • isActive is a boolean value that reflects if current sidenote is the one selected
  • select is an action to use to select current sidenote (will behave differently depending on the mode used)
  • unselect is an action to use to unselect current sidenote (will behave differently depending on the mode used)

Contributing

See the Contributing guide for details.

License

This project is licensed under the MIT License.