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

@cloudcreativity/ember-quill

v1.0.0-alpha.2

Published

The default blueprint for ember-cli addons.

Downloads

561

Readme

@cloudcreativity/ember-quill

The Quill rich text editor for Ember.

Compatibility

  • Ember.js v3.16 or above
  • Ember CLI v2.13 or above
  • Node.js v10 or above

Installation

ember install @cloudcreativity/ember-quill

Usage

Contents

Introduction

This addon provides components for working with the Quill rich text editor in Ember.

Examples

Use the <Quill> component to create your toolbar and editor:

<Quill as |Ql|>
  <Ql.toolbar as |Tb|>
    <Tb.group>
      <Tb.bold />
      <Tb.italic />
      <Tb.underline />
    </Tb.group>
    <Tb.group>
      <Tb.list value="ordered" />
      <Tb.list value="bullet" />
    </Tb.group>
  </Ql.toolbar>

  <Ql.editor
    @delta={{this.delta}}
    @focused={{true}}
    @onChange={{this.setDelta}}
    @placeholder="Tell us your story."
    @theme="snow"
  />

  <div>
    Characters: {{Ql.characters}}<br>
    Words: {{Ql.words}}
  </div>
</Quill>

Or just use the <QuillEditor> component by itself:

<QuillEditor
  @delta={{this.delta}}
  @onChange={{this.setDelta}}
  @placeholder="Tell us your story."
  @theme="snow"
/>

Quill Component

The <Quill> component is a wrapper component that allows you to create the editor's toolbar via HTML. It ensures that the editor is wired correctly to use the HTML toolbar.

In addition, the <Quill> component yields the length and number of words of the editor contents, so that you can display these to the user if desired.

Toolbar

Use the yielded toolbar to build your editor's toolbar, for example:

<Quill as |Ql|>
  <Ql.toolbar as |Tb|>
    <Tb.bold />
    <Tb.italic />
  </Ql.toolbar>
</Quill>

The toolbar yields components for all the toolbar controls supported by Quill. These are either <button> and/or <select> elements. The supported controls are:

| Control | Type | | --- | --- | | align | <button> or <select> | | background | <select> | | blockquote | <button> | | bold | <button> | | clean | <button> | | code-block | <button> | | code | <button> | | color | <select> | | direction | <button> | | font | <select> | | formula | <button> | | header | <button> or <select> | | image | <button> | | indent | <button> | | italic | <button> | | link | <button> | | list | <button> | | script | <button> | | size | <select> | | strike | <button> | | underline | <button> | | video | <button> |

For <button> elements, set the value attribute if required. For example, the bold button does not need a value, but the list button does:

<Tb.bold />
<Tb.list value="ordered" />
<Tb.list value="bullet" />

For <select> elements, provide the list of values using the @value argument with the {{array}} helper:

<Tb.size @values={{array "small" false "large" "huge"}} />

Provide an empty value if you want to use the theme's default values. For example, the Snow theme provides a list of 35 colors for the color and background toolbar options. To use the defaults:

<Tb.color />
<Tb.background />

Some controls, e.g. header, work as either <button> or <select> elements. For these, you must provide a @values argument if you want to use a <select>. Otherwise a <button> will be used. For example:

<!-- Header Buttons -->
<Tb.header value="1" />
<Tb.header value="2" />

<!-- Header Select -->
<Tb.header @values={{array 1 2 3 4}} />

<!-- Header Select with Theme Defaults -->
<Tb.header @values={{array}} />

The group component allows you to group controls, i.e. add space between sets of controls. This is done by using a <span> with the ql-formats class:

<Tb.group>
  <Tb.bold />
  <Tb.italic />
</Tb.group>
<Tb.group>
  <Tb.list value="ordered" />
  <Tb.list value="bullet" />
</Tb.group>

Editor

Use the yielded editor to create the container <div> for the Quill Editor. This is automatically configured with the selector for your HTML toolbar:

<Quill as |Ql|>
  <Ql.toolbar>
    <!-- toolbar -->
  </Ql.toolbar>
  <Ql.editor @theme="snow" />
</Quill>

The yielded <Ql.editor> is an instance of the <QuillEditor> component. This component, along with all of its options, is described below.

Values

The <Quill> components also yields the following values:

| Value | Description | | --- | --- | | length | The length of editor content, provided by Quill's getLength method. | | characters | The length minus one. | | words | The number of words in the editor content. |

When the Quill Editor is empty, there is always a blank line representated by \n. This means Quill's getLength method always returns 1 for an empty editor. Typically if you want to display the length to users, you would need to subtract 1 from the length. This is why we yield both the length and the characters values.

For example, to display the number of words to the user:

<Quill as |Ql|>
  <!-- Toolbar and Editor -->

  Words: {{Ql.words}}
</Quill>

Quill Editor Component

The <QuillEditor> component can be used by itself if you do not want to define your toolbar in HTML. All the options described here can also be used when displaying the editor within the <Quill> component.

