@swimlane/swimlane-element
v2.2.0
Published
`SwimlaneElement` is a simple base class for creating Swimlane platform widgets using [lit-html](https://lit-html.polymer-project.org/) templating.
Downloads
24,836
Maintainers
Keywords
Readme
SwimlaneElement
SwimlaneElement
is a simple base class for creating Swimlane platform widgets using lit-html templating.
Building
Run npm run build
to build SwimlaneElement. The build artifacts will be stored in the build/
directory.
Development server
Run npm run start
to serve the demo.
Release
- Checkout master (
git checkout master
) - Pull master (
git pull
) - Refresh node modules (
npm ci
) - Examine log to determine next version (X.Y.Z)
- Run
git checkout -b release/X.Y.Z
- Update version in
package.json
. - Update changelog in
CHANGELOG.md
- Run
git commit -am "(release): X.Y.Z"
- Run
git tag X.Y.Z
- Run
git push origin HEAD --tags
- Run
npm run publish
- Submit PR
Overview
LitElement
(https://lit-element.polymer-project.org/) is a webcomponent base class that uses lit-html
(https://lit-html.polymer-project.org/) templating library. LitElement
(https://lit-element.polymer-project.org/) uses lit-html to render into the element's Shadow DOM and adds API to react to changes in properties.
SwimlaneElement
extends from LitElement
to add API for interacting with records or reports in the Swimlane platform.
Getting Started
/**
* Import `SwimlaneElement` class.
* The `css` and `html` methods are also imported from `swimlane-element`.
*/
import { SwimlaneElement, css, html } from '@swimlane/swimlane-element@1';
/**
* The `recordFrameTemplate` is a template function see templates below.
*/
import { recordFrameTemplate } from '@swimlane/swimlane-element@1/templates.js';
/**
* A Swimlane widget is implemented as an anonymous class which extends the `SwimlaneElement` class.
*/
export default class extends SwimlaneElement {
/**
* The `styles()` getter is a static class getter, in other words, it is a property defined on the class constructor.
* This style getter method does not have access to any properties stored in the objects.
* This getter defines styles common to all instances of this widget.
* Defining this in your widget is optional.
*/
static get styles() {
return [super.styles, css`
.frame::after {
content: "Record Output";
}
`];
}
/**
* The `render` method is an instance method and, therefore, has access to properties stored in the object (i.e. `record` and `report`, see properties below.
* The render method is scheduled by `LitElement` Lifecycle events and must return a `lit-html` template.
* Defining this method in your widget is required.
*/
render() {
return recordFrameTemplate(html`
<pre>${JSON.stringify(this.record, undefined, 2)}</pre>
`);
}
}
Properties
LitElement
efficiently manages declared properties and attributes. By default SwimlaneElement
declares record
or report
properties as well as the 'contextData'
property. Documentation on how LitElement
handles properties and attributes can be found here.
this.record
- Available to record widgets, an object containing key-value pairs for each field on the record.this.report
- Available to report widgets, an object containingdata
,rawData
, andquery
.this.contextData
- Available to both record and report widgets, an object containing data such asapplication
,currentUser
,origin
, andtoken
.
Templates
To define a template for a SwimlaneElement
component, write a render function that returns a lit-html
template. More details on writing render methods can be found in the documentation for LitElement
and lit-html. The swimlane-element
library includes predefined templates designed for the Swimlane platform. These templates can be imported from @swimlane/swimlane-element@1/templates.js
.
recordFrameTemplate
- A base template for rendering a frame on the record page. This function takes as arguments a template to render inside the frame and an optionalrows
height value. Without a definedrows
value the frame will auto size to the content.reportFrameTemplate
- A base template for rendering a frame on the dashboards. This function takes as arguments a template to render inside the frame and an optionalrows
height value. Without a definedrows
value the frame will auto size to the content.
Styles
As with LitElement
there are "three main places in which you can define styles for your host element" ref. The two most common methods for SwimlaneElements
will be to Define styles in a static styles property or Define styles in a style element.
Events
Documentation on how to handle events in LitElement
can be found here. SwimlaneElement
adds the following methods for emitting Swimlane widget events:
this.updateRecordValue(key, value)
: Available to record widgets. Updates record data by field key.this.addComment(key, value)
: Available to record widgets. Adds a new comment by field key.this.triggerIntegration(taskId)
: Available to record widgets. Triggers an integration.this.triggerSave()
: Available to record widgets. Triggers record save on the record page.this.triggerButton(buttonId)
: Available to record widgets. Triggers the specified button on the record page.
Lifecycle
LitElement
watches properties and attributes for changes and asynchronously renders the template to the element's shadow DOM. Documentation of LitElement
lifecycle methods and properties can be found here. In addition to the HtmlElement
and LitElement
lifecycle methods, SwimlaneElement
adds the resizedCallback
method.
resizedCallback
- This method (called whenever the element is resized) but default simply callsrequestUpdate
.
Examples
Basic
// SwimlaneElement and html are the basic required imports
import { SwimlaneElement, html } from '@swimlane/swimlane-element@1';
// Create and export a class definition for your widget that extends the SwimlaneElement base class
export default class extends SwimlaneElement {
// The render callback renders your element's template.
// It should always return the same template given the same properties and should not perform
// any side effects such as setting properties or manipulating the DOM.
render() {
// Return the template using the html template tag.
return html`
<div>Hello world!</div>
`;
}
}
Record data
import { SwimlaneElement, html } from '@swimlane/swimlane-element@1';
export default class extends SwimlaneElement {
// The render callback is called each time the record data changes.
// lit-html is optimized for handling frequent updates and updating the DOM efficiently
render() {
return html`
<div>
Current count: ${this.record['count']}
</div>
`;
}
}
Handling events
import { SwimlaneElement, html } from '@swimlane/swimlane-element@1';
export default class extends SwimlaneElement {
render() {
return html`
<div>
Current count: [${this.record['count']}]
<!-- Use @[eventname] syntax to register inline event handlers -->
<button @click=${() => this.updateRecordValue('count', this.record['count'] + 1)}>+</button>
<!-- You can also pass a function reference directly. -->
<button @click=${this._onDecrement}>-</button>
</div>
`;
}
_onDecrement() {
this.updateRecordValue('count', this.record['count'] - 1)
}
}
Styles in a static styles property
import { SwimlaneElement, html } from '@swimlane/swimlane-element@1';
export default class extends SwimlaneElement {
/**
* Styles should be added as a static getter. They are evaluated once, and then added
* in the element's shadow dom.
*/
static get styles() {
return css`
:host {
display: block;
}
.message {
color: blue;
}
`;
}
render() {
return html`
<div class="message">
Current count: ${this.record['count']}
</div>
`;
}
}
Swimlane styles
import { SwimlaneElement, html } from '@swimlane/swimlane-element@1';
import { recordFrameTemplate } from '@swimlane/swimlane-element@1/templates.js';
export default class extends SwimlaneElement {
/**
* The styles getter may return a array.
* Add `super.styles` to get swimlane default styles.
* Overide the `.frame::after` style to set a label for the frame.
*/
static get styles() {
return [super.styles, css`
:host {
display: block;
}
.message {
color: blue;
}
.frame::after {
content: "Current Count";
}
`];
}
/**
* Wrap the template in `recordFrameTemplate` function to add a frame.
* The seoncd argument (optional) is the row count height.
*/
render() {
return recordFrameTemplate(html`
<div class="message">
${this.record['count']}
</div>
`, 2);
}
}
Styles in a style element.
import { SwimlaneElement, html } from '@swimlane/swimlane-element@1';
export default class extends SwimlaneElement {
render() {
const color = this.record['count'] > 10 ? 'red' : 'blue';
return html`
<-- styles defined here are dynamic, and will update when properties update.
<style>
.message {
color: ${color};
}
</style>
<div class="message">
Current count: ${this.record['count']}
</div>
`;
}
}
Full Demo
import { SwimlaneElement, css, html } from '@swimlane/swimlane-element@1';
import { recordFrameTemplate } from '@swimlane/swimlane-element@1/templates.js';
export default class extends SwimlaneElement {
static get styles() {
return [super.styles, css`
:host {
text-align: center;
}
.frame::after {
content: "Current Count";
}
button {
font-size: xx-large;
margin-top: 10px;
height: 60px;
width: 60px;
border-radius: 5px;
background-color: #ffbb47;
color: #07080b;
bordeR: 0;
}
.message {
font-size: xx-large;
}
`];
}
render() {
const color = this.record['count'] > 10 ? '#FF4514' : '#1483FF';
return recordFrameTemplate(html`
<style>
.message {
color: ${color};
}
</style>
<div>
<div class="message">
${this.record['count']}
</div>
<button @click=${this._onIncrement}>+</button>
<button @click=${this._onDecrement}>-</button>
</div>
`, 2);
}
_onIncrement() {
this.updateRecordValue('count', this.record['count'] + 1)
}
_onDecrement() {
this.updateRecordValue('count', this.record['count'] - 1)
}
}
Credits
SwimlaneElement
is a Swimlane open-source project; we believe in giving back to the open-source community by sharing some of the projects we build for our application. Swimlane is an automated cyber security operations and incident response platform that enables cyber security teams to leverage threat intelligence, speed up incident response and automate security operations.