Add 80+ additional icons from FontAwesome (#6803)
* Add 80+ additional icons from FontAwesome * fix: color switch transition, add 6 more icons to fill out grid * Add strict validation for collection icon * fix: Avoid import from app in server
This commit is contained in:
@@ -5,13 +5,13 @@ import { Trans, useTranslation } from "react-i18next";
|
|||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { randomElement } from "@shared/random";
|
import { randomElement } from "@shared/random";
|
||||||
import { CollectionPermission } from "@shared/types";
|
import { CollectionPermission } from "@shared/types";
|
||||||
|
import { IconLibrary } from "@shared/utils/IconLibrary";
|
||||||
import { colorPalette } from "@shared/utils/collections";
|
import { colorPalette } from "@shared/utils/collections";
|
||||||
import { CollectionValidation } from "@shared/validations";
|
import { CollectionValidation } from "@shared/validations";
|
||||||
import Collection from "~/models/Collection";
|
import Collection from "~/models/Collection";
|
||||||
import Button from "~/components/Button";
|
import Button from "~/components/Button";
|
||||||
import Flex from "~/components/Flex";
|
import Flex from "~/components/Flex";
|
||||||
import IconPicker from "~/components/IconPicker";
|
import IconPicker from "~/components/IconPicker";
|
||||||
import { IconLibrary } from "~/components/Icons/IconLibrary";
|
|
||||||
import Input from "~/components/Input";
|
import Input from "~/components/Input";
|
||||||
import InputSelectPermission from "~/components/InputSelectPermission";
|
import InputSelectPermission from "~/components/InputSelectPermission";
|
||||||
import Switch from "~/components/Switch";
|
import Switch from "~/components/Switch";
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import * as React from "react";
|
|||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import styled, { useTheme } from "styled-components";
|
import styled, { useTheme } from "styled-components";
|
||||||
|
import Squircle from "@shared/components/Squircle";
|
||||||
import { s, ellipsis } from "@shared/styles";
|
import { s, ellipsis } from "@shared/styles";
|
||||||
import Document from "~/models/Document";
|
import Document from "~/models/Document";
|
||||||
import Pin from "~/models/Pin";
|
import Pin from "~/models/Pin";
|
||||||
@@ -17,7 +18,6 @@ import useStores from "~/hooks/useStores";
|
|||||||
import { hover } from "~/styles";
|
import { hover } from "~/styles";
|
||||||
import CollectionIcon from "./Icons/CollectionIcon";
|
import CollectionIcon from "./Icons/CollectionIcon";
|
||||||
import EmojiIcon from "./Icons/EmojiIcon";
|
import EmojiIcon from "./Icons/EmojiIcon";
|
||||||
import Squircle from "./Squircle";
|
|
||||||
import Text from "./Text";
|
import Text from "./Text";
|
||||||
import Tooltip from "./Tooltip";
|
import Tooltip from "./Tooltip";
|
||||||
|
|
||||||
|
|||||||
@@ -1,38 +1,3 @@
|
|||||||
import { CSSProperties } from "react";
|
import Flex from "@shared/components/Flex";
|
||||||
import styled from "styled-components";
|
|
||||||
|
|
||||||
type JustifyValues = CSSProperties["justifyContent"];
|
|
||||||
|
|
||||||
type AlignValues = CSSProperties["alignItems"];
|
|
||||||
|
|
||||||
const Flex = styled.div<{
|
|
||||||
auto?: boolean;
|
|
||||||
column?: boolean;
|
|
||||||
align?: AlignValues;
|
|
||||||
justify?: JustifyValues;
|
|
||||||
wrap?: boolean;
|
|
||||||
shrink?: boolean;
|
|
||||||
reverse?: boolean;
|
|
||||||
gap?: number;
|
|
||||||
}>`
|
|
||||||
display: flex;
|
|
||||||
flex: ${({ auto }) => (auto ? "1 1 auto" : "initial")};
|
|
||||||
flex-direction: ${({ column, reverse }) =>
|
|
||||||
reverse
|
|
||||||
? column
|
|
||||||
? "column-reverse"
|
|
||||||
: "row-reverse"
|
|
||||||
: column
|
|
||||||
? "column"
|
|
||||||
: "row"};
|
|
||||||
align-items: ${({ align }) => align};
|
|
||||||
justify-content: ${({ justify }) => justify};
|
|
||||||
flex-wrap: ${({ wrap }) => (wrap ? "wrap" : "initial")};
|
|
||||||
flex-shrink: ${({ shrink }) =>
|
|
||||||
shrink === true ? 1 : shrink === false ? 0 : "initial"};
|
|
||||||
gap: ${({ gap }) => (gap ? `${gap}px` : "initial")};
|
|
||||||
min-height: 0;
|
|
||||||
min-width: 0;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export default Flex;
|
export default Flex;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { useTranslation } from "react-i18next";
|
|||||||
import { PopoverDisclosure, usePopoverState } from "reakit";
|
import { PopoverDisclosure, usePopoverState } from "reakit";
|
||||||
import { MenuItem } from "reakit/Menu";
|
import { MenuItem } from "reakit/Menu";
|
||||||
import styled, { useTheme } from "styled-components";
|
import styled, { useTheme } from "styled-components";
|
||||||
|
import { IconLibrary } from "@shared/utils/IconLibrary";
|
||||||
import { colorPalette } from "@shared/utils/collections";
|
import { colorPalette } from "@shared/utils/collections";
|
||||||
import Flex from "~/components/Flex";
|
import Flex from "~/components/Flex";
|
||||||
import NudeButton from "~/components/NudeButton";
|
import NudeButton from "~/components/NudeButton";
|
||||||
@@ -10,7 +11,7 @@ import Text from "~/components/Text";
|
|||||||
import useOnClickOutside from "~/hooks/useOnClickOutside";
|
import useOnClickOutside from "~/hooks/useOnClickOutside";
|
||||||
import lazyWithRetry from "~/utils/lazyWithRetry";
|
import lazyWithRetry from "~/utils/lazyWithRetry";
|
||||||
import DelayedMount from "./DelayedMount";
|
import DelayedMount from "./DelayedMount";
|
||||||
import { IconLibrary } from "./Icons/IconLibrary";
|
import InputSearch from "./InputSearch";
|
||||||
import Popover from "./Popover";
|
import Popover from "./Popover";
|
||||||
|
|
||||||
const icons = IconLibrary.mapping;
|
const icons = IconLibrary.mapping;
|
||||||
@@ -38,11 +39,12 @@ function IconPicker({
|
|||||||
onChange,
|
onChange,
|
||||||
className,
|
className,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
|
const [query, setQuery] = React.useState("");
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const popover = usePopoverState({
|
const popover = usePopoverState({
|
||||||
gutter: 0,
|
gutter: 0,
|
||||||
placement: "bottom",
|
placement: "right",
|
||||||
modal: true,
|
modal: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -51,9 +53,15 @@ function IconPicker({
|
|||||||
onOpen?.();
|
onOpen?.();
|
||||||
} else {
|
} else {
|
||||||
onClose?.();
|
onClose?.();
|
||||||
|
setQuery("");
|
||||||
}
|
}
|
||||||
}, [onOpen, onClose, popover.visible]);
|
}, [onOpen, onClose, popover.visible]);
|
||||||
|
|
||||||
|
const filteredIcons = IconLibrary.findIcons(query);
|
||||||
|
const handleFilter = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
setQuery(event.target.value.toLowerCase());
|
||||||
|
};
|
||||||
|
|
||||||
const styles = React.useMemo(
|
const styles = React.useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
default: {
|
default: {
|
||||||
@@ -92,6 +100,9 @@ function IconPicker({
|
|||||||
{ capture: true }
|
{ capture: true }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const iconNames = Object.keys(icons);
|
||||||
|
const delayPerIcon = 250 / iconNames.length;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PopoverDisclosure {...popover}>
|
<PopoverDisclosure {...popover}>
|
||||||
@@ -112,69 +123,77 @@ function IconPicker({
|
|||||||
</PopoverDisclosure>
|
</PopoverDisclosure>
|
||||||
<Popover
|
<Popover
|
||||||
{...popover}
|
{...popover}
|
||||||
width={388}
|
width={552}
|
||||||
aria-label={t("Choose icon")}
|
aria-label={t("Choose an icon")}
|
||||||
hideOnClickOutside={false}
|
hideOnClickOutside={false}
|
||||||
>
|
>
|
||||||
<Icons>
|
<Flex column gap={12}>
|
||||||
{Object.keys(icons).map((name, index) => (
|
<Text size="large" weight="xbold">
|
||||||
<MenuItem key={name} onClick={() => onChange(color, name)}>
|
{t("Choose an icon")}
|
||||||
{(props) => (
|
</Text>
|
||||||
<IconButton
|
<InputSearch
|
||||||
style={
|
value={query}
|
||||||
{
|
placeholder={`${t("Filter")}…`}
|
||||||
"--delay": `${index * 8}ms`,
|
onChange={handleFilter}
|
||||||
} as React.CSSProperties
|
autoFocus
|
||||||
}
|
/>
|
||||||
{...props}
|
<div>
|
||||||
>
|
{iconNames.map((name, index) => (
|
||||||
<Icon
|
<MenuItem key={name} onClick={() => onChange(color, name)}>
|
||||||
as={IconLibrary.getComponent(name)}
|
{(props) => (
|
||||||
color={color}
|
<IconButton
|
||||||
size={30}
|
style={
|
||||||
|
{
|
||||||
|
opacity: query
|
||||||
|
? filteredIcons.includes(name)
|
||||||
|
? 1
|
||||||
|
: 0.3
|
||||||
|
: undefined,
|
||||||
|
"--delay": `${Math.round(index * delayPerIcon)}ms`,
|
||||||
|
} as React.CSSProperties
|
||||||
|
}
|
||||||
|
{...props}
|
||||||
>
|
>
|
||||||
{initial}
|
<Icon
|
||||||
</Icon>
|
as={IconLibrary.getComponent(name)}
|
||||||
</IconButton>
|
color={color}
|
||||||
)}
|
size={30}
|
||||||
</MenuItem>
|
>
|
||||||
))}
|
{initial}
|
||||||
</Icons>
|
</Icon>
|
||||||
<Colors>
|
</IconButton>
|
||||||
<React.Suspense
|
)}
|
||||||
fallback={
|
</MenuItem>
|
||||||
<DelayedMount>
|
))}
|
||||||
<Text>{t("Loading")}…</Text>
|
</div>
|
||||||
</DelayedMount>
|
<Flex>
|
||||||
}
|
<React.Suspense
|
||||||
>
|
fallback={
|
||||||
<ColorPicker
|
<DelayedMount>
|
||||||
color={color}
|
<Text>{t("Loading")}…</Text>
|
||||||
onChange={(color) => onChange(color.hex, icon)}
|
</DelayedMount>
|
||||||
colors={colorPalette}
|
}
|
||||||
triangle="hide"
|
>
|
||||||
styles={styles}
|
<ColorPicker
|
||||||
/>
|
color={color}
|
||||||
</React.Suspense>
|
onChange={(color) => onChange(color.hex, icon)}
|
||||||
</Colors>
|
colors={colorPalette}
|
||||||
|
triangle="hide"
|
||||||
|
styles={styles}
|
||||||
|
/>
|
||||||
|
</React.Suspense>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
</Popover>
|
</Popover>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Icon = styled.svg`
|
const Icon = styled.svg`
|
||||||
transition: fill 150ms ease-in-out;
|
transition: color 150ms ease-in-out, fill 150ms ease-in-out;
|
||||||
transition-delay: var(--delay);
|
transition-delay: var(--delay);
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Colors = styled(Flex)`
|
|
||||||
padding: 8px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const Icons = styled.div`
|
|
||||||
padding: 8px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const IconButton = styled(NudeButton)`
|
const IconButton = styled(NudeButton)`
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ import { observer } from "mobx-react";
|
|||||||
import { CollectionIcon } from "outline-icons";
|
import { CollectionIcon } from "outline-icons";
|
||||||
import { getLuminance } from "polished";
|
import { getLuminance } from "polished";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
|
import { IconLibrary } from "@shared/utils/IconLibrary";
|
||||||
import Collection from "~/models/Collection";
|
import Collection from "~/models/Collection";
|
||||||
import useStores from "~/hooks/useStores";
|
import useStores from "~/hooks/useStores";
|
||||||
import Logger from "~/utils/Logger";
|
import Logger from "~/utils/Logger";
|
||||||
import { IconLibrary } from "./IconLibrary";
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
/** The collection to show an icon for */
|
/** The collection to show an icon for */
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { MoreIcon, QuestionMarkIcon, UserIcon } from "outline-icons";
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { useTheme } from "styled-components";
|
import { useTheme } from "styled-components";
|
||||||
|
import Squircle from "@shared/components/Squircle";
|
||||||
import { CollectionPermission } from "@shared/types";
|
import { CollectionPermission } from "@shared/types";
|
||||||
import type Collection from "~/models/Collection";
|
import type Collection from "~/models/Collection";
|
||||||
import type Document from "~/models/Document";
|
import type Document from "~/models/Document";
|
||||||
@@ -14,7 +15,6 @@ import useStores from "~/hooks/useStores";
|
|||||||
import Avatar from "../Avatar";
|
import Avatar from "../Avatar";
|
||||||
import { AvatarSize } from "../Avatar/Avatar";
|
import { AvatarSize } from "../Avatar/Avatar";
|
||||||
import CollectionIcon from "../Icons/CollectionIcon";
|
import CollectionIcon from "../Icons/CollectionIcon";
|
||||||
import Squircle from "../Squircle";
|
|
||||||
import Tooltip from "../Tooltip";
|
import Tooltip from "../Tooltip";
|
||||||
import { StyledListItem } from "./MemberListItem";
|
import { StyledListItem } from "./MemberListItem";
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { Trans, useTranslation } from "react-i18next";
|
|||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import styled, { useTheme } from "styled-components";
|
import styled, { useTheme } from "styled-components";
|
||||||
|
import Squircle from "@shared/components/Squircle";
|
||||||
import { s } from "@shared/styles";
|
import { s } from "@shared/styles";
|
||||||
import { UrlHelper } from "@shared/utils/UrlHelper";
|
import { UrlHelper } from "@shared/utils/UrlHelper";
|
||||||
import Document from "~/models/Document";
|
import Document from "~/models/Document";
|
||||||
@@ -21,7 +22,6 @@ import { AvatarSize } from "../Avatar/Avatar";
|
|||||||
import CopyToClipboard from "../CopyToClipboard";
|
import CopyToClipboard from "../CopyToClipboard";
|
||||||
import NudeButton from "../NudeButton";
|
import NudeButton from "../NudeButton";
|
||||||
import { ResizingHeightContainer } from "../ResizingHeightContainer";
|
import { ResizingHeightContainer } from "../ResizingHeightContainer";
|
||||||
import Squircle from "../Squircle";
|
|
||||||
import Text from "../Text";
|
import Text from "../Text";
|
||||||
import Tooltip from "../Tooltip";
|
import Tooltip from "../Tooltip";
|
||||||
import { StyledListItem } from "./MemberListItem";
|
import { StyledListItem } from "./MemberListItem";
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ type Props = {
|
|||||||
/** Whether the text should be selectable (defaults to false) */
|
/** Whether the text should be selectable (defaults to false) */
|
||||||
selectable?: boolean;
|
selectable?: boolean;
|
||||||
/** The font weight of the text */
|
/** The font weight of the text */
|
||||||
weight?: "bold" | "normal";
|
weight?: "xbold" | "bold" | "normal";
|
||||||
/** Whether the text should be truncated with an ellipsis */
|
/** Whether the text should be truncated with an ellipsis */
|
||||||
ellipsis?: boolean;
|
ellipsis?: boolean;
|
||||||
};
|
};
|
||||||
@@ -47,7 +47,9 @@ const Text = styled.span<Props>`
|
|||||||
${(props) =>
|
${(props) =>
|
||||||
props.weight &&
|
props.weight &&
|
||||||
css`
|
css`
|
||||||
font-weight: ${props.weight === "bold"
|
font-weight: ${props.weight === "xbold"
|
||||||
|
? 600
|
||||||
|
: props.weight === "bold"
|
||||||
? 500
|
? 500
|
||||||
: props.weight === "normal"
|
: props.weight === "normal"
|
||||||
? 400
|
? 400
|
||||||
|
|||||||
@@ -61,6 +61,9 @@
|
|||||||
"@dnd-kit/sortable": "^7.0.2",
|
"@dnd-kit/sortable": "^7.0.2",
|
||||||
"@emoji-mart/data": "^1.0.6",
|
"@emoji-mart/data": "^1.0.6",
|
||||||
"@emoji-mart/react": "^1.1.1",
|
"@emoji-mart/react": "^1.1.1",
|
||||||
|
"@fortawesome/fontawesome-svg-core": "^6.5.2",
|
||||||
|
"@fortawesome/free-solid-svg-icons": "^6.5.2",
|
||||||
|
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||||
"@getoutline/y-prosemirror": "^1.0.18",
|
"@getoutline/y-prosemirror": "^1.0.18",
|
||||||
"@hocuspocus/extension-throttle": "1.1.2",
|
"@hocuspocus/extension-throttle": "1.1.2",
|
||||||
"@hocuspocus/provider": "1.1.2",
|
"@hocuspocus/provider": "1.1.2",
|
||||||
|
|||||||
@@ -174,6 +174,7 @@ describe("#collections.move", () => {
|
|||||||
token: admin.getJwtToken(),
|
token: admin.getJwtToken(),
|
||||||
id: collection.id,
|
id: collection.id,
|
||||||
index: "P",
|
index: "P",
|
||||||
|
icon: "flame",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const body = await res.json();
|
const body = await res.json();
|
||||||
@@ -181,6 +182,20 @@ describe("#collections.move", () => {
|
|||||||
expect(body.success).toBe(true);
|
expect(body.success).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should return error when icon is not valid", async () => {
|
||||||
|
const team = await buildTeam();
|
||||||
|
const admin = await buildAdmin({ teamId: team.id });
|
||||||
|
const collection = await buildCollection({ teamId: team.id });
|
||||||
|
const res = await server.post("/api/collections.move", {
|
||||||
|
body: {
|
||||||
|
token: admin.getJwtToken(),
|
||||||
|
id: collection.id,
|
||||||
|
icon: "nonsRence",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(res.status).toEqual(400);
|
||||||
|
});
|
||||||
|
|
||||||
it("should return error when index is not valid", async () => {
|
it("should return error when index is not valid", async () => {
|
||||||
const team = await buildTeam();
|
const team = await buildTeam();
|
||||||
const admin = await buildAdmin({ teamId: team.id });
|
const admin = await buildAdmin({ teamId: team.id });
|
||||||
|
|||||||
@@ -2,11 +2,20 @@ import isUndefined from "lodash/isUndefined";
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { randomElement } from "@shared/random";
|
import { randomElement } from "@shared/random";
|
||||||
import { CollectionPermission, FileOperationFormat } from "@shared/types";
|
import { CollectionPermission, FileOperationFormat } from "@shared/types";
|
||||||
|
import { IconLibrary } from "@shared/utils/IconLibrary";
|
||||||
import { colorPalette } from "@shared/utils/collections";
|
import { colorPalette } from "@shared/utils/collections";
|
||||||
import { Collection } from "@server/models";
|
import { Collection } from "@server/models";
|
||||||
import { ValidateColor, ValidateIcon, ValidateIndex } from "@server/validation";
|
import { ValidateColor, ValidateIndex } from "@server/validation";
|
||||||
import { BaseSchema } from "../schema";
|
import { BaseSchema } from "../schema";
|
||||||
|
|
||||||
|
function zodEnumFromObjectKeys<
|
||||||
|
TI extends Record<string, any>,
|
||||||
|
R extends string = TI extends Record<infer R, any> ? R : never
|
||||||
|
>(input: TI): z.ZodEnum<[R, ...R[]]> {
|
||||||
|
const [firstKey, ...otherKeys] = Object.keys(input) as [R, ...R[]];
|
||||||
|
return z.enum([firstKey, ...otherKeys]);
|
||||||
|
}
|
||||||
|
|
||||||
export const CollectionsCreateSchema = BaseSchema.extend({
|
export const CollectionsCreateSchema = BaseSchema.extend({
|
||||||
body: z.object({
|
body: z.object({
|
||||||
name: z.string(),
|
name: z.string(),
|
||||||
@@ -20,12 +29,7 @@ export const CollectionsCreateSchema = BaseSchema.extend({
|
|||||||
.nullish()
|
.nullish()
|
||||||
.transform((val) => (isUndefined(val) ? null : val)),
|
.transform((val) => (isUndefined(val) ? null : val)),
|
||||||
sharing: z.boolean().default(true),
|
sharing: z.boolean().default(true),
|
||||||
icon: z
|
icon: zodEnumFromObjectKeys(IconLibrary.mapping).optional(),
|
||||||
.string()
|
|
||||||
.max(ValidateIcon.maxLength, {
|
|
||||||
message: `Must be ${ValidateIcon.maxLength} or fewer characters long`,
|
|
||||||
})
|
|
||||||
.optional(),
|
|
||||||
sort: z
|
sort: z
|
||||||
.object({
|
.object({
|
||||||
field: z.union([z.literal("title"), z.literal("index")]),
|
field: z.union([z.literal("title"), z.literal("index")]),
|
||||||
@@ -171,12 +175,7 @@ export const CollectionsUpdateSchema = BaseSchema.extend({
|
|||||||
id: z.string().uuid(),
|
id: z.string().uuid(),
|
||||||
name: z.string().optional(),
|
name: z.string().optional(),
|
||||||
description: z.string().nullish(),
|
description: z.string().nullish(),
|
||||||
icon: z
|
icon: zodEnumFromObjectKeys(IconLibrary.mapping).nullish(),
|
||||||
.string()
|
|
||||||
.max(ValidateIcon.maxLength, {
|
|
||||||
message: `Must be ${ValidateIcon.maxLength} or fewer characters long`,
|
|
||||||
})
|
|
||||||
.nullish(),
|
|
||||||
permission: z.nativeEnum(CollectionPermission).nullish(),
|
permission: z.nativeEnum(CollectionPermission).nullish(),
|
||||||
color: z
|
color: z
|
||||||
.string()
|
.string()
|
||||||
|
|||||||
@@ -246,7 +246,3 @@ export class ValidateColor {
|
|||||||
public static regex = /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i;
|
public static regex = /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i;
|
||||||
public static message = "Must be a hex value (please use format #FFFFFF)";
|
public static message = "Must be a hex value (please use format #FFFFFF)";
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ValidateIcon {
|
|
||||||
public static maxLength = 50;
|
|
||||||
}
|
|
||||||
|
|||||||
38
shared/components/Flex.tsx
Normal file
38
shared/components/Flex.tsx
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
import { CSSProperties } from "react";
|
||||||
|
import styled from "styled-components";
|
||||||
|
|
||||||
|
type JustifyValues = CSSProperties["justifyContent"];
|
||||||
|
|
||||||
|
type AlignValues = CSSProperties["alignItems"];
|
||||||
|
|
||||||
|
const Flex = styled.div<{
|
||||||
|
auto?: boolean;
|
||||||
|
column?: boolean;
|
||||||
|
align?: AlignValues;
|
||||||
|
justify?: JustifyValues;
|
||||||
|
wrap?: boolean;
|
||||||
|
shrink?: boolean;
|
||||||
|
reverse?: boolean;
|
||||||
|
gap?: number;
|
||||||
|
}>`
|
||||||
|
display: flex;
|
||||||
|
flex: ${({ auto }) => (auto ? "1 1 auto" : "initial")};
|
||||||
|
flex-direction: ${({ column, reverse }) =>
|
||||||
|
reverse
|
||||||
|
? column
|
||||||
|
? "column-reverse"
|
||||||
|
: "row-reverse"
|
||||||
|
: column
|
||||||
|
? "column"
|
||||||
|
: "row"};
|
||||||
|
align-items: ${({ align }) => align};
|
||||||
|
justify-content: ${({ justify }) => justify};
|
||||||
|
flex-wrap: ${({ wrap }) => (wrap ? "wrap" : "initial")};
|
||||||
|
flex-shrink: ${({ shrink }) =>
|
||||||
|
shrink === true ? 1 : shrink === false ? 0 : "initial"};
|
||||||
|
gap: ${({ gap }) => (gap ? `${gap}px` : "initial")};
|
||||||
|
min-height: 0;
|
||||||
|
min-width: 0;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default Flex;
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { s } from "@shared/styles";
|
import { s } from "../styles";
|
||||||
import Squircle from "../Squircle";
|
import Squircle from "./Squircle";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
/** The width and height of the icon, including standard padding. */
|
/** The width and height of the icon, including standard padding. */
|
||||||
@@ -238,7 +238,8 @@
|
|||||||
"{{authorName}} created <3></3>": "{{authorName}} created <3></3>",
|
"{{authorName}} created <3></3>": "{{authorName}} created <3></3>",
|
||||||
"{{authorName}} opened <3></3>": "{{authorName}} opened <3></3>",
|
"{{authorName}} opened <3></3>": "{{authorName}} opened <3></3>",
|
||||||
"Show menu": "Show menu",
|
"Show menu": "Show menu",
|
||||||
"Choose icon": "Choose icon",
|
"Choose an icon": "Choose an icon",
|
||||||
|
"Filter": "Filter",
|
||||||
"Loading": "Loading",
|
"Loading": "Loading",
|
||||||
"Select a color": "Select a color",
|
"Select a color": "Select a color",
|
||||||
"Search": "Search",
|
"Search": "Search",
|
||||||
@@ -864,7 +865,6 @@
|
|||||||
"Enterprise": "Enterprise",
|
"Enterprise": "Enterprise",
|
||||||
"Recent imports": "Recent imports",
|
"Recent imports": "Recent imports",
|
||||||
"Everyone that has signed into {{appName}} is listed here. It’s possible that there are other users who have access through {{signinMethods}} but haven’t signed in yet.": "Everyone that has signed into {{appName}} is listed here. It’s possible that there are other users who have access through {{signinMethods}} but haven’t signed in yet.",
|
"Everyone that has signed into {{appName}} is listed here. It’s possible that there are other users who have access through {{signinMethods}} but haven’t signed in yet.": "Everyone that has signed into {{appName}} is listed here. It’s possible that there are other users who have access through {{signinMethods}} but haven’t signed in yet.",
|
||||||
"Filter": "Filter",
|
|
||||||
"Receive a notification whenever a new document is published": "Receive a notification whenever a new document is published",
|
"Receive a notification whenever a new document is published": "Receive a notification whenever a new document is published",
|
||||||
"Document updated": "Document updated",
|
"Document updated": "Document updated",
|
||||||
"Receive a notification when a document you are subscribed to is edited": "Receive a notification when a document you are subscribed to is edited",
|
"Receive a notification when a document you are subscribed to is edited": "Receive a notification when a document you are subscribed to is edited",
|
||||||
|
|||||||
@@ -1,3 +1,92 @@
|
|||||||
|
import {
|
||||||
|
faHeart,
|
||||||
|
faWandSparkles,
|
||||||
|
faUmbrella,
|
||||||
|
faMugHot,
|
||||||
|
faBook,
|
||||||
|
faDroplet,
|
||||||
|
faBrush,
|
||||||
|
faSnowflake,
|
||||||
|
faShop,
|
||||||
|
faShirt,
|
||||||
|
faBagShopping,
|
||||||
|
faGauge,
|
||||||
|
faMountainSun,
|
||||||
|
faPassport,
|
||||||
|
faPhoneVolume,
|
||||||
|
faNewspaper,
|
||||||
|
faNetworkWired,
|
||||||
|
faRocket,
|
||||||
|
faStarOfLife,
|
||||||
|
faSeedling,
|
||||||
|
faTrain,
|
||||||
|
faMicrochip,
|
||||||
|
faRecordVinyl,
|
||||||
|
faTrophy,
|
||||||
|
faHammer,
|
||||||
|
faRobot,
|
||||||
|
faCrown,
|
||||||
|
faCube,
|
||||||
|
faRoad,
|
||||||
|
faPuzzlePiece,
|
||||||
|
faIndustry,
|
||||||
|
faWorm,
|
||||||
|
faVault,
|
||||||
|
faUtensils,
|
||||||
|
faUserGraduate,
|
||||||
|
faUniversalAccess,
|
||||||
|
faTractor,
|
||||||
|
faTent,
|
||||||
|
faSpa,
|
||||||
|
faSocks,
|
||||||
|
faScissors,
|
||||||
|
faSailboat,
|
||||||
|
faPizzaSlice,
|
||||||
|
faPaw,
|
||||||
|
faMap,
|
||||||
|
faLaptopCode,
|
||||||
|
faKitMedical,
|
||||||
|
faFaceSurprise,
|
||||||
|
faFaceSmileWink,
|
||||||
|
faFaceSmileBeam,
|
||||||
|
faFaceMeh,
|
||||||
|
faFaceLaugh,
|
||||||
|
faFaceGrinStars,
|
||||||
|
faFaceDizzy,
|
||||||
|
faDog,
|
||||||
|
faCrow,
|
||||||
|
faCompactDisc,
|
||||||
|
faClapperboard,
|
||||||
|
faFeather,
|
||||||
|
faFish,
|
||||||
|
faCat,
|
||||||
|
faTree,
|
||||||
|
faShield,
|
||||||
|
faLaptop,
|
||||||
|
faDisplay,
|
||||||
|
faPrescription,
|
||||||
|
faWheelchairMove,
|
||||||
|
faGift,
|
||||||
|
faMagnet,
|
||||||
|
faPaintRoller,
|
||||||
|
faGamepad,
|
||||||
|
faCookieBite,
|
||||||
|
faTowerCell,
|
||||||
|
faTooth,
|
||||||
|
faDollarSign,
|
||||||
|
faSterlingSign,
|
||||||
|
faYenSign,
|
||||||
|
faPesoSign,
|
||||||
|
faRainbow,
|
||||||
|
faPenRuler,
|
||||||
|
faSwatchbook,
|
||||||
|
faStarAndCrescent,
|
||||||
|
faSolarPanel,
|
||||||
|
faUmbrellaBeach,
|
||||||
|
faGem,
|
||||||
|
faDna,
|
||||||
|
} from "@fortawesome/free-solid-svg-icons";
|
||||||
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import intersection from "lodash/intersection";
|
import intersection from "lodash/intersection";
|
||||||
import {
|
import {
|
||||||
BookmarkedIcon,
|
BookmarkedIcon,
|
||||||
@@ -54,7 +143,21 @@ import {
|
|||||||
ThumbsUpIcon,
|
ThumbsUpIcon,
|
||||||
TruckIcon,
|
TruckIcon,
|
||||||
} from "outline-icons";
|
} from "outline-icons";
|
||||||
import LetterIcon from "./LetterIcon";
|
import * as React from "react";
|
||||||
|
import styled from "styled-components";
|
||||||
|
import LetterIcon from "../components/LetterIcon";
|
||||||
|
|
||||||
|
type IconMapping = {
|
||||||
|
component: React.ComponentType<FAProps>;
|
||||||
|
keywords?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type FAProps = {
|
||||||
|
color?: string;
|
||||||
|
size?: number;
|
||||||
|
className?: string;
|
||||||
|
style?: React.CSSProperties;
|
||||||
|
};
|
||||||
|
|
||||||
export class IconLibrary {
|
export class IconLibrary {
|
||||||
/**
|
/**
|
||||||
@@ -78,7 +181,7 @@ export class IconLibrary {
|
|||||||
|
|
||||||
for (const key of keys) {
|
for (const key of keys) {
|
||||||
const icon = this.mapping[key];
|
const icon = this.mapping[key];
|
||||||
const keywords = icon.keywords.split(" ");
|
const keywords = icon.keywords?.split(" ");
|
||||||
const namewords = keyword.toLocaleLowerCase().split(" ");
|
const namewords = keyword.toLocaleLowerCase().split(" ");
|
||||||
const matches = intersection(namewords, keywords);
|
const matches = intersection(namewords, keywords);
|
||||||
|
|
||||||
@@ -90,11 +193,32 @@ export class IconLibrary {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find icons.
|
||||||
|
*
|
||||||
|
* @param query The query to search for
|
||||||
|
* @returns The icon results.
|
||||||
|
*/
|
||||||
|
public static findIcons(query: string) {
|
||||||
|
return Object.keys(this.mapping)
|
||||||
|
.map((key) => {
|
||||||
|
const icon = this.mapping[key];
|
||||||
|
const keywords = `${icon.keywords ?? ""} ${key}`;
|
||||||
|
|
||||||
|
if (keywords.includes(query.toLocaleLowerCase())) {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
})
|
||||||
|
.filter(Boolean);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A map of all icons available to end users in the app. This does not include icons that are used
|
* A map of all icons available to end users in the app. This does not include icons that are used
|
||||||
* internally only, which can be imported from `outline-icons` directly.
|
* internally only, which can be imported from `outline-icons` directly.
|
||||||
*/
|
*/
|
||||||
public static mapping = {
|
public static mapping: Record<string, IconMapping> = {
|
||||||
|
// Internal icons
|
||||||
academicCap: {
|
academicCap: {
|
||||||
component: AcademicCapIcon,
|
component: AcademicCapIcon,
|
||||||
keywords: "learn teach lesson guide tutorial onboarding training",
|
keywords: "learn teach lesson guide tutorial onboarding training",
|
||||||
@@ -311,5 +435,123 @@ export class IconLibrary {
|
|||||||
component: WarningIcon,
|
component: WarningIcon,
|
||||||
keywords: "warning alert error",
|
keywords: "warning alert error",
|
||||||
},
|
},
|
||||||
};
|
|
||||||
|
// Font awesome
|
||||||
|
...Object.fromEntries(
|
||||||
|
[
|
||||||
|
faHeart,
|
||||||
|
faWandSparkles,
|
||||||
|
faUmbrella,
|
||||||
|
faMugHot,
|
||||||
|
faBook,
|
||||||
|
faDroplet,
|
||||||
|
faBrush,
|
||||||
|
faSnowflake,
|
||||||
|
faShop,
|
||||||
|
faShirt,
|
||||||
|
faBagShopping,
|
||||||
|
faGauge,
|
||||||
|
faMountainSun,
|
||||||
|
faPassport,
|
||||||
|
faPhoneVolume,
|
||||||
|
faNewspaper,
|
||||||
|
faNetworkWired,
|
||||||
|
faRocket,
|
||||||
|
faStarOfLife,
|
||||||
|
faSeedling,
|
||||||
|
faTrain,
|
||||||
|
faMicrochip,
|
||||||
|
faRecordVinyl,
|
||||||
|
faTrophy,
|
||||||
|
faHammer,
|
||||||
|
faRobot,
|
||||||
|
faCrown,
|
||||||
|
faCube,
|
||||||
|
faRoad,
|
||||||
|
faPuzzlePiece,
|
||||||
|
faIndustry,
|
||||||
|
faWorm,
|
||||||
|
faVault,
|
||||||
|
faUtensils,
|
||||||
|
faUserGraduate,
|
||||||
|
faUniversalAccess,
|
||||||
|
faTractor,
|
||||||
|
faTent,
|
||||||
|
faSpa,
|
||||||
|
faSocks,
|
||||||
|
faScissors,
|
||||||
|
faSailboat,
|
||||||
|
faPizzaSlice,
|
||||||
|
faPaw,
|
||||||
|
faMap,
|
||||||
|
faLaptopCode,
|
||||||
|
faKitMedical,
|
||||||
|
faFaceSurprise,
|
||||||
|
faFaceSmileWink,
|
||||||
|
faFaceSmileBeam,
|
||||||
|
faFaceMeh,
|
||||||
|
faFaceLaugh,
|
||||||
|
faFaceGrinStars,
|
||||||
|
faFaceDizzy,
|
||||||
|
faDog,
|
||||||
|
faCrow,
|
||||||
|
faCompactDisc,
|
||||||
|
faClapperboard,
|
||||||
|
faFeather,
|
||||||
|
faFish,
|
||||||
|
faCat,
|
||||||
|
faTree,
|
||||||
|
faShield,
|
||||||
|
faLaptop,
|
||||||
|
faDisplay,
|
||||||
|
faPrescription,
|
||||||
|
faWheelchairMove,
|
||||||
|
faGift,
|
||||||
|
faMagnet,
|
||||||
|
faPaintRoller,
|
||||||
|
faGamepad,
|
||||||
|
faCookieBite,
|
||||||
|
faTowerCell,
|
||||||
|
faTooth,
|
||||||
|
faDollarSign,
|
||||||
|
faSterlingSign,
|
||||||
|
faYenSign,
|
||||||
|
faPesoSign,
|
||||||
|
faRainbow,
|
||||||
|
faPenRuler,
|
||||||
|
faSwatchbook,
|
||||||
|
faStarAndCrescent,
|
||||||
|
faSolarPanel,
|
||||||
|
faUmbrellaBeach,
|
||||||
|
faGem,
|
||||||
|
faDna,
|
||||||
|
].map((icon) => [
|
||||||
|
icon.iconName,
|
||||||
|
{
|
||||||
|
component: ({ color, size = 24, className, style }: FAProps) => (
|
||||||
|
<FontAwesomeWrapper size={size}>
|
||||||
|
<FontAwesomeIcon
|
||||||
|
style={{
|
||||||
|
width: 0.6666666667 * size,
|
||||||
|
height: 0.6666666667 * size,
|
||||||
|
...style,
|
||||||
|
}}
|
||||||
|
color={color}
|
||||||
|
icon={icon}
|
||||||
|
className={className}
|
||||||
|
/>
|
||||||
|
</FontAwesomeWrapper>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
])
|
||||||
|
),
|
||||||
|
} as const;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const FontAwesomeWrapper = styled.span<{ size: number }>`
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: ${(props) => props.size}px;
|
||||||
|
height: ${(props) => props.size}px;
|
||||||
|
`;
|
||||||
63
yarn.lock
63
yarn.lock
@@ -110,22 +110,7 @@
|
|||||||
lru-cache "^5.1.1"
|
lru-cache "^5.1.1"
|
||||||
semver "^6.3.1"
|
semver "^6.3.1"
|
||||||
|
|
||||||
"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.20.5", "@babel/helper-create-class-features-plugin@^7.20.7", "@babel/helper-create-class-features-plugin@^7.22.15":
|
"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.20.5", "@babel/helper-create-class-features-plugin@^7.20.7", "@babel/helper-create-class-features-plugin@^7.22.15", "@babel/helper-create-class-features-plugin@^7.24.1":
|
||||||
version "7.22.15"
|
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.15.tgz#97a61b385e57fe458496fad19f8e63b63c867de4"
|
|
||||||
integrity "sha1-l6YbOF5X/kWElvrRn45jtjyGfeQ= sha512-jKkwA59IXcvSaiK2UN45kKwSC9o+KuoXsBDvHvU/7BecYIp8GQ2UwrVvFgJASUT+hBnwJx6MhvMCuMzwZZ7jlg=="
|
|
||||||
dependencies:
|
|
||||||
"@babel/helper-annotate-as-pure" "^7.22.5"
|
|
||||||
"@babel/helper-environment-visitor" "^7.22.5"
|
|
||||||
"@babel/helper-function-name" "^7.22.5"
|
|
||||||
"@babel/helper-member-expression-to-functions" "^7.22.15"
|
|
||||||
"@babel/helper-optimise-call-expression" "^7.22.5"
|
|
||||||
"@babel/helper-replace-supers" "^7.22.9"
|
|
||||||
"@babel/helper-skip-transparent-expression-wrappers" "^7.22.5"
|
|
||||||
"@babel/helper-split-export-declaration" "^7.22.6"
|
|
||||||
semver "^6.3.1"
|
|
||||||
|
|
||||||
"@babel/helper-create-class-features-plugin@^7.24.1":
|
|
||||||
version "7.24.1"
|
version "7.24.1"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.1.tgz#db58bf57137b623b916e24874ab7188d93d7f68f"
|
resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.1.tgz#db58bf57137b623b916e24874ab7188d93d7f68f"
|
||||||
integrity sha512-1yJa9dX9g//V6fDebXoEfEsxkZHk3Hcbm+zLhyu6qVgYFLvmTALTeV+jNU9e5RnYtioBrGEOdoI2joMSNQ/+aA==
|
integrity sha512-1yJa9dX9g//V6fDebXoEfEsxkZHk3Hcbm+zLhyu6qVgYFLvmTALTeV+jNU9e5RnYtioBrGEOdoI2joMSNQ/+aA==
|
||||||
@@ -248,16 +233,7 @@
|
|||||||
"@babel/helper-wrap-function" "^7.18.9"
|
"@babel/helper-wrap-function" "^7.18.9"
|
||||||
"@babel/types" "^7.18.9"
|
"@babel/types" "^7.18.9"
|
||||||
|
|
||||||
"@babel/helper-replace-supers@^7.18.6", "@babel/helper-replace-supers@^7.20.7", "@babel/helper-replace-supers@^7.22.20", "@babel/helper-replace-supers@^7.22.9":
|
"@babel/helper-replace-supers@^7.18.6", "@babel/helper-replace-supers@^7.20.7", "@babel/helper-replace-supers@^7.22.20", "@babel/helper-replace-supers@^7.22.9", "@babel/helper-replace-supers@^7.24.1":
|
||||||
version "7.22.20"
|
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz#e37d367123ca98fe455a9887734ed2e16eb7a793"
|
|
||||||
integrity "sha1-4302cSPKmP5FWpiHc07S4W63p5M= sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw=="
|
|
||||||
dependencies:
|
|
||||||
"@babel/helper-environment-visitor" "^7.22.20"
|
|
||||||
"@babel/helper-member-expression-to-functions" "^7.22.15"
|
|
||||||
"@babel/helper-optimise-call-expression" "^7.22.5"
|
|
||||||
|
|
||||||
"@babel/helper-replace-supers@^7.24.1":
|
|
||||||
version "7.24.1"
|
version "7.24.1"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.24.1.tgz#7085bd19d4a0b7ed8f405c1ed73ccb70f323abc1"
|
resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.24.1.tgz#7085bd19d4a0b7ed8f405c1ed73ccb70f323abc1"
|
||||||
integrity sha512-QCR1UqC9BzG5vZl8BMicmZ28RuUBnHhAMddD8yHFHDRH9lLTZ9uUPehX8ctVPT8l0TKblJidqcgUUKGVrePleQ==
|
integrity sha512-QCR1UqC9BzG5vZl8BMicmZ28RuUBnHhAMddD8yHFHDRH9lLTZ9uUPehX8ctVPT8l0TKblJidqcgUUKGVrePleQ==
|
||||||
@@ -624,20 +600,13 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@babel/helper-plugin-utils" "^7.14.5"
|
"@babel/helper-plugin-utils" "^7.14.5"
|
||||||
|
|
||||||
"@babel/plugin-syntax-typescript@^7.24.1":
|
"@babel/plugin-syntax-typescript@^7.24.1", "@babel/plugin-syntax-typescript@^7.7.2":
|
||||||
version "7.24.1"
|
version "7.24.1"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.1.tgz#b3bcc51f396d15f3591683f90239de143c076844"
|
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.1.tgz#b3bcc51f396d15f3591683f90239de143c076844"
|
||||||
integrity sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw==
|
integrity sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/helper-plugin-utils" "^7.24.0"
|
"@babel/helper-plugin-utils" "^7.24.0"
|
||||||
|
|
||||||
"@babel/plugin-syntax-typescript@^7.7.2":
|
|
||||||
version "7.23.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz#24f460c85dbbc983cd2b9c4994178bcc01df958f"
|
|
||||||
integrity "sha1-JPRgyF27yYPNK5xJlBeLzAHflY8= sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ=="
|
|
||||||
dependencies:
|
|
||||||
"@babel/helper-plugin-utils" "^7.22.5"
|
|
||||||
|
|
||||||
"@babel/plugin-transform-arrow-functions@^7.18.6":
|
"@babel/plugin-transform-arrow-functions@^7.18.6":
|
||||||
version "7.20.7"
|
version "7.20.7"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.20.7.tgz#bea332b0e8b2dab3dafe55a163d8227531ab0551"
|
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.20.7.tgz#bea332b0e8b2dab3dafe55a163d8227531ab0551"
|
||||||
@@ -1663,6 +1632,32 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
tslib "2.4.0"
|
tslib "2.4.0"
|
||||||
|
|
||||||
|
"@fortawesome/fontawesome-common-types@6.5.2":
|
||||||
|
version "6.5.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.5.2.tgz#eaf2f5699f73cef198454ebc0c414e3688898179"
|
||||||
|
integrity sha512-gBxPg3aVO6J0kpfHNILc+NMhXnqHumFxOmjYCFfOiLZfwhnnfhtsdA2hfJlDnj+8PjAs6kKQPenOTKj3Rf7zHw==
|
||||||
|
|
||||||
|
"@fortawesome/fontawesome-svg-core@^6.5.2":
|
||||||
|
version "6.5.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.5.2.tgz#4b42de71e196039b0d5ccf88559b8044e3296c21"
|
||||||
|
integrity sha512-5CdaCBGl8Rh9ohNdxeeTMxIj8oc3KNBgIeLMvJosBMdslK/UnEB8rzyDRrbKdL1kDweqBPo4GT9wvnakHWucZw==
|
||||||
|
dependencies:
|
||||||
|
"@fortawesome/fontawesome-common-types" "6.5.2"
|
||||||
|
|
||||||
|
"@fortawesome/free-solid-svg-icons@^6.5.2":
|
||||||
|
version "6.5.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.5.2.tgz#9b40b077b27400a5e9fcbf2d15b986c7be69e9ca"
|
||||||
|
integrity sha512-QWFZYXFE7O1Gr1dTIp+D6UcFUF0qElOnZptpi7PBUMylJh+vFmIedVe1Ir6RM1t2tEQLLSV1k7bR4o92M+uqlw==
|
||||||
|
dependencies:
|
||||||
|
"@fortawesome/fontawesome-common-types" "6.5.2"
|
||||||
|
|
||||||
|
"@fortawesome/react-fontawesome@^0.2.0":
|
||||||
|
version "0.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.0.tgz#d90dd8a9211830b4e3c08e94b63a0ba7291ddcf4"
|
||||||
|
integrity sha512-uHg75Rb/XORTtVt7OS9WoK8uM276Ufi7gCzshVWkUJbHhh3svsUUeqXerrM96Wm7fRiDzfKRwSoahhMIkGAYHw==
|
||||||
|
dependencies:
|
||||||
|
prop-types "^15.8.1"
|
||||||
|
|
||||||
"@getoutline/y-prosemirror@^1.0.18":
|
"@getoutline/y-prosemirror@^1.0.18":
|
||||||
version "1.0.18"
|
version "1.0.18"
|
||||||
resolved "https://registry.yarnpkg.com/@getoutline/y-prosemirror/-/y-prosemirror-1.0.18.tgz#17245c0362d30adb85131c86fb9a59358884b234"
|
resolved "https://registry.yarnpkg.com/@getoutline/y-prosemirror/-/y-prosemirror-1.0.18.tgz#17245c0362d30adb85131c86fb9a59358884b234"
|
||||||
|
|||||||
Reference in New Issue
Block a user