mirror of https://github.com/zulip/zulip.git
ts: Migrate `popover_menus` to typescript.
This commit migrates `popover_menus` module to TypeScript. Also adds
a placeholder types declaration file for `css_variables` module.
(cherry picked from commit 02257b8cbf
)
This commit is contained in:
parent
3e012889aa
commit
edeea66b0f
|
@ -84,6 +84,7 @@ EXEMPT_FILES = make_set(
|
|||
"web/src/copied_tooltip.ts",
|
||||
"web/src/copy_and_paste.js",
|
||||
"web/src/csrf.ts",
|
||||
"web/src/css_variables.d.ts",
|
||||
"web/src/css_variables.js",
|
||||
"web/src/custom_profile_fields_ui.js",
|
||||
"web/src/dark_theme.ts",
|
||||
|
@ -166,9 +167,10 @@ EXEMPT_FILES = make_set(
|
|||
"web/src/pm_list_dom.ts",
|
||||
"web/src/poll_modal.js",
|
||||
"web/src/poll_widget.ts",
|
||||
"web/src/popover_menus.js",
|
||||
"web/src/popover_menus.ts",
|
||||
"web/src/popover_menus_data.js",
|
||||
"web/src/popovers.ts",
|
||||
"web/src/popperjs.d.ts",
|
||||
"web/src/read_receipts.js",
|
||||
"web/src/ready.ts",
|
||||
"web/src/realm_icon.ts",
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
/* This is a placeholder typescript declaration file for `css_variables` module.
|
||||
We can't convert the `css_variables` module to typescript yet because converting
|
||||
it causes Webpack to trigger type checking with the TypeScript compiler, which is very expensive.
|
||||
|
||||
TS-migration of this module was reverted in this PR: https://github.com/zulip/zulip/pull/24985.
|
||||
*/
|
||||
|
||||
declare const css_variables: {
|
||||
media_breakpoints: {
|
||||
xs_min: string;
|
||||
sm_min: string;
|
||||
md_min: string;
|
||||
mc_min: string;
|
||||
lg_min: string;
|
||||
xl_min: string;
|
||||
ml_min: string;
|
||||
mm_min: string;
|
||||
ms_min: string;
|
||||
};
|
||||
media_breakpoints_num: {
|
||||
xs: number;
|
||||
sm: number;
|
||||
md: number;
|
||||
mc: number;
|
||||
lg: number;
|
||||
xl: number;
|
||||
ml: number;
|
||||
mm: number;
|
||||
ms: number;
|
||||
};
|
||||
};
|
||||
|
||||
export = css_variables;
|
|
@ -3,6 +3,7 @@
|
|||
popovers system in popovers.js. */
|
||||
|
||||
import $ from "jquery";
|
||||
import type {Instance as PopoverInstance, Props as PopoverProps, ReferenceElement} from "tippy.js";
|
||||
import tippy from "tippy.js";
|
||||
|
||||
import * as blueslip from "./blueslip";
|
||||
|
@ -12,7 +13,25 @@ import * as overlays from "./overlays";
|
|||
import * as popovers from "./popovers";
|
||||
import * as util from "./util";
|
||||
|
||||
export const popover_instances = {
|
||||
type PopoverName =
|
||||
| "compose_control_buttons"
|
||||
| "starred_messages"
|
||||
| "drafts"
|
||||
| "left_sidebar_inbox_popover"
|
||||
| "left_sidebar_all_messages_popover"
|
||||
| "left_sidebar_recent_view_popover"
|
||||
| "top_left_sidebar"
|
||||
| "message_actions"
|
||||
| "stream_settings"
|
||||
| "compose_mobile_button"
|
||||
| "topics_menu"
|
||||
| "send_later"
|
||||
| "change_visibility_policy"
|
||||
| "personal_menu"
|
||||
| "gear_menu"
|
||||
| "help_menu";
|
||||
|
||||
export const popover_instances: Record<PopoverName, PopoverInstance | null> = {
|
||||
compose_control_buttons: null,
|
||||
starred_messages: null,
|
||||
drafts: null,
|
||||
|
@ -32,7 +51,7 @@ export const popover_instances = {
|
|||
};
|
||||
|
||||
/* Keyboard UI functions */
|
||||
export function popover_items_handle_keyboard(key, $items) {
|
||||
export function popover_items_handle_keyboard(key: string, $items?: JQuery): void {
|
||||
if (!$items) {
|
||||
return;
|
||||
}
|
||||
|
@ -58,7 +77,7 @@ export function popover_items_handle_keyboard(key, $items) {
|
|||
$items.eq(index).trigger("focus");
|
||||
}
|
||||
|
||||
export function focus_first_popover_item($items, index = 0) {
|
||||
export function focus_first_popover_item($items: JQuery, index = 0): void {
|
||||
if (!$items) {
|
||||
return;
|
||||
}
|
||||
|
@ -66,56 +85,59 @@ export function focus_first_popover_item($items, index = 0) {
|
|||
$items.eq(index).expectOne().trigger("focus");
|
||||
}
|
||||
|
||||
export function sidebar_menu_instance_handle_keyboard(instance, key) {
|
||||
export function sidebar_menu_instance_handle_keyboard(
|
||||
instance: PopoverInstance,
|
||||
key: string,
|
||||
): void {
|
||||
const items = get_popover_items_for_instance(instance);
|
||||
popover_items_handle_keyboard(key, items);
|
||||
}
|
||||
|
||||
export function get_visible_instance() {
|
||||
export function get_visible_instance(): PopoverInstance | null | undefined {
|
||||
return Object.values(popover_instances).find(Boolean);
|
||||
}
|
||||
|
||||
export function get_topic_menu_popover() {
|
||||
export function get_topic_menu_popover(): PopoverInstance | null {
|
||||
return popover_instances.topics_menu;
|
||||
}
|
||||
|
||||
export function get_scheduled_messages_popover() {
|
||||
export function get_scheduled_messages_popover(): PopoverInstance | null {
|
||||
return popover_instances.send_later;
|
||||
}
|
||||
|
||||
export function is_scheduled_messages_popover_displayed() {
|
||||
export function is_scheduled_messages_popover_displayed(): boolean | undefined {
|
||||
return popover_instances.send_later?.state.isVisible;
|
||||
}
|
||||
|
||||
export function get_compose_control_buttons_popover() {
|
||||
export function get_compose_control_buttons_popover(): PopoverInstance | null {
|
||||
return popover_instances.compose_control_buttons;
|
||||
}
|
||||
|
||||
export function get_starred_messages_popover() {
|
||||
export function get_starred_messages_popover(): PopoverInstance | null {
|
||||
return popover_instances.starred_messages;
|
||||
}
|
||||
|
||||
export function is_personal_menu_popover_displayed() {
|
||||
export function is_personal_menu_popover_displayed(): boolean | undefined {
|
||||
return popover_instances.personal_menu?.state.isVisible;
|
||||
}
|
||||
|
||||
export function is_gear_menu_popover_displayed() {
|
||||
export function is_gear_menu_popover_displayed(): boolean | undefined {
|
||||
return popover_instances.gear_menu?.state.isVisible;
|
||||
}
|
||||
|
||||
export function get_gear_menu_instance() {
|
||||
export function get_gear_menu_instance(): PopoverInstance | null {
|
||||
return popover_instances.gear_menu;
|
||||
}
|
||||
|
||||
export function is_help_menu_popover_displayed() {
|
||||
export function is_help_menu_popover_displayed(): boolean | undefined {
|
||||
return popover_instances.help_menu?.state.isVisible;
|
||||
}
|
||||
|
||||
export function is_message_actions_popover_displayed() {
|
||||
export function is_message_actions_popover_displayed(): boolean | undefined {
|
||||
return popover_instances.message_actions?.state.isVisible;
|
||||
}
|
||||
|
||||
function get_popover_items_for_instance(instance) {
|
||||
function get_popover_items_for_instance(instance: PopoverInstance): JQuery | undefined {
|
||||
const $current_elem = $(instance.popper);
|
||||
const class_name = $current_elem.attr("class");
|
||||
|
||||
|
@ -127,7 +149,7 @@ function get_popover_items_for_instance(instance) {
|
|||
return $current_elem.find("a:visible");
|
||||
}
|
||||
|
||||
export const default_popover_props = {
|
||||
export const default_popover_props: Partial<PopoverProps> = {
|
||||
delay: 0,
|
||||
appendTo: () => document.body,
|
||||
trigger: "click",
|
||||
|
@ -154,7 +176,8 @@ export const default_popover_props = {
|
|||
phase: "beforeWrite",
|
||||
requires: ["$$tippy"],
|
||||
fn({state}) {
|
||||
const instance = state.elements.reference._tippy;
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
||||
const instance = (state.elements.reference as ReferenceElement)._tippy!;
|
||||
const $popover = $(state.elements.popper);
|
||||
const $tippy_box = $popover.find(".tippy-box");
|
||||
if ($tippy_box.hasClass("show-when-reference-hidden")) {
|
||||
|
@ -249,7 +272,7 @@ export const left_sidebar_tippy_options = {
|
|||
},
|
||||
};
|
||||
|
||||
export function on_show_prep(instance) {
|
||||
export function on_show_prep(instance: PopoverInstance): void {
|
||||
$(instance.popper).on("click", (e) => {
|
||||
// Popover is not hidden on click inside it unless the click handler for the
|
||||
// element explicitly hides the popover when handling the event.
|
||||
|
@ -264,22 +287,19 @@ export function on_show_prep(instance) {
|
|||
});
|
||||
}
|
||||
|
||||
function get_props_for_popover_centering(popover_props) {
|
||||
function get_props_for_popover_centering(
|
||||
popover_props: Partial<PopoverProps>,
|
||||
): Partial<PopoverProps> {
|
||||
return {
|
||||
arrow: false,
|
||||
getReferenceClientRect: () => ({
|
||||
width: 0,
|
||||
height: 0,
|
||||
left: 0,
|
||||
top: 0,
|
||||
}),
|
||||
getReferenceClientRect: () => new DOMRect(0, 0, 0, 0),
|
||||
placement: "top",
|
||||
popperOptions: {
|
||||
modifiers: [
|
||||
{
|
||||
name: "offset",
|
||||
options: {
|
||||
offset({popper}) {
|
||||
offset({popper}: {popper: DOMRect}) {
|
||||
// Calculate the offset needed to place the reference in the center
|
||||
const x_offset_to_center = window.innerWidth / 2;
|
||||
let y_offset_to_center = window.innerHeight / 2 - popper.height / 2;
|
||||
|
@ -291,7 +311,7 @@ function get_props_for_popover_centering(popover_props) {
|
|||
// is causing a resize (thus calling this `offset` modifier function), in which case
|
||||
// we need to move the popover to the top of the screen.
|
||||
if (util.is_mobile()) {
|
||||
const $focused_element = $(document.activeElement);
|
||||
const $focused_element = $(document.activeElement!);
|
||||
if (
|
||||
$focused_element.is(
|
||||
"input[type=text], input[type=number], textarea",
|
||||
|
@ -334,7 +354,11 @@ function get_props_for_popover_centering(popover_props) {
|
|||
|
||||
// Toggles a popover menu directly; intended for use in keyboard
|
||||
// shortcuts and similar alternative ways to open a popover menu.
|
||||
export function toggle_popover_menu(target, popover_props, options) {
|
||||
export function toggle_popover_menu(
|
||||
target: ReferenceElement,
|
||||
popover_props: Partial<PopoverProps>,
|
||||
options?: {show_as_overlay_on_mobile: boolean},
|
||||
): void {
|
||||
const instance = target._tippy;
|
||||
if (instance) {
|
||||
instance.hide();
|
||||
|
@ -353,7 +377,7 @@ export function toggle_popover_menu(target, popover_props, options) {
|
|||
|
||||
if (popover_props.popperOptions?.modifiers) {
|
||||
popover_props.popperOptions.modifiers = [
|
||||
...default_popover_props.popperOptions.modifiers,
|
||||
...default_popover_props.popperOptions!.modifiers!,
|
||||
...popover_props.popperOptions.modifiers,
|
||||
];
|
||||
}
|
||||
|
@ -368,7 +392,7 @@ export function toggle_popover_menu(target, popover_props, options) {
|
|||
|
||||
// Main function to define a popover menu, opened via clicking on the
|
||||
// target selector.
|
||||
export function register_popover_menu(target, popover_props) {
|
||||
export function register_popover_menu(target: string, popover_props: Partial<PopoverProps>): void {
|
||||
// For some elements, such as the click target to open the message
|
||||
// actions menu, we want to avoid propagating the click event to
|
||||
// parent elements. Tippy's built-in `delegate` method does not
|
||||
|
@ -389,7 +413,7 @@ export function register_popover_menu(target, popover_props) {
|
|||
});
|
||||
}
|
||||
|
||||
export function initialize() {
|
||||
export function initialize(): void {
|
||||
/* Configure popovers to hide when toggling overlays. */
|
||||
overlays.register_pre_open_hook(popovers.hide_all);
|
||||
overlays.register_pre_close_hook(popovers.hide_all);
|
Loading…
Reference in New Issue