Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 22 additions & 22 deletions docs/_guide/actions.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,21 @@ Remember! Actions are _automatically_ bound using the `@controller` decorator. T
<div class="">

```html
<hello-controller>
<hello-world>
<input
data-target="hello-controller.name"
data-target="hello-world.name"
type="text"
>

<button
data-action="click:hello-controller#greet">
data-action="click:hello-world#greet">
Greet
</button>

<span
data-target="hello-controller.output">
data-target="hello-world.output">
</span>
</div>
</hello-world>
```

</div>
Expand All @@ -51,7 +51,7 @@ Remember! Actions are _automatically_ bound using the `@controller` decorator. T
import { controller, target } from "@github/catalyst"

@controller
class HelloController extends HTMLElement {
class HelloWorldElement extends HTMLElement {
@target nameTarget: HTMLElement
@target outputTarget: HTMLElement

Expand All @@ -78,40 +78,40 @@ The actions syntax follows a pattern of `event:controller#method`.
Multiple actions can be bound to multiple events, methods, and controllers. For example:

```html
<analytics-controller>
<hello-controller>
<analytics-tracking>
<hello-world>
<input
data-target="hello-controller.name"
data-target="hello-world.name"
data-action="
input:hello-controller#validate
blur:hello-controller#validate
focus:analytics-controller#hover
input:hello-world#validate
blur:hello-world#validate
focus:analytics-tracking#hover
"
type="text"
>

<button
data-action="
click:hello-controller#greet
click:analytics-controller#click
hover:analytics-controller#hover
click:hello-world#greet
click:analytics-tracking#click
hover:analytics-tracking#hover
"
>
Greet
</button>
</hello-controller>
</analytics-controller>
</hello-world>
</analytics-tracking>
```

### Custom Events

A Controller may emit custom events, which may be listened to by other Controllers using the same Actions Syntax. There is no extra syntax needed for this. For example a `lazy-controller` may dispatch a `loaded` event, once its contents are loaded, and other controllers can listen to this event:
A Controller may emit custom events, which may be listened to by other Controllers using the same Actions Syntax. There is no extra syntax needed for this. For example a `lazy-load` Controller may dispatch a `loaded` event, once its contents are loaded, and other controllers can listen to this event:

```html
<hover-card disabled>
<lazy-controller data-url="/user/1" data-action="loaded:hover-card#enable">
<lazy-load data-url="/user/1" data-action="loaded:hover-card#enable">
<loading-spinner>
</lazy-controller>
</lazy-load>
</hover-card>
```

Expand All @@ -123,7 +123,7 @@ Actions can always be bound to any method that is available on the Controller's
import {controller} from '@github/catalyst'

@controller
class HelloController extends HTMLElement {
class HelloWorldElement extends HTMLElement {

hidden = () => {
console.log('data-action cannot call this hidden method, but other JavaScript can!')
Expand All @@ -145,7 +145,7 @@ If you're not using decorators, then you'll need to call `bind(this)` somewhere
```
import {bind} from '@github/catalyst'

class HelloController extends HTMLElement {
class HelloWorldElement extends HTMLElement {

connectedCallback() {
bind(this)
Expand Down
8 changes: 4 additions & 4 deletions docs/_guide/decorators.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ Catalyst comes with the `@controller` decorator. This gets put on top of the cla

```js
@controller
class MyController extends HTMLElement {}
class HelloWorldElement extends HTMLElement {}
```

### Class Field Decorators

Catalyst comes with the `@target` and `@targets` decorators for more [read about Targets](/guide/targets). These get added on top or to the left of the field name, like so:

```js
class MyController extends HTMLElement {
class HelloWorldElement extends HTMLElement {

@target something

Expand All @@ -43,7 +43,7 @@ Catalyst doesn't currently ship with any method decorators, but you might see th


```js
class MyController extends HTMLElement {
class HelloWorldElement extends HTMLElement {

@log
submit() {
Expand All @@ -64,7 +64,7 @@ class MyController extends HTMLElement {
Some decorators are customisable - they get called with additional arguments, just like a function call. An example of this is the `@debounce` decorator in the [`@github/mini-throttle`](https://github.com/github/mini-throttle) package:

```js
class MyController extends HTMLElement {
class HelloWorldElement extends HTMLElement {

@debounce(100)
handleInput() {
Expand Down
36 changes: 18 additions & 18 deletions docs/_guide/targets.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ To create a Target, use the `@target` decorator on a class field, and add the ma
<div>

```html
<hello-controller>
<hello-world>
<span
data-target="hello-controller.output">
data-target="hello-world.output">
</span>
</div>
</hello-world>
```

</div>
Expand All @@ -29,7 +29,7 @@ To create a Target, use the `@target` decorator on a class field, and add the ma
import { controller, target } from "@github/catalyst"

@controller
class HelloController extends HTMLElement {
class HelloWorldElement extends HTMLElement {
@target outputTarget!: HTMLElement

greet() {
Expand Down Expand Up @@ -71,18 +71,18 @@ The `@target` decorator will only ever return _one_ element, just like `querySel
Elements can be referenced as multiple targets, and targets may be referenced multiple times within the HTML:

```html
<teammembers-controller>
<userlist-controller>
<user-controller data-target="userlist-controller.user">
<input type="checkbox" data-target="teammembers-controller.readCheckbox">
<input type="checkbox" data-target="teammembers-controller.writeCheckbox">
</user-controller>
<user-controller data-target="userlist-controller.user">
<input type="checkbox" data-target="teammembers-controller.readCheckbox">
<input type="checkbox" data-target="teammembers-controller.writeCheckbox">
</user-controller>
</userlist-controller>
</teammembers-controller>
<team-members>
<user-list>
<user-settings data-target="user-list.user">
<input type="checkbox" data-target="team-members.readCheckbox">
<input type="checkbox" data-target="team-members.writeCheckbox">
</user-settings>
<user-settings data-target="user-list.user">
<input type="checkbox" data-target="team-members.readCheckbox">
<input type="checkbox" data-target="team-members.writeCheckbox">
</user-settings>
</user-list>
</team-members>
```

<br>
Expand All @@ -91,7 +91,7 @@ Elements can be referenced as multiple targets, and targets may be referenced mu
import { controller, targets } from "@github/catalyst"

@controller
class HelloController extends HTMLElement {
class HelloWorldElement extends HTMLElement {
@targets readCheckbox!: HTMLElement
@targets writeCheckbox!: HTMLElement

Expand All @@ -110,7 +110,7 @@ If you're not using decorators, then you'll need to call `findTarget(this, key)`

```js
import {findTarget, findTargets} from '@github/catalyst'
class MyController extends HTMLElement {
class HelloWorldElement extends HTMLElement {

get outputTarget() {
return findTarget(this, 'outputTarget')
Expand Down
16 changes: 8 additions & 8 deletions docs/_guide/your-first-component.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ chapter: 2
Custom Elements allow you to create reusable components that you can declare in HTML, and [progressively enhance](https://en.wikipedia.org/wiki/Progressive_enhancement) within JavaScript. Custom Elements must named with a `-` in the HTML name, and the JS class must `extend HTMLElement`. When the browser connects each element class instance to the DOM node, `connectedCallback` is fired - this is where you can change parts of the element. Here's a basic example:

```html
<my-controller></my-controller>
<hello-world></hello-world>
<script>
class MyController extends HTMLElement {
class HelloWorldElement extends HTMLElement {
connectedCallback() {
this.innerHTML = 'Hello World!'
}
}
window.customElements.register('my-controller', MyController)
window.customElements.register('hello-world', HelloWorldElement)
</script>
```
<br>
Expand All @@ -31,27 +31,27 @@ Catalyst saves you writing some of this boilerplate, by automatically calling th

```js
@controller
class MyController extends HTMLElement {
class HelloWorldElement extends HTMLElement {
connectedCallback() {
this.innerHTML = 'Hello World!'
}
}
// No longer need this:
// window.customElements.register('my-controller', MyController)
// window.customElements.register('hello-world', HelloWorldElement)
```
<br>

Catalyst will automatically "dasherize" the class name. All capital letters get lowercased and dash separated.
Catalyst will automatically convert the classes name; removing the trailing `Element` suffix and lowercasing all capital letters, separating them with a dash.

By convention, Catalyst controllers end in `Controller`, but it's not required.
By convention, Catalyst controllers end in `Element`, and Catalyst will strip this for the tag name, but suffixing `Element` is not required. All examples in this guide use `Element` suffixed names.

#### What about without Decorators?

If you don't want to use decorators, you can simply wrap the class in a call to `controller`:

```js
controller(
class MyController extends HTMLElement {
class HelloWorldElement extends HTMLElement {
//...
}
)
Expand Down
12 changes: 6 additions & 6 deletions docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,24 +28,24 @@ <h1 class="h000-mktg mt-6 mr-6">Catalyse your Web Components</h1>
<div class="d-flex f4">
<div class="mt-4">
{% highlight html %}
<hello-controller>
<input data-target="hello-controller.name" type="text">
<hello-world>
<input data-target="hello-world.name" type="text">

<button data-action="click:hello-controller#greet">
<button data-action="click:hello-world#greet">
Greet
</button>

<span data-target="hello-controller.output">
<span data-target="hello-world.output">
</span>
</hello-controller>
</hello-world>
{% endhighlight %}
</div>
<div class="">
{% highlight js %}
import { controller, target } from "@github/catalyst"

@controller
class HelloController extends HTMLElement {
class HelloWorldElement extends HTMLElement {
@target name!: HTMLElement
@target output!: HTMLElement

Expand Down
5 changes: 4 additions & 1 deletion src/register.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ interface CustomElement {
* Example: HelloController => hello-controller
*/
export function register(classObject: CustomElement): void {
const name = classObject.name.replace(/([a-zA-Z])(?=[A-Z])/g, '$1-').toLowerCase()
const name = classObject.name
.replace(/([a-zA-Z])(?=[A-Z])/g, '$1-')
.replace(/-Element$/, '')
.toLowerCase()
if (!window.customElements.get(name)) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
Expand Down
6 changes: 6 additions & 0 deletions test/register.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,10 @@ describe('register', () => {
ThisIsAnExampleOfADasherisedClassName
)
})

it('automatically drops the `Element` suffix', () => {
class ASuffixedElement {}
register(ASuffixedElement)
expect(window.customElements.get('a-suffixed')).to.equal(ASuffixedElement)
})
})