From 1a386c9900cb655585015b12c284e3fc8d6b18e6 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Thu, 14 Mar 2024 20:21:56 -0600 Subject: [PATCH] feat: Add table sorting controls (#6678) * wip * refactor * fix: Missing shadow styling --- app/editor/components/ToolbarMenu.tsx | 27 +++-- app/editor/menus/tableCol.tsx | 47 +++++++-- app/editor/menus/tableRow.tsx | 48 +++++---- app/hooks/useDictionary.ts | 14 +-- shared/editor/commands/table.ts | 113 ++++++++++++++++++++- shared/editor/components/Styles.ts | 7 +- shared/editor/nodes/Table.ts | 24 +---- shared/editor/types/index.ts | 1 + shared/i18n/locales/en_US/translation.json | 10 +- yarn.lock | 30 +++--- 10 files changed, 229 insertions(+), 92 deletions(-) diff --git a/app/editor/components/ToolbarMenu.tsx b/app/editor/components/ToolbarMenu.tsx index 670317994..6e8cf190d 100644 --- a/app/editor/components/ToolbarMenu.tsx +++ b/app/editor/components/ToolbarMenu.tsx @@ -1,4 +1,3 @@ -import { ExpandedIcon } from "outline-icons"; import * as React from "react"; import { useMenuState } from "reakit"; import { MenuButton } from "reakit/Menu"; @@ -27,13 +26,15 @@ function ToolbarDropdown(props: { item: MenuItem }) { const { state } = view; const items: TMenuItem[] = React.useMemo(() => { - const handleClick = (item: MenuItem) => () => { - if (!item.name) { + const handleClick = (menuItem: MenuItem) => () => { + if (!menuItem.name) { return; } - commands[item.name]( - typeof item.attrs === "function" ? item.attrs(state) : item.attrs + commands[menuItem.name]( + typeof menuItem.attrs === "function" + ? menuItem.attrs(state) + : menuItem.attrs ); }; @@ -42,7 +43,10 @@ function ToolbarDropdown(props: { item: MenuItem }) { type: "button", title: child.label, icon: child.icon, - selected: child.active ? child.active(state) : false, + dangerous: child.dangerous, + visible: child.visible, + selected: + child.active !== undefined ? child.active(state) : undefined, onClick: handleClick(child), })) : []; @@ -51,10 +55,10 @@ function ToolbarDropdown(props: { item: MenuItem }) { return ( <> - {(props) => ( - + {(buttonProps) => ( + {item.label && } - + {item.icon} )} @@ -121,11 +125,6 @@ const FlexibleWrapper = styled.div` gap: 6px; `; -const Arrow = styled(ExpandedIcon)` - margin-right: -4px; - color: ${s("textSecondary")}; -`; - const Label = styled.span` font-size: 15px; font-weight: 500; diff --git a/app/editor/menus/tableCol.tsx b/app/editor/menus/tableCol.tsx index dab5ed516..69f5083f7 100644 --- a/app/editor/menus/tableCol.tsx +++ b/app/editor/menus/tableCol.tsx @@ -5,9 +5,12 @@ import { AlignCenterIcon, InsertLeftIcon, InsertRightIcon, + ArrowIcon, + MoreIcon, } from "outline-icons"; import { EditorState } from "prosemirror-state"; import * as React from "react"; +import styled from "styled-components"; import isNodeActive from "@shared/editor/queries/isNodeActive"; import { MenuItem } from "@shared/editor/types"; import { Dictionary } from "~/hooks/useDictionary"; @@ -58,22 +61,48 @@ export default function tableColMenuItems( name: "separator", }, { - name: rtl ? "addColumnAfter" : "addColumnBefore", - tooltip: rtl ? dictionary.addColumnAfter : dictionary.addColumnBefore, - icon: , + name: "sortTable", + tooltip: dictionary.sortAsc, + attrs: { index, direction: "asc" }, + icon: , }, { - name: rtl ? "addColumnBefore" : "addColumnAfter", - tooltip: rtl ? dictionary.addColumnBefore : dictionary.addColumnAfter, - icon: , + name: "sortTable", + tooltip: dictionary.sortDesc, + attrs: { index, direction: "desc" }, + icon: , }, { name: "separator", }, { - name: "deleteColumn", - tooltip: dictionary.deleteColumn, - icon: , + icon: , + children: [ + { + name: rtl ? "addColumnAfter" : "addColumnBefore", + label: rtl ? dictionary.addColumnAfter : dictionary.addColumnBefore, + icon: , + }, + { + name: rtl ? "addColumnBefore" : "addColumnAfter", + label: rtl ? dictionary.addColumnBefore : dictionary.addColumnAfter, + icon: , + }, + { + name: "deleteColumn", + dangerous: true, + label: dictionary.deleteColumn, + icon: , + }, + ], }, ]; } + +const SortAscIcon = styled(ArrowIcon)` + transform: rotate(-90deg); +`; + +const SortDescIcon = styled(ArrowIcon)` + transform: rotate(90deg); +`; diff --git a/app/editor/menus/tableRow.tsx b/app/editor/menus/tableRow.tsx index 5615e715f..79e4a5bbf 100644 --- a/app/editor/menus/tableRow.tsx +++ b/app/editor/menus/tableRow.tsx @@ -1,4 +1,9 @@ -import { TrashIcon, InsertAboveIcon, InsertBelowIcon } from "outline-icons"; +import { + TrashIcon, + InsertAboveIcon, + InsertBelowIcon, + MoreIcon, +} from "outline-icons"; import { EditorState } from "prosemirror-state"; import * as React from "react"; import { MenuItem } from "@shared/editor/types"; @@ -11,25 +16,28 @@ export default function tableRowMenuItems( ): MenuItem[] { return [ { - name: "addRowAfter", - tooltip: dictionary.addRowBefore, - icon: , - attrs: { index: index - 1 }, - visible: index !== 0, - }, - { - name: "addRowAfter", - tooltip: dictionary.addRowAfter, - icon: , - attrs: { index }, - }, - { - name: "separator", - }, - { - name: "deleteRow", - tooltip: dictionary.deleteRow, - icon: , + icon: , + children: [ + { + name: "addRowAfter", + label: dictionary.addRowBefore, + icon: , + attrs: { index: index - 1 }, + visible: index !== 0, + }, + { + name: "addRowAfter", + label: dictionary.addRowAfter, + icon: , + attrs: { index }, + }, + { + name: "deleteRow", + label: dictionary.deleteRow, + dangerous: true, + icon: , + }, + ], }, ]; } diff --git a/app/hooks/useDictionary.ts b/app/hooks/useDictionary.ts index 6a73e6750..cfbd81bcd 100644 --- a/app/hooks/useDictionary.ts +++ b/app/hooks/useDictionary.ts @@ -6,10 +6,10 @@ export default function useDictionary() { return React.useMemo( () => ({ - addColumnAfter: t("Insert column after"), - addColumnBefore: t("Insert column before"), - addRowAfter: t("Insert row after"), - addRowBefore: t("Insert row before"), + addColumnAfter: t("Insert after"), + addColumnBefore: t("Insert before"), + addRowAfter: t("Insert after"), + addRowBefore: t("Insert before"), alignCenter: t("Align center"), alignLeft: t("Align left"), alignRight: t("Align right"), @@ -25,8 +25,8 @@ export default function useDictionary() { createLinkError: t("Sorry, an error occurred creating the link"), createNewDoc: t("Create a new doc"), createNewChildDoc: t("Create a new child doc"), - deleteColumn: t("Delete column"), - deleteRow: t("Delete row"), + deleteColumn: t("Delete"), + deleteRow: t("Delete"), deleteTable: t("Delete table"), deleteAttachment: t("Delete file"), download: t("Download"), @@ -72,6 +72,8 @@ export default function useDictionary() { strikethrough: t("Strikethrough"), strong: t("Bold"), subheading: t("Subheading"), + sortAsc: t("Sort ascending"), + sortDesc: t("Sort descending"), table: t("Table"), mathInline: t("Math inline (LaTeX)"), mathBlock: t("Math block (LaTeX)"), diff --git a/shared/editor/commands/table.ts b/shared/editor/commands/table.ts index dc1bfecd6..31de593a3 100644 --- a/shared/editor/commands/table.ts +++ b/shared/editor/commands/table.ts @@ -14,7 +14,27 @@ import { } from "prosemirror-tables"; import { getCellsInColumn } from "../queries/table"; -export function createTable( +export function createTable({ + rowsCount, + colsCount, +}: { + rowsCount: number; + colsCount: number; +}): Command { + return (state, dispatch) => { + if (dispatch) { + const offset = state.tr.selection.anchor + 1; + const nodes = createTableInner(state, rowsCount, colsCount); + const tr = state.tr.replaceSelectionWith(nodes).scrollIntoView(); + const resolvedPos = tr.doc.resolve(offset); + tr.setSelection(TextSelection.near(resolvedPos)); + dispatch(tr); + } + return true; + }; +} + +export function createTableInner( state: EditorState, rowsCount: number, colsCount: number, @@ -62,6 +82,97 @@ export function createTable( return types.table.createChecked(null, rows); } +export function sortTable({ + index, + direction, +}: { + index: number; + direction: "asc" | "desc"; +}): Command { + return (state, dispatch) => { + if (!isInTable(state)) { + return false; + } + if (dispatch) { + const rect = selectedRect(state); + const table: Node[][] = []; + + for (let r = 0; r < rect.map.height; r++) { + const cells = []; + for (let c = 0; c < rect.map.width; c++) { + const cell = state.doc.nodeAt( + rect.tableStart + rect.map.map[r * rect.map.width + c] + ); + if (cell) { + cells.push(cell); + } + } + table.push(cells); + } + + // check if all the cells in the column are a number + const compareAsText = table.some((row) => { + const cell = row[index]?.textContent; + return cell === "" ? false : isNaN(parseFloat(cell)); + }); + + // remove the header row + const header = table.shift(); + + // sort table data based on column at index + table.sort((a, b) => { + if (compareAsText) { + return (a[index]?.textContent ?? "").localeCompare( + b[index]?.textContent ?? "" + ); + } else { + return ( + parseFloat(a[index]?.textContent ?? "") - + parseFloat(b[index]?.textContent ?? "") + ); + } + }); + + if (direction === "desc") { + table.reverse(); + } + + // add the header row back + if (header) { + table.unshift(header); + } + + // create the new table + const rows = []; + for (let i = 0; i < table.length; i += 1) { + rows.push(state.schema.nodes.tr.createChecked(null, table[i])); + } + + // replace the original table with this sorted one + const nodes = state.schema.nodes.table.createChecked(null, rows); + const { tr } = state; + + tr.replaceRangeWith( + rect.tableStart - 1, + rect.tableStart - 1 + rect.table.nodeSize, + nodes + ); + + dispatch( + tr + // .setSelection( + // CellSelection.create( + // tr.doc, + // rect.map.positionAt(0, index, rect.table) + // ) + // ) + .scrollIntoView() + ); + } + return true; + }; +} + export function addRowAndMoveSelection({ index, }: { diff --git a/shared/editor/components/Styles.ts b/shared/editor/components/Styles.ts index e70b0f734..b52889458 100644 --- a/shared/editor/components/Styles.ts +++ b/shared/editor/components/Styles.ts @@ -1274,6 +1274,10 @@ table { border-bottom: 1px solid ${props.theme.tableDivider}; } + tr:first-of-type { + background: ${props.theme.secondaryBackground}; + } + th { background: transparent; } @@ -1436,7 +1440,8 @@ table { top: 0; bottom: 0; ${props.rtl ? "right" : "left"}: -1em; - width: 16px; + width: 32px; + z-index: 1; transition: box-shadow 250ms ease-in-out; border: 0px solid transparent; border-${props.rtl ? "right" : "left"}-width: 1em; diff --git a/shared/editor/nodes/Table.ts b/shared/editor/nodes/Table.ts index 226931a5b..07f840b79 100644 --- a/shared/editor/nodes/Table.ts +++ b/shared/editor/nodes/Table.ts @@ -1,6 +1,6 @@ import { chainCommands } from "prosemirror-commands"; import { NodeSpec, Node as ProsemirrorNode } from "prosemirror-model"; -import { Command, Plugin, TextSelection } from "prosemirror-state"; +import { Plugin } from "prosemirror-state"; import { addColumnAfter, addColumnBefore, @@ -18,6 +18,7 @@ import { addRowAndMoveSelection, setColumnAttr, createTable, + sortTable, } from "../commands/table"; import { MarkdownSerializerState } from "../lib/markdown/serializer"; import tablesRule from "../rules/tables"; @@ -55,26 +56,9 @@ export default class Table extends Node { commands() { return { - createTable: - ({ - rowsCount, - colsCount, - }: { - rowsCount: number; - colsCount: number; - }): Command => - (state, dispatch) => { - if (dispatch) { - const offset = state.tr.selection.anchor + 1; - const nodes = createTable(state, rowsCount, colsCount); - const tr = state.tr.replaceSelectionWith(nodes).scrollIntoView(); - const resolvedPos = tr.doc.resolve(offset); - tr.setSelection(TextSelection.near(resolvedPos)); - dispatch(tr); - } - return true; - }, + createTable, setColumnAttr, + sortTable, addColumnBefore: () => addColumnBefore, addColumnAfter: () => addColumnAfter, deleteColumn: () => deleteColumn, diff --git a/shared/editor/types/index.ts b/shared/editor/types/index.ts index c9628bed1..cbbab810d 100644 --- a/shared/editor/types/index.ts +++ b/shared/editor/types/index.ts @@ -21,6 +21,7 @@ export type MenuItem = { keywords?: string; tooltip?: string; label?: string; + dangerous?: boolean; children?: MenuItem[]; defaultHidden?: boolean; attrs?: diff --git a/shared/i18n/locales/en_US/translation.json b/shared/i18n/locales/en_US/translation.json index 425f88242..dbc8f9849 100644 --- a/shared/i18n/locales/en_US/translation.json +++ b/shared/i18n/locales/en_US/translation.json @@ -329,10 +329,8 @@ "Replace": "Replace", "Replace all": "Replace all", "Profile picture": "Profile picture", - "Insert column after": "Insert column after", - "Insert column before": "Insert column before", - "Insert row after": "Insert row after", - "Insert row before": "Insert row before", + "Insert after": "Insert after", + "Insert before": "Insert before", "Align center": "Align center", "Align left": "Align left", "Align right": "Align right", @@ -347,8 +345,6 @@ "Sorry, an error occurred creating the link": "Sorry, an error occurred creating the link", "Create a new doc": "Create a new doc", "Create a new child doc": "Create a new child doc", - "Delete column": "Delete column", - "Delete row": "Delete row", "Delete table": "Delete table", "Delete file": "Delete file", "Download file": "Download file", @@ -388,6 +384,8 @@ "Strikethrough": "Strikethrough", "Bold": "Bold", "Subheading": "Subheading", + "Sort ascending": "Sort ascending", + "Sort descending": "Sort descending", "Table": "Table", "Math inline (LaTeX)": "Math inline (LaTeX)", "Math block (LaTeX)": "Math block (LaTeX)", diff --git a/yarn.lock b/yarn.lock index 8488b0693..e639b0978 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4010,7 +4010,7 @@ array.prototype.tosorted@^1.1.3: es-errors "^1.1.0" es-shim-unscopables "^1.0.2" -arraybuffer.prototype.slice@^1.0.2, arraybuffer.prototype.slice@^1.0.3: +arraybuffer.prototype.slice@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz#097972f4255e41bc3425e37dc3f6421cf9aefde6" integrity sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A== @@ -4092,7 +4092,7 @@ autotrack@^2.4.1: rollup-plugin-node-resolve "^3.0.0" source-map "^0.5.6" -available-typed-arrays@^1.0.5, available-typed-arrays@^1.0.6, available-typed-arrays@^1.0.7: +available-typed-arrays@^1.0.6, available-typed-arrays@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846" integrity sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ== @@ -5720,7 +5720,7 @@ deepmerge@^4.2.2, deepmerge@^4.3.1: resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" integrity "sha1-RLXyFHzTsA1LVhN2hZZvJv0l3Uo= sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==" -define-data-property@^1.0.1, define-data-property@^1.1.1, define-data-property@^1.1.4: +define-data-property@^1.0.1, define-data-property@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== @@ -5729,7 +5729,7 @@ define-data-property@^1.0.1, define-data-property@^1.1.1, define-data-property@^ es-errors "^1.3.0" gopd "^1.0.1" -define-properties@^1.1.3, define-properties@^1.1.4, define-properties@^1.2.0, define-properties@^1.2.1: +define-properties@^1.1.3, define-properties@^1.2.0, define-properties@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" integrity "sha1-EHgcxhbrlRqAoDS6/Kpzd/avK2w= sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==" @@ -6246,7 +6246,7 @@ es-iterator-helpers@^1.0.17: iterator.prototype "^1.1.2" safe-array-concat "^1.1.0" -es-set-tostringtag@^2.0.1, es-set-tostringtag@^2.0.2, es-set-tostringtag@^2.0.3: +es-set-tostringtag@^2.0.2, es-set-tostringtag@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz#8bb60f0a440c2e4281962428438d58545af39777" integrity sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ== @@ -7196,7 +7196,7 @@ get-stream@^6.0.0, get-stream@^6.0.1: resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" integrity "sha1-omLY7vZ6ztV8KFKtYWdSakPL97c= sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==" -get-symbol-description@^1.0.0, get-symbol-description@^1.0.2: +get-symbol-description@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.2.tgz#533744d5aa20aca4e079c8e5daf7fd44202821f5" integrity sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg== @@ -8016,7 +8016,7 @@ is-negated-glob@^1.0.0: resolved "https://registry.yarnpkg.com/is-negated-glob/-/is-negated-glob-1.0.0.tgz#6910bca5da8c95e784b5751b976cf5a10fee36d2" integrity "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI= sha512-czXVVn/QEmgvej1f50BZ648vUI+em0xqMq2Sn+QncCLN4zj1UAxlT+kw/6ggQTOaZPd1HqKQGEqbpQVtJucWug==" -is-negative-zero@^2.0.2, is-negative-zero@^2.0.3: +is-negative-zero@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.3.tgz#ced903a027aca6381b777a5743069d7376a49747" integrity sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw== @@ -8127,7 +8127,7 @@ is-symbol@^1.0.2, is-symbol@^1.0.3: dependencies: has-symbols "^1.0.2" -is-typed-array@^1.1.10, is-typed-array@^1.1.12, is-typed-array@^1.1.13, is-typed-array@^1.1.3, is-typed-array@^1.1.9: +is-typed-array@^1.1.13, is-typed-array@^1.1.3: version "1.1.13" resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.13.tgz#d6c5ca56df62334959322d7d7dd1cca50debe229" integrity sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw== @@ -11726,7 +11726,7 @@ rxjs@^7.0.0: dependencies: tslib "^2.1.0" -safe-array-concat@^1.0.1, safe-array-concat@^1.1.0: +safe-array-concat@^1.1.0: version "1.1.2" resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.2.tgz#81d77ee0c4e8b863635227c721278dd524c20edb" integrity sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q== @@ -11746,7 +11746,7 @@ safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.2, safe-buffer@~5.2.0: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity "sha1-Hq+fqb2x/dTsdfWPnNtOa3gn7sY= sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" -safe-regex-test@^1.0.0, safe-regex-test@^1.0.3: +safe-regex-test@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.3.tgz#a5b4c0f06e0ab50ea2c395c14d8371232924c377" integrity sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw== @@ -11897,7 +11897,7 @@ serialize-javascript@^4.0.0: dependencies: randombytes "^2.1.0" -set-function-length@^1.1.1, set-function-length@^1.2.1: +set-function-length@^1.2.1: version "1.2.2" resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== @@ -12867,7 +12867,7 @@ type@^2.0.0, type@^2.7.2: resolved "https://registry.yarnpkg.com/type/-/type-2.7.2.tgz#2376a15a3a28b1efa0f5350dcf72d24df6ef98d0" integrity sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw== -typed-array-buffer@^1.0.0, typed-array-buffer@^1.0.2: +typed-array-buffer@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz#1867c5d83b20fcb5ccf32649e5e2fc7424474ff3" integrity sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ== @@ -12876,7 +12876,7 @@ typed-array-buffer@^1.0.0, typed-array-buffer@^1.0.2: es-errors "^1.3.0" is-typed-array "^1.1.13" -typed-array-byte-length@^1.0.0, typed-array-byte-length@^1.0.1: +typed-array-byte-length@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz#d92972d3cff99a3fa2e765a28fcdc0f1d89dec67" integrity sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw== @@ -12887,7 +12887,7 @@ typed-array-byte-length@^1.0.0, typed-array-byte-length@^1.0.1: has-proto "^1.0.3" is-typed-array "^1.1.13" -typed-array-byte-offset@^1.0.0, typed-array-byte-offset@^1.0.2: +typed-array-byte-offset@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz#f9ec1acb9259f395093e4567eb3c28a580d02063" integrity sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA== @@ -12899,7 +12899,7 @@ typed-array-byte-offset@^1.0.0, typed-array-byte-offset@^1.0.2: has-proto "^1.0.3" is-typed-array "^1.1.13" -typed-array-length@^1.0.4, typed-array-length@^1.0.5: +typed-array-length@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.5.tgz#57d44da160296d8663fd63180a1802ebf25905d5" integrity sha512-yMi0PlwuznKHxKmcpoOdeLwxBoVPkqZxd7q2FgMkmD3bNwvF5VW0+UlUQ1k1vmktTu4Yu13Q0RIxEP8+B+wloA==