Configuration

The following Quill configuration options are supported when initialising Quill:

  • bounds
  • debug
  • formats
  • modules
  • placeholder
  • readOnly
  • scrollingContainer
  • theme

For example:

<QuillEditor @formats={{array "bold" "italic"}} @theme="snow" />

Quill does not provide a way of changing these values after initialisation. Therefore, changing these values after the component has been rendered is not supported.

Enabled

The <QuillEditor> component accepts an @enabled argument. Changing this value allows you to toggle whether the editor is enabled or not.

For example:

<QuillEditor @enabled={{not this.formIsDisabled}} />

The {{not}} helper is provided by the Ember Truth Helpers addon.

Focused

The @focused argument allows you to give the editor focus when it is rendered. For example:

<QuillEditor @focused={{true}} />

Delta

Use the @delta argument to provide the initial value of the editor using a Quill Delta. This is one-way bound: to subscribe to changes to the delta, use the onChange action:

<QuillEditor @delta={{this.delta}} @onChange={{this.setDelta}} />

The value you provide for the @delta argument does not need to be a Quill Delta instance. The editor's setContents method that is used to set the delta does accept the delta JSON.

Text

If you want to use plain text to set the initial value of the editor, use the @text argument. This is one-way bound: to subscribe to changes to the text, use the onText action:

<QuillEditor @text={{this.text}} @onText={{this.setText}} />

If you provide a value to the @delta argument, the @text argument will be ignored.

Events

To subscribe to Quill events, use the following actions:

| Quill Event | Action | | --- | --- | | text-change | @onTextChange | | selection-change | @onSelectionChange | | editor-change | @onEditorChange |

We also provide the following custom events:

| Action | Description | | --- | --- | | @onChange | Provides the updated delta for the editor, provided by Quill's getContents method. | | @onText | Provides the updated editor text, provided by Quill's getText method. | | @onLength | Provides the length of the editor content, provided by Quill's getLength method. | | @onWords | Provides the number of words in the editor content. |

Warning: If you are using the <Quill> component, the @onLength and @onWords actions are already wired up to provide the yielded length, characters and words values. If you use the @onLength or @onWords actions, the yielded values will NOT update.

Quill Service

If you need to interact with a Quill editor programmatically, you can do this via the Quill service.

All Quill instances are registered with the service using a name. To interact with an instance, provide the @name argument to the <QuillEditor> component, making sure that the name is unique for each editor you have rendered.

For example:

<Quill as |Ql|>
  <!-- Toolbar -->
  <Ql.editor @name="my-editor" />
</Quill>

<QuillEditor @name="other-editor" />

Then inject the service, for example:

import Component from '@glimmer/component';
import { inject as service } from '@ember/service';
import { action } from '@ember/object';

export default class CustomComponent extends Component {
  @service('quill') quillService;

  @action
  resetEditor() {
    this.quillService.setText('my-editor', '');
  }
}

The service provides all the following Quill methods. Each takes the name of the editor instance, followed by the arguments as defined in the Quill API documentation.

  • deleteText
  • getContents
  • getLength
  • insertEmbed
  • insertText
  • setContents
  • setText
  • updateContents
  • format
  • formatLine
  • formatText
  • getFormat
  • removeFormat
  • getBounds
  • getSelection
  • blur
  • disable
  • enable
  • focus
  • hasFocus
  • update

If you use the disable or enable methods, the @enabled argument on the <QuillEditor> component will get out-of-sync. We recommend using the @enabled argument rather than the methods via the service.

As Quill editor instances are deregistered from the service when the <QuillEditor> component is being destroyed, any methods that return values will return null if the named editor does not exist on the Quill service.

If you need to call multiple methods on a Quill instance, you can use the service's instance method to retrieve the named editor. This will return null if the editor is no longer registered:

const quill = this.quillService.instance('my-editor');

if (quill) {
  // ...
}

Quill Static Methods

To call static Quill methods, import Quill as follows:

import Quill from 'quill';

var Module = Quill.import('core/module');

class CustomModule extends Module {}

Quill.register('modules/custom-module', CustomModule);

Testing

All Quill event handlers are executed via the Ember runloop, to ensure that you can easily use your Quill components in tests.

Use the fillIn test helper with the .ql-editor selector:

test('it renders', async function (assert) {
  this.set('delta', {
    ops: [
      { insert: 'This is my story.\n'}
    ],
  });

  await render(hbs`
    <QuillEditor
      @delta={{this.delta}}
      @onChange={{action (mut this.delta)}}
    />
  `);

  assert.dom('.ql-editor').hasText('This is my story.');

  await fillIn('.ql-editor', 'This is my other story.');

  assert.deepEqual(this.delta.ops, [
    { insert: 'This is my other story.\n' },
  ]);
});

Contributing

See the Contributing guide for details.

License

This project is licensed under the MIT License.