diff --git a/apps/dashboard/app/(app)/apis/[apiId]/_components/create-key/create-key.constants.tsx b/apps/dashboard/app/(app)/apis/[apiId]/_components/create-key/create-key.constants.tsx index 3619517cea..96945fc7f9 100644 --- a/apps/dashboard/app/(app)/apis/[apiId]/_components/create-key/create-key.constants.tsx +++ b/apps/dashboard/app/(app)/apis/[apiId]/_components/create-key/create-key.constants.tsx @@ -1,5 +1,5 @@ -import type { StepNamesFrom } from "@/components/dialog-container/navigable-dialog"; import { CalendarClock, ChartPie, Code, Gauge, Key2 } from "@unkey/icons"; +import type { StepNamesFrom } from "@unkey/ui"; import type { SectionState } from "./types"; import { UsageSetup } from "./components/credits-setup"; diff --git a/apps/dashboard/app/(app)/apis/[apiId]/_components/create-key/index.tsx b/apps/dashboard/app/(app)/apis/[apiId]/_components/create-key/index.tsx index 6841199a5a..ff1d893416 100644 --- a/apps/dashboard/app/(app)/apis/[apiId]/_components/create-key/index.tsx +++ b/apps/dashboard/app/(app)/apis/[apiId]/_components/create-key/index.tsx @@ -1,12 +1,4 @@ "use client"; -import { - NavigableDialogBody, - NavigableDialogContent, - NavigableDialogFooter, - NavigableDialogHeader, - NavigableDialogNav, - NavigableDialogRoot, -} from "@/components/dialog-container/navigable-dialog"; import { NavbarActionButton } from "@/components/navigation/action-button"; import { CopyableIDButton } from "@/components/navigation/copyable-id-button"; import { Navbar } from "@/components/navigation/navbar"; @@ -14,7 +6,15 @@ import { usePersistedForm } from "@/hooks/use-persisted-form"; import { zodResolver } from "@hookform/resolvers/zod"; import { Plus } from "@unkey/icons"; import type { IconProps } from "@unkey/icons/src/props"; -import { Button } from "@unkey/ui"; +import { + Button, + NavigableDialogBody, + NavigableDialogContent, + NavigableDialogFooter, + NavigableDialogHeader, + NavigableDialogNav, + NavigableDialogRoot, +} from "@unkey/ui"; import { type FC, useEffect, useState } from "react"; import { FormProvider } from "react-hook-form"; import { toast } from "sonner"; diff --git a/apps/dashboard/app/(app)/apis/_components/create-api-button.tsx b/apps/dashboard/app/(app)/apis/_components/create-api-button.tsx index 4ccd0d05f7..56920e2101 100644 --- a/apps/dashboard/app/(app)/apis/_components/create-api-button.tsx +++ b/apps/dashboard/app/(app)/apis/_components/create-api-button.tsx @@ -16,7 +16,7 @@ import { z } from "zod"; const DynamicDialogContainer = dynamic( () => - import("@/components/dialog-container").then((mod) => ({ + import("@unkey/ui").then((mod) => ({ default: mod.DialogContainer, })), { ssr: false }, diff --git a/apps/engineering/content/design/components/dialog-container.mdx b/apps/engineering/content/design/components/dialog-container.mdx new file mode 100644 index 0000000000..eeb886bc1d --- /dev/null +++ b/apps/engineering/content/design/components/dialog-container.mdx @@ -0,0 +1,77 @@ +--- +title: DialogContainer +summary: The Dialog Container is a flexible modal component that provides a consistent way to display content in a modal dialog. It's built on top of Radix UI's Dialog primitive with additional styling and functionality. +--- +import { DialogContainerExample } from "./dialog/dialog-container.example" + +## Features + +- Accessible modal implementation +- Customizable overlay and content styling +- Close button with warning support +- Keyboard navigation support +- Customizable animations +- Responsive design + +## Structure + +The DialogContainer is composed of three main parts: + +1. **Header** - Contains the title and optional subtitle +2. **Content Area** - The main content section where children are rendered +3. **Footer** - Optional section for actions like buttons or additional information + +## Styling + +The component comes with default styling that includes: + +- Responsive width and height constraints +- Drop shadow and rounded corners +- Overlay with backdrop blur +- Dark mode support +- Customizable through `className` and `contentClassName` props + +## Usage + +```tsx + + Confirm + + } +> +
Your dialog content here
+
+``` + +### Basic Example + + + +## Props + +| Prop | Type | Default | Description | +|-------------------|-------------------------|-----------|--------------------------------------------------| +| isOpen | boolean | - | Controls the open state of the dialog | +| onOpenChange | (value: boolean) => void | - | Callback when the open state changes | +| title | string | - | The title of the dialog | +| subTitle | string | - | Optional subtitle for the dialog | +| footer | ReactNode | - | Optional footer content | +| className | string | - | Additional classes for the dialog container | +| contentClassName | string | - | Additional classes for the dialog content | +| preventAutoFocus | boolean | true | Whether to prevent auto-focus on open | +| children | ReactNode | - | The content to display in the dialog | + +## Accessibility + +The DialogContainer implements the following accessibility features: + +- Manages focus trap within the dialog +- Supports keyboard navigation (Esc to close) +- Proper ARIA attributes for screen readers +- Focus management can be controlled via `preventAutoFocus` diff --git a/apps/engineering/content/design/components/dialog/dialog-container.example.tsx b/apps/engineering/content/design/components/dialog/dialog-container.example.tsx new file mode 100644 index 0000000000..b13088f160 --- /dev/null +++ b/apps/engineering/content/design/components/dialog/dialog-container.example.tsx @@ -0,0 +1,63 @@ +"use client"; +import { RenderComponentWithSnippet } from "@/app/components/render"; +import { DialogContainer } from "@unkey/ui"; +import { Button, Input } from "@unkey/ui"; +import { useState } from "react"; + +export function DialogContainerExample() { + const [isOpen, setIsOpen] = useState(false); + const [inputValue, setInputValue] = useState(""); + const [inputResult, setInputResult] = useState(""); + + const handleSubmit = () => { + setInputResult(inputValue); + setIsOpen(false); + }; + + return ( + +
+
+ + + setIsOpen(!isOpen)} + subTitle="This is an example of a subTitle. Normally used to describe the dialog" + title="Example Dialog Title" + footer={ +
+ +
+ This is an example of a footer with a button for actions needed to be done +
+
+ } + > +
+

Dialog Content

+ setInputValue(e.target.value)} + /> +
+
+

+ Input Result: {inputResult} +

+
+
+
+ ); +} diff --git a/apps/engineering/content/design/components/dialog/navigable-dialog.example.tsx b/apps/engineering/content/design/components/dialog/navigable-dialog.example.tsx new file mode 100644 index 0000000000..8053322383 --- /dev/null +++ b/apps/engineering/content/design/components/dialog/navigable-dialog.example.tsx @@ -0,0 +1,101 @@ +"use client"; + +import { RenderComponentWithSnippet } from "@/app/components/render"; +import { Book2, Key } from "@unkey/icons"; +import type { IconProps } from "@unkey/icons/src/props"; +import { + Button, + NavigableDialogBody, + NavigableDialogContent, + NavigableDialogFooter, + NavigableDialogHeader, + NavigableDialogNav, + NavigableDialogRoot, +} from "@unkey/ui"; +import { memo, useState } from "react"; +import type { FC } from "react"; + +// Memoize static content to prevent unnecessary re-renders +const TabContent = memo(({ title, description }: { title: string; description: string }) => ( +
+

{title}

+

{description}

+
+)); +TabContent.displayName = "TabContent"; + +type TabId = "docs" | "security"; + +// Pre-define navigation items to prevent recreation on each render +const NAV_ITEMS: Array<{ + id: TabId; + label: string; + icon: FC; +}> = [ + { + id: "docs", + label: "Documentation", + icon: Book2, + }, + { + id: "security", + label: "Security", + icon: Key, + }, +]; + +// Pre-define content items using the memoized TabContent +const CONTENT_ITEMS: Array<{ + id: TabId; + content: JSX.Element; +}> = [ + { + id: "docs", + content: ( + + ), + }, + { + id: "security", + content: ( + + ), + }, +]; + +// Main example component +export const NavigableDialogExample = memo(() => { + const [isOpen, setIsOpen] = useState(false); + + return ( + +
+ + + + + + + + + + + + + + +
+
+ ); +}); + +NavigableDialogExample.displayName = "NavigableDialogExample"; diff --git a/apps/engineering/content/design/components/navigable-dialog.mdx b/apps/engineering/content/design/components/navigable-dialog.mdx new file mode 100644 index 0000000000..f2708004d9 --- /dev/null +++ b/apps/engineering/content/design/components/navigable-dialog.mdx @@ -0,0 +1,122 @@ +--- +title: NavigableDialog +summary: The Navigable Dialog is a multi-step modal component that provides a consistent way to display content with navigation between different sections. It's built on top of the Dialog Container with additional navigation capabilities. +--- +import { NavigableDialogExample } from "./dialog/navigable-dialog.example"; + +## Features + +- Multi-step navigation with sidebar +- Icon support for navigation items +- Accessible modal implementation +- State management between steps +- Customizable styling for each section +- Keyboard navigation support +- Responsive design + +## Structure + +The NavigableDialog is composed of several components that work together: + +1. **NavigableDialogRoot** - The container component that manages dialog state +2. **NavigableDialogHeader** - Contains the title and optional subtitle +3. **NavigableDialogBody** - Wrapper for navigation and content +4. **NavigableDialogNav** - Sidebar navigation with icons and labels +5. **NavigableDialogContent** - The main content area that displays the active section +6. **NavigableDialogFooter** - Optional section for actions like buttons + +## Styling + +The component includes default styling with: + +- Responsive layout with side navigation +- Smooth transitions between sections +- Icon support in navigation items +- Dark mode support +- Customizable through className props + +## Usage + +```tsx + + + + + + General settings content + }, + { + id: "security", + content:
Security settings content
+ }, + ]} + /> +
+ + + + +
+``` + +### Basic Example + + + +## Component Props + +### NavigableDialogRoot + +| Prop | Type | Default | Description | +|----------------|-------------------------|---------|------------------------------------------------| +| isOpen | boolean | - | Controls the open state of the dialog | +| onOpenChange | (value: boolean) => void | - | Callback when the open state changes | +| dialogClassName | string | - | Additional classes for the dialog container | +| preventAutoFocus | boolean | true | Whether to prevent auto-focus on open | +| children | ReactNode | - | The content to display in the dialog | + +### NavigableDialogNav + +| Prop | Type | Default | Description | +|---------|-------------------------------------------|---------|--------------------------------------| +| items | `{ id: string; label: ReactNode; icon?: FC }[]` | - | Navigation items configuration | +| className | string | - | Additional classes for the navigation | +| onNavigate | (fromId: string) => boolean \| `Promise`| - | Optional navigation validation | +| initialSelectedId | string | - | Initial active section ID | +| disabledIds | string[] | - | IDs of disabled navigation items | + +### NavigableDialogContent + +| Prop | Type | Default | Description | +|---------|----------------------------------------|---------|--------------------------------------| +| items | `{ id: string; content: ReactNode }[]` | - | Content items for each section | +| className | string | - | Additional classes for content area | + +### NavigableDialogHeader + +| Prop | Type | Default | Description | +|----------|--------|---------|--------------------------------| +| title | string | - | The title of the dialog | +| subTitle | string | - | Optional subtitle for the dialog| + +## Accessibility + +The NavigableDialog implements the following accessibility features: + +- Full keyboard navigation support +- ARIA labels for navigation items +- Focus management between sections +- Screen reader announcements for section changes +- All the accessibility features from the base Dialog component \ No newline at end of file diff --git a/internal/ui/package.json b/internal/ui/package.json index c7c947d061..4cffa88dc7 100644 --- a/internal/ui/package.json +++ b/internal/ui/package.json @@ -20,6 +20,7 @@ "@radix-ui/react-select": "^2.0.0", "@radix-ui/react-slot": "^1.1.0", "@radix-ui/react-tooltip": "^1.0.7", + "@radix-ui/react-dialog": "^1.0.5", "@unkey/icons": "workspace:^", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", diff --git a/internal/ui/src/components/dialog/dialog-container.tsx b/internal/ui/src/components/dialog/dialog-container.tsx new file mode 100644 index 0000000000..c70452c12b --- /dev/null +++ b/internal/ui/src/components/dialog/dialog-container.tsx @@ -0,0 +1,57 @@ +"use client"; +// biome-ignore lint: React in this context is used throughout, so biome will change to types because no APIs are used even though React is needed. +import * as React from "react"; +import type { PropsWithChildren, ReactNode } from "react"; +import { cn } from "../../lib/utils"; +import { Dialog, DialogContent } from "./parts/dialog"; +import { + DefaultDialogContentArea, + DefaultDialogFooter, + DefaultDialogHeader, +} from "./parts/dialog-parts"; + +type DialogContainerProps = PropsWithChildren<{ + className?: string; + isOpen: boolean; + onOpenChange: (value: boolean) => void; + title: string; + footer?: ReactNode; + contentClassName?: string; + preventAutoFocus?: boolean; + subTitle?: string; +}>; + +export const DialogContainer = ({ + className, + isOpen, + subTitle, + onOpenChange, + title, + children, + footer, + contentClassName, + preventAutoFocus = true, +}: DialogContainerProps) => { + return ( + + { + if (preventAutoFocus) { + e.preventDefault(); + } + }} + > + + {children} + {footer && {footer}} + + + ); +}; + +export { DefaultDialogHeader, DefaultDialogContentArea, DefaultDialogFooter }; diff --git a/apps/dashboard/components/dialog-container/navigable-dialog.tsx b/internal/ui/src/components/dialog/navigable-dialog.tsx similarity index 84% rename from apps/dashboard/components/dialog-container/navigable-dialog.tsx rename to internal/ui/src/components/dialog/navigable-dialog.tsx index a761549130..36548b9302 100644 --- a/apps/dashboard/components/dialog-container/navigable-dialog.tsx +++ b/internal/ui/src/components/dialog/navigable-dialog.tsx @@ -1,11 +1,17 @@ "use client"; -import { Dialog, DialogContent } from "@/components/ui/dialog"; import type { IconProps } from "@unkey/icons/src/props"; -import { Button } from "@unkey/ui"; -import { cn } from "@unkey/ui/src/lib/utils"; +// biome-ignore lint: React in this context is used throughout, so biome will change to types because no APIs are used even though React is needed. +import * as React from "react"; import { createContext, useCallback, useContext, useEffect, useState } from "react"; import type { FC, ReactNode } from "react"; -import { DefaultDialogContentArea, DefaultDialogFooter, DefaultDialogHeader } from "./dialog-parts"; +import { cn } from "../../lib/utils"; +import { Button } from "../button"; +import { Dialog, DialogContent } from "./parts/dialog"; +import { + DefaultDialogContentArea, + DefaultDialogFooter, + DefaultDialogHeader, +} from "./parts/dialog-parts"; type NavigableDialogContextType = { activeId: TStepName | undefined; @@ -25,19 +31,19 @@ const NavigableDialogContext: React.Context> = createNavigableDialogContext(); // Hook to use the NavigableDialog context -export function useNavigableDialog() { +const useNavigableDialog = () => { const context = useContext(NavigableDialogContext) as NavigableDialogContextType; if (context === undefined) { throw new Error("useNavigableDialog must be used within a NavigableDialogProvider"); } return context; -} +}; // Helper type to extract valid step names when using the component export type StepNamesFrom = T[number]["id"]; // Root component that provides context and structure -export function NavigableDialogRoot({ +const NavigableDialogRoot = ({ children, isOpen, onOpenChange, @@ -49,7 +55,7 @@ export function NavigableDialogRoot({ onOpenChange: (value: boolean) => void; dialogClassName?: string; preventAutoFocus?: boolean; -}) { +}) => { // Internal state - we'll initialize this when we get the first items from Nav const [activeId, setActiveId] = useState(); @@ -77,26 +83,26 @@ export function NavigableDialogRoot({ ); -} +}; // Header component -export function NavigableDialogHeader({ +const NavigableDialogHeader = ({ title, subTitle, }: { title: string; subTitle?: string; -}) { +}) => { return ; -} +}; // Footer component -export function NavigableDialogFooter({ children }: { children: ReactNode }) { +const NavigableDialogFooter = ({ children }: { children: ReactNode }) => { return {children}; -} +}; // Navigation sidebar component -export function NavigableDialogNav({ +const NavigableDialogNav = ({ items, className, onNavigate, @@ -114,13 +120,16 @@ export function NavigableDialogNav({ initialSelectedId?: TStepName; disabledIds?: TStepName[]; navWidthClass?: string; -}) { +}) => { const { activeId, setActiveId } = useNavigableDialog(); // Initialize activeId if it's not set and we have items useEffect(() => { - if (activeId === undefined && items.length > 0) { - setActiveId(initialSelectedId ?? items[0].id); + const allIds = items.map((i) => i.id); + if (!activeId || !allIds.includes(activeId)) { + setActiveId( + initialSelectedId && allIds.includes(initialSelectedId) ? initialSelectedId : allIds[0], + ); } }, [activeId, items, initialSelectedId, setActiveId]); @@ -198,9 +207,9 @@ export function NavigableDialogNav({ })} ); -} +}; -export function NavigableDialogContent({ +const NavigableDialogContent = ({ items, className, }: { @@ -209,7 +218,7 @@ export function NavigableDialogContent({ content: ReactNode; }[]; className?: string; -}) { +}) => { const { activeId } = useNavigableDialog(); return (
@@ -237,15 +246,25 @@ export function NavigableDialogContent({
); -} +}; // Main container for the nav and content -export function NavigableDialogBody({ +const NavigableDialogBody = ({ children, className, }: { children: ReactNode; className?: string; -}) { +}) => { return
{children}
; -} +}; + +export { + NavigableDialogRoot, + NavigableDialogHeader, + NavigableDialogFooter, + NavigableDialogNav, + NavigableDialogContent, + NavigableDialogBody, + useNavigableDialog, +}; diff --git a/internal/ui/src/components/dialog/parts/dialog-parts.tsx b/internal/ui/src/components/dialog/parts/dialog-parts.tsx new file mode 100644 index 0000000000..bf2f815863 --- /dev/null +++ b/internal/ui/src/components/dialog/parts/dialog-parts.tsx @@ -0,0 +1,58 @@ +"use client"; +// biome-ignore lint: React in this context is used throughout, so biome will change to types because no APIs are used even though React is needed. +import * as React from "react"; +import type { PropsWithChildren } from "react"; +import { cn } from "../../../lib/utils"; +import { + DialogFooter as ShadcnDialogFooter, + DialogHeader as ShadcnDialogHeader, + DialogTitle as ShadcnDialogTitle, +} from "./dialog"; + +type DefaultDialogHeaderProps = { + title: string; + subTitle?: string; + className?: string; +}; + +export const DefaultDialogHeader = ({ title, subTitle, className }: DefaultDialogHeaderProps) => { + return ( + + + {title} + {subTitle && ( // Conditionally render subtitle span only if it exists + {subTitle} + )} + + + ); +}; + +type DefaultDialogContentAreaProps = PropsWithChildren<{ + className?: string; +}>; + +export const DefaultDialogContentArea = ({ + children, + className, +}: DefaultDialogContentAreaProps) => { + return ( +
+ {children} +
+ ); +}; + +type DefaultDialogFooterProps = PropsWithChildren<{ + className?: string; +}>; + +export const DefaultDialogFooter = ({ children, className }: DefaultDialogFooterProps) => { + return ( + + {children} + + ); +}; diff --git a/internal/ui/src/components/dialog/parts/dialog.tsx b/internal/ui/src/components/dialog/parts/dialog.tsx new file mode 100644 index 0000000000..3e5c7ea415 --- /dev/null +++ b/internal/ui/src/components/dialog/parts/dialog.tsx @@ -0,0 +1,163 @@ +"use client"; + +import * as DialogPrimitive from "@radix-ui/react-dialog"; +import { X } from "lucide-react"; +import * as React from "react"; + +import { cn } from "../../../lib/utils"; + +const Dialog = DialogPrimitive.Root; + +const DialogTrigger = DialogPrimitive.Trigger; + +const DialogPortal = DialogPrimitive.Portal; + +const DialogClose = DialogPrimitive.Close; + +const DialogOverlay = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + showCloseWarning?: boolean; + onAttemptClose?: () => void; + } +>(({ className, showCloseWarning = false, onAttemptClose, ...props }, ref) => ( + +)); +DialogOverlay.displayName = DialogPrimitive.Overlay.displayName; + +const DialogContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + showCloseWarning?: boolean; + onAttemptClose?: () => void; + xButtonRef?: React.RefObject; + } +>( + ( + { className, children, showCloseWarning = false, onAttemptClose, xButtonRef, ...props }, + ref, + ) => { + const handleCloseAttempt = React.useCallback(() => { + // This handler is now only called when showCloseWarning is true + if (showCloseWarning) { + onAttemptClose?.(); + } + }, [showCloseWarning, onAttemptClose]); + + // Common class names for both button types + const buttonClassNames = + "absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent text-muted-foreground z-[51]"; + + return ( + + + { + if (showCloseWarning) { + e.preventDefault(); + handleCloseAttempt(); + } + }} + onPointerDownOutside={(e) => { + // Prevent closing only if warning is active and click is outside content + if (showCloseWarning) { + // Basic check: If the target is the overlay, it's handled there. + // More robust checks might be needed depending on content complexity. + const contentElement = (e.target as HTMLElement)?.closest('[role="dialog"]'); + if (!contentElement || contentElement !== e.currentTarget) { + e.preventDefault(); + handleCloseAttempt(); + } + } + }} + {...props} + > + {children} + + {/* Conditionally render the close button */} + {showCloseWarning ? ( + + ) : ( + // Use DialogPrimitive.Close for standard behavior + + + + )} + + + ); + }, +); +DialogContent.displayName = DialogPrimitive.Content.displayName; + +const DialogHeader = ({ className, ...props }: React.HTMLAttributes) => ( +
+); +DialogHeader.displayName = "DialogHeader"; + +const DialogFooter = ({ className, ...props }: React.HTMLAttributes) => ( +
+); +DialogFooter.displayName = "DialogFooter"; + +const DialogTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DialogTitle.displayName = DialogPrimitive.Title.displayName; + +const DialogDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DialogDescription.displayName = DialogPrimitive.Description.displayName; + +export { + Dialog, + DialogPortal, + DialogOverlay, + DialogClose, + DialogTrigger, + DialogContent, + DialogHeader, + DialogFooter, + DialogTitle, + DialogDescription, +}; diff --git a/internal/ui/src/index.ts b/internal/ui/src/index.ts index f51ac09fd4..67ba242880 100644 --- a/internal/ui/src/index.ts +++ b/internal/ui/src/index.ts @@ -1,6 +1,8 @@ export * from "./components/button"; export * from "./components/copy-button"; export * from "./components/date-time/date-time"; +export * from "./components/dialog/dialog-container"; +export * from "./components/dialog/navigable-dialog"; export * from "./components/empty"; export * from "./components/form"; export * from "./components/id"; diff --git a/packages/api/src/openapi.d.ts b/packages/api/src/openapi.d.ts index 583b11e443..4accd84f18 100644 --- a/packages/api/src/openapi.d.ts +++ b/packages/api/src/openapi.d.ts @@ -3659,9 +3659,14 @@ export interface operations { "application/json": { /** * @description The unique name of your permission. - * @example record.write + * @example Can write records */ name: string; + /** + * @description The unique slug of your permission. If not provided, the name is used. + * @example record.write + */ + slug?: string; /** * @description Explain what this permission does. This is just for your team, your users will not see this. * @example record.write can create new dns records for our domains. diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ab60b07ce1..ec46920310 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -611,7 +611,7 @@ importers: devDependencies: checkly: specifier: latest - version: 5.5.0(@types/node@20.14.9)(typescript@5.5.3) + version: 5.2.0(@types/node@20.14.9)(typescript@5.5.3) ts-node: specifier: 10.9.1 version: 10.9.1(@types/node@20.14.9)(typescript@5.5.3) @@ -901,6 +901,9 @@ importers: '@radix-ui/react-checkbox': specifier: ^1.0.4 version: 1.0.4(@types/react-dom@18.3.0)(@types/react@18.3.11)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-dialog': + specifier: ^1.0.5 + version: 1.0.5(@types/react-dom@18.3.0)(@types/react@18.3.11)(react-dom@18.3.1)(react@18.3.1) '@radix-ui/react-select': specifier: ^2.0.0 version: 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.11)(react-dom@18.3.1)(react@18.3.1) @@ -5535,6 +5538,30 @@ packages: fastq: 1.19.1 dev: true + /@oclif/core@4.2.8: + resolution: {integrity: sha512-OWv4Va6bERxIhrYcnUGzyhGRqktc64lJO6cZ3UwkzJDpfR8ZrbCxRfKRBBah1i8kzUlOAeAXnpbMBMah3skKwA==} + engines: {node: '>=18.0.0'} + dependencies: + ansi-escapes: 4.3.2 + ansis: 3.17.0 + clean-stack: 3.0.1 + cli-spinners: 2.9.2 + debug: 4.4.1(supports-color@8.1.1) + ejs: 3.1.10 + get-package-type: 0.1.0 + globby: 11.1.0 + indent-string: 4.0.0 + is-wsl: 2.2.0 + lilconfig: 3.1.3 + minimatch: 9.0.5 + semver: 7.7.2 + string-width: 4.2.3 + supports-color: 8.1.1 + widest-line: 3.1.0 + wordwrap: 1.0.0 + wrap-ansi: 7.0.0 + dev: true + /@oclif/core@4.3.0: resolution: {integrity: sha512-lIzHY+JMP6evrS5E/sGijNnwrCoNtGy8703jWXcMuPOYKiFhWoAqnIm1BGgoRgmxczkbSfRsHUL/lwsSgh74Lw==} engines: {node: '>=18.0.0'} @@ -5559,15 +5586,15 @@ packages: wrap-ansi: 7.0.0 dev: true - /@oclif/plugin-help@6.2.28: - resolution: {integrity: sha512-eFLP2yjiK+xMRGcv9k9jOWV08HB+/Cgg1ND91zS4Uwgp1krMoL39Is+hIqnZOKkmiEMtiv8k5EDqCVv+DTRywg==} + /@oclif/plugin-help@6.2.26: + resolution: {integrity: sha512-5KdldxEizbV3RsHOddN4oMxrX/HL6z79S94tbxEHVZ/dJKDWzfyCpgC9axNYqwmBF2pFZkozl/l7t3hCGOdalw==} engines: {node: '>=18.0.0'} dependencies: '@oclif/core': 4.3.0 dev: true - /@oclif/plugin-not-found@3.2.55(@types/node@20.14.9): - resolution: {integrity: sha512-+zgaRKoDsq431UyR/rOlJFDa6zdFkaNenQnLecrUWt9y9bwvw6Bs+mkQymAUJZCd9+JS4sZwqUilONXxU9g6DQ==} + /@oclif/plugin-not-found@3.2.44(@types/node@20.14.9): + resolution: {integrity: sha512-UF6GD/aDbElP6LJMZSSq72NvK0aQwtQ+fkjn0VLU9o1vNAA3M2K0tGL7lduZGQNw8LejOhr25eR4aXeRCgKb2A==} engines: {node: '>=18.0.0'} dependencies: '@inquirer/prompts': 7.5.3(@types/node@20.14.9) @@ -5578,8 +5605,8 @@ packages: - '@types/node' dev: true - /@oclif/plugin-plugins@5.4.38: - resolution: {integrity: sha512-tsohAIgtQRYb35G0W2QdubkNfc1Re+LtNujAomHBvz8wfWqPnwtnWGHob79/yxOV1j9R51AHZIuQ35gSdq39Ng==} + /@oclif/plugin-plugins@5.4.34: + resolution: {integrity: sha512-19sX+tHyR6M24GHbnedqqtk6w9QBgFZoa1y4zPmHf6VYaBeBmMBaq2dsLsdG0zv8LnWxaqguocICoxZTrV9f6A==} engines: {node: '>=18.0.0'} dependencies: '@oclif/core': 4.3.0 @@ -5597,8 +5624,8 @@ packages: - supports-color dev: true - /@oclif/plugin-warn-if-update-available@3.1.40: - resolution: {integrity: sha512-k5FBGxjXsSj56075MFVx5I9MAJa082evyPqLUBOjXL9w91q3k/89U+kTCfFNTQga8DykxhMP/7UTuDFV+d/Dhg==} + /@oclif/plugin-warn-if-update-available@3.1.35: + resolution: {integrity: sha512-gQfFW0UfT3msq/3O3idgBq4CA3cyXzFtrkoG7MK4FXVK0wxIdG0EVgJn4/o3jqjWO7t+93siCXyq56CGTGUZWQ==} engines: {node: '>=18.0.0'} dependencies: '@oclif/core': 4.3.0 @@ -9852,15 +9879,9 @@ packages: /@types/accepts@1.3.7: resolution: {integrity: sha512-Pay9fq2lM2wXPWbteBsRAGiWH2hig4ZE2asK+mm7kUzlxRTfL961rj89I6zV/E3PcIkDqyuBEcMxFT7rccugeQ==} dependencies: - '@types/node': 22.14.0 + '@types/node': 20.14.9 dev: false - /@types/archiver@6.0.3: - resolution: {integrity: sha512-a6wUll6k3zX6qs5KlxIggs1P1JcYJaTCx2gnlr+f0S1yd2DoaEwoIK10HmBaLnZwWneBz+JBm0dwcZu0zECBcQ==} - dependencies: - '@types/readdir-glob': 1.1.5 - dev: true - /@types/aria-query@5.0.4: resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} dev: true @@ -9869,13 +9890,13 @@ packages: resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} dependencies: '@types/connect': 3.4.38 - '@types/node': 22.14.0 + '@types/node': 20.14.9 dev: false /@types/connect@3.4.38: resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} dependencies: - '@types/node': 22.14.0 + '@types/node': 20.14.9 dev: false /@types/content-disposition@0.5.8: @@ -9885,7 +9906,7 @@ packages: /@types/conventional-commits-parser@5.0.1: resolution: {integrity: sha512-7uz5EHdzz2TqoMfV7ee61Egf5y6NkcO4FB/1iCCQnbeiI1F3xzv3vK5dBCXUCLQgGYS+mUeigK1iKQzvED+QnQ==} dependencies: - '@types/node': 22.14.0 + '@types/node': 20.14.9 dev: true optional: true @@ -9907,7 +9928,7 @@ packages: '@types/connect': 3.4.38 '@types/express': 4.17.22 '@types/keygrip': 1.0.6 - '@types/node': 22.14.0 + '@types/node': 20.14.9 dev: false /@types/cors@2.8.18: @@ -10016,7 +10037,7 @@ packages: /@types/express-serve-static-core@4.19.6: resolution: {integrity: sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==} dependencies: - '@types/node': 22.14.0 + '@types/node': 20.14.9 '@types/qs': 6.14.0 '@types/range-parser': 1.2.7 '@types/send': 0.17.4 @@ -10081,7 +10102,7 @@ packages: '@types/http-errors': 2.0.4 '@types/keygrip': 1.0.6 '@types/koa-compose': 3.2.8 - '@types/node': 22.14.0 + '@types/node': 20.14.9 dev: false /@types/mdast@4.0.4: @@ -10177,24 +10198,18 @@ packages: '@types/node': 20.14.9 dev: true - /@types/readdir-glob@1.1.5: - resolution: {integrity: sha512-raiuEPUYqXu+nvtY2Pe8s8FEmZ3x5yAH4VkLdihcPdalvsHltomrRC9BzuStrJ9yk06470hS0Crw0f1pXqD+Hg==} - dependencies: - '@types/node': 20.14.9 - dev: true - /@types/send@0.17.4: resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} dependencies: '@types/mime': 1.3.5 - '@types/node': 22.14.0 + '@types/node': 20.14.9 dev: false /@types/serve-static@1.15.7: resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==} dependencies: '@types/http-errors': 2.0.4 - '@types/node': 22.14.0 + '@types/node': 20.14.9 '@types/send': 0.17.4 dev: false @@ -10266,42 +10281,19 @@ packages: dev: true optional: true - /@typescript-eslint/project-service@8.33.0(typescript@5.5.3): - resolution: {integrity: sha512-d1hz0u9l6N+u/gcrk6s6gYdl7/+pp8yHheRTqP6X5hVDKALEaTn8WfGiit7G511yueBEL3OpOEpD+3/MBdoN+A==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - dependencies: - '@typescript-eslint/tsconfig-utils': 8.33.0(typescript@5.5.3) - '@typescript-eslint/types': 8.33.0 - debug: 4.4.1(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /@typescript-eslint/tsconfig-utils@8.33.0(typescript@5.5.3): - resolution: {integrity: sha512-sTkETlbqhEoiFmGr1gsdq5HyVbSOF0145SYDJ/EQmXHtKViCaGvnyLqWFFHtEXoS0J1yU8Wyou2UGmgW88fEug==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <5.9.0' - dependencies: - typescript: 5.5.3 - dev: true - - /@typescript-eslint/types@8.33.0: - resolution: {integrity: sha512-DKuXOKpM5IDT1FA2g9x9x1Ug81YuKrzf4mYX8FAVSNu5Wo/LELHWQyM1pQaDkI42bX15PWl0vNPt1uGiIFUOpg==} + /@typescript-eslint/types@8.24.1: + resolution: {integrity: sha512-9kqJ+2DkUXiuhoiYIUvIYjGcwle8pcPpdlfkemGvTObzgmYfJ5d0Qm6jwb4NBXP9W1I5tss0VIAnWFumz3mC5A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} dev: true - /@typescript-eslint/typescript-estree@8.33.0(typescript@5.5.3): - resolution: {integrity: sha512-vegY4FQoB6jL97Tu/lWRsAiUUp8qJTqzAmENH2k59SJhw0Th1oszb9Idq/FyyONLuNqT1OADJPXfyUNOR8SzAQ==} + /@typescript-eslint/typescript-estree@8.24.1(typescript@5.5.3): + resolution: {integrity: sha512-UPyy4MJ/0RE648DSKQe9g0VDSehPINiejjA6ElqnFaFIhI6ZEiZAkUI0D5MCk0bQcTf/LVqZStvQ6K4lPn/BRg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: '>=4.8.4 <5.9.0' + typescript: '>=4.8.4 <5.8.0' dependencies: - '@typescript-eslint/project-service': 8.33.0(typescript@5.5.3) - '@typescript-eslint/tsconfig-utils': 8.33.0(typescript@5.5.3) - '@typescript-eslint/types': 8.33.0 - '@typescript-eslint/visitor-keys': 8.33.0 + '@typescript-eslint/types': 8.24.1 + '@typescript-eslint/visitor-keys': 8.24.1 debug: 4.4.1(supports-color@8.1.1) fast-glob: 3.3.3 is-glob: 4.0.3 @@ -10313,11 +10305,11 @@ packages: - supports-color dev: true - /@typescript-eslint/visitor-keys@8.33.0: - resolution: {integrity: sha512-7RW7CMYoskiz5OOGAWjJFxgb7c5UNjTG292gYhWeOAcFmYCtVCSqjqSBj5zMhxbXo2JOW95YYrUWJfU0zrpaGQ==} + /@typescript-eslint/visitor-keys@8.24.1: + resolution: {integrity: sha512-EwVHlp5l+2vp8CoqJm9KikPZgi3gbdZAtabKT9KPShGeOcJhsv4Zdo3oc8T8I0uKEmYoU4ItyxbptjF08enaxg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} dependencies: - '@typescript-eslint/types': 8.33.0 + '@typescript-eslint/types': 8.24.1 eslint-visitor-keys: 4.2.0 dev: true @@ -11131,6 +11123,16 @@ packages: tslib: 2.8.1 dev: false + /assert@2.1.0: + resolution: {integrity: sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==} + dependencies: + call-bind: 1.0.8 + is-nan: 1.3.2 + object-is: 1.1.6 + object.assign: 4.1.7 + util: 0.12.5 + dev: true + /assertion-error@1.1.0: resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} dev: true @@ -11246,6 +11248,16 @@ packages: resolution: {integrity: sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==} engines: {node: '>= 6.0.0'} + /axios@1.7.4: + resolution: {integrity: sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==} + dependencies: + follow-redirects: 1.15.9 + form-data: 4.0.2 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + dev: true + /axios@1.9.0: resolution: {integrity: sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==} dependencies: @@ -11685,50 +11697,40 @@ packages: engines: {node: '>= 16'} dev: true - /checkly@5.5.0(@types/node@20.14.9)(typescript@5.5.3): - resolution: {integrity: sha512-5s7TyQsSo7qq55FVVPPMfQZQGm2C6ZkDbtg/YTMNOUPpU5ARTDQxUcmptis9SGldInerxR3kiMVeopnGCB4DwA==} + /checkly@5.2.0(@types/node@20.14.9)(typescript@5.5.3): + resolution: {integrity: sha512-y5VEdxuVfI66hEOMQlGKzcQsncCdewtG9ocKyA963MeOTW79v7a9dqHUJQLmBwLtUybaHVFXj7ha1RR57no9SA==} engines: {node: '>=18.0.0'} hasBin: true - peerDependencies: - jiti: '>=2' - peerDependenciesMeta: - jiti: - optional: true dependencies: - '@oclif/core': 4.3.0 - '@oclif/plugin-help': 6.2.28 - '@oclif/plugin-not-found': 3.2.55(@types/node@20.14.9) - '@oclif/plugin-plugins': 5.4.38 - '@oclif/plugin-warn-if-update-available': 3.1.40 - '@types/archiver': 6.0.3 - '@typescript-eslint/typescript-estree': 8.33.0(typescript@5.5.3) - acorn: 8.14.1 + '@oclif/core': 4.2.8 + '@oclif/plugin-help': 6.2.26 + '@oclif/plugin-not-found': 3.2.44(@types/node@20.14.9) + '@oclif/plugin-plugins': 5.4.34 + '@oclif/plugin-warn-if-update-available': 3.1.35 + '@typescript-eslint/typescript-estree': 8.24.1(typescript@5.5.3) + acorn: 8.14.0 acorn-walk: 8.3.4 - archiver: 7.0.1 - axios: 1.9.0 + axios: 1.7.4 chalk: 4.1.2 - ci-info: 4.2.0 + ci-info: 3.8.0 conf: 10.2.0 - dotenv: 16.5.0 - execa: 9.6.0 + dotenv: 16.3.1 git-repo-info: 2.1.1 - glob: 10.4.5 + glob: 10.3.1 indent-string: 4.0.0 json-stream-stringify: 3.1.6 json5: 2.2.3 jwt-decode: 3.1.2 log-symbols: 4.1.0 - luxon: 3.6.1 - minimatch: 9.0.5 - mqtt: 5.13.0 - open: 8.4.2 + luxon: 3.3.0 + mqtt: 5.10.1 + open: 8.4.0 p-queue: 6.6.2 prompts: 2.4.2 proxy-from-env: 1.1.0 - recast: 0.23.11 - semver: 7.7.2 + recast: 0.23.4 tunnel: 0.0.6 - uuid: 11.1.0 + uuid: 9.0.0 transitivePeerDependencies: - '@types/node' - bufferutil @@ -11804,13 +11806,13 @@ packages: zod: 3.23.8 dev: true - /ci-info@3.9.0: - resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} + /ci-info@3.8.0: + resolution: {integrity: sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==} engines: {node: '>=8'} dev: true - /ci-info@4.2.0: - resolution: {integrity: sha512-cYY9mypksY8NRqgDB1XD1RiJL338v/551niynFTGkZOO2LHuB2OmOYxDIe/ttN9AHwrqdum1360G3ald0W9kCg==} + /ci-info@3.9.0: + resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} engines: {node: '>=8'} dev: true @@ -12548,7 +12550,7 @@ packages: dependencies: is-arguments: 1.2.0 is-date-object: 1.1.0 - is-regex: 1.1.4 + is-regex: 1.2.1 object-is: 1.1.6 object-keys: 1.1.1 regexp.prototype.flags: 1.5.4 @@ -12833,6 +12835,11 @@ packages: engines: {node: '>=12'} dev: false + /dotenv@16.3.1: + resolution: {integrity: sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==} + engines: {node: '>=12'} + dev: true + /dotenv@16.5.0: resolution: {integrity: sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==} engines: {node: '>=12'} @@ -14545,7 +14552,7 @@ packages: '@radix-ui/react-navigation-menu': 1.2.13(@types/react-dom@18.3.0)(@types/react@18.3.11)(react-dom@18.3.1)(react@18.3.1) '@radix-ui/react-popover': 1.1.14(@types/react-dom@18.3.0)(@types/react@18.3.11)(react-dom@18.3.1)(react@18.3.1) '@radix-ui/react-scroll-area': 1.2.9(@types/react-dom@18.3.0)(@types/react@18.3.11)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-slot': 1.1.0(@types/react@18.3.11)(react@18.3.1) + '@radix-ui/react-slot': 1.2.3(@types/react@18.3.11)(react@18.3.1) '@radix-ui/react-tabs': 1.1.12(@types/react-dom@18.3.0)(@types/react@18.3.11)(react-dom@18.3.1)(react@18.3.1) class-variance-authority: 0.7.1 fumadocs-core: 14.5.4(@types/react@18.3.11)(next@14.2.15)(react-dom@18.3.1)(react@18.3.1) @@ -14739,6 +14746,18 @@ packages: /glob-to-regexp@0.4.1: resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} + /glob@10.3.1: + resolution: {integrity: sha512-9BKYcEeIs7QwlCYs+Y3GBvqAMISufUS0i2ELd11zpZjxI5V9iyRj0HgzB5/cLf2NY4vcYBTYzJ7GIui7j/4DOw==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + dependencies: + foreground-child: 3.3.1 + jackspeak: 2.3.6 + minimatch: 9.0.5 + minipass: 5.0.0 + path-scurry: 1.11.1 + dev: true + /glob@10.3.4: resolution: {integrity: sha512-6LFElP3A+i/Q8XQKEvZjkEWEOTgAIALR9AO2rwT8bgPhDd1anmqDJDZ6lLddI4ehxxxR1S5RIqKe1uapMQfYaQ==} engines: {node: '>=16 || 14 >=14.17'} @@ -15543,7 +15562,6 @@ packages: dependencies: call-bound: 1.0.4 has-tostringtag: 1.0.2 - dev: false /is-array-buffer@3.0.5: resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} @@ -15688,6 +15706,14 @@ packages: resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} engines: {node: '>= 0.4'} + /is-nan@1.3.2: + resolution: {integrity: sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + dev: true + /is-negative-zero@2.0.3: resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} engines: {node: '>= 0.4'} @@ -15899,7 +15925,6 @@ packages: '@isaacs/cliui': 8.0.2 optionalDependencies: '@pkgjs/parseargs': 0.11.0 - dev: false /jackspeak@3.4.3: resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} @@ -16460,8 +16485,8 @@ packages: react: 18.3.1 dev: false - /luxon@3.6.1: - resolution: {integrity: sha512-tJLxrKJhO2ukZ5z0gyjY1zPh3Rh88Ej9P7jNrZiHMUXHae1yvI2imgOZtL1TO8TW6biMMKfTtAOoEJANgtWBMQ==} + /luxon@3.3.0: + resolution: {integrity: sha512-An0UCfG/rSiqtAIiBPO0Y9/zAnHUZxAMiCpTd5h2smgsj7GGmcenvrvww2cqNA8/4A5ZrD1gJpHN2mIHZQF+Mg==} engines: {node: '>=12'} dev: true @@ -17296,11 +17321,13 @@ packages: - supports-color dev: true - /mqtt@5.13.0: - resolution: {integrity: sha512-pR+z+ChxFl3n8AKLQbTONVOOg/jl4KiKQRBAi78tjd6PksOWvl1nl9L8ZHOZ3MiavZfrUOjok2ddwc1VymGWRg==} + /mqtt@5.10.1: + resolution: {integrity: sha512-hXCOki8sANoQ7w+2OzJzg6qMBxTtrH9RlnVNV8panLZgnl+Gh0J/t4k6r8Az8+C7y3KAcyXtn0mmLixyUom8Sw==} engines: {node: '>=16.0.0'} hasBin: true dependencies: + '@types/readable-stream': 4.0.20 + '@types/ws': 8.18.1 commist: 3.2.0 concat-stream: 2.0.0 debug: 4.4.1(supports-color@8.1.1) @@ -17310,8 +17337,8 @@ packages: mqtt-packet: 9.0.2 number-allocator: 1.0.14 readable-stream: 4.7.0 + reinterval: 1.1.0 rfdc: 1.4.1 - socks: 2.8.4 split2: 4.2.0 worker-timers: 7.1.8 ws: 8.18.2 @@ -17849,7 +17876,6 @@ packages: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - dev: false /object-keys@1.1.1: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} @@ -17908,6 +17934,15 @@ packages: regex-recursion: 5.1.1 dev: false + /open@8.4.0: + resolution: {integrity: sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==} + engines: {node: '>=12'} + dependencies: + define-lazy-prop: 2.0.0 + is-docker: 2.2.1 + is-wsl: 2.2.0 + dev: true + /open@8.4.2: resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} engines: {node: '>=12'} @@ -19207,14 +19242,14 @@ packages: engines: {node: '>= 14.18.0'} dev: false - /recast@0.23.11: - resolution: {integrity: sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==} + /recast@0.23.4: + resolution: {integrity: sha512-qtEDqIZGVcSZCHniWwZWbRy79Dc6Wp3kT/UmDA2RJKBPg7+7k51aQBZirHmUGn5uvHf2rg8DkjizrN26k61ATw==} engines: {node: '>= 4'} dependencies: + assert: 2.1.0 ast-types: 0.16.1 esprima: 4.0.1 source-map: 0.6.1 - tiny-invariant: 1.3.3 tslib: 2.8.1 dev: true @@ -19381,6 +19416,10 @@ packages: transitivePeerDependencies: - supports-color + /reinterval@1.1.0: + resolution: {integrity: sha512-QIRet3SYrGp0HUHO88jVskiG6seqUGC5iAG7AwI/BV4ypGcuqk9Du6YQBUOUqm9c8pw1eyLoIaONifRua1lsEQ==} + dev: true + /remark-frontmatter@5.0.0: resolution: {integrity: sha512-XTFYvNASMe5iPN0719nPrdItC9aU0ssC4v14mH1BCi1u0n1gAocqcujWUrByftZTbLhRtiKRyjYTSIOcr69UVQ==} dependencies: @@ -20979,6 +21018,7 @@ packages: /tiny-invariant@1.3.3: resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} + dev: false /tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} @@ -21799,6 +21839,16 @@ packages: /util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + /util@0.12.5: + resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} + dependencies: + inherits: 2.0.4 + is-arguments: 1.2.0 + is-generator-function: 1.1.0 + is-typed-array: 1.1.15 + which-typed-array: 1.1.19 + dev: true + /utility-types@3.11.0: resolution: {integrity: sha512-6Z7Ma2aVEWisaL6TvBCy7P8rm2LQoPv6dJ7ecIaIixHcwfbJ0x7mWdbcwlIM5IGQxPZSFYeqRCqlOOeKoJYMkw==} engines: {node: '>= 4'} @@ -21809,16 +21859,16 @@ packages: engines: {node: '>= 0.4.0'} dev: true - /uuid@11.1.0: - resolution: {integrity: sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==} - hasBin: true - dev: true - /uuid@8.3.2: resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} hasBin: true dev: false + /uuid@9.0.0: + resolution: {integrity: sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==} + hasBin: true + dev: true + /v8-compile-cache-lib@3.0.1: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} dev: true