@mustib/web-components 0.0.0-alpha.4 → 0.0.0-alpha.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -23,7 +23,10 @@ type Elements = [
23
23
  'mu-range-fill',
24
24
  'mu-range-thumb',
25
25
  'mu-range-thumb-value',
26
- 'mu-icon'
26
+ 'mu-icon',
27
+ 'mu-sortable',
28
+ 'mu-sortable-item',
29
+ 'mu-sortable-trigger'
27
30
  ];
28
31
  declare abstract class MuElement extends LitElement {
29
32
  #private;
@@ -1,3 +1,3 @@
1
- export { M as MuElement } from '../mu-element-C36Rgp-m.js';
1
+ export { M as MuElement } from '../mu-element-CEvBHYiI.js';
2
2
  import 'lit';
3
3
  import 'lit/decorators.js';
@@ -16,6 +16,7 @@ declare class MuIcon extends MuElement {
16
16
  close: any;
17
17
  closeLine: any;
18
18
  noImage: any;
19
+ dragVertical: any;
19
20
  };
20
21
  name?: keyof typeof MuIcon.icons;
21
22
  protected firstUpdated(_changedProperties: PropertyValues): void;
@@ -1,4 +1,4 @@
1
- import { M as MuElement, _ as __decorate } from '../mu-element-C36Rgp-m.js';
1
+ import { M as MuElement, _ as __decorate } from '../mu-element-CEvBHYiI.js';
2
2
  import { css, html } from 'lit';
3
3
  import { property } from 'lit/decorators.js';
4
4
 
@@ -61,6 +61,9 @@ MuIcon.icons = {
61
61
  noImage: html `
62
62
  <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 115.19 123.38" style="enable-background:new 0 0 115.19 123.38" xml:space="preserve"><style type="text/css">.st0{fill-rule:evenodd;clip-rule:evenodd;stroke:#000000;stroke-width:0.5;stroke-miterlimit:2.6131;}</style><g><path class="st0" d="M93.13,79.5c12.05,0,21.82,9.77,21.82,21.82c0,12.05-9.77,21.82-21.82,21.82c-12.05,0-21.82-9.77-21.82-21.82 C71.31,89.27,81.08,79.5,93.13,79.5L93.13,79.5z M8.08,0.25h95.28c2.17,0,4.11,0.89,5.53,2.3c1.42,1.42,2.3,3.39,2.3,5.53v70.01 c-2.46-1.91-5.24-3.44-8.25-4.48V9.98c0-0.43-0.16-0.79-0.46-1.05c-0.26-0.26-0.66-0.46-1.05-0.46H9.94 c-0.43,0-0.79,0.16-1.05,0.46C8.63,9.19,8.43,9.58,8.43,9.98v70.02h0.03l31.97-30.61c1.28-1.18,3.29-1.05,4.44,0.23 c0.03,0.03,0.03,0.07,0.07,0.07l26.88,31.8c-4.73,5.18-7.62,12.08-7.62,19.65c0,3.29,0.55,6.45,1.55,9.4H8.08 c-2.17,0-4.11-0.89-5.53-2.3s-2.3-3.39-2.3-5.53V8.08c0-2.17,0.89-4.11,2.3-5.53S5.94,0.25,8.08,0.25L8.08,0.25z M73.98,79.35 l3.71-22.79c0.3-1.71,1.91-2.9,3.62-2.6c0.66,0.1,1.25,0.43,1.71,0.86l17.1,17.97c-2.18-0.52-4.44-0.79-6.78-0.79 C85.91,71.99,79.13,74.77,73.98,79.35L73.98,79.35z M81.98,18.19c3.13,0,5.99,1.28,8.03,3.32c2.07,2.07,3.32,4.9,3.32,8.03 c0,3.13-1.28,5.99-3.32,8.03c-2.07,2.07-4.9,3.32-8.03,3.32c-3.13,0-5.99-1.28-8.03-3.32c-2.07-2.07-3.32-4.9-3.32-8.03 c0-3.13,1.28-5.99,3.32-8.03C76.02,19.44,78.86,18.19,81.98,18.19L81.98,18.19z M85.82,88.05l19.96,21.6 c1.58-2.39,2.5-5.25,2.5-8.33c0-8.36-6.78-15.14-15.14-15.14C90.48,86.17,87.99,86.85,85.82,88.05L85.82,88.05z M100.44,114.58 l-19.96-21.6c-1.58,2.39-2.5,5.25-2.5,8.33c0,8.36,6.78,15.14,15.14,15.14C95.78,116.46,98.27,115.78,100.44,114.58L100.44,114.58z"/></g></svg>
63
63
  `,
64
+ dragVertical: html `
65
+ <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" stroke="var(--icon-fill)" stroke-width="3"><circle cx="8" cy="4" r="1"/><circle cx="16" cy="4" r="1"/><circle cx="8" cy="12" r="1"/><circle cx="16" cy="12" r="1"/><circle cx="8" cy="20" r="1"/><circle cx="16" cy="20" r="1"/></svg>
66
+ `,
64
67
  };
65
68
  __decorate([
66
69
  property()
@@ -1,4 +1,4 @@
1
- import { M as MuElement, _ as __decorate } from '../mu-element-C36Rgp-m.js';
1
+ import { M as MuElement, _ as __decorate } from '../mu-element-CEvBHYiI.js';
2
2
  import { css, html } from 'lit';
3
3
  import { property, query } from 'lit/decorators.js';
4
4
 
@@ -1,4 +1,4 @@
1
- import { M as MuElement, _ as __decorate } from '../mu-element-C36Rgp-m.js';
1
+ import { M as MuElement, _ as __decorate } from '../mu-element-CEvBHYiI.js';
2
2
  import { css, html } from 'lit';
3
3
  import { property, query } from 'lit/decorators.js';
4
4
 
@@ -1,4 +1,4 @@
1
- import { M as MuElement, _ as __decorate, g as getElementBoundaries } from '../mu-element-C36Rgp-m.js';
1
+ import { M as MuElement, _ as __decorate, g as getElementBoundaries } from '../mu-element-CEvBHYiI.js';
2
2
  import { css, html } from 'lit';
3
3
  import { state, property, query } from 'lit/decorators.js';
4
4
  import { MuTransparent } from './mu-transparent.js';
@@ -1,4 +1,4 @@
1
- import { M as MuElement, _ as __decorate, t as throttle, d as debounce, w as wait, g as getElementBoundaries } from '../mu-element-C36Rgp-m.js';
1
+ import { M as MuElement, _ as __decorate, t as throttle, d as debounce, w as wait, g as getElementBoundaries } from '../mu-element-CEvBHYiI.js';
2
2
  import { css, html } from 'lit';
3
3
  import { property } from 'lit/decorators.js';
4
4
  import { MuTransparent } from './mu-transparent.js';
@@ -1,4 +1,4 @@
1
- import { M as MuElement, _ as __decorate } from '../mu-element-C36Rgp-m.js';
1
+ import { M as MuElement, _ as __decorate } from '../mu-element-CEvBHYiI.js';
2
2
  import { css, html } from 'lit';
3
3
  import { property } from 'lit/decorators.js';
4
4
 
@@ -1,4 +1,4 @@
1
- import { M as MuElement, E as EventAction, _ as __decorate, g as getElementBoundaries, d as debounce, a as disableElementScroll, e as enableElementScroll } from '../mu-element-C36Rgp-m.js';
1
+ import { M as MuElement, E as EventAction, _ as __decorate, g as getElementBoundaries, d as debounce, a as disableElementScroll, e as enableElementScroll } from '../mu-element-CEvBHYiI.js';
2
2
  import { css, html } from 'lit';
3
3
  import { property } from 'lit/decorators.js';
4
4
  import { MuTransparent } from './mu-transparent.js';
@@ -1,4 +1,4 @@
1
- import { M as MuElement, _ as __decorate } from '../mu-element-C36Rgp-m.js';
1
+ import { M as MuElement, _ as __decorate } from '../mu-element-CEvBHYiI.js';
2
2
  import { css, nothing, html } from 'lit';
3
3
  import { property, state } from 'lit/decorators.js';
4
4
  import { repeat } from 'lit/directives/repeat.js';
@@ -1,4 +1,4 @@
1
- import { M as MuElement, _ as __decorate } from '../mu-element-C36Rgp-m.js';
1
+ import { M as MuElement, _ as __decorate } from '../mu-element-CEvBHYiI.js';
2
2
  import { css, html, nothing } from 'lit';
3
3
  import './mu-trigger.js';
4
4
  import { property, state } from 'lit/decorators.js';
@@ -1,4 +1,4 @@
1
- import { M as MuElement, E as EventAction, _ as __decorate } from '../mu-element-C36Rgp-m.js';
1
+ import { M as MuElement, E as EventAction, _ as __decorate } from '../mu-element-CEvBHYiI.js';
2
2
  import { css, html } from 'lit';
3
3
  import { property, queryAssignedElements } from 'lit/decorators.js';
4
4
  import { MuTransparent } from './mu-transparent.js';
@@ -0,0 +1,34 @@
1
+ import { CSSResultGroup } from 'lit';
2
+ import { MuElement, MuElementComponent } from './mu-element.js';
3
+ import '@mustib/utils/browser';
4
+
5
+ type MuSortableItemComponent = MuElementComponent['attributes'] & {
6
+ attributes: {
7
+ name: string;
8
+ };
9
+ };
10
+ declare class MuSortableItem extends MuElement {
11
+ static styles?: CSSResultGroup | undefined;
12
+ _addEventActionAttributes: undefined;
13
+ eventActionData: undefined;
14
+ name: string;
15
+ connectedCallback(): void;
16
+ /**
17
+ * Used to notify the item whether or not it is being sorted and is moving
18
+ */
19
+ setIsMoving(value: boolean): void;
20
+ /**
21
+ * Used to notify the item whether or not it is added to be sorted
22
+ */
23
+ setAdded(value: boolean): void;
24
+ protected _slotChangeHandler: () => void;
25
+ protected render(): unknown;
26
+ }
27
+ declare global {
28
+ interface HTMLElementTagNameMap {
29
+ 'mu-sortable-item': MuSortableItem;
30
+ }
31
+ }
32
+
33
+ export { MuSortableItem };
34
+ export type { MuSortableItemComponent };
@@ -0,0 +1,95 @@
1
+ import { M as MuElement, _ as __decorate } from '../mu-element-CEvBHYiI.js';
2
+ import { css, html } from 'lit';
3
+ import { property } from 'lit/decorators.js';
4
+ import { MuTransparent } from './mu-transparent.js';
5
+ import { MuSortableTrigger } from './mu-sortable-trigger.js';
6
+ import './mu-icon.js';
7
+
8
+ class MuSortableItem extends MuElement {
9
+ constructor() {
10
+ super(...arguments);
11
+ this._slotChangeHandler = () => {
12
+ const triggers = [];
13
+ const addElement = (element) => {
14
+ if (element instanceof MuSortableTrigger) {
15
+ triggers.push(element);
16
+ }
17
+ };
18
+ this.renderRoot
19
+ .querySelector('slot')
20
+ ?.assignedElements({ flatten: true })
21
+ .forEach((el) => {
22
+ if (el instanceof MuTransparent)
23
+ el.contents.forEach(addElement);
24
+ else
25
+ addElement(el);
26
+ });
27
+ if (!triggers.length) {
28
+ console.warn(`mu-sortable-item does not have any triggers`, this);
29
+ }
30
+ triggers.forEach((trigger) => {
31
+ trigger.for = this.name;
32
+ });
33
+ };
34
+ }
35
+ connectedCallback() {
36
+ super.connectedCallback();
37
+ this.addEventListener('mu-transparent-slotchange', this._slotChangeHandler);
38
+ this.renderRoot.addEventListener('slotchange', this._slotChangeHandler);
39
+ if (!this.name) {
40
+ this.updateComplete.then(() => {
41
+ console.warn(`mu-sortable-item does not has a name, it will be assigned this default one (${this.muId})`, this);
42
+ });
43
+ this.name = this.muId;
44
+ }
45
+ }
46
+ /**
47
+ * Used to notify the item whether or not it is being sorted and is moving
48
+ */
49
+ setIsMoving(value) {
50
+ value ? this.setAttribute('moving', '') : this.removeAttribute('moving');
51
+ }
52
+ /**
53
+ * Used to notify the item whether or not it is added to be sorted
54
+ */
55
+ setAdded(value) {
56
+ value ? this.setAttribute('added', '') : this.removeAttribute('added');
57
+ }
58
+ render() {
59
+ return html `
60
+ <slot></slot>
61
+ `;
62
+ }
63
+ }
64
+ MuSortableItem.styles = [
65
+ MuElement.cssBase,
66
+ css `
67
+ :host([added]) {
68
+ outline: 1px dashed;
69
+ }
70
+
71
+ :host([moving]) {
72
+ user-select: none;
73
+ cursor: grabbing;
74
+ opacity: 0.5;
75
+ }
76
+
77
+ :host {
78
+ animation: flip 150ms 100ms ease-out forwards;
79
+ transform: scaleY(-0.75);
80
+ transition: opacity 150ms;
81
+ }
82
+
83
+ @keyframes flip {
84
+ 100% {
85
+ transform: none;
86
+ }
87
+ }
88
+ `,
89
+ ];
90
+ __decorate([
91
+ property()
92
+ ], MuSortableItem.prototype, "name", void 0);
93
+ MuSortableItem.register('mu-sortable-item');
94
+
95
+ export { MuSortableItem };
@@ -0,0 +1,22 @@
1
+ import { CSSResultGroup } from 'lit';
2
+ import { MuElement } from './mu-element.js';
3
+ import './mu-icon.js';
4
+ import '@mustib/utils/browser';
5
+
6
+ declare class MuSortableTrigger extends MuElement {
7
+ static styles?: CSSResultGroup | undefined;
8
+ eventActionData: undefined;
9
+ /**
10
+ * The associated item name
11
+ */
12
+ for: string;
13
+ protected _addEventActionAttributes(): Promise<void>;
14
+ protected render(): unknown;
15
+ }
16
+ declare global {
17
+ interface HTMLElementTagNameMap {
18
+ 'mu-sortable-trigger': MuSortableTrigger;
19
+ }
20
+ }
21
+
22
+ export { MuSortableTrigger };
@@ -0,0 +1,61 @@
1
+ import { css, html } from 'lit';
2
+ import { M as MuElement } from '../mu-element-CEvBHYiI.js';
3
+ import './mu-icon.js';
4
+ import 'lit/decorators.js';
5
+
6
+ class MuSortableTrigger extends MuElement {
7
+ constructor() {
8
+ super(...arguments);
9
+ /**
10
+ * The associated item name
11
+ */
12
+ this.for = '';
13
+ }
14
+ async _addEventActionAttributes() {
15
+ await this.updateComplete;
16
+ /**
17
+ * mouse events
18
+ */
19
+ this.setAttribute('mu-sortable-pointerdown', JSON.stringify([
20
+ 'prepared? ||#prevent',
21
+ '#modifier:Control? ||toggle',
22
+ ['add', this.for],
23
+ '||prepare',
24
+ ]));
25
+ /**
26
+ * keyboard events
27
+ */
28
+ this.setAttribute('mu-sortable-keydown', JSON.stringify([
29
+ 'prepared? ||#prevent',
30
+ '#key:Enter,Space?#modifier:Control? ||toggle',
31
+ ['add', this.for, '#key:Enter,Space'],
32
+ '#key:Enter,Space? ||prepare',
33
+ ]));
34
+ }
35
+ render() {
36
+ return html `
37
+ <div id='container' tabindex='0' part='container'>
38
+ <slot>
39
+ <mu-icon name='dragVertical'></mu-icon>
40
+ </slot>
41
+ </div>
42
+ `;
43
+ }
44
+ }
45
+ MuSortableTrigger.styles = [
46
+ MuElement.cssBase,
47
+ css `
48
+ #container {
49
+ display: grid;
50
+ cursor: grab;
51
+ user-select: none;
52
+ }
53
+
54
+ #container:focus-visible {
55
+ outline: 1px solid;
56
+ }
57
+ `,
58
+ ];
59
+ MuSortableTrigger.register('mu-sortable-trigger');
60
+
61
+ export { MuSortableTrigger };
@@ -0,0 +1,97 @@
1
+ import { EventAction, GenerateData } from '@mustib/utils/browser';
2
+ import { CSSResultGroup, PropertyValues } from 'lit';
3
+ import { MuElement, MuElementComponent } from './mu-element.js';
4
+ import { MuSortableItem } from './mu-sortable-item.js';
5
+
6
+ type MuSortableComponent = {
7
+ attributes: MuElementComponent['attributes'] & {
8
+ multiple: MuSortable['multiple'];
9
+ throttle: MuSortable['throttle'];
10
+ };
11
+ events: Events;
12
+ };
13
+ type Events = {
14
+ 'mu-sortable-change': CustomEvent<{
15
+ /**
16
+ * items names order before sorting
17
+ */
18
+ from: string[];
19
+ /**
20
+ * items names order after sorting
21
+ */
22
+ to: string[];
23
+ /**
24
+ * item name that started prepare action
25
+ */
26
+ startItem: string;
27
+ /**
28
+ * selected items names
29
+ */
30
+ selected: string[];
31
+ }>;
32
+ };
33
+ type SortableItem = {
34
+ element: MuSortableItem;
35
+ index: number;
36
+ name: string;
37
+ };
38
+ declare class MuSortable extends MuElement {
39
+ static styles?: CSSResultGroup | undefined;
40
+ static globalEventActionEvents: string[];
41
+ static eventAction: EventAction<GenerateData<MuSortable>>;
42
+ _addEventActionAttributes: undefined;
43
+ eventActionData: {
44
+ eventAction: EventAction<GenerateData<MuSortable>>;
45
+ events: string[];
46
+ };
47
+ /**
48
+ * a boolean indicates if multiple items can be sorted at the same time
49
+ *
50
+ * @default false
51
+ */
52
+ multiple: boolean;
53
+ /**
54
+ * pointer move throttle in ms
55
+ *
56
+ * @default 50
57
+ */
58
+ throttle: number;
59
+ protected _sortableItemsNamesMap: Map<string, SortableItem>;
60
+ protected _sortableItemsElementsMap: Map<MuSortableItem, SortableItem>;
61
+ protected _sortableItems: SortableItem[];
62
+ protected _overSortableItem?: SortableItem;
63
+ protected _toBeSortedItems: Set<SortableItem>;
64
+ protected _moveActionAnimationFrameId?: number;
65
+ protected _hasStartedMovingItems: boolean;
66
+ protected _prepareData?: {
67
+ /**
68
+ * The item that triggered prepare action regardless if there are multiple items to be sorted
69
+ */
70
+ movingItem: SortableItem;
71
+ type: 'keyboard' | 'pointer';
72
+ /**
73
+ * Initial items order before any sorting
74
+ */
75
+ initialItems: SortableItem[];
76
+ };
77
+ protected _changeSortState(data: GenerateData<MuSortable>): void;
78
+ protected _getItemFromEventAction(data: GenerateData<MuSortable>): SortableItem;
79
+ protected _endSortingHandler: () => void;
80
+ protected _throttledGlobalPointerMoveHandler?: typeof this._globalPointerMoveHandler;
81
+ protected _moveItems(overItem: SortableItem | undefined): void;
82
+ protected _globalKeydownHandler: (event: KeyboardEvent) => void;
83
+ protected _globalPointerMoveHandler(event: PointerEvent): void;
84
+ protected _slotChangeHandler: () => Promise<void>;
85
+ protected firstUpdated(_changedProperties: PropertyValues): Promise<void>;
86
+ protected render(): unknown;
87
+ }
88
+ declare global {
89
+ interface HTMLElementTagNameMap {
90
+ 'mu-sortable': MuSortable;
91
+ }
92
+ interface GlobalEventHandlersEventMap extends Events {
93
+ }
94
+ }
95
+
96
+ export { MuSortable };
97
+ export type { MuSortableComponent };
@@ -0,0 +1,308 @@
1
+ import { M as MuElement, E as EventAction, t as throttle, _ as __decorate } from '../mu-element-CEvBHYiI.js';
2
+ import { html } from 'lit';
3
+ import { property } from 'lit/decorators.js';
4
+ import { MuTransparent } from './mu-transparent.js';
5
+ import { MuSortableItem } from './mu-sortable-item.js';
6
+ import { MuSortableTrigger } from './mu-sortable-trigger.js';
7
+ import './mu-icon.js';
8
+
9
+ class MuSortable extends MuElement {
10
+ constructor() {
11
+ super(...arguments);
12
+ this.eventActionData = {
13
+ eventAction: MuSortable.eventAction,
14
+ events: ['pointerdown', 'click', 'keydown'],
15
+ };
16
+ /**
17
+ * a boolean indicates if multiple items can be sorted at the same time
18
+ *
19
+ * @default false
20
+ */
21
+ this.multiple = false;
22
+ /**
23
+ * pointer move throttle in ms
24
+ *
25
+ * @default 50
26
+ */
27
+ this.throttle = 50;
28
+ this._sortableItemsNamesMap = new Map();
29
+ this._sortableItemsElementsMap = new Map();
30
+ this._sortableItems = [];
31
+ this._toBeSortedItems = new Set();
32
+ this._hasStartedMovingItems = false;
33
+ this._endSortingHandler = () => {
34
+ if (this._moveActionAnimationFrameId) {
35
+ cancelAnimationFrame(this._moveActionAnimationFrameId);
36
+ this._moveActionAnimationFrameId = undefined;
37
+ }
38
+ const prepareData = this._prepareData;
39
+ if (!prepareData) {
40
+ throw new Error('internal mu-sortable error (_prepareData) is undefined in end handler');
41
+ }
42
+ const selected = [];
43
+ const startItem = prepareData.movingItem.name;
44
+ const from = prepareData.initialItems.map((item) => item.name);
45
+ const to = this._sortableItems.map((item) => item.name);
46
+ if (this._throttledGlobalPointerMoveHandler)
47
+ document.removeEventListener('pointermove', this._throttledGlobalPointerMoveHandler);
48
+ document.removeEventListener('keydown', this._globalKeydownHandler);
49
+ document.removeEventListener('pointerup', this._endSortingHandler);
50
+ const eventName = 'mu-sortable-change';
51
+ const event = new CustomEvent(eventName, {
52
+ bubbles: true,
53
+ composed: true,
54
+ detail: { from, to, selected, startItem },
55
+ });
56
+ this._toBeSortedItems.forEach((item) => {
57
+ selected.push(item.name);
58
+ item.element.setAdded(false);
59
+ item.element.setIsMoving(false);
60
+ });
61
+ this._toBeSortedItems.clear();
62
+ this._hasStartedMovingItems = false;
63
+ this._prepareData = undefined;
64
+ this.dispatchEvent(event);
65
+ };
66
+ this._globalKeydownHandler = (event) => {
67
+ if (event.key === 'Enter' || event.key === ' ') {
68
+ this._endSortingHandler();
69
+ return;
70
+ }
71
+ let direction;
72
+ if (event.key === 'ArrowUp') {
73
+ direction = 'prev';
74
+ }
75
+ else if (event.key === 'ArrowDown')
76
+ direction = 'next';
77
+ if (!direction)
78
+ return;
79
+ const overItem = this.getNavigationItem({
80
+ direction,
81
+ items: this._sortableItems,
82
+ fromIndex: this._prepareData?.movingItem.index,
83
+ isNavigable: (item) => {
84
+ return !this._toBeSortedItems.has(item);
85
+ },
86
+ });
87
+ this._moveItems(overItem);
88
+ };
89
+ this._slotChangeHandler = async () => {
90
+ const toBeSortedNames = new Set([...this._toBeSortedItems].map((item) => item.name));
91
+ this._toBeSortedItems.clear();
92
+ this._sortableItems = [];
93
+ this._sortableItemsNamesMap.clear();
94
+ this._sortableItemsElementsMap.clear();
95
+ const addElement = (element) => {
96
+ if (element instanceof MuSortableItem) {
97
+ const name = element.name;
98
+ if (this._sortableItemsNamesMap.has(name)) {
99
+ console.warn('duplicated mu-sortable-item name', element);
100
+ return;
101
+ }
102
+ const item = {
103
+ element,
104
+ index: this._sortableItems.length,
105
+ name,
106
+ };
107
+ this._sortableItems.push(item);
108
+ this._sortableItemsElementsMap.set(element, item);
109
+ this._sortableItemsNamesMap.set(name, item);
110
+ if (this._prepareData?.movingItem.name === name) {
111
+ this._prepareData.movingItem = item;
112
+ }
113
+ if (toBeSortedNames.has(name)) {
114
+ this._toBeSortedItems.add(item);
115
+ }
116
+ }
117
+ };
118
+ this.renderRoot.querySelectorAll('slot').forEach((slot) => {
119
+ slot.assignedElements({ flatten: true }).forEach((el) => {
120
+ if (el instanceof MuTransparent)
121
+ el.contents.forEach(addElement);
122
+ else
123
+ addElement(el);
124
+ });
125
+ });
126
+ };
127
+ }
128
+ _changeSortState(data) {
129
+ const actionName = data._parsedAction.name;
130
+ if (this._hasStartedMovingItems) {
131
+ console.warn(`cannot use (${actionName}) action in mu-sortable when there is active sorting`, data);
132
+ return;
133
+ }
134
+ const item = this._getItemFromEventAction(data);
135
+ let operation;
136
+ if (actionName === 'toggle') {
137
+ operation = this._toBeSortedItems.has(item) ? 'delete' : 'add';
138
+ }
139
+ else
140
+ operation = actionName;
141
+ switch (operation) {
142
+ case 'add':
143
+ if (!this.multiple) {
144
+ this._toBeSortedItems.forEach((item) => {
145
+ item.element.setAdded(false);
146
+ });
147
+ this._toBeSortedItems.clear();
148
+ }
149
+ item.element.setAdded(true);
150
+ this._toBeSortedItems.add(item);
151
+ break;
152
+ case 'delete':
153
+ item.element.setAdded(false);
154
+ this._toBeSortedItems.delete(item);
155
+ break;
156
+ default:
157
+ console.warn(`unsupported action name (${actionName}) cannot change select state for mu-sortable`, data);
158
+ break;
159
+ }
160
+ }
161
+ _getItemFromEventAction(data) {
162
+ const actionName = data._parsedAction.name;
163
+ let itemName;
164
+ if (typeof data.actionParam === 'string' && data.actionParam !== '')
165
+ itemName = data.actionParam;
166
+ else if (data.matchedTarget instanceof MuSortableItem)
167
+ itemName = data.matchedTarget.name;
168
+ else if (data.matchedTarget instanceof MuSortableTrigger)
169
+ itemName = data.matchedTarget.for;
170
+ else {
171
+ throw new Error(`cannot get mu-sortable-item name for (${actionName}) action because it is not passed as action param or the element which dispatched the action is not the item itself or it's trigger`);
172
+ }
173
+ const item = this._sortableItemsNamesMap.get(itemName);
174
+ if (!item) {
175
+ throw new Error(`(${itemName}) is not recognized mu-sortable-item name`);
176
+ }
177
+ return item;
178
+ }
179
+ _moveItems(overItem) {
180
+ if (!this._toBeSortedItems.size)
181
+ return;
182
+ const lastAnimationFrameId = this._moveActionAnimationFrameId;
183
+ if (lastAnimationFrameId !== undefined)
184
+ cancelAnimationFrame(lastAnimationFrameId);
185
+ this._moveActionAnimationFrameId = requestAnimationFrame(() => {
186
+ const prepareData = this._prepareData;
187
+ if (!prepareData) {
188
+ throw new Error('internal mu-sortable error, (_prepareData) is undefined');
189
+ }
190
+ /**
191
+ * Notify sortable item of being moved
192
+ */
193
+ if (!this._hasStartedMovingItems) {
194
+ this._toBeSortedItems.forEach((item) => {
195
+ item.element.setIsMoving(true);
196
+ });
197
+ this._hasStartedMovingItems = true;
198
+ }
199
+ this._overSortableItem = overItem;
200
+ if (overItem) {
201
+ const preparedItem = prepareData.movingItem;
202
+ const isMovingBackward = preparedItem.index > overItem.index;
203
+ [...this._toBeSortedItems]
204
+ .sort((a, b) => isMovingBackward ? a.index - b.index : b.index - a.index)
205
+ .forEach((toBeSortedItem) => {
206
+ overItem.element.parentElement?.insertBefore(toBeSortedItem.element, isMovingBackward
207
+ ? overItem.element
208
+ : overItem.element.nextElementSibling);
209
+ });
210
+ }
211
+ });
212
+ }
213
+ _globalPointerMoveHandler(event) {
214
+ const overItemElement = document
215
+ .elementsFromPoint(event.clientX, event.clientY)
216
+ .find((el) => {
217
+ if (!(el instanceof MuSortableItem))
218
+ return false;
219
+ const sortableItem = this._sortableItemsElementsMap.get(el);
220
+ return sortableItem && !this._toBeSortedItems.has(sortableItem);
221
+ });
222
+ const overItem = overItemElement
223
+ ? this._sortableItemsElementsMap.get(overItemElement)
224
+ : undefined;
225
+ this._moveItems(overItem);
226
+ }
227
+ async firstUpdated(_changedProperties) {
228
+ this._slotChangeHandler();
229
+ await this.updateComplete;
230
+ this.addEventListener('mu-transparent-slotchange', this._slotChangeHandler);
231
+ this.renderRoot.addEventListener('slotchange', this._slotChangeHandler);
232
+ }
233
+ render() {
234
+ return html `
235
+ <slot></slot>
236
+ `;
237
+ }
238
+ }
239
+ MuSortable.styles = [MuElement.cssBase];
240
+ MuSortable.globalEventActionEvents = ['pointermove', 'pointerup'];
241
+ MuSortable.eventAction = new EventAction({
242
+ currTargetSelector: 'mu-sortable',
243
+ getEventAttributeName(eventName) {
244
+ return `mu-sortable-${eventName}`;
245
+ },
246
+ actions: {
247
+ toggle(data) {
248
+ data.event.currentTarget._changeSortState(data);
249
+ },
250
+ delete(data) {
251
+ data.event.currentTarget._changeSortState(data);
252
+ },
253
+ add(data) {
254
+ data.event.currentTarget._changeSortState(data);
255
+ },
256
+ prepare(data) {
257
+ const sortable = data.event.currentTarget;
258
+ if (sortable._prepareData) {
259
+ console.warn('cannot use prepare action for mu-sortable before current prepare ends', data);
260
+ return;
261
+ }
262
+ const movingItem = sortable._getItemFromEventAction(data);
263
+ let type;
264
+ if (data.actionParam === 'pointer' || data.actionParam === 'keyboard')
265
+ type = data.actionParam;
266
+ else if (data.event instanceof PointerEvent)
267
+ type = 'pointer';
268
+ else if (data.event instanceof KeyboardEvent)
269
+ type = 'keyboard';
270
+ else {
271
+ console.warn('cannot get prepare action type for mu-sortable', data);
272
+ return;
273
+ }
274
+ sortable._prepareData = {
275
+ movingItem,
276
+ initialItems: sortable._sortableItems,
277
+ type,
278
+ };
279
+ // need to defer so events not fire immediately
280
+ setTimeout(() => {
281
+ if (type === 'pointer') {
282
+ const handler = throttle(sortable._globalPointerMoveHandler.bind(sortable), sortable.throttle);
283
+ sortable._throttledGlobalPointerMoveHandler = handler;
284
+ document.addEventListener('pointermove', handler);
285
+ document.addEventListener('pointerup', sortable._endSortingHandler, { once: true });
286
+ }
287
+ else {
288
+ document.addEventListener('keydown', sortable._globalKeydownHandler);
289
+ }
290
+ }, 0);
291
+ },
292
+ },
293
+ switches: {
294
+ prepared(data) {
295
+ const sortable = data.event.currentTarget;
296
+ return sortable._prepareData !== undefined;
297
+ },
298
+ },
299
+ });
300
+ __decorate([
301
+ property({ type: Boolean })
302
+ ], MuSortable.prototype, "multiple", void 0);
303
+ __decorate([
304
+ property({ type: Number })
305
+ ], MuSortable.prototype, "throttle", void 0);
306
+ MuSortable.register('mu-sortable');
307
+
308
+ export { MuSortable };
@@ -1,4 +1,4 @@
1
- import { _ as __decorate, M as MuElement } from '../mu-element-C36Rgp-m.js';
1
+ import { _ as __decorate, M as MuElement } from '../mu-element-CEvBHYiI.js';
2
2
  import { css, html } from 'lit';
3
3
  import { property } from 'lit/decorators.js';
4
4
 
@@ -1,4 +1,4 @@
1
- import { _ as __decorate, p as parseJson } from '../mu-element-C36Rgp-m.js';
1
+ import { _ as __decorate, p as parseJson } from '../mu-element-CEvBHYiI.js';
2
2
  import { property } from 'lit/decorators.js';
3
3
  import { MuTransparent } from './mu-transparent.js';
4
4
  import 'lit';
package/index.d.ts CHANGED
@@ -18,6 +18,9 @@ import { MuSelectLabelComponent } from './components/mu-select-label.js';
18
18
  export { MuSelectLabel } from './components/mu-select-label.js';
19
19
  import { MuSelectLabelContentComponent } from './components/mu-select-label-content.js';
20
20
  export { MuSelectLabelContent } from './components/mu-select-label-content.js';
21
+ import { MuSortableComponent } from './components/mu-sortable.js';
22
+ import { MuSortableItemComponent } from './components/mu-sortable-item.js';
23
+ import './components/mu-sortable-trigger.js';
21
24
  import { MuTransparentComponent } from './components/mu-transparent.js';
22
25
  export { MuTransparent } from './components/mu-transparent.js';
23
26
  import { MuTriggerComponent } from './components/mu-trigger.js';
@@ -39,6 +42,8 @@ type ComponentsAttributes = {
39
42
  'mu-icon': MuIconComponent['attributes'];
40
43
  'mu-transparent': MuTransparentComponent['attributes'];
41
44
  'mu-trigger': MuTriggerComponent['attributes'];
45
+ 'mu-sortable': MuSortableComponent['attributes'];
46
+ 'mu-sortable-item': MuSortableItemComponent['attributes'];
42
47
  };
43
48
  type MuComponentsAttributes<GlobalAttributes = Record<string, any>> = {
44
49
  [key in keyof ComponentsAttributes]: Partial<ComponentsAttributes[key]> & GlobalAttributes;
package/index.js CHANGED
@@ -1,4 +1,4 @@
1
- export { M as MuElement } from './mu-element-C36Rgp-m.js';
1
+ export { M as MuElement } from './mu-element-CEvBHYiI.js';
2
2
  export { MuIcon } from './components/mu-icon.js';
3
3
  export { MuRange } from './components/mu-range.js';
4
4
  export { MuRangeFill } from './components/mu-range-fill.js';
@@ -458,6 +458,22 @@ class EventAction {
458
458
  },
459
459
  overridable: false,
460
460
  dynamic: false
461
+ },
462
+ '#modifier': {
463
+ handler(data) {
464
+ let modifiers;
465
+ const { event, switchParam } = data;
466
+ if (typeof switchParam === 'string')
467
+ modifiers = switchParam.split(',');
468
+ else if (Array.isArray(switchParam))
469
+ modifiers = switchParam;
470
+ if (!modifiers || modifiers.length === 0 || !(event instanceof PointerEvent || event instanceof KeyboardEvent)) {
471
+ return false;
472
+ }
473
+ return modifiers.some(modifier => event.getModifierState(modifier));
474
+ },
475
+ overridable: true,
476
+ dynamic: true
461
477
  }
462
478
  };
463
479
  /**
@@ -518,7 +534,7 @@ class EventAction {
518
534
  /**
519
535
  * Parse an action name and returns an object with the following properties:
520
536
  * - name: The name of the action.
521
- * - hasOr: A boolean indicating whether the action name starts with "||".
537
+ * - hasOr: A boolean indicating whether the action name starts with `||`.
522
538
  *
523
539
  * @param name - The name of the action to parse.
524
540
  */
@@ -527,6 +543,21 @@ class EventAction {
527
543
  const hasOr = trimmedName.startsWith('||');
528
544
  return { name: hasOr ? trimmedName.slice(2) : trimmedName, hasOr };
529
545
  }
546
+ /**
547
+ * Parse a switch name and returns an object with the following properties:
548
+ * - name: The name of the switch.
549
+ * - isNegated: A boolean indicating whether the switch name starts with `!`.
550
+ *
551
+ * @param name - The name of the switch to parse.
552
+ */
553
+ static parseSwitchName(name) {
554
+ const trimmedName = name.trim();
555
+ const isNegated = trimmedName.startsWith('!');
556
+ return {
557
+ name: isNegated ? trimmedName.slice(1) : trimmedName,
558
+ isNegated
559
+ };
560
+ }
530
561
  /**
531
562
  * Parse an action string and returns a {@link ParsedAction parsed action}.
532
563
  *
@@ -564,7 +595,7 @@ class EventAction {
564
595
  const hasSwitchParam = switchParamIndex !== -1;
565
596
  const switchName = hasSwitchParam ? switchString.slice(0, switchParamIndex) : switchString;
566
597
  const switchParam = hasSwitchParam ? switchString.slice(switchParamIndex + 1) : '';
567
- return { name: switchName.trim(), param: switchParam.trim() };
598
+ return { param: switchParam.trim(), ...this.parseSwitchName(switchName) };
568
599
  });
569
600
  }
570
601
  return { param: param.trim(), switches, ...EventAction.parseActionName(name) };
@@ -658,7 +689,15 @@ class EventAction {
658
689
  console.warn(`Switch named (${name}) is already registered and need (override) option to be true to be overridden`);
659
690
  continue;
660
691
  }
661
- this.switches[name] = switchData;
692
+ const parsedSwitchName = EventAction.parseSwitchName(name);
693
+ if (parsedSwitchName.isNegated) {
694
+ console.warn(`Switch name must not start with (!) as it is used to negate switches, add your logic once with the name (${parsedSwitchName.name}) and negate the switch name in the attribute instead, Please note that your switch handler will be wrapped in a negated one, and the name will be converted to (${parsedSwitchName.name}) if you omit this warning`);
695
+ const originalHandler = switchData.handler;
696
+ switchData.handler = (...args) => {
697
+ return !originalHandler(...args);
698
+ };
699
+ }
700
+ this.switches[parsedSwitchName.name] = switchData;
662
701
  }
663
702
  return this;
664
703
  }
@@ -695,7 +734,11 @@ class EventAction {
695
734
  console.warn(`Action named (${name}) is already registered and need (override) option to be true to be overridden`);
696
735
  continue;
697
736
  }
698
- this.actions[name] = actionData;
737
+ const parsedActionName = EventAction.parseActionName(name);
738
+ if (parsedActionName.hasOr) {
739
+ console.warn(`Action name cannot start with (||), as it is used to detect if the action hasOr, which is used as an indicator to not run other actions if this one gets executed, Please not that the action name will be converted to (${parsedActionName.name}) if you omit this warning`);
740
+ }
741
+ this.actions[parsedActionName.name] = actionData;
699
742
  }
700
743
  return this;
701
744
  }
@@ -729,8 +772,8 @@ class EventAction {
729
772
  switches: actionData.slice(2).map(switchData => {
730
773
  const [name = '', param = ''] = Array.isArray(switchData) ? switchData : switchData.split(':');
731
774
  return {
732
- name,
733
- param
775
+ param,
776
+ ...EventAction.parseSwitchName(name)
734
777
  };
735
778
  }),
736
779
  ...EventAction.parseActionName(actionData[0])
@@ -746,7 +789,7 @@ class EventAction {
746
789
  }
747
790
  return attributeString
748
791
  .split('&&')
749
- .map(EventAction.parseActionString);
792
+ .map(EventAction.parseActionString.bind(EventAction));
750
793
  }
751
794
  /**
752
795
  * for internal use
@@ -798,7 +841,7 @@ class EventAction {
798
841
  const checkSwitches = parsedAction.switches.length === 0 ? true : parsedAction.switches.every(switchData => {
799
842
  const staticValue = staticSwitches[switchData.name]?.get(switchData.param);
800
843
  if (staticValue !== undefined)
801
- return staticValue;
844
+ return switchData.isNegated ? !staticValue : staticValue;
802
845
  const switchAction = this.switches[switchData.name];
803
846
  if (!switchAction) {
804
847
  console.warn(`There is no registered switch with the name (${switchData.name}) for the event (${eventName})`, matchedTarget);
@@ -817,7 +860,7 @@ class EventAction {
817
860
  const map = staticSwitches[switchData.name] ||= new Map();
818
861
  map.set(switchData.param, value);
819
862
  }
820
- return value;
863
+ return switchData.isNegated ? !value : value;
821
864
  });
822
865
  if (!checkSwitches)
823
866
  continue;
package/package.json CHANGED
@@ -3,9 +3,9 @@
3
3
  "type": "module",
4
4
  "description": "A customizable web-components library with lit",
5
5
  "private": false,
6
- "version": "0.0.0-alpha.4",
6
+ "version": "0.0.0-alpha.5",
7
7
  "dependencies": {
8
- "@mustib/utils": "2.7.0"
8
+ "@mustib/utils": "2.8.1"
9
9
  },
10
10
  "peerDependencies": {
11
11
  "lit": "^3.3.1"