Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Saved segments variant C #4888

Draft
wants to merge 11 commits into
base: saved-segments/edit-actions-in-filters-menu
Choose a base branch
from
Draft
69 changes: 66 additions & 3 deletions assets/js/dashboard/components/dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
AppNavigationTarget
} from '../navigation/use-app-navigate'
import { NavigateOptions } from 'react-router-dom'
import { primaryNeutralButtonClass } from '../segments/segment-modals'

export const DropdownSubtitle = ({
children,
Expand All @@ -32,10 +33,68 @@ export const DropdownSubtitle = ({
</div>
)

export const SplitButton = forwardRef<
HTMLDivElement,
{
className?: string
leftOption: ReactNode
children: ReactNode
onClick: () => void
dropdownContainerProps: DetailedHTMLProps<
HTMLAttributes<HTMLButtonElement>,
HTMLButtonElement
>
}
>(
(
{
className,
leftOption,
children,
onClick,
dropdownContainerProps
// ...props
},
ref
) => {
const sharedButtonClass = 'flex items-stretch text-sm leading-tight h-9'

return (
<div className={className} ref={ref}>
<div
className={
classNames(sharedButtonClass)
// primaryNeutralButtonClass
// padded && 'p-2'
}
>
{leftOption}
{/* <div className="w-[1px]border-l-1 border-indigo-800 self-stretch"></div> */}
<button
className={classNames(
primaryNeutralButtonClass,
'!px-2 !py-2',
'rounded-l-none',
'border-l-1 border-indigo-800'
)}
onClick={onClick}
{...dropdownContainerProps}
aria-haspopup="true"
>
<ChevronDownIcon className="block w-4 h-4" />
</button>
</div>
{children}
</div>
)
}
)

export const ToggleDropdownButton = forwardRef<
HTMLDivElement,
{
variant?: 'ghost' | 'button'
padded?: boolean
withDropdownIndicator?: boolean
className?: string
currentOption: ReactNode
Expand All @@ -59,9 +118,9 @@ export const ToggleDropdownButton = forwardRef<
},
ref
) => {
const { variant } = { variant: 'button', ...props }
const { variant, padded } = { variant: 'button', padded: true, ...props }
const sharedButtonClass =
'flex items-center rounded text-sm leading-tight px-2 py-2 h-9'
'flex items-center rounded text-sm leading-tight h-9'

const buttonClass = {
ghost:
Expand All @@ -74,7 +133,11 @@ export const ToggleDropdownButton = forwardRef<
<div className={className} ref={ref}>
<button
onClick={onClick}
className={classNames(sharedButtonClass, buttonClass)}
className={classNames(
sharedButtonClass,
buttonClass,
padded && 'p-2'
)}
tabIndex={0}
aria-haspopup="true"
{...dropdownContainerProps}
Expand Down
42 changes: 27 additions & 15 deletions assets/js/dashboard/components/search-input.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
/** @format */

import React, { ChangeEventHandler, useCallback, useState, useRef } from 'react'
import { isModifierPressed, Keybind } from '../keybinding'
import { isModifierPressed, useKeybind } from '../keybinding'
import { useDebounce } from '../custom-hooks'
import classNames from 'classnames'

export const SearchInput = ({
className,
onSearch,
initialValue
initialValue,
placeholderFocused,
placeholderUnfocused
}: {
className?: string
onSearch: (value: string) => void
initialValue?: string
placeholderFocused?: string
placeholderUnfocused?: string
}) => {
const searchBoxRef = useRef<HTMLInputElement>(null)
const [isFocused, setIsFocused] = useState(false)
Expand Down Expand Up @@ -45,26 +49,34 @@ export const SearchInput = ({
[isFocused]
)

useKeybind({
target: searchBoxRef.current,
keyboardKey: 'Escape',
type: 'keyup',
handler: blurSearchBox,
shouldIgnoreWhen: [isModifierPressed]
})

useKeybind({
target: searchBoxRef.current,
keyboardKey: '/',
type: 'keyup',
handler: focusSearchBox,
shouldIgnoreWhen: [isModifierPressed]
})

return (
<>
<Keybind
keyboardKey="Escape"
type="keyup"
handler={blurSearchBox}
shouldIgnoreWhen={[isModifierPressed]}
/>
<Keybind
keyboardKey="/"
type="keyup"
handler={focusSearchBox}
shouldIgnoreWhen={[isModifierPressed]}
/>
<input
onBlur={() => setIsFocused(false)}
onFocus={() => setIsFocused(true)}
ref={searchBoxRef}
type="text"
placeholder={isFocused ? 'Search' : 'Press / to search'}
placeholder={
isFocused
? (placeholderFocused ?? 'Search')
: (placeholderUnfocused ?? 'Press / to search')
}
value={initialValue}
className={classNames(
'shadow-sm dark:bg-gray-900 dark:text-gray-100 focus:ring-indigo-500 focus:border-indigo-500 block sm:text-sm border-gray-300 dark:border-gray-500 rounded-md dark:bg-gray-800 w-48',
Expand Down
4 changes: 3 additions & 1 deletion assets/js/dashboard/dashboard-keybinds.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* @format */
import React from 'react'
import { NavigateKeybind } from './keybinding'
import { useSegmentExpandedContext } from './segments/segment-expanded-context'

const ClearFiltersKeybind = () => (
<NavigateKeybind
Expand All @@ -21,5 +22,6 @@ const ClearFiltersKeybind = () => (
)

export function DashboardKeybinds() {
return <>{false && <ClearFiltersKeybind />}</> // temp disable
const { modal } = useSegmentExpandedContext()
return modal === null && <ClearFiltersKeybind />
}
3 changes: 2 additions & 1 deletion assets/js/dashboard/datepicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ export default function QueryPeriodPicker() {
}, [closeMenu, query])

return (
<div className="flex pl-2 shrink-0">
<div className="flex pl-4 shrink-0">
<MovePeriodArrows />
<ToggleDropdownButton
withDropdownIndicator
Expand Down Expand Up @@ -449,6 +449,7 @@ export default function QueryPeriodPicker() {
type="keydown"
handler={onClick || closeMenu}
shouldIgnoreWhen={[isModifierPressed, isTyping]}
target={document}
/>
) : (
<NavigateKeybind
Expand Down
1 change: 1 addition & 0 deletions assets/js/dashboard/filters.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ function DropdownContent({ wrapped }) {
if (wrapped === WRAPSTATE.unwrapped || addingFilter) {
let filterModals = { ...FILTER_MODAL_TO_FILTER_GROUP }
if (!site.propsAvailable) delete filterModals.props
if (!site.flags.saved_segments) delete filterModals.segment

return <>{Object.keys(filterModals).map((option) => <OpenFilterGroupOptionsButton key={option} option={option} />)}</>
}
Expand Down
45 changes: 30 additions & 15 deletions assets/js/dashboard/keybinding.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,37 +60,51 @@ type KeyboardEventType = keyof Pick<
'keyup' | 'keydown' | 'keypress'
>

export function Keybind({
keyboardKey,
type,
handler,
shouldIgnoreWhen = []
}: {
type KeybindOptions = {
keyboardKey: string
type: KeyboardEventType
handler: (event: KeyboardEvent) => void
shouldIgnoreWhen?: Array<(event: KeyboardEvent) => boolean>
}) {
target?: Document | HTMLElement | null
}

export function useKeybind({
keyboardKey,
type,
handler,
shouldIgnoreWhen = [],
target
}: KeybindOptions) {
const wrappedHandler = useCallback(
(event: KeyboardEvent) => {
if (isKeyPressed(event, { keyboardKey, shouldIgnoreWhen })) {
handler(event)
}
},
[keyboardKey, handler, shouldIgnoreWhen]
)
) as EventListener

useEffect(() => {
const registerKeybind = () =>
document.addEventListener(type, wrappedHandler)
const registerKeybind = (t: HTMLElement | Document) =>
t.addEventListener(type, wrappedHandler)

const deregisterKeybind = () =>
document.removeEventListener(type, wrappedHandler)
const deregisterKeybind = (t: HTMLElement | Document) =>
t.removeEventListener(type, wrappedHandler)

registerKeybind()
if (target) {
registerKeybind(target)
}

return () => {
if (target) {
deregisterKeybind(target)
}
}
}, [target, type, wrappedHandler])
}

return deregisterKeybind
}, [type, wrappedHandler])
export function Keybind(opts: KeybindOptions) {
useKeybind(opts)

return null
}
Expand All @@ -115,6 +129,7 @@ export function NavigateKeybind({
type={type}
handler={handler}
shouldIgnoreWhen={[isModifierPressed, isTyping]}
target={document}
/>
)
}
Expand Down
Loading
Loading