@magnit-ce/task-list
v0.0.10
Published
A custom html element that provides sorting and management for custom task-card elements.
Downloads
526
Maintainers
Readme
magnitce-task-list
A custom HTMLElement
that provides features and events for managing custom <task-card>
elements.
Package size: ~11kb minified, ~14kb verbose.
Quick Reference
<task-list>
<task-card value="Dishes" is-finished="true"></task-card>
<task-card value="Laundry" color="#FF00FF"></task-card>
<task-card value="Sweeping"></task-card>
<task-card value="Cocktail (margarita:)">
<textarea slot="description">
1 part lime juice
1 part orange liqueur (grand marnier/cointreau/triple sec/etc)
3 parts tequila
1 twist of lime peel
1 tbsp rimming salt
1/2 shaker of ice
1 serving glass "on the rocks" (a serving amount of ice)
combine lime juice, orange liquer, and tequila in shaker
shake well for 10-20 seconds
strain liquid into serving glass
express oils from lime peel and wet serving glass rim with them
apply rimming salt to wetted rim of glass
</textarea>
</task-card>
<task-list>
<script type="module" src="/path/to/task-list[.min].js"></script>
Demos
https://catapart.github.io/magnitce-task-list/demo/
Support
- Firefox
- Chrome
- Edge
- Safari (Has not been tested; should be supported, based on custom element support)
Getting Started
Reference/Install
HTML Import (not required for vanilla js/ts; alternative to import statement)
<script type="module" src="/path/to/task-list[.min].js"></script>
npm
npm install @magnit-ce/task-list
Import
Vanilla js/ts
import "/path/to/task-list[.min].js"; // if you didn't reference from a <script>, reference with an import like this
import { TaskCardElement, TaskListElement } from "/path/to/task-list[.min].js";
npm
import "@magnit-ce/task-list"; // if you didn't reference from a <script>, reference with an import like this
import { TaskCardElement, TaskListElement } from "@magnit-ce/task-list";
Overview
The <task-list>
element is a container element for <task-card>
elements. It provides some basic task list features, like a customizeable header, an add button, the ability to show and hide its items, and a drag-and-drop feature. It also dispatches events when the list contents change.
Attributes
|Attribute|Effect|
|-|-|
|name
|Sets the title of the list. Displays as the value of the text input in the list header.|
|description
|Sets the title text of the list's header. Displays as "title text". Visible upon hovering a pointer over the header.|
|color
|A color to represent the list. Displays as the value of the color input in the list header. A categorization feature.|
|collapsed
|If true
, hides the list items. If false
, displays the list items.|
|drag-drop
|Enables drag-and-drop functionality for the list items.|
Drag and Drop
The <task-list>
element implements drag-and-drop features by using the native browser events dragstart
, dragend
, dragover
, and drop
. These events require non-trivial handlers, so the library expects <task-card>
elements as its list-items. While custom item types can be used, it is not recommended and may not have all of the features.
dragAndDropQueryParent
and parentScopeSelector
Facilitating moving items between lists means querying outside of the <task-list>
elements, themselves.
The dragAndDropQueryParent
is an element which has a querySelector()
function run on it to determine valid items for the drag target's (possible) siblings. In effect, this dragAndDropQueryParent
is any element that contains all of the <task-list>
elements which items will be able to be dragged-and-dropped between. By default, the dragAndDropQueryParent
is set to the document's <body>
element. This means that any <task-list>
in the document will be considered as a drop target.
To scope the query smaller, set the dragAndDropQueryParent
to the first ancestor element that contains all of the <task-list>
elements on your page.
The parentScopeSelector
serves the same function as the dragAndDropQueryParent
, but it is a string value that is used in the selector query. For reference, this is how the actual query looks:
this.dragAndDropQueryParent.querySelector(`${this.parentScopeSelector}${this.TASKCARD_TAG_NAME}[data-drag-id]`);
From that snippet, you can see that the two features can actually work together, if you need to dynamically narrow scope from a larger parent scope. But the simplification of all of this is that you can use either an element reference, or a css selector, or both, as a away to scope the <task-list>
elements when dragging and dropping.
Customization
[TaskListElement].TASKCARD_TAG_NAME
The TASKCARD_TAG_NAME
property of a <task-list>
element determines the string that will be used to match "card" child elements. By default, this value is set to <task-card>
, with the expectation of matching <task-card>
elements.
To be clear: this is only referenced by the drag-and-drop functionality and can otherwise be ignored.
To use a custom list item, replace the TASKCARD_TAG_NAME
with whatever the tag name is for the custom list item element.
Parts
The <task-list>
element uses the part
attribute to expose its shadow DOM content to the light DOM both for styling and selecting in javascript.
|Part Name|Description|
|-|-|
|header
|A <header>
element containting inputs for the list's color and name, as well as a collapse button, and a title
attribute set to the list's description
property.|
|color-container
|A container for the list's color input. May be used, with custom styling, to display the color while hiding the color input, itself.|
|color
|An <input type="color">
element that displays the list's color
property.|
|name
|An <input type="text">
element that displays the list's name
property.|
|collapse-button
|A button that toggles the list's collapsed status.|
|collapse-icon
|An icon on the collapse button to indicate "collapse". Default is ▲
.|
|tasks
|The <ul>
element containing all of the list's items.|
|add-button
|A button that dispatches the add
event.|
|add-icon
|An icon on the add button to indicate "add". Default is +
.|
|add-label
|The text on the add button to indicate "add". Default is Add Task
.|
findPart()
and getPart()
In addition to being able to select an element from the <task-list>
element's shadowRoot reference, this element provides a function for selecting one of its parts by using the findPart()
function.
In this example, the same part is selected with the default shadowRoot reference, and by using the findPart()
function:
const = document.querySelector('header');
findPart('').addEventListener('input', (event) =>
{
// queries the shadowRoot for an element with a part attribute of ""
});
shadowRoot.querySelector('[part="header"]').addEventListener('input', (event) =>
{
// queries the shadowRoot for an element with a part attribute of ""
});
(note: these two calls do exactly the same thing)
If one of this element's parts are going to be referenced frequently, the <task-list>
element's getPart()
function can be used instead.
With getPart()
, the element will be cached in RAM for immediate access witout having to perform a DOM query on the shadowRoot.
const = document.querySelector('');
taskCard.getPart(header'').addEventListener('input', (event) =>
{
// gets cached element and, if null: queries the shadowRoot for an element with a part attribute of ""
});
taskCard.shadowRoot.querySelector('[part="header"]').addEventListener('input', (event) =>
{
// queries the shadowRoot for an element with a part attribute of ""
});
(note: these two calls do two different things)
For event-based or initialization code, findPart()
should be fine for performance. But if the <task-list>
element is going to be updated multiple times in a row, the getPart()
function will provide a smoother experience.
Events
change
Detail
{
target: HTMLElement,
order?: number,
previousOrder?: number,
}
Description
Fires when either the list's name or color changes, and whenever a list item is dropped in the same list it was dragged from.
order
:
provides an integer of the item's index in the<task-list>
element.previousOrder
:
provides an integer of the item's index in the<task-list>
element before it was moved to its current position.target
:
provides the<task-list>
element or list item that invoked the change.
add
Detail
{
order: number
}
Description
Fires when the "Add" button is clicked.
order
:
provides an integer for assigning to a new task.
added
Detail
{
target: HTMLElement,
order: number,
}
Description
Fires when a new item is added to a list.
order
:
provides an integer of the item's index in the<task-list>
element the item was added to.target
:
provides the<task-list>
element that the item was added to.
removed
Detail
{
target: HTMLElement,
order: number
}
Description
Fires when an item is removed from a list.
order
:
provides an integer of the item's index in the<task-list>
element the item was removed from.target
:
provides the<task-list>
element that the item was removed from.
nested
Detail
{
target: TaskListElement,
}
Description
Fires when a new <task-list>
element is added to a parent <task-list>
element.
target
:
provides the<task-list>
element that was nested within the parent.
collapse
Detail
undefined
Description
Fires when the <task-list>
element is collapsed and uncollapsed.
Slots
The <task-list>
element allows customization by using slots to inject custom html content into its shadowRoot.
The <task-list>
element exposes the following slot
s:
|Slot Name|Description|Default
|-|-|-|
|header
|A heading that describes and distinguishes the list's items from other elements on the page.|[HTMLHeaderElement]|
|[Default]|Slot that holds all of the list items.(note: this slot has no name; all children of the <task-list>
element that do not specificy a slot
attribute value will be placed in this default slot.)|[empty]|
|add-button
|A button that is used to invoke the add
event, and indicate that the list needs to have a new item injected.|[HTMLButtonElement]|
|footer
|An area to include additional content or data about the list. Can also be used for nested <task-list>
elements.|[empty]|
Styling
The <task-list>
element itself, and its items, can all be styled with CSS, normally. Each of the elements in the <task-list>
element's shadowRoot can be selected for styling, directly, by using the ::part()
selector.
In this example, the header
part is being selected for styling:
task-list::part(header)
{
/* styling */
}
For a list of all part names, see the parts section.
<task-card>
and <task-board>
elements
The <task-list>
element is designed as a parent to the <task-card>
element and a child for the <task-board>
element.
Neither the <task-board>
or the <task-card>
elements are required for the <task-list>
element to function, but design decisions were made around how these three elements are expected to work together.
For developing custom implementations, the <task-board>
demo page gives examples of the three elements used as expected.
License
This library is in the public domain. You do not need permission, nor do you need to provide attribution, in order to use, modify, reproduce, publish, or sell it or any works using it or derived from it.