@openremote/or-tree-menu 1.8.0-snapshot.20250725120002 → 1.8.0-snapshot.20250728102340
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.
- package/README.md +1 -1
- package/custom-elements.json +22 -22
- package/dist/umd/index.bundle.js +731 -731
- package/dist/umd/index.bundle.js.map +1 -1
- package/dist/umd/index.js +731 -731
- package/dist/umd/index.js.map +1 -1
- package/dist/umd/index.orbundle.js +789 -789
- package/dist/umd/index.orbundle.js.map +1 -1
- package/lib/index.js +103 -713
- package/lib/model.js +1 -76
- package/lib/or-tree-group.js +49 -226
- package/lib/or-tree-node.js +40 -111
- package/lib/util.js +1 -39
- package/package.json +5 -5
- package/rspack.config.js +13 -13
package/lib/model.js
CHANGED
|
@@ -1,76 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* Copyright 2025, OpenRemote Inc.
|
|
3
|
-
*
|
|
4
|
-
* See the CONTRIBUTORS.txt file in the distribution for a
|
|
5
|
-
* full listing of individual contributors.
|
|
6
|
-
*
|
|
7
|
-
* This program is free software: you can redistribute it and/or modify
|
|
8
|
-
* it under the terms of the GNU Affero General Public License as
|
|
9
|
-
* published by the Free Software Foundation, either version 3 of the
|
|
10
|
-
* License, or (at your option) any later version.
|
|
11
|
-
*
|
|
12
|
-
* This program is distributed in the hope that it will be useful,
|
|
13
|
-
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
-
* GNU Affero General Public License for more details.
|
|
16
|
-
*
|
|
17
|
-
* You should have received a copy of the GNU Affero General Public License
|
|
18
|
-
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
19
|
-
*/
|
|
20
|
-
/**
|
|
21
|
-
* List of possible options for tree menu selection.
|
|
22
|
-
* The order within the enum is based on restrictiveness.
|
|
23
|
-
*
|
|
24
|
-
* - **LEAF** - only allows a single node to be selected, and forbids the selection of any parent node.
|
|
25
|
-
* - **SINGLE** - only allows a single node to be selected, but does allow the selection of the parent node.
|
|
26
|
-
* - **MULTI** - allows selecting multiple nodes using keyboard controls. (control and shift)
|
|
27
|
-
*/
|
|
28
|
-
export var TreeMenuSelection;
|
|
29
|
-
(function (TreeMenuSelection) {
|
|
30
|
-
TreeMenuSelection["LEAF"] = "leaf";
|
|
31
|
-
TreeMenuSelection["SINGLE"] = "single";
|
|
32
|
-
TreeMenuSelection["MULTI"] = "multi";
|
|
33
|
-
})(TreeMenuSelection || (TreeMenuSelection = {}));
|
|
34
|
-
/**
|
|
35
|
-
* List of sorting options in the header of the tree menu.
|
|
36
|
-
* By default, we include alphabetically sorting, but can be expanded by class inheritors.
|
|
37
|
-
*/
|
|
38
|
-
export var TreeMenuSorting;
|
|
39
|
-
(function (TreeMenuSorting) {
|
|
40
|
-
TreeMenuSorting["A_TO_Z"] = "a_to_z";
|
|
41
|
-
TreeMenuSorting["Z_TO_A"] = "z_to_a";
|
|
42
|
-
})(TreeMenuSorting || (TreeMenuSorting = {}));
|
|
43
|
-
/**
|
|
44
|
-
* Model for the SELECT event that {@link OrTreeMenu} can dispatch.
|
|
45
|
-
* Once a node is selected, a list of all the selected nodes will be shared with the consumer elements.
|
|
46
|
-
*/
|
|
47
|
-
export class OrTreeSelectEvent extends CustomEvent {
|
|
48
|
-
constructor(nodes) {
|
|
49
|
-
super(OrTreeSelectEvent.NAME, {
|
|
50
|
-
bubbles: true,
|
|
51
|
-
composed: true,
|
|
52
|
-
detail: nodes
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
OrTreeSelectEvent.NAME = "or-tree-select";
|
|
57
|
-
/**
|
|
58
|
-
* Model for the DRAG event that {@link OrTreeMenu} can dispatch.
|
|
59
|
-
* Once a node is dragged into (or outside) a group, we send details to consumer elements.
|
|
60
|
-
*/
|
|
61
|
-
export class OrTreeDragEvent extends CustomEvent {
|
|
62
|
-
constructor(nodes, groupNode, newNodes = []) {
|
|
63
|
-
super(OrTreeDragEvent.NAME, {
|
|
64
|
-
bubbles: true,
|
|
65
|
-
composed: true,
|
|
66
|
-
cancelable: true,
|
|
67
|
-
detail: {
|
|
68
|
-
nodes: nodes,
|
|
69
|
-
groupNode: groupNode,
|
|
70
|
-
newNodes: newNodes
|
|
71
|
-
}
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
OrTreeDragEvent.NAME = "or-tree-drag";
|
|
76
|
-
//# sourceMappingURL=model.js.map
|
|
1
|
+
export var TreeMenuSelection;!function(e){e.LEAF="leaf",e.SINGLE="single",e.MULTI="multi"}(TreeMenuSelection||(TreeMenuSelection={}));export var TreeMenuSorting;!function(e){e.A_TO_Z="a_to_z",e.Z_TO_A="z_to_a"}(TreeMenuSorting||(TreeMenuSorting={}));export class OrTreeSelectEvent extends CustomEvent{constructor(e){super(OrTreeSelectEvent.NAME,{bubbles:!0,composed:!0,detail:e})}}OrTreeSelectEvent.NAME="or-tree-select";export class OrTreeDragEvent extends CustomEvent{constructor(e,r,t=[]){super(OrTreeDragEvent.NAME,{bubbles:!0,composed:!0,cancelable:!0,detail:{nodes:e,groupNode:r,newNodes:t}})}}OrTreeDragEvent.NAME="or-tree-drag";
|
package/lib/or-tree-group.js
CHANGED
|
@@ -1,226 +1,49 @@
|
|
|
1
|
-
var __decorate
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
height: 44px;
|
|
51
|
-
display: flex;
|
|
52
|
-
align-items: center;
|
|
53
|
-
aspect-ratio: 1/1.25;
|
|
54
|
-
padding-left: 4px;
|
|
55
|
-
font-size: 18px;
|
|
56
|
-
color: #cccccc;
|
|
57
|
-
z-index: 10;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
#chevron:hover {
|
|
61
|
-
color: unset;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
:host(:not([readonly])) > #chevron {
|
|
65
|
-
cursor: pointer;
|
|
66
|
-
}
|
|
67
|
-
`;
|
|
68
|
-
/**
|
|
69
|
-
* @slot - Default slot for child nodes within the group
|
|
70
|
-
* @slot parent - Slot for inserting a parent node
|
|
71
|
-
* @csspart chevron - The chevron icon element for expanding/collapsing the group.
|
|
72
|
-
*/
|
|
73
|
-
let OrTreeGroup = class OrTreeGroup extends LitElement {
|
|
74
|
-
constructor() {
|
|
75
|
-
super(...arguments);
|
|
76
|
-
/**
|
|
77
|
-
* Determines the visibility of child nodes.
|
|
78
|
-
* Setting this to `false` hides them, and acts as a 'collapsed' state.
|
|
79
|
-
*/
|
|
80
|
-
this.expanded = false;
|
|
81
|
-
/**
|
|
82
|
-
* Only allows child nodes to be selected, making the expander (parent node) readonly.
|
|
83
|
-
* If this is set to false, only the chevron icon can be used to collapse/expand the list.
|
|
84
|
-
*/
|
|
85
|
-
this.leaf = false;
|
|
86
|
-
/**
|
|
87
|
-
* Makes the group readonly
|
|
88
|
-
*/
|
|
89
|
-
this.readonly = false;
|
|
90
|
-
/** A click event listener on the component, used for selecting, expanding, and collapsing the group */
|
|
91
|
-
this._slotClickListener = (e) => this.leaf ? this._onExpandToggle(e) : null;
|
|
92
|
-
/** A click event listener on the chevron, used for expanding/collapsing the group */
|
|
93
|
-
this._chevronClickListener = (e) => this._onExpandToggle(e);
|
|
94
|
-
}
|
|
95
|
-
static get styles() {
|
|
96
|
-
return [getStyles()];
|
|
97
|
-
}
|
|
98
|
-
/** Selects the group (parent) node. */
|
|
99
|
-
select() {
|
|
100
|
-
const groupNode = this.getGroupNode();
|
|
101
|
-
if (!this.leaf && groupNode) {
|
|
102
|
-
groupNode.selected = true;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
/** Selects the group node itself, and all children nodes within that group. */
|
|
106
|
-
selectAll() {
|
|
107
|
-
this.select();
|
|
108
|
-
this.getChildNodes().forEach(node => node.selected = true);
|
|
109
|
-
}
|
|
110
|
-
/** Deselects the group (parent) node. */
|
|
111
|
-
deselect() {
|
|
112
|
-
const groupNode = this.getGroupNode();
|
|
113
|
-
if (groupNode) {
|
|
114
|
-
groupNode.selected = false;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
/** Deselects the group node itself, and all children nodes within that group. */
|
|
118
|
-
deselectAll() {
|
|
119
|
-
this.deselect();
|
|
120
|
-
this.getChildNodes().forEach(node => node.selected = false);
|
|
121
|
-
}
|
|
122
|
-
/** Returns the group (parent) node ({@link OrTreeNode}) using a query selector. */
|
|
123
|
-
getGroupNode() {
|
|
124
|
-
var _a;
|
|
125
|
-
return (_a = this._parentNodes) === null || _a === void 0 ? void 0 : _a[0];
|
|
126
|
-
}
|
|
127
|
-
/** Returns a list of all children nodes ({@link OrTreeNode}) within the group, using a query selector. */
|
|
128
|
-
getChildNodes() {
|
|
129
|
-
return Array.from(this._childNodes || [])
|
|
130
|
-
.map(n => n.querySelector('or-tree-node'))
|
|
131
|
-
.filter(n => n != null);
|
|
132
|
-
}
|
|
133
|
-
firstUpdated(changedProps) {
|
|
134
|
-
var _a;
|
|
135
|
-
(_a = this._parentNodes) === null || _a === void 0 ? void 0 : _a.forEach(elem => {
|
|
136
|
-
elem.addEventListener("click", this._slotClickListener);
|
|
137
|
-
});
|
|
138
|
-
return super.firstUpdated(changedProps);
|
|
139
|
-
}
|
|
140
|
-
disconnectedCallback() {
|
|
141
|
-
var _a;
|
|
142
|
-
(_a = this._parentNodes) === null || _a === void 0 ? void 0 : _a.forEach(elem => {
|
|
143
|
-
elem.removeEventListener("click", this._slotClickListener);
|
|
144
|
-
});
|
|
145
|
-
super.disconnectedCallback();
|
|
146
|
-
}
|
|
147
|
-
render() {
|
|
148
|
-
return html `
|
|
149
|
-
${when(!this.readonly, () => this._getIconTemplate(this.expanded))}
|
|
150
|
-
<slot name="parent"></slot>
|
|
151
|
-
<ol ?hidden=${!this.expanded}>
|
|
152
|
-
<slot @slotchange=${this._onSlotChange}></slot>
|
|
153
|
-
</ol>
|
|
154
|
-
`;
|
|
155
|
-
}
|
|
156
|
-
/**
|
|
157
|
-
* Returns an HTML template that represents the icon for this group.
|
|
158
|
-
* @param expanded State of the group
|
|
159
|
-
*/
|
|
160
|
-
_getIconTemplate(expanded = false) {
|
|
161
|
-
return html `
|
|
162
|
-
<or-icon id="chevron" part="chevron" icon="${expanded ? "chevron-down" : "chevron-right"}"
|
|
163
|
-
@click="${this._chevronClickListener}"
|
|
164
|
-
></or-icon>
|
|
165
|
-
`;
|
|
166
|
-
}
|
|
167
|
-
/**
|
|
168
|
-
* Function that expands/collapses the group, changing the visibility of the child nodes.
|
|
169
|
-
*/
|
|
170
|
-
_onExpandToggle(_ev) {
|
|
171
|
-
this.expanded = !this.expanded;
|
|
172
|
-
}
|
|
173
|
-
/**
|
|
174
|
-
* Event listener for 'slotchange' of the default slot.
|
|
175
|
-
* Normally triggers when <or-tree-node> elements are added or removed.
|
|
176
|
-
*/
|
|
177
|
-
_onSlotChange(_ev) {
|
|
178
|
-
this._applyIndentToChildren();
|
|
179
|
-
}
|
|
180
|
-
/**
|
|
181
|
-
* Function that applies CSS to TreeNode based on the group indentation.
|
|
182
|
-
* It loops through all parent elements, and detects the amount of or-tree-group elements it is in.
|
|
183
|
-
* The more nested in the tree, the more left handed padding is applied.
|
|
184
|
-
* @param children Node elements to apply padding to.
|
|
185
|
-
*/
|
|
186
|
-
_applyIndentToChildren(children = this.getChildNodes()) {
|
|
187
|
-
const countGroups = (elem) => {
|
|
188
|
-
let count = 0;
|
|
189
|
-
while (elem) {
|
|
190
|
-
if (elem.tagName.toLowerCase() === "or-tree-group") {
|
|
191
|
-
count++;
|
|
192
|
-
}
|
|
193
|
-
elem = elem.parentElement;
|
|
194
|
-
}
|
|
195
|
-
return count;
|
|
196
|
-
};
|
|
197
|
-
children.forEach(child => {
|
|
198
|
-
let groupAmount = countGroups(child);
|
|
199
|
-
if (child.slot === "parent") {
|
|
200
|
-
groupAmount--; // Parent slot is the group itself, so remove 1
|
|
201
|
-
}
|
|
202
|
-
// Apply indent as padding to the node
|
|
203
|
-
child.style.setProperty("--or-tree-node-indent", `${24 + (groupAmount * 12)}px`);
|
|
204
|
-
});
|
|
205
|
-
}
|
|
206
|
-
};
|
|
207
|
-
__decorate([
|
|
208
|
-
property({ type: Boolean, reflect: true })
|
|
209
|
-
], OrTreeGroup.prototype, "expanded", void 0);
|
|
210
|
-
__decorate([
|
|
211
|
-
property({ type: Boolean })
|
|
212
|
-
], OrTreeGroup.prototype, "leaf", void 0);
|
|
213
|
-
__decorate([
|
|
214
|
-
property({ type: Boolean })
|
|
215
|
-
], OrTreeGroup.prototype, "readonly", void 0);
|
|
216
|
-
__decorate([
|
|
217
|
-
queryAssignedElements({ slot: undefined })
|
|
218
|
-
], OrTreeGroup.prototype, "_childNodes", void 0);
|
|
219
|
-
__decorate([
|
|
220
|
-
queryAssignedElements({ slot: "parent" })
|
|
221
|
-
], OrTreeGroup.prototype, "_parentNodes", void 0);
|
|
222
|
-
OrTreeGroup = __decorate([
|
|
223
|
-
customElement("or-tree-group")
|
|
224
|
-
], OrTreeGroup);
|
|
225
|
-
export { OrTreeGroup };
|
|
226
|
-
//# sourceMappingURL=or-tree-group.js.map
|
|
1
|
+
var __decorate=this&&this.__decorate||function(e,t,o,r){var n,l=arguments.length,s=l<3?t:null===r?r=Object.getOwnPropertyDescriptor(t,o):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,o,r);else for(var i=e.length-1;i>=0;i--)(n=e[i])&&(s=(l<3?n(s):l>3?n(t,o,s):n(t,o))||s);return l>3&&s&&Object.defineProperty(t,o,s),s};import{css as e,html as t,LitElement as o}from"lit";import{customElement as r,property as n,queryAssignedElements as l}from"lit/decorators.js";import{when as s}from"lit/directives/when.js";let getStyles=()=>e`
|
|
2
|
+
* {
|
|
3
|
+
box-sizing: border-box;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
:host {
|
|
7
|
+
position: relative;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
ol {
|
|
11
|
+
list-style: none;
|
|
12
|
+
padding: 0;
|
|
13
|
+
margin: 0;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
::slotted(*[slot="parent"]) {
|
|
17
|
+
cursor: pointer;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
#chevron {
|
|
21
|
+
position: absolute;
|
|
22
|
+
height: 44px;
|
|
23
|
+
display: flex;
|
|
24
|
+
align-items: center;
|
|
25
|
+
aspect-ratio: 1/1.25;
|
|
26
|
+
padding-left: 4px;
|
|
27
|
+
font-size: 18px;
|
|
28
|
+
color: #cccccc;
|
|
29
|
+
z-index: 10;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
#chevron:hover {
|
|
33
|
+
color: unset;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
:host(:not([readonly])) > #chevron {
|
|
37
|
+
cursor: pointer;
|
|
38
|
+
}
|
|
39
|
+
`,OrTreeGroup=class extends o{constructor(){super(...arguments),this.expanded=!1,this.leaf=!1,this.readonly=!1,this._slotClickListener=e=>this.leaf?this._onExpandToggle(e):null,this._chevronClickListener=e=>this._onExpandToggle(e)}static get styles(){return[getStyles()]}select(){let e=this.getGroupNode();!this.leaf&&e&&(e.selected=!0)}selectAll(){this.select(),this.getChildNodes().forEach(e=>e.selected=!0)}deselect(){let e=this.getGroupNode();e&&(e.selected=!1)}deselectAll(){this.deselect(),this.getChildNodes().forEach(e=>e.selected=!1)}getGroupNode(){var e;return null==(e=this._parentNodes)?void 0:e[0]}getChildNodes(){return Array.from(this._childNodes||[]).map(e=>e.querySelector("or-tree-node")).filter(e=>null!=e)}firstUpdated(e){var t;return null==(t=this._parentNodes)||t.forEach(e=>{e.addEventListener("click",this._slotClickListener)}),super.firstUpdated(e)}disconnectedCallback(){var e;null==(e=this._parentNodes)||e.forEach(e=>{e.removeEventListener("click",this._slotClickListener)}),super.disconnectedCallback()}render(){return t`
|
|
40
|
+
${s(!this.readonly,()=>this._getIconTemplate(this.expanded))}
|
|
41
|
+
<slot name="parent"></slot>
|
|
42
|
+
<ol ?hidden=${!this.expanded}>
|
|
43
|
+
<slot @slotchange=${this._onSlotChange}></slot>
|
|
44
|
+
</ol>
|
|
45
|
+
`}_getIconTemplate(e=!1){return t`
|
|
46
|
+
<or-icon id="chevron" part="chevron" icon="${e?"chevron-down":"chevron-right"}"
|
|
47
|
+
@click="${this._chevronClickListener}"
|
|
48
|
+
></or-icon>
|
|
49
|
+
`}_onExpandToggle(e){this.expanded=!this.expanded}_onSlotChange(e){this._applyIndentToChildren()}_applyIndentToChildren(e=this.getChildNodes()){e.forEach(e=>{let t=(e=>{let t=0;for(;e;)"or-tree-group"===e.tagName.toLowerCase()&&t++,e=e.parentElement;return t})(e);"parent"===e.slot&&t--,e.style.setProperty("--or-tree-node-indent",`${24+12*t}px`)})}};__decorate([n({type:Boolean,reflect:!0})],OrTreeGroup.prototype,"expanded",void 0),__decorate([n({type:Boolean})],OrTreeGroup.prototype,"leaf",void 0),__decorate([n({type:Boolean})],OrTreeGroup.prototype,"readonly",void 0),__decorate([l({slot:void 0})],OrTreeGroup.prototype,"_childNodes",void 0),__decorate([l({slot:"parent"})],OrTreeGroup.prototype,"_parentNodes",void 0),OrTreeGroup=__decorate([r("or-tree-group")],OrTreeGroup);export{OrTreeGroup};
|
package/lib/or-tree-node.js
CHANGED
|
@@ -1,114 +1,43 @@
|
|
|
1
|
-
var __decorate
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
-
};
|
|
7
|
-
/*
|
|
8
|
-
* Copyright 2025, OpenRemote Inc.
|
|
9
|
-
*
|
|
10
|
-
* See the CONTRIBUTORS.txt file in the distribution for a
|
|
11
|
-
* full listing of individual contributors.
|
|
12
|
-
*
|
|
13
|
-
* This program is free software: you can redistribute it and/or modify
|
|
14
|
-
* it under the terms of the GNU Affero General Public License as
|
|
15
|
-
* published by the Free Software Foundation, either version 3 of the
|
|
16
|
-
* License, or (at your option) any later version.
|
|
17
|
-
*
|
|
18
|
-
* This program is distributed in the hope that it will be useful,
|
|
19
|
-
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
20
|
-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
21
|
-
* GNU Affero General Public License for more details.
|
|
22
|
-
*
|
|
23
|
-
* You should have received a copy of the GNU Affero General Public License
|
|
24
|
-
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
25
|
-
*/
|
|
26
|
-
import { css, html, LitElement } from "lit";
|
|
27
|
-
import { customElement, property } from "lit/decorators.js";
|
|
28
|
-
const styles = css `
|
|
29
|
-
* {
|
|
30
|
-
box-sizing: border-box;
|
|
31
|
-
}
|
|
32
|
-
:host {
|
|
33
|
-
width: 100%;
|
|
34
|
-
height: var(--or-tree-node-height, 44px);
|
|
35
|
-
padding: 6px 12px 6px var(--or-tree-node-indent, 24px);
|
|
36
|
-
background: var(--or-tree-node-background, transparent);
|
|
37
|
-
border-left: 4px solid transparent;
|
|
38
|
-
display: flex;
|
|
39
|
-
align-items: center;
|
|
40
|
-
gap: var(--or-tree-node-gap, 8px);
|
|
41
|
-
overflow: hidden;
|
|
42
|
-
user-select: none;
|
|
43
|
-
--or-icon-width: 20px;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
:host(:not([readonly])) {
|
|
47
|
-
cursor: pointer;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
:host([readonly]) {
|
|
51
|
-
cursor: not-allowed;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
:host(:not([readonly]):hover) {
|
|
55
|
-
background: var(--or-tree-node-backgrond--hovered, #f8f9fa);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
:host([selected]) {
|
|
59
|
-
background: var(--or-tree-node-background--selected, #f1f3f5);
|
|
60
|
-
border-left: 4px solid var(--or-tree-node-color--selected, var(--or-app-color4, #4d9d2a));
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
::slotted(*:not([slot])) {
|
|
64
|
-
flex: 1;
|
|
65
|
-
}
|
|
66
|
-
`;
|
|
67
|
-
/**
|
|
68
|
-
* @slot prefix - Appends elements to the left hand side of the node, commonly used for icons.
|
|
69
|
-
* @slot - Default slot for the main content, commonly used for text.
|
|
70
|
-
* @slot suffix - Appends elements to the right hand side of the node.
|
|
71
|
-
*
|
|
72
|
-
* @cssprop --or-tree-node-height - Controls the height of the node
|
|
73
|
-
* @cssprop --or-tree-node-indent - Controls the left padding of the node
|
|
74
|
-
*
|
|
75
|
-
* @cssprop --or-tree-node-background - Sets the default background
|
|
76
|
-
* @cssprop --or-tree-node-background--hovered - Sets the background while hovering
|
|
77
|
-
* @cssprop --or-tree-node-background--selected - Sets the background when selected
|
|
78
|
-
*
|
|
79
|
-
* @cssprop --or-tree-node-color--selected - Sets the primary color of the node when selected
|
|
80
|
-
*/
|
|
81
|
-
let OrTreeNode = class OrTreeNode extends LitElement {
|
|
82
|
-
constructor() {
|
|
83
|
-
super(...arguments);
|
|
84
|
-
/**
|
|
85
|
-
* HTML attribute that only applies CSS, showing this node cannot be interacted with.
|
|
86
|
-
*/
|
|
87
|
-
this.readonly = false;
|
|
88
|
-
/**
|
|
89
|
-
* HTML attribute that only applies CSS, marking the node as 'selected'.
|
|
90
|
-
*/
|
|
91
|
-
this.selected = false;
|
|
1
|
+
var __decorate=this&&this.__decorate||function(e,r,o,t){var d,n=arguments.length,l=n<3?r:null===t?t=Object.getOwnPropertyDescriptor(r,o):t;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)l=Reflect.decorate(e,r,o,t);else for(var s=e.length-1;s>=0;s--)(d=e[s])&&(l=(n<3?d(l):n>3?d(r,o,l):d(r,o))||l);return n>3&&l&&Object.defineProperty(r,o,l),l};import{css as e,html as r,LitElement as o}from"lit";import{customElement as t,property as d}from"lit/decorators.js";let styles=e`
|
|
2
|
+
* {
|
|
3
|
+
box-sizing: border-box;
|
|
92
4
|
}
|
|
93
|
-
|
|
94
|
-
|
|
5
|
+
:host {
|
|
6
|
+
width: 100%;
|
|
7
|
+
height: var(--or-tree-node-height, 44px);
|
|
8
|
+
padding: 6px 12px 6px var(--or-tree-node-indent, 24px);
|
|
9
|
+
background: var(--or-tree-node-background, transparent);
|
|
10
|
+
border-left: 4px solid transparent;
|
|
11
|
+
display: flex;
|
|
12
|
+
align-items: center;
|
|
13
|
+
gap: var(--or-tree-node-gap, 8px);
|
|
14
|
+
overflow: hidden;
|
|
15
|
+
user-select: none;
|
|
16
|
+
--or-icon-width: 20px;
|
|
95
17
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
<slot></slot>
|
|
100
|
-
<slot name="suffix"></slot>
|
|
101
|
-
`;
|
|
18
|
+
|
|
19
|
+
:host(:not([readonly])) {
|
|
20
|
+
cursor: pointer;
|
|
102
21
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
]
|
|
113
|
-
|
|
114
|
-
|
|
22
|
+
|
|
23
|
+
:host([readonly]) {
|
|
24
|
+
cursor: not-allowed;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
:host(:not([readonly]):hover) {
|
|
28
|
+
background: var(--or-tree-node-backgrond--hovered, #f8f9fa);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
:host([selected]) {
|
|
32
|
+
background: var(--or-tree-node-background--selected, #f1f3f5);
|
|
33
|
+
border-left: 4px solid var(--or-tree-node-color--selected, var(--or-app-color4, #4d9d2a));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
::slotted(*:not([slot])) {
|
|
37
|
+
flex: 1;
|
|
38
|
+
}
|
|
39
|
+
`,OrTreeNode=class extends o{constructor(){super(...arguments),this.readonly=!1,this.selected=!1}static get styles(){return[styles]}render(){return r`
|
|
40
|
+
<slot name="prefix"></slot>
|
|
41
|
+
<slot></slot>
|
|
42
|
+
<slot name="suffix"></slot>
|
|
43
|
+
`}};__decorate([d({type:Boolean,reflect:!0})],OrTreeNode.prototype,"readonly",void 0),__decorate([d({type:Boolean,reflect:!0})],OrTreeNode.prototype,"selected",void 0),OrTreeNode=__decorate([t("or-tree-node")],OrTreeNode);export{OrTreeNode};
|
package/lib/util.js
CHANGED
|
@@ -1,39 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* Utility function that moves an array of {@link TreeNode} into another {@link TreeNode}, by adding them to their children.
|
|
3
|
-
* The function takes care of removing the nodes from the former group, and makes sure no duplicates end up in the list.
|
|
4
|
-
*
|
|
5
|
-
* @param nodesToMove - The array of nodes that are moved into a group.
|
|
6
|
-
* @param groupNode - The group node to insert nodesToMove in.
|
|
7
|
-
* @param treeNodes - Full list of nodes in the tree menu.
|
|
8
|
-
*/
|
|
9
|
-
export function moveNodesToGroupNode(nodesToMove, groupNode, treeNodes = []) {
|
|
10
|
-
console.debug(`Moving nodes '${nodesToMove.map(node => node.label).join(', ')}' into group '${groupNode === null || groupNode === void 0 ? void 0 : groupNode.label}'. Tree nodes are`, groupNode);
|
|
11
|
-
function filterAndAdd(nodes) {
|
|
12
|
-
return nodes.map(node => {
|
|
13
|
-
if (nodesToMove.some(nodeToMove => node.id === nodeToMove.id)) {
|
|
14
|
-
console.debug("Removed the node from original position.");
|
|
15
|
-
return null; // Removes the node from its original position
|
|
16
|
-
}
|
|
17
|
-
const newNode = Object.assign({}, node);
|
|
18
|
-
// Recursively loop through children
|
|
19
|
-
if (newNode.children) {
|
|
20
|
-
newNode.children = filterAndAdd(newNode.children).filter(child => child !== null);
|
|
21
|
-
}
|
|
22
|
-
// If the currently looped node is the target group node, add the nodes to its children
|
|
23
|
-
if (groupNode && node.id === (groupNode === null || groupNode === void 0 ? void 0 : groupNode.id)) {
|
|
24
|
-
nodesToMove.forEach(nodeToMove => {
|
|
25
|
-
newNode.children = newNode.children ? [...newNode.children, nodeToMove] : [nodeToMove];
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
return newNode;
|
|
29
|
-
}).filter(node => node !== null);
|
|
30
|
-
}
|
|
31
|
-
// Start the recursive function
|
|
32
|
-
const newNodes = filterAndAdd(treeNodes);
|
|
33
|
-
// If no groupNode is provided, add the nodesToMove to the top level
|
|
34
|
-
if (!groupNode) {
|
|
35
|
-
newNodes.push(...nodesToMove);
|
|
36
|
-
}
|
|
37
|
-
return newNodes;
|
|
38
|
-
}
|
|
39
|
-
//# sourceMappingURL=util.js.map
|
|
1
|
+
export function moveNodesToGroupNode(e,n,o=[]){console.debug(`Moving nodes '${e.map(e=>e.label).join(", ")}' into group '${null==n?void 0:n.label}'. Tree nodes are`,n);let l=function o(l){return l.map(l=>{if(e.some(e=>l.id===e.id))return console.debug("Removed the node from original position."),null;let i=Object.assign({},l);return i.children&&(i.children=o(i.children).filter(e=>null!==e)),n&&l.id===(null==n?void 0:n.id)&&e.forEach(e=>{i.children=i.children?[...i.children,e]:[e]}),i}).filter(e=>null!==e)}(o);return n||l.push(...e),l}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openremote/or-tree-menu",
|
|
3
|
-
"version": "1.8.0-snapshot.
|
|
3
|
+
"version": "1.8.0-snapshot.20250728102340",
|
|
4
4
|
"description": "Web Component for displaying a tree menu of items with a predefined hierarchy",
|
|
5
5
|
"customElements": "custom-elements.json",
|
|
6
6
|
"main": "dist/umd/index.bundle.js",
|
|
@@ -19,13 +19,13 @@
|
|
|
19
19
|
"license": "AGPL-3.0-or-later",
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"@mdi/js": "^5.9.55",
|
|
22
|
-
"@openremote/core": "1.8.0-snapshot.
|
|
23
|
-
"@openremote/or-mwc-components": "1.8.0-snapshot.
|
|
24
|
-
"@openremote/or-translate": "1.8.0-snapshot.
|
|
22
|
+
"@openremote/core": "1.8.0-snapshot.20250728102340",
|
|
23
|
+
"@openremote/or-mwc-components": "1.8.0-snapshot.20250728102340",
|
|
24
|
+
"@openremote/or-translate": "1.8.0-snapshot.20250728102340",
|
|
25
25
|
"lit": "^3.2.1"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
|
-
"@openremote/util": "1.8.0-snapshot.
|
|
28
|
+
"@openremote/util": "1.8.0-snapshot.20250728102340"
|
|
29
29
|
},
|
|
30
30
|
"publishConfig": {
|
|
31
31
|
"access": "public"
|
package/rspack.config.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
const util = require("@openremote/util");
|
|
2
|
-
|
|
3
|
-
bundles = {
|
|
4
|
-
"index": {
|
|
5
|
-
excludeOr: true
|
|
6
|
-
},
|
|
7
|
-
"index.bundle": {
|
|
8
|
-
excludeOr: true,
|
|
9
|
-
},
|
|
10
|
-
"index.orbundle": undefined
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
module.exports = util.generateExports(__dirname);
|
|
1
|
+
const util = require("@openremote/util");
|
|
2
|
+
|
|
3
|
+
bundles = {
|
|
4
|
+
"index": {
|
|
5
|
+
excludeOr: true
|
|
6
|
+
},
|
|
7
|
+
"index.bundle": {
|
|
8
|
+
excludeOr: true,
|
|
9
|
+
},
|
|
10
|
+
"index.orbundle": undefined
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
module.exports = util.generateExports(__dirname);
|