Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
C
coopwire-hypothesis
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
孙灵跃 Leon Sun
coopwire-hypothesis
Commits
8493d07d
Commit
8493d07d
authored
Jul 28, 2020
by
Kyle Keating
Committed by
Kyle Keating
Jul 29, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Improve typecheck (menu, menu-item, slider)
parent
a5698b9c
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
96 additions
and
128 deletions
+96
-128
use-element-should-close.js
src/sidebar/components/hooks/use-element-should-close.js
+4
-4
menu-item.js
src/sidebar/components/menu-item.js
+45
-63
menu.js
src/sidebar/components/menu.js
+32
-53
slider.js
src/sidebar/components/slider.js
+9
-4
groups.js
src/sidebar/store/modules/groups.js
+6
-1
tsconfig.json
src/tsconfig.json
+0
-3
No files found.
src/sidebar/components/hooks/use-element-should-close.js
View file @
8493d07d
...
...
@@ -14,7 +14,7 @@ import { listen } from '../../util/dom';
*/
/**
* @typedef {Ref<HTML
ButtonElement> &
Ref<PreactElement>} PreactRef
* @typedef {Ref<HTML
Element> |
Ref<PreactElement>} PreactRef
*/
/**
...
...
@@ -52,13 +52,13 @@ export default function useElementShouldClose(
const
getCurrentNode
=
closeableEl
=>
{
// if base is present, assume its a preact component
const
node
=
closeableEl
.
current
.
base
?
closeableEl
.
current
.
base
const
node
=
/** @type {PreactElement} */
(
closeableEl
.
current
)
.
base
?
/** @type {PreactElement} */
(
closeableEl
.
current
)
.
base
:
closeableEl
.
current
;
if
(
typeof
node
!==
'object'
)
{
throw
new
Error
(
'useElementShouldClose can not find a node reference'
);
}
return
node
;
return
/** @type {Node} */
(
node
)
;
};
useEffect
(()
=>
{
...
...
src/sidebar/components/menu-item.js
View file @
8493d07d
...
...
@@ -9,6 +9,44 @@ import SvgIcon from '../../shared/components/svg-icon';
import
MenuKeyboardNavigation
from
'./menu-keyboard-navigation'
;
import
Slider
from
'./slider'
;
/**
* @typedef MenuItemProps
* @prop {string} [href] -
* URL of the external link to open when this item is clicked. Either the `href` or an
* `onClick` callback should be supplied.
* @prop {string} [iconAlt] - Alt text for icon.
* @prop {string} [icon] -
* Name or URL of icon to display. If the value is a URL it is displayed using an `<img>`,
* if it is a name it is displayed using `SvgIcon`. If the property is `"blank"` a blank
* placeholder is displayed in place of an icon. If the property is falsey, no placeholder
* is displayed. The placeholder is useful to keep menu item labels aligned in a list if
* some items have icons and others do not.
* @prop {boolean} [isDisabled] -
* Dim the label to indicate that this item is not currently available. The `onClick`
* callback will still be invoked when this item is clicked and the submenu, if any,
* can still be toggled.
* @prop {boolean} [isExpanded] -
* Indicates that the submenu associated with this item is currently open.
* @prop {boolean} [isSelected] -
* Display an indicator to show that this menu item represents something which is currently
* selected/active/focused.
* @prop {boolean} [isSubmenuItem] -
* True if this item is part of a submenu, in which case it is rendered with a different
* style (shaded background)
* @prop {boolean} [isSubmenuVisible] -
* If present, display a button to toggle the sub-menu associated with this item and
* indicate the current state; `true` if the submenu is visible. Note. Omit this prop,
* or set it to null, if there is no `submenu`.
* @prop {string} label - Label of the menu item.
* @prop {(e: Event) => any} [onClick] - Callback to invoke when the menu item is clicked.
* @prop {(e: Event) => any} [onToggleSubmenu] -
* Callback when the user clicks on the toggle to change the expanded state of the menu.
* @prop {Object} [submenu] -
* Contents of the submenu for this item. This is typically a list of `MenuItem` components
* with the `isSubmenuItem` prop set to `true`, but can include other content as well.
* The submenu is only rendered if `isSubmenuVisible` is `true`.
*/
/**
* An item in a dropdown menu.
*
...
...
@@ -24,6 +62,8 @@ import Slider from './slider';
* For items that have submenus, the `MenuItem` will call the `renderSubmenu`
* prop to render the content of the submenu, when the submenu is visible.
* Note that the `submenu` is not supported for link (`href`) items.
*
* @param {MenuItemProps} props
*/
export
default
function
MenuItem
({
href
,
...
...
@@ -45,7 +85,9 @@ export default function MenuItem({
const
hasLeftIcon
=
icon
||
isSubmenuItem
;
const
hasRightIcon
=
icon
&&
isSubmenuItem
;
const
menuItemRef
=
useRef
(
null
);
const
menuItemRef
=
useRef
(
/** @type {(HTMLAnchorElement & HTMLDivElement)|null} */
(
null
)
);
let
focusTimer
=
null
;
let
renderedIcon
=
null
;
...
...
@@ -110,7 +152,7 @@ export default function MenuItem({
})}
href
=
{
href
}
target
=
"_blank"
tabIndex
=
"-1"
tabIndex
=
{
-
1
}
rel
=
"noopener noreferrer"
role
=
"menuitem"
onKeyDown
=
{
onKeyDown
}
...
...
@@ -137,7 +179,7 @@ export default function MenuItem({
'is-expanded'
:
isExpanded
,
'is-selected'
:
isSelected
,
})}
tabIndex
=
"-1"
tabIndex
=
{
-
1
}
onKeyDown
=
{
onKeyDown
}
onClick
=
{
onClick
}
role
=
{
isRadioButtonType
?
'menuitemradio'
:
'menuitem'
}
...
...
@@ -193,76 +235,16 @@ export default function MenuItem({
}
MenuItem
.
propTypes
=
{
/**
* URL of the external link to open when this item is clicked.
* Either the `href` or an `onClick` callback should be supplied.
*/
href
:
propTypes
.
string
,
/** Alt text for icon. */
iconAlt
:
propTypes
.
string
,
/**
* Name or URL of icon to display. If the value is a URL it is displayed
* using an `<img>`, if it is a name it is displayed using `SvgIcon`.
*
* If the property is `"blank"` a blank placeholder is displayed in place of an
* icon. If the property is falsey, no placeholder is displayed.
* The placeholder is useful to keep menu item labels aligned in a list if
* some items have icons and others do not.
*/
icon
:
propTypes
.
string
,
/**
* Dim the label to indicate that this item is not currently available.
*
* The `onClick` callback will still be invoked when this item is clicked and
* the submenu, if any, can still be toggled.
*/
isDisabled
:
propTypes
.
bool
,
/**
* Indicates that the submenu associated with this item is currently open.
*/
isExpanded
:
propTypes
.
bool
,
/**
* Display an indicator to show that this menu item represents something
* which is currently selected/active/focused.
*/
isSelected
:
propTypes
.
bool
,
/**
* True if this item is part of a submenu, in which case it is rendered
* with a different style (shaded background)
*/
isSubmenuItem
:
propTypes
.
bool
,
/**
* If present, display a button to toggle the sub-menu associated with this
* item and indicate the current state; `true` if the submenu is visible.
* Note. Omit this prop, or set it to null, if there is no `submenu`.
*/
isSubmenuVisible
:
propTypes
.
bool
,
/** Label of the menu item. */
label
:
propTypes
.
string
.
isRequired
,
/** Callback to invoke when the menu item is clicked. */
onClick
:
propTypes
.
func
,
/**
* Callback when the user clicks on the toggle to change the expanded
* state of the menu.
*/
onToggleSubmenu
:
propTypes
.
func
,
/**
* Contents of the submenu for this item.
*
* This is typically a list of `MenuItem` components with the `isSubmenuItem`
* prop set to `true`, but can include other content as well.
* The submenu is only rendered if `isSubmenuVisible` is `true`.
*/
submenu
:
propTypes
.
any
,
};
src/sidebar/components/menu.js
View file @
8493d07d
...
...
@@ -24,6 +24,34 @@ const menuArrow = className => (
*/
let
ignoreNextClick
=
false
;
/**
* @typedef MenuProps
* @prop {'left'|'right'} [align] -
* Whether the menu content is aligned with the left (default) or right edges of the
* toggle element.
* @prop {string} [arrowClass] -
* Additional CSS class for the arrow caret at the edge of the menu content that "points"
* toward the menu's toggle button. This can be used to adjust the position of that caret
* respective to the toggle button.
* @prop {Object|string} [label] - Label element for the toggle button that hides and shows the menu.
* @prop {Object} [children] -
* Menu items and sections to display in the content area of the menu. These are typically
* `MenuSection` and `MenuItem` components, but other custom content is also allowed.
* @prop {boolean} [containerPositioned] -
* Whether the menu elements should be positioned relative to the Menu container. When
* `false`, the consumer is responsible for positioning.
* @prop {string} [contentClass] - Additional CSS classes to apply to the menu.
* @prop {boolean} [defaultOpen] - Whether the menu is open or closed when initially rendered.
* @prop {(open: boolean) => any} [onOpenChanged] - Callback invoked when the menu is
* opened or closed. This can be used, for example, to reset any ephemeral state that the
* menu content may have.
* @prop {string} title -
* A title for the menu. This is important for accessibility if the menu's toggle button
* has only an icon as a label.
* @prop {boolean} [menuIndicator] -
* Whether to display an indicator next to the label that there is a dropdown menu.
*/
/**
* A drop-down menu.
*
...
...
@@ -41,6 +69,8 @@ let ignoreNextClick = false;
* <MenuItem label="Log out"/>
* </MenuSection>
* </Menu>
*
* @param {MenuProps} props
*/
export
default
function
Menu
({
align
=
'left'
,
...
...
@@ -89,7 +119,7 @@ export default function Menu({
//
// These handlers close the menu when the user taps or clicks outside the
// menu or presses Escape.
const
menuRef
=
useRef
();
const
menuRef
=
useRef
(
/** @type {HTMLDivElement|null} */
(
null
)
);
// Menu element should close via `closeMenu` whenever it's open and there
// are user interactions outside of it (e.g. clicks) in the document
...
...
@@ -163,7 +193,7 @@ export default function Menu({
contentClass
)}
role
=
"menu"
tabIndex
=
"-1"
tabIndex
=
{
-
1
}
onClick
=
{
closeMenu
}
onKeyDown
=
{
handleMenuKeyDown
}
>
...
...
@@ -178,68 +208,17 @@ export default function Menu({
}
Menu
.
propTypes
=
{
/**
* Whether the menu content is aligned with the left (default) or right edges
* of the toggle element.
*/
align
:
propTypes
.
oneOf
([
'left'
,
'right'
]),
/**
* Additional CSS class for the arrow caret at the edge of the menu
* content that "points" toward the menu's toggle button. This can be used
* to adjust the position of that caret respective to the toggle button.
*/
arrowClass
:
propTypes
.
string
,
/**
* Label element for the toggle button that hides and shows the menu.
*/
label
:
propTypes
.
oneOfType
([
propTypes
.
object
.
isRequired
,
propTypes
.
string
.
isRequired
,
]),
/**
* Menu items and sections to display in the content area of the menu.
*
* These are typically `MenuSection` and `MenuItem` components, but other
* custom content is also allowed.
*/
children
:
propTypes
.
any
,
/**
* Whether the menu elements should be positioned relative to the Menu
* container. When `false`, the consumer is responsible for positioning.
*/
containerPositioned
:
propTypes
.
bool
,
/**
* Additional CSS classes to apply to the menu.
*/
contentClass
:
propTypes
.
string
,
/**
* Whether the menu is open or closed when initially rendered.
*/
defaultOpen
:
propTypes
.
bool
,
/**
* Callback invoked when the menu is opened or closed.
*
* This can be used, for example, to reset any ephemeral state that the
* menu content may have.
*/
onOpenChanged
:
propTypes
.
func
,
/**
* A title for the menu. This is important for accessibility if the menu's
* toggle button has only an icon as a label.
*/
title
:
propTypes
.
string
.
isRequired
,
/**
* Whether to display an indicator next to the label that there is a
* dropdown menu.
*/
menuIndicator
:
propTypes
.
bool
,
};
src/sidebar/components/slider.js
View file @
8493d07d
...
...
@@ -2,6 +2,12 @@ import { createElement } from 'preact';
import
{
useCallback
,
useEffect
,
useRef
,
useState
}
from
'preact/hooks'
;
import
propTypes
from
'prop-types'
;
/**
* @typedef SliderProps
* @prop {Object} [children] - The slideable content to hide or reveal.
* @prop {boolean} visible - Whether the content should be visible or not.
*/
/**
* A container which reveals its content when `visible` is `true` using
* a sliding animation.
...
...
@@ -11,6 +17,8 @@ import propTypes from 'prop-types';
* order.
*
* Currently the only reveal/expand direction supported is top-down.
*
* @param {SliderProps} props
*/
export
default
function
Slider
({
children
,
visible
})
{
const
containerRef
=
useRef
(
null
);
...
...
@@ -76,6 +84,7 @@ export default function Slider({ children, visible }) {
// nb. Preact uses "ontransitionend" rather than "onTransitionEnd".
// See https://bugs.chromium.org/p/chromium/issues/detail?id=961193
//
// @ts-ignore
// eslint-disable-next-line react/no-unknown-property
ontransitionend
=
{
handleTransitionEnd
}
ref
=
{
containerRef
}
...
...
@@ -97,9 +106,5 @@ export default function Slider({ children, visible }) {
Slider
.
propTypes
=
{
children
:
propTypes
.
any
,
/**
* Whether the content should be visible or not.
*/
visible
:
propTypes
.
bool
,
};
src/sidebar/store/modules/groups.js
View file @
8493d07d
...
...
@@ -206,7 +206,12 @@ const getCurrentlyViewingGroups = createSelector(
*
* // Selectors
* @prop {() => Group[]} allGroups
* // TODO: add rest ...
* @prop {() => Group[]} allGroups
* @prop {() => Group|undefined|null} focusedGroup
* @prop {() => string|null} focusedGroupId
* @prop {() => Group[]} getFeaturedGroups
* @prop {(id: string) => Group|undefined} getGroup
* @prop {() => Group[]} getInScopeGroups
*/
export
default
{
...
...
src/tsconfig.json
View file @
8493d07d
...
...
@@ -48,8 +48,6 @@
"sidebar/components/hypothesis-app.js"
,
"sidebar/components/logged-out-message.js"
,
"sidebar/components/login-prompt-panel.js"
,
"sidebar/components/menu-item.js"
,
"sidebar/components/menu.js"
,
"sidebar/components/moderation-banner.js"
,
"sidebar/components/new-note-btn.js"
,
"sidebar/components/search-input.js"
,
...
...
@@ -59,7 +57,6 @@
"sidebar/components/sidebar-content-error.js"
,
"sidebar/components/sidebar-content.js"
,
"sidebar/components/sidebar-panel.js"
,
"sidebar/components/slider.js"
,
"sidebar/components/sort-menu.js"
,
"sidebar/components/stream-content.js"
,
"sidebar/components/stream-search-input.js"
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment