@rettangoli/ui 0.1.8 → 0.1.10
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/package.json
CHANGED
|
@@ -38,6 +38,7 @@ export const handleOnUpdate = (deps, payload) => {
|
|
|
38
38
|
export const handleButtonClick = (deps, payload) => {
|
|
39
39
|
const { store, render, getRefIds, props } = deps;
|
|
40
40
|
const event = payload._event;
|
|
41
|
+
event.stopPropagation();
|
|
41
42
|
|
|
42
43
|
const button = getRefIds()['select-button'].elm;
|
|
43
44
|
|
|
@@ -73,6 +74,7 @@ export const handleClickOptionsPopoverOverlay = (deps, payload) => {
|
|
|
73
74
|
export const handleOptionClick = (deps, payload) => {
|
|
74
75
|
const { render, dispatchEvent, props, store } = deps;
|
|
75
76
|
const event = payload._event;
|
|
77
|
+
event.stopPropagation();
|
|
76
78
|
const id = event.currentTarget.id.replace('option-', '');
|
|
77
79
|
|
|
78
80
|
const option = props.options[id];
|
|
@@ -145,7 +147,8 @@ export const handleClearClick = (deps, payload) => {
|
|
|
145
147
|
|
|
146
148
|
export const handleAddOptionClick = (deps, payload) => {
|
|
147
149
|
const { store, render, dispatchEvent } = deps;
|
|
148
|
-
|
|
150
|
+
const { _event: event } = payload;
|
|
151
|
+
event.stopPropagation();
|
|
149
152
|
// Close the popover
|
|
150
153
|
store.closeOptionsPopover();
|
|
151
154
|
|
|
@@ -12,7 +12,7 @@ function flattenItems(items, selectedItemId = null) {
|
|
|
12
12
|
for (const item of items) {
|
|
13
13
|
const itemId = item.id || item.href || item.path;
|
|
14
14
|
const isSelected = selectedItemId === itemId;
|
|
15
|
-
|
|
15
|
+
|
|
16
16
|
// Add the parent item if it's not just a group label
|
|
17
17
|
result.push({
|
|
18
18
|
id: itemId,
|
|
@@ -31,7 +31,7 @@ function flattenItems(items, selectedItemId = null) {
|
|
|
31
31
|
for (const subItem of item.items) {
|
|
32
32
|
const subItemId = subItem.id || subItem.href || subItem.path;
|
|
33
33
|
const isSubSelected = selectedItemId === subItemId;
|
|
34
|
-
|
|
34
|
+
|
|
35
35
|
result.push({
|
|
36
36
|
id: subItemId,
|
|
37
37
|
title: subItem.title,
|
|
@@ -139,4 +139,4 @@ export const selectItem = ({ state, props, attrs }, id) => {
|
|
|
139
139
|
|
|
140
140
|
export const setState = (state) => {
|
|
141
141
|
// State management if needed
|
|
142
|
-
}
|
|
142
|
+
}
|
|
@@ -11,36 +11,41 @@ class RettangoliPopoverElement extends HTMLElement {
|
|
|
11
11
|
display: contents;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
dialog {
|
|
15
|
+
padding: 0;
|
|
16
|
+
border: none;
|
|
17
|
+
background: transparent;
|
|
18
|
+
margin: 0;
|
|
19
|
+
overflow: visible;
|
|
20
|
+
color: inherit;
|
|
21
|
+
scrollbar-width: none;
|
|
22
|
+
outline: none;
|
|
15
23
|
position: fixed;
|
|
16
24
|
top: 0;
|
|
17
25
|
left: 0;
|
|
18
26
|
width: 100vw;
|
|
19
27
|
height: 100vh;
|
|
20
|
-
|
|
21
|
-
|
|
28
|
+
/* Prevent dialog from being focused */
|
|
29
|
+
pointer-events: none;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
dialog::backdrop {
|
|
33
|
+
background-color: transparent;
|
|
34
|
+
/* Allow backdrop to receive clicks */
|
|
35
|
+
pointer-events: auto;
|
|
22
36
|
}
|
|
23
37
|
|
|
24
38
|
.popover-container {
|
|
25
39
|
position: fixed;
|
|
26
40
|
z-index: 1000;
|
|
27
|
-
display: none;
|
|
28
41
|
outline: none;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
:host([open]:not([no-overlay])) .popover-overlay {
|
|
32
|
-
display: block;
|
|
42
|
+
pointer-events: auto;
|
|
33
43
|
}
|
|
34
44
|
|
|
35
45
|
:host([open]) .popover-container {
|
|
36
46
|
display: block;
|
|
37
47
|
visibility: hidden;
|
|
38
48
|
}
|
|
39
|
-
|
|
40
|
-
/* For no-overlay mode, make the container non-interactive */
|
|
41
|
-
:host([no-overlay]) .popover-container {
|
|
42
|
-
pointer-events: none;
|
|
43
|
-
}
|
|
44
49
|
|
|
45
50
|
:host([open][positioned]) .popover-container {
|
|
46
51
|
visibility: visible;
|
|
@@ -65,20 +70,42 @@ class RettangoliPopoverElement extends HTMLElement {
|
|
|
65
70
|
this.shadow = this.attachShadow({ mode: "open" });
|
|
66
71
|
this.shadow.adoptedStyleSheets = [RettangoliPopoverElement.styleSheet];
|
|
67
72
|
|
|
68
|
-
// Create
|
|
69
|
-
this.
|
|
70
|
-
this.
|
|
71
|
-
|
|
73
|
+
// Create dialog element
|
|
74
|
+
this._dialogElement = document.createElement('dialog');
|
|
75
|
+
this.shadow.appendChild(this._dialogElement);
|
|
76
|
+
|
|
77
|
+
// Handle dialog backdrop clicks to close popover
|
|
78
|
+
this._dialogElement.addEventListener('click', (e) => {
|
|
79
|
+
e.stopPropagation();
|
|
80
|
+
// Close on backdrop clicks (when clicking outside the popover content)
|
|
81
|
+
const path = e.composedPath();
|
|
82
|
+
const clickedOnBackdrop = path[0] === this._dialogElement ||
|
|
83
|
+
(path[0].nodeName === 'DIALOG' && path[0] === this._dialogElement);
|
|
84
|
+
|
|
85
|
+
if (clickedOnBackdrop) {
|
|
86
|
+
this.dispatchEvent(new CustomEvent('close', {
|
|
87
|
+
detail: {}
|
|
88
|
+
}));
|
|
89
|
+
}
|
|
90
|
+
});
|
|
72
91
|
|
|
73
|
-
// Handle
|
|
74
|
-
this.
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
92
|
+
// Handle right-click on backdrop to close popover
|
|
93
|
+
this._dialogElement.addEventListener('contextmenu', (e) => {
|
|
94
|
+
// Close on backdrop right-clicks
|
|
95
|
+
const path = e.composedPath();
|
|
96
|
+
const clickedOnBackdrop = path[0] === this._dialogElement ||
|
|
97
|
+
(path[0].nodeName === 'DIALOG' && path[0] === this._dialogElement);
|
|
98
|
+
|
|
99
|
+
if (clickedOnBackdrop) {
|
|
100
|
+
e.preventDefault();
|
|
101
|
+
this.dispatchEvent(new CustomEvent('close', {
|
|
102
|
+
detail: {}
|
|
103
|
+
}));
|
|
104
|
+
}
|
|
78
105
|
});
|
|
79
106
|
|
|
80
|
-
// Handle
|
|
81
|
-
this.
|
|
107
|
+
// Handle ESC key - prevent native close and emit custom event
|
|
108
|
+
this._dialogElement.addEventListener('cancel', (e) => {
|
|
82
109
|
e.preventDefault();
|
|
83
110
|
this.dispatchEvent(new CustomEvent('close', {
|
|
84
111
|
detail: {}
|
|
@@ -88,20 +115,17 @@ class RettangoliPopoverElement extends HTMLElement {
|
|
|
88
115
|
// Create popover container
|
|
89
116
|
this._popoverContainer = document.createElement('div');
|
|
90
117
|
this._popoverContainer.className = 'popover-container';
|
|
91
|
-
this.
|
|
118
|
+
this._dialogElement.appendChild(this._popoverContainer);
|
|
92
119
|
|
|
93
120
|
// Store reference for content slot
|
|
94
121
|
this._slotElement = null;
|
|
95
122
|
|
|
96
123
|
// Track if we're open
|
|
97
124
|
this._isOpen = false;
|
|
98
|
-
|
|
99
|
-
// Bind event handlers
|
|
100
|
-
this._handleEscKey = this._handleEscKey.bind(this);
|
|
101
125
|
}
|
|
102
126
|
|
|
103
127
|
static get observedAttributes() {
|
|
104
|
-
return ["open", "x", "y", "placement"
|
|
128
|
+
return ["open", "x", "y", "placement"];
|
|
105
129
|
}
|
|
106
130
|
|
|
107
131
|
connectedCallback() {
|
|
@@ -112,14 +136,19 @@ class RettangoliPopoverElement extends HTMLElement {
|
|
|
112
136
|
}
|
|
113
137
|
|
|
114
138
|
disconnectedCallback() {
|
|
115
|
-
// Clean up
|
|
116
|
-
this.
|
|
139
|
+
// Clean up dialog if it's open
|
|
140
|
+
if (this._isOpen && this._dialogElement.open) {
|
|
141
|
+
this._dialogElement.close();
|
|
142
|
+
}
|
|
117
143
|
}
|
|
118
144
|
|
|
119
145
|
attributeChangedCallback(name, oldValue, newValue) {
|
|
120
146
|
if (name === 'open') {
|
|
121
147
|
if (newValue !== null && !this._isOpen) {
|
|
122
|
-
|
|
148
|
+
// Only show if element is connected to DOM
|
|
149
|
+
if (this.isConnected) {
|
|
150
|
+
this._show();
|
|
151
|
+
}
|
|
123
152
|
} else if (newValue === null && this._isOpen) {
|
|
124
153
|
this._hide();
|
|
125
154
|
}
|
|
@@ -138,8 +167,20 @@ class RettangoliPopoverElement extends HTMLElement {
|
|
|
138
167
|
}
|
|
139
168
|
|
|
140
169
|
this._isOpen = true;
|
|
141
|
-
|
|
142
|
-
|
|
170
|
+
|
|
171
|
+
// Show the dialog using setTimeout to ensure it's in the DOM
|
|
172
|
+
if (!this._dialogElement.open) {
|
|
173
|
+
setTimeout(() => {
|
|
174
|
+
if (this._dialogElement && !this._dialogElement.open) {
|
|
175
|
+
this._dialogElement.showModal();
|
|
176
|
+
}
|
|
177
|
+
}, 0);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Update position after dialog is shown
|
|
181
|
+
requestAnimationFrame(() => {
|
|
182
|
+
this._updatePosition();
|
|
183
|
+
});
|
|
143
184
|
}
|
|
144
185
|
}
|
|
145
186
|
|
|
@@ -147,13 +188,16 @@ class RettangoliPopoverElement extends HTMLElement {
|
|
|
147
188
|
if (this._isOpen) {
|
|
148
189
|
this._isOpen = false;
|
|
149
190
|
|
|
191
|
+
// Close the dialog
|
|
192
|
+
if (this._dialogElement.open) {
|
|
193
|
+
this._dialogElement.close();
|
|
194
|
+
}
|
|
195
|
+
|
|
150
196
|
// Remove slot to unmount content
|
|
151
197
|
if (this._slotElement) {
|
|
152
198
|
this._popoverContainer.removeChild(this._slotElement);
|
|
153
199
|
this._slotElement = null;
|
|
154
200
|
}
|
|
155
|
-
|
|
156
|
-
this._removeGlobalListeners();
|
|
157
201
|
}
|
|
158
202
|
}
|
|
159
203
|
|
|
@@ -246,25 +290,6 @@ class RettangoliPopoverElement extends HTMLElement {
|
|
|
246
290
|
return { left, top };
|
|
247
291
|
}
|
|
248
292
|
|
|
249
|
-
_addGlobalListeners() {
|
|
250
|
-
// Use setTimeout to avoid immediate triggering
|
|
251
|
-
setTimeout(() => {
|
|
252
|
-
document.addEventListener('keydown', this._handleEscKey);
|
|
253
|
-
}, 0);
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
_removeGlobalListeners() {
|
|
257
|
-
document.removeEventListener('keydown', this._handleEscKey);
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
_handleEscKey(e) {
|
|
262
|
-
if (e.key === 'Escape') {
|
|
263
|
-
this.dispatchEvent(new CustomEvent('close', {
|
|
264
|
-
detail: {}
|
|
265
|
-
}));
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
293
|
|
|
269
294
|
// Expose popover container for advanced usage
|
|
270
295
|
get popover() {
|