fix(dashboard): Tab behaviour in DataGrid (#8973)

* fix focus in datagrid

* cleanup

* fix keyboard commands

* cleanup

* cleanup

* always allow handler for special focus to fire

* cleanup
This commit is contained in:
Kasper Fabricius Kristensen authored and GitHub committed 2024-09-03 20:54:47 +02:00
1 parent f47f1aff49
commit 58c78a7f62
9 files changed
+270 -255

No files matched your search

@@ -43,14 +43,12 @@
"@uiw/react-json-view": "^2.0.0-alpha.17", "@uiw/react-json-view": "^2.0.0-alpha.17",
"cmdk": "^0.2.0", "cmdk": "^0.2.0",
"date-fns": "^3.6.0", "date-fns": "^3.6.0",
"focus-trap-react": "^10.2.3",
"framer-motion": "^11.0.3", "framer-motion": "^11.0.3",
"i18next": "23.7.11", "i18next": "23.7.11",
"i18next-browser-languagedetector": "7.2.0", "i18next-browser-languagedetector": "7.2.0",
"i18next-http-backend": "2.4.2", "i18next-http-backend": "2.4.2",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"match-sorter": "^6.3.4", "match-sorter": "^6.3.4",
"prop-types": "^15.8.1",
"qs": "^6.12.0", "qs": "^6.12.0",
"react": "^18.2.0", "react": "^18.2.0",
"react-country-flag": "^3.1.0", "react-country-flag": "^3.1.0",
@@ -136,6 +136,20 @@ const useDataGridShortcuts = () => {
Windows: ["Shift", "Ctrl", "↑"], Windows: ["Shift", "Ctrl", "↑"],
}, },
}, },
{
label: t("dataGrid.shortcuts.commands.focusToolbar"),
keys: {
Mac: ["⌃", "⌥", ","],
Windows: ["Ctrl", "Alt", ","],
},
},
{
label: t("dataGrid.shortcuts.commands.focusCancel"),
keys: {
Mac: ["⌃", "⌥", "."],
Windows: ["Ctrl", "Alt", "."],
},
},
], ],
[t] [t]
) )
@@ -16,10 +16,8 @@ import {
useReactTable, useReactTable,
} from "@tanstack/react-table" } from "@tanstack/react-table"
import { VirtualItem, useVirtualizer } from "@tanstack/react-virtual" import { VirtualItem, useVirtualizer } from "@tanstack/react-virtual"
import FocusTrap from "focus-trap-react" import React, {
import {
CSSProperties, CSSProperties,
MouseEvent,
ReactNode, ReactNode,
useCallback, useCallback,
useEffect, useEffect,
@@ -48,12 +46,11 @@ import {
} from "../hooks" } from "../hooks"
import { DataGridMatrix } from "../models" import { DataGridMatrix } from "../models"
import { DataGridCoordinates, GridColumnOption } from "../types" import { DataGridCoordinates, GridColumnOption } from "../types"
import { generateCellId, isCellMatch } from "../utils" import { isCellMatch, isSpecialFocusKey } from "../utils"
import { DataGridKeyboardShortcutModal } from "./data-grid-keyboard-shortcut-modal" import { DataGridKeyboardShortcutModal } from "./data-grid-keyboard-shortcut-modal"
export interface DataGridRootProps< export interface DataGridRootProps<
TData, TData,
TFieldValues extends FieldValues = FieldValues TFieldValues extends FieldValues = FieldValues,
> { > {
data?: TData[] data?: TData[]
columns: ColumnDef<TData>[] columns: ColumnDef<TData>[]
@@ -98,7 +95,7 @@ const getCommonPinningStyles = <TData,>(
export const DataGridRoot = < export const DataGridRoot = <
TData, TData,
TFieldValues extends FieldValues = FieldValues TFieldValues extends FieldValues = FieldValues,
>({ >({
data = [], data = [],
columns, columns,
@@ -117,7 +114,7 @@ export const DataGridRoot = <
formState: { errors }, formState: { errors },
} = state } = state
const [trapActive, setTrapActive] = useState(false) const [trapActive, setTrapActive] = useState(true)
const [anchor, setAnchor] = useState<DataGridCoordinates | null>(null) const [anchor, setAnchor] = useState<DataGridCoordinates | null>(null)
const [rangeEnd, setRangeEnd] = useState<DataGridCoordinates | null>(null) const [rangeEnd, setRangeEnd] = useState<DataGridCoordinates | null>(null)
@@ -317,25 +314,28 @@ export const DataGridRoot = <
anchor, anchor,
}) })
const { handleKeyDownEvent } = useDataGridKeydownEvent<TData, TFieldValues>({ const { handleKeyDownEvent, handleSpecialFocusKeys } =
matrix, useDataGridKeydownEvent<TData, TFieldValues>({
queryTool, containerRef,
anchor, matrix,
rangeEnd, queryTool,
isEditing, anchor,
setRangeEnd, rangeEnd,
getSelectionValues, isEditing,
getValues, setTrapActive,
setSelectionValues, setRangeEnd,
onEditingChangeHandler, getSelectionValues,
restoreSnapshot, getValues,
setSingleRange, setSelectionValues,
scrollToCoordinates, onEditingChangeHandler,
execute, restoreSnapshot,
undo, setSingleRange,
redo, scrollToCoordinates,
setValue, execute,
}) undo,
redo,
setValue,
})
const { handleMouseUpEvent } = useDataGridMouseUpEvent<TData, TFieldValues>({ const { handleMouseUpEvent } = useDataGridMouseUpEvent<TData, TFieldValues>({
matrix, matrix,
@@ -401,26 +401,20 @@ export const DataGridRoot = <
* Register all handlers for the grid. * Register all handlers for the grid.
*/ */
useEffect(() => { useEffect(() => {
const container = containerRef.current if (!trapActive) {
if (
!container ||
!container.contains(document.activeElement) ||
!trapActive
) {
return return
} }
container.addEventListener("keydown", handleKeyDownEvent) window.addEventListener("keydown", handleKeyDownEvent)
container.addEventListener("mouseup", handleMouseUpEvent) window.addEventListener("mouseup", handleMouseUpEvent)
// Copy and paste event listeners need to be added to the window // Copy and paste event listeners need to be added to the window
window.addEventListener("copy", handleCopyEvent) window.addEventListener("copy", handleCopyEvent)
window.addEventListener("paste", handlePasteEvent) window.addEventListener("paste", handlePasteEvent)
return () => { return () => {
container.removeEventListener("keydown", handleKeyDownEvent) window.removeEventListener("keydown", handleKeyDownEvent)
container.removeEventListener("mouseup", handleMouseUpEvent) window.removeEventListener("mouseup", handleMouseUpEvent)
window.removeEventListener("copy", handleCopyEvent) window.removeEventListener("copy", handleCopyEvent)
window.removeEventListener("paste", handlePasteEvent) window.removeEventListener("paste", handlePasteEvent)
@@ -433,12 +427,25 @@ export const DataGridRoot = <
handlePasteEvent, handlePasteEvent,
]) ])
const [isHeaderInteractionActive, setIsHeaderInteractionActive] = useEffect(() => {
useState(false) const specialFocusHandler = (e: KeyboardEvent) => {
if (isSpecialFocusKey(e)) {
handleSpecialFocusKeys(e)
return
}
}
window.addEventListener("keydown", specialFocusHandler)
return () => {
window.removeEventListener("keydown", specialFocusHandler)
}
}, [handleSpecialFocusKeys])
const handleHeaderInteractionChange = useCallback((isActive: boolean) => { const handleHeaderInteractionChange = useCallback((isActive: boolean) => {
setIsHeaderInteractionActive(isActive) if (isActive) {
setTrapActive(!isActive) setTrapActive(false)
}
}, []) }, [])
/** /**
@@ -476,6 +483,7 @@ export const DataGridRoot = <
control, control,
trapActive, trapActive,
errors, errors,
setTrapActive,
setIsSelecting, setIsSelecting,
setIsEditing: onEditingChangeHandler, setIsEditing: onEditingChangeHandler,
setSingleRange, setSingleRange,
@@ -496,6 +504,7 @@ export const DataGridRoot = <
control, control,
trapActive, trapActive,
errors, errors,
setTrapActive,
setIsSelecting, setIsSelecting,
onEditingChangeHandler, onEditingChangeHandler,
setSingleRange, setSingleRange,
@@ -513,6 +522,19 @@ export const DataGridRoot = <
] ]
) )
const handleRestoreGridFocus = useCallback(() => {
if (anchor && !trapActive) {
setTrapActive(true)
setSingleRange(anchor)
scrollToCoordinates(anchor, "both")
requestAnimationFrame(() => {
queryTool?.getContainer(anchor)?.focus()
})
}
}, [anchor, trapActive, queryTool])
return ( return (
<DataGridContext.Provider value={values}> <DataGridContext.Provider value={values}>
<div className="bg-ui-bg-subtle flex size-full flex-col"> <div className="bg-ui-bg-subtle flex size-full flex-col">
@@ -526,178 +548,116 @@ export const DataGridRoot = <
isHighlighted={isHighlighted} isHighlighted={isHighlighted}
onHeaderInteractionChange={handleHeaderInteractionChange} onHeaderInteractionChange={handleHeaderInteractionChange}
/> />
<FocusTrap <div className="size-full overflow-hidden">
active={trapActive && !isHeaderInteractionActive} <div
focusTrapOptions={{ ref={containerRef}
initialFocus: () => { autoFocus
if (!anchor) { tabIndex={0}
const coords = matrix.getFirstNavigableCell() className="relative h-full select-none overflow-auto outline-none"
onFocus={handleRestoreGridFocus}
if (!coords) { onClick={handleRestoreGridFocus}
return undefined data-container={true}
} role="application"
>
const id = generateCellId(coords) <div role="grid" className="text-ui-fg-subtle grid">
<div
return containerRef.current?.querySelector( role="rowgroup"
`[data-container-id="${id}"]` className="txt-compact-small-plus bg-ui-bg-subtle sticky top-0 z-[1] grid"
) >
} {grid.getHeaderGroups().map((headerGroup) => (
<div
const id = generateCellId(anchor) role="row"
key={headerGroup.id}
const anchorContainer = containerRef.current?.querySelector( className="flex h-10 w-full"
`[data-container-id="${id}` >
) as HTMLElement | null {virtualPaddingLeft ? (
<div
return anchorContainer ?? undefined role="presentation"
}, style={{ display: "flex", width: virtualPaddingLeft }}
onActivate: () => setTrapActive(true), />
onDeactivate: () => setTrapActive(false), ) : null}
fallbackFocus: () => { {virtualColumns.reduce((acc, vc, index, array) => {
if (!anchor) { const header = headerGroup.headers[vc.index]
const coords = matrix.getFirstNavigableCell() const previousVC = array[index - 1]
if (!coords) {
return containerRef.current!
}
const id = generateCellId(coords)
const firstCell = containerRef.current?.querySelector(
`[data-container-id="${id}"]`
) as HTMLElement | null
if (firstCell) {
return firstCell
}
return containerRef.current!
}
const id = generateCellId(anchor)
const anchorContainer = containerRef.current?.querySelector(
`[data-container-id="${id}`
) as HTMLElement | null
if (anchorContainer) {
return anchorContainer
}
return containerRef.current!
},
allowOutsideClick: true,
escapeDeactivates: false,
}}
>
<div className="size-full overflow-hidden">
<div
ref={containerRef}
tabIndex={-1}
onFocus={() => !trapActive && setTrapActive(true)}
className="relative h-full select-none overflow-auto outline-none"
>
<div role="grid" className="text-ui-fg-subtle grid">
<div
role="rowgroup"
className="txt-compact-small-plus bg-ui-bg-subtle sticky top-0 z-[1] grid"
>
{grid.getHeaderGroups().map((headerGroup) => (
<div
role="row"
key={headerGroup.id}
className="flex h-10 w-full"
>
{virtualPaddingLeft ? (
<div
role="presentation"
style={{ display: "flex", width: virtualPaddingLeft }}
/>
) : null}
{virtualColumns.reduce((acc, vc, index, array) => {
const header = headerGroup.headers[vc.index]
const previousVC = array[index - 1]
if (previousVC && vc.index !== previousVC.index + 1) {
// If there's a gap between the current and previous virtual columns
acc.push(
<div
key={`padding-${previousVC.index}-${vc.index}`}
role="presentation"
style={{
display: "flex",
width: `${vc.start - previousVC.end}px`,
}}
/>
)
}
if (previousVC && vc.index !== previousVC.index + 1) {
// If there's a gap between the current and previous virtual columns
acc.push( acc.push(
<div <div
key={header.id} key={`padding-${previousVC.index}-${vc.index}`}
role="columnheader" role="presentation"
data-column-index={vc.index}
style={{ style={{
width: header.getSize(), display: "flex",
...getCommonPinningStyles(header.column), width: `${vc.start - previousVC.end}px`,
}} }}
className="bg-ui-bg-base txt-compact-small-plus flex items-center border-b border-r px-4 py-2.5" />
>
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext()
)}
</div>
) )
}
return acc acc.push(
}, [] as ReactNode[])}
{virtualPaddingRight ? (
<div <div
role="presentation" key={header.id}
role="columnheader"
data-column-index={vc.index}
style={{ style={{
display: "flex", width: header.getSize(),
width: virtualPaddingRight, ...getCommonPinningStyles(header.column),
}} }}
/> className="bg-ui-bg-base txt-compact-small-plus flex items-center border-b border-r px-4 py-2.5"
) : null} >
</div> {header.isPlaceholder
))} ? null
</div> : flexRender(
<div header.column.columnDef.header,
role="rowgroup" header.getContext()
className="relative grid" )}
style={{ </div>
height: `${rowVirtualizer.getTotalSize()}px`, )
}}
>
{virtualRows.map((virtualRow) => {
const row = visibleRows[virtualRow.index] as Row<TData>
const rowIndex = flatRows.findIndex((r) => r.id === row.id)
return ( return acc
<DataGridRow }, [] as ReactNode[])}
key={row.id} {virtualPaddingRight ? (
row={row} <div
rowIndex={rowIndex} role="presentation"
virtualRow={virtualRow} style={{
flatColumns={flatColumns} display: "flex",
virtualColumns={virtualColumns} width: virtualPaddingRight,
anchor={anchor} }}
virtualPaddingLeft={virtualPaddingLeft}
virtualPaddingRight={virtualPaddingRight}
onDragToFillStart={onDragToFillStart}
/> />
) ) : null}
})} </div>
</div> ))}
</div>
<div
role="rowgroup"
className="relative grid"
style={{
height: `${rowVirtualizer.getTotalSize()}px`,
}}
>
{virtualRows.map((virtualRow) => {
const row = visibleRows[virtualRow.index] as Row<TData>
const rowIndex = flatRows.findIndex((r) => r.id === row.id)
return (
<DataGridRow
key={row.id}
row={row}
rowIndex={rowIndex}
virtualRow={virtualRow}
flatColumns={flatColumns}
virtualColumns={virtualColumns}
anchor={anchor}
virtualPaddingLeft={virtualPaddingLeft}
virtualPaddingRight={virtualPaddingRight}
onDragToFillStart={onDragToFillStart}
/>
)
})}
</div> </div>
</div> </div>
</div> </div>
</FocusTrap> </div>
</div> </div>
</DataGridContext.Provider> </DataGridContext.Provider>
) )
@@ -783,6 +743,7 @@ const DataGridHeader = ({
type="button" type="button"
onClick={onResetColumns} onClick={onResetColumns}
className="text-ui-fg-muted hover:text-ui-fg-subtle" className="text-ui-fg-muted hover:text-ui-fg-subtle"
data-id="reset-columns"
> >
{t("dataGrid.columns.resetToDefault")} {t("dataGrid.columns.resetToDefault")}
</Button> </Button>
@@ -821,7 +782,7 @@ type DataGridCellProps<TData> = {
columnIndex: number columnIndex: number
rowIndex: number rowIndex: number
anchor: DataGridCoordinates | null anchor: DataGridCoordinates | null
onDragToFillStart: (e: MouseEvent<HTMLElement>) => void onDragToFillStart: (e: React.MouseEvent<HTMLElement>) => void
} }
const DataGridCell = <TData,>({ const DataGridCell = <TData,>({
@@ -880,7 +841,7 @@ type DataGridRowProps<TData> = {
virtualColumns: VirtualItem<Element>[] virtualColumns: VirtualItem<Element>[]
flatColumns: Column<TData, unknown>[] flatColumns: Column<TData, unknown>[]
anchor: DataGridCoordinates | null anchor: DataGridCoordinates | null
onDragToFillStart: (e: MouseEvent<HTMLElement>) => void onDragToFillStart: (e: React.MouseEvent<HTMLElement>) => void
} }
const DataGridRow = <TData,>({ const DataGridRow = <TData,>({
@@ -12,6 +12,7 @@ type DataGridContextType<TFieldValues extends FieldValues> = {
// Grid state // Grid state
anchor: DataGridCoordinates | null anchor: DataGridCoordinates | null
trapActive: boolean trapActive: boolean
setTrapActive: (value: boolean) => void
errors: FieldErrors<TFieldValues> errors: FieldErrors<TFieldValues>
// Cell handlers // Cell handlers
getIsCellSelected: (coords: DataGridCoordinates) => boolean getIsCellSelected: (coords: DataGridCoordinates) => boolean
@@ -7,7 +7,7 @@ import {
DataGridCellRenderProps, DataGridCellRenderProps,
DataGridCoordinates, DataGridCoordinates,
} from "../types" } from "../types"
import { isCellMatch } from "../utils" import { isCellMatch, isSpecialFocusKey } from "../utils"
type UseDataGridCellOptions<TData, TValue> = { type UseDataGridCellOptions<TData, TValue> = {
context: CellContext<TData, TValue> context: CellContext<TData, TValue>
@@ -162,6 +162,10 @@ export const useDataGridCell = <TData, TValue>({
return return
} }
if (isSpecialFocusKey(e.nativeEvent)) {
return
}
const event = new KeyboardEvent(e.type, e.nativeEvent) const event = new KeyboardEvent(e.type, e.nativeEvent)
inputRef.current.focus() inputRef.current.focus()
@@ -15,6 +15,7 @@ import {
import { DataGridCoordinates } from "../types" import { DataGridCoordinates } from "../types"
type UseDataGridKeydownEventOptions<TData, TFieldValues extends FieldValues> = { type UseDataGridKeydownEventOptions<TData, TFieldValues extends FieldValues> = {
containerRef: React.RefObject<HTMLDivElement>
matrix: DataGridMatrix<TData, TFieldValues> matrix: DataGridMatrix<TData, TFieldValues>
anchor: DataGridCoordinates | null anchor: DataGridCoordinates | null
rangeEnd: DataGridCoordinates | null rangeEnd: DataGridCoordinates | null
@@ -23,6 +24,7 @@ type UseDataGridKeydownEventOptions<TData, TFieldValues extends FieldValues> = {
coords: DataGridCoordinates, coords: DataGridCoordinates,
direction: "horizontal" | "vertical" | "both" direction: "horizontal" | "vertical" | "both"
) => void ) => void
setTrapActive: (active: boolean) => void
setSingleRange: (coordinates: DataGridCoordinates | null) => void setSingleRange: (coordinates: DataGridCoordinates | null) => void
setRangeEnd: (coordinates: DataGridCoordinates | null) => void setRangeEnd: (coordinates: DataGridCoordinates | null) => void
onEditingChangeHandler: (value: boolean) => void onEditingChangeHandler: (value: boolean) => void
@@ -44,12 +46,14 @@ const VERTICAL_KEYS = ["ArrowUp", "ArrowDown"]
export const useDataGridKeydownEvent = < export const useDataGridKeydownEvent = <
TData, TData,
TFieldValues extends FieldValues TFieldValues extends FieldValues,
>({ >({
containerRef,
matrix, matrix,
anchor, anchor,
rangeEnd, rangeEnd,
isEditing, isEditing,
setTrapActive,
scrollToCoordinates, scrollToCoordinates,
setSingleRange, setSingleRange,
setRangeEnd, setRangeEnd,
@@ -104,8 +108,8 @@ export const useDataGridKeydownEvent = <
direction === "horizontal" direction === "horizontal"
? setSingleRange ? setSingleRange
: e.shiftKey : e.shiftKey
? setRangeEnd ? setRangeEnd
: setSingleRange : setSingleRange
if (!basis) { if (!basis) {
return return
@@ -115,6 +119,7 @@ export const useDataGridKeydownEvent = <
const handleNavigation = (coords: DataGridCoordinates) => { const handleNavigation = (coords: DataGridCoordinates) => {
e.preventDefault() e.preventDefault()
e.stopPropagation()
scrollToCoordinates(coords, direction) scrollToCoordinates(coords, direction)
updater(coords) updater(coords)
@@ -140,6 +145,33 @@ export const useDataGridKeydownEvent = <
] ]
) )
const handleTabKey = useCallback(
(e: KeyboardEvent) => {
if (!anchor) {
return
}
e.preventDefault()
e.stopPropagation()
const { row, col } = anchor
const key = e.shiftKey ? "ArrowLeft" : "ArrowRight"
const direction = "horizontal"
const next = matrix.getValidMovement(
row,
col,
key,
e.metaKey || e.ctrlKey
)
scrollToCoordinates(next, direction)
setSingleRange(next)
},
[anchor, scrollToCoordinates, setSingleRange, matrix]
)
const handleUndo = useCallback( const handleUndo = useCallback(
(e: KeyboardEvent) => { (e: KeyboardEvent) => {
e.preventDefault() e.preventDefault()
@@ -460,27 +492,33 @@ export const useDataGridKeydownEvent = <
[queryTool, isEditing, anchor, restoreSnapshot] [queryTool, isEditing, anchor, restoreSnapshot]
) )
const handleTabKey = useCallback( const handleSpecialFocusKeys = useCallback(
(e: KeyboardEvent) => { (e: KeyboardEvent) => {
if (!anchor || isEditing) { if (!containerRef || isEditing) {
return return
} }
e.preventDefault() const focusableElements = getFocusableElements(containerRef)
const direction = e.shiftKey ? "ArrowLeft" : "ArrowRight" const focusElement = (element: HTMLElement | null) => {
if (element) {
setTrapActive(false)
element.focus()
}
}
const next = matrix.getValidMovement( switch (e.key) {
anchor.row, case ".":
anchor.col, focusElement(focusableElements.cancel)
direction, break
e.metaKey || e.ctrlKey case ",":
) focusElement(focusableElements.shortcuts)
break
setSingleRange(next) default:
scrollToCoordinates(next, "horizontal") break
}
}, },
[anchor, isEditing, scrollToCoordinates, setSingleRange, matrix] [anchor, isEditing, setTrapActive, containerRef]
) )
const handleKeyDownEvent = useCallback( const handleKeyDownEvent = useCallback(
@@ -533,5 +571,29 @@ export const useDataGridKeydownEvent = <
return { return {
handleKeyDownEvent, handleKeyDownEvent,
handleSpecialFocusKeys,
} }
} }
function getFocusableElements(ref: React.RefObject<HTMLDivElement>) {
const focusableElements = Array.from(
document.querySelectorAll<HTMLElement>(
"[tabindex], a, button, input, select, textarea"
)
)
const currentElementIndex = focusableElements.indexOf(ref.current!)
const shortcuts =
currentElementIndex > 0 ? focusableElements[currentElementIndex - 1] : null
let cancel = null
for (let i = currentElementIndex + 1; i < focusableElements.length; i++) {
if (!ref.current!.contains(focusableElements[i])) {
cancel = focusableElements[i]
break
}
}
return { shortcuts, cancel }
}
@@ -20,3 +20,9 @@ export function isCellMatch(
return cell.row === coords.row && cell.col === coords.col return cell.row === coords.row && cell.col === coords.col
} }
const SPECIAL_FOCUS_KEYS = [".", ","]
export function isSpecialFocusKey(event: KeyboardEvent) {
return SPECIAL_FOCUS_KEYS.includes(event.key) && event.ctrlKey && event.altKey
}
@@ -243,7 +243,9 @@
"selectDown": "Select down", "selectDown": "Select down",
"selectUp": "Select up", "selectUp": "Select up",
"selectColumnDown": "Select column down", "selectColumnDown": "Select column down",
"selectColumnUp": "Select column up" "selectColumnUp": "Select column up",
"focusToolbar": "Focus toolbar",
"focusCancel": "Focus cancel"
} }
}, },
"errors": { "errors": {
@@ -576,7 +578,6 @@
"successToast": "Option {{title}} was successfully created." "successToast": "Option {{title}} was successfully created."
}, },
"deleteWarning": "You are about to delete the product option: {{title}}. This action cannot be undone." "deleteWarning": "You are about to delete the product option: {{title}}. This action cannot be undone."
}, },
"organization": { "organization": {
"header": "Organize", "header": "Organize",
-32
View File
@@ -4551,7 +4551,6 @@ __metadata:
autoprefixer: ^10.4.17 autoprefixer: ^10.4.17
cmdk: ^0.2.0 cmdk: ^0.2.0
date-fns: ^3.6.0 date-fns: ^3.6.0
focus-trap-react: ^10.2.3
framer-motion: ^11.0.3 framer-motion: ^11.0.3
i18next: 23.7.11 i18next: 23.7.11
i18next-browser-languagedetector: 7.2.0 i18next-browser-languagedetector: 7.2.0
@@ -4560,7 +4559,6 @@ __metadata:
match-sorter: ^6.3.4 match-sorter: ^6.3.4
postcss: ^8.4.33 postcss: ^8.4.33
prettier: ^3.1.1 prettier: ^3.1.1
prop-types: ^15.8.1
qs: ^6.12.0 qs: ^6.12.0
react: ^18.2.0 react: ^18.2.0
react-country-flag: ^3.1.0 react-country-flag: ^3.1.0
@@ -18451,29 +18449,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"focus-trap-react@npm:^10.2.3":
version: 10.2.3
resolution: "focus-trap-react@npm:10.2.3"
dependencies:
focus-trap: ^7.5.4
tabbable: ^6.2.0
peerDependencies:
prop-types: ^15.8.1
react: ">=16.3.0"
react-dom: ">=16.3.0"
checksum: 18527771cacc1083ecdf472276a4c46581a6289dc98b6caf1c31641091732933cbffdec78e4c86c2c1568ac4f82a83c367d6a4d7e0e84dc96b239d2d4c12c071
languageName: node
linkType: hard
"focus-trap@npm:^7.5.4":
version: 7.5.4
resolution: "focus-trap@npm:7.5.4"
dependencies:
tabbable: ^6.2.0
checksum: c09e12b957862b2608977ff90de782645f99c3555cc5d93977240c179befa8723b9b1183e93890b4ad9d364d52a1af36416e63a728522ecce656a447d9ddd945
languageName: node
linkType: hard
"follow-redirects@npm:^1.14.0, follow-redirects@npm:^1.14.4, follow-redirects@npm:^1.15.6": "follow-redirects@npm:^1.14.0, follow-redirects@npm:^1.14.4, follow-redirects@npm:^1.15.6":
version: 1.15.6 version: 1.15.6
resolution: "follow-redirects@npm:1.15.6" resolution: "follow-redirects@npm:1.15.6"
@@ -28925,13 +28900,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"tabbable@npm:^6.2.0":
version: 6.2.0
resolution: "tabbable@npm:6.2.0"
checksum: ced8b38f05f2de62cd46836d77c2646c42b8c9713f5bd265daf0e78ff5ac73d3ba48a7ca45f348bafeef29b23da7187c72250742d37627883ef89cbd7fa76898
languageName: node
linkType: hard
"table@npm:^6.0.9": "table@npm:^6.0.9":
version: 6.8.2 version: 6.8.2
resolution: "table@npm:6.8.2" resolution: "table@npm:6.8.2"