From 56151a36e6434ae429c1bfdebb3d1e6fcfe6b267 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mu-An=20=E2=9C=8C=EF=B8=8F=20Chiou?= Date: Tue, 4 Sep 2018 13:55:33 -0400 Subject: [PATCH] Built --- .gitignore | 1 - dist/index.esm.js | 529 ++++++++++++++++++++++++++++++++++++++++ dist/index.esm.js.flow | 12 + dist/index.umd.js | 537 +++++++++++++++++++++++++++++++++++++++++ dist/index.umd.js.flow | 12 + 5 files changed, 1090 insertions(+), 1 deletion(-) create mode 100644 dist/index.esm.js create mode 100644 dist/index.esm.js.flow create mode 100644 dist/index.umd.js create mode 100644 dist/index.umd.js.flow diff --git a/.gitignore b/.gitignore index 1eae0cf..c2658d7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1 @@ -dist/ node_modules/ diff --git a/dist/index.esm.js b/dist/index.esm.js new file mode 100644 index 0000000..532f743 --- /dev/null +++ b/dist/index.esm.js @@ -0,0 +1,529 @@ +var sortHandlers = new WeakMap(); +var state = null; + +function isDragging() { + return !!state; +} + +function sortable(el, fn) { + sortHandlers.set(el, fn); + el.addEventListener('dragstart', onDragStart); + el.addEventListener('dragenter', onDragEnter); + el.addEventListener('dragend', onDragEnd); + el.addEventListener('drop', onDrop); + el.addEventListener('dragover', onDragOver); +} + +// Determine if item2 is before item1 in the tree. +function isBefore(item1, item2) { + if (item1.parentNode === item2.parentNode) { + var node = item1; + while (node) { + if (node === item2) return true; + node = node.previousElementSibling; + } + } + return false; +} + +function isSameContainer(item1, item2) { + return item1.closest('task-lists') === item2.closest('task-lists'); +} + +function onDragStart(event) { + // Ignore selected text dragging within list items. + if (event.currentTarget !== event.target) return; + + var target = event.currentTarget; + if (!(target instanceof Element)) return; + + var sourceList = target.closest('.contains-task-list'); + if (!sourceList) return; + + target.classList.add('is-ghost'); + + // Add data to drag operation (required for Firefox). + if (event.dataTransfer) { + event.dataTransfer.setData('text/plain', target.textContent.trim()); + } + + if (!target.parentElement) return; + var siblings = Array.from(target.parentElement.children); + var sourceIndex = siblings.indexOf(target); + + state = { + didDrop: false, + dragging: target, + dropzone: target, + sourceList: sourceList, + sourceSibling: siblings[sourceIndex + 1] || null, + sourceIndex: sourceIndex + }; +} + +function onDragEnter(event) { + // Allow dragging task list item, not text, links, or files. + if (!state) return; + + var dropzone = event.currentTarget; + if (!(dropzone instanceof Element)) return; + + if (!isSameContainer(state.dragging, dropzone)) { + event.stopPropagation(); + return; + } + + // Necessary for dragging + event.preventDefault(); + if (event.dataTransfer) { + event.dataTransfer.dropEffect = 'move'; + } + + // Make sure we weren't already dragging in this task list item. + if (state.dropzone === dropzone) return; + + // Open an empty space in the list as a drop target. + state.dragging.classList.add('is-dragging'); + + state.dropzone = dropzone; + + if (isBefore(state.dragging, dropzone)) { + dropzone.before(state.dragging); + } else { + dropzone.after(state.dragging); + } +} + +function onDrop(event) { + // Allow dragging task list item, not text, links, or files. + if (!state) return; + + var dropzone = event.currentTarget; + if (!(dropzone instanceof Element)) return; + + // Notify dragend listener drag ended in a valid drop target. + state.didDrop = true; + + if (!state.dragging.parentElement) return; + var newIndex = Array.from(state.dragging.parentElement.children).indexOf(state.dragging); + + var currentList = dropzone.closest('.contains-task-list'); + if (!currentList) return; + + // Don't notify listener if the list hasn't changed. + if (state.sourceIndex === newIndex && state.sourceList === currentList) return; + + // Increment insertion index when moving item down in its own list. + if (state.sourceList === currentList && state.sourceIndex < newIndex) { + newIndex++; + } + + var src = { list: state.sourceList, index: state.sourceIndex }; + var dst = { list: currentList, index: newIndex }; + var fn = sortHandlers.get(state.dragging); + if (fn) fn({ src: src, dst: dst }); +} + +function onDragEnd() { + if (!state) return; + + state.dragging.classList.remove('is-dragging'); + state.dragging.classList.remove('is-ghost'); + + // If the drag ended in a valid drop target, the drop event listener will + // have already set this flag to true. If not, it'll still be false, and + // we'll know the drag was canceled. + if (!state.didDrop) { + state.sourceList.insertBefore(state.dragging, state.sourceSibling); + } + + // Reset for next drag. + state = null; +} + +function onDragOver(event) { + // Allow dragging task list item, not text, links, or files. + if (!state) return; + + var dropzone = event.currentTarget; + if (!(dropzone instanceof Element)) return; + + if (!isSameContainer(state.dragging, dropzone)) { + event.stopPropagation(); + return; + } + + // Necessary for dragging. + event.preventDefault(); + if (event.dataTransfer) { + event.dataTransfer.dropEffect = 'move'; + } +} + +var classCallCheck = function (instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } +}; + +var createClass = function () { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + + return function (Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; +}(); + +var inherits = function (subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); + } + + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + enumerable: false, + writable: true, + configurable: true + } + }); + if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; +}; + +var possibleConstructorReturn = function (self, call) { + if (!self) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + + return call && (typeof call === "object" || typeof call === "function") ? call : self; +}; + +function _CustomElement() { + return Reflect.construct(HTMLElement, [], this.__proto__.constructor); +} +Object.setPrototypeOf(_CustomElement.prototype, HTMLElement.prototype); +Object.setPrototypeOf(_CustomElement, HTMLElement); + +var observers = new WeakMap(); + +var TaskListsElement = function (_CustomElement2) { + inherits(TaskListsElement, _CustomElement2); + + function TaskListsElement() { + classCallCheck(this, TaskListsElement); + + var _this = possibleConstructorReturn(this, (TaskListsElement.__proto__ || Object.getPrototypeOf(TaskListsElement)).call(this)); + + _this.addEventListener('change', function (event) { + var checkbox = event.target; + if (!(checkbox instanceof HTMLInputElement)) return; + if (!checkbox.classList.contains('task-list-item-checkbox')) return; + + _this.dispatchEvent(new CustomEvent('task-lists:check', { + bubbles: true, + detail: { + position: position(checkbox), + checked: checkbox.checked + } + })); + }); + + observers.set(_this, new MutationObserver(syncState.bind(null, _this))); + return _this; + } + + createClass(TaskListsElement, [{ + key: 'connectedCallback', + value: function connectedCallback() { + var observer = observers.get(this); + if (observer) { + observer.observe(this, { childList: true, subtree: true }); + } + syncState(this); + } + }, { + key: 'disconnectedCallback', + value: function disconnectedCallback() { + var observer = observers.get(this); + if (observer) { + observer.disconnect(); + } + } + }, { + key: 'attributeChangedCallback', + value: function attributeChangedCallback(name, oldValue, newValue) { + if (oldValue === newValue) return; + + switch (name) { + case 'disabled': + syncDisabled(this); + break; + } + } + }, { + key: 'disabled', + get: function get$$1() { + return this.hasAttribute('disabled'); + }, + set: function set$$1(value) { + if (value) { + this.setAttribute('disabled', ''); + } else { + this.removeAttribute('disabled'); + } + } + }, { + key: 'sortable', + get: function get$$1() { + return this.hasAttribute('sortable'); + }, + set: function set$$1(value) { + if (value) { + this.setAttribute('sortable', ''); + } else { + this.removeAttribute('sortable'); + } + } + }], [{ + key: 'observedAttributes', + get: function get$$1() { + return ['disabled']; + } + }]); + return TaskListsElement; +}(_CustomElement); + + +var handleTemplate = document.createElement('template'); +handleTemplate.innerHTML = '\n \n \n '; + +var initialized = new WeakMap(); + +// Only top-level lists are draggable, and nested lists drag with their parent item. +function initItem(el) { + if (initialized.get(el)) return; + initialized.set(el, true); + + var taskList = el.closest('task-lists'); + if (!(taskList instanceof TaskListsElement)) return; + + // Single item task lists are not draggable. + if (taskList.querySelectorAll('.task-list-item').length <= 1) return; + + var fragment = handleTemplate.content.cloneNode(true); + var handle = fragment.querySelector('.handle'); + el.prepend(fragment); + + if (!handle) throw new Error('handle not found'); + handle.addEventListener('mouseenter', onHandleMouseOver); + handle.addEventListener('mouseleave', onHandleMouseOut); + + sortable(el, onSorted); + + // Drag operations don't remove :hover styles, so manage drag handle hover state. + el.addEventListener('mouseenter', onListItemMouseOver); + el.addEventListener('mouseleave', onListItemMouseOut); +} + +function onListItemMouseOver(event) { + var item = event.currentTarget; + if (!(item instanceof Element)) return; + + var list = item.closest('task-lists'); + if (!(list instanceof TaskListsElement)) return; + + if (list.sortable && !list.disabled) { + item.classList.add('hovered'); + } +} + +function onListItemMouseOut(event) { + var item = event.currentTarget; + if (!(item instanceof Element)) return; + item.classList.remove('hovered'); +} + +// Returns the list item position as a (list index, item index) tuple. +// Listen on top-level task lists because item indexing includes nested task lists. +function position(el) { + var list = rootTaskList(el); + if (!list) throw new Error('.contains-task-list not found'); + var flattened = Array.from(list.querySelectorAll('li')); + var index = flattened.indexOf(el.closest('.task-list-item')); + return [listIndex(list), index]; +} + +// Finds the list item's parent task list. +function taskList(el) { + var parent = el.parentElement; + return parent ? parent.closest('.contains-task-list') : null; +} + +// Is the task list this element belongs to a root list? +function isRootTaskList(el) { + return taskList(el) === rootTaskList(el); +} + +// Finds the highest task list in this element's ancestor chain. +function rootTaskList(node) { + var list = taskList(node); + return list ? rootTaskList(list) || list : null; +} + +function syncState(list) { + var items = list.querySelectorAll('.contains-task-list > .task-list-item'); + var _iteratorNormalCompletion = true; + var _didIteratorError = false; + var _iteratorError = undefined; + + try { + for (var _iterator = items[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { + var el = _step.value; + + if (isRootTaskList(el)) { + initItem(el); + } + } + } catch (err) { + _didIteratorError = true; + _iteratorError = err; + } finally { + try { + if (!_iteratorNormalCompletion && _iterator.return) { + _iterator.return(); + } + } finally { + if (_didIteratorError) { + throw _iteratorError; + } + } + } + + syncDisabled(list); +} + +function syncDisabled(list) { + var _iteratorNormalCompletion2 = true; + var _didIteratorError2 = false; + var _iteratorError2 = undefined; + + try { + for (var _iterator2 = list.querySelectorAll('.task-list-item')[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { + var el = _step2.value; + + el.classList.toggle('enabled', !list.disabled); + } + } catch (err) { + _didIteratorError2 = true; + _iteratorError2 = err; + } finally { + try { + if (!_iteratorNormalCompletion2 && _iterator2.return) { + _iterator2.return(); + } + } finally { + if (_didIteratorError2) { + throw _iteratorError2; + } + } + } + + var _iteratorNormalCompletion3 = true; + var _didIteratorError3 = false; + var _iteratorError3 = undefined; + + try { + for (var _iterator3 = list.querySelectorAll('.task-list-item-checkbox')[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { + var _el = _step3.value; + + if (_el instanceof HTMLInputElement) { + _el.disabled = list.disabled; + } + } + } catch (err) { + _didIteratorError3 = true; + _iteratorError3 = err; + } finally { + try { + if (!_iteratorNormalCompletion3 && _iterator3.return) { + _iterator3.return(); + } + } finally { + if (_didIteratorError3) { + throw _iteratorError3; + } + } + } +} + +// Given a top-level task list, return its index location in the container. All +// lists in the container, not just task lists, are indexed to match the +// server-side Markdown parser's indexing. +function listIndex(list) { + var container = list.closest('task-lists'); + if (!container) throw new Error('parent not found'); + var top = Array.from(container.querySelectorAll('ol, ul')); + return top.indexOf(list); +} + +function onSorted(_ref) { + var src = _ref.src, + dst = _ref.dst; + + var container = src.list.closest('task-lists'); + if (!container) return; + + container.dispatchEvent(new CustomEvent('task-lists:move', { + bubbles: true, + detail: { + src: [listIndex(src.list), src.index], + dst: [listIndex(dst.list), dst.index] + } + })); +} + +// Enable list item drag when handle is hovered. +function onHandleMouseOver(event) { + var target = event.currentTarget; + if (!(target instanceof Element)) return; + + var item = target.closest('.task-list-item'); + if (!item) return; + + var list = item.closest('task-lists'); + if (!(list instanceof TaskListsElement)) return; + + if (list.sortable && !list.disabled) { + item.setAttribute('draggable', 'true'); + } +} + +// Disable list item drag so text selection works. +function onHandleMouseOut(event) { + if (isDragging()) return; + + var target = event.currentTarget; + if (!(target instanceof Element)) return; + + var item = target.closest('.task-list-item'); + if (!item) return; + + item.setAttribute('draggable', 'false'); +} + +if (!window.customElements.get('task-lists')) { + window.TaskListsElement = TaskListsElement; + window.customElements.define('task-lists', TaskListsElement); +} + +export default TaskListsElement; diff --git a/dist/index.esm.js.flow b/dist/index.esm.js.flow new file mode 100644 index 0000000..571856c --- /dev/null +++ b/dist/index.esm.js.flow @@ -0,0 +1,12 @@ +/* @flow */ + +declare class TaskListsElement extends HTMLElement { + get disabled(): boolean; + set disabled(value: boolean): void; + get sortable(): boolean; + set sortable(value: boolean): void; +} + +declare module '@github/task-lists-element' { + declare export default typeof TaskListsElement +} diff --git a/dist/index.umd.js b/dist/index.umd.js new file mode 100644 index 0000000..7abb5cb --- /dev/null +++ b/dist/index.umd.js @@ -0,0 +1,537 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global.TaskListsElement = factory()); +}(this, (function () { 'use strict'; + + var sortHandlers = new WeakMap(); + var state = null; + + function isDragging() { + return !!state; + } + + function sortable(el, fn) { + sortHandlers.set(el, fn); + el.addEventListener('dragstart', onDragStart); + el.addEventListener('dragenter', onDragEnter); + el.addEventListener('dragend', onDragEnd); + el.addEventListener('drop', onDrop); + el.addEventListener('dragover', onDragOver); + } + + // Determine if item2 is before item1 in the tree. + function isBefore(item1, item2) { + if (item1.parentNode === item2.parentNode) { + var node = item1; + while (node) { + if (node === item2) return true; + node = node.previousElementSibling; + } + } + return false; + } + + function isSameContainer(item1, item2) { + return item1.closest('task-lists') === item2.closest('task-lists'); + } + + function onDragStart(event) { + // Ignore selected text dragging within list items. + if (event.currentTarget !== event.target) return; + + var target = event.currentTarget; + if (!(target instanceof Element)) return; + + var sourceList = target.closest('.contains-task-list'); + if (!sourceList) return; + + target.classList.add('is-ghost'); + + // Add data to drag operation (required for Firefox). + if (event.dataTransfer) { + event.dataTransfer.setData('text/plain', target.textContent.trim()); + } + + if (!target.parentElement) return; + var siblings = Array.from(target.parentElement.children); + var sourceIndex = siblings.indexOf(target); + + state = { + didDrop: false, + dragging: target, + dropzone: target, + sourceList: sourceList, + sourceSibling: siblings[sourceIndex + 1] || null, + sourceIndex: sourceIndex + }; + } + + function onDragEnter(event) { + // Allow dragging task list item, not text, links, or files. + if (!state) return; + + var dropzone = event.currentTarget; + if (!(dropzone instanceof Element)) return; + + if (!isSameContainer(state.dragging, dropzone)) { + event.stopPropagation(); + return; + } + + // Necessary for dragging + event.preventDefault(); + if (event.dataTransfer) { + event.dataTransfer.dropEffect = 'move'; + } + + // Make sure we weren't already dragging in this task list item. + if (state.dropzone === dropzone) return; + + // Open an empty space in the list as a drop target. + state.dragging.classList.add('is-dragging'); + + state.dropzone = dropzone; + + if (isBefore(state.dragging, dropzone)) { + dropzone.before(state.dragging); + } else { + dropzone.after(state.dragging); + } + } + + function onDrop(event) { + // Allow dragging task list item, not text, links, or files. + if (!state) return; + + var dropzone = event.currentTarget; + if (!(dropzone instanceof Element)) return; + + // Notify dragend listener drag ended in a valid drop target. + state.didDrop = true; + + if (!state.dragging.parentElement) return; + var newIndex = Array.from(state.dragging.parentElement.children).indexOf(state.dragging); + + var currentList = dropzone.closest('.contains-task-list'); + if (!currentList) return; + + // Don't notify listener if the list hasn't changed. + if (state.sourceIndex === newIndex && state.sourceList === currentList) return; + + // Increment insertion index when moving item down in its own list. + if (state.sourceList === currentList && state.sourceIndex < newIndex) { + newIndex++; + } + + var src = { list: state.sourceList, index: state.sourceIndex }; + var dst = { list: currentList, index: newIndex }; + var fn = sortHandlers.get(state.dragging); + if (fn) fn({ src: src, dst: dst }); + } + + function onDragEnd() { + if (!state) return; + + state.dragging.classList.remove('is-dragging'); + state.dragging.classList.remove('is-ghost'); + + // If the drag ended in a valid drop target, the drop event listener will + // have already set this flag to true. If not, it'll still be false, and + // we'll know the drag was canceled. + if (!state.didDrop) { + state.sourceList.insertBefore(state.dragging, state.sourceSibling); + } + + // Reset for next drag. + state = null; + } + + function onDragOver(event) { + // Allow dragging task list item, not text, links, or files. + if (!state) return; + + var dropzone = event.currentTarget; + if (!(dropzone instanceof Element)) return; + + if (!isSameContainer(state.dragging, dropzone)) { + event.stopPropagation(); + return; + } + + // Necessary for dragging. + event.preventDefault(); + if (event.dataTransfer) { + event.dataTransfer.dropEffect = 'move'; + } + } + + var classCallCheck = function (instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + }; + + var createClass = function () { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + + return function (Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; + }(); + + var inherits = function (subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); + } + + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + enumerable: false, + writable: true, + configurable: true + } + }); + if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; + }; + + var possibleConstructorReturn = function (self, call) { + if (!self) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + + return call && (typeof call === "object" || typeof call === "function") ? call : self; + }; + + function _CustomElement() { + return Reflect.construct(HTMLElement, [], this.__proto__.constructor); + } + Object.setPrototypeOf(_CustomElement.prototype, HTMLElement.prototype); + Object.setPrototypeOf(_CustomElement, HTMLElement); + + var observers = new WeakMap(); + + var TaskListsElement = function (_CustomElement2) { + inherits(TaskListsElement, _CustomElement2); + + function TaskListsElement() { + classCallCheck(this, TaskListsElement); + + var _this = possibleConstructorReturn(this, (TaskListsElement.__proto__ || Object.getPrototypeOf(TaskListsElement)).call(this)); + + _this.addEventListener('change', function (event) { + var checkbox = event.target; + if (!(checkbox instanceof HTMLInputElement)) return; + if (!checkbox.classList.contains('task-list-item-checkbox')) return; + + _this.dispatchEvent(new CustomEvent('task-lists:check', { + bubbles: true, + detail: { + position: position(checkbox), + checked: checkbox.checked + } + })); + }); + + observers.set(_this, new MutationObserver(syncState.bind(null, _this))); + return _this; + } + + createClass(TaskListsElement, [{ + key: 'connectedCallback', + value: function connectedCallback() { + var observer = observers.get(this); + if (observer) { + observer.observe(this, { childList: true, subtree: true }); + } + syncState(this); + } + }, { + key: 'disconnectedCallback', + value: function disconnectedCallback() { + var observer = observers.get(this); + if (observer) { + observer.disconnect(); + } + } + }, { + key: 'attributeChangedCallback', + value: function attributeChangedCallback(name, oldValue, newValue) { + if (oldValue === newValue) return; + + switch (name) { + case 'disabled': + syncDisabled(this); + break; + } + } + }, { + key: 'disabled', + get: function get$$1() { + return this.hasAttribute('disabled'); + }, + set: function set$$1(value) { + if (value) { + this.setAttribute('disabled', ''); + } else { + this.removeAttribute('disabled'); + } + } + }, { + key: 'sortable', + get: function get$$1() { + return this.hasAttribute('sortable'); + }, + set: function set$$1(value) { + if (value) { + this.setAttribute('sortable', ''); + } else { + this.removeAttribute('sortable'); + } + } + }], [{ + key: 'observedAttributes', + get: function get$$1() { + return ['disabled']; + } + }]); + return TaskListsElement; + }(_CustomElement); + + + var handleTemplate = document.createElement('template'); + handleTemplate.innerHTML = '\n \n \n '; + + var initialized = new WeakMap(); + + // Only top-level lists are draggable, and nested lists drag with their parent item. + function initItem(el) { + if (initialized.get(el)) return; + initialized.set(el, true); + + var taskList = el.closest('task-lists'); + if (!(taskList instanceof TaskListsElement)) return; + + // Single item task lists are not draggable. + if (taskList.querySelectorAll('.task-list-item').length <= 1) return; + + var fragment = handleTemplate.content.cloneNode(true); + var handle = fragment.querySelector('.handle'); + el.prepend(fragment); + + if (!handle) throw new Error('handle not found'); + handle.addEventListener('mouseenter', onHandleMouseOver); + handle.addEventListener('mouseleave', onHandleMouseOut); + + sortable(el, onSorted); + + // Drag operations don't remove :hover styles, so manage drag handle hover state. + el.addEventListener('mouseenter', onListItemMouseOver); + el.addEventListener('mouseleave', onListItemMouseOut); + } + + function onListItemMouseOver(event) { + var item = event.currentTarget; + if (!(item instanceof Element)) return; + + var list = item.closest('task-lists'); + if (!(list instanceof TaskListsElement)) return; + + if (list.sortable && !list.disabled) { + item.classList.add('hovered'); + } + } + + function onListItemMouseOut(event) { + var item = event.currentTarget; + if (!(item instanceof Element)) return; + item.classList.remove('hovered'); + } + + // Returns the list item position as a (list index, item index) tuple. + // Listen on top-level task lists because item indexing includes nested task lists. + function position(el) { + var list = rootTaskList(el); + if (!list) throw new Error('.contains-task-list not found'); + var flattened = Array.from(list.querySelectorAll('li')); + var index = flattened.indexOf(el.closest('.task-list-item')); + return [listIndex(list), index]; + } + + // Finds the list item's parent task list. + function taskList(el) { + var parent = el.parentElement; + return parent ? parent.closest('.contains-task-list') : null; + } + + // Is the task list this element belongs to a root list? + function isRootTaskList(el) { + return taskList(el) === rootTaskList(el); + } + + // Finds the highest task list in this element's ancestor chain. + function rootTaskList(node) { + var list = taskList(node); + return list ? rootTaskList(list) || list : null; + } + + function syncState(list) { + var items = list.querySelectorAll('.contains-task-list > .task-list-item'); + var _iteratorNormalCompletion = true; + var _didIteratorError = false; + var _iteratorError = undefined; + + try { + for (var _iterator = items[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { + var el = _step.value; + + if (isRootTaskList(el)) { + initItem(el); + } + } + } catch (err) { + _didIteratorError = true; + _iteratorError = err; + } finally { + try { + if (!_iteratorNormalCompletion && _iterator.return) { + _iterator.return(); + } + } finally { + if (_didIteratorError) { + throw _iteratorError; + } + } + } + + syncDisabled(list); + } + + function syncDisabled(list) { + var _iteratorNormalCompletion2 = true; + var _didIteratorError2 = false; + var _iteratorError2 = undefined; + + try { + for (var _iterator2 = list.querySelectorAll('.task-list-item')[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { + var el = _step2.value; + + el.classList.toggle('enabled', !list.disabled); + } + } catch (err) { + _didIteratorError2 = true; + _iteratorError2 = err; + } finally { + try { + if (!_iteratorNormalCompletion2 && _iterator2.return) { + _iterator2.return(); + } + } finally { + if (_didIteratorError2) { + throw _iteratorError2; + } + } + } + + var _iteratorNormalCompletion3 = true; + var _didIteratorError3 = false; + var _iteratorError3 = undefined; + + try { + for (var _iterator3 = list.querySelectorAll('.task-list-item-checkbox')[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { + var _el = _step3.value; + + if (_el instanceof HTMLInputElement) { + _el.disabled = list.disabled; + } + } + } catch (err) { + _didIteratorError3 = true; + _iteratorError3 = err; + } finally { + try { + if (!_iteratorNormalCompletion3 && _iterator3.return) { + _iterator3.return(); + } + } finally { + if (_didIteratorError3) { + throw _iteratorError3; + } + } + } + } + + // Given a top-level task list, return its index location in the container. All + // lists in the container, not just task lists, are indexed to match the + // server-side Markdown parser's indexing. + function listIndex(list) { + var container = list.closest('task-lists'); + if (!container) throw new Error('parent not found'); + var top = Array.from(container.querySelectorAll('ol, ul')); + return top.indexOf(list); + } + + function onSorted(_ref) { + var src = _ref.src, + dst = _ref.dst; + + var container = src.list.closest('task-lists'); + if (!container) return; + + container.dispatchEvent(new CustomEvent('task-lists:move', { + bubbles: true, + detail: { + src: [listIndex(src.list), src.index], + dst: [listIndex(dst.list), dst.index] + } + })); + } + + // Enable list item drag when handle is hovered. + function onHandleMouseOver(event) { + var target = event.currentTarget; + if (!(target instanceof Element)) return; + + var item = target.closest('.task-list-item'); + if (!item) return; + + var list = item.closest('task-lists'); + if (!(list instanceof TaskListsElement)) return; + + if (list.sortable && !list.disabled) { + item.setAttribute('draggable', 'true'); + } + } + + // Disable list item drag so text selection works. + function onHandleMouseOut(event) { + if (isDragging()) return; + + var target = event.currentTarget; + if (!(target instanceof Element)) return; + + var item = target.closest('.task-list-item'); + if (!item) return; + + item.setAttribute('draggable', 'false'); + } + + if (!window.customElements.get('task-lists')) { + window.TaskListsElement = TaskListsElement; + window.customElements.define('task-lists', TaskListsElement); + } + + return TaskListsElement; + +}))); diff --git a/dist/index.umd.js.flow b/dist/index.umd.js.flow new file mode 100644 index 0000000..571856c --- /dev/null +++ b/dist/index.umd.js.flow @@ -0,0 +1,12 @@ +/* @flow */ + +declare class TaskListsElement extends HTMLElement { + get disabled(): boolean; + set disabled(value: boolean): void; + get sortable(): boolean; + set sortable(value: boolean): void; +} + +declare module '@github/task-lists-element' { + declare export default typeof TaskListsElement +} pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy