@inboxsdk/core 0.2.29-alpha.0 → 0.2.29-alpha.2

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.
@@ -1,176 +1,294 @@
1
- import isEqual from 'lodash/isEqual';
2
- import kefir from 'kefir';
1
+ import Kefir from 'kefir';
2
+ import kefirStopper from 'kefir-stopper';
3
+ import kefirBus from 'kefir-bus';
3
4
  import EventEmitter from '../lib/safe-event-emitter';
4
5
  import { GmailAppMenuItemView, NATIVE_CLASS, INBOXSDK_CLASS, } from '../dom-driver/gmail/views/gmail-app-menu-item-view';
5
- import { CollapsiblePanelView } from './collapsible-panel-view';
6
+ import { NATIVE_CLASS as PANEL_NATIVE_CLASS, CollapsiblePanelView, } from './collapsible-panel-view';
6
7
  import { addCollapsiblePanel } from '../dom-driver/gmail/gmail-driver/add-collapsible-panel';
7
8
  import GmailElementGetter from '../dom-driver/gmail/gmail-element-getter';
8
- let prevNative = {
9
- menuItem: null,
10
- panel: null,
11
- route: null,
12
- };
13
- const setPrevNative = (next) => {
14
- prevNative = {
15
- ...prevNative,
16
- ...next,
17
- };
18
- };
9
+ var NativeAppMenuClassName;
10
+ (function (NativeAppMenuClassName) {
11
+ NativeAppMenuClassName["MAIL"] = "XJ";
12
+ NativeAppMenuClassName["CHAT"] = "ao4";
13
+ NativeAppMenuClassName["SPACES"] = "aIt";
14
+ NativeAppMenuClassName["MEET"] = "adZ";
15
+ })(NativeAppMenuClassName || (NativeAppMenuClassName = {}));
16
+ // Native Gmail menu button => the panel class names mapping
17
+ const nativeButtonToPanelMap = new Map([
18
+ [NativeAppMenuClassName.MAIL, 'aIH'],
19
+ [NativeAppMenuClassName.CHAT, 'arL'],
20
+ [NativeAppMenuClassName.SPACES, 'arM'],
21
+ [NativeAppMenuClassName.MEET, undefined], // Meet
22
+ ]);
23
+ /**
24
+ * Mail routes list is not exhaustive
25
+ */
26
+ const MAIL_ROUTES = ['inbox/:page'];
27
+ const CHAT_ROUTES = ['chat/welcome', 'chat/dm/:chatID'];
28
+ const SPACES_ROUTES = ['rooms/welcome', 'chat/space/:spaceID'];
29
+ const MEET_ROUTES = ['calls'];
30
+ const routeIDtoMenuItemClass = Object.fromEntries([
31
+ ...MAIL_ROUTES.map((route) => [route, NativeAppMenuClassName.MAIL]),
32
+ ...CHAT_ROUTES.map((route) => [route, NativeAppMenuClassName.CHAT]),
33
+ ...SPACES_ROUTES.map((route) => [route, NativeAppMenuClassName.SPACES]),
34
+ ...MEET_ROUTES.map((route) => [route, NativeAppMenuClassName.MEET]),
35
+ ]);
36
+ const initialRoutingStateStopper = kefirStopper();
19
37
  /**
20
38
  * Contains both a native Gmail app menu item and a collapsible panel.
21
39
  */
22
40
  export class AppMenuItemView extends EventEmitter {
23
- /**
24
- * Native panels are HTMLElements, custom panels are CollapsiblePanelViews.
25
- */
26
- static #activePanel;
27
- static #nativeMenuItemChangeStream = (() => {
28
- const stream = kefir.stream((emitter) => {
29
- const observer = new MutationObserver((mutations) => {
30
- for (const mutation of mutations) {
31
- const { target } = mutation;
32
- if (mutation.type === 'attributes' &&
33
- target instanceof HTMLElement &&
34
- target.classList.contains(NATIVE_CLASS) &&
35
- !target.classList.contains(INBOXSDK_CLASS)) {
36
- if (target.classList.contains(GmailAppMenuItemView.elementCss.ACTIVE)) {
37
- emitter.emit(['activated', target]);
38
- }
39
- else if (target.classList.contains(GmailAppMenuItemView.elementCss.HOVER)) {
40
- emitter.emit(['hovered', target]);
41
- }
42
- }
43
- }
44
- });
45
- const f = async () => {
46
- const gmailAppMenu = await GmailElementGetter.getAppMenuAsync();
47
- if (!gmailAppMenu) {
48
- return;
49
- }
50
- const { ACTIVE } = GmailAppMenuItemView.elementCss;
51
- const nativeMenuItemSelector = `.${NATIVE_CLASS}.${ACTIVE}:not(.${INBOXSDK_CLASS})`;
52
- const nativeActivePanel = AppMenuItemView.#getNativeActivePanel();
53
- setPrevNative({
54
- menuItem: gmailAppMenu.querySelector(nativeMenuItemSelector),
55
- panel: nativeActivePanel,
56
- });
57
- AppMenuItemView.#activePanel = nativeActivePanel;
58
- document.addEventListener('mousedown', (e) => {
59
- const { target } = e;
60
- if (!(target instanceof Element)) {
61
- return;
62
- }
63
- if (!gmailAppMenu.contains(target)) {
64
- return;
65
- }
66
- const closest = target.closest(`.${NATIVE_CLASS}:not(.${INBOXSDK_CLASS})`);
67
- if (closest) {
68
- emitter.emit(['mousedown-on-native-el', closest, e]);
69
- }
70
- });
71
- observer.observe(gmailAppMenu, {
72
- attributes: true,
73
- childList: true,
74
- subtree: true,
75
- });
76
- };
77
- f();
78
- });
79
- return stream;
80
- })();
81
- static #getNativeActivePanel() {
41
+ static #menuItemChangeStream = Kefir.pool();
42
+ static #routeViewDriverStream;
43
+ static #menuItemToPanelMap = new Map();
44
+ static #appMenuItemViews = new Set();
45
+ static #getActivePanel() {
82
46
  const appMenuElement = GmailElementGetter.getAppMenuContainer();
83
- const { ACTIVE, HOVER } = CollapsiblePanelView.elementCss;
84
- const nativePanel = appMenuElement?.querySelector(`${CollapsiblePanelView.elementSelectors.NATIVE}.${ACTIVE}:not(.${HOVER}):not(${CollapsiblePanelView.elementSelectors.CUSTOM})`);
47
+ const { ACTIVE } = CollapsiblePanelView.elementCss;
48
+ const nativePanel = appMenuElement?.querySelector(`.${PANEL_NATIVE_CLASS}.${ACTIVE}`);
85
49
  return nativePanel;
86
50
  }
87
- static #customMenuItems = new Set();
51
+ static #getActiveMenuItem() {
52
+ const appMenuElement = GmailElementGetter.getAppMenuContainer();
53
+ const { ACTIVE } = GmailAppMenuItemView.elementCss;
54
+ const button = appMenuElement?.querySelector(`.${NATIVE_CLASS}.${ACTIVE}`);
55
+ return button;
56
+ }
57
+ static #setUpRouteViewDriverStream(driver) {
58
+ if (AppMenuItemView.#routeViewDriverStream)
59
+ return;
60
+ AppMenuItemView.#routeViewDriverStream = driver.getRouteViewDriverStream();
61
+ const bus = kefirBus();
62
+ AppMenuItemView.#menuItemChangeStream.plug(bus);
63
+ AppMenuItemView.#routeViewDriverStream
64
+ .takeUntilBy(initialRoutingStateStopper)
65
+ .onValue(async (routeView) => {
66
+ const routeViewID = routeView.getRouteID();
67
+ const routeType = routeView.getRouteType();
68
+ const routeViewParams = routeView.getParams();
69
+ console.debug({
70
+ routeViewID,
71
+ routeType,
72
+ routeViewParams,
73
+ });
74
+ /* Handling custom app menu items */
75
+ const descriptors = Array.from(AppMenuItemView.#appMenuItemViews, async (appMenuItemView) => {
76
+ const gmailView = await appMenuItemView.#gmailViewPromise;
77
+ return [gmailView.menuItemDescriptor, gmailView];
78
+ });
79
+ const results = await Promise.all(descriptors);
80
+ const [, gmailView] = results.find(([descriptor]) => {
81
+ return descriptor?.isRouteActive(routeView);
82
+ }) ?? [];
83
+ if (gmailView?.element) {
84
+ bus.emit(['click', gmailView.element]);
85
+ return;
86
+ }
87
+ /* Handling native app menu items */
88
+ const selector = `.${routeViewID
89
+ ? routeIDtoMenuItemClass[routeViewID] ?? NativeAppMenuClassName.MAIL
90
+ : NativeAppMenuClassName.MAIL}`;
91
+ const element = document.querySelector(selector);
92
+ if (element) {
93
+ bus.emit(['click', element]);
94
+ return;
95
+ }
96
+ });
97
+ }
88
98
  static {
89
- AppMenuItemView.#nativeMenuItemChangeStream.onValue(async (e) => {
90
- const [type, el /*, mouseEvent */] = e;
91
- if (type === 'activated') {
92
- AppMenuItemView.#activePanel = AppMenuItemView.#getNativeActivePanel();
93
- await Promise.all(Array.from(AppMenuItemView.#customMenuItems).map(async (customMenuItem) => {
94
- await customMenuItem.#deactivate();
95
- }));
99
+ (async () => {
100
+ const gmailAppMenu = await GmailElementGetter.getAppMenuAsync();
101
+ if (!gmailAppMenu) {
102
+ return;
103
+ }
104
+ // Set up menu item panel -> menu collapsible panel element mappings
105
+ for (const [menuItemClass, panelClass] of nativeButtonToPanelMap) {
106
+ const menuItemElement = document.querySelector(`.${NATIVE_CLASS}.${menuItemClass}`);
107
+ const panelElement = panelClass
108
+ ? document.querySelector(`.${PANEL_NATIVE_CLASS}.${panelClass}`)
109
+ : null;
110
+ if (menuItemElement) {
111
+ AppMenuItemView.#menuItemToPanelMap.set(menuItemElement, panelElement ?? undefined);
112
+ }
96
113
  }
97
- if (type === 'mousedown-on-native-el') {
98
- if (prevNative.menuItem !== el) {
99
- prevNative.menuItem = el;
114
+ // Set up event listeners we use to control menu UI
115
+ const stream = Kefir.stream((emitter) => {
116
+ // We intercept some events emitted on Gmail (native) menu items to gain full control of the menu (menu items and panels).
117
+ // Thus, some native event handlers won't be invoked so we replicate the Gmail's behavior by ourselves.
118
+ const appMenuElement = GmailElementGetter.getAppMenuContainer();
119
+ for (const nativeMenuItem of appMenuElement?.querySelectorAll(`.${NATIVE_CLASS}:not(.${INBOXSDK_CLASS})`) ?? []) {
120
+ // Gmail uses this listener for panel hover state activation. It's prevented from propagation and we handle UI updates
121
+ nativeMenuItem.addEventListener('mouseenter', (e) => {
122
+ e.stopImmediatePropagation();
123
+ emitter.emit(['mouseenter', nativeMenuItem, e]);
124
+ }, true);
125
+ // Gmail uses this listener for panel hover state deactivation. It's prevented from propagation and we handle UI updates
126
+ nativeMenuItem.addEventListener('mouseleave', (e) => {
127
+ e.stopImmediatePropagation();
128
+ emitter.emit(['mouseleave', nativeMenuItem, e]);
129
+ }, true);
130
+ // Click event isn't prevented from propagation to let Gmail handle routing. The styling is handled by us
131
+ nativeMenuItem.addEventListener('click', () => {
132
+ emitter.emit(['click', nativeMenuItem]);
133
+ });
134
+ // Handle moving cursor out of panel. We use it to enhance the styling since it won't be handled by Gmail
135
+ const panel = AppMenuItemView.#menuItemToPanelMap.get(nativeMenuItem);
136
+ panel?.addEventListener('mouseleave', (e) => {
137
+ emitter.emit(['mouseleave', nativeMenuItem, e]);
138
+ });
139
+ }
140
+ });
141
+ AppMenuItemView.#menuItemChangeStream.plug(stream);
142
+ })();
143
+ }
144
+ static {
145
+ AppMenuItemView.#menuItemChangeStream.onValue(async (v) => {
146
+ const [type, menuItem, mouseEvent] = v;
147
+ const { ACTIVE, HOVER } = GmailAppMenuItemView.elementCss;
148
+ if (type === 'mouseenter') {
149
+ const panel = AppMenuItemView.#menuItemToPanelMap.get(menuItem);
150
+ if (mouseEvent.relatedTarget instanceof Node &&
151
+ (menuItem.contains(mouseEvent.relatedTarget) ||
152
+ panel?.contains(mouseEvent.relatedTarget)))
153
+ return;
154
+ const activeMenuItem = AppMenuItemView.#getActiveMenuItem();
155
+ const activePanel = AppMenuItemView.#getActivePanel();
156
+ if (activeMenuItem === menuItem && activePanel === panel)
100
157
  return;
158
+ // deactivate active panel
159
+ if (activePanel) {
160
+ activePanel.style.removeProperty('height');
161
+ activePanel.classList.remove(CollapsiblePanelView.elementCss.ACTIVE);
162
+ activePanel.classList.remove(CollapsiblePanelView.elementCss.HOVER);
163
+ }
164
+ // activate new panel
165
+ if (panel) {
166
+ const height = window.innerHeight - panel.getBoundingClientRect().top;
167
+ panel.style.cssText = `height: ${height}px;`;
168
+ panel.classList.add(CollapsiblePanelView.elementCss.ACTIVE);
169
+ panel.classList.add(CollapsiblePanelView.elementCss.HOVER);
170
+ // hover menu item
171
+ menuItem.classList.add(HOVER);
101
172
  }
102
173
  else {
103
- const { menuItem, panel, route } = prevNative;
104
- prevNative.menuItem = el;
105
- if (route) {
106
- document.location.hash = route;
107
- }
108
- menuItem?.classList.add(GmailAppMenuItemView.elementCss.ACTIVE);
109
- menuItem.classList.remove(GmailAppMenuItemView.elementCss.HOVER);
174
+ // panel doesn't exist (i.e. Meet) so activate active menu item's panel instead (as Gmail currently does -- FEB 2023)
175
+ const panel = activeMenuItem &&
176
+ AppMenuItemView.#menuItemToPanelMap.get(activeMenuItem);
110
177
  panel?.classList.add(CollapsiblePanelView.elementCss.ACTIVE);
111
- panel?.classList.remove(CollapsiblePanelView.elementCss.HOVER);
178
+ }
179
+ }
180
+ if (type === 'mouseleave') {
181
+ const activeMenuItem = AppMenuItemView.#getActiveMenuItem();
182
+ const activePanel = AppMenuItemView.#getActivePanel();
183
+ const activeMenuItemPanel = activeMenuItem &&
184
+ AppMenuItemView.#menuItemToPanelMap.get(activeMenuItem);
185
+ if (mouseEvent.relatedTarget instanceof Node &&
186
+ (menuItem.contains(mouseEvent.relatedTarget) ||
187
+ activePanel?.contains(mouseEvent.relatedTarget)))
188
+ return;
189
+ if (activePanel === activeMenuItemPanel)
190
+ return;
191
+ // unhover menu item
192
+ menuItem.classList.remove(HOVER);
193
+ // deactivate active panel
194
+ if (activePanel) {
195
+ activePanel.style.removeProperty('height');
196
+ activePanel.classList.remove(CollapsiblePanelView.elementCss.ACTIVE);
197
+ activePanel.classList.remove(CollapsiblePanelView.elementCss.HOVER);
198
+ }
199
+ // activate active menu item panel
200
+ if (activeMenuItemPanel) {
201
+ activeMenuItemPanel.classList.add(CollapsiblePanelView.elementCss.ACTIVE);
202
+ }
203
+ }
204
+ if (type === 'click') {
205
+ const appMenuElement = GmailElementGetter.getAppMenuContainer();
206
+ // deactivate active panel
207
+ const activePanel = AppMenuItemView.#getActivePanel();
208
+ if (activePanel) {
209
+ activePanel.style.removeProperty('height');
210
+ activePanel.classList.remove(CollapsiblePanelView.elementCss.ACTIVE);
211
+ activePanel.classList.remove(CollapsiblePanelView.elementCss.HOVER);
212
+ }
213
+ // deactivate menu items
214
+ for (const menuItem_ of appMenuElement?.querySelectorAll(`.${NATIVE_CLASS}`) ?? []) {
215
+ menuItem_.classList.remove(ACTIVE);
216
+ menuItem_.classList.remove(HOVER);
217
+ }
218
+ // activate menu item
219
+ menuItem.classList.add(ACTIVE);
220
+ // activate panel
221
+ const panel = AppMenuItemView.#menuItemToPanelMap.get(menuItem);
222
+ if (panel) {
223
+ panel.classList.add(CollapsiblePanelView.elementCss.ACTIVE);
112
224
  }
113
225
  }
114
226
  });
115
227
  }
228
+ get menuItemDescriptor() {
229
+ return this.#menuItemDescriptor;
230
+ }
116
231
  #driver;
117
232
  #destroyed = false;
118
233
  #gmailViewPromise;
119
234
  #collapsiblePanel;
120
- /** Denotes if either the collapsable panel or app menu item are hovered. */
121
- #hovered = false;
122
- menuItemDescriptor;
235
+ #appMenuItemStream;
236
+ #collapsiblePanelStream;
237
+ #menuItemDescriptor;
123
238
  constructor(driver, menuItemDescriptor) {
124
239
  super();
125
240
  this.#driver = driver;
126
- this.menuItemDescriptor = menuItemDescriptor;
241
+ this.#menuItemDescriptor = menuItemDescriptor;
127
242
  const gmailAppMenuItemView = this.#driver.addAppMenuItem(menuItemDescriptor);
128
243
  this.#gmailViewPromise = gmailAppMenuItemView;
129
244
  gmailAppMenuItemView.then((gmailView) => {
130
245
  if (this.#destroyed || !gmailView) {
131
246
  return; //we have been removed already
132
247
  }
133
- // add callbacks and listeners here
134
- gmailView.on('click', this.#onClick);
135
- gmailView.on('destroy', () => this.remove());
136
- gmailView.on('blur', this.#onBlur);
137
- gmailView.on('hover', this.#onHover);
138
- // handle routing
139
- driver.getRouteViewDriverStream().onValue((routeView) => {
140
- const routeViewID = routeView.getRouteID();
141
- const routeViewParams = routeView.getParams();
142
- const routeViewType = routeView.getRouteType();
143
- // Ignore custom routes that don't have a route id
144
- // TODO fix chat/spaces routes to have NATIVE routeViewTypes so we can gate on that instead.
145
- if (!(routeViewType === 'UNKNOWN' && routeViewID === null)) {
146
- console.log({ routeViewID, routeViewType });
147
- if (routeViewType !== 'CUSTOM') {
148
- prevNative.route === document.location.hash;
149
- }
150
- }
151
- const { activeRouteID, routeID, routeParams, activeRouteParams } = gmailView.menuItemDescriptor ?? {};
152
- let isActive = isEqual(activeRouteID || routeID, routeViewID);
153
- if (isActive) {
154
- if (activeRouteParams) {
155
- isActive = isEqual(activeRouteParams, routeViewParams);
156
- }
157
- else if (routeParams) {
158
- isActive = isEqual(routeParams, routeViewParams);
159
- }
160
- }
161
- // deactivation is handled by the native menu item change stream
162
- if (isActive) {
163
- this.#activate();
164
- }
248
+ const gmailElement = gmailView.element;
249
+ if (gmailElement) {
250
+ AppMenuItemView.#menuItemToPanelMap.set(gmailElement, undefined);
251
+ }
252
+ this.#appMenuItemStream = Kefir.stream((emitter) => {
253
+ gmailView.on('destroy', () => {
254
+ emitter.end();
255
+ this.remove();
256
+ });
257
+ gmailView.on('click', () => {
258
+ emitter.emit(['click', gmailElement]);
259
+ this.emit('click');
260
+ });
261
+ gmailView.on('hover', (e) => {
262
+ emitter.emit(['mouseenter', gmailElement, e]);
263
+ this.emit('hover');
264
+ });
265
+ gmailView.on('blur', (e) => {
266
+ emitter.emit(['mouseleave', gmailElement, e]);
267
+ this.emit('blur');
268
+ });
165
269
  });
270
+ AppMenuItemView.#menuItemChangeStream.plug(this.#appMenuItemStream);
271
+ AppMenuItemView.#setUpRouteViewDriverStream(driver);
272
+ AppMenuItemView.#appMenuItemViews.add(this);
166
273
  });
167
- AppMenuItemView.#customMenuItems.add(this);
168
274
  }
169
275
  async addCollapsiblePanel(panelDescriptor) {
170
276
  const collapsiblePanel = await addCollapsiblePanel(this.#driver, panelDescriptor);
171
277
  if (collapsiblePanel) {
172
- collapsiblePanel.on('blur', this.#onBlur);
173
- collapsiblePanel.on('hover', this.#onHover);
278
+ this.#gmailViewPromise.then((gmailView) => {
279
+ const gmailElement = gmailView.element;
280
+ if (gmailElement) {
281
+ this.#collapsiblePanelStream = Kefir.stream((emitter) => {
282
+ collapsiblePanel.on('blur', (e) => {
283
+ emitter.value(['mouseleave', gmailElement, e]);
284
+ });
285
+ });
286
+ AppMenuItemView.#menuItemChangeStream.plug(this.#collapsiblePanelStream);
287
+ }
288
+ if (gmailElement && collapsiblePanel) {
289
+ AppMenuItemView.#menuItemToPanelMap.set(gmailElement, collapsiblePanel.element);
290
+ }
291
+ });
174
292
  }
175
293
  this.#collapsiblePanel = collapsiblePanel;
176
294
  return collapsiblePanel;
@@ -183,18 +301,21 @@ export class AppMenuItemView extends EventEmitter {
183
301
  if (this.#destroyed)
184
302
  return;
185
303
  this.#destroyed = true;
186
- AppMenuItemView.#customMenuItems.delete(this);
187
304
  this.emit('destroy');
188
305
  this.#collapsiblePanel?.remove();
189
- this.#gmailViewPromise.then((gmailView) => gmailView.remove());
190
- }
191
- async #deactivate() {
192
- const gmailView = await this.#gmailViewPromise;
193
- gmailView.deactivate();
194
- this.#collapsiblePanel?.deactivate();
306
+ this.#gmailViewPromise.then((gmailView) => {
307
+ gmailView.element &&
308
+ AppMenuItemView.#menuItemToPanelMap.delete(gmailView.element);
309
+ gmailView.remove();
310
+ });
311
+ this.#appMenuItemStream &&
312
+ AppMenuItemView.#menuItemChangeStream.unplug(this.#appMenuItemStream);
313
+ this.#collapsiblePanelStream &&
314
+ AppMenuItemView.#menuItemChangeStream.unplug(this.#collapsiblePanelStream);
315
+ AppMenuItemView.#appMenuItemViews.delete(this);
316
+ initialRoutingStateStopper.destroy();
195
317
  }
196
318
  async #activate() {
197
- AppMenuItemView.#activePanel = this.#collapsiblePanel;
198
319
  const gmailView = await this.#gmailViewPromise;
199
320
  const appMenuElement = GmailElementGetter.getAppMenuContainer();
200
321
  const { ACTIVE } = GmailAppMenuItemView.elementCss;
@@ -205,55 +326,4 @@ export class AppMenuItemView extends EventEmitter {
205
326
  gmailView.activate();
206
327
  this.#collapsiblePanel?.activate();
207
328
  }
208
- #onBlur = async (e) => {
209
- const gmailView = await this.#gmailViewPromise;
210
- const { relatedTarget } = e;
211
- const blurringMenuItem = relatedTarget instanceof Node &&
212
- gmailView.element?.contains(relatedTarget);
213
- const blurringPanel = relatedTarget instanceof Node &&
214
- this.#collapsiblePanel?.element?.contains(relatedTarget);
215
- if (blurringMenuItem || blurringPanel) {
216
- return;
217
- }
218
- this.#hovered = false;
219
- gmailView.blur();
220
- const hasActivePanel = this.#hasActivePanel();
221
- this.#collapsiblePanel?.blur(hasActivePanel);
222
- if (!hasActivePanel) {
223
- if (AppMenuItemView.#activePanel instanceof CollapsiblePanelView) {
224
- AppMenuItemView.#activePanel?.activate();
225
- }
226
- else if (AppMenuItemView.#activePanel instanceof HTMLElement) {
227
- AppMenuItemView.#activePanel.classList.add(CollapsiblePanelView.elementCss.ACTIVE);
228
- }
229
- }
230
- this.emit('blur');
231
- };
232
- #hasActivePanel() {
233
- return (this.#collapsiblePanel != null &&
234
- AppMenuItemView.#activePanel === this.#collapsiblePanel);
235
- }
236
- #onHover = async (_e) => {
237
- if (this.#hovered) {
238
- return;
239
- }
240
- this.#hovered = true;
241
- const gmailView = await this.#gmailViewPromise;
242
- gmailView.hover();
243
- const hasActivePanel = this.#hasActivePanel();
244
- if (!hasActivePanel) {
245
- if (AppMenuItemView.#activePanel instanceof CollapsiblePanelView) {
246
- AppMenuItemView.#activePanel?.deactivate();
247
- }
248
- else if (AppMenuItemView.#activePanel instanceof HTMLElement) {
249
- AppMenuItemView.#activePanel.classList.remove(CollapsiblePanelView.elementCss.ACTIVE);
250
- }
251
- }
252
- this.#collapsiblePanel?.hover(hasActivePanel);
253
- this.emit('hover');
254
- };
255
- #onClick = () => {
256
- this.#activate();
257
- this.emit('click');
258
- };
259
329
  }
@@ -4,11 +4,11 @@ import { AppMenuItemPanelDescriptor } from '../namespaces/app-menu';
4
4
  import GmailDriver from '../dom-driver/gmail/gmail-driver';
5
5
  import { NavItemDescriptor } from '../dom-driver/gmail/views/gmail-nav-item-view';
6
6
  import NavItemView from './nav-item-view';
7
+ export declare const NATIVE_CLASS: "aqn";
8
+ export declare const INBOXSDK_CLASS: "inboxsdk__collapsiblePanel";
7
9
  type MessageEvents = {
8
- toggle: (collapsed: boolean) => void;
9
10
  destroy: () => void;
10
11
  blur: (e: MouseEvent) => void;
11
- hover: (e: MouseEvent) => void;
12
12
  };
13
13
  declare const CollapsiblePanelView_base: new () => TypedEmitter<MessageEvents>;
14
14
  export declare class CollapsiblePanelView extends CollapsiblePanelView_base {
@@ -26,23 +26,10 @@ export declare class CollapsiblePanelView extends CollapsiblePanelView_base {
26
26
  get element(): HTMLElement | undefined;
27
27
  set panelDescriptor(panelDescriptor: AppMenuItemPanelDescriptor);
28
28
  constructor(driver: GmailDriver);
29
- toggleCollapse(collapsed: boolean): void;
30
- /**
31
- * @internal
32
- */
33
- blur(isActivePanel: boolean): void;
34
- /**
35
- * @internal
36
- */
37
- hover(isActivePanel: boolean): void;
38
29
  /**
39
30
  * @internal
40
31
  */
41
32
  activate(): void;
42
- /**
43
- * @internal
44
- */
45
- deactivate(): void;
46
33
  remove(): void;
47
34
  addNavItem(navItemDescriptor: NavItemDescriptor | Kefir.Observable<NavItemDescriptor, any>): NavItemView | undefined;
48
35
  }
@@ -1 +1 @@
1
- {"version":3,"file":"collapsible-panel-view.d.ts","sourceRoot":"","sources":["../../../../../src/platform-implementation-js/views/collapsible-panel-view.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,eAAe,CAAC;AAEzC,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,OAAO,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AAIpE,OAAO,WAAW,MAAM,kCAAkC,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,+CAA+C,CAAC;AAClF,OAAO,WAAW,MAAM,iBAAiB,CAAC;AAa1C,KAAK,aAAa,GAAG;IACnB,MAAM,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;IACrC,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,IAAI,CAAC;IAC9B,KAAK,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,IAAI,CAAC;CAChC,CAAC;mDAEmE,aAAa,aAAa,CAAC;AAAhG,qBAAa,oBAAqB,SAAQ,yBAAuD;;IAC/F,MAAM,CAAC,gBAAgB;;;MAGZ;IACX,MAAM,CAAC,UAAU;;;QAGf,kDAAkD;;MAEzC;IAQX,IAAI,OAAO,4BAEV;IAED,IAAI,eAAe,CAAC,eAAe,EAAE,0BAA0B,EAG9D;gBAEW,MAAM,EAAE,WAAW;IAQ/B,cAAc,CAAC,SAAS,EAAE,OAAO;IAejC;;OAEG;IACH,IAAI,CAAC,aAAa,EAAE,OAAO;IAW3B;;OAEG;IACH,KAAK,CAAC,aAAa,EAAE,OAAO;IAY5B;;OAEG;IACH,QAAQ;IAQR;;OAEG;IACH,UAAU;IAOV,MAAM;IAON,UAAU,CACR,iBAAiB,EACb,iBAAiB,GACjB,KAAK,CAAC,UAAU,CAAC,iBAAiB,EAAE,GAAG,CAAC;CAuK/C"}
1
+ {"version":3,"file":"collapsible-panel-view.d.ts","sourceRoot":"","sources":["../../../../../src/platform-implementation-js/views/collapsible-panel-view.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,eAAe,CAAC;AAEzC,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,OAAO,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AAIpE,OAAO,WAAW,MAAM,kCAAkC,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,+CAA+C,CAAC;AAClF,OAAO,WAAW,MAAM,iBAAiB,CAAC;AAE1C,eAAO,MAAM,YAAY,OAAiB,CAAC;AAC3C,eAAO,MAAM,cAAc,8BAAwC,CAAC;AAQpE,KAAK,aAAa,GAAG;IACnB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,IAAI,CAAC;CAC/B,CAAC;mDAEmE,aAAa,aAAa,CAAC;AAAhG,qBAAa,oBAAqB,SAAQ,yBAAuD;;IAC/F,MAAM,CAAC,gBAAgB;;;MAGZ;IACX,MAAM,CAAC,UAAU;;;QAGf,kDAAkD;;MAEzC;IAQX,IAAI,OAAO,4BAEV;IAED,IAAI,eAAe,CAAC,eAAe,EAAE,0BAA0B,EAG9D;gBAEW,MAAM,EAAE,WAAW;IAS/B;;OAEG;IACH,QAAQ;IAQR,MAAM;IAON,UAAU,CACR,iBAAiB,EACb,iBAAiB,GACjB,KAAK,CAAC,UAAU,CAAC,iBAAiB,EAAE,GAAG,CAAC;CA+J/C"}
@@ -6,10 +6,9 @@ import autoHtml from 'auto-html';
6
6
  import querySelector from '../lib/dom/querySelectorOrFail';
7
7
  import GmailElementGetter from '../dom-driver/gmail/gmail-element-getter';
8
8
  import NavItemView from './nav-item-view';
9
- const ELEMENT_CLASS = 'aqn oy8Mbf inboxsdk__collapsiblePanel';
10
- // const ELEMENT_CLASS_ACTIVE = `aqn oy8Mbf ${ACTIVE_CLASS_NAME_TOKEN}` as const;
11
- // const ELEMENT_CLASS_COLLAPSED =
12
- // `aqn oy8Mbf ${COLLAPSED_CLASS_NAME_TOKEN}` as const;
9
+ export const NATIVE_CLASS = 'aqn';
10
+ export const INBOXSDK_CLASS = 'inboxsdk__collapsiblePanel';
11
+ const ELEMENT_CLASS = `${NATIVE_CLASS} ${INBOXSDK_CLASS} oy8Mbf`;
13
12
  const PRIMARY_BUTTON_ELEMENT_CLASS = 'T-I T-I-KE L3';
14
13
  const PRIMARY_BUTTON_ELEMENT_SELECTOR = '.T-I.T-I-KE.L3';
15
14
  const NAV_MENU_CONTAINER_ELEMENT_SELECTOR = '.at9 .n3 .TK';
@@ -41,48 +40,9 @@ export class CollapsiblePanelView extends EventEmitter {
41
40
  super();
42
41
  this.#driver = driver;
43
42
  this.#element = this.#setupElement();
44
- this.#element.addEventListener('mouseover', this.#onHover);
45
- this.#element.addEventListener('mouseout', this.#onBlur);
46
- }
47
- toggleCollapse(collapsed) {
48
- const element = this.element;
49
- if (!element)
50
- return;
51
- const { COLLAPSED } = CollapsiblePanelView.elementCss;
52
- if (collapsed) {
53
- element.classList.add(COLLAPSED);
54
- }
55
- else {
56
- element.classList.remove(COLLAPSED);
57
- }
58
- this.emit('toggle', collapsed);
59
- }
60
- /**
61
- * @internal
62
- */
63
- blur(isActivePanel) {
64
- const { element } = this;
65
- if (!element)
66
- return;
67
- element.classList.remove(CollapsiblePanelView.elementCss.HOVER);
68
- if (!isActivePanel) {
69
- element.classList.remove(CollapsiblePanelView.elementCss.ACTIVE);
70
- }
71
- element.style.removeProperty('height');
72
- }
73
- /**
74
- * @internal
75
- */
76
- hover(isActivePanel) {
77
- const { element } = this;
78
- const { ACTIVE, HOVER } = CollapsiblePanelView.elementCss;
79
- if (!element || element.classList.contains(ACTIVE))
80
- return;
81
- element.classList.add(HOVER);
82
- if (!isActivePanel) {
83
- element.classList.add(CollapsiblePanelView.elementCss.ACTIVE);
84
- }
85
- element.style.cssText = 'height: 785px;';
43
+ this.#element.addEventListener('mouseleave', (e) => {
44
+ this.emit('blur', e);
45
+ });
86
46
  }
87
47
  /**
88
48
  * @internal
@@ -94,15 +54,6 @@ export class CollapsiblePanelView extends EventEmitter {
94
54
  element?.classList.remove(CollapsiblePanelView.elementCss.HOVER);
95
55
  element.classList.add(CollapsiblePanelView.elementCss.ACTIVE);
96
56
  }
97
- /**
98
- * @internal
99
- */
100
- deactivate() {
101
- const element = this.element;
102
- if (!element)
103
- return;
104
- element.classList.remove(CollapsiblePanelView.elementCss.ACTIVE);
105
- }
106
57
  remove() {
107
58
  if (this.#destroyed)
108
59
  return;
@@ -213,10 +164,4 @@ export class CollapsiblePanelView extends EventEmitter {
213
164
  }
214
165
  buttonTextEl.textContent = this.#panelDescriptor?.primaryButton?.name ?? '';
215
166
  }
216
- #onBlur = (e) => {
217
- this.emit('blur', e);
218
- };
219
- #onHover = (e) => {
220
- this.emit('hover', e);
221
- };
222
167
  }